Mathematical function differentiation with C#?

32,341

Solution 1

You can't calculate the exact derivative of a function using a computer program (unless you're doing symbolic math... but that's another, way more complicated, topic).

There are several approaches to computing a numerical derivative of a function. The simplest is the centered three-point method:

  • Take a small number h
  • Evaluate [f(x+h) - f(x-h)] / 2h
  • Voilà, an approximation of f'(x), with only two function evaluations

Another approach is the centered five-point method:

  • Take a small number h
  • Evaluate [f(x-2h) - 8f(x-h) + 8f(x+h) - f(x+2h)] / 12h
  • Voilà, a better approximation of f'(x), but it requires more function evaluations

Another topic is how to implement this using C#. First, you need a delegate that represents a function that maps a subset of the real numbers onto a another subset of the real numbers:

delegate double RealFunction(double arg);

Then, you need a routing that evaluates the derivative:

public double h = 10e-6; // I'm not sure if this is valid C#, I'm used to C++

static double Derivative(RealFunction f, double arg)
{
    double h2 = h*2;
    return (f(x-h2) - 8*f(x-h) + 8*f(x+h) - f(x+h2)) / (h2*6);
}

If you want an object-oriented implementation, you should create the following classes:

interface IFunction
{
    // Since operator () can't be overloaded, we'll use this trick.
    double this[double arg] { get; }
}

class Function : IFunction
{
    RealFunction func;

    public Function(RealFunction func)
    { this.func = func; }

    public double this[double arg]
    { get { return func(arg); } }
}

class Derivative : IFunction
{
    IFunction func;
    public static double h = 10e-6;

    public Derivative(IFunction func)
    { this.func = func; }

    public double this[double arg]
    {
        get
        {
            double h2 = h*2;
            return (
                func[arg - h2] - func[arg + h2] +
                ( func[arg + h]  - func[arg - h] ) * 8
                ) / (h2 * 6);
        }
    }
}

Solution 2

If you're thinking of symbolic manipulation of formulae then you're better off doing your derivations in languages like Maple or Mathematica. They're designed for symbolic computation.

EDIT: If Maple and Mathematica are too expensive for you then there are other options. Wikipedia has a fairly complete listing of computer algebra packages. http://en.wikipedia.org/wiki/Comparison_of_computer_algebra_systems

Solution 3

Are you thinking of Lambda Expressions?

Basically you can pass a function into a function.

So think of a Sort on an object. Depending on the nature of the object would help determine how the objects are sorted.

But you can still create a generic sort function then pass in how to compare objects.

Solution 4

Another approach can be to leverage the extensions methods using the well-known definition of the derivative number and compute its approximation accordingly.

As it has already been mentioned, this is pretty easy for a numeric approach not a symbolic one:

public partial static class IEnumerableExtensions
{
    public static IEnumerable<Double> Derivate1<TSource>(this IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
    {
        var enumerator = source.GetEnumerator();

        enumerator.Reset();
        enumerator.MoveNext();

        var itemPrevious = enumerator.Current;
        var itemNext = default(TSource);

        while (enumerator.MoveNext())
        {
            itemNext = enumerator.Current;

            var itemPreviousX = selectorX(itemPrevious);
            var itemPreviousY = selectorY(itemPrevious);

            var itemNextX = selectorX(itemNext);
            var itemNextY = selectorY(itemNext);

            var derivative = (itemNextY - itemPreviousY) / (itemNextX - itemPreviousX);

            yield return derivative;

            itemPrevious = itemNext;
        }
    }
}

or if you are more into a foreach fashion

public partial static class IEnumerableExtensions
{
     public static IEnumerable<Double> Derivate2<TSource>(IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
     {
         var itemPrevious = source.First();

         source = source.Skip(1);

         foreach (var itemNext in source)
         {
             var itemPreviousX = selectorX(itemPrevious);
             var itemPreviousY = selectorY(itemPrevious);

             var itemNextX = selectorX(itemNext);
             var itemNextY = selectorY(itemNext);

             var derivative = (itemNextY - itemPreviousY) / (itemNextX - itemPreviousX);

             yield return derivative;

             itemPrevious = itemNext;
        }
    }
}

You can refactor everything as below:

public static partial class MathHelpers
{
    public static Double Derivate(Double xPrevious, Double xNext, Double yPrevious, Double yNext)
    {
        var derivative = (yNext - yPrevious)/(xNext - xPrevious);

        return derivative;
    }
}

public static class IEnumerableExtensions
{
     public static IEnumerable<Double> Derivate<TSource>(IEnumerable<TSource> source, Func<TSource, Double> selectorX, Func<TSource, Double> selectorY)
     {
         var itemPrevious = source.First();

         source = source.Skip(1);

         foreach (var itemNext in source)
         {
             var derivative = MathHelpers.Derivate(selectorX(itemPrevious), selectorX(itemNext), selectorY(itemPrevious), selectorY(itemNext));

             yield return derivative;

             itemPrevious = itemNext;
        }
    }
}
Share:
32,341
Rogez Sanchez
Author by

Rogez Sanchez

Updated on July 23, 2022

Comments

  • Rogez Sanchez
    Rogez Sanchez almost 2 years

    I see that I can declare a function with (say)

    public double Function(double parameter)
    

    but what if I do want to take the derivative of that function?

  • Rogez Sanchez
    Rogez Sanchez over 15 years
    Yes this is what I would like. Create a function and manipulate it. I need a third party?
  • ntownsend
    ntownsend over 15 years
    The verbal form of the derivative operation in calculus is 'differentiate', not 'derive'.
  • B Bulfin
    B Bulfin over 15 years
    Ah. Duly noted. Learning. I like it.
  • Dr. Andrew Burnett-Thompson
    Dr. Andrew Burnett-Thompson over 12 years
    Very consise and simple explanation of Numerical Differentiation in C#. Thanks :)
  • pyon
    pyon over 12 years
    @Andrew Burnett-Thompson: Thanks.
  • LaRiFaRi
    LaRiFaRi over 10 years
    Could you please demonstrate how to use this?
  • pyon
    pyon over 10 years
    @LaRiFaRi: Sorry, my C# is rusty these days, I am more of a Haskell and ML programmer. But here is the general idea: 1. make a regular method that takes a double and returns a double, 2. construct a Function, passing the method you previously created as its delegate argument, 3. construct a Derivative, passing the Function you previously created as its argument.
  • sdjuan
    sdjuan over 7 years
    @pyon: that looks interesting but like LaRiFaRi I'd like to see an example. What you described in answer to LaRiFaRi seems like a text description of the 3 parts of the object version you posted in your answer. I can easily implement that object version you describe but I have no clue how to actually call that to get a derivative back from it. Thanks.
  • pyon
    pyon over 7 years
    @sdjuan: To call an IFunction, use the operator [], as if you were indexing an array.
  • Rusty Nail
    Rusty Nail over 6 years
    Forgive my ignorance, what type is x representing? imaginary Number? String? Double? Tuple?
  • Rusty Nail
    Rusty Nail over 6 years
    Apologies: Double, the arg variable is x two different methods.