Apache Commons Math hat eine schöne Reihe von Algorithmen, insbesondere "SplineInterpolator", das API docs
Ein Beispiel sehen, wie wir die Interpolationsfunktionen für Alpha nennen (x), beta (x) von Groovy:
package example.com
import org.apache.commons.math3.analysis.interpolation.SplineInterpolator
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction
import statec.Extrapolate.Value;
class Interpolate {
enum Value {
ALPHA, BETA
}
def static xValues = [
-284086,
-94784,
31446,
354837,
667782,
982191
]
def static alphaValues = [
71641,
78245,
80871,
94045,
105780,
119616
]
def static betaValues = [
95552,
103413,
108667,
128456,
144686,
171953
]
static def getValueByName(Value value, int i) {
def res
switch (value) {
case Value.ALPHA:
res = alphaValues[i]
break
case Value.BETA:
res = betaValues[i]
break
default:
assert false
}
return res
}
static PolynomialSplineFunction interpolate(Value value) {
def yValues = []
int i = 0
xValues.each {
def y = getValueByName(value, i++)
yValues << (y as Double)
}
SplineInterpolator spi = new SplineInterpolator()
return spi.interpolate(xValues as double[], yValues as double[])
}
static void main(def argv) {
//
// Create a map mapping a Value instance to its interpolating function
//
def interpolations = [:]
Value.values().each {
interpolations[it] = interpolate(it)
}
//
// Create an array of new x values to compute display.
// Make sure the last "original" value is in there!
// Note that the newxValues MUST stay within the range of the original xValues!
//
def newxValues = []
for (long x = xValues[0] ; x < xValues[-1] ; x+=25000) {
newxValues << x
}
newxValues << xValues[-1]
//
// Write interpolated values for ALPHA and BETA, adding the original values in columns 4 and 5
//
System.out << "X , ALPHA, BETA, X_orig, ALPHA_orig, BETA_orig" << "\n"
int origIndex = 0
newxValues.each { long x ->
def alpha_ipol = interpolations[Value.ALPHA].value(x)
def beta_ipol = interpolations[Value.BETA].value(x)
String out = "${x} , ${alpha_ipol} , ${beta_ipol}"
if (x >= xValues[origIndex]) {
out += ", ${xValues[origIndex]}, ${alphaValues[origIndex]}, ${betaValues[origIndex]}"
origIndex++
}
System.out << out << "\n"
}
}
}
Und jetzt ein Wegthema Beispiel für Fortschreibungen, weil es Spaß macht. Hier verwenden wir die gleichen Daten wie oben, extrapolieren aber mit einem Polynom zweiten Grades. Und die passenden Klassen natürlich. Wieder in Groovy:
package example.com
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction
import org.apache.commons.math3.fitting.PolynomialFitter
import org.apache.commons.math3.fitting.WeightedObservedPoint
import org.apache.commons.math3.optim.SimpleVectorValueChecker
import org.apache.commons.math3.optim.nonlinear.vector.jacobian.GaussNewtonOptimizer
class Extrapolate {
enum Value {
ALPHA, BETA
}
def static xValues = [
-284086,
-94784,
31446,
354837,
667782,
982191
]
def static alphaValues = [
71641,
78245,
80871,
94045,
105780,
119616
]
def static betaValues = [
95552,
103413,
108667,
128456,
144686,
171953
]
static def getValueByName(Value value, int i) {
def res
switch (value) {
case Value.ALPHA:
res = alphaValues[i]
break
case Value.BETA:
res = betaValues[i]
break
default:
assert false
}
return res
}
static PolynomialFunction extrapolate(Value value) {
//
// how to check that we converged
//
def checker
A: {
double relativeThreshold = 0.01
double absoluteThreshold = 10
int maxIter = 1000
checker = new SimpleVectorValueChecker(relativeThreshold, absoluteThreshold, maxIter)
}
//
// how to fit
//
def fitter
B: {
def useLUdecomposition = true
def optimizer = new GaussNewtonOptimizer(useLUdecomposition, checker)
fitter = new PolynomialFitter(optimizer)
int i = 0
xValues.each {
def weight = 1.0
def y = getValueByName(value, i++)
fitter.addObservedPoint(new WeightedObservedPoint(weight, it, y))
}
}
//
// fit using a 2-degree polynomial; guess at a linear function at first
// "a0 + (a1 * x) + (a2 * x²)"; a linear guess mean a2 == 0
//
def params
C: {
def mStart = getValueByName(value,0)
def mEnd = getValueByName(value,-1)
def xStart = xValues[0]
def xEnd = xValues[-1]
def a2 = 0
def a1 = (mEnd - mStart)/(xEnd - xStart) // slope
def a0 = mStart - (xStart * a1) // 0-intersection
def guess = [a0 , a1 , a2]
params = fitter.fit(guess as double[])
}
//
// make polynomial
//
return new PolynomialFunction(params)
}
static void main(def argv) {
//
// Create a map mapping a Value instance to its interpolating function
//
def extrapolations = [:]
Value.values().each {
extrapolations[it] = extrapolate(it)
}
//
// New x, this times reaching out past the range of the original xValues
//
def newxValues = []
for (long x = xValues[0] - 400000L ; x < xValues[-1] + 400000L ; x += 10000) {
newxValues << x
}
//
// Write the extrapolated series ALPHA and BETA, adding the original values in columns 4 and 5
//
System.out << "X , ALPHA, BETA, X_orig, ALPHA_orig, BETA_orig" << "\n"
int origIndex = 0
newxValues.each { long x ->
def alpha_xpol = extrapolations[Value.ALPHA].value(x)
def beta_xpol = extrapolations[Value.BETA].value(x)
String out = "${x} , ${alpha_xpol} , ${beta_xpol}"
if (origIndex < xValues.size() && x >= xValues[origIndex]) {
out += ", ${xValues[origIndex]}, ${alphaValues[origIndex]}, ${betaValues[origIndex]}"
origIndex++
}
System.out << out << "\n"
}
}
}
Frage Wesen "on hold": Man könnte die Frage umformulieren Beispiel-Code in Java von Kurvenanpassung Code zu geben (natürlich, dass Code in einigen Bibliotheken ziehen, so Das kann man als Empfehlung sehen). Bei dieser Frage geht es nicht um JFreeChart, das nur die Punkte übernimmt und sie anzeigt, aber keine zusätzlichen Punkte generiert. Ich bin wirklich erstaunt, dass Linked und Related genau diese Frage nicht zeigen. –