Reputation: 149
In my main script, I am trying to eliminate cell arrays of S
that have the same elements. For example, if you run the current script (with a=v=2
) then you will obtain the following values for S
:
S{1}(:, :, 1) = [0 0; 0 0]; S{1}(:, :, 2) = [0 0; 0 0];
S{2}(:, :, 1) = [0 0; 1 1]; S{2}(:, :, 2) = [0 1; 0 1];
S{3}(:, :, 1) = [0 1; 0 1]; S{3}(:, :, 2) = [0 0; 1 1];
S{4}(:, :, 1) = [1 0; 1 0]; S{4}(:, :, 2) = [1 1; 0 0];
S{5}(:, :, 1) = [1 1; 0 0]; S{5}(:, :, 2) = [1 0; 1 0];
S{6}(:, :, 1) = [1 1; 1 1]; S{6}(:, :, 2) = [1 1; 1 1];
The code should see S{2}
and S{3}
, S{4}
and S{5}
as having the same subsets. Therefore, the results I wish to get should be S{1}
, S{2}
, S{4}
, and S{6}
.
I know MATLAB has the ismember
, isequal
, etc. functions but they do not seem to work on cell arrays...or I could not get them working.
Is there a concise way to handle this with cell arrays as it is currently written?
Main Script:
clear all
clc
a = 2;
v = 2;
R = dec2base(0:1:v^(v^a)-1, v)-'0';
cnt1 = 0;
cnt2 = 0;
for j=1:v^(v^a)
% List all degenerates in Psi1
V = FN_Break(a, v, R(j,:));
if V > 0 % Connector is degenerate
cnt1 = cnt1 + 1;
Psi1(cnt1,1) = j-1;
% Store all "breaks" into cell array S
S{cnt1} = FN_Break_T(a,v,R(j,:));
else % Connector is not degenerate
cnt2 = cnt2 + 1;
Psi2(cnt2,1) = j-1;
end
end
Function FN_Break
:
function [valU] = FN_Beak(a, v, R)
FreeAtomCtr = 0;
for j=0:v^a-1
for k=1:a
for l=1:a
B = dec2base(j,v,a);
atom(l,j+1) = str2num(B(l));
end
end
end
for j=1:a % Do this for each atom
cnt(1:v) = 0;
for k = 1:v^a % Do this for each position of each atom
for l=0:v-1 % Break this down for each value
if atom(j,k) == l
cnt(1+l) = cnt(1+l) + 1;
T(1+l, cnt(1+l),j) = R(k);
end
end
end
end
for j=1:a
B = unique(T(:,:,j), 'rows');
if dot(size(B), [1 0]) < v % does not depend on this atom
FreeAtomCtr = FreeAtomCtr + 1;
end
end
valU = FreeAtomCtr;
end
function FN_Break_T
:
function [valU] = FN_Beak_T(a, v, R)
FreeAtomCtr = 0;
for j=0:v^a-1
for k=1:a
for l=1:a
B = dec2base(j,v,a);
atom(l,j+1) = str2num(B(l));
end
end
end
for j=1:a % Do this for each atom
cnt(1:v) = 0;
for k = 1:v^a % Do this for each position of each atom
for l=0:v-1 % Break this down for each value
if atom(j,k) == l
cnt(1+l) = cnt(1+l) + 1;
T(1+l, cnt(1+l),j) = R(k);
end
end
end
end
for j=1:a
B = unique(T(:,:,j), 'rows');
if dot(size(B), [1 0]) < v % does not depend on this atom
FreeAtomCtr = FreeAtomCtr + 1;
end
end
valU = T;
end
Upvotes: 0
Views: 44
Reputation: 12214
One approach could be to hash your combinations and use those to compare the cell contents. You can use ismember
to index pairs based on possible combinations (4, in this case), then sort
the results and use unique
to find the first instance of each unique (sorted) hash.
For example:
S{1}(:, :, 1) = [0 0; 0 0]; S{1}(:, :, 2) = [0 0; 0 0];
S{2}(:, :, 1) = [0 0; 1 1]; S{2}(:, :, 2) = [0 1; 0 1];
S{3}(:, :, 1) = [0 1; 0 1]; S{3}(:, :, 2) = [0 0; 1 1];
S{4}(:, :, 1) = [1 0; 1 0]; S{4}(:, :, 2) = [1 1; 0 0];
S{5}(:, :, 1) = [1 1; 0 0]; S{5}(:, :, 2) = [1 0; 1 0];
S{6}(:, :, 1) = [1 1; 1 1]; S{6}(:, :, 2) = [1 1; 1 1];
combinations = [0 0; 0 1; 1 0; 1 1];
% Assume array in every cell has the same shape
hash = zeros(size(S{1}, 1)*size(S{1}, 3), numel(S));
for ii = 1:numel(S)
[~, hash(:,ii)] = ismember([S{ii}(:, :)].', combinations, 'rows');
end
hash = sort(hash, 1).';
[~, keepidx] = unique(hash, 'rows');
S = S(keepidx);
Which gives the desired S
(cells 1, 2, 4, 6)
If you instead want to nest the duplicates, you can use the following:
hash = sort(hash, 1).';
[~, keepidx, uniqueidx] = unique(hash, 'rows');
bincounts = accumarray(uniqueidx, 1); % Count occurrences
for ii = 1:numel(bincounts)
if bincounts(ii) > 1
idx = find(uniqueidx == ii);
S{idx(1)} = S(idx); % Nest duplicates in first instance of duplicate
end
end
S = S(keepidx);
This uses the third output of unique
along with accumarray
to obtain the occurrence count of each unique combination. The duplicates are nested and then the original cell array is pruned as before.
Upvotes: 1