LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
JSIM2LINE.m
1function model = JSIM2LINE(filename,modelName)
2% MODEL = JSIM2LINE(FILENAME,MODELNAME)
3
4% Copyright (c) 2012-2026, Imperial College London
5% All rights reserved.
6T0=tic;
7% import model
8Pref.Str2Num = 'always';
9xDoc = xml_read(filename,Pref);
10try
11 xDoc = xDoc.sim;
12end
13
14% create network
15if nargin<2
16 [~,modelName] = fileparts(xDoc.ATTRIBUTE.name);
17end
18model = Network(modelName);
19
20% create stations
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},'\','_');
26end
27
28xsection = {xDoc.node.section};
29strategy = cell(1,length(node_name));
30xsection_par = {};
31xsection_i = {};
32xsection_javaClass = {};
33sink_idx = -1;
34source_idx = -1;
35
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
43% case {'Buffer'}
44% xsection_i_type{i} = {xsection{i}.ATTRIBUTE};
45% switch xsection_i_type{i}{2}.className
46% case {'StatelessClassSwitcher'}
47% isStation(i) = 0;
48% end
49% end
50% end
51
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
58 case 'JobSink'
59 node{i} = Sink(model, node_name{i});
60 sink_idx = i;
61 case 'RandomSource'
62 node{i} = Source(model, node_name{i});
63 source_idx = i;
64 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
65 nSources=1;
66 case 'Join'
67 forkMap=find(cellfun(@any,strfind(cellfun(@class,model.nodes,'UniformOutput',false),'Fork')));
68 if length(forkMap)>1
69 line_error(mfilename,'JSIM2LINE supports at most a single fork-join pair.');
70 end
71 node{i} = Join(model, node_name{i}, node{forkMap});
72 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
73 case 'Queue'
74 switch xsection_javaClass{i}{3}.className
75 case 'Fork'
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};
79 otherwise
80 switch xsection_javaClass{i}{2}.className
81 case 'ServiceTunnel'
82 node{i} = Router(model, node_name{i});
83 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
84 otherwise
85 xsection_par{i} = {xsection{i}.parameter};
86 xsection_i_par{i} = xsection_i{i}.parameter;
87
88 xsection_i_value{i} = {xsection_i_par{i}.value};
89 xsection_i_par_attr{i} = {xsection_i_par{i}.ATTRIBUTE};
90
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});
94 %else
95
96 xsvc{i} = {xsection_i{i}(2).parameter.subParameter};
97 xrouting{i} = {xsection_i{i}(3).parameter.subParameter.ATTRIBUTE};
98
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;
105 % end
106
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};
113 otherwise
114 xput_strategy{i}= {xput_strategy{i}(4).subParameter.ATTRIBUTE};
115 end
116 switch xput_strategy{i}{1}.name
117 case 'TailStrategy'
118 strategy{i} = SchedStrategy.FCFS;
119 case 'TailStrategyPriority'
120 strategy{i} = SchedStrategy.HOL;
121 case 'HeadStrategy'
122 strategy{i} = SchedStrategy.LCFS;
123 case 'RandStrategy'
124 strategy{i} = SchedStrategy.SIRO;
125 case 'SJFStrategy'
126 strategy{i} = SchedStrategy.SJF;
127 case 'SEPTStrategy'
128 strategy{i} = SchedStrategy.SEPT;
129 case 'LJFStrategy'
130 strategy{i} = SchedStrategy.LJF;
131 case 'LEPTStrategy'
132 strategy{i} = SchedStrategy.LEPT;
133 end
134
135 xsection_i_type{i} = {xsection{i}.ATTRIBUTE};
136 switch xsection_i_type{i}{2}.className
137 case 'Delay'
138 node{i} = Delay(model, node_name{i});
139 xcapacity = {xsection_i_par{i}.value};
140 node{i}.setCapacity(xcapacity{1}); % buffer size
141 case 'Server'
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;
150 end
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
158 case 'EPSStrategy'
159 strategy{i} = SchedStrategy.PS;
160 case 'DPSStrategy'
161 strategy{i} = SchedStrategy.DPS;
162 case 'GPSStrategy'
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;
170 end
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});
176 case 'ClassSwitch'
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});
182 end
183 node{i} = ClassSwitch(model, node_name{i}, csMatrix);
184 end
185 end
186 end
187 case 'Storage'
188 node{i} = Place(model, node_name{i});
189 case 'Enabling'
190 node{i} = Transition(model, node_name{i});
191 end
192end
193
194% create classes
195classes = {xDoc.userClass.ATTRIBUTE};
196for r=1:length(classes)
197 ref = findstring(node_name,classes{r}.referenceSource);
198 switch classes{r}.type
199 case JobClassType.toText(JobClassType.CLOSED)
200 jobclass{r} = ClosedClass(model, classes{r}.name, classes{r}.customers, node{ref}, classes{r}.priority);
201 case JobClassType.toText(JobClassType.OPEN)
202 % sink and source have been created before
203 jobclass{r} = OpenClass(model, classes{r}.name, classes{r}.priority);
204 if strcmpi(classes{r}.referenceSource,'StatelessClassSwitcher')
205 sourceIdx = cellisa(node,'Source');
206 node{sourceIdx}.setArrival(jobclass{r},Disabled.getInstance());
207 end
208 end
209end
210
211
212for i=1:length(node_name)
213 xsection_i{i} = {xsection{i}};
214 xsection_i{i} = xsection_i{i}{1}; % input, service, and output sections of node i
215 xsection_javaClass{i} = {xsection_i{i}.ATTRIBUTE};
216 switch xsection_javaClass{i}{1}.className % input section
217
218 case 'Storage'
219 node{i}.init();
220 if xsection_i{1,i}(1).parameter(1).value == -1
221 node{i}.setCapacity(Inf);
222 else
223 node{i}.setCapacity(xsection_i{1,i}(1).parameter(1).value);
224 end
225 if isa(xsection_i{1, i}(1).parameter(2).refClass,'cell')
226 nclasses = length(xsection_i{1, i}(1).parameter(2).refClass);
227 else
228 nclasses = 1;
229 end
230 for c=1:nclasses
231 if xsection_i{1, i}(1).parameter(2).subParameter(c).value == -1
232 node{i}.setClassCapacity(c, Inf);
233 else
234 node{i}.setClassCapacity(c, xsection_i{1, i}(1).parameter(2).subParameter(c).value);
235 end
236 switch xsection_i{1, i}(1).parameter(3).subParameter(c).value
237 case 'BAS blocking'
238 node{i}.setDropRule(c, DropStrategy.BAS);
239 case 'drop'
240 node{i}.setDropRule(c, DropStrategy.DROP);
241 case 'waiting queue'
242 node{i}.setDropRule(c, DropStrategy.WAITQ);
243 end
244 end
245 node{i}.setState(0);
246
247 case 'Enabling'
248 % Enabling Section
249 nmodes = length(xsection_i{1, i}(1).parameter(1).subParameter);
250 for m=1:nmodes
251 node{i}.setModeNames(m, xsection_i{1, i}(2).parameter(1).subParameter(m).value);
252 end
253 node{i}.init();
254 for m=1:nmodes
255 ninputs = length(xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter);
256 for j=1:ninputs
257 refClasses = xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).refClass;
258 if isa(refClasses,'cell')
259 nclasses = length(refClasses);
260 else
261 nclasses = 1;
262 end
263 nodeName = xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(1).value;
264 targetNode = model.getNodeByName(nodeName);
265 for k=1:nclasses
266 enable = xsection_i{1, i}(1).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).subParameter(k).value;
267 if enable == -1
268 node{i}.setEnablingConditions(m,k,targetNode,Inf);
269 else
270 node{i}.setEnablingConditions(m,k,targetNode,enable);
271 end
272 inhibit = xsection_i{1, i}(1).parameter(2).subParameter(m).subParameter.subParameter(j).subParameter(2).subParameter(k).value;
273 if inhibit == -1
274 node{i}.setInhibitingConditions(m,k,targetNode,Inf);
275 else
276 node{i}.setInhibitingConditions(m,k,targetNode,inhibit);
277 end
278 end
279 end
280 end
281 % Timing Section
282 for m=1:nmodes
283 numOfServers = xsection_i{1, i}(2).parameter(2).subParameter(m).value;
284 if numOfServers == -1
285 node{i}.setNumberOfServers(m, Inf);
286 else
287 node{i}.setNumberOfServers(m, numOfServers);
288 end
289 timingSt = xsection_i{1, i}(2).parameter(3).subParameter(m).ATTRIBUTE.classPath;
290 if strcmp(timingSt,'jmt.engine.NetStrategies.ServiceStrategies.ZeroServiceTimeStrategy')
291 node{i}.setTimingStrategy(m,TimingStrategy.IMMEDIATE);
292 else
293 node{i}.setTimingStrategy(m,TimingStrategy.TIMED);
294 distribution = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(1).ATTRIBUTE.name;
295 lambda = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(1).value;
296 switch distribution
297 case 'Exponential'
298 node{i}.setDistribution(m,Exp(lambda));
299 case 'Erlang'
300 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
301 node{i}.setDistribution(m,Erlang(lambda, lambda1));
302 case 'Hyperexponential'
303 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
304 lambda2 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(3).value;
305 node{i}.setDistribution(m,HyperExp(lambda, lambda1, lambda2));
306 case 'Coxian'
307 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
308 lambda2 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(3).value;
309 node{i}.setDistribution(m,Coxian([lambda, lambda1], [lambda2,1]));
310 case 'Deterministic'
311 node{i}.setDistribution(m,Det(lambda));
312 case 'Pareto'
313 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
314 node{i}.setDistribution(m,Pareto(lambda, lambda1));
315 case 'Gamma'
316 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
317 node{i}.setDistribution(m,Gamma(lambda, lambda1));
318 case 'Uniform'
319 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
320 node{i}.setDistribution(m,Uniform(lambda, lambda1));
321 case 'Replayer'
322 node{i}.setDistribution(m,Replayer(lambda));
323 case 'Trace'
324 node{i}.setDistribution(m,Trace(lambda));
325 case 'Weibull'
326 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
327 node{i}.setDistribution(m,Weibull(lambda1, lambda)); % scale and shape are inverted in the constructor
328 case 'Lognormal'
329 lambda1 = xsection_i{1, i}(2).parameter(3).subParameter(m).subParameter(2).subParameter(2).value;
330 node{i}.setDistribution(m,Lognormal(lambda, lambda1));
331 otherwise
332 error('The model includes an arrival distribution not supported by the model-to-model transformation from JMT.')
333 end
334 end
335 firingPriorities = xsection_i{1, i}(2).parameter(4).subParameter(m).value;
336 node{i}.setFiringPriorities(m, firingPriorities);
337 firingWeights = xsection_i{1, i}(2).parameter(5).subParameter(m).value;
338 node{i}.setFiringWeights(m, firingWeights);
339 end
340 % Firing Section
341 for m=1:nmodes
342 if isfield(xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter,'CONTENT')
343 noutputs = 0;
344 else
345 noutputs = length(xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter);
346 end
347 for j=1:noutputs
348 refClasses = xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).refClass;
349 if isa(refClasses, 'cell')
350 nclasses = length(refClasses);
351 else
352 nclasses = 1;
353 end
354 nodeName = xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(1).value;
355 for k=1:nclasses
356 outcome = xsection_i{1, i}(3).parameter(1).subParameter(m).subParameter.subParameter(j).subParameter(2).subParameter(k).value;
357 if outcome == -1
358 node{i}.setFiringOutcome(m,k,nodeName,Inf);
359 else
360 node{i}.setFiringOutcome(m,k,nodeName,outcome);
361 end
362 end
363 end
364 end
365 end
366end
367
368schedparams = cell(1,length(node_name));
369% set service distributions
370for i=1:length(node_name)
371 if isa(node{i},'Source')
372 for r=1:length(classes)
373 xsection_par{i} = {xsection{i}.parameter};
374 xsection_i_par{i} = xsection_i{i}.parameter;
375 xsection_i_subpar{i} = {xsection_i_par{i}.subParameter};
376 xarv_statdistrib{i}{r}={xsection_i_subpar{i}{1}.subParameter};
377 if isempty(xarv_statdistrib{i}{r}{r})
378 node{i}.setArrival(jobclass{r}, Disabled.getInstance());
379 else
380 xarv_statdistrib{i}{r}={xarv_statdistrib{i}{r}{r}.ATTRIBUTE};
381 xarv{i} = {xsection_i{i}(1).parameter.subParameter};
382 xarv_sec{i} = {xarv{i}{1}.subParameter};
383 switch xarv_statdistrib{i}{r}{1}.name
384 case 'Exponential'
385 par={xarv_sec{i}{r}.subParameter}; par=par{2};
386 node{i}.setArrival(jobclass{r}, Exp(par.value));
387 case 'Erlang'
388 par={xarv_sec{i}{r}.subParameter}; par=par{2};
389 node{i}.setArrival(jobclass{r}, Erlang(par(1).value,par(2).value));
390 case 'Hyperexponential'
391 par={xarv_sec{i}{r}.subParameter}; par=par{2};
392 node{i}.setArrival(jobclass{r}, HyperExp(par(1).value,par(2).value,par(3).value));
393 case 'Coxian'
394 par={xarv_sec{i}{r}.subParameter}; par=par{2};
395 node{i}.setArrival(jobclass{r}, Coxian([par(1).value,par(2).value],[par(3).value,1]));
396 case 'Deterministic'
397 par={xarv_sec{i}{r}.subParameter}; par=par{2};
398 node{i}.setArrival(jobclass{r}, Det(par.value));
399 case 'Pareto'
400 par={xarv_sec{i}{r}.subParameter}; par=par{2};
401 node{i}.setArrival(jobclass{r}, Pareto(par(1).value, par(2).value));
402 case 'Weibull'
403 par={xarv_sec{i}{r}.subParameter}; par=par{2};
404 node{i}.setArrival(jobclass{r}, Weibull(par(1).value, par(2).value));
405 case 'Lognormal'
406 par={xarv_sec{i}{r}.subParameter}; par=par{2};
407 node{i}.setArrival(jobclass{r}, Lognormal(par(1).value, par(2).value));
408 case 'Gamma'
409 par={xarv_sec{i}{r}.subParameter}; par=par{2};
410 node{i}.setArrival(jobclass{r}, Gamma(par(1).value, par(2).value));
411 case 'Uniform'
412 par={xarv_sec{i}{r}.subParameter}; par=par{2};
413 node{i}.setArrival(jobclass{r}, Uniform(par(1).value, par(2).value));
414 case 'Replayer'
415 par={xarv_sec{i}{r}.subParameter}; par=par{2};
416 node{i}.setArrival(jobclass{r}, Replayer(par.value));
417 case 'Trace'
418 par={xarv_sec{i}{r}.subParameter}; par=par{2};
419 node{i}.setArrival(jobclass{r}, Trace(par.value));
420 case 'Burst (MMPP2)'
421 par={xarv_sec{i}{r}.subParameter}; par=par{2};
422 node{i}.setArrival(jobclass{r}, MMPP2(par(1).value,par(2).value,par(3).value,par(4).value));
423 case 'Burst (MAP)'
424 par={xarv_sec{i}{r}.subParameter}; par=par{2};
425 pars = {par(1).subParameter.subParameter};
426 D0 = [];
427 for c=1:length(pars)
428 D0 = [D0; pars{c}.value];
429 end
430 pars = {par(2).subParameter.subParameter};
431 D1 = [];
432 for c=1:length(pars)
433 D1 = [D1; pars{c}.value];
434 end
435 ax = MAP(D0,D1);
436 node{i}.setArrival(jobclass{r}, ax);
437 case 'Phase-Type'
438 par={xarv_sec{i}{r}.subParameter}; par=par{2};
439 alpha = [par(1).subParameter.subParameter.value];
440 pars = {par(2).subParameter.subParameter};
441 T = [];
442 for c=1:length(pars)
443 T = [T; pars{c}.value];
444 end
445 if any(any(tril(T,-1))>0) % not APH
446 line_warning(mfilename,'The input model uses a general PH distribution, which is not yet supported in LINE. Fitting the first three moments into an APH distribution.\n');
447 PH = {T,-T*ones(size(T,1),1)*alpha};
448 ax = APH.fitCentral(map_mean(PH), map_var(PH), map_skew(PH));
449 else % APH
450 ax = APH(alpha, T);
451 end
452 node{i}.setArrival(jobclass{r}, ax);
453 otherwise
454 line_error(mfilename,'The model includes an arrival distribution not supported by the model-to-model transformation from JMT.')
455 xarv_statdistrib{i}{r}{1}.name
456 node{i}.setArrival(jobclass{r}, Exp(1)); %TODO
457 end
458 end
459 end
460 elseif isa(node{i},'Queue') || isa(node{i},'Delay') || isa(node{i},'DelayStation')
461 if isempty(schedparams{i})
462 switch SchedStrategy.toId(strategy{i})
463 case {SchedStrategy.SEPT,SchedStrategy.LEPT}
464 schedparams{i} = NaN*ones(1,length(classes));
465 otherwise
466 schedparams{i} = ones(1,length(classes));
467 end
468 end
469 for r=1:length(classes)
470 switch xsection_i_type{i}{2}.className
471 case 'StatelessClassSwitcher'
472 % do nothing
473 continue
474 case 'Delay'
475 xsvc_sec{i} = {xsvc{i}{1}.subParameter};
476 otherwise
477 xsvc_sec{i} = {xsvc{i}{3}.subParameter};
478 end
479 if isempty(xsvc_sec{i}{r})
480 xsvc_statdistrib{i}{r}={struct('name','Disabled')};
481 else
482 xsvc_statdistrib{i}{r}={xsvc_sec{i}{r}.ATTRIBUTE};
483 end
484 para_ir = schedparams{i}(r);
485 switch xsvc_statdistrib{i}{r}{1}.name
486 case 'Disabled'
487 node{i}.setService(jobclass{r}, Disabled.getInstance());
488 case 'Replayer'
489 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
490 node{i}.setService(jobclass{r}, Replayer(par.value), para_ir);
491 case 'Trace'
492 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
493 node{i}.setService(jobclass{r}, Trace(par.value), para_ir);
494 case 'Exponential'
495 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
496 node{i}.setService(jobclass{r}, Exp(par.value), para_ir);
497 case 'Erlang'
498 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
499 node{i}.setService(jobclass{r}, Erlang(par(1).value,par(2).value), para_ir);
500 case 'Hyperexponential'
501 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
502 node{i}.setService(jobclass{r}, HyperExp(par(1).value,par(2).value,par(3).value), para_ir);
503 case 'Coxian'
504 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
505 node{i}.setService(jobclass{r}, Coxian([par(1).value,par(2).value],[par(3).value,1]), para_ir);
506 case 'Deterministic'
507 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
508 node{i}.setService(jobclass{r}, Det(par.value));
509 case 'Pareto'
510 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
511 node{i}.setService(jobclass{r}, Pareto(par(1).value, par(2).value));
512 case 'Weibull'
513 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
514 node{i}.setService(jobclass{r}, Weibull(par(1).value, par(2).value));
515 case 'Lognormal'
516 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
517 node{i}.setService(jobclass{r}, Lognormal(par(1).value, par(2).value));
518 case 'Gamma'
519 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
520 node{i}.setService(jobclass{r}, Gamma(par(1).value, par(2).value));
521 case 'Burst (MMPP2)'
522 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
523 node{i}.setService(jobclass{r}, MMPP2(par(1).value,par(2).value,par(3).value,par(4).value));
524 case 'Burst (MAP)'
525 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
526 pars = {par(1).subParameter.subParameter};
527 D0 = [];
528 for c=1:length(pars)
529 D0 = [D0; pars{c}.value];
530 end
531 pars = {par(2).subParameter.subParameter};
532 D1 = [];
533 for c=1:length(pars)
534 D1 = [D1; pars{c}.value];
535 end
536 ax = MAP(D0,D1);
537 node{i}.setService(jobclass{r}, ax);
538 case 'Phase-Type'
539 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
540 alpha = [par(1).subParameter.subParameter.value];
541 pars = {par(2).subParameter.subParameter};
542 T = [];
543 for c=1:length(pars)
544 T = [T; pars{c}.value];
545 end
546 if any(any(tril(T,-1))>0) % not APH
547 line_warning(mfilename,'The input model uses a general PH distribution, which is not yet supported in LINE. Fitting the first three moments into an APH distribution.\n');
548 PH = {T,-T*ones(size(T,1),1)*alpha};
549 ax = APH.fitCentral(map_mean(PH), map_var(PH), map_skew(PH));
550 else % APH
551 ax = APH(alpha, T);
552 end
553 node{i}.setService(jobclass{r}, ax);
554 case 'Uniform'
555 par={xsvc_sec{i}{r}.subParameter}; par=par{2};
556 node{i}.setService(jobclass{r}, Uniform(par(1).value, par(2).value));
557 otherwise
558 xsvc_statdistrib{i}{r}{1}.name
559 line_error(mfilename,'The model includes a service distribution not supported by the model-to-model transformation from JMT.')
560 xsvc_statdistrib{i}{r}{1}.name
561 node{i}.setService(jobclass{r}, Exp(1), para_ir); %TODO
562 end
563 end
564 for c=1:length(xsection_i_par_attr{i})
565 switch xsection_i_par_attr{i}{c}.name
566 case 'size'
567 node{i}.input.setSize(xsection_i_value{i}{c}); % buffer size
568 end
569 end
570 end
571end
572
573% create links
574C = zeros(length(node_name)); % connection matrix
575links = {xDoc.connection.ATTRIBUTE};
576for l=1:length(links)
577 source = findstring(orig_node_name,links{l}.source);
578 target = findstring(orig_node_name,links{l}.target);
579 % model.addLink(station{source},station{target});
580 C(source,target) = 1;
581end
582
583% assign routing probabilities
584P = zeros(length(node_name)*length(classes));
585for from=1:length(node_name)
586 for target=1:length(node_name)
587 if C(from,target)
588 model.addLink(node{from},node{target});
589 end
590 end
591end
592
593for from=1:length(node_name)
594 switch class(node{from})
595 case 'Place'
596 case 'Transition'
597 case 'Sink'
598 otherwise
599 for r=1:length(classes)
600 switch xrouting{from}{r}.name
601 case 'Random'
602 node{from}.setRouting(jobclass{r},RoutingStrategy.RAND);
603 % targets = find(C(from,:));
604 % if isa(jobclass{r},'Class')
605 % targets = setdiff(targets, [sink_idx, source_idx]);
606 % end
607 % for target = targets(:)'
608 % % node{from}.setProbRouting(jobclass{r}, node{target}, 1 / length(targets));
609 % P((from-1)*length(classes)+r, (target-1)*length(classes)+r) = 1 / length(targets);
610 % end
611 case 'Probabilities'
612 node{from}.setRouting(jobclass{r},RoutingStrategy.PROB);
613 xroutprobarray = {xsection_i{from}(3).parameter.subParameter.subParameter};
614 xroutprob = {xroutprobarray{r}.subParameter}; xroutprob = xroutprob{1};
615 xroutprobdest = {xroutprob.subParameter};
616 for j=1:length(xroutprobdest)
617 xprob={xroutprobdest{j}.value};
618 target = findstring(node_name,xprob{1});
619 prob = xprob{2};
620 node{from}.setProbRouting(jobclass{r}, node{target}, prob);
621 % P((from-1)*length(classes)+r, (target-1)*length(classes)+r) = prob;
622 end
623 case 'Power of k'
624 line_error(mfilename,'Power of k import not supported yet.')
625 case 'Round Robin'
626 node{from}.setRouting(jobclass{r},RoutingStrategy.RROBIN);
627 case 'Weighted Round Robin'
628 node{from}.setRouting(jobclass{r},RoutingStrategy.WRROBIN);
629 xroutprobarray = {xsection_i{from}(3).parameter.subParameter.subParameter};
630 xroutprob = {xroutprobarray{r}.subParameter}; xroutprob = xroutprob{1};
631 xroutprobdest = {xroutprob.subParameter};
632 for j=1:length(xroutprobdest)
633 xprob={xroutprobdest{j}.value};
634 target = findstring(node_name,xprob{1});
635 weight = xprob{2};
636 node{from}.setRouting(RoutingStrategy.WRROBIN, node{target}, jobclass{r}, weight);
637 end
638 case 'Join the Shortest Queue (JSQ)'
639 node{from}.setRouting(jobclass{r},RoutingStrategy.JSQ);
640 case 'Disabled'
641 node{from}.setRouting(jobclass{r},RoutingStrategy.DISABLED);
642 end
643 end
644 end
645end
646%model.link(P);
647%line_printf(['JMT2LINE parsing time: ',num2str(Ttot),' s\n']);
648
649if length(model.getIndexSourceStation)>1
650 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');
651 error(txt);
652end
653
654
655% Preload
656state = zeros(length(node),length(classes));
657if isfield(xDoc,'preload') && ~isempty(xDoc.preload.stationPopulations)
658 npreloadStates = length(xDoc.preload.stationPopulations);
659 for st=1:npreloadStates
660 nodeName = xDoc.preload.stationPopulations(st).ATTRIBUTE.stationName;
661 ind = model.getNodeIndex(nodeName);
662 for r=1:length(xDoc.preload.stationPopulations(st).classPopulation)
663 c = model.getClassIndex(xDoc.preload.stationPopulations(st).classPopulation(r).ATTRIBUTE.refClass);
664 state(ind,c) = xDoc.preload.stationPopulations(st).classPopulation(r).ATTRIBUTE.population;
665 end
666 if isa(node{ind},'Place')
667 %node{ind}.setState(state(ind,:));
668 if length(classes)>1
669 line_error(mfilename,'Import failed: Colored Petri net models are not yet supported in LINE.\n');
670 end
671 end
672 end
673end
674try
675 model.initFromMarginal(state);
676catch
677 line_warning(mfilename,'Import failed to automatically initialize the model.\n');
678end
679Ttot=toc(T0);
680end