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

如何让Scipy Optimize适配仅含可选参数的函数?

通用求解Scipy fsolve任意位置未知参数的方法

问题背景

给定如下函数,用于已知两个参数时求解第三个参数,使函数返回值为0:

def func(a=None, b=None, c=None):    
    return 100-(a+b*c)

使用Scipy的fsolve求解首位未知参数a时(已知b和c)可正常运行:

from scipy import optimize
dat = {"b":1, "c":2}
optimize.fsolve(lambda x: func(x, **dat), x0=0)
# 输出:array([98.])

但求解非首位参数(如c,已知a和b)时会触发TypeError: func() got multiple values for argument 'a':

dat = {"a":1, "b":2}
optimize.fsolve(lambda x: func(x, **dat), x0=0)

需要一种通用方法,无需为每个未知参数编写单独函数,即可用fsolve求解任意位置的未知参数。


解决方案

方法1:动态构造参数映射包装函数

核心逻辑是先定位未知参数(即未在已知参数字典中出现的函数参数),再将fsolve传入的求解值赋值给该参数,最后调用原函数。

from scipy import optimize
import numpy as np

def func(a=None, b=None, c=None):    
    return 100-(a+b*c)

def solve_for_param(target_func, known_params, x0=0):
    # 获取原函数的所有参数名称
    param_names = target_func.__code__.co_varnames[:target_func.__code__.co_argcount]
    # 筛选出未知参数(仅支持单参数求解场景)
    unknown_param = next(p for p in param_names if p not in known_params)
    
    def wrapper(x):
        # 将求解值赋值给未知参数,合并到参数字典
        params = known_params.copy()
        # 兼容fsolve传入的数组类型输入
        params[unknown_param] = x[0] if isinstance(x, (list, tuple, np.ndarray)) else x
        return target_func(**params)
    
    return optimize.fsolve(wrapper, x0=x0)

使用示例

  • 求解a(已知b=1, c=2):
solve_for_param(func, {"b":1, "c":2})
# 输出:array([98.])
  • 求解c(已知a=1, b=2):
solve_for_param(func, {"a":1, "b":2})
# 输出:array([49.5])
  • 求解b(已知a=10, c=5):
solve_for_param(func, {"a":10, "c":5})
# 输出:array([18.])

方法2:用inspect模块兼容复杂参数场景

如果函数存在默认值、可变参数等更复杂的参数结构,使用inspect模块获取参数签名会更严谨:

import inspect
from scipy import optimize
import numpy as np

def func(a=None, b=None, c=None):    
    return 100-(a+b*c)

def solve_for_param(target_func, known_params, x0=0):
    # 获取函数的完整参数签名
    sig = inspect.signature(target_func)
    param_names = list(sig.parameters.keys())
    unknown_param = next(p for p in param_names if p not in known_params)
    
    def wrapper(x):
        params = known_params.copy()
        # 处理numpy数组类型的输入
        params[unknown_param] = x.item() if hasattr(x, 'item') else x
        return target_func(**params)
    
    return optimize.fsolve(wrapper, x0=x0)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:48:25