Version: 0.8.0

# Causality Loops

## Cyclesâ€‹

The interconnection pattern for a collection of reactors can form a cycle, but some care is required. Consider the following example:

target C; reactor A { input x:int; output y:int; reaction(x) -> y {= // ... something here ... =} } reactor B { input x:int; output y:int; reaction(x) {= // ... something here ... =} reaction(startup) -> y {= // ... something here ... =} } main reactor { a = new A(); b = new B(); a.y -> b.x; b.y -> a.x; }

This program yields the following diagram:

The diagram highlights a causality loop in the program. At each tag, in reactor `B`, the first reaction has to execute before the second if it is enabled, a precedence indicated with the red dashed arrow. But the first can't execute until the reaction of `A` has executed, and that reaction cannot execute until the second reaction `B` has executed. There is no way to satisfy these requirements, so the tools refuse to generated code.

## Cycles with Delaysâ€‹

One way to break the causality loop and get an executable program is to introduce a logical delay into the loop, as shown below:

target C; reactor A { input x:int; output y:int; reaction(x) -> y {= // ... something here ... =} } reactor B { input x:int; output y:int; reaction(x) {= // ... something here ... =} reaction(startup) -> y {= // ... something here ... =} } main reactor { a = new A(); b = new B(); a.y -> b.x after 0; b.y -> a.x; }

Here, we have used a delay of 0, which results in a delay of one microstep. We could equally well have specified a positive time value.

## Reaction Orderâ€‹

Frequently, a program will have such cycles, but you don't want a logical delay in the loop. To get a cycle without logical delays, the reactions need to be reordered, as shown below:

target C; reactor A { input x:int; output y:int; reaction(x) -> y {= // ... something here ... =} } reactor B { input x:int; output y:int; reaction(startup) -> y {= // ... something here ... =} reaction(x) {= // ... something here ... =} } main reactor { a = new A(); b = new B(); a.y -> b.x; b.y -> a.x; }

There is no longer any causality loop.