1 /* augmented Lagrangian method for constrained optimization
3 * copyright Robert Dodier, October 2005
4 * Released under the terms of the GNU General Public License
6 * See http://www-fp.mcs.anl.gov/otc/Guide/OptWeb/continuous/constrained/nonlinearcon/auglag.html
7 * and http://www.cs.ubc.ca/spider/ascher/542/chap10.pdf
9 * This implementation minimizes the augmented Lagrangian by
10 * applying LBFGS (a quasi-Newton algorithm).
12 * Function: augmented_lagrangian_method (FOM, xx, constraints, yy, [optional_args])
14 * FOM = figure of merit expression
15 * xx = list of variables over which to minimize
16 * constraints = list of expressions to be held equal to zero
17 * yy = list of initial guesses for xx
19 * optional_args = more arguments of the form symbol = value
20 * optional arguments recognized are:
22 * niter = number of iterations of the augmented Lagrangian algorithm
23 * lbfgs_tolerance = tolerance supplied to LBFGS
24 * iprint = IPRINT parameter supplied to LBFGS
25 * %lambda = initial value of %lambda
27 * LBFGS (to solve grad L = 0) has to be loaded before calling augmented_lagrangian_method.
32 load (augmented_lagrangian);
37 augmented_lagrangian_method (FOM, xx, C, yy, niter = 20);
39 * => [[x = 0.6661347183787, y = 0.33306735918935], %lambda = [- 1.331471514325457]]
42 * same as Example 1, but with gradient computed by Lisp functions
43 * Construct Lisp functions suitable for this example via translate
46 load (augmented_lagrangian);
52 F1(x, y) := ''(diff(F(x, y), x));
53 F2(x, y) := ''(diff(F(x, y), y));
54 translate (F, F1, F2);
55 :lisp (mremprop '|$f| 'mexpr)
56 :lisp (mremprop '|$f1| 'mexpr)
57 :lisp (mremprop '|$f2| 'mexpr)
58 augmented_lagrangian_method ('[F(x, y), [F1(x, y), F2(x, y)]], xx, C, yy, niter = 20);
60 * => [[x = 0.6661347183787, y = 0.33306735918935], %lambda = [- 1.331471514325457]]
63 /* fboundp detects various kinds of Maxima functions */
66 or ?mget (a, ?mexpr) # false
67 or ?get (a, ?mfexpr\*) # false
68 or ?mget (a, ?mmacro) # false;
70 if not fboundp (lbfgs) then load (lbfgs);
72 with_parameters ([L]) ::= buildq ([a : subst (":", "=", ev (L [1])), e : rest (L)], block (a, splice (e)));
74 augmented_lagrangian_method (FOM, xx, constraints, yy, [optional_args]) :=
76 block ([n, augmented_lagrangian, %lambda, %nu, FOM_augment,
77 niter : 10, lbfgs_tolerance : 1e-4, iprint : [1, 1]],
79 nconstraints: length (constraints),
82 apply ("+", makelist (%lambda[i] * constraints[i], i, 1, nconstraints))
83 + (1/2) * apply ("+", makelist (%nu[i] * constraints[i]^2, i, 1, nconstraints)),
86 then block ([FOM_proper, FOM_grad],
87 FOM_proper : first (FOM) + FOM_augment,
88 FOM_grad : second (FOM) + map (lambda ([x], diff (FOM_augment, x)), xx),
89 augmented_lagrangian : [FOM_proper, FOM_grad])
90 else augmented_lagrangian: FOM + FOM_augment,
92 %lambda: makelist (1, i, 1, nconstraints),
94 %nu: makelist (1, i, 1, nconstraints),
96 with_parameters (optional_args,
100 (soln: lbfgs (augmented_lagrangian, xx, yy, lbfgs_tolerance, iprint),
104 %lambda: %lambda + apply ("+", %nu * map (lambda ([c], subst (soln, c)), constraints)),
108 [map ("=", xx, yy), '%lambda = %lambda]));