Skip to content

Add derivatives for the splines #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Jan 8, 2021

Conversation

avik-pal
Copy link
Member

@avik-pal avik-pal commented Aug 5, 2020

TODOs:

  • Implement derivatives for all the interpolation methods
  • Integrate with ChainRulesCore
  • Verify correctness using FiniteDifferences

Follow up from SciML/DiffEqFlux.jl#380

@avik-pal
Copy link
Member Author

avik-pal commented Aug 8, 2020

I am finding it hard to get the BSpline derivative right. From my understanding the derivative of a BSpline is another BSpline of lower order. Reference

N = spline_coefficients(n, A.d - 1, A.k[2:(end - 1)], t)
ducum = zero(eltype(A.u))
for i = 1:(n - 1)
      ducum += N[i] * (A.c[i + 1] - A.c[i]) / (A.k[i + A.d + 1] - A.k[i + 1])
end
ducum * A.d

But the gradients seem to be way off.

@ChrisRackauckas
Copy link
Member

That looks like it might introduce some numerical errors? I think @YingboMa might have comments on this.

@avik-pal
Copy link
Member Author

@YingboMa any thoughts on this?

@ChrisRackauckas
Copy link
Member

Is there a version where BSplines are left off that we can open an issue on to complete later?

@YingboMa
Copy link
Member

Sorry, I missed this PR. I will review it today.

@YingboMa
Copy link
Member

I can help with the BSpline derivative later today.

@YingboMa
Copy link
Member

For the BSpline derivative, you should check pg. 72 of the NURBS book https://www.springer.com/gp/book/9783642973857. I am not familiar with BSplines, but I think a bulletproof way of differentiating BSplines is just to differentiate each basis function individually.

@avik-pal
Copy link
Member Author

The current implementation was differentiating each basis function itself. I removed the BSpline implementation for the time being so that we can move forward with the PR, and can tackle that later.

@YingboMa
Copy link
Member

I think you have an off-by-one error in your code, also the derivative of the coordinate transformation is missing.

This gives the correct derivative

using DataInterpolations, Calculus
ts = 0:4
data = sin.(ts)
A = BSplineInterpolation(data,float.(ts),3,:ArcLen,:Average)
n = length(A.t)
t = 0.1
idx = searchsortedlast(A.t,t)
idx == length(A.t) ? idx -= 1 : nothing
t_ = A.p[idx] + (t - A.t[idx])/(A.t[idx+1] - A.t[idx]) * (A.p[idx+1] - A.p[idx])

Nm1 = DataInterpolations.spline_coefficients(n, A.d-1, A.k, t_)
scale = (A.t[idx+1] - A.t[idx]) * (A.p[idx+1] - A.p[idx])
ducum = zero(eltype(A.u))
for i = 1:(n - 1)
    ducum += Nm1[i+1] * (A.c[i + 1] - A.c[i]) / (A.k[i + A.d + 1] - A.k[i + 1])
end
ducum * A.d * scale
Calculus.derivative(A, t)
julia> ducum * A.d * scale
1.0854013436178458

julia> Calculus.derivative(A, t)
1.0854013436149472

@ChrisRackauckas
Copy link
Member

I rebased this branch back to current master since it was falling behind a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants