Apalache operators
In addition to the standard TLA+ operators described in the previous section,
Apalache defines a number of operators, which do not belong to the core language of TLA+,
but which Apalache uses to provide clarity, efficiency, or special functionality.
These operators belong to the module Apalache
,
and can be used in any specification by declaring EXTENDS Apalache
.
Assignment
Notation: v' := e
LaTeX notation:
Arguments: Two arguments. The first is a primed variable name, the second is arbitrary.
Apalache type: (a, a) => Bool
, for some type a
Effect: The expression v' := e
evaluates to v' = e
.
At the level of Apalache static analysis, such expressions indicate parts of an action,
where the value of a state-variable in a successor state is determined.
See here for more details about assignments in Apalache.
Determinism: Deterministic.
Errors: If the first argument is not a primed variable name, or if the assignment operator is used where assignments are prohibited, Apalache statically reports an error.
Example in TLA+:
x' := 1 \* x' = 1
x' := (y = z) \* x' = (y = z)
x' := (y' := z) \* x' = (y' = z) in TLC, assignment error in Apalache
x' := 1 \/ x' := 2 \* x' = 1 \/ x' = 2
x' := 1 /\ x' := 2 \* FALSE in TLC, assignment error in Apalache
x' := 1 \/ x' := "a" \* Type error in Apalache
(x' + 1) := 1 \* (x' + 1) = 1 in TLC, assignment error in Apalache
IF x' := 1 THEN 1 ELSE 0 \* Assignment error in Apalache
Example in Python:
>> a = 1 # a' := 1
>> a == 1 # a' = 1
True
>> a = b = "c" # b' := "c" /\ a' := b'
>> a = (b == "c") # a' := (b = "c")
Non-deterministically guess a value
Notation: Guess(S)
LaTeX notation: Guess(S)
Arguments: One argument: a finite set S
, possibly empty.
Apalache type: Set(a) => a
, for some type a
.
Effect: Non-deterministically pick a value out of the set S
, if S
is
non-empty. If S
is empty, return some value of the proper type.
Determinism: Non-deterministic if S
is non-empty, that is, two subsequent
calls to Guess(S)
may return x, y \in S
that can differ (x /= y
) or may
be equal (x = y
). Moreover, Apalache considers all possible combinations of
elements of S
in the model checking mode. If S
is empty, Guess(S)
produces the same value of a proper type.
Errors:
If S
is not a set, Apalache reports an error.
Example in TLA+:
/\ 1 = Guess({ 1, 2, 3 }) \* TRUE or FALSE
/\ 2 = Guess({ 1, 2, 3 }) \* TRUE or FALSE
/\ 3 = Guess({ 1, 2, 3 }) \* TRUE or FALSE
/\ 4 /= Guess({ 1, 2, 3 }) \* TRUE
/\ Guess({ 1, 2, 3 }) \in Int \* TRUE
Value generators
Notation: Gen(bound)
LaTeX notation: Gen(bound)
Arguments: One argument: an integer literal or a constant expression (of the integer type).
Apalache type: Int => a
, for some type a
.
Effect: A generator of a data structure. Given a positive integer bound
,
and assuming that the type of the operator application is known, we recursively
generate a TLA+ data structure as a tree, whose width is bound by the number
bound
.
Determinism: The generated data structure is unrestricted. It is effectively implementing data non-determinism.
Errors:
If the type of Gen
cannot be inferred from its application context,
or if bound
is not an integer, Apalache reports an error.
Example in TLA+:
\* produce an unrestricted integer
LET \* @type: Int;
oneInt == Gen(1)
IN
\* produce a set of integers up to 10 elements
LET \* @type: Set(Int);
setOfInts == Gen(10)
IN
\* produce a sequence of up to 10 elements
\* that are integers up to 10 elements each
LET \* @type: Seq(Set(Int));
sequenceOfInts == Gen(10)
IN
...
Folding
The operators ApaFoldSet
and ApaFoldSeqLeft
are explained in more detail in a dedicated section here.
Operator iteration
Notation: Repeat(Op, N, x)
LaTeX notation: Repeat(Op, N, x)
Arguments: Three arguments: An operator Op
, an iteration counter N
(a nonnegative constant integer expression), and an
initial value x
.
Apalache type: ((a, Int), Int, a) => a
, for some type a
.
Effect: For a given constant bound N
, computes the value
F(F(F(F(x,1), 2), ...), N)
. If N=0
it evaluates to x
.
Repeat(Op, N, x) ==
ApaFoldSeqLeft(Op, x, MkSeq(N, LAMBDA i:i))
Apalache implements a more efficient encoding of this operator than the default one.
Determinism: Deterministic.
Errors:
If any argument is ill-typed, or N
is not a nonnegative constant integer expression, Apalache reports an error.
Example in TLA+:
Op(a) == a + 1
LET OpModified(a,i) == Op(i)
IN Repeat(OpModified, 0, 5) = 5 \* TRUE
Op2(a,i) == a + i
Repeat(Op2, 0, 5) = 15 \* TRUE
Convert a set of pairs to a function
Notation: SetAsFun(S)
LaTeX notation: SetAsFun(S)
Arguments: One argument: A set of pairs S
, which may be empty.
Apalache type: Set(<<a, b>>) => (a -> b)
, for some types a
and b
.
Effect: Convert a set of pairs S
to a function F
, with the property that F(x) = y => <<x,y>> \in S
.
Note that if S
contains at least two pairs <<x, y>>
and <<x, z>>
, such that y /= z
, then F
is not uniquely defined.
We use CHOOSE
to resolve this ambiguity. The operator SetAsFun
can be defined as follows:
SetAsFun(S) ==
LET Dom == { x: <<x, y>> \in S }
Rng == { y: <<x, y>> \in S }
IN
[ x \in Dom |-> CHOOSE y \in Rng: <<x, y>> \in S ]
Apalache implements a more efficient encoding of this operator than the default one.
Determinism: Deterministic.
Errors:
If S
is ill-typed, Apalache reports an error.
Example in TLA+:
SetAsFun({ <<1, 2>>, <<3, 4>> }) = [x \in { 1, 3 } |-> x + 1] \* TRUE
SetAsFun({}) = [x \in {} |-> x] \* TRUE
LET F == SetAsFun({ <<1, 2>>, <<1, 3>>, <<1, 4>> }) IN
\* this is all we can guarantee, when the relation is non-deterministic
\/ F = [x \in { 1 } |-> 2]
\/ F = [x \in { 1 } |-> 3]
\/ F = [x \in { 1 } |-> 4]
Construct a sequence
Notation: MkSeq(n, F)
LaTeX notation: MkSeq(n, F)
Arguments: Two arguments: sequence length n
(a constant integer
expression), and element constructor F(i)
.
Apalache type: (Int, (Int => a)) => Seq(a)
, for some type a
.
Effect: Produce the sequence of n
elements <<F(1), .., F(n)>>
.
Determinism: Deterministic.
Errors:
If n
is not a constant, or is negative, Apalache reports an error.
Example in TLA+:
LET Double(i) == 2 * i IN
MkSeq(3, Double) = <<2, 4, 6>> \* TRUE
Interpret a function as a sequence
Notation: FunAsSeq(fn, len, maxLen)
LaTeX notation: FunAsSeq(fn, len, maxLen)
Arguments: Three arguments:
- A function
fn
that should be interpreted as a sequence. - An integer
len
, denoting the length of the sequence, with the property1..len \subseteq DOMAIN fn
. Apalache does not check this requirement. It is up to the user to ensure that it holds. This expression is not necessarily constant. - An integer constant
maxLen
, which is an upper bound onlen
, that is,len <= maxLen
.
Apalache type: (Int -> a, Int, Int) => Seq(a)
, for some type a
Effect: The expression FunAsSeq(fn, len, maxLen)
evaluates to the
sequence << fn[1], ..., fn[Min(len, maxLen)] >>
.
Determinism: Deterministic.
Errors: If the types of fn
, len
or maxLen
do not match the expected types,
Apalache statically reports a type error.
Additionally, if it is not the case that 1..len \subseteq DOMAIN fn
, the result is undefined.
Example in TLA+:
Head([ x \in 1..5 |-> x * x ]) \* 1 in TLC, type error in Apalache
FunAsSeq([ x \in 1..5 |-> x * x ], 3, 3) \* <<1,4,9>>
Head(FunAsSeq([ x \in 1..5 |-> x * x ], 3, 3)) \* 1
FunAsSeq(<<1,2,3>>, 3, 3) \* <<1,2,3>> in TLC, type error in Apalache
FunAsSeq([ x \in {0,42} |-> x * x ], 3, 3) \* UNDEFINED
Example in Python:
# define a TLA+-like dictionary via a python function
def boundedFn(f, dom):
return { x: f(x) for x in dom }
# this is how we could define funAsSeq in python
def funAsSeq(f, length, maxLen):
return [ f.get(i) for i in range(1, min(length, maxLen) + 1) ]
# TLA+: [ x \in 1..5 |-> x * x ]
f = boundedFn(lambda x: x * x, range(1,6))
# TLA+: [ x \in {0, 42} |-> x * x ]
g = boundedFn(lambda x: x * x, {0, 42})
>>> f[1]
1
>>> funAsSeq(f, 3, 3)
[1, 4, 9]
>>> funAsSeq(f, 3, 3)[1]
1
>>> funAsSeq(g, 3, 3)
[None, None, None]
Skolemization Hint
Notation: Skolem(e)
LaTeX notation: Skolem(e)
Arguments: One argument. Must be an expression of the form \E x \in S: P
.
Apalache type: (Bool) => Bool
Effect: The expression Skolem(\E x \in S: P)
provides a hint to Apalache,
that the existential quantification may be skolemized.
It evaluates to the same value as \E x \in S: P
.
Determinism: Deterministic.
Errors:
If e
is not a Boolean expression, throws a type error.
If it is Boolean, but not an existentially quantified expression, throws a StaticAnalysisException
.
Note:
This is an operator produced internally by Apalache.
You may see instances of this operator, when reading the .tla
side-outputs of various passes.
Manual use of this operator is discouraged and, in many cases, not supported.
Example in TLA+:
Skolem( \E x \in {1,2}: x = 1 ) \* TRUE
Skolem( 1 ) \* 1 in TLC, type error in Apalache
Skolem( TRUE ) \* TRUE in TLC, error in Apalache
Set expansion
Notation: Expand(S)
LaTeX notation: Expand(S)
Arguments: One argument. Must be either SUBSET SS
or [T1 -> T2]
.
Apalache type: (Set(a)) => Set(a)
, for some a
.
Effect: The expression Expand(S)
provides instructions to Apalache,
that the large set S
(powerset or set of functions) should be explicitly constructed as a finite set,
overriding Apalache's optimizations for dealing with such collections.
It evaluates to the same value as S
.
Determinism: Deterministic.
Errors:
If e
is not a set, throws a type error. If the expression is a set,
but is not of the form SUBSET SS
or [T1 -> T2]
, throws a StaticAnalysisException
.
Note:
This is an operator produced internally by Apalache.
You may see instances of this operator, when reading the .tla
side-outputs of various passes.
Manual use of this operator is discouraged and, in many cases, not supported.
Example in TLA+:
Expand( SUBSET {1,2} ) \* {{},{1},{2},{1,2}}
Expand( {1,2} ) \* {1,2} in TLC, error in Apalache
Expand( 1 ) \* 1 in TLC, type error in Apalache
Cardinality Hint
Notation: ConstCardinality(e)
LaTeX notation: ConstCardinality(e)
Arguments: One argument. Must be an expression of the form Cardinality(S) >= k
.
Apalache type: (Bool) => Bool
Effect: The expression ConstCardinality(Cardinality(S) >= k)
provides a hint to Apalache,
that Cardinality(S)
is a constant, allowing Apalache to encode the constraint e
without attempting to dynamically encode Cardinality(S)
.
It evaluates to the same value as e
.
Determinism: Deterministic.
Errors:
If S
is not a Boolean expression, throws a type error.
If it is Boolean, but not an existentially quantified expression, throws a StaticAnalysisException
.
Note:
This is an operator produced internally by Apalache.
You may see instances of this operator, when reading the .tla
side-outputs of various passes.
Manual use of this operator is discouraged and, in many cases, not supported.
Example in TLA+:
Skolem( \E x \in {1,2}: x = 1 ) \* TRUE
Skolem( 1 ) \* 1 in TLC, type error in Apalache
Skolem( TRUE ) \* TRUE in TLC, error in Apalache