Оптимизация наилучшего коэффициента усиления в зависимости от емкости / стоимости

#python #algorithm

#python #алгоритм

Вопрос:

Приведен примерный набор данных, представляющих (стоимость, коэффициент усиления)

 items = [ (1000, 300), (500, 150), (400, 120), (300, 100), (200, 50), (55, 25) ]
  

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

f (элементы, емкость, максимальная стоимость)

создаст единую запись, указывающую наиболее эффективные количества элементов, ограниченных емкостью и стоимостью.

 class BestCombo(object):

    def __init__(self, items, qtyLimit, costLimit):
      self.bestPerf  = 0
      self.best      = None
      self.items     = items
      self.qtyLimit  = qtyLimit
      self.costLimit = costLimit

      self._findBest(load=[], qty=0, cost=0, perf=0)

    def _findBest(self, load, qty, cost, perf):
      idx = len(load)
      if idx >= len(self.items):
        if qty <= self.qtyLimit and cost <= self.costLimit:
          if perf > self.bestPerf:
            self.bestPerf = perf
            self.best = list(load)
        return

      item = self.items[idx]
      maximum = min(self.qtyLimit - qty, (self.costLimit - cost) // item[0])
      for q in range(0, maximum   1):
        self._findBest(load   [[item, q]], qty   q, cost   item[0] * q, perf   item[1] * q)

items = [ (1000, 300), (500, 150), (400, 120), (300, 100), (200, 50), (55, 25) ]
print("3, 900")
print(BestCombo(items, 3, 900).best)
print("3, 1100")
print(BestCombo(items, 3, 1100).best)
print("3, 3000")
print(BestCombo(items, 3, 3000).best)
print("10, 900")
print(BestCombo(items, 10, 900).best)
print("42, 21000")
print(BestCombo(items, 42, 21805).best)
  

Таким образом, получается «наилучший» результат, который указывает, что 3 единицы производительности по 900 лучше всего подходят для 3 из (300,100) элементов, в то время как 3,1100 дают наилучшие значения 1×500 и 2×300.

Хотя этот подход работает, он очень медленный для нетривиальных значений.

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

Список «элементы» потенциально может содержать максимум 64-90 элементов, емкость вряд ли будет намного выше 255.

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

Возможно ли выполнить поиск без применения грубой силы?

Ответ №1:

Это очень похоже http://en.wikipedia.org/wiki/Knapsack_problem. В общем случае это займет экспоненциальное время, но один из подходов динамического программирования может оказаться практичным, особенно если вы готовы округлить некоторые числа, чтобы получить точный ответ на задачу с округленными числами, который будет приблизительным ответом на вашу проблему.