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