MATLAB: remove subarrays from a multidimensional array to an array of them

I would like to build a function

[B, ind] = extract_ones(A)

which removes some of the sub-arrays of binary array A in arbitrary sizes, so that the remainder of the array B is the largest possible array with only one, and I would also like to record in ind , where each of the 1 in B .


Example 1

Suppose A is a 2-dimensional array as shown

A = 
1 1 0 0 0 1
1 1 1 0 1 1
0 0 0 1 0 1
1 1 0 1 0 1
1 1 0 1 0 1
1 1 1 1 1 1

After removing A (3, :) and A (:, 3: 5) , we have exit B

B = 
1 1 1
1 1 1
1 1 1
1 1 1
1 1 1

which is the largest array with only by deleting lines and columns of A . Since fifteen 1 of B correspond

A(1,1) A(1,2) A(1,6)
A(2,1) A(2,2) A(2,6)
A(4,1) A(4,2) A(4,6)
A(5,1) A(5,2) A(5,6)
A(6,1) A(6,2) A(6,6)

A(1) A(7)  A(31)
A(2) A(8)  A(32)
A(4) A(10) A(34)
A(5) A(11) A(35)
A(6) A(12) A(36)

ind ( ind ):

ind = [1 2 4 5 6 7 8 10 11 12 31 32 34 35 36]

2

A

A = ones(6,3,4,3);
A(2,2,2,2) = 0;
A(4,1,3,3) = 0;
A(1,1,4,2) = 0;
A(1,1,4,1) = 0;

, , A (2,2,2,2), A (4,1,3,3), A (1,1,4,3) A (1,1, 4,1), ..

A(2,:,:,:)
A(:,1,:,:)

B 1. , B

A([1,3:6],2:3,1:4,1:3)

, ind , , ..

ind = [7    9   10  11  12  13  15  16  17  18  25  27  28  29  30  31  33  34  35  36  43  45  46  47  48  49  51  52  53  54  61  63  64  65  66  67  69  70  71  72  79  81  82  83  84  85  87  88  89  90  97  99  100 101 102 103 105 106 107 108 115 117 118 119 120 121 123 124 125 126 133 135 136 137 138 139 141 142 143 144 151 153 154 155 156 157 159 160 161 162 169 171 172 173 174 175 177 178 179 180 187 189 190 191 192 193 195 196 197 198 205 207 208 209 210 211 213 214 215 216]

, , , 8-D, , - , , ?


[ 2 (GMT-4), 2 2017 ]

, . :

Inds = reshape(1:numel(A),size(A)); % Keep track on which 1 survive.
cont = true;

while cont
    sz = size(A);
    zero_percentage = 0;
    Test_location = [];

    % This nested for loops are for determining which sub-array of A has the
    % maximum proportion of zeros.
    for J = 1 : ndims(A)
        for K = 1 : sz(J)
            % Location is in the form of (_,_,_,...,_)
            % where the J-th blank is K, the other blanks are colons.
            Location = strcat('(',repmat(':,',1,(J-1)),int2str(K),repmat(',:',1,(ndims(A)-J)),')');
            Test_array = eval(strcat('A',Location,';'));
            N = numel(Test_array);
            while numel(Test_array) ~= 1
                Test_array = sum(Test_array);
            end
            test_zero_percentage = 1 - (Test_array/N);
            if test_zero_percentage > zero_percentage
                zero_percentage = test_zero_percentage;
                Test_location = Location;
            end
        end
    end

    % Delete the array with maximum proportion of zeros
    eval(strcat('A',Test_location,'= [];'))
    eval(strcat('Inds',Test_location,'= [];'))

    % Determine if there are still zeros in A. If there are, continue the while loop.
    cont = A;
    while numel(cont) ~= 1
        cont = prod(cont);
    end
    cont = ~logical(cont);
end

:

1) , .

2) . , A

A = 
 0     0     0     1     1     0
 0     1     1     0     1     1
 1     0     1     1     1     1
 1     0     0     1     1     1
 0     1     1     0     1     1
 0     1     0     0     1     1
 1     0     0     0     1     1
 1     0     0     0     0     0

B = 
 1     1
 1     1
 1     1
 1     1
 1     1
 1     1

Inds =
 34    42
 35    43
 36    44
 37    45
 38    46
 39    47

:

B =
 1     1     1
 1     1     1
 1     1     1

Inds =
 10    34    42
 13    37    45
 14    38    46

* 2 [ 12noon (GMT-4), 2 Aug 2017]

. . , Inds. , .

function [B, Inds] = Finding_ones(A)

Inds = reshape(1:numel(A),size(A)); % Keep track on which 1 survive.
sz0 = size(A);
cont = true;

