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 % Add equal-probability entries to routing matrix
1169 % so that link() preserves RAND routing
1170 nout = 0;
1171 for j= outlinks_i(:)'
1172 jdest_idx = matlab2java_node_idx(j);
1173 if jdest_idx >= 0
1174 nout = nout + 1;
1175 end
1176 end
1177 if nout > 0
1178 prob = 1.0 / nout;
1179 for j= outlinks_i(:)'
1180 jdest_idx = matlab2java_node_idx(j);
1181 if jdest_idx >= 0
1182 jrt_matrix.set(jclasses.get(k-1), jclasses.get(k-1), jnodes.get(jnode_idx), jnodes.get(jdest_idx), prob);
1183 end
1184 end
1185 end
1186 else
1187 for j= outlinks_i(:)'
1188 jdest_idx = matlab2java_node_idx(j);
1189 if jdest_idx >= 0
1190 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1191 end
1192 end
1193 end
1194 case RoutingStrategy.RROBIN
1195 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RROBIN);
1196 outlinks_i=find(connections(i,:))';
1197 if useLinkMethod
1198 line_error(mfilename,'RROBIN cannot be used together with the link() command.');
1199 end
1200 for j= outlinks_i(:)'
1201 jdest_idx = matlab2java_node_idx(j);
1202 if jdest_idx >= 0
1203 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1204 end
1205 end
1206 case RoutingStrategy.WRROBIN
1207 outlinks_i=find(connections(i,:))';
1208 for j= outlinks_i(:)'
1209 jdest_idx = matlab2java_node_idx(j);
1210 if jdest_idx >= 0
1211 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1212 end
1213 end
1214 if useLinkMethod
1215 line_error(mfilename,'RROBIN cannot be used together with the link() command.');
1216 end
1217 for j= 1:length(output_strat{3})
1218 node_target = jmodel.getNodeByName(output_strat{3}{j}{1}.getName());
1219 weight = output_strat{3}{j}{2};
1220 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.WRROBIN, node_target, weight);
1221 end
1222 case RoutingStrategy.PROB
1223 outlinks_i=find(connections(i,:));
1224 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1), jline.lang.constant.RoutingStrategy.PROB);
1225 if ~useLinkMethod
1226 for j= outlinks_i(:)'
1227 jdest_idx = matlab2java_node_idx(j);
1228 if jdest_idx >= 0
1229 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1230 end
1231 end
1232 end
1233 if length(output_strat) >= 3
1234 probabilities = output_strat{3};
1235 for j = 1:length(probabilities)
1236 dest_idx = probabilities{j}{1}.index;
1237 jdest_idx = matlab2java_node_idx(dest_idx);
1238 if (connections(i, dest_idx) ~= 0) && jdest_idx >= 0
1239 if useLinkMethod
1240 jrt_matrix.set(jclasses.get(k-1), jclasses.get(k-1), jnodes.get(jnode_idx), jnodes.get(jdest_idx), probabilities{j}{2});
1241 else
1242 jnodes.get(jnode_idx).setProbRouting(jclasses.get(k-1), jnodes.get(jdest_idx), probabilities{j}{2});
1243 end
1244 end
1245 end
1246 end
1247 otherwise
1248 line_warning(mfilename, sprintf('''%s'' routing strategy not supported by JLINE, setting as Disabled.\n',output_strat{2}));
1249 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1250 end
1251 end
1252 end
1253 end
1254 if useLinkMethod
1255 jmodel.link(jrt_matrix);
1256 % Align the sn.rtorig be the same, treating artificial
1257 % ClassSwitch nodes as if they were explicitly specified
1258 jsn = jmodel.getStruct(true);
1259 rtorig = java.util.HashMap();
1260 if ~isempty(model.sn.rtorig)
1261 if iscell(model.sn.rtorig)
1262 for r = 1:njclasses
1263 sub_rtorig = java.util.HashMap();
1264 for s = 1:njclasses
1265 sub_rtorig.put(jclasses.get(s-1), JLINE.from_line_matrix(model.sn.rtorig{r,s}));
1266 end
1267 rtorig.put(jclasses.get(r-1), sub_rtorig);
1268 end
1269 end
1270 end
1271 jsn.rtorig = rtorig;
1272 end
1273 end
1274
1275 function model = from_jline_routing(model, jnetwork)
1276 jnodes = jnetwork.getNodes();
1277 jclasses = jnetwork.getClasses();
1278 %n_classes = jclasses.size();
1279 n_nodes = jnodes.size();
1280 network_nodes = model.getNodes;
1281 network_classes = model.getClasses;
1282
1283 connections = JLINE.from_jline_matrix(jnetwork.getConnectionMatrix());
1284 [row,col] = find(connections);
1285 for i=1:length(row)
1286 model.addLink(network_nodes{row(i)},network_nodes{col(i)});
1287 end
1288
1289 for n = 1 : n_nodes
1290 jnode = jnodes.get(n-1);
1291 output_strategies = jnode.getOutputStrategies();
1292 n_strategies = output_strategies.size();
1293 for m = 1 : n_strategies
1294 output_strat = output_strategies.get(m-1);
1295 routing_strat = output_strat.getRoutingStrategy;
1296 routing_strat_classidx = output_strat.getJobClass.getIndex();
1297 switch char(routing_strat)
1298 case 'RAND'
1299 network_nodes{n}.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RAND);
1300 case 'RROBIN'
1301 network_nodes{n}.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1302 case 'DISABLED'
1303 network_nodes{n}.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1304 end
1305 end
1306 end
1307 end
1308
1309 function model = from_jline_links(model, jnetwork)
1310 P = model.initRoutingMatrix;
1311 jnodes = jnetwork.getNodes();
1312 jclasses = jnetwork.getClasses();
1313 n_classes = jclasses.size();
1314 n_nodes = jnodes.size();
1315
1316 for n = 1 : n_nodes
1317 jnode = jnodes.get(n-1);
1318 output_strategies = jnode.getOutputStrategies();
1319 n_strategies = output_strategies.size();
1320 for m = 1 : n_strategies
1321 output_strat = output_strategies.get(m-1);
1322 dest = output_strat.getDestination();
1323 if~isempty(dest) % disabled strategy
1324 in_idx = jnetwork.getNodeIndex(jnode)+1;
1325 out_idx = jnetwork.getNodeIndex(dest)+1;
1326 if n_classes == 1
1327 P{1}(in_idx,out_idx) = output_strat.getProbability();
1328 else
1329 strat_class = output_strat.getJobClass();
1330 class_idx = jnetwork.getJobClassIndex(strat_class)+1;
1331 P{class_idx,class_idx}(in_idx,out_idx) = output_strat.getProbability();
1332 end
1333 end
1334 end
1335 end
1336 model.link(P);
1337
1338 %Align the sn.rtorig be the same (Assume Java network is
1339 %created by calling Network.link)
1340 sn = jnetwork.getStruct;
1341 rtorig = cell(n_classes, n_classes);
1342 for r = 1:n_classes
1343 for s = 1:n_classes
1344 rtorig{r,s} = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1345 end
1346 end
1347 model.sn.rtorig = rtorig;
1348 end
1349
1350 function [jnetwork] = from_line_network(model)
1351 %w = warning;
1352 %warning('off');
1353 sn = model.getStruct;
1354
1355 jnetwork = jline.lang.Network(model.getName);
1356 line_nodes = model.getNodes;
1357 line_classes = model.getClasses;
1358
1359 jnodes = cell(1,length(line_nodes));
1360 jclasses = cell(1,length(line_classes));
1361
1362 for n = 1 : length(line_nodes)
1363 % Skip auto-added ClassSwitch nodes - Java's link() will add them automatically
1364 if isa(line_nodes{n}, 'ClassSwitch') && line_nodes{n}.autoAdded
1365 continue;
1366 end
1367 if isa(line_nodes{n}, 'Join')
1368 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, jnodes{line_nodes{n}.joinOf.index}, sn);
1369 else
1370 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, [], sn);
1371 end
1372 end
1373
1374 for n = 1 : length(line_classes)
1375 jclasses{n} = JLINE.from_line_class(line_classes{n}, jnetwork);
1376 end
1377
1378 % Set up forJobClass associations for signal classes
1379 for n = 1 : length(line_classes)
1380 if (isa(line_classes{n}, 'Signal') || isa(line_classes{n}, 'OpenSignal') || isa(line_classes{n}, 'ClosedSignal'))
1381 if ~isempty(line_classes{n}.targetJobClass)
1382 targetIdx = line_classes{n}.targetJobClass.index;
1383 jclasses{n}.forJobClass(jclasses{targetIdx});
1384 end
1385 end
1386 end
1387
1388 for n = 1: length(jnodes)
1389 if isempty(jnodes{n})
1390 continue; % Skip nodes that were not converted (e.g., auto-added ClassSwitch)
1391 end
1392 JLINE.set_service(line_nodes{n}, jnodes{n}, line_classes);
1393 JLINE.set_delayoff(line_nodes{n}, jnodes{n}, line_classes);
1394 end
1395
1396 % Set drop rules for stations (after classes are created)
1397 for n = 1: length(jnodes)
1398 if isempty(jnodes{n})
1399 continue; % Skip nodes that were not converted
1400 end
1401 if isa(line_nodes{n}, 'Station') && ~isa(line_nodes{n}, 'Source')
1402 for r = 1:length(line_classes)
1403 if length(line_nodes{n}.dropRule) >= r && ~isempty(line_nodes{n}.dropRule(r))
1404 dropRule = line_nodes{n}.dropRule(r);
1405 switch dropRule
1406 case DropStrategy.DROP
1407 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.Drop);
1408 case DropStrategy.BAS
1409 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.BlockingAfterService);
1410 case DropStrategy.WAITQ
1411 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.WaitingQueue);
1412 end
1413 end
1414 end
1415 end
1416 end
1417
1418 % Transfer LJCD (Limited Joint Class Dependence) scaling for stations
1419 % This must be done after classes are created since LJCD is indexed per-class
1420 for n = 1:length(jnodes)
1421 if isempty(jnodes{n})
1422 continue;
1423 end
1424 if isa(line_nodes{n}, 'Station') && ~isempty(line_nodes{n}.ljcdScaling) && ~isempty(line_nodes{n}.ljcdCutoffs)
1425 jCutoffs = JLINE.from_line_matrix(line_nodes{n}.ljcdCutoffs(:));
1426 K = length(line_nodes{n}.ljcdScaling);
1427 jScalingMap = java.util.HashMap();
1428 for c = 1:K
1429 if ~isempty(line_nodes{n}.ljcdScaling{c})
1430 jScalingVec = JLINE.from_line_matrix(line_nodes{n}.ljcdScaling{c}(:));
1431 jScalingMap.put(jclasses{c}, jScalingVec);
1432 end
1433 end
1434 jnodes{n}.setLimitedJointClassDependence(jScalingMap, jCutoffs);
1435 end
1436 end
1437
1438 % Set polling type and switchover times for polling queues
1439 for n = 1: length(jnodes)
1440 if isempty(jnodes{n})
1441 continue;
1442 end
1443 if isa(line_nodes{n}, 'Queue') && line_nodes{n}.schedStrategy == SchedStrategy.POLLING
1444 % Set polling type
1445 if ~isempty(line_nodes{n}.pollingType) && ~isempty(line_nodes{n}.pollingType{1})
1446 pollingType = line_nodes{n}.pollingType{1};
1447 switch pollingType
1448 case PollingType.GATED
1449 jPollingType = jline.lang.constant.PollingType.GATED;
1450 case PollingType.EXHAUSTIVE
1451 jPollingType = jline.lang.constant.PollingType.EXHAUSTIVE;
1452 case PollingType.KLIMITED
1453 jPollingType = jline.lang.constant.PollingType.KLIMITED;
1454 end
1455 if pollingType == PollingType.KLIMITED && ~isempty(line_nodes{n}.pollingPar)
1456 jnodes{n}.setPollingType(jPollingType, int32(line_nodes{n}.pollingPar));
1457 else
1458 jnodes{n}.setPollingType(jPollingType);
1459 end
1460 end
1461 % Set switchover times
1462 if ~isempty(line_nodes{n}.switchoverTime)
1463 for r = 1:length(line_classes)
1464 if length(line_nodes{n}.switchoverTime) >= r && ~isempty(line_nodes{n}.switchoverTime{r})
1465 soTime = line_nodes{n}.switchoverTime{r};
1466 if ~isa(soTime, 'Immediate')
1467 jnodes{n}.setSwitchover(jclasses{r}, JLINE.from_line_distribution(soTime));
1468 end
1469 end
1470 end
1471 end
1472 end
1473 end
1474
1475 for n = 1: length(jnodes)
1476 if isempty(jnodes{n})
1477 continue; % Skip nodes that were not converted
1478 end
1479 if isa(line_nodes{n},"ClassSwitch") && ~line_nodes{n}.autoAdded
1480 % Only set csMatrix for user-defined ClassSwitch nodes (not auto-added)
1481 JLINE.set_csMatrix(line_nodes{n}, jnodes{n}, jclasses);
1482 elseif isa(line_nodes{n},"Join")
1483 jnodes{n}.initJoinJobClasses();
1484 elseif isa(line_nodes{n},"Cache")
1485 for r = 1 : sn.nclasses
1486 if length(line_nodes{n}.server.hitClass) >= r && ~isempty(line_nodes{n}.server.hitClass(r))
1487 if ~isa(line_nodes{n}.popularity{r},'Disabled')
1488 jnodes{n}.setRead(jclasses{r}, JLINE.from_line_distribution(line_nodes{n}.popularity{r}));
1489 jnodes{n}.setHitClass(jclasses{r}, jclasses{line_nodes{n}.server.hitClass(r)});
1490 jnodes{n}.setMissClass(jclasses{r}, jclasses{line_nodes{n}.server.missClass(r)});
1491 end
1492 end
1493 end
1494 % Transfer accessProb from MATLAB to Java
1495 if ~isempty(line_nodes{n}.accessProb)
1496 accessProbMat = line_nodes{n}.accessProb;
1497 [K1, K2] = size(accessProbMat);
1498 jAccessProb = javaArray('jline.util.matrix.Matrix', K1, K2);
1499 for k1 = 1:K1
1500 for k2 = 1:K2
1501 if ~isempty(accessProbMat{k1, k2})
1502 jAccessProb(k1, k2) = JLINE.from_line_matrix(accessProbMat{k1, k2});
1503 end
1504 end
1505 end
1506 jnodes{n}.setAccessProb(jAccessProb);
1507 end
1508 elseif isa(line_nodes{n}, "Transition")
1509 % First, add modes (must be done after classes are created)
1510 for m = 1:line_nodes{n}.getNumberOfModes()
1511 modeName = line_nodes{n}.modeNames{m};
1512 jmode = jnodes{n}.addMode(modeName);
1513 % Set timing strategy
1514 switch line_nodes{n}.timingStrategies(m)
1515 case TimingStrategy.TIMED
1516 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.TIMED);
1517 case TimingStrategy.IMMEDIATE
1518 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.IMMEDIATE);
1519 end
1520 % Set distribution
1521 jnodes{n}.setDistribution(jmode, JLINE.from_line_distribution(line_nodes{n}.distributions{m}));
1522 % Set firing weights and priorities
1523 jnodes{n}.setFiringWeights(jmode, line_nodes{n}.firingWeights(m));
1524 jnodes{n}.setFiringPriorities(jmode, int32(line_nodes{n}.firingPriorities(m)));
1525 % Set number of servers
1526 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(line_nodes{n}.numberOfServers(m)));
1527 end
1528 % Now set enabling conditions, inhibiting conditions, and firing outcomes
1529 jmodes = jnodes{n}.getModes();
1530 for m = 1:line_nodes{n}.getNumberOfModes()
1531 jmode = jmodes.get(m-1);
1532 enabCond = line_nodes{n}.enablingConditions{m};
1533 inhibCond = line_nodes{n}.inhibitingConditions{m};
1534 firingOut = line_nodes{n}.firingOutcomes{m};
1535 for r = 1:sn.nclasses
1536 for i = 1:length(line_nodes)
1537 % Set enabling conditions
1538 if enabCond(i, r) > 0 && isa(line_nodes{i}, 'Place')
1539 jnodes{n}.setEnablingConditions(jmode, jclasses{r}, jnodes{i}, enabCond(i, r));
1540 end
1541 % Set inhibiting conditions
1542 if inhibCond(i, r) < Inf && isa(line_nodes{i}, 'Place')
1543 jnodes{n}.setInhibitingConditions(jmode, jclasses{r}, jnodes{i}, inhibCond(i, r));
1544 end
1545 % Set firing outcomes
1546 if firingOut(i, r) ~= 0
1547 jnodes{n}.setFiringOutcome(jmode, jclasses{r}, jnodes{i}, firingOut(i, r));
1548 end
1549 end
1550 end
1551 end
1552 end
1553 end
1554
1555 % Assume JLINE and LINE network are both created via link
1556 JLINE.from_line_links(model, jnetwork);
1557
1558 % Transfer finite capacity regions from MATLAB to Java
1559 if ~isempty(model.regions)
1560 for f = 1:length(model.regions)
1561 fcr = model.regions{f};
1562 % Convert MATLAB node list to Java list
1563 javaNodeList = java.util.ArrayList();
1564 for i = 1:length(fcr.nodes)
1565 matlabNode = fcr.nodes{i};
1566 % Find corresponding Java node by name
1567 nodeName = matlabNode.getName();
1568 for j = 1:length(line_nodes)
1569 if strcmp(line_nodes{j}.getName(), nodeName) && ~isempty(jnodes{j})
1570 javaNodeList.add(jnodes{j});
1571 break;
1572 end
1573 end
1574 end
1575 % Create Java FCR
1576 jfcr = jnetwork.addRegion(javaNodeList);
1577 % Set global max jobs
1578 if fcr.globalMaxJobs > 0 && ~isinf(fcr.globalMaxJobs)
1579 jfcr.setGlobalMaxJobs(fcr.globalMaxJobs);
1580 end
1581 % Set per-class max jobs and drop rules
1582 for r = 1:length(line_classes)
1583 if length(fcr.classMaxJobs) >= r && fcr.classMaxJobs(r) > 0 && ~isinf(fcr.classMaxJobs(r))
1584 jfcr.setClassMaxJobs(jclasses{r}, fcr.classMaxJobs(r));
1585 end
1586 if length(fcr.dropRule) >= r
1587 % Convert MATLAB DropStrategy numeric to Java DropStrategy enum
1588 jDropStrategy = jline.lang.constant.DropStrategy.fromID(fcr.dropRule(r));
1589 jfcr.setDropRule(jclasses{r}, jDropStrategy);
1590 end
1591 end
1592 end
1593 end
1594
1595 jnetwork.initDefault;
1596 for n = 1: length(line_nodes)
1597 if isempty(jnodes{n})
1598 continue; % Skip nodes that were not converted
1599 end
1600 if line_nodes{n}.isStateful
1601 jnodes{n}.setState(JLINE.from_line_matrix(line_nodes{n}.getState));
1602 jnodes{n}.setStateSpace(JLINE.from_line_matrix(line_nodes{n}.getStateSpace));
1603 jnodes{n}.setStatePrior(JLINE.from_line_matrix(line_nodes{n}.getStatePrior));
1604 end
1605 end
1606 % Force struct refresh so sn.state reflects updated node states
1607 jnetwork.setHasStruct(false);
1608
1609 end
1610
1611 function jnetwork = line_to_jline(model)
1612 jnetwork = LINE2JLINE(model);
1613 end
1614
1615 function model = jline_to_line(jnetwork)
1616 if isa(jnetwork,'JNetwork')
1617 jnetwork = jnetwork.obj;
1618 end
1619 %javaaddpath(jar_loc);
1620 model = Network(char(jnetwork.getName));
1621 network_nodes = jnetwork.getNodes;
1622 job_classes = jnetwork.getClasses;
1623
1624 line_nodes = cell(network_nodes.size,1);
1625 line_classes = cell(job_classes.size,1);
1626
1627
1628 for n = 1 : network_nodes.size
1629 if ~isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch')
1630 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
1631 end
1632 end
1633
1634 for n = 1 : job_classes.size
1635 line_classes{n} = JLINE.from_jline_class(job_classes.get(n-1), model);
1636 end
1637
1638 for n = 1 : network_nodes.size
1639 if isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch')
1640 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
1641 end
1642 end
1643
1644 for n = 1 : network_nodes.size
1645 JLINE.set_line_service(network_nodes.get(n-1), line_nodes{n}, job_classes, line_classes);
1646 end
1647
1648 if ~isempty(jnetwork.getStruct.rtorig)
1649 % Use link() method
1650 model = JLINE.from_jline_links(model, jnetwork);
1651 else
1652 % Do not use link() method
1653 model = JLINE.from_jline_routing(model, jnetwork);
1654 end
1655 end
1656
1657 function matrix = arraylist_to_matrix(jline_matrix)
1658 if isempty(jline_matrix)
1659 matrix = [];
1660 else
1661 matrix = zeros(jline_matrix.size(), 1);
1662 for row = 1:jline_matrix.size()
1663 matrix(row, 1) = jline_matrix.get(row-1);
1664 end
1665 end
1666 end
1667
1668 function matrix = from_jline_matrix(jline_matrix)
1669 if isempty(jline_matrix)
1670 matrix = [];
1671 else
1672 matrix = zeros(jline_matrix.getNumRows(), jline_matrix.getNumCols());
1673 for row = 1:jline_matrix.getNumRows()
1674 for col = 1:jline_matrix.getNumCols()
1675 val = jline_matrix.get(row-1, col-1);
1676 if (val >= 33333333 && val <= 33333334)
1677 matrix(row, col) = GlobalConstants.Immediate;
1678 elseif (val >= -33333334 && val <= -33333333)
1679 matrix(row, col) = -GlobalConstants.Immediate;
1680 elseif (val >= 2147483647 - 1) % Integer.MAX_VALUE with -1 tolerance
1681 matrix(row, col) = Inf;
1682 elseif (val <= -2147483648 + 1) % Integer.MIN_VALUE with +1 tolerance
1683 matrix(row, col) = -Inf;
1684 else
1685 matrix(row, col) = val;
1686 end
1687 end
1688 end
1689 end
1690 end
1691
1692 function jline_matrix = from_line_matrix(matrix)
1693 [rows, cols] = size(matrix);
1694 jline_matrix = jline.util.matrix.Matrix(rows, cols);
1695 for row = 1:rows
1696 for col = 1:cols
1697 if matrix(row,col) ~= 0
1698 jline_matrix.set(row-1, col-1, matrix(row, col));
1699 end
1700 end
1701 end
1702 end
1703
1704 function lsn = from_jline_struct_layered(jlayerednetwork, jlsn)
1705 lsn = LayeredNetworkStruct();
1706 lsn.nidx= jlsn.nidx;
1707 lsn.nhosts= jlsn.nhosts;
1708 lsn.ntasks= jlsn.ntasks;
1709 lsn.nentries= jlsn.nentries;
1710 lsn.nacts= jlsn.nacts;
1711 lsn.ncalls= jlsn.ncalls;
1712 lsn.hshift= jlsn.hshift;
1713 lsn.tshift= jlsn.tshift;
1714 lsn.eshift= jlsn.eshift;
1715 lsn.ashift= jlsn.ashift;
1716 lsn.cshift= jlsn.cshift;
1717 for h=1:jlsn.nhosts
1718 lsn.tasksof{h,1} = JLINE.arraylist_to_matrix(jlsn.tasksof.get(uint32(h)))';
1719 end
1720 for t=1:jlsn.ntasks
1721 lsn.entriesof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.entriesof.get(uint32(jlsn.tshift+t)))';
1722 end
1723 for t=1:(jlsn.ntasks+jlsn.nentries)
1724 lsn.actsof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.actsof.get(uint32(jlsn.tshift+t)))';
1725 end
1726 for a=1:jlsn.nacts
1727 lsn.callsof{lsn.ashift+a,1} = JLINE.arraylist_to_matrix(jlsn.callsof.get(uint32(jlsn.ashift+a)))';
1728 end
1729 for i = 1:jlsn.sched.size
1730 lsn.sched(i,1) = SchedStrategy.(char(jlsn.sched.get(uint32(i))));
1731 end
1732 for i = 1:jlsn.names.size
1733 lsn.names{i,1} = jlsn.names.get(uint32(i));
1734 lsn.hashnames{i,1} = jlsn.hashnames.get(uint32(i));
1735 end
1736 lsn.mult = JLINE.from_jline_matrix(jlsn.mult);
1737 lsn.mult = lsn.mult(2:(lsn.eshift+1))'; % remove 0-padding
1738 lsn.maxmult = JLINE.from_jline_matrix(jlsn.maxmult);
1739 lsn.maxmult = lsn.maxmult(2:(lsn.eshift+1))'; % remove 0-padding
1740
1741 lsn.repl = JLINE.from_jline_matrix(jlsn.repl)';
1742 lsn.repl = lsn.repl(2:end); % remove 0-padding
1743 lsn.type = JLINE.from_jline_matrix(jlsn.type)';
1744 lsn.type = lsn.type(2:end); % remove 0-padding
1745 lsn.parent = JLINE.from_jline_matrix(jlsn.parent);
1746 lsn.parent = lsn.parent(2:end); % remove 0-padding
1747 lsn.nitems = JLINE.from_jline_matrix(jlsn.nitems);
1748 % Ensure proper column vector format matching MATLAB's (nhosts+ntasks+nentries) x 1
1749 if isrow(lsn.nitems)
1750 lsn.nitems = lsn.nitems(2:end)'; % remove 0-padding and transpose
1751 else
1752 lsn.nitems = lsn.nitems(2:end); % remove 0-padding (already column)
1753 end
1754 % Ensure correct size
1755 expectedSize = lsn.nhosts + lsn.ntasks + lsn.nentries;
1756 if length(lsn.nitems) < expectedSize
1757 lsn.nitems(expectedSize,1) = 0;
1758 elseif length(lsn.nitems) > expectedSize
1759 lsn.nitems = lsn.nitems(1:expectedSize);
1760 end
1761 lsn.replacestrat = JLINE.from_jline_matrix(jlsn.replacestrat);
1762 lsn.replacestrat = lsn.replacestrat(2:end)'; % remove 0-padding
1763 for i = 1:jlsn.callnames.size
1764 lsn.callnames{i,1} = jlsn.callnames.get(uint32(i));
1765 lsn.callhashnames{i,1} = jlsn.callhashnames.get(uint32(i));
1766 end
1767 for i = 1:jlsn.calltype.size % calltype may be made into a matrix in Java
1768 ct = char(jlsn.calltype.get(uint32(i)));
1769 lsn.calltype(i) = CallType.(ct);
1770 end
1771 lsn.calltype = sparse(lsn.calltype'); % remove 0-padding
1772 lsn.callpair = JLINE.from_jline_matrix(jlsn.callpair);
1773 lsn.callpair = lsn.callpair(2:end,2:end); % remove 0-paddings
1774 if isempty(lsn.callpair)
1775 lsn.callpair=[];
1776 end
1777 lsn.actpretype = sparse(JLINE.from_jline_matrix(jlsn.actpretype)');
1778 lsn.actpretype = lsn.actpretype(2:end); % remove 0-padding
1779 lsn.actposttype = sparse(JLINE.from_jline_matrix(jlsn.actposttype)');
1780 lsn.actposttype = lsn.actposttype(2:end); % remove 0-padding
1781 lsn.graph = JLINE.from_jline_matrix(jlsn.graph);
1782 lsn.graph = lsn.graph(2:end,2:end); % remove 0-paddings
1783 lsn.dag = JLINE.from_jline_matrix(jlsn.dag);
1784 lsn.dag = lsn.dag(2:end,2:end); % remove 0-paddings
1785 lsn.taskgraph = JLINE.from_jline_matrix(jlsn.taskgraph);
1786 lsn.taskgraph = sparse(lsn.taskgraph(2:end,2:end)); % remove 0-paddings
1787 lsn.replygraph = JLINE.from_jline_matrix(jlsn.replygraph);
1788 lsn.replygraph = logical(lsn.replygraph(2:end,2:end)); % remove 0-paddings
1789 lsn.iscache = JLINE.from_jline_matrix(jlsn.iscache);
1790 % Ensure proper column vector format matching MATLAB's (nhosts+ntasks) x 1
1791 expectedCacheSize = lsn.nhosts + lsn.ntasks;
1792 if isrow(lsn.iscache)
1793 if length(lsn.iscache) > expectedCacheSize
1794 lsn.iscache = lsn.iscache(2:(expectedCacheSize+1))'; % remove 0-padding and transpose
1795 else
1796 lsn.iscache = lsn.iscache'; % just transpose
1797 end
1798 end
1799 % Ensure correct size
1800 if length(lsn.iscache) < expectedCacheSize
1801 lsn.iscache(expectedCacheSize,1) = 0;
1802 elseif length(lsn.iscache) > expectedCacheSize
1803 lsn.iscache = lsn.iscache(1:expectedCacheSize);
1804 end
1805 lsn.iscaller = JLINE.from_jline_matrix(jlsn.iscaller);
1806 lsn.iscaller = full(lsn.iscaller(2:end,2:end)); % remove 0-paddings
1807 lsn.issynccaller = JLINE.from_jline_matrix(jlsn.issynccaller);
1808 lsn.issynccaller = full(lsn.issynccaller(2:end,2:end)); % remove 0-paddings
1809 lsn.isasynccaller = JLINE.from_jline_matrix(jlsn.isasynccaller);
1810 lsn.isasynccaller = full(lsn.isasynccaller(2:end,2:end)); % remove 0-paddings
1811 lsn.isref = JLINE.from_jline_matrix(jlsn.isref);
1812 lsn.isref = lsn.isref(2:end)'; % remove 0-paddings
1813 end
1814
1815 function sn = from_jline_struct(jnetwork, jsn)
1816 %lst and rtfun are not implemented
1817 %Due to the transformation of Java lambda to matlab function
1818 if nargin<2
1819 jsn = jnetwork.getStruct(false);
1820 end
1821 jclasses = jnetwork.getClasses();
1822 jnodes = jnetwork.getNodes();
1823 jstateful = jnetwork.getStatefulNodes();
1824 jstations = jnetwork.getStations();
1825 sn = NetworkStruct();
1826
1827 sn.nnodes = jsn.nnodes;
1828 sn.nclasses = jsn.nclasses;
1829 sn.nclosedjobs = jsn.nclosedjobs;
1830 sn.nstations = jsn.nstations;
1831 sn.nstateful = jsn.nstateful;
1832 sn.nchains = jsn.nchains;
1833
1834 sn.refstat = JLINE.from_jline_matrix(jsn.refstat) + 1;
1835 sn.njobs = JLINE.from_jline_matrix(jsn.njobs);
1836 sn.nservers = JLINE.from_jline_matrix(jsn.nservers);
1837 sn.connmatrix = JLINE.from_jline_matrix(jsn.connmatrix);
1838 % Fix for Java getConnectionMatrix bug: ensure connmatrix is nnodes x nnodes
1839 if size(sn.connmatrix,1) < sn.nnodes
1840 sn.connmatrix(sn.nnodes,1) = 0;
1841 end
1842 if size(sn.connmatrix,2) < sn.nnodes
1843 sn.connmatrix(1,sn.nnodes) = 0;
1844 end
1845 sn.scv = JLINE.from_jline_matrix(jsn.scv);
1846 sn.isstation = logical(JLINE.from_jline_matrix(jsn.isstation));
1847 sn.isstateful = logical(JLINE.from_jline_matrix(jsn.isstateful));
1848 sn.isstatedep = logical(JLINE.from_jline_matrix(jsn.isstatedep));
1849 sn.nodeToStateful = JLINE.from_jline_matrix(jsn.nodeToStateful)+1;
1850 sn.nodeToStateful(sn.nodeToStateful==0) = nan;
1851 sn.nodeToStation = JLINE.from_jline_matrix(jsn.nodeToStation)+1;
1852 sn.nodeToStation(sn.nodeToStation==0) = nan;
1853 sn.stationToNode = JLINE.from_jline_matrix(jsn.stationToNode)+1;
1854 sn.stationToNode(sn.stationToNode==0) = nan;
1855 sn.stationToStateful = JLINE.from_jline_matrix(jsn.stationToStateful)+1;
1856 sn.stationToStateful(sn.stationToStateful==0) = nan;
1857 sn.statefulToStation = JLINE.from_jline_matrix(jsn.statefulToStation)+1;
1858 sn.statefulToStation(sn.statefulToStation==0) = nan;
1859 sn.statefulToNode = JLINE.from_jline_matrix(jsn.statefulToNode)+1;
1860 sn.statefulToNode(sn.statefulToNode==0) = nan;
1861 sn.rates = JLINE.from_jline_matrix(jsn.rates);
1862 sn.fj = JLINE.from_jline_matrix(jsn.fj);
1863 sn.classprio = JLINE.from_jline_matrix(jsn.classprio);
1864 sn.phases = JLINE.from_jline_matrix(jsn.phases);
1865 sn.phasessz = JLINE.from_jline_matrix(jsn.phasessz);
1866 sn.phaseshift = JLINE.from_jline_matrix(jsn.phaseshift);
1867 sn.schedparam = JLINE.from_jline_matrix(jsn.schedparam);
1868 sn.chains = logical(JLINE.from_jline_matrix(jsn.chains));
1869 sn.rt = JLINE.from_jline_matrix(jsn.rt);
1870 sn.nvars = JLINE.from_jline_matrix(jsn.nvars);
1871 sn.rtnodes = JLINE.from_jline_matrix(jsn.rtnodes);
1872 sn.csmask = logical(JLINE.from_jline_matrix(jsn.csmask));
1873 sn.isslc = logical(JLINE.from_jline_matrix(jsn.isslc));
1874 sn.cap = JLINE.from_jline_matrix(jsn.cap);
1875 sn.classcap = JLINE.from_jline_matrix(jsn.classcap);
1876 sn.refclass = JLINE.from_jline_matrix(jsn.refclass)+1;
1877 sn.lldscaling = JLINE.from_jline_matrix(jsn.lldscaling);
1878
1879 if ~isempty(jsn.cdscaling) && jsn.cdscaling.size() > 0
1880 % Convert Java SerializableFunction to MATLAB function handles
1881 sn.cdscaling = cell(sn.nstations, 1);
1882 % Iterate through the map entries to handle null values properly
1883 entrySet = jsn.cdscaling.entrySet();
1884 entryIter = entrySet.iterator();
1885 stationFunMap = containers.Map();
1886 while entryIter.hasNext()
1887 entry = entryIter.next();
1888 stationName = char(entry.getKey().getName());
1889 try
1890 jfun = entry.getValue();
1891 if ~isempty(jfun)
1892 stationFunMap(stationName) = jfun;
1893 end
1894 catch
1895 % getValue() returns null for default lambda functions
1896 % Skip and use default value
1897 end
1898 end
1899 % Assign functions to stations
1900 for i = 1:sn.nstations
1901 jstation = jstations.get(i-1);
1902 stationName = char(jstation.getName());
1903 if isKey(stationFunMap, stationName)
1904 jfun = stationFunMap(stationName);
1905 % Create a MATLAB function handle that calls the Java apply() method
1906 sn.cdscaling{i} = @(ni) JLINE.call_java_cdscaling(jfun, ni);
1907 else
1908 sn.cdscaling{i} = @(ni) 1;
1909 end
1910 end
1911 else
1912 sn.cdscaling = cell(sn.nstations, 0);
1913 end
1914
1915 if ~isempty(jsn.nodetype)
1916 sn.nodetype = zeros(sn.nnodes, 1);
1917 for i = 1:jsn.nodetype.size
1918 nodetype = jsn.nodetype.get(i-1);
1919 switch nodetype.name().toCharArray'
1920 case 'Queue'
1921 sn.nodetype(i) = NodeType.Queue;
1922 case 'Delay'
1923 sn.nodetype(i) = NodeType.Delay;
1924 case 'Source'
1925 sn.nodetype(i) = NodeType.Source;
1926 case 'Sink'
1927 sn.nodetype(i) = NodeType.Sink;
1928 case 'Join'
1929 sn.nodetype(i) = NodeType.Join;
1930 case 'Fork'
1931 sn.nodetype(i) = NodeType.Fork;
1932 case 'ClassSwitch'
1933 sn.nodetype(i) = NodeType.ClassSwitch;
1934 case 'Logger'
1935 sn.nodetype(i) = NodeType.Logger;
1936 case 'Cache'
1937 sn.nodetype(i) = NodeType.Cache;
1938 case 'Place'
1939 sn.nodetype(i) = NodeType.Place;
1940 case 'Transition'
1941 sn.nodetype(i) = NodeType.Transition;
1942 case 'Router'
1943 sn.nodetype(i) = NodeType.Router;
1944 end
1945 end
1946 else
1947 sn.nodetype = [];
1948 end
1949
1950 if ~isempty(jsn.classnames)
1951 for i = 1:jsn.classnames.size
1952 sn.classnames(i,1) = jsn.classnames.get(i-1);
1953 end
1954 else
1955 sn.classnames = [];
1956 end
1957
1958 if ~isempty(jsn.nodenames)
1959 for i = 1:jsn.nodenames.size
1960 sn.nodenames(i,1) = jsn.nodenames.get(i-1);
1961 end
1962 else
1963 sn.nodenames = [];
1964 end
1965
1966 if ~isempty(jsn.rtorig) && jsn.rtorig.size()>0
1967 sn.rtorig = cell(sn.nclasses, sn.nclasses);
1968 for r = 1:sn.nclasses
1969 for s = 1:sn.nclasses
1970 sn.rtorig{r,s} = JLINE.from_jline_matrix(jsn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1971 end
1972 end
1973 else
1974 sn.rtorig = {};
1975 end
1976
1977 if ~isempty(jsn.state)
1978 sn.state = cell(sn.nstateful, 1);
1979 for i = 1:sn.nstateful
1980 sn.state{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getState());
1981 end
1982 else
1983 sn.state = {};
1984 end
1985
1986 if ~isempty(jsn.stateprior)
1987 sn.stateprior = cell(sn.nstateful, 1);
1988 for i = 1:sn.nstateful
1989 sn.stateprior{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStatePrior());
1990 end
1991 else
1992 sn.stateprior = {};
1993 end
1994
1995 if ~isempty(jsn.space)
1996 sn.space = cell(sn.nstateful, 1);
1997 for i = 1:sn.nstateful
1998 sn.space{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStateSpace());
1999 end
2000 else
2001 sn.space = {};
2002 end
2003
2004 if ~isempty(jsn.routing)
2005 sn.routing = zeros(sn.nnodes, sn.nclasses);
2006 for i = 1:sn.nnodes
2007 for j = 1:sn.nclasses
2008 routingStrategy = jsn.routing.get(jnodes.get(i-1)).get(jclasses.get(j-1));
2009 switch routingStrategy.name().toCharArray'
2010 case 'PROB'
2011 sn.routing(i,j) = RoutingStrategy.PROB;
2012 case 'RAND'
2013 sn.routing(i,j) = RoutingStrategy.RAND;
2014 case 'RROBIN'
2015 sn.routing(i,j) = RoutingStrategy.RROBIN;
2016 case 'WRROBIN'
2017 sn.routing(i,j) = RoutingStrategy.WRROBIN;
2018 case 'JSQ'
2019 sn.routing(i,j) = RoutingStrategy.JSQ;
2020 case 'DISABLED'
2021 sn.routing(i,j) = RoutingStrategy.DISABLED;
2022 case 'FIRING'
2023 sn.routing(i,j) = RoutingStrategy.FIRING;
2024 case 'KCHOICES'
2025 sn.routing(i,j) = RoutingStrategy.KCHOICES;
2026 end
2027 end
2028 end
2029 else
2030 sn.routing = [];
2031 end
2032
2033 if ~isempty(jsn.procid)
2034 sn.procid = nan(sn.nstations, sn.nclasses); % Initialize with NaN to match MATLAB behavior
2035 for i = 1:sn.nstations
2036 for j = 1:sn.nclasses
2037 stationMap = jsn.procid.get(jstations.get(i-1));
2038 if isempty(stationMap)
2039 sn.procid(i,j) = ProcessType.DISABLED;
2040 continue;
2041 end
2042 processType = stationMap.get(jclasses.get(j-1));
2043 if isempty(processType)
2044 sn.procid(i,j) = ProcessType.DISABLED;
2045 continue;
2046 end
2047 switch processType.name.toCharArray'
2048 case 'EXP'
2049 sn.procid(i,j) = ProcessType.EXP;
2050 case 'ERLANG'
2051 sn.procid(i,j) = ProcessType.ERLANG;
2052 case 'HYPEREXP'
2053 sn.procid(i,j) = ProcessType.HYPEREXP;
2054 case 'PH'
2055 sn.procid(i,j) = ProcessType.PH;
2056 case 'APH'
2057 sn.procid(i,j) = ProcessType.APH;
2058 case 'MAP'
2059 sn.procid(i,j) = ProcessType.MAP;
2060 case 'UNIFORM'
2061 sn.procid(i,j) = ProcessType.UNIFORM;
2062 case 'DET'
2063 sn.procid(i,j) = ProcessType.DET;
2064 case 'COXIAN'
2065 sn.procid(i,j) = ProcessType.COXIAN;
2066 case 'GAMMA'
2067 sn.procid(i,j) = ProcessType.GAMMA;
2068 case 'PARETO'
2069 sn.procid(i,j) = ProcessType.PARETO;
2070 case 'WEIBULL'
2071 sn.procid(i,j) = ProcessType.WEIBULL;
2072 case 'LOGNORMAL'
2073 sn.procid(i,j) = ProcessType.LOGNORMAL;
2074 case 'MMPP2'
2075 sn.procid(i,j) = ProcessType.MMPP2;
2076 case 'REPLAYER'
2077 sn.procid(i,j) = ProcessType.REPLAYER;
2078 case 'TRACE'
2079 sn.procid(i,j) = ProcessType.TRACE;
2080 case 'IMMEDIATE'
2081 sn.procid(i,j) = ProcessType.IMMEDIATE;
2082 case 'DISABLED'
2083 sn.procid(i,j) = ProcessType.DISABLED;
2084 case 'COX2'
2085 sn.procid(i,j) = ProcessType.COX2;
2086 case 'BMAP'
2087 sn.procid(i,j) = ProcessType.BMAP;
2088 case 'ME'
2089 sn.procid(i,j) = ProcessType.ME;
2090 case 'RAP'
2091 sn.procid(i,j) = ProcessType.RAP;
2092 case 'BINOMIAL'
2093 sn.procid(i,j) = ProcessType.BINOMIAL;
2094 case 'POISSON'
2095 sn.procid(i,j) = ProcessType.POISSON;
2096 case 'GEOMETRIC'
2097 sn.procid(i,j) = ProcessType.GEOMETRIC;
2098 case 'DUNIFORM'
2099 sn.procid(i,j) = ProcessType.DUNIFORM;
2100 case 'BERNOULLI'
2101 sn.procid(i,j) = ProcessType.BERNOULLI;
2102 case 'PRIOR'
2103 sn.procid(i,j) = ProcessType.PRIOR;
2104 otherwise
2105 % Unknown ProcessType - default to DISABLED
2106 sn.procid(i,j) = ProcessType.DISABLED;
2107 end
2108 end
2109 end
2110 else
2111 sn.procid = [];
2112 end
2113
2114 if ~isempty(jsn.mu)
2115 sn.mu = cell(sn.nstations, 1);
2116 for i = 1:sn.nstations
2117 sn.mu{i} = cell(1, sn.nclasses);
2118 for j = 1:sn.nclasses
2119 sn.mu{i}{j} = JLINE.from_jline_matrix(jsn.mu.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2120 end
2121 end
2122 else
2123 sn.mu = {};
2124 end
2125
2126 if ~isempty(jsn.phi)
2127 sn.phi = cell(sn.nstations, 1);
2128 for i = 1:sn.nstations
2129 sn.phi{i} = cell(1, sn.nclasses);
2130 for j = 1:sn.nclasses
2131 sn.phi{i}{j} = JLINE.from_jline_matrix(jsn.phi.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2132 end
2133 end
2134 else
2135 sn.phi = {};
2136 end
2137
2138 if ~isempty(jsn.proc)
2139 sn.proc = cell(sn.nstations, 1);
2140 for i = 1:sn.nstations
2141 sn.proc{i} = cell(1, sn.nclasses);
2142 for j = 1:sn.nclasses
2143 proc_i_j = jsn.proc.get(jstations.get(i-1)).get(jclasses.get(j-1));
2144 sn.proc{i}{j} = cell(1, proc_i_j.size);
2145 for k = 1:proc_i_j.size
2146 sn.proc{i}{j}{k} = JLINE.from_jline_matrix(proc_i_j.get(uint32(k-1)));
2147 end
2148 end
2149 end
2150 else
2151 sn.proc = {};
2152 end
2153
2154 if ~isempty(jsn.pie)
2155 sn.pie = cell(sn.nstations, 1);
2156 for i = 1:sn.nstations
2157 sn.pie{i} = cell(1, sn.nclasses);
2158 for j = 1:sn.nclasses
2159 sn.pie{i}{j} = JLINE.from_jline_matrix(jsn.pie.get(jstations.get(i-1)).get(jclasses.get(j-1)));
2160 end
2161 end
2162 else
2163 sn.pie = {};
2164 end
2165
2166 if ~isempty(jsn.sched)
2167 sn.sched = zeros(sn.nstations, 1);
2168 for i = 1:sn.nstations
2169 schedStrategy = jsn.sched.get(jstations.get(i-1));
2170 switch schedStrategy.name.toCharArray'
2171 case 'INF'
2172 sn.sched(i) = SchedStrategy.INF;
2173 case 'FCFS'
2174 sn.sched(i) = SchedStrategy.FCFS;
2175 case 'LCFS'
2176 sn.sched(i) = SchedStrategy.LCFS;
2177 case 'LCFSPR'
2178 sn.sched(i) = SchedStrategy.LCFSPR;
2179 case 'SIRO'
2180 sn.sched(i) = SchedStrategy.SIRO;
2181 case 'SJF'
2182 sn.sched(i) = SchedStrategy.SJF;
2183 case 'LJF'
2184 sn.sched(i) = SchedStrategy.LJF;
2185 case 'PS'
2186 sn.sched(i) = SchedStrategy.PS;
2187 case 'DPS'
2188 sn.sched(i) = SchedStrategy.DPS;
2189 case 'GPS'
2190 sn.sched(i) = SchedStrategy.GPS;
2191 case 'PSPRIO'
2192 sn.sched(i) = SchedStrategy.PSPRIO;
2193 case 'DPSPRIO'
2194 sn.sched(i) = SchedStrategy.DPSPRIO;
2195 case 'GPSPRIO'
2196 sn.sched(i) = SchedStrategy.GPSPRIO;
2197 case 'SEPT'
2198 sn.sched(i) = SchedStrategy.SEPT;
2199 case 'LEPT'
2200 sn.sched(i) = SchedStrategy.LEPT;
2201 case {'HOL', 'FCFSPRIO'}
2202 sn.sched(i) = SchedStrategy.FCFSPRIO;
2203 case 'FORK'
2204 sn.sched(i) = SchedStrategy.FORK;
2205 case 'EXT'
2206 sn.sched(i) = SchedStrategy.EXT;
2207 case 'REF'
2208 sn.sched(i) = SchedStrategy.REF;
2209 end
2210 end
2211 else
2212 sn.sched = [];
2213 end
2214
2215 if ~isempty(jsn.inchain)
2216 sn.inchain = cell(1, sn.nchains);
2217 for i = 1:sn.nchains
2218 sn.inchain{1,i} = JLINE.from_jline_matrix(jsn.inchain.get(uint32(i-1)))+1;
2219 end
2220 else
2221 sn.inchain = {};
2222 end
2223
2224 if ~isempty(jsn.visits)
2225 sn.visits = cell(sn.nchains, 1);
2226 for i = 1:sn.nchains
2227 sn.visits{i,1} = JLINE.from_jline_matrix(jsn.visits.get(uint32(i-1)));
2228 end
2229 else
2230 sn.visits = {};
2231 end
2232
2233 if ~isempty(jsn.nodevisits)
2234 sn.nodevisits = cell(1, sn.nchains);
2235 for i = 1:sn.nchains
2236 sn.nodevisits{1,i} = JLINE.from_jline_matrix(jsn.nodevisits.get(uint32(i-1)));
2237 end
2238 else
2239 sn.nodevisits = {};
2240 end
2241
2242 if ~isempty(jsn.droprule)
2243 sn.droprule = zeros(sn.nstations, sn.nclasses);
2244 for i = 1:sn.nstations
2245 for j = 1:sn.nclasses
2246 dropStrategy = jsn.droprule.get(jstations.get(i-1)).get(jclasses.get(j-1));
2247 switch dropStrategy.name.toCharArray'
2248 case 'WaitingQueue'
2249 sn.droprule(i,j) = DropStrategy.WAITQ;
2250 case 'Drop'
2251 sn.droprule(i,j) = DropStrategy.DROP;
2252 case 'BlockingAfterService'
2253 sn.droprule(i,j) = DropStrategy.BAS;
2254 end
2255 end
2256 end
2257 else
2258 sn.droprule = [];
2259 end
2260
2261 if ~isempty(jsn.nodeparam)
2262 sn.nodeparam = cell(sn.nnodes, 1);
2263
2264 for i = 1:sn.nnodes
2265 jnode = jnodes.get(i-1);
2266 jparam = jsn.nodeparam.get(jnode);
2267
2268 %if jparam.isEmpty
2269 % sn.nodeparam{i} = [];
2270 % continue;
2271 %end
2272
2273 % StationNodeParam
2274 if isa(jparam, 'jline.lang.nodeparam.StationNodeParam')
2275 if ~isempty(jparam.fileName)
2276 sn.nodeparam{i}.fileName = cell(1, sn.nclasses);
2277 for r = 1:sn.nclasses
2278 fname = jparam.fileName.get(r-1);
2279 if ~isempty(fname)
2280 sn.nodeparam{i}.fileName{r} = char(fname);
2281 end
2282 end
2283 end
2284 end
2285
2286 % TransitionNodeParam
2287 if isa(jparam, 'jline.lang.nodeparam.TransitionNodeParam')
2288 if ~isempty(jparam.firingprocid)
2289 sn.nodeparam{i}.firingprocid = containers.Map('KeyType', 'char', 'ValueType', 'any');
2290 keys = jparam.firingprocid.keySet.iterator;
2291 while keys.hasNext
2292 key = keys.next;
2293 proc = jparam.firingprocid.get(key);
2294 sn.nodeparam{i}.firingprocid(char(key.toString)) = char(proc.toString);
2295 end
2296 end
2297 if ~isempty(jparam.firingphases)
2298 sn.nodeparam{i}.firingphases = JLINE.from_jline_matrix(jparam.firingphases);
2299 end
2300 if ~isempty(jparam.fireweight)
2301 sn.nodeparam{i}.fireweight = JLINE.from_jline_matrix(jparam.fireweight);
2302 end
2303 end
2304
2305 % JoinNodeParam
2306 if isa(jparam, 'jline.lang.nodeparam.JoinNodeParam')
2307 if ~isempty(jparam.joinStrategy)
2308 sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
2309 sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
2310 for r = 1:sn.nclasses
2311 jclass = jclasses.get(r-1);
2312 joinStrategy = jparam.joinStrategy.get(jclass);
2313 if ~isempty(joinStrategy)
2314 strategyStr = char(joinStrategy.name.toString);
2315 switch strategyStr
2316 case 'STD'
2317 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
2318 case 'PARTIAL'
2319 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
2320 otherwise
2321 sn.nodeparam{i}.joinStrategy{r} = strategyStr;
2322 end
2323 sn.nodeparam{i}.fanIn{r} = jparam.fanIn.get(jclass);
2324 end
2325 end
2326 end
2327 end
2328
2329 % RoutingNodeParam
2330 if isa(jparam, 'jline.lang.nodeparam.RoutingNodeParam')
2331 for r = 1:sn.nclasses
2332 jclass = jclasses.get(r-1);
2333
2334 if ~isempty(jparam.weights) && jparam.weights.containsKey(jclass)
2335 sn.nodeparam{i}.weights{r} = JLINE.from_jline_matrix(jparam.weights.get(jclass));
2336 end
2337
2338 if ~isempty(jparam.outlinks) && jparam.outlinks.containsKey(jclass)
2339 sn.nodeparam{i}.outlinks{r} = JLINE.from_jline_matrix(jparam.outlinks.get(jclass));
2340 end
2341 end
2342 end
2343
2344 % ForkNodeParam
2345 if isa(jparam, 'jline.lang.nodeparam.ForkNodeParam')
2346 if ~isnan(jparam.fanOut)
2347 sn.nodeparam{i}.fanOut = jparam.fanOut;
2348 end
2349 end
2350
2351 % CacheNodeParam
2352 if isa(jparam, 'jline.lang.nodeparam.CacheNodeParam')
2353 % nitems
2354 if ~isnan(jparam.nitems)
2355 sn.nodeparam{i}.nitems = jparam.nitems;
2356 end
2357
2358 % accost
2359 if ~isempty(jparam.accost)
2360 % For Java 2D arrays (Matrix[][]), size(arr,2) returns 1 in MATLAB
2361 % We need to get length of first row to get actual second dimension
2362 K1 = size(jparam.accost, 1);
2363 if K1 > 0
2364 firstRow = jparam.accost(1); % Get first row (Java array)
2365 K2 = length(firstRow);
2366 else
2367 K2 = 0;
2368 end
2369 sn.nodeparam{i}.accost = cell(K1, K2);
2370 for k1 = 1:K1
2371 for k2 = 1:K2
2372 mat = jparam.accost(k1, k2); % MATLAB handles Java array indexing
2373 if ~isempty(mat)
2374 sn.nodeparam{i}.accost{k1, k2} = JLINE.from_jline_matrix(mat);
2375 end
2376 end
2377 end
2378 end
2379
2380 % itemcap
2381 if ~isempty(jparam.itemcap)
2382 sn.nodeparam{i}.itemcap = JLINE.from_jline_matrix(jparam.itemcap);
2383 end
2384
2385 % pread - convert from Java Map<Integer, List<Double>> to MATLAB cell array {R}
2386 if ~isempty(jparam.pread)
2387 nclasses = sn.nclasses;
2388 sn.nodeparam{i}.pread = cell(1, nclasses);
2389 for r = 1:nclasses
2390 list = jparam.pread.get(int32(r-1)); % Java 0-based indexing
2391 if ~isempty(list)
2392 values = zeros(1, list.size);
2393 for j = 1:list.size
2394 values(j) = list.get(j-1);
2395 end
2396 sn.nodeparam{i}.pread{r} = values;
2397 else
2398 sn.nodeparam{i}.pread{r} = NaN;
2399 end
2400 end
2401 end
2402
2403 % replacestrat
2404 if ~isempty(jparam.replacestrat)
2405 switch char(jparam.replacestrat)
2406 case 'RR'
2407 sn.nodeparam{i}.replacestrat = ReplacementStrategy.RR;
2408 case 'FIFO'
2409 sn.nodeparam{i}.replacestrat = ReplacementStrategy.FIFO;
2410 case 'SFIFO'
2411 sn.nodeparam{i}.replacestrat = ReplacementStrategy.SFIFO;
2412 case 'LRU'
2413 sn.nodeparam{i}.replacestrat = ReplacementStrategy.LRU;
2414 end
2415 end
2416
2417 % hitclass
2418 if ~isempty(jparam.hitclass)
2419 sn.nodeparam{i}.hitclass = 1+JLINE.from_jline_matrix(jparam.hitclass);
2420 end
2421
2422 % missclass
2423 if ~isempty(jparam.missclass)
2424 sn.nodeparam{i}.missclass =1+ JLINE.from_jline_matrix(jparam.missclass);
2425 end
2426
2427 % actual hit/miss probabilities
2428 if ~isempty(jparam.actualhitprob)
2429 sn.nodeparam{i}.actualhitprob = JLINE.from_jline_matrix(jparam.actualhitprob);
2430 end
2431 if ~isempty(jparam.actualmissprob)
2432 sn.nodeparam{i}.actualmissprob = JLINE.from_jline_matrix(jparam.actualmissprob);
2433 end
2434 end
2435 end
2436 else
2437 sn.nodeparam = {};
2438 end
2439
2440 % if ~isempty(jsn.nodeparam)
2441 % sn.nodeparam = cell(sn.nnodes, 1);
2442 % % Note that JLINE only support node parameters related to
2443 % % Fork, Join, WWROBIN and RROBIN
2444 % for i = 1:sn.nnodes
2445 % if jsn.nodeparam.get(jnodes.get(i-1)).isEmpty
2446 % sn.nodeparam{i} = [];
2447 % else
2448 % if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).nitems)
2449 % sn.nodeparam{i}.nitems = jsn.nodeparam.get(jnodes.get(i-1)).nitems;
2450 % end
2451 % if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).fanOut)
2452 % sn.nodeparam{i}.fanOut = jsn.nodeparam.get(jnodes.get(i-1)).fanOut;
2453 % end
2454 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy)
2455 % if ~jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.isEmpty
2456 % sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
2457 % sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
2458 % for r = 1:sn.nclasses
2459 % joinStrategy = jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.get(jclasses.get(r-1));
2460 % switch joinStrategy.name.toCharArray'
2461 % case 'STD'
2462 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
2463 % case 'PARTIAL'
2464 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
2465 % end
2466 % sn.nodeparam{i}.fanIn{r} = jsn.nodeparam.get(jnodes.get(i-1)).fanIn.get(jclasses.get(r-1));
2467 % end
2468 % end
2469 % end
2470 %
2471 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).weights)
2472 % for r = 1:sn.nclasses
2473 % sn.nodeparam{i}{r}.weights = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).weights.get(jclasses.get(r-1)));
2474 % end
2475 % end
2476 %
2477 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).outlinks)
2478 % for r = 1:sn.nclasses
2479 % sn.nodeparam{i}{r}.outlinks = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).outlinks.get(jclasses.get(r-1)));
2480 % end
2481 % end
2482 % end
2483 % end
2484 % else
2485 % sn.nodeparam = {};
2486 % end
2487
2488 if ~isempty(jsn.sync)
2489 jsync = jsn.sync;
2490 sn.sync = cell(jsync.size, 1);
2491 for i = 1:jsync.size
2492 jsync_i = jsync.get(uint32(i-1));
2493 sn.sync{i,1} = struct('active',cell(1),'passive',cell(1));
2494
2495 jactive = jsync_i.active.get(uint32(0));
2496 jpassive = jsync_i.passive.get(uint32(0));
2497
2498 %Currently assume that prob would always be a value
2499 %instead of lambda function (No idea of how to convert
2500 %Java lambda function to matlab lambda function)
2501 switch jactive.getEvent.name.toCharArray'
2502 case 'INIT'
2503 sn.sync{i,1}.active{1} = Event(EventType.INIT, jactive.getNode+1, jactive.getJobClass+1, ...
2504 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2505 jactive.getT, jactive.getJob);
2506 case 'LOCAL'
2507 sn.sync{i,1}.active{1} = Event(EventType.LOCAL, jactive.getNode+1, jactive.getJobClass+1, ...
2508 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2509 jactive.getT, jactive.getJob);
2510 case 'ARV'
2511 sn.sync{i,1}.active{1} = Event(EventType.ARV, jactive.getNode+1, jactive.getJobClass+1, ...
2512 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2513 jactive.getT, jactive.getJob);
2514 case 'DEP'
2515 sn.sync{i,1}.active{1} = Event(EventType.DEP, jactive.getNode+1, jactive.getJobClass+1, ...
2516 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2517 jactive.getT, jactive.getJob);
2518 case 'PHASE'
2519 sn.sync{i,1}.active{1} = Event(EventType.PHASE, jactive.getNode+1, jactive.getJobClass+1, ...
2520 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2521 jactive.getT, jactive.getJob);
2522 case 'READ'
2523 sn.sync{i,1}.active{1} = Event(EventType.READ, jactive.getNode+1, jactive.getJobClass+1, ...
2524 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2525 jactive.getT, jactive.getJob);
2526 case 'STAGE'
2527 sn.sync{i,1}.active{1} = Event(EventType.STAGE, jactive.getNode+1, jactive.getJobClass+1, ...
2528 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
2529 jactive.getT, jactive.getJob);
2530 end
2531
2532 switch jpassive.getEvent.name.toCharArray'
2533 case 'INIT'
2534 sn.sync{i,1}.passive{1} = Event(EventType.INIT, jpassive.getNode+1, jpassive.getJobClass+1, ...
2535 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2536 jpassive.getT, jpassive.getJob);
2537 case 'LOCAL'
2538 sn.sync{i,1}.passive{1} = Event(EventType.LOCAL, jpassive.getNode+1, jpassive.getJobClass+1, ...
2539 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2540 jpassive.getT, jpassive.getJob);
2541 case 'ARV'
2542 sn.sync{i,1}.passive{1} = Event(EventType.ARV, jpassive.getNode+1, jpassive.getJobClass+1, ...
2543 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2544 jpassive.getT, jpassive.getJob);
2545 case 'DEP'
2546 sn.sync{i,1}.passive{1} = Event(EventType.DEP, jpassive.getNode+1, jpassive.getJobClass+1, ...
2547 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2548 jpassive.getT, jpassive.getJob);
2549 case 'PHASE'
2550 sn.sync{i,1}.passive{1} = Event(EventType.PHASE, jpassive.getNode+1, jpassive.getJobClass+1, ...
2551 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2552 jpassive.getT, jpassive.getJob);
2553 case 'READ'
2554 sn.sync{i,1}.passive{1} = Event(EventType.READ, jpassive.getNode+1, jpassive.getJobClass+1, ...
2555 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2556 jpassive.getT, jpassive.getJob);
2557 case 'STAGE'
2558 sn.sync{i,1}.passive{1} = Event(EventType.STAGE, jpassive.getNode+1, jpassive.getJobClass+1, ...
2559 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
2560 jpassive.getT, jpassive.getJob);
2561 end
2562 end
2563 else
2564 sn.sync = {};
2565 end
2566 end
2567
2568 function [QN,UN,RN,WN,AN,TN] = arrayListToResults(alist)
2569 switch class(alist)
2570 case 'jline.solvers.LayeredNetworkAvgTable'
2571 QN = JLINE.arraylist_to_matrix(alist.getQLen());
2572 UN = JLINE.arraylist_to_matrix(alist.getUtil());
2573 RN = JLINE.arraylist_to_matrix(alist.getRespT());
2574 WN = JLINE.arraylist_to_matrix(alist.getResidT());
2575 AN = NaN*JLINE.arraylist_to_matrix(alist.getTput()); % getArvR not yet available in JLINE
2576 TN = JLINE.arraylist_to_matrix(alist.getTput());
2577 otherwise
2578 QN = JLINE.arraylist_to_matrix(alist.getQLen());
2579 UN = JLINE.arraylist_to_matrix(alist.getUtil());
2580 RN = JLINE.arraylist_to_matrix(alist.getRespT());
2581 WN = JLINE.arraylist_to_matrix(alist.getResidT());
2582 AN = JLINE.arraylist_to_matrix(alist.getArvR());
2583 TN = JLINE.arraylist_to_matrix(alist.getTput());
2584 end
2585 end
2586
2587 function featSupported = getFeatureSet()
2588 % FEATSUPPORTED = GETFEATURESET()
2589
2590 featSupported = SolverFeatureSet;
2591 featSupported.setTrue({'Sink','Source',...
2592 'ClassSwitch','Delay','DelayStation','Queue',...
2593 'APH','Coxian','Erlang','Exp','HyperExp',...
2594 'StatelessClassSwitcher','InfiniteServer','SharedServer','Buffer','Dispatcher',...
2595 'Server','JobSink','RandomSource','ServiceTunnel',...
2596 'SchedStrategy_INF','SchedStrategy_PS',...
2597 'RoutingStrategy_PROB','RoutingStrategy_RAND',...
2598 'ClosedClass','OpenClass'});
2599 end
2600
2601 function [bool, featSupported] = supports(model)
2602 % [BOOL, FEATSUPPORTED] = SUPPORTS(MODEL)
2603
2604 featUsed = model.getUsedLangFeatures();
2605 featSupported = JLINE.getFeatureSet();
2606 bool = SolverFeatureSet.supports(featSupported, featUsed);
2607 end
2608
2609
2610 function solverOptions = parseSolverOptions(solverOptions, options)
2611 fn = fieldnames(options);
2612 fn2 = fieldnames(solverOptions);
2613 for f = 1:length(fn)
2614 found = 0;
2615 for j = 1:length(fn2)
2616 if strcmp(fn{f}, fn2{j})
2617 found = 1;
2618 switch fn{f}
2619 case 'seed'
2620 solverOptions.seed = options.seed;
2621 case 'samples'
2622 solverOptions.samples = options.samples;
2623 case 'confint'
2624 % Parse confint - can be a level (0.95) or 0 to disable
2625 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
2626 if confintEnabled
2627 solverOptions.confint = confintLevel;
2628 else
2629 solverOptions.confint = 0;
2630 end
2631 case 'method'
2632 solverOptions.method = options.method;
2633 case 'config'
2634 if isfield(options.config,'eventcache')
2635 solverOptions.config.eventcache = options.config.eventcache;
2636 end
2637 if isfield(options.config,'fork_join')
2638 solverOptions.config.fork_join = options.config.fork_join;
2639 end
2640 if isfield(options.config,'highvar')
2641 solverOptions.config.highvar = options.config.highvar;
2642 end
2643 if isfield(options.config,'multiserver')
2644 solverOptions.config.multiserver = options.config.multiserver;
2645 end
2646 if isfield(options.config,'np_priority')
2647 solverOptions.config.np_priority = options.config.np_priority;
2648 end
2649 case 'verbose'
2650 switch options.(fn{f})
2651 case {VerboseLevel.SILENT}
2652 solverOptions.verbose = solverOptions.verbose.SILENT;
2653 case {VerboseLevel.STD}
2654 solverOptions.verbose = solverOptions.verbose.STD;
2655 case {VerboseLevel.DEBUG}
2656 solverOptions.verbose = solverOptions.verbose.DEBUG;
2657 end
2658 case 'init_sol'
2659 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.init_sol);
2660 case 'cutoff'
2661 if isscalar(options.cutoff)
2662 solverOptions.(fn{f}) = jline.util.matrix.Matrix.singleton(options.cutoff);
2663 else
2664 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.cutoff);
2665 end
2666 case 'odesolvers'
2667 case 'rewardIterations'
2668 solverOptions.rewardIterations = java.lang.Integer(options.rewardIterations);
2669 otherwise
2670 solverOptions.(fn{f}) = options.(fn{f});
2671 end
2672
2673 break;
2674 end
2675 end
2676 if ~found
2677 line_printf('Could not find option %s in the JLINE options.\n', fn{f});
2678 end
2679 end
2680 end
2681
2682 function [ssa] = SolverSSA(network_object, options)
2683 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.SSA);
2684 if nargin>1
2685 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2686 end
2687 jline.util.Maths.setRandomNumbersMatlab(true);
2688 ssa = jline.solvers.ssa.SolverSSA(network_object, solverOptions);
2689 end
2690
2691 function [mam] = SolverMAM(network_object, options)
2692 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MAM);
2693 if nargin>1
2694 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2695 end
2696 mam = jline.solvers.mam.SolverMAM(network_object, solverOptions);
2697 end
2698
2699 function [jmt] = SolverJMT(network_object, options)
2700 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.JMT);
2701 if nargin>1
2702 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2703 end
2704 jmt = jline.solvers.jmt.SolverJMT(network_object, solverOptions);
2705 end
2706
2707 function [ctmc] = SolverCTMC(network_object, options)
2708 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.CTMC);
2709 if nargin>1
2710 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2711 end
2712 ctmc = jline.solvers.ctmc.SolverCTMC(network_object,solverOptions);
2713 end
2714
2715 function [fluid] = SolverFluid(network_object, options)
2716 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.FLUID);
2717 if nargin>1
2718 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2719 end
2720 fluid = jline.solvers.fluid.SolverFluid(network_object, solverOptions);
2721 end
2722
2723 function [QN, UN, RN, TN, CN, XN, t, QNt, UNt, TNt, xvec] = runFluidAnalyzer(network, options)
2724 % RUNFLUIDANALYZER Run JLINE fluid analyzer and return results
2725 %
2726 % [QN, UN, RN, TN, CN, XN, T, QNT, UNT, TNT, XVEC] = JLINE.runFluidAnalyzer(NETWORK, OPTIONS)
2727 %
2728 % Runs the JLINE fluid solver on the given network and converts
2729 % results back to MATLAB data structures.
2730 %
2731 % Input:
2732 % network - LINE Network model
2733 % options - Solver options structure with fields:
2734 % .method - solver method
2735 % .stiff - use stiff ODE solver
2736 %
2737 % Output:
2738 % QN, UN, RN, TN - Steady-state metrics [M x K]
2739 % CN, XN - System metrics [1 x K]
2740 % t - Time vector [Tmax x 1]
2741 % QNt, UNt, TNt - Transient metrics {M x K} cells
2742 % xvec - State vector structure
2743
2744 jmodel = LINE2JLINE(network);
2745 jsolver = JLINE.SolverFluid(jmodel);
2746 import jline.solvers.fluid.*;
2747
2748 jsolver.options.method = options.method;
2749 jsolver.options.stiff = options.stiff;
2750 result = jsolver.runMethodSpecificAnalyzerViaLINE();
2751
2752 % Convert JLINE result to MATLAB data structures
2753 M = jmodel.getNumberOfStatefulNodes();
2754 K = jmodel.getNumberOfClasses();
2755
2756 QN = NaN * zeros(M, K);
2757 UN = NaN * zeros(M, K);
2758 RN = NaN * zeros(M, K);
2759 TN = NaN * zeros(M, K);
2760 CN = NaN * zeros(1, K);
2761 XN = NaN * zeros(1, K);
2762
2763 QNt = cell(M, K);
2764 UNt = cell(M, K);
2765 TNt = cell(M, K);
2766
2767 Tmax = result.t.length();
2768 t = NaN * zeros(Tmax, 1);
2769
2770 for ist = 1:M
2771 for jst = 1:K
2772 QN(ist, jst) = result.QN.get(ist-1, jst-1);
2773 UN(ist, jst) = result.UN.get(ist-1, jst-1);
2774 RN(ist, jst) = result.RN.get(ist-1, jst-1);
2775 TN(ist, jst) = result.TN.get(ist-1, jst-1);
2776 end
2777 end
2778
2779 for jst = 1:K
2780 CN(1, jst) = result.CN.get(0, jst-1);
2781 XN(1, jst) = result.XN.get(0, jst-1);
2782 end
2783
2784 for ist = 1:M
2785 for jst = 1:K
2786 for p = 1:Tmax
2787 QNt{ist, jst}(p, 1) = result.QNt(ist, jst).get(p-1, 0);
2788 UNt{ist, jst}(p, 1) = result.UNt(ist, jst).get(p-1, 0);
2789 TNt{ist, jst}(p, 1) = result.TNt(ist, jst).get(p-1, 0);
2790 end
2791 end
2792 end
2793
2794 for p = 1:Tmax
2795 t(p, 1) = result.t.get(p-1, 0);
2796 end
2797
2798 % JLINE does not return odeStateVec
2799 xvec.odeStateVec = [];
2800 xvec.sn = network;
2801 end
2802
2803 function [des] = SolverDES(network_object, options)
2804 % Create DES-specific options object
2805 desOptions = jline.solvers.des.DESOptions();
2806 if nargin>1
2807 % Copy standard options
2808 desOptions.samples = options.samples;
2809 desOptions.seed = options.seed;
2810 % Parse confint
2811 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
2812 if confintEnabled
2813 desOptions.confint = confintLevel;
2814 else
2815 desOptions.confint = 0;
2816 end
2817 % Pass timespan for transient analysis
2818 if isfield(options, 'timespan') && length(options.timespan) >= 2
2819 desOptions.timespan = options.timespan;
2820 end
2821 % Pass DES-specific options if configured
2822 if isfield(options, 'config')
2823 % Transient detection options
2824 if isfield(options.config, 'tranfilter')
2825 desOptions.tranfilter = options.config.tranfilter;
2826 end
2827 if isfield(options.config, 'mserbatch')
2828 desOptions.mserbatch = options.config.mserbatch;
2829 end
2830 if isfield(options.config, 'warmupfrac')
2831 desOptions.warmupfrac = options.config.warmupfrac;
2832 end
2833 % Confidence interval options
2834 if isfield(options.config, 'cimethod')
2835 desOptions.cimethod = options.config.cimethod;
2836 end
2837 if isfield(options.config, 'obmoverlap')
2838 desOptions.obmoverlap = options.config.obmoverlap;
2839 end
2840 if isfield(options.config, 'ciminbatch')
2841 desOptions.ciminbatch = options.config.ciminbatch;
2842 end
2843 if isfield(options.config, 'ciminobs')
2844 desOptions.ciminobs = options.config.ciminobs;
2845 end
2846 % Convergence options
2847 if isfield(options.config, 'cnvgon')
2848 desOptions.cnvgon = options.config.cnvgon;
2849 end
2850 if isfield(options.config, 'cnvgtol')
2851 desOptions.cnvgtol = options.config.cnvgtol;
2852 end
2853 if isfield(options.config, 'cnvgbatch')
2854 desOptions.cnvgbatch = options.config.cnvgbatch;
2855 end
2856 if isfield(options.config, 'cnvgchk')
2857 desOptions.cnvgchk = options.config.cnvgchk;
2858 end
2859 end
2860 end
2861 des = jline.solvers.des.SolverDES(network_object, desOptions);
2862 end
2863
2864 function [mva] = SolverMVA(network_object, options)
2865 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MVA);
2866 if nargin>1
2867 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2868 end
2869 mva = jline.solvers.mva.SolverMVA(network_object, solverOptions);
2870 end
2871
2872 function [nc] = SolverNC(network_object, options)
2873 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.NC);
2874 if nargin>1
2875 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2876 end
2877 nc = jline.solvers.nc.SolverNC(network_object, solverOptions);
2878 end
2879
2880 function [auto] = SolverAuto(network_object, options)
2881 solverOptions = jline.solvers.auto.AUTOptions();
2882 if nargin>1
2883 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
2884 end
2885 auto = jline.solvers.auto.SolverAUTO(network_object, solverOptions);
2886 end
2887
2888 function streamOpts = StreamingOptions(varargin)
2889 % STREAMINGOPTIONS Create Java StreamingOptions for SSA/DES stream() method
2890 %
2891 % @brief Creates StreamingOptions for streaming simulation metrics
2892 %
2893 % @param varargin Name-value pairs for options:
2894 % 'transport' - 'http' (recommended) or 'grpc' (default: 'http')
2895 % 'endpoint' - Receiver endpoint (default: 'localhost:8080/metrics' for HTTP)
2896 % 'mode' - 'sampled' or 'time_window' (default: 'sampled')
2897 % 'sampleFrequency' - Push every N events in sampled mode (default: 100)
2898 % 'timeWindowSeconds' - Window duration in time_window mode (default: 1.0)
2899 % 'serviceName' - Service identifier (default: 'line-stream')
2900 % 'includeQueueLength' - Include queue length metrics (default: true)
2901 % 'includeUtilization' - Include utilization metrics (default: true)
2902 % 'includeThroughput' - Include throughput metrics (default: true)
2903 % 'includeResponseTime' - Include response time metrics (default: true)
2904 % 'includeArrivalRate' - Include arrival rate metrics (default: true)
2905 %
2906 % @return streamOpts Java StreamingOptions object
2907 %
2908 % Example:
2909 % @code
2910 % streamOpts = JLINE.StreamingOptions('transport', 'http', 'sampleFrequency', 50);
2911 % @endcode
2912
2913 streamOpts = jline.streaming.StreamingOptions();
2914
2915 % Parse optional arguments
2916 p = inputParser;
2917 addParameter(p, 'transport', 'http', @ischar);
2918 addParameter(p, 'endpoint', '', @ischar); % Empty means use default for transport
2919 addParameter(p, 'mode', 'sampled', @ischar);
2920 addParameter(p, 'sampleFrequency', 100, @isnumeric);
2921 addParameter(p, 'timeWindowSeconds', 1.0, @isnumeric);
2922 addParameter(p, 'serviceName', 'line-stream', @ischar);
2923 addParameter(p, 'includeQueueLength', true, @islogical);
2924 addParameter(p, 'includeUtilization', true, @islogical);
2925 addParameter(p, 'includeThroughput', true, @islogical);
2926 addParameter(p, 'includeResponseTime', true, @islogical);
2927 addParameter(p, 'includeArrivalRate', true, @islogical);
2928 parse(p, varargin{:});
2929
2930 % Set transport type
2931 transportTypes = javaMethod('values', 'jline.streaming.StreamingOptions$TransportType');
2932 switch lower(p.Results.transport)
2933 case 'http'
2934 streamOpts.transport = transportTypes(1); % HTTP
2935 case 'grpc'
2936 streamOpts.transport = transportTypes(2); % GRPC
2937 otherwise
2938 streamOpts.transport = transportTypes(1); % Default to HTTP
2939 end
2940
2941 % Set endpoint (use provided or default based on transport)
2942 if ~isempty(p.Results.endpoint)
2943 streamOpts.endpoint = p.Results.endpoint;
2944 end
2945 % If empty, StreamingOptions uses its default for the transport type
2946
2947 % Set mode
2948 streamModes = javaMethod('values', 'jline.streaming.StreamingOptions$StreamMode');
2949 switch lower(p.Results.mode)
2950 case 'sampled'
2951 streamOpts.mode = streamModes(1); % SAMPLED
2952 case 'time_window'
2953 streamOpts.mode = streamModes(2); % TIME_WINDOW
2954 otherwise
2955 streamOpts.mode = streamModes(1); % Default to SAMPLED
2956 end
2957
2958 % Set other options
2959 streamOpts.sampleFrequency = p.Results.sampleFrequency;
2960 streamOpts.timeWindowSeconds = p.Results.timeWindowSeconds;
2961 streamOpts.serviceName = p.Results.serviceName;
2962 streamOpts.includeQueueLength = p.Results.includeQueueLength;
2963 streamOpts.includeUtilization = p.Results.includeUtilization;
2964 streamOpts.includeThroughput = p.Results.includeThroughput;
2965 streamOpts.includeResponseTime = p.Results.includeResponseTime;
2966 streamOpts.includeArrivalRate = p.Results.includeArrivalRate;
2967 end
2968
2969 function result = convertSampleResult(jresult)
2970 % CONVERTSAMPLERESULT Convert Java sample result to MATLAB struct
2971 %
2972 % @brief Converts Java SampleNodeState to MATLAB structure
2973 %
2974 % @param jresult Java SampleNodeState object
2975 % @return result MATLAB struct with fields: t, state, isaggregate
2976
2977 result = struct();
2978
2979 % Convert time matrix
2980 if ~isempty(jresult.t)
2981 result.t = JLINE.from_jline_matrix(jresult.t);
2982 else
2983 result.t = [];
2984 end
2985
2986 % Convert state matrix
2987 if ~isempty(jresult.state) && isa(jresult.state, 'jline.util.matrix.Matrix')
2988 result.state = JLINE.from_jline_matrix(jresult.state);
2989 else
2990 result.state = [];
2991 end
2992
2993 result.isaggregate = jresult.isaggregate;
2994 end
2995
2996 function [ln] = SolverLN(layered_network_object, options)
2997 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.LN);
2998 if nargin>1
2999 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3000 end
3001 ln = jline.solvers.ln.SolverLN(layered_network_object, solverOptions);
3002 end
3003
3004 function serfun = handle_to_serializablefun(handle, sn)
3005 % HANDLE_TO_SERIALIZABLEFUN Convert MATLAB function handle to Java SerializableFunction
3006 %
3007 % This function pre-computes the function values for all possible state
3008 % combinations and creates a Java PrecomputedCDFunction object.
3009 %
3010 % @param handle MATLAB function handle that takes a vector ni and returns a scalar
3011 % @param sn Network struct containing njobs (population per class)
3012 % @return serfun Java PrecomputedCDFunction object
3013
3014 % Get number of classes and maximum populations
3015 nclasses = sn.nclasses;
3016 njobs = sn.njobs; % Population per class
3017
3018 % For open classes (njobs=0), use a reasonable bound
3019 maxPop = njobs;
3020 for r = 1:nclasses
3021 if maxPop(r) == 0 || isinf(maxPop(r))
3022 % For open classes, use sum of closed class populations or 100 as bound
3023 maxPop(r) = max(100, sum(njobs(isfinite(njobs) & njobs > 0)));
3024 end
3025 end
3026
3027 % Create Java PrecomputedCDFunction object
3028 serfun = jline.util.PrecomputedCDFunction(nclasses);
3029
3030 % Enumerate all possible state combinations and pre-compute function values
3031 % Use recursive enumeration to handle arbitrary number of classes
3032 JLINE.enumerate_states(handle, serfun, maxPop, zeros(1, nclasses), 1);
3033 end
3034
3035 function enumerate_states(handle, serfun, maxPop, currentState, classIdx)
3036 % ENUMERATE_STATES Recursively enumerate all state combinations
3037 %
3038 % @param handle MATLAB function handle
3039 % @param serfun Java PrecomputedCDFunction object to populate
3040 % @param maxPop Maximum population per class
3041 % @param currentState Current state being built
3042 % @param classIdx Current class index being enumerated
3043
3044 nclasses = length(maxPop);
3045
3046 if classIdx > nclasses
3047 % We have a complete state, compute and store the function value
3048 try
3049 value = handle(currentState);
3050 % Convert to Java int array and add to serfun
3051 jstate = jline.util.matrix.Matrix(1, nclasses);
3052 for r = 1:nclasses
3053 jstate.set(0, r-1, currentState(r));
3054 end
3055 serfun.addValue(jstate, value);
3056 catch
3057 % If function evaluation fails, skip this state
3058 end
3059 return;
3060 end
3061
3062 % Enumerate all populations for current class
3063 for n = 0:maxPop(classIdx)
3064 currentState(classIdx) = n;
3065 JLINE.enumerate_states(handle, serfun, maxPop, currentState, classIdx + 1);
3066 end
3067 end
3068
3069 function result = call_java_cdscaling(jfun, ni)
3070 % CALL_JAVA_CDSCALING Call a Java SerializableFunction for class dependence
3071 %
3072 % This function converts a MATLAB vector to a Java Matrix and calls
3073 % the Java function's apply() method.
3074 %
3075 % @param jfun Java SerializableFunction<Matrix, Double> object
3076 % @param ni MATLAB vector representing the state (jobs per class)
3077 % @return result The scaling factor returned by the Java function
3078
3079 % Convert MATLAB vector to Java Matrix
3080 if isrow(ni)
3081 jmatrix = jline.util.matrix.Matrix(1, length(ni));
3082 for r = 1:length(ni)
3083 jmatrix.set(0, r-1, ni(r));
3084 end
3085 else
3086 jmatrix = jline.util.matrix.Matrix(length(ni), 1);
3087 for r = 1:length(ni)
3088 jmatrix.set(r-1, 0, ni(r));
3089 end
3090 end
3091
3092 % Call the Java function and convert result to MATLAB double
3093 jresult = jfun.apply(jmatrix);
3094 result = double(jresult);
3095 end
3096
3097 end
3098end
Definition mmt.m:93