mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 17:45:32 +00:00
na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
5ad486901e
commit
b22928bfc9
5 changed files with 96 additions and 8 deletions
|
@ -15,6 +15,7 @@ Author:
|
|||
#include "math/polysat/constraint.h"
|
||||
#include "math/polysat/solver.h"
|
||||
#include "math/polysat/log.h"
|
||||
#include "math/polysat/log_helper.h"
|
||||
#include "math/polysat/var_constraint.h"
|
||||
#include "math/polysat/eq_constraint.h"
|
||||
#include "math/polysat/ule_constraint.h"
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace polysat {
|
|||
virtual void restore_bound() = 0;
|
||||
virtual void add_le(var_t v, var_t w) = 0;
|
||||
virtual void add_lt(var_t v, var_t w) = 0;
|
||||
virtual void restore_ineq() = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -128,6 +129,15 @@ namespace polysat {
|
|||
fix_entry():x(null_var), r(0) {}
|
||||
};
|
||||
|
||||
struct ineq {
|
||||
var_t v { null_var };
|
||||
var_t w { null_var };
|
||||
bool strict { false };
|
||||
bool is_active { true };
|
||||
ineq(var_t v, var_t w, bool s):
|
||||
v(v), w(w), strict(s) {}
|
||||
};
|
||||
|
||||
static const var_t null_var = UINT_MAX;
|
||||
reslimit& m_limit;
|
||||
mutable manager m;
|
||||
|
@ -148,6 +158,13 @@ namespace polysat {
|
|||
vector<stashed_bound> m_stashed_bounds;
|
||||
map<numeral, fix_entry, typename manager::hash, typename manager::eq> m_value2fixed_var;
|
||||
|
||||
// inequalities
|
||||
svector<ineq> m_ineqs;
|
||||
unsigned_vector m_ineqs_to_check;
|
||||
bool_vector m_var_is_touched;
|
||||
vector<unsigned_vector> m_var2ineqs;
|
||||
svector<var_t> m_vars_to_untouch;
|
||||
|
||||
public:
|
||||
fixplex(reslimit& lim):
|
||||
m_limit(lim),
|
||||
|
@ -164,8 +181,9 @@ namespace polysat {
|
|||
void set_bounds(var_t v, rational const& lo, rational const& hi) override;
|
||||
void set_value(var_t v, rational const& val) override;
|
||||
void restore_bound() override;
|
||||
void add_le(var_t v, var_t w) override;
|
||||
void add_lt(var_t v, var_t w) override;
|
||||
void add_le(var_t v, var_t w) override { add_ineq(v, w, false); }
|
||||
void add_lt(var_t v, var_t w) override { add_ineq(v, w, true); }
|
||||
virtual void restore_ineq() override;
|
||||
|
||||
void set_bounds(var_t v, numeral const& lo, numeral const& hi);
|
||||
void unset_bounds(var_t v) { m_vars[v].set_free(); }
|
||||
|
@ -235,6 +253,11 @@ namespace polysat {
|
|||
pivot_strategy_t pivot_strategy() { return m_bland ? S_BLAND : S_DEFAULT; }
|
||||
var_t select_error_var(bool least);
|
||||
|
||||
// facilities for handling inequalities
|
||||
void add_ineq(var_t v, var_t w, bool strict);
|
||||
void touch_var(var_t x);
|
||||
lbool check_ineqs();
|
||||
|
||||
bool is_solved(row const& r) const;
|
||||
bool is_solved(var_t v) const { SASSERT(is_base(v)); return is_solved(base2row(v)); }
|
||||
|
||||
|
|
|
@ -76,11 +76,13 @@ namespace polysat {
|
|||
return l_false;
|
||||
case l_undef:
|
||||
m_to_patch.insert(v);
|
||||
if (l_false == check_ineqs())
|
||||
return l_false;
|
||||
return l_undef;
|
||||
}
|
||||
}
|
||||
SASSERT(well_formed());
|
||||
return l_true;
|
||||
return check_ineqs();
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
|
@ -226,6 +228,7 @@ namespace polysat {
|
|||
if (delta == 0)
|
||||
return;
|
||||
m_vars[v].m_value += delta;
|
||||
touch_var(v);
|
||||
SASSERT(!is_base(v));
|
||||
|
||||
//
|
||||
|
@ -473,15 +476,66 @@ namespace polysat {
|
|||
}
|
||||
|
||||
template<typename Ext>
|
||||
void fixplex<Ext>::add_le(var_t v, var_t w) {
|
||||
NOT_IMPLEMENTED_YET();
|
||||
void fixplex<Ext>::add_ineq(var_t v, var_t w, bool strict) {
|
||||
unsigned idx = m_ineqs.size();
|
||||
m_var2ineqs.reserve(std::max(v, w) + 1);
|
||||
m_var2ineqs[v].push_back(idx);
|
||||
m_var2ineqs[w].push_back(idx);
|
||||
m_ineqs_to_check.push_back(idx);
|
||||
m_ineqs.push_back(ineq(v, w, strict));
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
void fixplex<Ext>::add_lt(var_t v, var_t w) {
|
||||
NOT_IMPLEMENTED_YET();
|
||||
void fixplex<Ext>::restore_ineq() {
|
||||
auto ineq = m_ineqs.back();
|
||||
m_var2ineqs[ineq.v].pop_back();
|
||||
m_var2ineqs[ineq.w].pop_back();
|
||||
m_ineqs.pop_back();
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
void fixplex<Ext>::touch_var(var_t v) {
|
||||
if (v >= m_var2ineqs.size())
|
||||
return;
|
||||
if (m_var_is_touched.get(v, false))
|
||||
return;
|
||||
m_var_is_touched.set(v, true);
|
||||
for (auto idx : m_var2ineqs[v]) {
|
||||
if (!m_ineqs[idx].is_active) {
|
||||
m_ineqs[idx].is_active = true;
|
||||
m_ineqs_to_check.push_back(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
lbool fixplex<Ext>::check_ineqs() {
|
||||
m_vars_to_untouch.reset();
|
||||
for (auto idx : m_ineqs_to_check) {
|
||||
if (idx >= m_ineqs.size())
|
||||
continue;
|
||||
auto& ineq = m_ineqs[idx];
|
||||
var_t v = ineq.v;
|
||||
var_t w = ineq.w;
|
||||
if (ineq.strict && value(v) >= value(w)) {
|
||||
IF_VERBOSE(0, verbose_stream() << "violated v" << v << " < v" << w << "\n");
|
||||
return l_false;
|
||||
}
|
||||
if (ineq.strict && value(v) > value(w)) {
|
||||
IF_VERBOSE(0, verbose_stream() << "violated v" << v << " <= v" << w << "\n");
|
||||
return l_false;
|
||||
}
|
||||
ineq.is_active = false;
|
||||
m_vars_to_untouch.push_back(v);
|
||||
m_vars_to_untouch.push_back(w);
|
||||
}
|
||||
for (auto v : m_vars_to_untouch)
|
||||
m_var_is_touched.set(v, false);
|
||||
m_ineqs_to_check.reset();
|
||||
m_vars_to_untouch.reset();
|
||||
return l_true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the coefficient b of y has the minimal number of trailing zeros.
|
||||
|
@ -615,6 +669,7 @@ namespace polysat {
|
|||
set_base_value(y);
|
||||
xI.m_is_base = false;
|
||||
xI.m_value = new_value;
|
||||
touch_var(x);
|
||||
row r_x(rx);
|
||||
add_patch(y);
|
||||
SASSERT(well_formed_row(r_x));
|
||||
|
@ -815,6 +870,7 @@ namespace polysat {
|
|||
SASSERT(is_base(x));
|
||||
row r = base2row(x);
|
||||
m_vars[x].m_value = solve_for(row2value(r), row2base_coeff(r));
|
||||
touch_var(x);
|
||||
bool was_integral = row_is_integral(r);
|
||||
m_rows[r.id()].m_integral = is_solved(r);
|
||||
if (was_integral && !row_is_integral(r))
|
||||
|
|
|
@ -53,6 +53,12 @@ namespace polysat {
|
|||
m_rows.pop_back();
|
||||
break;
|
||||
}
|
||||
case trail_i::add_ineq_i: {
|
||||
auto [v, sz] = m_rows.back();
|
||||
sz2fixplex(sz).restore_ineq();
|
||||
m_rows.pop_back();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -179,7 +185,8 @@ namespace polysat {
|
|||
fp.add_le(v, w);
|
||||
else
|
||||
fp.add_lt(w, v);
|
||||
|
||||
m_trail.push_back(trail_i::add_ineq_i);
|
||||
m_rows.push_back(std::make_pair(v, sz));
|
||||
}
|
||||
|
||||
void linear_solver::new_bit(var_constraint& c) {
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace polysat {
|
|||
add_var_i,
|
||||
add_mono_i,
|
||||
set_bound_i,
|
||||
add_ineq_i,
|
||||
add_row_i
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue