class FoodSupplyModel(Model):
    def __init__(self, fridgesCount, width, height):
        self.fridgesCount = fridgesCount
        self.running = True
        self.grid = MultiGrid(height, width, torus=False)
        self.schedule = DayScheduler(self)
        self.productTypes = ["A", "B", "C"]
        self.fridges = []
        self.isSupplyInProgress = False
        self.orders = []

        def randomFreeCoordinates():
            while True:
                x = random.randrange(self.grid.width)
                y = random.randrange(self.grid.height)
                if self.grid.is_cell_empty((x, y)):
                    return (x, y)

        def balancedInitialContents(capacity):
            amount = capacity / len(self.productTypes)
            return {product: amount for product in self.productTypes}

        for i in range(self.fridgesCount):
            capacity = 30
            dailyUsages = [{"A": 3, "B": 2, "C": 1}, {"A": 4, "B": 1, "C": 2}, {"A": 2, "B": 2, "C": 3}]
            fridge = FridgeAgent(i, capacity, dailyUsages[i % 3], balancedInitialContents(capacity))
            self.fridges.append(fridge)
            self.grid.place_agent(fridge, randomFreeCoordinates())

        self.supplier = SupplierAgent(1000)

        self.truck = TruckAgent(0, capacity=100)
        self.schedule.add(self.truck)
        # self.grid.place_agent(self.truck, randomFreeCoordinates())
        self.grid.place_agent(self.truck, (0,0))


    def nextDay(self):
        for fridge in self.fridges:
            fridge.step(self)
        self.supplier.step(self)
        self.orders = []
        self.isSupplyInProgress = True


    def step(self):
        self.schedule.step()
    
    def run_model(self, n):
        for i in range(n):
            self.step()
Beispiel #2
0
class CommuteModel(Model):
    """This agent-based model seeks to demonstrate the effect of spatial
    inequality on the way agents commute."""
    def __init__(self, N, initial_wealth, cost_per_pixel, pt_cost,
                 cost_to_move, pt_aval, width, height, city_pos):
        self.num_agents = N
        self.grid = MultiGrid(width, height, True)
        self.schedule = RandomActivation(self)

        # place commute agents
        for unique_id in range(self.num_agents):
            x = random.randrange(self.grid.width)
            y = random.randrange(self.grid.height)
            pos = (x, y)
            if self.grid.is_cell_empty(pos):
                a = CommuteAgent(unique_id, self, pos, city_pos,
                                 initial_wealth, cost_per_pixel, pt_cost,
                                 cost_to_move, pt_aval)
                self.schedule.add(a)
                self.grid.place_agent(a, pos)

        self.grid.place_agent(CityAgent(city_pos), city_pos)
        self.ginicollector = DataCollector(
            model_reporters={"Gini": compute_gini},
            agent_reporters={"Wealth": "wealth"})
        self.avgcollector = DataCollector(
            model_reporters={"Average Income": compute_avg_wealth},
            agent_reporters={"Wealth": "wealth"})
        self.ginicollector.collect(self)
        self.avgcollector.collect(self)

        self.running = True

    def step(self):
        self.schedule.step()
        # collect data
        self.ginicollector.collect(self)
        self.avgcollector.collect(self)

    def run_model(self, n):
        for i in range(n):
            self.step()
