function [t, M, yout]= PN_sim(Pre, Post, M0, ti_tf, options) % Simulating a Petri net, using a SFC/Grafcet simulation methodology. % See book "Automating Manufacturing Systems", by Hugh Jack, 2008 % (ch20. Sequential Function Charts) % % Petri net model: % M(k+1) = M(k) +(Post-Pre)*q(k) % Pre and Post are NxM matrices, meaning N places and M transitions % % Input: % Pre : NxM : preconditions matrix % Post : NxM : postconditions matrix % M0 : Mx1 : intial marking % ti_tf: 1x2 : init and final time % % Output: % t : NTx1 : time vector (steps of 5ms) % M : NTxM : states of the PN along time % yout: NTxNO: output of the PN along time % % Requires the following auxiliary functions: % function act= PN_s2act(MP) % function yout= PN_s2yout(MP) % function qk= PN_tfire(MP, t) % Nov2011, J. Gaspar if nargin<4 kb_tst(2); return end % 0. Start PN at state M0 % PN= struct('MP',M0, 'trans',zeros(size(Pre,2),1), 'yout',[], ... 'Pre',Pre, 'Post',Post, ... 'ti',ti_tf(1), 'tf',ti_tf(2), 'tm',ti_tf(1), 'dt',5e-3 ); tSav= (PN.ti:PN.dt:PN.tf)'; MPSav= zeros(length(tSav), length(PN.MP)); youtSav= zeros(length(tSav), length(PN_s2yout(PN.MP))); h = waitbar(0,'Please wait...'); for i= 1:length(tSav) PN.tm= tSav(i); % 1. Check transitions (update state) qk= PN_tfire(PN.MP, PN.tm); qk2= filter_possible_firings(PN.MP, PN.Pre, qk(:)); PN.MP= PN.MP +(Post-Pre)*qk2; % 2. Do place activities yout= PN_s2yout(PN.MP); % Log all results MPSav(i,:)= PN.MP'; qkSav(i,:)= qk2'; youtSav(i,:)= yout; waitbar((PN.tm-PN.ti)/(PN.tf-PN.ti), h); end; % while close(h); % define the output arguments % t= tSav; M= MPSav; yout= youtSav; return function qk2= filter_possible_firings(M0, Pre, qk) % verify Pre*q <= M % try to fire all qk entries M= M0; mask= zeros(size(qk)); for i=1:length(qk) mask(i)= 1; if any(Pre*(mask.*qk) > M) % exceeds available markings mask(i)= 0; %else % % mask(i) is ok, apply the firing % % (consume some marking) % M= M - Pre(:,i)*qk(i); end end qk2= mask.*qk;