Message Boards Message Boards

2 Replies
1 Total Likes
View groups...
Share this post:

How to output best solution found so far in Simulated Annealing?

Posted 10 years ago

I have a numerical function with 5 variables that takes about 2 minutes to evaluate each time. Trying to minimize the function with the "SimmulatedAnnealing" method takes several days of calculation.

I want Mathematica to print the best solution found so far, each time a new best solution is found while the algorithm is still running.

This code outputs the current values of the solution each step, but since the method doesn't always move towards a solution that is better than the previous one at each step, the last solution printed is not always the best solution so far

NMinimize[{StressError[p1, p2, p3, p4, p5], p1 > 0, p2 > 0, p3 > 0, p4 > 0, p5 > 0}, {{p1, 0.5, 2}, {p2, 0.5, 2}, {p3, 0.5, 2}, {p4, 
           0.5, 2}, {p5, 0.5, 2}}, Method -> "SimulatedAnnealing", 
         StepMonitor :> Print[{p1, p2, p3, p4, p5}]]

A way of doing this would be evaluating the function at each step, and only printing if it is the best solution found so far. Example:

BestSoFar = Infinity
NMinimize[{StressError[p1, p2, p3, p4, p5], p1 > 0, p2 > 0, p3 > 0, p4 > 0, p5 > 0}, {{p1, 0.5, 2}, {p2, 0.5, 2}, {p3, 0.5, 2}, {p4, 
           0.5, 2}, {p5, 0.5, 2}}, Method -> "SimulatedAnnealing", 
 StepMonitor :> (If[StressError[p1, p2, p3, p4, p5] < BestSoFar, 
    BestSoFar= StressError[p1, p2, p3, p4, p5]; Print[{p1, p2, p3, p4, p5}]])]

The problem with the previous code is that it would evaluate the function again at each step (which, considering that there are several hundreds of steps in the calculation, and evaluating the function takes about 2 minutes, would add a considerable amount of time to the calculation); the algorithm should already evaluate the function at each step, so evaluating it again shouldn't be needed.

Do you know a more efficient way to do the same?

2 Replies

Among other possibilities, you might want to memoize that objective. This is done as

StressError[p1_, p2_, p3_, p4_, p5_]:= StressError[p1, p2, p3, p4, p5]=...

Once computed for a particular {p1,...,p5} it will subsequently be found by lookup.

Also it might be useful to define it in such a way that it only evaluates when given explicit numeric input. If symbolic processing is any part of the speed issue, this change will redress that.

POSTED BY: Daniel Lichtblau
Posted 10 years ago

Thanks, the method described works in making evaluations with repeated parameters of the function much faster

StressError[p1_?NumericQ, p2_?NumericQ, p3_?NumericQ, p4_?NumericQ, p5_?NumericQ]:= StressError[p1, p2, p3, p4, p5] = ...

By adding "?NumericQ" I define the function to only evaluate with numeric input (that is how I defined the function initially), so numeric evaluation shouldn't take place.

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
or Discard

Group Abstract Group Abstract