A MATLAB function with mixed scalar and vector as inputs fail

1 回表示 (過去 30 日間)
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022 年 9 月 7 日
コメント済み: Walter Roberson 2022 年 9 月 8 日
Hello,
I have a question which I explain by a simple example first. Consider the matlab function
H=@(x,x0,par1,par2)[x+par1 x.^2+par2;1-x.^2-par2 x.^3+par1];
where here x and x0 are vectors but par1 and par2 are scalars. So, H should give us matrices as output (if x and x0 are also
scalars then such matrices are square, otherwise we get non-square matrices). Any of the combinations H([1; 2],[3; 4],1,2), H([1; 2],[3 4],1,2)
H([1 2],[3; 4],1,2) and H([1 2],[3 4],1,2) works and MATLAB does not through any error message.
Now, consider the attached matlab function H_LL(x,x0,par1,par2,par3,par4,par5) which is just longer and has 5 parameters, instead of 2. Unfortunately, this only works if x and x0 are only scalars (and I do not know why!!!)
It would be great if you have an idea what's wrong here?
Thanks
Babak
  2 件のコメント
David Hill
David Hill 2022 年 9 月 7 日
Given an example of your inputs and what you expect for the size of the output.
dpb
dpb 2022 年 9 月 7 日
function h_LL = H_LL(x,x0,par1,par2,par3,par4,par5)
%H_LL
% H_LL = H_LL(X,X0,PAR1,PAR2,PAR3,PAR4,PAR5)
% This function was generated by the Symbolic Math Toolbox version 8.6.
% 07-Sep-2022 16:46:14
t2 = par4.^2;
t3 = x.^2;
t4 = x.^3;
t6 = 1.0./par2;
t8 = 1.0./par5.^2;
t9 = 1.0./par5.^3;
t10 = -x0;
t5 = t3.^2;
t7 = t6.^2;
t11 = t6.*x;
t12 = t2+t3;
t13 = t11-1.0;
t14 = 1.0./t12;
t15 = t14.^2;
t16 = t14.^3;
t17 = (par1.*t13.*x)./1.0e+2;
t18 = (par3.*t3.*t14)./1.0e+2;
t20 = (par1.*t4.*t7.*t8.*t13)./1.0e+2;
t21 = (par1.*t5.*t7.*t8.*t14)./1.0e+2;
t24 = (t4.*t8.*t13.*t14)./1.0e+2;
t19 = (par3.*par4.*t5.*t8.*t16)./5.0e+1;
t22 = (par1.*par3.*par4.*t5.*t7.*t8.*t15)./5.0e+1;
t25 = (par3.*par4.*t4.*t8.*t13.*t15)./5.0e+1;
t26 = -t24;
t27 = t10+t17+t18+x;
t23 = -t22;
t28 = t3.*t7.*t8.*t27;
t29 = par1.*t3.*t7.*t9.*t27.*2.0;
t31 = t9.*t13.*t27.*x.*2.0;
t32 = t3.*t9.*t14.*t27.*2.0;
t33 = par4.*t3.*t8.*t15.*t27.*2.0;
t34 = par3.*par4.*t3.*t9.*t15.*t27.*4.0;
t30 = -t29;
t35 = -t34;
t36 = t20+t28;
t37 = t19+t33;
h_LL = reshape([t3.*t8.*t13.^2.*(-1.0./1.0e+2),t36,t26,t25,t31,t36,par1.^2.*t5.*t7.^2.*t8.*(-1.0./1.0e+2)-par1.*t3.*t6.^3.*t8.*t27.*2.0,t21,t23,t30,t26,t21,t5.*t8.*t15.*(-1.0./1.0e+2),t37,t32,t25,t23,t37,par3.^2.*t2.*t5.*t8.*t15.^2.*(-1.0./2.5e+1)+par3.*t3.*t8.*t15.*t27.*2.0-par3.*t2.*t3.*t8.*t16.*t27.*8.0,t35,t31,t30,t32,t35,t8-t8.^2.*t27.^2.*3.0e+2],[5,5]);
What a nightmare!
But, all kinds of things have to be so for that to work -- specifically with respect to x, at a bare minimum without looking hard we find
...
t3 = x.^2;
...
t17 = (par1.*t13.*x)./1.0e+2;
t18 = (par3.*t3.*t14)./1.0e+2;
...
which will require x be same dimensions as par1 or a scalar that can multiply anything on an element-by-element basis.
Trying to make any sense of of this without what generated it is hopeless -- and trying to generalize it to anything other than that specific case is, as well....

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

採用された回答

Walter Roberson
Walter Roberson 2022 年 9 月 7 日
h_LL = reshape([t3.*t8.*t13.^2.*(-1.0./1.0e+2),t36,t26,t25,t31,t36,par1.^2.*t5.*t7.^2.*t8.*(-1.0./1.0e+2)-par1.*t3.*t6.^3.*t8.*t27.*2.0,t21,t23,t30,t26,t21,t5.*t8.*t15.*(-1.0./1.0e+2),t37,t32,t25,t23,t37,par3.^2.*t2.*t5.*t8.*t15.^2.*(-1.0./2.5e+1)+par3.*t3.*t8.*t15.*t27.*2.0-par3.*t2.*t3.*t8.*t16.*t27.*8.0,t35,t31,t30,t32,t35,t8-t8.^2.*t27.^2.*3.0e+2],[5,5]);
You have 25 components in the [], each the same size as your x input. You ask to reshape() that to a 5 x 5 matrix. If x is scalar, that works out fine, a 1 x 25 reshaped to 5 x 5 fits perfectly. But if x were (for example) length 2, you would have a 1 x (25*2) array being reshaped to 5 x 5, and you cannot reshape 50 elements into 25 spaces.
You could edit the code to reshape the input x into the third dimension,
x = reshape(x, 1, 1, []);
and then in the assignment to h_LL you could change the reshape from [5,5] to 5, 5, [] . This would give you a 5 x 5 x numel(x) result... at the expense of having to manually edit the code.
You cannot convince the Symbolic Toolbox matlabFunction() to itself properly vectorize a function that returns an array (or a function that uses piecewise() or some other functions such as int()) .
  2 件のコメント
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022 年 9 月 8 日
Hi Walter,
As you can see I never created this matlab function (well, I did :-) ), it is automatically generated by matlab symbolic toolbox because I used the following command
H_LL=matlabFunction(H_LL,'File','H_LL','vars',[x x0 par],'Outputs',{'h_LL'});
This way matlab 'optimizes' the matlab function (this is why you see a lot of t_i's. It looks ugly but is is supper nice since this way calling the function is much faster). If, instead, I would use the command
H_LL=matlabFunction(H_LL,'File','H_LL','vars',[x x0 par],'Outputs',{'h_LL'},'Optimize',false);
then I would not run into this problem but my code would get slower, unfortunately.
I think that there should be a way to fix this problem in matlab for any general function. I can, of course, fis this specific function but this does not make me happy since I could have any other function. So, I hope that in the future this issue gets fixed which means: 1) users can use the 'optimize' option and 2) They do not run into any error message once they want to work with the matlab function being optimized.
Thanks
Babak
Walter Roberson
Walter Roberson 2022 年 9 月 8 日
This is not going to get "fixed". This is fundamental to the design of the Symbolic Toolbox. All symbolic variable names are scalars and are calculated with as scalars. matlabFunction makes no attempt to check input sizes against output sizes

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

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeEntering Commands についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by