formatting

This commit is contained in:
2023-03-14 18:53:00 +08:00
parent a8d50e1f81
commit 5b0e17ce52
10 changed files with 183 additions and 266 deletions

315
model.py
View File

@@ -5,33 +5,9 @@ import random
import networkx as nx
from firm import FirmAgent
from product import ProductAgent
from orm import db_session, Sample, Result
from orm import db_session, Result
import platform
sample = 0
seed = 0
n_iter = 10
# dct_list_init_remove_firm_prod = {133: ['1.4.4.1'], 2: ['1.1.3']}
# dct_list_init_remove_firm_prod = {
# 135: ['1.3.2.1'],
# 133: ['1.4.4.1'],
# 2: ['1.1.3']
# }
dct_list_init_remove_firm_prod = {
'140': ['1.4.5.1'],
'135': ['1.3.2.1'],
'133': ['1.4.4.1'],
'2': ['1.1.3']
}
n_max_trial = 5
dct_sample_para = {
'sample': sample,
'seed': seed,
'n_iter': n_iter,
'n_max_trial': n_max_trial,
'dct_list_init_remove_firm_prod': dct_list_init_remove_firm_prod,
}
class Model(ap.Model):
def setup(self):
@@ -41,7 +17,7 @@ class Model(ap.Model):
self.nprandom = np.random.default_rng(self.p.seed)
self.int_n_iter = int(self.p.n_iter)
self.int_n_max_trial = int(self.p.n_max_trial)
self.dct_list_remove_firm_prod = self.p.dct_list_init_remove_firm_prod
self.dct_lst_remove_firm_prod = self.p.dct_lst_init_remove_firm_prod
# init graph bom
BomNodes = pd.read_csv('BomNodes.csv', index_col=0)
@@ -77,69 +53,52 @@ class Model(ap.Model):
# add edge to G_firm according to G_bom
for node in nx.nodes(G_Firm):
# print(node, '-' * 20)
for product_code in G_Firm.nodes[node]['Product_Code']:
# print(product_code)
for succ_product_code in list(G_bom.successors(product_code)):
# print(succ_product_code)
list_succ_firms = Firm['Code'][Firm[succ_product_code] ==
1].to_list()
list_revenue_log = [
# 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] ==
1].to_list()
lst_succ_firm_size = [
G_Firm.nodes[succ_firm]['Revenue_Log']
for succ_firm in list_succ_firms
for succ_firm in lst_succ_firm
]
# list_prob = [
# (v - min(list_revenue_log) + 1) /
# (max(list_revenue_log) - min(list_revenue_log) + 1)
# for v in list_revenue_log
# ]
# list_flag = [
# self.nprandom.choice([1, 0], p=[prob, 1 - prob])
# for prob in list_prob
# ]
# # print(list(zip(list_succ_firms,list_flag,list_prob)))
# list_added_edges = [(node, succ_firm, {
# 'Product': product_code
# }) for succ_firm, flag in zip(list_succ_firms, list_flag)
# if flag == 1]
list_prob = [
size / sum(list_revenue_log)
for size in list_revenue_log
lst_prob = [
size / sum(lst_succ_firm_size)
for size in lst_succ_firm_size
]
list_f_same_p = Firm['Code'][Firm[product_code] ==
1].to_list()
list_f_size_same_p = [
# select multiple successors based on relative size of this firm
lst_same_prod_firm = Firm['Code'][Firm[product_code] ==
1].to_list()
lst_same_prod_firm_size = [
G_Firm.nodes[f]['Revenue_Log']
for f in list_f_same_p
for f in lst_same_prod_firm
]
share = G_Firm.nodes[node]['Revenue_Log'] / sum(list_f_size_same_p)
num_succ_f = round(share * len(list_succ_firms)) if round(share * len(list_succ_firms)) > 0 else 1
list_choose_firm = self.nprandom.choice(list_succ_firms, num_succ_f,
p=list_prob)
list_choose_firm = list(set(list_choose_firm))
list_added_edges = [(node, succ_firm, {
share = G_Firm.nodes[node]['Revenue_Log'] / sum(
lst_same_prod_firm_size)
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,
p=lst_prob)
lst_choose_firm = list(
set(lst_choose_firm
)) # nprandom.choice may have duplicates
lst_add_edge = [(node, succ_firm, {
'Product': product_code
}) for succ_firm in list_choose_firm]
G_Firm.add_edges_from(list_added_edges)
# print('-' * 20)
}) for succ_firm in lst_choose_firm]
G_Firm.add_edges_from(lst_add_edge)
self.firm_network = ap.Network(self, G_Firm)
self.product_network = ap.Network(self, G_bom)
# print([node.label for node in self.firm_network.nodes])
# print([list(self.firm_network.graph.predecessors(node))
# for node in self.firm_network.nodes])
# print([self.firm_network.graph.nodes[node.label]['Name']
# for node in self.firm_network.nodes])
# print([v for v in self.firm_network.graph.nodes(data=True)])
# init product
for ag_node, attr in self.product_network.graph.nodes(data=True):
product_agent = ProductAgent(self,
code=ag_node.label,
name=attr['Name'])
self.product_network.add_agents([product_agent], [ag_node])
self.a_list_total_products = ap.AgentList(self,
self.product_network.agents)
product = ProductAgent(self, code=ag_node.label, name=attr['Name'])
self.product_network.add_agents([product], [ag_node])
self.a_lst_total_products = ap.AgentList(self,
self.product_network.agents)
# init firm
for ag_node, attr in self.firm_network.graph.nodes(data=True):
@@ -149,201 +108,164 @@ class Model(ap.Model):
name=attr['Name'],
type_region=attr['Type_Region'],
revenue_log=attr['Revenue_Log'],
a_list_product=self.a_list_total_products.select([
a_lst_product=self.a_lst_total_products.select([
code in attr['Product_Code']
for code in self.a_list_total_products.code
for code in self.a_lst_total_products.code
]))
# init capacity based on discrete uniform distribution
# list_out_edges = list(
# self.firm_network.graph.out_edges(ag_node,
# keys=True,
# data='Product'))
# for product in firm_agent.a_list_product:
# capacity = len([
# edge for edge in list_out_edges if edge[-1] ==
# product.code])
# firm_agent.dct_prod_capacity[product] = capacity
for product in firm_agent.a_list_product:
# init extra capacity based on discrete uniform distribution
for product in firm_agent.a_lst_product:
firm_agent.dct_prod_capacity[product] = self.nprandom.integers(
firm_agent.revenue_log / 5, firm_agent.revenue_log / 5 + 2)
# print(firm_agent.name, firm_agent.dct_prod_capacity)
self.firm_network.add_agents([firm_agent], [ag_node])
self.a_list_total_firms = ap.AgentList(self, self.firm_network.agents)
# print(list(zip(self.a_list_total_firms.code,
# self.a_list_total_firms.name,
# self.a_list_total_firms.capacity)))
self.a_lst_total_firms = ap.AgentList(self, self.firm_network.agents)
# init dct_list_remove_firm_prod (from string to agent)
t_dct = {}
for firm_code, list_product in self.dct_list_remove_firm_prod.items():
firm = self.a_list_total_firms.select(
self.a_list_total_firms.code == firm_code)[0]
t_dct[firm] = self.a_list_total_products.select([
code in list_product
for code in self.a_list_total_products.code
for firm_code, lst_product in self.dct_lst_remove_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_list_remove_firm_prod = t_dct
self.dct_list_disrupt_firm_prod = t_dct
self.dct_lst_remove_firm_prod = t_dct
self.dct_lst_disrupt_firm_prod = t_dct
# init output
self.list_dct_list_remove_firm_prod = []
self.list_dct_list_disrupt_firm_prod = []
self.lst_dct_lst_remove_firm_prod = []
self.lst_dct_lst_disrupt_firm_prod = []
# set the initial firm product that are removed
for firm, a_list_product in self.dct_list_remove_firm_prod.items():
for product in a_list_product:
assert product in firm.a_list_product, \
for firm, a_lst_product in self.dct_lst_remove_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_list_product_removed.append(product)
firm.a_lst_product_removed.append(product)
# draw network
# self.draw_network()
def update(self):
self.a_list_total_firms.clean_before_time_step()
self.a_lst_total_firms.clean_before_time_step()
# output
self.list_dct_list_remove_firm_prod.append(
(self.t, self.dct_list_remove_firm_prod))
self.list_dct_list_disrupt_firm_prod.append(
(self.t, self.dct_list_disrupt_firm_prod))
self.lst_dct_lst_remove_firm_prod.append(
(self.t, self.dct_lst_remove_firm_prod))
self.lst_dct_lst_disrupt_firm_prod.append(
(self.t, self.dct_lst_disrupt_firm_prod))
# stop simulation if reached terminal number of iteration
if self.t == self.int_n_iter or len(
self.dct_list_remove_firm_prod) == 0:
self.dct_lst_remove_firm_prod) == 0:
self.int_stop_times = self.t
print(self.int_stop_times, self.t)
self.stop()
def step(self):
# shuffle self.dct_list_remove_firm_prod
# dct_key_list = list(self.dct_list_remove_firm_prod.keys())
# self.nprandom.shuffle(dct_key_list)
# self.dct_list_remove_firm_prod = {
# key: self.dct_list_remove_firm_prod[key].shuffle()
# for key in dct_key_list
# }
# print(self.dct_list_remove_firm_prod)
print('\n', '=' * 20, 'step', self.t, '=' * 20)
print(
'dct_list_remove_firm_prod', {
key.name: value.code
for key, value in self.dct_list_remove_firm_prod.items()
for key, value in self.dct_lst_remove_firm_prod.items()
})
# remove_edge_to_cus_and_cus_up_prod
for firm, a_list_product in self.dct_list_remove_firm_prod.items():
for product in a_list_product:
for firm, a_lst_product in self.dct_lst_remove_firm_prod.items():
for product in a_lst_product:
firm.remove_edge_to_cus_remove_cus_up_prod(product)
for n_trial in range(self.int_n_max_trial):
print('=' * 10, 'trial', n_trial, '=' * 10)
# seek_alt_supply
# shuffle self.a_list_total_firms
self.a_list_total_firms = self.a_list_total_firms.shuffle()
for firm in self.a_list_total_firms:
if len(firm.a_list_up_product_removed) > 0:
# print(firm.name)
# print(firm.a_list_up_product_removed.code)
# shuffle self.a_lst_total_firms
self.a_lst_total_firms = self.a_lst_total_firms.shuffle()
for firm in self.a_lst_total_firms:
if len(firm.a_lst_up_product_removed) > 0:
firm.seek_alt_supply()
# handle_request
# shuffle self.a_list_total_firms
self.a_list_total_firms = self.a_list_total_firms.shuffle()
for firm in self.a_list_total_firms:
# shuffle self.a_lst_total_firms
self.a_lst_total_firms = self.a_lst_total_firms.shuffle()
for firm in self.a_lst_total_firms:
if len(firm.dct_request_prod_from_firm) > 0:
firm.handle_request()
# reset dct_request_prod_from_firm
self.a_list_total_firms.clean_before_trial()
self.a_lst_total_firms.clean_before_trial()
# do not use:
# self.a_list_total_firms.dct_request_prod_from_firm = {} why?
# self.a_lst_total_firms.dct_request_prod_from_firm = {} why?
# based on a_list_up_product_removed,
# update a_list_product_disrupted / a_list_product_removed
# update dct_list_disrupt_firm_prod / dct_list_remove_firm_prod
self.dct_list_remove_firm_prod = {}
self.dct_list_disrupt_firm_prod = {}
for firm in self.a_list_total_firms:
if len(firm.a_list_up_product_removed) > 0:
print(firm.name, 'a_list_up_product_removed', [
product.code for product in firm.a_list_up_product_removed
# based on a_lst_up_product_removed
# update a_lst_product_disrupted / a_lst_product_removed
# update dct_lst_disrupt_firm_prod / dct_lst_remove_firm_prod
self.dct_lst_remove_firm_prod = {}
self.dct_lst_disrupt_firm_prod = {}
for firm in self.a_lst_total_firms:
if len(firm.a_lst_up_product_removed) > 0:
print(firm.name, 'a_lst_up_product_removed', [
product.code for product in firm.a_lst_up_product_removed
])
for product in firm.a_list_product:
for product in firm.a_lst_product:
n_up_product_removed = 0
for up_product_removed in firm.a_list_up_product_removed:
for up_product_removed in firm.a_lst_up_product_removed:
if product in up_product_removed.a_successors():
n_up_product_removed += 1
if n_up_product_removed == 0:
continue
else:
# update a_list_product_disrupted / dct_list_disrupt_firm_prod
if product not in firm.a_list_product_disrupted:
firm.a_list_product_disrupted.append(product)
if firm in self.dct_list_disrupt_firm_prod.keys():
self.dct_list_disrupt_firm_prod[firm].append(
# update a_lst_product_disrupted / dct_lst_disrupt_firm_prod
if product not in firm.a_lst_product_disrupted:
firm.a_lst_product_disrupted.append(product)
if firm in self.dct_lst_disrupt_firm_prod.keys():
self.dct_lst_disrupt_firm_prod[firm].append(
product)
else:
self.dct_list_disrupt_firm_prod[
self.dct_lst_disrupt_firm_prod[
firm] = ap.AgentList(
self.model, [product])
# update a_list_product_removed / dct_list_remove_firm_prod
# update a_lst_product_removed / dct_list_remove_firm_prod
# mark disrupted firm as removed based conditionally
lost_percent = n_up_product_removed / len(
product.a_predecessors())
list_revenue_log = self.a_list_total_firms.revenue_log
std_size = (firm.revenue_log - min(list_revenue_log) +
1) / (max(list_revenue_log) -
min(list_revenue_log) + 1)
p_remove = 1 - std_size * (1 - lost_percent)
flag = self.nprandom.choice([1, 0],
p=[p_remove, 1 - p_remove])
# flag = 1
if flag == 1:
firm.a_list_product_removed.append(product)
# if firm in
# self.dct_list_remove_firm_prod[firm] = firm.a_list_product_removed
if firm in self.dct_list_remove_firm_prod.keys():
self.dct_list_remove_firm_prod[firm].append(
lst_size = self.a_lst_total_firms.revenue_log
std_size = (firm.revenue_log - min(lst_size) +
1) / (max(lst_size) - min(lst_size) + 1)
prod_remove = 1 - std_size * (1 - lost_percent)
if self.nprandom.choice(
[True, False], p=[prod_remove, 1 - prod_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(
product)
else:
self.dct_list_remove_firm_prod[
self.dct_lst_remove_firm_prod[
firm] = ap.AgentList(
self.model, [product])
# # update the firm that is removed
# self.dct_list_remove_firm_prod = {}
# for firm in self.a_list_total_firms:
# if len(firm.a_list_product_removed) > 0:
# self.dct_list_remove_firm_prod[
# firm] = firm.a_list_product_removed
# print(self.dct_list_remove_firm_prod)
print(
'dct_list_remove_firm_prod', {
key.name: value.code
for key, value in self.dct_list_remove_firm_prod.items()
for key, value in self.dct_lst_remove_firm_prod.items()
})
def end(self):
print('/' * 20, 'output', '/' * 20)
print('dct_list_remove_firm_prod')
for t, dct in self.list_dct_list_remove_firm_prod:
for firm, a_list_product in dct.items():
for product in a_list_product:
for t, dct in self.lst_dct_lst_remove_firm_prod:
for firm, a_lst_product in dct.items():
for product in a_lst_product:
print(t, firm.name, product.code)
print('dct_list_disrupt_firm_prod')
for t, dct in self.list_dct_list_disrupt_firm_prod:
for firm, a_list_product in dct.items():
for product in a_list_product:
print('dct_lst_disrupt_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:
print(t, firm.name, product.code)
qry_result = db_session.query(Result).filter_by(s_id=self.sample.id)
if qry_result.count() == 0:
lst_result_info = []
for t, dct in self.list_dct_list_disrupt_firm_prod:
for firm, a_list_product in dct.items():
for product in a_list_product:
# print(t, firm.name, product.code)
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:
db_r = Result(s_id=self.sample.id,
id_firm=firm.code,
id_product=product.code,
@@ -352,11 +274,10 @@ 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.list_dct_list_remove_firm_prod:
for firm, a_list_product in dct.items():
for product in a_list_product:
# print(t, firm.name, product.code)
# only firm disrupted can be removed
for t, dct in self.lst_dct_lst_remove_firm_prod:
for firm, a_lst_product in dct.items():
for product in a_lst_product:
# only firm disrupted can be removed theoretically
qry_f_p = db_session.query(Result).filter(
Result.s_id == self.sample.id,
Result.id_firm == firm.code,
@@ -364,8 +285,8 @@ class Model(ap.Model):
if qry_f_p.count() == 1:
qry_f_p.update({"is_removed": True})
db_session.commit()
self.sample.is_done_flag, self.sample.computer_name = 1, platform.node(
)
self.sample.is_done_flag = 1
self.sample.computer_name = platform.node()
self.sample.stop_t = self.int_stop_times
db_session.commit()
@@ -401,7 +322,3 @@ class Model(ap.Model):
edge_label,
font_size=4)
plt.savefig("network.png")
# model = Model(dct_sample_para)
# model.run()