1classdef APH < Markovian
2 % APH Acyclic Phase-type distribution with tree-like structure
4 % APH represents acyclic phase-type distributions where the underlying
5 % Markov chain has no cycles (tree-like structure). This subclass of
6 % phase-type distributions provides computational advantages
while maintaining
7 % flexibility
for modeling various service time distributions.
9 % @brief Acyclic phase-type distribution with tree-like Markov structure
11 % Key characteristics:
12 % - Subclass of general phase-type distributions
13 % - Acyclic structure (no cycles in transition graph)
14 % - Tree-like Markov chain topology
15 % - Computational advantages over general PH distributions
16 % - Maintains distribution approximation capabilities
18 % Acyclic structure benefits:
19 % - More efficient algorithms
for many operations
20 % - Simpler parameter fitting procedures
21 % - Easier interpretation and visualization
22 % - Reduced computational complexity in analyses
24 % APH distributions are used
for:
25 % - Service time modeling with reduced complexity
26 % - Fitting distributions with controlled structure
27 % - Matrix-analytic methods requiring efficiency
28 % - Systems where acyclic behavior
is natural
29 % - Performance models needing fast computation
33 % alpha = [1, 0]; T = [-2, 1; 0, -3]; % Simple 2-phase acyclic
34 % aph_dist = APH(alpha, T);
35 % samples = aph_dist.sample(1000);
38 % Copyright (c) 2012-2026, Imperial College London
39 % All rights reserved.
42 function self = APH(alpha, T)
43 % APH Create an acyclic phase-type distribution instance
45 % @brief Creates an APH distribution with acyclic structure
46 % @param alpha Initial probability vector or Java APH object
47 % @param T Transient subgenerator matrix (acyclic structure)
48 % @return self APH distribution instance
49 self@Markovian('APH', 2);
51 if nargin == 1 && isa(alpha,
'jline.lang.processes.APH')
57 self.setParam(1,
'alpha', alpha);
58 self.setParam(2,
'T', T);
60 self.process = {T, -T * ones(length(T), 1) * alpha};
61 self.nPhases = length(alpha);
67 function alpha = getInitProb(self)
68 % ALPHA = GETINITPROB()
70 % Get vector of initial probabilities
71 alpha = self.getParam(1).paramValue(:);
72 alpha = reshape(alpha,1,length(alpha));
75 function T = getSubgenerator(self)
76 % T = GETSUBGENERATOR()
79 T = self.getParam(2).paramValue;
82 function X = sample(self, n)
85 % Get n samples from the distribution
86 if nargin<2 %~exist(
'n',
'var'),
89 X = map_sample(self.getProcess,n);
94 function update(self,varargin)
95 % UPDATE(SELF,VARARGIN)
97 % Update parameters to match the first n central moments
102 if length(varargin) > 3
103 line_warning(mfilename,
'Update in %s distributions can only handle 3 moments, ignoring higher-order moments.\n',
class(self));
108 e3 = -(2*e1^3-3*e1*e2-SKEW*(e2-e1^2)^(3/2));
109 [alpha,T] = APHFrom3Moments([e1,e2,e3]);
110 self.setParam(1,
'alpha', alpha);
111 self.setParam(2,
'T', T);
112 self.process = {T,-T*ones(length(T),1)*alpha};
113 self.immediate = NaN;
116 function updateFromRawMoments(self,varargin)
117 % UPDATE(SELF,VARARGIN)
119 % Update parameters to match the first n moments
124 if length(varargin) > 3
125 line_warning(mfilename,
'Update in %s distributions can only handle 3 moments, ignoring higher-order moments.\n',
class(self));
128 [alpha,T] = APHFrom3Moments([e1,e2,e3]);
143 elseif 0.5<scv && scv<1
144 if 6*(m1^3)*scv<m3 && m3<3*(m1^3)*(3*scv-1+sqrt(2)*(1-scv)^(3/2))
146 m2 = 3*(m1^3)*(3*scv-1+sqrt(2)*(1-scv)^(3/2));
148 elseif m3<min(3*(m1^3)*(3*scv-1+sqrt(2)*(1-scv)^(3/2)),6*(m1^3)*scv)
150 elseif m3>max(6*(m1^3)*scv,3*(m1^3)*(3*scv-1+sqrt(2)*(1-scv)^(3/2)))
158 % one dimensional exponential distribution with lambda = 1/m1
161 if m3<=(3/2)*m1^3*(1+scv)^2
162 m3 = (3/2)*m1^3*(1+scv)^2;
176 mu = (-b+6*m1*d+sqrt(a))/(b+sqrt(a));
177 lambda1 = (b-sqrt(a))/c;
178 lambda2 = (b+sqrt(a))/c;
186 mu = (-b+6*m1*d+sqrt(a))/(b+sqrt(a));
187 lambda1 = (b-sqrt(a))/c;
188 lambda2 = (b+sqrt(a))/c;
190 mu = (b-6*m1*d+sqrt(a))/(-b+sqrt(a));
191 lambda1 = (b+sqrt(a))/c;
192 lambda2 = (b-sqrt(a))/c;
195 lambda1 = 1/(scv*m1);
197 % one dimensional exponential distribution with lambda = 1/m1
201 lambda1 = 1/(scv*m1);
205 T = [-lambda1,lambda1;0,-lambda2];
207 self.setParam(1, 'alpha', alpha);
208 self.setParam(2, 'T', T);
209 self.process = {T,-T*ones(length(T),1)*alpha};
210 self.immediate = NaN;
213 function setMean(self,MEAN)
214 % UPDATEMEAN(SELF,MEAN)
216 % Update parameters to match the given mean
217 setMean@Markovian(self,MEAN);
220 % function setMeanAndSCV(self, MEAN, SCV)
221 % % UPDATEMEANANDSCV(MEAN, SCV)
223 % % Fit phase-type distribution with given mean and squared coefficient of
224 % % variation (SCV=variance/mean^2)
227 % [alpha,T] = APHFrom2Moments([e1,e2]);
228 % %e3=(3/2+1e-3)*e2^2/e1;
229 % %[alpha,T] = APHFrom3Moments([e1,e2,e3]);
230 % self.setParam(1,
'alpha', alpha);
231 % self.setParam(2,
'T', T);
232 % self.process = {T,-T*ones(length(T),1)*alpha};
233 % self.immediate = NaN;
236 function Ft = evalCDF(self,varargin)
237 alpha = self.getParam(1).paramValue;
238 T = self.getParam(2).paramValue;
239 e = ones(length(alpha),1);
246 if year(matlabRelease.Date)>2023 || strcmpi(matlabRelease.Release,
"R2023b")
248 t = linspace(0,mean+10*sigma,500);
249 F(1:length(t)) = 1-sum(expmv(T
',alpha',t)
',2);
251 for t = linspace(0,mean+10*sigma,500)
252 F(i) = 1-alpha*expm(T.*t)*e;
255 t = linspace(0,mean+10*sigma,500);
261 if year(matlabRelease.Date)>2023 || strcmpi(matlabRelease.Release,"R2023b")
263 F(1:length(t)) = 1-sum(expmv(T',alpha
',t)',2);
265 for i = 1:1:length(t)
266 Ft(i) = 1-alpha*expm(T.*t(i))*e;
276 function
aph = rand(order)
277 map = aph_rand(order);
281 function ex = fit(MEAN, SCV, SKEW)
282 % EX = FIT(MEAN, SCV, SKEW)
284 % Fit the distribution from first three standard moments (mean,
286 if MEAN <= GlobalConstants.FineTol
290 ex.update(MEAN, SCV, SKEW);
291 ex.immediate =
false;
295 function ex = fitRawMoments(m1, m2, m3)
297 % Fit the distribution from first three moments
298 if m1 <= GlobalConstants.FineTol
302 ex.updateFromRawMoments(m1, m2, m3);
303 ex.immediate =
false;
307 function ex = fitCentral(MEAN, VAR, SKEW)
308 % EX = FITCENTRAL(MEAN, VAR, SKEW)
310 % Fit the distribution from first three central moments (mean,
311 % variance, skewness)
312 if MEAN <= GlobalConstants.FineTol
316 ex.update(MEAN, VAR/MEAN^2, SKEW);
317 ex.immediate =
false;
321 function ex = fitMeanAndSCV(MEAN, SCV)
322 % EX = FITMEANANDSCV(MEAN, SCV)
324 % Fit the distribution from first three central moments (mean,
325 % variance, skewness)
326 if MEAN <= GlobalConstants.FineTol
333 [alpha,T] = APHFrom2Moments([e1,e2]);