What derivatives are used for splines in SciPy.interpolate.interp1d? - python

I'm trying to find out how the spline interpolation in scipy.interpolate.interp1d decides what the derivatives of the fitting/smoothing function should be. From the documentation, I understand that interp1d fits a spline if an int (or quadratic or cubic) is passed to the kind keyword.
But if I'm not providing any derivative information, how does it decide what the derivatives are? I tried to follow the function calls in the source code, but this only got me to the cryptic spleval function, which just seems to call FITPACK. And I wasn't really sure how to find information about FITPACK from their website...

Spline derivatives at the knot points are not explicitly prescribed, they are determined by continuity/smoothness conditions. I'll take the cubic case as an example. You give n x-values and n y-values. A cubic spline has 4*(n-1) coefficients, 4 on each of (n-1) intervals between the given x-values. These coefficients are determined from the following conditions:
The spline must be continuous at each interior knot: this is (n-2) equations, as there are (n-2) interior knots. We want both pieces to the left and right of a knot to have the same value at the knot.
The first derivative of the spline must be continuous at each interior knot: this is (n-2) equations.
The second derivative of the spline must be continuous at each interior knot: this is (n-2) equations.
The spline must match each of the given y-values: this is n equations.
The total so far is 4*n-6 equations for 4*n-4 unknowns. Two additional equations are needed; the most popular choice is to require the 3rd derivative to be continuous at the leftmost and rightmost interior knots (this is called the "not a knot" condition). Now we have a linear system of size 4*n-4, which can be solved for the coefficients.
The above should not be confused with Hermite interpolation, which is where one prescribes the values of derivatives as well as of the function itself. This is a less common task, and to my knowledge, SciPy does not have a built-in tool for it.

Related

Is there a SciPy function for computation of derivative of matrix exponential?

I work with Lie group SO(3). I know there exists an analytical expression for tangent application
from which the derivative of matrix exponential can be simply computed as
What I would like to do is to compute T(w).
The problem with simply implementing function T myself is that it is numerically imprecise for small norms of vector omega. I know there are exponential scipy.linalg.expm and logarithmic maps scipy.linalg.logm already in SciPy. Since this is similar I wonder if there is also the tangent map or the derivative. I noticed the scipy.linalg.expm_frechet, however, I didn't know how to connect it to T.
This does not directly answer your question but for
it is numerically imprecise for small norms of vector omega
you can just use Taylor series expansion for small |\omega| ie use something like
(1-cos(x))/x^2 = 1/2 - x^2/24, if |x| < eps, normal expression otherwise
for suitably small eps (say 1e-4)
and the same idea for (x-sin(x))/x^3
For numeric evaluation of the derivatives you can translate your code to use pytorch, and then autograd will do the work for you a.
For symbolic differentiation you can use sympy b

Constraint of Ordinary Least Squares using Scipy / Numpy

I am trying to solve the set of linear equations:
min || Ax - B ||^2
for t in [0,1]
such that the coefficients x in this equation satisfy the linear equation:
C x = D
This system attempts to fit a set of Polynomials to approximate a function F(t) over the range of t.
A is a matrix, representing the map of the set of polynomials over the range of t values
x is a vector of coefficients (what I want) corresponding to a weight applied to each polynomial in A
B is a vector representing the F(t) values,
C is a matrix and D a vector, which together represent the boundary conditions on the coefficients of this system
This is a case of solving linear equations using the constraint of ordinary least squares.
While there are known closed form solutions e.g. Karush-Kuhn-Tucker I'm looking for a routing in scipy / numpy that can be used to solve this.
Research has shown the scipy.optimize module, which includes functions such as:
scipy.optimize.least_squares .
scipy.optimize.nnls .
scipy.optimize.lsq_linear .
The above is suggested both from this question and this question.
But these do not have conditions that work for a constraint of some other linear equation. What can I use in scipy and numpy to do this?
For this you may use scipy.minimize(method='SLSQP'). The documentation is here.
You can define the equality constraint as a callable function with the signature:
def cons1(x):
return sum(D - C*x)
SLSQP essential uses the constraint then to drive your optimisation problem. Note that this is a gradient based decent, so you will most likely find a local minima to high dimensional problems.
Another option is scipy.minimize(method=’trust-constr’), the documentation is here. These methods are natively implemented in python so the source code and modifications are accessible through.
If you have a smooth monotonic or context function, in my experience SLSQP should suffice.

How to decide between scipy.integrate.simps or numpy.trapz?

