Summation with syms not returning a single value

2 次查看(过去 30 天)
I would expect the code below to return (O) just one value for zd=(A(:,3)) as I am summing the matrices.
A = ones(10,3);
syms x y zd
p = sum((x-A(:,1)).^2+(y-A(:,2)).^2+zd);
x = 2;
y = 3;
O = @(zd) double(subs(p));
O(A(:,3))
It rather returns 10 values as if it's not doing the summation. I think there must be an issue with setting the x and y values because the same code without symbols returns, as expected, a single value:
A = ones(10,3);
p = sum((2-A(:,1)).^2+(3-A(:,2)).^2+A(:,3))
Any ideas why the first code doesn't return a single value?

采纳的回答

Walter Roberson
Walter Roberson 2018-3-9
编辑:Walter Roberson 2018-3-9
Your O(A(:,3)) is essentially requesting that double(subs(p)) be executed once for each value of A(:,3) with zd being set to each value in turn, so you are going to get one answer for each A(:,3) value. [This is not how it is actually implemented, but the result is the same.]
When you create a symbolic expression involving a variable, then there is no way to tell the Symbolic toolbox that the variable is standing in for something that will later be replaced by an array and that you want array operations used in conjunction with the arrays that are already in the expression. As far as the symbolic toolbox is concerned, every symbolic variable name (that is not a function) represents a scalar, and it will use scalar logic for it.
Consider for example,
syms x y
x * y
y * x
ans =
x*y
ans =
x*y
Notice you get the same response for the two different orders. This is acceptable under the assumption that x and y are scalars, because scalars are commutative under matrix multiplication. It would, however, be unacceptable if x and y were standing in for arrays, because matrix multiplication of arrays is not commutative.
When you subs() in a matrix for a symbol in an expression, the entire expression is evaluated once for each value of the matrix, even if what you are subs() in is the same size as the original expression
> syms x
A = [1 + x, 2 + x; 3 + x, 4 + x]
X = [9 10; 11 12]
A =
[ x + 1, x + 2]
[ x + 3, x + 4]
X =
9 10
11 12
>> subs(A,x,X)
ans =
[ 10, 11, 11, 12]
[ 12, 13, 13, 14]
[ 12, 13, 13, 14]
[ 14, 15, 15, 16]
>> subs(A,x,[100 200])
ans =
[ 101, 201, 102, 202]
[ 103, 203, 104, 204]
When you subs() in multiple variables in the same subs() call, then corresponding elements of the input matrices are used.
>> syms x y
>> A = [x+y, x+2*y]
A =
[ x + y, x + 2*y]
>> subs(A,{x,y}, {[100 200], [1000 2000]})
ans =
[ 1100, 2200, 2100, 4200]
This is not the same as doing the two subs() sequentially:
>> subs(subs(A,x,[100 200]),y,[1000 2000])
ans =
[ 1100, 2100, 1200, 2200, 2100, 4100, 2200, 4200]
  3 个评论
Walter Roberson
Walter Roberson 2018-3-10
To work with matrices at the symbolic level, you have to specialize each formula according to the expected matrix size.
A1 = rand(64,1);
A2 = rand(2,1);
zd = sym('zd', [size(A1,1), 1]);
syms x y
p64 = sum((A1(:,1)-A2(1)).^2+(zd-A2(2)).^2);
O64 = @(ZD) double(subs(p64, zd, ZD));
Notice here that the zd in the O64 definition is an array of symbols. Each symbol is substituted with the corresponding value of ZD
You can often instead usefully use
On64 = matlabFunction(p64, 'vars', {zd});
which will return a function handle that expects a column vector of length 64 and will do the calculation numerically.
Spyros Polychronopoulos
Thank you so much Walter! It worked! Or I could use this method for just zd that is a matrix
A = ones(10,3);
syms x y
p = @(zd) sum((x-A(:,1)).^2+(y-A(:,2)).^2+zd);
x = 2;
y = 3;
O = @(zd) double(subs(p(zd)));
O(A(:,3))
Would you maybe also know how could I store various versions of O with different x and y depended only from zd? When I am doing that seems like that every time x and y change value they are affecting O{1} and O{2}. That tells me that O{1} is not only depended on zd and have a set value of x and y so O{1}(2) is equal to Q{2}(2). Please see the example code below:
A = ones(10,3);
Tx=[2 4];
Ty=[1 2];
syms x y zd
p = (sum((x-A(:,1)).^2+(y-A(:,2)).^2+zd));
for a=1:2
x = Tx(a);
y = Ty(a);
O{a} = @(zd) double(subs(p));
end
O{1}(2)
O{2}(2)

请先登录,再进行评论。

更多回答(0 个)

标签

Community Treasure Hunt

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

Start Hunting!

Translated by