1%{ @file qbd_setupdelayoff.m
2 % @brief Queue-length analysis
for system with setup delay and turn-off
4 % @author LINE Development Team
8 % @brief Analyzes queue length
for system with setup and turn-off phases
11 % This function performs queue-length analysis
for a queueing system with
12 % setup delay and turn-off periods
using QBD methods.
16 % QN = qbd_setupdelayoff(lambda, mu, alpharate, alphascv, betarate, betascv)
21 % <tr><th>Name<th>Description
22 % <tr><td>lambda<td>Arrival rate
23 % <tr><td>mu<td>Service rate
24 % <tr><td>alpharate<td>Rate of setup delay phase
25 % <tr><td>alphascv<td>Squared coefficient of variation
for setup delay
26 % <tr><td>betarate<td>Rate of turn-off phase
27 % <tr><td>betascv<td>Squared coefficient of variation for turn-off period
32 % <tr><th>Name<th>Description
33 % <tr><td>QN<td>Average queue length
36function QN = qbd_setupdelayoff(lambda, mu, alpharate, alphascv, betarate, betascv)
38% The phases are given as rates, so an exponential one is built directly from
39% its rate rather than round-tripped through its mean. APH.fitMeanAndSCV maps
40% any mean at or below GlobalConstants.FineTol to Exp(Inf), and an Immediate
41% setup or delay-off has rate GlobalConstants.Immediate whose mean is exactly
42% FineTol; the round trip therefore turned a finite 1e8 rate into an infinite
43% one, put -Inf in the generator, and collapsed QBD_pi onto the boundary level,
44% so the level loop below ran past the end of pn. For SCV 1 the fit returns
45% Exp(1/MEAN) anyway, so this
is the same process everywhere else.
46% Both phases are taken in canonical Coxian
form, whose entry vector
is [1 0 ..]
47% for every SCV. The chain below overloads its phase indices (at the boundary
48% level phase 1
is the off server and phases na+1.. are the delay-off; above it
49% phases 1..na are the setup and na+1
is the busy server), so a level-up
50% transition cannot also redistribute the phase: an arrival to an off server has
51% to enter the setup at phase 1. APH.fitMeanAndSCV violates that for SCV > 1,
52% where it returns a hyperexponential entered at phase 2 with probability 3/4,
53% which the chain then silently entered at phase 1 regardless.
54alpha = coxian_phase(alpharate, alphascv);
56% Completion rate of each phase. A Coxian may complete from any phase, not only
57% from the last one, so these are read per phase rather than off the diagonal.
60beta = coxian_phase(betarate, betascv);
65F = zeros(n); % forward transitions
66B = zeros(n); % backward transitions
71 F(na+i,na+1) = lambda;
76L = zeros(n); % local transitions
78 % Whole generator row, so a phase that both advances and completes (any
79 % Coxian with SCV > 1) contributes both; reading only the diagonal and the
80 % strict upper triangle assumed a pure series, which holds only for SCV <= 1.
81 L(i,1:na) = alpha{1}(i,1:na);
82 L(i,i) = L(i,i) - lambda;
83 L(i,na+1) = ta(i); % setup completes from phase i -> busy server
85L(na+1,na+1) = -mu -lambda;
87 L(na+i,na+i) = -lambda;
91L0 = zeros(na+nb); % local transitions at the boundary level
96 % As above, the whole generator row: the delay-off may expire from any
97 % phase, and its phase-to-phase rate
is the generator entry, not the
98 % diagonal (they coincide only for a series phase).
99 L0(na+i,na+(1:nb)) = beta{1}(i,1:nb);
100 L0(na+i,na+i) = L0(na+i,na+i) - lambda;
101 L0(na+i,1) = tb(i); % delay-off expires from phase i -> server off
105[~,R,~] = QBD_CR(B,L,F);
108% see _kb/03-api-layer.md (QBD boundary conventions) for rationale
109QN = 0; % queue-lengths
112while j+n-1 <= length(pn)
114 QN = QN + ni*sum(pn(j:(j+n-1)));
119function p = coxian_phase(rate, scv)
120%
P = COXIAN_PHASE(RATE, SCV) - canonical PH representation of a phase given
121% its rate, entered at phase 1 for every SCV. Exponential phases are built from
122% the rate directly, which
is exact and avoids the mean-based FineTol cutoff in
125 p = Exp(rate).getProcess;
127 p = Coxian.fitMeanAndSCV(1/rate, scv).getProcess;