1
$\begingroup$

I want to find a global minimum of a function which is defined only numerically and cannot be evaluated with symbolic arguments. For example, this could be a minimum of a compiled function.

numfun = Compile[{{x1,_Real}, {x2,_Real}, {x3,_Real}, {x4,_Real}, {x5,_Real},
                  {x6,_Real}, {x7,_Real}, {x8,_Real}, {x9,_Real}, {x10,_Real}}, 
                 Sqrt[(x1-1.0)^2+(x2-2.0)^2+(x3-3.0)^2+(x4-4.0)^2+(x5-5.0)^2
                     +(x6-6.0)^2+(x7-7.0)^2+(x8-8.0)^2+(x9-9.0)^2+(x10-10.0)^2]];

If I use NMinimize directly, it attempts to substitute symbolic arguments into my function. The following code generates a lot of warning messages:

First@RepeatedTiming@NMinimize[numfun[x1,x2,x3,x4,x5,x6,x7,x8,x9,x10], 
                               {x1,x2,x3,x4,x5,x6,x7,x8,x9,x10}]

CompiledFunction::cfsa: Argument x1 at position 1 should be a machine-size real number.

0.056

If I use standard wrapping trick to prevent symbolic input

ClearAll[numfunWrapper];
numfunWrapper[x1_Real,x2_Real,x3_Real,x4_Real,x5_Real,
              x6_Real,x7_Real,x8_Real,x9_Real,x10_Real]:=numfun[x1,x2,x3,x4,x5,x6,x7,x8,x9,x10];

then the performance is degraded by two orders of magnitude.

First@RepeatedTiming@NMinimize[numfunWrapper[x1,x2,x3,x4,x5,x6,x7,x8,x9,x10],
                               {x1,x2,x3,x4,x5,x6,x7,x8,x9,x10}]

1.904

Is there a way prevent NMinimize from using symbolic arguments/preprocessing without such performance penalty?

It seems that for a compiled function one can just disable warning messages, but are there any NMinimize options which can disable symbolic preprocessing like Method -> {Automatic, "SymbolicProcessing" -> 0} in the NIntegrate function?

$\endgroup$
  • $\begingroup$ You can turn the processing off in Compile via RuntimeOptions. That'll probably serve you best. $\endgroup$ – b3m2a1 May 9 at 0:25
  • 2
    $\begingroup$ The performance difference is probably due to the compiled function evaluating symbolically in the first case. You're not really using the compiled function. $\endgroup$ – Michael E2 May 9 at 0:53
  • $\begingroup$ @b3m2a1 Compile seems to work correctly. The issue is that NMinimize tries to supply compiled function with symbolic arguments. I would like to find out how to prevent this. $\endgroup$ – Shadowray May 9 at 21:03
  • $\begingroup$ @Shadowray what I'm saying is that Compile can be told to ignore symbolic options. That'll speed things up a lot. $\endgroup$ – b3m2a1 May 9 at 21:05
2
$\begingroup$

As I mentioned in the comments RuntimeOptions is your friend here:

numfun =
  Compile[{{x1, _Real}, {x2, _Real}, {x3, _Real}, {x4, _Real}, {x5, _Real}, {x6, _Real}, {x7, _Real}, {x8, _Real}, {x9, _Real}, {x10, _Real}}, Sqrt[(x1 - 1.0)^2 + (x2 - 2.0)^2 + (x3 - 3.0)^2 + (x4 - 4.0)^2 + (x5 - 5.0)^2 + (x6 - 6.0)^2 + (x7 - 7.0)^2 + (x8 - 8.0)^2 + (x9 - 9.0)^2 + (x10 - 10.0)^2],

   RuntimeOptions -> {"EvaluateSymbolically" -> False}
   ];

NMinimize[
  numfun[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10], {x1, x2, x3, x4, x5, x6, x7, x8, x9, x10}
  ] // AbsoluteTiming

{2.48474, {1.46191*10^-7, {x1 -> 1., x2 -> 2., x3 -> 3., x4 -> 4., x5 -> 5., x6 -> 6., x7 -> 7., x8 -> 8., x9 -> 9., x10 -> 10.}}}

ClearAll[numfunWrapper];
numfunWrapper[x1_Real, x2_Real, x3_Real, x4_Real, x5_Real, x6_Real, x7_Real, x8_Real, x9_Real, x10_Real] := numfun[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10];

NMinimize[
  numfunWrapper[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10], {x1, x2, x3, x4, x5, x6, x7, x8, x9, x10}
  ] // AbsoluteTiming

{3.98258, {1.46191*10^-7, {x1 -> 1., x2 -> 2., x3 -> 3., x4 -> 4., x5 -> 5., x6 -> 6., x7 -> 7., x8 -> 8., x9 -> 9., x10 -> 10.}}}

Of course for this case you'll be even better off with the direct symbolic processing done:

numfun2 =
  Compile[{{x1, _Real}, {x2, _Real}, {x3, _Real}, {x4, _Real}, {x5, _Real}, {x6, _Real}, {x7, _Real}, {x8, _Real}, {x9, _Real}, {x10, _Real}}, Sqrt[(x1 - 1.0)^2 + (x2 - 2.0)^2 + (x3 - 3.0)^2 + (x4 - 4.0)^2 + (x5 - 5.0)^2 + (x6 - 6.0)^2 + (x7 - 7.0)^2 + (x8 - 8.0)^2 + (x9 - 9.0)^2 + (x10 - 10.0)^2]
   ];

NMinimize[
   numfun2[x1, x2, x3, x4, x5, x6, x7, x8, x9, x10], {x1, x2, x3, x4, x5, x6, x7, x8, x9, x10}
   ] // Quiet // AbsoluteTiming

{0.010106, {3.20225*10^-6, {x1 -> 1., x2 -> 2., x3 -> 3., x4 -> 4., x5 -> 5., x6 -> 6., x7 -> 7., x8 -> 8., x9 -> 9., x10 -> 10.}}}

Which corresponds to inserting the symbolic form directly:

NMinimize[
  Sqrt[(x1 - 1.0)^2 + (x2 - 2.0)^2 + (x3 - 3.0)^2 + (x4 - 4.0)^2 + (x5 - 5.0)^2 + (x6 - 6.0)^2 + (x7 - 7.0)^2 + (x8 - 8.0)^2 + (x9 - 9.0)^2 + (x10 - 10.0)^2], {x1, x2, x3, x4, x5, x6, x7, x8, x9, x10}
  ] // AbsoluteTiming

{0.00434, {3.20225*10^-6, {x1 -> 1., x2 -> 2., x3 -> 3., x4 -> 4., x5 -> 5., x6 -> 6., x7 -> 7., x8 -> 8., x9 -> 9., x10 -> 10.}}}
$\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.