LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
JLINE.m
1classdef JLINE
2 % JLINE Conversion utilities for JLINE format models
3 %
4 % JLINE provides static methods to convert between LINE MATLAB models
5 % and JLINE Java/Kotlin models. This class serves as the primary interface
6 % for interoperability between the MATLAB and Java implementations of LINE.
7 %
8 % @brief JLINE format conversion and Java interoperability utilities
9 %
10 % Main functionality:
11 % - Convert LINE MATLAB models to JLINE Java models
12 % - Convert JLINE Java models back to LINE MATLAB format
13 % - Access JLINE solvers from MATLAB
14 % - Handle serialization between MATLAB and Java representations
15 %
16 % Example:
17 % @code
18 % % Convert a LINE model to JLINE format
19 % jnetwork = JLINE.from_model(network);
20 % % Get a JLINE solver
21 % jssa = JLINE.get_solver(jnetwork, 'ssa');
22 % @endcode
23
24 properties (Constant)
25 jar_loc = which('jline.jar');
26 end
27
28 methods(Static)
29
30 function model = from_line_layered_network(line_layered_network)
31 sn = line_layered_network.getStruct;
32
33 %% initialization
34 model = javaObject('jline.lang.layered.LayeredNetwork', line_layered_network.getName);
35
36 %% host processors
37 P = cell(1,sn.nhosts);
38 for h=1:sn.nhosts
39 if isinf(sn.mult(h))
40 sn_mult_h = java.lang.Integer.MAX_VALUE;
41 else
42 sn_mult_h = sn.mult(h);
43 end
44 switch sn.sched(h)
45 case SchedStrategy.REF
46 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.REF);
47 case SchedStrategy.INF
48 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.INF);
49 case SchedStrategy.FCFS
50 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.FCFS);
51 case SchedStrategy.LCFS
52 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFS);
53 case SchedStrategy.SIRO
54 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.SIRO);
55 case SchedStrategy.SJF
56 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.SJF);
57 case SchedStrategy.LJF
58 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LJF);
59 case SchedStrategy.PS
60 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.PS);
61 case SchedStrategy.DPS
62 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.DPS);
63 case SchedStrategy.GPS
64 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.GPS);
65 case SchedStrategy.SEPT
66 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.SEPT);
67 case SchedStrategy.LEPT
68 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LEPT);
69 case {SchedStrategy.HOL, SchedStrategy.FCFSPRIO}
70 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.FCFSPRIO);
71 case SchedStrategy.FORK
72 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.FORK);
73 case SchedStrategy.EXT
74 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.EXT);
75 case SchedStrategy.LCFSPR
76 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPR);
77 case SchedStrategy.LCFSPI
78 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPI);
79 case SchedStrategy.LCFSPRIO
80 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPRIO);
81 case SchedStrategy.LCFSPRPRIO
82 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPRPRIO);
83 case SchedStrategy.LCFSPIPRIO
84 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPIPRIO);
85 case SchedStrategy.PSPRIO % todo
86 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.PSPRIO);
87 case SchedStrategy.DPSPRIO % todo
88 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.DPSPRIO);
89 case SchedStrategy.GPSPRIO % todo
90 P{h} = javaObject('jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.GPSPRIO);
91 end
92 if sn.repl(h)~=1
93 P{h}.setReplication(sn.repl(h));
94 end
95 end
96
97 %% tasks
98 T = cell(1,sn.ntasks);
99 for t=1:sn.ntasks
100 tidx = sn.tshift+t;
101 if isinf(sn.mult(tidx))
102 sn_mult_tidx = java.lang.Integer.MAX_VALUE;
103 else
104 sn_mult_tidx = sn.mult(tidx);
105 end
106 % Check if this is a CacheTask
107 if sn.iscache(tidx)
108 % Get replacement strategy from ordinal
109 switch sn.replacestrat(tidx)
110 case ReplacementStrategy.RR
111 jReplacestrat = jline.lang.constant.ReplacementStrategy.RR;
112 case ReplacementStrategy.FIFO
113 jReplacestrat = jline.lang.constant.ReplacementStrategy.FIFO;
114 case ReplacementStrategy.SFIFO
115 jReplacestrat = jline.lang.constant.ReplacementStrategy.SFIFO;
116 case ReplacementStrategy.LRU
117 jReplacestrat = jline.lang.constant.ReplacementStrategy.LRU;
118 otherwise
119 jReplacestrat = jline.lang.constant.ReplacementStrategy.FIFO;
120 end
121 T{t} = javaObject('jline.lang.layered.CacheTask', model, sn.names{tidx}, sn.nitems(tidx), sn.itemcap{tidx}, jReplacestrat, sn_mult_tidx);
122 elseif sn.isfunction(tidx)
123 % FunctionTask (has setupTime/delayOffTime)
124 jSchedStrategy = JLINE.to_jline_sched_strategy(sn.sched(tidx));
125 T{t} = javaObject('jline.lang.layered.FunctionTask', model, sn.names{tidx}, sn_mult_tidx, jSchedStrategy);
126 else
127 jSchedStrategy = JLINE.to_jline_sched_strategy(sn.sched(tidx));
128 T{t} = javaObject('jline.lang.layered.Task', model, sn.names{tidx}, sn_mult_tidx, jSchedStrategy);
129 end
130 T{t}.on(P{sn.parent(tidx)});
131 if sn.repl(tidx)~=1
132 T{t}.setReplication(sn.repl(tidx));
133 end
134 if ~isempty(sn.think{tidx}) && sn.think_type(tidx) ~= ProcessType.DISABLED
135 switch sn.think_type(tidx)
136 case ProcessType.IMMEDIATE
137 T{t}.setThinkTime(jline.lang.processes.Immediate);
138 case ProcessType.EXP
139 T{t}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(tidx)));
140 case ProcessType.ERLANG
141 T{t}.setThinkTime(jline.lang.processes.Erlang.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
142 case ProcessType.HYPEREXP
143 if ~isempty(sn.think_params{tidx}) && length(sn.think_params{tidx}) >= 3
144 T{t}.setThinkTime(jline.lang.processes.HyperExp(sn.think_params{tidx}(1), sn.think_params{tidx}(2), sn.think_params{tidx}(3)));
145 else
146 T{t}.setThinkTime(jline.lang.processes.HyperExp.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
147 end
148 case ProcessType.COXIAN
149 T{t}.setThinkTime(jline.lang.processes.Coxian.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
150 case ProcessType.APH
151 T{t}.setThinkTime(jline.lang.processes.APH.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
152 case ProcessType.PH
153 if ~isempty(sn.think_proc{tidx})
154 proc = sn.think_proc{tidx};
155 T{t}.setThinkTime(jline.lang.processes.PH(JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2})));
156 else
157 T{t}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(tidx)));
158 end
159 case ProcessType.MAP
160 if ~isempty(sn.think_proc{tidx})
161 proc = sn.think_proc{tidx};
162 T{t}.setThinkTime(jline.lang.processes.MAP(JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2})));
163 else
164 T{t}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(tidx)));
165 end
166 otherwise
167 line_error(mfilename,sprintf('JLINE conversion does not support the %s distribution for task think time yet.',char(sn.think_type(tidx))));
168 end
169 end
170 % Setup time
171 if sn.isfunction(tidx) && ~isnan(sn.setuptime_mean(tidx)) && sn.setuptime_mean(tidx) > 1e-8
172 T{t}.setSetupTime(sn.setuptime_mean(tidx));
173 end
174 % Delay-off time
175 if sn.isfunction(tidx) && ~isnan(sn.delayofftime_mean(tidx)) && sn.delayofftime_mean(tidx) > 1e-8
176 T{t}.setDelayOffTime(sn.delayofftime_mean(tidx));
177 end
178 end
179 %% entries
180 E = cell(1,sn.nentries);
181 for e=1:sn.nentries
182 eidx = sn.eshift+e;
183 % Check if this is an ItemEntry (has nitems > 0)
184 if sn.nitems(eidx) > 0
185 % ItemEntry requires cardinality and popularity distribution
186 if ~isempty(sn.itemproc) && ~isempty(sn.itemproc{eidx})
187 jPopularity = JLINE.from_line_distribution(sn.itemproc{eidx});
188 else
189 % Default to uniform distribution
190 jPopularity = javaObject('jline.lang.processes.DiscreteSampler', jline.util.matrix.Matrix.uniformDistribution(sn.nitems(eidx)));
191 end
192 E{e} = javaObject('jline.lang.layered.ItemEntry', model, sn.names{eidx}, sn.nitems(eidx), jPopularity);
193 else
194 E{e} = javaObject('jline.lang.layered.Entry', model, sn.names{eidx});
195 end
196 E{e}.on(T{sn.parent(eidx)-sn.tshift});
197 end
198
199 %% activities
200 A = cell(1,sn.nacts);
201 for a=1:sn.nacts
202 aidx = sn.ashift+a;
203 tidx = sn.parent(aidx);
204 onTask = tidx-sn.tshift;
205 % Convert host demand from primitives to Java distribution
206 switch sn.hostdem_type(aidx)
207 case ProcessType.IMMEDIATE
208 jHostDem = jline.lang.processes.Immediate;
209 case ProcessType.DISABLED
210 jHostDem = jline.lang.processes.Disabled;
211 case ProcessType.EXP
212 jHostDem = javaObject('jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
213 case ProcessType.ERLANG
214 jHostDem = jline.lang.processes.Erlang.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
215 case ProcessType.HYPEREXP
216 if ~isempty(sn.hostdem_params{aidx}) && length(sn.hostdem_params{aidx}) >= 3
217 jHostDem = javaObject('jline.lang.processes.HyperExp', sn.hostdem_params{aidx}(1), sn.hostdem_params{aidx}(2), sn.hostdem_params{aidx}(3));
218 else
219 jHostDem = jline.lang.processes.HyperExp.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
220 end
221 case ProcessType.COXIAN
222 jHostDem = jline.lang.processes.Coxian.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
223 case ProcessType.APH
224 jHostDem = jline.lang.processes.APH.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
225 case ProcessType.PH
226 if ~isempty(sn.hostdem_proc{aidx})
227 proc = sn.hostdem_proc{aidx};
228 jHostDem = javaObject('jline.lang.processes.PH', JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2}));
229 else
230 jHostDem = javaObject('jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
231 end
232 case ProcessType.MAP
233 if ~isempty(sn.hostdem_proc{aidx})
234 proc = sn.hostdem_proc{aidx};
235 jHostDem = javaObject('jline.lang.processes.MAP', JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2}));
236 else
237 jHostDem = javaObject('jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
238 end
239 case ProcessType.DET
240 jHostDem = javaObject('jline.lang.processes.Det', sn.hostdem_mean(aidx));
241 otherwise
242 line_error(mfilename,sprintf('JLINE conversion does not support the %s distribution for host demand yet.',char(sn.hostdem_type(aidx))));
243 end
244 A{a} = javaObject('jline.lang.layered.Activity', model, sn.names{aidx}, jHostDem);
245 A{a}.on(T{onTask});
246
247 boundTo = find(sn.graph((sn.eshift+1):(sn.eshift+sn.nentries),aidx));
248
249 if ~isempty(boundTo)
250 A{a}.boundTo(E{boundTo});
251 end
252
253 if sn.sched(tidx) ~= SchedStrategy.REF % ref tasks don't reply
254 repliesTo = find(sn.replygraph(a,:)); % index of entry
255 if ~isempty(repliesTo)
256 if ~sn.isref(sn.parent(sn.eshift+repliesTo))
257 A{a}.repliesTo(E{repliesTo});
258 end
259 end
260 end
261
262 if ~isempty(sn.callpair)
263 cidxs = find(sn.callpair(:,1)==aidx);
264 calls = sn.callpair(:,2);
265 for c = cidxs(:)'
266 switch sn.calltype(c)
267 case CallType.SYNC
268 A{a}.synchCall(E{calls(c)-sn.eshift},sn.callproc_mean(c));
269 case CallType.ASYNC
270 A{a}.asynchCall(E{calls(c)-sn.eshift},sn.callproc_mean(c));
271 end
272 end
273 end
274
275 end
276
277 %% think times
278 for h=1:sn.nhosts
279 if ~isempty(sn.think{h}) && sn.think_type(h) ~= ProcessType.DISABLED
280 switch sn.think_type(h)
281 case ProcessType.IMMEDIATE
282 P{h}.setThinkTime(jline.lang.processes.Immediate);
283 case ProcessType.EXP
284 P{h}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(h)));
285 case ProcessType.ERLANG
286 P{h}.setThinkTime(jline.lang.processes.Erlang.fitMeanAndSCV(sn.think_mean(h),sn.think_scv(h)));
287 case ProcessType.HYPEREXP
288 % For HyperExp, reconstruct from params if available, otherwise use fitMeanAndSCV
289 if ~isempty(sn.think_params{h}) && length(sn.think_params{h}) >= 3
290 P{h}.setThinkTime(jline.lang.processes.HyperExp(sn.think_params{h}(1), sn.think_params{h}(2), sn.think_params{h}(3)));
291 else
292 P{h}.setThinkTime(jline.lang.processes.HyperExp.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
293 end
294 case ProcessType.COXIAN
295 % For Coxian, use fitMeanAndSCV
296 P{h}.setThinkTime(jline.lang.processes.Coxian.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
297 case ProcessType.APH
298 % For APH, reconstruct from params if available
299 if ~isempty(sn.think_params{h})
300 P{h}.setThinkTime(jline.lang.processes.APH.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
301 else
302 P{h}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(h)));
303 end
304 otherwise
305 line_error(mfilename,sprintf('JLINE conversion does not support the %s distribution yet.',char(sn.think_type(h))));
306 end
307 end
308 end
309
310 %% Sequential precedences
311 for ai = 1:sn.nacts
312 aidx = sn.ashift + ai;
313 tidx = sn.parent(aidx);
314 % for all successors
315 for bidx=find(sn.graph(aidx,:))
316 if bidx > sn.ashift % ignore precedence between entries and activities
317 % Serial pattern (SEQ)
318 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_SEQ && full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_SEQ
319 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.Serial(sn.names{aidx}, sn.names{bidx}));
320 end
321 end
322 end
323 end
324
325 %%%%%%%%%%%%%%%%%%%%%%%%%%% translated up to here
326
327 %% Loop precedences (POST_LOOP)
328 % Loop structure in sn.graph:
329 % - Entry activity (preAct) has edge to first loop body activity
330 % - Last loop body activity has back-edge to first loop body (weight = 1-1/counts)
331 % - Last loop body activity has edge to end activity (weight = 1/counts)
332 % - All loop body and end activities have POST_LOOP type
333 processedLoops = false(1, sn.nacts);
334 for ai = 1:sn.nacts
335 aidx = sn.ashift + ai;
336 tidx = sn.parent(aidx);
337 % Check if this activity starts a loop (has a successor with POST_LOOP type)
338 % and hasn't been processed as part of another loop
339 if processedLoops(ai)
340 continue;
341 end
342
343 successors = find(sn.graph(aidx,:));
344 for bidx = successors
345 if bidx > sn.ashift && full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_LOOP
346 % Skip if this loop body activity was already processed
347 if processedLoops(bidx - sn.ashift)
348 continue;
349 end
350 % Found start of a loop: aidx is the entry, bidx is first loop body activity
351 loopStart = bidx;
352 precActs = java.util.ArrayList();
353
354 % Follow the chain of POST_LOOP activities
355 curIdx = loopStart;
356 while true
357 precActs.add(sprintf("%s", sn.names{curIdx}));
358 processedLoops(curIdx - sn.ashift) = true;
359
360 % Find successors of current activity
361 curSuccessors = find(sn.graph(curIdx,:));
362 curSuccessors = curSuccessors(curSuccessors > sn.ashift);
363
364 % Check for loop termination: find the end activity
365 % End activity has weight = 1/counts (not the back-edge weight)
366 endIdx = 0;
367 nextIdx = 0;
368 for succIdx = curSuccessors
369 if full(sn.actposttype(succIdx)) == ActivityPrecedenceType.POST_LOOP
370 if succIdx == loopStart
371 % This is the back-edge, skip it
372 continue;
373 end
374 weight = full(sn.graph(curIdx, succIdx));
375 if weight > 0 && weight < 1
376 % This is the end activity (weight = 1/counts)
377 endIdx = succIdx;
378 else
379 % This is the next activity in the loop body (weight = 1.0)
380 nextIdx = succIdx;
381 end
382 end
383 end
384
385 if endIdx > 0
386 % Found end activity - calculate counts and output
387 weight = full(sn.graph(curIdx, endIdx));
388 if weight > 0
389 counts = 1/weight;
390 else
391 counts = 1; % Fallback to prevent division by zero
392 end
393 precActs.add(sprintf("%s", sn.names{endIdx}));
394 processedLoops(endIdx - sn.ashift) = true;
395
396 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.Loop(sn.names{aidx}, precActs, jline.util.matrix.Matrix(counts)));
397 break;
398 elseif nextIdx > 0
399 % Continue to next activity in loop body
400 curIdx = nextIdx;
401 else
402 % No more successors - shouldn't happen in valid loop
403 break;
404 end
405 end
406 break; % Only process one loop starting from this activity
407 end
408 end
409 end
410
411 %% OrFork precedences (POST_OR)
412 precMarker = 0;
413 for ai = 1:sn.nacts
414 probs = [];
415 aidx = sn.ashift + ai;
416 tidx = sn.parent(aidx);
417 prob_ctr = 0;
418 % for all successors
419 for bidx=find(sn.graph(aidx,:))
420 if bidx > sn.ashift % ignore precedence between entries and activities
421 % Or pattern (POST_OR)
422 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_OR
423 if precMarker == 0 % start a new orjoin
424 precActs = java.util.ArrayList();
425 precMarker = aidx-sn.ashift;
426 precActs.add(sprintf("%s", sn.names{bidx}));
427 probs=full(sn.graph(aidx,bidx));
428 else
429 precActs.add(sprintf("%s", sn.names{bidx}));
430 probs(end+1)=full(sn.graph(aidx,bidx));
431 end
432 end
433 end
434 end
435
436
437 if precMarker > 0
438 probsMatrix = jline.util.matrix.Matrix(1,length(probs));
439 for i=1:length(probs)
440 probsMatrix.set(0,i-1,probs(i));
441 end
442 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.OrFork(sn.names{precMarker+sn.ashift}, precActs, probsMatrix));
443 precMarker = 0;
444 end
445 end
446
447 %% AndFork precedences (POST_AND)
448 precMarker = 0;
449 postActs = '';
450 for ai = 1:sn.nacts
451 aidx = sn.ashift + ai;
452 tidx = sn.parent(aidx);
453 % for all successors
454 for bidx=find(sn.graph(aidx,:))
455 if bidx > sn.ashift % ignore precedence between entries and activities
456 % Or pattern (POST_AND)
457 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_AND
458 if isempty(postActs)
459 postActs = java.util.ArrayList();
460 postActs.add(sprintf("%s", sn.names{bidx}));
461 else
462 postActs.add(sprintf("%s", sn.names{bidx}));
463 end
464
465 if precMarker == 0 % start a new orjoin
466 precMarker = aidx-sn.ashift;
467 end
468 end
469 end
470 end
471 if precMarker > 0
472 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndFork(sn.names{precMarker+sn.ashift}, postActs));
473 precMarker = 0;
474 end
475 end
476
477 %% CacheAccess precedences (POST_CACHE)
478 precMarker = 0;
479 postActs = '';
480 for ai = 1:sn.nacts
481 aidx = sn.ashift + ai;
482 tidx = sn.parent(aidx);
483 % for all successors
484 for bidx=find(sn.graph(aidx,:))
485 if bidx > sn.ashift % ignore precedence between entries and activities
486 % CacheAccess pattern (POST_CACHE)
487 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_CACHE
488 if isempty(postActs)
489 postActs = java.util.ArrayList();
490 postActs.add(sprintf("%s", sn.names{bidx}));
491 else
492 postActs.add(sprintf("%s", sn.names{bidx}));
493 end
494
495 if precMarker == 0 % start a new cache access
496 precMarker = aidx-sn.ashift;
497 end
498 end
499 end
500 end
501 if precMarker > 0
502 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.CacheAccess(sn.names{precMarker+sn.ashift}, postActs));
503 precMarker = 0;
504 postActs = '';
505 end
506 end
507
508 %% OrJoin precedences (PRE_OR)
509 precMarker = 0;
510 for bi = sn.nacts:-1:1
511 bidx = sn.ashift + bi;
512 tidx = sn.parent(bidx);
513 % for all predecessors
514 for aidx=find(sn.graph(:,bidx))'
515 if aidx > sn.ashift % ignore precedence between entries and activities
516 % OrJoin pattern (PRE_OR)
517 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_OR
518 if precMarker == 0 % start a new orjoin
519 precActs = java.util.ArrayList();
520 precMarker = bidx-sn.ashift;
521 precActs.add(sprintf("%s", sn.names{aidx}));
522 else
523 precActs.add(sprintf("%s", sn.names{aidx}));
524 end
525 end
526 end
527 end
528 if precMarker > 0
529 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.OrJoin(precActs, sn.names{precMarker+sn.ashift}));
530 precMarker = 0;
531 end
532 end
533
534 %% AndJoin precedences (PRE_AND)
535 precMarker = 0;
536 for bi = sn.nacts:-1:1
537 bidx = sn.ashift + bi;
538 tidx = sn.parent(bidx);
539 % for all predecessors
540 for aidx=find(sn.graph(:,bidx))'
541 if aidx > sn.ashift % ignore precedence between entries and activities
542 % OrJoin pattern (PRE_AND)
543 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_AND
544 if precMarker == 0 % start a new orjoin
545 precActs = java.util.ArrayList();
546 precMarker = bidx-sn.ashift;
547 precActs.add(sprintf("%s", sn.names{aidx}));
548 else
549 precActs.add(sprintf("%s", sn.names{aidx}));
550 end
551 end
552 end
553 end
554 if precMarker > 0
555 % Find quorum parameter from original precedence structure
556 postActName = sn.names{precMarker+sn.ashift};
557 localTaskIdx = tidx - sn.tshift;
558 quorum = [];
559 for ap = 1:length(line_layered_network.tasks{localTaskIdx}.precedences)
560 precedence = line_layered_network.tasks{localTaskIdx}.precedences(ap);
561 if precedence.preType == ActivityPrecedenceType.PRE_AND
562 % Check if this precedence contains our post activity
563 if any(strcmp(precedence.postActs, postActName))
564 quorum = precedence.preParams;
565 break;
566 end
567 end
568 end
569
570 if isempty(quorum)
571 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndJoin(precActs, sn.names{precMarker+sn.ashift}));
572 else
573 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndJoin(precActs, sn.names{precMarker+sn.ashift}, quorum));
574 end
575 precMarker = 0;
576 end
577 end
578
579 end
580
581 function jdist = from_line_distribution(line_dist)
582 if isa(line_dist, 'Exp')
583 jdist = javaObject('jline.lang.processes.Exp', line_dist.getParam(1).paramValue);
584 elseif isa(line_dist, "APH")
585 alpha = line_dist.getParam(1).paramValue;
586 T = line_dist.getParam(2).paramValue;
587 jline_alpha = java.util.ArrayList();
588 for i = 1:length(alpha)
589 jline_alpha.add(alpha(i));
590 end
591 jline_T = JLINE.from_line_matrix(T);
592 jdist = javaObject('jline.lang.processes.APH', jline_alpha, jline_T);
593 elseif isa(line_dist, 'Coxian')
594 jline_mu = java.util.ArrayList();
595 jline_phi = java.util.ArrayList();
596 if length(line_dist.params) == 3
597 jline_mu.add(line_dist.getParam(1).paramValue);
598 jline_mu.add(line_dist.getParam(2).paramValue);
599 jline_phi.add(line_dist.getParam(3).paramValue);
600 else
601 mu = line_dist.getParam(1).paramValue;
602 phi = line_dist.getParam(2).paramValue;
603 for i = 1:length(mu)
604 jline_mu.add(mu(i));
605 end
606 for i = 1:length(phi)
607 jline_phi.add(phi(i));
608 end
609 end
610 jdist = javaObject('jline.lang.processes.Coxian', jline_mu, jline_phi);
611 elseif isa(line_dist, 'Det')
612 jdist = javaObject('jline.lang.processes.Det', line_dist.getParam(1).paramValue);
613 elseif isa(line_dist, 'DiscreteSampler')
614 popularity_p = JLINE.from_line_matrix(line_dist.getParam(1).paramValue);
615 popularity_val = JLINE.from_line_matrix(line_dist.getParam(2).paramValue);
616 jdist = javaObject('jline.lang.processes.DiscreteSampler', popularity_p, popularity_val);
617 elseif isa(line_dist, 'Erlang')
618 jdist = javaObject('jline.lang.processes.Erlang', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
619 elseif isa(line_dist, 'Gamma')
620 jdist = javaObject('jline.lang.processes.Gamma', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
621 elseif isa(line_dist, "HyperExp")
622 jdist = javaObject('jline.lang.processes.HyperExp', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue, line_dist.getParam(3).paramValue);
623 elseif isa(line_dist, 'Lognormal')
624 jdist = javaObject('jline.lang.processes.Lognormal', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
625 elseif isa(line_dist, 'Pareto')
626 jdist = javaObject('jline.lang.processes.Pareto', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
627 elseif isa(line_dist, 'MAP')
628 D0 = line_dist.D(0);
629 D1 = line_dist.D(1);
630 jdist = javaObject('jline.lang.processes.MAP', JLINE.from_line_matrix(D0), JLINE.from_line_matrix(D1));
631 elseif isa(line_dist, 'MMPP2')
632 lambda0 = line_dist.getParam(1).paramValue;
633 lambda1 = line_dist.getParam(2).paramValue;
634 sigma0 = line_dist.getParam(3).paramValue;
635 sigma1 = line_dist.getParam(4).paramValue;
636 jdist = javaObject('jline.lang.processes.MMPP2', lambda0, lambda1, sigma0, sigma1);
637 elseif isa(line_dist, 'PH')
638 alpha = line_dist.getParam(1).paramValue;
639 T = line_dist.getParam(2).paramValue;
640 jdist = javaObject('jline.lang.processes.PH', JLINE.from_line_matrix(alpha), JLINE.from_line_matrix(T));
641 elseif isa(line_dist, 'Uniform')
642 jdist = javaObject('jline.lang.processes.Uniform', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
643 elseif isa(line_dist, 'Weibull')
644 jdist = javaObject('jline.lang.processes.Weibull', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
645 elseif isa(line_dist, 'Zipf')
646 jdist = javaObject('jline.lang.processes.Zipf', line_dist.getParam(3).paramValue, line_dist.getParam(4).paramValue);
647 elseif isa(line_dist, 'Immediate')
648 jdist = javaObject('jline.lang.processes.Immediate');
649 elseif isempty(line_dist) || isa(line_dist, 'Disabled')
650 jdist = javaObject('jline.lang.processes.Disabled');
651 return;
652 elseif isa(line_dist, 'Replayer')
653 jdist = javaObject('jline.lang.processes.Replayer', line_dist.params{1}.paramValue);
654 elseif isa(line_dist, 'Trace')
655 jdist = javaObject('jline.lang.processes.Trace', line_dist.params{1}.paramValue);
656 elseif isa(line_dist, 'Prior')
657 % Convert Prior: each alternative is a distribution
658 dists = line_dist.getParam(1).paramValue;
659 probs = line_dist.getParam(2).paramValue;
660 jdists = java.util.ArrayList();
661 for k = 1:length(dists)
662 jdists.add(JLINE.from_line_distribution(dists{k}));
663 end
664 jdist = javaObject('jline.lang.processes.Prior', jdists, probs);
665 else
666 line_error(mfilename,'Distribution not supported by JLINE.');
667 end
668 end
669
670 function matlab_dist = from_jline_distribution(jdist)
671 if isa(jdist, 'jline.lang.processes.Exp')
672 matlab_dist = Exp(jdist.getRate());
673 elseif isa(jdist, 'jline.lang.processes.Det')
674 matlab_dist = Det(jdist.getParam(1).getValue);
675 elseif isa(jdist, 'jline.lang.processes.Erlang')
676 matlab_dist = Erlang(jdist.getParam(1).getValue(),jdist.getNumberOfPhases());
677 elseif isa(jdist, 'jline.lang.processes.Gamma')
678 matlab_dist = Gamma(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
679 elseif isa(jdist, 'jline.lang.processes.HyperExp')
680 matlab_dist = HyperExp(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue);
681 elseif isa(jdist, 'jline.lang.processes.Lognormal')
682 matlab_dist = Lognormal(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
683 elseif isa(jdist, 'jline.lang.processes.Pareto')
684 matlab_dist = Pareto(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
685 elseif isa(jdist, 'jline.lang.processes.Uniform')
686 matlab_dist = Uniform(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
687 elseif isa(jdist, 'jline.lang.processes.Weibull')
688 matlab_dist = Weibull(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
689 elseif isa(jdist, 'jline.lang.processes.MAP')
690 D0 = JLINE.from_jline_matrix(jdist.D(0));
691 D1 = JLINE.from_jline_matrix(jdist.D(1));
692 matlab_dist = MAP({D0, D1});
693 elseif isa(jdist, 'jline.lang.processes.APH')
694 alpha = JLINE.from_jline_matrix(jdist.getInitProb());
695 T = JLINE.from_jline_matrix(jdist.getSubgenerator());
696 matlab_dist = APH(alpha(:)', T);
697 elseif isa(jdist, 'jline.lang.processes.PH')
698 alpha = JLINE.from_jline_matrix(jdist.getInitProb());
699 T = JLINE.from_jline_matrix(jdist.getSubgenerator());
700 matlab_dist = PH(alpha(:)', T);
701 elseif isa(jdist, 'jline.lang.processes.Coxian')
702 if jdist.getNumberOfPhases == 2
703 matlab_dist = Coxian([jdist.getParam(1).getValue.get(0), jdist.getParam(1).getValue.get(1)], [jdist.getParam(2).getValue.get(0),1]);
704 else
705 jmu = jdist.getParam(1).getValue;
706 jphi = jdist.getParam(2).getValue;
707 mu = zeros(1, jmu.size);
708 phi = zeros(1, jphi.size);
709 for i = 1:jmu.size
710 mu(i) = jmu.get(i-1);
711 end
712 for i = 1:jphi.size
713 phi(i) = jphi.get(i-1);
714 end
715 matlab_dist = Coxian(mu, phi);
716 end
717 elseif isa(jdist, 'jline.lang.processes.Zipf')
718 matlab_dist = Zipf(jdist.getParam(3).getValue, jdist.getParam(4).getValue);
719 elseif isa(jdist, 'jline.lang.processes.DiscreteSampler')
720 jpMat = jdist.getParam(1).getValue;
721 jxMat = jdist.getParam(2).getValue;
722 p = zeros(1, jpMat.length);
723 x = zeros(1, jxMat.length);
724 for i = 1:jpMat.length
725 p(i) = jpMat.get(i-1);
726 end
727 for i = 1:jxMat.length
728 x(i) = jxMat.get(i-1);
729 end
730 matlab_dist = DiscreteSampler(p, x);
731 elseif isa(jdist, 'jline.lang.processes.Immediate')
732 matlab_dist = Immediate();
733 elseif isa(jdist, 'jline.lang.processes.Disabled')
734 matlab_dist = Disabled();
735 elseif isa(jdist, 'jline.lang.processes.MMPP2')
736 matlab_dist = MMPP2(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue, jdist.getParam(4).getValue);
737 elseif isa(jdist, 'jline.lang.processes.Prior')
738 % Convert Prior from JAR to MATLAB
739 jdists = jdist.getDistributions();
740 nalt = jdists.size();
741 dists = cell(1, nalt);
742 for k = 1:nalt
743 dists{k} = JLINE.from_jline_distribution(jdists.get(k-1));
744 end
745 probs = jdist.getProbabilities();
746 matlab_dist = Prior(dists, probs);
747 else
748 line_error(mfilename,'Distribution not supported by JLINE.');
749 end
750 end
751
752 function set_csMatrix(line_node, jnode, jclasses)
753 nClasses = length(line_node.model.classes);
754 csMatrix = jnode.initClassSwitchMatrix();
755 for i = 1:nClasses
756 for j = 1:nClasses
757 csMatrix.set(jclasses{i}, jclasses{j}, line_node.server.csFun(i,j,0,0));
758 end
759 end
760 jnode.setClassSwitchingMatrix(csMatrix);
761 end
762
763 function set_service(line_node, jnode, job_classes)
764 if (isa(line_node, 'Sink') || isa(line_node, 'Router') || isa(line_node, 'Cache') || isa(line_node, 'Logger') || isa(line_node, 'ClassSwitch') || isa(line_node, 'Fork') || isa(line_node, 'Join') || isa(line_node, 'Place') || isa(line_node, 'Transition'))
765 return;
766 end
767
768 for n = 1 : length(job_classes)
769 if (isa(line_node, 'Queue') || isa(line_node, 'Delay'))
770 matlab_dist = line_node.getService(job_classes{n});
771 elseif (isa(line_node, 'Source'))
772 matlab_dist = line_node.getArrivalProcess(job_classes{n});
773 else
774 line_error(mfilename,'Node not supported by JLINE.');
775 end
776 service_dist = JLINE.from_line_distribution(matlab_dist);
777
778 if (isa(line_node,'Queue') || isa(line_node, 'Delay'))
779 jnode.setService(jnode.getModel().getClasses().get(n-1), service_dist, line_node.schedStrategyPar(n));
780 elseif (isa(line_node, 'Source'))
781 jnode.setArrival(jnode.getModel().getClasses().get(n-1), service_dist);
782 end
783 end
784 end
785
786 function set_delayoff(line_node, jnode, job_classes)
787 % Transfer setup and delayoff times from MATLAB Queue to Java Queue
788 if ~isa(line_node, 'Queue')
789 return;
790 end
791
792 % Check if setupTime property exists and is not empty
793 if ~isprop(line_node, 'setupTime') || isempty(line_node.setupTime)
794 return;
795 end
796
797 for n = 1 : length(job_classes)
798 c = job_classes{n}.index;
799 % Check if both setupTime and delayoffTime are set for this class
800 if c <= length(line_node.setupTime) && ~isempty(line_node.setupTime{1, c}) && ...
801 c <= length(line_node.delayoffTime) && ~isempty(line_node.delayoffTime{1, c})
802 % Convert MATLAB distributions to Java distributions
803 setup_dist = JLINE.from_line_distribution(line_node.setupTime{1, c});
804 delayoff_dist = JLINE.from_line_distribution(line_node.delayoffTime{1, c});
805 % Set delayoff on the Java Queue
806 jnode.setDelayOff(jnode.getModel().getClasses().get(n-1), setup_dist, delayoff_dist);
807 end
808 end
809 end
810
811 function set_line_service(jline_node, line_node, job_classes, line_classes)
812 if (isa(line_node,'Sink')) || isa(line_node, 'ClassSwitch') || isa(line_node, 'Fork') || isa(line_node, 'Join') || isa(line_node, 'Place') || isa(line_node, 'Transition') || isa(line_node, 'Cache')
813 return;
814 end
815 for n = 1:job_classes.size()
816 if (isa(line_node, 'Queue') || isa(line_node, 'Delay'))
817 jdist = jline_node.getServiceProcess(job_classes.get(n-1));
818 matlab_dist = JLINE.from_jline_distribution(jdist);
819 weight = jline_node.getSchedStrategyPar(job_classes.get(n-1));
820 line_node.setService(line_classes{n}, matlab_dist, weight);
821 elseif (isa(line_node, 'Source'))
822 jdist = jline_node.getArrivalProcess(job_classes.get(n-1));
823 matlab_dist = JLINE.from_jline_distribution(jdist);
824 line_node.setArrival(line_classes{n}, matlab_dist);
825 elseif (isa(line_node, 'Router'))
826 % no-op
827 else
828 line_error(mfilename,'Node not supported by JLINE.');
829 end
830 end
831 end
832
833 function node_object = from_line_node(line_node, jnetwork, ~, forkNode, sn)
834 % Handle optional sn argument
835 if nargin < 5
836 sn = [];
837 end
838 if isa(line_node, 'Delay')
839 node_object = javaObject('jline.lang.nodes.Delay', jnetwork, line_node.getName);
840 elseif isa(line_node, 'Queue')
841 switch line_node.schedStrategy
842 case SchedStrategy.INF
843 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.INF);
844 case SchedStrategy.FCFS
845 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFS);
846 case SchedStrategy.LCFS
847 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFS);
848 case SchedStrategy.SIRO
849 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SIRO);
850 case SchedStrategy.SJF
851 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SJF);
852 case SchedStrategy.LJF
853 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LJF);
854 case SchedStrategy.PS
855 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PS);
856 case SchedStrategy.DPS
857 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.DPS);
858 case SchedStrategy.GPS
859 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.GPS);
860 case SchedStrategy.SEPT
861 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SEPT);
862 case SchedStrategy.LEPT
863 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LEPT);
864 case {SchedStrategy.HOL, SchedStrategy.FCFSPRIO}
865 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPRIO);
866 case SchedStrategy.FORK
867 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FORK);
868 case SchedStrategy.EXT
869 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.EXT);
870 case SchedStrategy.REF
871 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.REF);
872 case SchedStrategy.LCFSPR
873 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPR);
874 case SchedStrategy.LCFSPI
875 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPI);
876 case SchedStrategy.LCFSPRIO
877 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPRIO);
878 case SchedStrategy.LCFSPRPRIO
879 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPRPRIO);
880 case SchedStrategy.LCFSPIPRIO
881 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPIPRIO);
882 case SchedStrategy.FCFSPR
883 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPR);
884 case SchedStrategy.FCFSPI
885 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPI);
886 case SchedStrategy.FCFSPRPRIO
887 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPRPRIO);
888 case SchedStrategy.FCFSPIPRIO
889 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPIPRIO);
890 case SchedStrategy.PSPRIO
891 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PSPRIO);
892 case SchedStrategy.DPSPRIO
893 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.DPSPRIO);
894 case SchedStrategy.GPSPRIO
895 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.GPSPRIO);
896 case SchedStrategy.POLLING
897 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.POLLING);
898 case SchedStrategy.SRPT
899 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SRPT);
900 case SchedStrategy.SRPTPRIO
901 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SRPTPRIO);
902 case SchedStrategy.PSJF
903 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PSJF);
904 case SchedStrategy.FB
905 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FB);
906 case SchedStrategy.LRPT
907 node_object = javaObject('jline.lang.nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LRPT);
908 end
909 nservers = line_node.getNumberOfServers;
910 if isinf(nservers)
911 node_object.setNumberOfServers(java.lang.Integer.MAX_VALUE);
912 elseif nservers > 1
913 node_object.setNumberOfServers(line_node.getNumberOfServers);
914 end
915 if ~isempty(line_node.lldScaling)
916 node_object.setLoadDependence(JLINE.from_line_matrix(line_node.lldScaling));
917 end
918 if ~isempty(line_node.lcdScaling)
919 if isempty(sn)
920 line_error(mfilename, "Class-dependent models require sn struct for MATLAB-to-JAVA translation.");
921 end
922 node_object.setLimitedClassDependence(JLINE.handle_to_serializablefun(line_node.lcdScaling, sn));
923 end
924 % Transfer LJD (Limited Joint Dependence) scaling
925 if ~isempty(line_node.ljdScaling) && ~isempty(line_node.ljdCutoffs)
926 jScaling = JLINE.from_line_matrix(line_node.ljdScaling(:));
927 jCutoffs = JLINE.from_line_matrix(line_node.ljdCutoffs(:));
928 node_object.setLimitedJointDependence(jScaling, jCutoffs);
929 end
930 % NOTE: LJCD (Limited Joint Class Dependence) is transferred in
931 % from_line_network after classes are created
932 % Set queue capacity if finite
933 if ~isinf(line_node.cap)
934 node_object.setCapacity(line_node.cap);
935 end
936 elseif isa(line_node, 'Source')
937 node_object = javaObject('jline.lang.nodes.Source', jnetwork, line_node.getName);
938 elseif isa(line_node, 'Sink')
939 node_object = javaObject('jline.lang.nodes.Sink', jnetwork, line_node.getName);
940 elseif isa(line_node, 'Router')
941 node_object = javaObject('jline.lang.nodes.Router', jnetwork, line_node.getName);
942 elseif isa(line_node, 'ClassSwitch')
943 node_object = javaObject('jline.lang.nodes.ClassSwitch', jnetwork, line_node.getName);
944 elseif isa(line_node, 'Fork')
945 node_object = javaObject('jline.lang.nodes.Fork', jnetwork, line_node.name);
946 node_object.setTasksPerLink(line_node.output.tasksPerLink);
947 elseif isa(line_node, 'Join')
948 node_object = javaObject('jline.lang.nodes.Join', jnetwork, line_node.name, forkNode);
949 elseif isa(line_node, 'Logger')
950 node_object = javaObject('jline.lang.nodes.Logger', jnetwork, line_node.name, [line_node.filePath,line_node.fileName]);
951 elseif isa(line_node, 'Cache')
952 nitems = line_node.items.nitems;
953 switch line_node.replacestrategy
954 case ReplacementStrategy.RR
955 repStrategy = jline.lang.constant.ReplacementStrategy.RR;
956 case ReplacementStrategy.FIFO
957 repStrategy = jline.lang.constant.ReplacementStrategy.FIFO;
958 case ReplacementStrategy.SFIFO
959 repStrategy = jline.lang.constant.ReplacementStrategy.SFIFO;
960 case ReplacementStrategy.LRU
961 repStrategy = jline.lang.constant.ReplacementStrategy.LRU;
962 end
963 if ~isempty(line_node.graph)
964 node_object = javaObject('jline.lang.nodes.Cache', jnetwork, line_node.name, nitems, JLINE.from_line_matrix(line_node.itemLevelCap), repStrategy, JLINE.from_line_matrix(line_node.graph));
965 else
966 node_object = javaObject('jline.lang.nodes.Cache', jnetwork, line_node.name, nitems, JLINE.from_line_matrix(line_node.itemLevelCap), repStrategy);
967 end
968 elseif isa(line_node, 'Place')
969 node_object = javaObject('jline.lang.nodes.Place', jnetwork, line_node.getName);
970 elseif isa(line_node, 'Transition')
971 node_object = javaObject('jline.lang.nodes.Transition', jnetwork, line_node.getName);
972 % Modes are added later in from_line_network after classes are created
973 else
974 line_error(mfilename,'Node not supported by JLINE.');
975 end
976 end
977
978 function node_object = from_jline_node(jline_node, model, job_classes)
979 if isa(jline_node, 'jline.lang.nodes.Delay')
980 node_object = Delay(model, jline_node.getName.toCharArray');
981 elseif isa(jline_node, 'jline.lang.nodes.Queue')
982 schedStrategy = jline_node.getSchedStrategy;
983 switch schedStrategy.name().toCharArray'
984 case 'INF'
985 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.INF);
986 case 'FCFS'
987 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFS);
988 case 'LCFS'
989 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFS);
990 case 'SIRO'
991 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SIRO);
992 case 'SJF'
993 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SJF);
994 case 'LJF'
995 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LJF);
996 case 'PS'
997 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.PS);
998 case 'DPS'
999 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.DPS);
1000 case 'GPS'
1001 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.GPS);
1002 case 'SEPT'
1003 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SEPT);
1004 case 'LEPT'
1005 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LEPT);
1006 case {'HOL', 'FCFSPRIO'}
1007 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPRIO);
1008 case 'FORK'
1009 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FORK);
1010 case 'EXT'
1011 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.EXT);
1012 case 'REF'
1013 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.REF);
1014 case 'LCFSPR'
1015 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPR);
1016 case 'SRPT'
1017 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SRPT);
1018 case 'SRPTPRIO'
1019 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SRPTPRIO);
1020 case 'PSJF'
1021 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.PSJF);
1022 case 'FB'
1023 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FB);
1024 case 'LRPT'
1025 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LRPT);
1026 case 'PSPRIO'
1027 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.PSPRIO);
1028 case 'DPSPRIO'
1029 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.DPSPRIO);
1030 case 'GPSPRIO'
1031 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.GPSPRIO);
1032 case 'LCFSPI'
1033 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPI);
1034 case 'LCFSPRIO'
1035 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPRIO);
1036 case 'LCFSPRPRIO'
1037 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPRPRIO);
1038 case 'LCFSPIPRIO'
1039 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPIPRIO);
1040 case 'FCFSPR'
1041 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPR);
1042 case 'FCFSPI'
1043 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPI);
1044 case 'FCFSPRPRIO'
1045 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPRPRIO);
1046 case 'FCFSPIPRIO'
1047 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPIPRIO);
1048 case 'POLLING'
1049 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.POLLING);
1050 end
1051 node_object.setNumberOfServers(jline_node.getNumberOfServers);
1052 cap = jline_node.getCap();
1053 if cap < intmax && cap > 0
1054 node_object.setCapacity(cap);
1055 end
1056 if ~isempty(JLINE.from_jline_matrix(jline_node.getLimitedLoadDependence))
1057 node_object.setLoadDependence(JLINE.from_jline_matrix(jline_node.getLimitedLoadDependence));
1058 end
1059 elseif isa(jline_node, 'jline.lang.nodes.Source')
1060 node_object = Source(model, jline_node.getName.toCharArray');
1061 elseif isa(jline_node, 'jline.lang.nodes.Sink')
1062 node_object = Sink(model, jline_node.getName.toCharArray');
1063 elseif isa(jline_node, 'jline.lang.nodes.Router')
1064 node_object = Router(model, jline_node.getName.toCharArray');
1065 elseif isa(jline_node, 'jline.lang.nodes.ClassSwitch')
1066 nClasses = job_classes.size;
1067 csMatrix = zeros(nClasses, nClasses);
1068 for r = 1:nClasses
1069 for s = 1:nClasses
1070 csMatrix(r,s) = jline_node.getServer.applyCsFun(r-1,s-1);
1071 end
1072 end
1073 node_object = ClassSwitch(model, jline_node.getName.toCharArray', csMatrix);
1074 elseif isa(jline_node, 'jline.lang.nodes.Cache')
1075 numItems = jline_node.getNumberOfItems();
1076 itemLevelCap = JLINE.from_jline_matrix(jline_node.getItemLevelCap());
1077 replPolicy = jline_node.getReplacementStrategy();
1078 switch char(replPolicy)
1079 case 'LRU'
1080 rp = ReplacementStrategy.LRU;
1081 case 'FIFO'
1082 rp = ReplacementStrategy.FIFO;
1083 case 'RR'
1084 rp = ReplacementStrategy.RR;
1085 otherwise
1086 rp = ReplacementStrategy.LRU;
1087 end
1088 node_object = Cache(model, jline_node.getName.toCharArray', numItems, itemLevelCap, rp);
1089 % hitClass, missClass, and popularity set later in jline_to_line
1090 elseif isa(jline_node, 'jline.lang.nodes.Fork')
1091 node_object = Fork(model, jline_node.getName.toCharArray');
1092 tpl = jline_node.getOutput().tasksPerLink;
1093 if tpl > 1
1094 node_object.setTasksPerLink(tpl);
1095 end
1096 elseif isa(jline_node, 'jline.lang.nodes.Join')
1097 node_object = Join(model, jline_node.getName.toCharArray');
1098 % joinOf is set later in jline_to_line after all nodes are created
1099 elseif isa(jline_node, 'jline.lang.nodes.Place')
1100 node_object = Place(model, jline_node.getName.toCharArray');
1101 elseif isa(jline_node, 'jline.lang.nodes.Transition')
1102 node_object = Transition(model, jline_node.getName.toCharArray');
1103 % Note: Mode configurations need to be set after classes are created
1104 else
1105 line_error(mfilename,'Node not supported by JLINE.');
1106 end
1107 end
1108
1109 function node_class = from_line_class(line_class, jnetwork)
1110 % Check signal classes first (before their base classes)
1111 if isa(line_class, 'ClosedSignal')
1112 % ClosedSignal -> jline.lang.ClosedSignal
1113 jSignalType = jline.lang.constant.SignalType.fromID(line_class.signalType);
1114 node_class = javaObject('jline.lang.ClosedSignal', jnetwork, line_class.getName, jSignalType, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1115 elseif isa(line_class, 'Signal') || isa(line_class, 'OpenSignal')
1116 % Signal/OpenSignal -> jline.lang.Signal (includes CATASTROPHE type)
1117 jSignalType = jline.lang.constant.SignalType.fromID(line_class.signalType);
1118 node_class = javaObject('jline.lang.Signal', jnetwork, line_class.getName, jSignalType, line_class.priority);
1119 elseif isa(line_class, 'OpenClass')
1120 node_class = javaObject('jline.lang.OpenClass', jnetwork, line_class.getName, line_class.priority);
1121 elseif isa(line_class, 'SelfLoopingClass')
1122 node_class = javaObject('jline.lang.SelfLoopingClass', jnetwork, line_class.getName, line_class.population, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1123 elseif isa(line_class, 'ClosedClass')
1124 node_class = javaObject('jline.lang.ClosedClass', jnetwork, line_class.getName, line_class.population, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1125 else
1126 line_error(mfilename,'Class type not supported by JLINE.');
1127 end
1128 if line_class.isReferenceClass()
1129 node_class.setReferenceClass(true);
1130 end
1131 end
1132
1133 function node_class = from_jline_class(jclass, model)
1134 if isa(jclass, 'jline.lang.OpenClass')
1135 node_class = OpenClass(model, jclass.getName.toCharArray', jclass.getPriority);
1136 elseif isa(jclass, 'jline.lang.SelfLoopingClass')
1137 node_class = SelfLoopingClass(model, jclass.getName.toCharArray', jclass.getNumberOfJobs, model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority);
1138 elseif isa(jclass, 'jline.lang.ClosedClass')
1139 node_class = ClosedClass(model, jclass.getName.toCharArray', jclass.getNumberOfJobs, model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority);
1140 else
1141 line_error(mfilename,'Class type not supported by JLINE.');
1142 end
1143 end
1144
1145 function from_line_links(model, jmodel)
1146 connections = model.getConnectionMatrix();
1147 [m, ~] = size(connections);
1148 jnodes = jmodel.getNodes();
1149 jclasses = jmodel.getClasses();
1150 njclasses = jclasses.size();
1151 line_nodes = model.getNodes;
1152 sn = model.getStruct;
1153
1154 % Build mapping from MATLAB node index to Java node index
1155 % (accounting for skipped auto-added ClassSwitch nodes)
1156 matlab2java_node_idx = zeros(1, length(line_nodes));
1157 jidx = 0;
1158 for i = 1:length(line_nodes)
1159 if isa(line_nodes{i}, 'ClassSwitch') && line_nodes{i}.autoAdded
1160 matlab2java_node_idx(i) = -1; % Mark as skipped
1161 else
1162 matlab2java_node_idx(i) = jidx;
1163 jidx = jidx + 1;
1164 end
1165 end
1166
1167 %nodevisits = cellsum(sn.nodevisits);
1168 % [ ] Update to consider different weights/routing for classes
1169 if isempty(sn.rtorig)
1170 useLinkMethod = false; % this model did not call link()
1171 else
1172 jrt_matrix = jmodel.initRoutingMatrix();
1173 useLinkMethod = true;
1174 end
1175
1176 % For models with auto-added ClassSwitch nodes, use sn.rtorig directly
1177 % to set up routing with proper class switching
1178 hasAutoCS = false;
1179 for i = 1:length(line_nodes)
1180 if isa(line_nodes{i}, 'ClassSwitch') && line_nodes{i}.autoAdded
1181 hasAutoCS = true;
1182 break;
1183 end
1184 end
1185
1186 if useLinkMethod && hasAutoCS
1187 % Use sn.rtorig directly - it contains the full routing with class switching
1188 % sn.rtorig already excludes auto-added ClassSwitch nodes (it's based on nstations)
1189 % So we iterate over the rtorig matrix dimensions directly
1190 for r = 1:njclasses
1191 for s = 1:njclasses
1192 if ~isempty(sn.rtorig{r,s})
1193 Prs = sn.rtorig{r,s};
1194 [nrows, ncols] = size(Prs);
1195 for i = 1:nrows
1196 for j = 1:ncols
1197 if Prs(i,j) > 0
1198 % sn.rtorig uses station indices which map to non-CS nodes
1199 % Find the java node indices by matching station index to node
1200 jsrc_idx = i - 1; % Direct mapping since rtorig excludes CS
1201 jdest_idx = j - 1;
1202 jrt_matrix.set(jclasses.get(r-1), jclasses.get(s-1), jnodes.get(jsrc_idx), jnodes.get(jdest_idx), Prs(i,j));
1203 end
1204 end
1205 end
1206 end
1207 end
1208 end
1209 else
1210 % Original logic for models without auto-added ClassSwitch
1211 for i = 1:m
1212 line_node = line_nodes{i};
1213
1214 % Skip auto-added ClassSwitch nodes - Java will add them automatically
1215 if isa(line_node, 'ClassSwitch') && line_node.autoAdded
1216 continue;
1217 end
1218
1219 jnode_idx = matlab2java_node_idx(i);
1220 for k = 1:njclasses
1221 output_strat = line_node.output.outputStrategy{k};
1222 switch RoutingStrategy.fromText(output_strat{2})
1223 case RoutingStrategy.DISABLED
1224 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1225 case RoutingStrategy.RAND
1226 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RAND);
1227 outlinks_i=find(connections(i,:));
1228 if useLinkMethod
1229 % Do NOT add routing matrix entries for RAND routing.
1230 % JAR's getRoutingMatrix computes RAND routing from
1231 % the connection matrix (matching MATLAB behavior).
1232 % Adding entries would cause link() to convert RAND
1233 % to PROB, and for closed classes would incorrectly
1234 % include Sink connections.
1235 else
1236 for j= outlinks_i(:)'
1237 jdest_idx = matlab2java_node_idx(j);
1238 if jdest_idx >= 0
1239 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1240 end
1241 end
1242 end
1243 case RoutingStrategy.RROBIN
1244 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RROBIN);
1245 outlinks_i=find(connections(i,:))';
1246 if useLinkMethod
1247 line_error(mfilename,'RROBIN cannot be used together with the link() command.');
1248 end
1249 for j= outlinks_i(:)'
1250 jdest_idx = matlab2java_node_idx(j);
1251 if jdest_idx >= 0
1252 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1253 end
1254 end
1255 case RoutingStrategy.WRROBIN
1256 outlinks_i=find(connections(i,:))';
1257 for j= outlinks_i(:)'
1258 jdest_idx = matlab2java_node_idx(j);
1259 if jdest_idx >= 0
1260 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1261 end
1262 end
1263 if useLinkMethod
1264 line_error(mfilename,'RROBIN cannot be used together with the link() command.');
1265 end
1266 for j= 1:length(output_strat{3})
1267 node_target = jmodel.getNodeByName(output_strat{3}{j}{1}.getName());
1268 weight = output_strat{3}{j}{2};
1269 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.WRROBIN, node_target, weight);
1270 end
1271 case RoutingStrategy.PROB
1272 outlinks_i=find(connections(i,:));
1273 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1), jline.lang.constant.RoutingStrategy.PROB);
1274 if ~useLinkMethod
1275 for j= outlinks_i(:)'
1276 jdest_idx = matlab2java_node_idx(j);
1277 if jdest_idx >= 0
1278 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1279 end
1280 end
1281 end
1282 if length(output_strat) >= 3
1283 probabilities = output_strat{3};
1284 for j = 1:length(probabilities)
1285 dest_idx = probabilities{j}{1}.index;
1286 jdest_idx = matlab2java_node_idx(dest_idx);
1287 if (connections(i, dest_idx) ~= 0) && jdest_idx >= 0
1288 if useLinkMethod
1289 jrt_matrix.set(jclasses.get(k-1), jclasses.get(k-1), jnodes.get(jnode_idx), jnodes.get(jdest_idx), probabilities{j}{2});
1290 else
1291 jnodes.get(jnode_idx).setProbRouting(jclasses.get(k-1), jnodes.get(jdest_idx), probabilities{j}{2});
1292 end
1293 end
1294 end
1295 end
1296 case RoutingStrategy.JSQ
1297 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.JSQ);
1298 outlinks_i=find(connections(i,:))';
1299 if ~useLinkMethod
1300 for j= outlinks_i(:)'
1301 jdest_idx = matlab2java_node_idx(j);
1302 if jdest_idx >= 0
1303 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1304 end
1305 end
1306 end
1307 otherwise
1308 line_warning(mfilename, sprintf('''%s'' routing strategy not supported by JLINE, setting as Disabled.\n',output_strat{2}));
1309 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1310 end
1311 end
1312 end
1313 end
1314 if useLinkMethod
1315 jmodel.link(jrt_matrix);
1316 % Align the sn.rtorig be the same, treating artificial
1317 % ClassSwitch nodes as if they were explicitly specified
1318 jsn = jmodel.getStruct(true);
1319 rtorig = java.util.HashMap();
1320 if ~isempty(model.sn.rtorig)
1321 if iscell(model.sn.rtorig)
1322 for r = 1:njclasses
1323 sub_rtorig = java.util.HashMap();
1324 for s = 1:njclasses
1325 sub_rtorig.put(jclasses.get(s-1), JLINE.from_line_matrix(model.sn.rtorig{r,s}));
1326 end
1327 rtorig.put(jclasses.get(r-1), sub_rtorig);
1328 end
1329 end
1330 end
1331 jsn.rtorig = rtorig;
1332 end
1333 end
1334
1335 function model = from_jline_routing(model, jnetwork)
1336 jnodes = jnetwork.getNodes();
1337 jclasses = jnetwork.getClasses();
1338 n_nodes = jnodes.size();
1339 network_nodes = model.getNodes;
1340 network_classes = model.getClasses;
1341
1342 % Build name-to-MATLAB-node map (JAR and MATLAB may order nodes differently)
1343 node_by_name = containers.Map();
1344 for nn = 1:length(network_nodes)
1345 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1346 end
1347
1348 connections = JLINE.from_jline_matrix(jnetwork.getConnectionMatrix());
1349 [row,col] = find(connections);
1350 for i=1:length(row)
1351 from_name = char(jnodes.get(row(i)-1).getName());
1352 to_name = char(jnodes.get(col(i)-1).getName());
1353 model.addLink(node_by_name(from_name), node_by_name(to_name));
1354 end
1355
1356 for n = 1 : n_nodes
1357 jnode = jnodes.get(n-1);
1358 cur_node = node_by_name(char(jnode.getName()));
1359 output_strategies = jnode.getOutputStrategies();
1360 n_strategies = output_strategies.size();
1361 for m = 1 : n_strategies
1362 output_strat = output_strategies.get(m-1);
1363 routing_strat = output_strat.getRoutingStrategy;
1364 routing_strat_classidx = output_strat.getJobClass.getIndex();
1365 switch char(routing_strat)
1366 case 'RAND'
1367 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RAND);
1368 case 'RROBIN'
1369 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1370 case 'WRROBIN'
1371 dest = output_strat.getDestination();
1372 if ~isempty(dest)
1373 dest_name = char(dest.getName());
1374 if node_by_name.isKey(dest_name)
1375 weight = output_strat.getProbability();
1376 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1377 end
1378 end
1379 case 'DISABLED'
1380 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.DISABLED);
1381 end
1382 end
1383 end
1384 end
1385
1386 function model = from_jline_links(model, jnetwork)
1387 P = model.initRoutingMatrix;
1388 jnodes = jnetwork.getNodes();
1389 jclasses = jnetwork.getClasses();
1390 n_classes = jclasses.size();
1391 n_nodes = jnodes.size();
1392 network_nodes = model.getNodes;
1393
1394 % Build JAR-to-MATLAB node index mapping (node orders may differ)
1395 jar2ml = zeros(1, n_nodes);
1396 for jj = 1:n_nodes
1397 jar_name = char(jnodes.get(jj-1).getName());
1398 for mm = 1:length(network_nodes)
1399 if strcmp(network_nodes{mm}.name, jar_name)
1400 jar2ml(jj) = mm;
1401 break;
1402 end
1403 end
1404 end
1405
1406 hasDestinations = false;
1407 for n = 1 : n_nodes
1408 jnode = jnodes.get(n-1);
1409 output_strategies = jnode.getOutputStrategies();
1410 n_strategies = output_strategies.size();
1411 for m = 1 : n_strategies
1412 output_strat = output_strategies.get(m-1);
1413 dest = output_strat.getDestination();
1414 if~isempty(dest) % disabled strategy
1415 hasDestinations = true;
1416 in_idx = jar2ml(jnetwork.getNodeIndex(jnode)+1);
1417 out_idx = jar2ml(jnetwork.getNodeIndex(dest)+1);
1418 if n_classes == 1
1419 P{1}(in_idx,out_idx) = output_strat.getProbability();
1420 else
1421 strat_class = output_strat.getJobClass();
1422 class_idx = jnetwork.getJobClassIndex(strat_class)+1;
1423 P{class_idx,class_idx}(in_idx,out_idx) = output_strat.getProbability();
1424 end
1425 end
1426 end
1427 end
1428
1429 % If no OutputStrategy entries had destinations (e.g., model
1430 % loaded from JSON via LineModelIO.load), fall back to rtorig
1431 if ~hasDestinations
1432 sn = jnetwork.getStruct;
1433 if ~isempty(sn.rtorig)
1434 % rtorig is station-indexed (no permutation needed —
1435 % station ordering matches between JAR and MATLAB)
1436 for r = 1:n_classes
1437 for s = 1:n_classes
1438 rtMat = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1439 if ~isempty(rtMat)
1440 P{r,s} = rtMat;
1441 end
1442 end
1443 end
1444 end
1445 end
1446
1447 model.link(P);
1448
1449 % Restore non-PROB routing strategies (RROBIN, WRROBIN, etc.)
1450 % after link(), which sets all routing to PROB
1451 network_nodes = model.getNodes;
1452 network_classes = model.getClasses;
1453 node_by_name = containers.Map();
1454 for nn = 1:length(network_nodes)
1455 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1456 end
1457 for n = 1 : n_nodes
1458 jnode = jnodes.get(n-1);
1459 cur_node = node_by_name(char(jnode.getName()));
1460 output_strategies = jnode.getOutputStrategies();
1461 n_strategies = output_strategies.size();
1462 for m = 1 : n_strategies
1463 output_strat = output_strategies.get(m-1);
1464 routing_strat = output_strat.getRoutingStrategy;
1465 routing_strat_classidx = output_strat.getJobClass.getIndex();
1466 switch char(routing_strat)
1467 case 'RROBIN'
1468 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1469 case 'WRROBIN'
1470 dest = output_strat.getDestination();
1471 if ~isempty(dest)
1472 dest_name = char(dest.getName());
1473 if node_by_name.isKey(dest_name)
1474 % Clear stale PROB entries before first WRROBIN weight
1475 classIdx = routing_strat_classidx;
1476 if length(cur_node.output.outputStrategy) >= classIdx && ...
1477 length(cur_node.output.outputStrategy{1, classIdx}) >= 3
1478 curStrat = cur_node.output.outputStrategy{1, classIdx}{2};
1479 if ~strcmp(curStrat, 'WeightedRoundRobin')
1480 cur_node.output.outputStrategy{1, classIdx}{3} = {};
1481 end
1482 end
1483 weight = output_strat.getProbability();
1484 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1485 end
1486 end
1487 end
1488 end
1489 end
1490
1491 % Invalidate cached struct after modifying routing strategies
1492 model.resetStruct();
1493
1494 %Align the sn.rtorig be the same (Assume Java network is
1495 %created by calling Network.link)
1496 sn = jnetwork.getStruct;
1497 rtorig = cell(n_classes, n_classes);
1498 for r = 1:n_classes
1499 for s = 1:n_classes
1500 rtorig{r,s} = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1501 end
1502 end
1503 model.sn.rtorig = rtorig;
1504 end
1505
1506 function [jnetwork] = from_line_network(model)
1507 %w = warning;
1508 %warning('off');
1509 sn = model.getStruct;
1510
1511 jnetwork = javaObject('jline.lang.Network', model.getName);
1512 line_nodes = model.getNodes;
1513 line_classes = model.getClasses;
1514
1515 jnodes = cell(1,length(line_nodes));
1516 jclasses = cell(1,length(line_classes));
1517
1518 for n = 1 : length(line_nodes)
1519 % Skip auto-added ClassSwitch nodes - Java's link() will add them automatically
1520 if isa(line_nodes{n}, 'ClassSwitch') && line_nodes{n}.autoAdded
1521 continue;
1522 end
1523 if isa(line_nodes{n}, 'Join')
1524 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, jnodes{line_nodes{n}.joinOf.index}, sn);
1525 else
1526 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, [], sn);
1527 end
1528 end
1529
1530 for n = 1 : length(line_classes)
1531 jclasses{n} = JLINE.from_line_class(line_classes{n}, jnetwork);
1532 end
1533
1534 % Set up forJobClass associations for signal classes
1535 for n = 1 : length(line_classes)
1536 if (isa(line_classes{n}, 'Signal') || isa(line_classes{n}, 'OpenSignal') || isa(line_classes{n}, 'ClosedSignal'))
1537 if ~isempty(line_classes{n}.targetJobClass)
1538 targetIdx = line_classes{n}.targetJobClass.index;
1539 jclasses{n}.forJobClass(jclasses{targetIdx});
1540 end
1541 end
1542 end
1543
1544 for n = 1: length(jnodes)
1545 if isempty(jnodes{n})
1546 continue; % Skip nodes that were not converted (e.g., auto-added ClassSwitch)
1547 end
1548 JLINE.set_service(line_nodes{n}, jnodes{n}, line_classes);
1549 JLINE.set_delayoff(line_nodes{n}, jnodes{n}, line_classes);
1550 end
1551
1552 % Set drop rules for stations (after classes are created)
1553 for n = 1: length(jnodes)
1554 if isempty(jnodes{n})
1555 continue; % Skip nodes that were not converted
1556 end
1557 if isa(line_nodes{n}, 'Station') && ~isa(line_nodes{n}, 'Source')
1558 for r = 1:length(line_classes)
1559 if length(line_nodes{n}.dropRule) >= r && ~isempty(line_nodes{n}.dropRule(r))
1560 dropRule = line_nodes{n}.dropRule(r);
1561 switch dropRule
1562 case DropStrategy.DROP
1563 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.Drop);
1564 case DropStrategy.BAS
1565 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.BlockingAfterService);
1566 case DropStrategy.WAITQ
1567 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.WaitingQueue);
1568 end
1569 end
1570 end
1571 end
1572 end
1573
1574 % Transfer LJCD (Limited Joint Class Dependence) scaling for stations
1575 % This must be done after classes are created since LJCD is indexed per-class
1576 for n = 1:length(jnodes)
1577 if isempty(jnodes{n})
1578 continue;
1579 end
1580 if isa(line_nodes{n}, 'Station') && ~isempty(line_nodes{n}.ljcdScaling) && ~isempty(line_nodes{n}.ljcdCutoffs)
1581 jCutoffs = JLINE.from_line_matrix(line_nodes{n}.ljcdCutoffs(:));
1582 K = length(line_nodes{n}.ljcdScaling);
1583 jScalingMap = java.util.HashMap();
1584 for c = 1:K
1585 if ~isempty(line_nodes{n}.ljcdScaling{c})
1586 jScalingVec = JLINE.from_line_matrix(line_nodes{n}.ljcdScaling{c}(:));
1587 jScalingMap.put(jclasses{c}, jScalingVec);
1588 end
1589 end
1590 jnodes{n}.setLimitedJointClassDependence(jScalingMap, jCutoffs);
1591 end
1592 end
1593
1594 % Set polling type and switchover times for polling queues
1595 for n = 1: length(jnodes)
1596 if isempty(jnodes{n})
1597 continue;
1598 end
1599 if isa(line_nodes{n}, 'Queue') && line_nodes{n}.schedStrategy == SchedStrategy.POLLING
1600 % Set polling type
1601 if ~isempty(line_nodes{n}.pollingType) && ~isempty(line_nodes{n}.pollingType{1})
1602 pollingType = line_nodes{n}.pollingType{1};
1603 switch pollingType
1604 case PollingType.GATED
1605 jPollingType = jline.lang.constant.PollingType.GATED;
1606 case PollingType.EXHAUSTIVE
1607 jPollingType = jline.lang.constant.PollingType.EXHAUSTIVE;
1608 case PollingType.KLIMITED
1609 jPollingType = jline.lang.constant.PollingType.KLIMITED;
1610 end
1611 if pollingType == PollingType.KLIMITED && ~isempty(line_nodes{n}.pollingPar)
1612 jnodes{n}.setPollingType(jPollingType, int32(line_nodes{n}.pollingPar));
1613 else
1614 jnodes{n}.setPollingType(jPollingType);
1615 end
1616 end
1617 % Set switchover times
1618 if ~isempty(line_nodes{n}.switchoverTime)
1619 for r = 1:length(line_classes)
1620 if length(line_nodes{n}.switchoverTime) >= r && ~isempty(line_nodes{n}.switchoverTime{r})
1621 soTime = line_nodes{n}.switchoverTime{r};
1622 if ~isa(soTime, 'Immediate')
1623 jnodes{n}.setSwitchover(jclasses{r}, JLINE.from_line_distribution(soTime));
1624 end
1625 end
1626 end
1627 end
1628 end
1629 end
1630
1631 for n = 1: length(jnodes)
1632 if isempty(jnodes{n})
1633 continue; % Skip nodes that were not converted
1634 end
1635 if isa(line_nodes{n},"ClassSwitch") && ~line_nodes{n}.autoAdded
1636 % Only set csMatrix for user-defined ClassSwitch nodes (not auto-added)
1637 JLINE.set_csMatrix(line_nodes{n}, jnodes{n}, jclasses);
1638 elseif isa(line_nodes{n},"Join")
1639 jnodes{n}.initJoinJobClasses();
1640 % Restore RAND routing for all classes, matching ClosedClass/OpenClass
1641 % constructor behavior (initJoinJobClasses sets DISABLED by default)
1642 for r = 1 : sn.nclasses
1643 jnodes{n}.setRouting(jclasses{r}, jline.lang.constant.RoutingStrategy.RAND);
1644 end
1645 elseif isa(line_nodes{n},"Cache")
1646 for r = 1 : sn.nclasses
1647 if length(line_nodes{n}.server.hitClass) >= r && ~isempty(line_nodes{n}.server.hitClass(r))
1648 if ~isa(line_nodes{n}.popularity{r},'Disabled')
1649 jnodes{n}.setRead(jclasses{r}, JLINE.from_line_distribution(line_nodes{n}.popularity{r}));
1650 jnodes{n}.setHitClass(jclasses{r}, jclasses{line_nodes{n}.server.hitClass(r)});
1651 jnodes{n}.setMissClass(jclasses{r}, jclasses{line_nodes{n}.server.missClass(r)});
1652 end
1653 end
1654 end
1655 % Transfer accessProb from MATLAB to Java
1656 if ~isempty(line_nodes{n}.accessProb)
1657 accessProbMat = line_nodes{n}.accessProb;
1658 [K1, K2] = size(accessProbMat);
1659 jAccessProb = javaArray('jline.util.matrix.Matrix', K1, K2);
1660 for k1 = 1:K1
1661 for k2 = 1:K2
1662 if ~isempty(accessProbMat{k1, k2})
1663 jAccessProb(k1, k2) = JLINE.from_line_matrix(accessProbMat{k1, k2});
1664 end
1665 end
1666 end
1667 jnodes{n}.setAccessProb(jAccessProb);
1668 end
1669 elseif isa(line_nodes{n}, "Transition")
1670 % First, add modes (must be done after classes are created)
1671 for m = 1:line_nodes{n}.getNumberOfModes()
1672 modeName = line_nodes{n}.modeNames{m};
1673 jmode = jnodes{n}.addMode(modeName);
1674 % Set timing strategy
1675 switch line_nodes{n}.timingStrategies(m)
1676 case TimingStrategy.TIMED
1677 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.TIMED);
1678 case TimingStrategy.IMMEDIATE
1679 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.IMMEDIATE);
1680 end
1681 % Set distribution
1682 jnodes{n}.setDistribution(jmode, JLINE.from_line_distribution(line_nodes{n}.distributions{m}));
1683 % Set firing weights and priorities
1684 jnodes{n}.setFiringWeights(jmode, line_nodes{n}.firingWeights(m));
1685 jnodes{n}.setFiringPriorities(jmode, int32(line_nodes{n}.firingPriorities(m)));
1686 % Set number of servers
1687 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(line_nodes{n}.numberOfServers(m)));
1688 end
1689 % Now set enabling conditions, inhibiting conditions, and firing outcomes
1690 jmodes = jnodes{n}.getModes();
1691 for m = 1:line_nodes{n}.getNumberOfModes()
1692 jmode = jmodes.get(m-1);
1693 enabCond = line_nodes{n}.enablingConditions{m};
1694 inhibCond = line_nodes{n}.inhibitingConditions{m};
1695 firingOut = line_nodes{n}.firingOutcomes{m};
1696 for r = 1:sn.nclasses
1697 for i = 1:length(line_nodes)
1698 % Set enabling conditions
1699 if enabCond(i, r) > 0 && isa(line_nodes{i}, 'Place')
1700 jnodes{n}.setEnablingConditions(jmode, jclasses{r}, jnodes{i}, enabCond(i, r));
1701 end
1702 % Set inhibiting conditions
1703 if inhibCond(i, r) < Inf && isa(line_nodes{i}, 'Place')
1704 jnodes{n}.setInhibitingConditions(jmode, jclasses{r}, jnodes{i}, inhibCond(i, r));
1705 end
1706 % Set firing outcomes
1707 if firingOut(i, r) ~= 0
1708 jnodes{n}.setFiringOutcome(jmode, jclasses{r}, jnodes{i}, firingOut(i, r));
1709 end
1710 end
1711 end
1712 end
1713 end
1714 end
1715
1716 % Assume JLINE and LINE network are both created via link
1717 JLINE.from_line_links(model, jnetwork);
1718
1719 % Transfer finite capacity regions from MATLAB to Java
1720 if ~isempty(model.regions)
1721 for f = 1:length(model.regions)
1722 fcr = model.regions{f};
1723 % Convert MATLAB node list to Java list
1724 javaNodeList = java.util.ArrayList();
1725 for i = 1:length(fcr.nodes)
1726 matlabNode = fcr.nodes{i};
1727 % Find corresponding Java node by name
1728 nodeName = matlabNode.getName();
1729 for j = 1:length(line_nodes)
1730 if strcmp(line_nodes{j}.getName(), nodeName) && ~isempty(jnodes{j})
1731 javaNodeList.add(jnodes{j});
1732 break;
1733 end
1734 end
1735 end
1736 % Create Java FCR
1737 jfcr = jnetwork.addRegion(javaNodeList);
1738 % Set global max jobs
1739 if fcr.globalMaxJobs > 0 && ~isinf(fcr.globalMaxJobs)
1740 jfcr.setGlobalMaxJobs(fcr.globalMaxJobs);
1741 end
1742 % Set per-class max jobs and drop rules
1743 for r = 1:length(line_classes)
1744 if length(fcr.classMaxJobs) >= r && fcr.classMaxJobs(r) > 0 && ~isinf(fcr.classMaxJobs(r))
1745 jfcr.setClassMaxJobs(jclasses{r}, fcr.classMaxJobs(r));
1746 end
1747 if length(fcr.dropRule) >= r
1748 % Convert MATLAB DropStrategy numeric to Java DropStrategy enum
1749 jDropStrategy = jline.lang.constant.DropStrategy.fromID(fcr.dropRule(r));
1750 jfcr.setDropRule(jclasses{r}, jDropStrategy);
1751 end
1752 end
1753 % Transfer linear constraints if set
1754 if fcr.hasLinearConstraints()
1755 jA = JLINE.from_line_matrix(fcr.constraintA);
1756 jb = JLINE.from_line_matrix(fcr.constraintB);
1757 jfcr.setLinearConstraints(jA, jb);
1758 end
1759 end
1760 end
1761
1762 jnetwork.initDefault;
1763 for n = 1: length(line_nodes)
1764 if isempty(jnodes{n})
1765 continue; % Skip nodes that were not converted
1766 end
1767 if line_nodes{n}.isStateful
1768 jnodes{n}.setState(JLINE.from_line_matrix(line_nodes{n}.getState));
1769 jnodes{n}.setStateSpace(JLINE.from_line_matrix(line_nodes{n}.getStateSpace));
1770 jnodes{n}.setStatePrior(JLINE.from_line_matrix(line_nodes{n}.getStatePrior));
1771 end
1772 end
1773 % Force struct refresh so sn.state reflects updated node states
1774 jnetwork.setHasStruct(false);
1775
1776 end
1777
1778 function jnetwork = line_to_jline(model)
1779 jnetwork = LINE2JLINE(model);
1780 end
1781
1782 function model = jline_to_line(jnetwork)
1783 if isa(jnetwork,'JNetwork')
1784 jnetwork = jnetwork.obj;
1785 end
1786 %javaaddpath(jar_loc);
1787 model = Network(char(jnetwork.getName));
1788 network_nodes = jnetwork.getNodes;
1789 job_classes = jnetwork.getClasses;
1790
1791 line_nodes = cell(network_nodes.size,1);
1792 line_classes = cell(job_classes.size,1);
1793
1794
1795 for n = 1 : network_nodes.size
1796 if ~isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch')
1797 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
1798 end
1799 end
1800
1801 for n = 1 : job_classes.size
1802 line_classes{n} = JLINE.from_jline_class(job_classes.get(n-1), model);
1803 end
1804
1805 for n = 1 : network_nodes.size
1806 if isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch')
1807 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
1808 end
1809 end
1810
1811 % Deferred Fork/Join linking: set joinOf on Join nodes
1812 for n = 1 : network_nodes.size
1813 jnode = network_nodes.get(n-1);
1814 if isa(jnode, 'jline.lang.nodes.Join') && ~isempty(jnode.joinOf)
1815 forkName = char(jnode.joinOf.getName);
1816 for m = 1 : network_nodes.size
1817 if ~isempty(line_nodes{m}) && isa(line_nodes{m}, 'Fork') && strcmp(line_nodes{m}.name, forkName)
1818 line_nodes{n}.joinOf = line_nodes{m};
1819 break;
1820 end
1821 end
1822 end
1823 end
1824
1825 % Deferred Cache setup: set hitClass, missClass, popularity
1826 for n = 1 : network_nodes.size
1827 jnode = network_nodes.get(n-1);
1828 if isa(jnode, 'jline.lang.nodes.Cache') && isa(line_nodes{n}, 'Cache')
1829 cacheNode = line_nodes{n};
1830 % hitClass and missClass are stored as index vectors
1831 hitClassVec = JLINE.from_jline_matrix(jnode.getHitClass());
1832 missClassVec = JLINE.from_jline_matrix(jnode.getMissClass());
1833 for r = 1:job_classes.size
1834 hitIdx = hitClassVec(r);
1835 if hitIdx >= 0 && (hitIdx + 1) <= job_classes.size
1836 cacheNode.setHitClass(line_classes{r}, line_classes{hitIdx + 1});
1837 end
1838 missIdx = missClassVec(r);
1839 if missIdx >= 0 && (missIdx + 1) <= job_classes.size
1840 cacheNode.setMissClass(line_classes{r}, line_classes{missIdx + 1});
1841 end
1842 end
1843 % Popularity distributions
1844 for r = 1:job_classes.size
1845 try
1846 popDist = jnode.popularityGet(0, r-1);
1847 if ~isempty(popDist) && popDist.isDiscrete()
1848 matlabDist = JLINE.from_jline_distribution(popDist);
1849 if ~isempty(matlabDist)
1850 cacheNode.setRead(line_classes{r}, matlabDist);
1851 end
1852 end
1853 catch
1854 % No popularity for this class
1855 end
1856 end
1857 end
1858 end
1859
1860 for n = 1 : network_nodes.size
1861 JLINE.set_line_service(network_nodes.get(n-1), line_nodes{n}, job_classes, line_classes);
1862 end
1863
1864 % Check for state-dependent routing (RROBIN, WRROBIN, JSQ)
1865 % These cannot go through link(P) because it overrides routing strategies
1866 hasSDRouting = false;
1867 for n = 1 : network_nodes.size
1868 jnode = network_nodes.get(n-1);
1869 output_strategies = jnode.getOutputStrategies();
1870 for m = 1 : output_strategies.size()
1871 rs = char(output_strategies.get(m-1).getRoutingStrategy);
1872 if any(strcmp(rs, {'RROBIN','WRROBIN','JSQ','KCHOICES'}))
1873 hasSDRouting = true;
1874 break;
1875 end
1876 end
1877 if hasSDRouting; break; end
1878 end
1879
1880 if hasSDRouting
1881 % State-dependent routing: use addLink + setRouting
1882 model = JLINE.from_jline_routing(model, jnetwork);
1883 elseif ~isempty(jnetwork.getStruct.rtorig)
1884 % Use link() method
1885 model = JLINE.from_jline_links(model, jnetwork);
1886 else
1887 % Do not use link() method
1888 model = JLINE.from_jline_routing(model, jnetwork);
1889 end
1890 end
1891
1892 function matrix = arraylist_to_matrix(jline_matrix)
1893 if isempty(jline_matrix)
1894 matrix = [];
1895 else
1896 matrix = zeros(jline_matrix.size(), 1);
1897 for row = 1:jline_matrix.size()
1898 matrix(row, 1) = jline_matrix.get(row-1);
1899 end
1900 end
1901 end
1902
1903 function matrix = from_jline_matrix(jline_matrix)
1904 if isempty(jline_matrix)
1905 matrix = [];
1906 else
1907 matrix = zeros(jline_matrix.getNumRows(), jline_matrix.getNumCols());
1908 for row = 1:jline_matrix.getNumRows()
1909 for col = 1:jline_matrix.getNumCols()
1910 val = jline_matrix.get(row-1, col-1);
1911 if (val >= 33333333 && val <= 33333334)
1912 matrix(row, col) = GlobalConstants.Immediate;
1913 elseif (val >= -33333334 && val <= -33333333)
1914 matrix(row, col) = -GlobalConstants.Immediate;
1915 elseif (val >= 2147483647 - 1) % Integer.MAX_VALUE with -1 tolerance
1916 matrix(row, col) = Inf;
1917 elseif (val <= -2147483648 + 1) % Integer.MIN_VALUE with +1 tolerance
1918 matrix(row, col) = -Inf;
1919 else
1920 matrix(row, col) = val;
1921 end
1922 end
1923 end
1924 end
1925 end
1926
1927 function jline_matrix = from_line_matrix(matrix)
1928 [rows, cols] = size(matrix);
1929 jline_matrix = jline.util.matrix.Matrix(rows, cols);
1930 for row = 1:rows
1931 for col = 1:cols
1932 if matrix(row,col) ~= 0
1933 jline_matrix.set(row-1, col-1, matrix(row, col));
1934 end
1935 end
1936 end
1937 end
1938
1939 function lsn = from_jline_struct_layered(jlayerednetwork, jlsn)
1940 lsn = LayeredNetworkStruct();
1941 lsn.nidx= jlsn.nidx;
1942 lsn.nhosts= jlsn.nhosts;
1943 lsn.ntasks= jlsn.ntasks;
1944 lsn.nentries= jlsn.nentries;
1945 lsn.nacts= jlsn.nacts;
1946 lsn.ncalls= jlsn.ncalls;
1947 lsn.hshift= jlsn.hshift;
1948 lsn.tshift= jlsn.tshift;
1949 lsn.eshift= jlsn.eshift;
1950 lsn.ashift= jlsn.ashift;
1951 lsn.cshift= jlsn.cshift;
1952 for h=1:jlsn.nhosts
1953 lsn.tasksof{h,1} = JLINE.arraylist_to_matrix(jlsn.tasksof.get(uint32(h)))';
1954 end
1955 for t=1:jlsn.ntasks
1956 lsn.entriesof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.entriesof.get(uint32(jlsn.tshift+t)))';
1957 end
1958 for t=1:(jlsn.ntasks+jlsn.nentries)
1959 lsn.actsof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.actsof.get(uint32(jlsn.tshift+t)))';
1960 end
1961 for a=1:jlsn.nacts
1962 lsn.callsof{lsn.ashift+a,1} = JLINE.arraylist_to_matrix(jlsn.callsof.get(uint32(jlsn.ashift+a)))';
1963 end
1964 for i = 1:jlsn.sched.size
1965 lsn.sched(i,1) = SchedStrategy.(char(jlsn.sched.get(uint32(i))));
1966 end
1967 for i = 1:jlsn.names.size
1968 lsn.names{i,1} = jlsn.names.get(uint32(i));
1969 lsn.hashnames{i,1} = jlsn.hashnames.get(uint32(i));
1970 end
1971 lsn.mult = JLINE.from_jline_matrix(jlsn.mult);
1972 lsn.mult = lsn.mult(2:(lsn.eshift+1))'; % remove 0-padding
1973 lsn.maxmult = JLINE.from_jline_matrix(jlsn.maxmult);
1974 lsn.maxmult = lsn.maxmult(2:(lsn.eshift+1))'; % remove 0-padding
1975
1976 lsn.repl = JLINE.from_jline_matrix(jlsn.repl)';
1977 lsn.repl = lsn.repl(2:end); % remove 0-padding
1978 lsn.type = JLINE.from_jline_matrix(jlsn.type)';
1979 lsn.type = lsn.type(2:end); % remove 0-padding
1980 lsn.parent = JLINE.from_jline_matrix(jlsn.parent);
1981 lsn.parent = lsn.parent(2:end); % remove 0-padding
1982 lsn.nitems = JLINE.from_jline_matrix(jlsn.nitems);
1983 % Ensure proper column vector format matching MATLAB's (nhosts+ntasks+nentries) x 1
1984 if isrow(lsn.nitems)
1985 lsn.nitems = lsn.nitems(2:end)'; % remove 0-padding and transpose
1986 else
1987 lsn.nitems = lsn.nitems(2:end); % remove 0-padding (already column)
1988 end
1989 % Ensure correct size
1990 expectedSize = lsn.nhosts + lsn.ntasks + lsn.nentries;
1991 if length(lsn.nitems) < expectedSize
1992 lsn.nitems(expectedSize,1) = 0;
1993 elseif length(lsn.nitems) > expectedSize
1994 lsn.nitems = lsn.nitems(1:expectedSize);
1995 end
1996 lsn.replacestrat = JLINE.from_jline_matrix(jlsn.replacestrat);
1997 lsn.replacestrat = lsn.replacestrat(2:end)'; % remove 0-padding
1998 for i = 1:jlsn.callnames.size
1999 lsn.callnames{i,1} = jlsn.callnames.get(uint32(i));
2000 lsn.callhashnames{i,1} = jlsn.callhashnames.get(uint32(i));
2001 end
2002 for i = 1:jlsn.calltype.size % calltype may be made into a matrix in Java
2003 ct = char(jlsn.calltype.get(uint32(i)));
2004 lsn.calltype(i) = CallType.(ct);
2005 end
2006 lsn.calltype = sparse(lsn.calltype'); % remove 0-padding
2007 lsn.callpair = JLINE.from_jline_matrix(jlsn.callpair);
2008 lsn.callpair = lsn.callpair(2:end,2:end); % remove 0-paddings
2009 if isempty(lsn.callpair)
2010 lsn.callpair=[];
2011 end
2012 lsn.actpretype = sparse(JLINE.from_jline_matrix(jlsn.actpretype)');
2013 lsn.actpretype = lsn.actpretype(2:end); % remove 0-padding
2014 lsn.actposttype = sparse(JLINE.from_jline_matrix(jlsn.actposttype)');
2015 lsn.actposttype = lsn.actposttype(2:end); % remove 0-padding
2016 lsn.graph = JLINE.from_jline_matrix(jlsn.graph);
2017 lsn.graph = lsn.graph(2:end,2:end); % remove 0-paddings
2018 lsn.dag = JLINE.from_jline_matrix(jlsn.dag);
2019 lsn.dag = lsn.dag(2:end,2:end); % remove 0-paddings
2020 lsn.taskgraph = JLINE.from_jline_matrix(jlsn.taskgraph);
2021 lsn.taskgraph = sparse(lsn.taskgraph(2:end,2:end)); % remove 0-paddings
2022 lsn.replygraph = JLINE.from_jline_matrix(jlsn.replygraph);
2023 lsn.replygraph = logical(lsn.replygraph(2:end,2:end)); % remove 0-paddings
2024 lsn.iscache = JLINE.from_jline_matrix(jlsn.iscache);
2025 % Ensure proper column vector format matching MATLAB's (nhosts+ntasks) x 1
2026 expectedCacheSize = lsn.nhosts + lsn.ntasks;
2027 if isrow(lsn.iscache)
2028 if length(lsn.iscache) > expectedCacheSize
2029 lsn.iscache = lsn.iscache(2:(expectedCacheSize+1))'; % remove 0-padding and transpose
2030 else
2031 lsn.iscache = lsn.iscache'; % just transpose
2032 end
2033 end
2034 % Ensure correct size
2035 if length(lsn.iscache) < expectedCacheSize
2036 lsn.iscache(expectedCacheSize,1) = 0;
2037 elseif length(lsn.iscache) > expectedCacheSize
2038 lsn.iscache = lsn.iscache(1:expectedCacheSize);
2039 end
2040 lsn.iscaller = JLINE.from_jline_matrix(jlsn.iscaller);
2041 lsn.iscaller = full(lsn.iscaller(2:end,2:end)); % remove 0-paddings
2042 lsn.issynccaller = JLINE.from_jline_matrix(jlsn.issynccaller);
2043 lsn.issynccaller = full(lsn.issynccaller(2:end,2:end)); % remove 0-paddings
2044 lsn.isasynccaller = JLINE.from_jline_matrix(jlsn.isasynccaller);
2045 lsn.isasynccaller = full(lsn.isasynccaller(2:end,2:end)); % remove 0-paddings
2046 lsn.isref = JLINE.from_jline_matrix(jlsn.isref);
2047 lsn.isref = lsn.isref(2:end)'; % remove 0-paddings
2048 end
2049
2050 function sn = from_jline_struct(jnetwork, jsn)
2051 %lst and rtfun are not implemented
2052 %Due to the transformation of Java lambda to matlab function
2053 if nargin<2
2054 jsn = jnetwork.getStruct(false);
2055 end
2056 jclasses = jnetwork.getClasses();
2057 jnodes = jnetwork.getNodes();
2058 jstateful = jnetwork.getStatefulNodes();
2059 jstations = jnetwork.getStations();
2060 sn = NetworkStruct();
2061
2062 sn.nnodes = jsn.nnodes;
2063 sn.nclasses = jsn.nclasses;
2064 sn.nclosedjobs = jsn.nclosedjobs;
2065 sn.nstations = jsn.nstations;
2066 sn.nstateful = jsn.nstateful;
2067 sn.nchains = jsn.nchains;
2068
2069 sn.refstat = JLINE.from_jline_matrix(jsn.refstat) + 1;
2070 sn.njobs = JLINE.from_jline_matrix(jsn.njobs);
2071 sn.nservers = JLINE.from_jline_matrix(jsn.nservers);
2072 sn.connmatrix = JLINE.from_jline_matrix(jsn.connmatrix);
2073 % Fix for Java getConnectionMatrix bug: ensure connmatrix is nnodes x nnodes
2074 if size(sn.connmatrix,1) < sn.nnodes
2075 sn.connmatrix(sn.nnodes,1) = 0;
2076 end
2077 if size(sn.connmatrix,2) < sn.nnodes
2078 sn.connmatrix(1,sn.nnodes) = 0;
2079 end
2080 sn.scv = JLINE.from_jline_matrix(jsn.scv);
2081 sn.isstation = logical(JLINE.from_jline_matrix(jsn.isstation));
2082 sn.isstateful = logical(JLINE.from_jline_matrix(jsn.isstateful));
2083 sn.isstatedep = logical(JLINE.from_jline_matrix(jsn.isstatedep));
2084 sn.nodeToStateful = JLINE.from_jline_matrix(jsn.nodeToStateful)+1;
2085 sn.nodeToStateful(sn.nodeToStateful==0) = nan;
2086 sn.nodeToStation = JLINE.from_jline_matrix(jsn.nodeToStation)+1;
2087 sn.nodeToStation(sn.nodeToStation==0) = nan;
2088 sn.stationToNode = JLINE.from_jline_matrix(jsn.stationToNode)+1;
2089 sn.stationToNode(sn.stationToNode==0) = nan;
2090 sn.stationToStateful = JLINE.from_jline_matrix(jsn.stationToStateful)+1;
2091 sn.stationToStateful(sn.stationToStateful==0) = nan;
2092 sn.statefulToStation = JLINE.from_jline_matrix(jsn.statefulToStation)+1;
2093 sn.statefulToStation(sn.statefulToStation==0) = nan;
2094 sn.statefulToNode = JLINE.from_jline_matrix(jsn.statefulToNode)+1;
2095 sn.statefulToNode(sn.statefulToNode==0) = nan;
2096 sn.rates = JLINE.from_jline_matrix(jsn.rates);
2097 sn.fj = JLINE.from_jline_matrix(jsn.fj);
2098 sn.classprio = JLINE.from_jline_matrix(jsn.classprio);
2099 sn.phases = JLINE.from_jline_matrix(jsn.phases);
2100 sn.phasessz = JLINE.from_jline_matrix(jsn.phasessz);
2101 sn.phaseshift = JLINE.from_jline_matrix(jsn.phaseshift);
2102 sn.schedparam = JLINE.from_jline_matrix(jsn.schedparam);
2103 sn.chains = logical(JLINE.from_jline_matrix(jsn.chains));
2104 sn.rt = JLINE.from_jline_matrix(jsn.rt);
2105 sn.nvars = JLINE.from_jline_matrix(jsn.nvars);
2106 sn.rtnodes = JLINE.from_jline_matrix(jsn.rtnodes);
2107 sn.csmask = logical(JLINE.from_jline_matrix(jsn.csmask));
2108 sn.isslc = logical(JLINE.from_jline_matrix(jsn.isslc));
2109 sn.cap = JLINE.from_jline_matrix(jsn.cap);
2110 sn.classcap = JLINE.from_jline_matrix(jsn.classcap);
2111 sn.refclass = JLINE.from_jline_matrix(jsn.refclass)+1;
2112 sn.lldscaling = JLINE.from_jline_matrix(jsn.lldscaling);
2113
2114 if ~isempty(jsn.cdscaling) && jsn.cdscaling.size() > 0
2115 % Convert Java SerializableFunction to MATLAB function handles
2116 sn.cdscaling = cell(sn.nstations, 1);
2117 % Iterate through the map entries to handle null values properly
2118 entrySet = jsn.cdscaling.entrySet();
2119 entryIter = entrySet.iterator();
2120 stationFunMap = containers.Map();
2121 while entryIter.hasNext()
2122 entry = entryIter.next();
2123 stationName = char(entry.getKey().getName());
2124 try
2125 jfun = entry.getValue();
2126 if ~isempty(jfun)
2127 stationFunMap(stationName) = jfun;
2128 end
2129 catch
2130 % getValue() returns null for default lambda functions
2131 % Skip and use default value
2132 end
2133 end
2134 % Assign functions to stations
2135 for i = 1:sn.nstations
2136 jstation = jstations.get(i-1);
2137 stationName = char(jstation.getName());
2138 if isKey(stationFunMap, stationName)
2139 jfun = stationFunMap(stationName);
2140 % Create a MATLAB function handle that calls the Java apply() method
2141 sn.cdscaling{i} = @(ni) JLINE.call_java_cdscaling(jfun, ni);
2142 else
2143 sn.cdscaling{i} = @(ni) 1;
2144 end
2145 end
2146 else
2147 sn.cdscaling = cell(sn.nstations, 0);
2148 end
2149
2150 if ~isempty(jsn.nodetype)
2151 sn.nodetype = zeros(sn.nnodes, 1);
2152 for i = 1:jsn.nodetype.size
2153 nodetype = jsn.nodetype.get(i-1);
2154 switch nodetype.name().toCharArray'
2155 case 'Queue'
2156 sn.nodetype(i) = NodeType.Queue;
2157 case 'Delay'
2158 sn.nodetype(i) = NodeType.Delay;
2159 case 'Source'
2160 sn.nodetype(i) = NodeType.Source;
2161 case 'Sink'
2162 sn.nodetype(i) = NodeType.Sink;
2163 case 'Join'
2164 sn.nodetype(i) = NodeType.Join;
2165 case 'Fork'
2166 sn.nodetype(i) = NodeType.Fork;
2167 case 'ClassSwitch'
2168 sn.nodetype(i) = NodeType.ClassSwitch;
2169 case 'Logger'
2170 sn.nodetype(i) = NodeType.Logger;
2171 case 'Cache'
2172 sn.nodetype(i) = NodeType.Cache;
2173 case 'Place'
2174 sn.nodetype(i) = NodeType.Place;
2175 case 'Transition'
2176 sn.nodetype(i) = NodeType.Transition;
2177 case 'Router'
2178 sn.nodetype(i) = NodeType.Router;
2179 end
2180 end
2181 else
2182 sn.nodetype = [];
2183 end
2184
2185 if ~isempty(jsn.classnames)
2186 for i = 1:jsn.classnames.size
2187 sn.classnames(i,1) = jsn.classnames.get(i-1);
2188 end
2189 else
2190 sn.classnames = [];
2191 end
2192
2193 if ~isempty(jsn.nodenames)
2194 for i = 1:jsn.nodenames.size
2195 sn.nodenames(i,1) = jsn.nodenames.get(i-1);
2196 end
2197 else
2198 sn.nodenames = [];
2199 end
2200
2201 if ~isempty(jsn.rtorig) && jsn.rtorig.size()>0
2202 sn.rtorig = cell(sn.nclasses, sn.nclasses);
2203 for r = 1:sn.nclasses
2204 for s = 1:sn.nclasses
2205 sn.rtorig{r,s} = JLINE.from_jline_matrix(jsn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
2206 end
2207 end
2208 else
2209 sn.rtorig = {};
2210 end
2211
2212 if ~isempty(jsn.state)
2213 sn.state = cell(sn.nstateful, 1);
2214 for i = 1:sn.nstateful
2215 sn.state{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getState());
2216 end
2217 else
2218 sn.state = {};
2219 end
2220
2221 if ~isempty(jsn.stateprior)
2222 sn.stateprior = cell(sn.nstateful, 1);
2223 for i = 1:sn.nstateful
2224 sn.stateprior{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStatePrior());
2225 end
2226 else
2227 sn.stateprior = {};
2228 end
2229
2230 if ~isempty(jsn.space)
2231 sn.space = cell(sn.nstateful, 1);
2232 for i = 1:sn.nstateful
2233 sn.space{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStateSpace());
2234 end
2235 else
2236 sn.space = {};
2237 end
2238
2239 if ~isempty(jsn.routing)
2240 sn.routing = zeros(sn.nnodes, sn.nclasses);
2241 for i = 1:sn.nnodes
2242 for j = 1:sn.nclasses
2243 routingStrategy = jsn.routing.get(jnodes.get(i-1)).get(jclasses.get(j-1));
2244 switch routingStrategy.name().toCharArray'
2245 case 'PROB'
2246 sn.routing(i,j) = RoutingStrategy.PROB;
2247 case 'RAND'
2248 sn.routing(i,j) = RoutingStrategy.RAND;
2249 case 'RROBIN'
2250 sn.routing(i,j) = RoutingStrategy.RROBIN;
2251 case 'WRROBIN'
2252 sn.routing(i,j) = RoutingStrategy.WRROBIN;
2253 case 'JSQ'
2254 sn.routing(i,j) = RoutingStrategy.JSQ;
2255 case 'DISABLED'
2256 sn.routing(i,j) = RoutingStrategy.DISABLED;
2257 case 'FIRING'
2258 sn.routing(i,j) = RoutingStrategy.FIRING;
2259 case 'KCHOICES'
2260 sn.routing(i,j) = RoutingStrategy.KCHOICES;
2261 end
2262 end
2263 end
2264 else
2265 sn.routing = [];
2266 end
2267
2268 if ~isempty(jsn.procid)
2269 sn.procid = nan(sn.nstations, sn.nclasses); % Initialize with NaN to match MATLAB behavior
2270 for i = 1:sn.nstations
2271 for j = 1:sn.nclasses
2272 stationMap = jsn.procid.get(jstations.get(i-1));
2273 if isempty(stationMap)
2274 sn.procid(i,j) = ProcessType.DISABLED;
2275 continue;
2276 end
2277 processType = stationMap.get(jclasses.get(j-1));
2278 if isempty(processType)
2279 sn.procid(i,j) = ProcessType.DISABLED;
2280 continue;
2281 end
2282 switch processType.name.toCharArray'
2283 case 'EXP'
2284 sn.procid(i,j) = ProcessType.EXP;
2285 case 'ERLANG'
2286 sn.procid(i,j) = ProcessType.ERLANG;
2287 case 'HYPEREXP'
2288 sn.procid(i,j) = ProcessType.HYPEREXP;
2289 case 'PH'
2290 sn.procid(i,j) = ProcessType.PH;
2291 case 'APH'
2292 sn.procid(i,j) = ProcessType.APH;
2293 case 'MAP'
2294 sn.procid(i,j) = ProcessType.MAP;
2295 case 'UNIFORM'
2296 sn.procid(i,j) = ProcessType.UNIFORM;
2297 case 'DET'
2298 sn.procid(i,j) = ProcessType.DET;
2299 case 'COXIAN'
2300 sn.procid(i,j) = ProcessType.COXIAN;
2301 case 'GAMMA'
2302 sn.procid(i,j) = ProcessType.GAMMA;
2303 case 'PARETO'
2304 sn.procid(i,j) = ProcessType.PARETO;
2305 case 'WEIBULL'
2306 sn.procid(i,j) = ProcessType.WEIBULL;
2307 case 'LOGNORMAL'
2308 sn.procid(i,j) = ProcessType.LOGNORMAL;
2309 case 'MMPP2'
2310 sn.procid(i,j) = ProcessType.MMPP2;
2311 case 'REPLAYER'
2312 sn.procid(i,j) = ProcessType.REPLAYER;
2313 case 'TRACE'
2314 sn.procid(i,j) = ProcessType.TRACE;
2315 case 'IMMEDIATE'
2316 sn.procid(i,j) = ProcessType.IMMEDIATE;
2317 case 'DISABLED'
2318 sn.procid(i,j) = ProcessType.DISABLED;
2319 case 'COX2'
2320 sn.procid(i,j) = ProcessType.COX2;
2321 case 'BMAP'
2322 sn.procid(i,j) = ProcessType.BMAP;
2323 case 'ME'
2324 sn.procid(i,j) = ProcessType.ME;
2325 case 'RAP'
2326 sn.procid(i,j) = ProcessType.RAP;
2327 case 'BINOMIAL'
2328 sn.procid(i,j) = ProcessType.BINOMIAL;
2329 case 'POISSON'
2330 sn.procid(i,j) = ProcessType.POISSON;
2331 case 'GEOMETRIC'
2332 sn.procid(i,j) = ProcessType.GEOMETRIC;
2333 case 'DUNIFORM'
2334 sn.procid(i,j) = ProcessType.DUNIFORM;
2335 case 'BERNOULLI'
2336 sn.procid(i,j) = ProcessType.BERNOULLI;
2337 case 'PRIOR'
2338 sn.procid(i,j) = ProcessType.PRIOR;
2339 otherwise
2340 % Unknown ProcessType - default to DISABLED
2341 sn.procid(i,j) = ProcessType.DISABLED;
2342 end
2343 end
2344 end
2345 else
2346 sn.procid = [];
2347 end
2348
2349 if ~isempty(jsn.mu)
2350 sn.mu = cell(sn.nstations, 1);
2351 for i = 1:sn.nstations
2352 sn.mu{i} = cell(1, sn.nclasses);
2353 for j = 1:sn.nclasses
2354 sn.mu{i}{j} = JLINE.from_jline_matrix(jsn.mu.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2355 end
2356 end
2357 else
2358 sn.mu = {};
2359 end
2360
2361 if ~isempty(jsn.phi)
2362 sn.phi = cell(sn.nstations, 1);
2363 for i = 1:sn.nstations
2364 sn.phi{i} = cell(1, sn.nclasses);
2365 for j = 1:sn.nclasses
2366 sn.phi{i}{j} = JLINE.from_jline_matrix(jsn.phi.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2367 end
2368 end
2369 else
2370 sn.phi = {};
2371 end
2372
2373 if ~isempty(jsn.proc)
2374 sn.proc = cell(sn.nstations, 1);
2375 for i = 1:sn.nstations
2376 sn.proc{i} = cell(1, sn.nclasses);
2377 for j = 1:sn.nclasses
2378 proc_i_j = jsn.proc.get(jstations.get(i-1)).get(jclasses.get(j-1));
2379 sn.proc{i}{j} = cell(1, proc_i_j.size);
2380 for k = 1:proc_i_j.size
2381 sn.proc{i}{j}{k} = JLINE.from_jline_matrix(proc_i_j.get(uint32(k-1)));
2382 end
2383 end
2384 end
2385 else
2386 sn.proc = {};
2387 end
2388
2389 if ~isempty(jsn.pie)
2390 sn.pie = cell(sn.nstations, 1);
2391 for i = 1:sn.nstations
2392 sn.pie{i} = cell(1, sn.nclasses);
2393 for j = 1:sn.nclasses
2394 sn.pie{i}{j} = JLINE.from_jline_matrix(jsn.pie.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2395 end
2396 end
2397 else
2398 sn.pie = {};
2399 end
2400
2401 if ~isempty(jsn.sched)
2402 sn.sched = zeros(sn.nstations, 1);
2403 for i = 1:sn.nstations
2404 schedStrategy = jsn.sched.get(jstations.get(i-1));
2405 switch schedStrategy.name.toCharArray'
2406 case 'INF'
2407 sn.sched(i) = SchedStrategy.INF;
2408 case 'FCFS'
2409 sn.sched(i) = SchedStrategy.FCFS;
2410 case 'LCFS'
2411 sn.sched(i) = SchedStrategy.LCFS;
2412 case 'LCFSPR'
2413 sn.sched(i) = SchedStrategy.LCFSPR;
2414 case 'SIRO'
2415 sn.sched(i) = SchedStrategy.SIRO;
2416 case 'SJF'
2417 sn.sched(i) = SchedStrategy.SJF;
2418 case 'LJF'
2419 sn.sched(i) = SchedStrategy.LJF;
2420 case 'PS'
2421 sn.sched(i) = SchedStrategy.PS;
2422 case 'DPS'
2423 sn.sched(i) = SchedStrategy.DPS;
2424 case 'GPS'
2425 sn.sched(i) = SchedStrategy.GPS;
2426 case 'PSPRIO'
2427 sn.sched(i) = SchedStrategy.PSPRIO;
2428 case 'DPSPRIO'
2429 sn.sched(i) = SchedStrategy.DPSPRIO;
2430 case 'GPSPRIO'
2431 sn.sched(i) = SchedStrategy.GPSPRIO;
2432 case 'SEPT'
2433 sn.sched(i) = SchedStrategy.SEPT;
2434 case 'LEPT'
2435 sn.sched(i) = SchedStrategy.LEPT;
2436 case {'HOL', 'FCFSPRIO'}
2437 sn.sched(i) = SchedStrategy.FCFSPRIO;
2438 case 'FORK'
2439 sn.sched(i) = SchedStrategy.FORK;
2440 case 'EXT'
2441 sn.sched(i) = SchedStrategy.EXT;
2442 case 'REF'
2443 sn.sched(i) = SchedStrategy.REF;
2444 end
2445 end
2446 else
2447 sn.sched = [];
2448 end
2449
2450 if ~isempty(jsn.inchain)
2451 sn.inchain = cell(1, sn.nchains);
2452 for i = 1:sn.nchains
2453 sn.inchain{1,i} = JLINE.from_jline_matrix(jsn.inchain.get(uint32(i-1)))+1;
2454 end
2455 else
2456 sn.inchain = {};
2457 end
2458
2459 if ~isempty(jsn.visits)
2460 sn.visits = cell(sn.nchains, 1);
2461 for i = 1:sn.nchains
2462 sn.visits{i,1} = JLINE.from_jline_matrix(jsn.visits.get(uint32(i-1)));
2463 end
2464 else
2465 sn.visits = {};
2466 end
2467
2468 if ~isempty(jsn.nodevisits)
2469 sn.nodevisits = cell(1, sn.nchains);
2470 for i = 1:sn.nchains
2471 sn.nodevisits{1,i} = JLINE.from_jline_matrix(jsn.nodevisits.get(uint32(i-1)));
2472 end
2473 else
2474 sn.nodevisits = {};
2475 end
2476
2477 if ~isempty(jsn.droprule)
2478 sn.droprule = zeros(sn.nstations, sn.nclasses);
2479 for i = 1:sn.nstations
2480 for j = 1:sn.nclasses
2481 dropStrategy = jsn.droprule.get(jstations.get(i-1)).get(jclasses.get(j-1));
2482 switch dropStrategy.name.toCharArray'
2483 case 'WaitingQueue'
2484 sn.droprule(i,j) = DropStrategy.WAITQ;
2485 case 'Drop'
2486 sn.droprule(i,j) = DropStrategy.DROP;
2487 case 'BlockingAfterService'
2488 sn.droprule(i,j) = DropStrategy.BAS;
2489 end
2490 end
2491 end
2492 else
2493 sn.droprule = [];
2494 end
2495
2496 if ~isempty(jsn.nodeparam)
2497 sn.nodeparam = cell(sn.nnodes, 1);
2498
2499 for i = 1:sn.nnodes
2500 jnode = jnodes.get(i-1);
2501 jparam = jsn.nodeparam.get(jnode);
2502
2503 %if jparam.isEmpty
2504 % sn.nodeparam{i} = [];
2505 % continue;
2506 %end
2507
2508 % StationNodeParam
2509 if isa(jparam, 'jline.lang.nodeparam.StationNodeParam')
2510 if ~isempty(jparam.fileName)
2511 sn.nodeparam{i}.fileName = cell(1, sn.nclasses);
2512 for r = 1:sn.nclasses
2513 fname = jparam.fileName.get(r-1);
2514 if ~isempty(fname)
2515 sn.nodeparam{i}.fileName{r} = char(fname);
2516 end
2517 end
2518 end
2519 end
2520
2521 % TransitionNodeParam
2522 if isa(jparam, 'jline.lang.nodeparam.TransitionNodeParam')
2523 if ~isempty(jparam.firingprocid)
2524 sn.nodeparam{i}.firingprocid = containers.Map('KeyType', 'char', 'ValueType', 'any');
2525 keys = jparam.firingprocid.keySet.iterator;
2526 while keys.hasNext
2527 key = keys.next;
2528 proc = jparam.firingprocid.get(key);
2529 sn.nodeparam{i}.firingprocid(char(key.toString)) = char(proc.toString);
2530 end
2531 end
2532 if ~isempty(jparam.firingphases)
2533 sn.nodeparam{i}.firingphases = JLINE.from_jline_matrix(jparam.firingphases);
2534 end
2535 if ~isempty(jparam.fireweight)
2536 sn.nodeparam{i}.fireweight = JLINE.from_jline_matrix(jparam.fireweight);
2537 end
2538 end
2539
2540 % JoinNodeParam
2541 if isa(jparam, 'jline.lang.nodeparam.JoinNodeParam')
2542 if ~isempty(jparam.joinStrategy)
2543 sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
2544 sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
2545 for r = 1:sn.nclasses
2546 jclass = jclasses.get(r-1);
2547 joinStrategy = jparam.joinStrategy.get(jclass);
2548 if ~isempty(joinStrategy)
2549 strategyStr = char(joinStrategy.name.toString);
2550 switch strategyStr
2551 case 'STD'
2552 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
2553 case 'PARTIAL'
2554 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
2555 otherwise
2556 sn.nodeparam{i}.joinStrategy{r} = strategyStr;
2557 end
2558 sn.nodeparam{i}.fanIn{r} = jparam.fanIn.get(jclass);
2559 end
2560 end
2561 end
2562 end
2563
2564 % RoutingNodeParam
2565 if isa(jparam, 'jline.lang.nodeparam.RoutingNodeParam')
2566 for r = 1:sn.nclasses
2567 jclass = jclasses.get(r-1);
2568
2569 if ~isempty(jparam.weights) && jparam.weights.containsKey(jclass)
2570 sn.nodeparam{i}.weights{r} = JLINE.from_jline_matrix(jparam.weights.get(jclass));
2571 end
2572
2573 if ~isempty(jparam.outlinks) && jparam.outlinks.containsKey(jclass)
2574 sn.nodeparam{i}.outlinks{r} = JLINE.from_jline_matrix(jparam.outlinks.get(jclass));
2575 end
2576 end
2577 end
2578
2579 % ForkNodeParam
2580 if isa(jparam, 'jline.lang.nodeparam.ForkNodeParam')
2581 if ~isnan(jparam.fanOut)
2582 sn.nodeparam{i}.fanOut = jparam.fanOut;
2583 end
2584 end
2585
2586 % CacheNodeParam
2587 if isa(jparam, 'jline.lang.nodeparam.CacheNodeParam')
2588 % nitems
2589 if ~isnan(jparam.nitems)
2590 sn.nodeparam{i}.nitems = jparam.nitems;
2591 end
2592
2593 % accost
2594 if ~isempty(jparam.accost)
2595 % For Java 2D arrays (Matrix[][]), size(arr,2) returns 1 in MATLAB
2596 % We need to get length of first row to get actual second dimension
2597 K1 = size(jparam.accost, 1);
2598 if K1 > 0
2599 firstRow = jparam.accost(1); % Get first row (Java array)
2600 K2 = length(firstRow);
2601 else
2602 K2 = 0;
2603 end
2604 sn.nodeparam{i}.accost = cell(K1, K2);
2605 for k1 = 1:K1
2606 for k2 = 1:K2
2607 mat = jparam.accost(k1, k2); % MATLAB handles Java array indexing
2608 if ~isempty(mat)
2609 sn.nodeparam{i}.accost{k1, k2} = JLINE.from_jline_matrix(mat);
2610 end
2611 end
2612 end
2613 end
2614
2615 % itemcap
2616 if ~isempty(jparam.itemcap)
2617 sn.nodeparam{i}.itemcap = JLINE.from_jline_matrix(jparam.itemcap);
2618 end
2619
2620 % pread - convert from Java Map<Integer, List<Double>> to MATLAB cell array {R}
2621 if ~isempty(jparam.pread)
2622 nclasses = sn.nclasses;
2623 sn.nodeparam{i}.pread = cell(1, nclasses);
2624 for r = 1:nclasses
2625 list = jparam.pread.get(int32(r-1)); % Java 0-based indexing
2626 if ~isempty(list)
2627 values = zeros(1, list.size);
2628 for j = 1:list.size
2629 values(j) = list.get(j-1);
2630 end
2631 sn.nodeparam{i}.pread{r} = values;
2632 else
2633 sn.nodeparam{i}.pread{r} = NaN;
2634 end
2635 end
2636 end
2637
2638 % replacestrat
2639 if ~isempty(jparam.replacestrat)
2640 switch char(jparam.replacestrat)
2641 case 'RR'
2642 sn.nodeparam{i}.replacestrat = ReplacementStrategy.RR;
2643 case 'FIFO'
2644 sn.nodeparam{i}.replacestrat = ReplacementStrategy.FIFO;
2645 case 'SFIFO'
2646 sn.nodeparam{i}.replacestrat = ReplacementStrategy.SFIFO;
2647 case 'LRU'
2648 sn.nodeparam{i}.replacestrat = ReplacementStrategy.LRU;
2649 end
2650 end
2651
2652 % hitclass
2653 if ~isempty(jparam.hitclass)
2654 sn.nodeparam{i}.hitclass = 1+JLINE.from_jline_matrix(jparam.hitclass);
2655 end
2656
2657 % missclass
2658 if ~isempty(jparam.missclass)
2659 sn.nodeparam{i}.missclass =1+ JLINE.from_jline_matrix(jparam.missclass);
2660 end
2661
2662 % actual hit/miss probabilities
2663 if ~isempty(jparam.actualhitprob)
2664 sn.nodeparam{i}.actualhitprob = JLINE.from_jline_matrix(jparam.actualhitprob);
2665 end
2666 if ~isempty(jparam.actualmissprob)
2667 sn.nodeparam{i}.actualmissprob = JLINE.from_jline_matrix(jparam.actualmissprob);
2668 end
2669 end
2670 end
2671 else
2672 sn.nodeparam = {};
2673 end
2674
2675 % if ~isempty(jsn.nodeparam)
2676 % sn.nodeparam = cell(sn.nnodes, 1);
2677 % % Note that JLINE only support node parameters related to
2678 % % Fork, Join, WWROBIN and RROBIN
2679 % for i = 1:sn.nnodes
2680 % if jsn.nodeparam.get(jnodes.get(i-1)).isEmpty
2681 % sn.nodeparam{i} = [];
2682 % else
2683 % if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).nitems)
2684 % sn.nodeparam{i}.nitems = jsn.nodeparam.get(jnodes.get(i-1)).nitems;
2685 % end
2686 % if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).fanOut)
2687 % sn.nodeparam{i}.fanOut = jsn.nodeparam.get(jnodes.get(i-1)).fanOut;
2688 % end
2689 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy)
2690 % if ~jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.isEmpty
2691 % sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
2692 % sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
2693 % for r = 1:sn.nclasses
2694 % joinStrategy = jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.get(jclasses.get(r-1));
2695 % switch joinStrategy.name.toCharArray'
2696 % case 'STD'
2697 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
2698 % case 'PARTIAL'
2699 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
2700 % end
2701 % sn.nodeparam{i}.fanIn{r} = jsn.nodeparam.get(jnodes.get(i-1)).fanIn.get(jclasses.get(r-1));
2702 % end
2703 % end
2704 % end
2705 %
2706 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).weights)
2707 % for r = 1:sn.nclasses
2708 % sn.nodeparam{i}{r}.weights = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).weights.get(jclasses.get(r-1)));
2709 % end
2710 % end
2711 %
2712 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).outlinks)
2713 % for r = 1:sn.nclasses
2714 % sn.nodeparam{i}{r}.outlinks = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).outlinks.get(jclasses.get(r-1)));
2715 % end
2716 % end
2717 % end
2718 % end
2719 % else
2720 % sn.nodeparam = {};
2721 % end
2722
2723 if ~isempty(jsn.sync)
2724 jsync = jsn.sync;
2725 sn.sync = cell(jsync.size, 1);
2726 for i = 1:jsync.size
2727 jsync_i = jsync.get(uint32(i-1));
2728 sn.sync{i,1} = struct('active',cell(1),'passive',cell(1));
2729
2730 jactive = jsync_i.active.get(uint32(0));
2731 jpassive = jsync_i.passive.get(uint32(0));
2732
2733 %Currently assume that prob would always be a value
2734 %instead of lambda function (No idea of how to convert
2735 %Java lambda function to matlab lambda function)
2736 switch jactive.getEvent.name.toCharArray'
2737 case 'INIT'
2738 sn.sync{i,1}.active{1} = Event(EventType.INIT, jactive.getNode+1, jactive.getJobClass+1, ...
2739 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2740 jactive.getT, jactive.getJob);
2741 case 'LOCAL'
2742 sn.sync{i,1}.active{1} = Event(EventType.LOCAL, jactive.getNode+1, jactive.getJobClass+1, ...
2743 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2744 jactive.getT, jactive.getJob);
2745 case 'ARV'
2746 sn.sync{i,1}.active{1} = Event(EventType.ARV, jactive.getNode+1, jactive.getJobClass+1, ...
2747 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2748 jactive.getT, jactive.getJob);
2749 case 'DEP'
2750 sn.sync{i,1}.active{1} = Event(EventType.DEP, jactive.getNode+1, jactive.getJobClass+1, ...
2751 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2752 jactive.getT, jactive.getJob);
2753 case 'PHASE'
2754 sn.sync{i,1}.active{1} = Event(EventType.PHASE, jactive.getNode+1, jactive.getJobClass+1, ...
2755 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2756 jactive.getT, jactive.getJob);
2757 case 'READ'
2758 sn.sync{i,1}.active{1} = Event(EventType.READ, jactive.getNode+1, jactive.getJobClass+1, ...
2759 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2760 jactive.getT, jactive.getJob);
2761 case 'STAGE'
2762 sn.sync{i,1}.active{1} = Event(EventType.STAGE, jactive.getNode+1, jactive.getJobClass+1, ...
2763 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2764 jactive.getT, jactive.getJob);
2765 end
2766
2767 switch jpassive.getEvent.name.toCharArray'
2768 case 'INIT'
2769 sn.sync{i,1}.passive{1} = Event(EventType.INIT, jpassive.getNode+1, jpassive.getJobClass+1, ...
2770 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2771 jpassive.getT, jpassive.getJob);
2772 case 'LOCAL'
2773 sn.sync{i,1}.passive{1} = Event(EventType.LOCAL, jpassive.getNode+1, jpassive.getJobClass+1, ...
2774 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2775 jpassive.getT, jpassive.getJob);
2776 case 'ARV'
2777 sn.sync{i,1}.passive{1} = Event(EventType.ARV, jpassive.getNode+1, jpassive.getJobClass+1, ...
2778 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2779 jpassive.getT, jpassive.getJob);
2780 case 'DEP'
2781 sn.sync{i,1}.passive{1} = Event(EventType.DEP, jpassive.getNode+1, jpassive.getJobClass+1, ...
2782 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2783 jpassive.getT, jpassive.getJob);
2784 case 'PHASE'
2785 sn.sync{i,1}.passive{1} = Event(EventType.PHASE, jpassive.getNode+1, jpassive.getJobClass+1, ...
2786 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2787 jpassive.getT, jpassive.getJob);
2788 case 'READ'
2789 sn.sync{i,1}.passive{1} = Event(EventType.READ, jpassive.getNode+1, jpassive.getJobClass+1, ...
2790 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2791 jpassive.getT, jpassive.getJob);
2792 case 'STAGE'
2793 sn.sync{i,1}.passive{1} = Event(EventType.STAGE, jpassive.getNode+1, jpassive.getJobClass+1, ...
2794 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2795 jpassive.getT, jpassive.getJob);
2796 end
2797 end
2798 else
2799 sn.sync = {};
2800 end
2801 end
2802
2803 function [QN,UN,RN,WN,AN,TN] = arrayListToResults(alist)
2804 switch class(alist)
2805 case 'jline.solvers.LayeredNetworkAvgTable'
2806 QN = JLINE.arraylist_to_matrix(alist.getQLen());
2807 UN = JLINE.arraylist_to_matrix(alist.getUtil());
2808 RN = JLINE.arraylist_to_matrix(alist.getRespT());
2809 WN = JLINE.arraylist_to_matrix(alist.getResidT());
2810 AN = NaN*JLINE.arraylist_to_matrix(alist.getTput()); % getArvR not yet available in JLINE
2811 TN = JLINE.arraylist_to_matrix(alist.getTput());
2812 otherwise
2813 QN = JLINE.arraylist_to_matrix(alist.getQLen());
2814 UN = JLINE.arraylist_to_matrix(alist.getUtil());
2815 RN = JLINE.arraylist_to_matrix(alist.getRespT());
2816 WN = JLINE.arraylist_to_matrix(alist.getResidT());
2817 AN = JLINE.arraylist_to_matrix(alist.getArvR());
2818 TN = JLINE.arraylist_to_matrix(alist.getTput());
2819 end
2820 end
2821
2822 function featSupported = getFeatureSet()
2823 % FEATSUPPORTED = GETFEATURESET()
2824
2825 featSupported = SolverFeatureSet;
2826 featSupported.setTrue({'Sink','Source',...
2827 'ClassSwitch','Delay','DelayStation','Queue',...
2828 'APH','Coxian','Erlang','Exp','HyperExp',...
2829 'StatelessClassSwitcher','InfiniteServer','SharedServer','Buffer','Dispatcher',...
2830 'Server','JobSink','RandomSource','ServiceTunnel',...
2831 'SchedStrategy_INF','SchedStrategy_PS',...
2832 'RoutingStrategy_PROB','RoutingStrategy_RAND',...
2833 'ClosedClass','OpenClass'});
2834 end
2835
2836 function [bool, featSupported] = supports(model)
2837 % [BOOL, FEATSUPPORTED] = SUPPORTS(MODEL)
2838
2839 featUsed = model.getUsedLangFeatures();
2840 featSupported = JLINE.getFeatureSet();
2841 bool = SolverFeatureSet.supports(featSupported, featUsed);
2842 end
2843
2844
2845 function solverOptions = parseSolverOptions(solverOptions, options)
2846 fn = fieldnames(options);
2847 fn2 = fieldnames(solverOptions);
2848 for f = 1:length(fn)
2849 found = 0;
2850 for j = 1:length(fn2)
2851 if strcmp(fn{f}, fn2{j})
2852 found = 1;
2853 switch fn{f}
2854 case 'seed'
2855 solverOptions.seed = options.seed;
2856 case 'samples'
2857 solverOptions.samples = options.samples;
2858 case 'confint'
2859 % Parse confint - can be a level (0.95) or 0 to disable
2860 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
2861 if confintEnabled
2862 solverOptions.confint = confintLevel;
2863 else
2864 solverOptions.confint = 0;
2865 end
2866 case 'method'
2867 solverOptions.method = options.method;
2868 case 'config'
2869 if isfield(options.config,'eventcache')
2870 solverOptions.config.eventcache = options.config.eventcache;
2871 end
2872 if isfield(options.config,'fork_join')
2873 solverOptions.config.fork_join = options.config.fork_join;
2874 end
2875 if isfield(options.config,'highvar')
2876 solverOptions.config.highvar = options.config.highvar;
2877 end
2878 if isfield(options.config,'multiserver')
2879 solverOptions.config.multiserver = options.config.multiserver;
2880 end
2881 if isfield(options.config,'np_priority')
2882 solverOptions.config.np_priority = options.config.np_priority;
2883 end
2884 case 'verbose'
2885 switch options.(fn{f})
2886 case {VerboseLevel.SILENT}
2887 solverOptions.verbose = solverOptions.verbose.SILENT;
2888 case {VerboseLevel.STD}
2889 solverOptions.verbose = solverOptions.verbose.STD;
2890 case {VerboseLevel.DEBUG}
2891 solverOptions.verbose = solverOptions.verbose.DEBUG;
2892 end
2893 case 'init_sol'
2894 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.init_sol);
2895 case 'cutoff'
2896 if isscalar(options.cutoff)
2897 solverOptions.(fn{f}) = jline.util.matrix.Matrix.singleton(options.cutoff);
2898 else
2899 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.cutoff);
2900 end
2901 case 'odesolvers'
2902 case 'rewardIterations'
2903 solverOptions.rewardIterations = java.lang.Integer(options.rewardIterations);
2904 otherwise
2905 solverOptions.(fn{f}) = options.(fn{f});
2906 end
2907
2908 break;
2909 end
2910 end
2911 if ~found
2912 line_printf('Could not find option %s in the JLINE options.\n', fn{f});
2913 end
2914 end
2915 end
2916
2917 function [ssa] = SolverSSA(network_object, options)
2918 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.SSA);
2919 if nargin>1
2920 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2921 end
2922 jline.util.Maths.setRandomNumbersMatlab(true);
2923 ssa = jline.solvers.ssa.SolverSSA(network_object, solverOptions);
2924 end
2925
2926 function [mam] = SolverMAM(network_object, options)
2927 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MAM);
2928 if nargin>1
2929 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2930 end
2931 mam = jline.solvers.mam.SolverMAM(network_object, solverOptions);
2932 end
2933
2934 function [jmt] = SolverJMT(network_object, options)
2935 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.JMT);
2936 if nargin>1
2937 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2938 end
2939 jmt = jline.solvers.jmt.SolverJMT(network_object, solverOptions);
2940 end
2941
2942 function [ctmc] = SolverCTMC(network_object, options)
2943 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.CTMC);
2944 if nargin>1
2945 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2946 end
2947 ctmc = jline.solvers.ctmc.SolverCTMC(network_object,solverOptions);
2948 end
2949
2950 function [fluid] = SolverFluid(network_object, options)
2951 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.FLUID);
2952 if nargin>1
2953 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2954 end
2955 fluid = jline.solvers.fluid.SolverFluid(network_object, solverOptions);
2956 end
2957
2958 function [QN, UN, RN, TN, CN, XN, t, QNt, UNt, TNt, xvec] = runFluidAnalyzer(network, options)
2959 % RUNFLUIDANALYZER Run JLINE fluid analyzer and return results
2960 %
2961 % [QN, UN, RN, TN, CN, XN, T, QNT, UNT, TNT, XVEC] = JLINE.runFluidAnalyzer(NETWORK, OPTIONS)
2962 %
2963 % Runs the JLINE fluid solver on the given network and converts
2964 % results back to MATLAB data structures.
2965 %
2966 % Input:
2967 % network - LINE Network model
2968 % options - Solver options structure with fields:
2969 % .method - solver method
2970 % .stiff - use stiff ODE solver
2971 %
2972 % Output:
2973 % QN, UN, RN, TN - Steady-state metrics [M x K]
2974 % CN, XN - System metrics [1 x K]
2975 % t - Time vector [Tmax x 1]
2976 % QNt, UNt, TNt - Transient metrics {M x K} cells
2977 % xvec - State vector structure
2978
2979 jmodel = LINE2JLINE(network);
2980 jsolver = JLINE.SolverFluid(jmodel);
2981 import jline.solvers.fluid.*;
2982
2983 jsolver.options.method = options.method;
2984 jsolver.options.stiff = options.stiff;
2985 result = jsolver.runMethodSpecificAnalyzerViaLINE();
2986
2987 % Convert JLINE result to MATLAB data structures
2988 M = jmodel.getNumberOfStatefulNodes();
2989 K = jmodel.getNumberOfClasses();
2990
2991 QN = NaN * zeros(M, K);
2992 UN = NaN * zeros(M, K);
2993 RN = NaN * zeros(M, K);
2994 TN = NaN * zeros(M, K);
2995 CN = NaN * zeros(1, K);
2996 XN = NaN * zeros(1, K);
2997
2998 QNt = cell(M, K);
2999 UNt = cell(M, K);
3000 TNt = cell(M, K);
3001
3002 Tmax = result.t.length();
3003 t = NaN * zeros(Tmax, 1);
3004
3005 for ist = 1:M
3006 for jst = 1:K
3007 QN(ist, jst) = result.QN.get(ist-1, jst-1);
3008 UN(ist, jst) = result.UN.get(ist-1, jst-1);
3009 RN(ist, jst) = result.RN.get(ist-1, jst-1);
3010 TN(ist, jst) = result.TN.get(ist-1, jst-1);
3011 end
3012 end
3013
3014 for jst = 1:K
3015 CN(1, jst) = result.CN.get(0, jst-1);
3016 XN(1, jst) = result.XN.get(0, jst-1);
3017 end
3018
3019 for ist = 1:M
3020 for jst = 1:K
3021 for p = 1:Tmax
3022 QNt{ist, jst}(p, 1) = result.QNt(ist, jst).get(p-1, 0);
3023 UNt{ist, jst}(p, 1) = result.UNt(ist, jst).get(p-1, 0);
3024 TNt{ist, jst}(p, 1) = result.TNt(ist, jst).get(p-1, 0);
3025 end
3026 end
3027 end
3028
3029 for p = 1:Tmax
3030 t(p, 1) = result.t.get(p-1, 0);
3031 end
3032
3033 % JLINE does not return odeStateVec
3034 xvec.odeStateVec = [];
3035 xvec.sn = network;
3036 end
3037
3038 function [ldes] = SolverLDES(network_object, options)
3039 % Create LDES-specific options object
3040 ldesOptions = jline.solvers.ldes.LDESOptions();
3041 if nargin>1
3042 % Copy standard options
3043 ldesOptions.samples = options.samples;
3044 ldesOptions.seed = options.seed;
3045 % Parse confint
3046 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
3047 if confintEnabled
3048 ldesOptions.confint = confintLevel;
3049 else
3050 ldesOptions.confint = 0;
3051 end
3052 % Pass timespan for transient analysis
3053 if isfield(options, 'timespan') && length(options.timespan) >= 2
3054 ldesOptions.timespan = options.timespan;
3055 end
3056 % Pass LDES-specific options if configured
3057 if isfield(options, 'config')
3058 % Transient detection options
3059 if isfield(options.config, 'tranfilter')
3060 ldesOptions.tranfilter = options.config.tranfilter;
3061 end
3062 if isfield(options.config, 'mserbatch')
3063 ldesOptions.mserbatch = options.config.mserbatch;
3064 end
3065 if isfield(options.config, 'warmupfrac')
3066 ldesOptions.warmupfrac = options.config.warmupfrac;
3067 end
3068 % Confidence interval options
3069 if isfield(options.config, 'cimethod')
3070 ldesOptions.cimethod = options.config.cimethod;
3071 end
3072 if isfield(options.config, 'obmoverlap')
3073 ldesOptions.obmoverlap = options.config.obmoverlap;
3074 end
3075 if isfield(options.config, 'ciminbatch')
3076 ldesOptions.ciminbatch = options.config.ciminbatch;
3077 end
3078 if isfield(options.config, 'ciminobs')
3079 ldesOptions.ciminobs = options.config.ciminobs;
3080 end
3081 if isfield(options.config, 'spectralLowFreqFrac')
3082 ldesOptions.spectralLowFreqFrac = options.config.spectralLowFreqFrac;
3083 end
3084 % Convergence options
3085 if isfield(options.config, 'cnvgon')
3086 ldesOptions.cnvgon = options.config.cnvgon;
3087 end
3088 if isfield(options.config, 'cnvgtol')
3089 ldesOptions.cnvgtol = options.config.cnvgtol;
3090 end
3091 if isfield(options.config, 'cnvgbatch')
3092 ldesOptions.cnvgbatch = options.config.cnvgbatch;
3093 end
3094 if isfield(options.config, 'cnvgchk')
3095 ldesOptions.cnvgchk = options.config.cnvgchk;
3096 end
3097 end
3098 end
3099 ldes = jline.solvers.ldes.SolverLDES(network_object, ldesOptions);
3100 end
3101
3102 function [mva] = SolverMVA(network_object, options)
3103 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MVA);
3104 if nargin>1
3105 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3106 end
3107 mva = jline.solvers.mva.SolverMVA(network_object, solverOptions);
3108 end
3109
3110 function [nc] = SolverNC(network_object, options)
3111 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.NC);
3112 if nargin>1
3113 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3114 end
3115 nc = jline.solvers.nc.SolverNC(network_object, solverOptions);
3116 end
3117
3118 function [auto] = SolverAuto(network_object, options)
3119 solverOptions = jline.solvers.auto.AUTOptions();
3120 if nargin>1
3121 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3122 end
3123 auto = jline.solvers.auto.SolverAUTO(network_object, solverOptions);
3124 end
3125
3126 function streamOpts = StreamingOptions(varargin)
3127 % STREAMINGOPTIONS Create Java StreamingOptions for SSA/LDES stream() method
3128 %
3129 % @brief Creates StreamingOptions for streaming simulation metrics
3130 %
3131 % @param varargin Name-value pairs for options:
3132 % 'transport' - 'http' (recommended) or 'grpc' (default: 'http')
3133 % 'endpoint' - Receiver endpoint (default: 'localhost:8080/metrics' for HTTP)
3134 % 'mode' - 'sampled' or 'time_window' (default: 'sampled')
3135 % 'sampleFrequency' - Push every N events in sampled mode (default: 100)
3136 % 'timeWindowSeconds' - Window duration in time_window mode (default: 1.0)
3137 % 'serviceName' - Service identifier (default: 'line-stream')
3138 % 'includeQueueLength' - Include queue length metrics (default: true)
3139 % 'includeUtilization' - Include utilization metrics (default: true)
3140 % 'includeThroughput' - Include throughput metrics (default: true)
3141 % 'includeResponseTime' - Include response time metrics (default: true)
3142 % 'includeArrivalRate' - Include arrival rate metrics (default: true)
3143 %
3144 % @return streamOpts Java StreamingOptions object
3145 %
3146 % Example:
3147 % @code
3148 % streamOpts = JLINE.StreamingOptions('transport', 'http', 'sampleFrequency', 50);
3149 % @endcode
3150
3151 streamOpts = jline.streaming.StreamingOptions();
3152
3153 % Parse optional arguments
3154 p = inputParser;
3155 addParameter(p, 'transport', 'http', @ischar);
3156 addParameter(p, 'endpoint', '', @ischar); % Empty means use default for transport
3157 addParameter(p, 'mode', 'sampled', @ischar);
3158 addParameter(p, 'sampleFrequency', 100, @isnumeric);
3159 addParameter(p, 'timeWindowSeconds', 1.0, @isnumeric);
3160 addParameter(p, 'serviceName', 'line-stream', @ischar);
3161 addParameter(p, 'includeQueueLength', true, @islogical);
3162 addParameter(p, 'includeUtilization', true, @islogical);
3163 addParameter(p, 'includeThroughput', true, @islogical);
3164 addParameter(p, 'includeResponseTime', true, @islogical);
3165 addParameter(p, 'includeArrivalRate', true, @islogical);
3166 parse(p, varargin{:});
3167
3168 % Set transport type
3169 transportTypes = javaMethod('values', 'jline.streaming.StreamingOptions$TransportType');
3170 switch lower(p.Results.transport)
3171 case 'http'
3172 streamOpts.transport = transportTypes(1); % HTTP
3173 case 'grpc'
3174 streamOpts.transport = transportTypes(2); % GRPC
3175 otherwise
3176 streamOpts.transport = transportTypes(1); % Default to HTTP
3177 end
3178
3179 % Set endpoint (use provided or default based on transport)
3180 if ~isempty(p.Results.endpoint)
3181 streamOpts.endpoint = p.Results.endpoint;
3182 end
3183 % If empty, StreamingOptions uses its default for the transport type
3184
3185 % Set mode
3186 streamModes = javaMethod('values', 'jline.streaming.StreamingOptions$StreamMode');
3187 switch lower(p.Results.mode)
3188 case 'sampled'
3189 streamOpts.mode = streamModes(1); % SAMPLED
3190 case 'time_window'
3191 streamOpts.mode = streamModes(2); % TIME_WINDOW
3192 otherwise
3193 streamOpts.mode = streamModes(1); % Default to SAMPLED
3194 end
3195
3196 % Set other options
3197 streamOpts.sampleFrequency = p.Results.sampleFrequency;
3198 streamOpts.timeWindowSeconds = p.Results.timeWindowSeconds;
3199 streamOpts.serviceName = p.Results.serviceName;
3200 streamOpts.includeQueueLength = p.Results.includeQueueLength;
3201 streamOpts.includeUtilization = p.Results.includeUtilization;
3202 streamOpts.includeThroughput = p.Results.includeThroughput;
3203 streamOpts.includeResponseTime = p.Results.includeResponseTime;
3204 streamOpts.includeArrivalRate = p.Results.includeArrivalRate;
3205 end
3206
3207 function result = convertSampleResult(jresult)
3208 % CONVERTSAMPLERESULT Convert Java sample result to MATLAB struct
3209 %
3210 % @brief Converts Java SampleNodeState to MATLAB structure
3211 %
3212 % @param jresult Java SampleNodeState object
3213 % @return result MATLAB struct with fields: t, state, isaggregate
3214
3215 result = struct();
3216
3217 % Convert time matrix
3218 if ~isempty(jresult.t)
3219 result.t = JLINE.from_jline_matrix(jresult.t);
3220 else
3221 result.t = [];
3222 end
3223
3224 % Convert state matrix
3225 if ~isempty(jresult.state) && isa(jresult.state, 'jline.util.matrix.Matrix')
3226 result.state = JLINE.from_jline_matrix(jresult.state);
3227 else
3228 result.state = [];
3229 end
3230
3231 result.isaggregate = jresult.isaggregate;
3232 end
3233
3234 function [ln] = SolverLN(layered_network_object, options)
3235 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.LN);
3236 if nargin>1
3237 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3238 end
3239 ln = jline.solvers.ln.SolverLN(layered_network_object, solverOptions);
3240 end
3241
3242 function serfun = handle_to_serializablefun(handle, sn)
3243 % HANDLE_TO_SERIALIZABLEFUN Convert MATLAB function handle to Java SerializableFunction
3244 %
3245 % This function pre-computes the function values for all possible state
3246 % combinations and creates a Java PrecomputedCDFunction object.
3247 %
3248 % @param handle MATLAB function handle that takes a vector ni and returns a scalar
3249 % @param sn Network struct containing njobs (population per class)
3250 % @return serfun Java PrecomputedCDFunction object
3251
3252 % Get number of classes and maximum populations
3253 nclasses = sn.nclasses;
3254 njobs = sn.njobs; % Population per class
3255
3256 % For open classes (njobs=0), use a reasonable bound
3257 maxPop = njobs;
3258 for r = 1:nclasses
3259 if maxPop(r) == 0 || isinf(maxPop(r))
3260 % For open classes, use sum of closed class populations or 100 as bound
3261 maxPop(r) = max(100, sum(njobs(isfinite(njobs) & njobs > 0)));
3262 end
3263 end
3264
3265 % Create Java PrecomputedCDFunction object
3266 serfun = jline.util.PrecomputedCDFunction(nclasses);
3267
3268 % Enumerate all possible state combinations and pre-compute function values
3269 % Use recursive enumeration to handle arbitrary number of classes
3270 JLINE.enumerate_states(handle, serfun, maxPop, zeros(1, nclasses), 1);
3271 end
3272
3273 function enumerate_states(handle, serfun, maxPop, currentState, classIdx)
3274 % ENUMERATE_STATES Recursively enumerate all state combinations
3275 %
3276 % @param handle MATLAB function handle
3277 % @param serfun Java PrecomputedCDFunction object to populate
3278 % @param maxPop Maximum population per class
3279 % @param currentState Current state being built
3280 % @param classIdx Current class index being enumerated
3281
3282 nclasses = length(maxPop);
3283
3284 if classIdx > nclasses
3285 % We have a complete state, compute and store the function value
3286 try
3287 value = handle(currentState);
3288 % Convert to Java int array and add to serfun
3289 jstate = jline.util.matrix.Matrix(1, nclasses);
3290 for r = 1:nclasses
3291 jstate.set(0, r-1, currentState(r));
3292 end
3293 serfun.addValue(jstate, value);
3294 catch
3295 % If function evaluation fails, skip this state
3296 end
3297 return;
3298 end
3299
3300 % Enumerate all populations for current class
3301 for n = 0:maxPop(classIdx)
3302 currentState(classIdx) = n;
3303 JLINE.enumerate_states(handle, serfun, maxPop, currentState, classIdx + 1);
3304 end
3305 end
3306
3307 function result = call_java_cdscaling(jfun, ni)
3308 % CALL_JAVA_CDSCALING Call a Java SerializableFunction for class dependence
3309 %
3310 % This function converts a MATLAB vector to a Java Matrix and calls
3311 % the Java function's apply() method.
3312 %
3313 % @param jfun Java SerializableFunction<Matrix, Double> object
3314 % @param ni MATLAB vector representing the state (jobs per class)
3315 % @return result The scaling factor returned by the Java function
3316
3317 % Convert MATLAB vector to Java Matrix
3318 if isrow(ni)
3319 jmatrix = jline.util.matrix.Matrix(1, length(ni));
3320 for r = 1:length(ni)
3321 jmatrix.set(0, r-1, ni(r));
3322 end
3323 else
3324 jmatrix = jline.util.matrix.Matrix(length(ni), 1);
3325 for r = 1:length(ni)
3326 jmatrix.set(r-1, 0, ni(r));
3327 end
3328 end
3329
3330 % Call the Java function and convert result to MATLAB double
3331 jresult = jfun.apply(jmatrix);
3332 result = double(jresult);
3333 end
3334
3335 function jSched = to_jline_sched_strategy(schedId)
3336 % Convert MATLAB SchedStrategy id to jline SchedStrategy enum
3337 switch schedId
3338 case SchedStrategy.REF
3339 jSched = jline.lang.constant.SchedStrategy.REF;
3340 case SchedStrategy.INF
3341 jSched = jline.lang.constant.SchedStrategy.INF;
3342 case SchedStrategy.FCFS
3343 jSched = jline.lang.constant.SchedStrategy.FCFS;
3344 case SchedStrategy.LCFS
3345 jSched = jline.lang.constant.SchedStrategy.LCFS;
3346 case SchedStrategy.SIRO
3347 jSched = jline.lang.constant.SchedStrategy.SIRO;
3348 case SchedStrategy.SJF
3349 jSched = jline.lang.constant.SchedStrategy.SJF;
3350 case SchedStrategy.LJF
3351 jSched = jline.lang.constant.SchedStrategy.LJF;
3352 case SchedStrategy.PS
3353 jSched = jline.lang.constant.SchedStrategy.PS;
3354 case SchedStrategy.DPS
3355 jSched = jline.lang.constant.SchedStrategy.DPS;
3356 case SchedStrategy.GPS
3357 jSched = jline.lang.constant.SchedStrategy.GPS;
3358 case SchedStrategy.SEPT
3359 jSched = jline.lang.constant.SchedStrategy.SEPT;
3360 case SchedStrategy.LEPT
3361 jSched = jline.lang.constant.SchedStrategy.LEPT;
3362 case {SchedStrategy.HOL, SchedStrategy.FCFSPRIO}
3363 jSched = jline.lang.constant.SchedStrategy.FCFSPRIO;
3364 case SchedStrategy.FORK
3365 jSched = jline.lang.constant.SchedStrategy.FORK;
3366 case SchedStrategy.EXT
3367 jSched = jline.lang.constant.SchedStrategy.EXT;
3368 case SchedStrategy.LCFSPR
3369 jSched = jline.lang.constant.SchedStrategy.LCFSPR;
3370 case SchedStrategy.PSPRIO
3371 jSched = jline.lang.constant.SchedStrategy.PSPRIO;
3372 case SchedStrategy.DPSPRIO
3373 jSched = jline.lang.constant.SchedStrategy.DPSPRIO;
3374 case SchedStrategy.GPSPRIO
3375 jSched = jline.lang.constant.SchedStrategy.GPSPRIO;
3376 otherwise
3377 jSched = jline.lang.constant.SchedStrategy.FCFS;
3378 end
3379 end
3380
3381 end
3382end
Definition mmt.m:124