2013-12-10 16 views
9

Ciao, voglio integrare una funzione da 0 a diversi limiti superiori (circa 1000). Ho scritto un pezzo di codice per farlo usando un ciclo for e aggiungendo ogni valore a un array vuoto. Tuttavia mi rendo conto che potrei rendere il codice più veloce eseguendo integrali più piccoli e aggiungendo il risultato integrale precedente a quello appena calcolato. Quindi farei lo stesso numero di integrali, ma su un intervallo più piccolo, quindi aggiungo semplicemente l'integrale precedente per ottenere l'integrale da 0 a quel limite superiore. Heres il mio codice in questo momento:Come rendere la mia integrazione Python più veloce?

import numpy as np        #importing all relevant modules and functions 
from scipy.integrate import quad 
import pylab as plt 
import datetime 
t0=datetime.datetime.now()      #initial time 
num=np.linspace(0,10,num=1000)     #setting up array of values for t 
Lt=np.array([])         #empty array that values for L(t) are appended to 
def L(t):          #defining function for L 
    return np.cos(2*np.pi*t) 
for g in num:         #setting up for loop to do integrals for L at the different values for t 
    Lval,x=quad(L,0,g)       #using the quad function to get the values for L. quad takes the function, where to start the integral from, where to end the integration 
    Lv=np.append(Lv,[Lval])      #appending the different values for L at different values for t 

Quali modifiche devo fare per fare la tecnica di ottimizzazione che ho suggerito?

+0

Dovrebbe essere chiamato Lv? Altrimenti Lv non viene inizializzato prima che venga chiamato il metodo append. – Moustache

risposta

5

Fondamentalmente, è necessario tenere traccia dei valori precedenti di Lval e g. 0 è un buon valore iniziale per entrambi, poiché vogliamo iniziare aggiungendo 0 al primo integrale e 0 è l'inizio dell'intervallo. È possibile sostituire il ciclo for con:

last, lastG = 0, 0 
for g in num: 
    Lval,x = quad(L, lastG, g) 
    last, lastG = last + Lval, g 
    Lv=np.append(Lv,[last]) 

Nel mio test, questo è stato notevolmente più veloce.

Come @askewchan sottolinea nei commenti, questo è ancora più veloce:

Lv = [] 
last, lastG = 0, 0 
for g in num: 
    Lval,x = quad(L, lastG, g) 
    last, lastG = last + Lval, g 
    Lv.append(last) 
Lv = np.array(Lv) 
+1

Bel trucco, più * noticamente * più veloce: P A proposito, puoi aumentare la velocità di un altro 25% circa iniziando con 'Lv = []', e alla fine del ciclo 'Lv.append (ultimo) ', e dopo il ciclo' Lv = np.array (Lv) '. – askewchan

+0

'Lv1' non è inizializzato. –

+0

@WarrenWeckesser: Oops, 'Lv1' dovrebbe essere' Lv'. Ho modificato la risposta. –

0

Usando questa funzione:

scipy.integrate.cumtrapz

sono stato in grado di ridurre i tempi al di sotto della precisione della macchina (molto piccola).

La funzione esegue esattamente ciò che si richiede in modo estremamente efficiente. Vedere documentazione per ulteriori informazioni: https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.integrate.cumtrapz.html

Il seguente codice, che riproduce la versione prima e poi la mia:

# Module Declarations 
import numpy as np        
from scipy.integrate import quad 
from scipy.integrate import cumtrapz 
import time 

# Initialise Time Array      
num=np.linspace(0,10,num=1000) 

# Your Method  
t0 = time.time()     
Lv=np.array([])         
def L(t):          
    return np.cos(2*np.pi*t) 
for g in num:         
    Lval,x=quad(L,0,g)       
    Lv=np.append(Lv,[Lval]) 
t1 = time.time() 
print(t1-t0) 

# My Method 
t2 = time.time() 
functionValues = L(num) 
Lv_Version2 = cumtrapz(functionValues, num, initial=0) 
t3 = time.time() 
print(t3-t2) 

che produce costantemente:

t1-t0 = O (0,1) secondi

t3-t2 = 0 secondi

Problemi correlati