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 sets to the arrays encoding #1093

Merged
merged 54 commits into from
Nov 18, 2021

Conversation

rodrigo7491
Copy link
Collaborator

@rodrigo7491 rodrigo7491 commented Nov 12, 2021

  • Tests added for any new code
  • Ran make fmt-fix (or had formatting run automatically on all files edited)
  • Documentation added for any new functionality
  • Entry added to UNRELEASED.md for any new functionality

This PR contains the initial version of the arrays encoding. It adds support for basic types, which are unchanged from the original encoding, as well as sets. A number of encoding rules was changed, either explicitly, through new RewritingRule classes, or implicitly, through changes to Z3SolverContext that make the SMT constraints produced be different from those of the original rules. A number of existing unit and integration tests are now running with the arrays encoding. Below is an overview of the changes. Closes #1092.

  • SolverConfig. A new field was added to the solver configuration, to record the encoding being used. This field is set based on the check command options.
  • SolverContext. The core of the changes is in Z3SolverContext, as this is where the SMT constraints are made. See the updated ADR for details.
  • SymbStateRewriter. Three new explicit rules were added to ruleLookupTable in SymbStateRewriterImplWithArrays: EqRuleWithArrays, SetInRuleWithArrays, and SetInclusionRuleWithArrays.
  • Unit tests. The unit tests were refactored to account for the two possible encodings in the solver configuration. The most relevant refactoring change was in RewriterBase. To see which unit tests were enabled to run with the arrays encoding, check TestArenaWithArrays, TestRewriterWithArrays, and TestRecordingSolverContextWithArrays.
  • Integration tests. Some tests were enabled to run with the arrays encoding, by tagging them with array-encoding in cli-integration-tests. The CI setup to run the tagged tests is not part of this PR.
  • Documentation. ADR11 was updated to reflect the implementation changes made. Its high level description was not changed.

…into ro/tla-sets-as-smt-arrays

� Conflicts:
�	tla-bmcmt/src/main/scala/at/forsyte/apalache/tla/bmcmt/passes/BoundedCheckerPassImpl.scala
… and wrong ssa treatment during incremental solving
Copy link
Collaborator

@konnov konnov left a comment

Choose a reason for hiding this comment

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

The first batch of comments. I will continue today.

docs/src/adr/011adr-smt-arrays.md Outdated Show resolved Hide resolved
val rightDomain = state.arena.getDom(powsetCell)
val rightDomainElems = state.arena.getHas(rightDomain)
// EqConstraints need to be generated, since missing in-relations, e.g. in sets of tuples, will lead to errors.
// TODO: Inlining this method is pointless. We should consider handling tuples and other structures natively in SMT.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Good point. We should figure out how to deal with records that can be used as discriminated unions. Perhaps, ADTs should help us.

Copy link
Collaborator

@konnov konnov left a comment

Choose a reason for hiding this comment

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

More comments. More yet to come :)

rodrigo7491 and others added 2 commits November 17, 2021 15:27
…verConfig.scala

Co-authored-by: Igor Konnov <igor@informal.systems>
Copy link
Collaborator

@Kukovec Kukovec left a comment

Choose a reason for hiding this comment

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

Most comments are minor, but I think the lookup table one is pretty important.

Comment on lines +23 to +35
case (FinSetT(_), FinSetT(_)) =>
subset(rightState, leftCell, rightCell, false)

case (FinSetT(FinSetT(t1)), PowSetT(FinSetT(t2))) =>
if (t1 != t2) {
throw new RewriterException(
"Unexpected set types: %s and %s in %s"
.format(t1, t2, state.ex), state.ex)
} else {
subset(rightState, leftCell, rightCell, true)
}

