7
$\begingroup$

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)?

$\endgroup$
10
  • 2
    $\begingroup$ CheckAbort? Perhaps with Reap and Sow... $\endgroup$
    – Michael E2
    May 7, 2015 at 17:37
  • $\begingroup$ FindInstance[f[x, y] <= -5, {x, y}]? $\endgroup$
    – user484
    May 7, 2015 at 17:40
  • 1
    $\begingroup$ Might be able to do it with StepMonitor, e.g. having it Throw a result if it is sufficiently good. If you have in mind a particular threshold you can also make it into a constraint. $\endgroup$ May 7, 2015 at 20:21
  • $\begingroup$ @MichaelE2 Thanks for the hint to CheckAbort- I did not know of this function. I will definitely give it a try although george2079 already posted a working answer. Always so many ways to reach the goal :) $\endgroup$
    – Lukas
    May 7, 2015 at 20:44
  • 1
    $\begingroup$ I also tried FindMinimum but it tended to find the same results as NMinimize in my real problem. But now after I know how to stop, it might probably find results faster and I will give it a try again. - Also as an aside: In another comment to one of my questions you explained why NelderMead will probably not work that good. I tried different ones like DifferentialEvolutionand SimulatedAnnealing and also other algorithm parameters as explained in F. Gao, L. Han, Comp. Opt. and Appl., 51, 259-277. However, NelderMead with standard parameters led to best results in most cases $\endgroup$
    – Lukas
    May 8, 2015 at 6:42

1 Answer 1

7
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ Thanks alot for this answer. I did not think of Throw which is really well-suited for this case... Regarding the Print symbols: they are just "dummies" and have no special meaning. Also thanks for the side remark considering the usage NMinimize[fn=f[x,y],...]; I will probably implement that :) $\endgroup$
    – Lukas
    May 7, 2015 at 20:50
  • $\begingroup$ Forgot to mention: I will not accept the answer yet, although it works. Just t want to wait for a couple of days if someone posts another answer. $\endgroup$
    – Lukas
    May 8, 2015 at 6:44
  • $\begingroup$ @george2079, thank you for the answer. Eventually, NMimimize with Catch-Throw returns unevaluated expression (I'm on MMA 12.0). It doesn't happen with Reap-Sow, though. Before I did not encounter such a problem. Do you know why can in be? $\endgroup$
    – garej
    Sep 1, 2020 at 6:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.