1%{ @file qsys_is_retrial.m
2 % @brief Checks
if network
is a valid BMAP/PH/N/N bufferless retrial queue
4 % @author LINE Development Team
8 % @brief Checks
if network
is a valid BMAP/PH/N/N bufferless retrial queue
11 % Validates that the network structure matches the requirements
for
12 % the BMAP/PH/N/N retrial queue solver:
13 % - Single bufferless queue (capacity == number of servers)
14 % - Retrial drop strategy configured
15 % - BMAP/MAP arrival process at source
16 % - PH/Exp service at queue
19 % Based on: Dudin et al.,
"Analysis of BMAP/PH/N-Type Queueing System with
20 % Flexible Retrials Admission Control", Mathematics 2025, 13(9), 1434.
24 % [isRetrial, retInfo] = qsys_is_retrial(sn)
29 % <tr><th>Name<th>Description
30 % <tr><td>sn<td>Network structure
35 % <tr><th>Name<th>Description
36 % <tr><td>isRetrial<td>True if network
is valid BMAP/PH/N/N retrial topology
37 % <tr><td>retInfo<td>Struct with parameters for the retrial solver
40 % Copyright (c) 2012-2026, Imperial College London
41 % All rights reserved.
43function [isRetrial, retInfo] = qsys_is_retrial(sn)
48retInfo.stationIdx = [];
50retInfo.sourceIdx = [];
53retInfo.N = []; % Number of servers
54retInfo.alpha = []; % Retrial rate
55retInfo.gamma = 0; % Orbit impatience (
default 0)
56retInfo.p = 0; % Batch rejection prob (
default 0)
57retInfo.R = []; % Admission threshold (from FCR or
default N-1)
59% Check
if model
is open
60if ~sn_is_open_model(sn)
61 retInfo.errorMsg =
'BMAP/PH/N/N retrial solver requires open queueing model.';
65% Check
for single
class (current limitation)
67 retInfo.errorMsg =
'BMAP/PH/N/N retrial solver currently supports single class only.';
73% Find bufferless queue stations (capacity == nservers, finite capacity)
74bufferlessStations = [];
75for ist = 1:sn.nstations
76 if sn.nodetype(sn.stationToNode(ist)) == NodeType.Queue
77 if isfinite(sn.cap(ist)) && sn.cap(ist) == sn.nservers(ist)
78 bufferlessStations = [bufferlessStations, ist];
83if isempty(bufferlessStations)
84 retInfo.errorMsg =
'No bufferless queue found (capacity must equal number of servers).';
88% Check retrial drop strategy
90for ist = bufferlessStations(:)
'
91 if any(sn.droprule(ist,:) == DropStrategy.RETRIAL | ...
92 sn.droprule(ist,:) == DropStrategy.RETRIAL_WITH_LIMIT)
98if isempty(retrialStation)
99 retInfo.errorMsg = 'No retrial drop strategy configured on bufferless queue.
';
103retInfo.stationIdx = retrialStation;
104retInfo.nodeIdx = sn.stationToNode(retrialStation);
105retInfo.N = sn.nservers(retrialStation);
109for ist = 1:sn.nstations
110 if sn.nodetype(sn.stationToNode(ist)) == NodeType.Source
116if isempty(sourceStation)
117 retInfo.errorMsg = 'No Source node found.
';
121retInfo.sourceIdx = sourceStation;
123% Validate arrival process (must be MAP/BMAP)
124% sn.proc{station}{class} contains PH representation
125arrivalProc = sn.proc{sourceStation}{retInfo.classIdx};
126if isempty(arrivalProc) || ~iscell(arrivalProc) || length(arrivalProc) < 2
127 retInfo.errorMsg = 'Invalid arrival process at source.
';
131% Check if arrival is MAP/BMAP (has matrix structure)
132% For BMAP: proc is {D0, D1, D2, ...} or {alpha, A} for MAP
133% For Exp/PH at source: it's {1, -lambda} format
134if ~iscell(arrivalProc{1}) && size(arrivalProc{1}, 2) > 1
135 % This looks like a PH representation {alpha, A}, convert from arrival to MAP
136 % For now, we accept it - the solver_mam_retrial will handle conversion
137elseif iscell(arrivalProc{1})
138 % This might be BMAP format already
141% Validate service process (must be PH/Exp)
142serviceProc = sn.proc{retrialStation}{retInfo.classIdx};
143if isempty(serviceProc) || ~iscell(serviceProc) || length(serviceProc) < 2
144 retInfo.errorMsg =
'Invalid service process at queue.';
148% Extract retrial rate alpha from retrial delay distribution
149% In sn
struct, we need to check
for retrial configuration
150% For now, use
default if not found - the Network/getStruct needs to
export this
151retInfo.alpha = 0.1; % Default, will be extracted from sn in solver
153% Check
for FCR containing
this queue and extract admission threshold
154retInfo.R = retInfo.N - 1; % Default: no admission control
156% Check
if region field exists and
is non-empty
157if isfield(sn,
'region') && ~isempty(sn.region) && isfield(sn,
'nregions') && sn.nregions > 0
158 for f = 1:sn.nregions
159 regionMatrix = sn.region{f};
160 % Check
if this station
is in the region with a global capacity
161 if size(regionMatrix, 1) >= retrialStation
162 globalCapCol = size(regionMatrix, 2); % Last column
is typically global cap
163 if regionMatrix(retrialStation, globalCapCol) > 0
164 % Get the global max jobs
for this region
165 R_fcr = regionMatrix(retrialStation, globalCapCol);
166 if R_fcr <= retInfo.N - 1
167 retInfo.R = R_fcr; % Use FCR threshold
175% All validations passed