implicit definition of log

51 views
Skip to first unread message

Duane Nykamp

unread,
Sep 6, 2014, 2:50:38 PM9/6/14
to sy...@googlegroups.com
I really like the evaluate=False flag on parse_expr.  But, since log(0.1) automatically evaluates to a float, I'm trying to create an unevaluated version of log.  However, I'm getting strange results where log is implicitly defined. 

As shown below, once I define a function log that does nothing, sympy somehow implicitly defines it to be the usual log function.

Am I missing how this works or is this aberrant behavior?

My eventual plan is to have log.doit() return the original sympy function.

If I call the function something else, like llog, then I don't run into the behavior.  But, I'm not sure how to make printers display my llog function as log.

Thanks,
Duane



In [1]: from sympy import Function

In [2]: log
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-9a115ebc25a0> in <module>()
----> 1 log

NameError: name 'log' is not defined

In [3]: class log(Function):
   ...:     pass
   ...:

In [4]: log
Out[4]: __main__.log

In [5]: log(0.1)
Out[5]: -2.30258509299405

Aaron Meurer

unread,
Sep 6, 2014, 3:20:12 PM9/6/14
to sy...@googlegroups.com
SymPy automatically defines evaluation based on mpmath function names.
I think you can get around it by defining an empty _eval_evalf(self,
prec) function.

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/5df457b7-7ffc-4285-b9b5-b8ddce3f91ca%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Duane Nykamp

unread,
Sep 6, 2014, 4:09:56 PM9/6/14
to sy...@googlegroups.com
Perfect.  The following solution seems to work for me.  Thanks!

class log(Function):

    def _eval_evalf(self,prec):
        pass

    def doit(self, **hints):
        from sympy import log as sympy_log
        return sympy_log(self.args[0]).doit(**hints)

Aaron Meurer

unread,
Sep 6, 2014, 4:46:41 PM9/6/14
to sy...@googlegroups.com
Another option would be to name your class something different and
alias it to log (and also change the printers to print "log"). This
way is probably simpler, though, as you only have to override the one
evalf method rather than several printer methods.

Aaron Meurer
> https://groups.google.com/d/msgid/sympy/0957d959-bd5f-4327-872a-748a4f6c60c1%40googlegroups.com.

Duane Nykamp

unread,
Oct 2, 2014, 11:15:10 AM10/2/14
to sy...@googlegroups.com
By the way, the method I was using turned out to give problems.  Since .doit() returned the sympy log, I ended up having two different version of log in later expressions (depending on whether or not .doit() had been called), leading to strange results.

I found a better solution, simply setting _should_evalf to false.


from sympy import log as sympy_log
class log(sympy_log):
    @classmethod
    def _should_evalf(cls, arg):
        return -1
Reply all
Reply to author
Forward
0 new messages