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

使用scipy.optimize.minimize()遇ValueError:目标函数需返回标量值

解决scipy.optimize.minimize()的ValueError问题

错误原因

scipy.optimize.minimize()是用于最小化标量目标函数的工具,要求传入的目标函数必须返回单个数值(标量)。但你的equations函数返回的是一个三元组(三个物料平衡方程的残差),属于向量类型,这直接触发了ValueError: The user-provided objective function must return a scalar value.错误。

你实际要解决的是非线性方程组求解问题,应该使用SciPy中专门的方程组求解函数,比如scipy.optimize.root()或scipy.optimize.least_squares()。

修改后的代码

import numpy as np
from scipy.optimize import root  # 替换minimize为root

# 先定义所有平衡常数(示例值,根据实际情况替换)
k1, k2, k3, k4, k5 = 1e-10, 1e-5, 1e-4, 1e-3, 1e2
k6, k7, k8, k9, k10 = 1e3, 1e4, 1e-9, 1e10, 1e15

PH = np.linspace(0, 14, 71)
ni_total = 0.1
citrate_total = 0.9
ammonia_total = 0.3

def concs(citrate_total, ni_total, ammonia_total, PH):
    h = 10 ** (-PH)
    def equations(p):
        cit3, nio2, nh4 = p
        Hcit = h * cit3 * k4
        H2cit = h * Hcit * k3
        H3cit = h * H2cit * k2
        ni2pfree = (nio2 * k1 * (h ** 2)) / (1 + ((nio2 * k1 * (h ** 2)) / ni_total))
        NiH2cit = k7 * ni2pfree * H2cit
        NiHcit = k6 * ni2pfree * Hcit
        Nicit = k5 * ni2pfree * cit3
        nh3 = k8 * nh4 / h
        nin4p2 = k9 * (nh4 ** 4) / (h ** 2)
        nin6p2 = k10 * (nh4 ** 6) / (h ** 4)
        # 返回残差向量,root会寻找使所有残差趋近于0的解
        return (
            citrate_total - Hcit - H2cit - H3cit - Nicit - NiHcit - NiH2cit - cit3,
            ni_total - Nicit - NiHcit - NiH2cit - ni2pfree - nin4p2 - nin6p2 - nio2,
            ammonia_total - nh3 - 4 * nin4p2 - 6 * nin6p2 - nh4
        )
    initial_guess = [0.1, 0.1, 0.1]
    # 使用root求解方程组
    res = root(equations, initial_guess)
    # 检查求解是否成功
    if not res.success:
        raise RuntimeError(f"求解失败: {res.message}")
    cit3 = res.x[0]
    nio2 = res.x[1]
    nh4 = res.x[2]
    # 重新计算各物种浓度
    ni2pfree = (nio2 * k1 * (h ** 2)) / (1 + ((nio2 * k1 * (h ** 2)) / ni_total))
    Hcit = h * cit3 * k4
    H2cit = h * Hcit * k3
    H3cit = h * H2cit * k2
    NiH2cit = k7 * ni2pfree * H2cit
    NiHcit = k6 * ni2pfree * Hcit
    Nicit = k5 * ni2pfree * cit3
    nh3 = k8 * nh4 / h
    nin4p2 = k9 * (nh4 ** 4) / (h ** 2)
    nin6p2 = k10 * (nh4 ** 6) / (h ** 4)
    return [cit3, nio2, nh4, ni2pfree, Hcit, H2cit, H3cit, NiH2cit, NiHcit, Nicit, nh3, nin4p2, nin6p2]

# 遍历PH数组计算每个pH下的浓度
all_concs = [concs(citrate_total, ni_total, ammonia_total, ph) for ph in PH]

关键注意事项

  • 平衡常数定义:代码中添加了示例平衡常数k1至k10,请根据实际热力学数据替换为准确值,否则求解结果无意义。
  • 求解成功检查:添加了res.success判断,避免使用未成功求解的结果。
  • 批量处理PH:原代码中PH是数组,需要通过循环逐个传入concs函数计算。
  • 替代方案:如果需要最小化残差的平方和,可改用scipy.optimize.least_squares(),用法与root类似,同样接受返回向量的目标函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:25:01