B-splines in Go¶
The github.com/gomlx/bsplines implements B-spline functions.
It has 2 subpackages:
- github.com/gomlx/bsplines/plotly to plot a B-spline, demoed in this notebook.
- github.com/gomlx/bsplines/gomlx implements B-spline using GoMLX: it is accelerated (GPUs, etc) and can be used for machine learning as a building block for KAN: Kolmogorov–Arnold Networks.
Local development¶
Set a go.work
file for the notebook, so that is uses the packages gomlx
, gonb
and bsplines
from local disk, during development of those packages.
Skip this cell if you are not developing those packages, or don't have them cloned in the local directories.
In [1]:
!*rm -f go.work && go work init && go work use . && \
for dir in "${HOME}/Projects/gomlx" "${HOME}/Projects/gonb" "${HOME}/Projects/bsplines" ; do \
if [[ -d "${dir}" ]] ; then \
go work use "${dir}" ; \
fi ; \
done
%goworkfix
- Added replace rule for module "github.com/gomlx/bsplines" to local directory "/home/janpf/Projects/bsplines". - Added replace rule for module "github.com/gomlx/gomlx" to local directory "/home/janpf/Projects/gomlx". - Added replace rule for module "github.com/janpfeifer/gonb" to local directory "/home/janpf/Projects/gonb".
Examples from Wikipedia¶
Notice the curves are always contained within the convex hull formed by the control points -- their x-coordinate is taken as the mean of the knots values they affect.
The 1st derivative plot is also included, just click on the legend to display it.
In [2]:
import (
"github.com/gomlx/bsplines"
bsplinesplot "github.com/gomlx/bsplines/plotly"
)
%%
b := bsplines.New(2, []float64{0, 1, 2, 3}). // degree, knots
WithControlPoints([]float64{0, 0, 1, 0, 0}) // len(controls) = len(knots)+degree-1
fmt.Printf("\nB-spline(1.5)=%.3f\n\n", b.Evaluate(1.5))
bsplinesplot.New(b).WithMargin(0).Plot() // plot with no margin (no extrapolation)
B-spline(1.5)=0.750
In [3]:
%%
b := bsplines.New(3, []float64{-2, -1, 0, 1, 2, 3}). // degree, knots
WithControlPoints([]float64{0, 0, 0, 6, -2, 0, 0, 0}) // len(controls) = len(knots)+degree-1
bsplinesplot.New(b).WithMargin(0).Plot() // plot with no margin (no extrapolation)
Randomly Generated Curve¶
We also configure it with linear extrapolation at the margins.
In [4]:
import "math/rand/v2"
%%
const numControlPoints = 6
controlPoints := make([]float64, numControlPoints)
controlPoints[0] = 1.0
for ii := range controlPoints {
if ii > 0 {
controlPoints[ii] = controlPoints[ii-1] + (2.0*rand.Float64()-1.0)
}
}
b := bsplines.NewRegular(2, numControlPoints).WithControlPoints(controlPoints).
WithExtrapolation(bsplines.ExtrapolateLinear)
fmt.Printf("\nB-spline(0.5)=%.3f\n\n", b.Evaluate(0.5))
bsplinesplot.New(b).Plot() // Plot includes 10% margins by default, so we can see the linear extrapolation.
B-spline(0.5)=0.457