数值优化问题-在产品和方案之间进行选择所需的算法

时间:2019-07-08 11:01:25

标签: algorithm optimization numeric

我正在尝试针对以下情况找到最佳算法:我有许多不同的产品,每个产品有4个方案(彼此无关)以及该方案的成本和收入。例如:

Products and Scenarios

然后,我想找到方案的最佳组合,以便它在不超过给定成本约束的情况下返回最多的收入。例如。我希望它返回:

enter image description here

我考虑过创建每种可能的组合并计算每种组合的成本和收入(并且只选择成本<£x的最大收入),但是组合太多了,因为我有大约120种产品和5种方案(宇宙中有原子。

有人知道有什么算法可以对最佳方案做出最佳猜测吗?

非常感谢

1 个答案:

答案 0 :(得分:3)

这是著名的运筹学问题的一个版本,称为“ The Knapsack Problem”。

通常,这是一个“ NP-Hard”问题,因此没有已知的方法可以有效,最佳地解决此问题。 (而且您的版本比基本问题还要难。)

如果仍然需要最佳解决方案,则可以使用整数编程优化器/求解器来求解以下模型:

maximize sum( Revenue_ik * I_ik ) over all product-scenarios i,k  # maximize revenue

s.t.
sum( Cost_ik * I_ik ) over all product-scenarios i,k <= BUDGET  # Total cost should be lower than the budget
sum( I_ik ) over all scenarios k <= 1 for all products i   # Choose at most 1 scenario per product (we can make it equals if we *have* to choose)

I_ik in {0, 1} # Decision variables are binary: not choose or choose

话虽这么说,还有其他方法可以找到一个好的解决方案。例如,您可以使用试探法和本地搜索方法,例如:

  • 按收入/成本对选项进行排序,总是贪婪地选择成本效益最高的产品x方案。
  • 获取初始解决方案后,通过同时交换2个产品的方案来检查是否有可能进行改进。也就是说,在降低成本的同时又增加了成本。

此外,通常存在伪多项式算法来解决这类问题。对于您而言,(除非我丢失了某些东西)以下动态编程关系成立:

f(i, w) = max revenue possible using products 0...i, which costs at most w.

f(i, w) = max{ f(i-1, w) , f(i-1, w-Cost_ik) + Revenue_ik for each scenario k for product i }
f(-1, w) = 0 # base case
f(i, w) = -INFINITY if w < 0 # base case

如果最大预算W是合理的,则此算法可以非常有效地找到最佳解决方案。例如,下面是一个Python代码段,该代码段可以以275美元的预算最佳地解决您的当前实例:

cache = {}
chosen = {}

revenue = [[0, 200, 240, 250], [0, 207, 257, 398], [0, 115, 400, 350], [0, 240, 300, 340]]
cost = [[0, 30, 40, 60], [0, 35, 38, 70], [0, 110, 160, 240], [0, 80, 200, 350]]
scenarios = [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3]]
BUDGET = 275

def f(i, w):
    if w < 0:
        return -10000000
    if i == -1:
        return 0
    if (i, w) in cache:
        return cache[(i, w)]

    vals = [f(i - 1, w - cost[i][k]) + revenue[i][k] for k in scenarios[i]]
    max_val = max(vals)
    chosen_scenario = vals.index(max_val)
    chosen[(i, w)] = chosen_scenario
    cache[(i, w)] = max_val
    return max_val

print(f(3, BUDGET))
result = []
W = BUDGET
for i in reversed(range(len(scenarios))):
    chosen_scenario = chosen[(i, W)]
    result.append(chosen_scenario)
    W -= cost[i][chosen_scenario]

result.reverse()
print(result)  

输出:

1038
[2, 3, 2, 0]

最大可能的收入是1038,依次为每种产品选择方案2、3、2和0。