3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 17:45:32 +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:
Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/

View file

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

View file

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

View file

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

View file

@ -12,6 +12,7 @@ Abstract:
Author:
Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/
@ -42,6 +43,7 @@ namespace polysat {
for (unsigned k = size(v); k-- > 0; )
value &= val.get_bit(k) ? m_bdd.mk_var(k) : m_bdd.mk_nvar(k);
SASSERT((value && !m_viable[v]).is_false());
push_viable(v);
m_viable[v] &= !value;
}
@ -68,14 +70,8 @@ namespace polysat {
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):
m_trail(s),
solver::solver(reslimit& lim):
m_lim(lim),
m_bdd(1000),
m_dm(m_value_manager, m_alloc),
@ -132,7 +128,7 @@ namespace polysat {
m_activity.push_back(0);
m_vars.push_back(sz2pdd(sz).mk_var(v));
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);
return v;
}
@ -192,7 +188,7 @@ namespace polysat {
}
void solver::propagate() {
m_trail.push(value_trail(m_qhead));
push_qhead();
while (can_propagate())
propagate(m_search[m_qhead++].first);
}
@ -220,15 +216,51 @@ namespace polysat {
void solver::push_level() {
++m_level;
m_trail.push_scope();
m_trail.push_back(trail_instr_t::inc_level_i);
}
void solver::pop_levels(unsigned num_levels) {
m_trail.pop_scope(num_levels);
m_level -= num_levels;
while (num_levels > 0) {
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_redundant);
pop_assignment();
}
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) {
auto const& vars = c.vars();
if (vars.size() > 0)
@ -327,6 +337,7 @@ namespace polysat {
SASSERT(is_viable(v, val));
m_value[v] = val;
m_search.push_back(std::make_pair(v, val));
m_trail.push_back(trail_instr_t::assign_i);
m_justification[v] = j;
}
@ -473,7 +484,7 @@ namespace polysat {
if (!c)
return;
SASSERT(m_conflict_level <= m_justification[v].level());
m_cjust[v].push_back(c);
push_cjust(v, c);
add_lemma(c);
}
@ -490,11 +501,14 @@ namespace polysat {
rational val = m_value[v];
SASSERT(m_justification[v].is_decision());
bdd viable = m_viable[v];
m_conflict.append(m_cjust[v]);
constraints just(m_cjust[v]);
backjump(m_justification[v].level()-1);
SASSERT(m_cjust[v].empty());
m_cjust[v].append(m_conflict);
for (unsigned i = m_cjust[v].size(); i < just.size(); ++i)
push_cjust(v, just[i]);
for (constraint* c : m_conflict)
push_cjust(v, c);
m_conflict.reset();
push_viable(v);
m_viable[v] = viable;
add_non_viable(v, val);
m_free_vars.del_var_eh(v);

View file

@ -12,6 +12,7 @@ Abstract:
Author:
Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
--*/
#pragma once
@ -19,6 +20,7 @@ Author:
#include "util/statistics.h"
#include "math/polysat/constraint.h"
#include "math/polysat/justification.h"
#include "math/polysat/trail.h"
namespace polysat {
@ -36,7 +38,6 @@ namespace polysat {
typedef ptr_vector<constraint> constraints;
trail_stack& m_trail;
reslimit& m_lim;
scoped_ptr_vector<dd::pdd_manager> m_pdd;
dd::bdd_manager m_bdd;
@ -68,9 +69,35 @@ namespace polysat {
unsigned m_qhead { 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.
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]; }
/**
* check if value is viable according to m_viable.
@ -105,7 +132,6 @@ namespace polysat {
* undo trail operations for backtracking.
* Each struct is a subclass of trail and implements undo().
*/
struct t_del_var;
void del_var();
@ -113,7 +139,6 @@ namespace polysat {
void push_level();
void pop_levels(unsigned num_levels);
void pop_assignment();
void pop_constraints(scoped_ptr_vector<constraint>& cs);
void assign_core(pvar v, rational const& val, justification const& j);
@ -157,7 +182,6 @@ namespace polysat {
void revert_decision(pvar v);
void learn_lemma(pvar v, constraint* c);
void backjump(unsigned new_level);
void undo_var(pvar v);
void add_lemma(constraint* c);
bool invariant();
@ -170,7 +194,7 @@ namespace polysat {
* every update to the solver is going to be retractable
* by pushing an undo action on the trail stack.
*/
solver(trail_stack& s, reslimit& lim);
solver(reslimit& lim);
~solver();

View file

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