import json import os import datetime import networkx as nx import pandas as pd from mesa import Model from typing import TYPE_CHECKING from my_model import MyModel if TYPE_CHECKING: from controller_db import ControllerDB class Computation: def __init__(self, c_db: 'ControllerDB'): # 控制不同进程 计算不同的样本 但使用同一个 数据库 c_db self.c_db = c_db self.pid = os.getpid() def run(self, str_code='0', s_id=None): sample_random = self.c_db.fetch_a_sample(s_id) if sample_random is None: return True # lock this row by update is_done_flag to 0 将运行后的样本设置为 flag 0 self.c_db.lock_the_sample(sample_random) print( f"Pid {self.pid} ({str_code}) is running " f"sample {sample_random.id} at {datetime.datetime.now()}") # 将sample 对应的 experiment 的一系列值 和 参数值 传入 模型 中 包括列名 和 值 dct_exp = {column: getattr(sample_random.experiment, column) for column in sample_random.experiment.__table__.c.keys()} # 删除不需要的 主键 del dct_exp['id'] dct_sample_para = {'sample': sample_random, 'seed': sample_random.seed, **dct_exp} product_network_test = nx.adjacency_graph(json.loads(dct_sample_para['g_bom'])) model = MyModel(dct_sample_para) for i in range(1): model.step() print(i, datetime.datetime.now()) model.end() return False def initialize_firm_network(self): # Read the firm data firm = pd.read_csv("input_data/input_firm_data/Firm_amended.csv") firm['Code'] = firm['Code'].astype(str) firm.fillna(0, inplace=True) firm_attr = firm.loc[:, ["Code", "Type_Region", "Revenue_Log"]] firm_industry_relation = pd.read_csv("input_data/firm_industry_relation.csv") firm_industry_relation['Firm_Code'] = firm_industry_relation['Firm_Code'].astype('string') firm_product = [] grouped = firm_industry_relation.groupby('Firm_Code')['Product_Code'].apply(list) firm_product.append(grouped) firm_attr['Product_Code'] = firm_attr['Code'].map(grouped) firm_attr.set_index('Code', inplace=True) grouped = firm_industry_relation.groupby('Firm_Code') self.firm_prod_labels_dict = {code: group['Product_Code'].tolist() for code, group in grouped} # 遍历'Product_Code' 与 index 交换 for index, row in firm_attr.iterrows(): id_index_list = [] for i in row['Product_Code']: for key_values in self.id_code.items(): if int(key_values[0]) == i: for id in key_values[1]: id_index_list.append(id) firm_attr.at[index, 'Product_Code'] = id_index_list self.G_Firm.add_nodes_from(firm["Code"]) # Assign attributes to the firm nodes firm_labels_dict = {code: firm_attr.loc[code].to_dict() for code in self.G_Firm.nodes} nx.set_node_attributes(self.G_Firm, firm_labels_dict) self.Firm = firm def initialize_firm_product_network(self): firm_industry_relation = pd.read_csv("input_data/firm_industry_relation.csv") firm_industry_relation['Firm_Code'] = firm_industry_relation['Firm_Code'].astype('string') firm_industry_relation['Product_Code'] = firm_industry_relation['Product_Code'].apply(lambda x: [x]) # 将 'firm_prod' 表中的每一行作为图中的节点 self.G_FirmProd.add_nodes_from(firm_industry_relation.index) # 为每个节点分配属性 # 遍历'Product_Code' 与 index 交换 for index, row in firm_industry_relation.iterrows(): id_index_list = [] for i in row['Product_Code']: for key_values in self.id_code.items(): if int(key_values[0]) == i: for id in key_values[1]: id_index_list.append(id) firm_industry_relation.at[index, 'Product_Code'] = id_index_list firm_prod_labels_dict = {code: firm_industry_relation.loc[code].to_dict() for code in firm_industry_relation.index} nx.set_node_attributes(self.G_FirmProd, firm_prod_labels_dict) def add_edges_to_firm_network(self): """ Add edges between firms based on the product BOM relationships """ # Add edges to G_Firm according to G_bom for node in nx.nodes(self.G_Firm): lst_pred_product_code = [] for product_code in self.G_Firm.nodes[node]['Product_Code']: lst_pred_product_code += list(self.G_bom.predecessors(product_code)) lst_pred_product_code = list(set(lst_pred_product_code)) lst_pred_product_code = list(sorted(lst_pred_product_code)) # Ensure consistency for pred_product_code in lst_pred_product_code: # Get a list of firms producing the component (pred_product_code) lst_pred_firm = [firm_code for firm_code, product in self.firm_prod_labels_dict.items() if pred_product_code in product] # Select multiple suppliers (multi-sourcing) n_pred_firm = self.int_netw_prf_n if n_pred_firm > len(lst_pred_firm): n_pred_firm = len(lst_pred_firm) if self.is_prf_size: # 获取 firm 的 size 列表 lst_pred_firm_size = [self.G_Firm.nodes[pred_firm]['Revenue_Log'] for pred_firm in lst_pred_firm] # 检查 lst_pred_firm_size 是否为空或总和为 0 if len(lst_pred_firm_size) == 0 or sum(lst_pred_firm_size) == 0: # print("警告: lst_pred_firm_size 为空或总和为 0,无法生成概率分布") lst_choose_firm = [] # 返回空结果,或根据需要处理 else: # 计算总和 sum_pred_firm_size = sum(lst_pred_firm_size) # 归一化生成 lst_prob lst_prob = [size / sum_pred_firm_size for size in lst_pred_firm_size] # 使用 np.isclose() 确保概率总和接近 1 if not np.isclose(sum(lst_prob), 1.0): # print(f"警告: 概率总和为 {sum(lst_prob)},现在进行修正") lst_prob = [prob / sum(lst_prob) for prob in lst_prob] # 确保没有负值或 0 lst_prob = [max(0, prob) for prob in lst_prob] # 根据修正后的概率选择 firm lst_choose_firm = self.nprandom.choice(lst_pred_firm, n_pred_firm, replace=False, p=lst_prob) else: # 直接进行随机选择 lst_choose_firm = self.nprandom.choice(lst_pred_firm, n_pred_firm, replace=False) # Add edges from predecessor firms to current node (firm) lst_add_edge = [(pred_firm, node, {'Product': pred_product_code}) for pred_firm in lst_choose_firm] self.G_Firm.add_edges_from(lst_add_edge) # Add edges to firm-product network self.add_edges_to_firm_product_network(node, pred_product_code, lst_choose_firm) def add_edges_to_firm_product_network(self, node, pred_product_code, lst_choose_firm): """ Helper function to add edges to the firm-product network """ set_node_prod_code = set(self.G_Firm.nodes[node]['Product_Code']) set_pred_succ_code = set(self.G_bom.successors(pred_product_code)) lst_use_pred_prod_code = list(set_node_prod_code & set_pred_succ_code) if len(lst_use_pred_prod_code) == 0: print("错误") pred_node_list = [] for pred_firm in lst_choose_firm: for n, v in self.G_FirmProd.nodes(data=True): for v1 in v['Product_Code']: if v1 == pred_product_code and v['Firm_Code'] == pred_firm: pred_node_list.append(n) if len(pred_node_list) != 0: pred_node = pred_node_list[0] else: pred_node = -1 current_node_list = [] for use_pred_prod_code in lst_use_pred_prod_code: for n, v in self.G_FirmProd.nodes(data=True): for v1 in v['Product_Code']: if v1 == use_pred_prod_code and v['Firm_Code'] == node: current_node_list.append(n) if len(current_node_list) != 0: current_node = current_node_list[0] else: current_node = -1 if current_node != -1 and pred_node != -1: self.G_FirmProd.add_edge(pred_node, current_node) def connect_unconnected_nodes(self): """ Connect unconnected nodes in the firm network """ for node in nx.nodes(self.G_Firm): if self.G_Firm.degree(node) == 0: current_node_list = [] for product_code in self.G_Firm.nodes[node]['Product_Code']: for n, v in self.G_FirmProd.nodes(data=True): for v1 in v['Product_Code']: if v['Firm_Code'] == node and v1 == product_code: current_node_list.append(n) if len(current_node_list) != 0: current_node = current_node_list[0] else: current_node = -1 lst_succ_product_code = list(self.G_bom.successors(product_code)) for succ_product_code in lst_succ_product_code: lst_succ_firm = [firm_code for firm_code, product in self.firm_prod_labels_dict.items() if succ_product_code in product] n_succ_firm = self.int_netw_prf_n if n_succ_firm > len(lst_succ_firm): n_succ_firm = len(lst_succ_firm) if self.is_prf_size: lst_succ_firm_size = [self.G_Firm.nodes[succ_firm]['Revenue_Log'] for succ_firm in lst_succ_firm] if len(lst_succ_firm_size) == 0 or sum(lst_succ_firm_size) == 0: # print("警告: lst_pred_firm_size 为空或总和为 0,无法生成概率分布") lst_choose_firm = [] # 返回空结果,或根据需要处理 else: # 计算总和 sum_pred_firm_size = sum(lst_succ_firm_size) # 归一化生成 lst_prob lst_prob = [size / sum_pred_firm_size for size in lst_succ_firm_size] # 使用 np.isclose() 确保概率总和接近 1 if not np.isclose(sum(lst_prob), 1.0): # print(f"警告: 概率总和为 {sum(lst_prob)},现在进行修正") lst_prob = [prob / sum(lst_prob) for prob in lst_prob] # 确保没有负值或 0 lst_prob = [max(0, prob) for prob in lst_prob] lst_choose_firm = self.nprandom.choice(lst_succ_firm, n_succ_firm, replace=False, p=lst_prob) else: lst_choose_firm = self.nprandom.choice(lst_succ_firm, n_succ_firm, replace=False) lst_add_edge = [(node, succ_firm, {'Product': product_code}) for succ_firm in lst_choose_firm] self.G_Firm.add_edges_from(lst_add_edge) # Add edges to firm-product network succ_node_list = [] for succ_firm in lst_choose_firm: for n, v in self.G_FirmProd.nodes(data=True): for v1 in v['Product_Code']: if v1 == succ_product_code and v['Firm_Code'] == succ_firm: succ_node_list.append(n) if len(succ_node_list) != 0: succ_node = succ_node_list[0] else: succ_node = -1 if current_node != -1 and succ_node != -1: self.G_FirmProd.add_edge(current_node, succ_node) self.sample.g_firm = json.dumps(nx.adjacency_data(self.G_Firm)) self.firm_network = self.G_Firm # 直接使用 networkx 图对象 self.firm_prod_network = self.G_FirmProd # 直接使用 networkx 图对象