4 status (Normal / Affected / Disrupted / Removed)
This commit is contained in:
84
model.py
84
model.py
@@ -17,14 +17,14 @@ class Model(ap.Model):
|
||||
self.product_network = None # agentpy network
|
||||
self.firm_network = None # agentpy network
|
||||
self.firm_prod_network = None # networkx
|
||||
self.dct_lst_remove_firm_prod = self.p.dct_lst_init_remove_firm_prod
|
||||
self.dct_lst_disrupt_firm_prod = self.p.dct_lst_init_disrupt_firm_prod
|
||||
|
||||
# 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_remove = float(self.p.diff_remove)
|
||||
self.flt_diff_disrupt = float(self.p.diff_disrupt)
|
||||
self.proactive_ratio = float(self.p.proactive_ratio)
|
||||
self.drop_t = int(self.p.drop_t)
|
||||
self.remove_t = int(self.p.remove_t)
|
||||
self.int_netw_prf_n = int(self.p.netw_prf_n)
|
||||
|
||||
# init graph bom
|
||||
@@ -210,29 +210,29 @@ class Model(ap.Model):
|
||||
self.firm_network.add_agents([firm_agent], [ag_node])
|
||||
self.a_lst_total_firms = ap.AgentList(self, self.firm_network.agents)
|
||||
|
||||
# init dct_list_remove_firm_prod (from string to agent)
|
||||
# init dct_lst_disrupt_firm_prod (from string to agent)
|
||||
t_dct = {}
|
||||
for firm_code, lst_product in self.dct_lst_remove_firm_prod.items():
|
||||
for firm_code, lst_product in self.dct_lst_disrupt_firm_prod.items():
|
||||
firm = self.a_lst_total_firms.select(
|
||||
self.a_lst_total_firms.code == firm_code)[0]
|
||||
t_dct[firm] = self.a_lst_total_products.select([
|
||||
code in lst_product for code in self.a_lst_total_products.code
|
||||
])
|
||||
self.dct_lst_remove_firm_prod = t_dct
|
||||
self.dct_lst_disrupt_firm_prod = t_dct
|
||||
|
||||
# set the initial firm product that are removed
|
||||
# set the initial firm product that are disrupted
|
||||
print('\n', '=' * 20, 'step', self.t, '=' * 20)
|
||||
for firm, a_lst_product in self.dct_lst_remove_firm_prod.items():
|
||||
for firm, a_lst_product in self.dct_lst_disrupt_firm_prod.items():
|
||||
for product in a_lst_product:
|
||||
assert product in firm.a_lst_product, \
|
||||
f"product {product.code} not in firm {firm.code}"
|
||||
firm.a_lst_product_removed.append(product)
|
||||
firm.a_lst_product_disrupted.append(product)
|
||||
firm.dct_prod_up_prod_stat[
|
||||
product]['status'].append(('R', self.t))
|
||||
product]['status'].append(('D', self.t))
|
||||
|
||||
# proactive strategy
|
||||
# get all the firm prod affected
|
||||
for firm, a_lst_product in self.dct_lst_remove_firm_prod.items():
|
||||
for firm, a_lst_product in self.dct_lst_disrupt_firm_prod.items():
|
||||
for product in a_lst_product:
|
||||
init_node = \
|
||||
[n for n, v in
|
||||
@@ -290,7 +290,7 @@ class Model(ap.Model):
|
||||
for firm in self.a_lst_total_firms])[0]
|
||||
lst_cand = self.model.a_lst_total_firms.select([
|
||||
di_supp_prod in firm.a_lst_product
|
||||
and di_supp_prod not in firm.a_lst_product_removed
|
||||
and di_supp_prod not in firm.a_lst_product_disrupted
|
||||
for firm in self.model.a_lst_total_firms
|
||||
])
|
||||
n2n_betweenness = \
|
||||
@@ -312,7 +312,7 @@ class Model(ap.Model):
|
||||
# find a dfferent firm can produce the same product
|
||||
lst_cand = self.model.a_lst_total_firms.select([
|
||||
di_supp_prod in firm.a_lst_product
|
||||
and di_supp_prod not in firm.a_lst_product_removed
|
||||
and di_supp_prod not in firm.a_lst_product_disrupted
|
||||
and firm.code != di_supp_node['Firm_Code']
|
||||
for firm in self.model.a_lst_total_firms
|
||||
])
|
||||
@@ -339,24 +339,25 @@ class Model(ap.Model):
|
||||
def update(self):
|
||||
self.a_lst_total_firms.clean_before_time_step()
|
||||
|
||||
# reduce the size of removed firm
|
||||
# reduce the size of disrupted firm
|
||||
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 == 'R':
|
||||
if status == 'D':
|
||||
firm.size -= \
|
||||
firm.ori_size / len(firm.a_lst_product) / self.drop_t
|
||||
firm.ori_size / len(firm.a_lst_product) / self.remove_t
|
||||
print(self.t, firm.name, prod.code, firm.size)
|
||||
if self.t - ts + 1 == self.drop_t:
|
||||
if self.t - ts + 1 == self.remove_t:
|
||||
# turn disrupted firm into removed firm
|
||||
firm.dct_prod_up_prod_stat[
|
||||
prod]['status'].append(('N', self.t))
|
||||
prod]['status'].append(('R', self.t))
|
||||
|
||||
# stop simulation if all firm returned to normal 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 == 'R' and ts != 0:
|
||||
if status == 'D' and ts != 0:
|
||||
print("not stop because", firm.name, prod.code)
|
||||
break
|
||||
else:
|
||||
@@ -369,12 +370,12 @@ class Model(ap.Model):
|
||||
def step(self):
|
||||
print('\n', '=' * 20, 'step', self.t, '=' * 20)
|
||||
|
||||
# remove_edge_to_cus_and_cus_up_prod
|
||||
# remove edge to customer and affect customer up product
|
||||
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 == 'R' and ts == self.t-1:
|
||||
firm.remove_edge_to_cus_remove_cus_up_prod(prod)
|
||||
if status == 'D' 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):
|
||||
print('=' * 10, 'trial', n_trial, '=' * 10)
|
||||
@@ -413,45 +414,46 @@ class Model(ap.Model):
|
||||
# do not use:
|
||||
# self.a_lst_total_firms.dct_request_prod_from_firm = {} why?
|
||||
|
||||
# turn disrupted firm into removed firm conditionally
|
||||
# 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 == 'D':
|
||||
print(firm.name, 'disrupted product: ', product.code)
|
||||
n_up_product_removed = \
|
||||
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_removed == 0:
|
||||
if n_up_product_lost == 0:
|
||||
continue
|
||||
else:
|
||||
lost_percent = n_up_product_removed / len(
|
||||
lost_percent = n_up_product_lost / len(
|
||||
product.a_predecessors())
|
||||
lst_size = self.a_lst_total_firms.size
|
||||
lst_size = [firm.size for firm
|
||||
in self.a_lst_total_firms
|
||||
if product in firm.a_lst_product
|
||||
and product
|
||||
not in firm.a_lst_product_removed
|
||||
not in firm.a_lst_product_disrupted
|
||||
]
|
||||
std_size = (firm.size - min(lst_size) +
|
||||
1) / (max(lst_size) - min(lst_size) + 1)
|
||||
prob_remove = 1 - std_size * (1 - lost_percent)
|
||||
prob_disrupt = 1 - std_size * (1 - lost_percent)
|
||||
# damp prob
|
||||
prob_remove = prob_remove ** self.flt_diff_remove
|
||||
prob_disrupt = prob_disrupt ** self.flt_diff_disrupt
|
||||
# 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
|
||||
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_remove,
|
||||
1 - prob_remove]):
|
||||
firm.a_lst_product_removed.append(product)
|
||||
p=[prob_disrupt,
|
||||
1 - prob_disrupt]):
|
||||
firm.a_lst_product_disrupted.append(product)
|
||||
firm.dct_prod_up_prod_stat[
|
||||
product]['status'].append(('R', self.t))
|
||||
print(firm.name, 'removed product: ', product.code)
|
||||
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))
|
||||
@@ -473,7 +475,7 @@ class Model(ap.Model):
|
||||
# lst_result_info.append(db_r)
|
||||
# db_session.bulk_save_objects(lst_result_info)
|
||||
# db_session.commit()
|
||||
# for t, dct in self.lst_dct_lst_remove_firm_prod:
|
||||
# for t, dct in self.lst_dct_lst_disrupt_firm_prod:
|
||||
# for firm, a_lst_product in dct.items():
|
||||
# for product in a_lst_product:
|
||||
# # only firm disrupted can be removed theoretically
|
||||
|
||||
Reference in New Issue
Block a user