subs with a string, how to make this work with inheritance? Change from 0.7.3 to 0.7.4.1 ?

25 views
Skip to first unread message

Robert

unread,
Jul 22, 2014, 12:53:14 PM7/22/14
to sy...@googlegroups.com
Hey everyone,

Let's say I defined my own sympy.Symbol called MySymbol2. For some reason subs using a string doesn't always work, but it works for sympy.Symbol.

This is version 0.7.4.1. I have a 0.7.3 example below that works fine. I see that the function fallback in core.py was changed.

from is not test on line 992 in 0.7.3:
if arg is not args[i]
to not equal test on line 1036 in 0.7.4.1:
if arg != args[i]:


    >>> class MySymbol2(sympy.Symbol): pass
    >>> expr = MySymbol2('A') * (MySymbol2('X') > 5)
    >>> print expr.subs({'X':10})
    A*(X > 5)

    >>> expr = sympy.Symbol('A') * (sympy.Symbol('X') > 5)
    >>> print expr.subs({'X':10})
    A*True


Sometimes the subs work fine. Below X and Y are both substituted for my MySymbol
    >>> expr = sympy.sympify('3*X + Y')
    >>> subsDic2 = {'X': MySymbol2('X'), 'Y': MySymbol2('Y')}
    >>> expr2 = expr.subs(subsDic2)
    >>> print [(i, type(i)) for i in expr2.atoms()]
    [(X, <class 'stats.tests.modelSymbolicTest.MySymbol2'>), (3, <class 'sympy.core.numbers.Integer'>), (Y, <class 'stats.tests.modelSymbolicTest.MySymbol2'>)]



I've tried a fix like:

class MySymbolWithNameEq(sympy.Symbol):
    def __eq__(self, other):
        if isinstance(other, sympy.Symbol):
            return self.name.__eq__(other.name)
        else:
            return sympy.Symbol.__eq__(self, other)


but that causes the subs on 3*X+Y to fail and my A*(X>5) still fails. Notice that not all the atoms are replaced. 

    >>> expr = MySymbolWithNameEq('A') * (MySymbolWithNameEq('X') > 5)
    >>> print expr.subs({'X':10})
    A*(X > 5)

    >>> subsDic3 = {'X': MySymbolWithNameEq('X'), 'Y': MySymbolWithNameEq('Y')}
    >>> expr = sympy.sympify('3*X + Y')
    >>> expr2 = expr.subs(subsDic3)
    >>> print [(i, type(i)) for i in expr2.atoms()]
    [(Y, <class 'stats.tests.modelSymbolicTest.MySymbolWithNameEq'>), (X, <class 'sympy.core.symbol.Symbol'>), (3, <class 'sympy.core.numbers.Integer'>)]

#on 0.7.3 the above works correctly
    >>> expr2 = expr.subs(subsDic3)
    >>> print [(i, type(i)) for i in expr2.atoms()]
    [(X, <class 'stats.tests.modelSymbolicTest.MySymbolWithNameEq'>), (3, <class 'sympy.core.numbers.Integer'>), (Y, <class 'stats.tests.modelSymbolicTest.MySymbolWithNameEq'>)]


Any idea how to inherit from sympy.Symbol while still getting string substitution to work reliably?


thanks,
Rob

Aaron Meurer

unread,
Jul 22, 2014, 1:01:31 PM7/22/14
to sy...@googlegroups.com
I would recommend not using strings. It's better to convert everything
to SymPy objects and only use those.

Even so, the real fix for this would be to add a call to sympify()
somewhere in the subs code. But you shouldn't rely on functions in
SymPy calling sympify(). Some do, but there will always be those that
don't.

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sympy+un...@googlegroups.com.
> To post to this group, send email to sy...@googlegroups.com.
> Visit this group at http://groups.google.com/group/sympy.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sympy/574d5d01-c0ed-4fd5-97f2-ac1ff7156697%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages