Алгоритм для поиска наилучшей комбинации

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

Можно ли найти наилучшую комбинацию из 15 продуктов за менее чем 10 долларов США, из которых наибольшая сумма энергии (kJ), используя программирование?

Я знаю С#, но любой язык в порядке. Приветствия.

Обновление:. Немножко найти исходный код примера для выпуска рюкзака. Кто-нибудь есть или знает, где их найти. Бывали по поиску в Интернете в течение нескольких часов и, если возможно, нужно было отсортировать их завтра. Та.

Ответ 1

http://en.wikipedia.org/wiki/Knapsack_problem

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

Ответ 2

Это больше похоже на проблему linear programming.

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

Проверьте Симплексный метод.

Ответ 3

Это в Integer Linear Programming, оптимизирующее линейное уравнение, подверженное линейным ограничениям, где все переменные и коэффициенты являются целыми числами.

Вы хотите, чтобы переменные includeItem1,..., includeItemN с ограничениями 0 ≤ includeItemi ≤ 1 для всех значений я и includeItem1 +... + includeItemN ≤ 15 и includeItem1 * priceItem1 +... ≤ 10, максимально включающийItem1 * kilojouleItem1 +....

Положите это в свой любимый целочисленный решатель линейных программ и получите решение:)

См. также http://en.wikipedia.org/wiki/Linear_programming

Не имеет смысла говорить, что ваша конкретная проблема NP-полная, но она является экземпляром NP-полной (какой-то) проблемы, поэтому может быть и не теоретически быстрый способ ее выполнения. В зависимости от того, насколько вы близки к оптимальности, которую вы хотите получить, и как быстро работают ИЛП, это может быть осуществимо на практике.

Я не думаю, что проблема - это особый случай ILP, который делает его особенно легким для решения. Рассматривая это как проблему с рюкзаком, вы можете ограничить себя просмотром всех подмножеств 1..100, которые содержат не более (или точно) 15 элементов, которые являются многочленными в n --- it n-choose-15, что меньше (n ^ 15)/(15!), но это не очень полезно при n = 100.

Если вам нужны рекомендации для программ-решателей, я попробовал glpk и нашел приятным в использовании. Если вы хотите что-то, что стоит денег, мой преподаватель всегда говорил о CPLEX в качестве примера.

Ответ 4

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

Ответ 5

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

Закажите элементы по соотношению цена/качество, выбирая 100% самых высоких, пока не закончите деньги, затем выберите дробное значение самого высокого оставшегося.

Например, если цены 4,3,5,4 и энергии 3,5,2,7, заказ

7/4, 5/3, 3/4, 2/5

Итак, вы бы выбрали предметы 4 и 2, которые стоили бы 7 $, а оставшиеся 3 $вы купили бы 75% первого предмета по цене 3 доллара и энергии 3 *.75 = 2.25

Это даст полную энергию 14,25

Обратите внимание, что использование дробных значений даст вам более высокое объективное значение, чем разрешение только 0% или 100%, поэтому никакое целочисленное решение не будет лучше 14.25 (или 14 в этом отношении, поскольку объективное значение должно быть целым).

Чтобы решить проблему с оригинальным рюкзаком, вы можете использовать ветку и привязку, которые должны работать на практике. Предположим, что у вас есть текущее решение кандидата с объективным значением z *

  • Решите расслабленную проблему, где вы допускаете дробные веса. Если значение меньше z *, отбросьте эту ветвь.
  • Вычислить новое значение z, которое является решением, найденным без последнего дробного веса, если это значение больше z *, замените z * на ваше новое значение
  • Выберите один элемент (скажем, первый в списке, самый прибыльный) и сформируйте две подзадачи, в которых вы должны включить его в решение, а другое, где вы не можете включить его в решение (это шаг ветвления).
  • Пока у вас есть подзадачи, которые нужно решить, выберите один и вернитесь к шагу 1.

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

Для более подробного описания смотрите Branch and Bound в Википедии.

Ответ 7

Да, как все отметили, это сложная проблема с рюкзаком. Что-то простое может быть достаточно хорошим, хотя...

SELECT TOP 15 *
FROM Product
WHERE Price < 10
ORDER BY Energy DESC

Ответ 9

Должна быть разрешена проблема с Cream for Java. Там также доступна версия для С# CSharpCream.