Why does the anonymous function not evaluate correctly

I posted this in stack exchange comp science site 2 days back but couldn't get a response. Will restate with a simplified example and hope I get some directions.
Defining the following in a script (modifying matlab example for how x is inputted) and run it,
clc; clear;
anonrosen = @(x1,x2)(100*(x2 - x1^2)^2 + (1-x1)^2);
and then typing the following in command window,
anonrosen(-1,2)
yields,
ans =
104
But if I define the following in a script and run it,
clc; clear;syms x1 x2;
p = (100*(x2 - x1^2)^2 + (1-x1)^2);
anonrosen = @(x)p;
and then typing the following in command window,
anonrosen(-1,2)
yields,
ans =
(x1 - 1)^2 + 100*(- x1^2 + x2)^2
Why don't I get 104 as answer in 2nd approach?
The reason I want to make the 2nd approach work is the functional form "(100*(x2 - x1^2)^2 + (1-x1)^2)" in my application is being generated on the fly during application run depending on user inputs using symbolic toolbox so I cannot hard-code it the way it is done in matlab example code.
Thanks in advance Hari

 Accepted Answer

You have to define functions differently in the Symbolic Math Toolbox:
syms x1 x2
anonrosen = symfun(100*(x2 - x1^2)^2 + (1-x1)^2, [x1 x2])
anonrosen(-1,2)
produces:
anonrosen(x1, x2) =
(x1 - 1)^2 + 100*(- x1^2 + x2)^2
ans =
104

11 Comments

Thanks for the tip on symfun. I wasn't aware of this.
I have one follow-up question. I had simplified my original requirement and in my actual application the functional form is generated dynamically based on certain user inputs and this functional form is expressed in terms of decision variables x1, x2 as well as parameters a and b. Then for specific combination of parameters a and b, I'm passing my functional form to fmincon.
For example, see the parameterized Rosenbrock function below
clc;clear;
syms x1 x2 a b;
DynamicallyGeneratedParamFunc =(100*(x2 - x1^2)^a + (1-x1)^b);
a= 2; b=3;% providing values for parameters
anonrosen = symfun(DynamicallyGeneratedParamFunc, [x1 x2]);
anonrosen(-1,3);
ans =
100*2^a + 2^b
How do I get anonrosen to evaluate to numeric value by using the values of a and b?
One way, I could do is to use subs function in below,
clc;clear;
syms x1 x2 a b;
DynamicallyGeneratedParamFunc =(100*(x2 - x1^2)^a + (1-x1)^b);
anonrosen = symfun(subs(DynamicallyGeneratedParamFunc,[a b],[2 3]), [x1 x2]);
anonrosen(-1,3);
ans =
408
Is using subs the only way here?
PS: I do need to acknowledge that the same approach of using subs in anonymous function does not work while with symfun it works fine.
I have another follow-up question. Even with using subs within symfun for my application, even though all the parameters and the decision variables x1, x2 get substituted correctly, the answer I get is not simplified to one numeric value but rather a long numerical expression. If I use double function on this long numerical expressions then it evaluates correctly. Why is this happening?
For ex, my dynamically generated function is as follows (In above a and b are the parameters and x1/x2 the decision/independent variables): -
clc; clear;
syms a b x1 x2;
DynamicallyGeneratedParamFunc = (exp(2*a*x1)*exp(2*a*x2)*exp(2*b*x1)*exp(2*b*x2)*(a - b)^6)/(a^2*(a*x1*exp(a*x2)*exp(b*x1) - b*x1*exp(a*x1)*exp(a*x2) - a*x1*exp(b*x1)*exp(b*x2) - a*x2*exp(a*x1)*exp(b*x2) + b*x1*exp(a*x1)*exp(b*x2) + b*x2*exp(a*x1)*exp(a*x2) + a*x2*exp(b*x1)*exp(b*x2) - b*x2*exp(a*x2)*exp(b*x1) + a^2*x1*x2*exp(a*x1)*exp(b*x2) - a^2*x1*x2*exp(a*x2)*exp(b*x1) - a*b*x1*x2*exp(a*x1)*exp(b*x2) + a*b*x1*x2*exp(a*x2)*exp(b*x1))^2);
Now for a = 0.1213 and b= 0.07, I'm creating the symbolic function
MySymbolicFunc = symfun(subs(DynamicallyGeneratedParamFunc,[a b],[0.1213 0.07]), [x1 x2]);
Now in command window when I input the following,
MySymbolicFunc(2.5,5)
ans =
(18226538222455809*exp(5739/2000))/(14713690000000000000000*((1213*exp(21/40))/4000 - (996269*exp(1563/2000))/8000000 - (2829731*exp(2613/4000))/8000000 + (7*exp(3639/4000))/40)^2)
I have to use double function on above to force it to give a numerical value
double(MySymbolicFunc(2.5,5))
ans =
1.0507
In summary, why do I need to use subs (my first comment) and then why do i need to use double (my second comment)
Thanks
Hari
1. How do I get anonrosen to evaluate to numeric value by using the values of a and b ?
  • You have to include a and b in addition to x1 and x2 in the argument list, and then pass the numeric values for them as arguments. So using the subs function is not necessary here.
