# How to disable symbolic preprocessing in NMinimize without performance loss?

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?

• You can turn the processing off in Compile via RuntimeOptions. That'll probably serve you best. – b3m2a1 May 9 at 0:25
• The performance difference is probably due to the compiled function evaluating symbolically in the first case. You're not really using the compiled function. – Michael E2 May 9 at 0:53
• @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. – Shadowray May 9 at 21:03
• @Shadowray what I'm saying is that Compile can be told to ignore symbolic options. That'll speed things up a lot. – b3m2a1 May 9 at 21:05

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.}}}