Exemplo n.º 1
0
class Model(Model):
    def __init__(self, N, B, T, Treg, width, height):
        self.num_myelin = N * 8
        self.num_agents = N + B + T + Treg + self.num_myelin
        self.num_neurons = N
        self.num_myelin = 4
        self.num_limfocytB = B
        self.num_active_B = 0
        self.num_infected_B = 0
        self.num_limfocytT = T
        self.num_activeT = 0
        self.num_limfocytTreg = Treg
        self.grid = MultiGrid(width, height, True)
        self.schedule = RandomActivation(self)
        self.available_ids = set()
        self.dead_agents = set()
        self.new_agents = set()
        self.max_id = 0
        self.step_count = 1
        self.cytokina = 0
        self.cytokina_prev = 0
        self.sum = 0
        self.B = 0
        self.a = 0.80
        self.Ymax = 100
        open('new_and_dead.txt', 'w').close()
        # Create agents
        neuron_positions = [[3, 3], [3, 10], [3, 20], [3, 27], [10, 3],
                            [10, 10], [10, 20], [10, 27], [19, 3], [19, 10],
                            [19, 20], [19, 27], [26, 3], [26, 10], [26, 20],
                            [26, 27], [14, 15]]
        for i in range(self.num_neurons):
            a = Neuron(i, self, "Neuron")
            self.schedule.add(a)
            #Add agent to a random grid cell
            #x=self.random.randrange(self.grid.width)
            #y=self.random.randrange(self.grid.height)
            #self.grid.place_agent(a,(x,y))
            pos = neuron_positions[i]
            self.grid.place_agent(a, (pos[0], pos[1]))
            cells = self.grid.get_neighborhood(a.pos, True, False, 1)
            id = self.num_agents - i * 8
            for cell in cells:
                m = Myelin(id, self, "Myelin")
                self.schedule.add(m)
                self.grid.place_agent(m, cell)
                id -= 1

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

        self.max_id = self.num_agents - 1

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

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

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

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

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

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

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

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

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

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

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

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

    def running(self):
        self.step()

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

    def deficiencies(self):
        n = B_population(self)
        if n == 0:
            if len(self.available_ids) == 0:
                self.max_id += 1
                id = self.max_id
            else:
                id = min(self.available_ids)
                self.available_ids.remove(id)
            agent = LimfocytB(id, self, "LimfocytB")
            self.schedule.add(agent)
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(agent, (x, y))
            self.num_agents += 1
        n = T_population(self)
        if n == 0:
            for i in range(10):
                if len(self.available_ids) == 0:
                    self.max_id += 1
                    id = self.max_id
                else:
                    id = min(self.available_ids)
                    self.available_ids.remove(id)
                agent = LimfocytB(id, self, "LimfocytT")
                self.schedule.add(agent)
                x = self.random.randrange(self.grid.width)
                y = self.random.randrange(self.grid.height)
                self.grid.place_agent(agent, (x, y))
                self.num_agents += 1
        n = Treg_population(self)
        if n == 0:
            if len(self.available_ids) == 0:
                self.max_id += 1
                id = self.max_id
            else:
                id = min(self.available_ids)
                self.available_ids.remove(id)
            agent = LimfocytB(id, self, "LimfocytTreg")
            self.schedule.add(agent)
            x = self.random.randrange(self.grid.width)
            y = self.random.randrange(self.grid.height)
            self.grid.place_agent(agent, (x, y))
            self.num_agents += 1
