diff --git a/__pycache__/controller_db.cpython-38.pyc b/__pycache__/controller_db.cpython-38.pyc index b57bb9a..fb5de82 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 b4ef964..c570dbf 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 a708549..4bab2c3 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 61ffc60..e9f3b53 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 b164ebb..5d1a776 100644 --- a/controller_db.py +++ b/controller_db.py @@ -79,8 +79,8 @@ class ControllerDB: for product_code in row.index[row == 1].to_list(): dct = {code: [product_code]} list_dct.append(dct) - # list_dct = [{'140': ['1.4.5.1']}] - list_dct = [{'133': ['1.4.4.1']}] + list_dct = [{'140': ['1.4.5.1']}] + # list_dct = [{'133': ['1.4.4.1']}] # list_dct = [{'2': ['1.1.3']}] # list_dct = [{'135': ['1.3.2.1']}] # list_dct = [{'79': ['2.1.3.4']}] @@ -128,7 +128,7 @@ class ControllerDB: dct_lst_init_disrupt_firm_prod, g_bom, n_max_trial, prf_size, prf_conn, cap_limit_prob_type, cap_limit_level, - diff_new_conn, crit_supplier, diff_disrupt, + diff_new_conn, crit_supplier, proactive_ratio, remove_t, netw_prf_n): e = Experiment( idx_scenario=idx_scenario, @@ -144,7 +144,6 @@ class ControllerDB: cap_limit_level=cap_limit_level, diff_new_conn=diff_new_conn, crit_supplier=crit_supplier, - diff_disrupt=diff_disrupt, proactive_ratio=proactive_ratio, remove_t=remove_t, netw_prf_n=netw_prf_n diff --git a/firm.py b/firm.py index 8c2819f..afe58c3 100644 --- a/firm.py +++ b/firm.py @@ -11,8 +11,7 @@ class FirmAgent(ap.Agent): self.code = code self.name = name self.type_region = type_region - self.ori_size = revenue_log - self.size = revenue_log + self.size_stat = [] self.dct_prod_up_prod_stat = {} self.dct_prod_capacity = {} @@ -29,11 +28,15 @@ class FirmAgent(ap.Agent): self.flt_diff_new_conn = float(self.p.diff_new_conn) self.flt_crit_supplier = float(self.p.crit_supplier) + # init size_stat (self para) + # (size, time step), ts -1 denotes initialization + self.size_stat.append((revenue_log, -1)) + # init dct_prod_up_prod_stat (self para) for prod in a_lst_product: self.dct_prod_up_prod_stat[prod] = { - # (Normal / Affected / Disrupted / Removed, time step) - 'status': [('N', 0)], + # (Normal / Affected / Removed, time step) + 'status': [('N', -1)], # ts -1 denotes initialization # have or have no supply 'supply': dict.fromkeys(prod.a_predecessors(), True) } @@ -45,7 +48,7 @@ class FirmAgent(ap.Agent): "cap_limit_prob_type other than uniform, normal" if self.str_cap_limit_prob_type == 'uniform': extra_cap_mean = \ - self.size / self.flt_cap_limit_level + self.size_stat[0][0] / self.flt_cap_limit_level extra_cap = self.model.nprandom.integers(extra_cap_mean-2, extra_cap_mean+2) extra_cap = 0 if round(extra_cap) < 0 else round(extra_cap) @@ -53,7 +56,7 @@ class FirmAgent(ap.Agent): self.dct_prod_capacity[product] = extra_cap elif self.str_cap_limit_prob_type == 'normal': extra_cap_mean = \ - self.size / self.flt_cap_limit_level + self.size_stat[0][0] / self.flt_cap_limit_level extra_cap = self.model.nprandom.normal(extra_cap_mean, 1) extra_cap = 0 if round(extra_cap) < 0 else round(extra_cap) # print(firm_agent.name, extra_cap) @@ -133,7 +136,7 @@ class FirmAgent(ap.Agent): lst_size = \ [size for size in self.dct_cand_alt_supp_up_prod_disrupted[ - product].size] + product].size_stat[-1][0]] lst_prob = [size / sum(lst_size) for size in lst_size] select_alt_supply = self.model.nprandom.choice( @@ -146,7 +149,8 @@ class FirmAgent(ap.Agent): # select based on size of connected firm or not if self.is_prf_size: lst_firm_size = \ - [firm.size for firm in lst_firm_connect] + [firm.size_stat[-1][0] + for firm in lst_firm_connect] lst_prob = \ [size / sum(lst_firm_size) for size in lst_firm_size] @@ -215,7 +219,7 @@ class FirmAgent(ap.Agent): # handling based on size or not if self.is_prf_size: lst_firm_size = \ - [firm.size for firm in lst_firm] + [firm.size_stat[-1][0] for firm in lst_firm] lst_prob = \ [size / sum(lst_firm_size) for size in lst_firm_size] @@ -230,7 +234,8 @@ class FirmAgent(ap.Agent): # handling based on size of connected firm or not if self.is_prf_size: lst_firm_size = \ - [firm.size for firm in lst_firm_connect] + [firm.size_stat[-1][0] + for firm in lst_firm_connect] lst_prob = \ [size / sum(lst_firm_size) for size in lst_firm_size] @@ -273,6 +278,11 @@ class FirmAgent(ap.Agent): else: down_firm.dct_cand_alt_supp_up_prod_disrupted[product].remove(self) + print( + f"{self.name} denied {product.code} request " + f"from {down_firm.name}" + ) + def clean_before_trial(self): self.dct_request_prod_from_firm = {} diff --git a/model.py b/model.py index f7032c6..99614b7 100644 --- a/model.py +++ b/model.py @@ -22,7 +22,6 @@ class Model(ap.Model): # external variable self.int_n_max_trial = int(self.p.n_max_trial) self.is_prf_size = bool(self.p.prf_size) - self.flt_diff_disrupt = float(self.p.diff_disrupt) self.proactive_ratio = float(self.p.proactive_ratio) self.remove_t = int(self.p.remove_t) self.int_netw_prf_n = int(self.p.netw_prf_n) @@ -227,7 +226,8 @@ class Model(ap.Model): assert product in firm.dct_prod_up_prod_stat.keys(), \ f"product {product.code} not in firm {firm.code}" firm.dct_prod_up_prod_stat[ - product]['status'].append(('D', self.t)) + product]['status'].append(('A', self.t)) + print(f"initial removal {firm.name} {product.code}") # proactive strategy # get all the firm prod affected @@ -297,7 +297,7 @@ class Model(ap.Model): for path in lst_shortest_path]) \ / len(lst_shortest_path) drs = n2n_betweenness / \ - (len(lst_cand) * di_supp_firm.size) + (len(lst_cand) * di_supp_firm.size_stat[-1][0]) dct_drs[di_supp_code] = drs dct_drs = dict(sorted( dct_drs.items(), key=lambda kv: kv[1], reverse=True)) @@ -341,23 +341,25 @@ class Model(ap.Model): for firm in self.a_lst_total_firms: for prod in firm.dct_prod_up_prod_stat.keys(): status, ts = firm.dct_prod_up_prod_stat[prod]['status'][-1] - if status == 'D': - firm.size -= \ - firm.ori_size \ + if status == 'A': + size = firm.size_stat[-1][0] - \ + firm.size_stat[0][0] \ / len(firm.dct_prod_up_prod_stat.keys()) \ / self.remove_t - print(self.t, firm.name, prod.code, firm.size) + firm.size_stat.append((size, self.t)) + print(f'in ts {self.t}, reduce {firm.name} size ' + f'to {firm.size_stat[-1][0]} due to {prod.code}') if self.t - ts + 1 == self.remove_t: # turn disrupted firm into removed firm firm.dct_prod_up_prod_stat[ prod]['status'].append(('R', self.t)) - # stop simulation if all firm returned to normal except inital removal + # stop simulation if any firm still in affected except inital removal if self.t > 0: for firm in self.a_lst_total_firms: for prod in firm.dct_prod_up_prod_stat.keys(): status, ts = firm.dct_prod_up_prod_stat[prod]['status'][-1] - if status == 'D' and ts != 0: + if status == 'A' and ts != 0: print("not stop because", firm.name, prod.code) break else: @@ -374,7 +376,7 @@ class Model(ap.Model): for firm in self.a_lst_total_firms: for prod in firm.dct_prod_up_prod_stat.keys(): status, ts = firm.dct_prod_up_prod_stat[prod]['status'][-1] - if status == 'D' and ts == self.t-1: + if status == 'A' and ts == self.t-1: firm.remove_edge_to_cus_affect_cus_up_prod(prod) for n_trial in range(self.int_n_max_trial): @@ -387,7 +389,7 @@ class Model(ap.Model): lst_seek_prod = [] for prod in firm.dct_prod_up_prod_stat.keys(): status = firm.dct_prod_up_prod_stat[prod]['status'][-1][0] - if status != 'N': + if status == 'A': for supply in firm.dct_prod_up_prod_stat[ prod]['supply'].keys(): if not firm.dct_prod_up_prod_stat[ @@ -414,49 +416,6 @@ class Model(ap.Model): # do not use: # self.a_lst_total_firms.dct_request_prod_from_firm = {} why? - # turn affected firm into disrupted firm conditionally - for firm in self.a_lst_total_firms: - for product in firm.dct_prod_up_prod_stat.keys(): - status = firm.dct_prod_up_prod_stat[product]['status'][-1][0] - if status == 'A': - print(firm.name, 'affected product:', product.code) - n_up_product_lost = \ - sum([not stat for stat in - firm.dct_prod_up_prod_stat[ - product]['supply'].values()]) - if n_up_product_lost == 0: - continue - else: - lost_percent = n_up_product_lost / len( - product.a_predecessors()) - # firm (affected) + other firm (same product, normal) - lst_firm = [firm] - lst_firm += \ - [firm for firm - in self.a_lst_total_firms - if firm.is_prod_in_current_normal(product)] - lst_size = [firm.size for firm in lst_firm] - std_size = (firm.size - min(lst_size) + - 1) / (max(lst_size) - min(lst_size) + 1) - prob_disrupt = 1 - std_size * (1 - lost_percent) - # damp prob - prob_disrupt = prob_disrupt ** self.flt_diff_disrupt - # sample prob - prob_disrupt = self.nprandom.uniform( - prob_disrupt - 0.1, prob_disrupt + 0.1) - prob_disrupt = 1 if prob_disrupt > 1 else prob_disrupt - prob_disrupt = 0 if prob_disrupt < 0 else prob_disrupt - if self.nprandom.choice([True, False], - p=[prob_disrupt, - 1 - prob_disrupt]): - firm.dct_prod_up_prod_stat[ - product]['status'].append(('D', self.t)) - print(firm.name, 'disrupted product:', - product.code) - else: - firm.dct_prod_up_prod_stat[ - product]['status'].append(('N', self.t)) - def end(self): print('/' * 20, 'output', '/' * 20) diff --git a/oa_without_exp.csv b/oa_without_exp.csv index fcb75bf..66c1886 100644 --- a/oa_without_exp.csv +++ b/oa_without_exp.csv @@ -1,2 +1,2 @@ -X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11 -0,0,0,0,0,0,0,0,0,0,0 +X1,X2,X3,X4,X5,X6,X7,X8,X9,X10 +0,0,0,0,0,0,0,0,0,0 diff --git a/orm.py b/orm.py index 39f82c2..a955bf1 100644 --- a/orm.py +++ b/orm.py @@ -61,7 +61,6 @@ class Experiment(Base): cap_limit_level = Column(DECIMAL(8, 4), nullable=False) diff_new_conn = Column(DECIMAL(8, 4), nullable=False) crit_supplier = Column(DECIMAL(8, 4), nullable=False) - diff_disrupt = Column(DECIMAL(8, 4), nullable=False) proactive_ratio = Column(DECIMAL(8, 4), nullable=False) remove_t = Column(Integer, nullable=False) netw_prf_n = Column(Integer, nullable=False) diff --git a/xv_without_exp.csv b/xv_without_exp.csv index a6fa87e..2f2b311 100644 --- a/xv_without_exp.csv +++ b/xv_without_exp.csv @@ -1,2 +1,2 @@ -n_max_trial,prf_size,prf_conn,cap_limit_prob_type,cap_limit_level,diff_new_conn,crit_supplier,diff_disrupt,proactive_ratio,remove_t,netw_prf_n -10,TRUE,TRUE,uniform,10,0.5,0.1,0.01,1,5,2 +n_max_trial,prf_size,prf_conn,cap_limit_prob_type,cap_limit_level,diff_new_conn,crit_supplier,proactive_ratio,remove_t,netw_prf_n +10,TRUE,TRUE,uniform,10,0.1,0.1,1,5,2