1function [PH] = kpcfit_ph_auto(E,options)
2% [PH] = kpcfit_ph_auto(E, options)
5% Automatic fit a phase-type (PH) distribution
using exact or approximate
6% moment matching. Approximations are based on the Kronecker Product
7% Composition method (KPC).
10% E - vector of moments, E(k) = E[X^k]
14% PH{i,1}: the i-th fitted PH described as a PH-renewal process specified
15% in the (D0,D1) notation. The (alpha,T) representa
20%
for k=1:16 E(k) = mean(S.^k); end
21% options = kpcfit_ph_options(E,
'MinNumStates',2,
'MaxNumStates',8);
22% [PH]=kpcfit_ph_auto(E,options)
24% i=1; [alpha,T]=map2ph(PH{i,1}) % (alpha,T) distribution of i-th fitted PH
27 fprintf(
'kpcfit_ph: version %s\n',kpcfit_version())
28 fprintf('kpcfit_ph: type "help kpcfit_ph_options" for options\n')
32% scale moments such that E[X]=1
38E = (E(:) ./ Escale(:))';
40%% determine best exact fit -- Prony's method
42 fprintf('\nkpcfit_ph: starting exact fitting methods\n')
44PH_EXACT = kpcfit_ph_exact(E, options);
46%% determine best approximate fit -- moment space
48 fprintf('\nkpcfit_ph: starting approximate fitting method -- moment space (KPC-based)\n')
49 fprintf('\t\t\tRUN\t\tORD\tDIST\t\tRESULT')
54for J = max([2,ceil(log2(options.MinNumStates))]):ceil(log2(options.MaxNumStates)) % for all number of MAPs to compose
61 randomruns = ceil(2*options.Runs/3); % number of runs with random initial point
62 for run = 1:options.Runs
65 fprintf(1,
'\n\t\t\t%dr\t',run); %run number
67 fprintf(1,
'\n\t\t\t%d\t',run); %run number
69 fprintf(1,
'\t%d',2^J); % number of states
72 if run > randomruns && best > 0
73 x0 = PH_APX_MS{bestidx,3}; %x0 = x0 * mean(x0)*1e-2*rand(size(x0));
77 [APX, ~, x] = kpcfit_ph_search(E,J,options,x0);
79 if map_isfeasible(APX)
80 PH_APX_MS = store_result(PH_APX_MS,APX);
83 fprintf(1,
'\t\t\t\tx infeasible result.');
87 % fprintf(1,
'\t\t\t\tx optimization solver failed.');
92%% determine best approximate fit -- parameter space
94SCV = (E(2)-E(1)^2)/E(1)^2;
97 fprintf(
'\n\nkpcfit_ph: starting approximate fitting method -- hyper-exponential parameter space (non-KPC-based)\n')
101 fprintf(
'\t\t\tRUN\t\tORD\tDIST\t\tRESULT')
103 for J = max([2,ceil(log2(options.MinNumStates))]):ceil(log2(options.MaxNumStates)) % for all number of MAPs to compose
110 randomruns = ceil(2*options.Runs/3); % number of runs with random initial point
111 for run = 1:options.Runs
113 fprintf(1,'\n\t\t\t%d\t',run); %run number
114 fprintf(1,'\t%d',2^J); % number of states
117 [APX,~,x] = psfit_hyperexp_weighted(E,2^J);
119 if map_isfeasible(APX)
120 PH_APX_PS = store_result(PH_APX_PS,APX);
123 fprintf(1,'\t\t\t\tinfeasible result.');
128 fprintf(1,'\t\t\t\tx optimization solver failed.');
134 fprintf('\n\nkpcfit_ph: starting approximate fitting method --
aph parameter space (non-KPC-based)\n')
136 fprintf(
'\t\t\tRUN\t\tORD\tDIST\t\tRESULT')
137 for J = max([2,ceil(log2(options.MinNumStates))]):ceil(log2(options.MaxNumStates)) % for all number of MAPs to compose
144 randomruns = ceil(2*options.Runs/3); % number of runs with random initial point
145 for run = 1:options.Runs
146 fprintf(1,'\n\t\t\t%d\t',run); %run number
147 fprintf(1,'\t%d',2^J); % number of states
149 [APX,~,x] = psfit_aph_weighted(E,2^J);
151 if map_isfeasible(APX)
152 PH_APX_PS = store_result(PH_APX_PS,APX);
154 fprintf(1,'\t\t\t\tinfeasible result.');
158 fprintf(1,'\t\t\t\tx optimization solver failed.');
165%% ensure that all returned results match at least the mean
166% PH stays unassigned when neither the exact nor the approximate search finds
167% anything, and MATLAB then reports the opaque "Output argument PH not
168% assigned" from inside this function. Return an empty result instead and let
169% the caller decide, as the other kpctoolbox fitters do.
171nExactResults = size(PH_EXACT,1);
172nApproxMS = size(PH_APX_MS,1);
173%nApproxPS = size(PH_APX_PS,1);
175for j = 1:size(PH_EXACT,1)
176 PH{j,1} = map_scale(PH_EXACT{j},Eunscaled(1));
177 PH{j,2} = dist_fun(E,map_moment(PH_EXACT{j},1:length(E)));
181for j = 1:size(PH_APX_MS,1)
182 PH{nExactResults + j,1} = map_scale(PH_APX_MS{j,1},Eunscaled(1));
183 PH{nExactResults + j,2} = dist_fun(E,map_moment(PH_APX_MS{j,1},1:length(E)));
184 PH{nExactResults + j,3} = PH_APX_MS{j,3};
185 PH{nExactResults + j,4} =
'approx_moment_space';
187for j = 1:size(PH_APX_PS,1)
188 PH{nExactResults + nApproxMS + j,1} = map_scale(PH_APX_PS{j,1},Eunscaled(1));
189 PH{nExactResults + nApproxMS + j,2} = dist_fun(E,map_moment(PH_APX_PS{j,1},1:length(E)));
190 PH{nExactResults + nApproxMS + j,3} = PH_APX_PS{j,3};
191 PH{nExactResults + nApproxMS + j,4} =
'approx_param_space';
195 fprintf(sprintf(
'\n\nReturned %d PH distribution(s) by exact moment matching.',nExactResults));
196 fprintf(sprintf(
'\nReturned %d PH distribution(s) by approximate moment matching (moment space).',size(PH_APX_MS,1)));
197 fprintf(sprintf(
'\nReturned %d PH distribution(s) by approximate moment matching (parameter space).',size(PH_APX_PS,1)));
202 function dist = dist_fun(Eref,Eapx)
204 w = (log10(Eref(end)).^(1/length(Eref))).^-(1:length(Eref));
205 dist = w*abs( log10(Eref) - log10(Eapx) )
'; %%does not work!
208 function PH_APX_MS = store_result(PH_APX_MS,APX)
209 dist = dist_fun(E, map_moment(APX,1:length(E)));
212 fprintf(1,'\t-------- \tx no solution found.
',dist);
216 fprintf(1,'\t%6.6f
',dist);
218 if min([Inf,dist]) < mindist
219 % fprintf(1,'+
',length(PH_APX_MS));
221 PH_APX_MS{end+1,1} = APX;
222 if length(APX{1}) > 2^J
224 fprintf(1,sprintf('\to PH(%d) saved. \t elapsed: %0.3fs [order automatically increased to match second moment]
',length(APX{1}),toc));
228 fprintf(1,sprintf('\to PH(%d) saved. \t elapsed: %0.3fs
',length(APX{1}),toc));
232 PH_APX_MS{end,1} = APX;
234 fprintf(1,sprintf('\t+ PH(%d) updated. \t elapsed: %0.3fs
',length(APX{1}),toc));
238 bestidx = size(PH_APX_MS,1);
239 mindist = min([Inf,dist]);
240 PH_APX_MS{end,2} = dist;
241 PH_APX_MS{end,3} = x;
244 fprintf(1,sprintf('\t\t\t\t\t\t elapsed: %0.3fs
',toc));