5
$\begingroup$

Using Mathematica the definition of user functions , which return "pure functions" is quite easy

f[list_] := Function[t, Sin[list[[1]] t] + list[[2]] Cos[t]]
Plot[f[{2, 1}][t], {t, 0, 2 Pi}]

and often very useful. Please note the use of f[liste][time] with separated argument brackets.

My question: Is it possible to pre-compile the part f[list] in such a way that it returns a pure function object?

here a small example to clarify my question:

pg[a_(*liste *)] := Interpolation[{{0, 0}, {.4, a[[1]]}, {.8, a[[2]]}, {1, 1}} , InterpolationOrder -> 1]

defines a polygon with two variable points. pg[a] is a pure function object which can be used to find the polygon pg[a][x]~=x

opt = NMinimize[Sum[(trapez[{a, b}][x] - x)^2, {x, 0, 1, .2}], {a, b}] 
$\endgroup$
  • $\begingroup$ It is not clear to me why you want to compile the creation of the actual function. Oftentimes, it will be helpful enough to create the function only once, like in f[list_] := Function[t, Evaluate[Sin[list[[1]] t] + list[[2]] Cos[t]]]; g = f[{2, 1}]; Plot[g[t], {t, 0, 2 Pi}] $\endgroup$ – Henrik Schumacher Sep 7 '18 at 10:59
  • $\begingroup$ Thanks! My intention is to create an approximation function , which depends on a list of paramaters. Something like Interpoaltion[data[parameters]] These parameters are evaluated in a minimization process(involving NDSOlve,NMinimize), which calls the function repeatedly. For performance issues I would like to try a compiled version. $\endgroup$ – Ulrich Neumann Sep 7 '18 at 11:16
  • $\begingroup$ Hm. I don't get it. Would you please try to give a more concrete example that emphasizes where the performance bottleneck is? Btw.: Compiled functions cannot return a pure function. And if complex functions such as NMinimize or NDSolve appear in the code, it is usually not a good idea to compile it. But there might be other ways to speed up your code. $\endgroup$ – Henrik Schumacher Sep 7 '18 at 11:26
8
$\begingroup$

Here is simple code to get you going:

Clear[inferType];
inferType[arg_Integer] := _Integer
inferType[arg:_Real | _?NumericQ /; Re[arg]==arg] := _Real
inferType[arg_List] /; ArrayQ[arg,_,IntegerQ]:=   
   {_Integer,Length[Dimensions[arg]]};
inferType[arg_List] /; ArrayQ[arg,_,NumericQ] && Re[arg]==arg:=
   {_Real,Length[Dimensions[arg]]};
inferType[_]:= General;

ClearAll[memoize, compile, $preprocessingRules]

$preprocessingRules  = {
   p: HoldPattern[Part[list:{__Integer}, part_Integer]] :> 
      RuleCondition[p]
};

memoize[fn:HoldPattern[Function[var_, body_]], General]:= compile[fn] = fn

memoize[fn:HoldPattern[Function[var_, body_]], {t__} | t__] := compile[fn] =  
    Replace[
        ReplaceAll[Hold[body], $preprocessingRules],
        Hold[preprocessed_] :> Compile[{{var, t}}, preprocessed]
    ]

compile[fn:HoldPattern[Function[var_, body_]]][arg_]:= 
    memoize[fn, inferType[arg]][arg]

And then

f[list_]:=compile[Function[t,Sin[list[[1]] t]+list[[2]] Cos[t]]]

and

Plot[f[{2, 1}][t], {t, 0, 2 Pi}]

You can check what function was generated by calling

?compile

Both type-inferencer and preprocessor are very simplistic, and this is for one - argument function only, but this can be a starting point, if you want this kind of things.

$\endgroup$
  • 1
    $\begingroup$ Thank you for your tough answer, I will need a nonpredictable amount of time to understand it.... $\endgroup$ – Ulrich Neumann Sep 7 '18 at 12:20
  • $\begingroup$ @UlrichNeumann I will try to add some explanations when I get a spare moment. $\endgroup$ – Leonid Shifrin Sep 7 '18 at 12:55
  • $\begingroup$ Thanks again for your effort!. $\endgroup$ – Ulrich Neumann Sep 7 '18 at 13:02
  • $\begingroup$ What do you think about this variant Compile[{{list , _Real, 1}}, Function[t, Sin[list[[1]] t] + list[[2]] Cos[t]] &]? What is the difference to your solution? Thanks! $\endgroup$ – Ulrich Neumann Sep 8 '18 at 20:35
  • $\begingroup$ @UlrichNeumann The difference is that my code gets compiled dynamically, already after list variable value gets injected into Compile. Your suggestion won't work as intended, because Compile can't return a compiled pure function, and so the Function will remain uncompiled. $\endgroup$ – Leonid Shifrin Sep 9 '18 at 19:16

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.