计算不确定性的函数
Function that calculates uncertainty
您可能知道也可能不知道,由某个函数 定义的变量的不确定性公式由下式给出:
.
我想创建一个 python 函数来为我执行此操作。这是我目前拥有的:
import sympy as sp
from sympy import lambdify, symbols,diff
L,g = symbols('L g', real=True)
value_of_var = [5.4,9.8] # Arbitrary values for L and g
uncertainty_in_var = [0.3, 0.1]
function = 2*sp.pi*sp.sqrt(L/g) #Period of pendulum (purely for test purposes)
variables = [L,g]
def uncertainty_calculator(function):
partials = [diff(function,x) for x in variables] #Takes partial derivatives of variables
partial_times_uncertainty = [(x*y)**2 for x,y in zip(uncertainty_in_var,partials)] #Squares the product of the uncertainty and its respective partial
uncertainty = lambdify(variables, sp.sqrt(sum(partial_times_uncertainty)))
number = uncertainty(value_of_var[0],value_of_var[1])
return number
uncertainty = uncertainty_calculator(function)
print(uncertainty)
我很确定这对于这个特定函数来说工作正常,但是,我想更概括它,我希望它接受一个值列表、这些值的不确定性和一个函数,然后给出我的不确定性。我遇到的问题是,如果我的变量已经有一个值,那么函数将被评估为一个数字,因此我在尝试计算偏导数时只得到零,这由 symbols('L g', real=True)
行修复这使得函数在到达 lamdify 部分之前不会被评估。有谁知道如何做到这一点,拥有这样的功能对我的实验室真的很有帮助,因为手动计算该功能真的很痛苦。
看来你是在暗示symbols('L g', real=True)
解决了问题,我不明白问题出在哪里。可能是因为我没有使用过这个库,但你能详细说明你的问题吗?
如果函数不是单变量的,那么您将始终必须指定函数,然后指定符号及其值。如果您以交互方式使用它,则可以通过将函数作为字符串传递并将值的顺序与变量的排序顺序相对应来减少输入。然后函数的 return 可以是替换字典(因此您可以检查)和计算的不确定性。
>>> def ucalc(f, x, u):
... f = S(f)
... syms = list(ordered(f.free_symbols))
... assert len(x) == len(u) == len(syms)
... reps = dict(zip(syms, x))
... ui = IndexedBase('u')
... args = []
... for i, xi in enumerate(syms):
... reps[ui[xi]] = u[i]
... args.append((ui[xi]*diff(f, xi))**2)
... return reps, sqrt(Add(*args)).n(subs=reps)
...
>>> ucalc('2*pi*sqrt(L/g)',(9.8,5.4),(.1,.3))
({L: 9.8, g: 5.4, u[L]: 0.1, u[g]: 0.3}, 0.239055276534314)
请注意,IndexedBase 符号用于为不确定性创建临时变量,因为这些变量不会出现在方程本身中。
您可能知道也可能不知道,由某个函数
我想创建一个 python 函数来为我执行此操作。这是我目前拥有的:
import sympy as sp
from sympy import lambdify, symbols,diff
L,g = symbols('L g', real=True)
value_of_var = [5.4,9.8] # Arbitrary values for L and g
uncertainty_in_var = [0.3, 0.1]
function = 2*sp.pi*sp.sqrt(L/g) #Period of pendulum (purely for test purposes)
variables = [L,g]
def uncertainty_calculator(function):
partials = [diff(function,x) for x in variables] #Takes partial derivatives of variables
partial_times_uncertainty = [(x*y)**2 for x,y in zip(uncertainty_in_var,partials)] #Squares the product of the uncertainty and its respective partial
uncertainty = lambdify(variables, sp.sqrt(sum(partial_times_uncertainty)))
number = uncertainty(value_of_var[0],value_of_var[1])
return number
uncertainty = uncertainty_calculator(function)
print(uncertainty)
我很确定这对于这个特定函数来说工作正常,但是,我想更概括它,我希望它接受一个值列表、这些值的不确定性和一个函数,然后给出我的不确定性。我遇到的问题是,如果我的变量已经有一个值,那么函数将被评估为一个数字,因此我在尝试计算偏导数时只得到零,这由 symbols('L g', real=True)
行修复这使得函数在到达 lamdify 部分之前不会被评估。有谁知道如何做到这一点,拥有这样的功能对我的实验室真的很有帮助,因为手动计算该功能真的很痛苦。
看来你是在暗示symbols('L g', real=True)
解决了问题,我不明白问题出在哪里。可能是因为我没有使用过这个库,但你能详细说明你的问题吗?
如果函数不是单变量的,那么您将始终必须指定函数,然后指定符号及其值。如果您以交互方式使用它,则可以通过将函数作为字符串传递并将值的顺序与变量的排序顺序相对应来减少输入。然后函数的 return 可以是替换字典(因此您可以检查)和计算的不确定性。
>>> def ucalc(f, x, u):
... f = S(f)
... syms = list(ordered(f.free_symbols))
... assert len(x) == len(u) == len(syms)
... reps = dict(zip(syms, x))
... ui = IndexedBase('u')
... args = []
... for i, xi in enumerate(syms):
... reps[ui[xi]] = u[i]
... args.append((ui[xi]*diff(f, xi))**2)
... return reps, sqrt(Add(*args)).n(subs=reps)
...
>>> ucalc('2*pi*sqrt(L/g)',(9.8,5.4),(.1,.3))
({L: 9.8, g: 5.4, u[L]: 0.1, u[g]: 0.3}, 0.239055276534314)
请注意,IndexedBase 符号用于为不确定性创建临时变量,因为这些变量不会出现在方程本身中。