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% Mean queue length: QBD_pi returns
the level probabilities as a flat vector
109% of n phases per level, so level ni occupies pn(ni*n+1 : (ni+1)*n), exactly n
110% entries. Summing n+1 of them while advancing by n let each window reach into
111%
the next level, so one phase per level was counted twice, under two different
112% weights, and
the terminating check then dropped
the last level:
the queue
113% length came out high by up to 15% (worse
the slower
the setup, which
is where
114%
the overlapped phases hold most mass). Level 0
is skipped, holding no jobs.
115QN = 0; % queue-lengths
118while j+n-1 <= length(pn)
120 QN = QN + ni*sum(pn(j:(j+n-1)));
125function p = coxian_phase(rate, scv)
126%
P = COXIAN_PHASE(RATE, SCV) - canonical PH representation of a phase given
127% its rate, entered at phase 1 for every SCV. Exponential phases are built from
128%
the rate directly, which
is exact and avoids
the mean-based FineTol cutoff in
131 p = Exp(rate).getProcess;
133 p = Coxian.fitMeanAndSCV(1/rate, scv).getProcess;