3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00
This commit is contained in:
Nikolaj Bjorner 2017-06-01 14:50:37 -07:00
commit 55ba1e9178
52 changed files with 877 additions and 311 deletions

View file

@ -349,10 +349,10 @@ extern "C" {
//
// ----------------------------
#if 0
void Z3_API Z3_del_model(Z3_context c, Z3_model m) {
Z3_model_dec_ref(c, m);
}
unsigned Z3_API Z3_get_model_num_constants(Z3_context c, Z3_model m) {
return Z3_model_get_num_consts(c, m);
}
@ -368,6 +368,7 @@ extern "C" {
Z3_func_decl Z3_API Z3_get_model_func_decl(Z3_context c, Z3_model m, unsigned i) {
return Z3_model_get_func_decl(c, m, i);
}
#endif
unsigned get_model_func_num_entries_core(Z3_context c, Z3_model m, unsigned i) {

View file

@ -477,4 +477,60 @@ extern "C" {
Z3_CATCH_RETURN(Z3_L_UNDEF);
}
Z3_ast Z3_API Z3_solver_lookahead(Z3_context c,
Z3_solver s,
Z3_ast_vector candidates) {
Z3_TRY;
LOG_Z3_solver_lookahead(c, s, candidates);
ast_manager& m = mk_c(c)->m();
expr_ref_vector _candidates(m);
ast_ref_vector const& __candidates = to_ast_vector_ref(candidates);
for (auto & e : __candidates) {
if (!is_expr(e)) {
SET_ERROR_CODE(Z3_INVALID_USAGE);
return 0;
}
_candidates.push_back(to_expr(e));
}
expr_ref result(m);
unsigned timeout = to_solver(s)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
unsigned rlimit = to_solver(s)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", false);
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
api::context::set_interruptable si(*(mk_c(c)), eh);
{
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
scoped_timer timer(timeout, &eh);
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
try {
result = to_solver_ref(s)->lookahead(_candidates);
}
catch (z3_exception & ex) {
mk_c(c)->handle_exception(ex);
return 0;
}
}
mk_c(c)->save_ast_trail(result);
RETURN_Z3(of_ast(result));
Z3_CATCH_RETURN(0);
}
Z3_ast_vector Z3_API Z3_solver_get_lemmas(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_lemmas(c, s);
RESET_ERROR_CODE();
ast_manager& m = mk_c(c)->m();
init_solver(c, s);
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
mk_c(c)->save_object(v);
expr_ref_vector lemmas(m);
to_solver_ref(s)->get_lemmas(lemmas);
for (expr* e : lemmas) {
v->m_ast_vector.push_back(e);
}
RETURN_Z3(of_ast_vector(v));
Z3_CATCH_RETURN(0);
}
};

View file

@ -252,6 +252,29 @@ namespace Microsoft.Z3
return lboolToStatus(r);
}
/// <summary>
/// Select a lookahead literal from the set of supplied candidates.
/// </summary>
public BoolExpr Lookahead(IEnumerable<BoolExpr> candidates)
{
ASTVector cands = new ASTVector(Context);
foreach (var c in candidates) cands.Push(c);
return (BoolExpr)Expr.Create(Context, Native.Z3_solver_lookahead(Context.nCtx, NativeObject, cands.NativeObject));
}
/// <summary>
/// Retrieve set of lemmas that have been inferred by solver.
/// </summary>
public BoolExpr[] Lemmas
{
get
{
var r = Native.Z3_solver_get_lemmas(Context.nCtx, NativeObject);
var v = new ASTVector(Context, r);
return v.ToBoolExprArray();
}
}
/// <summary>
/// The model of the last <c>Check</c>.
/// </summary>

View file

@ -6216,6 +6216,21 @@ class Solver(Z3PPObject):
consequences = [ consequences[i] for i in range(sz) ]
return CheckSatResult(r), consequences
def lemmas(self):
"""Extract auxiliary lemmas produced by solver"""
return AstVector(Z3_solver_get_lemmas(self.ctx.ref(), self.solver), self.ctx)
def lookahead(self, candidates = None):
"""Get lookahead literal"""
if candidates is None:
candidates = AstVector(None, self.ctx)
elif not isinstance(candidates, AstVector):
_cs = AstVector(None, self.ctx)
for c in candidates:
_asms.push(c)
candidates = _cs
return _to_expr_ref(Z3_solver_lookahead(self.ctx.ref(), self.solver, candidates), self.ctx)
def proof(self):
"""Return a proof for the last `check()`. Proof construction must be enabled."""
return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx)

View file

