过去几天我一直在考虑一个问题,但由于我是MATLAB的初学者,我不知道如何解决它。这是背景。假设您有一个对称N×N
矩阵,其中每个元素都是0
或1
,N = (1,2,...,n)
。
例如:
A =
0 1 1 0
1 0 0 1
1 0 0 0
0 1 0 0
如果A(i,j) == 1
,则可以形成货币对(i,j)
,如果A(i,j)==0
,则无法形成货币对(i,j)
。例如,(1,2)
是一对可能的对,A(1,2)==A(2,1)==1
但(3,4)
不是A(3,4)==A(4,3)==0
的可能对。
这是问题所在。假设集合N
中的成员只能与集合中最多一个其他不同成员N
成对(即,如果1与2形成一对,那么1不能形成一对3)。如何找到可能对的所有可能“列表”?在上面的示例中,一个“列表”仅包含(1,2)
对。如果形成该对,则不可能形成任何其他对。另一个“列表”是:((1,3),(2,4))
。我搜索了论坛,发现后者“列表”是可以找到的最大匹配,例如,通过使用二分图方法。但是,我不一定只对找到最大匹配感兴趣;我有兴趣找到所有可能的“列表”。
另一个例子:
A =
0 1 1 1
1 0 0 1
1 0 0 0
1 1 0 0
在此示例中,有三个可能的列表:
(1,2)
((1,3),(2,4))
(1,4)
我希望你能理解我的问题,如果不清楚我会道歉。我感谢所有帮助。非常感谢!
答案 0 :(得分:1)
这可能是一种快速的方法。
<强>代码强>
%// Given data, A
A =[ 0 1 1 1;
1 0 0 1;
1 0 0 0;
1 1 0 0];
%%// The lists will be stored in 'out' as a cell array and can be accessed as out{1}, out{2}, etc.
out = cell(size(A,1)-1,1);
%%// Code that detects the lists using "selective" diagonals
for k = 1:size(A,1)-1
[x,y] = find(triu(A,k).*(~triu(ones(size(A)),k+1)));
out(k) = {[x y]};
end
out(cellfun('isempty',out))=[]; %%// Remove empty lists
%%// Verification - Print out the lists
for k = 1:numel(out)
disp(out{k})
end
<强>输出强>
1 2
1 3
2 4
1 4
编辑1
基本上我会计算矩阵的所有成对指数,以满足问题中设定的标准,然后简单地将它们映射到给定的矩阵上。找到“有效”指数的部分显然是其中的繁琐部分,并且在处理大于10的输入矩阵时,采用一些积极方法的代码也很昂贵。
<强>代码强>
%// Given data, A
A = [0 1 1 1; 1 0 1 1; 1 1 0 1; 1 1 1 0]
%%// Get all pairwise combinations starting with 1
all_combs = sortrows(perms(1:size(A,1)));
all_combs = all_combs(all_combs(:,1)==1,:);
%%// Get the "valid" indices
all_combs_diff = diff(all_combs,1,2);
valid_ind_mat = all_combs(all(all_combs_diff(:,1:2:end)>0,2),:);
valid_ind_mat = valid_ind_mat(all(diff(valid_ind_mat(:,1:2:end),1,2)>0,2),:);
%%// Map the ones of A onto the valid indices to get the lists in a matrix and then cell array
out_cell = mat2cell(valid_ind_mat,repmat(1,[1 size(valid_ind_mat,1)]),repmat(2,[1 size(valid_ind_mat,2)/2]));
A_masked = A(sub2ind(size(A),valid_ind_mat(:,1:2:end),valid_ind_mat(:,2:2:end)));
out_cell(~A_masked)={[]};
%%// Remove empty lists
out_cell(all(cellfun('isempty',out_cell),2),:)=[];
%%// Verification - Print out the lists
disp('Lists =');
for k1 = 1:size(out_cell,1)
disp(strcat(' List',num2str(k1),':'));
for k2 = 1:size(out_cell,2)
if ~isempty(out_cell{k1,k2})
disp(out_cell{k1,k2})
end
end
end
<强>输出强>
A =
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Lists =
List1:
1 2
3 4
List2:
1 3
2 4
List3:
1 4
2 3
答案 1 :(得分:0)
我确信有更快的方法,但这是明显的解决方案:
%// Set top half to 0, and find indices of all remaining 1's
A(triu(A)==1) = 0;
[ii,jj] = find(A);
%// Put these in a matrix for further processing
P = [ii jj];
%// Sort indices into 'lists' of the kind you defined
X = repmat({}, size(P,1),1);
for ii = 1:size(P,1)-1
X{ii}{1} = P(ii,:);
for jj = ii+1:size(P,1)
if ~any(ismember(P(ii,:), P(jj,:)))
X{ii}{end+1} = P(jj,:); end
end
end