3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-03 19:35:42 +00:00

move to self-contained trail instructions

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-04-15 17:38:36 -07:00
parent 2eadcd586a
commit 549b984c88
7 changed files with 87 additions and 46 deletions

View file

@ -8,6 +8,7 @@ Module Name:
Author: Author:
Nikolaj Bjorner (nbjorner) 2021-03-19 Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/ --*/

View file

@ -8,6 +8,7 @@ Module Name:
Author: Author:
Nikolaj Bjorner (nbjorner) 2021-03-19 Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/ --*/

View file

@ -8,6 +8,7 @@ Module Name:
Author: Author:
Nikolaj Bjorner (nbjorner) 2021-03-19 Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/ --*/

View file

@ -8,6 +8,7 @@ Module Name:
Author: Author:
Nikolaj Bjorner (nbjorner) 2021-03-19 Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/ --*/
#pragma once #pragma once

View file

@ -12,6 +12,7 @@ Abstract:
Author: Author:
Nikolaj Bjorner (nbjorner) 2021-03-19 Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/ --*/
@ -42,6 +43,7 @@ namespace polysat {
for (unsigned k = size(v); k-- > 0; ) for (unsigned k = size(v); k-- > 0; )
value &= val.get_bit(k) ? m_bdd.mk_var(k) : m_bdd.mk_nvar(k); value &= val.get_bit(k) ? m_bdd.mk_var(k) : m_bdd.mk_nvar(k);
SASSERT((value && !m_viable[v]).is_false()); SASSERT((value && !m_viable[v]).is_false());
push_viable(v);
m_viable[v] &= !value; m_viable[v] &= !value;
} }
@ -68,14 +70,8 @@ namespace polysat {
return is_unique ? l_true : l_undef; return is_unique ? l_true : l_undef;
} }
struct solver::t_del_var : public trail {
solver& s;
t_del_var(solver& s): s(s) {}
void undo() override { s.del_var(); }
};
solver::solver(trail_stack& s, reslimit& lim): solver::solver(reslimit& lim):
m_trail(s),
m_lim(lim), m_lim(lim),
m_bdd(1000), m_bdd(1000),
m_dm(m_value_manager, m_alloc), m_dm(m_value_manager, m_alloc),
@ -132,7 +128,7 @@ namespace polysat {
m_activity.push_back(0); m_activity.push_back(0);
m_vars.push_back(sz2pdd(sz).mk_var(v)); m_vars.push_back(sz2pdd(sz).mk_var(v));
m_size.push_back(sz); m_size.push_back(sz);
m_trail.push(t_del_var(*this)); m_trail.push_back(trail_instr_t::add_var_i);
m_free_vars.mk_var_eh(v); m_free_vars.mk_var_eh(v);
return v; return v;
} }
@ -192,7 +188,7 @@ namespace polysat {
} }
void solver::propagate() { void solver::propagate() {
m_trail.push(value_trail(m_qhead)); push_qhead();
while (can_propagate()) while (can_propagate())
propagate(m_search[m_qhead++].first); propagate(m_search[m_qhead++].first);
} }
@ -220,15 +216,51 @@ namespace polysat {
void solver::push_level() { void solver::push_level() {
++m_level; ++m_level;
m_trail.push_scope(); m_trail.push_back(trail_instr_t::inc_level_i);
} }
void solver::pop_levels(unsigned num_levels) { void solver::pop_levels(unsigned num_levels) {
m_trail.pop_scope(num_levels); while (num_levels > 0) {
m_level -= num_levels; switch (m_trail.back()) {
case trail_instr_t::qhead_i: {
pop_qhead();
break;
}
case trail_instr_t::add_var_i: {
del_var();
break;
}
case trail_instr_t::inc_level_i: {
--m_level;
--num_levels;
break;
}
case trail_instr_t::viable_i: {
auto p = m_viable_trail.back();
m_viable[p.first] = p.second;
m_viable_trail.pop_back();
break;
}
case trail_instr_t::assign_i: {
auto v = m_search.back().first;
m_free_vars.unassign_var_eh(v);
m_justification[v] = justification::unassigned();
m_search.pop_back();
break;
}
case trail_instr_t::just_i: {
auto v = m_cjust_trail.back();
m_cjust[v].pop_back();
m_cjust_trail.pop_back();
break;
}
default:
UNREACHABLE();
}
m_trail.pop_back();
}
pop_constraints(m_constraints); pop_constraints(m_constraints);
pop_constraints(m_redundant); pop_constraints(m_redundant);
pop_assignment();
} }
void solver::pop_constraints(scoped_ptr_vector<constraint>& cs) { void solver::pop_constraints(scoped_ptr_vector<constraint>& cs) {
@ -239,28 +271,6 @@ namespace polysat {
} }
} }
/**
* TBD: rewrite for proper backtracking where variable levels don't follow scope level.
* use a marker into m_search for level as in SAT solver.
*/
void solver::pop_assignment() {
while (!m_search.empty() && m_justification[m_search.back().first].level() > m_level) {
undo_var(m_search.back().first);
m_search.pop_back();
}
}
// Base approach just clears all assignments.
// TBD approach allows constraints to constrain bits of v. They are
// added to cjust and affect viable outside of search.
void solver::undo_var(pvar v) {
m_justification[v] = justification::unassigned();
m_free_vars.unassign_var_eh(v);
m_cjust[v].reset();
m_viable[v] = m_bdd.mk_true();
}
void solver::add_watch(constraint& c) { void solver::add_watch(constraint& c) {
auto const& vars = c.vars(); auto const& vars = c.vars();
if (vars.size() > 0) if (vars.size() > 0)
@ -327,6 +337,7 @@ namespace polysat {
SASSERT(is_viable(v, val)); SASSERT(is_viable(v, val));
m_value[v] = val; m_value[v] = val;
m_search.push_back(std::make_pair(v, val)); m_search.push_back(std::make_pair(v, val));
m_trail.push_back(trail_instr_t::assign_i);
m_justification[v] = j; m_justification[v] = j;
} }
@ -473,7 +484,7 @@ namespace polysat {
if (!c) if (!c)
return; return;
SASSERT(m_conflict_level <= m_justification[v].level()); SASSERT(m_conflict_level <= m_justification[v].level());
m_cjust[v].push_back(c); push_cjust(v, c);
add_lemma(c); add_lemma(c);
} }
@ -490,11 +501,14 @@ namespace polysat {
rational val = m_value[v]; rational val = m_value[v];
SASSERT(m_justification[v].is_decision()); SASSERT(m_justification[v].is_decision());
bdd viable = m_viable[v]; bdd viable = m_viable[v];
m_conflict.append(m_cjust[v]); constraints just(m_cjust[v]);
backjump(m_justification[v].level()-1); backjump(m_justification[v].level()-1);
SASSERT(m_cjust[v].empty()); for (unsigned i = m_cjust[v].size(); i < just.size(); ++i)
m_cjust[v].append(m_conflict); push_cjust(v, just[i]);
for (constraint* c : m_conflict)
push_cjust(v, c);
m_conflict.reset(); m_conflict.reset();
push_viable(v);
m_viable[v] = viable; m_viable[v] = viable;
add_non_viable(v, val); add_non_viable(v, val);
m_free_vars.del_var_eh(v); m_free_vars.del_var_eh(v);

View file

@ -12,6 +12,7 @@ Abstract:
Author: Author:
Nikolaj Bjorner (nbjorner) 2021-03-19 Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/ --*/
#pragma once #pragma once
@ -19,6 +20,7 @@ Author:
#include "util/statistics.h" #include "util/statistics.h"
#include "math/polysat/constraint.h" #include "math/polysat/constraint.h"
#include "math/polysat/justification.h" #include "math/polysat/justification.h"
#include "math/polysat/trail.h"
namespace polysat { namespace polysat {
@ -36,7 +38,6 @@ namespace polysat {
typedef ptr_vector<constraint> constraints; typedef ptr_vector<constraint> constraints;
trail_stack& m_trail;
reslimit& m_lim; reslimit& m_lim;
scoped_ptr_vector<dd::pdd_manager> m_pdd; scoped_ptr_vector<dd::pdd_manager> m_pdd;
dd::bdd_manager m_bdd; dd::bdd_manager m_bdd;
@ -68,9 +69,35 @@ namespace polysat {
unsigned m_qhead { 0 }; unsigned m_qhead { 0 };
unsigned m_level { 0 }; unsigned m_level { 0 };
svector<trail_instr_t> m_trail;
unsigned_vector m_qhead_trail;
vector<std::pair<pvar, bdd>> m_viable_trail;
unsigned_vector m_cjust_trail;
unsigned_vector m_base_levels; // External clients can push/pop scope. unsigned_vector m_base_levels; // External clients can push/pop scope.
void push_viable(pvar v) {
m_viable_trail.push_back(std::make_pair(v, m_viable[v]));
}
void push_qhead() {
m_trail.push_back(trail_instr_t::qhead_i);
m_qhead_trail.push_back(m_qhead);
}
void pop_qhead() {
m_qhead = m_qhead_trail.back();
m_qhead_trail.pop_back();
}
void push_cjust(pvar v, constraint* c) {
m_cjust[v].push_back(c);
m_trail.push_back(trail_instr_t::just_i);
m_cjust_trail.push_back(v);
}
unsigned size(pvar v) const { return m_size[v]; } unsigned size(pvar v) const { return m_size[v]; }
/** /**
* check if value is viable according to m_viable. * check if value is viable according to m_viable.
@ -105,7 +132,6 @@ namespace polysat {
* undo trail operations for backtracking. * undo trail operations for backtracking.
* Each struct is a subclass of trail and implements undo(). * Each struct is a subclass of trail and implements undo().
*/ */
struct t_del_var;
void del_var(); void del_var();
@ -113,7 +139,6 @@ namespace polysat {
void push_level(); void push_level();
void pop_levels(unsigned num_levels); void pop_levels(unsigned num_levels);
void pop_assignment();
void pop_constraints(scoped_ptr_vector<constraint>& cs); void pop_constraints(scoped_ptr_vector<constraint>& cs);
void assign_core(pvar v, rational const& val, justification const& j); void assign_core(pvar v, rational const& val, justification const& j);
@ -157,7 +182,6 @@ namespace polysat {
void revert_decision(pvar v); void revert_decision(pvar v);
void learn_lemma(pvar v, constraint* c); void learn_lemma(pvar v, constraint* c);
void backjump(unsigned new_level); void backjump(unsigned new_level);
void undo_var(pvar v);
void add_lemma(constraint* c); void add_lemma(constraint* c);
bool invariant(); bool invariant();
@ -170,7 +194,7 @@ namespace polysat {
* every update to the solver is going to be retractable * every update to the solver is going to be retractable
* by pushing an undo action on the trail stack. * by pushing an undo action on the trail stack.
*/ */
solver(trail_stack& s, reslimit& lim); solver(reslimit& lim);
~solver(); ~solver();

View file

@ -7,11 +7,10 @@ namespace polysat {
struct solver_scope { struct solver_scope {
reslimit lim; reslimit lim;
trail_stack stack;
}; };
struct scoped_solver : public solver_scope, public solver { struct scoped_solver : public solver_scope, public solver {
scoped_solver(): solver(stack, lim) {} scoped_solver(): solver(lim) {}
void check() { void check() {
std::cout << check_sat() << "\n"; std::cout << check_sat() << "\n";