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.
Consider the Rosenbrock function in http://www.mathworks.com/help/optim/ug/writing-objective-functions.html#brhkghv-6
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
채택된 답변
Star Strider
2014년 6월 29일
편집: Star Strider
2014년 6월 29일
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
Hari
2014년 6월 30일
편집: Star Strider
2014년 6월 30일
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.
Hari
2014년 6월 30일
편집: Star Strider
2014년 6월 30일
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
Star Strider
2014년 6월 30일
편집: Star Strider
2014년 6월 30일
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)
Star Strider
2014년 6월 30일
편집: Star Strider
2014년 6월 30일
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.
추가 답변 (0개)
카테고리
도움말 센터 및 File Exchange에서 Code Performance에 대해 자세히 알아보기
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!웹사이트 선택
번역된 콘텐츠를 보고 지역별 이벤트와 혜택을 살펴보려면 웹사이트를 선택하십시오. 현재 계신 지역에 따라 다음 웹사이트를 권장합니다:
또한 다음 목록에서 웹사이트를 선택하실 수도 있습니다.
사이트 성능 최적화 방법
최고의 사이트 성능을 위해 중국 사이트(중국어 또는 영어)를 선택하십시오. 현재 계신 지역에서는 다른 국가의 MathWorks 사이트 방문이 최적화되지 않았습니다.
미주
- América Latina (Español)
- Canada (English)
- United States (English)
유럽
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
