2013-03-07 2 views
1

У меня есть массив B из:Сочетание возможных значений в массиве с несколькими ограничениями в Matlab?

B=[1 2 3; 10 20 30 ; 100 200 300 ; 1000 2000 3000] 

таким образом, что

B = 

      1   2   3 
      10   20   30 
     100   200   300 
     1000  2000  3000 

Я использую следующий код, чтобы найти возможные комбинации между этими переменными, которые ниже определенного значения (ограничение) - - 2000 в данном случае:

A=[123; 323; 12 ; 421] 
SA=sum(A) 
V=cell(length(B),1); 
n=1; 
for k = 1:length(B) 
    for idx = nchoosek(1:length(B), k)' 
     B_subset = B(idx); 
     if (SA + sum(B_subset) <= 2000) 
      V(n)={B_subset(:)}; %store them in a cell 
      n=n+1; 
     end 
    end 
end 

Однако я не смог совместить их так, как я хочу ниже.


Цель:

Найти возможные комбинации из B, которые будут добавлены в SA так, что их сумма меньше, чем 2000?


Ограничение 1:

  • только одно значение из каждой строки в массиве B могут быть использованы одновременно.

Например, это НЕ приемлемо: [1 2 20] [2 20 30]
Это правильно один: [1 20 100] [3 200 3000]


Ограничение 2: - Ответы должны храниться в ячейке V только в одном столбце (как указано в коде выше).

Клетка должна иметь результат, похожий на тот, что я в настоящее время, имеющий:

V = 

    [  100] 
    [  300] 
    [  200] 
    [2x1 double] 
    [2x1 double] 
    [2x1 double] 
    [3x1 double] 
+0

- это содержимое 'V' OK? Вам просто нужно форматирование вывода? –

+0

Я обновлю вопрос с тем, как должен выглядеть V – NLed

+0

«V» выглядит подозрительно знакомым :) Будет обновлен ответ. –

ответ

1

Измененный код только немного и добавил тест ниже - если V неизменна -> не было никаких комбинаций - > отобразите это. Отредактировано, чтобы сохранить его в массиве ячеек V и одновременно создать строку для печати.

Этот код рассматривает каждую комбинацию из трех элементов из B, где каждый элемент принадлежит к другому столбцу.

V=cell(length(B),1); 
A=[123; 323; 12 ; 421]; 
SA=sum(A); 
S = 'possible combinations :'; 
n = 1 
for ii=1:4 
    for jj=1:4 
     if jj == ii 
      continue 
     end 
     for kk=1:4 
      if or(kk == jj,kk == ii) 
       continue 
      end 
      B_subset = [B(ii,1), B(jj,2), B(kk,3)]; 
      if (SA + sum(B_subset) <= 2000) 
       S = [S, ' ', mat2str(B_subset)]; 
       V{n} = B_subset; 
       n += 1; 
      end 
     end 
    end 
end 

if V == 'possible combinations :' 
    disp('No possible combinations found') 
else 
    disp(S) 
end 

EDIT: добавление ответа на новую часть вопроса. Во внутреннем цикле вычисляются различные комбинации включенных строк.

V = {} 
for ii=1:3 
    for jj=1:3 
     for kk=1:3 
      for ll = 1:3 
       rows = [ii, jj, kk, ll] 
       if isequal(rows, unique(rows)) 
        % loop for turning off individual elements 
        result = [B(1,ii), B(2,jj), B(3,kk), B(4,ll)] 
        for mm = 0:1:15 
         % make a binary string - will loop through all combinations of zeros and ones 
         str1 = dec2bin(mm,4) 
         mask = zeros(1,4) 
         for nn = 1:4 % make a numeric vector 
          mask(nn) = str2num(str1(nn)) 
         end 
         masked_result = mask.*result 
         V = [V {masked_result}] 
        end 
       end 
      end 
     end 
    end 
end 
+0

Код по-прежнему использует значения из одной строки, такие как '100 200 30' или' 10 200 30' – NLed

+0

Вы сказали одно значение из каждого столбца: это делается с тремя циклами. Тогда вы сказали только одно значение за строку - это делается с продолжением. Он не может выполнить '100 200 30', потому что' jj' и 'ii' будут одинаковыми, и он будет продолжен, прежде чем проверять ответ. 'V' имеет в нем старые значения, потому что он не был инициализирован снова. Я обновил ответ, также меняя цикл на 4 для всего B. –

+0

@NLed: Я не понимаю, чего вы хотите. Каждый жизнеспособный ответ - матрица 1x3. Почему есть 4 элемента? Кроме того, вы хотите также печатать ответы, которые превышают 2000 или даже комбинации, которые разделяют строку или столбец? –

1

Вот это исправление следует сделать трюк:

SA = sum(A); 
V = cell(numel(B), 1);     % // Changed 'length' to 'numel' 
n = 1; 
for k = 1:size(B, 1)     % // Changed 'length' to 'size' 
    for idx = nchoosek(1:numel(B), k)' %'// Changed 'length' to 'numel' 

     %// Ignore the combination if there are two elements from the same row 
     rows = mod(idx, size(B, 1)); 
     if ~isequal(rows, unique(rows)) 
      continue 
     end 

     B_subset = B(idx); 
     if (SA + sum(B_subset) <= 2000) 
      V(n) = {B_subset(:)}; 
      n = n + 1; 
     end 
    end 
end 

Возможно, это не самое эффективное решение Eсть, но это коротко, и это работает.

+0

пример, что означает ~ равнозначно? и как этот код перебирает разные строки/столбцы, прежде чем проверять, являются ли они жизнеспособными комбинациями? – NLed

+0

@NLed 'numel' означает количество элементов - в этом случае это 4x3 = 12. '~' является отрицанием в matlab, поэтому это '~ isequal' означает, что' rows' не равно 'unique (rows)' - это происходит, когда в 'rows' есть дублированные элементы. –

+0

@DedekMraz благодарит вас за объяснение – NLed

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