Beispiel #3
0
class Themepark(Model):
    def __init__(self, N_attr, N_cust, width, height, strategy, theme,
                 max_time, weight, adaptive):
        self.max_time = max_time
        self.N_attr = N_attr
        self.penalty_per = PENALTY_PERCENTAGE
        self.weight = weight
        self.adaptive = adaptive
        self.strategies = STRATEGIES
        self.x_list, self.y_list, self.positions = xlist, ylist, positions
        self.x_list, self.y_list, self.positions = get_attraction_coordinates(
            WIDTH, HEIGHT, self.N_attr, theme)
        self.happinesses = []
        self.path_coordinates = get_coordinates(WIDTH, HEIGHT, NUM_OBSTACLES,
                                                self.N_attr, theme)
        self.N_cust = N_cust  # num of customer agents
        self.total_steps = 0
        self.cust_ids = N_cust
        self.strategy = strategy
        self.grid = MultiGrid(width, height, torus=False)
        self.schedule = BaseScheduler(self)
        self.schedule_Attraction = BaseScheduler(self)
        self.schedule_Customer = BaseScheduler(self)
        self.totalTOTAL = 0  #TODO: DEZE NAAM VERANDEREN
        self.attractions = self.make_attractions()
        self.attraction_history = self.make_attr_hist()
        self.park_score = []
        self.data_dict = {}
        self.hist_random_strat = []
        self.hist_close_strat = []
        self.all_rides_list = []
        self.strategy_composition = self.make_strategy_composition()
        self.customers = self.add_customers(self.N_cust)
        self.monitor = Monitor(self.max_time, self.N_attr, self.positions)
        self.running = True

        # TODO: ALS HET GOED IS KUNNEN AL DEZE INITS WEG, MAAR DIT MOETEN WE WEL NOG EVEN DUBBEL CHECKEN
        # --> dit is gecheckt op het runnen van main_cluster_random_noise
        # self.theme = theme
        # self.starting_positions = [[int((WIDTH/2)-1), 0], [int(WIDTH/2), 0], [int((WIDTH/2)+1), 0]]
        # self.width = width
        # self.height = height
        # self.data = []
        # self.data_customers = []
        # self.memory = 5
        # self.customer_score = []
        # self.only_random = False
        # self.total_waited_time = 0

        # Initialize dictionary of attractions
        for attraction in self.get_attractions():
            self.data_dict[attraction.unique_id] = ({
                "id": attraction.unique_id,
                "length": attraction.attraction_duration,
                "waiting_list": []
            })

        # TODO ADD COMMENT (SNAP NIET WAT DE DATACOLLECTOR IS)
        if len(self.strategies) == 6:
            self.datacollector = DataCollector({
                "Random":
                lambda m: self.strategy_counter(self.strategies[0]),
                "0.00":
                lambda m: self.strategy_counter(self.strategies[1]),
                "0.25":
                lambda m: self.strategy_counter(self.strategies[2]),
                "0.50":
                lambda m: self.strategy_counter(self.strategies[3]),
                "0.75":
                lambda m: self.strategy_counter(self.strategies[4]),
                "1.00":
                lambda m: self.strategy_counter(self.strategies[5]),
            })
        else:
            self.datacollector = DataCollector({
                "0.00":
                lambda m: self.strategy_counter(self.strategies[0]),
                "0.25":
                lambda m: self.strategy_counter(self.strategies[1]),
                "0.50":
                lambda m: self.strategy_counter(self.strategies[2]),
                "0.75":
                lambda m: self.strategy_counter(self.strategies[3]),
                "1.00":
                lambda m: self.strategy_counter(self.strategies[4]),
            })

        self.datacollector2 = DataCollector(
            {"score": lambda m: self.make_score()})

    def make_score(self):
        """
        Get the efficiency score
        """
        ideal = {}
        cust_in_row = 0
        for i in range(len(self.get_attractions())):
            ideal[i] = self.N_cust / self.N_attr
            cust_in_row += self.get_attractions()[i].N_current_cust

        tot_difference = 0
        for i in range(len(self.get_attractions())):

            difference = abs(cust_in_row / self.N_attr -
                             self.get_attractions()[i].N_current_cust)
            tot_difference += difference

        fraction_not_right = (tot_difference / self.N_cust)
        return abs(1 - (fraction_not_right)) * cust_in_row / self.N_cust

    def make_attr_hist(self):
        """
        Initialize a dictionary in which the history of the attractions can be
        added in.
        """
        attraction_history = {}
        for attraction in self.get_attractions():
            attraction_history[attraction] = [0] * (self.max_time + 1)

        return attraction_history

    def strategy_counter(self, strategy):
        """
        Count how many customers of different strategies are at the attractions
        """
        counter_total = {}

        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(attraction_pos,
                                             moore=True,
                                             radius=0,
                                             include_center=True)

            counter = 0
            for agent in self.customers:
                if agent.weight == strategy:
                    counter += 1

        return counter

    def make_strategy_composition(self):
        """
        TODO: ANNEMIJN KAN JIJ HIER COMMENTS BIJ DOEN? + RANDOM_TEST_4 WEGHALEN
        """
        if self.strategy == "Random_test_4":
            self.strategies = ["Random_test_4", 0.0, 0.25, 0.50, 0.75, 1.0]
            dict = {
                self.strategies[0]: 1 / 6,
                self.strategies[1]: 0.20,
                self.strategies[2]: 0.20,
                self.strategies[3]: 0.20,
                self.strategies[4]: 0.20,
                self.strategies[5]: 0.20
            }

            composition_list = []
            for i in range(len(self.strategies)):
                if i == 0:
                    dict[self.strategies[i]] = FRACTION_RANDOM
                    continue
                else:
                    composition_list.append(random.randint(0, 100))
            sum_comp = sum(composition_list)

            sum_comp = sum_comp - sum_comp * FRACTION_RANDOM
            for i in range(len(self.strategies)):
                if i == 0:
                    continue
                else:
                    dict[self.strategies[i]] = composition_list[i -
                                                                1] / sum_comp

        else:
            dict = {
                self.strategies[0]: 0.20,
                self.strategies[1]: 0.20,
                self.strategies[2]: 0.20,
                self.strategies[3]: 0.20,
                self.strategies[4]: 0.20
            }

            composition_list = []
            for i in range(len(self.strategies)):

                composition_list.append(random.randint(0, 100))

            sum_comp = sum(composition_list)

            sum_comp = sum_comp
            for i in range(len(self.strategies)):

                dict[self.strategies[i]] = composition_list[i - 1] / sum_comp

        return dict

    def make_attractions(self):
        """
        Initialize attractions on fixed position.
        """

        attractions = {}
        for i in range(self.N_attr):

            pos = (self.x_list[i], self.y_list[i])
            if self.grid.is_cell_empty(pos):

                name = str(i)
                a = Attraction(i, self, pos, name, self.N_cust, self.weight)
                attractions[i] = a

                self.schedule_Attraction.add(a)
                self.grid.place_agent(a, pos)
        return attractions

    def get_attractions(self):
        """
        Get a list with all attractions.
        """
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)

        attractions = []
        for agent in agents:
            if type(agent) == Attraction:
                attractions.append(agent)

        return attractions

    def calculate_people(self):
        """
        Calculate how many customers are in which attraction.
        """

        counter_total = {}

        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(attraction_pos,
                                             moore=True,
                                             radius=0,
                                             include_center=True)

            counter = 0
            for agent in agents:
                if type(agent) is Customer:
                    counter += 1
                else:
                    attraction = agent

            attraction.N_current_cust = counter
            counter_total[attraction.unique_id] = counter

        return list(counter_total.values())

    def add_customers(self, N_cust, added=False):
        """
        Initialize customers on random positions.
        """

        weights_list = []
        if self.adaptive is True:

            for j in self.strategy_composition.keys():
                for i in range(round(N_cust * self.strategy_composition[j])):
                    weights_list.append(j)

            if len(weights_list) < self.N_cust:
                rand = random.choice(self.strategies)
                weights_list.append(rand)
            elif len(weights_list) > self.N_cust:
                rand = random.choice(weights_list)
                weights_list.remove(rand)

        else:

            # if the strategy is not random add weights to weights_list
            if self.strategy is not "Random":
                for i in range(round(N_cust)):
                    weights_list.append(self.weight)

        cust_list = []
        for i in range(N_cust):

            pos_temp = [
                random.randint(0, WIDTH - 1),
                random.randint(0, HEIGHT - 1)
            ]
            rand_x, rand_y = pos_temp[0], pos_temp[1]

            pos = (rand_x, rand_y)

            if added is True:
                i = self.cust_ids
            if self.strategy == "Random_test_4":
                if weights_list[i] == "Random_test_4":
                    strategy = "Random_test_4"
                else:
                    strategy = "Closest_by"
            else:
                strategy = self.strategy

            # Set weight
            if weights_list == []:
                weight = None
            else:
                weight = weights_list[i]

            # Initialize customer and add customer to the model
            a = Customer(i, self, pos, self.x_list, self.y_list,
                         self.positions, strategy, weight, self.adaptive)
            self.schedule_Customer.add(a)
            self.grid.place_agent(a, pos)
            cust_list.append(a)

        return cust_list

    def calc_waiting_time(self):
        """
        Calculate the waitingtime per attraction
        """

        counter_total = {}

        attractions = self.get_attractions()
        for attraction in attractions:

            counter_total[
                attraction.unique_id] = attraction.current_waitingtime

        return counter_total

    def calculate_people_sorted(self):
        """
        Calculate how many customers are in which attraction.
        Returns a SORTED LIST.
        For example: indexes = [3, 2, 5, 1, 4]
        indicates that attraction3 has the least people waiting.
        """

        counter_total = {}

        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(attraction_pos,
                                             moore=True,
                                             radius=0,
                                             include_center=True)

            counter = 0
            for agent in agents:
                if type(agent) is Customer:
                    counter += 1
                else:
                    attraction = agent

            attraction.N_current_cust = counter
            self.attraction_history[attraction][self.totalTOTAL] = counter
            counter_total[attraction.unique_id] = counter

        return counter_total

    def make_route(self):
        """
        Draw coordinates of a possible path.
        """

        for i in range(len(self.path_coordinates)):
            pos = self.path_coordinates[i]

            if pos not in self.positions:

                # Create path agent
                path = Route(i, self, pos)
                self.schedule.add(path)

                self.grid.place_agent(path, pos)

    # TODO: THEMEPARK SCORE GEBRUIKEN WE NIET MEER, DIT ALLEMAAL VERWIJDEREN OVERAL?
    def get_themepark_score(self):
        """
        Get score of a themepark based on:
            - A total of all waitingtimes for every customer
            - The total number of rides taken
        """
        attractions = self.get_attractions()
        total_wait, total_rides = 0, 0
        for attraction in attractions:
            total_wait += attraction.current_waitingtime

            if attraction.current_a is not None:
                total_rides += 1

        if total_rides == 0:
            return total_rides

        return (total_wait / total_rides)

    def get_strategy_history(self):
        """
        Update history with how many customers chose which strategy.
        """

        customers = self.get_customers()
        randomstrat, closebystrat = 0, 0

        for customer in customers:
            if customer.strategy == "Random" or customer.strategy == "Random_test_4":
                randomstrat += 1
            elif customer.strategy == "Closest_by":
                closebystrat += 1

        self.hist_random_strat.append(randomstrat)
        self.hist_close_strat.append(closebystrat)

    def get_customers(self):
        """
        Returns a list of all the customers in the themepark.
        """
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)

        customers = []

        # Add customers to list
        for agent in agents:
            if type(agent) == Customer:
                customers.append(agent)

        return customers

    def get_data_customers(self):
        """
        Return dictionary with data of customers.
        """

        data = {}
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)

        for agent in agents:
            if type(agent) is Customer:
                data[agent.unique_id] = {
                    "totalwaited": agent.total_ever_waited,
                    "visited_attractions": agent.nmbr_attractions,
                    "strategy": agent.strategy,
                    "swapped_strat": agent.strategy_swap_hist
                }

        return data

