2016-06-14 3 views
2

Так что у меня этот кусок кода (в MATLAB)MATLAB: Все комбинации суммы векторов

% Define vectorfield 
g1=[5,0,0]; 
g2=[0,3,0]; 
g3=[0,0,4]; 

% Define on-off 
u=[0;1]; 

% Define set to make field symmetric 
symm=[1;-1]; 
k=1; 

%% Generate possible combinations of vector fields 
for a=1:length(u) 
for b=1:length(symm) 
    for c=1:length(u) 
    for d=1:length(symm) 
     for e=1:length(u) 
     for f=1:length(symm) 
      allvecfields(k,:)=u(a).*symm(b).*g1+u(c).*symm(d).*g2+u(e).*symm(f).*g3; 
      k=k+1; 
     end 
     end 
    end 
    end 
end 
end 

realfields=transpose(unique(allvecfields,'rows')); 

Каждый столбец realfields является уникальным положительным, отрицательным или нулевым сочетание g «с. Мне нужна помощь, обобщающая это. То есть размер каждого g может быть n, а число g может быть m. Код должен по-прежнему возвращать все уникальные возможные комбинации g. У меня такое чувство, что рекурсия должна быть использована, но все мои попытки потерпели неудачу.

Также allvecfields(k,:) просто означает k-я строка, все столбцы. Даже если ваш ответ содержит C/C++ или Java-код (без каких-либо специальных функций от них), это подходит для меня. Я переведу его в MATLAB.

Я просмотрел combvec и файл allcomb, но они не делают то, что мне нужно. Например, transpose(unique(combvec(g1,g2,g3,-g1,-g2,-g3)','rows')) возвращает матрицу 6x63, а не 3x27, которую я хочу. Добыча

vals=transpose(unique(combvec(g1,g2,g3)','rows')); 
vals=[vals transpose(unique(combvec(-g1,g2,g3)','rows'))]; 
vals=[vals transpose(unique(combvec(g1,-g2,g3)','rows'))]; 
vals=[vals transpose(unique(combvec(g1,g2,-g3)','rows'))]; 
vals=[vals transpose(unique(combvec(g1,-g2,-g3)','rows'))]; 
vals=[vals transpose(unique(combvec(-g1,g2,-g3)','rows'))]; 
vals=[vals transpose(unique(combvec(-g1,-g2,g3)','rows'))]; 
vals=[vals transpose(unique(combvec(-g1,-g2,-g3)','rows'))]; 
vals=unique(vals','rows'); 

Дает то, что я хочу, но это не помогает в обобщении.

EDIT: Исправлена ​​ошибка в последней строке первого кодового блока. Требуемая мощность для этого случая достаточно велика (27 столбцов), но если мы только что g1 и g2, то выход будет:

realfields = 

-5 -5 -5  0  0  0  5  5  5 
-3  0  3 -3  0  3 -3  0  3 
0  0  0  0  0  0  0  0  0 

EDIT: на основе предложения в комментариях, я был в состоянии переписать приведенный выше код, как,

u=[-1,0,1]; 
k=1; 
for a=1:length(u) 
    for b=1:length(u) 
    for c=1:length(u) 
     uMat(k,:)=[u(a) u(b) u(c)]; 
     k=k+1; 
    end 
    end 
end 

g1=[5,0,0]; 
g2=[0,3,0]; 
g3=[0,0,4]; 
gMat=[g1' g2' g3']; 

for a=1:size(uMat,1) 
    allvecfields(k,:)=sum(bsxfun(@times,gMat,uMat(a,:)),2); 
end 

realfields=transpose(unique(allvecfields,'rows')) 

Я думаю, что это немного более элегантно, но я до сих пор застрял, как динамически генерировать uMat учитывая количество столбцов в gMat. Я не могу поверить, что для этого не существует функции. Любая помощь будет оценена по достоинству.

+0

Желаемый результат, полученный вашим входом, поможет. – thewaywewalk

+0

Я думаю, что если вы складываете все 'g' в матрицу, а также создаете вектор с продуктами' u' и 'symm', это может привести вас в правильном направлении и сделать код эффективным. –

+0

Обратите внимание, что транспонирование - это просто '.'' – percusse

ответ

0

Вот решение

g1=[5,0,0]; 
g2=[0,3,0]; 
g3=[0,0,4]; 

gMat=[g1' g2' g3']; 

m=size(gMat',1); 
allvecfields = zeros(3^m,m); 

for k = 1:3^m 
allvecfields(k,:) = double(dec2base(k-1,3,m)-'1'); 
end 

realfields = (allvecfields*gMat')' 

Кредиты на: Roger Stafford для этого гениального решения.

Смежные вопросы