3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-21 05:13:39 +00:00

update lookahead to include extensions

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-06-07 16:35:35 -07:00
parent 83635eb826
commit f3b0ede6e8
13 changed files with 1855 additions and 1944 deletions

View file

@ -14,6 +14,7 @@ z3_add_component(sat
sat_iff3_finder.cpp sat_iff3_finder.cpp
sat_integrity_checker.cpp sat_integrity_checker.cpp
sat_local_search.cpp sat_local_search.cpp
sat_lookahead.cpp
sat_model_converter.cpp sat_model_converter.cpp
sat_mus.cpp sat_mus.cpp
sat_parallel.cpp sat_parallel.cpp

View file

@ -542,14 +542,15 @@ extern "C" {
} }
int Z3_read_interpolation_problem(Z3_context ctx, unsigned *_num, Z3_ast *cnsts[], unsigned *parents[], const char *filename, Z3_string_ptr error, unsigned *ret_num_theory, Z3_ast *theory[]){ int Z3_read_interpolation_problem(Z3_context ctx, Z3_ast_vector cnsts, unsigned* _num, unsigned* parents[], const char *filename, Z3_string_ptr error, Z3_ast_vector theory){
hash_map<std::string, std::string> file_params; hash_map<std::string, std::string> file_params;
get_file_params(filename, file_params); get_file_params(filename, file_params);
unsigned num_theory = 0; unsigned num_theory = 0;
if (file_params.find("THEORY") != file_params.end()) if (file_params.find("THEORY") != file_params.end()) {
num_theory = atoi(file_params["THEORY"].c_str()); num_theory = atoi(file_params["THEORY"].c_str());
}
Z3_ast_vector assertions = iZ3_parse(ctx, filename, error); Z3_ast_vector assertions = iZ3_parse(ctx, filename, error);
if (assertions == 0) if (assertions == 0)
@ -559,23 +560,15 @@ extern "C" {
num_theory = Z3_ast_vector_size(ctx, assertions); num_theory = Z3_ast_vector_size(ctx, assertions);
unsigned num = Z3_ast_vector_size(ctx, assertions) - num_theory; unsigned num = Z3_ast_vector_size(ctx, assertions) - num_theory;
read_cnsts.resize(num);
read_parents.resize(num); read_parents.resize(num);
read_theory.resize(num_theory);
for (unsigned j = 0; j < num_theory; j++) for (unsigned j = 0; theory && j < num_theory; j++)
read_theory[j] = Z3_ast_vector_get(ctx, assertions, j); Z3_ast_vector_push(ctx, theory, Z3_ast_vector_get(ctx, assertions, j));
for (unsigned j = 0; j < num; j++) for (unsigned j = 0; j < num; j++)
read_cnsts[j] = Z3_ast_vector_get(ctx, assertions, j + num_theory); Z3_ast_vector_push(ctx, cnsts, Z3_ast_vector_get(ctx, assertions, j + num_theory));
if (ret_num_theory)
*ret_num_theory = num_theory;
if (theory)
*theory = &read_theory[0];
if (!parents){ if (!parents){
*_num = num;
*cnsts = &read_cnsts[0];
Z3_ast_vector_dec_ref(ctx, assertions); Z3_ast_vector_dec_ref(ctx, assertions);
return true; return true;
} }
@ -586,7 +579,7 @@ extern "C" {
hash_map<Z3_ast, int> pred_map; hash_map<Z3_ast, int> pred_map;
for (unsigned j = 0; j < num; j++){ for (unsigned j = 0; j < num; j++){
Z3_ast lhs = 0, rhs = read_cnsts[j]; Z3_ast lhs = 0, rhs = Z3_ast_vector_get(ctx, cnsts, j);
if (Z3_get_decl_kind(ctx, Z3_get_app_decl(ctx, Z3_to_app(ctx, rhs))) == Z3_OP_IMPLIES){ if (Z3_get_decl_kind(ctx, Z3_get_app_decl(ctx, Z3_to_app(ctx, rhs))) == Z3_OP_IMPLIES){
Z3_app app1 = Z3_to_app(ctx, rhs); Z3_app app1 = Z3_to_app(ctx, rhs);
@ -627,7 +620,7 @@ extern "C" {
read_error << "formula " << j + 1 << ": should be (implies {children} fmla parent)"; read_error << "formula " << j + 1 << ": should be (implies {children} fmla parent)";
goto fail; goto fail;
} }
read_cnsts[j] = lhs; Z3_ast_vector_set(ctx, cnsts, j, lhs);
Z3_ast name = rhs; Z3_ast name = rhs;
if (pred_map.find(name) != pred_map.end()){ if (pred_map.find(name) != pred_map.end()){
read_error << "formula " << j + 1 << ": duplicate symbol"; read_error << "formula " << j + 1 << ": duplicate symbol";
@ -646,7 +639,6 @@ extern "C" {
} }
*_num = num; *_num = num;
*cnsts = &read_cnsts[0];
*parents = &read_parents[0]; *parents = &read_parents[0];
Z3_ast_vector_dec_ref(ctx, assertions); Z3_ast_vector_dec_ref(ctx, assertions);
return true; return true;

View file

@ -133,19 +133,16 @@ namespace Microsoft.Z3
/// well documented.</remarks> /// well documented.</remarks>
public int ReadInterpolationProblem(string filename, out Expr[] cnsts, out uint[] parents, out string error, out Expr[] theory) public int ReadInterpolationProblem(string filename, out Expr[] cnsts, out uint[] parents, out string error, out Expr[] theory)
{ {
uint num = 0, num_theory = 0; uint num = 0;
IntPtr[] n_cnsts;
IntPtr[] n_theory;
IntPtr n_err_str; IntPtr n_err_str;
int r = Native.Z3_read_interpolation_problem(nCtx, ref num, out n_cnsts, out parents, filename, out n_err_str, ref num_theory, out n_theory); ASTVector _cnsts = new ASTVector(this);
ASTVector _theory = new ASTVector(this);
int r = Native.Z3_read_interpolation_problem(nCtx, _cnsts.NativeObject, ref num, out parents, filename, out n_err_str, _theory.NativeObject);
error = Marshal.PtrToStringAnsi(n_err_str); error = Marshal.PtrToStringAnsi(n_err_str);
cnsts = new Expr[num]; cnsts = _cnsts.ToExprArray();
parents = new uint[num]; parents = new uint[num];
theory = new Expr[num_theory]; theory = _theory.ToExprArray();
for (int i = 0; i < num; i++)
cnsts[i] = Expr.Create(this, n_cnsts[i]);
for (int i = 0; i < num_theory; i++)
theory[i] = Expr.Create(this, n_theory[i]);
return r; return r;
} }

View file

@ -207,18 +207,17 @@ extern "C" {
where each value is represented using the common symbols between where each value is represented using the common symbols between
the formulas in the subtree and the remainder of the formulas. the formulas in the subtree and the remainder of the formulas.
def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _out(UINT), _out_managed_array(1, AST), _out_managed_array(1, UINT), _in(STRING), _out(STRING), _out(UINT), _out_managed_array(6, AST))) def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _in(AST_VECTOR), _out(UINT), _out_managed_array(2, UINT), _in(STRING), _out(STRING), _in(AST_VECTOR)))
*/ */
int Z3_API Z3_read_interpolation_problem(Z3_context ctx, int Z3_API Z3_read_interpolation_problem(Z3_context ctx,
unsigned *num, Z3_ast_vector cnsts,
Z3_ast *cnsts[], unsigned* num,
unsigned *parents[], unsigned* parents[],
Z3_string filename, Z3_string filename,
Z3_string_ptr error, Z3_string_ptr error,
unsigned *num_theory, Z3_ast_vector theory);
Z3_ast *theory[]);

View file

@ -266,7 +266,7 @@ UNARY_CMD(pp_cmd, "display", "<term>", "display the given term.", CPK_EXPR, expr
ctx.regular_stream() << std::endl; ctx.regular_stream() << std::endl;
}); });
UNARY_CMD(echo_cmd, "echo", "<string>", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << arg << std::endl;); UNARY_CMD(echo_cmd, "echo", "<string>", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << "\"" << arg << "\"" << std::endl;);
class set_get_option_cmd : public cmd { class set_get_option_cmd : public cmd {

View file

@ -79,12 +79,6 @@ namespace sat {
} }
} }
void card_extension::init_watch(bool_var v) {
if (m_var_infos.size() <= static_cast<unsigned>(v)) {
m_var_infos.resize(static_cast<unsigned>(v)+100);
}
}
void card_extension::init_watch(card& c, bool is_true) { void card_extension::init_watch(card& c, bool is_true) {
clear_watch(c); clear_watch(c);
if (c.lit() != null_literal && c.lit().sign() == is_true) { if (c.lit() != null_literal && c.lit().sign() == is_true) {
@ -94,7 +88,7 @@ namespace sat {
SASSERT(c.lit() == null_literal || value(c.lit()) == l_true); SASSERT(c.lit() == null_literal || value(c.lit()) == l_true);
unsigned j = 0, sz = c.size(), bound = c.k(); unsigned j = 0, sz = c.size(), bound = c.k();
if (bound == sz) { if (bound == sz) {
for (unsigned i = 0; i < sz && !s().inconsistent(); ++i) { for (unsigned i = 0; i < sz && !inconsistent(); ++i) {
assign(c, c[i]); assign(c, c[i]);
} }
return; return;
@ -135,7 +129,7 @@ namespace sat {
set_conflict(c, alit); set_conflict(c, alit);
} }
else if (j == bound) { else if (j == bound) {
for (unsigned i = 0; i < bound && !s().inconsistent(); ++i) { for (unsigned i = 0; i < bound && !inconsistent(); ++i) {
assign(c, c[i]); assign(c, c[i]);
} }
} }
@ -149,20 +143,12 @@ namespace sat {
void card_extension::clear_watch(card& c) { void card_extension::clear_watch(card& c) {
unsigned sz = std::min(c.k() + 1, c.size()); unsigned sz = std::min(c.k() + 1, c.size());
for (unsigned i = 0; i < sz; ++i) { for (unsigned i = 0; i < sz; ++i) {
unwatch_literal(c[i], &c); unwatch_literal(c[i], c);
} }
} }
void card_extension::unwatch_literal(literal lit, card* c) { void card_extension::unwatch_literal(literal lit, card& c) {
if (m_var_infos.size() <= static_cast<unsigned>(lit.var())) { get_wlist(~lit).erase(watched(c.index()));
return;
}
ptr_vector<card>*& cards = m_var_infos[lit.var()].m_card_watch[lit.sign()];
if (!is_tag_empty(cards)) {
if (remove(*cards, c)) {
cards = set_tag_empty(cards);
}
}
} }
void card_extension::assign(card& c, literal lit) { void card_extension::assign(card& c, literal lit) {
@ -177,7 +163,7 @@ namespace sat {
m_num_propagations_since_pop++; m_num_propagations_since_pop++;
//TRACE("sat", tout << "#prop: " << m_stats.m_num_propagations << " - " << c.lit() << " => " << lit << "\n";); //TRACE("sat", tout << "#prop: " << m_stats.m_num_propagations << " - " << c.lit() << " => " << lit << "\n";);
SASSERT(validate_unit_propagation(c)); SASSERT(validate_unit_propagation(c));
if (s().m_config.m_drat) { if (get_config().m_drat) {
svector<drat::premise> ps; svector<drat::premise> ps;
literal_vector lits; literal_vector lits;
if (c.lit() != null_literal) lits.push_back(~c.lit()); if (c.lit() != null_literal) lits.push_back(~c.lit());
@ -186,27 +172,16 @@ namespace sat {
} }
lits.push_back(lit); lits.push_back(lit);
ps.push_back(drat::premise(drat::s_ext(), c.lit())); // null_literal case. ps.push_back(drat::premise(drat::s_ext(), c.lit())); // null_literal case.
s().m_drat.add(lits, ps); drat_add(lits, ps);
} }
s().assign(lit, justification::mk_ext_justification(c.index())); assign(lit, justification::mk_ext_justification(c.index()));
break; break;
} }
} }
void card_extension::watch_literal(card& c, literal lit) { void card_extension::watch_literal(card& c, literal lit) {
TRACE("sat_verbose", tout << "watch: " << lit << "\n";); TRACE("sat_verbose", tout << "watch: " << lit << "\n";);
init_watch(lit.var()); get_wlist(~lit).push_back(watched(c.index()));
ptr_vector<card>* cards = m_var_infos[lit.var()].m_card_watch[lit.sign()];
if (cards == 0) {
cards = alloc(ptr_vector<card>);
m_var_infos[lit.var()].m_card_watch[lit.sign()] = cards;
}
else if (is_tag_empty(cards)) {
cards = set_tag_non_empty(cards);
m_var_infos[lit.var()].m_card_watch[lit.sign()] = cards;
}
TRACE("sat_verbose", tout << "insert: " << lit.var() << " " << lit.sign() << "\n";);
cards->push_back(&c);
} }
void card_extension::set_conflict(card& c, literal lit) { void card_extension::set_conflict(card& c, literal lit) {
@ -214,8 +189,8 @@ namespace sat {
TRACE("sat", display(tout, c, true); ); TRACE("sat", display(tout, c, true); );
SASSERT(validate_conflict(c)); SASSERT(validate_conflict(c));
SASSERT(value(lit) == l_false); SASSERT(value(lit) == l_false);
s().set_conflict(justification::mk_ext_justification(c.index()), ~lit); set_conflict(justification::mk_ext_justification(c.index()), ~lit);
SASSERT(s().inconsistent()); SASSERT(inconsistent());
} }
// pb: // pb:
@ -322,7 +297,7 @@ namespace sat {
lbool card_extension::add_assign(pb& p, literal alit) { lbool card_extension::add_assign(pb& p, literal alit) {
TRACE("sat", display(tout << "assign: " << alit << "\n", p, true);); TRACE("sat", display(tout << "assign: " << alit << "\n", p, true););
SASSERT(!s().inconsistent()); SASSERT(!inconsistent());
unsigned sz = p.size(); unsigned sz = p.size();
unsigned bound = p.k(); unsigned bound = p.k();
unsigned num_watch = p.num_watch(); unsigned num_watch = p.num_watch();
@ -364,7 +339,7 @@ namespace sat {
} }
} }
SASSERT(!s().inconsistent()); SASSERT(!inconsistent());
DEBUG_CODE(for (auto idx : m_pb_undef) { SASSERT(value(p[idx].second) == l_undef); }); DEBUG_CODE(for (auto idx : m_pb_undef) { SASSERT(value(p[idx].second) == l_undef); });
if (slack < bound) { if (slack < bound) {
@ -400,7 +375,7 @@ namespace sat {
} }
for (literal lit : to_assign) { for (literal lit : to_assign) {
if (s().inconsistent()) break; if (inconsistent()) break;
if (value(lit) == l_undef) { if (value(lit) == l_undef) {
assign(p, lit); assign(p, lit);
} }
@ -415,37 +390,18 @@ namespace sat {
void card_extension::watch_literal(pb& p, wliteral l) { void card_extension::watch_literal(pb& p, wliteral l) {
literal lit = l.second; literal lit = l.second;
init_watch(lit.var()); get_wlist(~lit).push_back(watched(p.index()));
ptr_vector<pb>* pbs = m_var_infos[lit.var()].m_pb_watch[lit.sign()];
if (pbs == 0) {
pbs = alloc(ptr_vector<pb>);
m_var_infos[lit.var()].m_pb_watch[lit.sign()] = pbs;
}
else if (is_tag_empty(pbs)) {
pbs = set_tag_non_empty(pbs);
m_var_infos[lit.var()].m_pb_watch[lit.sign()] = pbs;
}
TRACE("sat_verbose", tout << "insert: " << lit.var() << " " << lit.sign() << "\n";);
pbs->push_back(&p);
} }
void card_extension::clear_watch(pb& p) { void card_extension::clear_watch(pb& p) {
unsigned sz = p.size(); unsigned sz = p.size();
for (unsigned i = 0; i < sz; ++i) { for (unsigned i = 0; i < sz; ++i) {
unwatch_literal(p[i].second, &p); unwatch_literal(p[i].second, p);
} }
} }
void card_extension::unwatch_literal(literal lit, pb* p) { void card_extension::unwatch_literal(literal lit, pb& p) {
if (m_var_infos.size() <= static_cast<unsigned>(lit.var())) { get_wlist(~lit).erase(watched(p.index()));
return;
}
pb_watch*& pbs = m_var_infos[lit.var()].m_pb_watch[lit.sign()];
if (!is_tag_empty(pbs)) {
if (remove(*pbs, p)) {
pbs = set_tag_empty(pbs);
}
}
} }
void card_extension::set_conflict(pb& p, literal lit) { void card_extension::set_conflict(pb& p, literal lit) {
@ -453,8 +409,8 @@ namespace sat {
TRACE("sat", display(tout, p, true); ); TRACE("sat", display(tout, p, true); );
// SASSERT(validate_conflict(p)); // SASSERT(validate_conflict(p));
SASSERT(value(lit) == l_false); SASSERT(value(lit) == l_false);
s().set_conflict(justification::mk_ext_justification(p.index()), ~lit); set_conflict(justification::mk_ext_justification(p.index()), ~lit);
SASSERT(s().inconsistent()); SASSERT(inconsistent());
} }
void card_extension::assign(pb& p, literal lit) { void card_extension::assign(pb& p, literal lit) {
@ -468,15 +424,15 @@ namespace sat {
SASSERT(validate_unit_propagation(p, lit)); SASSERT(validate_unit_propagation(p, lit));
m_stats.m_num_pb_propagations++; m_stats.m_num_pb_propagations++;
m_num_propagations_since_pop++; m_num_propagations_since_pop++;
if (s().m_config.m_drat) { if (get_config().m_drat) {
svector<drat::premise> ps; svector<drat::premise> ps;
literal_vector lits; literal_vector lits;
get_pb_antecedents(lit, p, lits); get_pb_antecedents(lit, p, lits);
lits.push_back(lit); lits.push_back(lit);
ps.push_back(drat::premise(drat::s_ext(), p.lit())); ps.push_back(drat::premise(drat::s_ext(), p.lit()));
s().m_drat.add(lits, ps); drat_add(lits, ps);
} }
s().assign(lit, justification::mk_ext_justification(p.index())); assign(lit, justification::mk_ext_justification(p.index()));
break; break;
} }
} }
@ -513,53 +469,6 @@ namespace sat {
out << ">= " << p.k() << "\n"; out << ">= " << p.k() << "\n";
} }
void card_extension::asserted_pb(literal l, ptr_vector<pb>* pbs, pb* p0) {
TRACE("sat", tout << "literal: " << l << " has pb: " << !is_tag_empty(pbs) << " p0 != 0: " << (p0 != 0) << "\n";);
if (!is_tag_empty(pbs)) {
ptr_vector<pb>::iterator begin = pbs->begin();
ptr_vector<pb>::iterator it = begin, it2 = it, end = pbs->end();
for (; it != end; ++it) {
pb& p = *(*it);
if (p.lit() != null_literal && value(p.lit()) != l_true) {
continue;
}
switch (add_assign(p, ~l)) {
case l_true: // unit propagation, keep watching the literal
if (it2 != it) {
*it2 = *it;
}
++it2;
break;
case l_false: // conflict.
SASSERT(s().inconsistent());
for (; it != end; ++it, ++it2) {
*it2 = *it;
}
pbs->set_end(it2);
return;
case l_undef: // watch literal was swapped
if (s().inconsistent()) {
++it;
for (; it != end; ++it, ++it2) {
*it2 = *it;
}
pbs->set_end(it2);
return;
}
break;
}
}
pbs->set_end(it2);
if (pbs->empty()) {
m_var_infos[l.var()].m_pb_watch[!l.sign()] = set_tag_empty(pbs);
}
}
if (p0 != 0 && !s().inconsistent()) {
init_watch(*p0, !l.sign());
}
}
// xor: // xor:
void card_extension::copy_xor(card_extension& result) { void card_extension::copy_xor(card_extension& result) {
@ -575,20 +484,12 @@ namespace sat {
} }
void card_extension::clear_watch(xor& x) { void card_extension::clear_watch(xor& x) {
unwatch_literal(x[0], &x); unwatch_literal(x[0], x);
unwatch_literal(x[1], &x); unwatch_literal(x[1], x);
} }
void card_extension::unwatch_literal(literal lit, xor* c) { void card_extension::unwatch_literal(literal lit, xor& c) {
if (m_var_infos.size() <= static_cast<unsigned>(lit.var())) { get_wlist(~lit).erase(watched(c.index()));
return;
}
xor_watch*& xors = m_var_infos[lit.var()].m_xor_watch;
if (!is_tag_empty(xors)) {
if (remove(*xors, c)) {
xors = set_tag_empty(xors);
}
}
} }
bool card_extension::parity(xor const& x, unsigned offset) const { bool card_extension::parity(xor const& x, unsigned offset) const {
@ -620,16 +521,15 @@ namespace sat {
switch (j) { switch (j) {
case 0: case 0:
if (!parity(x, 0)) { if (!parity(x, 0)) {
literal_set litset; unsigned l = lvl(x[0]);
for (unsigned i = 0; i < sz; ++i) { j = 1;
litset.insert(x[i]); for (unsigned i = 1; i < sz; ++i) {
if (lvl(x[i]) > l) {
j = i;
l = lvl(x[i]);
} }
literal_vector const& lits = s().m_trail;
unsigned idx = lits.size()-1;
while (!litset.contains(lits[idx])) {
--idx;
} }
set_conflict(x, lits[idx]); set_conflict(x, x[j]);
} }
break; break;
case 1: case 1:
@ -644,18 +544,18 @@ namespace sat {
} }
void card_extension::assign(xor& x, literal lit) { void card_extension::assign(xor& x, literal lit) {
SASSERT(!s().inconsistent()); SASSERT(!inconsistent());
switch (value(lit)) { switch (value(lit)) {
case l_true: case l_true:
break; break;
case l_false: case l_false:
set_conflict(x, lit); set_conflict(x, lit);
SASSERT(s().inconsistent()); SASSERT(inconsistent());
break; break;
default: default:
m_stats.m_num_xor_propagations++; m_stats.m_num_xor_propagations++;
m_num_propagations_since_pop++; m_num_propagations_since_pop++;
if (s().m_config.m_drat) { if (get_config().m_drat) {
svector<drat::premise> ps; svector<drat::premise> ps;
literal_vector lits; literal_vector lits;
if (x.lit() != null_literal) lits.push_back(~x.lit()); if (x.lit() != null_literal) lits.push_back(~x.lit());
@ -664,25 +564,17 @@ namespace sat {
} }
lits.push_back(lit); lits.push_back(lit);
ps.push_back(drat::premise(drat::s_ext(), x.lit())); ps.push_back(drat::premise(drat::s_ext(), x.lit()));
s().m_drat.add(lits, ps); drat_add(lits, ps);
} }
TRACE("sat", display(tout << lit << " ", x, true);); TRACE("sat", display(tout << lit << " ", x, true););
s().assign(lit, justification::mk_ext_justification(x.index())); assign(lit, justification::mk_ext_justification(x.index()));
break; break;
} }
} }
void card_extension::watch_literal(xor& x, literal lit) { void card_extension::watch_literal(xor& x, literal lit) {
TRACE("sat_verbose", tout << "watch: " << lit << "\n";); TRACE("sat_verbose", tout << "watch: " << lit << "\n";);
init_watch(lit.var()); get_wlist(~lit).push_back(watched(x.index()));
xor_watch*& xors = m_var_infos[lit.var()].m_xor_watch;
if (xors == 0) {
xors = alloc(ptr_vector<xor>);
}
else if (is_tag_empty(xors)) {
xors = set_tag_non_empty(xors);
}
xors->push_back(&x);
TRACE("sat_verbose", tout << "insert: " << lit.var() << " " << lit.sign() << "\n";); TRACE("sat_verbose", tout << "insert: " << lit.var() << " " << lit.sign() << "\n";);
} }
@ -693,8 +585,8 @@ namespace sat {
if (value(lit) == l_true) lit.neg(); if (value(lit) == l_true) lit.neg();
SASSERT(validate_conflict(x)); SASSERT(validate_conflict(x));
TRACE("sat", display(tout << lit << " ", x, true);); TRACE("sat", display(tout << lit << " ", x, true););
s().set_conflict(justification::mk_ext_justification(x.index()), ~lit); set_conflict(justification::mk_ext_justification(x.index()), ~lit);
SASSERT(s().inconsistent()); SASSERT(inconsistent());
} }
lbool card_extension::add_assign(xor& x, literal alit) { lbool card_extension::add_assign(xor& x, literal alit) {
@ -735,49 +627,9 @@ namespace sat {
else if (!parity(x, 0)) { else if (!parity(x, 0)) {
set_conflict(x, ~x[1]); set_conflict(x, ~x[1]);
} }
return s().inconsistent() ? l_false : l_true; return inconsistent() ? l_false : l_true;
} }
void card_extension::asserted_xor(literal l, ptr_vector<xor>* xors, xor* x) {
TRACE("sat", tout << l << " " << !is_tag_empty(xors) << " " << (x != 0) << "\n";);
if (!is_tag_empty(xors)) {
ptr_vector<xor>::iterator begin = xors->begin();
ptr_vector<xor>::iterator it = begin, it2 = it, end = xors->end();
for (; it != end; ++it) {
xor& c = *(*it);
if (c.lit() != null_literal && value(c.lit()) != l_true) {
continue;
}
switch (add_assign(c, ~l)) {
case l_false: // conflict
for (; it != end; ++it, ++it2) {
*it2 = *it;
}
SASSERT(s().inconsistent());
xors->set_end(it2);
return;
case l_undef: // watch literal was swapped
break;
case l_true: // unit propagation, keep watching the literal
if (it2 != it) {
*it2 = *it;
}
++it2;
break;
}
}
xors->set_end(it2);
if (xors->empty()) {
m_var_infos[l.var()].m_xor_watch = set_tag_empty(xors);
}
}
if (x != 0 && !s().inconsistent()) {
init_watch(*x, !l.sign());
}
}
void card_extension::normalize_active_coeffs() { void card_extension::normalize_active_coeffs() {
while (!m_active_var_set.empty()) m_active_var_set.erase(); while (!m_active_var_set.empty()) m_active_var_set.erase();
unsigned i = 0, j = 0, sz = m_active_vars.size(); unsigned i = 0, j = 0, sz = m_active_vars.size();
@ -841,7 +693,6 @@ namespace sat {
m_active_vars.reset(); m_active_vars.reset();
} }
bool card_extension::resolve_conflict() { bool card_extension::resolve_conflict() {
if (0 == m_num_propagations_since_pop) { if (0 == m_num_propagations_since_pop) {
return false; return false;
@ -1084,9 +935,9 @@ namespace sat {
TRACE("sat", tout << m_lemma << "\n";); TRACE("sat", tout << m_lemma << "\n";);
if (s().m_config.m_drat) { if (get_config().m_drat) {
svector<drat::premise> ps; // TBD fill in svector<drat::premise> ps; // TBD fill in
s().m_drat.add(m_lemma, ps); drat_add(m_lemma, ps);
} }
s().m_lemma.reset(); s().m_lemma.reset();
@ -1155,16 +1006,11 @@ namespace sat {
return p; return p;
} }
card_extension::card_extension(): m_solver(0), m_has_xor(false) { card_extension::card_extension(): m_solver(0), m_lookahead(0) {
TRACE("sat", tout << this << "\n";); TRACE("sat", tout << this << "\n";);
} }
card_extension::~card_extension() { card_extension::~card_extension() {
for (unsigned i = 0; i < m_var_infos.size(); ++i) {
m_var_infos[i].reset();
}
m_var_trail.reset();
m_var_lim.reset();
m_stats.reset(); m_stats.reset();
} }
@ -1180,9 +1026,9 @@ namespace sat {
m_card_axioms.push_back(c); m_card_axioms.push_back(c);
} }
else { else {
init_watch(v); get_wlist(literal(v, false)).push_back(index);
m_var_infos[v].m_card = c; get_wlist(literal(v, true)).push_back(index);
m_var_trail.push_back(v); m_index_trail.push_back(index);
} }
} }
@ -1197,28 +1043,58 @@ namespace sat {
m_pb_axioms.push_back(p); m_pb_axioms.push_back(p);
} }
else { else {
init_watch(v); get_wlist(literal(v, false)).push_back(index);
m_var_infos[v].m_pb = p; get_wlist(literal(v, true)).push_back(index);
m_var_trail.push_back(v); m_index_trail.push_back(index);
} }
} }
void card_extension::add_xor(bool_var v, literal_vector const& lits) { void card_extension::add_xor(bool_var v, literal_vector const& lits) {
m_has_xor = true;
unsigned index = 4*m_xors.size() + 0x1; unsigned index = 4*m_xors.size() + 0x1;
SASSERT(is_xor_index(index)); SASSERT(is_xor_index(index));
SASSERT(v != null_bool_var);
xor* x = new (memory::allocate(xor::get_obj_size(lits.size()))) xor(index, literal(v, false), lits); xor* x = new (memory::allocate(xor::get_obj_size(lits.size()))) xor(index, literal(v, false), lits);
m_xors.push_back(x); m_xors.push_back(x);
init_watch(v); get_wlist(literal(v, false)).push_back(index);
m_var_infos[v].m_xor = x; get_wlist(literal(v, true)).push_back(index);
m_var_trail.push_back(v); m_index_trail.push_back(index);
} }
void card_extension::propagate(literal l, ext_constraint_idx idx, bool & keep) { void card_extension::propagate(literal l, ext_constraint_idx idx, bool & keep) {
TRACE("sat", tout << l << " " << idx << "\n";);
if (is_pb_index(idx)) {
pb& p = index2pb(idx);
if (l.var() == p.lit().var()) {
init_watch(p, !l.sign());
}
else {
keep = l_undef != add_assign(p, ~l);
}
}
else if (is_card_index(idx)) {
card& c = index2card(idx);
if (l.var() == c.lit().var()) {
init_watch(c, !l.sign());
}
else {
keep = l_undef != add_assign(c, ~l);
}
}
else if (is_xor_index(idx)) {
xor& x = index2xor(idx);
if (l.var() == x.lit().var()) {
init_watch(x, !l.sign());
}
else {
keep = l_undef != add_assign(x, ~l);
}
}
else {
UNREACHABLE(); UNREACHABLE();
} }
}
void card_extension::ensure_parity_size(bool_var v) { void card_extension::ensure_parity_size(bool_var v) {
@ -1454,100 +1330,53 @@ namespace sat {
} }
SASSERT(validate_unit_propagation(c)); SASSERT(validate_unit_propagation(c));
for (unsigned i = 0; i < bound && !s().inconsistent(); ++i) { for (unsigned i = 0; i < bound && !inconsistent(); ++i) {
assign(c, c[i]); assign(c, c[i]);
} }
return s().inconsistent() ? l_false : l_true; return inconsistent() ? l_false : l_true;
} }
void card_extension::asserted(literal l) { void card_extension::asserted(literal l) {
bool_var v = l.var();
if (s().inconsistent()) return;
if (v >= m_var_infos.size()) return;
var_info& vinfo = m_var_infos[v];
ptr_vector<card>* cards = vinfo.m_card_watch[!l.sign()];
ptr_vector<xor>* xors = vinfo.m_xor_watch;
ptr_vector<pb>* pbs = vinfo.m_pb_watch[!l.sign()];
pb* p = vinfo.m_pb;
card* crd = vinfo.m_card;
xor* x = vinfo.m_xor;
if (!is_tag_empty(cards)) {
ptr_vector<card>::iterator begin = cards->begin();
ptr_vector<card>::iterator it = begin, it2 = it, end = cards->end();
for (; it != end; ++it) {
card& c = *(*it);
if (c.lit() != null_literal && value(c.lit()) != l_true) {
continue;
}
switch (add_assign(c, ~l)) {
case l_false: // conflict
for (; it != end; ++it, ++it2) {
*it2 = *it;
}
SASSERT(s().inconsistent());
cards->set_end(it2);
return;
case l_undef: // watch literal was swapped
break;
case l_true: // unit propagation, keep watching the literal
if (it2 != it) {
*it2 = *it;
}
++it2;
break;
}
}
cards->set_end(it2);
if (cards->empty()) {
m_var_infos[v].m_card_watch[!l.sign()] = set_tag_empty(cards);
}
}
if (crd != 0 && !s().inconsistent()) {
init_watch(*crd, !l.sign());
}
if ((!is_tag_empty(pbs) || p) && !s().inconsistent()) {
asserted_pb(l, pbs, p);
}
if (m_has_xor && !s().inconsistent()) {
asserted_xor(l, xors, x);
}
} }
check_result card_extension::check() { return CR_DONE; } check_result card_extension::check() { return CR_DONE; }
void card_extension::push() { void card_extension::push() {
m_var_lim.push_back(m_var_trail.size()); m_index_lim.push_back(m_index_trail.size());
} }
void card_extension::pop(unsigned n) { void card_extension::pop(unsigned n) {
TRACE("sat_verbose", tout << "pop:" << n << "\n";); TRACE("sat_verbose", tout << "pop:" << n << "\n";);
unsigned new_lim = m_var_lim.size() - n; unsigned new_lim = m_index_lim.size() - n;
unsigned sz = m_var_lim[new_lim]; unsigned sz = m_index_lim[new_lim];
while (m_var_trail.size() > sz) { while (m_index_trail.size() > sz) {
bool_var v = m_var_trail.back(); unsigned index = m_index_trail.back();
m_var_trail.pop_back(); m_index_trail.pop_back();
if (v != null_bool_var) { if (is_card_index(index)) {
card* c = m_var_infos[v].m_card; SASSERT(m_cards.back()->index() == index);
if (c) { clear_watch(*m_cards.back());
clear_watch(*c); dealloc(m_cards.back());
m_var_infos[v].m_card = 0; m_cards.pop_back();
dealloc(c);
} }
xor* x = m_var_infos[v].m_xor; else if (is_pb_index(index)) {
if (x) { SASSERT(m_pbs.back()->index() == index);
clear_watch(*x); clear_watch(*m_pbs.back());
m_var_infos[v].m_xor = 0; dealloc(m_pbs.back());
dealloc(x); m_pbs.pop_back();
}
else if (is_xor_index(index)) {
SASSERT(m_xors.back()->index() == index);
clear_watch(*m_xors.back());
dealloc(m_xors.back());
m_xors.pop_back();
}
else {
UNREACHABLE();
} }
} }
} m_index_lim.resize(new_lim);
m_var_lim.resize(new_lim);
m_num_propagations_since_pop = 0; m_num_propagations_since_pop = 0;
} }
@ -1604,30 +1433,6 @@ namespace sat {
} }
} }
void card_extension::display_watch(std::ostream& out, bool_var v, bool sign) const {
card_watch const* w = m_var_infos[v].m_card_watch[sign];
if (!is_tag_empty(w)) {
card_watch const& wl = *w;
out << literal(v, sign) << " |-> ";
for (unsigned i = 0; i < wl.size(); ++i) {
out << wl[i]->lit() << " ";
}
out << "\n";
}
}
void card_extension::display_watch(std::ostream& out, bool_var v) const {
xor_watch const* w = m_var_infos[v].m_xor_watch;
if (!is_tag_empty(w)) {
xor_watch const& wl = *w;
out << "v" << v << " |-> ";
for (unsigned i = 0; i < wl.size(); ++i) {
out << wl[i]->lit() << " ";
}
out << "\n";
}
}
void card_extension::display(std::ostream& out, ineq& ineq) const { void card_extension::display(std::ostream& out, ineq& ineq) const {
for (unsigned i = 0; i < ineq.m_lits.size(); ++i) { for (unsigned i = 0; i < ineq.m_lits.size(); ++i) {
out << ineq.m_coeffs[i] << "*" << ineq.m_lits[i] << " "; out << ineq.m_coeffs[i] << "*" << ineq.m_lits[i] << " ";
@ -1694,17 +1499,6 @@ namespace sat {
} }
std::ostream& card_extension::display(std::ostream& out) const { std::ostream& card_extension::display(std::ostream& out) const {
for (unsigned vi = 0; vi < m_var_infos.size(); ++vi) {
display_watch(out, vi, false);
display_watch(out, vi, true);
display_watch(out, vi);
}
for (unsigned vi = 0; vi < m_var_infos.size(); ++vi) {
card* c = m_var_infos[vi].m_card;
if (c) display(out, *c, false);
xor* x = m_var_infos[vi].m_xor;
if (x) display(out, *x, false);
}
return out; return out;
} }

View file

@ -21,8 +21,10 @@ Revision History:
#include"sat_extension.h" #include"sat_extension.h"
#include"sat_solver.h" #include"sat_solver.h"
#include"sat_lookahead.h"
#include"scoped_ptr_vector.h" #include"scoped_ptr_vector.h"
namespace sat { namespace sat {
class card_extension : public extension { class card_extension : public extension {
@ -116,52 +118,8 @@ namespace sat {
void push(literal l, unsigned c) { m_lits.push_back(l); m_coeffs.push_back(c); } void push(literal l, unsigned c) { m_lits.push_back(l); m_coeffs.push_back(c); }
}; };
typedef ptr_vector<card> card_watch;
typedef ptr_vector<xor> xor_watch;
typedef ptr_vector<pb> pb_watch;
struct var_info {
card_watch* m_card_watch[2];
pb_watch* m_pb_watch[2];
xor_watch* m_xor_watch;
card* m_card;
pb* m_pb;
xor* m_xor;
var_info(): m_xor_watch(0), m_card(0), m_xor(0), m_pb(0) {
m_card_watch[0] = 0;
m_card_watch[1] = 0;
m_pb_watch[0] = 0;
m_pb_watch[1] = 0;
}
void reset() {
dealloc(m_card);
dealloc(m_xor);
dealloc(m_pb);
dealloc(card_extension::set_tag_non_empty(m_card_watch[0]));
dealloc(card_extension::set_tag_non_empty(m_card_watch[1]));
dealloc(card_extension::set_tag_non_empty(m_pb_watch[0]));
dealloc(card_extension::set_tag_non_empty(m_pb_watch[1]));
dealloc(card_extension::set_tag_non_empty(m_xor_watch));
}
};
template<typename T>
static ptr_vector<T>* set_tag_empty(ptr_vector<T>* c) {
return TAG(ptr_vector<T>*, c, 1);
}
template<typename T>
static bool is_tag_empty(ptr_vector<T> const* c) {
return !c || GET_TAG(c) == 1;
}
template<typename T>
static ptr_vector<T>* set_tag_non_empty(ptr_vector<T>* c) {
return UNTAG(ptr_vector<T>*, c);
}
solver* m_solver; solver* m_solver;
lookahead* m_lookahead;
stats m_stats; stats m_stats;
ptr_vector<card> m_cards; ptr_vector<card> m_cards;
@ -172,9 +130,8 @@ namespace sat {
scoped_ptr_vector<pb> m_pb_axioms; scoped_ptr_vector<pb> m_pb_axioms;
// watch literals // watch literals
svector<var_info> m_var_infos; unsigned_vector m_index_trail;
unsigned_vector m_var_trail; unsigned_vector m_index_lim;
unsigned_vector m_var_lim;
// conflict resolution // conflict resolution
unsigned m_num_marks; unsigned m_num_marks;
@ -185,7 +142,6 @@ namespace sat {
tracked_uint_set m_active_var_set; tracked_uint_set m_active_var_set;
literal_vector m_lemma; literal_vector m_lemma;
unsigned m_num_propagations_since_pop; unsigned m_num_propagations_since_pop;
bool m_has_xor;
unsigned_vector m_parity_marks; unsigned_vector m_parity_marks;
literal_vector m_parity_trail; literal_vector m_parity_trail;
@ -206,7 +162,7 @@ namespace sat {
void clear_watch(card& c); void clear_watch(card& c);
void reset_coeffs(); void reset_coeffs();
void reset_marked_literals(); void reset_marked_literals();
void unwatch_literal(literal w, card* c); void unwatch_literal(literal w, card& c);
void get_card_antecedents(literal l, card const& c, literal_vector & r); void get_card_antecedents(literal l, card const& c, literal_vector & r);
@ -214,13 +170,12 @@ namespace sat {
void copy_xor(card_extension& result); void copy_xor(card_extension& result);
void clear_watch(xor& x); void clear_watch(xor& x);
void watch_literal(xor& x, literal lit); void watch_literal(xor& x, literal lit);
void unwatch_literal(literal w, xor* x); void unwatch_literal(literal w, xor& x);
void init_watch(xor& x, bool is_true); void init_watch(xor& x, bool is_true);
void assign(xor& x, literal lit); void assign(xor& x, literal lit);
void set_conflict(xor& x, literal lit); void set_conflict(xor& x, literal lit);
bool parity(xor const& x, unsigned offset) const; bool parity(xor const& x, unsigned offset) const;
lbool add_assign(xor& x, literal alit); lbool add_assign(xor& x, literal alit);
void asserted_xor(literal l, ptr_vector<xor>* xors, xor* x);
void get_xor_antecedents(literal l, unsigned index, justification js, literal_vector& r); void get_xor_antecedents(literal l, unsigned index, justification js, literal_vector& r);
void get_xor_antecedents(literal l, xor const& x, literal_vector & r); void get_xor_antecedents(literal l, xor const& x, literal_vector & r);
@ -236,7 +191,6 @@ namespace sat {
// pb functionality // pb functionality
unsigned m_a_max; unsigned m_a_max;
void copy_pb(card_extension& result); void copy_pb(card_extension& result);
void asserted_pb(literal l, ptr_vector<pb>* pbs, pb* p);
void init_watch(pb& p, bool is_true); void init_watch(pb& p, bool is_true);
lbool add_assign(pb& p, literal alit); lbool add_assign(pb& p, literal alit);
void add_index(pb& p, unsigned index, literal lit); void add_index(pb& p, unsigned index, literal lit);
@ -244,28 +198,18 @@ namespace sat {
void clear_watch(pb& p); void clear_watch(pb& p);
void set_conflict(pb& p, literal lit); void set_conflict(pb& p, literal lit);
void assign(pb& p, literal l); void assign(pb& p, literal l);
void unwatch_literal(literal w, pb* p); void unwatch_literal(literal w, pb& p);
void get_pb_antecedents(literal l, pb const& p, literal_vector & r); void get_pb_antecedents(literal l, pb const& p, literal_vector & r);
inline lbool value(literal lit) const { return m_lookahead ? m_lookahead->value(lit) : m_solver->value(lit); }
template<typename T>
bool remove(ptr_vector<T>& ts, T* t) {
unsigned sz = ts.size();
for (unsigned j = 0; j < sz; ++j) {
if (ts[j] == t) {
std::swap(ts[j], ts[sz-1]);
ts.pop_back();
return sz == 1;
}
}
return false;
}
inline lbool value(literal lit) const { return m_solver->value(lit); }
inline unsigned lvl(literal lit) const { return m_solver->lvl(lit); } inline unsigned lvl(literal lit) const { return m_solver->lvl(lit); }
inline unsigned lvl(bool_var v) const { return m_solver->lvl(v); } inline unsigned lvl(bool_var v) const { return m_solver->lvl(v); }
inline bool inconsistent() const { return m_lookahead ? m_lookahead->inconsistent() : m_solver->inconsistent(); }
inline watch_list& get_wlist(literal l) { return m_lookahead ? m_lookahead->get_wlist(l) : m_solver->get_wlist(l); }
inline void assign(literal l, justification j) { if (m_lookahead) m_lookahead->assign(l); else m_solver->assign(l, j); }
inline void set_conflict(justification j, literal l) { if (m_lookahead) m_lookahead->set_conflict(); else m_solver->set_conflict(j, l); }
inline config const& get_config() const { return m_solver->get_config(); }
inline void drat_add(literal_vector const& c, svector<drat::premise> const& premises) { m_solver->m_drat.add(c, premises); }
void normalize_active_coeffs(); void normalize_active_coeffs();
@ -296,13 +240,12 @@ namespace sat {
void display(std::ostream& out, card const& c, bool values) const; void display(std::ostream& out, card const& c, bool values) const;
void display(std::ostream& out, pb const& p, bool values) const; void display(std::ostream& out, pb const& p, bool values) const;
void display(std::ostream& out, xor const& c, bool values) const; void display(std::ostream& out, xor const& c, bool values) const;
void display_watch(std::ostream& out, bool_var v) const;
void display_watch(std::ostream& out, bool_var v, bool sign) const;
public: public:
card_extension(); card_extension();
virtual ~card_extension(); virtual ~card_extension();
virtual void set_solver(solver* s) { m_solver = s; } virtual void set_solver(solver* s) { m_solver = s; }
virtual void set_lookahead(lookahead* l) { m_lookahead = l; }
void add_at_least(bool_var v, literal_vector const& lits, unsigned k); void add_at_least(bool_var v, literal_vector const& lits, unsigned k);
void add_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k); void add_pb_ge(bool_var v, svector<wliteral> const& wlits, unsigned k);
void add_xor(bool_var v, literal_vector const& lits); void add_xor(bool_var v, literal_vector const& lits);

View file

@ -33,6 +33,7 @@ namespace sat {
public: public:
virtual ~extension() {} virtual ~extension() {}
virtual void set_solver(solver* s) = 0; virtual void set_solver(solver* s) = 0;
virtual void set_lookahead(lookahead* s) = 0;
virtual void propagate(literal l, ext_constraint_idx idx, bool & keep) = 0; virtual void propagate(literal l, ext_constraint_idx idx, bool & keep) = 0;
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) = 0; virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) = 0;
virtual void asserted(literal l) = 0; virtual void asserted(literal l) = 0;

1597
src/sat/sat_lookahead.cpp Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -779,14 +779,14 @@ namespace sat {
case watched::EXT_CONSTRAINT: case watched::EXT_CONSTRAINT:
SASSERT(m_ext); SASSERT(m_ext);
m_ext->propagate(l, it->get_ext_constraint_idx(), keep); m_ext->propagate(l, it->get_ext_constraint_idx(), keep);
if (keep) {
*it2 = *it;
it2++;
}
if (m_inconsistent) { if (m_inconsistent) {
CONFLICT_CLEANUP(); CONFLICT_CLEANUP();
return false; return false;
} }
if (keep) {
*it2 = *it;
it2++;
}
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();

View file

@ -124,6 +124,7 @@ namespace sat {
}; };
class solver; class solver;
class lookahead;
class clause; class clause;
class clause_wrapper; class clause_wrapper;
class integrity_checker; class integrity_checker;

View file

@ -103,7 +103,7 @@ namespace sat {
} }
bool is_ext_constraint() const { return get_kind() == EXT_CONSTRAINT; } bool is_ext_constraint() const { return get_kind() == EXT_CONSTRAINT; }
ext_constraint_idx get_ext_constraint_idx() const { SASSERT(is_ext_constraint()); return m_val2; } ext_constraint_idx get_ext_constraint_idx() const { SASSERT(is_ext_constraint()); return m_val1; }
bool operator==(watched const & w) const { return m_val1 == w.m_val1 && m_val2 == w.m_val2; } bool operator==(watched const & w) const { return m_val1 == w.m_val1 && m_val2 == w.m_val2; }
bool operator!=(watched const & w) const { return !operator==(w); } bool operator!=(watched const & w) const { return !operator==(w); }