A plugin to add positions to the nodes.

Place and Transition are added an optional argument for the constructor pos=(x,y) to set their position. Moreover, these classes are added an attribute pos that holds a pair of numbers with attributes x and y and methods shift(dx, dy) and moveto(x, y). So, when the plugin is loaded, we can specify and retreive nodes positions:

>>> import snakes.plugins
>>> snakes.plugins.load('pos', 'snakes.nets', 'nets')
<module ...>
>>> from nets import PetriNet, Place, Transition
>>> n = PetriNet('N')
>>> n.add_place(Place('p00'))
>>> t10 = Transition('t10', pos=(1, 0))
>>> n.add_transition(t10)
>>> n.add_place(Place('p11', pos=(1, 1)))
>>> n.add_transition(Transition('t01', pos=(0, 1)))
>>> t10.pos
Position(1, 0)
>>> t10.pos.x
1
>>> t10.pos.y
0
>>> t10.pos()
(1, 0)

Nodes positions is immutable, we must use method moveto to change positions:

>>> t10.pos.y = 1
Traceback (most recent call last):
  ...
AttributeError: readonly attribute
>>> t10.pos.moveto(t10.pos.x, 1)
>>> t10.pos
Position(1, 1)

Petri nets are added methods bbox() that returns a pair of extrema ((xmin, ymin), (xmax, ymax)), a method shift(dx, dy) that shift all the nodes, and a method transpose() that rotates the net in such a way that the top-down direction becomes left-right:

>>> n.bbox()
((0, 0), (1, 1))
>>> n.shift(1, 2)
>>> n.bbox()
((1, 2), (2, 3))
>>> n.node('t01').copy().pos
Position(1, 3)
>>> n.transpose()
>>> n.node('t01').pos
Position(-3, 1)

Class Position

class Position (object) :

The position of a node

Method Position.__init__

def __init__ (self, x, y) :

Constructor expects the Cartesian coordinates of the node, they can be provided as float or int.

Call API

Method Position.moveto

def moveto (self, x, y) :

Change current coordinates to the specified position

Call API

Method Position.shift

def shift (self, dx, dy) :

Shift current coordinates by the specified amount.

Call API

Method Position.__getitem__

def __getitem__ (self, index) :

Access coordinates by index

>>> Position(1, 2)[0]
1
>>> Position(1, 2)[1]
2
>>> Position(1, 2)[42]
Traceback (most recent call last):
  ...
IndexError: Position index out of range
Call API
Exceptions

Method Position.__iter__

def __iter__ (self) :

Successively yield x and y coordinates

>>> list(Position(1, 2))
[1, 2]

Method Position.__call__

def __call__ (self) :

Return the position as a pair of values

>>> Position(1, 2.0)()
(1, 2.0)
Call API

Extensions

Class Place

class Place (module.Place) :

Method Place.__init__

def __init__ (self, name, tokens=[], check=None, **args) :

If no position is given (0, 0) is chosen

>>> Place('p').pos
Position(0, 0)
>>> Place('p', pos=(1,2)).pos
Position(1, 2)
Call API

Class Transition

class Transition (module.Transition) :

Method Transition.__init__

def __init__ (self, name, guard=None, **args) :

If no position is given (0, 0) is chosen

>>> Transition('t').pos
Position(0, 0)
>>> Transition('t', pos=(1,2)).pos
Position(1, 2)
Call API

Class PetriNet

class PetriNet (module.PetriNet) :

Method PetriNet.add_place

def add_place (self, place, **args) :

Position can be set also when a place is added to the net.

>>> n = PetriNet('n')
>>> n.add_place(Place('a', pos=(1, 2)))
>>> n.node('a').pos
Position(1, 2)
>>> n.add_place(Place('b'), pos=(3,4))
>>> n.node('b').pos
Position(3, 4)
>>> n.add_place(Place('c', pos=(42, 42)), pos=(5, 6))
>>> n.node('c').pos
Position(5, 6)
Call API

Method PetriNet.add_transition

def add_transition (self, trans, **args) :

Position can be set also when a transitions is added to the net. See method add_place above.

Call API

Method PetriNet.merge_places

def merge_places (self, target, sources, **args) :

When places are merged, the position of the new place is the barycentre of the positions of the merged nodes. Optionally, position can be specified in the call the merge_places.

>>> n = PetriNet('n')
>>> n.add_place(Place('a', pos=(1,2)))
>>> n.add_place(Place('b', pos=(3,4)))
>>> n.merge_places('c', ['a', 'b'])
>>> n.node('c').pos
Position(2.0, 3.0)
>>> n.merge_places('d', ['a', 'b'], pos=(0, 0))
>>> n.node('d').pos
Position(0, 0)
Call API

Method PetriNet.merge_transitions

def merge_transitions (self, target, sources, **args) :

See method merge_places above.

Method PetriNet.bbox

def bbox (self) :

The bounding box of the net, that is, the smallest rectangle that contains all nodes coordinates.

Call API

Method PetriNet.shift

def shift (self, dx, dy) :

Shift every node by (dx, dy)

Call API

Method PetriNet.transpose

def transpose (self) :

Perform a clockwise 90 degrees rotation of node coordinates, ie, change every position (x, y) to (-y, x)