@ -6023,6 +6023,29 @@ extern "C" {
Z3_ast_vector assumptions,
Z3_ast_vector variables,
Z3_ast_vector consequences);
/**
\brief select a literal from the list of candidate propositional variables to split on.
If the candidate list is empty, then the solver chooses a formula based on its internal state.
def_API('Z3_solver_lookahead', AST, (_in(CONTEXT), _in(SOLVER), _in(AST_VECTOR)))
*/
Z3_ast Z3_API Z3_solver_lookahead(Z3_context c, Z3_solver s, Z3_ast_vector candidates);
/**
\brief retrieve lemmas from solver state. Lemmas are auxiliary unit literals,
binary clauses and other learned clauses that are below a minimal glue level.
Lemmas that have been retrieved in a previous call may be suppressed from subsequent
calls.
def_API('Z3_solver_get_lemmas', AST_VECTOR, (_in(CONTEXT), _in(SOLVER)))
*/
Z3_ast_vector Z3_API Z3_solver_get_lemmas(Z3_context c, Z3_solver s);
/**
\brief Retrieve the model for the last #Z3_solver_check or #Z3_solver_check_assumptions
@ -6031,6 +6054,7 @@ extern "C" {
def_API('Z3_solver_get_model', MODEL, (_in(CONTEXT), _in(SOLVER)))
*/
Z3_model Z3_API Z3_solver_get_model(Z3_context c, Z3_solver s);
/**

View file

@ -20,12 +20,12 @@ Revision History:
--*/
#include"var_subst.h"
#include"ast_ll_pp.h"
#include"ast_util.h"
#include"distribute_forall.h"
#include"bool_rewriter.h"
distribute_forall::distribute_forall(ast_manager & m, basic_simplifier_plugin & p) :
distribute_forall::distribute_forall(ast_manager & m) :
m_manager(m),
m_bsimp(p),
m_cache(m) {
}
@ -109,6 +109,8 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
expr * e = get_cached(q->get_expr());
if (m_manager.is_not(e) && m_manager.is_or(to_app(e)->get_arg(0))) {
bool_rewriter br(m_manager);
// found target for simplification
// (forall X (not (or F1 ... Fn)))
// -->
@ -121,8 +123,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
for (unsigned i = 0; i < num_args; i++) {
expr * arg = or_e->get_arg(i);
expr_ref not_arg(m_manager);
// m_bsimp.mk_not applies basic simplifications. For example, if arg is of the form (not a), then it will return a.
m_bsimp.mk_not(arg, not_arg);
br.mk_not(arg, not_arg);
quantifier_ref tmp_q(m_manager);
tmp_q = m_manager.update_quantifier(q, not_arg);
expr_ref new_q(m_manager);
@ -132,7 +133,7 @@ void distribute_forall::reduce1_quantifier(quantifier * q) {
expr_ref result(m_manager);
// m_bsimp.mk_and actually constructs a (not (or ...)) formula,
// it will also apply basic simplifications.
m_bsimp.mk_and(new_args.size(), new_args.c_ptr(), result);
br.mk_and(new_args.size(), new_args.c_ptr(), result);
cache_result(q, result);
}
else {

View file

@ -22,7 +22,6 @@ Revision History:
#define DISTRIBUTE_FORALL_H_
#include"ast.h"
#include"basic_simplifier_plugin.h"
#include"act_cache.h"
/**
@ -47,7 +46,6 @@ Revision History:
class distribute_forall {
typedef act_cache expr_map;
ast_manager & m_manager;
basic_simplifier_plugin & m_bsimp; // useful for constructing formulas and/or/not in simplified form.
ptr_vector<expr> m_todo;
expr_map m_cache;
ptr_vector<expr> m_new_args;
@ -57,7 +55,7 @@ class distribute_forall {
public:
distribute_forall(ast_manager & m, basic_simplifier_plugin & p);
distribute_forall(ast_manager & m);
/**
\brief Apply the distribute_forall transformation (when possible) to all universal quantifiers in \c f.

View file

@ -822,8 +822,7 @@ struct pb2bv_rewriter::imp {
p.get_bool("keep_cardinality_constraints", false) ||
p.get_bool("sat.cardinality.solver", false) ||
p.get_bool("cardinality.solver", false) ||
gparams::get_module("sat").get_bool("cardinality.solver", false) ||
keep_pb();
gparams::get_module("sat").get_bool("cardinality.solver", false);
}
bool keep_pb() const {

View file

@ -326,6 +326,7 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l):
m_numeral_as_real(false),
m_ignore_check(false),
m_exit_on_error(false),
m_processing_pareto(false),
m_manager(m),
m_own_manager(m == 0),
m_manager_initialized(false),
@ -1130,6 +1131,7 @@ void cmd_context::insert_aux_pdecl(pdecl * p) {
}
void cmd_context::reset(bool finalize) {
m_processing_pareto = false;
m_logic = symbol::null;
m_check_sat_result = 0;
m_numeral_as_real = false;
@ -1174,6 +1176,7 @@ void cmd_context::reset(bool finalize) {
}
void cmd_context::assert_expr(expr * t) {
m_processing_pareto = false;
if (!m_check_logic(t))
throw cmd_exception(m_check_logic.get_last_error());
m_check_sat_result = 0;
@ -1186,6 +1189,7 @@ void cmd_context::assert_expr(expr * t) {
}
void cmd_context::assert_expr(symbol const & name, expr * t) {
m_processing_pareto = false;
if (!m_check_logic(t))
throw cmd_exception(m_check_logic.get_last_error());
if (!produce_unsat_cores() || name == symbol::null) {
@ -1286,6 +1290,7 @@ static void restore(ast_manager & m, ptr_vector<expr> & c, unsigned old_sz) {
}
void cmd_context::restore_assertions(unsigned old_sz) {
m_processing_pareto = false;
if (!has_manager()) {
// restore_assertions invokes m(), so if cmd_context does not have a manager, it will try to create one.
SASSERT(old_sz == m_assertions.size());
@ -1303,6 +1308,7 @@ void cmd_context::restore_assertions(unsigned old_sz) {
void cmd_context::pop(unsigned n) {
m_check_sat_result = 0;
m_processing_pareto = false;
if (n == 0)
return;
unsigned lvl = m_scopes.size();
@ -1333,7 +1339,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
unsigned rlimit = m_params.m_rlimit;
scoped_watch sw(*this);
lbool r;
bool was_pareto = false, was_opt = false;
bool was_opt = false;
if (m_opt && !m_opt->empty()) {
was_opt = true;
@ -1342,21 +1348,15 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
scoped_ctrl_c ctrlc(eh);
scoped_timer timer(timeout, &eh);
scoped_rlimit _rlimit(m().limit(), rlimit);
ptr_vector<expr> cnstr(m_assertions);
cnstr.append(num_assumptions, assumptions);
get_opt()->set_hard_constraints(cnstr);
if (!m_processing_pareto) {
ptr_vector<expr> cnstr(m_assertions);
cnstr.append(num_assumptions, assumptions);
get_opt()->set_hard_constraints(cnstr);
}
try {
r = get_opt()->optimize();
while (r == l_true && get_opt()->is_pareto()) {
was_pareto = true;
get_opt()->display_assignment(regular_stream());
regular_stream() << "\n";
if (get_opt()->print_model()) {
model_ref mdl;
get_opt()->get_model(mdl);
display_model(mdl);
}
r = get_opt()->optimize();
if (r == l_true && get_opt()->is_pareto()) {
m_processing_pareto = true;
}
}
catch (z3_error & ex) {
@ -1366,8 +1366,8 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
get_opt()->display_assignment(regular_stream());
throw cmd_exception(ex.msg());
}
if (was_pareto && r == l_false) {
r = l_true;
if (m_processing_pareto && r != l_true) {
m_processing_pareto = false;
}
get_opt()->set_status(r);
}
@ -1400,7 +1400,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
validate_model();
}
validate_check_sat_result(r);
if (was_opt && r != l_false && !was_pareto) {
if (was_opt && r != l_false && !m_processing_pareto) {
get_opt()->display_assignment(regular_stream());
}

View file

@ -123,7 +123,6 @@ public:
virtual void display_assignment(std::ostream& out) = 0;
virtual bool is_pareto() = 0;
virtual void set_logic(symbol const& s) = 0;
virtual bool print_model() const = 0;
virtual void get_box_model(model_ref& mdl, unsigned index) = 0;
virtual void updt_params(params_ref const& p) = 0;
};
@ -161,6 +160,7 @@ protected:
status m_status;
bool m_numeral_as_real;
bool m_ignore_check; // used by the API to disable check-sat() commands when parsing SMT 2.0 files.
bool m_processing_pareto; // used when re-entering check-sat for pareto front.
bool m_exit_on_error;
static std::ostringstream g_error_stream;

View file

@ -50,7 +50,8 @@ void rule_properties::collect(rule_set const& rules) {
}
for (unsigned i = 0; m_inf_sort.empty() && i < r->get_decl()->get_arity(); ++i) {
sort* d = r->get_decl()->get_domain(i);
if (!m.is_bool(d) && !m_dl.is_finite_sort(d) && !m_bv.is_bv_sort(d)) {
sort_size sz = d->get_num_elements();
if (!sz.is_finite()) {
m_inf_sort.push_back(m_rule);
}
}

View file

@ -318,11 +318,6 @@ namespace opt {
return r;
}
bool context::print_model() const {
opt_params optp(m_params);
return optp.print_model();
}
void context::get_base_model(model_ref& mdl) {
mdl = m_model;
}

View file

@ -183,7 +183,6 @@ namespace opt {
virtual bool empty() { return m_scoped_state.m_objectives.empty(); }
virtual void set_hard_constraints(ptr_vector<expr> & hard);
virtual lbool optimize();
virtual bool print_model() const;
virtual void set_model(model_ref& _m) { m_model = _m; }
virtual void get_model(model_ref& _m);
virtual void get_box_model(model_ref& _m, unsigned index);

View file

@ -7,7 +7,6 @@ def_module_params('opt',
('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'),
('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'),
('rlimit', UINT, 0, 'resource limit (0 means no limit)'),
('print_model', BOOL, False, 'display model for satisfiable constraints'),
('enable_sls', BOOL, False, 'enable SLS tuning during weighted maxsast'),
('enable_sat', BOOL, True, 'enable the new SAT core for propositional constraints'),
('elim_01', BOOL, True, 'eliminate 01 variables'),

View file

@ -42,7 +42,8 @@ namespace sat {
stats() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); }
};
public:
class card {
unsigned m_index;
literal m_lit;
@ -105,6 +106,7 @@ namespace sat {
void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
void negate() { m_lits[0].neg(); }
};
protected:
struct ineq {
literal_vector m_lits;
@ -304,6 +306,13 @@ namespace sat {
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_xor(bool_var v, literal_vector const& lits);
unsigned num_pb() const { return m_pbs.size(); }
pb const& get_pb(unsigned i) const { return *m_pbs[i]; }
unsigned num_card() const { return m_cards.size(); }
card const& get_card(unsigned i) const { return *m_cards[i]; }
unsigned num_xor() const { return m_xors.size(); }
xor const& get_xor(unsigned i) const { return *m_xors[i]; }
virtual void propagate(literal l, ext_constraint_idx idx, bool & keep);
virtual bool resolve_conflict();
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r);

View file

@ -126,6 +126,27 @@ namespace sat {
m_drat_file = p.drat_file();
m_drat = (m_drat_check || m_drat_file != symbol("")) && p.threads() == 1;
m_dyn_sub_res = p.dyn_sub_res();
// Parameters used in Liang, Ganesh, Poupart, Czarnecki AAAI 2016.
m_branching_heuristic = BH_VSIDS;
if (p.branching_heuristic() == symbol("vsids")) {
m_branching_heuristic = BH_VSIDS;
}
else if (p.branching_heuristic() == symbol("chb")) {
m_branching_heuristic = BH_CHB;
}
else if (p.branching_heuristic() == symbol("lrb")) {
m_branching_heuristic = BH_LRB;
}
else {
throw sat_param_exception("invalid branching heuristic: accepted heuristics are 'vsids', 'lrb' or 'chb'");
}
m_anti_exploration = m_branching_heuristic != BH_VSIDS;
m_step_size_init = 0.40;
m_step_size_dec = 0.000001;
m_step_size_min = 0.06;
m_reward_multiplier = 0.9;
m_reward_offset = 1000000.0;
}
void config::collect_param_descrs(param_descrs & r) {

View file

@ -44,6 +44,12 @@ namespace sat {
GC_PSM_GLUE
};
enum branching_heuristic {
BH_VSIDS,
BH_CHB,
BH_LRB
};
struct config {
unsigned long long m_max_memory;
phase_selection m_phase;
@ -95,6 +101,14 @@ namespace sat {
symbol m_glue_psm;
symbol m_psm_glue;
// branching heuristic settings.
branching_heuristic m_branching_heuristic;
bool m_anti_exploration;
double m_step_size_init;
double m_step_size_dec;
double m_step_size_min;
double m_reward_multiplier;
double m_reward_offset;
config(params_ref const & p);
void updt_params(params_ref const & p);
static void collect_param_descrs(param_descrs & d);

View file

@ -46,7 +46,7 @@ namespace sat {
virtual std::ostream& display(std::ostream& out) const = 0;
virtual std::ostream& display_justification(std::ostream& out, ext_justification_idx idx) const = 0;
virtual void collect_statistics(statistics& st) const = 0;
virtual extension* copy(solver* s) = 0;
virtual extension* copy(solver* s) = 0;
virtual void find_mutexes(literal_vector& lits, vector<literal_vector> & mutexes) = 0;
};

View file

@ -384,6 +384,7 @@ namespace sat {
candidate(bool_var v, float r): m_var(v), m_rating(r) {}
};
svector<candidate> m_candidates;
uint_set m_select_lookahead_vars;
float get_rating(bool_var v) const { return m_rating[v]; }
float get_rating(literal l) const { return get_rating(l.var()); }
@ -468,7 +469,11 @@ namespace sat {
for (bool_var const* it = m_freevars.begin(), * end = m_freevars.end(); it != end; ++it) {
SASSERT(is_undef(*it));
bool_var x = *it;
if (newbies || active_prefix(x)) {
if (!m_select_lookahead_vars.empty() && m_select_lookahead_vars.contains(x)) {
m_candidates.push_back(candidate(x, m_rating[x]));
sum += m_rating[x];
}
else if (newbies || active_prefix(x)) {
m_candidates.push_back(candidate(x, m_rating[x]));
sum += m_rating[x];
}
@ -1857,6 +1862,31 @@ namespace sat {
return search();
}
literal select_lookahead(bool_var_vector const& vars) {
m_search_mode = lookahead_mode::searching;
scoped_level _sl(*this, c_fixed_truth);
init();
if (inconsistent()) return null_literal;
inc_istamp();
for (auto v : vars) {
m_select_lookahead_vars.insert(v);
}
literal l = choose();
m_select_lookahead_vars.reset();
if (inconsistent()) return null_literal;
// assign unit literals that were found during search for lookahead.
unsigned num_assigned = 0;
for (literal lit : m_trail) {
if (!m_s.was_eliminated(lit.var()) && m_s.value(lit) != l_true) {
m_s.assign(lit, justification());
++num_assigned;
}
}
IF_VERBOSE(1, verbose_stream() << "(sat-lookahead :units " << num_assigned << ")\n";);
return l;
}
/**
\brief simplify set of clauses by extracting units from a lookahead at base level.
*/

View file

@ -9,6 +9,7 @@ def_module_params('sat',
('restart.initial', UINT, 100, 'initial restart (number of conflicts)'),
('restart.max', UINT, UINT_MAX, 'maximal number of restarts.'),
('restart.factor', DOUBLE, 1.5, 'restart increment factor for geometric strategy'),
('branching.heuristic', SYMBOL, 'vsids', 'branching heuristic vsids, lrb or chb'),
('random_freq', DOUBLE, 0.01, 'frequency of random case splits'),
('random_seed', UINT, 0, 'random seed'),
('burst_search', UINT, 100, 'number of conflicts before first global simplification'),
@ -21,8 +22,7 @@ def_module_params('sat',
('minimize_lemmas', BOOL, True, 'minimize learned clauses'),
('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'),
('core.minimize', BOOL, False, 'minimize computed core'),
('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'),
('threads', UINT, 1, 'number of parallel threads to use'),
('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'), ('threads', UINT, 1, 'number of parallel threads to use'),
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'),
('drat.file', SYMBOL, '', 'file to dump DRAT proofs'),
('drat.check', BOOL, False, 'build up internal proof and check'),

View file

@ -175,6 +175,11 @@ namespace sat {
m_phase.push_back(PHASE_NOT_AVAILABLE);
m_prev_phase.push_back(PHASE_NOT_AVAILABLE);
m_assigned_since_gc.push_back(false);
m_last_conflict.push_back(0);
m_last_propagation.push_back(0);
m_participated.push_back(0);
m_canceled.push_back(0);
m_reasoned.push_back(0);
m_case_split_queue.mk_var_eh(v);
m_simplifier.insert_elim_todo(v);
SASSERT(!was_eliminated(v));
@ -581,6 +586,29 @@ namespace sat {
if (m_ext && m_external[v])
m_ext->asserted(l);
switch (m_config.m_branching_heuristic) {
case BH_VSIDS:
break;
case BH_CHB:
m_last_propagation[v] = m_stats.m_conflict;
break;
case BH_LRB:
m_participated[v] = 0;
m_reasoned[v] = 0;
break;
}
if (m_config.m_anti_exploration) {
uint64 age = m_stats.m_conflict - m_canceled[v];
if (age > 0) {
double decay = pow(0.95, age);
m_activity[v] = static_cast<unsigned>(m_activity[v] * decay);
// NB. MapleSAT does not update canceled.
m_canceled[v] = m_stats.m_conflict;
m_case_split_queue.activity_changed_eh(v, false);
}
}
SASSERT(!l.sign() || m_phase[v] == NEG_PHASE);
SASSERT(l.sign() || m_phase[v] == POS_PHASE);
@ -772,12 +800,26 @@ namespace sat {
}
bool solver::propagate(bool update) {
unsigned qhead = m_qhead;
bool r = propagate_core(update);
if (m_config.m_branching_heuristic == BH_CHB) {
update_chb_activity(r, qhead);
}
CASSERT("sat_propagate", check_invariant());
CASSERT("sat_missed_prop", check_missed_propagation());
return r;
}
literal solver::select_lookahead(bool_var_vector const& vars) {
lookahead lh(*this);
literal result = lh.select_lookahead(vars);
if (result == null_literal) {
set_conflict(justification());
}
// extract unit literals from lh
return result;
}
// -----------------------
//
// Search
@ -1065,6 +1107,18 @@ namespace sat {
}
while (!m_case_split_queue.empty()) {
if (m_config.m_anti_exploration) {
next = m_case_split_queue.min_var();
auto age = m_stats.m_conflict - m_canceled[next];
while (age > 0) {
double decay = pow(0.95, age);
m_activity[next] = static_cast<unsigned>(m_activity[next] * pow(0.95, age));
m_case_split_queue.activity_changed_eh(next, false);
m_canceled[next] = m_stats.m_conflict;
next = m_case_split_queue.min_var();
age = m_stats.m_conflict - m_canceled[next];
}
}
next = m_case_split_queue.next_var();
if (value(next) == l_undef && !was_eliminated(next))
return next;
@ -1829,6 +1883,9 @@ namespace sat {
m_conflicts_since_restart++;
m_conflicts_since_gc++;
m_stats.m_conflict++;
if (m_step_size > m_config.m_step_size_min) {
m_step_size -= m_config.m_step_size_dec;
}
m_conflict_lvl = get_max_lvl(m_not_l, m_conflict);
TRACE("sat", tout << "conflict detected at level " << m_conflict_lvl << " for ";
@ -2176,7 +2233,16 @@ namespace sat {
SASSERT(var < num_vars());
if (!is_marked(var) && var_lvl > 0) {
mark(var);
inc_activity(var);
switch (m_config.m_branching_heuristic) {
case BH_VSIDS:
inc_activity(var);
break;
case BH_CHB:
m_last_conflict[var] = m_stats.m_conflict;
break;
default:
break;
}
if (var_lvl == m_conflict_lvl)
num_marks++;
else
@ -2432,6 +2498,9 @@ namespace sat {
\brief Reset the mark of the variables in the current lemma.
*/
void solver::reset_lemma_var_marks() {
if (m_config.m_branching_heuristic == BH_LRB) {
update_lrb_reasoned();
}
literal_vector::iterator it = m_lemma.begin();
literal_vector::iterator end = m_lemma.end();
SASSERT(!is_marked((*it).var()));
@ -2442,6 +2511,58 @@ namespace sat {
}
}
void solver::update_lrb_reasoned() {
unsigned sz = m_lemma.size();
SASSERT(!is_marked(m_lemma[0].var()));
mark(m_lemma[0].var());
for (unsigned i = m_lemma.size(); i > 0; ) {
--i;
justification js = m_justification[m_lemma[i].var()];
switch (js.get_kind()) {
case justification::NONE:
break;
case justification::BINARY:
update_lrb_reasoned(js.get_literal());
break;
case justification::TERNARY:
update_lrb_reasoned(js.get_literal1());
update_lrb_reasoned(js.get_literal2());
break;
case justification::CLAUSE: {
clause & c = *(m_cls_allocator.get_clause(js.get_clause_offset()));
for (unsigned i = 0; i < c.size(); ++i) {
update_lrb_reasoned(c[i]);
}
break;
}
case justification::EXT_JUSTIFICATION: {
fill_ext_antecedents(m_lemma[i], js);
literal_vector::iterator it = m_ext_antecedents.begin();
literal_vector::iterator end = m_ext_antecedents.end();
for (; it != end; ++it) {
update_lrb_reasoned(*it);
}
break;
}
}
}
reset_mark(m_lemma[0].var());
for (unsigned i = m_lemma.size(); i > sz; ) {
--i;
reset_mark(m_lemma[i].var());
}
m_lemma.shrink(sz);
}
void solver::update_lrb_reasoned(literal lit) {
bool_var v = lit.var();
if (!is_marked(v)) {
mark(v);
m_reasoned[v]++;
m_lemma.push_back(lit);
}
}
/**
\brief Apply dynamic subsumption resolution to new lemma.
Only binary and ternary clauses are used.
@ -2618,6 +2739,18 @@ namespace sat {
bool_var v = l.var();
SASSERT(value(v) == l_undef);
m_case_split_queue.unassign_var_eh(v);
if (m_config.m_branching_heuristic == BH_LRB) {
uint64 interval = m_stats.m_conflict - m_last_propagation[v];
if (interval > 0) {
auto activity = m_activity[v];
auto reward = (m_config.m_reward_offset * (m_participated[v] + m_reasoned[v])) / interval;
m_activity[v] = static_cast<unsigned>(m_step_size * reward + ((1 - m_step_size) * activity));
m_case_split_queue.activity_changed_eh(v, m_activity[v] > activity);
}
}
if (m_config.m_anti_exploration) {
m_canceled[v] = m_stats.m_conflict;
}
}
m_trail.shrink(old_sz);
m_qhead = old_sz;
@ -2800,6 +2933,8 @@ namespace sat {
m_probing.updt_params(p);
m_scc.updt_params(p);
m_rand.set_seed(m_config.m_random_seed);
m_step_size = m_config.m_step_size_init;
}
void solver::collect_param_descrs(param_descrs & d) {
@ -2837,6 +2972,7 @@ namespace sat {
// -----------------------
void solver::rescale_activity() {
SASSERT(m_config.m_branching_heuristic == BH_VSIDS);
svector<unsigned>::iterator it = m_activity.begin();
svector<unsigned>::iterator end = m_activity.end();
for (; it != end; ++it) {
@ -2845,6 +2981,18 @@ namespace sat {
m_activity_inc >>= 14;
}
void solver::update_chb_activity(bool is_sat, unsigned qhead) {
SASSERT(m_config.m_branching_heuristic == BH_CHB);
double multiplier = m_config.m_reward_offset * (is_sat ? m_config.m_reward_multiplier : 1.0);
for (unsigned i = qhead; i < m_trail.size(); ++i) {
auto v = m_trail[i].var();
auto reward = multiplier / (m_stats.m_conflict - m_last_conflict[v] + 1);
auto activity = m_activity[v];
m_activity[v] = static_cast<unsigned>(m_step_size * reward + ((1.0 - m_step_size) * activity));
m_case_split_queue.activity_changed_eh(v, m_activity[v] > activity);
}
}
// -----------------------
//
// Iterators

View file

@ -110,8 +110,17 @@ namespace sat {
svector<char> m_eliminated;
svector<char> m_external;
svector<unsigned> m_level;
// branch variable selection:
svector<unsigned> m_activity;
unsigned m_activity_inc;
svector<uint64> m_last_conflict;
svector<uint64> m_last_propagation;
svector<uint64> m_participated;
svector<uint64> m_canceled;
svector<uint64> m_reasoned;
int m_action;
double m_step_size;
// phase
svector<char> m_phase;
svector<char> m_prev_phase;
svector<char> m_assigned_since_gc;
@ -300,7 +309,7 @@ namespace sat {
}
void set_par(parallel* p, unsigned id);
bool canceled() { return !m_rlimit.inc(); }
config const& get_config() { return m_config; }
config const& get_config() const { return m_config; }
extension* get_extension() const { return m_ext.get(); }
void set_extension(extension* e);
typedef std::pair<literal, literal> bin_clause;
@ -343,6 +352,8 @@ namespace sat {
model_converter const & get_model_converter() const { return m_mc; }
void set_model(model const& mdl);
literal select_lookahead(bool_var_vector const& vars);
protected:
unsigned m_conflicts;
unsigned m_restarts;
@ -555,6 +566,12 @@ namespace sat {
private:
void rescale_activity();
void update_chb_activity(bool is_sat, unsigned qhead);
void update_lrb_reasoned();
void update_lrb_reasoned(literal lit);
// -----------------------
//
// Iterators

View file

@ -66,7 +66,11 @@ class inc_sat_solver : public solver {
expr_dependency_ref m_dep_core;
svector<double> m_weights;
std::string m_unknown;
// access formulas after they have been pre-processed and handled by the sat solver.
// this allows to access the internal state of the SAT solver and carry on partial results.
bool m_internalized; // are formulas internalized?
bool m_internalized_converted; // have internalized formulas been converted back
expr_ref_vector m_internalized_fmls; // formulas in internalized format
typedef obj_map<expr, sat::literal> dep2asm_t;
public:
@ -81,7 +85,10 @@ public:
m_map(m),
m_num_scopes(0),
m_dep_core(m),
m_unknown("no reason given") {
m_unknown("no reason given"),
m_internalized(false),
m_internalized_converted(false),
m_internalized_fmls(m) {
updt_params(p);
init_preprocess();
}
@ -141,6 +148,8 @@ public:
if (r != l_true) return r;
r = internalize_assumptions(sz, assumptions, dep2asm);
if (r != l_true) return r;
m_internalized = true;
m_internalized_converted = false;
r = m_solver.check(m_asms.size(), m_asms.c_ptr());
@ -170,8 +179,11 @@ public:
m_fmls_head_lim.push_back(m_fmls_head);
if (m_bb_rewriter) m_bb_rewriter->push();
m_map.push();
m_internalized = true;
m_internalized_converted = false;
}
virtual void pop(unsigned n) {
m_internalized = false;
if (n > m_num_scopes) { // allow inc_sat_solver to
n = m_num_scopes; // take over for another solver.
}
@ -204,6 +216,7 @@ public:
}
virtual ast_manager& get_manager() const { return m; }
virtual void assert_expr(expr * t) {
m_internalized = false;
TRACE("goal2sat", tout << mk_pp(t, m) << "\n";);
m_fmls.push_back(t);
}
@ -242,6 +255,28 @@ public:
return 0;
}
virtual expr_ref lookahead(expr_ref_vector const& candidates) {
sat::bool_var_vector vars;
u_map<expr*> var2candidate;
for (auto c : candidates) {
// TBD: check membership
sat::bool_var v = m_map.to_bool_var(c);
SASSERT(v != sat::null_bool_var);
vars.push_back(v);
var2candidate.insert(v, c);
}
sat::literal l = m_solver.select_lookahead(vars);
if (l == sat::null_literal) {
return expr_ref(m.mk_true(), m);
}
expr* e;
if (!var2candidate.find(l.var(), e)) {
// TBD: if candidate set is empty, then do something else.
e = m.mk_true();
}
return expr_ref(l.sign() ? m.mk_not(e) : e, m);
}
virtual lbool get_consequences_core(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq) {
init_preprocess();
TRACE("sat", tout << assumptions << "\n" << vars << "\n";);
@ -320,9 +355,18 @@ public:
virtual void get_labels(svector<symbol> & r) {
}
virtual unsigned get_num_assertions() const {
return m_fmls.size();
const_cast<inc_sat_solver*>(this)->convert_internalized();
if (m_internalized && m_internalized_converted) {
return m_internalized_fmls.size();
}
else {
return m_fmls.size();
}
}
virtual expr * get_assertion(unsigned idx) const {
if (m_internalized && m_internalized_converted) {
return m_internalized_fmls[idx];
}
return m_fmls[idx];
}
virtual unsigned get_num_assumptions() const {
@ -332,6 +376,32 @@ public:
return m_asmsf[idx];
}
void convert_internalized() {
if (!m_internalized) return;
sat2goal s2g;
model_converter_ref mc;
goal g(m, false, false, false);
s2g(m_solver, m_map, m_params, g, mc);
extract_model();
if (!m_model) {
m_model = alloc(model, m);
}
model_ref mdl = m_model;
if (m_mc) (*m_mc)(mdl);
for (unsigned i = 0; i < mdl->get_num_constants(); ++i) {
func_decl* c = mdl->get_constant(i);
expr_ref eq(m.mk_eq(m.mk_const(c), mdl->get_const_interp(c)), m);
g.assert_expr(eq);
}
m_internalized_fmls.reset();
g.get_formulas(m_internalized_fmls);
// g.display(std::cout);
m_internalized_converted = true;
// if (mc) mc->display(std::cout << "mc");
// if (m_mc) m_mc->display(std::cout << "m_mc\n");
// if (m_mc0) m_mc0->display(std::cout << "m_mc0\n");
}
void init_preprocess() {
if (m_preprocess) {
m_preprocess->reset();
@ -374,7 +444,7 @@ private:
init_preprocess();
SASSERT(g->models_enabled());
SASSERT(!g->proofs_enabled());
TRACE("goal2sat", g->display(tout););
TRACE("sat", g->display(tout););
try {
(*m_preprocess)(g, m_subgoals, m_mc, m_pc, m_dep_core);
}
@ -391,7 +461,7 @@ private:
}
g = m_subgoals[0];
expr_ref_vector atoms(m);
TRACE("goal2sat", g->display_with_dependencies(tout););
TRACE("sat", g->display_with_dependencies(tout););
m_goal2sat(*g, m_params, m_solver, m_map, dep2asm, true);
m_goal2sat.get_interpreted_atoms(atoms);
if (!atoms.empty()) {

View file

@ -39,6 +39,15 @@ namespace sat {
m_queue.decreased(v);
}
void activity_changed_eh(bool_var v, bool up) {
if (m_queue.contains(v)) {
if (up)
m_queue.decreased(v);
else
m_queue.increased(v);
}
}
void mk_var_eh(bool_var v) {
m_queue.reserve(v+1);
m_queue.insert(v);
@ -61,6 +70,8 @@ namespace sat {
bool empty() const { return m_queue.empty(); }
bool_var next_var() { SASSERT(!empty()); return m_queue.erase_min(); }
bool_var min_var() { SASSERT(!empty()); return m_queue.min_value(); }
};
};

View file

@ -137,7 +137,7 @@ struct goal2sat::imp {
sat::bool_var v = m_solver.mk_var(ext);
m_map.insert(t, v);
l = sat::literal(v, sign);
TRACE("goal2sat", tout << "new_var: " << v << "\n" << mk_ismt2_pp(t, m) << "\n";);
TRACE("sat", tout << "new_var: " << v << ": " << mk_ismt2_pp(t, m) << "\n";);
if (ext && !is_uninterp_const(t)) {
m_interpreted_atoms.push_back(t);
}
@ -993,6 +993,7 @@ struct sat2goal::imp {
expr_ref_vector m_lit2expr;
unsigned long long m_max_memory;
bool m_learned;
unsigned m_glue;
imp(ast_manager & _m, params_ref const & p):m(_m), m_lit2expr(m) {
updt_params(p);
@ -1000,6 +1001,7 @@ struct sat2goal::imp {
void updt_params(params_ref const & p) {
m_learned = p.get_bool("learned", false);
m_glue = p.get_uint("glue", UINT_MAX);
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
}
@ -1042,20 +1044,71 @@ struct sat2goal::imp {
return m_lit2expr.get(l.index());
}
void assert_clauses(sat::clause * const * begin, sat::clause * const * end, goal & r) {
void assert_pb(goal& r, sat::card_extension::pb const& p) {
pb_util pb(m);
ptr_buffer<expr> lits;
vector<rational> coeffs;
for (unsigned i = 0; i < p.size(); ++i) {
lits.push_back(lit2expr(p[i].second));
coeffs.push_back(rational(p[i].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);
}
r.assert_expr(fml);
}
void assert_card(goal& r, sat::card_extension::card const& c) {
pb_util pb(m);
ptr_buffer<expr> lits;
for (unsigned i = 0; i < c.size(); ++i) {
lits.push_back(lit2expr(c[i]));
}
expr_ref fml(pb.mk_at_most_k(c.size(), lits.c_ptr(), c.k()), m);
if (c.lit() != sat::null_literal) {
fml = m.mk_eq(lit2expr(c.lit()), fml);
}
r.assert_expr(fml);
}
void assert_xor(goal & r, sat::card_extension::xor const& x) {
ptr_buffer<expr> lits;
for (unsigned i = 0; i < x.size(); ++i) {
lits.push_back(lit2expr(x[i]));
}
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);
}
r.assert_expr(fml);
}
void assert_clauses(sat::solver const & s, sat::clause * const * begin, sat::clause * const * end, goal & r, bool asserted) {
ptr_buffer<expr> lits;
for (sat::clause * const * it = begin; it != end; it++) {
checkpoint();
lits.reset();
sat::clause const & c = *(*it);
unsigned sz = c.size();
for (unsigned i = 0; i < sz; i++) {
lits.push_back(lit2expr(c[i]));
if (asserted || m_learned || c.glue() <= s.get_config().m_gc_small_lbd) {
for (unsigned i = 0; i < sz; i++) {
lits.push_back(lit2expr(c[i]));
}
r.assert_expr(m.mk_or(lits.size(), lits.c_ptr()));
}
r.assert_expr(m.mk_or(lits.size(), lits.c_ptr()));
}
}
sat::card_extension* get_card_extension(sat::solver const& s) {
sat::extension* ext = s.get_extension();
return dynamic_cast<sat::card_extension*>(ext);
}
void operator()(sat::solver const & s, atom2bool_var const & map, goal & r, model_converter_ref & mc) {
if (s.inconsistent()) {
r.assert_expr(m.mk_false());
@ -1087,9 +1140,22 @@ struct sat2goal::imp {
r.assert_expr(m.mk_or(lit2expr(it->first), lit2expr(it->second)));
}
// collect clauses
assert_clauses(s.begin_clauses(), s.end_clauses(), r);
if (m_learned)
assert_clauses(s.begin_learned(), s.end_learned(), r);
assert_clauses(s, s.begin_clauses(), s.end_clauses(), r, true);
assert_clauses(s, s.begin_learned(), s.end_learned(), r, false);
// TBD: collect assertions from plugin
sat::card_extension* ext = get_card_extension(s);
if (ext) {
for (unsigned i = 0; i < ext->num_pb(); ++i) {
assert_pb(r, ext->get_pb(i));
}
for (unsigned i = 0; i < ext->num_card(); ++i) {
assert_card(r, ext->get_card(i));
}
for (unsigned i = 0; i < ext->num_xor(); ++i) {
assert_xor(r, ext->get_xor(i));
}
}
}
};
@ -1100,6 +1166,7 @@ sat2goal::sat2goal():m_imp(0) {
void sat2goal::collect_param_descrs(param_descrs & r) {
insert_max_memory(r);
r.insert("learned", CPK_BOOL, "(default: false) collect also learned clauses.");
r.insert("glue", CPK_UINT, "(default: max-int) collect learned clauses with glue level below parameter.");
}
struct sat2goal::scoped_set_imp {

View file

@ -43,7 +43,7 @@ Revision History:
#include"quasi_macros.h"
asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p):
m_manager(m),
m(m),
m_params(p),
m_pre_simplifier(m),
m_simplifier(m),
@ -63,7 +63,7 @@ asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p):
setup_simplifier_plugins(m_simplifier, m_bsimp, arith_simp, m_bvsimp);
SASSERT(m_bsimp != 0);
SASSERT(arith_simp != 0);
m_macro_finder = alloc(macro_finder, m_manager, m_macro_manager);
m_macro_finder = alloc(macro_finder, m, m_macro_manager);
basic_simplifier_plugin * basic_simp = 0;
bv_simplifier_plugin * bv_simp = 0;
@ -90,16 +90,16 @@ void asserted_formulas::setup() {
}
void asserted_formulas::setup_simplifier_plugins(simplifier & s, basic_simplifier_plugin * & bsimp, arith_simplifier_plugin * & asimp, bv_simplifier_plugin * & bvsimp) {
bsimp = alloc(basic_simplifier_plugin, m_manager);
bsimp = alloc(basic_simplifier_plugin, m);
s.register_plugin(bsimp);
asimp = alloc(arith_simplifier_plugin, m_manager, *bsimp, m_params);
asimp = alloc(arith_simplifier_plugin, m, *bsimp, m_params);
s.register_plugin(asimp);
s.register_plugin(alloc(array_simplifier_plugin, m_manager, *bsimp, s, m_params));
bvsimp = alloc(bv_simplifier_plugin, m_manager, *bsimp, m_params);
s.register_plugin(alloc(array_simplifier_plugin, m, *bsimp, s, m_params));
bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, m_params);
s.register_plugin(bvsimp);
s.register_plugin(alloc(datatype_simplifier_plugin, m_manager, *bsimp));
s.register_plugin(alloc(fpa_simplifier_plugin, m_manager, *bsimp));
s.register_plugin(alloc(seq_simplifier_plugin, m_manager, *bsimp));
s.register_plugin(alloc(datatype_simplifier_plugin, m, *bsimp));
s.register_plugin(alloc(fpa_simplifier_plugin, m, *bsimp));
s.register_plugin(alloc(seq_simplifier_plugin, m, *bsimp));
}
void asserted_formulas::init(unsigned num_formulas, expr * const * formulas, proof * const * prs) {
@ -108,7 +108,7 @@ void asserted_formulas::init(unsigned num_formulas, expr * const * formulas, pro
SASSERT(!m_inconsistent);
SASSERT(m_scopes.empty());
m_asserted_formulas.append(num_formulas, formulas);
if (m_manager.proofs_enabled())
if (m.proofs_enabled())
m_asserted_formula_prs.append(num_formulas, prs);
}
@ -125,9 +125,9 @@ void asserted_formulas::push_assertion(expr * e, proof * pr, expr_ref_vector & r
SASSERT(!result.empty());
return;
}
if (m_manager.is_false(e))
if (m.is_false(e))
m_inconsistent = true;
::push_assertion(m_manager, e, pr, result, result_prs);
::push_assertion(m, e, pr, result, result_prs);
}
void asserted_formulas::set_eliminate_and(bool flag) {
@ -145,13 +145,13 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
push_assertion(e, _in_pr, m_asserted_formulas, m_asserted_formula_prs);
return;
}
proof_ref in_pr(_in_pr, m_manager);
expr_ref r1(m_manager);
proof_ref pr1(m_manager);
expr_ref r2(m_manager);
proof_ref pr2(m_manager);
TRACE("assert_expr_before_simp", tout << mk_ll_pp(e, m_manager) << "\n";);
TRACE("assert_expr_bug", tout << mk_pp(e, m_manager) << "\n";);
proof_ref in_pr(_in_pr, m);
expr_ref r1(m);
proof_ref pr1(m);
expr_ref r2(m);
proof_ref pr2(m);
TRACE("assert_expr_before_simp", tout << mk_ll_pp(e, m) << "\n";);
TRACE("assert_expr_bug", tout << mk_pp(e, m) << "\n";);
if (m_params.m_pre_simplifier) {
m_pre_simplifier(e, r1, pr1);
}
@ -161,14 +161,14 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
}
set_eliminate_and(false); // do not eliminate and before nnf.
m_simplifier(r1, r2, pr2);
TRACE("assert_expr_bug", tout << "after...\n" << mk_pp(r1, m_manager) << "\n";);
if (m_manager.proofs_enabled()) {
TRACE("assert_expr_bug", tout << "after...\n" << mk_pp(r1, m) << "\n";);
if (m.proofs_enabled()) {
if (e == r2)
pr2 = in_pr;
else
pr2 = m_manager.mk_modus_ponens(in_pr, m_manager.mk_transitivity(pr1, pr2));
pr2 = m.mk_modus_ponens(in_pr, m.mk_transitivity(pr1, pr2));
}
TRACE("assert_expr_after_simp", tout << mk_ll_pp(r1, m_manager) << "\n";);
TRACE("assert_expr_after_simp", tout << mk_ll_pp(r1, m) << "\n";);
push_assertion(r2, pr2, m_asserted_formulas, m_asserted_formula_prs);
TRACE("asserted_formulas_bug", tout << "after assert_expr\n"; display(tout););
}
@ -176,7 +176,7 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
void asserted_formulas::assert_expr(expr * e) {
if (inconsistent())
return;
assert_expr(e, m_manager.mk_asserted(e));
assert_expr(e, m.mk_asserted(e));
}
void asserted_formulas::get_assertions(ptr_vector<expr> & result) {
@ -184,13 +184,13 @@ void asserted_formulas::get_assertions(ptr_vector<expr> & result) {
}
void asserted_formulas::push_scope() {
SASSERT(inconsistent() || m_asserted_qhead == m_asserted_formulas.size() || m_manager.canceled());
SASSERT(inconsistent() || m_asserted_qhead == m_asserted_formulas.size() || m.canceled());
TRACE("asserted_formulas_scopes", tout << "push:\n"; display(tout););
m_scopes.push_back(scope());
m_macro_manager.push_scope();
scope & s = m_scopes.back();
s.m_asserted_formulas_lim = m_asserted_formulas.size();
SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead || m_manager.canceled());
SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead || m.canceled());
s.m_inconsistent_old = m_inconsistent;
m_defined_names.push();
m_bv_sharing.push_scope();
@ -206,7 +206,7 @@ void asserted_formulas::pop_scope(unsigned num_scopes) {
m_inconsistent = s.m_inconsistent_old;
m_defined_names.pop(num_scopes);
m_asserted_formulas.shrink(s.m_asserted_formulas_lim);
if (m_manager.proofs_enabled())
if (m.proofs_enabled())
m_asserted_formula_prs.shrink(s.m_asserted_formulas_lim);
m_asserted_qhead = s.m_asserted_formulas_lim;
m_scopes.shrink(new_lvl);
@ -228,7 +228,7 @@ void asserted_formulas::reset() {
#ifdef Z3DEBUG
bool asserted_formulas::check_well_sorted() const {
for (unsigned i = 0; i < m_asserted_formulas.size(); i++) {
if (!is_well_sorted(m_manager, m_asserted_formulas.get(i))) return false;
if (!is_well_sorted(m, m_asserted_formulas.get(i))) return false;
}
return true;
}
@ -322,7 +322,7 @@ void asserted_formulas::display(std::ostream & out) const {
for (unsigned i = 0; i < m_asserted_formulas.size(); i++) {
if (i == m_asserted_qhead)
out << "[HEAD] ==>\n";
out << mk_pp(m_asserted_formulas.get(i), m_manager) << "\n";
out << mk_pp(m_asserted_formulas.get(i), m) << "\n";
}
out << "inconsistent: " << inconsistent() << "\n";
}
@ -331,7 +331,7 @@ void asserted_formulas::display_ll(std::ostream & out, ast_mark & pp_visited) co
if (!m_asserted_formulas.empty()) {
unsigned sz = m_asserted_formulas.size();
for (unsigned i = 0; i < sz; i++)
ast_def_ll_pp(out, m_manager, m_asserted_formulas.get(i), pp_visited, true, false);
ast_def_ll_pp(out, m, m_asserted_formulas.get(i), pp_visited, true, false);
out << "asserted formulas:\n";
for (unsigned i = 0; i < sz; i++)
out << "#" << m_asserted_formulas[i]->get_id() << " ";
@ -346,23 +346,23 @@ void asserted_formulas::reduce_asserted_formulas() {
if (inconsistent()) {
return;
}
expr_ref_vector new_exprs(m_manager);
proof_ref_vector new_prs(m_manager);
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
unsigned i = m_asserted_qhead;
unsigned sz = m_asserted_formulas.size();
for (; i < sz && !inconsistent(); i++) {
expr * n = m_asserted_formulas.get(i);
SASSERT(n != 0);
proof * pr = m_asserted_formula_prs.get(i, 0);
expr_ref new_n(m_manager);
proof_ref new_pr(m_manager);
expr_ref new_n(m);
proof_ref new_pr(m);
m_simplifier(n, new_n, new_pr);
TRACE("reduce_asserted_formulas", tout << mk_pp(n, m_manager) << " -> " << mk_pp(new_n, m_manager) << "\n";);
TRACE("reduce_asserted_formulas", tout << mk_pp(n, m) << " -> " << mk_pp(new_n, m) << "\n";);
if (n == new_n.get()) {
push_assertion(n, pr, new_exprs, new_prs);
}
else {
new_pr = m_manager.mk_modus_ponens(pr, new_pr);
new_pr = m.mk_modus_ponens(pr, new_pr);
push_assertion(new_n, new_pr, new_exprs, new_prs);
}
if (canceled()) {
@ -376,15 +376,15 @@ void asserted_formulas::swap_asserted_formulas(expr_ref_vector & new_exprs, proo
SASSERT(!inconsistent() || !new_exprs.empty());
m_asserted_formulas.shrink(m_asserted_qhead);
m_asserted_formulas.append(new_exprs);
if (m_manager.proofs_enabled()) {
if (m.proofs_enabled()) {
m_asserted_formula_prs.shrink(m_asserted_qhead);
m_asserted_formula_prs.append(new_prs);
}
}
void asserted_formulas::find_macros_core() {
expr_ref_vector new_exprs(m_manager);
proof_ref_vector new_prs(m_manager);
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
unsigned sz = m_asserted_formulas.size();
m_macro_finder->operator()(sz - m_asserted_qhead, m_asserted_formulas.c_ptr() + m_asserted_qhead,
m_asserted_formula_prs.c_ptr() + m_asserted_qhead, new_exprs, new_prs);
@ -407,9 +407,9 @@ void asserted_formulas::expand_macros() {
void asserted_formulas::apply_quasi_macros() {
IF_VERBOSE(10, verbose_stream() << "(smt.find-quasi-macros)\n";);
TRACE("before_quasi_macros", display(tout););
expr_ref_vector new_exprs(m_manager);
proof_ref_vector new_prs(m_manager);
quasi_macros proc(m_manager, m_macro_manager, m_simplifier);
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
quasi_macros proc(m, m_macro_manager, m_simplifier);
while (proc(m_asserted_formulas.size() - m_asserted_qhead,
m_asserted_formulas.c_ptr() + m_asserted_qhead,
m_asserted_formula_prs.c_ptr() + m_asserted_qhead,
@ -423,28 +423,29 @@ void asserted_formulas::apply_quasi_macros() {
}
void asserted_formulas::nnf_cnf() {
IF_VERBOSE(10, verbose_stream() << "(smt.nnf)\n";);
nnf apply_nnf(m_manager, m_defined_names);
expr_ref_vector new_exprs(m_manager);
proof_ref_vector new_prs(m_manager);
expr_ref_vector push_todo(m_manager);
proof_ref_vector push_todo_prs(m_manager);
nnf apply_nnf(m, m_defined_names);
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
expr_ref_vector push_todo(m);
proof_ref_vector push_todo_prs(m);
unsigned i = m_asserted_qhead;
unsigned sz = m_asserted_formulas.size();
TRACE("nnf_bug", tout << "i: " << i << " sz: " << sz << "\n";);
for (; i < sz; i++) {
expr * n = m_asserted_formulas.get(i);
TRACE("nnf_bug", tout << "processing:\n" << mk_pp(n, m_manager) << "\n";);
TRACE("nnf_bug", tout << "processing:\n" << mk_pp(n, m) << "\n";);
proof * pr = m_asserted_formula_prs.get(i, 0);
expr_ref r1(m_manager);
proof_ref pr1(m_manager);
CASSERT("well_sorted",is_well_sorted(m_manager, n));
expr_ref r1(m);
proof_ref pr1(m);
CASSERT("well_sorted",is_well_sorted(m, n));
push_todo.reset();
push_todo_prs.reset();
apply_nnf(n, push_todo, push_todo_prs, r1, pr1);
CASSERT("well_sorted",is_well_sorted(m_manager, r1));
pr = m_manager.mk_modus_ponens(pr, pr1);
CASSERT("well_sorted",is_well_sorted(m, r1));
pr = m.mk_modus_ponens(pr, pr1);
push_todo.push_back(r1);
push_todo_prs.push_back(pr);
@ -456,13 +457,13 @@ void asserted_formulas::nnf_cnf() {
expr * n = push_todo.get(k);
proof * pr = 0;
m_simplifier(n, r1, pr1);
CASSERT("well_sorted",is_well_sorted(m_manager, r1));
CASSERT("well_sorted",is_well_sorted(m, r1));
if (canceled()) {
return;
}
if (m_manager.proofs_enabled())
pr = m_manager.mk_modus_ponens(push_todo_prs.get(k), pr1);
if (m.proofs_enabled())
pr = m.mk_modus_ponens(push_todo_prs.get(k), pr1);
else
pr = 0;
push_assertion(r1, pr, new_exprs, new_prs);
@ -476,23 +477,23 @@ void asserted_formulas::NAME() {
IF_VERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \
TRACE(LABEL, tout << "before:\n"; display(tout);); \
FUNCTOR_DEF; \
expr_ref_vector new_exprs(m_manager); \
proof_ref_vector new_prs(m_manager); \
expr_ref_vector new_exprs(m); \
proof_ref_vector new_prs(m); \
unsigned i = m_asserted_qhead; \
unsigned sz = m_asserted_formulas.size(); \
for (; i < sz; i++) { \
expr * n = m_asserted_formulas.get(i); \
proof * pr = m_asserted_formula_prs.get(i, 0); \
expr_ref new_n(m_manager); \
expr_ref new_n(m); \
functor(n, new_n); \
TRACE("simplifier_simple_step", tout << mk_pp(n, m_manager) << "\n" << mk_pp(new_n, m_manager) << "\n";); \
TRACE("simplifier_simple_step", tout << mk_pp(n, m) << "\n" << mk_pp(new_n, m) << "\n";); \
if (n == new_n.get()) { \
push_assertion(n, pr, new_exprs, new_prs); \
} \
else if (m_manager.proofs_enabled()) { \
proof_ref new_pr(m_manager); \
new_pr = m_manager.mk_rewrite_star(n, new_n, 0, 0); \
new_pr = m_manager.mk_modus_ponens(pr, new_pr); \
else if (m.proofs_enabled()) { \
proof_ref new_pr(m); \
new_pr = m.mk_rewrite_star(n, new_n, 0, 0); \
new_pr = m.mk_modus_ponens(pr, new_pr); \
push_assertion(new_n, new_pr, new_exprs, new_prs); \
} \
else { \
@ -505,7 +506,7 @@ void asserted_formulas::NAME() {
TRACE(LABEL, display(tout);); \
}
MK_SIMPLE_SIMPLIFIER(apply_distribute_forall, distribute_forall functor(m_manager, *m_bsimp), "distribute_forall", "distribute-forall");
MK_SIMPLE_SIMPLIFIER(apply_distribute_forall, distribute_forall functor(m), "distribute_forall", "distribute-forall");
void asserted_formulas::reduce_and_solve() {
IF_VERBOSE(10, verbose_stream() << "(smt.reducing)\n";);
@ -516,22 +517,22 @@ void asserted_formulas::reduce_and_solve() {
void asserted_formulas::infer_patterns() {
IF_VERBOSE(10, verbose_stream() << "(smt.pattern-inference)\n";);
TRACE("before_pattern_inference", display(tout););
pattern_inference infer(m_manager, m_params);
expr_ref_vector new_exprs(m_manager);
proof_ref_vector new_prs(m_manager);
pattern_inference infer(m, m_params);
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
unsigned i = m_asserted_qhead;
unsigned sz = m_asserted_formulas.size();
for (; i < sz; i++) {
expr * n = m_asserted_formulas.get(i);
proof * pr = m_asserted_formula_prs.get(i, 0);
expr_ref new_n(m_manager);
proof_ref new_pr(m_manager);
expr_ref new_n(m);
proof_ref new_pr(m);
infer(n, new_n, new_pr);
if (n == new_n.get()) {
push_assertion(n, pr, new_exprs, new_prs);
}
else if (m_manager.proofs_enabled()) {
new_pr = m_manager.mk_modus_ponens(pr, new_pr);
else if (m.proofs_enabled()) {
new_pr = m.mk_modus_ponens(pr, new_pr);
push_assertion(new_n, new_pr, new_exprs, new_prs);
}
else {
@ -554,16 +555,16 @@ void asserted_formulas::commit(unsigned new_qhead) {
void asserted_formulas::eliminate_term_ite() {
IF_VERBOSE(10, verbose_stream() << "(smt.eliminating-ite-term)\n";);
TRACE("before_elim_term_ite", display(tout););
elim_term_ite elim(m_manager, m_defined_names);
expr_ref_vector new_exprs(m_manager);
proof_ref_vector new_prs(m_manager);
elim_term_ite elim(m, m_defined_names);
expr_ref_vector new_exprs(m);
proof_ref_vector new_prs(m);
unsigned i = m_asserted_qhead;
unsigned sz = m_asserted_formulas.size();
for (; i < sz; i++) {
expr * n = m_asserted_formulas.get(i);
proof * pr = m_asserted_formula_prs.get(i, 0);
expr_ref new_n(m_manager);
proof_ref new_pr(m_manager);
expr_ref new_n(m);
proof_ref new_pr(m);
elim(n, new_exprs, new_prs, new_n, new_pr);
SASSERT(new_n.get() != 0);
DEBUG_CODE({
@ -574,8 +575,8 @@ void asserted_formulas::eliminate_term_ite() {
if (n == new_n.get()) {
push_assertion(n, pr, new_exprs, new_prs);
}
else if (m_manager.proofs_enabled()) {
new_pr = m_manager.mk_modus_ponens(pr, new_pr);
else if (m.proofs_enabled()) {
new_pr = m.mk_modus_ponens(pr, new_pr);
push_assertion(new_n, new_pr, new_exprs, new_prs);
}
else {
@ -602,31 +603,31 @@ void asserted_formulas::propagate_values() {
// - new_exprs2 is the set R
//
// The loop also updates the m_cache. It adds the entries x -> n to it.
expr_ref_vector new_exprs1(m_manager);
proof_ref_vector new_prs1(m_manager);
expr_ref_vector new_exprs2(m_manager);
proof_ref_vector new_prs2(m_manager);
expr_ref_vector new_exprs1(m);
proof_ref_vector new_prs1(m);
expr_ref_vector new_exprs2(m);
proof_ref_vector new_prs2(m);
unsigned sz = m_asserted_formulas.size();
for (unsigned i = 0; i < sz; i++) {
expr_ref n(m_asserted_formulas.get(i), m_manager);
proof_ref pr(m_asserted_formula_prs.get(i, 0), m_manager);
TRACE("simplifier", tout << mk_pp(n, m_manager) << "\n";);
expr_ref n(m_asserted_formulas.get(i), m);
proof_ref pr(m_asserted_formula_prs.get(i, 0), m);
TRACE("simplifier", tout << mk_pp(n, m) << "\n";);
expr* lhs, *rhs;
if (m_manager.is_eq(n, lhs, rhs) &&
(m_manager.is_value(lhs) || m_manager.is_value(rhs))) {
if (m_manager.is_value(lhs)) {
if (m.is_eq(n, lhs, rhs) &&
(m.is_value(lhs) || m.is_value(rhs))) {
if (m.is_value(lhs)) {
std::swap(lhs, rhs);
n = m_manager.mk_eq(lhs, rhs);
pr = m_manager.mk_symmetry(pr);
n = m.mk_eq(lhs, rhs);
pr = m.mk_symmetry(pr);
}
if (!m_manager.is_value(lhs) && !m_simplifier.is_cached(lhs)) {
if (!m.is_value(lhs) && !m_simplifier.is_cached(lhs)) {
if (i >= m_asserted_qhead) {
new_exprs1.push_back(n);
if (m_manager.proofs_enabled())
if (m.proofs_enabled())
new_prs1.push_back(pr);
}
TRACE("propagate_values", tout << "found:\n" << mk_pp(lhs, m_manager) << "\n->\n" << mk_pp(rhs, m_manager) << "\n";
if (pr) tout << "proof: " << mk_pp(pr, m_manager) << "\n";);
TRACE("propagate_values", tout << "found:\n" << mk_pp(lhs, m) << "\n->\n" << mk_pp(rhs, m) << "\n";
if (pr) tout << "proof: " << mk_pp(pr, m) << "\n";);
m_simplifier.cache_result(lhs, rhs, pr);
found = true;
continue;
@ -634,7 +635,7 @@ void asserted_formulas::propagate_values() {
}
if (i >= m_asserted_qhead) {
new_exprs2.push_back(n);
if (m_manager.proofs_enabled())
if (m.proofs_enabled())
new_prs2.push_back(pr);
}
}
@ -646,14 +647,14 @@ void asserted_formulas::propagate_values() {
for (unsigned i = 0; i < sz; i++) {
expr * n = new_exprs2.get(i);
proof * pr = new_prs2.get(i, 0);
expr_ref new_n(m_manager);
proof_ref new_pr(m_manager);
expr_ref new_n(m);
proof_ref new_pr(m);
m_simplifier(n, new_n, new_pr);
if (n == new_n.get()) {
push_assertion(n, pr, new_exprs1, new_prs1);
}
else {
new_pr = m_manager.mk_modus_ponens(pr, new_pr);
new_pr = m.mk_modus_ponens(pr, new_pr);
push_assertion(new_n, new_pr, new_exprs1, new_prs1);
}
}
@ -677,25 +678,25 @@ void asserted_formulas::propagate_booleans() {
cont = false;
unsigned i = m_asserted_qhead;
unsigned sz = m_asserted_formulas.size();
#define PROCESS() { \
expr * n = m_asserted_formulas.get(i); \
proof * pr = m_asserted_formula_prs.get(i, 0); \
expr_ref new_n(m_manager); \
proof_ref new_pr(m_manager); \
m_simplifier(n, new_n, new_pr); \
m_asserted_formulas.set(i, new_n); \
if (m_manager.proofs_enabled()) { \
new_pr = m_manager.mk_modus_ponens(pr, new_pr); \
m_asserted_formula_prs.set(i, new_pr); \
} \
if (n != new_n) { \
cont = true; \
modified = true; \
} \
if (m_manager.is_not(new_n)) \
m_simplifier.cache_result(to_app(new_n)->get_arg(0), m_manager.mk_false(), m_manager.mk_iff_false(new_pr)); \
else \
m_simplifier.cache_result(new_n, m_manager.mk_true(), m_manager.mk_iff_true(new_pr)); \
#define PROCESS() { \
expr * n = m_asserted_formulas.get(i); \
proof * pr = m_asserted_formula_prs.get(i, 0); \
expr_ref new_n(m); \
proof_ref new_pr(m); \
m_simplifier(n, new_n, new_pr); \
m_asserted_formulas.set(i, new_n); \
if (m.proofs_enabled()) { \
new_pr = m.mk_modus_ponens(pr, new_pr); \
m_asserted_formula_prs.set(i, new_pr); \
} \
if (n != new_n) { \
cont = true; \
modified = true; \
} \
if (m.is_not(new_n)) \
m_simplifier.cache_result(to_app(new_n)->get_arg(0), m.mk_false(), m.mk_iff_false(new_pr)); \
else \
m_simplifier.cache_result(new_n, m.mk_true(), m.mk_iff_true(new_pr)); \
}
for (; i < sz; i++) {
PROCESS();
@ -715,57 +716,58 @@ void asserted_formulas::propagate_booleans() {
}
#define MK_SIMPLIFIER(NAME, FUNCTOR, TAG, MSG, REDUCE) \
bool asserted_formulas::NAME() { \
IF_VERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \
TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \
FUNCTOR; \
bool changed = false; \
expr_ref_vector new_exprs(m_manager); \
proof_ref_vector new_prs(m_manager); \
unsigned i = m_asserted_qhead; \
unsigned sz = m_asserted_formulas.size(); \
for (; i < sz; i++) { \
expr * n = m_asserted_formulas.get(i); \
proof * pr = m_asserted_formula_prs.get(i, 0); \
expr_ref new_n(m_manager); \
proof_ref new_pr(m_manager); \
functor(n, new_n, new_pr); \
if (n == new_n.get()) { \
push_assertion(n, pr, new_exprs, new_prs); \
} \
else if (m_manager.proofs_enabled()) { \
changed = true; \
if (!new_pr) new_pr = m_manager.mk_rewrite(n, new_n); \
new_pr = m_manager.mk_modus_ponens(pr, new_pr); \
push_assertion(new_n, new_pr, new_exprs, new_prs); \
} \
else { \
changed = true; \
push_assertion(new_n, 0, new_exprs, new_prs); \
} \
} \
swap_asserted_formulas(new_exprs, new_prs); \
TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \
if (changed && REDUCE) { \
reduce_and_solve(); \
bool asserted_formulas::NAME() { \
IF_VERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \
TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \
} \
return changed; \
}
FUNCTOR; \
bool changed = false; \
expr_ref_vector new_exprs(m); \
proof_ref_vector new_prs(m); \
unsigned i = m_asserted_qhead; \
unsigned sz = m_asserted_formulas.size(); \
for (; i < sz; i++) { \
expr * n = m_asserted_formulas.get(i); \
proof * pr = m_asserted_formula_prs.get(i, 0); \
expr_ref new_n(m); \
proof_ref new_pr(m); \
functor(n, new_n, new_pr); \
if (n == new_n.get()) { \
push_assertion(n, pr, new_exprs, new_prs); \
} \
else if (m.proofs_enabled()) { \
changed = true; \
if (!new_pr) new_pr = m.mk_rewrite(n, new_n); \
new_pr = m.mk_modus_ponens(pr, new_pr); \
push_assertion(new_n, new_pr, new_exprs, new_prs); \
} \
else { \
changed = true; \
push_assertion(new_n, 0, new_exprs, new_prs); \
} \
} \
swap_asserted_formulas(new_exprs, new_prs); \
TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \
if (changed && REDUCE) { \
reduce_and_solve(); \
TRACE(TAG, ast_mark visited; display_ll(tout, visited);); \
} \
return changed; \
}
MK_SIMPLIFIER(pull_cheap_ite_trees, pull_cheap_ite_tree_star functor(m_manager, m_simplifier), "pull_cheap_ite_trees", "pull-cheap-ite-trees", false);
MK_SIMPLIFIER(pull_nested_quantifiers, pull_nested_quant functor(m_manager), "pull_nested_quantifiers", "pull-nested-quantifiers", false);
MK_SIMPLIFIER(pull_cheap_ite_trees, pull_cheap_ite_tree_star functor(m, m_simplifier), "pull_cheap_ite_trees", "pull-cheap-ite-trees", false);
MK_SIMPLIFIER(pull_nested_quantifiers, pull_nested_quant functor(m), "pull_nested_quantifiers", "pull-nested-quantifiers", false);
proof * asserted_formulas::get_inconsistency_proof() const {
if (!inconsistent())
return 0;
if (!m_manager.proofs_enabled())
if (!m.proofs_enabled())
return 0;
unsigned sz = m_asserted_formulas.size();
for (unsigned i = 0; i < sz; i++) {
expr * f = m_asserted_formulas.get(i);
if (m_manager.is_false(f))
if (m.is_false(f))
return m_asserted_formula_prs.get(i);
}
UNREACHABLE();
@ -780,14 +782,14 @@ void asserted_formulas::refine_inj_axiom() {
for (; i < sz; i++) {
expr * n = m_asserted_formulas.get(i);
proof * pr = m_asserted_formula_prs.get(i, 0);
expr_ref new_n(m_manager);
if (is_quantifier(n) && simplify_inj_axiom(m_manager, to_quantifier(n), new_n)) {
TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(n, m_manager) << "\n" << mk_pp(new_n, m_manager) << "\n";);
expr_ref new_n(m);
if (is_quantifier(n) && simplify_inj_axiom(m, to_quantifier(n), new_n)) {
TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(n, m) << "\n" << mk_pp(new_n, m) << "\n";);
m_asserted_formulas.set(i, new_n);
if (m_manager.proofs_enabled()) {
proof_ref new_pr(m_manager);
new_pr = m_manager.mk_rewrite(n, new_n);
new_pr = m_manager.mk_modus_ponens(pr, new_pr);
if (m.proofs_enabled()) {
proof_ref new_pr(m);
new_pr = m.mk_rewrite(n, new_n);
new_pr = m.mk_modus_ponens(pr, new_pr);
m_asserted_formula_prs.set(i, new_pr);
}
}
@ -797,36 +799,36 @@ void asserted_formulas::refine_inj_axiom() {
MK_SIMPLIFIER(apply_bit2int, bit2int& functor = m_bit2int, "bit2int", "propagate-bit-vector-over-integers", true);
MK_SIMPLIFIER(cheap_quant_fourier_motzkin, elim_bounds_star functor(m_manager), "elim_bounds", "cheap-fourier-motzkin", true);
MK_SIMPLIFIER(cheap_quant_fourier_motzkin, elim_bounds_star functor(m), "elim_bounds", "cheap-fourier-motzkin", true);
MK_SIMPLIFIER(elim_bvs_from_quantifiers, bv_elim_star functor(m_manager), "bv_elim", "eliminate-bit-vectors-from-quantifiers", true);
MK_SIMPLIFIER(elim_bvs_from_quantifiers, bv_elim_star functor(m), "bv_elim", "eliminate-bit-vectors-from-quantifiers", true);
#define LIFT_ITE(NAME, FUNCTOR, MSG) \
void asserted_formulas::NAME() { \
IF_VERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \
TRACE("lift_ite", display(tout);); \
FUNCTOR; \
unsigned i = m_asserted_qhead; \
unsigned sz = m_asserted_formulas.size(); \
for (; i < sz; i++) { \
expr * n = m_asserted_formulas.get(i); \
proof * pr = m_asserted_formula_prs.get(i, 0); \
expr_ref new_n(m_manager); \
proof_ref new_pr(m_manager); \
functor(n, new_n, new_pr); \
TRACE("lift_ite_step", tout << mk_pp(n, m_manager) << "\n";); \
IF_VERBOSE(10000, verbose_stream() << "lift before: " << get_num_exprs(n) << ", after: " << get_num_exprs(new_n) << "\n";); \
m_asserted_formulas.set(i, new_n); \
if (m_manager.proofs_enabled()) { \
new_pr = m_manager.mk_modus_ponens(pr, new_pr); \
m_asserted_formula_prs.set(i, new_pr); \
} \
} \
TRACE("lift_ite", display(tout);); \
reduce_and_solve(); \
}
#define LIFT_ITE(NAME, FUNCTOR, MSG) \
void asserted_formulas::NAME() { \
IF_VERBOSE(10, verbose_stream() << "(smt." << MSG << ")\n";); \
TRACE("lift_ite", display(tout);); \
FUNCTOR; \
unsigned i = m_asserted_qhead; \
unsigned sz = m_asserted_formulas.size(); \
for (; i < sz; i++) { \
expr * n = m_asserted_formulas.get(i); \
proof * pr = m_asserted_formula_prs.get(i, 0); \
expr_ref new_n(m); \
proof_ref new_pr(m); \
functor(n, new_n, new_pr); \
TRACE("lift_ite_step", tout << mk_pp(n, m) << "\n";); \
IF_VERBOSE(10000, verbose_stream() << "lift before: " << get_num_exprs(n) << ", after: " << get_num_exprs(new_n) << "\n";); \
m_asserted_formulas.set(i, new_n); \
if (m.proofs_enabled()) { \
new_pr = m.mk_modus_ponens(pr, new_pr); \
m_asserted_formula_prs.set(i, new_pr); \
} \
} \
TRACE("lift_ite", display(tout);); \
reduce_and_solve(); \
}
LIFT_ITE(lift_ite, push_app_ite functor(m_simplifier, m_params.m_lift_ite == LI_CONSERVATIVE), "lifting ite");
LIFT_ITE(ng_lift_ite, ng_push_app_ite functor(m_simplifier, m_params.m_ng_lift_ite == LI_CONSERVATIVE), "lifting ng ite");
@ -848,12 +850,12 @@ void asserted_formulas::max_bv_sharing() {
for (; i < sz; i++) {
expr * n = m_asserted_formulas.get(i);
proof * pr = m_asserted_formula_prs.get(i, 0);
expr_ref new_n(m_manager);
proof_ref new_pr(m_manager);
expr_ref new_n(m);
proof_ref new_pr(m);
m_bv_sharing(n, new_n, new_pr);
m_asserted_formulas.set(i, new_n);
if (m_manager.proofs_enabled()) {
new_pr = m_manager.mk_modus_ponens(pr, new_pr);
if (m.proofs_enabled()) {
new_pr = m.mk_modus_ponens(pr, new_pr);
m_asserted_formula_prs.set(i, new_pr);
}
}

View file

@ -35,7 +35,7 @@ class arith_simplifier_plugin;
class bv_simplifier_plugin;
class asserted_formulas {
ast_manager & m_manager;
ast_manager & m;
smt_params & m_params;
simplifier m_pre_simplifier;
simplifier m_simplifier;
@ -94,7 +94,7 @@ class asserted_formulas {
unsigned get_total_size() const;
bool has_bv() const;
void max_bv_sharing();
bool canceled() { return m_manager.canceled(); }
bool canceled() { return m.canceled(); }
public:
asserted_formulas(ast_manager & m, smt_params & p);
@ -115,7 +115,7 @@ public:
void commit();
void commit(unsigned new_qhead);
expr * get_formula(unsigned idx) const { return m_asserted_formulas.get(idx); }
proof * get_formula_proof(unsigned idx) const { return m_manager.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; }
proof * get_formula_proof(unsigned idx) const { return m.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; }
expr * const * get_formulas() const { return m_asserted_formulas.c_ptr(); }
proof * const * get_formula_proofs() const { return m_asserted_formula_prs.c_ptr(); }
void init(unsigned num_formulas, expr * const * formulas, proof * const * prs);

View file

@ -44,6 +44,7 @@ def_module_params(module_name='smt',
('arith.euclidean_solver', BOOL, False, 'eucliean solver for linear integer arithmetic'),
('arith.propagate_eqs', BOOL, True, 'propagate (cheap) equalities'),
('arith.propagation_mode', UINT, 2, '0 - no propagation, 1 - propagate existing literals, 2 - refine bounds'),
('arith.reflect', BOOL, True, 'reflect arithmetical operators to the congruence closure'),
('arith.branch_cut_ratio', UINT, 2, 'branch/cut ratio for linear integer arithmetic'),
('arith.int_eq_branch', BOOL, False, 'branching using derived integer equations'),
('arith.ignore_int', BOOL, False, 'treat integer variables as real'),

View file

@ -35,6 +35,7 @@ void theory_arith_params::updt_params(params_ref const & _p) {
m_arith_ignore_int = p.arith_ignore_int();
m_arith_bound_prop = static_cast<bound_prop_mode>(p.arith_propagation_mode());
m_arith_dump_lemmas = p.arith_dump_lemmas();
m_arith_reflect = p.arith_reflect();
}
@ -85,4 +86,4 @@ void theory_arith_params::display(std::ostream & out) const {
DISPLAY_PARAM(m_nl_arith_branching);
DISPLAY_PARAM(m_nl_arith_rounds);
DISPLAY_PARAM(m_arith_euclidean_solver);
}
}

View file

@ -7304,7 +7304,7 @@ namespace smt {
TRACE("str", tout << "variable " << mk_ismt2_pp(ap, get_manager()) << " is #" << v << std::endl;);
}
}
} else if (ex_sort == bool_sort) {
} else if (ex_sort == bool_sort && !is_quantifier(ex)) {
TRACE("str", tout << "setting up axioms for " << mk_ismt2_pp(ex, get_manager()) <<
": expr is of sort Bool" << std::endl;);
// set up axioms for boolean terms
@ -7351,7 +7351,7 @@ namespace smt {
// if expr is an application, recursively inspect all arguments
if (is_app(ex)) {
app * term = (app*)ex;
app * term = to_app(ex);
unsigned num_args = term->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
set_up_axioms(term->get_arg(i));

View file

@ -162,3 +162,9 @@ bool solver::is_literal(ast_manager& m, expr* e) {
return is_uninterp_const(e) || (m.is_not(e, e) && is_uninterp_const(e));
}
expr_ref solver::lookahead(expr_ref_vector const& candidates) {
ast_manager& m = candidates.get_manager();
return expr_ref(m.mk_true(), m);
}

View file

@ -172,6 +172,17 @@ public:
*/
virtual lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);
/**
\brief extract a lookahead candidates for branching.
*/
virtual expr_ref lookahead(expr_ref_vector const& candidates);
/**
\brief extract learned lemmas.
*/
virtual void get_lemmas(expr_ref_vector& lemmas) {}
/**
\brief Display the content of this solver.
*/

View file

@ -150,7 +150,21 @@ public:
if (m.canceled()) {
throw tactic_exception(Z3_CANCELED_MSG);
}
throw tactic_exception(local_solver->reason_unknown().c_str());
if (in->models_enabled()) {
model_ref mdl;
local_solver->get_model(mdl);
if (mdl) {
mc = model2model_converter(mdl.get());
mc = concat(fmc.get(), mc.get());
}
}
in->reset();
unsigned sz = local_solver->get_num_assertions();
for (unsigned i = 0; i < sz; ++i) {
in->assert_expr(local_solver->get_assertion(i));
}
result.push_back(in.get());
break;
}
local_solver->collect_statistics(m_st);
}

View file

@ -117,8 +117,10 @@ struct bit_blaster_model_converter : public model_converter {
SASSERT(is_uninterp_const(bit));
func_decl * bit_decl = to_app(bit)->get_decl();
expr * bit_val = old_model->get_const_interp(bit_decl);
// remark: if old_model does not assign bit_val, then assume it is false.
if (bit_val != 0 && m().is_true(bit_val))
if (bit_val == 0) {
goto bail;
}
if (m().is_true(bit_val))
val++;
}
}
@ -133,15 +135,50 @@ struct bit_blaster_model_converter : public model_converter {
func_decl * bit_decl = to_app(bit)->get_decl();
expr * bit_val = old_model->get_const_interp(bit_decl);
// remark: if old_model does not assign bit_val, then assume it is false.
if (bit_val != 0 && !util.is_zero(bit_val))
if (bit_val == 0) {
goto bail;
}
if (!util.is_zero(bit_val))
val++;
}
}
new_val = util.mk_numeral(val, bv_sz);
new_model->register_decl(m_vars.get(i), new_val);
continue;
bail:
new_model->register_decl(m_vars.get(i), mk_bv(bs, *old_model));
}
}
app_ref mk_bv(expr* bs, model& old_model) {
bv_util util(m());
unsigned bv_sz = to_app(bs)->get_num_args();
expr_ref_vector args(m());
app_ref result(m());
for (unsigned j = 0; j < bv_sz; ++j) {
expr * bit = to_app(bs)->get_arg(j);
SASSERT(is_uninterp_const(bit));
func_decl * bit_decl = to_app(bit)->get_decl();
expr * bit_val = old_model.get_const_interp(bit_decl);
if (bit_val != 0) {
args.push_back(bit_val);
}
else {
args.push_back(bit);
}
}
if (TO_BOOL) {
SASSERT(is_app_of(bs, m().get_family_id("bv"), OP_MKBV));
result = util.mk_bv(bv_sz, args.c_ptr());
}
else {
SASSERT(is_app_of(bs, m().get_family_id("bv"), OP_CONCAT));
result = util.mk_concat(bv_sz, args.c_ptr());
}
return result;
}
virtual void operator()(model_ref & md, unsigned goal_idx) {
SASSERT(goal_idx == 0);
model * new_model = alloc(model, m());

View file

@ -262,6 +262,13 @@ void goal::get_formulas(ptr_vector<expr> & result) {
}
}
void goal::get_formulas(expr_ref_vector & result) {
unsigned sz = size();
for (unsigned i = 0; i < sz; i++) {
result.push_back(form(i));
}
}
void goal::update(unsigned i, expr * f, proof * pr, expr_dependency * d) {
// KLM: don't know why this assertion is no longer true
// SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));

View file

@ -120,6 +120,7 @@ public:
void update(unsigned i, expr * f, proof * pr = 0, expr_dependency * dep = 0);
void get_formulas(ptr_vector<expr> & result);
void get_formulas(expr_ref_vector & result);
void elim_true();
void elim_redundancies();

View file

@ -149,6 +149,7 @@ public:
virtual void set_reason_unknown(char const* msg) { m_solver->set_reason_unknown(msg); }
virtual void get_labels(svector<symbol> & r) { m_solver->get_labels(r); }
virtual ast_manager& get_manager() const { return m; }
virtual expr_ref lookahead(expr_ref_vector& candidates) { flush_assertions(); return m_solver->lookahead(candidates); }
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) { return m_solver->find_mutexes(vars, mutexes); }
virtual lbool get_consequences_core(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences) {
flush_assertions();

View file

@ -30,7 +30,6 @@ Notes:
#include"qffp_tactic.h"
#include"qfaufbv_tactic.h"
#include"qfauflia_tactic.h"
#include"qfufnra_tactic.h"
tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
tactic * st = using_params(and_then(mk_simplify_tactic(m),
@ -44,7 +43,6 @@ tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
cond(mk_is_nra_probe(), mk_nra_tactic(m),
cond(mk_is_lira_probe(), mk_lira_tactic(m, p),
cond(mk_is_qffp_probe(), mk_qffp_tactic(m, p),
//cond(mk_is_qfufnra_probe(), mk_qfufnra_tactic(m, p),
mk_smt_tactic()))))))))))),
p);
return st;

