离散事件动态系统 #Petri网作业 #可达图 #赋时Petri

离散事件动态系统作业 #Petri网 #可达图 #赋时Petri

本文章由作者独立创作,为研究生某课程作业,仅供参考

先吐槽一点:CSDN竟然无法使用svg矢量图

1. 图的类型

1.1 有向图是一个二元组

G = ( V , E ) {   V : 结点或定点的集合   E : 有向弧或者有向边的集合 G=(V,E)\\ \begin{cases} \ V:结点或定点的集合\\ \ E:有向弧或者有向边的集合\\ \end{cases} G=(V,E){ V:结点或定点的集合 E:有向弧或者有向边的集合

E = {   ( V 2 , V 1 ) , ( V 2 , V 3 ) , ( V 4 , V 1 ) , ( V 4 , V 3 )   } E=\{\:(V2,V1),(V2,V3),(V4,V1),(V4,V3)\:\} E={(V2,V1),(V2,V3),(V4,V1),(V4,V3)}

1.2 二分图是一个三元组

G = ( V ˉ , V ^ , E ) V = V ˉ ∪ V ^ ∀   ( x , y ) ∈ E ,   ( x ∈ V ˉ   ∩   y ∈ V ^ )   ∪   ( x ∈ V ^   ∩   y ∈ V ˉ ) G=(\bar{V},\hat{V},E)\\ V=\bar{V}\cup\hat{V}\\ \forall\:(x,y)\in E,\:(x\in\bar{V}\ \cap\ y\in\hat{V})\,\cup\,(x\in\hat{V}\ \cap\ y\in\bar{V})\\ G=(Vˉ,V^,E)V=VˉV^(x,y)E,(xVˉ  yV^)(xV^  yVˉ)

1.3 加权图是一个三元组

G = ( V , E , W ) W :   E → R \begin{aligned} &G=(V,E,W)\\ &W:\ E\rightarrow R \end{aligned} G=(V,E,W)W: ER

2. Petri网

P e t r i Petri Petri网是德国当代数学家 C . A . P e t r i C.A.Petri C.A.Petri 定义的一种通用的数学模型,用以描述存在于条件与事件间的关系。这一工作进行于1960~1962年间。此后各国学者,例如美国 M I T MIT MIT(麻省理工学院)及欧洲的众多大学,对网作了大量的研究。1980年以来,“ P e t r i Petri Petri网理论及应用欧洲研讨会”每年召开一次年会,交流新的研究成果。法国的科研人员为此做出了贡献。早在1972~1973年,已利用 P e t r i Petri Petri网模型来描述逻辑控制器,它对 G r a f c e t Grafcet Grafcet的建立产生了影响。

P e t r i Petri Petri网的模型是丰富的,既有严格的数学表达式,又有形象生动的图形化结构,能够描述离散事件动态系统中的顺序、选择、互斥、并发等事件关系,能对具有并行( p a r a l l e l i s m parallelism parallelism)、并发( c o n c u r r e n c y concurrency concurrency)、同步( s y n c h r o n i z a t i o n synchronization synchronization)、资源分享( r e s o u r c e s h a r i n g resource sharing resourcesharing)等特性建立模型并使之形象化。 P e t r i Petri Petri网在离散事件动态系统的建模、分析、仿真、形式化验证、故障诊断和调度控制等方面都有广泛的应用。

2.1 Petri网的表示

P e t r i Petri Petri网是一个四元组,有向二分加权图
N = ( P , T , F , W ) {   P : 库所集合,圆圈   T : 变迁集合,矩形 ( 方框 )   F : 有向弧集合   W : F → Z ( 权值 ) N=(P,T,F,W)\\ \begin{cases} \ P:库所集合,圆圈\\ \ T:变迁集合,矩形(方框)\\ \ F:有向弧集合\\ \ W:F\rightarrow Z(权值)\\ \end{cases} N=(P,T,F,W)  P:库所集合,圆圈 T:变迁集合,矩形(方框) F:有向弧集合 W:FZ(权值)
​ 另外,

C − = P × T C^-=P \times T C=P×T表示 ∣ P ∣ × ∣ T ∣ |P|\times |T| P×T维的前置关联矩阵;

C + = T × P C^+=T \times P C+=T×P表示 ∣ T ∣ × ∣ P ∣ |T|\times |P| T×P维的后置关联矩阵;

m 0 = [ 0 , 1 , . . . ] m_0=[0,1,...] m0=[0,1,...]表示初始标识的集合,每个库所中的标识皆称作 t o k e n token token t o k e n token token用圆点表示,该集合中 t o k e n token token的总数量为非负整数;

C C C表示关联矩阵,其是由前后置关联矩阵计算得到的, C = C − − C + C=C^--C^+ C=CC+

2.2 使能变迁

​ 如果一个变迁的每个输入库所的 t o k e n token token数不小于该库所到它弧上的权值,那么变迁是使能的。


m ≥ C − ( :    , t ) m\geq C^- (:\;,t) mC(:,t)

2.3 氢氧生水Petri网实例

​ 下面以一个氢氧生水的例子来简单描述 P e t r i Petri Petri
在这里插入图片描述

​ 前置关联矩阵 C − C^- C,表示每个变迁 ( t 1 , t 2 ) (t_1,t_2) (t1,t2)输入的变化, C − = [   2 0   1 0   0 2   ] C^-=\left[ \begin{matrix} \:2&0\\\:1&0\\\:0&2\end{matrix}\:\right] C= 210002

​ 后置关联矩阵 C + C^+ C+,表示每个变迁 ( t 1 , t 2 ) (t_1,t_2) (t1,t2)输出的变化, C + = [   0 2   0 1   2 0   ] C^+=\left[ \begin{matrix} \:0&2\\\:0&1\\\:2&0\end{matrix}\:\right] C+= 002210

​ 关联矩阵 C = C + − C − = [   − 2 2   − 1 1   2 − 2   ] C = C^+-C^- =\left[ \begin{matrix} \:-2&2\\\:-1&1\\\:2&-2\end{matrix}\:\right] C=C+C= 212212

m 0 m_0 m0为初始状态,即初始每个库所中的 t o k r n tokrn tokrn数, m 0 = [   3   1   2   ] m_0=\left[ \begin{matrix} \:3\\\:1\\\:2\end{matrix}\:\right] m0= 312

Petri网的激发有如下基本规则:

r u l e 1 rule1 rule1:只有使能的变迁才可以激发;

r u l e 2 rule2 rule2:变迁的激发耗时为0;

r u l e 3 rule3 rule3:如果一个变迁激发,会从它的每个输入库所取走弧上权值个 t o k e n token token,并给它的输出库所放入弧上权值个 t o k e n token token
m k + 1 = m k + C ( :    , t ) = m k + C ⋅ e → k + 1 m_{k+1} = m_k + C(:\;,t) = m_k + C \cdot \overrightarrow{e}_{k+1} mk+1=mk+C(:,t)=mk+Ce k+1
​ 在氢氧生水的例子中,激发第一次变迁,可以得到
m 1 = m 0 + C ⋅ e → 1 = [   3   1   2   ] + [   − 2 2   − 1 1   2 − 2   ] ⋅ [   1   0   ] = [   3   1   2   ] + [   − 2   − 1   2   ] = [   1   0   4   ] \begin{aligned} m_1 &= m_0 + C \cdot \overrightarrow{e}_1 \\ &=\left[ \begin{matrix} \:3\\\:1\\\:2\end{matrix}\:\right] + \left[ \begin{matrix} \:-2&2\\\:-1&1\\\:2&-2\end{matrix}\:\right] \cdot \left[ \begin{matrix} \:1\\\:0\end{matrix}\:\right]\\ &=\left[ \begin{matrix} \:3\\\:1\\\:2\end{matrix}\:\right] + \left[ \begin{matrix} \:-2\\\:-1\\\:2\end{matrix}\:\right] = \left[ \begin{matrix} \:1\\\:0\\\:4\end{matrix}\:\right]\\ \end{aligned} m1=m0+Ce 1= 312 + 212212 [10]= 312 + 212 = 104

2.4 典型的Petri网实例

2.4.1 典型Petri网结构图

在这里插入图片描述

2.4.2 典型Petri网matlab代码实现
%% petri_fun.m
function m=petri_fun(k)
    m0 = [3;1;2;1;2;2;1];
    m = m0;
    if k>0
        C_minus = [2 0 0 0 0 0 0 0 0 0;
                   1 0 0 0 0 0 0 0 0 0;
                   0 2 0 0 0 0 0 0 0 0;
                   0 0 1 0 1 0 0 0 0 0;
                   0 0 0 2 0 1 0 0 0 0;
                   0 0 0 0 0 0 2 0 1 0;
                   0 0 0 0 0 0 0 1 0 1];
        C_plus =  [0 0 1 0 0 0 0 0 1 0;
                   0 0 0 1 0 0 0 0 0 1;
                   2 0 0 0 0 0 0 0 0 0;
                   0 1 0 0 0 0 1 0 0 0;
                   0 1 0 0 0 0 0 1 0 0;
                   0 0 0 0 1 0 0 0 0 0;
                   0 0 0 0 0 2 0 0 0 0];
        C = C_plus - C_minus;
        E = eye(10);
        for i=1:k
            e = E(:,i);
            if all(m0 + C_minus*e >=0)
                m = m0 + C*e;
                m0 = m;
            else
                fprintf("当前变迁无法激活,m = \n");
            end
        end
    elseif k==0
        fprintf("初始状态 m0 = \n");
    else
        fprintf("未发生变迁,m = \n");
    end
end

%% run.m
display(petri_fun(0));
for i=1:10
    fprintf("第%d次变迁,状态 m%d = \n",i,i);
    disp(petri_fun(i));
end
2.4.3 执行结果

在这里插入图片描述

在这里插入图片描述

3. Petri网可达图

3.1 Petri网可达图算法

​ 输入:后置关联矩阵 C + C^+ C+,前置关联矩阵 C − C^- C,初始标识 m 0 m_0 m0

​ 输出:可达图 G r = ( V , E , W ) G_r = (V,E,W) Gr=(V,E,W),加权有向图

算法步骤:

s t e p 1 step1 step1:设 V n e w V_{new} Vnew表示新结点的集合;

s t e p 2 step2 step2:画出可达图的根结点,并将其标为 m 0 m_0 m0,即 V = V ∪ { m 0 } V=V\cup\{m_0\} V=V{m0}

s t e p 3 step3 step3:将 m 0 m_0 m0标为新结点,即 V n e w = { m 0 } V_{new}=\{m_0\} Vnew={m0}

s t e p 4 step4 step4 i f if if 已经没有待扩展的新结点 ( V n e w = ∅ ) (V_{new}=\emptyset) (Vnew=),则输出可达图 G G G,并退出算法;

e l s e else else,从 V n e w V_{new} Vnew中任意选择一个新结点 m m m,并将 m m m V n e w V_{new} Vnew中删除;

s t e p 5 step5 step5:令 T e = {   ∀ t ∈ T   ∣ m ≥ C − ( : , t )   } T_e=\{\ \forall t \in T \ |m\geq C^-(:,t)\ \} Te={ tT mC(:,t) }

s t e p 6 step6 step6:从 T e T_e Te中任意选择一个变迁 t t t,并将其从 T e T_e Te中删除;

s t e p 7 step7 step7 m ′ = m + C + ( : , t ) − C − ( : , t ) m^{'} = m + C^+(:,t) - C^-(:,t) m=m+C+(:,t)C(:,t)

s t e p 8 step8 step8 i f if if m ′ m^{'} m还没出现过 ( m ′ ∉ V ) (m^{'}\notin V) (m/V),则 V = V ∪ { m ′ } V=V\cup \{m^{'}\} V=V{m} E = E ∪ { ( m , m ′ ) } E=E\cup \{(m,m^{'})\} E=E{(m,m)} W { ( m , m ′ ) } = t W\{(m,m^{'})\}=t W{(m,m)}=t,并将 m ′ m^{'} m放入 V n e w V_{new} Vnew中;

e l s e else else E = E ∪ { ( m , m ′ ) } E=E\cup \{(m,m^{'})\} E=E{(m,m)} W { ( m , m ′ ) } = t W\{(m,m^{'})\}=t W{(m,m)}=t

s t e p 9 step9 step9 i f if if T e = ∅ T_e = \emptyset Te=,返回 s t e p 4 step4 step4

e l s e else else T e ≠ ∅ T_e \neq \emptyset Te=,返回 s t e p 6 step6 step6

3.2 可达图matlab代码实现

注:以下两个文本文档为前置后置关联矩阵,自己创一个.txt即可
C_minus.txt
2 0 1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 1 1 0
0 2 1 0 1 0 0 0 0 0
0 0 0 2 0 1 0 0 1 0
0 2 0 0 0 0 2 1 0 1

C_plus.txt
0 0 1 0 0 0 2 0 1 0
2 0 0 0 2 0 0 0 1 0
0 1 0 0 0 0 0 1 0 0
0 0 0 2 1 0 2 0 1 0
0 0 0 1 0 2 0 0 0 1

%% step1~3: Initial
clear all;
clc;
C_minus = readmatrix("C_minus.txt");
C_plus =  readmatrix("C_plus.txt");
C = C_plus - C_minus
m0 = [4;2;3;1;3];
V = {};
V = [V,m0];
E = {};
W = {};
V_new = {m0};
Te = {};
symbol = 0;
origin = {};
destination = {};
weight = {};

%% main circulate
while true
    if symbol==0
        % step4: Exit or select random node
        [exit,m,V_new] = select_node(V_new,V,E,W,origin,destination,weight); 
        if exit==1
            break;
        end
        Te = crate_Te(Te,m,C_minus);    % step5: Create Te
        if isempty(Te)
        else
            [t,Te]=select_t(Te);        % step6: Select random t from Te
            child=transition(C,m,t);    % step7: Transition
            mask=judge(child,V);        % Judge whether 'child' has ever apperaed
            % step8: Add to Collection
            [V,E,W,V_new,origin,destination,weight]=collection(C,m,child,mask, ...
    t,V,E,W,V_new,origin,destination,weight); 
            symbol = 0;
        end
    else
        [t,Te]=select_t(Te);            % step6: Select random t from Te
        child=transition(C,m,t);        % step7: Transition
        mask=judge(child,V);            % Judge whether 'child' has ever apperaed
        % step8: Add to Collection
        [V,E,W,V_new,origin,destination,weight]=collection(C,m,child,mask, ...
    t,V,E,W,V_new,origin,destination,weight); 
    end
    % step9: Return and execute the next circulate
    if isempty(Te)
        symbol = 0;
    else
        symbol = 1;
    end
end

%% step4: Exit or select random node
function [exit,m,V_new]=select_node(V_new,V,E,W,origin,destination,weight)
    if isempty(V_new)
        V = cell2mat(V);
        writematrix(V,'V.txt');
        fprintf('V=\n');
        disp(V);

        fprintf('E=\n');
        disp(E);

        W = cell2mat(W);
        writematrix(W,'W.txt');
        fprintf('W=\n');
        disp(W);

        m = [];
        exit = 1;
        G = digraph(origin,destination);
        figure(1)
        plot(G,"EdgeLabel",weight,"LineWidth",1.5,"MarkerSize",6, ...
    "ArrowSize",9,"NodeColor",'red','EdgeFontSize',9, ...
    'NodeFontSize',10)
        figure(2)
        plot(G,"EdgeLabel",weight,"LineWidth",1.5,"MarkerSize",6, ...
    "ArrowSize",9,"NodeColor",'red','EdgeFontSize',9, ...
    'NodeFontSize',10,'Layout','force3')
    else
        index = randi([1,length(V_new)]);
        m = V_new(index);
        V_new(index) =[];           % delete m from V_new
        exit = 0;
    end
end
%% step5: Create Te
function Te=crate_Te(Te,m,C_minus)
    sign = 0;
    I = eye(10);
    m = cell2mat(m);
    while true
        sign=sign+1;
        if sign>10 || length(find( m-C_minus(:,sign) <0))~=0
            break;
        else
            temp = {I(:,sign)};
            Te = [Te,temp];
        end
    end
end
%% step6: Select random t from Te
function [t,Te]=select_t(Te)
    if isempty(Te)
        return
    else
        sign = randi(length(Te));
        t = Te(sign);
        Te(sign) =[];               % delete t from Te
    end
end
%% step7: Transition
function child=transition(C,m,t)
    t = cell2mat(t);
    m = cell2mat(m);
    child = m + C*t;
end
%% Judge whether 'child' has ever apperaed
function mask=judge(child,V)
    child_cell = {child};
    mask = 0;
    for i=1:length(V)
        if ~isequal(child_cell,V(1,i))
        else
            mask = i;               % appera,record
            break;
        end
    end
end
%% step8: Add to Collection
function [V,E,W,V_new,origin,destination,weight]=collection(C,m,child,mask, ...
    t,V,E,W,V_new,origin,destination,weight)
    m = cell2mat(m);
    t = cell2mat(t);
    temp = sprintf('m%d',length(V));
    origin = [origin,temp];
    if mask==0
        arc = [m,child];
        V = [V,child];
        temp = sprintf('m%d',length(V));
        destination = [destination,temp];
        E = [E,arc];
        W = [W,C*t];
        temp = sprintf('t%d',length(W));
        weight = [weight,temp];
        V_new = [V_new,child];
    else
        child = V(1,mask);
        child = cell2mat(child);
        arc = [m,child];
        temp = sprintf('m%d',mask);
        destination = [destination,temp];
        E = [E,arc];
        W = [W,C*t];
        temp = sprintf('t%d',length(W));
        weight = [weight,temp];
    end
end

3.3 Petri网可达图执行结果

​ 输出可达图如下所示:
在这里插入图片描述

​ 输出三维力导向图如下:

在这里插入图片描述

​ 窗口输出V, E, W 如下所示:

在这里插入图片描述

4. 赋时Petri网

4.1 赋时Petri网模型

​ 所谓赋时Petri网就是在普通Petri网的基础上加入了时间因素,需要引入 d k , x k , λ k d_k,x_k,\lambda_k dk,xk,λk 这几个时间变量
{   G = ( N , d , m 0 )   X k = m k , v k , g k \begin{cases} \:G=(N,d,m_0)\\ \:X_k=m_k,v_k,g_k\\ \end{cases} {G=(N,d,m0)Xk=mk,vk,gk

其中,
{   N 是一个 P t r i 网结构   d 是时延   m 0 是初始标识   m k 是经过 k 次变迁激发到达的标识   v k 是 t o k e n 在库所中已经等待的时间   g k 是 P e t r i 网到达 x k 时已经等待的时间 \begin{cases} \:N是一个Ptri网结构\\\:d是时延\\\:m_0是初始标识\\\:m_k是经过k次变迁激发到达的标识\\\:v_k是token在库所中已经等待的时间\\\:g_k是Petri网到达x_k时已经等待的时间\end{cases} N是一个Ptri网结构d是时延m0是初始标识mk是经过k次变迁激发到达的标识vktoken在库所中已经等待的时间gkPetri网到达xk时已经等待的时间
激发条件:
{   m k − C − ( : , e k ) > 0   v k ( p ) ≥ d ( p ) \begin{cases} \:m_k-C^-(:,e_k)>0\\ \:v_k(p)\geq d(p)\\ \end{cases} {mkC(:,ek)>0vk(p)d(p)
定义:

λ k \lambda_k λk表示第 k k k次和第 k + 1 k+1 k+1次变迁之间的时间间隔

定理:

​ 对于 G = ( N , d , m 0 ) G=(N,d,m_0) G=(N,d,m0),对处于第 k k k个激发时刻的状态 X k X_k Xk λ k + 1 \lambda_{k+1} λk+1表示第 k + 1 k+1 k+1个变迁还需等待的时间,那么:
{   m k ≥ C − ( : , e k + 1 )   λ = m a x (   d ( p ) − v k ( p )   )   m k + 1 = m k + C ( : , e k + 1 )   v k + 1 = v k − d i a g ( v k ) ⋅ C − ( : , e k + 1 ) + λ k + 1 ⋅ ( m k + 1 − C + ( : , e k + 1 ) )   g k + 1 = g k + λ k + 1 \begin{cases} \ m_k\geq C^-(:,e_{k+1})\\ \ \lambda = max(\ d(p)-v_k(p)\ )\\ \ m_{k+1} = m_k+C(:,e_{k+1})\\ \ v_{k+1} = v_k - diag(v_k)\cdot C^-(:,e_{k+1}) + \lambda_{k+1}\cdot (m_{k+1} - C^+(:,e_{k+1}))\\ \ g_{k+1} = g_k + \lambda_{k+1}\\ \end{cases}  mkC(:,ek+1) λ=max( d(p)vk(p) ) mk+1=mk+C(:,ek+1) vk+1=vkdiag(vk)C(:,ek+1)+λk+1(mk+1C+(:,ek+1)) gk+1=gk+λk+1

4.2 赋时Petri网可达图算法

输入: C − ,   C ,   d ,   m 0 ,   m g C^-,\ C,\ d,\ m_0,\ m_g C, C, d, m0, mg

​ **输出:**赋时 P e t r i Petri Petri网可达图

步骤如下:

​ (1)初始化 X 0 = ( m 0 , v 0 , g 0 ) X_0=(m_0,v_0,g_0) X0=(m0,v0,g0),其中 m 0 m_0 m0作为初始标识, v 0 = 0 v_0=0 v0=0 λ 0 = 0 \lambda_0=0 λ0=0 g 0 = 0 g_0=0 g0=0

​ (2)将初始状态 X 0 = ( m 0 , v 0 , g 0 ) X_0=(m_0,v_0,g_0) X0=(m0,v0,g0)作为可达树的根结点,并标记为 n e w new new

​ (3)如果 m 0 = m g m_0=m_g m0=mg,将 X 0 X_0 X0标记为 g a o l gaol gaol,算法退出,否则继续执行下一步;

​ (4)从可达树中任意选择一个 n e w new new结点,表示为 X k = ( m k , v k , g k ) X_k=(m_k,v_k,g_k) Xk=(mk,vk,gk),并将该结点标记为 o l d old old

​ (5)计算 X k X_k Xk状态下使能的变迁集合 E k = { t ∈ T   ∣   m k ≥ C − ( : , t ) } E_k=\{t\in T \ |\ m_k \geq C^-(:,t) \} Ek={tT  mkC(:,t)}

​ (6) f o r    a l l    e k ∈ E k   ,    d o for\ \ all\ \ e_k\in E_k\ ,\ \ do for  all  ekEk ,  do

​ (7) 激发 e k e_k ek,产生新状态 X k + 1 X_{k+1} Xk+1,根据公式分别计算 λ k + 1 ,   m k + 1 ,   v k + 1 和 g k + 1 \lambda_{k+1},\ m_{k+1},\ v_{k+1}和g_{k+1} λk+1, mk+1, vk+1gk+1

​ (8) 如果 X k + 1 X_{k+1} Xk+1是新状态,在可达树中添加一个表示 X k + 1 X_{k+1} Xk+1的结点;

​ (9) 画一条从 X k X_k Xk指向 X k + 1 X_{k+1} Xk+1的弧,弧上标记激发变迁 e k e_k ek

​ (10) 如果 m k + 1 = m g m_{k+1}=m_g mk+1=mg,将 X k + 1 X_{k+1} Xk+1对应的结点记为 g o a l goal goal,否则记为 n e w new new

​ (11) e n d end end

​ (12)如果可达树中存在 n e w new new结点,那么返回第4步。

4.3 赋时Petri网实例

4.3.1 设计赋时Petri网结构

​ 改进了课堂上的赋时 P e t r i Petri Petri网例子,如下图所示

在这里插入图片描述

​ 为使 P 2 P2 P2不会一直积累, c o n s t r a i n t constraint constraint:
P 2 ≤ 1 P_2\leq1 P21
i n t r o d u c e   C ,   s o   h a v e introduce\ C ,\ so\ have introduce C, so have
P 2 + C = 1 w h i c h 0 ∗ P 0 + 0 ∗ P 1 + 1 ∗ P 2 + 0 ∗ P 3 + 0 ∗ P 4 + 0 ∗ P 5 + 0 ∗ P 6 + C   =   b w = [ 0 0 1 0 0 0 0 ] (   w  是 P 0 ∼ P 6 的系数 ) w ˉ = w ∗ C = [ 0 0 1 0 0 0 0 ] ∗ [ − 1 1 0 − 1 1 0 − 1 0 1 0 0 0 1 − 1 0 1 − 1 0 0 1 0 ] = [ − 1 0 1 ] m 0 ( c ) = b − w ∗ m 0 = 1 − [ 0 0 1 0 0 0 0 ] ∗ [ 0 0 0 1 1 1 0 ] = 1 − 0 = 1 P_2 + C =1\\ which\quad 0*P_0+0*P_1+1*P_2+0*P_3+0*P_4+0*P_5+0*P_6+C\ =\ b \\ w = \left[ \begin{matrix} 0 & 0 & 1 & 0 & 0 & 0 & 0 \end{matrix} \right]\quad(\ w\ 是P_0\sim P_6的系数)\\ \bar{w} = w*C = \left[ \begin{matrix} 0 & 0 & 1 & 0 & 0 & 0 & 0 \end{matrix} \right]*\left[ \begin{matrix} -1 & 1 & 0 \\ -1 & 1 & 0 \\ -1 & 0 & 1 \\ 0 & 0 & 0 \\ 1 & -1 & 0 \\ 1 & -1 & 0 \\ 0 & 1 & 0 \\ \end{matrix} \right] =\left[ \begin{matrix} -1 & 0 & 1 \end{matrix} \right] \\ m_0(c) = b - w*m_0 = 1 - \left[ \begin{matrix} 0 & 0 & 1 & 0 & 0 & 0 & 0 \end{matrix} \right]*\left[ \begin{matrix} 0 \\ 0 \\ 0 \\ 1 \\ 1 \\ 1 \\ 0 \end{matrix} \right] =1-0=1\\ P2+C=1which0P0+0P1+1P2+0P3+0P4+0P5+0P6+C = bw=[0010000]( w P0P6的系数)wˉ=wC=[0010000] 111011011001110010000 =[101]m0(c)=bwm0=1[0010000] 0001110 =10=1

​ 因此, C C C的库所初始值为1,在变迁中, C C C T 0 T_0 T0获得1个 t o k e n token token,从 T 1 T_1 T1获得0个 t o k e n token token,并给 T 2 T_2 T2赋予1个 t o k e n token token

4.3.2 赋时Petri网可达树matlab代码实现

注:以下两个文本文档为前置后置关联矩阵,自己创一个.txt即可
C_minus.txt
1 0 0
1 0 0
1 0 0
0 0 1
0 1 0
0 1 0
0 0 0
0 0 1

C_plus.txt
0 1 0
0 1 0
0 0 1
0 0 1
1 0 0
1 0 0
0 1 0
1 0 0

%% Time_given_Petri.m
clear;clc;
C_minus = readmatrix("C_minus.txt");
C_plus =  readmatrix("C_plus.txt");
C = C_plus - C_minus;
d = [10 8 0 12 10 8 0 0]';
mg = [1 1 0 1 0 0 6 1]';
%% Step1~2: Initial
X0 = state_X;
Ek = {};
V = [X0];
V_new = [X0];
origin = {};
destination = {};
weight = {};
%% Step3: Judge whether X0 is goal
if isequal(X0.m,mg)
    X0.goal = true;             % mark X0 as goal, algorithm exit
    origin = [origin,'X0 is goal'];
    destination = [destination,'X0 is goal'];
else
    while ~isempty(V_new)
        %% Step4: Random select a node from V_new as Xk
        index = randi([1,length(V_new)]);
        Xk = V_new(index);
        V_new(index) = [];      % delete Xk from V_new
        % V = [V,Xk];           % set Xk -> old
        for j = 1:length(V)
            if isequal(V(j).m,Xk.m)    % if Xk_plus has ever appear
                father_index = j; break;
            end
        end
        %% Step5: Calculate Transfer_Collection
        [Xk,Ek] = Transfer_Collection(Xk,C_minus);
        %% Step6
        for i = 1:length(Ek)
            %% Step7: Calculate lamda, m, v, g of Xk_plus
            ek = Ek(i);
            Xk_plus = state_X;
            Xk_plus.m = Xk.m + C(:,ek);
            Xk_plus.lamda = max(d(C_minus(:,ek)~=0)-Xk.v(C_minus(:,ek)~=0));
            Xk_plus.v = Xk.v-diag(Xk.v)*C_minus(:,ek)+Xk_plus.lamda*(Xk_plus.m-C_plus(:,ek));
            Xk_plus.g = Xk.g + Xk_plus.lamda;
            %% Step8: append Xk_plus
            sign = 1;                   % default Xk_plus is new
            for j = 1:length(V)
                if isequal(V(j).m,Xk_plus.m) % if Xk_plus has ever appear
                    sign = 0; break;
                end
            end
            if sign==1                  % if Xk_plus is new, append to V
                %% Step9: Digraph
                temp = sprintf('X%d',father_index-1);
                origin = [origin,temp];
                V = [V,Xk_plus];
                temp = sprintf('X%d',length(V)-1);
                destination = [destination,temp];
                temp = sprintf('t%d',ek-1);
                weight = [weight,temp];
            end
            %% Step10: If Vk_plus.m==mg, mark -> goal, else -> new
            if isequal(Xk_plus.m,mg)
                Xk_plus.goal = true;
                temp = sprintf('X%d is goal',length(V)-1);
                destination(end) = {temp};
                break;
            else
                V_new = [V_new,Xk_plus];
            end
        end
    end
end
G = digraph(origin,destination);
figure(1)
plot(G,"EdgeLabel",weight,"LineWidth",1.6,"MarkerSize",6,"ArrowSize", ...
    11,"NodeColor",'red','EdgeFontSize',9,'NodeFontSize',10, ...
    'ArrowPosition',0.9,'EdgeLabelColor','blue');
figure(2)
plot(G,"EdgeLabel",weight,"LineWidth",1.6,"MarkerSize",6,"ArrowSize", ...
    11,"NodeColor",'red','EdgeFontSize',9,'NodeFontSize',10, ...
    'Layout','force3','ArrowPosition',0.9,'EdgeLabelColor','blue');

%% state_X.m
classdef state_X
    properties
        m = [0 0 0 1 1 1 0 1]';         % initial m0, v0, g, lamda
        v = [0 0 0 0 0 0 0 0]';
        g = 0;
        lamda = 0;
        goal = false;
    end
    methods
        function [object,Ek] = Transfer_Collection(object,C_minus)
            Ek = [];
            for t=1:length(C_minus(1,:))
                if all(object.m>=C_minus(:,t))
                    Ek = [Ek,t];
                end
            end
        end
    end
end
4.3.3 赋时Petri网可达树执行结果

​ notes:由于程序中设定随机选择 V n e w V_{new} Vnew中的结点扩展,因此程序每次运行的结果不一定相同。

​ 输出可达树如下所示:

在这里插入图片描述

​ 输出三维力导向图如下:

在这里插入图片描述

5. 有色Petri网

5.1 颜色集

C = { g , w , b , . . . } C=\{g,w,b,...\} C={g,w,b,...}

t o k e n token token上的颜色集: C t o k e n ⟹ C t k n C_{token} \Longrightarrow C_{tkn} CtokenCtkn

​ 变迁上的颜色集: C t r a n s i t i o n ⟹ C t r s C_{transition} \Longrightarrow C_{trs} CtransitionCtrs

C ^ t k n \hat C_{tkn} C^tkn:由 C t k n C_{tkn} Ctkn中元素组成的多重集的集合;

m : P →   C ^ t k n m:P\rightarrow\ \hat C_{tkn} m:P C^tkn

5.2 有色Petri网(普通Petri网的折叠)

​ 有色Petri网就是在Petri网的基础上引入颜色的概念,对同类的个体赋予相同的颜色,不同类的个体以不同的颜色加以区分。另外token也增加了颜色,可以描述对象的属性信息,在弧上和变迁上存在着条件表达式和函数,说明弧的权值和颜色属性以及变迁触发的约束条件。

​ 有色Petri网用七元组来表示,即$CPN={{P,T,E,C_{tkn},C_{trs},m_0,W_{arc}} } $

​ (1) P P P : 库所的有限集合, P = { p 1 , p 2 , . . . , p m } P={\{p_1,p_2,...,p_m}\} P={p1,p2,...,pm};

​ (2) T T T : 变迁的有限集合, T = { t 1 , t 2 , . . . , t n } T={\{t_1,t_2,...,t_n}\} T={t1,t2,...,tn};

​ (3) W a r c W_{arc} Warc : 弧的有限集合,满足$P\cap T=P\cap W_{arc}=T\cap W_{arc}=\varnothing $;

​ (4) C t k n C_{tkn} Ctkn : 每个库所对应的颜色集合

​ (5) C t r s C_{trs} Ctrs : 每个变迁对应的颜色集合

​ (6) m 0 m_0 m0 : P → C ^ t k n P\rightarrow \widehat C_{tkn} PC tkn (由 C t k n C_{tkn} Ctkn 中的每个元素组成的多重集合)

5.3 激发规则与更新规则

∀ C ∈ C t r s , t ∈ T \forall C \in C_{trs} , t \in T CCtrs,tT m k ≥ C c − ( : , t ) m_k\geq C_c^-(:,t) mkCc(:,t) ,则该颜色对应的变迁可激发

m k + 1 = m k + C c ( : , t ) m_{k+1}=m_k+C_c (:,t) mk+1=mk+Cc(:,t)

5.4 可覆盖树算法

输入:前置关联矩阵C − ^- ,后置关联矩阵C + ^+ +,初始标识 m 0 m_0 m0

​ (1)绘制根结点记为 m 0 m_0 m0,并将之标记为新结点 n e w new new

​ (2)判断可覆盖树中是否含有 n e w new new结点:如果没有,将可覆盖树输出,判断终止,算法结束;反之,执行3;

​ (3)在 n e w new new结点中任意选择一个 m m m;

​ (4) f o r   a l l    t ∈ T for \ all\ \ t\in T for all  tT

​ (5) i f if if $ \ m\geq$ C − ( : , t ) C^-(:,t) C(:,t), t h e n then then

​ (6) 进行m的更新 m k + 1 = m k + C ( : , t ) = m k + C ⋅ e → m_{k+1}=m_k+C(:,t)=m_k+C\cdot \overrightarrow{e} mk+1=mk+C(:,t)=mk+Ce

​ (7) 如果树中存在一个标识 m ‘ m^` m

KaTeX parse error: Undefined control sequence: \and at position 16: m^`\geq m^{``} \̲a̲n̲d̲(\ \exists \ p\…

​ (8) ∀ p ∈ P , m ‘ ( p ) > m ‘ ‘ ( p ) , m ‘ ( p ) = ω \forall p\in P,m^`(p)>m^{``}(p),m^`(p)=\omega pP,m(p)>m‘‘(p),m(p)=ω

​ (9) 遍历树,判断 m ‘ m^` m是否为旧结点,标记为 o l d old old,反之,标记为新结点 n e w new new

​ (10) e n d i f endif endif

​ (11) e n d f o r endfor endfor

​ (12)返回第2步

致歉

由于课业繁多,且离散系统优化调度不是本人研究方向,因此止步于皮毛,仅供参考。

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在 Node.js 中,导出类需要使用第三方库。其中比较常用的是 `graphviz` 和 `plantuml`。下面分别介绍使用这两个库导出类的方法。 1. 使用 `graphviz` 导出类 `graphviz` 是一个流行的绘工具,它可以生成各种类型的形,包括类。要使用 `graphviz` 导出类,首先需要安装该库: ``` npm install graphviz ``` 接着,可以使用以下代码生成一个简单的类: ```javascript const graphviz = require('graphviz'); const g = graphviz.digraph('G'); g.set('rankdir', 'LR'); const classNode = g.addNode('Class', { shape: 'box' }); const fieldNode = g.addNode('Field', { shape: 'ellipse' }); const methodNode = g.addNode('Method', { shape: 'ellipse' }); g.addEdge(classNode, fieldNode); g.addEdge(classNode, methodNode); console.log(g.to_dot()); ``` 上述代码使用 `graphviz` 创建了一个名为 `G` 的有向,其中包含三个节点(类、字段和方法),以及两条边(从类到字段,从类到方法)。最后,它使用 `to_dot()` 方法将形输出为 Graphviz DOT 格式的字符串。 将输出的 DOT 格式复制到 Graphviz 程序中(如 `dot`)即可生成类。也可以使用第三方库 `viz.js` 直接在浏览器中渲染形。 2. 使用 `plantuml` 导出类 `plantuml` 是另一个流行的绘工具,它可以使用类似于 UML 的语言描述各种类型的形。要使用 `plantuml` 导出类,首先需要安装该库: ``` npm install -g node-plantuml ``` 接着,可以使用以下代码生成一个简单的类: ```javascript const plantuml = require('node-plantuml'); const source = ` @startuml class Class { +field: type +method(): void } @enduml `; plantuml.generate(source, { format: 'png' }).then(data => console.log(data)); ``` 上述代码使用 `plantuml` 创建了一个包含一个类的类,并将其转换为 PNG 格式的二进制数据。可以将该数据写入文件或通过络发送给客户端。 该库还支持将类输出为 SVG、ASCII 等格式,并且可以使用 `pipe` 方法将其直接输出到流中。例如,以下代码将类输出到 HTTP 响应中: ```javascript const http = require('http'); const plantuml = require('node-plantuml'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'image/png' }); plantuml.generate('@startuml\nClass\n@enduml\n', { format: 'png' }).pipe(res); }); server.listen(3000); ``` 在浏览器中访问 `http://localhost:3000` 即可查看生成的类

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值