C++ 实现Petri网转换规则
2017-10-20 本文已影响14人
顽强的猫尾草
模拟场景:
编写一个程序来模拟一个Petri网的行为。该程序应该读入一组转换规则,以及一组状态列表,这些状态对应于网络链路层发出一个新的分组或者接受一个新的分组。初始状态也是要读入的。该程序应该从初始状态开始,随机地选取那些激活的转换,并激发这些转换,检查一下看是否有“一台主机接受了2个分组而另一台主机并没有在此期间发出新的分组”这样的情形。
关于Petri网...
Petri网由库所(Place)和变迁(Transition)组成,库所用圆圈“○”表示,变迁用矩形“□”表示。变迁和库所之间可以用有向弧连接,共有两种类型的弧:从库所到变迁;从变迁到库所,从库所到库所、或从变迁到变迁的弧是不允许的。库所可以容纳标记(Token,托肯),用黑点表示。Petri网结构是固定的,而库所中的标记是分布可变的。Petri网的状态用库所中标记的分布来描述。变迁只有满足可实施条件才能实施,也就是说,每个输入库所都至少要有一个标记,变迁才能够被“Fire”(点火、装弹),实施就绪。变迁实施时,消耗掉来自输入库所的标记,并为输出库所产生标记。
变迁是PetriNet中的主动元素。通过实施变迁,过程从一个状态变到另一个状态。因此,变迁经常表示事件、操作、转换或传输。库所是Petri网中的被动元素,它们不能改变网的状态,库所通常表示媒介、缓冲器、地理位置、状态、阶段或条件。标记通常表示对象,这些对象可能是具体的事物,也可能是抽象的信息。
简单代码实现:
#include<iostream>
#include "string.h"
#include "stdlib.h"
#include "time.h"
#define maxnum 100 //最大变迁规则数目
#define maxlength 15 //变迁规则单侧最大长度
using namespace std;
struct TransRules //存放变迁规则
{
char left[maxlength];
char right[maxlength];
}Rules[maxnum];
char state_issue[maxnum];
char state_accept[maxnum];
int TransRules_input() //变迁规则的输入,返回规则数目
{
cout << "请输入转换规则(以#结束,以/代表空): " << endl;
int i = 0;
do
{
i++;
cin >> Rules[i].left;
if(Rules[i].left[0]=='#') //#表示输入结束
break;
cout << " ==> ";
cin >> Rules[i].right; //把变迁规则输入存放到Rules[1]开始的数组中
}while(strcmp(Rules[i].left,"#")!=0);
return i-1;
}
int main()
{
int enable[maxnum]; //就绪的变迁序号
int trans_num; //变迁次数
int randtrans;
char init_state[maxlength]; //初始状态
int rule_num = TransRules_input(); //变迁规则数目
cout << "请输入初始状态: ";
cin >> init_state;
cout << "请输入要转换的次数: ";
cin >> trans_num;
cout << endl;
int transflag = 0; //变迁是否能继续的标志
srand((unsigned) time(NULL));
for(int x=0;(x<trans_num)&&(!transflag);x++)
{
int flag = 0;
int m = 0;
int i, j;
for(i=1;i<=rule_num;i++) //搜索就绪的变迁
{
for(j=0;(j<(int)strlen(Rules[i].left))&&(flag==0);)
//flag==1表示规则左部已经有状态不属于初始态了,下一个状态不能就绪
{
int k = 0;
while((Rules[i].left[j]!=init_state[k])&&(k<(int)strlen(init_state)))
k++;
if(k<(int)strlen(init_state)) //在init_state中找到相同的状态
j++;
else
{
flag = 1;
j++;
}
}
if((j==(int)strlen(Rules[i].left))&&(!flag))
//规则的左部全部属于初始状态,故可以就绪
{
enable[m] = i; //把就绪的序号存入enable数组
m++;
}
flag = 0;
}
int enable_num = m; //就绪的变迁数
if(enable_num==0)
{
transflag = 1; //表明变迁不能继续进行
cout << "变迁无法继续进行!" << endl;
}
else
{
int n = rand();
randtrans = n % enable_num;
int flag1 = 0;
int w = 0;
char temp[maxlength];
for(int y=0;y<(int)strlen(init_state);y++) //把原状态替换为变迁后的状态
{
for(int z=0;(z<(int)strlen(Rules[enable[randtrans]].left))&&(!flag1);z++)
{
if(init_state[y]==Rules[enable[randtrans]].left[z]) //保留未变迁的状态
{
flag1 = 1;
}
}
if(flag1==0)
{
temp[w] = init_state[y];
w++;
}
flag1 = 0;
}
int flag2 = 0;
for(i=0;i<(int)strlen(Rules[enable[randtrans]].right);i++)
{
for(j=0;(j<w)&&(!flag2);j++)
{
if(Rules[enable[randtrans]].right[i]==temp[j])
flag2 = 1;
}
if((!flag2)&&(Rules[enable[randtrans]].right[i]!='/'))
//变迁后的状态未在剩余状态中出现过且不为空
{
temp[w] = Rules[enable[randtrans]].right[i];
w++;
}
}
temp[w] = '\0';
strcpy(init_state,""); //清除原来的初始状态
strcpy(init_state,temp);
cout << "第" << x+1 << "次转换后的状态:" << init_state << endl;
}
}
system("pause");
}
题目来源:《计算机网络(第3版)》第三章课后习题No.39