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 rebuilt from (type,mean,scv,params) -- see _kb/12-interfaces-and-docs.md
197 if sn.isfunction(tidx) && ~isnan(sn.setuptime_mean(tidx)) && sn.setuptime_mean(tidx) > 1e-8
198 T{t}.setSetupTime(JLINE.from_line_lqn_dist(sn.setuptime_type(tidx), ...
199 sn.setuptime_mean(tidx), sn.setuptime_scv(tidx), ...
200 sn.setuptime_params{tidx}, sn.setuptime_proc{tidx}));
203 if sn.isfunction(tidx) && ~isnan(sn.delayofftime_mean(tidx)) && sn.delayofftime_mean(tidx) > 1e-8
204 T{t}.setDelayOffTime(JLINE.from_line_lqn_dist(sn.delayofftime_type(tidx), ...
205 sn.delayofftime_mean(tidx), sn.delayofftime_scv(tidx), ...
206 sn.delayofftime_params{tidx}, sn.delayofftime_proc{tidx}));
210 E = cell(1,sn.nentries);
213 % Check
if this is an ItemEntry (has nitems > 0)
214 if sn.nitems(eidx) > 0
215 % ItemEntry requires cardinality and popularity distribution
216 if ~isempty(sn.itemproc) && ~isempty(sn.itemproc{eidx})
217 jPopularity = JLINE.from_line_distribution(sn.itemproc{eidx});
219 % Default to uniform distribution
220 jPopularity = javaObject(
'jline.lang.processes.DiscreteSampler', jline.util.matrix.Matrix.uniformDistribution(sn.nitems(eidx)));
222 E{e} = javaObject(
'jline.lang.layered.ItemEntry', model, sn.names{eidx}, sn.nitems(eidx), jPopularity);
224 E{e} = javaObject(
'jline.lang.layered.Entry', model, sn.names{eidx});
226 E{e}.on(T{sn.parent(eidx)-sn.tshift});
227 % Open arrival gated on arrival_mean, not arrival_type -- see _kb/12-interfaces-and-docs.md
228 if ~isnan(sn.arrival_mean(eidx)) && sn.arrival_mean(eidx) > 0
229 E{e}.setArrival(JLINE.from_line_lqn_dist(sn.arrival_type(eidx), ...
230 sn.arrival_mean(eidx), sn.arrival_scv(eidx), ...
231 sn.arrival_params{eidx}, sn.arrival_proc{eidx}));
236 A = cell(1,sn.nacts);
239 tidx = sn.parent(aidx);
240 onTask = tidx-sn.tshift;
241 % Convert host demand from primitives to Java distribution
242 switch sn.hostdem_type(aidx)
243 case ProcessType.IMMEDIATE
244 jHostDem = jline.lang.processes.Immediate;
245 case ProcessType.DISABLED
246 jHostDem = jline.lang.processes.Disabled;
248 jHostDem = javaObject(
'jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
249 case ProcessType.ERLANG
250 jHostDem = jline.lang.processes.Erlang.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
251 case ProcessType.HYPEREXP
252 if ~isempty(sn.hostdem_params{aidx}) && length(sn.hostdem_params{aidx}) >= 3
253 jHostDem = javaObject(
'jline.lang.processes.HyperExp', sn.hostdem_params{aidx}(1), sn.hostdem_params{aidx}(2), sn.hostdem_params{aidx}(3));
255 jHostDem = jline.lang.processes.HyperExp.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
257 case ProcessType.COXIAN
258 jHostDem = jline.lang.processes.Coxian.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
260 jHostDem = jline.lang.processes.APH.fitMeanAndSCV(sn.hostdem_mean(aidx), sn.hostdem_scv(aidx));
262 if ~isempty(sn.hostdem_proc{aidx})
263 proc = sn.hostdem_proc{aidx};
264 jHostDem = javaObject(
'jline.lang.processes.PH', JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2}));
266 jHostDem = javaObject(
'jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
269 if ~isempty(sn.hostdem_proc{aidx})
270 proc = sn.hostdem_proc{aidx};
271 jHostDem = javaObject(
'jline.lang.processes.MAP', JLINE.from_line_matrix(proc{1}), JLINE.from_line_matrix(proc{2}));
273 jHostDem = javaObject(
'jline.lang.processes.Exp', 1/sn.hostdem_mean(aidx));
276 jHostDem = javaObject(
'jline.lang.processes.Det', sn.hostdem_mean(aidx));
277 case ProcessType.UNIFORM
278 p = sn.hostdem_params{aidx};
279 jHostDem = javaObject(
'jline.lang.processes.Uniform', p(1), p(2));
280 case ProcessType.GAMMA
281 p = sn.hostdem_params{aidx};
282 jHostDem = javaObject(
'jline.lang.processes.Gamma', p(1), p(2));
283 case ProcessType.PARETO
284 p = sn.hostdem_params{aidx};
285 jHostDem = javaObject(
'jline.lang.processes.Pareto', p(1), p(2));
286 case ProcessType.WEIBULL
287 p = sn.hostdem_params{aidx};
288 jHostDem = javaObject(
'jline.lang.processes.Weibull', p(1), p(2));
289 case ProcessType.LOGNORMAL
290 p = sn.hostdem_params{aidx};
291 jHostDem = javaObject(
'jline.lang.processes.Lognormal', p(1), p(2));
293 line_error(mfilename,sprintf(
'JLINE conversion does not support the %s distribution for host demand yet.',
char(sn.hostdem_type(aidx))));
295 A{a} = javaObject(
'jline.lang.layered.Activity', model, sn.names{aidx}, jHostDem);
298 boundTo = find(sn.graph((sn.eshift+1):(sn.eshift+sn.nentries),aidx));
301 A{a}.boundTo(E{boundTo});
304 if sn.sched(tidx) ~= SchedStrategy.REF % ref tasks don
't reply
305 repliesTo = find(sn.replygraph(a,:)); % index of entry
306 if ~isempty(repliesTo)
307 if ~sn.isref(sn.parent(sn.eshift+repliesTo))
308 A{a}.repliesTo(E{repliesTo});
313 if ~isempty(sn.callpair)
314 cidxs = find(sn.callpair(:,1)==aidx);
315 calls = sn.callpair(:,2);
317 switch sn.calltype(c)
319 A{a}.synchCall(E{calls(c)-sn.eshift},sn.callproc_mean(c));
321 A{a}.asynchCall(E{calls(c)-sn.eshift},sn.callproc_mean(c));
330 if ~isempty(sn.think{h}) && sn.think_type(h) ~= ProcessType.DISABLED
331 switch sn.think_type(h)
332 case ProcessType.IMMEDIATE
333 P{h}.setThinkTime(jline.lang.processes.Immediate);
335 P{h}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(h)));
336 case ProcessType.ERLANG
337 P{h}.setThinkTime(jline.lang.processes.Erlang.fitMeanAndSCV(sn.think_mean(h),sn.think_scv(h)));
338 case ProcessType.HYPEREXP
339 % For HyperExp, reconstruct from params
if available, otherwise use fitMeanAndSCV
340 if ~isempty(sn.think_params{h}) && length(sn.think_params{h}) >= 3
341 P{h}.setThinkTime(jline.lang.processes.HyperExp(sn.think_params{h}(1), sn.think_params{h}(2), sn.think_params{h}(3)));
343 P{h}.setThinkTime(jline.lang.processes.HyperExp.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
345 case ProcessType.COXIAN
346 % For Coxian, use fitMeanAndSCV
347 P{h}.setThinkTime(jline.lang.processes.Coxian.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
349 % For APH, reconstruct from params
if available
350 if ~isempty(sn.think_params{h})
351 P{h}.setThinkTime(jline.lang.processes.APH.fitMeanAndSCV(sn.think_mean(h), sn.think_scv(h)));
353 P{h}.setThinkTime(jline.lang.processes.Exp(1/sn.think_mean(h)));
356 P{h}.setThinkTime(jline.lang.processes.Det(sn.think_mean(h)));
357 case ProcessType.UNIFORM
358 p = sn.think_params{h};
359 P{h}.setThinkTime(jline.lang.processes.Uniform(p(1), p(2)));
360 case ProcessType.GAMMA
361 p = sn.think_params{h};
362 P{h}.setThinkTime(jline.lang.processes.Gamma(p(1), p(2)));
363 case ProcessType.PARETO
364 p = sn.think_params{h};
365 P{h}.setThinkTime(jline.lang.processes.Pareto(p(1), p(2)));
366 case ProcessType.WEIBULL
367 p = sn.think_params{h};
368 P{h}.setThinkTime(jline.lang.processes.Weibull(p(1), p(2)));
369 case ProcessType.LOGNORMAL
370 p = sn.think_params{h};
371 P{h}.setThinkTime(jline.lang.processes.Lognormal(p(1), p(2)));
373 line_error(mfilename,sprintf(
'JLINE conversion does not support the %s distribution yet.',
char(sn.think_type(h))));
378 %% Sequential precedences
380 aidx = sn.ashift + ai;
381 tidx = sn.parent(aidx);
383 for bidx=find(sn.graph(aidx,:))
384 if bidx > sn.ashift % ignore precedence between entries and activities
385 % Serial pattern (SEQ)
386 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_SEQ && full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_SEQ
387 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.Serial(sn.names{aidx}, sn.names{bidx}));
393 %% Loop precedences (POST_LOOP)
394 % sn.graph loop encoding -- see _kb/04-networkstruct.md
395 processedLoops = false(1, sn.nacts);
397 aidx = sn.ashift + ai;
398 tidx = sn.parent(aidx);
399 % Check
if this activity starts a loop (has a successor with POST_LOOP type)
400 % and hasn
't been processed as part of another loop
401 if processedLoops(ai)
405 successors = find(sn.graph(aidx,:));
406 for bidx = successors
407 if bidx > sn.ashift && full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_LOOP
408 % Skip if this loop body activity was already processed
409 if processedLoops(bidx - sn.ashift)
412 % Found start of a loop: aidx is the entry, bidx is first loop body activity
414 precActs = java.util.ArrayList();
416 % Follow the chain of POST_LOOP activities
419 precActs.add(sprintf("%s", sn.names{curIdx}));
420 processedLoops(curIdx - sn.ashift) = true;
422 % Find successors of current activity
423 curSuccessors = find(sn.graph(curIdx,:));
424 curSuccessors = curSuccessors(curSuccessors > sn.ashift);
426 % Check for loop termination: find the end activity
427 % End activity has weight = 1/counts (not the back-edge weight)
430 for succIdx = curSuccessors
431 if full(sn.actposttype(succIdx)) == ActivityPrecedenceType.POST_LOOP
432 if succIdx == loopStart
433 % This is the back-edge, skip it
436 weight = full(sn.graph(curIdx, succIdx));
437 if weight > 0 && weight < 1
438 % This is the end activity (weight = 1/counts)
441 % This is the next activity in the loop body (weight = 1.0)
448 % Found end activity - calculate counts and output
449 weight = full(sn.graph(curIdx, endIdx));
453 counts = 1; % Fallback to prevent division by zero
455 precActs.add(sprintf("%s", sn.names{endIdx}));
456 processedLoops(endIdx - sn.ashift) = true;
458 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.Loop(sn.names{aidx}, precActs, jline.util.matrix.Matrix(counts)));
461 % Continue to next activity in loop body
464 % No more successors - shouldn't happen in valid loop
468 break; % Only process one loop starting from
this activity
473 %% OrFork precedences (POST_OR)
477 aidx = sn.ashift + ai;
478 tidx = sn.parent(aidx);
481 for bidx=find(sn.graph(aidx,:))
482 if bidx > sn.ashift % ignore precedence between entries and activities
483 % Or pattern (POST_OR)
484 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_OR
485 if precMarker == 0 % start a new orjoin
486 precActs = java.util.ArrayList();
487 precMarker = aidx-sn.ashift;
488 precActs.add(sprintf(
"%s", sn.names{bidx}));
489 probs=full(sn.graph(aidx,bidx));
491 precActs.add(sprintf(
"%s", sn.names{bidx}));
492 probs(end+1)=full(sn.graph(aidx,bidx));
500 probsMatrix = jline.util.matrix.Matrix(1,length(probs));
501 for i=1:length(probs)
502 probsMatrix.set(0,i-1,probs(i));
504 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.OrFork(sn.names{precMarker+sn.ashift}, precActs, probsMatrix));
509 %% AndFork precedences (POST_AND)
513 aidx = sn.ashift + ai;
514 tidx = sn.parent(aidx);
516 for bidx=find(sn.graph(aidx,:))
517 if bidx > sn.ashift % ignore precedence between entries and activities
518 % Or pattern (POST_AND)
519 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_AND
521 postActs = java.util.ArrayList();
522 postActs.add(sprintf(
"%s", sn.names{bidx}));
524 postActs.add(sprintf(
"%s", sn.names{bidx}));
527 if precMarker == 0 % start a
new orjoin
528 precMarker = aidx-sn.ashift;
534 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndFork(sn.names{precMarker+sn.ashift}, postActs));
539 %% CacheAccess precedences (POST_CACHE)
543 aidx = sn.ashift + ai;
544 tidx = sn.parent(aidx);
546 for bidx=find(sn.graph(aidx,:))
547 if bidx > sn.ashift % ignore precedence between entries and activities
548 % CacheAccess pattern (POST_CACHE)
549 if full(sn.actposttype(bidx)) == ActivityPrecedenceType.POST_CACHE
551 postActs = java.util.ArrayList();
552 postActs.add(sprintf(
"%s", sn.names{bidx}));
554 postActs.add(sprintf(
"%s", sn.names{bidx}));
557 if precMarker == 0 % start a
new cache access
558 precMarker = aidx-sn.ashift;
564 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.CacheAccess(sn.names{precMarker+sn.ashift}, postActs));
570 %% OrJoin precedences (PRE_OR)
572 for bi = sn.nacts:-1:1
573 bidx = sn.ashift + bi;
574 tidx = sn.parent(bidx);
575 %
for all predecessors
576 for aidx=find(sn.graph(:,bidx))
'
577 if aidx > sn.ashift % ignore precedence between entries and activities
578 % OrJoin pattern (PRE_OR)
579 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_OR
580 if precMarker == 0 % start a new orjoin
581 precActs = java.util.ArrayList();
582 precMarker = bidx-sn.ashift;
583 precActs.add(sprintf("%s", sn.names{aidx}));
585 precActs.add(sprintf("%s", sn.names{aidx}));
591 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.OrJoin(precActs, sn.names{precMarker+sn.ashift}));
596 %% AndJoin precedences (PRE_AND)
598 for bi = sn.nacts:-1:1
599 bidx = sn.ashift + bi;
600 tidx = sn.parent(bidx);
601 % for all predecessors
602 for aidx=find(sn.graph(:,bidx))'
603 if aidx > sn.ashift % ignore precedence between entries and activities
604 % OrJoin pattern (PRE_AND)
605 if full(sn.actpretype(aidx)) == ActivityPrecedenceType.PRE_AND
606 if precMarker == 0 % start a new orjoin
607 precActs = java.util.ArrayList();
608 precMarker = bidx-sn.ashift;
609 precActs.add(sprintf(
"%s", sn.names{aidx}));
611 precActs.add(sprintf(
"%s", sn.names{aidx}));
617 % Find quorum parameter from original precedence structure
618 postActName = sn.names{precMarker+sn.ashift};
619 localTaskIdx = tidx - sn.tshift;
621 for ap = 1:length(line_layered_network.tasks{localTaskIdx}.precedences)
622 precedence = line_layered_network.tasks{localTaskIdx}.precedences(ap);
623 if precedence.preType == ActivityPrecedenceType.PRE_AND
624 % Check
if this precedence contains our post activity
625 if any(strcmp(precedence.postActs, postActName))
626 quorum = precedence.preParams;
633 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndJoin(precActs, sn.names{precMarker+sn.ashift}));
635 T{tidx-sn.tshift}.addPrecedence(jline.lang.layered.ActivityPrecedence.AndJoin(precActs, sn.names{precMarker+sn.ashift}, quorum));
643 function jdist = from_line_distribution(line_dist)
644 if isa(line_dist,
'Exp')
645 jdist = javaObject('jline.lang.processes.Exp', line_dist.getParam(1).paramValue);
646 elseif isa(line_dist, "APH")
647 alpha = line_dist.getParam(1).paramValue;
648 T = line_dist.getParam(2).paramValue;
649 jline_alpha = java.util.ArrayList();
650 for i = 1:length(alpha)
651 jline_alpha.add(alpha(i));
653 jline_T = JLINE.from_line_matrix(T);
654 jdist = javaObject('jline.lang.processes.APH', jline_alpha, jline_T);
655 elseif isa(line_dist, 'Coxian')
656 jline_mu = java.util.ArrayList();
657 jline_phi = java.util.ArrayList();
658 if length(line_dist.params) == 3
659 jline_mu.add(line_dist.getParam(1).paramValue);
660 jline_mu.add(line_dist.getParam(2).paramValue);
661 jline_phi.add(line_dist.getParam(3).paramValue);
663 mu = line_dist.getParam(1).paramValue;
664 phi = line_dist.getParam(2).paramValue;
668 for i = 1:length(phi)
669 jline_phi.add(phi(i));
672 jdist = javaObject('jline.lang.processes.Coxian', jline_mu, jline_phi);
673 elseif isa(line_dist, 'Det')
674 jdist = javaObject('jline.lang.processes.Det', line_dist.getParam(1).paramValue);
675 elseif isa(line_dist, 'DiscreteSampler')
676 popularity_p = JLINE.from_line_matrix(line_dist.getParam(1).paramValue);
677 popularity_val = JLINE.from_line_matrix(line_dist.getParam(2).paramValue);
678 jdist = javaObject('jline.lang.processes.DiscreteSampler', popularity_p, popularity_val);
679 elseif isa(line_dist, 'Erlang')
680 jdist = javaObject('jline.lang.processes.Erlang', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
681 elseif isa(line_dist, 'Gamma')
682 jdist = javaObject('jline.lang.processes.Gamma', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
683 elseif isa(line_dist, "HyperExp")
684 jdist = javaObject('jline.lang.processes.HyperExp', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue, line_dist.getParam(3).paramValue);
685 elseif isa(line_dist, 'Lognormal')
686 jdist = javaObject('jline.lang.processes.Lognormal', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
687 elseif isa(line_dist, 'Pareto')
688 jdist = javaObject('jline.lang.processes.Pareto', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
689 elseif isa(line_dist, 'MAP')
692 jdist = javaObject('jline.lang.processes.MAP', JLINE.from_line_matrix(D0), JLINE.from_line_matrix(D1));
693 elseif isa(line_dist, 'MMPP2')
694 lambda0 = line_dist.getParam(1).paramValue;
695 lambda1 = line_dist.getParam(2).paramValue;
696 sigma0 = line_dist.getParam(3).paramValue;
697 sigma1 = line_dist.getParam(4).paramValue;
698 jdist = javaObject('jline.lang.processes.MMPP2', lambda0, lambda1, sigma0, sigma1);
699 elseif isa(line_dist, 'NHPP')
700 jdist = javaObject('jline.lang.processes.NHPP', line_dist.getBreakpoints(), line_dist.getRates(), logical(line_dist.isCyclic()));
701 elseif isa(line_dist, 'BMAP') % before MarkedMAP (BMAP < MarkedMAP)
702 % Both sides use MarkedMAP layout {D0,D1_total,D1..DK} -- see _kb/12-interfaces-and-docs.md
703 nmp = length(line_dist.process);
704 jD = javaArray(
'jline.util.matrix.Matrix', nmp);
706 jD(k) = JLINE.from_line_matrix(line_dist.process{k});
708 jdist = javaObject(
'jline.lang.processes.BMAP', javaObject(
'jline.util.matrix.MatrixCell', jD));
709 elseif isa(line_dist,
'MarkedMMPP')
710 nmp = length(line_dist.params); % {D0, D1, D11..D1K}
711 jD = javaArray(
'jline.util.matrix.Matrix', nmp);
713 jD(k) = JLINE.from_line_matrix(line_dist.getParam(k).paramValue);
715 jdist = javaObject(
'jline.lang.processes.MarkedMMPP', javaObject(
'jline.util.matrix.MatrixCell', jD));
716 elseif isa(line_dist,
'MarkedMAP')
717 nmp = length(line_dist.params); % {D0, D1, D11..D1K}
718 jD = javaArray(
'jline.util.matrix.Matrix', nmp);
720 jD(k) = JLINE.from_line_matrix(line_dist.getParam(k).paramValue);
722 jdist = javaObject(
'jline.lang.processes.MarkedMAP', javaObject(
'jline.util.matrix.MatrixCell', jD));
723 elseif isa(line_dist,
'DMAP')
724 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)));
725 elseif isa(line_dist, 'ME')
726 jdist = javaObject('jline.lang.processes.ME', JLINE.from_line_matrix(line_dist.getParam(1).paramValue), JLINE.from_line_matrix(line_dist.getParam(2).paramValue));
727 elseif isa(line_dist, 'RAP')
728 jdist = javaObject('jline.lang.processes.RAP', JLINE.from_line_matrix(line_dist.getParam(1).paramValue), JLINE.from_line_matrix(line_dist.getParam(2).paramValue));
729 elseif isa(line_dist, 'MMDP2') % before MMDP (MMDP2 < MMDP)
730 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);
731 elseif isa(line_dist, 'MMDP')
732 jdist = javaObject('jline.lang.processes.MMDP', JLINE.from_line_matrix(line_dist.getParam(1).paramValue), JLINE.from_line_matrix(line_dist.getParam(2).paramValue));
733 elseif isa(line_dist, 'Normal')
734 jdist = javaObject('jline.lang.processes.Normal', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
735 elseif isa(line_dist, 'Bernoulli')
736 jdist = javaObject('jline.lang.processes.Bernoulli', line_dist.getParam(1).paramValue);
737 elseif isa(line_dist, 'Geometric')
738 jdist = javaObject('jline.lang.processes.Geometric', line_dist.getParam(1).paramValue);
739 elseif isa(line_dist, 'Poisson')
740 jdist = javaObject('jline.lang.processes.Poisson', line_dist.getParam(1).paramValue);
741 elseif isa(line_dist, 'Binomial')
742 jdist = javaObject('jline.lang.processes.Binomial', int32(line_dist.getParam(1).paramValue), line_dist.getParam(2).paramValue);
743 elseif isa(line_dist, 'DiscreteUniform')
744 jdist = javaObject('jline.lang.processes.DiscreteUniform', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
745 elseif isa(line_dist, 'EmpiricalCDF')
746 % MATLAB stores data as [cdf, x]
column pairs; the JAR two-argument
747 % constructor takes (cdfdata, xdata)
748 if size(line_dist.data, 2) >= 2
749 jdist = javaObject('jline.lang.processes.EmpiricalCDF', JLINE.from_line_matrix(line_dist.data(:,1)), JLINE.from_line_matrix(line_dist.data(:,2)));
751 jdist = javaObject('jline.lang.processes.EmpiricalCDF', JLINE.from_line_matrix(line_dist.data));
753 elseif isa(line_dist, 'PH')
754 alpha = line_dist.getParam(1).paramValue;
755 T = line_dist.getParam(2).paramValue;
756 jdist = javaObject('jline.lang.processes.PH', JLINE.from_line_matrix(alpha), JLINE.from_line_matrix(T));
757 elseif isa(line_dist, 'Uniform')
758 jdist = javaObject('jline.lang.processes.Uniform', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
759 elseif isa(line_dist, 'Weibull')
760 jdist = javaObject('jline.lang.processes.Weibull', line_dist.getParam(1).paramValue, line_dist.getParam(2).paramValue);
761 elseif isa(line_dist, 'Zipf')
762 jdist = javaObject('jline.lang.processes.Zipf', line_dist.getParam(3).paramValue, line_dist.getParam(4).paramValue);
763 elseif isa(line_dist, 'Immediate')
764 jdist = javaObject('jline.lang.processes.Immediate');
765 elseif isempty(line_dist) || isa(line_dist, 'Disabled')
766 jdist = javaObject('jline.lang.processes.Disabled');
768 elseif isa(line_dist, 'Trace') % before Replayer (Trace < Replayer)
769 jdist = javaObject('jline.lang.processes.Trace', line_dist.params{1}.paramValue);
770 elseif isa(line_dist,
'Replayer')
771 jdist = javaObject('jline.lang.processes.Replayer', line_dist.params{1}.paramValue);
772 elseif isa(line_dist,
'Prior')
773 % Convert Prior: each alternative
is a distribution
774 dists = line_dist.getParam(1).paramValue;
775 probs = line_dist.getParam(2).paramValue;
776 jdists = java.util.ArrayList();
777 for k = 1:length(dists)
778 jdists.add(JLINE.from_line_distribution(dists{k}));
780 jdist = javaObject(
'jline.lang.processes.Prior', jdists, probs);
782 line_error(mfilename,
'Distribution not supported by JLINE.');
786 function [jRemDist, jRemPol] = from_line_signal_removal(line_class)
787 % FROM_LINE_SIGNAL_REMOVAL Marshal a signal
class's batch-removal
788 % distribution and removal policy. Returns empties when the class
789 % uses the defaults (remove exactly 1, RANDOM policy), so callers
790 % can keep using the short JAR constructors in that case.
793 if isprop(line_class, 'removalDistribution
') && ~isempty(line_class.removalDistribution) ...
794 && ~isa(line_class.removalDistribution, 'Disabled
')
795 jRemDist = JLINE.from_line_distribution(line_class.removalDistribution);
797 if isprop(line_class, 'removalPolicy
') && ~isempty(line_class.removalPolicy)
798 if ~isempty(jRemDist) || line_class.removalPolicy ~= RemovalPolicy.RANDOM
799 jRemPol = jline.lang.constant.RemovalPolicy.fromID(int32(line_class.removalPolicy));
801 elseif ~isempty(jRemDist)
802 jRemPol = jline.lang.constant.RemovalPolicy.RANDOM;
806 function matlab_dist = from_jline_distribution(jdist)
807 if isa(jdist, 'jline.lang.processes.Exp
')
808 matlab_dist = Exp(jdist.getRate());
809 elseif isa(jdist, 'jline.lang.processes.Det
')
810 matlab_dist = Det(jdist.getParam(1).getValue);
811 elseif isa(jdist, 'jline.lang.processes.Erlang
')
812 matlab_dist = Erlang(jdist.getParam(1).getValue(),jdist.getNumberOfPhases());
813 elseif isa(jdist, 'jline.lang.processes.Gamma
')
814 matlab_dist = Gamma(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
815 elseif isa(jdist, 'jline.lang.processes.HyperExp
')
816 matlab_dist = HyperExp(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue);
817 elseif isa(jdist, 'jline.lang.processes.Lognormal
')
818 matlab_dist = Lognormal(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
819 elseif isa(jdist, 'jline.lang.processes.Pareto
')
820 matlab_dist = Pareto(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
821 elseif isa(jdist, 'jline.lang.processes.Uniform
')
822 matlab_dist = Uniform(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
823 elseif isa(jdist, 'jline.lang.processes.Weibull
')
824 matlab_dist = Weibull(jdist.getParam(1).getValue,jdist.getParam(2).getValue);
825 elseif isa(jdist, 'jline.lang.processes.MAP
')
826 D0 = JLINE.from_jline_matrix(jdist.D(0));
827 D1 = JLINE.from_jline_matrix(jdist.D(1));
828 matlab_dist = MAP({D0, D1});
829 elseif isa(jdist, 'jline.lang.processes.APH
')
830 alpha = JLINE.from_jline_matrix(jdist.getInitProb());
831 T = JLINE.from_jline_matrix(jdist.getSubgenerator());
832 matlab_dist = APH(alpha(:)', T);
833 elseif isa(jdist,
'jline.lang.processes.PH')
834 alpha = JLINE.from_jline_matrix(jdist.getInitProb());
835 T = JLINE.from_jline_matrix(jdist.getSubgenerator());
836 matlab_dist = PH(alpha(:)', T);
837 elseif isa(jdist, 'jline.lang.processes.Coxian')
838 if jdist.getNumberOfPhases == 2
839 matlab_dist = Coxian([jdist.getParam(1).getValue.get(0), jdist.getParam(1).getValue.get(1)], [jdist.getParam(2).getValue.get(0),1]);
841 jmu = jdist.getParam(1).getValue;
842 jphi = jdist.getParam(2).getValue;
843 mu = zeros(1, jmu.size);
844 phi = zeros(1, jphi.size);
846 mu(i) = jmu.get(i-1);
849 phi(i) = jphi.get(i-1);
851 matlab_dist = Coxian(mu, phi);
853 elseif isa(jdist, 'jline.lang.processes.Zipf')
854 matlab_dist = Zipf(jdist.getParam(3).getValue, jdist.getParam(4).getValue);
855 elseif isa(jdist, 'jline.lang.processes.DiscreteSampler')
856 jpMat = jdist.getParam(1).getValue;
857 jxMat = jdist.getParam(2).getValue;
858 p = zeros(1, jpMat.length);
859 x = zeros(1, jxMat.length);
860 for i = 1:jpMat.length
861 p(i) = jpMat.get(i-1);
863 for i = 1:jxMat.length
864 x(i) = jxMat.get(i-1);
866 matlab_dist = DiscreteSampler(p, x);
867 elseif isa(jdist, 'jline.lang.processes.Immediate')
868 matlab_dist = Immediate();
869 elseif isa(jdist, 'jline.lang.processes.Disabled')
870 matlab_dist = Disabled();
871 elseif isa(jdist, 'jline.lang.processes.MMPP2')
872 matlab_dist = MMPP2(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue, jdist.getParam(4).getValue);
873 elseif isa(jdist, 'jline.lang.processes.NHPP')
874 jBp = jdist.getBreakpoints();
875 jRates = jdist.getRates();
876 bp = zeros(1, length(jBp));
877 rates = zeros(1, length(jRates));
878 for k = 1:length(jBp)
881 for k = 1:length(jRates)
882 rates(k) = jRates(k);
884 matlab_dist = NHPP(bp, rates, logical(jdist.isCyclic()));
885 elseif isa(jdist, 'jline.lang.processes.Prior')
886 % Convert Prior from JAR to MATLAB
887 jdists = jdist.getDistributions();
888 nalt = jdists.size();
889 dists = cell(1, nalt);
891 dists{k} = JLINE.from_jline_distribution(jdists.get(k-1));
893 probs = jdist.getProbabilities();
894 matlab_dist = Prior(dists, probs);
895 elseif isa(jdist,
'jline.lang.processes.Normal')
896 matlab_dist = Normal(jdist.getParam(1).getValue, jdist.getParam(2).getValue);
897 elseif isa(jdist, 'jline.lang.processes.Bernoulli')
898 matlab_dist = Bernoulli(jdist.getParam(1).getValue);
899 elseif isa(jdist, 'jline.lang.processes.Geometric')
900 matlab_dist = Geometric(jdist.getParam(1).getValue);
901 elseif isa(jdist, 'jline.lang.processes.Poisson')
902 matlab_dist = Poisson(jdist.getParam(1).getValue);
903 elseif isa(jdist, 'jline.lang.processes.Binomial')
904 matlab_dist = Binomial(
double(jdist.getParam(1).getValue), jdist.getParam(2).getValue);
905 elseif isa(jdist, 'jline.lang.processes.DiscreteUniform')
906 matlab_dist = DiscreteUniform(jdist.getParam(1).getValue, jdist.getParam(2).getValue);
907 elseif isa(jdist, 'jline.lang.processes.EmpiricalCDF')
908 d = JLINE.from_jline_matrix(jdist.getData());
909 if size(d, 2) >= 2 % stored as [cdf, x]; MATLAB ctor
is (xdata, cdfdata)
910 matlab_dist = EmpiricalCDF(d(:,2), d(:,1));
912 matlab_dist = EmpiricalCDF(d);
914 elseif isa(jdist, 'jline.lang.processes.Trace') % before Replayer (Trace < Replayer)
915 v = jdist.getParam(1).getValue;
916 if isa(v, 'java.lang.String'), v =
char(v); end
917 matlab_dist = Trace(v);
918 elseif isa(jdist, 'jline.lang.processes.Replayer')
919 v = jdist.getParam(1).getValue;
920 if isa(v, 'java.lang.String'), v =
char(v); end
921 matlab_dist = Replayer(v);
922 elseif isa(jdist, 'jline.lang.processes.DMAP')
923 matlab_dist = DMAP(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
924 elseif isa(jdist, 'jline.lang.processes.ME')
925 matlab_dist = ME(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
926 elseif isa(jdist, 'jline.lang.processes.RAP')
927 matlab_dist = RAP(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
928 elseif isa(jdist, 'jline.lang.processes.MMDP2') % before MMDP (MMDP2 < MMDP)
929 matlab_dist = MMDP2(jdist.getParam(1).getValue, jdist.getParam(2).getValue, jdist.getParam(3).getValue, jdist.getParam(4).getValue);
930 elseif isa(jdist, 'jline.lang.processes.MMDP')
931 matlab_dist = MMDP(JLINE.from_jline_matrix(jdist.getParam(1).getValue), JLINE.from_jline_matrix(jdist.getParam(2).getValue));
932 elseif isa(jdist, 'jline.lang.processes.BMAP') % before MarkedMAP (BMAP < MarkedMAP)
933 % JAR cell
is MarkedMAP layout; rebuilt to standard {D0,D1,...} -- see _kb/12-interfaces-and-docs.md
934 proc = jdist.getProcess();
937 D{1} = JLINE.from_jline_matrix(proc.get(0));
939 D{1+k} = JLINE.from_jline_matrix(proc.get(1+k));
941 matlab_dist = BMAP(D);
942 elseif isa(jdist,
'jline.lang.processes.MarkedMMPP')
943 proc = jdist.getProcess(); % {D0, D1, D11..D1K}
947 D{k} = JLINE.from_jline_matrix(proc.get(k-1));
949 matlab_dist = MarkedMMPP(D, K);
950 elseif isa(jdist,
'jline.lang.processes.MarkedMAP')
951 proc = jdist.getProcess(); % {D0, D1, D11..D1K}
955 D{k} = JLINE.from_jline_matrix(proc.get(k-1));
957 matlab_dist = MarkedMAP(D, K);
959 line_error(mfilename,
'Distribution not supported by JLINE.');
963 function set_csMatrix(line_node, jnode, jclasses)
964 nClasses = length(line_node.model.classes);
965 csMatrix = jnode.initClassSwitchMatrix();
968 csMatrix.set(jclasses{i}, jclasses{j}, line_node.server.csFun(i,j,0,0));
971 jnode.setClassSwitchingMatrix(csMatrix);
974 function set_service(line_node, jnode, job_classes)
975 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'))
979 for n = 1 : length(job_classes)
980 if (isa(line_node,
'Queue') || isa(line_node,
'Delay'))
981 matlab_dist = line_node.getService(job_classes{n});
982 elseif (isa(line_node,
'Source'))
983 matlab_dist = line_node.getArrivalProcess(job_classes{n});
985 line_error(mfilename,
'Node not supported by JLINE.');
987 service_dist = JLINE.from_line_distribution(matlab_dist);
989 if (isa(line_node,
'Queue') || isa(line_node,
'Delay'))
990 jnode.setService(jnode.getModel().getClasses().get(n-1), service_dist, line_node.schedStrategyPar(n));
991 elseif (isa(line_node,
'Source'))
992 jnode.setArrival(jnode.getModel().getClasses().get(n-1), service_dist);
997 function set_delayoff(line_node, jnode, job_classes)
998 % Transfer setup and delayoff times from MATLAB Queue to Java Queue
999 if ~isa(line_node, 'Queue')
1003 % Check if setupTime property exists and
is not empty
1004 if ~isprop(line_node, 'setupTime') || isempty(line_node.setupTime)
1008 for n = 1 : length(job_classes)
1009 c = job_classes{n}.index;
1010 % Check
if both setupTime and delayoffTime are set
for this class
1011 if c <= length(line_node.setupTime) && ~isempty(line_node.setupTime{1, c}) && ...
1012 c <= length(line_node.delayoffTime) && ~isempty(line_node.delayoffTime{1, c})
1013 % Convert MATLAB distributions to Java distributions
1014 setup_dist = JLINE.from_line_distribution(line_node.setupTime{1, c});
1015 delayoff_dist = JLINE.from_line_distribution(line_node.delayoffTime{1, c});
1016 % Set delayoff on the Java Queue
1017 jnode.setDelayOff(jnode.getModel().getClasses().get(n-1), setup_dist, delayoff_dist);
1022 function set_line_service(jline_node, line_node, job_classes, line_classes)
1023 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')
1026 for n = 1:job_classes.size()
1027 if (isa(line_node, 'Queue') || isa(line_node, 'Delay'))
1028 jdist = jline_node.getServiceProcess(job_classes.get(n-1));
1029 matlab_dist = JLINE.from_jline_distribution(jdist);
1030 weight = jline_node.getSchedStrategyPar(job_classes.get(n-1));
1031 line_node.setService(line_classes{n}, matlab_dist, weight);
1032 elseif (isa(line_node,
'Source'))
1033 jdist = jline_node.getArrivalProcess(job_classes.get(n-1));
1034 matlab_dist = JLINE.from_jline_distribution(jdist);
1035 line_node.setArrival(line_classes{n}, matlab_dist);
1036 elseif (isa(line_node,
'Router'))
1039 line_error(mfilename,'Node not supported by JLINE.');
1044 function node_object = from_line_node(line_node, jnetwork, ~, forkNode, sn)
1045 % Handle optional sn argument
1049 if isa(line_node,
'Delay')
1050 node_object = javaObject('jline.lang.
nodes.Delay', jnetwork, line_node.getName);
1051 elseif isa(line_node, 'Queue')
1052 switch line_node.schedStrategy
1053 case SchedStrategy.INF
1054 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.INF);
1055 case SchedStrategy.FCFS
1056 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFS);
1057 case SchedStrategy.LCFS
1058 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFS);
1059 case SchedStrategy.SIRO
1060 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SIRO);
1061 case SchedStrategy.SJF
1062 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SJF);
1063 case SchedStrategy.LJF
1064 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LJF);
1065 case SchedStrategy.PS
1066 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PS);
1067 case SchedStrategy.DPS
1068 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.DPS);
1069 case SchedStrategy.GPS
1070 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.GPS);
1071 case SchedStrategy.SEPT
1072 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SEPT);
1073 case SchedStrategy.LEPT
1074 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LEPT);
1075 case SchedStrategy.HOL
1076 % HOL maps to the JAR's own HOL, not FCFSPRIO -- see _kb/12-interfaces-and-docs.md
1077 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.HOL);
1078 case SchedStrategy.FCFSPRIO
1079 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPRIO);
1080 case SchedStrategy.FORK
1081 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FORK);
1082 case SchedStrategy.EXT
1083 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.EXT);
1084 case SchedStrategy.REF
1085 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.REF);
1086 case SchedStrategy.LCFSPR
1087 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPR);
1088 case SchedStrategy.LCFSPI
1089 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPI);
1090 case SchedStrategy.LCFSPRIO
1091 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPRIO);
1092 case SchedStrategy.LCFSPRPRIO
1093 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPRPRIO);
1094 case SchedStrategy.LCFSPIPRIO
1095 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LCFSPIPRIO);
1096 case SchedStrategy.FCFSPR
1097 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPR);
1098 case SchedStrategy.FCFSPI
1099 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPI);
1100 case SchedStrategy.FCFSPRPRIO
1101 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPRPRIO);
1102 case SchedStrategy.FCFSPIPRIO
1103 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FCFSPIPRIO);
1104 case SchedStrategy.PSPRIO
1105 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PSPRIO);
1106 case SchedStrategy.DPSPRIO
1107 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.DPSPRIO);
1108 case SchedStrategy.GPSPRIO
1109 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.GPSPRIO);
1110 case SchedStrategy.POLLING
1111 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.POLLING);
1112 case SchedStrategy.SRPT
1113 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SRPT);
1114 case SchedStrategy.SRPTPRIO
1115 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SRPTPRIO);
1116 case SchedStrategy.PSJF
1117 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PSJF);
1118 case SchedStrategy.FB
1119 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FB);
1120 case SchedStrategy.LRPT
1121 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LRPT);
1122 case SchedStrategy.EDD
1123 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.EDD);
1124 case SchedStrategy.EDF
1125 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.EDF);
1126 case SchedStrategy.LPS
1127 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.LPS);
1128 case SchedStrategy.SETF
1129 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.SETF);
1130 case SchedStrategy.FSP
1131 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.FSP);
1132 case SchedStrategy.PAS
1133 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.PAS);
1134 case SchedStrategy.OI
1135 node_object = javaObject('jline.lang.
nodes.Queue', jnetwork, line_node.getName, jline.lang.constant.SchedStrategy.OI);
1137 line_error(mfilename, sprintf('JLINE conversion does not support the %s scheduling strategy yet.',
char(SchedStrategy.toText(line_node.schedStrategy))));
1139 nservers = line_node.getNumberOfServers;
1141 node_object.setNumberOfServers(java.lang.Integer.MAX_VALUE);
1143 node_object.setNumberOfServers(line_node.getNumberOfServers);
1145 if ~isempty(line_node.lldScaling)
1146 node_object.setLoadDependence(JLINE.from_line_matrix(line_node.lldScaling));
1148 if ~isempty(line_node.lcdScaling)
1150 line_error(mfilename, "Class-dependent models require sn struct for MATLAB-to-JAVA translation.");
1152 cdPeakJava = line_node.lcdScalingPeak;
1153 if isscalar(cdPeakJava)
1154 cdPeakJava = repmat(cdPeakJava, 1, sn.nclasses);
1156 node_object.setLimitedClassDependence(JLINE.handle_to_serializablefun(line_node.lcdScaling, sn), JLINE.from_line_matrix(cdPeakJava(:)'));
1158 if ~isempty(line_node.ljdScaling)
1160 line_error(mfilename, "Joint-dependent models require sn struct for MATLAB-to-JAVA translation.");
1162 jdPeakJava = line_node.ljdScalingPeak;
1163 if isscalar(jdPeakJava)
1164 jdPeakJava = repmat(jdPeakJava, 1, sn.nclasses);
1166 node_object.setLimitedJointDependence(JLINE.handle_to_serializablefun(line_node.ljdScaling, sn), JLINE.from_line_matrix(jdPeakJava(:)'));
1168 % Set queue capacity if finite
1169 if ~isinf(line_node.cap)
1170 node_object.setCapacity(line_node.cap);
1172 % Transfer LPS job limit (stored in schedStrategyPar(1))
1173 if line_node.schedStrategy == SchedStrategy.LPS && ~isempty(line_node.schedStrategyPar) && line_node.schedStrategyPar(1) >= 1
1174 node_object.setLimit(int32(line_node.schedStrategyPar(1)));
1176 elseif isa(line_node, 'Source')
1177 node_object = javaObject('jline.lang.
nodes.Source', jnetwork, line_node.getName);
1178 elseif isa(line_node, 'Sink')
1179 node_object = javaObject('jline.lang.
nodes.Sink', jnetwork, line_node.getName);
1180 elseif isa(line_node, 'Router')
1181 node_object = javaObject('jline.lang.
nodes.Router', jnetwork, line_node.getName);
1182 elseif isa(line_node, 'ClassSwitch')
1183 node_object = javaObject('jline.lang.
nodes.ClassSwitch', jnetwork, line_node.getName);
1184 elseif isa(line_node, 'Fork')
1185 node_object = javaObject('jline.lang.
nodes.Fork', jnetwork, line_node.name);
1186 node_object.setTasksPerLink(line_node.output.tasksPerLink);
1187 elseif isa(line_node, 'Join')
1188 node_object = javaObject('jline.lang.
nodes.Join', jnetwork, line_node.name, forkNode);
1189 elseif isa(line_node, 'Logger')
1190 node_object = javaObject('jline.lang.
nodes.Logger', jnetwork, line_node.name, [line_node.filePath,line_node.fileName]);
1191 % Output-field flags transferred unconditionally (JAR defaults all false) -- see _kb/12-interfaces-and-docs.md
1192 node_object.setStartTime(strcmpi(
char(line_node.getStartTime), 'true'));
1193 node_object.setLoggerName(strcmpi(
char(line_node.getLoggerName), 'true'));
1194 node_object.setTimestamp(strcmpi(
char(line_node.getTimestamp), 'true'));
1195 node_object.setJobID(strcmpi(
char(line_node.getJobID), 'true'));
1196 node_object.setJobClass(strcmpi(
char(line_node.getJobClass), 'true'));
1197 node_object.setTimeSameClass(strcmpi(
char(line_node.getTimeSameClass), 'true'));
1198 node_object.setTimeAnyClass(strcmpi(
char(line_node.getTimeAnyClass), 'true'));
1199 elseif isa(line_node, 'Cache')
1200 nitems = line_node.items.nitems;
1201 switch line_node.replacestrategy
1202 case ReplacementStrategy.RR
1203 repStrategy = jline.lang.constant.ReplacementStrategy.RR;
1204 case ReplacementStrategy.FIFO
1205 repStrategy = jline.lang.constant.ReplacementStrategy.FIFO;
1206 case ReplacementStrategy.SFIFO
1207 repStrategy = jline.lang.constant.ReplacementStrategy.SFIFO;
1208 case ReplacementStrategy.LRU
1209 repStrategy = jline.lang.constant.ReplacementStrategy.LRU;
1211 if ~isempty(line_node.graph)
1212 % graph
is a per-item cell array of (h+1)x(h+1) matrices
1213 gcells = line_node.graph;
1214 if ~iscell(gcells), gcells = {gcells}; end
1215 jGraph = javaArray(
'jline.util.matrix.Matrix', numel(gcells));
1216 for gidx = 1:numel(gcells)
1217 jGraph(gidx) = JLINE.from_line_matrix(gcells{gidx});
1219 node_object = javaObject(
'jline.lang.nodes.Cache', jnetwork, line_node.name, nitems, JLINE.from_line_matrix(line_node.itemLevelCap), repStrategy, jGraph);
1221 node_object = javaObject(
'jline.lang.nodes.Cache', jnetwork, line_node.name, nitems, JLINE.from_line_matrix(line_node.itemLevelCap), repStrategy);
1223 elseif isa(line_node,
'Place')
1224 if line_node.isQueueing()
1225 % Reconstructed with its scheduling strategy for setService -- see _kb/12-interfaces-and-docs.md
1226 jsched = jline.lang.constant.SchedStrategy.fromText(SchedStrategy.toText(line_node.schedStrategy));
1227 node_object = javaObject('jline.lang.
nodes.Place', jnetwork, line_node.getName, jsched);
1229 node_object = javaObject('jline.lang.
nodes.Place', jnetwork, line_node.getName);
1231 elseif isa(line_node, 'Transition')
1232 node_object = javaObject('jline.lang.
nodes.Transition', jnetwork, line_node.getName);
1233 % Modes are added later in from_line_network after classes are created
1235 line_error(mfilename,'Node not supported by JLINE.');
1239 function node_object = from_jline_node(jline_node, model, job_classes)
1240 if isa(jline_node, 'jline.lang.
nodes.Delay')
1241 node_object = Delay(model, jline_node.getName.toCharArray');
1242 elseif isa(jline_node, 'jline.lang.
nodes.Queue')
1243 schedStrategy = jline_node.getSchedStrategy;
1244 switch schedStrategy.name().toCharArray'
1246 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.INF);
1248 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFS);
1250 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFS);
1252 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SIRO);
1254 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SJF);
1256 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LJF);
1258 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.PS);
1260 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.DPS);
1262 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.GPS);
1264 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SEPT);
1266 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LEPT);
1267 case {
'HOL',
'FCFSPRIO'}
1268 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FCFSPRIO);
1270 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FORK);
1272 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.EXT);
1274 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.REF);
1276 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LCFSPR);
1278 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SRPT);
1280 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.SRPTPRIO);
1282 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.PSJF);
1284 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FB);
1286 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LRPT);
1288 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.PSPRIO);
1290 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.DPSPRIO);
1292 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.GPSPRIO);
1294 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPI);
1296 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LCFSPRIO);
1298 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.LCFSPRPRIO);
1300 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LCFSPIPRIO);
1302 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPR);
1304 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FCFSPI);
1306 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.FCFSPRPRIO);
1308 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FCFSPIPRIO);
1310 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.POLLING);
1312 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.EDD);
1314 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.EDF);
1316 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.LPS);
1318 node_object = Queue(model, jline_node.getName.toCharArray', SchedStrategy.SETF);
1320 node_object = Queue(model, jline_node.getName.toCharArray
', SchedStrategy.FSP);
1322 % PAS rate function is a Java SerializableFunction, not recoverable as a MATLAB handle
1323 line_error(mfilename, 'JLINE-to-LINE conversion does not support PAS queues (service rate function not recoverable).
');
1325 line_error(mfilename, sprintf('JLINE-to-LINE conversion does not support the %s scheduling strategy yet.
', char(schedStrategy.name())));
1327 node_object.setNumberOfServers(jline_node.getNumberOfServers);
1328 cap = jline_node.getCap();
1329 if cap < intmax && cap > 0
1330 node_object.setCapacity(cap);
1332 if ~isempty(JLINE.from_jline_matrix(jline_node.getLimitedLoadDependence))
1333 node_object.setLoadDependence(JLINE.from_jline_matrix(jline_node.getLimitedLoadDependence));
1335 elseif isa(jline_node, 'jline.lang.nodes.Source
')
1336 node_object = Source(model, jline_node.getName.toCharArray');
1337 elseif isa(jline_node,
'jline.lang.nodes.Sink')
1338 node_object = Sink(model, jline_node.getName.toCharArray');
1339 elseif isa(jline_node, 'jline.lang.
nodes.Router')
1340 node_object = Router(model, jline_node.getName.toCharArray');
1341 elseif isa(jline_node, 'jline.lang.
nodes.ClassSwitch')
1342 nClasses = job_classes.size;
1343 csMatrix = zeros(nClasses, nClasses);
1346 csMatrix(r,s) = jline_node.getServer.applyCsFun(r-1,s-1);
1349 node_object = ClassSwitch(model, jline_node.getName.toCharArray', csMatrix);
1350 elseif isa(jline_node, 'jline.lang.
nodes.Cache')
1351 numItems = jline_node.getNumberOfItems();
1352 itemLevelCap = JLINE.from_jline_matrix(jline_node.getItemLevelCap());
1353 replPolicy = jline_node.getReplacementStrategy();
1354 switch
char(replPolicy)
1356 rp = ReplacementStrategy.LRU;
1358 rp = ReplacementStrategy.FIFO;
1360 rp = ReplacementStrategy.RR;
1362 rp = ReplacementStrategy.LRU;
1364 node_object = Cache(model, jline_node.getName.toCharArray', numItems, itemLevelCap, rp);
1365 % hitClass, missClass, and popularity set later in jline_to_line
1366 elseif isa(jline_node, 'jline.lang.
nodes.Fork')
1367 node_object = Fork(model, jline_node.getName.toCharArray');
1368 tpl = jline_node.getOutput().tasksPerLink;
1370 node_object.setTasksPerLink(tpl);
1372 elseif isa(jline_node, 'jline.lang.
nodes.Join')
1373 node_object = Join(model, jline_node.getName.toCharArray');
1374 % joinOf
is set later in jline_to_line after all
nodes are created
1375 elseif isa(jline_node, 'jline.lang.
nodes.Place')
1376 node_object = Place(model, jline_node.getName.toCharArray');
1377 elseif isa(jline_node, 'jline.lang.
nodes.Transition')
1378 node_object = Transition(model, jline_node.getName.toCharArray');
1379 % Note: Mode configurations need to be set after classes are created
1381 line_error(mfilename,'Node not supported by JLINE.');
1385 function node_class = from_line_class(line_class, jnetwork)
1386 % Check signal classes first (before their base classes)
1387 if isa(line_class, 'ClosedSignal')
1388 % ClosedSignal -> jline.lang.ClosedSignal
1389 jSignalType = jline.lang.constant.SignalType.fromID(line_class.signalType);
1390 [jRemDist, jRemPol] = JLINE.from_line_signal_removal(line_class);
1391 if isempty(jRemDist) && isempty(jRemPol)
1392 node_class = javaObject('jline.lang.ClosedSignal', jnetwork, line_class.getName, jSignalType, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1394 node_class = javaObject('jline.lang.ClosedSignal', jnetwork, line_class.getName, jSignalType, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority, jRemDist, jRemPol);
1396 elseif isa(line_class, 'Signal') || isa(line_class, 'OpenSignal')
1397 % Signal/OpenSignal -> jline.lang.Signal (includes CATASTROPHE type)
1398 jSignalType = jline.lang.constant.SignalType.fromID(line_class.signalType);
1399 [jRemDist, jRemPol] = JLINE.from_line_signal_removal(line_class);
1400 if isempty(jRemDist) && isempty(jRemPol)
1401 node_class = javaObject('jline.lang.Signal', jnetwork, line_class.getName, jSignalType, line_class.priority);
1403 node_class = javaObject('jline.lang.Signal', jnetwork, line_class.getName, jSignalType, line_class.priority, jRemDist, jRemPol);
1405 elseif isa(line_class, 'OpenClass')
1406 node_class = javaObject('jline.lang.OpenClass', jnetwork, line_class.getName, line_class.priority);
1407 elseif isa(line_class, 'SelfLoopingClass')
1408 node_class = javaObject('jline.lang.SelfLoopingClass', jnetwork, line_class.getName, line_class.population, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1409 elseif isa(line_class, 'ClosedClass')
1410 node_class = javaObject('jline.lang.ClosedClass', jnetwork, line_class.getName, line_class.population, jnetwork.getNodeByName(line_class.refstat.getName), line_class.priority);
1412 line_error(mfilename,'Class type not supported by JLINE.');
1414 % Transfer relative deadline (used by EDD/EDF scheduling)
1415 if isprop(line_class, 'deadline') && ~isempty(line_class.deadline) && ~isinf(line_class.deadline)
1416 node_class.setDeadline(line_class.deadline);
1418 if line_class.isReferenceClass()
1419 node_class.setReferenceClass(true);
1423 function node_class = from_jline_class(jclass, model)
1424 % Check signal classes first (their base classes would match below)
1425 if isa(jclass, 'jline.lang.ClosedSignal')
1426 [remDist, remPol] = JLINE.from_jline_signal_removal(jclass);
1427 node_class = ClosedSignal(model, jclass.getName.toCharArray', jclass.getSignalType().getID(), model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority, remDist, remPol);
1428 elseif isa(jclass, 'jline.lang.OpenSignal')
1429 node_class = OpenSignal(model, jclass.getName.toCharArray', jclass.getSignalType().getID(), jclass.getPriority);
1430 elseif isa(jclass, 'jline.lang.Signal')
1431 [remDist, remPol] = JLINE.from_jline_signal_removal(jclass);
1432 node_class = Signal(model, jclass.getName.toCharArray', jclass.getSignalType().getID(), jclass.getPriority, remDist, remPol);
1433 elseif isa(jclass, 'jline.lang.OpenClass')
1434 node_class = OpenClass(model, jclass.getName.toCharArray', jclass.getPriority);
1435 elseif isa(jclass, 'jline.lang.SelfLoopingClass')
1436 node_class = SelfLoopingClass(model, jclass.getName.toCharArray', jclass.getNumberOfJobs, model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority);
1437 elseif isa(jclass, 'jline.lang.ClosedClass')
1438 node_class = ClosedClass(model, jclass.getName.toCharArray', jclass.getNumberOfJobs, model.getNodeByName(jclass.getReferenceStation.getName), jclass.getPriority);
1440 line_error(mfilename,'Class type not supported by JLINE.');
1442 % Transfer relative deadline (used by EDD/EDF scheduling)
1443 dl = jclass.getDeadline();
1445 node_class.deadline = dl;
1449 function [remDist, remPol] = from_jline_signal_removal(jclass)
1450 % FROM_JLINE_SIGNAL_REMOVAL Read back a JAR signal's batch-removal
1451 % distribution and policy for the MATLAB signal constructors.
1452 jRemDist = jclass.getRemovalDistribution();
1453 if isempty(jRemDist)
1456 remDist = JLINE.from_jline_distribution(jRemDist);
1458 jRemPol = jclass.getRemovalPolicy();
1460 remPol = RemovalPolicy.RANDOM;
1462 remPol = jRemPol.getID();
1466 function from_line_links(model, jmodel)
1467 connections = model.getConnectionMatrix();
1468 [m, ~] = size(connections);
1469 jnodes = jmodel.getNodes();
1470 jclasses = jmodel.getClasses();
1471 njclasses = jclasses.size();
1472 line_nodes = model.getNodes;
1473 sn = model.getStruct;
1475 % Build mapping from MATLAB node index to Java node index
1476 % (accounting for skipped auto-added ClassSwitch
nodes)
1477 matlab2java_node_idx = zeros(1, length(line_nodes));
1479 for i = 1:length(line_nodes)
1480 if isa(line_nodes{i},
'ClassSwitch') && line_nodes{i}.autoAdded
1481 matlab2java_node_idx(i) = -1; % Mark as skipped
1483 matlab2java_node_idx(i) = jidx;
1489 % [ ] Update to consider different weights/routing
for classes
1490 if isempty(sn.rtorig)
1491 useLinkMethod = false; % this model did not call link()
1493 jrt_matrix = jmodel.initRoutingMatrix();
1494 useLinkMethod = true;
1497 % For models with auto-added ClassSwitch
nodes, use sn.rtorig directly
1498 % to set up routing with proper class switching
1500 for i = 1:length(line_nodes)
1501 if isa(line_nodes{i},
'ClassSwitch') && line_nodes{i}.autoAdded
1507 if useLinkMethod && hasAutoCS
1508 % sn.rtorig already excludes
auto-added ClassSwitch
nodes (station-indexed) -- see _kb/12-interfaces-and-docs.md
1511 if ~isempty(sn.rtorig{r,s})
1512 Prs = sn.rtorig{r,s};
1513 [nrows, ncols] = size(Prs);
1517 % sn.rtorig uses station indices which
map to non-CS
nodes
1518 % Find the java node indices by matching station index to node
1519 jsrc_idx = i - 1; % Direct mapping since rtorig excludes CS
1521 jrt_matrix.set(jclasses.get(r-1), jclasses.get(s-1), jnodes.get(jsrc_idx), jnodes.get(jdest_idx), Prs(i,j));
1529 % Original logic
for models without
auto-added ClassSwitch
1531 line_node = line_nodes{i};
1533 % Skip
auto-added ClassSwitch
nodes - Java will add them automatically
1534 if isa(line_node, 'ClassSwitch') && line_node.autoAdded
1538 jnode_idx = matlab2java_node_idx(i);
1540 output_strat = line_node.output.outputStrategy{k};
1541 switch RoutingStrategy.fromText(output_strat{2})
1542 case RoutingStrategy.DISABLED
1543 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1544 case RoutingStrategy.RAND
1545 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RAND);
1546 outlinks_i=find(connections(i,:));
1548 % No routing-matrix entries for RAND under useLinkMethod -- see _kb/12-interfaces-and-docs.md
1550 for j= outlinks_i(:)'
1551 jdest_idx = matlab2java_node_idx(j);
1553 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1557 case RoutingStrategy.RROBIN
1558 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RROBIN);
1559 outlinks_i=find(connections(i,:))
';
1561 line_error(mfilename,'RROBIN cannot be used together with the link() command.
');
1563 for j= outlinks_i(:)'
1564 jdest_idx = matlab2java_node_idx(j);
1566 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1569 case RoutingStrategy.WRROBIN
1570 outlinks_i=find(connections(i,:))
';
1571 for j= outlinks_i(:)'
1572 jdest_idx = matlab2java_node_idx(j);
1574 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1578 line_error(mfilename,
'RROBIN cannot be used together with the link() command.');
1580 for j= 1:length(output_strat{3})
1581 node_target = jmodel.getNodeByName(output_strat{3}{j}{1}.getName());
1582 weight = output_strat{3}{j}{2};
1583 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.WRROBIN, node_target, weight);
1585 case RoutingStrategy.PROB
1586 outlinks_i=find(connections(i,:));
1587 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1), jline.lang.constant.RoutingStrategy.PROB);
1589 for j= outlinks_i(:)
'
1590 jdest_idx = matlab2java_node_idx(j);
1592 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1596 if length(output_strat) >= 3
1597 probabilities = output_strat{3};
1598 for j = 1:length(probabilities)
1599 dest_idx = probabilities{j}{1}.index;
1600 jdest_idx = matlab2java_node_idx(dest_idx);
1601 if (connections(i, dest_idx) ~= 0) && jdest_idx >= 0
1603 jrt_matrix.set(jclasses.get(k-1), jclasses.get(k-1), jnodes.get(jnode_idx), jnodes.get(jdest_idx), probabilities{j}{2});
1605 jnodes.get(jnode_idx).setProbRouting(jclasses.get(k-1), jnodes.get(jdest_idx), probabilities{j}{2});
1610 case RoutingStrategy.JSQ
1611 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.JSQ);
1612 outlinks_i=find(connections(i,:))';
1614 for j= outlinks_i(:)
'
1615 jdest_idx = matlab2java_node_idx(j);
1617 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1621 case RoutingStrategy.SQ
1622 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.SQ);
1623 if length(output_strat) >= 3 && ~isempty(output_strat{3})
1624 dparam = output_strat{3}{1};
1625 jnodes.get(jnode_idx).setSQRouting(jclasses.get(k-1), int32(dparam));
1627 outlinks_i=find(connections(i,:))';
1629 for j= outlinks_i(:)
'
1630 jdest_idx = matlab2java_node_idx(j);
1632 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1636 case RoutingStrategy.RL
1637 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.RL);
1638 outlinks_i=find(connections(i,:))';
1640 for j= outlinks_i(:)
'
1641 jdest_idx = matlab2java_node_idx(j);
1643 jmodel.addLink(jnodes.get(jnode_idx), jnodes.get(jdest_idx));
1647 % Forward RL value fn/action nodes/state size from outputStrategy{r}{3..5} -- see _kb/12-interfaces-and-docs.md
1648 if length(output_strat) >= 5
1649 valFnRaw = output_strat{3};
1650 nodesNeedAction = output_strat{4};
1651 stateSize = output_strat{5};
1652 if ~isempty(valFnRaw)
1654 % Tabular: flatten N-D array to a row vector and pass shape.
1655 shp = size(valFnRaw);
1656 jvfFlat = jline.util.matrix.Matrix(1, numel(valFnRaw));
1658 for f = 1:numel(flat)
1659 jvfFlat.set(0, f-1, double(flat(f)));
1661 jshape = int32(shp(:)');
1662 jnna = int32(nodesNeedAction(:)
' - 1); % MATLAB->Java 0-based
1663 jnodes.get(jnode_idx).setRLRouting(jclasses.get(k-1), jvfFlat, jshape, jnna, int32(stateSize));
1665 % Linear approx: coefficient row vector.
1666 coeff = valFnRaw(:)';
1667 jvf = jline.util.matrix.Matrix(1, numel(coeff));
1668 for f = 1:numel(coeff)
1669 jvf.set(0, f-1,
double(coeff(f)));
1671 jnna = int32(nodesNeedAction(:)
' - 1);
1672 jnodes.get(jnode_idx).setRLRouting(jclasses.get(k-1), jvf, int32([]), jnna, int32(stateSize));
1677 line_warning(mfilename, sprintf('''%s
'' routing strategy not supported by JLINE, setting as Disabled.\n
',output_strat{2}));
1678 jnodes.get(jnode_idx).setRouting(jclasses.get(k-1),jline.lang.constant.RoutingStrategy.DISABLED);
1684 jmodel.link(jrt_matrix);
1685 % Align the sn.rtorig be the same, treating artificial
1686 % ClassSwitch nodes as if they were explicitly specified
1687 jsn = jmodel.getStruct(true);
1688 rtorig = java.util.HashMap();
1689 if ~isempty(model.sn.rtorig)
1690 if iscell(model.sn.rtorig)
1692 sub_rtorig = java.util.HashMap();
1694 sub_rtorig.put(jclasses.get(s-1), JLINE.from_line_matrix(model.sn.rtorig{r,s}));
1696 rtorig.put(jclasses.get(r-1), sub_rtorig);
1700 jsn.rtorig = rtorig;
1704 function model = from_jline_routing(model, jnetwork)
1705 jnodes = jnetwork.getNodes();
1706 jclasses = jnetwork.getClasses();
1707 n_nodes = jnodes.size();
1708 network_nodes = model.getNodes;
1709 network_classes = model.getClasses;
1711 % Build name-to-MATLAB-node map (JAR and MATLAB may order nodes differently)
1712 node_by_name = containers.Map();
1713 for nn = 1:length(network_nodes)
1714 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1717 connections = JLINE.from_jline_matrix(jnetwork.getConnectionMatrix());
1718 [row,col] = find(connections);
1720 from_name = char(jnodes.get(row(i)-1).getName());
1721 to_name = char(jnodes.get(col(i)-1).getName());
1722 model.addLink(node_by_name(from_name), node_by_name(to_name));
1726 jnode = jnodes.get(n-1);
1727 cur_node = node_by_name(char(jnode.getName()));
1728 output_strategies = jnode.getOutputStrategies();
1729 n_strategies = output_strategies.size();
1730 for m = 1 : n_strategies
1731 output_strat = output_strategies.get(m-1);
1732 routing_strat = output_strat.getRoutingStrategy;
1733 routing_strat_classidx = output_strat.getJobClass.getIndex();
1734 switch char(routing_strat)
1736 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RAND);
1738 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1740 dest = output_strat.getDestination();
1742 dest_name = char(dest.getName());
1743 if node_by_name.isKey(dest_name)
1744 weight = output_strat.getProbability();
1745 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1749 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.DISABLED);
1755 function model = from_jline_links(model, jnetwork)
1756 P = model.initRoutingMatrix;
1757 jnodes = jnetwork.getNodes();
1758 jclasses = jnetwork.getClasses();
1759 n_classes = jclasses.size();
1760 n_nodes = jnodes.size();
1761 network_nodes = model.getNodes;
1763 % Build JAR-to-MATLAB node index mapping (node orders may differ)
1764 jar2ml = zeros(1, n_nodes);
1766 jar_name = char(jnodes.get(jj-1).getName());
1767 for mm = 1:length(network_nodes)
1768 if strcmp(network_nodes{mm}.name, jar_name)
1775 hasDestinations = false;
1777 jnode = jnodes.get(n-1);
1778 output_strategies = jnode.getOutputStrategies();
1779 n_strategies = output_strategies.size();
1780 for m = 1 : n_strategies
1781 output_strat = output_strategies.get(m-1);
1782 dest = output_strat.getDestination();
1783 if~isempty(dest) % disabled strategy
1784 hasDestinations = true;
1785 in_idx = jar2ml(jnetwork.getNodeIndex(jnode)+1);
1786 out_idx = jar2ml(jnetwork.getNodeIndex(dest)+1);
1788 P{1}(in_idx,out_idx) = output_strat.getProbability();
1790 strat_class = output_strat.getJobClass();
1791 class_idx = jnetwork.getJobClassIndex(strat_class)+1;
1792 P{class_idx,class_idx}(in_idx,out_idx) = output_strat.getProbability();
1798 % If no OutputStrategy entries had destinations (e.g., model
1799 % loaded from JSON via LineModelIO.load), fall back to rtorig
1801 sn = jnetwork.getStruct;
1802 if ~isempty(sn.rtorig)
1803 % rtorig is station-indexed (no permutation needed —
1804 % station ordering matches between JAR and MATLAB)
1807 rtMat = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1818 % Restore non-PROB routing strategies (RROBIN, WRROBIN, etc.)
1819 % after link(), which sets all routing to PROB
1820 network_nodes = model.getNodes;
1821 network_classes = model.getClasses;
1822 node_by_name = containers.Map();
1823 for nn = 1:length(network_nodes)
1824 node_by_name(network_nodes{nn}.name) = network_nodes{nn};
1827 jnode = jnodes.get(n-1);
1828 cur_node = node_by_name(char(jnode.getName()));
1829 output_strategies = jnode.getOutputStrategies();
1830 n_strategies = output_strategies.size();
1831 for m = 1 : n_strategies
1832 output_strat = output_strategies.get(m-1);
1833 routing_strat = output_strat.getRoutingStrategy;
1834 routing_strat_classidx = output_strat.getJobClass.getIndex();
1835 switch char(routing_strat)
1837 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.RROBIN);
1839 dest = output_strat.getDestination();
1841 dest_name = char(dest.getName());
1842 if node_by_name.isKey(dest_name)
1843 % Clear stale PROB entries before first WRROBIN weight
1844 classIdx = routing_strat_classidx;
1845 if length(cur_node.output.outputStrategy) >= classIdx && ...
1846 length(cur_node.output.outputStrategy{1, classIdx}) >= 3
1847 curStrat = cur_node.output.outputStrategy{1, classIdx}{2};
1848 if ~strcmp(curStrat, 'WeightedRoundRobin
')
1849 cur_node.output.outputStrategy{1, classIdx}{3} = {};
1852 weight = output_strat.getProbability();
1853 cur_node.setRouting(network_classes{routing_strat_classidx}, RoutingStrategy.WRROBIN, node_by_name(dest_name), weight);
1860 % Invalidate cached struct after modifying routing strategies
1861 model.resetStruct();
1863 %Align the sn.rtorig be the same (Assume Java network is
1864 %created by calling Network.link)
1865 sn = jnetwork.getStruct;
1866 rtorig = cell(n_classes, n_classes);
1869 rtorig{r,s} = JLINE.from_jline_matrix(sn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
1872 model.sn.rtorig = rtorig;
1875 function [jnetwork] = from_line_network(model)
1878 sn = model.getStruct;
1880 jnetwork = javaObject('jline.lang.Network
', model.getName);
1881 % setChecks carried over before link() (SolverLN fast-mode layers) -- see _kb/12-interfaces-and-docs.md
1882 jnetwork.setChecks(logical(model.getChecks));
1883 line_nodes = model.getNodes;
1884 line_classes = model.getClasses;
1886 jnodes = cell(1,length(line_nodes));
1887 jclasses = cell(1,length(line_classes));
1889 for n = 1 : length(line_nodes)
1890 % Skip auto-added ClassSwitch nodes - Java's link() will add them automatically
1891 if isa(line_nodes{n},
'ClassSwitch') && line_nodes{n}.autoAdded
1894 if isa(line_nodes{n},
'Join')
1895 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, jnodes{line_nodes{n}.joinOf.index}, sn);
1897 jnodes{n} = JLINE.from_line_node(line_nodes{n}, jnetwork, line_classes, [], sn);
1901 for n = 1 : length(line_classes)
1902 jclasses{n} = JLINE.from_line_class(line_classes{n}, jnetwork);
1905 % Set up forJobClass associations
for signal classes
1906 for n = 1 : length(line_classes)
1907 if (isa(line_classes{n},
'Signal') || isa(line_classes{n},
'OpenSignal') || isa(line_classes{n},
'ClosedSignal'))
1908 if ~isempty(line_classes{n}.targetJobClass)
1909 targetIdx = line_classes{n}.targetJobClass.index;
1910 jclasses{n}.forJobClass(jclasses{targetIdx});
1915 for n = 1: length(jnodes)
1916 if isempty(jnodes{n})
1917 continue; % Skip
nodes that were not converted (e.g.,
auto-added ClassSwitch)
1919 JLINE.set_service(line_nodes{n}, jnodes{n}, line_classes);
1920 JLINE.set_delayoff(line_nodes{n}, jnodes{n}, line_classes);
1923 % Set drop rules
for stations (after classes are created)
1924 for n = 1: length(jnodes)
1925 if isempty(jnodes{n})
1926 continue; % Skip
nodes that were not converted
1928 if isa(line_nodes{n},
'Station') && ~isa(line_nodes{n},
'Source')
1929 for r = 1:length(line_classes)
1930 if length(line_nodes{n}.dropRule) >= r && ~isempty(line_nodes{n}.dropRule(r))
1931 dropRule = line_nodes{n}.dropRule(r);
1933 case DropStrategy.DROP
1934 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.Drop);
1935 case DropStrategy.BAS
1936 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.BlockingAfterService);
1937 case DropStrategy.BBS
1938 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.BlockingBeforeService);
1939 case DropStrategy.RSRD
1940 jnodes{n}.setDropRule(jclasses{r}, jline.lang.constant.DropStrategy.ReServiceOnRejection);
1941 % WAITQ (-1, MATLAB
's universal default) is never transferred -- see _kb/12-interfaces-and-docs.md
1945 % Transfer per-class capacity limits (setChainCapacity/classCap)
1946 if ~isempty(line_nodes{n}.classCap)
1947 for r = 1:min(length(line_classes), length(line_nodes{n}.classCap))
1948 if isfinite(line_nodes{n}.classCap(r)) && line_nodes{n}.classCap(r) >= 0
1949 jnodes{n}.setClassCap(jclasses{r}, int32(line_nodes{n}.classCap(r)));
1956 % Set polling type and switchover times for polling queues
1957 for n = 1: length(jnodes)
1958 if isempty(jnodes{n})
1961 if isa(line_nodes{n}, 'Queue
') && line_nodes{n}.schedStrategy == SchedStrategy.POLLING
1963 if ~isempty(line_nodes{n}.pollingType) && ~isempty(line_nodes{n}.pollingType{1})
1964 pollingType = line_nodes{n}.pollingType{1};
1966 case PollingType.GATED
1967 jPollingType = jline.lang.constant.PollingType.GATED;
1968 case PollingType.EXHAUSTIVE
1969 jPollingType = jline.lang.constant.PollingType.EXHAUSTIVE;
1970 case PollingType.KLIMITED
1971 jPollingType = jline.lang.constant.PollingType.KLIMITED;
1972 case PollingType.DECREMENTING
1973 jPollingType = jline.lang.constant.PollingType.DECREMENTING;
1975 line_error(mfilename, sprintf('Unsupported polling type
for the Java backend: %d.
', PollingType.toId(pollingType)));
1977 if pollingType == PollingType.KLIMITED && ~isempty(line_nodes{n}.pollingPar)
1978 jnodes{n}.setPollingType(jPollingType, int32(line_nodes{n}.pollingPar));
1980 jnodes{n}.setPollingType(jPollingType);
1983 % Set switchover times
1984 if ~isempty(line_nodes{n}.switchoverTime)
1985 for r = 1:length(line_classes)
1986 if length(line_nodes{n}.switchoverTime) >= r && ~isempty(line_nodes{n}.switchoverTime{r})
1987 soTime = line_nodes{n}.switchoverTime{r};
1988 if ~isa(soTime, 'Immediate
')
1989 jnodes{n}.setSwitchover(jclasses{r}, JLINE.from_line_distribution(soTime));
1997 % Transfer impatience features (reneging, balking, retrial) for queues
1998 % These require classes to be created first.
1999 for n = 1: length(jnodes)
2000 if isempty(jnodes{n})
2003 if ~isa(line_nodes{n}, 'Queue
')
2006 % Immediate feedback (self-looping jobs stay in service): either
2007 % 'all
' or a cell array of class indices on the MATLAB side
2008 if ~isempty(line_nodes{n}.immediateFeedback)
2009 if ischar(line_nodes{n}.immediateFeedback)
2010 jnodes{n}.setImmediateFeedback(true);
2011 elseif iscell(line_nodes{n}.immediateFeedback)
2012 for fbc = 1:length(line_nodes{n}.immediateFeedback)
2013 jnodes{n}.setImmediateFeedback(jclasses{line_nodes{n}.immediateFeedback{fbc}});
2017 for r = 1:length(line_classes)
2018 % Reneging (timer-based patience). Only RENEGING is supported;
2019 % BALKING via setPatience is rejected by both MATLAB and the JAR.
2020 if ~isempty(line_nodes{n}.patienceDistributions) && ...
2021 r <= length(line_nodes{n}.patienceDistributions) && ...
2022 ~isempty(line_nodes{n}.patienceDistributions{1, r})
2023 patDist = line_nodes{n}.patienceDistributions{1, r};
2024 if ~isa(patDist, 'Disabled
')
2025 impType = ImpatienceType.RENEGING;
2026 if ~isempty(line_nodes{n}.impatienceTypes) && ...
2027 r <= length(line_nodes{n}.impatienceTypes) && ...
2028 ~isempty(line_nodes{n}.impatienceTypes{1, r})
2029 impType = line_nodes{n}.impatienceTypes{1, r};
2031 jImpType = jline.lang.constant.ImpatienceType.fromID(int32(impType));
2032 jnodes{n}.setPatience(jclasses{r}, jImpType, JLINE.from_line_distribution(patDist));
2035 % Balking (state-based, queue-length/expected-wait thresholds)
2036 if ~isempty(line_nodes{n}.balkingStrategies) && ...
2037 r <= length(line_nodes{n}.balkingStrategies) && ...
2038 ~isempty(line_nodes{n}.balkingStrategies{1, r})
2039 balkStrat = line_nodes{n}.balkingStrategies{1, r};
2041 case BalkingStrategy.QUEUE_LENGTH
2042 jBalkStrat = jline.lang.constant.BalkingStrategy.QUEUE_LENGTH;
2043 case BalkingStrategy.EXPECTED_WAIT
2044 jBalkStrat = jline.lang.constant.BalkingStrategy.EXPECTED_WAIT;
2045 case BalkingStrategy.COMBINED
2046 jBalkStrat = jline.lang.constant.BalkingStrategy.COMBINED;
2048 jBalkStrat = jline.lang.constant.BalkingStrategy.QUEUE_LENGTH;
2050 thresholds = line_nodes{n}.balkingThresholds{1, r};
2051 jThresholds = java.util.ArrayList();
2052 for ti = 1:length(thresholds)
2053 th = thresholds{ti};
2057 maxJobs = java.lang.Integer.MAX_VALUE;
2059 jThresholds.add(javaObject('jline.lang.constant.BalkingThreshold
', int32(minJobs), int32(maxJobs), th{3}));
2061 jnodes{n}.setBalking(jclasses{r}, jBalkStrat, jThresholds);
2063 % Retrial (orbit + retrial delay distribution)
2064 if ~isempty(line_nodes{n}.retrialDelays) && ...
2065 r <= length(line_nodes{n}.retrialDelays) && ...
2066 ~isempty(line_nodes{n}.retrialDelays{1, r})
2067 retDist = line_nodes{n}.retrialDelays{1, r};
2068 if ~isa(retDist, 'Disabled
')
2070 if ~isempty(line_nodes{n}.retrialMaxAttempts) && r <= length(line_nodes{n}.retrialMaxAttempts)
2071 maxAttempts = line_nodes{n}.retrialMaxAttempts(r);
2073 jnodes{n}.setRetrial(jclasses{r}, JLINE.from_line_distribution(retDist), int32(maxAttempts));
2076 % Orbit impatience (abandonment from the retrial orbit)
2077 if ~isempty(line_nodes{n}.orbitImpatienceDistributions) && ...
2078 r <= length(line_nodes{n}.orbitImpatienceDistributions) && ...
2079 ~isempty(line_nodes{n}.orbitImpatienceDistributions{1, r})
2080 orbDist = line_nodes{n}.orbitImpatienceDistributions{1, r};
2081 if ~isa(orbDist, 'Disabled
')
2082 jnodes{n}.setOrbitImpatience(jclasses{r}, JLINE.from_line_distribution(orbDist));
2085 % Batch rejection probability (retrial queues)
2086 if ~isempty(line_nodes{n}.batchRejectProb) && ...
2087 r <= length(line_nodes{n}.batchRejectProb) && ...
2088 line_nodes{n}.batchRejectProb(r) > 0
2089 jnodes{n}.setBatchRejectProbability(jclasses{r}, line_nodes{n}.batchRejectProb(r));
2094 % PAS rate function + swap graph transfer; requires classes created first -- see _kb/12-interfaces-and-docs.md
2095 for n = 1: length(jnodes)
2096 if isempty(jnodes{n})
2099 if ~isa(line_nodes{n}, 'Queue
') || ...
2100 (line_nodes{n}.schedStrategy ~= SchedStrategy.PAS && line_nodes{n}.schedStrategy ~= SchedStrategy.OI)
2103 if isempty(line_nodes{n}.svcRateFun)
2104 line_error(mfilename, sprintf('PAS queue
''%s
'' has no service rate function mu(c); set it via setService(@(c) ...).
', line_nodes{n}.getName));
2106 if isinf(line_nodes{n}.cap)
2107 line_error(mfilename, sprintf('PAS queue
''%s
'' requires a finite capacity
for JLINE conversion; set it via setCap(...).
', line_nodes{n}.getName));
2109 jSerFun = JLINE.pas_handle_to_serializablefun(line_nodes{n}.svcRateFun, sn.nclasses, line_nodes{n}.cap);
2110 jnodes{n}.setServiceRateFunction(jSerFun);
2111 % Transfer the swap graph if explicitly set (otherwise the JAR
2112 % defaults to a complete graph at struct refresh, as MATLAB does)
2113 if ~isempty(line_nodes{n}.swapGraph)
2114 jnodes{n}.setSwapGraph(JLINE.from_line_matrix(line_nodes{n}.swapGraph));
2118 % Transfer heterogeneous server types and their per-(serverType,class)
2119 % service distributions. Requires classes to be created first.
2120 for n = 1: length(jnodes)
2121 if isempty(jnodes{n})
2124 if ~isa(line_nodes{n}, 'Queue
') || isempty(line_nodes{n}.serverTypes)
2127 % Map MATLAB class names to Java class objects
2128 % Add each server type with its compatible classes
2129 jServerTypes = cell(1, length(line_nodes{n}.serverTypes));
2130 for st = 1:length(line_nodes{n}.serverTypes)
2131 serverType = line_nodes{n}.serverTypes{st};
2132 jCompat = java.util.ArrayList();
2133 compatClasses = serverType.getCompatibleClasses();
2134 for cc = 1:length(compatClasses)
2135 jCompat.add(jclasses{compatClasses{cc}.index});
2137 jST = javaObject('jline.lang.constant.ServerType
', serverType.getName(), int32(serverType.getNumOfServers()), jCompat);
2138 jnodes{n}.addServerType(jST);
2139 jServerTypes{st} = jST;
2141 % Set heterogeneous scheduling policy
2142 switch line_nodes{n}.heteroSchedPolicy
2143 case HeteroSchedPolicy.ORDER
2144 jHetPol = jline.lang.constant.HeteroSchedPolicy.ORDER;
2145 case HeteroSchedPolicy.ALIS
2146 jHetPol = jline.lang.constant.HeteroSchedPolicy.ALIS;
2147 case HeteroSchedPolicy.ALFS
2148 jHetPol = jline.lang.constant.HeteroSchedPolicy.ALFS;
2149 case HeteroSchedPolicy.FAIRNESS
2150 jHetPol = jline.lang.constant.HeteroSchedPolicy.FAIRNESS;
2151 case HeteroSchedPolicy.FSF
2152 jHetPol = jline.lang.constant.HeteroSchedPolicy.FSF;
2153 case HeteroSchedPolicy.RAIS
2154 jHetPol = jline.lang.constant.HeteroSchedPolicy.RAIS;
2156 jHetPol = jline.lang.constant.HeteroSchedPolicy.ORDER;
2158 jnodes{n}.setHeteroSchedPolicy(jHetPol);
2159 % Set per-(serverType, class) service distributions
2160 for st = 1:length(line_nodes{n}.serverTypes)
2161 serverType = line_nodes{n}.serverTypes{st};
2162 for r = 1:length(line_classes)
2163 hetDist = line_nodes{n}.getHeteroService(line_classes{r}, serverType);
2164 if ~isempty(hetDist)
2165 jnodes{n}.setService(jclasses{r}, jServerTypes{st}, JLINE.from_line_distribution(hetDist));
2171 for n = 1: length(jnodes)
2172 if isempty(jnodes{n})
2173 continue; % Skip nodes that were not converted
2175 if isa(line_nodes{n},"ClassSwitch") && ~line_nodes{n}.autoAdded
2176 % Only set csMatrix for user-defined ClassSwitch nodes (not auto-added)
2177 JLINE.set_csMatrix(line_nodes{n}, jnodes{n}, jclasses);
2178 elseif isa(line_nodes{n},"Join")
2179 jnodes{n}.initJoinJobClasses();
2180 % Restore RAND routing for all classes, matching ClosedClass/OpenClass
2181 % constructor behavior (initJoinJobClasses sets DISABLED by default)
2182 for r = 1 : sn.nclasses
2183 jnodes{n}.setRouting(jclasses{r}, jline.lang.constant.RoutingStrategy.RAND);
2185 % Join quorum strategy/count transferred after initJoinJobClasses resets defaults
2186 for r = 1 : sn.nclasses
2187 if length(line_nodes{n}.input.joinStrategy) >= r && ~isempty(line_nodes{n}.input.joinStrategy{r}) ...
2188 && line_nodes{n}.input.joinStrategy{r} == JoinStrategy.PARTIAL
2189 jnodes{n}.setStrategy(jclasses{r}, jline.lang.constant.JoinStrategy.PARTIAL);
2191 if length(line_nodes{n}.input.joinRequired) >= r && ~isempty(line_nodes{n}.input.joinRequired{r}) ...
2192 && line_nodes{n}.input.joinRequired{r} > 0
2193 jnodes{n}.setRequired(jclasses{r}, line_nodes{n}.input.joinRequired{r});
2196 elseif isa(line_nodes{n},"Cache")
2197 hitC = line_nodes{n}.server.hitClass;
2198 missC = line_nodes{n}.server.missClass;
2199 for r = 1 : sn.nclasses
2200 % Per-class cache setup gated on what the class actually has, not hitClass alone -- see _kb/09-ldes-and-cache.md
2201 hasPop = numel(line_nodes{n}.popularity) >= r ...
2202 && ~isempty(line_nodes{n}.popularity{r}) ...
2203 && ~isa(line_nodes{n}.popularity{r},'Disabled
');
2204 hasHit = length(hitC) >= r && full(hitC(r)) > 0;
2205 hasMiss = length(missC) >= r && full(missC(r)) > 0;
2207 jnodes{n}.setRead(jclasses{r}, JLINE.from_line_distribution(line_nodes{n}.popularity{r}));
2210 jnodes{n}.setHitClass(jclasses{r}, jclasses{full(hitC(r))});
2213 jnodes{n}.setMissClass(jclasses{r}, jclasses{full(missC(r))});
2216 % Transfer accessProb from MATLAB to Java
2217 if ~isempty(line_nodes{n}.accessProb)
2218 accessProbMat = line_nodes{n}.accessProb;
2219 [K1, K2] = size(accessProbMat);
2220 jAccessProb = javaArray('jline.util.matrix.Matrix
', K1, K2);
2223 if ~isempty(accessProbMat{k1, k2})
2224 jAccessProb(k1, k2) = JLINE.from_line_matrix(accessProbMat{k1, k2});
2228 jnodes{n}.setAccessProb(jAccessProb);
2230 % attachRetrievalSystem restores delayed-hit bookkeeping the JAR solvers detect -- see _kb/09-ldes-and-cache.md
2231 if ~isempty(line_nodes{n}.retrievalSystemQueueIndices) ...
2232 && line_nodes{n}.retrievalSystemQueueIndices.Count > 0
2233 rsqi = line_nodes{n}.retrievalSystemQueueIndices;
2234 rclasses = line_nodes{n}.server.retrievalClasses; % [nItems x nclasses], 1-based or -1
2235 nItemsRS = size(rclasses, 1);
2236 keysRS = keys(rsqi);
2237 for kk = 1:numel(keysRS)
2238 jobinIdx0 = double(keysRS{kk}); % 0-based arrival class index
2239 jobinClassObj = jclasses{jobinIdx0 + 1};
2240 queueIdxs = rsqi(keysRS{kk}); % 1-based MATLAB node indices
2241 qList = javaObject('java.util.ArrayList
');
2242 for q = 1:numel(queueIdxs)
2243 qList.add(java.lang.Integer(int32(queueIdxs(q) - 1))); % 0-based node index
2245 rcArr = javaArray('jline.lang.JobClass
', nItemsRS);
2247 rIdx = rclasses(i, jobinIdx0 + 1);
2249 rcArr(i) = jclasses{rIdx};
2252 jnodes{n}.attachRetrievalSystem(jobinClassObj, qList, rcArr);
2255 elseif isa(line_nodes{n}, "Place") && line_nodes{n}.isQueueing()
2256 % QPN embedded queue marshalled after classes exist; setService flips the Place to queueing -- see _kb/12-interfaces-and-docs.md
2257 for r = 1:sn.nclasses
2258 if numel(line_nodes{n}.serviceProcess) >= r && ~isempty(line_nodes{n}.serviceProcess{r})
2259 jdist = JLINE.from_line_distribution(line_nodes{n}.serviceProcess{r});
2260 jnodes{n}.setService(jclasses{r}, jdist);
2263 nsrv = line_nodes{n}.numberOfServers;
2265 jnodes{n}.setNumberOfServers(int32(nsrv));
2267 for r = 1:sn.nclasses
2268 if numel(line_nodes{n}.departureDiscipline) >= r && line_nodes{n}.departureDiscipline(r) > 0
2269 jnodes{n}.setDepartureDiscipline(jclasses{r}, ...
2270 jline.lang.constant.DepartureDiscipline.fromID(line_nodes{n}.departureDiscipline(r)));
2273 elseif isa(line_nodes{n}, "Transition")
2274 % First, add modes (must be done after classes are created)
2275 for m = 1:line_nodes{n}.getNumberOfModes()
2276 modeName = line_nodes{n}.modeNames{m};
2277 jmode = jnodes{n}.addMode(modeName);
2278 % Set timing strategy
2279 switch line_nodes{n}.timingStrategies(m)
2280 case TimingStrategy.TIMED
2281 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.TIMED);
2282 case TimingStrategy.IMMEDIATE
2283 jnodes{n}.setTimingStrategy(jmode, jline.lang.constant.TimingStrategy.IMMEDIATE);
2286 jnodes{n}.setDistribution(jmode, JLINE.from_line_distribution(line_nodes{n}.distributions{m}));
2287 % Set firing weights and priorities
2288 jnodes{n}.setFiringWeights(jmode, line_nodes{n}.firingWeights(m));
2289 jnodes{n}.setFiringPriorities(jmode, int32(line_nodes{n}.firingPriorities(m)));
2290 % Set number of servers
2291 nsrv = line_nodes{n}.numberOfServers(m);
2293 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(intmax('int32
')));
2295 jnodes{n}.setNumberOfServers(jmode, java.lang.Integer(int32(nsrv)));
2298 % Now set enabling conditions, inhibiting conditions, and firing outcomes
2299 jmodes = jnodes{n}.getModes();
2300 for m = 1:line_nodes{n}.getNumberOfModes()
2301 jmode = jmodes.get(m-1);
2302 enabCond = line_nodes{n}.enablingConditions{m};
2303 inhibCond = line_nodes{n}.inhibitingConditions{m};
2304 firingOut = line_nodes{n}.firingOutcomes{m};
2305 % Condition matrices sized at addMode time; bound access by their own row count to avoid over-indexing
2306 for r = 1:sn.nclasses
2307 for i = 1:length(line_nodes)
2308 % Set enabling conditions
2309 if i <= size(enabCond, 1) && enabCond(i, r) > 0 && isa(line_nodes{i}, 'Place
')
2310 jnodes{n}.setEnablingConditions(jmode, jclasses{r}, jnodes{i}, enabCond(i, r));
2312 % Set inhibiting conditions
2313 if i <= size(inhibCond, 1) && inhibCond(i, r) < Inf && isa(line_nodes{i}, 'Place
')
2314 jnodes{n}.setInhibitingConditions(jmode, jclasses{r}, jnodes{i}, inhibCond(i, r));
2316 % Set firing outcomes
2317 if i <= size(firingOut, 1) && firingOut(i, r) ~= 0
2318 jnodes{n}.setFiringOutcome(jmode, jclasses{r}, jnodes{i}, firingOut(i, r));
2326 % Node states transferred before from_line_links to precede the JAR's initDefault validation -- see _kb/12-interfaces-and-docs.md
2327 for n = 1: length(line_nodes)
2328 if isempty(jnodes{n})
2331 if line_nodes{n}.isStateful
2332 jnodes{n}.setState(JLINE.from_line_matrix(line_nodes{n}.getState));
2333 jnodes{n}.setStateSpace(JLINE.from_line_matrix(line_nodes{n}.getStateSpace));
2334 jnodes{n}.setStatePrior(JLINE.from_line_matrix(line_nodes{n}.getStatePrior));
2338 % Assume JLINE and LINE network are both created via link
2339 JLINE.from_line_links(model, jnetwork);
2341 % Transfer finite capacity regions from MATLAB to Java
2342 if ~isempty(model.regions)
2343 for f = 1:length(model.regions)
2344 fcr = model.regions{f};
2345 % Convert MATLAB node list to Java list
2346 javaNodeList = java.util.ArrayList();
2347 for i = 1:length(fcr.nodes)
2348 matlabNode = fcr.
nodes{i};
2349 % Find corresponding Java node by name
2350 nodeName = matlabNode.getName();
2351 for j = 1:length(line_nodes)
2352 if strcmp(line_nodes{j}.getName(), nodeName) && ~isempty(jnodes{j})
2353 javaNodeList.add(jnodes{j});
2359 jfcr = jnetwork.addRegion(javaNodeList);
2360 % Set global max jobs
2361 if fcr.globalMaxJobs > 0 && ~isinf(fcr.globalMaxJobs)
2362 jfcr.setGlobalMaxJobs(fcr.globalMaxJobs);
2364 % Global memory budget passed unrounded (fractional classSize footprints are legitimate)
2365 if fcr.globalMaxMemory > 0 && ~isinf(fcr.globalMaxMemory)
2366 jfcr.setGlobalMaxMemory(fcr.globalMaxMemory);
2368 % Set per-class max jobs, memory, footprint, weight, drop rules
2369 for r = 1:length(line_classes)
2370 if length(fcr.classMaxJobs) >= r && fcr.classMaxJobs(r) > 0 && ~isinf(fcr.classMaxJobs(r))
2371 jfcr.setClassMaxJobs(jclasses{r}, fcr.classMaxJobs(r));
2373 if length(fcr.classMaxMemory) >= r && fcr.classMaxMemory(r) > 0 && ~isinf(fcr.classMaxMemory(r))
2374 jfcr.setClassMaxMemory(jclasses{r}, round(fcr.classMaxMemory(r)));
2376 % classSize passed unrounded, matching the JMT XML writer;
default-valued (1) entries skipped as redundant
2377 if length(fcr.classSize) >= r && isfinite(fcr.classSize(r)) && fcr.classSize(r) >= 0 && fcr.classSize(r) ~= 1
2378 jfcr.setClassSize(jclasses{r}, fcr.classSize(r));
2380 if length(fcr.classWeight) >= r && isfinite(fcr.classWeight(r)) && fcr.classWeight(r) > 0 && fcr.classWeight(r) ~= 1
2381 jfcr.setClassWeight(jclasses{r}, fcr.classWeight(r));
2383 if length(fcr.dropRule) >= r
2384 % Convert MATLAB DropStrategy numeric to Java DropStrategy
enum
2385 jDropStrategy = jline.lang.constant.DropStrategy.fromID(fcr.dropRule(r));
2386 jfcr.setDropRule(jclasses{r}, jDropStrategy);
2389 % Transfer linear constraints
if set
2390 if fcr.hasLinearConstraints()
2391 jA = JLINE.from_line_matrix(fcr.constraintA);
2392 jb = JLINE.from_line_matrix(fcr.constraintB);
2393 jfcr.setLinearConstraints(jA, jb);
2398 % CTMC reward handles marshalled as a tabulated TabulatedRewardFunction -- see _kb/12-interfaces-and-docs.md
2399 if (isstruct(sn) && isfield(sn, 'reward') || isprop(sn, 'reward')) && ~isempty(sn.reward)
2400 for ri = 1:length(sn.reward)
2401 jnetwork.setReward(sn.reward{ri}.name, JLINE.reward_handle_to_tabulatedfun(sn.reward{ri}.fn, sn));
2405 % Node states transferred before initDefault so it only fills
nodes still lacking one
2406 for n = 1: length(line_nodes)
2407 if isempty(jnodes{n})
2408 continue; % Skip
nodes that were not converted
2410 if line_nodes{n}.isStateful
2411 jnodes{n}.setState(JLINE.from_line_matrix(line_nodes{n}.getState));
2412 jnodes{n}.setStateSpace(JLINE.from_line_matrix(line_nodes{n}.getStateSpace));
2413 jnodes{n}.setStatePrior(JLINE.from_line_matrix(line_nodes{n}.getStatePrior));
2416 jnetwork.initDefault;
2417 % Force
struct refresh so sn.state reflects updated node states
2418 jnetwork.setHasStruct(
false);
2422 function jnetwork = line_to_jline(model)
2423 jnetwork = LINE2JLINE(model);
2426 function model = jline_to_line(jnetwork)
2427 if isa(jnetwork,
'JNetwork')
2428 jnetwork = jnetwork.obj;
2430 %javaaddpath(jar_loc);
2431 model = Network(
char(jnetwork.getName));
2432 network_nodes = jnetwork.getNodes;
2433 job_classes = jnetwork.getClasses;
2435 line_nodes = cell(network_nodes.size,1);
2436 line_classes = cell(job_classes.size,1);
2439 for n = 1 : network_nodes.size
2440 if ~isa(network_nodes.get(n-1), 'jline.lang.
nodes.ClassSwitch')
2441 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
2445 for n = 1 : job_classes.size
2446 line_classes{n} = JLINE.from_jline_class(job_classes.get(n-1), model);
2449 % Deferred signal target association (forJobClass), once all
2451 for n = 1 : job_classes.size
2452 jc = job_classes.get(n-1);
2453 if isa(jc,
'jline.lang.ClosedSignal') || isa(jc,
'jline.lang.OpenSignal') || isa(jc,
'jline.lang.Signal')
2454 jtarget = jc.getTargetJobClass();
2455 if ~isempty(jtarget)
2456 tname =
char(jtarget.getName);
2457 for m = 1 : job_classes.size
2458 if strcmp(line_classes{m}.name, tname)
2459 line_classes{n}.forJobClass(line_classes{m});
2467 for n = 1 : network_nodes.size
2468 if isa(network_nodes.get(n-1),
'jline.lang.nodes.ClassSwitch')
2469 line_nodes{n} = JLINE.from_jline_node(network_nodes.get(n-1), model, job_classes);
2473 % Deferred Fork/Join linking: set joinOf on Join
nodes
2474 for n = 1 : network_nodes.size
2475 jnode = network_nodes.get(n-1);
2476 if isa(jnode,
'jline.lang.nodes.Join') && ~isempty(jnode.joinOf)
2477 forkName =
char(jnode.joinOf.getName);
2478 for m = 1 : network_nodes.size
2479 if ~isempty(line_nodes{m}) && isa(line_nodes{m},
'Fork') && strcmp(line_nodes{m}.name, forkName)
2480 line_nodes{n}.joinOf = line_nodes{m};
2487 % Deferred Cache setup: set hitClass, missClass, popularity
2488 for n = 1 : network_nodes.size
2489 jnode = network_nodes.get(n-1);
2490 if isa(jnode,
'jline.lang.nodes.Cache') && isa(line_nodes{n},
'Cache')
2491 cacheNode = line_nodes{n};
2492 % hitClass and missClass are stored as index vectors
2493 hitClassVec = JLINE.from_jline_matrix(jnode.getHitClass());
2494 missClassVec = JLINE.from_jline_matrix(jnode.getMissClass());
2495 for r = 1:job_classes.size
2496 hitIdx = hitClassVec(r);
2497 if hitIdx >= 0 && (hitIdx + 1) <= job_classes.size
2498 cacheNode.setHitClass(line_classes{r}, line_classes{hitIdx + 1});
2500 missIdx = missClassVec(r);
2501 if missIdx >= 0 && (missIdx + 1) <= job_classes.size
2502 cacheNode.setMissClass(line_classes{r}, line_classes{missIdx + 1});
2505 % Popularity distributions
2506 for r = 1:job_classes.size
2508 popDist = jnode.popularityGet(0, r-1);
2509 if ~isempty(popDist) && popDist.isDiscrete()
2510 matlabDist = JLINE.from_jline_distribution(popDist);
2511 if ~isempty(matlabDist)
2512 cacheNode.setRead(line_classes{r}, matlabDist);
2516 % No popularity
for this class
2522 for n = 1 : network_nodes.size
2523 JLINE.set_line_service(network_nodes.get(n-1), line_nodes{n}, job_classes, line_classes);
2526 % Configure Transition modes (distributions, enabling/inhibiting/firing, etc.)
2527 for n = 1 : network_nodes.size
2528 jnode = network_nodes.get(n-1);
2529 if isa(jnode, 'jline.lang.
nodes.Transition') && isa(line_nodes{n},
'Transition')
2530 tnode = line_nodes{n};
2531 jmodes = jnode.getModes();
2532 nmodes = jmodes.size();
2534 jmode = jmodes.get(m-1);
2535 modeName = char(jmode.getName());
2536 % addMode
if not yet present (Transition starts with one
default mode)
2537 if m > tnode.getNumberOfModes()
2538 tnode.addMode(modeName);
2540 tnode.setModeNames(m, modeName);
2543 ts = jnode.timingStrategies.get(jmode);
2545 tsName = char(ts.name());
2546 if strcmp(tsName,
'IMMEDIATE')
2547 tnode.setTimingStrategy(m, TimingStrategy.IMMEDIATE);
2549 tnode.setTimingStrategy(m, TimingStrategy.TIMED);
2553 jdist = jnode.getFiringDistribution(jmode);
2555 matlabDist = JLINE.from_jline_distribution(jdist);
2556 if ~isempty(matlabDist)
2557 tnode.setDistribution(m, matlabDist);
2561 numSrv = jnode.getNumberOfModeServers(jmode);
2562 if numSrv == intmax('int32') || numSrv == intmax('int64')
2563 tnode.setNumberOfServers(m, Inf);
2565 tnode.setNumberOfServers(m,
double(numSrv));
2567 % Firing priority and weight (read from matrices by mode index)
2568 if jnode.firingPriorities.getNumElements() > (m-1)
2569 tnode.setFiringPriorities(m, jnode.firingPriorities.get(m-1));
2571 if jnode.firingWeights.getNumElements() > (m-1)
2572 tnode.setFiringWeights(m, jnode.firingWeights.get(m-1));
2574 % Enabling conditions
2575 ecMat = jnode.enablingConditions.get(jmode);
2577 nrows = ecMat.getNumRows();
2578 ncols = ecMat.getNumCols();
2581 val = ecMat.get(ni-1, ci-1);
2582 if val > 0 && ni <= length(line_nodes) && isa(line_nodes{ni},
'Place')
2583 tnode.setEnablingConditions(m, ci, line_nodes{ni}, val);
2588 % Inhibiting conditions
2589 icMat = jnode.inhibitingConditions.get(jmode);
2591 nrows = icMat.getNumRows();
2592 ncols = icMat.getNumCols();
2595 val = icMat.get(ni-1, ci-1);
2596 if isfinite(val) && val > 0 && ni <= length(line_nodes) && isa(line_nodes{ni},
'Place')
2597 tnode.setInhibitingConditions(m, ci, line_nodes{ni}, val);
2603 foMat = jnode.firingOutcomes.get(jmode);
2605 nrows = foMat.getNumRows();
2606 ncols = foMat.getNumCols();
2609 val = foMat.get(ni-1, ci-1);
2610 if val ~= 0 && ni <= length(line_nodes)
2611 tnode.setFiringOutcome(m, ci, line_nodes{ni}, val);
2620 % Check
for state-dependent routing (RROBIN, WRROBIN, JSQ)
2621 % These cannot go through link(
P) because it overrides routing strategies
2622 hasSDRouting = false;
2623 for n = 1 : network_nodes.size
2624 jnode = network_nodes.get(n-1);
2625 output_strategies = jnode.getOutputStrategies();
2626 for m = 1 : output_strategies.size()
2627 rs = char(output_strategies.get(m-1).getRoutingStrategy);
2628 if any(strcmp(rs, {
'RROBIN',
'WRROBIN',
'JSQ',
'SQ'}))
2629 hasSDRouting = true;
2633 if hasSDRouting; break; end
2637 % State-dependent routing: use addLink + setRouting
2638 model = JLINE.from_jline_routing(model, jnetwork);
2639 elseif ~isempty(jnetwork.getStruct.rtorig)
2641 model = JLINE.from_jline_links(model, jnetwork);
2643 % Do not use link() method
2644 model = JLINE.from_jline_routing(model, jnetwork);
2647 % Restore initial state on Place
nodes after linking
2648 for n = 1 : network_nodes.size
2649 jnode = network_nodes.get(n-1);
2650 if isa(jnode, 'jline.lang.
nodes.Place') && ~isempty(line_nodes{n}) && isa(line_nodes{n},
'Place')
2651 jst = jnode.getState();
2652 if ~isempty(jst) && ~jst.isEmpty()
2653 line_nodes{n}.setState(JLINE.from_jline_matrix(jst));
2658 % FCR transfer, reverse of the from_line_network block above
2659 jregions = jnetwork.getRegions();
2660 for f = 1 : jregions.size()
2661 jfcr = jregions.get(f-1);
2662 jrnodes = jfcr.getNodes();
2663 regionNodes = cell(1, jrnodes.size());
2664 for i = 1 : jrnodes.size()
2665 rname = char(jrnodes.get(i-1).getName());
2666 for n = 1 : length(line_nodes)
2667 if ~isempty(line_nodes{n}) && strcmp(line_nodes{n}.getName(), rname)
2668 regionNodes{i} = line_nodes{n};
2673 fcr = model.addRegion(regionNodes);
2674 gmj = jfcr.getGlobalMaxJobs();
2676 fcr.setGlobalMaxJobs(gmj);
2678 gmm = jfcr.getGlobalMaxMemory();
2680 fcr.setGlobalMaxMemory(gmm);
2682 for r = 1 : length(line_classes)
2683 jclass = job_classes.get(r-1);
2684 cmj = jfcr.getClassMaxJobs(jclass);
2686 fcr.setClassMaxJobs(line_classes{r}, cmj);
2688 cmm = jfcr.getClassMaxMemory(jclass);
2690 fcr.setClassMaxMemory(line_classes{r}, cmm);
2692 cw = jfcr.getClassWeight(jclass);
2693 if isfinite(cw) && cw > 0 && cw ~= 1
2694 fcr.setClassWeight(line_classes{r}, cw);
2696 cs = jfcr.getClassSize(jclass);
2697 if isfinite(cs) && cs >= 0 && cs ~= 1
2698 fcr.setClassSize(line_classes{r}, cs);
2700 % Java getID() uses the MATLAB numeric ids (fromID accepts
2701 % them on the forward path), so the
id round-trips directly.
2702 fcr.setDropRule(line_classes{r}, jfcr.getDropStrategy(jclass).getID());
2704 jlin = jfcr.getLinearConstraints();
2706 fcr.setConstraint(JLINE.from_jline_matrix(jlin(1)), JLINE.from_jline_matrix(jlin(2)));
2711 function matrix = arraylist_to_matrix(jline_matrix)
2712 if isempty(jline_matrix)
2715 matrix = zeros(jline_matrix.size(), 1);
2716 for row = 1:jline_matrix.size()
2717 matrix(row, 1) = jline_matrix.get(row-1);
2722 function matrix = from_jline_matrix(jline_matrix)
2723 if isempty(jline_matrix)
2726 matrix = zeros(jline_matrix.getNumRows(), jline_matrix.getNumCols());
2727 for row = 1:jline_matrix.getNumRows()
2728 for col = 1:jline_matrix.getNumCols()
2729 val = jline_matrix.get(row-1, col-1);
2730 if (val >= 33333333 && val <= 33333334)
2731 matrix(row, col) = GlobalConstants.Immediate;
2732 elseif (val >= -33333334 && val <= -33333333)
2733 matrix(row, col) = -GlobalConstants.Immediate;
2734 elseif (val >= 2147483647 - 1) % Integer.MAX_VALUE with -1 tolerance
2735 matrix(row, col) = Inf;
2736 elseif (val <= -2147483648 + 1) % Integer.MIN_VALUE with +1 tolerance
2737 matrix(row, col) = -Inf;
2739 matrix(row, col) = val;
2746 function jdist = from_line_lqn_dist(ptype, dmean, dscv, dparams, dproc)
2747 % JDIST = FROM_LINE_LQN_DIST(PTYPE, DMEAN, DSCV, DPROC)
2748 % Rebuild a JAR distribution from the LayeredNetworkStruct fields of
2749 % an LQN distribution, keeping its variability. Passing the mean
2750 % alone to a setSomething(
double) overload rebuilds it as Exp(1/mean)
2751 % with SCV 1, which silently discards everything above the first
2752 % moment: an Erlang setup and an exponential one of the same mean
2753 % would reach the JAR as the same process.
2755 case ProcessType.IMMEDIATE
2756 jdist = jline.lang.processes.Immediate;
2757 case ProcessType.EXP
2758 jdist = jline.lang.processes.Exp(1/dmean);
2759 case ProcessType.ERLANG
2760 jdist = jline.lang.processes.Erlang.fitMeanAndSCV(dmean, dscv);
2761 case ProcessType.HYPEREXP
2762 % Rebuilt from its own (p,lambda1,lambda2), not a two-moment refit -- see _kb/12-interfaces-and-docs.md
2763 if ~isempty(dparams) && length(dparams) >= 3
2764 jdist = jline.lang.processes.HyperExp(dparams(1), dparams(2), dparams(3));
2766 jdist = jline.lang.processes.HyperExp.fitMeanAndSCV(dmean, dscv);
2768 case ProcessType.COXIAN
2769 jdist = jline.lang.processes.Coxian.fitMeanAndSCV(dmean, dscv);
2770 case ProcessType.APH
2771 jdist = jline.lang.processes.APH.fitMeanAndSCV(dmean, dscv);
2772 case {ProcessType.PH, ProcessType.MAP}
2774 if ptype == ProcessType.PH
2775 jdist = jline.lang.processes.PH(JLINE.from_line_matrix(dproc{1}), JLINE.from_line_matrix(dproc{2}));
2777 jdist = jline.lang.processes.MAP(JLINE.from_line_matrix(dproc{1}), JLINE.from_line_matrix(dproc{2}));
2780 jdist = jline.lang.processes.Exp(1/dmean);
2782 case ProcessType.DET
2783 jdist = jline.lang.processes.Det(dmean);
2785 % Any other type
is carried by mean and SCV, which
is exact
2786 %
for SCV 1 and a two-moment fit otherwise.
2787 if abs(dscv-1) < GlobalConstants.FineTol
2788 jdist = jline.lang.processes.Exp(1/dmean);
2790 jdist = jline.lang.processes.APH.fitMeanAndSCV(dmean, dscv);
2795 function jline_matrix = from_line_matrix(matrix)
2796 [rows, cols] = size(matrix);
2797 jline_matrix = jline.util.matrix.Matrix(rows, cols);
2800 if matrix(row,col) ~= 0
2801 jline_matrix.set(row-1, col-1, matrix(row, col));
2807 function lsn = from_jline_struct_layered(jlayerednetwork, jlsn)
2808 lsn = LayeredNetworkStruct();
2809 lsn.nidx= jlsn.nidx;
2810 lsn.nhosts= jlsn.nhosts;
2811 lsn.ntasks= jlsn.ntasks;
2812 lsn.nentries= jlsn.nentries;
2813 lsn.nacts= jlsn.nacts;
2814 lsn.ncalls= jlsn.ncalls;
2815 lsn.hshift= jlsn.hshift;
2816 lsn.tshift= jlsn.tshift;
2817 lsn.eshift= jlsn.eshift;
2818 lsn.ashift= jlsn.ashift;
2819 lsn.cshift= jlsn.cshift;
2821 lsn.tasksof{h,1} = JLINE.arraylist_to_matrix(jlsn.tasksof.get(uint32(h)))
';
2824 lsn.entriesof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.entriesof.get(uint32(jlsn.tshift+t)))';
2826 for t=1:(jlsn.ntasks+jlsn.nentries)
2827 lsn.actsof{lsn.tshift+t,1} = JLINE.arraylist_to_matrix(jlsn.actsof.get(uint32(jlsn.tshift+t)))';
2830 lsn.callsof{lsn.ashift+a,1} = JLINE.arraylist_to_matrix(jlsn.callsof.get(uint32(jlsn.ashift+a)))';
2832 for i = 1:jlsn.sched.size
2833 lsn.sched(i,1) = SchedStrategy.(char(jlsn.sched.get(uint32(i))));
2835 for i = 1:jlsn.names.size
2836 lsn.names{i,1} = jlsn.names.get(uint32(i));
2837 lsn.hashnames{i,1} = jlsn.hashnames.get(uint32(i));
2839 lsn.mult = JLINE.from_jline_matrix(jlsn.mult);
2840 lsn.mult = lsn.mult(2:(lsn.eshift+1))
'; % remove 0-padding
2841 lsn.maxmult = JLINE.from_jline_matrix(jlsn.maxmult);
2842 lsn.maxmult = lsn.maxmult(2:(lsn.eshift+1))'; % remove 0-padding
2844 lsn.repl = JLINE.from_jline_matrix(jlsn.repl)';
2845 lsn.repl = lsn.repl(2:end); % remove 0-padding
2846 lsn.type = JLINE.from_jline_matrix(jlsn.type)';
2847 lsn.type = lsn.type(2:end); % remove 0-padding
2848 lsn.parent = JLINE.from_jline_matrix(jlsn.parent);
2849 lsn.parent = lsn.parent(2:end); % remove 0-padding
2850 lsn.nitems = JLINE.from_jline_matrix(jlsn.nitems);
2851 % Ensure proper
column vector format matching MATLAB
's (nhosts+ntasks+nentries) x 1
2852 if isrow(lsn.nitems)
2853 lsn.nitems = lsn.nitems(2:end)'; % remove 0-padding and transpose
2855 lsn.nitems = lsn.nitems(2:end); % remove 0-padding (already
column)
2857 % Ensure correct size
2858 expectedSize = lsn.nhosts + lsn.ntasks + lsn.nentries;
2859 if length(lsn.nitems) < expectedSize
2860 lsn.nitems(expectedSize,1) = 0;
2861 elseif length(lsn.nitems) > expectedSize
2862 lsn.nitems = lsn.nitems(1:expectedSize);
2864 lsn.replacestrat = JLINE.from_jline_matrix(jlsn.replacestrat);
2865 lsn.replacestrat = lsn.replacestrat(2:end)
'; % remove 0-padding
2866 for i = 1:jlsn.callnames.size
2867 lsn.callnames{i,1} = jlsn.callnames.get(uint32(i));
2868 lsn.callhashnames{i,1} = jlsn.callhashnames.get(uint32(i));
2870 for i = 1:jlsn.calltype.size % calltype may be made into a matrix in Java
2871 ct = char(jlsn.calltype.get(uint32(i)));
2872 lsn.calltype(i) = CallType.(ct);
2874 lsn.calltype = sparse(lsn.calltype'); % remove 0-padding
2875 lsn.callpair = JLINE.from_jline_matrix(jlsn.callpair);
2876 lsn.callpair = lsn.callpair(2:end,2:end); % remove 0-paddings
2877 if isempty(lsn.callpair)
2880 lsn.actpretype = sparse(JLINE.from_jline_matrix(jlsn.actpretype)
');
2881 lsn.actpretype = lsn.actpretype(2:end); % remove 0-padding
2882 lsn.actposttype = sparse(JLINE.from_jline_matrix(jlsn.actposttype)');
2883 lsn.actposttype = lsn.actposttype(2:end); % remove 0-padding
2884 lsn.graph = JLINE.from_jline_matrix(jlsn.graph);
2885 lsn.graph = lsn.graph(2:end,2:end); % remove 0-paddings
2886 lsn.dag = JLINE.from_jline_matrix(jlsn.dag);
2887 lsn.dag = lsn.dag(2:end,2:end); % remove 0-paddings
2888 lsn.taskgraph = JLINE.from_jline_matrix(jlsn.taskgraph);
2889 lsn.taskgraph = sparse(lsn.taskgraph(2:end,2:end)); % remove 0-paddings
2890 lsn.replygraph = JLINE.from_jline_matrix(jlsn.replygraph);
2891 lsn.replygraph = logical(lsn.replygraph(2:end,2:end)); % remove 0-paddings
2892 lsn.iscache = JLINE.from_jline_matrix(jlsn.iscache);
2893 % Ensure proper
column vector format matching MATLAB
's (nhosts+ntasks) x 1
2894 expectedCacheSize = lsn.nhosts + lsn.ntasks;
2895 if isrow(lsn.iscache)
2896 if length(lsn.iscache) > expectedCacheSize
2897 lsn.iscache = lsn.iscache(2:(expectedCacheSize+1))'; % remove 0-padding and transpose
2899 lsn.iscache = lsn.iscache'; % just transpose
2902 % Ensure correct size
2903 if length(lsn.iscache) < expectedCacheSize
2904 lsn.iscache(expectedCacheSize,1) = 0;
2905 elseif length(lsn.iscache) > expectedCacheSize
2906 lsn.iscache = lsn.iscache(1:expectedCacheSize);
2908 lsn.iscaller = JLINE.from_jline_matrix(jlsn.iscaller);
2909 lsn.iscaller = full(lsn.iscaller(2:end,2:end)); % remove 0-paddings
2910 lsn.issynccaller = JLINE.from_jline_matrix(jlsn.issynccaller);
2911 lsn.issynccaller = full(lsn.issynccaller(2:end,2:end)); % remove 0-paddings
2912 lsn.isasynccaller = JLINE.from_jline_matrix(jlsn.isasynccaller);
2913 lsn.isasynccaller = full(lsn.isasynccaller(2:end,2:end)); % remove 0-paddings
2914 lsn.isref = JLINE.from_jline_matrix(jlsn.isref);
2915 lsn.isref = lsn.isref(2:end)
'; % remove 0-paddings
2918 function sn = from_jline_struct(jnetwork, jsn)
2919 %lst and rtfun are not implemented
2920 %Due to the transformation of Java lambda to matlab function
2922 jsn = jnetwork.getStruct(false);
2924 jclasses = jnetwork.getClasses();
2925 jnodes = jnetwork.getNodes();
2926 jstateful = jnetwork.getStatefulNodes();
2927 jstations = jnetwork.getStations();
2928 sn = NetworkStruct();
2930 sn.nnodes = jsn.nnodes;
2931 sn.nclasses = jsn.nclasses;
2932 sn.nclosedjobs = jsn.nclosedjobs;
2933 sn.nstations = jsn.nstations;
2934 sn.nstateful = jsn.nstateful;
2935 sn.nchains = jsn.nchains;
2937 sn.refstat = JLINE.from_jline_matrix(jsn.refstat) + 1;
2938 sn.njobs = JLINE.from_jline_matrix(jsn.njobs);
2939 sn.nservers = JLINE.from_jline_matrix(jsn.nservers);
2940 sn.connmatrix = JLINE.from_jline_matrix(jsn.connmatrix);
2941 % Fix for Java getConnectionMatrix bug: ensure connmatrix is nnodes x nnodes
2942 if size(sn.connmatrix,1) < sn.nnodes
2943 sn.connmatrix(sn.nnodes,1) = 0;
2945 if size(sn.connmatrix,2) < sn.nnodes
2946 sn.connmatrix(1,sn.nnodes) = 0;
2948 sn.scv = JLINE.from_jline_matrix(jsn.scv);
2949 sn.isstation = logical(JLINE.from_jline_matrix(jsn.isstation));
2950 sn.isstateful = logical(JLINE.from_jline_matrix(jsn.isstateful));
2951 sn.isstatedep = logical(JLINE.from_jline_matrix(jsn.isstatedep));
2952 sn.nodeToStateful = JLINE.from_jline_matrix(jsn.nodeToStateful)+1;
2953 sn.nodeToStateful(sn.nodeToStateful==0) = nan;
2954 sn.nodeToStation = JLINE.from_jline_matrix(jsn.nodeToStation)+1;
2955 sn.nodeToStation(sn.nodeToStation==0) = nan;
2956 sn.stationToNode = JLINE.from_jline_matrix(jsn.stationToNode)+1;
2957 sn.stationToNode(sn.stationToNode==0) = nan;
2958 sn.stationToStateful = JLINE.from_jline_matrix(jsn.stationToStateful)+1;
2959 sn.stationToStateful(sn.stationToStateful==0) = nan;
2960 sn.statefulToStation = JLINE.from_jline_matrix(jsn.statefulToStation)+1;
2961 sn.statefulToStation(sn.statefulToStation==0) = nan;
2962 sn.statefulToNode = JLINE.from_jline_matrix(jsn.statefulToNode)+1;
2963 sn.statefulToNode(sn.statefulToNode==0) = nan;
2964 sn.rates = JLINE.from_jline_matrix(jsn.rates);
2965 sn.fj = JLINE.from_jline_matrix(jsn.fj);
2966 sn.classprio = JLINE.from_jline_matrix(jsn.classprio);
2967 sn.phases = JLINE.from_jline_matrix(jsn.phases);
2968 sn.phasessz = JLINE.from_jline_matrix(jsn.phasessz);
2969 sn.phaseshift = JLINE.from_jline_matrix(jsn.phaseshift);
2970 sn.schedparam = JLINE.from_jline_matrix(jsn.schedparam);
2971 sn.chains = logical(JLINE.from_jline_matrix(jsn.chains));
2972 sn.rt = JLINE.from_jline_matrix(jsn.rt);
2973 sn.nvars = JLINE.from_jline_matrix(jsn.nvars);
2974 sn.rtnodes = JLINE.from_jline_matrix(jsn.rtnodes);
2975 sn.csmask = logical(JLINE.from_jline_matrix(jsn.csmask));
2976 sn.isslc = logical(JLINE.from_jline_matrix(jsn.isslc));
2977 sn.cap = JLINE.from_jline_matrix(jsn.cap);
2978 sn.classcap = JLINE.from_jline_matrix(jsn.classcap);
2979 sn.refclass = JLINE.from_jline_matrix(jsn.refclass)+1;
2980 sn.lldscaling = JLINE.from_jline_matrix(jsn.lldscaling);
2982 if ~isempty(jsn.cdscaling) && jsn.cdscaling.size() > 0
2983 % Convert Java SerializableFunction to MATLAB function handles
2984 sn.cdscaling = cell(sn.nstations, 1);
2985 % Iterate through the map entries to handle null values properly
2986 entrySet = jsn.cdscaling.entrySet();
2987 entryIter = entrySet.iterator();
2988 stationFunMap = containers.Map();
2989 while entryIter.hasNext()
2990 entry = entryIter.next();
2991 stationName = char(entry.getKey().getName());
2993 jfun = entry.getValue();
2995 stationFunMap(stationName) = jfun;
2998 % getValue() returns null for default lambda functions
2999 % Skip and use default value
3002 % Assign functions to stations
3003 for i = 1:sn.nstations
3004 jstation = jstations.get(i-1);
3005 stationName = char(jstation.getName());
3006 if isKey(stationFunMap, stationName)
3007 jfun = stationFunMap(stationName);
3008 % Create a MATLAB function handle that calls the Java apply() method
3009 sn.cdscaling{i} = @(ni) JLINE.call_java_cdscaling(jfun, ni);
3011 sn.cdscaling{i} = @(ni) 1;
3015 sn.cdscaling = cell(sn.nstations, 0);
3018 % joint-dependence handles eta_i(n) (non-product-form), twin of the
3019 % cdscaling readback above.
3020 if isprop(jsn, 'jdscaling
') && ~isempty(jsn.jdscaling) && jsn.jdscaling.size() > 0
3021 sn.jdscaling = cell(sn.nstations, 1);
3022 entrySet = jsn.jdscaling.entrySet();
3023 entryIter = entrySet.iterator();
3024 stationFunMap = containers.Map();
3025 while entryIter.hasNext()
3026 entry = entryIter.next();
3027 stationName = char(entry.getKey().getName());
3029 jfun = entry.getValue();
3031 stationFunMap(stationName) = jfun;
3036 for i = 1:sn.nstations
3037 jstation = jstations.get(i-1);
3038 stationName = char(jstation.getName());
3039 if isKey(stationFunMap, stationName)
3040 jfun = stationFunMap(stationName);
3041 sn.jdscaling{i} = @(ni) JLINE.call_java_cdscaling(jfun, ni);
3043 sn.jdscaling{i} = @(ni) 1;
3047 sn.jdscaling = cell(sn.nstations, 0);
3050 if ~isempty(jsn.nodetype)
3051 sn.nodetype = zeros(sn.nnodes, 1);
3052 for i = 1:jsn.nodetype.size
3053 nodetype = jsn.nodetype.get(i-1);
3054 switch nodetype.name().toCharArray'
3056 sn.nodetype(i) = NodeType.Queue;
3058 sn.nodetype(i) = NodeType.Delay;
3060 sn.nodetype(i) = NodeType.Source;
3062 sn.nodetype(i) = NodeType.Sink;
3064 sn.nodetype(i) = NodeType.Join;
3066 sn.nodetype(i) = NodeType.Fork;
3068 sn.nodetype(i) = NodeType.ClassSwitch;
3070 sn.nodetype(i) = NodeType.Logger;
3072 sn.nodetype(i) = NodeType.Cache;
3074 sn.nodetype(i) = NodeType.Place;
3076 sn.nodetype(i) = NodeType.Transition;
3078 sn.nodetype(i) = NodeType.Router;
3085 if ~isempty(jsn.classnames)
3086 for i = 1:jsn.classnames.size
3087 sn.classnames(i,1) = jsn.classnames.get(i-1);
3093 if ~isempty(jsn.nodenames)
3094 for i = 1:jsn.nodenames.size
3095 sn.nodenames(i,1) = jsn.nodenames.get(i-1);
3101 if ~isempty(jsn.rtorig) && jsn.rtorig.size()>0
3102 sn.rtorig = cell(sn.nclasses, sn.nclasses);
3103 for r = 1:sn.nclasses
3104 for s = 1:sn.nclasses
3105 sn.rtorig{r,s} = JLINE.from_jline_matrix(jsn.rtorig.get(jclasses.get(r-1)).get(jclasses.get(s-1)));
3112 if ~isempty(jsn.state)
3113 sn.state = cell(sn.nstateful, 1);
3114 for i = 1:sn.nstateful
3115 sn.state{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getState());
3121 if ~isempty(jsn.stateprior)
3122 sn.stateprior = cell(sn.nstateful, 1);
3123 for i = 1:sn.nstateful
3124 sn.stateprior{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStatePrior());
3130 if ~isempty(jsn.space)
3131 sn.space = cell(sn.nstateful, 1);
3132 for i = 1:sn.nstateful
3133 sn.space{i} = JLINE.from_jline_matrix(jstateful.get(i-1).getStateSpace());
3139 if ~isempty(jsn.routing)
3140 sn.routing = zeros(sn.nnodes, sn.nclasses);
3142 for j = 1:sn.nclasses
3143 routingStrategy = jsn.routing.get(jnodes.get(i-1)).get(jclasses.get(j-1));
3144 switch routingStrategy.name().toCharArray'
3146 sn.routing(i,j) = RoutingStrategy.PROB;
3148 sn.routing(i,j) = RoutingStrategy.RAND;
3150 sn.routing(i,j) = RoutingStrategy.RROBIN;
3152 sn.routing(i,j) = RoutingStrategy.WRROBIN;
3154 sn.routing(i,j) = RoutingStrategy.JSQ;
3156 sn.routing(i,j) = RoutingStrategy.DISABLED;
3158 sn.routing(i,j) = RoutingStrategy.FIRING;
3160 sn.routing(i,j) = RoutingStrategy.SQ;
3168 if ~isempty(jsn.procid)
3169 sn.procid = nan(sn.nstations, sn.nclasses); % Initialize with NaN to match MATLAB behavior
3170 for i = 1:sn.nstations
3171 for j = 1:sn.nclasses
3172 stationMap = jsn.procid.get(jstations.get(i-1));
3173 if isempty(stationMap)
3174 sn.procid(i,j) = ProcessType.DISABLED;
3177 processType = stationMap.get(jclasses.get(j-1));
3178 if isempty(processType)
3179 sn.procid(i,j) = ProcessType.DISABLED;
3182 switch processType.name.toCharArray'
3184 sn.procid(i,j) = ProcessType.EXP;
3186 sn.procid(i,j) = ProcessType.ERLANG;
3188 sn.procid(i,j) = ProcessType.HYPEREXP;
3190 sn.procid(i,j) = ProcessType.PH;
3192 sn.procid(i,j) = ProcessType.APH;
3194 sn.procid(i,j) = ProcessType.MAP;
3196 sn.procid(i,j) = ProcessType.UNIFORM;
3198 sn.procid(i,j) = ProcessType.DET;
3200 sn.procid(i,j) = ProcessType.COXIAN;
3202 sn.procid(i,j) = ProcessType.GAMMA;
3204 sn.procid(i,j) = ProcessType.PARETO;
3206 sn.procid(i,j) = ProcessType.WEIBULL;
3208 sn.procid(i,j) = ProcessType.LOGNORMAL;
3210 sn.procid(i,j) = ProcessType.MMPP2;
3212 sn.procid(i,j) = ProcessType.REPLAYER;
3214 sn.procid(i,j) = ProcessType.TRACE;
3216 sn.procid(i,j) = ProcessType.IMMEDIATE;
3218 sn.procid(i,j) = ProcessType.DISABLED;
3220 sn.procid(i,j) = ProcessType.COX2;
3222 sn.procid(i,j) = ProcessType.BMAP;
3224 sn.procid(i,j) = ProcessType.ME;
3226 sn.procid(i,j) = ProcessType.RAP;
3228 sn.procid(i,j) = ProcessType.BINOMIAL;
3230 sn.procid(i,j) = ProcessType.POISSON;
3232 sn.procid(i,j) = ProcessType.GEOMETRIC;
3234 sn.procid(i,j) = ProcessType.DUNIFORM;
3236 sn.procid(i,j) = ProcessType.BERNOULLI;
3238 sn.procid(i,j) = ProcessType.PRIOR;
3240 % Unknown ProcessType - default to DISABLED
3241 sn.procid(i,j) = ProcessType.DISABLED;
3250 sn.mu = cell(sn.nstations, 1);
3251 for i = 1:sn.nstations
3252 sn.mu{i} = cell(1, sn.nclasses);
3253 for j = 1:sn.nclasses
3254 sn.mu{i}{j} = JLINE.from_jline_matrix(jsn.mu.get(jstations.get(i-1)).get(jclasses.get(j-1)));
3261 if ~isempty(jsn.phi)
3262 sn.phi = cell(sn.nstations, 1);
3263 for i = 1:sn.nstations
3264 sn.phi{i} = cell(1, sn.nclasses);
3265 for j = 1:sn.nclasses
3266 sn.phi{i}{j} = JLINE.from_jline_matrix(jsn.phi.get(jstations.get(i-1)).get(jclasses.get(j-1)));
3273 if ~isempty(jsn.proc)
3274 sn.proc = cell(sn.nstations, 1);
3275 for i = 1:sn.nstations
3276 sn.proc{i} = cell(1, sn.nclasses);
3277 for j = 1:sn.nclasses
3278 proc_i_j = jsn.proc.get(jstations.get(i-1)).get(jclasses.get(j-1));
3279 sn.proc{i}{j} = cell(1, proc_i_j.size);
3280 for k = 1:proc_i_j.size
3281 sn.proc{i}{j}{k} = JLINE.from_jline_matrix(proc_i_j.get(uint32(k-1)));
3289 if ~isempty(jsn.pie)
3290 sn.pie = cell(sn.nstations, 1);
3291 for i = 1:sn.nstations
3292 sn.pie{i} = cell(1, sn.nclasses);
3293 for j = 1:sn.nclasses
3294 sn.pie{i}{j} = JLINE.from_jline_matrix(jsn.pie.get(jstations.get(i-1)).get(jclasses.get(j-1)));
3301 if ~isempty(jsn.sched)
3302 sn.sched = zeros(sn.nstations, 1);
3303 for i = 1:sn.nstations
3304 schedStrategy = jsn.sched.get(jstations.get(i-1));
3305 switch schedStrategy.name.toCharArray'
3307 sn.sched(i) = SchedStrategy.INF;
3309 sn.sched(i) = SchedStrategy.FCFS;
3311 sn.sched(i) = SchedStrategy.LCFS;
3313 sn.sched(i) = SchedStrategy.LCFSPR;
3315 sn.sched(i) = SchedStrategy.SIRO;
3317 sn.sched(i) = SchedStrategy.SJF;
3319 sn.sched(i) = SchedStrategy.LJF;
3321 sn.sched(i) = SchedStrategy.PS;
3323 sn.sched(i) = SchedStrategy.DPS;
3325 sn.sched(i) = SchedStrategy.GPS;
3327 sn.sched(i) = SchedStrategy.PSPRIO;
3329 sn.sched(i) = SchedStrategy.DPSPRIO;
3331 sn.sched(i) = SchedStrategy.GPSPRIO;
3333 sn.sched(i) = SchedStrategy.SEPT;
3335 sn.sched(i) = SchedStrategy.LEPT;
3336 case {
'HOL',
'FCFSPRIO'}
3337 sn.sched(i) = SchedStrategy.FCFSPRIO;
3339 sn.sched(i) = SchedStrategy.FORK;
3341 sn.sched(i) = SchedStrategy.EXT;
3343 sn.sched(i) = SchedStrategy.REF;
3350 if ~isempty(jsn.inchain)
3351 sn.inchain = cell(1, sn.nchains);
3352 for i = 1:sn.nchains
3353 sn.inchain{1,i} = JLINE.from_jline_matrix(jsn.inchain.get(uint32(i-1)))+1;
3359 if ~isempty(jsn.visits)
3360 sn.
visits = cell(sn.nchains, 1);
3361 for i = 1:sn.nchains
3362 sn.
visits{i,1} = JLINE.from_jline_matrix(jsn.visits.get(uint32(i-1)));
3368 if ~isempty(jsn.nodevisits)
3370 for i = 1:sn.nchains
3371 sn.
nodevisits{1,i} = JLINE.from_jline_matrix(jsn.nodevisits.get(uint32(i-1)));
3377 if ~isempty(jsn.droprule)
3378 sn.droprule = zeros(sn.nstations, sn.nclasses);
3379 for i = 1:sn.nstations
3380 for j = 1:sn.nclasses
3381 dropStrategy = jsn.droprule.get(jstations.get(i-1)).get(jclasses.get(j-1));
3382 switch dropStrategy.name.toCharArray'
3384 sn.droprule(i,j) = DropStrategy.WAITQ;
3386 sn.droprule(i,j) = DropStrategy.DROP;
3387 case 'BlockingAfterService'
3388 sn.droprule(i,j) = DropStrategy.BAS;
3396 if ~isempty(jsn.nodeparam)
3397 sn.nodeparam = cell(sn.nnodes, 1);
3400 jnode = jnodes.get(i-1);
3401 jparam = jsn.nodeparam.get(jnode);
3404 % sn.nodeparam{i} = [];
3409 if isa(jparam,
'jline.lang.nodeparam.StationNodeParam')
3410 if ~isempty(jparam.fileName)
3411 sn.nodeparam{i}.fileName = cell(1, sn.nclasses);
3412 for r = 1:sn.nclasses
3413 fname = jparam.fileName.get(r-1);
3415 sn.nodeparam{i}.fileName{r} = char(fname);
3421 % TransitionNodeParam
3422 if isa(jparam,
'jline.lang.nodeparam.TransitionNodeParam')
3423 if ~isempty(jparam.firingprocid)
3424 sn.nodeparam{i}.firingprocid = containers.Map(
'KeyType',
'char',
'ValueType',
'any');
3425 keys = jparam.firingprocid.keySet.iterator;
3428 proc = jparam.firingprocid.get(key);
3429 sn.nodeparam{i}.firingprocid(
char(key.toString)) = char(proc.toString);
3432 if ~isempty(jparam.firingphases)
3433 sn.nodeparam{i}.firingphases = JLINE.from_jline_matrix(jparam.firingphases);
3435 if ~isempty(jparam.fireweight)
3436 sn.nodeparam{i}.fireweight = JLINE.from_jline_matrix(jparam.fireweight);
3441 if isa(jparam,
'jline.lang.nodeparam.JoinNodeParam')
3442 if ~isempty(jparam.joinStrategy)
3443 sn.nodeparam{i}.joinStrategy = cell(1, sn.nclasses);
3444 sn.nodeparam{i}.fanIn = cell(1, sn.nclasses);
3445 for r = 1:sn.nclasses
3446 jclass = jclasses.get(r-1);
3447 joinStrategy = jparam.joinStrategy.get(jclass);
3448 if ~isempty(joinStrategy)
3449 strategyStr = char(joinStrategy.name.toString);
3452 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.STD;
3454 sn.nodeparam{i}.joinStrategy{r} = JoinStrategy.PARTIAL;
3456 sn.nodeparam{i}.joinStrategy{r} = strategyStr;
3458 sn.nodeparam{i}.fanIn{r} = jparam.fanIn.get(jclass);
3465 if isa(jparam,
'jline.lang.nodeparam.RoutingNodeParam')
3466 for r = 1:sn.nclasses
3467 jclass = jclasses.get(r-1);
3469 if ~isempty(jparam.weights) && jparam.weights.containsKey(jclass)
3470 sn.nodeparam{i}.weights{r} = JLINE.from_jline_matrix(jparam.weights.get(jclass));
3473 if ~isempty(jparam.outlinks) && jparam.outlinks.containsKey(jclass)
3474 sn.nodeparam{i}.outlinks{r} = JLINE.from_jline_matrix(jparam.outlinks.get(jclass));
3480 if isa(jparam,
'jline.lang.nodeparam.ForkNodeParam')
3481 if ~isnan(jparam.fanOut)
3482 sn.nodeparam{i}.fanOut = jparam.fanOut;
3487 if isa(jparam,
'jline.lang.nodeparam.CacheNodeParam')
3489 if ~isnan(jparam.nitems)
3490 sn.nodeparam{i}.nitems = jparam.nitems;
3494 if ~isempty(jparam.accost)
3495 % For Java 2D arrays (Matrix[][]), size(arr,2) returns 1 in MATLAB
3496 % We need to get length of first row to get actual second dimension
3497 K1 = size(jparam.accost, 1);
3499 firstRow = jparam.accost(1); % Get first row (Java array)
3500 K2 = length(firstRow);
3504 sn.nodeparam{i}.accost = cell(K1, K2);
3507 mat = jparam.accost(k1, k2); % MATLAB handles Java array indexing
3509 sn.nodeparam{i}.accost{k1, k2} = JLINE.from_jline_matrix(mat);
3516 if ~isempty(jparam.itemcap)
3517 sn.nodeparam{i}.itemcap = JLINE.from_jline_matrix(jparam.itemcap);
3520 % pread - convert from Java Map<Integer, List<Double>> to MATLAB cell array {R}
3521 if ~isempty(jparam.pread)
3522 nclasses = sn.nclasses;
3523 sn.nodeparam{i}.pread = cell(1, nclasses);
3525 list = jparam.pread.get(int32(r-1)); % Java 0-based indexing
3527 values = zeros(1, list.size);
3529 values(j) = list.get(j-1);
3531 sn.nodeparam{i}.pread{r} = values;
3533 sn.nodeparam{i}.pread{r} = NaN;
3539 if ~isempty(jparam.replacestrat)
3540 switch
char(jparam.replacestrat)
3542 sn.nodeparam{i}.replacestrat = ReplacementStrategy.RR;
3544 sn.nodeparam{i}.replacestrat = ReplacementStrategy.FIFO;
3546 sn.nodeparam{i}.replacestrat = ReplacementStrategy.SFIFO;
3548 sn.nodeparam{i}.replacestrat = ReplacementStrategy.LRU;
3553 if ~isempty(jparam.hitclass)
3554 sn.nodeparam{i}.hitclass = 1+JLINE.from_jline_matrix(jparam.hitclass);
3558 if ~isempty(jparam.missclass)
3559 sn.nodeparam{i}.missclass =1+ JLINE.from_jline_matrix(jparam.missclass);
3562 % actual hit/miss probabilities
3563 if ~isempty(jparam.actualhitprob)
3564 sn.nodeparam{i}.actualhitprob = JLINE.from_jline_matrix(jparam.actualhitprob);
3566 if ~isempty(jparam.actualmissprob)
3567 sn.nodeparam{i}.actualmissprob = JLINE.from_jline_matrix(jparam.actualmissprob);
3575 if ~isempty(jsn.sync)
3577 sn.sync = cell(jsync.size, 1);
3578 for i = 1:jsync.size
3579 jsync_i = jsync.get(uint32(i-1));
3580 sn.sync{i,1} =
struct(
'active',cell(1),
'passive',cell(1));
3582 jactive = jsync_i.active.get(uint32(0));
3583 jpassive = jsync_i.passive.get(uint32(0));
3585 % Assumes prob
is a value, not a Java lambda function
3586 switch jactive.getEvent.name.toCharArray
'
3588 sn.sync{i,1}.active{1} = Event(EventType.INIT, jactive.getNode+1, jactive.getJobClass+1, ...
3589 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3590 jactive.getT, jactive.getJob);
3592 sn.sync{i,1}.active{1} = Event(EventType.LOCAL, jactive.getNode+1, jactive.getJobClass+1, ...
3593 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3594 jactive.getT, jactive.getJob);
3596 sn.sync{i,1}.active{1} = Event(EventType.ARV, jactive.getNode+1, jactive.getJobClass+1, ...
3597 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3598 jactive.getT, jactive.getJob);
3600 sn.sync{i,1}.active{1} = Event(EventType.DEP, jactive.getNode+1, jactive.getJobClass+1, ...
3601 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3602 jactive.getT, jactive.getJob);
3604 sn.sync{i,1}.active{1} = Event(EventType.PHASE, jactive.getNode+1, jactive.getJobClass+1, ...
3605 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3606 jactive.getT, jactive.getJob);
3608 sn.sync{i,1}.active{1} = Event(EventType.READ, jactive.getNode+1, jactive.getJobClass+1, ...
3609 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3610 jactive.getT, jactive.getJob);
3612 sn.sync{i,1}.active{1} = Event(EventType.STAGE, jactive.getNode+1, jactive.getJobClass+1, ...
3613 jactive.getProb, JLINE.from_jline_matrix(jactive.getState), ...
3614 jactive.getT, jactive.getJob);
3617 switch jpassive.getEvent.name.toCharArray'
3619 sn.sync{i,1}.passive{1} = Event(EventType.INIT, jpassive.getNode+1, jpassive.getJobClass+1, ...
3620 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3621 jpassive.getT, jpassive.getJob);
3623 sn.sync{i,1}.passive{1} = Event(EventType.LOCAL, jpassive.getNode+1, jpassive.getJobClass+1, ...
3624 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3625 jpassive.getT, jpassive.getJob);
3627 sn.sync{i,1}.passive{1} = Event(EventType.ARV, jpassive.getNode+1, jpassive.getJobClass+1, ...
3628 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3629 jpassive.getT, jpassive.getJob);
3631 sn.sync{i,1}.passive{1} = Event(EventType.DEP, jpassive.getNode+1, jpassive.getJobClass+1, ...
3632 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3633 jpassive.getT, jpassive.getJob);
3635 sn.sync{i,1}.passive{1} = Event(EventType.PHASE, jpassive.getNode+1, jpassive.getJobClass+1, ...
3636 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3637 jpassive.getT, jpassive.getJob);
3639 sn.sync{i,1}.passive{1} = Event(EventType.READ, jpassive.getNode+1, jpassive.getJobClass+1, ...
3640 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3641 jpassive.getT, jpassive.getJob);
3643 sn.sync{i,1}.passive{1} = Event(EventType.STAGE, jpassive.getNode+1, jpassive.getJobClass+1, ...
3644 jpassive.getProb, JLINE.from_jline_matrix(jpassive.getState), ...
3645 jpassive.getT, jpassive.getJob);
3653 function [QN,UN,RN,WN,AN,TN] = arrayListToResults(alist)
3655 case 'jline.solvers.LayeredNetworkAvgTable'
3656 QN = JLINE.arraylist_to_matrix(alist.getQLen());
3657 UN = JLINE.arraylist_to_matrix(alist.getUtil());
3658 RN = JLINE.arraylist_to_matrix(alist.getRespT());
3659 WN = JLINE.arraylist_to_matrix(alist.getResidT());
3660 AN = JLINE.arraylist_to_matrix(alist.getArvR());
3661 TN = JLINE.arraylist_to_matrix(alist.getTput());
3663 QN = JLINE.arraylist_to_matrix(alist.getQLen());
3664 UN = JLINE.arraylist_to_matrix(alist.getUtil());
3665 RN = JLINE.arraylist_to_matrix(alist.getRespT());
3666 WN = JLINE.arraylist_to_matrix(alist.getResidT());
3667 AN = JLINE.arraylist_to_matrix(alist.getArvR());
3668 TN = JLINE.arraylist_to_matrix(alist.getTput());
3672 function featSupported = getFeatureSet()
3673 % FEATSUPPORTED = GETFEATURESET()
3675 featSupported = SolverFeatureSet;
3676 featSupported.setTrue({
'Sink',
'Source',...
3677 'ClassSwitch',
'Delay',
'DelayStation',
'Queue',...
3678 'APH',
'Coxian',
'Erlang',
'Exp',
'HyperExp',...
3679 'StatelessClassSwitcher',
'InfiniteServer',
'SharedServer',
'Buffer',
'Dispatcher',...
3680 'Server',
'JobSink',
'RandomSource',
'ServiceTunnel',...
3681 'SchedStrategy_INF',
'SchedStrategy_PS',...
3682 'RoutingStrategy_PROB',
'RoutingStrategy_RAND',...
3683 'ClosedClass',
'OpenClass'});
3686 function [bool, featSupported] = supports(model)
3687 % [BOOL, FEATSUPPORTED] = SUPPORTS(MODEL)
3689 featUsed = model.getUsedLangFeatures();
3690 featSupported = JLINE.getFeatureSet();
3691 bool = SolverFeatureSet.supports(featSupported, featUsed);
3695 function solverOptions = parseSolverOptions(solverOptions, options)
3696 fn = fieldnames(options);
3697 fn2 = fieldnames(solverOptions);
3698 for f = 1:length(fn)
3700 for j = 1:length(fn2)
3701 if strcmp(fn{f}, fn2{j})
3705 solverOptions.seed = options.seed;
3707 solverOptions.samples = options.samples;
3709 % Parse confint - can be a level (0.95) or 0 to disable
3710 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
3712 solverOptions.confint = confintLevel;
3714 solverOptions.confint = 0;
3717 solverOptions.method = options.method;
3719 if isfield(options.config,
'eventcache')
3720 solverOptions.config.eventcache = options.config.eventcache;
3722 if isfield(options.config,'fork_join')
3723 solverOptions.config.fork_join = options.config.fork_join;
3725 if isfield(options.config,'highvar')
3726 solverOptions.config.highvar = options.config.highvar;
3728 if isfield(options.config,'multiserver')
3729 solverOptions.config.multiserver = options.config.multiserver;
3731 if isfield(options.config,'np_priority')
3732 solverOptions.config.np_priority = options.config.np_priority;
3734 if isfield(options.config,'warmupfrac') && ~isempty(options.config.warmupfrac) ...
3735 && options.config.warmupfrac > 0
3736 % SSA warmup discard (mean estimates + CI batch means)
3737 solverOptions.config.warmupfrac = java.lang.Double(options.config.warmupfrac);
3740 switch options.(fn{f})
3741 case {VerboseLevel.SILENT}
3742 solverOptions.verbose = solverOptions.verbose.SILENT;
3743 case {VerboseLevel.STD}
3744 solverOptions.verbose = solverOptions.verbose.STD;
3745 case {VerboseLevel.DEBUG}
3746 solverOptions.verbose = solverOptions.verbose.DEBUG;
3749 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.init_sol);
3751 if isscalar(options.cutoff)
3752 solverOptions.(fn{f}) = jline.util.matrix.Matrix.singleton(options.cutoff);
3754 solverOptions.(fn{f}) = JLINE.from_line_matrix(options.cutoff);
3757 case 'rewardIterations'
3758 solverOptions.rewardIterations = java.lang.Integer(options.rewardIterations);
3760 solverOptions.(fn{f}) = options.(fn{f});
3767 line_printf(
'Could not find option %s in the JLINE options.\n', fn{f});
3772 function [ssa] = SolverSSA(network_object, options)
3773 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.SSA);
3775 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3777 jline.util.Maths.setRandomNumbersMatlab(
true);
3778 ssa = jline.solvers.ssa.SolverSSA(network_object, solverOptions);
3781 function [qns] = SolverQNS(network_object, options)
3782 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.QNS);
3784 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3786 qns = jline.solvers.wrappers.qns.SolverQNS(network_object, solverOptions);
3789 function [mam] = SolverMAM(network_object, options)
3790 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MAM);
3792 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3794 mam = jline.solvers.mam.SolverMAM(network_object, solverOptions);
3797 function [jmt] = SolverJMT(network_object, options)
3798 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.JMT);
3800 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3802 jmt = jline.solvers.wrappers.jmt.SolverJMT(network_object, solverOptions);
3805 function [ctmc] = SolverCTMC(network_object, options)
3806 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.CTMC);
3808 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3810 ctmc = jline.solvers.ctmc.SolverCTMC(network_object,solverOptions);
3813 function [infGen, eventFilt, syncInfo, stateSpace, nodeStateSpace] = getSymbolicGenerator(ctmc, invertSymbol)
3814 % [INFGEN, EVENTFILT, SYNCINFO, STATESPACE, NODESTATESPACE] = GETSYMBOLICGENERATOR(CTMC, INVERTSYMBOL)
3815 % Symbolic infinitesimal generator of a JLINE SolverCTMC object, with
3816 % each
event filtration normalized by its minimum positive rate and
3817 % scaled by a symbolic variable x1..xE, as in the native
3818 % SolverCTMC.getSymbolicGenerator. Coefficient matrices are computed
3819 % by the JAR; symbolic objects are rebuilt with the Symbolic Toolbox.
3821 invertSymbol =
false;
3824 line_error(mfilename,'This method requires MATLAB''s Symbolic Toolbox.');
3826 res = ctmc.getSymbolicGenerator(invertSymbol);
3827 stateSpace = JLINE.from_jline_matrix(res.stateSpace);
3828 n = size(stateSpace,1);
3829 nEvents = res.eventFilt.size();
3830 infGen = sym(zeros(n));
3831 eventFilt = cell(1, nEvents);
3833 symName = res.symbols.get(e-1);
3834 if ~isempty(symName)
3835 Fe = JLINE.from_jline_matrix(res.eventFilt.get(e-1));
3837 eventFilt{e} = Fe / sym(
char(symName),
'real');
3839 eventFilt{e} = Fe * sym(
char(symName),
'real');
3841 infGen = infGen + eventFilt{e};
3844 infGen = ctmc_makeinfgen(infGen);
3845 syncInfo = res.syncInfo;
3846 nodeStateSpace = cell(1, res.nodeStateSpace.size());
3847 for i = 1:res.nodeStateSpace.size()
3848 nodeStateSpace{i} = JLINE.from_jline_matrix(res.nodeStateSpace.get(i-1));
3852 function [fluid] = SolverFluid(network_object, options)
3853 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.FLUID);
3855 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
3857 fluid = jline.solvers.fluid.SolverFluid(network_object, solverOptions);
3860 function [QN, UN, RN, TN, CN, XN, t, QNt, UNt, TNt, xvec] = runFluidAnalyzer(network, options)
3861 % RUNFLUIDANALYZER Run JLINE fluid analyzer and
return results
3863 % [QN, UN, RN, TN, CN, XN, T, QNT, UNT, TNT, XVEC] = JLINE.runFluidAnalyzer(NETWORK, OPTIONS)
3865 % Runs the JLINE fluid solver on the given network and converts
3866 % results back to MATLAB data structures.
3869 % network - LINE Network model
3870 % options - Solver options structure with fields:
3871 % .method - solver method
3872 % .stiff - use stiff ODE solver
3875 % QN, UN, RN, TN - Steady-state metrics [M x K]
3876 % CN, XN - System metrics [1 x K]
3877 % t - Time vector [Tmax x 1]
3878 % QNt, UNt, TNt - Transient metrics {M x K} cells
3879 % xvec - State vector structure
3881 jmodel = LINE2JLINE(network);
3882 jsolver = JLINE.SolverFluid(jmodel);
3883 import jline.solvers.fluid.*;
3885 jsolver.options.method = options.method;
3886 jsolver.options.stiff = options.stiff;
3887 result = jsolver.runMethodSpecificAnalyzerViaLINE();
3889 % Convert JLINE result to MATLAB data structures
3890 M = jmodel.getNumberOfStatefulNodes();
3891 K = jmodel.getNumberOfClasses();
3893 QN = NaN * zeros(M, K);
3894 UN = NaN * zeros(M, K);
3895 RN = NaN * zeros(M, K);
3896 TN = NaN * zeros(M, K);
3897 CN = NaN * zeros(1, K);
3898 XN = NaN * zeros(1, K);
3904 Tmax = result.t.length();
3905 t = NaN * zeros(Tmax, 1);
3909 QN(ist, jst) = result.QN.get(ist-1, jst-1);
3910 UN(ist, jst) = result.UN.get(ist-1, jst-1);
3911 RN(ist, jst) = result.RN.get(ist-1, jst-1);
3912 TN(ist, jst) = result.TN.get(ist-1, jst-1);
3917 CN(1, jst) = result.CN.get(0, jst-1);
3918 XN(1, jst) = result.XN.get(0, jst-1);
3924 QNt{ist, jst}(p, 1) = result.QNt(ist, jst).get(p-1, 0);
3925 UNt{ist, jst}(p, 1) = result.UNt(ist, jst).get(p-1, 0);
3926 TNt{ist, jst}(p, 1) = result.TNt(ist, jst).get(p-1, 0);
3932 t(p, 1) = result.t.get(p-1, 0);
3935 % JLINE does not
return odeStateVec
3936 xvec.odeStateVec = [];
3940 function [ldes] = SolverLDES(network_object, options)
3941 % Create LDES-specific options object
3942 ldesOptions = jline.solvers.ldes.LDESOptions();
3944 % Copy standard options
3945 ldesOptions.samples = options.samples;
3946 ldesOptions.seed = options.seed;
3947 % Java backend silenced at SILENT/STD to avoid duplicating the MATLAB summary lines -- see _kb/12-interfaces-and-docs.md
3948 if isfield(options, 'verbose')
3949 switch options.verbose
3950 case {VerboseLevel.DEBUG}
3951 ldesOptions.verbose = ldesOptions.verbose.DEBUG;
3953 ldesOptions.verbose = ldesOptions.verbose.SILENT;
3957 [confintEnabled, confintLevel] = Solver.parseConfInt(options.confint);
3959 ldesOptions.confint = confintLevel;
3961 ldesOptions.confint = 0;
3963 % Pass timespan
for transient analysis
3964 if isfield(options,
'timespan') && length(options.timespan) >= 2
3965 ldesOptions.timespan = options.timespan;
3967 % Warm-start initial placement (station-major vector, e.g. set
3968 % by @SolverLDES/initFromSolver from an auxiliary solver)
3969 if isfield(options, 'init_sol') && ~isempty(options.init_sol)
3970 ldesOptions.init_sol = JLINE.from_line_matrix(options.init_sol);
3972 % Pass LDES-specific options if configured
3973 if isfield(options, 'config')
3974 % Transient detection options
3975 if isfield(options.config, 'tranfilter')
3976 ldesOptions.tranfilter = options.config.tranfilter;
3978 if isfield(options.config,
'mserbatch')
3979 ldesOptions.mserbatch = options.config.mserbatch;
3981 if isfield(options.config, 'warmupfrac')
3982 ldesOptions.warmupfrac = options.config.warmupfrac;
3984 % Confidence interval options
3985 if isfield(options.config, 'cimethod')
3986 ldesOptions.cimethod = options.config.cimethod;
3988 if isfield(options.config, 'obmoverlap')
3989 ldesOptions.obmoverlap = options.config.obmoverlap;
3991 if isfield(options.config, 'ciminbatch')
3992 ldesOptions.ciminbatch = options.config.ciminbatch;
3994 if isfield(options.config, 'ciminobs')
3995 ldesOptions.ciminobs = options.config.ciminobs;
3997 if isfield(options.config, 'spectralLowFreqFrac')
3998 ldesOptions.spectralLowFreqFrac = options.config.spectralLowFreqFrac;
4000 % Convergence options
4001 if isfield(options.config, 'cnvgon')
4002 ldesOptions.cnvgon = options.config.cnvgon;
4004 if isfield(options.config, 'cnvgtol')
4005 ldesOptions.cnvgtol = options.config.cnvgtol;
4007 if isfield(options.config, 'cnvgbatch')
4008 ldesOptions.cnvgbatch = options.config.cnvgbatch;
4010 if isfield(options.config, 'cnvgchk')
4011 ldesOptions.cnvgchk = options.config.cnvgchk;
4015 ldes = jline.solvers.ldes.SolverLDES(network_object, ldesOptions);
4018 function [mva] = SolverMVA(network_object, options)
4019 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.MVA);
4021 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4023 mva = jline.solvers.mva.SolverMVA(network_object, solverOptions);
4026 function [nc] = SolverNC(network_object, options)
4027 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.NC);
4029 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4031 nc = jline.solvers.nc.SolverNC(network_object, solverOptions);
4034 function [auto] = SolverAuto(network_object, options)
4035 solverOptions = jline.solvers.auto.AUTOptions();
4037 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4039 auto = jline.solvers.auto.SolverAUTO(network_object, solverOptions);
4042 function streamOpts = StreamingOptions(varargin)
4043 % STREAMINGOPTIONS Create Java StreamingOptions for SSA/LDES stream() method
4045 % @brief Creates StreamingOptions for streaming simulation metrics
4047 % @param varargin Name-value pairs for options:
4048 % 'transport' - 'http' (recommended) or 'grpc' (default: 'http')
4049 % 'endpoint' - Receiver endpoint (default: 'localhost:8080/metrics' for HTTP)
4050 % 'mode' - 'sampled' or 'time_window' (default: 'sampled')
4051 % 'sampleFrequency' - Push every N events in sampled mode (default: 100)
4052 % 'timeWindowSeconds' - Window duration in time_window mode (default: 1.0)
4053 % 'serviceName' - Service identifier (default: 'line-stream')
4054 % 'includeQueueLength' - Include queue length metrics (default: true)
4055 % 'includeUtilization' - Include utilization metrics (default: true)
4056 % 'includeThroughput' - Include throughput metrics (default: true)
4057 % 'includeResponseTime' - Include response time metrics (default: true)
4058 % 'includeArrivalRate' - Include arrival rate metrics (default: true)
4060 % @return streamOpts Java StreamingOptions
object
4064 % streamOpts = JLINE.StreamingOptions('transport', 'http', 'sampleFrequency', 50);
4067 streamOpts = jline.streaming.StreamingOptions();
4069 % Parse optional arguments
4071 addParameter(p, 'transport', 'http', @ischar);
4072 addParameter(p, 'endpoint', '', @ischar); % Empty means use default for transport
4073 addParameter(p, 'mode', 'sampled', @ischar);
4074 addParameter(p, 'sampleFrequency', 100, @isnumeric);
4075 addParameter(p, 'timeWindowSeconds', 1.0, @isnumeric);
4076 addParameter(p, 'serviceName', 'line-stream', @ischar);
4077 addParameter(p, 'includeQueueLength', true, @islogical);
4078 addParameter(p, 'includeUtilization', true, @islogical);
4079 addParameter(p, 'includeThroughput', true, @islogical);
4080 addParameter(p, 'includeResponseTime', true, @islogical);
4081 addParameter(p, 'includeArrivalRate', true, @islogical);
4082 parse(p, varargin{:});
4084 % Set transport type
4085 transportTypes = javaMethod(
'values',
'jline.streaming.StreamingOptions$TransportType');
4086 switch lower(p.Results.transport)
4088 streamOpts.transport = transportTypes(1); % HTTP
4090 streamOpts.transport = transportTypes(2); % GRPC
4092 streamOpts.transport = transportTypes(1); % Default to HTTP
4095 % Set endpoint (use provided or default based on transport)
4096 if ~isempty(p.Results.endpoint)
4097 streamOpts.endpoint = p.Results.endpoint;
4099 % If empty, StreamingOptions uses its default for the transport type
4102 streamModes = javaMethod('values', 'jline.streaming.StreamingOptions$StreamMode');
4103 switch lower(p.Results.mode)
4105 streamOpts.mode = streamModes(1); % SAMPLED
4107 streamOpts.mode = streamModes(2); % TIME_WINDOW
4109 streamOpts.mode = streamModes(1); % Default to SAMPLED
4113 streamOpts.sampleFrequency = p.Results.sampleFrequency;
4114 streamOpts.timeWindowSeconds = p.Results.timeWindowSeconds;
4115 streamOpts.serviceName = p.Results.serviceName;
4116 streamOpts.includeQueueLength = p.Results.includeQueueLength;
4117 streamOpts.includeUtilization = p.Results.includeUtilization;
4118 streamOpts.includeThroughput = p.Results.includeThroughput;
4119 streamOpts.includeResponseTime = p.Results.includeResponseTime;
4120 streamOpts.includeArrivalRate = p.Results.includeArrivalRate;
4123 function result = convertSampleResult(jresult)
4124 % CONVERTSAMPLERESULT Convert Java sample result to MATLAB struct
4126 % @brief Converts Java SampleNodeState to MATLAB structure
4128 % @param jresult Java SampleNodeState
object
4129 % @return result MATLAB struct with fields: t, state, isaggregate
4133 % Convert time matrix
4134 if ~isempty(jresult.t)
4135 result.t = JLINE.from_jline_matrix(jresult.t);
4140 % Convert state matrix
4141 if ~isempty(jresult.state) && isa(jresult.state, 'jline.util.matrix.Matrix')
4142 result.state = JLINE.from_jline_matrix(jresult.state);
4147 result.isaggregate = jresult.isaggregate;
4150 function [ln] = SolverLN(layered_network_object, options)
4151 solverOptions = jline.solvers.SolverOptions(jline.lang.constant.SolverType.LN);
4153 solverOptions = JLINE.parseSolverOptions(solverOptions, options);
4155 ln = jline.solvers.ln.SolverLN(layered_network_object, solverOptions);
4158 function jfun = reward_handle_to_tabulatedfun(rewardFn, sn)
4159 % REWARD_HANDLE_TO_TABULATEDFUN Convert a MATLAB reward function
4160 % handle to a Java TabulatedRewardFunction by pre-computing its
4161 % value over an enumerable superset of the aggregated state space.
4163 % The domain per class r
is: all per-station count vectors with
4164 % sum <= njobs(r) for closed classes, and per-station counts capped
4165 % by classcap(i,r) (or the default CTMC cutoff of 100 when
4166 % infinite) for open classes. The JAR reward analyzer evaluates the
4167 % function only on reachable stateSpaceAggr rows, which are a
4168 % subset of this domain; unseen states raise a descriptive error.
4170 % @param rewardFn MATLAB reward handle @(state) or @(state, sn)
4171 % @param sn Network struct
4172 % @return jfun Java jline.lang.reward.TabulatedRewardFunction
4177 % Per-class families of feasible per-station count vectors, with a
4178 % guard against combinatorial explosion (as in the PAS precompute)
4179 classVecs = cell(1, K);
4182 if isfinite(sn.njobs(r)) && sn.njobs(r) > 0
4183 classVecs{r} = JLINE.reward_enum_capped(M, sn.njobs(r)*ones(1,M), sn.njobs(r));
4187 if sn.sched(i) == SchedStrategy.EXT
4188 % Source never holds jobs in the aggregated CTMC state -- see _kb/04-networkstruct.md
4192 c = sn.classcap(i,r);
4194 c = 100; %
default CTMC cutoff (see solver_ctmc_reward)
4198 classVecs{r} = JLINE.reward_enum_capped(M, caps, Inf);
4200 total = total * size(classVecs{r},1);
4202 line_error(mfilename,
'Reward pre-computation would enumerate more than 5e6 aggregated states; set finite class capacities (or smaller populations) for JLINE conversion.');
4206 % Index maps
for RewardState, as in solver_ctmc_reward
4207 nodeToStationMap = containers.Map(
'KeyType',
'int32',
'ValueType',
'int32');
4208 classToIndexMap = containers.Map(
'KeyType',
'int32',
'ValueType',
'int32');
4209 for ind = 1:sn.nnodes
4210 if sn.isstation(ind)
4211 nodeToStationMap(int32(ind)) = sn.nodeToStation(ind);
4215 classToIndexMap(int32(r)) = r;
4218 jfun = javaObject(
'jline.lang.reward.TabulatedRewardFunction');
4219 counts = zeros(1, K);
4221 counts(r) = size(classVecs{r}, 1);
4225 row = zeros(1, M*K);
4227 row(((1:M)-1)*K + r) = classVecs{r}(idx(r), :);
4229 rewardState = RewardState(row, sn, nodeToStationMap, classToIndexMap);
4230 % Try the
new single-argument API first, then the backward
4231 % compatible @(state, sn) signature (as in solver_ctmc_reward)
4233 val = rewardFn(rewardState);
4236 val = rewardFn(row, sn);
4241 jfun.addValue(JLINE.from_line_matrix(row),
double(val));
4242 % Advance the mixed-radix odometer over classes
4245 idx(r) = idx(r) + 1;
4246 if idx(r) <= counts(r)
4258 function V = reward_enum_capped(M, caps, budget)
4259 % REWARD_ENUM_CAPPED All integer row vectors v (1 x M) with
4260 % 0 <= v(i) <= caps(i) and sum(v) <= budget.
4262 hi = min(caps(1), budget);
4267 hi = min(caps(1), budget);
4269 Vsub = JLINE.reward_enum_capped(M-1, caps(2:end), budget - n);
4270 V = [V; [n*ones(size(Vsub,1),1), Vsub]]; %#ok<AGROW>
4274 function serfun = pas_handle_to_serializablefun(handle, nclasses, cap)
4275 % PAS_HANDLE_TO_SERIALIZABLEFUN Convert a PAS service rate function
4276 % mu(c) (MATLAB handle of the ordered class list) to a Java
4277 % SerializableFunction by pre-computing mu over every ordered prefix
4278 % up to the queue capacity.
4280 % The JAR queries mu(c) with the ordered prefix as a row vector of
4281 % 0-based class indices (jline.lang.state.AfterEventStation), and the
4282 % PrecomputedRateFunction keys on the stringified vector, so values
4283 % are stored under the matching 0-based key.
4285 % @param handle MATLAB mu(c) handle taking a 1-based ordered class list
4286 % @param nclasses Number of classes
4287 % @param cap Station capacity (max ordered-list length)
4288 % @return serfun Java PrecomputedCDFunction
4290 % Guard against combinatorial explosion of ordered sequences
4293 term = term * nclasses;
4297 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));
4300 serfun = jline.util.PrecomputedRateFunction(nclasses, 0.0);
4301 JLINE.pas_enumerate_seqs(handle, serfun, nclasses, cap, []);
4304 function pas_enumerate_seqs(handle, serfun, nclasses, cap, prefix)
4305 % PAS_ENUMERATE_SEQS Recursively enumerate ordered class sequences
4306 % (1-based, length 1..cap) and store mu(prefix) under the matching
4307 % 0-based key expected by the JAR.
4309 val = handle(prefix); % mu(c), 1-based ordered list
4310 keyMat = JLINE.from_line_matrix(prefix - 1); % 0-based key (1 x p)
4311 serfun.addValue(keyMat, double(val));
4313 if length(prefix) >= cap
4317 JLINE.pas_enumerate_seqs(handle, serfun, nclasses, cap, [prefix, r]);
4321 function serfun = handle_to_serializablefun(handle, sn)
4322 % HANDLE_TO_SERIALIZABLEFUN Convert MATLAB function handle to Java SerializableFunction
4324 % This function pre-computes the function values for all possible state
4325 % combinations and creates a Java PrecomputedCDFunction object.
4327 % @param handle MATLAB function handle that takes a vector ni and returns a scalar
4328 % @param sn Network struct containing njobs (population per class)
4329 % @return serfun Java PrecomputedCDFunction object
4331 % Get number of classes and maximum populations
4332 nclasses = sn.nclasses;
4333 njobs = sn.njobs; % Population per class
4335 % For open classes (njobs=0), use a reasonable bound
4338 if maxPop(r) == 0 || isinf(maxPop(r))
4339 % For open classes, use sum of closed class populations or 100 as bound
4340 maxPop(r) = max(100, sum(njobs(isfinite(njobs) & njobs > 0)));
4344 % Create Java PrecomputedCDFunction object
4345 serfun = jline.util.PrecomputedCDFunction(nclasses);
4347 % Enumerate all possible state combinations and pre-compute function values
4348 % Use recursive enumeration to handle arbitrary number of classes
4349 JLINE.enumerate_states(handle, serfun, maxPop, zeros(1, nclasses), 1);
4352 function enumerate_states(handle, serfun, maxPop, currentState, classIdx)
4353 % ENUMERATE_STATES Recursively enumerate all state combinations
4355 % @param handle MATLAB function handle
4356 % @param serfun Java PrecomputedCDFunction object to populate
4357 % @param maxPop Maximum population per class
4358 % @param currentState Current state being built
4359 % @param classIdx Current class index being enumerated
4361 nclasses = length(maxPop);
4363 if classIdx > nclasses
4364 % Complete state: errors NOT swallowed here (a lookup miss falls back to beta=1, i.e. unscaled)
4365 value = handle(currentState);
4366 % Convert to Java int array and add to serfun
4367 jstate = jline.util.matrix.Matrix(1, nclasses);
4369 jstate.set(0, r-1, currentState(r));
4372 % Chain-independent beta_i(n): one scaling shared by every
4373 % class, broadcast on the Java side.
4374 serfun.addValue(jstate, double(value));
4376 % Chain-specific beta_{i,r}(n): keep the per-class vector whole (double[] overload), not the scalar one
4377 serfun.addValue(jstate, double(value(:)'));
4382 % Enumerate all populations
for current
class
4383 for n = 0:maxPop(classIdx)
4384 currentState(classIdx) = n;
4385 JLINE.enumerate_states(handle, serfun, maxPop, currentState, classIdx + 1);
4389 function result = call_java_cdscaling(jfun, ni)
4390 % CALL_JAVA_CDSCALING Call a Java SerializableFunction
for class dependence
4392 % This function converts a MATLAB vector to a Java Matrix and calls
4393 % the Java function
's apply() method.
4395 % @param jfun Java SerializableFunction<Matrix, Double> object
4396 % @param ni MATLAB vector representing the state (jobs per class)
4397 % @return result The scaling factor returned by the Java function
4399 % Convert MATLAB vector to Java Matrix
4401 jmatrix = jline.util.matrix.Matrix(1, length(ni));
4402 for r = 1:length(ni)
4403 jmatrix.set(0, r-1, ni(r));
4406 jmatrix = jline.util.matrix.Matrix(length(ni), 1);
4407 for r = 1:length(ni)
4408 jmatrix.set(r-1, 0, ni(r));
4412 % Call the Java function and convert result to MATLAB double
4413 jresult = jfun.apply(jmatrix);
4414 result = double(jresult);
4417 function jSched = to_jline_sched_strategy(schedId)
4418 % Convert MATLAB SchedStrategy id to jline SchedStrategy enum
4420 case SchedStrategy.REF
4421 jSched = jline.lang.constant.SchedStrategy.REF;
4422 case SchedStrategy.INF
4423 jSched = jline.lang.constant.SchedStrategy.INF;
4424 case SchedStrategy.FCFS
4425 jSched = jline.lang.constant.SchedStrategy.FCFS;
4426 case SchedStrategy.LCFS
4427 jSched = jline.lang.constant.SchedStrategy.LCFS;
4428 case SchedStrategy.SIRO
4429 jSched = jline.lang.constant.SchedStrategy.SIRO;
4430 case SchedStrategy.SJF
4431 jSched = jline.lang.constant.SchedStrategy.SJF;
4432 case SchedStrategy.LJF
4433 jSched = jline.lang.constant.SchedStrategy.LJF;
4434 case SchedStrategy.PS
4435 jSched = jline.lang.constant.SchedStrategy.PS;
4436 case SchedStrategy.DPS
4437 jSched = jline.lang.constant.SchedStrategy.DPS;
4438 case SchedStrategy.GPS
4439 jSched = jline.lang.constant.SchedStrategy.GPS;
4440 case SchedStrategy.SEPT
4441 jSched = jline.lang.constant.SchedStrategy.SEPT;
4442 case SchedStrategy.LEPT
4443 jSched = jline.lang.constant.SchedStrategy.LEPT;
4444 case SchedStrategy.HOL
4445 % preserve HOL (exact M/G/1 priority in the JAR) rather than
4446 % collapsing to FCFSPRIO (egflin approximation)
4447 jSched = jline.lang.constant.SchedStrategy.HOL;
4448 case SchedStrategy.FCFSPRIO
4449 jSched = jline.lang.constant.SchedStrategy.FCFSPRIO;
4450 case SchedStrategy.FORK
4451 jSched = jline.lang.constant.SchedStrategy.FORK;
4452 case SchedStrategy.EXT
4453 jSched = jline.lang.constant.SchedStrategy.EXT;
4454 case SchedStrategy.LCFSPR
4455 jSched = jline.lang.constant.SchedStrategy.LCFSPR;
4456 case SchedStrategy.PSPRIO
4457 jSched = jline.lang.constant.SchedStrategy.PSPRIO;
4458 case SchedStrategy.DPSPRIO
4459 jSched = jline.lang.constant.SchedStrategy.DPSPRIO;
4460 case SchedStrategy.GPSPRIO
4461 jSched = jline.lang.constant.SchedStrategy.GPSPRIO;
4463 jSched = jline.lang.constant.SchedStrategy.FCFS;
4467 function tf = is_custom_handle(funCell, e, h, defaultStr)
4468 % IS_CUSTOM_HANDLE True if funCell{e,h} is a function handle that
4469 % differs from the given identity default (whitespace-insensitive
4470 % func2str comparison).
4472 if isempty(funCell) || size(funCell,1) < e || size(funCell,2) < h
4476 if isempty(fh) || ~isa(fh, 'function_handle
')
4479 tf = ~strcmp(regexprep(func2str(fh), '\s+', ''), defaultStr);
4482 function jwf = from_line_workflow(line_wf)
4483 % Convert a MATLAB Workflow to a JAR Workflow.
4484 jwf = javaObject(
'jline.lang.workflow.Workflow', java.lang.String(line_wf.getName()));
4485 acts = line_wf.activities;
4486 for a = 1:length(acts)
4488 actName = java.lang.String(act.name);
4489 if ~isempty(act.hostDemand) && isa(act.hostDemand,
'Distribution')
4490 jdist = JLINE.from_line_distribution(act.hostDemand);
4491 jwf.addActivity(actName, jdist);
4493 jwf.addActivity(actName, 1.0);
4496 precs = line_wf.precedences;
4497 for p = 1:length(precs)
4499 preActs = java.util.ArrayList();
4500 for k = 1:length(prec.preActs)
4501 preActs.add(java.lang.String(prec.preActs{k}));
4503 postActs = java.util.ArrayList();
4504 for k = 1:length(prec.postActs)
4505 postActs.add(java.lang.String(prec.postActs{k}));
4507 preTypeStr = java.lang.String(ActivityPrecedenceType.toText(prec.preType));
4508 postTypeStr = java.lang.String(ActivityPrecedenceType.toText(prec.postType));
4509 if ~isempty(prec.preParams)
4510 preParamsMat = JLINE.from_line_matrix(prec.preParams(:)');
4512 preParamsMat = javaObject('jline.util.matrix.Matrix', 0, 0);
4514 if ~isempty(prec.postParams)
4515 postParamsMat = JLINE.from_line_matrix(prec.postParams(:)');
4517 postParamsMat = javaObject('jline.util.matrix.Matrix', 0, 0);
4519 jprec = javaObject('jline.lang.layered.ActivityPrecedence', ...
4520 preActs, postActs, preTypeStr, postTypeStr, preParamsMat, postParamsMat);
4521 jwf.addPrecedence(jprec);
4525 function jenv = from_line_environment(line_env)
4526 % Convert a MATLAB Environment to a JAR Environment.
4527 E = height(line_env.envGraph.Nodes);
4528 jenv = javaObject('jline.lang.Environment', java.lang.String(line_env.getName()), int32(E));
4530 stageName =
char(line_env.envGraph.Nodes.Name{e});
4531 stageType = char(line_env.envGraph.Nodes.Type{e});
4532 stageModel = line_env.ensemble{e};
4533 jmodel = JLINE.from_line_network(stageModel);
4534 jenv.addStage(int32(e-1), java.lang.String(stageName), java.lang.String(stageType), jmodel);
4536 if ~isempty(line_env.env)
4537 [Erows, Ecols] = size(line_env.env);
4540 d = line_env.env{e,h};
4541 if isempty(d) || isa(d,
'Disabled')
4544 % Custom reset handles cannot marshal to JAR functional interfaces; error rather than drop silently
4545 if JLINE.is_custom_handle(line_env.resetFun, e, h, '@(q)q') ...
4546 || JLINE.is_custom_handle(line_env.resetEnvRatesFun, e, h, '@(originalDist,QExit,UExit,TExit)originalDist') ...
4547 || JLINE.is_custom_handle(line_env.resetStateFun, e, h, '@(pi)pi')
4548 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));
4550 jdist = JLINE.from_line_distribution(d);
4551 jenv.addTransition(int32(e-1), int32(h-1), jdist);