1. 程式人生 > >Petri網可覆蓋性樹的構造演算法

Petri網可覆蓋性樹的構造演算法

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
typedef struct Node {
	int m[300] = { 0 };//標識
	int flag = 0;//新0,舊1,端點2
	int isfirable[300] = { 0 };//儲存可以發生的變遷名字
	struct Node *parent;//該節點的父節點
	int t = 0;//儲存生成這個節點所發生的變遷名字
};
int main() {
	int m = 4;//庫所個數
	int n = 4;//變遷個數
	int A[4][4] = { {1,-1,0,0},{-1,1,1,0},{1,0,-1,-1},{0,-1,-1,1} };//關聯矩陣
	int A1[4][4] = { {1,0,0,0},{0,1,1,0},{1,0,0,0},{0,0,0,1} };//輸出矩陣
	int A2[4][4] = { {0,1,0,0},{1,0,0,0},{0,0,1,1},{0,1,1,0} };//輸入矩陣
	int M0[4] = { 1,0,0,0 };//初始標識
	/*另一個例子
	int m = 3;
	int n = 4;
	int A[4][3] = { {-1,1,0},{1,-1,0},{0,1,-1},{0,-1,1} };
	int A1[4][3] = { {0,1,0},{1,0,0},{0,1,0},{0,0,1} };
	int A2[4][3] = { {1,0,0},{0,1,0},{0,0,1},{0,1,0} };
	int M0[4] = { 0,1,0,0 };
	*/
	int k = 0;//當前可達樹中節點數目
	Node Tree[500];//可達樹中所有節點
	//頭結點
	Node *head = new Node;
	head->parent = NULL;
	//M0是根節點
	for (int i = 0; i < m; i++) {
		Tree[k].m[i] = M0[i];//把初始標識M0賦值給Tree[0]
	}
	Tree[k].parent = head;
	Tree[k].flag = 0;
	k++;
	int newNode;
	int exist;
	int test = 0;
	while (1) {
		//判斷存在標識為新的節點newNode,即flag為0的節點
		exist = 0;
		newNode = 0;
		for (int i = 0; i < k; i++) {
			if (Tree[i].flag == 0) {//找到標識為新的節點
				exist = 1;
				newNode = i;
				break;
			}
		}
		if (exist == 0) {//不存在標識為新的節點
			break;
		}
		//任選標識為新的節點newNode,設為M
		int M[5] = { 0 };
		int M1[5] = { 0 };
		for (int i = 0; i < m; i++) {
			M[i] = Tree[newNode].m[i];//將標識為新的節點設為M
		}
		//if從M0到M的有向路上出現過M
		Node *q = Tree[newNode].parent;
		int repeated = 1;
		while (q) {
			for (int i = 0; i < m; i++) {
				repeated = 1;//新加的
				if ( M[i]!= q->m[i]) {
					repeated = 0;
					break;
				}
			}
			if (repeated == 1) {
				break;
			}
			q = q->parent;
		}
		if (repeated == 1) {//路徑上有一個節點的標識為M
			Tree[newNode].flag = 1;//then M的標識改為舊,返回step1
			continue;
		}
		//if 在M下所有變遷都不能發生
		int enable;
		int enableNum=0 ;
		for (int i = 0; i < n; i++) {//對於所有的變遷
			enable = -1;
			for (int j = 0; j < m; j++) {
				if (M[j] <A2[i][j]) {//變遷ti不能發生
					enable = 0;
					break;
				}
			}
			//變遷從t0開始編號
			if (enable == -1) {//變遷ti可以發生
				Tree[newNode].isfirable[enableNum] = i;
				enableNum++;
			}
		}
		//標記M為端點
		if (enableNum == 0) {
			Tree[newNode].flag = 2;
			continue;
		}
		//對於在M下每個可發生的變遷
		for (int i = 0; i < enableNum; i++) {
			//可發生變遷ti的編號i為hang
			//計算M1
			for (int j = 0; j < m; j++) {
				if (M[j] == 'w')
					M1[j] = M[j];
				else {
					int hang = Tree[newNode].isfirable[i];
					M1[j] = M[j] + A[hang][j];
				}	
			}
			//路徑上是否存在M2,使得M2<M1
			Node *pp = Tree[newNode].parent;
			int flagW;//標識是否存在無界量
			
			while (pp&&pp!=head) {
				flagW = 0;
				for (int ii = 0; ii < m; ii++) {
					if (pp->m[ii] > M1[ii]) {
						flagW = 1;
						break;
					}
				}
				if (flagW == 0) {
					for (int ii = 0; ii < m; ii++) {
						if (pp->m[ii] < M1[ii]) {
							M1[ii] = 'w';//標識無界量w
						}
					}
				}
				pp = pp->parent;
			}
			//引入新節點M1
			for (int z = 0; z < m; z++) {
				Tree[k].m[z] = M1[z];
			}
			Tree[k].flag = 0;//新節點M1標記為新
			Tree[k].parent = &Tree[newNode];//新節點的父節點
			Tree[k].t = Tree[newNode].isfirable[i];//通過發生哪個變遷得到的Tree[k]
			Tree[newNode].flag = 1;//擦去節點的新標註
			k++;//可達樹中節點個數加一
		}
	}
	cout << k<< endl;
	system("pause");
	return 0;
}