?
Ich hab noch ein wenig gefummelt:
package org.example;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
public class DataFit {
public static double calcY(final double i, final Double[] d) {
return d[0] * i * i * i + d[1] * i * i + d[2] * i + d[3];
}
public static double calcE(final double[][] xys, final Double[] d) {
double sum = 0;
for (double[] xy : xys) {
sum += Math.abs(calcY(xy[0], d) - xy[1]);
}
return sum;
}
public static double check(final double bestE, final Double[] best, final ArrayList<Double[]> bests, final double[][] xys) {
double e = calcE(xys, best);
if (e < bestE) {
bests.add(best);
return e;
}
return 10000;
}
public static void shrink(final double[][] xys, final ArrayList<Double[]> bests) {
bests.sort(Comparator.comparingDouble(a -> calcE(xys, a)));
while (bests.size() > 10) {
bests.remove(bests.size() - 1);
}
}
public static ArrayList<Double[]> fit1(final double[][] xys, final int limit, final double step, final double[] startValues) {
int[] starts = new int[startValues.length];
for (int i = 0; i < starts.length; i++) {
starts[i] = Math.max(0, (int) Math.round((startValues[i] - 1d / step * (limit / 2d)) * limit));
}
ArrayList<Double[]> bests = new ArrayList<>();
double bestE = 10000;
for (int i = starts[0]; i <= starts[0] + limit; i++) {
for (int j = starts[1]; j <= starts[1] + limit; j++) {
for (int k = starts[2]; k <= starts[2] + limit; k++) {
for (int l = starts[3]; l <= starts[3] + limit; l++) {
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, -j / step, -k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, -j / step, -k / step, l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, -j / step, k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, -j / step, k / step, l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, j / step, -k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, j / step, -k / step, l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, j / step, k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{-i / step, j / step, k / step, l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, -j / step, -k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, -j / step, -k / step, l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, -j / step, k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, -j / step, k / step, l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, j / step, -k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, j / step, -k / step, l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, j / step, k / step, -l / step}, bests, xys));
bestE = Math.min(bestE, check(bestE, new Double[]{i / step, j / step, k / step, l / step}, bests, xys));
if (bests.size() > 20) {
shrink(xys, bests);
}
}
}
}
}
shrink(xys, bests);
return bests;
}
@SuppressWarnings("UnusedReturnValue")
public static ArrayList<Double[]> fit2(final double[][] xys) {
ArrayList<Double[]> bests1 = new ArrayList<>();
ArrayList<Double[]> bests2 = new ArrayList<>();
// 0.5, 1.0 and 2.0 divisor = 2.0, 1.0 and 0.5-step width
for (int i = 1; i <= 4; i *= 2) {
bests1.addAll(fit1(xys, 50, i / 2d, new double[4]));
}
shrink(xys, bests1);
for (Double[] best : bests1) {
System.out.println(Arrays.toString(best));
System.out.println(calcE(xys, best));
}
System.out.println();
// 50 limit and 50 divisor (0.02-step width) = 0.02, 0.04, ..., 1.0
for (Double[] best : bests1) {
bests2.addAll(fit1(xys, 50, 50, new double[]{best[0], best[1], best[2], best[3]}));
}
shrink(xys, bests2);
for (Double[] best : bests2) {
System.out.println(Arrays.toString(best));
System.out.println(calcE(xys, best));
}
System.out.println();
return bests2;
}
public static void main(String[] args) {
fit2(new double[][]{{0, 4.5}, {4, 43}, {8, 80}, {10, 99}, {12, 100}});
fit2(new double[][]{{0, 1}, {4, 30}, {8, 49}, {10, 64}, {12, 100}});
}
}
(Am besten von unten nach oben lesen).
Die Ausgabe wäre dann:
[0.0, -0.5, 14.0, 4.0]
18.5
[0.0, -0.5, 14.0, 3.5]
19.0
[0.0, 0.0, 9.5, 4.0]
19.5
[0.0, 0.0, 9.0, 7.0]
20.5
[0.0, 0.0, 9.0, 7.0]
20.5
[0.0, 0.0, 9.0, 6.5]
21.0
[0.0, 0.0, 9.0, 6.0]
21.5
[0.0, 0.0, 9.0, 6.0]
21.5
[0.0, 0.0, 9.0, 5.5]
22.0
[0.0, 0.0, 9.0, 5.0]
22.5
[-0.04, 0.42, 8.68, 4.5]
6.439999999999998
[-0.04, 0.42, 8.66, 4.5]
6.6000000000000085
[-0.04, 0.42, 8.64, 4.5]
6.799999999999997
[-0.04, 0.42, 8.62, 4.64]
7.140000000000028
[-0.04, 0.42, 8.62, 4.62]
7.1600000000000135
[-0.04, 0.42, 8.62, 4.6]
7.180000000000048
[-0.04, 0.42, 8.62, 4.58]
7.200000000000033
[-0.04, 0.42, 8.62, 4.56]
7.220000000000025
[-0.04, 0.42, 8.62, 4.54]
7.24000000000001
[-0.04, 0.42, 8.62, 4.52]
7.260000000000037
[0.0, 0.5, 2.0, 1.0]
23.0
[0.0, 0.5, 2.0, 0.5]
24.5
[0.0, 0.5, 1.5, 5.0]
26.0
[0.0, 0.5, 1.5, 4.5]
26.5
[0.0, 0.5, 1.5, 4.0]
27.0
[0.0, 0.5, 1.5, 3.5]
27.5
[0.0, 0.5, 1.5, 3.0]
28.0
[0.0, 0.5, 1.5, 2.5]
28.5
[0.0, 0.5, 1.0, 9.0]
29.0
[0.0, 0.5, 1.0, 8.5]
29.5
[0.0, 0.56, 1.52, 1.0]
22.27999999999998
[0.0, 0.56, 1.52, 1.0]
22.27999999999998
[0.0, 0.56, 1.52, 0.98]
22.339999999999982
[0.0, 0.56, 1.52, 0.98]
22.339999999999982
[0.0, 0.56, 1.52, 0.96]
22.399999999999977
[0.0, 0.56, 1.52, 0.96]
22.399999999999977
[0.0, 0.56, 1.5, 1.16]
22.399999999999984
[0.0, 0.56, 1.5, 1.14]
22.41999999999998
[0.0, 0.56, 1.5, 1.12]
22.439999999999984
[0.0, 0.56, 1.5, 1.1]
22.45999999999998
Das heißt, ein Polygon 3. Grades mit den Koeffizienten [-0.04, 0.42, 8.68, 4.5] wäre für die erste Punktemenge "optimal" und ein Polygon 2. Grades mit den Koeffizienten [0.56, 1.52, 1.0] wäre für die zweite Punktemenge "optimal". Gezeichnet hab ich es jetzt nicht extra, aber ich nehme an, dass das stimmt, optimal und minimal (die Koeffizienten betreffend) wäre. Aber belehrt mich gerne eines Besseres ...