135 lines
4.7 KiB
Python
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)
|