Skip to main content

numerics - Combined numerical minimization and maximization


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?



Answer



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]).


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...