2010-11-12 12 views
31

Je voudrais générer toutes les combinaisons possibles des éléments d'un nombre donné de vecteurs.Générer toutes les combinaisons possibles des éléments de certains vecteurs (produit cartésien)

Par exemple, pour [1 2], [1 2] et [4 5] Je veux générer les éléments:

[1 1 4; 1 1 5; 1 2 4; 1 2 5; 2 1 4; 2 1 5; 2 2 4; 2 2 5]

Le problème est que je ne connais pas le nombre de vecteurs pour lesquels je dois calculer les combinaisons . Il peut y avoir 3 comme dans ce cas, ou il peut y avoir 10, et j'ai besoin d'une généralisation . Pouvez-vous s'il vous plaît m'aider à cela dans MATLAB? Y a-t-il déjà une fonction prédéfinie capable de faire cette tâche?

+10

ce que vous cherchez s'appelle le 'produit cartésien' des vecteurs. Vous pouvez avoir de la chance sur Google. –

Répondre

16

Essayez la fonction ALLCOMB à FileExchange.

Si vous vous stockez des vecteurs dans un réseau de cellules, vous pouvez l'exécuter comme ceci:

a = {[1 2], [1 2], [4 5]}; 
allcomb(a{:}) 
ans = 

    1  1  4 
    1  1  5 
    1  2  4 
    1  2  5 
    2  1  4 
    2  1  5 
    2  2  4 
    2  2  5 
+6

Notez que 'ALLCOMB' utilise' NDGRID' essentiellement de la même manière que dans la réponse d'Amro, avec une protection contre les erreurs. – lodhb

+0

Ouais merci juste ce que je cherchais .. :-) – tim

46

Tenir compte de cette solution en utilisant la fonction NDGRID:

sets = {[1 2], [1 2], [4 5]}; 
[x y z] = ndgrid(sets{:}); 
cartProd = [x(:) y(:) z(:)]; 

cartProd = 
    1  1  4 
    2  1  4 
    1  2  4 
    2  2  4 
    1  1  5 
    2  1  5 
    1  2  5 
    2  2  5 

Ou si vous voulez une solution générale pour n'importe quel nombre d'ensembles (sans avoir à créer les variables manuellement), utilisez cette définition de fonction:

function result = cartesianProduct(sets) 
    c = cell(1, numel(sets)); 
    [c{:}] = ndgrid(sets{:}); 
    result = cell2mat(cellfun(@(v)v(:), c, 'UniformOutput',false)); 
end 

Notez que si vous préférez, vous pouvez trier les résultats:

cartProd = sortrows(cartProd, 1:numel(sets)); 

En outre, le code ci-dessus ne vérifie pas si les jeux ont aucune valeur en double (ex: {[1 1] [1 2] [4 5]}). Ajouter cette une ligne si vous voulez:

sets = cellfun(@unique, sets, 'UniformOutput',false); 
11

Cette réponses tardives fournit deux solutions supplémentaires, le second est la solution (à mon avis) et une amélioration de la solution de réponse Amro avec ndgrid en appliquant Matlab est puissant listes séparées par des virgules au lieu de réseaux de cellules de haute performance,

  1. Si vous avez le Neural Network Toolbox: utiliser combvec
  2. Si vous ne pas avoir la boîte à outils, comme c'est habituellement le cas: ci-dessous est une autre façon de généraliser le produit cartésien pour n'importe quel nombre d'ensembles.

Comme Amro a fait dans sa réponse, la syntaxe des listes séparées par des virgules (v{:}) fournit les entrées et sorties de ndgrid. La différence (quatrième ligne) est qu'elle évite cellfun et cell2mat en appliquant des listes séparées par des virgules, encore une fois, maintenant que les entrées à cat:

N = numel(a); 
v = cell(N,1); 
[v{:}] = ndgrid(a{:}); 
res = reshape(cat(N+1,v{:}),[],N); 

L'utilisation de cat et reshape réduit le temps d'exécution de près de moitié. Cette approche a été démontrée dans my answer to an different question et more formally by Luis Mendo.

0

nous pouvons aussi utiliser l'instruction 'combvec' dans Matlab

no_inp=3 % number of inputs we want...in this case we have 3 inputs     
    a=[1 2 3] 
    b=[1 2 3] 
    c=[1 2 3] 

    pre_final=combvec(c,b,a)'; 
    final=zeros(size(pre_final)); 

    for i=1:no_inp 
    final(:,i)=pre_final(:,no_inp-i+1); 
    end 
    final 

Hope it helps. Bonne chance.

Questions connexes