J-Splines Curve Fitting

Introduction

This paper introduces a versatile method, tentatively named "J-Splines," for fitting arbitrary functions f(x), particularly those that exhibit linear behavior (0th or 1st order) at their left and right extremities. The core idea is to sum a series of "softplus-like" logarithmic terms, each contributing a localized bend to the overall curve.

The core intuition is that each component function (term) starts asymptotically at 0 (for x far to the left of its center) and ends with a specific linear slope (for x far to the right of its center), provided its parameters a and b have the same sign. This means the "inactive" parts of such a term do not distort the existing function. By strategically placing and shaping these terms, one can locally "bend" the curve at desired points to match a target shape or dataset. It's analogous to bending an iron wire into a specific form – similar in spirit to splines, but potentially simpler for constructing f(x) functions directly.

Disclaimers

Author: This document, the "J-Splines" method concept, and the provided examples were developed by jimd80 (pseudonym).

Regarding AI Assistance: AI was used to assist with text generation, code structuring, and layout formatting for this document.

Regarding the Name "J-Splines": The term "J-Splines" is proposed by the author for the method described herein. The author does not claim this name if it has been previously used by others for similar or identical methods.

The Core Term

The fundamental building block of this method is the function:

Term(x; a, b, c) = a * ln(1 + eb * (x - c) / a)

Where:

By allowing a and b to be positive or negative, bends can be created in various directions. For the term to start near zero and then introduce a bend (the primary mode of use in this paper for building up a curve), a and b should have the same sign (so b/a > 0). In this case: For x << c, b*(x-c)/a is large and negative, so eb*(x-c)/a approaches 0. Thus, ln(1 + e...) approaches ln(1) = 0, and the term is ~0. For x >> c, b*(x-c)/a is large and positive, so e... is large. ln(1 + e...) approaches ln(eb*(x-c)/a) = b*(x-c)/a. Thus, the term becomes a * (b*(x-c)/a) = b*(x-c), which has a slope of b.

The Full Function

The overall J-Spline function F(x) is a sum of these terms, potentially with an initial linear function F_initial(x) = m_0*x + y_0:

F(x) = F_initial(x) + Σ [ai * ln(1 + ebi * (x - ci) / ai)]

This allows the function to start with a non-zero value or slope and then be progressively modified by the subsequent terms. Each term i is typically configured such that a_i and b_i have the same sign.

Visualizing Single Bends

The following charts illustrate the behavior of a single term where `a` and `b` have the same sign. We'll assume F_initial(x) = 0 for simplicity.

Chart 1: Upward Bend (a > 0, b > 0)

Single term: a=20, b=1, c=150. The function starts at 0 and transitions to a line with slope b=1.

Chart 2: Downward Bend (a < 0, b < 0)

Single term: a=-20, b=-1, c=150. The function starts at 0 and transitions to a line with slope b=-1.

Note: If a and b have opposite signs (b/a < 0), the term starts with a slope b (for x << c) and transitions to a slope of 0 (for x >> c). For instance, if a > 0, b < 0, it starts with a negative slope and flattens out. If a < 0, b > 0, it starts with a positive slope and flattens out. The charts above show cases where a and b have the same sign, causing a bend *from* an initial horizontal line.

Building Complex Curves by Summation: An Example

Multiple terms can be summed to create more complex shapes. Each new term, when a_i and b_i have the same sign, adds its local "bend" (changing the slope by b_i) to the function formed by the preceding terms, primarily after x = c_i.

Let's construct an example function aiming to pass near the following target data points (shown as red circles in the charts below): (50, 50), (150, 100), (300, 200), (350, 200), (450, 240), (550, 200).

We start with a base function F_0(x) = 50. The full J-Spline function with four terms will be:

F(x) = F_0(x) + a1*ln(1 + eb1*(x-c1)/a1) + a2*ln(1 + eb2*(x-c2)/a2) + a3*ln(1 + eb3*(x-c3)/a3) + a4*ln(1 + eb4*(x-c4)/a4)

The parameters are chosen as follows:

Substituting these values, the specific function is:

F(x) = 50 + 20*ln(1 + e1*(x-100)/20) + (-20)*ln(1 + e(-1)*(x-250)/(-20)) + 20*ln(1 + e0.8*(x-400)/20) + (-20)*ln(1 + e(-2.4)*(x-500)/(-20))

Note that for each term i, the ratio bi/ai is positive (e.g., for Term 2, (-1)/(-20) = 1/20). This ensures that each term contributes approximately 0 for x << ci and introduces its bend to the right of ci.

Chart 3.1: Base + 1 Term (Upward Bend)

Base: F0(x)=50. Term 1: a=20, b=1, c=100. Slope becomes ~1 after x=100.

Chart 3.2: Base + 2 Terms (Creating a Plateau)

Previous function + Term 2: a=-20, b=-1, c=250. Slope becomes ~0 after x=250.

Chart 3.3: Base + 3 Terms (Second Upward Bend)

Previous function + Term 3: a=20, b=0.8, c=400. Slope becomes ~0.8 after x=400.

Chart 3.4: Base + 4 Terms (Final Downward Bend)

Previous function + Term 4: a=-20, b=-2.4, c=500. Slope becomes ~0.8 - 2.4 = -1.6 after x=500.

Advantages and Properties

Conclusion

The "J-Splines" method, based on summing a * ln(1 + eb*(x-c)/a) terms, offers a powerful yet conceptually simple approach to curve fitting and function construction. Its ability to locally modify a curve while maintaining overall smoothness and predictable asymptotic behavior (when parameters are chosen appropriately, e.g. a_i and b_i having the same sign for additive bends) makes it a valuable tool. Finding the optimal parameters (a_i, b_i, c_i) for a given dataset would typically involve numerical optimization techniques, but the manual, intuitive construction demonstrated here highlights the method's underlying mechanics.