3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-28 03:15:50 +00:00

Dedup op constraints

This commit is contained in:
Jakob Rath 2022-11-07 15:02:48 +01:00
parent 89acd96a89
commit 2953b1c093
5 changed files with 61 additions and 40 deletions

View file

@ -31,6 +31,9 @@ namespace polysat {
class op_constraint;
class signed_constraint;
using constraints = ptr_vector<constraint>;
using signed_constraints = vector<signed_constraint>;
/// Normalized inequality:
/// lhs <= rhs, if !is_strict
/// lhs < rhs, otherwise
@ -44,7 +47,6 @@ namespace polysat {
signed_constraint as_signed_constraint() const;
};
class constraint {
friend class constraint_manager;
friend class signed_constraint;
@ -126,7 +128,6 @@ namespace polysat {
inline std::ostream& operator<<(std::ostream& out, constraint const& c) { return c.display(out); }
class signed_constraint final {
public:
using ptr_t = constraint*;

View file

@ -24,13 +24,6 @@ Author:
namespace polysat {
// class constraint_dedup {
// public:
// using op_constraint_args_eq = default_eq<op_constraint_args>;
// using op_constraint_args_hash = obj_hash<op_constraint_args>;
// map<op_constraint_args, pvar, op_constraint_args_hash, op_constraint_args_eq> op_constraint_vars;
// };
constraint_manager::constraint_manager(solver& s): s(s) {}
void constraint_manager::assign_bv2c(sat::bool_var bv, constraint* c) {
@ -155,14 +148,14 @@ namespace polysat {
/** Look up constraint among stored constraints. */
constraint* constraint_manager::dedup(constraint* c1) {
constraint* c2 = nullptr;
if (m_constraint_table.find(c1, c2)) {
if (m_dedup.constraints.find(c1, c2)) {
dealloc(c1);
return c2;
}
else {
SASSERT(!c1->has_bvar());
ensure_bvar(c1);
m_constraint_table.insert(c1);
m_dedup.constraints.insert(c1);
store(c1);
return c1;
}
@ -289,10 +282,14 @@ namespace polysat {
}
pdd constraint_manager::band(pdd const& p, pdd const& q) {
op_constraint_args const args(op_constraint::code::and_op, p, q);
auto& m = p.manager();
auto it = m_dedup.op_constraint_expr.find_iterator(args);
if (it != m_dedup.op_constraint_expr.end())
return m.mk_var(it->m_value);
unsigned sz = m.power_of_2();
// TODO: return existing r if we call again with the same arguments
pdd r = m.mk_var(s.add_var(sz));
m_dedup.op_constraint_expr.insert(args, r.var());
s.assign_eh(band(p, q, r), null_dependency);
return r;
}

View file

@ -12,25 +12,24 @@ Author:
--*/
#pragma once
#include "math/polysat/constraint.h"
#include "math/polysat/clause.h"
#include <iostream>
#include "math/polysat/constraint.h"
#include "math/polysat/op_constraint.h"
namespace polysat {
class constraint;
class ule_constraint;
class umul_ovfl_constraint;
class smul_fl_constraint;
class op_constraint;
class signed_constraint;
class constraint_dedup {
public:
using constraint_hash = obj_ptr_hash<constraint>;
using constraint_eq = deref_eq<constraint>;
using constraint_table = ptr_hashtable<constraint, constraint_hash, constraint_eq>;
constraint_table constraints;
using constraint_hash = obj_ptr_hash<constraint>;
using constraint_eq = deref_eq<constraint>;
using constraint_table = ptr_hashtable<constraint, constraint_hash, constraint_eq>;
using constraints = ptr_vector<constraint>;
using signed_constraints = vector<signed_constraint>;
using op_constraint_args_eq = default_eq<op_constraint_args>;
using op_constraint_args_hash = obj_hash<op_constraint_args>;
using op_constraint_expr_map = map<op_constraint_args, pvar, op_constraint_args_hash, op_constraint_args_eq>;
op_constraint_expr_map op_constraint_expr;
};
// Manage constraint lifetime, deduplication, and connection to boolean variables/literals.
class constraint_manager {
@ -40,11 +39,10 @@ namespace polysat {
// Constraints indexed by their boolean variable
ptr_vector<constraint> m_bv2constraint;
// Constraints that have a boolean variable, for deduplication
constraint_table m_constraint_table;
scoped_ptr_vector<constraint> m_constraints;
// scoped_ptr<constraint_dedup> m_dedup;
constraint_dedup m_dedup;
// Clause storage per level
vector<vector<clause_ref>> m_clauses;

View file

@ -78,6 +78,10 @@ namespace polysat {
return is_always_false(is_positive, s.subst(p()), s.subst(q()), s.subst(r()));
}
bool op_constraint::is_currently_false(solver& s, assignment_t const& sub, bool is_positive) const {
return is_always_false(is_positive, s.subst(sub, p()), s.subst(sub, q()), s.subst(sub, r()));
}
std::ostream& op_constraint::display(std::ostream& out, lbool status) const {
switch (status) {
case l_true: return display(out);

View file

@ -20,6 +20,7 @@ Author:
--*/
#pragma once
#include "math/polysat/constraint.h"
#include <optional>
namespace polysat {
@ -57,7 +58,7 @@ namespace polysat {
std::ostream& display(std::ostream& out) const override;
bool is_always_false(bool is_positive) const override;
bool is_currently_false(solver& s, bool is_positive) const override;
bool is_currently_false(solver& s, assignment_t const& sub, bool is_positive) const override { return false; }
bool is_currently_false(solver& s, assignment_t const& sub, bool is_positive) const override;
void narrow(solver& s, bool is_positive, bool first) override;
inequality as_inequality(bool is_positive) const override { throw default_exception("is not an inequality"); }
unsigned hash() const override;
@ -67,4 +68,24 @@ namespace polysat {
void add_to_univariate_solver(solver& s, univariate_solver& us, unsigned dep, bool is_positive) const override;
};
struct op_constraint_args {
op_constraint::code op;
// NOTE: this is only optional because table2map requires a default constructor
std::optional<std::pair<pdd, pdd>> args;
op_constraint_args() = default;
op_constraint_args(op_constraint::code op, pdd lhs, pdd rhs)
: op(op), args({std::move(lhs), std::move(rhs)}) {}
bool operator==(op_constraint_args const& other) const {
return op == other.op && args == other.args;
}
unsigned hash() const {
unsigned const lhs_hash = args ? args->first.hash() : 0;
unsigned const rhs_hash = args ? args->second.hash() : 0;
return mk_mix(static_cast<unsigned>(op), lhs_hash, rhs_hash);
}
};
}