LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
qbd_raprap1.m
1%{ @file qbd_raprap1.m
2 % @brief Solves a RAP/RAP/1 queue using QBD methods
3 %
4 % @author LINE Development Team
5%}
6
7%{
8 % @brief Analyzes RAP/RAP/1 queue using Quasi-Birth-Death process
9 %
10 % @details
11 % This function solves a RAP/RAP/1 queue (Rational Arrival Process) using
12 % QBD methods, computing throughput, queue length, utilization, and other
13 % performance metrics.
14 %
15 % The two RAPs are INDEPENDENT of each other, so the QBD phase space is the
16 % product of the two phase spaces and the blocks factor as Kronecker
17 % products. This function is the thin product-space wrapper; the analysis
18 % itself is the block-level core qbd_rap.m, which solves an arbitrary QBD
19 % with RAP components. A model whose arrival process and sequence of
20 % service times share a phase space, and are therefore cross-correlated,
21 % has no such product structure and must call qbd_rap directly.
22 %
23 % @par References:
24 % N. G. Bean and B. F. Nielsen, "Quasi-Birth-and-Death Processes with
25 % Rational Arrival Process Components", Stochastic Models, 26(3), 2010,
26 % pp. 309-334. The analysis rests on the prediction-process interpretation
27 % of a RAP due to Asmussen and Bladt, which is what allows a QBD argument
28 % to be carried over to matrices that are not nonnegative. The same
29 % prediction process underlies the conditional-vector RAP sampler in
30 % rap_sample.m.
31 %
32 % @par Phase ordering:
33 % The QBD phase is the pair (arrival phase, service phase) laid out with
34 % the ARRIVAL phase major and the service phase minor, i.e. the phase index
35 % is (a-1)*ns + s. That is the ordering produced by kron(RAPa, eye(ns)) and
36 % kron(eye(na), RAPs), and pqueue is indexed by it downstream in
37 % solver_mam_basic, so the two Kronecker factors must not be swapped.
38 %
39 % @par Syntax:
40 % @code
41 % [XN, QN, UN, pqueue, R, eta, G, B, L, F] = qbd_raprap1(RAPa, RAPs)
42 % [XN, QN, UN, pqueue, R, eta, G, B, L, F] = qbd_raprap1(RAPa, RAPs, util)
43 % @endcode
44 %
45 % @par Parameters:
46 % <table>
47 % <tr><th>Name<th>Description
48 % <tr><td>RAPa<td>Arrival process (RAP)
49 % <tr><td>RAPs<td>Service process (RAP)
50 % <tr><td>util<td>(Optional) Target utilization to scale service rate
51 % </table>
52 %
53 % @par Returns:
54 % <table>
55 % <tr><th>Name<th>Description
56 % <tr><td>XN<td>System throughput
57 % <tr><td>QN<td>Mean queue length
58 % <tr><td>UN<td>Utilization
59 % <tr><td>pqueue<td>Queue length distribution
60 % <tr><td>R<td>Rate matrix R
61 % <tr><td>eta<td>Caudal characteristic
62 % <tr><td>G<td>Rate matrix G
63 % <tr><td>B<td>Backward transition block
64 % <tr><td>L<td>Local transition block
65 % <tr><td>F<td>Forward transition block
66 % </table>
67%}
68function [XN,QN,UN,pqueue,R,eta,G,B,L,F]=qbd_raprap1(RAPa,RAPs,util)
69% [XN,QN,UN,PQUEUE,R,ETA]=QBD_RAPRAP1(RAPA,RAPS,UTIL)
70
71na = length(RAPa{1});
72ns = length(RAPs{1});
73
74if nargin>=3 %exist('util','var')
75 RAPs = map_scale(RAPs,util/map_lambda(RAPa));
76end
77
78% QBD blocks of the RAP/RAP/1 queue: a level is the number in system, a
79% phase is the (arrival,service) RAP phase pair, arrival phase major. The
80% level rises on an arrival (F), falls on a service completion (B), and the
81% two RAPs evolve independently between level changes (L, the Kronecker sum
82% of the two hidden generators). At level 0 the queue is empty, so no
83% service completion can occur and only the arrival RAP evolves: the
84% boundary local block is B1 = kron(Ca,I) and the boundary up-block is F.
85F = kron(RAPa{2},eye(ns)); % arrivals, level up
86L = kron(RAPa{1},eye(ns)) + kron(eye(na),RAPs{1});
87B = kron(eye(na),RAPs{2}); % service completions, level down
88B1 = kron(RAPa{1},eye(ns));
89
90% Theorem 7 of Bean and Nielsen (2010), in qbd_rap.m: G from the quadratic
91% matrix equation, U = L + F*G, R = F*inv(-U), and pi0 from the boundary
92% equation pi0*(B1 + R*B) = 0 normalised by pi0*inv(I-R)*e = 1.
93[~,~,R,G,~,eta,~,pi0] = qbd_rap(F, L, B, F, B1, 0);
94
95% Level series. The truncation rule is the one of QBD_pi with MaxNumComp
96% 100: accumulate levels until the mass reaches 1-1e-10, capped at 101
97% level vectors. qbd_rap returns the exact mean queue length in closed
98% form, but this function keeps reporting the truncated series because
99% pqueue is the documented return value and downstream consumers (and the
100% JAR and Python ports) must cut the tail at exactly the same point,
101% otherwise the means disagree at the 1e-9 level.
102maxNumComp = 100;
103pqueue = pi0;
104sumpi = sum(pi0);
105numit = 1;
106while sumpi < 1-1e-10 && numit < 1+maxNumComp
107 pqueue(numit+1,1:(na*ns)) = pqueue(numit,:)*R;
108 numit = numit+1;
109 sumpi = sumpi + sum(pqueue(numit,:));
110end
111
112numLevels = size(pqueue,1);
113levelProb = sum(pqueue,2);
114QN = (0:(numLevels-1))*levelProb;
115
116if na == 1 && ns == 1
117 UN = 1 - pqueue(1);
118else
119 UN= 1 - sum(pqueue(1,:));
120end
121XN=map_lambda(RAPa);
122end
Definition Station.m:245