pythonlinear-regressionturtle-graphicspython-turtleevolutionary-algorithm

Why is the creature in my evolution simulator acting dumb?


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 : )


Solution

  • 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.

    enter image description here