3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-28 23:17:56 +00:00

make cutset maintainance incremental, expose option for goal2sat to populate aig

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-01-08 16:39:49 -08:00
parent 301f9598a4
commit ca243428f8
7 changed files with 188 additions and 156 deletions

View file

@ -16,9 +16,12 @@
--*/ --*/
#include "sat/sat_aig_finder.h" #include "sat/sat_aig_finder.h"
#include "sat/sat_solver.h"
namespace sat { namespace sat {
aig_finder::aig_finder(solver& s): s(s), m_big(s.rand()) {}
void aig_finder::operator()(clause_vector& clauses) { void aig_finder::operator()(clause_vector& clauses) {
m_big.init(s, true); m_big.init(s, true);
find_aigs(clauses); find_aigs(clauses);

View file

@ -29,11 +29,12 @@
#include "util/statistics.h" #include "util/statistics.h"
#include "sat/sat_clause.h" #include "sat/sat_clause.h"
#include "sat/sat_types.h" #include "sat/sat_types.h"
#include "sat/sat_solver.h"
#include "sat/sat_big.h" #include "sat/sat_big.h"
namespace sat { namespace sat {
class solver;
class aig_finder { class aig_finder {
solver& s; solver& s;
big m_big; big m_big;
@ -50,7 +51,7 @@ namespace sat {
void validate_clause(literal_vector const& clause, vector<literal_vector> const& clauses); void validate_clause(literal_vector const& clause, vector<literal_vector> const& clauses);
public: public:
aig_finder(solver& s) : s(s), m_big(s.rand()) {} aig_finder(solver& s);
~aig_finder() {} ~aig_finder() {}
void set(std::function<void (literal head, literal_vector const& ands)>& f) { m_on_aig = f; } void set(std::function<void (literal head, literal_vector const& ands)>& f) { m_on_aig = f; }
void set(std::function<void (literal head, literal cond, literal th, literal el)>& f) { m_on_if = f; } void set(std::function<void (literal head, literal cond, literal th, literal el)>& f) { m_on_if = f; }

View file

@ -25,9 +25,8 @@ namespace sat {
struct aig_simplifier::report { struct aig_simplifier::report {
aig_simplifier& s; aig_simplifier& s;
aig_cuts& c;
stopwatch m_watch; stopwatch m_watch;
report(aig_simplifier& s, aig_cuts& c): s(s), c(c) { m_watch.start(); } report(aig_simplifier& s): s(s) { m_watch.start(); }
~report() { ~report() {
IF_VERBOSE(2, IF_VERBOSE(2,
verbose_stream() << "(sat.aig-simplifier" verbose_stream() << "(sat.aig-simplifier"
@ -39,39 +38,53 @@ namespace sat {
} }
}; };
aig_simplifier::aig_simplifier(solver& s):s(s), m_aig_cuts(m_config.m_max_cut_size, m_config.m_max_cutset_size) {
}
void aig_simplifier::add_and(literal head, unsigned sz, literal const* lits) {
m_aig_cuts.add_node(head, and_op, sz, lits);
}
void aig_simplifier::add_or(literal head, unsigned sz, literal const* lits) {
m_aig_cuts.add_node(head, and_op, sz, lits);
}
void aig_simplifier::add_xor(literal head, unsigned sz, literal const* lits) {
m_aig_cuts.add_node(head, xor_op, sz, lits);
}
void aig_simplifier::add_ite(literal head, literal c, literal t, literal e) {
literal lits[3] = { c, t, e };
m_aig_cuts.add_node(head, ite_op, 3, lits);
}
void aig_simplifier::add_iff(literal head, literal l1, literal l2) {
literal lits[2] = { l1, ~l2 };
m_aig_cuts.add_node(head, xor_op, 2, lits);
}
void aig_simplifier::operator()() { void aig_simplifier::operator()() {
aig_cuts aigc; report _report(*this);
report _report(*this, aigc);
TRACE("aig_simplifier", s.display(tout);); TRACE("aig_simplifier", s.display(tout););
clauses2aig(aigc); clauses2aig();
aig2clauses(aigc); aig2clauses();
} }
/** /**
\brief extract AIG definitions from clauses \brief extract AIG definitions from clauses
Ensure that they are sorted and variables have unique definitions. Ensure that they are sorted and variables have unique definitions.
*/ */
void aig_simplifier::clauses2aig(aig_cuts& aigc) { void aig_simplifier::clauses2aig() {
struct aig_def {
literal head;
bool_op op;
unsigned sz;
unsigned offset;
aig_def(literal h, bool_op op, unsigned sz, unsigned o): head(h), op(op), sz(sz), offset(o) {}
};
svector<aig_def> aig_defs;
literal_vector literals; literal_vector literals;
std::function<void (literal head, literal_vector const& ands)> on_and = std::function<void (literal head, literal_vector const& ands)> on_and =
[&,this](literal head, literal_vector const& ands) { [&,this](literal head, literal_vector const& ands) {
aig_defs.push_back(aig_def(head, and_op, ands.size(), literals.size())); m_aig_cuts.add_node(head, and_op, ands.size(), ands.c_ptr());
literals.append(ands);
m_stats.m_num_ands++; m_stats.m_num_ands++;
}; };
std::function<void (literal head, literal c, literal t, literal e)> on_ite = std::function<void (literal head, literal c, literal t, literal e)> on_ite =
[&,this](literal head, literal c, literal t, literal e) { [&,this](literal head, literal c, literal t, literal e) {
aig_defs.push_back(aig_def(head, ite_op, 3, literals.size())); literal args[3] = { c, t, e };
literal args[3] = { c, t, e }; m_aig_cuts.add_node(head, ite_op, 3, args);
literals.append(3, args);
m_stats.m_num_ites++; m_stats.m_num_ites++;
}; };
aig_finder af(s); aig_finder af(s);
@ -97,88 +110,25 @@ namespace sat {
// ~head = t1 + t2 + .. // ~head = t1 + t2 + ..
literal head = ~xors[index]; literal head = ~xors[index];
unsigned sz = xors.size() - 1; unsigned sz = xors.size() - 1;
aig_defs.push_back(aig_def(head, xor_op, sz, literals.size()));
for (unsigned i = xors.size(); i-- > 0; ) { for (unsigned i = xors.size(); i-- > 0; ) {
if (i != index) if (i != index)
literals.push_back(xors[i]); literals.push_back(xors[i]);
} }
m_aig_cuts.add_node(head, xor_op, sz, literals.c_ptr());
literals.reset();
m_stats.m_num_xors++; m_stats.m_num_xors++;
}; };
xor_finder xf(s); xor_finder xf(s);
xf.set(on_xor); xf.set(on_xor);
xf(clauses); xf(clauses);
svector<bool> outs(s.num_vars(), false);
svector<bool> ins(s.num_vars(), false);
for (auto a : aig_defs) {
outs[a.head.var()] = true;
}
for (auto a : aig_defs) {
for (unsigned i = 0; i < a.sz; ++i) {
unsigned v = literals[a.offset+i].var();
if (!outs[v]) ins[v] = true;
}
}
std::function<void(aig_def)> force_var = [&] (aig_def a) {
for (unsigned i = 0; i < a.sz; ++i) {
unsigned v = literals[a.offset + i].var();
if (!ins[v]) {
aigc.add_var(v);
ins[v] = true;
}
}
};
std::function<void(unsigned)> add_var = [&] (unsigned v) {
if (!outs[v] && ins[v]) {
aigc.add_var(v);
outs[v] = true;
}
};
for (auto a : aig_defs) {
for (unsigned i = 0; i < a.sz; ++i) {
add_var(literals[a.offset+i].var());
}
}
while (true) {
unsigned j = 0;
for (auto a : aig_defs) {
bool visited = true;
for (unsigned i = 0; visited && i < a.sz; ++i) {
visited &= ins[literals[a.offset + i].var()];
}
unsigned h = a.head.var();
if (!ins[h] && visited) {
ins[h] = true;
aigc.add_node(a.head, a.op, a.sz, literals.c_ptr() + a.offset);
}
else if (!ins[h]) {
aig_defs[j++] = a;
}
else {
TRACE("aig_simplifier", tout << "skip " << a.head << " == .. \n";);
force_var(a);
}
}
if (j == 0) {
break;
}
if (j == aig_defs.size()) {
IF_VERBOSE(2, verbose_stream() << "break cycle " << j << "\n");
force_var(aig_defs.back());
}
aig_defs.shrink(j);
}
} }
void aig_simplifier::aig2clauses(aig_cuts& aigc) { void aig_simplifier::aig2clauses() {
vector<cut_set> cuts = aigc.get_cuts(m_config.m_max_cut_size, m_config.m_max_cutset_size); vector<cut_set> const& cuts = m_aig_cuts.get_cuts();
map<cut const*, unsigned, cut::hash_proc, cut::eq_proc> cut2id; map<cut const*, unsigned, cut::hash_proc, cut::eq_proc> cut2id;
union_find_default_ctx ctx; union_find_default_ctx ctx;
union_find<> uf(ctx); union_find<> uf(ctx), uf2(ctx);
for (unsigned i = 2*s.num_vars(); i--> 0; ) uf.mk_var(); for (unsigned i = 2*s.num_vars(); i--> 0; ) uf.mk_var();
auto add_eq = [&](literal l1, literal l2) { auto add_eq = [&](literal l1, literal l2) {
uf.merge(l1.index(), l2.index()); uf.merge(l1.index(), l2.index());
@ -212,8 +162,31 @@ namespace sat {
} }
} }
if (old_num_eqs < m_stats.m_num_eqs) { if (old_num_eqs < m_stats.m_num_eqs) {
elim_eqs elim(s); // extract equivalences over non-eliminated literals.
elim(uf); bool new_eq = false;
for (unsigned idx = 0; idx < uf.get_num_vars(); ++idx) {
if (!uf.is_root(idx) || 1 == uf.size(idx)) continue;
literal root = null_literal;
unsigned first = idx;
do {
literal lit = to_literal(idx);
if (!s.was_eliminated(lit)) {
if (root == null_literal) {
root = lit;
}
else {
uf2.merge(lit.index(), root.index());
new_eq = true;
}
}
idx = uf.next(idx);
}
while (first != idx);
}
if (new_eq) {
elim_eqs elim(s);
elim(uf2);
}
} }
} }
@ -224,28 +197,18 @@ namespace sat {
st.update("sat-aig.ites", m_stats.m_num_ites); st.update("sat-aig.ites", m_stats.m_num_ites);
st.update("sat-aig.xors", m_stats.m_num_xors); st.update("sat-aig.xors", m_stats.m_num_xors);
} }
vector<cut_set> aig_cuts::get_cuts(unsigned max_cut_size, unsigned max_cutset_size) { aig_cuts::aig_cuts(unsigned max_cut_size, unsigned max_cutset_size) {
unsigned_vector sorted = top_sort();
vector<cut_set> cuts(m_aig.size());
m_max_cut_size = std::min(cut().max_cut_size, max_cut_size); m_max_cut_size = std::min(cut().max_cut_size, max_cut_size);
m_max_cutset_size = max_cutset_size; m_max_cutset_size = max_cutset_size;
}
vector<cut_set> const& aig_cuts::get_cuts() {
unsigned_vector node_ids = filter_valid_nodes();
m_cut_set1.init(m_region, m_max_cutset_size + 1); m_cut_set1.init(m_region, m_max_cutset_size + 1);
m_cut_set2.init(m_region, m_max_cutset_size + 1); m_cut_set2.init(m_region, m_max_cutset_size + 1);
augment(node_ids, m_cuts);
unsigned j = 0; return m_cuts;
for (unsigned id : sorted) {
node const& n = m_aig[id];
if (n.is_valid()) {
auto& cut_set = cuts[id];
cut_set.init(m_region, m_max_cutset_size + 1);
cut_set.push_back(cut(id));
sorted[j++] = id;
}
}
sorted.shrink(j);
augment(sorted, cuts);
return cuts;
} }
void aig_cuts::augment(unsigned_vector const& ids, vector<cut_set>& cuts) { void aig_cuts::augment(unsigned_vector const& ids, vector<cut_set>& cuts) {
@ -259,6 +222,12 @@ namespace sat {
else if (n.is_ite()) { else if (n.is_ite()) {
augment_ite(n, cut_set, cuts); augment_ite(n, cut_set, cuts);
} }
else if (n.num_children() == 0) {
augment_aig0(n, cut_set, cuts);
}
else if (n.num_children() == 1) {
augment_aig1(n, cut_set, cuts);
}
else if (n.num_children() == 2) { else if (n.num_children() == 2) {
augment_aig2(n, cut_set, cuts); augment_aig2(n, cut_set, cuts);
} }
@ -299,6 +268,28 @@ namespace sat {
} }
} }
void aig_cuts::augment_aig0(node const& n, cut_set& cs, vector<cut_set>& cuts) {
SASSERT(n.is_and());
cut c;
cs.reset();
if (!n.sign()) {
c.m_table = 3;
}
cs.insert(c);
}
void aig_cuts::augment_aig1(node const& n, cut_set& cs, vector<cut_set>& cuts) {
SASSERT(n.is_and());
literal lit = child(n, 0);
for (auto const& a : cuts[lit.var()]) {
if (cs.size() >= m_max_cutset_size) break;
cut c;
c.set_table(a.m_table);
if (n.sign()) c.negate();
cs.insert(c);
}
}
void aig_cuts::augment_aig2(node const& n, cut_set& cs, vector<cut_set>& cuts) { void aig_cuts::augment_aig2(node const& n, cut_set& cs, vector<cut_set>& cuts) {
SASSERT(n.is_and() || n.is_xor()); SASSERT(n.is_and() || n.is_xor());
literal l1 = child(n, 0); literal l1 = child(n, 0);
@ -363,7 +354,11 @@ namespace sat {
void aig_cuts::add_var(unsigned v) { void aig_cuts::add_var(unsigned v) {
m_aig.reserve(v + 1); m_aig.reserve(v + 1);
m_aig[v] = node(v); m_cuts.reserve(v + 1);
if (!m_aig[v].is_valid()) {
m_aig[v] = node(v);
init_cut_set(v);
}
SASSERT(m_aig[v].is_valid()); SASSERT(m_aig[v].is_valid());
} }
@ -371,49 +366,45 @@ namespace sat {
TRACE("aig_simplifier", tout << head << " == " << op << " " << literal_vector(sz, args) << "\n";); TRACE("aig_simplifier", tout << head << " == " << op << " " << literal_vector(sz, args) << "\n";);
unsigned v = head.var(); unsigned v = head.var();
m_aig.reserve(v + 1); m_aig.reserve(v + 1);
m_aig[v] = node(head.sign(), op, sz, m_literals.size()); unsigned offset = m_literals.size();
node n(head.sign(), op, sz, offset);
m_literals.append(sz, args); m_literals.append(sz, args);
DEBUG_CODE( for (unsigned i = 0; i < sz; ++i) {
for (unsigned i = 0; i < sz; ++i) { if (!m_aig[args[i].var()].is_valid()) {
SASSERT(m_aig[args[i].var()].is_valid()); add_var(args[i].var());
}); }
}
if (!m_aig[v].is_valid() || m_aig[v].is_var()) {
m_aig[v] = n;
init_cut_set(v);
}
else {
insert_aux(v, n);
}
SASSERT(m_aig[v].is_valid()); SASSERT(m_aig[v].is_valid());
} }
unsigned_vector aig_cuts::top_sort() { void aig_cuts::init_cut_set(unsigned id) {
unsigned_vector result; node const& n = m_aig[id];
svector<bool> visit; SASSERT(n.is_valid());
visit.reserve(m_aig.size(), false); auto& cut_set = m_cuts[id];
unsigned_vector todo; cut_set.init(m_region, m_max_cutset_size + 1);
cut_set.push_back(cut(id));
}
void aig_cuts::insert_aux(unsigned v, node const& n) {
// TBD: throttle and replacement strategy
m_aux_aig.reserve(v + 1);
m_aux_aig[v].push_back(n);
}
unsigned_vector aig_cuts::filter_valid_nodes() {
unsigned id = 0; unsigned id = 0;
unsigned_vector result;
for (node const& n : m_aig) { for (node const& n : m_aig) {
if (n.is_valid()) todo.push_back(id); if (n.is_valid()) result.push_back(id);
++id; ++id;
} }
while (!todo.empty()) {
unsigned id = todo.back();
if (visit[id]) {
todo.pop_back();
continue;
}
bool all_visit = true;
node const& n = m_aig[id];
SASSERT(n.is_valid());
if (!n.is_var()) {
for (unsigned i = 0; i < n.num_children(); ++i) {
bool_var v = child(n, i).var();
if (!visit[v]) {
todo.push_back(v);
all_visit = false;
}
}
}
if (all_visit) {
visit[id] = true;
result.push_back(id);
todo.pop_back();
}
}
return result; return result;
} }
} }

View file

@ -61,18 +61,26 @@ namespace sat {
unsigned m_max_cut_size; unsigned m_max_cut_size;
unsigned m_max_cutset_size; unsigned m_max_cutset_size;
cut_set m_cut_set1, m_cut_set2; cut_set m_cut_set1, m_cut_set2;
vector<cut_set> m_cuts;
unsigned_vector top_sort(); void insert_aux(unsigned v, node const& n);
void init_cut_set(unsigned id);
unsigned_vector filter_valid_nodes();
void augment(unsigned_vector const& ids, vector<cut_set>& cuts); void augment(unsigned_vector const& ids, vector<cut_set>& cuts);
void augment_ite(node const& n, cut_set& cs, vector<cut_set>& cuts); void augment_ite(node const& n, cut_set& cs, vector<cut_set>& cuts);
void augment_aig0(node const& n, cut_set& cs, vector<cut_set>& cuts);
void augment_aig1(node const& n, cut_set& cs, vector<cut_set>& cuts);
void augment_aig2(node const& n, cut_set& cs, vector<cut_set>& cuts); void augment_aig2(node const& n, cut_set& cs, vector<cut_set>& cuts);
void augment_aigN(node const& n, cut_set& cs, vector<cut_set>& cuts); void augment_aigN(node const& n, cut_set& cs, vector<cut_set>& cuts);
public: public:
aig_cuts(unsigned max_cut_size, unsigned max_cutset_size);
void add_var(unsigned v); void add_var(unsigned v);
void add_node(literal head, bool_op op, unsigned sz, literal const* args); void add_node(literal head, bool_op op, unsigned sz, literal const* args);
literal child(node const& n, unsigned idx) const { SASSERT(!n.is_var()); SASSERT(idx < n.num_children()); return m_literals[n.offset() + idx]; } literal child(node const& n, unsigned idx) const { SASSERT(!n.is_var()); SASSERT(idx < n.num_children()); return m_literals[n.offset() + idx]; }
vector<cut_set> get_cuts(unsigned max_cut_size, unsigned max_cutset_size); vector<cut_set> const & get_cuts();
}; };
class aig_simplifier { class aig_simplifier {
@ -91,14 +99,22 @@ namespace sat {
solver& s; solver& s;
stats m_stats; stats m_stats;
config m_config; config m_config;
aig_cuts m_aig_cuts;
struct report; struct report;
void clauses2aig(aig_cuts& aigc); void clauses2aig();
void aig2clauses(aig_cuts& aigc); void aig2clauses();
public: public:
aig_simplifier(solver& s) : s(s) {} aig_simplifier(solver& s);
~aig_simplifier() {} ~aig_simplifier() {}
void operator()(); void operator()();
void collect_statistics(statistics& st) const; void collect_statistics(statistics& st) const;
void add_and(literal head, unsigned sz, literal const* args);
void add_or(literal head, unsigned sz, literal const* args);
void add_xor(literal head, unsigned sz, literal const* args);
void add_ite(literal head, literal c, literal t, literal e);
void add_iff(literal head, literal l1, literal l2);
}; };
} }

View file

@ -31,6 +31,7 @@ Revision History:
#include "sat/sat_simplifier.h" #include "sat/sat_simplifier.h"
#include "sat/sat_scc.h" #include "sat/sat_scc.h"
#include "sat/sat_asymm_branch.h" #include "sat/sat_asymm_branch.h"
#include "sat/sat_aig_simplifier.h"
#include "sat/sat_iff3_finder.h" #include "sat/sat_iff3_finder.h"
#include "sat/sat_probing.h" #include "sat/sat_probing.h"
#include "sat/sat_mus.h" #include "sat/sat_mus.h"
@ -89,6 +90,7 @@ namespace sat {
config m_config; config m_config;
stats m_stats; stats m_stats;
scoped_ptr<extension> m_ext; scoped_ptr<extension> m_ext;
scoped_ptr<aig_simplifier> m_aig_simplifier;
parallel* m_par; parallel* m_par;
drat m_drat; // DRAT for generating proofs drat m_drat; // DRAT for generating proofs
clause_allocator m_cls_allocator[2]; clause_allocator m_cls_allocator[2];
@ -398,6 +400,7 @@ namespace sat {
bool is_incremental() const { return m_config.m_incremental; } bool is_incremental() const { return m_config.m_incremental; }
extension* get_extension() const override { return m_ext.get(); } extension* get_extension() const override { return m_ext.get(); }
void set_extension(extension* e) override; void set_extension(extension* e) override;
aig_simplifier* get_aig_simplifier() override { return m_aig_simplifier.get(); }
bool set_root(literal l, literal r); bool set_root(literal l, literal r);
void flush_roots(); void flush_roots();
typedef std::pair<literal, literal> bin_clause; typedef std::pair<literal, literal> bin_clause;

View file

@ -23,7 +23,10 @@ Revision History:
#include "sat/sat_types.h" #include "sat/sat_types.h"
namespace sat { namespace sat {
class aig_simplifier;
class extension;
class solver_core { class solver_core {
protected: protected:
reslimit& m_rlimit; reslimit& m_rlimit;
@ -89,6 +92,8 @@ namespace sat {
virtual extension* get_extension() const { return nullptr; } virtual extension* get_extension() const { return nullptr; }
virtual void set_extension(extension* e) { if (e) throw default_exception("optional API not supported"); } virtual void set_extension(extension* e) { if (e) throw default_exception("optional API not supported"); }
virtual aig_simplifier* get_aig_simplifier() { return nullptr; }
// The following methods are used when converting the state from the SAT solver back // The following methods are used when converting the state from the SAT solver back
// to a set of assertions. // to a set of assertions.

View file

@ -35,6 +35,7 @@ Notes:
#include "ast/for_each_expr.h" #include "ast/for_each_expr.h"
#include "sat/tactic/goal2sat.h" #include "sat/tactic/goal2sat.h"
#include "sat/ba_solver.h" #include "sat/ba_solver.h"
#include "sat/sat_aig_simplifier.h"
#include "model/model_evaluator.h" #include "model/model_evaluator.h"
#include "model/model_v2_pp.h" #include "model/model_v2_pp.h"
#include "tactic/tactic.h" #include "tactic/tactic.h"
@ -53,6 +54,7 @@ struct goal2sat::imp {
ast_manager & m; ast_manager & m;
pb_util pb; pb_util pb;
sat::ba_solver* m_ext; sat::ba_solver* m_ext;
sat::aig_simplifier* m_aig;
svector<frame> m_frame_stack; svector<frame> m_frame_stack;
svector<sat::literal> m_result_stack; svector<sat::literal> m_result_stack;
obj_map<app, sat::literal> m_cache; obj_map<app, sat::literal> m_cache;
@ -73,6 +75,7 @@ struct goal2sat::imp {
m(_m), m(_m),
pb(m), pb(m),
m_ext(nullptr), m_ext(nullptr),
m_aig(nullptr),
m_solver(s), m_solver(s),
m_map(map), m_map(map),
m_dep2asm(dep2asm), m_dep2asm(dep2asm),
@ -82,6 +85,7 @@ struct goal2sat::imp {
m_is_lemma(false) { m_is_lemma(false) {
updt_params(p); updt_params(p);
m_true = sat::null_literal; m_true = sat::null_literal;
m_aig = s.get_aig_simplifier();
} }
void updt_params(params_ref const & p) { void updt_params(params_ref const & p) {
@ -252,6 +256,9 @@ struct goal2sat::imp {
sat::literal l(k, false); sat::literal l(k, false);
m_cache.insert(t, l); m_cache.insert(t, l);
sat::literal * lits = m_result_stack.end() - num; sat::literal * lits = m_result_stack.end() - num;
if (m_aig) m_aig->add_or(l, num, lits);
for (unsigned i = 0; i < num; i++) { for (unsigned i = 0; i < num; i++) {
mk_clause(~lits[i], l); mk_clause(~lits[i], l);
} }
@ -290,8 +297,11 @@ struct goal2sat::imp {
sat::bool_var k = m_solver.add_var(false); sat::bool_var k = m_solver.add_var(false);
sat::literal l(k, false); sat::literal l(k, false);
m_cache.insert(t, l); m_cache.insert(t, l);
// l => /\ lits
sat::literal * lits = m_result_stack.end() - num; sat::literal * lits = m_result_stack.end() - num;
if (m_aig) m_aig->add_and(l, num, lits);
// l => /\ lits
for (unsigned i = 0; i < num; i++) { for (unsigned i = 0; i < num; i++) {
mk_clause(~l, lits[i]); mk_clause(~l, lits[i]);
} }
@ -341,6 +351,7 @@ struct goal2sat::imp {
mk_clause(~t, ~e, l, false); mk_clause(~t, ~e, l, false);
mk_clause(t, e, ~l, false); mk_clause(t, e, ~l, false);
} }
if (m_aig) m_aig->add_ite(l, c, t, e);
m_result_stack.shrink(sz-3); m_result_stack.shrink(sz-3);
if (sign) if (sign)
l.neg(); l.neg();
@ -374,6 +385,7 @@ struct goal2sat::imp {
mk_clause(~l, ~l1, l2); mk_clause(~l, ~l1, l2);
mk_clause(l, l1, l2); mk_clause(l, l1, l2);
mk_clause(l, ~l1, ~l2); mk_clause(l, ~l1, ~l2);
if (m_aig) m_aig->add_iff(l, l1, l2);
m_result_stack.shrink(sz-2); m_result_stack.shrink(sz-2);
if (sign) if (sign)
l.neg(); l.neg();
@ -400,6 +412,7 @@ struct goal2sat::imp {
} }
ensure_extension(); ensure_extension();
m_ext->add_xr(lits); m_ext->add_xr(lits);
if (m_aig) m_aig->add_xor(~lits.back(), lits.size() - 1, lits.c_ptr() + 1);
sat::literal lit(v, sign); sat::literal lit(v, sign);
if (root) { if (root) {
m_result_stack.reset(); m_result_stack.reset();
@ -634,7 +647,7 @@ struct goal2sat::imp {
m_ext = alloc(sat::ba_solver); m_ext = alloc(sat::ba_solver);
m_solver.set_extension(m_ext); m_solver.set_extension(m_ext);
} }
} }
} }
void convert(app * t, bool root, bool sign) { void convert(app * t, bool root, bool sign) {