3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 01:25:31 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-09-13 13:54:51 +02:00
parent 5d9ed5b0a9
commit 67c4777514
11 changed files with 251 additions and 126 deletions

View file

@ -1162,18 +1162,21 @@ namespace nlsat {
new_lit = m_solver.mk_ineq_literal(new_k, new_factors.size(), new_factors.c_ptr(), new_factors_even.c_ptr());
if (l.sign())
new_lit.neg();
TRACE("nlsat_simplify_core", tout << "simplified literal:\n"; display(tout, new_lit); tout << "\n";);
TRACE("nlsat_simplify_core", tout << "simplified literal:\n"; display(tout, new_lit); tout << " " << m_solver.value(new_lit) << "\n";);
if (max_var(new_lit) < max) {
// The conflicting core may have redundant literals.
// We should check whether new_lit is true in the current model, and discard it if that is the case
VERIFY(m_solver.value(new_lit) != l_undef);
if (m_solver.value(new_lit) == l_false)
if (m_solver.value(new_lit) == l_true) {
new_lit = l;
}
else {
add_literal(new_lit);
new_lit = true_literal;
return;
new_lit = true_literal;
}
}
else {
new_lit = normalize(new_lit, max);
TRACE("nlsat_simplify_core", tout << "simplified literal after normalization:\n"; display(tout, new_lit); tout << " " << m_solver.value(new_lit) << "\n";);
}
new_lit = normalize(new_lit, max);
TRACE("nlsat_simplify_core", tout << "simplified literal after normalization:\n"; display(tout, new_lit); tout << "\n";);
}
else {
new_lit = l;
@ -1333,6 +1336,7 @@ namespace nlsat {
poly * eq_p = eq->p(0);
VERIFY(simplify(C, eq_p, max));
// add equation as an assumption
TRACE("nlsat_simpilfy_core", display(tout << "adding equality as assumption ", literal(eq->bvar(), true)); tout << "\n";);
add_literal(literal(eq->bvar(), true));
}
}
@ -1511,7 +1515,7 @@ namespace nlsat {
result.set(i, ~result[i]);
}
DEBUG_CODE(
TRACE("nlsat", m_solver.display(tout, result.size(), result.c_ptr()); );
TRACE("nlsat", m_solver.display(tout, result.size(), result.c_ptr()) << "\n"; );
for (literal l : result) {
CTRACE("nlsat", l_true != m_solver.value(l), m_solver.display(tout, l) << " " << m_solver.value(l) << "\n";);
SASSERT(l_true == m_solver.value(l));
@ -1619,12 +1623,12 @@ namespace nlsat {
unsigned glb_index = 0, lub_index = 0;
scoped_anum lub(m_am), glb(m_am), x_val(m_am);
x_val = m_assignment.value(x);
bool glb_valid = false, lub_valid = false;
for (unsigned i = 0; i < ps.size(); ++i) {
p = ps.get(i);
scoped_anum_vector & roots = m_roots_tmp;
roots.reset();
m_am.isolate_roots(p, undef_var_assignment(m_assignment, x), roots);
bool glb_valid = false, lub_valid = false;
for (auto const& r : roots) {
int s = m_am.compare(x_val, r);
SASSERT(s != 0);
@ -1632,23 +1636,19 @@ namespace nlsat {
if (s < 0 && (!lub_valid || m_am.lt(r, lub))) {
lub_index = i;
m_am.set(lub, r);
lub_valid = true;
}
if (s > 0 && (!glb_valid || m_am.lt(glb, r))) {
glb_index = i;
m_am.set(glb, r);
m_am.set(glb, r);
glb_valid = true;
}
lub_valid |= s < 0;
glb_valid |= s > 0;
}
if (glb_valid) {
++num_glb;
}
if (lub_valid) {
++num_lub;
if (s < 0) ++num_lub;
if (s > 0) ++num_glb;
}
}
TRACE("nlsat_explain", tout << ps << "\n";);
TRACE("nlsat_explain", tout << "glb: " << num_glb << " lub: " << num_lub << "\n" << lub_index << "\n" << glb_index << "\n" << ps << "\n";);
if (num_lub == 0) {
project_plus_infinity(x, ps);

View file

@ -5,6 +5,7 @@ def_module_params('nlsat',
params=(max_memory_param(),
('lazy', UINT, 0, "how lazy the solver is."),
('reorder', BOOL, True, "reorder variables."),
('log_lemmas', BOOL, False, "display lemmas as self-contained SMT formulas"),
('simplify_conflicts', BOOL, True, "simplify conflicts using equalities before resolving them in nlsat solver."),
('minimize_conflicts', BOOL, False, "minimize conflicts"),
('randomize', BOOL, True, "randomize selection of a witness in nlsat."),

View file

@ -156,6 +156,8 @@ namespace nlsat {
unsigned m_scope_lvl;
struct bvar_assignment {};
struct stage {};
struct trail {
enum kind { BVAR_ASSIGNMENT, INFEASIBLE_UPDT, NEW_LEVEL, NEW_STAGE, UPDT_EQ };
kind m_kind;
@ -164,9 +166,9 @@ namespace nlsat {
interval_set * m_old_set;
atom * m_old_eq;
};
trail(bool_var b):m_kind(BVAR_ASSIGNMENT), m_b(b) {}
trail(bool_var b, bvar_assignment):m_kind(BVAR_ASSIGNMENT), m_b(b) {}
trail(interval_set * old_set):m_kind(INFEASIBLE_UPDT), m_old_set(old_set) {}
trail(bool stage):m_kind(stage ? NEW_STAGE : NEW_LEVEL) {}
trail(bool s, stage):m_kind(s ? NEW_STAGE : NEW_LEVEL) {}
trail(atom * a):m_kind(UPDT_EQ), m_old_eq(a) {}
};
svector<trail> m_trail;
@ -182,6 +184,7 @@ namespace nlsat {
bool m_random_order;
unsigned m_random_seed;
bool m_inline_vars;
bool m_log_lemmas;
unsigned m_max_conflicts;
// statistics
@ -240,6 +243,7 @@ namespace nlsat {
m_random_order = p.shuffle_vars();
m_random_seed = p.seed();
m_inline_vars = p.inline_vars();
m_log_lemmas = p.log_lemmas();
m_ism.set_seed(m_random_seed);
m_explain.set_simplify_cores(m_simplify_cores);
m_explain.set_minimize_cores(min_cores);
@ -730,6 +734,14 @@ namespace nlsat {
}
};
void log_lemma(std::ostream& out, clause const& cls) {
display_smt2(out);
out << "(assert (not ";
display_smt2(out, cls) << "))\n";
display(out << "(echo \"", cls) << "\")\n";
out << "(check-sat)\n(reset)\n";
}
clause * mk_clause(unsigned num_lits, literal const * lits, bool learned, _assumption_set a) {
SASSERT(num_lits > 0);
unsigned cid = m_cid_gen.mk();
@ -741,6 +753,9 @@ namespace nlsat {
TRACE("nlsat_sort", tout << "mk_clause:\n"; display(tout, *cls); tout << "\n";);
std::sort(cls->begin(), cls->end(), lit_lt(*this));
TRACE("nlsat_sort", tout << "after sort:\n"; display(tout, *cls); tout << "\n";);
if (learned && m_log_lemmas) {
log_lemma(std::cout, *cls);
}
if (learned)
m_learned.push_back(cls);
else
@ -764,7 +779,7 @@ namespace nlsat {
// -----------------------
void save_assign_trail(bool_var b) {
m_trail.push_back(trail(b));
m_trail.push_back(trail(b, bvar_assignment()));
}
void save_set_updt_trail(interval_set * old_set) {
@ -776,11 +791,11 @@ namespace nlsat {
}
void save_new_stage_trail() {
m_trail.push_back(trail(true));
m_trail.push_back(trail(true, stage()));
}
void save_new_level_trail() {
m_trail.push_back(trail(false));
m_trail.push_back(trail(false, stage()));
}
void undo_bvar_assignment(bool_var b) {
@ -934,8 +949,10 @@ namespace nlsat {
\brief Assign literal using the given justification
*/
void assign(literal l, justification j) {
TRACE("nlsat", tout << "assigning literal: "; display(tout, l);
tout << "\njustification kind: " << j.get_kind() << "\n";);
TRACE("nlsat",
display(tout << "assigning literal: ", l);
display(tout << " <- ", j););
SASSERT(assigned_value(l) == l_undef);
SASSERT(j != null_justification);
SASSERT(!j.is_null());
@ -1086,9 +1103,10 @@ namespace nlsat {
switch (j.get_kind()) {
case justification::CLAUSE:
if (j.get_clause()->assumptions() != nullptr) return;
break;
break;
case justification::LAZY:
if (j.get_lazy()->num_clauses() > 0) return;
if (j.get_lazy()->num_lits() > 0) return;
break;
default:
break;
@ -1098,8 +1116,10 @@ namespace nlsat {
SASSERT(x != null_var);
if (m_var2eq[x] != 0 && degree(m_var2eq[x]) <= degree(a))
return; // we only update m_var2eq if the new equality has smaller degree
TRACE("simplify_core", tout << "Saving equality for "; m_display_var(tout, x) << " (x" << x << ") ";
tout << "scope-lvl: " << scope_lvl() << "\n"; display(tout, literal(b, false)) << "\n";);
TRACE("nlsat_simplify_core", tout << "Saving equality for "; m_display_var(tout, x) << " (x" << x << ") ";
tout << "scope-lvl: " << scope_lvl() << "\n"; display(tout, literal(b, false)) << "\n";
display(tout, j);
);
save_updt_eq_trail(m_var2eq[x]);
m_var2eq[x] = a;
}
@ -1125,7 +1145,7 @@ namespace nlsat {
checkpoint();
if (value(l) == l_false)
continue;
TRACE("nlsat_inf_set", tout << "xk: " << m_xk << ", max_var(l): " << max_var(l) << ", l: "; display(tout, l); tout << "\n";);
CTRACE("nlsat", max_var(l) != m_xk, display(tout); tout << "xk: " << m_xk << ", max_var(l): " << max_var(l) << ", l: "; display(tout, l); tout << "\n";);
SASSERT(value(l) == l_undef);
SASSERT(max_var(l) == m_xk);
bool_var b = l.var();
@ -1195,7 +1215,6 @@ namespace nlsat {
bool process_clause(clause const & cls, bool satisfy_learned) {
if (is_satisfied(cls))
return true;
TRACE("nlsat", display(tout << "processing clause: ", cls) << "\n";);
if (m_xk == null_var)
return process_boolean_clause(cls);
else
@ -1255,7 +1274,22 @@ namespace nlsat {
m_irrational_assignments++;
m_assignment.set_core(m_xk, w);
}
bool is_satisfied() {
if (m_bk == null_bool_var && m_xk >= num_vars()) {
TRACE("nlsat", tout << "found model\n"; display_assignment(tout););
fix_patch();
SASSERT(check_satisfied(m_clauses));
return true; // all variables were assigned, and all clauses were satisfied.
}
else {
return false;
}
}
/**
\brief main procedure
*/
@ -1264,8 +1298,11 @@ namespace nlsat {
TRACE("nlsat_proof", tout << "ASSERTED\n"; display(tout););
TRACE("nlsat_proof_sk", tout << "ASSERTED\n"; display_abst(tout););
TRACE("nlsat_mathematica", display_mathematica(tout););
TRACE("nlsat", display_smt2(tout););
m_bk = 0;
m_xk = null_var;
m_conflicts = 0;
while (true) {
CASSERT("nlsat", check_satisfied());
if (m_xk == null_var) {
@ -1277,22 +1314,18 @@ namespace nlsat {
new_stage(); // peek next arith var
}
TRACE("nlsat_bug", tout << "xk: x" << m_xk << " bk: b" << m_bk << "\n";);
if (m_bk == null_bool_var && m_xk >= num_vars()) {
TRACE("nlsat", tout << "found model\n"; display_assignment(tout););
fix_patch();
SASSERT(check_satisfied(m_clauses));
return l_true; // all variables were assigned, and all clauses were satisfied.
if (is_satisfied()) {
return l_true;
}
while (true) {
TRACE("nlsat", tout << "processing variable ";
TRACE("nlsat_verbose", tout << "processing variable ";
if (m_xk != null_var) {
m_display_var(tout, m_xk); tout << " " << m_watches[m_xk].size();
}
else {
tout << m_bwatches[m_bk].size() << " boolean b" << m_bk;
}
tout << "\n";
);
tout << "\n";);
checkpoint();
clause * conflict_clause;
if (m_xk == null_var)
@ -1301,12 +1334,12 @@ namespace nlsat {
conflict_clause = process_clauses(m_watches[m_xk]);
if (conflict_clause == nullptr)
break;
if (!resolve(*conflict_clause))
return l_false;
if (!resolve(*conflict_clause))
return l_false;
if (m_conflicts >= m_max_conflicts)
return l_undef;
}
if (m_xk == null_var) {
if (m_bvalues[m_bk] == l_undef) {
decide(literal(m_bk, true));
@ -1319,6 +1352,7 @@ namespace nlsat {
}
}
lbool search_check() {
lbool r = l_undef;
while (true) {
@ -1521,6 +1555,7 @@ namespace nlsat {
// antecedent must be false in the current arith interpretation
SASSERT(value(antecedent) == l_false);
if (!is_marked(b)) {
TRACE("nlsat_resolve", tout << max_var(b) << " " << m_xk << "\n";);
SASSERT(is_arith_atom(b) && max_var(b) < m_xk); // must be in a previous stage
TRACE("nlsat_resolve", tout << "literal is unassigned, but it is false in arithmetic interpretation, adding it to lemma\n";);
mark(b);
@ -2692,6 +2727,26 @@ namespace nlsat {
display_num_assignment(out);
return out;
}
std::ostream& display(std::ostream& out, justification j) const {
switch (j.get_kind()) {
case justification::CLAUSE:
display(out, *j.get_clause()) << "\n";
break;
case justification::LAZY: {
lazy_justification const& lz = *j.get_lazy();
display(out, lz.num_lits(), lz.lits()) << "\n";
for (unsigned i = 0; i < lz.num_clauses(); ++i) {
display(out, lz.clause(i)) << "\n";
}
break;
}
default:
out << j.get_kind() << "\n";
break;
}
return out;
}
std::ostream& display(std::ostream & out, ineq_atom const & a, display_var_proc const & proc, bool use_star = false) const {
unsigned sz = a.size();
@ -2769,6 +2824,10 @@ namespace nlsat {
out << " 0)";
return out;
}
std::ostream& display_smt2(std::ostream & out, root_atom const & a, display_var_proc const & proc) const {
return display(out, a, proc);
}
std::ostream& display(std::ostream & out, root_atom const & a, display_var_proc const & proc) const {
proc(out, a.x());
@ -2898,6 +2957,10 @@ namespace nlsat {
return display(out, l, m_display_var);
}
std::ostream& display_smt2(std::ostream & out, literal l) const {
return display_smt2(out, l, m_display_var);
}
std::ostream& display_mathematica(std::ostream & out, literal l) const {
if (l.sign()) {
bool_var b = l.var();
@ -2947,7 +3010,7 @@ namespace nlsat {
return out;
}
std::ostream& display(std::ostream & out, unsigned num, literal const * ls) {
std::ostream& display(std::ostream & out, unsigned num, literal const * ls) const {
return display(out, num, ls, m_display_var);
}
@ -3147,7 +3210,7 @@ namespace nlsat {
for (clause* c : m_clauses) {
display_smt2(out, *c) << "\n";
}
out << "))\n(check-sat)" << std::endl;
out << "))\n" << std::endl;
return out;
}
};
@ -3346,6 +3409,22 @@ namespace nlsat {
return display(out, ls.size(), ls.c_ptr());
}
std::ostream& solver::display_smt2(std::ostream & out, literal l) const {
return m_imp->display_smt2(out, l);
}
std::ostream& solver::display_smt2(std::ostream & out, unsigned n, literal const* ls) const {
for (unsigned i = 0; i < n; ++i) {
display_smt2(out, ls[i]);
out << " ";
}
return out;
}
std::ostream& solver::display_smt2(std::ostream & out, literal_vector const& ls) const {
return display_smt2(out, ls.size(), ls.c_ptr());
}
std::ostream& solver::display(std::ostream & out, var x) const {
return m_imp->m_display_var(out, x);
}

View file

@ -245,6 +245,13 @@ namespace nlsat {
std::ostream& display(std::ostream & out, atom const& a) const;
std::ostream& display_smt2(std::ostream & out, literal l) const;
std::ostream& display_smt2(std::ostream & out, unsigned n, literal const* ls) const;
std::ostream& display_smt2(std::ostream & out, literal_vector const& ls) const;
/**
\brief Display variable
*/