Create symbolic matrix from triplets with repeated indices

2 次查看(过去 30 天)
Hi everyone,
I am trying to build a symbolic matrix from the triplets iRow, jCol, aElm such that
A(iRow(k),jCol(k)) = A(iRow(k),jCol(k))+aElm(k)
the work can be easily done with 'sparse' or 'accumarray', but my vector aElm is symbolic and these functions do not defined for input arguments of type 'sym'. I may use linear indexing, however the iRow and jCol vectors contains repeated indices and the values must be summed up in the final matrix. A for-loop gets the job done, but I am looking for a cleaner vectorised way, if possible. Suggestions?
Example
syms a1 a2 a3 a4
iRow = [1 2 1 2];
jCol = [1 1 1 2];
aElm = [a1 a2 a3 a4];
% expected result
A =
[ a1 + a3, 0]
[ a2, a4]
Thank you in advance!
Fabio
  1 个评论
Karan Gill
Karan Gill 2017-6-26
I didn't understand the correspondence between your equation
A(...,...) = A(...,...) + aElm(...)
and your code. From your equation, "A" is predefined, and then elements of "aElm" get added to it? But in your code, "A" is not predefined. I didn't understand how "A" results from your variable definitions.

请先登录,再进行评论。

采纳的回答

Andrei Bobrov
Andrei Bobrov 2017-6-26
编辑:Andrei Bobrov 2017-6-26
iRow = [1 2 1 2];
jCol = [1 1 1 2];
aElm = sym('a',[1 4])
k = accumarray([iRow(:),jCol(:)],(1:numel(iRow))',[],@(x){x});
s = size(k);
out = zeros(s,'sym');
for jj = 1:numel(k)
out(jj) = sum(aElm(k{jj}));
end
out = reshape(out,s)

更多回答(1 个)

John D'Errico
John D'Errico 2017-6-26
编辑:John D'Errico 2017-6-26
Not a big problem. If you do this often, then just write a function for it, that will take the vectors of indices, as well as the symbolic elements.
function A = populateSymArray(rind,cind,symvals,n,m)
% populates an array of symbolic elements
% rind, cind - lists of row and column indices
% symvals - list of symbolic elements to be populate the array
% n, m - final size of the array
A = zeros(n,m,'sym');
rc = [rind(:),cind(:)];
symvals = symvals(:);
[rc,tags] = sortrows(rc);
symvals = symvals(tags);
% this loop will be a short one
while ~isempty(rc)
k = find(any(diff(rc,[],1),2));
if isempty(k)
k = size(rc,1);
end
ind = rc(k,1) + (rc(k,2)-1)*n;
A(ind) = A(ind) + symvals(k);
rc(k,:) = [];
symvals(k) = [];
end
That code has a loop in it, but the loop will be an efficient one as long as your elements are scattered around the array.

Community Treasure Hunt

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

Start Hunting!

Translated by