2009-08-03 6 views
7

Sto cercando una libreria java o un aiuto per scrivere la mia funzione di interpolazione. Cioè ho due matrici di doppi che sono potenzialmente di dimensioni diverse, ma sono ordinati. Devo essere in grado di fare una stima dei valori intermedi e inserirli in modo che entrambi gli array abbiano le stesse dimensioni. In effetti il ​​numero totale di punti che appaiono nell'interpolazione è la somma delle 2 dimensioni dell'array meno 1. L'intervallo di ciascun array deve rimanere lo stesso, tuttavia non è necessaria alcuna estrapolazione.Interpolazione su una matrice (o due)

es. a1 = [1, 4, 9, 16, 25, 36] e a2 = [6, 9, 14, 30]

i risultati potrebbero essere ad es.

a1 = [1, 2.25, 4, 6,25, 9, 12,25, 16, 25, 36] e a2 = [6, 6,5625, 7,25, 9, 10,0625, 11,25, 14, 25,25, 30]

questi esempi sono f(x) = x^2 and g(x) = x^2 + 5, tuttavia potrebbe facilmente essere stato qualsiasi polinomio - il punto è di essere in grado di stimare/approssimare la funzione dal set di dati abbastanza bene da fornire un'interpolazione abbastanza decente. Qui il valore x è solo l'indice dell'array di input. Nell'output solo i valori y sono importanti.

+0

La tua domanda è un po 'poco chiaro. Potresti darci un banale esempio concreto? – skaffman

+0

Ho modificato per mostrare un esempio, anche se non è necessariamente l'output che una funzione potrebbe/vorrebbe dare, ma penso che dimostri un output accettabile. – Robert

risposta

13

Le altre risposte forniscono interpolazioni lineari, che in realtà non funzionano per dati complessi non lineari. Si desidera un spline fit, (interpolazione spline), credo.

La spline adatta descrive regioni dei dati utilizzando una serie di punti di controllo dai dati, quindi applica un'interpolazione polinomiale tra punti di controllo. Più punti di controllo ti danno una vestibilità più precisa, meno un adattamento più generale. Le spline sono molto più precise di quelle lineari, più veloci da usare rispetto a un adattamento di regressione generale, meglio di un polinomio di alto ordine perché non farà cose pazze tra i punti di controllo.

Non riesco a ricordare i nomi dalla mia testa, ma ci sono alcune librerie di adattamento eccellenti in Java - Suggerisco di cercarne una piuttosto che scrivere la propria funzione.


** EDIT: Biblioteche che potrebbero essere utili: **

** Teoria/codice che potrebbe essere utile: **

  • applet Spline con codice: link
  • Arkan spline ferramenta per poli-linee a spline Bezier
  • Theory spline e alcuni matematica per il montaggio. Più matematica, meno codice, potrebbe aiutare se le librerie non lo fanno.
+0

Sì, questo è esattamente quello che sto cercando ... più precisamente in cosa e dove sono queste librerie. – Robert

+0

Ho aggiunto collegamenti ad alcune librerie e codice + teoria per lavorare con le spline se le librerie no. Non dimenticare di accettare la risposta se ti è utile! – BobMcGee

0

semplice interpolazione lineare può essere calcolata utilizzando qualcosa di simile:

Point2D interp1_lin(Point2D p1, Point2D p2, double x) { 
//Pre conditions 
assert p1.x<x; 
assert x<p2.x; 
//Calculate slope from p1 to p2 
double m = (p2.x-p1.x)/(p2.y-p1.y); 
//Calculate y position of x 
double y = (x-p1.x)*m+p1.y; 
//create new point 
return new Point2D.Double(x,y); 
} 

fa questo aiuto?

0

È necessario ottenere i valori x corrispondenti ai valori y. Altrimenti nessun algoritmo sarà in grado di determinare se [1, 16, 81] è x^2 per [1, 4, 9] o x^4 per [1, 2, 3]. Vuoi interpolare sei valori o nessuno?

E quindi, quando si assegnano i valori x, è possibile utilizzare una sorta di interpolazione (lineare, spline kubic, il nome) per approssimare i valori mancanti.

+0

ok, non ho pensato correttamente al mio esempio - supponiamo che ogni indice dell'array sia il valore x per l'input, quindi dopo l'interpolazione non ci interessa più il valore x. – Robert

2

Progettata per array di dati una dimensione

import java.util.ArrayList; 

