A very strange problem

5 ビュー (過去 30 日間)
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022 年 1 月 14 日
Hi friends!
After spending an hour on a seemingly simple problem I was not able to figour out what is wrong and this is why
I am bothering you, Consider the following commands:
D0=1;D1=1;
f='@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
f=vectorize(f);f=str2func(f);f(1)
which gives me an error saying that "Unrecognized function or variable 'D0'.". But, when I copy the second line and run it, it works!!! To get what I mean the following is what happend on my command window exactly (see also a printscreen of my command window attached)
>> D0=1;D1=1;
f=@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)];
f=vectorize(f);
f=str2func(f);
f(1)
Unrecognized function or variable 'D0'.
Error in code2>@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
>> f=@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)];
>> f(1)
ans =
-1.5
1
I find this really crazy and am impatiently looking forward to hear from you.
Thanks in advance!
Babak
  4 件のコメント
Steven Lord
Steven Lord 2022 年 1 月 14 日
If your functions are that long, change your text files to MATLAB function files and use function handles to those files. This could also allow you to extract out common code segments into helper functions that can be called by one or more of your large function files.

サインインしてコメントする。

採用された回答

John D'Errico
John D'Errico 2022 年 1 月 14 日
編集済み: John D'Errico 2022 年 1 月 14 日
I suppose this is a subtle problem that bears explanation.
D0=1;D1=1;
f='@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
That does NOT create a function handle named f. It is a string. Next, you do this:
f=vectorize(f)
f = '@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]'
That just produces a new string. Still not a function.
f=str2func(f)
f = function_handle with value:
@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
So finally, f exists as a function handle. WHEW!
f(1)
Unrecognized function or variable 'D0'.

Error in solution>@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
But what happened? str2func creates a function handle, returning a result. But str2func does not have D0 in its workspace. So when you try to use f, in the form of f(1), things fail. f does not know the value of D0 or D1, because they do not exist in the workspace of the function str2func.
However, if I do this:
f= @(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]
f =
function_handle with value:
@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]
f(1)
ans =
-1.5
1
now f works, because D0 and D1 were available to f when I created that function handle. It encapsulates them in the workspace internal to the function handle, and all is good. However, f is not "vectorized", as a function of the variable dt.
Anyway, a problem exists, because f returns a vector. you would need to carefully define what that result will be when dt is itself a vector or an array. And as importantly, suppose dt was a row vector, versus a column vector? That code for f, if you blindly throw the vectorize function at it, will produce some screwy results. Magical functions like vectorize are not that intelligent.
Instead, it is far better to vectorize the code yourself. So I might do this, in a way that is insensitive to the shape of dt as a row or column vector.
fvect = @(dt)[(-D0)*dt(:).^0.5+(-D0*D1)*dt(:).^1.5/2 , 1/2*(-1+(1)+(2*D1+2*D0^2)*dt(:)/2)].'
fvect(1)
ans =
-1.5
1
fvect(1:5)
ans =
-1.5 -2.8284 -4.3301 -6 -7.8262
1 2 3 4 5
fvect((1:5)')
ans =
-1.5 -2.8284 -4.3301 -6 -7.8262
1 2 3 4 5
So fvect has been carefully vectorized to produce a result that is consistent with f when called with scalar input, but when called with a vector input, it produces a 2xn array.
Finally, because fvect was constructed directly, it fully encapsulates the values of D0 and D1 as they were found in the workspace when fvect was created.
But expecting vectorize to successfully do that is a bit too much, certainly to know the values of D0 and D1.
  5 件のコメント
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022 年 1 月 14 日
Thanks Torsten for your precious time!

サインインしてコメントする。

その他の回答 (2 件)

KSSV
KSSV 2022 年 1 月 14 日
f='@(D0,D1,dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
f=vectorize(f);
f=str2func(f);
D0=1;D1=1;dt=1 ;
f(D0,D1,dt) % you need to input three variables to the function
ans = 2×1
-1.5000 1.0000
  3 件のコメント
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022 年 1 月 15 日
This is a clever and beautiful solution! (I wish if matlab could use AI techniques and tell me "did you want this?" so that I would not waste a lot of time for such things)
Trying to understand why your therapy works. Perhaps, the clue is that in your solution D0 and D1 are defined after the command f=str2func(f) while in my case if was before.

サインインしてコメントする。


Matt J
Matt J 2022 年 1 月 14 日
An alternative solution is to download afslim() from,
D0=1;D1=1;
f='@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
f=afslim(vectorize(f),D0,D1)
f = function_handle with value:
@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
f(1)
ans = 2×1
-1.5000 1.0000
  1 件のコメント
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022 年 1 月 15 日
This is great! Thanks!

サインインしてコメントする。

Community Treasure Hunt

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

Start Hunting!

Translated by