Python优化Skill python-optimization

Python优化技能提供数学优化在Python中的全面指导,包括问题分类、库选择(如scipy、pyomo、cvxpy、GEKKO)、求解器配置和实现模式,适用于线性规划、二次规划、非线性规划、混合整数规划、凸优化和全局优化问题。关键词:Python优化,数学优化,scipy,pyomo,cvxpy,GEKKO,线性规划,非线性规划,优化算法,参数估计。

预测建模 0 次安装 0 次浏览 更新于 3/12/2026

名称: python-optimization 描述: Python中数学优化的专家指导 - 系统问题分类、库选择(scipy、pyomo、cvxpy、GEKKO)、求解器配置和实现模式,适用于线性规划、二次规划、非线性规划、混合整数规划、凸优化和全局优化问题 允许工具: [“*”]

Python优化专家

概述

通过系统问题分析、适当的库选择和稳健实现,掌握Python中的数学优化。本技能指导您对优化问题进行分类、选择正确的求解器、实现高效解决方案,并在线性规划、非线性规划、混合整数问题和全局优化中解决收敛问题。

核心价值: 将优化问题从数学公式转化为工作Python代码,使用最适合您特定问题类型的库和求解器。

何时使用

在以下情况下使用本技能:

  • 最小化或最大化目标函数
  • 参数估计和曲线拟合
  • 投资组合优化和资源分配
  • 生产计划与调度
  • 工程设计优化
  • 控制与动态优化
  • 解决约束或无约束优化问题
  • 在scipy、pyomo、cvxpy或其他优化库之间选择

不要用于:

  • 简单求根(使用scipy.optimize.root代替)
  • 仅线性代数(使用numpy/scipy.linalg)
  • 需要符号数学(使用sympy)

问题分析框架

步骤1:提取问题组件

始终识别:

  1. 目标函数: 要最小化或最大化什么?

    • 示例:最小化成本、最大化利润、最小化误差
  2. 决策变量: 什么可以改变?

    • 连续(实数)还是离散(整数)?
    • 有多少变量?
  3. 约束: 存在什么限制?

    • 等式约束:h(x) = 0
    • 不等式约束:g(x) ≥ 0
    • 边界:下限 ≤ x ≤ 上限
  4. 数据/参数: 给定了什么值?

    • 常数、测量值、输入数据

步骤2:分类问题类型

线性规划(LP)

  • 线性目标函数
  • 仅线性约束
  • 示例:max c’x subject to Ax ≤ b

二次规划(QP)

  • 二次目标函数
  • 线性约束
  • 示例:min (1/2)x’Qx + c’x subject to Ax ≤ b

非线性规划(NLP)

  • 非线性目标或约束
  • 平滑、可微函数
  • 示例:min f(x) subject to g(x) ≥ 0

混合整数规划(MIP/MILP/MINLP)

  • 部分或所有变量必须是整数
  • 组合优化
  • 示例:调度、分配问题

凸优化

  • 凸目标函数
  • 凸可行域
  • 保证全局最优

全局优化

  • 怀疑有多个局部最小值
  • 非凸问题
  • 需要全局搜索策略

最小二乘

  • 最小化残差平方和
  • 参数估计、曲线拟合
  • 专用求解器利用特殊结构

动态优化 / 最优控制

  • 时间相关变量
  • 微分方程作为约束
  • 轨迹优化

步骤3:表征问题规模

小问题: < 100 变量

  • 大多数方法效果良好
  • scipy.optimize 足够

中等问题: 100-1,000 变量

  • 需要高效算法
  • 考虑专用求解器

大问题: > 1,000 变量

  • 需要稀疏矩阵技术
  • 使用pyomo或专用求解器
  • 利用问题结构

其他特征:

  • 导数可用吗?解析还是数值?
  • 平滑还是非平滑?
  • 稀疏还是密集?
  • 特殊结构(可分离等)?

库选择指南

scipy.optimize - 默认选择

使用时机:

  • 小到中等问题(<1,000 变量)
  • 无约束或平滑约束非线性规划
  • 快速原型和开发
  • 最小二乘 / 曲线拟合
  • 偏好Python原生解决方案

优势:

  • 属于scipy(广泛可用)
  • 易于使用,文档良好
  • 多种算法可用
  • 无需额外依赖

限制:

  • 不理想用于大规模问题
  • 对混合整数支持有限
  • 不如商业求解器复杂

pyomo - 代数建模

使用时机:

  • 大规模问题(>1,000 变量)
  • 混合整数规划
  • 需要多个求解器后端
  • 偏好代数建模
  • 生产环境

优势:

  • 可扩展到非常大的问题
  • 支持许多外部求解器
  • 清晰的数学表示
  • 活跃开发和社区

限制:

  • 对许多问题类型需要外部求解器
  • 学习曲线较陡
  • 额外安装复杂度

cvxpy - 凸优化

使用时机:

  • 问题是(或可能是)凸的
  • 希望自动凸性验证
  • 偏好有纪律的凸规划
  • 投资组合优化、控制

优势:

  • 自动凸性检测
  • 数学表示语法
  • 多个求解器后端
  • 对凸问题优秀

限制:

  • 仅用于凸问题
  • 对非凸问题较不灵活
  • DCP规则的学习曲线

GEKKO - 动态优化

使用时机:

  • 黑盒函数(无导数)
  • 动态优化 / 最优控制
  • 涉及微分方程
  • 过程控制、轨迹优化

优势:

  • 自然处理微分方程
  • 无导数优化
  • 对动态系统良好
  • 时间相关问题

限制:

  • 专用用例
  • 比scipy少见
  • 需要GEKKO服务器

比较表

最适合 问题类型 规模
scipy.optimize 通用非线性规划、原型 线性规划、二次规划、非线性规划、最小二乘 小-中等
pyomo 大规模、混合整数规划 线性规划、混合整数线性规划、非线性规划、混合整数非线性规划 任意
cvxpy 凸问题 线性规划、二次规划、二阶锥规划、半定规划 中等-大
GEKKO 动态优化 非线性规划、微分代数方程、模型预测控制 小-中等

scipy.optimize - 方法选择

无约束优化

minimize(f, x0, method='BFGS', jac=gradient)

  • 用于: 平滑无约束问题
  • 需要: 梯度(或使用有限差分)
  • 优点: 快速收敛、稳健
  • 缺点: 可能陷入局部最小值

minimize(f, x0, method='L-BFGS-B', bounds=bounds)

  • 用于: 大规模带箱约束
  • 优点: 内存高效、处理边界
  • 缺点: 仅箱约束(无一般约束)

minimize(f, x0, method='Nelder-Mead')

  • 用于: 无导数、非平滑
  • 优点: 无需导数
  • 缺点: 收敛慢、对大规模问题不可靠

minimize(f, x0, method='Powell')

  • 用于: 无导数、比Nelder-Mead更好
  • 优点: 比Nelder-Mead更稳健
  • 缺点: 仍无导数(较慢)

约束优化

minimize(f, x0, method='SLSQP', constraints=cons)

  • 用于: 一般约束(等式 + 不等式)
  • 优点: 处理所有约束类型
  • 缺点: 比trust-constr稳健性差

minimize(f, x0, method='trust-constr', constraints=cons)

  • 用于: 困难约束问题
  • 优点: 最稳健、可使用Hessian矩阵
  • 缺点: 比SLSQP慢

minimize(f, x0, method='COBYLA', constraints=cons)

  • 用于: 无导数带约束
  • 优点: 无需导数
  • 缺点: 慢、精度较低

专用函数

least_squares(residual, x0, bounds=bounds)

  • 用于: 非线性最小二乘
  • 优点: 利用平方和结构
  • 缺点: 仅用于最小二乘问题

curve_fit(model, xdata, ydata, p0=initial)

  • 用于: 参数估计、曲线拟合
  • 优点: 拟合的简单接口
  • 缺点: 仅是least_squares的包装

differential_evolution(f, bounds)

  • 用于: 全局优化、多个局部最小值
  • 优点: 找到全局最优、无导数
  • 缺点: 慢、必须指定边界

