2016-06-26 21 views
3

In Sympy 0.7.6 hatte ich keine Probleme mit dem folgenden Code für die Module = 'Sympy' und die Module = 'numpy' Optionen. Jetzt mit sympy v0.1, die Auswertung mit Modulen = ‚numpy‘ erhöhen, um eine Zerodivisionerror:Fehler mit sympy.lambdify für stückweise Funktionen und numpy Modul

import sympy 

x, y = sympy.symbols(['x', 'y']) 
expr = sympy.Piecewise((1/x, y < -1), (x, y <= 1), (1/x, True)) 

f_sympy = sympy.lambdify([x, y], expr, modules='sympy') 
f_numpy = sympy.lambdify([x, y], expr, modules='numpy') 

print f_sympy(0, 1) # performs well 

print f_numpy(0, 1) # issue: ZeroDivisionError 

scheint, wie die stückweise definierten Funktionen, bevor die Bedingung auswerten mit Modulen = ‚numpy‘.

Meine Fragen sind:

Ist dieses Verhalten normal?

Wenn ja, warum, und wie man einen stückweisen Ausdruck definiert und so schnell wie mit numpy Modul ohne die sympy.lambdify Prozedur auswertet?

EDIT:

gefunden, dass die Lösung in meinem Fall ist Theanos:

import sympy 

x, y = sympy.symbols(['x', 'y']) 
f = sympy.Piecewise((1/x, y < -1), (x, y <= 1), (1/x, True)) 

from sympy.printing.theanocode import theano_function 
f_theano = theano_function([x, y], [f]) 

print f_theano(0, 1) # OK, return 0 

Antwort

2

Ich löschte meine andere Antwort (falls Sie es schon gesehen haben). Es gibt eine viel einfachere Lösung.

Der ZeroDivisionError kommt, weil der Lambda-Ausdruck ungefähr lambda x, y: select([less(y, -1),less_equal(y, 1),True], [1/x,x,1/x], default=nan) erzeugt. Das Problem ist, dass die Übergabe von x = 0 dazu führt, dass 1/0 von Python ausgewertet wird, was den Fehler auslöst.

Aber NumPy ist gut mit Teilen durch Null. Es wird eine Warnung ausgeben, aber ansonsten funktioniert es gut (es gibt inf), und in diesem Beispiel gibt es kein Problem, da die inf nicht tatsächlich verwendet wird.

So ist die Lösung, um die Eingabe zu lambdify als numpy Arrays zu wickeln, das heißt, statt

f_numpy(0, 1) 

Verwendung

f_numpy(array(0), array(1)) 

Es gibt eine SymPy issue diese Diskussion, wenn Sie interessiert sind.

+0

Vielen Dank. Das ist jetzt viel klarer für mich. Ich werde die 'numpy.array' Lösung versuchen. Für jetzt verwende ich diese Workaround, die ich erstellt, die "Lambdarepr" und (leider) "eval" ruft: https://gist.github.com/A-Falaize/ff2fafd5ab19f88c478f7494e340a619 Dies funktioniert für mich, ist aber nicht sehr ' Python '. Was sind die Nachteile einer solchen Lösung? – Toht

+0

Ich sehe nicht, wie das Lambdify des armen Mannes dieses Problem löst. Von dem, was ich sagen kann, tut alles, was deine Funktion macht, 'sympy.lambdify' auch, aber' sympy.lambdify' macht auch viel mehr, also würde ich empfehlen, es einfach zu benutzen. – asmeurer