I have a set of points, of which when I plot I get the graph below. I would like to find the area under the graph, however I am not sure whether scipy.integrate.simps or numpy.trapz is more suitable.
Could someone advice me on the mathematical background between the two functions and thus the conclusion on which function is more accurate?
The trapezoidal rule is the simplest of numerical integration methods. In effect, it estimates the area under a curve by approximating the curve with straight line segments, which only requires two points for each segment. Simpson's rule uses quadratic curves to approximate the function segments instead, each of which requires three points, sampled from your function, to approximate a given segment.
So what is the error associated with using these numerical methods as approximations to an analytical integral?
The error associated with the trapezoidal rule, to leading order, is proportional to h^2[f'(a) - f'(b)]. h is the spacing between sampled points in your function; f'(a) and f'(b) are the first derivative of your function at the beginning and end of the sampling domain.
The error through Simpson's rule, on the other hand, is proportional to h^4[f'''(a) - f'''(b)]. f''' is the third-order derivative in your function.
h is typically small, so h^4 is typically much smaller than h^2!
TLDR: Simpson's rule typically gives far superior results for numerical integration, compared to the trapezoidal rule, with basically no additional computational cost.

Solving Second Order ODE in coordinate space

I need to numerically compute the eigenvalues and eigenfunctions of the radial Schrodinger Equation in the case of a 3D and 2D Coulomb potential. The differential equation contains both the first and second derivative of R(r).
The problem is that scipy.integrate.ode or scipy.integrate.odeint require "initial values" for the function and its first derivative - every example I've seen online uses a differential equation in t, so that specifying the initial conditions of the system is trivial and arbitrary.
Since I am considering an ODE in space, not time, I should note that "initial conditions" should be more accurately called "boundary conditions". For my case, however, the function R(r) must only be finite at the origin, but there is no specific value it must take at r=0. Furthermore the derivative of the radial wavefunction, R', is physically meaningless and so constraining (or especially specifying) its value at the origin is nonsensical. The only definite boundary conditions present in the system is that the function must exponentially decay to zero for very large r.
In this case I am considering, instead of making the linspace count up from zero to some large number, make it count backwards from a large value to zero, for which I can set my "initial condition at r -> infinity" such that R and R' are zero.
Anyone else have this issue, and what workaround did you find for it?
Thank you!

Finding the length of a cubic B-spline

Using scipy's interpolate.splprep function get a parametric spline on parameter u, but the domain of u is not the line integral of the spline, it is a piecewise linear connection of the input coordinates. I've tried integrate.splint, but that just gives the individual integrals over u. Obviously, I can numerically integrate a bunch of Cartesian differential distances, but I was wondering if there was closed-form method for getting the length of a spline or spline segment (using scipy or numpy) that I was overlooking.
Edit: I am looking for a closed-form solution or a very fast way to converge to a machine-precision answer. I have all but given up on the numerical root-finding methods and am now primarily after a closed-form answer. If anyone has any experience integrating elliptical functions or can point me to a good resource (other than Wolfram), That would be great.
I'm going to try Maxima to try to get the indefinite integral of what I believe is the function for one segment of the spline: I cross-posted this on MathOverflow
Because both x & y are cubic parametric functions, there isn't a closed solution in terms of simple functions. Numerical integration is the way to go. Either integrating the arc length expression or simply adding line segment lengths - depends on the accuracy you are after and how much effort you want to exert.
An accurate and fast "Adding length of line segments" method:
Using recurvise subdivision (a form of de Casteljeau's algorithm) to generate points, can give you a highly accurate representation with minimal number of points.
Only subdivide subdivisions if they fail to meet a criteria. Usually the criteria is based on the length joining the control points (the hull or cage).
For cubic, usually comparing closeness of P0P1+P1P2+P2P3 to P0P3, where P0, P1, P2 & P3 are the control points that define your bezier.
You can find some Delphi code here:
link text
It should be relatively easy to convert to Python.
It will generate the points. The code already calculates the length of the segments in order to test the criteria. You can simply accumulate those length values along the way.
You can integrate the function sqrt(x'(u)**2+y'(u)**2) over u, where you calculate the derivatives x' and y' of your coordinates with scipy.interpolate.splev. The integration can be done with one of the routines from scipy.integrate (quad is precise [Clenshaw-Curtis], romberg is generally faster). This should be more precise, and probably faster than adding up lots of small distances (which is equivalent to integrating with the rectangle rule).

Categories