diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..fed8c48
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+OrderSystem.py
\ No newline at end of file
diff --git a/.idea/HTSim.iml b/.idea/HTSim.iml
new file mode 100644
index 0000000..d870a4a
--- /dev/null
+++ b/.idea/HTSim.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ab530bf
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..6b96659
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ABMfim流程00.txt b/ABMfim流程00.txt
new file mode 100644
index 0000000..4aa49c2
--- /dev/null
+++ b/ABMfim流程00.txt
@@ -0,0 +1,42 @@
+!按子系统功能!
+
+Oss:
+接收订单。
+计算到当期为止,未交付订单的各类产品与其库存之差,得到gap最大的产品,并将能获得该商品最大生产率的生产状态通知Iss和Pss。
+
+交付当期到期和已经出现延期的订单,先进先出。
+
+计算(env)延期平均时间:延期时间 * 延期产品数/10000
+
+Iss:
+按照Oss指定的生产状态,准备原材料并交付Pss(如果原材料不充足,就将能交付的先交付)
+
+每期末统计原材料使用情况,按照遗传算法提供的Sspolicy,选择是否订货(初始原材料备货为s),如果订货要随机生成该原材料的交货期。
+
+每期末要更新原材料剩余情况(上一次余值+当期到货量-当期使用量)
+
+更新产成品期末库存。
+
+
+Pss:
+根据Oss的指示,开始生产,如果原材料不充足,就按照gap大小进行生产;如果没有gap的产品了,就按照库存水平由少到多进行生产。
+(此处如果出现原材料余料,回交Iss)
+生成最终生产结果,产成品交付Iss。
+
+
+!按流程 !
+
+Oss:接收订单。计算到当期为止,未交付订单的各类产品与其库存之差,得到gap最大的产品,并将能获得该商品最大生产率的生产状态通知Iss和Pss。
+
+Iss:按照Oss指定的生产状态,准备原材料并交付Pss(如果原材料不充足,就将能交付的先交付)。
+
+Pss:根据Oss的指示,开始生产,如果原材料不充足,就按照gap大小进行生产;如果没有gap的产品了,就按照库存水平由少到多进行生产。
+(此处如果出现原材料余料,回交Iss)
+生成最终生产结果,产成品交付Iss。
+
+Iss:统计原材料使用情况,按照遗传算法提供的Sspolicy,选择是否订货(初始原材料备货为s),如果订货要随机生成该原材料的交货期。
+每期末要更新原材料剩余情况(上一次余值+当期到货量-当期使用量)。
+更新产成品期末库存。
+
+Oss:交付当期到期和已经出现延期的订单,先进先出。计算(env)延期平均时间:延期时间 * 延期产品数/10000
+
diff --git a/Environment.py b/Environment.py
new file mode 100644
index 0000000..0ca7f73
--- /dev/null
+++ b/Environment.py
@@ -0,0 +1,165 @@
+import random
+import numpy as np
+import pandas as pd
+import agentpy as ap
+from datetime import datetime
+from numpy import random
+import json
+
+from Firm import Firm
+# import passive agents
+from Order import Order
+
+from fake_api import get_plan_by_pp_id, get_bom_by_prd_id
+
+
+class FMSEnv(ap.Model):
+ # put all parameters here, not in any other places
+ # xv_int_max_order: int
+ # ev_n_order_created: int
+
+ the_firm: Firm
+
+ # record data, define below
+ # op_os_n_total_order: int
+ # op_os_n_total_order_delayed: int
+ op_os_all_delay_time: list
+ # op_os_delay_ratio: float
+ # op_is_flt_material_room_left: float
+ # op_is_flt_product_room_left: float
+
+ op_ps_str_status: str
+ op_os_to_dlv: np.ndarray
+ op_is_current_product: np.ndarray
+ op_is_current_material: np.ndarray
+ op_is_trans_material: np.ndarray
+ op_ps_back_trans_material: np.ndarray
+ op_ps_produced_num: np.ndarray
+ op_is_ip_mat_id: np.ndarray
+ op_ip_prd_s: np.ndarray
+ op_ip_prd_big_s: np.ndarray
+ op_ip_prd_est_pfm: int
+
+ def __init__(self, dct_all_para, _run_id=None):
+ super().__init__()
+
+ # create agents here
+ self.the_firm = Firm(env=self, dct_all_para=dct_all_para)
+
+ # get the input parameter values from the dictionary
+ self.int_stop_time = int(dct_all_para['time'])
+ # self.xv_int_max_order = int(dct_all_para['xv_int_max_order'])
+ self.xv_dlv_product_para = np.asarray(dct_all_para['xv_dlv_product_para'])
+ # self.xv_int_dlv_period_lam = int(dct_all_para['xv_int_dlv_period_lam'])
+ # self.ev_n_order_created = 0
+
+ self.running = True
+ self.t = 0
+
+ # Creation of orders should be done in the environment
+ def create_order(self):
+ # Check if maximum number of orders has been reached
+ xv_int_create_order_num = 1
+ # xv_int_create_order_num = random.poisson(lam=xv_int_create_order_lam, size=None)
+ # if self.ev_n_order_created < xv_int_max_order:
+ for i in range(xv_int_create_order_num):
+ new_order = Order(model=self, time_created=self.t, xv_dlv_product_para=self.xv_dlv_product_para,
+ leadtime=max(self.the_firm.xv_ary_lead_time))
+ return new_order
+ return None
+
+ # Execute the interactions of each time step in the simulation.
+ def step(self):
+ # organize the interactions of agents in each time step here
+ new_order = self.create_order()
+ self.the_firm.the_os.accept_order(new_order)
+
+ self.the_firm.operating()
+ self.update()
+
+ if self.t >= self.int_stop_time:
+ self.running = False
+ self.stop()
+ else:
+ print(f"running the {self.t} step")
+
+ # Record data after each simulation
+ def update(self):
+ self.op_os_n_total_order = len(self.the_firm.the_os.a_lst_order)
+ # self.op_os_n_total_order_delayed = len([e for e in self.the_firm.the_os.a_lst_order if e.xv_dlv_t < self.t])
+ self.op_os_to_dlv = self.the_firm.the_os.ev_ary_to_dlv
+ # self.op_os_all_delay_time = self.the_firm.the_os.ev_lst_all_delay_time
+
+ self.op_ps_produced_num = self.the_firm.the_ps.ev_ary_produced_num
+ self.op_ps_str_status = self.the_firm.the_ps.ev_str_status
+
+ # self.op_is_current_product = self.model.the_firm.the_is.ev_ary_current_product
+ #
+ # self.op_is_current_material = self.model.the_firm.the_is.ev_ary_current_material
+ #
+ # self.op_is_trans_material= self.model.the_firm.the_is.ev_lst_trans_material
+
+ self.op_ps_back_trans_material = self.model.the_firm.the_ps.ev_lst_backtrans_material
+
+ self.record([att for att in self.__dict__.keys() if att.startswith('op_')])
+ pass
+
+
+if __name__ == '__main__':
+ dct_para = {
+ 'time': 60,
+ # 'xv_int_max_order': random.randint(30, 50),
+ # 'xv_dlv_product_para': tuple([(30, 100), (30, 50)]),
+ # 'xv_dlv_product_para': tuple([30,40,30,20]), # 读取生产率 np.read.
+ # 'xv_int_dlv_period_lam': 8.5,
+ # 'xv_int_create_order_lam': 2,
+ # 'xv_ary_price_product': tuple([0.3,0.2,0.5,1]),
+ # 'xv_ary_cost_material_per': tuple([0.1,0.1,0.2,0.4]),
+ # 'xv_ary_volume_material': tuple([1.0, 1.5]),
+ # 'xv_ary_volume_product': tuple([3.0, 5.0]),
+ 'xv_array_lead_time': 2, # 读取原材料表格 np.read.,暂时不读
+ # 'xv_int_lead_time_c': 3,
+ # 'xv_int_lead_time_d': 1,
+ 'xv_ary_initial_product_num': pd.read_excel("initial_product.xlsx").to_numpy(),
+ 'xv_ary_initial_material_num': pd.read_excel("initial_material.xlsx").to_numpy(), # 应读取遗传算法中随机生成的s,暂写为'1' 创建两个excel分别存储产品和原材料的库存 每个excel中存系统代码和库存
+ # 'xv_flt_initial_cash': 50000.0,
+ # 'dct_status_info': json.dumps({ #需要引入生产状态表
+ # "0": {"xv_flt_produce_rate": tuple([0.0, 0.0]),
+ # "xv_ary_mat_material": tuple([0.0, 0.0]),
+ # "xv_flt_broken_rate": 0,
+ # "xv_flt_run_cost": 0.0,
+ # "name": "wait"
+ # },
+ # "1": {"xv_flt_produce_rate": tuple([90.0, 0.0]),
+ # "xv_ary_mat_material": tuple([4.0, 1.0]),
+ # "xv_flt_broken_rate": 0.03,
+ # "xv_flt_run_cost": 40.0,
+ # "name": "produceA"
+ # },
+ # "2": {"xv_flt_produce_rate": tuple([0.0, 60.0]),
+ # "xv_ary_mat_material": tuple([1.5, 5.0]),
+ # "xv_flt_broken_rate": 0.05,
+ # "xv_flt_run_cost": 50.0,
+ # "name": "produceB"
+ # },
+ # "3": {"xv_flt_produce_rate": tuple([55.0, 30.0]),
+ # "xv_ary_mat_material": tuple([2.0, 1.5]),
+ # "xv_flt_broken_rate": 0.07,
+ # "xv_flt_run_cost": 60.0,
+ # "name": "produceAB"
+ # },
+ # "-1": {"xv_flt_produce_rate": 0.0,
+ # "xv_ary_mat_material": tuple([0.0, 0.0]),
+ # "xv_flt_broken_rate": 0.1,
+ # "xv_flt_run_cost": 100.0,
+ # "name": "failed"
+ # }
+ # })
+
+ }
+ sample = ap.Sample(dct_para)
+
+ exp = ap.Experiment(FMSEnv, sample, iterations=1, record=True)
+ results = exp.run()
+ # results['variables']['FMSEnv'].to_excel(f"simulation-results-{datetime.today().strftime('%Y-%m-%d-%H-%M-%S')}.xlsx",
+ # engine='openpyxl')
diff --git a/Firm.py b/Firm.py
new file mode 100644
index 0000000..22607b7
--- /dev/null
+++ b/Firm.py
@@ -0,0 +1,37 @@
+import numpy as np
+import json
+
+from InventorySystem import InventorySystem
+from OrderSystem import OrderSystem
+from ProduceSystem import ProduceSystem
+
+# Create Company Instance
+class Firm:
+ the_os: OrderSystem
+ the_is: InventorySystem
+ the_ps: ProduceSystem
+
+ def __init__(self, env, dct_all_para):
+ self.env = env
+
+ # get the parameters here
+ self.xv_ary_initial_product_num = np.asarray(dct_all_para['xv_ary_initial_product_num'])
+ self.xv_ary_initial_material_num = np.asarray(dct_all_para['xv_ary_initial_material_num'])
+ self.dct_status_info = json.loads(dct_all_para['dct_status_info'])
+ self.xv_ary_lead_time = np.array([dct_all_para['xv_int_lead_time_a'], dct_all_para['xv_int_lead_time_b']])
+
+ # create agents here
+ self.the_os = OrderSystem(env)
+ self.the_is = InventorySystem(env, xv_ary_initial_material_num=self.xv_ary_initial_material_num,
+ xv_ary_initial_product_num=self.xv_ary_initial_product_num,
+ xv_ary_lead_time=self.xv_ary_lead_time)
+ self.the_ps = ProduceSystem(env, dct_status_info=self.dct_status_info)
+ # self.the_fs = FinancialSystem(env, xv_flt_initial_cash=self.xv_flt_initial_cash)
+
+ def operating(self):
+ self.the_os.rank_order()
+ self.the_ps.change_status()
+ self.the_ps.run_produce()
+ self.the_os.do_shipment()
+ # self.the_is.inventory_cost()
+ # self.the_fs.financial_calculating()
diff --git a/InventorySystem.py b/InventorySystem.py
new file mode 100644
index 0000000..a82daac
--- /dev/null
+++ b/InventorySystem.py
@@ -0,0 +1,128 @@
+import agentpy as ap
+import numpy as np
+from collections import deque
+
+
+class InventorySystem(ap.Agent):
+
+ xv_ary_initial_material_num: np.ndarray
+ xv_ary_initial_product_num: np.ndarray
+ ev_ary_current_material: np.ndarray #期末库存
+ ev_ary_current_product: np.ndarray #期末库存
+ ev_lst_trans_quan_material: np.ndarray # Iss传递给Pss的原材料数量
+ ev_lst_backtrans_quan_material: np.ndarray # Pss退回的原材料数量
+ ev_ary_material_state_to_use: np.ndarray # 当期预期使用的原材料
+ ev_ary_material_to_use: np.ndarray # 当期实际消耗的原材料
+ xv_array_dlv_product: np.ndarray # 产品交付
+
+ ev_ary_is_order_material: np.ndarray # 是否订购产品
+ ev_ary_num_material_to_order: np.ndarray # 订购数量
+ ev_ary_num_material_order_done: np.ndarray # 当期送到的数量
+
+ # set the lead time of material replenishment
+ xv_ary_lead_time: np.ndarray
+
+ # the list of materials in transit
+ ev_lst_trans_material: list # Iss交给Pss的原材料
+ ev_list_back_trans_material: list # Pss返回的原材料
+
+ ev_lst_material_inventory: list
+ ev_lst_product_inventory: list
+
+ # Material list
+ xv_lst_material: np.ndarray
+ xv_ary_bom: np.ndarray
+
+ # 原材料订购的开始时间和到达时间
+ ev_int_order_time: np.ndarray
+ ev_int_arrive_time: np.ndarray
+ ev_ary_num_material_order_done: np.ndarray # 当期原材料到货量
+
+ def setup(self, xv_ary_initial_material_num,
+ xv_ary_initial_product_num, xv_ary_lead_time):
+
+ # Set up the initial inventory quantity
+ self.xv_ary_initial_material_num = xv_ary_initial_material_num
+ self.xv_ary_initial_product_num = xv_ary_initial_product_num
+ self.ev_ary_current_material = xv_ary_initial_material_num # 115*2
+ self.ev_ary_current_product = xv_ary_initial_product_num #23*2
+ self.ev_ary_num_material_order_done = np.zeros((115, ))
+
+ # set the lead time of materials
+ # 读取各个原材料的历史平均交货周期 bom table
+ self.xv_ary_lead_time = pd.read_excel("bom23.xlsx").iloc[:, 4].to_numpy()
+ # 切换成原材料
+ self.ev_ary_is_order_material = np.array([False for i in range(115)])
+ self.ev_ary_num_material_to_order = np.zeros((115,)) # 初始化
+ self.ev_ary_material_state_to_use = np.zeros((115,))
+
+ self.ev_lst_material_inventory = []
+ self.ev_lst_product_inventory = []
+
+ self.xv_lst_material = pd.read_excel("rawmaterial.xlsx").to_numpy()
+
+ self.xv_ary_bom = pd.read_excel("bom23.xlsx").to_numpy()
+
+ self.ev_lst_trans_quan_material = [] # Iss传递给Pss的原材料数量
+ self.ev_lst_backtrans_quan_material = [] # Pss退回的原材料数量
+
+ self.ev_int_order_time = np.zeros((115,))
+ self.ev_int_arrive_time = np.zeros((115,))
+
+ def material_state_to_use(self, xv_ary_dlv_product, ev_int_produce_type):
+ # 读取Oss决定的生产状态,根据生产状态所需的原材料进行汇总
+ # self. ev_ary_material_state_to_use = np.multiply(self.xv_array_dlv_product, 原材料表 )
+ produce_state = 1 # 获取生产状态
+ produce_plan = xv_plan_excel[xv_plan_excel[:, 0] == produce_state]
+ for plan in produce_plan:
+ for bom in self.xv_ary_bom:
+ if plan[1] == bom[0]:
+ self.ev_ary_material_state_to_use[np.where(self.xv_lst_material == bom[1])] += plan[3] * bom[
+ 2] # 某原材料的生产数量加等产品生产量乘单位原材料消耗量
+
+ def material_check(self, ev_ary_material_state_to_use):
+ # 根据Iss决策,核对库存是否充足,并将拥有的原材料交给Pss
+ # 可能需要一部生成原材料列表在调用
+ # Check whether materials are enough and transfer material
+ index_mapping = {value: idx for idx, value in enumerate(self.ev_ary_current_material[:, 0])}
+ sorted_indices = [index_mapping[value] for value in self.xv_lst_material]
+ self.ev_ary_current_material = self.ev_ary_current_material[sorted_indices] # 按照原材料制定顺序进行重排
+ for i in range(115):
+ if self.ev_ary_current_material[i, 1] >= ev_ary_material_state_to_use[i]:
+ self.ev_lst_trans_quan_material[i] = ev_ary_material_state_to_use[i]
+ # return (self.ev_ary_current_material >= ev_ary_material_to_use).all()
+ else:
+ self.ev_lst_trans_quan_material[i] = self.ev_ary_current_material[i]
+
+ def consume_and_store(self, ev_ary_material_to_use, ev_ary_produced_num,ev_changed_product,
+ ev_lst_backtrans_material):
+ self.ev_lst_backtrans_quan_material = ev_lst_backtrans_material
+ # Update the inventory after production
+ for i in range(115):
+ self.ev_ary_material_to_use[i] = self.ev_lst_trans_quan_material[i] - \
+ self.ev_lst_backtrans_quan_material[i]
+
+ if self.ev_int_arrive_time == self.model.t: # 判断材料是否到达
+ self.ev_ary_num_material_order_done[i] += self.ev_ary_num_material_to_order[i]
+ self.ev_ary_num_material_to_order[i] = 0
+ self.ev_ary_is_order_material[i] = False
+
+ self.ev_ary_current_material = self.ev_ary_current_material - ev_ary_material_to_use \
+ + self.ev_ary_num_material_order_done
+ self.ev_ary_current_product = ev_changed_product + ev_ary_produced_num
+ return self.ev_ary_current_material, self.ev_ary_current_product
+
+ def material_replenishment(self):
+ # Check the inventory of material to decide whether to replenish
+ # 核对原材料数量是否低于s
+ # 带时间戳
+ for i in range(115):
+ if self.ev_ary_current_material[i] <= s:
+ self.ev_ary_is_order_material[i] = True
+ self.ev_ary_num_material_to_order[i] = S - self.ev_ary_current_material[i]
+ self.ev_int_order_time[i] = self.model.t
+ self.ev_int_arrive_time[i] = self.ev_int_order_time[i] + \
+ self.xv_ary_bom[self.xv_ary_bom[:, 1] == self.xv_lst_material[i]][0, 4]
+ else:
+ self.ev_ary_num_material_to_order[i] = 0
+
diff --git a/Order.py b/Order.py
new file mode 100644
index 0000000..c6a8e89
--- /dev/null
+++ b/Order.py
@@ -0,0 +1,36 @@
+import agentpy as ap
+import random
+import numpy as np
+from numpy import random
+import pandas as pd
+
+
+class Order(ap.Agent):
+
+ xv_time_created: int # 订单创建时间
+ xv_time_circle: int # 随机生成的交货周期
+ xv_dlv_t: int # 客户希望的交货时间
+ ev_actual_dlv_t: int # 实际交付时间
+
+ ev_is_delivered: bool # 订单是否已交付
+ ev_is_accepted: bool # 订单是否被接受
+ ev_int_delay_time: int # total delay time
+
+ xv_ary_dlv_product: np.ndarray
+ ev_ary_dlv_product: np.ndarray
+
+ def setup(self, time_created):
+ self.xv_time_created = time_created
+ # read the demand of 23 productions
+ df = pd.read_excel("demand23.xlsx")
+ self.xv_ary_dlv_product = df.to_numpy()
+ df = df.iloc[:, 1]
+ self.ev_ary_dlv_product = df.to_numpy()
+ self.xv_time_circle = np.random.randint(7, 11, 1)
+ self.xv_dlv_t = self.xv_time_created + self.xv_time_circle
+ self.ev_actual_dlv_t = self.xv_dlv_t
+ self.ev_int_delay_time = self.ev_actual_dlv_t - self.xv_dlv_t
+
+ # Set the initial status of order to be undelivered, accepted
+ self.ev_is_delivered = False
+ self.ev_is_accepted = False
diff --git a/OrderSystem.py b/OrderSystem.py
new file mode 100644
index 0000000..004d0b6
--- /dev/null
+++ b/OrderSystem.py
@@ -0,0 +1,103 @@
+import agentpy as ap
+import numpy as np
+from Order import Order
+import pandas as pd
+
+# 输出一个生产状态指令,一个交付情况,一个延期时间计算
+class OrderSystem(ap.Agent):
+ a_lst_order: ap.AgentList[Order]
+ ev_int_produce_type: int
+ ev_ary_to_dlv: np.ndarray # 当前order list内所有产品的综合
+ ev_ary_product_to_produce: np.ndarray # 用于计算 production gap
+ ev_lst_all_delay_time: list
+ ev_ave_delay_time: float
+ xv_plan_excel: np.ndarray
+ ev_lst_flag: list
+ ev_changed_product: np.ndarray
+ # ev_ary_dlv_product: np.ndarray??????
+
+ def setup(self):
+ # Create a list of order
+ self.a_lst_order = ap.AgentList(self, [])
+ self.ev_ary_to_dlv = np.zeros((23, 1))
+ self.ev_int_produce_type = 0
+ self.ev_ary_product_to_produce = np.zeros((23,))
+ self.ev_lst_all_delay_time = []
+ self.ev_ave_delay_time = 0
+ # self.ev_ary_dlv_product = np.zeros((23,)) ????
+ self.ev_changed_product = np.zeros((23, ))
+ self.xv_plan_excel = pd.read_excel("plan.xlsx").to_numpy()
+ pass
+
+ def accept_order(self, new_order):
+ # Determine whether the order is received and all are currently received
+ if new_order is not None:
+ new_order.ev_is_accepted = True
+ self.a_lst_order.append(new_order)
+
+ def rank_order(self):
+ # Sort order
+ self.a_lst_order = self.a_lst_order.sort('xv_dlv_t', reverse=False)
+
+ def produce_status(self):
+ # 计算a_lst_order内所有订单包含的产品总量与当期库存的gap,排序最大缺口量,选定生产状态
+ self.ev_ary_to_dlv = np.zeros((23,))
+ for order in self.model.the_firm.the_os.a_lst_order:
+ self.ev_ary_to_dlv += order.ev_ary_dlv_product # 当前天之前所有的还未满足的需求求和
+ self.ev_ary_product_to_produce[:, 1] = self.ev_ary_to_dlv - self.model.the_firm.the_is.ev_ary_current_product
+ # self.ev_ary_product_to_produce = self.model.the_firm.the_is.ev_ary_current_product - self.ev_ary_to_dlv
+ # self.ev_ary_product_to_produce > 0:
+ # 选出这些产品,按照数值大小进行分类,数值最大的产品对应的能带来最大生产率的状态,则选定为ev_int_produce_type
+ # 如果均<=0, 按照产品库存ev_ary_current_material进行排序,选择能给库存最低的产品带来最高生产率的状态
+ sorted_indices = np.argsort(self.ev_ary_product_to_produce[:, 1])[::-1]
+ sorted_data = self.ev_ary_product_to_produce[sorted_indices]
+ if sorted_data[0, 1] > 0: # 判断是否存在库存不足
+ pass
+ else:
+ sorted_indices = np.argsort(self.model.the_firm.the_is.ev_ary_current_product[:, 1]) # 对库存进行从小到大排序
+ sorted_data = self.model.the_firm.the_is.ev_ary_current_product[sorted_indices]
+
+ a = self.xv_plan_excel[self.xv_plan_excel[:, 1] == sorted_data[0, 0]] # 检索最大值的产品的四种方案或者最小库存产品的四种方案
+ sorted_indices = np.argsort(a[:, 3])[::-1]
+ sorted_data = a[sorted_indices]
+ # return sorted_data[0, 0]
+ self.ev_int_produce_type = sorted_data[0, 0]
+ return self.ev_int_produce_type
+
+ def do_shipment(self,ev_ary_current_product):
+ # Make shipments based on ranked order list
+ # 交付两次,第一次未交付完成的订单要标记,交货的时候先便利delay的订单,如果能够满足全部剩余量,就交货,如果不能
+ # 就继续在列表中存在
+ # 只有完全交付的订单,才计算delay time = order.ev_int_delay_time * 第二次交付的订单内的各类产品之和
+ # 需要更新 order.ev_ary_dlv_product
+ # Make shipments based on ranked order list
+ self.ev_lst_all_delay_time = []
+ self.ev_ave_delay_time = 0
+ self.ev_changed_product = ev_ary_current_product # 23x1 ndarray 存储本次库存的改变
+ for order in self.a_lst_order:
+ if order.xv_dlv_t == self.model.t: # 第一次交付
+ # Check and make shipment
+ order.ev_is_delivered = True
+ for i in range(len(order.ev_ary_dlv_product)):
+ if order.ev_ary_dlv_product[i] <= self.ev_changed_product[i]:
+ order.ev_ary_dlv_product[i] = 0
+ self.ev_changed_product[i] -= order.ev_ary_dlv_product[i]
+ else:
+ order.ev_is_delivered = False
+ elif order.xv_dlv_t < self.model.t and order.ev_is_delivered == False: # 第二次交付
+ order.ev_is_delivered = True
+ for i in range(len(order.ev_ary_dlv_product)):
+ if order.ev_ary_dlv_product[i] > self.ev_changed_product[i]: # 先判断能不能一次性交付
+ order.ev_is_delivered = False
+
+ if order.ev_is_delivered: # 如果一次性交付
+ delay_num = np.sum(order.ev_ary_dlv_product)
+ order.ev_ary_dlv_product = np.zeros((23,))
+ self.ev_changed_product = self.ev_changed_product - order.ev_ary_dlv_product
+
+ order.ev_actual_dlv_t = self.model.t
+ order.ev_int_delay_time = order.ev_actual_dlv_t - order.xv_dlv_t
+
+ self.ev_ave_delay_time += order.ev_int_delay_time * delay_num / 10000
+
+ return self.ev_changed_product, self.ev_ave_delay_time
diff --git a/ProduceSystem.py b/ProduceSystem.py
new file mode 100644
index 0000000..63d25b7
--- /dev/null
+++ b/ProduceSystem.py
@@ -0,0 +1,60 @@
+import agentpy as ap
+import numpy as np
+import random
+
+
+class ProduceSystem(ap.Agent):
+ ev_str_status: str # 0,6,8,10 pp_id
+ ev_lst_backtrans_material: list # 退回Iss的原材料
+ ev_ary_produce_number: np.ndarray
+
+ def setup(self, dct_status_info):
+ self.ev_str_status = 0
+ self.ev_lst_backtrans_material = []
+
+ def change_status(self):
+ self.ev_str_status = self.model.the_firm.the_os.produce_status()
+
+
+ def run_produce(self, ev_lst_material, ev_lst_trans_quan_material, ev_ary_product_to_produce, xv_plan_excel,
+ xv_ary_bom): # ev_ary_product_to_produce 是 需求和库存的gap 23x2
+ # 生产状态由Iss确定,这个函数需要计算生产数量和原材料消耗量。
+ # 如果原材料不足,就按照production gap(ev_ary_product_to_produce) 大小进行生产;如果没有gap的产品了,就按照库存水平由少到多进行生产。
+ # 输出生产结果和原材料消耗结果
+ produce_plan = xv_plan_excel[xv_plan_excel[:, 0] == self.ev_str_status]
+ sorted_indices = np.argsort(ev_ary_product_to_produce[:, 1])[::-1]
+ sorted_data = ev_ary_product_to_produce[sorted_indices] # 对gap进行从大到小排序
+ sorted_indices_product = np.argsort(self.model.the_firm.the_is.ev_ary_current_product[:, 1]) # 对库存进行从小到大排序
+ sorted_data_product = self.model.the_firm.the_is.ev_ary_current_product[sorted_indices_product]
+ self.ev_lst_backtrans_material = ev_lst_trans_quan_material
+ self.ev_ary_produce_number = []
+ for product in sorted_data:
+ if product[1] > 0: # gap存在
+ product_material = xv_ary_bom[xv_ary_bom[:, 0] == product[0]]
+ produce_number = produce_plan[produce_plan[:, 1] == product[0]][3]
+ for material in product_material:
+ produce_number = min(produce_number, int(
+ self.ev_lst_backtrans_material[np.where(ev_lst_material == material[1])] / material[
+ 2])) # 取能生产的最小个数
+ for material in product_material:
+ self.ev_lst_backtrans_material[np.where(ev_lst_material == material[1])] -= produce_number * material[
+ 2] # 更新原材料消耗情况
+ self.ev_ary_produce_number.append([product[0], produce_number])
+ sorted_data_product = sorted_data_product[sorted_data_product[:, 0] != product[0]]
+ else:
+ for current_product in sorted_data_product:
+ product_material = xv_ary_bom[xv_ary_bom[:, 0] == current_product[0]]
+ produce_number = produce_plan[produce_plan[:, 1] == current_product[0]][3]
+ for material in product_material:
+ produce_number = min(produce_number, int(
+ self.ev_lst_backtrans_material[np.where(ev_lst_material == material[1])] / material[
+ 2])) # 取能生产的最小个数
+ for material in product_material:
+ self.ev_lst_backtrans_material[np.where(ev_lst_material == material[1])] -= produce_number * \
+ material[2] # 更新原材料消耗情况
+ self.ev_ary_produce_number.append([current_product[0], produce_number])
+ break
+
+ self.ev_ary_produce_number = np.array(self.ev_ary_produce_number)
+
+ return self.ev_ary_produce_number, self.ev_lst_backtrans_material
\ No newline at end of file
diff --git a/bom23.csv b/bom23.csv
new file mode 100644
index 0000000..bd0886b
--- /dev/null
+++ b/bom23.csv
@@ -0,0 +1,208 @@
+prd_id,mtr_id,qty,unit
+ADTB331M0611,Z013V09501055,0.000347,ƽ
+ADTB331M0611,F00VC50A055,0.000418,ƽ
+ADTB331M0611,SM26040B070,0.000033,ǧ
+ADTB331M0611,D12073G2126b,0.0001,
+ADTB331M0611,YG00002,9.33E-06,
+ADTB331M0611,YHCP50A,0.00017,ǧ
+ADTB331M0611,L063-109Y,0.0001,֧
+ADTB331M0611,P06-30I,0.0001,ֻ
+ADTB331M0611,GT063T,0.000039,ǧ
+AGTR4R7V0812,Z510V12001070,0.000623,ƽ
+AGTR4R7V0812,F30VC20A070,0.000784,ƽ
+AGTR4R7V0812,EHD450Z085,0.000094,ǧ
+AGTR4R7V0812,D12087F2126,0.0001,
+AGTR4R7V0812,YG00001,2.07E-05,
+AGTR4R7V0812,YHBH421H,0.00019,ǧ
+AGTR4R7V0812,N080-130Y,0.0001,֧
+AGTR4R7V0812,P08-30I,0.0001,ֻ
+AGTR4R7V0812,GT080C,0.000071,ǧ
+AMSR2R2M0609,Z530V12001050,0.000295,ƽ
+AMSR2R2M0609,F30VC30A050,0.000345,ƽ
+AMSR2R2M0609,W19040X065,0.000045,ǧ
+AMSR2R2M0609,D12073T2126b,0.0001,
+AMSR2R2M0609,YG00001,9.33E-06,
+AMSR2R2M0609,YHBH421H,0.00011,ǧ
+AMSR2R2M0609,T063-100Y,0.0001,֧
+AMSR2R2M0609,P06-26T,0.0001,ֻ
+AMSR2R2M0609,MS063T,0.000039,ǧ
+RD1H108M12025,Z067V10201160,0.00576,ƽ
+RD1H108M12025,F00VC40A160,0.006224,ƽ
+RD1H108M12025,SM26040B190,0.000519,ǧ
+RD1H108M12025,D15147G2328y,0.0001,
+RD1H108M12025,YG00006,0.000031,
+RD1H108M12025,YHCP50A,0.00121,ǧ
+RD1H108M12025,L125-257+,0.0001,֧
+RD1H108M12025,GNH-12.5M,0.0001,ֻ
+RD1H108M12025,AW125T,0.000181,ǧ
+RD1E108M10020,Z036V09001140,0.002408,ƽ
+RD1E108M10020,F00VC40A140,0.002982,ƽ
+RD1E108M10020,SM26040B160,0.000209,ǧ
+RD1E108M10020,D15147G2328y,0.0001,
+RD1E108M10020,YG00005,0.000031,
+RD1E108M10020,YHCP50A,0.00057,ǧ
+RD1E108M10020,L100-215+,0.0001,֧
+RD1E108M10020,GNH-10F,0.0001,ֻ
+RD1E108M10020,AW100T,0.000121,ǧ
+AMSR100V1013I,Z530V12001070,0.00126,ƽ
+AMSR100V1013I,F30VC20A070,0.00147,ƽ
+AMSR100V1013I,W19040X085,0.00018,ǧ
+AMSR100V1013I,D15091TL2328,0.0001,
+AMSR100V1013I,YG00007,,ǧ
+AMSR100V1013I,YHBH421H,0.00026,ǧ
+AMSR100V1013I,T100-135Y,0.0001,֧
+AMSR100V1013I,P10-35T,0.0001,ֻ
+AMSR100V1013I,MS100T,0.000086,ǧ
+AGEN181V1625,Z280V12002170,0.009673,ƽ
+AGEN181V1625,F30VC20A170,0.010948,ƽ
+AGEN181V1625,EHD440Z200,0.001346,ǧ
+AGEN181V1625,D20180G2530,0.0001,
+AGEN181V1625,YG00006,0.000065,
+AGEN181V1625,YHBH250H,0.0028,ǧ
+AGEN181V1625,T160-270Y,0.0001,֧
+AGEN181V1625,P16-50I,0.0001,ֻ
+AGEN181V1625,EF160T,0.000261,ǧ
+CEGM680M1020,Z210V11501140,0.002884,ƽ
+CEGM680M1020,F30VC20A140,0.003164,ƽ
+CEGM680M1020,W28540X1160,0.000334,ǧ
+CEGM680M1020,D15131G2328,0.0001,
+CEGM680M1020,YG00005,0.000031,
+CEGM680M1020,YHBH250H,0.00057,ǧ
+CEGM680M1020,N100-210Y,0.0001,֧
+CEGM680M1020,P10-35I,0.0001,ֻ
+CEGM680M1020,EG100T,0.000117,ǧ
+RD2G475M1012M,Z660V12002070,0.000819,ƽ
+RD2G475M1012M,F30VC20A070,0.001057,ƽ
+RD2G475M1012M,WS28050K085,0.000127,ǧ
+RD2G475M1012M,TX15084*G2328,0.0001,
+RD2G475M1012M,YG00003,0.0000285,
+RD2G475M1012M,YHBH450H,0.00025,ǧ
+RD2G475M1012M,L100-130+,0.0001,֧
+RD2G475M1012M,GNH-10L,0.0001,ֻ
+RD2G475M1012M,AW100T,0.000082,ǧ
+AMSR4R7M0812,Z530V12001070,0.00063,ƽ
+AMSR4R7M0812,F30VC20A070,0.000735,ƽ
+AMSR4R7M0812,EHD450Z085,0.000095,ǧ
+AMSR4R7M0812,D12087T2126d,0.0001,
+AMSR4R7M0812,YG00001,2.07E-05,
+AMSR4R7M0812,YHBH421H,0.00019,ǧ
+AMSR4R7M0812,T080-130Y,0.0001,֧
+AMSR4R7M0812,P08-30T,0.0001,ֻ
+AMSR4R7M0812,MS080T,0.000072,ǧ
+AVSR2R2V0609,Z530V12001050,0.000305,ƽ
+AVSR2R2V0609,F30VC30A050,0.00037,ƽ
+AVSR2R2V0609,W19040X065,0.000046,ǧ
+AVSR2R2V0609,D12073F2126b,0.0001,
+AVSR2R2V0609,YG00001,9.33E-06,
+AVSR2R2V0609,YHBH421H,0.00011,ǧ
+AVSR2R2V0609,L063-100Y,0.0001,֧
+AVSR2R2V0609,P06-26I,0.0001,ֻ
+AVSR2R2V0609,EF063C,0.000034,ǧ
+AMSR6R8M1013,Z530V12001070,0.000903,ƽ
+AMSR6R8M1013,F30VC20A070,0.001043,ƽ
+AMSR6R8M1013,EHD450Z085,0.000136,ǧ
+AMSR6R8M1013,D15091T2328,0.0001,
+AMSR6R8M1013,YG00002,1.93E-05,
+AMSR6R8M1013,YHBH421H,0.00026,ǧ
+AMSR6R8M1013,T100-135Y,0.0001,֧
+AMSR6R8M1013,P10-35T,0.0001,ֻ
+AMSR6R8M1013,MS100T,0.000086,ǧ
+AMSR3R3M0810,Z530V12001050,0.000445,ƽ
+AMSR3R3M0810,F30VC30A050,0.00052,ƽ
+AMSR3R3M0810,EHD450Z065,0.000072,ǧ
+AMSR3R3M0810,D12073T2126b,0.0001,
+AMSR3R3M0810,YG00002,0.000019,
+AMSR3R3M0810,YHBH421H,0.00017,ǧ
+AMSR3R3M0810,T080-103Y,0.0001,֧
+AMSR3R3M0810,P08-26T,0.0001,ֻ
+AMSR3R3M0810,MS080T,0.000059,ǧ
+AMSN120M0812I,Z280V12001070,0.000651,ƽ
+AMSN120M0812I,F30VC20A070,0.000826,ƽ
+AMSN120M0812I,EHD450Z085,0.000098,ǧ
+AMSN120M0812I,D12087TL2126d,0.0001,
+AMSN120M0812I,YG00003,0.000031,
+AMSN120M0812I,YHBH250H,0.00019,ǧ
+AMSN120M0812I,T080-130Y,0.0001,֧
+AMSN120M0812I,P08-30T,0.0001,ֻ
+AMSN120M0812I,MS080T,0.000072,ǧ
+WL1H476M6L011,Z082V10001065,0.000371,ƽ
+WL1H476M6L011,F20VC50A065,0.000436,ƽ
+WL1H476M6L011,MJ24540K080,0.001368,ǧ
+WL1H476M6L011,D12087G2126,0.0001,
+WL1H476M6L011,YG00024,0.00001,
+WL1H476M6L011,YHCP50A,0.00012,ǧ
+WL1H476M6L011,L063-117+,0.0001,֧
+WL1H476M6L011,GAH-6.3L,0.0001,ֻ
+WL1H476M6L011,AW063T,0.000043,ǧ
+AMSR8R2M1013,Z530V12001070,0.001085,ƽ
+AMSR8R2M1013,F30VC20A070,0.001225,ƽ
+AMSR8R2M1013,EHD450Z085,0.000164,ǧ
+AMSR8R2M1013,D15091T2328,0.0001,
+AMSR8R2M1013,YG00001,1.93E-05,
+AMSR8R2M1013,YHBH421H,0.00026,ǧ
+AMSR8R2M1013,T100-135Y,0.0001,֧
+AMSR8R2M1013,P10-35T,0.0001,ֻ
+AMSR8R2M1013,MS100T,0.000086,ǧ
+AGFM121M1320,Z210V11501140,0.004998,ƽ
+AGFM121M1320,F30VC20A140,0.005348,ƽ
+AGFM121M1320,EHD440Z160,0.000579,ǧ
+AGFM121M1320,D15147G2328bd,0.0001,
+AGFM121M1320,YG00004,0.0000375,
+AGFM121M1320,YHBH250H,0.00099,ǧ
+AGFM121M1320,L130-215Y,0.0001,֧
+AGFM121M1320,P13-35I,0.0001,ֻ
+AGFM121M1320,EF130T,0.000155,ǧ
+AGSS100V1013,Z590V10503075,0.001493,ƽ
+AGSS100V1013,F30VC20A075,0.00162,ƽ
+AGSS100V1013,W19040X090,0.00021,ǧ
+AGSS100V1013,D15091F2328,0.0001,
+AGSS100V1013,YG00003,0.000029,
+AGSS100V1013,YHBH450H,0.00049,ǧ
+AGSS100V1013,L100-140Y,0.0001,֧
+AGSS100V1013,P10-35I,0.0001,ֻ
+AGSS100V1013,GS100C,0.000099,ǧ
+AVSR3R3V0609,Z490V12501055,0.000358,ƽ
+AVSR3R3V0609,F30VC20A055,0.000413,ƽ
+AVSR3R3V0609,W19040X070,0.000053,ǧ
+AVSR3R3V0609,D12073F2126b,0.0001,
+AVSR3R3V0609,YG00001,9.33E-06,
+AVSR3R3V0609,YHBH421H,0.00011,ǧ
+AVSR3R3V0609,L063-100Y,0.0001,֧
+AVSR3R3V0609,P06-20I,0.0001,ֻ
+AVSR3R3V0609,EF063C,0.000034,ǧ
+ACSR4R7V0812,Z530V12001070,0.000623,ƽ
+ACSR4R7V0812,F30VC20A070,0.000728,ƽ
+ACSR4R7V0812,EHD450Z085,0.000094,ǧ
+ACSR4R7V0812,D12087F2126,0.0001,
+ACSR4R7V0812,YG00001,2.07E-05,
+ACSR4R7V0812,YHBH421H,0.00019,ǧ
+ACSR4R7V0812,N080-130Y,0.0001,֧
+ACSR4R7V0812,P08-30I,0.0001,ֻ
+ACSR4R7V0812,GS080T,0.000072,ǧ
+AMSR1R0M0609VI,Z480V12002050,0.000115,ƽ
+AMSR1R0M0609VI,F30VC30A050,0.000165,ƽ
+AMSR1R0M0609VI,EHD450Z065,0.000018,ǧ
+AMSR1R0M0609VI,D12073TL2126b,0.0001,
+AMSR1R0M0609VI,YG00002,9.33E-06,
+AMSR1R0M0609VI,YHBH421H,0.00011,ǧ
+AMSR1R0M0609VI,T063-100Y,0.0001,֧
+AMSR1R0M0609VI,P06-26T,0.0001,ֻ
+AMSR1R0M0609VI,MS063T,0.000039,ǧ
+AGTR4R7V0812V,Z510V12001070,0.000623,ƽ
+AGTR4R7V0812V,F30VC20A070,0.000784,ƽ
+AGTR4R7V0812V,W19020K085,0.000094,ǧ
+AGTR4R7V0812V,D12087F2126,0.0001,
+AGTR4R7V0812V,YG00001,2.07E-05,
+AGTR4R7V0812V,YHBH421H,0.00019,ǧ
+AGTR4R7V0812V,N080-130Y,0.0001,֧
+AGTR4R7V0812V,P08-30I,0.0001,ֻ
+AGTR4R7V0812V,GT080C,0.000071,ǧ
+WL1V477M10016,Z047V10401100,0.00153,ƽ
+WL1V477M10016,F00VC40A100,0.00202,ƽ
+WL1V477M10016,SM26050B120,0.00017,ǧ
+WL1V477M10016,D15131G2328,0.0001,
+WL1V477M10016,YG00004,0.00003,
+WL1V477M10016,YHCP50A,0.00049,ǧ
+WL1V477M10016,L100-175+,0.0001,֧
+WL1V477M10016,GNH-10F,0.0001,ֻ
+WL1V477M10016,AW100T,0.000101,ǧ
diff --git a/bom23.xlsx b/bom23.xlsx
new file mode 100644
index 0000000..43a982b
Binary files /dev/null and b/bom23.xlsx differ
diff --git a/demand23.xlsx b/demand23.xlsx
new file mode 100644
index 0000000..b661fff
Binary files /dev/null and b/demand23.xlsx differ
diff --git a/fake_api.py b/fake_api.py
new file mode 100644
index 0000000..341cf75
--- /dev/null
+++ b/fake_api.py
@@ -0,0 +1,20 @@
+import pandas as pd
+
+df_bom = pd.read_excel('bom23.xlsx', engine='openpyxl')
+
+df_plan = pd.read_excel('plan.xlsx', engine='openpyxl')
+
+
+def get_bom_by_prd_id(prd_id):
+ df_sub = df_bom.loc[df_bom['prd_id'] == prd_id]
+ return df_sub[['mtr_id', 'qty']]
+
+
+def get_plan_by_pp_id(pp_id):
+ df_sub = df_plan.loc[df_plan['pp_id'] == int(pp_id)]
+ return df_sub[['prd_id', 'size', 'rate']]
+
+
+if __name__ == '__main__':
+ print(get_bom_by_prd_id('ADTB331M0611'))
+ print(get_plan_by_pp_id('0')) # 0, 6, 8, 10
diff --git a/plan.xlsx b/plan.xlsx
new file mode 100644
index 0000000..2b9bb7c
Binary files /dev/null and b/plan.xlsx differ
diff --git a/rawmaterial.xlsx b/rawmaterial.xlsx
new file mode 100644
index 0000000..fd5bbd1
Binary files /dev/null and b/rawmaterial.xlsx differ