Skip to content

Commit

Permalink
fix unsoundness in quantifier propagation #6116 and add initial lemma…
Browse files Browse the repository at this point in the history
… logging
  • Loading branch information
NikolajBjorner committed Aug 24, 2022
1 parent 912b284 commit ce1f398
Show file tree
Hide file tree
Showing 15 changed files with 78 additions and 13 deletions.
2 changes: 1 addition & 1 deletion scripts/mk_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def init_project_def():
add_lib('params', ['util'])
add_lib('smt_params', ['params'], 'smt/params')
add_lib('grobner', ['ast', 'dd', 'simplex'], 'math/grobner')
add_lib('sat', ['util', 'dd', 'grobner'])
add_lib('sat', ['params', 'util', 'dd', 'grobner'])
add_lib('nlsat', ['polynomial', 'sat'])
add_lib('lp', ['util', 'nlsat', 'grobner', 'interval', 'smt_params'], 'math/lp')
add_lib('rewriter', ['ast', 'polynomial', 'automata', 'params'], 'ast/rewriter')
Expand Down
9 changes: 6 additions & 3 deletions src/sat/sat_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Revision History:
#include "sat/sat_types.h"
#include "sat/sat_params.hpp"
#include "sat/sat_simplifier_params.hpp"
#include "params/solver_params.hpp"


