3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-06 01:24:08 +00:00

adding ack/model

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-08-28 12:55:31 -07:00
parent 7f0b5bc129
commit 4244ce4aad
31 changed files with 831 additions and 914 deletions

View file

@ -39,9 +39,7 @@ def init_project_def():
add_lib('solver', ['model', 'tactic', 'proofs'])
add_lib('cmd_context', ['solver', 'rewriter'])
add_lib('sat_smt', ['sat', 'euf', 'tactic'], 'sat/smt')
add_lib('sat_ba', ['sat', 'sat_smt'], 'sat/ba')
add_lib('sat_euf', ['sat', 'euf', 'sat_ba'], 'sat/euf')
add_lib('sat_tactic', ['tactic', 'sat', 'solver', 'sat_euf'], 'sat/tactic')
add_lib('sat_tactic', ['tactic', 'sat', 'solver', 'sat_smt'], 'sat/tactic')
add_lib('smt2parser', ['cmd_context', 'parser_util'], 'parsers/smt2')
add_lib('pattern', ['normal_forms', 'smt2parser', 'rewriter'], 'ast/pattern')
add_lib('core_tactics', ['tactic', 'macros', 'normal_forms', 'rewriter', 'pattern'], 'tactic/core')
@ -83,7 +81,7 @@ def init_project_def():
includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files)
add_lib('extra_cmds', ['cmd_context', 'subpaving_tactic', 'qe', 'arith_tactics'], 'cmd_context/extra_cmds')
add_exe('shell', ['api', 'sat', 'extra_cmds','opt'], exe_name='z3')
add_exe('test', ['api', 'fuzzing', 'simplex', 'sat_euf'], exe_name='test-z3', install=False)
add_exe('test', ['api', 'fuzzing', 'simplex', 'sat_smt'], exe_name='test-z3', install=False)
_libz3Component = add_dll('api_dll', ['api', 'sat', 'extra_cmds'], 'api/dll',
reexports=['api'],
dll_name='libz3',

View file

@ -60,8 +60,6 @@ add_subdirectory(math/subpaving/tactic)
add_subdirectory(tactic/aig)
add_subdirectory(solver)
add_subdirectory(sat/smt)
add_subdirectory(sat/ba)
add_subdirectory(sat/euf)
add_subdirectory(sat/tactic)
add_subdirectory(tactic/arith)
add_subdirectory(nlsat/tactic)

View file

@ -255,7 +255,10 @@ namespace euf {
explanations up to the least common ancestors.
*/
void egraph::push_congruence(enode* n1, enode* n2, bool comm) {
SASSERT(is_app(n1->get_owner()));
SASSERT(n1->get_decl() == n2->get_decl());
if (m_used_cc)
m_used_cc(to_app(n1->get_owner()), to_app(n2->get_owner()));
if (comm &&
n1->get_arg(0)->get_root() == n2->get_arg(1)->get_root() &&
n1->get_arg(1)->get_root() == n2->get_arg(0)->get_root()) {
@ -268,30 +271,28 @@ namespace euf {
push_lca(n1->get_arg(i), n2->get_arg(i));
}
void egraph::push_lca(enode* a, enode* b) {
enode* egraph::find_lca(enode* a, enode* b) {
SASSERT(a->get_root() == b->get_root());
enode* n = a;
while (n) {
n->mark2();
n = n->m_target;
}
n = b;
while (n) {
if (n->is_marked2())
n->unmark2();
else if (!n->is_marked1())
m_todo.push_back(n);
n = n->m_target;
}
n = a;
while (n->is_marked2()) {
n->unmark2();
if (!n->is_marked1())
m_todo.push_back(n);
a->mark2_targets<true>();
while (!b->is_marked2())
b = b->m_target;
a->mark2_targets<false>();
return b;
}
void egraph::push_to_lca(enode* n, enode* lca) {
while (n != lca) {
m_todo.push_back(n);
n = n->m_target;
}
}
void egraph::push_lca(enode* a, enode* b) {
enode* lca = find_lca(a, b);
push_to_lca(a, lca);
push_to_lca(b, lca);
}
void egraph::push_todo(enode* n) {
while (n) {
m_todo.push_back(n);
@ -313,7 +314,11 @@ namespace euf {
void egraph::explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, bool comm) {
SASSERT(m_todo.empty());
SASSERT(a->get_root() == b->get_root());
push_lca(a, b);
enode* lca = find_lca(a, b);
push_to_lca(a, lca);
push_to_lca(b, lca);
if (m_used_eq)
m_used_eq(a->get_owner(), b->get_owner(), lca->get_owner());
explain_todo(justifications);
}

View file

@ -70,7 +70,8 @@ namespace euf {
enode_vector m_new_lits;
enode_vector m_todo;
stats m_stats;
std::function<void(expr*,expr*,expr*)> m_used_eq;
std::function<void(app*,app*)> m_used_cc;
void push_eq(enode* r1, enode* n1, unsigned r2_num_parents) {
m_eqs.push_back(add_eq_record(r1, n1, r2_num_parents));
@ -87,6 +88,8 @@ namespace euf {
void reinsert_equality(enode* p);
void update_children(enode* n);
void push_lca(enode* a, enode* b);
enode* find_lca(enode* a, enode* b);
void push_to_lca(enode* a, enode* lca);
void push_congruence(enode* n1, enode* n2, bool commutative);
void push_todo(enode* n);
template <typename T>
@ -126,6 +129,10 @@ namespace euf {
bool inconsistent() const { return m_inconsistent; }
enode_vector const& new_eqs() const { return m_new_eqs; }
enode_vector const& new_lits() const { return m_new_lits; }
void set_used_eq(std::function<void(expr*,expr*,expr*)>& used_eq) { m_used_eq = used_eq; }
void set_used_cc(std::function<void(app*,app*)>& used_cc) { m_used_cc = used_cc; }
template <typename T>
void explain(ptr_vector<T>& justifications);
template <typename T>

View file

@ -104,11 +104,29 @@ namespace euf {
void mark2() { m_mark2 = true; }
void unmark2() { m_mark2 = false; }
bool is_marked2() { return m_mark2; }
template<bool m> void mark1_targets() {
enode* n = this;
while (n) {
if (m) n->mark1(); else n->unmark1();
n = n->m_target;
}
}
template<bool m> void mark2_targets() {
enode* n = this;
while (n) {
if (m) n->mark2(); else n->unmark2();
n = n->m_target;
}
}
void add_parent(enode* p) { m_parents.push_back(p); }
unsigned class_size() const { return m_class_size; }
bool is_root() const { return m_root == this; }
enode* get_root() const { return m_root; }
expr* get_owner() const { return m_owner; }
unsigned get_owner_id() const { return m_owner->get_id(); }
unsigned get_root_id() const { return m_root->m_owner->get_id(); }
void inc_class_size(unsigned n) { m_class_size += n; }
void dec_class_size(unsigned n) { m_class_size -= n; }

View file

@ -1,8 +0,0 @@
z3_add_component(sat_ba
SOURCES
ba_solver.cpp
ba_internalize.cpp
COMPONENT_DEPENDENCIES
sat
)

View file

@ -1,9 +0,0 @@
z3_add_component(sat_euf
SOURCES
euf_solver.cpp
euf_model.cpp
COMPONENT_DEPENDENCIES
sat
sat_smt
euf
)

View file

@ -1,72 +0,0 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
euf_model.cpp
Abstract:
Model building for EUF solver plugin.
Author:
Nikolaj Bjorner (nbjorner) 2020-08-25
--*/
#include "ast/ast_pp.h"
#include "sat/euf/euf_solver.h"
#include "model/value_factory.h"
namespace euf {
model_converter* solver::get_model() {
sat::th_dependencies deps;
collect_dependencies(deps);
// deps.sort();
expr_ref_vector values(m);
dependencies2values(deps, values);
return nullptr;
}
void solver::collect_dependencies(sat::th_dependencies& deps) {
}
void solver::dependencies2values(sat::th_dependencies& deps, expr_ref_vector& values) {
user_sort_factory user_sort(m);
for (enode* n : deps) {
unsigned id = n->get_root()->get_owner_id();
if (values.get(id) != nullptr)
continue;
expr* e = n->get_owner();
values.reserve(id + 1);
if (m.is_bool(e)) {
switch (s().value(m_expr2var.to_bool_var(e))) {
case l_true:
values.set(id, m.mk_true());
break;
default:
values.set(id, m.mk_false());
break;
}
continue;
}
auto* mb = get_model_builder(e);
if (mb)
mb->add_value(n, values);
else if (m.is_uninterp(m.get_sort(e))) {
expr* v = user_sort.get_fresh_value(m.get_sort(e));
values.set(id, v);
}
else {
IF_VERBOSE(1, verbose_stream() << "no model values created for " << mk_pp(e, m) << "\n");
}
}
NOT_IMPLEMENTED_YET();
}
}

View file

@ -86,7 +86,7 @@ namespace sat {
virtual unsigned max_var(unsigned w) const = 0;
virtual bool extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& card,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) {
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) {
return false;
}
};

View file

@ -454,6 +454,8 @@ namespace sat {
void display_lookahead_scores(std::ostream& out);
stats const& stats() const { return m_stats; }
protected:
unsigned m_conflicts_since_init;

View file

@ -615,7 +615,7 @@ public:
private:
lbool internalize_goal(goal_ref& g, dep2asm_t& dep2asm, bool is_lemma) {
lbool internalize_goal(goal_ref& g, dep2asm_t& dep2asm) {
m_solver.pop_to_base_level();
if (m_solver.inconsistent())
return l_false;
@ -662,7 +662,7 @@ private:
// ensure that if goal is already internalized, then import mc from m_solver.
m_goal2sat(*g, m_params, m_solver, m_map, dep2asm, is_incremental(), is_lemma);
m_goal2sat(*g, m_params, m_solver, m_map, dep2asm, is_incremental());
m_goal2sat.get_interpreted_atoms(atoms);
if (!m_sat_mc) m_sat_mc = alloc(sat2goal::mc, m);
m_sat_mc->flush_smc(m_solver, m_map);
@ -690,7 +690,7 @@ private:
for (unsigned i = 0; i < get_num_assumptions(); ++i) {
g->assert_expr(get_assumption(i), m.mk_leaf(get_assumption(i)));
}
lbool res = internalize_goal(g, dep2asm, false);
lbool res = internalize_goal(g, dep2asm);
if (res == l_true) {
extract_assumptions(sz, asms, dep2asm);
}
@ -831,7 +831,7 @@ private:
expr* fml = m_fmls.get(i);
g->assert_expr(fml);
}
lbool res = internalize_goal(g, dep2asm, false);
lbool res = internalize_goal(g, dep2asm);
if (res != l_undef) {
m_fmls_head = m_fmls.size();
}

View file

@ -1,7 +1,12 @@
z3_add_component(sat_smt
SOURCES
atom2bool_var.cpp
sat_th.cpp
ba_solver.cpp
xor_solver.cpp
ba_internalize.cpp
euf_ackerman.cpp
euf_solver.cpp
euf_model.cpp
COMPONENT_DEPENDENCIES
sat
ast

View file

@ -7,7 +7,7 @@ Module Name:
Abstract:
INternalize methods for Boolean algebra operators.
Internalize methods for Boolean algebra operators.
Author:
@ -16,12 +16,11 @@ Author:
--*/
#include "sat/ba/ba_internalize.h"
#include "sat/smt/ba_internalize.h"
namespace sat {
literal ba_internalize::internalize(sat_internalizer& si, expr* e, bool sign, bool root) {
m_si = &si;
literal ba_internalize::internalize(expr* e, bool sign, bool root) {
if (pb.is_pb(e))
return internalize_pb(e, sign, root);
if (m.is_xor(e))
@ -35,7 +34,7 @@ namespace sat {
sat::bool_var v = m_solver.add_var(true);
lits.push_back(literal(v, true));
auto add_expr = [&](expr* a) {
literal lit = m_si->internalize(a);
literal lit = si.internalize(a);
m_solver.set_external(lit.var());
lits.push_back(lit);
};
@ -100,7 +99,7 @@ namespace sat {
void ba_internalize::convert_pb_args(app* t, literal_vector& lits) {
for (expr* arg : *t) {
lits.push_back(m_si->internalize(arg));
lits.push_back(si.internalize(arg));
m_solver.set_external(lits.back().var());
}
}
@ -192,10 +191,10 @@ namespace sat {
literal l1(v1, false), l2(v2, false);
bool_var v = m_solver.add_var(false);
literal l(v, false);
m_si->mk_clause(~l, l1);
m_si->mk_clause(~l, l2);
m_si->mk_clause(~l1, ~l2, l);
m_si->cache(t, l);
si.mk_clause(~l, l1);
si.mk_clause(~l, l2);
si.mk_clause(~l1, ~l2, l);
si.cache(t, l);
if (sign) l.neg();
return l;
}
@ -218,7 +217,7 @@ namespace sat {
bool_var v = m_solver.add_var(true);
literal lit(v, false);
ba.add_at_least(v, lits, k.get_unsigned());
m_si->cache(t, lit);
si.cache(t, lit);
if (sign) lit.neg();
TRACE("ba", tout << "root: " << root << " lit: " << lit << "\n";);
return lit;
@ -245,7 +244,7 @@ namespace sat {
bool_var v = m_solver.add_var(true);
literal lit(v, false);
ba.add_at_least(v, lits, k2);
m_si->cache(t, lit);
si.cache(t, lit);
if (sign) lit.neg();
return lit;
}
@ -267,10 +266,10 @@ namespace sat {
literal l1(v1, false), l2(v2, false);
bool_var v = m_solver.add_var(false);
literal l(v, false);
m_si->mk_clause(~l, l1);
m_si->mk_clause(~l, l2);
m_si->mk_clause(~l1, ~l2, l);
m_si->cache(t, l);
si.mk_clause(~l, l1);
si.mk_clause(~l, l2);
si.mk_clause(~l1, ~l2, l);
si.cache(t, l);
if (sign) l.neg();
return l;
}
@ -278,4 +277,63 @@ namespace sat {
return null_literal;
}
}
expr_ref ba_decompile::get_card(std::function<expr_ref(sat::literal)>& lit2expr, ba_solver::card const& c) {
ptr_buffer<expr> lits;
for (sat::literal l : c) {
lits.push_back(lit2expr(l));
}
expr_ref fml(pb.mk_at_least_k(c.size(), lits.c_ptr(), c.k()), m);
if (c.lit() != sat::null_literal) {
fml = m.mk_eq(lit2expr(c.lit()), fml);
}
return fml;
}
expr_ref ba_decompile::get_pb(std::function<expr_ref(sat::literal)>& lit2expr, ba_solver::pb const& p) {
ptr_buffer<expr> lits;
vector<rational> coeffs;
for (auto const& wl : p) {
lits.push_back(lit2expr(wl.second));
coeffs.push_back(rational(wl.first));
}
rational k(p.k());
expr_ref fml(pb.mk_ge(p.size(), coeffs.c_ptr(), lits.c_ptr(), k), m);
if (p.lit() != sat::null_literal) {
fml = m.mk_eq(lit2expr(p.lit()), fml);
}
return fml;
}
expr_ref ba_decompile::get_xor(std::function<expr_ref(sat::literal)>& lit2expr, ba_solver::xr const& x) {
ptr_buffer<expr> lits;
for (sat::literal l : x) {
lits.push_back(lit2expr(l));
}
expr_ref fml(m.mk_xor(x.size(), lits.c_ptr()), m);
if (x.lit() != sat::null_literal) {
fml = m.mk_eq(lit2expr(x.lit()), fml);
}
return fml;
}
bool ba_decompile::to_formulas(std::function<expr_ref(sat::literal)>& l2e, expr_ref_vector& fmls) {
for (auto* c : ba.constraints()) {
switch (c->tag()) {
case ba_solver::card_t:
fmls.push_back(get_card(l2e, c->to_card()));
break;
case sat::ba_solver::pb_t:
fmls.push_back(get_pb(l2e, c->to_pb()));
break;
case sat::ba_solver::xr_t:
fmls.push_back(get_xor(l2e, c->to_xr()));
break;
}
}
return true;
}
}

View file

@ -19,7 +19,7 @@ Author:
#pragma once
#include "sat/smt/sat_th.h"
#include "sat/ba/ba_solver.h"
#include "sat/smt/ba_solver.h"
#include "ast/pb_decl_plugin.h"
@ -31,7 +31,7 @@ namespace sat {
pb_util pb;
ba_solver& ba;
solver_core& m_solver;
sat_internalizer* m_si;
sat_internalizer& si;
literal convert_eq_k(app* t, rational const& k, bool root, bool sign);
literal convert_at_most_k(app* t, rational const& k, bool root, bool sign);
literal convert_at_least_k(app* t, rational const& k, bool root, bool sign);
@ -44,10 +44,30 @@ namespace sat {
void convert_pb_args(app* t, literal_vector& lits);
literal internalize_pb(expr* e, bool sign, bool root);
literal internalize_xor(expr* e, bool sign, bool root);
public:
ba_internalize(ba_solver& ba, solver_core& s, ast_manager& m) : m(m), pb(m), ba(ba), m_solver(s) {}
ba_internalize(ba_solver& ba, solver_core& s, sat_internalizer& si, ast_manager& m) :
m(m), pb(m), ba(ba), m_solver(s), si(si) {}
~ba_internalize() override {}
literal internalize(sat_internalizer& si, expr* e, bool sign, bool root) override;
literal internalize(expr* e, bool sign, bool root) override;
};
class ba_decompile : public sat::th_decompile {
ast_manager& m;
ba_solver& ba;
solver_core& m_solver;
pb_util pb;
expr_ref get_card(std::function<expr_ref(sat::literal)>& l2e, ba_solver::card const& c);
expr_ref get_pb(std::function<expr_ref(sat::literal)>& l2e, ba_solver::pb const& p);
expr_ref get_xor(std::function<expr_ref(sat::literal)>& l2e, ba_solver::xr const& x);
public:
ba_decompile(ba_solver& ba, solver_core& s, ast_manager& m) :
m(m), ba(ba), m_solver(s), pb(m) {}
~ba_decompile() override {}
bool to_formulas(std::function<expr_ref(sat::literal)>& l2e, expr_ref_vector& fmls) override;
};
}

View file

@ -7,7 +7,7 @@ Module Name:
Abstract:
Extension for cardinality and xr reasoning.
Extension for cardinality and xor reasoning.
Author:
@ -18,9 +18,9 @@ Revision History:
--*/
#include <cmath>
#include "sat/ba/ba_solver.h"
#include "sat/sat_types.h"
#include "util/mpz.h"
#include "sat/sat_types.h"
#include "sat/smt/ba_solver.h"
#include "sat/sat_simplifier_params.hpp"
#include "sat/sat_xor_finder.h"
@ -55,15 +55,6 @@ namespace sat {
return static_cast<pb_base const&>(*this);
}
ba_solver::xr& ba_solver::constraint::to_xr() {
SASSERT(is_xr());
return static_cast<xr&>(*this);
}
ba_solver::xr const& ba_solver::constraint::to_xr() const{
SASSERT(is_xr());
return static_cast<xr const&>(*this);
}
unsigned ba_solver::constraint::fold_max_var(unsigned w) const {
if (lit() != null_literal) w = std::max(w, lit().var());
@ -205,32 +196,7 @@ namespace sat {
}
// -----------------------------------
// xr
ba_solver::xr::xr(extension* e, unsigned id, literal_vector const& lits):
constraint(e, xr_t, id, null_literal, lits.size(), get_obj_size(lits.size())) {
for (unsigned i = 0; i < size(); ++i) {
m_lits[i] = lits[i];
}
}
bool ba_solver::xr::is_watching(literal l) const {
return
l == (*this)[0] || l == (*this)[1] ||
~l == (*this)[0] || ~l == (*this)[1];
}
bool ba_solver::xr::well_formed() const {
uint_set vars;
if (lit() != null_literal) vars.insert(lit().var());
for (literal l : *this) {
bool_var v = l.var();
if (vars.contains(v)) return false;
vars.insert(v);
}
return true;
}
// ----------------------------
// card
@ -908,107 +874,6 @@ namespace sat {
out << ">= " << p.k() << "\n";
}
// --------------------
// xr:
void ba_solver::clear_watch(xr& x) {
x.clear_watch();
unwatch_literal(x[0], x);
unwatch_literal(x[1], x);
unwatch_literal(~x[0], x);
unwatch_literal(~x[1], x);
}
bool ba_solver::parity(xr const& x, unsigned offset) const {
bool odd = false;
unsigned sz = x.size();
for (unsigned i = offset; i < sz; ++i) {
SASSERT(value(x[i]) != l_undef);
if (value(x[i]) == l_true) {
odd = !odd;
}
}
return odd;
}
bool ba_solver::init_watch(xr& x) {
clear_watch(x);
VERIFY(x.lit() == null_literal);
TRACE("ba", display(tout, x, true););
unsigned sz = x.size();
unsigned j = 0;
for (unsigned i = 0; i < sz && j < 2; ++i) {
if (value(x[i]) == l_undef) {
x.swap(i, j);
++j;
}
}
switch (j) {
case 0:
if (!parity(x, 0)) {
unsigned l = lvl(x[0]);
j = 1;
for (unsigned i = 1; i < sz; ++i) {
if (lvl(x[i]) > l) {
j = i;
l = lvl(x[i]);
}
}
set_conflict(x, x[j]);
}
return false;
case 1:
SASSERT(x.lit() == null_literal || value(x.lit()) == l_true);
assign(x, parity(x, 1) ? ~x[0] : x[0]);
return false;
default:
SASSERT(j == 2);
watch_literal(x[0], x);
watch_literal(x[1], x);
watch_literal(~x[0], x);
watch_literal(~x[1], x);
return true;
}
}
lbool ba_solver::add_assign(xr& x, literal alit) {
// literal is assigned
unsigned sz = x.size();
TRACE("ba", tout << "assign: " << ~alit << "@" << lvl(~alit) << " " << x << "\n"; display(tout, x, true); );
VERIFY(x.lit() == null_literal);
SASSERT(value(alit) != l_undef);
unsigned index = (x[1].var() == alit.var()) ? 1 : 0;
VERIFY(x[index].var() == alit.var());
// find a literal to swap with:
for (unsigned i = 2; i < sz; ++i) {
literal lit = x[i];
if (value(lit) == l_undef) {
x.swap(index, i);
unwatch_literal(~alit, x);
// alit gets unwatched by propagate_core because we return l_undef
watch_literal(lit, x);
watch_literal(~lit, x);
TRACE("ba", tout << "swap in: " << lit << " " << x << "\n";);
return l_undef;
}
}
if (index == 0) {
x.swap(0, 1);
}
// alit resides at index 1.
VERIFY(x[1].var() == alit.var());
if (value(x[0]) == l_undef) {
bool p = parity(x, 1);
assign(x, p ? ~x[0] : x[0]);
}
else if (!parity(x, 0)) {
set_conflict(x, ~x[1]);
}
return inconsistent() ? l_false : l_true;
}
// ---------------------------
// conflict resolution
@ -1977,116 +1842,7 @@ namespace sat {
add_pb_ge(lit, wlits, k, false);
}
void ba_solver::add_xr(literal_vector const& lits) {
add_xr(lits, false);
}
bool ba_solver::all_distinct(literal_vector const& lits) {
return s().all_distinct(lits);
}
bool ba_solver::all_distinct(clause const& c) {
return s().all_distinct(c);
}
bool ba_solver::all_distinct(xr const& x) {
init_visited();
for (literal l : x) {
if (is_visited(l.var())) {
return false;
}
mark_visited(l.var());
}
return true;
}
literal ba_solver::add_xor_def(literal_vector& lits, bool learned) {
unsigned sz = lits.size();
SASSERT (sz > 1);
VERIFY(all_distinct(lits));
init_visited();
bool parity1 = true;
for (literal l : lits) {
mark_visited(l.var());
parity1 ^= l.sign();
}
for (auto const & w : get_wlist(lits[0])) {
if (w.get_kind() != watched::EXT_CONSTRAINT) continue;
constraint& c = index2constraint(w.get_ext_constraint_idx());
if (!c.is_xr()) continue;
xr& x = c.to_xr();
if (sz + 1 != x.size()) continue;
bool is_match = true;
literal l0 = null_literal;
bool parity2 = true;
for (literal l : x) {
if (!is_visited(l.var())) {
if (l0 == null_literal) {
l0 = l;
}
else {
is_match = false;
break;
}
}
else {
parity2 ^= l.sign();
}
}
if (is_match) {
SASSERT(all_distinct(x));
if (parity1 == parity2) l0.neg();
if (!learned && x.learned()) {
set_non_learned(x);
}
return l0;
}
}
bool_var v = s().mk_var(true, true);
literal lit(v, false);
lits.push_back(~lit);
add_xr(lits, learned);
return lit;
}
ba_solver::constraint* ba_solver::add_xr(literal_vector const& _lits, bool learned) {
literal_vector lits;
u_map<bool> var2sign;
bool sign = false, odd = false;
for (literal lit : _lits) {
if (var2sign.find(lit.var(), sign)) {
var2sign.erase(lit.var());
odd ^= (sign ^ lit.sign());
}
else {
var2sign.insert(lit.var(), lit.sign());
}
}
for (auto const& kv : var2sign) {
lits.push_back(literal(kv.m_key, kv.m_value));
}
if (odd && !lits.empty()) {
lits[0].neg();
}
switch (lits.size()) {
case 0:
if (!odd)
s().set_conflict(justification(0));
return nullptr;
case 1:
s().assign_scoped(lits[0]);
return nullptr;
default:
break;
}
void * mem = m_allocator.allocate(xr::get_obj_size(lits.size()));
xr* x = new (mem) xr(this, next_id(), lits);
x->set_learned(learned);
add_constraint(x);
return x;
}
/*
\brief return true to keep watching literal.
@ -2178,89 +1934,6 @@ namespace sat {
m_parity_marks[v] = 0;
}
/**
\brief perform parity resolution on xr premises.
The idea is to collect premises based on xr resolvents.
Variables that are repeated an even number of times cancel out.
*/
void ba_solver::get_xr_antecedents(literal l, unsigned index, justification js, literal_vector& r) {
unsigned level = lvl(l);
bool_var v = l.var();
SASSERT(js.get_kind() == justification::EXT_JUSTIFICATION);
TRACE("ba", tout << l << ": " << js << "\n";
for (unsigned i = 0; i <= index; ++i) tout << s().m_trail[i] << " "; tout << "\n";
s().display_units(tout);
);
unsigned num_marks = 0;
while (true) {
TRACE("ba", tout << "process: " << l << " " << js << "\n";);
if (js.get_kind() == justification::EXT_JUSTIFICATION) {
constraint& c = index2constraint(js.get_ext_justification_idx());
TRACE("ba", tout << c << "\n";);
if (!c.is_xr()) {
r.push_back(l);
}
else {
xr& x = c.to_xr();
if (x[1].var() == l.var()) {
x.swap(0, 1);
}
VERIFY(x[0].var() == l.var());
for (unsigned i = 1; i < x.size(); ++i) {
literal lit(value(x[i]) == l_true ? x[i] : ~x[i]);
inc_parity(lit.var());
if (lvl(lit) == level) {
TRACE("ba", tout << "mark: " << lit << "\n";);
++num_marks;
}
else {
m_parity_trail.push_back(lit);
}
}
}
}
else {
r.push_back(l);
}
bool found = false;
while (num_marks > 0) {
l = s().m_trail[index];
v = l.var();
unsigned n = get_parity(v);
if (n > 0 && lvl(l) == level) {
reset_parity(v);
num_marks -= n;
if (n % 2 == 1) {
found = true;
break;
}
}
--index;
}
if (!found) {
break;
}
--index;
js = s().m_justification[v];
}
// now walk the defined literals
for (literal lit : m_parity_trail) {
if (get_parity(lit.var()) % 2 == 1) {
r.push_back(lit);
}
else {
// IF_VERBOSE(2, verbose_stream() << "skip even parity: " << lit << "\n";);
}
reset_parity(lit.var());
}
m_parity_trail.reset();
TRACE("ba", tout << r << "\n";);
}
/**
\brief retrieve a sufficient set of literals from p that imply l.
@ -2400,12 +2073,6 @@ namespace sat {
}
}
void ba_solver::simplify(xr& x) {
if (x.learned()) {
x.set_removed();
m_constraint_removed = true;
}
}
void ba_solver::get_antecedents(literal l, card const& c, literal_vector& r) {
if (l == ~c.lit()) {
@ -2431,24 +2098,6 @@ namespace sat {
}
}
void ba_solver::get_antecedents(literal l, xr const& x, literal_vector& r) {
if (x.lit() != null_literal) r.push_back(x.lit());
// TRACE("ba", display(tout << l << " ", x, true););
SASSERT(x.lit() == null_literal || value(x.lit()) == l_true);
SASSERT(x[0].var() == l.var() || x[1].var() == l.var());
if (x[0].var() == l.var()) {
SASSERT(value(x[1]) != l_undef);
r.push_back(value(x[1]) == l_true ? x[1] : ~x[1]);
}
else {
SASSERT(value(x[0]) != l_undef);
r.push_back(value(x[0]) == l_true ? x[0] : ~x[0]);
}
for (unsigned i = 2; i < x.size(); ++i) {
SASSERT(value(x[i]) != l_undef);
r.push_back(value(x[i]) == l_true ? x[i] : ~x[i]);
}
}
// ----------------------------
// constraint generic methods
@ -2617,31 +2266,6 @@ namespace sat {
return l_undef;
}
lbool ba_solver::eval(xr const& x) const {
bool odd = false;
for (auto l : x) {
switch (value(l)) {
case l_true: odd = !odd; break;
case l_false: break;
default: return l_undef;
}
}
return odd ? l_true : l_false;
}
lbool ba_solver::eval(model const& m, xr const& x) const {
bool odd = false;
for (auto l : x) {
switch (value(m, l)) {
case l_true: odd = !odd; break;
case l_false: break;
default: return l_undef;
}
}
return odd ? l_true : l_false;
}
bool ba_solver::validate() {
if (!validate_watch_literals()) {
@ -2940,52 +2564,9 @@ namespace sat {
}
}
void ba_solver::pre_simplify() {
VERIFY(s().at_base_lvl());
if (s().inconsistent())
return;
m_constraint_removed = false;
xor_finder xf(s());
for (unsigned sz = m_constraints.size(), i = 0; i < sz; ++i) pre_simplify(xf, *m_constraints[i]);
for (unsigned sz = m_learned.size(), i = 0; i < sz; ++i) pre_simplify(xf, *m_learned[i]);
bool change = m_constraint_removed;
cleanup_constraints();
if (change) {
// remove non-used variables.
init_use_lists();
remove_unused_defs();
set_non_external();
}
}
void ba_solver::pre_simplify(xor_finder& xf, constraint& c) {
if (c.is_xr() && c.size() <= xf.max_xor_size()) {
unsigned sz = c.size();
literal_vector lits;
bool parity = false;
xr const& x = c.to_xr();
for (literal lit : x) {
parity ^= lit.sign();
}
// IF_VERBOSE(0, verbose_stream() << "blast: " << c << "\n");
for (unsigned i = 0; i < (1ul << sz); ++i) {
if (xf.parity(sz, i) == parity) {
lits.reset();
for (unsigned j = 0; j < sz; ++j) {
lits.push_back(literal(x[j].var(), (0 != (i & (1 << j)))));
}
// IF_VERBOSE(0, verbose_stream() << lits << "\n");
s().mk_clause(lits);
}
}
c.set_removed();
m_constraint_removed = true;
}
}
void ba_solver::simplify() {
if (!s().at_base_lvl()) s().pop_to_base_level();
if (!s().at_base_lvl())
s().pop_to_base_level();
if (s().inconsistent())
return;
unsigned trail_sz, count = 0;
@ -3381,9 +2962,6 @@ namespace sat {
return false;
}
bool ba_solver::clausify(xr& x) {
return false;
}
bool ba_solver::clausify(card& c) {
return false;
@ -3771,82 +3349,6 @@ namespace sat {
}
}
// merge xors that contain cut variable
void ba_solver::merge_xor() {
unsigned sz = s().num_vars();
for (unsigned i = 0; i < sz; ++i) {
literal lit(i, false);
unsigned index = lit.index();
if (m_cnstr_use_list[index].size() == 2) {
constraint& c1 = *m_cnstr_use_list[index][0];
constraint& c2 = *m_cnstr_use_list[index][1];
if (c1.is_xr() && c2.is_xr() &&
m_clause_use_list.get(lit).empty() &&
m_clause_use_list.get(~lit).empty()) {
bool unique = true;
for (watched w : get_wlist(lit)) {
if (w.is_binary_clause()) unique = false;
}
for (watched w : get_wlist(~lit)) {
if (w.is_binary_clause()) unique = false;
}
if (!unique) continue;
xr const& x1 = c1.to_xr();
xr const& x2 = c2.to_xr();
literal_vector lits, dups;
bool parity = false;
init_visited();
for (literal l : x1) {
mark_visited(l.var());
lits.push_back(l);
}
for (literal l : x2) {
if (is_visited(l.var())) {
dups.push_back(l);
}
else {
lits.push_back(l);
}
}
init_visited();
for (literal l : dups) mark_visited(l);
unsigned j = 0;
for (unsigned i = 0; i < lits.size(); ++i) {
literal l = lits[i];
if (is_visited(l)) {
// skip
}
else if (is_visited(~l)) {
parity ^= true;
}
else {
lits[j++] = l;
}
}
lits.shrink(j);
if (!parity) lits[0].neg();
IF_VERBOSE(1, verbose_stream() << "binary " << lits << " : " << c1 << " " << c2 << "\n");
c1.set_removed();
c2.set_removed();
add_xr(lits, !c1.learned() && !c2.learned());
m_constraint_removed = true;
}
}
}
}
void ba_solver::extract_xor() {
xor_finder xf(s());
std::function<void (literal_vector const&)> f = [this](literal_vector const& l) { add_xr(l, false); };
xf.set(f);
clause_vector clauses(s().clauses());
xf(clauses);
for (clause* cp : xf.removed_clauses()) {
cp->set_removed(true);
m_clause_removed = true;
}
}
void ba_solver::init_visited() { s().init_visited(); }
void ba_solver::mark_visited(literal l) { s().mark_visited(l); }
void ba_solver::mark_visited(bool_var v) { s().mark_visited(v); }
@ -3915,6 +3417,7 @@ namespace sat {
cs.set_end(it2);
}
/*
\brief subsumption between two cardinality constraints
- A >= k subsumes A + B >= k' for k' <= k
@ -4380,23 +3883,6 @@ namespace sat {
out << ">= " << ineq.m_k << "\n";
}
void ba_solver::display(std::ostream& out, xr const& x, bool values) const {
out << "xr: ";
for (literal l : x) {
out << l;
if (values) {
out << "@(" << value(l);
if (value(l) != l_undef) {
out << ":" << lvl(l);
}
out << ") ";
}
else {
out << " ";
}
}
out << "\n";
}
void ba_solver::display_lit(std::ostream& out, literal lit, unsigned sz, bool values) const {
if (lit != null_literal) {
@ -4555,13 +4041,6 @@ namespace sat {
return false;
}
bool ba_solver::validate_unit_propagation(xr const& x, literal alit) const {
if (value(x.lit()) != l_true) return false;
for (unsigned i = 1; i < x.size(); ++i) {
if (value(x[i]) == l_undef) return false;
}
return true;
}
bool ba_solver::validate_lemma() {
int64_t bound64 = m_bound;

View file

@ -0,0 +1,211 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
euf_ackerman.cpp
Abstract:
Ackerman reduction plugin for EUF
Author:
Nikolaj Bjorner (nbjorner) 2020-08-28
--*/
#pragma once
#include "sat/smt/euf_solver.h"
#include "sat/smt/euf_ackerman.h"
namespace euf {
ackerman::ackerman(solver& s, ast_manager& m): s(s), m(m) {
new_tmp();
}
ackerman::~ackerman() {
reset();
dealloc(m_tmp_inference);
}
void ackerman::reset() {
for (inference* inf : m_table) {
m.dec_ref(inf->a);
m.dec_ref(inf->b);
m.dec_ref(inf->c);
}
m_table.reset();
m_queue = nullptr;
}
void ackerman::insert(expr* a, expr* b, expr* lca) {
if (a->get_id() > b->get_id())
std::swap(a, b);
inference& inf = *m_tmp_inference;
inf.a = a;
inf.b = b;
inf.c = lca;
inf.is_cc = false;
insert();
}
void ackerman::insert(app* a, app* b) {
if (a->get_id() > b->get_id())
std::swap(a, b);
inference& inf = *m_tmp_inference;
inf.a = a;
inf.b = b;
inf.c = nullptr;
inf.is_cc = true;
insert();
}
void ackerman::remove_from_queue(inference* inf) {
if (m_queue->m_next == m_queue) {
SASSERT(inf == m_queue);
m_queue = nullptr;
return;
}
if (m_queue == inf)
m_queue = inf->m_next;
auto* next = inf->m_next;
auto* prev = inf->m_prev;
prev->m_next = next;
next->m_prev = prev;
}
void ackerman::push_to_front(inference* inf) {
if (!m_queue) {
m_queue = inf;
}
else if (m_queue != inf) {
auto* next = inf->m_next;
auto* prev = inf->m_prev;
prev->m_next = next;
next->m_prev = prev;
inf->m_prev = m_queue->m_prev;
inf->m_next = m_queue;
m_queue->m_prev = inf;
}
}
void ackerman::insert() {
inference* inf = m_tmp_inference;
inference* other = m_table.insert_if_not_there(inf);
if (other == inf) {
m.inc_ref(inf->a);
m.inc_ref(inf->b);
m.inc_ref(inf->c);
}
else
new_tmp();
other->m_count++;
push_to_front(other);
}
void ackerman::remove(inference* inf) {
remove_from_queue(inf);
m_table.erase(inf);
m.dec_ref(inf->a);
m.dec_ref(inf->b);
m.dec_ref(inf->c);
dealloc(inf);
}
void ackerman::new_tmp() {
m_tmp_inference = alloc(inference);
m_tmp_inference->m_next = m_tmp_inference->m_prev = m_tmp_inference;
m_tmp_inference->m_count = 0;
}
void ackerman::cg_conflict_eh(expr * n1, expr * n2) {
if (s.m_config.m_dack != DACK_ROOT)
return;
if (!is_app(n1) || !is_app(n2))
return;
app* a = to_app(n1);
app* b = to_app(n2);
if (a->get_decl() != b->get_decl() || a->get_num_args() != b->get_num_args())
return;
insert(a, b);
gc();
}
void ackerman::used_eq_eh(expr* a, expr* b, expr* c) {
if (!s.m_config.m_dack_eq)
return;
if (a == b || a == c || b == c)
return;
insert(a, b, c);
gc();
}
void ackerman::used_cc_eh(app* a, app* b) {
if (s.m_config.m_dack != DACK_CR)
return;
SASSERT(a->get_decl() == b->get_decl());
SASSERT(a->get_num_args() == b->get_num_args());
insert(a, b);
gc();
}
void ackerman::gc() {
m_num_propagations_since_last_gc++;
if (m_num_propagations_since_last_gc <= s.m_config.m_dack_gc)
return;
m_num_propagations_since_last_gc = 0;
while (m_table.size() > m_gc_threshold)
remove(m_queue->m_prev);
m_gc_threshold *= 110;
m_gc_threshold /= 100;
m_gc_threshold++;
}
void ackerman::propagate() {
SASSERT(s.s().at_base_lvl());
auto* n = m_queue;
inference* k = nullptr;
unsigned num_prop = static_cast<unsigned>(s.s().stats().m_conflict * s.m_config.m_dack_factor);
num_prop = std::min(num_prop, m_table.size());
for (unsigned i = 0; i < num_prop; ++i, n = k) {
k = n->m_next;
if (n->m_count < s.m_config.m_dack_threshold)
continue;
if (n->is_cc)
add_cc(n->a, n->b);
else
add_eq(n->a, n->b, n->c);
remove(n);
}
}
void ackerman::add_cc(expr* _a, expr* _b) {
app* a = to_app(_a);
app* b = to_app(_b);
sat::literal_vector lits;
unsigned sz = a->get_num_args();
for (unsigned i = 0; i < sz; ++i) {
expr_ref eq(m.mk_eq(a->get_arg(i), b->get_arg(i)), m);
sat::literal lit = s.internalize(eq, true, false);
lits.push_back(~lit);
}
expr_ref eq(m.mk_eq(a, b), m);
lits.push_back(s.internalize(eq, false, false));
s.s().mk_clause(lits, true);
}
void ackerman::add_eq(expr* a, expr* b, expr* c) {
sat::literal lits[3];
expr_ref eq1(m.mk_eq(a, c), m);
expr_ref eq2(m.mk_eq(b, c), m);
expr_ref eq3(m.mk_eq(a, b), m);
lits[0] = s.internalize(eq1, true, false);
lits[1] = s.internalize(eq2, true, false);
lits[2] = s.internalize(eq3, false, false);
s.s().mk_clause(3, lits, true);
}
}

View file

@ -0,0 +1,89 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
euf_ackerman.h
Abstract:
Ackerman reduction plugin for EUF
Author:
Nikolaj Bjorner (nbjorner) 2020-08-25
--*/
#pragma once
#include "ast/euf/euf_egraph.h"
#include "sat/smt/atom2bool_var.h"
#include "sat/smt/sat_th.h"
namespace euf {
class solver;
class ackerman {
struct inference {
bool is_cc;
expr* a, *b, *c;
inference* m_next{ nullptr };
inference* m_prev{ nullptr };
unsigned m_count{ 0 };
inference():is_cc(false), a(nullptr), b(nullptr), c(nullptr) {}
inference(app* a, app* b):is_cc(true), a(a), b(b), c(nullptr) {}
inference(expr* a, expr* b, expr* c):is_cc(false), a(a), b(b), c(c) {}
};
struct inference_eq {
bool operator()(inference const* a, inference const* b) const {
return a->is_cc == b->is_cc && a->a == b->a && a->b == b->b && a->c == b->c;
}
};
struct inference_hash {
unsigned operator()(inference const* a) const {
SASSERT(a->a && a->b);
return mk_mix(a->a->get_id(), a->b->get_id(), a->c ? a->c->get_id() : 0);
}
};
typedef hashtable<inference*, inference_hash, inference_eq> table_t;
solver& s;
ast_manager& m;
table_t m_table;
inference* m_queue { nullptr };
inference* m_tmp_inference { nullptr };
unsigned m_gc_threshold { 1 };
unsigned m_propagate_threshold { 0 };
unsigned m_num_propagations_since_last_gc { 0 };
void reset();
void new_tmp();
void insert(expr* a, expr* b, expr* lca);
void insert(app* a, app* b);
void insert();
void remove(inference* inf);
void add_cc(expr* a, expr* b);
void add_eq(expr* a, expr* b, expr* c);
void gc();
void push_to_front(inference* inf);
void remove_from_queue(inference* inf);
public:
ackerman(solver& s, ast_manager& m);
~ackerman();
void cg_conflict_eh(expr * n1, expr * n2);
void used_eq_eh(expr* a, expr* b, expr* lca);
void used_cc_eh(app* a, app* b);
void propagate();
};
};

138
src/sat/smt/euf_model.cpp Normal file
View file

@ -0,0 +1,138 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
euf_model.cpp
Abstract:
Model building for EUF solver plugin.
Author:
Nikolaj Bjorner (nbjorner) 2020-08-25
--*/
#include "ast/ast_pp.h"
#include "sat/smt/euf_solver.h"
#include "model/value_factory.h"
namespace euf {
void solver::update_model(model_ref& mdl) {
deps_t deps;
expr_ref_vector values(m);
collect_dependencies(deps);
deps.topological_sort();
dependencies2values(deps, values, mdl);
values2model(deps, values, mdl);
}
sat::th_model_builder* solver::get_model_builder(expr* e) const {
if (is_app(e))
return get_model_builder(to_app(e)->get_decl());
return nullptr;
}
sat::th_model_builder* solver::get_model_builder(func_decl* f) const {
return m_id2model_builder.get(f->get_family_id(), nullptr);
}
bool solver::include_func_interp(func_decl* f) const {
if (f->get_family_id() == null_family_id)
return true;
sat::th_model_builder* mb = get_model_builder(f);
return mb && mb->include_func_interp(f);
}
void solver::collect_dependencies(deps_t& deps) {
for (enode* n : m_egraph.nodes()) {
if (n->num_args() == 0) {
deps.insert(n, nullptr);
continue;
}
auto* mb = get_model_builder(n->get_owner());
if (mb)
mb->add_dep(n, deps);
else
deps.insert(n, nullptr);
}
}
void solver::dependencies2values(deps_t& deps, expr_ref_vector& values, model_ref const& mdl) {
user_sort_factory user_sort(m);
for (enode* n : deps.top_sorted()) {
unsigned id = n->get_root_id();
if (values.get(id, nullptr))
continue;
expr* e = n->get_owner();
values.reserve(id + 1);
if (m.is_bool(e) && is_uninterp_const(e) && mdl->get_const_interp(to_app(e)->get_decl())) {
values.set(id, mdl->get_const_interp(to_app(e)->get_decl()));
continue;
}
// model of s() must have been fixed.
if (m.is_bool(e)) {
switch (s().value(m_expr2var.to_bool_var(e))) {
case l_true:
values.set(id, m.mk_true());
break;
case l_false:
values.set(id, m.mk_false());
break;
default:
break;
}
continue;
}
auto* mb = get_model_builder(e);
if (mb)
mb->add_value(n, values);
else if (m.is_uninterp(m.get_sort(e))) {
expr* v = user_sort.get_fresh_value(m.get_sort(e));
values.set(id, v);
}
else {
IF_VERBOSE(1, verbose_stream() << "no model values created for " << mk_pp(e, m) << "\n");
}
}
}
void solver::values2model(deps_t const& deps, expr_ref_vector const& values, model_ref& mdl) {
ptr_vector<expr> args;
for (enode* n : deps.top_sorted()) {
expr* e = n->get_owner();
if (!is_app(e))
continue;
app* a = to_app(e);
func_decl* f = a->get_decl();
if (!include_func_interp(f))
continue;
if (m.is_bool(e) && is_uninterp_const(e) && mdl->get_const_interp(f))
continue;
expr* v = values.get(n->get_root_id());
unsigned arity = f->get_arity();
if (arity == 0)
mdl->register_decl(f, v);
else {
auto* fi = mdl->get_func_interp(f);
if (!fi) {
fi = alloc(func_interp, m, arity);
mdl->register_decl(f, fi);
}
args.reset();
for (enode* arg : enode_args(n))
args.push_back(values.get(arg->get_root_id()));
if (!fi->get_entry(args.c_ptr()))
fi->insert_new_entry(args.c_ptr(), v);
}
}
}
void solver::register_macros(model& mdl) {
// TODO
}
}

View file

@ -16,15 +16,19 @@ Author:
--*/
#include "ast/pb_decl_plugin.h"
#include "sat/smt/sat_smt.h"
#include "sat/ba/ba_solver.h"
#include "sat/ba/ba_internalize.h"
#include "sat/euf/euf_solver.h"
#include "sat/sat_solver.h"
#include "tactic/tactic_exception.h"
#include "sat/sat_solver.h"
#include "sat/smt/sat_smt.h"
#include "sat/smt/ba_solver.h"
#include "sat/smt/ba_internalize.h"
#include "sat/smt/euf_solver.h"
namespace euf {
void solver::updt_params(params_ref const& p) {
m_config.updt_params(p);
}
/**
* retrieve extension that is associated with Boolean variable.
*/
@ -55,9 +59,10 @@ namespace euf {
auto* ba = alloc(sat::ba_solver);
ba->set_solver(m_solver);
add_extension(pb.get_family_id(), ba);
auto* bai = alloc(sat::ba_internalize, *ba, s(), m);
auto* bai = alloc(sat::ba_internalize, *ba, s(), si, m);
m_id2internalize.setx(pb.get_family_id(), bai, nullptr);
m_internalizers.push_back(bai);
m_decompilers.push_back(alloc(sat::ba_decompile, *ba, s(), m));
ba->push_scopes(s().num_scopes());
return ba;
}
@ -74,12 +79,12 @@ namespace euf {
void solver::get_antecedents(literal l, ext_justification_idx idx, literal_vector& r) {
auto* ext = sat::index_base::to_extension(idx);
if (ext == this)
get_antecedents(l, *euf_base::from_idx(idx), r);
get_antecedents(l, *constraint::from_idx(idx), r);
else
ext->get_antecedents(l, idx, r);
}
void solver::get_antecedents(literal l, euf_base& j, literal_vector& r) {
void solver::get_antecedents(literal l, constraint& j, literal_vector& r) {
m_explain.reset();
euf::enode* n = nullptr;
bool sign = false;
@ -90,6 +95,8 @@ namespace euf {
sign = l.sign() != p.second;
}
// init_ackerman();
switch (j.id()) {
case 0:
SASSERT(m_egraph.inconsistent());
@ -144,6 +151,9 @@ namespace euf {
}
for (euf::enode* eq : m_egraph.new_eqs()) {
bool_var v = m_expr2var.to_bool_var(eq->get_owner());
expr* a = nullptr, *b = nullptr;
if (s().value(v) == l_false && m_ackerman && m.is_eq(eq->get_owner(), a, b))
m_ackerman->cg_conflict_eh(a, b);
s().assign(literal(v, false), sat::justification::mk_ext_justification(s().scope_lvl(), m_eq_idx.to_index()));
}
for (euf::enode* p : m_egraph.new_lits()) {
@ -152,7 +162,10 @@ namespace euf {
SASSERT(m.is_bool(e));
SASSERT(m.is_true(p->get_root()->get_owner()) || sign);
bool_var v = m_expr2var.to_bool_var(e);
s().assign(literal(v, sign), sat::justification::mk_ext_justification(s().scope_lvl(), m_lit_idx.to_index()));
literal lit(v, sign);
if (s().value(lit) == l_false && m_ackerman)
m_ackerman->cg_conflict_eh(p->get_owner(), p->get_root()->get_owner());
s().assign(lit, sat::justification::mk_ext_justification(s().scope_lvl(), m_lit_idx.to_index()));
}
}
@ -204,6 +217,8 @@ namespace euf {
void solver::simplify() {
for (auto* e : m_extensions)
e->simplify();
if (m_ackerman)
m_ackerman->propagate();
}
void solver::clauses_modifed() {
@ -243,12 +258,14 @@ namespace euf {
m_egraph.collect_statistics(st);
for (auto* e : m_extensions)
e->collect_statistics(st);
st.update("euf dynack", m_stats.m_num_dynack);
}
solver* solver::copy_core() {
ast_manager& to = m_translate ? m_translate->to() : m;
atom2bool_var& a2b = m_translate_expr2var ? *m_translate_expr2var : m_expr2var;
auto* r = alloc(solver, to, a2b);
auto* r = alloc(solver, to, a2b, si);
r->m_config = m_config;
std::function<void*(void*)> copy_justification = [&](void* x) { return (void*)(r->base_ptr() + ((unsigned*)x - base_ptr())); };
r->m_egraph.copy_from(m_egraph, copy_justification);
return r;
@ -325,6 +342,23 @@ namespace euf {
return w;
}
void solver::init_ackerman() {
if (m_ackerman)
return;
if (m_config.m_dack == DACK_DISABLED)
return;
m_ackerman = alloc(ackerman, *this, m);
std::function<void(expr*,expr*,expr*)> used_eq = [&](expr* a, expr* b, expr* lca) {
m_ackerman->used_eq_eh(a, b, lca);
};
std::function<void(app*,app*)> used_cc = [&](app* a, app* b) {
m_ackerman->used_cc_eh(a, b);
};
m_egraph.set_used_eq(used_eq);
m_egraph.set_used_cc(used_cc);
}
sat::th_internalizer* solver::get_internalizer(expr* e) {
if (is_app(e))
return m_id2internalize.get(to_app(e)->get_family_id(), nullptr);
@ -334,25 +368,19 @@ namespace euf {
}
return nullptr;
}
sat::th_model_builder* solver::get_model_builder(expr* e) {
if (is_app(e))
return m_id2model_builder.get(to_app(e)->get_family_id(), nullptr);
return nullptr;
}
sat::literal solver::internalize(sat::sat_internalizer& si, expr* e, bool sign, bool root) {
sat::literal solver::internalize(expr* e, bool sign, bool root) {
auto* ext = get_internalizer(e);
if (ext)
return ext->internalize(si, e, sign, root);
return ext->internalize(e, sign, root);
if (!m_true) {
m_true = visit(si, m.mk_true());
m_false = visit(si, m.mk_false());
m_true = visit(m.mk_true());
m_false = visit(m.mk_false());
}
SASSERT(!si.is_bool_op(e));
sat::scoped_stack _sc(m_stack);
unsigned sz = m_stack.size();
euf::enode* n = visit(si, e);
euf::enode* n = visit(e);
while (m_stack.size() > sz) {
loop:
if (!m.inc())
@ -368,7 +396,7 @@ namespace euf {
while (fr.m_idx < num) {
expr* arg = to_app(e)->get_arg(fr.m_idx);
fr.m_idx++;
n = visit(si, arg);
n = visit(arg);
if (!n)
goto loop;
}
@ -376,13 +404,13 @@ namespace euf {
for (unsigned i = 0; i < num; ++i)
m_args.push_back(m_egraph.find(to_app(e)->get_arg(i)));
n = m_egraph.mk(e, num, m_args.c_ptr());
attach_bool_var(si, n);
attach_bool_var(n);
}
SASSERT(m_egraph.find(e));
return literal(m_expr2var.to_bool_var(e), sign);
}
euf::enode* solver::visit(sat::sat_internalizer& si, expr* e) {
euf::enode* solver::visit(expr* e) {
euf::enode* n = m_egraph.find(e);
if (n)
return n;
@ -399,11 +427,11 @@ namespace euf {
return nullptr;
}
n = m_egraph.mk(e, 0, nullptr);
attach_bool_var(si, n);
attach_bool_var(n);
return n;
}
void solver::attach_bool_var(sat::sat_internalizer& si, euf::enode* n) {
void solver::attach_bool_var(euf::enode* n) {
expr* e = n->get_owner();
if (m.is_bool(e)) {
sat::bool_var v = si.add_bool_var(e);
@ -420,6 +448,18 @@ namespace euf {
m_bool_var_trail.push_back(v);
}
bool solver::to_formulas(std::function<expr_ref(sat::literal)>& l2e, expr_ref_vector& fmls) {
for (auto* th : m_decompilers) {
if (!th->to_formulas(l2e, fmls))
return false;
}
for (euf::enode* n : m_egraph.nodes()) {
if (!n->is_root())
fmls.push_back(m.mk_eq(n->get_owner(), n->get_root()->get_owner()));
}
return true;
}
bool solver::extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& card,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) {
if (m_true)

View file

@ -17,12 +17,14 @@ Author:
#pragma once
#include "util/scoped_ptr_vector.h"
#include "sat/sat_extension.h"
#include "ast/euf/euf_egraph.h"
#include "ast/ast_translation.h"
#include "ast/euf/euf_egraph.h"
#include "smt/params/smt_params.h"
#include "tactic/model_converter.h"
#include "sat/sat_extension.h"
#include "sat/smt/atom2bool_var.h"
#include "sat/smt/sat_th.h"
#include "tactic/model_converter.h"
#include "sat/smt/euf_ackerman.h"
namespace euf {
typedef sat::literal literal;
@ -31,66 +33,89 @@ namespace euf {
typedef sat::literal_vector literal_vector;
typedef sat::bool_var bool_var;
class euf_base : public sat::index_base {
class constraint : public sat::index_base {
unsigned m_id;
public:
euf_base(sat::extension* e, unsigned id) :
constraint(sat::extension* e, unsigned id) :
index_base(e), m_id(id)
{}
unsigned id() const { return m_id; }
static euf_base* from_idx(size_t z) { return reinterpret_cast<euf_base*>(z); }
static constraint* from_idx(size_t z) { return reinterpret_cast<constraint*>(z); }
};
class solver : public sat::extension, public sat::th_internalizer {
ast_manager& m;
atom2bool_var& m_expr2var;
euf::egraph m_egraph;
sat::solver* m_solver;
sat::lookahead* m_lookahead;
ast_translation* m_translate;
atom2bool_var* m_translate_expr2var;
class solver : public sat::extension, public sat::th_internalizer, public sat::th_decompile {
typedef top_sort<euf::enode> deps_t;
friend class ackerman;
struct stats {
unsigned m_num_dynack;
stats() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); }
};
euf::enode* m_true;
euf::enode* m_false;
svector<euf::enode_bool_pair> m_var2node;
ptr_vector<unsigned> m_explain;
euf::enode_vector m_args;
svector<sat::frame> m_stack;
unsigned m_num_scopes { 0 };
unsigned_vector m_bool_var_trail;
unsigned_vector m_bool_var_lim;
scoped_ptr_vector<sat::extension> m_extensions;
ptr_vector<sat::extension> m_id2extension;
ptr_vector<sat::th_internalizer> m_id2internalize;
scoped_ptr_vector<sat::th_internalizer> m_internalizers;
scoped_ptr_vector<sat::th_model_builder> m_model_builders;
ptr_vector<sat::th_model_builder> m_id2model_builder;
euf_base m_conflict_idx, m_eq_idx, m_lit_idx;
ast_manager& m;
atom2bool_var& m_expr2var;
sat::sat_internalizer& si;
smt_params m_config;
euf::egraph m_egraph;
stats m_stats;
sat::solver* m_solver { nullptr };
sat::lookahead* m_lookahead { nullptr };
ast_translation* m_translate { nullptr };
atom2bool_var* m_translate_expr2var { nullptr };
scoped_ptr<ackerman> m_ackerman;
euf::enode* m_true { nullptr };
euf::enode* m_false { nullptr };
svector<euf::enode_bool_pair> m_var2node;
ptr_vector<unsigned> m_explain;
euf::enode_vector m_args;
svector<sat::frame> m_stack;
unsigned m_num_scopes { 0 };
unsigned_vector m_bool_var_trail;
unsigned_vector m_bool_var_lim;
scoped_ptr_vector<sat::extension> m_extensions;
ptr_vector<sat::extension> m_id2extension;
ptr_vector<sat::th_internalizer> m_id2internalize;
scoped_ptr_vector<sat::th_internalizer> m_internalizers;
scoped_ptr_vector<sat::th_model_builder> m_model_builders;
ptr_vector<sat::th_model_builder> m_id2model_builder;
scoped_ptr_vector<sat::th_decompile> m_decompilers;
constraint m_conflict_idx, m_eq_idx, m_lit_idx;
sat::solver& s() { return *m_solver; }
unsigned * base_ptr() { return reinterpret_cast<unsigned*>(this); }
euf::enode* visit(sat::sat_internalizer& si, expr* e);
void attach_bool_var(sat::sat_internalizer& si, euf::enode* n);
// internalization
sat::th_internalizer* get_internalizer(expr* e);
euf::enode* visit(expr* e);
void attach_bool_var(euf::enode* n);
void attach_bool_var(sat::bool_var v, bool sign, euf::enode* n);
solver* copy_core();
// extensions
sat::extension* get_extension(sat::bool_var v);
sat::extension* get_extension(expr* e);
void add_extension(family_id fid, sat::extension* e);
sat::th_internalizer* get_internalizer(expr* e);
void init_ackerman();
sat::th_model_builder* get_model_builder(expr* e);
// model building
bool include_func_interp(func_decl* f) const;
sat::th_model_builder* get_model_builder(expr* e) const;
sat::th_model_builder* get_model_builder(func_decl* f) const;
void register_macros(model& mdl);
void dependencies2values(deps_t& deps, expr_ref_vector& values, model_ref const& mdl);
void collect_dependencies(deps_t& deps);
void values2model(deps_t const& deps, expr_ref_vector const& values, model_ref& mdl);
// solving
void propagate();
void get_antecedents(literal l, euf_base& j, literal_vector& r);
void dependencies2values(sat::th_dependencies& deps, expr_ref_vector& values);
void collect_dependencies(sat::th_dependencies& deps);
void sort_dependencies(sat::th_dependencies& deps);
void get_antecedents(literal l, constraint& j, literal_vector& r);
public:
solver(ast_manager& m, atom2bool_var& expr2var):
solver(ast_manager& m, atom2bool_var& expr2var, sat::sat_internalizer& si, params_ref const& p = params_ref()):
m(m),
m_expr2var(expr2var),
si(si),
m_egraph(m),
m_solver(nullptr),
m_lookahead(nullptr),
@ -101,9 +126,13 @@ namespace euf {
m_conflict_idx(this, 0),
m_eq_idx(this, 1),
m_lit_idx(this, 2)
{}
{
updt_params(p);
}
~solver() override {}
void updt_params(params_ref const& p);
void set_solver(sat::solver* s) override { m_solver = s; }
void set_lookahead(sat::lookahead* s) override { m_lookahead = s; }
struct scoped_set_translate {
@ -143,11 +172,9 @@ namespace euf {
bool extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& card,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) override;
sat::literal internalize(sat::sat_internalizer& si, expr* e, bool sign, bool root) override;
model_converter* get_model();
bool to_formulas(std::function<expr_ref(sat::literal)>& l2e, expr_ref_vector& fmls);
sat::literal internalize(expr* e, bool sign, bool root) override;
void update_model(model_ref& mdl);
};
};

View file

@ -1,37 +0,0 @@
/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
sat_th.cpp
Abstract:
Theory plugins
Author:
Nikolaj Bjorner (nbjorner) 2020-08-25
--*/
#include "sat/smt/sat_th.h"
#include "util/top_sort.h"
namespace sat {
/*
* \brief add dependency: dst depends on src.
*/
void th_dependencies::add(euf::enode* src, euf::enode* dst) {
}
/*
* \brief sort dependencies.
*/
void th_dependencies::sort() {
top_sort<euf::enode> top;
}
}

View file

@ -16,33 +16,26 @@ Author:
--*/
#pragma once
#include "util/top_sort.h"
#include "sat/smt/sat_smt.h"
#include "ast/euf/euf_egraph.h"
namespace sat {
class th_dependencies {
public:
th_dependencies() {}
euf::enode * const* begin() const { return nullptr; }
euf::enode * const* end() const { return nullptr; }
/*
* \brief add dependency: dst depends on src.
*/
void add(euf::enode* src, euf::enode* dst);
/*
* \brief sort dependencies.
*/
void sort();
};
class th_internalizer {
public:
virtual literal internalize(sat_internalizer& si, expr* e, bool sign, bool root) = 0;
virtual ~th_internalizer() {}
virtual literal internalize(expr* e, bool sign, bool root) = 0;
};
class th_decompile {
public:
virtual ~th_decompile() {}
virtual bool to_formulas(std::function<expr_ref(sat::literal)>& lit2expr, expr_ref_vector& fmls) = 0;
};
class th_model_builder {
@ -59,7 +52,12 @@ namespace sat {
/**
\brief compute dependencies for node n
*/
virtual void add_dep(euf::enode* n, th_dependencies& dep) = 0;
virtual void add_dep(euf::enode* n, top_sort<euf::enode>& dep) = 0;
/**
\brief should function be included in model.
*/
virtual bool include_func_interp(func_decl* f) const { return false; }
};

View file

@ -7,8 +7,6 @@ z3_add_component(sat_tactic
tactic
solver
sat_smt
sat_ba
sat_euf
TACTIC_HEADERS
sat_tactic.h
)

View file

@ -35,9 +35,9 @@ Notes:
#include "ast/for_each_expr.h"
#include "sat/tactic/goal2sat.h"
#include "sat/sat_cut_simplifier.h"
#include "sat/ba/ba_internalize.h"
#include "sat/ba/ba_solver.h"
#include "sat/euf/euf_solver.h"
#include "sat/smt/ba_internalize.h"
#include "sat/smt/ba_solver.h"
#include "sat/smt/euf_solver.h"
#include "model/model_evaluator.h"
#include "model/model_v2_pp.h"
#include "tactic/tactic.h"
@ -71,7 +71,6 @@ struct goal2sat::imp : public sat::sat_internalizer {
bool m_default_external;
bool m_xor_solver;
bool m_euf;
bool m_is_lemma;
imp(ast_manager & _m, params_ref const & p, sat::solver_core & s, atom2bool_var & map, dep2asm_map& dep2asm, bool default_external):
@ -83,8 +82,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
m_dep2asm(dep2asm),
m_trail(m),
m_interpreted_atoms(m),
m_default_external(default_external),
m_is_lemma(false) {
m_default_external(default_external) {
updt_params(p);
m_true = sat::null_literal;
m_aig = s.get_cut_simplifier();
@ -107,21 +105,19 @@ struct goal2sat::imp : public sat::sat_internalizer {
m_solver.add_clause(1, &l, false);
}
void set_lemma_mode(bool f) { m_is_lemma = f; }
void mk_clause(sat::literal l1, sat::literal l2) override {
TRACE("goal2sat", tout << "mk_clause: " << l1 << " " << l2 << "\n";);
m_solver.add_clause(l1, l2, m_is_lemma);
m_solver.add_clause(l1, l2, false);
}
void mk_clause(sat::literal l1, sat::literal l2, sat::literal l3, bool is_lemma = false) override {
TRACE("goal2sat", tout << "mk_clause: " << l1 << " " << l2 << " " << l3 << "\n";);
m_solver.add_clause(l1, l2, l3, m_is_lemma || is_lemma);
m_solver.add_clause(l1, l2, l3, is_lemma);
}
void mk_clause(unsigned num, sat::literal * lits) {
TRACE("goal2sat", tout << "mk_clause: "; for (unsigned i = 0; i < num; i++) tout << lits[i] << " "; tout << "\n";);
m_solver.add_clause(num, lits, m_is_lemma);
m_solver.add_clause(num, lits, false);
}
sat::literal mk_true() {
@ -444,7 +440,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
sat::extension* ext = m_solver.get_extension();
euf::solver* euf = nullptr;
if (!ext) {
euf = alloc(euf::solver, m, m_map);
euf = alloc(euf::solver, m, m_map, *this);
m_solver.set_extension(euf);
for (unsigned i = m_solver.num_scopes(); i-- > 0; )
euf->push();
@ -454,7 +450,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
}
if (!euf)
throw default_exception("cannot convert to euf");
sat::literal lit = euf->internalize(*this, e, sign, root);
sat::literal lit = euf->internalize(e, sign, root);
if (root)
m_result_stack.reset();
if (lit == sat::null_literal)
@ -478,8 +474,8 @@ struct goal2sat::imp : public sat::sat_internalizer {
}
if (!ba)
throw default_exception("cannot convert to pb");
sat::ba_internalize internalize(*ba, m_solver, m);
sat::literal lit = internalize.internalize(*this, t, sign, root);
sat::ba_internalize internalize(*ba, m_solver, *this, m);
sat::literal lit = internalize.internalize(t, sign, root);
if (root)
m_result_stack.reset();
else
@ -735,7 +731,13 @@ bool goal2sat::has_unsupported_bool(goal const & g) {
return test<unsupported_bool_proc>(g);
}
goal2sat::goal2sat():m_imp(nullptr), m_interpreted_atoms(nullptr) {
goal2sat::goal2sat():
m_imp(nullptr),
m_interpreted_atoms(nullptr) {
}
goal2sat::~goal2sat() {
dealloc(m_imp);
}
void goal2sat::collect_param_descrs(param_descrs & r) {
@ -743,25 +745,18 @@ void goal2sat::collect_param_descrs(param_descrs & r) {
r.insert("ite_extra", CPK_BOOL, "(default: true) add redundant clauses (that improve unit propagation) when encoding if-then-else formulas");
}
struct goal2sat::scoped_set_imp {
goal2sat * m_owner;
scoped_set_imp(goal2sat * o, goal2sat::imp * i):m_owner(o) {
m_owner->m_imp = i;
}
~scoped_set_imp() {
m_owner->m_imp = nullptr;
}
};
void goal2sat::operator()(goal const & g, params_ref const & p, sat::solver_core & t, atom2bool_var & m, dep2asm_map& dep2asm, bool default_external, bool is_lemma) {
imp proc(g.m(), p, t, m, dep2asm, default_external);
scoped_set_imp set(this, &proc);
proc.set_lemma_mode(is_lemma);
proc(g);
dealloc(m_interpreted_atoms);
void goal2sat::operator()(goal const & g, params_ref const & p, sat::solver_core & t, atom2bool_var & m, dep2asm_map& dep2asm, bool default_external) {
if (!m_imp)
m_imp = alloc(imp, g.m(), p, t, m, dep2asm, default_external);
(*m_imp)(g);
m_interpreted_atoms = alloc(expr_ref_vector, g.m());
m_interpreted_atoms->append(proc.m_interpreted_atoms);
m_interpreted_atoms->append(m_imp->m_interpreted_atoms);
if (!t.get_extension()) {
dealloc(m_imp);
m_imp = nullptr;
}
}
void goal2sat::get_interpreted_atoms(expr_ref_vector& atoms) {
@ -948,50 +943,6 @@ struct sat2goal::imp {
return m_lit2expr.get(l.index());
}
void assert_pb(ref<mc>& mc, goal& r, sat::ba_solver::pb const& p) {
pb_util pb(m);
ptr_buffer<expr> lits;
vector<rational> coeffs;
for (auto const& wl : p) {
lits.push_back(lit2expr(mc, wl.second));
coeffs.push_back(rational(wl.first));
}
rational k(p.k());
expr_ref fml(pb.mk_ge(p.size(), coeffs.c_ptr(), lits.c_ptr(), k), m);
if (p.lit() != sat::null_literal) {
fml = m.mk_eq(lit2expr(mc, p.lit()), fml);
}
r.assert_expr(fml);
}
void assert_card(ref<mc>& mc, goal& r, sat::ba_solver::card const& c) {
pb_util pb(m);
ptr_buffer<expr> lits;
for (sat::literal l : c) {
lits.push_back(lit2expr(mc, l));
}
expr_ref fml(pb.mk_at_least_k(c.size(), lits.c_ptr(), c.k()), m);
if (c.lit() != sat::null_literal) {
fml = m.mk_eq(lit2expr(mc, c.lit()), fml);
}
r.assert_expr(fml);
}
void assert_xor(ref<mc>& mc, goal & r, sat::ba_solver::xr const& x) {
ptr_buffer<expr> lits;
for (sat::literal l : x) {
lits.push_back(lit2expr(mc, l));
}
expr_ref fml(m.mk_xor(x.size(), lits.c_ptr()), m);
if (x.lit() != sat::null_literal) {
fml = m.mk_eq(lit2expr(mc, x.lit()), fml);
}
r.assert_expr(fml);
}
void assert_clauses(ref<mc>& mc, sat::solver_core const & s, sat::clause_vector const& clauses, goal & r, bool asserted) {
ptr_buffer<expr> lits;
unsigned small_lbd = 3; // s.get_config().m_gc_small_lbd;
@ -1008,10 +959,6 @@ struct sat2goal::imp {
}
}
sat::ba_solver* get_ba_solver(sat::solver_core const& s) {
return dynamic_cast<sat::ba_solver*>(s.get_extension());
}
void operator()(sat::solver_core & s, atom2bool_var const & map, goal & r, ref<mc> & mc) {
if (s.at_base_lvl() && s.inconsistent()) {
r.assert_expr(m.mk_false());
@ -1039,21 +986,21 @@ struct sat2goal::imp {
// collect clauses
assert_clauses(mc, s, s.clauses(), r, true);
sat::ba_solver* ext = get_ba_solver(s);
auto* ext = s.get_extension();
if (ext) {
for (auto* c : ext->constraints()) {
switch (c->tag()) {
case sat::ba_solver::card_t:
assert_card(mc, r, c->to_card());
break;
case sat::ba_solver::pb_t:
assert_pb(mc, r, c->to_pb());
break;
case sat::ba_solver::xr_t:
assert_xor(mc, r, c->to_xr());
break;
}
std::function<expr_ref(sat::literal)> l2e = [&](sat::literal lit) {
return expr_ref(lit2expr(mc, lit), m);
};
expr_ref_vector fmls(m);
sat::ba_solver* ba = dynamic_cast<sat::ba_solver*>(ext);
if (ba) {
sat::ba_decompile decompile(*ba, s, m);
decompile.to_formulas(l2e, fmls);
}
else
dynamic_cast<euf::solver*>(ext)->to_formulas(l2e, fmls);
for (expr* f : fmls)
r.assert_expr(f);
}
}

View file

@ -38,12 +38,11 @@ Notes:
class goal2sat {
struct imp;
imp * m_imp;
struct scoped_set_imp;
expr_ref_vector* m_interpreted_atoms;
scoped_ptr<expr_ref_vector> m_interpreted_atoms;
public:
goal2sat();
~goal2sat() { dealloc(m_interpreted_atoms); }
~goal2sat();
typedef obj_map<expr, sat::literal> dep2asm_map;
@ -61,7 +60,7 @@ public:
\warning conversion throws a tactic_exception, if it is interrupted (by set_cancel),
an unsupported operator is found, or memory consumption limit is reached (set with param :max-memory).
*/
void operator()(goal const & g, params_ref const & p, sat::solver_core & t, atom2bool_var & m, dep2asm_map& dep2asm, bool default_external = false, bool is_lemma = false);
void operator()(goal const & g, params_ref const & p, sat::solver_core & t, atom2bool_var & m, dep2asm_map& dep2asm, bool default_external = false);
void get_interpreted_atoms(expr_ref_vector& atoms);

View file

@ -25,7 +25,6 @@ Revision History:
#include "sat/dimacs.h"
#include "sat/sat_params.hpp"
#include "sat/sat_solver.h"
#include "sat/ba/ba_solver.h"
#include "sat/tactic/goal2sat.h"
#include "ast/reg_decl_plugins.h"
#include "tactic/tactic.h"

View file

@ -11,8 +11,6 @@ z3_add_component(smt_params
theory_seq_params.cpp
theory_str_params.cpp
COMPONENT_DEPENDENCIES
ast
bit_blaster
pattern
PYG_FILES
smt_params_helper.pyg

View file

@ -18,7 +18,6 @@ Revision History:
--*/
#pragma once
#include "ast/ast.h"
#include "smt/params/dyn_ack_params.h"
#include "smt/params/qi_params.h"
#include "smt/params/theory_arith_params.h"

View file

@ -22,8 +22,8 @@ Revision History:
#include "smt/smt_quantifier_stat.h"
#include "smt/smt_checker.h"
#include "smt/smt_quantifier.h"
#include "smt/params/qi_params.h"
#include "smt/fingerprints.h"
#include "smt/params/qi_params.h"
#include "parsers/util/cost_parser.h"
#include "smt/cost_evaluator.h"
#include "smt/cached_var_subst.h"

View file

@ -18,11 +18,11 @@ Revision History:
#pragma once
#include "util/obj_hashtable.h"
#include "util/vector.h"
#include<algorithm>
#include<type_traits>
#include<memory.h>
#include "util/obj_hashtable.h"
#include "util/vector.h"
#include "util/memory_manager.h"
@ -52,12 +52,13 @@ class top_sort {
else {
m_dfs_num.insert(f, m_next_preorder++);
m_stack_S.push_back(f);
m_stack_P.push_back(f);
for (T* g : *m_deps[f]) {
traverse(g);
}
if (f == m_stack_P.back()) {
m_stack_P.push_back(f);
if (m_deps[f]) {
for (T* g : *m_deps[f]) {
traverse(g);
}
}
if (f == m_stack_P.back()) {
p_id = m_top_sorted.size();
T* s_f;
do {
@ -94,7 +95,16 @@ public:
m_deps.insert(t, s);
}
ptr_vector<T> const& top_sorted() { return m_top_sorted; }
void add(T* t, T* s) {
T_set* tb = nullptr;
if (!m_deps.find(t, tb)) {
tb = alloc(T_set);
insert(s, tb);
}
t->insert(s);
}
ptr_vector<T> const& top_sorted() const { return m_top_sorted; }
obj_map<T, unsigned> const& partition_ids() const { return m_partition_id; }