3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-02-24 17:21:21 +00:00

bug fixes

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2025-10-27 05:51:42 +01:00
parent c832802183
commit d847a28589
10 changed files with 118 additions and 76 deletions

View file

@ -27,7 +27,10 @@ Revision History:
std::ostream& operator<<(std::ostream& out, theory_axiom const& ax) {
return out << "axiom";
auto &m = ax.clause.get_manager();
for (auto e : ax.clause)
out << mk_pp(e, m) << " ";
return out;
}
// a ~ set.empty => not (x in a)
@ -36,7 +39,8 @@ void finite_set_axioms::in_empty_axiom(expr *x) {
// Generate: not (x in empty_set)
// where empty_set is the empty set of x's type
sort* elem_sort = x->get_sort();
expr_ref empty_set(u.mk_empty(elem_sort), m);
sort *set_sort = u.mk_finite_set_sort(elem_sort);
expr_ref empty_set(u.mk_empty(set_sort), m);
expr_ref x_in_empty(u.mk_in(x, empty_set), m);
theory_axiom* ax = alloc(theory_axiom, m, "in-empty", x);
@ -357,7 +361,7 @@ void finite_set_axioms::subset_axiom(expr* a) {
void finite_set_axioms::extensionality_axiom(expr *a, expr* b) {
// a != b => set.in (set.diff(a, b) a) != set.in (set.diff(a, b) b)
expr_ref diff_ab(u.mk_difference(a, b), m);
expr_ref diff_ab(u.mk_ext(a, b), m);
expr_ref a_eq_b(m.mk_eq(a, b), m);
expr_ref diff_in_a(u.mk_in(diff_ab, a), m);
@ -370,9 +374,9 @@ void finite_set_axioms::extensionality_axiom(expr *a, expr* b) {
ax->clause.push_back(m.mk_not(diff_in_b));
m_add_clause(ax);
theory_axiom* ax2 = alloc(theory_axiom, m, "extensionality", a, b);
ax2->clause.push_back(m.mk_not(a_eq_b));
ax2->clause.push_back(diff_in_a);
ax2->clause.push_back(diff_in_b);
m_add_clause(ax2);
ax = alloc(theory_axiom, m, "extensionality", a, b);
ax->clause.push_back(a_eq_b);
ax->clause.push_back(diff_in_a);
ax->clause.push_back(diff_in_b);
m_add_clause(ax);
}

View file

@ -11,7 +11,7 @@ Abstract:
Author:
GitHub Copilot Agent 2025
Nikolaj Bjorner (nbjorner) - October 2025
--*/
@ -222,6 +222,44 @@ br_status finite_set_rewriter::mk_in(expr * elem, expr * set, expr_ref & result)
result = m.mk_eq(elem, singleton_elem);
return BR_REWRITE1;
}
// NB we don't rewrite (set.in x (set.union s t)) to (or (set.in x s) (set.in x t))
// because it creates two new sub-expressions. The expression (set.union s t) could
// be shared with other expressions so the net effect of this rewrite could be to create
// a larger formula for the solver.
return BR_FAILED;
}
/**
* if a, b are set expressions we can create an on-the-fly heap for their min-elements
* a, b are normalized to the form (set.union s t) or (set.empty) where
* s is a singleton or range expression such that every element in t are above s.
* we distinguish numerical values from value expressions:
* - for numerical values we use the ordering over numerals to pick minimal ranges
* - for unique value expressions ranging over non-numerals use expression identifiers
* - for other expressions use identifiers to sort expressions, but make sure to be inconclusive
* for set difference
* We want mk_eq_core to produce a result true/false if the arguments are both (unique) values.
* This allows to evaluate models for being well-formed conclusively.
*
* A way to convert a set expression to a heap is as follows:
*
* min({s}) = {s} u {}
* min({}) = {}
* min([l..u]) = [l..u] u {}
* min(s u t) =
* let range_s u s1 = min(s)
* let range_t u t1 = min(t)
* if range_s < range_t:
* range_s u (t u s1)
* if range_t < range_t:
* range_t u (s u t1)
* if range_t n range_s != {}:
* min(range_t, range_s) u the rest ...
* etc.
*/
br_status finite_set_rewriter::mk_eq_core(expr* a, expr* b, expr_ref& result) {
return BR_FAILED;
}

View file

@ -55,5 +55,7 @@ public:
finite_set_util& util() { return m_util; }
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
br_status mk_eq_core(expr *a, expr *b, expr_ref &result);
};

View file

@ -688,6 +688,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
st = m_ar_rw.mk_eq_core(a, b, result);
else if (s_fid == m_seq_rw.get_fid())
st = m_seq_rw.mk_eq_core(a, b, result);
else if (s_fid == m_fs_rw.get_fid())
st = m_fs_rw.mk_eq_core(a, b, result);
if (st != BR_FAILED)
return st;
st = extended_bv_eq(a, b, result);