LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
reachableSpaceGenerator.m
1function [SSq,SSh,sn] = reachableSpaceGenerator(sn,options)
2% [SSQ,SSH,QN] = REACHABLESPACEGENERATOR(QN,OPTIONS)
3%
4% This differs from spaceGenerator as it is restricted to states reachable
5% from the initial state.
6
7% Copyright (c) 2012-2026, Imperial College London
8% All rights reserved.
9
10% By default the jobs are all initialized in the first valid state
11
12%nstations = sn.nstations;
13nstateful = sn.nstateful;
14%init_nserver = sn.nservers; % restore Inf at delay nodes
15R = sn.nclasses;
16N = sn.njobs';
17sync = sn.sync;
18csmask = sn.csmask;
19stack = {sn.state'};
20SSq = [];
21A = length(sn.sync);
22sync = sn.sync;
23isSimulation = false;
24local = sn.nnodes+1;
25
26for act=1:A
27 node_a{act} = sync{act}.active{1}.node;
28 node_p{act} = sync{act}.passive{1}.node;
29 class_a{act} = sync{act}.active{1}.class;
30 class_p{act} = sync{act}.passive{1}.class;
31 event_a{act} = sync{act}.active{1}.event;
32 event_p{act} = sync{act}.passive{1}.event;
33 outprob_a{act} = [];
34 outprob_p{act} = [];
35end
36
37space = cell(1,nstateful);
38for i=1:nstateful
39 space{i} = sn.state{i};
40end
41SSh = ones(1,nstateful); % initial state
42it = 0;
43%ih = 1;
44stack_index = 1;
45maxstatesz = zeros(1,nstateful);
46% Q = sparse([]);
47% Dfilt = cell(1,A);
48% for a=1:A
49% Dfilt{a} = sparse([]);
50% end
51while 1
52 if isempty(stack)
53 %Q = ctmc_makeinfgen(Q);
54 SSq = []; % initial state
55 for i=1:size(SSh,1)
56 colctr = 1;
57 for j=1:nstateful
58 SSq(i,colctr:(colctr+size(space{j},2)-1)) = space{j}(SSh(i,j),:);
59 colctr = colctr+size(space{j},2);
60 end
61 end
62 % for a=1:A
63 % if (size(Dfilt{a},1) < size(SSq,1)) || (size(Dfilt{a},2) < size(SSq,1))
64 % Dfilt{a}(size(SSq,1),size(SSq,1)) = 0;
65 % end
66 % end
67 sn.space = space;
68 return
69 end
70 % pop state
71 stateCell = stack{end};
72 state = cell2mat(stateCell);
73 ih = stack_index(end);
74 stack_index(end)=[];
75 stack(end)=[];
76 statelen = cellfun(@length, stateCell);
77 newStateCell = cell(1,A);
78 %samples_collected
79 ctr = 1;
80 enabled_sync = {}; % row is action label, col1=rate, col2=new state
81 %enabled_new_state = {};
82 enabled_rates = [];
83 for act=1:A
84 outprob_a{act} = [];
85 outprob_p{act} = [];
86 update_cond_a = true; %((node_a{act} == last_node_a || node_a{act} == last_node_p));
87 newStateCell{act} = stateCell;
88 if update_cond_a || isempty(outprob_a{act})
89 isf = sn.nodeToStateful(node_a{act});
90 [newStateCell{act}{sn.nodeToStateful(node_a{act})}, rate_a{act}, outprob_a{act}] = State.afterEvent(sn, node_a{act}, stateCell{isf}, event_a{act}, class_a{act}, isSimulation);
91 if size(newStateCell{act}{sn.nodeToStateful(node_a{act})},1) == 0
92 outprob_a{act} = [];
93 end
94 end
95
96 if isempty(newStateCell{act}{sn.nodeToStateful(node_a{act})}) || isempty(rate_a{act}) % state not found
97 continue
98 end
99
100 for ia=1:size(newStateCell{act}{sn.nodeToStateful(node_a{act})},1) % for all possible new states of the active agent
101 if isempty(newStateCell{act}{sn.nodeToStateful(node_a{act})})
102 continue
103 end
104
105 if newStateCell{act}{sn.nodeToStateful(node_a{act})}(ia,:) == -1 % hash not found
106 continue
107 end
108 %update_cond_p = ((node_p{act} == last_node_a || node_p{act} == last_node_p)) || isempty(outprob_p{act});
109 update_cond = true; %update_cond_a || update_cond_p;
110 if rate_a{act}(ia)>0
111 if node_p{act} ~= local
112 if node_p{act} == node_a{act} %self-loop
113 if update_cond
114 % since self-loop sare multiple instantaneous
115 % state transitions, we save the intermediate
116 % states in the sn.space structure
117 i = node_p{act};
118 nci = newStateCell{act}{sn.nodeToStateful(node_a{act})};
119 for j=1:size(nci,1)
120 if length(nci(j,:)) > size(space{i},2)
121 space{i} = [zeros(size(space{i},1),length(nci(j,:))-size(space{i},2)),space{i}];
122 elseif length(nci(j,:)) < size(space{i},2)
123 nci = [zeros(1, size(space{i},2)-length(nci(j,:))),nci(j,:)];
124 end
125 if matchrow(space{i},nci(j,:))==-1
126 space{i}(end+1,:) = nci(j,:);
127 end
128 end
129 [newStateCell{act}{sn.nodeToStateful(node_p{act})}, ~, outprob_p{act}] = State.afterEvent(sn, node_p{act}, newStateCell{act}{sn.nodeToStateful(node_a{act})}, event_p{act}, class_p{act}, isSimulation);
130 outprob_a{act} = outprob_p{act};
131 end
132 else % departure from active
133 if update_cond
134 [newStateCell{act}{sn.nodeToStateful(node_p{act})}, ~, outprob_p{act}] = State.afterEvent(sn, node_p{act}, stateCell{sn.nodeToStateful(node_p{act})}, event_p{act}, class_p{act}, isSimulation);
135 end
136 end
137 if ~isempty(newStateCell{act}{sn.nodeToStateful(node_p{act})})
138 if sn.isstatedep(node_a{act},3)
139 prob_sync_p{act} = sync{act}.passive{1}.prob(stateCell, newStateCell{act}); %state-dependent
140 else
141 prob_sync_p{act} = sync{act}.passive{1}.prob;
142 end
143 else
144 prob_sync_p{act} = 0;
145 end
146 end
147 if ~isempty(newStateCell{act}{sn.nodeToStateful(node_a{act})})
148 if node_p{act} == local
149 prob_sync_p{act} = 1; %outprob_a{act}; % was 1
150 end
151 if ~isnan(rate_a{act})
152 if all(~cellfun(@isempty,newStateCell{act}))
153 if event_a{act} == EventType.DEP
154 node_a_sf{act} = sn.nodeToStateful(node_a{act});
155 node_p_sf{act} = sn.nodeToStateful(node_p{act});
156 end
157 % simulate also self-loops as we need to log them
158 if node_p{act} < local && ~csmask(class_a{act}, class_p{act}) && sn.nodetype(node_p{act})~=NodeType.Source && (rate_a{act}(ia) * prob_sync_p{act} >0)
159 line_error(mfilename,sprintf('Error: state-dependent routing at node %d (%s) violates the class switching mask (node %d -> node %d, class %d -> class %d).', node_a{act}, sn.nodenames{node_a{act}}, node_a{act}, node_p{act}, class_a{act}, class_p{act}));
160 end
161 enabled_rates(ctr) = rate_a{act}(ia) * prob_sync_p{act};
162 enabled_sync{ctr} = act;
163 ctr = ctr + 1; % keep
164 end
165 end
166 end
167 end
168 end
169 end
170
171 for firing_ctr=1:length(enabled_rates)
172 firing_rate = enabled_rates(firing_ctr);
173 last_node_a = node_a{enabled_sync{firing_ctr}};
174 last_node_p = node_p{enabled_sync{firing_ctr}};
175 act = enabled_sync{firing_ctr};
176 netstates = newStateCell{act};
177 if enabled_rates(firing_ctr)>0 && ~any(cellfun(@isempty,netstates))
178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179 nvec = cellfun(@(c) size(c,1)-1, netstates);
180 n = pprod(nvec);
181 while n>=0
182 newstate = [];
183 newstatec = {};
184 firingprob = 1;
185 for i=1:size(netstates,2)
186 if i==last_node_a
187 firingprob = firingprob*outprob_a{enabled_sync{firing_ctr}}(1+n(i));
188 end
189 if i==last_node_p
190 firingprob = firingprob*outprob_p{enabled_sync{firing_ctr}}(1+n(i));
191 end
192 maxstatesz(i) = max(maxstatesz(i),length(netstates{i}(1+n(i),:)));
193 newstate = [newstate,zeros(1,maxstatesz(i)-length(netstates{i}(1+n(i),:))),netstates{i}(1+n(i),:)];
194 newstatec{i} = [zeros(1,maxstatesz(i)-length(netstates{i}(1+n(i),:))),netstates{i}(1+n(i),:)];
195 end
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 if firingprob>0
198 hashednewstate = zeros(1,nstateful);
199 for i=1:nstateful
200 if length(newstatec{i}) > size(space{i},2)
201 hashednewstate(i) = matchrow([zeros(size(space{i},1),length(newstatec{i})-size(space{i},2)),space{i}], newstatec{i});
202 else
203 hashednewstate(i) = matchrow(space{i}, newstatec{i});
204 end
205 end
206 jh = matchrow(SSh,hashednewstate);
207 if jh == -1 || (length(newstate)~=length(state) || any(newstate~=state))
208 % store and update jh index
209 if jh == -1
210 for i=1:nstateful
211 if hashednewstate(i) == -1
212 nci = newstatec{i};
213 if length(nci) > size(space{i},2)
214 space{i} = [zeros(size(space{i},1),length(nci)-size(space{i},2)),space{i}];
215 elseif length(nci) < size(space{i},2)
216 nci = [zeros(1, size(space{i},2)-length(nci)),nci];
217 end
218 space{i}(end+1,:) = nci;
219 hashednewstate(i) = size(space{i},1);
220 end
221 end
222 SSh = [SSh; hashednewstate];
223 jh = size(SSh,1);
224 stack{end+1} = newstatec;
225 stack_index(end+1) = jh;
226 end
227 end
228 % for some reason the Q generation is buggy so we
229 % disabled it
230 % if (size(Q,1)< ih) || (size(Q,2)< jh)
231 % Q(ih,jh) = firing_rate;
232 % for a=1:A
233 % Dfilt{act}(ih,jh) = 0;
234 % end
235 % Dfilt{act}(ih,jh) = firing_rate;
236 % else
237 % Q(ih,jh) = Q(ih,jh) + firing_rate;
238 % for a=1:A
239 % if (size(Dfilt{act},1) < ih) || (size(Dfilt{act},2) < jh)
240 % Dfilt{act}(ih,jh) = 0;
241 % end
242 % end
243 % Dfilt{act}(ih,jh) = Dfilt{act}(ih,jh) + firing_rate;
244 % end
245 end
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 n = pprod(n,nvec);
248 end
249 end
250 end
251 it = it + 1;
252end
253end
Definition mmt.m:92