2010-11-12 18 views
31

Me gustaría generar todas las combinaciones posibles de los elementos de un número dado de vectores.Generar todas las combinaciones posibles de los elementos de algunos vectores (producto cartesiano)

Por ejemplo, para [1 2], [1 2] y [4 5] Quiero generar los elementos:

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

El problema es que no sé el número de vectores para el cual necesito para calcular las combinaciones . Puede haber 3 como en este caso, o puede haber 10, y necesito una generalización . ¿Puedes ayudarme con esto en MATLAB? ¿Ya hay una función predefinida que puede hacer esta tarea?

+10

lo que está buscando se llama el 'producto cartesiano' de los vectores. Es posible que tengas suerte buscando en Google para eso. –

Respuesta

16

Pruebe ALLCOMB function en FileExchange.

Si se almacenan los vectores en una serie de células, se puede ejecutar la siguiente manera:

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

Tenga en cuenta que 'ALLCOMB' utiliza' NDGRID' esencialmente de la misma manera que en la respuesta de Amro, con la prueba de errores en la parte superior. – lodhb

+0

Sí, gracias precisamente lo que estaba buscando .. :-) – tim

46

considerar esta solución utilizando la función 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 

O si desea una solución general para cualquier cantidad de conjuntos (sin tener que crear las variables manualmente), use esta definición de función:

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

Tenga en cuenta que, si lo prefiere, puede ordenar los resultados:

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

Además, el código anterior no comprobar si los conjuntos no tienen valores duplicados (por ejemplo: {[1 1] [1 2] [4 5]}). Añadir esta línea si desea:

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

tan tarde respuestas proporciona dos soluciones adicionales, en el que el segundo es la solución (en mi opinión) y una mejora en la solución de la respuesta de Amro con ndgrid mediante la aplicación de MATLAB de gran alcance listas separadas por comas en lugar de células matrices de alto rendimiento,

  1. Si usted tiene la caja de herramientas de redes neuronales: utilizar combvec
  2. Si lo hace, no tener la caja de herramientas, como suele ser el caso: a continuación, hay otra forma de generalizar el producto cartesiano para cualquier cantidad de conjuntos.

Así como Amro hizo en su respuesta, la sintaxis de las listas separadas por comas (v{:}) suministra tanto las entradas y salidas de ndgrid. La diferencia (cuarta línea) es que evita cellfun y cell2mat mediante la aplicación de listas separadas por comas, de nuevo, ahora como las entradas a cat:

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

El uso de cat y reshape reduce el tiempo de ejecución casi a la mitad. Este enfoque se demostró en my answer to an different question y more formally by Luis Mendo.

0

también podemos utilizar la instrucción 'combvec' en 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 

espero que ayude. Buena suerte.

Cuestiones relacionadas