how can I get better performance here? - python

I am working on a project to visualize the game of life and it's different variations.
Smoothlife is the most complicated, I am not quit sure if I am doing it 100% right, but however any suggestions to increase the performance here??
what about FFT and kernel convolution any one who knows the proper way to create the kernel??
attaching a link to the article of smooth life
https://arxiv.org/pdf/1111.1567.pdf
here's a version implemented by Sean Murhpy, but can't really get my head around the math.
https://github.com/duckythescientist/SmoothLife
from cmath import sqrt
from concurrent.futures import thread
import os
import numpy as np
import threading
from turtle import shape
class SmoothL:
def __init__(self,width, height, inner_radius=2, outer_radius=10):
self.width = width
self.height = height
self.inner = inner_radius
self.outer = outer_radius
self.game_field = np.zeros(shape=(self.width, self.height))
self.game_field_next = np.zeros(shape=(self.width, self.height))
self.inner_neigh = np.zeros(shape=(self.width, self.height))
self.outer_neigh = np.zeros(shape=(self.width, self.height))
self.b1 = 0.278
self.b2 = 0.365
self.d1 = 0.267
self.d2 = 0.445
self.n = 0.032
self.m = 0.2
def create_cells(self, new_cells, age):
for i in range(new_cells):
x = np.random.randint(0, self.width - self.outer)
y = np.random.randint(0, self.height - self.outer)
self.game_field[x:x + self.outer, y:y + self.outer] = age
def sigmaoid_1(self, x, a):
return 1.0 / (1.0 + np.exp(-4.0 * (x - a) / self.m))
def sigmaoid_2(self, x, a, b):
return self.sigmaoid_1(x, a) * (1.0 - self.sigmaoid_1(x, b))
def sigmaoid_m(self, x, y, m):
return x * (1.0-self.sigmaoid_1(m, 0.5)) + y * self.sigmaoid_1(m, 0.5)
def sigmaoid_s(self, n, m):
return self.sigmaoid_2(n, self.sigmaoid_m(self.b1, self.d1, m), self.sigmaoid_m(self.b2, self.d2, m))
def get_neighbours(self,x,y):
sum_outer = 0
count_outer = 0
sum_inner= 0
count_inner = 0
for k in range(-self.outer,self.outer+1):
for h in range(-self.outer,self.outer+1):
if 0<=x+k<self.width and 0<=y+h<self.height:
data=self.game_field[x+k][y+h]
if (float)(np.sqrt(k**2 + h**2))<=self.outer:
count_inner+=1
sum_inner+=data
if (float)(np.sqrt(k**2 + h**2))>self.inner:
count_outer+=1
sum_outer+=data
self.game_field_next[x][y]=np.clip(self.sigmaoid_s(sum_outer/count_outer,sum_inner/count_inner),0,1)
def iterate_all(self,min_x,max_x,min_y,max_y):
for i in range(min_x,max_x+1):
for j in range(min_y,max_y+1):
self.get_neighbours(i,j)
def result(self,min_x,max_x,min_y,max_y):
for i in range(min_x,max_x+1):
for j in range(min_y,max_y+1):
self.game_field[i][j]
def next(self):
threads= []
y_range=(int)(self.height/10)
min_y=0
max_y=y_range-1
x_range=(int)(self.width/10)
min_x=0
max_x=x_range-1
for _ in range(10):
min_y=0
max_y=y_range-1
for _ in range(10):
t=threading.Thread(target=self.iterate_all,args=[min_x,max_x,min_y,max_y])
t.start()
threads.append(t)
min_y+=y_range
max_y+=y_range
min_x+=x_range
max_x+=x_range
for thread in threads:
thread.join()
threads.clear()
self.game_field=self.game_field_next
return self.game_field

Related

planets created from 1d perlin noise terrain look weird

i am trying to make planets using pyglet but they end up looking like stars result
here is my code
also i need a way to convert a batch to a sprite (to move it easily)
import pyglet
from pyglet import shapes
import opensimplex
import math
import time
brtd = 0
######## planets###########
class planetobj():
def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home never will thy become infected with the virus that has a closedcure"):
self.seed = seed
self.age = age
self.position = position
self.color = color
self.name = name
self.description = description
def gplanet(self,size):
opensimplex.seed(self.seed)
done = 0
xc = 0
c = 0
self.terrain = []
start = opensimplex.noise2(x=0, y=self.age)
while (done == 0 or xc < 50) and not xc > 100 :
xc = xc + 1
c = c + size
value = opensimplex.noise2(x=xc, y=self.age)
self.terrain.append(value * size)
if xc > 50:
if math.floor(value * 100 ) == math.floor(start * 100):
self.done = 1
def mkplanet(self, x,y):
self.batch = pyglet.graphics.Batch()
corner1 = (x,y)
self.trias = []
counter = 0
cornerback = [0,0]
for i in self.terrain:
counter += 1
radi = (360 / len(self.terrain)) * counter
radi2 = (360 / len(self.terrain)) * ((counter + 1 ) % len(self.terrain))
theta = self.terrain[(counter +1 ) % len(self.terrain)]
corner3 = (x + math.sin(radi) * ( i ) ,math.cos(radi) * ( i ) + y )
corner2 = (x + math.sin(radi2) * ( theta ) ,math.cos(radi2) * ( theta ) + y )
self.trias.append(shapes.Triangle( x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch) )
############ basic game logic & rendering ###########
scr_X = 400
scr_Y = 300
window = pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch()
earth = planetobj()
earth.gplanet(200)
planets = []
planets.append(earth)
earth.mkplanet( 50 ,50)
#window.event
def on_draw():
window.clear()
earth.batch.draw()
pyglet.app.run()
i tried changing the values that get divided by 'len(self.terrain)'
but i could not find out how to make the planets look round
EDIT
thank you kind commenter (and also the rest of stackoverflow)
now i made a working version feel free to use it
'''
import opensimplex
import math
import pyglet
from pyglet import shapes
pi = 3.1459
debug = 0
class planetobj():
def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home never will thy become infected with the virus that has a closedcure"):
self.seed = seed
self.age = age
self.position = position
self.color = color
self.name = name
self.description = description
def gplanet(self,size):
self.batch = pyglet.graphics.Batch()
opensimplex.seed(self.seed)
done = 0
xc = 0
c = 0
self.terrain = []
start = opensimplex.noise2(x=0, y=self.age)
while (done == 0 or xc < 50) and not xc > 100 :
xc = xc + 1
c = c + size
value = opensimplex.noise2(x=xc, y=self.age)
self.terrain.append(value * 10 + size)
if xc > 36:
if math.floor(value * 100 ) == math.floor(start * 100):
self.done = 1
def mkplanet(self, x,y):
global debug
corner1 = (x,y)
self.trias = []
deltatheta = 360 / len(self.terrain)
for counter,i in enumerate(self.terrain):
theta1 = ((deltatheta * counter)/180) * 3.1459
theta2 = (deltatheta * (counter + 2)/180) * 3.1459
radius = self.terrain[counter]
print(str(theta1) + "," + str(theta2))
radius2 = self.terrain[(counter + 1 )% len(self.terrain)]
corner2 = (x + radius2 * math.cos(theta1), y + radius * math.sin(theta1))
corner3 = ( (x + radius2 * math.cos(theta2)), (y + radius2 * math.sin(theta2)))
self.trias.append(shapes.Triangle(x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch) )
if debug == 1:
self.trias.append(shapes.Circle( corner2[0], corner2[1], 2, color=(255, counter % 255, 40), batch=self.batch) )
self.trias.append(shapes.Circle( corner3[0], corner3[1], 2, color=(255,255, 255), batch=self.batch) )
############ basic game logic & rendering ###########
scr_X = 400
scr_Y = 300
window = pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch()
earth = planetobj()
earth.gplanet(150)
earth.mkplanet( 250,150)
print(earth.batch)
earth.batch.draw
#window.event
def on_draw():
window.clear()
earth.batch.draw()
print("drawing")
pyglet.app.run()
'''
OK, I've corrected your trigonometry, but there are some other issues. The random values you get back from the noise generator are between -1 and 1. You are then multiplying that by the planet size, which gives you wild variations from wedge to wedge. What you want is to have a basic wedge size, which you use the noise to adjust bit by bit. Here, I'm saying that the noise should be 3% of the wedge size (size/30).
I didn't want to download opensimplex, so I've used a uniform random number generator. I'm also using matplotlib to plot the triangle, but see if this is closer to what you intended.
import math
import random
import numpy as np
import matplotlib.pyplot as plt
class planetobj():
def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=""):
self.seed = seed
self.age = age
self.position = position
self.color = color
self.name = name
self.description = description
def gplanet(self,size):
done = 0
xc = 0
self.terrain = []
start = random.uniform(-1,1)
while (done == 0 or xc < 50) and not xc > 100 :
xc = xc + 1
value = random.uniform(-1,1)
self.terrain.append(size + value * size / 30)
if xc > 50 and math.floor(value * 100) == math.floor(start * 100):
done = 1
def mkplanet(self, x,y):
corner1 = (x,y)
self.trias = []
deltatheta = 360 / len(self.terrain)
for counter,i in enumerate(self.terrain):
theta1 = deltatheta * counter
theta2 = deltatheta * (counter + 1)
radius = self.terrain[counter]
corner2 = (x + radius * math.cos(theta1), y + radius * math.sin(theta1))
corner3 = (x + radius * math.cos(theta2), y + radius * math.sin(theta2))
# self.trias.append(shapes.Triangle( x, y, corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch) )
self.trias.append(( x, y, corner2[0], corner2[1], corner3[0], corner3[1], (1.0,(counter%255)/255,1.0) ))
earth = planetobj()
earth.gplanet(200)
earth.mkplanet(50 ,50)
print(earth.trias)
plt.figure()
plt.scatter( [48,48,52,52],[-50,50,-50,50] )
for t in earth.trias:
tri = np.array(t[:6]).reshape(3,2)
plt.gca().add_patch(plt.Polygon( tri, color=t[6] ))
plt.show()
Output:

Is there a good way to speed up raytracing in Python?

I've been following the Raytracing in one weekend tutorial series (which is coded in C++), but I've run into a problem. I know Python is not really the language for raytracing, and it shows. Rendering 4 spheres with 100 samples per pixel at 600x300px with multithreading took a little over an quarter of an hour.
I figured that multithreading wasn't really doing anything. I needed multiprocessing. I tried to implement it, but it gave me the error that pygame.Surface wasn't serializable. Is there a solution for this, or maybe even a better way of implementing this? Or is the best way forward to recreate this in C#/C++?
The render:
Multithreaded code:
vec3.py
import math
import random
class vec3:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __add__(self, other):
return vec3(
self.x + other.x,
self.y + other.y,
self.z + other.z
)
def __sub__(self, other):
return vec3(
self.x - other.x,
self.y - other.y,
self.z - other.z
)
def __mul__(self, val):
if type(val) == vec3:
return vec3(
self.x * val.x,
self.y * val.y,
self.z * val.z
)
else:
return vec3(
self.x * val,
self.y * val,
self.z * val
)
def __truediv__(self, val):
return vec3(
self.x / val,
self.y / val,
self.z / val
)
def __pow__(self, pow):
return vec3(
self.x ** pow,
self.y ** pow,
self.z ** pow
)
def __rshift__(self, val):
return vec3(
self.x >> val,
self.y >> val,
self.z >> val
)
def __repr__(self):
return "vec3({}, {}, {})".format(self.x, self.y, self.z)
def __str__(self):
return "({}, {}, {})".format(self.x, self.y, self.z)
def dot(self, other):
return (
self.x * other.x +
self.y * other.y +
self.z * other.z
)
def cross(self, other):
return vec3(
(self.y * other.z) - (self.z * other.y),
-(self.x * other.z) - (self.z * other.x),
(self.x * other.y) - (self.y * other.x)
)
def length(self):
return math.sqrt(
(self.x ** 2) +
(self.y ** 2) +
(self.z ** 2)
)
def squared_length(self):
return (
(self.x ** 2) +
(self.y ** 2) +
(self.z ** 2))
def make_unit_vector(self):
return self / (self.length() + 0.0001)
def reflect(self, normal):
return self - normal * (self.dot(normal) * 2)
Raytracing.py
import uuid
import math
import pygame
from random import random
from vec3 import vec3
from threading import Thread
#import time
imprecision = 0.00000001
mindist = 0.001
maxdist = 999999999
class Material:
def random_in_unit_sphere():
p = vec3(random(), random(), random())*2 - vec3(1, 1, 1)
while p.squared_length() >= 1:
p = vec3(random(), random(), random())*2 - vec3(1, 1, 1)
return p
class Matte:
def __init__(self, albedo):
self.albedo = albedo
def scatter(self, ray, rec, scattered):
target = rec.p + rec.normal + Material.random_in_unit_sphere()
scattered.origin = rec.p
scattered.direction = target - rec.p
return True, self.albedo
class Metal:
def __init__(self, albedo, fuzz = 0):
self.albedo = albedo
self.fuzz = fuzz
def scatter(self, ray, rec, scattered):
reflected = ray.direction.make_unit_vector().reflect(rec.normal)
scattered.origin = rec.p
scattered.direction = reflected + (Material.random_in_unit_sphere() * self.fuzz)
return (scattered.direction.dot(rec.normal) > 0), self.albedo
class Transparent:
def __init__(self, refractive_index):
self.ri = refractive_index
def refract(self, v, normal, ni_over_nt):
uv = v.make_unit_vector()
dt = uv.dot(normal)
discriminant = 1 - (ni_over_nt * ni_over_nt * (1-dt*dt))
if discriminant > 0:
refracted = (uv - normal*dt) * ni_over_nt - (normal * math.sqrt(discriminant))
return True, refracted
else:
return False, None
def scatter(self, ray, rec, scattered):
reflected = ray.direction.reflect(rec.normal)
if ray.direction.dot(rec.normal) > 0:
outward_normal = 0 - rec.normal
ni_over_nt = self.ri
else:
outward_normal = rec.normal
ni_over_nt = 1 / self.ri
refracted = self.refract(ray.direction, outward_normal, ni_over_nt)
return bool(refracted[0]), vec3(1, 1, 1)
class Object:
class Sphere:
def __init__(self, pos, r, material=Material.Matte(0.5)):
self.center = pos
self.r = r
self.material = material
def hit(self, ray, t_min, t_max, rec):
oc = ray.origin - self.center
a = ray.direction.dot(ray.direction)
b = oc.dot(ray.direction)
c = oc.dot(oc) - (self.r * self.r)
discriminant = (b*b) - (a*c)
if discriminant < 0:
return False
else:
t = (-b - math.sqrt(discriminant)) / (a + imprecision)
if (t_min < t < t_max):
rec.t = t
rec.p = ray.point_at_parameter(t)
rec.normal = (rec.p - self.center) / self.r
rec.material = self.material
return True
t = (-b + math.sqrt(discriminant)) / (a + imprecision)
if (t_min < t < t_max):
rec.t = t
rec.p = ray.point_at_parameter(t)
rec.normal = (rec.p - self.center) / self.r
rec.material = self.material
return True
class Scene:
def genUUID(self):
id = uuid.uuid4()
while id in self.objects.keys():
id = uuid.uuid4()
return id
def __init__(self):
self.objects = {}
def add(self, object):
id = self.genUUID()
self.objects[id] = object
return id
def hit(self, ray, t_min, t_max, hit_record):
tmp_hit_record = Camera.HitRec()
hit_any = False
closest = maxdist
for object in self.objects.keys():
if self.objects[object].hit(ray, t_min, closest, tmp_hit_record):
hit_any = True
closest = tmp_hit_record.t
hit_record.t = tmp_hit_record.t
hit_record.p = tmp_hit_record.p
hit_record.normal = tmp_hit_record.normal
hit_record.material = tmp_hit_record.material
return hit_any
class Camera:
class Ray:
def __init__(self, A, B):
self.origin = A
self.direction = B
def point_at_parameter(self, t):
return self.origin + (self.direction * t)
class HitRec:
def __init__(self):
self.t = 0
self.p = vec3(0, 0, 0)
self.normal = vec3(0, 0, 0)
def __init__(self, w, screen, scene = Scene(), screen_ratio = 16/9, focal_length = 1):
self.w = w
self.h = int(w / screen_ratio)
self.screen = screen
self.scene = scene
self.screen_ratio = screen_ratio
self.screen_unit_width = 4
self.focal_length = focal_length
self.sampels_per_pixel = 1
self.max_hit_depth = 5
self.max_block_size = 100
# self.depthT = pygame.Surface((w, self.h))
self.origin = vec3(0, 0, 0)
self.horizontal = vec3(self.screen_unit_width, 0, 0)
self.vertical = vec3(0, (-self.screen_unit_width / self.screen_ratio), 0)
self.top_left_corner = \
self.origin - (self.horizontal/2) - (self.vertical/2) - vec3(0, 0, self.focal_length)
def color(self, ray, depth=0):
# Check for sphere hit
rec = self.HitRec()
if self.scene.hit(ray, mindist, maxdist, rec):
scattered = self.Ray(vec3(0, 0, 0), vec3(0, 0, 0))
hit = rec.material.scatter(ray, rec, scattered) # Scattered is the output ray
if depth < self.max_hit_depth and hit[0]:
return self.color(scattered, depth + 1) * hit[1]
else:
return hit[1]
# target = rec.p + rec.normal + self.random_in_unit_sphere()
# return self.color(self.Ray(rec.p, target - rec.p)) * 0.5
## return vec3(rec.normal.x + 1, rec.normal.y + 1, rec.normal.z + 1) * 0.5, rec.t
# Background if nothing's hit
unit_dir = ray.direction.make_unit_vector()
t = 0.5 * (unit_dir.y + 1)
return (vec3(1, 1, 1) * (1 - t)) + (vec3(0.5, 0.7, 1) * t)#, maxdist
def getRay(self, u, v):
return self.Ray(
self.origin,
self.top_left_corner + (self.horizontal * (u + imprecision)) + (self.vertical * (v + imprecision))
)
def renderSquare(self, xoff, yoff, w, h):
pygame.draw.rect(self.screen, (255, 255, 255), (xoff, yoff, w, h))
pygame.display.update()
for y in range(h):
for x in range(w):
col = vec3(0, 0, 0)
for n in range(self.sampels_per_pixel):
u = (x + xoff + random()-0.5) / self.w
v = (y + yoff + random()-0.5) / self.h
r = self.getRay(u, v)
col += (self.color(r) / self.sampels_per_pixel)
col = vec3(math.sqrt(col.x), math.sqrt(col.y), math.sqrt(col.z))
self.screen.set_at((x + xoff, y + yoff), (col.x * 255, col.y * 255, col.z * 255))
pygame.display.update()
def render(self):
blocks = []
for i in range(math.ceil(self.w / self.max_block_size)):
for j in range(math.ceil(self.h / self.max_block_size)):
blocks.append(Thread( target = self.renderSquare, args=(
i * self.max_block_size,
j * self.max_block_size,
self.max_block_size,
self.max_block_size
)))
for job in blocks:
job.start()
for job in blocks:
job.join()
if __name__ == '__main__':
from Raytracing import Camera, Scene, Object
import pygame
pygame.init()
WIDTH, HEIGHT = 600, 300
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Multithreaded raytracer')
scene = Scene()
scene.add(Object.Sphere(vec3( 0, 0, -1), 0.5, Material.Matte(vec3(0, 0.3, 0.8))))
scene.add(Object.Sphere(vec3(-1, 0, -1), 0.5, Material.Metal(vec3(0.8, 0.8, 0.8), 0.1)))
scene.add(Object.Sphere(vec3( 1, 0, -1), 0.5, Material.Metal(vec3(0.8, 0.6, 0.2), 1)))
scene.add(Object.Sphere(vec3(0, -100.5, -1), 100, Material.Matte(vec3(0.8, 0.8, 0))))
tracer = Camera(WIDTH, screen, scene, screen_ratio=2 / 1)
# tracer.render()
tracer.sampels_per_pixel = 100
tracer.render()
loop = True
while loop:
for event in pygame.event.get():
if event.type==pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
loop = False
if event.type==pygame.QUIT:
loop = False
pygame.display.update()
pygame.quit()

Creating a genetic algorithm

Im trying to recreate this code: https://github.com/Code-Bullet/Smart-Dots-Genetic-Algorithm-Tutorial/tree/master/BestTutorialEver , but in python, and it doesn't work, it keeps mutating the best dot and every generation starts with less dots.
Here is the code (i use pygame for graphics):
Brain class:
class Brain(object):
def __init__(self, size):
self.size = size
self.step = 0
self.directions = [[0.0, 0.0] for j in range(size)]
for i in range(len(self.directions)):
randomAngle = random.uniform(0, 2 * math.pi)
self.directions[i][0] = math.sin(randomAngle)
self.directions[i][1] = math.cos(randomAngle)
def mutate(self):
mutationRate = 1
for i in range(self.size):
rand = random.random()
if rand < mutationRate:
dirAngle = math.acos(self.directions[i][1]) * (1.0 + random.random())
self.directions[i][0] = math.sin(dirAngle)
self.directions[i][1] = math.cos(dirAngle)
Population Class:
class Population(object):
def __init__(self, size, win):
self.bestDot = 0
self.fitnessSum = 0.0
self.win = win
self.size = size
self.dots = [Dot(win) for i in range(size)]
def show(self):
for i in range(self.size-1):
self.dots[i+1].show()
self.dots[0].show()
def updt(self):
for i in range(self.size):
self.dots[i].updt()
def calculateFitness(self):
for i in range(self.size):
self.dots[i].calculateFitness()
def allDotsDead(self):
for i in range(self.size):
if not self.dots[i].dead and not self.dots[i].reachGoal:
return False
return True
def naturalSelection(self):
newDots = [Dot(self.win) for i in range(self.size)]
self.setBestDot()
self.calculateFitnessSum()
newDots[0] = self.dots[self.bestDot].baby()
newDots[0].isBest = True
for i in range(self.size-1):
parent = self.selectParent()
newDots[i+1] = parent.baby()
print(newDots[1])
self.dots = newDots
def calculateFitnessSum(self):
self.fitnessSum = 0.0
for i in range(self.size):
self.fitnessSum += self.dots[i].fitness
print(self.fitnessSum)
def selectParent(self):
rand = random.uniform(0, self.fitnessSum)
runningSum = 0.0
for i in range(self.size):
runningSum += self.dots[i].fitness
if runningSum >= rand:
return self.dots[i]
return None
def mutate(self):
for i in range(self.size):
if not self.dots[i].isBest:
self.dots[i].brain.mutate()
def setBestDot(self):
max = 0.0
maxIndex = 0
for i in range(len(self.dots)):
if self.dots[i].fitness > max:
max = self.dots[i].fitness
maxIndex = i
self.bestDot = maxIndex
Dot Class:
WIDTH, HEIGHT = 720, 640
GOAL = (WIDTH / 2, 50)
class Dot(object):
def __init__(self, win):
self.win = win
self.fitness = 0
self.reachGoal = False
self.dead = False
self.brain = Brain(200)
self.pos = [WIDTH / 2, HEIGHT - 50]
self.vel = [0, 0]
self.acc = [0, 0]
self.isBest = False
def move(self):
if len(self.brain.directions) > self.brain.step:
self.acc = self.brain.directions[self.brain.step]
self.brain.step += 1
else:
self.dead = True
for i in range(len(self.vel)): self.vel[i] += self.acc[i]
if self.vel[0] >= 5: self.vel[0] = 5
if self.vel[1] >= 5: self.vel[1] = 5
for i in range(len(self.pos)): self.pos[i] += self.vel[i]
def show(self):
if self.isBest:
pygame.draw.circle(self.win, (0, 255, 0), self.pos, 4)
else:
pygame.draw.circle(self.win, (200, 100, 0), self.pos, 2)
def updt(self):
if not self.dead and not self.reachGoal:
self.move()
if self.pos[0] < 4 or self.pos[1] < 4 or self.pos[0] > WIDTH - 4 or self.pos[1] > HEIGHT - 4:
self.dead = True
elif math.hypot(self.pos[0] - GOAL[0], self.pos[1] - GOAL[1]) < 5:
self.reachGoal = True
def calculateFitness(self):
distToGoal = math.hypot(self.pos[0] - GOAL[0], self.pos[1] - GOAL[1])
self.fitness = 1.0 / 16.0 + 10000.0 / (distToGoal * distToGoal)
def baby(self):
baby = Dot(self.win)
baby.brain.directions = self.brain.directions
return baby
The problem is that i especify that the best dot dont mutate, but its mutate or change to a worst dot, also, i dont know why but in every generetion less dots spawn(or dots has exactly the same brain a dont mutate not even a litle), the mutation rate is in 100% but in every run there are less and less dots.
Here screenshots of the first and 5th generation: https://imgur.com/a/675Jxit
Also, if someone has some genetic algorithm in python to take as a model it would help.
I did not try the project you mentioned. You may try PyGAD, a Python 3 library for building the genetic algorithm and training machine learning algorithms. It is open-source where you can find the code at GitHub.
It is simple to use which allows you to control the crossover, mutation, and parent selection operators in an easy way. You can also control many parameters of the genetic algorithm using PyGAD.
PyGAD also works with a user-defined fitness function so you can adapt it to a wide-range of problems.
After installing PyGAD (pip install pygad), here is a simple example to get started that tries to find the best values for W1, W2, and W3 that satisfies the following equation:
44 = 4xW_1 - 2xW_2 + 1.2xW_3
import pygad
import numpy
function_inputs = [4,-2, 1.2]
desired_output = 44
def fitness_func(solution, solution_idx):
output = numpy.sum(solution*function_inputs)
fitness = 1.0 / (numpy.abs(output - desired_output) + 0.000001)
return fitness
def on_generation(ga_instance):
print(ga_instance.population)
ga_instance = pygad.GA(num_generations=50,
num_parents_mating=2,
fitness_func=fitness_func,
num_genes=3,
sol_per_pop=5)
ga_instance.run()
ga_instance.plot_result()
solution, solution_fitness, _ = ga_instance.best_solution()
print("Parameters of the best solution : {solution}".format(solution=solution))
print("Fitness value of the best solution = {solution_fitness}".format(solution_fitness=solution_fitness))

Python Creating a tick in a class

So I'm spawning circles at random in Python and I decided I wanted to make each circle it's own object. So I created a class for them.
I wanted each circle to have their own tick function so that each one can do their own thing. (change colors, size, de-spawn etc.) However I'm having a lot of issues getting the tick method to work.
Here is my code:
from random import *
from tkinter import *
from time import *
size = 2000
window = Tk()
count = 0
class Shape(object):
def __init__(self,name, canv, size, col, x0, y0,d,outline):
self.name = name
self.canv = canv
self.size = size
self.col = col
self.x0 = x0
self.y0 = y0
self.d = d
self.outline = outline
self.age=0
def death(self):
pass
def spawn(self):
self.canv.create_oval(self.x0, self.y0, self.x0 + self.d, self.y0 + self.d, outline=self.outline, fill = self.col)
def tick(self):
self.age = self.age +time.time()
while True:
tick()
# var canv = A new Canvas Object (The Window Object to be put in, The Canvice width, The canvice Height)
canv = Canvas(window, width=size, height=size)
canv.pack()
d = 0
while True:
col = choice(['#EAEA00'])
x0 = randint(0, size)
y0 = randint(0, size)
#d = randint(0, size/5)
d = (d + 0.001)
count = count+1
outline = 'white'
shapes[count] = Shape("shape" + str(count), canv, size, col, x0, y0, d, outline)
shapes[count].spawn()
#canv.create_oval(x0, y0, x0 + d, y0 + d, outline='white', fill = col)
window.update()
So basically I get two different errors from this part of the code:
while True:
tick()
Ether it's a TypeError: tick() missing one required positional argument: 'self' or if I put self into the parameters I get self is undefined.
So what am I doing wrong?

