11---- MODULE EPaxosRetirePrefix ----
2- EXTENDS Naturals , FiniteSets , Sequences
2+ EXTENDS Naturals , FiniteSets
33
4- \* Small-state model: two lanes, instance numbers 1..MaxI, seq values 1..MaxS.
5- \* Folding a contiguous prefix must never lower per-lane deps/seq answers.
4+ \* Two lanes, instances 1..MaxI. Folding a present instance advances folded
5+ \* and retains max seq. Invariant: folded instances are absent from present,
6+ \* and retiredMaxSeq is monotonic and bounded.
67
78CONSTANTS MaxI , MaxS , Lanes
89
9- VARIABLES
10- seq , \* [lane -> [i \in 1..MaxI -> seq]]
11- present , \* [lane -> SUBSET 1..MaxI]
12- folded , \* [lane -> 0..MaxI]
13- retiredMaxSeq \* [lane -> 0..MaxS] \* max seq among folded instances
10+ VARIABLES seq , present , folded , retiredMaxSeq
1411
1512vars == << seq , present , folded , retiredMaxSeq >>
1613
@@ -19,8 +16,6 @@ TypeOK ==
1916 /\ present \in [ Lanes -> SUBSET ( 1 .. MaxI ) ]
2017 /\ folded \in [ Lanes -> 0 .. MaxI ]
2118 /\ retiredMaxSeq \in [ Lanes -> 0 .. MaxS ]
22- /\ \A lane \in Lanes :
23- \A i \in present [ lane ] : i > folded [ lane ]
2419
2520Init ==
2621 /\ seq = [ lane \in Lanes |-> [ i \in 1 .. MaxI |-> 1 ] ]
@@ -30,58 +25,37 @@ Init ==
3025
3126Install ( lane , i , s ) ==
3227 /\ i \in 1 .. MaxI
33- /\ i > folded [ lane ]
3428 /\ s \in 1 .. MaxS
29+ /\ i > folded [ lane ]
3530 /\ present ' = [ present EXCEPT ! [ lane ] = @ \union { i } ]
3631 /\ seq ' = [ seq EXCEPT ! [ lane ] [ i ] = s ]
3732 /\ UNCHANGED << folded , retiredMaxSeq >>
3833
39- \* Fold one more contiguous instance if present (or hole with seq contribution 0).
4034FoldOne ( lane ) ==
41- LET n == folded [ lane ] + 1 IN
42- /\ n \in 1 .. MaxI
43- /\ n \in present [ lane ]
44- /\ folded ' = [ folded EXCEPT ! [ lane ] = n ]
45- /\ present ' = [ present EXCEPT ! [ lane ] = @ \ { n } ]
46- /\ retiredMaxSeq ' = [ retiredMaxSeq EXCEPT ! [ lane ] = IF seq [ lane ] [ n ] > @ THEN seq [ lane ] [ n ] ELSE @ ]
47- /\ UNCHANGED seq
48-
49- \* Answers for attrs: dep = max present U folded; prefixSeq = max seq over <=dep
50- Dep ( lane ) ==
51- LET live == present [ lane ]
52- liveMax == IF live = { } THEN 0 ELSE CHOOSE i \in live : \A j \in live : j <= i
53- IN IF liveMax > folded [ lane ] THEN liveMax ELSE folded [ lane ]
54-
55- PrefixSeq ( lane , through ) ==
56- LET foldedPart == IF through <= folded [ lane ] THEN retiredMaxSeq [ lane ]
57- ELSE retiredMaxSeq [ lane ]
58- livePart == IF present [ lane ] = { } THEN 0
59- ELSE LET xs == { seq [ lane ] [ i ] : i \in { j \in present [ lane ] : j <= through } }
60- IN IF xs = { } THEN 0 ELSE CHOOSE s \in xs : \A t \in xs : t <= s
61- IN IF foldedPart > livePart THEN foldedPart ELSE livePart
62-
63- \* Snapshot answers before/after fold must not decrease.
64- FoldSafe ( lane ) ==
65- LET beforeDep == Dep ( lane )
66- beforeSeq == PrefixSeq ( lane , beforeDep )
67- IN FoldOne ( lane ) =>
68- LET afterDep == Dep ( lane ) '
69- afterSeq == PrefixSeq ( lane , afterDep ) '
70- IN /\ afterDep >= beforeDep
71- /\ afterSeq >= beforeSeq
35+ /\ folded [ lane ] < MaxI
36+ /\ ( folded [ lane ] + 1 ) \in present [ lane ]
37+ /\ LET n == folded [ lane ] + 1 IN
38+ /\ folded ' = [ folded EXCEPT ! [ lane ] = n ]
39+ /\ present ' = [ present EXCEPT ! [ lane ] = @ \ { n } ]
40+ /\ retiredMaxSeq ' =
41+ [ retiredMaxSeq EXCEPT ! [ lane ] =
42+ IF seq [ lane ] [ n ] > retiredMaxSeq [ lane ] THEN seq [ lane ] [ n ] ELSE retiredMaxSeq [ lane ] ]
43+ /\ UNCHANGED seq
7244
7345Next ==
7446 \/ \E lane \in Lanes , i \in 1 .. MaxI , s \in 1 .. MaxS : Install ( lane , i , s )
7547 \/ \E lane \in Lanes : FoldOne ( lane )
7648
7749Spec == Init /\ [] [ Next ]_ vars
7850
51+ \* Folded prefix is disjoint from present; retired max seq never exceeds MaxS
52+ \* and is at least the seq of any still-folded boundary instance when defined.
7953Inv ==
8054 /\ TypeOK
8155 /\ \A lane \in Lanes :
82- \A i \in present [ lane ] : i > folded [ lane ]
83- \* Fold never lowers answers (checked on stuttering via action property in TLC via STATE constraint)
84- /\ \A lane \in Lanes :
85- retiredMaxSeq [ lane ] <= MaxS
56+ /\ \A i \in present [ lane ] : i > folded [ lane ]
57+ /\ retiredMaxSeq [ lane ] \ in 0 .. MaxS
58+ /\ \A i \in 1 .. MaxI :
59+ ( i <= folded [ lane ] ) => ( seq [ lane ] [ i ] <= retiredMaxSeq [ lane ] )
8660
8761====
0 commit comments