Skip to content

Commit

Permalink
Extrapolation (#53)
Browse files Browse the repository at this point in the history
* use latest nimib and nimibook

* fix links to Clonkk's github

* add section on extrapolation

* Update book/numerical_methods/interpolation.nim

Co-authored-by: Vindaar <[email protected]>

* Update book/numerical_methods/interpolation.nim

Co-authored-by: Vindaar <[email protected]>

---------

Co-authored-by: Vindaar <[email protected]>
  • Loading branch information
HugoGranstrom and Vindaar authored Jul 10, 2023
1 parent 86b6e6b commit ca74353
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
4 changes: 2 additions & 2 deletions book/external_language_integration/julia/basics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ nbInit(theme = useNimibook)
nbText: """
# Using Julia with Nim
In this tutorial, we explore how to use [Nimjl](https://github.com/Clokk/nimjl) to integrate [Julia](https://julialang.org/) code with Nim.
In this tutorial, we explore how to use [Nimjl](https://github.com/Clonkk/nimjl) to integrate [Julia](https://julialang.org/) code with Nim.
## What is Julia ?
Expand All @@ -20,7 +20,7 @@ Most notably, it has a strong emphasis on scientific computing and Julia's Array
# Tutorial
[Nimjl](https://github.com/Clokk/nimjl) already has some [examples](https://github.com/Clonkk/nimjl/examples/) that explains the basics, make sure to go through them in order.
[Nimjl](https://github.com/Clonkk/nimjl) already has some [examples](https://github.com/Clonkk/nimjl/examples/) that explains the basics, make sure to go through them in order.
## Basic stuff
Expand Down
49 changes: 49 additions & 0 deletions book/numerical_methods/interpolation.nim
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,55 @@ We can now evaluate it on a denser set of points and compare it to the original
As we can see, the interpolant does a decent job of approximating the function.
It is worse where the function is changing a lot and closer to the original
in the middle where there is less happening.
### Extrapolation
For 1D interpolators, extrapolation is supported. The available methods are:
- `Constant`: Set all points outside the range of the interpolator to a specified value.
- `Edge`: Use the value of the left/right edge.
- `Linear`: Uses linear extrapolation using the two points closest to the edge.
- `Native` (default): Uses the native method of the interpolator to extrapolate. For Linear1D it will be a linear extrapolation, and for Cubic and Hermite splines it will be cubic extrapolation.
- `Error`: Raises an `ValueError` if `x` is outside the range.
The extrapolation method is optionally supplied as an argument to `eval` and `derivEval`:
"""

nbCode:
echo "Edge: ", interp.eval(-1.0, Edge) # will use the value at x=0
echo "Constant: ", interp.eval(-1.0, Constant, NaN) # will return NaN
echo "Linear: ", interp.eval(-1.0, ExtrapolateKind.Linear)
echo "Native: ", interp.eval(-1.0) # will use Native by default

nbText: hlMd"""
As you can see, the choice of extrapolation method affects the values considerably.
Keep in mind though that `-1.0` is quite a big extrapolation and the further away we go, the worse the approximation gets.
Here is a visual example of how the different methods behave. I have removed the two outermost points on each side from the example before (ignore the point at `(0, 0)`, it's a bug):
"""
block:
let t = linspace(0.0, 4.2, 100)
let yOriginal = t.map(f)
let x = x[2..^3]
let y = y[2..^3]
let interp = newHermiteSpline(x, y)
let yLinear = interp.eval(t, ExtrapolateKind.Linear)
let yConstant = interp.eval(t, ExtrapolateKind.Constant, 0.0)
let yEdge = interp.eval(t, ExtrapolateKind.Edge)
let yNative = interp.eval(t, ExtrapolateKind.Native)
var df = toDf({"x": x, "y": y, "t": t, "f(t)": yOriginal, "Linear": yLinear, "Constant": yConstant, "Edge": yEdge, "Native": yNative})
df = df.gather(@["f(t)", "Linear", "Constant", "Edge", "Native"], key = "Class", value = "Value")
ggplot(df, aes("t", "Value", color="Class")) +
geom_line() +
geom_point(aes("x", "y")) +
ylim(-3.5, 3.5, "drop") +
ggsave("images/compare_interp_extrapolate.png")

nbImage("images/compare_interp_extrapolate.png", caption="Showcase of the extrapolation methods.")

nbText: hlMd"""
As we can see, the `Edge` and `Constant` are just horizontal lines while `Linear` has the same slope as the edge of the interpolant.
`Native` on the other hand is smooth but quite quickly starts to take off towards $\pm \infty$ (for the linear interpolator it would behave the same as `Linear` though).
Which method you should use is very dependent on the application and what behavior you want it to exhibit.
Of course, you should try to avoid extrapolation whenever possible.
"""

block Part2:
Expand Down
4 changes: 2 additions & 2 deletions scinim_getting_started.nimble
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ binDir = "bin"

# Dependencies
requires "nim >= 1.2.0"
requires "nimib#head"
requires "nimibook#280a626a902745b378cc2186374f14c904c9a606"
requires "nimib"
requires "nimibook"
requires "ggplotnim == 0.5.6"
requires "datamancer >= 0.2.1"
requires "mpfit"
Expand Down

0 comments on commit ca74353

Please sign in to comment.