1function model = JMVA2LINE(filename,modelName)
2% MODEL = JMVA2LINE(FILENAME,MODELNAME)
4% Copyright (c) 2012-2026, Imperial College London
8Pref.Str2Num = 'always';
9xDoc = xml_read(filename,Pref);
10[~,fname]=fileparts(filename);
19model = Network(modelName);
26if isfield(xDoc.parameters.stations,
'delaystation')
27 nInfStations = length(xDoc.parameters.stations.delaystation);
29 nodes{end+1} = Delay(model, xDoc.parameters.stations.delaystation(i).ATTRIBUTE.name);
34if isfield(xDoc.parameters.stations,
'listation')
35 nLIStations = length(xDoc.parameters.stations.listation);
37 nodes{end+1} = Queue(model, xDoc.parameters.stations.listation(i).ATTRIBUTE.name, SchedStrategy.PS);
42if isfield(xDoc.parameters.stations,
'ldstation')
43 nLDStations = length(xDoc.parameters.stations.ldstation);
46 if isfield(xDoc.parameters.stations.ldstation(i).ATTRIBUTE, 'servers')
47 nServers = xDoc.parameters.stations.ldstation(i).ATTRIBUTE.servers;
49 nodes{end+1} = Queue(model, xDoc.parameters.stations.ldstation(i).ATTRIBUTE.name, SchedStrategy.PS);
50 nodes{end}.setNumberOfServers(nServers);
59if isfield(xDoc.parameters.classes,
'openclass')
60 source = Source(model, 'Source');
61 sink = Sink(model, 'Sink');
62 nOpenClasses = length(xDoc.parameters.
classes.openclass);
64 name = xDoc.parameters.
classes.openclass(r).ATTRIBUTE.name;
65 jobclass{r} = OpenClass(model, name, 0);
66 rate = xDoc.parameters.classes.openclass(r).ATTRIBUTE.rate;
67 source.setArrival(
jobclass{r}, Exp(rate));
73if isfield(xDoc.parameters.classes,
'closedclass')
74 nClosedClasses = length(xDoc.parameters.
classes.closedclass);
75 for r=1:nClosedClasses
76 name = xDoc.parameters.
classes.closedclass(r).ATTRIBUTE.name;
77 population = xDoc.parameters.
classes.closedclass(r).ATTRIBUTE.population;
78 if isfield(xDoc.parameters,'ReferenceStation')
79 refstat = model.getStationByName(xDoc.parameters.ReferenceStation.Class(nOpenClasses+r).ATTRIBUTE.refStation);
81 jobclass{nOpenClasses + r} = ClosedClass(model, name, population,
nodes{1}, 0);
86 for r=1:(nOpenClasses+nClosedClasses)
87 servTime = xDoc.parameters.stations.delaystation(i).servicetimes.servicetime(r).CONTENT;
88 visits = xDoc.parameters.stations.delaystation(i).visits.visit(r).CONTENT;
89 servClass = model.getClassByName(xDoc.parameters.stations.delaystation(i).servicetimes.servicetime(r).ATTRIBUTE.customerclass);
92 nodes{i}.setService(servClass,Exp(1/demand));
93 visited(i,servClass) =
true;
95 nodes{i}.setService(servClass,Disabled.getInstance());
96 visited(i,servClass) =
false;
101 for r=1:(nOpenClasses+nClosedClasses)
102 servTime = xDoc.parameters.stations.listation(i).servicetimes.servicetime(r).CONTENT;
103 visits = xDoc.parameters.stations.listation(i).visits.visit(r).CONTENT;
104 servClass = model.getClassByName(xDoc.parameters.stations.listation(i).servicetimes.servicetime(r).ATTRIBUTE.customerclass);
107 nodes{nInfStations+i}.setService(servClass,Exp(1/demand));
108 visited(nInfStations + i,servClass) =
true;
110 nodes{nInfStations+i}.setService(servClass,Disabled.getInstance());
111 visited(nInfStations + i,servClass) =
false;
118 ldst = xDoc.parameters.stations.ldstation(i);
119 nodeIdx = nInfStations + nLIStations + i;
120 for r=1:(nOpenClasses+nClosedClasses)
121 visits = ldst.visits.visit(r).CONTENT;
122 servClass = model.getClassByName(ldst.servicetimes.servicetimes(r).ATTRIBUTE.customerclass);
123 % Parse per-population service demands from LD station
124 stData = ldst.servicetimes.servicetimes(r).servicetime;
125 if ischar(stData) || isstring(stData)
126 % Semicolon or comma-separated format:
"d(0);d(1);...;d(N)"
127 if contains(
char(stData),
';')
128 demands = str2double(strsplit(
char(stData), ';'));
130 demands = str2double(strsplit(
char(stData), ','));
132 elseif isnumeric(stData)
133 demands = stData(:)';
135 % Array of structured entries
136 demands = arrayfun(@(x) x.CONTENT, stData);
139 demands = demands(~isnan(demands));
140 % demands(1)
is at population 0, demands(2) at population 1, etc.
141 % Skip zero-population entry if present
142 if length(demands) > 1 && demands(1) == 0
143 demands = demands(2:end); % now demands(n) = demand at population n
145 if
visits > 0 && ~isempty(demands) && demands(1) > 0
146 baseDemand = demands(1) *
visits;
147 nodes{nodeIdx}.setService(servClass, Exp(1/baseDemand));
148 visited(nodeIdx, servClass) =
true;
149 % Set load-dependent scaling: alpha(n) = baseDemand / (demands(n)*
visits)
150 if length(demands) > 1
151 alpha = demands(1) ./ demands;
152 alpha(demands <= 0) = 0;
153 nodes{nodeIdx}.setLoadDependence(alpha);
156 nodes{nodeIdx}.setService(servClass, Disabled.getInstance());
157 visited(nodeIdx, servClass) =
false;
162P = model.initRoutingMatrix;
164 P{r,r} = Network.serialRouting({source,
nodes{find(visited(:,r))},sink});
166for r=1:nClosedClasses
167 P{nOpenClasses+r,nOpenClasses+r} = Network.serialRouting(
nodes{find(visited(:,nOpenClasses+r))});
171%line_printf([
'JMT2LINE parsing time: ',num2str(Ttot),
' s\n']);