1function result = qsys_mapg1(D0, D1, serviceMoments, varargin)
2% QSYS_MAPG1 Analyzes a MAP/G/1 queue
using BUTools MMAPPH1FCFS.
4% RESULT = QSYS_MAPG1(D0, D1, SERVICEMOMENTS) analyzes a MAP/G/1 queue with:
5% D0 - MAP hidden transition matrix (n x n)
6% D1 - MAP arrival transition matrix (n x n)
7% SERVICEMOMENTS - First k raw moments of service time [E[S], E[S^2], ...]
8% (k = 2 or 3
for best accuracy)
10% The general service time
is fitted to a Phase-Type distribution
using
11% moment matching before analysis.
13% RESULT = QSYS_MAPG1(...,
'numQLMoms', K) computes K queue length moments
14% RESULT = QSYS_MAPG1(...,
'numQLProbs', N) computes N queue length probs
15% RESULT = QSYS_MAPG1(...,
'numSTMoms', K) computes K sojourn time moments
17% Returns a
struct with fields:
18% meanQueueLength - Mean number of customers in system
19% meanWaitingTime - Mean waiting time in queue
20% meanSojournTime - Mean sojourn time (waiting + service)
21% utilization - Server utilization
22% queueLengthDist - Queue length distribution
P(Q=n)
23% queueLengthMoments- Raw moments of queue length
24% sojournTimeMoments- Raw moments of sojourn time
25% analyzer - Name of analyzer used
27% See also MMAPPH1FCFS, APHFrom3Moments, qsys_mapph1
29% Parse optional arguments
31addParameter(p, 'numQLMoms', 3);
32addParameter(p, 'numQLProbs', 100);
33addParameter(p, 'numSTMoms', 3);
36numQLMoms = p.Results.numQLMoms;
37numQLProbs = p.Results.numQLProbs;
38numSTMoms = p.Results.numSTMoms;
40% Fit service distribution to PH using moment matching
41[sigma, S] = fitServiceToPH(serviceMoments);
43% Build arrival
MMAP structure for BUTools (single class)
46% Service parameters as cell arrays
51[ncMoms, ncDistr, stMoms] = MMAPPH1FCFS(D, sigmaCell, SCell, ...
52 'ncMoms', numQLMoms,
'ncDistr', numQLProbs,
'stMoms', numSTMoms);
54% Compute utilization from arrival and service rates
55theta = ctmc_solve(D0 + D1);
56lambda = sum(theta * D1);
58meanService = serviceMoments(1);
59mu = 1.0 / meanService;
75% Waiting time = sojourn time - service time
76meanWT = max(0, meanST - meanService);
80result.meanQueueLength = meanQL;
81result.meanWaitingTime = meanWT;
82result.meanSojournTime = meanST;
83result.utilization = rho;
84result.queueLengthDist = ncDistr;
85result.queueLengthMoments = ncMoms;
86result.sojournTimeMoments = stMoms;
87result.analyzer =
'BUTools:MMAPPH1FCFS';
91function [sigma, S] = fitServiceToPH(moments)
92% FITSERVICETOPH Fits a general service time distribution to PH.
94% Uses moment matching with APHFrom3Moments when 3 moments are available,
95% otherwise falls back to simpler approximations.
99if length(moments) >= 3
100 % Use APH from 3 moments
for best accuracy
102 [sigma, S] = APHFrom3Moments(moments(1:3));
104 % Fallback to 2-phase PH
106 [sigma, S] = PH2From3Moments(moments(1:3));
108 % Ultimate fallback to exponential
109 [sigma, S] = createExponentialPH(m1);
112elseif length(moments) >= 2
113 % Use 2 moments - create PH(2) with matching mean and variance
115 cv2 = m2 / (m1 * m1) - 1.0; % Squared coefficient of variation
118 % Deterministic or near-deterministic: use Erlang approximation
119 k = max(1, round(1.0 / max(cv2, 0.01)));
120 [sigma, S] = createErlangPH(m1, k);
122 % Hypoexponential: use Erlang-k approximation
123 k = max(2, round(1.0 / cv2));
124 [sigma, S] = createErlangPH(m1, k);
127 [sigma, S] = createExponentialPH(m1);
129 % Hyperexponential: use 2-phase hyperexponential
130 [sigma, S] = createHyperexp2PH(m1, cv2);
133 % Only mean provided - use exponential
134 [sigma, S] = createExponentialPH(m1);
139function [sigma, S] = createExponentialPH(mean)
140% Creates an exponential PH distribution.
145function [sigma, S] = createErlangPH(mean, k)
146% Creates an Erlang-k PH distribution.
160function [sigma, S] = createHyperexp2PH(mean, cv2)
161% Creates a 2-phase hyperexponential with matched mean and cv2.
163% Balanced means approach
165p = 0.5 * (1.0 + sqrt((cv2 - 1.0) / (cv2 + 1.0)));
166lambda1 = 2.0 * p / mean;
167lambda2 = 2.0 * (1.0 - p) / mean;
170S = diag([-lambda1, -lambda2]);