6
$\begingroup$

As per the title, consider the following trivial example:

f[x_] := (Print[x]; -x^2 + 10 x)
NMaximize[
 f[x], x
 ]
(* x *)
(* {25., {x -> 5.}} *)

Now, as the printed x shows, NMaximize (like many other similar functions) first symbolically evaluates f[x] looking for ways to make the maximization process more efficient (and in this case understanding without further evaluation where the maximum is).

This is of course very convenient in many cases, but there are instances where the symbolical evaluation of the function can be extremely computationally expensive so that this initial evaluation may take more time that it is required for the maximization itself.

The standard way to avoid this is to redefine f to accept only numeric inputs, as per f[x_?NumericQ] := (Print[x]; -x^2 + 10 x), which works as intended. This can however be inconvenient, for example in the case of functions with many inputs, or more complicated input patterns.

Is there an easier way to tell Mathematica to not try to symbolically evaluate f, and go straight to use numerical methods?

$\endgroup$
3
  • $\begingroup$ Might it be that a proper method fulfills your goal. $\endgroup$ – corey979 Oct 26 '16 at 20:50
  • $\begingroup$ @corey979 explicitly fixing a method does not prevent the symbolic evaluation of f[x] $\endgroup$ – glS Oct 26 '16 at 21:07
  • $\begingroup$ Isn't it easier just to use Block[{foo}, foo[x_?NumericQ] := f[x]; NMaximize[foo[x], x]] as needed in each case? $\endgroup$ – Michael E2 Oct 27 '16 at 2:36
4
$\begingroup$

Somewhat like wigg0t's in that it uses the pattern-matching of the evaluation sequence, replaceIf[in, pat :> expr] replaces the input in by expr if in matches the pattern pat:

ClearAll[replaceIf];
replaceIf[in_, (Rule | RuleDelayed)[pat_, expr_]] /; MatchQ[in, pat] := expr;

Usage:

NMaximize[replaceIf[x, _?NumericQ :> f[x]], x]

A possible alternative is to use the fact that Equal does not evaluate to True or False if an argument is symbolic:

NMaximize[If[x == 0 || x != 0, f[x]], x]
$\endgroup$
2
  • $\begingroup$ this however still requires to specify the form of the numerical input, and it's not that much shorter that just redifining the function locally in a Block or Module as per your previous comment. What about defining a wrapper that redirects the first evaluation and calls the function regularly after that? Do you think that would cause problems to NMaximize (or whatever other function)? $\endgroup$ – glS Oct 27 '16 at 13:32
  • $\begingroup$ @gIS I don't think anything is shorter (or clearer) than foo[x_?NumericQ] := f[x], with or without Block. It seems at the least you would have to use NumericQ, and given that, foo seems terse. It would be nice if there were an option to NMaximize[] that did what you wanted, but I don't think there is one. -- FWIW, I like the generality of replaceIf[], which is a bit like a GeneralUtilities`Match[] that doesn't Panic[] when the pattern doesn't match. But my preferred method is the one you are seeking to avoid. $\endgroup$ – Michael E2 Oct 27 '16 at 18:30
6
$\begingroup$

You could wrap your function in a head that suspends evaluation.

ClearAll[suspend];
SetAttributes[suspend, HoldFirst];
suspend[expr_, {__?NumericQ}] := expr

With[{vars = {x}}, NMaximize[suspend[f[x], vars], vars]]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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