linprog(c, A_ub, b_ub)

  • 用于: 仅线性规划
  • 优点: 专用线性规划、高效
  • 缺点: 仅线性问题

实现模式

模式1:无约束优化

from scipy.optimize import minimize
import numpy as np

def objective(x):
    """
    要最小化的目标函数。

    示例:Rosenbrock函数
    f(x) = sum((1 - x[i])^2 + 100*(x[i+1] - x[i]^2)^2)
    """
    return sum((1 - x[:-1])**2 + 100*(x[1:] - x[:-1]**2)**2)

def gradient(x):
    """
    解析梯度 - 如果可能总是提供!
    显著提高收敛速度和可靠性。
    """
    grad = np.zeros_like(x)
    grad[:-1] = -2*(1 - x[:-1]) - 400*x[:-1]*(x[1:] - x[:-1]**2)
    grad[1:] += 200*(x[1:] - x[:-1]**2)
    return grad

# 初始猜测
x0 = np.array([0.5, 0.5])

# 优化
result = minimize(objective, x0, method='BFGS', jac=gradient)

# 检查结果
print(f"成功: {result.success}")
print(f"消息: {result.message}")
print(f"最优 x: {result.x}")
print(f"最优值: {result.fun}")
print(f"迭代次数: {result.nit}")
print(f"函数评估次数: {result.nfev}")

模式2:约束优化

from scipy.optimize import minimize
import numpy as np

def objective(x):
    """目标:最小化 x[0]^2 + x[1]^2"""
    return x[0]**2 + x[1]**2

def constraint_ineq(x):
    """不等式约束:x[0] + x[1] - 1 >= 0"""
    return x[0] + x[1] - 1

def constraint_eq(x):
    """等式约束:x[0]^2 + x[1]^2 - 1 = 0"""
    return x[0]**2 + x[1]**2 - 1

# 定义约束(可以有多个)
constraints = [
    {'type': 'ineq', 'fun': constraint_ineq},  # g(x) >= 0
    {'type': 'eq', 'fun': constraint_eq}       # h(x) = 0
]

# 边界:[(下限, 上限), ...],使用None表示无边界
bounds = [(-2, 2), (-2, 2)]

# 初始猜测(如果可能,应该是可行的)
x0 = np.array([0.5, 0.5])

# 优化
result = minimize(
    objective,
    x0,
    method='SLSQP',
    constraints=constraints,
    bounds=bounds,
    options={'ftol': 1e-9, 'maxiter': 1000}
)

print(f"最优 x: {result.x}")
print(f"最优值: {result.fun}")

# 验证约束是否满足
print(f"
约束验证:")
print(f"不等式(应 >= 0): {constraint_ineq(result.x):.6f}")
print(f"等式(应 ~0): {constraint_eq(result.x):.6e}")

模式3:参数估计(曲线拟合)

from scipy.optimize import curve_fit
import numpy as np

def model(x, a, b, c):
    """
    模型函数:f(x; 参数)

    示例:指数衰减 + 偏移
    """
    return a * np.exp(-b * x) + c

# 生成合成数据(实践中,这是您的测量数据)
x_data = np.linspace(0, 10, 50)
y_true = 2.5 * np.exp(-0.3 * x_data) + 0.5
y_data = y_true + 0.1 * np.random.randn(len(x_data))  # 添加噪声

# 将模型拟合到数据
# p0 = 初始参数猜测(可选但推荐)
params, covariance = curve_fit(
    model,
    x_data,
    y_data,
    p0=[2, 0.5, 0]  # 初始猜测:[a, b, c]
)

# 提取参数和不确定性
a_opt, b_opt, c_opt = params
uncertainties = np.sqrt(np.diag(covariance))

print(f"最优参数:")
print(f"  a = {a_opt:.3f} ± {uncertainties[0]:.3f}")
print(f"  b = {b_opt:.3f} ± {uncertainties[1]:.3f}")
print(f"  c = {c_opt:.3f} ± {uncertainties[2]:.3f}")

# 计算R平方
y_pred = model(x_data, *params)
ss_res = np.sum((y_data - y_pred)**2)
ss_tot = np.sum((y_data - np.mean(y_data))**2)
r_squared = 1 - (ss_res / ss_tot)
print(f"
R² = {r_squared:.4f}")

模式4:最小二乘(残差)

from scipy.optimize import least_squares
import numpy as np

def residuals(params, x, y):
    """
    最小二乘的残差函数。

    返回:残差数组(模型 - 数据)
    """
    a, b, c = params
    model = a * np.exp(-b * x) + c
    return model - y

# 数据
x_data = np.linspace(0, 10, 50)
y_data = 2.5 * np.exp(-0.3 * x_data) + 0.5 + 0.1*np.random.randn(50)

# 初始猜测
p0 = [2, 0.5, 0]

# 带边界优化
result = least_squares(
    residuals,
    p0,
    args=(x_data, y_data),
    bounds=([0, 0, -np.inf], [10, 5, np.inf])  # 下界和上界
)

print(f"成功: {result.success}")
print(f"最优参数: {result.x}")
print(f"最终成本(残差平方和): {result.cost}")
print(f"最优性: {result.optimality}")  # 应该小

模式5:线性规划

from scipy.optimize import linprog
import numpy as np

"""
线性规划问题:

最大化:   3*x1 + 2*x2
约束: x1 + x2 <= 4
            2*x1 + x2 <= 5
            x1, x2 >= 0

注意:linprog最小化,所以对于最大化需取负目标函数
"""

# 目标系数(对于最大化取负)
c = [-3, -2]

# 不等式约束:A_ub @ x <= b_ub
A_ub = np.array([
    [1, 1],   # x1 + x2 <= 4
    [2, 1]    # 2*x1 + x2 <= 5
])
b_ub = np.array([4, 5])

# 边界:x1, x2 >= 0
bounds = [(0, None), (0, None)]

# 求解
result = linprog(
    c,
    A_ub=A_ub,
    b_ub=b_ub,
    bounds=bounds,
    method='highs'  # 默认,最有效
)

print(f"成功: {result.success}")
print(f"最优 x: {result.x}")
print(f"最优值(最小化): {result.fun}")
print(f"最优值(最大化): {-result.fun}")

模式6:全局优化

from scipy.optimize import differential_evolution
import numpy as np

def objective(x):
    """
    具有多个局部最小值的函数。

    示例:Rastrigin函数
    """
    A = 10
    return A*len(x) + sum(x**2 - A*np.cos(2*np.pi*x))

# 必须为每个变量指定边界
bounds = [(-5.12, 5.12), (-5.12, 5.12)]

# 全局优化
result = differential_evolution(
    objective,
    bounds,
    strategy='best1bin',
    maxiter=1000,
    popsize=15,
    tol=1e-7,
    atol=1e-9,
    workers=-1,  # 使用所有CPU核心
    polish=True,  # 最后局部细化
    seed=42  # 为可重复性
)

print(f"成功: {result.success}")
print(f"全局最小值 x: {result.x}")
print(f"全局最小值: {result.fun}")
print(f"函数评估次数: {result.nfev}")

# 对比,尝试从随机起点局部优化
from scipy.optimize import minimize
x0 = np.random.uniform(-5.12, 5.12, 2)
local_result = minimize(objective, x0, method='BFGS')
print(f"
从随机起点局部优化:")
print(f"局部最小值: {local_result.fun}")
print(f"(全局更好: {result.fun < local_result.fun})")

模式7:pyomo(大规模 / 混合整数)

import pyomo.environ as pyo

# 创建模型
model = pyo.ConcreteModel()

# 决策变量
model.x = pyo.Var(domain=pyo.NonNegativeReals)
model.y = pyo.Var(domain=pyo.Integers, bounds=(0, 10))
model.z = pyo.Var([1, 2, 3], domain=pyo.Binary)  # 索引二进制变量

# 参数(可选)
model.a = pyo.Param(initialize=2.5)
model.b = pyo.Param([1, 2, 3], initialize={1: 1.0, 2: 2.0, 3: 3.0})

# 目标函数
model.obj = pyo.Objective(
    expr=model.x**2 + model.y + sum(model.z[i] for i in [1,2,3]),
    sense=pyo.minimize  # 或 pyo.maximize
)

# 约束
model.con1 = pyo.Constraint(expr=model.x + model.y >= 5)
model.con2 = pyo.Constraint(expr=2*model.x - model.y <= 10)
model.con3 = pyo.Constraint(expr=sum(model.z[i] for i in [1,2,3]) <= 2)

# 求解
# 对于连续:'ipopt'(非线性)或'glpk'(线性)
# 对于整数:'cbc', 'glpk', 'gurobi'(商业)
solver = pyo.SolverFactory('ipopt')
results = solver.solve(model, tee=True)  # tee=True显示求解器输出

# 检查是否最优
if results.solver.termination_condition == pyo.TerminationCondition.optimal:
    print("
找到最优解!")
    print(f"x = {pyo.value(model.x):.4f}")
    print(f"y = {pyo.value(model.y):.4f}")
    print(f"z = {[pyo.value(model.z[i]) for i in [1,2,3]]}")
    print(f"目标值 = {pyo.value(model.obj):.4f}")
else:
    print(f"求解器状态: {results.solver.termination_condition}")

模式8:cvxpy(凸优化)

import cvxpy as cp
import numpy as np

"""
投资组合优化示例:
在最小预期回报约束下最小化方差
"""

# 问题数据
n = 4  # 资产数量
mu = np.array([0.12, 0.10, 0.07, 0.03])  # 预期回报
Sigma = np.array([  # 协方差矩阵
    [0.10, 0.03, 0.01, 0.00],
    [0.03, 0.08, 0.02, 0.01],
    [0.01, 0.02, 0.05, 0.01],
    [0.00, 0.01, 0.01, 0.02]
])

# 变量
w = cp.Variable(n)  # 投资组合权重

# 目标:最小化方差
objective = cp.Minimize(cp.quad_form(w, Sigma))

# 约束
constraints = [
    cp.sum(w) == 1,           # 权重和为1
    w >= 0,                   # 无卖空
    mu @ w >= 0.10            # 最小预期回报
]

# 求解
problem = cp.Problem(objective, constraints)
problem.solve()

# 结果
print(f"状态: {problem.status}")
if problem.status == 'optimal':
    print(f"最优投资组合权重: {w.value}")
    print(f"投资组合方差: {problem.value:.6f}")
    print(f"投资组合标准差: {np.sqrt(problem.value):.4f}")
    print(f"预期回报: {(mu @ w.value):.4f}")
else:
    print(f"问题无法求解: {problem.status}")

最佳实践

1. 总是提供解析梯度

原因: 10-100倍更快收敛,更可靠

def objective(x):
    return x[0]**2 + x[1]**2

def gradient(x):
    """解析梯度 - 比有限差分好得多"""
    return np.array([2*x[0], 2*x[1]])

# 好:使用解析梯度
result = minimize(objective, x0, method='BFGS', jac=gradient)

# 可以但较慢:使用有限差分
result = minimize(objective, x0, method='BFGS')

2. 验证梯度

from scipy.optimize import check_grad

# 检查梯度准确性
error = check_grad(objective, gradient, x0)
print(f"梯度误差: {error}")  # 应 < 1e-5

# 对于约束
for con in constraints:
    if 'jac' in con:
        error = check_grad(con['fun'], con['jac'], x0)
        print(f"约束梯度误差: {error}")

3. 缩放变量

问题: 变量量级差异很大

# 坏:x1 ~ 1e-6, x2 ~ 1e6
x = [1e-6, 1e6]

解决方案: 归一化到相似尺度

# 好:两个变量 ~ O(1)
x_scaled = [x[0] * 1e6, x[1] / 1e6]

def objective_scaled(x_scaled):
    x = [x_scaled[0] / 1e6, x_scaled[1] * 1e6]  # 转换回
    return original_objective(x)

4. 提供良好的初始猜测

# 坏:随机或任意起点
x0 = np.zeros(n)

# 好:物理合理或可行起点
x0 = np.array([1.0, 2.0, 0.5])  # 基于问题知识

# 更好:对于非凸问题尝试多个起点
initial_guesses = [
    np.array([1.0, 2.0]),
    np.array([-1.0, -2.0]),
    np.random.randn(2)
]

results = [minimize(objective, x0) for x0 in initial_guesses]
best_result = min(results, key=lambda r: r.fun)

5. 验证解决方案

def validate_solution(result, constraints, bounds):
    """综合解决方案验证"""

    # 检查优化成功
    assert result.success, f"优化失败: {result.message}"

    # 检查不等式约束:g(x) >= 0
    for i, con in enumerate([c for c in constraints if c['type'] == 'ineq']):
        val = con['fun'](result.x)
        assert val >= -1e-6, f"不等式约束 {i} 违反: {val:.2e}"

    # 检查等式约束:h(x) = 0
    for i, con in enumerate([c for c in constraints if c['type'] == 'eq']):
        val = con['fun'](result.x)
        assert abs(val) < 1e-6, f"等式约束 {i} 违反: {val:.2e}"

    # 检查边界
    if bounds is not None:
        for i, (lb, ub) in enumerate(bounds):
            if lb is not None:
                assert result.x[i] >= lb - 1e-6, f"下界 {i} 违反"
            if ub is not None:
                assert result.x[i] <= ub + 1e-6, f"上界 {i} 违反"

    print("✓ 所有约束满足")
    return True

# 使用它
validate_solution(result, constraints, bounds)

6. 处理收敛问题

常见问题和解决方案:

# 问题:"未达到预期误差"
# 解决方案1:放宽容差
result = minimize(
    objective, x0,
    method='BFGS',
    options={'ftol': 1e-6, 'gtol': 1e-5}  # 较宽松
)

# 解决方案2:缩放变量
x_scaled = x / typical_scale
result = minimize(objective_scaled, x_scaled)

# 解决方案3:尝试不同方法
result = minimize(objective, x0, method='trust-constr')

# 解决方案4:更好的初始猜测
x0 = feasible_starting_point()

# 问题:陷入局部最小值
# 解决方案:全局优化
result = differential_evolution(objective, bounds)

# 问题:约束不兼容
# 解决方案:检查约束可行性
from scipy.optimize import fsolve
# 尝试找到任何可行点
def feasibility(x):
    violations = []
    for con in constraints:
        if con['type'] == 'eq':
            violations.append(con['fun'](x))
    return violations

x_feasible = fsolve(feasibility, x0)

常见问题类型 - 快速参考

1. 无约束:最小化 f(x)

minimize(f, x0, method='BFGS', jac=grad)

2. 箱约束:最小化 f(x) 约束 lb ≤ x ≤ ub

minimize(f, x0, method='L-BFGS-B', bounds=bounds)

3. 一般约束:最小化 f(x) 约束 g(x) ≥ 0, h(x) = 0

cons = [{'type': 'ineq', 'fun': g}, {'type': 'eq', 'fun': h}]
minimize(f, x0, method='SLSQP', constraints=cons)

4. 最小二乘:最小化 ||r(x)||²

least_squares(residual, x0, bounds=(lb, ub))

5. 曲线拟合:将模型拟合到数据

params, cov = curve_fit(model, xdata, ydata, p0=initial)

6. 线性规划:最小化 c’x 约束 Ax ≤ b

linprog(c, A_ub=A, b_ub=b, bounds=bounds)

7. 混合整数:某些变量必须是整数

# 使用 pyomo
model.x = pyo.Var(domain=pyo.Integers)
solver = pyo.SolverFactory('cbc')
solver.solve(model)

8. 全局:多个局部最小值

differential_evolution(f, bounds)

9. 投资组合优化

# cvxpy
w = cp.Variable(n)
objective = cp.Minimize(cp.quad_form(w, Sigma))
constraints = [cp.sum(w) == 1, w >= 0, mu @ w >= target_return]
problem = cp.Problem(objective, constraints)
problem.solve()

10. 带不确定性的参数估计

params, cov = curve_fit(model, xdata, ydata)
uncertainties = np.sqrt(np.diag(cov))

响应格式

当解决优化问题时,总是:

1. 重述问题

"根据您的描述,这是一个 [问题类型] 问题:

目标: 最小化/最大化 f(x) = … 变量: x ∈ R^n(或对于整数,x ∈ Z^n) 约束:

  • [列出不等式约束]
  • [列出等式约束]
  • [列出边界]"

2. 解释库/方法选择

"由于此问题具有 [特征],我推荐 [库][方法]

  • [原因1]
  • [原因2]
  • [如果这不奏效,替代方案]"

3. 提供完整实现

# 完整、可运行代码,带注释
# 包含导入、数据、函数、优化、验证

4. 显示和解释结果

"结果:

  • 最优 x:[值]
  • 最优值:[值]
  • 约束满足:✓ / ✗
  • 收敛:[迭代次数,函数评估次数]

解释: [解决方案在上下文中的含义]"

5. 如果需要,建议改进

"如果出现收敛问题:

  • 尝试 [替代方法]
  • 调整 [参数]
  • 考虑 [问题重构]"

高级主题

多目标优化

对于具有 多个冲突目标 的问题(最小化成本 AND 最大化性能),使用专用的 python-multiobjective-optimization 技能,涵盖:

  • Pareto最优性和Pareto前沿
  • 进化算法(NSGA-II, NSGA-III, MOEA/D)
  • 标量化方法(加权和,ε-约束)
  • 库:pymoo, platypus, DEAP
  • Pareto分析和决策制定
  • 可视化技术

快速示例 - 使用scipy的加权和标量化:

from scipy.optimize import minimize

def scalarize_objectives(x, weights):
    """多目标的加权和方法"""
    f1 = objective1(x)
    f2 = objective2(x)
    return weights[0] * f1 + weights[1] * f2

# 求解不同权重组合以追踪Pareto前沿
weights_list = [(1, 0), (0.75, 0.25), (0.5, 0.5), (0.25, 0.75), (0, 1)]
pareto_front = []

for weights in weights_list:
    result = minimize(
        lambda x: scalarize_objectives(x, weights),
        x0,
        method='SLSQP',
        constraints=constraints
    )
    if result.success:
        pareto_front.append({
            'x': result.x,
            'f1': objective1(result.x),
            'f2': objective2(result.x)
        })

注意: 加权和仅找到Pareto前沿的凸部分。对于全面多目标优化,见python-multiobjective-optimization技能。

鲁棒优化

def worst_case_objective(x, uncertainty_scenarios):
    """最小化最坏情况性能"""
    return max(objective(x, scenario) for scenario in uncertainty_scenarios)

result = minimize(worst_case_objective, x0, args=(scenarios,))

随机优化

def expected_objective(x, n_samples=1000):
    """最小化随机参数上的期望值"""
    samples = np.random.normal(mu, sigma, (n_samples, n_params))
    return np.mean([objective(x, sample) for sample in samples])

result = minimize(expected_objective, x0)

故障排除指南

问题 症状 解决方案
收敛慢 许多迭代,进展慢 提供解析梯度,缩放变量,更好的x0
局部最小值 不同x0给出不同解 使用differential_evolution,尝试多个起点
约束违反 解不满足约束 检查约束公式,确保可行x0,收紧容差
“未达到预期误差” 结果中警告 放宽容差,缩放变量,尝试不同方法
数值误差 NaN或Inf值 缩放变量,避免目标中的极端值
内存错误 大问题崩溃 使用稀疏矩阵,L-BFGS-B,或带稀疏求解器的pyomo

安装

# 核心优化
pip install scipy

# 对于大规模和混合整数
pip install pyomo

# 为pyomo安装求解器
conda install -c conda-forge ipopt  # 非线性
conda install -c conda-forge glpk   # 线性/整数
pip install cplex  # 商业,需要许可证

# 对于凸优化
pip install cvxpy

# 对于动态优化
pip install gekko

额外资源

相关技能

  • python-multiobjective-optimization - 带Pareto前沿的多目标优化(NSGA-II, NSGA-III, pymoo)
  • pycse - 带置信区间的回归分析,常微分方程求解
  • python-best-practices - 优化代码的代码质量和测试
  • python-ase - 材料科学中的原子结构优化