Nelle versioni precedenti (0.7.5 e precedenti), ufuncify
funzionava solo su matrici a dimensione singola per il primo argomento (non molto eccitante). A partire da 0.7.6 (non ancora rilasciato, ma dovrebbe essere in una settimana!) ufuncify
crea istanze istanze di numpy.ufunc
per impostazione predefinita (include codice C in numpy api). Il tuo codice sopra richiede solo una piccola modifica per farlo funzionare.
In [1]: import numpy as np
In [2]: from sympy import sin, cos, lambdify
In [3]: from sympy.abc import x,y,z
In [4]: from sympy.utilities.autowrap import ufuncify
In [5]: from sympy.printing.theanocode import theano_function
In [6]: xg, yg, zg = np.mgrid[0:1:50*1j, 0:1:50*1j, 0:1:50*1j]
In [7]: f = sym.sin(x)*sym.cos(y)*sym.sin(z)
In [8]: ufunc_f = ufuncify([x,y,z], f)
In [9]: theano_f = theano_function([x, y, z], f, dims={x: 3, y: 3, z: 3})
In [10]: lambda_f = lambdify([x, y, z], f)
In [11]: type(ufunc_f)
Out[11]: numpy.ufunc
In [12]: type(theano_f)
Out[12]: theano.compile.function_module.Function
In [13]: type(lambda_f)
Out[13]: function
In [14]: %timeit ufunc_f(xg, yg, zg)
10 loops, best of 3: 21 ms per loop
In [15]: %timeit theano_f(xg, yg, zg)
10 loops, best of 3: 20.7 ms per loop
In [16]: %timeit lambda_f(xg, yg, zg)
10 loops, best of 3: 22.3 ms per loop
ufuncify
e theano_function
sono comparabili, e leggermente superiore lambdify
per questa semplice espressione. La differenza è maggiore utilizzando l'espressione più complicato indicato di seguito:
In [17]: f = sin(x)*cos(y)*sin(z) + sin(4*(x - y**2*sin(z)))
In [18]: ufunc_f = ufuncify([x,y,z], f)
In [19]: theano_f = theano_function([x, y, z], f, dims={x: 3, y: 3, z: 3})
In [20]: lambda_f = lambdify([x, y, z], f)
In [21]: %timeit ufunc_f(xg, yg, zg)
10 loops, best of 3: 29.2 ms per loop
In [22]: %timeit theano_f(xg, yg, zg)
10 loops, best of 3: 29.2 ms per loop
In [23]: %timeit lambda_f(xg, yg, zg)
10 loops, best of 3: 42.1 ms per loop
Questo è molto veloce rispetto all'utilizzo della versione pitone, come vengono creati array intermedi, il ciclo viene attraversato ed il calcolo corse in C. Theano produce velocità equivalenti, dato che vengono compilate anche in codice nativo. Per le espressioni di grandi dimensioni che vedo quando si esegue multibody dynamics, ufuncify
(e il relativo autowrap
) eseguire in modo significativo più veloce di lambdify
. Non ho molta esperienza con theano, quindi non posso dire quanto bene sia il loro approccio in scala, ma suppongo che sarebbe simile.
Come ho detto sopra, questo è disponibile solo in sympy 0.7.6 e versioni successive. Dovrebbe essere rilasciato presto, ma fino ad allora è possibile prendere la fonte da github.Documenti su ufuncify
nuovo comportamento here
La documentazione 'ufuncify' afferma esplicitamente:' La funzione restituita può agire solo su un array alla volta, poiché solo il primo argomento accetta matrici come input. Sarai comunque costretto a chiudere la chiamata all'argomento 'ufuncify' in un ciclo double for. Questo * potrebbe * velocizzare alcune cose, ma dipende interamente dalle tue equazioni. –
Sì, hai ragione, speravo che ci potesse essere qualche trucco per farlo. Ad ogni modo, immagino che un ciclo double for sarà anche lento, ma ci proverò. C'è forse qualche alternativa a ufuncify? – jrsm