You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改代码实现单类别最多选一次的Totpod最大化求解

问题分析与解决方案

原代码的核心问题是决策变量定义错误,以及目标函数和约束逻辑完全偏离需求。你需要为每个数据行(而非每个Cat类别)创建二进制变量,同时约束每个Cat类别下最多选中一行,最终最大化选中行的Totpod总和。

修正后的Pulp实现代码

import pandas as pd
from pulp import LpProblem, LpVariable, LpMaximize, lpSum, value

# 构建数据框,保留原始索引a/b/c
data = {'a': ['Amu', 508], 'b': ['Coif', 508], 'c': ['Amu', 253]}
df = pd.DataFrame.from_dict(data, orient='index', columns=['Cat', 'Totpod'])

# 为每个行(索引a/b/c)创建二进制决策变量:1表示选中该行,0表示不选
row_vars = LpVariable.dicts("Row", df.index, cat="Binary")

# 创建最大化问题
prob = LpProblem("Maximize_TotPod", LpMaximize)

# 目标函数:最大化选中行的Totpod总和
prob += lpSum(row_vars[row] * df.loc[row, 'Totpod'] for row in df.index)

# 约束条件:每个Cat类别下,选中的行数量不超过1
for cat in df['Cat'].unique():
    prob += lpSum(row_vars[row] for row in df[df['Cat'] == cat].index) <= 1

# 求解问题
prob.solve()

# 提取选中的行索引和总和
selected_rows = [row for row in df.index if row_vars[row].value() == 1]
total_totpod = value(prob.objective)

print("Selected index:", selected_rows)
print("Max Totpod:", total_totpod)

关键修改点说明

  • 决策变量调整:将原有的cat_vars改为row_vars,针对每个数据行(a/b/c)创建二进制变量,精准控制每行是否被选中。
  • 目标函数修正:直接累加选中行的Totpod值,而非按Cat类别求和后再计算。
  • 约束逻辑修正:针对每个唯一的Cat类别,约束该类别下选中的行数量≤1,确保每个类别最多选一次。
  • 结果计算修正:移除错误的totpod_sum累加,直接取目标函数的计算值作为总和,同时输出选中的行索引而非Cat值。

可选方案:使用Scipy优化器实现

如果你想更换优化器,可使用Scipy的linprog(注意Scipy默认是最小化,需转换为最大化问题):

import pandas as pd
from scipy.optimize import linprog

# 构建数据
data = {'a': ['Amu', 508], 'b': ['Coif', 508], 'c': ['Amu', 253]}
df = pd.DataFrame.from_dict(data, orient='index', columns=['Cat', 'Totpod'])

# 目标函数系数:因为linprog是最小化,所以取负数
c = -df['Totpod'].values

# 约束矩阵:每个Cat类别对应一行约束,确保选中数量≤1
constraints = []
for cat in df['Cat'].unique():
    row_mask = df['Cat'] == cat
    constraint_row = [1 if row_mask.iloc[i] else 0 for i in range(len(df))]
    constraints.append({'type': '≤', 'fun': lambda x, cr=constraint_row: sum(x * cr) - 1})

# 变量边界:每个变量是0或1的二进制变量
bounds = [(0, 1) for _ in range(len(df))]

# 求解
result = linprog(c, bounds=bounds, constraints=constraints, method='highs')

# 提取结果
selected_rows = df.index[result.x.round() == 1].tolist()
total_totpod = -result.fun

print("Selected index:", selected_rows)
print("Max Totpod:", total_totpod)

内容的提问来源于stack exchange,提问作者Wick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:27:28