示例#1
0
class TestMultiGrid(unittest.TestCase):
    '''
    Testing a toroidal MultiGrid
    '''

    torus = True

    def setUp(self):
        '''
        Create a test non-toroidal grid and populate it with Mock Agents
        '''
        width = 3
        height = 5
        self.grid = MultiGrid(width, height, self.torus)
        self.agents = []
        counter = 0
        for x in range(width):
            for y in range(height):
                for i in range(TEST_MULTIGRID[x][y]):
                    counter += 1
                    # Create and place the mock agent
                    a = MockAgent(counter, None)
                    self.agents.append(a)
                    self.grid.place_agent(a, (x, y))

    def test_agent_positions(self):
        '''
        Ensure that the agents are all placed properly on the MultiGrid.
        '''
        for agent in self.agents:
            x, y = agent.pos
            assert agent in self.grid[x][y]

    def test_neighbors(self):
        '''
        Test the toroidal MultiGrid neighborhood methods.
        '''

        neighborhood = self.grid.get_neighborhood((1, 1), moore=True)
        assert len(neighborhood) == 8

        neighborhood = self.grid.get_neighborhood((1, 4), moore=True)
        assert len(neighborhood) == 8

        neighborhood = self.grid.get_neighborhood((0, 0), moore=False)
        assert len(neighborhood) == 4

        neighbors = self.grid.get_neighbors((1, 4), moore=False)
        assert len(neighbors) == 0

        neighbors = self.grid.get_neighbors((1, 4), moore=True)
        assert len(neighbors) == 5

        neighbors = self.grid.get_neighbors((1, 1),
                                            moore=False,
                                            include_center=True)
        assert len(neighbors) == 7

        neighbors = self.grid.get_neighbors((1, 3), moore=False, radius=2)
        assert len(neighbors) == 11
示例#2
0
文件: test_grid.py 项目: GeoESW/mesa
class TestMultiGrid(unittest.TestCase):
    '''
    Testing a toroidal MultiGrid
    '''

    torus = True

    def setUp(self):
        '''
        Create a test non-toroidal grid and populate it with Mock Agents
        '''
        width = 3
        height = 5
        self.grid = MultiGrid(width, height, self.torus)
        self.agents = []
        counter = 0
        for x in range(width):
            for y in range(height):
                for i in range(TEST_MULTIGRID[x][y]):
                    counter += 1
                    # Create and place the mock agent
                    a = MockAgent(counter, None)
                    self.agents.append(a)
                    self.grid.place_agent(a, (x, y))

    def test_agent_positions(self):
        '''
        Ensure that the agents are all placed properly on the MultiGrid.
        '''
        for agent in self.agents:
            x, y = agent.pos
            assert agent in self.grid[x][y]

    def test_neighbors(self):
        '''
        Test the toroidal MultiGrid neighborhood methods.
        '''

        neighborhood = self.grid.get_neighborhood((1, 1), moore=True)
        assert len(neighborhood) == 8

        neighborhood = self.grid.get_neighborhood((1, 4), moore=True)
        assert len(neighborhood) == 8

        neighborhood = self.grid.get_neighborhood((0, 0), moore=False)
        assert len(neighborhood) == 4

        neighbors = self.grid.get_neighbors((1, 4), moore=False)
        assert len(neighbors) == 0

        neighbors = self.grid.get_neighbors((1, 4), moore=True)
        assert len(neighbors) == 5

        neighbors = self.grid.get_neighbors((1, 1), moore=False,
                                            include_center=True)
        assert len(neighbors) == 7

        neighbors = self.grid.get_neighbors((1, 3), moore=False, radius=2)
        assert len(neighbors) == 11
示例#3
0
class bacModel(Model):
    '''world model for Eden Growth Model Simulation'''
    def __init__(self, beginRad, splitChance, x=-1, y=-1, mut_rate=MUTATION_RATE):
        self.running = True
        self.num_agents = 0
        self.schedule = RandomActivation(self)
        self.grid = MultiGrid(WIDTH, HEIGHT, IS_TOROIDAL) #True for toroidal
        #self.datacollector = DataCollector(
        #    model_reporters = {"Identifier": function_name}, #note no parentheses, just function name
        #    agent_reporter = {"Identifier2": function_name2})

        if x == -1:
            x = self.grid.width // 2
        if y == -1:
            y = self.grid.height // 2

        #create subsequent agents
        positions = self.grid.get_neighborhood((x,y), moore=False, radius=beginRad, include_center=True)
        for coord in positions:
            roll = random.random()
            a = bacAgent(self.num_agents, self, False, splitChance)
            self.num_agents += 1
            self.schedule.add(a)
            self.grid.place_agent(a, coord)


    def step(self):
        #self.datacollector.collect(self)
        self.schedule.step()
示例#4
0
class bacServerModel(Model):
    ################
    ###Deprecated###
    ################
    def __init__(self, width, height, beginRad):
            self.running = True
            self.num_agents = width * height
            self.schedule = RandomActivation(self)
            self.grid = MultiGrid(width, height, IS_TOROIDAL) #True for toroidal
            #self.datacollector = DataCollector(
            #    model_reporters = {"Identifier": function_name}, #note no parentheses, just function name
            #    agent_reporter = {"Identifier2": function_name2})

            for x in range(self.grid.width):
                for y in range(self.grid.height):
                    a = bacServerAgent(self.num_agents, self)
                    self.num_agents += 1
                    self.schedule.add(a)
                    self.grid.place_agent(a, (x,y))

            x = self.grid.width // 2
            y = self.grid.height // 2

            #create subsequent agents
            positions = self.grid.get_neighborhood((x,y), moore=False, radius=beginRad, include_center=True)
            for coord in positions:
                ag = self.grid.get_cell_list_contents([coord])[0]
                ag.activate()


    def step(self):
        #self.datacollector.collect(self)
        self.schedule.step()
示例#5
0
 def move(self):
     '''
     The random move function for the fish schools.
     '''
     neighbourhood = MultiGrid.get_neighborhood(self.model.grid, self.pos, True, False, 1)
     new_pos = random.choice(neighbourhood)
     MultiGrid.move_agent(self.model.grid, self, new_pos)
示例#6
0
    def fisherman_move(self):
        '''
        The random move function for the fisherman.
        '''
    	neighbourhood = MultiGrid.get_neighborhood(self.model.grid, self.pos, True, False, 1)
    	new_pos = random.choice(neighbourhood)
    	while (new_pos[0] < self.model.no_fish_size) and (new_pos[1] < self.model.no_fish_size):
    		new_pos = random.choice(neighbourhood)

    	MultiGrid.move_agent(self.model.grid, self, new_pos)
示例#7
0
class HoominWorld(Model):

    LEFT = 0
    RIGHT = 1
    STRAIGHT = 2

    FRIENDNODELOGNAME = "friendnodes"
    TOTALMESSAGELOGNAME = "totalmessages"
    STEPSTOCOMPLETIONLOGNAME = "stepstocompletion"

    verbose = False
    description = "A model of foot traffic and radio communication in an urban environment"

    def __init__(self,
                 height=50,
                 width=50,
                 initial_hoomins=10,
                 logtag="default"):
        super().__init__()

        print("initializing ", settings.width, settings.height)
        #map height and width
        self.height = settings.height
        self.width = settings.width

        #logging framework
        self.logger = Logging("logs", logtag)
        self.logtag = logtag
        self.G = nx.Graph()

        #graph visualization
        if not settings.runheadless:
            plt.ion()
            plt.show()

        #ignore this. it does nothing
        self.hoomin_level = 0

        #road generation tuning
        self.straightweight = settings.straightweight
        self.leftweight = settings.leftweight
        self.rightweight = settings.rightweight
        self.initial_roads = settings.initial_roads
        self.initial_road_seeds = settings.initial_road_seeds
        self.gridspacing = settings.gridspacing
        self.roadcurrentcoord = np.array((0, 0))
        self.roaddir = np.array((1, 0))
        self.roadset = set()

        #home tuning options
        self.homes_per_hoomins = 1
        self.initial_homes = self.homes_per_hoomins * initial_hoomins
        self.homeset = set()

        #scatterbrain metrics
        self.total_scattermessages = 0
        self.global_scattermessages = 0
        self.hoominzero_nodecount = 0

        #hoomin tuning values
        self.initial_hoomins = settings.initial_hoomins
        self.schedule = RandomHoominActivation(self)
        self.grid = MultiGrid(self.height, self.width, torus=True)
        self.datacollector = DataCollector({
            "Messages Exchanged":
            lambda m: m.total_scattermessages,
            "FriendGraph Node Count":
            lambda m: m.hoominzero_nodecount
        })

        #initialize roads
        for i in range(self.initial_road_seeds):
            x = self.random.randrange(self.width)
            y = self.random.randrange(self.height)

            self.singleroad((x, y))

        homelist = []

        #initialize homes
        for i in range(self.initial_homes):
            road = self.random.sample(self.roadset, 1)
            if len(road) > 0 and road[0] is not None:
                neighbors = self.grid.get_neighborhood(road[0].pos, False,
                                                       True)
                for neighbor in neighbors:
                    n = []
                    if len(self.grid.get_cell_list_contents(neighbor)) is 0:
                        n.append(neighbor)
                    if len(n) > 0:
                        homeblock = self.random.sample(n, 1)
                        home = Home(self.next_id(), homeblock[0], self)
                        homelist.append(home)
                        self.grid.place_agent(home, homeblock[0])
            else:
                print(
                    "systemic oppression under capitalism forclosed on one hoomin's home."
                )

        self.homeset = self.homeset.union(set(homelist))

        #initialize hoomins
        for i in range(self.initial_hoomins):
            x = self.random.randrange(self.width)
            y = self.random.randrange(self.height)
            hoomin = SocialHoomin(self.next_id(), (x, y), self)
            if i == 1:
                for x in range(settings.initial_scattermessages):
                    hoomin.store_scattermessage("hoomin!")
                hoomin.pos = (0, 0)
                x = 0
                y = 0
                self.hoomin_zero_id = hoomin.unique_id

            if i == self.initial_hoomins - 1:
                self.final_hoomin_id = hoomin.unique_id
                hoomin.pos = (self.width - 1, self.height - 1)
                x = self.width - 1
                y = self.height - 1

            possiblehomes = self.homeset.difference(Home.claimedhomes)
            if len(possiblehomes) > 0:
                myhome = self.random.sample(possiblehomes, 1)
            if len(myhome) > 0:
                myhome[0].claim(hoomin)
            self.grid.place_agent(hoomin, (x, y))
            self.schedule.add(hoomin)
            self.G.add_node(hoomin, agent=[hoomin])

        #initialize hoomin friends
        friendlist = set(self.schedule._agents)
        for i in self.schedule._agents:
            fren = self.random.sample(friendlist.difference(set([i])),
                                      settings.friendsperhoomin)
            for x in fren:
                self.schedule._agents[i].addfriend(x)
                self.G.add_edge(self.schedule._agents[i],
                                self.schedule._agents[x])

        self.roadplace_grid()
        self.running = True
        self.datacollector.collect(self)

    def roadplace_grid(self):
        for h in range(self.height):
            if h % self.gridspacing is 0:
                for w in range(self.width):
                    road = Road(self.next_id(), (w, h), self)
                    self.grid.place_agent(road, (w, h))

        for w in range(self.width):
            if w % self.gridspacing is 0:
                for h in range(self.height):
                    road = Road(self.next_id(), (w, h), self)
                    self.grid.place_agent(road, (w, h))

    def roadplace_random(self, direction=0):

        if direction is HoominWorld.STRAIGHT:
            True
        elif direction is HoominWorld.LEFT:
            self.roaddir = np.array((-1 * self.roaddir[1], self.roaddir[0]))
        elif direction is HoominWorld.RIGHT:
            self.roaddir = np.array((self.roaddir[1], -1 * self.roaddir[0]))
        else:
            self.roaddir = np.array((0, 0))
            print("bad bad bad")
#        print("placing road, direction ", direction, " coord: ", self.roadcurrentcoord)

        newcoord = self.roadcurrentcoord + self.roaddir
        if newcoord[0] >= self.width or newcoord[0] < 0:
            return None
        if newcoord[1] >= self.height or newcoord[1] < 0:
            return None

        self.roadcurrentcoord += self.roaddir

        road = Road(self.next_id(), tuple(self.roadcurrentcoord), self)
        self.grid.place_agent(road, tuple(self.roadcurrentcoord))

        return road

    def singleroad(self, initialcoord=(0, 0)):
        #initialize roads
        #print("placing road seed: ", initialcoord)
        roaddir = self.random.randrange(4)
        roadseedx = self.random.randrange(self.width)
        roadseedy = self.random.randrange(self.height)
        road = Road(self.next_id(), (roadseedx, roadseedy), self)
        self.roadcurrentcoord = (roadseedx, roadseedy)
        self.grid.place_agent(road, (roadseedx, roadseedy))

        #note: roads are not scheduled because they do nothing
        road = None
        counter = 0
        roadlist = []
        for i in range(self.initial_roads):
            while road is None:
                val = self.random.random()
                #print("val: " , val)
                if val <= self.straightweight:
                    road = self.roadplace_random(HoominWorld.STRAIGHT)
                elif val > self.straightweight and val <= self.leftweight + self.straightweight:
                    road = self.roadplace_random(HoominWorld.LEFT)
                elif val > self.leftweight + self.straightweight:
                    road = self.roadplace_random(HoominWorld.RIGHT)
                if road is None:
                    #print("err: road is none")
                    True

                roadlist.append(road)
            road = None
            counter += 1
        #print("initialized ", counter, " road tiles")
        self.roadset = self.roadset.union(set(roadlist))
        del roadlist

    def get_hoomin_level(self):
        return self.hoomin_level

    def logstep(self):
        if not self.logger.isopen(HoominWorld.FRIENDNODELOGNAME):
            self.logger.open(HoominWorld.FRIENDNODELOGNAME, overwrite=True)
        if not self.logger.isopen(HoominWorld.TOTALMESSAGELOGNAME):
            self.logger.open(HoominWorld.TOTALMESSAGELOGNAME, overwrite=True)

        self.logger.write(
            HoominWorld.TOTALMESSAGELOGNAME,
            str(self.hoomin_level) + " " + str(self.global_scattermessages))

        st = "STEP: " + str(self.hoomin_level) + " hoominzero: " + str(
            self.schedule._agents[self.hoomin_zero_id].friendgraph.
            number_of_nodes()) + " finalhoomin: " + str(self.schedule._agents[
                self.final_hoomin_id].friendgraph.number_of_nodes())
        self.logger.write(HoominWorld.FRIENDNODELOGNAME, st)

    def step(self):
        self.schedule.step()
        self.datacollector.collect(self)
        self.hoomin_level += 1
        if self.hoomin_level % settings.graphrefreshfreq == 0 and settings.displayfriendgraph and not settings.runheadless:
            plt.cla()
            plt.clf()
            nx.draw(self.schedule._agents[self.hoomin_zero_id].friendgraph)
            plt.draw()
            plt.pause(0.001)
        if self.verbose:
            print([self.schedule.time, "nothing yet"])

        if len(self.schedule._agents[self.final_hoomin_id].scatterbuffer
               ) >= settings.initial_scattermessages:
            print("model completed")
            self.running = False
            if not self.logger.isopen(HoominWorld.STEPSTOCOMPLETIONLOGNAME):
                self.logger.open(HoominWorld.STEPSTOCOMPLETIONLOGNAME,
                                 overwrite=True)
            self.logger.write(HoominWorld.STEPSTOCOMPLETIONLOGNAME,
                              self.hoomin_level)
            self.logger.close(HoominWorld.STEPSTOCOMPLETIONLOGNAME)

        self.logstep()

    def run_model(self, step_count=200):
        if self.verbose:
            print("Initializing hoomins",
                  self.schedule.get_hoomin_count(Hoomin))
        while self.running:
            self.step()
