Skip to content

Commit 15d356c

Browse files
lemmyclaude
andcommitted
ewd998: move RECURSIVE SimpleCycle from Utils.tla to EWD998_anim.tla
TLAPS does not currently support RECURSIVE *operators*, so any module that EXTENDS Utils.tla (EWD998Chan, EWD998ChanID, EWD998PCal) fails to load. Inline the operator into its sole caller EWD998_anim.tla so Utils.tla loads under TLAPS again. Existing EWD998 / ATD proofs unchanged. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: Markus Alexander Kuppe <github.com@lemmster.de>
1 parent b864582 commit 15d356c

4 files changed

Lines changed: 18 additions & 15 deletions

File tree

specifications/ewd998/EWD998Chan.tla

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
(* Shmuel Safra's version of termination detection. *)
66
(* Contrary to EWD998, this variant models message channels as sequences. *)
77
(***************************************************************************)
8-
EXTENDS Integers, Sequences, FiniteSets, Utils
8+
EXTENDS Integers, Sequences, SequencesExt, FiniteSets, Utils
99

1010
CONSTANT N
1111
ASSUME NAssumption == N \in Nat \ {0} \* At least one node.

specifications/ewd998/EWD998_anim.tla

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@
3737
***************************************************************************)
3838
EXTENDS EWD998ChanID, SVG, TLC
3939

40+
(***************************************************************************)
41+
(* SimpleCycle is a recursive variant of the predicate IsSimpleCycle from *)
42+
(* Utils.tla. It does not work with PlusPy or TLAPS but is orders of *)
43+
(* magnitude faster when evaluated by TLC, which is why it lives here *)
44+
(* inline in the animation module rather than in Utils.tla. *)
45+
(***************************************************************************)
46+
SimpleCycle(S) ==
47+
LET sts == LET SE == INSTANCE SequencesExt IN SE!SetToSeq(S)
48+
RECURSIVE SimpleCycleRec(_,_,_)
49+
SimpleCycleRec(seq, prefix, i) ==
50+
IF i = Len(seq)
51+
THEN prefix @@ (seq[i] :> seq[1])
52+
ELSE SimpleCycleRec(seq, prefix @@ (seq[i] :> seq[i+1]), i+1)
53+
IN SimpleCycleRec(sts, sts[1] :> sts[2], 2)
54+
4055
\* Deterministic node ordering: ensures nodes appear in consistent positions
4156
\* across all animation frames (Best Practice from Animation Guide)
4257
SomeRingOfNodes == SimpleCycle(Node)

specifications/ewd998/Utils.tla

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
------------------------------- MODULE Utils -------------------------------
2-
EXTENDS Integers, Sequences, FiniteSets, TLC, Functions, SequencesExt
2+
EXTENDS Integers, Sequences, FiniteSets, Functions
33

44
\* No support for RECURSIVE in PlusPy.
55
IsSimpleCycle(S, r) ==
@@ -13,16 +13,4 @@ IsSimpleCycle(S, r) ==
1313
IN << r[head] >> \o F[i-1]
1414
IN Range(F[Cardinality(S)]) = S
1515

16-
\* SimpleCycle is a recursive variant of the predicate IsSimpleCycle above. It
17-
\* does not work with PlusPy, but is orders of magnitude faster when evaluated
18-
\* by TLC.
19-
SimpleCycle(S) ==
20-
LET sts == LET SE == INSTANCE SequencesExt IN SE!SetToSeq(S)
21-
RECURSIVE SimpleCycle(_,_,_)
22-
SimpleCycle(seq, prefix, i) ==
23-
IF i = Len(seq)
24-
THEN prefix @@ (seq[i] :> seq[1])
25-
ELSE SimpleCycle(seq, prefix @@ (seq[i] :> seq[i+1]), i+1)
26-
IN SimpleCycle(sts, sts[1] :> sts[2], 2)
27-
2816
=============================================================================

specifications/ewd998/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,4 @@
201201
"models": []
202202
}
203203
]
204-
}
204+
}

0 commit comments

Comments
 (0)