eBook: Integration and Automation of Manufacturing Systems
   



TOC PREV NEXT

29.4 USING THE SUBROUTINES


29.4.1 Basic Petri Net Simulation

The subroutines are applied in a methodical manner. Before the user can integrate the subroutines into their program, they must draw out the petri net, and label all places and transitions. The example given above is illustrated below.



After these labels are determined, they are defined using the petri net subroutines. The arcs in the petri net are also defined in the program. There are defined with respect to the transitions. That is to say that an arc is an input to, or output from a transition. After the petri net structure has been defined, tokens may be placed in the places of the net. The tokens are as given in the previous example.



The transitions are then selectively fired in the net, by function calls in the program. This program also has calls to functions which print the petri net structure after each transition. The code is show below for the example above.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "global.h"
#include "petri.h"


int test1()
/*
* BASIC TEST NET (Peterson book, 1981, pg. 19)
*/
{
static int error;
static struct petri_net net;
static int p1, p2, p3, p4, p5;
static int t1, t2, t3, t4;

error = petri_init(&net);
p1 = petri_place(&net, "p1");
p2 = petri_place(&net, "p2");
p3 = petri_place(&net, "p3");
p4 = petri_place(&net, "p4");
p5 = petri_place(&net, "p5");

t1 = petri_transition(&net, "t1");
t2 = petri_transition(&net, "t2");
t3 = petri_transition(&net, "t3");
t4 = petri_transition(&net, "t4");

petri_input(&net, p1, t1, 1);
petri_input(&net, p2, t2, 1);
petri_input(&net, p3, t2, 1);
petri_input(&net, p4, t2, 1);
petri_input(&net, p4, t3, 1);
petri_input(&net, p4, t3, 1);
petri_input(&net, p5, t4, 1);

petri_output(&net, p2, t1, 1);
petri_output(&net, p3, t1, 1);
petri_output(&net, p4, t1, 1);
petri_output(&net, p4, t1, 1);
petri_output(&net, p2, t2, 1);
petri_output(&net, p5, t3, 1);
petri_output(&net, p3, t4, 1);
petri_output(&net, p4, t4, 1);

petri_add_tokens(&net, p1, 1);
petri_add_tokens(&net, p4, 2);
petri_add_tokens(&net, p5, 1);

petri_print(&net);

petri_event(&net, t4);
petri_print(&net);

petri_event(&net, t1);
petri_print(&net);

petri_event(&net, t3);
petri_print(&net);

return error;
}

As can be seen this method of implementation is very simple. The user is able to define a number of nets, and refer to transitions and places by name.

29.4.2 Transitions With Inhibiting Inputs

In some cases we want to prevent a transition from firing. To do this, the idea of inhibiting inputs has been proposed. If a transition has an inhibiting input from a place, that has any tokens in it, then the transition cannot fire. Otherwise the transition may fire normally. A sample net has been devised for this case, it is seen below.



The program below shows that the inhibiting input is simply defined when the arc is defined.

int test2()
/*
* INHIBITED TEST NET (Peterson book, 1981, pg. 196)
*/
{
static int error;
static struct petri_net net;
static int p1, p2, p3, p4, p5, p6;
static int t1, t2, t3, t4;

error = petri_init(&net);
p1 = petri_place(&net, "p1");
p2 = petri_place(&net, "p2");
p3 = petri_place(&net, "p3");
p4 = petri_place(&net, "p4");
p5 = petri_place(&net, "p5");
p6 = petri_place(&net, "p6");

t1 = petri_transition(&net, "t1");
t2 = petri_transition(&net, "t2");
t3 = petri_transition(&net, "t3");
t4 = petri_transition(&net, "t4");

petri_input(&net, p1, t1, 1);
petri_input(&net, p2, t2, 1);
petri_input(&net, p3, t2, 1);
petri_input(&net, p5, t3, 1);
petri_input(&net, p3, t4, INHIBIT);
petri_input(&net, p4, t4, 1);
petri_input(&net, p6, t4, 1);

petri_output(&net, p1, t1, 1);
petri_output(&net, p3, t1, 1);
petri_output(&net, p2, t2, 1);
petri_output(&net, p4, t3, 1);
petri_output(&net, p5, t3, 1);
petri_output(&net, p6, t4, 1);

petri_add_tokens(&net, p1, 1);
petri_add_tokens(&net, p2, 1);
petri_add_tokens(&net, p5, 1);
petri_add_tokens(&net, p6, 1);

petri_print(&net);

petri_event(&net, t1);
petri_print(&net);
petri_event(&net, t3);
petri_print(&net);
petri_event(&net, t4);
petri_print(&net);
petri_event(&net, t2);
petri_print(&net);
petri_event(&net, t4);
petri_print(&net);

return error;
}

29.4.3 An Exclusive OR Transition:

The inhibitory inputs are complimentary to the exclusive or function. Thus another research proposed an Exclusive or transition which will fire when one (and only one) input is from a place with tokens. An example of a problem using this, a ring shift register was modelled. This net is modelled as shown below.