示例#8
0
class EmasModel(Model):
    description = (
        "A model for simulating using EMAS model"
    )

    def __init__(
            self,
            height=HEIGHT,
            width=WIDTH,
            columns=2,
            rows=2,
            death_level=0,
            migration_level=10,
            init_energy=100,
            moore=True,
            reproduction_level=7,
            parent_part_to_child=30,
            base_child_energy=5,
            energy_redistribution_radius=4,
            islands=[]
    ):
        super().__init__()
        self.height: int = height
        self.width: int = width
        self.columns: int = columns
        self.rows: int = rows
        self.death_level: float = death_level
        self.migration_level: float = migration_level
        self.moore: bool = moore
        self.reproduction_level: float = reproduction_level
        self.parent_part_to_child: float = parent_part_to_child
        self.base_child_energy: float = base_child_energy
        self.init_energy: float = init_energy
        self.energy_redistribution_radius: int = energy_redistribution_radius
        self.islands: List[Tuple[Tuple[int, int], Tuple[int, int]]] = islands
        self.grid = MultiGrid(self.height, self.width, torus=True)

        borders_x_indexes = sorted([int(self.width * part / columns) for part in range(1, self.columns)])
        columns_points: Set[Tuple[int, int]] = {(x, y) for x in borders_x_indexes for y in range(self.height)}

        borders_y_indexes = sorted([int(self.height * part / rows) for part in range(1, self.rows)])
        rows_points: Set[Tuple[int, int]] = {(x, y) for x in range(self.width) for y in borders_y_indexes}

        for border_cords in columns_points | rows_points:
            border = IslandBorderAgent(self.next_id(), border_cords, self)
            self.grid.place_agent(border, border_cords)

        islands_x_corners = [-1] + borders_x_indexes + [self.width]
        islands_y_corners = [-1] + borders_y_indexes + [self.height]

        # left lower and right upper corner
        self.islands = [
            ((x, y), (islands_x_corners[x_u + 1], islands_y_corners[y_u + 1]))
            for x_u, x in enumerate(islands_x_corners) if x != self.width
            for y_u, y in enumerate(islands_y_corners) if y != self.height
        ]

    def get_neighborhood(self, pos: Coordinate, include_center=False, radius=1, moore=True):
        next_moves = self.grid.get_neighborhood(pos, moore, include_center, radius)
        island = self.get_island(pos)
        return self._filter_coors_in_island(island, next_moves)

    def redistribute_energy(self, pos: Coordinate, energy: float, include_center=False, radius=10):
        neighbours = self.grid.get_neighbors(pos, self.moore, include_center, radius)
        island = self.get_island(pos)
        close_neighbours = list(filter(lambda n: self._is_in_island(island, n.pos), neighbours))
        emas_neighbours = list(filter(lambda a: isinstance(a, EmasAgent), close_neighbours))
        if emas_neighbours:
            energy_delta = energy / len(emas_neighbours)
            for neighbour in emas_neighbours:
                neighbour.energy += energy_delta

    def get_island(self, pos: Coordinate):
        return list(filter(lambda coors: coors[0][0] < pos[0] < coors[1][0] and coors[0][1] < pos[1] < coors[1][1],
                           self.islands)).pop()

    def _filter_coors_in_island(self, island: Tuple[Tuple[int, int], Tuple[int, int]],
                                positions: List[Tuple[int, int]]):
        return list(filter(lambda move: island[0][0] < move[0] < island[1][0] and island[0][1] < move[1] <
                                        island[1][1], positions))

    def _is_in_island(self, island, pos):
        return island[0][0] < pos[0] < island[1][0] and island[0][1] < pos[1] < island[1][1]

    def _filter_for_emas_agents(self, agents):
        return filter(lambda a: isinstance(a, EmasAgent), agents)

    def get_closest_neighbour_on_island(self, pos: Coordinate):
        island = self.get_island(pos)

        taxi_radius = abs(island[0][0] - island[1][0]) + abs(island[0][1] - island[1][1])

        # moore=False -> find neighbourhood using taxi metric
        neighbours = self.grid.get_neighbors(pos, False, include_center=False, radius=taxi_radius)
        island_neighbours = [
            agent for agent in neighbours if self._is_in_island(island, agent.pos) and isinstance(agent, EmasAgent)
        ]

        closest_neighbour = None
        closest_distance = taxi_radius
        for agent in island_neighbours:
            if self.taxi_distance(pos, agent.pos) < closest_distance:
                closest_distance = self.taxi_distance(pos, agent.pos)
                closest_neighbour = agent

        return closest_neighbour

    def taxi_distance(self, pos_a: Coordinate, pos_b: Coordinate):
        return abs(pos_a[0] - pos_b[0]) + abs(pos_a[1] - pos_b[1])
class ExplorationArea(Model):
    def __init__(
            self,
            nrobots,
            wifi_range,
            radar_radius=6,
            alpha=8.175,
            gamma=0.65,
            inj_pri=0,
            ninjured=None,
            ncells=None,
            obstacles_dist=None,
            load_file=None,
            dump_datas=True,  # enable data collection
            alpha_variation=False,  # record datas for alpha variation studies
            alpha_csv=alpha_csv,  # aggregate datas
            alpha_step_csv=alpha_step_csv,  # single step datas
            gamma_variation=False,  # record datas for gamma variation studies
            gamma_csv=gamma_csv,
            optimization_task=False,  # enable a small part of data collection for optimization task
            time_csv=number_of_steps_csv,
            robot_status_csv=robot_status_csv):

        # checking params consistency
        if not load_file and (not ncells or not obstacles_dist
                              or not ninjured):
            print("Invalid params")
            sys.exit(-1)

        # used in server start
        self.running = True
        self.nrobots = nrobots
        self.radar_radius = radar_radius
        self.ncells = ncells
        self.obstacles_dist = obstacles_dist
        self.wifi_range = wifi_range
        self.alpha = alpha
        self.gamma = gamma
        self.ninjured = ninjured
        self.inj_pri = inj_pri
        self.dump_datas = dump_datas
        self.optimization_task = optimization_task
        self.frontier = set()
        self.broken_beans = 0
        # Data collection tools
        if self.dump_datas:
            # it represents the sum of the difficulties of every cell
            self.total_difficulty = 0

            self.dc_robot_status = DataCollector({
                "idling":
                lambda m: self.get_number_robots_status(m, "idling"),
                "travelling":
                lambda m: self.get_number_robots_status(m, "travelling"),
                "exploring":
                lambda m: self.get_number_robots_status(m, "exploring"),
                "deploying_bean":
                lambda m: self.get_number_robots_status(m, "deploying_bean"),
                "step":
                lambda m: self.get_step(m)
            })
            self.time_csv = time_csv
            self.robot_status_csv = robot_status_csv

        if self.optimization_task:
            self.total_idling_time = 0

        self.alpha_variation = alpha_variation
        self.gamma_variation = gamma_variation
        if self.alpha_variation:
            self.costs_each_path = list()
            self.alpha_csv = alpha_csv
            self.alpha_step = dict()
            self.alpha_step_csv = alpha_step_csv
        if self.gamma_variation:
            self.gamma_df = pd.DataFrame(columns=["step", "mean", "std"])
            self.gamma_csv = gamma_csv

        self.schedule = RandomActivation(self)
        # unique counter for agents
        self.agent_counter = 1
        self.nobstacle = 0
        # graph of seen cells
        self.seen_graph = nx.DiGraph()

        rnd.seed()

        # place a cell agent for store data and visualization on each cell of the grid
        # if map is not taken from file, create it
        if load_file == None:
            self.grid = MultiGrid(ncells + 2, ncells + 2, torus=False)
            for i in self.grid.coord_iter():
                if i[1] != 0 and i[2] != 0 and i[1] != self.ncells + 1 and i[
                        2] != self.ncells + 1:
                    rand = np.random.random_sample()
                    obstacle = True if rand < self.obstacles_dist else False
                    # if obstacle
                    if obstacle:
                        self.nobstacle += 1
                        difficulty = math.inf
                        explored = -1
                        priority = 0
                        utility = -math.inf
                    # if free
                    else:
                        difficulty = np.random.randint(low=1, high=13)
                        if self.dump_datas:
                            self.total_difficulty += difficulty
                        explored = 0
                        priority = 0
                        utility = 1.0
                # if contour cell
                else:
                    difficulty = np.random.randint(low=1, high=13)
                    explored = -2
                    priority = -math.inf
                    utility = -math.inf
                # place the agent in the grid
                a = Cell(self.agent_counter, self, i[1:], difficulty, explored,
                         priority, utility)
                self.grid.place_agent(a, i[1:])
                self.agent_counter += 1

            # create injured agents
            valid_coord = []
            for i in self.grid.coord_iter():
                cell = [
                    e for e in self.grid.get_cell_list_contents(i[1:])
                    if isinstance(e, Cell)
                ][0]
                if cell.explored == 0:
                    valid_coord.append(cell.pos)
            for i in range(0, ninjured):
                inj_index = rnd.choice(valid_coord)
                a = Injured(self.agent_counter, self, inj_index)
                self.schedule.add(a)
                self.grid.place_agent(a, inj_index)
                self.agent_counter += 1
        else:
            # load map from file
            try:
                with open(load_file, 'r') as f:
                    file = f.read()
            except:
                print("file not found")
                sys.exit(-1)
            exported_map = literal_eval(file)
            self.ncells = int(math.sqrt(len(exported_map["Cell"].keys()))) - 2
            self.grid = MultiGrid(self.ncells + 2,
                                  self.ncells + 2,
                                  torus=False)
            for index in exported_map["Cell"].keys():
                cell = exported_map["Cell"][index]
                difficulty = cell[2]
                explored = cell[3]
                priority = cell[4]
                utility = cell[5]
                if difficulty == "inf":
                    difficulty = math.inf
                if priority == "-inf":
                    priority = -math.inf
                if utility == "-inf":
                    utility = -math.inf
                if explored == -1:
                    self.nobstacle += 1
                if self.dump_datas and utility == 1:
                    self.total_difficulty += difficulty
                a = Cell(self.agent_counter, self, index, difficulty, explored,
                         priority, utility)
                self.grid.place_agent(a, index)
                self.agent_counter += 1

            for index in exported_map["Injured"].keys():
                a = Injured(self.agent_counter, self, index)
                self.schedule.add(a)
                self.grid.place_agent(a, index)
                self.agent_counter += 1

        # create robotic agents
        row = 0
        starting_coord = []
        # data collection number of beans requested
        if self.dump_datas:
            self.deployed_beans_at_start = 0
        # generating the list for the starting position of robots
        for c in range(self.grid.width):
            # take the agent cell
            cell = [
                e for e in self.grid.get_cell_list_contents(tuple([c, row]))
                if isinstance(e, Cell)
            ][0]
            if cell.explored != -1:
                starting_coord.append(c)
        for i in range(0, self.nrobots):
            column = rnd.choice(starting_coord)
            a = Robot(self.agent_counter, self, tuple([column, row]),
                      self.radar_radius)
            self.schedule.add(a)
            self.grid.place_agent(a, (column, row))
            self.agent_counter += 1
            # create initial frontier: add cell in front of the robot if valid and not obstacles
            cell = [
                e for e in self.grid.get_cell_list_contents(
                    tuple([column, row + 1])) if isinstance(e, Cell)
            ][0]
            if cell.explored == 0:
                self.frontier.add(tuple([column, row + 1]))
            try:
                cell = [
                    e for e in self.grid.get_cell_list_contents(
                        tuple([column + 1, row + 1])) if isinstance(e, Cell)
                ][0]
                if cell.explored == 0:
                    self.frontier.add(tuple([column + 1, row + 1]))
            except:
                pass
            try:
                cell = [
                    e for e in self.grid.get_cell_list_contents(
                        tuple([column - 1, row + 1])) if isinstance(e, Cell)
                ][0]
                if cell.explored == 0:
                    self.frontier.add(tuple([column - 1, row + 1]))
            except:
                pass

            cell = [
                e
                for e in self.grid.get_cell_list_contents(tuple([column, row]))
                if isinstance(e, Cell)
            ][0]
            # in the cell where some robots are deployed, only one bean is deployed
            if not cell.wifi_bean:
                cell.wifi_bean = True
                for index in self.grid.get_neighborhood(
                        cell.pos,
                        "moore",
                        include_center=False,
                        radius=self.wifi_range):
                    cell = [
                        e for e in self.grid.get_cell_list_contents(index)
                        if isinstance(e, Cell)
                    ][0]
                    cell.wifi_covered = True
                if self.dump_datas:
                    self.deployed_beans_at_start += 1

    # what the model does at each time step
    def step(self):

        # data collection for alpha variation
        if self.alpha_variation:
            sim_step = self.get_step(self)
            self.alpha_step[sim_step] = list()

        # call step function for all of the robots in random order
        self.schedule.step()

        if self.dump_datas:
            self.dc_robot_status.collect(self)
        if self.optimization_task:
            self.total_idling_time += self.get_number_robots_status(
                self, "idling")
        if self.gamma_variation:
            distances = self.compute_robot_distances(self)
            self.gamma_df = self.gamma_df.append(
                {
                    "step": self.get_step(self),
                    "mean": distances[0],
                    "std": distances[1]
                },
                ignore_index=True,
                sort=False)
        # if all seen cells have benn explored, stop the simulation
        # we do this so if there are unreachable cells, the cannot be seen, so the simulation stops anyway
        stop_exploration_done = True
        for node in self.seen_graph.nodes():
            cell = [
                obj for obj in self.grid.get_cell_list_contents(node)
                if isinstance(obj, Cell)
            ][0]
            if cell.explored == 0 or cell.explored == 1:
                stop_exploration_done = False
        stop_no_robots = False
        if len([x for x in self.schedule.agents if isinstance(x, Robot)]) == 0:
            stop_no_robots = True
        stop = stop_exploration_done or stop_no_robots

        if stop:
            print("Simultation ended")
            # Data collection
            if self.dump_datas:
                df = pd.read_csv(self.time_csv)
                df = df.append(
                    {
                        "nrobots": self.nrobots,
                        "ncells": self.ncells,
                        "steps": self.schedule.steps,
                        "total_difficulty": self.total_difficulty,
                        "beans_deployed": self.get_number_bean_deployed(self)
                    },
                    ignore_index=True)
                df.to_csv(self.time_csv, index=False)

                df_robots_status = self.dc_robot_status.get_model_vars_dataframe(
                )
                df = pd.read_csv(self.robot_status_csv)
                if len(df["sim_id"]) == 0:
                    df_robots_status["sim_id"] = 0
                else:
                    df_robots_status["sim_id"] = df["sim_id"][df.index[-1]] + 1
                df = df.append(df_robots_status, ignore_index=True, sort=False)
                df.to_csv(self.robot_status_csv, index=False)

            if self.alpha_variation:
                mean = round(np.mean(self.costs_each_path), 3)
                std = round(np.std(self.costs_each_path), 3)
                df = pd.read_csv(self.alpha_csv)
                df = df.append(
                    {
                        "nrobots": self.nrobots,
                        "radar_radius": self.radar_radius,
                        "alpha": self.alpha,
                        "gamma": self.gamma,
                        "mean": mean,
                        "std": std
                    },
                    ignore_index=True)
                df.to_csv(self.alpha_csv, index=False)

                tmp_df = pd.DataFrame(columns=["step", "cost"])
                for s, costs in zip(self.alpha_step.keys(),
                                    self.alpha_step.values()):
                    if not costs:
                        tmp_df = tmp_df.append({
                            "step": s,
                            "cost": -1
                        },
                                               ignore_index=True,
                                               sort=False)
                        continue
                    for c in costs:
                        tmp_df = tmp_df.append({
                            "step": s,
                            "cost": c
                        },
                                               ignore_index=True,
                                               sort=False)
                df = pd.read_csv(self.alpha_step_csv)
                if len(df["sim_id"]) == 0:
                    tmp_df["sim_id"] = 0
                else:
                    tmp_df["sim_id"] = df["sim_id"][df.index[-1]] + 1
                tmp_df["nrobots"] = self.nrobots
                tmp_df["radar_radius"] = self.radar_radius
                tmp_df["alpha"] = self.alpha
                tmp_df["gamma"] = self.gamma
                df = df.append(tmp_df, ignore_index=True, sort=False)
                df.to_csv(self.alpha_step_csv, index=False)

            if self.gamma_variation:
                df = pd.read_csv(self.gamma_csv)
                if len(df["sim_id"]) == 0:
                    self.gamma_df["sim_id"] = 0
                else:
                    self.gamma_df["sim_id"] = df["sim_id"][df.index[-1]] + 1
                self.gamma_df["nrobots"] = self.nrobots
                self.gamma_df["radar_radius"] = self.radar_radius
                self.gamma_df["alpha"] = self.alpha
                self.gamma_df["gamma"] = self.gamma
                df = df.append(self.gamma_df, ignore_index=True, sort=False)
                df.to_csv(self.gamma_csv, index=False)

            self.running = False

    def run_model(self):
        while (True):
            # search for unexplored cells
            stop = True
            for node in self.seen_graph.nodes():
                cell = [
                    obj for obj in self.grid.get_cell_list_contents(node)
                    if isinstance(obj, Cell)
                ][0]
                if cell.explored == 0 or cell.explored == 1:
                    stop = False
            # if all seen cells have benn explored, stop the simulation
            # we do this so if there are unreachable cells, the cannot be seen, so the simulation stops anyway
            if stop:
                self.running = False
                break
            else:
                self.step()

    # Data collection utilities
    @staticmethod
    def get_step(m):
        return m.schedule.steps

    # these two should go faster since cells are not in the scheduler anymore
    @staticmethod
    def get_number_robots_status(m, status):
        status_value = {
            "idling": 0,
            "travelling": 1,
            "exploring": 2,
            "deploying_bean": 3
        }
        return len([
            x for x in m.schedule.agents
            if isinstance(x, Robot) and x.status == status_value[status]
        ])

    @staticmethod
    def get_number_bean_deployed(m):
        return sum([
            x.number_bean_deployed
            for x in m.schedule.agents if isinstance(x, Robot)
        ]) + m.deployed_beans_at_start

    # function for gamma variation
    @staticmethod
    def compute_robot_distances(m):
        nrobots = m.nrobots
        T_up = np.full(
            (nrobots, nrobots),
            0.0)  # if it's only zero, numpy represents only integers
        # didn't dig deep in numpy doc but it looks like it handles triangualr matrices as "normal" matrices, so
        # i just initilize a full matrix and then i'll use it as a triangular.
        robots = [x for x in m.schedule.agents if isinstance(x, Robot)]
        # the order of the robots in robots can change from step to step (due to the random scheduler),
        # This shouldn't create any type of problem, but to avoid a lot of problems with indexes later on
        # we sort them basing on the unique_id
        robots.sort(key=lambda x: x.unique_id)
        # I need the lowest id to shift back the ids to fit the matrices coordinations
        lowest_id = robots[0].unique_id
        for r in robots:
            matrix_id_row = r.unique_id - lowest_id
            # the distance of a robot to itself is zero by definition
            y1, x1 = r.pos
            for i in range(matrix_id_row + 1, nrobots):
                r2 = robots[i]  # i can do this because they are sorted
                y2, x2 = r2.pos
                T_up[matrix_id_row][i] = distance.euclidean([x1, y1], [x2, y2])
        mean_dist_robots = list()
        # the robot 0 has only the rows
        mean_robot_zero = sum(T_up[0, 1:nrobots])
        mean_dist_robots.append(mean_robot_zero)
        for i in range(1, nrobots -
                       1):  # the last row has no values, i iters the rows
            mean_robot = (sum(T_up[0:i, i]) +
                          sum(T_up[i, i + 1:nrobots])) / (nrobots - 1)
            mean_dist_robots.append(mean_robot)
        # last robot has only the columns
        mean_last_robot = sum(T_up[0:nrobots - 1, nrobots - 1])
        mean_dist_robots.append(mean_last_robot)
        return tuple([
            round(np.mean(mean_dist_robots), 3),
            round(np.std(mean_dist_robots), 3)
        ])
