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}")
你之前遇到的问题解析
ValueError: Objective function must return a scalar:
你之前的目标函数定义了x和y两个参数,但scipy.minimize只会传入优化变量x,导致传参错误。现在我们把国家参数提前预处理,目标函数只接受x,解决了这个问题。分配值非常接近、总和超过100:
- 你之前用的是不等式约束
x[0]+x[1]+x[2]-100 >=0,这会允许总和大于100,改成等式约束后强制总和等于100。 - 初始值设置不合理也可能导致优化器收敛到局部最优,用平均分配的初始值能让优化器找到更合理的分配方案。
- 你之前用的是不等式约束
内容的提问来源于stack exchange,提问作者quant
相关产品推荐
相关产品推荐

