diff --git a/__pycache__/controller_db.cpython-38.pyc b/__pycache__/controller_db.cpython-38.pyc index ade8257..5598263 100644 Binary files a/__pycache__/controller_db.cpython-38.pyc and b/__pycache__/controller_db.cpython-38.pyc differ diff --git a/__pycache__/firm.cpython-38.pyc b/__pycache__/firm.cpython-38.pyc index 55d9a42..3820ea3 100644 Binary files a/__pycache__/firm.cpython-38.pyc and b/__pycache__/firm.cpython-38.pyc differ diff --git a/__pycache__/model.cpython-38.pyc b/__pycache__/model.cpython-38.pyc index 2255dbb..1d55e5e 100644 Binary files a/__pycache__/model.cpython-38.pyc and b/__pycache__/model.cpython-38.pyc differ diff --git a/__pycache__/orm.cpython-38.pyc b/__pycache__/orm.cpython-38.pyc index dab8f28..6100d0e 100644 Binary files a/__pycache__/orm.cpython-38.pyc and b/__pycache__/orm.cpython-38.pyc differ diff --git a/controller_db.py b/controller_db.py index ad1a454..f70faed 100644 --- a/controller_db.py +++ b/controller_db.py @@ -113,8 +113,8 @@ class ControllerDB: def add_experiment_1(self, idx_scenario, idx_init_removal, dct_lst_init_remove_firm_prod, g_bom, n_max_trial, crit_supplier, firm_pref_request, - firm_pref_accept, netw_pref_cust_n, - netw_pref_cust_size, cap_limit, diff_new_conn, + firm_pref_accept, netw_pref_supp_n, + netw_pref_supp_size, cap_limit, diff_new_conn, diff_remove, proactive_ratio): e = Experiment( idx_scenario=idx_scenario, @@ -127,8 +127,8 @@ class ControllerDB: crit_supplier=crit_supplier, firm_pref_request=firm_pref_request, firm_pref_accept=firm_pref_accept, - netw_pref_cust_n=netw_pref_cust_n, - netw_pref_cust_size=netw_pref_cust_size, + netw_pref_supp_n=netw_pref_supp_n, + netw_pref_supp_size=netw_pref_supp_size, cap_limit=cap_limit, diff_new_conn=diff_new_conn, diff_remove=diff_remove, diff --git a/firm.py b/firm.py index 2571d90..e88a64a 100644 --- a/firm.py +++ b/firm.py @@ -76,17 +76,44 @@ class FirmAgent(ap.Agent): ]) if not self.dct_cand_alt_supply_up_prod_removed[product]: continue - # select based on size - lst_size_damp = \ - [size ** self.flt_firm_pref_request for size in - self.dct_cand_alt_supply_up_prod_removed[ - product].revenue_log] - lst_prob = [size_damp / sum(lst_size_damp) - for size_damp in lst_size_damp - ] - select_alt_supply = self.model.nprandom.choice( - self.dct_cand_alt_supply_up_prod_removed[product], - p=lst_prob) + # select based on connection + lst_firm_connect = [] + for firm in self.dct_cand_alt_supply_up_prod_removed[product]: + out_edges = self.model.firm_network.graph.out_edges( + self.model.firm_network.positions[firm], keys=True) + in_edges = self.model.firm_network.graph.in_edges( + self.model.firm_network.positions[firm], keys=True) + lst_adj_firm = [] + lst_adj_firm += \ + [ap.AgentIter(self.model, edge[1]).to_list()[ + 0].code for edge in out_edges] + lst_adj_firm += \ + [ap.AgentIter(self.model, edge[0]).to_list()[ + 0].code for edge in in_edges] + if self.code in lst_adj_firm: + lst_firm_connect.append(firm) + if len(lst_firm_connect) == 0: + # select based on size + lst_size_damp = \ + [size ** self.flt_firm_pref_request for size in + self.dct_cand_alt_supply_up_prod_removed[ + product].revenue_log] + lst_prob = [size_damp / sum(lst_size_damp) + for size_damp in lst_size_damp] + select_alt_supply = self.model.nprandom.choice( + self.dct_cand_alt_supply_up_prod_removed[product], + p=lst_prob) + elif len(lst_firm_connect) > 0: + # select based on size of firm that has connection + lst_firm_size_damp = \ + [size ** self.flt_firm_pref_accept + for size in lst_firm_connect.revenue_log] + lst_prob = \ + [size_damp / sum(lst_firm_size_damp) + for size_damp in lst_firm_size_damp] + select_alt_supply = \ + self.model.nprandom.choice(lst_firm_connect, + p=lst_prob) # print( # f"{self.name} selct alt supply for {product.code} " # f"from {select_alt_supply.name}" @@ -140,21 +167,19 @@ class FirmAgent(ap.Agent): if len(lst_firm_connect) == 0: # handling based on size lst_firm_size_damp = \ - [firm.revenue_log ** self.flt_firm_pref_accept - for firm in lst_firm] + [size ** self.flt_firm_pref_accept + for size in lst_firm.revenue_log] lst_prob = \ [size_damp / sum(lst_firm_size_damp) for size_damp in lst_firm_size_damp] select_customer = \ self.model.nprandom.choice(lst_firm, p=lst_prob) self.accept_request(select_customer, product) - elif len(lst_firm_connect) == 1: - self.accept_request(lst_firm_connect[0], product) - elif len(lst_firm_connect) > 1: + elif len(lst_firm_connect) > 0: # handling based on size of firm that has connection lst_firm_size_damp = \ - [firm.revenue_log ** self.flt_firm_pref_accept - for firm in lst_firm_connect] + [size ** self.flt_firm_pref_accept + for size in lst_firm_connect.revenue_log] lst_prob = \ [size_damp / sum(lst_firm_size_damp) for size_damp in lst_firm_size_damp] diff --git a/model.py b/model.py index 90a27d4..9c2952d 100644 --- a/model.py +++ b/model.py @@ -1,7 +1,7 @@ import agentpy as ap import pandas as pd import numpy as np -import random +# import random import networkx as nx from firm import FirmAgent from product import ProductAgent @@ -14,15 +14,15 @@ class Model(ap.Model): def setup(self): self.sample = self.p.sample self.int_stop_times, self.int_stop_t = 0, None - self.random = random.Random(self.p.seed) + # self.random = random.Random(self.p.seed) self.nprandom = np.random.default_rng(self.p.seed) self.int_n_iter = int(self.p.n_iter) self.dct_lst_remove_firm_prod = self.p.dct_lst_init_remove_firm_prod self.int_n_max_trial = int(self.p.n_max_trial) - self.flt_netw_pref_cust_n = float(self.p.netw_pref_cust_n) - self.flt_netw_pref_cust_size = float(self.p.netw_pref_cust_size) + self.flt_netw_pref_supp_n = float(self.p.netw_pref_supp_n) + self.flt_netw_pref_supp_size = float(self.p.netw_pref_supp_size) self.flt_cap_limit = int(self.p.cap_limit) self.flt_diff_remove = float(self.p.diff_remove) self.proactive_ratio = float(self.p.proactive_ratio) @@ -69,22 +69,23 @@ class Model(ap.Model): # add edge to G_firm according to G_bom for node in nx.nodes(G_Firm): for product_code in G_Firm.nodes[node]['Product_Code']: - for succ_product_code in list(G_bom.successors(product_code)): + for pred_product_code in \ + list(G_bom.predecessors(product_code)): # for each product of a certain firm - # get each successor (finished product) of this product - # get a list of firm producing this successor - lst_succ_firm = Firm['Code'][Firm[succ_product_code] == + # get each predecessor (component) of this product + # get a list of firm producing this component + lst_pred_firm = Firm['Code'][Firm[pred_product_code] == 1].to_list() - lst_succ_firm_size_damp = \ - [G_Firm.nodes[succ_firm]['Revenue_Log'] ** - self.flt_netw_pref_cust_size - for succ_firm in lst_succ_firm + lst_pred_firm_size_damp = \ + [G_Firm.nodes[pred_firm]['Revenue_Log'] ** + self.flt_netw_pref_supp_size + for pred_firm in lst_pred_firm ] lst_prob = \ - [size_damp / sum(lst_succ_firm_size_damp) - for size_damp in lst_succ_firm_size_damp + [size_damp / sum(lst_pred_firm_size_damp) + for size_damp in lst_pred_firm_size_damp ] - # select multiple customer + # select multiple supplier # based on relative size of this firm lst_same_prod_firm = Firm['Code'][Firm[product_code] == 1].to_list() @@ -95,27 +96,31 @@ class Model(ap.Model): share = G_Firm.nodes[node]['Revenue_Log'] / sum( lst_same_prod_firm_size) # damp share - share = share ** self.flt_netw_pref_cust_n - n_succ_firm = round(share * len(lst_succ_firm)) if round( - share * len(lst_succ_firm)) > 0 else 1 # at least one - lst_choose_firm = self.nprandom.choice(lst_succ_firm, - n_succ_firm, + share = share ** self.flt_netw_pref_supp_n + n_pred_firm = round(share * len(lst_pred_firm)) if round( + share * len(lst_pred_firm)) > 0 else 1 # at least one + lst_choose_firm = self.nprandom.choice(lst_pred_firm, + n_pred_firm, replace=False, p=lst_prob) - lst_add_edge = [(node, succ_firm, { + lst_add_edge = [(node, pred_firm, { 'Product': product_code - }) for succ_firm in lst_choose_firm] + }) for pred_firm in lst_choose_firm] G_Firm.add_edges_from(lst_add_edge) # graph firm prod pred_node = [n for n, v in G_FirmProd.nodes(data=True) if v['Firm_Code'] == node and v['Product_Code'] == product_code][0] - for succ_firm in lst_choose_firm: - succ_node = [n for n, v in G_FirmProd.nodes(data=True) - if v['Firm_Code'] == succ_firm and - v['Product_Code'] == succ_product_code][0] - G_FirmProd.add_edge(pred_node, succ_node) + for pred_firm in lst_choose_firm: + pred_node = [n for n, v in G_FirmProd.nodes(data=True) + if v['Firm_Code'] == pred_firm and + v['Product_Code'] == pred_product_code][0] + G_FirmProd.add_edge(pred_node, pred_node) + + # unconnected node + # for node in nx.nodes(G_Firm): + # if node. self.sample.g_firm = json.dumps(nx.adjacency_data(G_Firm)) self.firm_network = ap.Network(self, G_Firm) @@ -367,12 +372,17 @@ class Model(ap.Model): ] std_size = (firm.revenue_log - min(lst_size) + 1) / (max(lst_size) - min(lst_size) + 1) - prod_remove = 1 - std_size * (1 - lost_percent) + prob_remove = 1 - std_size * (1 - lost_percent) + # sample prob + prob_remove = self.nprandom.uniform( + prob_remove - 0.1, prob_remove + 0.1) + prob_remove = 1 if prob_remove > 1 else prob_remove + prob_remove = 0 if prob_remove < 0 else prob_remove # damp prod - prod_remove = prod_remove ** self.flt_diff_remove + prob_remove = prob_remove ** self.flt_diff_remove if self.nprandom.choice([True, False], - p=[prod_remove, - 1 - prod_remove]): + p=[prob_remove, + 1 - prob_remove]): firm.a_lst_product_removed.append(product) if firm in self.dct_lst_remove_firm_prod.keys(): self.dct_lst_remove_firm_prod[firm].append( diff --git a/network.png b/network.png index 9d6ea41..c07f197 100644 Binary files a/network.png and b/network.png differ diff --git a/orm.py b/orm.py index ee721c8..962d2de 100644 --- a/orm.py +++ b/orm.py @@ -58,8 +58,8 @@ class Experiment(Base): crit_supplier = Column(DECIMAL(8, 4), nullable=False) firm_pref_request = Column(DECIMAL(8, 4), nullable=False) firm_pref_accept = Column(DECIMAL(8, 4), nullable=False) - netw_pref_cust_n = Column(DECIMAL(8, 4), nullable=False) - netw_pref_cust_size = Column(DECIMAL(8, 4), nullable=False) + netw_pref_supp_n = Column(DECIMAL(8, 4), nullable=False) + netw_pref_supp_size = Column(DECIMAL(8, 4), nullable=False) cap_limit = Column(Integer, nullable=False) diff_new_conn = Column(DECIMAL(8, 4), nullable=False) diff_remove = Column(DECIMAL(8, 4), nullable=False) diff --git a/test.ipynb b/test.ipynb index 37b947c..b4d5648 100644 --- a/test.ipynb +++ b/test.ipynb @@ -168,6 +168,55 @@ "list_dct = result.loc[result['count']>=9, 'dct_lst_init_remove_firm_prod'].to_list()\n", "print(len(list_dct))" ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "probabilities do not sum to 1", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[2], line 3\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mnumpy\u001b[39;00m \u001b[39mas\u001b[39;00m \u001b[39mnp\u001b[39;00m\n\u001b[1;32m----> 3\u001b[0m np\u001b[39m.\u001b[39;49mrandom\u001b[39m.\u001b[39;49mchoice([\u001b[39m1\u001b[39;49m], p\u001b[39m=\u001b[39;49m[\u001b[39m0.9\u001b[39;49m])\n", + "File \u001b[1;32mmtrand.pyx:933\u001b[0m, in \u001b[0;36mnumpy.random.mtrand.RandomState.choice\u001b[1;34m()\u001b[0m\n", + "\u001b[1;31mValueError\u001b[0m: probabilities do not sum to 1" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "np.random.choice([1], p=[0.9])" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.004495606232695251" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prob_remove = 0\n", + "prob_remove = np.random.uniform(\n", + " prob_remove - 0.1, prob_remove + 0.1)\n", + "prob_remove = 1 if prob_remove > 1 else prob_remove\n", + "prob_remove = 0 if prob_remove < 0 else prob_remove\n", + "prob_remove" + ] } ], "metadata": { diff --git a/xv_with_exp.csv b/xv_with_exp.csv index 43afc2d..fae4d3a 100644 --- a/xv_with_exp.csv +++ b/xv_with_exp.csv @@ -1,4 +1,4 @@ -n_max_trial,crit_supplier,firm_pref_request,firm_pref_accept,netw_pref_cust_n,netw_pref_cust_size,cap_limit,diff_new_conn,diff_remove,proactive_ratio +n_max_trial,crit_supplier,firm_pref_request,firm_pref_accept,netw_pref_supp_n,netw_pref_supp_size,cap_limit,diff_new_conn,diff_remove,proactive_ratio 15,2,2,2,0.5,2,4,0.5,0.5,0.4 10,1,1,1,1,1,2,1,1,0.6 5,0.5,0.5,0.5,2,0.5,1,2,2,0.8 diff --git a/xv_without_exp.csv b/xv_without_exp.csv index 7e20aa7..5da5d04 100644 --- a/xv_without_exp.csv +++ b/xv_without_exp.csv @@ -1,2 +1,2 @@ -n_max_trial,crit_supplier,firm_pref_request,firm_pref_accept,netw_pref_cust_n,netw_pref_cust_size,cap_limit,diff_new_conn,diff_remove,proactive_ratio -10,1,1,1,1,1,2,1,1,0 +n_max_trial,crit_supplier,firm_pref_request,firm_pref_accept,netw_pref_supp_n,netw_pref_supp_size,cap_limit,diff_new_conn,diff_remove,proactive_ratio +10,1,1,1,1,1,2,1,1,0.8