LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
APH.m
1classdef APH < Markovian
2 % APH Acyclic Phase-type distribution with tree-like structure
3 %
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.
8 %
9 % @brief Acyclic phase-type distribution with tree-like Markov structure
10 %
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
17 %
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
23 %
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
30 %
31 % Example:
32 % @code
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);
36 % @endcode
37 %
38 % Copyright (c) 2012-2026, Imperial College London
39 % All rights reserved.
40
41 methods
42 function self = APH(alpha, T)
43 % APH Create an acyclic phase-type distribution instance
44 %
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);
50
51 if nargin == 1 && isa(alpha, 'jline.lang.processes.APH')
52 self.obj = alpha;
53 self.params = {};
54 self.support = [];
55 return;
56 else
57 self.setParam(1, 'alpha', alpha);
58 self.setParam(2, 'T', T);
59
60 self.process = {T, -T * ones(length(T), 1) * alpha};
61 self.nPhases = length(alpha);
62 end
63 end
64 end
65
66 methods
67 function alpha = getInitProb(self)
68 % ALPHA = GETINITPROB()
69
70 % Get vector of initial probabilities
71 alpha = self.getParam(1).paramValue(:);
72 alpha = reshape(alpha,1,length(alpha));
73 end
74
75 function T = getSubgenerator(self)
76 % T = GETSUBGENERATOR()
77
78 % Get subgenerator
79 T = self.getParam(2).paramValue;
80 end
81
82 function X = sample(self, n)
83 % X = SAMPLE(N)
84
85 % Get n samples from the distribution
86 if nargin<2 %~exist('n','var'),
87 n = 1;
88 end
89 X = map_sample(self.getProcess,n);
90 end
91 end
92
93 methods
94 function update(self,varargin)
95 % UPDATE(SELF,VARARGIN)
96
97 % Update parameters to match the first n central moments
98 % (n<=4)
99 MEAN = varargin{1};
100 SCV = varargin{2};
101 SKEW = varargin{3};
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));
104 end
105
106 e1 = MEAN;
107 e2 = (1+SCV)*e1^2;
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;
114 end
115
116 function updateFromRawMoments(self,varargin)
117 % UPDATE(SELF,VARARGIN)
118
119 % Update parameters to match the first n moments
120 % (n<=4)
121 e1 = varargin{1};
122 e2 = varargin{2};
123 e3 = varargin{3};
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));
126 end
127 try
128 [alpha,T] = APHFrom3Moments([e1,e2,e3]);
129 catch
130 m1 = e1;
131 m2 = e2;
132 m3 = e3;
133 if m2<1.5*m1^2
134 m2 = 1.5*m1^2;
135 else
136 m2 = m2;
137 end
138
139 scv = (m2/(m1^2))-1;
140
141 if scv == 0.5
142 satisfy = 2;
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))
145 satisfy = 1;
146 m2 = 3*(m1^3)*(3*scv-1+sqrt(2)*(1-scv)^(3/2));
147 m3 = 6*(m1^3)*scv;
148 elseif m3<min(3*(m1^3)*(3*scv-1+sqrt(2)*(1-scv)^(3/2)),6*(m1^3)*scv)
149 satisfy = 0;
150 elseif m3>max(6*(m1^3)*scv,3*(m1^3)*(3*scv-1+sqrt(2)*(1-scv)^(3/2)))
151 satisfy = 0;
152 else
153 satisfy = 1;
154 m3 = m3;
155 end
156 elseif scv == 1
157 satisfy = 3;
158 % one dimensional exponential distribution with lambda = 1/m1
159 elseif scv>1
160 satisfy = 1;
161 if m3<=(3/2)*m1^3*(1+scv)^2
162 m3 = (3/2)*m1^3*(1+scv)^2;
163 else
164 m3 = m3;
165 end
166 else
167 satisfy = 1;
168 m3 = m3;
169 end
170
171 if satisfy == 2
172 c = 0.75*m1^4;
173 d = 0.5*m1^2;
174 b = 1.5*m1^3;
175 a = 0;
176 mu = (-b+6*m1*d+sqrt(a))/(b+sqrt(a));
177 lambda1 = (b-sqrt(a))/c;
178 lambda2 = (b+sqrt(a))/c;
179 elseif satisfy == 1
180 c = 3*m2^2-2*m1*m3;
181 d = 2*m1^2-m2;
182 b = 3*m1*m2-m3;
183 a = b^2-6*c*d;
184
185 if c>0
186 mu = (-b+6*m1*d+sqrt(a))/(b+sqrt(a));
187 lambda1 = (b-sqrt(a))/c;
188 lambda2 = (b+sqrt(a))/c;
189 elseif c<0
190 mu = (b-6*m1*d+sqrt(a))/(-b+sqrt(a));
191 lambda1 = (b+sqrt(a))/c;
192 lambda2 = (b-sqrt(a))/c;
193 else
194 mu = 1/(2*scv);
195 lambda1 = 1/(scv*m1);
196 lambda2 = 2/m1;
197 % one dimensional exponential distribution with lambda = 1/m1
198 end
199 else
200 mu = 1/(2*scv);
201 lambda1 = 1/(scv*m1);
202 lambda2 = 2/m1;
203 end
204 alpha = [mu,1-mu];
205 T = [-lambda1,lambda1;0,-lambda2];
206 end
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;
211 end
212
213 function setMean(self,MEAN)
214 % UPDATEMEAN(SELF,MEAN)
215
216 % Update parameters to match the given mean
217 setMean@Markovian(self,MEAN);
218 end
219
220 % function setMeanAndSCV(self, MEAN, SCV)
221 % % UPDATEMEANANDSCV(MEAN, SCV)
222 %
223 % % Fit phase-type distribution with given mean and squared coefficient of
224 % % variation (SCV=variance/mean^2)
225 % e1 = MEAN;
226 % e2 = (1+SCV)*e1^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;
234 % end
235
236 function Ft = evalCDF(self,varargin)
237 alpha = self.getParam(1).paramValue;
238 T = self.getParam(2).paramValue;
239 e = ones(length(alpha),1);
240 if isempty(varargin)
241 mean = self.getMean;
242 var = self.getVar;
243 sigma = sqrt(var);
244 F = [];
245 i = 1;
246 if year(matlabRelease.Date)>2023 || strcmpi(matlabRelease.Release,"R2023b")
247 % use exmpmv
248 t = linspace(0,mean+10*sigma,500);
249 F(1:length(t)) = 1-sum(expmv(T',alpha',t)',2);
250 else
251 for t = linspace(0,mean+10*sigma,500)
252 F(i) = 1-alpha*expm(T.*t)*e;
253 i = i+1;
254 end
255 t = linspace(0,mean+10*sigma,500);
256 end
257 Ft = [F',t'];
258 else
259 t = varargin{1};
260 Ft = [];
261 if year(matlabRelease.Date)>2023 || strcmpi(matlabRelease.Release,"R2023b")
262 % use exmpmv
263 F(1:length(t)) = 1-sum(expmv(T',alpha',t)',2);
264 else
265 for i = 1:1:length(t)
266 Ft(i) = 1-alpha*expm(T.*t(i))*e;
267 end
268 end
269 end
270 end
271
272 end
273
274 methods (Static)
275
276 function aph = rand(order)
277 map = aph_rand(order);
278 aph = APH(map_pie(map),map{1});
279 end
280
281 function ex = fit(MEAN, SCV, SKEW)
282 % EX = FIT(MEAN, SCV, SKEW)
283
284 % Fit the distribution from first three standard moments (mean,
285 % SCV, skewness)
286 if MEAN <= GlobalConstants.FineTol
287 ex = APH(1.0, [1]);
288 else
289 ex = APH(1.0, [1]);
290 ex.update(MEAN, SCV, SKEW);
291 ex.immediate = false;
292 end
293 end
294
295 function ex = fitRawMoments(m1, m2, m3)
296
297 % Fit the distribution from first three moments
298 if m1 <= GlobalConstants.FineTol
299 ex = Exp(Inf);
300 else
301 ex = APH(1.0, [1]);
302 ex.updateFromRawMoments(m1, m2, m3);
303 ex.immediate = false;
304 end
305 end
306
307 function ex = fitCentral(MEAN, VAR, SKEW)
308 % EX = FITCENTRAL(MEAN, VAR, SKEW)
309
310 % Fit the distribution from first three central moments (mean,
311 % variance, skewness)
312 if MEAN <= GlobalConstants.FineTol
313 ex = Exp(Inf);
314 else
315 ex = APH(1.0, [1]);
316 ex.update(MEAN, VAR/MEAN^2, SKEW);
317 ex.immediate = false;
318 end
319 end
320
321 function ex = fitMeanAndSCV(MEAN, SCV)
322 % EX = FITMEANANDSCV(MEAN, SCV)
323
324 % Fit the distribution from first three central moments (mean,
325 % variance, skewness)
326 if MEAN <= GlobalConstants.FineTol
327 ex = Exp(Inf);
328 elseif SCV==1.0
329 ex = Exp(1/MEAN);
330 else
331 e1 = MEAN;
332 e2 = (1+SCV)*e1^2;
333 [alpha,T] = APHFrom2Moments([e1,e2]);
334 ex = APH(alpha, T);
335 end
336 end
337 end
338
339end