如何查找成对的所有组合

时间:2013-07-28 15:47:31

标签: matlab set combinations

我想生成3对男性和2名女性对的所有组合。配对有很多例子(例如this),但没有一个处理成对的集合。

例如,如果我有:

Men   = {'M1', 'M2'};
Women = {'W1', 'W2', 'W3'};

我想要的结果是以下几组:

(M1, W1), (M2, W2)
(M1, W1), (M2, W3)
(M1, W2), (M2, W1)
(M1, W2), (M2, W3)
(M1, W3), (M2, W1)
(M1, W3), (M2, W2)

谢谢。

3 个答案:

答案 0 :(得分:2)

实际上这很简单。要填充一组 k 对,您需要 k 男性和 k 女性,所以让我们找到 k 的所有可能组合 k 女性:

%// Find all possible combinations of sets of k pairs of men and women
k = 2;
idx_m = nchoosek(1:numel(Men), k);             % // Indices of men
idx_w = nchoosek(1:numel(Women), k);           % // Indices of women
idx_w = reshape(idx_w(:, perms(1:k)), [], k);  % // All permutations

然后让我们构建 k 男性和 k 女性的所有可能组合:

[idx_comb_w, idx_comb_m] = find(ones(size(idx_w , 1), size(idx_m , 1)));
idx = sortrows([idx_m(idx_comb_m(:), :), idx_w(idx_comb_w(:), :)]);
idx = idx(:, reshape(1:size(idx, 2), k, [])'); %'// Rearrange in pairs

结果矩阵idx包含集合中男性和女性的指数(第一列是男性,第二列 - 女性,第三列 - 男性,第四列 - 女性,等等......)

实施例

Men = {'M1', 'M2'};
Women = {'W1', 'W2', 'W3'};

%// Find all possible combinations of sets of k pairs of men and women
k = 2;
idx_m = nchoosek(1:numel(Men), k);
idx_w = nchoosek(1:numel(Women), k);
idx_w = reshape(idx_w(:, perms(1:k)), [], k);
[idx_comb_w, idx_comb_m] = find(ones(size(idx_w , 1), size(idx_m , 1)));

%// Construct pairs from indices and print sets nicely
idx = sortrows([idx_m(idx_comb_m(:), :), idx_w(idx_comb_w(:), :)]);
idx = idx(:, reshape(1:size(idx, 2), k, [])');

%// Obtain actual sets
sets = cell(size(idx));
sets(:, 1:2:end) = Men(idx(:, 1:2:end));
sets(:, 2:2:end) = Women(idx(:, 2:2:end));

%// Print sets nicely
sets_t = sets';
fprintf([repmat('(%s, %s), ', 1, k - 1), '(%s, %s)\n'], sets_t{:})

此处生成的数组sets已经过调整,以包含MenWomen的实际值。结果是:

(M1, W1), (M2, W2)
(M1, W1), (M2, W3)
(M1, W2), (M2, W1)
(M1, W2), (M2, W3)
(M1, W3), (M2, W1)
(M1, W3), (M2, W2)

答案 1 :(得分:0)

此示例使用FEX file allcomb

men = {'M1', 'M2', 'M3'};
women = {'W1', 'W2'};
allPeople = [men, women];
%// Play with vector index because allcomb doesn't work with cell
[~, id_men] = ismember(men,allPeople);
[~, id_women] = ismember(women,allPeople);


%// give all combinations for men/women
setOfMenWomen = allcomb(id_men,id_women);
%// give all combinations of pairs
nComb = size(setOfMenWomen,1);
setOfPair = nchoosek(1:nComb,2);
%// give all combinations for men/women/men/women
setOfPairMenWomen = cell2mat(arrayfun(@(id) setOfMenWomen(id,:), setOfPair, 'UniformOutput', 0));
%// get ids of set of pairs with the same men twice
isDoubleMen = setOfPairMenWomen(:,1) == setOfPairMenWomen(:,3);
%// get ids of set of pairs with the same women twice
isDoubleWomen = setOfPairMenWomen(:,2) == setOfPairMenWomen(:,4);
%// We don't want to have set of pairs with twice same men or same women
cond = isDoubleWomen | isDoubleMen;
setOfPairMenWomen(cond,:) = [];

%//results :
allPeople(setOfPairMenWomen)

答案 2 :(得分:0)

我无法确切地看到你的问题是什么。您是否在MATLAB中搜索算法或实现?我将尝试用数学方法回答。

您可以通过将其设置为graph问题来解决您的问题:您的一组人是顶点集。通过将所有男性与所有女性联系起来形成边缘现在找到(最大)matchings的集合。

这取决于你想要什么:你想要例如元素((M1,W1))成为解决方案的一部分吗?然后,您正在搜索匹配项(请参阅Hosoya index了解解决方案集中的元素数量)。如果您只想要不添加其他配对的元素,那么您只考虑最大匹配。

如果您将问题扩展到通用的非性别对,这可能会有所帮助:http://en.wikipedia.org/wiki/Telephone_number_(mathematics)