Specifying liveness so a cycle doesn't happen in TLA+ - tla+

I'm writing a specification of a simple client-server interaction to learn TLA+:
-------------------------------- MODULE Bar --------------------------------
VARIABLES
sessionOK, \* if session is OK or expired
msg \* message currently on the wire
vars == <<msg, sessionOK>>
TypeOK ==
/\ sessionOK \in {TRUE, FALSE}
/\ msg \in {
"Query",
"OK",
"Unauthorized",
"null"
}
Init ==
/\ msg = "null"
/\ sessionOK = FALSE
Query ==
/\ msg \in {"null", "OK"}
/\ msg' = "Query"
/\ UNCHANGED <<sessionOK>>
OK ==
/\ msg = "Query"
/\ sessionOK = TRUE
/\ msg' = "OK"
/\ UNCHANGED <<sessionOK>>
Unauthorized ==
/\ msg = "Query"
/\ sessionOK = FALSE
/\ msg' = "Unauthorized"
/\ UNCHANGED <<sessionOK>>
Authorize ==
/\ msg = "Unauthorized"
/\ msg' = "null"
/\ sessionOK' = TRUE
Expire ==
/\ sessionOK = TRUE
/\ sessionOK' = FALSE
/\ UNCHANGED <<msg>>
Next ==
\/ Query
\/ Unauthorized
\/ OK
\/ Authorize
\/ Expire
Spec == Init /\ [][Next]_vars /\ WF_vars(Next)
=============================================================================
As you can hopefully see the client can run some query against a server, and if the session is OK, it will get a result, otherwise it gets a message that it needs to authorize and then retry. The session can expire at any time.
I want to ensure that the client eventually will get a result, so I added this line to properties:
(msg = "Query") ~> (msg = "OK")
Upon model checking, I'm confronted with a counter-example going like this:
Init -> (Query -> Unauthorized -> Authorize -> Expire),
with the part in parentheses repeating indefinitely. My first thought was to make a strong fairness requirement on OK step. However the problem is in this scenario OK step is never enabled.
I could add things like []<><<OK>>_vars (which reads "it's always the case that eventually OK occurs"), but this feels like cheating, and from what I gather specifying liveness using arbitrary temporal formulas -- and not weak or strong fairness -- is frowned upon.
How can I use weak or strong fairness to guarantee that a query will eventually get a response? Or maybe my model is bad? I'm out of ideas...

I'm answering my own question. If anyone thinks they have a better answer, please share.
I found this aptly-named thread How to test a process eventually succeeds after indefinite number of retries?, where Leslie Lamport himself points out we can just assert fairness on a conjuction of an action and some other formula. In our scenario Spec then looks like this:
Spec ==
/\ Init
/\ [][Next]_vars
/\ WF_vars(Next)
/\ SF_vars(OK)
/\ SF_vars(Query /\ (sessionOK = TRUE))
Now, what do each of these formulas in conjuction mean? The first three are quite obvious and were included in my attempt at defining Spec.
Init is true on the first state of the behaviour.
Next is true for every step of the behaviour (with stuttering allowed).
Next will continue to occur if it continues to be enabled indefinitely, so a system doesn't come to a stop in the middle of message exchange.
Fourth one was my intuition: it fixes the situation where the query is made, and then the session expires.
If OK is repeatedly enabled (possible to happen) then it will eventually happen.
And fifth is what was missing: it fixes the situation where OK was never enabled in the first place, because the session expired before the Query could happen.
If it is repeatedly the case that Query can happen and the session is valid at the same time, it will eventually happen.

Related

What is the interpretation of <>P -> (!P U R)

What is the interpretation of <>P -> (!P U R)? This seems to be contradiction since in future P is expected and checking the absence of P until R.
Model checking tool passes this via BDD as well as BMC techniques.
I don't see any contradiction.
The property is made true by any Buchi automaton s.t.
P is always false [because the premise of the implication is false], or
At some point in the future P becomes true, yet for some time P may be false until R becomes true.
i.e.
In natural language, one would express that property as follows: "If, by any chance, sooner or later P becomes true, then it must be the case that the 'event' R fired first".
For instance, you can imagine P be "sending answer message" and R be "received input message" and the whole property be "no unsolicited answer message is ever sent".

\in works, while \subseteq gives a "identifier undefined" error