# TODO: NET ALS THEMEPARK SCORE GEBRUIKEN WE DIT NEIT MEER TOCH????

    def calc_hapiness(self):
        """
        Calculate mean hapiness of all customers, based on:

        - How many rides were taken
        - Number of times in the same attraction
        - Total waiting time
        """
        customers = self.get_customers()

        scores = []

        for customer in customers:
            history = customer.history
            values = list(history.values())
            total_rides = sum(values)

            if total_rides != 0:
                scores.append(total_rides / self.N_attr -
                              self.totalTOTAL / customer.total_ever_waited)
            else:
                return None

        scores = np.interp(scores, (min(scores), max(scores)), (1, 10))

        return np.mean(scores)

    def get_history_list(self):
        """
        Create a list with the history of the customers.
        """

        customers = self.get_customers()
        histories = {}

        for customer in customers:
            history = customer.history
            values = list(history.values())
            histories[customer.unique_id] = values
        return histories

    def final(self):
        """
        End run and return data.
        """

        # Create list with at every time step the amount of attractions that are active
        attractions = self.get_attractions()
        self.all_rides_list = [0] * len(attractions[0].in_attraction_list)
        for attraction in attractions:
            for i in range(len(attraction.in_attraction_list)):
                self.all_rides_list[i] += attraction.in_attraction_list[i]

        # Change the all_rides_list into fractions
        for i in range(len(self.all_rides_list)):
            self.all_rides_list[i] /= self.N_attr

        # Initialize history list and get agents
        hist_list = []
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)

        # Save history of all customers
        cust_data = self.get_data_customers()
        for agent in agents:
            if type(agent) is Customer:
                sum_attr = sum(agent.history.values())
                if sum_attr > 0:
                    hist_list.append(agent.strategy_swap_hist)
                else:
                    hist_list.append(agent.strategy_swap_hist)

        histories = self.get_history_list()

        # Save data
        try:
            pickle.dump(self.datacollector.get_model_vars_dataframe(),
                        open("../data/strategy_history.p", 'wb'))
            pickle.dump(self.datacollector2.get_model_vars_dataframe(),
                        open("../data/eff_score_history.p", 'wb'))
            pickle.dump(cust_data, open("../data/customers.p", 'wb'))
            pickle.dump(self.park_score[-1], open("../data/park_score.p",
                                                  "wb"))
            pickle.dump(self.happinesses, open("../data/hapiness.p", "wb"))
            pickle.dump(histories, open("../data/cust_history.p", 'wb'))
        except:
            pickle.dump(self.datacollector.get_model_vars_dataframe(),
                        open("data/strategy_history.p", 'wb'))
            pickle.dump(self.datacollector2.get_model_vars_dataframe(),
                        open("data/eff_score_history.p", 'wb'))
            pickle.dump(cust_data, open("data/customers.p", 'wb'))
            pickle.dump(self.park_score[-1], open("data/park_score.p", "wb"))
            pickle.dump(self.happinesses, open("data/hapiness.p", "wb"))
            pickle.dump(histories, open("data/cust_history.p", 'wb'))

        try:
            pickle.dump(self.all_rides_list, open("../data/all_rides.p", "wb"))
        except:
            pickle.dump(self.all_rides_list, open("data/all_rides.p", "wb"))

        print()
        print("RUN HAS ENDED")
        print()

    def save_data(self):
        """
        Save data of all attractions and customers.
        """
        # Get info
        waitinglines = self.calc_waiting_time()

        for i in range(len(self.attractions)):
            self.data_dict[i]["waiting_list"].append(waitinglines.get(i))

        self.park_score.append(sum(waitinglines.values()))
        self.happinesses.append(self.calc_hapiness())

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

        # Take a step if max steps is not reached
        if self.totalTOTAL < self.max_time:
            self.totalTOTAL += 1
            self.schedule.step()
            self.datacollector.collect(self)
            self.datacollector2.collect(self)

            self.schedule_Attraction.step()
            self.schedule_Customer.step()

            self.total_steps += 1

            self.save_data()
            self.get_strategy_history()

        # Stop simulation
        else:
            for key in self.attraction_history.keys():
                y = self.attraction_history[key]
                x = list(range(0, self.max_time))

            self.final()
Beispiel #4
0
class EV_Model(Model):
    def __init__(self,
                 N=50,
                 width=20,
                 height=20,
                 n_poles=10,
                 vision=10,
                 grid_positions="random",
                 initial_bravery=10,
                 battery_size=25,
                 open_grid=True):
        self.battery_size = battery_size
        self.initial_bravery = initial_bravery
        self.num_agents = N
        self.open = open_grid
        if self.open == True:
            self.grid = MultiGrid(width, height, True)
        else:
            self.grid = MultiGrid(width, height, False)
        self.schedule = RandomActivationByBreed(self)
        self.vision = vision
        self.grid_size = width

        # adds CPs based on the input grid position
        if grid_positions == "circle":

            center_grid = (int(width / 2), int(height / 2))
            circle_list = PointsInCircum(round(self.grid_size / 4),
                                         int(N * n_poles))
            for i, coord in enumerate(circle_list):
                new_coord = (coord[0] + center_grid[0],
                             coord[1] + center_grid[1])

                charge_pole = Charge_pole(i, new_coord, self)
                self.grid.place_agent(charge_pole, new_coord)
                self.schedule.add(charge_pole)

        elif grid_positions == "big circle":
            center_grid = (int(width / 2), int(height / 2))
            circle_list = PointsInCircum(round(self.grid_size / 2 - 1),
                                         int(N * n_poles))
            for i, coord in enumerate(circle_list):
                new_coord = (coord[0] + center_grid[0],
                             coord[1] + center_grid[1])

                charge_pole = Charge_pole(i, new_coord, self)
                self.grid.place_agent(charge_pole, new_coord)
                self.schedule.add(charge_pole)

        elif grid_positions == "random":
            for i in range(int(N * n_poles)):
                # Add the agent to a random grid cell
                empty_coord = self.grid.find_empty()
                charge_pole = Charge_pole(i, empty_coord, self)
                self.grid.place_agent(charge_pole, empty_coord)
                self.schedule.add(charge_pole)

        elif grid_positions == "LHS":
            coord_list = np.round(
                lhs(2, samples=int(N * n_poles), criterion="m") *
                (self.grid_size - 1))
            for i in range(int(N * n_poles)):
                coord = tuple((int(coord_list[i][0]), int(coord_list[i][1])))
                if self.grid.is_cell_empty(coord):
                    charge_pole = Charge_pole(i, coord, self)
                    self.grid.place_agent(charge_pole, coord)
                else:
                    empty_coord = self.grid.find_empty()
                    charge_pole = Charge_pole(i, empty_coord, self)
                    self.grid.place_agent(charge_pole, empty_coord)
                self.schedule.add(charge_pole)

        # Create EV agents
        for i in range(self.num_agents):

            # Add the agent to a random empty grid cell
            home_pos = self.grid.find_empty()
            work_pos = self.grid.find_empty()

            EV = EV_Agent(i, self, self.vision, home_pos, work_pos,
                          initial_bravery, battery_size)
            self.schedule.add(EV)

            self.grid.place_agent(EV, home_pos)
            self.totalEVs = i

        self.datacollector = DataCollector(
            agent_reporters={},
            model_reporters={
                "Avg_Battery": mean_all_battery,
                "Usage": avg_usage,
                "High_Usage": high_usage,
                "Low_Usage": low_usage,
                "Total_attempts": totalAttempts,
                "Percentage_failed": percentageFailed,
                "Average_lifespan": averageLifespan,
                "lower25": lowest_25_percent,
                "timeInState": time_in_state,
                "unique_battery": specific_battery,
                "Num_agents": count_agents,
                "EVs": lambda m: m.schedule.get_breed_count(EV_Agent)
            })

        self.running = True
        self.current_EVs = self.totalEVs

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

    def stableAgents(self):
        while self.current_EVs < self.num_agents:
            home_pos = self.grid.find_empty()
            work_pos = self.grid.find_empty()
            EV = EV_Agent(self.totalEVs, self, self.vision, home_pos, work_pos,
                          self.initial_bravery, self.battery_size)
            self.grid.place_agent(EV, home_pos)
            self.schedule.add(EV)
            self.totalEVs += 1
            self.current_EVs += 1
