|
2 | 2 | (**************************************************************************)
|
3 | 3 | (* Background reading: Conjoining Specifications by Abadi and Lamport *)
|
4 | 4 | (* https://lamport.azurewebsites.net/pubs/abadi-conjoining.pdf *)
|
5 |
| -(* *) |
6 |
| -(* Spec A and B are two components that together are composed into a *) |
7 |
| -(* larger system. It's toy example in the sense that minimize *) |
8 |
| -(* interaction of A and B to behaviors where first A takes its steps *) |
9 |
| -(* followed by B. Variable y in A and B represents the control wire *) |
10 |
| -(* that A and B use to synchronize. *) |
11 |
| -(* Variable z has been added to make the example more interesting--it *) |
12 |
| -(* only appears in spec A but *not* B. *) |
13 |
| -(* *) |
14 | 5 | (**************************************************************************)
|
15 |
| -EXTENDS Naturals, Sequences |
16 |
| - |
17 |
| -(* COMPONENT Spec A *) |
18 |
| ------------- MODULE A ------------ |
19 |
| -VARIABLES x, \* Abstract/very high-level representation of the overall computation. |
20 |
| - \* Think of it as some computation going on. At a certain state |
21 |
| - \* of the computation, the composed system transitions into the |
22 |
| - \* next phase. |
23 |
| - z \* z is the variable that is only going to be present in spec A. |
24 |
| -varsA == <<x, z>> |
25 |
| - |
26 |
| -InitA == |
| 6 | +EXTENDS Integers, Sequences |
| 7 | + |
| 8 | +Nodes == 1..3 \* Fixed to 1..3 here but should be a constant. |
| 9 | + |
| 10 | +(* COMPONENT Spec A (Computation) *) |
| 11 | +------ MODULE A -------- |
| 12 | +VARIABLES x, \* Private to this component. |
| 13 | + active \* Shared with component spec B. |
| 14 | +vars == <<x,active>> |
| 15 | + |
| 16 | +Type == |
| 17 | + /\ x \in 0..10 |
| 18 | + /\ active \in [ Nodes -> BOOLEAN ] |
| 19 | + |
| 20 | +Init == |
27 | 21 | /\ x = 0
|
28 |
| - /\ z = TRUE |
29 |
| - |
30 |
| -NextA == |
31 |
| - /\ x < 6 |
32 |
| - /\ x' = x + 1 |
33 |
| - /\ z' = ~ z |
| 22 | + /\ active \in [ Nodes -> BOOLEAN ] |
| 23 | + |
| 24 | +Next == |
| 25 | + \* Not all nodes are inactive. |
| 26 | + /\ \E i \in DOMAIN active : active[i] = TRUE |
| 27 | + \* Mimic some computation. |
| 28 | + /\ x' \in 1..10 |
| 29 | + \* Computation changed the activation of 0 to N nodes. |
| 30 | + /\ active' \in [ Nodes -> BOOLEAN ] |
34 | 31 |
|
35 | 32 | ==================================
|
36 | 33 |
|
37 |
| -(* COMPONENT Spec B *) |
38 |
| -VARIABLES x |
39 |
| -varsB == <<x>> |
| 34 | +(* COMPONENT Spec B (Safra's termination detection) *) |
| 35 | +------------ MODULE B ------------ |
| 36 | +VARIABLES active, \* Shared with component A. |
| 37 | + inactive \* Shared with component C. |
| 38 | +vars == <<inactive, active>> |
40 | 39 |
|
41 |
| -\* ++Observation: This is most likely not the original Init predicate of a |
42 |
| -\* standalone B component, unless perhaps we consider spec A |
43 |
| -\* the environment of spec B. In this particular example, |
44 |
| -\* InitB is superfluouos anyway. However, if one would want |
45 |
| -\* to prove something about spec B, we probably need an init |
46 |
| -\* predicate (=> Conjoining Specifications). |
47 |
| -InitB == |
48 |
| - /\ x \in Nat \* Spec B may starts with x being any natural number, |
49 |
| - \* which is where A left off. |
| 40 | +Type == |
| 41 | + /\ inactive \subseteq Nodes |
| 42 | + /\ active \in [ Nodes -> BOOLEAN ] |
50 | 43 |
|
51 |
| -NextB == |
52 |
| - /\ x < 10 |
53 |
| - /\ x' = x + 1 |
| 44 | +Init == |
| 45 | + /\ inactive = {} |
| 46 | + /\ active \in [ Nodes -> BOOLEAN ] |
| 47 | + |
| 48 | +Next == |
| 49 | + \* Since this high-level composition abstracts away communication, |
| 50 | + \* we could abstract termination detection into a single step: |
| 51 | + \* /\ \A i \in DOMAIN active : active[i] = FALSE |
| 52 | + \* /\ inactive' = Nodes |
| 53 | + \* However, we want to model the possible interleavings of the |
| 54 | + \* A and B spec. |
| 55 | + /\ \E i \in DOMAIN active: |
| 56 | + active[i] = FALSE /\ i \notin inactive |
| 57 | + /\ inactive' = inactive \cup { |
| 58 | + CHOOSE i \in DOMAIN active: |
| 59 | + active[i] = FALSE /\ i \notin inactive |
| 60 | + } |
| 61 | + /\ UNCHANGED active |
| 62 | + |
| 63 | +================================== |
54 | 64 |
|
55 |
| ------------------------------------------------------------------------------ |
| 65 | +(* COMPONENT Spec C (orderly/graceful shutdown) *) |
| 66 | +------------ MODULE C ------------ |
| 67 | +VARIABLES inactive \* Shared with component spec B. |
| 68 | +vars == <<inactive>> |
56 | 69 |
|
57 |
| -(* This *extends* component spec B to defines what happens to the variables |
58 |
| - in spec A, which are not defined in B, when B takes a step. *) |
59 |
| -VARIABLES restOfTheUniverse |
| 70 | +Type == |
| 71 | + /\ inactive \subseteq Nodes |
60 | 72 |
|
61 |
| -\* Note that TLC doesn't complain about restOfTheUniverse |
62 |
| -\* not appearing in InitB. |
63 |
| -OpenNextB == |
64 |
| - /\ NextB |
65 |
| - /\ UNCHANGED <<restOfTheUniverse>> |
| 73 | +Init == |
| 74 | + /\ inactive \subseteq Nodes |
66 | 75 |
|
| 76 | +IOExit == TRUE \* Shutdown via sys.exit |
| 77 | + |
| 78 | +Next == |
| 79 | + /\ inactive = Nodes |
| 80 | + /\ UNCHANGED inactive |
| 81 | + /\ IOExit |
| 82 | +================================== |
| 83 | + |
| 84 | +----------------------------------------------------------------------------- |
| 85 | + |
| 86 | +(* Component specification. *) |
| 87 | +VARIABLES x, active, inactive |
67 | 88 | vars ==
|
68 |
| - <<x,restOfTheUniverse>> |
| 89 | + <<inactive, x, active>> |
| 90 | + |
| 91 | +A == INSTANCE A |
| 92 | +B == INSTANCE B |
| 93 | +C == INSTANCE C |
| 94 | + |
| 95 | +TypeOK == |
| 96 | + /\ A!Type |
| 97 | + /\ B!Type |
| 98 | + /\ C!Type |
| 99 | + |
| 100 | +Init == |
| 101 | + /\ A!Init |
| 102 | + /\ B!Init |
| 103 | + /\ C!Init |
| 104 | + |
| 105 | +\* PlusPy will most certainly not be able to evaluate this |
| 106 | +\* Next formula. Might have to introduce an auxiliary variable |
| 107 | +\* that represents the phase/stage of composed system. |
| 108 | +Next == |
| 109 | + \/ /\ ENABLED A!Next |
| 110 | + /\ [A!Next]_vars |
| 111 | + /\ UNCHANGED <<inactive>> |
| 112 | + \/ /\ ENABLED B!Next |
| 113 | + /\ [B!Next]_vars |
| 114 | + /\ UNCHANGED <<x>> |
| 115 | + \/ /\ [C!Next]_vars |
| 116 | + /\ UNCHANGED <<x, active>> |
| 117 | + |
| 118 | +Spec == Init /\ [][Next]_vars /\ WF_vars(Next) |
69 | 119 |
|
70 |
| -(* Composition of A and B (A /\ B) *) |
71 |
| -(* Down here we know about the internals *) |
72 |
| -(* of spec A and B (whitebox component). *) |
| 120 | +THEOREM Spec => []TypeOK |
73 | 121 |
|
74 |
| -INSTANCE A WITH z <- restOfTheUniverse |
| 122 | +(* The system eventually converges to shutdown. This, however, does |
| 123 | + *not* hold because component spec A could keep computing forever. *) |
| 124 | +AlwaysShutdown == |
| 125 | + <>[][C!Next]_vars |
75 | 126 |
|
76 |
| -Spec == InitA /\ InitB /\ [][ IF ENABLED NextA THEN [NextA]_vars |
77 |
| - ELSE [OpenNextB]_vars |
78 |
| - ]_vars |
| 127 | +(* Unless all nodes are inactive at startup, some computation will occur. *) |
| 128 | +ComputationIfSomeActive == |
| 129 | + [n \in Nodes |-> FALSE] # active => <>[](x \in 1..10) |
| 130 | +THEOREM Spec => ComputationIfSomeActive |
79 | 131 |
|
80 |
| -Inv == x \in 0..10 |
81 |
| -THEOREM Spec => Inv |
| 132 | +(* Iff - from some point onward - all nodes will become |
| 133 | + inactive, the composed system will eventually shutdown. *) |
| 134 | +ShutdownIfNoComputation == |
| 135 | + <>[][~ A!Next]_vars => <>[][C!Next]_vars |
| 136 | +THEOREM Spec => ShutdownIfNoComputation |
82 | 137 |
|
83 |
| -\* Not a theorem due to no fairness constraint. |
84 |
| -Live == |
85 |
| - <>[](x = 10) |
86 | 138 | =============================================================================
|
87 | 139 | \* Modification History
|
88 |
| -\* Last modified Fri Jun 12 17:34:09 PDT 2020 by markus |
| 140 | +\* Last modified Mon Jun 15 17:37:21 PDT 2020 by markus |
89 | 141 | \* Last modified Fri Jun 12 16:30:19 PDT 2020 by Markus Kuppe
|
90 | 142 | \* Created Fri Jun 12 10:30:09 PDT 2020 by Leslie Lamport
|
0 commit comments