【问题标题】:Function Returning Different Results with Same Inputs使用相同输入返回不同结果的函数
【发布时间】:2022-01-16 16:17:15
【问题描述】:

我正在开发一个建模函数来模拟火车的运动。在我的脚本中,我有一个运行函数三次的检查。第二次和第三次返回相同的值,但第一次返回不同的值。

    dvdtA = lambda x, v: (1 / (Tmass + mw)) * (Ap * (rg / rw)) * (((P0gauge + Patm) * V0) / (V0 + (Ap * (rg / rw) * x)) - Patm) \
        -0.5 * Cd * pa * A * (v**2) - (Cr * Tmass * g)

    dvdtD = lambda v: (1 / Tmass) * (- 0.5 * Cd * pa * A * (v**2) - (Cr * Tmass * g))
    dxdt = lambda v: v
    Ft = lambda x: (1 / (Tmass + mw)) * (Ap * (rg / rw)) * (((P0gauge + Patm) * V0) / (V0 + (Ap * (rg / rw) * x)) - Patm)
    trainMotion = np.array([dvdtA, dvdtD, dxdt, Ft])

    # Checking design constraints ######################################
    if (Ht < 0.23) and (Wt < 0.2) and (rg/rw < 1):

        # Optimization #################################################
        if RK4(trainMotion, h, tspan, v0, x0, La, slipCheck) is not None:
            if RK4(trainMotion, h, tspan, v0, x0, La, slipCheck)[1] < tFinish:
                bestParams = np.array([r0, P0gauge, rg, Ls, rp, tankMat])
                bestODE = trainMotion
                bestLa = La
                bestSlipCheck = slipCheck
                bestTime = RK4(trainMotion, h, tspan, v0, x0, La, slipCheck)[1]

这是在 for 循环中编写的,该循环随机选择一组参数,然后运行它们以生成您在开始时看到的 ODES。错误发生在“优化”区域下方。 RK4 上的第一次调用生成的结果集与第二次和第三次不同,它们都生成完全相同的结果。我不明白为什么第一次与第二次和第三次不同。 此外,当我稍后在脚本中再次将那些“最佳[ODE/LA/etc] 插入 RK4 函数时,尽管这些参数之前已通过检查,但检查失败并返回 None。

作为参考,这里是 RK4 函数本身:

import math as mt
import numpy as np

def RungeKutta(fun, h, tspan, x0, y0, Ls, slipCheck):
    yArr = np.zeros([len(tspan), 2])
    yArr[0,1] = y0
    yArr[0,0] = x0
    
    for i in range(len(tspan) - 1):
        
        k1 = fun[2](yArr[i, 1])
        k2 = fun[2](yArr[i, 1] + k1 * (h/2))
        k3 = fun[2](yArr[i, 1] + k2 * (h/2))
        k4 = fun[2](yArr[i, 1] + k3 * h)

        yArr[i+1, 0] = yArr[i, 0] + h * (k1/6 + k2/3 + k3/3 + k4/6)
        
        if (fun[3](yArr[i+1, 0]) > slipCheck) or (yArr[i+1, 0] > 12.5):
            return None

        if yArr[i, 0] <= Ls:
            k1 = fun[0](yArr[i, 0], yArr[i, 1])
            k2 = fun[0](yArr[i, 0] + h/2, yArr[i, 1] + k1 * (h/2))
            k3 = fun[0](yArr[i, 0] + h/2, yArr[i, 1] + k2 * (h/2))
            k4 = fun[0](yArr[i, 0] + h, yArr[i, 1] + k3 * h)

            yArr[i+1, 1] = yArr[i, 1] + h * (k1/6 + k2/3 + k3/3 + k4/6)

        elif yArr[i, 0] > Ls:
            k1 = fun[1](yArr[i, 1])
            k2 = fun[1](yArr[i, 1] + k1 * (h/2))
            k3 = fun[1](yArr[i, 1] + k2 * (h/2))
            k4 = fun[1](yArr[i, 1] + k3 * h)
                   
            yArr[i+1, 1] = yArr[i, 1] + h * (k1/6 + k2/3 + k3/3 + k4/6)

        if i >= 3:
            if yArr[i+1, 1] < 0 and yArr[i+1, 0] > 10:
                tFinish = tspan[i]
                data = np.column_stack((yArr, tspan))
                return data, tFinish       

    return None

