mirror of
https://github.com/Z3Prover/z3
synced 2025-08-02 09:20:22 +00:00
Update viable tests
This commit is contained in:
parent
c954e82503
commit
b23c1b4016
2 changed files with 212 additions and 163 deletions
|
@ -1910,122 +1910,6 @@ namespace polysat {
|
||||||
|
|
||||||
}; // class test_polysat
|
}; // class test_polysat
|
||||||
|
|
||||||
|
|
||||||
// Here we deal with linear constraints of the form
|
|
||||||
//
|
|
||||||
// a1*x + b1 <= a2*x + b2 (mod m = 2^bw)
|
|
||||||
//
|
|
||||||
// and their negation.
|
|
||||||
|
|
||||||
class test_fi {
|
|
||||||
|
|
||||||
static bool is_violated(rational const& a1, rational const& b1, rational const& a2, rational const& b2,
|
|
||||||
rational const& val, bool negated, rational const& m) {
|
|
||||||
rational const lhs = (a1*val + b1) % m;
|
|
||||||
rational const rhs = (a2*val + b2) % m;
|
|
||||||
if (negated)
|
|
||||||
return lhs <= rhs;
|
|
||||||
else
|
|
||||||
return lhs > rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true if the input is valid and the test did useful work
|
|
||||||
static bool check_one(rational const& a1, rational const& b1, rational const& a2, rational const& b2, rational const& val, bool negated, unsigned bw) {
|
|
||||||
rational const m = rational::power_of_two(bw);
|
|
||||||
if (a1.is_zero() && a2.is_zero())
|
|
||||||
return false;
|
|
||||||
if (!is_violated(a1, b1, a2, b2, val, negated, m))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
scoped_solver s(__func__);
|
|
||||||
auto x = s.var(s.add_var(bw));
|
|
||||||
signed_constraint c = s.ule(a1*x + b1, a2*x + b2);
|
|
||||||
if (negated)
|
|
||||||
c.negate();
|
|
||||||
viable& v = s.m_viable;
|
|
||||||
v.intersect(x.var(), c);
|
|
||||||
// Trigger forbidden interval refinement
|
|
||||||
v.is_viable(x.var(), val);
|
|
||||||
auto* e = v.m_units[x.var()];
|
|
||||||
if (!e) {
|
|
||||||
std::cout << "test_fi: no interval for a1=" << a1 << " b1=" << b1 << " a2=" << a2 << " b2=" << b2 << " val=" << val << " neg=" << negated << std::endl;
|
|
||||||
// VERIFY(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
VERIFY(e);
|
|
||||||
auto* first = e;
|
|
||||||
SASSERT(e->next() == e); // the result is expected to be a single interval (although for this check it doesn't really matter if there's more...)
|
|
||||||
do {
|
|
||||||
rational const& lo = e->interval.lo_val();
|
|
||||||
rational const& hi = e->interval.hi_val();
|
|
||||||
for (rational x = lo; x != hi; x = (x + 1) % m) {
|
|
||||||
// LOG("lo=" << lo << " hi=" << hi << " x=" << x);
|
|
||||||
if (!is_violated(a1, b1, a2, b2, val, negated, m)) {
|
|
||||||
std::cout << "test_fi: unsound for a1=" << a1 << " b1=" << b1 << " a2=" << a2 << " b2=" << b2 << " val=" << val << " neg=" << negated << std::endl;
|
|
||||||
VERIFY(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: now try to extend lo/hi one by one to find out how "bad" our interval really is.
|
|
||||||
// (probably slow so maybe add a flag to enable/disable that.)
|
|
||||||
e = e->next();
|
|
||||||
}
|
|
||||||
while (e != first);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static void exhaustive(unsigned bw = 0) {
|
|
||||||
if (bw == 0) {
|
|
||||||
exhaustive(1);
|
|
||||||
exhaustive(2);
|
|
||||||
exhaustive(3);
|
|
||||||
exhaustive(4);
|
|
||||||
exhaustive(5);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
std::cout << "test_fi::exhaustive for bw=" << bw << std::endl;
|
|
||||||
rational const m = rational::power_of_two(bw);
|
|
||||||
for (rational p(1); p < m; ++p) {
|
|
||||||
for (rational r(1); r < m; ++r) {
|
|
||||||
// TODO: remove this condition to test the cases other than disequal_lin! (also start p,q from 0)
|
|
||||||
if (p == r)
|
|
||||||
continue;
|
|
||||||
for (rational q(0); q < m; ++q)
|
|
||||||
for (rational s(0); s < m; ++s)
|
|
||||||
for (rational v(0); v < m; ++v)
|
|
||||||
for (bool negated : {true, false})
|
|
||||||
check_one(p, q, r, s, v, negated, bw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void randomized(unsigned num_rounds = 100000, unsigned bw = 16) {
|
|
||||||
std::cout << "test_fi::randomized for bw=" << bw << " (" << num_rounds << " rounds)" << std::endl;
|
|
||||||
rational const m = rational::power_of_two(bw);
|
|
||||||
VERIFY(bw <= 32 && "random_gen generates 32-bit numbers");
|
|
||||||
random_gen rng;
|
|
||||||
unsigned round = num_rounds;
|
|
||||||
while (round) {
|
|
||||||
// rational a1 = (rational(rng()) % (m - 1)) + 1;
|
|
||||||
// rational a2 = (rational(rng()) % (m - 1)) + 1;
|
|
||||||
rational a1 = rational(rng()) % m;
|
|
||||||
rational a2 = rational(rng()) % m;
|
|
||||||
if (a1.is_zero() || a2.is_zero() || a1 == a2)
|
|
||||||
continue;
|
|
||||||
rational b1 = rational(rng()) % m;
|
|
||||||
rational b2 = rational(rng()) % m;
|
|
||||||
rational val = rational(rng()) % m;
|
|
||||||
bool useful =
|
|
||||||
check_one(a1, b1, a2, b2, val, true, bw)
|
|
||||||
|| check_one(a1, b1, a2, b2, val, false, bw);
|
|
||||||
if (useful)
|
|
||||||
round--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // class test_fi
|
|
||||||
|
|
||||||
} // namespace polysat
|
} // namespace polysat
|
||||||
|
|
||||||
|
|
||||||
|
@ -2154,9 +2038,6 @@ void tst_polysat() {
|
||||||
RUN(test_polysat::test_ineq_non_axiom1());
|
RUN(test_polysat::test_ineq_non_axiom1());
|
||||||
RUN(test_polysat::test_ineq_non_axiom4());
|
RUN(test_polysat::test_ineq_non_axiom4());
|
||||||
|
|
||||||
// test_fi::exhaustive();
|
|
||||||
// test_fi::randomized();
|
|
||||||
|
|
||||||
if (collect_test_records)
|
if (collect_test_records)
|
||||||
test_records.display(std::cout);
|
test_records.display(std::cout);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,64 +5,80 @@
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
|
class big_random_gen {
|
||||||
|
unsigned m_bit_width;
|
||||||
|
random_gen m_rng32_int;
|
||||||
|
rational m_two_to_32 = rational::power_of_two(32);
|
||||||
|
rational m_mod_value;
|
||||||
|
|
||||||
|
// create 32-bit random number
|
||||||
|
unsigned rng32_unsigned() {
|
||||||
|
return static_cast<unsigned>(m_rng32_int());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
big_random_gen(unsigned bit_width):
|
||||||
|
m_bit_width(bit_width),
|
||||||
|
m_mod_value(rational::power_of_two(bit_width)) {}
|
||||||
|
|
||||||
|
rational operator()() {
|
||||||
|
rational x(rng32_unsigned());
|
||||||
|
unsigned bw = m_bit_width;
|
||||||
|
while (bw > 32) {
|
||||||
|
x = x * m_two_to_32 + rng32_unsigned();
|
||||||
|
bw -= 32;
|
||||||
|
}
|
||||||
|
return mod(x, m_mod_value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct solver_scopev {
|
struct solver_scopev {
|
||||||
reslimit lim;
|
reslimit lim;
|
||||||
};
|
};
|
||||||
|
|
||||||
class scoped_solverv : public solver_scopev, public solver {
|
class scoped_solverv : public solver_scopev, public solver {
|
||||||
public:
|
public:
|
||||||
viable v;
|
scoped_solverv(): solver(lim) {}
|
||||||
scoped_solverv(): solver(lim), v(*this) {}
|
viable& v() { return m_viable; }
|
||||||
~scoped_solverv() {
|
|
||||||
for (unsigned i = m_trail.size(); i-- > 0;) {
|
|
||||||
switch (m_trail[i]) {
|
|
||||||
case trail_instr_t::viable_add_i:
|
|
||||||
v.pop_viable();
|
|
||||||
break;
|
|
||||||
case trail_instr_t::viable_rem_i:
|
|
||||||
v.push_viable();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void test1() {
|
static void test1() {
|
||||||
scoped_solverv s;
|
scoped_solverv s;
|
||||||
auto xv = s.add_var(3);
|
auto xv = s.add_var(3);
|
||||||
auto x = s.var(xv);
|
auto x = s.var(xv);
|
||||||
s.v.push_var(3);
|
viable& v = s.v();
|
||||||
rational val;
|
rational val;
|
||||||
auto c = s.ule(x + 3, x + 5);
|
s.add_ule(x + 3, x + 5);
|
||||||
s.v.intersect(xv, c);
|
VERIFY_EQ(s.check_sat(), l_true);
|
||||||
std::cout << s.v << "\n";
|
std::cout << v << "\n";
|
||||||
std::cout << "min " << s.v.min_viable(xv, val) << " " << val << "\n";
|
std::cout << "min " << v.min_viable(xv, val) << " " << val << "\n";
|
||||||
std::cout << "max " << s.v.max_viable(xv, val) << " " << val << "\n";
|
std::cout << "max " << v.max_viable(xv, val) << " " << val << "\n";
|
||||||
s.v.intersect(xv, s.ule(x, 2));
|
s.add_ule(x, 2);
|
||||||
std::cout << s.v << "\n";
|
VERIFY_EQ(s.check_sat(), l_true);
|
||||||
s.v.intersect(xv, s.ule(1, x));
|
std::cout << v << "\n";
|
||||||
std::cout << s.v << "\n";
|
s.add_ule(1, x);
|
||||||
std::cout << "min " << s.v.min_viable(xv, val) << " " << val << "\n";
|
VERIFY_EQ(s.check_sat(), l_true);
|
||||||
std::cout << "max " << s.v.max_viable(xv, val) << " " << val << "\n";
|
std::cout << v << "\n";
|
||||||
s.v.intersect(xv, s.ule(x, 3));
|
std::cout << "min " << v.min_viable(xv, val) << " " << val << "\n";
|
||||||
std::cout << s.v << "\n";
|
std::cout << "max " << v.max_viable(xv, val) << " " << val << "\n";
|
||||||
std::cout << s.v.find_viable(xv, val) << " " << val << "\n";
|
s.add_ule(x, 3);
|
||||||
std::cout << "min " << s.v.min_viable(xv, val) << " " << val << "\n";
|
VERIFY_EQ(s.check_sat(), l_true);
|
||||||
std::cout << "max " << s.v.max_viable(xv, val) << " " << val << "\n";
|
std::cout << v << "\n";
|
||||||
s.v.intersect(xv, s.ule(3, x));
|
std::cout << v.find_viable(xv, val) << " " << val << "\n";
|
||||||
std::cout << s.v << "\n";
|
std::cout << "min " << v.min_viable(xv, val) << " " << val << "\n";
|
||||||
std::cout << s.v.find_viable(xv, val) << " " << val << "\n";
|
std::cout << "max " << v.max_viable(xv, val) << " " << val << "\n";
|
||||||
|
s.add_ule(3, x);
|
||||||
|
VERIFY_EQ(s.check_sat(), l_false);
|
||||||
|
std::cout << v << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_interval(scoped_solverv& s, pvar xv, pdd x, unsigned lo, unsigned len) {
|
static void add_interval(scoped_solverv& s, pvar xv, pdd x, unsigned lo, unsigned len) {
|
||||||
if (lo == 0)
|
if (lo == 0)
|
||||||
s.v.intersect(xv, s.ule(x, len - 1));
|
s.v().intersect(xv, s.ule(x, len - 1));
|
||||||
else if (lo + len == 8)
|
else if (lo + len == 8)
|
||||||
s.v.intersect(xv, s.ule(lo, x));
|
s.v().intersect(xv, s.ule(lo, x));
|
||||||
else
|
else
|
||||||
s.v.intersect(xv, ~s.ule(x - ((lo + len)%8), x - lo));
|
s.v().intersect(xv, ~s.ule(x - ((lo + len)%8), x - lo));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool member(unsigned i, unsigned lo, unsigned len) {
|
static bool member(unsigned i, unsigned lo, unsigned len) {
|
||||||
|
@ -80,7 +96,7 @@ namespace polysat {
|
||||||
static void validate_intervals(scoped_solverv& s, pvar xv, vector<std::pair<unsigned, unsigned>> const& intervals) {
|
static void validate_intervals(scoped_solverv& s, pvar xv, vector<std::pair<unsigned, unsigned>> const& intervals) {
|
||||||
for (unsigned i = 0; i < 8; ++i) {
|
for (unsigned i = 0; i < 8; ++i) {
|
||||||
bool mem1 = member(i, intervals);
|
bool mem1 = member(i, intervals);
|
||||||
bool mem2 = s.v.is_viable(xv, rational(i));
|
bool mem2 = s.v().is_viable(xv, rational(i));
|
||||||
if (mem1 != mem2)
|
if (mem1 != mem2)
|
||||||
std::cout << "test violation: " << i << " member of all intervals " << mem1 << " viable: " << mem2 << "\n";
|
std::cout << "test violation: " << i << " member of all intervals " << mem1 << " viable: " << mem2 << "\n";
|
||||||
VERIFY_EQ(mem1, mem2);
|
VERIFY_EQ(mem1, mem2);
|
||||||
|
@ -91,11 +107,10 @@ namespace polysat {
|
||||||
scoped_solverv s;
|
scoped_solverv s;
|
||||||
auto xv = s.add_var(3);
|
auto xv = s.add_var(3);
|
||||||
auto x = s.var(xv);
|
auto x = s.var(xv);
|
||||||
s.v.push_var(3);
|
|
||||||
for (auto const& [lo, len] : intervals)
|
for (auto const& [lo, len] : intervals)
|
||||||
add_interval(s, xv, x, lo, len);
|
add_interval(s, xv, x, lo, len);
|
||||||
std::cout << intervals << "\n";
|
std::cout << intervals << "\n";
|
||||||
//std::cout << s.v << "\n";
|
//std::cout << s.v() << "\n";
|
||||||
validate_intervals(s, xv, intervals);
|
validate_intervals(s, xv, intervals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,13 +305,166 @@ namespace polysat {
|
||||||
VERIFY(solver->check() == l_false);
|
VERIFY(solver->check() == l_false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class test_fi {
|
||||||
|
|
||||||
|
static bool is_violated(rational const& a1, rational const& b1, rational const& a2, rational const& b2, rational const& val, bool negated, rational const& M) {
|
||||||
|
rational const lhs = mod(a1*val + b1, M);
|
||||||
|
rational const rhs = mod(a2*val + b2, M);
|
||||||
|
if (negated)
|
||||||
|
return lhs <= rhs;
|
||||||
|
else
|
||||||
|
return lhs > rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool check_one(unsigned a1, unsigned b1, unsigned a2, unsigned b2, unsigned val, unsigned bw) {
|
||||||
|
return check_one(rational(a1), rational(b1), rational(a2), rational(b2), rational(val), bw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the input is valid and the test did useful work
|
||||||
|
static bool check_one(rational const& a1, rational const& b1, rational const& a2, rational const& b2, rational const& val, unsigned bw) {
|
||||||
|
// std::cout << "a1=" << a1 << " b1=" << b1 << " a2=" << a2 << " b2=" << b2 << " val=" << val << " bw=" << bw << "\n";
|
||||||
|
rational const M = rational::power_of_two(bw);
|
||||||
|
if (a1.is_zero() && a2.is_zero())
|
||||||
|
return false;
|
||||||
|
bool negated = false;
|
||||||
|
if (!is_violated(a1, b1, a2, b2, val, negated, M))
|
||||||
|
negated = !negated;
|
||||||
|
SASSERT(is_violated(a1, b1, a2, b2, val, negated, M));
|
||||||
|
|
||||||
|
scoped_solverv s;
|
||||||
|
auto x = s.var(s.add_var(bw));
|
||||||
|
signed_constraint c = s.ule(a1*x + b1, a2*x + b2);
|
||||||
|
if (negated)
|
||||||
|
c.negate();
|
||||||
|
if (c.is_always_true() || c.is_always_false())
|
||||||
|
return false;
|
||||||
|
bool expect_optimality =
|
||||||
|
// refine-equal-lin should now find the optimal interval in all cases
|
||||||
|
a1.is_zero() || a2.is_zero() || a1 == a2;
|
||||||
|
SASSERT_EQ(c.vars().size(), 1);
|
||||||
|
viable& v = s.v();
|
||||||
|
v.intersect(x.var(), c);
|
||||||
|
// Trigger forbidden interval refinement
|
||||||
|
v.is_viable(x.var(), val);
|
||||||
|
auto* e = v.m_units[x.var()];
|
||||||
|
if (!e) {
|
||||||
|
std::cout << "test_fi: no interval for a1=" << a1 << " b1=" << b1 << " a2=" << a2 << " b2=" << b2 << " val=" << val << " neg=" << negated << std::endl;
|
||||||
|
VERIFY(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
VERIFY(e);
|
||||||
|
auto* first = e;
|
||||||
|
SASSERT(e->next() == e); // the result is expected to be a single interval (although for this check it doesn't really matter if there's more...)
|
||||||
|
|
||||||
|
auto check_is_violated = [&](rational const& x, bool expect_violated) -> bool {
|
||||||
|
if (is_violated(a1, b1, a2, b2, x, negated, M) == expect_violated)
|
||||||
|
return true;
|
||||||
|
std::cout << "ERROR: a1=" << a1 << " b1=" << b1 << " a2=" << a2 << " b2=" << b2 << " val=" << val << " negated=" << negated << " bw=" << bw << "\n";
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
do {
|
||||||
|
rational const& lo = e->interval.is_full() ? rational::zero() : e->interval.lo_val();
|
||||||
|
rational const& hi = e->interval.is_full() ? M : e->interval.hi_val();
|
||||||
|
rational const& len = e->interval.is_full() ? M : e->interval.current_len();
|
||||||
|
unsigned max_offset = 1000;
|
||||||
|
unsigned check_offset = len.is_unsigned() ? std::min(max_offset, len.get_unsigned() / 2) : max_offset;
|
||||||
|
for (unsigned i = 0; i <= check_offset; ++i) {
|
||||||
|
for (rational x : { lo + i, hi - (i + 1), val - i, val + i }) {
|
||||||
|
x = mod(x, M);
|
||||||
|
if (!e->interval.currently_contains(x))
|
||||||
|
continue;
|
||||||
|
VERIFY(check_is_violated(x, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (M > max_offset) {
|
||||||
|
big_random_gen rng(bw);
|
||||||
|
for (unsigned i = 0; i < 1000; ++i) {
|
||||||
|
rational const x = mod(lo + mod(rng(), len), M);
|
||||||
|
VERIFY(e->interval.currently_contains(x));
|
||||||
|
VERIFY(check_is_violated(x, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (expect_optimality && !e->interval.is_full()) {
|
||||||
|
VERIFY(check_is_violated(lo - 1, false));
|
||||||
|
VERIFY(check_is_violated(hi, false));
|
||||||
|
}
|
||||||
|
e = e->next();
|
||||||
|
}
|
||||||
|
while (e != first);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void exhaustive() {
|
||||||
|
exhaustive(1);
|
||||||
|
exhaustive(2);
|
||||||
|
exhaustive(3);
|
||||||
|
exhaustive(4);
|
||||||
|
exhaustive(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exhaustive(unsigned bw) {
|
||||||
|
std::cout << "test_fi::exhaustive for bw=" << bw << std::endl;
|
||||||
|
rational const m = rational::power_of_two(bw);
|
||||||
|
for (rational p; p < m; ++p)
|
||||||
|
for (rational r; r < m; ++r)
|
||||||
|
for (rational q; q < m; ++q)
|
||||||
|
for (rational s; s < m; ++s)
|
||||||
|
for (rational v; v < m; ++v)
|
||||||
|
check_one(p, q, r, s, v, bw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void randomized(unsigned num_rounds, unsigned bw) {
|
||||||
|
std::cout << "test_fi::randomized for bw=" << bw << " (" << num_rounds << " rounds)" << std::endl;
|
||||||
|
big_random_gen rng(bw);
|
||||||
|
unsigned round = num_rounds;
|
||||||
|
while (round) {
|
||||||
|
std::cout << "round " << round << "\n";
|
||||||
|
rational a1 = rng();
|
||||||
|
rational a2 = rng();
|
||||||
|
rational b1 = rng();
|
||||||
|
rational b2 = rng();
|
||||||
|
rational val = rng();
|
||||||
|
bool useful = check_one(a1, b1, a2, b2, val, bw);
|
||||||
|
if (!a1.is_zero() && !a2.is_zero() && a1 != a2) {
|
||||||
|
// make sure to trigger refine-equal-lin as well
|
||||||
|
useful |= check_one(a1, b1, a1, b2, val, bw);
|
||||||
|
useful |= check_one(rational::zero(), b1, a2, b2, val, bw);
|
||||||
|
useful |= check_one(a1, b1, rational::zero(), b2, val, bw);
|
||||||
|
}
|
||||||
|
if (useful)
|
||||||
|
round--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class test_fi
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void tst_viable() {
|
void tst_viable() {
|
||||||
|
set_log_enabled(false);
|
||||||
polysat::test1();
|
polysat::test1();
|
||||||
polysat::test_univariate();
|
polysat::test_univariate();
|
||||||
polysat::test_univariate_minmax();
|
polysat::test_univariate_minmax();
|
||||||
polysat::test2(); // takes long
|
polysat::test2();
|
||||||
|
polysat::test_fi::exhaustive();
|
||||||
|
polysat::test_fi::randomized(10000, 16);
|
||||||
|
polysat::test_fi::randomized(1000, 256);
|
||||||
|
#if 0
|
||||||
|
// TODO: case where refine-equal-lin is still looping:
|
||||||
|
polysat::test_fi::check_one(
|
||||||
|
rational("359753528351133424343509264780402113166597651845926285955318862825137336"),
|
||||||
|
rational("752856510718007431332405387553440539688023502087834331667662410998631117"),
|
||||||
|
rational("359753528351133424343509264780402113166597651845926285955318862825137336"),
|
||||||
|
rational("752856510698397765512447284907808137313109237627169307951559225462781625"),
|
||||||
|
rational("453547182885518174546100861831801761371386469830527870060540275516786265"),
|
||||||
|
256
|
||||||
|
);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue