Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #106050 > unrolled thread
| Started by | Poul Riis <priisdk@gmail.com> |
|---|---|
| First post | 2016-03-30 04:17 -0700 |
| Last post | 2016-03-31 23:26 +0100 |
| Articles | 16 — 9 participants |
Back to article view | Back to comp.lang.python
sympy Poul Riis <priisdk@gmail.com> - 2016-03-30 04:17 -0700
Re: sympy Ben Finney <ben+python@benfinney.id.au> - 2016-03-30 22:29 +1100
Re: sympy Ned Batchelder <ned@nedbatchelder.com> - 2016-03-30 04:39 -0700
Re: sympy Steven D'Aprano <steve@pearwood.info> - 2016-03-30 23:56 +1100
Re: sympy Poul Riis <priisdk@gmail.com> - 2016-03-30 08:23 -0700
Re: sympy Robert Kern <robert.kern@gmail.com> - 2016-03-30 16:29 +0100
Re: sympy Steven D'Aprano <steve@pearwood.info> - 2016-03-31 02:59 +1100
Re: sympy Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-03-31 17:49 +1300
Re: sympy Poul Riis <priisdk@gmail.com> - 2016-03-30 23:51 -0700
Re: sympy Poul Riis <priisdk@gmail.com> - 2016-03-31 03:57 -0700
Re: sympy Peter Otten <__peter__@web.de> - 2016-03-31 16:55 +0200
Re: sympy Chris Angelico <rosuav@gmail.com> - 2016-04-01 04:05 +1100
Re: sympy Peter Otten <__peter__@web.de> - 2016-03-31 19:51 +0200
Re: sympy Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2016-03-31 19:59 +0100
Re: sympy Poul Riis <priisdk@gmail.com> - 2016-03-31 14:33 -0700
Re: sympy Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2016-03-31 23:26 +0100
| From | Poul Riis <priisdk@gmail.com> |
|---|---|
| Date | 2016-03-30 04:17 -0700 |
| Subject | sympy |
| Message-ID | <733f5f0d-9b4e-4023-897b-e1f2730c39cb@googlegroups.com> |
Is it possible to transfer results from sympy to 'normal' python.
In the case below I think my intention is clear enough but it does not work as intended. How can it be done?
Poul Riis
from sympy import *
x=Symbol('x')
ftext=diff(1/(x**2+1),x)
def f(t):
return ftext.subs(x,'t')
print(f(3))
[toc] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2016-03-30 22:29 +1100 |
| Message-ID | <mailman.194.1459337388.28225.python-list@python.org> |
| In reply to | #106050 |
Poul Riis <priisdk@gmail.com> writes: > Is it possible to transfer results from sympy to 'normal' python. Is Sympy not “normal Python”? What transfer are you intending? > In the case below I think my intention is clear enough but it does not > work as intended. How can it be done? First: no, your intention is not clear. Please write idiomatic Python: spaces around operators, names which describe the meaning. Follow the coding style guide PEP 8 <URL:https://www.python.org/dev/peps/pep-0008/>. Second: no, the intent is obscured because you are using ‘from sympy import *’. This clobbers the global namespace, making it much more difficult to tell which names come from a different namespace. Instead, do ‘import sympy’ and qualify names ‘sympy.Symbol’, etc. Third: if the code “does not work as intended”, then the answer can be no better than “change it until it works as intended”. If you want more detail, please provide more detail on what it *is* doing, and what you think it *should* do instead. -- \ “I bet one legend that keeps recurring throughout history, in | `\ every culture, is the story of Popeye.” —Jack Handey | _o__) | Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Ned Batchelder <ned@nedbatchelder.com> |
|---|---|
| Date | 2016-03-30 04:39 -0700 |
| Message-ID | <7a86698a-866f-4dc1-8ef7-80bde8afd6f6@googlegroups.com> |
| In reply to | #106050 |
On Wednesday, March 30, 2016 at 7:17:33 AM UTC-4, Poul Riis wrote:
> Is it possible to transfer results from sympy to 'normal' python.
Poul, welcome to the group.
> In the case below I think my intention is clear enough but it does not work as intended. How can it be done?
>
> from sympy import *
> x=Symbol('x')
> ftext=diff(1/(x**2+1),x)
>
> def f(t):
> return ftext.subs(x,'t')
>
> print(f(3))
You'd be surprised how hard it is to understand what someone else thinks
a small chunk of code should do. :)
Even if we can work out what this was meant to do, it will be easier to help
if you are explicit about the outcome you are getting, and how that differs
from the outcome you want.
--Ned.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2016-03-30 23:56 +1100 |
| Message-ID | <56fbcd01$0$1599$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #106050 |
On Wed, 30 Mar 2016 10:17 pm, Poul Riis wrote:
> Is it possible to transfer results from sympy to 'normal' python.
>
> In the case below I think my intention is clear enough but it does not
> work as intended. How can it be done?
How can what be done? Unfortunately, we're not able to read your mind. We
can read your code, and can see what your code does, but how are we
supposed to know what it is supposed to do?
> from sympy import *
> x=Symbol('x')
> ftext=diff(1/(x**2+1),x)
>
> def f(t):
> return ftext.subs(x,'t')
>
> print(f(3))
This code seems to work perfectly to me. You differentiate an expression,
then substitute the 'x' variable for 't':
-2*t/(t**2 + 1)**2
What were you expecting?
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Poul Riis <priisdk@gmail.com> |
|---|---|
| Date | 2016-03-30 08:23 -0700 |
| Message-ID | <99b7cf43-50ff-4de7-8de0-e324658682bf@googlegroups.com> |
| In reply to | #106064 |
What I intend to do is to let sympy find the derivative of some welldefined function and next define the foundation derivative as a normal function so that I can calculate numerical values or even make a graph.
[toc] | [prev] | [next] | [standalone]
| From | Robert Kern <robert.kern@gmail.com> |
|---|---|
| Date | 2016-03-30 16:29 +0100 |
| Message-ID | <mailman.212.1459351804.28225.python-list@python.org> |
| In reply to | #106083 |
On 2016-03-30 16:23, Poul Riis wrote: > What I intend to do is to let sympy find the derivative of some welldefined function and next define the foundation derivative as a normal function so that I can calculate numerical values or even make a graph. http://docs.sympy.org/dev/modules/utilities/lambdify.html#sympy.utilities.lambdify.lambdify -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2016-03-31 02:59 +1100 |
| Message-ID | <56fbf7e7$0$1591$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #106083 |
On Thu, 31 Mar 2016 02:23 am, Poul Riis wrote:
> What I intend to do is to let sympy find the derivative of some
> welldefined function and next define the foundation derivative as a normal
> function so that I can calculate numerical values or even make a graph.
I'm glad you explained what you *actually* wanted, because I was going to
guess that you wanted to evaluate the derivative at x = 3:
py> ftext.evalf(subs={x:3})
-0.0600000000000000
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2016-03-31 17:49 +1300 |
| Message-ID | <dm3oicFpmg4U1@mid.individual.net> |
| In reply to | #106090 |
Steven D'Aprano wrote:
> On Thu, 31 Mar 2016 02:23 am, Poul Riis wrote:
>
>>What I intend to do is to let sympy find the derivative of some
>>welldefined function and next define the foundation derivative as a normal
>>function
>
> py> ftext.evalf(subs={x:3})
> -0.0600000000000000
Given all that, it looks like you want
def f(t):
return ftext.evalf(subs={x:t})
--
Greg
[toc] | [prev] | [next] | [standalone]
| From | Poul Riis <priisdk@gmail.com> |
|---|---|
| Date | 2016-03-30 23:51 -0700 |
| Message-ID | <98f57610-bd25-4d00-b095-703360a79fa1@googlegroups.com> |
| In reply to | #106123 |
Den torsdag den 31. marts 2016 kl. 06.49.34 UTC+2 skrev Gregory Ewing:
> Steven D'Aprano wrote:
> > On Thu, 31 Mar 2016 02:23 am, Poul Riis wrote:
> >
> >>What I intend to do is to let sympy find the derivative of some
> >>welldefined function and next define the foundation derivative as a normal
> >>function
> >
> > py> ftext.evalf(subs={x:3})
> > -0.0600000000000000
>
> Given all that, it looks like you want
>
> def f(t):
> return ftext.evalf(subs={x:t})
>
> --
> Greg
Oh, yes, that works! Thank you!
Poul Riis
[toc] | [prev] | [next] | [standalone]
| From | Poul Riis <priisdk@gmail.com> |
|---|---|
| Date | 2016-03-31 03:57 -0700 |
| Message-ID | <244e1277-e105-4419-a449-7f2012c6d78e@googlegroups.com> |
| In reply to | #106090 |
Den onsdag den 30. marts 2016 kl. 17.59.49 UTC+2 skrev Steven D'Aprano:
> On Thu, 31 Mar 2016 02:23 am, Poul Riis wrote:
>
> > What I intend to do is to let sympy find the derivative of some
> > welldefined function and next define the foundation derivative as a normal
> > function so that I can calculate numerical values or even make a graph.
>
>
> I'm glad you explained what you *actually* wanted, because I was going to
> guess that you wanted to evaluate the derivative at x = 3:
>
>
> py> ftext.evalf(subs={x:3})
> -0.0600000000000000
>
>
>
> --
> Steven
... However, the sympy way seems to be about 70 times slower than using the derivative calculated 'by hand' (try the example below).
Can it be done in a more efficient way?
Poul Riis
from sympy import *
from time import *
x=Symbol('x')
ftext=diff(sin(x),x)
def fmsympy(t):
return ftext.evalf(subs={x:t})
def fm(t):
return cos(t)
nloop=10000
tstart=time()
# nloop evaluations with sympy
for i in range(0,nloop):
a=fmsympy(1)
dt1=time()-tstart
# nloop evaluations without sympy
tstart=time()
for i in range(0,nloop):
a=fm(1)
dt2=time()-tstart
print(nloop,' evaluations with sympy : dt1 =',dt1)
print(nloop,' evaluations without sympy: dt2 =',dt2)
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2016-03-31 16:55 +0200 |
| Message-ID | <mailman.264.1459436170.28225.python-list@python.org> |
| In reply to | #106144 |
Poul Riis wrote:
> Den onsdag den 30. marts 2016 kl. 17.59.49 UTC+2 skrev Steven D'Aprano:
>> On Thu, 31 Mar 2016 02:23 am, Poul Riis wrote:
>>
>> > What I intend to do is to let sympy find the derivative of some
>> > welldefined function and next define the foundation derivative as a
>> > normal function so that I can calculate numerical values or even make a
>> > graph.
>>
>>
>> I'm glad you explained what you *actually* wanted, because I was going to
>> guess that you wanted to evaluate the derivative at x = 3:
>>
>>
>> py> ftext.evalf(subs={x:3})
>> -0.0600000000000000
>>
>>
>>
>> --
>> Steven
>
> ... However, the sympy way seems to be about 70 times slower than using
> the derivative calculated 'by hand' (try the example below). Can it be
> done in a more efficient way?
Hm, the two functions fmsympy() and fm() do not return the same value:
$ python -i sympy_diff.py
10000 evaluations with sympy : dt1 = 0.7178411483764648
10000 evaluations without sympy: dt2 = 0.10177111625671387
>>> fm(42)
cos(42)
>>> fmsympy(42)
-0.399985314988351
What's the point of that benchmark?
> Poul Riis
>
>
>
> from sympy import *
> from time import *
> x=Symbol('x')
> ftext=diff(sin(x),x)
>
> def fmsympy(t):
> return ftext.evalf(subs={x:t})
>
> def fm(t):
> return cos(t)
>
> nloop=10000
> tstart=time()
> # nloop evaluations with sympy
> for i in range(0,nloop):
> a=fmsympy(1)
> dt1=time()-tstart
>
> # nloop evaluations without sympy
> tstart=time()
> for i in range(0,nloop):
> a=fm(1)
> dt2=time()-tstart
>
> print(nloop,' evaluations with sympy : dt1 =',dt1)
> print(nloop,' evaluations without sympy: dt2 =',dt2)
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-04-01 04:05 +1100 |
| Message-ID | <mailman.272.1459443911.28225.python-list@python.org> |
| In reply to | #106144 |
On Fri, Apr 1, 2016 at 1:55 AM, Peter Otten <__peter__@web.de> wrote: > Hm, the two functions fmsympy() and fm() do not return the same value: > > $ python -i sympy_diff.py > 10000 evaluations with sympy : dt1 = 0.7178411483764648 > 10000 evaluations without sympy: dt2 = 0.10177111625671387 >>>> fm(42) > cos(42) >>>> fmsympy(42) > -0.399985314988351 > Maybe not, but that's simply because one of them is completely evaluated. The cosine of 42 radians is indeed -0.4ish. >>> math.cos(42) -0.39998531498835127 ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2016-03-31 19:51 +0200 |
| Message-ID | <mailman.275.1459446733.28225.python-list@python.org> |
| In reply to | #106144 |
Chris Angelico wrote: > On Fri, Apr 1, 2016 at 1:55 AM, Peter Otten <__peter__@web.de> wrote: >> Hm, the two functions fmsympy() and fm() do not return the same value: >> >> $ python -i sympy_diff.py >> 10000 evaluations with sympy : dt1 = 0.7178411483764648 >> 10000 evaluations without sympy: dt2 = 0.10177111625671387 >>>>> fm(42) >> cos(42) >>>>> fmsympy(42) >> -0.399985314988351 >> > > Maybe not, but that's simply because one of them is completely > evaluated. The cosine of 42 radians is indeed -0.4ish. > >>>> math.cos(42) > -0.39998531498835127 My guess was that the OP fell into the trap that he himself carefully set up with the star import, and accidentally used sympy.cos() where he wanted to invoke math.cos(). The fix would actually increase the speed difference -- but first make it right, then, maybe, fast. Adding another storey to the tower of guesses, Robert Kern has probably already provided the answer ;)
[toc] | [prev] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2016-03-31 19:59 +0100 |
| Message-ID | <mailman.276.1459450793.28225.python-list@python.org> |
| In reply to | #106144 |
On 31 March 2016 at 11:57, Poul Riis <priisdk@gmail.com> wrote:
>
> ... However, the sympy way seems to be about 70 times slower than using the derivative calculated 'by hand' (try the example below).
> Can it be done in a more efficient way?
>
> Poul Riis
>
>
>
> from sympy import *
> from time import *
> x=Symbol('x')
> ftext=diff(sin(x),x)
>
> def fmsympy(t):
> return ftext.evalf(subs={x:t})
>
> def fm(t):
> return cos(t)
I think you have misunderstood what is going on here. Let's actually
try those two methods out:
$ isympy
IPython console for SymPy 0.7.5 (Python 2.7.9-64-bit) (ground types: gmpy)
These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
Documentation can be found at http://www.sympy.org
In [1]: ftext = diff(sin(x), x)
In [2]: ftext
Out[2]: cos(x)
In [3]: ftext.evalf(subs={x:1})
Out[3]: 0.540302305868140
In [4]: cos(1)
Out[4]: cos(1)
So the first version (your fmsympy) takes the symbolic expression
cos(x) represented as a sympy expression tree and substitutes 1 for x
(which requires walking the tree to look fo all occurrences of x).
Then it evaluates the result to 15 decimal digits of precision using
the pure Python mpmath multiprecision math library. To prove that it's
not really a float calculation let's increase the precision:
In [5]: ftext.evalf(subs={x:1}, n=100)
Out[5]: 0.5403023058681397174009366074429766037323104206179222276700972553811003947744717645179518560871830893
Your second version (fm) makes a sympy expression using the cos
function from sympy and the argument 1. This creates a symbolic sympy
expression cos(1) and returns that. It doesn't do any evaluation of
the expression to get the digits of the actual numeric answer.
So I'm not surprised that the two operations take different amounts of
time. One doesn't evaluate the expression and the other does using a
slow multiprecision library. Also note though that sympy uses a cache
to accelerate repeated calculations so if you time it doing the exact
same thing repeatedly in a loop then you may just be measuring
cache-hit performance for two different inputs rather than actual
evaluation time.
If you want to see one that's a lot faster use the cos function from
the math module:
In [9]: from math import cos
In [10]: cos(1)
Out[10]: 0.540302305868
This calculates cos(1) using IEEE 64-bit binary floating point
(Python's float type) with hardware acceleration from your processor's
FPU instructions. This should be a lot faster then either substituting
into symbolic expressions in sympy or evaluating trignometric
functions with mpmath.
Generally I would use sympy in order to derive the mathematical
expressions that I want to compute. However if I then want to evaluate
the expressions many times in a loop with different input numbers for
example then I would rewrite the expression without using sympy. Sympy
has code generation capabilities to automate this but you seemed to be
confused about basic sympy usage right now so I wouldn't recommend
them without knowing more about what you're trying to do.
--
Oscar
[toc] | [prev] | [next] | [standalone]
| From | Poul Riis <priisdk@gmail.com> |
|---|---|
| Date | 2016-03-31 14:33 -0700 |
| Message-ID | <9c8497d9-f158-4f94-9a9f-39d6cb63850c@googlegroups.com> |
| In reply to | #106050 |
Den onsdag den 30. marts 2016 kl. 13.17.33 UTC+2 skrev Poul Riis:
> Is it possible to transfer results from sympy to 'normal' python.
>
> In the case below I think my intention is clear enough but it does not work as intended. How can it be done?
>
> Poul Riis
>
>
>
>
> from sympy import *
> x=Symbol('x')
> ftext=diff(1/(x**2+1),x)
>
> def f(t):
> return ftext.subs(x,'t')
>
> print(f(3))
Well, cos(1) should have been cos(1.0) (which forces numerical evaluation, try example below).
I am just trying to implement one little thing that all CAS tools can do in a few lines, namely finding the derivative of a given function followed by evalution of numerical values, something like:
define(fm(x),diff(f(x),x))
fm(1.0)
Sympy can find the derivative, and once that has been completed I would expect that there is some way to find numerical values just as fast as if the derivative had been given 'by hand'. But how exactly?
Poul Riis
from sympy import *
from time import *
x=Symbol('x')
ftext=diff(sin(x),x)
def fmsympy(t):
return ftext.evalf(subs={x:t})
def fm(t):
return cos(t)
nloop=10000
tstart=time()
for i in range(0,nloop):
a=fmsympy(1)
dt1=time()-tstart
print(a)
tstart=time()
for i in range(0,nloop):
a=fm(1.0)
dt2=time()-tstart
print(a)
print(nloop,' evaluations with sympy : dt1 =',dt1)
print(nloop,' evaluations without sympy: dt2 =',dt2)
[toc] | [prev] | [next] | [standalone]
| From | Oscar Benjamin <oscar.j.benjamin@gmail.com> |
|---|---|
| Date | 2016-03-31 23:26 +0100 |
| Message-ID | <mailman.283.1459463216.28225.python-list@python.org> |
| In reply to | #106183 |
On 31 March 2016 at 22:33, Poul Riis <priisdk@gmail.com> wrote:
> Den onsdag den 30. marts 2016 kl. 13.17.33 UTC+2 skrev Poul Riis:
>> Is it possible to transfer results from sympy to 'normal' python.
>>
>> In the case below I think my intention is clear enough but it does not work as intended. How can it be done?
>>
>> Poul Riis
>>
>> from sympy import *
>> x=Symbol('x')
>> ftext=diff(1/(x**2+1),x)
>>
>> def f(t):
>> return ftext.subs(x,'t')
>>
>> print(f(3))
>
> Well, cos(1) should have been cos(1.0) (which forces numerical evaluation, try example below).
> I am just trying to implement one little thing that all CAS tools can do in a few lines, namely finding the derivative of a given function followed by evalution of numerical values, something like:
> define(fm(x),diff(f(x),x))
> fm(1.0)
>
> Sympy can find the derivative, and once that has been completed I would expect that there is some way to find numerical values just as fast as if the derivative had been given 'by hand'. But how exactly?
I assume that you're responding to me (even though your post is a
reply to yourself).
Robert Kern already answered this question earlier in the thread:
$ isympy
IPython console for SymPy 0.7.5 (Python 2.7.9-64-bit) (ground types: gmpy)
These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
Documentation can be found at http://www.sympy.org
In [1]: f = lambdify(x, sin(x).diff(x))
In [2]: f
Out[2]: <function numpy.<lambda>>
In [3]: f(1)
Out[3]: 0.540302305868
We can pull apart this function f returned here:
In [4]: import dis
In [5]: dis.dis(f)
1 0 LOAD_GLOBAL 0 (cos)
3 LOAD_FAST 0 (x)
6 CALL_FUNCTION 1
9 RETURN_VALUE
In [6]: f.func_globals['cos']
Out[6]: <function math.cos>
So the function f returned by lambdify uses math.cos which is the
64-bit float function I mentioned earlier (i.e. the faster one). You
can pass an int in and it will be coerced to float. You should find
that the performance of f is as good as lambda x: math.cos(x).
So lambdify takes an expression and a sequence of symbols and
generates a function whose arguments are substituted for the sequence
of symbols. The return value of the function is the result of
substituting the arguments for the symbols in the expression. I think
this is what you asked for.
--
Oscar
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web