2 % Abstract phase-type distribution with Markovian structure
4 % Defined by initial probabilities and transient subgenerator matrix.
6 % Copyright (c) 2012-2026, Imperial College London
10 function self = PH(alpha, T)
11 % PH Create a phase-type distribution instance
13 % @brief Creates a phase-type distribution with initial probabilities and subgenerator
14 % @param alpha Initial probability vector (must sum to ≤ 1)
15 % @param T Transient subgenerator matrix (must be nonsingular)
16 % @
return self PH distribution instance
17 self@Markovian(
'PH', 2);
18 self.setParam(1,
'alpha', alpha);
19 self.setParam(2,
'T', T);
20 T = self.getSubgenerator;
21 ph = {T,-T*ones(length(T),1)*self.getInitProb};
23 self.nPhases = length(self.process{1});
28 function alpha = getInitProb(self)
29 % ALPHA = GETINITPROB()
31 % Get vector of initial probabilities
32 alpha = self.getParam(1).paramValue(:);
33 alpha = reshape(alpha,1,length(alpha));
36 function T = getSubgenerator(self)
37 % T = GETSUBGENERATOR()
40 T = self.getParam(2).paramValue;
43 function X = sample(self, n)
46 % Get n samples from the distribution
47 if nargin<2 %~exist(
'n',
'var'),
50 X = map_sample(self.getProcess,n);
55 function update(self,varargin)
56 % UPDATE(SELF,VARARGIN)
58 % Update parameters to match the first n central moments
63 if length(varargin) > 3
64 line_warning(mfilename,
'Update in %s distributions can only handle 3 moments, ignoring higher-order moments.\n',
class(self));
68 e3 = -(2*e1^3-3*e1*e2-SKEW*(e2-e1^2)^(3/2));
71 [alpha,T] = APHFrom3Moments([e1,e2,e3]);
73 options = kpcfit_ph_options([e1,e2,e3],
'MinNumStates',2,
'MaxNumStates',2,
'Verbose',
false);
74 ph = kpcfit_ph_auto([e1,e2,e3],options);
76 % the two-state search found nothing; fall back to the
77 % acyclic fitter, which searches the order itself
78 APH = aph_fit(e1,e2,e3);
83 alpha=map_pie(ph{1,1});
87 self.setParam(1,
'alpha', alpha);
88 self.setParam(2,
'T', T);
89 self.process = {T,-T*ones(length(T),1)*alpha};
92 function setMean(self,MEAN)
93 % UPDATEMEAN(SELF,MEAN)
95 % Update parameters to match the given mean
97 ph = map_scale(ph,MEAN);
98 self.setParam(1,
'alpha', map_pie(ph));
99 self.setParam(2,
'T', ph{1});
100 self.process = {T,-T*ones(length(T),1)*self.getInitProb};
103 % function setMeanAndSCV(self, MEAN, SCV)
104 % % UPDATEMEANANDSCV(MEAN, SCV)
106 % % Fit phase-type distribution with given mean and squared coefficient of
107 % % variation (SCV=variance/mean^2)
110 % [alpha,T] = APHFrom2Moments([e1,e2]);
111 % %options = kpcfit_ph_options([e1,e2],
'MinNumStates',2,
'MaxNumStates',2,
'Verbose',
false);
112 % %ph = kpcfit_ph_auto([e1,e2],options);
113 % %[alpha,T]=map2ph(ph{1,1});
115 % alpha=map_pie(ph{1,1});
117 % self.setParam(1,
'alpha', alpha);
118 % self.setParam(2,
'T', T);
119 % self.process = {T,-T*ones(length(T),1)*self.getInitProb};
125function ex = fit(MEAN, SCV, SKEW)
126 % EX = FIT(MEAN, SCV, SKEW)
128 % Fit the distribution from first three standard moments (mean,
130 if MEAN <= GlobalConstants.FineTol
134 ex.update(MEAN, SCV, SKEW);
135 ex.immediate =
false;
139 function ex = fitRawMoments(m1, m2, m3)
141 % Fit the distribution from first three moments
142 if m1 <= GlobalConstants.FineTol
145 % updateFromRawMoments does not exist on PH; convert to the
146 % (mean, SCV, skewness) triple that update does accept
147 SCV = (m2 - m1^2)/m1^2;
148 SKEW = (m3 - 3*m1*m2 + 2*m1^3)/(m2 - m1^2)^(3/2);
150 ex.update(m1, SCV, SKEW);
151 ex.immediate =
false;
155 function ex = fitCentral(MEAN, VAR, SKEW)
156 % EX = FITCENTRAL(MEAN, VAR, SKEW)
158 % Fit the distribution from first three central moments (mean,
159 % variance, skewness)
160 if MEAN <= GlobalConstants.FineTol
164 ex.update(MEAN, VAR/MEAN^2, SKEW);
165 ex.immediate =
false;
169 function ex = fitMeanAndSCV(MEAN, SCV)
170 % EX = FITMEANANDSCV(MEAN, SCV)
172 % Fit the distribution from first three central moments (mean,
173 % variance, skewness)
174 if MEAN <= GlobalConstants.FineTol
179 % Two moments only: take the minimum-skewness third moment of
180 % the acyclic
class, as APH.fitMeanAndSCV does. The SKEW that
181 % used to be referenced here was never a parameter of
this
182 % method, so every call errored.
183 ex = APH.fitMeanAndSCV(MEAN, SCV);
184 ex.immediate =
false;
188 % function ex = fromRepresentation(dep)
189 % % EX = FROMREPRESENTATION(DEP)
191 % % Build a phase-type distribution from a cell array {D0,D1}
193 % ex = PH(map_pie(dep),dep{1});