In this example the EOR transition is marked with a plus in a circle (at `t7'). When run, a token will appear in p1, p3, and p5 in a repeating cycle. The program to set this up is seen below.

int test3()
/*
* EOR TEST NET (Peterson book, 1981, discussed pg. 190)
* This is for a single bit shifter
*/
{
static int error;
static struct petri_net net;
static int p1, p2, p3, p4, p5, p6, p7, p8, p9, p10;
static int t1, t2, t3, t4, t5, t6, t7;

error = petri_init(&net);
p1 = petri_place(&net, "p1");
p2 = petri_place(&net, "p2");
p3 = petri_place(&net, "p3");
p4 = petri_place(&net, "p4");
p5 = petri_place(&net, "p5");
p6 = petri_place(&net, "p6");
p7 = petri_place(&net, "p7");
p8 = petri_place(&net, "p8");
p9 = petri_place(&net, "p9");
p10 = petri_place(&net, "p10");

t1 = petri_transition(&net, "t1");
t2 = petri_transition(&net, "t2");
t3 = petri_transition(&net, "t3");
t4 = petri_transition(&net, "t4");
t5 = petri_transition(&net, "t5");
t6 = petri_transition(&net, "t6");
t7 = petri_transition(&net, "t7");

petri_input(&net, p6, t1, 1);
petri_input(&net, p7, t1, 1);
petri_input(&net, p2, t2, 1);
petri_input(&net, p7, t2, 1);
petri_input(&net, p4, t3, 1);
petri_input(&net, p7, t3, 1);
petri_input(&net, p1, t4, 1);
petri_input(&net, p3, t5, 1);
petri_input(&net, p5, t6, 1);
petri_input(&net, p8, t7, 1);
petri_input(&net, p9, t7, 1);
petri_input(&net, p10, t7, 1);

petri_output(&net, p1, t1, 1);
petri_output(&net, p3, t2, 1);
petri_output(&net, p5, t3, 1);
petri_output(&net, p2, t4, 1);
petri_output(&net, p8, t4, 1);
petri_output(&net, p4, t5, 1);
petri_output(&net, p9, t5, 1);
petri_output(&net, p6, t6, 1);
petri_output(&net, p10, t6, 1);
petri_output(&net, p7, t7, 1);

petri_type_transition(&net, t7, EOR);

petri_add_tokens(&net, p1, 1);

petri_print(&net);

petri_event(&net, t4);
petri_print(&net);
petri_event(&net, t7);
petri_print(&net);
petri_event(&net, t2);
petri_print(&net);
petri_event(&net, t5);
petri_print(&net);
petri_event(&net, t7);
petri_print(&net);
petri_event(&net, t3);
petri_print(&net);
petri_event(&net, t6);
petri_print(&net);
petri_event(&net, t7);
petri_print(&net);

return error;
}

29.4.4 Colored Tokens

This section should be considered incorrect. The theory has not been found, although the approach should adhere to the concept. The concept is that each token may now have a color, and a second bit of private information. If a transition is specified to be colored, it will only fire if tokens of the specified color are available at the inputs. The subroutines will then require that the user supply a new set of instance information so that new tokens may be issued.

The net used has tokens of mixed colors in it, an is seen below.



The code is shown below. The reader should note that a second subroutine is used. This is done because there is a bit of code which would be repeated for each update of tokens at the transition.

int test4()
/*
* COLOR TEST NET (Assumed for now)
* Two consumers of different colors and one input. The instances of tokens
* are kept track of.
*/
{
static int error, i;
static struct petri_net net;
static int p1, p2, p3;
static int t1, t2;
static int color1 = 1, color2 = 2;
static int instance[20], instance_pnt;

error = petri_init(&net);
p1 = petri_place(&net, "p1");
p2 = petri_place(&net, "p2");
p3 = petri_place(&net, "p3");

t1 = petri_transition(&net, "t1");
t2 = petri_transition(&net, "t2");

petri_input(&net, p1, t1, 1);
petri_input(&net, p3, t1, 1);
petri_input(&net, p2, t2, 1);
petri_input(&net, p3, t2, 1);

petri_output(&net, p1, t1, 1);
petri_output(&net, p2, t2, 1);

petri_type_transition(&net, t1, COLORED);
petri_type_transition(&net, t2, COLORED);

for(i = 0; i < 20; i++) instance[i] = i;
instance_pnt = 0;

petri_add_color_token(&net, p1, color1, instance[instance_pnt]);
instance_pnt++;
petri_add_color_token(&net, p2, color2, instance[instance_pnt]);
instance_pnt++;
petri_add_color_token(&net, p3, color1, instance[instance_pnt]);
instance_pnt++;
petri_add_color_token(&net, p3, color2, instance[instance_pnt]);
instance_pnt++;

petri_print(&net);
sub4(&net, t2, color1, instance, &instance_pnt);
petri_print(&net);
sub4(&net, t1, color1, instance, &instance_pnt);
petri_print(&net);
sub4(&net, t1, color1, instance, &instance_pnt);
petri_print(&net);
sub4(&net, t2, color2, instance, &instance_pnt);

petri_print(&net);

return error;
}

int sub4(net, transition, color, instance, instance_pnt)
struct petri_net *net;
int transition, color, *instance, *instance_pnt;
{
static int error, i, list[20], n, outputs;

error = ERROR;
if(petri_in_event(net, transition, color) == NO_ERROR){
if(petri_get_consumed(net, transition, &color, list, &n, &outputs) == NO_ERROR){
for(i = 0; i <= n; i++) instance[list[i]] = -1000;
if(petri_set_produced(net, transition, &(instance[*instance_pnt]),outputs) == NO_ERROR){
*instance_pnt += outputs;
error = petri_out_event(net, transition);
}
}
}

return error;
}

29.4.5 RELATIONAL NETS

Relational nets will use various firing rules for each transition. This is by far the most useful for varied manufacturing conditions. An example is seen below.



This may be seen in the fifth test subroutine in the program.

TOC PREV NEXT

Search for More:

Custom Search