Advertisement
Guest User

Untitled

a guest
Sep 25th, 2020
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 3.97 KB | None | 0 0
  1. // File Library.fs
  2.  
  3. module NumericalIntegrator
  4.  
  5. type XYdata =
  6.     {
  7.         X : float
  8.         Y : float list
  9.     }
  10.  
  11. let listToXYdata theList =
  12.     {X = List.head theList; Y = List.tail theList}
  13.    
  14. let step theDiffEq delta (initialData:XYdata) =
  15.     let rec helper newY oldY =
  16.         match oldY with
  17.         | y1::y2::tail   ->  helper
  18.                                 ( (y1 + delta * y2) :: newY )
  19.                                 (y2 :: tail)
  20.         | [yLast]       ->  (yLast + delta * (theDiffEq initialData)) :: newY
  21.                             |> List.rev
  22.         | []            ->  failwith "error"
  23.     {X = initialData.X + delta; Y = helper [] initialData.Y }
  24.  
  25.  
  26. let stepMany (numSteps:uint) theDiffEq delta initialConditions =
  27.     let rec helper history (iterationsLeft:uint) =
  28.         match iterationsLeft with
  29.         | 0u -> history
  30.         | iterationsLeft -> helper (step theDiffEq delta history.Head :: history) (iterationsLeft - 1u)
  31.     helper [initialConditions] numSteps
  32.     |> List.rev
  33.  
  34.  
  35. // File Tests.fs
  36.  
  37. module Tests
  38.  
  39. open System
  40. open Xunit
  41. open Swensen.Unquote
  42.  
  43. open NumericalIntegrator
  44.  
  45. let isWithinToleranceOf expectedFunc tolerance (actual:XYdata list) =
  46.     let helper index (data:XYdata) =
  47.         let expected = expectedFunc data.X
  48.         try
  49.             Assert.InRange(data.Y.Head, expected - tolerance, expected + tolerance)
  50.         with
  51.             | :? Sdk.InRangeException ->    
  52.                 let message =
  53.                     sprintf
  54.                         "  -----\nAt iteration %d exceeded tolerance of %f\nExpected %f\nActual %f\n     -----"
  55.                         index tolerance expected data.Y.Head
  56.                 Assert.True(false, message)
  57.            
  58.     actual
  59.     |> List.iteri helper
  60.     |> ignore
  61.  
  62. let computationTime numSteps theDiffEq delta initialConditions =
  63.     let crono = Diagnostics.Stopwatch.StartNew()
  64.     stepMany numSteps theDiffEq delta initialConditions
  65.     |> ignore
  66.     crono.Stop()
  67.     crono.ElapsedMilliseconds
  68.  
  69. let computationTimeMany howMany numSteps theDiffEq delta initialConditions =
  70.     List.init howMany
  71.         (fun _ -> computationTime numSteps theDiffEq delta initialConditions)
  72.  
  73. let benchmark theDiffEq =
  74.     computationTimeMany 20 100000u theDiffEq 0.01 {X = 0.0; Y = [1.0]}
  75.     |> List.averageBy float
  76.  
  77.  
  78.              
  79. [<Fact>]
  80. let ``Test single step of y1=1`` () =
  81.     let theDiffEq xy = 1.0
  82.     let delta = 0.1
  83.     let initialConditions = listToXYdata [0.0; 0.0]
  84.  
  85.     listToXYdata [delta; delta] =! step theDiffEq delta initialConditions
  86.  
  87. [<Fact>]
  88. let ``Test stepMany with y1=1`` () =
  89.     let theDiffEq xy = 1.0
  90.     let delta = 0.1
  91.     let initialConditions = listToXYdata [0.0; 0.0]
  92.     let steps = 2u
  93.  
  94.     let expected =
  95.         [ [0.0; 0.0]; [delta; delta]; [delta*2.0; delta*2.0] ]
  96.         |> List.map listToXYdata
  97.    
  98.     [initialConditions] =! stepMany 0u theDiffEq delta initialConditions
  99.     expected =! stepMany steps theDiffEq delta initialConditions
  100.  
  101. [<Fact>]
  102. let ``y1 = y`` () =
  103.     let theDiffEq (xy:XYdata) = xy.Y.[0]
  104.     let delta = 5e-4
  105.     let initialConditions = listToXYdata [0.0; 1.0]
  106.     let expectedFunc x = Math.Exp x
  107.     let numSteps = 200u
  108.     let tolerance = 1e-4
  109.  
  110.     let actualResult = stepMany numSteps theDiffEq delta initialConditions
  111.  
  112.     actualResult
  113.     |> isWithinToleranceOf expectedFunc tolerance
  114.  
  115. [<Fact>]
  116. let ``y2 = -y`` () =
  117.     let theDiffEq xy = -xy.Y.[0]
  118.     let delta = 5e-4
  119.     let initialConditions = listToXYdata [0.0; 1.0; 0.0]
  120.     let expectedFunc x = Math.Cos x
  121.     let numSteps = 200u
  122.     let tolerance = 1e-4
  123.  
  124.     let actualResult = stepMany numSteps theDiffEq delta initialConditions
  125.  
  126.     actualResult
  127.     |> isWithinToleranceOf expectedFunc tolerance
  128.  
  129. [<Fact>]
  130. let ``Benchmark`` () =
  131.     let theDiffEq xy = -xy.Y.[0]
  132.     let averageMilliseconds = benchmark theDiffEq
  133.     averageMilliseconds <! 60.0
  134.     printfn "\n -- BENCHMARK --\nTook %f ms\n ---------------" averageMilliseconds
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement