Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Strings and Rationals to the Princess backend #391

Open
wants to merge 107 commits into
base: master
Choose a base branch
from

Conversation

daniel-raffler
Copy link
Contributor

@daniel-raffler daniel-raffler commented Sep 13, 2024

Hello everyone,
the goal of this pull request is to add two more theories for strings and rational numbers to the Princess backend. It is a continuation of the work that went into #257. Some of the issues that blocked us from merging it back then have since been resolved, and at least the rational formula manager is actually starting to look pretty good now. Here is a comparison between Princess and some other solvers when running BMC on the ReachSafety-Floats task with option cpa.predicate.encodeFloatAs=RATIONAL set to test the rational formula manager:

Screenshot from 2024-10-17 14-14-36

It's a bit harder to evaluate how well the String manager is working now. The Ostrich team has been very helpful and they quickly fixed a couple of bugs that we've reported. However, since CPAchecker doesn't use String theory there is no easy way of trying it out.

Linked issues:

Princess (Rationals)

Ostrich (Strings)

I've added (partial) workarounds for the two Princess issues, but some work may still be needed. For Ostrich the biggest limitation is that the solver can only handle constraints where (at least) one of the sides is a singleton (= constant) string. Something like "a str.<= b" where both a and b are variables is already impossible. This is a known issue and they're planning a redesign for the solver that will allow it to handle such constraints. In the mean time we might want to add some additional error messages to make sure that the user knows why their program is failing.

serras and others added 30 commits December 6, 2021 11:34
Please apply 'ant format-diff' before commiting,
or the extended version 'ant format-source'.
Scala is not upwards and not downwards compatible.
The upcoming Ostrich library is only available for Scala 2.12,
so we downgrade Scala for Princess.
This is an initial step and the usage is still unclear. This is not tested.
… theory and arrays.

Princess intenally converts all real-arrays to int-arrays
and thus there is some casting and quantification in SMT.
Princess needs non-rational UF arguments to be explicitly casted to rational.
@daniel-raffler daniel-raffler self-assigned this Sep 13, 2024
… rationals (f.ex "1/3 <= y"). This extends the workaround we already use for terms to equations as Princess seems to have a bug when it comes to evaluating rational terms"

This reverts commit 3b7229a
…ese were temporarily disabled due to a bug that has now been fixed. See uuverifiers/princess#11
…. The problem here is that Princess introduces quantifiers when rationals are used, not that arrays can't be combined with rational numbers.
…upport division by zero, but it currently seems to be broken for rationals (at least with the way we're using them)
…incess to crash when non-linear terms are used"

This reverts commit 3bc04a8.
Copy link
Collaborator

@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.

Looks like this was not easy. Good job!
I have some small remarks that we should take into account before merging.

Also, is it possible to use Ostrich without Princess in theory?

<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/java/runtime-princess/ostrich_2.13.jar!/" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess the org.sat4j.core.jar and the ostrich-ecma2020-parser_2.13.jar are only called from these 2 new Jars?

Copy link
Contributor Author

@daniel-raffler daniel-raffler Oct 16, 2024

Choose a reason for hiding this comment

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

Yes, those are both dependencies of ostrich_2.13.jar and we never call them directly. Here is the section from the Ostrich ivy.xml:

<dependencies>
	<dependency org="org.scala-lang" name="scala-library" rev="2.13.8" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
	<dependency org="io.github.uuverifiers" name="ostrich-ecma2020-parser_2.13" rev="1.3" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
	<dependency org="io.github.uuverifiers" name="princess_2.13" rev="2023-06-19" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
	<dependency org="org.sat4j" name="org.sat4j.core" rev="2.3.1" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
	<dependency org="org.scalacheck" name="scalacheck_2.13" rev="1.14.0" force="true" conf="test->runtime(*),master(*)"/>
	<dependency org="dk.brics.automaton" name="automaton" rev="1.11-8" force="true" conf="compile->compile(*),master(*);runtime->runtime(*)"/>
</dependencies>

In fact we may want to remove automaton.jar as well as it is just another dependency?

.withMessage("Solver %s does not support floor operation", solverToUse())
.that(solverToUse())
.isNotEqualTo(Solvers.OPENSMT);
requireRationalFloor();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess checking once here is enough ;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.

Yes, it should be fixed now :)

requireArrays();
requireIntegers();

IntegerFormula _i = imgr.makeVariable("i");
Copy link
Collaborator

Choose a reason for hiding this comment

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

_i is not a valid variable name according to our style guide.

Copy link
Contributor Author

@daniel-raffler daniel-raffler Oct 16, 2024

Choose a reason for hiding this comment

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

These variable names seem to be used for the entire class, though. Should I just rename all the variables, or would it be better to handle this somewhere else?


@Override
protected IExpression floor(IExpression number) {
throw new AssertionError("floor is not supported in Princess");
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks like a UnsupportedOperationException.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed!


IExpression result = PrincessEnvironment.rationalTheory.mul((ITerm) number1, (ITerm) number2);

if (result instanceof IIntLit && ((IIntLit) result).value().equals(IdealInt.apply(0))) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

A comment for explaining this line would be nice.

} else if (pTerm instanceof IFormula) {
return creator.getBoolType();
} else {
// TODO: Do we need more cases?
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be good to look into this before merging.

IExpression evaluation = evaluate(formula);
if (evaluation == null) {
// fallback: try to simplify the query and evaluate again.
evaluation = evaluate(creator.getEnv().simplify(formula));
Copy link
Collaborator

Choose a reason for hiding this comment

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

What happens when simplify() is called for rationals?

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've given it a try now, and unfortunately simplify() doesn't seem to solve the issue. The entire code here is meant to work around uuverifiers/princess#7 and uuverifiers/princess#8 in Princess and we might be able to simplify it again once these bugs have been closed.

@@ -508,32 +540,69 @@ private static String getName(IExpression var) {
}

static FormulaType<?> getFormulaType(IExpression pFormula) {
// TODO: We could use Sort.sortof() here, but it sometimes returns `integer` even though the
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should extract this into an issue so that we don't forget.

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've opened a new Princess issue for this: uuverifiers/princess#16

static Seq<ITerm> toITermSeq(IExpression... exprs) {
return toITermSeq(Arrays.asList(exprs));
}

IExpression simplify(IExpression f) {
// TODO this method is not tested, check it!
Copy link
Collaborator

Choose a reason for hiding this comment

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

Native solver tests seem appropriate considering there is some assumptions that we put on the behavior of the solver.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean simplify here?

new OstrichStringTheory(
toSeq(new ArrayList<>()),
new OFlags(
OFlags.$lessinit$greater$default$1(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

A comment explaining these would be nice.

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've added the arguments and their default values by copying the description from Ostrich.

@daniel-raffler
Copy link
Contributor Author

Looks like this was not easy. Good job!

Thanks!

Also, is it possible to use Ostrich without Princess in theory?

No, unforunately not. Ostrich does include a script to run it directly from the command line, however, internally this will still just call Princess.

From our perspective it's probably best to see Ostrich as the String Theory module of Princess.

…FormulaManager, rather than an AssertionError
…sing bracket in PrincessStringFormulaManager
…String when trying to parse a \u{...} character with 5 digits. Such escape sequences are valid in SMTLIB, but can't be supported by us for Princess as we are restricted to the BMP in UTF16. We also added a test for this special case.
We're now evaluating formulas directly on the stack as there are several issues in Princess that block us from using the partial model with rational numbers. Once those issues have been resolved we can revert this change and move back to using the partial model.
… would unregister themselves from the prover while being closed by it.
@daniel-raffler daniel-raffler marked this pull request as ready for review October 29, 2024 14:57
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.

Princess: No StringFormulaManager
4 participants