Documentation
¶
Overview ¶
Package modelchecker implements the model checker for the FizzBuzz program. It is based on the Starlark interpreter for the python part of the code. For the interpreter to implement the model checker, we need to simulate parallel universe. Every time, there is a non-deterministic choice, we need to fork the universe and continue the execution in both the universes with the different choices. Each universe is represented by a process. Each process has a heap and multiple threads. Each thread has a stack of call frames. Each call frame has a program counter and scope (with nesting). The heap is shared across all the threads in the process. Duplicate detection: Two threads are same if they have the same stack of call frames Two processes are same if they have the same heap and same threads.
Index ¶
- Constants
- func CheckAssertion(process *Process, invariant *ast.Invariant, index int) bool
- func CheckFastLiveness(allNodes []*Node) ([]*Link, *InvariantPosition)
- func CheckInvariant(process *Process, invariant *ast.Invariant) bool
- func CheckInvariants(process *Process) map[int][]int
- func CheckLivenessSccAlwaysEventually(nodes []*Node, invPos InvariantPosition) (bool, error)
- func CheckRefinement(process *Process, refinement *ast.Refinement, joinHashes JoinHashes) bool
- func CheckStrictLiveness(node *Node, nodes []*Node) ([]*Link, *InvariantPosition)
- func CheckTransitionAssertion(process *Process, invariant *ast.Invariant, index int) bool
- func CheckTransitionInvariants(process *Process) map[int][]int
- func CloneDict(oldDict starlark.StringDict, refs map[starlark.Value]starlark.Value, ...) starlark.StringDict
- func ContainsInt(skipstmts []int, i int) bool
- func CopyDict(from starlark.StringDict, to starlark.StringDict, ...) starlark.StringDict
- func DeepCopyBuiltIn(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, ...) (starlark.Value, error)
- func EndOfBlock(path string) string
- func ExecFunction(process *Process, name string) starlark.Value
- func GenerateCommunicationGraph(messages []string) string
- func GenerateDotFile(node *Node, visited map[*Node]bool) string
- func GenerateErrorPathProtoOfJson(errorPath []*Link, pathPrefix string) ([]string, []string, error)
- func GenerateFailurePath(nodes []*Link, name string, invariant *InvariantPosition) string
- func GenerateFailurePathHtml(srcFileName string, failurePath []*Link, invariant *InvariantPosition, ...) error
- func GenerateProtoOfJson(nodes []*Node, pathPrefix string) ([]string, []string, error)
- func GetAllNodes(root *Node, maxActions int64) ([]*Node, []string, *Node, int)
- func GetFieldByPath(msg proto.Message, path string) *reflect.Value
- func GetNextFieldPath(msg proto.Message, path string) (string, *reflect.Value)
- func GetProtoFieldByPath(file *ast.File, location string) proto.Message
- func GetStringFieldByPath(file *ast.File, location string) (string, bool)
- func HandleModules(path string) map[string]starlark.Value
- func LoadModule(moduleFile string) starlark.StringDict
- func MapRoleValuesInOrder(m map[starlark.Value]starlark.Value, oldList []*lib.Role) []*lib.Role
- func NewDictFromStringDict(vals starlark.StringDict) *starlark.Dict
- func PanicIfFalse(ok bool, msg string)
- func PanicOnError(err error)
- func ParentBlockPath(path string) string
- func ReadOptionsFromYaml(filename string) (*proto.StateSpaceOptions, error)
- func ReadOptionsFromYamlString(contents string) (*proto.StateSpaceOptions, error)
- func RemoveLastBlock(path string) string
- func RemoveLastForStmt(path string) string
- func RemoveLastLoop(path string) string
- func RemoveLastLoopBlock(path string) string
- func RemoveLastSegment(path string, substr string) string
- func RemoveLastWhileStmt(path string) string
- func RemoveMergeNodes(root *Node)
- func StringDictToJson(stringDict starlark.StringDict) ([]byte, error)
- func StringDictToJsonRetainType(strDict starlark.StringDict) ([]byte, error)
- func StringDictToJsonString(stringDict starlark.StringDict) string
- func StringDictToMap(stringDict starlark.StringDict) map[string]string
- type CallFrame
- type CallStack
- type ChannelMessage
- func (cm *ChannelMessage) Clone(refs map[starlark.Value]starlark.Value, ...) *ChannelMessage
- func (cm *ChannelMessage) Frame() *CallFrame
- func (cm *ChannelMessage) Function() string
- func (cm *ChannelMessage) HashCode() string
- func (cm *ChannelMessage) MarshalJSON() ([]byte, error)
- func (cm *ChannelMessage) Params() starlark.StringDict
- func (cm *ChannelMessage) Receiver() string
- func (cm *ChannelMessage) String() string
- type CodeSnippet
- type CycleCallback
- type CycleCallbackResult
- type DefType
- type Definition
- type DurabilitySpec
- type Evaluator
- func (e *Evaluator) EvalExpr(filename string, expr *ast.Expr, prevState starlark.StringDict) (starlark.Value, error)
- func (e *Evaluator) EvalPyExpr(filename string, src interface{}, prevState starlark.StringDict) (starlark.Value, error)
- func (e *Evaluator) ExecAction(filename string, action *ast.Action, prevState starlark.StringDict) (bool, error)
- func (e *Evaluator) ExecAnyStmt(filename string, anyStmt *ast.AnyStmt, prevState starlark.StringDict) (bool, error)
- func (e *Evaluator) ExecBlock(filename string, block *ast.Block, prevState starlark.StringDict) (bool, error)
- func (e *Evaluator) ExecForStmt(filename string, forStmt *ast.ForStmt, prevState starlark.StringDict) bool
- func (e *Evaluator) ExecIfStmt(filename string, ifStmt *ast.IfStmt, prevState starlark.StringDict) bool
- func (e *Evaluator) ExecInit(variables *ast.StateVars) (starlark.StringDict, error)
- func (e *Evaluator) ExecInitOld(variables *ast.StateVars) (starlark.StringDict, error)
- func (e *Evaluator) ExecPyStmt(filename string, stmt *ast.PyStmt, prevState starlark.StringDict) (bool, error)
- type HashKey
- type Heap
- type Histogram
- type HistogramEntry
- type InvariantPosition
- type JoinHashes
- type Link
- func AlwaysEventuallyFast(nodes []*Node, predicate Predicate) ([]*Link, bool)
- func AlwaysEventuallyFinal(nodes []*Node, root *Node, predicate Predicate) ([]*Link, bool)
- func CycleFinderFinal(nodes []*Node, root *Node, callback CycleCallback) ([]*Link, bool)
- func CycleFinderFinalBfs(node *Node, callback CycleCallback) ([]*Link, bool)
- func EventuallyAlwaysFast(nodes []*Node, predicate Predicate) ([]*Link, bool)
- func EventuallyAlwaysFinal(nodes []*Node, root *Node, predicate Predicate) ([]*Link, bool)
- func ExtractFailurePath(node *Node, rootNode *Node) []*Link
- func InitNodeToLink(node *Node) *Link
- func ReverseLink(node *Node, link *Link) *Link
- type ModelError
- type Node
- func (n *Node) Attach()
- func (n *Node) CreateNewToOldThreadIndexMap(other *Node) map[int]int
- func (n *Node) Duplicate(other *Node, yield bool)
- func (n *Node) ForkForAction(process *Process, role *lib.Role, action *ast.Action) *Node
- func (n *Node) ForkForAlternatePaths(process *Process, name string) *Node
- func (n *Node) GetJsonString() string
- func (n *Node) GetName() string
- func (n *Node) GetStateString() string
- func (n *Node) MarshalJSON() ([]byte, error)
- func (n *Node) String() string
- type Predicate
- type Process
- func (p *Process) CloneForAssert(permutations map[lib.SymmetricValue][]lib.SymmetricValue, alt int) *Process
- func (p *Process) Enable()
- func (p *Process) Fork() *Process
- func (p *Process) GetAllVariables() starlark.StringDict
- func (p *Process) GetAllVariablesNocopy() starlark.StringDict
- func (p *Process) GetSymmetryRoles() []*lib.SymmetricValues
- func (p *Process) GetThreads() []*Thread
- func (p *Process) GetThreadsCount() int
- func (p *Process) HasFailedInvariants() bool
- func (p *Process) HashCode() string
- func (p *Process) IsYieldNode() bool
- func (p *Process) MarshalJSON() ([]byte, error)
- func (p *Process) NewModelError(sourceInfo *ast.SourceInfo, msg string, nestedError error) *ModelError
- func (p *Process) NewThread() *Thread
- func (p *Process) PanicIfFalse(ok bool, sourceInfo *ast.SourceInfo, msg string)
- func (p *Process) PanicOnError(sourceInfo *ast.SourceInfo, msg string, nestedError error)
- func (p *Process) RecordCall(callerFrame *CallFrame, receiverFrame *CallFrame, flow ast.Flow)
- func (p *Process) RecordReturn(callerFrame *CallFrame, receiverFrame *CallFrame, val starlark.Value, ...)
- type Processor
- func (p *Processor) ExceedsActionCountLimits(action *ast.Action, statProcess *Process, role *lib.Role) bool
- func (p *Processor) GetVisitedNodesCount() int
- func (p *Processor) InitializeNode() (*Node, *Node, error)
- func (p *Processor) ResetEphemeralVariables(node *Node, oldRole *lib.Role)
- func (p *Processor) Start() (init *Node, failedNode *Node, err error)
- func (p *Processor) StartSimulation() (init *Node, failedNode *Node, err error)
- func (p *Processor) Stop()
- func (p *Processor) Stopped() bool
- func (p *Processor) YieldFork(node *Node, process *Process)
- func (p *Processor) YieldNode(node *Node)
- type ProtoPath
- type RoleDurabilitySpec
- type Scope
- type Stats
- type Thread
- func (t *Thread) Clone(permutations map[lib.SymmetricValue][]lib.SymmetricValue, alt int) *Thread
- func (t *Thread) CopyInitValuesForEphemeralFields(oldFrame *CallFrame)
- func (t *Thread) CurrentPcSourceInfo() *ast.SourceInfo
- func (t *Thread) Execute() ([]*Process, bool)
- func (t *Thread) ExitScope() *Scope
- func (t *Thread) FindNextProgramCounter() string
- func (t *Thread) HashCode() string
- func (t *Thread) InsertNewScope() *Scope
- type Transition
- type TransitionSet
Constants ¶
const (
ActionsWithMultipleBlocks = `` /* 3732-byte string literal not displayed */
)
Variables ¶
This section is empty.
Functions ¶
func CheckAssertion ¶
func CheckFastLiveness ¶
func CheckFastLiveness(allNodes []*Node) ([]*Link, *InvariantPosition)
func CheckInvariants ¶
func CheckLivenessSccAlwaysEventually ¶
func CheckLivenessSccAlwaysEventually(nodes []*Node, invPos InvariantPosition) (bool, error)
func CheckRefinement ¶ added in v0.2.0
func CheckRefinement(process *Process, refinement *ast.Refinement, joinHashes JoinHashes) bool
func CheckStrictLiveness ¶
func CheckStrictLiveness(node *Node, nodes []*Node) ([]*Link, *InvariantPosition)
func CloneDict ¶
func CloneDict(oldDict starlark.StringDict, refs map[starlark.Value]starlark.Value, permutations map[lib.SymmetricValue][]lib.SymmetricValue, alt int) starlark.StringDict
func ContainsInt ¶
func CopyDict ¶
func CopyDict(from starlark.StringDict, to starlark.StringDict, refs map[starlark.Value]starlark.Value, permutations map[lib.SymmetricValue][]lib.SymmetricValue, alt int) starlark.StringDict
CopyDict copies values `from` to `to` overriding existing values. If the `to` is nil, creates a new dict.
func DeepCopyBuiltIn ¶
func EndOfBlock ¶
func GenerateFailurePath ¶
func GenerateFailurePath(nodes []*Link, name string, invariant *InvariantPosition) string
func GenerateFailurePathHtml ¶ added in v0.2.0
func GenerateFailurePathHtml(srcFileName string, failurePath []*Link, invariant *InvariantPosition, outDir string) error
GenerateFailurePathHtml creates an HTML file showing differences between adjacent failurePath Links
func GenerateProtoOfJson ¶
func GetNextFieldPath ¶
func GetStringFieldByPath ¶
func LoadModule ¶
func LoadModule(moduleFile string) starlark.StringDict
func MapRoleValuesInOrder ¶
MapRoleValuesInOrder returns the values of the map m. The values will be in an indeterminate order.
func NewDictFromStringDict ¶
func NewDictFromStringDict(vals starlark.StringDict) *starlark.Dict
func PanicIfFalse ¶
func PanicOnError ¶
func PanicOnError(err error)
func ParentBlockPath ¶
func ReadOptionsFromYaml ¶
func ReadOptionsFromYaml(filename string) (*proto.StateSpaceOptions, error)
func ReadOptionsFromYamlString ¶
func ReadOptionsFromYamlString(contents string) (*proto.StateSpaceOptions, error)
func RemoveLastBlock ¶
func RemoveLastForStmt ¶
func RemoveLastLoop ¶
func RemoveLastLoopBlock ¶
func RemoveLastSegment ¶
func RemoveLastWhileStmt ¶
func RemoveMergeNodes ¶
func RemoveMergeNodes(root *Node)
func StringDictToJson ¶
func StringDictToJson(stringDict starlark.StringDict) ([]byte, error)
func StringDictToJsonRetainType ¶
func StringDictToJsonRetainType(strDict starlark.StringDict) ([]byte, error)
func StringDictToJsonString ¶
func StringDictToJsonString(stringDict starlark.StringDict) string
func StringDictToMap ¶
func StringDictToMap(stringDict starlark.StringDict) map[string]string
Types ¶
type CallFrame ¶
type CallFrame struct {
// FileIndex is the ast.FileIndex that this frame is executing.
FileIndex int
// Name is the full path of the function/action being executed.
Name string
// contains filtered or unexported fields
}
func (*CallFrame) MarshalJSON ¶
type CallStack ¶
func NewCallStack ¶
func NewCallStack() *CallStack
func (*CallStack) Clone ¶
func (s *CallStack) Clone(map[lib.SymmetricValue][]lib.SymmetricValue, int) *CallStack
type ChannelMessage ¶
type ChannelMessage struct {
// contains filtered or unexported fields
}
func (*ChannelMessage) Clone ¶
func (cm *ChannelMessage) Clone(refs map[starlark.Value]starlark.Value, permutations map[lib.SymmetricValue][]lib.SymmetricValue, alt int) *ChannelMessage
func (*ChannelMessage) Frame ¶
func (cm *ChannelMessage) Frame() *CallFrame
func (*ChannelMessage) Function ¶
func (cm *ChannelMessage) Function() string
func (*ChannelMessage) HashCode ¶
func (cm *ChannelMessage) HashCode() string
func (*ChannelMessage) MarshalJSON ¶
func (cm *ChannelMessage) MarshalJSON() ([]byte, error)
func (*ChannelMessage) Params ¶
func (cm *ChannelMessage) Params() starlark.StringDict
func (*ChannelMessage) Receiver ¶
func (cm *ChannelMessage) Receiver() string
func (*ChannelMessage) String ¶
func (cm *ChannelMessage) String() string
type CodeSnippet ¶
type CodeSnippet interface {
GetSourceInfo() *ast.SourceInfo
}
type CycleCallback ¶
type CycleCallback func(path []*Link, cycles int) (bool, *CycleCallbackResult)
type CycleCallbackResult ¶
type CycleCallbackResult struct {
// contains filtered or unexported fields
}
type DefType ¶
type DefType string
DefType is a custom enum-like type
const (
Function DefType = "function"
)
type Definition ¶
type Definition struct {
DefType DefType
// contains filtered or unexported fields
}
type DurabilitySpec ¶
type DurabilitySpec struct {
RoleDurabilitySpec map[string]RoleDurabilitySpec
}
func (*DurabilitySpec) AddDurabilitySpec ¶
func (d *DurabilitySpec) AddDurabilitySpec(evaluator *Evaluator, role *ast.Role)
func (*DurabilitySpec) HasDurabilitySpec ¶
func (d *DurabilitySpec) HasDurabilitySpec(role string) bool
HasDurabilitySpec returns true if the role has a durability spec.
func (*DurabilitySpec) IsFieldDurable ¶
func (d *DurabilitySpec) IsFieldDurable(role string, field string) bool
IsFieldDurable returns true if the field is durable for the role.
type Evaluator ¶
type Evaluator struct {
// contains filtered or unexported fields
}
func NewEvaluator ¶
func NewEvaluator(options *syntax.FileOptions, thread *starlark.Thread) *Evaluator
func NewModelChecker ¶
func (*Evaluator) EvalPyExpr ¶
func (*Evaluator) ExecAction ¶
func (*Evaluator) ExecAnyStmt ¶
func (*Evaluator) ExecForStmt ¶
func (*Evaluator) ExecIfStmt ¶
func (*Evaluator) ExecInitOld ¶
func (*Evaluator) ExecPyStmt ¶
type Heap ¶
type Heap struct {
CachedHashCode string
// contains filtered or unexported fields
}
func NewComposedHeap ¶ added in v0.2.0
func (*Heap) GetSymmetryDefs ¶
func (h *Heap) GetSymmetryDefs() []*lib.SymmetricValues
func (*Heap) MarshalJSON ¶
type Histogram ¶
type Histogram struct {
// contains filtered or unexported fields
}
func FindAbsorptionCosts ¶
func (*Histogram) GetAllHistogram ¶
func (h *Histogram) GetAllHistogram() []HistogramEntry
func (*Histogram) GetMeanCounts ¶
type HistogramEntry ¶
type HistogramEntry struct {
// contains filtered or unexported fields
}
type InvariantPosition ¶
func CheckSimpleExistsWitness ¶
func CheckSimpleExistsWitness(nodes []*Node) []*InvariantPosition
func NewInvariantPosition ¶
func NewInvariantPosition(fileIndex, invariantIndex int) *InvariantPosition
type JoinHashes ¶ added in v0.2.0
type JoinHashes map[HashKey][]TransitionSet
type Link ¶
type Link struct {
Node *Node
Type string
Name string
Labels []string
Fairness ast.FairnessLevel
ChoiceFairness ast.FairnessLevel
Messages []*ast.Message
ReqId int
ThreadsMap map[int]int
FailedInvariants map[int][]int
}
func AlwaysEventuallyFast ¶
func AlwaysEventuallyFinal ¶
func CycleFinderFinal ¶
func CycleFinderFinal(nodes []*Node, root *Node, callback CycleCallback) ([]*Link, bool)
func CycleFinderFinalBfs ¶
func CycleFinderFinalBfs(node *Node, callback CycleCallback) ([]*Link, bool)
func EventuallyAlwaysFast ¶
func EventuallyAlwaysFinal ¶
func ExtractFailurePath ¶ added in v0.2.0
func InitNodeToLink ¶
func ReverseLink ¶
func (*Link) HasFailedInvariants ¶
func (*Link) IsCrashLink ¶
type ModelError ¶
type ModelError struct {
SourceInfo *proto.SourceInfo
Msg string
Process *Process
NestedError error
}
func NewModelError ¶
func NewModelError(sourceInfo *proto.SourceInfo, msg string, process *Process, nestedError error) *ModelError
func (*ModelError) Error ¶
func (e *ModelError) Error() string
func (*ModelError) SprintStackTrace ¶
func (e *ModelError) SprintStackTrace() string
type Node ¶
type Node struct {
*Process `json:"process"`
Inbound []*Link `json:"-"`
Outbound []*Link `json:"-"`
DuplicateOf *Node
// contains filtered or unexported fields
}
func (*Node) CreateNewToOldThreadIndexMap ¶
func (*Node) ForkForAction ¶
func (*Node) ForkForAlternatePaths ¶
func (*Node) GetJsonString ¶
func (*Node) GetStateString ¶
func (*Node) MarshalJSON ¶
type Process ¶
type Process struct {
Heap *Heap `json:"state"`
Threads []*Thread `json:"threads"`
Current int `json:"current"`
Name string `json:"name"`
Files []*ast.File `json:"-"`
Parent *Process `json:"-"`
Evaluator *Evaluator `json:"-"`
Children []*Process `json:"-"`
FailedInvariants map[int][]int `json:"failedInvariants"`
Stats *Stats `json:"stats"`
// Witness indicates the successful liveness checks
// For liveness checks, not all nodes will pass the condition, witness indicates
// which invariants this node passed.
Witness [][]bool `json:"witness"`
Returns starlark.StringDict `json:"returns"`
SymbolTable map[string]*Definition `json:"-"`
Labels []string `json:"-"`
Messages []*ast.Message `json:"-"`
// Fairness is actually a property of the transition/link. But to determine whether
// the link is fair, we need to know if the process stepped through at least one
// fair statement. To determine that, each thread maintains the fairness level
// of the action that started. If that thread executed a statement, that process becomes fair,
// that in-turn makes the link fair.
Fairness ast.FairnessLevel `json:"-"`
Enabled bool `json:"-"`
ThreadProgress bool `json:"-"`
Roles []*lib.Role `json:"roles"`
Channels map[int]*lib.Channel `json:"channels"`
ChannelMessages map[int][]*ChannelMessage `json:"channel_messages"`
CachedHashCode string `json:"-"`
CachedThreadHashes []string `json:"-"`
Modules map[string]starlark.Value `json:"-"`
EnableCheckpoint bool `json:"-"`
ChoiceFairness ast.FairnessLevel `json:"-"`
// contains filtered or unexported fields
}
func (*Process) CloneForAssert ¶
func (p *Process) CloneForAssert(permutations map[lib.SymmetricValue][]lib.SymmetricValue, alt int) *Process
func (*Process) GetAllVariables ¶
func (p *Process) GetAllVariables() starlark.StringDict
GetAllVariables returns all variables visible in the Current thread. This includes state variables and variables from the Current thread's variables in the top call frame
func (*Process) GetAllVariablesNocopy ¶
func (p *Process) GetAllVariablesNocopy() starlark.StringDict
GetAllVariablesNocopy returns all variables visible in the Current thread, without deep copying. This includes state variables and variables from the Current thread's variables in the top call frame
func (*Process) GetSymmetryRoles ¶
func (p *Process) GetSymmetryRoles() []*lib.SymmetricValues
func (*Process) GetThreads ¶
GetThreads returns the active threads
func (*Process) GetThreadsCount ¶
func (*Process) HasFailedInvariants ¶
func (*Process) IsYieldNode ¶ added in v0.2.0
func (*Process) MarshalJSON ¶
func (*Process) NewModelError ¶
func (p *Process) NewModelError(sourceInfo *ast.SourceInfo, msg string, nestedError error) *ModelError
func (*Process) PanicIfFalse ¶
func (p *Process) PanicIfFalse(ok bool, sourceInfo *ast.SourceInfo, msg string)
func (*Process) PanicOnError ¶
func (p *Process) PanicOnError(sourceInfo *ast.SourceInfo, msg string, nestedError error)
func (*Process) RecordCall ¶
type Processor ¶
type Processor struct {
Init *Node
Files []*ast.File
Seed int64
// contains filtered or unexported fields
}
func NewProcessor ¶
func (*Processor) ExceedsActionCountLimits ¶
func (*Processor) GetVisitedNodesCount ¶
func (*Processor) ResetEphemeralVariables ¶
func (*Processor) StartSimulation ¶
type RoleDurabilitySpec ¶
type RoleDurabilitySpec struct {
// contains filtered or unexported fields
}
type Scope ¶
type Scope struct {
// contains filtered or unexported fields
}
func (*Scope) GetAllVisibleVariables ¶
func (s *Scope) GetAllVisibleVariables(roleRefs map[starlark.Value]starlark.Value) starlark.StringDict
GetAllVisibleVariables returns all variables visible in this scope.
func (*Scope) MarshalJSON ¶
type Thread ¶
type Thread struct {
Id int `json:"id"`
Process *Process `json:"-"`
Files []*ast.File `json:"-"`
Stack *CallStack `json:"stack"`
Fairness ast.FairnessLevel `json:"fairness"`
Aborted bool `json:"-"`
}
Thread represents a thread of execution.
func (*Thread) Clone ¶
func (t *Thread) Clone(permutations map[lib.SymmetricValue][]lib.SymmetricValue, alt int) *Thread
func (*Thread) CopyInitValuesForEphemeralFields ¶
func (*Thread) CurrentPcSourceInfo ¶
func (t *Thread) CurrentPcSourceInfo() *ast.SourceInfo
func (*Thread) ExitScope ¶
ExitScope removes the Current scope and returns the removed scope or nil if no scope was present.
func (*Thread) FindNextProgramCounter ¶
func (*Thread) InsertNewScope ¶
InsertNewScope adds a new scope to the Current stack frame and returns the newly created scope.
type TransitionSet ¶ added in v0.2.0
type TransitionSet map[Transition]bool
type NodeSet map[*modelchecker.Node]bool