Beispiel #5
0
class Battlefield(Model):
    """
    Główna klasa modelu w której wszystko sie dzieje

    Arg:
    width (int): szerokość planszy
    height (int): wysokość planszy
    """
    def __init__(self, width, height):
        super().__init__()

        self.width = width
        self.height = height
        self.survived_steps_blue = 0
        self.survived_steps_red = 0
        self.grid = MultiGrid(width, height, False)
        self.schedule = RandomActivation(self)
        self.running = True
        self.spawn_from_file()
        self.initial_red_count = self.count_units("#ff0000")
        self.initial_blue_count = self.count_units("#00aab2")
        self.tmp = self.count_cost()
        self.starting_cost_blue = self.tmp[1][0]
        self.starting_cost_red = self.tmp[0][0]

        self.datacollector = DataCollector(
            model_reporters={
                "Suma przeżytych rund każdej jednostki do kosztu całej armii - czerwoni":
                compute_cost_red,
                "Suma przeżytych rund każdej jednostki do kosztu całej armii - niebiescy":
                compute_cost_blue
            })

        self.datacollector_health = DataCollector(
            model_reporters={
                "Punkty życia armii czerwonej": compute_health_red,
                "Punkty życia armii niebieskiej": compute_health_blue
            })

    def spawn_from_file(self):
        units = read_from_file('Data/army.txt')
        """
        Wkłada jednostki z listy na planszę
        :return:
        """

        for element in units:
            if element[2] == 'I':
                a = Infantry(self.current_id, self)
            elif element[2] == 'A':
                a = Archers(self.current_id, self)
            elif element[2] == 'C':
                a = Cavalry(self.current_id, self)
            elif element[2] == 'R':
                a = Rock(self.current_id, self)
            self.next_id()
            a.set_color(element[3])
            a.timer = random.choice([True, False])
            self.schedule.add(a)

            if self.grid.is_cell_empty((element[0], element[1])):
                self.grid.place_agent(a, (element[0], element[1]))
            else:
                print("Unable to place unit on that cell")

    def step(self):
        """
        Uruchamia losowo wszystkich agentów
        :return:
        """
        self.schedule.step()
        self.is_simulation_over()
        self.datacollector.collect(self)
        self.datacollector_health.collect(self)

    def count_cost(self):
        """
        Funkcja do liczenia kosztów armii
        :return: zwraca tablice krotek (koszt,kolor)
        """
        costs = []
        temp = [0, '#ff0000', 0, '#00aab2']
        for a in self.schedule.agents:
            if a.color == "#ff0000":
                temp[0] += a.cost
            elif a.color == "#00aab2":
                temp[2] += a.cost
        costs.append((temp[0], temp[1]))
        costs.append((temp[2], temp[3]))
        return costs

    def count_units(self, color):
        """
        Zlicza ilość jednostek danego koloru
        :param color: Kolor jednostek jakie ma liczyć
        :return: zwraca ilość jednostek
        """
        counter = 0
        for a in self.schedule.agents:
            if a.color == color:
                counter += 1
        return counter

    def is_simulation_over(self):
        """
        Sprawdza czy symulacja sie zakończyła
        :return:
        """
        temp = self.count_cost()
        if temp[0][0] == 0 or temp[1][0] == 0:
            self.running = False
            to_file(
                self.write_results(), "Data/results" + str(self.width) + "x" +
                str(self.height) + ".txt")

    def write_results(self):
        string = ""
        if self.who_won() == 1:
            string += "Blue won with "
            string += str(self.count_units("#00aab2"))
            string += " units left."
            string += "  Starting with || Blue units "
            string += str(self.initial_blue_count)
            string += " - "
            string += str(self.initial_red_count)
            string += " Red units\n"
        else:
            string += "Red won with "
            string += str(self.count_units("#ff0000"))
            string += " units left"
            string += "  Starting with || Blue units "
            string += str(self.initial_blue_count)
            string += " - "
            string += str(self.initial_red_count)
            string += " Red units\n"
        return string

    def who_won(self):
        """
        Sprawdza kto wygrał
        :return: zwraca 1 kiedy wygrali niebiescy i 0 jak wygralki czerwoni
        """
        temp = self.count_cost()
        if temp[0][0] > 0:
            return 0
        else:
            return 1
Beispiel #6
0
class SquashBee(Model):
    def __init__(self,
                 height=50,
                 width=50,
                 time=0,
                 density_bee=50,
                 density_gender_bee=50,
                 gain_polline_raccolto=40,
                 density_zucca=50,
                 prob_accoppiamento=50,
                 offsetX=5,
                 offsetY=5):

        self.height = height
        self.width = width
        self.time = 200
        self.density_bee = density_bee
        self.density_gender_bee = density_gender_bee
        self.gain_polline_raccolto = gain_polline_raccolto
        self.density_zucca = density_zucca
        self.prob_accoppiamento = prob_accoppiamento
        self.offsetX = offsetX
        self.offsetY = offsetY
        self.anno = 1

        self.schedule = RandomActivation(self)
        self.grid = MultiGrid(self.width, self.height, torus=True)

        self.datacollector = DataCollector({
            "Zucche_fiori":
            lambda m: self.count_type(m, "Flower"),
            "Zucche":
            lambda m: self.count_type(m, "Zucca"),
            "Seed":
            lambda m: self.count_type(m, "Seed"),
            "Api":
            lambda m: self.count_type(m, "Bee"),
            "Larve":
            lambda m: self.count_type(m, "Bee_son")
        })

        # metto le api nella griglia
        for i in range(self.density_bee):
            x = self.random.randrange(2, 33)
            y = self.random.randrange(2, 33)
            new_bee = Bee((x, y), self, self.density_gender_bee,
                          self.gain_polline_raccolto, 120)
            self.grid.place_agent(new_bee, (x, y))
            self.schedule.add(new_bee)

        # metto i fiori delle zucche nella griglia
        for i in range(self.density_zucca):
            x = self.random.randrange(5, 30)
            y = self.random.randrange(5, 30)
            new_zucca = Zucca_flower((x, y), self, self.prob_accoppiamento, 45)
            self.grid._place_agent((x, y), new_zucca)
            self.schedule.add(new_zucca)

        # metto i fiori nella griglia
        for i in range(150):
            x = self.random.randrange(self.height)
            y = self.random.randrange(self.width)
            new_f = flower((x, y), self)
            self.grid._place_agent((x, y), new_f)
            self.schedule.add(new_f)

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

    def step(self):
        self.time += 1

        #fioritura primaverile
        if self.time == 90:
            # metto i fiori nella griglia
            for i in range(150):
                x = self.random.randrange(self.height)
                y = self.random.randrange(self.width)
                if (self.grid.is_cell_empty((x, y))):
                    new_f = flower((x, y), self)
                    self.grid._place_agent((x, y), new_f)
                    self.schedule.add(new_f)

        # semina ogni anno
        if self.time == 160:
            # metto i semi delle zucche nella griglia
            if self.anno % 2 == 0:
                for i in range(self.density_zucca):
                    x = self.random.randrange(5 + self.offsetX,
                                              30 + self.offsetX)
                    y = self.random.randrange(5 + self.offsetY,
                                              30 + self.offsetY)
                    if (self.grid.is_cell_empty((x, y))):
                        new_seme = Zucca_seed((x, y), self)
                        self.grid._place_agent((x, y), new_seme)
                        self.schedule.add(new_seme)
            if self.anno % 2 == 1:
                for i in range(self.density_zucca):
                    x = self.random.randrange(5, 30)
                    y = self.random.randrange(5, 30)
                    if (self.grid.is_cell_empty((x, y))):
                        new_seme = Zucca_seed((x, y), self)
                        self.grid._place_agent((x, y), new_seme)
                        self.schedule.add(new_seme)

        # reset anno
        if self.time == 360:
            self.time = 0
            self.anno += 1

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

    @staticmethod
    def count_type(model, agent_type):
        """
        Helper method to count trees in a given condition in a given model.
        """
        count = 0
        for agent in model.schedule.agents:
            if agent.type_agent == agent_type:
                count += 1
        return count
