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 case RoutingStrategy.KCHOICES
1308 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.KCHOICES);
1309 if length(output_strat) >= 3 && length(output_strat{3}) >= 2
1310 kparam = output_strat{3}{1};
1311 memparam = logical(output_strat{3}{2});
1312 jnodes.get(jnode_idx).setKChoicesRouting(jclasses.get(k-1), int32(kparam), memparam);
1313 end
1314 outlinks_i=find(connections(i,:))';
1315 if ~useLinkMethod
1316 for j= outlinks_i(:)'
1317 jdest_idx = matlab2java_node_idx(j);
1318 if jdest_idx >= 0
1319 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1320 end
1321 end
1322 end
1323 case RoutingStrategy.RL
1324 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RL);
1325 outlinks_i=find(connections(i,:))';
1326 if ~useLinkMethod
1327 for j= outlinks_i(:)'
1328 jdest_idx = matlab2java_node_idx(j);
1329 if jdest_idx >= 0
1330 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1331 end
1332 end
1333 end
1334 % Forward the value function, action nodes, and
1335 % state size from outputStrategy{r}{3..5} so the
1336 % JAR sub_rl can replicate MATLAB's decisions.
1337 if length(output_strat) >= 5
1338 valFnRaw = output_strat{3};
1339 nodesNeedAction = output_strat{4};
1340 stateSize = output_strat{5};
1341 if ~isempty(valFnRaw)
1342 if stateSize == 0
1343 % Tabular: flatten N-D array to a row vector and pass shape.
1344 shp = size(valFnRaw);
1345 jvfFlat = jline.util.matrix.Matrix(1, numel(valFnRaw));
1346 flat = valFnRaw(:);
1347 for f = 1:numel(flat)
1348 jvfFlat.set(0, f-1, double(flat(f)));
1349 end
1350 jshape = int32(shp(:)');
1351 jnna = int32(nodesNeedAction(:)' - 1); % MATLAB->Java 0-based
1352 jnodes.get(jnode_idx).setRLRouting(jclasses.get(k-1), jvfFlat, jshape, jnna, int32(stateSize));
1353 else
1354 % Linear approx: coefficient row vector.
1355 coeff = valFnRaw(:)';
1356 jvf = jline.util.matrix.Matrix(1, numel(coeff));
1357 for f = 1:numel(coeff)
1358 jvf.set(0, f-1, double(coeff(f)));
1359 end
1360 jnna = int32(nodesNeedAction(:)' - 1);
1361 jnodes.get(jnode_idx).setRLRouting(jclasses.get(k-1), jvf, int32([]), jnna, int32(stateSize));
1362 end
1363 end
1364 end
1365 otherwise
1366 line_warning(mfilename, sprintf('''%s'' routing strategy not supported by JLINE, setting as Disabled.\n',output_strat{2}));
1367 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1368 end
1369 end
1370 end
1371 end
1372 if useLinkMethod
1373 jmodel.link(jrt_matrix);
1374 % Align the sn.rtorig be the same, treating artificial
1375 % ClassSwitch nodes as if they were explicitly specified
1376 jsn = jmodel.getStruct(true);
1377 rtorig = java.util.HashMap();
1378 if ~isempty(model.sn.rtorig)
1379 if iscell(model.sn.rtorig)
1380 for r = 1:njclasses
1381 sub_rtorig = java.util.HashMap();
1382 for s = 1:njclasses
1383 sub_rtorig.put(jclasses.get(s-1), JLINE.from_line_matrix(model.sn.rtorig{r,s}));
1384 end
1385 rtorig.put(jclasses.get(r-1), sub_rtorig);
1386 end
1387 end
1388 end
1389 jsn.rtorig = rtorig;
1390 end
1391 end
1392
1393 function model = from_jline_routing(model, jnetwork)
1394 jnodes = jnetwork.getNodes();
1395 jclasses = jnetwork.getClasses();
1396 n_nodes = jnodes.size();
1397 network_nodes = model.getNodes;
1398 network_classes = model.getClasses;
1399
1400 % Build name-to-MATLAB-node map (JAR and MATLAB may order nodes differently)
1401 node_by_name = containers.Map();
1402 for nn = 1:length(network_nodes)
1403 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1404 end
1405
1406 connections = JLINE.from_jline_matrix(jnetwork.getConnectionMatrix());
1407 [row,col] = find(connections);
1408 for i=1:length(row)
1409 from_name = char(jnodes.get(row(i)-1).getName());
1410 to_name = char(jnodes.get(col(i)-1).getName());
1411 model.addLink(node_by_name(from_name), node_by_name(to_name));
1412 end
1413
1414 for n = 1 : n_nodes
1415 jnode = jnodes.get(n-1);
1416 cur_node = node_by_name(char(jnode.getName()));
1417 output_strategies = jnode.getOutputStrategies();
1418 n_strategies = output_strategies.size();
1419 for m = 1 : n_strategies
1420 output_strat = output_strategies.get(m-1);
1421 routing_strat = output_strat.getRoutingStrategy;
1422 routing_strat_classidx = output_strat.getJobClass.getIndex();
1423 switch char(routing_strat)
1424 case 'RAND'
1425 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RAND);
1426 case 'RROBIN'
1427 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1428 case 'WRROBIN'
1429 dest = output_strat.getDestination();
1430 if ~isempty(dest)
1431 dest_name = char(dest.getName());
1432 if node_by_name.isKey(dest_name)
1433 weight = output_strat.getProbability();
1434 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1435 end
1436 end
1437 case 'DISABLED'
1438 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.DISABLED);
1439 end
1440 end
1441 end
1442 end
1443
1444 function model = from_jline_links(model, jnetwork)
1445 P = model.initRoutingMatrix;
1446 jnodes = jnetwork.getNodes();
1447 jclasses = jnetwork.getClasses();
1448 n_classes = jclasses.size();
1449 n_nodes = jnodes.size();
1450 network_nodes = model.getNodes;
1451
1452 % Build JAR-to-MATLAB node index mapping (node orders may differ)
1453 jar2ml = zeros(1, n_nodes);
1454 for jj = 1:n_nodes
1455 jar_name = char(jnodes.get(jj-1).getName());
1456 for mm = 1:length(network_nodes)
1457 if strcmp(network_nodes{mm}.name, jar_name)
1458 jar2ml(jj) = mm;
1459 break;
1460 end
1461 end
1462 end
1463
1464 hasDestinations = false;
1465 for n = 1 : n_nodes
1466 jnode = jnodes.get(n-1);
1467 output_strategies = jnode.getOutputStrategies();
1468 n_strategies = output_strategies.size();
1469 for m = 1 : n_strategies
1470 output_strat = output_strategies.get(m-1);
1471 dest = output_strat.getDestination();
1472 if~isempty(dest) % disabled strategy
1473 hasDestinations = true;
1474 in_idx = jar2ml(jnetwork.getNodeIndex(jnode)+1);
1475 out_idx = jar2ml(jnetwork.getNodeIndex(dest)+1);
1476 if n_classes == 1
1477 P{1}(in_idx,out_idx) = output_strat.getProbability();
1478 else
1479 strat_class = output_strat.getJobClass();
1480 class_idx = jnetwork.getJobClassIndex(strat_class)+1;
1481 P{class_idx,class_idx}(in_idx,out_idx) = output_strat.getProbability();
1482 end
1483 end
1484 end
1485 end
1486
1487 % If no OutputStrategy entries had destinations (e.g., model
1488 % loaded from JSON via LineModelIO.load), fall back to rtorig
1489 if ~hasDestinations
1490 sn = jnetwork.getStruct;
1491 if ~isempty(sn.rtorig)
1492 % rtorig is station-indexed (no permutation needed —
1493 % station ordering matches between JAR and MATLAB)
1494 for r = 1:n_classes
1495 for s = 1:n_classes
1496 rtMat = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1497 if ~isempty(rtMat)
1498 P{r,s} = rtMat;
1499 end
1500 end
1501 end
1502 end
1503 end
1504
1505 model.link(P);
1506
1507 % Restore non-PROB routing strategies (RROBIN, WRROBIN, etc.)
1508 % after link(), which sets all routing to PROB
1509 network_nodes = model.getNodes;
1510 network_classes = model.getClasses;
1511 node_by_name = containers.Map();
1512 for nn = 1:length(network_nodes)
1513 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1514 end
1515 for n = 1 : n_nodes
1516 jnode = jnodes.get(n-1);
1517 cur_node = node_by_name(char(jnode.getName()));
1518 output_strategies = jnode.getOutputStrategies();
1519 n_strategies = output_strategies.size();
1520 for m = 1 : n_strategies
1521 output_strat = output_strategies.get(m-1);
1522 routing_strat = output_strat.getRoutingStrategy;
1523 routing_strat_classidx = output_strat.getJobClass.getIndex();
1524 switch char(routing_strat)
1525 case 'RROBIN'
1526 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1527 case 'WRROBIN'
1528 dest = output_strat.getDestination();
1529 if ~isempty(dest)
1530 dest_name = char(dest.getName());
1531 if node_by_name.isKey(dest_name)
1532 % Clear stale PROB entries before first WRROBIN weight
1533 classIdx = routing_strat_classidx;
1534 if length(cur_node.output.outputStrategy) >= classIdx && ...
1535 length(cur_node.output.outputStrategy{1, classIdx}) >= 3
1536 curStrat = cur_node.output.outputStrategy{1, classIdx}{2};
1537 if ~strcmp(curStrat, 'WeightedRoundRobin')
1538 cur_node.output.outputStrategy{1, classIdx}{3} = {};
1539 end
1540 end
1541 weight = output_strat.getProbability();
1542 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1543 end
1544 end
1545 end
1546 end
1547 end
1548
1549 % Invalidate cached struct after modifying routing strategies
1550 model.resetStruct();
1551
1552 %Align the sn.rtorig be the same (Assume Java network is
1553 %created by calling Network.link)
1554 sn = jnetwork.getStruct;
1555 rtorig = cell(n_classes, n_classes);
1556 for r = 1:n_classes
1557 for s = 1:n_classes
1558 rtorig{r,s} = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1559 end
1560 end
1561 model.sn.rtorig = rtorig;
1562 end
1563
1564 function [jnetwork] = from_line_network(model)
1565 %w = warning;
1566 %warning('off');
1567 sn = model.getStruct;
1568
1569 jnetwork = javaObject('jline.lang.Network', model.getName);
1570 line_nodes = model.getNodes;
1571 line_classes = model.getClasses;
1572
1573 jnodes = cell(1,length(line_nodes));
1574 jclasses = cell(1,length(line_classes));
1575
1576 for n = 1 : length(line_nodes)
1577 % Skip auto-added ClassSwitch nodes - Java's link() will add them automatically
1578 if isa(line_nodes{n}, 'ClassSwitch') && line_nodes{n}.autoAdded
1579 continue;
1580 end
1581 if isa(line_nodes{n}, 'Join')
1582 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, jnodes{line_nodes{n}.joinOf.index}, sn);
1583 else
1584 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, [], sn);
1585 end
1586 end
1587
1588 for n = 1 : length(line_classes)
1589 jclasses{n} = JLINE.from_line_class(line_classes{n}, jnetwork);
1590 end
1591
1592 % Set up forJobClass associations for signal classes
1593 for n = 1 : length(line_classes)
1594 if (isa(line_classes{n}, 'Signal') || isa(line_classes{n}, 'OpenSignal') || isa(line_classes{n}, 'ClosedSignal'))
1595 if ~isempty(line_classes{n}.targetJobClass)
1596 targetIdx = line_classes{n}.targetJobClass.index;
1597 jclasses{n}.forJobClass(jclasses{targetIdx});
1598 end
1599 end
1600 end
1601
1602 for n = 1: length(jnodes)
1603 if isempty(jnodes{n})
1604 continue; % Skip nodes that were not converted (e.g., auto-added ClassSwitch)
1605 end
1606 JLINE.set_service(line_nodes{n}, jnodes{n}, line_classes);
1607 JLINE.set_delayoff(line_nodes{n}, jnodes{n}, line_classes);
1608 end
1609
1610 % Set drop rules for stations (after classes are created)
1611 for n = 1: length(jnodes)
1612 if isempty(jnodes{n})
1613 continue; % Skip nodes that were not converted
1614 end
1615 if isa(line_nodes{n}, 'Station') && ~isa(line_nodes{n}, 'Source')
1616 for r = 1:length(line_classes)
1617 if length(line_nodes{n}.dropRule) >= r && ~isempty(line_nodes{n}.dropRule(r))
1618 dropRule = line_nodes{n}.dropRule(r);
1619 switch dropRule
1620 case DropStrategy.DROP
1621 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.Drop);
1622 case DropStrategy.BAS
1623 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.BlockingAfterService);
1624 case DropStrategy.WAITQ
1625 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.WaitingQueue);
1626 end
1627 end
1628 end
1629 end
1630 end
1631
1632 % Transfer LJCD (Limited Joint Class Dependence) scaling for stations
1633 % This must be done after classes are created since LJCD is indexed per-class
1634 for n = 1:length(jnodes)
1635 if isempty(jnodes{n})
1636 continue;
1637 end
1638 if isa(line_nodes{n}, 'Station') && ~isempty(line_nodes{n}.ljcdScaling) && ~isempty(line_nodes{n}.ljcdCutoffs)
1639 jCutoffs = JLINE.from_line_matrix(line_nodes{n}.ljcdCutoffs(:));
1640 K = length(line_nodes{n}.ljcdScaling);
1641 jScalingMap = java.util.HashMap();
1642 for c = 1:K
1643 if ~isempty(line_nodes{n}.ljcdScaling{c})
1644 jScalingVec = JLINE.from_line_matrix(line_nodes{n}.ljcdScaling{c}(:));
1645 jScalingMap.put(jclasses{c}, jScalingVec);
1646 end
1647 end
1648 jnodes{n}.setLimitedJointClassDependence(jScalingMap, jCutoffs);
1649 end
1650 end
1651
1652 % Set polling type and switchover times for polling queues
1653 for n = 1: length(jnodes)
1654 if isempty(jnodes{n})
1655 continue;
1656 end
1657 if isa(line_nodes{n}, 'Queue') && line_nodes{n}.schedStrategy == SchedStrategy.POLLING
1658 % Set polling type
1659 if ~isempty(line_nodes{n}.pollingType) && ~isempty(line_nodes{n}.pollingType{1})
1660 pollingType = line_nodes{n}.pollingType{1};
1661 switch pollingType
1662 case PollingType.GATED
1663 jPollingType = jline.lang.constant.PollingType.GATED;
1664 case PollingType.EXHAUSTIVE
1665 jPollingType = jline.lang.constant.PollingType.EXHAUSTIVE;
1666 case PollingType.KLIMITED
1667 jPollingType = jline.lang.constant.PollingType.KLIMITED;
1668 end
1669 if pollingType == PollingType.KLIMITED && ~isempty(line_nodes{n}.pollingPar)
1670 jnodes{n}.setPollingType(jPollingType, int32(line_nodes{n}.pollingPar));
1671 else
1672 jnodes{n}.setPollingType(jPollingType);
1673 end
1674 end
1675 % Set switchover times
1676 if ~isempty(line_nodes{n}.switchoverTime)
1677 for r = 1:length(line_classes)
1678 if length(line_nodes{n}.switchoverTime) >= r && ~isempty(line_nodes{n}.switchoverTime{r})
1679 soTime = line_nodes{n}.switchoverTime{r};
1680 if ~isa(soTime, 'Immediate')
1681 jnodes{n}.setSwitchover(jclasses{r}, JLINE.from_line_distribution(soTime));
1682 end
1683 end
1684 end
1685 end
1686 end
1687 end
1688
1689 for n = 1: length(jnodes)
1690 if isempty(jnodes{n})
1691 continue; % Skip nodes that were not converted
1692 end
1693 if isa(line_nodes{n},"ClassSwitch") && ~line_nodes{n}.autoAdded
1694 % Only set csMatrix for user-defined ClassSwitch nodes (not auto-added)
1695 JLINE.set_csMatrix(line_nodes{n}, jnodes{n}, jclasses);
1696 elseif isa(line_nodes{n},"Join")
1697 jnodes{n}.initJoinJobClasses();
1698 % Restore RAND routing for all classes, matching ClosedClass/OpenClass
1699 % constructor behavior (initJoinJobClasses sets DISABLED by default)
1700 for r = 1 : sn.nclasses
1701 jnodes{n}.setRouting(jclasses{r}, jline.lang.constant.RoutingStrategy.RAND);
1702 end
1703 elseif isa(line_nodes{n},"Cache")
1704 for r = 1 : sn.nclasses
1705 if length(line_nodes{n}.server.hitClass) >= r && ~isempty(line_nodes{n}.server.hitClass(r))
1706 if ~isa(line_nodes{n}.popularity{r},'Disabled')
1707 jnodes{n}.setRead(jclasses{r}, JLINE.from_line_distribution(line_nodes{n}.popularity{r}));
1708 jnodes{n}.setHitClass(jclasses{r}, jclasses{line_nodes{n}.server.hitClass(r)});
1709 jnodes{n}.setMissClass(jclasses{r}, jclasses{line_nodes{n}.server.missClass(r)});
1710 end
1711 end
1712 end
1713 % Transfer accessProb from MATLAB to Java
1714 if ~isempty(line_nodes{n}.accessProb)
1715 accessProbMat = line_nodes{n}.accessProb;
1716 [K1, K2] = size(accessProbMat);
1717 jAccessProb = javaArray('jline.util.matrix.Matrix', K1, K2);
1718 for k1 = 1:K1
1719 for k2 = 1:K2
1720 if ~isempty(accessProbMat{k1, k2})
1721 jAccessProb(k1, k2) = JLINE.from_line_matrix(accessProbMat{k1, k2});
1722 end
1723 end
1724 end
1725 jnodes{n}.setAccessProb(jAccessProb);
1726 end
1727 elseif isa(line_nodes{n}, "Transition")
1728 % First, add modes (must be done after classes are created)
1729 for m = 1:line_nodes{n}.getNumberOfModes()
1730 modeName = line_nodes{n}.modeNames{m};
1731 jmode = jnodes{n}.addMode(modeName);
1732 % Set timing strategy
1733 switch line_nodes{n}.timingStrategies(m)
1734 case TimingStrategy.TIMED
1735 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.TIMED);
1736 case TimingStrategy.IMMEDIATE
1737 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.IMMEDIATE);
1738 end
1739 % Set distribution
1740 jnodes{n}.setDistribution(jmode, JLINE.from_line_distribution(line_nodes{n}.distributions{m}));
1741 % Set firing weights and priorities
1742 jnodes{n}.setFiringWeights(jmode, line_nodes{n}.firingWeights(m));
1743 jnodes{n}.setFiringPriorities(jmode, int32(line_nodes{n}.firingPriorities(m)));
1744 % Set number of servers
1745 nsrv = line_nodes{n}.numberOfServers(m);
1746 if isinf(nsrv)
1747 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(intmax('int32')));
1748 else
1749 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(int32(nsrv)));
1750 end
1751 end
1752 % Now set enabling conditions, inhibiting conditions, and firing outcomes
1753 jmodes = jnodes{n}.getModes();
1754 for m = 1:line_nodes{n}.getNumberOfModes()
1755 jmode = jmodes.get(m-1);
1756 enabCond = line_nodes{n}.enablingConditions{m};
1757 inhibCond = line_nodes{n}.inhibitingConditions{m};
1758 firingOut = line_nodes{n}.firingOutcomes{m};
1759 for r = 1:sn.nclasses
1760 for i = 1:length(line_nodes)
1761 % Set enabling conditions
1762 if enabCond(i, r) > 0 && isa(line_nodes{i}, 'Place')
1763 jnodes{n}.setEnablingConditions(jmode, jclasses{r}, jnodes{i}, enabCond(i, r));
1764 end
1765 % Set inhibiting conditions
1766 if inhibCond(i, r) < Inf && isa(line_nodes{i}, 'Place')
1767 jnodes{n}.setInhibitingConditions(jmode, jclasses{r}, jnodes{i}, inhibCond(i, r));
1768 end
1769 % Set firing outcomes
1770 if firingOut(i, r) ~= 0
1771 jnodes{n}.setFiringOutcome(jmode, jclasses{r}, jnodes{i}, firingOut(i, r));
1772 end
1773 end
1774 end
1775 end
1776 end
1777 end
1778
1779 % Assume JLINE and LINE network are both created via link
1780 JLINE.from_line_links(model, jnetwork);
1781
1782 % Transfer finite capacity regions from MATLAB to Java
1783 if ~isempty(model.regions)
1784 for f = 1:length(model.regions)
1785 fcr = model.regions{f};
1786 % Convert MATLAB node list to Java list
1787 javaNodeList = java.util.ArrayList();
1788 for i = 1:length(fcr.nodes)
1789 matlabNode = fcr.nodes{i};
1790 % Find corresponding Java node by name
1791 nodeName = matlabNode.getName();
1792 for j = 1:length(line_nodes)
1793 if strcmp(line_nodes{j}.getName(), nodeName) && ~isempty(jnodes{j})
1794 javaNodeList.add(jnodes{j});
1795 break;
1796 end
1797 end
1798 end
1799 % Create Java FCR
1800 jfcr = jnetwork.addRegion(javaNodeList);
1801 % Set global max jobs
1802 if fcr.globalMaxJobs > 0 && ~isinf(fcr.globalMaxJobs)
1803 jfcr.setGlobalMaxJobs(fcr.globalMaxJobs);
1804 end
1805 % Set per-class max jobs and drop rules
1806 for r = 1:length(line_classes)
1807 if length(fcr.classMaxJobs) >= r && fcr.classMaxJobs(r) > 0 && ~isinf(fcr.classMaxJobs(r))
1808 jfcr.setClassMaxJobs(jclasses{r}, fcr.classMaxJobs(r));
1809 end
1810 if length(fcr.dropRule) >= r
1811 % Convert MATLAB DropStrategy numeric to Java DropStrategy enum
1812 jDropStrategy = jline.lang.constant.DropStrategy.fromID(fcr.dropRule(r));
1813 jfcr.setDropRule(jclasses{r}, jDropStrategy);
1814 end
1815 end
1816 % Transfer linear constraints if set
1817 if fcr.hasLinearConstraints()
1818 jA = JLINE.from_line_matrix(fcr.constraintA);
1819 jb = JLINE.from_line_matrix(fcr.constraintB);
1820 jfcr.setLinearConstraints(jA, jb);
1821 end
1822 end
1823 end
1824
1825 jnetwork.initDefault;
1826 for n = 1: length(line_nodes)
1827 if isempty(jnodes{n})
1828 continue; % Skip nodes that were not converted
1829 end
1830 if line_nodes{n}.isStateful
1831 jnodes{n}.setState(JLINE.from_line_matrix(line_nodes{n}.getState));
1832 jnodes{n}.setStateSpace(JLINE.from_line_matrix(line_nodes{n}.getStateSpace));
1833 jnodes{n}.setStatePrior(JLINE.from_line_matrix(line_nodes{n}.getStatePrior));
1834 end
1835 end
1836 % Force struct refresh so sn.state reflects updated node states
1837 jnetwork.setHasStruct(false);
1838
1839 end
1840
1841 function jnetwork = line_to_jline(model)
1842 jnetwork = LINE2JLINE(model);
1843 end
1844
1845 function model = jline_to_line(jnetwork)
1846 if isa(jnetwork,'JNetwork')
1847 jnetwork = jnetwork.obj;
1848 end
1849 %javaaddpath(jar_loc);
1850 model = Network(char(jnetwork.getName));
1851 network_nodes = jnetwork.getNodes;
1852 job_classes = jnetwork.getClasses;
1853
1854 line_nodes = cell(network_nodes.size,1);
1855 line_classes = cell(job_classes.size,1);
1856
1857
1858 for n = 1 : network_nodes.size
1859 if ~isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch')
1860 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
1861 end
1862 end
1863
1864 for n = 1 : job_classes.size
1865 line_classes{n} = JLINE.from_jline_class(job_classes.get(n-1), model);
1866 end
1867
1868 for n = 1 : network_nodes.size
1869 if isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch')
1870 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
1871 end
1872 end
1873
1874 % Deferred Fork/Join linking: set joinOf on Join nodes
1875 for n = 1 : network_nodes.size
1876 jnode = network_nodes.get(n-1);
1877 if isa(jnode, 'jline.lang.nodes.Join') && ~isempty(jnode.joinOf)
1878 forkName = char(jnode.joinOf.getName);
1879 for m = 1 : network_nodes.size
1880 if ~isempty(line_nodes{m}) && isa(line_nodes{m}, 'Fork') && strcmp(line_nodes{m}.name, forkName)
1881 line_nodes{n}.joinOf = line_nodes{m};
1882 break;
1883 end
1884 end
1885 end
1886 end
1887
1888 % Deferred Cache setup: set hitClass, missClass, popularity
1889 for n = 1 : network_nodes.size
1890 jnode = network_nodes.get(n-1);
1891 if isa(jnode, 'jline.lang.nodes.Cache') && isa(line_nodes{n}, 'Cache')
1892 cacheNode = line_nodes{n};
1893 % hitClass and missClass are stored as index vectors
1894 hitClassVec = JLINE.from_jline_matrix(jnode.getHitClass());
1895 missClassVec = JLINE.from_jline_matrix(jnode.getMissClass());
1896 for r = 1:job_classes.size
1897 hitIdx = hitClassVec(r);
1898 if hitIdx >= 0 && (hitIdx + 1) <= job_classes.size
1899 cacheNode.setHitClass(line_classes{r}, line_classes{hitIdx + 1});
1900 end
1901 missIdx = missClassVec(r);
1902 if missIdx >= 0 && (missIdx + 1) <= job_classes.size
1903 cacheNode.setMissClass(line_classes{r}, line_classes{missIdx + 1});
1904 end
1905 end
1906 % Popularity distributions
1907 for r = 1:job_classes.size
1908 try
1909 popDist = jnode.popularityGet(0, r-1);
1910 if ~isempty(popDist) && popDist.isDiscrete()
1911 matlabDist = JLINE.from_jline_distribution(popDist);
1912 if ~isempty(matlabDist)
1913 cacheNode.setRead(line_classes{r}, matlabDist);
1914 end
1915 end
1916 catch
1917 % No popularity for this class
1918 end
1919 end
1920 end
1921 end
1922
1923 for n = 1 : network_nodes.size
1924 JLINE.set_line_service(network_nodes.get(n-1), line_nodes{n}, job_classes, line_classes);
1925 end
1926
1927 % Configure Transition modes (distributions, enabling/inhibiting/firing, etc.)
1928 for n = 1 : network_nodes.size
1929 jnode = network_nodes.get(n-1);
1930 if isa(jnode, 'jline.lang.nodes.Transition') && isa(line_nodes{n}, 'Transition')
1931 tnode = line_nodes{n};
1932 jmodes = jnode.getModes();
1933 nmodes = jmodes.size();
1934 for m = 1 : nmodes
1935 jmode = jmodes.get(m-1);
1936 modeName = char(jmode.getName());
1937 % addMode if not yet present (Transition starts with one default mode)
1938 if m > tnode.getNumberOfModes()
1939 tnode.addMode(modeName);
1940 else
1941 tnode.setModeNames(m, modeName);
1942 end
1943 % Timing strategy
1944 ts = jnode.timingStrategies.get(jmode);
1945 if ~isempty(ts)
1946 tsName = char(ts.name());
1947 if strcmp(tsName, 'IMMEDIATE')
1948 tnode.setTimingStrategy(m, TimingStrategy.IMMEDIATE);
1949 else
1950 tnode.setTimingStrategy(m, TimingStrategy.TIMED);
1951 end
1952 end
1953 % Distribution
1954 jdist = jnode.getFiringDistribution(jmode);
1955 if ~isempty(jdist)
1956 matlabDist = JLINE.from_jline_distribution(jdist);
1957 if ~isempty(matlabDist)
1958 tnode.setDistribution(m, matlabDist);
1959 end
1960 end
1961 % Number of servers
1962 numSrv = jnode.getNumberOfModeServers(jmode);
1963 if numSrv == intmax('int32') || numSrv == intmax('int64')
1964 tnode.setNumberOfServers(m, Inf);
1965 else
1966 tnode.setNumberOfServers(m, double(numSrv));
1967 end
1968 % Firing priority and weight (read from matrices by mode index)
1969 if jnode.firingPriorities.getNumElements() > (m-1)
1970 tnode.setFiringPriorities(m, jnode.firingPriorities.get(m-1));
1971 end
1972 if jnode.firingWeights.getNumElements() > (m-1)
1973 tnode.setFiringWeights(m, jnode.firingWeights.get(m-1));
1974 end
1975 % Enabling conditions
1976 ecMat = jnode.enablingConditions.get(jmode);
1977 if ~isempty(ecMat)
1978 nrows = ecMat.getNumRows();
1979 ncols = ecMat.getNumCols();
1980 for ni = 1 : nrows
1981 for ci = 1 : ncols
1982 val = ecMat.get(ni-1, ci-1);
1983 if val > 0 && ni <= length(line_nodes) && isa(line_nodes{ni}, 'Place')
1984 tnode.setEnablingConditions(m, ci, line_nodes{ni}, val);
1985 end
1986 end
1987 end
1988 end
1989 % Inhibiting conditions
1990 icMat = jnode.inhibitingConditions.get(jmode);
1991 if ~isempty(icMat)
1992 nrows = icMat.getNumRows();
1993 ncols = icMat.getNumCols();
1994 for ni = 1 : nrows
1995 for ci = 1 : ncols
1996 val = icMat.get(ni-1, ci-1);
1997 if isfinite(val) && val > 0 && ni <= length(line_nodes) && isa(line_nodes{ni}, 'Place')
1998 tnode.setInhibitingConditions(m, ci, line_nodes{ni}, val);
1999 end
2000 end
2001 end
2002 end
2003 % Firing outcomes
2004 foMat = jnode.firingOutcomes.get(jmode);
2005 if ~isempty(foMat)
2006 nrows = foMat.getNumRows();
2007 ncols = foMat.getNumCols();
2008 for ni = 1 : nrows
2009 for ci = 1 : ncols
2010 val = foMat.get(ni-1, ci-1);
2011 if val ~= 0 && ni <= length(line_nodes)
2012 tnode.setFiringOutcome(m, ci, line_nodes{ni}, val);
2013 end
2014 end
2015 end
2016 end
2017 end
2018 end
2019 end
2020
2021 % Check for state-dependent routing (RROBIN, WRROBIN, JSQ)
2022 % These cannot go through link(P) because it overrides routing strategies
2023 hasSDRouting = false;
2024 for n = 1 : network_nodes.size
2025 jnode = network_nodes.get(n-1);
2026 output_strategies = jnode.getOutputStrategies();
2027 for m = 1 : output_strategies.size()
2028 rs = char(output_strategies.get(m-1).getRoutingStrategy);
2029 if any(strcmp(rs, {'RROBIN','WRROBIN','JSQ','KCHOICES'}))
2030 hasSDRouting = true;
2031 break;
2032 end
2033 end
2034 if hasSDRouting; break; end
2035 end
2036
2037 if hasSDRouting
2038 % State-dependent routing: use addLink + setRouting
2039 model = JLINE.from_jline_routing(model, jnetwork);
2040 elseif ~isempty(jnetwork.getStruct.rtorig)
2041 % Use link() method
2042 model = JLINE.from_jline_links(model, jnetwork);
2043 else
2044 % Do not use link() method
2045 model = JLINE.from_jline_routing(model, jnetwork);
2046 end
2047
2048 % Restore initial state on Place nodes after linking
2049 for n = 1 : network_nodes.size
2050 jnode = network_nodes.get(n-1);
2051 if isa(jnode, 'jline.lang.nodes.Place') && ~isempty(line_nodes{n}) && isa(line_nodes{n}, 'Place')
2052 jst = jnode.getState();
2053 if ~isempty(jst) && ~jst.isEmpty()
2054 line_nodes{n}.setState(JLINE.from_jline_matrix(jst));
2055 end
2056 end
2057 end
2058 end
2059
2060 function matrix = arraylist_to_matrix(jline_matrix)
2061 if isempty(jline_matrix)
2062 matrix = [];
2063 else
2064 matrix = zeros(jline_matrix.size(), 1);
2065 for row = 1:jline_matrix.size()
2066 matrix(row, 1) = jline_matrix.get(row-1);
2067 end
2068 end
2069 end
2070
2071 function matrix = from_jline_matrix(jline_matrix)
2072 if isempty(jline_matrix)
2073 matrix = [];
2074 else
2075 matrix = zeros(jline_matrix.getNumRows(), jline_matrix.getNumCols());
2076 for row = 1:jline_matrix.getNumRows()
2077 for col = 1:jline_matrix.getNumCols()
2078 val = jline_matrix.get(row-1, col-1);
2079 if (val >= 33333333 && val <= 33333334)
2080 matrix(row, col) = GlobalConstants.Immediate;
2081 elseif (val >= -33333334 && val <= -33333333)
2082 matrix(row, col) = -GlobalConstants.Immediate;
2083 elseif (val >= 2147483647 - 1) % Integer.MAX_VALUE with -1 tolerance
2084 matrix(row, col) = Inf;
2085 elseif (val <= -2147483648 + 1) % Integer.MIN_VALUE with +1 tolerance
2086 matrix(row, col) = -Inf;
2087 else
2088 matrix(row, col) = val;
2089 end
2090 end
2091 end
2092 end
2093 end
2094
2095 function jline_matrix = from_line_matrix(matrix)
2096 [rows, cols] = size(matrix);
2097 jline_matrix = jline.util.matrix.Matrix(rows, cols);
2098 for row = 1:rows
2099 for col = 1:cols
2100 if matrix(row,col) ~= 0
2101 jline_matrix.set(row-1, col-1, matrix(row, col));
2102 end
2103 end
2104 end
2105 end
2106
2107 function lsn = from_jline_struct_layered(jlayerednetwork, jlsn)
2108 lsn = LayeredNetworkStruct();
2109 lsn.nidx= jlsn.nidx;
2110 lsn.nhosts= jlsn.nhosts;
2111 lsn.ntasks= jlsn.ntasks;
2112 lsn.nentries= jlsn.nentries;
2113 lsn.nacts= jlsn.nacts;
2114 lsn.ncalls= jlsn.ncalls;
2115 lsn.hshift= jlsn.hshift;
2116 lsn.tshift= jlsn.tshift;
2117 lsn.eshift= jlsn.eshift;
2118 lsn.ashift= jlsn.ashift;
2119 lsn.cshift= jlsn.cshift;
2120 for h=1:jlsn.nhosts
2121 lsn.tasksof{h,1} = JLINE.arraylist_to_matrix(jlsn.tasksof.get(uint32(h)))';
2122 end
2123 for t=1:jlsn.ntasks
2124 lsn.entriesof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.entriesof.get(uint32(jlsn.tshift+t)))';
2125 end
2126 for t=1:(jlsn.ntasks+jlsn.nentries)
2127 lsn.actsof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.actsof.get(uint32(jlsn.tshift+t)))';
2128 end
2129 for a=1:jlsn.nacts
2130 lsn.callsof{lsn.ashift+a,1} = JLINE.arraylist_to_matrix(jlsn.callsof.get(uint32(jlsn.ashift+a)))';
2131 end
2132 for i = 1:jlsn.sched.size
2133 lsn.sched(i,1) = SchedStrategy.(char(jlsn.sched.get(uint32(i))));
2134 end
2135 for i = 1:jlsn.names.size
2136 lsn.names{i,1} = jlsn.names.get(uint32(i));
2137 lsn.hashnames{i,1} = jlsn.hashnames.get(uint32(i));
2138 end
2139 lsn.mult = JLINE.from_jline_matrix(jlsn.mult);
2140 lsn.mult = lsn.mult(2:(lsn.eshift+1))'; % remove 0-padding
2141 lsn.maxmult = JLINE.from_jline_matrix(jlsn.maxmult);
2142 lsn.maxmult = lsn.maxmult(2:(lsn.eshift+1))'; % remove 0-padding
2143
2144 lsn.repl = JLINE.from_jline_matrix(jlsn.repl)';
2145 lsn.repl = lsn.repl(2:end); % remove 0-padding
2146 lsn.type = JLINE.from_jline_matrix(jlsn.type)';
2147 lsn.type = lsn.type(2:end); % remove 0-padding
2148 lsn.parent = JLINE.from_jline_matrix(jlsn.parent);
2149 lsn.parent = lsn.parent(2:end); % remove 0-padding
2150 lsn.nitems = JLINE.from_jline_matrix(jlsn.nitems);
2151 % Ensure proper column vector format matching MATLAB's (nhosts+ntasks+nentries) x 1
2152 if isrow(lsn.nitems)
2153 lsn.nitems = lsn.nitems(2:end)'; % remove 0-padding and transpose
2154 else
2155 lsn.nitems = lsn.nitems(2:end); % remove 0-padding (already column)
2156 end
2157 % Ensure correct size
2158 expectedSize = lsn.nhosts + lsn.ntasks + lsn.nentries;
2159 if length(lsn.nitems) < expectedSize
2160 lsn.nitems(expectedSize,1) = 0;
2161 elseif length(lsn.nitems) > expectedSize
2162 lsn.nitems = lsn.nitems(1:expectedSize);
2163 end
2164 lsn.replacestrat = JLINE.from_jline_matrix(jlsn.replacestrat);
2165 lsn.replacestrat = lsn.replacestrat(2:end)'; % remove 0-padding
2166 for i = 1:jlsn.callnames.size
2167 lsn.callnames{i,1} = jlsn.callnames.get(uint32(i));
2168 lsn.callhashnames{i,1} = jlsn.callhashnames.get(uint32(i));
2169 end
2170 for i = 1:jlsn.calltype.size % calltype may be made into a matrix in Java
2171 ct = char(jlsn.calltype.get(uint32(i)));
2172 lsn.calltype(i) = CallType.(ct);
2173 end
2174 lsn.calltype = sparse(lsn.calltype'); % remove 0-padding
2175 lsn.callpair = JLINE.from_jline_matrix(jlsn.callpair);
2176 lsn.callpair = lsn.callpair(2:end,2:end); % remove 0-paddings
2177 if isempty(lsn.callpair)
2178 lsn.callpair=[];
2179 end
2180 lsn.actpretype = sparse(JLINE.from_jline_matrix(jlsn.actpretype)');
2181 lsn.actpretype = lsn.actpretype(2:end); % remove 0-padding
2182 lsn.actposttype = sparse(JLINE.from_jline_matrix(jlsn.actposttype)');
2183 lsn.actposttype = lsn.actposttype(2:end); % remove 0-padding
2184 lsn.graph = JLINE.from_jline_matrix(jlsn.graph);
2185 lsn.graph = lsn.graph(2:end,2:end); % remove 0-paddings
2186 lsn.dag = JLINE.from_jline_matrix(jlsn.dag);
2187 lsn.dag = lsn.dag(2:end,2:end); % remove 0-paddings
2188 lsn.taskgraph = JLINE.from_jline_matrix(jlsn.taskgraph);
2189 lsn.taskgraph = sparse(lsn.taskgraph(2:end,2:end)); % remove 0-paddings
2190 lsn.replygraph = JLINE.from_jline_matrix(jlsn.replygraph);
2191 lsn.replygraph = logical(lsn.replygraph(2:end,2:end)); % remove 0-paddings
2192 lsn.iscache = JLINE.from_jline_matrix(jlsn.iscache);
2193 % Ensure proper column vector format matching MATLAB's (nhosts+ntasks) x 1
2194 expectedCacheSize = lsn.nhosts + lsn.ntasks;
2195 if isrow(lsn.iscache)
2196 if length(lsn.iscache) > expectedCacheSize
2197 lsn.iscache = lsn.iscache(2:(expectedCacheSize+1))'; % remove 0-padding and transpose
2198 else
2199 lsn.iscache = lsn.iscache'; % just transpose
2200 end
2201 end
2202 % Ensure correct size
2203 if length(lsn.iscache) < expectedCacheSize
2204 lsn.iscache(expectedCacheSize,1) = 0;
2205 elseif length(lsn.iscache) > expectedCacheSize
2206 lsn.iscache = lsn.iscache(1:expectedCacheSize);
2207 end
2208 lsn.iscaller = JLINE.from_jline_matrix(jlsn.iscaller);
2209 lsn.iscaller = full(lsn.iscaller(2:end,2:end)); % remove 0-paddings
2210 lsn.issynccaller = JLINE.from_jline_matrix(jlsn.issynccaller);
2211 lsn.issynccaller = full(lsn.issynccaller(2:end,2:end)); % remove 0-paddings
2212 lsn.isasynccaller = JLINE.from_jline_matrix(jlsn.isasynccaller);
2213 lsn.isasynccaller = full(lsn.isasynccaller(2:end,2:end)); % remove 0-paddings
2214 lsn.isref = JLINE.from_jline_matrix(jlsn.isref);
2215 lsn.isref = lsn.isref(2:end)'; % remove 0-paddings
2216 end
2217
2218 function sn = from_jline_struct(jnetwork, jsn)
2219 %lst and rtfun are not implemented
2220 %Due to the transformation of Java lambda to matlab function
2221 if nargin<2
2222 jsn = jnetwork.getStruct(false);
2223 end
2224 jclasses = jnetwork.getClasses();
2225 jnodes = jnetwork.getNodes();
2226 jstateful = jnetwork.getStatefulNodes();
2227 jstations = jnetwork.getStations();
2228 sn = NetworkStruct();
2229
2230 sn.nnodes = jsn.nnodes;
2231 sn.nclasses = jsn.nclasses;
2232 sn.nclosedjobs = jsn.nclosedjobs;
2233 sn.nstations = jsn.nstations;
2234 sn.nstateful = jsn.nstateful;
2235 sn.nchains = jsn.nchains;
2236
2237 sn.refstat = JLINE.from_jline_matrix(jsn.refstat) + 1;
2238 sn.njobs = JLINE.from_jline_matrix(jsn.njobs);
2239 sn.nservers = JLINE.from_jline_matrix(jsn.nservers);
2240 sn.connmatrix = JLINE.from_jline_matrix(jsn.connmatrix);
2241 % Fix for Java getConnectionMatrix bug: ensure connmatrix is nnodes x nnodes
2242 if size(sn.connmatrix,1) < sn.nnodes
2243 sn.connmatrix(sn.nnodes,1) = 0;
2244 end
2245 if size(sn.connmatrix,2) < sn.nnodes
2246 sn.connmatrix(1,sn.nnodes) = 0;
2247 end
2248 sn.scv = JLINE.from_jline_matrix(jsn.scv);
2249 sn.isstation = logical(JLINE.from_jline_matrix(jsn.isstation));
2250 sn.isstateful = logical(JLINE.from_jline_matrix(jsn.isstateful));
2251 sn.isstatedep = logical(JLINE.from_jline_matrix(jsn.isstatedep));
2252 sn.nodeToStateful = JLINE.from_jline_matrix(jsn.nodeToStateful)+1;
2253 sn.nodeToStateful(sn.nodeToStateful==0) = nan;
2254 sn.nodeToStation = JLINE.from_jline_matrix(jsn.nodeToStation)+1;
2255 sn.nodeToStation(sn.nodeToStation==0) = nan;
2256 sn.stationToNode = JLINE.from_jline_matrix(jsn.stationToNode)+1;
2257 sn.stationToNode(sn.stationToNode==0) = nan;
2258 sn.stationToStateful = JLINE.from_jline_matrix(jsn.stationToStateful)+1;
2259 sn.stationToStateful(sn.stationToStateful==0) = nan;
2260 sn.statefulToStation = JLINE.from_jline_matrix(jsn.statefulToStation)+1;
2261 sn.statefulToStation(sn.statefulToStation==0) = nan;
2262 sn.statefulToNode = JLINE.from_jline_matrix(jsn.statefulToNode)+1;
2263 sn.statefulToNode(sn.statefulToNode==0) = nan;
2264 sn.rates = JLINE.from_jline_matrix(jsn.rates);
2265 sn.fj = JLINE.from_jline_matrix(jsn.fj);
2266 sn.classprio = JLINE.from_jline_matrix(jsn.classprio);
2267 sn.phases = JLINE.from_jline_matrix(jsn.phases);
2268 sn.phasessz = JLINE.from_jline_matrix(jsn.phasessz);
2269 sn.phaseshift = JLINE.from_jline_matrix(jsn.phaseshift);
2270 sn.schedparam = JLINE.from_jline_matrix(jsn.schedparam);
2271 sn.chains = logical(JLINE.from_jline_matrix(jsn.chains));
2272 sn.rt = JLINE.from_jline_matrix(jsn.rt);
2273 sn.nvars = JLINE.from_jline_matrix(jsn.nvars);
2274 sn.rtnodes = JLINE.from_jline_matrix(jsn.rtnodes);
2275 sn.csmask = logical(JLINE.from_jline_matrix(jsn.csmask));
2276 sn.isslc = logical(JLINE.from_jline_matrix(jsn.isslc));
2277 sn.cap = JLINE.from_jline_matrix(jsn.cap);
2278 sn.classcap = JLINE.from_jline_matrix(jsn.classcap);
2279 sn.refclass = JLINE.from_jline_matrix(jsn.refclass)+1;
2280 sn.lldscaling = JLINE.from_jline_matrix(jsn.lldscaling);
2281
2282 if ~isempty(jsn.cdscaling) && jsn.cdscaling.size() > 0
2283 % Convert Java SerializableFunction to MATLAB function handles
2284 sn.cdscaling = cell(sn.nstations, 1);
2285 % Iterate through the map entries to handle null values properly
2286 entrySet = jsn.cdscaling.entrySet();
2287 entryIter = entrySet.iterator();
2288 stationFunMap = containers.Map();
2289 while entryIter.hasNext()
2290 entry = entryIter.next();
2291 stationName = char(entry.getKey().getName());
2292 try
2293 jfun = entry.getValue();
2294 if ~isempty(jfun)
2295 stationFunMap(stationName) = jfun;
2296 end
2297 catch
2298 % getValue() returns null for default lambda functions
2299 % Skip and use default value
2300 end
2301 end
2302 % Assign functions to stations
2303 for i = 1:sn.nstations
2304 jstation = jstations.get(i-1);
2305 stationName = char(jstation.getName());
2306 if isKey(stationFunMap, stationName)
2307 jfun = stationFunMap(stationName);
2308 % Create a MATLAB function handle that calls the Java apply() method
2309 sn.cdscaling{i} = @(ni) JLINE.call_java_cdscaling(jfun, ni);
2310 else
2311 sn.cdscaling{i} = @(ni) 1;
2312 end
2313 end
2314 else
2315 sn.cdscaling = cell(sn.nstations, 0);
2316 end
2317
2318 if ~isempty(jsn.nodetype)
2319 sn.nodetype = zeros(sn.nnodes, 1);
2320 for i = 1:jsn.nodetype.size
2321 nodetype = jsn.nodetype.get(i-1);
2322 switch nodetype.name().toCharArray'
2323 case 'Queue'
2324 sn.nodetype(i) = NodeType.Queue;
2325 case 'Delay'
2326 sn.nodetype(i) = NodeType.Delay;
2327 case 'Source'
2328 sn.nodetype(i) = NodeType.Source;
2329 case 'Sink'
2330 sn.nodetype(i) = NodeType.Sink;
2331 case 'Join'
2332 sn.nodetype(i) = NodeType.Join;
2333 case 'Fork'
2334 sn.nodetype(i) = NodeType.Fork;
2335 case 'ClassSwitch'
2336 sn.nodetype(i) = NodeType.ClassSwitch;
2337 case 'Logger'
2338 sn.nodetype(i) = NodeType.Logger;
2339 case 'Cache'
2340 sn.nodetype(i) = NodeType.Cache;
2341 case 'Place'
2342 sn.nodetype(i) = NodeType.Place;
2343 case 'Transition'
2344 sn.nodetype(i) = NodeType.Transition;
2345 case 'Router'
2346 sn.nodetype(i) = NodeType.Router;
2347 end
2348 end
2349 else
2350 sn.nodetype = [];
2351 end
2352
2353 if ~isempty(jsn.classnames)
2354 for i = 1:jsn.classnames.size
2355 sn.classnames(i,1) = jsn.classnames.get(i-1);
2356 end
2357 else
2358 sn.classnames = [];
2359 end
2360
2361 if ~isempty(jsn.nodenames)
2362 for i = 1:jsn.nodenames.size
2363 sn.nodenames(i,1) = jsn.nodenames.get(i-1);
2364 end
2365 else
2366 sn.nodenames = [];
2367 end
2368
2369 if ~isempty(jsn.rtorig) && jsn.rtorig.size()>0
2370 sn.rtorig = cell(sn.nclasses, sn.nclasses);
2371 for r = 1:sn.nclasses
2372 for s = 1:sn.nclasses
2373 sn.rtorig{r,s} = JLINE.from_jline_matrix(jsn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
2374 end
2375 end
2376 else
2377 sn.rtorig = {};
2378 end
2379
2380 if ~isempty(jsn.state)
2381 sn.state = cell(sn.nstateful, 1);
2382 for i = 1:sn.nstateful
2383 sn.state{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getState());
2384 end
2385 else
2386 sn.state = {};
2387 end
2388
2389 if ~isempty(jsn.stateprior)
2390 sn.stateprior = cell(sn.nstateful, 1);
2391 for i = 1:sn.nstateful
2392 sn.stateprior{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStatePrior());
2393 end
2394 else
2395 sn.stateprior = {};
2396 end
2397
2398 if ~isempty(jsn.space)
2399 sn.space = cell(sn.nstateful, 1);
2400 for i = 1:sn.nstateful
2401 sn.space{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStateSpace());
2402 end
2403 else
2404 sn.space = {};
2405 end
2406
2407 if ~isempty(jsn.routing)
2408 sn.routing = zeros(sn.nnodes, sn.nclasses);
2409 for i = 1:sn.nnodes
2410 for j = 1:sn.nclasses
2411 routingStrategy = jsn.routing.get(jnodes.get(i-1)).get(jclasses.get(j-1));
2412 switch routingStrategy.name().toCharArray'
2413 case 'PROB'
2414 sn.routing(i,j) = RoutingStrategy.PROB;
2415 case 'RAND'
2416 sn.routing(i,j) = RoutingStrategy.RAND;
2417 case 'RROBIN'
2418 sn.routing(i,j) = RoutingStrategy.RROBIN;
2419 case 'WRROBIN'
2420 sn.routing(i,j) = RoutingStrategy.WRROBIN;
2421 case 'JSQ'
2422 sn.routing(i,j) = RoutingStrategy.JSQ;
2423 case 'DISABLED'
2424 sn.routing(i,j) = RoutingStrategy.DISABLED;
2425 case 'FIRING'
2426 sn.routing(i,j) = RoutingStrategy.FIRING;
2427 case 'KCHOICES'
2428 sn.routing(i,j) = RoutingStrategy.KCHOICES;
2429 end
2430 end
2431 end
2432 else
2433 sn.routing = [];
2434 end
2435
2436 if ~isempty(jsn.procid)
2437 sn.procid = nan(sn.nstations, sn.nclasses); % Initialize with NaN to match MATLAB behavior
2438 for i = 1:sn.nstations
2439 for j = 1:sn.nclasses
2440 stationMap = jsn.procid.get(jstations.get(i-1));
2441 if isempty(stationMap)
2442 sn.procid(i,j) = ProcessType.DISABLED;
2443 continue;
2444 end
2445 processType = stationMap.get(jclasses.get(j-1));
2446 if isempty(processType)
2447 sn.procid(i,j) = ProcessType.DISABLED;
2448 continue;
2449 end
2450 switch processType.name.toCharArray'
2451 case 'EXP'
2452 sn.procid(i,j) = ProcessType.EXP;
2453 case 'ERLANG'
2454 sn.procid(i,j) = ProcessType.ERLANG;
2455 case 'HYPEREXP'
2456 sn.procid(i,j) = ProcessType.HYPEREXP;
2457 case 'PH'
2458 sn.procid(i,j) = ProcessType.PH;
2459 case 'APH'
2460 sn.procid(i,j) = ProcessType.APH;
2461 case 'MAP'
2462 sn.procid(i,j) = ProcessType.MAP;
2463 case 'UNIFORM'
2464 sn.procid(i,j) = ProcessType.UNIFORM;
2465 case 'DET'
2466 sn.procid(i,j) = ProcessType.DET;
2467 case 'COXIAN'
2468 sn.procid(i,j) = ProcessType.COXIAN;
2469 case 'GAMMA'
2470 sn.procid(i,j) = ProcessType.GAMMA;
2471 case 'PARETO'
2472 sn.procid(i,j) = ProcessType.PARETO;
2473 case 'WEIBULL'
2474 sn.procid(i,j) = ProcessType.WEIBULL;
2475 case 'LOGNORMAL'
2476 sn.procid(i,j) = ProcessType.LOGNORMAL;
2477 case 'MMPP2'
2478 sn.procid(i,j) = ProcessType.MMPP2;
2479 case 'REPLAYER'
2480 sn.procid(i,j) = ProcessType.REPLAYER;
2481 case 'TRACE'
2482 sn.procid(i,j) = ProcessType.TRACE;
2483 case 'IMMEDIATE'
2484 sn.procid(i,j) = ProcessType.IMMEDIATE;
2485 case 'DISABLED'
2486 sn.procid(i,j) = ProcessType.DISABLED;
2487 case 'COX2'
2488 sn.procid(i,j) = ProcessType.COX2;
2489 case 'BMAP'
2490 sn.procid(i,j) = ProcessType.BMAP;
2491 case 'ME'
2492 sn.procid(i,j) = ProcessType.ME;
2493 case 'RAP'
2494 sn.procid(i,j) = ProcessType.RAP;
2495 case 'BINOMIAL'
2496 sn.procid(i,j) = ProcessType.BINOMIAL;
2497 case 'POISSON'
2498 sn.procid(i,j) = ProcessType.POISSON;
2499 case 'GEOMETRIC'
2500 sn.procid(i,j) = ProcessType.GEOMETRIC;
2501 case 'DUNIFORM'
2502 sn.procid(i,j) = ProcessType.DUNIFORM;
2503 case 'BERNOULLI'
2504 sn.procid(i,j) = ProcessType.BERNOULLI;
2505 case 'PRIOR'
2506 sn.procid(i,j) = ProcessType.PRIOR;
2507 otherwise
2508 % Unknown ProcessType - default to DISABLED
2509 sn.procid(i,j) = ProcessType.DISABLED;
2510 end
2511 end
2512 end
2513 else
2514 sn.procid = [];
2515 end
2516
2517 if ~isempty(jsn.mu)
2518 sn.mu = cell(sn.nstations, 1);
2519 for i = 1:sn.nstations
2520 sn.mu{i} = cell(1, sn.nclasses);
2521 for j = 1:sn.nclasses
2522 sn.mu{i}{j} = JLINE.from_jline_matrix(jsn.mu.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2523 end
2524 end
2525 else
2526 sn.mu = {};
2527 end
2528
2529 if ~isempty(jsn.phi)
2530 sn.phi = cell(sn.nstations, 1);
2531 for i = 1:sn.nstations
2532 sn.phi{i} = cell(1, sn.nclasses);
2533 for j = 1:sn.nclasses
2534 sn.phi{i}{j} = JLINE.from_jline_matrix(jsn.phi.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2535 end
2536 end
2537 else
2538 sn.phi = {};
2539 end
2540
2541 if ~isempty(jsn.proc)
2542 sn.proc = cell(sn.nstations, 1);
2543 for i = 1:sn.nstations
2544 sn.proc{i} = cell(1, sn.nclasses);
2545 for j = 1:sn.nclasses
2546 proc_i_j = jsn.proc.get(jstations.get(i-1)).get(jclasses.get(j-1));
2547 sn.proc{i}{j} = cell(1, proc_i_j.size);
2548 for k = 1:proc_i_j.size
2549 sn.proc{i}{j}{k} = JLINE.from_jline_matrix(proc_i_j.get(uint32(k-1)));
2550 end
2551 end
2552 end
2553 else
2554 sn.proc = {};
2555 end
2556
2557 if ~isempty(jsn.pie)
2558 sn.pie = cell(sn.nstations, 1);
2559 for i = 1:sn.nstations
2560 sn.pie{i} = cell(1, sn.nclasses);
2561 for j = 1:sn.nclasses
2562 sn.pie{i}{j} = JLINE.from_jline_matrix(jsn.pie.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2563 end
2564 end
2565 else
2566 sn.pie = {};
2567 end
2568
2569 if ~isempty(jsn.sched)
2570 sn.sched = zeros(sn.nstations, 1);
2571 for i = 1:sn.nstations
2572 schedStrategy = jsn.sched.get(jstations.get(i-1));
2573 switch schedStrategy.name.toCharArray'
2574 case 'INF'
2575 sn.sched(i) = SchedStrategy.INF;
2576 case 'FCFS'
2577 sn.sched(i) = SchedStrategy.FCFS;
2578 case 'LCFS'
2579 sn.sched(i) = SchedStrategy.LCFS;
2580 case 'LCFSPR'
2581 sn.sched(i) = SchedStrategy.LCFSPR;
2582 case 'SIRO'
2583 sn.sched(i) = SchedStrategy.SIRO;
2584 case 'SJF'
2585 sn.sched(i) = SchedStrategy.SJF;
2586 case 'LJF'
2587 sn.sched(i) = SchedStrategy.LJF;
2588 case 'PS'
2589 sn.sched(i) = SchedStrategy.PS;
2590 case 'DPS'
2591 sn.sched(i) = SchedStrategy.DPS;
2592 case 'GPS'
2593 sn.sched(i) = SchedStrategy.GPS;
2594 case 'PSPRIO'
2595 sn.sched(i) = SchedStrategy.PSPRIO;
2596 case 'DPSPRIO'
2597 sn.sched(i) = SchedStrategy.DPSPRIO;
2598 case 'GPSPRIO'
2599 sn.sched(i) = SchedStrategy.GPSPRIO;
2600 case 'SEPT'
2601 sn.sched(i) = SchedStrategy.SEPT;
2602 case 'LEPT'
2603 sn.sched(i) = SchedStrategy.LEPT;
2604 case {'HOL', 'FCFSPRIO'}
2605 sn.sched(i) = SchedStrategy.FCFSPRIO;
2606 case 'FORK'
2607 sn.sched(i) = SchedStrategy.FORK;
2608 case 'EXT'
2609 sn.sched(i) = SchedStrategy.EXT;
2610 case 'REF'
2611 sn.sched(i) = SchedStrategy.REF;
2612 end
2613 end
2614 else
2615 sn.sched = [];
2616 end
2617
2618 if ~isempty(jsn.inchain)
2619 sn.inchain = cell(1, sn.nchains);
2620 for i = 1:sn.nchains
2621 sn.inchain{1,i} = JLINE.from_jline_matrix(jsn.inchain.get(uint32(i-1)))+1;
2622 end
2623 else
2624 sn.inchain = {};
2625 end
2626
2627 if ~isempty(jsn.visits)
2628 sn.visits = cell(sn.nchains, 1);
2629 for i = 1:sn.nchains
2630 sn.visits{i,1} = JLINE.from_jline_matrix(jsn.visits.get(uint32(i-1)));
2631 end
2632 else
2633 sn.visits = {};
2634 end
2635
2636 if ~isempty(jsn.nodevisits)
2637 sn.nodevisits = cell(1, sn.nchains);
2638 for i = 1:sn.nchains
2639 sn.nodevisits{1,i} = JLINE.from_jline_matrix(jsn.nodevisits.get(uint32(i-1)));
2640 end
2641 else
2642 sn.nodevisits = {};
2643 end
2644
2645 if ~isempty(jsn.droprule)
2646 sn.droprule = zeros(sn.nstations, sn.nclasses);
2647 for i = 1:sn.nstations
2648 for j = 1:sn.nclasses
2649 dropStrategy = jsn.droprule.get(jstations.get(i-1)).get(jclasses.get(j-1));
2650 switch dropStrategy.name.toCharArray'
2651 case 'WaitingQueue'
2652 sn.droprule(i,j) = DropStrategy.WAITQ;
2653 case 'Drop'
2654 sn.droprule(i,j) = DropStrategy.DROP;
2655 case 'BlockingAfterService'
2656 sn.droprule(i,j) = DropStrategy.BAS;
2657 end
2658 end
2659 end
2660 else
2661 sn.droprule = [];
2662 end
2663
2664 if ~isempty(jsn.nodeparam)
2665 sn.nodeparam = cell(sn.nnodes, 1);
2666
2667 for i = 1:sn.nnodes
2668 jnode = jnodes.get(i-1);
2669 jparam = jsn.nodeparam.get(jnode);
2670
2671 %if jparam.isEmpty
2672 % sn.nodeparam{i} = [];
2673 % continue;
2674 %end
2675
2676 % StationNodeParam
2677 if isa(jparam, 'jline.lang.nodeparam.StationNodeParam')
2678 if ~isempty(jparam.fileName)
2679 sn.nodeparam{i}.fileName = cell(1, sn.nclasses);
2680 for r = 1:sn.nclasses
2681 fname = jparam.fileName.get(r-1);
2682 if ~isempty(fname)
2683 sn.nodeparam{i}.fileName{r} = char(fname);
2684 end
2685 end
2686 end
2687 end
2688
2689 % TransitionNodeParam
2690 if isa(jparam, 'jline.lang.nodeparam.TransitionNodeParam')
2691 if ~isempty(jparam.firingprocid)
2692 sn.nodeparam{i}.firingprocid = containers.Map('KeyType', 'char', 'ValueType', 'any');
2693 keys = jparam.firingprocid.keySet.iterator;
2694 while keys.hasNext
2695 key = keys.next;
2696 proc = jparam.firingprocid.get(key);
2697 sn.nodeparam{i}.firingprocid(char(key.toString)) = char(proc.toString);
2698 end
2699 end
2700 if ~isempty(jparam.firingphases)
2701 sn.nodeparam{i}.firingphases = JLINE.from_jline_matrix(jparam.firingphases);
2702 end
2703 if ~isempty(jparam.fireweight)
2704 sn.nodeparam{i}.fireweight = JLINE.from_jline_matrix(jparam.fireweight);
2705 end
2706 end
2707
2708 % JoinNodeParam
2709 if isa(jparam, 'jline.lang.nodeparam.JoinNodeParam')
2710 if ~isempty(jparam.joinStrategy)
2711 sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
2712 sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
2713 for r = 1:sn.nclasses
2714 jclass = jclasses.get(r-1);
2715 joinStrategy = jparam.joinStrategy.get(jclass);
2716 if ~isempty(joinStrategy)
2717 strategyStr = char(joinStrategy.name.toString);
2718 switch strategyStr
2719 case 'STD'
2720 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
2721 case 'PARTIAL'
2722 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
2723 otherwise
2724 sn.nodeparam{i}.joinStrategy{r} = strategyStr;
2725 end
2726 sn.nodeparam{i}.fanIn{r} = jparam.fanIn.get(jclass);
2727 end
2728 end
2729 end
2730 end
2731
2732 % RoutingNodeParam
2733 if isa(jparam, 'jline.lang.nodeparam.RoutingNodeParam')
2734 for r = 1:sn.nclasses
2735 jclass = jclasses.get(r-1);
2736
2737 if ~isempty(jparam.weights) && jparam.weights.containsKey(jclass)
2738 sn.nodeparam{i}.weights{r} = JLINE.from_jline_matrix(jparam.weights.get(jclass));
2739 end
2740
2741 if ~isempty(jparam.outlinks) && jparam.outlinks.containsKey(jclass)
2742 sn.nodeparam{i}.outlinks{r} = JLINE.from_jline_matrix(jparam.outlinks.get(jclass));
2743 end
2744 end
2745 end
2746
2747 % ForkNodeParam
2748 if isa(jparam, 'jline.lang.nodeparam.ForkNodeParam')
2749 if ~isnan(jparam.fanOut)
2750 sn.nodeparam{i}.fanOut = jparam.fanOut;
2751 end
2752 end
2753
2754 % CacheNodeParam
2755 if isa(jparam, 'jline.lang.nodeparam.CacheNodeParam')
2756 % nitems
2757 if ~isnan(jparam.nitems)
2758 sn.nodeparam{i}.nitems = jparam.nitems;
2759 end
2760
2761 % accost
2762 if ~isempty(jparam.accost)
2763 % For Java 2D arrays (Matrix[][]), size(arr,2) returns 1 in MATLAB
2764 % We need to get length of first row to get actual second dimension
2765 K1 = size(jparam.accost, 1);
2766 if K1 > 0
2767 firstRow = jparam.accost(1); % Get first row (Java array)
2768 K2 = length(firstRow);
2769 else
2770 K2 = 0;
2771 end
2772 sn.nodeparam{i}.accost = cell(K1, K2);
2773 for k1 = 1:K1
2774 for k2 = 1:K2
2775 mat = jparam.accost(k1, k2); % MATLAB handles Java array indexing
2776 if ~isempty(mat)
2777 sn.nodeparam{i}.accost{k1, k2} = JLINE.from_jline_matrix(mat);
2778 end
2779 end
2780 end
2781 end
2782
2783 % itemcap
2784 if ~isempty(jparam.itemcap)
2785 sn.nodeparam{i}.itemcap = JLINE.from_jline_matrix(jparam.itemcap);
2786 end
2787
2788 % pread - convert from Java Map<Integer, List<Double>> to MATLAB cell array {R}
2789 if ~isempty(jparam.pread)
2790 nclasses = sn.nclasses;
2791 sn.nodeparam{i}.pread = cell(1, nclasses);
2792 for r = 1:nclasses
2793 list = jparam.pread.get(int32(r-1)); % Java 0-based indexing
2794 if ~isempty(list)
2795 values = zeros(1, list.size);
2796 for j = 1:list.size
2797 values(j) = list.get(j-1);
2798 end
2799 sn.nodeparam{i}.pread{r} = values;
2800 else
2801 sn.nodeparam{i}.pread{r} = NaN;
2802 end
2803 end
2804 end
2805
2806 % replacestrat
2807 if ~isempty(jparam.replacestrat)
2808 switch char(jparam.replacestrat)
2809 case 'RR'
2810 sn.nodeparam{i}.replacestrat = ReplacementStrategy.RR;
2811 case 'FIFO'
2812 sn.nodeparam{i}.replacestrat = ReplacementStrategy.FIFO;
2813 case 'SFIFO'
2814 sn.nodeparam{i}.replacestrat = ReplacementStrategy.SFIFO;
2815 case 'LRU'
2816 sn.nodeparam{i}.replacestrat = ReplacementStrategy.LRU;
2817 end
2818 end
2819
2820 % hitclass
2821 if ~isempty(jparam.hitclass)
2822 sn.nodeparam{i}.hitclass = 1+JLINE.from_jline_matrix(jparam.hitclass);
2823 end
2824
2825 % missclass
2826 if ~isempty(jparam.missclass)
2827 sn.nodeparam{i}.missclass =1+ JLINE.from_jline_matrix(jparam.missclass);
2828 end
2829
2830 % actual hit/miss probabilities
2831 if ~isempty(jparam.actualhitprob)
2832 sn.nodeparam{i}.actualhitprob = JLINE.from_jline_matrix(jparam.actualhitprob);
2833 end
2834 if ~isempty(jparam.actualmissprob)
2835 sn.nodeparam{i}.actualmissprob = JLINE.from_jline_matrix(jparam.actualmissprob);
2836 end
2837 end
2838 end
2839 else
2840 sn.nodeparam = {};
2841 end
2842
2843 % if ~isempty(jsn.nodeparam)
2844 % sn.nodeparam = cell(sn.nnodes, 1);
2845 % % Note that JLINE only support node parameters related to
2846 % % Fork, Join, WWROBIN and RROBIN
2847 % for i = 1:sn.nnodes
2848 % if jsn.nodeparam.get(jnodes.get(i-1)).isEmpty
2849 % sn.nodeparam{i} = [];
2850 % else
2851 % if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).nitems)
2852 % sn.nodeparam{i}.nitems = jsn.nodeparam.get(jnodes.get(i-1)).nitems;
2853 % end
2854 % if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).fanOut)
2855 % sn.nodeparam{i}.fanOut = jsn.nodeparam.get(jnodes.get(i-1)).fanOut;
2856 % end
2857 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy)
2858 % if ~jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.isEmpty
2859 % sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
2860 % sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
2861 % for r = 1:sn.nclasses
2862 % joinStrategy = jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.get(jclasses.get(r-1));
2863 % switch joinStrategy.name.toCharArray'
2864 % case 'STD'
2865 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
2866 % case 'PARTIAL'
2867 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
2868 % end
2869 % sn.nodeparam{i}.fanIn{r} = jsn.nodeparam.get(jnodes.get(i-1)).fanIn.get(jclasses.get(r-1));
2870 % end
2871 % end
2872 % end
2873 %
2874 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).weights)
2875 % for r = 1:sn.nclasses
2876 % sn.nodeparam{i}{r}.weights = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).weights.get(jclasses.get(r-1)));
2877 % end
2878 % end
2879 %
2880 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).outlinks)
2881 % for r = 1:sn.nclasses
2882 % sn.nodeparam{i}{r}.outlinks = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).outlinks.get(jclasses.get(r-1)));
2883 % end
2884 % end
2885 % end
2886 % end
2887 % else
2888 % sn.nodeparam = {};
2889 % end
2890
2891 if ~isempty(jsn.sync)
2892 jsync = jsn.sync;
2893 sn.sync = cell(jsync.size, 1);
2894 for i = 1:jsync.size
2895 jsync_i = jsync.get(uint32(i-1));
2896 sn.sync{i,1} = struct('active',cell(1),'passive',cell(1));
2897
2898 jactive = jsync_i.active.get(uint32(0));
2899 jpassive = jsync_i.passive.get(uint32(0));
2900
2901 %Currently assume that prob would always be a value
2902 %instead of lambda function (No idea of how to convert
2903 %Java lambda function to matlab lambda function)
2904 switch jactive.getEvent.name.toCharArray'
2905 case 'INIT'
2906 sn.sync{i,1}.active{1} = Event(EventType.INIT, jactive.getNode+1, jactive.getJobClass+1, ...
2907 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2908 jactive.getT, jactive.getJob);
2909 case 'LOCAL'
2910 sn.sync{i,1}.active{1} = Event(EventType.LOCAL, jactive.getNode+1, jactive.getJobClass+1, ...
2911 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2912 jactive.getT, jactive.getJob);
2913 case 'ARV'
2914 sn.sync{i,1}.active{1} = Event(EventType.ARV, jactive.getNode+1, jactive.getJobClass+1, ...
2915 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2916 jactive.getT, jactive.getJob);
2917 case 'DEP'
2918 sn.sync{i,1}.active{1} = Event(EventType.DEP, jactive.getNode+1, jactive.getJobClass+1, ...
2919 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2920 jactive.getT, jactive.getJob);
2921 case 'PHASE'
2922 sn.sync{i,1}.active{1} = Event(EventType.PHASE, jactive.getNode+1, jactive.getJobClass+1, ...
2923 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2924 jactive.getT, jactive.getJob);
2925 case 'READ'
2926 sn.sync{i,1}.active{1} = Event(EventType.READ, jactive.getNode+1, jactive.getJobClass+1, ...
2927 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2928 jactive.getT, jactive.getJob);
2929 case 'STAGE'
2930 sn.sync{i,1}.active{1} = Event(EventType.STAGE, jactive.getNode+1, jactive.getJobClass+1, ...
2931 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2932 jactive.getT, jactive.getJob);
2933 end
2934
2935 switch jpassive.getEvent.name.toCharArray'
2936 case 'INIT'
2937 sn.sync{i,1}.passive{1} = Event(EventType.INIT, jpassive.getNode+1, jpassive.getJobClass+1, ...
2938 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2939 jpassive.getT, jpassive.getJob);
2940 case 'LOCAL'
2941 sn.sync{i,1}.passive{1} = Event(EventType.LOCAL, jpassive.getNode+1, jpassive.getJobClass+1, ...
2942 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2943 jpassive.getT, jpassive.getJob);
2944 case 'ARV'
2945 sn.sync{i,1}.passive{1} = Event(EventType.ARV, jpassive.getNode+1, jpassive.getJobClass+1, ...
2946 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2947 jpassive.getT, jpassive.getJob);
2948 case 'DEP'
2949 sn.sync{i,1}.passive{1} = Event(EventType.DEP, jpassive.getNode+1, jpassive.getJobClass+1, ...
2950 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2951 jpassive.getT, jpassive.getJob);
2952 case 'PHASE'
2953 sn.sync{i,1}.passive{1} = Event(EventType.PHASE, jpassive.getNode+1, jpassive.getJobClass+1, ...
2954 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2955 jpassive.getT, jpassive.getJob);
2956 case 'READ'
2957 sn.sync{i,1}.passive{1} = Event(EventType.READ, jpassive.getNode+1, jpassive.getJobClass+1, ...
2958 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2959 jpassive.getT, jpassive.getJob);
2960 case 'STAGE'
2961 sn.sync{i,1}.passive{1} = Event(EventType.STAGE, jpassive.getNode+1, jpassive.getJobClass+1, ...
2962 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2963 jpassive.getT, jpassive.getJob);
2964 end
2965 end
2966 else
2967 sn.sync = {};
2968 end
2969 end
2970
2971 function [QN,UN,RN,WN,AN,TN] = arrayListToResults(alist)
2972 switch class(alist)
2973 case 'jline.solvers.LayeredNetworkAvgTable'
2974 QN = JLINE.arraylist_to_matrix(alist.getQLen());
2975 UN = JLINE.arraylist_to_matrix(alist.getUtil());
2976 RN = JLINE.arraylist_to_matrix(alist.getRespT());
2977 WN = JLINE.arraylist_to_matrix(alist.getResidT());
2978 AN = NaN*JLINE.arraylist_to_matrix(alist.getTput()); % getArvR not yet available in JLINE
2979 TN = JLINE.arraylist_to_matrix(alist.getTput());
2980 otherwise
2981 QN = JLINE.arraylist_to_matrix(alist.getQLen());
2982 UN = JLINE.arraylist_to_matrix(alist.getUtil());
2983 RN = JLINE.arraylist_to_matrix(alist.getRespT());
2984 WN = JLINE.arraylist_to_matrix(alist.getResidT());
2985 AN = JLINE.arraylist_to_matrix(alist.getArvR());
2986 TN = JLINE.arraylist_to_matrix(alist.getTput());
2987 end
2988 end
2989
2990 function featSupported = getFeatureSet()
2991 % FEATSUPPORTED = GETFEATURESET()
2992
2993 featSupported = SolverFeatureSet;
2994 featSupported.setTrue({'Sink','Source',...
2995 'ClassSwitch','Delay','DelayStation','Queue',...
2996 'APH','Coxian','Erlang','Exp','HyperExp',...
2997 'StatelessClassSwitcher','InfiniteServer','SharedServer','Buffer','Dispatcher',...
2998 'Server','JobSink','RandomSource','ServiceTunnel',...
2999 'SchedStrategy_INF','SchedStrategy_PS',...
3000 'RoutingStrategy_PROB','RoutingStrategy_RAND',...
3001 'ClosedClass','OpenClass'});
3002 end
3003
3004 function [bool, featSupported] = supports(model)
3005 % [BOOL, FEATSUPPORTED] = SUPPORTS(MODEL)
3006
3007 featUsed = model.getUsedLangFeatures();
3008 featSupported = JLINE.getFeatureSet();
3009 bool = SolverFeatureSet.supports(featSupported, featUsed);
3010 end
3011
3012
3013 function solverOptions = parseSolverOptions(solverOptions, options)
3014 fn = fieldnames(options);
3015 fn2 = fieldnames(solverOptions);
3016 for f = 1:length(fn)
3017 found = 0;
3018 for j = 1:length(fn2)
3019 if strcmp(fn{f}, fn2{j})
3020 found = 1;
3021 switch fn{f}
3022 case 'seed'
3023 solverOptions.seed = options.seed;
3024 case 'samples'
3025 solverOptions.samples = options.samples;
3026 case 'confint'
3027 % Parse confint - can be a level (0.95) or 0 to disable
3028 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
3029 if confintEnabled
3030 solverOptions.confint = confintLevel;
3031 else
3032 solverOptions.confint = 0;
3033 end
3034 case 'method'
3035 solverOptions.method = options.method;
3036 case 'config'
3037 if isfield(options.config,'eventcache')
3038 solverOptions.config.eventcache = options.config.eventcache;
3039 end
3040 if isfield(options.config,'fork_join')
3041 solverOptions.config.fork_join = options.config.fork_join;
3042 end
3043 if isfield(options.config,'highvar')
3044 solverOptions.config.highvar = options.config.highvar;
3045 end
3046 if isfield(options.config,'multiserver')
3047 solverOptions.config.multiserver = options.config.multiserver;
3048 end
3049 if isfield(options.config,'np_priority')
3050 solverOptions.config.np_priority = options.config.np_priority;
3051 end
3052 case 'verbose'
3053 switch options.(fn{f})
3054 case {VerboseLevel.SILENT}
3055 solverOptions.verbose = solverOptions.verbose.SILENT;
3056 case {VerboseLevel.STD}
3057 solverOptions.verbose = solverOptions.verbose.STD;
3058 case {VerboseLevel.DEBUG}
3059 solverOptions.verbose = solverOptions.verbose.DEBUG;
3060 end
3061 case 'init_sol'
3062 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.init_sol);
3063 case 'cutoff'
3064 if isscalar(options.cutoff)
3065 solverOptions.(fn{f}) = jline.util.matrix.Matrix.singleton(options.cutoff);
3066 else
3067 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.cutoff);
3068 end
3069 case 'odesolvers'
3070 case 'rewardIterations'
3071 solverOptions.rewardIterations = java.lang.Integer(options.rewardIterations);
3072 otherwise
3073 solverOptions.(fn{f}) = options.(fn{f});
3074 end
3075
3076 break;
3077 end
3078 end
3079 if ~found
3080 line_printf('Could not find option %s in the JLINE options.\n', fn{f});
3081 end
3082 end
3083 end
3084
3085 function [ssa] = SolverSSA(network_object, options)
3086 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.SSA);
3087 if nargin>1
3088 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3089 end
3090 jline.util.Maths.setRandomNumbersMatlab(true);
3091 ssa = jline.solvers.ssa.SolverSSA(network_object, solverOptions);
3092 end
3093
3094 function [qns] = SolverQNS(network_object, options)
3095 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.QNS);
3096 if nargin>1
3097 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3098 end
3099 qns = jline.solvers.qns.SolverQNS(network_object, solverOptions);
3100 end
3101
3102 function [mam] = SolverMAM(network_object, options)
3103 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MAM);
3104 if nargin>1
3105 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3106 end
3107 mam = jline.solvers.mam.SolverMAM(network_object, solverOptions);
3108 end
3109
3110 function [jmt] = SolverJMT(network_object, options)
3111 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.JMT);
3112 if nargin>1
3113 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3114 end
3115 jmt = jline.solvers.jmt.SolverJMT(network_object, solverOptions);
3116 end
3117
3118 function [ctmc] = SolverCTMC(network_object, options)
3119 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.CTMC);
3120 if nargin>1
3121 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3122 end
3123 ctmc = jline.solvers.ctmc.SolverCTMC(network_object,solverOptions);
3124 end
3125
3126 function [fluid] = SolverFluid(network_object, options)
3127 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.FLUID);
3128 if nargin>1
3129 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3130 end
3131 fluid = jline.solvers.fluid.SolverFluid(network_object, solverOptions);
3132 end
3133
3134 function [QN, UN, RN, TN, CN, XN, t, QNt, UNt, TNt, xvec] = runFluidAnalyzer(network, options)
3135 % RUNFLUIDANALYZER Run JLINE fluid analyzer and return results
3136 %
3137 % [QN, UN, RN, TN, CN, XN, T, QNT, UNT, TNT, XVEC] = JLINE.runFluidAnalyzer(NETWORK, OPTIONS)
3138 %
3139 % Runs the JLINE fluid solver on the given network and converts
3140 % results back to MATLAB data structures.
3141 %
3142 % Input:
3143 % network - LINE Network model
3144 % options - Solver options structure with fields:
3145 % .method - solver method
3146 % .stiff - use stiff ODE solver
3147 %
3148 % Output:
3149 % QN, UN, RN, TN - Steady-state metrics [M x K]
3150 % CN, XN - System metrics [1 x K]
3151 % t - Time vector [Tmax x 1]
3152 % QNt, UNt, TNt - Transient metrics {M x K} cells
3153 % xvec - State vector structure
3154
3155 jmodel = LINE2JLINE(network);
3156 jsolver = JLINE.SolverFluid(jmodel);
3157 import jline.solvers.fluid.*;
3158
3159 jsolver.options.method = options.method;
3160 jsolver.options.stiff = options.stiff;
3161 result = jsolver.runMethodSpecificAnalyzerViaLINE();
3162
3163 % Convert JLINE result to MATLAB data structures
3164 M = jmodel.getNumberOfStatefulNodes();
3165 K = jmodel.getNumberOfClasses();
3166
3167 QN = NaN * zeros(M, K);
3168 UN = NaN * zeros(M, K);
3169 RN = NaN * zeros(M, K);
3170 TN = NaN * zeros(M, K);
3171 CN = NaN * zeros(1, K);
3172 XN = NaN * zeros(1, K);
3173
3174 QNt = cell(M, K);
3175 UNt = cell(M, K);
3176 TNt = cell(M, K);
3177
3178 Tmax = result.t.length();
3179 t = NaN * zeros(Tmax, 1);
3180
3181 for ist = 1:M
3182 for jst = 1:K
3183 QN(ist, jst) = result.QN.get(ist-1, jst-1);
3184 UN(ist, jst) = result.UN.get(ist-1, jst-1);
3185 RN(ist, jst) = result.RN.get(ist-1, jst-1);
3186 TN(ist, jst) = result.TN.get(ist-1, jst-1);
3187 end
3188 end
3189
3190 for jst = 1:K
3191 CN(1, jst) = result.CN.get(0, jst-1);
3192 XN(1, jst) = result.XN.get(0, jst-1);
3193 end
3194
3195 for ist = 1:M
3196 for jst = 1:K
3197 for p = 1:Tmax
3198 QNt{ist, jst}(p, 1) = result.QNt(ist, jst).get(p-1, 0);
3199 UNt{ist, jst}(p, 1) = result.UNt(ist, jst).get(p-1, 0);
3200 TNt{ist, jst}(p, 1) = result.TNt(ist, jst).get(p-1, 0);
3201 end
3202 end
3203 end
3204
3205 for p = 1:Tmax
3206 t(p, 1) = result.t.get(p-1, 0);
3207 end
3208
3209 % JLINE does not return odeStateVec
3210 xvec.odeStateVec = [];
3211 xvec.sn = network;
3212 end
3213
3214 function [ldes] = SolverLDES(network_object, options)
3215 % Create LDES-specific options object
3216 ldesOptions = jline.solvers.ldes.LDESOptions();
3217 if nargin>1
3218 % Copy standard options
3219 ldesOptions.samples = options.samples;
3220 ldesOptions.seed = options.seed;
3221 % Parse confint
3222 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
3223 if confintEnabled
3224 ldesOptions.confint = confintLevel;
3225 else
3226 ldesOptions.confint = 0;
3227 end
3228 % Pass timespan for transient analysis
3229 if isfield(options, 'timespan') && length(options.timespan) >= 2
3230 ldesOptions.timespan = options.timespan;
3231 end
3232 % Pass LDES-specific options if configured
3233 if isfield(options, 'config')
3234 % Transient detection options
3235 if isfield(options.config, 'tranfilter')
3236 ldesOptions.tranfilter = options.config.tranfilter;
3237 end
3238 if isfield(options.config, 'mserbatch')
3239 ldesOptions.mserbatch = options.config.mserbatch;
3240 end
3241 if isfield(options.config, 'warmupfrac')
3242 ldesOptions.warmupfrac = options.config.warmupfrac;
3243 end
3244 % Confidence interval options
3245 if isfield(options.config, 'cimethod')
3246 ldesOptions.cimethod = options.config.cimethod;
3247 end
3248 if isfield(options.config, 'obmoverlap')
3249 ldesOptions.obmoverlap = options.config.obmoverlap;
3250 end
3251 if isfield(options.config, 'ciminbatch')
3252 ldesOptions.ciminbatch = options.config.ciminbatch;
3253 end
3254 if isfield(options.config, 'ciminobs')
3255 ldesOptions.ciminobs = options.config.ciminobs;
3256 end
3257 if isfield(options.config, 'spectralLowFreqFrac')
3258 ldesOptions.spectralLowFreqFrac = options.config.spectralLowFreqFrac;
3259 end
3260 % Convergence options
3261 if isfield(options.config, 'cnvgon')
3262 ldesOptions.cnvgon = options.config.cnvgon;
3263 end
3264 if isfield(options.config, 'cnvgtol')
3265 ldesOptions.cnvgtol = options.config.cnvgtol;
3266 end
3267 if isfield(options.config, 'cnvgbatch')
3268 ldesOptions.cnvgbatch = options.config.cnvgbatch;
3269 end
3270 if isfield(options.config, 'cnvgchk')
3271 ldesOptions.cnvgchk = options.config.cnvgchk;
3272 end
3273 end
3274 end
3275 ldes = jline.solvers.ldes.SolverLDES(network_object, ldesOptions);
3276 end
3277
3278 function [mva] = SolverMVA(network_object, options)
3279 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MVA);
3280 if nargin>1
3281 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3282 end
3283 mva = jline.solvers.mva.SolverMVA(network_object, solverOptions);
3284 end
3285
3286 function [nc] = SolverNC(network_object, options)
3287 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.NC);
3288 if nargin>1
3289 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3290 end
3291 nc = jline.solvers.nc.SolverNC(network_object, solverOptions);
3292 end
3293
3294 function [auto] = SolverAuto(network_object, options)
3295 solverOptions = jline.solvers.auto.AUTOptions();
3296 if nargin>1
3297 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3298 end
3299 auto = jline.solvers.auto.SolverAUTO(network_object, solverOptions);
3300 end
3301
3302 function streamOpts = StreamingOptions(varargin)
3303 % STREAMINGOPTIONS Create Java StreamingOptions for SSA/LDES stream() method
3304 %
3305 % @brief Creates StreamingOptions for streaming simulation metrics
3306 %
3307 % @param varargin Name-value pairs for options:
3308 % 'transport' - 'http' (recommended) or 'grpc' (default: 'http')
3309 % 'endpoint' - Receiver endpoint (default: 'localhost:8080/metrics' for HTTP)
3310 % 'mode' - 'sampled' or 'time_window' (default: 'sampled')
3311 % 'sampleFrequency' - Push every N events in sampled mode (default: 100)
3312 % 'timeWindowSeconds' - Window duration in time_window mode (default: 1.0)
3313 % 'serviceName' - Service identifier (default: 'line-stream')
3314 % 'includeQueueLength' - Include queue length metrics (default: true)
3315 % 'includeUtilization' - Include utilization metrics (default: true)
3316 % 'includeThroughput' - Include throughput metrics (default: true)
3317 % 'includeResponseTime' - Include response time metrics (default: true)
3318 % 'includeArrivalRate' - Include arrival rate metrics (default: true)
3319 %
3320 % @return streamOpts Java StreamingOptions object
3321 %
3322 % Example:
3323 % @code
3324 % streamOpts = JLINE.StreamingOptions('transport', 'http', 'sampleFrequency', 50);
3325 % @endcode
3326
3327 streamOpts = jline.streaming.StreamingOptions();
3328
3329 % Parse optional arguments
3330 p = inputParser;
3331 addParameter(p, 'transport', 'http', @ischar);
3332 addParameter(p, 'endpoint', '', @ischar); % Empty means use default for transport
3333 addParameter(p, 'mode', 'sampled', @ischar);
3334 addParameter(p, 'sampleFrequency', 100, @isnumeric);
3335 addParameter(p, 'timeWindowSeconds', 1.0, @isnumeric);
3336 addParameter(p, 'serviceName', 'line-stream', @ischar);
3337 addParameter(p, 'includeQueueLength', true, @islogical);
3338 addParameter(p, 'includeUtilization', true, @islogical);
3339 addParameter(p, 'includeThroughput', true, @islogical);
3340 addParameter(p, 'includeResponseTime', true, @islogical);
3341 addParameter(p, 'includeArrivalRate', true, @islogical);
3342 parse(p, varargin{:});
3343
3344 % Set transport type
3345 transportTypes = javaMethod('values', 'jline.streaming.StreamingOptions$TransportType');
3346 switch lower(p.Results.transport)
3347 case 'http'
3348 streamOpts.transport = transportTypes(1); % HTTP
3349 case 'grpc'
3350 streamOpts.transport = transportTypes(2); % GRPC
3351 otherwise
3352 streamOpts.transport = transportTypes(1); % Default to HTTP
3353 end
3354
3355 % Set endpoint (use provided or default based on transport)
3356 if ~isempty(p.Results.endpoint)
3357 streamOpts.endpoint = p.Results.endpoint;
3358 end
3359 % If empty, StreamingOptions uses its default for the transport type
3360
3361 % Set mode
3362 streamModes = javaMethod('values', 'jline.streaming.StreamingOptions$StreamMode');
3363 switch lower(p.Results.mode)
3364 case 'sampled'
3365 streamOpts.mode = streamModes(1); % SAMPLED
3366 case 'time_window'
3367 streamOpts.mode = streamModes(2); % TIME_WINDOW
3368 otherwise
3369 streamOpts.mode = streamModes(1); % Default to SAMPLED
3370 end
3371
3372 % Set other options
3373 streamOpts.sampleFrequency = p.Results.sampleFrequency;
3374 streamOpts.timeWindowSeconds = p.Results.timeWindowSeconds;
3375 streamOpts.serviceName = p.Results.serviceName;
3376 streamOpts.includeQueueLength = p.Results.includeQueueLength;
3377 streamOpts.includeUtilization = p.Results.includeUtilization;
3378 streamOpts.includeThroughput = p.Results.includeThroughput;
3379 streamOpts.includeResponseTime = p.Results.includeResponseTime;
3380 streamOpts.includeArrivalRate = p.Results.includeArrivalRate;
3381 end
3382
3383 function result = convertSampleResult(jresult)
3384 % CONVERTSAMPLERESULT Convert Java sample result to MATLAB struct
3385 %
3386 % @brief Converts Java SampleNodeState to MATLAB structure
3387 %
3388 % @param jresult Java SampleNodeState object
3389 % @return result MATLAB struct with fields: t, state, isaggregate
3390
3391 result = struct();
3392
3393 % Convert time matrix
3394 if ~isempty(jresult.t)
3395 result.t = JLINE.from_jline_matrix(jresult.t);
3396 else
3397 result.t = [];
3398 end
3399
3400 % Convert state matrix
3401 if ~isempty(jresult.state) && isa(jresult.state, 'jline.util.matrix.Matrix')
3402 result.state = JLINE.from_jline_matrix(jresult.state);
3403 else
3404 result.state = [];
3405 end
3406
3407 result.isaggregate = jresult.isaggregate;
3408 end
3409
3410 function [ln] = SolverLN(layered_network_object, options)
3411 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.LN);
3412 if nargin>1
3413 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3414 end
3415 ln = jline.solvers.ln.SolverLN(layered_network_object, solverOptions);
3416 end
3417
3418 function serfun = handle_to_serializablefun(handle, sn)
3419 % HANDLE_TO_SERIALIZABLEFUN Convert MATLAB function handle to Java SerializableFunction
3420 %
3421 % This function pre-computes the function values for all possible state
3422 % combinations and creates a Java PrecomputedCDFunction object.
3423 %
3424 % @param handle MATLAB function handle that takes a vector ni and returns a scalar
3425 % @param sn Network struct containing njobs (population per class)
3426 % @return serfun Java PrecomputedCDFunction object
3427
3428 % Get number of classes and maximum populations
3429 nclasses = sn.nclasses;
3430 njobs = sn.njobs; % Population per class
3431
3432 % For open classes (njobs=0), use a reasonable bound
3433 maxPop = njobs;
3434 for r = 1:nclasses
3435 if maxPop(r) == 0 || isinf(maxPop(r))
3436 % For open classes, use sum of closed class populations or 100 as bound
3437 maxPop(r) = max(100, sum(njobs(isfinite(njobs) & njobs > 0)));
3438 end
3439 end
3440
3441 % Create Java PrecomputedCDFunction object
3442 serfun = jline.util.PrecomputedCDFunction(nclasses);
3443
3444 % Enumerate all possible state combinations and pre-compute function values
3445 % Use recursive enumeration to handle arbitrary number of classes
3446 JLINE.enumerate_states(handle, serfun, maxPop, zeros(1, nclasses), 1);
3447 end
3448
3449 function enumerate_states(handle, serfun, maxPop, currentState, classIdx)
3450 % ENUMERATE_STATES Recursively enumerate all state combinations
3451 %
3452 % @param handle MATLAB function handle
3453 % @param serfun Java PrecomputedCDFunction object to populate
3454 % @param maxPop Maximum population per class
3455 % @param currentState Current state being built
3456 % @param classIdx Current class index being enumerated
3457
3458 nclasses = length(maxPop);
3459
3460 if classIdx > nclasses
3461 % We have a complete state, compute and store the function value
3462 try
3463 value = handle(currentState);
3464 % Convert to Java int array and add to serfun
3465 jstate = jline.util.matrix.Matrix(1, nclasses);
3466 for r = 1:nclasses
3467 jstate.set(0, r-1, currentState(r));
3468 end
3469 serfun.addValue(jstate, value);
3470 catch
3471 % If function evaluation fails, skip this state
3472 end
3473 return;
3474 end
3475
3476 % Enumerate all populations for current class
3477 for n = 0:maxPop(classIdx)
3478 currentState(classIdx) = n;
3479 JLINE.enumerate_states(handle, serfun, maxPop, currentState, classIdx + 1);
3480 end
3481 end
3482
3483 function result = call_java_cdscaling(jfun, ni)
3484 % CALL_JAVA_CDSCALING Call a Java SerializableFunction for class dependence
3485 %
3486 % This function converts a MATLAB vector to a Java Matrix and calls
3487 % the Java function's apply() method.
3488 %
3489 % @param jfun Java SerializableFunction<Matrix, Double> object
3490 % @param ni MATLAB vector representing the state (jobs per class)
3491 % @return result The scaling factor returned by the Java function
3492
3493 % Convert MATLAB vector to Java Matrix
3494 if isrow(ni)
3495 jmatrix = jline.util.matrix.Matrix(1, length(ni));
3496 for r = 1:length(ni)
3497 jmatrix.set(0, r-1, ni(r));
3498 end
3499 else
3500 jmatrix = jline.util.matrix.Matrix(length(ni), 1);
3501 for r = 1:length(ni)
3502 jmatrix.set(r-1, 0, ni(r));
3503 end
3504 end
3505
3506 % Call the Java function and convert result to MATLAB double
3507 jresult = jfun.apply(jmatrix);
3508 result = double(jresult);
3509 end
3510
3511 function jSched = to_jline_sched_strategy(schedId)
3512 % Convert MATLAB SchedStrategy id to jline SchedStrategy enum
3513 switch schedId
3514 case SchedStrategy.REF
3515 jSched = jline.lang.constant.SchedStrategy.REF;
3516 case SchedStrategy.INF
3517 jSched = jline.lang.constant.SchedStrategy.INF;
3518 case SchedStrategy.FCFS
3519 jSched = jline.lang.constant.SchedStrategy.FCFS;
3520 case SchedStrategy.LCFS
3521 jSched = jline.lang.constant.SchedStrategy.LCFS;
3522 case SchedStrategy.SIRO
3523 jSched = jline.lang.constant.SchedStrategy.SIRO;
3524 case SchedStrategy.SJF
3525 jSched = jline.lang.constant.SchedStrategy.SJF;
3526 case SchedStrategy.LJF
3527 jSched = jline.lang.constant.SchedStrategy.LJF;
3528 case SchedStrategy.PS
3529 jSched = jline.lang.constant.SchedStrategy.PS;
3530 case SchedStrategy.DPS
3531 jSched = jline.lang.constant.SchedStrategy.DPS;
3532 case SchedStrategy.GPS
3533 jSched = jline.lang.constant.SchedStrategy.GPS;
3534 case SchedStrategy.SEPT
3535 jSched = jline.lang.constant.SchedStrategy.SEPT;
3536 case SchedStrategy.LEPT
3537 jSched = jline.lang.constant.SchedStrategy.LEPT;
3538 case {SchedStrategy.HOL, SchedStrategy.FCFSPRIO}
3539 jSched = jline.lang.constant.SchedStrategy.FCFSPRIO;
3540 case SchedStrategy.FORK
3541 jSched = jline.lang.constant.SchedStrategy.FORK;
3542 case SchedStrategy.EXT
3543 jSched = jline.lang.constant.SchedStrategy.EXT;
3544 case SchedStrategy.LCFSPR
3545 jSched = jline.lang.constant.SchedStrategy.LCFSPR;
3546 case SchedStrategy.PSPRIO
3547 jSched = jline.lang.constant.SchedStrategy.PSPRIO;
3548 case SchedStrategy.DPSPRIO
3549 jSched = jline.lang.constant.SchedStrategy.DPSPRIO;
3550 case SchedStrategy.GPSPRIO
3551 jSched = jline.lang.constant.SchedStrategy.GPSPRIO;
3552 otherwise
3553 jSched = jline.lang.constant.SchedStrategy.FCFS;
3554 end
3555 end
3556
3557 function jwf = from_line_workflow(line_wf)
3558 % Convert a MATLAB Workflow to a JAR Workflow.
3559 jwf = javaObject('jline.lang.workflow.Workflow', java.lang.String(line_wf.getName()));
3560 acts = line_wf.activities;
3561 for a = 1:length(acts)
3562 act = acts{a};
3563 actName = java.lang.String(act.name);
3564 if ~isempty(act.hostDemand) && isa(act.hostDemand, 'Distribution')
3565 jdist = JLINE.from_line_distribution(act.hostDemand);
3566 jwf.addActivity(actName, jdist);
3567 else
3568 jwf.addActivity(actName, 1.0);
3569 end
3570 end
3571 precs = line_wf.precedences;
3572 for p = 1:length(precs)
3573 prec = precs(p);
3574 preActs = java.util.ArrayList();
3575 for k = 1:length(prec.preActs)
3576 preActs.add(java.lang.String(prec.preActs{k}));
3577 end
3578 postActs = java.util.ArrayList();
3579 for k = 1:length(prec.postActs)
3580 postActs.add(java.lang.String(prec.postActs{k}));
3581 end
3582 preTypeStr = java.lang.String(ActivityPrecedenceType.toText(prec.preType));
3583 postTypeStr = java.lang.String(ActivityPrecedenceType.toText(prec.postType));
3584 if ~isempty(prec.preParams)
3585 preParamsMat = JLINE.from_line_matrix(prec.preParams(:)');
3586 else
3587 preParamsMat = javaObject('jline.util.matrix.Matrix', 0, 0);
3588 end
3589 if ~isempty(prec.postParams)
3590 postParamsMat = JLINE.from_line_matrix(prec.postParams(:)');
3591 else
3592 postParamsMat = javaObject('jline.util.matrix.Matrix', 0, 0);
3593 end
3594 jprec = javaObject('jline.lang.layered.ActivityPrecedence', ...
3595 preActs, postActs, preTypeStr, postTypeStr, preParamsMat, postParamsMat);
3596 jwf.addPrecedence(jprec);
3597 end
3598 end
3599
3600 function jenv = from_line_environment(line_env)
3601 % Convert a MATLAB Environment to a JAR Environment.
3602 E = height(line_env.envGraph.Nodes);
3603 jenv = javaObject('jline.lang.Environment', java.lang.String(line_env.getName()), int32(E));
3604 for e = 1:E
3605 stageName = char(line_env.envGraph.Nodes.Name{e});
3606 stageType = char(line_env.envGraph.Nodes.Type{e});
3607 stageModel = line_env.ensemble{e};
3608 jmodel = JLINE.from_line_network(stageModel);
3609 jenv.addStage(int32(e-1), java.lang.String(stageName), java.lang.String(stageType), jmodel);
3610 end
3611 if ~isempty(line_env.env)
3612 [Erows, Ecols] = size(line_env.env);
3613 for e = 1:Erows
3614 for h = 1:Ecols
3615 d = line_env.env{e,h};
3616 if isempty(d) || isa(d, 'Disabled')
3617 continue;
3618 end
3619 jdist = JLINE.from_line_distribution(d);
3620 jenv.addTransition(int32(e-1), int32(h-1), jdist);
3621 end
3622 end
3623 end
3624 jenv.init();
3625 end
3626
3627 end
3628end
Definition mmt.m:124