LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
aph2_adjust.m
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.
4% 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)
12% Output:
13% M2a: adjusted value for M2
14% M3a: adjusted value for M3
15
16if nargin < 4
17 method = 'simple';
18end
19
20% tolerance for strict inequalities
21tol = 1e-4;
22
23if strcmp(method, 'simple')
24 M1sq = M1^2;
25 scv = ((M2-M1sq)/M1sq);
26 if scv < 1/2
27 % (M2 - M1^2)/M1^2 = 1/2
28 % M2 - M1^2 = 1/2 M1^2
29 % M2 = 3/2 M1^2
30 M2a = 3/2 * M1^2;
31 scva = ((M2a-M1sq)/M1sq);
32 else
33 M2a = M2;
34 scva = scv;
35 end
36 if scva <= 1
37 lb = 3*M1^3*(3*scva-1+sqrt(2)*(1-scva)^(3/2));
38 ub = 6*M1^3*scva;
39 if M3 < lb
40 M3a = lb;
41 elseif M3 > ub
42 M3a = ub;
43 else
44 M3a = M3;
45 end
46 else
47 lb = 3/2*M1^3*(1+scva)^2;
48 if M3 <= lb
49 M3a = lb * (1 + tol);
50 else
51 M3a = M3;
52 end
53 end
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, ...
59 'x0', [M2 M3], ...
60 'lb', [0 0], ...
61 'ub', [inf inf], ...
62 'nonlcon', @nonlcon1);
63 prob2 = createOptimProblem('fmincon', ...
64 'objective', @fun, ...
65 'x0', [M2 M3], ...
66 'lb', [0 0], ...
67 'ub', [inf inf], ...
68 'nonlcon', @nonlcon2);
69 % adjustment to make the first fit feasible
70 x = run(GlobalSearch('Display','iter'), prob1);
71 M2a1 = x(1);
72 M3a1 = x(2);
73 % adjustment to make the second fit feasible
74 x = run(GlobalSearch('Display','iter'), prob2);
75 M2a2 = x(1);
76 M3a2 = x(2);
77 else
78 options = optimset('Display', 'iter','Algorithm','active-set');
79 x = fmincon(@fun, [M2 M3], [], [], [], [], [0 0], [], @nonlcon1, options);
80 M2a1 = x(1);
81 M3a1 = x(2);
82 x = fmincon(@fun, [M2 M3], [], [], [], [], [0 0], [], @nonlcon2, options);
83 M2a2 = x(1);
84 M3a2 = x(2);
85 end
86 % pick the smallest adjustment
87 if norm([M2a1 M3a1] - [M2 M3]) < norm([M2a2 M3a2] - [M2 M3])
88 M2a = M2a1;
89 M3a = M3a1;
90 else
91 M2a = M2a2;
92 M3a = M3a2;
93 end
94elseif strcmp(method, 'opt_param') || strcmp(method, 'opt_param_gads')
95 % optimize in parameter space
96 feastol = 1e-6;
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, ...
104 'x0', x0, ...
105 'lb', lb, ...
106 'ub', ub, ...
107 'nonlcon', @nonlcon3);
108 x = run(GlobalSearch('Display','none'), prob);
109 else
110 options = optimset('Display', 'none','Algorithm','active-set');
111 x = fmincon(@fun2, x0, [], [], [], [], lb, ub, @nonlcon3, options);
112 end
113 l2 = x(1);
114 r1 = x(2);
115 l1 = M1 - l2*r1;
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;
118else
119 error('Invalid method: %s', method);
120end
121
122 function obj = fun2(x)
123 l2 = x(1);
124 r1 = x(2);
125 l1 = M1 - l2*r1;
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]);
129 end
130
131 function [c, ceq] = nonlcon3(x)
132 l2 = x(1);
133 r1 = x(2);
134 c = l2*r1 - M1 + feastol;
135 ceq = [];
136 end
137
138 % minimize euclidean distance to sample values of M2 and M3
139 function obj = fun(x)
140 obj = norm(x - [M2 M3]);
141 end
142
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;
145 tmp1 = 3*sqrt(tmp0);
146 tmp2 = xM3 - 3*M1*xM2;
147 tmp3 = (6*xM2 - 12*M1^2);
148 l1 = (tmp2 + tmp1)/tmp3;
149 l2 = (tmp2 - tmp1)/tmp3;
150 p1 = (M1 - l1)/l2;
151 end
152
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;
155 tmp1 = 3*sqrt(tmp0);
156 tmp2 = xM3 - 3*M1*xM2;
157 tmp3 = (6*xM2 - 12*M1^2);
158 l1 = (tmp2 - tmp1)/tmp3;
159 l2 = (tmp2 + tmp1)/tmp3;
160 p1 = (M1 - l1)/l2;
161 end
162
163 % check feasibility for the first fit
164 function [c, ceq] = nonlcon1(x)
165 xM2 = x(1);
166 xM3 = x(2);
167 [p1,l1,l2] = aph2_fit1(xM2,xM3);
168 c = zeros(4,1);
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
173 ceq = [];
174 end
175
176 % check feasibility for the second fit
177 function [c, ceq] = nonlcon2(x)
178 xM2 = x(1);
179 xM3 = x(2);
180 [p1,l1,l2] = aph2_fit2(xM2,xM3);
181 c = zeros(4,1);
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
186 ceq = [];
187 end
188
189end