Beispiel #7
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
Beispiel #8
0
class Themepark(Model):
    def __init__(self, N_attr, N_cust, width, height, strategy, theme, max_time, weight, adaptive):
        self.theme = theme
        self.max_time = max_time
        self.N_attr = N_attr
        self.penalty_per = PENALTY_PERCENTAGE
        self.weight = weight
        self.adaptive = adaptive
        self.strategies = STRATEGIES
        self.x_list, self.y_list, self.positions = xlist, ylist, positions
        self.x_list, self.y_list, self.positions = get_attraction_coordinates(WIDTH, HEIGHT, self.N_attr, theme)
        self.happinesses = []
        self.starting_positions = [[int((WIDTH/2)-1), 0], [int(WIDTH/2), 0], [int((WIDTH/2)+1), 0]]
        self.path_coordinates = get_coordinates(WIDTH, HEIGHT, NUM_OBSTACLES, self.N_attr, theme)
        self.N_attr = N_attr    # num of attraction agents
        self.N_cust = N_cust    # num of customer agents
        self.width = width
        self.height = height
        self.total_steps = 0
        self.cust_ids = N_cust
        self.strategy = strategy
        self.grid = MultiGrid(width, height, torus=False)
        self.schedule = BaseScheduler(self)
        self.schedule_Attraction = BaseScheduler(self)
        self.schedule_Customer = BaseScheduler(self)
        self.totalTOTAL = 0
        self.attractions = self.make_attractions()
        self.attraction_history = self.make_attr_hist()
        self.running = True
        self.data = []
        self.data_customers = []
        self.park_score = []
        self.data_dict = {}
        self.hist_random_strat = []
        self.hist_close_strat = []
        self.all_rides_list = []
        self.strategy_composition = self.make_strategy_composition()
        self.memory = 5
        self.customer_score = []
        self.customers = self.add_customers(self.N_cust)
        self.only_random = False


        for attraction in self.get_attractions():
            self.data_dict[attraction.unique_id] = ({
                               "id": attraction.unique_id,
                               "length": attraction.attraction_duration,
                               "waiting_list": []})

        if len(self.strategies) == 6:
            self.datacollector = DataCollector(

                {"Random": lambda m: self.strategy_counter(self.strategies[0]),
                "0.00": lambda m: self.strategy_counter(self.strategies[1]),
                "0.25": lambda m: self.strategy_counter(self.strategies[2]),
                "0.50": lambda m: self.strategy_counter(self.strategies[3]),
                "0.75": lambda m: self.strategy_counter(self.strategies[4]),
                "1.00": lambda m: self.strategy_counter(self.strategies[5]),
                })
        else:
            self.datacollector = DataCollector(
                {"0.00": lambda m: self.strategy_counter(self.strategies[0]),
                "0.25": lambda m: self.strategy_counter(self.strategies[1]),
                "0.50": lambda m: self.strategy_counter(self.strategies[2]),
                "0.75": lambda m: self.strategy_counter(self.strategies[3]),
                "1.00": lambda m: self.strategy_counter(self.strategies[4]),
                })

        self.datacollector2 = DataCollector(
            {"score": lambda m: self.make_score()})

        self.total_waited_time = 0

        self.monitor = Monitor(self.max_time, self.N_attr, self.positions)

    def make_score(self):
        ideal = {}
        cust_in_row = 0
        for i in range(len(self.get_attractions())):
            ideal[i] = self.N_cust/self.N_attr
            cust_in_row += self.get_attractions()[i].N_current_cust

        tot_difference = 0
        for i in range(len(self.get_attractions())):

            difference = abs(cust_in_row/self.N_attr  - self.get_attractions()[i].N_current_cust)
            tot_difference += difference

        fraction_not_right = (tot_difference/self.N_cust)
        return abs(1-(fraction_not_right)) * cust_in_row/self.N_cust

    def make_attr_hist(self):
        attraction_history = {}
        for attraction in self.get_attractions():

            attraction_history[attraction] = [0] * (self.max_time + 1)
        return attraction_history

    def strategy_counter(self, strategy):
        counter_total = {}

        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(
                attraction_pos,
                moore=True,
                radius=0,
                include_center=True
            )

            counter = 0
            for agent in self.customers:
                if agent.weight == strategy:
                    counter += 1

        return counter

    def make_strategy_composition(self):
        if self.strategy == "Random_test_4":
            self.strategies = ["Random_test_4", 0.0, 0.25, 0.50, 0.75, 1.0]
            dict = {self.strategies[0]: 1/6, self.strategies[1]:0.20, self.strategies[2]:0.20,
                            self.strategies[3]:0.20, self.strategies[4]:0.20, self.strategies[5]: 0.20}

            composition_list = []
            for i in range(len(self.strategies)):
                if i == 0:
                    dict[self.strategies[i]] = FRACTION_RANDOM
                    continue
                else:
                    composition_list.append(random.randint(0,100))
            sum_comp = sum(composition_list)

            sum_comp = sum_comp - sum_comp * FRACTION_RANDOM
            for i in range(len(self.strategies)):
                if i == 0:
                    continue
                else:
                    dict[self.strategies[i]] = composition_list[i-1] /sum_comp

        else:
            dict = {self.strategies[0]: 0.20, self.strategies[1]:0.20, self.strategies[2]:0.20,
                            self.strategies[3]:0.20, self.strategies[4]:0.20}

            composition_list = []
            for i in range(len(self.strategies)):

                composition_list.append(random.randint(0,100))

            sum_comp = sum(composition_list)

            sum_comp = sum_comp
            for i in range(len(self.strategies)):

                dict[self.strategies[i]] = composition_list[i-1] /sum_comp



        return dict

    def make_attractions(self):
        """ Initialize attractions on fixed position."""

        attractions = {}
        for i in range(self.N_attr):

            pos = (self.x_list[i], self.y_list[i])
            if self.grid.is_cell_empty(pos):

                name = str(i)
                a = Attraction(i, self, pos, name, self.N_cust, self.weight)
                attractions[i] = a

                self.schedule_Attraction.add(a)
                self.grid.place_agent(a, pos)
        return attractions

    def get_attractions(self):
        """
        Get a list with all attractions
        """
        agents = self.grid.get_neighbors(
            mid_point,
            moore=True,
            radius=RADIUS,
            include_center=True)

        attractions = []
        for agent in agents:
            if type(agent) == Attraction:
                attractions.append(agent)

        return attractions

    def add_customers(self, N_cust, added=False):
        """ Initialize customers on random positions."""

        weights_list = []
        if self.adaptive is True:

            for j in self.strategy_composition.keys():
                for i in range(round(N_cust*self.strategy_composition[j])):
                    weights_list.append(j)

            if len(weights_list) < self.N_cust:
                rand = random.choice(self.strategies)
                weights_list.append(rand)
            elif len(weights_list) > self.N_cust:
                rand = random.choice(weights_list)
                weights_list.remove(rand)


        else:
            if self.strategy is not "Random":

                # do what normally is done
                for i in range(round(N_cust)):
                    weights_list.append(self.weight)


        cust_list = []
        # weight_counter = 0
        # pick_weight = 0
        for i in range(N_cust):

            # pos_temp = random.choice(self.starting_positions)
            pos_temp = [random.randint(0,WIDTH-1), random.randint(0,HEIGHT-1)]
            rand_x, rand_y = pos_temp[0], pos_temp[1]

            pos = (rand_x, rand_y)

            if added is True:
                i = self.cust_ids
            if self.strategy == "Random_test_4":
                if weights_list[i] == "Random_test_4":
                    strategy = "Random_test_4"
                else:
                    strategy = "Closest_by"
            else:
                strategy = self.strategy


            # Deze if is omdat bij alleen random self.weight none is!
            if weights_list == []:
                weight = None
            else:
                weight = weights_list[i]
            a = Customer(i, self, pos, self.x_list, self.y_list, self.positions, strategy, weight, self.adaptive)

            self.schedule_Customer.add(a)

            self.grid.place_agent(a, pos)
            cust_list.append(a)

        return cust_list

    def calculate_people(self):
        """Calculate how many customers are in which attraction."""

        counter_total = {}

        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(
                attraction_pos,
                moore=True,
                radius=0,
                include_center=True
            )

            counter = 0
            for agent in agents:
                if type(agent) is Customer:
                    counter += 1
                else:
                    attraction = agent

            attraction.N_current_cust = counter
            counter_total[attraction.unique_id] = counter

        return list(counter_total.values())

    def calc_waiting_time(self):

        counter_total = {}

        attractions = self.get_attractions()
        for attraction in attractions:

            counter_total[attraction.unique_id] = attraction.current_waitingtime

        return counter_total


    def calculate_people_sorted(self):
        """
        Calculate how many customers are in which attraction.
        Returns a SORTED LIST.
        For example: indexes = [3, 2, 5, 1, 4]
        indicates that attraction3 has the least people waiting.
        """

        counter_total = {}

        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(
                attraction_pos,
                moore=True,
                radius=0,
                include_center=True
            )

            counter = 0
            for agent in agents:
                if type(agent) is Customer:
                    counter += 1
                else:
                    attraction = agent

            attraction.N_current_cust = counter
            self.attraction_history[attraction][self.totalTOTAL] = counter
            counter_total[attraction.unique_id] = counter
        return counter_total

    def make_route(self):
        """Draw coordinates of a possible path."""

        for i in range(len(self.path_coordinates)):
            pos = self.path_coordinates[i]

            if pos not in self.positions:

                # Create path agent
                path = Route(i, self, pos)
                self.schedule.add(path)

                self.grid.place_agent(path, pos)

    def get_themepark_score(self):
        """
        Get score of a themepark based on:
            - A total of all waitingtimes for every customer
            - TODO
        """
        attractions = self.get_attractions()
        total_wait, total_rides = 0, 0
        for attraction in attractions:
            total_wait += attraction.current_waitingtime

            if attraction.current_a is not None:
                total_rides += 1

        if total_rides == 0:
            return total_rides

        return (total_wait / total_rides)

    def get_strategy_history(self):
        """ Update history with how many customers chose which strategy """

        customers = self.get_customers()
        randomstrat, closebystrat = 0, 0

        for customer in customers:
            if customer.strategy == "Random" or customer.strategy == "Random_test_4":
                randomstrat += 1
            elif customer.strategy == "Closest_by":
                closebystrat += 1

        self.hist_random_strat.append(randomstrat)
        self.hist_close_strat.append(closebystrat)

    def get_customers(self):
        agents = self.grid.get_neighbors(
            mid_point,
            moore=True,
            radius=RADIUS,
            include_center=True)

        customers = []

        # Count customer agents
        for agent in agents:
            if type(agent) == Customer:
                customers.append(agent)
        return customers

    def get_data_customers(self):
        """ Return dictionary with data of customers """

        data = {}
        agents = self.grid.get_neighbors(
            mid_point,
            moore=True,
            radius=RADIUS,
            include_center=True)

        for agent in agents:
            if type(agent) is Customer:
                data[agent.unique_id] = {
                "totalwaited": agent.total_ever_waited,
                "visited_attractions": agent.nmbr_attractions,
                "strategy": agent.strategy,
                "swapped_strat": agent.strategy_swap_hist
                }
        return data

    def calc_hapiness(self):
        """
        Calculate mean hapiness of all customers, based on:

        - How many rides were taken
        - Number of times in the same attraction
        - Total waiting time
        """
        customers = self.get_customers()

        scores = []



        for customer in customers:
            history = customer.history
            values = list(history.values())
            total_rides = sum(values)

            if total_rides != 0:
                scores.append(total_rides / self.N_attr - self.totalTOTAL / customer.total_ever_waited)
            else:
                return None

        scores = np.interp(scores, (min(scores), max(scores)), (1, 10))
        return np.mean(scores)

    def get_history_list(self):

        customers = self.get_customers()


        histories = {}

        for customer in customers:
            history = customer.history
            values = list(history.values())
            histories[customer.unique_id] = values
        return histories

    def final(self):
        """ Return data """
        hist_list = []
        agents = self.grid.get_neighbors(
            mid_point,
            moore=True,
            radius=RADIUS,
            include_center=True)

        attractions = self.get_attractions()
        self.all_rides_list = [0] * len(attractions[0].in_attraction_list)
        for attraction in attractions:
            for i in range(len(attraction.in_attraction_list)):
                self.all_rides_list[i] += attraction.in_attraction_list[i]

        for i in range(len(self.all_rides_list)):
            self.all_rides_list[i] /= self.N_attr
        print("ALL RIDES LIST", self.all_rides_list)

        cust_data = self.get_data_customers()
        for agent in agents:
            if type(agent) is Customer:
                sum_attr = sum(agent.history.values())
                if sum_attr > 0:
                    hist_list.append(agent.strategy_swap_hist)
                else:
                    hist_list.append(agent.strategy_swap_hist)
                # print("swap:",agent.strategy_swap_hist , "sum:",sum_attr)


        # plt.hist(hist_list)
        # plt.show()

        histories = self.get_history_list()

        # save data
        try:
            pickle.dump(self.datacollector.get_model_vars_dataframe(), open("../data/strategy_history.p", 'wb'))
            pickle.dump(self.datacollector2.get_model_vars_dataframe(), open("../data/eff_score_history.p", 'wb'))
            pickle.dump(cust_data, open("../data/customers.p", 'wb'))
            pickle.dump(self.park_score[-1], open("../data/park_score.p", "wb"))
            pickle.dump(self.happinesses, open("../data/hapiness.p", "wb"))
            pickle.dump(histories, open("../data/cust_history.p", 'wb'))
        except:
            pickle.dump(self.datacollector.get_model_vars_dataframe(), open("data/strategy_history.p", 'wb'))
            pickle.dump(self.datacollector2.get_model_vars_dataframe(), open("data/eff_score_history.p", 'wb'))
            pickle.dump(cust_data, open("data/customers.p", 'wb'))
            pickle.dump(self.park_score[-1], open("data/park_score.p", "wb"))
            pickle.dump(self.happinesses, open("data/hapiness.p", "wb"))
            pickle.dump(histories, open("data/cust_history.p", 'wb'))

        try:
            pickle.dump(self.all_rides_list, open("../data/all_rides.p", "wb"))
        except:
            pickle.dump(self.all_rides_list, open("data/all_rides.p", "wb"))

        print()
        print("RUN HAS ENDED")
        print()


    def save_data(self):
        """Save data of all attractions and customers."""

        # Get info
        waitinglines = self.calc_waiting_time()

        for i in range(len(self.attractions)):
            self.data_dict[i]["waiting_list"].append(waitinglines.get(i))

        self.park_score.append(sum(waitinglines.values()))
        self.happinesses.append(self.calc_hapiness())

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

        if self.totalTOTAL < self.max_time:
            self.totalTOTAL += 1
            self.schedule.step()
            self.datacollector.collect(self)
            self.datacollector2.collect(self)

            self.schedule_Attraction.step()

            self.schedule_Customer.step()

            # update memory of attractions
            # attractions = self.get_attractions()
            # for attraction in attractions:
            #     attraction.update_memory()

            self.total_steps += 1

            self.save_data()
            self.get_strategy_history()

        else:
            for key in self.attraction_history.keys():
                y = self.attraction_history[key]
                x = list(range(0, self.max_time))
            self.final()
