LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
spaceGeneratorNodes.m
1function [nodeStateSpace, sn, capacityc] = spaceGeneratorNodes(sn, cutoff, options)
2if nargin<3
3 options = Solver.defaultOptions;
4end
5N = sn.njobs';
6sn.space = {};
7capacityc = zeros(sn.nnodes, sn.nclasses);
8% Draft SPN support
9% for n=1:sn.nnodes
10% if isfield(sn.varsparam{n}, "capacityc")
11% capacityc(n) = sn.varsparam{n}.capacityc;
12% end
13% end
14for ind=1:sn.nnodes
15 if sn.isstation(ind) % place jobs across stations
16 ist = sn.nodeToStation(ind);
17 isf = sn.nodeToStateful(ind);
18 for r=1:sn.nclasses %cut-off open classes to finite capacity
19 c = find(sn.chains(:,r));
20 if ~isempty(sn.visits{c}) && sn.visits{c}(isf,r) == 0
21 capacityc(ind,r) = 0;
22 % Draft SPN support
23 %elseif isfield(sn.varsparam{ind}, 'capacityc')
24 % capacityc(ind,r) = min(cutoff(ist,r), sn.classcap(ist,r));
25 elseif sn.nodetype(ind) ~= NodeType.Place && ~isempty(sn.proc) && ~isempty(sn.proc{ist}{r}) && any(any(isnan(sn.proc{ist}{r}{1}))) % disabled (not Places - they hold tokens without service)
26 capacityc(ind,r) = 0;
27 else
28 if isinf(N(r))
29 capacityc(ind,r) = min(cutoff(ist,r), sn.classcap(ist,r));
30 else
31 capacityc(ind,r) = sum(sn.njobs(sn.chains(c,:)));
32 end
33 end
34 end
35 if sn.isstation(ind)
36 % in this case, the local variables are produced within
37 % fromMarginalBounds, e.g., for RROBIN routing
38 sn.space{isf} = State.fromMarginalBounds(sn, ind, [], capacityc(ind,:), sn.cap(ist), options);
39 else
40 % this is the case for example of cache nodes
41 state_bufsrv = State.fromMarginalBounds(sn, ind, [], capacityc(ind,:), sn.cap(ist), options);
42 state_var = State.spaceLocalVars(sn, ind);
43 sn.space{isf} = State.cartesian(state_bufsrv,state_var); % generate all possible states for local variables
44 end
45 if isinf(sn.nservers(ist))
46 sn.nservers(ist) = sum(capacityc(ind,:));
47 end
48 elseif sn.isstateful(ind) % generate state space of other stateful nodes that are not stations
49 %ist = sn.nodeToStation(ind);
50 isf = sn.nodeToStateful(ind);
51 switch sn.nodetype(ind)
52 case NodeType.Cache
53 for r=1:sn.nclasses % restrict state space generation to immediate events
54 if isnan(sn.nodeparam{ind}.pread{r})
55 capacityc(ind,r) = 1; %
56 else
57 capacityc(ind,r) = 1; %
58 end
59 end
60 case NodeType.Router
61 % For Router nodes, only allow capacity for classes that have
62 % non-zero nodevisits (classes that actually visit the Router)
63 for r=1:sn.nclasses
64 c = find(sn.chains(:,r));
65 if ~isempty(sn.nodevisits{c}) && sn.nodevisits{c}(ind,r) > 0
66 capacityc(ind,r) = 1;
67 else
68 capacityc(ind,r) = 0;
69 end
70 end
71 case NodeType.Transition
72 capacityc(ind,:) = 0; % Transitions don't hold class-based jobs
73 % Generate per-mode state space (bypass fromMarginalBounds)
74 nmodes = sn.nodeparam{ind}.nmodes;
75 firingphases = sn.nodeparam{ind}.firingphases;
76 if any(isnan(firingphases))
77 firingphases = zeros(1, nmodes);
78 for m = 1:nmodes
79 if iscell(sn.nodeparam{ind}.firingproc) && ~isempty(sn.nodeparam{ind}.firingproc{m})
80 firingphases(m) = size(sn.nodeparam{ind}.firingproc{m}{1}, 1);
81 else
82 firingphases(m) = 1;
83 end
84 end
85 end
86 fK = firingphases;
87 nmodeservers = sn.nodeparam{ind}.nmodeservers;
88 max_jobs = sum(sn.njobs(~isinf(sn.njobs)));
89 if any(isinf(sn.njobs))
90 max_jobs = max_jobs + sum(cutoff(1,:));
91 end
92 mode_spaces = cell(1, nmodes);
93 for m = 1:nmodes
94 max_srv_m = nmodeservers(m);
95 if isinf(max_srv_m)
96 max_srv_m = max_jobs;
97 end
98 max_srv_m = min(max_srv_m, max_jobs);
99 mode_states = [];
100 for total = 0:max_srv_m
101 phase_combs = multichoose(fK(m), total);
102 buf_m = nmodeservers(m);
103 if isinf(buf_m)
104 buf_m = GlobalConstants.MaxInt();
105 end
106 buf_m = buf_m - total;
107 mode_states = [mode_states; repmat(buf_m, size(phase_combs,1), 1), phase_combs]; %#ok<AGROW>
108 end
109 mode_spaces{m} = mode_states;
110 end
111 trans_space = mode_spaces{1};
112 for m = 2:nmodes
113 trans_space = State.cartesian(trans_space, mode_spaces{m});
114 end
115 trans_space = [trans_space, zeros(size(trans_space,1), nmodes)]; % append fired counts
116 state_var = State.spaceLocalVars(sn, ind);
117 sn.space{isf} = State.cartesian(trans_space, state_var);
118 continue; % skip fromMarginalBounds below
119 otherwise
120 capacityc(ind,:) = 1; %
121 end
122 state_bufsrv = State.fromMarginalBounds(sn, ind, [], capacityc(ind,:), 1, options);
123 state_var = State.spaceLocalVars(sn, ind);
124 sn.space{isf} = State.cartesian(state_bufsrv,state_var); % generate all possible states for local variables
125
126 % Prune locally invalid cache states for retrieval-system caches. The
127 % unfiltered cartesian product enumerates states the dynamics can never
128 % reach -- an item simultaneously cached and being retrieved, more items
129 % in retrieval than the retrieval-system capacity, or more than one job
130 % in the cache server. Leaving them in pollutes the CTMC stationary
131 % distribution. The cross-node (cache <-> queue) consistency is enforced
132 % during global composition. Non-retrieval caches are left untouched.
133 if sn.nodetype(ind) == NodeType.Cache ...
134 && isfield(sn.nodeparam{ind},'retrievalSystemCapacity') ...
135 && sn.nodeparam{ind}.retrievalSystemCapacity > 0
136 np = sn.nodeparam{ind};
137 nItems = np.nitems;
138 tcc = np.totalCacheCapacity;
139 rsc = np.retrievalSystemCapacity;
140 lvs = size(state_bufsrv,2); % per-class server presence is columns 1..lvs
141 value = sn.space{isf};
142 keep = false(size(value,1),1);
143 for row = 1:size(value,1)
144 st = value(row,:);
145 % at most one class job may sit in the cache server/buffer
146 validRow = sum(st(1:lvs)) <= 1;
147 if validRow
148 nbits = 0;
149 cacheItems = st((lvs+1):(lvs+tcc));
150 for col = (lvs+tcc+1):size(st,2)
151 if st(col) == 0, continue; end
152 nbits = nbits + 1;
153 item = col - (lvs+tcc); % 1-based item id of the set bit
154 % a cached item cannot simultaneously be in the retrieval system
155 if any(cacheItems == item)
156 validRow = false; break;
157 end
158 end
159 % at most retrievalSystemCapacity items may be in retrieval at once
160 if validRow && nbits > rsc
161 validRow = false;
162 end
163 end
164 keep(row) = validRow;
165 end
166 sn.space{isf} = value(keep,:);
167 end
168 end
169end
170nodeStateSpace = sn.space;
171end