3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-19 15:16:29 +00:00

Merge branch 'master' into goal2sat-skip-single-ref-cache

This commit is contained in:
Nikolaj Bjorner 2026-06-16 11:10:27 -07:00 committed by GitHub
commit f4cdcce434
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 213 additions and 72 deletions

View file

@ -60,6 +60,7 @@
<Warn>4</Warn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>$(OutputPath)\Microsoft.Z3.xml</DocumentationFile>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<!-- Compilation items -->

View file

@ -5400,10 +5400,20 @@
"dev": true
},
"node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz",
"integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"uc.micro": "^2.0.0"
@ -5501,15 +5511,25 @@
}
},
"node_modules/markdown-it": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz",
"integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"linkify-it": "^5.0.1",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"

View file

@ -768,7 +768,7 @@ void bit_blaster_tpl<Cfg>::mk_smod(unsigned sz, expr * const * a_bits, expr * co
template<typename Cfg>
void bit_blaster_tpl<Cfg>::mk_eq(unsigned sz, expr * const * a_bits, expr * const * b_bits, expr_ref & out) {
expr_ref_vector out_bits(m());
out_bits.reserve(sz);
out_bits.resize(sz);
for (unsigned i = 0; i < sz; ++i) {
mk_iff(a_bits[i], b_bits[i], out);
out_bits[i] = out;

View file

@ -86,9 +86,15 @@ namespace seq {
}
/*
Collect the leaves of a t-regex der (an ITE / antimirov union /
union-tree with regex leaves) into the output vector. Empty
(re.empty) leaves are dropped.
Collect the leaves of a t-regex der (an ITE-tree whose leaves are
regex expressions) into the output vector. Empty (re.empty) leaves
are dropped.
Each leaf is treated as a single bisimulation state regardless of
its top-level shape (including re.union and re.antimirov_union):
descending into a union at the leaf would split one state into
several, which is semantically unsound for the bisimulation /
union-find merging that follows.
Returns false if we encountered an unexpected node (e.g. a free
variable creeping in) in that case the caller should bail out.
@ -102,9 +108,7 @@ namespace seq {
expr* e = work.back();
work.pop_back();
expr* c = nullptr, * t = nullptr, * f = nullptr;
if (m.is_ite(e, c, t, f) ||
m_util.re.is_union(e, t, f) ||
m_util.re.is_antimirov_union(e, t, f)) {
if (m.is_ite(e, c, t, f)) {
if (seen.insert_if_not_there(t))
work.push_back(t);
if (seen.insert_if_not_there(f))

View file

@ -45,7 +45,7 @@ Author:
class dependent_expr_state {
unsigned m_qhead = 0;
bool m_suffix_frozen = false;
unsigned m_num_recfun = 0, m_num_lambdas = 0;
unsigned m_num_recfun = 0;
lbool m_has_quantifiers = l_undef;
ast_mark m_frozen;
func_decl_ref_vector m_frozen_trail;

View file

@ -4672,7 +4672,6 @@ namespace smt {
theory_id th_id = l->get_id();
for (enode * parent : enode::parents(n)) {
auto p = parent->get_expr();
family_id fid = parent->get_family_id();
if (fid != th_id && fid != m.get_basic_family_id()) {
if (is_beta_redex(parent, n))

View file

@ -66,7 +66,6 @@ namespace smt {
unsigned m_final_check_ls_steps = 30000;
unsigned m_final_check_ls_steps_delta = 10000;
unsigned m_final_check_ls_steps_min = 10000;
unsigned m_final_check_ls_steps_max = 30000;
bool m_has_unassigned_clause_after_resolve = false;
unsigned m_after_resolve_decide_gap = 4;
unsigned m_after_resolve_decide_count = 0;

View file

@ -460,7 +460,6 @@ class parallel_solver {
};
unsigned id;
parallel_solver& p;
batch_manager& b;
ast_manager m; /* worker-local manager */
ref<solver> s; /* translated solver copy */
@ -579,7 +578,7 @@ class parallel_solver {
worker(unsigned id, parallel_solver& p,
solver& src, params_ref const& params,
expr_ref_vector const& src_asms)
: id(id), p(p), b(p.m_batch_manager),
: id(id), b(p.m_batch_manager),
asms(m), m_g2l(src.get_manager(), m), m_l2g(m, src.get_manager())
{
/* create translated solver copy */

View file

@ -185,6 +185,10 @@ public:
expr_safe_replace rep(m);
tactic_report report("lia2card", *g);
if (recfun::util(m()).has_rec_defs()) {
result.push_back(g.get());
return;
}
bound_manager bounds(m);
for (unsigned i = 0; i < g->size(); ++i)

View file

@ -452,7 +452,7 @@ static void project(nlsat::solver& s, nlsat::explain& ex, nlsat::var x, unsigned
std::cout << "\n";
}
static void project_fa(nlsat::solver& s, nlsat::explain& ex, nlsat::var x, unsigned num, nlsat::literal const* lits) {
static nlsat::scoped_literal_vector project_fa(nlsat::solver& s, nlsat::explain& ex, nlsat::var x, unsigned num, nlsat::literal const* lits) {
std::cout << "Project ";
nlsat::scoped_literal_vector result(s);
ex.compute_conflict_explanation(num, lits, result);
@ -464,6 +464,7 @@ static void project_fa(nlsat::solver& s, nlsat::explain& ex, nlsat::var x, unsig
s.display(std::cout << " ", ~lits[i]);
}
std::cout << ")\n";
return result;
}
static nlsat::literal mk_gt(nlsat::solver& s, nlsat::poly* p) {
@ -490,6 +491,39 @@ static nlsat::literal mk_root_eq(nlsat::solver& s, nlsat::poly* p, nlsat::var x,
return nlsat::literal(b, false);
}
static bool contains_var(nlsat::var_vector const& vars, nlsat::var x) {
for (auto v : vars) {
if (v == x)
return true;
}
return false;
}
static bool clause_contains_root_dependency(
nlsat::solver& s,
nlsat::scoped_literal_vector const& result,
nlsat::atom::kind kind,
nlsat::var target,
unsigned root_index,
nlsat::var dep1,
nlsat::var dep2,
nlsat::var dep3) {
nlsat::pmanager& pm = s.pm();
nlsat::var_vector vars;
for (auto l : result) {
nlsat::atom* a = s.bool_var2atom(l.var());
if (!a || !a->is_root_atom() || a->get_kind() != kind)
continue;
nlsat::root_atom* ra = nlsat::to_root_atom(a);
if (ra->x() != target || ra->i() != root_index || pm.max_var(ra->p()) != target)
continue;
s.vars(l, vars);
if (contains_var(vars, dep1) && contains_var(vars, dep2) && contains_var(vars, dep3))
return true;
}
return false;
}
static void set_assignment_value(nlsat::assignment& as, anum_manager& am, nlsat::var v, rational const& val) {
scoped_anum tmp(am);
am.set(tmp, val.to_mpq());
@ -1183,8 +1217,8 @@ static void tst_15() {
auto cell = lws.single_cell();
}
// Test case for unsound lemma lws2380 - comparing standard projection vs levelwise
// The issue: x7 is unconstrained in levelwise output but affects the section polynomial
// Historical lws2380 regression test: both projection paths should preserve
// the x7-linked section/root constraints that witness the projected dependency.
static void tst_16() {
// enable_trace("nlsat_explain");
@ -1283,8 +1317,9 @@ static void tst_16() {
lits.push_back(mk_gt(s, p0.get())); // x13 > 0
lits.push_back(mk_gt(s, p1.get())); // p1 > 0
project_fa(s, ex, x13, lits.size(), lits.data());
auto result = project_fa(s, ex, x13, lits.size(), lits.data());
std::cout << "\n";
ENSURE(clause_contains_root_dependency(s, result, nlsat::atom::ROOT_EQ, x11, 1, x7, x8, x10));
};
run_test(false); // Standard projection
@ -2144,11 +2179,11 @@ static void tst_22() {
}
}
if (all_false) {
if (all_false)
std::cout << "*** ALL literals FALSE at counterexample - LEMMA IS UNSOUND! ***\n";
} else {
else
std::cout << "At least one literal is TRUE - lemma is sound at this point\n";
}
ENSURE(!all_false);
};
run_test(false); // lws=false (buggy)

View file

@ -62,10 +62,6 @@ public:
struct key_data {
Key * m_key = nullptr;
Value m_value;
key_data() = default;
key_data(Key* k): m_key(k) {}
key_data(Key* k, Value const& v): m_key(k), m_value(v) {}
key_data(Key* k, Value&& v): m_key(k), m_value(std::move(v)) {}
Value const & get_value() const { return m_value; }
Key & get_key () const { return *m_key; }
unsigned hash() const { return m_key->hash(); }
@ -136,15 +132,15 @@ public:
}
void insert(Key * const k, Value const & v) {
m_table.insert(key_data(k, v));
m_table.insert(key_data{k, v});
}
void insert(Key * const k, Value && v) {
m_table.insert(key_data(k, std::move(v)));
m_table.insert(key_data{k, std::move(v)});
}
Value& insert_if_not_there(Key * k, Value const & v) {
return m_table.insert_if_not_there2(key_data(k, v))->get_data().m_value;
return m_table.insert_if_not_there2(key_data{k, v})->get_data().m_value;
}
Value& insert_if_not_there(Key * k, Value && v) {
@ -194,7 +190,7 @@ public:
}
iterator find_iterator(Key * k) const {
return m_table.find(key_data(k));
return m_table.find(key_data{k});
}
bool contains(Key * k) const {
@ -202,7 +198,7 @@ public:
}
void remove(Key * k) {
m_table.remove(key_data(k));
m_table.remove(key_data{k});
}
void erase(Key * k) {
@ -213,7 +209,7 @@ public:
void get_collisions(Key * k, vector<Key*>& collisions) {
vector<key_data> cs;
m_table.get_collisions(key_data(k), cs);
m_table.get_collisions(key_data{k}, cs);
for (key_data const& kd : cs) {
collisions.push_back(kd.m_key);
}

View file

@ -59,17 +59,13 @@ protected:
class entry;
public:
class key_data {
Key1 * m_key1;
Key2 * m_key2;
Key1 * m_key1 = nullptr;
Key2 * m_key2 = nullptr;
Value m_value;
unsigned m_hash;
unsigned m_hash = 0;
friend class entry;
public:
key_data():
m_key1(nullptr),
m_key2(nullptr),
m_hash(0) {
}
key_data() = default;
key_data(Key1 * k1, Key2 * k2):
m_key1(k1),
m_key2(k2) {

View file

@ -60,19 +60,14 @@ protected:
class entry;
public:
class key_data {
Key1 * m_key1;
Key2 * m_key2;
Key3 * m_key3;
Key1 * m_key1 = nullptr;
Key2 * m_key2 = nullptr;
Key3 * m_key3 = nullptr;
Value m_value;
unsigned m_hash;
unsigned m_hash = 0;
friend class entry;
public:
key_data():
m_key1(nullptr),
m_key2(nullptr),
m_key3(nullptr),
m_hash(0) {
}
key_data() = default;
key_data(Key1 * k1, Key2 * k2, Key3 * k3):
m_key1(k1),
m_key2(k2),

View file

@ -30,17 +30,6 @@ class symbol_table {
struct key_data {
symbol m_key;
T m_data;
key_data() = default;
explicit key_data(symbol k):
m_key(k) {
}
key_data(symbol k, const T & d):
m_key(k),
m_data(d) {
}
};
struct key_data_hash_proc {
@ -129,7 +118,7 @@ public:
}
bool contains(symbol key) const {
return m_sym_table.contains(key_data(key));
return m_sym_table.contains(key_data{key});
}
unsigned get_scope_level() const {
@ -148,11 +137,11 @@ public:
m_trail_stack.push_back(dummy);
key_data & new_entry = m_trail_stack.back();
new_entry.m_key = symbol::mark(new_entry.m_key);
m_sym_table.insert(key_data(key, data));
m_sym_table.insert(key_data{key, data});
}
}
else {
m_sym_table.insert(key_data(key, data));
m_sym_table.insert(key_data{key, data});
}
}