2023-07-24 15:07:19 +08:00
|
|
|
|
import agentpy as ap
|
|
|
|
|
import numpy as np
|
2023-07-25 21:32:08 +08:00
|
|
|
|
import pandas as pd
|
2023-07-24 15:07:19 +08:00
|
|
|
|
from collections import deque
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class InventorySystem(ap.Agent):
|
2023-07-25 21:32:08 +08:00
|
|
|
|
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_ary_material_state_to_use: np.ndarray # 当期预期使用的原材料
|
|
|
|
|
ev_ary_material_to_use: np.ndarray # 当期实际消耗的原材料
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
ev_ary_is_order_material: np.ndarray # 是否订购产品
|
|
|
|
|
ev_ary_num_material_to_order: np.ndarray # 订购数量
|
|
|
|
|
ev_ary_num_material_order_done: np.ndarray # 当期送到的数量
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
|
|
|
|
# set the lead time of material replenishment
|
2023-07-25 21:32:08 +08:00
|
|
|
|
xv_ary_lead_time: np.ndarray # 原材料订货的等待时间
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
|
|
|
|
# the list of materials in transit
|
2023-07-25 21:32:08 +08:00
|
|
|
|
ev_lst_trans_quan_material: list # Iss传递给Pss的原材料数量
|
|
|
|
|
ev_lst_backtrans_quan_material: list # Pss退回的原材料数量
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Material list
|
2023-07-25 21:32:08 +08:00
|
|
|
|
xv_ary_material: np.ndarray
|
2023-07-24 15:07:19 +08:00
|
|
|
|
xv_ary_bom: np.ndarray
|
|
|
|
|
|
|
|
|
|
# 原材料订购的开始时间和到达时间
|
2023-07-25 21:32:08 +08:00
|
|
|
|
ev_ary_order_time: np.ndarray
|
|
|
|
|
ev_ary_arrive_time: np.ndarray
|
|
|
|
|
|
|
|
|
|
xv_product_num: int
|
|
|
|
|
xv_material_num: int
|
|
|
|
|
|
|
|
|
|
xv_ary_plan: np.ndarray
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
def setup(self, xv_ary_initial_material_num, xv_ary_initial_product_num, xv_product_num, xv_material_num,
|
|
|
|
|
xv_ary_bom, xv_ary_plan, xv_ary_material_id):
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
|
|
|
|
# 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
|
2023-07-25 21:32:08 +08:00
|
|
|
|
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.xv_product_num = xv_product_num # 产成品个数
|
|
|
|
|
self.xv_material_num = xv_material_num # 原材料个数
|
|
|
|
|
self.ev_ary_num_material_order_done = np.zeros((xv_material_num,)) # 当期原材料送到的数量 115x1
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
|
|
|
|
# set the lead time of materials
|
|
|
|
|
# 读取各个原材料的历史平均交货周期 bom table
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.xv_ary_lead_time = xv_ary_bom[:, (1, 4)] # 每一种原材料的到货时间(有重复)
|
2023-07-24 15:07:19 +08:00
|
|
|
|
# 切换成原材料
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.ev_ary_is_order_material = np.array([False for i in range(xv_material_num)]) # 是否订购原材料
|
|
|
|
|
self.ev_ary_num_material_to_order = np.zeros((xv_material_num,)) # 原材料订货数量
|
|
|
|
|
self.ev_ary_material_state_to_use = np.zeros((xv_material_num,)) # 一个周期内按照设定生产状态完全生产 原材料消耗数量 计划
|
|
|
|
|
self.ev_ary_material_to_use = np.zeros((xv_material_num,)) # 当期实际消耗的原材料数量
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.xv_ary_material = xv_ary_material_id # 原材料顺序
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.xv_ary_bom = xv_ary_bom # bom表
|
|
|
|
|
self.xv_ary_plan = xv_ary_plan # plan表
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
|
|
|
|
self.ev_lst_trans_quan_material = [] # Iss传递给Pss的原材料数量
|
|
|
|
|
self.ev_lst_backtrans_quan_material = [] # Pss退回的原材料数量
|
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.ev_ary_order_time = np.zeros((xv_material_num,)) # 原材料订货时间戳
|
|
|
|
|
self.ev_ary_arrive_time = np.zeros((xv_material_num,)) # 原材料到货时间戳
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
# def material_state_to_use(self, ev_int_produce_type, xv_plan_excel):
|
|
|
|
|
# # 读取Oss决定的生产状态,根据生产状态所需的原材料进行汇总
|
|
|
|
|
# # self. ev_ary_material_state_to_use = np.multiply(self.xv_array_dlv_product, 原材料表 )
|
|
|
|
|
# produce_state = ev_int_produce_type # 获取生产状态
|
|
|
|
|
|
|
|
|
|
def material_state_to_use(self): # 根据生产状态 看生产一个周期需要多少原材料
|
2023-07-24 15:07:19 +08:00
|
|
|
|
# 读取Oss决定的生产状态,根据生产状态所需的原材料进行汇总
|
|
|
|
|
# self. ev_ary_material_state_to_use = np.multiply(self.xv_array_dlv_product, 原材料表 )
|
2023-07-25 21:32:08 +08:00
|
|
|
|
produce_state = self.model.the_firm.the_os.ev_int_produce_type # 获取生产状态
|
|
|
|
|
produce_plan = self.xv_ary_plan[self.xv_ary_plan[:, 0] == produce_state] # 该生产状态下各产品的生产计划
|
|
|
|
|
for product_plan in produce_plan:
|
2023-07-24 15:07:19 +08:00
|
|
|
|
for bom in self.xv_ary_bom:
|
2023-07-25 21:32:08 +08:00
|
|
|
|
if product_plan[1] == bom[0]:
|
|
|
|
|
self.ev_ary_material_state_to_use[np.where(self.xv_ary_material == bom[1])] += product_plan[3] * \
|
|
|
|
|
bom[
|
|
|
|
|
2] # 某原材料的生产数量加等产品生产量乘单位原材料消耗量
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
def material_check(self): # 检查库存是否充足
|
2023-07-24 15:07:19 +08:00
|
|
|
|
# 根据Iss决策,核对库存是否充足,并将拥有的原材料交给Pss
|
|
|
|
|
# 可能需要一部生成原材料列表在调用
|
|
|
|
|
# Check whether materials are enough and transfer material
|
2023-07-25 21:32:08 +08:00
|
|
|
|
for i in range(self.xv_material_num):
|
|
|
|
|
self.ev_lst_trans_quan_material[i] = min(self.ev_ary_current_material[i, 1],
|
|
|
|
|
self.ev_ary_material_state_to_use[i]) # 需要数量和库存两者间的较小值
|
|
|
|
|
# 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]
|
|
|
|
|
# else:
|
|
|
|
|
# self.ev_lst_trans_quan_material[i] = self.ev_ary_current_material[i]
|
|
|
|
|
|
|
|
|
|
def consume_and_store(self, ev_ary_produced_num, ev_changed_product,
|
2023-07-24 15:07:19 +08:00
|
|
|
|
ev_lst_backtrans_material):
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.ev_lst_backtrans_quan_material = ev_lst_backtrans_material # Pss传回的原材料数量
|
2023-07-24 15:07:19 +08:00
|
|
|
|
# Update the inventory after production
|
2023-07-25 21:32:08 +08:00
|
|
|
|
for i in range(self.xv_material_num):
|
2023-07-24 15:07:19 +08:00
|
|
|
|
self.ev_ary_material_to_use[i] = self.ev_lst_trans_quan_material[i] - \
|
|
|
|
|
self.ev_lst_backtrans_quan_material[i]
|
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
if self.ev_ary_arrive_time[i] == self.model.t: # 判断材料是否到达
|
|
|
|
|
self.ev_ary_current_material[i, 1] = self.ev_ary_current_material[i, 1] - self.ev_ary_material_to_use[i] \
|
|
|
|
|
+ self.ev_ary_num_material_to_order[i] # 减消耗量 加订购量
|
2023-07-24 15:07:19 +08:00
|
|
|
|
self.ev_ary_num_material_to_order[i] = 0
|
|
|
|
|
self.ev_ary_is_order_material[i] = False
|
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.ev_ary_current_product[:, 1] = ev_changed_product + ev_ary_produced_num[:, 1] # 上期期末加本期生产
|
2023-07-24 15:07:19 +08:00
|
|
|
|
|
2023-07-25 21:32:08 +08:00
|
|
|
|
# return self.ev_ary_current_material, self.ev_ary_current_product
|
|
|
|
|
|
|
|
|
|
def material_replenishment(self, xv_ary_s, xv_ary_S):
|
2023-07-24 15:07:19 +08:00
|
|
|
|
# Check the inventory of material to decide whether to replenish
|
|
|
|
|
# 核对原材料数量是否低于s
|
|
|
|
|
# 带时间戳
|
2023-07-25 21:32:08 +08:00
|
|
|
|
for i in range(self.xv_material_num):
|
|
|
|
|
if self.ev_ary_current_material[i, 1] <= xv_ary_s[i, 1] and self.ev_ary_is_order_material[i] == False:
|
2023-07-24 15:07:19 +08:00
|
|
|
|
self.ev_ary_is_order_material[i] = True
|
2023-07-25 21:32:08 +08:00
|
|
|
|
self.ev_ary_num_material_to_order[i] = xv_ary_S[i, 1] - self.ev_ary_current_material[i, 1]
|
|
|
|
|
self.ev_ary_order_time[i] = self.model.t
|
|
|
|
|
self.ev_ary_arrive_time[i] = self.ev_int_order_time[i] + self.xv_ary_lead_time[
|
|
|
|
|
self.xv_ary_lead_time[:, 0] == self.ev_ary_current_material[i, 0]][0, 1]
|
2023-07-24 15:07:19 +08:00
|
|
|
|
else:
|
|
|
|
|
self.ev_ary_num_material_to_order[i] = 0
|