Somma ponderata degli ultimi N numeri


19

Supponiamo di ricevere numeri in uno stream. Dopo aver ricevuto ciascun numero, è necessario calcolare una somma ponderata degli ultimi numeri, in cui i pesi sono sempre gli stessi, ma arbitrari.N

Quanto efficacemente può essere fatto se ci è permesso mantenere una struttura di dati per aiutare con il calcolo? Possiamo fare di meglio di , ovvero ricalcolare la somma ogni volta che viene ricevuto un numero?Θ(N)

Ad esempio: supponiamo che i pesi siano . A un certo punto abbiamo l'elenco degli ultimi numeri L_1 = \ langle a, b, c, d \ rangle> e la somma ponderata S_1 = w_1 * a + w_2 * b + w_3 * c + w_4 * d .W=w1,w2,w3,w4NL1=a,b,c,d>S1=w1a+w2b+w3c+w4d

Quando viene ricevuto un altro numero, e , aggiorniamo l'elenco per ottenere L2=b,c,d,e e dobbiamo calcolare S2=w1b+w2c+w3d+w4e .

Considerazione sull'uso di FFT Un caso speciale di questo problema sembra essere risolvibile in modo efficiente impiegando la trasformata di Fourier veloce. Qui, calcoliamo le somme pesate S in multipli di N . In altre parole, riceviamo N numeri e solo allora possiamo calcolare le corrispondenti N pesate. Per fare ciò, abbiamo bisogno N1 numeri passati N-1 (per i quali sono già state calcolate le somme) e N nuovi numeri, in totale numeri 2N1 .

Se questo vettore di numeri di input e il vettore di peso W definiscono i coefficienti dei polinomi P(x) e Q(x) , con coefficienti in Q invertiti, vediamo che il prodotto P(x)×Q(x) è un polinomio i cui coefficienti davanti a xN1 fino a x2N2 sono esattamente le somme ponderate che cerchiamo. Questi possono essere calcolati usando FFT in Θ(Nlog(N)) tempo, che ci dà una media di Θ(log(N)) tempo per numero di input.

Questa non è tuttavia una soluzione al problema come indicato, poiché è necessario che la somma ponderata sia calcolata in modo efficiente ogni volta che viene ricevuto un nuovo numero - non possiamo ritardare il calcolo.


Nota che puoi usare LaTeX qui.
Raffaello

Gli input provengono da una distribuzione nota? Hanno qualche utile proprietà matematica? In caso contrario, è improbabile che ciò sia possibile (a meno che qualcuno non sia in grado di trovare una forma chiusa ordinata che sia calcolabile in modo sublineare - certamente non riesco a trovarne una). Inoltre, le approssimazioni sono OK? Potrebbe essere una strada da percorrere se ti è utile.
RDN

I filtri FIR lo fanno, quindi il loro design sarà rilevante.
adrianN,

@RDN Ho posto questa domanda come una curiosità, non ho in mente un'applicazione pratica.
Ambroz Bizjak,

Risposte:


6

Ecco un'elaborazione del tuo approccio. Ogni iterazioni, usiamo l'algoritmo FFT per calcolare i valori della convoluzione nel tempo , supponendo che i valori successivi siano zero. In altre parole, stiamo calcolando dove sono i pesi (o i pesi inversi), è la sequenza di input, è l'ora corrente e per .m O ( n log n ) m n - 1 i = 0 w i a t - i + k ,mmO(nlogn)mw i n a i t a t = 0 t > t

Σio=0n-1wioun't-io+K,0Km-1,
wionun'iotun't'=0t'>t

Per ciascuna delle seguenti iterazioni, siamo in grado di calcolare la convoluzione richiesto nel tempo (la esima iterazione richiede tempo ). Quindi il tempo ammortizzato è . Questo è ridotto al minimo scegliendo , che fornisce un tempo di esecuzione ammortizzato di .O ( m ) i O ( i ) O ( m ) + O ( n log n / m ) m = mO(m)ioO(io)O(m)+O(nlogn/m) O(m=nlognO(nlogn)

Possiamo migliorare il tempo di esecuzione nel caso peggiore di suddividendo il calcolo in parti. Correggi e definisci Ogni dipende solo da input, quindi può essere calcolato nel tempo . Inoltre, dato per , possiamo calcolare la convoluzione nel tempo . Il piano quindi è di mantenere l'elenco Per ogni periodo dimbO(nlogn)mC T , p 2 m O ( m log m )

bT,p,o=i=0m1wpm+iaTmi+o,CT,p=bT,p,0,,bT,p,m1.
CT,p2mO(mlogm) 0 p n / m - 1 O ( n / m + mCt/mp,p0pn/m1C t / m - p , p ,O(n/m+m)m n / m O ( m log m ) O ( ( n / m 2 ) m log m ) = O ( ( n / m ) log m ) O ( ( n / m ) log m + m ) m =
Ct/mp,p,0pn/m1.
minput, dobbiamo aggiornare di questi. Ogni aggiornamento richiede tempo , quindi se distribuiamo questi aggiornamenti in modo uniforme, ogni input occuperà il lavoro . Insieme al calcolo della convoluzione stessa, la complessità temporale per input è . Scegliendo come prima, questo dà .n/mO(mlogm)O((n/m2)mlogm)=O((n/m)logm)O((n/m)logm+m) O(m=nlognO(nlogn)

Soluzione meravigliosa, grazie, non ero davvero sicuro che potesse essere fatto.
Ambroz Bizjak,

E funziona! Implementazione C: ideone.com/opuoMj
Ambroz Bizjak

Meh, mi mancava quell'ultimo bit di codice che in realtà lo fa interrompere il calcolo, risolto qui ideone.com/GRXMAZ .
Ambroz Bizjak,

Sulla mia macchina questo algoritmo inizia ad essere più veloce del semplice algoritmo a circa 17000 pesi. Per piccoli numeri di pesi è lento. Indice di riferimento: ideone.com/b7erxu
Ambroz Bizjak

Molto impressionante che tu l'abbia effettivamente implementato! Probabilmente vuoi ottimizzare oltre . La scelta è solo una guida approssimativa e potrebbe non essere ottimale. Hai provato a eseguire l'algoritmo con valori diversi di ? mm=nlognm
Yuval Filmus,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.