【问题讨论】:

  • 为什么要计算3次(不是真的最优),计算一次并使用3次结果,为什么不返回(None.None),RK4总是返回2项,否则return np.column_stack((yArr, tspan)), tspan[i]
  • 不是所有的除法/,而是将其转换为*,这样更快,至少在C++中,也许python语句的执行速度比/
  • 你有没有为每次运行转储yArr 的中间结果并比较它们的不同之处,然后找出原因
  • 我是否正确理解您在每次迭代中重新创建 lambda 语句?这种东西很难调试。我会推荐 def 在循环之前使用相应参数的函数,以避免通过优化意外更改变量,这可能是可变数据结构的情况。
  • 在 for 循环的每次迭代中都会重新创建 lambda 语句,但是这里调用了 3 次函数,它使用 lambda 函数而不重写它们。 @JonathanWeine

标签: python visual-studio-code


【解决方案1】:

让RK4总是返回2个值,调用RK4时解包

    dvdtA = lambda x, v: (1 / (Tmass + mw)) * (Ap * (rg / rw)) * (((P0gauge + Patm) * V0) / (V0 + (Ap * (rg / rw) * x)) - Patm) \
        -0.5 * Cd * pa * A * (v**2) - (Cr * Tmass * g)

    dvdtD = lambda v: (1 / Tmass) * (- 0.5 * Cd * pa * A * (v**2) - (Cr * Tmass * g))
    dxdt = lambda v: v
    Ft = lambda x: (1 / (Tmass + mw)) * (Ap * (rg / rw)) * (((P0gauge + Patm) * V0) / (V0 + (Ap * (rg / rw) * x)) - Patm)
    trainMotion = np.array([dvdtA, dvdtD, dxdt, Ft])

    # Checking design constraints ######################################
    if (Ht < 0.23) and (Wt < 0.2) and (rg/rw < 1):

        # Optimization #################################################
        data, tFinishResult = RK4(trainMotion, h, tspan, v0, x0, La, slipCheck)
        if data is not None:
            if tFinishResult < tFinish:
                bestParams = np.array([r0, P0gauge, rg, Ls, rp, tankMat])
                bestODE = trainMotion
                bestLa = La
                bestSlipCheck = slipCheck
                bestTime = tFinishResult

RK4 功能:

import math as mt
import numpy as np

def RungeKutta(fun, h, tspan, x0, y0, Ls, slipCheck):
    yArr = np.zeros([len(tspan), 2])
    yArr[0,1] = y0
    yArr[0,0] = x0
    
    for i in range(len(tspan) - 1):
        
        k1 = fun[2](yArr[i, 1])
        k2 = fun[2](yArr[i, 1] + k1 * (h/2))
        k3 = fun[2](yArr[i, 1] + k2 * (h/2))
        k4 = fun[2](yArr[i, 1] + k3 * h)

        yArr[i+1, 0] = yArr[i, 0] + h * (k1/6 + k2/3 + k3/3 + k4/6)
        
        if (fun[3](yArr[i+1, 0]) > slipCheck) or (yArr[i+1, 0] > 12.5):
            return None,None

        if yArr[i, 0] <= Ls:
            k1 = fun[0](yArr[i, 0], yArr[i, 1])
            k2 = fun[0](yArr[i, 0] + h/2, yArr[i, 1] + k1 * (h/2))
            k3 = fun[0](yArr[i, 0] + h/2, yArr[i, 1] + k2 * (h/2))
            k4 = fun[0](yArr[i, 0] + h, yArr[i, 1] + k3 * h)

            yArr[i+1, 1] = yArr[i, 1] + h * (k1/6 + k2/3 + k3/3 + k4/6)

        elif yArr[i, 0] > Ls:
            k1 = fun[1](yArr[i, 1])
            k2 = fun[1](yArr[i, 1] + k1 * (h/2))
            k3 = fun[1](yArr[i, 1] + k2 * (h/2))
            k4 = fun[1](yArr[i, 1] + k3 * h)
                   
            yArr[i+1, 1] = yArr[i, 1] + h * (k1/6 + k2/3 + k3/3 + k4/6)

        if i >= 3:
            if yArr[i+1, 1] < 0 and yArr[i+1, 0] > 10:
                data = np.column_stack((yArr, tspan))
                tFinish = tspan[i]
                return data, tFinish       

    return None, None

【讨论】:

    猜你喜欢
    • 2012-03-23
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    相关资源
    最近更新 更多