Create symbolic matrix from triplets with repeated indices

조회 수: 2 (최근 30일)
Fabio Freschi
Fabio Freschi 2017년 6월 23일
편집: Andrei Bobrov 2017년 6월 26일
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