3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-07 07:45:46 +00:00

enable reduce_by, more tests

This commit is contained in:
Nikolaj Bjorner 2021-09-19 13:41:39 -04:00
parent 58c66ffee8
commit c69c316b27
7 changed files with 142 additions and 36 deletions

View file

@ -104,7 +104,7 @@ namespace polysat {
// if clause is unsat then assign arbitrary
// solver handles unsat clauses by creating a conflict.
// solver also can propagate, but need to check that it does indeed.
void constraint_manager::watch(clause& cl, solver& s) {
void constraint_manager::watch(clause& cl, solver& s) {
if (cl.size() <= 1)
return;
bool first = true;

View file

@ -93,7 +93,7 @@ namespace polysat {
}
void ex_polynomial_superposition::reduce_by(pvar v, conflict_core& core) {
return;
//return;
bool progress = true;
while (progress) {
progress = false;
@ -111,6 +111,10 @@ namespace polysat {
for (auto c : core) {
if (c == eq)
continue;
if (is_positive_equality_over(v, c))
continue;
if (!c.is_currently_false(s()))
continue;
if (c->is_ule()) {
auto lhs = c->to_ule().lhs();
auto rhs = c->to_ule().rhs();
@ -121,10 +125,11 @@ namespace polysat {
auto c2 = s().ule(a, b);
if (!c.is_positive())
c2 = ~c2;
vector<signed_constraint> premises;
premises.push_back(eq);
premises.push_back(c);
core.replace(c, c2, premises);
SASSERT(c2.is_currently_false(s()));
if (!c2->has_bvar() || l_undef == c2.bvalue(s()))
core.keep(c2); // adds propagation of c to the search stack
core.reset();
core.set(c2);
return true;
}
}

View file

@ -16,19 +16,29 @@ Author:
namespace polysat {
std::ostream& search_item::display(std::ostream& out) const {
switch (kind()) {
std::ostream& search_state::display(search_item const& item, std::ostream& out) const {
switch (item.kind()) {
case search_item_k::assignment:
return out << "v" << var() << "=?";
return out << "v" << item.var() << " := " << value(item.var());
case search_item_k::boolean:
return out << lit();
return out << item.lit();
}
UNREACHABLE();
return out;
}
std::ostream& search_state::display(std::ostream& out) const {
return out << m_items;
for (auto const& item : m_items)
display(item, out) << " ";
return out;
}
rational search_state::value(pvar v) const {
for (auto const& [p, r] : m_assignment)
if (v == p)
return r;
UNREACHABLE();
return rational::zero();
}
void search_state::push_assignment(pvar p, rational const& r) {
@ -42,9 +52,8 @@ namespace polysat {
void search_state::pop() {
auto const& item = m_items.back();
if (item.is_assignment()) {
m_assignment.pop_back();
}
if (item.is_assignment())
m_assignment.pop_back();
m_items.pop_back();
}

View file

@ -42,17 +42,15 @@ namespace polysat {
bool is_boolean() const { return m_kind == search_item_k::boolean; }
search_item_k kind() const { return m_kind; }
pvar var() const { SASSERT(is_assignment()); return m_var; }
sat::literal lit() const { SASSERT(is_boolean()); return m_lit; }
std::ostream& display(std::ostream& out) const;
sat::literal lit() const { SASSERT(is_boolean()); return m_lit; }
};
inline std::ostream& operator<<(std::ostream& out, search_item const& s) { return s.display(out); }
class search_state {
vector<search_item> m_items;
assignment_t m_assignment; // First-order part of the search state
rational value(pvar v) const;
public:
unsigned size() const { return m_items.size(); }
@ -70,10 +68,19 @@ namespace polysat {
const_iterator end() const { return m_items.end(); }
std::ostream& display(std::ostream& out) const;
std::ostream& display(search_item const& item, std::ostream& out) const;
};
struct search_item_pp {
search_state const& s;
search_item const& i;
search_item_pp(search_state const& s, search_item const& i) : s(s), i(i) {}
};
inline std::ostream& operator<<(std::ostream& out, search_state const& s) { return s.display(out); }
inline std::ostream& operator<<(std::ostream& out, search_item_pp const& p) { return p.s.display(p.i, out); }
// Go backwards over the search_state.
// If new entries are added during processing an item, they will be queued for processing next after the current item.

View file

@ -339,7 +339,6 @@ namespace polysat {
}
}
void solver::add_watch(signed_constraint c) {
SASSERT(c);
auto const& vars = c->vars();
@ -468,7 +467,7 @@ namespace polysat {
LOG("search state: " << m_search);
LOG("Conflict: " << m_conflict);
auto const& item = *search_it;
LOG_H2("Working on " << item);
LOG_H2("Working on " << search_item_pp(m_search, item));
if (item.is_assignment()) {
// Resolve over variable assignment
pvar v = item.var();
@ -543,7 +542,7 @@ namespace polysat {
void solver::learn_lemma(pvar v, clause& lemma) {
LOG("Learning: "<< lemma);
SASSERT(lemma.size() > 0);
SASSERT(!lemma.empty());
lemma.set_justified_var(v);
add_lemma(lemma);
decide_bool(lemma);
@ -624,7 +623,7 @@ namespace polysat {
void solver::revert_bool_decision(sat::literal lit) {
sat::bool_var const var = lit.var();
LOG_H3("Reverting boolean decision: " << lit);
LOG_H3("Reverting boolean decision: " << lit << " " << m_conflict);
SASSERT(m_bvars.is_decision(var));
// Current situation: we have a decision for boolean literal L on top of the stack, and a conflict core.
@ -663,6 +662,8 @@ namespace polysat {
}
clause_ref reason = reason_builder.build();
std::cout << "reason " << *reason << "\n";
// The lemma where 'lit' comes from.
// Currently, boolean decisions always come from guessing a literal of a learned non-unit lemma.
clause* lemma = m_bvars.lemma(var); // need to grab this while 'lit' is still assigned
@ -748,7 +749,6 @@ namespace polysat {
LOG("Lemma: " << lemma);
for (sat::literal lit : lemma) {
LOG(" Literal " << lit << " is: " << lit2cnstr(lit));
SASSERT(!lit2cnstr(lit).is_currently_true(*this));
SASSERT(m_bvars.value(lit) != l_true);
}
SASSERT(!lemma.empty());