2. ... the answer I get is not simplified to one numeric value but rather a long numerical expression ... Why is this happening?
  • That is the default Symbolic Math Toolbox behaviour. The vpa function is another way (other than double that you have already discovered) to get a simplified numeric result.
Thanks for the response. The challenge with above approach is that using subs/double on top of the symfun makes the overall script depending on evaluation of this symbolic function quite slow (20+ seconds depending on # of function calls). On the other hand, if I use the following approach
clc;clear;
syms x1 x2 a b;
DynamicallyGeneratedParamFunc =(100*(x2 - x1^2)^a + (1-x1)^b);
MySymbolicFunc = matlabFunction(subs(DynamicallyGeneratedParamFunc,[a b],[0.1213 0.07]),'vars',[x1, x2],'file','');
it evaluates correctly and takes around ~7 seconds for my application. Though this is faster than symfun+double+dubs approach, my original question was to somehow decrease this time further. For example, in above can I somehow do away with subs function as part of matlabFunction (subs takes the most time as per profiler).
"You have to include a and b in addition to x1 and x2 in the argument list, and then pass the numeric values for them as arguments."
I cannot have a and b in arguments of "MySymbolicFunc" as I'm using fmincon to call MySymbolicFunc and fmincon will evaluate MySymbolicFunc for specific values of x1 and x2 but it will not have access to values of a and b. In short, I'm minimizing MySymbolicFunc for known values of a and b. Is there anyway values of a and b can be supplied to MySymbolicFunc before fmincon is invoked (and without using subs)
My pleasure!
If you are going to use it with fmincon, I would use matlabFunction to create an anonymous function (or function file) out of it, then call fmincon with (for example):
x = fmincon(@(x) MySymbolicFunction(x,a,b) ... )
It will then pick up (a,b) from the workspace as anonymous functions usually do, and will optimise with respect to x = [x(1) x(2)]. You may have to do a bit of editing with the Editor’s ‘Search and Replace’ ability (changing x1 to x(1) and similarly for x(2)) to create a vector of parameters for x in your function if you use it as an anonymous function, but it should be relatively easy after that. If you use a function file, simply add the lines:
x1 = x(1);
x2 = x(2);
before the function statement itself to do the same thing.
The Symbolic Math Toolbox is generally not good for such recursive operations. It does single calculations and some short loops well, but is highly inefficient for other procedures that MATLAB does well.
Thanks for the tip on creating anonymous function with both x + a/b as parameters.
Did it solve your problem, or are we still working on it?
Thank you for the continued support (and sorry for delay in getting back). I learned 2 new techniques (symfun and more importantly creating anonymous function with x and a/b as parameters) and I'm sure this would be useful in future as well.
I learnt the answer to my question (anonymous function not resolving correctly) so I will close this question.
PS: Will post a seperate question as I'm (still) having challenges with speeding up this part of the code and will share different ways to do the same thing,
My pleasure!
I wanted to be sure I continued to monitor your question in the event we had not resolved it.
I’ll look for your next Question. Good call on creating it separately, since once an Answer is Accepted (THANKS!) it tends to not be followed-up.
Don't close the question. Don't delete what you wrote. Don't do anything of the sort.
Leave the question there, for others to read and learn from it.
Then accept the answer if it solved your problem. Vote it up.

Sign in to comment.

More Answers (0)

Asked:

on 29 Jun 2014

Commented:

on 5 Jul 2014

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!