Create symbolic matrix from triplets with repeated indices

2 visualizzazioni (ultimi 30 giorni)
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 Commento
Karan Gill
Karan Gill il 26 Giu 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.

Accedi per commentare.

Risposta accettata

Andrei Bobrov
Andrei Bobrov il 26 Giu 2017
Modificato: Andrei Bobrov il 26 Giu 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)

Più risposte (1)

John D'Errico
John D'Errico il 26 Giu 2017
Modificato: John D'Errico il 26 Giu 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.

Community Treasure Hunt

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

Start Hunting!

Translated by