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

Scipy/Facile优化逻辑构建求助:求和优化代码实现困惑

针对你的组合优化问题的解决方案

先帮你把问题拆解清楚,这本质是个0-1整数线性规划问题——选或不选某一行是二元决策,还要满足各表格的选行数量约束,刚好能用scipy的优化工具解决。下面结合建模思路和代码示例给你讲透:

第一步:把问题转化为数学模型

假设你有5个表格A、B、C、D、E,分别有n_A、n_B、n_C、n_D、n_E行。我们给每一行分配一个0-1变量:

  • A的第i行对应变量x_Ai,选则为1,不选为0
  • B的第j行对应变量x_Bj,以此类推

目标函数

假设你要优化的是选中行的某个指标之和(比如每行的成本、收益),比如最小化这个和:

总目标 = sum(x_Ai * 行i的指标值) + sum(x_Bj * 行j的指标值) + ... + sum(x_Em * 行m的指标值)

如果是最大化,只需要把目标函数取反(因为scipy工具默认求最小)。

约束条件

  1. 各表格的选行数量要求:
    • A选2行:sum(x_A1, x_A2, ..., x_AnA) = 2
    • B选3行:sum(x_B1, x_B2, ..., x_BnB) = 3
    • C选2行:sum(x_C1, ..., x_CnC) = 2
    • D选1行:sum(x_D1, ..., x_DnD) = 1
    • E选1行:sum(x_E1, ..., x_EnE) = 1
  2. 所有变量只能是0或1:x_xxx ∈ {0,1}

第二步:用scipy.linprog实现(推荐,scipy 1.9+支持)

直接上可运行的示例代码,你可以替换成自己的表格数据:

import numpy as np
from scipy.optimize import linprog

# ---------------------- 替换成你的实际数据 ----------------------
# 每个表格的行对应的待优化指标值(比如成本、收益)
A_vals = [1.2, 3.1, 2.5, 4.0]  # A有4行,要选2行
B_vals = [0.8, 1.5, 2.2, 3.0, 0.5]  # B有5行,要选3行
C_vals = [5.0, 2.3, 1.8]  # C有3行,要选2行
D_vals = [3.5, 2.8]  # D有2行,要选1行
E_vals = [4.2, 1.9]  # E有2行,要选1行
# --------------------------------------------------------------

# 1. 构建目标函数系数数组c(把所有行的指标值合并成一维)
c = np.concatenate([A_vals, B_vals, C_vals, D_vals, E_vals])

# 2. 构建约束条件的等式矩阵A_eq和右端向量b_eq
n_A, n_B, n_C, n_D, n_E = len(A_vals), len(B_vals), len(C_vals), len(D_vals), len(E_vals)
total_vars = len(c)

# 每个约束对应一行,只有对应表格的变量位置为1
constraint_A = np.zeros(total_vars)
constraint_A[:n_A] = 1  # A的变量在最前面

constraint_B = np.zeros(total_vars)
constraint_B[n_A:n_A+n_B] = 1

constraint_C = np.zeros(total_vars)
constraint_C[n_A+n_B:n_A+n_B+n_C] = 1

constraint_D = np.zeros(total_vars)
constraint_D[n_A+n_B+n_C:n_A+n_B+n_C+n_D] = 1

constraint_E = np.zeros(total_vars)
constraint_E[-n_E:] = 1  # E的变量在最后

A_eq = np.vstack([constraint_A, constraint_B, constraint_C, constraint_D, constraint_E])
b_eq = np.array([2, 3, 2, 1, 1])  # 对应各表格的选行数量

# 3. 设置变量边界:每个变量只能是0或1
bounds = [(0, 1)] * total_vars

# 4. 求解整数规划
result = linprog(
    c=c,
    A_eq=A_eq,
    b_eq=b_eq,
    bounds=bounds,
    method='highs',  # 必须用支持整数约束的方法
    integrality=np.ones(total_vars)  # 所有变量都是整数(0或1)
)

# 5. 解析结果
if result.success:
    print("✅ 优化成功!")
    x = result.x.round()  # 浮点数结果转0-1整数
    # 提取每个表格选中的行索引
    selected_A = np.where(x[:n_A] == 1)[0]
    selected_B = np.where(x[n_A:n_A+n_B] == 1)[0]
    selected_C = np.where(x[n_A+n_B:n_A+n_B+n_C] == 1)[0]
    selected_D = np.where(x[n_A+n_B+n_C:n_A+n_B+n_C+n_D] == 1)[0]
    selected_E = np.where(x[-n_E:] == 1)[0]
    
    print(f"A选中的行索引:{selected_A}")
    print(f"B选中的行索引:{selected_B}")
    print(f"C选中的行索引:{selected_C}")
    print(f"D选中的行索引:{selected_D}")
    print(f"E选中的行索引:{selected_E}")
    print(f"目标函数最终值:{result.fun:.2f}")
else:
    print("❌ 优化失败,原因:", result.message)

第三步:关键细节说明

  • 最大化需求处理:如果要最大化指标和,只需把c改成-c,最后把result.fun取反即可。
  • 低版本scipy兼容:如果你的scipy版本低于1.9,无法使用linprog的integrality参数,可以改用scipy.optimize.minimize配合整数约束:
    from scipy.optimize import minimize, LinearConstraint, Bounds
    
    def objective(x):
        return np.dot(x, c)  # 最大化的话返回 -np.dot(x, c)
    
    linear_constraint = LinearConstraint(A_eq, b_eq, b_eq)
    bounds = Bounds([0]*total_vars, [1]*total_vars)
    x0 = np.zeros(total_vars)  # 初始猜测值
    
    result = minimize(
        objective,
        x0=x0,
        method='trust-constr',
        bounds=bounds,
        constraints=[linear_constraint],
        integrality=np.ones(total_vars)
    )
    
  • 无解排查:如果优化失败,先检查表格行数是否满足选行要求(比如A只有1行却要求选2行,肯定无解)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:36:52