0
$\begingroup$

I'm trying to make my code more efficient so exploring alternatives and providing a simplified example here. Here are 3 different versions I thought of for defining an anonymous function in matlab.

% Version 1 definition in script

clc;
clear;

syms x1 x2;

b = 2;

c = 3.5;

ExampleFunc = @(x1,x2) x1^3 + b*x2 + c;

% Below from command window for version 1

ExampleFunc

ExampleFunc =

 @(x1,x2)x1^3+b*x2+c

ExampleFunc(2.5,5)

ans =

29.1250



% Version 2 definition in script

clc;
clear;

syms x1 x2;

b=2;

c=3.5;

TempExpr = x1^3 + b*x2 + c;

ExampleFunc = @(x1,x2) TempExpr;

% Below results from command window  for version 2

ExampleFunc

ExampleFunc =

 @(x1,x2)TempExpr

ExampleFunc(2.5,5)

ans =

x1^3 + 2*x2 + 7/2

% Version 3 definition in script

clc;

clear;

syms x1 x2 b c;

TempExpr = x1^3 + b*x2 + c;

b=2;

c=3.5;

ExampleFunc = @(x1,x2) TempExpr;

% Below results from command window  for version 3

ExampleFunc

ExampleFunc =

 @(x1,x2)TempExpr

ExampleFunc(2.5,5)

ans =

x1^3 + c + b*x2

Why do the above versions provide different results when I try to query the definition and evaluate for particular values of x1 and x2: -

  • In Version 1, the definition does not show the values of b and c in it (though I understand that as per Matlab documentation the values for b and c are stored in back-end as constant values - Btw, how to check what those exact values are. Typing b, c in command window wouldn't be correct as it will show the values assumed by those 2 variables in the workspace at time of querying and not while defining?).

On the other hand, in Version 2 (and version 3) the definition does not expand out TempExpr (Btw, how to check what TempExpr is? I can type it in but is that the only way?) In case of Version 2, typing TempExpr in command window replaces b and c with values used during its definition. In case of Version 3, typing TempExpr in command window retains b and c in symbolic form?

  • Why does the evaluation at x1=2.5 and x2=5, work correctly for Version 1 (numerical answer provided) while in Version 2 it only shows the underlying definition for ExampleFunc (with b and c substituted based on values used during definition) but does not evaluate at the given point.

In Version 3, neither b and c get substituted and nor is the function evaluated at given values x1, x2?

Intended result: My ultimate goal is to force Version 3 to behave like Version 1 in terms of function evaluation. Reason is in my application, b, c can be thought of as parameters which when defined in symbolic form enables precise definition of TempExpr and then subsequently for particular values of the parameters b and c, I pass the ExampleFunc to fmincon which then evaluates ExampleFunc at specific values of x, x2.

Presently in order to force Version 3 to behave like Version 1, I have to use subs function for definition of ExampleFunc which increases execution time (significant as I'm running fmincon for huge number of parameter combinations). My hope was that by using anonymous functions the values of b, c would be automatically substituted with values used during the anonymous function definition but that is not the behaviour noticed here.

$\endgroup$
  • $\begingroup$ I hope I figured out the right way to provide code sample (selecting the pasted code and clicking on {} button). Would like to know the right way to provide results from command window $\endgroup$ – Hari Jun 27 '14 at 15:09
  • $\begingroup$ I found this interesting text in matlab website which supports my above statement that subs function is slower than using matlabFunction (anonymous function) point 4 - "Evaluating symbolic expressions with the subs function is time-consuming. It is much more efficient to use matlabFunction." $\endgroup$ – Hari Jun 27 '14 at 18:49
1
$\begingroup$

Intended result: My ultimate goal is to force Version 3 to behave like Version 1 in terms of function evaluation. Reason is in my application, b, c can be thought of as parameters which when defined in symbolic form enables precise definition of TempExpr and then subsequently for particular values of the parameters b and c, I pass the ExampleFunc to fmincon which then evaluates ExampleFunc at specific values of x, x2.

If that is what you want to do, why not use a closure?

[ExampleFunc] = function myClosure(b,c)
return @(x1,x2)(x1.^3 + b * x2 + c)

This construct builds upon your existing anonymous function construction by allowing you to bind values of b and c to your anonymous function nonlocally. You can use the closure as a factory to generate a bunch of objective functions with different parameter values.

As for your three examples, the differences between Examples 1 and 2 mainly seem to have to do with scope; when using TempExpr in the anonymous function definition instead of the actual expression, it uses the variables x1 and x2 defined at global scope rather than the anonymous function scope.

The difference between Examples 2 and 3 mainly seems to be that in Example 3, you declare b and c as symbolic variables. I don't see why you need any variables here to be symbolic, since you're only evaluating functions; perhaps I'm missing something.

$\endgroup$
  • $\begingroup$ Thanks for the response. I may not have been clear enough in my post. My workflow is such that the expression "TempExpr" is dynamically generated based on user input and this will be dependent on the 2 parameters a, b and the 2 independent variables x1 and x2. I wouldnt know in advance as to what this expression would look like. If I had known it, I would have used the form of Version 1. I cannot use the suggested approach of closure because it will have the same issues as highlighted in version 3. Now once TempExpr" is generated dynamically, then I provide specific values of a, b as in V3. $\endgroup$ – Hari Jun 30 '14 at 17:43
  • $\begingroup$ To be clearer, I perform a series of computations whose complexity depends on user inputs and the end output is stored in "TempExpr" which has 2 parameters a/b and 2 independent variables x1/x2. Now I have a For loop wherein for specific values of the parameters a/b, I have to minimize the "TempExpr". $\endgroup$ – Hari Jun 30 '14 at 19:04
  • $\begingroup$ This is what am doing right now in order to make it evaluate correctly (but takes ~7 seconds) and my question is if there is a matlab trick to make it faster. In my case, ExampleFunc = matlabFunction(subs(TempExpr,{b, c},{2, 3.5}),'vars',{x1, x2},'file',''); Note, the "TempExpr" is already simplified using simplify function $\endgroup$ – Hari Jun 30 '14 at 20:24

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.