This Simulator implements the 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 block in VisualSim. 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 blockcalled PetriNetBlock which is a collection of Places and Transitions, and those Places and Transitions are visible to the director of the container of the PetriNetBlock. The users can choose which form of models to use, and/or mix them together.
The basic Petri net is a directed, weighted, bipartite graph consisting of two kinds of nodes, called Places and Transitions, 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 weights (positive integers). Labels of unity weight are usually omitted. Multiple arcs can exist between a Place and a Transition. A marking assigns to each Place p an nonnegative integer k, we say that p is marked with k tokens.
Please note here the term token is used differently from the general VisualSim term token. Here a token is really the integer 1. k tokens is represented by the integer k.
A Transition t is said to be enabled if each input Place p of t is marked with at least the sum of w(p, t) tokens, where w(p, t) are the weights of the arcs from p to t.
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 t removes w(p, t) tokens from each input Place p of t, and adds w(t, p) tokens to each output Place p of t, where w(t, p) and w(p, t) are the weights of the arcs from and to the Transition respectively.
A Transition without any input Place is called a source Transition, and one without any output Place is called a sink Transition. Note that a source Transition is unconditionally enabled, and that the firing of a sink Transition consumes tokens, but does not produce any.
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.
As pointed out earlier, in VisualSim 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 PetriNetBlock graph G = (V, E) contains three kinds of nodes: Places p_i, Transitions t_i, and PetriNetBlocks PA_i, i.e., V = {p_i} union {t_i} union {PA_i} , where each PA_i itself is again defined as a PetriNetBlock. Places are assigned with non-negative integer markings. The default marking is 0. A Place is implemented by the atomic actor Place. A PetriNetBlock is a TypedCompositeActor contains Places, Transitions and/or PetriNetBlocks.
Each node of V is called a component of the PetriNetBlock G. Therefore the vertex set V of G is also called the component set of the PetriNetBlock G. The concept of component is a key difference between the basic Petri net model and the hierarchical Petri net model defined here. In VisualSim term, a component is an element in the entityList of the PetriNetBlock. A PetriNetBlock consists of components. A component can be a Place, a Transition, and a PetriNetBlock component. A component can be enabled and fires if it is a Transition or it is a PetriNetBlock component that contains other Transitions. When the firing method _fireHierarchicalPetriNetOnce() fires, it chooses one component to fire.
The definition of PetriNetBlock defines one form of hierarchical and compositional Petri nets. It defines a hierarchical Petri net since the PetriNetBlock G can contain other PetriNetBlocks PA_i as components. It defines a compositional Petri net since two PetriNetBlocks PA_1 and PA_2 of V can be connected through their ports to form a bigger Petri net G.
The second form of Hierarchical and compositional Petri net comes from the fact that a Transition can be any TypedCompositeActor in VisualSim simulators, 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 PetriNet Simulator as the local Simulator for the Transition.
The set of Transitions of the PetriNetBlock G, or the Transition set of G, is defined to be the union of the Transitions t_i with the sets of Transitions of each PetriNetBlock component PA_i. A member of the Transition set of G is therefore contained in G itself in which case the Transition is also a component of G, or it is contained in some PetriNetBlock component PA_i. Therefore a Transition is a different concept from a Component in PetriNetBlock graph. The method findTransitions() returns the Transition set of G.
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 PetriNetBlock component can have multiple ports. A PetriNetActor component PA_j can be connected to Places p_i, Transitions t_i, or other PetriNetBlock components PA_i through ports. A Place p_i can be connected to Transitions t_i, or to ports of PetriNetBlock components PA_i. A Transition t_i can be connected to Places p_i or to ports of PetriNetBlock components PA_i.
One restriction is that a port of a PetriNetBlock component PA_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.
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.
For a Transition t, all Places p that can reach t through ports or without ports are the input Places of t. All Places that can be reached from t through ports or without ports are the output Places of t. Given a Transition t, the methods _findBackwardConnectedPlaces() and _findForwardConnectedPlaces() find the input and output Places of the Transition respectively.
A Transition t is enabled or ready in the PetriNetActor if for each input Place p of t, the marking of p is bigger than the sum of the weights of all arcs connecting p to t. The method isTransitionReady(transition) tests whether the given Transition is enabled/ready or not.
If a Transition t is enabled and t is contained in a PetriNetBlock component PA_i, then the PetriNetActor component PA_i is also an enabled component. On the other hand, for any PetriNetBlock component PA_i, if it contains an enabled Transition, then the PetriNetBlock component PA_i is enabled. The method PetriNetBlock.prefire() tests whether there is any enabled Transitions contained in the PetriNetBlock component.
An enabled Transition may or may not fire. For the given PetriNetBlock G, all its enabled components including Transitions t_i and PetriNetBlock components PA_i are collected together in a list returned by _readyComponentList(). Suppose the list has n components of t_i and PA_i, each component has 1/n probability to be chosen to fire. The method _fireHierarchicalPetriNetOnce() chooses one component from the list to fire.
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.
If a PetriNetBlock component PA_i is chosen to fire, the director then recursively repeats the same procedure for PA_i as for the top level PetriNetBlock G.
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.
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.