public class Interpolator { 

public static Float CosineInterpolate(Float y1,Float y2,Float mu) 
{ 
    double mu2; 

    mu2 = (1.0f-Math.cos(mu*Math.PI))/2.0f; 
    Float f_mu2 = new Float(mu2); 
    return(y1*(1.0f-f_mu2)+y2*f_mu2); 
} 

public static Float LinearInterpolate(Float y1,Float y2,Float mu) 
{ 
    return(y1*(1-mu)+y2*mu); 
} 


public static Float[] Interpolate(Float[] a, String mode) { 

    // Check that have at least the very first and very last values non-null 
    if (!(a[0] != null && a[a.length-1] != null)) return null; 

    ArrayList<Integer> non_null_idx = new ArrayList<Integer>(); 
    ArrayList<Integer> steps = new ArrayList<Integer>(); 

    int step_cnt = 0; 
    for (int i=0; i<a.length; i++) 
    { 
     if (a[i] != null) 
     { 
      non_null_idx.add(i); 
      if (step_cnt != 0) { 
       steps.add(step_cnt); 
       System.err.println("aDDed step >> " + step_cnt); 
      } 
      step_cnt = 0; 
     } 
     else 
     { 
      step_cnt++; 
     } 
    } 

    Float f_start = null; 
    Float f_end = null; 
    Float f_step = null; 
    Float f_mu = null; 

    int i = 0; 
    while (i < a.length - 1) // Don't do anything for the very last element (which should never be null) 
    { 
     if (a[i] != null && non_null_idx.size() > 1 && steps.size() > 0) 
     { 
      f_start = a[non_null_idx.get(0)]; 
      f_end = a[non_null_idx.get(1)]; 
      f_step = new Float(1.0)/new Float(steps.get(0) + 1); 
      f_mu = f_step; 
      non_null_idx.remove(0); 
      steps.remove(0); 
     } 
     else if (a[i] == null) 
     { 
      if (mode.equalsIgnoreCase("cosine")) 
       a[i] = CosineInterpolate(f_start, f_end, f_mu); 
      else 
       a[i] = LinearInterpolate(f_start, f_end, f_mu); 
      f_mu += f_step; 
     } 
     i++; 
    } 

    return a; 
} 
} 

Non so se aiuta ... E 'molto veloce codificata, quindi se qualcuno ha un/modo più bello più performante a fare lo stesso , grazie per aver contribuito

USO:

input : Float[] a = {1.0f, null, null, 2.0f, null, null, null, 15.0f}; 

call : Interpolator.Interpolate(a, "Linear"); 

output : 1.0|1.3333333|1.6666667|2.0|5.25|8.5|11.75|15.0 
+0

restituisce un valore nullo. –

1

So che questa è una risposta vecchia, ma è il primo colpo di Google durante la ricerca di Java interpolazione. La risposta accettata fornisce alcuni link utili, ma JMSL deve essere acquistato e il sito Web JSpline + appare impreciso.

Apache Commons Math ha implementazioni di interpolazioni lineari e spline che appaiono semplici, funzionali e affidabili.

http://commons.apache.org/proper/commons-math/

0

versione leggera di matrice unidimensionale interpolatore lineare:

public static float[] interpolate(float[] data) { 
    int startIdx = -1; 
    float startValue = 0f; 
    float element; 
    for (int i = 0; i < data.length - 1; i++) { 
     element = data[i]; 
     if (element != 0f) { 
      if (startIdx != -1) { 
       doInterpolate(startValue, element, startIdx + 1, i - startIdx - 1, data); 
      } 
      startValue = element; 
      startIdx = i; 
     } 
    } 
    return data; 
} 

private static void doInterpolate(float start, float end, int startIdx, int count, float[] data) { 
    float delta = (end - start)/(count + 1); 
    for (int i = startIdx; i < startIdx + count; i++) { 
     data[i] = start + delta * (i - startIdx + 1); 
    } 
} 
0

essere molto attenti con spline-misura e vestibilità polinomiali. Questi due possono dare un comportamento assurdo che può far deragliare molti dei dati (quelli che si ritiene siano una rappresentazione dei).

Tutto ciò che utilizza derivati ​​(pendenze) di dati può essere totalmente deragliato.

La cosa migliore che si può fare è tracciare i dati, capire cosa sta facendo e solo la regressione in forma (lineare, polinomiale, log-log); una volta che lo hai fatto, dovresti tracciare il tuo adattamento sui dati originali e assicurarti di vedere un ragionevole accordo. Saltare questa fase di confronto è una pessima idea.

Alcuni set di dati non daranno accesso a polinomi, log-log, ecc .; se i tuoi punti di dati sono adeguatamente distribuiti sull'intervallo di dati, non c'è niente di sbagliato nell'interpolazione a tratti (lineare o polinomiale ecc.). Per battere un cavallo morto, se usi l'interpolazione a tratti, evita qualsiasi cosa utilizzi derivazioni/pendenze della tua interpolazione a tratti perché avrà discontinuità e farà sì che le cose si comportino male.