mirror of
https://github.com/Z3Prover/z3
synced 2025-12-18 10:18:33 +00:00
add sketch for incremental algorithm
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
450412c854
commit
ba28e85f04
5 changed files with 94 additions and 5 deletions
|
|
@ -163,4 +163,10 @@ namespace smt {
|
||||||
return th->final_check_eh();
|
return th->final_check_eh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbool arith_value::check_lp_feasible(vector<std::pair<bool, expr_ref>>& ineqs, literal_vector& lit_core,
|
||||||
|
enode_pair_vector& eq_core) {
|
||||||
|
if (!m_thr)
|
||||||
|
return l_undef;
|
||||||
|
return m_thr->check_lp_feasible(ineqs, lit_core, eq_core);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -48,5 +48,7 @@ namespace smt {
|
||||||
expr_ref get_up(expr* e) const;
|
expr_ref get_up(expr* e) const;
|
||||||
expr_ref get_fixed(expr* e) const;
|
expr_ref get_fixed(expr* e) const;
|
||||||
final_check_status final_check();
|
final_check_status final_check();
|
||||||
|
lbool check_lp_feasible(vector<std::pair<bool, expr_ref>> &ineqs, literal_vector &lit_core,
|
||||||
|
enode_pair_vector &eq_core);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -285,11 +285,28 @@ namespace smt {
|
||||||
* Associate tracking literal C_i with current assignment.
|
* Associate tracking literal C_i with current assignment.
|
||||||
* Assume C_i
|
* Assume C_i
|
||||||
* Assert !C_0, .. , !C_{i-1}, C_i => /\_i |s_i| = sum_j n_ij and /\ n_j >= 0
|
* Assert !C_0, .. , !C_{i-1}, C_i => /\_i |s_i| = sum_j n_ij and /\ n_j >= 0
|
||||||
* Incremental algorithm with blocking clauses (sketch)
|
* Incremental algorithm with blocking clauses
|
||||||
* If /\_i |s_i| = sum_j n_ij and /\ n_j >= 0 is unsat
|
* Enumerate N assignments at a time.
|
||||||
* Then, instead of asserting sum constraint assert
|
* use smt_arith_value::check_lp_feasiable to check if current assignment is feasible.
|
||||||
* C_i <=> \/_j core_j
|
* if it is, then yield the current assignment. Assume there is a filter that avoids future
|
||||||
* where core_j come from covering of LRA conflict
|
* calls to find more models if the current model satisfies all cardinality terms.
|
||||||
|
* In other words, for every |s| the model produces a set with |s| elements,
|
||||||
|
* where |s| is the value assigned by the arithmetic solver.
|
||||||
|
* if it is not feasible, extract the infeasible core from call:
|
||||||
|
* - card_core: a set of cardinality atoms
|
||||||
|
* - lit_core: a set of literals asserted into the arithmetic solver
|
||||||
|
* - eq_core: a set of equations asserte into the arithmetic solver
|
||||||
|
* First take the card_core atoms and enumerate Boolean models for m_solver that
|
||||||
|
* satisfy the disjunction of those atoms.
|
||||||
|
* - Infeasibility of the current model meant that there was no linear assignment to
|
||||||
|
* the subset in card_core that satisfied lit_core & eq_core. So the query to extend the
|
||||||
|
* set of assignments is to fix this.
|
||||||
|
* If there is some model for the disjunction of card_core atoms, then
|
||||||
|
* add new slacks for the models an continue, possibly querying the arithmetic solver if the new set of
|
||||||
|
* linear relaxation to the subset is feasible.
|
||||||
|
* If there is no model to the disjunction of card_core atoms, then
|
||||||
|
* it means that size_core & lit_core & eq_core is unsat.
|
||||||
|
* where size_core is the unsat core for m_solver.
|
||||||
*/
|
*/
|
||||||
lbool theory_finite_set_size::run_solver() {
|
lbool theory_finite_set_size::run_solver() {
|
||||||
expr_ref_vector asms(m);
|
expr_ref_vector asms(m);
|
||||||
|
|
|
||||||
|
|
@ -1624,6 +1624,61 @@ public:
|
||||||
return FC_DONE;
|
return FC_DONE;
|
||||||
return FC_GIVEUP;
|
return FC_GIVEUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a set of equalities are lp feasible.
|
||||||
|
* push local scope
|
||||||
|
* internalize ineqs
|
||||||
|
* assert ineq constraints
|
||||||
|
* check lp feasibility
|
||||||
|
* extract core
|
||||||
|
* pop local scope
|
||||||
|
* return verdict
|
||||||
|
*/
|
||||||
|
|
||||||
|
lbool check_lp_feasible(vector<std::pair<bool, expr_ref>> &ineqs, literal_vector& lit_core, enode_pair_vector& eq_core) {
|
||||||
|
lbool st = l_undef;
|
||||||
|
push_scope_eh(); // pushes an arithmetic scope
|
||||||
|
u_map<unsigned> ci2index;
|
||||||
|
unsigned index = 0;
|
||||||
|
for (auto &[in_core, f] : ineqs) {
|
||||||
|
expr *x, *y;
|
||||||
|
rational r;
|
||||||
|
in_core = false;
|
||||||
|
if (m.is_eq(f, x, y) && a.is_numeral(y, r)) {
|
||||||
|
internalize_term(to_app(x));
|
||||||
|
auto j = get_lpvar(th.get_th_var(x));
|
||||||
|
auto ci = lp().add_var_bound(j, lp::EQ, r);
|
||||||
|
ci2index.insert(ci, index);
|
||||||
|
lp().activate(ci);
|
||||||
|
if (is_infeasible()) {
|
||||||
|
st = l_false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
if (st != l_false) {
|
||||||
|
st = make_feasible();
|
||||||
|
SASSERT(st != l_false || is_infeasible());
|
||||||
|
}
|
||||||
|
if (st == l_false) {
|
||||||
|
m_explanation.clear();
|
||||||
|
lp().get_infeasibility_explanation(m_explanation);
|
||||||
|
for (auto ev : m_explanation) {
|
||||||
|
unsigned index;
|
||||||
|
if (ci2index.find(ev.ci(), index))
|
||||||
|
ineqs[index].first = true;
|
||||||
|
else
|
||||||
|
set_evidence(ev.ci(), lit_core, eq_core);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pop_scope_eh(1);
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
final_check_status final_check_eh() {
|
final_check_status final_check_eh() {
|
||||||
if (propagate_core())
|
if (propagate_core())
|
||||||
|
|
@ -4369,6 +4424,10 @@ void theory_lra::validate_model(proto_model& mdl) {
|
||||||
m_imp->validate_model(mdl);
|
m_imp->validate_model(mdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lbool theory_lra::check_lp_feasible(vector<std::pair<bool, expr_ref>>& ineqs, literal_vector& lit_core, enode_pair_vector& eq_core) {
|
||||||
|
return m_imp->check_lp_feasible(ineqs, lit_core, eq_core);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
template class lp::lp_bound_propagator<smt::theory_lra::imp>;
|
template class lp::lp_bound_propagator<smt::theory_lra::imp>;
|
||||||
template void lp::lar_solver::propagate_bounds_for_touched_rows<smt::theory_lra::imp>(lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
template void lp::lar_solver::propagate_bounds_for_touched_rows<smt::theory_lra::imp>(lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,11 @@ namespace smt {
|
||||||
bool get_upper(enode* n, rational& r, bool& is_strict);
|
bool get_upper(enode* n, rational& r, bool& is_strict);
|
||||||
void solve_for(vector<solution>& s) override;
|
void solve_for(vector<solution>& s) override;
|
||||||
|
|
||||||
|
// check if supplied set of linear constraints are LP feasible within current backtracking context
|
||||||
|
// identify core by setting Boolean flags to true for constraints used in the proof of infeasibility
|
||||||
|
// and return l_false if infeasible.
|
||||||
|
lbool check_lp_feasible(vector<std::pair<bool, expr_ref>> &ineqs, literal_vector& lit_core, enode_pair_vector& eq_core);
|
||||||
|
|
||||||
void updt_params() override;
|
void updt_params() override;
|
||||||
|
|
||||||
void display(std::ostream & out) const override;
|
void display(std::ostream & out) const override;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue