Turtle Graphics are incompatible with gmpy

M

Mensanator

I hadn't noticed this before, but the overhaul of Turtle Graphics
dating
back to 2.6 has been broken as far as gmpy is concerned.

I hadn't noticed because I usually have tracing turned off (tracing
off
takes 3-4 seconds, tracing on takes 6-7 minutes).

In 3.1, tracing is now a screen attribute, not a turtle atribute.
I have no idea why

tooter = turtle.Turtle()
tooter.tracer(False)

doesn't give me an error (I thought silent errors were a bad thing).

Had to change to

tooter = turtle.Turtle()
tooter.screen.tracer(False) # tracer now a screen attribute

to turn tracing off in 3.1.

Naturally, having tracing on caused my program to crash. The 2.6
version
seemed to work, but only because turning off tracing as a turtle
attribute
works in 2.6.

So I turned it back on and it crashed too.

2.5 worked okay.

The reason is that code in turtle.py was chabged from

v2.5
if self._drawing:
if self._tracing:
dx = float(x1 - x0)
dy = float(y1 - y0)
distance = hypot(dx, dy)
nhops = int(distance)

to

v3.1
if self._speed and screen._tracing == 1:
diff = (end-start)
diffsq = (diff[0]*screen.xscale)**2 + (diff[1]
*screen.yscale)**2
nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)
*self._speed))

Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy
floating point). Otherwise, you get

Traceback (most recent call last):
File "K:\user_python26\turtle\turtle_xy_Py3.py", line 95, in
<module>
tooter.goto(the_coord)
File "C:\Python31\lib\turtle.py", line 1771, in goto
self._goto(Vec2D(*x))
File "C:\Python31\lib\turtle.py", line 3165, in _goto
nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
ValueError: mpq.pow fractional exponent, inexact-root

So when using gmpy, you have to convert the .mpz to int before calling
turtle
functions. (if tracing is on).

demo code (fixed code commented out)

import gmpy

## (even) hi----|
## |
## lo (odd)
## or
##
## (even) lo
## |
## |
## ----hi (odd)
##
##
##
##

import turtle

tooter = turtle.Turtle()

tooter.hideturtle()
tooter.speed('fast')
turtle.update()
# make tracer false and it works
#tooter.screen.tracer(False) # tracer now a screen attribute
tooter.penup()
tooter.color('black')

s = ['1','0']
while len(s[0])<10000:
s = [''.join(s), s[0]]


origin = [0,0]
if s[0] == '0':
tooter.goto(origin)
tooter.dot(1)
if s[1] == '0':
tooter.goto([1,0])
tooter.dot(1)

print(len(s[0]))

for i,j in enumerate(s[0]):
the_coord=[]
cur_root = gmpy.sqrt(i)
lo__root = gmpy.sqrt(i)**2
hi__root = ((gmpy.sqrt(i)+1)**2)
## cur_root = int(gmpy.sqrt(i))
## lo__root = int(gmpy.sqrt(i)**2)
## hi__root = int(((gmpy.sqrt(i)+1)**2))

if hi__root%2==0:
side = 'northeast'
else:
side = 'southwest'

elbow = (hi__root - lo__root)//2 + lo__root + 1

if i>= elbow:

side_len = i - elbow
elbow_plus = True
else:
side_len = elbow - i
elbow_plus = False

