def __init__(self, name, network, graphical, pos=(0, 0), obstacles=None): super().__init__(network) self.graphical = graphical self.name = name self.rect = pg.Rect(pos, SurvivalPeepo.SIZE) self.rect.center = pos self.rotation = 0 self.edge_right = end_line(SurvivalPeepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(SurvivalPeepo.RADIUS, self.rotation - 30, self.rect.center) self.edge_middle = end_line(SurvivalPeepo.RADIUS, self.rotation, self.rect.center) if self.graphical: self.image = self.make_image() self.image_original = self.image.copy() self.health = 0 self.obstacles = obstacles or [] self.motor = { LEFT: False, RIGHT: False } self.view = { '1': False, '2': False, '3': False, '4': False, '5': False, '6': False, } self.generative_model = GenerativeModel(self, n_jobs=1)
def __init__(self, network, action_space, observation_space): super().__init__(network) self.action_space = action_space self.observation_space = observation_space self.obs = np.empty(4) self.reward = 0 self.done = False self.act = 0 self.generative_model = GenerativeModel(self, n_jobs=4)
def __init__(self, name, network, pos=(0, 0)): super().__init__(network) self.name = name self.rect = pg.Rect(pos, Portia.SIZE) self.rect.center = pos self.rotation = 0 self.image = self.make_image() self.image_original = self.image.copy() self.generative_model = GenerativeModel(self, n_jobs=1)
class PeepoAgent(Peepo): def __init__(self, network, action_space, observation_space): super().__init__(network) self.action_space = action_space self.observation_space = observation_space self.obs = np.empty(4) self.reward = 0 self.done = False self.act = 0 self.generative_model = GenerativeModel(self, n_jobs=4) def update(self, obz, rewardz, donez): self.obs = obz self.reward = rewardz self.done = donez self.generative_model.process() return self.act def observation(self, name): if VISION.lower() in name.lower(): quad = self.get_quadrant(name) return self.normalized_distribution( self.obs[quad], self.observation_space.low[quad], self.observation_space.high[quad]) if MOTOR.lower() in name.lower(): return [0.1, 0.9] if self.act else [0.9, 0.1] logging.warning( 'Reached code which should not be reached in observation') return [0.5, 0.5] def action(self, node, prediction): self.act = np.argmax(prediction) @staticmethod def normalized_distribution(value, mini, maxi, target_min=0, target_max=1): if str(maxi) == '3.4028235e+38': mini, maxi = -1, 1 x = target_max * ((value - mini) / (maxi - mini)) + target_min return np.array([x, 1 - x]) @staticmethod def get_quadrant(name): for quad in ['0', '1', '2', '3']: if quad.lower() in name.lower(): return int(quad) raise ValueError('Unexpected node name %s, could not find 0,1,2,3', name)
def __init__(self, name, network, graphical, pos=(0, 0)): super().__init__(network) self.graphical = graphical self.name = name self.rect = pg.Rect(pos, AntPeepo.SIZE) self.rect.center = pos self.rotation = 0 if self.graphical: self.image = self.make_image() self.image_original = self.image.copy() self.motor = {LEFT: False, RIGHT: False} self.generative_model = GenerativeModel(self, n_jobs=1) self.path = []
class Portia(Peepo): SIZE = (4, 4) RADIUS = 50 SPEED = 2 def __init__(self, name, network, pos=(0, 0)): super().__init__(network) self.name = name self.rect = pg.Rect(pos, Portia.SIZE) self.rect.center = pos self.rotation = 0 self.image = self.make_image() self.image_original = self.image.copy() self.generative_model = GenerativeModel(self, n_jobs=1) def observation(self, name): return [0.0, 0.0] def action(self, node, prediction): pass def update(self): self.generative_model.process() self.rect.x += Portia.SPEED * math.cos(math.radians(self.rotation)) self.rect.y += Portia.SPEED * math.sin(math.radians(self.rotation)) self.image = pg.transform.rotate(self.image_original, -self.rotation) self.rect = self.image.get_rect(center=self.rect.center) if self.rect.x < 0 or self.rect.y < 0 or self.rect.x > 800 or self.rect.y > 800: self.rect.x, self.rect.y = 400, 400 def draw(self, surface): surface.blit(self.image, self.rect) def make_image(self): image = pg.Surface(self.rect.size).convert_alpha() image.fill((0, 0, 0, 0)) image_rect = image.get_rect() pg.draw.rect(image, pg.Color("black"), image_rect) pg.draw.rect(image, pg.Color("green"), image_rect.inflate(-2, -2)) return image
def __init__(self, name, network, graphical, pos=(0, 0), ennemies=None, food=None): self.graphical = graphical self.name = name self.network = network self.rect = pg.Rect(pos, Peepo.SIZE) self.rect.center = pos self.rotation = 0 self.edge_right = end_line(Peepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(Peepo.RADIUS, self.rotation - 30, self.rect.center) self.edge_middle = end_line(Peepo.RADIUS, self.rotation, self.rect.center) if self.graphical: self.image = self.make_image() self.image_original = self.image.copy() self.stomach = 0 self.bang = 0 self.ennemies = ennemies or [] self.food = food or [] self.obstacles = [] self.assemble_obstacles() self.motor = {LEFT: False, RIGHT: False} self.view = { '1': False, '2': False, '3': False, '4': False, } self.is_an_enemy = False self.is_food = False self.generative_model = GenerativeModel(network, SensoryInputPeepo(self), n_jobs=1)
def __init__(self, peepo_actor, actors): super().__init__(self.create_model()) self.peepo_actor = peepo_actor self.actors = actors self.motor_output = {pg.K_LEFT: False, pg.K_RIGHT: False} self.obstacle_input = {'1': False, '2': False, '3': False, '4': False, '5': False, '6': False} self.wander_left_chance = 0 self.wander_right_chance = 0 self.wandering_left = False self.wandering_right = False self.genmodel = GenerativeModel(self)
def create_network(): network = BayesianModel([('A', 'B')]) cpd_a = TabularCPD(variable='A', variable_card=2, values=[[0.2, 0.8]]) cpd_b = TabularCPD(variable='B', variable_card=2, values=[[0.1, 0.7], [0.9, 0.3]], evidence=['A'], evidence_card=[2]) network.add_cpds(cpd_a, cpd_b) network.check_model() return GenerativeModel(TestSensoryInput(), network)
def test_topology(self): self.networx_test = self.networx.copy() self.pgmpy_test = self.pgmpy.copy() model = {'main': GenerativeModel(SensoryInputVirtualPeepo(self), self.pgmpy_test)} expected_result = [0,0,0] ''' ------ going through all possible "colors''' for color in range(0, self.number_of_colors): states = self.colors_table[:,color] shape = self.colors_cpd.values.shape reshaped_cpd = self.colors_cpd.values.reshape(shape[0], int(np.prod(shape) / shape[0])) expected_result = reshaped_cpd[:,int(color)] for i, pixel in enumerate(states): cardinality = self.pgmpy_test.get_cardinality('BENS_'+str(i)) self.pgmpy_test.get_cpds('BENS_' + str(i)).values = CPD.create_fixed_parent(cardinality, state = int(pixel)) self.do_inference(model ,expected_result)
def create_network_for_add_edge(): """ Note: adding an edge where the values are duplicated from the existing connecting nodes won't change predictions at all. Since it will just take on the value of the pre-existing state, given that we duplicate the values... Maybe go back to 0.5 0.5 defaults? """ network = BayesianModel([('A', 'B'), ('C', 'D')]) cpd_a = TabularCPD(variable='A', variable_card=2, values=[[0.4, 0.6]]) cpd_b = TabularCPD(variable='B', variable_card=2, values=[[0.1, 0.9], [0.9, 0.1]], evidence=['A'], evidence_card=[2]) cpd_c = TabularCPD(variable='C', variable_card=2, values=[[0.6, 0.4]]) cpd_d = TabularCPD(variable='D', variable_card=2, values=[[0.8, 0.9], [0.2, 0.1]], evidence=['C'], evidence_card=[2]) network.add_cpds(cpd_a, cpd_b, cpd_c, cpd_d) network.check_model() return GenerativeModel(TestSensoryInput(), network)
class GoLPeepo(Peepo): """ This organism represents peepo. Each peepo takes as parameters a name, an initial position and the list of obstacles present in its environment. """ SIZE = (4, 4) RADIUS = 50 SPEED = 2 def __init__(self, name, network, graphical, pos=(0, 0), ennemies=None, food=None): super().__init__(network) self.graphical = graphical self.name = name self.rect = pg.Rect(pos, GoLPeepo.SIZE) self.rect.center = pos self.rotation = 0 self.edge_right = end_line(GoLPeepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(GoLPeepo.RADIUS, self.rotation - 30, self.rect.center) if self.graphical: self.image = self.make_image() self.image_original = self.image.copy() self.stomach = 0 self.bang = 0 self.ennemies = ennemies or [] self.food = food or [] self.obstacles = [] self.assemble_obstacles() self.motor = {LEFT: False, RIGHT: False} self.view = { '1': False, '2': False, '3': False, '4': False, '5': False, '6': False, } self.is_an_enemy = False self.is_food = False self.generative_model = GenerativeModel(self, n_jobs=1) def assemble_obstacles(self): for i, x in enumerate(self.food): self.obstacles.append([x, 0, i]) for i, x in enumerate(self.ennemies): self.obstacles.append([x, 1, i]) def observation(self, name): if VISION.lower() in name.lower(): return [0.1, 0.9 ] if self.view[self.get_quadrant(name)] else [0.9, 0.1] if MOTOR.lower() in name.lower(): return [0.1, 0.9 ] if self.motor[self.get_direction(name)] else [0.9, 0.1] if ID_ENNEMY.lower() in name.lower(): return [0.1, 0.9] if self.is_an_enemy else [0.9, 0.1] if ID_FOOD.lower() in name.lower(): return [0.1, 0.9] if self.is_food else [0.9, 0.1] def action(self, node, prediction): if np.argmax(prediction) == 0: self.motor[self.get_direction(node)] = False else: self.motor[self.get_direction(node)] = True @staticmethod def get_quadrant(name): for quad in ['1', '2', '3', '4', '5', '6']: if quad.lower() in name.lower(): return quad raise ValueError('Unexpected node name %s, could not find 1,2,3,4,5,6', name) @staticmethod def get_direction(name): for direction in [LEFT, RIGHT]: if direction.lower() in name.lower(): return direction raise ValueError('Unexpected node name %s, could not find LEFT, RIGHT', name) def update(self): self.generative_model.process() self.rect.x += GoLPeepo.SPEED * math.cos(math.radians(self.rotation)) self.rect.y += GoLPeepo.SPEED * math.sin(math.radians(self.rotation)) if self.motor[LEFT]: self.rotation -= 10 if self.rotation < 0: self.rotation = 360 if self.motor[RIGHT]: self.rotation += 10 if self.rotation > 360: self.rotation = 0 self.calculate_obstacles() if self.graphical: self.image = pg.transform.rotate(self.image_original, -self.rotation) self.rect = self.image.get_rect(center=self.rect.center) self.edge_right = end_line(GoLPeepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(GoLPeepo.RADIUS, self.rotation - 30, self.rect.center) if self.rect.x < 0 or self.rect.y < 0 or self.rect.x > 800 or self.rect.y > 800: self.rect.x, self.rect.y = 400, 400 def draw(self, surface): surface.blit(self.image, self.rect) pg.draw.line(surface, pg.Color("red"), self.rect.center, self.edge_right, 2) pg.draw.line(surface, pg.Color("green"), self.rect.center, self.edge_left, 2) def make_image(self): image = pg.Surface(self.rect.size).convert_alpha() image.fill(TRANSPARENT) image_rect = image.get_rect() pg.draw.rect(image, pg.Color("black"), image_rect) pg.draw.rect(image, pg.Color("green"), image_rect.inflate(-2, -2)) return image def calculate_obstacles(self): self.view = {x: False for x in self.view} self.is_an_enemy = False self.is_food = False observations = self.obstacles for obstacle in observations: if self.rect.colliderect(obstacle[0].rect): if obstacle[1] == 0: self.stomach += 1 self.obstacles.remove(obstacle) else: self.bang += 1 # self.obstacles.remove(obstacle) peepo_vec = pg.math.Vector2(self.rect.center) if collision(obstacle[0].rect, peepo_vec, self.edge_left, self.edge_right, GoLPeepo.RADIUS): edge1 = end_line(GoLPeepo.RADIUS, self.rotation - 30, self.rect.center) edge2 = end_line(GoLPeepo.RADIUS, self.rotation - 20, self.rect.center) edge3 = end_line(GoLPeepo.RADIUS, self.rotation - 10, self.rect.center) edge4 = end_line(GoLPeepo.RADIUS, self.rotation, self.rect.center) edge5 = end_line(GoLPeepo.RADIUS, self.rotation + 10, self.rect.center) edge6 = end_line(GoLPeepo.RADIUS, self.rotation + 20, self.rect.center) edge7 = end_line(GoLPeepo.RADIUS, self.rotation + 30, self.rect.center) self.view['1'] = collision(obstacle[0].rect, peepo_vec, edge1, edge2, GoLPeepo.RADIUS) self.view['2'] = collision(obstacle[0].rect, peepo_vec, edge2, edge3, GoLPeepo.RADIUS) self.view['3'] = collision(obstacle[0].rect, peepo_vec, edge3, edge4, GoLPeepo.RADIUS) self.view['4'] = collision(obstacle[0].rect, peepo_vec, edge4, edge5, GoLPeepo.RADIUS) self.view['5'] = collision(obstacle[0].rect, peepo_vec, edge5, edge6, GoLPeepo.RADIUS) self.view['6'] = collision(obstacle[0].rect, peepo_vec, edge6, edge7, GoLPeepo.RADIUS) if obstacle[1] == 1: self.is_an_enemy = True if obstacle[1] == 0: self.is_food = True self.food = [] [self.food.append(x[0]) for x in self.obstacles if x[1] == 0]
class SurvivalPeepo(Peepo): """ This organism represents peepo. Each peepo takes as parameters a name, an initial position and the list of obstacles present in its environment. """ SIZE = (4, 4) RADIUS = 50 SPEED = 2 def __init__(self, name, network, graphical, pos=(0, 0), obstacles=None): super().__init__(network) self.graphical = graphical self.name = name self.rect = pg.Rect(pos, SurvivalPeepo.SIZE) self.rect.center = pos self.rotation = 0 self.edge_right = end_line(SurvivalPeepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(SurvivalPeepo.RADIUS, self.rotation - 30, self.rect.center) self.edge_middle = end_line(SurvivalPeepo.RADIUS, self.rotation, self.rect.center) if self.graphical: self.image = self.make_image() self.image_original = self.image.copy() self.health = 0 self.obstacles = obstacles or [] self.motor = { LEFT: False, RIGHT: False } self.view = { '1': False, '2': False, '3': False, '4': False, '5': False, '6': False, } self.generative_model = GenerativeModel(self, n_jobs=1) def observation(self, name): if VISION.lower() in name.lower(): return [0.1, 0.9] if self.view[self.get_quadrant(name)] else [0.9, 0.1] if MOTOR.lower() in name.lower(): return [0.1, 0.9] if self.motor[self.get_direction(name)] else [0.9, 0.1] return [0.5, 0.5] def action(self, node, prediction): if np.argmax(prediction) == 0: self.motor[self.get_direction(node)] = False else: self.motor[self.get_direction(node)] = True @staticmethod def get_quadrant(name): for quad in ['1', '2', '3', '4', '5', '6']: if quad.lower() in name.lower(): return quad raise ValueError('Unexpected node name %s, could not find 1,2,3,4,5,6', name) @staticmethod def get_direction(name): for direction in [LEFT, RIGHT]: if direction.lower() in name.lower(): return direction raise ValueError('Unexpected node name %s, could not find LEFT, RIGHT', name) def update(self): self.generative_model.process() self.rect.x += SurvivalPeepo.SPEED * math.cos(math.radians(self.rotation)) self.rect.y += SurvivalPeepo.SPEED * math.sin(math.radians(self.rotation)) if self.motor[LEFT]: self.rotation -= 10 if self.rotation < 0: self.rotation = 360 if self.motor[RIGHT]: self.rotation += 10 if self.rotation > 360: self.rotation = 0 self.edge_middle = end_line(SurvivalPeepo.RADIUS, self.rotation, self.rect.center) self.calculate_obstacles() if self.graphical: self.image = pg.transform.rotate(self.image_original, -self.rotation) self.rect = self.image.get_rect(center=self.rect.center) self.edge_right = end_line(SurvivalPeepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(SurvivalPeepo.RADIUS, self.rotation - 30, self.rect.center) if self.rect.x < 0 or self.rect.y < 0 or self.rect.x > 800 or self.rect.y > 800: self.rect.x, self.rect.y = 400, 400 def draw(self, surface): surface.blit(self.image, self.rect) pg.draw.line(surface, pg.Color("red"), self.rect.center, self.edge_right, 2) pg.draw.line(surface, pg.Color("green"), self.rect.center, self.edge_left, 2) def make_image(self): image = pg.Surface(self.rect.size).convert_alpha() image.fill(TRANSPARENT) image_rect = image.get_rect() pg.draw.rect(image, pg.Color("black"), image_rect) pg.draw.rect(image, pg.Color("green"), image_rect.inflate(-2, -2)) return image def calculate_obstacles(self): self.view = {x: False for x in self.view} peepo_vec = pg.math.Vector2(self.rect.center) min_distance = 1000 closest_obstacle = None for obstacle in self.obstacles: if self.rect.colliderect(obstacle.rect): self.health += 1 self.obstacles.remove(obstacle) if collision(obstacle.rect, peepo_vec, self.edge_left, self.edge_right, SurvivalPeepo.RADIUS): distance = math.hypot(obstacle.rect.x - self.rect.x, obstacle.rect.y - self.rect.y) if distance <= min_distance: closest_obstacle = obstacle min_distance = distance if closest_obstacle: edge1 = end_line(SurvivalPeepo.RADIUS, self.rotation - 30, self.rect.center) edge2 = end_line(SurvivalPeepo.RADIUS, self.rotation - 20, self.rect.center) edge3 = end_line(SurvivalPeepo.RADIUS, self.rotation - 10, self.rect.center) edge4 = end_line(SurvivalPeepo.RADIUS, self.rotation, self.rect.center) edge5 = end_line(SurvivalPeepo.RADIUS, self.rotation + 10, self.rect.center) edge6 = end_line(SurvivalPeepo.RADIUS, self.rotation + 20, self.rect.center) edge7 = end_line(SurvivalPeepo.RADIUS, self.rotation + 30, self.rect.center) self.view['1'] = collision(closest_obstacle.rect, peepo_vec, edge1, edge2, SurvivalPeepo.RADIUS) self.view['2'] = collision(closest_obstacle.rect, peepo_vec, edge2, edge3, SurvivalPeepo.RADIUS) self.view['3'] = collision(closest_obstacle.rect, peepo_vec, edge3, edge4, SurvivalPeepo.RADIUS) self.view['4'] = collision(closest_obstacle.rect, peepo_vec, edge4, edge5, SurvivalPeepo.RADIUS) self.view['5'] = collision(closest_obstacle.rect, peepo_vec, edge5, edge6, SurvivalPeepo.RADIUS) self.view['6'] = collision(closest_obstacle.rect, peepo_vec, edge6, edge7, SurvivalPeepo.RADIUS)
logging.basicConfig() logging.getLogger().setLevel(logging.DEBUG) class Baby: def __init__(self): self.limbs = { md.LEFT_ARM: False, md.RIGHT_ARM: False, md.LEFT_FOOT: False, md.RIGHT_FOOT: False } model = GenerativeModel(md.baby_model(), SensoryInputCribBaby(Baby(), Crib())) while True: model.process() # def run(): # model = GenerativeModel(SensoryInputCribBaby(Baby(), Crib()), md.fully_connected_model()) # # model.process() # original_model = model.network.copy() # edges = original_model.edges() # # result = {} # # for x in range(0, len(edges) + 1): # subresult = [] # for cmb in itertools.combinations(edges, x):
def create_networks(self): gamma = 1 # this controls how steep the discrimination will be between the classes (gamma << 1 low discrimination, gamma >> 1 : high discrimination sigma = 1 # this controls how steep the squeezing of the action will be index_jump = int( self.raptor_actor.alfa_increment / self.resolution ) #calculates the number of "sector jumps" dpeending on the tuple alfa_ainvrement and sector_resolution index_jump = 2 # print("Index gamma ", index_gamma) ParentNodes = [] ParentNodes.append("MEM_vision_left") ParentNodes.append("MEM_vision_right") ParentNodes.append("BEN_Correction") ParentNodes.append("BEN_Direction") #ParentNodes.append("Reward_Predicted") count = 0 while count < len(ParentNodes): self.network.add_node(ParentNodes[count]) count = count + 1 LeafNodes = [] LeafNodes.append("LEN_vision_left") LeafNodes.append("LEN_vision_right") LeafNodes.append("LEN_motor_Correction") LeafNodes.append("LEN_motor_Direction") count = 0 while count < len(LeafNodes): self.network.add_node(LeafNodes[count]) count = count + 1 self.network.add_edge(ParentNodes[0], LeafNodes[0]) self.network.add_edge(ParentNodes[2], LeafNodes[0]) self.network.add_edge(ParentNodes[3], LeafNodes[0]) self.network.add_edge(ParentNodes[1], LeafNodes[1]) self.network.add_edge(ParentNodes[2], LeafNodes[1]) self.network.add_edge(ParentNodes[3], LeafNodes[1]) self.network.add_edge(ParentNodes[2], LeafNodes[2]) self.network.add_edge(ParentNodes[3], LeafNodes[3]) CPD_Parents = [] CPD_Parents.append( CPD.parent_cpd( ParentNodes[0], self.cardinality_vision, int(random.uniform(0, self.cardinality_vision - 0.4)), sigma / 2, "fixed")) CPD_Parents.append( CPD.parent_cpd( ParentNodes[1], self.cardinality_vision, int(random.uniform(0, self.cardinality_vision - 0.4)), sigma / 2, "fixed")) CPD_Parents.append( CPD.parent_cpd( ParentNodes[2], self.cardinality_correction, int(random.uniform(0, self.cardinality_correction - 0.4)), sigma / 2, "fixed")) CPD_Parents.append( CPD.parent_cpd( ParentNodes[3], self.cardinality_direction, int(random.uniform(0, self.cardinality_direction - 0.4)), sigma / 2, "fixed")) for n in range(0, len(CPD_Parents)): self.network.add_cpds(CPD_Parents[n]) CPD_Leafs = [] CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[0], self.cardinality_vision, [ self.cardinality_vision, self.cardinality_correction, self.cardinality_direction ], [ParentNodes[0], ParentNodes[2], ParentNodes[3]], 'left_vision', index_jump)) CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[1], self.cardinality_vision, [ self.cardinality_vision, self.cardinality_correction, self.cardinality_direction ], [ParentNodes[1], ParentNodes[2], ParentNodes[3]], 'right_vision', index_jump)) CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[2], self.cardinality_correction, [self.cardinality_correction], [ParentNodes[2]], 'one_2_one', index_jump)) CPD_Leafs.append( CPD.leaf_cpd(LeafNodes[3], self.cardinality_direction, [self.cardinality_direction], [ParentNodes[3]], 'one_2_one', index_jump)) for n in range(0, len(CPD_Leafs)): self.network.add_cpds(CPD_Leafs[n]) self.network.check_model() #draw_network(self.network) '''for n in range(0,len(CPD_Latents)): print("Latents :") print(CPD_Latents[n])''' for n in range(0, len(CPD_Leafs)): print("Leafs :") print(CPD_Leafs[n]) #wait = input("PRESS ENTER TO CONTINUE.") relevant_parent_nodes = [2, 3] return { 'main': GenerativeModel(SensoryInputVirtualPeepo(self), self.network) }
class AntPeepo(Peepo): """ This organism represents peepo. """ SIZE = (4, 4) RADIUS = 50 SPEED = 2 def __init__(self, name, network, graphical, pos=(0, 0)): super().__init__(network) self.graphical = graphical self.name = name self.rect = pg.Rect(pos, AntPeepo.SIZE) self.rect.center = pos self.rotation = 0 if self.graphical: self.image = self.make_image() self.image_original = self.image.copy() self.motor = {LEFT: False, RIGHT: False} self.generative_model = GenerativeModel(self, n_jobs=1) self.path = [] def observation(self, name): if MOTOR.lower() in name.lower(): return [0.1, 0.9 ] if self.motor[self.get_direction(name)] else [0.9, 0.1] return [0.5, 0.5] def action(self, node, prediction): if np.argmax(prediction) == 0: self.motor[self.get_direction(node)] = False else: self.motor[self.get_direction(node)] = True @staticmethod def get_direction(name): for direction in [LEFT, RIGHT]: if direction.lower() in name.lower(): return direction raise ValueError('Unexpected node name %s, could not find LEFT, RIGHT', name) def update(self): self.generative_model.process() self.drift_hypotheses() self.rect.x += AntPeepo.SPEED * math.cos(math.radians(self.rotation)) self.rect.y += AntPeepo.SPEED * math.sin(math.radians(self.rotation)) if self.motor[LEFT]: self.rotation -= 10 if self.rotation < 0: self.rotation = 360 if self.motor[RIGHT]: self.rotation += 10 if self.rotation > 360: self.rotation = 0 if self.graphical: self.image = pg.transform.rotate(self.image_original, -self.rotation) self.rect = self.image.get_rect(center=self.rect.center) if self.rect.x < 0: self.rect.x = 799 if self.rect.x > 800: self.rect.x = 1 if self.rect.y < 0: self.rect.y = 799 if self.rect.y > 800: self.rect.y = 1 self.path.append((self.rect.x, self.rect.y)) def drift_hypotheses(self): for root in self.generative_model.get_roots(): root_index = self.generative_model.get_node_index(root.name) if random.choice([0, 1]): old_hypo = self.generative_model.bayesian_network.states[ root_index].distribution.items() moving = [old_hypo[0][1], old_hypo[1][1]] if np.argmax(moving): # ~ [0.1, 0.9] -> [0.9, 0.1] change = 0.05 if moving[1] - change < 0.1: moving = [0.9, 0.1] else: moving = [moving[0] + change, moving[1] - change] else: # ~ [0.9, 0.1] -> [0.1, 0.9] change = 0.1 if moving[0] - change < 0.1: moving = [0.1, 0.9] else: moving = [moving[0] - change, moving[1] + change] new_hypo = {0: moving[0], 1: moving[1]} self.generative_model.bayesian_network.states[ root_index].distribution = DiscreteDistribution(new_hypo) def draw(self, surface): surface.blit(self.image, self.rect) for step in self.path: surface.set_at(step, pg.Color("red")) def make_image(self): image = pg.Surface(self.rect.size).convert_alpha() image.fill(TRANSPARENT) image_rect = image.get_rect() pg.draw.rect(image, pg.Color("black"), image_rect) pg.draw.rect(image, pg.Color("green"), image_rect.inflate(-2, -2)) return image
class WanderingPeepo(Peepo): RADIUS = 100 WAN_LEFT = 'RON_wandering_left' WAN_RIGHT = 'RON_wandering_right' OBS_LEFT = 'RON_obstacle_left' OBS_RIGHT = 'RON_obstacle_right' MOT_LEFT = 'LEN_motor_left' MOT_RIGHT = 'LEN_motor_right' VIS_1 = 'LEN_vision_1' VIS_2 = 'LEN_vision_2' VIS_3 = 'LEN_vision_3' VIS_4 = 'LEN_vision_4' VIS_5 = 'LEN_vision_5' VIS_6 = 'LEN_vision_6' def __init__(self, peepo_actor, actors): super().__init__(self.create_model()) self.peepo_actor = peepo_actor self.actors = actors self.motor_output = {pg.K_LEFT: False, pg.K_RIGHT: False} self.obstacle_input = {'1': False, '2': False, '3': False, '4': False, '5': False, '6': False} self.wander_left_chance = 0 self.wander_right_chance = 0 self.wandering_left = False self.wandering_right = False self.genmodel = GenerativeModel(self) def action(self, node, prediction): # prediction [0.9, 0.1] = STOP # prediction [0.1, 0.9] = START if np.argmax(prediction) == 0: if 'left' in node: self.motor_output[pg.K_LEFT] = False if 'right' in node: self.motor_output[pg.K_RIGHT] = False else: if 'left' in node: self.motor_output[pg.K_LEFT] = True if 'right' in node: self.motor_output[pg.K_RIGHT] = True def observation(self, name): if 'vision' in name: # prediction [0.9, 0.1] = NO OBSTACLE # prediction [0.1, 0.9] = OBSTACLE if '1' in name: return np.array([0.1, 0.9]) if self.obstacle_input['1'] else np.array([0.9, 0.1]) if '2' in name: return np.array([0.1, 0.9]) if self.obstacle_input['2'] else np.array([0.9, 0.1]) if '3' in name: return np.array([0.1, 0.9]) if self.obstacle_input['3'] else np.array([0.9, 0.1]) if '4' in name: return np.array([0.1, 0.9]) if self.obstacle_input['4'] else np.array([0.9, 0.1]) if '5' in name: return np.array([0.1, 0.9]) if self.obstacle_input['5'] else np.array([0.9, 0.1]) if '6' in name: return np.array([0.1, 0.9]) if self.obstacle_input['6'] else np.array([0.9, 0.1]) elif 'motor' in name: # prediction [0.9, 0.1] = STOPPED # prediction [0.1, 0.9] = MOVING if 'left' in name: return np.array([0.1, 0.9]) if self.motor_output[pg.K_LEFT] else np.array([0.9, 0.1]) if 'right' in name: return np.array([0.1, 0.9]) if self.motor_output[pg.K_RIGHT] else np.array([0.9, 0.1]) def update(self): network = self.genmodel.bayesian_network # [0.9, 0.1] = OFF # [0.1, 0.9] = ON if self.wandering_left: state = network.states[self.genmodel.get_node_index(self.WAN_LEFT)] state.distribution = DiscreteDistribution(change_distribution(state.distribution.items(), [0.9, 0.1])) self.wander_left_chance = 0 self.wandering_left = False else: self.wander_left_chance += 0.1 if random.randint(0, 100) <= self.wander_left_chance: state = network.states[self.genmodel.get_node_index(self.WAN_LEFT)] state.distribution = DiscreteDistribution(change_distribution(state.distribution.items(), [0.1, 0.9])) self.wandering_left = True if self.wandering_right: state = network.states[self.genmodel.get_node_index(self.WAN_RIGHT)] state.distribution = DiscreteDistribution(change_distribution(state.distribution.items(), [0.9, 0.1])) self.wander_right_chance = 0 self.wandering_right = False else: self.wander_right_chance += 0.1 if random.randint(0, 100) <= self.wander_right_chance: state = network.states[self.genmodel.get_node_index(self.WAN_RIGHT)] state.distribution = DiscreteDistribution(change_distribution(state.distribution.items(), [0.1, 0.9])) self.wandering_right = True def create_model(self): pp_network = PeepoNetwork( ron_nodes=[ {'name': self.WAN_LEFT, 'card': 2}, {'name': self.WAN_RIGHT, 'card': 2}, {'name': self.OBS_LEFT, 'card': 2}, {'name': self.OBS_RIGHT, 'card': 2} ], ext_nodes=[ {'name': self.VIS_1, 'card': 2}, {'name': self.VIS_2, 'card': 2}, {'name': self.VIS_3, 'card': 2}, {'name': self.VIS_4, 'card': 2}, {'name': self.VIS_5, 'card': 2}, {'name': self.VIS_6, 'card': 2} ], pro_nodes=[ {'name': self.MOT_LEFT, 'card': 2}, {'name': self.MOT_RIGHT, 'card': 2} ], edges=[ (self.WAN_LEFT, self.MOT_LEFT), (self.WAN_RIGHT, self.MOT_RIGHT), (self.OBS_LEFT, self.MOT_RIGHT), (self.OBS_RIGHT, self.MOT_LEFT), (self.OBS_LEFT, self.VIS_1), (self.OBS_LEFT, self.VIS_2), (self.OBS_LEFT, self.VIS_3), (self.OBS_RIGHT, self.VIS_4), (self.OBS_RIGHT, self.VIS_5), (self.OBS_RIGHT, self.VIS_6), ], cpds={ self.WAN_LEFT: [0.9, 0.1], self.WAN_RIGHT: [0.9, 0.1], self.OBS_LEFT: [0.9, 0.1], self.OBS_RIGHT: [0.9, 0.1], self.VIS_1: [[0.9, 0.1], [0.1, 0.9]], self.VIS_2: [[0.9, 0.1], [0.1, 0.9]], self.VIS_3: [[0.9, 0.1], [0.1, 0.9]], self.VIS_4: [[0.9, 0.1], [0.1, 0.9]], self.VIS_5: [[0.9, 0.1], [0.1, 0.9]], self.VIS_6: [[0.9, 0.1], [0.1, 0.9]], self.MOT_LEFT: [[0.9, 0.1, 0.1, 0.1], [0.1, 0.9, 0.9, 0.9]], self.MOT_RIGHT: [[0.9, 0.1, 0.1, 0.1], [0.1, 0.9, 0.9, 0.9]], }) pp_network.assemble() return pp_network def process(self): self.calculate_obstacles() self.genmodel.process() def calculate_obstacles(self): for key in self.obstacle_input: self.obstacle_input[key] = False for actor in self.actors: peepo_vec = vec(self.peepo_actor.rect.center) collided = collision(actor.rect, peepo_vec, self.peepo_actor.edge_left, self.peepo_actor.edge_right, WanderingPeepo.RADIUS) if collided: if 'wall' in actor.id: edge = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation, self.peepo_actor.rect.center) if 'left' in actor.id: wall_vec = vec((5, self.peepo_actor.rect.y)) deg = math.degrees( math.atan2(wall_vec.y - edge.y, wall_vec.x - edge.x)) + self.peepo_actor.rotation if deg < 0: self.obstacle_input['6'] = True else: self.obstacle_input['1'] = True elif 'right' in actor.id: wall_vec = vec((1598, self.peepo_actor.rect.y)) deg = math.degrees( math.atan2(wall_vec.y - edge.y, wall_vec.x - edge.x)) + self.peepo_actor.rotation if deg < 0: self.obstacle_input['1'] = True else: self.obstacle_input['6'] = True elif 'up' in actor.id: wall_vec = vec((5, self.peepo_actor.rect.y)) deg = math.degrees( math.atan2(wall_vec.y - edge.y, wall_vec.x - edge.x)) + self.peepo_actor.rotation if deg < 90: self.obstacle_input['6'] = True else: self.obstacle_input['1'] = True else: wall_vec = vec((5, self.peepo_actor.rect.y)) deg = math.degrees( math.atan2(wall_vec.y - edge.y, wall_vec.x - edge.x)) + self.peepo_actor.rotation if deg < -90: self.obstacle_input['6'] = True else: self.obstacle_input['1'] = True else: edge1 = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation - 30, self.peepo_actor.rect.center) edge2 = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation - 20, self.peepo_actor.rect.center) edge3 = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation - 10, self.peepo_actor.rect.center) edge4 = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation, self.peepo_actor.rect.center) edge5 = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation + 10, self.peepo_actor.rect.center) edge6 = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation + 20, self.peepo_actor.rect.center) edge7 = end_line(WanderingPeepo.RADIUS, self.peepo_actor.rotation + 30, self.peepo_actor.rect.center) self.obstacle_input['1'] = collision(actor.rect, peepo_vec, edge1, edge2, WanderingPeepo.RADIUS) self.obstacle_input['2'] = collision(actor.rect, peepo_vec, edge2, edge3, WanderingPeepo.RADIUS) self.obstacle_input['3'] = collision(actor.rect, peepo_vec, edge3, edge4, WanderingPeepo.RADIUS) self.obstacle_input['4'] = collision(actor.rect, peepo_vec, edge4, edge5, WanderingPeepo.RADIUS) self.obstacle_input['5'] = collision(actor.rect, peepo_vec, edge5, edge6, WanderingPeepo.RADIUS) self.obstacle_input['6'] = collision(actor.rect, peepo_vec, edge6, edge7, WanderingPeepo.RADIUS)
class CointossPeepo(Peepo): def __init__(self, coin_set, model_type): super().__init__(self.create_model(model_type)) self.coin_set = coin_set self.index = 0 self.generative_model = GenerativeModel(self, n_jobs=1) def update(self): return self.generative_model.process() def action(self, node, prediction): pass def observation(self, name): val = np.array([1, 0]) if self.coin_set[self.index] == 0 else np.array([0, 1]) self.index += 1 return val @staticmethod def create_model(model_type): a = 'A' b = 'B' c = 'C' d = 'D' if model_type == "paired": pp_network = PeepoNetwork( ron_nodes=[ {'name': a, 'card': 2}, ], ext_nodes=[ {'name': d, 'card': 2}, ], pro_nodes=[ ], edges=[ (a, d), ], cpds={ a: [0.5, 0.5], d: [[0.99, 0.01], [0.01, 0.99]] }) elif model_type == "sorted": pp_network = PeepoNetwork( ron_nodes=[ {'name': a, 'card': 2}, ], ext_nodes=[ {'name': d, 'card': 2}, ], pro_nodes=[ ], edges=[ (a, d), ], cpds={ a: [0.9, 0.1], d: [[0.01, 0.99], [0.99, 0.01]] }) elif model_type == "default": pp_network = PeepoNetwork( ron_nodes=[ {'name': a, 'card': 2}, ], ext_nodes=[ {'name': d, 'card': 2}, ], pro_nodes=[ ], edges=[ (a, d), ], cpds={ a: [0.5, 0.5], d: [[0.99, 0.01], [0.01, 0.99]] }) else: pp_network = PeepoNetwork( ron_nodes=[ {'name': a, 'card': 2}, {'name': b, 'card': 2}, {'name': c, 'card': 2} ], ext_nodes=[ {'name': d, 'card': 2}, ], pro_nodes=[ ], edges=[ (a, d), (b, d), (c, d), ], cpds={ a: [0.9, 0.1], b: [0.1, 0.9], c: [0.1, 0.9], d: [[0.1, 0.9, 0.1, 0.9, 0.1, 0.9, 0.9, 0.9], [0.9, 0.1, 0.9, 0.1, 0.9, 0.1, 0.1, 0.1]] }) pp_network.assemble() return pp_network
def __init__(self, coin_set, model_type): super().__init__(self.create_model(model_type)) self.coin_set = coin_set self.index = 0 self.generative_model = GenerativeModel(self, n_jobs=1)
logging.basicConfig() logging.getLogger().setLevel(logging.DEBUG) logging.info('logging initialized') bot = PeepoBot() logging.info('bot initialized') network = BayesianModel([('hypo', 'infrared'), ('hypo', 'motor')]) cpd_a = TabularCPD(variable='hypo', variable_card=2, values=[[0.7, 0.3]]) cpd_b = TabularCPD(variable='infrared', variable_card=2, values=[[0.9, 0.1], [0.1, 0.9]], evidence=['hypo'], evidence_card=[2]) cpd_c = TabularCPD(variable='motor', variable_card=2, values=[[0.9, 0.1], [0.1, 0.9]], evidence=['hypo'], evidence_card=[2]) network.add_cpds(cpd_a, cpd_b, cpd_c) network.check_model() model = GenerativeModel(SensoryInput(bot), network) logging.info('starting predictive processing') while True: model.process()
class Peepo: """ This organism represents peepo. Each peepo takes as parameters a name, an initial position and the list of obstacles present in its environment. """ SIZE = (4, 4) RADIUS = 50 SPEED = 2 def __init__(self, name, network, graphical, pos=(0, 0), ennemies=None, food=None): self.graphical = graphical self.name = name self.network = network self.rect = pg.Rect(pos, Peepo.SIZE) self.rect.center = pos self.rotation = 0 self.edge_right = end_line(Peepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(Peepo.RADIUS, self.rotation - 30, self.rect.center) self.edge_middle = end_line(Peepo.RADIUS, self.rotation, self.rect.center) if self.graphical: self.image = self.make_image() self.image_original = self.image.copy() self.stomach = 0 self.bang = 0 self.ennemies = ennemies or [] self.food = food or [] self.obstacles = [] self.assemble_obstacles() self.motor = {LEFT: False, RIGHT: False} self.view = { '1': False, '2': False, '3': False, '4': False, } self.is_an_enemy = False self.is_food = False self.generative_model = GenerativeModel(network, SensoryInputPeepo(self), n_jobs=1) def assemble_obstacles(self): self.obstacles = [] for i, x in enumerate(self.food): self.obstacles.append([x, 0, i]) for i, x in enumerate(self.ennemies): self.obstacles.append([x, 1, i]) def update(self): self.generative_model.process() self.rect.x += Peepo.SPEED * math.cos(math.radians(self.rotation)) self.rect.y += Peepo.SPEED * math.sin(math.radians(self.rotation)) if self.motor[LEFT]: self.rotation -= 10 if self.rotation < 0: self.rotation = 360 if self.motor[RIGHT]: self.rotation += 10 if self.rotation > 360: self.rotation = 0 self.edge_middle = end_line(Peepo.RADIUS, self.rotation, self.rect.center) self.calculate_obstacles() if self.graphical: self.image = pg.transform.rotate(self.image_original, -self.rotation) self.rect = self.image.get_rect(center=self.rect.center) self.edge_right = end_line(Peepo.RADIUS, self.rotation + 30, self.rect.center) self.edge_left = end_line(Peepo.RADIUS, self.rotation - 30, self.rect.center) if self.rect.x < 0 or self.rect.y < 0 or self.rect.x > 800 or self.rect.y > 800: self.rect.x, self.rect.y = 400, 400 def draw(self, surface): surface.blit(self.image, self.rect) pg.draw.line(surface, pg.Color("red"), self.rect.center, self.edge_right, 2) pg.draw.line(surface, pg.Color("green"), self.rect.center, self.edge_left, 2) pg.draw.line(surface, pg.Color("blue"), self.rect.center, self.edge_middle, 4) pg.draw.circle(surface, pg.Color("grey"), self.rect.center, Peepo.RADIUS, 2) def make_image(self): image = pg.Surface(self.rect.size).convert_alpha() image.fill(TRANSPARENT) image_rect = image.get_rect() pg.draw.rect(image, pg.Color("black"), image_rect) pg.draw.rect(image, pg.Color("green"), image_rect.inflate(-2, -2)) return image def calculate_obstacles(self): self.view = {x: False for x in self.view} self.is_an_enemy = False self.is_food = False for obstacle in self.obstacles: if self.rect.colliderect(obstacle[0].rect): if obstacle[1] == 0: self.stomach += 1 self.obstacles.remove(obstacle) else: self.bang += 1 self.obstacles.remove(obstacle) self.food = [] [self.food.append(x[0]) for x in self.obstacles if x[1] == 0] self.ennemies = [] [self.ennemies.append(x[0]) for x in self.obstacles if x[1] == 1] self.assemble_obstacles() observations = [] for obstacle in self.obstacles: distance = math.sqrt( (obstacle[0].rect.center[0] - self.rect.center[0])**2 + (obstacle[0].rect.center[1] - self.rect.center[1])**2) if distance <= Peepo.RADIUS: observations.append(obstacle) edge1 = end_line(Peepo.RADIUS, self.rotation - 30, self.rect.center) edge2 = end_line(Peepo.RADIUS, self.rotation - 15, self.rect.center) edge3 = end_line(Peepo.RADIUS, self.rotation, self.rect.center) edge4 = end_line(Peepo.RADIUS, self.rotation + 15, self.rect.center) edge5 = end_line(Peepo.RADIUS, self.rotation + 30, self.rect.center) sectors = [[edge1, edge2], [edge2, edge3], [edge3, edge4], [edge4, edge5]] peepo_vec = pg.math.Vector2(self.rect.center) relevant_sector = ["0", self.rect.center, Peepo.RADIUS] closest_distance = 10000. for index, sector in enumerate(sectors): lower_edge = sector[0] upper_edge = sector[1] for obstacle in observations: is_collision = collision(obstacle[0].rect, peepo_vec, lower_edge, upper_edge, Peepo.RADIUS) if is_collision: distance = math.sqrt( (obstacle[0].rect.center[0] - peepo_vec[0])**2 + (obstacle[0].rect.center[1] - peepo_vec[1])**2) if distance <= closest_distance: closest_distance = distance relevant_sector[0] = str(index + 1) relevant_sector[1] = obstacle[0].rect.center relevant_sector[2] = closest_distance if obstacle[1] == 1: self.is_an_enemy = True self.is_food = False if obstacle[1] == 0: self.is_food = True self.is_an_enemy = False self.view = {x: False for x in self.view} self.view[relevant_sector[0]] = True sight_angle = 0 only_true = relevant_sector[0] if only_true == '0': sight_angle = self.rotation if only_true == '1': sight_angle = self.rotation - 22.5 if only_true == '2': sight_angle = self.rotation - 7.5 if only_true == '3': sight_angle = self.rotation + 7.5 if only_true == '4': sight_angle = self.rotation + 22.5 self.edge_middle = end_line(relevant_sector[2] / 20, sight_angle, relevant_sector[1])