Алгоритм сортировки и группировки списка взвешенных объектов

У меня есть несколько фрагментов данных.

Ради аргументов мы скажем, что они

File 1 - 150Kb
File 2 -  50Kb
File 3 -  70Kb
File 4 -  60Kb
File 5 -  70Kb
File 6 - 100Kb
File 7 -  90Kb

Для передачи я могу упаковать их в максимальную полезную нагрузку 300 КБ.

Если вы просто перебираете их, чтобы получить

TRANS1: 150Kb + 50Kb + 70Kb = 270Kb - the next file puts you over the limit of 300Kb
TRANS2: 60Kb + 70Kb + 100Kb = 230Kb - the next file puts you over the limit of 300Kb
TRANS3: 90Kb

Итак, три отдельные передачи.

Но если вы реорганизуете их, вы можете отправить

Files 1,2,6 together = 300Kb
Files 3,4,5,7 together = 290Kb

Таким образом, вы сократите количество отдельных передач. Поскольку с каждой передачей связаны денежные затраты (эти передачи на самом деле являются вызовами API к сторонней системе, где мы выставляем счет за каждый вызов API), мы хотели бы свести количество отдельных отправок полезной нагрузки к минимуму.

Существует ли какой-либо алгоритм сортировки вокруг такого рода оптимизации, который будет принимать список взвешенных объектов и сортировать/группировать их, чтобы в итоге вы получили наименьшее количество групп?

Для справки, я бы кодировал это в .NET, но если вы можете предоставить пример на другом языке или реализацию/описание псевдокода, это тоже было бы здорово.

Спасибо, Эоин С.


person Eoin Campbell    schedule 04.06.2010    source источник
comment
en.wikipedia.org/wiki/Knapsack_problem   -  person Artelius    schedule 04.06.2010
comment
Спасибо Artelius & Thariama, это выглядит именно так, как мне нужно. Очень признателен. Никогда раньше не слышал термина «проблема рюкзака». Ваше здоровье :)   -  person Eoin Campbell    schedule 04.06.2010
comment
И спасибо, Петар, я думаю, что твоя проблема с упаковкой контейнеров лучше соответствует тому, что я пытаюсь сделать. Буду исследовать оба. Для справки, в лучшем случае будет только 7-8 чанков и в большинстве случаев ‹ 5.   -  person Eoin Campbell    schedule 04.06.2010
comment
Если это всего 7-8 чанков, просто переберите все возможные комбинации, и все будет хорошо :)   -  person Petar Minchev    schedule 04.06.2010
comment
да, я думаю, что в случае, если элементов не больше 7 или 8, лучше всего использовать подход Петарса для создания всех возможных комбинаций.   -  person Thariama    schedule 04.06.2010


Ответы (3)


Ваша проблема в точности связана с проблемой упаковки в корзину, которая, к сожалению, является NP-полной:( Если число пакетов довольно мало, вы можете перебрать любую возможную комбинацию.

В противном случае предлагаемое мной решение динамического программирования не даст оптимального ответа, поскольку будет предполагать, что вы всегда группируете последовательные пакеты. Но он будет работать быстро и даст что-то близкое к истине. Я использую рекурсию с мемоизацией. Хорошо бы вначале отсортировать пакеты по возрастанию.

const int INF = 1000000;
const int MAXSIZE = 300;
int DP[NumberOfPackets][MaxPayload];

int solve(int packetNum, int sizeUsed)
{
   if (packetNum == NumberOfPackets)
      return 0;

   if (DP[packetNum][sizeUsed] != -1)
      return DP[packetNum][sizeUsed];

   int res = INF;

   //Try to put the packet in the current group
   if (sizeUsed + size[packetNum] <= MAXSIZE) 
      res = min(res, solve(packetNum + 1, sizeUsed + size[packetNum]));

   //Try to start another group with the current packet
   res = min(res, solve(packetNum + 1, size[packetNum]) + 1);

   return DP[packetNum][sizeUsed] = res;
}

int answer = solve(1, size[0]);
person Petar Minchev    schedule 04.06.2010
comment
на самом деле это выглядит немного лучше для того, что я делаю, чем рюкзак. Спасибо Петар. - person Eoin Campbell; 04.06.2010
comment
@Eoin: Не «немного лучше». Bin-packing — точное совпадение. Рюкзак и бин-упаковка - это разные вещи! Bin-packing строго NP-Complete, т. е. никаких алгоритмов псевдополиномиального времени. В случае с Knapsack это не так. - person ; 04.06.2010

То, что вы ищете, - это алгоритм рюкзака или его модификация. Проблема не решается эффективно, но вы можете приблизиться к идеальному решению.

Вы можете использовать этот поиск Google для реализации.

person Thariama    schedule 04.06.2010
comment
К этому следует добавить, что если фактическое n составляет всего 7 или около того, асимптотическая эффективность на самом деле не является проблемой. - person AakashM; 04.06.2010

Это напоминает мне проблему с рюкзаком. Я не следил за этим, но я помню, что это NP-полная проблема: читайте «сложно». В основном нужно найти компромисс между «правильным» и «быстрым».

Это не значит невозможно, но это явно та область, где совершенство — враг хорошего.

Я бы начал с подхода «Сначала большие камни», запустив пару симуляций. Держите лучшее решение. Используйте ограниченное время, чтобы прервать поиск и использовать лучший из найденных на данный момент.

person Peter Tillemans    schedule 04.06.2010
comment
Исходная проблема рюкзака может быть решена за время NumberOfItems * AvailableCapacity. Но его проблема немного в другом. Я думаю, чтобы найти оптимальное решение, он должен проверить все возможности, в отличие от задачи о рюкзаке. - person Petar Minchev; 04.06.2010
comment
Да, но это сложно сделать в ограниченное время, как это всегда необходимо в реальной жизни. Вот почему вы должны быстро найти разумное решение, посмотреть, сможете ли вы найти лучшее, и использовать лучшее, что вы нашли, когда время истекло. В практических случаях количество элементов будет разумным, но если моя жена пойдет за покупками, вам понадобится кластер Hadoop. - person Peter Tillemans; 04.06.2010
comment
Да, это правда. Я просто хотел сказать, что его проблема (упаковка мусорного ведра) сложнее, чем у оригинального рюкзака. - person Petar Minchev; 04.06.2010