8
$\begingroup$

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

$\endgroup$
3
  • $\begingroup$ I cannot reproduce this pb on mma 9 macos. try x=. first? $\endgroup$
    – chris
    Aug 14, 2014 at 16:14
  • $\begingroup$ minimizing a function of 63 variable can be a bit challenging :-) $\endgroup$
    – chris
    Aug 14, 2014 at 20:32
  • $\begingroup$ @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. $\endgroup$
    – MOON
    Aug 14, 2014 at 20:38

2 Answers 2

11
$\begingroup$

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

$\endgroup$
6
  • $\begingroup$ 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. $\endgroup$
    – MOON
    Aug 14, 2014 at 19:55
  • $\begingroup$ Does my edit answer your question? $\endgroup$ Aug 15, 2014 at 8:57
  • $\begingroup$ Yes it works. Thank you. Although I have to install C compiler to use the CompilationTarget. $\endgroup$
    – MOON
    Aug 15, 2014 at 9:41
  • $\begingroup$ Sorry yes, though the Windows SDK should be straightforward enough to download. $\endgroup$ Aug 15, 2014 at 9:45
  • $\begingroup$ 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. $\endgroup$ Dec 16, 2014 at 1:17
1
$\begingroup$

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. *)

$\endgroup$
4
  • $\begingroup$ I got this error, although it returns the answer: CompiledFunction::cfsa: Argument x1 at position 1 should be a machine-size real number. >> $\endgroup$
    – MOON
    Aug 14, 2014 at 21:00
  • $\begingroup$ 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. $\endgroup$ Aug 15, 2014 at 9:05
  • $\begingroup$ sure but the OP wanted to demonstrate that the pb came from compilation over 63 variables. $\endgroup$
    – chris
    Aug 15, 2014 at 9:08
  • $\begingroup$ Yep fair point! $\endgroup$ Aug 15, 2014 at 9:10

Your Answer

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

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