while cont
    sz = size(A);
    zero_percentage = 0;
    Test_location = [];

    % This nested for loops are for determining which sub-array of A has the
    % maximum proportion of zeros.
    for J = 1 : ndims(A)
        for K = 1 : sz(J)
            % Location is in the form of (_,_,_,...,_)
            % where the J-th blank is K, the other blanks are colons.
            Location = strcat('(',repmat(':,',1,(J-1)),int2str(K),repmat(',:',1,(ndims(A)-J)),')');
            Test_array = eval(strcat('A',Location,';'));
            N = numel(Test_array);
            Test_array = sum(Test_array(:));

            test_zero_percentage = 1 - (Test_array/N);
            if test_zero_percentage > zero_percentage
                eval(strcat('Testfornumel = numel(A',Location,');'))
                if Testfornumel < numel(A) % Preventing the A from being empty
                    zero_percentage = test_zero_percentage;
                    Test_location = Location;
                end
            end
        end
    end

    % Delete the array with maximum proportion of zeros
    eval(strcat('A',Test_location,'= [];'))
    eval(strcat('Inds',Test_location,'= [];'))

    % Determine if there are still zeros in A. If there are, continue the while loop.
    cont = A;
    while numel(cont) ~= 1
        cont = prod(cont);
    end
    cont = ~logical(cont);
end

B = A;

% command = 'i1, i2, ... ,in'
% here, n is the number of dimansion of A.
command = 'i1';
for J = 2 : length(sz0)
    command = strcat(command,',i',int2str(J));
end

Inds = reshape(Inds,numel(Inds),1); %#ok<NASGU> 
eval(strcat('[',command,'] = ind2sub(sz0,Inds);'))

% Reform Inds into a 2-D matrix, which each column indicate the location of
% the 1 originated from A.
Inds = squeeze(eval(strcat('[',command,']')));
Inds = reshape(Inds',length(sz0),numel(Inds)/length(sz0));

end
+4
2

. . .

function [ res ] = seed_grow( A )
if ~islogical(A),A=(A==1);end
if ~any(A(:)),res={};end
go = true;
dims=size(A);
ind = cell([1 length(dims)]);  %cell to store find results
seeds=A;maxmat=0;
while go %main loop to remove all posible seeds
    [ind{:}]=find(seeds,1,'first');
    S = [ind{:}]; %the seed
    St = [ind{:}]; %the end of the seed
    go2=true;
    val_dims=1:length(dims);
    while go2 %loop to grow each dimension
        D=1;
        while D<=length(val_dims) %add one to each dimension
            St(val_dims(D))=St(val_dims(D))+1;
            I={};
            for ct = 1:length(S),I{ct}=S(ct):St(ct);end %generate indices
            if St(val_dims(D))>dims(val_dims(D))
                res=false;%outside matrix
            else
                res=A(I{:});
            end 
            if ~all(res(:)) %invalid addition to dimension
                St(val_dims(D))=St(val_dims(D))-1; %undo
                val_dims(D)=[]; D=D-1; %do not try again
                if isempty(val_dims),go2=false;end %end of growth
            end
            D=D+1;
        end
    end
    %evaluate the result
    mat = prod((St+1)-S); %size of matrix
    if mat>maxmat
        res={S,St};
        maxmat=mat;
    end
    %tried to expand, now remove seed option
    for ct = 1:length(S),I{ct}=S(ct):St(ct);end %generate indices
    seeds(I{:})=0;    
    if ~any(seeds),go=0;end
end
end

:

A =  [0     0     0     1     1     0
 0     1     1     0     1     1
 1     0     1     1     1     1
 1     0     0     1     1     1
 0     1     1     0     1     1
 0     1     0     0     1     1
 1     0     0     0     1     1
 1     0     0     0     0     0];
[ res ] = seed_grow( A );
for ct = 1:length(res),I{ct}=res{1}(ct):res{2}(ct);end %generate indices
B=A(I{:});
idx = reshape(1:numel(A),size(A)); 
idx = idx(I{:});

:

B =

     1     1
     1     1
     1     1
     1     1
     1     1
     1     1


idx =

    34    42
    35    43
    36    44
    37    45
    38    46
    39    47
+1

, . , 0, .

, . , , .

function [B,ind] = extract_ones( A )
if ~islogical(A),A=(A==1);end
if ~any(A(:)),B=[];ind=[];return,end
B=A;cdel=[];rdel=[];
while ~all(B(:))
    [I,J] = ind2sub(size(B),find(B==0));
    ih=histcounts(I,[0.5:1:size(B,1)+0.5]); %zero in rows
    jh=histcounts(J,[0.5:1:size(B,2)+0.5]); %zero in columns
    if max(ih)>max(jh)
        idxr=find(ih==max(ih),1,'first');
        B(idxr,:)=[];
        %store deletion
        rdel(end+1)=idxr+sum(rdel<=idxr);
    elseif max(ih)==max(jh)
        idxr=find(ih==max(ih),1,'first');
        idxc=find(jh==max(jh),1,'first');
        B(idxr,:)=[];
        B(:,idxc)=[];
        %store deletions
        rdel(end+1)=idxr+sum(rdel<=idxr);
        cdel(end+1)=idxc+sum(cdel<=idxc);
    else
        idxc=find(jh==max(jh),1,'first');
        B(:,idxc)=[];
        %store deletions
        cdel(end+1)=idxc+sum(cdel<=idxc);
    end
end
A(rdel,:)=0;
A(:,cdel)=0;
ind=find(A);
+2

Source: https://habr.com/ru/post/1682668/


All Articles