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

22316 commits

Author SHA1 Message Date
Ilana Shapiro
e88cac2fe1 restore smt_parallel to old/original version so we have a consistent baseline (even though it still includes newer bugs we've identified) 2026-06-16 21:37:11 -07:00
Ilana Shapiro
5c8cbaea3a Handle cancellation for parallel leases 2026-06-16 20:15:10 -07:00
Ilana Shapiro
c10e7c2a6f attempt at lease policy patch 2026-06-16 20:13:33 -07:00
Nikolaj Bjorner
fc5e4d7557 check for lease expiration before checking for m.inc()
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-15 16:00:26 -06:00
Nikolaj Bjorner
48ae786c4c catch exceptions from cube and backbone calls. They can throw
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-15 14:02:43 -06:00
Nikolaj Bjorner
2b9b9a9623 log exceptions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-15 10:28:52 -07:00
Nikolaj Bjorner
4237f9d86b log exceptions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-15 10:03:46 -07:00
Nikolaj Bjorner
4dbd592137 guard cancelation behind !m.inc()
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-14 23:56:48 -07:00
Ilana Shapiro
778760ec98 Merge branch 'solver_parallel' of github.com:Z3Prover/z3 into solver_parallel 2026-06-14 23:32:32 -07:00
Ilana Shapiro
be1b2f6e15 normalize parallel params 2026-06-14 23:31:47 -07:00
Nikolaj Bjorner
dba826039d avoid spurious cancel
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-14 23:31:37 -07:00
Nikolaj Bjorner
e95f9757c9 lipstick
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-14 22:38:40 -07:00
Nikolaj Bjorner
26f7ce23b6 lipstick
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-14 22:29:33 -07:00
Nikolaj Bjorner
38a8644ae3 avoid double cancel
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-14 22:24:21 -07:00
Ilana Shapiro
5b307545e6 change scheduling in old smt_parallel code to keep it updated 2026-06-14 22:02:00 -07:00
Ilana Shapiro
fc3892486c fix cancel bugs and remove smt_parallel_params 2026-06-14 19:55:28 -07:00
Nikolaj Bjorner
84a3c8789f fix scoping for functions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-14 14:06:48 -07:00
Nikolaj Bjorner
96092b196c add exception handling in case run method throws
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-14 13:46:29 -07:00
Nikolaj Bjorner
f2270d4654 make sure split atoms are not already used on the path
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-13 17:01:09 -07:00
Nikolaj Bjorner
f2d5d6fecf add set_canceled to smt_parallel to avoid deadlock
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-13 16:13:47 -07:00
Nikolaj Bjorner
491d990ed1 use structured parameters
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-13 08:38:58 -07:00
Nikolaj Bjorner
bcbfeec6c0 address deadlock in cancellation path
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-13 08:32:34 -07:00
Nikolaj Bjorner
864c6a3f34 remove get/set max conflicts from solver, handle it using updt_params and get_params.
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-12 18:34:08 -07:00
Nikolaj Bjorner
81af0cc230 remove atom
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-12 10:58:11 -07:00
Nikolaj Bjorner
7f1e74c0da remove atom
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-12 10:49:05 -07:00
copilot-swe-agent[bot]
502309f246
Sort cube candidates by activity with tie shuffling 2026-06-12 17:26:55 +00:00
copilot-swe-agent[bot]
af5bbb4566
Restore atom2bool_var.cpp to fix CI build break 2026-06-12 06:37:48 +00:00
copilot-swe-agent[bot]
4b7e4cf08a
Remove const_cast from smt_solver context access 2026-06-12 06:15:29 +00:00
Nikolaj Bjorner
a3f07ba9ab
Update atom2bool_var.cpp 2026-06-11 22:47:32 -07:00
Nikolaj Bjorner
96ac8bfd77 redo priority selection 2026-06-11 16:49:36 -07:00
Nikolaj Bjorner
9485e96416 signatrue update 2026-06-11 15:59:08 -07:00
Nikolaj Bjorner
6b91b5a1dd Merge branch 'solver_parallel' of https://github.com/z3prover/z3 into solver_parallel 2026-06-11 15:54:04 -07:00
Nikolaj Bjorner
deb9fe4240 use bool_var instead of unsigned 2026-06-11 15:53:44 -07:00
Nikolaj Bjorner
49d725f477 refactor 2026-06-11 15:40:38 -07:00
Nikolaj Bjorner
de028f33a2
Update inc_sat_solver.cpp 2026-06-11 15:40:11 -07:00
Nikolaj Bjorner
5aa06b6333 refactor phase update 2026-06-11 15:28:48 -07:00
Nikolaj Bjorner
e06ca1489e remove parallal_stats 2026-06-11 14:51:28 -07:00
Nikolaj Bjorner
6ef8660adb
Parallel tactic (#9824)
Co-authored-by: Ilana Shapiro <ilanashapiro@Ilanas-MacBook-Pro.local>
Co-authored-by: Ilana Shapiro <ilanashapiro@Ilanas-MBP.localdomain>
2026-06-11 09:14:00 -07:00
Eric Astor
677abb589e
Add rlimit support in fixedpoint parameters (#9798)
The C++ implementation of the fixedpoint engine (in
z3/src/api/api_datalog.cpp) already attempts to read `rlimit` from its
local parameters:

```c++
unsigned rlimit = to_fixedpoint(d)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
```

However, because `rlimit` was not registered in the public fp parameter
schema (`fp_params.pyg`), any attempt by clients to set it locally via
`Z3_fixedpoint_set_params` was rejected by the Z3 parameter validator
with an "unknown parameter" error.
2026-06-10 15:13:05 -07:00
Nikolaj Bjorner
384414b10c
Update seq_regex_bisim.h 2026-06-10 15:06:12 -07:00
Nikolaj Bjorner
44a561ec46
Update seq_regex_bisim.cpp 2026-06-10 15:04:24 -07:00
Nikolaj Bjorner
207e6b439a
Update seq_regex_bisim.cpp 2026-06-10 15:03:46 -07:00
Margus Veanes
513b81253b
Add OP_RE_XOR and union-find bisimulation for ground regex equivalence (#9804)
Implements the algorithm of Eq(p,q) = Empty(p XOR q)' using a union-find
driven bisimulation closure (per the CAV'26 ERE paper).

### What's added

* **New primitive OP_RE_XOR (re.xor)** wired through seq_decl_plugin:
parser signature, info propagation (nullable, min_length), and
pretty-printer.
* **seq_rewriter**: structural XOR rewrites ( XOR r = empty, XOR empty =
r, ull XOR r = comp(r), comp/comp absorption, complement push, AC
normalisation), nullability (Null(p XOR q) = Null(p) != Null(q)),
derivative (D_a(p XOR q) = D_a(p) XOR D_a(q)), reverse, antimirov
derivative, and `check_deriv_normal_form` coverage.
* **New class seq::regex_bisim** in
`src/ast/rewriter/seq_regex_bisim.{h,cpp}` to keep the bisim logic out
of the already-large `seq_rewriter.cpp`. Uses `basic_union_find` from
`util/union_find.h`, an `obj_map` for the node assignment, and a
50000-step bound (returns `l_undef` on overrun).
* **Integration** in `seq_rewriter::reduce_re_eq` (with a re-entry
guard) and in `seq_regex::propagate_eq` / `propagate_ne` for ground
regexes; on `l_undef` we fall back to the existing axiomatisation.
* **`sls_seq_plugin`**: extend `OP_RE_DIFF` switch arms to also cover
`OP_RE_XOR`.

### Validation

* Full release build with MSVC + Ninja.
* `./test-z3 /a` -- 89/89 tests passing.
* `./test-z3 /seq smt2print_parse` -- PASS.
* Smoke tests with `(a|b)*` vs `(a*b*)*` (equal) and `a*` vs `(a|b)*`
(not equal) return the expected `sat`/`unsat` quickly.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-10 14:58:20 -07:00
dependabot[bot]
589bd9e6f5
Bump shell-quote from 1.7.3 to 1.8.4 in /src/api/js (#9803)
Bumps [shell-quote](https://github.com/ljharb/shell-quote) from 1.7.3 to
1.8.4.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ljharb/shell-quote/blob/main/CHANGELOG.md">shell-quote's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/ljharb/shell-quote/compare/v1.8.3...v1.8.4">v1.8.4</a>
- 2026-05-22</h2>
<h3>Commits</h3>
<ul>
<li>[Fix] <code>quote</code>: validate object-token shapes <a
href="4378a6e613"><code>4378a6e</code></a></li>
<li>[Dev Deps] update <code>@ljharb/eslint-config</code>,
<code>auto-changelog</code>, <code>eslint</code>, <code>npmignore</code>
<a
href="22ebec0434"><code>22ebec0</code></a></li>
<li>[Tests] increase coverage <a
href="9f3caa3190"><code>9f3caa3</code></a></li>
<li>[readme] replace runkit CI badge with shields.io check-runs badge <a
href="3344a047dd"><code>3344a04</code></a></li>
<li>[Dev Deps] update <code>@ljharb/eslint-config</code> <a
href="699c5113d1"><code>699c511</code></a></li>
</ul>
<h2><a
href="https://github.com/ljharb/shell-quote/compare/v1.8.2...v1.8.3">v1.8.3</a>
- 2025-06-01</h2>
<h3>Fixed</h3>
<ul>
<li>[Fix] remove unnecessary backslash escaping in single quotes <a
href="https://redirect.github.com/ljharb/shell-quote/issues/15"><code>[#15](https://github.com/ljharb/shell-quote/issues/15)</code></a></li>
</ul>
<h2><a
href="https://github.com/ljharb/shell-quote/compare/v1.8.1...v1.8.2">v1.8.2</a>
- 2024-11-27</h2>
<h3>Fixed</h3>
<ul>
<li>[Fix] <code>quote</code>: preserve empty strings <a
href="https://redirect.github.com/ljharb/shell-quote/issues/18"><code>[#18](https://github.com/ljharb/shell-quote/issues/18)</code></a></li>
</ul>
<h3>Commits</h3>
<ul>
<li>[meta] fix changelog tags <a
href="0fb9fd8441"><code>0fb9fd8</code></a></li>
<li>[actions] split out node 10-20, and 20+ <a
href="819bd842e0"><code>819bd84</code></a></li>
<li>[Dev Deps] update <code>@ljharb/eslint-config</code>,
<code>auto-changelog</code>, <code>npmignore</code>, <code>tape</code>
<a
href="fc564086c8"><code>fc56408</code></a></li>
<li>[actions] update npm for windows tests <a
href="fdeb0fd102"><code>fdeb0fd</code></a></li>
<li>[Dev Deps] update <code>@ljharb/eslint-config</code>,
<code>aud</code>, <code>tape</code> <a
href="b8a4a3b3f5"><code>b8a4a3b</code></a></li>
<li>[actions] prevent node 14 on ARM mac from failing <a
href="9eecafc048"><code>9eecafc</code></a></li>
<li>[meta] exclude more files from the package <a
href="4044e7fad4"><code>4044e7f</code></a></li>
<li>[Tests] replace <code>aud</code> with <code>npm audit</code> <a
href="8cfdbd8ec3"><code>8cfdbd8</code></a></li>
<li>[meta] add missing <code>engines.node</code> <a
href="843820e1a4"><code>843820e</code></a></li>
<li>[Dev Deps] add missing peer dep <a
href="4c3b88d792"><code>4c3b88d</code></a></li>
<li>[Dev Deps] pin <code>jackspeak</code> since 2.1.2+ depends on npm
aliases, which kill the install process in npm &lt; 6 <a
href="80322ed591"><code>80322ed</code></a></li>
</ul>
<h2><a
href="https://github.com/ljharb/shell-quote/compare/v1.8.0...v1.8.1">v1.8.1</a>
- 2023-04-07</h2>
<h3>Fixed</h3>
<ul>
<li>[Fix] <code>parse</code>: preserve whitespace in comments <a
href="https://redirect.github.com/ljharb/shell-quote/issues/6"><code>[#6](https://github.com/ljharb/shell-quote/issues/6)</code></a></li>
<li>[Fix] properly support the <code>escape</code> option <a
href="https://redirect.github.com/ljharb/shell-quote/issues/5"><code>[#5](https://github.com/ljharb/shell-quote/issues/5)</code></a></li>
</ul>
<h3>Commits</h3>
<ul>
<li>[Refactor] <code>parse</code>: hoist <code>getVar</code> to module
level <a
href="b42ac73e39"><code>b42ac73</code></a></li>
<li>[Refactor] hoist some vars to module level <a
href="8f0c5c3c9d"><code>8f0c5c3</code></a></li>
<li>[Refactor] <code>parse</code>: use <code>slice</code> over
<code>substr</code>, cache some values <a
href="fcb2e1acd5"><code>fcb2e1a</code></a></li>
<li>[Refactor] <code>parse</code>: a bit of cleanup <a
href="6780ec5194"><code>6780ec5</code></a></li>
<li>[Refactor] <code>parse</code>: tweak the regex to not match nothing
<a
href="227d4742a0"><code>227d474</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="ff166e2b63"><code>ff166e2</code></a>
v1.8.4</li>
<li><a
href="4378a6e613"><code>4378a6e</code></a>
[Fix] <code>quote</code>: validate object-token shapes</li>
<li><a
href="22ebec0434"><code>22ebec0</code></a>
[Dev Deps] update <code>@ljharb/eslint-config</code>,
<code>auto-changelog</code>, <code>eslint</code>, `npmig...</li>
<li><a
href="9f3caa3190"><code>9f3caa3</code></a>
[Tests] increase coverage</li>
<li><a
href="3344a047dd"><code>3344a04</code></a>
[readme] replace runkit CI badge with shields.io check-runs badge</li>
<li><a
href="699c5113d1"><code>699c511</code></a>
[Dev Deps] update <code>@ljharb/eslint-config</code></li>
<li><a
href="487a9b41a7"><code>487a9b4</code></a>
v1.8.3</li>
<li><a
href="01faafff97"><code>01faaff</code></a>
[Fix] remove unnecessary backslash escaping in single quotes</li>
<li><a
href="b19fc77e66"><code>b19fc77</code></a>
v1.8.2</li>
<li><a
href="59d29ea694"><code>59d29ea</code></a>
[Fix] <code>quote</code>: preserve empty strings</li>
<li>Additional commits viewable in <a
href="https://github.com/ljharb/shell-quote/compare/v1.7.3...v1.8.4">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~ljharb">ljharb</a>, a new releaser for
shell-quote since your current version.</p>
</details>
<details>
<summary>Install script changes</summary>
<p>This version adds <code>prepublish</code> script that runs during
installation. Review the package contents before updating.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=shell-quote&package-manager=npm_and_yarn&previous-version=1.7.3&new-version=1.8.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/Z3Prover/z3/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-10 08:40:36 -07:00
Lev Nachmanson
1b2ca1a1bf
Fix off-by-one column after comment lines in SMT2 scanner (#9808)
This bug was discovered by claude analyzing the descrepency of outputs
in https://github.com/Z3Prover/bench/discussions/2516. The benchmark was
edited - a line required stats was commented out - and this exposed the
scanner inconsistent behavior.
read_comment and read_multiline_comment handled end-of-line newlines as
new_line(); next();, the reverse of the main scan() loop's next();
new_line();. This left m_spos one higher on the line following a
comment, shifting every reported column on that line by +1 (e.g. a (pop)
error reported column 5 instead of 4 when the previous line was a
comment). Reorder both comment readers to match scan() so column numbers
are consistent regardless of whether the preceding line is a comment.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-10 06:49:31 -07:00
Copilot
e093be8b60
seq_rewriter: add missing concat rewrites for nullable/full-seq/star cases (#9782)
`seq_rewriter.cpp` was missing several regex-concat normalizations
around `re.all` (`Σ*`), causing avoidable growth and missed
simplifications. This update fills the four gaps: nullable absorption,
guarded union distribution, intersection suffix elimination, and
nested-star collapse.

- **Nullable/full-seq absorption (A1)**
  - Generalizes `Σ*·R → Σ*` and `R·Σ* → Σ*` beyond `Σ*·Σ*`.
  - Applies when `R` is interpreted, nullable, and has `min_length = 0`.

- **Guarded distribution over union (A2)**
- Adds `Σ*·(R1 ∪ R2)` distribution when at least one arm is already
`Σ*`-headed.
- Rebuilds via normalized union so the redundant arm collapses to `Σ*`.

- **Intersection + full-seq tail elimination (A3)**
- Adds `(R1 ∩ … ∩ Rn)·Σ* → (R1 ∩ … ∩ Rn)` when every intersection leaf
already ends in `Σ*`.

- **Nested star concat collapse (A4)**
- Adds `R*·(R*·X) → R*·X`, covering non-adjacent star patterns not
handled by the prior adjacent-only rewrite.

```cpp
if (re().is_full_seq(a) && accepts_empty_word(b)) result = a;               // A1
if (re().is_full_seq(a) && re().is_union(b, u1, u2) && ...) ...             // A2
if (re().is_intersection(a, u1, u2) && re().is_full_seq(b) && ...) result=a; // A3
if (re().is_star(a, a1) && re().is_concat(b, b1, b2) && re().is_star(b1,b3) && a1==b3) result=b; // A4
```

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-09 14:38:38 -07:00
Copilot
d415ead6a2
Port is_classical attribute to seq_util::rex::info (#9796)
`is_classical` (tracks whether a regex uses only classical operators —
no complement, intersection, diff, or empty-language/fail) was only
available on `euf::snode`. Moving it into `seq_util::rex::info` makes it
accessible to all regex-handling code without going through the snode
layer.

### Changes

**`seq_decl_plugin.h`**
- Added `bool classical { true }` to `seq_util::rex::info`
- The general `info` constructor requires `bool is_classical` explicitly
(no default)

**`seq_decl_plugin.cpp`**
- `mk_info_rec`: `OP_RE_EMPTY_SET` (fail) sets `classical=false`
- `mk_info_rec`: `OP_RE_RANGE`, `OP_RE_FULL_CHAR_SET`, `OP_RE_OF_PRED`
set `classical=false`
- `complement()`, `conj()` (intersection), `diff()`: always produce
`classical=false`
- `star()`, `plus()`, `opt()`, `concat()`, `disj()`, `orelse()`,
`loop()`: propagate `classical` via logical AND over operands
- `operator=` and `display()` updated to include `classical`

### Semantics

| Operation | `classical` |
|-----------|-------------|
| `re.empty` (fail) | `false` |
| `re.range`, `re.allchar`, `re.of.pred` | `false` |
| `re.comp` (complement) | `false` |
| `re.inter` (intersection) | `false` |
| `re.diff` | `false` |
| `re.all` (full sequence set) | `true` |
| `str.to.re` (string literal) | `true` |
| `re.*`, `re.+`, `re.opt`, `re.++`, `re.union`, `re.loop` | inherited
from operands |

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-09 14:35:48 -07:00
Copilot
f0956a622f
Refactor regex subset logic into seq_subset with depth-bounded recursion and optimized concat traversal (#9777)
`seq_rewriter::is_subset` was too localized and missed key subset
implications for regex concatenations. This change extracts subset
reasoning into a dedicated component and adds heuristic
closure/monotonicity rules, then tunes the recursion strategy based on
profiling feedback.

- **Architecture: isolate subset reasoning**
  - Introduce `seq_subset` in `src/ast/rewriter` (`seq_subset.h/.cpp`).
- Add `seq_subset` as an attribute on `seq_rewriter` and route
`seq_rewriter::is_subset` through it.
- Keep `seq_rewriter` focused on rewrite orchestration while subset
logic evolves independently.

- **Subset rules: broaden inferable cases**
- Add derive-style subset decomposition across `union`, `intersection`,
`complement`, `concat`, and bounded `loop`.
  - Add E3-style closure rules:
    - `R ⊆ R*`
    - `R1* ⊆ R2*  ⇐  R1 ⊆ R2`
    - `R1+ ⊆ R2+  ⇐  R1 ⊆ R2`
  - Add missing cheap cases:
    - `ε ⊆ R` when `R` is nullable
    - `R ⊆ R+`
    - `R+ ⊆ R*`
    - Range containment: `[c1–c2] ⊆ [c3–c4]` when `c3 ≤ c1 ∧ c2 ≤ c4`
    - `to_re(s) ⊆ range` for single-character string constants
    - Difference monotonicity: `a1 \ a2 ⊆ b` when `a1 ⊆ b`
- Star absorption checks for concat/star combinations (`R·R* ⊆ R*`,
`R*·R ⊆ R*`)
- Preserve nullable-based `. +` handling and top/bottom regular-language
shortcuts.

- **Concatenation reasoning and traversal tuning**
- Remove `flatten_concat` and assume right-associative concatenation
traversal.
- Keep containment shortcuts for both `R ⊆ Σ*·R'` and `R ⊆ R'·Σ*` when
`R ⊆ R'`.
  - Make concat/concat handling tail-recursive on second arguments.

- **Depth-bounded recursion (profiling follow-up)**
- Replace visited-pair hash-table recursion state with an explicit depth
parameter in `is_subset_rec`.
  - Add `m_max_depth = 3` and return `false` when the bound is reached.
- Increment depth on recursive calls, except for the tail-recursive
concat-second-argument step.

- **Build integration**
  - Register `seq_subset.cpp` in `src/ast/rewriter/CMakeLists.txt`.

```cpp
// seq_rewriter.cpp
bool seq_rewriter::is_subset(expr* r1, expr* r2) const {
    return m_subset.is_subset(r1, r2);
}
```

---------

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-09 13:42:28 -07:00
Lev Nachmanson
6eeb274cd2
Fix FPA incremental soundness for fp.to_* terms (#9022) (#9787)
Fixes #9022.

## Problem

After a `(push)`, Z3 could incorrectly report `unsat` for satisfiable
FPA formulas in which an uninterpreted function returns a floating-point
value (e.g. `int_to_fp`). The example in #9022 has a single `push` and a
single `check-sat` (no `pop`), so the `m_rw.reset()` added in
`pop_scope_eh` by #8712 does not apply.

## Root cause

`theory_fpa` lazily converts FP constraints to bit-vectors and asserts
the equivalences/side conditions as **unit theory axioms**
(`assert_cnstr` → `mk_th_axiom`, which `assign`s the literal at the
current decision level).

For `fp.to_*` terms (`fp.to_real`, `fp.to_ubv`, …) the conversion
equality and side conditions are emitted **only** in
`internalize_term()`, which runs exactly once. The `else if` branch for
fpa-family conversion terms in `relevant_eh` previously did nothing.

These unit axioms are level-local: on DPLL backtracking the assignment
is undone, but `internalize_term()` is not re-run for the
already-internalized term (in particular when the term lives at the
user-`push` base level, where its clause is not a reinit clause). The
side conditions include the axioms linking FP uninterpreted functions to
their bit-vector counterparts (`int_to_fp(i) =
fp(extract(int_to_fp_bv(i)))`). Once lost, `int_to_fp_bv` becomes
unconstrained, enabling an unsound `unsat`. This is exactly the behavior
described in #8345/#9022 (and why the result flips with vs. without
`push`).

## Fix

`relevant_eh` re-fires on relevancy re-propagation after a backtrack.
Re-emit the conversion equality and side conditions for `fp.to_*` terms
there, mirroring `internalize_term`, so the FP↔BV linking axioms stay in
force across backtracking. On an `m_conversions` cache hit this just
re-asserts the (hash-consed) conversion equality and a `true` side
condition, so it adds no new terms and no clause bloat. The change only
adds sound constraints, so it can never turn a satisfiable formula
`unsat`.

## Validation

- #9022 reproducer: no longer reports `unsat` across many random seeds
and longer timeouts; a model (`sat`) is still found (the problem is
inherently hard quantified FP + nonlinear arithmetic, so timeouts are
expected).
- #8345 reproducer: first `check-sat` still `unsat` (the negated
quantifier axiom is valid).
- Additional incremental push/pop FP cases with
`fp.to_real`/`fp.add`/`fp.sub` and FP-returning UFs: correct, consistent
results.
- `test-z3 /a`: all 89 unit tests pass.
- Debug build (soundness assertions enabled): no assertion failures on
the above cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-09 10:22:03 -07:00
Copilot
a5495b78fa
Avoid invalidated column-cell references in LP pivot paths (#9783)
MSVC ASan reports showed a container-overflow in LP tableau pivoting,
reproducible from both examples and solver tests (issue #9781). The
failure came from reading a `column_cell` through a reference after
pivoting removed that entry from the backing column.

- **Root cause**
- `pivot_column_tableau` and the analogous Diophantine elimination loop
both held `auto& c = column.back()` across a call
(`pivot_row_to_row_given_cell`) that immediately removes that very cell
from the column via `remove_element`.
- After the mutation, the subsequent read `c.var()` used for bookkeeping
observed invalid memory.

- **Change**
- Record the affected row in the bookkeeping set (`m_touched_rows` /
`m_changed_rows`) by reading `c.var()` **before** the pivot call, while
the back cell is still valid.
- Make `static_matrix::pivot_row_to_row_given_cell` return `void`
instead of `bool`. Its result (`!rowii.empty()`) was always `true`: both
callers keep the matrix at full row rank (the tableau basis columns form
an identity submatrix; the Diophantine `m_l_matrix` stays invertible),
so an elementary row operation can never empty a row. The dead `if
(!...) return false;` early-exit in `pivot_column_tableau` is removed
and replaced with a `SASSERT(!rowii.empty())` documenting the invariant.

- **Affected code paths**
- `src/math/lp/static_matrix.h`, `src/math/lp/static_matrix.cpp`,
`src/math/lp/static_matrix_def.h`
  - `src/math/lp/lp_core_solver_base_def.h`
  - `src/math/lp/dioph_eq.cpp`

- **Behavioral impact**
  - No algorithmic change to pivoting.
- Removes the stale-reference hazard in the loops that repeatedly
eliminate entries from a column.

```c++
while (column.size() > 1) {
    auto& c = column.back();
    SASSERT(c.var() != piv_row_index);
    if (m_touched_rows != nullptr)
        m_touched_rows->insert(c.var());
    m_A.pivot_row_to_row_given_cell(piv_row_index, c, j);
}
```

- **Verification**
- Reproduced the exact issue #9781 failure on a local ASan build
(`container-overflow` in `pivot_column_tableau`) using the pre-fix code,
and confirmed it is gone with this change.
- The 4 reported tests pass clean under ASan: `c_example`,
`cpp_example`, `test-z3 get_implied_equalities`, `test-z3 quant_solve`.
  - Full `test-z3 /a` suite: 89 passed, 0 failed, 0 ASan errors.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>
Co-authored-by: Lev Nachmanson <levnach@hotmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-09 07:36:05 -07:00