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:
parent
2eadcd586a
commit
549b984c88
7 changed files with 87 additions and 46 deletions
|
@ -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
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue