LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
amap2_adjust_gamma.m
1function [M2a, M3a, GAMMAa] = amap2_adjust_gamma(M1, M2, M3, GAMMA, weights, method, constraints)
2% Computes a feasible set of characteristics for the MAP(2) that is as
3% close as possible to the desired set of characterstics.
4% Input:
5% - M1,M2,M3: moments of the marginal distribution
6% - GAMMA: auto-correlation decay rate
7% - weights: an optional three-element vector with the weights associated
8% to M2, M3, GAMMA. Default is [10 1 10];
9% - method: the method used to compute the feasible set of characteristics
10% 1) pattern search on M2, M3, GAMMA
11% 2) fit M3 as closely as possible, then perform pattern search
12% on M3, GAMMA (weight of M2 is ignored)
13% 3) (default) prioritize M2, then M3, then GAMMA
14% 4) fit M2 as closely as possible, then perform PSwarm
15% on M3 with bounds [M3_lb(M2), M3_ub(M2)] minimizing the
16% objective function:
17% f(x) = weight(2)*(M3a/M3-1)^2 + weight(3)*(GAMMAa/GAMMA-1)^2
18% where GAMMAa = max(GAMMA_LB(M3a), min(GAMMA, GAMMA_UB(M3a))
19% Output:
20% - M2a,M3a: feasible moments of the marginal distribution (M1 is always
21% feasible)
22% - GAMMAa: feasible auto-correlation decay rate
23
24if nargin == 4 || isempty(weights)
25 % ignored with method 3 and 4
26 weights = [10 1 10];
27end
28
29if nargin <= 5
30 method = 3;
31end
32if nargin <= 6
33 constraints = 2;
34end
35
36if constraints == 1
37 if method == 1
38 nonlcon = @nonlcon_safe;
39 else
40 nonlcon = @nonlcon_safe2;
41 end
42elseif constraints == 2
43 if method == 1
44 nonlcon = @nonlcon_theoretical;
45 else
46 nonlcon = @nonlcon_theoretical2;
47 end
48else
49 error('Invalid option');
50end
51
52if method == 1 || method == 2
53 options = psoptimset;
54 options = psoptimset(options,'MaxIter', 1e5);
55 options = psoptimset(options,'MaxFunEvals', 1e5);
56 options = psoptimset(options,'PollingOrder', 'Success');
57 options = psoptimset(options,'SearchMethod', { @searchneldermead [] [] });
58 options = psoptimset(options,'CompleteSearch', 'on');
59 options = psoptimset(options,'Display', 'iter');
60 options = psoptimset(options,'TolCon', 1e-100);
61end
62
63% tolerance for strict inequalities
64tol = 1e-2;
65
66if method == 1
67 if GAMMA > 0
68 FEASIBLE = map_scale(amap2_assemble(1,1/3,1/2,2/3,1),M1);
69 else
70 FEASIBLE = map_scale(amap2_assemble(1,2/3,1/2,2/3,2),M1);
71 end
72 FM2 = map_moment(FEASIBLE,2);
73 FM3 = map_moment(FEASIBLE,3);
74 FGAMMA = map_acf(FEASIBLE,4)/map_acf(FEASIBLE,3);
75 x = patternsearch(@fun,[FM2 FM3 FGAMMA],[],[],[],[],[0 0 -1],[inf inf, 1-tol], nonlcon, options);
76 M2a = x(1);
77 M3a = x(2);
78 GAMMAa = x(3);
79elseif method == 2
80 % force feasibility of the second moment
81 M2a = max(3/2*M1^2, M2);
82 % find a feasible value of the third moment. The interval must be derived
83 % from the ADJUSTED second moment: with the unadjusted M2 the branch test
84 % and the bound formulas below refer to a normalized moment the search is
85 % not constrained to, which can return an inverted interval and abort
86 % nonlcon_theoretical2 with a complex constraint value.
87 n2 = M2a/(M1^2);
88 p2 = 3*(n2-2)/(3*n2) * (-2*sqrt(3)/sqrt(12-6*n2) - 1);
89 a2 = (n2-2)/(p2*(1-n2) + sqrt(p2^2 + (2*p2*(n2-2))));
90 l2 = 3*(a2+1)/(a2*p2+1) - (6*a2)/(2+a2*p2*(2*a2+2));
91 u2 = 6*(n2-1)/n2;
92 if 3/2 <= n2 && n2 < 2
93 FM3 = (l2 + (u2-l2)/2) * M1* M2a;
94 M3_LB = l2 * M1 * M2a;
95 M3_UB = u2 * M1 * M2a;
96 else
97 FM3 = (3/2) * M2a^2 / M1 + tol;
98 M3_LB = FM3;
99 M3_UB = inf;
100 end
101 % null decay rate is always feasible
102 FGAMMA = 0;
103 % find best feasible values of M3 and GAMMA
104 x = patternsearch(@fun2,[FM3 FGAMMA],[],[],[],[],[M3_LB -1],[M3_UB, 1-tol], nonlcon, options);
105 %x = fmincon(@fun2,[FM3 FGAMMA],[],[],[],[],[M3_LB -1],[M3_UB, 1], nonlcon);
106 M3a = x(1);
107 GAMMAa = x(2);
108elseif method == 3
109 % priorities are M2 > M3 > GAMMA
110 [M2a,M3a] = aph2_adjust(M1, M2, M3);
111 [lb, ub] = compute_gamma_bounds(M2a, M3a);
112 GAMMAa = max(lb, min(GAMMA, ub));
113elseif method == 4
114 % priorities are M2 > GAMMA > M3
115 % adjust second moment
116 M1sq = M1^2;
117 scv = ((M2-M1sq)/M1sq);
118 if scv < 1/2
119 % (M2 - M1^2)/M1^2 = 1/2
120 % M2 - M1^2 = 1/2 M1^2
121 % M2 = 3/2 M1^2
122 M2a = 3/2 * M1^2;
123 scva = ((M2a-M1sq)/M1sq);
124 else
125 M2a = M2;
126 scva = scv;
127 end
128 % get bounds on third moment
129 if scva <= 1
130 M3_lb = 3*M1^3*(3*scva-1+sqrt(2)*(1-scva)^(3/2));
131 M3_ub = 6*M1^3*scva;
132 elseif scva > 1
133 M3_lb = 3/2*M1^3*(1+scva)^2;
134 M3_ub = inf;
135 end
136 % compute M3a and GAMMAa
137 if abs(M3_lb - M3_ub) < tol
138 % exponential
139 M3a = (M3_lb + M3_ub)/2;
140 GAMMAa = 0;
141 else
142 % optimization problem formulation
143 problem.Variables = 1;
144 problem.LB = M3_lb + tol;
145 problem.UB = M3_ub;
146 problem.ObjFunction = @gamma_objective;
147 M3a = PSwarm(problem);
148 % compute adjusted gamma
149 [lb, ub] = compute_gamma_bounds(M2a, M3a);
150 GAMMAa = max(lb, min(GAMMA, ub));
151 end
152else
153 error('Invalid method for adjusting AMAP(2) characteristics');
154end
155
156 function obj = gamma_objective(M3a)
157 [lb,ub] = compute_gamma_bounds(M2a, M3a);
158 GAMMAa = max(lb, min(GAMMA, ub));
159 obj = weights(2) * (M3a/M3-1)^2 + weights(3) * (GAMMAa/GAMMA-1)^2;
160 end
161
162 function [lb, ub] = compute_gamma_bounds(M2a, M3a)
163 N2a = M2a/(M1)^2;
164 N3a = M3a/(M2a*M1);
165 if N2a < 2
166 lb = -(N2a*(N3a-6)+6)/(3*N2a-6);
167 ub = -(2* (0.5*(N2a-2)+0.5*sqrt(N2a^2 - 2*N2a*N3a/3))^2 )/(N2a-2);
168 ub = ub * (1 - tol);
169 elseif N3a < 9 - 12/N2a
170 lb = -(N2a*(N3a-6)+6)/(3*N2a-6);
171 ub = 1-tol;
172 else
173 x1 = sqrt(N2a*(N2a*(18*N2a+N3a*(N3a-18)-27)+24*N3a));
174 x2 = N2a*(N3a-9);
175 lb = (x2-x1+12)/(x2+x1+12);
176 ub = 1-tol;
177 end
178 end
179
180 function obj = fun(x)
181 v = (x - [M2 M3 GAMMA]) ./ [M2 M3 GAMMA] .* weights;
182 obj = norm(v);
183 end
184
185 function obj = fun2(x)
186 v = (x - [M3 GAMMA]) ./ [M3 GAMMA] .* weights(2:3);
187 obj = norm(v);
188 end
189
190 function [c, ceq] = nonlcon_safe(x)
191 xM2 = x(1);
192 xM3 = x(2);
193 xGAMMA = x(3);
194 AMAPS = amap2_fit_decay(M1,xM2,xM3,xGAMMA);
195 if isempty(AMAPS)
196 c = 1;
197 else
198 c = 0;
199 end
200 ceq = [];
201 end
202
203 function [c, ceq] = nonlcon_safe2(x)
204 xM3 = x(1);
205 xGAMMA = x(2);
206 AMAPS = amap2_fit_decay(M1,M2,xM3,xGAMMA);
207 if isempty(AMAPS)
208 c = 1;
209 else
210 c = 0;
211 end
212 ceq = [];
213 end
214
215 function [c, ceq] = nonlcon_theoretical(x)
216 xM2 = x(1);
217 xM3 = x(2);
218 xGAMMA = x(3);
219
220 % compute normalized moments
221 n2 = xM2/(M1^2);
222 n3 = xM3/(M1*xM2);
223
224 %m3a_printf('M1 = %f, M2 = %f, M3 = %f, GAMMA = %f\n', M1, xM2, xM3, xGAMMA);
225 %m3a_printf('n2 = %f, n3 = %f\n', n2, n3);
226
227 % simplifying notations for moments bounds. The formulas are only
228 % defined on 3/2 <= n2 < 2, so evaluate them at a CLAMPED n2: an
229 % iterate below 3/2 (which constraint 1 is there to push back) or at
230 % exactly 2 would otherwise leave the third-moment rows at zero, and
231 % M3 would be unconstrained while constraint 1 is satisfied to solver
232 % tolerance. Observed: the search returning n2 = 3/2 - 1.3e-11 with
233 % n3 = 0.795, where the only admissible n3 is 2.
234 n2b = min(max(n2, 3/2), 2 - 1e-12);
235 p2 = 3*(n2b-2)/(3*n2b) * (-2*sqrt(3)/sqrt(12-6*n2b) - 1);
236 a2 = (n2b-2)/(p2*(1-n2b) + sqrt(p2^2 + (2*p2*(n2b-2))));
237 l2 = 3*(a2+1)/(a2*p2+1) - (6*a2)/(2+a2*p2*(2*a2+2));
238 u2 = 6*(n2b-1)/n2b;
239
240 %if (M2-M1^2)/M1^2 == 1
241 % m3a_printf('Exponential\n');
242 %end
243
244 eps = 1e-8;
245
246 c = zeros(5,1);
247 % CONSTRAINT 1: 3/2 <= n
248 c(1) = 3/2 - n2;
249 if n2 <= 2
250 % CONSTRAINT 2: l2 <= n3
251 % CONSTRAINT 3: n3 <= u2
252 c(2) = l2 - n3;
253 c(3) = n3 - u2;
254 else
255 % CONSTRAINT 2: 3/2 n2 < n3
256 % CONSTRAINT 3: disabled
257 c(2) = 3/2 * n2 - n3 + eps;
258 c(3) = 0;
259 end
260
261 % BOUNDS FOR AUTOCORRELATION DECAY
262 lb1 = -(n2*(n3-6)+6)/(3*n2-6);
263 ub1 = -(2*(1/2*(n2-2)+1/2*sqrt(n2^2-(2*n2*n3)/3))^2)/(n2-2);
264 tmp1 = n2*(n3-9);
265 tmp2 = sqrt(n2*(n2*(18*n2+n3*(n3-18)-27)+24*n3));
266 lb2 = (tmp1-tmp2+12)/(tmp1+tmp2+12);
267 %m3a_printf('LB1 = %f, LB2 = %f\n', lb1, lb2);
268 if n2 < 2
269 %m3a_printf('LB1 <= gamma: %d\n', lb1 <= xGAMMA);
270 %m3a_printf('gamma <= UB: %d\n', xGAMMA <= ub1);
271 c(4) = lb1 - xGAMMA;
272 c(5) = xGAMMA - ub1;
273 elseif n2 > 2 && n3 < 9 - 12/n2
274 %m3a_printf('LB1 <= gamma: %d\n', lb1 <= xGAMMA);
275 %m3a_printf('gamma <= 1: %d\n', xGAMMA <= 1);
276 c(4) = lb1 - xGAMMA;
277 c(5) = xGAMMA - 1;
278 elseif n2 > 2 && n3 >= 9 - 12/n2
279 %m3a_printf('LB2 <= gamma: %d\n', lb2 <= xGAMMA);
280 %m3a_printf('gamma <= 1: %d\n', xGAMMA <= 1);
281 c(4) = lb2 - xGAMMA;
282 c(5) = xGAMMA - 1;
283 end
284
285 ceq = [];
286
287 end
288
289 function [c, ceq] = nonlcon_theoretical2(x)
290
291 xM3 = x(1);
292 xGAMMA = x(2);
293
294 % compute normalized moments, from the ADJUSTED second moment that the
295 % bound interval was built on
296 n2 = M2a/(M1^2);
297 n3 = xM3/(M1*M2a);
298
299 % M3 is always feasible because of the bound constraints
300
301 % BOUNDS FOR AUTOCORRELATION DECAY
302 lb1 = -(n2*(n3-6)+6)/(3*n2-6);
303 ub1 = -(2*(1/2*(n2-2)+1/2*sqrt(n2^2-(2*n2*n3)/3))^2)/(n2-2);
304 tmp1 = n2*(n3-9);
305 tmp2 = sqrt(n2*(n2*(18*n2+n3*(n3-18)-27)+24*n3));
306 lb2 = (tmp1-tmp2+12)/(tmp1+tmp2+12);
307 %m3a_printf('LB1 = %f, LB2 = %f\n', lb1, lb2);
308 if n2 < 2
309 %m3a_printf('LB1 <= gamma: %d\n', lb1 <= xGAMMA);
310 %m3a_printf('gamma <= UB: %d\n', xGAMMA <= ub1);
311 c(4) = lb1 - xGAMMA;
312 c(5) = xGAMMA - ub1;
313 elseif n2 > 2 && n3 < 9 - 12/n2
314 %m3a_printf('LB1 <= gamma: %d\n', lb1 <= xGAMMA);
315 %m3a_printf('gamma <= 1: %d\n', xGAMMA <= 1);
316 c(4) = lb1 - xGAMMA;
317 c(5) = xGAMMA - 1;
318 elseif n2 > 2 && n3 >= 9 - 12/n2
319 %m3a_printf('LB2 <= gamma: %d\n', lb2 <= xGAMMA);
320 %m3a_printf('gamma <= 1: %d\n', xGAMMA <= 1);
321 c(4) = lb2 - xGAMMA;
322 c(5) = xGAMMA - 1;
323 end
324
325 ceq = [];
326
327 end
328
329end