1function [M2a, M3a] = aph2_adjust(M1, M2, M3, method)
2% Finds feasible values of M2 and M3
for an APH(2) distribution as close as
3% possible to the values provided as an input.
5% M1, M2, M3: the first three moments of the distribution
6% method:
string with the method name, can be one of the following
7% simple (default): [Telek and Heindl, 2002]
8% opt_param: optimize in parameter space
9% opt_param_gads: optimize in parameter space (global)
10% opt_char: optimize in characteristics space
11% opt_char_gads: optimize in characteristics space (global)
13% M2a: adjusted value for M2
14% M3a: adjusted value for M3
20% tolerance for strict inequalities
23if strcmp(method, 'simple')
25 scv = ((M2-M1sq)/M1sq);
27 % (M2 - M1^2)/M1^2 = 1/2
28 % M2 - M1^2 = 1/2 M1^2
31 scva = ((M2a-M1sq)/M1sq);
37 lb = 3*M1^3*(3*scva-1+sqrt(2)*(1-scva)^(3/2));
47 lb = 3/2*M1^3*(1+scva)^2;
54elseif strcmp(method, 'opt_char') || strcmp(method, 'opt_char_gads')
55 % optimize in moment space
56 if strcmp(method, 'opt_char_gads')
57 prob1 = createOptimProblem('fmincon', ...
58 'objective', @fun, ...
62 'nonlcon', @nonlcon1);
63 prob2 = createOptimProblem('fmincon', ...
64 'objective', @fun, ...
68 'nonlcon', @nonlcon2);
69 % adjustment to make the first fit feasible
70 x = run(GlobalSearch('Display','iter'), prob1);
73 % adjustment to make the second fit feasible
74 x = run(GlobalSearch('Display','iter'), prob2);
78 options = optimset('Display', 'iter','Algorithm','active-set');
79 x = fmincon(@fun, [M2 M3], [], [], [], [], [0 0], [], @nonlcon1, options);
82 x = fmincon(@fun, [M2 M3], [], [], [], [], [0 0], [], @nonlcon2, options);
86 % pick the smallest adjustment
87 if norm([M2a1 M3a1] - [M2 M3]) < norm([M2a2 M3a2] - [M2 M3])
94elseif strcmp(method, 'opt_param') || strcmp(method, 'opt_param_gads')
95 % optimize in parameter space
97 degentol = 1e-8; % set to zero to allow exponential
98 x0 = [M1 1/2]; % initial solution that fits M1 exactly
99 lb = [feastol degentol];
100 ub = [inf 1-degentol];
101 if strcmp(method, 'opt_param_gads')
102 prob = createOptimProblem('fmincon', ...
103 'objective', @fun2, ...
107 'nonlcon', @nonlcon3);
108 x = run(GlobalSearch('Display','none'), prob);
110 options = optimset('Display', 'none','Algorithm','active-set');
111 x = fmincon(@fun2, x0, [], [], [], [], lb, ub, @nonlcon3, options);
116 M2a = 2*l1^2 + 2*r1*l1*l2 + 2*r1*l2^2;
117 M3a = 6*l1^3 + 6*r1*l1^2*l2 + 6*r1*l1*l2^2 + 6*r1*l2^3;
119 error('Invalid method: %s', method);
122 function obj = fun2(x)
126 xM2 = 2*l1^2 + 2*r1*l1*l2 + 2*r1*l2^2;
127 xM3 = 6*l1^3 + 6*r1*l1^2*l2 + 6*r1*l1*l2^2 + 6*r1*l2^3;
128 obj = norm([M2 M3] - [xM2 xM3]);
131 function [c, ceq] = nonlcon3(x)
134 c = l2*r1 - M1 + feastol;
138 % minimize euclidean distance to sample values of M2 and M3
139 function obj = fun(x)
140 obj = norm(x - [M2 M3]);
143 function [p1,l1,l2] = aph2_fit1(xM2,xM3)
144 tmp0 = (8*M1^3*xM3)/3 - 3*M1^2*xM2^2 - 2*M1*xM2*xM3 + 2*xM2^3 + xM3^2/9;
146 tmp2 = xM3 - 3*M1*xM2;
147 tmp3 = (6*xM2 - 12*M1^2);
148 l1 = (tmp2 + tmp1)/tmp3;
149 l2 = (tmp2 - tmp1)/tmp3;
153 function [p1,l1,l2] = aph2_fit2(xM2,xM3)
154 tmp0 = (8*M1^3*xM3)/3 - 3*M1^2*xM2^2 - 2*M1*xM2*xM3 + 2*xM2^3 + xM3^2/9;
156 tmp2 = xM3 - 3*M1*xM2;
157 tmp3 = (6*xM2 - 12*M1^2);
158 l1 = (tmp2 - tmp1)/tmp3;
159 l2 = (tmp2 + tmp1)/tmp3;
163 % check feasibility for the first fit
164 function [c, ceq] = nonlcon1(x)
167 [p1,l1,l2] = aph2_fit1(xM2,xM3);
169 c(1) = -tmp0; % non-negative square root argument
170 c(2) = -l1 + 1e-6; % non-negative l1
171 c(3) = -l2 + 1e-6; % non-negative l2
172 c(4) = -p1; % non-negative p1
176 % check feasibility for the second fit
177 function [c, ceq] = nonlcon2(x)
180 [p1,l1,l2] = aph2_fit2(xM2,xM3);
182 c(1) = -tmp0; % non-negative square root argument
183 c(2) = -l1 + 1e-6; % non-negative l1
184 c(3) = -l2 + 1e-6; % non-negative l2
185 c(4) = -p1; % non-negative p1