2016-03-27 13 views
2

1000'ler x ve y koordinatları olan bir tablom var. Eşleşen bir fonksiyon denklemini bulmanın en hızlı yolu hangisidir?Değer denklemini değer tablosundan çıkartın

tablo aşağıdaki gibidir:

t - y

0 - 0.3113 
1 - 0.5493 
2 - 0.7190 
3 - 0.6474 
4 - 0.9200 
5 - 0.2467 
6 - 0.8068 
7 - 0.5910 
8 - 0.8302 
9 - 0.2612 
10 - 0.9869 

t genliği, zaman y anlamına gelir.

Şimdi bu noktaların hepsine belirli bir zamanda ulaşan bir denklem oluşturmak istiyorum. Birinden diğerine geçiş mümkün olduğunca düz (doğrusal) olmalı, ayrıca düz çizgiler olmamalıdır. Asenkron sinüs dalgası gibi bir tür dalga formunda olmasını istiyorum.

Bunu nasıl gerçekleştireceğini bilen var mı?

+0

bak artıyor varsayar. – intboolstring

+1

java'dan daha çok bir matlab işi gibi görünse de, burada [kübik spline] (https://commons.apache.org/proper/commons-math/jacoco/org.apache.commons.math3.analysis.interpolation/SplineInterpolator .java.html) kaynak kodu. – Daniel

cevap

0

Her bir nokta çifti arasında kübik parçalar oluşturmak için kübik splineları kullanabilirsiniz. Spline, tüm noktaları vurmanızı ve segmentler arasındaki sürekliliğin 0'dan yüksek olmasını sağlayacaktır. 0 sürekliliği, noktaların bağlanması için hatların kullanıldığını gösterir. Aşağıda, en basit/en havalı splinelardan biri olan bir Catmull-Rom spline uygulamasıdır.
Caveat
Bu uygulama x monotonik regresyon içine

import java.util.Arrays; 

public class CatmullRomSpline 
{ 
    protected double[] _x; 
    protected double[] _y; 
    public CatmullRomSpline(final double[] x, final double[] y) 
    { 
     this._x = x; 
     this._y = y;  
    } 

    public double getValueAt(double x) 
    { 
     int length = this._x.length; 
     int index = Arrays.binarySearch(this._x, x); 
     double result; 
     // Exact match was found 
     if(index >= 0) 
     { 
      result = this._y[index]; 
     } 
     // x is smaller than the smaller value in the sequence 
     else if(index == -1) 
     { 
      result = -1; 
     } 
     // x is larger than the largest number in the sequence 
     else if(index == -length - 1) 
     { 
      result = -2; 
     } 
     // the number is between two of the numbers in the sequence 
     else 
     { 
      index = -(index + 2); 
      double p0, p1, p2, p3; 
      if(index == 0) 
      { 
       p1 = this._y[0]; 
       p2 = this._y[1]; 
       p3 = this._y[2]; 
       p0 = 2 * p1 - p2; 
      } 
      else if(index >= length - 2) 
      { 
       p0 = this._y[length - 3]; 
       p1 = this._y[length - 2]; 
       p2 = this._y[length - 1]; 
       p3 = 2 * p2 - p1; 
      } 
      else 
      { 
       p1 = this._y[index]; 
       p2 = this._y[index + 1]; 
       p3 = this._y[index + 2]; 
       p0 = this._y[index - 1]; 
      } 
      // Normalize range from [0, 1] to agree with the derivation of the spline 
      x = (x - this._x[index])/(this._x[index + 1] - this._x[index]); 
      double c0 = p1; 
      double c1 = p2 - p0; 
      double c2 = p2 - p1; 
      double c3 = p1 - p3; 
      double c4 = c1 - c3; 
      result = c0 + x * (0.5 * c1 + x * (0.5 * c3 + 3 * c2 - c1 + x * (0.5 * c4 - 2 * c2))); 
     } 
     return result; 
    } 
    public static void main(String[] args) 
    { 
     // I'm fitting a parabola from t = 1 to t = 4 
     double[] t = new double[] {0, 1, 2, 3, 4, 5}; 
     double[] y = new double[] {0, 1, 4, 9, 16, 25}; 

     int noPoints = 6; 
     double[] tHat = linspace(1.0, 4.0, noPoints); 

     CatmullRomSpline csp = new CatmullRomSpline(t, y); 
     for(double value : tHat) 
     { 
      System.out.printf("y(t = %.4f) = %.4f\n", value, csp.getValueAt(value)); 
     } 
     /* Output 
      y(t = 1.0000) = 1.0000 
      y(t = 1.5000) = 2.2500 
      y(t = 2.0000) = 4.0000 
      y(t = 2.5000) = 6.2500 
      y(t = 3.0000) = 9.0000 
      y(t = 3.5000) = 12.2500 
      y(t = 4.0000) = 16.0000 
     */ 
    } 
    public static double[] linspace(double begin, double end, int noPoints) 
    { 
     double[] arr = new double[noPoints + 1]; 
     double delta = (end - begin)/noPoints; 
     for(int i = 0; i < noPoints; i++) 
     { 
      arr[i] = begin + i * delta; 
     } 
     arr[noPoints] = end; 
     return arr; 
    } 
} 
İlgili konular