1function outputFileName = writeJMVA(sn, outputFileName, options)
2% FNAME = WRITEJMVA(SN, FNAME, OPTIONS)
4% Copyright (c) 2012-2026, Imperial College London
7%
if ~self.model.hasProductFormSolution
8% line_error(mfilename,
'JMVA requires the model to have a product-form solution.');
11%
if self.model.hasClassSwitching
12% line_error(mfilename,
'JMVA does not support class switching.');
15mvaDoc = com.mathworks.xml.XMLUtils.createDocument(
'model');
16mvaElem = mvaDoc.getDocumentElement;
18xmlnsXsi =
'http://www.w3.org/2001/XMLSchema-instance';
19mvaElem.setAttribute(
'xmlns:xsi', xmlnsXsi);
20mvaElem.setAttribute(
'xsi:noNamespaceSchemaLocation',
'JMTmodel.xsd');
22algTypeElement = mvaDoc.createElement(
'algType');
25 if max(sn.nservers(isfinite(sn.nservers))) > 1
26 line_error(mfilename,sprintf(
'%s does not support multi-server stations.',options.method));
28 algTypeElement.setAttribute(
'name',
'RECAL');
30 if max(sn.nservers(isfinite(sn.nservers))) > 1
31 line_error(mfilename,sprintf(
'%s does not support multi-server stations.',options.method));
33 algTypeElement.setAttribute(
'name',
'Chow');
34 case {
'jmva.bs',
'jmva.amva'}
35 if max(sn.nservers(isfinite(sn.nservers))) > 1
36 line_error(mfilename,sprintf(
'%s does not support multi-server stations.',options.method));
38 algTypeElement.setAttribute(
'name',
'Bard-Schweitzer');
40 if max(sn.nservers(isfinite(sn.nservers))) > 1
41 line_error(mfilename,sprintf(
'%s does not support multi-server stations.',options.method));
43 algTypeElement.setAttribute(
'name',
'AQL');
45 if max(sn.nservers(isfinite(sn.nservers))) > 1
46 line_error(mfilename,sprintf(
'%s does not support multi-server stations.',options.method));
48 algTypeElement.setAttribute(
'name',
'Linearizer');
50 if max(sn.nservers(isfinite(sn.nservers))) > 1
51 line_error(mfilename,sprintf(
'%s does not support multi-server stations.',options.method));
53 algTypeElement.setAttribute(
'name',
'De Souza-Muntz Linearizer');
55 % algTypeElement.setAttribute(
'name',
'Logistic Sampling');
57 algTypeElement.setAttribute(
'name',
'MVA');
59algTypeElement.setAttribute(
'tolerance',
'1.0E-7');
60algTypeElement.setAttribute(
'maxSamples',num2str(options.samples));
63M = sn.nstations; %number of stations
64NK = sn.njobs
'; % initial population per class
68% determine service times
73[Lchain,STchain,Vchain,alpha,Nchain,SCVchain] = sn_get_demands_chain(sn);
76parametersElem = mvaDoc.createElement('parameters
');
77classesElem = mvaDoc.createElement('classes');
78classesElem.setAttribute('number
',num2str(sn.nchains));
79stationsElem = mvaDoc.createElement('stations
');
80stationsElem.setAttribute('number
',num2str(sn.nstations - sum(sn.nodetype == NodeType.Source)));
81refStationsElem = mvaDoc.createElement('ReferenceStation
');
82refStationsElem.setAttribute('number
',num2str(sn.nchains));
83algParamsElem = mvaDoc.createElement('algParams
');
85sourceid = sn.nodetype == NodeType.Source;
87 if isfinite(sum(sn.njobs(sn.chains(c,:))))
88 classElem = mvaDoc.createElement('closedclass
');
89 classElem.setAttribute('population
',num2str(Nchain(c)));
90 classElem.setAttribute('name
',sprintf('Chain%02d
',c));
92 classElem = mvaDoc.createElement('openclass
');
93 classElem.setAttribute('rate
',num2str(sum(sn.rates(sourceid,sn.chains(c,:)))));
94 classElem.setAttribute('name
',sprintf('Chain%02d
',c));
96 classesElem.appendChild(classElem);
99isLoadDep = false(1,sn.nstations);
101 switch sn.nodetype(sn.stationToNode(i))
103 statElem = mvaDoc.createElement('delaystation
');
104 statElem.setAttribute('name
',sn.nodenames{sn.stationToNode(i)});
106 if sn.nservers(i) == 1
107 isLoadDep(i) = false;
108 statElem = mvaDoc.createElement('listation
');
109 statElem.setAttribute('name
',sn.nodenames{sn.stationToNode(i)});
110 statElem.setAttribute('servers
',num2str(1));
113 statElem = mvaDoc.createElement('ldstation
');
114 statElem.setAttribute('name
',sn.nodenames{sn.stationToNode(i)});
115 statElem.setAttribute('servers
',num2str(1));
120 srvTimesElem = mvaDoc.createElement('servicetimes
');
123 statSrvTimeElem = mvaDoc.createElement('servicetimes
');
124 statSrvTimeElem.setAttribute('customerclass
',sprintf('Chain%02d
',c));
125 ldSrvString = num2str(STchain(i,c));
126 % For open models (Inf population), use nservers as cutoff
127 % since service time is constant at S/c for n >= c
129 ldLimit = sn.nservers(i);
135 ldSrvString = sprintf('%s;%s
',ldSrvString,num2str(STchain(i,c)/min( n, sn.nservers(i) )));
137 statSrvTimeElem.appendChild(mvaDoc.createTextNode(ldSrvString));
138 srvTimesElem.appendChild(statSrvTimeElem);
140 statSrvTimeElem = mvaDoc.createElement('servicetime
');
141 statSrvTimeElem.setAttribute('customerclass
',sprintf('Chain%02d
',c));
142 statSrvTimeElem.appendChild(mvaDoc.createTextNode(num2str(STchain(i,c))));
143 srvTimesElem.appendChild(statSrvTimeElem);
146 statElem.appendChild(srvTimesElem);
147 visitsElem = mvaDoc.createElement('visits');
149 statVisitElem = mvaDoc.createElement('visit
');
150 statVisitElem.setAttribute('customerclass
',sprintf('Chain%02d
',c));
152 val = Lchain(i,c) ./ STchain(i,c);
156 statVisitElem.appendChild(mvaDoc.createTextNode(num2str(val)));
157 visitsElem.appendChild(statVisitElem);
159 statElem.appendChild(visitsElem);
161 stationsElem.appendChild(statElem);
164refstatchain = zeros(C,1);
166 inchain = sn.inchain{c};
167 refstatchain(c) = sn.refstat(inchain(1));
171 classRefElem = mvaDoc.createElement('Class
');
172 classRefElem.setAttribute('name
',sprintf('Chain%02d
',c));
173 % For open chains, the refstat is Source which is excluded from JMVA output.
174 % Use the first non-Source station as the reference station instead.
175 refIdx = refstatchain(c);
176 refNodeType = sn.nodetype(sn.stationToNode(refIdx));
177 if refNodeType == NodeType.Source
178 for ii=1:sn.nstations
179 nt = sn.nodetype(sn.stationToNode(ii));
180 if nt ~= NodeType.Source && nt ~= NodeType.Sink
186 classRefElem.setAttribute('refStation
',sn.nodenames{sn.stationToNode(refIdx)});
187 refStationsElem.appendChild(classRefElem);
190compareAlgsElem = mvaDoc.createElement('compareAlgs
');
191compareAlgsElem.setAttribute('value
','false');
192algParamsElem.appendChild(algTypeElement);
193algParamsElem.appendChild(compareAlgsElem);
195parametersElem.appendChild(classesElem);
196parametersElem.appendChild(stationsElem);
197parametersElem.appendChild(refStationsElem);
198mvaElem.appendChild(parametersElem);
199mvaElem.appendChild(algParamsElem);
201xmlwrite(outputFileName, mvaDoc);