mesa/model.py

135 lines
4.7 KiB
Python

import json
import networkx as nx
import pandas as pd
from mesa import Model
from mesa.time import RandomActivation
from mesa.space import MultiGrid
from mesa.datacollection import DataCollector
from firm import FirmAgent
from product import ProductAgent
from scheduler import CustomScheduler
class MyModel(Model):
def __init__(self, params):
self.num_agents = params['N']
self.grid = MultiGrid(params['width'], params['height'], True)
self.schedule = CustomScheduler(self)
# Initialize parameters from `params`
self.sample = params['sample']
self.int_stop_ts = 0
self.int_n_iter = int(params['n_iter'])
self.dct_lst_init_disrupt_firm_prod = params['dct_lst_init_disrupt_firm_prod']
# external variable
self.int_n_max_trial = int(params['n_max_trial'])
self.is_prf_size = bool(params['prf_size'])
self.remove_t = int(params['remove_t'])
self.int_netw_prf_n = int(params['netw_prf_n'])
self.product_network = None
self.firm_network = None
self.firm_prod_network = None
# Initialize product network
G_bom = nx.adjacency_graph(json.loads(params['g_bom']))
self.product_network = G_bom
# Initialize firm network
self.initialize_firm_network()
# Initialize firm product network
self.initialize_firm_prod_network()
# Initialize agents
self.initialize_agents()
# Data collector (if needed)
self.datacollector = DataCollector(
agent_reporters={"Product Code": "code"}
)
def initialize_firm_network(self):
# Read firm data and initialize firm network
firm = pd.read_csv("input_data/Firm_amended.csv")
firm['Code'] = firm['Code'].astype('string')
firm.fillna(0, inplace=True)
firm_attr = firm[["Code", "Type_Region", "Revenue_Log"]]
firm_product = []
for _, row in firm.loc[:, '1':].iterrows():
firm_product.append(row[row == 1].index.to_list())
firm_attr['Product_Code'] = firm_product
firm_attr.set_index('Code', inplace=True)
G_Firm = nx.MultiDiGraph()
G_Firm.add_nodes_from(firm["Code"])
# Add node attributes
firm_labels_dict = {}
for code in G_Firm.nodes:
firm_labels_dict[code] = firm_attr.loc[code].to_dict()
nx.set_node_attributes(G_Firm, firm_labels_dict)
# Add edges based on BOM graph
self.add_edges_based_on_bom(G_Firm)
self.firm_network = G_Firm
def initialize_firm_prod_network(self):
# Read firm product data and initialize firm product network
firm_prod = pd.read_csv("input_data/Firm_amended.csv")
firm_prod.fillna(0, inplace=True)
firm_prod = pd.DataFrame({'bool': firm_prod.loc[:, '1':].stack()})
firm_prod = firm_prod[firm_prod['bool'] == 1].reset_index()
firm_prod.drop('bool', axis=1, inplace=True)
firm_prod.rename({'level_0': 'Firm_Code', 'level_1': 'Product_Code'}, axis=1, inplace=True)
firm_prod['Firm_Code'] = firm_prod['Firm_Code'].astype('string')
G_FirmProd = nx.MultiDiGraph()
G_FirmProd.add_nodes_from(firm_prod.index)
# Add node attributes
firm_prod_labels_dict = {}
for code in firm_prod.index:
firm_prod_labels_dict[code] = firm_prod.loc[code].to_dict()
nx.set_node_attributes(G_FirmProd, firm_prod_labels_dict)
self.firm_prod_network = G_FirmProd
def add_edges_based_on_bom(self, G_Firm):
# Logic to add edges to the G_Firm graph based on BOM
pass
def initialize_agents(self):
# Initialize product and firm agents
for node, attr in self.product_network.nodes(data=True):
product = ProductAgent(node, self, code=node, name=attr['Name'])
self.schedule.add(product)
for node, attr in self.firm_network.nodes(data=True):
firm_agent = FirmAgent(
node,
self,
code=node,
type_region=attr['Type_Region'],
revenue_log=attr['Revenue_Log'],
a_lst_product=[] # Populate based on products
)
self.schedule.add(firm_agent)
# Initialize disruptions
self.initialize_disruptions()
def initialize_disruptions(self):
# Set the initial firm product disruptions
for firm, products in self.dct_lst_init_disrupt_firm_prod.items():
for product in products:
if isinstance(firm, FirmAgent):
firm.dct_prod_up_prod_stat[product]['p_stat'].append(('D', self.schedule.steps))
def step(self):
self.schedule.step()
self.datacollector.collect(self)