Hello,
One of you did kindly respond my question (my question was very similar to this one) but I again ran into problem and need to bother you again. Sorry for this. Consider the following
>> syms x y p1 p2
h=[x*y+p1 y^2-1;x^3+p2^2 1-x^2+p1*p2];
H=matlabFunction(h)
H =
function_handle with value:
@(p1,p2,x,y)reshape([p1+x.*y,p2.^2+x.^3,y.^2-1.0,p1.*p2-x.^2+1.0],[2,2])
I am not happy with this. I would prefer the 'reshape' to be removed. Why? because this is never convenient in letting me to to do vector operations. For instance, if I use the command H(1,2,[3 4],[5 6]) then matlab throws an erros message. How can I tell matlab PLEASE make the following matlab function for me:
H=@(p1,p2,x,y)[x*y+p1 y^2-1;x^3+p2^2 1-x^2+p1*p2];
I know how to tackle this problem when all inputs p1,p2,x,y have the same size (I can fix it by the command HL = @(p1v,p2v,xv,yv) arrayfun(H, p1v,p2v,xv,yv, 'Unif',0);).
However, here p1 and p2 are scalar parameters while x and y are (row) vectors of the same size (like H(1,2,[3 4],[5 6]), as I mentioned above). The best way to tackle this problem for me is as follows:
I would prefer the output to be a 3D array where the first page is H(1,2,3,5) and the second page is H(1,2,4,6).
Thanks for your kind help, in advance!
Babak

2 commentaires

Steven Lord
Steven Lord le 8 Sep 2022
Since this question appears to be a continuation of https://www.mathworks.com/matlabcentral/answers/1800275-inconveniences-working-with-matlabfunction you should probably add comments to that question (which has already received several comments and answers) rather than posting a new question.
Hi Steven,
Sorry for this. I continue with my former question (which I did already).

Connectez-vous pour commenter.

 Réponse acceptée

I responded to your original post and Comment.
Reposting here —
This is an application of passing extra parameters. As such, it now needs a separate function call in order to work correctly.
Try this —
Hmtx = cat(3, Hfcn(1,2,3,5), Hfcn(1,2,4,6))
Hmtx =
Hmtx(:,:,1) = 16 24 31 -6 Hmtx(:,:,2) = 25 35 68 -13
function M = Hfcn(p1,p2,v1,v2)
H = @(p1,p2,x,y)reshape([p1+x.*y,p2.^2+x.^3,y.^2-1.0,p1.*p2-x.^2+1.0],[2,2]);
C = arrayfun(@(xv,yv)H(p1,p2,xv,yv),v1,v2, 'Unif',0);
M = cell2mat(C);
end
.

Plus de réponses (2)

If you don't need to work in symbolics, don't.
h=@(p1,p2,x,y)[x.*y+p1,y.^2-1;x.^3+p2^2, 1-x.^2+p1*p2];
h(1,2,[3 4],[5 6])
ans = 2×4
16 25 24 35 31 68 -6 -13
Walter Roberson
Walter Roberson le 8 Sep 2022

0 votes

Sorry, but matlabFunction() is not going to change about this, as it involves a fundamental model of what symbolic variables are and how they are manipulated.

8 commentaires

