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