Petri網可達分析算法

Petri網導論這本教材第三章的算法

C++實現

輸入 爲 庫所和變遷個數 以及關聯矩陣

4 4
1 -1 0 0
-1 1 1 0
1 0 -1 -1
0 -1 -1 1
1 0 0 0
3 4
-1 1 0
1 -1 0
0 1 -1
0 -1 1
0 1 0

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>

using namespace std;

#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007

#define mp make_pair
#define fi first
#define se second

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m=(l+r)>>1

using namespace std;

const int nmax = 1000 + 10;
const int tmax = 100 + 10;
const int pmax = 100 + 10;

int np, nt;//輸入庫所和變遷個數
int A[tmax][pmax];//輸入關聯矩陣
int A1[tmax][pmax], A2[tmax][pmax];//輸出矩陣A+ 和輸入矩陣A-
int M0[pmax];//輸入初始標識
int M[pmax], M1[pmax];//當前標識

struct Node {//CT節點
    int m[pmax];//標識向量
    struct Node* parent;//指向父節點的指針
    int t;//變遷編號 1,2……,nt(對應下標+1)
    int flag;//標記 0爲新,1爲舊,-1爲端點

    Node() {
        memset(m, 0 ,sizeof(m));
        parent = NULL;
        t = 0;
        flag = 0;
    };
} Tr[nmax];

bool repeat(int i) {//true爲M是重複節點
    for(int j = 0; j < np; ++j) {
        if(M[j] != Tr[i].m[j]) return false;
    }
    return true;//M(j) == m[j] j=1,2,...,np
}

bool check(int i) {// true爲ti可發生
    for(int j = 0; j < np; ++j) {
        if(M[j] < A2[i][j]) return false;
    }
    return true;//M[ti> 充要條件:M(j)>=aij j=1,2,...,np
}

int main() {
    freopen("input.txt",  "r", stdin);
    freopen("output.txt", "w", stdout);
    int cases = 0;

    /* 輸入庫所個數np和變遷個數nt,0 0結束輸入 */
    while(~scanf("%d %d", &np, &nt) && (np != 0 || nt != 0)) {

        printf("Case %d:\n", ++cases);
        int CR = 0;//1爲可覆蓋樹,0爲可達樹
        int k = 0;//記錄CT中節點的個數

        /* 清理上一組數據 */
        memset(Tr, 0, sizeof(Tr));
        memset(A,  0, sizeof(A));
        memset(A1, 0, sizeof(A1));
        memset(A2, 0, sizeof(A2));
        memset(M0, 0, sizeof(M0));
        memset(M,  0, sizeof(M));
        memset(M1, 0, sizeof(M1));

        /* 輸入關聯矩陣A和初始標識M0 */
        for(int i = 0; i < nt; ++i) {
            for(int j = 0; j < np; ++j) {
                scanf("%d", &A[i][j]);
                if(A[i][j] == 1)  A1[i][j] =  A[i][j];
                if(A[i][j] == -1) A2[i][j] = -A[i][j];
            }
        }//關聯矩陣

        /* step0 以初始標識爲CT的根節點,並標爲新=0 */
        Node *head;//空的頭節點
        head = (Node*)malloc(sizeof(struct Node));
        head->parent = NULL;
        Tr[k].parent = head;//根節點(初始標識)M0=Tr[0] 指向空的頭節點head
        for(int i = 0; i < np; ++i) {
            scanf("%d", &M0[i]);
            Tr[k].m[i] = M0[i];//Tr[0]爲CT根節點
        }//初始標識
        k++;//目前只有一個根節點k=1

        /* step1 是否存在新=0的節點,任選一個新的節點爲當前節點=M */
        while(1) {
            int nnew = -1;//當前節點(標識)的下標
            for(int i = 0; i < k; ++i) {
                if(Tr[i].flag == 0) {
                    nnew = i;//有新節點,下標爲i
                    break;
                }
            }if(nnew == -1) {//判斷沒有新的節點,結束while
                break;
            }//step1 結束,否則繼續

            /* 將任意一個新節點設置爲當前節點=M */
            for(int i = 0; i < np; ++i) {
                M[i] = Tr[nnew].m[i];
            }

            /* step2 根節點=head 到 當前節點=M 的路徑上 如果有重複標爲舊flag=1 */
            int rep = 0;
            Node *q = Tr[nnew].parent;//q指向當前節點M的父節點
            while(q->parent != NULL) {
                int f = 0;
                for(int j = 0; j < np; ++j) {
                    if(M[j] != q->m[j]) f = 1;
                }if(f == 0) {//M是重複節點
                    Tr[nnew].flag = 1;//標爲舊=1
                    rep = 1;
                    break;
                }
                q = q->parent;
            }if(rep == 1) {
                continue;//返回while,step1
            }//step2 結束,不標爲舊則繼續

            /* step3 當前節點=M 如果所有的變遷都是死的標爲端點=-1 */
            int dead = -1;
            for(int i = 0; i < nt; ++i) {
                if(check(i)) {//存在可發生的變遷ti
                    dead = i;
                    break;
                }
            }if(dead == -1) {
                Tr[nnew].flag = -1;//所有的變遷都不可發生,標爲端點=-1
                continue;//返回while,step1
            }//step3 結束,不標爲端點則繼續

            /* step4 對每個可發生的t */
            for(int i = 0; i < nt; ++i) {//遍歷每一個變遷t
                if(check(i)){//ti可發生
                    for(int j = 0; j < np; ++j) {
                        /* 計算M1 */
                        if(M[j] == 'w') M1[j] = M[j];
                        else M1[j] = M[j] + A[i][j];
                        Tr[k].m[j] = M1[j];
                    }

                    /* 插入w分量 */
                    Node *p = &Tr[nnew];//p指向當前節點M
                    while(p->parent != NULL) {
                        int f = 0;
                        for(int j = 0; j < np; ++j) {
                            if(p->m[j] > M1[j]) {
                                f = -1;//不滿足條件
                                break;
                            }
                        }if(f == 0) {
                            for(int j = 0; j < np; ++j) {
                                if(p->m[j] < M1[j]) {
                                    Tr[k].m[j] = 'w';
                                    CR = 1;//存在w分量
                                }
                            }
                        }
                        p = p->parent;
                    }//判斷是否有無窮w

                    /* 插入新節點 */
                    Tr[k].parent = &Tr[nnew];//有向弧
                    Tr[k].t = i + 1;//有向弧旁標
                    Tr[nnew].flag = 2;//抹去標註
                    k++;//節點個數增加
                }
            }//step4 結束,創建了新節點,繼續找標爲新=1的節點
        }//無標爲新的節點,while結束
        /* step1 結束,算法結束 */

        /* 輸出得到可覆蓋樹CT或者可達樹RT */
        if(CR == 0) printf("The tree is reachability tree ");
        else        printf("The tree is coverability tree ");
        printf("of %d nodes.\n", k);
        for(int i = 0; i < k; ++i) {
            for(int j = 0; j < np; ++j) {
                if(j == 0) printf("M%d = [", i);
                if(Tr[i].m[j] != 'w') printf("%d", Tr[i].m[j]);
                else printf("%c", Tr[i].m[j]);
                if(j != np - 1) printf(",");
                else printf("]");
            }

            if(Tr[i].t != 0) printf(" t%d", Tr[i].t);

            if(Tr[i].parent != head) {
                for(int j = 0; j < np; ++j) {
                    if(j == 0) printf(" parent = [");
                    if(Tr[i].parent->m[j] != 'w') printf("%d", Tr[i].parent->m[j]);
                    else printf("%c", Tr[i].parent->m[j]);
                    if(j != np - 1) printf(",");
                    else printf("]");
                }
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

16年12月完成 現在只是存一下(主要比較好找)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章