if side == 'northeast':
elbow_offset = [(gmpy.sqrt(elbow)-1)//2 +1,-((gmpy.sqrt(elbow)-1)//
2) +1]
else:
elbow_offset = [-((gmpy.sqrt(elbow)-1)//2 +1),((gmpy.sqrt
(elbow)-1)//2 +1)]
## if side == 'northeast':
## elbow_offset = [int((gmpy.sqrt(elbow)-1)//2 +1),-int(((gmpy.sqrt
(elbow)-1)//2) +1)]
## else:
## elbow_offset = [-int(((gmpy.sqrt(elbow)-1)//2 +1)),int
(((gmpy.sqrt(elbow)-1)//2 +1))]

elbow_coord = [origin[0]+elbow_offset[0],origin[1]+elbow_offset[1]]

if i != hi__root and i != lo__root:
if i == elbow:
the_coord = elbow_coord
else:
if elbow_plus:
if side == 'northeast':
the_coord = [elbow_coord[0]-side_len,elbow_coord[1]]
else:
the_coord = [elbow_coord[0]+side_len,elbow_coord[1]]
else:
if side == 'northeast':
the_coord = [elbow_coord[0],elbow_coord[1]+side_len]
else:
the_coord = [elbow_coord[0],elbow_coord[1]-side_len]
else:
if i % 2 == 0: # even square
n = gmpy.sqrt(i)//2 - 1
## n = int(gmpy.sqrt(i)//2) - 1
the_coord = [-n, -n-1]
else:
n = (gmpy.sqrt(i)-1)//2 - 1
## n = int((gmpy.sqrt(i)-1)//2) - 1
the_coord = [1+n, 1+n]
if j == '0':
tooter.goto(the_coord)
tooter.dot(2)
print('done')

turtle.update()
turtle.done()
print('done')
 
C

casevh

I hadn't noticed this before, but the overhaul of Turtle Graphics
dating
back to 2.6 has been broken as far as gmpy is concerned.
The reason is that code in turtle.py was chabged from

v2.5
        if self._drawing:
            if self._tracing:
                dx = float(x1 - x0)
                dy = float(y1 - y0)
                distance = hypot(dx, dy)
                nhops = int(distance)

to

v3.1
       if self._speed and screen._tracing == 1:
            diff = (end-start)
            diffsq = (diff[0]*screen.xscale)**2 + (diff[1]
*screen.yscale)**2
            nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)
*self._speed))

Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy
floating point). Otherwise, you get

Traceback (most recent call last):
  File "K:\user_python26\turtle\turtle_xy_Py3.py", line 95, in
<module>
    tooter.goto(the_coord)
  File "C:\Python31\lib\turtle.py", line 1771, in goto
    self._goto(Vec2D(*x))
  File "C:\Python31\lib\turtle.py", line 3165, in _goto
    nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
ValueError: mpq.pow fractional exponent, inexact-root
Warning: Completely untested fix ahead!

What happens if you change turtle.py to use

nhops=1+int((math.sqrt(diffsq)/(3*math.pow(1.1, self._speed)
*self._speed))

casevh
 
S

Steven D'Aprano

In 3.1, tracing is now a screen attribute, not a turtle atribute.
I have no idea why

tooter = turtle.Turtle()
tooter.tracer(False)

doesn't give me an error (I thought silent errors were a bad thing).

What makes it an error? Do you consider the following an error?
.... pass
....
Perhaps you mean, it's an API change you didn't know about, and you wish to
protest that Turtle Graphics made an incompatible API change without
telling you?

Naturally, having tracing on caused my program to crash.

It seg faulted or raised an exception?


[...]
Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy floating point). Otherwise, you get

How does diffsq get to be a mpf? Are gmpy floats supposed to be supported?
 
G

Gregor Lingl

Mensanator said:
I hadn't noticed this before, but the overhaul of Turtle Graphics
dating
back to 2.6 has been broken as far as gmpy is concerned.

I hadn't noticed because I usually have tracing turned off (tracing
off
takes 3-4 seconds, tracing on takes 6-7 minutes).

In 3.1, tracing is now a screen attribute, not a turtle atribute.
I have no idea why

tooter = turtle.Turtle()
tooter.tracer(False)

doesn't give me an error (I thought silent errors were a bad thing).

Hi,

on my machine I get:

Python 3.1 (r31:73574, Jun 26 2009, 20:21:35) [MSC v.1500 32 bit
(Intel)] on win32
Type "copyright", "credits" or "license()" for more information.Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
tooter.tracer(False)
AttributeError: 'Turtle' object has no attribute 'tracer'
I'd like to help with your problem but I'd much better be
able to analyze it, if I had a version of your script,
which works as you intended with Python 2.5 and the old
turtle module. Could you please post it?

(The one you posted below uses some commands of the
turtle 2.6 module which are not present in 2.5, so it
doesn't run with Python 2.5)

Regards,
Gregor

Had to change to

tooter = turtle.Turtle()
tooter.screen.tracer(False) # tracer now a screen attribute

to turn tracing off in 3.1.

Naturally, having tracing on caused my program to crash. The 2.6
version
seemed to work, but only because turning off tracing as a turtle
attribute
works in 2.6.

So I turned it back on and it crashed too.

2.5 worked okay.

The reason is that code in turtle.py was chabged from

v2.5
if self._drawing:
if self._tracing:
dx = float(x1 - x0)
dy = float(y1 - y0)
distance = hypot(dx, dy)
nhops = int(distance)

to

v3.1
if self._speed and screen._tracing == 1:
diff = (end-start)
diffsq = (diff[0]*screen.xscale)**2 + (diff[1]
*screen.yscale)**2
nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)
*self._speed))

Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy
floating point). Otherwise, you get

Traceback (most recent call last):
File "K:\user_python26\turtle\turtle_xy_Py3.py", line 95, in
<module>
tooter.goto(the_coord)
File "C:\Python31\lib\turtle.py", line 1771, in goto
self._goto(Vec2D(*x))
File "C:\Python31\lib\turtle.py", line 3165, in _goto
nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
ValueError: mpq.pow fractional exponent, inexact-root

So when using gmpy, you have to convert the .mpz to int before calling
turtle
functions. (if tracing is on).

demo code (fixed code commented out)

import gmpy

## (even) hi----|
## |
## lo (odd)
## or
##
## (even) lo
## |
## |
## ----hi (odd)
##
##
##
##

import turtle

tooter = turtle.Turtle()

tooter.hideturtle()
tooter.speed('fast')
turtle.update()
# make tracer false and it works
#tooter.screen.tracer(False) # tracer now a screen attribute
tooter.penup()
tooter.color('black')

s = ['1','0']
while len(s[0])<10000:
s = [''.join(s), s[0]]


origin = [0,0]
if s[0] == '0':
tooter.goto(origin)
tooter.dot(1)
if s[1] == '0':
tooter.goto([1,0])
tooter.dot(1)

print(len(s[0]))

for i,j in enumerate(s[0]):
the_coord=[]
cur_root = gmpy.sqrt(i)
lo__root = gmpy.sqrt(i)**2
hi__root = ((gmpy.sqrt(i)+1)**2)
## cur_root = int(gmpy.sqrt(i))
## lo__root = int(gmpy.sqrt(i)**2)
## hi__root = int(((gmpy.sqrt(i)+1)**2))

if hi__root%2==0:
side = 'northeast'
else:
side = 'southwest'

elbow = (hi__root - lo__root)//2 + lo__root + 1

if i>= elbow:

side_len = i - elbow
elbow_plus = True
else:
side_len = elbow - i
elbow_plus = False

if side == 'northeast':
elbow_offset = [(gmpy.sqrt(elbow)-1)//2 +1,-((gmpy.sqrt(elbow)-1)//
2) +1]
else:
elbow_offset = [-((gmpy.sqrt(elbow)-1)//2 +1),((gmpy.sqrt
(elbow)-1)//2 +1)]
## if side == 'northeast':
## elbow_offset = [int((gmpy.sqrt(elbow)-1)//2 +1),-int(((gmpy.sqrt
(elbow)-1)//2) +1)]
## else:
## elbow_offset = [-int(((gmpy.sqrt(elbow)-1)//2 +1)),int
(((gmpy.sqrt(elbow)-1)//2 +1))]

elbow_coord = [origin[0]+elbow_offset[0],origin[1]+elbow_offset[1]]

if i != hi__root and i != lo__root:
if i == elbow:
the_coord = elbow_coord
else:
if elbow_plus:
if side == 'northeast':
the_coord = [elbow_coord[0]-side_len,elbow_coord[1]]
else:
the_coord = [elbow_coord[0]+side_len,elbow_coord[1]]
else:
if side == 'northeast':
the_coord = [elbow_coord[0],elbow_coord[1]+side_len]
else:
the_coord = [elbow_coord[0],elbow_coord[1]-side_len]
else:
if i % 2 == 0: # even square
n = gmpy.sqrt(i)//2 - 1
## n = int(gmpy.sqrt(i)//2) - 1
the_coord = [-n, -n-1]
else:
n = (gmpy.sqrt(i)-1)//2 - 1
## n = int((gmpy.sqrt(i)-1)//2) - 1
the_coord = [1+n, 1+n]
if j == '0':
tooter.goto(the_coord)
tooter.dot(2)
print('done')

turtle.update()
turtle.done()
print('done')
 
G

Gregor Lingl

Steven said:
What makes it an error? Do you consider the following an error?

... pass
...

Perhaps you mean, it's an API change you didn't know about, and you wish to
protest that Turtle Graphics made an incompatible API change without
telling you?

It didn't form 2.5 to 2.6 (at least not intentionally). But with the
indroduction of the TurtleScreen class and the Screen class/object
(singleton) a few of the turtle methods were also implemented as screen
methods and as turtle methods declared deprecated (see docs of Python
2.6). These deprecated turtle methods do not occur as turtle methods any
more in Python 3.x.

Among them is the tracer method, which in fact does not control single
turtle objects but all the turtles on a given screen.

So there is an icompatibility beween 2.6 and 3.x

But as far as I have understood, this doesn't concern the problem
reported by mensator.

Regards,
Gregor

Naturally, having tracing on caused my program to crash.

It seg faulted or raised an exception?


[...]
Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy floating point). Otherwise, you get

How does diffsq get to be a mpf? Are gmpy floats supposed to be supported?
 
C

casevh

In 3.1, tracing is now a screen attribute, not a turtle atribute.
I have no idea why
  tooter = turtle.Turtle()
  tooter.tracer(False)
doesn't give me an error (I thought silent errors were a bad thing).

What makes it an error? Do you consider the following an error?

...     pass
...

Perhaps you mean, it's an API change you didn't know about, and you wish to
protest that Turtle Graphics made an incompatible API change without
telling you?
Naturally, having tracing on caused my program to crash.

It seg faulted or raised an exception?

[...]
Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy floating point). Otherwise, you get

How does diffsq get to be a mpf? Are gmpy floats supposed to be supported?

The root cause of the error is that GMP, the underlying library for
gmpy, provides only the basic floating point operations. gmpy
implements a very limited exponentiation function. Python's math
library will convert an mpf to a float automatically so I think the
revised calculation for nhops should work with either any numerical
type that supports __float__.

casevh
 
M

Mensanator

It didn't form 2.5 to 2.6 (at least not intentionally). But with the
indroduction of the TurtleScreen class and the Screen class/object
(singleton) a few of the turtle methods were also implemented as screen
methods and as turtle methods declared deprecated (see docs of Python
2.6). These deprecated turtle methods do not occur as turtle methods any
more in Python 3.x.

More info.

Yes, there is no tracer attribute...when the object is created.

But watch this (Python 3.1):
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
tooter.tracer
AttributeError: 'Turtle' object has no attribute 'tracer'<function tracer at 0x013E0ED0>

Now, after setting hide, speed, update, a tracer exists.
Is that supposed to happen? That explains why there was no error
when I set the turtle attribute instead of the screen attribute.
And, of course, setting the turtle attribute accomplishes nothing,
as actual tracing is controlled by the screen attribute as you say.
Among them is the tracer method, which in fact does not control single
turtle objects but all the turtles on a given screen.

So there is an icompatibility beween 2.6 and 3.x

But as far as I have understood, this doesn't concern the problem
reported by mensator.

Only that the problem is hidden when tracing is off, as the nhops
variable is never evaluated when trace is off.
 
G

Gregor Lingl

Mensanator said:
More info.

Yes, there is no tracer attribute...when the object is created.

But watch this (Python 3.1):

Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
tooter.tracer
AttributeError: 'Turtle' object has no attribute 'tracer'
<function tracer at 0x013E0ED0>

Now, after setting hide, speed, update, a tracer exists.
No,
Help on function tracer in module turtle:

tracer(n=None, delay=None)
Turns turtle animation on/off and set delay for update drawings.

Optional arguments:
n -- nonnegative integer
delay -- nonnegative integer

If n is given, only each n-th regular screen update is really
performed.
(Can be used to accelerate the drawing of complex graphics.)
Second arguments sets delay value.)

Example: fd(dist)
rt(90)
dist += 2

The reason for this is, that the turtle module (the new one as well as
the old one) has a vers special design: The methods of class Turtle are
also available as functions (which are in fact methods calls of an
anonymous turtle). The same holds for the methods of TurtleScreen.

The intention behind this design is that you can use the module in an
OOP way as well as with procedural programming (especially for beginners).

When using objects I normally use

from turtle import Turtle, Screen
screen = Screen()
# that creates singleton object, the screen the turtle acts on
and I create as many turtles as I need from the Turtle class

So turtle.tracer() doesn't make sense anymore

Is that supposed to happen? That explains why there was no error
when I set the turtle attribute instead of the screen attribute.

You do not 'set the turtle attribute', you call the tracer function of
the turtle module
And, of course, setting the turtle attribute accomplishes nothing,
as actual tracing is controlled by the screen attribute as you say.


Only that the problem is hidden when tracing is off, as the nhops
variable is never evaluated when trace is off.

Nevertheless I'd like to see a working Python 2.5 version of your script.

Regards,
Gregor
 
M

Mensanator

What makes it an error? Do you consider the following an error?


...     pass
...

Come on, even _I_ know this:
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
t.tracer
AttributeError: 'Test' object has no attribute 'tracer'
False



Perhaps you mean, it's an API change you didn't know about, and you wish to
protest that Turtle Graphics made an incompatible API change without
telling you?

What does this mean?
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
tooter.tracer
AttributeError: 'Turtle' object has no attribute 'tracer'<function tracer at 0x013E0ED0>

How did the tracer attribute appear out of thin air?
And more importantly, why, if has been deprecated and
dropped from 3.x?
It seg faulted or raised an exception?

Why did you snip it? Should I not refer to this as a crash?

Traceback (most recent call last):
File "K:\user_python26\turtle\turtle_xy_Py3.py", line 95, in
<module>
tooter.goto(the_coord)
File "C:\Python31\lib\turtle.py", line 1771, in goto
self._goto(Vec2D(*x))
File "C:\Python31\lib\turtle.py", line 3165, in _goto
nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
ValueError: mpq.pow fractional exponent, inexact-root
[...]
Unfortunately, that calculation of nhops is illegal if diffsq is
an .mpf (gmpy floating point). Otherwise, you get

How does diffsq get to be a mpf?

No idea. I neglected to mention I'm using the new gmpy 1.10.
Don't know if that has any bearing.
Are gmpy floats supposed to be supported?

Apparently not, as gmpy has only limited exponential capability.
Looks like I need to change turtle.py to use math.sqrt(diffsq)
or float(diffsq)**0.5. Or not pass turtle.py any .mpz since it
can't handle them.
 
W

Wolfram Hinderer

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    tooter.tracer
AttributeError: 'Turtle' object has no attribute 'tracer'>>> tooter.hideturtle()

<function tracer at 0x013E0ED0>

How did the tracer attribute appear out of thin air?

You seem to confuse the "tooter" Turtle object and the "turtle" module
when talking about "the tracer attribute".
 
E

Ethan Furman

Mensanator wrote:

