3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 18:31:49 +00:00
z3/test/nlsat.cpp
Leonardo de Moura 68269c43a6 other components
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:48:48 -07:00

307 lines
9.7 KiB
C++

/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
nlsat.cpp
Abstract:
nlsat procedure
Author:
Leonardo (leonardo) 2012-01-09
Notes:
--*/
#include"nlsat_assignment.h"
#include"nlsat_interval_set.h"
#include"nlsat_evaluator.h"
#include"nlsat_solver.h"
#include"util.h"
nlsat::interval_set_ref tst_interval(nlsat::interval_set_ref const & s1,
nlsat::interval_set_ref const & s2,
unsigned expected_num_intervals,
bool check_num_intervals = true) {
nlsat::interval_set_manager & ism = s1.m();
nlsat::interval_set_ref r(ism);
std::cout << "------------------\n";
std::cout << "s1: " << s1 << "\n";
std::cout << "s2: " << s2 << "\n";
r = ism.mk_union(s1, s2);
std::cout << "union(s1, s2): " << r << std::endl;
SASSERT(!check_num_intervals || ism.num_intervals(r) == expected_num_intervals);
SASSERT(ism.subset(s1, r));
SASSERT(ism.subset(s2, r));
if (ism.set_eq(s1, s2)) {
SASSERT(ism.set_eq(s1, r));
SASSERT(ism.set_eq(s2, r));
}
else {
SASSERT(ism.subset(s1, s2) || !ism.subset(r, s2));
SASSERT(ism.subset(s2, s1) || !ism.subset(r, s1));
}
nlsat::interval_set_ref r2(ism);
r2 = ism.mk_union(s2, s1);
SASSERT(ism.set_eq(r, r2));
anum zero;
nlsat::interval_set_ref full(ism);
nlsat::literal dummy(131, false);
full = ism.mk(true, true, zero, true, true, zero, dummy);
SASSERT(ism.set_eq(r, full) == ism.is_full(r));
return r;
}
static void tst3() {
enable_trace("nlsat_interval");
unsynch_mpq_manager qm;
anum_manager am(qm);
small_object_allocator allocator;
nlsat::interval_set_manager ism(am, allocator);
scoped_anum sqrt2(am), m_sqrt2(am), two(am), m_two(am), three(am), one(am), zero(am);
am.set(two, 2);
am.set(m_two, -2);
am.set(one, 1);
am.root(two, 2, sqrt2);
am.set(m_sqrt2, sqrt2);
am.neg(m_sqrt2);
am.set(three, 3);
nlsat::literal p1(1, false);
nlsat::literal p2(2, false);
nlsat::literal p3(3, false);
nlsat::literal p4(4, false);
nlsat::literal np2(2, true);
nlsat::interval_set_ref s1(ism), s2(ism), s3(ism), s4(ism);
s1 = ism.mk_empty();
std::cout << "s1: " << s1 << "\n";
s2 = ism.mk(true, true, zero, false, false, sqrt2, np2);
std::cout << "s2: " << s2 << "\n";
s3 = ism.mk(false, false, zero, false, false, two, p1);
std::cout << "s3: " << s3 << "\n";
s4 = ism.mk_union(s2, s3);
std::cout << "s4: " << s4 << "\n";
// Case
// s1: [ ... ]
// s2: [ ... ]
s1 = ism.mk(false, false, zero, false, false, two, p1);
s2 = ism.mk(false, false, zero, false, false, two, p2);
tst_interval(s1, s2, 1);
// Case
// s1: [ ... ]
// s2: [ ... ]
s1 = ism.mk(false, false, zero, false, false, two, p1);
s2 = ism.mk(false, false, m_sqrt2, false, false, one, p2);
s3 = ism.mk_union(s1, s2);
tst_interval(s1, s2, 2);
// Case
// s1: [ ... ]
// s2: [ ... ]
s1 = ism.mk(false, false, m_sqrt2, false, false, one, p1);
s2 = ism.mk(false, false, zero, false, false, two, p2);
tst_interval(s1, s2, 2);
// Case
// s1: [ ... ]
// s2: [ ... ]
s1 = ism.mk(false, false, m_sqrt2, false, false, one, p1);
s2 = ism.mk(false, false, two, false, false, three, p2);
tst_interval(s1, s2, 2);
// Case
// s1: [ ... ]
// s2: [ ... ]
s1 = ism.mk(false, false, m_sqrt2, false, false, three, p1);
s2 = ism.mk(false, false, zero, false, false, two, p2);
tst_interval(s1, s2, 1);
// Case
// s1: [ ... ]
// s2: [ ... ] [ ... ]
s1 = ism.mk(false, false, m_two, false, false, two, p1);
s2 = ism.mk(false, false, m_sqrt2, false, false, zero, p2);
s3 = ism.mk(false, false, one, false, false, three, p2);
s2 = ism.mk_union(s2, s3);
tst_interval(s1, s2, 2);
// Case
// s1: [ ... ]
// s2: [ ... ]
s1 = ism.mk(false, false, m_two, false, false, two, p1);
s2 = ism.mk(false, false, two, false, false, three, p2);
tst_interval(s1, s2, 2);
s2 = ism.mk(true, false, two, false, false, three, p2);
tst_interval(s1, s2, 2);
s2 = ism.mk(true, false, two, false, false, three, p1);
tst_interval(s1, s2, 1);
s1 = ism.mk(false, false, m_two, true, false, two, p1);
tst_interval(s1, s2, 2);
s1 = ism.mk(false, false, two, false, false, two, p1);
s2 = ism.mk(false, false, two, false, false, three, p2);
tst_interval(s1, s2, 1);
// Case
// s1: [ ... ] [ ... ]
// s2: [ .. ] [ ... ] [ ... ]
s1 = ism.mk(false, false, m_two, false, false, zero, p1);
s3 = ism.mk(false, false, one, false, false, three, p1);
s1 = ism.mk_union(s1, s3);
s2 = ism.mk(true, true, zero, false, false, m_sqrt2, p2);
tst_interval(s1, s2, 3);
s3 = ism.mk(false, false, one, false, false, sqrt2, p2);
s2 = ism.mk_union(s2, s3);
s3 = ism.mk(false, false, two, true, true, zero, p2);
s2 = ism.mk_union(s2, s3);
tst_interval(s1, s2, 4);
// Case
s1 = ism.mk(true, true, zero, false, false, one, p1);
s2 = ism.mk(true, false, one, true, true, zero, p2);
tst_interval(s1, s2, 2);
s2 = ism.mk(true, false, one, false, false, two, p2);
s3 = ism.mk(false, false, two, true, true, zero, p1);
s2 = ism.mk_union(s2, s3);
tst_interval(s1, s2, 3);
}
static nlsat::interval_set_ref mk_random(nlsat::interval_set_manager & ism, anum_manager & am, int range, int space, int tries, bool minus_inf, bool plus_inf,
nlsat::literal lit) {
static random_gen gen;
SASSERT(range > 0);
SASSERT(space > 0);
nlsat::interval_set_ref r(ism), curr(ism);
scoped_anum lower(am);
scoped_anum upper(am);
int prev = -range + (gen() % (space*4));
if (gen() % 3 == 0 && minus_inf) {
int next = prev + (gen() % space);
bool open = gen() % 2 == 0;
am.set(upper, next);
r = ism.mk(true, true, lower, open, false, upper, lit);
prev = next;
}
for (int i = 0; i < tries; i++) {
int l = prev + (gen() % space);
int u = l + (gen() % space);
bool lower_open = gen() % 2 == 0;
bool upper_open = gen() % 2 == 0;
if ((lower_open || upper_open) && l == u)
u++;
am.set(lower, l);
am.set(upper, u);
curr = ism.mk(lower_open, false, lower, upper_open, false, upper, lit);
r = ism.mk_union(r, curr);
prev = u;
}
if (gen() % 3 == 0 && plus_inf) {
int next = prev + (gen() % space);
bool open = gen() % 2 == 0;
am.set(lower, next);
curr = ism.mk(open, false, lower, true, true, upper, lit);
r = ism.mk_union(r, curr);
}
return r;
}
static void check_subset_result(nlsat::interval_set_ref const & s1,
nlsat::interval_set_ref const & s2,
nlsat::interval_set_ref const & r,
nlsat::literal l1,
nlsat::literal l2) {
nlsat::interval_set_manager ism(s1.m());
nlsat::interval_set_ref tmp(ism);
unsigned num = ism.num_intervals(r);
nlsat::literal_vector lits;
ism.get_justifications(r, lits);
SASSERT(lits.size() <= 2);
for (unsigned i = 0; i < num; i++) {
tmp = ism.get_interval(r, i);
ism.get_justifications(tmp, lits);
SASSERT(lits.size() == 1);
if (lits[0] == l1) {
SASSERT(ism.subset(tmp, s1));
}
else {
SASSERT(lits[0] == l2);
SASSERT(ism.subset(tmp, s2));
}
}
}
static void tst4() {
enable_trace("nlsat_interval");
unsynch_mpq_manager qm;
anum_manager am(qm);
small_object_allocator allocator;
nlsat::interval_set_manager ism(am, allocator);
nlsat::interval_set_ref s1(ism), s2(ism), r(ism);
nlsat::literal l1(1, false);
nlsat::literal l2(2, false);
for (unsigned i = 0; i < 100; i++) {
s1 = mk_random(ism, am, 20, 3, 10, true, true, l1);
s2 = mk_random(ism, am, 20, 3, 10, true, true, l2);
r = tst_interval(s1, s2, 0, false);
check_subset_result(s1, s2, r, l1, l2);
}
for (unsigned i = 0; i < 100; i++) {
s1 = mk_random(ism, am, 200, 100, 20, true, true, l1);
s2 = mk_random(ism, am, 200, 100, 20, true, true, l2);
r = tst_interval(s1, s2, 0, false);
check_subset_result(s1, s2, r, l1, l2);
}
}
static void tst5() {
params_ref ps;
nlsat::solver s(ps);
unsynch_mpq_manager & qm = s.qm();
anum_manager & am = s.am();
nlsat::pmanager & pm = s.pm();
nlsat::assignment as(am);
small_object_allocator allocator;
nlsat::interval_set_manager ism(am, allocator);
nlsat::evaluator ev(as, pm, allocator);
nlsat::var x0, x1;
x0 = pm.mk_var();
x1 = pm.mk_var();
polynomial_ref p(pm);
polynomial_ref _x0(pm), _x1(pm);
_x0 = pm.mk_polynomial(x0);
_x1 = pm.mk_polynomial(x1);
p = (_x0^2) + (_x1^2) - 2;
nlsat::poly * _p[1] = { p.get() };
bool is_even[1] = { false };
nlsat::bool_var b = s.mk_ineq_atom(nlsat::atom::GT, 1, _p, is_even);
nlsat::atom * a = s.bool_var2atom(b);
SASSERT(a != 0);
nlsat::interval_set_ref i(ism);
scoped_anum zero(am);
am.set(zero, 0);
as.set(0, zero);
i = ev.infeasible_intervals(a, true);
std::cout << "1) " << i << "\n";
as.set(1, zero);
i = ev.infeasible_intervals(a, true);
std::cout << "2) " << i << "\n";
}
void tst_nlsat() {
tst5();
tst4();
tst3();
}