LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_mva_marie_analyzer.m
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)
3%
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.
11%
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.
15%
16% Copyright (c) 2012-2026, Imperial College London
17% All rights reserved.
18
19Tstart = tic;
20lG = NaN;
21actualmethod = 'marie';
22
23M = sn.nstations;
24[Lchain,STchain,Vchain,alpha,Nchain,SCVchain,refstatchain] = sn_get_demands_chain(sn); %#ok<ASGLU>
25C = sn.nchains;
26
27%% gating
28% Closed models only.
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'').']);
32end
33
34% Delay/infinite-server stations (fold into think time); the rest are queueing.
35isDelay = isinf(sn.nservers(:)) | (sn.sched(:) == SchedStrategy.INF);
36
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);
41if ~all(schedOK)
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));
45end
46
47queueRows = find(~isDelay);
48delayRows = find(isDelay);
49Mq = numel(queueRows);
50
51%% per-chain think time from the delay stations
52Z = zeros(1,C);
53for c = 1:C
54 Z(c) = sum(Lchain(delayRows,c));
55end
56
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,:);
62for jj = 1:Mq
63 if sn.sched(queueRows(jj)) ~= SchedStrategy.FCFS
64 SCV(jj,:) = 1;
65 end
66end
67SCV(~isfinite(SCV) | SCV <= 0) = 1; % guard undefined SCV (e.g. zero demand)
68
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.']);
75end
76
77%% Marie solve
78if C == 1
79 [Xm,Qm,Um,~,lastiter] = pfqn_marie(L, Nchain, Z, SCV, [], [], nservers);
80else
81 [Xm,Qm,Um,~,lastiter] = pfqn_marie(L, Nchain, Z, SCV);
82end
83Xchain = Xm(:)'; % 1 x C chain throughput (reference station)
84
85%% assemble full-station chain-level matrices
86Qchain = zeros(M,C);
87Uchain = zeros(M,C);
88Rchain = zeros(M,C);
89Qchain(queueRows,:) = Qm;
90Uchain(queueRows,:) = Um;
91Tchain = repmat(Xchain,M,1) .* Vchain; % per-station throughput = chain X * visits
92
93% residence per station (Little's law, consistent with Marie's Q)
94for ist = 1:M
95 for c = 1:C
96 if Tchain(ist,c) > 0
97 Rchain(ist,c) = Qchain(ist,c) / Tchain(ist,c);
98 end
99 end
100end
101
102% delay stations: number in service Q = T*S, U = T*S, R = S
103for jj = 1:numel(delayRows)
104 ist = delayRows(jj);
105 for c = 1:C
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);
109 end
110end
111
112[QN,UN,RN,TN,CN,XN] = sn_deaggregate_chain_results(sn, Lchain, [], STchain, Vchain, alpha, ...
113 Qchain, Uchain, Rchain, Tchain, [], Xchain);
114
115runtime = toc(Tstart);
116end