14 KiB
TLA+ symbols and identifiers
Note that PlusCal allows user-defined operators, so any operator shown as non-native may be introduced by a module if it is part of the user-definable symbols, as defined by Table 4 in the P-syntax manual.
Arrows
Oriented
Single ->
->- In
[S -> D]: the set of functions from domain S to destination set (codomain) D
- In
<-:- used in TLA+ only as part of
INSTANCEstatements withWITHclauses- Example:
INSTANCE Foo WITH x <- e
- Example:
- used in TLC Toolbox CFG files to assign values to constants (but doesn't work in TLC CLI)
- used in lectures to represent substitution in expressions, like
f WITH v <- e, which substitutes expressionefor the symbolvin expressionf.
- used in TLA+ only as part of
|->, used only as[x |-> y],- a function mapping a single element
xto valuey, - if
xis a string, that function is called a record or struct - if
xis a natural, that function is called a sequence or tuple if the domain is finite.
- a function mapping a single element
>-and-<: not native TLA+ symbols
Double =>
=>: impliesA => B = B \/ ~A
<=>: logical equivalence, same as=but only applicable to booleansA <=> B = (A => B) /\ (B => A)A <=> B = (A /\ B) \/ (~A /\ ~B)
>=: greater than or equal operator<=: less than or equal operator=<: less than or equal operator>=<: not part of TLA+
Tilde ~>
~>: leads to- TODO
<~: not a native TLA+ symbol
Symmetric
<->: logical equivalence- Unlike
=, only applies to booleans
- Unlike
No other symmetric arrow is a native TLA+ symbol.
Brackets etc
[]: always or functions
- Empty: always temporal operator box
[]PmeansPis true in every state of the system, i.e. it is an invariant~[]P: in EVERY behaviour, there exists at least one state where P is false[foo]_bar- is shorthand for
foo \/ UNCHANGED bar, assumingbaris a sequence, e.g.<<x, y>> - which means for
foo \/ (x' = x /\ y= y)`
- is shorthand for
- The combination
[]<>always eventually can be called repeatedly[]<>Pmeans thatPwill keep becoming true infinitely often.- It's like saying "no matter when you look,
Pwill eventually be true again." - Meaning at some point in the future,
Pwill become true and remain true forever after. - It's like saying "eventually,
Pwill always hold."
- Non-empty: functions
- In
[S -> D], a set of functions. See Arrows/--> - In
[x |-> y]a specific function. See Arrows/|-> - TODO check: "For any function
f = [x ∈ DOMAIN f: x ↦ f[x]]"
- In
{}: sets
{}: empty set{ x1, ... xN }: enumerated set{ x: y }: a set comprehension. Two kinds have names:{ expr: x \in S }: a set map, read as "values of expr where x is in S"( x \in S: expr }: a set filter, read as "keys of S where expr holds true"
<>: eventually, tuples
<>: eventually temporal operator diamond- Meaning at some point in the future,
Pwill become true and remain true forever after. It's like saying "eventually,Pwill always hold."
- Meaning at some point in the future,
<>[]: eventually always- At some point in the future,
Pwill become true and remain true forever after. - It's like saying "eventually,
Pwill always hold."
- At some point in the future,
<<A>>_vmeansAis true ANDvchanges- Compare to
[A]_vmeaningAis true ORvdoesn't change
- Compare to
<<a, b, c>>defines a tuple/sequence. Some texts (incorrectly ?) use(a, b, c).
()
(a, b, c): tuple construction is referenced somewhere, but should be<<a, b, c>>f(x, y, z): non-niladic function application- niladic function
fapplication is writtenf - that is because a niladic function and its application are actually the same
- niladic function
- Expressions grouping for arithmetic
- Logical and temporal precedence grouping
Predefined functions and operators, by module
All are pure functions, no mutators.
At least some direct engine support
Naturals
+,-,*,/,^,%: arithmetic<,<=,>,>=and less-used=<for<=Nat: the set of natural integers- Cannot be enumerated by TLC (in a quantifier or CHOOSE)
- Can be used for membership checking
..to define "range" sets like1..3 = {1, 2, 3}\div: integer floor division:10 \div 3 = 3
Integers
- All of
Naturals, plus... Int: the set of all integers- unary
-: negative numbers, like-2
Sequences
Append(S, e): appends elementeat the end of sequence S and returns the resultHead(S): first element of S (cf. Lisp CAR)Len(S): length of sequence\o: concatenation of two sequences (vs seq + element forAppend)SelectSeq(seq, Op(_)): filter a sequence usingOpIsEven(x) == x % 2 = 0(%has precedence over=)SelectSeq(<<1, 2, 3>>, IsEven) = <<2>>
Seq(set): the set of all sequences ofsetelements (so countable infinite, aleph-null)- Is actually efficient in TLC, counter-intuitively
- Cannot be enumerated by TLC (in a quantifier or CHOOSE)
- Can be used for membership checking
SubSeq(S, m, n): subsequence of s from m to n, both includedTail(S): sequence S without first element (cf. Lisp CDR)
Required for PlusCal procedures.
TLC
-
:>shorthand notation for functions with a singleton domaina :> b = [x \in {a} |-> b]
-
@@: dyadic function merge- if both operands share the same key use the LEFT one (cf. LearnTLA+ (other sources say the right one)
-
SortSeq(seq, Op(_, _)) Sorts the sequence with comparator Op.
-
Any- Used as
x \in Anyto get any valuexof any type - Do not use in a spec
- May be useful for modeling properties
- Used as
-
Assert(e, t): checks thateis true and returns, or printstifeif false -
JavaTime: The current epoch time. -
Permutations(set): all functions acting as permutations of the setPermutations(S) == {f \in [S -> S] : \A w \in S : \E v \in S : f[v]=w}
-
Print(t, e):- From one source: prints the value of
ewith tagt - From the Standard modules page on LearnTLA:
Print(val, out): PrintsToString(val), and evaluates tooutas an expression. - From experience: requires
e = TRUEand printstto output
- From one source: prints the value of
-
PrintT(val): Equivalent toPrint(val, TRUE). -
RandomElement(set): Randomly pulls an element from set. The value can be different on different runs! -
SortSetq(seq): Sorts a sequence -
TLCEval(v): Evaluatesvand caches the result. Can be used to speed up recursive definitions. -
TLCGet(val): val can be either an integer or a string.- If an integer, retrieves the value from the corresponding
TLCSet. - If a string, retrieves statistics from the current model run. The following strings are valid:
- “queue”
- “generated”
- “distinct”
- "duration”: number of seconds elapsed since the beginning of model checking
- “level”: the length of the current behavior
- can be used to bound an unbound model.
- “diameter”: the length of the longest global behavior
- “stats”: all of the global stats (everything excluding “level”), as a struct.
- If an integer, retrieves the value from the corresponding
-
TLCSet(i, val): Sets the value forTLCGet(i).imust be a positive integer.TLCSetcan be called multiple times in the same step.
-
ToString(val): String conversion.
Each TLC worker thread carries a distinct “cache” for the values of TLCGet(i). As such, it’s generally inadvisable to use TLCSet to profile information that lasts beyond a single step.TLCSet statements evaluated during the initial state, however, will be propagated to all workers.
TLCExt
AssertEq(a, b): Equivalent to a = b, except that if a # b, it also prints the values of a and b.- This does not terminate model checking!
AssertError(str, exp): True if exp doesn’t throw an error, or if exp throws an error that exactly matches str.- False otherwise
- This does not terminate model checking!
Trace: Returns the “history” of the current behavior, as a sequence of structs.TLCModelValue(str): Creates a new model value with name str.- Can only be used in constant definitions, as part of an ordinary assignment.
CONSTANT Threads <- {
TLCModelValue(ToString(i)): i \in 1..3
}
- assigns the constant
Threadsa set of model values corresponding to the strings"1","2", and"3". - This is useful for scenarios where you want to represent distinct entities (like threads) in a model without tying them to specific numeric values.
100% TLA+ user space modules
Bags
Bags defines a special kind of functions, from items to natural values, meant to represent their "count".
IsABag(f)IsABag([a |-> 3, b |-> 7]) = TRUEbecause both 3 and 7 are naturalsIsABag([a |-> 3, b |-> "B"]) = FALSEbecause "B" is not a naturalIsABag([a |-> 3, b |-> -2]) = FALSEbecause -2 is not a natural- Any function over the empty set passes
IsABagbecause no elements fail to be naturals
BagToSet(bag): returns the domain of bag- equivalent to
DOMAIN bag
- equivalent to
SetToBag(set)creates a bag with set elements as keys and counts all equal to 1- equivalent to
[x \in set |-> 1]
- equivalent to
BagIn(e, bag):e \in DOMAIN bagEmptyBag: `<<>>- Subtlety: any function over the empty set is the
EmptyBag
- Subtlety: any function over the empty set is the
(+): dyadic bag addition merges two bags, adding counts on merged keys(-): dyadic bag subtraction, subtracting counts on all keys present in the right argument, and dropping all keys with resulting negative or zero countsBagUnion(set): bag addition of all members of the set\sqsubseteq: dyadic operator: true IFF all elements in the right operand have at least as high a count as those in the left operandSubBag(bag): the set of all subbags ofbagas defined by\sqsubseteqSubBag(EmptyBag) = {<<>>}SubBag([a |-> 2]) = {<<>>, [a -> 1], [a -> 2]}
BagOfAll(Op(_), bag): mapping ofOpover the bag KEYS (not values)BagOfAll(LAMBDA x: x^2, <<1, 3, 5>>) = (1 :> 1 @@ 4 :> 3 @@ 9 :> 5)
BagCardinality(bag): the sum of all counts in the bagCopiesIn(e, bag): the count for keyein the bag, 0 if it is absent
FiniteSets
Cardinality(S): number of elements in SIsFiniteSet(S): is S finite ?
Json
ToJson(val): convert to a JSON string- sets and sequences -> JSON arrays
- functions: objects with string keys; converting any non-string source elements to their string representation
JsonSerialize(absoluteFilename, value): convert value to a JSON fileJsonDeserialize(absolutefilename): imports a JSON object from a file
Randomization
Provides pseudo-random subsets, which will prevent TLC from checking all possible states.
This is useful for optimization, but may introduce oversights.
RandomSubset(k, S): random size-k subset of S.RandomSetOfSubsets(k, n, S): k random subsets of S, where each random subset has on average n elements- May generate duplicates, so return fewer than
kelements, - May return the empty set
- May generate duplicates, so return fewer than
TestRandomSetOfSubsets(k, n, S)- Calls
RandomSetOfSubsets(k, n, S)five times (hardcoded) and returns the number of unique sets each time, as a sequence
- Calls
Reals
Nothing usable in TLC
Realtime
Nothing usable in TLC
PlusCal
Structure
- Defined within a TLA+ spec, by a block comment starting by:
(*--algorithm <name>or(*--fair algorithm <name>where<name>is irrelevant, and finished byend algorithm; *)- Although the opening and closing comments do not have to be adjacent to
algorithmandend algorithmsome plugins may fail in that case, like the VSCode plugin as of 2025-02
- Although the opening and closing comments do not have to be adjacent to
- Order of sections
- Opening:
(*--[fair] algorithm foo - Declarations, semicolon-terminated, e.g.:
variable seq \in S \x S;- only onevariableclauseindex = 1;seen = {};- notice: no
:=, no==
- Operator definitions: TLA+ code, wrapped in
define/end define - Macros (see 02-writing-specs)
- Procedures (see 07-concurrency)
- Code, either indented off a
beginfor the algorithm body, or[fair] process <name>for a process
- labels, as the unit of atomicity
- always containing statements
- adding a + to the label name makes it a "fair" label
- adding a - to the label name makes it an "unfair" label
- statements, semicolon-terminated
- assignments use
:=and are limited to one par variable per label
- Closing:
end algorithm; *)
- Opening:
Predefined
- Variables:
pcfor Program Counter: the label of the NEXT statement to be executedself: from the P-syntax spec:- "Within the body of a process set, self equals the current process’s identifier"
stackif the algorithm contains one or more procedures
- Labels
Donelabel: from the P-syntax spec: "There is an implicit label Done at the end of every process, and at the end of a uniprocess algorithm""Errorlabel: from the P-syntax spec: "There is an implicit label Error immediately after the body. If control ever reaches that point, then execution of either the process (multiprocess algorithm) or the complete algorithm (uniprocess algorithm) halts"
Tips and ideas
- Represent a directed graph:
- create a function
graphon pairs of points, TRUE iff there is a directed edge between them, GraphType = [Node \X Node -> BOOLEAN]This impliesgraph \in GraphType= TRUE.
- create a function
- When using
tlc -dump dot <out> <spec.tla>, the<out>_liveness.dotfile represents the inner representation of TLC, and is generally considered useless except to debug TLC itself. Do not waste time on it.