Compare commits

...

3 Commits

Author SHA1 Message Date
HaoYizhi 64ed87da0b change system 2023-03-04 17:49:13 +08:00
HaoYizhi cf11c0c9bb capacity init network 2023-02-28 16:56:12 +08:00
HaoYizhi c29a75177c model firm product 2023-02-27 22:02:46 +08:00
11 changed files with 348 additions and 47 deletions

16
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "C:\\Users\\ASUS\\OneDrive\\Project\\ScrAbm\\Dissertation\\IIabm\\model.py",
"console": "integratedTerminal",
"justMyCode": true
}
]
}

Binary file not shown.

Binary file not shown.

117
firm.py
View File

@ -2,21 +2,118 @@ import agentpy as ap
class FirmAgent(ap.Agent): class FirmAgent(ap.Agent):
def setup(self, code, name, type_region, revenue_log, list_product, def setup(self, code, name, type_region, revenue_log, a_list_product):
capacity):
self.firm_network = self.model.firm_network self.firm_network = self.model.firm_network
self.product_network = self.model.product_network
self.code = code self.code = code
self.name = name self.name = name
self.type_region = type_region self.type_region = type_region
self.revenue_log = revenue_log self.revenue_log = revenue_log
self.list_product = list_product self.a_list_product = a_list_product
self.capacity = capacity self.dct_prod_capacity = dict.fromkeys(self.a_list_product)
self.dct_product_is_disrupted = dict.fromkeys(list_product, False) self.a_list_up_product_removed = ap.AgentList(self.model, [])
self.dct_product_is_removed = dict.fromkeys(list_product, False) self.a_list_product_disrupted = ap.AgentList(self.model, [])
self.a_list_product_removed = ap.AgentList(self.model, [])
def remove_edge_to_customer_if_removed(self, remove_product): self.dct_num_trial_up_product_removed = {}
t = self.firm_network.graph.out_edges( self.dct_request_prod_from_firm = {}
self.firm_network.positions[self], keys=True, data=True)
print(t) def remove_edge_to_cus_and_cus_up_prod(self, remove_product):
list_out_edges = list(
self.firm_network.graph.out_edges(
self.firm_network.positions[self], keys=True, data='Product'))
for n1, n2, key, product_code in list_out_edges:
if product_code == remove_product.code:
# remove edge
# print(n1, n2, key, product_code)
self.firm_network.graph.remove_edge(n1, n2, key)
# remove customer up product if does not have alternative
customer = ap.AgentIter(self.model, n2).to_list()[0]
list_in_edges = list(
self.firm_network.graph.in_edges(n2,
keys=True,
data='Product'))
select_edges = [
edge for edge in list_in_edges
if edge[-1] == remove_product.code
]
if len(select_edges) == 0:
if remove_product not in \
customer.a_list_up_product_removed:
customer.a_list_up_product_removed.append(
remove_product)
customer.dct_num_trial_up_product_removed[
remove_product] = 0
# # disrupt customer
# customer = ap.AgentIter(self.model, n2).to_list()[0]
# for product in customer.a_list_product:
# if product in remove_product.a_successors():
# if product not in customer.a_list_product_disrupted:
# customer.a_list_product_disrupted.append(
# product)
# print(customer.a_list_product_disrupted.code)
def seek_alt_supply(self):
print(self.name, 'seek_alt_supply')
for product in self.a_list_up_product_removed:
if self.dct_num_trial_up_product_removed[
product] <= self.model.int_n_max_trial:
candidate_alt_supply = self.model.a_list_total_firms.select([
product in firm.a_list_product
for firm in self.model.a_list_total_firms
])
# print(candidate_alt_supply)
# print(candidate_alt_supply.name)
# print(candidate_alt_supply.a_list_product.code)
# select based on size
list_prob = [
size / sum(candidate_alt_supply.revenue_log)
for size in candidate_alt_supply.revenue_log
]
select_alt_supply = self.model.nprandom.choice(
candidate_alt_supply, p=list_prob)
print('select_alt_supply', select_alt_supply.name)
assert product in select_alt_supply.a_list_product, \
f"{select_alt_supply} \
does not produce requested product {product}"
if product in select_alt_supply.dct_request_prod_from_firm.\
keys():
select_alt_supply.dct_request_prod_from_firm[
product].append(self)
else:
select_alt_supply.dct_request_prod_from_firm[product] = [
self
]
print({
key.code: [v.name for v in value]
for key, value in
select_alt_supply.dct_request_prod_from_firm.items()
})
self.dct_num_trial_up_product_removed[product] += 1
def handle_request(self):
print(self.name, 'handle_request')
for product, list_firm in self.dct_request_prod_from_firm.items():
# if self.dct_prod_capacity[product] > 0:
# if len(list_firm) == 1:
# self.accept_request(list_firm[0], product)
print(product.code, [firm.name for firm in list_firm])
def accept_request(self, down_firm, product):
self.firm_network.graph.add_edges_from([
(self.firm_network.positions[self],
self.firm_network.positions[down_firm], {
'Product': product.code
})
])
self.dct_prod_capacity[product] -= 1
self.dct_request_prod_from_firm[product].remove(down_firm)
down_firm.a_list_up_product_removed.remove(product)
def clean_before_trial(self):
self.dct_request_prod_from_firm = {}

