Skip to content

Conversation

@leventeBajczi
Copy link
Contributor

Old versions of z3 were really good at interpolation, and I want to add support for it in JavaSMT.

To this end, I've added the implementation of a Z3Legacy solver (to be renamed, as discussed with @baierd), which builds on the 4.5.0 release of z3, rebuilt to use com.microsoft.z3legacy as its package name to avoid name collisions with new z3.

Pre-built binaries with the modifications are available at https://github.com/leventeBajczi/z3/releases/tag/legacy-4.3.0-15644597379, which Theta already uses like this. This should be somehow integrated into the solver management of JavaSMT, which I have no experience with.

To demonstrate how good this version of Z3 is, I ran some preliminary tests in CPAchecker, and found that an NLA encoding of programs using Z3 as the interpolation solver in the predicate analysis configuration results in 510 successfully solved tasks, which are otherwise unsolved by the bitprecise encoding of the same tasks with mathsat5.

Also, I found that #381 (which I opened) is referenced in 3 of the tests, that now failed on this implementation. I removed the overly constraining line which expected the constraint IDs to be unique, which is not necessary IMO if the interpolation problem reported in that issue is otherwise handled - which it seems to be.

@baierd
Copy link
Contributor

baierd commented Oct 29, 2025

Thank you very much for the PR! It seems like the old Z3 version is beneficial to have. Could you also post the tables and/or quantile-plots from your experiments (for documentation purposes)?

We need to make sure that there are no issues when running both Z3 instances at the same time! I'll try to start some tests in CPAchecker and report back.

@leventeBajczi
Copy link
Contributor Author

Sure! Here are some:
z3-vs-baseline.table.html
In particular, the #/table?filter=0(0*status*(status(notIn()),category(in(correct)))),1(0*status*(status(notIn()),category(in(error)))) filter shows the real advantage of using Z3 with nonlinear integers complementing the best bitvector config (can solve 510 unsolved tasks).

@baierd
Copy link
Contributor

baierd commented Oct 31, 2025

Thank you very much!

Btw. could you try using Z3 version 4.5 from our Ivy repo?
Maybe the old lib still works?

@leventeBajczi
Copy link
Contributor Author

I haven't used it, but I'd be cautious about using it. The libraries I built use the com.microsoft.z3legacy package, as to not mistakenly use a mismatched java/native library.

@baierd
Copy link
Contributor

baierd commented Oct 31, 2025

I haven't used it, but I'd be cautious about using it. The libraries I built use the com.microsoft.z3legacy package, as to not mistakenly use a mismatched java/native library.

Good to know! So we need to compile and release it again. Thanks for the clarification!

@leventeBajczi
Copy link
Contributor Author

Well, I'd suggest just using the ones I linked to, but sure, I can also provide a patch on top of the 4.5.0 Z3 so that you can rebuild it if you'd prefer.

Copy link
Contributor

@baierd baierd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find more issues than some small suggestions and quantifier visitation being outdated. Good job and thank you for all your work!

I suggest to import this into a branch in JavaSMT first, then add the binaries to Ivy, run a more complex test-setup in CPAchecker before merging.

* an API wrapper for a collection of SMT solvers:
* https://github.com/sosy-lab/java-smt
*
* SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2025 😉

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, fixed!

MATHSAT5,
SMTINTERPOL,
Z3,
Z3LEGACY,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kfriedberger @PhilippWendler @leventeBajczi i kinda feel like Z3 legacy is a little unspecific. Since the version is fixed, should we use the actual version? I.e. Z3-3.5?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solver is able to provide its version string anyway. As it is a version of Z3 with interpolation support, we might name it Z3_INTERPOLATION or simply Z3_3_5 . Special chars like dots or hyphens are not allowed in Java enums.

The JavaSMT enum it independent of the native library, so the library can be called z3Legacy or similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like encoding the version (Z3_INTERPOLATION could I think be confused with iZ3), so I changed it to Z3_4_5_0.

storedConstraints = new ArrayDeque<>();
storedConstraints.push(PathCopyingPersistentTreeMap.of());
} else {
storedConstraints = null; // we use NULL as flag for "no unsat-core"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Optional would reduce the chance of accidental null access.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could go through the whole code once and update to latest coding conventions, and include latest bugfixes from Z3.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... i mean, including latest bugfixes for JavaSMT only, no bugfixes for an outdated Z3. 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. This should include Z3 as well, since this for example is still present in our Z3. But this should be done independently of Levis work and help, as he/we want this for SVCOMP this year actually ;D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed it in this file; but this came directly from the Z3 implementation, and I did not touch that now. I agree this should probably be fixed globally in the project.

Native.getAppDecl(environment, f)));
case Z3_VAR_AST:
int deBruijnIdx = Native.getIndexValue(environment, f);
return visitor.visitBoundVariable(formula, deBruijnIdx);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that visitBoundVariable() has recently been deprecated.
visitQuantifier() now returns the free variable equivalents for all bound variables and the body with all the bound variables re-substituted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should probably be fixed together with the up-to-date z3 formula creator, and I'd prefer to leave this part as close in the two implementations as possible. LMK if you don't agree!

@baierd
Copy link
Contributor

baierd commented Nov 1, 2025

Well, I'd suggest just using the ones I linked to, but sure, I can also provide a patch on top of the 4.5.0 Z3 so that you can rebuild it if you'd prefer.

We want to use a uniform build-process and build-system, as the dependencies used when building may depend on the system used. Also, the scripts do everything more or less automatically anyway, including the upload. @kfriedberger knows more about the publishing, but it might be more work to re-use your binaries compared to executing a command.

You have to remember that even for a fixed Z3 version, the libraries behind it might be updated from time to time!

@leventeBajczi
Copy link
Contributor Author

leventeBajczi commented Nov 1, 2025

Thanks for the reviews and the answers! I'll get to fixing the code soon, but in the meantime, I prepared a patch:
z3legacy.patch
This can be applied to the 4.5.0 tag and then built with

mkdir release
python2.7 scripts/mk_make.py --prefix=$PWD/release --java
cd build/ && make -j $(nproc) && make install

(i.e., the usual build command back in 4.5.0 times 😅 )

Besides the package rename, this also fixes some weird issue in the hwf.cpp file. I just took a later version's equivalent code, and for us, this has been working for the past ~1 year, so I think it's safe to say it didn't break something trivial, and fixed that weird behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants