Petri网可达分析算法

来源:互联网 发布:mac导入铃声 编辑:程序博客网 时间:2024/06/06 02:22

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)>>1using 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月完成 现在只是存一下(主要比较好找)

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 狗在屋里有味道怎么办 养狗家里有异味怎么办 养狗房子有味道怎么办 狗身上有腥臭味怎么办 狗狗不想养了怎么办 药流2天后没出血怎么办 药流当天血多怎么办 怀孕四十天不想要怎么办 人流后出血量大怎么办 药流一直不出血怎么办 药流一直不见红怎么办 药流12天还流血怎么办? 把别人车刮了怎么办 车划掉漆了怎么办啊 倒车时碰了车怎么办 车头掉了一点漆怎么办 新买的车被刮了怎么办 白色车车头漆掉了一小块怎么办 临时牌照丢了1张怎么办 临牌遗失了一张怎么办 临牌只有一张了怎么办 临时牌丢了一个怎么办 药流出血特别多怎么办 新车刮擦了一点怎么办 自己的车撞墙了怎么办 新车被撞了个坑怎么办 车门被刮变形了怎么办 撞到别人的新车怎么办 新车掉了一点漆怎么办 新车擦了点漆怎么办 车挂了一点漆怎么办 第一天上班中途想走了怎么办 车子前脸裂开了怎么办 不想干了想辞职怎么办 药流期间老是吐怎么办 在工厂上班辞工后没发工资怎么办 培训期三天想走怎么办 药流吃了药吐了怎么办 工作3天不下去怎么办 在新公司融不进去怎么办 药流吃药吐了怎么办