18
$\begingroup$

I want to numerically calculate the maximum of a function defined by the minimization of another function, like the following:

NMaximize[b/.NMinimize[(a^2+b)^2,{b}][[2]],{a}]

Obviously the intended result (for this simple test function) would be:

{0., {a->0.}}

because the inner minimization would give b=-a^2 for any value of a, and maximizing that gives 0 for a=0.

However I get the error message NMinimize::nnum: "The function value (-0.829053+a^2)^2 is not a number at {b} = {-0.829053}." and the result NMaximize[b/.{b},{a}]. I figured that this is due to premature evaluation of the argument (i.e. before a got anumerical value), therefore I tried to wrap either the whole first argument of just the NMinimize call in Unevaluated, but neither helped.

So my question is: How can I do this combined numerical optimization?

$\endgroup$

1 Answer 1

22
$\begingroup$

This is a rather common issue that comes up with many numerical functions (FindRoot, NIntegrate, FindMaximum, NMaximize, etc.) It is also explained in this Wolfram Knowledge Base article. Sometimes you want to pass these functions an expression that has a symbolic parameter, and compute the result for different values of that parameter.

Example:

fun[a_] := Block[{b}, b /. NMinimize[(a^2 + b)^2, {b}][[2]]]

This will work nicely if you call it with a numeric argument: fun[3]. But it will cause an error in NMinimize if you call it with a symbolic parameter: fun[a] (for obvious reasons).

The solution is:

Clear[fun]
fun[a_?NumericQ] := Block[{b}, b /. NMinimize[(a^2 + b)^2, {b}][[2]]]

NMaximize[fun[a], {a}]

(Be sure to evaluate Clear[...] to get rid of the previous definition of fun!)

This ensures that fun will only evaluate for numerical arguments, i.e. fun[a] won't evaluate inside NMaximize before NMaximize actually substitutes a number for a.

And this is also the answer to your specific question: make the inner NMinimize expression a separate function, and make sure it only evaluates for numerical arguments.


Requested edit

An important related point is: how can we match only numerical quantities using a pattern? One might think of using _Real (as in the comment below). The problem with this is that it will only match numbers whose Head is Real. This excludes integers (such as 1,2,3), rationals (2/3, 4/5), constants (such as Pi or E), or expressions like Sqrt[2].

The only robust solution is using NumericQ[] (x_ ? NumericQ in a pattern). NumericQ will return True for anything that gives a number when N[] is applied to it.

There's another related function, NumberQ[], which gives True only for objects with Integer, Rational, Real or Complex, but not for constant or expressions (Pi or Sin[3]).

$\endgroup$
7
  • 4
    $\begingroup$ This is such a common issue I suggested making a faq-item out of it even before the site was launched. It comes up every 10 days on MathGroup. $\endgroup$
    – Szabolcs
    Commented Jan 20, 2012 at 9:26
  • $\begingroup$ A small followup question: I've noticed that fun[a_Real] seems to work as well in my toy example (I hoped to make it faster that way, but it didn't have any significant effect). Are there cases for NMinimize where a_Real would fail, but a_?NumericQ wouldn't? $\endgroup$
    – celtschk
    Commented Jan 20, 2012 at 10:13
  • $\begingroup$ @celtschk See my edit. $\endgroup$
    – Szabolcs
    Commented Jan 20, 2012 at 10:24
  • $\begingroup$ Thanks, but my question was specific to NMinimize. It's clear to me that the function then will not work if given symbolic or exact arguments; however, it's not clear to me whether NMinimize will ever pass anything not matching _Real to the function. $\endgroup$
    – celtschk
    Commented Jan 20, 2012 at 10:29
  • $\begingroup$ @celtschk I can't tell you if it will ever pass an integer, but I wouldn't worry about performance differences. NumericQ is well optimized. I'll dig up a benchmark later. $\endgroup$
    – Szabolcs
    Commented Jan 20, 2012 at 10:32

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.