Hi Walter,
I have a different personal opinion. I think that it is time to consider matlabFunction() with a flag like 'no change' (or similar names). Let me explain a bit. Consider the following matlab function:
syms x
f1 = [x; 1] ; f2 = [x 1;2 x.^2];
f1 = matlabFunction(f1); f2 = matlabFunction(f2);
which gives us f1 = @(x)[x;1.0]; f2 = @(x)reshape([x,2.0,1.0,x.^2],[2,2]). Both of these are bad in the sense that none of them let you to do vector caculations. For instance, I cannot calculate f1([1 2]) or f2([1 2]). And, when we try to fix these annoying problem using the following it also fails:
syms x
f1 = [x; 1+0.*x] ; f2 = [x 1+0.*x;2+0.*x x^2];
f1 = matlabFunction(f1); f2 = matlabFunction(f2);
which also fails because matlab has simplified f1 and f2 "WITHOUT MY PERMISION".
How do I fix such issues often?
To fix the above mentioned ANOYANCES I need to resort to character calculations and use the command str2func as bellow:
syms x ANNOYANCE
f1 = [x; 1] ; f2 = [x 1;2 x^2];
f1(~has(f1,x))=f1(~has(f1,x))+ANNOYANCE;
f2(~has(f2,x))=f2(~has(f2,x))+ANNOYANCE;
f1=char(f1);f2=char(f2);
f1=vectorize(f1);f2=vectorize(f2);
f1=replace(f1,'ANNOYANCE',strcat(['0.*' char(x)]));
f2=replace(f2,'ANNOYANCE',strcat(['0.*' char(x)]));
f1=append('@(x)',f1);
f2=append('@(x)',f2);
f1=str2func(f1);
f2=str2func(f2);
So, in sum, it is time to put an end to this (I know, you might have a better idea to fix this but you will also have to write some lines and put effort to fix it). So, my suggestion is the following:
"KEEP MATLABFUNCYION AS IT IS BUT JUST CONSIDER AN EXTERA FLAG LIKE
F = matlabFunction(f, 'no change')"
I hope I could convince you!
Let me know!
Thanks,
Babak
You are misunderstanding what is happening. Consider
syms x
f = 3*x^2 + 2*x + 1
f = 
y1 = 5*diff(f,x)
y1 = 
y2 = 7*diff(f,x,x)
y2 = 
42
g1 = matlabFunction(y1, 'vars', x)
g1 = function_handle with value:
@(x)x.*3.0e+1+1.0e+1
g2 = matlabFunction(y2, 'vars', x)
g2 = function_handle with value:
@(x)4.2e+1
g3 = matlabFunction(7*diff(f,x,x), 'vars', x)
g3 = function_handle with value:
@(x)4.2e+1
You can see that g3 does not take into account the size() of x -- if you were to pass in a vector of length 5 it would only return scalar 42 not a vector that repeated 42 as many times as elements there were in x.
But if you look at y2 you can see that the 7*diff(f,x,x) has already lost the size of x and become the constant 42.
So it is not the case that matlabFunction() is examining its input and optimizing some internal repmat(42, size(x)) away to a simple scalar 42 -- matlabFunction() only receives the 42 with no information about where it came from. matlabFunction() emits based upon the information it is given.
Now consider
f1 = matlabFunction([x; 1])
if you pass in a column vector for x, then what is the desired output? Should the output of f1([3;2]) be [3;2;1] or should it be [3;2;1;1] where the constant 1 is being repeated according to the size of x ? It should be clear that you might want different behaviour for different constants. For example,
f2 = matlabFunction([x;1;0*x])
That hints that you might want just a scalar 1, but that you want 0's the same size as x. But what matlabFunction recieves is going to be [x; 1; 0] because [x;1;0*x] is going to be evaluated before it reaches matlabFunction()
Can we code this using size(), something like
syms x
f3 = matlabFunction([x; 1; zeros(size(x))])
But "syms x" creates a symbolic scalar, so size(x) would be 1 1, so matlabFunction is going to receive [x; 1; 0]
Can you work with the new symbolic matrices?
x = symmatrix('x', [3 2])
f4 = [x;1 1;zeros(size(x))]
%f4 would be vertcat(x, vertcat(symmatrix(ones(1,2)), symmatrix(zeros(3,2))))
but you cannot matlabFunction() a symmatrix so you have to convert to sym:
f5 = matlabFunction( symmatrix2sym(f4), 'vars', symmatrix2sym(x))
% f5 = @(x1_1,x2_1,x3_1,x1_2,x2_2,x3_2)reshape([x1_1,x2_1,x3_1,1.0,0.0,0.0,0.0,x1_2,x2_2,x3_2,1.0,0.0,0.0,0.0],[7,2])
and you are back to a fixed size.
There are currently no circumstances under which you can designate a particular expression as being variable size and convince matlabFunction() to generate appropriate code that takes into account the size at run-time.
Let us consider
syms y z
f6 = y - y + z - z
f5 is going to receive scalar 0. If somehow you had designated y and z as variable size, a hypothetical
varsizesym y z %hypothetical
f6 = y - y + z - z
then the expression would have to generate something like
f6 = varsizesym(0, y) + varsizesym(0, z)
What is the size of f6? Because of implicit expansion, we do not know until fairly late in the computation...
We can imagine that we might want f7 = [1; f6] -- but is that 1 intended to be scalar 1, or is it intended to be 1 with the size number of columns as f6, or is it intended to be 1 with the same number of rows as f6...
so we start needing (hypothetical) code such as
f7 = varsizesym(1, 'width', f6)
but as we extend into 3 or more dimensions, naming the dimensions becomes unworkable, so we start needing varsizesym(1, 'size', symsize(f6)) where symsize(f6) is the runtime size of f6...
You can see that this is all a lot more complicated that just adding a flag to matlabFunction: it would require adding new symbolic operations that return unresolved until subs() is used.
Speaking of subs(), what if what you subs() in is a symbolic vector that includes an unresolved symbolic variable name? If it includes a (hypothetical) varsizesym symbolic variable? How do we define the sizes properly?
Hi Walter,
Well. You are 96.56 % right :-)
You said that:
f1 = matlabFunction([x; 1])
if you pass in a column vector for x, then what is the desired output? Should the output of f1([3;2]) be [3;2;1] or should it be [3;2;1;1] where the constant 1 is being repeated according to the size of x ? It should be clear that you might want different behaviour for different constants.
Well, the output of f1([3;2]) should be [3;2;1] not [3;2;1;1]. Why? Because, [3;2] is a column vector and is consistent with f1. My point was not about such cases. My point was about situations where we get dimensionality mismatch. So, the right question is to ask: "How to compute f1([3 2])?" This is the case of dimensional mismatch. Therefore, I suggested that in such cases we need a 'smarter' matlabFunction to 'read our mind' (aren't we living in the era of arteficial inteligence?) and if I have defined f1 = matlabFunction([x; 1], 'loose') (based on your correct comments expressions get simplified before and this has nothing to do with matlabFunction. So, I thought the flag 'loose' is more indicative than 'no change') it should not throw any error message with regard to dimensional mismatch. If you think deeply you will see that there is just 'one way' for this to make sense and that unigue way is to interpret f1([3 2] as [3 2;1 1].
Well, I completely understand that my suggestion might be difficult to implement as it might be inconsistent with many other issues. At the end, you definitely know more than a person like me.
Suppose you have
syms x
f = [1 2 3; 4 x 6; 7 8 9]
F = matlabFunction(f, 'loose') %hypothetical keyword
What output would you expect for F([100 200]) ? What output would you expect for F([300; 400]) ?
Now suppose you have
syms x y
g = [x; y]
G = matlabFunction(g, 'loose')
What output would you expect for G(1, [20 30]) ? What output would you expect for G([10; 11], 40) ? What output would you expect for G([10; 11], [50 60]) ?
f = [1 2 3; 4 x 6; 7 8 9]
g = [x; y]
Personallly I would love to have they behaves like auto-expansion but on array construction, not only for symbolic variable but also for non-symbolic objects.
(In the first case f only x that is "vector" along dimension > 2 can be accepted).
Hi Walter,
Sorry to respond VERY late (I was extremely sick over the past 10 days. still ...). My answers in bellow:
1) syms x
f = [1 2 3; 4 x 6; 7 8 9]
F = matlabFunction(f, 'loose')
What is F([100 200])?
Answer: F([100 200]) =
[1 2 3
4 [100 200] 6
7 8 9]
So, as I mentionec before, this is the case of dimensional mismatch. Based on what I mentioned the answer is
[1 2 2 3
4 100 200 6
7 8 8 9]
Why? Here, Second column has problem. Rows do not have any problem. To make sense of this it can be uniquely understood that the correction matrix should have the size 3*4. Since in the second column we have a criminal object [100 200] where the first part, i.e., 100 is ok but here 200 is the annoying part to be fixed. So, here we keep 100 and repeat the second column again and use 200 in place of 100 (if you think , this is unique).
2)syms x y
g = [x; y]
G = matlabFunction(g, 'loose')
What is G(1, [20 30]) ?
Answer: G(1, [20 30]) =
[1
[20 30]]
This is the case of dimensional mismatch again. Here, rows do not have any problem. But columns have. So, we should seek a 2*2 matrix to fix this. Clearly, based on what I have mentioned before the unique answer is
[1 30
20 30]
What is G([10; 11], [50 60])?
Answer: G([10; 11], [50 60]) =
[[10
11]
50 60]
Here, rows are fine. We need to fix columns. Then the answer is
[10 60
50 60]
Well, you know better and more!
Huh. I would have guessed that it would be the 1 that should be duplicated, not the 30.
No. The correction should be for the elements we have mismatch issue which is 30. This was the point
in my comments: if we get dimensional mismatch becose one component, say component i, does not match the rest then the correction should be performed in a way to replicate the 'non-matching' parts of compontnt i to the rest of dimensions. Well, it is not unique, unlike what I said before but based on the mentioned 'principle' it seems to be a unique cvorection. Anyway, I find this useful and a very natural and useful correction to the mismatch dimensional problems.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Programming dans Centre d'aide et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by