4 status (Normal / Affected / Disrupted / Removed)

This commit is contained in:
2023-06-18 21:39:15 +08:00
parent fe128f8681
commit 6f99d9978e
10 changed files with 94 additions and 92 deletions

70
firm.py
View File

@@ -14,13 +14,13 @@ class FirmAgent(ap.Agent):
self.ori_size = revenue_log
self.size = revenue_log
self.a_lst_product = a_lst_product
self.a_lst_product_removed = ap.AgentList(self.model, [])
self.a_lst_product_disrupted = ap.AgentList(self.model, [])
self.dct_prod_up_prod_stat = {}
self.dct_prod_capacity = {}
# para in trial
self.dct_n_trial_up_prod_removed = {}
self.dct_cand_alt_supply_up_prod_removed = {}
self.dct_n_trial_up_prod_disrupted = {}
self.dct_cand_alt_supp_up_prod_disrupted = {}
self.dct_request_prod_from_firm = {}
# external variable
@@ -34,7 +34,7 @@ class FirmAgent(ap.Agent):
# init dct_prod_up_prod_stat (self para)
for prod in a_lst_product:
self.dct_prod_up_prod_stat[prod] = {
# Normal / Disrupted / Removed + time step
# (Normal / Affected / Disrupted / Removed, time step)
'status': [('N', 0)],
# have or have no supply
'supply': dict.fromkeys(prod.a_predecessors(), True)
@@ -61,16 +61,17 @@ class FirmAgent(ap.Agent):
# print(firm_agent.name, extra_cap)
self.dct_prod_capacity[product] = extra_cap
def remove_edge_to_cus_remove_cus_up_prod(self, remove_product):
def remove_edge_to_cus_affect_cus_up_prod(self, disrupted_prod):
# para remove_product is the product that self got disrupted
lst_out_edge = list(
self.firm_network.graph.out_edges(
self.firm_network.positions[self], keys=True, data='Product'))
for n1, n2, key, product_code in lst_out_edge:
if product_code == remove_product.code:
# remove edge
if product_code == disrupted_prod.code:
# remove edge to customer
self.firm_network.graph.remove_edge(n1, n2, key)
# remove customer up product conditionally
# customer up product affected conditionally
customer = ap.AgentIter(self.model, n2).to_list()[0]
lst_in_edge = list(
self.firm_network.graph.in_edges(n2,
@@ -78,45 +79,44 @@ class FirmAgent(ap.Agent):
data='Product'))
lst_select_in_edge = [
edge for edge in lst_in_edge
if edge[-1] == remove_product.code
if edge[-1] == disrupted_prod.code
]
prod_remove = math.exp(-1 * self.flt_crit_supplier *
len(lst_select_in_edge))
prob_lost_supp = math.exp(-1 * self.flt_crit_supplier *
len(lst_select_in_edge))
if self.model.nprandom.choice([True, False],
p=[prod_remove,
1 - prod_remove]):
customer.dct_n_trial_up_prod_removed[remove_product] = 0
p=[prob_lost_supp,
1 - prob_lost_supp]):
customer.dct_n_trial_up_prod_disrupted[disrupted_prod] = 0
for prod in customer.dct_prod_up_prod_stat.keys():
if remove_product in \
if disrupted_prod in \
customer.dct_prod_up_prod_stat[
prod]['supply'].keys():
customer.dct_prod_up_prod_stat[
prod]['supply'][remove_product] = False
prod]['supply'][disrupted_prod] = False
customer.dct_prod_up_prod_stat[
prod]['status'].append(('D', self.model.t))
print(self.name, remove_product.code, 'affect',
prod]['status'].append(('A', self.model.t))
print(self.name, disrupted_prod.code, 'affect',
customer.name, prod.code)
def seek_alt_supply(self, product):
# para product is the product that self is seeking
# for product in self.a_lst_up_product_removed:
print(f"{self.name} seek alt supply for {product.code}")
if self.dct_n_trial_up_prod_removed[
if self.dct_n_trial_up_prod_disrupted[
product] <= self.model.int_n_max_trial:
if self.dct_n_trial_up_prod_removed[product] == 0:
if self.dct_n_trial_up_prod_disrupted[product] == 0:
# select a list of candidate firm that has the product
self.dct_cand_alt_supply_up_prod_removed[product] = \
self.dct_cand_alt_supp_up_prod_disrupted[product] = \
self.model.a_lst_total_firms.select([
product in firm.a_lst_product
and product not in firm.a_lst_product_removed
and product not in firm.a_lst_product_disrupted
for firm in self.model.a_lst_total_firms
])
if self.dct_cand_alt_supply_up_prod_removed[product]:
if self.dct_cand_alt_supp_up_prod_disrupted[product]:
# select based on connection
lst_firm_connect = []
if self.is_prf_conn:
for firm in \
self.dct_cand_alt_supply_up_prod_removed[product]:
self.dct_cand_alt_supp_up_prod_disrupted[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(
@@ -135,16 +135,16 @@ class FirmAgent(ap.Agent):
if self.is_prf_size:
lst_size = \
[size for size in
self.dct_cand_alt_supply_up_prod_removed[
self.dct_cand_alt_supp_up_prod_disrupted[
product].size]
lst_prob = [size / sum(lst_size)
for size in lst_size]
select_alt_supply = self.model.nprandom.choice(
self.dct_cand_alt_supply_up_prod_removed[product],
self.dct_cand_alt_supp_up_prod_disrupted[product],
p=lst_prob)
else:
select_alt_supply = self.model.nprandom.choice(
self.dct_cand_alt_supply_up_prod_removed[product])
self.dct_cand_alt_supp_up_prod_disrupted[product])
elif len(lst_firm_connect) > 0:
# select based on size of connected firm or not
if self.is_prf_size:
@@ -182,7 +182,7 @@ class FirmAgent(ap.Agent):
select_alt_supply.dct_request_prod_from_firm.items()
})
self.dct_n_trial_up_prod_removed[product] += 1
self.dct_n_trial_up_prod_disrupted[product] += 1
def handle_request(self):
print(self.name, 'handle_request')
@@ -266,23 +266,23 @@ class FirmAgent(ap.Agent):
prod]['supply'][product] = True
down_firm.dct_prod_up_prod_stat[
prod]['status'].append(('N', self.model.t))
del down_firm.dct_n_trial_up_prod_removed[product]
del down_firm.dct_cand_alt_supply_up_prod_removed[product]
del down_firm.dct_n_trial_up_prod_disrupted[product]
del down_firm.dct_cand_alt_supp_up_prod_disrupted[product]
print(
f"{self.name} accept {product.code} request "
f"from {down_firm.name}"
)
else:
down_firm.dct_cand_alt_supply_up_prod_removed[product].remove(self)
down_firm.dct_cand_alt_supp_up_prod_disrupted[product].remove(self)
def clean_before_trial(self):
self.dct_request_prod_from_firm = {}
def clean_before_time_step(self):
self.dct_n_trial_up_prod_removed = \
dict.fromkeys(self.dct_n_trial_up_prod_removed.keys(), 0)
self.dct_cand_alt_supply_up_prod_removed = {}
self.dct_n_trial_up_prod_disrupted = \
dict.fromkeys(self.dct_n_trial_up_prod_disrupted.keys(), 0)
self.dct_cand_alt_supp_up_prod_disrupted = {}
def get_firm_network_node(self):
return self.firm_network.positions[self]