Replies: 5 comments 23 replies
-
@bugarela, @shonfeder, @Kukovec, @thpani, this is a long text. I would like to hear your opinion. This issue is kind of blocking me on the simulator. It looks like I have found a solution, but maybe it is not the optimal one. |
Beta Was this translation helpful? Give feedback.
-
As I said in the Quint meeting, I think we should try to abstract this complexity and give the user a clearer interface. And we don't have to define specs the same way TLA+ does in the surface syntax. We could instead have some syntax to define specs in the form:
and probably have some nice symbols/operator to this normal form. I can't think of a good syntax right now but will try later, so here's a bad example:
|
Beta Was this translation helpful? Give feedback.
-
I'd just like to note my, POV as a non-expert at specifying: In this formula initializer TypeInit = {
& setOfMaps(Node, Bool).guess { a => active <- a }
& setOfMaps(Node, Color).guess { c => color <- c }
& Node.guess { n => tpos <- n }
& Color.guess { c => tcolor <- c }
} I find the fact that the reader has to descend into the innermost expression in each conjunct to figure out the state assignment really bad for readability. What we'd like, imo, is a way to always put the state variables being updated front and center. So if it were at all possible, I think this would be much nicer for users to read and write if it were something like: initializer TypeInit = {
& active <- setOfMaps(Node, Bool).guess()
& color <- setOfMaps(Node, Color).guess()
& tpos <- Node.guess()
& tcolor <- Color.guess()
} |
Beta Was this translation helpful? Give feedback.
-
As previously discussed, I have tried to introduce a new qualifier
After doing that, I have decided that we should not introduce the new keyword, for the following reasons:
My conclusion is that we simply should use actions for initialization and use the effects checker to make sure that the initializing action only writes to but does not read state variables. Just to double check, would the effects checker able to this, @bugarela? |
Beta Was this translation helpful? Give feedback.
-
This was a nice discussion. It looks like we have solved the issue with the initialisers. Closing the discussion. We can always come back to other ideas mentioned here. |
Beta Was this translation helpful? Give feedback.
-
1. Context
We have introduced action-definitions to isolate side effects that are written as: delayed assignments
x <- e
, non-deterministic disjunctions{ A | B }
, and guessesS.guess { x => e }
. These features work nicely:https://github.com/informalsystems/tnt/blob/7e7e1853afadf2d19211dfafc3a0d188a8988184/examples/ewd840/ewd840.tnt#L85-L92
https://github.com/informalsystems/tnt/blob/7e7e1853afadf2d19211dfafc3a0d188a8988184/examples/ewd840/ewd840.tnt#L105-L106
2. Problem
We kept spec initialization as in TLA. That is the system is initialized with a predicate. Here is how it was written in ewd840:
https://github.com/informalsystems/tnt/blob/7e7e1853afadf2d19211dfafc3a0d188a8988184/examples/ewd840/ewd840.tnt#L34-L39
Technically, this should pose no problem, if we translate Quint to TLA+ and later use TLC or Apalache. They both treat some equalities as assignments.
There are two issues however:
Init
should be used as assignments and which are not.3. Solution
Similar to how we have introduced actions, I propose to introduce initializers. They will be like actions that are not allowed to read state variables (as there are no state variables before initialization). So our example of
Init
(see above) would look like follows:We can use the effects checker to make sure that the definitions tagged with
initializer
do not read state variables, and they do write to state variables.4. Complications
If we introduce the special initializers, we have to understand how to deal with the following issues.
4.1. Restricting the initial states
Quite often we want to further restrict the initial states with a predicate. For instance, if we wanted to state that all active tokens have the "black" color in the above example, it would be very easy to do in TLA+:
Since we are not allowed to refer to the next-state variables in Quint, we have refer to the guessed values. So the equivalent Quint code would look much more complex:
This modification is probably bearable. But it becomes even more complex, if we want to use the common TLA+ idiom of restricting the initial states with
TypeOK /\ Inv
. Let's have a look atTypeOK
andInv
, as defined in Quint:https://github.com/informalsystems/tnt/blob/7e7e1853afadf2d19211dfafc3a0d188a8988184/examples/ewd840/ewd840.tnt#L23-L28
https://github.com/informalsystems/tnt/blob/7e7e1853afadf2d19211dfafc3a0d188a8988184/examples/ewd840/ewd840.tnt#L172-L176
We do not want to embed
Inv
intoTypeOK
, as it would be too much work, this would prevent us from reusingInv
, and this process is in general error-prone.In principle, we would like to use
TypeOK
as an initializer andInv
as an additional predicate:We want to write something like
{ TypeInit & Inv }
. However, this should not be allowed, asInv
refers to previous-state variables, andTypeInit
writes to next-state variables.What we actually mean here is something like sequential composition:
TypeInit; Inv
. That is,TypeInit
writes to the state variables, the operator;
rolls turns next-state variables in the previous-state variables, and the predicateInv
evaluates previous-state variables.If we introduce the operator for sequential composition
;
(which actually exists in TLA+ and is called\cdot
), we can turn initializers into predicates like follows:Having defined
TypeInit
andTypedInv
, we can check inductive invariants with initializers and we reuse the same definitions ofTypeInit
andInv
, without the need for creative code duplication.So if we introduce
;
, then we probably should expect the user to give us the system initializer in the formInit; InitPred
, whereInit
is an initializer, andInitPred
is an additional predicate, which can be justtrue
.4.2. Using initializers in temporal formulas
This issue is similar to that in Section 4.1.
A TLA+ spec is usually summarized in the canonical form:
We can easily express
[][Next]_vars
in Quint asalways(stutter(Next, vars))
, but what about the initializer?We have two options:
init(Init)
.;
discussed in Section 4.1.If we go with
;
, then the spec in the canonical form would look like:If this looks too ugly, we can always introduce an additional predicate:
and use it in the temporal formula:
Beta Was this translation helpful? Give feedback.
All reactions