chappi
chappi

Reputation: 63

How to integrate conditions in a MATLAB anonymous function?

My below code is quite time consuming because of a quite big A matrix (150,000^2). Can I integrate the conditions as a function @(x) in accumarray? So that I can work on the cell-based for all the rows b without having to convert into double and apply the condition? I think it will be much faster ! Thank you very much !

tic
[a b c]=find(A.'); %extract the positions of non-zero elements of A
add_sym=accumarray(b,c,[],@(x){x}); % re-arrange the values of same row b
add_r = [];
for i = 1:size(add_sym) % go through every row to check the conditions
    r = vertcat(add_sym{i})';  % inverting cell into double vector
    if size(r,2)==1  % and apply the 3 conditions for each row
        add_r0 = 0;
    elseif size(r,2) > 1 && any(r<2)== 0 % many 2s
        add_r0 = r;
        add_r0(1)   = -2;
        add_r0(end) = 2;
        add_r0(2:end-1) = 0;
    elseif size(r,2) > 1 && any(r<2)~= 0 % 2 and 1
        k = find(diff(r)==-1); % find right 2 position
        add_r0 = r;
        add_r0(1)   = -1;
        add_r0(end) = -1;
        add_r0(k) = 2;
        add_r0(2:k-1) = 0;
        add_r0(k+1:end-1) = 0;
    end    
    add_r = [add_r; add_r0']; % saving the replaced values as vectors
end   
ADD = sparse(b,a,add_r,nm,nm,nzmax); % put it back to the same position of sparse matrix A (with replaced value)

toc

This code is written for the question asked here

Upvotes: 1

Views: 72

Answers (1)

jvz
jvz

Reputation: 1422

In principle, you are looping over the rows of the sparse A matrix. Instead of converting to cells and back, it is probably more convenient to explicitly extract the rows and do your checks. My attempt:

% dummy A, contains 0, 1 or 2's at random
N = 1e4;
A = sparse(randi(2,[N,N])); % A contains 1's and 2's
A(rand([N,N])<0.8) = 0; % randomly delete 80%

tic
add_r = zeros([nnz(A),1]);
iter = 0;
for n=1:size(A,1)
    tmp = A(n,:);
    iter_incr = nnz(tmp);
    if iter_incr==1 % no need to set add_r element to zero
        %
    elseif iter_incr>0
        if ~any(tmp(tmp>0)<2)
            add_r(iter+1) = -2;
            add_r(iter+iter_incr) = 2;
        else
            add_r(iter+1) = -1;
            add_r(iter+iter_incr) = -1;
            add_r(iter+find(tmp(tmp>0)==2)) = 2;
        end
    end

    % increment
    iter = iter + iter_incr;
end
toc

This runs in about 20 seconds on my laptop, I had to kill your solution after several minutes. Note that I was unable to test for larger matrices at the moment, this is a 10000 by 10000 matrix, and probably does not resemble the structure of your data well.

Upvotes: 2

Related Questions