I tried to make a evolution simulator. So I started with a creature first. But instead of going towards the food, this guy is sorta going front-back,front-back. So,what is the problem with this??? I have two modules in my code,one is the main,other is Think-made by me. Both of them are given below. Please see what problem is there. Main module=>
import turtle,random,Think,time
world=turtle.Screen()
world.setup(400,400)#O(0,0),X(180,0),X'(-185,0),Y(0,185),Y'(0,-180)
def growfood():
food=turtle.Turtle()
food.color("green")
food.shape("circle")
food.shapesize(0.4)
food.penup()
food.speed(0)
food.goto(random.randint(-185,180),random.randint(-180,185))
return food
class Creature:
body=None
brain=Think.neuron()
def __init__(self):
self.body=turtle.Turtle()
#self.body.penup()
self.body.color("blue")
self.body.shape("square")
self.body.shapesize(0.5)
def move(self,y,x,dely,delx):
self.body.goto(self.body.xcor()+x*5,self.body.ycor()+y*5)
ny=(food.ycor()-self.body.ycor())-dely
nx=(food.xcor()-self.body.xcor())-dely
self.brain.adjust(dely, delx, ny/5, nx/5, y, x)
def locatefood(self):
delx=food.xcor()-self.body.xcor()
dely=food.ycor()-self.body.ycor()
return dely,delx
def think(self):
dely,delx=self.locatefood()
y,x=self.brain.think(dely,delx)
print("(x,y)=("+str(x)+","+str(y)+")")
self.move(y,x,dely,delx)
crt=Creature()
food=growfood()
run=0
while run<120:
world.update()
crt.think()
if crt.body.distance(food)<15:
food=growfood()
time.sleep(1)
Think module=>
from math import tanh
from random import random
class neuron:
biasy,biasx=1,1
lr=1
weighty,weightx,weightby,weightbx=random(),random(),random(),random()
def adjust(self,dely,delx,ny,nx,y,x):
#adjust y
erry=ny-y
self.weighty+=erry*dely*self.lr
self.weightby+=erry*self.biasy*self.lr
#adjust x
errx=nx-x
self.weightx+=errx*delx*self.lr
self.weightbx+=erry*self.biasx*self.lr
def think(self,dely,delx):
y=dely*self.weighty+self.biasy*self.weightby
x=delx*self.weightx+self.biasx*self.weightbx
y=tanh(y)
print(y)
if y>0:
y=1
elif y<0:
y=-1
else:
y=0
x=tanh(x)
print(x)
if x>0:
x=1
elif x<0:
x=-1
else:
x=0
return y,x
Thank you : )
I see a couple of code issues, first there appears to be a typo here:
self.weightbx+=erry*self.biasx*self.lr
based on symmetry, I would have expected errx
, not erry
. The next problem I have with the code is this:
ny=(food.ycor()-self.body.ycor())-dely
nx=(food.xcor()-self.body.xcor())-dely
Besides the dely
vs. delx
symmetry problem, I would have expected you to strip the signs of these numbers and use the signs you calculated:
ny = abs(food.ycor() - self.body.ycor()) * dely
nx = abs(food.xcor() - self.body.xcor()) * delx
To try to get ahead of these symmetry issues, I've rewritten your code below to do vector math, when possible, rather than calculate individual coordinates. (This breaks down somewhat as the turtle Vec2D
multiplication operation is an inner product, and not simply a multiplication of coordinates.)
Think.py
from math import tanh, copysign
from random import random
from turtle import Vec2D
class neuron:
lr = 1
bias = Vec2D(1, 1)
weight = Vec2D(random(), random())
weightb = Vec2D(random(), random())
def adjust(self, delta, guess, position):
error = (guess - position) * self.lr
self.weight += Vec2D(error[0] * delta[0], error[1] * delta[1])
self.weightb += Vec2D(error[0] * self.bias[0], error[1] * self.bias[1])
def think(self, delta):
x = delta[0] * self.weight[0] + self.bias[0] * self.weightb[0]
y = delta[1] * self.weight[1] + self.bias[1] * self.weightb[1]
return Vec2D(copysign(1, tanh(x)), copysign(1, tanh(y)))
main program:
from turtle import Screen, Turtle, Vec2D
from random import randint
from Think import neuron
class Creature:
body = Turtle()
brain = neuron()
def __init__(self):
self.body.hideturtle()
self.body.color('blue')
self.body.shape('square')
self.body.shapesize(0.5)
#self.body.penup()
self.body.showturtle()
def move(self, position, delta):
self.body.goto(self.body.position() + position)
guess = self.locatefood()
guess = Vec2D(abs(guess[0]) * delta[0], abs(guess[1]) * delta[1])
self.brain.adjust(delta, guess, position)
def locatefood(self):
return food.position() - self.body.position()
def think(self):
delta = self.locatefood()
position = self.brain.think(delta)
self.move(position, delta)
def growfood(previous):
if previous: # don't waste food!
food = previous
food.hideturtle()
food.color('orange')
food.stamp()
else:
food = Turtle()
food.hideturtle()
food.shape('circle')
food.shapesize(0.4)
food.penup()
food.color('green')
food.goto(randint(-37, 36), randint(-36, 37))
food.showturtle()
return food
def seek():
global run, food
crt.think()
if crt.body.distance(food) < 2:
food = growfood(food)
if run > 0:
run -= 1
world.ontimer(seek, 1000) # milliseconds
world = Screen()
world.setup(400, 400)
world.setworldcoordinates(-40, -40, 40, 40) # scaled by 5
run = 120
food = growfood(None)
crt = Creature()
seek()
world.exitonclick()
My code might be wrongheaded simulation-wise, but is mainly to enlighten you about alternate techniques when working with the turtle library. E.g. using ontimer()
instead of sleep()
; using setworldcoordinates()
to build in an implicit scale factor rather than multiplying and dividing each time; resusing turtles as they are a global entity that don't get garbage collected.