136
model.py
View File

@ -3,16 +3,19 @@ import pandas as pd
import numpy as np import numpy as np
import networkx as nx import networkx as nx
from firm import FirmAgent from firm import FirmAgent
from product import ProductAgent
sample = 0 sample = 0
seed = 0 seed = 0
n_iter = 3 n_iter = 3
dct_list_init_remove_firm_prod = {0: ['1.4.4'], 2: ['1.1.3']} dct_list_init_remove_firm_prod = {0: ['1.4.4'], 2: ['1.1.3']}
n_max_trial = 2
dct_sample_para = { dct_sample_para = {
'sample': sample, 'sample': sample,
'seed': seed, 'seed': seed,
'n_iter': n_iter, 'n_iter': n_iter,
'dct_list_init_remove_firm_prod': dct_list_init_remove_firm_prod 'n_max_trial': n_max_trial,
'dct_list_init_remove_firm_prod': dct_list_init_remove_firm_prod,
} }
@ -20,8 +23,9 @@ class Model(ap.Model):
def setup(self): def setup(self):
self.sample = self.p.sample self.sample = self.p.sample
self.nprandom = np.random.default_rng(self.p.seed) self.nprandom = np.random.default_rng(self.p.seed)
self.dct_list_remove_firm_prod = self.p.dct_list_init_remove_firm_prod
self.int_n_iter = int(self.p.n_iter) 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
# init graph bom # init graph bom
BomNodes = pd.read_csv('BomNodes.csv', index_col=0) BomNodes = pd.read_csv('BomNodes.csv', index_col=0)
@ -67,24 +71,34 @@ class Model(ap.Model):
G_Firm.nodes[succ_firm]['Revenue_Log'] G_Firm.nodes[succ_firm]['Revenue_Log']
for succ_firm in list_succ_firms for succ_firm in list_succ_firms
] ]
# 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 = [ list_prob = [
(v - min(list_revenue_log) + 1) / size / sum(list_revenue_log)
(max(list_revenue_log) - min(list_revenue_log) + 1) for size in list_revenue_log
for v in list_revenue_log
] ]
list_flag = [ succ_firm = self.nprandom.choice(list_succ_firms,
self.nprandom.choice([1, 0], p=[prob, 1 - prob]) p=list_prob)
for prob in list_prob
]
# print(list(zip(list_succ_firms,list_flag,list_prob)))
list_added_edges = [(node, succ_firm, { list_added_edges = [(node, succ_firm, {
'Product': product_code 'Product': product_code
}) for succ_firm, flag in zip(list_succ_firms, list_flag) })]
if flag == 1]
G_Firm.add_edges_from(list_added_edges) G_Firm.add_edges_from(list_added_edges)
# print('-' * 20) # print('-' * 20)
self.firm_network = ap.Network(self, G_Firm) 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([node.label for node in self.firm_network.nodes])
# print([list(self.firm_network.graph.predecessors(node)) # print([list(self.firm_network.graph.predecessors(node))
# for node in self.firm_network.nodes]) # for node in self.firm_network.nodes])
@ -92,6 +106,15 @@ class Model(ap.Model):
# for node in self.firm_network.nodes]) # for node in self.firm_network.nodes])
# print([v for v in self.firm_network.graph.nodes(data=True)]) # 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)
# init firm # init firm
for ag_node, attr in self.firm_network.graph.nodes(data=True): for ag_node, attr in self.firm_network.graph.nodes(data=True):
firm_agent = FirmAgent( firm_agent = FirmAgent(
@ -100,38 +123,59 @@ class Model(ap.Model):
name=attr['Name'], name=attr['Name'],
type_region=attr['Type_Region'], type_region=attr['Type_Region'],
revenue_log=attr['Revenue_Log'], revenue_log=attr['Revenue_Log'],
list_product=attr['Product_Code'], a_list_product=self.a_list_total_products.select([
# init capacity as the degree of out edges code in attr['Product_Code']
capacity=self.firm_network.graph.out_degree(ag_node)) for code in self.a_list_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:
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.firm_network.add_agents([firm_agent], [ag_node])
self.a_list_total_firms = ap.AgentList(self, self.firm_network.agents) self.a_list_total_firms = ap.AgentList(self, self.firm_network.agents)
# print(list(zip(self.a_list_total_firms.code, # print(list(zip(self.a_list_total_firms.code,
# self.a_list_total_firms.name, # self.a_list_total_firms.name,
# self.a_list_total_firms.capacity))) # self.a_list_total_firms.capacity)))
# set the initial firm product that are removed # 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(): for firm_code, list_product in self.dct_list_remove_firm_prod.items():
firm = self.a_list_total_firms.select( firm = self.a_list_total_firms.select(
self.a_list_total_firms.code == firm_code)[0] self.a_list_total_firms.code == firm_code)[0]
for product in list_product: t_dct[firm] = self.a_list_total_products.select([
assert product in firm.list_product, \ code in list_product
f"product {product} not in firm {firm_code}" for code in self.a_list_total_products.code
firm.dct_product_is_removed[product] = True ])
self.dct_list_remove_firm_prod = t_dct
# 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, \
f"product {product.code} not in firm {firm.code}"
firm.a_list_product_removed.append(product)
def update(self): def update(self):
# Update the firm that is removed # update the firm that is removed
self.dct_list_remove_firm_prod = {} self.dct_list_remove_firm_prod = {}
for firm in self.a_list_total_firms: for firm in self.a_list_total_firms:
for product, flag in firm.dct_product_is_removed.items(): if len(firm.a_list_product_removed) > 0:
if flag is True: self.dct_list_remove_firm_prod[
if firm.code in self.dct_list_remove_firm_prod.keys(): firm] = firm.a_list_product_removed
self.dct_list_remove_firm_prod[firm.code].append(
product)
else:
self.dct_list_remove_firm_prod[firm.code] = [product]
# print(self.dct_list_remove_firm_prod) # print(self.dct_list_remove_firm_prod)
# Stop simulation if reached terminal number of iteration # stop simulation if reached terminal number of iteration
if self.t == self.int_n_iter or len( if self.t == self.int_n_iter or len(
self.dct_list_remove_firm_prod) == 0: self.dct_list_remove_firm_prod) == 0:
self.stop() self.stop()
@ -141,14 +185,34 @@ class Model(ap.Model):
dct_key_list = list(self.dct_list_remove_firm_prod.keys()) dct_key_list = list(self.dct_list_remove_firm_prod.keys())
self.nprandom.shuffle(dct_key_list) self.nprandom.shuffle(dct_key_list)
self.dct_list_remove_firm_prod = { self.dct_list_remove_firm_prod = {
key: self.dct_list_remove_firm_prod[key] key: self.dct_list_remove_firm_prod[key].shuffle()
for key in dct_key_list for key in dct_key_list
} }
for firm_code, list_product in self.dct_list_remove_firm_prod.items(): # print(self.dct_list_remove_firm_prod)
firm = self.a_list_total_firms.select(
self.a_list_total_firms.code == firm_code)[0] # remove_edge_to_cus_and_cus_up_prod
for product in list_product: for firm, a_list_product in self.dct_list_remove_firm_prod.items():
firm.remove_edge_to_customer_if_removed(product) for product in a_list_product:
firm.remove_edge_to_cus_and_cus_up_prod(product)
for n_trial in range(self.int_n_max_trial):
print('=' * 20, n_trial, '=' * 20)
# seek_alt_supply
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)
firm.seek_alt_supply()
# handle_request
for firm in self.a_list_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()
# do not use:
# self.a_list_total_firms.dct_request_prod_from_firm = {} why?
def end(self): def end(self):
pass pass
@ -189,6 +253,6 @@ class Model(ap.Model):
model = Model(dct_sample_para) model = Model(dct_sample_para)
model.setup() model.setup()
model.draw_network()
model.update() model.update()
model.step() model.step()
# model.draw_network()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

16
product.py Normal file
View File

@ -0,0 +1,16 @@
import agentpy as ap
class ProductAgent(ap.Agent):
def setup(self, code, name):
self.product_network = self.model.product_network
self.code = code
self.name = name
def a_successors(self):
nodes = self.product_network.graph.successors(
self.product_network.positions[self])
return ap.AgentList(
self.model,
[ap.AgentIter(self.model, node).to_list()[0] for node in nodes])

Binary file not shown.

View File

@ -1,9 +1,48 @@
agentpy==0.1.5 agentpy==0.1.5
alabaster==0.7.13
Babel==2.12.1
certifi @ file:///C:/b/abs_85o_6fm0se/croot/certifi_1671487778835/work/certifi
charset-normalizer==3.0.1
colorama==0.4.6
cycler==0.11.0
decorator==5.1.1
dill==0.3.6
docutils==0.19
idna==3.4
imagesize==1.4.1
importlib-metadata==6.0.0
Jinja2==3.1.2
joblib==1.2.0
kiwisolver==1.4.4
MarkupSafe==2.1.2
matplotlib==3.3.4 matplotlib==3.3.4
matplotlib-inline==0.1.6 matplotlib-inline==0.1.6
multiprocess==0.70.14
networkx==2.5 networkx==2.5
numpy==1.20.3 numpy==1.20.3
numpydoc==1.1.0 numpydoc==1.1.0
packaging==23.0
pandas==1.4.1 pandas==1.4.1
pandas-stubs==1.2.0.39 pandas-stubs==1.2.0.39
pygraphviz==1.9 Pillow==9.4.0
Pygments==2.14.0
pygraphviz @ file:///C:/Users/ASUS/OneDrive/Project/ScrAbm/Dissertation/IIabm/pygraphviz-1.9-cp38-cp38-win_amd64.whl
pyparsing==3.0.9
python-dateutil==2.8.2
pytz==2022.7.1
requests==2.28.2
SALib==1.4.7
scipy==1.10.1
six==1.16.0
snowballstemmer==2.2.0
Sphinx==6.1.3
sphinxcontrib-applehelp==1.0.4
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
traitlets==5.9.0
urllib3==1.26.14
wincertstore==0.2
zipp==3.15.0

View File

@ -0,0 +1,9 @@
agentpy==0.1.5
matplotlib==3.3.4
matplotlib-inline==0.1.6
networkx==2.5
numpy==1.20.3
numpydoc==1.1.0
pandas==1.4.1
pandas-stubs==1.2.0.39
pygraphviz==1.9

60
test.ipynb Normal file
View File

@ -0,0 +1,60 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"\n",
"np.random.randint(0.5, 3.5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "base",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.8"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "bcdafc093860683ffb58d6956591562b7f8ed5d58147d17d71a5d4d6605a08df"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}