Skip to main content
Version: 0.6.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.