3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-23 11:37:54 +00:00

adding arith sls

This commit is contained in:
Nikolaj Bjorner 2023-02-07 19:27:19 -08:00
parent 6a2d60a6ba
commit 96d815b904
17 changed files with 625 additions and 35 deletions

View file

@ -78,12 +78,7 @@ namespace arith {
m_eq_tail++;
}
public:
void set_type(euf::solver& ctx, hint_type ty) {
ctx.push(value_trail<unsigned>(m_eq_tail));
ctx.push(value_trail<unsigned>(m_lit_tail));
m_ty = ty;
reset();
}
void set_type(euf::solver& ctx, hint_type ty);
void set_num_le(unsigned n) { m_num_le = n; }
void add_eq(euf::enode* a, euf::enode* b) { add(a, b, true); }
void add_diseq(euf::enode* a, euf::enode* b) { add(a, b, false); }
@ -96,12 +91,9 @@ namespace arith {
}
std::pair<rational, literal> const& lit(unsigned i) const { return m_literals[i]; }
std::tuple<enode*, enode*, bool> const& eq(unsigned i) const { return m_eqs[i]; }
arith_proof_hint* mk(euf::solver& s) {
return new (s.get_region()) arith_proof_hint(m_ty, m_num_le, m_lit_head, m_lit_tail, m_eq_head, m_eq_tail);
}
arith_proof_hint* mk(euf::solver& s);
};
class solver : public euf::th_euf_solver {
friend struct arith_proof_hint;
@ -144,7 +136,7 @@ namespace arith {
};
int_hashtable<var_value_hash, var_value_eq> m_model_eqs;
bool m_new_eq { false };
bool m_new_eq = false;
// temporary values kept during internalization
@ -198,6 +190,85 @@ namespace arith {
}
};
// local search portion for arithmetic
class sls {
enum class ineq_kind { EQ, LE, LT, NE };
enum class var_kind { INT, REAL };
typedef unsigned var_t;
typedef unsigned atom_t;
struct stats {
unsigned m_num_flips = 0;
};
// encode args <= bound, args = bound, args < bound
struct ineq {
vector<std::pair<rational, var_t>> m_args;
ineq_kind m_op = ineq_kind::LE;
rational m_bound;
rational m_args_value;
bool is_true() const {
switch (m_op) {
case ineq_kind::LE:
return m_args_value <= m_bound;
case ineq_kind::EQ:
return m_args_value == m_bound;
case ineq_kind::NE:
return m_args_value != m_bound;
default:
return m_args_value < m_bound;
}
}
};
struct var_info {
rational m_value;
rational m_best_value;
var_kind m_kind = var_kind::INT;
vector<std::pair<rational, atom_t>> m_atoms;
};
struct atom_info {
ineq m_ineq;
unsigned m_clause_idx;
bool m_is_bool = false;
bool m_phase = false;
bool m_best_phase = false;
unsigned m_breaks = 0;
};
solver& s;
ast_manager& m;
unsigned m_max_arith_steps = 0;
stats m_stats;
vector<atom_info> m_atoms;
vector<var_info> m_vars;
bool flip();
void log() {}
bool flip_unsat() { return false; }
bool flip_clauses() { return false; }
bool flip_dscore() { return false; }
// bool flip_dscore(clause const&);
// bool flip(clause const&);
rational dtt(ineq const& ineq) const { return dtt(ineq.m_args_value, ineq); }
rational dtt(rational const& args, ineq const& ineq) const;
rational dtt(ineq const& ineq, var_t v, rational const& new_value) const;
// rational dts(clause const& cl, var_t v, rational const& new_value) const;
// rational dts(clause const& cl) const;
bool cm(ineq const& ineq, var_t v, rational& new_value);
rational value(var_t v) const { return m_vars[v].m_value; }
public:
sls(solver& s);
void operator ()(bool_vector& phase);
void set_bounds_begin();
void set_bounds_end(unsigned num_literals);
void set_bounds(enode* n);
};
sls m_local_search;
typedef vector<std::pair<rational, lpvar>> var_coeffs;
vector<rational> m_columns;
var_coeffs m_left_side; // constraint left side
@ -233,10 +304,10 @@ namespace arith {
unsigned m_asserted_qhead = 0;
svector<std::pair<theory_var, theory_var> > m_assume_eq_candidates;
unsigned m_assume_eq_head{ 0 };
unsigned m_assume_eq_head = 0;
lp::u_set m_tmp_var_set;
unsigned m_num_conflicts{ 0 };
unsigned m_num_conflicts = 0;
lp_api::stats m_stats;
svector<scope> m_scopes;
@ -515,6 +586,11 @@ namespace arith {
bool enable_ackerman_axioms(euf::enode* n) const override { return !a.is_add(n->get_expr()); }
bool has_unhandled() const override { return m_not_handled != nullptr; }
void set_bounds_begin() override { m_local_search.set_bounds_begin(); }
void set_bounds_end(unsigned num_literals) override { m_local_search.set_bounds_end(num_literals); }
void set_bounds(enode* n) override { m_local_search.set_bounds(n); }
void local_search(bool_vector& phase) override { m_local_search(phase); }
// bounds and equality propagation callbacks
lp::lar_solver& lp() { return *m_solver; }
lp::lar_solver const& lp() const { return *m_solver; }
@ -523,4 +599,7 @@ namespace arith {
void consume(rational const& v, lp::constraint_index j);
bool bound_is_interesting(unsigned vi, lp::lconstraint_kind kind, const rational& bval) const;
};
}