mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 00:26:38 +00:00
reorganize polysat functionality to use abstract solver interface
make dependency be self-contained
This commit is contained in:
parent
45f3aab5ff
commit
9bfecead73
23 changed files with 381 additions and 123 deletions
|
@ -58,7 +58,8 @@ def init_project_def():
|
|||
add_lib('proto_model', ['model', 'rewriter', 'smt_params'], 'smt/proto_model')
|
||||
add_lib('smt', ['bit_blaster', 'macros', 'normal_forms', 'cmd_context', 'proto_model', 'solver_assertions',
|
||||
'substitution', 'grobner', 'simplex', 'proofs', 'pattern', 'parser_util', 'fpa', 'lp'])
|
||||
add_lib('sat_smt', ['sat', 'euf', 'smt', 'tactic', 'solver', 'smt_params', 'bit_blaster', 'fpa', 'mbp', 'normal_forms', 'lp', 'pattern', 'qe_lite'], 'sat/smt')
|
||||
add_lib('polysat', ['util', 'dd'], 'sat/smt/polysat'),
|
||||
add_lib('sat_smt', ['sat', 'euf', 'smt', 'tactic', 'solver', 'smt_params', 'bit_blaster', 'fpa', 'mbp', 'polysat', 'normal_forms', 'lp', 'pattern', 'qe_lite'], 'sat/smt')
|
||||
add_lib('sat_tactic', ['tactic', 'sat', 'solver', 'sat_smt'], 'sat/tactic')
|
||||
add_lib('nlsat_tactic', ['nlsat', 'sat_tactic', 'arith_tactics'], 'nlsat/tactic')
|
||||
add_lib('bv_tactics', ['tactic', 'bit_blaster', 'core_tactics'], 'tactic/bv')
|
||||
|
|
|
@ -73,6 +73,7 @@ add_subdirectory(parsers/smt2)
|
|||
add_subdirectory(solver/assertions)
|
||||
add_subdirectory(ast/pattern)
|
||||
add_subdirectory(math/lp)
|
||||
add_subdirectory(sat/smt/polysat)
|
||||
add_subdirectory(sat/smt)
|
||||
add_subdirectory(sat/tactic)
|
||||
add_subdirectory(nlsat/tactic)
|
||||
|
|
|
@ -33,16 +33,9 @@ z3_add_component(sat_smt
|
|||
pb_internalize.cpp
|
||||
pb_pb.cpp
|
||||
pb_solver.cpp
|
||||
polysat_assignment.cpp
|
||||
polysat_constraints.cpp
|
||||
polysat_core.cpp
|
||||
polysat_internalize.cpp
|
||||
polysat_fi.cpp
|
||||
polysat_model.cpp
|
||||
polysat_solver.cpp
|
||||
polysat_ule.cpp
|
||||
polysat_umul_ovfl.cpp
|
||||
polysat_viable.cpp
|
||||
q_clause.cpp
|
||||
q_ematch.cpp
|
||||
q_eval.cpp
|
||||
|
|
15
src/sat/smt/polysat/CMakeLists.txt
Normal file
15
src/sat/smt/polysat/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
z3_add_component(polysat
|
||||
SOURCES
|
||||
polysat_assignment.cpp
|
||||
polysat_constraints.cpp
|
||||
polysat_core.cpp
|
||||
polysat_fi.cpp
|
||||
polysat_ule.cpp
|
||||
polysat_umul_ovfl.cpp
|
||||
polysat_viable.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
util
|
||||
dd
|
||||
smt_params
|
||||
)
|
||||
|
|
@ -12,8 +12,8 @@ Author:
|
|||
|
||||
--*/
|
||||
|
||||
#include "sat/smt/polysat_assignment.h"
|
||||
#include "sat/smt/polysat_core.h"
|
||||
#include "sat/smt/polysat/polysat_assignment.h"
|
||||
#include "sat/smt/polysat/polysat_core.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -13,7 +13,7 @@ Author:
|
|||
--*/
|
||||
#pragma once
|
||||
#include "util/scoped_ptr_vector.h"
|
||||
#include "sat/smt/polysat_types.h"
|
||||
#include "sat/smt/polysat/polysat_types.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -12,11 +12,10 @@ Author:
|
|||
|
||||
--*/
|
||||
|
||||
#include "sat/smt/polysat_core.h"
|
||||
#include "sat/smt/polysat_solver.h"
|
||||
#include "sat/smt/polysat_constraints.h"
|
||||
#include "sat/smt/polysat_ule.h"
|
||||
#include "sat/smt/polysat_umul_ovfl.h"
|
||||
#include "sat/smt/polysat/polysat_core.h"
|
||||
#include "sat/smt/polysat/polysat_constraints.h"
|
||||
#include "sat/smt/polysat/polysat_ule.h"
|
||||
#include "sat/smt/polysat/polysat_umul_ovfl.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -15,7 +15,7 @@ Author:
|
|||
|
||||
#pragma once
|
||||
#include "util/trail.h"
|
||||
#include "sat/smt/polysat_types.h"
|
||||
#include "sat/smt/polysat/polysat_types.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -29,8 +29,7 @@ polysat::core
|
|||
--*/
|
||||
|
||||
#include "params/bv_rewriter_params.hpp"
|
||||
#include "sat/smt/polysat_solver.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/smt/polysat/polysat_core.h"
|
||||
|
||||
namespace polysat {
|
||||
|
||||
|
@ -79,10 +78,10 @@ namespace polysat {
|
|||
}
|
||||
};
|
||||
|
||||
core::core(solver& s) :
|
||||
core::core(solver_interface& s) :
|
||||
s(s),
|
||||
m_viable(*this),
|
||||
m_constraints(s.get_trail_stack()),
|
||||
m_constraints(s.trail()),
|
||||
m_assignment(*this),
|
||||
m_var_queue(m_activity)
|
||||
{}
|
||||
|
@ -109,7 +108,7 @@ namespace polysat {
|
|||
m_justification.push_back(null_dependency);
|
||||
m_watch.push_back({});
|
||||
m_var_queue.mk_var_eh(v);
|
||||
s.ctx.push(mk_add_var(*this));
|
||||
s.trail().push(mk_add_var(*this));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -134,7 +133,7 @@ namespace polysat {
|
|||
add_watch(idx, vars[0]);
|
||||
if (vars.size() > 1)
|
||||
add_watch(idx, vars[1]);
|
||||
s.ctx.push(mk_add_watch(*this));
|
||||
s.trail().push(mk_add_watch(*this));
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
@ -146,7 +145,7 @@ namespace polysat {
|
|||
if (m_var_queue.empty())
|
||||
return sat::check_result::CR_DONE;
|
||||
m_var = m_var_queue.next_var();
|
||||
s.ctx.push(mk_dqueue_var(m_var, *this));
|
||||
s.trail().push(mk_dqueue_var(m_var, *this));
|
||||
switch (m_viable.find_viable(m_var, m_value)) {
|
||||
case find_t::empty:
|
||||
m_unsat_core = m_viable.explain();
|
||||
|
@ -169,11 +168,11 @@ namespace polysat {
|
|||
bool core::propagate() {
|
||||
if (m_qhead == m_prop_queue.size() && m_vqhead == m_prop_queue.size())
|
||||
return false;
|
||||
s.ctx.push(value_trail(m_qhead));
|
||||
for (; m_qhead < m_prop_queue.size() && !s.ctx.inconsistent(); ++m_qhead)
|
||||
s.trail().push(value_trail(m_qhead));
|
||||
for (; m_qhead < m_prop_queue.size() && !s.inconsistent(); ++m_qhead)
|
||||
propagate_assignment(m_prop_queue[m_qhead]);
|
||||
s.ctx.push(value_trail(m_vqhead));
|
||||
for (; m_vqhead < m_prop_queue.size() && !s.ctx.inconsistent(); ++m_vqhead)
|
||||
s.trail().push(value_trail(m_vqhead));
|
||||
for (; m_vqhead < m_prop_queue.size() && !s.inconsistent(); ++m_vqhead)
|
||||
propagate_value(m_prop_queue[m_vqhead]);
|
||||
return true;
|
||||
}
|
||||
|
@ -202,12 +201,12 @@ namespace polysat {
|
|||
return;
|
||||
if (m_var_queue.contains(v)) {
|
||||
m_var_queue.del_var_eh(v);
|
||||
s.ctx.push(mk_dqueue_var(v, *this));
|
||||
s.trail().push(mk_dqueue_var(v, *this));
|
||||
}
|
||||
m_values[v] = value;
|
||||
m_justification[v] = dep;
|
||||
m_assignment.push(v , value);
|
||||
s.ctx.push(mk_assign_var(v, *this));
|
||||
s.trail().push(mk_assign_var(v, *this));
|
||||
|
||||
// update the watch lists for pvars
|
||||
// remove constraints from m_watch[v] that have more than 2 free variables.
|
||||
|
@ -289,7 +288,7 @@ namespace polysat {
|
|||
|
||||
void core::assign_eh(unsigned index, bool sign, dependency const& dep) {
|
||||
m_prop_queue.push_back({ index, sign, dep });
|
||||
s.ctx.push(push_back_vector(m_prop_queue));
|
||||
s.trail().push(push_back_vector(m_prop_queue));
|
||||
}
|
||||
|
||||
dependency_vector core::explain_eval(signed_constraint const& sc) {
|
||||
|
@ -309,7 +308,7 @@ namespace polysat {
|
|||
}
|
||||
|
||||
trail_stack& core::trail() {
|
||||
return s.get_trail_stack();
|
||||
return s.trail();
|
||||
}
|
||||
|
||||
}
|
|
@ -20,15 +20,15 @@ Author:
|
|||
#include "util/dependency.h"
|
||||
#include "math/dd/dd_pdd.h"
|
||||
#include "sat/smt/sat_th.h"
|
||||
#include "sat/smt/polysat_types.h"
|
||||
#include "sat/smt/polysat_constraints.h"
|
||||
#include "sat/smt/polysat_viable.h"
|
||||
#include "sat/smt/polysat_assignment.h"
|
||||
#include "sat/smt/polysat/polysat_types.h"
|
||||
#include "sat/smt/polysat/polysat_constraints.h"
|
||||
#include "sat/smt/polysat/polysat_viable.h"
|
||||
#include "sat/smt/polysat/polysat_assignment.h"
|
||||
|
||||
namespace polysat {
|
||||
|
||||
class core;
|
||||
class solver;
|
||||
class solver_interface;
|
||||
|
||||
class core {
|
||||
class mk_add_var;
|
||||
|
@ -45,7 +45,7 @@ namespace polysat {
|
|||
signed_constraint sc;
|
||||
dependency d;
|
||||
};
|
||||
solver& s;
|
||||
solver_interface& s;
|
||||
viable m_viable;
|
||||
constraints m_constraints;
|
||||
assignment m_assignment;
|
||||
|
@ -87,7 +87,7 @@ namespace polysat {
|
|||
dependency_vector explain_eval(signed_constraint const& sc);
|
||||
|
||||
public:
|
||||
core(solver& s);
|
||||
core(solver_interface& s);
|
||||
|
||||
sat::check_result check();
|
||||
|
|
@ -13,11 +13,11 @@ Author:
|
|||
Nikolaj Bjorner (nbjorner) 2021-03-19
|
||||
|
||||
--*/
|
||||
#include "sat/smt/polysat_fi.h"
|
||||
#include "sat/smt/polysat_interval.h"
|
||||
#include "sat/smt/polysat_umul_ovfl.h"
|
||||
#include "sat/smt/polysat_ule.h"
|
||||
#include "sat/smt/polysat_core.h"
|
||||
#include "sat/smt/polysat/polysat_fi.h"
|
||||
#include "sat/smt/polysat/polysat_interval.h"
|
||||
#include "sat/smt/polysat/polysat_umul_ovfl.h"
|
||||
#include "sat/smt/polysat/polysat_ule.h"
|
||||
#include "sat/smt/polysat/polysat_core.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -14,9 +14,9 @@ Author:
|
|||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "sat/smt/polysat_types.h"
|
||||
#include "sat/smt/polysat_interval.h"
|
||||
#include "sat/smt/polysat_constraints.h"
|
||||
#include "sat/smt/polysat/polysat_types.h"
|
||||
#include "sat/smt/polysat/polysat_interval.h"
|
||||
#include "sat/smt/polysat/polysat_constraints.h"
|
||||
|
||||
namespace polysat {
|
||||
|
224
src/sat/smt/polysat/polysat_interval.h
Normal file
224
src/sat/smt/polysat/polysat_interval.h
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*++
|
||||
Copyright (c) 2021 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
polysat intervals
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2021-03-19
|
||||
Jakob Rath 2021-04-6
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "sat/smt/polysat/polysat_types.h"
|
||||
#include <optional>
|
||||
|
||||
namespace polysat {
|
||||
|
||||
struct pdd_bounds {
|
||||
pdd lo; ///< lower bound, inclusive
|
||||
pdd hi; ///< upper bound, exclusive
|
||||
};
|
||||
|
||||
/**
|
||||
* An interval is either [lo; hi[ (excl. upper bound) or the full domain Z_{2^w}.
|
||||
* If lo > hi, the interval wraps around, i.e., represents the union of [lo; 2^w[ and [0; hi[.
|
||||
* Membership test t \in [lo; hi[ is equivalent to t - lo < hi - lo.
|
||||
*/
|
||||
class interval {
|
||||
std::optional<pdd_bounds> m_bounds = std::nullopt;
|
||||
|
||||
interval() = default;
|
||||
interval(pdd const& lo, pdd const& hi): m_bounds({lo, hi}) {}
|
||||
public:
|
||||
static interval empty(dd::pdd_manager& m) { return proper(m.zero(), m.zero()); }
|
||||
static interval full() { return {}; }
|
||||
static interval proper(pdd const& lo, pdd const& hi) { return {lo, hi}; }
|
||||
|
||||
interval(interval const&) = default;
|
||||
interval(interval&&) = default;
|
||||
interval& operator=(interval const& other) {
|
||||
m_bounds = std::nullopt; // clear pdds first to allow changing pdd_manager (probably should change the PDD assignment operator; but for now I want to be able to detect manager confusions)
|
||||
m_bounds = other.m_bounds;
|
||||
return *this;
|
||||
}
|
||||
interval& operator=(interval&& other) {
|
||||
m_bounds = std::nullopt; // clear pdds first to allow changing pdd_manager
|
||||
m_bounds = std::move(other.m_bounds);
|
||||
return *this;
|
||||
}
|
||||
~interval() = default;
|
||||
|
||||
bool is_full() const { return !m_bounds; }
|
||||
bool is_proper() const { return !!m_bounds; }
|
||||
bool is_always_empty() const { return is_proper() && lo() == hi(); }
|
||||
pdd const& lo() const { SASSERT(is_proper()); return m_bounds->lo; }
|
||||
pdd const& hi() const { SASSERT(is_proper()); return m_bounds->hi; }
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, interval const& i) {
|
||||
if (i.is_full())
|
||||
return os << "full";
|
||||
else
|
||||
return os << "[" << i.lo() << " ; " << i.hi() << "[";
|
||||
}
|
||||
|
||||
// distance from a to b, wrapping around at mod_value.
|
||||
// basically mod(b - a, mod_value), but distance(0, mod_value, mod_value) = mod_value.
|
||||
inline rational distance(rational const& a, rational const& b, rational const& mod_value) {
|
||||
SASSERT(mod_value.is_power_of_two());
|
||||
SASSERT(0 <= a && a < mod_value);
|
||||
SASSERT(0 <= b && b <= mod_value);
|
||||
rational x = b - a;
|
||||
if (x.is_neg())
|
||||
x += mod_value;
|
||||
return x;
|
||||
}
|
||||
|
||||
class r_interval {
|
||||
rational m_lo;
|
||||
rational m_hi;
|
||||
|
||||
r_interval(rational lo, rational hi)
|
||||
: m_lo(std::move(lo)), m_hi(std::move(hi))
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
static r_interval empty() {
|
||||
return {rational::zero(), rational::zero()};
|
||||
}
|
||||
|
||||
static r_interval full() {
|
||||
return {rational(-1), rational::zero()};
|
||||
}
|
||||
|
||||
static r_interval proper(rational lo, rational hi) {
|
||||
SASSERT(0 <= lo);
|
||||
SASSERT(0 <= hi);
|
||||
return {std::move(lo), std::move(hi)};
|
||||
}
|
||||
|
||||
bool is_full() const { return m_lo.is_neg(); }
|
||||
bool is_proper() const { return !is_full(); }
|
||||
bool is_empty() const { return is_proper() && lo() == hi(); }
|
||||
rational const& lo() const { SASSERT(is_proper()); return m_lo; }
|
||||
rational const& hi() const { SASSERT(is_proper()); return m_hi; }
|
||||
|
||||
// this one also supports representing full intervals as [lo;mod_value[
|
||||
static rational len(rational const& lo, rational const& hi, rational const& mod_value) {
|
||||
SASSERT(mod_value.is_power_of_two());
|
||||
SASSERT(0 <= lo && lo < mod_value);
|
||||
SASSERT(0 <= hi && hi <= mod_value);
|
||||
SASSERT(hi != mod_value || lo == 0); // hi == mod_value only allowed when lo == 0
|
||||
rational len = hi - lo;
|
||||
if (len.is_neg())
|
||||
len += mod_value;
|
||||
return len;
|
||||
}
|
||||
|
||||
rational len(rational const& mod_value) const {
|
||||
SASSERT(is_proper());
|
||||
return len(lo(), hi(), mod_value);
|
||||
}
|
||||
|
||||
// deals only with proper intervals
|
||||
// but works with full intervals represented as [0;mod_value[ -- maybe we should just change representation of full intervals to this always
|
||||
static bool contains(rational const& lo, rational const& hi, rational const& val) {
|
||||
if (lo <= hi)
|
||||
return lo <= val && val < hi;
|
||||
else
|
||||
return val < hi || val >= lo;
|
||||
}
|
||||
|
||||
bool contains(rational const& val) const {
|
||||
if (is_full())
|
||||
return true;
|
||||
else
|
||||
return contains(lo(), hi(), val);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class eval_interval {
|
||||
interval m_symbolic;
|
||||
rational m_concrete_lo;
|
||||
rational m_concrete_hi;
|
||||
|
||||
eval_interval(interval&& i, rational const& lo_val, rational const& hi_val):
|
||||
m_symbolic(std::move(i)), m_concrete_lo(lo_val), m_concrete_hi(hi_val) {}
|
||||
public:
|
||||
static eval_interval empty(dd::pdd_manager& m) {
|
||||
return {interval::empty(m), rational::zero(), rational::zero()};
|
||||
}
|
||||
|
||||
static eval_interval full() {
|
||||
return {interval::full(), rational::zero(), rational::zero()};
|
||||
}
|
||||
|
||||
static eval_interval proper(pdd const& lo, rational const& lo_val, pdd const& hi, rational const& hi_val) {
|
||||
SASSERT(0 <= lo_val && lo_val <= lo.manager().max_value());
|
||||
SASSERT(0 <= hi_val && hi_val <= hi.manager().max_value());
|
||||
return {interval::proper(lo, hi), lo_val, hi_val};
|
||||
}
|
||||
|
||||
bool is_full() const { return m_symbolic.is_full(); }
|
||||
bool is_proper() const { return m_symbolic.is_proper(); }
|
||||
bool is_always_empty() const { return m_symbolic.is_always_empty(); }
|
||||
bool is_currently_empty() const { return is_proper() && lo_val() == hi_val(); }
|
||||
interval const& symbolic() const { return m_symbolic; }
|
||||
pdd const& lo() const { return m_symbolic.lo(); }
|
||||
pdd const& hi() const { return m_symbolic.hi(); }
|
||||
rational const& lo_val() const { SASSERT(is_proper()); return m_concrete_lo; }
|
||||
rational const& hi_val() const { SASSERT(is_proper()); return m_concrete_hi; }
|
||||
|
||||
rational current_len() const {
|
||||
SASSERT(is_proper());
|
||||
return mod(hi_val() - lo_val(), lo().manager().two_to_N());
|
||||
}
|
||||
|
||||
bool currently_contains(rational const& val) const {
|
||||
if (is_full())
|
||||
return true;
|
||||
else if (lo_val() <= hi_val())
|
||||
return lo_val() <= val && val < hi_val();
|
||||
else
|
||||
return val < hi_val() || val >= lo_val();
|
||||
}
|
||||
|
||||
bool currently_contains(eval_interval const& other) const {
|
||||
if (is_full())
|
||||
return true;
|
||||
if (other.is_full())
|
||||
return false;
|
||||
// lo <= lo' <= hi' <= hi'
|
||||
if (lo_val() <= other.lo_val() && other.lo_val() <= other.hi_val() && other.hi_val() <= hi_val())
|
||||
return true;
|
||||
if (lo_val() <= hi_val())
|
||||
return false;
|
||||
// hi < lo <= lo' <= hi'
|
||||
if (lo_val() <= other.lo_val() && other.lo_val() <= other.hi_val())
|
||||
return true;
|
||||
// lo' <= hi' <= hi < lo
|
||||
if (other.lo_val() <= other.hi_val() && other.hi_val() <= hi_val())
|
||||
return true;
|
||||
// hi' <= hi < lo <= lo'
|
||||
if (other.hi_val() <= hi_val() && lo_val() <= other.lo_val())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}; // class eval_interval
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, eval_interval const& i) {
|
||||
if (i.is_full())
|
||||
return os << "full";
|
||||
else {
|
||||
auto& m = i.hi().manager();
|
||||
return os << i.symbolic() << " := [" << m.normalize(i.lo_val()) << ";" << m.normalize(i.hi_val()) << "[";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
67
src/sat/smt/polysat/polysat_types.h
Normal file
67
src/sat/smt/polysat/polysat_types.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*++
|
||||
Copyright (c) 2021 Microsoft Corporation
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2021-03-19
|
||||
Jakob Rath 2021-04-06
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
#include "math/dd/dd_pdd.h"
|
||||
#include "util/trail.h"
|
||||
#include "util/sat_literal.h"
|
||||
|
||||
namespace polysat {
|
||||
|
||||
using pdd = dd::pdd;
|
||||
using pvar = unsigned;
|
||||
using theory_var = unsigned;
|
||||
|
||||
using pvar_vector = unsigned_vector;
|
||||
inline const pvar null_var = UINT_MAX;
|
||||
|
||||
|
||||
|
||||
class dependency {
|
||||
std::variant<sat::literal, std::pair<theory_var, theory_var>> m_data;
|
||||
unsigned m_level;
|
||||
public:
|
||||
dependency(sat::literal lit, unsigned level) : m_data(lit), m_level(level) {}
|
||||
dependency(theory_var v1, theory_var v2, unsigned level) : m_data(std::make_pair(v1, v2)), m_level(level) {}
|
||||
bool is_null() const { return is_literal() && *std::get_if<sat::literal>(&m_data) == sat::null_literal; }
|
||||
bool is_literal() const { return std::holds_alternative<sat::literal>(m_data); }
|
||||
sat::literal literal() const { SASSERT(is_literal()); return *std::get_if<sat::literal>(&m_data); }
|
||||
std::pair<theory_var, theory_var> eq() const { SASSERT(!is_literal()); return *std::get_if<std::pair<theory_var, theory_var>>(&m_data); }
|
||||
unsigned level() const { return m_level; }
|
||||
};
|
||||
|
||||
inline const dependency null_dependency = dependency(sat::null_literal, UINT_MAX);
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, dependency d) {
|
||||
if (d.is_null())
|
||||
return out << "null";
|
||||
else if (d.is_literal())
|
||||
return out << d.literal() << "@" << d.level();
|
||||
else
|
||||
return out << "v" << d.eq().first << " == v" << d.eq().second << "@" << d.level();
|
||||
}
|
||||
|
||||
using dependency_vector = vector<dependency>;
|
||||
|
||||
class signed_constraint;
|
||||
|
||||
class solver_interface {
|
||||
public:
|
||||
virtual void add_eq_literal(pvar v, rational const& val) = 0;
|
||||
virtual void set_conflict(dependency_vector const& core) = 0;
|
||||
virtual void set_lemma(vector<signed_constraint> const& lemma, unsigned level, dependency_vector const& core) = 0;
|
||||
virtual dependency propagate(signed_constraint sc, dependency_vector const& deps) = 0;
|
||||
virtual void propagate(dependency const& d, bool sign, dependency_vector const& deps) = 0;
|
||||
virtual trail_stack& trail() = 0;
|
||||
virtual bool inconsistent() const = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -70,8 +70,8 @@ Useful lemmas:
|
|||
|
||||
--*/
|
||||
|
||||
#include "sat/smt/polysat_constraints.h"
|
||||
#include "sat/smt/polysat_ule.h"
|
||||
#include "sat/smt/polysat/polysat_constraints.h"
|
||||
#include "sat/smt/polysat/polysat_ule.h"
|
||||
|
||||
#define LOG(_msg_) verbose_stream() << _msg_ << "\n"
|
||||
|
|
@ -12,9 +12,8 @@ Author:
|
|||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "sat/smt/polysat_ule.h"
|
||||
#include "sat/smt/polysat_assignment.h"
|
||||
#include "sat/smt/polysat_constraints.h"
|
||||
#include "sat/smt/polysat/polysat_assignment.h"
|
||||
#include "sat/smt/polysat/polysat_constraints.h"
|
||||
|
||||
|
||||
namespace polysat {
|
|
@ -10,9 +10,9 @@ Author:
|
|||
Jakob Rath, Nikolaj Bjorner (nbjorner) 2021-12-09
|
||||
|
||||
--*/
|
||||
#include "sat/smt/polysat_constraints.h"
|
||||
#include "sat/smt/polysat_assignment.h"
|
||||
#include "sat/smt/polysat_umul_ovfl.h"
|
||||
#include "sat/smt/polysat/polysat_constraints.h"
|
||||
#include "sat/smt/polysat/polysat_assignment.h"
|
||||
#include "sat/smt/polysat/polysat_umul_ovfl.h"
|
||||
|
||||
|
||||
namespace polysat {
|
|
@ -11,7 +11,7 @@ Author:
|
|||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "sat/smt/polysat_constraints.h"
|
||||
#include "sat/smt/polysat/polysat_constraints.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -18,8 +18,8 @@ Notes:
|
|||
|
||||
#include "util/debug.h"
|
||||
#include "util/log.h"
|
||||
#include "sat/smt/polysat_viable.h"
|
||||
#include "sat/smt/polysat_core.h"
|
||||
#include "sat/smt/polysat/polysat_viable.h"
|
||||
#include "sat/smt/polysat/polysat_core.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -21,8 +21,8 @@ Author:
|
|||
#include "util/map.h"
|
||||
#include "util/small_object_allocator.h"
|
||||
|
||||
#include "sat/smt/polysat_types.h"
|
||||
#include "sat/smt/polysat_fi.h"
|
||||
#include "sat/smt/polysat/polysat_types.h"
|
||||
#include "sat/smt/polysat/polysat_fi.h"
|
||||
|
||||
namespace polysat {
|
||||
|
|
@ -27,8 +27,8 @@ The result of polysat::core::check is one of:
|
|||
#include "ast/euf/euf_bv_plugin.h"
|
||||
#include "sat/smt/polysat_solver.h"
|
||||
#include "sat/smt/euf_solver.h"
|
||||
#include "sat/smt/polysat_ule.h"
|
||||
#include "sat/smt/polysat_umul_ovfl.h"
|
||||
#include "sat/smt/polysat/polysat_ule.h"
|
||||
#include "sat/smt/polysat/polysat_umul_ovfl.h"
|
||||
|
||||
|
||||
namespace polysat {
|
||||
|
@ -82,7 +82,7 @@ namespace polysat {
|
|||
core.push_back(d.literal());
|
||||
}
|
||||
else {
|
||||
auto const [v1, v2] = m_var_eqs[d.index()];
|
||||
auto const [v1, v2] = d.eq();
|
||||
euf::enode* const n1 = var2enode(v1);
|
||||
euf::enode* const n2 = var2enode(v2);
|
||||
VERIFY(n1->get_root() == n2->get_root());
|
||||
|
@ -151,7 +151,7 @@ namespace polysat {
|
|||
auto sc = m_core.eq(p, q);
|
||||
m_var_eqs.setx(m_var_eqs_head, {v1, v2}, {v1, v2});
|
||||
ctx.push(value_trail<unsigned>(m_var_eqs_head));
|
||||
auto d = dependency(m_var_eqs_head, s().scope_lvl());
|
||||
auto d = dependency(v1, v2, s().scope_lvl());
|
||||
unsigned index = m_core.register_constraint(sc, d);
|
||||
m_core.assign_eh(index, false, d);
|
||||
m_var_eqs_head++;
|
||||
|
@ -192,7 +192,7 @@ namespace polysat {
|
|||
ctx.propagate(lit, ex);
|
||||
}
|
||||
else if (sign) {
|
||||
auto const [v1, v2] = m_var_eqs[d.index()];
|
||||
auto const [v1, v2] = d.eq();
|
||||
// equalities are always asserted so a negative propagation is a conflict.
|
||||
auto n1 = var2enode(v1);
|
||||
auto n2 = var2enode(v2);
|
||||
|
@ -202,6 +202,14 @@ namespace polysat {
|
|||
}
|
||||
}
|
||||
|
||||
bool solver::inconsistent() const {
|
||||
return s().inconsistent();
|
||||
}
|
||||
|
||||
trail_stack& solver::trail() {
|
||||
return ctx.get_trail_stack();
|
||||
}
|
||||
|
||||
void solver::add_lemma(vector<signed_constraint> const& lemma) {
|
||||
sat::literal_vector lits;
|
||||
for (auto sc : lemma)
|
||||
|
|
|
@ -18,7 +18,7 @@ Author:
|
|||
|
||||
#include "sat/smt/sat_th.h"
|
||||
#include "math/dd/dd_pdd.h"
|
||||
#include "sat/smt/polysat_core.h"
|
||||
#include "sat/smt/polysat/polysat_core.h"
|
||||
|
||||
namespace euf {
|
||||
class solver;
|
||||
|
@ -27,7 +27,7 @@ namespace euf {
|
|||
namespace polysat {
|
||||
|
||||
|
||||
class solver : public euf::th_euf_solver {
|
||||
class solver : public euf::th_euf_solver, public solver_interface {
|
||||
typedef euf::theory_var theory_var;
|
||||
typedef euf::theory_id theory_id;
|
||||
typedef sat::literal literal;
|
||||
|
@ -53,8 +53,6 @@ namespace polysat {
|
|||
expr* get_hint(euf::solver& s) const override { return nullptr; }
|
||||
};
|
||||
|
||||
friend class core;
|
||||
|
||||
bv_util bv;
|
||||
arith_util m_autil;
|
||||
stats m_stats;
|
||||
|
@ -128,12 +126,14 @@ namespace polysat {
|
|||
void internalize_set(euf::theory_var v, pdd const& p);
|
||||
|
||||
// callbacks from core
|
||||
void add_eq_literal(pvar v, rational const& val);
|
||||
void set_conflict(dependency_vector const& core);
|
||||
void set_lemma(vector<signed_constraint> const& lemma, unsigned level, dependency_vector const& core);
|
||||
dependency propagate(signed_constraint sc, dependency_vector const& deps);
|
||||
void propagate(dependency const& d, bool sign, dependency_vector const& deps);
|
||||
|
||||
void add_eq_literal(pvar v, rational const& val) override;
|
||||
void set_conflict(dependency_vector const& core) override;
|
||||
void set_lemma(vector<signed_constraint> const& lemma, unsigned level, dependency_vector const& core) override;
|
||||
dependency propagate(signed_constraint sc, dependency_vector const& deps) override;
|
||||
void propagate(dependency const& d, bool sign, dependency_vector const& deps) override;
|
||||
trail_stack& trail() override;
|
||||
bool inconsistent() const override;
|
||||
|
||||
void add_lemma(vector<signed_constraint> const& lemma);
|
||||
|
||||
std::pair<sat::literal_vector, euf::enode_pair_vector> explain_deps(dependency_vector const& deps);
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/*++
|
||||
Copyright (c) 2021 Microsoft Corporation
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2021-03-19
|
||||
Jakob Rath 2021-04-06
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "math/dd/dd_pdd.h"
|
||||
#include "util/sat_literal.h"
|
||||
|
||||
namespace polysat {
|
||||
|
||||
using pdd = dd::pdd;
|
||||
using pvar = unsigned;
|
||||
|
||||
using pvar_vector = unsigned_vector;
|
||||
inline const pvar null_var = UINT_MAX;
|
||||
|
||||
|
||||
class dependency {
|
||||
unsigned m_index;
|
||||
unsigned m_level;
|
||||
public:
|
||||
dependency(sat::literal lit, unsigned level) : m_index(2 * lit.index()), m_level(level) {}
|
||||
dependency(unsigned var_idx, unsigned level) : m_index(1 + 2 * var_idx), m_level(level) {}
|
||||
bool is_null() const { return m_level == UINT_MAX; }
|
||||
bool is_literal() const { return m_index % 2 == 0; }
|
||||
sat::literal literal() const { SASSERT(is_literal()); return sat::to_literal(m_index / 2); }
|
||||
unsigned index() const { SASSERT(!is_literal()); return (m_index - 1) / 2; }
|
||||
unsigned level() const { return m_level; }
|
||||
};
|
||||
|
||||
inline const dependency null_dependency = dependency(0, UINT_MAX);
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, dependency d) {
|
||||
if (d.is_literal())
|
||||
return out << d.literal() << "@" << d.level();
|
||||
else
|
||||
return out << "v" << d.index() << "@" << d.level();
|
||||
}
|
||||
|
||||
using dependency_vector = vector<dependency>;
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue