Skip to content

Conversation

@daniel-raffler
Copy link
Contributor

@daniel-raffler daniel-raffler commented Oct 28, 2025

This MR adds Bitwuzla multi-dimensional array model evaluation.
(Similar to #539 for CVC5)

Also, more tests for this not based on SMTLIb2 parsing are added.

@daniel-raffler daniel-raffler added this to the Release 6.0.0 milestone Oct 28, 2025
@daniel-raffler daniel-raffler self-assigned this Oct 28, 2025
@baierd baierd self-requested a review October 28, 2025 19:38
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.

LGTM. But i would like to test this with at least the 2 tests from the related CVC5 branch, if possible more.

@baierd
Copy link
Contributor

baierd commented Oct 28, 2025

@daniel-raffler could you maybe add a test that (for Integer and BV if possible) that uses multi-dimensional arrays, but with at least 1 store instruction?

Bonus points if the store itself stores a multi-dimensional array.

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.

Thanks for adding the tests! I think many can be combined to test the behavior in 2 tests (per theory). Something like:

  1. Nested arrays with UFs (you can combine store and select)
  2. Nested arrays with UFs and non UFs (store and select combined)

(The CVC5 branch already has tests for only nested arrays w select, so no need for that)

}

/** Evaluate the UF or array constraint and check that the model contains the expected values. */
private <T> void checkModelContains(
Copy link
Contributor

Choose a reason for hiding this comment

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

Methods like this already exist AFAIK. Could you check and reuse the existing ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I can rewrite the tests to use testModelGetters just as on the CVC5 branch


checkModelContains(
bmgr.and(
bvmgr.equal(amgr.select(array, idxA), valA),
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this not covered by existing tests?
(It might be that there are only Integer based tests for this)

}

@Test
public void testArray1BvBV() {
Copy link
Contributor

Choose a reason for hiding this comment

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

A description, e.g. SMTLIB2, of whats tested should be added to all new tests.

@daniel-raffler
Copy link
Contributor Author

@daniel-raffler could you maybe add a test that (for Integer and BV if possible) that uses multi-dimensional arrays, but with at least 1 store instruction?

Bonus points if the store itself stores a multi-dimensional array.

I've added 68cb59c from the modelArrayGeneration branch and two more tests for 3d arrays that use stores. Is that what you had in mind?

LGTM. But i would like to test this with at least the 2 tests from the related CVC5 branch, if possible more.

The tests from the CVC5 branch also seem to be working

These will be added later. The quickfix is just about array values in the model
@daniel-raffler
Copy link
Contributor Author

daniel-raffler commented Oct 30, 2025

Thanks for adding the tests! I think many can be combined to test the behavior in 2 tests (per theory). Something like:

1. Nested arrays with UFs (you can combine store and select)

2. Nested arrays with UFs and non UFs (store and select combined)

(The CVC5 branch already has tests for only nested arrays w select, so no need for that)

I've removed the UF tests again as they were meant to test assignments for uninterpreted functions and aren't needed here. Other than that there is some overlap with the tests from the CVC5 branch and I'm not if we can't just remove all of the tests here.

What do you think still needs testing that isn't already covered by the CVC5 branch?

I'm getting different results for testArray1BvBV and testArray2BvBV on Z3 and Yices (EDIT: See here for the JUnit results). In the first test we get an incomplete model while the second test crashes, so maybe these two should be kept? Since testArray1BvBV is essentially the same as testGetArrays3BitvectorNoParsing from the CVC5 branch we would then only need to add testArray2BvBV (and maybe testArray2IntInt for completeness sake)

// Should be unreachable
// We assume that array values are made up of "const" and "store" nodes with non-array
// constants as leaves
throw new AssertionError();
Copy link
Contributor

Choose a reason for hiding this comment

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

A more expressive exception and message could be added here.

}

/** Returns the arguments of an UF or array definition from the model. */
private Iterable<Formula> getFunctionArgs(Formula pValue) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually why don't we have a visitor method for retrieving all UFs, including all applications? @kfriedberger do you know? Seems like this might be helpful in general.

new DefaultFormulaVisitor<>() {
@Override
protected Iterable<Formula> visitDefault(Formula f) {
throw new IllegalArgumentException();
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you sure this is correct?
Since you don't override all methods of the super-class, this can be called!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's fine. The argument to this function is a "key" formula from the model. So it's either (f 1 2 3) for a UF mapping f(1,2,3) or (Select (Select (Select 1 arr) 2) 3) for an array mapping arr(1,2,3). We then get the arguments 1, 2 and 3 by simply returning them for the UF mapping: this is the else branch in visitFunction. Or descending the term recursively if we have an array: that's the if part of visitFunction and visitFreeVariable for the base case

The whole function could be removed if we rewrite the tests to use testModelGetters

return FluentIterable.concat(
getFunctionArgs(args.get(0)), ImmutableList.of(args.get(1)));
} else {
// Assume its an UF value
Copy link
Contributor

Choose a reason for hiding this comment

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

visitFunction() is defined to be called on any function, including UFs. I would recommend explicitly checking for UFs. You could take a look at the VariableAndUFExtractor for inspiration.

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

Labels

Development

Successfully merging this pull request may close these issues.

2 participants