python - 如何解决带有额外约束的背包问题? (或替代算法)

标签 python optimization mathematical-optimization matching knapsack-problem

扩展背包问题的常见动态规划解决方案:

def knapSack(W, wt, val, n):
    results = []
    K = [[0 for x in range(W + 1)] for x in range(n + 1)]
    # Build tаble K[][] in bоttоm uр mаnner
    for i in range(n + 1):
        for w in range(W + 1):
            if (i == 0)  or  (w == 0):
                K[i][w] = 0
            elif wt[i-1] <= w:
                K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w])
            else:
                K[i][w] = K[i-1][w]
    print(K[n][W])
    return(set(results))


# Driver code
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)

knapSack(W, wt, val, n) = 220

现在也许我添加额外的约束:

# Driver code
val_all = [60, 100, 120, 50, 80, 10]
wt_all = [10, 20, 30, 15, 20, 5]
W_all = 50
n_all = len(val_all)

val_1 = [60, 100, 120]
wt_1 = [10, 20, 30]
W_1 = 30
n_1 = len(val_1)

val_2 = [50, 80, 10]
wt_2 = [15, 20, 5]
W_2 = 25
n_2 = len(val_2)

我想使用相同的值最大化所有 3 个值。 val_all 的解为 240 [60, 100, 80]。 val_1 的最大值为 160 [60, 100],val_2 的最大值为 90 [80, 10],但考虑到我想要相同的值,并且 10 不在其他两组中,则最大解决方案将为 80。

我还想知道您是否可以添加到函数中以提供所选值以及最大值。这种方法对于大型列表是否可行,因为我有一个包含 150,000 个不同值的列表,每个值都有不同的权重。

可能有更好的算法,我的问题是我有 150,000 个值,每个值都有一个权重,需要选择任意数量的这些值,以便我们获得接近上限的 W 值。然而,该数据实际上是两种不同类型值的混合,每种类型的权重之和也有 W1 和 W2 上限值。我想最大化所有三个方程,但使用同一组值。 W1 或 W2 中选择的任何值都必须存在于 W 中。

这个背包代码不会很有用,因为我有 150k 个值,平均重量为 50,重量上限为 600 万。如此大的循环,时间复杂度将是巨大的。

最佳答案

根据最上面的评论,我发现了一个非常快并且允许这样做的包:

from mip import Model, xsum, maximize, BINARY

all = pd.read_csv('df_all.csv')
X = pd.read_csv('df_x_only.csv')
Y = pd.read_csv('df_y_only.csv')

p = all.id.values # as we arent optimizing the value of the index, p is irrelevant and we replace xsum(p[i] with xsum(w[i] in the objective function
w = all.new_weights.values
w1 = X.new_weights.values
w2 = Y.new_weights.values

c = 5876834
Cx = 4902953
Cy = 719051.4

I = range(len(w))
I1 = range(len(w1))
I2 = range(len(w2))

m = Model("knapsack")

x = [m.add_var(var_type=BINARY) for i in I]

m.objective = maximize(xsum(w[i] * x[i] for i in I)) + maximize(xsum(w1[i] * x[i] for i in I1)) + maximize(xsum(w2[i] * x[i] for i in I2))

m += xsum(w[i] * x[i] for i in I) <= c*1.05
m += xsum(w[i] * x[i] for i in I) >= c*0.95
m += xsum(w1[i] * x[i] for i in I1) <= Cx*1.05
m += xsum(w1[i] * x[i] for i in I1) >= Cx*0.95
m += xsum(w2[i] * x[i] for i in I2) <= Cy*1.05
m += xsum(w2[i] * x[i] for i in I2) >= Cy*0.95

m.optimize()


selected = [i for i in I if x[i].x >= 0.99]

关于python - 如何解决带有额外约束的背包问题? (或替代算法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74602059/

相关文章:

python - Raspberry - 发送 CAN 消息

optimization - 这个时钟什么时候买的?

python - 为什么我的 NLTK 函数在处理 DataFrame 时很慢?

c# - 优化托管到 native 调用

opencv - 如何计算神经网络输出层的二阶导数?

python - 如何保护 python 中的 mysqldb 连接?

python - QtDesigner 预览与实际 GUI 不同

machine-learning - RISO 的 L-BFGS 不起作用

寻找最小组件集合的算法

python - 根据条件将 df 中的列除以另一个 df 值