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.
Hari
2014 年 6 月 30 日
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).
Hari
2014 年 6 月 30 日
"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.
Hari
2014 年 7 月 2 日
Thanks for the tip on creating anonymous function with both x + a/b as parameters.
Star Strider
2014 年 7 月 3 日
Did it solve your problem, or are we still working on it?
Hari
2014 年 7 月 5 日
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,
Star Strider
2014 年 7 月 5 日
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.
John D'Errico
2014 年 7 月 5 日
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!Web サイトの選択
Web サイトを選択すると、翻訳されたコンテンツにアクセスし、地域のイベントやサービスを確認できます。現在の位置情報に基づき、次のサイトの選択を推奨します:
また、以下のリストから Web サイトを選択することもできます。
最適なサイトパフォーマンスの取得方法
中国のサイト (中国語または英語) を選択することで、最適なサイトパフォーマンスが得られます。その他の国の 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)