case _ =>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Technically, the case PowSetT(FinSetT(t1)), FinSetT(FinSetT(t1) should be possible too, no? Suboptimal, but not illegal.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is equal to the original SetInclusionRule rule. I didn't think much about it since an exception is already thrown there. If we make a change it should be in both encodings I think. Maybe in a separate PR?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@konnov thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

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

There is case _ => that throws an exception below. So it will be reported as an error. Perhaps, we should throw a better exception there that indicates that this case is not supported.

Copy link
Collaborator

@Kukovec Kukovec Nov 17, 2021

Choose a reason for hiding this comment

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

Yeah, but shouldn't

A == {1,2}
B == SUBSET A \subseteq { x \in SUBSET A: \A y \in x: y < 5 } \* <=> SUBSET A \subseteq SUBSET A <=> TRUE

translate into exactly the case where the LHS is a PowSetT and the RHS is a standard FinSetT because of the filter?
You can't throw on this example.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not sure. You can try this example and see what happens. Maybe the left-hand side will get expanded. If it does not, we should fix ExpansionMarker to do that.

Copy link
Collaborator

Choose a reason for hiding this comment

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

See #1103

Copy link
Collaborator

@konnov konnov left a comment

Choose a reason for hiding this comment

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

This looks very good. See the other comments. As far as I understand, this PR contains the rules for set equality, set membership, and subseteq. Are other set operators planned for a separate PR?

Comment on lines +192 to +196
// The updated set is cached here, it needs to be added to a predicate later, via "getInPred".
// The inStored map is used to ensure that the first call to "getInPred" related to the declared inPred will
// return a "store", and the subsequent calls will return a "select".
inCache += ((set.id, elem.id) -> (updatedSet, level))
inStored += ((set.id, elem.id) -> List((false, level)))
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 an error-prone approach. What happens if a rewriting rule does not use inPred at all and then store is used in a random place somewhere? An alternative would be to explicitly introduce two operators in ApalacheOper: store and select. These would be auxiliary operators that only appear in the internals of Apalache.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The point about using the cache wrongly could be made about any of the caches in the solver context. inStored is currently used only in declareInPredIfNeeded and getInPred.

I like the idea of adding store and select, I haven't though of adding new ApalacheOper before.

Comment on lines +225 to +227
// inPred can either represent an array update, i.e. a "store", or an array access, i.e. a "select", as the
// the current implementation is adhering to the interface made for the original encoding.
// TODO: Should we split this method and abandon the concept of an in-relation?
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, I would prefer having store and select as operators in the Apalache IR, as it seems you need them.

@rodrigo7491
Copy link
Collaborator Author

This looks very good. See the other comments. As far as I understand, this PR contains the rules for set equality, set membership, and subseteq. Are other set operators planned for a separate PR?

The PR contains rules for all set operators in the map, excluding the ones flagged at the bottom. Most rules, like set ctr, set union, etc., were added implicitly by changing the constraints they generated, as mentioned in the top comment.

@konnov
Copy link
Collaborator

konnov commented Nov 17, 2021

This looks very good. See the other comments. As far as I understand, this PR contains the rules for set equality, set membership, and subseteq. Are other set operators planned for a separate PR?

The PR contains rules for all set operators in the map, excluding the ones flagged at the bottom. Most rules, like set ctr, set union, etc., were added implicitly by changing the constraints they generated, as mentioned in the top comment.

So it means they did not require any change?

@rodrigo7491
Copy link
Collaborator Author

So it means they did not require any change?

The RewritingRule classes themselves no, but the "conceptual" rules did change, since they now generate different smt constraints and thus lead to a different 4-tuple state, as described in the paper.

@konnov
Copy link
Collaborator

konnov commented Nov 18, 2021

So it means they did not require any change?

The RewritingRule classes themselves no, but the "conceptual" rules did change, since they now generate different smt constraints and thus lead to a different 4-tuple state, as described in the paper.

That's interesting. If we introduce store and select, you would have to rewrite those rules too, right?

@rodrigo7491
Copy link
Collaborator Author

That's interesting. If we introduce store and select, you would have to rewrite those rules too, right?

Probably. It depends on how store and select end up being implemented. Since this is quite a fundamental change, should I do this here or in a follow up PR?

@konnov
Copy link
Collaborator

konnov commented Nov 18, 2021

That's interesting. If we introduce store and select, you would have to rewrite those rules too, right?

Probably. It depends on how store and select end up being implemented. Since this is quite a fundamental change, should I do this here or in a follow up PR?

Yes, I think we can postpone it for another PR. This one is not going to break anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEATURE] Add support for sets to the SMT encoding with arrays
3 participants