Skip to main content
Version: 0.8.0

Causality Loops

This article has examples in the following target languages:

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:

Lingua Franca diagram: CycleCreator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Sunday, April 10, 2022 at 1:46:50 PM Pacific Daylight TimeReactor contains cyclic dependencies!Show CycleFilter CycleCycleAxyB12xy

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; }
Lingua Franca diagram: CycleWithDelayCreator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Sunday, April 10, 2022 at 1:54:07 PM Pacific Daylight TimeCycleWithDelayAxyB12xy0

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; }
Lingua Franca diagram: CycleReorderedCreator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Sunday, April 10, 2022 at 1:59:04 PM Pacific Daylight TimeCycleReorderedAxyB12xy

There is no longer any causality loop.