FOR loops
Independent processing of N tokens
In the simplest case you want to do the same task for independent data. In the workflow arena this
generally means that you want to process the stream of tokens. Which in turn means that there is
no loop at all, just input tokens entering the processing workflow and result tokens leaving it.
Whenever possible, try to express your problem this way.
The following example shows the design for a file processing pipeline workflow. The first composite
is continuously watching a directory and outputs new files packed in arrays. The ArrayToSequence actor
creates a stream of file tokens from each array token. The rest of the workflow is processing each
file independently from the others.
Note: Because of the changing rate of token outputs for each input token in
ArrayToSequence, this workflow cannot run under SDF. However, the rest of the workflow can run under
SDF as well. If you prefer SDF over PN, you can put the processing pipeline (right to the
ArrayToSequence actor)into a composite actor with its own SDF director. This way you save computing
resources by using a single thread for the whole processing, however, this way you loose the
parallel processing capabilities of PN.
Processing a token iteratively N times
The author of this howto is not aware of whether this type of looping can be solved differently
from the general WHILE loops in Kepler. So, please, read on to the next section.
WHILE / DO-WHILE loops
If the looping condition depends on the actual data, you need to implement the WHILE (or UNTIL) loop
within the workflow control. There is no special actor or workflow construction for loops.
You have to realize a WHILE loop quite similar to assembly languages, using conditional branching and
jumping (have you ever heard about GOTO?).
While loop in PN
In PN, one can merge independent token streams with NondeterministicMerge, so the control flow
of a while loop is easy to implement. The entry point of the loop is reached from two places: from
outside to begin a loop, and from the end of the loop. If the condition holds the processing
(the token) goes on the loop-inside workflow, otherwise through the exit point.
The following example multiplies the a number with itself as long as the input is less than 1000.
So the result is 65536 for input=2 (producing the numbers 4, 16, 256 and 65536 within the loop).
Download this workflow
Do-while loop in PN
In a do-while loop, the condition is evaluated at the end of the loop, so the loop-inside part is
executed at least once. The following until loop produces 65536 for input 2 as well as the above
while loop. However, for inputs greater than 1001, this workflow will still do one multiplication
in contrast to the while loop.
The following example multiplies the a number with itself as long as the result is less than 1000.
Download this workflow
While loop in DDF
In DDF, the NondeterministicMerge cannot be used but there is another solution. We can use
DDFBooleanSelect as we have used it for merging tokens from the branches of an IF-THEN-ELSE.
However, for this we need an additional control input, therefore the result of the condition
evaluation should be delivered to the select actor, too. The following figure shows the replacement
of the merge actor for the select actor and the additional connections. This workflow has a cycle
dependency at the select actor and therefore hangs in deadlock right at the beginning.
When a workflow is drawn with a loop, the dependency graph of actors will have a cycle.
The SampleDelay actor has the key role in breaking the dependency cycle in the workflow;
without that the actors would wait forever for their first input. The SampleDelay is a special
actor that outputs one or more tokens without input so that it brings the workflow execution in motion.
The same workflow as above with PN realized in DDF looks like the following. A SampleDelay actor is put
into the control path to the select actor, which emits a false token at the beginning. This
breaks the dependency, and the select actor passes the initial value coming on its false branch.
Download this workflow
A nice example from Ptolemy demos
The next example is taken from Ptolemy to demonstrate a data-dependent loop. This workflow is actually
a nested loop. The external loop is a FOR loop, where Ramp produces the numbers from 1 to N, and N is
set in the DDFDirector as number of firing. The internal WHILE loop is then realized in the control flow
within the workflow, using BooleanSwitch and DDFBooleanSelect.
Download this workflow
Special cases
Processing a file line-by-line, in SDF
Ptolemy developers were nice to provide the LineReader actor that reads a file line-by-line and
produces a string token for each line. It has an EndOfFile output port, too, which outputs true when
EOF is reached. With this actor, a loop on the content of a file can be realized in SDF!
The loop is controlled simply by the output of the LineReader actor. Its implementation ensures
(its postfire() returns false when EOF is reached, see the actor's documentation) that the loop stops
when the end of file is reached.
Download this workflow
Processing a file line-by-line, with external trigger
The good news is over. The above file reader loop runs in itself. But in most cases you want to put
this worfklow into a larger workflow, run it when needed and do something more after finishing with
the file. The author of this howto could not create such workflows in SDF, so the next example
reverts back to DDF (or PN).
Download this workflow