mirror of
https://github.com/Z3Prover/z3
synced 2026-05-01 16:13:44 +00:00
na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
2720d9ae59
commit
7b01f263f4
2 changed files with 35 additions and 36 deletions
|
|
@ -148,7 +148,6 @@ namespace nla {
|
||||||
}
|
}
|
||||||
|
|
||||||
void stellensatz2::init_solver() {
|
void stellensatz2::init_solver() {
|
||||||
m_ctrail.reset(); // pops constraints
|
|
||||||
m_num_scopes = 0;
|
m_num_scopes = 0;
|
||||||
m_monomial_factory.reset();
|
m_monomial_factory.reset();
|
||||||
m_coi.init();
|
m_coi.init();
|
||||||
|
|
@ -296,7 +295,7 @@ namespace nla {
|
||||||
ci = m_constraints.size();
|
ci = m_constraints.size();
|
||||||
|
|
||||||
unsigned level = get_level(j);
|
unsigned level = get_level(j);
|
||||||
if (std::holds_alternative<assumption_justification>(j)) {
|
if (is_decision(j)) {
|
||||||
level = m_num_scopes;
|
level = m_num_scopes;
|
||||||
++m_num_scopes;
|
++m_num_scopes;
|
||||||
}
|
}
|
||||||
|
|
@ -336,11 +335,11 @@ namespace nla {
|
||||||
SASSERT(ci != lp::null_ci);
|
SASSERT(ci != lp::null_ci);
|
||||||
if (conflict == lp::null_ci)
|
if (conflict == lp::null_ci)
|
||||||
return lp::null_ci;
|
return lp::null_ci;
|
||||||
// TODO: the variable to resolve on occurs in ci and has to be extracted from ci or the justification for ci.
|
auto const &[p, k] = m_constraints[ci];
|
||||||
// It is likely adequate to suppose ci is justified by bounds propagation and the variable is in the propagated
|
if (p.is_var())
|
||||||
// bound. It could also be that ci is a decision. Note that extracting variables for resolution is optional. we
|
return resolve_variable(p.var(), ci, conflict);
|
||||||
// will anyhow end up flipping the last decision. v is maximal variable in ci?
|
if (p.is_minus())
|
||||||
NOT_IMPLEMENTED_YET();
|
return resolve_variable((-p).var(), ci, conflict);
|
||||||
return lp::null_ci;
|
return lp::null_ci;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -629,7 +628,7 @@ namespace nla {
|
||||||
if (std::holds_alternative<external_justification>(j)) {
|
if (std::holds_alternative<external_justification>(j)) {
|
||||||
external.push_back(ci);
|
external.push_back(ci);
|
||||||
}
|
}
|
||||||
else if (std::holds_alternative<assumption_justification>(j)) {
|
else if (is_decision(j)) {
|
||||||
assumptions.push_back(ci);
|
assumptions.push_back(ci);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -808,15 +807,6 @@ namespace nla {
|
||||||
return;
|
return;
|
||||||
if (m_has_occurs[ci])
|
if (m_has_occurs[ci])
|
||||||
return;
|
return;
|
||||||
struct undo_occurs : public trail {
|
|
||||||
stellensatz2 & s;
|
|
||||||
lp::constraint_index ci;
|
|
||||||
undo_occurs(stellensatz2 & s, lp::constraint_index ci) : s(s), ci(ci) {}
|
|
||||||
void undo() override {
|
|
||||||
s.remove_occurs(ci);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
m_ctrail.push(undo_occurs(*this, ci));
|
|
||||||
m_has_occurs[ci] = true;
|
m_has_occurs[ci] = true;
|
||||||
auto const &con = m_constraints[ci];
|
auto const &con = m_constraints[ci];
|
||||||
for (auto v : con.p.free_vars())
|
for (auto v : con.p.free_vars())
|
||||||
|
|
@ -824,7 +814,8 @@ namespace nla {
|
||||||
}
|
}
|
||||||
|
|
||||||
void stellensatz2::remove_occurs(lp::constraint_index ci) {
|
void stellensatz2::remove_occurs(lp::constraint_index ci) {
|
||||||
SASSERT(m_has_occurs[ci]);
|
if (!m_has_occurs[ci])
|
||||||
|
return;
|
||||||
m_has_occurs[ci] = false;
|
m_has_occurs[ci] = false;
|
||||||
auto const &con = m_constraints[ci];
|
auto const &con = m_constraints[ci];
|
||||||
for (auto v : con.p.free_vars())
|
for (auto v : con.p.free_vars())
|
||||||
|
|
@ -1091,8 +1082,8 @@ namespace nla {
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stellensatz2::backtrack(unsigned ci, svector<lp::constraint_index> const &deps) {
|
stellensatz2::constraint stellensatz2::negate_constraint(constraint const &c) {
|
||||||
auto &[p, k] = m_constraints[ci];
|
auto [p, k] = c;
|
||||||
switch (k) {
|
switch (k) {
|
||||||
case lp::lconstraint_kind::GE:
|
case lp::lconstraint_kind::GE:
|
||||||
if (is_int(p)) {
|
if (is_int(p)) {
|
||||||
|
|
@ -1113,18 +1104,22 @@ namespace nla {
|
||||||
k = lp::lconstraint_kind::GT;
|
k = lp::lconstraint_kind::GT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lp::constraint_index head = ci, tail = ci + 1;
|
return {p, k};
|
||||||
|
}
|
||||||
|
|
||||||
|
void stellensatz2::backtrack(unsigned ci, svector<lp::constraint_index> const &deps) {
|
||||||
|
auto &[p, k] = m_constraints[ci];
|
||||||
unsigned propagation_level = 0;
|
unsigned propagation_level = 0;
|
||||||
for (auto ci : deps)
|
for (auto ci : deps)
|
||||||
propagation_level = std::max(propagation_level, m_levels[ci]);
|
propagation_level = std::max(propagation_level, m_levels[ci]);
|
||||||
|
m_constraint_index.erase({p.index(), k});
|
||||||
|
|
||||||
// propagate negated constraint
|
// propagate negated constraint
|
||||||
m_justifications[head] = propagation_justification(deps);
|
m_constraints[ci] = negate_constraint(m_constraints[ci]);
|
||||||
m_levels[head] = propagation_level;
|
m_justifications[ci] = propagation_justification(deps);
|
||||||
m_constraints[head] = {p, k};
|
m_levels[ci] = propagation_level;
|
||||||
m_num_scopes = propagation_level;
|
m_num_scopes = propagation_level;
|
||||||
++head;
|
lp::constraint_index head = ci + 1, tail = ci + 1;
|
||||||
// replay other constraints
|
// replay other constraints
|
||||||
unsigned sz = m_constraints.size();
|
unsigned sz = m_constraints.size();
|
||||||
svector<lp::constraint_index> tail2head;
|
svector<lp::constraint_index> tail2head;
|
||||||
|
|
@ -1133,15 +1128,20 @@ namespace nla {
|
||||||
return old_ci < sz ? old_ci : tail2head[sz - old_ci];
|
return old_ci < sz ? old_ci : tail2head[sz - old_ci];
|
||||||
};
|
};
|
||||||
for (; tail < m_constraints.size(); ++tail) {
|
for (; tail < m_constraints.size(); ++tail) {
|
||||||
|
auto [p, k] = m_constraints[tail];
|
||||||
auto level = get_level(m_justifications[tail]);
|
auto level = get_level(m_justifications[tail]);
|
||||||
if (tail < sz && level > propagation_level)
|
auto has_occurs = m_has_occurs[tail];
|
||||||
continue;
|
remove_occurs(tail);
|
||||||
|
m_constraint_index.erase({p.index(), k});
|
||||||
|
if (level > m_num_scopes)
|
||||||
|
continue;
|
||||||
m_constraints[head] = m_constraints[tail];
|
m_constraints[head] = m_constraints[tail];
|
||||||
m_justifications[head] = translate_j(translate_ci, m_justifications[tail]);
|
m_justifications[head] = translate_j(translate_ci, m_justifications[tail]);
|
||||||
m_levels[head] = get_level(m_justifications[tail]);
|
m_levels[head] = is_decision(head) ? ++m_num_scopes : get_level(m_justifications[tail]);
|
||||||
if (is_decision(head))
|
|
||||||
m_levels[head] = ++m_num_scopes;
|
|
||||||
tail2head[sz - tail] = head;
|
tail2head[sz - tail] = head;
|
||||||
|
if (has_occurs)
|
||||||
|
init_occurs(head);
|
||||||
|
m_constraint_index.insert({p.index(), k}, head);
|
||||||
++head;
|
++head;
|
||||||
}
|
}
|
||||||
m_constraints.shrink(head);
|
m_constraints.shrink(head);
|
||||||
|
|
|
||||||
|
|
@ -166,8 +166,6 @@ namespace nla {
|
||||||
lpvar m_var;
|
lpvar m_var;
|
||||||
bool m_is_upper;
|
bool m_is_upper;
|
||||||
};
|
};
|
||||||
|
|
||||||
trail_stack m_ctrail; // constraint and variable trail
|
|
||||||
unsigned m_num_scopes = 0;
|
unsigned m_num_scopes = 0;
|
||||||
coi m_coi;
|
coi m_coi;
|
||||||
mutable dd::pdd_manager pddm;
|
mutable dd::pdd_manager pddm;
|
||||||
|
|
@ -214,6 +212,8 @@ namespace nla {
|
||||||
lbool search();
|
lbool search();
|
||||||
lbool resolve_conflict();
|
lbool resolve_conflict();
|
||||||
void backtrack(lp::constraint_index ci, svector<lp::constraint_index> const &deps);
|
void backtrack(lp::constraint_index ci, svector<lp::constraint_index> const &deps);
|
||||||
|
constraint negate_constraint(constraint const &c);
|
||||||
|
|
||||||
void init_search();
|
void init_search();
|
||||||
void init_levels();
|
void init_levels();
|
||||||
void pop_bound();
|
void pop_bound();
|
||||||
|
|
@ -234,9 +234,8 @@ namespace nla {
|
||||||
}
|
}
|
||||||
void reset_conflict() { m_conflict = lp::null_ci; m_conflict_dep.reset(); }
|
void reset_conflict() { m_conflict = lp::null_ci; m_conflict_dep.reset(); }
|
||||||
bool is_conflict() const { return !m_conflict_dep.empty(); }
|
bool is_conflict() const { return !m_conflict_dep.empty(); }
|
||||||
bool is_decision(lp::constraint_index ci) const {
|
bool is_decision(justification const& j) const { return std::holds_alternative<assumption_justification>(j); }
|
||||||
return std::holds_alternative<assumption_justification>(m_justifications[ci]);
|
bool is_decision(lp::constraint_index ci) const { return is_decision(m_justifications[ci]); }
|
||||||
}
|
|
||||||
|
|
||||||
indexed_uint_set m_tabu;
|
indexed_uint_set m_tabu;
|
||||||
unsigned_vector m_var2level, m_level2var;
|
unsigned_vector m_var2level, m_level2var;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue