简体   繁体   中英

Overriding the division operator when lambdifying symbolic expressions in sympy

I'm using Sympy to evaluate symbolic expressions provided by users, but the division operator isn't behaving like any other mathematical operator. When evaluating an expression on objects with overridden operators, I get the expected result for addition, subtraction, and multiplication, but not division. The code below illustrates my problem:

import sympy
import numpy

class NewMath(int):

    def __add__(self, other):
        print "Adding!"
        return

    def __sub__(self, other):
        print "Subtracting!"
        return

    def __mul__(self, other):
        print "Multiplying!"
        return

    def __div__(self, other):
        print "Dividing!"
        return

three = NewMath(3)
four = NewMath(4)

three + four
three - four
three * four
three / four

# Override sympys default math
func_map = {'+':NewMath.__add__,
            '/':NewMath.__div__}

lambda_args = [sympy.Symbol(arg) for arg in ['three', 'four']]

print "Now sympy math:"
lambda_addition = sympy.lambdify(lambda_args, sympy.Symbol('three') + sympy.Symbol('four'), modules=func_map)
lambda_addition(three, four)

lambda_subtraction = sympy.lambdify(lambda_args, sympy.Symbol('three')  - sympy.Symbol('four'), modules=func_map)
lambda_subtraction(three, four)

lambda_multiplucation = sympy.lambdify(lambda_args, sympy.Symbol('three')  * sympy.Symbol('four'), modules=func_map)
lambda_multiplucation(three, four)

lambda_division = sympy.lambdify(lambda_args, sympy.Symbol('three')  / sympy.Symbol('four'), modules=func_map)
lambda_division(three, four)

The output:

Adding!
Subtracting!
Multiplying!
Dividing!
Now sympy math:
Adding!
Subtracting!
Multiplying!
0.75

I've read the Sympy Docs and seen that the / operator is a common gotcha, but the docs just seem to indicate that division will default to integer division, I can't see anything that indicates / can't be overridden. You can see in my example I even attempted to use the modules argument to manually replace division with my custom operator, to no avail.

I've also seen that division in sympy is really just a power of -1 and multiplication , does this mean my cause is hopeless?

I'm using python 2.7 and sympy 1.0

Your cause is certainly not completely hopeless. Here are a few options to get you started.

First off, it seems as if you understand the difference between \\__div__ \\__truediv__ and \\__floordiv__ but if you didn't already, here is some python 2.7 documentation for them.

In python 2.7, overriding \\__div__ seems like it should do what you want, except for that sympy documentation you found about a/b being evaluated as a * b^(-1) . To get around that, you could also override the exponentiation operator.

I tried running your code in my python3 environment, changing all instances of print so they have parentheses and replacing all instances of div with truediv .

This isn't really a complete answer, but I can't post comments, so this is what you get!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM