Contact

Email (PGP key), Homepage

Address: IBISC, 1st floor, room 16,
University of Évry
Tour Évry 2
523 place des terrasses de l'Agora
91000 Évry, France

Tel: (+33)160873718
Fax: (+33)160873789


Search

Rss Posts

Rss Comments

Login

 

First steps with SNAKES

Friday, January 15, 2010

In this post, we define a simple coloured Petri net and see how to fire transitions and get markings.


Let's consider a simple coloured Petri net with a single transition that increments an integer valued token (so, 0 is the value of the token, not a number of tokens) token held by a single place, the incrementation stops when the value is 5 thanks to a guard on the transition.
To define this net, we must load SNAKES, define a Petri net (lets call it 'First net'), add the place (called 'p'), add the transition (called 't') and then connect them with arcs.
>>> from snakes.nets import *
>>> n = PetriNet('First net')
>>> n.add_place(Place('p', [0]))
>>> n.add_transition(Transition('t', Expression('x<5')))
>>> n.add_input('p', 't', Variable('x'))
>>> n.add_output('p', 't', Expression('x+1'))
Expression Place(p, [0]) constructs a new instance of class Place that expects the name of the place as its first argument. The second argument is optional and is the initial marking of the place, that can be given as a list tokens (or any iterable collection).
In order to build the transition, we create an instance of class Transition whose constructor expects the name of the transition and an optional guard (true by default). A guard is specified as Expression("...") where "..." is an arbitrary Python expression, like Expression("x<5") in our example.
Arcs are added using one of the methods add_input or add_output of PetriNet; both expect a place name, a transition name (always in this order) and the arc annotation as arguments (always in this order). An input arc is directed from a place toward a transition, an output arc is outgoing a transition; so arcs are considered from the point of view of the transition to which they are connected. In particular, arc annotations may be:
  • values as instances of class Value whose constructor simply expects the value that can be any Python object. For instances, Value(1) is the integer 1.
  • variables names that can be bound to token values when a transition if executed. A variable is created by instantiating class Variable whose constructor expects the name of the variable as a Python string (matching regexp "[a-zA-Z]\w*").
  • expressions to compute new values. An expression is an instance of class Expression whose constructor expects any Python expression as a string. In our example, Expression("x+1") as been used on the output arc.
The first step to execute a transition is to bind the variables labelling the input arcs to actual token values. This is possible by calling method modes() of a transition. It returns a list of Substitution instances that are dict-like objects to map variable names to values. Method modes returns a list of substitutions that enable the transition:
  • each input arc, evaluated through the substitution, yields a multiset of tokens smaller than or equal to the current marking of the connected place;
  • each output arc, evaluated through the substitution, yields a multiset of tokens that respects the type constraint of the connected place;
  • the guard of the transition, evaluates to True through the substitution.
For instance, with our net, exactly one mode is available to fire the transition:
>>> n.transition('t').modes()
[Substitution(x=0)]
In order to fire a transition, we have to call its method fire with an enabling substitution as argument. In our example, we could run:
>>> n.transition('t').fire(Substitution(x=0))
>>> n.place('p').tokensIn [15]: n.get_marking()
MultiSet([1])
Notice how attribute token allows to inspect the marking of each places. But we can also get the marking of a whole net:
>>> n.get_marking()
Marking({'p': MultiSet([1])})
Related Posts:

Post a comment