Exemplo n.º 2
0
class LandModel(Model):



    """
    Main model
    """
    def __init__(self,
                 percentage_buyers, # Percentage of buyers to be added acording to the available land  
                 percentage_high_income, #Percentage that are high income
                 rich_market_reach, # The amount of properties the rich can bid
                 poor_market_reach, # The amount of properties the poor can bid
                 base_price, # The land base price
                 base_income, # The base income for all buyers
                 rich_poor_std, #Standard deviation for the rich and poor
                 num_cities, # The number of cities
                 b, # Constant for the wtp formula                 
                 urbanization_over_rural_roductivity, # Constant for the probability of selling
                 size, # tuple: (width, height)                                  
                 alpha = 0.5,# The alpha parameter (preference)
                 amenities = "uniform", #The amenities
                 rural_productivity = "uniform", # The rural productivity
                 buyer_mode =  cons.BID_SCHEME.BEST,
                 max_epochs = 10, #number of epochs
                 max_urbanization = np.inf # Maximum number of urbanization units
                 ): 


        position = "CENTRAL"

        #print('')
        #print('Rich: ' + str(rich_market_reach) + ' Poor: ' + str(poor_market_reach))

        #Variables for batch run
        self.num_epochs = 0
        self.max_epochs = max_epochs
        self.max_urbanization = max_urbanization
        self.running = True

        #Scheduler
        self.schedule = BaseScheduler(self)

        #Assigns variables to the model
        self.base_price = base_price
        self.base_income = base_income
        self.rich_poor_std = rich_poor_std

        self.rich_market_reach = rich_market_reach
        self.poor_market_reach = poor_market_reach

        self.b = b

        self.w2 = urbanization_over_rural_roductivity
        self.w1 = 1 - self.w2

        self.epyslon = 0

        self.alpha = alpha

        self.buyer_mode = buyer_mode

        #Sets up the grid

        #Size of Grid
        self.width = size[0]
        self.height = size[1]
        self.grid = MultiGrid(self.width, self.height, True) # Multigrid - Agents can share a cell

        #Assign the shapes
        self.grid_shape = (self.width, self.height)


        #Distribution variables
        self.amenities = self.get_distribution(amenities)
        self.rural_productivity = self.get_distribution(rural_productivity)

        #Starts the patches as an empty matix
        self.patches = np.empty((self.width, self.height), dtype = object)


        #Invokes the city generator
        # Checks if will import from raster
        if str(num_cities).upper() == 'RASTER':
            centers, city_fun = CityGenerator.import_from_raster(self.grid_shape)

        else:    
            # Handles the city creation (at random) and the corresponding centers
            centers, city_fun = CityGenerator.make_cities_fun(self.grid_shape, num_cities = num_cities, position = position)

        self.city_centers = centers

        #Calculates max city distance (for the city proximity function)
        self.max_city_distance = self.get_max_city_distance()

        #Starts land patches and city pathces (both are sets to guarantee O(1) lookup)
        self.land_patches = set()
        self.city_patches = set()


        #Iterates over each possible patch and assigns city or land
        for index in list(itertools.product(range(self.width), range(self.height))):

            patch = LandPatch("land_patch_" + str(index), self)
            patch.type = city_fun(index)

            if(patch.type == cons.LAND_TYPES.CITY):
                self.city_patches.add(patch)
                patch.convert_to_city()
            else:
                self.land_patches.add(patch)
                patch.convert_to_land()

            self.grid.place_agent(patch, index)
            self.patches[index] = patch
            patch.set_properties() # Initializes patch


        #The number of sellers will be the number of land patches
        num_sellers = len(self.land_patches)


        self.percentage_buyers = percentage_buyers
        if(percentage_buyers <= 0 or percentage_buyers > 100):
            raise ValueError('Percentage of buyers is incorrect: ' + str(percentage_buyers))

        # Calculates the number of buyers
        self.percentage_high_income = percentage_high_income
        self.num_buyers = np.round((self.percentage_buyers/100)*len(self.land_patches))
        

        # Sets up the number of poor and rich buyers
        self.num_rich_buyers = int(self.num_buyers*self.percentage_high_income/100)
        self.num_poor_buyers = int(self.num_buyers*(100- self.percentage_high_income)/100)

        #Number of Agents
        self.num_sellers = num_sellers
        self.num_buyers = self.num_rich_buyers + self.num_poor_buyers
        self.num_agents = self.num_sellers + self.num_buyers

        self.buyers = set()
        self.sellers = set()

        #To remove
        # At the end of each iteration will remove the sellers who sold
        self.to_remove = []

        # adds the sellers (one for each land patch)
        added_sellers = 0
        for pat in self.land_patches:

            seller = Seller("seller_" + str(added_sellers), self, pat)
            self.schedule.add(seller)

            #Adds the seller
            self.grid.place_agent(seller, pat.pos)
            self.sellers.add(seller)

            added_sellers += 1


        # Adds the buyers
        self.add_rich_buyers(self.num_rich_buyers)
        self.add_poor_buyers(self.num_poor_buyers)

        # The data collector
        # For plotting oprions
        self.current_bids = []

        self.datacollector = DataCollector(
                model_reporters={"Amenities": get_mean_amenities})




    def step(self):
        """
        Method that simulates the step of an epoch
        """

        #Scehdule
        #print('Step ' + str(self.num_epochs))

        #Calculates the sellers that will sell
        market = set()
        for seller in self.sellers:
            if(seller.will_sell()):
                market.add(seller)

        if(len(market) == 0):
            print('Nobody wants to sell')

        #All the buyer make their bids
        for buyer in self.buyers:
            buyer.make_bids(market, self.buyer_mode)


        #Asjust Epsylon
        self.epyslon = (len(self.buyers) - len(self.sellers))/(len(self.buyers) + len(self.sellers))

        #Randomly, buyers and sellers interact
        sellers = random.sample(self.sellers, len(self.sellers))
        for seller in sellers:
            sold = seller.sell()
            if(sold):
                #Removes seller
                self.grid._remove_agent(seller.pos, seller)
                self.sellers.remove(seller)

        self.current_bids = []

        #removes all buyers
        self.remove_all_buyers()

        #Updates the number of buyers for next epoch
        self.num_buyers = np.round((self.percentage_buyers/100)*len(self.land_patches))
        
        

        # Sets up the number of poor and rich buyers
        self.num_rich_buyers = int(self.num_buyers*self.percentage_high_income/100)
        self.num_poor_buyers = int(self.num_buyers*(100- self.percentage_high_income)/100)        
        self.num_buyers = self.num_rich_buyers + self.num_poor_buyers

        #Adds the new generation
        self.add_rich_buyers(self.num_rich_buyers)
        self.add_poor_buyers(self.num_poor_buyers)

        #Collects data
        self.datacollector.collect(self)

        #Adjust progress variables (for batch process)
        self.num_epochs += 1
        if(self.num_epochs == self.max_epochs or self.get_num_patches() == 0):
            self.running = False

        #Stops the process if the maximum urbanization limit is exceeded
        if(len(self.city_patches) >= self.max_urbanization):
            print(self.num_epochs)
            self.running = False



    def get_max_city_distance(self):
        """
        Calculates the max city distance available in the greed (recall there can
        be multiple cities)
        """
        indices = list(itertools.product(range(self.width),range(self.height)))
        positions = np.array(indices)
        centers = np.array(self.city_centers)

        dist_centers = metrics.pairwise.euclidean_distances(positions,centers)
        dist_centers = np.min(dist_centers, axis = 1)

        return(np.max(dist_centers))


    def get_available_pos(self):
        """
        Gets an available position (so agent don't end up in a city patch)
        Was design for when the agents bought around them.
        """

        if(self.land_patches):
            land_patch = random.sample(self.land_patches,1)[0]
            return(land_patch.pos)

        return(None)

    def get_available_positions(self, k, replace = False):

        choices = np.random.choice(list(self.land_patches), size = k, replace = replace)

        return([land_patch.pos for land_patch in choices])
        


    def get_num_patches(self):
        return(len(self.land_patches))



    def remove_all_buyers(self):
        """
        Removes all buyers from the model. At the end of every epoch,
        this method is called
        """
        for agent in self.buyers:
            self.grid._remove_agent(agent.pos, agent)
            self.schedule.remove(agent)

        self.buyers = set()


    def add_rich_buyers(self, num_rich_buyers):
        """
        Add rich buyers to the grid
        """
        indices = self.get_available_positions(num_rich_buyers)

        for i in range(num_rich_buyers):
            income = max(0,(self.base_income + np.abs(np.random.normal(loc = 0, scale = self.rich_poor_std))))
            buyer = Buyer("buyer_rich_" + str(i), self, income = income, market_reach = self.rich_market_reach, type = cons.AGENT_TYPES.RICH)
            self.schedule.add(buyer)

            #Gets an available position
            index = indices[i]

            #Adds the buyer
            self.grid.place_agent(buyer, index)
            self.buyers.add(buyer)


    def add_poor_buyers(self, num_poor_buyers):
        """
        Add poor buyers to the grid
        """
        indices = self.get_available_positions(num_poor_buyers)

        for i in range(num_poor_buyers):
            income = max(0,(self.base_income - np.abs(np.random.normal(loc = 0, scale = self.rich_poor_std))))
            buyer = Buyer("buyer_poor_" + str(i), self, income = income, market_reach = self.poor_market_reach, type = cons.AGENT_TYPES.POOR)
            self.schedule.add(buyer)

            #Gets an available position
            index = indices[i]

            #Adds the buyer
            self.grid.place_agent(buyer, index)

            self.buyers.add(buyer)



    def get_distribution(self, name):
        """
        Gets the corresponding function depending on the distribution
        """

        if("CONSTANT" in str(name).upper()):
            name = name.replace(" ","")
            values = name.split("=")
            if(len(values) != 2):
                raise ValueError("If function is constant, should specify its value")

            constant = float(values[1])
            return(lambda x: constant )        

        if(str(name).upper() == "UNIFORM"):
            return(lambda x: np.random.uniform())

        if(str(name).upper() == "RASTER_AMENITIES"):
            return(CityGenerator.amenities_from_raster(self.grid_shape))


        raise ValueError("No implementation for the distribution: "  + str(name))



    def get_tract_info(self, tract = 4):

        matrix = self.get_sold_type_matrix()
        array = get_tract_structure(matrix, tract)

        n = len(array)
        r = np.apply_along_axis(lambda x: np.sum(x == cons.AGENT_TYPES.RICH), 0, array)
        R = np.sum(matrix == cons.AGENT_TYPES.RICH)
        p = np.apply_along_axis(lambda x: np.sum(x == cons.AGENT_TYPES.POOR), 0, array)
        P = np.sum(matrix == cons.AGENT_TYPES.POOR)

        return(n,r,R,p,P)




    def get_sold_type_matrix(self):

        #Extract the matrix with the values
        matrix = np.array([[ self.patches[i,j].sold_type for j in range(self.patches.shape[1])] for i in range(self.patches.shape[0])])
        return(matrix)