Integration

Binder

Differentiation

Numerical differentiation is used to estimate the derivative of a mathematical function using values of the function and perhaps other knowledge about the function.

Three-Point Differentiation

FSharp.Stats implements a three point differentiation method. This method takes a set of values and their function values. For a given value xT of the set, one defines three other points which should be considered to calculate the differential at xT. Here follows a small snippet.

First, we create our data. In this case our function is f(x) = x ^ 3.

open FSharp.Stats

// x data
let xs = Array.init 100 (fun x -> float x / 8.)
// y data
let ys = Array.map (fun x -> x ** 3.) xs

Now we apply the threePointDifferentiation to every point starting with the second and ending with the second last. We can't do it for every point because for every point we need to have three other points in close proximity.

let y's = 
    [|
    for i = 1 to xs.Length - 2 do
        yield xs.[i],Integration.Differentiation.differentiateThreePoint xs ys i (i-1) (i) (i+1)
    |]

We compare the resulting values with the values of the known differential f'(x) = 3x^2, here called g(x)

open Plotly.NET

let comparisonChart = 
    [
    Chart.Point(xs,ys,Name = "f(x)")
    Chart.Point(y's,Name = "f'(x)")
    Chart.Point(Array.map (fun x -> x,(x ** 2.) * 3.) xs,Name = "g(x)")
    ]
    |> Chart.Combine

Two-Point Differentiation

To calculate the approximation for the derivative, a Two-Point Differentiation calculates the difference of f(x) at x and f(x) at x+h and correlates it to h. This will give better approximations the smaller h is. The function uses two different mathematical approaches to decrease the error, one for h > 1. and one for h < 1.


Data model


open FSharp.Stats.Integration.Differentiation.TwoPointDifferentiation
open FSharp.Stats.Integration.Differentiation

let testFunction x = x**2. 

let test1 = differentiate 0.5 testFunction 2.
//Result for test1 is: 4.00

let test2 = differentiate 3. testFunction 2.
//Result for test2 is: 7.00

let test3 = differentiate 0.1 testFunction 2.
//Result for test3 is: 4.00
  • The correct result for test1 (f(x) = x2.) is assumed to be 4.
  • With a higher h (for test2 h = 3., compared to the 0.5 used in test1) the approximation error increases.

You can try and find an optimal h - value with the "differentiateOptimalHBy" - function. This function uses the first h-value it assumes to give good results for the numerical differentiation calculation. Due to this, possible error due to float precision is avoided. In the following example this is not really necessary, as values are quite big.

let hArray = [|0.1 .. 0.1 .. 2.|]

let test4 = differentiateOptimalHBy hArray testFunction 2.
//Result for test4 is: 4.00

If you want to use a presuggested hArray then you can use the "differentiateOptimalH" function. This function uses an array from 0.01 to 5e^-100 in [|0.01; 0.005; 0.001; 0.0005; 0.0001 ..|]-increments as hArray.

let test5 = differentiateOptimalH testFunction 2. 
//Result for test5 is: 4.00
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
namespace FSharp.Stats
val xs : float []
Multiple items
module Array

from FSharp.Stats

--------------------
module Array

from Microsoft.FSharp.Collections
val init : count:int -> initializer:(int -> 'T) -> 'T []
val x : int
Multiple items
val float : value:'T -> float (requires member op_Explicit)

--------------------
type float = System.Double

--------------------
type float<'Measure> = float
val ys : float []
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []
val x : float
val y's : (float * float) []
val i : int
property System.Array.Length: int with get
namespace FSharp.Stats.Integration
module Differentiation

from FSharp.Stats.Integration
val differentiateThreePoint : xValues:float [] -> yValues:float [] -> idxT:int -> idx0:int -> idx1:int -> idx2:int -> float
namespace Plotly
namespace Plotly.NET
val comparisonChart : GenericChart.GenericChart
type Chart =
  static member Area : xy:seq<#IConvertible * #IConvertible> * ?Name:string * ?ShowMarkers:bool * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:TextPosition * ?TextFont:Font * ?Dash:DrawingStyle * ?Width:'a2 -> GenericChart
  static member Area : x:seq<#IConvertible> * y:seq<#IConvertible> * ?Name:string * ?ShowMarkers:bool * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:TextPosition * ?TextFont:Font * ?Dash:DrawingStyle * ?Width:'a2 -> GenericChart
  static member Bar : keysvalues:seq<#IConvertible * #IConvertible> * ?Name:string * ?Showlegend:bool * ?Color:'a2 * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:TextPosition * ?TextFont:Font * ?Marker:Marker -> GenericChart
  static member Bar : keys:seq<#IConvertible> * values:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?Color:'a2 * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:TextPosition * ?TextFont:Font * ?Marker:Marker -> GenericChart
  static member BoxPlot : xy:seq<'a0 * 'a1> * ?Name:string * ?Showlegend:bool * ?Color:string * ?Fillcolor:'a2 * ?Opacity:float * ?Whiskerwidth:'a3 * ?Boxpoints:Boxpoints * ?Boxmean:BoxMean * ?Jitter:'a4 * ?Pointpos:'a5 * ?Orientation:Orientation * ?Marker:Marker * ?Line:Line * ?Alignmentgroup:'a6 * ?Offsetgroup:'a7 * ?Notched:bool * ?NotchWidth:float * ?QuartileMethod:QuartileMethod -> GenericChart
  static member BoxPlot : ?x:'a0 * ?y:'a1 * ?Name:string * ?Showlegend:bool * ?Color:string * ?Fillcolor:'a2 * ?Opacity:float * ?Whiskerwidth:'a3 * ?Boxpoints:Boxpoints * ?Boxmean:BoxMean * ?Jitter:'a4 * ?Pointpos:'a5 * ?Orientation:Orientation * ?Marker:Marker * ?Line:Line * ?Alignmentgroup:'a6 * ?Offsetgroup:'a7 * ?Notched:bool * ?NotchWidth:float * ?QuartileMethod:QuartileMethod -> GenericChart
  static member Bubble : xysizes:seq<#IConvertible * #IConvertible * #IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:TextPosition * ?TextFont:Font * ?StackGroup:string * ?Orientation:Orientation * ?GroupNorm:GroupNorm * ?UseWebGL:bool -> GenericChart
  static member Bubble : x:seq<#IConvertible> * y:seq<#IConvertible> * sizes:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:TextPosition * ?TextFont:Font * ?StackGroup:string * ?Orientation:Orientation * ?GroupNorm:GroupNorm * ?UseWebGL:bool -> GenericChart
  static member Candlestick : stockTimeSeries:seq<DateTime * StockData> * ?Increasing:Line * ?Decreasing:Line * ?WhiskerWidth:float * ?Line:Line * ?XCalendar:Calendar -> GenericChart
  static member Candlestick : open:seq<#IConvertible> * high:seq<#IConvertible> * low:seq<#IConvertible> * close:seq<#IConvertible> * x:seq<#IConvertible> * ?Increasing:Line * ?Decreasing:Line * ?WhiskerWidth:float * ?Line:Line * ?XCalendar:Calendar -> GenericChart
  ...
static member Chart.Point : xy:seq<#System.IConvertible * #System.IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:StyleParam.Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:StyleParam.TextPosition * ?TextFont:Font * ?StackGroup:string * ?Orientation:StyleParam.Orientation * ?GroupNorm:StyleParam.GroupNorm * ?UseWebGL:bool -> GenericChart.GenericChart
static member Chart.Point : x:seq<#System.IConvertible> * y:seq<#System.IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:StyleParam.Symbol * ?Color:string * ?Opacity:float * ?Labels:seq<string> * ?TextPosition:StyleParam.TextPosition * ?TextFont:Font * ?StackGroup:string * ?Orientation:StyleParam.Orientation * ?GroupNorm:StyleParam.GroupNorm * ?UseWebGL:bool -> GenericChart.GenericChart
static member Chart.Combine : gCharts:seq<GenericChart.GenericChart> -> GenericChart.GenericChart
module GenericChart

from Plotly.NET
val toChartHTML : gChart:GenericChart.GenericChart -> string
module TwoPointDifferentiation

from FSharp.Stats.Integration.Differentiation
val testFunction : x:float -> float
val test1 : float
val differentiate : h:float -> f:(float -> float) -> x:float -> float
val test2 : float
val test3 : float
val hArray : float []
val test4 : float
val differentiateOptimalHBy : hArr:float [] -> f:(float -> float) -> x:float -> float
val test5 : float
val differentiateOptimalH : f:(float -> float) -> x:float -> float