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

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

What is and isn't a valid variable specification for Manipulate?

I have an expression whose terms have arguments (representing subscripts), like this: myExpr = A[0] + V[1,T] I would like to put it inside a Manipulate to see its value as I move around the parameters. (The goal is eventually to plot it wrt one of the variables inside.) However, Mathematica complains when I set V[1,T] as a manipulated variable: Manipulate[Evaluate[myExpr], {A[0], 0, 1}, {V[1, T], 0, 1}] (*Manipulate::vsform: Manipulate argument {V[1,T],0,1} does not have the correct form for a variable specification. >> *) As a workaround, if I get rid of the symbol T inside the argument, it works fine: Manipulate[ Evaluate[myExpr /. T -> 15], {A[0], 0, 1}, {V[1, 15], 0, 1}] Why this behavior? Can anyone point me to the documentation that says what counts as a valid variable? And is there a way to get Manpiulate to accept an expression with a symbolic argument as a variable? Investigations I've done so far: I tried using variableQ from this answer , but it says V[1...