14.Using Python - larics/Petri.Net GitHub Wiki

Starting of version 2.1, Petri.NET simulator allows Python programming language to be used for system control. Instead of previously described “rules”, here we can implement a much more complicated control algorithms, as well as other features like saving data, using advanced mathematical functions, printing debug messages, connecting to other systems, etc.

Internet provides great resources for learning Python, numerous free books, videos and/or examples. Here we expect the reader to have at least basic experience with programming and programming languages.

Petri.NET simulator uses Python code in the following way:

  • Before each step, a Python function Step(k) is called, with parameter k corresponding to time instance
  • At the end of simulation, a Python function Reset() is called. Existence of this function isn’t mandatory and simulation will work well even without it.
  • Each place is associated with one global variable named as place NameID. User must take care that there are no places with same name. If NameID is empty, global variable is set to default name in form Px (as in the following example).
  • User can define its own functions and use them within Step(k) function

Example system is shown in Figure 14-1. Input place contains 20 tokens, which are passed to operation P2, using resource P3. Token advancement can be disabled or enabled using control place P5.

Figure 14.1. A simple system

Our task will be to allow processing of only 10 tokens. Python code that achieves this that task is:

def Step(k):
	global P5, P4
	if P4 < 10:
		P5 = 1
	else:
		P5 = 0

To use this code we have to write it in the „Python code editor“, shown in figure 14-2. Panel „Python output“ is used to report syntax and/or runtime errors.

Figure 14.2. A system and python code

Additional information during simulation can be obtained using Python command print. If we modify the previous code with two prints commands:

def Step(k):
	global P5, P4
	if P4 < 10:
		P5 = 1
		print "k=",k, ":T1 is open"
	else:
		P5 = 0
		print "k=",k, ":T1 is closed"

we’ll get a step by step information about transition T1 state printed out into “Python output” panel.

To access additional place features a function FindPlace should be used. Using that function an entire object with its properties will be available. For example, In following timed network we souble operation duration for place named "P2", but only when it contains a single token. In order to work properly, "P2" needs to be explicitely set as NameID.

def Step(k):
	xxx = FindPlace("P2")
	if xxx.Tokens==1:
		xxx.Duration *= 2
		print "Duration is now ", xxx.Duration, " (k=",k,")"

To get value of state vector global variable states_vector (list of integers) and names_vector (list of string) are available. To easily determine type of each element in that vector, a global variable types_vector is added too. A sample usage is shown in code below:

def Step(k):
	global names_vector, states_vector, types_vector
	print str(names_vector)
	print str(states_vector)
	print str(types_vector)

How to install Python extensions/libraries

Once you get a latest release zip and unpack it somewhere, together with a PetriNet simulator you'll find ipy.exe. Those executable is an IronPython shell. A reason why we include it here is a possibility to use it to install new packages/libraries that can be used from scripting. Before installation we must be sure that following requirement is satisfied: Library must support Python 2.6

For example let's take a look how to install pySerial (a Python library that simplify access to COM port). Checking that library we'll find several archives with libraries for different Python versions. We pick one that targets Python 2.6.

Once we download it, we'll unpacked archive on some place then open command prompt and go to that place. using ipy.exe you can execute command that will start installation script. Usually those command is ipy.exe setup.py install.

How this look like is shown below:

E:\Petri.Net.git\pyserial-2.6>..\ipy setup.py install
running install
running build
running build_py
warning: build_py: byte-compiling is disabled, skipping.
running build_scripts
running install_lib
warning: install_lib: byte-compiling is disabled, skipping.
running install_scripts
running install_egg_info
Removing E:\projects\PetriNet.git\Libs\IronPython\Lib\site-packages\pyserial-2.6-py2.6.egg-info
Writing E:\projects\PetriNet.git\Libs\IronPython\Lib\site-packages\pyserial-2.6-py2.6.egg-info

E:\Petri.Net.git\pyserial-2.6>

Similar method should be used with other packages. You'll only have to remember that we use Python 2.6 here so packages must be compatible with that.