2 * Karinto Library Project
\r
4 * This software is distributed under a zlib-style license.
\r
5 * See license.txt for more information.
\r
9 using System.Collections.Generic;
\r
10 using System.Diagnostics;
\r
15 /// 最小二乗法による近似多項式を求める
\r
17 public static class CurveFitter
\r
19 public static Polynomial Fit(PointList target, int order)
\r
24 return FitQuadratic(target);
\r
26 return FitLinear(target);
\r
28 throw new NotImplementedException();
\r
31 public static Polynomial FitLinear(PointList target)
\r
34 // bn = Σ x[i]^n * y[i]
\r
35 double a2 = 0, a1 = 0, a0 = target.Count;
\r
36 double b1 = 0, b0 = 0;
\r
37 foreach (Point p in target)
\r
46 // ( a2 a1 )・( k1 ) = ( b1 )
\r
47 // ( a1 a0 ) ( k0 ) ( b0 )
\r
48 double det = a0 * a2 - a1 * a1; // 係数行列の行列式
\r
49 if (Math.Abs(det) < Double.Epsilon)
\r
52 throw new NotImplementedException();
\r
54 double k1 = a0 * b1 - a1 * b0;
\r
55 double k0 = -a1 * b1 + a2 * b0;
\r
56 double[] c = new Double[] { k0 / det, k1 / det };
\r
57 return new Polynomial(c);
\r
60 public static Polynomial FitQuadratic(PointList target)
\r
63 // bn = Σ x[i]^n * y[i]
\r
64 double a4 = 0, a3 = 0, a2 = 0, a1 = 0, a0 = target.Count;
\r
65 double b2 = 0, b1 = 0, b0 = 0;
\r
66 foreach (Point p in target)
\r
70 double xx = xi * xi;
\r
71 double yx = yi * xi;
\r
80 // 3元連立一次方程式の解をクラメルの公式で考える
\r
81 // ( a4 a3 a2 ) ( k2 ) ( b2 )
\r
82 // | a3 a2 a1 |・| k1 | = | b1 |
\r
83 // ( a2 a1 a0 ) ( k0 ) ( b0 )
\r
84 double det = (a0 * a2 - a1 * a1) * a4 - a0 * a3 * a3 + 2 * a1 * a2 * a3 - a2 * a2 * a2; // 係数行列の行列式
\r
85 if (Math.Abs(det) < Double.Epsilon)
\r
88 return FitLinear(target);
\r
90 double k2 = (a0 * a2 - a1 * a1) * b2 + (a1 * a2 - a0 * a3) * b1 + (a1 * a3 - a2 * a2) * b0;
\r
91 double k1 = (a1 * a2 - a0 * a3) * b2 + (a0 * a4 - a2 * a2) * b1 + (a2 * a3 - a1 * a4) * b0;
\r
92 double k0 = (a1 * a3 - a2 * a2) * b2 + (a2 * a3 - a1 * a4) * b1 + (a2 * a4 - a3 * a3) * b0;
\r
93 double[] c = new double[] { k0 / det, k1 / det, k2 / det };
\r
94 return new Polynomial(c);
\r
97 public static double CalucurateR2(PointList target, Polynomial approx)
\r
99 double[] yArray = approx.GetValues(target.XArray);
\r
100 PointList yy = new PointList(target.YArray, yArray);
\r