2 % JLINE Conversion utilities
for JLINE format models
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.
8 % @brief JLINE format conversion and Java interoperability utilities
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
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');
26 function jar_loc = get_jar_location()
27 % Get jline.jar location, downloading
if necessary.
28 % Re-checks on each call, so deleted JAR triggers re-download.
29 % Treats lang='java' as a wrapper that auto-downloads jline.jar if absent.
30 jar_loc = which('jline.jar');
31 if isempty(jar_loc) || ~isfile(jar_loc)
32 jar_loc = lineDownloadJAR(
false); % Silent re-download
36 function model = from_line_layered_network(line_layered_network)
37 sn = line_layered_network.getStruct;
40 model = javaObject(
'jline.lang.layered.LayeredNetwork', line_layered_network.getName);
43 P = cell(1,sn.nhosts);
46 sn_mult_h = java.lang.Integer.MAX_VALUE;
48 sn_mult_h = sn.mult(h);
51 case SchedStrategy.REF
52 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.REF);
53 case SchedStrategy.INF
54 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.INF);
55 case SchedStrategy.FCFS
56 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.FCFS);
57 case SchedStrategy.LCFS
58 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFS);
59 case SchedStrategy.SIRO
60 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.SIRO);
61 case SchedStrategy.SJF
62 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.SJF);
63 case SchedStrategy.LJF
64 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LJF);
66 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.PS);
67 case SchedStrategy.DPS
68 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.DPS);
69 case SchedStrategy.GPS
70 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.GPS);
71 case SchedStrategy.SEPT
72 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.SEPT);
73 case SchedStrategy.LEPT
74 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LEPT);
75 case {SchedStrategy.HOL, SchedStrategy.FCFSPRIO}
76 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.FCFSPRIO);
77 case SchedStrategy.FORK
78 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.FORK);
79 case SchedStrategy.EXT
80 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.EXT);
81 case SchedStrategy.LCFSPR
82 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPR);
83 case SchedStrategy.LCFSPI
84 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPI);
85 case SchedStrategy.LCFSPRIO
86 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPRIO);
87 case SchedStrategy.LCFSPRPRIO
88 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPRPRIO);
89 case SchedStrategy.LCFSPIPRIO
90 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.LCFSPIPRIO);
91 case SchedStrategy.PSPRIO % todo
92 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.PSPRIO);
93 case SchedStrategy.DPSPRIO % todo
94 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.DPSPRIO);
95 case SchedStrategy.GPSPRIO % todo
96 P{h} = javaObject(
'jline.lang.layered.Processor', model, sn.names{h}, sn_mult_h, jline.lang.constant.SchedStrategy.GPSPRIO);
99 P{h}.setReplication(sn.repl(h));
104 T = cell(1,sn.ntasks);
107 if isinf(sn.mult(tidx))
108 sn_mult_tidx = java.lang.Integer.MAX_VALUE;
110 sn_mult_tidx = sn.mult(tidx);
112 % Check
if this is a CacheTask
114 % Get replacement strategy from ordinal
115 switch sn.replacestrat(tidx)
116 case ReplacementStrategy.RR
117 jReplacestrat = jline.lang.constant.ReplacementStrategy.RR;
118 case ReplacementStrategy.FIFO
119 jReplacestrat = jline.lang.constant.ReplacementStrategy.FIFO;
120 case ReplacementStrategy.SFIFO
121 jReplacestrat = jline.lang.constant.ReplacementStrategy.SFIFO;
122 case ReplacementStrategy.LRU
123 jReplacestrat = jline.lang.constant.ReplacementStrategy.LRU;
125 jReplacestrat = jline.lang.constant.ReplacementStrategy.FIFO;
127 T{t} = javaObject(
'jline.lang.layered.CacheTask', model, sn.names{tidx}, sn.nitems(tidx), sn.itemcap{tidx}, jReplacestrat, sn_mult_tidx);
128 if isfield(sn,
'hasretrieval') && numel(sn.hasretrieval)>=tidx && sn.hasretrieval(tidx)
129 T{t}.setRetrieval(
true);
131 elseif sn.isfunction(tidx)
132 % FunctionTask (has setupTime/delayOffTime)
133 jSchedStrategy = JLINE.to_jline_sched_strategy(sn.sched(tidx));
134 T{t} = javaObject(
'jline.lang.layered.FunctionTask', model, sn.names{tidx}, sn_mult_tidx, jSchedStrategy);
136 jSchedStrategy = JLINE.to_jline_sched_strategy(sn.sched(tidx));
137 T{t} = javaObject(
'jline.lang.layered.Task', model, sn.names{tidx}, sn_mult_tidx, jSchedStrategy);
139 T{t}.on(
P{sn.parent(tidx)});
141 T{t}.setReplication(sn.repl(tidx));
143 if ~isempty(sn.think{tidx}) && sn.think_type(tidx) ~= ProcessType.DISABLED
144 switch sn.think_type(tidx)
145 case ProcessType.IMMEDIATE
146 T{t}.setThinkTime(jline.lang.processes.Immediate);
148 T{t}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(tidx)));
149 case ProcessType.ERLANG
150 T{t}.setThinkTime(jline.lang.processes.Erlang.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
151 case ProcessType.HYPEREXP
152 if ~isempty(sn.think_params{tidx}) && length(sn.think_params{tidx}) >= 3
153 T{t}.setThinkTime(jline.lang.processes.HyperExp(sn.think_params{tidx}(1), sn.think_params{tidx}(2), sn.think_params{tidx}(3)));
155 T{t}.setThinkTime(jline.lang.processes.HyperExp.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
157 case ProcessType.COXIAN
158 T{t}.setThinkTime(jline.lang.processes.Coxian.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
160 T{t}.setThinkTime(jline.lang.processes.APH.fitMeanAndSCV(sn.think_mean(tidx), sn.think_scv(tidx)));
162 if ~isempty(sn.think_proc{tidx})
163 proc = sn.think_proc{tidx};
164 T{t}.setThinkTime(jline.lang.processes.PH(JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2})));
166 T{t}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(tidx)));
169 if ~isempty(sn.think_proc{tidx})
170 proc = sn.think_proc{tidx};
171 T{t}.setThinkTime(jline.lang.processes.MAP(JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2})));
173 T{t}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(tidx)));
176 T{t}.setThinkTime(jline.lang.processes.Det(sn.think_mean(tidx)));
177 case ProcessType.UNIFORM
178 p = sn.think_params{tidx};
179 T{t}.setThinkTime(jline.lang.processes.Uniform(p(1), p(2)));
180 case ProcessType.GAMMA
181 p = sn.think_params{tidx};
182 T{t}.setThinkTime(jline.lang.processes.Gamma(p(1), p(2)));
183 case ProcessType.PARETO
184 p = sn.think_params{tidx};
185 T{t}.setThinkTime(jline.lang.processes.Pareto(p(1), p(2)));
186 case ProcessType.WEIBULL
187 p = sn.think_params{tidx};
188 T{t}.setThinkTime(jline.lang.processes.Weibull(p(1), p(2)));
189 case ProcessType.LOGNORMAL
190 p = sn.think_params{tidx};
191 T{t}.setThinkTime(jline.lang.processes.Lognormal(p(1), p(2)));
193 line_error(mfilename,sprintf(
'JLINE conversion does not support the %s distribution for task think time yet.',
char(sn.think_type(tidx))));
196 % Setup time. The distribution
is rebuilt from its type, mean and
197 % SCV: handing
the mean to setSetupTime(
double) made
the JAR
198 % rebuild it as Exp(1/mean) with SCV 1, so a non-exponential
199 % setup lost its variability crossing into lang='java' while
the
200 % mean still matched, and
the two langs disagreed silently.
201 if sn.isfunction(tidx) && ~isnan(sn.setuptime_mean(tidx)) && sn.setuptime_mean(tidx) > 1e-8
202 T{t}.setSetupTime(JLINE.from_line_lqn_dist(sn.setuptime_type(tidx), ...
203 sn.setuptime_mean(tidx), sn.setuptime_scv(tidx), ...
204 sn.setuptime_params{tidx}, sn.setuptime_proc{tidx}));
207 if sn.isfunction(tidx) && ~isnan(sn.delayofftime_mean(tidx)) && sn.delayofftime_mean(tidx) > 1e-8
208 T{t}.setDelayOffTime(JLINE.from_line_lqn_dist(sn.delayofftime_type(tidx), ...
209 sn.delayofftime_mean(tidx), sn.delayofftime_scv(tidx), ...
210 sn.delayofftime_params{tidx}, sn.delayofftime_proc{tidx}));
214 E = cell(1,sn.nentries);
217 % Check
if this is an ItemEntry (has nitems > 0)
218 if sn.nitems(eidx) > 0
219 % ItemEntry requires cardinality and popularity distribution
220 if ~isempty(sn.itemproc) && ~isempty(sn.itemproc{eidx})
221 jPopularity = JLINE.from_line_distribution(sn.itemproc{eidx});
223 % Default to uniform distribution
224 jPopularity = javaObject(
'jline.lang.processes.DiscreteSampler', jline.util.matrix.Matrix.uniformDistribution(sn.nitems(eidx)));
226 E{e} = javaObject(
'jline.lang.layered.ItemEntry', model, sn.names{eidx}, sn.nitems(eidx), jPopularity);
228 E{e} = javaObject(
'jline.lang.layered.Entry', model, sn.names{eidx});
230 E{e}.on(T{sn.parent(eidx)-sn.tshift});
231 % Open arrival at
the entry. The bridge previously never called
232 % setArrival, so open-arrival LQNs lost their source crossing
233 % into lang='java'. Guarded on arrival_mean, which
is NaN for
234 % entries without an arrival: arrival_type preallocates to 0,
235 % which collides with ProcessType.EXP.
236 if ~isnan(sn.arrival_mean(eidx)) && sn.arrival_mean(eidx) > 0
237 E{e}.setArrival(JLINE.from_line_lqn_dist(sn.arrival_type(eidx), ...
238 sn.arrival_mean(eidx), sn.arrival_scv(eidx), ...
239 sn.arrival_params{eidx}, sn.arrival_proc{eidx}));
244 A = cell(1,sn.nacts);
247 tidx = sn.parent(aidx);
248 onTask = tidx-sn.tshift;
249 % Convert host demand from primitives to Java distribution
250 switch sn.hostdem_type(aidx)
251 case ProcessType.IMMEDIATE
252 jHostDem = jline.lang.processes.Immediate;
253 case ProcessType.DISABLED
254 jHostDem = jline.lang.processes.Disabled;
256 jHostDem = javaObject(
'jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
257 case ProcessType.ERLANG
258 jHostDem = jline.lang.processes.Erlang.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
259 case ProcessType.HYPEREXP
260 if ~isempty(sn.hostdem_params{aidx}) && length(sn.hostdem_params{aidx}) >= 3
261 jHostDem = javaObject(
'jline.lang.processes.HyperExp', sn.hostdem_params{aidx}(1), sn.hostdem_params{aidx}(2), sn.hostdem_params{aidx}(3));
263 jHostDem = jline.lang.processes.HyperExp.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
265 case ProcessType.COXIAN
266 jHostDem = jline.lang.processes.Coxian.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
268 jHostDem = jline.lang.processes.APH.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
270 if ~isempty(sn.hostdem_proc{aidx})
271 proc = sn.hostdem_proc{aidx};
272 jHostDem = javaObject(
'jline.lang.processes.PH', JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2}));
274 jHostDem = javaObject(
'jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
277 if ~isempty(sn.hostdem_proc{aidx})
278 proc = sn.hostdem_proc{aidx};
279 jHostDem = javaObject(
'jline.lang.processes.MAP', JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2}));
281 jHostDem = javaObject(
'jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
284 jHostDem = javaObject(
'jline.lang.processes.Det', sn.hostdem_mean(aidx));
285 case ProcessType.UNIFORM
286 p = sn.hostdem_params{aidx};
287 jHostDem = javaObject(
'jline.lang.processes.Uniform', p(1), p(2));
288 case ProcessType.GAMMA
289 p = sn.hostdem_params{aidx};
290 jHostDem = javaObject(
'jline.lang.processes.Gamma', p(1), p(2));
291 case ProcessType.PARETO
292 p = sn.hostdem_params{aidx};
293 jHostDem = javaObject(
'jline.lang.processes.Pareto', p(1), p(2));
294 case ProcessType.WEIBULL
295 p = sn.hostdem_params{aidx};
296 jHostDem = javaObject(
'jline.lang.processes.Weibull', p(1), p(2));
297 case ProcessType.LOGNORMAL
298 p = sn.hostdem_params{aidx};
299 jHostDem = javaObject(
'jline.lang.processes.Lognormal', p(1), p(2));
301 line_error(mfilename,sprintf(
'JLINE conversion does not support the %s distribution for host demand yet.',
char(sn.hostdem_type(aidx))));
303 A{a} = javaObject(
'jline.lang.layered.Activity', model, sn.names{aidx}, jHostDem);
306 boundTo = find(sn.graph((sn.eshift+1):(sn.eshift+sn.nentries),aidx));
309 A{a}.boundTo(E{boundTo});
312 if sn.sched(tidx) ~= SchedStrategy.REF % ref tasks don
't reply
313 repliesTo = find(sn.replygraph(a,:)); % index of entry
314 if ~isempty(repliesTo)
315 if ~sn.isref(sn.parent(sn.eshift+repliesTo))
316 A{a}.repliesTo(E{repliesTo});
321 if ~isempty(sn.callpair)
322 cidxs = find(sn.callpair(:,1)==aidx);
323 calls = sn.callpair(:,2);
325 switch sn.calltype(c)
327 A{a}.synchCall(E{calls(c)-sn.eshift},sn.callproc_mean(c));
329 A{a}.asynchCall(E{calls(c)-sn.eshift},sn.callproc_mean(c));
338 if ~isempty(sn.think{h}) && sn.think_type(h) ~= ProcessType.DISABLED
339 switch sn.think_type(h)
340 case ProcessType.IMMEDIATE
341 P{h}.setThinkTime(jline.lang.processes.Immediate);
343 P{h}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(h)));
344 case ProcessType.ERLANG
345 P{h}.setThinkTime(jline.lang.processes.Erlang.fitMeanAndSCV(sn.think_mean(h),sn.think_scv(h)));
346 case ProcessType.HYPEREXP
347 % For HyperExp, reconstruct from params
if available, otherwise use fitMeanAndSCV
348 if ~isempty(sn.think_params{h}) && length(sn.think_params{h}) >= 3
349 P{h}.setThinkTime(jline.lang.processes.HyperExp(sn.think_params{h}(1), sn.think_params{h}(2), sn.think_params{h}(3)));
351 P{h}.setThinkTime(jline.lang.processes.HyperExp.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
353 case ProcessType.COXIAN
354 % For Coxian, use fitMeanAndSCV
355 P{h}.setThinkTime(jline.lang.processes.Coxian.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
357 % For APH, reconstruct from params
if available
358 if ~isempty(sn.think_params{h})
359 P{h}.setThinkTime(jline.lang.processes.APH.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
361 P{h}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(h)));
364 P{h}.setThinkTime(jline.lang.processes.Det(sn.think_mean(h)));
365 case ProcessType.UNIFORM
366 p = sn.think_params{h};
367 P{h}.setThinkTime(jline.lang.processes.Uniform(p(1), p(2)));
368 case ProcessType.GAMMA
369 p = sn.think_params{h};
370 P{h}.setThinkTime(jline.lang.processes.Gamma(p(1), p(2)));
371 case ProcessType.PARETO
372 p = sn.think_params{h};
373 P{h}.setThinkTime(jline.lang.processes.Pareto(p(1), p(2)));
374 case ProcessType.WEIBULL
375 p = sn.think_params{h};
376 P{h}.setThinkTime(jline.lang.processes.Weibull(p(1), p(2)));
377 case ProcessType.LOGNORMAL
378 p = sn.think_params{h};
379 P{h}.setThinkTime(jline.lang.processes.Lognormal(p(1), p(2)));
381 line_error(mfilename,sprintf(
'JLINE conversion does not support the %s distribution yet.',
char(sn.think_type(h))));
386 %% Sequential precedences
388 aidx = sn.ashift + ai;
389 tidx = sn.parent(aidx);
391 for bidx=find(sn.graph(aidx,:))
392 if bidx > sn.ashift % ignore precedence between entries and activities
393 % Serial pattern (SEQ)
394 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_SEQ && full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_SEQ
395 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.Serial(sn.names{aidx}, sn.names{bidx}));
401 %%%%%%%%%%%%%%%%%%%%%%%%%%% translated up to here
403 %% Loop precedences (POST_LOOP)
404 % Loop structure in sn.graph:
405 % - Entry activity (preAct) has edge to first loop body activity
406 % - Last loop body activity has back-edge to first loop body (weight = 1-1/counts)
407 % - Last loop body activity has edge to end activity (weight = 1/counts)
408 % - All loop body and end activities have POST_LOOP type
409 processedLoops = false(1, sn.nacts);
411 aidx = sn.ashift + ai;
412 tidx = sn.parent(aidx);
413 % Check
if this activity starts a loop (has a successor with POST_LOOP type)
414 % and hasn
't been processed as part of another loop
415 if processedLoops(ai)
419 successors = find(sn.graph(aidx,:));
420 for bidx = successors
421 if bidx > sn.ashift && full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_LOOP
422 % Skip if this loop body activity was already processed
423 if processedLoops(bidx - sn.ashift)
426 % Found start of a loop: aidx is the entry, bidx is first loop body activity
428 precActs = java.util.ArrayList();
430 % Follow the chain of POST_LOOP activities
433 precActs.add(sprintf("%s", sn.names{curIdx}));
434 processedLoops(curIdx - sn.ashift) = true;
436 % Find successors of current activity
437 curSuccessors = find(sn.graph(curIdx,:));
438 curSuccessors = curSuccessors(curSuccessors > sn.ashift);
440 % Check for loop termination: find the end activity
441 % End activity has weight = 1/counts (not the back-edge weight)
444 for succIdx = curSuccessors
445 if full(sn.actposttype(succIdx)) == ActivityPrecedenceType.POST_LOOP
446 if succIdx == loopStart
447 % This is the back-edge, skip it
450 weight = full(sn.graph(curIdx, succIdx));
451 if weight > 0 && weight < 1
452 % This is the end activity (weight = 1/counts)
455 % This is the next activity in the loop body (weight = 1.0)
462 % Found end activity - calculate counts and output
463 weight = full(sn.graph(curIdx, endIdx));
467 counts = 1; % Fallback to prevent division by zero
469 precActs.add(sprintf("%s", sn.names{endIdx}));
470 processedLoops(endIdx - sn.ashift) = true;
472 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.Loop(sn.names{aidx}, precActs, jline.util.matrix.Matrix(counts)));
475 % Continue to next activity in loop body
478 % No more successors - shouldn't happen in valid loop
482 break; % Only process one loop starting from
this activity
487 %% OrFork precedences (POST_OR)
491 aidx = sn.ashift + ai;
492 tidx = sn.parent(aidx);
495 for bidx=find(sn.graph(aidx,:))
496 if bidx > sn.ashift % ignore precedence between entries and activities
497 % Or pattern (POST_OR)
498 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_OR
499 if precMarker == 0 % start a new orjoin
500 precActs = java.util.ArrayList();
501 precMarker = aidx-sn.ashift;
502 precActs.add(sprintf(
"%s", sn.names{bidx}));
503 probs=full(sn.graph(aidx,bidx));
505 precActs.add(sprintf(
"%s", sn.names{bidx}));
506 probs(end+1)=full(sn.graph(aidx,bidx));
514 probsMatrix = jline.util.matrix.Matrix(1,length(probs));
515 for i=1:length(probs)
516 probsMatrix.set(0,i-1,probs(i));
518 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.OrFork(sn.names{precMarker+sn.ashift}, precActs, probsMatrix));
523 %% AndFork precedences (POST_AND)
527 aidx = sn.ashift + ai;
528 tidx = sn.parent(aidx);
530 for bidx=find(sn.graph(aidx,:))
531 if bidx > sn.ashift % ignore precedence between entries and activities
532 % Or pattern (POST_AND)
533 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_AND
535 postActs = java.util.ArrayList();
536 postActs.add(sprintf(
"%s", sn.names{bidx}));
538 postActs.add(sprintf(
"%s", sn.names{bidx}));
541 if precMarker == 0 % start a
new orjoin
542 precMarker = aidx-sn.ashift;
548 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndFork(sn.names{precMarker+sn.ashift}, postActs));
553 %% CacheAccess precedences (POST_CACHE)
557 aidx = sn.ashift + ai;
558 tidx = sn.parent(aidx);
560 for bidx=find(sn.graph(aidx,:))
561 if bidx > sn.ashift % ignore precedence between entries and activities
562 % CacheAccess pattern (POST_CACHE)
563 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_CACHE
565 postActs = java.util.ArrayList();
566 postActs.add(sprintf(
"%s", sn.names{bidx}));
568 postActs.add(sprintf(
"%s", sn.names{bidx}));
571 if precMarker == 0 % start a
new cache access
572 precMarker = aidx-sn.ashift;
578 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.CacheAccess(sn.names{precMarker+sn.ashift}, postActs));
584 %% OrJoin precedences (PRE_OR)
586 for bi = sn.nacts:-1:1
587 bidx = sn.ashift + bi;
588 tidx = sn.parent(bidx);
589 %
for all predecessors
590 for aidx=find(sn.graph(:,bidx))
'
591 if aidx > sn.ashift % ignore precedence between entries and activities
592 % OrJoin pattern (PRE_OR)
593 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_OR
594 if precMarker == 0 % start a new orjoin
595 precActs = java.util.ArrayList();
596 precMarker = bidx-sn.ashift;
597 precActs.add(sprintf("%s", sn.names{aidx}));
599 precActs.add(sprintf("%s", sn.names{aidx}));
605 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.OrJoin(precActs, sn.names{precMarker+sn.ashift}));
610 %% AndJoin precedences (PRE_AND)
612 for bi = sn.nacts:-1:1
613 bidx = sn.ashift + bi;
614 tidx = sn.parent(bidx);
615 % for all predecessors
616 for aidx=find(sn.graph(:,bidx))'
617 if aidx > sn.ashift % ignore precedence between entries and activities
618 % OrJoin pattern (PRE_AND)
619 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_AND
620 if precMarker == 0 % start a new orjoin
621 precActs = java.util.ArrayList();
622 precMarker = bidx-sn.ashift;
623 precActs.add(sprintf(
"%s", sn.names{aidx}));
625 precActs.add(sprintf(
"%s", sn.names{aidx}));
631 % Find quorum parameter from original precedence structure
632 postActName = sn.names{precMarker+sn.ashift};
633 localTaskIdx = tidx - sn.tshift;
635 for ap = 1:length(line_layered_network.tasks{localTaskIdx}.precedences)
636 precedence = line_layered_network.tasks{localTaskIdx}.precedences(ap);
637 if precedence.preType == ActivityPrecedenceType.PRE_AND
638 % Check
if this precedence contains our post activity
639 if any(strcmp(precedence.postActs, postActName))
640 quorum = precedence.preParams;
647 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndJoin(precActs, sn.names{precMarker+sn.ashift}));
649 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndJoin(precActs, sn.names{precMarker+sn.ashift}, quorum));
657 function jdist = from_line_distribution(line_dist)
658 if isa(line_dist,
'Exp')
659 jdist = javaObject('jline.lang.processes.Exp', line_dist.getParam(1).paramValue);
660 elseif isa(line_dist, "APH")
661 alpha = line_dist.getParam(1).paramValue;
662 T = line_dist.getParam(2).paramValue;
663 jline_alpha = java.util.ArrayList();
664 for i = 1:length(alpha)
665 jline_alpha.add(alpha(i));
667 jline_T = JLINE.from_line_matrix(T);
668 jdist = javaObject('jline.lang.processes.APH', jline_alpha, jline_T);
669 elseif isa(line_dist, 'Coxian')
670 jline_mu = java.util.ArrayList();
671 jline_phi = java.util.ArrayList();
672 if length(line_dist.params) == 3
673 jline_mu.add(line_dist.getParam(1).paramValue);
674 jline_mu.add(line_dist.getParam(2).paramValue);
675 jline_phi.add(line_dist.getParam(3).paramValue);
677 mu = line_dist.getParam(1).paramValue;
678 phi = line_dist.getParam(2).paramValue;
682 for i = 1:length(phi)
683 jline_phi.add(phi(i));
686 jdist = javaObject('jline.lang.processes.Coxian', jline_mu, jline_phi);
687 elseif isa(line_dist, 'Det')
688 jdist = javaObject('jline.lang.processes.Det', line_dist.getParam(1).paramValue);
689 elseif isa(line_dist, 'DiscreteSampler')
690 popularity_p = JLINE.from_line_matrix(line_dist.getParam(1).paramValue);
691 popularity_val = JLINE.from_line_matrix(line_dist.getParam(2).paramValue);
692 jdist = javaObject('jline.lang.processes.DiscreteSampler', popularity_p, popularity_val);
693 elseif isa(line_dist, 'Erlang')
694 jdist = javaObject('jline.lang.processes.Erlang', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
695 elseif isa(line_dist, 'Gamma')
696 jdist = javaObject('jline.lang.processes.Gamma', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
697 elseif isa(line_dist, "HyperExp")
698 jdist = javaObject('jline.lang.processes.HyperExp', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue, line_dist.getParam(3).paramValue);
699 elseif isa(line_dist, 'Lognormal')
700 jdist = javaObject('jline.lang.processes.Lognormal', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
701 elseif isa(line_dist, 'Pareto')
702 jdist = javaObject('jline.lang.processes.Pareto', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
703 elseif isa(line_dist, 'MAP')
706 jdist = javaObject('jline.lang.processes.MAP', JLINE.from_line_matrix(D0), JLINE.from_line_matrix(D1));
707 elseif isa(line_dist, 'MMPP2')
708 lambda0 = line_dist.getParam(1).paramValue;
709 lambda1 = line_dist.getParam(2).paramValue;
710 sigma0 = line_dist.getParam(3).paramValue;
711 sigma1 = line_dist.getParam(4).paramValue;
712 jdist = javaObject('jline.lang.processes.MMPP2', lambda0, lambda1, sigma0, sigma1);
713 elseif isa(line_dist, 'NHPP')
714 jdist = javaObject('jline.lang.processes.NHPP', line_dist.getBreakpoints(), line_dist.getRates(), logical(line_dist.isCyclic()));
715 elseif isa(line_dist, 'BMAP') % before MarkedMAP (BMAP < MarkedMAP)
716 % Both sides store
the process cell in MarkedMAP layout
717 % {D0, D1_total, D1..DK}: MATLAB in line_dist.process (params
718 % are unreliable, see
the constructor note in BMAP.m) and
the
719 % JAR BMAP(MatrixCell) constructor reads index 1 as D1_total
720 % (see its validateGenerator), so
the cell
is passed as-
is
721 nmp = length(line_dist.process);
722 jD = javaArray(
'jline.util.matrix.Matrix', nmp);
724 jD(k) = JLINE.from_line_matrix(line_dist.process{k});
726 jdist = javaObject(
'jline.lang.processes.BMAP', javaObject(
'jline.util.matrix.MatrixCell', jD));
727 elseif isa(line_dist,
'MarkedMMPP')
728 nmp = length(line_dist.params); % {D0, D1, D11..D1K}
729 jD = javaArray(
'jline.util.matrix.Matrix', nmp);
731 jD(k) = JLINE.from_line_matrix(line_dist.getParam(k).paramValue);
733 jdist = javaObject(
'jline.lang.processes.MarkedMMPP', javaObject(
'jline.util.matrix.MatrixCell', jD));
734 elseif isa(line_dist,
'MarkedMAP')
735 nmp = length(line_dist.params); % {D0, D1, D11..D1K}
736 jD = javaArray(
'jline.util.matrix.Matrix', nmp);
738 jD(k) = JLINE.from_line_matrix(line_dist.getParam(k).paramValue);
740 jdist = javaObject(
'jline.lang.processes.MarkedMAP', javaObject(
'jline.util.matrix.MatrixCell', jD));
741 elseif isa(line_dist,
'DMAP')
742 jdist = javaObject('jline.lang.processes.DMAP', javaObject('jline.util.matrix.MatrixCell', JLINE.from_line_matrix(line_dist.getParam(1).paramValue), JLINE.from_line_matrix(line_dist.getParam(2).paramValue)));
743 elseif isa(line_dist, 'ME')
744 jdist = javaObject('jline.lang.processes.ME', JLINE.from_line_matrix(line_dist.getParam(1).paramValue), JLINE.from_line_matrix(line_dist.getParam(2).paramValue));
745 elseif isa(line_dist, 'RAP')
746 jdist = javaObject('jline.lang.processes.RAP', JLINE.from_line_matrix(line_dist.getParam(1).paramValue), JLINE.from_line_matrix(line_dist.getParam(2).paramValue));
747 elseif isa(line_dist, 'MMDP2') % before MMDP (MMDP2 < MMDP)
748 jdist = javaObject('jline.lang.processes.MMDP2', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue, line_dist.getParam(3).paramValue, line_dist.getParam(4).paramValue);
749 elseif isa(line_dist, 'MMDP')
750 jdist = javaObject('jline.lang.processes.MMDP', JLINE.from_line_matrix(line_dist.getParam(1).paramValue), JLINE.from_line_matrix(line_dist.getParam(2).paramValue));
751 elseif isa(line_dist, 'Normal')
752 jdist = javaObject('jline.lang.processes.Normal', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
753 elseif isa(line_dist, 'Bernoulli')
754 jdist = javaObject('jline.lang.processes.Bernoulli', line_dist.getParam(1).paramValue);
755 elseif isa(line_dist, 'Geometric')
756 jdist = javaObject('jline.lang.processes.Geometric', line_dist.getParam(1).paramValue);
757 elseif isa(line_dist, 'Poisson')
758 jdist = javaObject('jline.lang.processes.Poisson', line_dist.getParam(1).paramValue);
759 elseif isa(line_dist, 'Binomial')
760 jdist = javaObject('jline.lang.processes.Binomial', int32(line_dist.getParam(1).paramValue), line_dist.getParam(2).paramValue);
761 elseif isa(line_dist, 'DiscreteUniform')
762 jdist = javaObject('jline.lang.processes.DiscreteUniform', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
763 elseif isa(line_dist, 'EmpiricalCDF')
764 % MATLAB stores data as [cdf, x]
column pairs;
the JAR two-argument
765 % constructor takes (cdfdata, xdata)
766 if size(line_dist.data, 2) >= 2
767 jdist = javaObject('jline.lang.processes.EmpiricalCDF', JLINE.from_line_matrix(line_dist.data(:,1)), JLINE.from_line_matrix(line_dist.data(:,2)));
769 jdist = javaObject('jline.lang.processes.EmpiricalCDF', JLINE.from_line_matrix(line_dist.data));
771 elseif isa(line_dist, 'PH')
772 alpha = line_dist.getParam(1).paramValue;
773 T = line_dist.getParam(2).paramValue;
774 jdist = javaObject('jline.lang.processes.PH', JLINE.from_line_matrix(alpha), JLINE.from_line_matrix(T));
775 elseif isa(line_dist, 'Uniform')
776 jdist = javaObject('jline.lang.processes.Uniform', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
777 elseif isa(line_dist, 'Weibull')
778 jdist = javaObject('jline.lang.processes.Weibull', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
779 elseif isa(line_dist, 'Zipf')
780 jdist = javaObject('jline.lang.processes.Zipf', line_dist.getParam(3).paramValue, line_dist.getParam(4).paramValue);
781 elseif isa(line_dist, 'Immediate')
782 jdist = javaObject('jline.lang.processes.Immediate');
783 elseif isempty(line_dist) || isa(line_dist, 'Disabled')
784 jdist = javaObject('jline.lang.processes.Disabled');
786 elseif isa(line_dist, 'Trace') % before Replayer (Trace < Replayer)
787 jdist = javaObject('jline.lang.processes.Trace', line_dist.params{1}.paramValue);
788 elseif isa(line_dist,
'Replayer')
789 jdist = javaObject('jline.lang.processes.Replayer', line_dist.params{1}.paramValue);
790 elseif isa(line_dist,
'Prior')
791 % Convert Prior: each alternative
is a distribution
792 dists = line_dist.getParam(1).paramValue;
793 probs = line_dist.getParam(2).paramValue;
794 jdists = java.util.ArrayList();
795 for k = 1:length(dists)
796 jdists.add(JLINE.from_line_distribution(dists{k}));
798 jdist = javaObject(
'jline.lang.processes.Prior', jdists, probs);
800 line_error(mfilename,
'Distribution not supported by JLINE.');
804 function [jRemDist, jRemPol] = from_line_signal_removal(line_class)
805 % FROM_LINE_SIGNAL_REMOVAL Marshal a signal
class's batch-removal
806 % distribution and removal policy. Returns empties when the class
807 % uses the defaults (remove exactly 1, RANDOM policy), so callers
808 % can keep using the short JAR constructors in that case.
811 if isprop(line_class, 'removalDistribution
') && ~isempty(line_class.removalDistribution) ...
812 && ~isa(line_class.removalDistribution, 'Disabled
')
813 jRemDist = JLINE.from_line_distribution(line_class.removalDistribution);
815 if isprop(line_class, 'removalPolicy
') && ~isempty(line_class.removalPolicy)
816 if ~isempty(jRemDist) || line_class.removalPolicy ~= RemovalPolicy.RANDOM
817 jRemPol = jline.lang.constant.RemovalPolicy.fromID(int32(line_class.removalPolicy));
819 elseif ~isempty(jRemDist)
820 jRemPol = jline.lang.constant.RemovalPolicy.RANDOM;
824 function matlab_dist = from_jline_distribution(jdist)
825 if isa(jdist, 'jline.lang.processes.Exp
')
826 matlab_dist = Exp(jdist.getRate());
827 elseif isa(jdist, 'jline.lang.processes.Det
')
828 matlab_dist = Det(jdist.getParam(1).getValue);
829 elseif isa(jdist, 'jline.lang.processes.Erlang
')
830 matlab_dist = Erlang(jdist.getParam(1).getValue(),jdist.getNumberOfPhases());
831 elseif isa(jdist, 'jline.lang.processes.Gamma
')
832 matlab_dist = Gamma(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
833 elseif isa(jdist, 'jline.lang.processes.HyperExp
')
834 matlab_dist = HyperExp(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue);
835 elseif isa(jdist, 'jline.lang.processes.Lognormal
')
836 matlab_dist = Lognormal(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
837 elseif isa(jdist, 'jline.lang.processes.Pareto
')
838 matlab_dist = Pareto(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
839 elseif isa(jdist, 'jline.lang.processes.Uniform
')
840 matlab_dist = Uniform(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
841 elseif isa(jdist, 'jline.lang.processes.Weibull
')
842 matlab_dist = Weibull(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
843 elseif isa(jdist, 'jline.lang.processes.MAP
')
844 D0 = JLINE.from_jline_matrix(jdist.D(0));
845 D1 = JLINE.from_jline_matrix(jdist.D(1));
846 matlab_dist = MAP({D0, D1});
847 elseif isa(jdist, 'jline.lang.processes.APH
')
848 alpha = JLINE.from_jline_matrix(jdist.getInitProb());
849 T = JLINE.from_jline_matrix(jdist.getSubgenerator());
850 matlab_dist = APH(alpha(:)', T);
851 elseif isa(jdist,
'jline.lang.processes.PH')
852 alpha = JLINE.from_jline_matrix(jdist.getInitProb());
853 T = JLINE.from_jline_matrix(jdist.getSubgenerator());
854 matlab_dist = PH(alpha(:)', T);
855 elseif isa(jdist, 'jline.lang.processes.Coxian')
856 if jdist.getNumberOfPhases == 2
857 matlab_dist = Coxian([jdist.getParam(1).getValue.get(0), jdist.getParam(1).getValue.get(1)], [jdist.getParam(2).getValue.get(0),1]);
859 jmu = jdist.getParam(1).getValue;
860 jphi = jdist.getParam(2).getValue;
861 mu = zeros(1, jmu.size);
862 phi = zeros(1, jphi.size);
864 mu(i) = jmu.get(i-1);
867 phi(i) = jphi.get(i-1);
869 matlab_dist = Coxian(mu, phi);
871 elseif isa(jdist, 'jline.lang.processes.Zipf')
872 matlab_dist = Zipf(jdist.getParam(3).getValue, jdist.getParam(4).getValue);
873 elseif isa(jdist, 'jline.lang.processes.DiscreteSampler')
874 jpMat = jdist.getParam(1).getValue;
875 jxMat = jdist.getParam(2).getValue;
876 p = zeros(1, jpMat.length);
877 x = zeros(1, jxMat.length);
878 for i = 1:jpMat.length
879 p(i) = jpMat.get(i-1);
881 for i = 1:jxMat.length
882 x(i) = jxMat.get(i-1);
884 matlab_dist = DiscreteSampler(p, x);
885 elseif isa(jdist, 'jline.lang.processes.Immediate')
886 matlab_dist = Immediate();
887 elseif isa(jdist, 'jline.lang.processes.Disabled')
888 matlab_dist = Disabled();
889 elseif isa(jdist, 'jline.lang.processes.MMPP2')
890 matlab_dist = MMPP2(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue, jdist.getParam(4).getValue);
891 elseif isa(jdist, 'jline.lang.processes.NHPP')
892 jBp = jdist.getBreakpoints();
893 jRates = jdist.getRates();
894 bp = zeros(1, length(jBp));
895 rates = zeros(1, length(jRates));
896 for k = 1:length(jBp)
899 for k = 1:length(jRates)
900 rates(k) = jRates(k);
902 matlab_dist = NHPP(bp, rates, logical(jdist.isCyclic()));
903 elseif isa(jdist, 'jline.lang.processes.Prior')
904 % Convert Prior from JAR to MATLAB
905 jdists = jdist.getDistributions();
906 nalt = jdists.size();
907 dists = cell(1, nalt);
909 dists{k} = JLINE.from_jline_distribution(jdists.get(k-1));
911 probs = jdist.getProbabilities();
912 matlab_dist = Prior(dists, probs);
913 elseif isa(jdist,
'jline.lang.processes.Normal')
914 matlab_dist = Normal(jdist.getParam(1).getValue, jdist.getParam(2).getValue);
915 elseif isa(jdist, 'jline.lang.processes.Bernoulli')
916 matlab_dist = Bernoulli(jdist.getParam(1).getValue);
917 elseif isa(jdist, 'jline.lang.processes.Geometric')
918 matlab_dist = Geometric(jdist.getParam(1).getValue);
919 elseif isa(jdist, 'jline.lang.processes.Poisson')
920 matlab_dist = Poisson(jdist.getParam(1).getValue);
921 elseif isa(jdist, 'jline.lang.processes.Binomial')
922 matlab_dist = Binomial(
double(jdist.getParam(1).getValue), jdist.getParam(2).getValue);
923 elseif isa(jdist, 'jline.lang.processes.DiscreteUniform')
924 matlab_dist = DiscreteUniform(jdist.getParam(1).getValue, jdist.getParam(2).getValue);
925 elseif isa(jdist, 'jline.lang.processes.EmpiricalCDF')
926 d = JLINE.from_jline_matrix(jdist.getData());
927 if size(d, 2) >= 2 % stored as [cdf, x]; MATLAB ctor
is (xdata, cdfdata)
928 matlab_dist = EmpiricalCDF(d(:,2), d(:,1));
930 matlab_dist = EmpiricalCDF(d);
932 elseif isa(jdist, 'jline.lang.processes.Trace') % before Replayer (Trace < Replayer)
933 v = jdist.getParam(1).getValue;
934 if isa(v, 'java.lang.String'), v =
char(v); end
935 matlab_dist = Trace(v);
936 elseif isa(jdist, 'jline.lang.processes.Replayer')
937 v = jdist.getParam(1).getValue;
938 if isa(v, 'java.lang.String'), v =
char(v); end
939 matlab_dist = Replayer(v);
940 elseif isa(jdist, 'jline.lang.processes.DMAP')
941 matlab_dist = DMAP(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
942 elseif isa(jdist, 'jline.lang.processes.ME')
943 matlab_dist = ME(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
944 elseif isa(jdist, 'jline.lang.processes.RAP')
945 matlab_dist = RAP(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
946 elseif isa(jdist, 'jline.lang.processes.MMDP2') % before MMDP (MMDP2 < MMDP)
947 matlab_dist = MMDP2(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue, jdist.getParam(4).getValue);
948 elseif isa(jdist, 'jline.lang.processes.MMDP')
949 matlab_dist = MMDP(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
950 elseif isa(jdist, 'jline.lang.processes.BMAP') % before MarkedMAP (BMAP < MarkedMAP)
951 % The JAR BMAP process cell
is in MarkedMAP layout
952 % {D0, D1_total, D1..DK};
the MATLAB BMAP constructor expects
953 %
the standard {D0, D1, ..., DK} and rebuilds D1_total itself
954 proc = jdist.getProcess();
957 D{1} = JLINE.from_jline_matrix(proc.get(0));
959 D{1+k} = JLINE.from_jline_matrix(proc.get(1+k));
961 matlab_dist = BMAP(D);
962 elseif isa(jdist,
'jline.lang.processes.MarkedMMPP')
963 proc = jdist.getProcess(); % {D0, D1, D11..D1K}
967 D{k} = JLINE.from_jline_matrix(proc.get(k-1));
969 matlab_dist = MarkedMMPP(D, K);
970 elseif isa(jdist,
'jline.lang.processes.MarkedMAP')
971 proc = jdist.getProcess(); % {D0, D1, D11..D1K}
975 D{k} = JLINE.from_jline_matrix(proc.get(k-1));
977 matlab_dist = MarkedMAP(D, K);
979 line_error(mfilename,
'Distribution not supported by JLINE.');
983 function set_csMatrix(line_node, jnode, jclasses)
984 nClasses = length(line_node.model.classes);
985 csMatrix = jnode.initClassSwitchMatrix();
988 csMatrix.set(jclasses{i}, jclasses{j}, line_node.server.csFun(i,j,0,0));
991 jnode.setClassSwitchingMatrix(csMatrix);
994 function set_service(line_node, jnode, job_classes)
995 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'))
999 for n = 1 : length(job_classes)
1000 if (isa(line_node,
'Queue') || isa(line_node,
'Delay'))
1001 matlab_dist = line_node.getService(job_classes{n});
1002 elseif (isa(line_node,
'Source'))
1003 matlab_dist = line_node.getArrivalProcess(job_classes{n});
1005 line_error(mfilename,
'Node not supported by JLINE.');
1007 service_dist = JLINE.from_line_distribution(matlab_dist);
1009 if (isa(line_node,
'Queue') || isa(line_node,
'Delay'))
1010 jnode.setService(jnode.getModel().getClasses().get(n-1), service_dist, line_node.schedStrategyPar(n));
1011 elseif (isa(line_node,
'Source'))
1012 jnode.setArrival(jnode.getModel().getClasses().get(n-1), service_dist);
1017 function set_delayoff(line_node, jnode, job_classes)
1018 % Transfer setup and delayoff times from MATLAB Queue to Java Queue
1019 if ~isa(line_node, 'Queue')
1023 % Check if setupTime property exists and
is not empty
1024 if ~isprop(line_node, 'setupTime') || isempty(line_node.setupTime)
1028 for n = 1 : length(job_classes)
1029 c = job_classes{n}.index;
1030 % Check
if both setupTime and delayoffTime are set
for this class
1031 if c <= length(line_node.setupTime) && ~isempty(line_node.setupTime{1, c}) && ...
1032 c <= length(line_node.delayoffTime) && ~isempty(line_node.delayoffTime{1, c})
1033 % Convert MATLAB distributions to Java distributions
1034 setup_dist = JLINE.from_line_distribution(line_node.setupTime{1, c});
1035 delayoff_dist = JLINE.from_line_distribution(line_node.delayoffTime{1, c});
1036 % Set delayoff on
the Java Queue
1037 jnode.setDelayOff(jnode.getModel().getClasses().get(n-1), setup_dist, delayoff_dist);
1042 function set_line_service(jline_node, line_node, job_classes, line_classes)
1043 if (isa(line_node,
'Sink')) || isa(line_node,
'ClassSwitch') || isa(line_node,
'Fork') || isa(line_node,
'Join') || isa(line_node,
'Place') || isa(line_node,
'Transition') || isa(line_node,
'Cache')
1046 for n = 1:job_classes.size()
1047 if (isa(line_node, 'Queue') || isa(line_node, 'Delay'))
1048 jdist = jline_node.getServiceProcess(job_classes.get(n-1));
1049 matlab_dist = JLINE.from_jline_distribution(jdist);
1050 weight = jline_node.getSchedStrategyPar(job_classes.get(n-1));
1051 line_node.setService(line_classes{n}, matlab_dist, weight);
1052 elseif (isa(line_node,
'Source'))
1053 jdist = jline_node.getArrivalProcess(job_classes.get(n-1));
1054 matlab_dist = JLINE.from_jline_distribution(jdist);
1055 line_node.setArrival(line_classes{n}, matlab_dist);
1056 elseif (isa(line_node,
'Router'))
1059 line_error(mfilename,'Node not supported by JLINE.');
1064 function node_object = from_line_node(line_node, jnetwork, ~, forkNode, sn)
1065 % Handle optional sn argument
1069 if isa(line_node,
'Delay')
1070 node_object = javaObject('jline.lang.
nodes.Delay', jnetwork, line_node.getName);
1071 elseif isa(line_node, 'Queue')
1072 switch line_node.schedStrategy
1073 case SchedStrategy.INF
1074 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.INF);
1075 case SchedStrategy.FCFS
1076 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFS);
1077 case SchedStrategy.LCFS
1078 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFS);
1079 case SchedStrategy.SIRO
1080 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SIRO);
1081 case SchedStrategy.SJF
1082 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SJF);
1083 case SchedStrategy.LJF
1084 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LJF);
1085 case SchedStrategy.PS
1086 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PS);
1087 case SchedStrategy.DPS
1088 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.DPS);
1089 case SchedStrategy.GPS
1090 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.GPS);
1091 case SchedStrategy.SEPT
1092 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SEPT);
1093 case SchedStrategy.LEPT
1094 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LEPT);
1095 case SchedStrategy.HOL
1096 % HOL (head-of-line, non-preemptive priority) maps to
the
1097 % JAR's HOL, which routes to
the exact M/G/1 priority
1098 % analyzer; collapsing it to FCFSPRIO would instead select
1099 %
the egflin priority approximation and diverge from
the
1100 % MATLAB-native result.
1101 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.HOL);
1102 case SchedStrategy.FCFSPRIO
1103 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPRIO);
1104 case SchedStrategy.FORK
1105 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FORK);
1106 case SchedStrategy.EXT
1107 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.EXT);
1108 case SchedStrategy.REF
1109 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.REF);
1110 case SchedStrategy.LCFSPR
1111 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPR);
1112 case SchedStrategy.LCFSPI
1113 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPI);
1114 case SchedStrategy.LCFSPRIO
1115 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPRIO);
1116 case SchedStrategy.LCFSPRPRIO
1117 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPRPRIO);
1118 case SchedStrategy.LCFSPIPRIO
1119 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPIPRIO);
1120 case SchedStrategy.FCFSPR
1121 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPR);
1122 case SchedStrategy.FCFSPI
1123 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPI);
1124 case SchedStrategy.FCFSPRPRIO
1125 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPRPRIO);
1126 case SchedStrategy.FCFSPIPRIO
1127 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPIPRIO);
1128 case SchedStrategy.PSPRIO
1129 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PSPRIO);
1130 case SchedStrategy.DPSPRIO
1131 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.DPSPRIO);
1132 case SchedStrategy.GPSPRIO
1133 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.GPSPRIO);
1134 case SchedStrategy.POLLING
1135 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.POLLING);
1136 case SchedStrategy.SRPT
1137 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SRPT);
1138 case SchedStrategy.SRPTPRIO
1139 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SRPTPRIO);
1140 case SchedStrategy.PSJF
1141 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PSJF);
1142 case SchedStrategy.FB
1143 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FB);
1144 case SchedStrategy.LRPT
1145 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LRPT);
1146 case SchedStrategy.EDD
1147 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.EDD);
1148 case SchedStrategy.EDF
1149 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.EDF);
1150 case SchedStrategy.LPS
1151 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LPS);
1152 case SchedStrategy.SETF
1153 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SETF);
1154 case SchedStrategy.FSP
1155 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FSP);
1156 case SchedStrategy.PAS
1157 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PAS);
1158 case SchedStrategy.OI
1159 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.OI);
1161 line_error(mfilename, sprintf('JLINE conversion does not support
the %s scheduling strategy yet.',
char(SchedStrategy.toText(line_node.schedStrategy))));
1163 nservers = line_node.getNumberOfServers;
1165 node_object.setNumberOfServers(java.lang.Integer.MAX_VALUE);
1167 node_object.setNumberOfServers(line_node.getNumberOfServers);
1169 if ~isempty(line_node.lldScaling)
1170 node_object.setLoadDependence(JLINE.from_line_matrix(line_node.lldScaling));
1172 if ~isempty(line_node.lcdScaling)
1174 line_error(mfilename, "Class-dependent models require sn struct for MATLAB-to-JAVA translation.");
1176 cdPeakJava = line_node.lcdScalingPeak;
1177 if isscalar(cdPeakJava)
1178 cdPeakJava = repmat(cdPeakJava, 1, sn.nclasses);
1180 node_object.setLimitedClassDependence(JLINE.handle_to_serializablefun(line_node.lcdScaling, sn), JLINE.from_line_matrix(cdPeakJava(:)'));
1182 % Set queue capacity if finite
1183 if ~isinf(line_node.cap)
1184 node_object.setCapacity(line_node.cap);
1186 % Transfer LPS job limit (stored in schedStrategyPar(1))
1187 if line_node.schedStrategy == SchedStrategy.LPS && ~isempty(line_node.schedStrategyPar) && line_node.schedStrategyPar(1) >= 1
1188 node_object.setLimit(int32(line_node.schedStrategyPar(1)));
1190 elseif isa(line_node, 'Source')
1191 node_object = javaObject('jline.lang.
nodes.Source', jnetwork, line_node.getName);
1192 elseif isa(line_node, 'Sink')
1193 node_object = javaObject('jline.lang.
nodes.Sink', jnetwork, line_node.getName);
1194 elseif isa(line_node, 'Router')
1195 node_object = javaObject('jline.lang.
nodes.Router', jnetwork, line_node.getName);
1196 elseif isa(line_node, 'ClassSwitch')
1197 node_object = javaObject('jline.lang.
nodes.ClassSwitch', jnetwork, line_node.getName);
1198 elseif isa(line_node, 'Fork')
1199 node_object = javaObject('jline.lang.
nodes.Fork', jnetwork, line_node.name);
1200 node_object.setTasksPerLink(line_node.output.tasksPerLink);
1201 elseif isa(line_node, 'Join')
1202 node_object = javaObject('jline.lang.
nodes.Join', jnetwork, line_node.name, forkNode);
1203 elseif isa(line_node, 'Logger')
1204 node_object = javaObject('jline.lang.
nodes.Logger', jnetwork, line_node.name, [line_node.filePath,line_node.fileName]);
1205 % Transfer
the output-field flags. MATLAB stores them as
1206 % 'true'/'false'
char;
the JAR booleans all default to false,
1207 % so transfer unconditionally to preserve MATLAB's defaults
1208 % (timestamp/jobID/jobClass enabled).
1209 node_object.setStartTime(strcmpi(
char(line_node.getStartTime), 'true'));
1210 node_object.setLoggerName(strcmpi(
char(line_node.getLoggerName), 'true'));
1211 node_object.setTimestamp(strcmpi(
char(line_node.getTimestamp), 'true'));
1212 node_object.setJobID(strcmpi(
char(line_node.getJobID), 'true'));
1213 node_object.setJobClass(strcmpi(
char(line_node.getJobClass), 'true'));
1214 node_object.setTimeSameClass(strcmpi(
char(line_node.getTimeSameClass), 'true'));
1215 node_object.setTimeAnyClass(strcmpi(
char(line_node.getTimeAnyClass), 'true'));
1216 elseif isa(line_node, 'Cache')
1217 nitems = line_node.items.nitems;
1218 switch line_node.replacestrategy
1219 case ReplacementStrategy.RR
1220 repStrategy = jline.lang.constant.ReplacementStrategy.RR;
1221 case ReplacementStrategy.FIFO
1222 repStrategy = jline.lang.constant.ReplacementStrategy.FIFO;
1223 case ReplacementStrategy.SFIFO
1224 repStrategy = jline.lang.constant.ReplacementStrategy.SFIFO;
1225 case ReplacementStrategy.LRU
1226 repStrategy = jline.lang.constant.ReplacementStrategy.LRU;
1228 if ~isempty(line_node.graph)
1229 % graph
is a per-item cell array of (h+1)x(h+1) matrices
1230 gcells = line_node.graph;
1231 if ~iscell(gcells), gcells = {gcells}; end
1232 jGraph = javaArray(
'jline.util.matrix.Matrix', numel(gcells));
1233 for gidx = 1:numel(gcells)
1234 jGraph(gidx) = JLINE.from_line_matrix(gcells{gidx});
1236 node_object = javaObject(
'jline.lang.nodes.Cache', jnetwork, line_node.name, nitems, JLINE.from_line_matrix(line_node.itemLevelCap), repStrategy, jGraph);
1238 node_object = javaObject(
'jline.lang.nodes.Cache', jnetwork, line_node.name, nitems, JLINE.from_line_matrix(line_node.itemLevelCap), repStrategy);
1240 elseif isa(line_node,
'Place')
1241 if line_node.isQueueing()
1242 % Queueing place: reconstruct with its scheduling strategy so
1243 %
the JAR installs
the matching embedded-queue server section
1244 % when setService
is marshalled (see from_line_network).
1245 jsched = jline.lang.constant.SchedStrategy.fromText(SchedStrategy.toText(line_node.schedStrategy));
1246 node_object = javaObject('jline.lang.
nodes.Place', jnetwork, line_node.getName, jsched);
1248 node_object = javaObject('jline.lang.
nodes.Place', jnetwork, line_node.getName);
1250 elseif isa(line_node, 'Transition')
1251 node_object = javaObject('jline.lang.
nodes.Transition', jnetwork, line_node.getName);
1252 % Modes are added later in from_line_network after classes are created
1254 line_error(mfilename,'Node not supported by JLINE.');
1258 function node_object = from_jline_node(jline_node, model, job_classes)
1259 if isa(jline_node, 'jline.lang.
nodes.Delay')
1260 node_object = Delay(model, jline_node.getName.toCharArray');
1261 elseif isa(jline_node, 'jline.lang.
nodes.Queue')
1262 schedStrategy = jline_node.getSchedStrategy;
1263 switch schedStrategy.name().toCharArray'
1265 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.INF);
1267 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFS);
1269 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFS);
1271 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SIRO);
1273 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SJF);
1275 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LJF);
1277 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.PS);
1279 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.DPS);
1281 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.GPS);
1283 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SEPT);
1285 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LEPT);
1286 case {
'HOL',
'FCFSPRIO'}
1287 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FCFSPRIO);
1289 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FORK);
1291 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.EXT);
1293 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.REF);
1295 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LCFSPR);
1297 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SRPT);
1299 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.SRPTPRIO);
1301 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.PSJF);
1303 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FB);
1305 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LRPT);
1307 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.PSPRIO);
1309 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.DPSPRIO);
1311 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.GPSPRIO);
1313 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPI);
1315 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LCFSPRIO);
1317 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPRPRIO);
1319 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LCFSPIPRIO);
1321 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPR);
1323 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FCFSPI);
1325 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPRPRIO);
1327 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FCFSPIPRIO);
1329 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.POLLING);
1331 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.EDD);
1333 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.EDF);
1335 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LPS);
1337 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SETF);
1339 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FSP);
1341 % The PAS service rate function mu(c) lives in a Java
1342 % SerializableFunction and cannot be reconstructed as a
1344 line_error(mfilename, 'JLINE-to-LINE conversion does not support PAS queues (service rate function not recoverable).
');
1346 line_error(mfilename, sprintf('JLINE-to-LINE conversion does not support
the %s scheduling strategy yet.
', char(schedStrategy.name())));
1348 node_object.setNumberOfServers(jline_node.getNumberOfServers);
1349 cap = jline_node.getCap();
1350 if cap < intmax && cap > 0
1351 node_object.setCapacity(cap);
1353 if ~isempty(JLINE.from_jline_matrix(jline_node.getLimitedLoadDependence))
1354 node_object.setLoadDependence(JLINE.from_jline_matrix(jline_node.getLimitedLoadDependence));
1356 elseif isa(jline_node, 'jline.lang.nodes.Source
')
1357 node_object = Source(model, jline_node.getName.toCharArray');
1358 elseif isa(jline_node,
'jline.lang.nodes.Sink')
1359 node_object = Sink(model, jline_node.getName.toCharArray');
1360 elseif isa(jline_node, 'jline.lang.
nodes.Router')
1361 node_object = Router(model, jline_node.getName.toCharArray');
1362 elseif isa(jline_node, 'jline.lang.
nodes.ClassSwitch')
1363 nClasses = job_classes.size;
1364 csMatrix = zeros(nClasses, nClasses);
1367 csMatrix(r,s) = jline_node.getServer.applyCsFun(r-1,s-1);
1370 node_object = ClassSwitch(model, jline_node.getName.toCharArray', csMatrix);
1371 elseif isa(jline_node, 'jline.lang.
nodes.Cache')
1372 numItems = jline_node.getNumberOfItems();
1373 itemLevelCap = JLINE.from_jline_matrix(jline_node.getItemLevelCap());
1374 replPolicy = jline_node.getReplacementStrategy();
1375 switch
char(replPolicy)
1377 rp = ReplacementStrategy.LRU;
1379 rp = ReplacementStrategy.FIFO;
1381 rp = ReplacementStrategy.RR;
1383 rp = ReplacementStrategy.LRU;
1385 node_object = Cache(model, jline_node.getName.toCharArray', numItems, itemLevelCap, rp);
1386 % hitClass, missClass, and popularity set later in jline_to_line
1387 elseif isa(jline_node, 'jline.lang.
nodes.Fork')
1388 node_object = Fork(model, jline_node.getName.toCharArray');
1389 tpl = jline_node.getOutput().tasksPerLink;
1391 node_object.setTasksPerLink(tpl);
1393 elseif isa(jline_node, 'jline.lang.
nodes.Join')
1394 node_object = Join(model, jline_node.getName.toCharArray');
1395 % joinOf
is set later in jline_to_line after all
nodes are created
1396 elseif isa(jline_node, 'jline.lang.
nodes.Place')
1397 node_object = Place(model, jline_node.getName.toCharArray');
1398 elseif isa(jline_node, 'jline.lang.
nodes.Transition')
1399 node_object = Transition(model, jline_node.getName.toCharArray');
1400 % Note: Mode configurations need to be set after classes are created
1402 line_error(mfilename,'Node not supported by JLINE.');
1406 function node_class = from_line_class(line_class, jnetwork)
1407 % Check signal classes first (before their base classes)
1408 if isa(line_class, 'ClosedSignal')
1409 % ClosedSignal -> jline.lang.ClosedSignal
1410 jSignalType = jline.lang.constant.SignalType.fromID(line_class.signalType);
1411 [jRemDist, jRemPol] = JLINE.from_line_signal_removal(line_class);
1412 if isempty(jRemDist) && isempty(jRemPol)
1413 node_class = javaObject('jline.lang.ClosedSignal', jnetwork, line_class.getName, jSignalType, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1415 node_class = javaObject('jline.lang.ClosedSignal', jnetwork, line_class.getName, jSignalType, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority, jRemDist, jRemPol);
1417 elseif isa(line_class, 'Signal') || isa(line_class, 'OpenSignal')
1418 % Signal/OpenSignal -> jline.lang.Signal (includes CATASTROPHE type)
1419 jSignalType = jline.lang.constant.SignalType.fromID(line_class.signalType);
1420 [jRemDist, jRemPol] = JLINE.from_line_signal_removal(line_class);
1421 if isempty(jRemDist) && isempty(jRemPol)
1422 node_class = javaObject('jline.lang.Signal', jnetwork, line_class.getName, jSignalType, line_class.priority);
1424 node_class = javaObject('jline.lang.Signal', jnetwork, line_class.getName, jSignalType, line_class.priority, jRemDist, jRemPol);
1426 elseif isa(line_class, 'OpenClass')
1427 node_class = javaObject('jline.lang.OpenClass', jnetwork, line_class.getName, line_class.priority);
1428 elseif isa(line_class, 'SelfLoopingClass')
1429 node_class = javaObject('jline.lang.SelfLoopingClass', jnetwork, line_class.getName, line_class.population, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1430 elseif isa(line_class, 'ClosedClass')
1431 node_class = javaObject('jline.lang.ClosedClass', jnetwork, line_class.getName, line_class.population, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1433 line_error(mfilename,'Class type not supported by JLINE.');
1435 % Transfer relative deadline (used by EDD/EDF scheduling)
1436 if isprop(line_class, 'deadline') && ~isempty(line_class.deadline) && ~isinf(line_class.deadline)
1437 node_class.setDeadline(line_class.deadline);
1439 if line_class.isReferenceClass()
1440 node_class.setReferenceClass(true);
1444 function node_class = from_jline_class(jclass, model)
1445 % Check signal classes first (their base classes would match below)
1446 if isa(jclass, 'jline.lang.ClosedSignal')
1447 [remDist, remPol] = JLINE.from_jline_signal_removal(jclass);
1448 node_class = ClosedSignal(model, jclass.getName.toCharArray', jclass.getSignalType().getID(), model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority, remDist, remPol);
1449 elseif isa(jclass, 'jline.lang.OpenSignal')
1450 node_class = OpenSignal(model, jclass.getName.toCharArray', jclass.getSignalType().getID(), jclass.getPriority);
1451 elseif isa(jclass, 'jline.lang.Signal')
1452 [remDist, remPol] = JLINE.from_jline_signal_removal(jclass);
1453 node_class = Signal(model, jclass.getName.toCharArray', jclass.getSignalType().getID(), jclass.getPriority, remDist, remPol);
1454 elseif isa(jclass, 'jline.lang.OpenClass')
1455 node_class = OpenClass(model, jclass.getName.toCharArray', jclass.getPriority);
1456 elseif isa(jclass, 'jline.lang.SelfLoopingClass')
1457 node_class = SelfLoopingClass(model, jclass.getName.toCharArray', jclass.getNumberOfJobs, model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority);
1458 elseif isa(jclass, 'jline.lang.ClosedClass')
1459 node_class = ClosedClass(model, jclass.getName.toCharArray', jclass.getNumberOfJobs, model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority);
1461 line_error(mfilename,'Class type not supported by JLINE.');
1463 % Transfer relative deadline (used by EDD/EDF scheduling)
1464 dl = jclass.getDeadline();
1466 node_class.deadline = dl;
1470 function [remDist, remPol] = from_jline_signal_removal(jclass)
1471 % FROM_JLINE_SIGNAL_REMOVAL Read back a JAR signal's batch-removal
1472 % distribution and policy for
the MATLAB signal constructors.
1473 jRemDist = jclass.getRemovalDistribution();
1474 if isempty(jRemDist)
1477 remDist = JLINE.from_jline_distribution(jRemDist);
1479 jRemPol = jclass.getRemovalPolicy();
1481 remPol = RemovalPolicy.RANDOM;
1483 remPol = jRemPol.getID();
1487 function from_line_links(model, jmodel)
1488 connections = model.getConnectionMatrix();
1489 [m, ~] = size(connections);
1490 jnodes = jmodel.getNodes();
1491 jclasses = jmodel.getClasses();
1492 njclasses = jclasses.size();
1493 line_nodes = model.getNodes;
1494 sn = model.getStruct;
1496 % Build mapping from MATLAB node index to Java node index
1497 % (accounting for skipped auto-added ClassSwitch
nodes)
1498 matlab2java_node_idx = zeros(1, length(line_nodes));
1500 for i = 1:length(line_nodes)
1501 if isa(line_nodes{i},
'ClassSwitch') && line_nodes{i}.autoAdded
1502 matlab2java_node_idx(i) = -1; % Mark as skipped
1504 matlab2java_node_idx(i) = jidx;
1510 % [ ] Update to consider different weights/routing
for classes
1511 if isempty(sn.rtorig)
1512 useLinkMethod = false; % this model did not call link()
1514 jrt_matrix = jmodel.initRoutingMatrix();
1515 useLinkMethod = true;
1518 % For models with auto-added ClassSwitch
nodes, use sn.rtorig directly
1519 % to set up routing with proper class switching
1521 for i = 1:length(line_nodes)
1522 if isa(line_nodes{i},
'ClassSwitch') && line_nodes{i}.autoAdded
1528 if useLinkMethod && hasAutoCS
1529 % Use sn.rtorig directly - it contains
the full routing with class switching
1530 % sn.rtorig already excludes auto-added ClassSwitch
nodes (it's based on nstations)
1531 % So we iterate over
the rtorig matrix dimensions directly
1534 if ~isempty(sn.rtorig{r,s})
1535 Prs = sn.rtorig{r,s};
1536 [nrows, ncols] = size(Prs);
1540 % sn.rtorig uses station indices which
map to non-CS
nodes
1541 % Find
the java node indices by matching station index to node
1542 jsrc_idx = i - 1; % Direct mapping since rtorig excludes CS
1544 jrt_matrix.set(jclasses.get(r-1), jclasses.get(s-1), jnodes.get(jsrc_idx), jnodes.get(jdest_idx), Prs(i,j));
1552 % Original logic
for models without
auto-added ClassSwitch
1554 line_node = line_nodes{i};
1556 % Skip
auto-added ClassSwitch
nodes - Java will add them automatically
1557 if isa(line_node, 'ClassSwitch') && line_node.autoAdded
1561 jnode_idx = matlab2java_node_idx(i);
1563 output_strat = line_node.output.outputStrategy{k};
1564 switch RoutingStrategy.fromText(output_strat{2})
1565 case RoutingStrategy.DISABLED
1566 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1567 case RoutingStrategy.RAND
1568 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RAND);
1569 outlinks_i=find(connections(i,:));
1571 % Do NOT add routing matrix entries
for RAND routing.
1572 % JAR
's getRoutingMatrix computes RAND routing from
1573 % the connection matrix (matching MATLAB behavior).
1574 % Adding entries would cause link() to convert RAND
1575 % to PROB, and for closed classes would incorrectly
1576 % include Sink connections.
1578 for j= outlinks_i(:)'
1579 jdest_idx = matlab2java_node_idx(j);
1581 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1585 case RoutingStrategy.RROBIN
1586 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RROBIN);
1587 outlinks_i=find(connections(i,:))
';
1589 line_error(mfilename,'RROBIN cannot be used together with
the link() command.
');
1591 for j= outlinks_i(:)'
1592 jdest_idx = matlab2java_node_idx(j);
1594 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1597 case RoutingStrategy.WRROBIN
1598 outlinks_i=find(connections(i,:))
';
1599 for j= outlinks_i(:)'
1600 jdest_idx = matlab2java_node_idx(j);
1602 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1606 line_error(mfilename,
'RROBIN cannot be used together with the link() command.');
1608 for j= 1:length(output_strat{3})
1609 node_target = jmodel.getNodeByName(output_strat{3}{j}{1}.getName());
1610 weight = output_strat{3}{j}{2};
1611 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.WRROBIN, node_target, weight);
1613 case RoutingStrategy.PROB
1614 outlinks_i=find(connections(i,:));
1615 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1), jline.lang.constant.RoutingStrategy.PROB);
1617 for j= outlinks_i(:)
'
1618 jdest_idx = matlab2java_node_idx(j);
1620 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1624 if length(output_strat) >= 3
1625 probabilities = output_strat{3};
1626 for j = 1:length(probabilities)
1627 dest_idx = probabilities{j}{1}.index;
1628 jdest_idx = matlab2java_node_idx(dest_idx);
1629 if (connections(i, dest_idx) ~= 0) && jdest_idx >= 0
1631 jrt_matrix.set(jclasses.get(k-1), jclasses.get(k-1), jnodes.get(jnode_idx), jnodes.get(jdest_idx), probabilities{j}{2});
1633 jnodes.get(jnode_idx).setProbRouting(jclasses.get(k-1), jnodes.get(jdest_idx), probabilities{j}{2});
1638 case RoutingStrategy.JSQ
1639 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.JSQ);
1640 outlinks_i=find(connections(i,:))';
1642 for j= outlinks_i(:)
'
1643 jdest_idx = matlab2java_node_idx(j);
1645 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1649 case RoutingStrategy.KCHOICES
1650 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.KCHOICES);
1651 if length(output_strat) >= 3 && length(output_strat{3}) >= 2
1652 kparam = output_strat{3}{1};
1653 memparam = logical(output_strat{3}{2});
1654 jnodes.get(jnode_idx).setKChoicesRouting(jclasses.get(k-1), int32(kparam), memparam);
1656 outlinks_i=find(connections(i,:))';
1658 for j= outlinks_i(:)
'
1659 jdest_idx = matlab2java_node_idx(j);
1661 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1665 case RoutingStrategy.RL
1666 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RL);
1667 outlinks_i=find(connections(i,:))';
1669 for j= outlinks_i(:)
'
1670 jdest_idx = matlab2java_node_idx(j);
1672 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1676 % Forward the value function, action nodes, and
1677 % state size from outputStrategy{r}{3..5} so the
1678 % JAR sub_rl can replicate MATLAB's decisions.
1679 if length(output_strat) >= 5
1680 valFnRaw = output_strat{3};
1681 nodesNeedAction = output_strat{4};
1682 stateSize = output_strat{5};
1683 if ~isempty(valFnRaw)
1685 % Tabular: flatten N-D array to a row vector and pass shape.
1686 shp = size(valFnRaw);
1687 jvfFlat = jline.util.matrix.Matrix(1, numel(valFnRaw));
1689 for f = 1:numel(flat)
1690 jvfFlat.set(0, f-1,
double(flat(f)));
1692 jshape = int32(shp(:)
');
1693 jnna = int32(nodesNeedAction(:)' - 1); % MATLAB->Java 0-based
1694 jnodes.get(jnode_idx).setRLRouting(jclasses.get(k-1), jvfFlat, jshape, jnna, int32(stateSize));
1696 % Linear approx: coefficient row vector.
1697 coeff = valFnRaw(:)
';
1698 jvf = jline.util.matrix.Matrix(1, numel(coeff));
1699 for f = 1:numel(coeff)
1700 jvf.set(0, f-1, double(coeff(f)));
1702 jnna = int32(nodesNeedAction(:)' - 1);
1703 jnodes.get(jnode_idx).setRLRouting(jclasses.get(k-1), jvf, int32([]), jnna, int32(stateSize));
1708 line_warning(mfilename, sprintf(
'''%s
'' routing strategy not supported by JLINE, setting as Disabled.\n
',output_strat{2}));
1709 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1715 jmodel.link(jrt_matrix);
1716 % Align the sn.rtorig be the same, treating artificial
1717 % ClassSwitch nodes as if they were explicitly specified
1718 jsn = jmodel.getStruct(true);
1719 rtorig = java.util.HashMap();
1720 if ~isempty(model.sn.rtorig)
1721 if iscell(model.sn.rtorig)
1723 sub_rtorig = java.util.HashMap();
1725 sub_rtorig.put(jclasses.get(s-1), JLINE.from_line_matrix(model.sn.rtorig{r,s}));
1727 rtorig.put(jclasses.get(r-1), sub_rtorig);
1731 jsn.rtorig = rtorig;
1735 function model = from_jline_routing(model, jnetwork)
1736 jnodes = jnetwork.getNodes();
1737 jclasses = jnetwork.getClasses();
1738 n_nodes = jnodes.size();
1739 network_nodes = model.getNodes;
1740 network_classes = model.getClasses;
1742 % Build name-to-MATLAB-node map (JAR and MATLAB may order nodes differently)
1743 node_by_name = containers.Map();
1744 for nn = 1:length(network_nodes)
1745 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1748 connections = JLINE.from_jline_matrix(jnetwork.getConnectionMatrix());
1749 [row,col] = find(connections);
1751 from_name = char(jnodes.get(row(i)-1).getName());
1752 to_name = char(jnodes.get(col(i)-1).getName());
1753 model.addLink(node_by_name(from_name), node_by_name(to_name));
1757 jnode = jnodes.get(n-1);
1758 cur_node = node_by_name(char(jnode.getName()));
1759 output_strategies = jnode.getOutputStrategies();
1760 n_strategies = output_strategies.size();
1761 for m = 1 : n_strategies
1762 output_strat = output_strategies.get(m-1);
1763 routing_strat = output_strat.getRoutingStrategy;
1764 routing_strat_classidx = output_strat.getJobClass.getIndex();
1765 switch char(routing_strat)
1767 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RAND);
1769 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1771 dest = output_strat.getDestination();
1773 dest_name = char(dest.getName());
1774 if node_by_name.isKey(dest_name)
1775 weight = output_strat.getProbability();
1776 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1780 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.DISABLED);
1786 function model = from_jline_links(model, jnetwork)
1787 P = model.initRoutingMatrix;
1788 jnodes = jnetwork.getNodes();
1789 jclasses = jnetwork.getClasses();
1790 n_classes = jclasses.size();
1791 n_nodes = jnodes.size();
1792 network_nodes = model.getNodes;
1794 % Build JAR-to-MATLAB node index mapping (node orders may differ)
1795 jar2ml = zeros(1, n_nodes);
1797 jar_name = char(jnodes.get(jj-1).getName());
1798 for mm = 1:length(network_nodes)
1799 if strcmp(network_nodes{mm}.name, jar_name)
1806 hasDestinations = false;
1808 jnode = jnodes.get(n-1);
1809 output_strategies = jnode.getOutputStrategies();
1810 n_strategies = output_strategies.size();
1811 for m = 1 : n_strategies
1812 output_strat = output_strategies.get(m-1);
1813 dest = output_strat.getDestination();
1814 if~isempty(dest) % disabled strategy
1815 hasDestinations = true;
1816 in_idx = jar2ml(jnetwork.getNodeIndex(jnode)+1);
1817 out_idx = jar2ml(jnetwork.getNodeIndex(dest)+1);
1819 P{1}(in_idx,out_idx) = output_strat.getProbability();
1821 strat_class = output_strat.getJobClass();
1822 class_idx = jnetwork.getJobClassIndex(strat_class)+1;
1823 P{class_idx,class_idx}(in_idx,out_idx) = output_strat.getProbability();
1829 % If no OutputStrategy entries had destinations (e.g., model
1830 % loaded from JSON via LineModelIO.load), fall back to rtorig
1832 sn = jnetwork.getStruct;
1833 if ~isempty(sn.rtorig)
1834 % rtorig is station-indexed (no permutation needed —
1835 % station ordering matches between JAR and MATLAB)
1838 rtMat = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1849 % Restore non-PROB routing strategies (RROBIN, WRROBIN, etc.)
1850 % after link(), which sets all routing to PROB
1851 network_nodes = model.getNodes;
1852 network_classes = model.getClasses;
1853 node_by_name = containers.Map();
1854 for nn = 1:length(network_nodes)
1855 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1858 jnode = jnodes.get(n-1);
1859 cur_node = node_by_name(char(jnode.getName()));
1860 output_strategies = jnode.getOutputStrategies();
1861 n_strategies = output_strategies.size();
1862 for m = 1 : n_strategies
1863 output_strat = output_strategies.get(m-1);
1864 routing_strat = output_strat.getRoutingStrategy;
1865 routing_strat_classidx = output_strat.getJobClass.getIndex();
1866 switch char(routing_strat)
1868 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1870 dest = output_strat.getDestination();
1872 dest_name = char(dest.getName());
1873 if node_by_name.isKey(dest_name)
1874 % Clear stale PROB entries before first WRROBIN weight
1875 classIdx = routing_strat_classidx;
1876 if length(cur_node.output.outputStrategy) >= classIdx && ...
1877 length(cur_node.output.outputStrategy{1, classIdx}) >= 3
1878 curStrat = cur_node.output.outputStrategy{1, classIdx}{2};
1879 if ~strcmp(curStrat, 'WeightedRoundRobin
')
1880 cur_node.output.outputStrategy{1, classIdx}{3} = {};
1883 weight = output_strat.getProbability();
1884 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1891 % Invalidate cached struct after modifying routing strategies
1892 model.resetStruct();
1894 %Align the sn.rtorig be the same (Assume Java network is
1895 %created by calling Network.link)
1896 sn = jnetwork.getStruct;
1897 rtorig = cell(n_classes, n_classes);
1900 rtorig{r,s} = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1903 model.sn.rtorig = rtorig;
1906 function [jnetwork] = from_line_network(model)
1909 sn = model.getStruct;
1911 jnetwork = javaObject('jline.lang.Network
', model.getName);
1912 line_nodes = model.getNodes;
1913 line_classes = model.getClasses;
1915 jnodes = cell(1,length(line_nodes));
1916 jclasses = cell(1,length(line_classes));
1918 for n = 1 : length(line_nodes)
1919 % Skip auto-added ClassSwitch nodes - Java's link() will add them automatically
1920 if isa(line_nodes{n},
'ClassSwitch') && line_nodes{n}.autoAdded
1923 if isa(line_nodes{n},
'Join')
1924 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, jnodes{line_nodes{n}.joinOf.index}, sn);
1926 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, [], sn);
1930 for n = 1 : length(line_classes)
1931 jclasses{n} = JLINE.from_line_class(line_classes{n}, jnetwork);
1934 % Set up forJobClass associations
for signal classes
1935 for n = 1 : length(line_classes)
1936 if (isa(line_classes{n},
'Signal') || isa(line_classes{n},
'OpenSignal') || isa(line_classes{n},
'ClosedSignal'))
1937 if ~isempty(line_classes{n}.targetJobClass)
1938 targetIdx = line_classes{n}.targetJobClass.index;
1939 jclasses{n}.forJobClass(jclasses{targetIdx});
1944 for n = 1: length(jnodes)
1945 if isempty(jnodes{n})
1946 continue; % Skip
nodes that were not converted (e.g.,
auto-added ClassSwitch)
1948 JLINE.set_service(line_nodes{n}, jnodes{n}, line_classes);
1949 JLINE.set_delayoff(line_nodes{n}, jnodes{n}, line_classes);
1952 % Set drop rules
for stations (after classes are created)
1953 for n = 1: length(jnodes)
1954 if isempty(jnodes{n})
1955 continue; % Skip
nodes that were not converted
1957 if isa(line_nodes{n},
'Station') && ~isa(line_nodes{n},
'Source')
1958 for r = 1:length(line_classes)
1959 if length(line_nodes{n}.dropRule) >= r && ~isempty(line_nodes{n}.dropRule(r))
1960 dropRule = line_nodes{n}.dropRule(r);
1962 case DropStrategy.DROP
1963 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.Drop);
1964 case DropStrategy.BAS
1965 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.BlockingAfterService);
1966 case DropStrategy.BBS
1967 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.BlockingBeforeService);
1968 case DropStrategy.RSRD
1969 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.ReServiceOnRejection);
1970 % WAITQ (-1)
is MATLAB's universal default drop rule
1971 % for every station-class pair, not a user request.
1972 % The JAR treats an absent (null) drop rule as
the
1973 % same waiting-queue default, and its refreshCapacity
1974 % guard rejects an EXPLICIT setDropRule(WAITQ) at a
1975 % finite buffer for an open class. Marshalling
the
1976 % default WAITQ
explicitly would fabricate that user
1977 % intent and make
the guard misfire on
the derived
1978 % classCap=0 that an unserved open class carries
1979 % (e.g. InitClass at Delay1, Class1 at Queue1). So do
1980 % not transfer WAITQ: only
the genuine blocking/loss
1981 % policies above carry user intent.
1985 % Transfer per-class capacity limits (setChainCapacity/classCap)
1986 if ~isempty(line_nodes{n}.classCap)
1987 for r = 1:min(length(line_classes), length(line_nodes{n}.classCap))
1988 if isfinite(line_nodes{n}.classCap(r)) && line_nodes{n}.classCap(r) >= 0
1989 jnodes{n}.setClassCap(jclasses{r}, int32(line_nodes{n}.classCap(r)));
1996 % Set polling type and switchover times
for polling queues
1997 for n = 1: length(jnodes)
1998 if isempty(jnodes{n})
2001 if isa(line_nodes{n},
'Queue') && line_nodes{n}.schedStrategy == SchedStrategy.POLLING
2003 if ~isempty(line_nodes{n}.pollingType) && ~isempty(line_nodes{n}.pollingType{1})
2004 pollingType = line_nodes{n}.pollingType{1};
2006 case PollingType.GATED
2007 jPollingType = jline.lang.constant.PollingType.GATED;
2008 case PollingType.EXHAUSTIVE
2009 jPollingType = jline.lang.constant.PollingType.EXHAUSTIVE;
2010 case PollingType.KLIMITED
2011 jPollingType = jline.lang.constant.PollingType.KLIMITED;
2012 case PollingType.DECREMENTING
2013 jPollingType = jline.lang.constant.PollingType.DECREMENTING;
2015 line_error(mfilename, sprintf(
'Unsupported polling type for the Java backend: %d.', PollingType.toId(pollingType)));
2017 if pollingType == PollingType.KLIMITED && ~isempty(line_nodes{n}.pollingPar)
2018 jnodes{n}.setPollingType(jPollingType, int32(line_nodes{n}.pollingPar));
2020 jnodes{n}.setPollingType(jPollingType);
2023 % Set switchover times
2024 if ~isempty(line_nodes{n}.switchoverTime)
2025 for r = 1:length(line_classes)
2026 if length(line_nodes{n}.switchoverTime) >= r && ~isempty(line_nodes{n}.switchoverTime{r})
2027 soTime = line_nodes{n}.switchoverTime{r};
2028 if ~isa(soTime,
'Immediate')
2029 jnodes{n}.setSwitchover(jclasses{r}, JLINE.from_line_distribution(soTime));
2037 % Transfer impatience features (reneging, balking, retrial)
for queues
2038 % These require classes to be created first.
2039 for n = 1: length(jnodes)
2040 if isempty(jnodes{n})
2043 if ~isa(line_nodes{n},
'Queue')
2046 % Immediate feedback (self-looping jobs stay in service): either
2047 %
'all' or a cell array of class indices on
the MATLAB side
2048 if ~isempty(line_nodes{n}.immediateFeedback)
2049 if ischar(line_nodes{n}.immediateFeedback)
2050 jnodes{n}.setImmediateFeedback(true);
2051 elseif iscell(line_nodes{n}.immediateFeedback)
2052 for fbc = 1:length(line_nodes{n}.immediateFeedback)
2053 jnodes{n}.setImmediateFeedback(jclasses{line_nodes{n}.immediateFeedback{fbc}});
2057 for r = 1:length(line_classes)
2058 % Reneging (timer-based patience). Only RENEGING
is supported;
2059 % BALKING via setPatience
is rejected by both MATLAB and
the JAR.
2060 if ~isempty(line_nodes{n}.patienceDistributions) && ...
2061 r <= length(line_nodes{n}.patienceDistributions) && ...
2062 ~isempty(line_nodes{n}.patienceDistributions{1, r})
2063 patDist = line_nodes{n}.patienceDistributions{1, r};
2064 if ~isa(patDist,
'Disabled')
2065 impType = ImpatienceType.RENEGING;
2066 if ~isempty(line_nodes{n}.impatienceTypes) && ...
2067 r <= length(line_nodes{n}.impatienceTypes) && ...
2068 ~isempty(line_nodes{n}.impatienceTypes{1, r})
2069 impType = line_nodes{n}.impatienceTypes{1, r};
2071 jImpType = jline.lang.constant.ImpatienceType.fromID(int32(impType));
2072 jnodes{n}.setPatience(jclasses{r}, jImpType, JLINE.from_line_distribution(patDist));
2075 % Balking (state-based, queue-length/expected-wait thresholds)
2076 if ~isempty(line_nodes{n}.balkingStrategies) && ...
2077 r <= length(line_nodes{n}.balkingStrategies) && ...
2078 ~isempty(line_nodes{n}.balkingStrategies{1, r})
2079 balkStrat = line_nodes{n}.balkingStrategies{1, r};
2081 case BalkingStrategy.QUEUE_LENGTH
2082 jBalkStrat = jline.lang.constant.BalkingStrategy.QUEUE_LENGTH;
2083 case BalkingStrategy.EXPECTED_WAIT
2084 jBalkStrat = jline.lang.constant.BalkingStrategy.EXPECTED_WAIT;
2085 case BalkingStrategy.COMBINED
2086 jBalkStrat = jline.lang.constant.BalkingStrategy.COMBINED;
2088 jBalkStrat = jline.lang.constant.BalkingStrategy.QUEUE_LENGTH;
2090 thresholds = line_nodes{n}.balkingThresholds{1, r};
2091 jThresholds = java.util.ArrayList();
2092 for ti = 1:length(thresholds)
2093 th = thresholds{ti};
2097 maxJobs = java.lang.Integer.MAX_VALUE;
2099 jThresholds.add(javaObject(
'jline.lang.constant.BalkingThreshold', int32(minJobs), int32(maxJobs), th{3}));
2101 jnodes{n}.setBalking(jclasses{r}, jBalkStrat, jThresholds);
2103 % Retrial (orbit + retrial delay distribution)
2104 if ~isempty(line_nodes{n}.retrialDelays) && ...
2105 r <= length(line_nodes{n}.retrialDelays) && ...
2106 ~isempty(line_nodes{n}.retrialDelays{1, r})
2107 retDist = line_nodes{n}.retrialDelays{1, r};
2108 if ~isa(retDist,
'Disabled')
2110 if ~isempty(line_nodes{n}.retrialMaxAttempts) && r <= length(line_nodes{n}.retrialMaxAttempts)
2111 maxAttempts = line_nodes{n}.retrialMaxAttempts(r);
2113 jnodes{n}.setRetrial(jclasses{r}, JLINE.from_line_distribution(retDist), int32(maxAttempts));
2116 % Orbit impatience (abandonment from
the retrial orbit)
2117 if ~isempty(line_nodes{n}.orbitImpatienceDistributions) && ...
2118 r <= length(line_nodes{n}.orbitImpatienceDistributions) && ...
2119 ~isempty(line_nodes{n}.orbitImpatienceDistributions{1, r})
2120 orbDist = line_nodes{n}.orbitImpatienceDistributions{1, r};
2121 if ~isa(orbDist,
'Disabled')
2122 jnodes{n}.setOrbitImpatience(jclasses{r}, JLINE.from_line_distribution(orbDist));
2125 % Batch rejection probability (retrial queues)
2126 if ~isempty(line_nodes{n}.batchRejectProb) && ...
2127 r <= length(line_nodes{n}.batchRejectProb) && ...
2128 line_nodes{n}.batchRejectProb(r) > 0
2129 jnodes{n}.setBatchRejectProbability(jclasses{r}, line_nodes{n}.batchRejectProb(r));
2134 % Transfer pass-and-swap (PAS) parameters: the total service rate
2135 % function mu(c) and the swap graph. Requires classes to be created
2136 % first (
the JAR setServiceRateFunction derives per-class rates and
2137 % setSwapGraph validates against
the class
count).
2138 for n = 1: length(jnodes)
2139 if isempty(jnodes{n})
2142 if ~isa(line_nodes{n},
'Queue') || ...
2143 (line_nodes{n}.schedStrategy ~= SchedStrategy.PAS && line_nodes{n}.schedStrategy ~= SchedStrategy.OI)
2146 if isempty(line_nodes{n}.svcRateFun)
2147 line_error(mfilename, sprintf(
'PAS queue ''%s'' has no service rate function mu(c); set it via setService(@(c) ...).', line_nodes{n}.getName));
2149 if isinf(line_nodes{n}.cap)
2150 line_error(mfilename, sprintf(
'PAS queue ''%s'' requires a finite capacity for JLINE conversion; set it via setCap(...).', line_nodes{n}.getName));
2152 jSerFun = JLINE.pas_handle_to_serializablefun(line_nodes{n}.svcRateFun, sn.nclasses, line_nodes{n}.cap);
2153 jnodes{n}.setServiceRateFunction(jSerFun);
2155 % defaults to a complete graph at
struct refresh, as MATLAB does)
2156 if ~isempty(line_nodes{n}.swapGraph)
2157 jnodes{n}.setSwapGraph(JLINE.from_line_matrix(line_nodes{n}.swapGraph));
2161 % Transfer heterogeneous server types and their per-(serverType,class)
2162 % service distributions. Requires classes to be created first.
2163 for n = 1: length(jnodes)
2164 if isempty(jnodes{n})
2167 if ~isa(line_nodes{n},
'Queue') || isempty(line_nodes{n}.serverTypes)
2170 % Map MATLAB
class names to Java class objects
2171 % Add each server type with its compatible classes
2172 jServerTypes = cell(1, length(line_nodes{n}.serverTypes));
2173 for st = 1:length(line_nodes{n}.serverTypes)
2174 serverType = line_nodes{n}.serverTypes{st};
2175 jCompat = java.util.ArrayList();
2176 compatClasses = serverType.getCompatibleClasses();
2177 for cc = 1:length(compatClasses)
2178 jCompat.add(jclasses{compatClasses{cc}.index});
2180 jST = javaObject(
'jline.lang.constant.ServerType', serverType.getName(), int32(serverType.getNumOfServers()), jCompat);
2181 jnodes{n}.addServerType(jST);
2182 jServerTypes{st} = jST;
2184 % Set heterogeneous scheduling policy
2185 switch line_nodes{n}.heteroSchedPolicy
2186 case HeteroSchedPolicy.ORDER
2187 jHetPol = jline.lang.constant.HeteroSchedPolicy.ORDER;
2188 case HeteroSchedPolicy.ALIS
2189 jHetPol = jline.lang.constant.HeteroSchedPolicy.ALIS;
2190 case HeteroSchedPolicy.ALFS
2191 jHetPol = jline.lang.constant.HeteroSchedPolicy.ALFS;
2192 case HeteroSchedPolicy.FAIRNESS
2193 jHetPol = jline.lang.constant.HeteroSchedPolicy.FAIRNESS;
2194 case HeteroSchedPolicy.FSF
2195 jHetPol = jline.lang.constant.HeteroSchedPolicy.FSF;
2196 case HeteroSchedPolicy.RAIS
2197 jHetPol = jline.lang.constant.HeteroSchedPolicy.RAIS;
2199 jHetPol = jline.lang.constant.HeteroSchedPolicy.ORDER;
2201 jnodes{n}.setHeteroSchedPolicy(jHetPol);
2202 % Set per-(serverType, class) service distributions
2203 for st = 1:length(line_nodes{n}.serverTypes)
2204 serverType = line_nodes{n}.serverTypes{st};
2205 for r = 1:length(line_classes)
2206 hetDist = line_nodes{n}.getHeteroService(line_classes{r}, serverType);
2207 if ~isempty(hetDist)
2208 jnodes{n}.setService(jclasses{r}, jServerTypes{st}, JLINE.from_line_distribution(hetDist));
2214 for n = 1: length(jnodes)
2215 if isempty(jnodes{n})
2216 continue; % Skip
nodes that were not converted
2218 if isa(line_nodes{n},
"ClassSwitch") && ~line_nodes{n}.autoAdded
2219 % Only set csMatrix
for user-defined ClassSwitch
nodes (not auto-added)
2220 JLINE.set_csMatrix(line_nodes{n}, jnodes{n}, jclasses);
2221 elseif isa(line_nodes{n},
"Join")
2222 jnodes{n}.initJoinJobClasses();
2223 % Restore RAND routing
for all classes, matching ClosedClass/OpenClass
2224 % constructor behavior (initJoinJobClasses sets DISABLED by
default)
2225 for r = 1 : sn.nclasses
2226 jnodes{n}.setRouting(jclasses{r}, jline.lang.constant.RoutingStrategy.RAND);
2228 % Transfer per-class join strategy and required
count (quorum
2229 % joins). Must run after initJoinJobClasses, which replaces
2230 %
the Joiner section and resets both to their STD/-1 defaults.
2231 for r = 1 : sn.nclasses
2232 if length(line_nodes{n}.input.joinStrategy) >= r && ~isempty(line_nodes{n}.input.joinStrategy{r}) ...
2233 && line_nodes{n}.input.joinStrategy{r} == JoinStrategy.PARTIAL
2234 jnodes{n}.setStrategy(jclasses{r}, jline.lang.constant.JoinStrategy.PARTIAL);
2236 if length(line_nodes{n}.input.joinRequired) >= r && ~isempty(line_nodes{n}.input.joinRequired{r}) ...
2237 && line_nodes{n}.input.joinRequired{r} > 0
2238 jnodes{n}.setRequired(jclasses{r}, line_nodes{n}.input.joinRequired{r});
2241 elseif isa(line_nodes{n},
"Cache")
2242 hitC = line_nodes{n}.server.hitClass;
2243 missC = line_nodes{n}.server.missClass;
2244 for r = 1 : sn.nclasses
2245 % Transfer per-class cache setup based on what each class
2246 % actually has: read (input) classes carry a popularity plus a
2247 % hit and miss class;
the auto-generated retrieval classes carry
2248 % a one-hot popularity and a miss class only. Gating on hitClass
2249 % alone (as before) dropped
the retrieval classes' read
2250 % distribution, leaving
the JAR cache state handler with a null
2251 % popularity (NPE in AfterEventCache during SSA/CTMC).
2252 hasPop = numel(line_nodes{n}.popularity) >= r ...
2253 && ~isempty(line_nodes{n}.popularity{r}) ...
2254 && ~isa(line_nodes{n}.popularity{r},
'Disabled');
2255 hasHit = length(hitC) >= r && full(hitC(r)) > 0;
2256 hasMiss = length(missC) >= r && full(missC(r)) > 0;
2258 jnodes{n}.setRead(jclasses{r}, JLINE.from_line_distribution(line_nodes{n}.popularity{r}));
2261 jnodes{n}.setHitClass(jclasses{r}, jclasses{full(hitC(r))});
2264 jnodes{n}.setMissClass(jclasses{r}, jclasses{full(missC(r))});
2267 % Transfer accessProb from MATLAB to Java
2268 if ~isempty(line_nodes{n}.accessProb)
2269 accessProbMat = line_nodes{n}.accessProb;
2270 [K1, K2] = size(accessProbMat);
2271 jAccessProb = javaArray(
'jline.util.matrix.Matrix', K1, K2);
2274 if ~isempty(accessProbMat{k1, k2})
2275 jAccessProb(k1, k2) = JLINE.from_line_matrix(accessProbMat{k1, k2});
2279 jnodes{n}.setAccessProb(jAccessProb);
2281 % Reconstruct
the delayed-hit retrieval system bookkeeping on
the
2282 % Java cache. line_to_jline already transfers
the retrieval queues,
2283 % their service and
the routing; attachRetrievalSystem restores
the
2284 % cache-internal state (retrievalSystemCapacity, queue indices,
2285 % retrieval-class set and per-item mapping)
the JAR
solvers read to
2286 % detect
the retrieval system. Without it
the JAR routes to
the plain
2287 % cache analyzer (no delayed hits; NC errors when nItems < cap+2).
2288 if ~isempty(line_nodes{n}.retrievalSystemQueueIndices) ...
2289 && line_nodes{n}.retrievalSystemQueueIndices.Count > 0
2290 rsqi = line_nodes{n}.retrievalSystemQueueIndices;
2291 rclasses = line_nodes{n}.server.retrievalClasses; % [nItems x nclasses], 1-based or -1
2292 nItemsRS = size(rclasses, 1);
2293 keysRS = keys(rsqi);
2294 for kk = 1:numel(keysRS)
2295 jobinIdx0 = double(keysRS{kk}); % 0-based arrival class index
2296 jobinClassObj = jclasses{jobinIdx0 + 1};
2297 queueIdxs = rsqi(keysRS{kk}); % 1-based MATLAB node indices
2298 qList = javaObject('java.util.ArrayList');
2299 for q = 1:numel(queueIdxs)
2300 qList.add(java.lang.Integer(int32(queueIdxs(q) - 1))); % 0-based node index
2302 rcArr = javaArray('jline.lang.JobClass', nItemsRS);
2304 rIdx = rclasses(i, jobinIdx0 + 1);
2306 rcArr(i) = jclasses{rIdx};
2309 jnodes{n}.attachRetrievalSystem(jobinClassObj, qList, rcArr);
2312 elseif isa(line_nodes{n},
"Place") && line_nodes{n}.isQueueing()
2313 % Queueing place (QPN embedded queue): marshal
the per-class
2314 % service processes, embedded-server
count and departure
2315 % discipline. Must run after classes are created. The Place was
2316 % already reconstructed with its scheduling strategy in
2317 % from_line_node; setService flips it to queueing on
the JAR side.
2318 for r = 1:sn.nclasses
2319 if numel(line_nodes{n}.serviceProcess) >= r && ~isempty(line_nodes{n}.serviceProcess{r})
2320 jdist = JLINE.from_line_distribution(line_nodes{n}.serviceProcess{r});
2321 jnodes{n}.setService(jclasses{r}, jdist);
2324 nsrv = line_nodes{n}.numberOfServers;
2326 jnodes{n}.setNumberOfServers(int32(nsrv));
2328 for r = 1:sn.nclasses
2329 if numel(line_nodes{n}.departureDiscipline) >= r && line_nodes{n}.departureDiscipline(r) > 0
2330 jnodes{n}.setDepartureDiscipline(jclasses{r}, ...
2331 jline.lang.constant.DepartureDiscipline.fromID(line_nodes{n}.departureDiscipline(r)));
2334 elseif isa(line_nodes{n},
"Transition")
2335 % First, add modes (must be done after classes are created)
2336 for m = 1:line_nodes{n}.getNumberOfModes()
2337 modeName = line_nodes{n}.modeNames{m};
2338 jmode = jnodes{n}.addMode(modeName);
2339 % Set timing strategy
2340 switch line_nodes{n}.timingStrategies(m)
2341 case TimingStrategy.TIMED
2342 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.TIMED);
2343 case TimingStrategy.IMMEDIATE
2344 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.IMMEDIATE);
2347 jnodes{n}.setDistribution(jmode, JLINE.from_line_distribution(line_nodes{n}.distributions{m}));
2348 % Set firing weights and priorities
2349 jnodes{n}.setFiringWeights(jmode, line_nodes{n}.firingWeights(m));
2350 jnodes{n}.setFiringPriorities(jmode, int32(line_nodes{n}.firingPriorities(m)));
2351 % Set number of servers
2352 nsrv = line_nodes{n}.numberOfServers(m);
2354 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(intmax(
'int32')));
2356 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(int32(nsrv)));
2359 % Now set enabling conditions, inhibiting conditions, and firing outcomes
2360 jmodes = jnodes{n}.getModes();
2361 for m = 1:line_nodes{n}.getNumberOfModes()
2362 jmode = jmodes.get(m-1);
2363 enabCond = line_nodes{n}.enablingConditions{m};
2364 inhibCond = line_nodes{n}.inhibitingConditions{m};
2365 firingOut = line_nodes{n}.firingOutcomes{m};
2366 % The condition matrices are sized (nnodes x nclasses)
2367 % at addMode time
using the node
count then in existence,
2368 % so a transition created before later
nodes has fewer
2369 % rows than length(line_nodes). Bound each access by
the
2370 % matrix
's own row count to avoid over-indexing.
2371 for r = 1:sn.nclasses
2372 for i = 1:length(line_nodes)
2373 % Set enabling conditions
2374 if i <= size(enabCond, 1) && enabCond(i, r) > 0 && isa(line_nodes{i}, 'Place
')
2375 jnodes{n}.setEnablingConditions(jmode, jclasses{r}, jnodes{i}, enabCond(i, r));
2377 % Set inhibiting conditions
2378 if i <= size(inhibCond, 1) && inhibCond(i, r) < Inf && isa(line_nodes{i}, 'Place
')
2379 jnodes{n}.setInhibitingConditions(jmode, jclasses{r}, jnodes{i}, inhibCond(i, r));
2381 % Set firing outcomes
2382 if i <= size(firingOut, 1) && firingOut(i, r) ~= 0
2383 jnodes{n}.setFiringOutcome(jmode, jclasses{r}, jnodes{i}, firingOut(i, r));
2391 % Transfer the MATLAB-side node states (e.g. a closed pass-and-swap
2392 % station's required initial placement) BEFORE from_line_links, whose
2393 % internal getStruct call would otherwise trigger
the JAR
's initDefault
2394 % validation and error on a missing PAS placement before the states
2395 % have been provided.
2396 for n = 1: length(line_nodes)
2397 if isempty(jnodes{n})
2400 if line_nodes{n}.isStateful
2401 jnodes{n}.setState(JLINE.from_line_matrix(line_nodes{n}.getState));
2402 jnodes{n}.setStateSpace(JLINE.from_line_matrix(line_nodes{n}.getStateSpace));
2403 jnodes{n}.setStatePrior(JLINE.from_line_matrix(line_nodes{n}.getStatePrior));
2407 % Assume JLINE and LINE network are both created via link
2408 JLINE.from_line_links(model, jnetwork);
2410 % Transfer finite capacity regions from MATLAB to Java
2411 if ~isempty(model.regions)
2412 for f = 1:length(model.regions)
2413 fcr = model.regions{f};
2414 % Convert MATLAB node list to Java list
2415 javaNodeList = java.util.ArrayList();
2416 for i = 1:length(fcr.nodes)
2417 matlabNode = fcr.nodes{i};
2418 % Find corresponding Java node by name
2419 nodeName = matlabNode.getName();
2420 for j = 1:length(line_nodes)
2421 if strcmp(line_nodes{j}.getName(), nodeName) && ~isempty(jnodes{j})
2422 javaNodeList.add(jnodes{j});
2428 jfcr = jnetwork.addRegion(javaNodeList);
2429 % Set global max jobs
2430 if fcr.globalMaxJobs > 0 && ~isinf(fcr.globalMaxJobs)
2431 jfcr.setGlobalMaxJobs(fcr.globalMaxJobs);
2433 % Set global memory budget (KV-cache cap in the LLM model).
2434 % Passed unrounded: fractional budgets are legitimate now
2435 % that classSize footprints may be fractional.
2436 if fcr.globalMaxMemory > 0 && ~isinf(fcr.globalMaxMemory)
2437 jfcr.setGlobalMaxMemory(fcr.globalMaxMemory);
2439 % Set per-class max jobs, memory, footprint, weight, drop rules
2440 for r = 1:length(line_classes)
2441 if length(fcr.classMaxJobs) >= r && fcr.classMaxJobs(r) > 0 && ~isinf(fcr.classMaxJobs(r))
2442 jfcr.setClassMaxJobs(jclasses{r}, fcr.classMaxJobs(r));
2444 if length(fcr.classMaxMemory) >= r && fcr.classMaxMemory(r) > 0 && ~isinf(fcr.classMaxMemory(r))
2445 jfcr.setClassMaxMemory(jclasses{r}, round(fcr.classMaxMemory(r)));
2447 % classSize is the per-class memory footprint charged against
2448 % the global memory budget; default is 1. Passed unrounded
2449 % (Java stores it as double) so fractional footprints match
2450 % the JMT XML writer; zero is a legitimate explicit footprint.
2451 % Default-valued entries are skipped to avoid redundant
2452 % MATLAB-to-Java calls (both sides default to 1).
2453 if length(fcr.classSize) >= r && isfinite(fcr.classSize(r)) && fcr.classSize(r) >= 0 && fcr.classSize(r) ~= 1
2454 jfcr.setClassSize(jclasses{r}, fcr.classSize(r));
2456 if length(fcr.classWeight) >= r && isfinite(fcr.classWeight(r)) && fcr.classWeight(r) > 0 && fcr.classWeight(r) ~= 1
2457 jfcr.setClassWeight(jclasses{r}, fcr.classWeight(r));
2459 if length(fcr.dropRule) >= r
2460 % Convert MATLAB DropStrategy numeric to Java DropStrategy enum
2461 jDropStrategy = jline.lang.constant.DropStrategy.fromID(fcr.dropRule(r));
2462 jfcr.setDropRule(jclasses{r}, jDropStrategy);
2465 % Transfer linear constraints if set
2466 if fcr.hasLinearConstraints()
2467 jA = JLINE.from_line_matrix(fcr.constraintA);
2468 jb = JLINE.from_line_matrix(fcr.constraintB);
2469 jfcr.setLinearConstraints(jA, jb);
2474 % Transfer CTMC reward definitions. The MATLAB reward functions are
2475 % opaque handles evaluated on rows of the aggregated state space
2476 % [n_{1,1},...,n_{M,K}] (station-major), so they are marshalled by
2477 % tabulating their values over the enumerable superset of that
2478 % domain into a jline TabulatedRewardFunction.
2479 if (isstruct(sn) && isfield(sn, 'reward
') || isprop(sn, 'reward
')) && ~isempty(sn.reward)
2480 for ri = 1:length(sn.reward)
2481 jnetwork.setReward(sn.reward{ri}.name, JLINE.reward_handle_to_tabulatedfun(sn.reward{ri}.fn, sn));
2485 % Transfer the MATLAB-side node states BEFORE initDefault so that the
2486 % JAR's initDefault sees user-provided initial states (e.g. a closed
2487 % pass-and-swap station
's required initial placement) rather than
2488 % erroring or fabricating a default for them. initDefault then only
2489 % initializes the stateful nodes still lacking a state.
2490 for n = 1: length(line_nodes)
2491 if isempty(jnodes{n})
2492 continue; % Skip nodes that were not converted
2494 if line_nodes{n}.isStateful
2495 jnodes{n}.setState(JLINE.from_line_matrix(line_nodes{n}.getState));
2496 jnodes{n}.setStateSpace(JLINE.from_line_matrix(line_nodes{n}.getStateSpace));
2497 jnodes{n}.setStatePrior(JLINE.from_line_matrix(line_nodes{n}.getStatePrior));
2500 jnetwork.initDefault;
2501 % Force struct refresh so sn.state reflects updated node states
2502 jnetwork.setHasStruct(false);
2506 function jnetwork = line_to_jline(model)
2507 jnetwork = LINE2JLINE(model);
2510 function model = jline_to_line(jnetwork)
2511 if isa(jnetwork,'JNetwork
')
2512 jnetwork = jnetwork.obj;
2514 %javaaddpath(jar_loc);
2515 model = Network(char(jnetwork.getName));
2516 network_nodes = jnetwork.getNodes;
2517 job_classes = jnetwork.getClasses;
2519 line_nodes = cell(network_nodes.size,1);
2520 line_classes = cell(job_classes.size,1);
2523 for n = 1 : network_nodes.size
2524 if ~isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch
')
2525 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
2529 for n = 1 : job_classes.size
2530 line_classes{n} = JLINE.from_jline_class(job_classes.get(n-1), model);
2533 % Deferred signal target association (forJobClass), once all
2535 for n = 1 : job_classes.size
2536 jc = job_classes.get(n-1);
2537 if isa(jc, 'jline.lang.ClosedSignal
') || isa(jc, 'jline.lang.OpenSignal
') || isa(jc, 'jline.lang.Signal
')
2538 jtarget = jc.getTargetJobClass();
2539 if ~isempty(jtarget)
2540 tname = char(jtarget.getName);
2541 for m = 1 : job_classes.size
2542 if strcmp(line_classes{m}.name, tname)
2543 line_classes{n}.forJobClass(line_classes{m});
2551 for n = 1 : network_nodes.size
2552 if isa(network_nodes.get(n-1), 'jline.lang.nodes.ClassSwitch
')
2553 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
2557 % Deferred Fork/Join linking: set joinOf on Join nodes
2558 for n = 1 : network_nodes.size
2559 jnode = network_nodes.get(n-1);
2560 if isa(jnode, 'jline.lang.nodes.Join
') && ~isempty(jnode.joinOf)
2561 forkName = char(jnode.joinOf.getName);
2562 for m = 1 : network_nodes.size
2563 if ~isempty(line_nodes{m}) && isa(line_nodes{m}, 'Fork
') && strcmp(line_nodes{m}.name, forkName)
2564 line_nodes{n}.joinOf = line_nodes{m};
2571 % Deferred Cache setup: set hitClass, missClass, popularity
2572 for n = 1 : network_nodes.size
2573 jnode = network_nodes.get(n-1);
2574 if isa(jnode, 'jline.lang.nodes.Cache
') && isa(line_nodes{n}, 'Cache
')
2575 cacheNode = line_nodes{n};
2576 % hitClass and missClass are stored as index vectors
2577 hitClassVec = JLINE.from_jline_matrix(jnode.getHitClass());
2578 missClassVec = JLINE.from_jline_matrix(jnode.getMissClass());
2579 for r = 1:job_classes.size
2580 hitIdx = hitClassVec(r);
2581 if hitIdx >= 0 && (hitIdx + 1) <= job_classes.size
2582 cacheNode.setHitClass(line_classes{r}, line_classes{hitIdx + 1});
2584 missIdx = missClassVec(r);
2585 if missIdx >= 0 && (missIdx + 1) <= job_classes.size
2586 cacheNode.setMissClass(line_classes{r}, line_classes{missIdx + 1});
2589 % Popularity distributions
2590 for r = 1:job_classes.size
2592 popDist = jnode.popularityGet(0, r-1);
2593 if ~isempty(popDist) && popDist.isDiscrete()
2594 matlabDist = JLINE.from_jline_distribution(popDist);
2595 if ~isempty(matlabDist)
2596 cacheNode.setRead(line_classes{r}, matlabDist);
2600 % No popularity for this class
2606 for n = 1 : network_nodes.size
2607 JLINE.set_line_service(network_nodes.get(n-1), line_nodes{n}, job_classes, line_classes);
2610 % Configure Transition modes (distributions, enabling/inhibiting/firing, etc.)
2611 for n = 1 : network_nodes.size
2612 jnode = network_nodes.get(n-1);
2613 if isa(jnode, 'jline.lang.nodes.Transition
') && isa(line_nodes{n}, 'Transition
')
2614 tnode = line_nodes{n};
2615 jmodes = jnode.getModes();
2616 nmodes = jmodes.size();
2618 jmode = jmodes.get(m-1);
2619 modeName = char(jmode.getName());
2620 % addMode if not yet present (Transition starts with one default mode)
2621 if m > tnode.getNumberOfModes()
2622 tnode.addMode(modeName);
2624 tnode.setModeNames(m, modeName);
2627 ts = jnode.timingStrategies.get(jmode);
2629 tsName = char(ts.name());
2630 if strcmp(tsName, 'IMMEDIATE
')
2631 tnode.setTimingStrategy(m, TimingStrategy.IMMEDIATE);
2633 tnode.setTimingStrategy(m, TimingStrategy.TIMED);
2637 jdist = jnode.getFiringDistribution(jmode);
2639 matlabDist = JLINE.from_jline_distribution(jdist);
2640 if ~isempty(matlabDist)
2641 tnode.setDistribution(m, matlabDist);
2645 numSrv = jnode.getNumberOfModeServers(jmode);
2646 if numSrv == intmax('int32
') || numSrv == intmax('int64
')
2647 tnode.setNumberOfServers(m, Inf);
2649 tnode.setNumberOfServers(m, double(numSrv));
2651 % Firing priority and weight (read from matrices by mode index)
2652 if jnode.firingPriorities.getNumElements() > (m-1)
2653 tnode.setFiringPriorities(m, jnode.firingPriorities.get(m-1));
2655 if jnode.firingWeights.getNumElements() > (m-1)
2656 tnode.setFiringWeights(m, jnode.firingWeights.get(m-1));
2658 % Enabling conditions
2659 ecMat = jnode.enablingConditions.get(jmode);
2661 nrows = ecMat.getNumRows();
2662 ncols = ecMat.getNumCols();
2665 val = ecMat.get(ni-1, ci-1);
2666 if val > 0 && ni <= length(line_nodes) && isa(line_nodes{ni}, 'Place
')
2667 tnode.setEnablingConditions(m, ci, line_nodes{ni}, val);
2672 % Inhibiting conditions
2673 icMat = jnode.inhibitingConditions.get(jmode);
2675 nrows = icMat.getNumRows();
2676 ncols = icMat.getNumCols();
2679 val = icMat.get(ni-1, ci-1);
2680 if isfinite(val) && val > 0 && ni <= length(line_nodes) && isa(line_nodes{ni}, 'Place
')
2681 tnode.setInhibitingConditions(m, ci, line_nodes{ni}, val);
2687 foMat = jnode.firingOutcomes.get(jmode);
2689 nrows = foMat.getNumRows();
2690 ncols = foMat.getNumCols();
2693 val = foMat.get(ni-1, ci-1);
2694 if val ~= 0 && ni <= length(line_nodes)
2695 tnode.setFiringOutcome(m, ci, line_nodes{ni}, val);
2704 % Check for state-dependent routing (RROBIN, WRROBIN, JSQ)
2705 % These cannot go through link(P) because it overrides routing strategies
2706 hasSDRouting = false;
2707 for n = 1 : network_nodes.size
2708 jnode = network_nodes.get(n-1);
2709 output_strategies = jnode.getOutputStrategies();
2710 for m = 1 : output_strategies.size()
2711 rs = char(output_strategies.get(m-1).getRoutingStrategy);
2712 if any(strcmp(rs, {'RROBIN
','WRROBIN
','JSQ
','KCHOICES
'}))
2713 hasSDRouting = true;
2717 if hasSDRouting; break; end
2721 % State-dependent routing: use addLink + setRouting
2722 model = JLINE.from_jline_routing(model, jnetwork);
2723 elseif ~isempty(jnetwork.getStruct.rtorig)
2725 model = JLINE.from_jline_links(model, jnetwork);
2727 % Do not use link() method
2728 model = JLINE.from_jline_routing(model, jnetwork);
2731 % Restore initial state on Place nodes after linking
2732 for n = 1 : network_nodes.size
2733 jnode = network_nodes.get(n-1);
2734 if isa(jnode, 'jline.lang.nodes.Place
') && ~isempty(line_nodes{n}) && isa(line_nodes{n}, 'Place
')
2735 jst = jnode.getState();
2736 if ~isempty(jst) && ~jst.isEmpty()
2737 line_nodes{n}.setState(JLINE.from_jline_matrix(jst));
2742 % Transfer finite capacity regions from Java to MATLAB (reverse of
2743 % the block in from_line_network; without this the FCR is silently
2744 % dropped and the reconstructed model solves unconstrained).
2745 jregions = jnetwork.getRegions();
2746 for f = 1 : jregions.size()
2747 jfcr = jregions.get(f-1);
2748 jrnodes = jfcr.getNodes();
2749 regionNodes = cell(1, jrnodes.size());
2750 for i = 1 : jrnodes.size()
2751 rname = char(jrnodes.get(i-1).getName());
2752 for n = 1 : length(line_nodes)
2753 if ~isempty(line_nodes{n}) && strcmp(line_nodes{n}.getName(), rname)
2754 regionNodes{i} = line_nodes{n};
2759 fcr = model.addRegion(regionNodes);
2760 gmj = jfcr.getGlobalMaxJobs();
2762 fcr.setGlobalMaxJobs(gmj);
2764 gmm = jfcr.getGlobalMaxMemory();
2766 fcr.setGlobalMaxMemory(gmm);
2768 for r = 1 : length(line_classes)
2769 jclass = job_classes.get(r-1);
2770 cmj = jfcr.getClassMaxJobs(jclass);
2772 fcr.setClassMaxJobs(line_classes{r}, cmj);
2774 cmm = jfcr.getClassMaxMemory(jclass);
2776 fcr.setClassMaxMemory(line_classes{r}, cmm);
2778 cw = jfcr.getClassWeight(jclass);
2779 if isfinite(cw) && cw > 0 && cw ~= 1
2780 fcr.setClassWeight(line_classes{r}, cw);
2782 cs = jfcr.getClassSize(jclass);
2783 if isfinite(cs) && cs >= 0 && cs ~= 1
2784 fcr.setClassSize(line_classes{r}, cs);
2786 % Java getID() uses the MATLAB numeric ids (fromID accepts
2787 % them on the forward path), so the id round-trips directly.
2788 fcr.setDropRule(line_classes{r}, jfcr.getDropStrategy(jclass).getID());
2790 jlin = jfcr.getLinearConstraints();
2792 fcr.setConstraint(JLINE.from_jline_matrix(jlin(1)), JLINE.from_jline_matrix(jlin(2)));
2797 function matrix = arraylist_to_matrix(jline_matrix)
2798 if isempty(jline_matrix)
2801 matrix = zeros(jline_matrix.size(), 1);
2802 for row = 1:jline_matrix.size()
2803 matrix(row, 1) = jline_matrix.get(row-1);
2808 function matrix = from_jline_matrix(jline_matrix)
2809 if isempty(jline_matrix)
2812 matrix = zeros(jline_matrix.getNumRows(), jline_matrix.getNumCols());
2813 for row = 1:jline_matrix.getNumRows()
2814 for col = 1:jline_matrix.getNumCols()
2815 val = jline_matrix.get(row-1, col-1);
2816 if (val >= 33333333 && val <= 33333334)
2817 matrix(row, col) = GlobalConstants.Immediate;
2818 elseif (val >= -33333334 && val <= -33333333)
2819 matrix(row, col) = -GlobalConstants.Immediate;
2820 elseif (val >= 2147483647 - 1) % Integer.MAX_VALUE with -1 tolerance
2821 matrix(row, col) = Inf;
2822 elseif (val <= -2147483648 + 1) % Integer.MIN_VALUE with +1 tolerance
2823 matrix(row, col) = -Inf;
2825 matrix(row, col) = val;
2832 function jdist = from_line_lqn_dist(ptype, dmean, dscv, dparams, dproc)
2833 % JDIST = FROM_LINE_LQN_DIST(PTYPE, DMEAN, DSCV, DPROC)
2834 % Rebuild a JAR distribution from the LayeredNetworkStruct fields of
2835 % an LQN distribution, keeping its variability. Passing the mean
2836 % alone to a setSomething(double) overload rebuilds it as Exp(1/mean)
2837 % with SCV 1, which silently discards everything above the first
2838 % moment: an Erlang setup and an exponential one of the same mean
2839 % would reach the JAR as the same process.
2841 case ProcessType.IMMEDIATE
2842 jdist = jline.lang.processes.Immediate;
2843 case ProcessType.EXP
2844 jdist = jline.lang.processes.Exp(1/dmean);
2845 case ProcessType.ERLANG
2846 jdist = jline.lang.processes.Erlang.fitMeanAndSCV(dmean, dscv);
2847 case ProcessType.HYPEREXP
2848 % Rebuilt from its own (p,lambda1,lambda2) when available: a
2849 % HyperExp carries three parameters, so a two-moment refit
2850 % returns some other HyperExp of the same mean and SCV, not
2851 % this one (HyperExp(0.1,1,10) comes back as
2852 % (0.99,6.14,0.348)).
2853 if ~isempty(dparams) && length(dparams) >= 3
2854 jdist = jline.lang.processes.HyperExp(dparams(1), dparams(2), dparams(3));
2856 jdist = jline.lang.processes.HyperExp.fitMeanAndSCV(dmean, dscv);
2858 case ProcessType.COXIAN
2859 jdist = jline.lang.processes.Coxian.fitMeanAndSCV(dmean, dscv);
2860 case ProcessType.APH
2861 jdist = jline.lang.processes.APH.fitMeanAndSCV(dmean, dscv);
2862 case {ProcessType.PH, ProcessType.MAP}
2864 if ptype == ProcessType.PH
2865 jdist = jline.lang.processes.PH(JLINE.from_line_matrix(dproc{1}), JLINE.from_line_matrix(dproc{2}));
2867 jdist = jline.lang.processes.MAP(JLINE.from_line_matrix(dproc{1}), JLINE.from_line_matrix(dproc{2}));
2870 jdist = jline.lang.processes.Exp(1/dmean);
2872 case ProcessType.DET
2873 jdist = jline.lang.processes.Det(dmean);
2875 % Any other type is carried by mean and SCV, which is exact
2876 % for SCV 1 and a two-moment fit otherwise.
2877 if abs(dscv-1) < GlobalConstants.FineTol
2878 jdist = jline.lang.processes.Exp(1/dmean);
2880 jdist = jline.lang.processes.APH.fitMeanAndSCV(dmean, dscv);
2885 function jline_matrix = from_line_matrix(matrix)
2886 [rows, cols] = size(matrix);
2887 jline_matrix = jline.util.matrix.Matrix(rows, cols);
2890 if matrix(row,col) ~= 0
2891 jline_matrix.set(row-1, col-1, matrix(row, col));
2897 function lsn = from_jline_struct_layered(jlayerednetwork, jlsn)
2898 lsn = LayeredNetworkStruct();
2899 lsn.nidx= jlsn.nidx;
2900 lsn.nhosts= jlsn.nhosts;
2901 lsn.ntasks= jlsn.ntasks;
2902 lsn.nentries= jlsn.nentries;
2903 lsn.nacts= jlsn.nacts;
2904 lsn.ncalls= jlsn.ncalls;
2905 lsn.hshift= jlsn.hshift;
2906 lsn.tshift= jlsn.tshift;
2907 lsn.eshift= jlsn.eshift;
2908 lsn.ashift= jlsn.ashift;
2909 lsn.cshift= jlsn.cshift;
2911 lsn.tasksof{h,1} = JLINE.arraylist_to_matrix(jlsn.tasksof.get(uint32(h)))';
2914 lsn.entriesof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.entriesof.get(uint32(jlsn.tshift+t)))';
2916 for t=1:(jlsn.ntasks+jlsn.nentries)
2917 lsn.actsof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.actsof.get(uint32(jlsn.tshift+t)))';
2920 lsn.callsof{lsn.ashift+a,1} = JLINE.arraylist_to_matrix(jlsn.callsof.get(uint32(jlsn.ashift+a)))';
2922 for i = 1:jlsn.sched.size
2923 lsn.sched(i,1) = SchedStrategy.(char(jlsn.sched.get(uint32(i))));
2925 for i = 1:jlsn.names.size
2926 lsn.names{i,1} = jlsn.names.get(uint32(i));
2927 lsn.hashnames{i,1} = jlsn.hashnames.get(uint32(i));
2929 lsn.mult = JLINE.from_jline_matrix(jlsn.mult);
2930 lsn.mult = lsn.mult(2:(lsn.eshift+1))
'; % remove 0-padding
2931 lsn.maxmult = JLINE.from_jline_matrix(jlsn.maxmult);
2932 lsn.maxmult = lsn.maxmult(2:(lsn.eshift+1))'; % remove 0-padding
2934 lsn.repl = JLINE.from_jline_matrix(jlsn.repl)';
2935 lsn.repl = lsn.repl(2:end); % remove 0-padding
2936 lsn.type = JLINE.from_jline_matrix(jlsn.type)';
2937 lsn.type = lsn.type(2:end); % remove 0-padding
2938 lsn.parent = JLINE.from_jline_matrix(jlsn.parent);
2939 lsn.parent = lsn.parent(2:end); % remove 0-padding
2940 lsn.nitems = JLINE.from_jline_matrix(jlsn.nitems);
2941 % Ensure proper
column vector format matching MATLAB
's (nhosts+ntasks+nentries) x 1
2942 if isrow(lsn.nitems)
2943 lsn.nitems = lsn.nitems(2:end)'; % remove 0-padding and transpose
2945 lsn.nitems = lsn.nitems(2:end); % remove 0-padding (already
column)
2947 % Ensure correct size
2948 expectedSize = lsn.nhosts + lsn.ntasks + lsn.nentries;
2949 if length(lsn.nitems) < expectedSize
2950 lsn.nitems(expectedSize,1) = 0;
2951 elseif length(lsn.nitems) > expectedSize
2952 lsn.nitems = lsn.nitems(1:expectedSize);
2954 lsn.replacestrat = JLINE.from_jline_matrix(jlsn.replacestrat);
2955 lsn.replacestrat = lsn.replacestrat(2:end)
'; % remove 0-padding
2956 for i = 1:jlsn.callnames.size
2957 lsn.callnames{i,1} = jlsn.callnames.get(uint32(i));
2958 lsn.callhashnames{i,1} = jlsn.callhashnames.get(uint32(i));
2960 for i = 1:jlsn.calltype.size % calltype may be made into a matrix in Java
2961 ct = char(jlsn.calltype.get(uint32(i)));
2962 lsn.calltype(i) = CallType.(ct);
2964 lsn.calltype = sparse(lsn.calltype'); % remove 0-padding
2965 lsn.callpair = JLINE.from_jline_matrix(jlsn.callpair);
2966 lsn.callpair = lsn.callpair(2:end,2:end); % remove 0-paddings
2967 if isempty(lsn.callpair)
2970 lsn.actpretype = sparse(JLINE.from_jline_matrix(jlsn.actpretype)
');
2971 lsn.actpretype = lsn.actpretype(2:end); % remove 0-padding
2972 lsn.actposttype = sparse(JLINE.from_jline_matrix(jlsn.actposttype)');
2973 lsn.actposttype = lsn.actposttype(2:end); % remove 0-padding
2974 lsn.graph = JLINE.from_jline_matrix(jlsn.graph);
2975 lsn.graph = lsn.graph(2:end,2:end); % remove 0-paddings
2976 lsn.dag = JLINE.from_jline_matrix(jlsn.dag);
2977 lsn.dag = lsn.dag(2:end,2:end); % remove 0-paddings
2978 lsn.taskgraph = JLINE.from_jline_matrix(jlsn.taskgraph);
2979 lsn.taskgraph = sparse(lsn.taskgraph(2:end,2:end)); % remove 0-paddings
2980 lsn.replygraph = JLINE.from_jline_matrix(jlsn.replygraph);
2981 lsn.replygraph = logical(lsn.replygraph(2:end,2:end)); % remove 0-paddings
2982 lsn.iscache = JLINE.from_jline_matrix(jlsn.iscache);
2983 % Ensure proper
column vector format matching MATLAB
's (nhosts+ntasks) x 1
2984 expectedCacheSize = lsn.nhosts + lsn.ntasks;
2985 if isrow(lsn.iscache)
2986 if length(lsn.iscache) > expectedCacheSize
2987 lsn.iscache = lsn.iscache(2:(expectedCacheSize+1))'; % remove 0-padding and transpose
2989 lsn.iscache = lsn.iscache'; % just transpose
2992 % Ensure correct size
2993 if length(lsn.iscache) < expectedCacheSize
2994 lsn.iscache(expectedCacheSize,1) = 0;
2995 elseif length(lsn.iscache) > expectedCacheSize
2996 lsn.iscache = lsn.iscache(1:expectedCacheSize);
2998 lsn.iscaller = JLINE.from_jline_matrix(jlsn.iscaller);
2999 lsn.iscaller = full(lsn.iscaller(2:end,2:end)); % remove 0-paddings
3000 lsn.issynccaller = JLINE.from_jline_matrix(jlsn.issynccaller);
3001 lsn.issynccaller = full(lsn.issynccaller(2:end,2:end)); % remove 0-paddings
3002 lsn.isasynccaller = JLINE.from_jline_matrix(jlsn.isasynccaller);
3003 lsn.isasynccaller = full(lsn.isasynccaller(2:end,2:end)); % remove 0-paddings
3004 lsn.isref = JLINE.from_jline_matrix(jlsn.isref);
3005 lsn.isref = lsn.isref(2:end)
'; % remove 0-paddings
3008 function sn = from_jline_struct(jnetwork, jsn)
3009 %lst and rtfun are not implemented
3010 %Due to the transformation of Java lambda to matlab function
3012 jsn = jnetwork.getStruct(false);
3014 jclasses = jnetwork.getClasses();
3015 jnodes = jnetwork.getNodes();
3016 jstateful = jnetwork.getStatefulNodes();
3017 jstations = jnetwork.getStations();
3018 sn = NetworkStruct();
3020 sn.nnodes = jsn.nnodes;
3021 sn.nclasses = jsn.nclasses;
3022 sn.nclosedjobs = jsn.nclosedjobs;
3023 sn.nstations = jsn.nstations;
3024 sn.nstateful = jsn.nstateful;
3025 sn.nchains = jsn.nchains;
3027 sn.refstat = JLINE.from_jline_matrix(jsn.refstat) + 1;
3028 sn.njobs = JLINE.from_jline_matrix(jsn.njobs);
3029 sn.nservers = JLINE.from_jline_matrix(jsn.nservers);
3030 sn.connmatrix = JLINE.from_jline_matrix(jsn.connmatrix);
3031 % Fix for Java getConnectionMatrix bug: ensure connmatrix is nnodes x nnodes
3032 if size(sn.connmatrix,1) < sn.nnodes
3033 sn.connmatrix(sn.nnodes,1) = 0;
3035 if size(sn.connmatrix,2) < sn.nnodes
3036 sn.connmatrix(1,sn.nnodes) = 0;
3038 sn.scv = JLINE.from_jline_matrix(jsn.scv);
3039 sn.isstation = logical(JLINE.from_jline_matrix(jsn.isstation));
3040 sn.isstateful = logical(JLINE.from_jline_matrix(jsn.isstateful));
3041 sn.isstatedep = logical(JLINE.from_jline_matrix(jsn.isstatedep));
3042 sn.nodeToStateful = JLINE.from_jline_matrix(jsn.nodeToStateful)+1;
3043 sn.nodeToStateful(sn.nodeToStateful==0) = nan;
3044 sn.nodeToStation = JLINE.from_jline_matrix(jsn.nodeToStation)+1;
3045 sn.nodeToStation(sn.nodeToStation==0) = nan;
3046 sn.stationToNode = JLINE.from_jline_matrix(jsn.stationToNode)+1;
3047 sn.stationToNode(sn.stationToNode==0) = nan;
3048 sn.stationToStateful = JLINE.from_jline_matrix(jsn.stationToStateful)+1;
3049 sn.stationToStateful(sn.stationToStateful==0) = nan;
3050 sn.statefulToStation = JLINE.from_jline_matrix(jsn.statefulToStation)+1;
3051 sn.statefulToStation(sn.statefulToStation==0) = nan;
3052 sn.statefulToNode = JLINE.from_jline_matrix(jsn.statefulToNode)+1;
3053 sn.statefulToNode(sn.statefulToNode==0) = nan;
3054 sn.rates = JLINE.from_jline_matrix(jsn.rates);
3055 sn.fj = JLINE.from_jline_matrix(jsn.fj);
3056 sn.classprio = JLINE.from_jline_matrix(jsn.classprio);
3057 sn.phases = JLINE.from_jline_matrix(jsn.phases);
3058 sn.phasessz = JLINE.from_jline_matrix(jsn.phasessz);
3059 sn.phaseshift = JLINE.from_jline_matrix(jsn.phaseshift);
3060 sn.schedparam = JLINE.from_jline_matrix(jsn.schedparam);
3061 sn.chains = logical(JLINE.from_jline_matrix(jsn.chains));
3062 sn.rt = JLINE.from_jline_matrix(jsn.rt);
3063 sn.nvars = JLINE.from_jline_matrix(jsn.nvars);
3064 sn.rtnodes = JLINE.from_jline_matrix(jsn.rtnodes);
3065 sn.csmask = logical(JLINE.from_jline_matrix(jsn.csmask));
3066 sn.isslc = logical(JLINE.from_jline_matrix(jsn.isslc));
3067 sn.cap = JLINE.from_jline_matrix(jsn.cap);
3068 sn.classcap = JLINE.from_jline_matrix(jsn.classcap);
3069 sn.refclass = JLINE.from_jline_matrix(jsn.refclass)+1;
3070 sn.lldscaling = JLINE.from_jline_matrix(jsn.lldscaling);
3072 if ~isempty(jsn.cdscaling) && jsn.cdscaling.size() > 0
3073 % Convert Java SerializableFunction to MATLAB function handles
3074 sn.cdscaling = cell(sn.nstations, 1);
3075 % Iterate through the map entries to handle null values properly
3076 entrySet = jsn.cdscaling.entrySet();
3077 entryIter = entrySet.iterator();
3078 stationFunMap = containers.Map();
3079 while entryIter.hasNext()
3080 entry = entryIter.next();
3081 stationName = char(entry.getKey().getName());
3083 jfun = entry.getValue();
3085 stationFunMap(stationName) = jfun;
3088 % getValue() returns null for default lambda functions
3089 % Skip and use default value
3092 % Assign functions to stations
3093 for i = 1:sn.nstations
3094 jstation = jstations.get(i-1);
3095 stationName = char(jstation.getName());
3096 if isKey(stationFunMap, stationName)
3097 jfun = stationFunMap(stationName);
3098 % Create a MATLAB function handle that calls the Java apply() method
3099 sn.cdscaling{i} = @(ni) JLINE.call_java_cdscaling(jfun, ni);
3101 sn.cdscaling{i} = @(ni) 1;
3105 sn.cdscaling = cell(sn.nstations, 0);
3108 if ~isempty(jsn.nodetype)
3109 sn.nodetype = zeros(sn.nnodes, 1);
3110 for i = 1:jsn.nodetype.size
3111 nodetype = jsn.nodetype.get(i-1);
3112 switch nodetype.name().toCharArray'
3114 sn.nodetype(i) = NodeType.Queue;
3116 sn.nodetype(i) = NodeType.Delay;
3118 sn.nodetype(i) = NodeType.Source;
3120 sn.nodetype(i) = NodeType.Sink;
3122 sn.nodetype(i) = NodeType.Join;
3124 sn.nodetype(i) = NodeType.Fork;
3126 sn.nodetype(i) = NodeType.ClassSwitch;
3128 sn.nodetype(i) = NodeType.Logger;
3130 sn.nodetype(i) = NodeType.Cache;
3132 sn.nodetype(i) = NodeType.Place;
3134 sn.nodetype(i) = NodeType.Transition;
3136 sn.nodetype(i) = NodeType.Router;
3143 if ~isempty(jsn.classnames)
3144 for i = 1:jsn.classnames.size
3145 sn.classnames(i,1) = jsn.classnames.get(i-1);
3151 if ~isempty(jsn.nodenames)
3152 for i = 1:jsn.nodenames.size
3153 sn.nodenames(i,1) = jsn.nodenames.get(i-1);
3159 if ~isempty(jsn.rtorig) && jsn.rtorig.size()>0
3160 sn.rtorig = cell(sn.nclasses, sn.nclasses);
3161 for r = 1:sn.nclasses
3162 for s = 1:sn.nclasses
3163 sn.rtorig{r,s} = JLINE.from_jline_matrix(jsn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
3170 if ~isempty(jsn.state)
3171 sn.state = cell(sn.nstateful, 1);
3172 for i = 1:sn.nstateful
3173 sn.state{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getState());
3179 if ~isempty(jsn.stateprior)
3180 sn.stateprior = cell(sn.nstateful, 1);
3181 for i = 1:sn.nstateful
3182 sn.stateprior{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStatePrior());
3188 if ~isempty(jsn.space)
3189 sn.space = cell(sn.nstateful, 1);
3190 for i = 1:sn.nstateful
3191 sn.space{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStateSpace());
3197 if ~isempty(jsn.routing)
3198 sn.routing = zeros(sn.nnodes, sn.nclasses);
3200 for j = 1:sn.nclasses
3201 routingStrategy = jsn.routing.get(jnodes.get(i-1)).get(jclasses.get(j-1));
3202 switch routingStrategy.name().toCharArray'
3204 sn.routing(i,j) = RoutingStrategy.PROB;
3206 sn.routing(i,j) = RoutingStrategy.RAND;
3208 sn.routing(i,j) = RoutingStrategy.RROBIN;
3210 sn.routing(i,j) = RoutingStrategy.WRROBIN;
3212 sn.routing(i,j) = RoutingStrategy.JSQ;
3214 sn.routing(i,j) = RoutingStrategy.DISABLED;
3216 sn.routing(i,j) = RoutingStrategy.FIRING;
3218 sn.routing(i,j) = RoutingStrategy.KCHOICES;
3226 if ~isempty(jsn.procid)
3227 sn.procid = nan(sn.nstations, sn.nclasses); % Initialize with NaN to match MATLAB behavior
3228 for i = 1:sn.nstations
3229 for j = 1:sn.nclasses
3230 stationMap = jsn.procid.get(jstations.get(i-1));
3231 if isempty(stationMap)
3232 sn.procid(i,j) = ProcessType.DISABLED;
3235 processType = stationMap.get(jclasses.get(j-1));
3236 if isempty(processType)
3237 sn.procid(i,j) = ProcessType.DISABLED;
3240 switch processType.name.toCharArray'
3242 sn.procid(i,j) = ProcessType.EXP;
3244 sn.procid(i,j) = ProcessType.ERLANG;
3246 sn.procid(i,j) = ProcessType.HYPEREXP;
3248 sn.procid(i,j) = ProcessType.PH;
3250 sn.procid(i,j) = ProcessType.APH;
3252 sn.procid(i,j) = ProcessType.MAP;
3254 sn.procid(i,j) = ProcessType.UNIFORM;
3256 sn.procid(i,j) = ProcessType.DET;
3258 sn.procid(i,j) = ProcessType.COXIAN;
3260 sn.procid(i,j) = ProcessType.GAMMA;
3262 sn.procid(i,j) = ProcessType.PARETO;
3264 sn.procid(i,j) = ProcessType.WEIBULL;
3266 sn.procid(i,j) = ProcessType.LOGNORMAL;
3268 sn.procid(i,j) = ProcessType.MMPP2;
3270 sn.procid(i,j) = ProcessType.REPLAYER;
3272 sn.procid(i,j) = ProcessType.TRACE;
3274 sn.procid(i,j) = ProcessType.IMMEDIATE;
3276 sn.procid(i,j) = ProcessType.DISABLED;
3278 sn.procid(i,j) = ProcessType.COX2;
3280 sn.procid(i,j) = ProcessType.BMAP;
3282 sn.procid(i,j) = ProcessType.ME;
3284 sn.procid(i,j) = ProcessType.RAP;
3286 sn.procid(i,j) = ProcessType.BINOMIAL;
3288 sn.procid(i,j) = ProcessType.POISSON;
3290 sn.procid(i,j) = ProcessType.GEOMETRIC;
3292 sn.procid(i,j) = ProcessType.DUNIFORM;
3294 sn.procid(i,j) = ProcessType.BERNOULLI;
3296 sn.procid(i,j) = ProcessType.PRIOR;
3298 % Unknown ProcessType - default to DISABLED
3299 sn.procid(i,j) = ProcessType.DISABLED;
3308 sn.mu = cell(sn.nstations, 1);
3309 for i = 1:sn.nstations
3310 sn.mu{i} = cell(1, sn.nclasses);
3311 for j = 1:sn.nclasses
3312 sn.mu{i}{j} = JLINE.from_jline_matrix(jsn.mu.get(jstations.get(i-1)).get(jclasses.get(j-1)));
3319 if ~isempty(jsn.phi)
3320 sn.phi = cell(sn.nstations, 1);
3321 for i = 1:sn.nstations
3322 sn.phi{i} = cell(1, sn.nclasses);
3323 for j = 1:sn.nclasses
3324 sn.phi{i}{j} = JLINE.from_jline_matrix(jsn.phi.get(jstations.get(i-1)).get(jclasses.get(j-1)));
3331 if ~isempty(jsn.proc)
3332 sn.proc = cell(sn.nstations, 1);
3333 for i = 1:sn.nstations
3334 sn.proc{i} = cell(1, sn.nclasses);
3335 for j = 1:sn.nclasses
3336 proc_i_j = jsn.proc.get(jstations.get(i-1)).get(jclasses.get(j-1));
3337 sn.proc{i}{j} = cell(1, proc_i_j.size);
3338 for k = 1:proc_i_j.size
3339 sn.proc{i}{j}{k} = JLINE.from_jline_matrix(proc_i_j.get(uint32(k-1)));
3347 if ~isempty(jsn.pie)
3348 sn.pie = cell(sn.nstations, 1);
3349 for i = 1:sn.nstations
3350 sn.pie{i} = cell(1, sn.nclasses);
3351 for j = 1:sn.nclasses
3352 sn.pie{i}{j} = JLINE.from_jline_matrix(jsn.pie.get(jstations.get(i-1)).get(jclasses.get(j-1)));
3359 if ~isempty(jsn.sched)
3360 sn.sched = zeros(sn.nstations, 1);
3361 for i = 1:sn.nstations
3362 schedStrategy = jsn.sched.get(jstations.get(i-1));
3363 switch schedStrategy.name.toCharArray'
3365 sn.sched(i) = SchedStrategy.INF;
3367 sn.sched(i) = SchedStrategy.FCFS;
3369 sn.sched(i) = SchedStrategy.LCFS;
3371 sn.sched(i) = SchedStrategy.LCFSPR;
3373 sn.sched(i) = SchedStrategy.SIRO;
3375 sn.sched(i) = SchedStrategy.SJF;
3377 sn.sched(i) = SchedStrategy.LJF;
3379 sn.sched(i) = SchedStrategy.PS;
3381 sn.sched(i) = SchedStrategy.DPS;
3383 sn.sched(i) = SchedStrategy.GPS;
3385 sn.sched(i) = SchedStrategy.PSPRIO;
3387 sn.sched(i) = SchedStrategy.DPSPRIO;
3389 sn.sched(i) = SchedStrategy.GPSPRIO;
3391 sn.sched(i) = SchedStrategy.SEPT;
3393 sn.sched(i) = SchedStrategy.LEPT;
3394 case {
'HOL',
'FCFSPRIO'}
3395 sn.sched(i) = SchedStrategy.FCFSPRIO;
3397 sn.sched(i) = SchedStrategy.FORK;
3399 sn.sched(i) = SchedStrategy.EXT;
3401 sn.sched(i) = SchedStrategy.REF;
3408 if ~isempty(jsn.inchain)
3409 sn.inchain = cell(1, sn.nchains);
3410 for i = 1:sn.nchains
3411 sn.inchain{1,i} = JLINE.from_jline_matrix(jsn.inchain.get(uint32(i-1)))+1;
3417 if ~isempty(jsn.visits)
3418 sn.
visits = cell(sn.nchains, 1);
3419 for i = 1:sn.nchains
3420 sn.
visits{i,1} = JLINE.from_jline_matrix(jsn.visits.get(uint32(i-1)));
3426 if ~isempty(jsn.nodevisits)
3428 for i = 1:sn.nchains
3429 sn.
nodevisits{1,i} = JLINE.from_jline_matrix(jsn.nodevisits.get(uint32(i-1)));
3435 if ~isempty(jsn.droprule)
3436 sn.droprule = zeros(sn.nstations, sn.nclasses);
3437 for i = 1:sn.nstations
3438 for j = 1:sn.nclasses
3439 dropStrategy = jsn.droprule.get(jstations.get(i-1)).get(jclasses.get(j-1));
3440 switch dropStrategy.name.toCharArray'
3442 sn.droprule(i,j) = DropStrategy.WAITQ;
3444 sn.droprule(i,j) = DropStrategy.DROP;
3445 case 'BlockingAfterService'
3446 sn.droprule(i,j) = DropStrategy.BAS;
3458 jnode = jnodes.get(i-1);
3467 if isa(jparam,
'jline.lang.nodeparam.StationNodeParam')
3468 if ~isempty(jparam.fileName)
3469 sn.
nodeparam{i}.fileName = cell(1, sn.nclasses);
3470 for r = 1:sn.nclasses
3471 fname = jparam.fileName.get(r-1);
3473 sn.nodeparam{i}.fileName{r} = char(fname);
3479 % TransitionNodeParam
3480 if isa(jparam,
'jline.lang.nodeparam.TransitionNodeParam')
3481 if ~isempty(jparam.firingprocid)
3482 sn.
nodeparam{i}.firingprocid = containers.Map(
'KeyType',
'char',
'ValueType',
'any');
3483 keys = jparam.firingprocid.keySet.iterator;
3486 proc = jparam.firingprocid.get(key);
3487 sn.nodeparam{i}.firingprocid(
char(key.toString)) = char(proc.toString);
3490 if ~isempty(jparam.firingphases)
3491 sn.
nodeparam{i}.firingphases = JLINE.from_jline_matrix(jparam.firingphases);
3493 if ~isempty(jparam.fireweight)
3494 sn.
nodeparam{i}.fireweight = JLINE.from_jline_matrix(jparam.fireweight);
3499 if isa(jparam,
'jline.lang.nodeparam.JoinNodeParam')
3500 if ~isempty(jparam.joinStrategy)
3501 sn.
nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
3502 sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
3503 for r = 1:sn.nclasses
3504 jclass = jclasses.get(r-1);
3505 joinStrategy = jparam.joinStrategy.get(jclass);
3506 if ~isempty(joinStrategy)
3507 strategyStr = char(joinStrategy.name.toString);
3510 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
3512 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
3514 sn.nodeparam{i}.joinStrategy{r} = strategyStr;
3516 sn.nodeparam{i}.fanIn{r} = jparam.fanIn.get(jclass);
3523 if isa(jparam,
'jline.lang.nodeparam.RoutingNodeParam')
3524 for r = 1:sn.nclasses
3525 jclass = jclasses.get(r-1);
3527 if ~isempty(jparam.weights) && jparam.weights.containsKey(jclass)
3528 sn.
nodeparam{i}.weights{r} = JLINE.from_jline_matrix(jparam.weights.get(jclass));
3531 if ~isempty(jparam.outlinks) && jparam.outlinks.containsKey(jclass)
3532 sn.nodeparam{i}.outlinks{r} = JLINE.from_jline_matrix(jparam.outlinks.get(jclass));
3538 if isa(jparam,
'jline.lang.nodeparam.ForkNodeParam')
3539 if ~isnan(jparam.fanOut)
3545 if isa(jparam,
'jline.lang.nodeparam.CacheNodeParam')
3547 if ~isnan(jparam.nitems)
3552 if ~isempty(jparam.accost)
3553 % For Java 2D arrays (Matrix[][]), size(arr,2) returns 1 in MATLAB
3554 % We need to get length of first row to get actual second dimension
3555 K1 = size(jparam.accost, 1);
3557 firstRow = jparam.accost(1); % Get first row (Java array)
3558 K2 = length(firstRow);
3565 mat = jparam.accost(k1, k2); % MATLAB handles Java array indexing
3567 sn.nodeparam{i}.accost{k1, k2} = JLINE.from_jline_matrix(mat);
3574 if ~isempty(jparam.itemcap)
3575 sn.
nodeparam{i}.itemcap = JLINE.from_jline_matrix(jparam.itemcap);
3578 % pread - convert from Java Map<Integer, List<Double>> to MATLAB cell array {R}
3579 if ~isempty(jparam.pread)
3580 nclasses = sn.nclasses;
3581 sn.
nodeparam{i}.pread = cell(1, nclasses);
3583 list = jparam.pread.get(int32(r-1)); % Java 0-based indexing
3585 values = zeros(1, list.size);
3587 values(j) = list.get(j-1);
3589 sn.nodeparam{i}.pread{r} = values;
3591 sn.nodeparam{i}.pread{r} = NaN;
3597 if ~isempty(jparam.replacestrat)
3598 switch
char(jparam.replacestrat)
3600 sn.
nodeparam{i}.replacestrat = ReplacementStrategy.RR;
3602 sn.nodeparam{i}.replacestrat = ReplacementStrategy.FIFO;
3604 sn.nodeparam{i}.replacestrat = ReplacementStrategy.SFIFO;
3606 sn.nodeparam{i}.replacestrat = ReplacementStrategy.LRU;
3611 if ~isempty(jparam.hitclass)
3612 sn.
nodeparam{i}.hitclass = 1+JLINE.from_jline_matrix(jparam.hitclass);
3616 if ~isempty(jparam.missclass)
3617 sn.
nodeparam{i}.missclass =1+ JLINE.from_jline_matrix(jparam.missclass);
3620 % actual hit/miss probabilities
3621 if ~isempty(jparam.actualhitprob)
3622 sn.
nodeparam{i}.actualhitprob = JLINE.from_jline_matrix(jparam.actualhitprob);
3624 if ~isempty(jparam.actualmissprob)
3625 sn.
nodeparam{i}.actualmissprob = JLINE.from_jline_matrix(jparam.actualmissprob);
3633 %
if ~isempty(jsn.nodeparam)
3634 % sn.nodeparam = cell(sn.nnodes, 1);
3635 % % Note that JLINE only support node parameters related to
3636 % % Fork, Join, WWROBIN and RROBIN
3637 %
for i = 1:sn.nnodes
3638 %
if jsn.nodeparam.get(jnodes.get(i-1)).isEmpty
3639 % sn.nodeparam{i} = [];
3641 %
if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).nitems)
3642 % sn.nodeparam{i}.nitems = jsn.nodeparam.get(jnodes.get(i-1)).nitems;
3644 %
if ~isnan(jsn.nodeparam.get(jnodes.get(i-1)).fanOut)
3645 % sn.nodeparam{i}.fanOut = jsn.nodeparam.get(jnodes.get(i-1)).fanOut;
3647 %
if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy)
3648 %
if ~jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.isEmpty
3649 % sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
3650 % sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
3651 %
for r = 1:sn.nclasses
3652 % joinStrategy = jsn.nodeparam.get(jnodes.get(i-1)).joinStrategy.get(jclasses.get(r-1));
3653 %
switch joinStrategy.name.toCharArray
'
3655 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
3657 % sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
3659 % sn.nodeparam{i}.fanIn{r} = jsn.nodeparam.get(jnodes.get(i-1)).fanIn.get(jclasses.get(r-1));
3664 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).weights)
3665 % for r = 1:sn.nclasses
3666 % sn.nodeparam{i}{r}.weights = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).weights.get(jclasses.get(r-1)));
3670 % if ~isempty(jsn.nodeparam.get(jnodes.get(i-1)).outlinks)
3671 % for r = 1:sn.nclasses
3672 % sn.nodeparam{i}{r}.outlinks = JLINE.from_jline_matrix(jsn.nodeparam.get(jnodes.get(i-1)).outlinks.get(jclasses.get(r-1)));
3678 % sn.nodeparam = {};
3681 if ~isempty(jsn.sync)
3683 sn.sync = cell(jsync.size, 1);
3684 for i = 1:jsync.size
3685 jsync_i = jsync.get(uint32(i-1));
3686 sn.sync{i,1} = struct('active
',cell(1),'passive
',cell(1));
3688 jactive = jsync_i.active.get(uint32(0));
3689 jpassive = jsync_i.passive.get(uint32(0));
3691 %Currently assume that prob would always be a value
3692 %instead of lambda function (No idea of how to convert
3693 %Java lambda function to matlab lambda function)
3694 switch jactive.getEvent.name.toCharArray'
3696 sn.sync{i,1}.active{1} = Event(EventType.INIT, jactive.getNode+1, jactive.getJobClass+1, ...
3697 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3698 jactive.getT, jactive.getJob);
3700 sn.sync{i,1}.active{1} = Event(EventType.LOCAL, jactive.getNode+1, jactive.getJobClass+1, ...
3701 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3702 jactive.getT, jactive.getJob);
3704 sn.sync{i,1}.active{1} = Event(EventType.ARV, jactive.getNode+1, jactive.getJobClass+1, ...
3705 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3706 jactive.getT, jactive.getJob);
3708 sn.sync{i,1}.active{1} = Event(EventType.DEP, jactive.getNode+1, jactive.getJobClass+1, ...
3709 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3710 jactive.getT, jactive.getJob);
3712 sn.sync{i,1}.active{1} = Event(EventType.PHASE, jactive.getNode+1, jactive.getJobClass+1, ...
3713 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3714 jactive.getT, jactive.getJob);
3716 sn.sync{i,1}.active{1} = Event(EventType.READ, jactive.getNode+1, jactive.getJobClass+1, ...
3717 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3718 jactive.getT, jactive.getJob);
3720 sn.sync{i,1}.active{1} = Event(EventType.STAGE, jactive.getNode+1, jactive.getJobClass+1, ...
3721 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3722 jactive.getT, jactive.getJob);
3725 switch jpassive.getEvent.name.toCharArray
'
3727 sn.sync{i,1}.passive{1} = Event(EventType.INIT, jpassive.getNode+1, jpassive.getJobClass+1, ...
3728 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3729 jpassive.getT, jpassive.getJob);
3731 sn.sync{i,1}.passive{1} = Event(EventType.LOCAL, jpassive.getNode+1, jpassive.getJobClass+1, ...
3732 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3733 jpassive.getT, jpassive.getJob);
3735 sn.sync{i,1}.passive{1} = Event(EventType.ARV, jpassive.getNode+1, jpassive.getJobClass+1, ...
3736 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3737 jpassive.getT, jpassive.getJob);
3739 sn.sync{i,1}.passive{1} = Event(EventType.DEP, jpassive.getNode+1, jpassive.getJobClass+1, ...
3740 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3741 jpassive.getT, jpassive.getJob);
3743 sn.sync{i,1}.passive{1} = Event(EventType.PHASE, jpassive.getNode+1, jpassive.getJobClass+1, ...
3744 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3745 jpassive.getT, jpassive.getJob);
3747 sn.sync{i,1}.passive{1} = Event(EventType.READ, jpassive.getNode+1, jpassive.getJobClass+1, ...
3748 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3749 jpassive.getT, jpassive.getJob);
3751 sn.sync{i,1}.passive{1} = Event(EventType.STAGE, jpassive.getNode+1, jpassive.getJobClass+1, ...
3752 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3753 jpassive.getT, jpassive.getJob);
3761 function [QN,UN,RN,WN,AN,TN] = arrayListToResults(alist)
3763 case 'jline.solvers.LayeredNetworkAvgTable
'
3764 QN = JLINE.arraylist_to_matrix(alist.getQLen());
3765 UN = JLINE.arraylist_to_matrix(alist.getUtil());
3766 RN = JLINE.arraylist_to_matrix(alist.getRespT());
3767 WN = JLINE.arraylist_to_matrix(alist.getResidT());
3768 AN = JLINE.arraylist_to_matrix(alist.getArvR());
3769 TN = JLINE.arraylist_to_matrix(alist.getTput());
3771 QN = JLINE.arraylist_to_matrix(alist.getQLen());
3772 UN = JLINE.arraylist_to_matrix(alist.getUtil());
3773 RN = JLINE.arraylist_to_matrix(alist.getRespT());
3774 WN = JLINE.arraylist_to_matrix(alist.getResidT());
3775 AN = JLINE.arraylist_to_matrix(alist.getArvR());
3776 TN = JLINE.arraylist_to_matrix(alist.getTput());
3780 function featSupported = getFeatureSet()
3781 % FEATSUPPORTED = GETFEATURESET()
3783 featSupported = SolverFeatureSet;
3784 featSupported.setTrue({'Sink
','Source
',...
3785 'ClassSwitch
','Delay
','DelayStation
','Queue
',...
3786 'APH
','Coxian
','Erlang
','Exp
','HyperExp
',...
3787 'StatelessClassSwitcher
','InfiniteServer
','SharedServer
','Buffer
','Dispatcher
',...
3788 'Server
','JobSink
','RandomSource
','ServiceTunnel
',...
3789 'SchedStrategy_INF
','SchedStrategy_PS
',...
3790 'RoutingStrategy_PROB
','RoutingStrategy_RAND
',...
3791 'ClosedClass
','OpenClass
'});
3794 function [bool, featSupported] = supports(model)
3795 % [BOOL, FEATSUPPORTED] = SUPPORTS(MODEL)
3797 featUsed = model.getUsedLangFeatures();
3798 featSupported = JLINE.getFeatureSet();
3799 bool = SolverFeatureSet.supports(featSupported, featUsed);
3803 function solverOptions = parseSolverOptions(solverOptions, options)
3804 fn = fieldnames(options);
3805 fn2 = fieldnames(solverOptions);
3806 for f = 1:length(fn)
3808 for j = 1:length(fn2)
3809 if strcmp(fn{f}, fn2{j})
3813 solverOptions.seed = options.seed;
3815 solverOptions.samples = options.samples;
3817 % Parse confint - can be a level (0.95) or 0 to disable
3818 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
3820 solverOptions.confint = confintLevel;
3822 solverOptions.confint = 0;
3825 solverOptions.method = options.method;
3827 if isfield(options.config,'eventcache
')
3828 solverOptions.config.eventcache = options.config.eventcache;
3830 if isfield(options.config,'fork_join
')
3831 solverOptions.config.fork_join = options.config.fork_join;
3833 if isfield(options.config,'highvar
')
3834 solverOptions.config.highvar = options.config.highvar;
3836 if isfield(options.config,'multiserver
')
3837 solverOptions.config.multiserver = options.config.multiserver;
3839 if isfield(options.config,'np_priority
')
3840 solverOptions.config.np_priority = options.config.np_priority;
3842 if isfield(options.config,'warmupfrac
') && ~isempty(options.config.warmupfrac) ...
3843 && options.config.warmupfrac > 0
3844 % SSA warmup discard (mean estimates + CI batch means)
3845 solverOptions.config.warmupfrac = java.lang.Double(options.config.warmupfrac);
3848 switch options.(fn{f})
3849 case {VerboseLevel.SILENT}
3850 solverOptions.verbose = solverOptions.verbose.SILENT;
3851 case {VerboseLevel.STD}
3852 solverOptions.verbose = solverOptions.verbose.STD;
3853 case {VerboseLevel.DEBUG}
3854 solverOptions.verbose = solverOptions.verbose.DEBUG;
3857 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.init_sol);
3859 if isscalar(options.cutoff)
3860 solverOptions.(fn{f}) = jline.util.matrix.Matrix.singleton(options.cutoff);
3862 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.cutoff);
3865 case 'rewardIterations
'
3866 solverOptions.rewardIterations = java.lang.Integer(options.rewardIterations);
3868 solverOptions.(fn{f}) = options.(fn{f});
3875 line_printf('Could not find option %s in
the JLINE options.\n
', fn{f});
3880 function [ssa] = SolverSSA(network_object, options)
3881 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.SSA);
3883 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3885 jline.util.Maths.setRandomNumbersMatlab(true);
3886 ssa = jline.solvers.ssa.SolverSSA(network_object, solverOptions);
3889 function [qns] = SolverQNS(network_object, options)
3890 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.QNS);
3892 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3894 qns = jline.solvers.wrappers.qns.SolverQNS(network_object, solverOptions);
3897 function [mam] = SolverMAM(network_object, options)
3898 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MAM);
3900 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3902 mam = jline.solvers.mam.SolverMAM(network_object, solverOptions);
3905 function [jmt] = SolverJMT(network_object, options)
3906 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.JMT);
3908 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3910 jmt = jline.solvers.wrappers.jmt.SolverJMT(network_object, solverOptions);
3913 function [ctmc] = SolverCTMC(network_object, options)
3914 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.CTMC);
3916 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3918 ctmc = jline.solvers.ctmc.SolverCTMC(network_object,solverOptions);
3921 function [infGen, eventFilt, syncInfo, stateSpace, nodeStateSpace] = getSymbolicGenerator(ctmc, invertSymbol)
3922 % [INFGEN, EVENTFILT, SYNCINFO, STATESPACE, NODESTATESPACE] = GETSYMBOLICGENERATOR(CTMC, INVERTSYMBOL)
3923 % Symbolic infinitesimal generator of a JLINE SolverCTMC object, with
3924 % each event filtration normalized by its minimum positive rate and
3925 % scaled by a symbolic variable x1..xE, as in the native
3926 % SolverCTMC.getSymbolicGenerator. Coefficient matrices are computed
3927 % by the JAR; symbolic objects are rebuilt with the Symbolic Toolbox.
3929 invertSymbol = false;
3932 line_error(mfilename,'This method
requires MATLAB
''s Symbolic Toolbox.
');
3934 res = ctmc.getSymbolicGenerator(invertSymbol);
3935 stateSpace = JLINE.from_jline_matrix(res.stateSpace);
3936 n = size(stateSpace,1);
3937 nEvents = res.eventFilt.size();
3938 infGen = sym(zeros(n));
3939 eventFilt = cell(1, nEvents);
3941 symName = res.symbols.get(e-1);
3942 if ~isempty(symName)
3943 Fe = JLINE.from_jline_matrix(res.eventFilt.get(e-1));
3945 eventFilt{e} = Fe / sym(char(symName),'real
');
3947 eventFilt{e} = Fe * sym(char(symName),'real
');
3949 infGen = infGen + eventFilt{e};
3952 infGen = ctmc_makeinfgen(infGen);
3953 syncInfo = res.syncInfo;
3954 nodeStateSpace = cell(1, res.nodeStateSpace.size());
3955 for i = 1:res.nodeStateSpace.size()
3956 nodeStateSpace{i} = JLINE.from_jline_matrix(res.nodeStateSpace.get(i-1));
3960 function [fluid] = SolverFluid(network_object, options)
3961 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.FLUID);
3963 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3965 fluid = jline.solvers.fluid.SolverFluid(network_object, solverOptions);
3968 function [QN, UN, RN, TN, CN, XN, t, QNt, UNt, TNt, xvec] = runFluidAnalyzer(network, options)
3969 % RUNFLUIDANALYZER Run JLINE fluid analyzer and return results
3971 % [QN, UN, RN, TN, CN, XN, T, QNT, UNT, TNT, XVEC] = JLINE.runFluidAnalyzer(NETWORK, OPTIONS)
3973 % Runs the JLINE fluid solver on the given network and converts
3974 % results back to MATLAB data structures.
3977 % network - LINE Network model
3978 % options - Solver options structure with fields:
3979 % .method - solver method
3980 % .stiff - use stiff ODE solver
3983 % QN, UN, RN, TN - Steady-state metrics [M x K]
3984 % CN, XN - System metrics [1 x K]
3985 % t - Time vector [Tmax x 1]
3986 % QNt, UNt, TNt - Transient metrics {M x K} cells
3987 % xvec - State vector structure
3989 jmodel = LINE2JLINE(network);
3990 jsolver = JLINE.SolverFluid(jmodel);
3991 import jline.solvers.fluid.*;
3993 jsolver.options.method = options.method;
3994 jsolver.options.stiff = options.stiff;
3995 result = jsolver.runMethodSpecificAnalyzerViaLINE();
3997 % Convert JLINE result to MATLAB data structures
3998 M = jmodel.getNumberOfStatefulNodes();
3999 K = jmodel.getNumberOfClasses();
4001 QN = NaN * zeros(M, K);
4002 UN = NaN * zeros(M, K);
4003 RN = NaN * zeros(M, K);
4004 TN = NaN * zeros(M, K);
4005 CN = NaN * zeros(1, K);
4006 XN = NaN * zeros(1, K);
4012 Tmax = result.t.length();
4013 t = NaN * zeros(Tmax, 1);
4017 QN(ist, jst) = result.QN.get(ist-1, jst-1);
4018 UN(ist, jst) = result.UN.get(ist-1, jst-1);
4019 RN(ist, jst) = result.RN.get(ist-1, jst-1);
4020 TN(ist, jst) = result.TN.get(ist-1, jst-1);
4025 CN(1, jst) = result.CN.get(0, jst-1);
4026 XN(1, jst) = result.XN.get(0, jst-1);
4032 QNt{ist, jst}(p, 1) = result.QNt(ist, jst).get(p-1, 0);
4033 UNt{ist, jst}(p, 1) = result.UNt(ist, jst).get(p-1, 0);
4034 TNt{ist, jst}(p, 1) = result.TNt(ist, jst).get(p-1, 0);
4040 t(p, 1) = result.t.get(p-1, 0);
4043 % JLINE does not return odeStateVec
4044 xvec.odeStateVec = [];
4048 function [ldes] = SolverLDES(network_object, options)
4049 % Create LDES-specific options object
4050 ldesOptions = jline.solvers.ldes.LDESOptions();
4052 % Copy standard options
4053 ldesOptions.samples = options.samples;
4054 ldesOptions.seed = options.seed;
4055 % Silence the Java backend at SILENT/STD so its progress,
4056 % transient-filter, CI-method and analysis chatter does not
4057 % duplicate the MATLAB layer's SSA-style summary: MATLAB emits
4058 % the "LDES samples" line (see @SolverLDES/runAnalyzer) and the
4059 % analysis line (@NetworkSolver/setAvgResults, which for LDES
4060 % drops "Iterations" and reports
the MATLAB release as env).
4061 % This mirrors the already-clean native-binary path, which
4062 % captures Java stdout instead of echoing it. DEBUG still
4063 % forwards the Java internals for troubleshooting.
4064 if isfield(options, 'verbose')
4065 switch options.verbose
4066 case {VerboseLevel.DEBUG}
4067 ldesOptions.verbose = ldesOptions.verbose.DEBUG;
4069 ldesOptions.verbose = ldesOptions.verbose.SILENT;
4073 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
4075 ldesOptions.confint = confintLevel;
4077 ldesOptions.confint = 0;
4079 % Pass timespan
for transient analysis
4080 if isfield(options,
'timespan') && length(options.timespan) >= 2
4081 ldesOptions.timespan = options.timespan;
4083 % Warm-start initial placement (station-major vector, e.g. set
4084 % by @SolverLDES/initFromSolver from an auxiliary solver)
4085 if isfield(options, 'init_sol') && ~isempty(options.init_sol)
4086 ldesOptions.init_sol = JLINE.from_line_matrix(options.init_sol);
4088 % Pass LDES-specific options if configured
4089 if isfield(options, 'config')
4090 % Transient detection options
4091 if isfield(options.config, 'tranfilter')
4092 ldesOptions.tranfilter = options.config.tranfilter;
4094 if isfield(options.config,
'mserbatch')
4095 ldesOptions.mserbatch = options.config.mserbatch;
4097 if isfield(options.config, 'warmupfrac')
4098 ldesOptions.warmupfrac = options.config.warmupfrac;
4100 % Confidence interval options
4101 if isfield(options.config, 'cimethod')
4102 ldesOptions.cimethod = options.config.cimethod;
4104 if isfield(options.config, 'obmoverlap')
4105 ldesOptions.obmoverlap = options.config.obmoverlap;
4107 if isfield(options.config, 'ciminbatch')
4108 ldesOptions.ciminbatch = options.config.ciminbatch;
4110 if isfield(options.config, 'ciminobs')
4111 ldesOptions.ciminobs = options.config.ciminobs;
4113 if isfield(options.config, 'spectralLowFreqFrac')
4114 ldesOptions.spectralLowFreqFrac = options.config.spectralLowFreqFrac;
4116 % Convergence options
4117 if isfield(options.config, 'cnvgon')
4118 ldesOptions.cnvgon = options.config.cnvgon;
4120 if isfield(options.config, 'cnvgtol')
4121 ldesOptions.cnvgtol = options.config.cnvgtol;
4123 if isfield(options.config, 'cnvgbatch')
4124 ldesOptions.cnvgbatch = options.config.cnvgbatch;
4126 if isfield(options.config, 'cnvgchk')
4127 ldesOptions.cnvgchk = options.config.cnvgchk;
4131 ldes = jline.
solvers.ldes.SolverLDES(network_object, ldesOptions);
4134 function [mva] = SolverMVA(network_object, options)
4135 solverOptions = jline.
solvers.SolverOptions(jline.lang.constant.SolverType.MVA);
4137 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4139 mva = jline.
solvers.mva.SolverMVA(network_object, solverOptions);
4142 function [nc] = SolverNC(network_object, options)
4143 solverOptions = jline.
solvers.SolverOptions(jline.lang.constant.SolverType.NC);
4145 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4147 nc = jline.
solvers.nc.SolverNC(network_object, solverOptions);
4150 function [auto] = SolverAuto(network_object, options)
4151 solverOptions = jline.
solvers.auto.AUTOptions();
4153 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4155 auto = jline.
solvers.auto.SolverAUTO(network_object, solverOptions);
4158 function streamOpts = StreamingOptions(varargin)
4159 % STREAMINGOPTIONS Create Java StreamingOptions for SSA/LDES stream() method
4161 % @brief Creates StreamingOptions for streaming simulation metrics
4163 % @param varargin Name-value pairs for options:
4164 % 'transport' - 'http' (recommended) or 'grpc' (default: 'http')
4165 % 'endpoint' - Receiver endpoint (default: 'localhost:8080/metrics' for HTTP)
4166 % 'mode' - 'sampled' or 'time_window' (default: 'sampled')
4167 % 'sampleFrequency' - Push every N events in sampled mode (default: 100)
4168 % 'timeWindowSeconds' - Window duration in time_window mode (default: 1.0)
4169 % 'serviceName' - Service identifier (default: 'line-stream')
4170 % 'includeQueueLength' - Include queue length metrics (default: true)
4171 % 'includeUtilization' - Include utilization metrics (default: true)
4172 % 'includeThroughput' - Include throughput metrics (default: true)
4173 % 'includeResponseTime' - Include response time metrics (default: true)
4174 % 'includeArrivalRate' - Include arrival rate metrics (default: true)
4176 % @return streamOpts Java StreamingOptions
object
4180 % streamOpts = JLINE.StreamingOptions('transport', 'http', 'sampleFrequency', 50);
4183 streamOpts = jline.streaming.StreamingOptions();
4185 % Parse optional arguments
4187 addParameter(p, 'transport', 'http', @ischar);
4188 addParameter(p, 'endpoint', '', @ischar); % Empty means use default for transport
4189 addParameter(p, 'mode', 'sampled', @ischar);
4190 addParameter(p, 'sampleFrequency', 100, @isnumeric);
4191 addParameter(p, 'timeWindowSeconds', 1.0, @isnumeric);
4192 addParameter(p, 'serviceName', 'line-stream', @ischar);
4193 addParameter(p, 'includeQueueLength', true, @islogical);
4194 addParameter(p, 'includeUtilization', true, @islogical);
4195 addParameter(p, 'includeThroughput', true, @islogical);
4196 addParameter(p, 'includeResponseTime', true, @islogical);
4197 addParameter(p, 'includeArrivalRate', true, @islogical);
4198 parse(p, varargin{:});
4200 % Set transport type
4201 transportTypes = javaMethod(
'values',
'jline.streaming.StreamingOptions$TransportType');
4202 switch lower(p.Results.transport)
4204 streamOpts.transport = transportTypes(1); % HTTP
4206 streamOpts.transport = transportTypes(2); % GRPC
4208 streamOpts.transport = transportTypes(1); % Default to HTTP
4211 % Set endpoint (use provided or default based on transport)
4212 if ~isempty(p.Results.endpoint)
4213 streamOpts.endpoint = p.Results.endpoint;
4215 % If empty, StreamingOptions uses its default for
the transport type
4218 streamModes = javaMethod('values', 'jline.streaming.StreamingOptions$StreamMode');
4219 switch lower(p.Results.mode)
4221 streamOpts.mode = streamModes(1); % SAMPLED
4223 streamOpts.mode = streamModes(2); % TIME_WINDOW
4225 streamOpts.mode = streamModes(1); % Default to SAMPLED
4229 streamOpts.sampleFrequency = p.Results.sampleFrequency;
4230 streamOpts.timeWindowSeconds = p.Results.timeWindowSeconds;
4231 streamOpts.serviceName = p.Results.serviceName;
4232 streamOpts.includeQueueLength = p.Results.includeQueueLength;
4233 streamOpts.includeUtilization = p.Results.includeUtilization;
4234 streamOpts.includeThroughput = p.Results.includeThroughput;
4235 streamOpts.includeResponseTime = p.Results.includeResponseTime;
4236 streamOpts.includeArrivalRate = p.Results.includeArrivalRate;
4239 function result = convertSampleResult(jresult)
4240 % CONVERTSAMPLERESULT Convert Java sample result to MATLAB struct
4242 % @brief Converts Java SampleNodeState to MATLAB structure
4244 % @param jresult Java SampleNodeState
object
4245 % @return result MATLAB struct with fields: t, state, isaggregate
4249 % Convert time matrix
4250 if ~isempty(jresult.t)
4251 result.t = JLINE.from_jline_matrix(jresult.t);
4256 % Convert state matrix
4257 if ~isempty(jresult.state) && isa(jresult.state, 'jline.util.matrix.Matrix')
4258 result.state = JLINE.from_jline_matrix(jresult.state);
4263 result.isaggregate = jresult.isaggregate;
4266 function [ln] = SolverLN(layered_network_object, options)
4267 solverOptions = jline.
solvers.SolverOptions(jline.lang.constant.SolverType.LN);
4269 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4271 ln = jline.
solvers.ln.SolverLN(layered_network_object, solverOptions);
4274 function jfun = reward_handle_to_tabulatedfun(rewardFn, sn)
4275 % REWARD_HANDLE_TO_TABULATEDFUN Convert a MATLAB reward function
4276 % handle to a Java TabulatedRewardFunction by pre-computing its
4277 % value over an enumerable superset of
the aggregated state space.
4279 % The domain per class r
is: all per-station
count vectors with
4280 % sum <= njobs(r) for closed classes, and per-station counts capped
4281 % by classcap(i,r) (or
the default CTMC cutoff of 100 when
4282 % infinite) for open classes. The JAR reward analyzer evaluates
the
4283 % function only on reachable stateSpaceAggr rows, which are a
4284 % subset of this domain; unseen states raise a descriptive error.
4286 % @param rewardFn MATLAB reward handle @(state) or @(state, sn)
4287 % @param sn Network struct
4288 % @return jfun Java jline.lang.reward.TabulatedRewardFunction
4293 % Per-class families of feasible per-station
count vectors, with a
4294 % guard against combinatorial explosion (as in
the PAS precompute)
4295 classVecs = cell(1, K);
4298 if isfinite(sn.njobs(r)) && sn.njobs(r) > 0
4299 classVecs{r} = JLINE.reward_enum_capped(M, sn.njobs(r)*ones(1,M), sn.njobs(r));
4303 if sn.sched(i) == SchedStrategy.EXT
4304 % Source (arrival) station: it never holds jobs in
4306 % enumerating it 0..cutoff both wastes states and
4307 % multiplies
the per-class box needlessly. Cap at 0.
4311 c = sn.classcap(i,r);
4313 c = 100; %
default CTMC cutoff (see solver_ctmc_reward)
4317 classVecs{r} = JLINE.reward_enum_capped(M, caps, Inf);
4319 total = total * size(classVecs{r},1);
4321 line_error(mfilename,
'Reward pre-computation would enumerate more than 5e6 aggregated states; set finite class capacities (or smaller populations) for JLINE conversion.');
4325 % Index maps
for RewardState, as in solver_ctmc_reward
4326 nodeToStationMap = containers.Map(
'KeyType',
'int32',
'ValueType',
'int32');
4327 classToIndexMap = containers.Map(
'KeyType',
'int32',
'ValueType',
'int32');
4328 for ind = 1:sn.nnodes
4329 if sn.isstation(ind)
4330 nodeToStationMap(int32(ind)) = sn.nodeToStation(ind);
4334 classToIndexMap(int32(r)) = r;
4337 jfun = javaObject(
'jline.lang.reward.TabulatedRewardFunction');
4338 counts = zeros(1, K);
4340 counts(r) = size(classVecs{r}, 1);
4344 row = zeros(1, M*K);
4346 row(((1:M)-1)*K + r) = classVecs{r}(idx(r), :);
4348 rewardState = RewardState(row, sn, nodeToStationMap, classToIndexMap);
4349 % Try
the new single-argument API first, then
the backward
4350 % compatible @(state, sn) signature (as in solver_ctmc_reward)
4352 val = rewardFn(rewardState);
4355 val = rewardFn(row, sn);
4360 jfun.addValue(JLINE.from_line_matrix(row),
double(val));
4361 % Advance
the mixed-radix odometer over classes
4364 idx(r) = idx(r) + 1;
4365 if idx(r) <= counts(r)
4377 function V = reward_enum_capped(M, caps, budget)
4378 % REWARD_ENUM_CAPPED All integer row vectors v (1 x M) with
4379 % 0 <= v(i) <= caps(i) and sum(v) <= budget.
4381 hi = min(caps(1), budget);
4386 hi = min(caps(1), budget);
4388 Vsub = JLINE.reward_enum_capped(M-1, caps(2:end), budget - n);
4389 V = [V; [n*ones(size(Vsub,1),1), Vsub]]; %#ok<AGROW>
4393 function serfun = pas_handle_to_serializablefun(handle, nclasses, cap)
4394 % PAS_HANDLE_TO_SERIALIZABLEFUN Convert a PAS service rate function
4395 % mu(c) (MATLAB handle of the ordered class list) to a Java
4396 % SerializableFunction by pre-computing mu over every ordered prefix
4397 % up to the queue capacity.
4399 % The JAR queries mu(c) with the ordered prefix as a row vector of
4400 % 0-based class indices (jline.lang.state.AfterEventStation), and the
4401 % PrecomputedRateFunction keys on the stringified vector, so values
4402 % are stored under the matching 0-based key.
4404 % @param handle MATLAB mu(c) handle taking a 1-based ordered class list
4405 % @param nclasses Number of classes
4406 % @param cap Station capacity (max ordered-list length)
4407 % @return serfun Java PrecomputedCDFunction
4409 % Guard against combinatorial explosion of ordered sequences
4412 term = term * nclasses;
4416 line_error(mfilename, sprintf('PAS service rate pre-computation would enumerate %d ordered states (nclasses=%d, cap=%d); too large
for JLINE conversion.
', nseq, nclasses, cap));
4419 serfun = jline.util.PrecomputedRateFunction(nclasses, 0.0);
4420 JLINE.pas_enumerate_seqs(handle, serfun, nclasses, cap, []);
4423 function pas_enumerate_seqs(handle, serfun, nclasses, cap, prefix)
4424 % PAS_ENUMERATE_SEQS Recursively enumerate ordered class sequences
4425 % (1-based, length 1..cap) and store mu(prefix) under the matching
4426 % 0-based key expected by the JAR.
4428 val = handle(prefix); % mu(c), 1-based ordered list
4429 keyMat = JLINE.from_line_matrix(prefix - 1); % 0-based key (1 x p)
4430 serfun.addValue(keyMat, double(val));
4432 if length(prefix) >= cap
4436 JLINE.pas_enumerate_seqs(handle, serfun, nclasses, cap, [prefix, r]);
4440 function serfun = handle_to_serializablefun(handle, sn)
4441 % HANDLE_TO_SERIALIZABLEFUN Convert MATLAB function handle to Java SerializableFunction
4443 % This function pre-computes the function values for all possible state
4444 % combinations and creates a Java PrecomputedCDFunction object.
4446 % @param handle MATLAB function handle that takes a vector ni and returns a scalar
4447 % @param sn Network struct containing njobs (population per class)
4448 % @return serfun Java PrecomputedCDFunction object
4450 % Get number of classes and maximum populations
4451 nclasses = sn.nclasses;
4452 njobs = sn.njobs; % Population per class
4454 % For open classes (njobs=0), use a reasonable bound
4457 if maxPop(r) == 0 || isinf(maxPop(r))
4458 % For open classes, use sum of closed class populations or 100 as bound
4459 maxPop(r) = max(100, sum(njobs(isfinite(njobs) & njobs > 0)));
4463 % Create Java PrecomputedCDFunction object
4464 serfun = jline.util.PrecomputedCDFunction(nclasses);
4466 % Enumerate all possible state combinations and pre-compute function values
4467 % Use recursive enumeration to handle arbitrary number of classes
4468 JLINE.enumerate_states(handle, serfun, maxPop, zeros(1, nclasses), 1);
4471 function enumerate_states(handle, serfun, maxPop, currentState, classIdx)
4472 % ENUMERATE_STATES Recursively enumerate all state combinations
4474 % @param handle MATLAB function handle
4475 % @param serfun Java PrecomputedCDFunction object to populate
4476 % @param maxPop Maximum population per class
4477 % @param currentState Current state being built
4478 % @param classIdx Current class index being enumerated
4480 nclasses = length(maxPop);
4482 if classIdx > nclasses
4483 % We have a complete state, compute and store the function value.
4484 % Errors are deliberately NOT swallowed here: a state that fails
4485 % to tabulate falls back to the neutral scaling beta=1 on lookup,
4486 % which silently returns the UNSCALED network rather than failing.
4487 value = handle(currentState);
4488 % Convert to Java int array and add to serfun
4489 jstate = jline.util.matrix.Matrix(1, nclasses);
4491 jstate.set(0, r-1, currentState(r));
4494 % Chain-independent beta_i(n): one scaling shared by every
4495 % class, broadcast on the Java side.
4496 serfun.addValue(jstate, double(value));
4498 % Chain-specific beta_{i,r}(n): keep the per-class vector
4499 % whole (the double[] overload). Passing it to the scalar
4500 % addValue would raise, and collapsing it would drop the
4501 % per-class resolution the FES aggregation depends on.
4502 serfun.addValue(jstate, double(value(:)'));
4507 % Enumerate all populations
for current
class
4508 for n = 0:maxPop(classIdx)
4509 currentState(classIdx) = n;
4510 JLINE.enumerate_states(handle, serfun, maxPop, currentState, classIdx + 1);
4514 function result = call_java_cdscaling(jfun, ni)
4515 % CALL_JAVA_CDSCALING Call a Java SerializableFunction
for class dependence
4517 % This function converts a MATLAB vector to a Java Matrix and calls
4518 %
the Java function
's apply() method.
4520 % @param jfun Java SerializableFunction<Matrix, Double> object
4521 % @param ni MATLAB vector representing the state (jobs per class)
4522 % @return result The scaling factor returned by the Java function
4524 % Convert MATLAB vector to Java Matrix
4526 jmatrix = jline.util.matrix.Matrix(1, length(ni));
4527 for r = 1:length(ni)
4528 jmatrix.set(0, r-1, ni(r));
4531 jmatrix = jline.util.matrix.Matrix(length(ni), 1);
4532 for r = 1:length(ni)
4533 jmatrix.set(r-1, 0, ni(r));
4537 % Call the Java function and convert result to MATLAB double
4538 jresult = jfun.apply(jmatrix);
4539 result = double(jresult);
4542 function jSched = to_jline_sched_strategy(schedId)
4543 % Convert MATLAB SchedStrategy id to jline SchedStrategy enum
4545 case SchedStrategy.REF
4546 jSched = jline.lang.constant.SchedStrategy.REF;
4547 case SchedStrategy.INF
4548 jSched = jline.lang.constant.SchedStrategy.INF;
4549 case SchedStrategy.FCFS
4550 jSched = jline.lang.constant.SchedStrategy.FCFS;
4551 case SchedStrategy.LCFS
4552 jSched = jline.lang.constant.SchedStrategy.LCFS;
4553 case SchedStrategy.SIRO
4554 jSched = jline.lang.constant.SchedStrategy.SIRO;
4555 case SchedStrategy.SJF
4556 jSched = jline.lang.constant.SchedStrategy.SJF;
4557 case SchedStrategy.LJF
4558 jSched = jline.lang.constant.SchedStrategy.LJF;
4559 case SchedStrategy.PS
4560 jSched = jline.lang.constant.SchedStrategy.PS;
4561 case SchedStrategy.DPS
4562 jSched = jline.lang.constant.SchedStrategy.DPS;
4563 case SchedStrategy.GPS
4564 jSched = jline.lang.constant.SchedStrategy.GPS;
4565 case SchedStrategy.SEPT
4566 jSched = jline.lang.constant.SchedStrategy.SEPT;
4567 case SchedStrategy.LEPT
4568 jSched = jline.lang.constant.SchedStrategy.LEPT;
4569 case SchedStrategy.HOL
4570 % preserve HOL (exact M/G/1 priority in the JAR) rather than
4571 % collapsing to FCFSPRIO (egflin approximation)
4572 jSched = jline.lang.constant.SchedStrategy.HOL;
4573 case SchedStrategy.FCFSPRIO
4574 jSched = jline.lang.constant.SchedStrategy.FCFSPRIO;
4575 case SchedStrategy.FORK
4576 jSched = jline.lang.constant.SchedStrategy.FORK;
4577 case SchedStrategy.EXT
4578 jSched = jline.lang.constant.SchedStrategy.EXT;
4579 case SchedStrategy.LCFSPR
4580 jSched = jline.lang.constant.SchedStrategy.LCFSPR;
4581 case SchedStrategy.PSPRIO
4582 jSched = jline.lang.constant.SchedStrategy.PSPRIO;
4583 case SchedStrategy.DPSPRIO
4584 jSched = jline.lang.constant.SchedStrategy.DPSPRIO;
4585 case SchedStrategy.GPSPRIO
4586 jSched = jline.lang.constant.SchedStrategy.GPSPRIO;
4588 jSched = jline.lang.constant.SchedStrategy.FCFS;
4592 function tf = is_custom_handle(funCell, e, h, defaultStr)
4593 % IS_CUSTOM_HANDLE True if funCell{e,h} is a function handle that
4594 % differs from the given identity default (whitespace-insensitive
4595 % func2str comparison).
4597 if isempty(funCell) || size(funCell,1) < e || size(funCell,2) < h
4601 if isempty(fh) || ~isa(fh, 'function_handle
')
4604 tf = ~strcmp(regexprep(func2str(fh), '\s+', ''), defaultStr);
4607 function jwf = from_line_workflow(line_wf)
4608 % Convert a MATLAB Workflow to a JAR Workflow.
4609 jwf = javaObject(
'jline.lang.workflow.Workflow', java.lang.String(line_wf.getName()));
4610 acts = line_wf.activities;
4611 for a = 1:length(acts)
4613 actName = java.lang.String(act.name);
4614 if ~isempty(act.hostDemand) && isa(act.hostDemand,
'Distribution')
4615 jdist = JLINE.from_line_distribution(act.hostDemand);
4616 jwf.addActivity(actName, jdist);
4618 jwf.addActivity(actName, 1.0);
4621 precs = line_wf.precedences;
4622 for p = 1:length(precs)
4624 preActs = java.util.ArrayList();
4625 for k = 1:length(prec.preActs)
4626 preActs.add(java.lang.String(prec.preActs{k}));
4628 postActs = java.util.ArrayList();
4629 for k = 1:length(prec.postActs)
4630 postActs.add(java.lang.String(prec.postActs{k}));
4632 preTypeStr = java.lang.String(ActivityPrecedenceType.toText(prec.preType));
4633 postTypeStr = java.lang.String(ActivityPrecedenceType.toText(prec.postType));
4634 if ~isempty(prec.preParams)
4635 preParamsMat = JLINE.from_line_matrix(prec.preParams(:)');
4637 preParamsMat = javaObject('jline.util.matrix.Matrix', 0, 0);
4639 if ~isempty(prec.postParams)
4640 postParamsMat = JLINE.from_line_matrix(prec.postParams(:)');
4642 postParamsMat = javaObject('jline.util.matrix.Matrix', 0, 0);
4644 jprec = javaObject('jline.lang.layered.ActivityPrecedence', ...
4645 preActs, postActs, preTypeStr, postTypeStr, preParamsMat, postParamsMat);
4646 jwf.addPrecedence(jprec);
4650 function jenv = from_line_environment(line_env)
4651 % Convert a MATLAB Environment to a JAR Environment.
4652 E = height(line_env.envGraph.Nodes);
4653 jenv = javaObject('jline.lang.Environment', java.lang.String(line_env.getName()), int32(E));
4655 stageName =
char(line_env.envGraph.Nodes.Name{e});
4656 stageType = char(line_env.envGraph.Nodes.Type{e});
4657 stageModel = line_env.ensemble{e};
4658 jmodel = JLINE.from_line_network(stageModel);
4659 jenv.addStage(int32(e-1), java.lang.String(stageName), java.lang.String(stageType), jmodel);
4661 if ~isempty(line_env.env)
4662 [Erows, Ecols] = size(line_env.env);
4665 d = line_env.env{e,h};
4666 if isempty(d) || isa(d,
'Disabled')
4669 % Custom reset functions are MATLAB handles over a
4670 % continuous domain and cannot be marshalled to
the JAR
4671 % functional interfaces; error out rather than silently
4672 % dropping a non-identity reset policy.
4673 if JLINE.is_custom_handle(line_env.resetFun, e, h, '@(q)q') ...
4674 || JLINE.is_custom_handle(line_env.resetEnvRatesFun, e, h, '@(originalDist,QExit,UExit,TExit)originalDist') ...
4675 || JLINE.is_custom_handle(line_env.resetStateFun, e, h, '@(pi)pi')
4676 line_error(mfilename, sprintf('JLINE conversion cannot marshal
the custom reset function on Environment transition %d->%d (resetFun/resetEnvRatesFun/resetStateFun); use
the MATLAB-native SolverENV for this model.', e, h));
4678 jdist = JLINE.from_line_distribution(d);
4679 jenv.addTransition(int32(e-1), int32(h-1), jdist);