Hello sympy people!

I couldn't find any information on the topic of "Error Analysis" in sympy 
(possibly because terms like "standard", "error", and "propagation" don't 
really catch this top well in search engines ;)

Anyway, I just went ahead and wrote a basic converter from any expression 
to the expression for the error; I just documented it in the docstring if 
you are curious.

It's a little rudimentary and could be better -- namely the error of (2*a) 
is reported as 2*sqrt(ae**2/a**2)*Abs(a) instead of just 2*ae -- but it 
seems to at least produce correct results.

Please let me know if there is already a better way to do this or if you 
find a bug with this code (or if you find the code useful)!

Thanks!
-David Mashburn


def 
GetCombinedErrorExpression(sympyExpression,variables,errorVariables,verbose=False,top=True):
    '''Takes any symbolc expression with variables involving basic +-*/^ 
and converts
       it to the symbolic expression for the standard errors using error 
propagation rules
       
       "variables" is the list of variables to use; anything else is 
assumed to be constant
       "errorVariables" is the corresponding list of variables for the 
errors that will be used in the output
       errorVariables are simple symbols used to generate the return 
expression
       verbose prints the expression and all sub-expressions generated by 
recursion
       
       For cases not easily handlable, this simply returns None
       
       WARNING! No error handling is done in the case that there are 
variables IN exponents;
                you should only use error-free constants in exponents (but 
bases can have errors)
       
       Simple examples:
         
         a,b,c,ae,be,ce = sympy.symbols('a,b,c,ae,be,ce')
         
         GetCombinedErrorExpression(a**2,[a],[ae])
           --> 2*a*ae
         
         GetCombinedErrorExpression(a+b+c,[a,b,c],[ae,be,ce]) )
           --> sqrt(ae**2 + be**2 + ce**2)
         
         GetCombinedErrorExpression(a*b*c,[a,b,c],[ae,be,ce]) )
           --> sqrt(ce**2/c**2 + be**2/b**2 + ae**2/a**2)*Abs(a*b*c)
         
         GetCombinedErrorExpression(a/b,[a,b],[ae,be])
           --> sqrt(be**2/b**2 + ae**2/a**2)*Abs(a/b)
         
         GetCombinedErrorExpression(a+2*b+c**2,[a,b,c],[ae,be,ce])
           (pretty form) --> 
                 _____________________________
                /                      2    2 
               /    2      2   2   4*be *|b|  
              /   ae  + 4*c *ce  + ---------- 
             /                          2     
           \/                          b      
       '''
    if verbose:
        print sympyExpression
    if top: # Check that input variables are correct, but only do it once!
        assert hasattr(variables,__len__)
        assert hasattr(errorVariables.__len__)
        assert len(variables)==len(errorVariables)
        for v in variables:
            assert v.__class__==sympy.Symbol
        for v in errorVariables:
            assert v.__class__==sympy.Symbol
        
    # Handle cases for sympyExpression (can be any of Add, Mul, Symbol, 
Integer, Float, Number)
    if sympyExpression.__class__==sympy.Add:
        subExpressions = sympyExpression.as_coeff_add()[1]
        subExpressionsError = [ 
GetCombinedErrorExpression(s,variables,errorVariables,verbose,top=False)
                               for s in subExpressions ]
        if None in subExpressionsError:
            return None
        else:
            return sympy.sqrt(sum([s**2 for s in subExpressionsError]))
    elif sympyExpression.__class__==sympy.Mul:
        subExpressions = sympyExpression.as_coeff_mul()[1]
        subExpressionsError = [ 
GetCombinedErrorExpression(s,variables,errorVariables,verbose,top=False)
                               for s in subExpressions ]
        if None in subExpressionsError:
            return None
        else:
            errorsDivVars = [ subExpressionsError[i]/subExpressions[i]
                             for i in range(len(subExpressions)) ]
            return sympy.Abs(sympyExpression)*sympy.sqrt(sum([s**2 for s in 
errorsDivVars]))
    elif sympyExpression.__class__==sympy.Pow:
        subExpression,exponent = sympyExpression.as_base_exp()
        subExpressionError = 
GetCombinedErrorExpression(subExpression,variables,errorVariables,verbose,top=False)
        if subExpressionError==None:
            return None
        return 
sympyExpression*sympy.Abs(exponent)*subExpressionError/subExpression
    elif sympyExpression.__class__ in (sympy.Symbol,
                                        sympy.Integer,
                                        sympy.Float,
                                        sympy.Number):
        if sympyExpression in variables:
            return errorVariables[variables.index(sympyExpression)] # 
return the appropriate error var
        else:
            return 0 # assume it's a constant 
        return sympyExpression
    else: # kick any other cases as exceptions...
        return None

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sympy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to