LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
afterEventJoin.m
1function [outspace, outrate, outprob, eventCache] = afterEventJoin(sn, ind, inspace, event, class, isSimulation, eventCache, key)
2% [OUTSPACE, OUTRATE, OUTPROB, EVENTCACHE] = AFTEREVENTJOIN(SN, IND, INSPACE, EVENT, CLASS, ISSIMULATION, EVENTCACHE, KEY)
3%
4% Handle afterEvent logic for Join stations on FJ-augmented structs
5% (see ModelAdapter.fjtag). The join state is a plain per-class count
6% vector [n_1..n_R] of buffered jobs: auxiliary-class entries count the
7% sibling tasks waiting for synchronization.
8%
9% ARV (passive): buffer the arriving job/sibling.
10% DEP in an original class r (active, immediate): enabled when a plain
11% class-r job is buffered, or when some tag t has the full required
12% sibling multiset present (all B branches, identity matching by tag).
13% The firing consumes the siblings of the LOWEST complete tag and lets
14% one class-r job depart; the r->destination move is the regular sync
15% pairing generated by refreshSync from the join routing.
16
17% Copyright (c) 2012-2026, Imperial College London
18% All rights reserved.
19
20outspace = [];
21outrate = [];
22outprob = 1;
23
24R = sn.nclasses;
25n = inspace(:,(end-R+1):end); % per-class counts (rows x R)
26
27switch event
28 case EventType.ARV
29 n(:,class) = n(:,class) + 1;
30 outspace = n;
31 outrate = -1*ones(size(outspace,1),1); % passive action, rate is unspecified
32 case EventType.DEP
33 fjp = [];
34 if iscell(sn.nodeparam) && length(sn.nodeparam) >= ind && isstruct(sn.nodeparam{ind}) && isfield(sn.nodeparam{ind},'fj')
35 fjp = sn.nodeparam{ind}.fj;
36 end
37 % auxiliary sibling classes never depart individually: they are
38 % consumed only by the original-class join firing below
39 isaux = false;
40 if ~isempty(fjp)
41 for rr=fjp.origclasses(:)'
42 if ~isempty(fjp.auxmatrix{rr}) && any(any(fjp.auxmatrix{rr} == class))
43 isaux = true;
44 break
45 end
46 end
47 end
48 if isaux
49 return
50 end
51 outspace = zeros(0,R);
52 outrate = zeros(0,1);
53 outprob = zeros(0,1);
54 for row=1:size(n,1)
55 nrow = n(row,:);
56 if nrow(class) > 0
57 % plain (non-forked) job buffered in the departing class
58 nrow(class) = nrow(class) - 1;
59 outspace(end+1,:) = nrow; %#ok<AGROW>
60 outrate(end+1,1) = GlobalConstants.Immediate; %#ok<AGROW>
61 outprob(end+1,1) = 1; %#ok<AGROW>
62 elseif ~isempty(fjp) && length(fjp.auxmatrix) >= class && ~isempty(fjp.auxmatrix{class})
63 auxm = fjp.auxmatrix{class}; % B x T matrix of auxiliary class indices
64 req = fjp.required{class}; % B x 1 required siblings per branch
65 T = size(auxm,2);
66 tstar = 0;
67 for t=1:T
68 if all(nrow(auxm(:,t)) >= req(:)')
69 tstar = t; % lowest complete tag, canonical consumption
70 break
71 end
72 end
73 if tstar > 0
74 nrow(auxm(:,tstar)) = nrow(auxm(:,tstar)) - req(:)';
75 outspace(end+1,:) = nrow; %#ok<AGROW>
76 outrate(end+1,1) = GlobalConstants.Immediate; %#ok<AGROW>
77 outprob(end+1,1) = 1; %#ok<AGROW>
78 end
79 end
80 end
81 if isempty(outspace)
82 outspace = [];
83 outrate = [];
84 outprob = 1;
85 end
86end
87
88if isSimulation
89 if nargin>=7 && isobject(eventCache)
90 eventCache(key) = {outprob, outspace, outrate};
91 end
92 if size(outspace,1) > 1
93 tot_rate = sum(outrate);
94 cum_rate = cumsum(outrate) / tot_rate;
95 firing_ctr = 1 + max([0,find( rand > cum_rate' )]); % select action
96 outspace = outspace(firing_ctr,:);
97 outrate = sum(outrate);
98 outprob = outprob(firing_ctr,:);
99 end
100end
101
102end
Definition Station.m:245