without模型转型成功!但是without还无法插入表 o
This commit is contained in:
		
							parent
							
								
									60b402c043
								
							
						
					
					
						commit
						ede00b0403
					
				| 
						 | 
					@ -3,6 +3,13 @@
 | 
				
			||||||
  <component name="CsvFileAttributes">
 | 
					  <component name="CsvFileAttributes">
 | 
				
			||||||
    <option name="attributeMap">
 | 
					    <option name="attributeMap">
 | 
				
			||||||
      <map>
 | 
					      <map>
 | 
				
			||||||
 | 
					        <entry key="\input_data\BomCateNet.csv">
 | 
				
			||||||
 | 
					          <value>
 | 
				
			||||||
 | 
					            <Attribute>
 | 
				
			||||||
 | 
					              <option name="separator" value="," />
 | 
				
			||||||
 | 
					            </Attribute>
 | 
				
			||||||
 | 
					          </value>
 | 
				
			||||||
 | 
					        </entry>
 | 
				
			||||||
        <entry key="\input_data\BomNodes.csv">
 | 
					        <entry key="\input_data\BomNodes.csv">
 | 
				
			||||||
          <value>
 | 
					          <value>
 | 
				
			||||||
            <Attribute>
 | 
					            <Attribute>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										121
									
								
								firm.py
								
								
								
								
							
							
						
						
									
										121
									
								
								firm.py
								
								
								
								
							| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
from mesa import Agent
 | 
					from mesa import Agent
 | 
				
			||||||
import numpy as np
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FirmAgent(Agent):
 | 
					class FirmAgent(Agent):
 | 
				
			||||||
| 
						 | 
					@ -55,47 +54,71 @@ class FirmAgent(Agent):
 | 
				
			||||||
            self.dct_prod_capacity[product] = extra_cap
 | 
					            self.dct_prod_capacity[product] = extra_cap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def remove_edge_to_cus(self, disrupted_prod):
 | 
					    def remove_edge_to_cus(self, disrupted_prod):
 | 
				
			||||||
 | 
					        # parameter disrupted_prod is the product that self got disrupted
 | 
				
			||||||
        lst_out_edge = list(
 | 
					        lst_out_edge = list(
 | 
				
			||||||
            self.firm_network.neighbors(self.unique_id))
 | 
					            self.firm_network.out_edges(
 | 
				
			||||||
        for n2 in lst_out_edge:
 | 
					                self.unique_id, keys=True, data='Product'))
 | 
				
			||||||
            edge_data = self.firm_network.edges[self.unique_id, n2]
 | 
					        for n1, n2, key, product_code in lst_out_edge:
 | 
				
			||||||
            if edge_data.get('Product') == disrupted_prod.code:
 | 
					            if product_code == disrupted_prod.unique_id:
 | 
				
			||||||
                customer = self.model.schedule.get_agent(n2)
 | 
					                # update customer up product supplier status
 | 
				
			||||||
 | 
					                customer = next(agent for agent in self.model.company_agents if agent.unique_id == n2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for prod in customer.dct_prod_up_prod_stat.keys():
 | 
					                for prod in customer.dct_prod_up_prod_stat.keys():
 | 
				
			||||||
                    if disrupted_prod in customer.dct_prod_up_prod_stat[prod]['s_stat'].keys():
 | 
					                    if disrupted_prod in customer.dct_prod_up_prod_stat[prod]['s_stat'].keys():
 | 
				
			||||||
                        customer.dct_prod_up_prod_stat[prod]['s_stat'][disrupted_prod][
 | 
					                        customer.dct_prod_up_prod_stat[prod]['s_stat'][disrupted_prod][
 | 
				
			||||||
                            'set_disrupt_firm'].add(self)
 | 
					                            'set_disrupt_firm'].add(self)
 | 
				
			||||||
                self.firm_network.remove_edge(self.unique_id, n2)
 | 
					                        # print(f"{self.name} disrupt {customer.name}'s "
 | 
				
			||||||
 | 
					                        #       f"{prod.code} due to {disrupted_prod.code}")
 | 
				
			||||||
 | 
					                # remove edge to customer
 | 
				
			||||||
 | 
					                self.firm_network.remove_edge(n1, n2, key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def disrupt_cus_prod(self, prod, disrupted_up_prod):
 | 
					    def disrupt_cus_prod(self, prod, disrupted_up_prod):
 | 
				
			||||||
        num_lost = len(self.dct_prod_up_prod_stat[prod]['s_stat'][disrupted_up_prod]['set_disrupt_firm'])
 | 
					        # parameter prod is the product that has disrupted_up_prod
 | 
				
			||||||
        num_remain = len([
 | 
					        # parameter disrupted_up_prod is the product that
 | 
				
			||||||
            u for u in self.firm_network.neighbors(self.unique_id)
 | 
					        # self's component exists disrupted supplier
 | 
				
			||||||
            if self.firm_network.G.edges[u, self.unique_id].get('Product') == disrupted_up_prod.code])
 | 
					        num_lost = \
 | 
				
			||||||
 | 
					            len(self.dct_prod_up_prod_stat[prod]['s_stat']
 | 
				
			||||||
 | 
					                [disrupted_up_prod]['set_disrupt_firm'])
 | 
				
			||||||
 | 
					        num_remain = \
 | 
				
			||||||
 | 
					            len([u for u, _, _, d in
 | 
				
			||||||
 | 
					                 self.firm_network.in_edges(self.get_firm_network_unique_id(),
 | 
				
			||||||
 | 
					                                            keys=True,
 | 
				
			||||||
 | 
					                                            data='Product')
 | 
				
			||||||
 | 
					                 if d == disrupted_up_prod.unique_id])
 | 
				
			||||||
        lost_percent = num_lost / (num_lost + num_remain)
 | 
					        lost_percent = num_lost / (num_lost + num_remain)
 | 
				
			||||||
        lst_size = [firm.size_stat[-1][0] for firm in self.model.schedule.agents]
 | 
					        lst_size = \
 | 
				
			||||||
        std_size = (self.size_stat[-1][0] - min(lst_size) + 1) / (max(lst_size) - min(lst_size) + 1)
 | 
					            [firm.size_stat[-1][0] for firm in self.model.company_agents]
 | 
				
			||||||
 | 
					        std_size = (self.size_stat[-1][0] - min(lst_size) + 1) \
 | 
				
			||||||
 | 
					                   / (max(lst_size) - min(lst_size) + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # calculate probability of disruption
 | 
				
			||||||
        prob_disrupt = 1 - std_size * (1 - lost_percent)
 | 
					        prob_disrupt = 1 - std_size * (1 - lost_percent)
 | 
				
			||||||
        if self.random.choice([True, False], p=[prob_disrupt, 1 - prob_disrupt]):
 | 
					        if self.model.nprandom.choice([True, False],
 | 
				
			||||||
 | 
					                                      p=[prob_disrupt,
 | 
				
			||||||
 | 
					                                         1 - prob_disrupt]):
 | 
				
			||||||
            self.dct_n_trial_up_prod_disrupted[disrupted_up_prod] = 0
 | 
					            self.dct_n_trial_up_prod_disrupted[disrupted_up_prod] = 0
 | 
				
			||||||
            self.dct_prod_up_prod_stat[prod]['s_stat'][disrupted_up_prod]['stat'] = False
 | 
					            self.dct_prod_up_prod_stat[
 | 
				
			||||||
            status, _ = self.dct_prod_up_prod_stat[prod]['p_stat'][-1]
 | 
					                prod]['s_stat'][disrupted_up_prod]['stat'] = False
 | 
				
			||||||
 | 
					            status, _ = self.dct_prod_up_prod_stat[
 | 
				
			||||||
 | 
					                prod]['p_stat'][-1]
 | 
				
			||||||
            if status != 'D':
 | 
					            if status != 'D':
 | 
				
			||||||
                self.dct_prod_up_prod_stat[prod]['p_stat'].append(('D', self.model.schedule.time))
 | 
					                self.dct_prod_up_prod_stat[
 | 
				
			||||||
 | 
					                    prod]['p_stat'].append(('D', self.model.t))
 | 
				
			||||||
 | 
					                # print(f"{self.name}'s {prod.code} turn to D status due to "
 | 
				
			||||||
 | 
					                #       f"disrupted supplier of {disrupted_up_prod.code}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def seek_alt_supply(self, product):
 | 
					    def seek_alt_supply(self, product):
 | 
				
			||||||
        if self.dct_n_trial_up_prod_disrupted[product] <= self.model.int_n_max_trial:
 | 
					        if self.dct_n_trial_up_prod_disrupted[product] <= self.model.int_n_max_trial:
 | 
				
			||||||
            if self.dct_n_trial_up_prod_disrupted[product] == 0:
 | 
					            if self.dct_n_trial_up_prod_disrupted[product] == 0:
 | 
				
			||||||
                self.dct_cand_alt_supp_up_prod_disrupted[product] = [
 | 
					                self.dct_cand_alt_supp_up_prod_disrupted[product] = [
 | 
				
			||||||
                    firm for firm in self.model.schedule.agents
 | 
					                    firm for firm in self.model.company_agents
 | 
				
			||||||
                    if firm.is_prod_in_current_normal(product)]
 | 
					                    if firm.is_prod_in_current_normal(product)]
 | 
				
			||||||
            if self.dct_cand_alt_supp_up_prod_disrupted[product]:
 | 
					            if self.dct_cand_alt_supp_up_prod_disrupted[product]:
 | 
				
			||||||
                lst_firm_connect = []
 | 
					                lst_firm_connect = []
 | 
				
			||||||
                if self.is_prf_conn:
 | 
					                if self.is_prf_conn:
 | 
				
			||||||
                    for firm in self.dct_cand_alt_supp_up_prod_disrupted[product]:
 | 
					                    for firm in self.dct_cand_alt_supp_up_prod_disrupted[product]:
 | 
				
			||||||
                        if self.firm_network.G.has_edge(self.unique_id, firm.unique_id) or \
 | 
					                        if self.firm_network.has_edge(self.unique_id, firm.unique_id) or \
 | 
				
			||||||
                                self.firm_network.G.has_edge(firm.unique_id, self.unique_id):
 | 
					                                self.firm_network.has_edge(firm.unique_id, self.unique_id):
 | 
				
			||||||
                            lst_firm_connect.append(firm)
 | 
					                            lst_firm_connect.append(firm)
 | 
				
			||||||
                if len(lst_firm_connect) == 0:
 | 
					                if len(lst_firm_connect) == 0:
 | 
				
			||||||
                    if self.is_prf_size:
 | 
					                    if self.is_prf_size:
 | 
				
			||||||
| 
						 | 
					@ -133,8 +156,8 @@ class FirmAgent(Agent):
 | 
				
			||||||
                    lst_firm_connect = []
 | 
					                    lst_firm_connect = []
 | 
				
			||||||
                    if self.is_prf_conn:
 | 
					                    if self.is_prf_conn:
 | 
				
			||||||
                        for firm in lst_firm:
 | 
					                        for firm in lst_firm:
 | 
				
			||||||
                            if self.firm_network.G.has_edge(self.unique_id, firm.unique_id) or \
 | 
					                            if self.firm_network.has_edge(self.unique_id, firm.unique_id) or \
 | 
				
			||||||
                                    self.firm_network.G.has_edge(firm.unique_id, self.unique_id):
 | 
					                                    self.firm_network.has_edge(firm.unique_id, self.unique_id):
 | 
				
			||||||
                                lst_firm_connect.append(firm)
 | 
					                                lst_firm_connect.append(firm)
 | 
				
			||||||
                    if len(lst_firm_connect) == 0:
 | 
					                    if len(lst_firm_connect) == 0:
 | 
				
			||||||
                        if self.is_prf_size:
 | 
					                        if self.is_prf_size:
 | 
				
			||||||
| 
						 | 
					@ -156,26 +179,26 @@ class FirmAgent(Agent):
 | 
				
			||||||
                for down_firm in lst_firm:
 | 
					                for down_firm in lst_firm:
 | 
				
			||||||
                    down_firm.dct_cand_alt_supp_up_prod_disrupted[product].remove(self)
 | 
					                    down_firm.dct_cand_alt_supp_up_prod_disrupted[product].remove(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    def accept_request(self, down_firm, product):
 | 
					    def accept_request(self, down_firm, product):
 | 
				
			||||||
                        if self.firm_network.G.has_edge(self.unique_id, down_firm.unique_id) or \
 | 
					        if self.firm_network.has_edge(self.unique_id, down_firm.unique_id) or \
 | 
				
			||||||
                                self.firm_network.G.has_edge(down_firm.unique_id, self.unique_id):
 | 
					                self.firm_network.has_edge(down_firm.unique_id, self.unique_id):
 | 
				
			||||||
                            prod_accept = 1.0
 | 
					            prod_accept = 1.0
 | 
				
			||||||
                        else:
 | 
					        else:
 | 
				
			||||||
                            prod_accept = self.flt_diff_new_conn
 | 
					            prod_accept = self.flt_diff_new_conn
 | 
				
			||||||
                        if self.random.choice([True, False], p=[prod_accept, 1 - prod_accept]):
 | 
					        if self.model.nprandom.choice([True, False], p=[prod_accept, 1 - prod_accept]):
 | 
				
			||||||
                            self.firm_network.G.add_edge(self.unique_id, down_firm.unique_id, Product=product.code)
 | 
					            self.firm_network.add_edge(self.unique_id, down_firm.unique_id, Product=product.unique_id)
 | 
				
			||||||
                            self.dct_prod_capacity[product] -= 1
 | 
					            self.dct_prod_capacity[product] -= 1
 | 
				
			||||||
                            self.dct_request_prod_from_firm[product].remove(down_firm)
 | 
					            self.dct_request_prod_from_firm[product].remove(down_firm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            for prod in down_firm.dct_prod_up_prod_stat.keys():
 | 
					            for prod in down_firm.dct_prod_up_prod_stat.keys():
 | 
				
			||||||
                                if product in down_firm.dct_prod_up_prod_stat[prod]['s_stat']:
 | 
					                if product in down_firm.dct_prod_up_prod_stat[prod]['s_stat']:
 | 
				
			||||||
                                    down_firm.dct_prod_up_prod_stat[prod]['s_stat'][product]['stat'] = True
 | 
					                    down_firm.dct_prod_up_prod_stat[prod]['s_stat'][product]['stat'] = True
 | 
				
			||||||
                                    down_firm.dct_prod_up_prod_stat[prod]['p_stat'].append(
 | 
					                    down_firm.dct_prod_up_prod_stat[prod]['p_stat'].append(
 | 
				
			||||||
                                        ('N', self.model.schedule.time))
 | 
					                        ('N', self.model.t))
 | 
				
			||||||
                            del down_firm.dct_n_trial_up_prod_disrupted[product]
 | 
					            del down_firm.dct_n_trial_up_prod_disrupted[product]
 | 
				
			||||||
                            del down_firm.dct_cand_alt_supp_up_prod_disrupted[product]
 | 
					            del down_firm.dct_cand_alt_supp_up_prod_disrupted[product]
 | 
				
			||||||
                        else:
 | 
					        else:
 | 
				
			||||||
                            down_firm.dct_cand_alt_supp_up_prod_disrupted[product].remove(self)
 | 
					            down_firm.dct_cand_alt_supp_up_prod_disrupted[product].remove(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def clean_before_trial(self):
 | 
					    def clean_before_trial(self):
 | 
				
			||||||
        self.dct_request_prod_from_firm = {}
 | 
					        self.dct_request_prod_from_firm = {}
 | 
				
			||||||
| 
						 | 
					@ -188,13 +211,25 @@ class FirmAgent(Agent):
 | 
				
			||||||
        # Update the status of products and refresh disruption sets
 | 
					        # Update the status of products and refresh disruption sets
 | 
				
			||||||
        for prod in self.dct_prod_up_prod_stat.keys():
 | 
					        for prod in self.dct_prod_up_prod_stat.keys():
 | 
				
			||||||
            status, ts = self.dct_prod_up_prod_stat[prod]['p_stat'][-1]
 | 
					            status, ts = self.dct_prod_up_prod_stat[prod]['p_stat'][-1]
 | 
				
			||||||
            if ts != self.model.schedule.time:
 | 
					            if ts != self.model.t:
 | 
				
			||||||
                self.dct_prod_up_prod_stat[prod]['p_stat'].append((status, self.model.schedule.time))
 | 
					                self.dct_prod_up_prod_stat[prod]['p_stat'].append((status, self.model.t))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Refresh the set of disrupted firms
 | 
					            # Refresh the set of disrupted firms
 | 
				
			||||||
            for up_prod in self.dct_prod_up_prod_stat[prod]['s_stat'].keys():
 | 
					            for up_prod in self.dct_prod_up_prod_stat[prod]['s_stat'].keys():
 | 
				
			||||||
                self.dct_prod_up_prod_stat[prod]['s_stat'][up_prod]['set_disrupt_firm'] = set()
 | 
					                self.dct_prod_up_prod_stat[prod]['s_stat'][up_prod]['set_disrupt_firm'] = set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_firm_network_unique_id(self):
 | 
				
			||||||
 | 
					        return self.unique_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def is_prod_in_current_normal(self, prod):
 | 
				
			||||||
 | 
					        if prod in self.dct_prod_up_prod_stat.keys():
 | 
				
			||||||
 | 
					            if self.dct_prod_up_prod_stat[prod]['p_stat'][-1][0] == 'N':
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                return False
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def step(self):
 | 
					    def step(self):
 | 
				
			||||||
        # 在每个时间步进行的操作
 | 
					        # 在每个时间步进行的操作
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										157
									
								
								my_model.py
								
								
								
								
							
							
						
						
									
										157
									
								
								my_model.py
								
								
								
								
							| 
						 | 
					@ -6,8 +6,8 @@ import pandas as pd
 | 
				
			||||||
from mesa import Model
 | 
					from mesa import Model
 | 
				
			||||||
from mesa.space import MultiGrid, NetworkGrid
 | 
					from mesa.space import MultiGrid, NetworkGrid
 | 
				
			||||||
from mesa.datacollection import DataCollector
 | 
					from mesa.datacollection import DataCollector
 | 
				
			||||||
from mesa.time import RandomActivation
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import numpy as np
 | 
				
			||||||
from firm import FirmAgent
 | 
					from firm import FirmAgent
 | 
				
			||||||
from product import ProductAgent
 | 
					from product import ProductAgent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,10 +35,20 @@ class MyModel(Model):
 | 
				
			||||||
        self.data_collector = DataCollector(
 | 
					        self.data_collector = DataCollector(
 | 
				
			||||||
            agent_reporters={"Product": "name"}
 | 
					            agent_reporters={"Product": "name"}
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					        # initialize graph bom
 | 
				
			||||||
 | 
					        self.G_bom = nx.adjacency_graph(json.loads(params['g_bom']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Create the firm-product network graph
 | 
				
			||||||
 | 
					        self.G_FirmProd = nx.MultiDiGraph()
 | 
				
			||||||
 | 
					        # Create the firm network graph
 | 
				
			||||||
 | 
					        self.G_Firm = nx.MultiDiGraph()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.company_agents = []
 | 
					        self.company_agents = []
 | 
				
			||||||
        self.product_agents = []
 | 
					        self.product_agents = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.nprandom = np.random.default_rng(params['seed'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Initialize parameters from `params`
 | 
					        # Initialize parameters from `params`
 | 
				
			||||||
        self.sample = params['sample']
 | 
					        self.sample = params['sample']
 | 
				
			||||||
        self.int_stop_ts = 0
 | 
					        self.int_stop_ts = 0
 | 
				
			||||||
| 
						 | 
					@ -62,121 +72,136 @@ class MyModel(Model):
 | 
				
			||||||
    def initialize_product_network(self, params):
 | 
					    def initialize_product_network(self, params):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self.product_network = nx.adjacency_graph(json.loads(params['g_bom']))
 | 
					            self.product_network = nx.adjacency_graph(json.loads(params['g_bom']))
 | 
				
			||||||
            print(
 | 
					 | 
				
			||||||
                f"Product network initialized with {self.product_network.number_of_nodes()} nodes and {self.product_network.number_of_edges()} edges.")
 | 
					 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            print(f"Failed to initialize product network: {e}")
 | 
					            print(f"Failed to initialize product network: {e}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def initialize_firm_network(self):
 | 
					    def initialize_firm_network(self):
 | 
				
			||||||
        """ Initialize the firm network and add it to the model. """
 | 
					        """ Initialize the firm network by reading firm data from a CSV file """
 | 
				
			||||||
 | 
					        # Read the firm data
 | 
				
			||||||
        Firm = pd.read_csv("input_data/Firm_amended.csv")
 | 
					        Firm = pd.read_csv("input_data/Firm_amended.csv")
 | 
				
			||||||
        Firm['Code'] = Firm['Code'].astype('string')
 | 
					        Firm['Code'] = Firm['Code'].astype('string')
 | 
				
			||||||
        Firm.fillna(0, inplace=True)
 | 
					        Firm.fillna(0, inplace=True)
 | 
				
			||||||
        Firm_attr = Firm.loc[:, ["Code", "Type_Region", "Revenue_Log"]]
 | 
					        Firm_attr = Firm.loc[:, ["Code", "Type_Region", "Revenue_Log"]]
 | 
				
			||||||
        firm_product = [row[row == 1].index.to_list() for _, row in Firm.loc[:, '1':].iterrows()]
 | 
					
 | 
				
			||||||
 | 
					        firm_product = []
 | 
				
			||||||
 | 
					        for _, row in Firm.loc[:, '1':].iterrows():
 | 
				
			||||||
 | 
					            firm_product.append(row[row == 1].index.to_list())
 | 
				
			||||||
        Firm_attr.loc[:, 'Product_Code'] = firm_product
 | 
					        Firm_attr.loc[:, 'Product_Code'] = firm_product
 | 
				
			||||||
        Firm_attr.set_index('Code', inplace=True)
 | 
					        Firm_attr.set_index('Code', inplace=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.firm_network = nx.MultiDiGraph()
 | 
					 | 
				
			||||||
        self.firm_network.add_nodes_from(Firm["Code"])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        firm_labels_dict = {code: Firm_attr.loc[code].to_dict() for code in self.firm_network.nodes}
 | 
					        self.G_Firm.add_nodes_from(Firm["Code"])
 | 
				
			||||||
        nx.set_node_attributes(self.firm_network, firm_labels_dict)
 | 
					
 | 
				
			||||||
 | 
					        # 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):
 | 
					    def initialize_firm_product_network(self):
 | 
				
			||||||
        """ Initialize the firm-product network and add it to the model. """
 | 
					        """ Initialize the firm-product network """
 | 
				
			||||||
 | 
					        # Read the firm-product data
 | 
				
			||||||
        Firm_Prod = pd.read_csv("input_data/Firm_amended.csv")
 | 
					        Firm_Prod = pd.read_csv("input_data/Firm_amended.csv")
 | 
				
			||||||
        Firm_Prod.fillna(0, inplace=True)
 | 
					        Firm_Prod.fillna(0, inplace=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Stack the firm-product relationships into a DataFrame
 | 
				
			||||||
        firm_prod = pd.DataFrame({'bool': Firm_Prod.loc[:, '1':].stack()})
 | 
					        firm_prod = pd.DataFrame({'bool': Firm_Prod.loc[:, '1':].stack()})
 | 
				
			||||||
        firm_prod = firm_prod[firm_prod['bool'] == 1].reset_index()
 | 
					        firm_prod = firm_prod[firm_prod['bool'] == 1].reset_index()
 | 
				
			||||||
        firm_prod.drop('bool', axis=1, inplace=True)
 | 
					        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.rename({'level_0': 'Firm_Code', 'level_1': 'Product_Code'}, axis=1, inplace=True)
 | 
				
			||||||
        firm_prod['Firm_Code'] = firm_prod['Firm_Code'].astype('string')
 | 
					        firm_prod['Firm_Code'] = firm_prod['Firm_Code'].astype('string')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.firm_prod_network = nx.MultiDiGraph()
 | 
					        self.G_FirmProd.add_nodes_from(firm_prod.index)
 | 
				
			||||||
        self.firm_prod_network.add_nodes_from(firm_prod.index)
 | 
					        # Assign attributes to the firm-product nodes
 | 
				
			||||||
 | 
					 | 
				
			||||||
        firm_prod_labels_dict = {code: firm_prod.loc[code].to_dict() for code in firm_prod.index}
 | 
					        firm_prod_labels_dict = {code: firm_prod.loc[code].to_dict() for code in firm_prod.index}
 | 
				
			||||||
        nx.set_node_attributes(self.firm_prod_network, firm_prod_labels_dict)
 | 
					        nx.set_node_attributes(self.G_FirmProd, firm_prod_labels_dict)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.add_edges_to_firm_network()
 | 
					 | 
				
			||||||
        self.connect_unconnected_nodes()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        print(
 | 
					 | 
				
			||||||
            f"Firm network has {self.firm_network.number_of_nodes()} nodes and {self.firm_network.number_of_edges()} edges.")
 | 
					 | 
				
			||||||
        print(
 | 
					 | 
				
			||||||
            f"Product network has {self.product_network.number_of_nodes()} nodes and {self.product_network.number_of_edges()} edges.")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_edges_to_firm_network(self):
 | 
					    def add_edges_to_firm_network(self):
 | 
				
			||||||
        """ Add edges to the firm network based on product BOM. """
 | 
					        """ Add edges between firms based on the product BOM relationships """
 | 
				
			||||||
        Firm = pd.read_csv("input_data/Firm_amended.csv")
 | 
					        # Add edges to G_Firm according to G_bom
 | 
				
			||||||
        Firm['Code'] = Firm['Code'].astype('string')
 | 
					        for node in nx.nodes(self.G_Firm):
 | 
				
			||||||
        Firm.fillna(0, inplace=True)
 | 
					 | 
				
			||||||
        for node in nx.nodes(self.firm_network):
 | 
					 | 
				
			||||||
            lst_pred_product_code = []
 | 
					            lst_pred_product_code = []
 | 
				
			||||||
            for product_code in self.firm_network.nodes[node]['Product_Code']:
 | 
					            for product_code in self.G_Firm.nodes[node]['Product_Code']:
 | 
				
			||||||
                lst_pred_product_code += list(self.product_network.predecessors(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(set(lst_pred_product_code))
 | 
				
			||||||
            lst_pred_product_code = list(sorted(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:
 | 
					            for pred_product_code in lst_pred_product_code:
 | 
				
			||||||
                lst_pred_firm = Firm['Code'][Firm[pred_product_code] == 1].to_list()
 | 
					                # Get a list of firms producing the component (pred_product_code)
 | 
				
			||||||
 | 
					                lst_pred_firm = self.Firm['Code'][self.Firm[pred_product_code] == 1].to_list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # Select multiple suppliers (multi-sourcing)
 | 
				
			||||||
                n_pred_firm = self.int_netw_prf_n
 | 
					                n_pred_firm = self.int_netw_prf_n
 | 
				
			||||||
                if n_pred_firm > len(lst_pred_firm):
 | 
					                if n_pred_firm > len(lst_pred_firm):
 | 
				
			||||||
                    n_pred_firm = len(lst_pred_firm)
 | 
					                    n_pred_firm = len(lst_pred_firm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if self.is_prf_size:
 | 
					                if self.is_prf_size:
 | 
				
			||||||
                    lst_pred_firm_size = [self.firm_network.nodes[pred_firm]['Revenue_Log'] for pred_firm in
 | 
					                    lst_pred_firm_size = [self.G_Firm.nodes[pred_firm]['Revenue_Log'] for pred_firm in
 | 
				
			||||||
                                          lst_pred_firm]
 | 
					                                          lst_pred_firm]
 | 
				
			||||||
                    lst_prob = [size / sum(lst_pred_firm_size) for size in lst_pred_firm_size]
 | 
					                    lst_prob = [size / sum(lst_pred_firm_size) for size in lst_pred_firm_size]
 | 
				
			||||||
                    lst_choose_firm = self.random.choices(lst_pred_firm, k=n_pred_firm, weights=lst_prob)
 | 
					                    lst_choose_firm = self.nprandom.choice(lst_pred_firm, n_pred_firm, replace=False, p=lst_prob)
 | 
				
			||||||
                else:
 | 
					                else:
 | 
				
			||||||
                    lst_choose_firm = self.random.choices(lst_pred_firm, k=n_pred_firm)
 | 
					                    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]
 | 
					                lst_add_edge = [(pred_firm, node, {'Product': pred_product_code}) for pred_firm in lst_choose_firm]
 | 
				
			||||||
                self.firm_network.add_edges_from(lst_add_edge)
 | 
					                self.G_Firm.add_edges_from(lst_add_edge)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Add edges to firm-prod network
 | 
					                # Add edges to firm-product network
 | 
				
			||||||
                set_node_prod_code = set(self.firm_network.nodes[node]['Product_Code'])
 | 
					                self.add_edges_to_firm_product_network(node, pred_product_code, lst_choose_firm)
 | 
				
			||||||
                set_pred_succ_code = set(self.product_network.successors(pred_product_code))
 | 
					 | 
				
			||||||
                lst_use_pred_prod_code = list(set_node_prod_code & set_pred_succ_code)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for pred_firm in lst_choose_firm:
 | 
					    def add_edges_to_firm_product_network(self, node, pred_product_code, lst_choose_firm):
 | 
				
			||||||
                    pred_node = [n for n, v in self.firm_prod_network.nodes(data=True) if
 | 
					        """ Helper function to add edges to the firm-product network """
 | 
				
			||||||
                                 v['Firm_Code'] == pred_firm and v['Product_Code'] == pred_product_code][0]
 | 
					        set_node_prod_code = set(self.G_Firm.nodes[node]['Product_Code'])
 | 
				
			||||||
                    for use_pred_prod_code in lst_use_pred_prod_code:
 | 
					        set_pred_succ_code = set(self.G_bom.successors(pred_product_code))
 | 
				
			||||||
                        current_node = [n for n, v in self.firm_prod_network.nodes(data=True) if
 | 
					        lst_use_pred_prod_code = list(set_node_prod_code & set_pred_succ_code)
 | 
				
			||||||
                                        v['Firm_Code'] == node and v['Product_Code'] == use_pred_prod_code][0]
 | 
					
 | 
				
			||||||
                        self.firm_prod_network.add_edge(pred_node, current_node)
 | 
					        for pred_firm in lst_choose_firm:
 | 
				
			||||||
 | 
					            pred_node = [n for n, v in self.G_FirmProd.nodes(data=True) if
 | 
				
			||||||
 | 
					                         v['Firm_Code'] == pred_firm and v['Product_Code'] == pred_product_code][0]
 | 
				
			||||||
 | 
					            for use_pred_prod_code in lst_use_pred_prod_code:
 | 
				
			||||||
 | 
					                current_node = [n for n, v in self.G_FirmProd.nodes(data=True) if
 | 
				
			||||||
 | 
					                                v['Firm_Code'] == node and v['Product_Code'] == use_pred_prod_code][0]
 | 
				
			||||||
 | 
					                self.G_FirmProd.add_edge(pred_node, current_node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def connect_unconnected_nodes(self):
 | 
					    def connect_unconnected_nodes(self):
 | 
				
			||||||
        """ Connect unconnected nodes in the firm network. """
 | 
					        """ Connect unconnected nodes in the firm network """
 | 
				
			||||||
        Firm = pd.read_csv("input_data/Firm_amended.csv")
 | 
					        for node in nx.nodes(self.G_Firm):
 | 
				
			||||||
        Firm['Code'] = Firm['Code'].astype('string')
 | 
					            if self.G_Firm.degree(node) == 0:
 | 
				
			||||||
        Firm.fillna(0, inplace=True)
 | 
					                for product_code in self.G_Firm.nodes[node]['Product_Code']:
 | 
				
			||||||
        for node in nx.nodes(self.firm_network):
 | 
					                    current_node = [n for n, v in self.G_FirmProd.nodes(data=True) if
 | 
				
			||||||
            if self.firm_network.degree(node) == 0:
 | 
					 | 
				
			||||||
                for product_code in self.firm_network.nodes[node]['Product_Code']:
 | 
					 | 
				
			||||||
                    current_node = [n for n, v in self.firm_prod_network.nodes(data=True) if
 | 
					 | 
				
			||||||
                                    v['Firm_Code'] == node and v['Product_Code'] == product_code][0]
 | 
					                                    v['Firm_Code'] == node and v['Product_Code'] == product_code][0]
 | 
				
			||||||
                    lst_succ_product_code = list(self.product_network.successors(product_code))
 | 
					                    lst_succ_product_code = list(self.G_bom.successors(product_code))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    for succ_product_code in lst_succ_product_code:
 | 
					                    for succ_product_code in lst_succ_product_code:
 | 
				
			||||||
                        lst_succ_firm = Firm['Code'][Firm[succ_product_code] == 1].to_list()
 | 
					                        lst_succ_firm = self.Firm['Code'][self.Firm[succ_product_code] == 1].to_list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        n_succ_firm = self.int_netw_prf_n
 | 
					                        n_succ_firm = self.int_netw_prf_n
 | 
				
			||||||
                        if n_succ_firm > len(lst_succ_firm):
 | 
					                        if n_succ_firm > len(lst_succ_firm):
 | 
				
			||||||
                            n_succ_firm = len(lst_succ_firm)
 | 
					                            n_succ_firm = len(lst_succ_firm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if self.is_prf_size:
 | 
					                        if self.is_prf_size:
 | 
				
			||||||
                            lst_succ_firm_size = [self.firm_network.nodes[succ_firm]['Revenue_Log'] for succ_firm in
 | 
					                            lst_succ_firm_size = [self.G_Firm.nodes[succ_firm]['Revenue_Log'] for succ_firm in
 | 
				
			||||||
                                                  lst_succ_firm]
 | 
					                                                  lst_succ_firm]
 | 
				
			||||||
                            lst_prob = [size / sum(lst_succ_firm_size) for size in lst_succ_firm_size]
 | 
					                            lst_prob = [size / sum(lst_succ_firm_size) for size in lst_succ_firm_size]
 | 
				
			||||||
                            lst_choose_firm = self.random.choices(lst_succ_firm, k=n_succ_firm, weights=lst_prob)
 | 
					                            lst_choose_firm = self.nprandom.choice(lst_succ_firm, n_succ_firm, replace=False,
 | 
				
			||||||
 | 
					                                                                   p=lst_prob)
 | 
				
			||||||
                        else:
 | 
					                        else:
 | 
				
			||||||
                            lst_choose_firm = self.random.choices(lst_succ_firm, k=n_succ_firm)
 | 
					                            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.firm_network.add_edges_from(lst_add_edge)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        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
 | 
				
			||||||
                        for succ_firm in lst_choose_firm:
 | 
					                        for succ_firm in lst_choose_firm:
 | 
				
			||||||
                            succ_node = [n for n, v in self.firm_prod_network.nodes(data=True) if
 | 
					                            succ_node = [n for n, v in self.G_FirmProd.nodes(data=True) if
 | 
				
			||||||
                                         v['Firm_Code'] == succ_firm and v['Product_Code'] == succ_product_code][0]
 | 
					                                         v['Firm_Code'] == succ_firm and v['Product_Code'] == succ_product_code][0]
 | 
				
			||||||
                            self.firm_prod_network.add_edge(current_node, succ_node)
 | 
					                            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 图对象
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def initialize_agents(self):
 | 
					    def initialize_agents(self):
 | 
				
			||||||
        """ Initialize agents and add them to the model. """
 | 
					        """ Initialize agents and add them to the model. """
 | 
				
			||||||
| 
						 | 
					@ -189,7 +214,6 @@ class MyModel(Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for ag_node, attr in self.firm_network.nodes(data=True):
 | 
					        for ag_node, attr in self.firm_network.nodes(data=True):
 | 
				
			||||||
            a_lst_product = [agent for agent in self.product_agents if agent.unique_id in attr['Product_Code']]
 | 
					            a_lst_product = [agent for agent in self.product_agents if agent.unique_id in attr['Product_Code']]
 | 
				
			||||||
            print(a_lst_product)
 | 
					 | 
				
			||||||
            firm_agent = FirmAgent(
 | 
					            firm_agent = FirmAgent(
 | 
				
			||||||
                ag_node, self,
 | 
					                ag_node, self,
 | 
				
			||||||
                type_region=attr['Type_Region'],
 | 
					                type_region=attr['Type_Region'],
 | 
				
			||||||
| 
						 | 
					@ -208,7 +232,8 @@ class MyModel(Model):
 | 
				
			||||||
        # 遍历初始公司-产品干扰数据,将其转化为基于公司和产品的映射
 | 
					        # 遍历初始公司-产品干扰数据,将其转化为基于公司和产品的映射
 | 
				
			||||||
        for firm_code, lst_product in self.dct_lst_init_disrupt_firm_prod.items():
 | 
					        for firm_code, lst_product in self.dct_lst_init_disrupt_firm_prod.items():
 | 
				
			||||||
            # 从 company_agents 列表中选择指定公司
 | 
					            # 从 company_agents 列表中选择指定公司
 | 
				
			||||||
            firm = next(firm for firm in self.company_agents if firm.unique_id == firm_code)
 | 
					            firms = [firm for firm in self.company_agents if firm.unique_id == firm_code]
 | 
				
			||||||
 | 
					            firm = firms[0] if firms else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # 从总产品列表中选择该公司受干扰的产品
 | 
					            # 从总产品列表中选择该公司受干扰的产品
 | 
				
			||||||
            disrupted_products = [product for product in self.product_agents if product.unique_id in lst_product]
 | 
					            disrupted_products = [product for product in self.product_agents if product.unique_id in lst_product]
 | 
				
			||||||
| 
						 | 
					@ -219,6 +244,7 @@ class MyModel(Model):
 | 
				
			||||||
        # 更新 self.dct_lst_init_disrupt_firm_prod 字典,存储公司及其受干扰的产品
 | 
					        # 更新 self.dct_lst_init_disrupt_firm_prod 字典,存储公司及其受干扰的产品
 | 
				
			||||||
        self.dct_lst_init_disrupt_firm_prod = t_dct
 | 
					        self.dct_lst_init_disrupt_firm_prod = t_dct
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # 设置初始受干扰的公司产品状态
 | 
					        # 设置初始受干扰的公司产品状态
 | 
				
			||||||
        for firm, a_lst_product in self.dct_lst_init_disrupt_firm_prod.items():
 | 
					        for firm, a_lst_product in self.dct_lst_init_disrupt_firm_prod.items():
 | 
				
			||||||
            for product in a_lst_product:
 | 
					            for product in a_lst_product:
 | 
				
			||||||
| 
						 | 
					@ -236,7 +262,6 @@ class MyModel(Model):
 | 
				
			||||||
            self.product_agents.append(agent)
 | 
					            self.product_agents.append(agent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def step(self):
 | 
					    def step(self):
 | 
				
			||||||
        print(f"Running step {self.t}")
 | 
					 | 
				
			||||||
        # 1. Remove edge to customer and disrupt customer up product
 | 
					        # 1. Remove edge to customer and disrupt customer up product
 | 
				
			||||||
        for firm in self.company_agents:
 | 
					        for firm in self.company_agents:
 | 
				
			||||||
            for prod in firm.dct_prod_up_prod_stat.keys():
 | 
					            for prod in firm.dct_prod_up_prod_stat.keys():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue