mirror of
https://github.com/Z3Prover/z3
synced 2025-06-28 08:58:44 +00:00
track pvar_kind
This commit is contained in:
parent
63e81e2bb0
commit
d62aa82762
7 changed files with 32 additions and 22 deletions
|
@ -401,8 +401,8 @@ namespace polysat {
|
||||||
if (it != m_dedup.m_quot_rem_expr.end())
|
if (it != m_dedup.m_quot_rem_expr.end())
|
||||||
return { m.mk_var(it->m_value.first), m.mk_var(it->m_value.second) };
|
return { m.mk_var(it->m_value.first), m.mk_var(it->m_value.second) };
|
||||||
|
|
||||||
pdd q = m.mk_var(s.add_var(sz)); // quotient
|
pdd q = m.mk_var(s.add_var(sz, pvar_kind::internal)); // quotient
|
||||||
pdd r = m.mk_var(s.add_var(sz)); // remainder
|
pdd r = m.mk_var(s.add_var(sz, pvar_kind::internal)); // remainder
|
||||||
m_dedup.m_quot_rem_expr.insert(args, { q.var(), r.var() });
|
m_dedup.m_quot_rem_expr.insert(args, { q.var(), r.var() });
|
||||||
m_dedup.m_div_rem_list.push_back({ a, b, q.var(), r.var() });
|
m_dedup.m_div_rem_list.push_back({ a, b, q.var(), r.var() });
|
||||||
|
|
||||||
|
@ -467,7 +467,7 @@ namespace polysat {
|
||||||
if (it != m_dedup.op_constraint_expr.end())
|
if (it != m_dedup.op_constraint_expr.end())
|
||||||
return m.mk_var(it->m_value);
|
return m.mk_var(it->m_value);
|
||||||
|
|
||||||
pdd r = m.mk_var(s.add_var(sz));
|
pdd r = m.mk_var(s.add_var(sz, pvar_kind::op));
|
||||||
m_dedup.op_constraint_expr.insert(args, r.var());
|
m_dedup.op_constraint_expr.insert(args, r.var());
|
||||||
|
|
||||||
signed_constraint c = mk_op_constraint(op, p, q, r);
|
signed_constraint c = mk_op_constraint(op, p, q, r);
|
||||||
|
@ -644,7 +644,7 @@ namespace polysat {
|
||||||
auto const it = m_dedup.m_bv_ext_expr.find_iterator(args);
|
auto const it = m_dedup.m_bv_ext_expr.find_iterator(args);
|
||||||
if (it != m_dedup.m_bv_ext_expr.end())
|
if (it != m_dedup.m_bv_ext_expr.end())
|
||||||
return s.var(it->m_value);
|
return s.var(it->m_value);
|
||||||
pvar const v = s.add_var(v_sz);
|
pvar const v = s.add_var(v_sz, pvar_kind::internal);
|
||||||
pdd const V = s.var(v);
|
pdd const V = s.var(v);
|
||||||
m_dedup.m_bv_ext_expr.insert(args, v);
|
m_dedup.m_bv_ext_expr.insert(args, v);
|
||||||
// (1) v[|p|-1:0] = p
|
// (1) v[|p|-1:0] = p
|
||||||
|
@ -665,7 +665,7 @@ namespace polysat {
|
||||||
auto const it = m_dedup.m_bv_ext_expr.find_iterator(args);
|
auto const it = m_dedup.m_bv_ext_expr.find_iterator(args);
|
||||||
if (it != m_dedup.m_bv_ext_expr.end())
|
if (it != m_dedup.m_bv_ext_expr.end())
|
||||||
return s.var(it->m_value);
|
return s.var(it->m_value);
|
||||||
pdd const v = s.var(s.add_var(v_sz));
|
pdd const v = s.var(s.add_var(v_sz, pvar_kind::internal));
|
||||||
m_dedup.m_bv_ext_expr.insert(args, v.var());
|
m_dedup.m_bv_ext_expr.insert(args, v.var());
|
||||||
// (1) v[|p|-1:0] = p
|
// (1) v[|p|-1:0] = p
|
||||||
s.add_eq(q, extract(v, p_sz - 1, 0));
|
s.add_eq(q, extract(v, p_sz - 1, 0));
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace polysat {
|
||||||
SASSERT(!m_names.contains(key));
|
SASSERT(!m_names.contains(key));
|
||||||
m_names.insert(key, v);
|
m_names.insert(key, v);
|
||||||
m_terms[v] = t;
|
m_terms[v] = t;
|
||||||
|
LOG("set_name v" << v << " := " << t);
|
||||||
}
|
}
|
||||||
|
|
||||||
pvar name_manager::get_name(pdd const& t) const {
|
pvar name_manager::get_name(pdd const& t) const {
|
||||||
|
@ -57,7 +58,7 @@ namespace polysat {
|
||||||
pvar v = get_name(t);
|
pvar v = get_name(t);
|
||||||
if (v != null_var)
|
if (v != null_var)
|
||||||
return v;
|
return v;
|
||||||
v = s.add_var(t.power_of_2());
|
v = s.add_var(t.power_of_2(), pvar_kind::name);
|
||||||
s.add_eq(s.var(v), t);
|
s.add_eq(s.var(v), t);
|
||||||
set_name(v, t);
|
set_name(v, t);
|
||||||
return v;
|
return v;
|
||||||
|
|
|
@ -943,7 +943,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
// allocate new variable if we cannot reuse it
|
// allocate new variable if we cannot reuse it
|
||||||
if (v == null_var) {
|
if (v == null_var) {
|
||||||
v = m_solver.add_var(hi - lo + 1);
|
v = m_solver.add_var(hi - lo + 1, pvar_kind::internal);
|
||||||
#if 1
|
#if 1
|
||||||
// slice didn't have a variable yet; so we can re-use it for the new variable
|
// slice didn't have a variable yet; so we can re-use it for the new variable
|
||||||
// (we end up with a "phantom" enode that was first created for the variable)
|
// (we end up with a "phantom" enode that was first created for the variable)
|
||||||
|
@ -984,6 +984,7 @@ namespace polysat {
|
||||||
m_extract_dedup.insert(args, v);
|
m_extract_dedup.insert(args, v);
|
||||||
m_extract_trail.push_back(args);
|
m_extract_trail.push_back(args);
|
||||||
m_trail.push_back(trail_item::mk_extract);
|
m_trail.push_back(trail_item::mk_extract);
|
||||||
|
LOG("mk_extract: v" << src << "[" << hi << ":" << lo << "] = v" << v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,7 +1021,7 @@ namespace polysat {
|
||||||
v = replay_var;
|
v = replay_var;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
v = m_solver.add_var(total_width);
|
v = m_solver.add_var(total_width, pvar_kind::internal);
|
||||||
enode* sv = var2slice(v);
|
enode* sv = var2slice(v);
|
||||||
VERIFY(merge(slices, sv, dep_t()));
|
VERIFY(merge(slices, sv, dep_t()));
|
||||||
// NOTE: add_concat_node must be done after merge to preserve the invariant: "a base slice is never equivalent to a congruence node".
|
// NOTE: add_concat_node must be done after merge to preserve the invariant: "a base slice is never equivalent to a congruence node".
|
||||||
|
|
|
@ -168,12 +168,16 @@ namespace polysat {
|
||||||
return sz2pdd(size(v));
|
return sz2pdd(size(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned solver::add_var(unsigned sz) {
|
unsigned solver::add_var(unsigned sz, pvar_kind k) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (m_is_solving) {
|
||||||
|
SASSERT(k != pvar_kind::external); // NOTE: if this assertion fails, most likely pvar_kind wasn't set for some internal variable.
|
||||||
|
}
|
||||||
|
#endif
|
||||||
pvar const v = m_value.size();
|
pvar const v = m_value.size();
|
||||||
|
m_kind.push_back(k);
|
||||||
m_value.push_back(rational::zero());
|
m_value.push_back(rational::zero());
|
||||||
m_justification.push_back(justification::unassigned());
|
m_justification.push_back(justification::unassigned());
|
||||||
m_viable.push_var(sz);
|
|
||||||
m_viable_fallback.push_var(sz);
|
|
||||||
m_pwatch.push_back({});
|
m_pwatch.push_back({});
|
||||||
m_activity.push_back(0);
|
m_activity.push_back(0);
|
||||||
m_vars.push_back(sz2pdd(sz).mk_var(v));
|
m_vars.push_back(sz2pdd(sz).mk_var(v));
|
||||||
|
@ -182,6 +186,8 @@ namespace polysat {
|
||||||
m_free_pvars.mk_var_eh(v);
|
m_free_pvars.mk_var_eh(v);
|
||||||
m_names.push_var(var(v)); // needs m_vars
|
m_names.push_var(var(v)); // needs m_vars
|
||||||
m_slicing.add_var(sz);
|
m_slicing.add_var(sz);
|
||||||
|
m_viable.push_var(sz);
|
||||||
|
m_viable_fallback.push_var(sz);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +201,8 @@ namespace polysat {
|
||||||
pvar v = m_value.size() - 1;
|
pvar v = m_value.size() - 1;
|
||||||
m_viable.pop_var();
|
m_viable.pop_var();
|
||||||
m_viable_fallback.pop_var();
|
m_viable_fallback.pop_var();
|
||||||
|
m_names.pop_var();
|
||||||
|
m_kind.pop_back();
|
||||||
m_value.pop_back();
|
m_value.pop_back();
|
||||||
m_justification.pop_back();
|
m_justification.pop_back();
|
||||||
m_pwatch.pop_back();
|
m_pwatch.pop_back();
|
||||||
|
@ -202,7 +210,6 @@ namespace polysat {
|
||||||
m_vars.pop_back();
|
m_vars.pop_back();
|
||||||
m_size.pop_back();
|
m_size.pop_back();
|
||||||
m_free_pvars.del_var_eh(v);
|
m_free_pvars.del_var_eh(v);
|
||||||
m_names.pop_var();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::assign_eh(signed_constraint c, dependency dep) {
|
void solver::assign_eh(signed_constraint c, dependency dep) {
|
||||||
|
|
|
@ -173,6 +173,7 @@ namespace polysat {
|
||||||
slicing m_slicing;
|
slicing m_slicing;
|
||||||
|
|
||||||
// Per variable information
|
// Per variable information
|
||||||
|
svector<pvar_kind> m_kind;
|
||||||
vector<rational> m_value; // assigned value
|
vector<rational> m_value; // assigned value
|
||||||
vector<justification> m_justification; // justification for variable assignment
|
vector<justification> m_justification; // justification for variable assignment
|
||||||
vector<constraints> m_pwatch; // watch list datastructure into constraints.
|
vector<constraints> m_pwatch; // watch list datastructure into constraints.
|
||||||
|
@ -240,6 +241,7 @@ namespace polysat {
|
||||||
* Each struct is a subclass of trail and implements undo().
|
* Each struct is a subclass of trail and implements undo().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
pvar add_var(unsigned sz, pvar_kind k);
|
||||||
void del_var();
|
void del_var();
|
||||||
|
|
||||||
dd::pdd_manager& sz2pdd(unsigned sz) const;
|
dd::pdd_manager& sz2pdd(unsigned sz) const;
|
||||||
|
@ -409,7 +411,7 @@ namespace polysat {
|
||||||
/**
|
/**
|
||||||
* Add variable with bit-size.
|
* Add variable with bit-size.
|
||||||
*/
|
*/
|
||||||
pvar add_var(unsigned sz);
|
pvar add_var(unsigned sz) { return add_var(sz, pvar_kind::external); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create polynomial terms
|
* Create polynomial terms
|
||||||
|
|
|
@ -44,8 +44,7 @@ namespace polysat {
|
||||||
external, // regular variables (from the input formula)
|
external, // regular variables (from the input formula)
|
||||||
name, // name for a polynomial term
|
name, // name for a polynomial term
|
||||||
op, // result of an op_constraint
|
op, // result of an op_constraint
|
||||||
extract, // result of an extract operation
|
internal, // other internal variable
|
||||||
concat, // result of a concat operation
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class dependency {
|
class dependency {
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace polysat {
|
||||||
|
|
||||||
pdd power = get_dyadic_valuation(p).second;
|
pdd power = get_dyadic_valuation(p).second;
|
||||||
|
|
||||||
pvar rest = s.add_var(p.power_of_2());
|
pvar rest = s.add_var(p.power_of_2(), pvar_kind::internal);
|
||||||
pdd rest_pdd = m.mk_var(rest);
|
pdd rest_pdd = m.mk_var(rest);
|
||||||
m_rest_constants.setx(v, rest, -1);
|
m_rest_constants.setx(v, rest, -1);
|
||||||
s.add_clause(s.eq(power * rest_pdd, p), false);
|
s.add_clause(s.eq(power * rest_pdd, p), false);
|
||||||
|
@ -119,7 +119,7 @@ namespace polysat {
|
||||||
if (m_inverse_constants.size() > v && m_inverse_constants[v] != -1)
|
if (m_inverse_constants.size() > v && m_inverse_constants[v] != -1)
|
||||||
return optional<pdd>(s.var(m_inverse_constants[v]));
|
return optional<pdd>(s.var(m_inverse_constants[v]));
|
||||||
|
|
||||||
pvar inv = s.add_var(p.power_of_2());
|
pvar inv = s.add_var(p.power_of_2(), pvar_kind::internal);
|
||||||
pdd inv_pdd = m.mk_var(inv);
|
pdd inv_pdd = m.mk_var(inv);
|
||||||
m_inverse_constants.setx(v, inv, -1);
|
m_inverse_constants.setx(v, inv, -1);
|
||||||
s.add_clause(s.eq(inv_pdd * p, m.one()), false);
|
s.add_clause(s.eq(inv_pdd * p, m.one()), false);
|
||||||
|
@ -138,8 +138,8 @@ namespace polysat {
|
||||||
pvar pv2;
|
pvar pv2;
|
||||||
bool new_var = false;
|
bool new_var = false;
|
||||||
if (m_pv_constants.size() <= v || m_pv_constants[v] == -1) {
|
if (m_pv_constants.size() <= v || m_pv_constants[v] == -1) {
|
||||||
pv = s.add_var(m.power_of_2()); // TODO: What's a good value? Unfortunately we cannot use an integer
|
pv = s.add_var(m.power_of_2(), pvar_kind::internal); // TODO: What's a good value? Unfortunately we cannot use an integer
|
||||||
pv2 = s.add_var(m.power_of_2());
|
pv2 = s.add_var(m.power_of_2(), pvar_kind::internal);
|
||||||
m_pv_constants.setx(v, pv, -1);
|
m_pv_constants.setx(v, pv, -1);
|
||||||
m_pv_power_constants.setx(v, pv2, -1);
|
m_pv_power_constants.setx(v, pv2, -1);
|
||||||
// [nsb cr]: why these calls to m.mk_var()?
|
// [nsb cr]: why these calls to m.mk_var()?
|
||||||
|
@ -586,7 +586,7 @@ namespace polysat {
|
||||||
pvar p_inv = m_pseudo_inverse[v][parity];
|
pvar p_inv = m_pseudo_inverse[v][parity];
|
||||||
|
|
||||||
if (p_inv == -1) {
|
if (p_inv == -1) {
|
||||||
p_inv = s.add_var(p.power_of_2());
|
p_inv = s.add_var(p.power_of_2(), pvar_kind::internal);
|
||||||
m_pseudo_inverse[v][parity] = p_inv;
|
m_pseudo_inverse[v][parity] = p_inv;
|
||||||
// NB: Strictly speaking this condition does not say that "p_inv" is the pseudo-inverse.
|
// NB: Strictly speaking this condition does not say that "p_inv" is the pseudo-inverse.
|
||||||
// However, the variable elimination lemma stays valid even if "p_inv" is not really the pseudo-inverse anymore (e.g., because of parity was reduced)
|
// However, the variable elimination lemma stays valid even if "p_inv" is not really the pseudo-inverse anymore (e.g., because of parity was reduced)
|
||||||
|
@ -608,7 +608,7 @@ namespace polysat {
|
||||||
if (m_inverse.size() > v && m_inverse[v] != -1)
|
if (m_inverse.size() > v && m_inverse[v] != -1)
|
||||||
return s.var(m_inverse[v]);
|
return s.var(m_inverse[v]);
|
||||||
|
|
||||||
pvar inv = s.add_var(p.power_of_2());
|
pvar inv = s.add_var(p.power_of_2(), pvar_kind::internal);
|
||||||
pdd inv_pdd = s.var(inv);
|
pdd inv_pdd = s.var(inv);
|
||||||
m_inverse.setx(v, inv, -1);
|
m_inverse.setx(v, inv, -1);
|
||||||
s.add_clause(s.eq(inv_pdd * p, p.manager().one()), false);
|
s.add_clause(s.eq(inv_pdd * p, p.manager().one()), false);
|
||||||
|
@ -634,7 +634,7 @@ namespace polysat {
|
||||||
needs_propagate = !tuple.second[parity];
|
needs_propagate = !tuple.second[parity];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
odd_v = s.add_var(p.power_of_2());
|
odd_v = s.add_var(p.power_of_2(), pvar_kind::internal);
|
||||||
verbose_stream() << "Odd part v" << odd_v << " of " << p << " introduced\n";
|
verbose_stream() << "Odd part v" << odd_v << " of " << p << " introduced\n";
|
||||||
m_odd.setx(v, optional<std::pair<pvar, bool_vector>>({ odd_v, bool_vector(p.power_of_2(), false) }), optional<std::pair<pvar, bool_vector>>::undef());
|
m_odd.setx(v, optional<std::pair<pvar, bool_vector>>({ odd_v, bool_vector(p.power_of_2(), false) }), optional<std::pair<pvar, bool_vector>>::undef());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue