def gen_from_xmlstring(): """Generate BT graph from xml string.""" dname = '/home/aadeshnpn/Documents/BYU/hcmi/hri/supporting_materials/nest_maintenance' # noqa: E501 xmlstring = '' m = Model() a = Agent('1', m) bt = BTConstruct(None, a, xmlstring) bt.construct() bt.visualize(name=dname + '/' + str(90))
class GEBTAgent(Agent): """An minimalistic GE agent.""" def __init__(self, name, model): super().__init__(name, model) self.location = () self.direction = model.random.rand() * (2 * np.pi) self.speed = 2 self.radius = 3 self.operation_threshold = 2 self.genome_storage = [] # Define a BTContruct object self.bt = BTConstruct(None, self) self.blackboard = Blackboard() self.blackboard.shared_content = dict() # Grammatical Evolution part from ponyge.algorithm.parameters import Parameters parameter = Parameters() parameter_list = ['--parameters', 'swarm.txt'] parameter.params['POPULATION_SIZE'] = self.operation_threshold // 2 parameter.params['RANDOM_SEED'] = model.seed parameter.set_params(parameter_list) self.parameter = parameter individual = initialisation(self.parameter, 1) self.individual = individual self.bt.xmlstring = self.individual[0].phenotype self.bt.construct() self.output = py_trees.display.ascii_tree(self.bt.behaviour_tree.root) # Location history self.location_history = set() self.timestamp = 0 def step(self): """A single step (sense, act) in the environment.""" self.bt.behaviour_tree.tick() self.individual = initialisation(self.parameter, 1) self.bt.xmlstring = self.individual[0].phenotype self.bt.construct() self.output = py_trees.display.ascii_tree(self.bt.behaviour_tree.root) def advance(self): pass
def main(): """Parse args and call bt visualize module.""" # dname = '/home/aadeshnpn/Documents/BYU/hcmi/hri/supporting_materials/nest_maintenance' # noqa: E501 # jfname = dname + '/1539014820252.json' # dname = '/home/aadeshnpn/Documents/BYU/hcmi/hri/supporting_materials/cooperative_transport' # noqa: E501 # jfname = dname + '/1538447335350.json' dname = '/home/aadeshnpn/Documents/BYU/hcmi/hri/supporting_materials/foraging' # noqa: E501 jfname = dname + '/1538473090382007.json' jdata = JsonPhenotypeData.load_json_file(jfname) phenotypes = jdata['phenotypes'] for i in range(len(phenotypes)): # if i >= 5: # break m = Model() a = Agent('1', m) bt = BTConstruct(None, a, phenotypes[i]) bt.construct() bt.visualize(name=dname + '/' + str(i))
class GEBTAgent(Agent): """ An minimalistic GE agent """ def __init__(self, name, model): super().__init__(name, model) self.location = () self.direction = model.random.rand() * (2 * np.pi) self.speed = 2 self.radius = 3 # self.exchange_time = model.random.randint(2, 4) # This doesn't help. Maybe only perform genetic operations when # an agents meet 10% of its total population # """ self.operation_threshold = 2 self.genome_storage = [] # Define a BTContruct object self.bt = BTConstruct(None, self) self.blackboard = Blackboard() self.blackboard.shared_content = dict() self.shared_content = dict() # Grammatical Evolution part from ponyge.algorithm.parameters import Parameters parameter = Parameters() parameter_list = ['--parameters', 'swarm.txt'] # Comment when different results is desired. # Else set this for testing purpose parameter.params['RANDOM_SEED'] = name # np.random.randint(1, 99999999) parameter.params['POPULATION_SIZE'] = self.operation_threshold // 2 parameter.set_params(parameter_list) self.parameter = parameter individual = initialisation(self.parameter, 1) individual = evaluate_fitness(individual, self.parameter) self.individual = individual self.bt.xmlstring = self.individual[0].phenotype self.bt.construct() def step(self): # """ # Doing this is equivalent of using behavior tree with four classes # in this order, Move, HasMoney, NeighbourCondition, ShareMoney # self.move() # execute BT py_trees.logging.level = py_trees.logging.Level.DEBUG # output = py_trees.display.ascii_tree(self.bt.behaviour_tree.root) # print ('bt tree', output, self.individual[0].phenotype) self.bt.behaviour_tree.tick() cellmates = self.model.grid.get_objects_from_grid( 'GEBTAgent', self.location) # print (cellmates) if len(self.genome_storage) >= self.operation_threshold: self.exchange_chromosome(cellmates) self.bt.xmlstring = self.individual[0].phenotype self.bt.construct() if len(cellmates) > 1: self.store_genome(cellmates) def advance(self): pass def move(self): new_location = () x = int(self.location[0] + np.cos(self.direction) * self.speed) y = int(self.location[1] + np.sin(self.direction) * self.speed) new_location, direction = self.model.grid.check_limits((x, y), self.direction) self.model.grid.move_object(self.location, self, new_location) self.location = new_location self.direction = direction def store_genome(self, cellmates): # cellmates.remove(self) self.genome_storage += [agent.individual[0] for agent in cellmates] def exchange_chromosome(self, cellmates): print('from exchange', self.name) individuals = self.genome_storage parents = selection(self.parameter, individuals) cross_pop = crossover(self.parameter, parents) new_pop = mutation(self.parameter, cross_pop) new_pop = evaluate_fitness(new_pop, self.parameter) individuals = replacement(self.parameter, new_pop, individuals) individuals.sort(reverse=False) self.individual = [individuals[0]] self.genome_storage = []
class EvolAgent(Agent): """An minimalistic swarm agent.""" def __init__(self, name, model): """Initialize the agent.""" super().__init__(name, model) self.location = () self.direction = model.random.rand() * (2 * np.pi) self.speed = 2 self.radius = 3 self.results = "db" # This can take 2 values. db or file # self.exchange_time = model.random.randint(2, 4) # This doesn't help. Maybe only perform genetic operations when # an agents meet 10% of its total population # """ self.operation_threshold = 2 self.genome_storage = [] # Define a BTContruct object self.bt = BTConstruct(None, self) # self.blackboard = Blackboard() # self.blackboard.shared_content = dict() self.shared_content = dict() # self.shared_content = dict( self.carryable = False self.beta = 0.0001 self.food_collected = 0 # Grammatical Evolution part from ponyge.algorithm.parameters import Parameters parameter = Parameters() parameter_list = ['--parameters', '../..,' + model.parm] # Comment when different results is desired. # Else set this for testing purpose # parameter.params['RANDOM_SEED'] = name # # np.random.randint(1, 99999999) parameter.params['POPULATION_SIZE'] = self.operation_threshold // 2 parameter.set_params(parameter_list) self.parameter = parameter individual = initialisation(self.parameter, 1) individual = evaluate_fitness(individual, self.parameter) self.individual = individual self.bt.xmlstring = self.individual[0].phenotype self.bt.construct() self.diversity_fitness = self.individual[0].fitness self.delayed_reward = 0 # Location history self.location_history = set() self.timestamp = 0 self.step_count = 0 self.fitness_name = True def get_food_in_hub(self): """Return food in the hub.""" grid = self.model.grid hub_loc = self.model.hub.location neighbours = grid.get_neighborhood(hub_loc, 10) food_objects = grid.get_objects_from_list_of_grid('Food', neighbours) agent_food_objects = [] for food in food_objects: if (food.agent_name == self.name and food.phenotype == self.individual[0].phenotype): agent_food_objects.append(food) return agent_food_objects def detect_food_carrying(self): """Detect if the agent is carrying food.""" if len(self.attached_objects) > 0: print('Food carying', self.name, self.attached_objects) output = py_trees.display.ascii_tree(self.bt.behaviour_tree.root) print(output) def store_genome(self, cellmates): """Store the genome from neighbours.""" # cellmates.remove(self) # self.genome_storage += [agent.individual[0] for agent in cellmates] for agent in cellmates: if agent.food_collected > 0: self.genome_storage += agent.individual elif len(agent.attached_objects) > 0: self.genome_storage += agent.individual elif agent.exploration_fitness() > 10: self.genome_storage += agent.individual def exchange_chromosome(self, ): """Perform genetic operations.""" # print('from exchange', self.name) individuals = self.genome_storage parents = selection(self.parameter, individuals) cross_pop = crossover(self.parameter, parents) new_pop = mutation(self.parameter, cross_pop) new_pop = evaluate_fitness(new_pop, self.parameter) individuals = replacement(self.parameter, new_pop, individuals) individuals.sort(reverse=False) self.individual = [individuals[0]] self.individual[0].fitness = 0 self.genome_storage = [] def genetic_step(self): """Additional procedures called after genecti step.""" self.delayed_reward = self.individual[0].fitness self.exchange_chromosome() self.bt.xmlstring = self.individual[0].phenotype self.bt.construct() self.food_collected = 0 self.location_history = set() self.timestamp = 0 self.diversity_fitness = self.individual[0].fitness def overall_fitness(self): """Compute complete fitness. Goals are represented by objective function. We use combination of objective function to define overall fitness of the agents performance. """ # Use a decyaing function to generate fitness # Use two step decaying function # First block gives importance to exploration and when as soon # food has been found, the next block will focus on dropping # the food on hub self.individual[0].fitness = (1 - self.beta) * self.delayed_reward \ + self.exploration_fitness() + self.carrying_fitness() \ + self.food_collected def carrying_fitness(self): """Compute carrying fitness. This fitness supports the carrying behavior of the agents. """ return len(self.attached_objects) * (self.timestamp) def exploration_fitness(self): """Compute the exploration fitness.""" # Use exploration space as fitness values return len(self.location_history) - 1 # New Agent methods for behavior based robotics def sense(self): """Sense included in behavior tree.""" pass def plan(self): """Plan not required for now.""" pass def step(self): """Agent action at a single time step.""" # py_trees.logging.level = py_trees.logging.Level.DEBUG # output = py_trees.display.ascii_tree(self.bt.behaviour_tree.root) # Couting variables self.timestamp += 1 self.step_count += 1 # Increase beta self.beta = self.step_count / self.model.iter self.location_history.add(self.location) # Compute the behavior tree self.bt.behaviour_tree.tick() # Find the no.of food collected from the BT execution self.food_collected = len(self.get_food_in_hub()) # Computes overall fitness using Beta function self.overall_fitness() cellmates = self.model.grid.get_objects_from_grid( type(self).__name__, self.location) # Create a results instance and save it to a file """ self.results = Results( self.model.pname, self.model.connect, self.model.sn, self.name, self.step_count, self.timestamp, self.beta, self.individual[0].fitness, self.diversity_fitness, self.exploration_fitness(), self.food_collected, len(cellmates), self.individual[0].genome, self.individual[0].phenotype, self.bt ) """ # Save the results to a db # self.results.save_to_file() # Logic for gentic operations. # If the genome storage has enough genomes and agents has done some # exploration then compute the genetic step OR # 600 time step has passed and the agent has not done anything useful # then also perform genetic step storage_threshold = len( self.genome_storage) >= (self.model.num_agents / 1.4) if storage_threshold: self.genetic_step() elif (storage_threshold is False and self.timestamp > 50 and self.exploration_fitness() < 10): individual = initialisation(self.parameter, 10) individual = evaluate_fitness(individual, self.parameter) self.genome_storage = individual self.genetic_step() # If neighbours found, store the genome if len(cellmates) > 1: self.store_genome(cellmates) def advance(self): """Require for staged activation.""" pass
class RunSwarmAgent(Agent): """A swarm agent. This agent will run the behaviors evolved. """ def __init__(self, name, model): """Initialize the agent.""" super().__init__(name, model) self.location = () self.direction = model.random.rand() * (2 * np.pi) self.speed = 2 self.radius = 3 self.carryable = False # Define a BTContruct object self.bt = BTConstruct(None, self) self.shared_content = dict() self.food_collected = 0 self.bt.xmlstring = model.xmlstring self.bt.construct() # self.diversity_fitness = model.fitness # Location history self.location_history = set() self.timestamp = 0 self.step_count = 0 def get_food_in_hub(self): # return len(self.attached_objects) * 1000 grid = self.model.grid hub_loc = self.model.hub.location neighbours = grid.get_neighborhood(hub_loc, 10) food_objects = grid.get_objects_from_list_of_grid('Food', neighbours) agent_food_objects = [] for food in food_objects: if food.agent_name == self.name: agent_food_objects.append(food) # print (food_objects) return agent_food_objects def detect_food_carrying(self): if len(self.attached_objects) > 0: print('Food carying', self.name, self.attached_objects) output = py_trees.display.ascii_tree(self.bt.behaviour_tree.root) print(output) def carrying_fitness(self): """Compute carrying fitness. This fitness supports the carrying behavior of the agents. """ return len(self.attached_objects) def exploration_fitness(self): """Compute the exploration fitness.""" # Use exploration space as fitness values return len(self.location_history) # New Agent methods for behavior based robotics def sense(self): """Sense included in behavior tree.""" pass def plan(self): """Plan not required for now.""" pass def step(self): """Agent action at a single time step.""" # Maintain the location history of the agent # self.location_history.add(self.location) # Compute the behavior tree self.bt.behaviour_tree.tick() # Find the no.of food collected from the BT execution # self.food_collected = len(self.get_food_in_hub()) def advance(self): """Require for staged activation.""" pass
class SimAgentResComm2(Agent): """Simulation agent for resilience. An minimalistic behavior tree for swarm agent to simulate resilient behaviors a node is removed. """ def __init__(self, name, model, xmlstring=None): super().__init__(name, model) self.location = () self.direction = model.random.rand() * (2 * np.pi) self.speed = 2 self.radius = 3 self.moveable = True self.shared_content = dict() self.carryable = False # Define a BTContruct object self.bt = BTConstruct(None, self) class DummyIndividual: def __init__(self): self.phenotype = None dummyind = DummyIndividual() self.individual = [dummyind] self.individual[0].phenotype = xmlstring self.bt.xmlstring = xmlstring self.bt.construct() # When the actuator is not working. We repalce the move # premitive behavior with dummpy move behaviors 50% of # the time. self.dummy_bt = self.replace_nodes() # Move node only works 50% of the time # py_trees.logging.level = py_trees.logging.Level.DEBUG # py_trees.display.print_ascii_tree(self.dummy_bt.behaviour_tree.root) """ for a in self.dummy_bt.behaviour_tree.root.iterate(): try: py_trees.display.print_ascii_tree(a.behaviour_tree.root) except AttributeError: pass """ def step(self): # Only the actuators work 50% of the time if self.model.random.rand() < 0.5: self.bt.behaviour_tree.tick() else: self.dummy_bt.behaviour_tree.tick() def advance(self): pass def replace_nodes(self): dummy_bt = copy.copy(self.bt) root = dummy_bt.behaviour_tree.root # For now dummpy node is removed but it could be different def remove(roots, node): communication_list = [ 'SendSignal', 'ReceiveSignal', 'DropCue', 'PickCue' ] if type(node).__name__ in communication_list: roots.remove_child(node) for node in root.iterate(): try: innerroot = node.behaviour_tree.root for innernode in innerroot.iterate(): remove(innerroot, innernode) except AttributeError: remove(root, node) return dummy_bt
class SimAgent(Agent): """Simulation agent. An minimalistic behavior tree for swarm agent implementing carry and drop behavior. """ def __init__(self, name, model, xmlstring=None): super().__init__(name, model) self.location = () self.direction = model.random.rand() * (2 * np.pi) self.speed = 2 self.radius = 3 self.moveable = True self.shared_content = dict() self.carryable = False # Define a BTContruct object self.bt = BTConstruct(None, self) class DummyIndividual: def __init__(self): self.phenotype = None dummyind = DummyIndividual() self.individual = [dummyind] self.individual[0].phenotype = xmlstring self.bt.xmlstring = xmlstring self.bt.construct() """ # Drop branch dseq = py_trees.composites.Sequence('DSequence') iscarrying = IsCarrying('1') iscarrying.setup(0, self, 'Food') neighhub = NeighbourObjects('2') neighhub.setup(0, self, 'Hub') drop = CompositeDrop('4') drop.setup(0, self, 'Food') dseq.add_children([neighhub, drop]) # Carry branch cseq = py_trees.composites.Sequence('CSequence') neighsite = NeighbourObjects('5') neighsite.setup(0, self, 'Sites') neighfood = NeighbourObjects('50') neighfood.setup(0, self, 'Food') invcarrying = py_trees.meta.inverter(IsCarrying)('8') invcarrying.setup(0, self, 'Food') carry = CompositeSingleCarry('6') carry.setup(0, self, 'Food') cseq.add_children([neighsite, neighfood, invcarrying, carry]) # Locomotion branch # Move to site siteseq = py_trees.composites.Sequence('SiteSeq') sitefound = IsVisitedBefore('7') sitefound.setup(0, self, 'Sites') gotosite = MoveTowards('9') gotosite.setup(0, self, 'Sites') siteseq.add_children([sitefound, invcarrying, gotosite]) # Move to hub hubseq = py_trees.composites.Sequence('HubSeq') gotohub = MoveTowards('10') gotohub.setup(0, self, 'Hub') hubseq.add_children([iscarrying, gotohub]) sitenotfound = py_trees.meta.inverter(IsVisitedBefore)('11') sitenotfound.setup(0, self, 'Sites') explore = Explore('12') explore.setup(0, self) randwalk = py_trees.composites.Sequence('Randwalk') randwalk.add_children([explore]) locoselect = py_trees.composites.Selector('Move') locoselect.add_children([siteseq, hubseq, explore]) select = py_trees.composites.Selector('Main') select.add_children([dseq, cseq, locoselect]) self.behaviour_tree = py_trees.trees.BehaviourTree(select) """ # py_trees.logging.level = py_trees.logging.Level.DEBUG # py_trees.display.print_ascii_tree(select) def step(self): self.bt.behaviour_tree.tick() def advance(self): pass
class SimAgent(Agent): """Simulation agent. An minimalistic behavior tree for swarm agent implementing carry and drop behavior. """ def __init__(self, name, model, xmlstring=None): super().__init__(name, model) self.location = () self.direction = model.random.rand() * (2 * np.pi) self.speed = 2 self.radius = 3 self.moveable = True self.shared_content = dict() self.carryable = False # Define a BTContruct object self.bt = BTConstruct(None, self) class DummyIndividual: def __init__(self): self.phenotype = None dummyind = DummyIndividual() self.individual = [dummyind] self.individual[0].phenotype = xmlstring self.bt.xmlstring = xmlstring self.bt.construct() """ # Drop branch dseq = py_trees.composites.Sequence('DSequence') iscarrying = IsCarrying('1') iscarrying.setup(0, self, 'Debris') neighhub = NeighbourObjects('2') neighhub.setup(0, self, 'Obstacles') drop = CompositeDrop('4') drop.setup(0, self, 'Debris') dseq.add_children([neighhub, drop]) # Carry branch cseq = py_trees.composites.Sequence('CSequence') neighsite = py_trees.meta.inverter(NeighbourObjects)('5') neighsite.setup(0, self, 'Obstacles') neighfood = NeighbourObjects('50') neighfood.setup(0, self, 'Debris') invcarrying = py_trees.meta.inverter(IsCarrying)('8') invcarrying.setup(0, self, 'Debris') carry = CompositeSingleCarry('6') carry.setup(0, self, 'Debris') cseq.add_children([neighsite, neighfood, invcarrying, carry]) # Locomotion branch # Move to site siteseq = py_trees.composites.Sequence('SiteSeq') sitefound = IsVisitedBefore('7') sitefound.setup(0, self, 'Obstacles') gotosite = MoveTowards('9') gotosite.setup(0, self, 'Obstacles') siteseq.add_children([sitefound, iscarrying, gotosite]) # Move to hub hubseq = py_trees.composites.Sequence('HubSeq') gotohub = MoveTowards('10') gotohub.setup(0, self, 'Hub') hubseq.add_children([iscarrying, gotohub]) sitenotfound = py_trees.meta.inverter(IsVisitedBefore)('11') sitenotfound.setup(0, self, 'Obstacles') explore = Explore('12') explore.setup(0, self) randwalk = py_trees.composites.Sequence('Randwalk') randwalk.add_children([explore]) locoselect = py_trees.composites.Selector('Move') locoselect.add_children([siteseq, explore]) select = py_trees.composites.Selector('Main') select.add_children([dseq, cseq, locoselect]) self.behaviour_tree = py_trees.trees.BehaviourTree(select) """ # py_trees.logging.level = py_trees.logging.Level.DEBUG # py_trees.display.print_ascii_tree(select) def step(self): self.bt.behaviour_tree.tick() def advance(self): pass def replace_nodes(self): dummy_bt = copy.copy(self.bt) # dummy_bt.behaviour_tree.tick() root = dummy_bt.behaviour_tree.root # For now dummpy node is move but it could be different name = 'Dummy' + str(self.model.random.randint(0, 1000, 1)[0]) dummynode = Dummymove(name) def replace(roots, node): if type(node).__name__ == 'Move': roots.replace_child(node, dummynode) for node in root.iterate(): try: innerroot = node.behaviour_tree.root for innernode in innerroot.iterate(): replace(innerroot, innernode) except AttributeError: replace(root, node) return dummy_bt