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