2012-02-29 2 views
4

давайте предположим, я имею следующую логическую матрицу:MATLAB: получить все перестановки для конкретной логической матрицы

log = [1 1 0; 
     0 1 1; 
     1 0 1; 
     0 0 1]; 

колонн описывает нечто вроде корзины и отдельные строки описывают некоторые объекты, идентифицированных по какому-либо признаку (например, шары разных цветов) вы можете положить в эти корзины. 1 означает, что вы можете положить его (в корзину, описанную в колонке), 0 вы не можете.

Каждая корзина может содержать только один объект. мне интересно, как вычислить перестановки о том, как поместить в объектах для данной конфигурации, это означает, что я говорю: I want to have objects in basket 1 and 3 but none in basket 2, which would be [1 0 1]:

Поэтому у меня есть следующие возможности:

  • корзина 2: 0 штук
  • корзина 1: может содержать либо объект 1, либо объект. 3
  • корзина 3: может содержать либо объект 2, obj. 3 или obj. 4

так что в целом, у меня есть полные перестановки (одна строка описывает одну перестановку, колонка описания корзины и число описывает объект):

1 0 2 
1 0 3 
1 0 4 
2 0 2 
2 0 3 
2 0 4 

, как сделать это в хороший алгоритм, который адаптируется к произвольному количеству корзин и объектов? я могу только думать о вложенном и уродливой зацикливание :( Большое спасибо!

+1

В первой колонке окончательного ответа, это скорее [1 1 1 3 3 3] ', а не [1 1 1 2 2 2]'? – Oli

ответ

4

Я хотел бы сделать это рекурсивно:

function out = permlog(log,bag) 
if bag(1)==0 
    curr=0; 
else 
    curr = find(log(:,1)); 
end 
if size(log,2)==1 
    out = curr; 
    return 
else 
    add = permlog(log(:,2:end),bag(2:end)); 
    out = []; 
    for i=1:numel(curr) 
     tmp = [repmat(curr(i),size(add,1),1),add]; 
     out =[out;tmp]; 
    end 
end 

дает выход вы описываете:

permlog(log,[1,0,1]) 

ans = 

    1  0  2 
    1  0  3 
    1  0  4 
    3  0  2 
    3  0  3 
    3  0  4 
+0

ОК, спасибо вам обоим, оба отличных решения. Я бы сказал, что предпочитаю использовать ndgrid, потому что его встроенный, но почему-то ваше решение быстрее, особенно для довольно маленьких матриц. Так что я отмечаю, как принято, так как я использую более быстрый ... спасибо, ребята – tim

5

Вы можете использовать ndgrid. Эта функция делает именно то, что вы ищете.

[b1 b2 b3]=ndgrid([1 2],[0],[2 3 4]); 
[b1(:) b2(:) b3(:)] 

ans = 

1  0  2 
2  0  2 
1  0  3 
2  0  3 
1  0  4 
2  0  4 

Чтобы ответить вам полный вопрос, вам нужно чтобы получить [1 2],[0],[2 3 4] из вашего журнала переменной:

log = [1 1 0; 
    0 1 1; 
    1 0 1; 
    0 0 1]; 
log=bsxfun(@times,log,[1 0 1]); 
poss=cellfun(@find,mat2cell(log,size(log,1),ones(1,size(log,2))),'UniformOutput',0) 
poss(cellfun(@isempty,poss))={0} 
basket=cell(1,size(log,2)); 
[basket{:}]=ndgrid(poss{:}); 
basket=cell2mat(cellfun(@(x) x(:),basket,'UniformOutput',0)) 

корзины =

1  0  2 
3  0  2 
1  0  3 
3  0  3 
1  0  4 
3  0  4 
+0

выглядит интересно, но как именно я должен конкретизировать результаты для произвольных входных данных? – tim

+0

спасибо за редактирование Оли, как адаптироваться, когда есть больше корзин? Я не могу динамически изменять количество выходных варов в своих запрограммированных операциях, может ли я ?! – tim

+0

еще раз спасибо, но все же остается вопрос о моем втором комментарии. добавьте корзину, и код не может автоматически адаптироваться, потому что b1 ... b3 жестко запрограммирован. – tim

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