I have the following spec:
------------------------------ MODULE Group ------------------------------
CONSTANTS People
VARIABLES members
Init == members \subseteq People
Next == members' = members
Group == Init /\ [][Next]_members
=============================================================================
(I simplified this spec to the point where it's not doing anything useful.)
When I try to run it through TLC, I get the following error:
In evaluation, the identifier members is either undefined or not an operator.
The error points to the Init line.
When I change the Init line to:
Init == members \in People
it validates fine.
I want the former functionality because I mean for members to be a collection of People, not a single person.
According to section 16.1.6 of Leslie Lamport's Specifying Systems, "TLA+ provides the following operators on sets:" and lists both \in and \subseteq.
Why is TLA+ not letting me use \subseteq?
While that is a valid TLA+ expression, TLC can only assign next-state values to a variable x by the statements x' = e or x' \in S. See section 14.2.6 for details. This holds for the initial assignment, too. In your case, you probably want members \in SUBSET People.

How do I model-check a module that depends on an unbound variable?

I'm going through Specifying Systems right now and I'm a little puzzled about how I'd model-check the following module:
---------------------------- MODULE BoundedFIFO ----------------------------
EXTENDS Naturals, Sequences
VARIABLES in, out
CONSTANT Message, N
ASSUME (N \in Nat) /\ (N > 0)
Inner(q) == INSTANCE InnerFIFO
BNext(q) == /\ Inner(q)!Next
/\ Inner(q)!BufRcv => (Len(q) < N)
Spec == \EE q : Inner(q)!Init /\ [][BNext(q)]_<<in, out, q>>
=============================================================================
I see that both the Init and BNext formulas are operators, parameterized by q. How would I supply this to the model checker?
You can't: \E x : P(x) is an unbounded expression, which TLC cannot handle. Many of the specs in Specifying Systems can't be modeled. More recent guides, such as the TLA+ Hyperbook or Learn TLA+, are more careful to keep all of their specs modelable.

How to assert a given state leads to a another state with variables in TLA+?

Sorry the title is a bit cryptic. I have a TLA+ spec that defines two sets:
variables Requests = {}, Outcomes = {};
I have one set of workers adding requests, and another set or workers fulfilling them and writing to Outcomes. Each request has a unique Id, which the matching Outcome entry will then also contain.
I want to guarantee that any request added to the Requests set is eventually matched by a structure with the same Id in the Outcomes set. I've been trying to do this using the "leads to", ~>, operator, but can't figure out how to resolve the Id matching portion.
I've naively tried something like:
RequestsAreFulfilled == \E req \in Requests: TRUE
~> \E outcome \in Outcomes : outcome.id = req.id
But this obviously breaks since req is not defined in the second expression. I've considered something along the lines of the second express being "Then there is a state where all Request items are matched by Outcome items", but that doesn't work since the system never terminates - there may very well always be more requests in the Requests set, since Outcomes is always playing catch-up.
What is a way for me to assert that a request is eventually matched with an outcome with the same id?
TLC has some trouble proving liveness properties with nonconstant sets. Let's start with the fixed case, where you have a finite, fixed set of ids. Then we can specify the relation as
\A id \in Ids: (\E r \in req: r.id = id) ~> (\E o \in out: o.id = id)
In this case, though, we're better off using structures, as they're easier to understand and express shared relationships better.
requested = [i \in Ids |-> FALSE];
processed = [i \in Ids |-> FALSE];
\A id \in Ids: requested[i] ~> processed[i]
or
messages = [i \in Ids |-> [requested |-> FALSE, processed |-> FALSE]]
\A id \in Ids:
LET m == messages[i]
IN m.requested ~> m.processed
If you want an infinite number of messages, one way to get TLC to handle liveness checks is to use a fixed set of ids then add logic to "recycle" finished messages - set both requested and processed to FALSE. Then we can use the always-eventually operator, []<>, to express this:
\A id \in Ids: []<>(requested[i] => processed[i])

How not to use GOTO function here

I know the global resentment of the goto logic.. but here it goes. Here is the case, say you have a function take in a status and decide which action you are going to take. This is a pseudo-code in python (as a joke.)
def function(status, condition, value):
if(status == A) :
goto actionA
if(status == B) :
goto actionB
if(value > 1 or condition == C):
goto actionA
...more conditions you got the idea.
return;
actionA:
dosthA
return
actionB:
dosthB
return
...more actions
My question is, how would you implement such code?
It needs to be easy to read. If later you decide to add an action or add an status or condition, you can do that with some confidence that it will not break earlier logic.
You are jumping out of the conditional and down to your labels after every condition so only one of these can run.
In order to avoid duplicating the actionA code and avoid goto, you can just move your conditions around. dosthA will execute if status == A or if the status is not B (because then the other block will run) and the third condition matchs. Careful to preserve the behavior I get this:
def function(status, condition, value):
if(status == A or (status != B && (value > 1 or condition == C))) :
dosthA
return
if(status == B) :
dosthB
return
...more conditions you got the idea.
return;
Also this is effectively a bunch of "else if"s or a switch since you're returning. Using "else if" or switch would probably increase clarity but in order to make the fewest changes an illustrate the actual important part of the answer I didn't make this into "else if"s.
By the way I'm a firm believer that the use of goto is a bad idea. It's worth reading Edsger W. Dijkstra's influential Go To Statement Considered Harmful.

Resources