14

7

In this great answer a compiled version of the Nelder-Mead algorithm is presented.

Since it works on arbitrary dimensions (i.e. arbitrary number of arguments), it has to use apply on the objective function. The problem is that `Apply`

is not directly supported inside `Compile`

. To overcome this limitation the following code is used:

```
(* Produces compiled code for the Nelder-Mead algorithm with the objective function inlined *)
ClearAll[apply];
SetAttributes[apply, HoldAll];
apply[f : (_Function | _CompiledFunction), vars : {__Symbol}] :=
With[{applied := f @@ vars},
Function[arglist, Block[vars, vars = arglist; applied]]
];
```

This seems to work (inside the package), but I have no idea, how it works.

**Could somebody explain the techniques behind this code snippet?** Specifically:

- What does
`SetDelayed`

do inside`With`

? Why does

`vars`

appear twice in the arguments to`Block`

?Why doesn't this minimal example work? (I believe it mimics what is done in the mentioned answer...)

`Clear[a, b, c, x, y, z, objectiveFunction, cfunc]; objectiveFunction = Compile[{a, b, c, x, y, z} , (a - x)^2 + 50 (b - y)^2 + (c - z)^2]; cfunc = With[{f = apply[objectiveFunction, {a, b, c, x, y, z}]}, Compile[ {{pts, _Real, 1}}, f@pts] ] << CompiledFunctionTools` CompilePrint[cfunc]`

**EDIT:**

Here is the working snippet. Note that `"InlineCompiledFunctions"`

must be set to `True`

to avoid the call to `MainEvaluate`

.

```
ClearAll[a, b, c, x, y, z, apply, objectiveFunction, cfunc];
(* Produces inlinable code for use inside Compile (where Apply is not \
supported directly) *)
SetAttributes[apply, HoldRest];
apply[f : (_Function | _CompiledFunction), vars : {__Symbol}] :=
Function[arglist, Block[vars, vars = arglist; f @@ vars]];
objectiveFunction = Compile[{a, b, c, x, y, z} ,
(a - x)^2 + 50 (b - y)^2 + (c - z)^2];
apply[objectiveFunction, {a, b, c, x, y, z}]
cfunc = With[{f = apply[objectiveFunction, {a, b, c, x, y, z}]},
Compile[ {{pts, _Real, 1}}, f@pts,
CompilationOptions -> {"InlineCompiledFunctions" -> True}]
]
<< CompiledFunctionTools`
CompilePrint[cfunc]
```

This makes me wonder why is the a system option called ApplyCompileLength and why is it set to Infinity – Szabolcs – 2012-05-04T09:12:19.860

2@Szabolcs This is an entirely different story.

`Apply`

as discussed here evaluates at (pre)`Compile`

-time and is a tool of code generation. The option you mention governs the auto-compilation of`Apply`

, when it would be explicitly present in the`Compile`

body when auto-compiling. Since`Apply`

is only supported for 3 heads (`List`

,`Plus`

and`Times`

) by`Compile`

, it does not generally make sense to set the mentioned option to a finite number. In case you have one of those heads, you can of course reset it. – Leonid Shifrin – 2012-05-04T09:18:32.393@Leonid (It was really a question, not a comment...) Is it documented somewhere that it's supported for these three heads? Do you know why that option is set to

`Infinity`

? – Szabolcs – 2012-05-04T09:27:09.497@Szabolcs It is documented, but I can't tell you where off hand. For the option setting,

`Infinity`

is equivalent to saying "don't attempt to auto-compile at all". The fact that only 3 heads are supported means that`Compile`

does notgenerally support`Apply`

, which is probably the reason for this setting. For those heads, it can be reset manually, as I mentioned. – Leonid Shifrin – 2012-05-04T09:33:56.067