mirror of
https://github.com/Z3Prover/z3
synced 2025-08-29 06:28:57 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
a412a554eb
21 changed files with 334 additions and 86 deletions
|
@ -77,6 +77,7 @@ namespace sat {
|
|||
m_burst_search = p.burst_search();
|
||||
|
||||
m_max_conflicts = p.max_conflicts();
|
||||
m_num_parallel = p.parallel_threads();
|
||||
|
||||
// These parameters are not exposed
|
||||
m_simplify_mult1 = _p.get_uint("simplify_mult1", 300);
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace sat {
|
|||
unsigned m_random_seed;
|
||||
unsigned m_burst_search;
|
||||
unsigned m_max_conflicts;
|
||||
unsigned m_num_parallel;
|
||||
|
||||
unsigned m_simplify_mult1;
|
||||
double m_simplify_mult2;
|
||||
|
|
|
@ -23,7 +23,7 @@ Notes:
|
|||
|
||||
namespace sat {
|
||||
|
||||
mus::mus(solver& s):s(s), m_is_active(false),m_restart(0), m_max_restarts(0) {}
|
||||
mus::mus(solver& s):s(s), m_is_active(false), m_max_num_restarts(UINT_MAX) {}
|
||||
|
||||
mus::~mus() {}
|
||||
|
||||
|
@ -31,8 +31,6 @@ namespace sat {
|
|||
m_core.reset();
|
||||
m_mus.reset();
|
||||
m_model.reset();
|
||||
m_max_restarts = (s.m_stats.m_restart - m_restart) + 10;
|
||||
m_restart = s.m_stats.m_restart;
|
||||
}
|
||||
|
||||
void mus::set_core() {
|
||||
|
@ -49,12 +47,12 @@ namespace sat {
|
|||
}
|
||||
|
||||
lbool mus::operator()() {
|
||||
m_max_num_restarts = s.m_config.m_core_minimize_partial ? s.num_restarts() + 10 : UINT_MAX;
|
||||
flet<bool> _disable_min(s.m_config.m_core_minimize, false);
|
||||
flet<bool> _is_active(m_is_active, true);
|
||||
IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";);
|
||||
IF_VERBOSE(3, verbose_stream() << "(sat.mus size: " << s.get_core().size() << " core: [" << s.get_core() << "])\n";);
|
||||
reset();
|
||||
lbool r = mus1();
|
||||
m_restart = s.m_stats.m_restart;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -63,13 +61,13 @@ namespace sat {
|
|||
TRACE("sat", tout << "old core: " << s.get_core() << "\n";);
|
||||
literal_vector& core = get_core();
|
||||
literal_vector& mus = m_mus;
|
||||
if (core.size() > 64) {
|
||||
if (!minimize_partial && core.size() > 64) {
|
||||
return mus2();
|
||||
}
|
||||
unsigned delta_time = 0;
|
||||
unsigned core_miss = 0;
|
||||
while (!core.empty()) {
|
||||
IF_VERBOSE(3, verbose_stream() << "(opt.mus reducing core: " << core.size() << " mus: " << mus.size() << ")\n";);
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat.mus num-to-process: " << core.size() << " mus: " << mus.size();
|
||||
if (minimize_partial) verbose_stream() << " max-restarts: " << m_max_num_restarts;
|
||||
verbose_stream() << ")\n";);
|
||||
TRACE("sat",
|
||||
tout << "core: " << core << "\n";
|
||||
tout << "mus: " << mus << "\n";);
|
||||
|
@ -78,34 +76,35 @@ namespace sat {
|
|||
set_core();
|
||||
return l_undef;
|
||||
}
|
||||
if (minimize_partial && 3*delta_time > core.size() && core.size() < mus.size()) {
|
||||
break;
|
||||
}
|
||||
unsigned num_literals = core.size() + mus.size();
|
||||
if (num_literals <= 2) {
|
||||
// IF_VERBOSE(0, verbose_stream() << "num literals: " << core << " " << mus << "\n";);
|
||||
break;
|
||||
}
|
||||
if (s.m_config.m_core_minimize_partial && s.m_stats.m_restart - m_restart > m_max_restarts) {
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat restart budget exceeded)\n";);
|
||||
set_core();
|
||||
return l_true;
|
||||
}
|
||||
|
||||
literal lit = core.back();
|
||||
core.pop_back();
|
||||
lbool is_sat;
|
||||
{
|
||||
flet<unsigned> _restart_bound(s.m_config.m_restart_max, m_max_num_restarts);
|
||||
scoped_append _sa(mus, core);
|
||||
mus.push_back(~lit);
|
||||
is_sat = s.check(mus.size(), mus.c_ptr());
|
||||
TRACE("sat", tout << "mus: " << mus << "\n";);
|
||||
}
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat.mus " << is_sat << ")\n";);
|
||||
switch (is_sat) {
|
||||
case l_undef:
|
||||
core.push_back(lit);
|
||||
set_core();
|
||||
return l_undef;
|
||||
if (!s.canceled()) {
|
||||
// treat restart max as sat, so literal is in the mus
|
||||
mus.push_back(lit);
|
||||
}
|
||||
else {
|
||||
core.push_back(lit);
|
||||
set_core();
|
||||
return l_undef;
|
||||
}
|
||||
break;
|
||||
case l_true: {
|
||||
SASSERT(value_at(lit, s.get_model()) == l_false);
|
||||
mus.push_back(lit);
|
||||
|
@ -115,11 +114,9 @@ namespace sat {
|
|||
case l_false:
|
||||
literal_vector const& new_core = s.get_core();
|
||||
if (new_core.contains(~lit)) {
|
||||
IF_VERBOSE(3, verbose_stream() << "miss core " << lit << "\n";);
|
||||
++core_miss;
|
||||
IF_VERBOSE(3, verbose_stream() << "(sat.mus unit reduction, literal is in both cores " << lit << ")\n";);
|
||||
}
|
||||
else {
|
||||
core_miss = 0;
|
||||
TRACE("sat", tout << "core: " << new_core << " mus: " << mus << "\n";);
|
||||
core.reset();
|
||||
for (unsigned i = 0; i < new_core.size(); ++i) {
|
||||
|
@ -131,14 +128,6 @@ namespace sat {
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned new_num_literals = core.size() + mus.size();
|
||||
if (new_num_literals == num_literals) {
|
||||
delta_time++;
|
||||
}
|
||||
else {
|
||||
delta_time = 0;
|
||||
}
|
||||
}
|
||||
set_core();
|
||||
IF_VERBOSE(3, verbose_stream() << "(sat.mus.new " << s.m_core << ")\n";);
|
||||
|
@ -159,13 +148,9 @@ namespace sat {
|
|||
|
||||
lbool mus::qx(literal_set& assignment, literal_set& support, bool has_support) {
|
||||
lbool is_sat = l_true;
|
||||
if (s.m_config.m_core_minimize_partial && s.m_stats.m_restart - m_restart > m_max_restarts) {
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat restart budget exceeded)\n";);
|
||||
return l_true;
|
||||
}
|
||||
if (has_support) {
|
||||
scoped_append _sa(m_mus, support.to_vector());
|
||||
is_sat = s.check(m_mus.size(), m_mus.c_ptr());
|
||||
is_sat = s.check(m_mus.size(), m_mus.c_ptr());
|
||||
switch (is_sat) {
|
||||
case l_false: {
|
||||
literal_set core(s.get_core());
|
||||
|
@ -173,7 +158,7 @@ namespace sat {
|
|||
assignment.reset();
|
||||
return l_true;
|
||||
}
|
||||
case l_undef:
|
||||
case l_undef:
|
||||
return l_undef;
|
||||
case l_true:
|
||||
update_model();
|
||||
|
|
|
@ -26,8 +26,7 @@ namespace sat {
|
|||
literal_vector m_mus;
|
||||
bool m_is_active;
|
||||
model m_model; // model obtained during minimal unsat core
|
||||
unsigned m_restart;
|
||||
unsigned m_max_restarts;
|
||||
unsigned m_max_num_restarts;
|
||||
|
||||
|
||||
public:
|
||||
|
|
45
src/sat/sat_par.cpp
Normal file
45
src/sat/sat_par.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_par.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Utilities for parallel SAT solving.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-1-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "sat_par.h"
|
||||
|
||||
|
||||
namespace sat {
|
||||
|
||||
par::par() {}
|
||||
|
||||
void par::exchange(literal_vector const& in, unsigned& limit, literal_vector& out) {
|
||||
#pragma omp critical (par_solver)
|
||||
{
|
||||
if (limit < m_units.size()) {
|
||||
// this might repeat some literals.
|
||||
out.append(m_units.size() - limit, m_units.c_ptr() + limit);
|
||||
}
|
||||
for (unsigned i = 0; i < in.size(); ++i) {
|
||||
literal lit = in[i];
|
||||
if (!m_unit_set.contains(lit.index())) {
|
||||
m_unit_set.insert(lit.index());
|
||||
m_units.push_back(lit);
|
||||
}
|
||||
}
|
||||
limit = m_units.size();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
39
src/sat/sat_par.h
Normal file
39
src/sat/sat_par.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*++
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
sat_par.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Utilities for parallel SAT solving.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2017-1-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef SAT_PAR_H_
|
||||
#define SAT_PAR_H_
|
||||
|
||||
#include"sat_types.h"
|
||||
#include"hashtable.h"
|
||||
#include"map.h"
|
||||
|
||||
namespace sat {
|
||||
|
||||
class par {
|
||||
typedef hashtable<unsigned, u_hash, u_eq> index_set;
|
||||
literal_vector m_units;
|
||||
index_set m_unit_set;
|
||||
public:
|
||||
par();
|
||||
void exchange(literal_vector const& in, unsigned& limit, literal_vector& out);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -22,4 +22,5 @@ def_module_params('sat',
|
|||
('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'),
|
||||
('parallel_threads', UINT, 1, 'number of parallel threads to use'),
|
||||
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks')))
|
||||
|
|
|
@ -896,7 +896,7 @@ namespace sat {
|
|||
unsigned idx = l.index();
|
||||
if (m_queue.contains(idx))
|
||||
m_queue.decreased(idx);
|
||||
else
|
||||
else
|
||||
m_queue.insert(idx);
|
||||
}
|
||||
literal next() { SASSERT(!empty()); return to_literal(m_queue.erase_min()); }
|
||||
|
@ -918,16 +918,19 @@ namespace sat {
|
|||
}
|
||||
|
||||
void insert(literal l) {
|
||||
bool_var v = l.var();
|
||||
if (s.is_external(v) || s.was_eliminated(v))
|
||||
return;
|
||||
m_queue.insert(l);
|
||||
}
|
||||
|
||||
bool process_var(bool_var v) {
|
||||
return !s.is_external(v) && !s.was_eliminated(v);
|
||||
}
|
||||
|
||||
void operator()(unsigned num_vars) {
|
||||
for (bool_var v = 0; v < num_vars; v++) {
|
||||
insert(literal(v, false));
|
||||
insert(literal(v, true));
|
||||
if (process_var(v)) {
|
||||
insert(literal(v, false));
|
||||
insert(literal(v, true));
|
||||
}
|
||||
}
|
||||
while (!m_queue.empty()) {
|
||||
s.checkpoint();
|
||||
|
@ -941,9 +944,9 @@ namespace sat {
|
|||
void process(literal l) {
|
||||
TRACE("blocked_clause", tout << "processing: " << l << "\n";);
|
||||
model_converter::entry * new_entry = 0;
|
||||
if (s.is_external(l.var()) || s.was_eliminated(l.var()))
|
||||
if (!process_var(l.var())) {
|
||||
return;
|
||||
|
||||
}
|
||||
{
|
||||
m_to_remove.reset();
|
||||
{
|
||||
|
@ -963,8 +966,10 @@ namespace sat {
|
|||
mc.insert(*new_entry, c);
|
||||
unsigned sz = c.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (c[i] != l)
|
||||
m_queue.decreased(~c[i]);
|
||||
literal lit = c[i];
|
||||
if (lit != l && process_var(lit.var())) {
|
||||
m_queue.decreased(~lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
s.unmark_all(c);
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace sat {
|
|||
m_rlimit(l),
|
||||
m_config(p),
|
||||
m_ext(ext),
|
||||
m_par(0),
|
||||
m_cleaner(*this),
|
||||
m_simplifier(*this, p),
|
||||
m_scc(*this, p),
|
||||
|
@ -72,6 +73,8 @@ namespace sat {
|
|||
|
||||
void solver::copy(solver const & src) {
|
||||
SASSERT(m_mc.empty() && src.m_mc.empty());
|
||||
SASSERT(scope_lvl() == 0);
|
||||
SASSERT(src.scope_lvl() == 0);
|
||||
// create new vars
|
||||
if (num_vars() < src.num_vars()) {
|
||||
for (bool_var v = num_vars(); v < src.num_vars(); v++) {
|
||||
|
@ -81,19 +84,25 @@ namespace sat {
|
|||
VERIFY(v == mk_var(ext, dvar));
|
||||
}
|
||||
}
|
||||
unsigned sz = src.scope_lvl() == 0 ? src.m_trail.size() : src.m_scopes[0].m_trail_lim;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
assign(src.m_trail[i], justification());
|
||||
}
|
||||
|
||||
{
|
||||
// copy binary clauses
|
||||
vector<watch_list>::const_iterator it = src.m_watches.begin();
|
||||
vector<watch_list>::const_iterator end = src.m_watches.begin();
|
||||
for (unsigned l_idx = 0; it != end; ++it, ++l_idx) {
|
||||
watch_list const & wlist = *it;
|
||||
unsigned sz = src.m_watches.size();
|
||||
for (unsigned l_idx = 0; l_idx < sz; ++l_idx) {
|
||||
literal l = ~to_literal(l_idx);
|
||||
watch_list::const_iterator it2 = wlist.begin();
|
||||
watch_list::const_iterator end2 = wlist.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
if (!it2->is_binary_non_learned_clause())
|
||||
watch_list const & wlist = src.m_watches[l_idx];
|
||||
watch_list::const_iterator it = wlist.begin();
|
||||
watch_list::const_iterator end = wlist.end();
|
||||
for (; it != end; ++it) {
|
||||
if (!it->is_binary_non_learned_clause())
|
||||
continue;
|
||||
literal l2 = it->get_literal();
|
||||
if (l.index() > l2.index())
|
||||
continue;
|
||||
literal l2 = it2->get_literal();
|
||||
mk_clause_core(l, l2);
|
||||
}
|
||||
}
|
||||
|
@ -711,6 +720,9 @@ namespace sat {
|
|||
pop_to_base_level();
|
||||
IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";);
|
||||
SASSERT(scope_lvl() == 0);
|
||||
if (m_config.m_num_parallel > 0 && !m_par) {
|
||||
return check_par(num_lits, lits);
|
||||
}
|
||||
#ifdef CLONE_BEFORE_SOLVING
|
||||
if (m_mc.empty()) {
|
||||
m_clone = alloc(solver, m_params, 0 /* do not clone extension */);
|
||||
|
@ -759,6 +771,7 @@ namespace sat {
|
|||
|
||||
restart();
|
||||
simplify_problem();
|
||||
exchange_par();
|
||||
if (check_inconsistent()) return l_false;
|
||||
gc();
|
||||
|
||||
|
@ -774,6 +787,121 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
|
||||
enum par_exception_kind {
|
||||
DEFAULT_EX,
|
||||
ERROR_EX
|
||||
};
|
||||
|
||||
lbool solver::check_par(unsigned num_lits, literal const* lits) {
|
||||
int num_threads = static_cast<int>(m_config.m_num_parallel);
|
||||
scoped_limits scoped_rlimit(rlimit());
|
||||
vector<reslimit> rlims(num_threads);
|
||||
ptr_vector<sat::solver> solvers(num_threads);
|
||||
sat::par par;
|
||||
for (int i = 0; i < num_threads; ++i) {
|
||||
m_params.set_uint("random_seed", i);
|
||||
solvers[i] = alloc(sat::solver, m_params, rlims[i], 0);
|
||||
solvers[i]->copy(*this);
|
||||
solvers[i]->set_par(&par);
|
||||
scoped_rlimit.push_child(&solvers[i]->rlimit());
|
||||
}
|
||||
int finished_id = -1;
|
||||
std::string ex_msg;
|
||||
par_exception_kind ex_kind;
|
||||
unsigned error_code = 0;
|
||||
lbool result = l_undef;
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < num_threads; ++i) {
|
||||
try {
|
||||
lbool r = solvers[i]->check(num_lits, lits);
|
||||
bool first = false;
|
||||
#pragma omp critical (par_solver)
|
||||
{
|
||||
if (finished_id == UINT_MAX) {
|
||||
finished_id = i;
|
||||
first = true;
|
||||
result = r;
|
||||
}
|
||||
}
|
||||
if (first) {
|
||||
if (r == l_true) {
|
||||
set_model(solvers[i]->get_model());
|
||||
}
|
||||
else if (r == l_false) {
|
||||
m_core.reset();
|
||||
m_core.append(solvers[i]->get_core());
|
||||
}
|
||||
for (int j = 0; j < num_threads; ++j) {
|
||||
if (i != j) {
|
||||
rlims[j].cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (z3_error & err) {
|
||||
if (i == 0) {
|
||||
error_code = err.error_code();
|
||||
ex_kind = ERROR_EX;
|
||||
}
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
if (i == 0) {
|
||||
ex_msg = ex.msg();
|
||||
ex_kind = DEFAULT_EX;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < num_threads; ++i) {
|
||||
dealloc(solvers[i]);
|
||||
}
|
||||
if (finished_id == -1) {
|
||||
switch (ex_kind) {
|
||||
case ERROR_EX: throw z3_error(error_code);
|
||||
default: throw default_exception(ex_msg.c_str());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
\brief import lemmas/units from parallel sat solvers.
|
||||
*/
|
||||
void solver::exchange_par() {
|
||||
if (m_par && scope_lvl() == 0) {
|
||||
unsigned num_in = 0, num_out = 0;
|
||||
SASSERT(scope_lvl() == 0); // parallel with assumptions is TBD
|
||||
literal_vector in, out;
|
||||
for (unsigned i = m_par_limit_out; i < m_trail.size(); ++i) {
|
||||
literal lit = m_trail[i];
|
||||
if (lit.var() < m_par_num_vars) {
|
||||
++num_out;
|
||||
out.push_back(lit);
|
||||
}
|
||||
}
|
||||
m_par_limit_out = m_trail.size();
|
||||
m_par->exchange(out, m_par_limit_in, in);
|
||||
for (unsigned i = 0; !inconsistent() && i < in.size(); ++i) {
|
||||
literal lit = in[i];
|
||||
SASSERT(lit.var() < m_par_num_vars);
|
||||
if (lvl(lit.var()) != 0 || value(lit) != l_true) {
|
||||
++num_in;
|
||||
assign(lit, justification());
|
||||
}
|
||||
}
|
||||
if (num_in > 0 || num_out > 0) {
|
||||
IF_VERBOSE(1, verbose_stream() << "(sat-sync out: " << num_out << " in: " << num_in << ")\n";);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void solver::set_par(par* p) {
|
||||
m_par = p;
|
||||
m_par_num_vars = num_vars();
|
||||
m_par_limit_in = 0;
|
||||
m_par_limit_out = 0;
|
||||
}
|
||||
|
||||
bool_var solver::next_var() {
|
||||
bool_var next;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ Revision History:
|
|||
#include"sat_iff3_finder.h"
|
||||
#include"sat_probing.h"
|
||||
#include"sat_mus.h"
|
||||
#include"sat_par.h"
|
||||
#include"params.h"
|
||||
#include"statistics.h"
|
||||
#include"stopwatch.h"
|
||||
|
@ -74,6 +75,7 @@ namespace sat {
|
|||
config m_config;
|
||||
stats m_stats;
|
||||
extension * m_ext;
|
||||
par* m_par;
|
||||
random_gen m_rand;
|
||||
clause_allocator m_cls_allocator;
|
||||
cleaner m_cleaner;
|
||||
|
@ -128,6 +130,10 @@ namespace sat {
|
|||
literal_set m_assumption_set; // set of enabled assumptions
|
||||
literal_vector m_core; // unsat core
|
||||
|
||||
unsigned m_par_limit_in;
|
||||
unsigned m_par_limit_out;
|
||||
unsigned m_par_num_vars;
|
||||
|
||||
void del_clauses(clause * const * begin, clause * const * end);
|
||||
|
||||
friend class integrity_checker;
|
||||
|
@ -209,6 +215,7 @@ namespace sat {
|
|||
bool inconsistent() const { return m_inconsistent; }
|
||||
unsigned num_vars() const { return m_level.size(); }
|
||||
unsigned num_clauses() const;
|
||||
unsigned num_restarts() const { return m_restarts; }
|
||||
bool is_external(bool_var v) const { return m_external[v] != 0; }
|
||||
bool was_eliminated(bool_var v) const { return m_eliminated[v] != 0; }
|
||||
unsigned scope_lvl() const { return m_scope_lvl; }
|
||||
|
@ -240,7 +247,9 @@ namespace sat {
|
|||
m_num_checkpoints = 0;
|
||||
if (memory::get_allocation_size() > m_config.m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG);
|
||||
}
|
||||
void set_par(par* p);
|
||||
bool canceled() { return !m_rlimit.inc(); }
|
||||
config const& get_config() { return m_config; }
|
||||
typedef std::pair<literal, literal> bin_clause;
|
||||
protected:
|
||||
watch_list & get_wlist(literal l) { return m_watches[l.index()]; }
|
||||
|
@ -316,6 +325,8 @@ namespace sat {
|
|||
bool check_model(model const & m) const;
|
||||
void restart();
|
||||
void sort_watch_lits();
|
||||
void exchange_par();
|
||||
lbool check_par(unsigned num_lits, literal const* lits);
|
||||
|
||||
// -----------------------
|
||||
//
|
||||
|
|
|
@ -140,6 +140,7 @@ public:
|
|||
if (r != l_true) return r;
|
||||
|
||||
r = m_solver.check(m_asms.size(), m_asms.c_ptr());
|
||||
|
||||
switch (r) {
|
||||
case l_true:
|
||||
if (sz > 0) {
|
||||
|
@ -276,6 +277,8 @@ public:
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) {
|
||||
sat::literal_vector ls;
|
||||
u_map<expr*> lit2var;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue