Numerical Differentiation in IronPython QuickStart Sample

Illustrates how to approximate the derivative of a function in IronPython.

View this sample in: C# Visual Basic F#

```Python
import numerics

from math import *
from System import Math

# The numerical differentiation classes reside in the
# Extreme.Mathematics.Calculus namespace.
from Extreme.Mathematics.Calculus import *
# Function delegates reside in the Extreme.Mathematics
# namespace.
from Extreme.Mathematics import *

# Illustrates numerical differentiation using the
# FunctionMath class in the Extreme.Mathematics 
# namespace of Extreme Numerics.NET.

# Numerical differentiation is a fairly simple
# procedure. Its accuracy is inherently limited
# because of unavoidable round-off error.
#
# All calculations are performed by static methods
# of the FunctionMath class. All methods are extension
# methods, so they can be applied to the delegates
# directly.

#
# Standard numerical differentiation.
#

# Central differences are the standard way of
# approximating the result of a function.
# For this to work, it must be possible to 
# evaluate the target function on both sides of
# the point where the numerical result is
# requested.

# The function must be provided as a 
# Func<double, double>. For more information about 
# this delegate, see the FunctionDelegates 
# QuickStart Sample.
fCentral = cos

print "Central differences:"
# The actual calculation is performed by the
# CentralDerivative method.
result = FunctionMath.CentralDerivative(fCentral, 1.0)
print "  Result =", result
print "  Actual =", -sin(1.0)
# This method is overloaded. It has an optional
# out parameter that returns an estimate for the
# error in the result.
import clr
estimatedError = clr.Reference[float]()
result = FunctionMath.CentralDerivative(fCentral, 1.0, estimatedError)
print "Estimated error =", estimatedError.Value

#
# Forward and backward differences.
#

# Some functions are not defined everywhere.
# If the result is required on a boundary
# of the domain where it is defined, the central
# differences method breaks down. This also happens
# if the function has a discontinuity close to the
# differentiation point.
# 
# In these cases, either forward or backward 
# differences may be used instead.
#
# Here is an example of a function that may require
# forward differences. It is undefined for
# x < -2:
fForward = lambda x: (x+2) * (x+2) * Math.Sqrt(x+2)
			
# Calculating the derivative using central 
# differences returns NaN (Not a Number):
result = FunctionMath.CentralDerivative(fForward, -2.0, estimatedError)
print "Using central differences may not work:"
print "  Derivative =", result
print "  Estimated error =", estimatedError.Value

# Using the ForwardDerivative method does work:
print "Using forward differences instead:"
result = FunctionMath.ForwardDerivative(fForward, -2.0, estimatedError)
print "  Derivative =", result
print "  Estimated error =", estimatedError
			
# The FBackward function at the end of this file
# is an example of a function that requires
# backward differences for differentiation at
# x = 0.
fBackward = lambda x: 1.0 if x > 0.0 else Math.Sin(x)
print "Using backward differences:"
result = FunctionMath.BackwardDerivative(fBackward, 0.0, estimatedError)
print "  Derivative =", result
print "  Estimated error =", estimatedError

#
# Derivative function
#

# In some cases, it may be useful to have the
# derivative of a function in the form of a 
# Func<double, double>, so it can be passed as
# an argument to other methods. This is very
# easy to do.
print "Using delegates:"
			
# For central differences:
dfCentral = FunctionMath.GetNumericalDifferentiator(fCentral)
print "Central: f'(1) =", dfCentral(1)
			
# For forward differences:
dfForward = FunctionMath.GetForwardDifferentiator(fForward)
print "Forward: f'(-2) =", dfForward(-2)

# For backward differences:
dfBackward = FunctionMath.GetBackwardDifferentiator(fBackward)
print "Backward: f'(0) =", dfBackward(0)
```