Beispiel #9
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
Beispiel #10
0
class Themepark(Model):
    def __init__(self, N_attr, N_cust, width, height, strategy, theme,
                 max_time, weight, adaptive):
        """
        Args:
            N_attr (int): the amount of attractions in the theme park
            N_cust (int): the amout of customers in the theme park
            width (int): the width of the theme park grid
            height (int): the height of the theme park grid
            strategy (str): the strategy of this run (random agents, adaptive agents
                            or adaptive agents with noise)
            theme (str): the setup of the park (circle, random or clustered)
            max_time (int): the number of time steps the park will do in one run
            weight (float): if the customer agents are non-adaptive, this is the strategy
                            they are using
            adaptive (bool): whether customer agents are able to switch strategies
        """
        self.theme = theme
        self.max_time = max_time
        self.N_attr = N_attr
        self.penalty_per = PENALTY_PERCENTAGE
        self.weight = weight
        self.adaptive = adaptive
        self.strategies = STRATEGIES
        self.happinesses = []
        self.N_attr = N_attr
        self.N_cust = N_cust
        self.width = width
        self.height = height
        self.total_steps = 0
        self.cust_ids = N_cust
        self.strategy = strategy
        self.grid = MultiGrid(width, height, torus=False)
        self.schedule = BaseScheduler(self)
        self.schedule_Attraction = BaseScheduler(self)
        self.schedule_Customer = BaseScheduler(self)

        # Cluster or circle coordinates
        if self.theme == "cluster":
            self.x_list, self.y_list, self.positions = xlist, ylist, positions
        elif self.theme == "circle":
            self.x_list, self.y_list, self.positions = get_attraction_coordinates(
                width, height, N_attr, "circle")

        # keeps up the current time
        self.totalTOTAL = 0

        # add attractions to park
        self.attractions = self.make_attractions()
        self.attraction_history = self.make_attr_hist()
        self.running = True
        self.data_dict = {}

        # keep up a history of the strategies
        self.hist_random_strat = []
        self.hist_close_strat = []

        # keep up a history of the occupation of the rides
        self.all_rides_list = []

        # distribution of strategies throughout population
        self.strategy_composition = self.make_strategy_composition()

        # add customers to park
        self.customers = self.add_customers(self.N_cust)

        # keep up park score throughout time
        self.park_score = []

        for attraction in self.get_attractions():
            self.data_dict[attraction.unique_id] = ({
                "id": attraction.unique_id,
                "length": attraction.attraction_duration,
                "waiting_list": []
            })

        # datacollector for the visualisation of the data
        if self.strategy == "Random_test_4":
            self.datacollector = DataCollector({
                "Random":
                lambda m: self.strategy_counter(self.strategies[0]),
                "0.00":
                lambda m: self.strategy_counter(self.strategies[1]),
                "0.25":
                lambda m: self.strategy_counter(self.strategies[2]),
                "0.50":
                lambda m: self.strategy_counter(self.strategies[3]),
                "0.75":
                lambda m: self.strategy_counter(self.strategies[4]),
                "1.00":
                lambda m: self.strategy_counter(self.strategies[5]),
            })

        elif self.strategy == "Random":
            self.datacollector = DataCollector(
                {"Random": lambda m: self.N_cust})

        else:
            self.datacollector = DataCollector({
                "0.00":
                lambda m: self.strategy_counter(self.strategies[0]),
                "0.25":
                lambda m: self.strategy_counter(self.strategies[1]),
                "0.50":
                lambda m: self.strategy_counter(self.strategies[2]),
                "0.75":
                lambda m: self.strategy_counter(self.strategies[3]),
                "1.00":
                lambda m: self.strategy_counter(self.strategies[4]),
            })

        self.datacollector2 = DataCollector(
            {"score": lambda m: self.make_score()})

    def make_score(self):
        """
        Calculates and returns an efficiency score for the enire theme park.
        """

        # calculates the ideal distribution of customers over the attractions per attraction
        ideal = {}
        cust_in_row = 0
        for i in range(len(self.get_attractions())):
            ideal[i] = self.N_cust / self.N_attr
            cust_in_row += self.get_attractions()[i].N_current_cust

        # calculates the difference between the ideal and the real situation
        tot_difference = 0
        for i in range(len(self.get_attractions())):

            difference = abs(cust_in_row / self.N_attr -
                             self.get_attractions()[i].N_current_cust)
            tot_difference += difference

        # the fraction of customers that is not optimally distributed
        fraction_not_right = (tot_difference / self.N_cust)

        # add a penalty by multiplying by the fraction of people currently in a line
        score = abs(1 - (fraction_not_right)) * cust_in_row / self.N_cust
        return score

    def make_attr_hist(self):
        """
        Make history of attractions that are visited for each customer.
        """
        attraction_history = {}
        for attraction in self.get_attractions():

            attraction_history[attraction] = [0] * (self.max_time + 1)
        return attraction_history

    def strategy_counter(self, strategy):
        """
        Input is a strategy, for example "0.25" or "Random", output is
        the number of strategies are adopted at a current time step.
        """
        for attraction_pos in self.positions:
            counter = 0
            for agent in self.customers:
                if agent.weight == strategy:
                    counter += 1
        return counter

    def make_strategy_composition(self):
        """
        Make a composition of all strategies over the entire theme park.
        Returns a dictionary with strategies as keys and the fraction of people
        using this strategy as value.
        """

        # if this is a run with adaptive agents and noise
        if self.strategy == "Random_test_4":
            self.strategies = ["Random_test_4", 0.0, 0.25, 0.50, 0.75, 1.0]

            # make dictionary with fractions (values can be ignored!)
            dict = {
                self.strategies[0]: 0,
                self.strategies[1]: 0.20,
                self.strategies[2]: 0.20,
                self.strategies[3]: 0.20,
                self.strategies[4]: 0.20,
                self.strategies[5]: 0.20
            }

            composition_list = []
            for i in range(len(self.strategies)):
                if i == 0:
                    dict[self.strategies[i]] = FRACTION_RANDOM
                    continue
                else:

                    # choose a random number
                    composition_list.append(random.randint(0, 100))

            sum_comp = sum(composition_list)
            sum_comp = sum_comp - sum_comp * FRACTION_RANDOM
            for i in range(len(self.strategies)):
                if i == 0:
                    continue
                else:

                    # determine the fraction of customer agents with this strategy
                    dict[self.strategies[i]] = composition_list[i -
                                                                1] / sum_comp

        # runs without noise
        else:
            # make dictionary with fractions (values can be ignored!)
            dict = {
                self.strategies[0]: 0.20,
                self.strategies[1]: 0.20,
                self.strategies[2]: 0.20,
                self.strategies[3]: 0.20,
                self.strategies[4]: 0.20
            }

            composition_list = []
            for i in range(len(self.strategies)):

                # choose a random number
                composition_list.append(random.randint(0, 100))

            sum_comp = sum(composition_list)

            for i in range(len(self.strategies)):

                # determine the fraction of agents with this strategy
                dict[self.strategies[i]] = composition_list[i - 1] / sum_comp

        return dict

    def make_attractions(self):
        """
        Initialize attractions on fixed positions, defined in the global
        variables x_list and y_list. Returns a dictionary of attractions
        """

        attractions = {}
        for i in range(self.N_attr):

            pos = (self.x_list[i], self.y_list[i])

            # place attraction if grid cell is empty
            if self.grid.is_cell_empty(pos):

                name = str(i)
                a = Attraction(i, self, pos, name)
                attractions[i] = a

                self.schedule_Attraction.add(a)
                self.grid.place_agent(a, pos)
        return attractions

    def get_attractions(self):
        """
        Return a list with all attractions.
        """
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)

        attractions = []
        for agent in agents:
            if type(agent) == Attraction:
                attractions.append(agent)

        return attractions

    def add_customers(self, N_cust, added=False):
        """
        Initialize customers on random positions.
        Returns a list of all customers
        """

        # a list of weights of which the indices correspond to the id of the agent
        # to who this weight is given
        weights_list = []

        # Adaptive strategy
        if self.adaptive is True:

            # Decide weights for every customer
            for j in self.strategy_composition.keys():
                for i in range(round(N_cust * self.strategy_composition[j])):
                    weights_list.append(j)

            # Add weights for the random strategy
            if len(weights_list) < self.N_cust:
                rand = random.choice(self.strategies)
                weights_list.append(rand)
            elif len(weights_list) > self.N_cust:
                rand = random.choice(weights_list)
                weights_list.remove(rand)

        else:
            if self.strategy is not "Random":
                for i in range(round(N_cust)):
                    print(self.weight)
                    weights_list.append(self.weight)

        cust_list = []
        for i in range(N_cust):

            # Get random location within grid height and width
            pos_temp = [
                random.randint(0, WIDTH - 1),
                random.randint(0, HEIGHT - 1)
            ]
            rand_x, rand_y = pos_temp[0], pos_temp[1]
            pos = (rand_x, rand_y)

            if added is True:
                i = self.cust_ids
            if self.strategy == "Random_test_4":
                if weights_list[i] == "Random_test_4":
                    strategy = "Random_test_4"
                else:
                    strategy = "Closest_by"
            else:
                strategy = self.strategy

            if weights_list == []:
                weight = None
            else:
                weight = weights_list[i]

            # make customer
            a = Customer(i, self, pos, strategy, weight, self.adaptive)
            self.schedule_Customer.add(a)
            self.grid.place_agent(a, pos)
            cust_list.append(a)

        return cust_list

    def calculate_people(self):
        """
        Calculate how many customers are in which attraction.
        Returns a list of which the indices correspond to the ids of the atttraction
        """

        counter_total = {}

        # loop through attractions
        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(attraction_pos,
                                             moore=True,
                                             radius=0,
                                             include_center=True)

            counter = 0

            # find customers in this attraction
            for agent in agents:
                if type(agent) is Customer:
                    counter += 1
                else:
                    attraction = agent

            # update the amount of customers in this attraction
            attraction.N_current_cust = counter
            counter_total[attraction.unique_id] = counter

        return list(counter_total.values())

    def calc_waiting_time(self):
        """
        Return a dictionary of watingtimes for every attraction
        """
        counter_total = {}

        attractions = self.get_attractions()
        for attraction in attractions:

            counter_total[
                attraction.unique_id] = attraction.current_waitingtime

        return counter_total

    def calculate_people_sorted(self):
        """
        Calculate how many customers are in which attraction.
        Returns a dictionary with attraction-ids as keys and customers in line as values.
        """

        counter_total = {}

        # loop through attractions
        for attraction_pos in self.positions:

            agents = self.grid.get_neighbors(attraction_pos,
                                             moore=True,
                                             radius=0,
                                             include_center=True)

            counter = 0

            # find customers in this attraction
            for agent in agents:
                if type(agent) is Customer:
                    counter += 1
                else:
                    attraction = agent

            # update the amount of customers in this attraction
            attraction.N_current_cust = counter
            self.attraction_history[attraction][self.totalTOTAL] = counter
            counter_total[attraction.unique_id] = counter

        return counter_total

    def get_strategy_history(self):
        """ Update history with how many customers chose which strategy """

        customers = self.get_customers()
        randomstrat, closebystrat = 0, 0

        for customer in customers:
            if customer.strategy == "Random" or customer.strategy == "Random_test_4":
                randomstrat += 1
            elif customer.strategy == "Closest_by":
                closebystrat += 1

        self.hist_random_strat.append(randomstrat)
        self.hist_close_strat.append(closebystrat)

    def get_customers(self):
        """Return a list of all customers in the theme park."""
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)

        customers = []

        # Count customer agents
        for agent in agents:
            if type(agent) == Customer:
                customers.append(agent)
        return customers

    def get_data_customers(self):
        """ Return dictionary with data of customers """

        data = {}
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)

        for agent in agents:
            if type(agent) is Customer:
                data[agent.unique_id] = {
                    "totalwaited": agent.total_ever_waited,
                    "visited_attractions": agent.nmbr_attractions,
                    "strategy": agent.strategy,
                    "swapped_strat": agent.strategy_swap_hist
                }
        return data

    def calc_hapiness(self):
        """
        Calculate mean hapiness of all customers, based on:

        - How many rides were taken
        - Number of times in the same attraction
        - Total waiting time

        Returns the mean happiness of all customers
        """
        customers = self.get_customers()
        scores = []

        for customer in customers:
            history = customer.history
            values = list(history.values())
            total_rides = sum(values)

            if total_rides != 0:
                scores.append(total_rides / self.N_attr -
                              self.totalTOTAL / customer.total_ever_waited)
            else:
                return None

        scores = np.interp(scores, (min(scores), max(scores)), (1, 10))
        return np.mean(scores)

    def get_history_list(self):
        """
        Return a dictionary of the history of visited attraction for
        each customer.
        """

        customers = self.get_customers()
        histories = {}

        for customer in customers:
            history = customer.history
            values = list(history.values())
            histories[customer.unique_id] = values
        return histories

    def final(self):
        """ Return and save data at the end of the run."""

        hist_list = []
        agents = self.grid.get_neighbors(mid_point,
                                         moore=True,
                                         radius=RADIUS,
                                         include_center=True)
        attractions = self.get_attractions()

        # Make a list for the fraction of occupied rides at all time steps
        self.all_rides_list = [0] * len(attractions[0].in_attraction_list)
        for attraction in attractions:
            for i in range(len(attraction.in_attraction_list)):
                self.all_rides_list[i] += attraction.in_attraction_list[i]
        for i in range(len(self.all_rides_list)):
            self.all_rides_list[i] /= self.N_attr

        cust_data = self.get_data_customers()
        for agent in agents:
            if type(agent) is Customer:
                sum_attr = sum(agent.history.values())
                if sum_attr > 0:
                    hist_list.append(agent.strategy_swap_hist)
                else:
                    hist_list.append(agent.strategy_swap_hist)

        histories = self.get_history_list()

        # save data
        try:
            pickle.dump(self.datacollector.get_model_vars_dataframe(),
                        open("../data/strategy_history.p", 'wb'))
            pickle.dump(self.datacollector2.get_model_vars_dataframe(),
                        open("../data/eff_score_history.p", 'wb'))
            pickle.dump(cust_data, open("../data/customers.p", 'wb'))
            pickle.dump(self.park_score[-1], open("../data/park_score.p",
                                                  "wb"))
            pickle.dump(self.happinesses, open("../data/hapiness.p", "wb"))
            pickle.dump(histories, open("../data/cust_history.p", 'wb'))
            pickle.dump(self.all_rides_list, open("../data/all_rides.p", "wb"))
        except:
            pickle.dump(self.datacollector.get_model_vars_dataframe(),
                        open("data/strategy_history.p", 'wb'))
            pickle.dump(self.datacollector2.get_model_vars_dataframe(),
                        open("data/eff_score_history.p", 'wb'))
            pickle.dump(cust_data, open("data/customers.p", 'wb'))
            pickle.dump(self.park_score[-1], open("data/park_score.p", "wb"))
            pickle.dump(self.happinesses, open("data/hapiness.p", "wb"))
            pickle.dump(histories, open("data/cust_history.p", 'wb'))
            pickle.dump(self.all_rides_list, open("data/all_rides.p", "wb"))

        print()
        print("RUN HAS ENDED")
        print()

    def save_data(self):
        """Save data of all attractions and customers."""

        # Get info
        waitinglines = self.calc_waiting_time()

        for i in range(len(self.attractions)):
            self.data_dict[i]["waiting_list"].append(waitinglines.get(i))

        self.park_score.append(sum(waitinglines.values()))
        self.happinesses.append(self.calc_hapiness())

    def step(self):
        """Advance the model by one step."""
        if self.totalTOTAL < self.max_time:
            self.totalTOTAL += 1
            self.schedule.step()

            # Collect data for every step
            self.datacollector.collect(self)
            self.datacollector2.collect(self)

            # Step for both attraction and customer
            self.schedule_Attraction.step()
            self.schedule_Customer.step()

            self.total_steps += 1

            # Save data and update strategy history
            self.save_data()
            self.get_strategy_history()

        else:
            for key in self.attraction_history.keys():
                y = self.attraction_history[key]
                x = list(range(0, self.max_time))
            self.final()
