Create symbolic matrix from triplets with repeated indices
1 view (last 30 days)
Show older comments
Fabio Freschi
on 23 Jun 2017
Edited: Andrei Bobrov
on 26 Jun 2017
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 Comment
Karan Gill
on 26 Jun 2017
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.
Accepted Answer
Andrei Bobrov
on 26 Jun 2017
Edited: Andrei Bobrov
on 26 Jun 2017
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)
0 Comments
More Answers (1)
John D'Errico
on 26 Jun 2017
Edited: John D'Errico
on 26 Jun 2017
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.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!