Skip to main content

Transitions

Transitions define behavior: how the system changes state. A transition body is a sequence of operations.

Transition Kinds

KeywordRole
initInitialization transition; runs once at startup.
tranStep transition; runs on every step.
havocNon-deterministic reset of variables.

The implicit base class Anything provides empty init, tran, and havoc transitions, so any class that does not declare its own inherits these no-ops.

Declaring a Transition

A transition declaration consists of one of the kind keywords, a name, a parameter list, and a body in { }.

tran increment() {
value := value + 1
}

With parameters:

tran setBy(amount: int) {
value := value + amount
}

Parameters are passed by value when the transition is invoked through an inline call.

The Implicit main, init, and havoc

A transition declared without a name has an implicit name based on its kind:

DeclarationImplicit name
tran { ... }main
init { ... }init
havoc { ... }havoc

Hence tran { value := value + 1 } is equivalent to a transition tran main() { value := value + 1 }. The implicit main and init transitions are the special transitions checked and run by the model checker.

class Counter {
var value: int := 0

redefine init {
value := 0
}

redefine tran {
value := value + 1
}
}

Multiple Branches with or

A transition body may contain alternative branches separated by or. This is a shorthand for wrapping the body in a top-level choice.

tran step() {
value := value + 1
} or {
value := value - 1
}

The verifier explores both branches non-deterministically.

Abstract Transitions

An abstract transition has no body. Concrete subclasses must redefine it.

abstract tran fire()

Redefining Transitions

Override an inherited transition of the same name with redefine.

redefine tran increment() {
if (value < maximum()) {
value := value + 1
}
}

The same applies to the implicit transitions inherited from Anything: overriding them requires redefine.

redefine init {
value := 0
}
redefine tran {
inline child.main()
}