Beispiel #11
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)
Beispiel #12
0
class Covid(Model):
    """
    Model class for the Covid infection model.
    """
    def __init__(self,
                 density,
                 initial_infected,
                 infection_rate,
                 min_infected,
                 max_infected,
                 mean_infected,
                 min_exposed,
                 max_exposed,
                 mean_exposed,
                 day_steps,
                 day_isolation,
                 detection_rate,
                 width=20):
        """
        """
        # square grid
        height = width
        self.height = height
        self.width = width

        self.density = density
        self.initial_infected = initial_infected
        self.infection_rate = infection_rate
        self.detection_rate = detection_rate

        self.day_steps = day_steps

        self.min_exposed = min_exposed * self.day_steps
        self.max_exposed = max_exposed * self.day_steps
        self.mean_exposed = mean_exposed * self.day_steps

        self.min_infected = min_infected * self.day_steps
        self.max_infected = max_infected * self.day_steps
        self.mean_infected = mean_infected * self.day_steps

        self.day_isolation = day_isolation * self.day_steps

        self.schedule = RandomActivation(self)
        self.grid = MultiGrid(width, height, torus=True)

        self.infected = 0
        self.exposed = 0
        self.susceptible = 0
        self.removed = 0

        self.contact = 0
        self.cuminfected = 0
        self.isolated = 0
        self.stats = {
            "infected": [],
            "exposed": [],
            "susceptible": [],
            "removed": [],
            "isolated": []
        }

        self.datacollector = DataCollector(
            # Model-level count
            {
                "contact": "contact",
                "infected": "infected",
                "cuminfected": "cuminfected",
                "exposed": "exposed",
                "susceptible": "susceptible",
                "removed": "removed",
                "isolated": "isolated",
                "stats": "stats"
            },

            # For testing purposes, agent's individual x and y
            {
                "x": lambda a: a.pos[0],
                "y": lambda a: a.pos[1]
            })

        # Set up agents
        # We use a grid iterator that returns
        # the coordinates of a cell as well as
        # its contents. (coord_iter)

        num_agents = 0
        num_infected = 0

        while num_agents < self.density:

            #for cell in self.grid.coord_iter():
            #x = cell[1]
            #y = cell[2]

            # obtaining non-empty cell
            x = int(self.random.uniform(0, width))
            y = int(self.random.uniform(0, height))

            while not self.grid.is_cell_empty((x, y)):
                x = int(self.random.uniform(0, width))
                y = int(self.random.uniform(0, height))

            if num_agents < self.density and self.random.random() < 0.2:

                if num_infected < self.initial_infected:
                    agent_type = Infected()
                    num_infected += 1

                    # generate typical infected lifespan from normal distribution
                    ls = self.random.uniform(self.min_infected,
                                             self.max_infected)
                    agent_type.setLifespan(ls)
                    agent_type.set_detected(
                        self.random.uniform(0, 1) < self.detection_rate)

                else:
                    agent_type = Susceptible()

                agent = CovidAgent((x, y), self, agent_type)
                self.grid.place_agent(agent, (x, y))
                self.schedule.add(agent)
                num_agents += 1

        #print(str(num_agents)+" agents finally.")
        self.running = True
        #self.datacollector.collect(self)

    def step(self):
        """
        Run one step of the model. If All agents are happy, halt the model.
        """
        # Reset counters
        self.infected = 0
        self.exposed = 0
        self.susceptible = 0
        self.removed = 0
        self.isolated = 0

        self.schedule.step()

        # compute average contact per agent
        total = 0
        for cell in self.grid.coord_iter():
            content, x, y = cell
            if content:
                for c in content:
                    total += len(c.contact)

                    if isinstance(c.d_state, Infected):
                        self.infected += 1
                    elif isinstance(c.d_state, Exposed):
                        self.exposed += 1
                    elif isinstance(c.d_state, Susceptible):
                        self.susceptible += 1
                    elif isinstance(c.d_state, Removed):
                        self.removed += 1

                    if not c.move:
                        #print("isolated")
                        self.isolated += 1

        self.contact = total / self.schedule.get_agent_count()

        self.stats["infected"].append(self.infected)
        self.stats["exposed"].append(self.exposed)
        self.stats["susceptible"].append(self.susceptible)
        self.stats["removed"].append(self.removed)
        self.stats["isolated"].append(self.isolated)

        # collect data
        self.datacollector.collect(self)

        if self.infected + self.exposed == 0:
            self.running = False

        if self.schedule.steps / self.day_steps > 180:
            self.running = False