View file

@ -97,6 +97,7 @@ public:
virtual void get_labels(svector<symbol> & r) { m_solver->get_labels(r); }
virtual ast_manager& get_manager() const { return m; }
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) { return m_solver->find_mutexes(vars, mutexes); }
virtual expr_ref lookahead(expr_ref_vector& candidates) { return m_solver->lookahead(candidates); }
virtual lbool get_consequences_core(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences) {
datatype_util dt(m);

View file

@ -18,11 +18,13 @@ Notes:
--*/
#include "fd_solver.h"
#include "fd_tactic.h"
#include "tactic.h"
#include "inc_sat_solver.h"
#include "enum2bv_solver.h"
#include "pb2bv_solver.h"
#include "bounded_int2bv_solver.h"
#include "solver/solver2tactic.h"
solver * mk_fd_solver(ast_manager & m, params_ref const & p) {
solver* s = mk_inc_sat_solver(m, p);
@ -31,3 +33,7 @@ solver * mk_fd_solver(ast_manager & m, params_ref const & p) {
s = mk_bounded_int2bv_solver(m, p, s);
return s;
}
tactic * mk_fd_tactic(ast_manager & m, params_ref const& p) {
return mk_solver2tactic(mk_fd_solver(m, p));
}

View file

@ -26,4 +26,5 @@ class solver;
solver * mk_fd_solver(ast_manager & m, params_ref const & p);
#endif

View file

@ -93,6 +93,7 @@ public:
virtual void set_reason_unknown(char const* msg) { m_solver->set_reason_unknown(msg); }
virtual void get_labels(svector<symbol> & r) { m_solver->get_labels(r); }
virtual ast_manager& get_manager() const { return m; }
virtual expr_ref lookahead(expr_ref_vector& candidates) { flush_assertions(); return m_solver->lookahead(candidates); }
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) { return m_solver->find_mutexes(vars, mutexes); }
virtual lbool get_consequences_core(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences) {
flush_assertions();

View file

@ -34,11 +34,11 @@ Notes:
#include"default_tactic.h"
#include"ufbv_tactic.h"
#include"qffp_tactic.h"
#include"qfufnra_tactic.h"
#include"horn_tactic.h"
#include"smt_solver.h"
#include"inc_sat_solver.h"
#include"fd_solver.h"
#include"fd_tactic.h"
#include"bv_rewriter.h"
#include"solver2tactic.h"
@ -91,9 +91,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const
else if (logic=="HORN")
return mk_horn_tactic(m, p);
else if (logic == "QF_FD")
return mk_solver2tactic(mk_fd_solver(m, p));
//else if (logic=="QF_UFNRA")
// return mk_qfufnra_tactic(m, p);
return mk_fd_tactic(m, p);
else
return mk_default_tactic(m, p);
}

View file

@ -1159,12 +1159,14 @@ void solve_mps_double(std::string file_name, bool look_for_min, unsigned max_ite
lp_solver<double, double> * solver = reader.create_solver(dual);
setup_solver(max_iterations, time_limit, look_for_min, args_parser, solver);
int begin = get_millisecond_count();
stopwatch sw;
sw.start();
if (dual) {
std::cout << "solving for dual" << std::endl;
}
solver->find_maximal_solution();
int span = get_millisecond_span(begin);
sw.stop();
double span = sw.get_seconds();
std::cout << "Status: " << lp_status_to_string(solver->get_status()) << std::endl;
if (solver->get_status() == lp_status::OPTIMAL) {
if (reader.column_names().size() < 20) {
@ -1213,7 +1215,8 @@ void solve_mps_rational(std::string file_name, bool look_for_min, unsigned max_i
if (reader.is_ok()) {
auto * solver = reader.create_solver(dual);
setup_solver(max_iterations, time_limit, look_for_min, args_parser, solver);
int begin = get_millisecond_count();
stopwatch sw;
sw.start();
solver->find_maximal_solution();
std::cout << "Status: " << lp_status_to_string(solver->get_status()) << std::endl;
@ -1227,7 +1230,7 @@ void solve_mps_rational(std::string file_name, bool look_for_min, unsigned max_i
}
std::cout << "cost = " << cost.get_double() << std::endl;
}
std::cout << "processed in " << get_millisecond_span(begin) / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << std::endl;
std::cout << "processed in " << sw.get_current_seconds() / 1000.0 << " seconds, running for " << solver->m_total_iterations << " iterations" << std::endl;
delete solver;
} else {
std::cout << "cannot process " << file_name << std::endl;
@ -2426,9 +2429,10 @@ void run_lar_solver(argument_parser & args_parser, lar_solver * solver, mps_read
std::cout << "status = " << lp_status_to_string(solver->get_status()) << std::endl;
return;
}
int begin = get_millisecond_count();
stopwatch sw;
sw.start();
lp_status status = solver->solve();
std::cout << "status is " << lp_status_to_string(status) << ", processed for " << get_millisecond_span(begin) / 1000.0 <<" seconds, and " << solver->get_total_iterations() << " iterations" << std::endl;
std::cout << "status is " << lp_status_to_string(status) << ", processed for " << sw.get_current_seconds() <<" seconds, and " << solver->get_total_iterations() << " iterations" << std::endl;
if (solver->get_status() == INFEASIBLE) {
vector<std::pair<lean::mpq, constraint_index>> evidence;
solver->get_infeasibility_explanation(evidence);

View file

@ -55,10 +55,6 @@ public:
void set_core_solver_bounds();
void update_time_limit_from_starting_time(int start_time) {
this->m_settings.time_limit -= (get_millisecond_span(start_time) / 1000.);
}
void find_maximal_solution();
void fill_A_x_and_basis_for_stage_one_total_inf();

View file

@ -152,7 +152,6 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::set_core_solver_
template <typename T, typename X> void lp_primal_simplex<T, X>::find_maximal_solution() {
int preprocessing_start_time = get_millisecond_count();
if (this->problem_is_empty()) {
this->m_status = lp_status::EMPTY;
return;
@ -169,7 +168,6 @@ template <typename T, typename X> void lp_primal_simplex<T, X>::find_maximal_sol
fill_acceptable_values_for_x();
this->count_slacks_and_artificials();
set_core_solver_bounds();
update_time_limit_from_starting_time(preprocessing_start_time);
solve_with_total_inf();
}

View file

@ -8,9 +8,9 @@
#include <string>
#include <algorithm>
#include <limits>
#include <sys/timeb.h>
#include <iomanip>
#include "util/lp/lp_utils.h"
#include "util/stopwatch.h"
namespace lean {
typedef unsigned var_index;
@ -69,10 +69,6 @@ enum non_basic_column_value_position { at_low_bound, at_upper_bound, at_fixed, f
template <typename X> bool is_epsilon_small(const X & v, const double& eps); // forward definition
int get_millisecond_count();
int get_millisecond_span(int start_time);
class lp_resource_limit {
public:
virtual bool get_cancel_flag() = 0;
@ -92,12 +88,13 @@ struct lp_settings {
private:
class default_lp_resource_limit : public lp_resource_limit {
lp_settings& m_settings;
int m_start_time;
stopwatch m_sw;
public:
default_lp_resource_limit(lp_settings& s): m_settings(s), m_start_time(get_millisecond_count()) {}
default_lp_resource_limit(lp_settings& s): m_settings(s) {
m_sw.start();
}
virtual bool get_cancel_flag() {
int span_in_mills = get_millisecond_span(m_start_time);
return (span_in_mills / 1000.0 > m_settings.time_limit);
return (m_sw.get_current_seconds() > m_settings.time_limit);
}
};

View file

@ -52,19 +52,6 @@ lp_status lp_status_from_string(std::string status) {
lean_unreachable();
return lp_status::UNKNOWN; // it is unreachable
}
int get_millisecond_count() {
timeb tb;
ftime(&tb);
return tb.millitm + (tb.time & 0xfffff) * 1000;
}
int get_millisecond_span(int start_time) {
int span = get_millisecond_count() - start_time;
if (span < 0)
span += 0x100000 * 1000;
return span;
}
template <typename T>

View file

@ -58,8 +58,8 @@ unsigned get_width_of_column(unsigned j, vector<vector<std::string>> & A) {
unsigned r = 0;
for (unsigned i = 0; i < A.size(); i++) {
vector<std::string> & t = A[i];
std::string str= t[j];
unsigned s = str.size();
std::string str = t[j];
unsigned s = static_cast<unsigned>(str.size());
if (r < s) {
r = s;
}
@ -69,8 +69,8 @@ unsigned get_width_of_column(unsigned j, vector<vector<std::string>> & A) {
void print_matrix_with_widths(vector<vector<std::string>> & A, vector<unsigned> & ws, std::ostream & out) {
for (unsigned i = 0; i < A.size(); i++) {
for (unsigned j = 0; j < A[i].size(); j++) {
print_blanks(ws[j] - A[i][j].size(), out);
for (unsigned j = 0; j < static_cast<unsigned>(A[i].size()); j++) {
print_blanks(ws[j] - static_cast<unsigned>(A[i][j].size()), out);
out << A[i][j] << " ";
}
out << std::endl;

View file

@ -1050,8 +1050,8 @@ bool sparse_matrix<T, X>::get_pivot_for_column(unsigned &i, unsigned &j, int c_p
if (i_inv < k) continue;
unsigned j_inv = adjust_column_inverse(j);
if (j_inv < k) continue;
int small = elem_is_too_small(i, j, c_partial_pivoting);
if (!small) {
int _small = elem_is_too_small(i, j, c_partial_pivoting);
if (!_small) {
#ifdef LEAN_DEBUG
// if (!really_best_pivot(i, j, c_partial_pivoting, k)) {
// print_active_matrix(k);
@ -1063,7 +1063,7 @@ bool sparse_matrix<T, X>::get_pivot_for_column(unsigned &i, unsigned &j, int c_p
j = j_inv;
return true;
}
if (small != 2) { // 2 means that the pair is not in the matrix
if (_small != 2) { // 2 means that the pair is not in the matrix
pivots_candidates_that_are_too_small.push_back(std::make_pair(i, j));
}
}