1function model = JSIM2LINE(filename,modelName)
2% MODEL = JSIM2LINE(FILENAME,MODELNAME)
4% Copyright (c) 2012-2026, Imperial College London
8Pref.Str2Num = 'always';
9xDoc = xml_read(filename,Pref);
16 [~,modelName] = fileparts(xDoc.ATTRIBUTE.name);
18model = Network(modelName);
21node_name = cellfun(@(x) x.name, {xDoc.node.ATTRIBUTE},
'UniformOutput',
false)
';
22orig_node_name = node_name;
23for i=1:length(node_name)
24 node_name{i}=strrep(node_name{i},'/
','_
');
25 node_name{i}=strrep(node_name{i},'\
','_
');
28xsection = {xDoc.node.section};
29strategy = cell(1,length(node_name));
32xsection_javaClass = {};
36% This is to create the cs elements last, unclear if it affects correctness
37% isStation = ones(1,length(node_name));
38% for i=1:length(node_name)
39% xsection_i{i} = {xsection{i}};
40% xsection_i{i} = xsection_i{i}{1}; % input, service, and output sections of node i
41% xsection_class{i} = {xsection_i{i}.ATTRIBUTE};
42% switch xsection_class{i}{1}.className % input section
44% xsection_i_type{i} = {xsection{i}.ATTRIBUTE};
45% switch xsection_i_type{i}{2}.className
46% case {'StatelessClassSwitcher
'}
52%for i=[find(isStation==1), find(isStation==0)]
53for i=1:length(node_name)
54 xsection_i{i} = {xsection{i}};
55 xsection_i{i} = xsection_i{i}{1}; % input, service, and output sections of node i
56 xsection_javaClass{i} = {xsection_i{i}.ATTRIBUTE};
57 switch xsection_javaClass{i}{1}.className % input section
59 node{i} = Sink(model, node_name{i});
62 node{i} = Source(model, node_name{i});
64 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
67 forkMap=find(cellfun(@any,strfind(cellfun(@class,model.nodes,'UniformOutput
',false),'Fork
')));
69 line_error(mfilename,'JSIM2LINE supports at most a single fork-join pair.
');
71 node{i} = Join(model, node_name{i}, node{forkMap});
72 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
74 switch xsection_javaClass{i}{3}.className
76 node{i} = Fork(model, node_name{i});
77 node{i}.setTasksPerLink(xsection_i{i}(3).parameter(1).value); %jobsPerLink
78 xrouting{i} = {xsection_i{i}(3).parameter(4).subParameter.ATTRIBUTE};
80 switch xsection_javaClass{i}{2}.className
82 node{i} = Router(model, node_name{i});
83 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
85 xsection_par{i} = {xsection{i}.parameter};
86 xsection_i_par{i} = xsection_i{i}.parameter;
88 xsection_i_value{i} = {xsection_i_par{i}.value};
89 xsection_i_par_attr{i} = {xsection_i_par{i}.ATTRIBUTE};
91 xsection_i_subpar{i} = {xsection_i_par{i}.subParameter};
92 %if xsection_i_value{i}{1}==-1
93 % node{i} = Router(model, node_name{i});
96 xsvc{i} = {xsection_i{i}(2).parameter.subParameter};
97 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
99 % xget_strategy{i} = {xsection_i_par{i}.ATTRIBUTE};
100 % switch xget_strategy{i}{3}.name
101 % case 'LCFSstrategy
'
102 % strategy{i} = SchedStrategy.LCFS;
103 % case 'FCFSstrategy
'
104 % strategy{i} = SchedStrategy.FCFS;
107 xput_strategy{i} = xsection_i_par{i};
108 switch xput_strategy{i}(3).ATTRIBUTE.name
109 case 'retrialDistributions
'
110 % new XML format from 1.2.0
111 %xretrial_strategy{i}= {xput_strategy{i}(4)};
112 xput_strategy{i}= {xput_strategy{i}(5).subParameter.ATTRIBUTE};
114 xput_strategy{i}= {xput_strategy{i}(4).subParameter.ATTRIBUTE};
116 switch xput_strategy{i}{1}.name
118 strategy{i} = SchedStrategy.FCFS;
119 case 'TailStrategyPriority
'
120 strategy{i} = SchedStrategy.HOL;
122 strategy{i} = SchedStrategy.LCFS;
124 strategy{i} = SchedStrategy.SIRO;
126 strategy{i} = SchedStrategy.SJF;
128 strategy{i} = SchedStrategy.SEPT;
130 strategy{i} = SchedStrategy.LJF;
132 strategy{i} = SchedStrategy.LEPT;
135 xsection_i_type{i} = {xsection{i}.ATTRIBUTE};
136 switch xsection_i_type{i}{2}.className
138 node{i} = Delay(model, node_name{i});
139 xcapacity = {xsection_i_par{i}.value};
140 node{i}.setCapacity(xcapacity{1}); % buffer size
142 node{i} = Queue(model, node_name{i}, strategy{i});
143 xcapacity = {xsection_i_par{i}.value};
144 node{i}.setCapacity(xcapacity{1}); % buffer size
145 xsection_par_val{i} = {xsection_par{end}{2}.value};
146 node{i}.setNumServers(xsection_par_val{i}{1});
147 switch SchedStrategy.toId(strategy{i})
148 case SchedStrategy.SEPT
149 schedparams{i} = NaN;
151 case 'PSServer
' % requires JMT >= 1.0.2
152 strategy_i_sub={xsection_par{i}{2}.subParameter};
153 strategy_i_sub4=strategy_i_sub{4}; strategy_i_sub4={strategy_i_sub4.ATTRIBUTE};
154 strategy_i_sub5=strategy_i_sub{5};
155 schedparams{i} = cell2mat({strategy_i_sub5.value});
156 r=1; % we assume the strategies are identical across classes
157 switch strategy_i_sub4{r}.name
159 strategy{i} = SchedStrategy.PS;
161 strategy{i} = SchedStrategy.DPS;
163 strategy{i} = SchedStrategy.GPS;
164 case 'EPSStrategyPriority
'
165 strategy{i} = SchedStrategy.PSPRIO;
166 case 'DPSStrategyPriority
'
167 strategy{i} = SchedStrategy.DPSPRIO;
168 case 'GPSStrategyPriority
'
169 strategy{i} = SchedStrategy.GPSPRIO;
171 node{i} = Queue(model, node_name{i}, strategy{i});
172 xcapacity = {xsection_i_par{i}.value};
173 node{i}.setCapacity(xcapacity{1}); % buffer size
174 xsection_par_val{i} = {xsection_par{end}{2}.value};
175 node{i}.setNumServers(xsection_par_val{i}{1});
177 strategy_i_sub={xsection_par{i}{2}.subParameter};
178 strategy_i_sub1=strategy_i_sub{1}; strategy_i_sub1={strategy_i_sub1.subParameter};
179 csMatrix = zeros(length(strategy_i_sub1));
180 for r=1:length(strategy_i_sub1)
181 csMatrix(r,:) = cell2mat({strategy_i_sub1{r}.value});
183 node{i} = ClassSwitch(model, node_name{i}, csMatrix);
188 node{i} = Place(model, node_name{i});
190 node{i} = Transition(model, node_name{i});
195classes = {xDoc.userClass.ATTRIBUTE};
196% JMT uses higher priority value = higher priority, LINE uses lower value = higher priority
197% We need to invert priorities when importing from JMT
199for r=1:length(classes)
200 if classes{r}.priority > maxPrio
201 maxPrio = classes{r}.priority;
204for r=1:length(classes)
205 ref = findstring(node_name,classes{r}.referenceSource);
206 % Invert priority: JMT uses higher=higher, LINE uses lower=higher
207 linePrio = maxPrio - classes{r}.priority;
208 switch classes{r}.type
209 case JobClassType.toText(JobClassType.CLOSED)
210 jobclass{r} = ClosedClass(model, classes{r}.name, classes{r}.customers, node{ref}, linePrio);
211 case JobClassType.toText(JobClassType.OPEN)
212 % sink and source have been created before
213 jobclass{r} = OpenClass(model, classes{r}.name, linePrio);
214 if strcmpi(classes{r}.referenceSource,'StatelessClassSwitcher
')
215 sourceIdx = cellisa(node,'Source
');
216 node{sourceIdx}.setArrival(jobclass{r},Disabled.getInstance());
222for i=1:length(node_name)
223 xsection_i{i} = {xsection{i}};
224 xsection_i{i} = xsection_i{i}{1}; % input, service, and output sections of node i
225 xsection_javaClass{i} = {xsection_i{i}.ATTRIBUTE};
226 switch xsection_javaClass{i}{1}.className % input section
230 if xsection_i{1,i}(1).parameter(1).value == -1
231 node{i}.setCapacity(Inf);
233 node{i}.setCapacity(xsection_i{1,i}(1).parameter(1).value);
235 if isa(xsection_i{1, i}(1).parameter(2).refClass,'cell
')
236 nclasses = length(xsection_i{1, i}(1).parameter(2).refClass);
241 if xsection_i{1, i}(1).parameter(2).subParameter(c).value == -1
242 node{i}.setClassCapacity(c, Inf);
244 node{i}.setClassCapacity(c, xsection_i{1, i}(1).parameter(2).subParameter(c).value);
246 switch xsection_i{1, i}(1).parameter(3).subParameter(c).value
248 node{i}.setDropRule(c, DropStrategy.BAS);
250 node{i}.setDropRule(c, DropStrategy.DROP);
252 node{i}.setDropRule(c, DropStrategy.WAITQ);
259 nmodes = length(xsection_i{1, i}(1).parameter(1).subParameter);
261 node{i}.setModeNames(m, xsection_i{1, i}(2).parameter(1).subParameter(m).value);
265 ninputs = length(xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter);
267 refClasses = xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).refClass;
268 if isa(refClasses,'cell
')
269 nclasses = length(refClasses);
273 nodeName = xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(1).value;
274 targetNode = model.getNodeByName(nodeName);
276 enable = xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).subParameter(k).value;
278 node{i}.setEnablingConditions(m,k,targetNode,Inf);
280 node{i}.setEnablingConditions(m,k,targetNode,enable);
282 inhibit = xsection_i{1, i}(1).parameter(2).subParameter(m).subParameter.subParameter(j).subParameter(2).subParameter(k).value;
283 if inhibit == -1 || inhibit == 0
284 % JMT encodes "no inhibitor arc" as 0 (see the
285 % Inf->0 mapping in saveInhibitingConditions.m); a
286 % threshold of 0 would otherwise inhibit at >=0
287 % tokens, i.e. always, deadlocking the transition.
288 node{i}.setInhibitingConditions(m,k,targetNode,Inf);
290 node{i}.setInhibitingConditions(m,k,targetNode,inhibit);
297 numOfServers = xsection_i{1, i}(2).parameter(2).subParameter(m).value;
298 if numOfServers == -1
299 node{i}.setNumberOfServers(m, Inf);
301 node{i}.setNumberOfServers(m, numOfServers);
303 timingSt = xsection_i{1, i}(2).parameter(3).subParameter(m).ATTRIBUTE.classPath;
304 if strcmp(timingSt,'jmt.engine.NetStrategies.ServiceStrategies.ZeroServiceTimeStrategy
')
305 node{i}.setTimingStrategy(m,TimingStrategy.IMMEDIATE);
307 node{i}.setTimingStrategy(m,TimingStrategy.TIMED);
308 distribution = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(1).ATTRIBUTE.name;
309 lambda = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(1).value;
312 node{i}.setDistribution(m,Exp(lambda));
314 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
315 node{i}.setDistribution(m,Erlang(lambda, lambda1));
316 case 'Hyperexponential
'
317 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
318 lambda2 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(3).value;
319 node{i}.setDistribution(m,HyperExp(lambda, lambda1, lambda2));
321 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
322 lambda2 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(3).value;
323 node{i}.setDistribution(m,Coxian([lambda, lambda1], [lambda2,1]));
325 node{i}.setDistribution(m,Det(lambda));
327 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
328 node{i}.setDistribution(m,Pareto(lambda, lambda1));
330 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
331 node{i}.setDistribution(m,Gamma(lambda, lambda1));
333 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
334 node{i}.setDistribution(m,Uniform(lambda, lambda1));
336 node{i}.setDistribution(m,Replayer(lambda));
338 node{i}.setDistribution(m,Trace(lambda));
340 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
341 node{i}.setDistribution(m,Weibull(lambda1, lambda)); % scale and shape are inverted in the constructor
343 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
344 node{i}.setDistribution(m,Lognormal(lambda, lambda1));
346 error('The model includes an arrival distribution not supported by
the model-to-model transformation from JMT.
')
349 firingPriorities = xsection_i{1, i}(2).parameter(4).subParameter(m).value;
350 node{i}.setFiringPriorities(m, firingPriorities);
351 firingWeights = xsection_i{1, i}(2).parameter(5).subParameter(m).value;
352 node{i}.setFiringWeights(m, firingWeights);
356 if isfield(xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter,'CONTENT
')
359 noutputs = length(xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter);
362 refClasses = xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).refClass;
363 if isa(refClasses, 'cell
')
364 nclasses = length(refClasses);
368 nodeName = xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(1).value;
370 outcome = xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).subParameter(k).value;
372 node{i}.setFiringOutcome(m,k,nodeName,Inf);
374 node{i}.setFiringOutcome(m,k,nodeName,outcome);
382schedparams = cell(1,length(node_name));
383% set service distributions
384for i=1:length(node_name)
385 if isa(node{i},'Source
')
386 for r=1:length(classes)
387 xsection_par{i} = {xsection{i}.parameter};
388 xsection_i_par{i} = xsection_i{i}.parameter;
389 xsection_i_subpar{i} = {xsection_i_par{i}.subParameter};
390 xarv_statdistrib{i}{r}={xsection_i_subpar{i}{1}.subParameter};
391 if isempty(xarv_statdistrib{i}{r}{r})
392 node{i}.setArrival(jobclass{r}, Disabled.getInstance());
394 xarv_statdistrib{i}{r}={xarv_statdistrib{i}{r}{r}.ATTRIBUTE};
395 xarv{i} = {xsection_i{i}(1).parameter.subParameter};
396 xarv_sec{i} = {xarv{i}{1}.subParameter};
397 switch xarv_statdistrib{i}{r}{1}.name
399 par={xarv_sec{i}{r}.subParameter}; par=par{2};
400 node{i}.setArrival(jobclass{r}, Exp(par.value));
402 par={xarv_sec{i}{r}.subParameter}; par=par{2};
403 node{i}.setArrival(jobclass{r}, Erlang(par(1).value,par(2).value));
404 case 'Hyperexponential
'
405 par={xarv_sec{i}{r}.subParameter}; par=par{2};
406 node{i}.setArrival(jobclass{r}, HyperExp(par(1).value,par(2).value,par(3).value));
408 par={xarv_sec{i}{r}.subParameter}; par=par{2};
409 node{i}.setArrival(jobclass{r}, Coxian([par(1).value,par(2).value],[par(3).value,1]));
411 par={xarv_sec{i}{r}.subParameter}; par=par{2};
412 node{i}.setArrival(jobclass{r}, Det(par.value));
414 par={xarv_sec{i}{r}.subParameter}; par=par{2};
415 node{i}.setArrival(jobclass{r}, Pareto(par(1).value, par(2).value));
417 par={xarv_sec{i}{r}.subParameter}; par=par{2};
418 node{i}.setArrival(jobclass{r}, Weibull(par(1).value, par(2).value));
420 par={xarv_sec{i}{r}.subParameter}; par=par{2};
421 node{i}.setArrival(jobclass{r}, Lognormal(par(1).value, par(2).value));
423 par={xarv_sec{i}{r}.subParameter}; par=par{2};
424 node{i}.setArrival(jobclass{r}, Gamma(par(1).value, par(2).value));
426 par={xarv_sec{i}{r}.subParameter}; par=par{2};
427 node{i}.setArrival(jobclass{r}, Uniform(par(1).value, par(2).value));
429 par={xarv_sec{i}{r}.subParameter}; par=par{2};
430 node{i}.setArrival(jobclass{r}, Replayer(par.value));
432 par={xarv_sec{i}{r}.subParameter}; par=par{2};
433 node{i}.setArrival(jobclass{r}, Trace(par.value));
435 par={xarv_sec{i}{r}.subParameter}; par=par{2};
436 node{i}.setArrival(jobclass{r}, MMPP2(par(1).value,par(2).value,par(3).value,par(4).value));
438 par={xarv_sec{i}{r}.subParameter}; par=par{2};
439 pars = {par(1).subParameter.subParameter};
442 D0 = [D0; pars{c}.value];
444 pars = {par(2).subParameter.subParameter};
447 D1 = [D1; pars{c}.value];
450 node{i}.setArrival(jobclass{r}, ax);
452 par={xarv_sec{i}{r}.subParameter}; par=par{2};
453 alpha = [par(1).subParameter.subParameter.value];
454 pars = {par(2).subParameter.subParameter};
457 T = [T; pars{c}.value];
459 if any(any(tril(T,-1))>0) % not APH, use general PH
464 node{i}.setArrival(jobclass{r}, ax);
466 line_warning(mfilename,'The model includes an arrival distribution (%s) not directly supported by
the model-to-model transformation from JMT. Attempting APH moment-matching.
', xarv_statdistrib{i}{r}{1}.name);
468 par={xarv_sec{i}{r}.subParameter}; par=par{2};
469 mean_val = 1/par(1).value; % JMT stores rate (lambda) as first parameter
471 scv_val = par(2).value^2; % JMT stores c (CoV) as second parameter
472 node{i}.setArrival(jobclass{r}, APH.fit(mean_val, scv_val));
474 node{i}.setArrival(jobclass{r}, Exp(par(1).value));
477 line_warning(mfilename,'APH moment-matching failed
for arrival distribution %s: %s. Using Exp(1) as fallback.', xarv_statdistrib{i}{r}{1}.name, me.message);
478 node{i}.setArrival(
jobclass{r}, Exp(1));
483 elseif isa(node{i},
'Queue') || isa(node{i},
'Delay') || isa(node{i},
'DelayStation')
484 if isempty(schedparams{i})
485 switch SchedStrategy.toId(strategy{i})
486 case {SchedStrategy.SEPT,SchedStrategy.LEPT}
487 schedparams{i} = NaN*ones(1,length(classes));
489 schedparams{i} = ones(1,length(classes));
492 for r=1:length(classes)
493 switch xsection_i_type{i}{2}.className
494 case 'StatelessClassSwitcher'
498 xsvc_sec{i} = {xsvc{i}{1}.subParameter};
500 xsvc_sec{i} = {xsvc{i}{3}.subParameter};
502 if isempty(xsvc_sec{i}{r})
503 xsvc_statdistrib{i}{r}={
struct(
'name',
'Disabled')};
505 xsvc_statdistrib{i}{r}={xsvc_sec{i}{r}.ATTRIBUTE};
507 para_ir = schedparams{i}(r);
508 switch xsvc_statdistrib{i}{r}{1}.name
510 node{i}.setService(
jobclass{r}, Disabled.getInstance());
512 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
513 node{i}.setService(
jobclass{r}, Replayer(par.value), para_ir);
515 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
516 node{i}.setService(
jobclass{r}, Trace(par.value), para_ir);
518 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
519 node{i}.setService(
jobclass{r}, Exp(par.value), para_ir);
521 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
522 node{i}.setService(
jobclass{r}, Erlang(par(1).value,par(2).value), para_ir);
523 case 'Hyperexponential'
524 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
525 node{i}.setService(
jobclass{r}, HyperExp(par(1).value,par(2).value,par(3).value), para_ir);
527 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
528 node{i}.setService(
jobclass{r}, Coxian([par(1).value,par(2).value],[par(3).value,1]), para_ir);
530 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
531 node{i}.setService(
jobclass{r}, Det(par.value));
533 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
534 node{i}.setService(
jobclass{r}, Pareto(par(1).value, par(2).value));
536 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
537 node{i}.setService(
jobclass{r}, Weibull(par(1).value, par(2).value));
539 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
540 node{i}.setService(
jobclass{r}, Lognormal(par(1).value, par(2).value));
542 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
543 node{i}.setService(
jobclass{r}, Gamma(par(1).value, par(2).value));
545 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
546 node{i}.setService(
jobclass{r}, MMPP2(par(1).value,par(2).value,par(3).value,par(4).value));
548 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
549 pars = {par(1).subParameter.subParameter};
552 D0 = [D0; pars{c}.value];
554 pars = {par(2).subParameter.subParameter};
557 D1 = [D1; pars{c}.value];
560 node{i}.setService(
jobclass{r}, ax);
562 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
563 alpha = [par(1).subParameter.subParameter.value];
564 pars = {par(2).subParameter.subParameter};
567 T = [T; pars{c}.value];
569 if any(any(tril(T,-1))>0) % not APH, use general PH
574 node{i}.setService(
jobclass{r}, ax);
576 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
577 node{i}.setService(
jobclass{r}, Uniform(par(1).value, par(2).value));
579 line_warning(mfilename,
'The model includes a service distribution (%s) not directly supported by the model-to-model transformation from JMT. Attempting APH moment-matching.', xsvc_statdistrib{i}{r}{1}.name);
581 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
582 mean_val = 1/par(1).value; % JMT stores rate (lambda) as first parameter
584 scv_val = par(2).value^2; % JMT stores c (CoV) as second parameter
585 node{i}.setService(
jobclass{r}, APH.fit(mean_val, scv_val), para_ir);
587 node{i}.setService(
jobclass{r}, Exp(par(1).value), para_ir);
590 line_warning(mfilename,
'APH moment-matching failed for service distribution %s: %s. Using Exp(1) as fallback.', xsvc_statdistrib{i}{r}{1}.name, me.message);
591 node{i}.setService(
jobclass{r}, Exp(1), para_ir);
595 for c=1:length(xsection_i_par_attr{i})
596 switch xsection_i_par_attr{i}{c}.name
598 node{i}.input.setSize(xsection_i_value{i}{c}); % buffer size
605C = zeros(length(node_name)); % connection matrix
606links = {xDoc.connection.ATTRIBUTE};
608 source = findstring(orig_node_name,links{l}.source);
609 target = findstring(orig_node_name,links{l}.target);
610 % model.addLink(station{source},station{target});
611 C(source,target) = 1;
614% assign routing probabilities
615P = zeros(length(node_name)*length(classes));
616for from=1:length(node_name)
617 for target=1:length(node_name)
619 model.addLink(node{from},node{target});
624for from=1:length(node_name)
625 switch class(node{from})
630 for r=1:length(classes)
631 switch xrouting{from}{r}.name
633 node{from}.setRouting(
jobclass{r},RoutingStrategy.RAND);
634 % targets = find(C(from,:));
636 % targets = setdiff(targets, [sink_idx, source_idx]);
638 %
for target = targets(:)
'
639 % % node{from}.setProbRouting(jobclass{r}, node{target}, 1 / length(targets));
640 % P((from-1)*length(classes)+r, (target-1)*length(classes)+r) = 1 / length(targets);
643 node{from}.setRouting(jobclass{r},RoutingStrategy.PROB);
644 xroutprobarray = {xsection_i{from}(3).parameter.subParameter.subParameter};
645 xroutprob = {xroutprobarray{r}.subParameter}; xroutprob = xroutprob{1};
646 xroutprobdest = {xroutprob.subParameter};
647 for j=1:length(xroutprobdest)
648 xprob={xroutprobdest{j}.value};
649 target = findstring(node_name,xprob{1});
651 node{from}.setProbRouting(jobclass{r}, node{target}, prob);
652 % P((from-1)*length(classes)+r, (target-1)*length(classes)+r) = prob;
655 % Both parameters are read by NAME off class r's own
656 % strategy node. The exporter (JMTIO.saveRoutingStrategy)
657 % writes two children per class, <k> then <withMemory>,
658 % so flattening parameter.subParameter.subParameter and
659 % indexing it by r conflates
the child position with
the
660 % class index and can never reach withMemory.
661 k = 2; % JMT
default when <k>
is absent
662 withMemory =
false; % JMT
default when <withMemory>
is absent
663 xstrat = xsection_i{from}(3).parameter.subParameter(r);
664 if isfield(xstrat,
'subParameter')
665 xpars = xstrat.subParameter;
666 for pj = 1:numel(xpars)
667 if ~isfield(xpars(pj),'ATTRIBUTE') || ~isfield(xpars(pj),'value')
670 switch xpars(pj).ATTRIBUTE.name
677 % A LINE-written file parses as logical,
678 % a hand-written or older JMT one as
the
679 % text 'true'/'false'.
680 wm = xpars(pj).value;
682 withMemory = strcmpi(strtrim(wm),'true');
684 withMemory = logical(wm);
689 node{from}.setRouting(
jobclass{r}, RoutingStrategy.KCHOICES, k, withMemory);
691 node{from}.setRouting(
jobclass{r},RoutingStrategy.RROBIN);
692 case 'Weighted Round Robin'
693 node{from}.setRouting(
jobclass{r},RoutingStrategy.WRROBIN);
694 xroutprobarray = {xsection_i{from}(3).parameter.subParameter.subParameter};
695 xroutprob = {xroutprobarray{r}.subParameter}; xroutprob = xroutprob{1};
696 xroutprobdest = {xroutprob.subParameter};
697 for j=1:length(xroutprobdest)
698 xprob={xroutprobdest{j}.value};
699 target = findstring(node_name,xprob{1});
701 node{from}.setRouting(RoutingStrategy.WRROBIN, node{target},
jobclass{r}, weight);
703 case 'Join the Shortest Queue (JSQ)'
704 node{from}.setRouting(
jobclass{r},RoutingStrategy.JSQ);
706 node{from}.setRouting(
jobclass{r},RoutingStrategy.DISABLED);
712%line_printf([
'JMT2LINE parsing time: ',num2str(Ttot),
' s\n']);
714if length(model.getIndexSourceStation)>1
715 txt = sprintf(
'LINE supports JMT models with at most a single source node. You can refactor your JMT model in several ways:\n - If you are mapping in JMT each class to a different source, this is not required. You can instead assign the same reference station to each class and configure class routing in the routing panel of the source node.\n - In more general cases, you may follow these three steps:\n (1) give a different name to each class of arrival, assigning these classes to a single source as reference station.\n (2) put a class-switch node after the source to switch the new classes into the original classes they were in the model with multiple sources.\n (3) configure the routing section of this class-switch node to set the same routing for the classes as they were in the original model.\n');
721state = zeros(length(node),length(classes));
722if isfield(xDoc,
'preload') && ~isempty(xDoc.preload.stationPopulations)
723 npreloadStates = length(xDoc.preload.stationPopulations);
724 for st=1:npreloadStates
725 nodeName = xDoc.preload.stationPopulations(st).ATTRIBUTE.stationName;
726 ind = model.getNodeIndex(nodeName);
727 for r=1:length(xDoc.preload.stationPopulations(st).classPopulation)
728 c = model.getClassIndex(xDoc.preload.stationPopulations(st).classPopulation(r).ATTRIBUTE.refClass);
729 state(ind,c) = xDoc.preload.stationPopulations(st).classPopulation(r).ATTRIBUTE.population;
731 if isa(node{ind},
'Place')
732 %node{ind}.setState(state(ind,:));
734 line_error(mfilename,
'Import failed: Colored Petri net models are not yet supported in LINE.\n');
740 model.initFromMarginal(state);
742 line_warning(mfilename,
'Import failed to automatically initialize the model.\n');