1function [QN,UN,RN,TN,CN,XN,lG,runtime,lastiter,actualmethod] = solver_mva_marie_analyzer(sn, options)
2% [QN,UN,RN,TN,CN,XN,LG,RUNTIME,LASTITER,ACTUALMETHOD] = SOLVER_MVA_MARIE_ANALYZER(SN, OPTIONS)
4% Marie
's iterative aggregation-decomposition (Marie 1979/1980) for closed
5% networks with FCFS non-exponential (Coxian) service, wired as SolverMVA
6% method 'marie
'. Infinite-server stations fold into per-chain think time;
7% pfqn_marie is applied to the queueing stations, where only FCFS is service-
8% sensitive (its SCV is used) while insensitive product-form disciplines
9% (PS, LCFSPR) are forced to exponential. Chain results are then deaggregated
10% to classes via sn_deaggregate_chain_results.
12% Single chain: aggregate is the exact load-dependent product-form solve, so
13% exponential service is exact. Multiple chains: aggregate is QD-AMVA with
14% class-dependent scaling, exact for product form and approximate otherwise.
16% Copyright (c) 2012-2026, Imperial College London
21actualmethod = 'marie
';
24[Lchain,STchain,Vchain,alpha,Nchain,SCVchain,refstatchain] = sn_get_demands_chain(sn); %#ok<ASGLU>
29if any(isinf(Nchain)) || any(sn.nodetype == NodeType.Source)
30 line_error(mfilename, ['The
''marie
'' method supports closed models only;
this model has open
' ...
31 'classes. Use another SolverMVA method (e.g.
''default'').
']);
34% Delay/infinite-server stations (fold into think time); the rest are queueing.
35isDelay = isinf(sn.nservers(:)) | (sn.sched(:) == SchedStrategy.INF);
37% Scheduling support: FCFS (service-sensitive), the insensitive product-form
38% disciplines PS/LCFSPR (treated as exponential), and Delay. Reject others.
39schedOK = isDelay | (sn.sched(:) == SchedStrategy.FCFS) | ...
40 (sn.sched(:) == SchedStrategy.PS) | (sn.sched(:) == SchedStrategy.LCFSPR);
42 bad = find(~schedOK, 1);
43 line_error(mfilename, sprintf(['The
''marie
'' method supports FCFS, PS, LCFSPR and Delay
' ...
44 'stations only; station %d has an unsupported scheduling strategy. Use another SolverMVA method.
'], bad));
47queueRows = find(~isDelay);
48delayRows = find(isDelay);
51%% per-chain think time from the delay stations
54 Z(c) = sum(Lchain(delayRows,c));
57%% queueing-station demands and effective SCV
58% Only FCFS is service-time sensitive; PS/LCFSPR are insensitive (product
59% form), so their SCV is set to 1 (exponential-equivalent for Marie).
60L = Lchain(queueRows,:);
61SCV = SCVchain(queueRows,:);
63 if sn.sched(queueRows(jj)) ~= SchedStrategy.FCFS
67SCV(~isfinite(SCV) | SCV <= 0) = 1; % guard undefined SCV (e.g. zero demand)
69% Multiserver isolation is supported for single-chain models only.
70nservers = sn.nservers(queueRows);
71nservers(~isfinite(nservers)) = 1;
72if C > 1 && any(nservers > 1)
73 line_error(mfilename, ['The
''marie
'' method supports multiserver queueing stations
for ' ...
74 'single-chain models only;
this model
is multichain with a multiserver station.
']);
79 [Xm,Qm,Um,~,lastiter] = pfqn_marie(L, Nchain, Z, SCV, [], [], nservers);
81 [Xm,Qm,Um,~,lastiter] = pfqn_marie(L, Nchain, Z, SCV);
83Xchain = Xm(:)'; % 1 x C chain throughput (reference station)
85%% assemble full-station chain-level matrices
89Qchain(queueRows,:) = Qm;
90Uchain(queueRows,:) = Um;
91Tchain = repmat(Xchain,M,1) .* Vchain; % per-station throughput = chain X *
visits
93% residence per station (Little
's law, consistent with Marie's Q)
97 Rchain(ist,c) = Qchain(ist,c) / Tchain(ist,c);
102% delay stations: number in service Q = T*S, U = T*S, R = S
103for jj = 1:numel(delayRows)
106 Qchain(ist,c) = Tchain(ist,c) * STchain(ist,c);
107 Uchain(ist,c) = Tchain(ist,c) * STchain(ist,c);
108 Rchain(ist,c) = STchain(ist,c);
112[QN,UN,RN,TN,CN,XN] = sn_deaggregate_chain_results(sn, Lchain, [], STchain, Vchain, alpha, ...
113 Qchain, Uchain, Rchain, Tchain, [], Xchain);
115runtime = toc(Tstart);