LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
amap2_adjust_gamma.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_MAM_AMAP2_ADJUST_GAMMA_H
6#define LINE_API_MAM_AMAP2_ADJUST_GAMMA_H
7
8/**
9 * @file
10 * @ingroup api_mam
11 * Nearest AMAP(2)-feasible (M2, M3, GAMMA)
12 * (matlab/lib/m3a/m3a/amap2/amap2_adjust_gamma.m).
13 *
14 * M1 is always feasible on its own, so only the second and third moments and
15 * the autocorrelation decay rate GAMMA are adjusted. The reference offers four
16 * methods, which trade fidelity between the three characteristics:
17 *
18 * 1 joint search over (M2, M3, GAMMA) minimizing the weighted relative
19 * deviation, subject to the theoretical AMAP(2) feasibility region;
20 * 2 M2 forced feasible in closed form, then a search over (M3, GAMMA);
21 * 3 (the reference default) strict priority M2 > M3 > GAMMA: apply the
22 * closed-form APH(2) adjustment of aph2_adjust to (M2, M3), then clamp
23 * GAMMA into the interval that pair admits. No optimizer at all;
24 * 4 strict priority M2 > GAMMA > M3: M2 is forced feasible, then M3 is
25 * chosen inside its feasible interval to minimize a weighted objective in
26 * which GAMMA is always clamped to the interval implied by M3.
27 *
28 * The feasibility region and the GAMMA interval are those of Casale, Zhang
29 * and Smirni's AMAP(2) characterization, transcribed from the reference's
30 * compute_gamma_bounds and nonlcon_theoretical.
31 *
32 * ACCEPTANCE CONTRACT (see line/util/auglag.h). Methods 1 and 2 are driven in
33 * MATLAB by patternsearch (a direct-search method with a Nelder-Mead search
34 * step) and method 4 by PSwarm, a stochastic particle swarm. This port uses
35 * the augmented Lagrangian with a simplex inner solver for 1 and 2, and a
36 * deterministic multi-start bounded simplex search for 4. None of these
37 * reproduce the reference's iterates, and PSwarm in particular is not
38 * reproducible even against itself. What is guaranteed and tested is the
39 * specification:
40 * 1. the returned triple satisfies the AMAP(2) feasibility conditions, so
41 * amap2_fitall_gamma admits at least one solution for it;
42 * 2. an input that is already feasible is returned unchanged by every
43 * method (objective zero);
44 * 3. the achieved objective -- the reference's own weighted relative
45 * deviation -- is returned in Amap2AdjustGammaResult::objective so it can
46 * be compared against any other optimizer's on the same input.
47 *
48 * ON THE `constraints` ARGUMENT. The reference selects between two constraint
49 * sets: constraints = 2 (default) is the theoretical characterization used
50 * here, and constraints = 1 replaces it by the indicator
51 * "amap2_fit_decay returns something", a zero/one function of x. That
52 * indicator is discontinuous, has zero gradient wherever it is defined, and
53 * carries no information about the direction of feasibility; it is usable by
54 * patternsearch only because a direct-search poll needs no derivative. It is
55 * NOT ported: an augmented Lagrangian on a 0/1 constraint degenerates into an
56 * unguided penalty. Requesting it raises UnsupportedError rather than silently
57 * substituting the theoretical set (which is what the JAR does -- it accepts
58 * the argument and ignores it).
59 *
60 * Gated on transcendental arithmetic: square roots in the bounds and
61 * tolerance-driven optimization.
62 */
63
64#include <cstddef>
65#include <vector>
66
72#include "line/num/number.h"
73#include "line/util/auglag.h"
74#include "line/util/error.h"
76
77namespace line {
78namespace mam {
79
80/** Result of amap2_adjust_gamma. */
81template <class T>
83 T M2a;
84 T M3a;
86 T objective; ///< the reference's weighted relative deviation at the answer
87 bool feasible;///< the returned triple satisfies the AMAP(2) conditions
88};
89
90namespace fitdetail {
91
92/** The interval of feasible GAMMA for a given (M1, M2a, M3a); compute_gamma_bounds. */
93template <class T>
94void amap2_gamma_bounds(const T& M1, const T& M2a, const T& M3a, const T& tol, T& lb, T& ub) {
95 const T one = num_traits<T>::from_int(1);
96 const T two = num_traits<T>::from_int(2);
97 const T three = num_traits<T>::from_int(3);
98 const T six = num_traits<T>::from_int(6);
99 const T nine = num_traits<T>::from_int(9);
100 const T twelve = num_traits<T>::from_int(12);
101 const T eighteen = num_traits<T>::from_int(18);
102 const T twentyfour = num_traits<T>::from_int(24);
103 const T twentyseven = num_traits<T>::from_int(27);
104 const T half = num_traits<T>::from_rational(1, 2);
105 const T zero = num_traits<T>::from_int(0);
106
107 const T N2a = M2a / (M1 * M1);
108 const T N3a = M3a / (M2a * M1);
109
110 if (N2a < two) {
111 lb = -(N2a * (N3a - six) + six) / (three * N2a - six);
112 const T disc = N2a * N2a - two * N2a * N3a / three;
113 const T root = disc > zero ? num_sqrt(disc) : zero;
114 const T inner = half * (N2a - two) + half * root;
115 ub = -(two * inner * inner) / (N2a - two);
116 ub = ub * (one - tol);
117 } else if (N3a < nine - twelve / N2a) {
118 lb = -(N2a * (N3a - six) + six) / (three * N2a - six);
119 ub = one - tol;
120 } else {
121 const T inner = N2a * (eighteen * N2a + N3a * (N3a - eighteen) - twentyseven) +
122 twentyfour * N3a;
123 const T arg = N2a * inner;
124 const T x1 = arg > zero ? num_sqrt(arg) : zero;
125 const T x2 = N2a * (N3a - nine);
126 lb = (x2 - x1 + twelve) / (x2 + x1 + twelve);
127 ub = one - tol;
128 }
129}
130
131/**
132 * The reference's nonlcon_theoretical: five inequalities c <= 0 expressing
133 * AMAP(2) feasibility of (M2, M3, GAMMA) at a fixed M1. Rows 2 and 3 are the
134 * third-moment bounds, whose form differs on either side of N2 = 2; rows 4 and
135 * 5 are the GAMMA interval.
136 *
137 * REFERENCE DEFECT (matlab/lib/m3a/m3a/amap2/amap2_adjust_gamma.m,
138 * nonlcon_theoretical): the third-moment rows are written as
139 * if 3/2 <= n2 && n2 < 2 ... elseif n2 > 2 ...
140 * with no else, and c is preallocated to zeros(5,1). For n2 BELOW 3/2, and at
141 * n2 EXACTLY 2, neither branch runs and rows 2 and 3 stay at zero -- that is,
142 * the third moment is left completely unconstrained. Row 1 (3/2 - n2 <= 0) is
143 * the only thing pushing n2 up, and it is satisfied as soon as the deficit is
144 * below the solver's constraint tolerance, at which point any n3 whatsoever is
145 * declared feasible. Reproduction with this port's optimizer, before the
146 * repair below: minimizing the weighted deviation from
147 * (M1, M2, M3, GAMMA) = (1, 1.3, 2, 0.5) returns
148 * (M2a, M3a, GAMMAa) = (1.4999999999870, 1.19265, 0.49871) with objective
149 * 1.591 -- n2 is 1.3e-11 short of 3/2, so rows 2 and 3 vanish and the third
150 * moment settles at n3 = 0.795 where the only APH(2) with n2 = 3/2 has
151 * n3 = 2 exactly. The objective beats every genuinely feasible point.
152 *
153 * The repair is to evaluate the third-moment bounds at n2 CLAMPED into the
154 * region, max(n2, 3/2), and to use the n2 > 2 form at n2 = 2 as well, so that
155 * the rows are defined everywhere and continuous across both junctions. Row 1
156 * still carries the n2 >= 3/2 requirement itself. MATLAB was NOT edited.
157 */
158template <class T>
159std::vector<T> amap2_feasibility(const T& M1, const T& xM2, const T& xM3, const T& xGAMMA) {
160 const T zero = num_traits<T>::from_int(0);
161 const T one = num_traits<T>::from_int(1);
162 const T two = num_traits<T>::from_int(2);
163 const T three = num_traits<T>::from_int(3);
164 const T six = num_traits<T>::from_int(6);
165 const T nine = num_traits<T>::from_int(9);
166 const T twelve = num_traits<T>::from_int(12);
167 const T eighteen = num_traits<T>::from_int(18);
168 const T twentyfour = num_traits<T>::from_int(24);
169 const T twentyseven = num_traits<T>::from_int(27);
170 const T half = num_traits<T>::from_rational(1, 2);
171 const T threehalf = num_traits<T>::from_rational(3, 2);
172 const T eps = num_traits<T>::from_double(1e-8);
173
174 const T n2 = xM2 / (M1 * M1);
175 const T n3 = xM3 / (M1 * xM2);
176
177 std::vector<T> c(5, zero);
178 c[0] = threehalf - n2;
179
180 // n2 clamped into the region, so that rows 1 and 2 below are defined for
181 // every argument; see the reference-defect note above
182 const T n2c = n2 < threehalf ? threehalf : n2;
183 if (n2c < two) {
184 // the reference's p2, a2, l2, u2; all real only for n2 < 2, which is
185 // why they are evaluated inside this branch alone
186 const T p2 = three * (n2c - two) / (three * n2c) *
187 (-two * num_sqrt(three) / num_sqrt(T(twelve - six * n2c)) - one);
188 const T inner = p2 * p2 + two * p2 * (n2c - two);
189 const T a2 = (n2c - two) / (p2 * (one - n2c) + (inner > zero ? num_sqrt(inner) : zero));
190 const T l2 = three * (a2 + one) / (a2 * p2 + one) -
191 six * a2 / (two + a2 * p2 * (two * a2 + two));
192 const T u2 = six * (n2c - one) / n2c;
193 c[1] = l2 - n3;
194 c[2] = n3 - u2;
195 } else {
196 c[1] = threehalf * n2c - n3 + eps;
197 c[2] = zero;
198 }
199
200 const T lb1 = -(n2 * (n3 - six) + six) / (three * n2 - six);
201 const T disc = n2 * n2 - two * n2 * n3 / three;
202 const T root1 = disc > zero ? num_sqrt(disc) : zero;
203 const T innerub = half * (n2 - two) + half * root1;
204 const T ub1 = -(two * innerub * innerub) / (n2 - two);
205 const T tmp1 = n2 * (n3 - nine);
206 const T arg2 = n2 * (n2 * (eighteen * n2 + n3 * (n3 - eighteen) - twentyseven) +
207 twentyfour * n3);
208 const T tmp2 = arg2 > zero ? num_sqrt(arg2) : zero;
209 const T lb2 = (tmp1 - tmp2 + twelve) / (tmp1 + tmp2 + twelve);
210
211 if (n2 < two) {
212 c[3] = lb1 - xGAMMA;
213 c[4] = xGAMMA - ub1;
214 } else if (n3 < nine - twelve / n2) {
215 c[3] = lb1 - xGAMMA;
216 c[4] = xGAMMA - one;
217 } else {
218 c[3] = lb2 - xGAMMA;
219 c[4] = xGAMMA - one;
220 }
221 return c;
222}
223
224} // namespace fitdetail
225
226/**
227 * Is (M1, M2, M3, GAMMA) AMAP(2)-feasible? The predicate behind the
228 * acceptance criterion of every method here; it is the reference's own
229 * nonlcon_theoretical, evaluated rather than optimized.
230 */
231template <class T>
232bool amap2_gamma_feasible(const T& M1, const T& M2, const T& M3, const T& GAMMA, const T& slack) {
233 const std::vector<T> c = fitdetail::amap2_feasibility(M1, M2, M3, GAMMA);
234 for (std::size_t i = 0; i < c.size(); ++i)
235 if (c[i] > slack) return false;
236 return true;
237}
238
239/**
240 * Nearest AMAP(2)-feasible characteristics.
241 *
242 * @param M1,M2,M3,GAMMA the requested characteristics
243 * @param weights the three weights on (M2, M3, GAMMA); the reference
244 * default is (10, 1, 10). Ignored by methods 3 and 4's
245 * first component, exactly as in the reference
246 * @param method 1..4, see the header comment; the reference default 3
247 * @param constraints 2 for the theoretical region (the only one ported);
248 * 1 raises UnsupportedError
249 * @param tol the strict-inequality slack, the reference's 1e-2
250 */
251template <class T>
252Amap2AdjustGammaResult<T> amap2_adjust_gamma(const T& M1, const T& M2, const T& M3, const T& GAMMA,
253 const std::vector<T>& weights, int method,
254 int constraints, const T& tol) {
256 "amap2_adjust_gamma requires transcendental arithmetic");
257 using std::sqrt;
258 const T zero = num_traits<T>::from_int(0);
259 const T one = num_traits<T>::from_int(1);
260 const T two = num_traits<T>::from_int(2);
261 const T three = num_traits<T>::from_int(3);
262 const T half = num_traits<T>::from_rational(1, 2);
263 const T threehalf = num_traits<T>::from_rational(3, 2);
264
265 if (M1 <= zero) throw InputError("amap2_adjust_gamma: non-positive first moment");
266 if (weights.size() != 3) throw InputError("amap2_adjust_gamma: three weights are required");
267 if (constraints == 1)
268 throw UnsupportedError(
269 "amap2_adjust_gamma: constraints = 1 uses a 0/1 feasibility indicator that only a "
270 "direct-search poll can exploit; not ported");
271 if (constraints != 2) throw InputError("amap2_adjust_gamma: constraints must be 1 or 2");
272
273 // the reference's fun / fun2 divide by the targets
274 if (method != 3 && (M2 == zero || M3 == zero || GAMMA == zero))
275 throw InputError(
276 "amap2_adjust_gamma: methods 1, 2 and 4 minimize a RELATIVE deviation, which is "
277 "undefined when a target is zero; use method 3");
278
280
281 if (method == 3) {
282 // priorities M2 > M3 > GAMMA; entirely closed form
283 const Aph2AdjustResult<T> ad = aph2_adjust(M1, M2, M3);
284 r.M2a = ad.M2a;
285 r.M3a = ad.M3a;
286 T lb = zero, ub = zero;
287 fitdetail::amap2_gamma_bounds(M1, r.M2a, r.M3a, tol, lb, ub);
288 r.GAMMAa = GAMMA < lb ? lb : (GAMMA > ub ? ub : GAMMA);
289 } else if (method == 1) {
290 // joint search over (M2, M3, GAMMA)
291 const T w0 = weights[0], w1 = weights[1], w2 = weights[2];
292 auto f = [M2, M3, GAMMA, w0, w1, w2](const std::vector<T>& x) {
293 const T a0 = (x[0] - M2) / M2 * w0;
294 const T a1 = (x[1] - M3) / M3 * w1;
295 const T a2 = (x[2] - GAMMA) / GAMMA * w2;
296 using std::sqrt;
297 return sqrt(T(a0 * a0 + a1 * a1 + a2 * a2));
298 };
299 auto g = [M1](const std::vector<T>& x) {
300 return fitdetail::amap2_feasibility(M1, x[0], x[1], x[2]);
301 };
302
303 // the reference's analytically feasible starting point
304 const Map<T> feas =
305 GAMMA > zero
306 ? map_scale(amap2_assemble(one, T(one / three), half, T(two / three), 1), M1)
307 : map_scale(amap2_assemble(one, T(two / three), half, T(two / three), 2), M1);
308 std::vector<unsigned> lags(2);
309 lags[0] = 3;
310 lags[1] = 4;
311 const std::vector<T> acf = map_acf(feas, lags);
312 std::vector<T> x0(3);
313 x0[0] = map_moment(feas, 2);
314 x0[1] = map_moment(feas, 3);
315 x0[2] = acf[1] / acf[0];
316
317 // deterministic second start rationale: see _kb/03-api-layer.md (cpp port notes: mam)
318 const Aph2AdjustResult<T> ad3 = aph2_adjust(M1, M2, M3);
319 T lb3 = zero, ub3 = zero;
320 fitdetail::amap2_gamma_bounds(M1, ad3.M2a, ad3.M3a, tol, lb3, ub3);
321 std::vector<T> x1(3);
322 x1[0] = ad3.M2a;
323 x1[1] = ad3.M3a;
324 x1[2] = GAMMA < lb3 ? lb3 : (GAMMA > ub3 ? ub3 : GAMMA);
325
326 std::vector<Bound<T>> bnd(3);
327 bnd[0] = bound_lower(zero);
328 bnd[1] = bound_lower(zero);
329 bnd[2] = bound_box(T(-one), T(one - tol));
330
332 opt.ctol = num_traits<T>::from_double(1e-10);
333 const AugLagResult<T> s0 = auglag(f, NoConstraints<T>(), g, x0, bnd, opt);
334 const AugLagResult<T> s1 = auglag(f, NoConstraints<T>(), g, x1, bnd, opt);
335 const bool f0 = s0.violation <= opt.ctol;
336 const bool f1 = s1.violation <= opt.ctol;
337 const bool take1 = (f1 && !f0) || (f1 == f0 && s1.fval < s0.fval);
338 const AugLagResult<T>& sol = take1 ? s1 : s0;
339 r.M2a = sol.x[0];
340 r.M3a = sol.x[1];
341 r.GAMMAa = sol.x[2];
342 } else if (method == 2) {
343 // M2 forced feasible in closed form, then a search over (M3, GAMMA)
344 r.M2a = M2 > threehalf * M1 * M1 ? M2 : T(threehalf * M1 * M1);
345 // REFERENCE DEFECT (method 2 interval): see _kb/03-api-layer.md (cpp port notes: mam)
346 const T n2 = r.M2a / (M1 * M1);
347 T M3_LB, M3_UB, FM3;
348 bool ub_finite = true;
349 if (n2 >= threehalf && n2 < two) {
350 const T p2 = three * (n2 - two) / (three * n2) *
351 (-two * fitdetail::num_sqrt(three) /
352 fitdetail::num_sqrt(T(num_traits<T>::from_int(12) -
353 num_traits<T>::from_int(6) * n2)) -
354 one);
355 const T inner = p2 * p2 + two * p2 * (n2 - two);
356 const T a2 = (n2 - two) /
357 (p2 * (one - n2) + (inner > zero ? fitdetail::num_sqrt(inner) : zero));
358 const T l2 = three * (a2 + one) / (a2 * p2 + one) -
360 (two + a2 * p2 * (two * a2 + two));
361 const T u2 = num_traits<T>::from_int(6) * (n2 - one) / n2;
362 FM3 = (l2 + (u2 - l2) / two) * M1 * r.M2a;
363 M3_LB = l2 * M1 * r.M2a;
364 M3_UB = u2 * M1 * r.M2a;
365 } else {
366 FM3 = threehalf * r.M2a * r.M2a / M1 + tol;
367 M3_LB = FM3;
368 M3_UB = FM3; // unused, the bound is one-sided
369 ub_finite = false;
370 }
371
372 const T w1 = weights[1], w2 = weights[2];
373 auto f = [M3, GAMMA, w1, w2](const std::vector<T>& x) {
374 const T a1 = (x[0] - M3) / M3 * w1;
375 const T a2 = (x[1] - GAMMA) / GAMMA * w2;
376 using std::sqrt;
377 return sqrt(T(a1 * a1 + a2 * a2));
378 };
379 const T M2a_c = r.M2a;
380 auto g = [M1, M2a_c](const std::vector<T>& x) {
381 return fitdetail::amap2_feasibility(M1, M2a_c, x[0], x[1]);
382 };
383
384 std::vector<T> x0(2);
385 x0[0] = FM3;
386 x0[1] = zero; // a null decay rate is always feasible
387 std::vector<Bound<T>> bnd(2);
388 bnd[0] = ub_finite ? bound_box(M3_LB, M3_UB) : bound_lower(M3_LB);
389 bnd[1] = bound_box(T(-one), T(one - tol));
390
392 opt.ctol = num_traits<T>::from_double(1e-10);
393 const AugLagResult<T> sol = auglag(f, NoConstraints<T>(), g, x0, bnd, opt);
394 r.M3a = sol.x[0];
395 r.GAMMAa = sol.x[1];
396 } else if (method == 4) {
397 // priorities M2 > GAMMA > M3
398 const T M1sq = M1 * M1;
399 const T scv = (M2 - M1sq) / M1sq;
400 T scva;
401 if (scv < half) {
402 r.M2a = threehalf * M1sq;
403 scva = (r.M2a - M1sq) / M1sq;
404 } else {
405 r.M2a = M2;
406 scva = scv;
407 }
408 T M3_lb, M3_ub;
409 bool ub_finite;
410 if (scva <= one) {
411 const T d = one - scva;
412 M3_lb = three * fitdetail::pw(M1, 3) *
413 (three * scva - one + fitdetail::num_sqrt(two) * d * fitdetail::num_sqrt(d));
414 M3_ub = num_traits<T>::from_int(6) * fitdetail::pw(M1, 3) * scva;
415 ub_finite = true;
416 } else {
417 M3_lb = threehalf * fitdetail::pw(M1, 3) * (one + scva) * (one + scva);
418 M3_ub = M3_lb;
419 ub_finite = false;
420 }
421
422 if (ub_finite && num_abs(T(M3_lb - M3_ub)) < tol) {
423 r.M3a = (M3_lb + M3_ub) / two;
424 r.GAMMAa = zero;
425 } else {
426 const T w1 = weights[1], w2 = weights[2];
427 const T M2a_c = r.M2a;
428 auto obj = [M1, M2a_c, M3, GAMMA, w1, w2, tol](const std::vector<T>& x) {
430 fitdetail::amap2_gamma_bounds(M1, M2a_c, x[0], tol, lb, ub);
431 const T ga = GAMMA < lb ? lb : (GAMMA > ub ? ub : GAMMA);
432 const T a1 = x[0] / M3 - num_traits<T>::from_int(1);
433 const T a2 = ga / GAMMA - num_traits<T>::from_int(1);
434 return T(w1 * a1 * a1 + w2 * a2 * a2);
435 };
436
437 // deterministic multi-start rationale: see _kb/03-api-layer.md (cpp port notes: mam)
438 const T lo = M3_lb + tol;
439 std::vector<T> starts;
440 const unsigned nstart = 9;
441 for (unsigned k = 0; k < nstart; ++k) {
442 const T frac = num_traits<T>::from_int(long(k)) /
443 num_traits<T>::from_int(long(nstart - 1));
444 if (ub_finite)
445 starts.push_back(T(lo + frac * (M3_ub - lo)));
446 else
447 starts.push_back(T(lo * (one + frac * num_traits<T>::from_int(9))));
448 }
449
450 std::vector<Bound<T>> bnd(1);
451 bnd[0] = ub_finite ? bound_box(lo, M3_ub) : bound_lower(lo);
452
454 nmo.xtol = num_traits<T>::from_double(1e-12);
455 nmo.ftol = num_traits<T>::from_double(1e-16);
456
457 T bestf = zero;
458 T bestx = lo;
459 bool have = false;
460 for (std::size_t k = 0; k < starts.size(); ++k) {
461 std::vector<T> x0(1, starts[k]);
462 const NelderMeadResult<T> s = nelder_mead_box(obj, x0, bnd, nmo);
463 if (!have || s.fval < bestf) {
464 bestf = s.fval;
465 bestx = s.x[0];
466 have = true;
467 }
468 }
469 r.M3a = bestx;
470 T lb = zero, ub = zero;
471 fitdetail::amap2_gamma_bounds(M1, r.M2a, r.M3a, tol, lb, ub);
472 r.GAMMAa = GAMMA < lb ? lb : (GAMMA > ub ? ub : GAMMA);
473 }
474 } else {
475 throw InputError("amap2_adjust_gamma: method must be 1, 2, 3 or 4");
476 }
477
478 // the reference's own objective, reported for comparison
479 if (M2 == zero || M3 == zero || GAMMA == zero) {
480 r.objective = zero;
481 } else {
482 const T a0 = (r.M2a - M2) / M2 * weights[0];
483 const T a1 = (r.M3a - M3) / M3 * weights[1];
484 const T a2 = (r.GAMMAa - GAMMA) / GAMMA * weights[2];
485 r.objective = sqrt(T(a0 * a0 + a1 * a1 + a2 * a2));
486 }
489 return r;
490}
491
492/** amap2_adjust_gamma with the reference defaults: weights (10,1,10), method 3, constraints 2. */
493template <class T>
494Amap2AdjustGammaResult<T> amap2_adjust_gamma(const T& M1, const T& M2, const T& M3,
495 const T& GAMMA) {
496 std::vector<T> w(3);
497 w[0] = num_traits<T>::from_int(10);
498 w[1] = num_traits<T>::from_int(1);
499 w[2] = num_traits<T>::from_int(10);
500 return amap2_adjust_gamma(M1, M2, M3, GAMMA, w, 3, 2, T(num_traits<T>::from_double(1e-2)));
501}
502
503/** amap2_adjust_gamma with a chosen method and the remaining reference defaults. */
504template <class T>
505Amap2AdjustGammaResult<T> amap2_adjust_gamma(const T& M1, const T& M2, const T& M3, const T& GAMMA,
506 int method) {
507 std::vector<T> w(3);
508 w[0] = num_traits<T>::from_int(10);
509 w[1] = num_traits<T>::from_int(1);
510 w[2] = num_traits<T>::from_int(10);
511 return amap2_adjust_gamma(M1, M2, M3, GAMMA, w, method, 2,
513}
514
515} // namespace mam
516} // namespace line
517
518#endif // LINE_API_MAM_AMAP2_ADJUST_GAMMA_H
Assemble an AMAP(2) in one of the two canonical forms (matlab/lib/m3a/m3a/amap2/amap2_assemble....
Nearest APH(2)-feasible values of the second and third moments (matlab/lib/m3a/m3a/aph2/aph2_adjust....
Augmented Lagrangian method for equality- and inequality-constrained minimization,...
InputError(const std::string &what)
Definition error.h:39
UnsupportedError(const std::string &what)
Definition error.h:51
The exception types the port throws.
Scalar helpers shared by the MAP/PH moment-matching headers.
Markovian arrival process descriptors: stationary vectors, rate, moments, autocorrelation and the ind...
MAP constructors and structural transformations.
std::vector< T > map_acf(const Map< T > &m, const std::vector< unsigned > &lags)
Autocorrelation coefficients of the inter-arrival times at the given lags,.
Definition map_moment.h:168
Amap2AdjustGammaResult< T > amap2_adjust_gamma(const T &M1, const T &M2, const T &M3, const T &GAMMA, const std::vector< T > &weights, int method, int constraints, const T &tol)
Nearest AMAP(2)-feasible characteristics.
Aph2AdjustResult< T > aph2_adjust(const T &M1, const T &M2, const T &M3, const T &tol)
Feasible (M2, M3) closest to the input, holding M1 fixed.
Definition aph2_adjust.h:46
Map< T > amap2_assemble(const T &l1, const T &l2, const T &p1, const T &p2, int form)
AMAP(2) in canonical form 1 (gamma >= 0) or 2 (gamma < 0).
Map< T > map_scale(const Map< T > &in, const T &new_mean)
Rescale time so that the mean inter-arrival time becomes new_mean.
T map_moment(const Map< T > &m, unsigned k)
Raw moment of order k of the inter-arrival time: k!
Definition map_moment.h:118
bool amap2_gamma_feasible(const T &M1, const T &M2, const T &M3, const T &GAMMA, const T &slack)
Is (M1, M2, M3, GAMMA) AMAP(2)-feasible?
T num_abs(const T &v)
Definition number.h:172
AugLagResult< T > auglag(F f, H h, G g, const std::vector< T > &x0, const std::vector< Bound< T > > &bounds, const AugLagOptions< T > &opt)
Augmented Lagrangian with a scalar objective and a simplex inner solver.
Definition auglag.h:141
NelderMeadResult< T > nelder_mead_box(F f, const std::vector< T > &x0, const std::vector< Bound< T > > &bounds, const NelderMeadOptions< T > &opt)
Box-constrained simplex minimization by the transformation described in the header comment.
Definition neldermead.h:370
AugLagOptions< T > auglag_defaults()
Defaults: rho0 = 10, growth 10, feasibility 1e-10, 50 outer iterations.
Definition auglag.h:81
NelderMeadOptions< T > nelder_mead_defaults()
fminsearch's coefficients and initial simplex, with tighter tolerances.
Definition neldermead.h:79
Bound< T > bound_box(const T &lo, const T &hi)
lo <= x <= hi.
Definition neldermead.h:146
Bound< T > bound_lower(const T &lo)
lo <= x.
Definition neldermead.h:128
Derivative-free simplex minimization (Nelder and Mead, 1965), with optional box bounds imposed by a c...
Number-type abstraction for the templated API port.
Tuning of the outer multiplier iteration.
Definition auglag.h:68
Outcome of a constrained solve.
Definition auglag.h:96
std::vector< T > x
best point found
Definition auglag.h:97
T violation
max(|h_i|, max(0, g_j)) at x
Definition auglag.h:99
T fval
the ORIGINAL objective f(x), not the augmented one
Definition auglag.h:98
Tuning of the simplex iteration.
Definition neldermead.h:64
T ftol
stop when the spread of f over the simplex falls below this
Definition neldermead.h:65
T xtol
stop when the diameter of the simplex falls below this
Definition neldermead.h:66
Outcome of a simplex minimization.
Definition neldermead.h:96
std::vector< T > x
best point found
Definition neldermead.h:97
T fval
objective there
Definition neldermead.h:98
A constraint map that returns no constraints; the default for h or g.
Definition auglag.h:108
Result of amap2_adjust_gamma.
bool feasible
the returned triple satisfies the AMAP(2) conditions
T objective
the reference's weighted relative deviation at the answer
Result of aph2_adjust.
Definition aph2_adjust.h:36
A MAP as the pair of matrices (D0, D1).
Definition map_moment.h:53