You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用SciPy函数实现Goal Seek求解线性方程未知变量?

如何用SciPy替代循环遍历实现线性方程的单变量求解?

当然可以用SciPy来解决这个问题,而且效率会比你现在的循环遍历高很多!既然你的方程是线性的,SciPy的优化模块里有专门的单变量求解工具,完全能替代手动循环,还能保证结果的精度。

核心思路

你现在的需求是找到xp_bot使得abs(equN - N) < 1,本质上是求解线性方程equN - N = 0的根(因为方程是线性的,这个根就是唯一解)。SciPy的scipy.optimize.root_scalar函数专门处理单变量方程求根,比手动遍历效率高得多。

具体步骤

  1. 调整目标函数
    你的ULS函数当前返回的是差值的绝对值,我们可以直接返回equN - N,这样求解器能更精准地找到等于0的点,后续再验证是否满足精度要求即可:

    def ULS(xp_bot):
        xp_top = 0.00014
        xp_all = []
        slope = (xp_bot - xp_top) / (Ln)
        for i in range(0, 100, 1):
            xp_calc = i * slope + xp_top
            xp_all.append(xp_calc)
        xp_all.append(xp_bot)
        xmi_all = []
        for i in range(0, 100, 1):
            xmi_calc = (xp_all[i] + xp_all[i+1]) / 2
            xmi_all.append(xmi_calc)
        xi_all = []
        for i in range(0, 100, 1):
            xi_calc = xmi_all[i] + xni_all[i]
            xi_all.append(xi_calc)
        sic_all = []
        for item in xi_all:
            if item >= 0:
                sic = item * Ecm
                sic_all.append(sic)
            else:
                sic = 0
                sic_all.append(sic)
        fic_step = np.multiply(sic_all, a)
        fic = np.divide(fic_step, 1000)
        sis_all = []
        for item in xi_all:
            sis = item * Es
            sis_all.append(sis)
        fis_step = np.multiply(sis_all, a_s)
        fis = np.divide(fis_step, 1000)
        M_conc = []
        for i in range(0, 100):
            multi_c = np.divide(fic, 1000)
            M_conc = np.multiply(leverarm, multi_c)
            multi_s = np.divide(fis, 1000)
            M_steel = np.multiply(leverarm, multi_s)
            M_sls = sum(M_conc) + sum(M_steel)
        equN = sum(fic) + sum(fis)
        return equN - N  # 改为返回差值,去掉绝对值
    
  2. 使用SciPy求解
    导入root_scalar函数,定义好所有依赖变量(比如Lnxni_allEcm等),然后设置xp_bot的搜索范围并求解:

    import numpy as np
    from scipy.optimize import root_scalar
    
    # 先确保所有依赖变量已正确赋值(示例,根据你的实际情况修改)
    Ln = 1.0
    xni_all = np.random.rand(100)  # 替换为你的实际数组
    Ecm = 30000
    a = np.array([...])  # 长度为100的数组
    Es = 200000
    a_s = np.array([...])  # 长度为100的数组
    leverarm = np.array([...])  # 长度为100的数组
    N = 1000  # 你的目标N值
    
    # 设置xp_bot的合理搜索范围(根据你的实际场景调整)
    result = root_scalar(ULS, bracket=[0, 0.001], method='bisect')
    
    # 验证结果
    if result.converged:
        xp_bot_solution = result.root
        if abs(ULS(xp_bot_solution)) < 1:
            print(f"找到的xp_bot解为:{xp_bot_solution:.6f}")
        else:
            print("解不满足精度要求,请检查搜索范围或参数")
    else:
        print("求解失败,请确认函数逻辑或调整搜索区间")
    

额外提示

  • 因为你的方程是线性的,root_scalar会瞬间收敛,比手动循环高效无数倍,尤其是需要多次求解的场景。
  • 如果不确定xp_bot的范围,可以先通过少量循环大致确定一个合理区间,再传给bracket参数。
  • 除了二分法,也可以使用method='newton'(牛顿法),但需要提供函数的导数(线性函数的导数是常数,如果你能计算出来,求解速度会更快)。

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

火山引擎 最新活动