mirror of
https://github.com/Z3Prover/z3
synced 2025-04-28 03:15:50 +00:00
Dedup op constraints
This commit is contained in:
parent
89acd96a89
commit
2953b1c093
5 changed files with 61 additions and 40 deletions
|
@ -31,6 +31,9 @@ namespace polysat {
|
||||||
class op_constraint;
|
class op_constraint;
|
||||||
class signed_constraint;
|
class signed_constraint;
|
||||||
|
|
||||||
|
using constraints = ptr_vector<constraint>;
|
||||||
|
using signed_constraints = vector<signed_constraint>;
|
||||||
|
|
||||||
/// Normalized inequality:
|
/// Normalized inequality:
|
||||||
/// lhs <= rhs, if !is_strict
|
/// lhs <= rhs, if !is_strict
|
||||||
/// lhs < rhs, otherwise
|
/// lhs < rhs, otherwise
|
||||||
|
@ -44,7 +47,6 @@ namespace polysat {
|
||||||
signed_constraint as_signed_constraint() const;
|
signed_constraint as_signed_constraint() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class constraint {
|
class constraint {
|
||||||
friend class constraint_manager;
|
friend class constraint_manager;
|
||||||
friend class signed_constraint;
|
friend class signed_constraint;
|
||||||
|
@ -126,7 +128,6 @@ namespace polysat {
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out, constraint const& c) { return c.display(out); }
|
inline std::ostream& operator<<(std::ostream& out, constraint const& c) { return c.display(out); }
|
||||||
|
|
||||||
|
|
||||||
class signed_constraint final {
|
class signed_constraint final {
|
||||||
public:
|
public:
|
||||||
using ptr_t = constraint*;
|
using ptr_t = constraint*;
|
||||||
|
|
|
@ -24,13 +24,6 @@ Author:
|
||||||
|
|
||||||
namespace polysat {
|
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) {}
|
constraint_manager::constraint_manager(solver& s): s(s) {}
|
||||||
|
|
||||||
void constraint_manager::assign_bv2c(sat::bool_var bv, constraint* c) {
|
void constraint_manager::assign_bv2c(sat::bool_var bv, constraint* c) {
|
||||||
|
@ -155,14 +148,14 @@ namespace polysat {
|
||||||
/** Look up constraint among stored constraints. */
|
/** Look up constraint among stored constraints. */
|
||||||
constraint* constraint_manager::dedup(constraint* c1) {
|
constraint* constraint_manager::dedup(constraint* c1) {
|
||||||
constraint* c2 = nullptr;
|
constraint* c2 = nullptr;
|
||||||
if (m_constraint_table.find(c1, c2)) {
|
if (m_dedup.constraints.find(c1, c2)) {
|
||||||
dealloc(c1);
|
dealloc(c1);
|
||||||
return c2;
|
return c2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SASSERT(!c1->has_bvar());
|
SASSERT(!c1->has_bvar());
|
||||||
ensure_bvar(c1);
|
ensure_bvar(c1);
|
||||||
m_constraint_table.insert(c1);
|
m_dedup.constraints.insert(c1);
|
||||||
store(c1);
|
store(c1);
|
||||||
return c1;
|
return c1;
|
||||||
}
|
}
|
||||||
|
@ -289,10 +282,14 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
pdd constraint_manager::band(pdd const& p, pdd const& q) {
|
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& 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();
|
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));
|
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);
|
s.assign_eh(band(p, q, r), null_dependency);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,25 +12,24 @@ Author:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "math/polysat/constraint.h"
|
|
||||||
#include "math/polysat/clause.h"
|
#include "math/polysat/clause.h"
|
||||||
#include <iostream>
|
#include "math/polysat/constraint.h"
|
||||||
|
#include "math/polysat/op_constraint.h"
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
class constraint;
|
class constraint_dedup {
|
||||||
class ule_constraint;
|
public:
|
||||||
class umul_ovfl_constraint;
|
using constraint_hash = obj_ptr_hash<constraint>;
|
||||||
class smul_fl_constraint;
|
using constraint_eq = deref_eq<constraint>;
|
||||||
class op_constraint;
|
using constraint_table = ptr_hashtable<constraint, constraint_hash, constraint_eq>;
|
||||||
class signed_constraint;
|
constraint_table constraints;
|
||||||
|
|
||||||
using constraint_hash = obj_ptr_hash<constraint>;
|
using op_constraint_args_eq = default_eq<op_constraint_args>;
|
||||||
using constraint_eq = deref_eq<constraint>;
|
using op_constraint_args_hash = obj_hash<op_constraint_args>;
|
||||||
using constraint_table = ptr_hashtable<constraint, constraint_hash, constraint_eq>;
|
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;
|
||||||
using constraints = ptr_vector<constraint>;
|
};
|
||||||
using signed_constraints = vector<signed_constraint>;
|
|
||||||
|
|
||||||
// Manage constraint lifetime, deduplication, and connection to boolean variables/literals.
|
// Manage constraint lifetime, deduplication, and connection to boolean variables/literals.
|
||||||
class constraint_manager {
|
class constraint_manager {
|
||||||
|
@ -40,11 +39,10 @@ namespace polysat {
|
||||||
|
|
||||||
// Constraints indexed by their boolean variable
|
// Constraints indexed by their boolean variable
|
||||||
ptr_vector<constraint> m_bv2constraint;
|
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_vector<constraint> m_constraints;
|
||||||
|
|
||||||
// scoped_ptr<constraint_dedup> m_dedup;
|
constraint_dedup m_dedup;
|
||||||
|
|
||||||
// Clause storage per level
|
// Clause storage per level
|
||||||
vector<vector<clause_ref>> m_clauses;
|
vector<vector<clause_ref>> m_clauses;
|
||||||
|
|
|
@ -78,6 +78,10 @@ namespace polysat {
|
||||||
return is_always_false(is_positive, s.subst(p()), s.subst(q()), s.subst(r()));
|
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 {
|
std::ostream& op_constraint::display(std::ostream& out, lbool status) const {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case l_true: return display(out);
|
case l_true: return display(out);
|
||||||
|
|
|
@ -20,6 +20,7 @@ Author:
|
||||||
--*/
|
--*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "math/polysat/constraint.h"
|
#include "math/polysat/constraint.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ namespace polysat {
|
||||||
std::ostream& display(std::ostream& out) const override;
|
std::ostream& display(std::ostream& out) const override;
|
||||||
bool is_always_false(bool is_positive) 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, 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;
|
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"); }
|
inequality as_inequality(bool is_positive) const override { throw default_exception("is not an inequality"); }
|
||||||
unsigned hash() const override;
|
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;
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue