def __init__(self, maxframes): self.settings = self.initSettings() self.sim_frames = int(self.settings['sim_frames']) self.controller = Controller(self) self.view = View(self) self.crashed = False self.grid = self.initGrid() self.keys = {} self.reader = GenomeReader(self) self.evolution = Evolution(self) self.evolution.loadGenomes('../res/genomes', 1000) self.entities = { 'food': Consumable('food', 400, 300, 'Food', 0.5, self), 'player': NPC('player', 400, 220, 2, 10, 10, 'PC', 1, self.reader.makeGenome('../res/genomes/000000.dna'), self) } self.grid = self.addEntities2Grid() self.score = 0 self.maxframes = 0 self.startThreads()
def __init__(self, maxframes): self.settings = self.initSettings() self.X, self.Y = self.loadData() self.crashed = False self.reader = GenomeReader(self) self.evolution = Evolution(self) self.evolution.loadGenomes('../res/genomes', 10) self.score = 0 self.best = 999999 self.startThreads()
def load_system(self, system, ai): """ Load the system from a YAML file """ self.ai = ai with open(system, 'r') as f: system = yaml.load(f) self.minimap = system['minimap'] self.connections = system['connections'] self.vehicles = system.get('vehicles', 40) self.core = Core(self.minimap, self.connections, self.vehicles) hidden_layers = layers = system.get('layers', []) side_neurons = len(self.core.junction_queues) self.layers = [side_neurons] + hidden_layers + [side_neurons] self.evolution = Evolution(self.layers)
def __init__(self, pipe=None, lock=None, seed=42, worker_nr=None, partition=None, environment=None, environment_name=None, pop_size=0, cppn_output_range=0, input_shape=None, hidden_shapes=None, output_shape=None, c1=1.0, c2=1.0, c3=0.4, dt=3.0, prob_add_link=0.1, prob_add_node=0.03, prob_mut_weights=0.8, prob_mut_uniform=0.9, prob_interspecies_mating=0.001, elitism=0.2, activation_function=None, cppn_weight_range=None, function_set=None): super().__init__() self.population = [] #current population of genomes self.fitness_scores = None self.random = RandomState(seed) self.pipe = pipe self.lock = lock self.worker_nr = worker_nr self.partition = partition self.pop_size = pop_size self.population = [None] * pop_size self.fitness_scores = np.full((pop_size, ), None, dtype=float) self.cppn_output_range = cppn_output_range self.input_shape = input_shape self.hidden_shapes = hidden_shapes self.output_shape = (output_shape, ) self.environment = environment if self.SHOW_BEST_INDIVIDUAL or self.SHOW: self.environment.render() time.sleep(5) self.environment_name = environment_name while len(self.output_shape) < len(self.input_shape): self.output_shape = (1, ) + self.output_shape self.activation_function = activation_function self.loadGenomesFromFiles(self.GENOMES_BASE_FOLDER + environment_name) self.c1 = c1 self.c2 = c2 self.c3 = c3 self.dt = dt self.prob_add_link = prob_add_link self.prob_add_node = prob_add_node self.prob_mut_weights = prob_mut_weights self.prob_mut_uniform = prob_mut_uniform self.prob_interspecies_mating = prob_interspecies_mating self.elitism = elitism self.cppn_weight_range = cppn_weight_range self.function_set = function_set #structures self.layers = [] self.weights = [] self.coords = [] self.buildStructures(self.input_shape, self.hidden_shapes, self.output_shape) self.evolution = Evolution( genomes=self.population, fitness=self.fitness_scores, random=self.random, c1=self.c1, c2=self.c2, c3=self.c3, dt=self.dt, prob_add_link=self.prob_add_link, prob_add_node=self.prob_add_node, prob_mut_weights=self.prob_mut_weights, prob_mut_uniform=self.prob_mut_uniform, prob_interspecies_mating=self.prob_interspecies_mating, elitism=self.elitism, weight_range=self.cppn_weight_range, function_set=self.function_set)
class Worker(Process): GENOMES_BASE_FOLDER = '../res/genomes/' #base directory where pre-trained genomes are stored SHOW_BEST_INDIVIDUAL = True SHOW = True def __init__(self, pipe=None, lock=None, seed=42, worker_nr=None, partition=None, environment=None, environment_name=None, pop_size=0, cppn_output_range=0, input_shape=None, hidden_shapes=None, output_shape=None, c1=1.0, c2=1.0, c3=0.4, dt=3.0, prob_add_link=0.1, prob_add_node=0.03, prob_mut_weights=0.8, prob_mut_uniform=0.9, prob_interspecies_mating=0.001, elitism=0.2, activation_function=None, cppn_weight_range=None, function_set=None): super().__init__() self.population = [] #current population of genomes self.fitness_scores = None self.random = RandomState(seed) self.pipe = pipe self.lock = lock self.worker_nr = worker_nr self.partition = partition self.pop_size = pop_size self.population = [None] * pop_size self.fitness_scores = np.full((pop_size, ), None, dtype=float) self.cppn_output_range = cppn_output_range self.input_shape = input_shape self.hidden_shapes = hidden_shapes self.output_shape = (output_shape, ) self.environment = environment if self.SHOW_BEST_INDIVIDUAL or self.SHOW: self.environment.render() time.sleep(5) self.environment_name = environment_name while len(self.output_shape) < len(self.input_shape): self.output_shape = (1, ) + self.output_shape self.activation_function = activation_function self.loadGenomesFromFiles(self.GENOMES_BASE_FOLDER + environment_name) self.c1 = c1 self.c2 = c2 self.c3 = c3 self.dt = dt self.prob_add_link = prob_add_link self.prob_add_node = prob_add_node self.prob_mut_weights = prob_mut_weights self.prob_mut_uniform = prob_mut_uniform self.prob_interspecies_mating = prob_interspecies_mating self.elitism = elitism self.cppn_weight_range = cppn_weight_range self.function_set = function_set #structures self.layers = [] self.weights = [] self.coords = [] self.buildStructures(self.input_shape, self.hidden_shapes, self.output_shape) self.evolution = Evolution( genomes=self.population, fitness=self.fitness_scores, random=self.random, c1=self.c1, c2=self.c2, c3=self.c3, dt=self.dt, prob_add_link=self.prob_add_link, prob_add_node=self.prob_add_node, prob_mut_weights=self.prob_mut_weights, prob_mut_uniform=self.prob_mut_uniform, prob_interspecies_mating=self.prob_interspecies_mating, elitism=self.elitism, weight_range=self.cppn_weight_range, function_set=self.function_set) """ What to do while running """ def run(self): stop = False while not stop: self.fitness_scores = np.full((self.pop_size, ), None, dtype=float) for genome_id in self.partition: self.fitness_scores[genome_id] = self.evaluate(genome_id) self.pipe.send(self.fitness_scores) self.fitness_scores = self.pipe.recv() time.sleep(5) #prevent overheating or something? self.writeGenomesToFiles(self.GENOMES_BASE_FOLDER + self.environment_name) #calculate highscore over multiple trials. This does not count to towards training time self.pipe.send(self.calcHighscore()) stop = self.pipe.recv() self.population = self.evolution.evolve( fitness_scores=self.fitness_scores, genomes=self.population) def calcHighscore(self): genome_id = np.nanargmax(self.fitness_scores) #build phenotype cppn = CPPN(genome=self.population[genome_id], cppn_output_range=self.cppn_output_range) substrate = Substrate(CPPN=cppn, layers=self.layers, coords=self.coords, activation_function=self.activation_function, cppn_output_range=self.cppn_output_range) highscores = [] for _ in range( max(1, int(1 / (len(self.population) / len(self.partition))))): observation = self.environment.reset() score = 0. while True: activations = substrate.querySubstrate( input_matrix=observation) action = np.argmax(activations) observation, reward, done, info = self.environment.step(action) print(info) score += reward if self.SHOW_BEST_INDIVIDUAL: self.environment.render() time.sleep(1. / 60) if done: print(info) highscores.append(score) break return np.array(highscores, dtype=float) def evaluate(self, genome_id): #build phenotype cppn = CPPN(genome=self.population[genome_id], cppn_output_range=self.cppn_output_range) substrate = Substrate(CPPN=cppn, layers=self.layers, coords=self.coords, activation_function=self.activation_function, cppn_output_range=self.cppn_output_range) #play simulation observation = self.environment.reset() score = 0. while True: activations = substrate.querySubstrate(input_matrix=observation) action = np.argmax(activations) observation, reward, done, info = self.environment.step(action) score += reward if self.SHOW: self.environment.render() time.sleep(1. / 60) if done: return score return 0. def show(self): genome_id = np.nanargmax(self.fitness_scores) #build phenotype cppn = CPPN(genome=self.population[genome_id], cppn_output_range=self.cppn_output_range) substrate = Substrate(CPPN=cppn, layers=self.layers, coords=self.coords, activation_function=self.activation_function, cppn_output_range=self.cppn_output_range) #play simulation observation = self.environment.reset() while True: self.environment.render() time.sleep(1. / 24) activations = substrate.querySubstrate(input_matrix=observation) action = np.argmax(activations) observation, _, done, _ = self.environment.step(action) if done: self.environment.render() return """ Load (pre-trained) genomes from .genome files """ def loadGenomesFromFiles(self, path): self.lock.acquire() for genome_file in os.listdir(path): if genome_file.endswith(".genome"): with open(os.path.join(path, genome_file)) as f: try: genome = json.load(f) #.read() except: log(self, traceback.format_exc()) #genome = lambdaJSON.deserialize(serialized) genome['links'] = { int(key): genome['links'][key] for key in genome['links'] } self.population[int(genome_file.split('.')[0])] = genome self.lock.release() def writeGenomesToFiles(self, path): self.lock.acquire() for genome_id in self.partition: with open(path + '/' + str(genome_id).zfill(3) + '.genome', 'w+') as jf: json.dump(self.population[genome_id], jf) #jf.write(lambdaJSON.serialize(self.population[genome_id])) self.lock.release() def stopCondition(self): return False def buildStructures(self, input_shape, hidden_shapes, output_shape): #layers self.layers.append(np.zeros(input_shape)) for shape in hidden_shapes: self.layers.append(np.zeros(shape)) self.layers.append(np.zeros(output_shape)) l_coords = [] #coordinates l_axis = np.arange(-1., 1., 2. / len(self.layers)) + 1. / len(self.layers) if len(input_shape) == 1: #if layers are 1-D for l_id in range(len(self.layers) - 1): w_shape = self.layers[l_id + 1].shape + self.layers[l_id].shape l_coords.append( np.array( list( product( (np.arange(-1., 1., 2. / self.layers[l_id + 1].shape[0]) + 1. / self.layers[l_id + 1].shape[0]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id + 0].shape[0]) + 1. / self.layers[l_id + 0].shape[0] ).tolist()))).reshape(w_shape + (2, ))) l_coords[-1] = np.concatenate((np.array( [(l_axis[l_id], l_axis[l_id + 1])] * (l_coords[-1].shape[0] * l_coords[-1].shape[1])).reshape(l_coords[-1].shape[:-1] + (2, )), l_coords[-1]), axis=-1) elif len(input_shape) == 2: #if layers are 2-D for l_id in range(len(self.layers) - 1): w_shape = self.layers[l_id + 1].shape + self.layers[l_id].shape l_coords.append( np.array( list( product( (np.arange(-1., 1., 2. / self.layers[l_id + 1].shape[0]) + 1. / self.layers[l_id + 1].shape[0]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id + 1].shape[1]) + 1. / self.layers[l_id + 1].shape[1]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id].shape[0]) + 1. / self.layers[l_id].shape[0]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id].shape[1]) + 1. / self.layers[l_id].shape[1] ).tolist()))).reshape(w_shape + (4, ))) l_coords[-1] = np.concatenate((np.array( [(l_axis[l_id], l_axis[l_id + 1])] * (l_coords[-1].shape[0] * l_coords[-1].shape[1] * l_coords[-1].shape[2] * l_coords[-1].shape[3])).reshape(l_coords[-1].shape[:-1] + (2, )), l_coords[-1]), axis=-1) elif len(input_shape) == 3: for l_id in range(len(self.layers) - 1): #if layers are 3-D w_shape = self.layers[l_id + 1].shape + self.layers[l_id].shape l_coords.append( np.array( list( product( (np.arange(-1., 1., 2. / self.layers[l_id + 1].shape[0]) + 1. / self.layers[l_id + 1].shape[0]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id + 1].shape[1]) + 1. / self.layers[l_id + 1].shape[1]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id + 1].shape[2]) + 1. / self.layers[l_id + 1].shape[2]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id].shape[0]) + 1. / self.layers[l_id].shape[0]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id].shape[1]) + 1. / self.layers[l_id].shape[1]).tolist(), (np.arange(-1., 1., 2. / self.layers[l_id].shape[2]) + 1. / self.layers[l_id].shape[2] ).tolist()))).reshape(w_shape + (4, ))) l_coords[-1] = np.concatenate((np.array( [(l_axis[l_id], l_axis[l_id + 1])] * (l_coords[-1].shape[0] * l_coords[-1].shape[1] * l_coords[-1].shape[2] * l_coords[-1].shape[3] * l_coords[-1].shape[4] * l_coords[-1].shape[5])).reshape(l_coords[-1].shape[:-1] + (2, )), l_coords[-1]), axis=-1) self.coords = np.array(l_coords)
class Model: print_fps = False print_score = False gen_idx = 0 def __init__(self, maxframes): self.settings = self.initSettings() self.X, self.Y = self.loadData() self.crashed = False self.reader = GenomeReader(self) self.evolution = Evolution(self) self.evolution.loadGenomes('../res/genomes', 10) self.score = 0 self.best = 999999 self.startThreads() """INITIALIZATION""" def initSettings(self): settings = {} with open('../res/settings.txt', 'r') as f: for line in f: if len(line) > 1 and not line[0] == '#': line_data = (line.rstrip()).split("=") line_data = [(d.rstrip()).lstrip() for d in line_data] settings[line_data[0]] = line_data[ 1] if not line_data[1].isdigit() else float( line_data[1]) return settings def loadData(self): df = pd.read_csv('../../train.csv') X = df[[c for c in df.columns if c != 'SalePrice']] X_float = X.select_dtypes(exclude=['object']).fillna(0) y = df['SalePrice'] X.fillna('None', inplace=True) one_hot = pd.get_dummies(df) return (one_hot, y) def loadGenome(self): reader = GenomeReader(self) genome = reader.makeGenome('../res/genomes/best.dna', self) return genome def loadNetwork(self, genome): return Brain(genome, self) def startThreads(self): m_thread = MyThread(3, "ModelThread", self.loop) m_thread.start() m_thread.join() def reset(self): (self.gen_idx, genome) = self.evolution.getNextGenome() self.genome = genome self.network = self.loadNetwork(self.genome) self.score = 0 """GAME LOOP""" def loop(self): x = [row.tolist() for _, row in self.X.iterrows()] y = [price for price in self.Y] errs = [0] * len(x) epoch = 0 while not self.crashed: epoch += 1 if epoch % 10 == 0: self.settings = self.initSettings() self.sim_frames = int(self.settings['sim_frames']) self.reset() errs = [0] * len(x) for i, e in enumerate(x): pred = max(0, self.network.query(e)[0]) true = y[i] errs[i] = (np.log(pred + 1) - np.log(true + 1))**2 rmsle = np.sqrt(np.mean(errs)) self.evolution.reportFitness(self.gen_idx, 10. / rmsle) print(str(epoch) + " -> " + str(rmsle), end='\r') if rmsle < self.best: self.best = rmsle print("BEST: %s " % (str(rmsle)), end='\r') """GETTER METHODS""" def getSettings(self): return self.settings def getCrashed(self): return self.crashed def getGenome(self, name='player'): return self.entities[name].getGenome() def getNetwork(self, name='player'): return self.entities[name].getNetwork() def getScore(self): return self.score """SETTER METHODS""" def setCrashed(self, boolean): self.crashed = boolean
class Model: grid = [] manual = False print_fps = True print_score = False gen_idx = 0 map_name = "02.jpg" def __init__(self, maxframes): self.settings = self.initSettings() self.sim_frames = int(self.settings['sim_frames']) self.controller = Controller(self) self.view = View(self) self.crashed = False self.grid = self.initGrid() self.keys = {} self.reader = GenomeReader(self) self.evolution = Evolution(self) self.evolution.loadGenomes('../res/genomes', 1000) self.entities = { 'food': Consumable('food', 400, 300, 'Food', 0.5, self), 'player': NPC('player', 400, 220, 2, 10, 10, 'PC', 1, self.reader.makeGenome('../res/genomes/000000.dna'), self) } self.grid = self.addEntities2Grid() self.score = 0 self.maxframes = 0 self.startThreads() """INITIALIZATION""" def initSettings(self): settings = {} with open('../res/settings.txt', 'r') as f: for line in f: if len(line) > 1 and not line[0] == '#': line_data = (line.rstrip()).split("=") line_data = [(d.rstrip()).lstrip() for d in line_data] settings[line_data[0]] = line_data[ 1] if not line_data[1].isdigit() else float( line_data[1]) return settings def initGrid(self): self.builder = GridCreator(self) grid = self.builder.buildGrid("../res/grids/" + self.map_name) return grid def addEntities2Grid(self): return self.builder.addEntities(self.grid) def loadGenome(self): reader = GenomeReader(self) genome = reader.makeGenome('../res/genomes/000000.dna') return genome def loadNetwork(self, genome): return Brain(genome) def startThreads(self): c_thread = self.controller.start() v_thread = self.view.start() m_thread = MyThread(3, "ModelThread", self.loop) c_thread.start() v_thread.start() m_thread.start() c_thread.join() v_thread.join() m_thread.join() def reset(self): (self.gen_idx, genome) = self.evolution.getNextGenome() self.entities = { 'food': Consumable('food', 400, 300, 'Food', 0.5, self), 'player': NPC('player', 400, 220, 2, 10, 10, 'PC', 1, genome, self) } self.grid = self.addEntities2Grid() self.keys = {} self.genome = self.loadGenome() self.network = self.loadNetwork(self.genome) self.score = 0 """GAME LOOP""" def loop(self): start_time = time.time() last_frame_time = time.time() tmp = 0 epoch = 0 stop = False while not self.crashed: epoch += 1 if epoch % 10 == 0: self.settings = self.initSettings() self.sim_frames = int(self.settings['sim_frames']) self.reset() c_frame = 0 stopped = 0 while not self.crashed and c_frame < self.sim_frames: tmp += 1 c_frame += 1 last_frame_time = self.sleep(last_frame_time) for _, e in self.entities.items(): if e.canUpdate(): (oldx, oldy, newx, newy) = e.update() #update position in the grid if oldx != newx or oldy != newy: stopped = 0 self.grid[oldx][oldy].remEntity(e.getName()) self.grid[newx][newy].addEntity(e.getName()) if self.grid[newx][newy].contains('food'): self.grid[newx][newy].remEntity('food') self.spawnFood() self.score += 1 if self.print_score: print("Score: " + str(self.score), end='\r') else: stopped += 1 if tmp % 100 == 0: if self.print_fps: print("Running @ %.2f fps" % (float(tmp) / (time.time() - start_time)), end='\r') start_time = time.time() tmp = 0 if stopped >= 300: self.score -= 1 stopped = 0 break self.evolution.reportFitness(self.gen_idx, self.score + 1.) c_frame = 0 def sleep(self, last_frame_time): sleep_time = 1. / self.settings['game_FPS'] - (time.time() - last_frame_time) if sleep_time > 0: time.sleep(sleep_time) return last_frame_time + 1. / self.settings['game_FPS'] def spawnFood(self): (x, y) = (random.randint(0, 23), random.randint(0, 19)) while self.isBlocked(x * 32 + 16, y * 32 + 16): #print( str(x) + "," + str(y) ) (x, y) = (random.randint(0, 23), random.randint(0, 19)) self.entities['food'] = Consumable('food', x * 32 + 16, y * 32 + 16, 'Food', 0.5, self) self.grid[x][y].addEntity('food') """GETTER METHODS""" def isBlocked(self, x, y, name=None): (x_grid, y_grid) = self.getGridPosition(x, y) tile = self.grid[x_grid][y_grid] if tile.isEmpty(): return False else: contents = [ n for n in tile.getContents() if (n == 'wall' or self.entities[n].getBlocking()) ] if name == None and len(contents) > 0: return True else: return not len([n for n in contents if n != name]) == 0 def getSettings(self): return self.settings def getCrashed(self): return self.crashed def getKey(self, key): try: return self.keys[key] except KeyError: return False def getEntities(self): return self.entities def getGridPosition(self, x, y): return (int((x) / 32), int((y) / 32)) def getGrid(self): return self.grid def getGenome(self, name='player'): return self.entities[name].getGenome() def getNetwork(self, name='player'): return self.entities[name].getNetwork() def getMapName(self): return self.map_name def getScore(self): return self.score """SETTER METHODS""" def setCrashed(self, boolean): self.crashed = boolean def setKey(self, key, boolean): self.keys[key] = boolean
class Controller: """ Class which glues the project components together """ def __init__(self): self.minimap = None self.connections = None self.vehicles = None self.layers = None self.evolution = None self.presenter = None self.core = None self.ai = None def load_system(self, system, ai): """ Load the system from a YAML file """ self.ai = ai with open(system, 'r') as f: system = yaml.load(f) self.minimap = system['minimap'] self.connections = system['connections'] self.vehicles = system.get('vehicles', 40) self.core = Core(self.minimap, self.connections, self.vehicles) hidden_layers = layers = system.get('layers', []) side_neurons = len(self.core.junction_queues) self.layers = [side_neurons] + hidden_layers + [side_neurons] self.evolution = Evolution(self.layers) def present(self): """ Called when the user wants to run the simulation with GUI """ nn = self.evolution.get_nn(numpy.load(self.ai)) if self.ai else None self.core.reset(nn) self.presenter = Presenter(self.connections, self.minimap, (900, 900)) self.presenter.main_loop(self.core) def validate(self): pass def develop(self): """ Called when the user wants to train the AI for a given system from YAML """ try: while True: self.__train() print('') finally: with open(self.ai, 'wb') as f: numpy.save(f, self.evolution.best_fit['weights']) def __train(self): """ Evaluate the population of current generation and breed them """ for index, individual in enumerate(self.evolution.queue): self.evolution.rated(individual, self.__rate(individual)) if index % 5 == 0: print('.', end='') sys.stdout.flush() self.evolution.breed() def __rate(self, individual): """ Evaluate how good the AI was """ self.core.reset(self.evolution.get_nn(individual['weights'])) stucked = 0 for _ in range(TEST_STEPS): self.core.step() for link in self.core.links: stucked += link.stucked for ap in self.core.access_points: if ap.inactive: stucked += ap.to_generate return stucked