LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
solver_mva_qsys_analyzer.m
1function [Q,U,R,T,C,X,lG,runtime,totiter] = solver_mva_qsys_analyzer(sn, options)
2% [Q,U,R,T,C,X,LG,RUNTIME,ITER] = SOLVER_MVA_QSYS_ANALYZER(QN, OPTIONS)
3
4% Copyright (c) 2012-2026, Imperial College London
5% All rights reserved.
6
7T0=tic;
8M = sn.nstations;
9K = sn.nclasses;
10Q = zeros(M,K); U = zeros(M,K);
11R = zeros(M,K); T = zeros(M,K);
12C = zeros(1,K); X = zeros(M,K);
13totiter = 1;
14
15method = options.method;
16source_ist = sn.nodeToStation(sn.nodetype == NodeType.Source);
17queue_ist = sn.nodeToStation(sn.nodetype == NodeType.Queue);
18lambda = sn.rates(source_ist)*sn.visits{source_ist}(sn.stationToStateful(queue_ist));
19k = sn.nservers(queue_ist);
20mu = sn.rates(queue_ist);
21ca = sqrt(sn.scv(source_ist));
22cs = sqrt(sn.scv(queue_ist));
23
24line_debug('MVA qsys analyzer starting: method=%s, lambda=%g, mu=%g, k=%d', method, lambda, mu, k);
25
26% Check for BMAP arrivals (batch Markovian)
27arvproc = sn.proc{source_ist};
28if iscell(arvproc) && length(arvproc) >= 1
29 arvproc = arvproc{1};
30end
31
32if isa(arvproc, 'BMAP')
33 line_debug('BMAP arrival process detected');
34 srvproc = sn.proc{queue_ist};
35 if iscell(srvproc) && length(srvproc) >= 1
36 srvproc = srvproc{1};
37 end
38
39 % Check if service is exponential
40 if isa(srvproc, 'Exp')
41 line_debug('Service is exponential, using MX/M/1 queue model');
42 lambda_batch = arvproc.getRate();
43 E_X = arvproc.getMeanBatchSize();
44
45 % Compute second moment of batch size
46 % For BMAP, we need to extract this from the D matrices
47 batch_rates = arvproc.getBatchRates();
48 total_rate = sum(batch_rates);
49 if total_rate > 0
50 E_X2 = 0;
51 for bsize = 1:length(batch_rates)
52 E_X2 = E_X2 + (bsize^2) * batch_rates(bsize) / total_rate;
53 end
54 else
55 E_X2 = E_X^2; % Fallback to deterministic batch size
56 end
57
58 [W, Wq, U_mxm1, Q_mxm1] = qsys_mxm1(lambda_batch, mu, E_X, E_X2);
59 R(queue_ist,1) = W * sn.visits{1}(sn.stationToStateful(queue_ist));
60 C(1,1) = R(queue_ist,1);
61 X(queue_ist,1) = lambda_batch * E_X; % Job arrival rate
62 U(queue_ist,1) = U_mxm1;
63 T(source_ist,1) = lambda_batch * E_X;
64 T(queue_ist,1) = lambda_batch * E_X;
65 Q(queue_ist,1) = Q_mxm1;
66 lG = 0;
67 runtime=toc(T0);
68 method = 'mxm1';
69 return;
70 end
71end
72
73if strcmpi(method,'exact')
74 if ca == 1 && cs == 1 && k==1
75 method = 'mm1';
76 line_debug('Exact method selected: M/M/1 (ca=1, cs=1, k=1)');
77 elseif ca == 1 && cs == 1 && k>1
78 method = 'mmk';
79 line_debug('Exact method selected: M/M/k (ca=1, cs=1, k=%d)', k);
80 elseif ca == 1 && k==1
81 method = 'mg1';
82 line_debug('Exact method selected: M/G/1 (ca=1, k=1)');
83 elseif cs == 1 && k==1
84 method = 'gm1';
85 line_debug('Exact method selected: G/M/1 (cs=1, k=1)');
86 else
87 line_error(mfilename,'MVA exact method unavailable for this model.');
88 end
89end
90
91switch method
92 case 'default'
93 if ca == 1 && cs == 1 && k == 1
94 method = 'mm1';
95 line_debug('Default method: using M/M/1 exact solution\n');
96 elseif ca == 1 && cs == 1 && k > 1
97 method = 'mmk';
98 line_debug('Default method: using M/M/k exact solution (k=%d)\n', k);
99 elseif ca == 1 && k == 1
100 method = 'mg1';
101 line_debug('Default method: using M/G/1 exact solution\n');
102 elseif cs == 1 && k == 1
103 method = 'gm1';
104 line_debug('Default method: using G/M/1 exact solution\n');
105 elseif k > 1
106 method = 'gigk';
107 line_debug('Default method: using G/G/k approximation (k=%d)\n', k);
108 else
109 method = 'gig1.klb';
110 line_debug('Default method: using G/G/1 KLB approximation\n');
111 end
112end
113
114switch method
115 case 'mm1'
116 line_debug('Using M/M/1 exact solution');
117 R = qsys_mm1(lambda,mu);
118 case 'mmk'
119 line_debug('Using M/M/k exact solution (k=%d)', k);
120 R = qsys_mmk(lambda,mu,k);
121 case {'mg1', 'mgi1'} % verified
122 line_debug('Using M/G/1 exact solution');
123 R = qsys_mg1(lambda,mu,cs);
124 case {'gigk'}
125 line_debug('Using G/G/k approximation (k=%d)', k);
126 R = qsys_gigk_approx(lambda,mu,ca,cs,k);
127 case {'gigk.kingman_approx'}
128 line_debug('Using G/G/k Kingman approximation (k=%d)', k);
129 R = qsys_gigk_approx_kingman(lambda,mu,ca,cs,k);
130 case {'gig1', 'gig1.kingman'} % verified
131 line_debug('Using G/G/1 Kingman upper bound');
132 R = qsys_gig1_ubnd_kingman(lambda,mu,ca,cs);
133 case 'gig1.heyman'
134 line_debug('Using G/G/1 Heyman approximation');
135 R = qsys_gig1_approx_heyman(lambda,mu,ca,cs);
136 case 'gig1.allen'
137 line_debug('Using G/G/1 Allen-Cunneen approximation');
138 R = qsys_gig1_approx_allencunneen(lambda,mu,ca,cs);
139 case 'gig1.kobayashi'
140 line_debug('Using G/G/1 Kobayashi approximation');
141 R = qsys_gig1_approx_kobayashi(lambda,mu,ca,cs);
142 case 'gig1.klb'
143 line_debug('Using G/G/1 KLB approximation');
144 R = qsys_gig1_approx_klb(lambda,mu,ca,cs);
145 if strcmpi(options.method,'default')
146 method = sprintf('default [%s]','gig1.klb');
147 end
148 case 'gig1.marchal' % verified
149 line_debug('Using G/G/1 Marchal approximation');
150 R = qsys_gig1_approx_marchal(lambda,mu,ca,cs);
151 case {'gm1', 'gim1'}
152 line_debug('Using G/M/1 exact solution');
153 % sigma = Load at arrival instants (Laplace transform of the inter-arrival times)
154 LA = @(s) sn.lst{source_ist}{1}(s);
155 mu = sn.rates(queue_ist);
156 sigma = fzero(@(x) LA(mu-mu*x)-x,0.5);
157 R = qsys_gm1(sigma,mu);
158 otherwise
159 line_error(mfilename,'Unsupported method for a model with 1 station and 1 class.');
160end
161
162Rscalar = R; % save scalar from qsys function
163R = zeros(M,K);
164R(queue_ist,1) = Rscalar * sn.visits{1}(sn.stationToStateful(queue_ist));
165C(1,1) = R(queue_ist,1);
166X(queue_ist,1) = lambda;
167U(queue_ist,1) = lambda/mu/k;
168T(source_ist,1) = lambda;
169T(queue_ist,1) = lambda;
170Q(queue_ist,1) = X(queue_ist,1) * R(queue_ist,1);
171lG = 0;
172runtime=toc(T0);
173end