Skip to content

Commit 51e6800

Browse files
shaobo-heclaude
andcommitted
z3: strip (exit)/(get-model) before appending the tactic
Many SMT-LIB files end with `(check-sat) (exit)`. The preprocessing stripped only `(check-sat)` and appended `(apply <tactic>)` at the end, so a leftover `(exit)` made z3 quit before the tactic ran -> empty output -> silent fallback to the unsimplified file. On the real SMT-COMP QF_FP set this made --simplify a no-op (handled 3/151); with the fix it handles 125/151 (the rest declare a RoundingMode variable, which the evaluator doesn't model). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ff9bcab commit 51e6800

1 file changed

Lines changed: 11 additions & 4 deletions

File tree

src/z3.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,18 @@ fn apply_z3_tactic(path: &str, tactic: &str, tag: &str) -> std::io::Result<std::
181181
.filter(|e| matches!(e.head_sym(), Some("declare-const") | Some("declare-fun")))
182182
.collect();
183183

184+
// Strip the trailing solver commands and append the tactic application.
185+
// We must remove `(exit)` (and `(get-model)` etc.) too, not just
186+
// `(check-sat)`: many SMT-LIB files end with `(check-sat) (exit)`, and a
187+
// leftover `(exit)` makes z3 quit *before* reaching the appended tactic
188+
// (producing empty output and a silent fallback to the unsimplified file).
189+
let stripped = raw
190+
.replace("(check-sat)", "")
191+
.replace("(exit)", "")
192+
.replace("(get-model)", "")
193+
.replace("(get-unsat-core)", "");
184194
let tactic_file = temp_path(&format!("{tag}-in"));
185-
std::fs::write(
186-
&tactic_file,
187-
format!("{}\n(apply {tactic})\n", raw.replace("(check-sat)", "")),
188-
)?;
195+
std::fs::write(&tactic_file, format!("{stripped}\n(apply {tactic})\n"))?;
189196
// If z3 is unavailable, transparently fall back to the original file.
190197
let output = match run_z3(&tactic_file) {
191198
Ok(o) => o,

0 commit comments

Comments
 (0)