Automatisieren von Fehlerrechnung

\[ \sigma_{f(x_i)} = \sqrt{\sum_i \left( \frac{\partial f}{\partial x_i}\right)^{\!2} \sigma_{x_i}^2} \]

  1. Berechne die Ableitungen von \(f\) nach allen fehlerbehafteten Größen \(x_i\)
  2. Ableitungen in die obere Formel einsetzen
  3. Werte und Fehler der \(x_i\) einsetzen

# TODO: Korrelation erklären

python-uncertainties

In [1]:
from uncertainties import ufloat

x = ufloat(5, 1)
y = ufloat(3, 1)

x + y
Out[1]:
8.0+/-1.4142135623730951
In [2]:
# Korrelationen werden von uncertainties beachtet:
x = ufloat(3, 1)
y = ufloat(3, 1)

print(x**2 - y)
print(x**2 - x) # Fehler ist kleiner!
6+/-6
6+/-5

uncertainties.unumpy ergänzt numpy:

In [3]:
import numpy as np
import uncertainties.unumpy as unp

x = [1, 2, 3, 4, 5]
err = [0.1, 0.3, 0.1, 0.8, 1.0]

y = unp.uarray(x, err)

unp.cos(unp.exp(y))
Out[3]:
array([-0.9117339147869651+/-0.11166193174450133,
       0.4483562418187328+/-1.9814233218473645,
       0.3285947554325321+/-1.8970207322669204,
       -0.3706617333977958+/-40.567208903209576,
       -0.7260031145123346+/-102.06245489729305], dtype=object)

Zugriff auf Wert und Standardabweichung mit n und s:

In [4]:
x = ufloat(5, 1)
print(x.n)
print(x.s)
5.0
1.0

Bei unumpy mit nominal_values und std_devs

In [5]:
x = unp.uarray([1, 2, 3], [0.3, 0.3, 0.1])
print(unp.nominal_values(x))
print(unp.std_devs(x))
[ 1.  2.  3.]
[ 0.3  0.3  0.1]

Kann man natürlich auch abkürzen:

In [6]:
from uncertainties.unumpy import (nominal_values as noms,
                                  std_devs as stds)

print(noms(x))
print(stds(x))
[ 1.  2.  3.]
[ 0.3  0.3  0.1]

Man muss daran denken, die Funktionen aus unumpy zu benutzen (exp, cos, etc.)

In [7]:
unp.cos(x)
Out[7]:
array([0.5403023058681398+/-0.25244129544236893,
       -0.4161468365471424+/-0.2727892280477045,
       -0.9899924966004454+/-0.014112000805986721], dtype=object)

SymPy importieren:

In [8]:
from sympy import *

Mathematische Variablen erzeugen mit var():

In [9]:
x, y, z = var('x y z')

x + y + z
Out[9]:
x + y + z

Differenzieren mit diff():

In [10]:
f = x + y**3 - cos(z)**2

print(f.diff(x))
print(f.diff(y))
print(f.diff(z))
print(f.diff(z, z, z))
1
3*y**2
2*sin(z)*cos(z)
-8*sin(z)*cos(z)

Eine Funktion, die automatisch die Fehlerformel generiert:

In [11]:
from sympy import *

def error(f, err_vars=None):
    from sympy import Symbol, latex
    s = 0
    latex_names = dict()
    
    if err_vars == None:
        err_vars = f.free_symbols
        
    for v in err_vars:
        err = Symbol('latex_std_' + v.name)
        s += f.diff(v)**2 * err**2
        latex_names[err] = '\\sigma_{' + latex(v) + '}'
        
    return latex(sqrt(s), symbol_names=latex_names)

E, q, r = var('E_x q r')

f = E + q**2 * r

print(error(f))
\sqrt{\sigma_{E_{x}}^{2} + 4 \sigma_{q}^{2} q^{2} r^{2} + \sigma_{r}^{2} q^{4}}

\[\sqrt{\sigma_{E_{x}}^{2} + 4 \sigma_{q}^{2} q^{2} r^{2} + \sigma_{r}^{2} q^{4}}\]