6
$\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$
3
  • $\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$ Sep 7, 2018 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$ Sep 7, 2018 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$ Sep 7, 2018 at 11:26

1 Answer 1

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$
6
  • 1
    $\begingroup$ Thank you for your tough answer, I will need a nonpredictable amount of time to understand it.... $\endgroup$ Sep 7, 2018 at 12:20
  • $\begingroup$ @UlrichNeumann I will try to add some explanations when I get a spare moment. $\endgroup$ Sep 7, 2018 at 12:55
  • $\begingroup$ Thanks again for your effort!. $\endgroup$ Sep 7, 2018 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$ Sep 8, 2018 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$ Sep 9, 2018 at 19:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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