remove disrupt to removed, 3 status (Normal / Affected / Removed) + size_stat

This commit is contained in:
2023-07-02 13:00:13 +08:00
parent fe58a2cf9a
commit baf60ffd76
10 changed files with 40 additions and 73 deletions

View File

@@ -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)