LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
PHFromTrace.m
1% [alpha, A, logli] = PHFromTrace(trace, orders, maxIter, stopCond, initial, result)
2%
3% Performs PH distribution fitting using the EM algorithm
4% (G-FIT, [1]_).
5%
6% Parameters
7% ----------
8% trace : column vector, length K
9% The samples of the trace
10% orders : list of int, length(N), or int
11% The length of the list determines the number of
12% Erlang branches to use in the fitting method.
13% The entries of the list are the orders of the
14% Erlang distributions. If this parameter is a
15% single integer, all possible branch number - order
16% combinations are tested where the total number of
17% states is "orders".
18% maxIter : int, optional
19% Maximum number of iterations. The default value is
20% 200
21% stopCond : double, optional
22% The algorithm stops if the relative improvement of
23% the log likelihood falls below stopCond. The
24% default value is 1e-7
25% initial : tuple of two vectors, optional
26% The initial values of the branch probabilities and
27% rate parameters is given by this tuple. If not
28% given, a default initial guess is determined and
29% the algorithm starts from there.
30% result : {"vecmat", "vecvec"}, optional
31% The result can be returned two ways. If "vecmat" is
32% selected, the result is returned in the classical
33% representation of phase-type distributions, thus the
34% initial vector and the generator matrix.
35% If "vecvec" is selected, two vectors are returned,
36% one holds the branch probabilities, and the second
37% holds the rate parameters of the Erlang branches.
38% The default value is "vecmat"
39%
40% Returns
41% -------
42% (alpha, A) : tuple of matrix, shape (1,M) and matrix, shape (M,M)
43% If the "vecmat" result format is chosen, the function
44% returns the initial probability vector and the
45% generator matrix of the phase type distribution.
46% (pi, lambda) : tuple of vector, length N and vector, length N
47% If the "vecvec" result format is chosen, the function
48% returns the vector of branch probabilities and the
49% vector of branch rates in a tuple.
50% logli : double
51% The log-likelihood divided by the trace length
52%
53% Notes
54% -----
55% This procedure is quite fast in the supported
56% mathematical frameworks. If the maximum speed is
57% needed, please use the multi-core optimized c++
58% implementation called SPEM-FIT_.
59%
60% .. _SPEM-FIT: https://bitbucket.org/ghorvath78/spemfit
61%
62% References
63% ----------
64% .. [1] Thummler, Axel, Peter Buchholz, and Miklós Telek.
65% A novel approach for fitting probability
66% distributions to real trace data with the EM
67% algorithm. Dependable Systems and Networks, 2005.
68
69function [alpha, A, logli] = PHFromTrace (trace, orders, maxIter, stopCond, initial, result)
70
71 if ~exist('maxIter','var') || isempty(maxIter)
72 maxIter = 200;
73 end
74 if ~exist('stopCond','var') || isempty(stopCond)
75 stopCond = 1e-7;
76 end
77 if ~exist('initial','var')
78 initial = {};
79 end
80 if ~exist('result','var') || isempty(result)
81 result = 'vecmat';
82 end
83 global BuToolsVerbose;
84
85 function o = allorders (branches, sumorders)
86 if branches==1
87 o={sumorders};
88 else
89 o = {};
90 for ii=1:sumorders-branches+1
91 x = allorders (branches-1, sumorders-ii);
92 for j=1:length(x)
93 xt = sort([x{j} ii]);
94 % check if we have it already
95 found=false;
96 for ok=1:length(o)
97 if o{ok}==xt
98 found=true;
99 break;
100 end
101 end
102 if ~found
103 o{length(o)+1}=xt;
104 end
105 end
106 end
107 end
108 end
109
110 if length(orders)==1
111 bestAlpha = [];
112 bestA = [];
113 bestLogli = -inf;
114 bestOrders= [];
115 for br=2:orders
116 allord = allorders (br, orders);
117 for ox=1:length(allord)
118 [a,A,l] = PHFromTrace (trace, allord{ox}, maxIter, stopCond, initial, result);
119 if l > bestLogli
120 bestAlpha = a;
121 bestA = A;
122 bestLogli = l;
123 bestOrders = allord{ox};
124 end
125 end
126 end
127 alpha = bestAlpha;
128 A = bestA;
129 logli = bestLogli;
130 if BuToolsVerbose
131 fprintf('Best solution: logli=%g, orders=', bestLogli);
132 for i=1:length(bestOrders)
133 fprintf('%g',bestOrders(i));
134 if i<length(bestOrders)
135 fprintf(',');
136 else
137 fprintf('\n');
138 end
139 end
140 end
141 return;
142 end
143
144 M = length(orders);
145 K = length(trace);
146
147 % initial alpha and lambda is such that the mean is matched
148 if isempty(initial)
149 alphav = ones(1,M) / M;
150 lambda = diag(orders) * (1:M)';
151 trm = sum(trace)/length(trace);
152 inim = sum(alphav ./ (1:M));
153 lambda = lambda * inim / trm;
154 elseif length(initial)==2
155 if length(initial{1})==M && length(initial{2})==M
156 alphav = reshape(initial{1},1,M);
157 lambda = reshape(initial{2},M,1);
158 else
159 error('The length of the initial branch probability and rate vectors is not consistent with the length of the orders vector!');
160 end
161 else
162 error('Invalid initial branch probability and rate vectors!');
163 end
164
165 Q = zeros(M, K);
166 ologli = 1;
167 logli = 0;
168 steps = 1;
169 t1 = clock();
170 while abs((ologli-logli)/logli)>stopCond && steps<=maxIter
171 ologli = logli;
172 % E-step:
173 for i=1:M
174 Q(i,:) = (alphav(i)*(lambda(i)*trace).^(orders(i)-1) / factorial(orders(i)-1) * lambda(i)) .* exp(-lambda(i)*trace);
175 end
176 logli = sum(log(sum(Q,1))) / K;
177 nor = sum(Q,1);
178 for i=1:M
179 Q(i,:) = Q(i,:) ./ nor;
180 end
181 % M-step:
182 v1 = sum(Q,2);
183 v2 = Q*trace;
184 alphav = v1'/K;
185 lambda = diag(orders)*v1 ./ v2;
186 steps = steps+1;
187 if BuToolsVerbose && etime(clock(),t1)>2
188 fprintf('Num of iterations: %d, logli: %g\n', steps, logli);
189 t1 = clock();
190 end
191 end
192
193 if BuToolsVerbose
194 fprintf('Num of iterations: %d, logli: %g\n', steps, logli);
195 fprintf('EM algorithm terminated. (orders=');
196 for i=1:M
197 fprintf('%g',orders(i));
198 if i<M
199 fprintf(',');
200 else
201 fprintf(')\n');
202 end
203 end
204 end
205
206 if strcmp(result,'vecvec')
207 alpha = alphav;
208 A = lambda;
209 elseif strcmp(result,'vecmat')
210 N = sum(orders);
211 alpha = zeros(1,N);
212 A = zeros (N);
213 ix = 1;
214 for i=1:M
215 alpha(ix) = alphav(i);
216 A(ix:ix+orders(i)-1, ix:ix+orders(i)-1) = lambda(i)*(diag(ones(1,orders(i)-1),1)-diag(ones(1,orders(i))));
217 ix = ix + orders(i);
218 end
219 end
220end
221