This implementation of a PetriNet Director is an extension of the PetriNet
Director created by Wang and Lee located in the experimental domain. This
director supports an iteration count that can be used to stop execution,
even if transitions are ready to fire. The director also supports a
PetriNetDisplay actor that prints token counts of all the Places (at each
iteration) after execution is finished. The documentation for the original
Wang and Lee director is provided below and includes a definition of PetriNet.
<p>
This domain implements the basic Petri Net model where Places and Transitions
form a bipartite graph and enabled Transitions can fire randomly. It also
allows Transitions to be replaced by any other Actors in Ptolemy. It
implements two forms of Hierarchical and compositional Petri nets. The first
form of hierarchical and compositional Petri net semantics comes from the
fact that a Transition can contain a sub-Petri-net which is invisible to the
director of the container of the Transition. The second form of hierarchical
and compositional Petri net semantics comes from a new Actor called
PetriNetActor which is a collection of Places and Transitions, and those
Places and Transitions are visible to the director of the container of the
PetriNetActor. The users can choose which form of models to use, and/or mix
them together.
<p>
The basic Petri net is a directed, weighted, bipartite graph consisting of
two kinds of nodes, called <i>Places</i> and <i>Transitions</i>, where arcs
are either from a Place to a Transition or from a Transition to a Place. In
graphical representation, Places are drawn as circles, Transitions as bars or
boxes. Arcs are labeled with their <i>weights</i> (positive integers).
Labels of unity weight are usually omitted. Multiple arcs can exist between a
Place and a Transition. A <i>marking</i> assigns to each Place <i>p</i> an
nonnegative integer <i>k</i>, we say that <i>p</i> is <i>marked with k
tokens</i>.
<p>
Please note here the term <i>token</i> is used differently from the general
Ptolemy term <i>token</i>. Here a <i>token</i> is really the integer 1.
<i>k tokens</i> is represented by the integer <i>k</i>.
<p>
A Transition <i>t</i> is said to be <i>enabled</i> if each input Place <i>p</i>
of <i>t</i> is marked with at least the sum of <i>w(p, t)</i> tokens, where
<i>w(p, t)</i> are the weights of the arcs from <i>p</i> to <i>t</i>.
<p>
An enabled Transition may or may not fire. When there are multiple enabled
Transitions, any of them can fire randomly. A firing of an enabled Transition
<i>t</i> removes <i>w(p, t)</i> tokens from each input Place <i>p</i> of
<i>t</i>, and adds <i>w(t, p)</i> tokens to each output Place <i>p</i> of
<i>t</i>, where <i>w(t, p) and w(p, t) </i> are the weights of the arcs from
and to the Transition respectively.
<p>
A Transition without any input Place is called a <i>source Transition</i>,
and one without any output Place is called a <i>sink Transition</i>. Note
that a source Transition is unconditionally enabled, and that the firing of a
sink Transition consumes tokens, but does not produce any.
<p>
Many variations of Petri net exist in the literature including: hierarchical
Petri nets, colored Petri nets, timed Petri nets, fuzzy Petri nets,
stochastic Petri nets, compositional Petri nets, and many of the
combinations.
<p>
As pointed out earlier, in Ptolemy we implement the basic Petri net model
plus two kinds of hierarchical and compositional Petri nets. This is made
possible by defining the PetriNetActor. The PetriNetActor is a directed and
weighted graph just like the basic Petri Net model. However, a PetriNetActor
graph <i>G = (V, E) </i> contains three kinds of nodes: Places <i>p_i</i>,
Transitions <i>t_i</i>, and PetriNetActors <i>PA_i</i>, i.e., <i> V = {p_i}
union {t_i} union {PA_i} </i>, where each <i>PA_i</i> itself is again
defined as a PetriNetActor. Places are assigned with non-negative integer
markings. The default marking is 0. A Place is implemented by the atomic
actor Place. A PetriNetActor is a TypedCompositeActor contains Places,
Transitions and/or PetriNetActors.
<p>
Each node of <i>V</i> is called a <i>component</i> of the PetriNetActor
<i>G</i>. Therefore the vertex set <i>V</i> of <i>G</i> is also called the
<i>component set</i> of the PetriNetActor <i>G</i>. The concept of
<i>component</i> is a key difference between the basic Petri net model and
the hierarchical Petri net model defined here. In Ptolemy term, a component
is an element in the entityList of the PetriNetActor. A PetriNetActor
consists of components. A component can be a Place, a Transition, and a
PetriNetActor component. A component can be enabled and fires if it is a
Transition or it is a PetriNetActor component that contains other
Transitions. When the firing method _fireHierarchicalPetriNetOnce() fires, it
chooses one component to fire.
<p>
The definition of PetriNetActor defines one form of hierarchical and
compositional Petri nets. It defines a hierarchical Petri net since the
PetriNetActor <i>G</i> can contain other PetriNetActors <i>PA_i</i> as
components. It defines a compositional Petri net since two PetriNetActors
<i>PA_1 and PA_2 </i> of <i>V</i> can be connected through their ports to
form a bigger Petri net <i>G</i>.
<p>
The second form of Hierarchical and compositional Petri net comes from the
fact that a Transition can be any TypedCompositeActor in Ptolemy domains,
which can have its own firing director. The content of the Transition is
invisible to the director of the container of the Transition. Therefore it is
possible to have a Transition contains other Places and Transitions and has a
PetriNetDirector as the local director for the Transition.
<p>
The <i>set of Transitions</i> of the PetriNetActor <i>G</i>, or the
Transition set of <i>G</i>, is defined to be the union of the Transitions
<i>t_i</i> with the sets of Transitions of each PetriNetActor component
<i>PA_i</i>. A member of the Transition set of <i>G</i> is therefore
contained in <i>G</i> itself in which case the Transition is also a
component of <i>G</i>, or it is contained in some PetriNetActor component
<i>PA_i</i>. Therefore a Transition is a different concept from a Component
in PetriNetActor graph. The method findTransitions() returns the Transition
set of <i>G</i>.
<p>
A component has ports through which connections to other components are made.
A Place or a Transition each has one input port and one output port, where
multiple connections can be made. In our model, a PetriNetActor component can
have multiple ports. A PetriNetActor component <i>PA_j</i> can be connected
to Places <i>p_i</i>, Transitions <i>t_i</i>, or other PetriNetActor
components <i>PA_i</i> through ports. A Place <i>p_i</i> can be connected
to Transitions <i>t_i</i>, or to ports of PetriNetActor components <i>PA_i</i>.
A Transition <i>t_i</i> can be connected to Places <i>p_i</i> or to ports
of PetriNetActor components <i>PA_i</i>.
<p>
One restriction is that a port of a PetriNetActor component <i>PA_i</i> is
either connected to Places or to Transitions, but not both. Another
restriction is that a Place (Transition) is not allowed to be connected to
another Place (Transition) through ports. Though no verification of these two
conditions is checked, any violation of these two conditions will be reported
by appropriate methods during the execution.
<p>
Multiple arcs can exist between any two components. The arcs can be marked by
an nonnegative integer as their weights. Weight 1 can be omitted. The method
_getWeightNumber(arc) obtains the weight assigned to the arc. If no weight is
assigned, the default weight is 1.
<p>
For a Transition <i>t</i>, all Places <i>p</i> that can reach <i>t</i>
through ports or without ports are the input Places of <i>t</i>. All Places
that can be reached from <i>t</i> through ports or without ports are the
output Places of <i>t</i>. Given a Transition <i>t</i>, the methods
_findBackwardConnectedPlaces() and _findForwardConnectedPlaces() find the
input and output Places of the Transition respectively.
<p>
A Transition <i>t</i> is enabled or ready in the PetriNetActor if for each
input Place <i>p</i> of <i>t</i>, the marking of <i>p</i> is bigger than
the sum of the weights of all arcs connecting <i>p</i> to <i>t</i>. The
method isTransitionReady(transition) tests whether the given Transition is
enabled/ready or not.
<p>
If a Transition <i>t</i> is enabled and <i>t</i> is contained in a
PetriNetActor component <i>PA_i</i>, then the PetriNetActor component
<i>PA_i</i> is also an enabled component. On the other hand, for any
PetriNetActor component <i>PA_i</i>, if it contains an enabled Transition,
then the PetriNetActor component <i>PA_i</i> is enabled. The method
PetriNetActor.prefire() tests whether there is any enabled Transitions
contained in the PetriNetActor component.
<p>
An enabled Transition may or may not fire. For the given PetriNetActor <i>G</i>,
all its enabled components including Transitions <i>t_i</i> and
PetriNetActor components <i>PA_i</i> are collected together in a list
returned by _readyComponentList(). Suppose the list has <i>n</i> components
of <i>t_i</i> and <i>PA_i</i>, each component has <i>1/n</i> probability
to be chosen to fire. The method _fireHierarchicalPetriNetOnce() chooses one
component from the list to fire.
<p>
If an enabled Transition is chosen to fire, the method fireTransition() is
called to fire the Transition and update the input and output Places of the
Transition. The firing of the Transition is determined by its own director,
if there is one, otherwise no action is needed. For each input Place of the
Transition, its marking has to be decreased by the weight of each arc
connecting the Place to the Transition. For each output Place, the marking
will be increased by the weight of each arc connecting the Transition to the
Place.
<p>
If a PetriNetActor component <i>PA_i</i> is chosen to fire, the director
then recursively repeats the same procedure for <i>PA_i</i> as for the top
level PetriNetActor <i>G</i>.
<p>
Finally, the firing of the hierarchical Petri net is continued until there is
no more Transitions and components to fire, or it goes to infinite loop.
Currently no action is taken for infinite loops.
<p>
Other form of firing sequence can be defined as well. We could randomly fire
all the deeply contained Transitions. We could randomly fire the components
in each hierarchy.
[1] T. Murata, "Petri nets: properties, analysis and applications",
Proceedings of the IEEE, VOl. 77, NO. 4, April 1989, pp. 541-579. [2] J. L.
Peterson, "Petri Net Theory and the modeling of systems", Prentice Hall,
1981.
Yuke Wang, Edward A. Lee and modified by Zach Ezzell
$Id: PetriNetDirector.java 70402 2014-10-23 00:52:20Z cxh $
Ptolemy II 8.1
If true, this parameter specifies that the random number
generator should be reset on each run of the model (in
the initialize() method). It is a boolean that defaults
to false. This is a shared parameter, meaning that changing
it somewhere in the model causes it to be changed everywhere
in the model.
The seed that controls the random number generator that
determines which component is fired.
<p>This is a shared parameter, meaning that all instances of
PetriNetDirector or derived classes in the same model share the
same value. This parameter is used for testing so that a
model has predictable results and can be compared against
known good results.</p>
<p>A seed of zero is interpreted to mean that no seed is
specified, which means that each execution of the model could
result in distinct data. For the value 0, the seed is set to
System.currentTimeMillis() + hashCode(), which means that with
extremely high probability, two distinct directors will have
distinct seeds. However, current time may not have enough
resolution to ensure that two subsequent executions of the
same model have distinct seeds. For a value other than zero,
the seed is set to that value plus the hashCode() of the full
name of the director. This means that with high probability,
two distinct director will have distinct, but repeatable
seeds.</p>
<p>This parameter contains a LongToken, initially with value
0.</p>