示例#10
0
class Model(Model):
    def __init__(self, N, B, T, Treg, width, height):
        self.num_myelin = N * 8
        self.num_agents = N + B + T + Treg + self.num_myelin
        self.num_neurons = N
        self.num_myelin = 4
        self.num_limfocytB = B
        self.num_active_B = 0
        self.num_infected_B = 0
        self.num_limfocytT = T
        self.num_activeT = 0
        self.num_limfocytTreg = Treg
        self.grid = MultiGrid(width, height, True)
        self.schedule = RandomActivation(self)
        self.available_ids = set()
        self.dead_agents = set()
        self.new_agents = set()
        self.max_id = 0
        self.step_count = 1
        self.cytokina = 0
        self.cytokina_prev = 0
        self.sum = 0
        self.B = 0
        self.a = 0.80
        self.Ymax = 100
        open('new_and_dead.txt', 'w').close()
        # Create agents
        neuron_positions = [[3, 3], [3, 10], [3, 20], [3, 27], [10, 3],
                            [10, 10], [10, 20], [10, 27], [19, 3], [19, 10],
                            [19, 20], [19, 27], [26, 3], [26, 10], [26, 20],
                            [26, 27], [14, 15]]
        for i in range(self.num_neurons):
            a = Neuron(i, self, "Neuron")
            self.schedule.add(a)
            #Add agent to a random grid cell
            #x=self.random.randrange(self.grid.width)
            #y=self.random.randrange(self.grid.height)
            #self.grid.place_agent(a,(x,y))
            pos = neuron_positions[i]
            self.grid.place_agent(a, (pos[0], pos[1]))
            cells = self.grid.get_neighborhood(a.pos, True, False, 1)
            id = self.num_agents - i * 8
            for cell in cells:
                m = Myelin(id, self, "Myelin")
                self.schedule.add(m)
                self.grid.place_agent(m, cell)
                id -= 1

        #dodawanie różnych typów agentów zgodnie z ich liczbą podaną przy inicjacji modelu
        for i in range(self.num_limfocytB):
            a = LimfocytB(i + self.num_neurons, self, "LimfocytB")
            self.schedule.add(a)
            #Add agent to a random grid cell
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(a, (x, y))
        for i in range(self.num_limfocytT):
            a = LimfocytT(i + N + B, self, "LimfocytT")
            self.schedule.add(a)
            #Add agent to a random grid cell
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(a, (x, y))
        for i in range(self.num_limfocytTreg):
            a = LimfocytTreg(i + N + B + T, self, "LimfocytTreg")
            self.schedule.add(a)
            #Add agent to a random grid cell
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(a, (x, y))

        self.max_id = self.num_agents - 1

        self.datacollector_population = DataCollector(
            model_reporters={"Populacja": compute_population})
        self.datacollector_T_population = DataCollector(
            model_reporters={"Populacja Limfocytów T": T_population})
        #self.datacollector_T_precentage=DataCollector(
        #model_reporters={"Precentage Limfocyt T": T_popualtion_precentage})
        self.datacollector_B_population = DataCollector(
            model_reporters={"Populacja Limfocytów B": B_population})
        self.datacollector_Treg_population = DataCollector(
            model_reporters={"Populacja Limfocytów Treg": Treg_population})
        self.datacollector_B_active_population = DataCollector(
            model_reporters={
                "Populacja Aktywnych Limfocytów B": B_activated_population
            })
        self.datacollector_T_active_population = DataCollector(
            model_reporters={
                "Populacja Aktywnych Limfocytów T": T_activated_population
            })

        self.datacollector_B_infected_population = DataCollector(
            model_reporters={
                "Populacja Zainfekowanych Limfocytów B": B_infected_population
            })

        self.datacollector_myelin_population = DataCollector(
            model_reporters={
                "Populacja osłonek mielinowych": myelin_population
            })

        self.datacollector_myelin_healths = DataCollector(
            model_reporters={
                "Suma punktów życia osłonek mielinowych": myelin_healths
            })

    def step(self):
        #print("self running: "+str(self.running()))

        self.schedule.step()
        self.datacollector_population.collect(self)
        self.datacollector_T_population.collect(self)
        #self.datacollector_T_precentage.collect(self)
        self.datacollector_B_population.collect(self)
        self.datacollector_Treg_population.collect(self)
        self.datacollector_B_active_population.collect(self)
        self.datacollector_T_active_population.collect(self)
        self.datacollector_B_infected_population.collect(self)
        self.datacollector_myelin_population.collect(self)
        self.datacollector_myelin_healths.collect(self)
        self.adding_removing()

        self.datacollector_myelin_healths.get_model_vars_dataframe().to_csv(
            r'Data/myelin_healths25.txt', sep=' ', mode='w')
        self.datacollector_T_population.get_model_vars_dataframe().to_csv(
            r'Data/T_population25.txt', sep=' ', mode='w')
        self.datacollector_B_population.get_model_vars_dataframe().to_csv(
            r'Data/B_population25.txt', sep=' ', mode='w')
        self.datacollector_Treg_population.get_model_vars_dataframe().to_csv(
            r'Data/Treg_population25.txt', sep=' ', mode='w')
        self.datacollector_B_active_population.get_model_vars_dataframe(
        ).to_csv(r'Data/B_active_population25.txt', sep=' ', mode='w')
        self.datacollector_T_active_population.get_model_vars_dataframe(
        ).to_csv(r'Data/T_active_population25.txt', sep=' ', mode='w')
        self.datacollector_B_infected_population.get_model_vars_dataframe(
        ).to_csv(r'Data/B_infected_population25.txt', sep=' ', mode='w')

        print("Liczba agentów: " + str(self.num_agents))
        print("MaxID: " + str(self.max_id))

        self.cytokina = max(
            min((self.B + self.cytokina_prev), self.Ymax) * self.a, 0)

        print("Cytokina " + str(self.cytokina))
        print("Cytokina_prev " + str(self.cytokina_prev))

        f = open("agents.txt", 'a')
        f.write("======Step : " + str(self.step_count) + "\n")
        for agent in self.schedule.agents:
            f.write("Agent: " + str(agent.type) + " " + str(agent.unique_id) +
                    str(agent.pos) + "\n")

        f.close()
        self.cytokina_prev = self.cytokina
        self.B = 0

    def running(self):
        self.step()

    def adding_removing(
            self):  #funckja odpowiedzialna za dodawanie i usuwanie agentów
        #print("AddingRemoving")
        f = open("new_and_dead.txt", 'a')
        f.write("Step " + str(self.step_count) + "\n")
        f.write("======Dead agents======: " + "\n")
        for d in self.dead_agents:
            try:
                self.schedule.remove(d)
                self.num_agents -= 1
                self.available_ids.add(d.unique_id)
            except KeyError:
                continue
            try:
                self.grid._remove_agent(d.pos, d)
            except KeyError:
                continue
            f.write(str(d.unique_id) + " " + d.type + "\n")
            #if d.type=="AktywowanyLimfocytT":
            #    self.cytokina-=1
        self.dead_agents.clear()
        f.write("======New Agents=====: " + "\n")
        for n in self.new_agents:
            self.schedule.add(n)
            self.num_agents += 1
            self.grid.place_agent(n, n.pos)
            if n.unique_id in self.available_ids:
                self.available_ids.remove(n.unique_id)
            f.write(str(n.unique_id) + " " + n.type + "\n")
            #if n.type=="AktywowanyLimfocytT":
            #   self.cytokina+=1
        self.new_agents.clear()
        m = 1
        n = 0
        for agent in self.schedule.agents:
            if agent.unique_id > m:
                m = agent.unique_id
            if (agent.type == "LimfocytT") or (agent.type
                                               == "AktywowanyLimfocytT"):
                n += 1
        self.max_id = m
        self.num_limfocytT = 0
        self.deficiencies()
        f.close()

    def deficiencies(self):
        n = B_population(self)
        if n == 0:
            if len(self.available_ids) == 0:
                self.max_id += 1
                id = self.max_id
            else:
                id = min(self.available_ids)
                self.available_ids.remove(id)
            agent = LimfocytB(id, self, "LimfocytB")
            self.schedule.add(agent)
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(agent, (x, y))
            self.num_agents += 1
        n = T_population(self)
        if n == 0:
            for i in range(10):
                if len(self.available_ids) == 0:
                    self.max_id += 1
                    id = self.max_id
                else:
                    id = min(self.available_ids)
                    self.available_ids.remove(id)
                agent = LimfocytB(id, self, "LimfocytT")
                self.schedule.add(agent)
                x = self.random.randrange(self.grid.width)
                y = self.random.randrange(self.grid.height)
                self.grid.place_agent(agent, (x, y))
                self.num_agents += 1
        n = Treg_population(self)
        if n == 0:
            if len(self.available_ids) == 0:
                self.max_id += 1
                id = self.max_id
            else:
                id = min(self.available_ids)
                self.available_ids.remove(id)
            agent = LimfocytB(id, self, "LimfocytTreg")
            self.schedule.add(agent)
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(agent, (x, y))
            self.num_agents += 1
示例#11
0
class Model(Model):
    """A model with a number of agents.
    It represents a space where you can experiment by varying parameters"""

    def __init__(self, n_victims, n_offenders, n_criminal_generators, r_criminal_generators, max_cp,
                 pop_count, width, height):

        self.grid = MultiGrid(width, height, torus=False)
        self.schedule = RandomActivation(self)
        self.datacollector = DataCollector(
            model_reporters={"Average Perception of Safety": average_perception_of_safety,
                             "Crime-rate": crime_rate_single_run},
        )
        self.width = width
        self.height = height
        self.running = True

        # Number of crimes committed per time step.
        self.crime_number = 0.0


        # User settable parameters
        self.num_victims = n_victims
        self.num_offenders = n_offenders
        self.num_crime_areas = n_criminal_generators
        self.crime_area_rad = r_criminal_generators
        self.hotspot_rad = 1
        self.max_criminal_preference = max_cp
        self.pop_count = pop_count

        # add light agents to the grid
        self.light_layer()

        # add possible victims to the grid
        self.add_victims()

        # add possible offenders to the grid
        self.add_offenders()

        # add crime areas
        self.add_criminal_areas()

        self.datacollector.collect(self)

    def light_layer(self):
        """Add the light layer to the model. """
        for i in range(self.width):
            for j in range(self.height):
                l = Light(uuid.uuid4(), i + j, self)
                self.schedule.add(l)
                # light is ordered from darkest to lightest from the
                # bottom left corner to the top right corner.
                self.grid.place_agent(l, (i, j))

                # light is randomised, so long as the
                # luminance difference of surrounding cells is within a limit
                # self.grid.place_agent(l, self.r_pos(l))

    def r_pos(self, new_l):
        """Randomises the positions of the light realistically by considering the difference
        between the illuminance in one position and another"""

        # Position precisely one light agent per position.
        valid = False

        while not valid:
            x = self.random.randrange(self.width)
            y = self.random.randrange(self.height)

            # Check if there is already a light agent in this spot
            if not (any(isinstance(agent, Light)
                        for agent in self.grid.get_cell_list_contents((x, y)))):
                # Check whether given the difference in the influencing factors between the agent
                # and surrounding agents, the new agent can be placed in this position.
                # Returns True or False
                if self.valid_pos((x, y), new_l, 1):
                    valid = True
                    return x, y

    def valid_pos(self, n_pos, new_a, delta):
        """Check whether this position is a valid position given the difference in
        the inlfueincing factors between the new agent and the surrounding agents"""

        # Get the surrounding positions
        neighborhood = self.grid.get_neighborhood(n_pos, moore=True,
                                                  include_center=False)


        # Get the surrounding positions containing light agents.
        cell_contents = []
        for pos in neighborhood:
            cell_contents.append(self.grid.get_cell_list_contents([pos]))

        f_cell_contents = [val for sublist in cell_contents for val in sublist]

        surr_light = [a for a in f_cell_contents if isinstance(a, Light)]

        # If the surrounding light list is empty, return the position
        if len(surr_light) == 0:
            return True
        else:
            # Check whether the difference in illuminance is within the valid scope
            for l in surr_light:

                if abs(l.illuminance - new_a.illuminance) >= delta:
                    return False

        return True

    def get_random_pos(self):
        x = self.random.randrange(self.grid.width)
        y = self.random.randrange(self.grid.height)
        return (x, y)

    def add_victims(self):
        for i in range(self.num_victims):
            # Generate a safe location for this agent.
            s = SafeLocation(uuid.uuid4(), self)
            self.schedule.add(s)
            self.grid.place_agent(s, self.get_random_pos())

            # Generate the agent given its safe location.
            p = PossibleVictim(uuid.uuid4(), self, s)
            self.schedule.add(p)
            self.grid.place_agent(p, self.get_random_pos())

    def add_offenders(self):
        for i in range(self.num_offenders):
            c = PossibleOffender(uuid.uuid4(), self, self.max_criminal_preference)
            self.schedule.add(c)
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(c, (x, y))

    def generate_criminal_areas(self):
        """ Return a list of criminal areas with specified centroids and radius.
            If criminal areas overlap, update the criminal areas.

            DOES NOT ADD THE AREAS TO THE MODEL, AS IT IS ONLY THE POSITIONS
            WITHIN THE AREAS THAT ARE ADDED TO THE MODEL. """

        # ----- HELPER FUNCTION -----

        def generate_centroid_list(n):
            """ If no centroids have been passed,
            generate random centroids for the criminal areas. """
            centroids = []
            for i in range(n):
                x = self.random.randrange(self.grid.width)
                y = self.random.randrange(self.grid.height)
                centroids.append((x, y))
            return centroids

        def get_surr_pos(pos, r=3):
            return self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=r)

        # ---------------------------
        centroids = self.num_crime_areas
        radius = self.crime_area_rad

        # If the parameter passed as the centroid is an int, generate this number of centroids.
        if isinstance(centroids, int):
            centroids = generate_centroid_list(centroids)

        criminal_area = []
        # For every centroid in the list, create either a hotspot or a criminal area depending
        # on the type.
        for c in centroids:
            criminal_area.append(CrimeGenerator(uuid.uuid4(), self, c, radius))

        # Return a list of criminal areas.
        return criminal_area

    def add_criminal_areas(self, criminal_area=None):
        """Add crime areas to the model. """
        # If no criminal area has been passed, generate random criminal area.
        if criminal_area is None:
            criminal_area = self.generate_criminal_areas()

    def increment_crimes(self):
        self.crime_number += 1
        global crime_number
        crime_number += 1

    def check_victim_agents(self):
        if not [agent for agent in self.schedule.agents if
                isinstance(agent, PossibleVictim)]:
            self.running = False

    def step(self):
        """Advance the model by one step."""
        self.schedule.step()
        self.datacollector.collect(self)
        self.check_victim_agents()
        self.crime_number = 0
示例#12
0
class SleepAnimals_sinDataColl(Model):
    '''
    Analysis of the evolution of sleep in animals
    '''

    # Default values
    width               = 40
    height              = 40
    
    number_food_patch   = 40
    number_sleep_patch  = 40

    interdistance_factor    = 0.7
    intradistance_factor    = 0.2

    fp_depletion_tick   = 60
        
    def __init__(self, model_id , genome,width = 40, height = 40, 
                 number_food_patch = 40, number_sleep_patch = 40,
                 interdistance_factor = 0.7, intradistance_factor = 0.2,
                 fp_depletion = 60, sleep_and_food_gainfactor = 1):
        super().__init__()
        
        # Setting Parameters
        self.model_id               = model_id
        self.width                  = width
        self.height                 = height
        self.number_food_patch      = number_food_patch
        self.number_sleep_patch     = number_sleep_patch
        self.interdistance_factor   = interdistance_factor
        self.intradistance_factor   = intradistance_factor
        self.sue_factor             = sleep_and_food_gainfactor
        self.genome = genome

        self.fp_center_x = 0
        self.fp_center_y = 0
        self.sp_center_x = 0
        self.sp_center_y = 0

        self.current_id_food_patch  = 0
        self.current_id_sleep_patch = 0

        self.fp_tick_to_depletion   = fp_depletion

        self.schedule = RandomActivation(self)
        self.grid = MultiGrid(self.width, self.height, torus = False)
        #self.datacollector = DataCollector(
        #   agent_reporters={"Food_fitness"  : lambda a: a.fitness_food,
        #                    "Sleep_fitness" : lambda a: a.fitness_sleep,
        #                    "Fitness"       : lambda a: a.fitness,
        #                    "Mode"          : lambda a: a.mode,
        #                    "Direction"     : lambda a: a.lookingto})
        
        # Picking Centers for Food and Sleep Patches
        self.interdistance = 0
        self.intradistance = 0
        self.findingcenters()

        # Populating Food Patches
        self.available_food_patches = self.grid.get_neighborhood( (self.fp_center_x, self.fp_center_y), False, True, self.intradistance )
        i = 0
        while i < self.number_food_patch:
            self.new_foodpatch()
            i += 1

        # Populating Sleep Patches
        self.available_sleep_patches = self.grid.get_neighborhood( (self.sp_center_x, self.sp_center_y), False, True, self.intradistance )
        i = 0
        while i < self.number_sleep_patch:
            current_spot = random.choice(self.available_sleep_patches)
            if not self.grid.is_cell_empty(current_spot):
                continue
            sleep_patch = SleepPatch( self.next_id_sleeppatch(), self, current_spot )
            self.grid.place_agent( sleep_patch, current_spot )
            i += 1
        
        # Adding Animal to the world
        current_spot = random.choice( self.grid.empties )
        animal = Animal( self.next_id(), self, current_spot, self.genome, self.sue_factor, self.sue_factor )
        self.grid.place_agent( animal, current_spot )
        self.schedule.add( animal )
        

    def step(self):
        '''Advance the model by one step.'''
#        self.datacollector.collect(self)
        self.schedule.step()

    def findingcenters(self):
        max_manhattan_length = self.height + self.width
        self.interdistance = int(max_manhattan_length * self.interdistance_factor)
        self.intradistance = int(max_manhattan_length * self.intradistance_factor)

        fp_center_x = 0
        fp_center_y = 0
        sp_center_x = 0
        sp_center_y = 0
        
        centers_selected = False

        while not centers_selected:
            fp_center_x = random.randrange(self.width)
            fp_center_y = random.randrange(self.height)
            fp_center = (fp_center_x, fp_center_y)
            
            available_spots_food = self.grid.get_neighborhood(fp_center, False, False, self.intradistance)
            if len(available_spots_food) < 80:
                continue
            
            if self.interdistance > 0:
                list_centers_sp = list( set( self.grid.get_neighborhood(fp_center, False, False, self.interdistance + 1) ) - 
                                        set( self.grid.get_neighborhood(fp_center, False, False, self.interdistance - 1) ) )
                if len(list_centers_sp) < 5:
                    continue
            else:
                list_centers_sp = [(fp_center_x,fp_center_y)]

            sp_center = random.choice(list_centers_sp)
            (sp_center_x, sp_center_y) = sp_center

            available_spots_sleep = self.grid.get_neighborhood(sp_center, False, False, self.intradistance)
            if len(available_spots_sleep) < 80:
                continue

            centers_selected = True

        self.fp_center_x = fp_center_x
        self.fp_center_y = fp_center_y
        self.sp_center_x = sp_center_x
        self.sp_center_y = sp_center_y

    def next_id_foodpatch(self):
        """ Return the next unique ID for food patches, increment current_id"""
        self.current_id_food_patch += 1
        a = 'M' + str(self.model_id) + 'F' + str(self.current_id_food_patch)
        return a

    def next_id_sleeppatch(self):
        """ Return the next unique ID for sleep patches, increment current_id"""
        self.current_id_sleep_patch += 1
        a = 'M' + str(self.model_id) + 'S' + str(self.current_id_sleep_patch)
        return a

    def new_foodpatch(self):
        spot_found = False
        while not spot_found :
            current_spot = random.choice(self.available_food_patches)
            if not self.grid.is_cell_empty(current_spot):
                continue
            food_patch = FoodPatch(self.next_id_foodpatch(), self, current_spot, self.fp_tick_to_depletion)
            self.grid.place_agent(food_patch, current_spot)
            spot_found = True

    def arrayRGB_clusters(self):
        available_spots = np.full( (self.grid.width , self.grid.height , 3) , 255)
        for coordinates in self.available_sleep_patches:
            (x, y) = coordinates
            available_spots[x][y]= [100, 0, 150]
        for coordinates in self.available_food_patches:
            (x, y) = coordinates
            available_spots[x][y]= [10, 150, 0]
        return available_spots

    def arrayRGB_display(self):
        RGBdisplay = np.full((self.grid.width, self.grid.height,3), 255)
        for cell in self.grid.coord_iter():
            cell_content, x, y = cell
            a = list(cell_content)
            if len(a) == 0:
                RGBdisplay[x][y] = [255,255,255]
            elif len(a) == 1:
                if      isinstance(a[0], SleepPatch):
                    RGBdisplay[x][y] = [100,0,150]
                elif    isinstance(a[0], FoodPatch):
                    RGBdisplay[x][y] = [10,150,0]
                elif    isinstance(a[0], Animal):
                    RGBdisplay[x][y] = [0,0,0]
                else:
                    pass
            elif len(a) == 2:
                RGBdisplay[x][y] = [0,0,0]
            else:
                pass
        return RGBdisplay

    def array2D_display(self):
        display2D = np.zeros((self.grid.width, self.grid.height))
        for cell in self.grid.coord_iter():
            cell_content, x, y = cell
            a = list(cell_content)
            if len(a) == 0:
                display2D[x][y] = 0
            elif len(a) == 1:
                if isinstance(a[0], SleepPatch):
                    display2D[x][y] = 10
                elif isinstance(a[0], FoodPatch):
                    display2D[x][y] = 20
                elif isinstance(a[0], Animal):
                    display2D[x][y] = 30
                else:
                    pass
            else:
                pass
        return display2D
示例#13
0
class FireEvacuation(Model):
    MIN_HEALTH = 0.75
    MAX_HEALTH = 1

    MIN_SPEED = 1
    MAX_SPEED = 2

    MIN_NERVOUSNESS = 1
    MAX_NERVOUSNESS = 10

    MIN_EXPERIENCE = 1
    MAX_EXPERIENCE = 10

    MIN_VISION = 1
    # MAX_VISION is simply the size of the grid

    def __init__(self, floor_plan_file, human_count, collaboration_percentage, fire_probability, visualise_vision, random_spawn, save_plots):
        # Load floorplan
        # floorplan = np.genfromtxt(path.join("fire_evacuation/floorplans/", floor_plan_file))
        with open(os.path.join("fire_evacuation/floorplans/", floor_plan_file), "rt") as f:
            floorplan = np.matrix([line.strip().split() for line in f.readlines()])

        # Rotate the floorplan so it's interpreted as seen in the text file
        floorplan = np.rot90(floorplan, 3)

        # Check what dimension our floorplan is
        width, height = np.shape(floorplan)

        # Init params
        self.width = width
        self.height = height
        self.human_count = human_count
        self.collaboration_percentage = collaboration_percentage
        self.visualise_vision = visualise_vision
        self.fire_probability = fire_probability
        self.fire_started = False  # Turns to true when a fire has started
        self.save_plots = save_plots

        # Set up model objects
        self.schedule = RandomActivation(self)

        self.grid = MultiGrid(height, width, torus=False)

        # Used to start a fire at a random furniture location
        self.furniture_list = []

        # Used to easily see if a location is a FireExit or Door, since this needs to be done a lot
        self.fire_exit_list = []
        self.door_list = []

        # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan
        self.random_spawn = random_spawn
        self.spawn_list = []

        # Load floorplan objects
        for (x, y), value in np.ndenumerate(floorplan):
            value = str(value)
            floor_object = None
            if value is "W":
                floor_object = Wall((x, y), self)
            elif value is "E":
                floor_object = FireExit((x, y), self)
                self.fire_exit_list.append((x, y))
                self.door_list.append((x, y))  # Add fire exits to doors as well, since, well, they are
            elif value is "F":
                floor_object = Furniture((x, y), self)
                self.furniture_list.append((x, y))
            elif value is "D":
                floor_object = Door((x, y), self)
                self.door_list.append((x, y))
            elif value is "S":
                self.spawn_list.append((x, y))

            if floor_object:
                self.grid.place_agent(floor_object, (x, y))
                self.schedule.add(floor_object)

        # Create a graph of traversable routes, used by agents for pathing
        self.graph = nx.Graph()
        for agents, x, y in self.grid.coord_iter():
            pos = (x, y)

            # If the location is empty, or a door
            if not agents or any(isinstance(agent, Door) for agent in agents):
                neighbors = self.grid.get_neighborhood(pos, moore=True, include_center=True, radius=1)

                for neighbor in neighbors:
                    # If there is contents at this location and they are not Doors or FireExits, skip them
                    if not self.grid.is_cell_empty(neighbor) and neighbor not in self.door_list:
                        continue

                    self.graph.add_edge(pos, neighbor)

        # Collects statistics from our model run
        self.datacollector = DataCollector(
            {
                "Alive": lambda m: self.count_human_status(m, Human.Status.ALIVE),
                "Dead": lambda m: self.count_human_status(m, Human.Status.DEAD),
                "Escaped": lambda m: self.count_human_status(m, Human.Status.ESCAPED),
                "Incapacitated": lambda m: self.count_human_mobility(m, Human.Mobility.INCAPACITATED),
                "Normal": lambda m: self.count_human_mobility(m, Human.Mobility.NORMAL),
                "Panic": lambda m: self.count_human_mobility(m, Human.Mobility.PANIC),
                "Verbal Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.VERBAL_SUPPORT),
                "Physical Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.PHYSICAL_SUPPORT),
                "Morale Collaboration": lambda m: self.count_human_collaboration(m, Human.Action.MORALE_SUPPORT)
            }
        )

        # Calculate how many agents will be collaborators
        number_collaborators = int(round(self.human_count * (self.collaboration_percentage / 100)))

        # Start placing human agents
        for i in range(0, self.human_count):
            if self.random_spawn:  # Place human agents randomly
                pos = self.grid.find_empty()
            else:  # Place human agents at specified spawn locations
                pos = random.choice(self.spawn_list)

            if pos:
                # Create a random human
                health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100
                speed = random.randint(self.MIN_SPEED, self.MAX_SPEED)

                if number_collaborators > 0:
                    collaborates = True
                    number_collaborators -= 1
                else:
                    collaborates = False

                # Vision statistics obtained from http://www.who.int/blindness/GLOBALDATAFINALforweb.pdf
                vision_distribution = [0.0058, 0.0365, 0.0424, 0.9153]
                vision = int(np.random.choice(np.arange(self.MIN_VISION, self.width + 1, (self.width / len(vision_distribution))), p=vision_distribution))

                nervousness_distribution = [0.025, 0.025, 0.1, 0.1, 0.1, 0.3, 0.2, 0.1, 0.025, 0.025]  # Distribution with slight higher weighting for above median nerovusness
                nervousness = int(np.random.choice(range(self.MIN_NERVOUSNESS, self.MAX_NERVOUSNESS + 1), p=nervousness_distribution))  # Random choice starting at 1 and up to and including 10

                experience = random.randint(self.MIN_EXPERIENCE, self.MAX_EXPERIENCE)

                belief_distribution = [0.9, 0.1]  # [Believes, Doesn't Believe]
                believes_alarm = np.random.choice([True, False], p=belief_distribution)

                human = Human(pos, health=health, speed=speed, vision=vision, collaborates=collaborates, nervousness=nervousness, experience=experience, believes_alarm=believes_alarm, model=self)

                self.grid.place_agent(human, pos)
                self.schedule.add(human)
            else:
                print("No tile empty for human placement!")

        self.running = True

    # Plots line charts of various statistics from a run
    def save_figures(self):
        DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
        OUTPUT_DIR = DIR + "/output"

        results = self.datacollector.get_model_vars_dataframe()

        dpi = 100
        fig, axes = plt.subplots(figsize=(1920 / dpi, 1080 / dpi), dpi=dpi, nrows=1, ncols=3)

        status_results = results.loc[:, ['Alive', 'Dead', 'Escaped']]
        status_plot = status_results.plot(ax=axes[0])
        status_plot.set_title("Human Status")
        status_plot.set_xlabel("Simulation Step")
        status_plot.set_ylabel("Count")

        mobility_results = results.loc[:, ['Incapacitated', 'Normal', 'Panic']]
        mobility_plot = mobility_results.plot(ax=axes[1])
        mobility_plot.set_title("Human Mobility")
        mobility_plot.set_xlabel("Simulation Step")
        mobility_plot.set_ylabel("Count")

        collaboration_results = results.loc[:, ['Verbal Collaboration', 'Physical Collaboration', 'Morale Collaboration']]
        collaboration_plot = collaboration_results.plot(ax=axes[2])
        collaboration_plot.set_title("Human Collaboration")
        collaboration_plot.set_xlabel("Simulation Step")
        collaboration_plot.set_ylabel("Successful Attempts")
        collaboration_plot.set_ylim(ymin=0)

        timestr = time.strftime("%Y%m%d-%H%M%S")
        plt.suptitle("Percentage Collaborating: " + str(self.collaboration_percentage) + "%, Number of Human Agents: " + str(self.human_count), fontsize=16)
        plt.savefig(OUTPUT_DIR + "/model_graphs/" + timestr + ".png")
        plt.close(fig)

    # Starts a fire at a random piece of furniture with file_probability chance
    def start_fire(self):
        rand = random.random()
        if rand < self.fire_probability:
            fire_furniture = random.choice(self.furniture_list)
            fire = Fire(fire_furniture, self)
            self.grid.place_agent(fire, fire_furniture)
            self.schedule.add(fire)
            self.fire_started = True
            print("Fire started at:", fire_furniture)

    def step(self):
        """
        Advance the model by one step.
        """

        self.schedule.step()

        # If there's no fire yet, attempt to start one
        if not self.fire_started:
            self.start_fire()

        self.datacollector.collect(self)

        # If no more agents are alive, stop the model and collect the results
        if self.count_human_status(self, Human.Status.ALIVE) == 0:
            self.running = False

            if self.save_plots:
                self.save_figures()

    @staticmethod
    def count_human_collaboration(model, collaboration_type):
        """
        Helper method to count the number of collaborations performed by Human agents in the model
        """

        count = 0
        for agent in model.schedule.agents:
            if isinstance(agent, Human):
                if collaboration_type == Human.Action.VERBAL_SUPPORT:
                    count += agent.get_verbal_collaboration_count()
                elif collaboration_type == Human.Action.MORALE_SUPPORT:
                    count += agent.get_morale_collaboration_count()
                elif collaboration_type == Human.Action.PHYSICAL_SUPPORT:
                    count += agent.get_physical_collaboration_count()

        return count

    @staticmethod
    def count_human_status(model, status):
        """
        Helper method to count the status of Human agents in the model
        """
        count = 0
        for agent in model.schedule.agents:
            if isinstance(agent, Human):
                if agent.get_status() == status:
                    count += 1
        return count

    @staticmethod
    def count_human_mobility(model, mobility):
        """
        Helper method to count the mobility of Human agents in the model
        """
        count = 0
        for agent in model.schedule.agents:
            if isinstance(agent, Human):
                if agent.get_mobility() == mobility:
                    count += 1
        return count
示例#14
0
class InfectionModel(Model):
    """A model for infection spread."""
    def __init__(self,
                 human_count,
                 random_spawn,
                 save_plots,
                 floor_plan_file="floorplan_1.txt",
                 N=30,
                 width=10,
                 height=10,
                 ptrans=0.5,
                 progression_period=3,
                 progression_sd=2,
                 death_rate=0.0193,
                 recovery_days=21,
                 recovery_sd=7):
        # Load floorplan
        # floorplan = np.genfromtxt(path.join("infection_spread/floorplans/", floor_plan_file))
        with open(
                os.path.join("infection_spread/floorplans/", floor_plan_file),
                "rt") as f:
            floorplan = np.matrix(
                [line.strip().split() for line in f.readlines()])

        # Rotate the floorplan so it's interpreted as seen in the text file
        floorplan = np.rot90(floorplan, 3)

        # Check what dimension our floorplan is
        width, height = np.shape(floorplan)

        # Init params
        self.num_agents = N
        self.initial_outbreak_size = 1
        self.recovery_days = recovery_days
        self.recovery_sd = recovery_sd
        self.ptrans = ptrans
        self.death_rate = death_rate
        self.running = True
        self.dead_agents = []
        self.width = width
        self.height = height
        self.human_count = human_count

        # Set up model objects
        self.schedule = RandomActivation(self)
        self.grid = MultiGrid(height, width, torus=False)

        # Used to easily see if a location is an Exit or Door, since this needs to be done a lot
        self.exit_list = []
        self.door_list = []
        # If random spawn is false, spawn_list will contain the list of possible spawn points according to the floorplan
        self.random_spawn = random_spawn
        self.spawn_list = []

        # Load floorplan objects
        for (x, y), value in np.ndenumerate(floorplan):
            value = str(value)
            floor_object = None

            if value == "W":
                floor_object = Wall((x, y), self)

            elif value == "E":
                floor_object = Exit((x, y), self)
                self.exit_list.append((x, y))
                self.door_list.append((x, y))  # Add exits to doors as well

            elif value == "D":
                floor_object = Door((x, y), self)
                self.door_list.append((x, y))

            elif value == "S":
                self.spawn_list.append((x, y))

            if floor_object:
                self.grid.place_agent(floor_object, (x, y))
                self.schedule.add(floor_object)

        # Create a graph of traversable routes, used by agents for pathing
        self.graph = nx.Graph()
        for agents, x, y in self.grid.coord_iter():
            pos = (x, y)

            # If the location is empty, or a door
            if not agents or any(isinstance(agent, Door) for agent in agents):
                neighbors = self.grid.get_neighborhood(pos,
                                                       moore=True,
                                                       include_center=True,
                                                       radius=1)

                for neighbor in neighbors:
                    # If there is contents at this location and they are not Doors or Exits, skip them
                    if not self.grid.is_cell_empty(
                            neighbor) and neighbor not in self.door_list:
                        continue

                    self.graph.add_edge(pos, neighbor)

        # Collects statistics from our model run
        self.datacollector = DataCollector({
            "Susceptible":
            lambda m: self.count_human_status(m, Human.State.SUSCEPTIBLE),
            "Infected":
            lambda m: self.count_human_status(m, Human.State.INFECTED),
            "Removed":
            lambda m: self.count_human_status(m, Human.State.REMOVED)
        })

        # Start placing human agents
        # for i in range(0, self.human_count):
        #    if self.random_spawn:  # Place human agents randomly
        #       pos = self.grid.find_empty()
        #  else:  # Place human agents at specified spawn locations
        #     pos = random.choice(self.spawn_list)

        #if pos:
        # Create a random human
        #   health = random.randint(self.MIN_HEALTH * 100, self.MAX_HEALTH * 100) / 100
        #  speed = random.randint(self.MIN_SPEED, self.MAX_SPEED)

        for i in range(0, self.num_agents):
            a = Human(unique_id=i, model=self)
            self.schedule.add(a)
            # Add the agent to a random grid cell
            # x = self.random.randrange(self.grid.width)
            # y = self.random.randrange(self.grid.height)
            # self.grid.place_agent(a, (x, y))

            if self.random_spawn:  # Place human agents randomly
                pos = self.grid.find_empty()
            else:  # Place human agents at specified spawn locations
                pos = random.choice(self.spawn_list)

            self.grid.place_agent(a, pos)

            #make some agents infected at start
            infected = np.random.choice([0, 1], 1, p=[0.98, 0.02])
            if infected == 1:
                a.state = State.INFECTED
                a.recovery_time = self.get_recovery_time()

        self.datacollector = DataCollector(
            #model_reporters={"Gini": compute_gini},
            agent_reporters={"State": "state"})

    def get_recovery_time(self):
        return int(
            self.random.normalvariate(self.recovery_days, self.recovery_sd))

    def step(self):
        """
        Advance the model by one step.
        """
        self.schedule.step()
        self.datacollector.collect(self)
示例#15
0
class CancerModel(Model):
    def __init__(self,cancer_cells_number,cure_number,eat_values, verovatnoca_mutacije):
        self.counter = 0
        self.cure_number = cure_number
        radoznalosti = list(np.arange(0.01,KILLING_PROBABILITY,0.01))
        print(radoznalosti)
        self.datacollector = DataCollector(
        model_reporters = {"FitnessFunction":fitness_funkcija,
                           "SpeedSum":overall_speed,"SmartMedicine":num_of_smart_medicine,
                           "RadoznalostSum":radoznalost_sum  })
        grid_size = math.ceil(math.sqrt(cancer_cells_number*4))
        self.grid = MultiGrid(grid_size,grid_size,False)
        speeds = list(range(grid_size//2)) #popravi te boje TODO
        print(speeds)

        poss = self.generate_cancer_cell_positions(grid_size,cancer_cells_number)
        num_CSC = math.ceil(percentage(1,cancer_cells_number))
        pos_CSC = [self.random.choice(poss) for i in range(num_CSC)]
        self.schedule = RandomActivation(self)
        self.running = True
        for i in range(cancer_cells_number):
            pos = poss[i]
            c = CancerStemCell(uuid.uuid4(),self,value = eat_values[CancerStemCell.__class__]) if pos in pos_CSC else CancerCell(i,self,value=eat_values[CancerCell.__class__])
            self.grid.place_agent(c,pos)
            self.schedule.add(c)
        for i in range(cure_number):
            #pos = self.grid.find_empty()
            pos = (0,0)
            radoznalost = self.random.choice(radoznalosti)
            speed = self.random.choice(speeds)
            a = CureAgent(uuid.uuid4(),self,speed = speed,radoznalost=radoznalost) if i< cure_number//2 else SmartCureAgent(uuid.uuid4(),self,speed=speed,radoznalost = radoznalost)
            self.grid.place_agent(a,pos)
            self.schedule.add(a)

        for (i,(contents, x,y)) in enumerate(self.grid.coord_iter()):
            if not contents:
                c = HealthyCell(uuid.uuid4(),self,eat_values[HealthyCell.__class__])
                self.grid.place_agent(c,(x,y))
                self.schedule.add(c)

    def generate_cancer_cell_positions(self,grid_size,cancer_cells_number):
        center = grid_size//2
        poss = [(center,center)]
        for pos in poss:
            poss+=[n for n in self.grid.get_neighborhood(pos,moore=True,include_center=False) if n not in poss]
            if len(set(poss))>=cancer_cells_number:
                break
        poss = list(set(poss))
        return poss


    def duplicate_or_kill(self):
        koliko = math.ceil(percentage(5,self.cure_number)) # TODO igor javlja kako biramo procena
        cureagents = [c for c in self.schedule.agents if isinstance(c,CureAgent)]
        sortirani = sorted(cureagents, key=lambda x: x.points, reverse=True)
        poslednji = sortirani[-koliko:]
        prvi = sortirani[:koliko]
        assert(len(prvi)==len(poslednji))
        self.remove_agents(poslednji)
        self.duplicate_agents(prvi)

    def remove_agents(self,agents):
        for a in agents:
            self.schedule.remove(a)
            self.grid.remove_agent(a)
    def duplicate_agents(self,agents):
        for a in agents:
            a_new = a.__class__(uuid.uuid4(),model=self,speed = a.speed,radoznalost = a.radoznalost) #TODO ostale parametre isto poistoveti
            self.grid.place_agent(a_new,(1,1))
            self.schedule.add(a_new)

    def step(self):
        self.datacollector.collect(self)
        self.counter+=1
        self.schedule.step()
        if self.counter%10 ==0: # TODO ovo menjamo, parameter TODO
            #TODO sredi boje i
            #TODO sredi ovo pucanje zbog nule u latin hypercube
            #TODO napravi da je R promenljivo
            self.duplicate_or_kill()
示例#16
0
class PandemicsModel(Model):
    def __init__(self, config=default_config, disease=dis.covid_disease):
        self.agents_count = config.citizens_count + config.policemen_count
        self.disease = disease
        self.deceased = []
        self.buried = []
        self.deceased_counter = 0
        self.infected_counter = 0
        self.grid = MultiGrid(config.width, config.height, True)
        self.safety_per_cell = np.ones((config.height, config.width))
        self.buildings_map = np.zeros((config.height, config.width))
        self.buildings_id_map = np.zeros((config.height, config.width))
        self.schedule = SimultaneousActivation(self)
        self.datacollector = DataCollector(
            model_reporters={
                "deceased": "deceased_counter",
                "infected": "infected_counter"},
            agent_reporters={
                "hp": lambda a: a.profile["hp"],
                "mask_protection": "mask_protection",
                "infection_day": lambda a: a.profile["infection_day"],
                "obedience": lambda a: a.profile["obedience"],
                "fear": lambda a: a.profile["fear"]}
        )
        self.config = config
        self.buildings = {b["id"] : b for b in self.config.buildings}
        self.houses = [x for x in self.buildings.values() if x['type'] == 'house']
        self.workplaces = [x for x in self.buildings.values() if x['type'] == 'workplace']
        self.shops = [x for x in self.buildings.values() if x['type'] == 'shop']

        self.add_buildings_to_map(self.buildings)

        self.street_positions = []
        for x in range(self.config.width):
            for y in range(self.config.height):
                if self.buildings_map[y][x] == 0:
                    self.street_positions.append((x, y))

        self.house_to_agents = defaultdict(list)
        self.workplace_to_agents = defaultdict(list)

        self.current_location_type = None

        # Create agents
        for i in range(self.agents_count):
            if i < config.policemen_count:
                a = agent.create_distribution_policeman_agent(
                        i, self, config.policemen_mental_features_distribution)
                a.assign_house(self, self.houses)
            elif i < config.policemen_count + config.citizens_count:
                a = agent.create_distribution_citizen_agent(
                        i, self, config.citizens_mental_features_distribution)
                a.assign_house(self, self.houses)
                a.assign_workplace(self, self.workplaces)
            self.add_agent(a)

        for i in self.random.choices(self.schedule.agents, k=config.infected_count):
            i.start_infection()
        self.running = True
        self.steps_count = 0
        self.datacollector.collect(self)

    # Returns (type, id) of the building where agent a is currently located
    def where_is_agent(self, a):
        (x, y) = a.pos
        return (self.buildings_map[y][x], self.buildings_id_map[y][x])

    def compute_time_of_day(self):
        return self.steps_count % self.config.steps_per_day / (self.config.steps_per_day / HOURS_PER_DAY)

    def compute_current_location_type(self):
        t = self.compute_time_of_day()
        return self.config.day_plan[t] if t in self.config.day_plan else \
                self.config.day_plan[min(self.config.day_plan.keys(), key=lambda k: k-t)]

    # Updates current location type based on time of day and the config schedule
    # Returns true if there is a change in current_location_type
    def update_current_location_type(self):
        t = self.compute_time_of_day()
        if t in self.config.day_plan:
            self.current_location_type = self.config.day_plan[t]
            return True
        return False

    def add_buildings_to_map(self, buildings):
        for b in buildings.values():
            (x, y) = b["bottom-left"]
            for i in range(x, x+b["width"]):
                for j in range(y, y+b["height"]):
                    self.buildings_map[j][i] = self.config.building_tags[b['type']]
                    self.buildings_id_map[j][i] = b['id']

    def add_agent(self, a):
        self.schedule.add(a)
        # Add the agent to a random grid cell
        x = self.random.randrange(self.grid.width)
        y = self.random.randrange(self.grid.height)
        self.grid.place_agent(a, (x, y))

    def bury_agent(self, a):
        self.schedule.remove(a)
        self.grid.remove_agent(a)
        self.deceased_counter += 1
        self.buried.append(a)

    def risk_from_agents(self, agents, weight):
        risk = 0
        for a in agents:
            risk += 1 - a.mask_protection
        return risk*weight

    def evaluate_safety_per_cell(self):
        """ 1.0 is a perfectly safe cell - empty, with all neighbours
        and neighbours-of-neighbours empty as well """
        for content, x, y in model.grid.coord_iter():
            self.safety_per_cell[y][x] = 1 # initial value
            # Compute risk from (x,y) cell
            ring0_risk = self.risk_from_agents(content, weight=0.5)
            considered_cells = {(x,y)}

            # Compute risk coming from the neighbours of (x,y) cell
            neighbours = self.grid.get_neighborhood(
                (x,y), moore=True, include_center=False)
            neighbours_content = self.grid.get_cell_list_contents(neighbours)
            ring1_risk = self.risk_from_agents(neighbours_content, 0.25)
            considered_cells | set(neighbours)

            # Compute risk coming from
            # the neighbours of the neighbours of (x,y) cell
            neighbours_of_neighbours = set()
            for c in neighbours:
                neighbours_of_neighbours | set(
                    self.grid.get_neighborhood(
                        (x,y),moore=True, include_center=False))
            neighbours_of_neighbours -= considered_cells
            ring2_risk = self.risk_from_agents(
                self.grid.get_cell_list_contents(neighbours_of_neighbours), 0.125)
            self.safety_per_cell[y][x] -= ring0_risk + ring1_risk + ring2_risk

    def step(self):
        if (self.update_current_location_type()):
            for a in self.schedule.agents:
                if (self.current_location_type is not None):
                    b = a.select_building(self.current_location_type)
                    a.teleport_to_building(b)
                else:
                    a.teleport_to_street()

        self.evaluate_safety_per_cell()
        self.schedule.step()
        self.steps_count += 1
        # collect data
        self.datacollector.collect(self)
        for d in self.deceased:
            self.bury_agent(d)
        self.deceased = []

    def run_model(self, n):
        for i in range(n):
            self.step()
示例#17
0
文件: model.py 项目: Fije/MC-ACO
class Environment(Model):
    """ A model which contains a number of ant colonies. """
    def __init__(self, width, height, n_colonies, n_ants, n_obstacles, decay=0.2, sigma=0.1, moore=False, birth=True, death=True):
        """
        :param width: int, width of the system
        :param height: int, height of the system
        :param n_colonies: int, number of colonies
        :param n_ants: int, number of ants per colony
        :param decay: float, the rate in which the pheromone decays
        :param sigma: float, sigma of the Gaussian convolution
        :param moore: boolean, True/False whether Moore/vonNeumann is used
        """
        super().__init__()

        # Agent variables
        self.birth = birth
        self.death = death

        self.pheromone_level = 1

        # Environment variables
        self.width = width
        self.height = height
        self.grid = MultiGrid(width, height, False)

        self.moore = moore

        self.sigma = sigma
        self.decay = decay

        # Environment attributes
        self.schedule = RandomActivation(self)

        self.colonies = [Colony(self, i, (width // 2, height // 2), n_ants, birth=self.birth, death=self.death) for i in range(n_colonies)]

        self.pheromones = np.zeros((width, height), dtype=np.float)
        self.pheromone_updates = []

        self.food = FoodGrid(self)
        self.food.add_food()

        self.obstacles = []
        for _ in range(n_obstacles):
            self.obstacles.append(Obstacle(self))

        # Metric + data collection
        self.min_distance = distance.cityblock(self.colonies[0].pos, self.food.get_food_pos())
        self.datacollector = DataCollector(
            model_reporters={"Minimum path length": metrics.min_path_length,
                             "Mean minimum path length": metrics.mean_min_path_length},
            agent_reporters={"Agent minimum path length": lambda x: min(x.path_lengths),
                            "Encounters": Ant.count_encounters})

        # Animation attributes
        self.pheromone_im = None
        self.ax = None

    def step(self):
        """
        Do a single time-step using freeze-dry states, colonies are updated each time-step in random orders, and ants
        are updated per colony in random order.
        """
        self.food.step()
        self.datacollector.collect(self)

        # Update all colonies
        for col in random.sample(self.colonies, len(self.colonies)):
            col.step()

        self.schedule.step()
        self.update_pheromones()

    def move_agent(self, ant, pos):
        """
        Move an agent across the map.
        :param ant: class Ant
        :param pos: tuple (x, y)
        """
        if self.moore:
            assert np.sum(np.subtract(pos, ant.pos) ** 2) in [1, 2], \
                "the ant can't move from its original position {} to the new position {}, because the distance " \
                "is too large".format(ant.pos, pos)
        else:
            assert np.sum(np.subtract(pos, ant.pos) ** 2) == 1, \
                "the ant can't move from its original position {} to the new position {}, because the distance " \
                "is too large, loc_food {}".format(ant.pos, pos, self.food.get_food_pos())

        self.grid.move_agent(ant, pos)

    def get_random_position(self):
        return (np.random.randint(0, self.width), np.random.randint(0, self.height))

    def position_taken(self, pos):
        if pos in self.food.get_food_pos():
            return True

        for colony in self.colonies:
            if colony.on_colony(pos):
                return True

        for obstacle in self.obstacles:
            if obstacle.on_obstacle(pos):
                return True

        return False

    def add_food(self):
        """
        Add food somewhere on the map, which is not occupied by a colony yet
        """
        self.food.add_food()

    def place_pheromones(self, pos):
        """
        Add pheromone somewhere on the map
        :param pos: tuple (x, y)
        """
        self.pheromone_updates.append((pos, self.pheromone_level))

    def get_neighbor_pheromones(self, pos, id):
        """
        Get the passable neighboring positions and their respective pheromone levels for the pheromone id
        :param pos:
        :param id:
        :return:
        """
        indices = self.grid.get_neighborhood(pos, self.moore)
        indices = [x for x in indices if not any([isinstance(x, Obstacle) for x in self.grid[x[0]][x[1]]])]

        pheromones = [self.pheromones[x, y] for x, y in indices]

        return indices, pheromones

    def update_pheromones(self):
        """
        Place the pheromones at the end of a timestep on the grid. This is necessary for freeze-dry time-steps
        """
        for (pos, level) in self.pheromone_updates:
            # self.pheromones[pos] += level
            self.pheromones[pos] += 1

        self.pheromone_updates = []

        # gaussian convolution using self.sigma
        self.pheromones = gaussian_filter(self.pheromones, self.sigma) * self.decay


    def animate(self, ax):
        """

        :param ax:
        :return:
        """
        self.ax = ax
        self.animate_pheromones()
        self.animate_colonies()
        self.animate_ants()
        self.animate_food()
        self.animate_obstacles()

    def animate_pheromones(self):
        """
        Update the visualization part of the Pheromones.
        :param ax:
        """

        pheromones = np.rot90(self.pheromones.astype(np.float64).reshape(self.width, self.height))
        if not self.pheromone_im:
            self.pheromone_im = self.ax.imshow(pheromones,
                                               vmin=0, vmax=50,
                                               interpolation='None', cmap="Purples")
        else:
            self.pheromone_im.set_array(pheromones)

    def animate_colonies(self):
        """
        Update the visualization part of the Colonies.
        :return:
        """
        for colony in self.colonies:
            colony.update_vis()

    def animate_food(self):
        """
        Update the visualization part of the FoodGrid.
        :return:
        """
        self.food.update_vis()

    def animate_ants(self):
        """
        Update the visualization part of the Ants.
        """
        for ant in self.schedule.agents:
            ant.update_vis()

    def animate_obstacles(self):
        """
        Update the visualization part of the Obstacles.
        :return:
        """
        for obstacle in self.obstacles:
            obstacle.update_vis()

    def grid_to_array(self, pos):
        """
        Convert the position/indices on self.grid to imshow array.
        :param pos: tuple (int: x, int: y)
        :return: tuple (float: x, float: y)
        """
        return pos[0] - 0.5, self.height - pos[1] - 1.5

    def pheromone_threshold(self, threshold):
        """ Returns an array of the positions in the grid in which
        the pheromone levels are above the given threshold"""
        pher_above_thres = np.where(self.pheromones >= threshold)

        return list(zip(pher_above_thres[0],pher_above_thres[1]))

    def find_path(self, pher_above_thres):
        """ Returns the shortest paths from all the colonies to all the food sources.
        A path can only use the positions in the given array. Therefore, this function
        checks whether there is a possible path for a certain pheremone level.
        Essentially a breadth first search"""
        space_searched = False
        all_paths = []
        food_sources = self.food.get_food_pos()

        # Search the paths for a colony to all food sources
        for colony in self.colonies:
            colony_paths = []
            pos_list = {colony.pos} # Prooning
            possible_paths = [[colony.pos]]

            # Continue expanding search area until all food sources found
            # or until the entire space is searched
            while food_sources != [] and not space_searched:
                space_searched = True
                temp = []

                for path in possible_paths:
                    for neighbor in self.grid.get_neighborhood(include_center=False, radius=1, pos=path[-1], moore=self.moore):
                        if neighbor in food_sources:
                            food_path = copy(path)
                            food_path.append(neighbor)
                            colony_paths.append(food_path)
                            food_sources.remove(neighbor)

                        # Add epanded paths to the possible paths
                        if neighbor in pher_above_thres and neighbor not in pos_list:
                            space_searched = False
                            temp_path = copy(path)
                            temp_path.append(neighbor)
                            temp.append(temp_path)
                            pos_list.add(neighbor)

                    possible_paths.remove(path)

                possible_paths += temp

        all_paths.append(colony_paths)

        return all_paths
示例#18
0
class World(Model):
    def __init__(self, N, coop, width=100, height=100):
        self.num_agents = N
        self.grid = MultiGrid(width, height, False)
        self.schedule = RandomActivation(self)
        self.running = True
        self.population_center_x = np.random.randint(
            POP_MARGIN, self.grid.width - POP_MARGIN)
        self.population_center_y = np.random.randint(
            POP_MARGIN, self.grid.height - POP_MARGIN)
        self.num_energy_resources = RESERVE_SIZE
        self.ages = []
        self.expected_ages = []
        self.num_explorers = 0
        self.num_exploiters = 0
        self.datacollector = DataCollector(model_reporters={
            "Num_Explorer": "num_explorers",
            "Num_Exploiter": "num_exploiters"
        })
        self.bases = self.init_base()

        # add social agents to the world
        for i in range(1, self.num_agents + 1):
            if np.random.uniform() <= EXPLORER_RATIO:
                # create a new explorer
                a = Explorer("explorer_%d" % (i), self, coop)
                self.num_explorers += 1
            else:
                # create a new exploiter
                a = Exploiter("exploiter_%d" % (i), self, coop)
                self.num_exploiters += 1

            # keep society members confined at beginning
            x = np.random.randint(self.population_center_x - POP_SPREAD,
                                  self.population_center_x + POP_SPREAD)
            y = np.random.randint(self.population_center_y - POP_SPREAD,
                                  self.population_center_y + POP_SPREAD)
            self.grid.place_agent(a, (x, y))

            # add agent to scheduler
            self.schedule.add(a)
            self.expected_ages.append(a.energy / a.living_cost)

        # add energy reserves to the world
        for i in range(self.num_energy_resources):
            a = EnergyResource("energy_reserve_%d" % (i), self)

            # decide location of energy reserve
            x = np.random.randint(0, self.grid.width)
            y = np.random.randint(0, self.grid.height)
            self.grid.place_agent(a, (x, y))

            self.schedule.add(a)

    def init_base(self):
        pos = (self.population_center_x, self.population_center_y)
        return self.grid.get_neighborhood(pos, True, radius=POP_SPREAD)

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()
        if self.schedule.steps % NEW_ENERGY_STEPS == 0:
            num_dead = len(self.ages)
            remaining = self.num_agents - num_dead
            if np.random.uniform() < NEW_ENERGY_PROB and remaining > 10:
                self.num_energy_resources += 1
                a = EnergyResource(
                    "energy_reserve_%d" % (self.num_energy_resources), self)

                # decide location of energy reserve
                x = np.random.randint(0, self.grid.width)
                y = np.random.randint(0, self.grid.height)
                self.grid.place_agent(a, (x, y))

                self.schedule.add(a)
示例#19
0
class CancerModel(Model):
    def xprint(self, *args):
        logger.info("CANCER MODEL:  " + " ".join(map(str, args)))

    def __init__(self, cure_agent_type, config):

        self.xprint("STARTING SIMULATION !!!")
        self.counter = 0
        self.decay_number = 0
        self.lifetime_counter = 0
        self.metastasis_score = 0
        eat_values = {CancerCell: 1, HealthyCell: -1, CancerStemCell: 5}
        assert (issubclass(cure_agent_type, CureAgent))

        agent_memory_range = config["Agent"]["memory_limit"]
        agent_memory_type = config["Agent"]["memory_type"]
        radoznalost = config["Agent"]["curiosity"]
        turn_off_modifiers = config["Tumor"]["turn_off_modifiers"]
        CC_mutation_probability = config["Tumor"]["mutation_probability"]
        is_tumor_growing = config["Tumor"]["is_growing"]
        tumor_movement_stopping_range = config["Tumor"][
            "movement_stopping_range"]
        steps_before_mutation = config["Model"]["steps_before_mutation"]
        self.SAMPLE_i = config["Model"]["sample_i"]

        self.cure_number = config["Model"]["NA_number"]
        self.probabilites_ranges = config["Agent"]["probabilities_limits"]
        self.modifier_fraction = config["Tumor"]["modifier_fraction"]
        self.mode = config["Simulation"]["mode"]
        fname = "xxx" if self.mode == "learning" else config["Simulation"][
            "fname"]

        self.MUTATION_PERCENTAGE = config["Model"]["mutation_percentage"]
        tumor_growth_probability = config["Tumor"]["growth_probability"]
        cancer_cell_number = config["Model"]["CC_number"]

        #DATA COLLECTION

        self.datacollector = DataCollector(
            model_reporters={
                "FitnessFunction": fitness_funkcija,
                "AverageSpeed": speed_avg,
                "AverageMemoryCapacity": memory_size_all_avg,
                "PopulationHeterogenity": population_heterogenity,
                "MutationAmount": mutation_amount,
                "CancerStemCell Number": CSC_number,
                "CSC Specialized Agents": CSC_specialized_agents,
                "CancerHeterogenity1": cancer_heterogenity_1,
                "CancerHeterogenity2": cancer_heterogenity_2,
                "CC_Number": CC_number,
                "HealthyCell_Number": HC_number,
                "MetastasisScore": "metastasis_score",
                "CancerSize": cancer_size,
                "TotalTumorResiliance": overall_cancer_resiliance,
                "TumorResiliance_Pi": cancer_resiliance_Pi,
                "TumorResiliance_Pd": cancer_resiliance_Pd,
                "TumorResiliance_Pa": cancer_resiliance_Pa,
                "TumorResiliance_Pk": cancer_resiliance_Pk,
                "TumorResiliance_Psd": cancer_resiliance_Psd,
                "NumberOfMutatedCells": mutated_CCs_num,
                "TumorCoverage": tumor_coverage,
                "AveragePd": average_Pd,
                "AveragePa": average_Pa,
                "AveragePi": average_Pi,
                "AveragePk": average_Pk,
                "AveragePsd": average_Psd,
                #      "PopulationClusters":cluster_counts
            },
            agent_reporters={
                "Pi": get_Pi,
                "Pa": get_Pa,
                "Pd": get_Pd,
                "speed": get_speed,
                "Psd": get_Psd,
                "Pk": get_Pk,
                "memory_size": get_memory_size,
                "type": get_agent_type
            })
        grid_size = math.ceil(math.sqrt(cancer_cell_number * 4))

        self.STEPS_BEFORE_MUTATION = steps_before_mutation
        self.grid = MultiGrid(grid_size, grid_size, False)
        self.NUM_OF_INJECTION_POINTS = config["Model"]["injection_points"]
        #        self.speeds = list(range(1,grid_size//2))
        self.speeds = [
            1
        ]  #TODO ovo mozda bolje? ne znam da li treba u config fajlu?
        poss = self.generate_cancer_cell_positions(grid_size,
                                                   cancer_cell_number)
        num_CSC = math.ceil(percentage(1, cancer_cell_number))
        pos_CSC = [self.random.choice(poss) for i in range(num_CSC)]

        #ACTIVATE SIMULATION
        self.schedule = RandomActivation(self)
        self.running = True

        #PLACE CANCER CELLS

        for i in range(cancer_cell_number):
            pos = poss[i]
            has_modifiers = False if ((i < (
                (1 - self.modifier_fraction) * cancer_cell_number))
                                      or turn_off_modifiers is True
                                      ) else True  #10 % will be with modifiers
            c = CancerStemCell("CANCER_STEM_CELL-"+str(uuid.uuid4()),self,value = eat_values[CancerStemCell],has_modifiers=has_modifiers,mutation_probability=CC_mutation_probability,grows=is_tumor_growing,growth_probability=tumor_growth_probability) \
                if pos in pos_CSC else CancerCell("CANCER_CELL-"+str(uuid.uuid4()),self,value=eat_values[CancerCell],has_modifiers=has_modifiers,mutation_probability=CC_mutation_probability,grows=is_tumor_growing,growth_probability=tumor_growth_probability)
            self.grid.place_agent(c, pos)
            self.schedule.add(c)

        #PLACE HEALTHY CELLS

        for (i, (contents, x, y)) in enumerate(self.grid.coord_iter()):
            nbrs = self.grid.get_neighborhood([x, y], moore=True)
            second_nbrs = []
            for nbr in nbrs:
                second_nbrs += self.grid.get_neighborhood(nbr, moore=True)
            nbrs = nbrs + second_nbrs
            nbr_contents = self.grid.get_cell_list_contents(nbrs)
            nbr_CCs = [
                nbr for nbr in nbr_contents if isinstance(nbr, CancerCell)
            ]

            if not contents and len(nbr_CCs) == 0:
                c = HealthyCell(uuid.uuid4(), self, eat_values[HealthyCell])
                self.grid.place_agent(c, (x, y))
                self.schedule.add(c)

        if self.mode == "simulation":
            self.duplicate_mutate_or_kill = self.simulation_mode_function
            self.decay_probability = 0.04  #MAGIC NUMBER
            self.read_nanoagents_from_file(
                fname=fname,
                cure_agent_type=cure_agent_type,
                tumor_movement_stopping_range=tumor_movement_stopping_range,
                agent_memory_range=agent_memory_range,
                radoznalost=radoznalost)

        elif self.mode == "learning":
            self.decay_probability = 0
            self.make_nanoagents_from_scratch(cure_agent_type, radoznalost,
                                              agent_memory_type,
                                              agent_memory_range,
                                              tumor_movement_stopping_range,
                                              grid_size)
        else:
            assert ("False")

    def get_random_positions_on_empty_cells(self):
        """Gets the N random currently empty positions on the grid"""
        #GETTING EMPTY POSITIONS (for placing nano agents)
        empty_cells = [(x, y) for (i, (contents, x,
                                       y)) in enumerate(self.grid.coord_iter())
                       if not contents]
        positions = [
            self.random.choice(empty_cells)
            for i in range(self.NUM_OF_INJECTION_POINTS)
        ]
        self.xprint("The 5 random empty positions are %s" % positions)
        return positions

    def inject_nanoagents(self):
        """Injects the nanoagents, they will be activated slowly after"""
        from itertools import cycle

        positions = cycle(self.get_random_positions_on_empty_cells())
        for a in self.agents:
            self.grid.place_agent(a, next(positions))
        self.agents_iterator = iter(self.agents)

    def activate_next_batch_of_agents(self):
        agents_to_be_placed_at_each_steps = round(len(self.agents) /
                                                  14)  #MAGIC NUMBER
        for i in range(agents_to_be_placed_at_each_steps):
            self.schedule.add(next(self.agents_iterator))

    def read_nanoagents_from_file(self, fname, cure_agent_type, radoznalost,
                                  agent_memory_range,
                                  tumor_movement_stopping_range):
        import pandas as pd
        self.xprint("Reading nanoagents from file")
        df = pd.read_csv(fname)
        self.agents = []

        for i, row in df.iterrows():
            a = cure_agent_type(
                uuid.uuid4(),
                self,
                speeds=self.speeds,
                radoznalost=radoznalost,
                memory_type=row.memory_size,
                memory_range=agent_memory_range,
                tumor_movement_stopping_range=tumor_movement_stopping_range,
                probabilities_ranges=self.probabilites_ranges)
            a.Pi = row.Pi
            a.Pa = row.Pa
            a.Pd = row.Pd
            a.memory_size = row.memory_size
            a.memorija = FixSizeOrderedDict(max=row.memory_size)
            a.tumor_movement_stopping_rate = row.tumor_movement_stopping_rate
            self.agents.append(a)

    def make_nanoagents_from_scratch(self, cure_agent_type, radoznalost,
                                     agent_memory_type, agent_memory_range,
                                     tumor_movement_stopping_range, grid_size):
        from itertools import cycle
        self.xprint("Making nanoagents from scratch")
        positions = cycle(self.get_random_positions_on_empty_cells())
        for i in range(self.cure_number):
            pos = next(positions)
            self.xprint(pos)
            a = cure_agent_type(
                uuid.uuid4(),
                self,
                speeds=self.speeds,
                radoznalost=radoznalost,
                memory_type=agent_memory_type,
                memory_range=agent_memory_range,
                tumor_movement_stopping_range=tumor_movement_stopping_range,
                probabilities_ranges=self.probabilites_ranges)
            self.grid.place_agent(a, pos)
            self.schedule.add(a)

    def simulation_mode_function(self):
        self.xprint("In simulation mode - not duplicating or mutating")
        return

    def generate_cancer_cell_positions(self, grid_size, cancer_cells_number):
        center = grid_size // 2
        poss = [(center, center)]
        for pos in poss:
            poss += [
                n for n in self.grid.get_neighborhood(
                    pos, moore=True, include_center=False) if n not in poss
            ]
            if len(set(poss)) >= cancer_cells_number:
                break
        poss = list(set(poss))
        return poss

    def duplicate_mutate_or_kill(self):
        if self.mode == "simulation":
            assert (False)
        koliko = math.ceil(
            percentage(self.MUTATION_PERCENTAGE, self.cure_number))
        cureagents = [
            c for c in self.schedule.agents if isinstance(c, CureAgent)
        ]
        sortirani = sorted(cureagents, key=lambda x: x.points, reverse=True)
        poslednji = sortirani[-koliko:]
        prvi = sortirani[:koliko]
        sredina = len(sortirani) // 2
        pocetak_sredine = sredina - (koliko // 2)
        kraj_sredine = sredina + (koliko // 2)
        srednji = sortirani[pocetak_sredine:kraj_sredine]
        self.mutate_agents(srednji)
        assert (len(prvi) == len(poslednji))
        self.remove_agents(poslednji)
        self.duplicate_agents(prvi)

    def mutate_agents(self, agents):
        self.xprint("Mutating middle agents")
        for a in agents:
            a.mutate()

    def remove_agents(self, agents):
        for a in agents:
            self.kill_cell(a)

    def duplicate_agents(self, agents):
        for a in agents:
            a_new = a.copy()
            self.grid.place_agent(a_new, (1, 1))
            self.schedule.add(a_new)

    def kill_cell(self, cell):
        self.grid.remove_agent(cell)
        self.schedule.remove(cell)

    def detach_stem_cell(self, cell):
        self.metastasis_score += 1
        self.kill_cell(cell)

    def kill_all_agents(self):
        agents = [a for a in self.schedule.agents if isinstance(a, CureAgent)]
        for a in agents:
            a.kill_self()

    def write_population_to_file(self, i):
        df = record_model_population(self)
        df.to_csv("./Populations/Population{}-step{}.csv".format(
            self.SAMPLE_i, i))

    def step(self):
        self.datacollector.collect(self)

        if self.mode == "simulation":
            self.simulation_step()

        self.write_population_to_file(self.counter)

        self.schedule.step()

        self.counter += 1
        self.lifetime_counter += 1

        if self.counter % self.STEPS_BEFORE_MUTATION == 0:
            #ovde ga stavljamo da izbegnemo da na nultom koraku uradi to
            self.duplicate_mutate_or_kill()

    def simulation_step(self):
        LIFETIME_OF_NANOAGENTS = 80
        REINJECTION_PERIOD = 100
        if self.lifetime_counter > LIFETIME_OF_NANOAGENTS:
            self.kill_all_agents()
        # if self.counter%(LIFETIME_OF_NANOAGENTS+REINJECTION_PERIOD)==0:
        #         #svakih 180 koraka se ubrizgavaju

        #     self.inject_nanoagents()
        #     self.lifetime_counter = 0
        agents_at_each_step = round(self.cure_number / 14)
        for i in range(agents_at_each_step):
            try:
                self.schedule.add(next(self.agents_iterator))
            except StopIteration:
                break
        agents = [a for a in self.schedule.agents if isinstance(a, CureAgent)]
        assert (len(agents) <= self.cure_number)
示例#20
0
class World(Model):
    def __init__(self, N, coop, e_prob, width=100, height=100):
        self.num_agents = N
        self.grid = MultiGrid(width, height, False)
        self.schedule = RandomActivation(self)
        self.running = True
        self.population_center_x = np.random.randint(POP_MARGIN, self.grid.width - POP_MARGIN)
        self.population_center_y = np.random.randint(POP_MARGIN, self.grid.height - POP_MARGIN)
        self.num_energy_resources = RESERVE_SIZE
        self.num_explorers = 0
        self.num_exploiters = 0
        self.datacollector = DataCollector(model_reporters={"Num_Explorer": "num_explorers","Num_Exploiter": "num_exploiters"})
        self.bases = self.init_base()
        self.ages = dict()
        self.memoryLens = dict() # This will store average memory length at death for agent
        self.expected_ages = []
        self.member_tracker = []
        self.energy_tracker = []
        self.decay_rates = self.init_decay_rates()

        # add social agents to the world
        for i in range(1, self.num_agents + 1):
            if np.random.uniform() <= EXPLORER_RATIO:
                # create a new explorer
                a = Explorer("explorer_%d" %(i), self, coop)
                self.num_explorers += 1
            else:
                # create a new exploiter
                a = Exploiter("exploiter_%d" %(i), self, coop, e_prob)
                self.num_exploiters += 1

            # keep society members confined at beginning
            x = np.random.randint(self.population_center_x - POP_SPREAD, self.population_center_x + POP_SPREAD)
            y = np.random.randint(self.population_center_y - POP_SPREAD, self.population_center_y + POP_SPREAD)
            self.grid.place_agent(a, (x, y))

            # add agent to scheduler
            self.schedule.add(a)
            self.expected_ages.append(a.energy / a.living_cost)

        # add energy reserves to the world
        for i in range(self.num_energy_resources):
            a = EnergyResource("energy_reserve_%d" %(i), self, self.decay_rates[i])

            # decide location of energy reserve
            x = np.random.randint(0, self.grid.width)
            y = np.random.randint(0, self.grid.height)
            self.grid.place_agent(a, (x, y))

            self.schedule.add(a)

    def init_base(self):
        pos = (self.population_center_x, self.population_center_y)
        return self.grid.get_neighborhood(pos, True, radius=POP_SPREAD)

    def init_decay_rates(self):
        decay_rates = list(np.random.uniform(-0.1, 0.02, self.num_energy_resources))
        np.random.shuffle(decay_rates)
        return decay_rates

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()
        self.member_tracker.append((self.num_explorers, self.num_exploiters))

        # keep track of total energy in world
        if self.schedule.time % 50 == 0:
            energies = [e.reserve for e in self.schedule.agents if isinstance(e, EnergyResource)]
            if len(energies) > 0:
                mean_energy = np.mean(energies)
            else:
                mean_energy = 0
            self.energy_tracker.append(mean_energy)

        # change location of energy resources every 500 steps randomly
        # and change decay_rate to opposite every 100 steps
        if self.schedule.time % 50 == 0:
            for e in self.schedule.agents:
                if isinstance(e, EnergyResource) and np.random.uniform() < 0.1:
                    # change location
                    e.decay_rate *= -1
                    if self.schedule.time % 500 == 0:
                        self.grid.remove_agent(e)
                        x = np.random.randint(0, self.grid.width)
                        y = np.random.randint(0, self.grid.height)
                        self.grid.place_agent(e, (x, y))
示例#21
0
class World(Model):
    def __init__(self, N, coop, e_prob, width=100, height=100):
        self.num_agents = N
        self.grid = MultiGrid(width, height, False)
        self.schedule = RandomActivation(self)
        self.running = True
        self.population_center_x = np.random.randint(
            POP_MARGIN, self.grid.width - POP_MARGIN)
        self.population_center_y = np.random.randint(
            POP_MARGIN, self.grid.height - POP_MARGIN)
        self.num_energy_resources = RESERVE_SIZE
        self.num_explorers = 0
        self.num_exploiters = 0
        self.datacollector = DataCollector(model_reporters={
            "Num_Explorer": "num_explorers",
            "Num_Exploiter": "num_exploiters"
        })
        self.bases = self.init_base()
        self.ages = []
        self.expected_ages = []
        self.member_tracker = []
        self.energy_tracker = []

        # add social agents to the world
        for i in range(1, self.num_agents + 1):
            if np.random.uniform() <= EXPLORER_RATIO:
                # create a new explorer
                a = Explorer("explorer_%d" % (i), self, coop)
                self.num_explorers += 1
            else:
                # create a new exploiter
                a = Exploiter("exploiter_%d" % (i), self, coop, e_prob)
                self.num_exploiters += 1

            # keep society members confined at beginning
            x = np.random.randint(self.population_center_x - POP_SPREAD,
                                  self.population_center_x + POP_SPREAD)
            y = np.random.randint(self.population_center_y - POP_SPREAD,
                                  self.population_center_y + POP_SPREAD)
            self.grid.place_agent(a, (x, y))

            # add agent to scheduler
            self.schedule.add(a)
            self.expected_ages.append(a.energy / a.living_cost)

        # add energy reserves to the world
        for i in range(self.num_energy_resources):
            a = EnergyResource("energy_reserve_%d" % (i), self)

            # decide location of energy reserve
            x = np.random.randint(0, self.grid.width)
            y = np.random.randint(0, self.grid.height)
            self.grid.place_agent(a, (x, y))

            self.schedule.add(a)

    def init_base(self):
        pos = (self.population_center_x, self.population_center_y)
        return self.grid.get_neighborhood(pos, True, radius=POP_SPREAD)

    def step(self):
        self.datacollector.collect(self)
        self.schedule.step()
        self.member_tracker.append((self.num_explorers, self.num_exploiters))

        # keep track of total energy in world
        energies = [
            e.reserve for e in self.schedule.agents
            if isinstance(e, EnergyResource)
        ]
        if len(energies) > 0:
            mean_energy = np.mean(energies)
        else:
            mean_energy = 0
        self.energy_tracker.append(mean_energy)

        # adjust decay rates to keep mean energy balanced in the world
        if mean_energy <= MEAN_RESERVE - 5 * STDDEV_ENERGY:
            for e in self.schedule.agents:
                if isinstance(e, EnergyResource) and np.random.uniform() < 0.1:
                    e.decay_rate -= DECAY_RATE_ADJUST

        elif mean_energy >= MEAN_RESERVE + 5 * STDDEV_RESERVE:
            for e in self.schedule.agents:
                if isinstance(e, EnergyResource) and np.random.uniform() < 0.1:
                    e.decay_rate += DECAY_RATE_ADJUST

        # change location of energy resources every 100 steps randomly
        if self.schedule.time % 100 == 0:
            for e in self.schedule.agents:
                if isinstance(e, EnergyResource) and np.random.uniform() < 0.1:
                    # change location
                    self.grid.remove_agent(e)
                    x = np.random.randint(0, self.grid.width)
                    y = np.random.randint(0, self.grid.height)
                    self.grid.place_agent(e, (x, y))
示例#22
0
class PsyRTSGame(Model):
    # id generator to track run number in batch run data
    id_gen = itertools.count(1)

    height = 20
    width = 20

    verbose = False  # Print-monitoring


    description = 'A model for simulating participants running the different experiments.'

    def __init__(self, height=20, width=20, visibility = False ,initial_competitors=0,
                 initial_explorers=1, initial_predators=0  ,
                 impactTotalVisibility =.3 , impactPartialVisibility = .35, impactParticipants = .0,
                 impactCompetitors= .0, impactPredators= .0 ):
        '''
        Create a new PsyRTS  model with the given parameters.

        Args
            initial_competitors: Number of units each participant knows
            initial_explorers: Number of sheep to start with
            initial_predators: Number of wolves to start with
            visibility : total or partial visibility
        '''
        super().__init__()
        self.uid = next(self.id_gen)
        self.fps = 0
        # Set parameters
        self.height = height
        self.width = width
        self.visibility = visibility
        self.initial_competitors = initial_competitors
        self.initial_explorers = initial_explorers
        self.initial_predators = initial_predators

        self.schedule = RandomActivationByBreed(self)
        self.grid = MultiGrid(self.height, self.width, torus=False)
        self.uncertainty = 0.0
        self.resources= 0
        self.resourcesParticipants =0
        self.resourcesCompetitors = 0

        self.visitedCells = 0
        self.stepsExploring = 0
        self.stepsExploiting = 0


#parameters model
        mu, sigma = impactTotalVisibility, 0.05  # mean and standard deviation
        tv = np.random.normal(mu, sigma)
        if  tv < 0:
            tv = 0
       # print( "Starting with tv " , tv)




        mu, sigma = impactPartialVisibility, 0.05  # mean and standard deviation
        pv = np.random.normal(mu, sigma)
        if  pv < 0:
            pv = 0


        #print("Starting with pv ", pv)

        self.impactTotalVisibility = tv
        self.impactPartialVisibility  = pv
        self.impactParticipants = impactParticipants
        self.impactCompetitors = impactCompetitors
        self.impactPredators = impactPredators

        self.TotalCells = next_moves = self.grid.get_neighborhood( (10,10), True, True, 11)
        locationsResources = [(4,3) , (16,3), (3,10) , (10,10),(17,10) , (16,17),(4,17)  ]

        locationCPCompetitor = (10, 3)
        locationCPParticipant = (10, 17)

        self.locationsExploitation =[]

        for loc in locationsResources:#resources
            self.locationsExploitation = self.locationsExploitation + self.grid.get_neighborhood(loc, True, True,1)

        #cfp
        self.locationsExploitation = self.locationsExploitation + self.grid.get_neighborhood(locationCPParticipant, True, True, 1)
        #print( "size grid exploiit " + str(len(self.locationsExploitation)))

        self.locationsExploration =  list(set(self.TotalCells) - set(self.locationsExploitation))
        #print("size grid explore " + str(len(self.locationsExploration)))
        locationsParticipants = [(10, 16), (13, 15), (7, 15), ( 8, 15), (12, 15)  ]
        locationsCompetitors = [(10, 4), (13, 5), (7, 5), ( 8, 5), (12, 5) ]
        locationsPredators = [(10, 10), (13, 10), (7, 10), ( 8, 10), (12, 10) ]

        self.datacollector = DataCollector(
            model_reporters={
                "Experiment_Synth": track_experiment,
                "Conditions": track_params,
                "Step": track_run,
                "Exploration": exploration ,
                "Exploitation": exploitation,
                "ResourcesRatio": resourcesRatio,
                "ProportionEE": proportionEE,
                "MapExplored": mapExplored,

                             })   #reporto a datos

        centralplaceparticipant = CentralPlace(self.next_id(), locationCPParticipant, self, True)
        self.grid.place_agent(centralplaceparticipant, locationCPParticipant)
        self.schedule.add(centralplaceparticipant)

        centralplacecompetitor = CentralPlace(self.next_id(), locationCPCompetitor, self, False)
        self.grid.place_agent(centralplacecompetitor, locationCPCompetitor)
        self.schedule.add(centralplacecompetitor)

        # Create competitor:
        for i in range(self.initial_competitors):
            sheep = Competitor(self.next_id(), locationsCompetitors[i], self, True, centralplacecompetitor)
            self.grid.place_agent(sheep, locationsCompetitors[i])
            self.schedule.add(sheep)

        # Create explorers:
        for i in range(self.initial_explorers):
            sheep = Participant(self.next_id(), locationsParticipants[i], self, True, centralplaceparticipant)
            self.grid.place_agent(sheep, locationsParticipants[i])
            self.schedule.add(sheep)

        # Create predators
        for i in range(self.initial_predators):
            wolf = Predator(self.next_id(), locationsPredators[i], self, True)
            self.grid.place_agent(wolf, locationsPredators[i])
            self.schedule.add(wolf)

        for pa in locationsResources:
             # randrange gives you an integral value
             irand = randrange(1, 11)
             #irand = 4
             #print("resource con valores {} ". format(  irand)  )
             self.resources = self.resources + irand
             patch = Resources(self.next_id(), pa, self, irand)
             self.grid.place_agent(patch, pa)
             self.schedule.add(patch)

        for x in range(0,20):
            for y in range(0, 20):
                breadcrumb = BreadCrumb(self.next_id(), (x,y), self)
                self.grid.place_agent(breadcrumb, (x,y))
                self.schedule.add(breadcrumb)

        self.running = True
        self.datacollector.collect(self)


    def updateUncertainty(self):

        # information que gana por conocer el ambiente
        #participantExploration = (number_visited(self, True) +number_visited(self, False))/400
        participantExploration = mapExplored(self)


        uncertaintyVisibility = 0


        # if self.model.visibility :
        #     multitaskingFriction = (1 - self.model.impactParticipants ) ** self.model.initial_explorers
        # else:


        if self.visibility:
            uncertaintyVisibility  =   self.impactTotalVisibility
            self.uncertainty = uncertaintyVisibility
        else:
            uncertaintyVisibility  =  self.impactPartialVisibility
            self.uncertainty = uncertaintyVisibility* (1-participantExploration)



        if self.uncertainty <0 :
            self.uncertainty = 0
        #print("explored map {} uncertainty  in the environment {} ".format ( participantExploration, self.uncertainty ))




    def step(self):

        self.datacollector.collect(self)
        self.schedule.step()
        self.updateUncertainty()
        # collect data

        participantsAlive = self.schedule.get_breed_count(Participant)
        if participantsAlive <=0:
            print("Stop Participants dead")
            self.running = False

        if self.resourcesCompetitors +self.resourcesParticipants == self.resources:
            print("Stop No More Resources")
            self.running = False

        if self.schedule.steps>150:
            print("toomany steps")
            self.running = False

    def run_model(self, step_count=150):
        for i in range(step_count):
            self.step()