Кто знает правильные алгоритмы?

Все, что вы хотели знать о программизме, но боялись спросить.
anton2
Частый Гость
Сообщения: 41
Зарегистрирован: 08 май 2006, 17:20

Re: Кто знает правильные алгоритмы?

Сообщение anton2 »

nemiga писал(а): Вводим параметр товара "отношение качество-цена" (Goodie.value:=Goodie.quality/Goodie.price). Сортируем все товары по убыванию параметра value и отбираем сверху, пока денег хватит.
Ну например так:

товар 1 - цена 6, качество 61
товар 2 - цена 5, качество 50
товар 3 - цена 5, качество 50
бюджет 10
получаем 61 а не 100 :twisted:
anton2
Частый Гость
Сообщения: 41
Зарегистрирован: 08 май 2006, 17:20

Сообщение anton2 »

Старина Зотин писал(а):Самое забавное, что эта фигня, которую я написал в виде прототипа, оказывается, называется громким именем Martello and Toth greedy approximation algorithm.

Наверное, чуваки очень долго думали..

Кстати, мне придется с ним и остаться. Динамическое программирование в моем случае не работает. Я с целью упрощения не все рассказал о задаче. На самом деле у меня каждый предмет представляет из себя дерево предметов, суммарное value которых составляет value корня, ну и price, соответственно распределяется по ветвям. Если дерево перестает помещаться, его можно раздробить и включать отдельные ветви. В этом случае этот самый Martello and Toth обеспечивает довольно плотное заполнение (хотя и не оптимальное, но не слишком от него далекое - явно больше V/2, как с линейным списком), а кроме того я придумал, как все сделать за один проход дерева.

А динамическое программирование не работает, потому что результаты предыдущей итерации в этом случае, не обязательно подходят для следующей. Иногда можно добиться лучшего заполнения при неоптимальном заполнении на предыдущем шагу.
Интересная задача, а поподробней можно?

Если бы каждый товар можно было делить на произвольные части, то greedy алгоритм дает оптимальное решение (просто можно взять сначала самый лучший товар, потом тот который похуже и так далее, деля на части если не влезает в бюджет) - похоже что задача ближе к этому варианту.
vg
Маньяк
Сообщения: 2803
Зарегистрирован: 29 май 2003, 22:29
Откуда: Магадан - Миссиссага

Сообщение vg »

Старина Зотин писал(а): Динамическое программирование в моем случае не работает.
Не только в твоём. При шести и большей размерностях - задача практически не решается. Вернее очень медленно.
Аватара пользователя
sz
Маньяк
Сообщения: 1266
Зарегистрирован: 17 фев 2003, 19:34

Сообщение sz »

Поподробней можно, но боюсь утомить.

В общем, никаких роботов-покупателей я, разумеется, не пишу, а просто занимаюсь оптимизацией.

Задача примерно такая. Есть некий массив данных, который рассчитывается при прохождение через дерево в котором каждая нода делает какой-то свой вклад в рассчет. Ноды бывают разных типов и на рассчет у них уходит разное время. Одна из нод занимается тем, что сводит результаты своих детей с соотв. присвоенными весами. Ее называют BlendNode, а операцию сведения blending. Собственно, именно blend nodes и обеспечивают ветвление (на самом деле, не только они, но это уже детали - для нашей задачи достаточно считать, что только они).

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

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

Вопрос состоит в том, чтобы алгоритм поиска не перевесил выигрыш от выбрасывания нод. То, что я пока написал смотрится относительно неплохо - выполняется за линейное время O(N) (N - количество blends в дереве), абсолютное время выполнения порядка половины миллисекунды на дерево содержащее 100 blend nodes.
При потере точности 10% из 100 blends дерева вырезается в среднем около 60 нод. Время выполнения одной ноды сильно разнится в зависимости от типа, но в среднем это 0.1-0.2 миллисекунды. То есть, с моим алгоритмом в этом случае выигрывается 5 ms (что вдвое быстрее). По нашим меркам, это очень много.
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

любопытно. а как дерево меняется между итерациями ?
оно строится с нуля, оно пересобирается из текущего ?

поинт в том, чтобы посмотреть нельзя ли incrementally пересчитывать knapsack contents ..
Аватара пользователя
sz
Маньяк
Сообщения: 1266
Зарегистрирован: 17 фев 2003, 19:34

Сообщение sz »

Строится с нуля.
Аватара пользователя
nemiga
Маньяк
Сообщения: 2425
Зарегистрирован: 02 сен 2006, 19:05
Откуда: Minsk -> Seoul -> Ottawa

Re: Кто знает правильные алгоритмы?

Сообщение nemiga »

anton2 писал(а):
nemiga писал(а): Вводим параметр товара "отношение качество-цена" (Goodie.value:=Goodie.quality/Goodie.price). Сортируем все товары по убыванию параметра value и отбираем сверху, пока денег хватит.
Ну например так:

товар 1 - цена 6, качество 61
товар 2 - цена 5, качество 50
товар 3 - цена 5, качество 50
бюджет 10
получаем 61 а не 100 :twisted:
Пример искусственный: бюджет соизмерим с ценой товара. Я проверял на random выборке с большим бюджетом -- работает со свистом.

.
Аватара пользователя
sz
Маньяк
Сообщения: 1266
Зарегистрирован: 17 фев 2003, 19:34

Сообщение sz »

Ну так он и в жизни может оказаться соизмерим.
Аватара пользователя
nemiga
Маньяк
Сообщения: 2425
Зарегистрирован: 02 сен 2006, 19:05
Откуда: Minsk -> Seoul -> Ottawa

Re: Кто знает правильные алгоритмы?

Сообщение nemiga »

anton2 писал(а):
nemiga писал(а): Вводим параметр товара "отношение качество-цена" (Goodie.value:=Goodie.quality/Goodie.price). Сортируем все товары по убыванию параметра value и отбираем сверху, пока денег хватит.
Ну например так:

товар 1 - цена 6, качество 61
товар 2 - цена 5, качество 50
товар 3 - цена 5, качество 50
бюджет 10
получаем 61 а не 100 :twisted:
Еще можно попробовать так. Вводим кредит. Если денег не хватает, занимаем в долг. При этом параметр value вещи, купленой в долг, уменьшаем по той или иной формуле -- чем больше под эту вещь заняли, тем больше уменьшаем*.

Дальше, когда корзина заполнится, сортируем все вещи по "чистому" value (без учета сколько под какую занимали) и начинаем отдавать долг, выбрасывая сначала те, у которых value меньше.

*Примечание: да, даже с заемом может так получится, что самую лучшую вещь не купишь, но по-моему, этот алгоритм лучше простого greedy.

.
Ответить