paintevent in continuous loop?

I have the following code which draws ellipse on the circumference of a circle and then draws chords between ellipses. The chords are drawn fine but the event bombs on me and goes into a infinite loop.
def binomial(i, n):
return math.factorial(n) / float(
math.factorial(i) * math.factorial(n - i))
def bernstein(t, i, n):
return binomial(i, n) * (t ** i) * ((1 - t) ** (n - i))
def bezier(t, points):
n = len(points) - 1
x = y = 0
for i, pos in enumerate(points):
bern = bernstein(t, i, n)
x += pos[0] * bern
y += pos[1] * bern
return x, y
def bezier_curve_range(n, points):
for i in xrange(n):
t = i / float(n - 1)
yield bezier(t, points)
def getControlPt(x1, y1, x2, y2, t):
new_px = (1 - t) * x1 + t * x2
new_py = (1 - t) * y1 + t * y2
return new_px, new_py
class Temp1(QWidget):
def __init__(self, c, parent=None):
super(Temp1, self).__init__(parent)
self.text = "Hi"
self.cords = c
def paintEvent(self, e):
qp = QPainter(self)
qp.setPen(Qt.red)
bluePen = QPen(Qt.blue, 1, Qt.DashLine)
steps = 10000
for i in range(15):
for j in range(15):
if i == j:
continue
px, py = getControlPt(self.cords[i][0], self.cords[i][1], self.cords[j][0], self.cords[j][1], 0.55)
px1, py1 = getControlPt(px, py, self.cords[j][0], self.cords[j][1], 0.25)
px2, py2 = getControlPt(px1, py1, self.cords[j][0], self.cords[j][1], 0.75)
cp = (self.cords[i], (px, py) , (px1, py1), (px2, py2), self.cords[j])
oldPoint = cp[0]
qp.setPen(bluePen)
for point in bezier_curve_range(steps, cp):
qp.drawLine(oldPoint[0], oldPoint[1], point[0], point[1])
oldPoint = point
class Temp(QPushButton):
def __init__(self, x, y, w, h, theta, cords, parent=None):
super(Temp, self).__init__(parent)
self.w = w
self.h = h
self.x = x
self.y = y
self.text = "test"
self.angle = theta
self.cords = cords
def paintEvent(self, e):
qp = QPainter(self)
qp.setPen(Qt.red)
qp.drawEllipse(0, 0, self.w - 2, self.h -2)
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.cords = []
self.initUI()
def initUI(self):
self.setWindowTitle('Points')
self.drawP()
def drawP(self):
theta = 2 * np.pi / 15
for i in range(15):
angle = theta * (i + 1)
dx = int(round(400 + 300 * np.cos(angle)))
dy = int(round(400 + 300 * np.sin(angle)))
self.cords.append((dx, dy))
for i in range(15):
t = Temp(self.cords[i][0], self.cords[i][1], 45, 20, np.degrees(angle), self.cords, parent=self)
t.setGeometry(self.cords[i][0], self.cords[i][1] , 45, 20)
t1 = Temp1(self.cords, parent = self)
t1.setGeometry(0, 0, 800, 600)
app = QApplication(sys.argv)
ex = Example()
ex.setGeometry(0, 0, 800, 600)
ex.show()
sys.exit(app.exec_())
The problem is with the paintevent function of class Temp1.
If you throw a print 'Temp1.paintEvent', e, i, j inside the nested for loops inside of Temp1.paintEvent, you'll see that it's not hanging, it's just slow, and every time you hide the window, then bring it back up, it has to go through the whole paintEvent again before actually showing it. If you're patient the window will eventually pop up.

Categories