Suppose we have some function f[x,y]
that we want to optimize in way that we are only interested in values (x,y)
that guarantee our function value is below some value target
. See the following MWE:
f[x_, y_] := f[x, y] = x^2 - 4*x + y^2 - y - x*y;
findMin[target_, steps_] := Block[{nbr = -1},
solsOpt = NMinimize[
f[x, y],
{x, y},
Method -> "NelderMead",
(*EvaluationMonitor:>{nbr += 1; If[Mod[nbr, steps] == 0, Print["Step: ", nbr," ; Current value: ",f[x,y], " ; parameters: ",{x,y}],Print]}*)
EvaluationMonitor :> {nbr += 1; If[Mod[nbr, steps] == 0, Print["Step: ", nbr," ; Current value: ", f[x, y], " ; parameters: ", {x, y}], Print] || If[f[x, y] <= target, Abort[], Print]}
];
Print["Number of iterations: ", nbr];
Print["Final value: ", solsOpt[[1]]];
Return[solsOpt];
]
Of course findMin[-5,1]
stops after a few iterations and I can read the values (x,y)
that satisfy my criterion. However, I need to do that for a bunch of different functions f
inside a ParallelTable
structure, that in the end holds (function_index, final value, parameter values). By aborting no values are stored. What I want is something like "After reaching target, just assume optimization is finished and go on with the next one". Is that possible with the built-in function(s)?
Answer
Catch/Throw
:
findMin[target_, steps_] :=
Block[{nbr = -1},
solsOpt =
ReleaseHold@Catch@NMinimize[f[x, y], {x, y},
Method -> "NelderMead",
EvaluationMonitor :> {nbr += 1;
If[Mod[nbr, steps] == 0,
Print["Step: ", nbr, " ; Current value: ", f[x, y],
" ; parameters: ", {x, y}], Print] ||
If[f[x, y] <= target, Print["good enough"];
Throw[{f[x, y], {HoldForm[x] -> x, HoldForm[y] -> y}}],
Print]}];
Print["Number of iterations: ", nbr];
Print["Final value: ", solsOpt];
solsOpt]
findMin[-5, 1] (* three iterations, stop for threshold *)
{-6.1742, {x -> 2.2116, y -> 1.00612}}
findMin[-50, 1] (* 89 iterations , regular convergence *)
{-7., {x -> 3., y -> 2.}}
Aside , I don't know why you have the symbol Print
in there a few times not applied to any arguments..
Also, aside from the question you can do NMinimize[fn = f[x, y],...
then use the symbol fn
in your conditional If[fn <= target ..
so avoiding redundant evaluation of the function.
Comments
Post a Comment