What does this mean?



Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
tooter.tracer
AttributeError: 'Turtle' object has no attribute 'tracer'


<function tracer at 0x013E0ED0>

How did the tracer attribute appear out of thin air?

Perhaps I am missing something (wouldn't surprise me!) but it seems that
the first time you are looking for a tracer on 'tooter', and the second
time you are looking for a tracer on 'turtle'. After *turtle.tracer*
succeeds, does *tooter.tracer*?

~Ethan~
 
M

Mensanator

Mensanator wrote:

<snippers galore>










Perhaps I am missing something (wouldn't surprise me!) but it seems that
the first time you are looking for a tracer on 'tooter', and the second
time you are looking for a tracer on 'turtle'.  

Duh. I could have looked at that from now til the sun don't shine and
not seen it. And I even retyped it, no cut/paste.
After *turtle.tracer*
succeeds, does *tooter.tracer*?

No, that was my mistake. Too late now as the record is gone, but I
could have sworn I had the math exception first. That's what made
me go realize the tracing wasn't off which led me to add .screen.

Sounds like I should have gotten the attribute error first.

Maybe I did and am mis-remembering it. Usually, I don't start keeping
notes at first because I'm not expecting failure.
 
M

Mensanator

Mensanator schrieb:










No,

Yeah, I mistyped my example, sorry about that. I thought sure
it was the math error that lead me to the tracer issue, but that
might have been a mistake.
Nevertheless I'd like to see a working Python 2.5 version of your script.

I've commented out the parts that v2.5 doesn't have.
So the pen is still down and I have no .dot function,
but the gotos appear to still work as evidenced by
the large black square it now draws.

With tracing on in 2.5, I see the turtle move around
the square. With tracing off, I still the the square
outined, but without a turtle and much faster.

With 3.1, the screen is completely blank for 3-4 seconds and appears
all at once when it's done.

import gmpy

## (even) hi----|
## |
## lo (odd)
## or
##
## (even) lo
## |
## |
## ----hi (odd)
##
##
##
##

import turtle

tooter = turtle.Turtle()

#tooter.hideturtle()
tooter.speed('fast')
#turtle.update()
tooter.tracer(False)
#tooter.penup()
tooter.color('black')

s = ['1','0']
while len(s[0])<10000:
s = [''.join(s), s[0]]


origin = [0,0]
if s[0] == '0':
tooter.goto(origin)
#tooter.dot(1)
if s[1] == '0':
tooter.goto([1,0])
#tooter.dot(1)

print len(s[0])

for i,j in enumerate(s[0]):
the_coord=[]
cur_root = gmpy.sqrt(i)
lo__root = gmpy.sqrt(i)**2
hi__root = (gmpy.sqrt(i)+1)**2

if hi__root%2==0:
side = 'northeast'
else:
side = 'southwest'

elbow = (hi__root - lo__root)/2 + lo__root + 1

if i>= elbow:
side_len = i - elbow
elbow_plus = True
else:
side_len = elbow - i
elbow_plus = False

if side == 'northeast':
elbow_offset = [(gmpy.sqrt(elbow)-1)/2 +1,-((gmpy.sqrt(elbow)-1)/2
+1)]
else:
elbow_offset = [-((gmpy.sqrt(elbow)-1)/2 +1),((gmpy.sqrt(elbow)-1)/
2 +1)]

elbow_coord = [origin[0]+elbow_offset[0],origin[1]+elbow_offset[1]]

if i != hi__root and i != lo__root:
if i == elbow:
the_coord = elbow_coord
else:
if elbow_plus:
if side == 'northeast':
the_coord = [elbow_coord[0]-side_len,elbow_coord[1]]
else:
the_coord = [elbow_coord[0]+side_len,elbow_coord[1]]
else:
if side == 'northeast':
the_coord = [elbow_coord[0],elbow_coord[1]+side_len]
else:
the_coord = [elbow_coord[0],elbow_coord[1]-side_len]
else:
if i % 2 == 0: # even square
n = gmpy.sqrt(i)/2 - 1
the_coord = [-n, -n-1]
else:
n = (gmpy.sqrt(i)-1)/2 - 1
the_coord = [1+n, 1+n]
if j == '0':
tooter.goto(the_coord)
#tooter.dot(2)
print 'done'

#turtle.update()
turtle.done()
print 'done'
 
M

Mensanator

I fixed this to produce the actual image I'm looking
for instead of that stupid black square. All I did was
use up() & dowm() in place of penup(), pendown() and
replace dot(2) with forward(1).

I'll be posting a followup report later.


import gmpy

## (even) hi----|
## |
## lo (odd)
## or
##
## (even) lo
## |
## |
## ----hi (odd)
##
##
##
##

import turtle

tooter = turtle.Turtle()

#tooter.hideturtle()
tooter.speed('fast')
#turtle.update()
tooter.tracer(False)
#tooter.penup()
tooter.up()
tooter.color('black')

s = ['1','0']
while len(s[0])<10000:
s = [''.join(s), s[0]]


origin = [0,0]
if s[0] == '0':
tooter.goto(origin)
#tooter.dot(1)
tooter.down()
tooter.forward(1)
tooter.up()
if s[1] == '0':
tooter.goto([1,0])
#tooter.dot(1)
tooter.down()
tooter.forward(1)
tooter.up()

print len(s[0])

for i,j in enumerate(s[0]):
the_coord=[]
cur_root = gmpy.sqrt(i)
lo__root = gmpy.sqrt(i)**2
hi__root = (gmpy.sqrt(i)+1)**2

if hi__root%2==0:
side = 'northeast'
else:
side = 'southwest'

elbow = (hi__root - lo__root)/2 + lo__root + 1

if i>= elbow:
side_len = i - elbow
elbow_plus = True
else:
side_len = elbow - i
elbow_plus = False

if side == 'northeast':
elbow_offset = [(gmpy.sqrt(elbow)-1)/2 +1,-((gmpy.sqrt(elbow)-1)/2
+1)]
else:
elbow_offset = [-((gmpy.sqrt(elbow)-1)/2 +1),((gmpy.sqrt(elbow)-1)/
2 +1)]

elbow_coord = [origin[0]+elbow_offset[0],origin[1]+elbow_offset[1]]

if i != hi__root and i != lo__root:
if i == elbow:
the_coord = elbow_coord
else:
if elbow_plus:
if side == 'northeast':
the_coord = [elbow_coord[0]-side_len,elbow_coord[1]]
else:
the_coord = [elbow_coord[0]+side_len,elbow_coord[1]]
else:
if side == 'northeast':
the_coord = [elbow_coord[0],elbow_coord[1]+side_len]
else:
the_coord = [elbow_coord[0],elbow_coord[1]-side_len]
else:
if i % 2 == 0: # even square
n = gmpy.sqrt(i)/2 - 1
the_coord = [-n, -n-1]
else:
n = (gmpy.sqrt(i)-1)/2 - 1
the_coord = [1+n, 1+n]
if j == '0':
tooter.goto(the_coord)
#tooter.dot(2)
tooter.down()
tooter.forward(1)
tooter.up()
print 'done'

#turtle.update()
turtle.done()
print 'done'
 
G

Gregor Lingl

Mensanator said:

Hi Mansanator,

Thanks for that thorough investigations.
I hope I'll soon find time to study it in detail.

I've just one idea, but I don't know if you might
be intersted in it or if it's rewarding at all:

What would be the results when using the old turtle
module with Python 3.1 (it will certainly not run
out of the box, but perhaps 2to3 might do it?)

That would clarify the question if there is some
impact of new division or some changes in Tkinter.

Best regards,
Gregor
 
M

Mensanator

Hi Mansanator,

Thanks for that thorough investigations.
I hope I'll soon find time to study it in detail.

I've just one idea, but I don't know if you might
be intersted in it or if it's rewarding at all:

Sure, not tonight, of course, but I can give it try.
What would be the results when using the old turtle
module with Python 3.1 (it will certainly not run
out of the box, but perhaps 2to3 might do it?)

I would just need to copy turtle.py to 3.1 Lib (renamed,
of course)?
That would clarify the question if there is some
impact of new division or some changes in Tkinter.

I had a quick glance through the code. Not too many divisions
and most of them seemd to already be forcing float division
by constructs such as mutiplying by 1.0 (which I assume isn't
strictly neccessary as long as / and // are used correctly.

It seemed a lot of floats were used in the 2.5 code as I saw
such stuff as int(difference), so I really don't know why
..mpz would be a problem since they are integers also and a
Python int ought to be the same thing when coerced to a float
(at least in the range used by Turtle graphics.
 
M

Mensanator

Bad
I ran the 2.5 turtle.py through the 2to3 refactorer but the
result would not run in 3.1, some kind of type mismatch between
ints and NoneType. So I set it aside.

Good
I tracked down the actual cause of the image discrepencies in my
report.

http://www.mensanator.com/mensanator/PythonTurtle/turtle.htm

These are completely bogus as it turns out. I had thought I was
essentially executing the same code (aside from changing 3.1
turtle functions that don't exist in 2.5 to their equivalent).

But in my mucking about tracking down the gmpy problem, a bug
crept in when I converted back from Python ints

if side == 'northeast':
elbow_offset = [int((gmpy.sqrt(elbow)-1)//2 +1),
-int(((gmpy.sqrt(elbow)-1)//2) +1)]
else:
elbow_offset = [-int(((gmpy.sqrt(elbow)-1)//2 +1)),
int(((gmpy.sqrt(elbow)-1)//2 +1))]

to gmpy ints.

if side == 'northeast':
elbow_offset = [(gmpy.sqrt(elbow)-1)//2 +1,
-((gmpy.sqrt(elbow)-1)//2) +1]
else:
elbow_offset = [-((gmpy.sqrt(elbow)-1)//2 +1),
((gmpy.sqrt(elbow)-1)//2 +1)]

A ")" is mislocated in -((gmpy.sqrt(elbow)-1)//2) +1], the one
after "//2" should have been placed after the "+1". There were
still three matching sets, but the +1 was now happening after
the negation instead or prior to it. And, of course, this lead
to discrepencies in the calls to the turtle goto function.
And, luckily, the code chain for 2.5 originated from the version
prior to the introduction of this error, otherwise, if the same
error was in both, the images would have been identicle albeit
wrong.

So it looks like there is NO practical difference between the
2.5 algorithm and the 3.1 algorithm. I'm no longer going to try
to get the 2.5 turtle.py to work in 3.1.

And with the nhops calculation changed to

nhops = 1+int((float(diffsq)**0.5)/(3*(1.1**self._speed)
*self._speed))

it no longer crashes in trace mode.

This was probably originally provoked by gmpy 1.10 and probably
isn't a problem in 2.6 with gmpy 1.04. I had upgraded my 2.6 gmpy
to 1.10 where it also crashed. I may have run the test code in
2.6 when I had 1.04 installed but it's unlikely I would have done
so with tracing on since it's 100 times slower. But I expect it
would not have failed due to this:

<quote>
Changes in gmpy 1.10

Number conversion rules have changed.
-------------------------------------
The arguments in operations involving mixed types are converted
using the following rules:

Integer --> Rational --> Floating-point
'int' 'Fraction' 'float'
'long' 'mpq' 'Decimal'
'mpz' 'mpf'

Old behavior:
mpz(1) + float(1.2) --> float(2.2)
mpz(1) + Decimal('1.2') --> mpz(2)

New behavior:
mpz(1) + float(1.2) --> mpf(2.2)
mpz(1) + Decimal('1.2') --> mpf(2.2)
</quote>

Apparently, as I painfully found out, that rule change can cause
applications to fail due to an mpf result from a mixed type function
instead of a float when they subsequently use fractional
exponentiation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top