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

Python非线性函数优化:100 GP分配及SLSQP求解问题处理

解决GP分配的优化问题

看起来你在构建这个GP分配的优化问题时遇到了几个关键问题,我帮你梳理并修正一下:

首先,先明确核心需求:将100个GP分配给三个国家,每个国家的GP值必须为正,最大化三个国家的fun函数总和。下面是完整的解决方案:

1. 保留原始函数与数据

先把你提供的基础函数和数据保留下来:

import numpy as np
import pandas as pd
from scipy.optimize import minimize

def fun(Gp, Ra, Mr, Pot, Sp, Mc, Keep):
    if Keep == True:
        return Pot * np.tanh((Gp + Ra + Mr + Mc) * Sp)

dt_org = pd.DataFrame({
    "RA": [0.5, 0.8, 0.9], 
    "MR": [0.97, 0.95, 0.99], 
    "POT": [0.25, 0.12, 0.05], 
    "SP": [0.25, 0.12, 0.15], 
    "MC": [50, 75, 100], 
    "COUNTRY": ["GB", "IR", "GR"]
})

2. 预处理国家参数

先把每个国家的参数提取出来,避免在目标函数里重复取数,同时保证Keep参数的一致性(这里假设所有国家的Keep都是True,如果有不同可以单独调整):

# 提取每个国家的参数列表
country_params = []
for _, row in dt_org.iterrows():
    params = {
        "Ra": row["RA"],
        "Mr": row["MR"],
        "Pot": row["POT"],
        "Sp": row["SP"],
        "Mc": row["MC"],
        "Keep": True
    }
    country_params.append(params)

3. 定义正确的目标函数

scipy.optimize.minimize要求目标函数只能接受优化变量x作为唯一参数,所以我们把国家参数提前预处理,目标函数计算三个fun的总和的负数(因为我们要最大化总和,转为最小化负数即可):

def objective(x):
    # x是长度为3的数组,对应三个国家的GP分配值
    total_value = 0
    for i in range(3):
        total_value += fun(x[i], **country_params[i])
    # 返回负的总和,将最大化问题转为最小化问题
    return -total_value

4. 设置约束与边界

  • 约束:必须保证三个GP的总和等于100,所以用等式约束(你之前用的不等式约束会允许总和超过100,这是错误的)
  • 边界:每个GP必须为正,这里用1e-6代替0,避免优化器遇到数值边界问题:
# 等式约束:三个GP的总和等于100
constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 100})

# 边界:每个GP必须大于极小正数(避免等于0)
bounds = ((1e-6, None), (1e-6, None), (1e-6, None))

5. 设置初始值并运行优化

给优化器一个合理的初始值(比如平均分配100个GP),选择支持等式约束的SLSQP方法:

# 初始值:平均分配100个GP
initial_guess = np.array([100/3, 100/3, 100/3])

# 运行优化
result = minimize(objective, initial_guess, method='SLSQP', bounds=bounds, constraints=constraints)

6. 查看优化结果

print("优化完成!")
print(f"GP分配结果:")
print(f"GB: {result.x[0]:.2f}, IR: {result.x[1]:.2f}, GR: {result.x[2]:.2f}")
print(f"分配总和:{np.sum(result.x):.2f}")
print(f"最大化的目标函数值:{-result.fun:.4f}")

你之前遇到的问题解析

  1. ValueError: Objective function must return a scalar:
    你之前的目标函数定义了x和y两个参数,但scipy.minimize只会传入优化变量x,导致传参错误。现在我们把国家参数提前预处理,目标函数只接受x,解决了这个问题。

  2. 分配值非常接近、总和超过100:

    • 你之前用的是不等式约束x[0]+x[1]+x[2]-100 >=0,这会允许总和大于100,改成等式约束后强制总和等于100。
    • 初始值设置不合理也可能导致优化器收敛到局部最优,用平均分配的初始值能让优化器找到更合理的分配方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:36:45