Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 1419
Kernel: Anaconda (Python 3)
import numpy as np import matplotlib.pyplot as plt %matplotlib notebook plt.style.use('ggplot') import random from random import randint import math
food_amount = 50 pacman_amount = 200 board_size = 1000 default_health = 50 pacmen = [] food = [] crot = 1 cloc = .5 cbite = 1 turn_loss = 200 phi_prec = (80/255.) alpha_prec = 10/255. delta_prec = 10/255. pacman_radius = 1 food_health = 300 mutation_freq = .005 # percent any 0/1 would flip for each gene
class pacman: def __init__(self): #change dynamically self.x = random.uniform(49*board_size/100,51*board_size/100) self.y = random.uniform(49*board_size/100,51*board_size/100) #this is set so the prgression will be outward self.theta = randint(0,359) self.health = default_health self.active = 1 #dna self.phi = randint(0,255) self.alpha = randint(0,255) self.delta = randint(0,255) self.phi_val = self.phi*phi_prec self.alpha_val = self.alpha*alpha_prec self.delta_val = self.delta*delta_prec #self.f = closest food #self.dist = closest food distance def __bool__(self): return True def __repr__(self): return "{pacman, x:"+str(self.x)+", y:"+str(self.y)+", theta:"+str(self.theta)+"}" def find_dist(self,f): return np.sqrt((self.x-f.x)**2 + (self.y-f.y)**2) def find_angle(self,f): dx = f.x - self.x dy = f.y - self.y arc = math.degrees(math.atan((dy/dx))) theta1 = 1 if dx > 0: theta1 = 180 - arc #this used to be an if, but i think arctan returns a negative when a negative is inputted. #therefor the two would be equivalent else: if dy > 0: theta1 = np.absolute(arc) #this is absolute because the angle will be a negative else: theta1 = 360 - arc #theta1 is the angle the food is from the x axis #returned is the difference in the angles return np.absolute(theta1 - self.theta) def check_angle(self,f):#check if the food is in the range diff = (self.phi_val/2)#this creates virutal bounds f_angle = self.find_angle(f) if(f_angle < diff): return True return False def find_food(self): global food closest = False closest_dist = False for i in food: dist = self.find_dist(i) if((dist < closest_dist or not closest_dist) and (self.check_angle(i))): closest = i closest_dist = dist self.f = closest self.dist = closest_dist if(closest != False): return True return False def rotate_to_food(self):# returns (in radians!!!) the angle needed to get the food with genetic error #no cost to rotation dx = self.f.x - self.x dy = self.f.y - self.y arc = math.atan((dy/dx)) error = random.uniform(self.alpha_val/-2., self.alpha_val/2.) new_theta = arc + error return new_theta def get_food(self): theta = self.rotate_to_food() #warning this is in radians... #theta is not used... error = random.uniform(self.delta_val/-2., self.delta_val/2.)*0 new_dist = self.dist + (error*self.dist) #the error for distance is relative to the distance, ie the greater the dist the greater the error dx = self.f.x - self.x dy = self.f.y - self.y distx = new_dist*(dx/self.dist)#equivalent to cos, error is not associted with the angle yet disty = new_dist*(dy/self.dist)#equivalent to sin self.x += distx self.y += disty cost = cloc*new_dist self.health -= cost #cost of rotate def bite(self): to_food = self.find_dist(self.f) self.health -= cbite if(to_food < pacman_radius):#means the bite was sucessful self.health += food_health self.f.reset() self.check_bounds() def check_bounds(self): if(self.x > board_size or self.x < 0): self.x = self.x % board_size #if(self.x < 0): # self.x = board_size + self.x if(self.y > board_size or self.y < 0): self.y = self.y % board_size def random_rotate(self): self.theta = randint(0,359) #self.health += randint(-2,1) def step(self): self.health -= turn_loss if(self.find_food()): self.get_food() self.bite() self.random_rotate() def get_genes(self): return[self.phi,self.alpha,self.delta] def set_genes(self,genes): self.phi = genes[0] self.alpha = genes[1] self.delta = genes[2] def to_bits(self): genes = self.get_genes() split_genes = [] for i in genes: bin_str = format(i, '#010b') bin_str = bin_str[2:] split_genes.append([bin_str[:4],bin_str[4:]]) return split_genes def mutate(self, gene): #checks each 1/0 and finds a random num and if it below the threshold it mutates new_gene = '' for i in gene: rand = random.uniform(0,1) if(rand < mutation_freq): #this means the dna is flipping num = int(i) if(num == 1): num = 0 else: num = 1 new_gene += str(num) else: new_gene += str(i) return new_gene def reproduce(self,other): son1 = pacman() son2 = pacman() son1_genes = [] son2_genes = [] mybits = self.to_bits() otherbits = other.to_bits() for i,v in enumerate(mybits): son1_gene = v[0]+otherbits[i][1] son1_gene = self.mutate(son1_gene) son2_gene = otherbits[i][0]+v[1] son2_gene = self.mutate(son2_gene) son1_gene = int('0b'+son1_gene,base=2) son2_gene = int('0b'+son2_gene,base=2) son1_genes.append(son1_gene) son2_genes.append(son2_gene) son1.set_genes(son1_genes) son2.set_genes(son2_genes) return [son1,son2] p = pacman() p2 = pacman() print(p.reproduce(p2))
[{pacman, x:496.0876640735796, y:499.7720542154919, theta:267}, {pacman, x:491.0193979130969, y:490.0979186938236, theta:110}]
class dot: def __init__(self): self.x = random.uniform(0, board_size) self.y = random.uniform(0, board_size) self.active = 1 def __repr__(self): return "{dot, x:"+str(self.x)+", y:"+str(self.y)+"}" def reset(self): self.x = random.uniform(0, board_size) self.y = random.uniform(0, board_size)
def gen1(): global pacmen pacmen = [] for i in range(0,pacman_amount): p = pacman() pacmen.append(p) pacmen = np.array(pacmen) print(pacmen[0]) return pacmen def food1(): global food food = [] for i in range(0,food_amount): f = dot() food.append(f) food = np.array(food) return food def reproduce1(healthy_pacmen):# takes an array of pacmen and reproduces each with a neibor #inactive for now sons = [] for i,v in enumerate(healthy_pacmen): if( i % 2 == 1): temp = v.reproduce(healthy_pacmen[randint(0,len(healthy_pacmen)-1)]) sons.extend(temp) return sons def find_average_health(p,x=10): #takes an array of pacmen and finds the averge health #it will also sort the pacemen by health and return the helath of the xth pacman pacmen_ranked = [] avg_health = 0 for i in p: pacmen_ranked.append(i.health) avg_health += i.health avg_health = avg_health/len(p) pacmen_ranked = np.array(sorted(pacmen_ranked)) med_health = pacmen_ranked[x] print(avg_health, med_health) return avg_health, med_health def reproduce2(healthy_pacmen, x):# takes an array of pacmen and reproduces randomly with other heathy_pacmen # x is how many are cut off in the evolution sons = [] total = int(len(healthy_pacmen)/2) + int(x/2) + 1 for i in range(0,total): rand1 = randint(0,len(healthy_pacmen)-1) rand2 = randint(0,len(healthy_pacmen)-1) p1 = healthy_pacmen[rand1] p2 = healthy_pacmen[rand2] temp = p1.reproduce(p2) sons.extend(temp) return sons def average_genes(p):#phi alpha delta avg1 = 0 avg2 = 0 avg3 = 0 for i in p: avg1 += i.phi_val avg2 += i.alpha_val avg3 += i.delta_val avg1 = avg1/len(p) avg2 = avg2/len(p) avg3 = avg3/len(p) return avg1,avg2,avg3
def driver(gen,life_span,generations): food = food1() dt = 1 t = [0] tracker = [] genetics = [[],[],[]] cycles = [] global pacmen for g in range(0,generations): #iterates through each generation tracker.append([]) avg1,avg2,avg3 = average_genes(pacmen) genetics[0].append(avg1) genetics[1].append(avg2) genetics[2].append(avg3) for i in pacmen: tracker[g].append([]) cycles.append([]) t.append(t[-1]+dt) for q in range(0,life_span): #runs through time with current generation for i,v in enumerate(pacmen): tracker[g][i].append([v.x,v.y,v.theta]) v.step() cycles[g].append([])# note cycles starts after the first gen cycles[g][q].append([]) cycles[g][q].append([]) cycles[g][q].append([]) cycles[g][q].append([]) for w in pacmen: cycles[g][q][0].append(w.x) cycles[g][q][1].append(w.y) for f in food: cycles[g][q][2].append(f.x) cycles[g][q][3].append(f.y) #makes the next generation x = 150 # number of pacmen dieing healthy_pacmen = [] avg,med = find_average_health(pacmen,x) for i,v in enumerate(pacmen): #end of a generation mean reproduce if(v.health > med): healthy_pacmen.append(v) #this system kills off the bottom x pacmen sons = reproduce2(healthy_pacmen,x) pacmen = sons return t,tracker,genetics,cycles
t,tracker,genetics,cycles = driver(gen1(),50,100)#turns then generations
{pacman, x:501.69919874962875, y:503.04798100741584, theta:64} -3815.31783959 -1946.07189723 -4114.26515099 -2170.5709943 -3975.07799799 -2066.25418381 -3755.50822726 -1965.07109343 -3616.29499599 -1940.77504068 -3690.7968979 -1764.19257586 -3979.0906675 -2056.01912447 -4290.69078857 -2367.4848218 -3981.01642311 -1922.39179312 -3939.6863645 -2026.45407924 -3831.38891081 -2091.44412195 -4214.88162106 -2138.67220278 -4123.21131664 -2127.31361376 -4115.62159417 -2356.05583988 -4050.20590901 -2189.71098325 -4044.40594123 -2186.99227873 -3964.01996906 -2197.61014296 -4180.04978289 -2361.90044096 -4243.15438316 -2421.00200481 -4150.18396519 -2318.55521553 -3809.85711158 -2065.350969 -3971.69653459 -1996.13964536 -3552.08887577 -1925.52879773 -3991.09591077 -2181.82644806 -3785.67042561 -2048.49756536 -3827.66593677 -1806.5455548 -3928.78050089 -1988.74499469 -4307.06487915 -2412.08711557 -4153.43379747 -2145.87077543 -4196.95938929 -2122.30005702 -3754.60283112 -1949.7408634 -3995.66754308 -2275.80178608 -3898.29276041 -1992.16368694 -4083.90746967 -2224.81205992 -3880.09137798 -2189.93561829 -4049.33267186 -2124.36145868 -4093.50831416 -2267.32071278 -4154.66078288 -2263.11935847 -4037.32659127 -2336.64530871 -3879.97297194 -2081.36526778 -3914.37133026 -2152.23006674 -3936.7013003 -2259.12370244 -4155.2636051 -2105.32276369 -4045.84171781 -2206.54466472 -4007.78455396 -2166.66345542 -3990.8684907 -2127.29048226 -3852.51329238 -1945.84942298 -3809.83992985 -1761.81026518 -4089.07265984 -2122.51207476 -3772.62223457 -2018.11559398 -3797.16611349 -2130.05841331 -3701.51613632 -1912.24632563 -4171.96766121 -2386.37188094 -4295.1979911 -2081.67998764 -4005.47130381 -2152.73617501 -3869.64813224 -2001.54530992 -4171.88639342 -2030.43188771 -3975.37629364 -2272.06327566 -4016.80214405 -2028.41061006 -3905.81977153 -2056.57803658 -4183.71828418 -2314.89602058 -3912.5960737 -2287.55117686 -3801.23724706 -1793.3942031 -3852.19639012 -2264.25316557 -3751.4972184 -1916.27430808 -4178.16507006 -2115.32074358 -3922.54175058 -2222.91417402 -4180.48908047 -2433.6345698 -3931.99052744 -1985.24984404 -3868.82447792 -2227.5384429 -4187.49435715 -2483.69811193 -4000.45216503 -2013.22069678 -3804.98601004 -2207.35876212 -3869.79012874 -2032.84157295 -4026.46768502 -2075.8829961 -3914.31916923 -2271.04011859 -3994.33471277 -2341.72798893 -4081.33407362 -2019.02388294 -3663.44170819 -1927.52936306 -4046.36141721 -2026.99529518 -4197.34318466 -2228.33569726 -3997.92464666 -2157.49426746 -3851.40135586 -2212.53084159 -3837.20486526 -2149.12041587 -4156.6651353 -2145.99683056 -3838.43366166 -1931.91967357 -4107.90258048 -2200.43628345 -4162.13549029 -2362.42960673 -4030.86710074 -2219.14686347 -4106.8160968 -1948.20281767 -3729.30809497 -1967.1014909 -3853.84412223 -2173.36047639 -3972.1028353 -2014.93358718 -4263.75751057 -2214.77399736 -3782.32812425 -1895.5152025 -3827.38033598 -2109.18292218 -4179.54898165 -2206.92774549 -4106.08027629 -2171.13705348 -4271.0059647 -2171.31822858 -3752.4354194 -1854.3670115
print(genetics) plt.figure() plt.plot(genetics[0])# should increase #plt.plot(genetics[1])#should decrease #plt.plot(genetics[2])#should decrease # error is disabled
[[41.71764705882352, 39.476078431372564, 40.11921568627448, 42.768627450980375, 43.316078431372574, 43.02117647058825, 40.59294117647059, 36.461176470588235, 39.63450980392159, 40.28705882352943, 40.66823529411762, 38.5050980392157, 38.71686274509803, 39.01490196078432, 38.98509803921568, 40.050196078431384, 40.65098039215686, 37.66274509803921, 36.765490196078424, 39.472941176470584, 40.80784313725492, 40.858039215686276, 43.567058823529436, 39.678431372549, 41.992156862745084, 41.6, 39.86196078431373, 39.35529411764709, 40.282352941176505, 39.24392156862746, 42.82352941176471, 37.94039215686273, 40.55999999999999, 38.30274509803923, 39.05882352941177, 40.49568627450981, 38.69490196078431, 37.67529411764707, 39.73333333333334, 42.69333333333334, 39.778823529411746, 39.207843137254905, 39.6878431372549, 39.38352941176469, 40.43450980392157, 38.88784313725487, 41.18117647058821, 40.53803921568626, 38.45176470588237, 41.94509803921568, 42.741960784313754, 41.69725490196079, 37.8964705882353, 38.178823529411765, 39.549803921568625, 42.05803921568631, 36.6478431372549, 41.64235294117645, 40.382745098039216, 40.66196078431372, 37.83058823529413, 40.93803921568629, 39.910588235294156, 41.29098039215687, 41.61098039215688, 39.19372549019606, 40.097254901960795, 37.868235294117646, 39.844705882352926, 40.636862745098036, 37.93411764705884, 38.3576470588235, 41.82117647058821, 39.50745098039217, 40.18509803921569, 39.14509803921571, 40.77019607843136, 38.92078431372548, 42.81568627450978, 39.74588235294119, 37.86980392156861, 40.494117647058815, 41.41647058823528, 39.22666666666667, 40.001568627450986, 42.362352941176454, 38.85647058823529, 38.11607843137256, 38.90352941176469, 39.3427450980392, 41.488627450980374, 42.38274509803922, 40.60078431372549, 37.2392156862745, 41.24705882352941, 41.47921568627451, 39.68470588235296, 38.93960784313725, 38.829803921568654, 41.339607843137244], [5.13627450980392, 4.906666666666669, 4.85764705882353, 5.362941176470592, 4.917843137254902, 5.0741176470588245, 4.676666666666667, 4.9847058823529435, 4.732941176470587, 5.016862745098041, 4.901176470588235, 5.131176470588235, 5.227254901960787, 5.005294117647059, 5.2256862745098065, 4.689019607843135, 4.84764705882353, 4.649019607843137, 5.012941176470589, 4.9015686274509775, 5.132352941176473, 5.217058823529411, 5.205098039215688, 5.277058823529412, 4.677058823529412, 5.041372549019608, 5.051960784313728, 4.746470588235295, 5.000784313725493, 5.102549019607843, 4.86921568627451, 5.0672549019607835, 4.981372549019609, 5.588039215686273, 5.187647058823529, 5.030392156862747, 5.082352941176471, 4.841176470588237, 4.983333333333333, 4.951568627450979, 4.7282352941176455, 4.965098039215686, 5.018039215686277, 4.847843137254901, 5.075686274509804, 5.194705882352939, 4.879411764705884, 5.292745098039221, 5.005294117647059, 5.298431372549022, 5.0343137254902, 4.9492156862745125, 5.0864705882352945, 5.021176470588233, 4.93078431372549, 4.975490196078432, 5.035882352941175, 4.876470588235294, 4.756862745098039, 4.677450980392156, 5.08313725490196, 4.6517647058823535, 4.562745098039218, 5.099607843137255, 4.979019607843138, 5.432549019607847, 4.744901960784311, 5.038235294117647, 4.9382352941176455, 4.813137254901962, 4.803921568627447, 5.262745098039213, 5.288235294117648, 5.016078431372551, 5.0931372549019605, 4.763725490196076, 5.290392156862747, 4.821176470588232, 4.834313725490192, 4.719607843137254, 5.068431372549021, 4.687843137254902, 4.847254901960786, 5.417254901960783, 4.71392156862745, 4.859215686274513, 5.066862745098041, 5.052941176470587, 4.8439215686274535, 4.807058823529411, 5.093529411764703, 4.936274509803922, 4.7794117647058805, 4.957058823529413, 4.8358823529411765, 5.058039215686275, 5.083529411764708, 4.877843137254902, 4.894313725490196, 5.181372549019608], [4.908823529411765, 5.027058823529415, 4.952352941176469, 4.836078431372547, 5.27254901960784, 4.932941176470591, 4.878431372549022, 4.947843137254901, 5.151568627450982, 4.946666666666667, 5.055490196078434, 5.198823529411763, 5.127254901960783, 5.14235294117647, 4.967647058823528, 4.9399999999999995, 4.988235294117646, 4.70607843137255, 4.9949019607843175, 4.668627450980394, 4.860588235294119, 4.561176470588237, 5.330392156862741, 5.014509803921569, 4.980196078431372, 5.4788235294117635, 5.0888235294117665, 5.080196078431373, 5.117058823529408, 4.7676470588235285, 5.205098039215686, 5.305490196078432, 5.116666666666664, 5.493921568627451, 5.018039215686272, 5.2452941176470596, 5.302156862745095, 4.916274509803922, 5.018039215686274, 4.620196078431374, 5.193725490196075, 5.069411764705886, 5.145882352941179, 5.2590196078431415, 4.940000000000001, 4.997450980392156, 5.056274509803922, 5.149803921568626, 4.982745098039213, 4.83156862745098, 4.710588235294118, 5.214313725490197, 4.7474509803921565, 5.046078431372549, 5.072549019607843, 4.6837254901960765, 5.010784313725491, 5.173921568627451, 5.023137254901961, 4.984509803921569, 4.944901960784313, 5.431176470588236, 4.921960784313726, 5.221372549019605, 4.816470588235292, 4.694705882352942, 4.968235294117647, 4.817254901960787, 5.174117647058822, 5.166470588235296, 4.936078431372549, 5.122941176470587, 5.19078431372549, 4.8664705882352965, 4.915098039215685, 4.733725490196075, 5.055686274509805, 4.803921568627448, 5.411568627450978, 4.801764705882351, 5.535294117647059, 5.080588235294119, 5.107254901960785, 4.886274509803921, 5.04941176470588, 5.195490196078432, 5.148235294117646, 4.712352941176471, 4.926666666666665, 5.084901960784315, 5.024313725490199, 5.18235294117647, 4.772941176470589, 5.064117647058823, 5.346862745098037, 5.018823529411767, 4.9305882352941195, 5.119019607843138, 4.849215686274511, 5.058235294117644]]
<IPython.core.display.Javascript object>
[<matplotlib.lines.Line2D at 0x7f0a08346080>]
tracker = np.array(tracker) x = [] for i in tracker[0][0]: x.append(i[0]) plt.figure() plt.plot(x) figs = 8 gen = 0 f, axarr = plt.subplots(figs, sharex=True,sharey=True) for i in range(0,figs): axarr[i].scatter(cycles[gen][i][0],cycles[gen][i][1]) axarr[i].scatter(cycles[gen][i][2],cycles[gen][i][3], marker='^',c='red')
<IPython.core.display.Javascript object>
<IPython.core.display.Javascript object>