Re: Re: Solving nonlinear inequality constraints

• To: mathgroup at smc.vnet.net
• Subject: [mg91405] Re: [mg91243] Re: [mg91209] Solving nonlinear inequality constraints
• From: "Stuart Nettleton" <Stuart.Nettleton at uts.edu.au>
• Date: Wed, 20 Aug 2008 06:22:17 -0400 (EDT)
• Organization: University of Technology, Sydney

```Daniel's suggestions have led me to refine my notebook (below), which has
reduced memory usage slightly and thereby allowed a marginally increased
projection period from 9 to 10 periods:
1. Introducing a function for mu[t_] - this has not been achieved. Perhaps
I am missing something very major but I cannot see how this can be done!
As soon as mu[1], mu[2] are generated in variables, they are immediately
evaluated by the arbitrary function (such as mu[t_]:=0.5). The effect of
providing functions for all the variables is to evaluate the objective and
constraints. Therefore, NMinimize merely has a numeric value for the
objective function, a set of true and false for the constraints, and no
variables for optimising. The notebook below shows that not only mu[t] but
also variables like k[t] and s[t] need to be "freed" for optimization (as
in the standard Nordhaus model), which I can only see means that variables
cannot be given their own functions.
2. Removing Hold - the need for Hold is removed by using _?NumberQ in
functions to prevent the symbolic evaluation that would otherwise occur.
The first notebook below has this feature. The second notebook continues
to use Holds, which are eliminated before the NMinimize function. I have
some preference for the Hold approach because answers with small numbers
of periods can be different than when _?NumberQ is used and I tend to
think symbolic answers are more accurate.
3. Using the Hold approach (ie. without using _?NumberQ in functions)
provides the following performance and memory usage on an intel 64bit/16Gb:
Projection    Compilation    Total             Memory
Periods         Time                 Minutes        Mb
5                    1.0 sec               1.2                234
6                    2.4 secs             2.4                 535
7                    8.9 secs            24.8**         1234
8                    0.5 mins           12.8              2572
9                    2.3 mins           40.9              4943
10                  9.4  mins          66.3              8908
11                  33.5 mins*      runs out of memory
*   10.5Gb used in compilation phase
** looks odd but retested and this was the same result, so perhaps its due
to the shape of the curve
Usually at 6 periods and upwards there were one or two complaints that
"NMinimize::incst: NMinimize was unable to generate any initial points \
satisfying the inequality constraints" but the function kept running to a
final solution.

4. As previously observed, the result using _?NumberQ in functions is
surprisingly similar to that with Hold. There is a shorter compilation
phase of 1 minute offset by longer optimisation phase of 1.5 minutes,
resulting in a slightly longer calculation period. The comparative
statistics for 10 periods are:
Approach      Compilation    Total             Memory
Minutes           Minutes        Mb
Hold              9.4  mins          66.3             8908
_?NumberQ  8.3 mins           66.8             8901

Conclusion:
It is some success that the number of projection periods has increased
from 8 to 10.
However, I still need to ramp-up to 60 periods and would like to achive
this in less than an hour if possible.
The continued interest of Daniel and participants on this list is warmly
appreciated!

Thanks,
Stuart

**** Notebook using _?NumberQ ****

(*AppendTo[\$Echo,"stdout"];*)
(*SetOptions["stdout",PageWidth->110] ; \
*)
(* Nordhaus Brief Climate Change Policy Model May 2008 *)
(* \
Stuart Nettleton July 2008 *)

starttime = AbsoluteTime[];
periods = 5; (* projection periods *)
maxit = 5000; (* maximum \
iterations *)

(* objective function *)
(* program always minimises, so negative for \
maximisation *)
obj = {-cumu[periods]};

(* optimisation variables: topolology leaves *)
(* .. for NMinimize \
provide both upper and lower bounds *)
(* .. for FindMinimum provide \
a single start estimate *)
(* hold function prevents premature \
evaluation *)
(*opt = {{\[Mu][t],0.001,1},{k[t],100,10000}};*)

opt = {{\[Mu][t], 0.001, 1}};

(* exogenous parameters *)
pop0 = 6514;
popg = 0.35;
popa = 8600;
dela = 0.001;
d\[Sigma]1 = 0.003;
d\[Sigma]2 = 0.000;
pback = 1.17;
backrat = 2;
gback = 0.05;
\[Rho] = 0.015;
fex0 = -0.06;
fex1 = 0.30;
\[Kappa]1 = 1;
\[Kappa]2 = 1;
\[Kappa]21 = 1;
d\[Kappa] = 0;
\[Theta] = 2.8;
sr = 0.22;

(* exogenous variables *)

gfacpop[t_] :=
gfacpop[t] = (Exp[popg*(t - 1)] - 1)/Exp[popg*(t - 1)];
l[t_] := l[t] = pop0*(1 - gfacpop[t]) + gfacpop[t]*popa;
ga[t_] := ga[t] = ga[0]*Exp[-dela*10*(t - 1)];
a[t_] := a[t] = a[t - 1]/(1 - ga[t - 1]);
g\[Sigma][t_] :=
g\[Sigma][t] =
g\[Sigma][0]*
Exp[-d\[Sigma]1*10*(t - 1) - d\[Sigma]2*10*(t - 1)^2];
\[Sigma][t_] := \[Sigma][t] = \[Sigma][t - 1]/(1 - g\[Sigma][t]);
\[CapitalTheta][
t_] := \[CapitalTheta][
t] = (pback*\[Sigma][t]/\[Theta])*((backrat - 1 +
Exp[-gback*(t - 1)])/backrat);
eland[t_] := eland[t] = eland[0]*(1 - 0.1)^(t - 1);
r[t_] := r[t] = 1/(1 + \[Rho])^(10*(t - 1));
fex[t_] :=
fex[t] = fex0 + If[t < 12, 0.1*(fex1 - fex0)*(t - 1), 0.36];
\[Kappa][t_] := \[Kappa][t] =
If[t >= 25, \[Kappa]21, \[Kappa]21 + (\[Kappa]2 - \[Kappa]21)*
Exp[-d\[Kappa]*(t - 2)]];
\[CapitalPi][t_] := \[CapitalPi][t] = \[Kappa][t]^(1 - \[Theta]);
(*s[t_]:= s[t] =sr;*)

(* initial values of exogenous variables *)
ga[0] = 0.092;
a[1] = a[0] = 0.02722;
g\[Sigma][0] = -0.0730;
\[Sigma][1] = \[Sigma][0] = 0.13418;
eland[0] = 11;
\[Kappa][1] = \[Kappa][0] = 0.25372;

(* endogenous parameters *)
\[Alpha] = 2.0;
\[Gamma] = .30;
\[Delta] = 0.1;
\[Eta] = 3.8;
t2xco2 = 3;
\[Psi]1 = 0.00000;
\[Psi]2 = 0.0028388;
\[Psi]3 = 2.00;
\[Xi]1 = 0.220;
\[Xi]2 = \[Eta]/t2xco2;
\[Xi]3 = 0.300;
\[Xi]4 = 0.050;
\[Phi]12 = 0.189288;
\[Phi]12a = 0.189288;
\[Phi]11 = 1 - \[Phi]12a;
\[Phi]23 = 0.05;
\[Phi]23a = 0.05;
\[Phi]21 = 587.473*\[Phi]12a/1143.894;
\[Phi]22 = 1 - \[Phi]21 - \[Phi]23a;
\[Phi]32 = 1143.894*\[Phi]23a/18340;
\[Phi]33 = 1 - \[Phi]32;
mat1750 = 596.4;
k0 = 137;
y0 = 61.1;
c0 = 30;
mat0 = 808.9;
mup0 = 1255;
mlo0 = 18365;
tat0 = 0.7307;
tlo0 = 0.0068;
\[Mu]0 = 0.005;
ceind0 = 0;
cumu0 = 381800;
scale1 = 194;

(* endogenous equality constraints*)

ceind[t_?NumberQ] := eind[t - 1] + ceind[t - 1];
eind[t_?NumberQ] :=
10 *\[Sigma][t] *(1 - \[Mu][t]) *ygr[t] + eland[t];
for[t_?NumberQ] := \[Eta]*(Log[(matav[t] + 0.000001)/mat1750]/
Log[2]) + fex[t];
mat[t_?NumberQ] :=
eind[t - 1] + \[Phi]11*mat[t - 1] + \[Phi]21*mup[t - 1];
matav[t_?NumberQ] := (mat[t] + mat[t + 1])/2;
mlo[t_?NumberQ] := \[Phi]23*mup[t - 1] + \[Phi]33*mlo[t - 1];
mup[t_?NumberQ] := \[Phi]12*mat[t - 1] + \[Phi]22*
mup[t - 1] + \[Phi]32*mlo[t - 1];
tat[t_?NumberQ] :=
tat[t - 1] + \[Xi]1*(for[t] - \[Xi]2*
tat[t - 1] - \[Xi]3*(tat[t - 1] - tlo[t - 1]));
tlo[t_?NumberQ] := tlo[t - 1] + \[Xi]4*(tat[t - 1] - tlo[t - 1]);
ygr[t_?NumberQ] := a[t]* k[t]^\[Gamma] *l[t]^(1 - \[Gamma]);
dam[t_?NumberQ] :=
ygr[t]*(1 - 1/(1 + \[Psi]1*tat[t] + \[Psi]2*(tat[t]^\[Psi]3)));
\[CapitalLambda][t_?NumberQ] :=
ygr[t] *\[CapitalPi][t] *\[CapitalTheta][t] *\[Mu][t]^\[Theta];
y[t_?NumberQ] :=
ygr[t]*(1 - \[CapitalPi][t]*\[CapitalTheta][
t]*\[Mu][t]^\[Theta])/(1 + \[Psi]1*
tat[t] + \[Psi]2*(tat[t]^\[Psi]3));
inv[t_?NumberQ] := (y[t] + 0.001)*s[t];
(*k[t_?NumberQ]:=10*inv[t-1]+((1-\[Delta])^10)*k[t-1];*)

ri[t_?NumberQ] := \[Gamma]*y[t]/k[t] - (1 - (1 - \[Delta])^10)/10;
c[t_?NumberQ] := y[t] - inv[t];
u[t_?NumberQ] := ((c[t]/l[t])^(1 - \[Alpha]) - 1)/(1 - \[Alpha]);
cumu[t_?NumberQ] := cumu[t - 1] + (l[t]*u[t]*r[t]*10)/scale1;
cpc[t_?NumberQ] := c[t]*1000/l[t];
pcy[t_?NumberQ] := y[t]*1000/l[t];

(* initial values of endogenous variables *)

cumu[1] = cumu[0] = cumu0;
ceind[1] = ceind[0] = ceind0;
mat[1] = mat[0] = mat0;
mlo[1] = mlo[0] = mlo0;
mup[1] = mup[0] = mup0;
tat[1] = tat[0] = tat0;
tlo[1] = tlo[0] = tlo0;
y[0] = y0;
k[1] = k[0] = k0;
c[0] = c0;
\[Mu][1] = \[Mu][0] = \[Mu]0;

(* endogenous inequality constraints*)
endog = {
k[t] <= 10*inv[t - 1] + ((1 - \[Delta])^10)*k[t - 1],
0.02*k[periods] <= inv[periods],
100 <= k[t],
20 <= c[t],
10 <= mat[t],
100 <= mup[t],
1000 <= mlo[t],
-1 <= tlo[t] <= 20,
0 <= tat[t] <= 20,
ceind[t] <= 6000,
0 <= y[t],
0 <= inv[t],
0 <= ygr[t],
0 <= eind[t],
0 <= matav[t],
0 <= \[Mu][t]
};

(* processing ... *)

(*prepare the objective function*)
objvars = Simplify[obj];
objectimous =
Simplify[
Flatten[Union[Map[objvars /. t -> # &, Range[periods]]] /.
x_Symbol[i_Integer /; i < 0] -> 0]];

(*prepare the endogenous constraints*)
endovars = Simplify[endog];
endogenous =
Simplify[
Flatten[Union[Map[endovars /. t -> # &, Range[periods]]] /.
x_Symbol[i_Integer /; i < 0] -> 0]];

(*prepare the independent optimising variables*)

optvars = Simplify[opt];
optimous =
Union[Cases[
Flatten[Map[optvars /. t -> # &, Range[periods]],
1], {x_Symbol[_Integer], _Integer | _Real} | \
{x_Symbol[_Integer], _Integer | _Real, _Integer | _Real} | \
{x_Symbol[_Integer], _Integer | _Real, _Integer | _Real, _Integer | \
_Real}, Infinity]];
optimousvars =
Union[Cases[optimous, x_Symbol[i_Integer] -> x[i], Infinity]];

(*include any additional optimising variables arising from the \
endogenous constraints*)

primafacievars =
Union[Cases[objectimous, x_Symbol[i_Integer] -> x[i], Infinity],
Cases[endogenous, x_Symbol[i_Integer] -> x[i], Infinity]];
extendedvariables =
Union[optimous, Complement[primafacievars, optimousvars]];

(*prepare optimising function*)

Print[Round[(AbsoluteTime[] - starttime), 0.01],
" seconds compilation time, commencing optimisation ..."];

soln = NMinimize[Join[objectimous, endogenous], extendedvariables,
MaxIterations -> maxit];

(*output results*)
Print["Solution: ", soln];
Print[Round[(AbsoluteTime[] - starttime)/60, 0.01],
" minutes from start to completion"];
Print[Round[N[MaxMemoryUsed[]*10^-6], 0.1], " Mb memory used"];

**** Notebook using Hold ****

(*AppendTo[\$Echo,"stdout"];*)
(*SetOptions["stdout",PageWidth->110] ; \
*)
(* Nordhaus Brief Climate Change Policy Model May 2008 *)
(* \
Stuart Nettleton July 2008 *)

starttime = AbsoluteTime[];
periods = 11; (* projection periods *)
maxit = 5000; (* maximum \
iterations *)

(* objective function *)
(* program always minimises, so negative for \
maximisation *)
obj = Hold[-cumu[periods]];
objvars = Apply[List, Map[Hold, obj]];

(* preferences for optimisation variables (topolology leaves) *)
(* .. \
for NMinimize provide both upper and lower bounds *)
(* .. for \
FindMinimum provide a single start estimate *)
(* hold function \
prevents premature evaluation *)
(*opt = \
Hold[{\[Mu][t],0.001,1},{k[t],100,10000}];*)

opt = Hold[{\[Mu][t], 0.001, 1}];
optvars = Apply[List, Map[Hold, opt]];

(* exogenous parameters *)
pop0 = 6514;
popg = 0.35;
popa = 8600;
dela = 0.001;
d\[Sigma]1 = 0.003;
d\[Sigma]2 = 0.000;
pback = 1.17;
backrat = 2;
gback = 0.05;
\[Rho] = 0.015;
fex0 = -0.06;
fex1 = 0.30;
\[Kappa]1 = 1;
\[Kappa]2 = 1;
\[Kappa]21 = 1;
d\[Kappa] = 0;
\[Theta] = 2.8;
sr = 0.22;

(* exogenous variables *)

gfacpop[t_] :=
gfacpop[t] = (Exp[popg*(t - 1)] - 1)/Exp[popg*(t - 1)];
l[t_] := l[t] = pop0*(1 - gfacpop[t]) + gfacpop[t]*popa;
ga[t_] := ga[t] = ga[0]*Exp[-dela*10*(t - 1)];
a[t_] := a[t] = a[t - 1]/(1 - ga[t - 1]);
g\[Sigma][t_] :=
g\[Sigma][t] =
g\[Sigma][0]*
Exp[-d\[Sigma]1*10*(t - 1) - d\[Sigma]2*10*(t - 1)^2];
\[Sigma][t_] := \[Sigma][t] = \[Sigma][t - 1]/(1 - g\[Sigma][t]);
\[CapitalTheta][
t_] := \[CapitalTheta][
t] = (pback*\[Sigma][t]/\[Theta])*((backrat - 1 +
Exp[-gback*(t - 1)])/backrat);
eland[t_] := eland[t] = eland[0]*(1 - 0.1)^(t - 1);
r[t_] := r[t] = 1/(1 + \[Rho])^(10*(t - 1));
fex[t_] :=
fex[t] = fex0 + If[t < 12, 0.1*(fex1 - fex0)*(t - 1), 0.36];
\[Kappa][t_] := \[Kappa][t] =
If[t >=
25, \[Kappa]21, \[Kappa]21 + (\[Kappa]2 - \[Kappa]21)*
Exp[-d\[Kappa]*(t - 2)]];
\[CapitalPi][t_] := \[CapitalPi][t] = \[Kappa][t]^(1 - \[Theta]);
(*s[t_]:= s[t] =sr;*)

(* initial values of exogenous variables *)
ga[0] = 0.092;
a[1] = a[0] = 0.02722;
g\[Sigma][0] = -0.0730;
\[Sigma][1] = \[Sigma][0] = 0.13418;
eland[0] = 11;
\[Kappa][1] = \[Kappa][0] = 0.25372;

(* endogenous parameters *)
\[Alpha] = 2.0;
\[Gamma] = .30;
\[Delta] = 0.1;
\[Eta] = 3.8;
t2xco2 = 3;
\[Psi]1 = 0.00000;
\[Psi]2 = 0.0028388;
\[Psi]3 = 2.00;
\[Xi]1 = 0.220;
\[Xi]2 = \[Eta]/t2xco2;
\[Xi]3 = 0.300;
\[Xi]4 = 0.050;
\[Phi]12 = 0.189288;
\[Phi]12a = 0.189288;
\[Phi]11 = 1 - \[Phi]12a;
\[Phi]23 = 0.05;
\[Phi]23a = 0.05;
\[Phi]21 = 587.473*\[Phi]12a/1143.894;
\[Phi]22 = 1 - \[Phi]21 - \[Phi]23a;
\[Phi]32 = 1143.894*\[Phi]23a/18340;
\[Phi]33 = 1 - \[Phi]32;
mat1750 = 596.4;
k0 = 137;
y0 = 61.1;
c0 = 30;
mat0 = 808.9;
mup0 = 1255;
mlo0 = 18365;
tat0 = 0.7307;
tlo0 = 0.0068;
\[Mu]0 = 0.005;
ceind0 = 0;
cumu0 = 381800;
scale1 = 194;

(* endogenous equality constraints*)

ceind[t_] := eind[t - 1] + ceind[t - 1];
eind[t_] := 10 *\[Sigma][t] *(1 - \[Mu][t]) *ygr[t] + eland[t];
for[t_] := \[Eta]*(Log[(matav[t] + 0.000001)/mat1750]/Log[2]) +
fex[t];
mat[t_] := eind[t - 1] + \[Phi]11*mat[t - 1] + \[Phi]21*mup[t - 1];
matav[t_] := (mat[t] + mat[t + 1])/2;
mlo[t_] := \[Phi]23*mup[t - 1] + \[Phi]33*mlo[t - 1];
mup[t_] := \[Phi]12*mat[t - 1] + \[Phi]22*mup[t - 1] + \[Phi]32*
mlo[t - 1];
tat[t_] :=
tat[t - 1] + \[Xi]1*(for[t] - \[Xi]2*
tat[t - 1] - \[Xi]3*(tat[t - 1] - tlo[t - 1]));
tlo[t_] := tlo[t - 1] + \[Xi]4*(tat[t - 1] - tlo[t - 1]);
ygr[t_] := a[t]* k[t]^\[Gamma] *l[t]^(1 - \[Gamma]);
dam[t_] :=
ygr[t]*(1 - 1/(1 + \[Psi]1*tat[t] + \[Psi]2*(tat[t]^\[Psi]3)));
\[CapitalLambda][t_] :=
ygr[t] *\[CapitalPi][t] *\[CapitalTheta][t] *\[Mu][t]^\[Theta];
y[t_] :=
ygr[t]*(1 - \[CapitalPi][t]*\[CapitalTheta][
t]*\[Mu][t]^\[Theta])/(1 + \[Psi]1*
tat[t] + \[Psi]2*(tat[t]^\[Psi]3));
inv[t_] := (y[t] + 0.001)*s[t];
(*k[t_]:=10*inv[t-1]+((1-\[Delta])^10)*k[t-1];*)

ri[t_] := \[Gamma]*y[t]/k[t] - (1 - (1 - \[Delta])^10)/10;
c[t_] := y[t] - inv[t];
u[t_] := ((c[t]/l[t])^(1 - \[Alpha]) - 1)/(1 - \[Alpha]);
cumu[t_] := cumu[t - 1] + (l[t]*u[t]*r[t]*10)/scale1;
cpc[t_] := c[t]*1000/l[t];
pcy[t_] := y[t]*1000/l[t];

(* initial values of endogenous variables *)

cumu[1] = cumu[0] = cumu0;
ceind[1] = ceind[0] = ceind0;
mat[1] = mat[0] = mat0;
mlo[1] = mlo[0] = mlo0;
mup[1] = mup[0] = mup0;
tat[1] = tat[0] = tat0;
tlo[1] = tlo[0] = tlo0;
y[0] = y0;
k[1] = k[0] = k0;
c[0] = c0;
\[Mu][1] = \[Mu][0] = \[Mu]0;

(* endogenous inequality constraints*)
endog = Hold[
k[t] <= 10*inv[t - 1] + ((1 - \[Delta])^10)*k[t - 1],
0.02*k[periods] <= inv[periods],
100 <= k[t],
20 <= c[t],
10 <= mat[t],
100 <= mup[t],
1000 <= mlo[t],
-1 <= tlo[t] <= 20,
0 <= tat[t] <= 20,
ceind[t] <= 6000,
0 <= y[t],
0 <= inv[t],
0 <= ygr[t],
0 <= eind[t],
0 <= matav[t],
0 <= \[Mu][t]
];
endovars = Apply[List, Map[Hold, endog]];

(* processing ... *)

(* prepare the objective function *)

objectimous =
Simplify[
Flatten[Apply[List,
Map[ReleaseHold,
Union[Map[objvars /. t -> # &, Range[periods ]]]]] /.
x_Symbol[i_Integer /; i < 0] -> 0]];

(* prepare the endogenous constraints *)

endogenous =
Simplify[
Flatten[Apply[List,
Map[ReleaseHold,
Union[Map[endovars /. t -> # &, Range[periods ]]]]] /.
x_Symbol[i_Integer /; i < 0] -> 0]];

(* prepare the independent optimising variables *)

optimous =
Union[Cases[
Apply[List,
Map[ReleaseHold,
Flatten[Map[optvars /. t -> # &, Range[periods]]]]],
{x_Symbol[_Integer], _Integer | _Real} |
{x_Symbol[_Integer], _Integer | _Real, _Integer | _Real} |
{x_Symbol[_Integer], _Integer | _Real, _Integer | _Real, \
_Integer | _Real},
Infinity]];
optimousvars =
Union[Cases[optimous, x_Symbol[i_Integer] -> x[i], Infinity]];

(* include any additional optimising variables arising from the \
endogenous constraints *)

primafacievars =
Union[Cases[objectimous, x_Symbol[i_Integer] -> x[i], Infinity],
Cases[endogenous, x_Symbol[i_Integer] -> x[i], Infinity]] ;
extendedvariables =
Union[optimous, Complement[primafacievars, optimousvars]];

(* prepare optimising function *)

Print[Round[(AbsoluteTime[] - starttime), 0.01],
" seconds compilation time, commencing optimisation ..."];
soln = NMinimize[Join[objectimous, endogenous], extendedvariables,
MaxIterations -> maxit];

(* output results *)
Print["Solution: ", soln];
Print[Round[(AbsoluteTime[] - starttime)/60, 0.01],
" minutes from start to completion"];
Print[Round[N[MaxMemoryUsed[]*10^-6], 0.1], " Mb memory used"];

--
UTS CRICOS Provider Code:  00099F
DISCLAIMER: This email message and any accompanying attachments may contain
confidential information.  If you are not the intended recipient, do not
read, use, disseminate, distribute or copy this message or attachments.  If