LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
refreshGlobalSync.m
1function gsync = refreshGlobalSync(self)
2% SYNC = REFRESHGLOBALSYNC()
3
4sn = self.sn;
5local = self.getNumberOfNodes+1;
6nclasses = sn.nclasses;
7gsync = {};
8emptystate = cellzeros(sn.nnodes,1,0,0);
9if any(sn.isstatedep(:))
10 rtmask = self.sn.rtfun(emptystate, emptystate);
11else
12 rtmask = ceil(self.sn.rt);
13end
14
15% A Transition's global synchronizations are per (node, mode): the enabling and
16% firing events are read off the (nnodes x nclasses) enabling/firing matrices as
17% linear indices, so a class index carries no extra information here. Do NOT wrap
18% this in a per-class loop: doing so appended an identical ENABLE/FIRE pair for
19% every class, and the duplicated firings were each counted in depRates, inflating
20% the throughput of every multiclass SPN by exactly nclasses. Single-class models
21% were unaffected, which is why this went unnoticed. The JAR guards the same way
22% (see Network.refreshSync, "Only do this once per node, not for each class").
23for ind=1:sn.nnodes
24
25 if sn.isstateful(ind)
26 if sn.nodetype(ind) == NodeType.Transition
27 for m=1:sn.nodeparam{ind}.nmodes
28 % mode enabling
29 enablingPlaces = find(sn.nodeparam{ind}.enabling{m});
30 % inhibitor-arc input places (finite threshold). Added as
31 % LOCAL events (no state effect) so their markings are read
32 % into ep_space and the enabling test can apply the upper
33 % bound. Exclude places already listed as enabling inputs.
34 inhibitingPlaces = setdiff(find(~isinf(sn.nodeparam{ind}.inhibiting{m})), enablingPlaces);
35 gsync{end+1,1}.active{1} = ModeEvent(EventType.ENABLE, ind, m, 1.0);
36 gsync{end,1}.passive = cell(1,length(enablingPlaces)+length(inhibitingPlaces));
37 for ep=1:length(enablingPlaces)
38 gsync{end,1}.passive{ep} = ModeEvent(EventType.LOCAL, enablingPlaces(ep), m, 1.0); % ID_LOCAL has no state effects
39 end
40 for ip=1:length(inhibitingPlaces)
41 gsync{end,1}.passive{length(enablingPlaces)+ip} = ModeEvent(EventType.LOCAL, inhibitingPlaces(ip), m, 1.0);
42 end
43 end
44 for m=1:sn.nodeparam{ind}.nmodes
45 % mode firing
46 %
47 % POST events are produced only for positive firing entries.
48 % A negative entry marks an input place, where the user
49 % writes the token the PRE event already removes (see
50 % matlab/examples/solvers/ctmc_spn_mm1.m, which sets -1 on
51 % the input place and +1 on the output). Emitting a POST for
52 % it subtracted the token a second time, so a mode with an
53 % arc weight of one consumed two tokens per firing; the
54 % tandem SPN then reported per-place throughputs above its
55 % own arrival rate, which no steady-state chain admits.
56 % SolverJMT and the JAR both read the field this way: the
57 % JAR filters on firingMatrix.get(fp,rr) > 0
58 % (Network.java:7677), so this restores cross-language
59 % agreement as well.
60 firingPlaces = find(sn.nodeparam{ind}.firing{m} > 0);
61 enablingPlaces = find(sn.nodeparam{ind}.enabling{m});
62 % inhibitor-arc input places (finite threshold), read into
63 % ep_space for the firing enabling-degree test. Added as
64 % LOCAL events (no token effect); exclude places already
65 % present as enabling (PRE) or firing (POST) passives.
66 inhibitingPlaces = setdiff(find(~isinf(sn.nodeparam{ind}.inhibiting{m})), union(enablingPlaces, firingPlaces));
67 gsync{end+1,1}.active{1} = ModeEvent(EventType.FIRE, ind, m);
68
69 gsync{end,1}.passive = {};
70 for ep=1:length(enablingPlaces)
71 % TODO: this creates a departure event for each
72 % job pulled from the enabling places, which is
73 % inefficient
74 gsync{end,1}.passive{end+1} = ModeEvent(EventType.PRE, enablingPlaces(ep), m, sn.nodeparam{ind}.enabling{m}(enablingPlaces(ep)));
75 end
76 for fp=1:length(firingPlaces)
77 % TODO: this creates an arrival event for each
78 % fired job to the destination place, which is
79 % inefficient
80 gsync{end,1}.passive{end+1} = ModeEvent(EventType.POST, firingPlaces(fp), m, sn.nodeparam{ind}.firing{m}(firingPlaces(fp)));
81 end
82 for ip=1:length(inhibitingPlaces)
83 gsync{end,1}.passive{end+1} = ModeEvent(EventType.LOCAL, inhibitingPlaces(ip), m, 1.0);
84 end
85 end
86 end
87
88 end
89end
90if ~isempty(self.sn) %&& isprop(self.sn,'nvars')
91 self.sn.gsync = gsync;
92end
93end