namespace sat {
Expand All @@ -31,6 +32,8 @@ namespace sat {

void config::updt_params(params_ref const & _p) {
sat_params p(_p);
solver_params sp(_p);

m_max_memory = megabytes_to_bytes(p.max_memory());

symbol s = p.restart();
Expand Down Expand Up @@ -194,7 +197,7 @@ namespace sat {
m_drat_check_unsat = p.drat_check_unsat();
m_drat_check_sat = p.drat_check_sat();
m_drat_file = p.drat_file();
m_drat = (m_drat_check_unsat || m_drat_file.is_non_empty_string() || m_drat_check_sat) && p.threads() == 1;
m_drat = !p.drat_disable() && (sp.lemmas2console() || m_drat_check_unsat || m_drat_file.is_non_empty_string() || m_drat_check_sat) && p.threads() == 1;
m_drat_binary = p.drat_binary();
m_drat_activity = p.drat_activity();
m_drup_trim = p.drup_trim();
Expand Down Expand Up @@ -248,8 +251,8 @@ namespace sat {
m_card_solver = p.cardinality_solver();
m_xor_solver = false; // prevent users from playing with this option

sat_simplifier_params sp(_p);
m_elim_vars = sp.elim_vars();
sat_simplifier_params ssp(_p);
m_elim_vars = ssp.elim_vars();

#if 0
if (m_drat && (m_xor_solver || m_card_solver))
Expand Down
8 changes: 8 additions & 0 deletions src/sat/sat_drat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ namespace sat {
if (m_out) dump(1, &l, st);
if (m_bout) bdump(1, &l, st);
if (m_check) append(l, st);
if (m_print_clause) m_print_clause(1, &l, st);
}
void drat::add(literal l1, literal l2, status st) {
if (st.is_deleted())
Expand All @@ -700,6 +701,7 @@ namespace sat {
if (m_out) dump(2, ls, st);
if (m_bout) bdump(2, ls, st);
if (m_check) append(l1, l2, st);
if (m_print_clause) m_print_clause(2, ls, st);
}
void drat::add(clause& c, status st) {
if (st.is_deleted())
Expand All @@ -709,6 +711,7 @@ namespace sat {
if (m_out) dump(c.size(), c.begin(), st);
if (m_bout) bdump(c.size(), c.begin(), st);
if (m_check) append(mk_clause(c), st);
if (m_print_clause) m_print_clause(c.size(), c.begin(), st);
}

void drat::add(literal_vector const& lits, status st) {
Expand All @@ -729,6 +732,9 @@ namespace sat {
}
if (m_out)
dump(sz, lits, st);

if (m_print_clause)
m_print_clause(sz, lits, st);
}

void drat::add(literal_vector const& c) {
Expand All @@ -748,6 +754,8 @@ namespace sat {
}
}
}
if (m_print_clause)
m_print_clause(c.size(), c.data(), status::redundant());
}

void drat::del(literal l) {
Expand Down
6 changes: 6 additions & 0 deletions src/sat/sat_drat.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ namespace sat {
bool m_trim = false;
stats m_stats;

std::function<void(unsigned, literal const*, status)> m_print_clause;

void dump_activity();
void dump(unsigned n, literal const* c, status st);
void bdump(unsigned n, literal const* c, status st);
Expand Down Expand Up @@ -138,6 +140,10 @@ namespace sat {
void add(literal_vector const& c); // add learned clause
void add(unsigned sz, literal const* lits, status st);

void set_print_clause(std::function<void(unsigned, literal const*, status)>& print_clause) {
m_print_clause = print_clause;
}

// support for SMT - connect Boolean variables with AST nodes
// associate AST node id with Boolean variable v
void bool_def(bool_var v, unsigned n);
Expand Down
1 change: 1 addition & 0 deletions src/sat/sat_params.pyg
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def_module_params('sat',
('backtrack.conflicts', UINT, 4000, 'number of conflicts before enabling chronological backtracking'),
('threads', UINT, 1, 'number of parallel threads to use'),
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'),
('drat.disable', BOOL, False, 'override anything that enables DRAT'),
('drat.file', SYMBOL, '', 'file to dump DRAT proofs'),
('drat.binary', BOOL, False, 'use Binary DRAT output format'),
('drat.check_unsat', BOOL, False, 'build up internal proof and check'),
Expand Down
7 changes: 5 additions & 2 deletions src/sat/sat_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ namespace sat {
clause * solver::mk_clause_core(unsigned num_lits, literal * lits, sat::status st) {
bool redundant = st.is_redundant();
TRACE("sat", tout << "mk_clause: " << mk_lits_pp(num_lits, lits) << (redundant?" learned":" aux") << "\n";);
bool logged = false;
if (!redundant || !st.is_sat()) {
unsigned old_sz = num_lits;
bool keep = simplify_clause(num_lits, lits);
Expand All @@ -420,8 +421,10 @@ namespace sat {
return nullptr; // clause is equivalent to true.
}
// if an input clause is simplified, then log the simplified version as learned
if (m_config.m_drat && old_sz > num_lits)
if (m_config.m_drat && old_sz > num_lits) {
drat_log_clause(num_lits, lits, st);
logged = true;
}

++m_stats.m_non_learned_generation;
if (!m_searching) {
Expand All @@ -435,7 +438,7 @@ namespace sat {
set_conflict();
return nullptr;
case 1:
if (m_config.m_drat && (!st.is_sat() || st.is_input()))
if (!logged && m_config.m_drat && (!st.is_sat() || st.is_input()))
drat_log_clause(num_lits, lits, st);
assign_unit(lits[0]);
return nullptr;
Expand Down
2 changes: 1 addition & 1 deletion src/sat/sat_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ namespace sat {
};

struct no_drat_params : public params_ref {
no_drat_params() { set_sym("drat.file", symbol()); }
no_drat_params() { set_bool("drat.disable", true); }
};

class solver : public solver_core {
Expand Down
21 changes: 21 additions & 0 deletions src/sat/smt/euf_proof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Module Name:
--*/

#include "sat/smt/euf_solver.h"
#include "ast/ast_util.h"
#include <iostream>

namespace euf {

Expand Down Expand Up @@ -192,4 +194,23 @@ namespace euf {
get_drat().bool_def(lit.var(), eq->get_id());
}

void solver::log_clause(unsigned n, literal const* lits, sat::status st) {
if (get_config().m_lemmas2console) {
std::function<symbol(int)> ppth = [&](int th) {
return m.get_family_name(th);
};
if (st.is_redundant() || st.is_asserted()) {
expr_ref_vector clause(m);
for (unsigned i = 0; i < n; ++i) {
expr_ref e = literal2expr(lits[i]);
if (!e)
return;
clause.push_back(e);
}
expr_ref cl = mk_or(clause);
std::cout << sat::status_pp(st, ppth) << " " << cl << "\n";
}
}
}

}
8 changes: 8 additions & 0 deletions src/sat/smt/euf_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ namespace euf {
TRACE("before_search", s().display(tout););
for (auto* s : m_solvers)
s->init_search();

if (get_config().m_lemmas2console) {
std::function<void(unsigned, sat::literal const*, sat::status)> on_clause =
[&](unsigned n, sat::literal const* lits, sat::status st) {
log_clause(n, lits, st);
};
get_drat().set_print_clause(on_clause);
}
}

bool solver::is_external(bool_var v) {
Expand Down
1 change: 1 addition & 0 deletions src/sat/smt/euf_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ namespace euf {
obj_hashtable<ast> m_drat_asts;
bool m_drat_initialized{ false };
void init_drat();
void log_clause(unsigned n, literal const* lits, sat::status st);

// relevancy
//bool_vector m_relevant_expr_ids;
Expand Down
10 changes: 8 additions & 2 deletions src/sat/smt/q_ematch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,14 @@ namespace q {
else {
++m_stats.m_num_propagations;
auto& j = justification::from_index(j_idx);
auto lit = instantiate(j.m_clause, j.m_binding, j.m_clause[idx]);
ctx.propagate(lit, j_idx);
sat::literal_vector lits;
lits.push_back(~j.m_clause.m_literal);
for (unsigned i = 0; i < j.m_clause.size(); ++i)
lits.push_back(instantiate(j.m_clause, j.m_binding, j.m_clause[i]));
m_qs.log_instantiation(lits);
m_qs.add_clause(lits);
}

}

bool ematch::flush_prop_queue() {
Expand All @@ -408,6 +413,7 @@ namespace q {
void ematch::add_instantiation(clause& c, binding& b, sat::literal lit) {
m_evidence.reset();
ctx.propagate(lit, mk_justification(UINT_MAX, c, b.nodes()));
m_qs.log_instantiation(~c.m_literal, lit);
}

sat::literal ematch::instantiate(clause& c, euf::enode* const* binding, lit const& l) {
Expand Down
8 changes: 4 additions & 4 deletions src/sat/smt/q_eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,21 @@ namespace q {
unsigned lim = m_indirect_nodes.size();
lit l = c[i];
lbool cmp = compare(n, binding, l.lhs, l.rhs, evidence);
TRACE("q", tout << l.lhs << " ~~ " << l.rhs << " is " << cmp << "\n";);
switch (cmp) {
case l_false:
case l_false:
m_indirect_nodes.shrink(lim);
if (!l.sign)
break;
c.m_watch = i;
return l_true;
case l_true:
case l_true:
m_indirect_nodes.shrink(lim);
if (l.sign)
break;
break;
c.m_watch = i;
return l_true;
case l_undef:
TRACE("q", tout << l.lhs << " ~~ " << l.rhs << " is undef\n";);
if (idx != UINT_MAX) {
idx = UINT_MAX;
return l_undef;
Expand Down
1 change: 1 addition & 0 deletions src/sat/smt/q_mbi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ namespace q {
for (auto const& [qlit, fml, generation] : m_instantiations) {
euf::solver::scoped_generation sg(ctx, generation + 1);
sat::literal lit = ctx.mk_literal(fml);
m_qs.log_instantiation(~qlit, ~lit);
m_qs.add_clause(~qlit, ~lit);
}
m_instantiations.reset();
Expand Down
3 changes: 3 additions & 0 deletions src/sat/smt/q_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,7 @@ namespace q {
m_ematch.get_antecedents(l, idx, r, probing);
}

void solver::log_instantiation(unsigned n, sat::literal const* lits) {
TRACE("q", for (unsigned i = 0; i < n; ++i) tout << literal2expr(lits[i]) << "\n";);
}
}
4 changes: 4 additions & 0 deletions src/sat/smt/q_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,9 @@ namespace q {
sat::literal_vector const& universal() const { return m_universal; }
quantifier* flatten(quantifier* q);

void log_instantiation(sat::literal q, sat::literal i) { sat::literal lits[2] = { q, i }; log_instantiation(2, lits); }
void log_instantiation(sat::literal_vector const& lits) { log_instantiation(lits.size(), lits.data()); }
void log_instantiation(unsigned n, sat::literal const* lits);

};
}

0 comments on commit ce1f398

Please sign in to comment.