9

Consider this code:

variable = Sin[x];
fun = Compile[{{x, _Real}}, variable, CompilationOptions -> {"InlineExternalDefinitions" -> True}];
NMinimize[fun[x], {x}]

This code returns:

 CompiledFunction::cfsa: Argument x at position 1 should be a machine-size real number. >>
 {-1., {x -> -1.5707963267948966}}

Why do I get the error? How can I resolve this issue?

Edit

What if we use instead of Sin an expression like a+b? Because in reality I have an expression with 63 variable which must be find by NMinimize I cannot define a function of that expression and use it instead of Sin

MOON
  • 3,864
  • 23
  • 49
  • I cannot reproduce this pb on mma 9 macos. try x=. first? – chris Aug 14 '14 at 16:14
  • minimizing a function of 63 variable can be a bit challenging :-) – chris Aug 14 '14 at 20:32
  • @chris I already did it but it takes two hours to get the results. I thought if I compile the function which I want to minimize I may get some speed up. In another case, I realized that the compiled function is fast at least 3 times than when I use pure functions. – MOON Aug 14 '14 at 20:38

2 Answers2

12

Update

What if we use instead of Sin an expression like a+b?

I'll try a simple example, namely minimizing $(a + 3)^2 + (b - 3)^2$. Making use of CompilationOptions, I'll define a function with two variables, then nest that inside another compiled function prior to minimization.

Needs["CompiledFunctionTools`"]

myfunction = Compile[{{a}, {b}}, (a + 3)^2 + (b - 3)^2]

With[{variable = myfunction},
  fun = Compile[{{a, _Real}, {b, _Real}},
    variable[a, b],
    "RuntimeOptions" -> {"EvaluateSymbolically" -> False},
    CompilationOptions -> {"InlineCompiledFunctions" -> True},
    CompilationTarget -> "C"]
  ];

NMinimize[fun[x, y], {x, y}]

(* {1.97215*10^-30, {x -> -3., y -> 3.}} *)

You can add // Trace to the NMinimize to check for errors. For example, if you remove the line "RuntimeOptions" -> {"EvaluateSymbolically" -> False}, adding // Trace throws up the cfsa error from before.

And again, let's check all is well with the compilation.

CompilePrint[fun]

(*
    2 arguments
    5 Real registers
    Underflow checking off
    Overflow checking off
    Integer overflow checking on
    RuntimeAttributes -> {}

    R0 = A1
    R1 = A2
    Result = R4

    1   R2 = R0
    2   R3 = R1
    3   R4 = R2 + R3
    4   Return
*)

No calls to MainEvaluate.

Original answer

This works for me.

With[{variable = Sin}, 
  fun = Compile[{{a, _Real}}, variable[a], 
    "RuntimeOptions" -> {"EvaluateSymbolically" -> False}]
  ];
NMinimize[fun[x], x]

And let's check all is well:

Needs["CompiledFunctionTools`"]
With[{variable = Sin}, 
  fun = Compile[{{a, _Real}}, variable[a], 
    "RuntimeOptions" -> {"EvaluateSymbolically" -> False}, 
    CompilationTarget -> "C"]
  ];
CompilePrint[fun]

(*
        1 argument
        2 Real registers
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

        R0 = A1
        Result = R1

        1   R1 = Sin[ R0]
        2   Return
*)

As to why you get this problem, this question should answer it for you: Using a compiled function inside NIntegrate gives "CompiledFunction::cfsa" message

dr.blochwave
  • 8,768
  • 3
  • 42
  • 76
  • What if we use instead of Sin an expression like a+b? Because in reality I have an expression with 63 variable which must be find by NMinimize I cannot define a function of that expression and use it instead of Sin. – MOON Aug 14 '14 at 19:55
  • Does my edit answer your question? – dr.blochwave Aug 15 '14 at 08:57
  • Yes it works. Thank you. Although I have to install C compiler to use the CompilationTarget. – MOON Aug 15 '14 at 09:41
  • Sorry yes, though the Windows SDK should be straightforward enough to download. – dr.blochwave Aug 15 '14 at 09:45
  • I am in need of the similar thing (hopefully) to speed up my optimization. I might be wrong. But did you compile the function twice? (very top example of your post) First compile the function myfunction, then fun again. – Chen Stats Yu Dec 16 '14 at 01:17
  • I did, and CompilationOptions -> {"InlineCompiledFunctions" -> True} ensures it the first function is defined in the second. – dr.blochwave Dec 16 '14 at 23:35
2

In principle 63 variable is not a problem.

Lets define them

var = Table[ToExpression["x" <> ToString[i]], {i, 64}];

and a Quadratic function

Q = var.var;

This defines the function

fun = 
  Compile[Sequence@Map[{{#, _Real}} &, var] // Evaluate, Q, 
   CompilationOptions -> {"InlineExternalDefinitions" -> True}];

and the minimization proceeds as it should

NMinimize[fun @@ var, var]

(*
==> {0., {x1 -> 0., x2 -> 0., x3 -> 0., x4 -> 0., x5 -> 0., 
  x6 -> 0., x7 -> 0., x8 -> 0., x9 -> 0., x10 -> 0., x11 -> 0., 
  x12 -> 0., x13 -> 0., x14 -> 0., x15 -> 0., x16 -> 0., x17 -> 0., 
  x18 -> 0., x19 -> 0., x20 -> 0., x21 -> 0., x22 -> 0., x23 -> 0., 
  x24 -> 0., x25 -> 0., x26 -> 0., x27 -> 0., x28 -> 0., x29 -> 0., 
  x30 -> 0., x31 -> 0., x32 -> 0., x33 -> 0., x34 -> 0., x35 -> 0., 
  x36 -> 0., x37 -> 0., x38 -> 0., x39 -> 0., x40 -> 0., x41 -> 0., 
  x42 -> 0., x43 -> 0., x44 -> 0., x45 -> 0., x46 -> 0., x47 -> 0., 
  x48 -> 0., x49 -> 0., x50 -> 0., x51 -> 0., x52 -> 0., x53 -> 0., 
  x54 -> 0., x55 -> 0., x56 -> 0., x57 -> 0., x58 -> 0., x59 -> 0., 
  x60 -> 0., x61 -> 0., x62 -> 0., x63 -> 0., x64 -> 0.}}
*)

It works more generally for another objective function

 Q = (var - Table[i, {i, 64}]) //(#.# + (#.#)^2) &;
fun = Compile[Sequence@Map[{{#, _Real}} &, var] // Evaluate, Q, 
   CompilationOptions -> {"InlineExternalDefinitions" -> True}];   
NMinimize[fun @@ var, var];//Timing

(* ===> 0.78 sec. *)

chris
  • 22,860
  • 5
  • 60
  • 149
  • I got this error, although it returns the answer:

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

    – MOON Aug 14 '14 at 21:00
  • There's not much point in compiling this though, because when you check CompilePrint[fun] it has lots of calls to MainEvaluate? Indeed, if I just run NMinimize[Q, var] // AbsoluteTiming it takes 0.35 seconds and returns the correct answer with no errors. – dr.blochwave Aug 15 '14 at 09:05
  • sure but the OP wanted to demonstrate that the pb came from compilation over 63 variables. – chris Aug 15 '14 at 09:08
  • Yep fair point! – dr.blochwave Aug 15 '14 at 09:10