0

As you may or may not know, the formula for the uncertainty in a variable defined by some function h is given by:

k.
I want to create a python function that does this for me. This is what I currently have:

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)

I'm pretty sure this works fine for this specific function, however, I want to generalize it more, I want it to take in a list of values, the uncertainty of those values, and a function, and give me the uncertainty. The problem im having is that if my variables already have a value, then the function is evaluated to a number, and because of this I just get zero when trying to calculate the partial derivatives, this is fixed by the symbols('L g', real=True) line which keeps the function unevaluated until it gets to the lamdify part. Does anyone know how this can be done, having a function like this would really help with my labs as calculating that function by hand is a real pain.

  • Use `subs` rather than `lambdify`. Otherwise the code works so it isn't clear what problem you want to solve. – Oscar Benjamin Mar 21 '22 at 17:55
  • It's very counterintuitive that `uncertainty_in_var` is not a parameter of `uncertainty_calculator`. – Stef Mar 21 '22 at 18:03
  • I agree it does work, for this specfic function. However If i want to use this for another function I need to change the symbols line, vairbales list and the function. I guess im just wondering if there is a way to make it so you have to change less things, – Markus Hamre Mar 21 '22 at 18:06
  • I agree Stef, I can change this, I just wrote it that way to test if it works – Markus Hamre Mar 21 '22 at 18:14

2 Answers2

0

It seems that you implying that symbols('L g', real=True) fixes the problem, I cannot understand what's the problem. Probably because I haven't used this library but can you specify a little bit more your problem?

White_Sirilo
  • 264
  • 1
  • 11
  • if I have a variable that is defined by some function. For example, I want to calculate the period and I have a length equal to some number and g=9.8. If I don't have the symbols line before i define my function for the period then this function gets evaluated to a number. This means that T=some number and the partial derivatives are just zero since T is just a number. With the symbols line my function remains unevaluated and T=2pi *sqrt(L/g), which then allows me to calculate patial derivatives of this. – Markus Hamre Mar 21 '22 at 17:56
0

If the function is not univariate then you will always have to specify the function and then the symbols and their values. If you are using this interactively, you could cut down on the input by passing the function as a string and the values in their order corresponding to the sorted order of the variables. The return of the function could then be a replacement dictionary (so you can check) and the computed uncertainty.

>>> 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)

Note that an IndexedBase symbol is used to create the temporary variables for uncertainties since those do not appear in the equation itself.

smichr
  • 16,948
  • 2
  • 27
  • 34