In order to check if a process `Impl`

refines (in a particular semantic model)
a process `Spec`

, FDR firstly converts `Impl`

and `Spec`

into labelled
transition systems, as described in Compilation. FDR then
normalises the specification machine, as described in `normal`

. FDR then
explores the states of these processes in breadth-first order, checking that the
states are related according to the semantic model. As soon as FDR finds a
counterexample it immediately reports it. Thus, thanks to the breadth-first
order, any counterexample that FDR returns will be minimal in the length of the
trace (including taus).

In order to understand exactly how FDR visits state pairs during a refinement check, consider the following script:

```
channel a, b, c
P1 = a -> P2
P2 = P3 |~| P4
P3 = b -> P2
P4 = a -> P1
Q1 = a -> Q2
Q2 = b -> Q1
assert Q1 [T= P1
```

FDR initialises the search by looking at the state pair `(Q1, P1)`

(nb. state
pairs consist of a specification state and an implementation state). In the
traces model, FDR only has to check that the events (excluding tau) offered by
`P1`

are a subset of those offered by `Q1`

, which is clearly the cases here.
Hence, FDR now adds the successor state pairs for each event offered by `P1`

to the search. In this case, there is only one successor state pair after `a`

,
`(Q2, P2)`

.

When considering the state pair `(Q2, P2)`

note that `P2`

does not offer any
visible events, and therefore the event check is trivially true. FDR now needs
to add any new state pairs to the search. In this case, the two state pairs
`(Q2, P3)`

and `(Q2, P4)`

are added to the search. Note that the
specification part of the state pair is kept the same because the implementation
performs a tau. FDR will now consider the new state pairs. In particular, when
it considers `(Q2, P4)`

FDR will find a counterexample since the events
offered by `P4`

are not a subset of those offered by `Q2`

.

In order to reconstruct the trace that the invalid state pair was reached by,
FDR stores a parent state pair of each state pair that it finds during the
search. Thus, in the above example, FDR will set the parent of `(Q2, P4)`

as `(Q2, P2)`

and the parent of `(Q2, P2)`

to `(Q1, P1)`

. Thus, FDR can
reconstruct the counterexample trace by finding events that transition between
`(Q1, P1)`

and `(Q2, P2)`

, and `(Q2, P2)`

and `(Q2, P4)`

. This will
yield the trace `<a, tau>`

, in this case.

A counterexample to a refinement assertion consists of a trace leading to a particular state pair that are not related according the to semantic model in use. Thus, if the traces model is in use, then this must mean that the implementation can perform an event that the specification cannot. If the failures model is in use, then either the above case applies, or the implementation can refuse a set of events that the specification cannot. If the failures-divergences model is in use, then this must mean that either one of the above cases applies, or the implementation is divergent but the specification is not.

If FDR is asked to generate multiple counterexamples then this motivates the question of what FDR considers distinct counterexamples to be. In all cases, only a single counterexample will be generated from a single state pair. Thus, if a state pair is reachable via two different traces then only one counterexample will be generated, regardless of the number requested. Further, once FDR has found a counterexample for a given state pair, it does not look at successors of the state pair to see if they are counterexamples. Thus, for FDR to report two distinct counterexamples the counterexamples must be distinct state pairs, and the second state pair must be reachable via a path that does not include the first state pair. For example, the following has two counterexamples since the two STOP states are reachable via distinct paths:

```
P1 = STOP |~| P2
P2 = STOP
assert P1 :[deadlock free [F]]
```

However, the following only has one counterexample, since the second invalid state pair is only reachable via the first invalid state pair:

```
P1 = a -> P2 [] b -> STOP
P2 = a -> P1
Spec = a -> Spec
assert Spec [T= P1
```

Note that both `P1`

and` `P2`

violate the property, but `P2`

is only
reachable via `P1`

and thus is not considered.

As noted above, thanks to the breadth-first ordering that FDR visits the state
pairs in, FDR will always pick the counterexample that is reachable in the
fewest events (either tau or a visible event). Whilst this might imply that the
counterexample returned is chosen deterministically, this is not the case when
FDR is being used in parallel mode (i.e. `refinement.bfs.workers`

is
greater than 1) for two reasons:

The predecessor state pair of each state pair is chosen by a race between the different processor cores on each ply. For example, if two different cores both discover the same state pair on the same ply, then the state pair that is marked as the new state pair’s predecessor is chosen non-deterministically. This can result in a different trace being returned. The following script should exhibit this behaviour:

channel a, b, c P = a -> b -> Q [] b -> a -> Q Q = c -> STOP R = a -> R [] b -> R [] c -> R assert R [F= P

Note that there is precisely one state that violates the refinement,

`Q`

, but there are two different routes to`Q`

, via either`<a, b>`

or`<b, a>`

. Hence, since the states`b -> Q`

and`a -> Q`

are discovered on the same ply of the breadth-first search the winner will be chosen non-deterministically (assuming that they are visited by different cores). This should result in FDR non-deterministically returning either the counterexample trace`<a, b, c>`

or`<b, a, c>`

.On each ply of the search, there is essentially a race between the processor cores to find a counterexample: the first core that finds a counterexample wins. For example, consider the following refinement check:

channel a, b P = a -> STOP |~| b -> STOP assert STOP [T= P

There are two different counterexamples to this assertion: either the event

`a`

can be performed, or the event`b`

. Since these counterexamples are both found on the second ply of the search (the first ply simply explores the tau transitions available from the starting state), FDR will pick the counterexample non-deterministically, providing the two different states are picked by different cores.

In general use, the fact that different counterexamples are produced should
hopefully not be an issue. Unfortunately, there is no efficient way to make a
parallel version of FDR deterministically return the same counterexample. If it
is important that the same counterexample is returned each time then
`refinement.bfs.workers`

should be set to 1, thus disabling the
parallel refinement checker. This will obviously result in a decrease in
performance, but it does mean that the same counterexample will always be
returned.