From 0d414c031837ff74829c08b7f4f650c302e863d3 Mon Sep 17 00:00:00 2001 From: Saturneric Date: Mon, 19 Apr 2021 03:34:13 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=A7=E7=BB=AD=E7=BC=96=E5=86=99=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/dataSources.xml | 12 ++++ .idea/misc.xml | 2 +- .idea/scheduling.iml | 2 +- .idea/sqldialects.xml | 9 +++ dataset_importer.py | 138 ++++++++++++++++++++++++++++++++++++++++++ model.py | 54 +++++++++++++---- runtime.py | 43 ++++++++++++- scheduling.py | 60 ++++++++++++++++-- utils.py | 17 ++++++ 9 files changed, 318 insertions(+), 19 deletions(-) create mode 100644 .idea/dataSources.xml create mode 100644 .idea/sqldialects.xml create mode 100644 dataset_importer.py create mode 100644 utils.py diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..2084c46 --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,12 @@ + + + + + mysql.8 + true + com.mysql.cj.jdbc.Driver + jdbc:mysql://gz-cynosdbmysql-grp-4ynd0gkb.sql.tencentcdb.com:23027/outsoursing_dataset + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 30078b5..0816e31 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/.idea/scheduling.iml b/.idea/scheduling.iml index e1774a4..dde2ab6 100644 --- a/.idea/scheduling.iml +++ b/.idea/scheduling.iml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml new file mode 100644 index 0000000..c9c7d12 --- /dev/null +++ b/.idea/sqldialects.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/dataset_importer.py b/dataset_importer.py new file mode 100644 index 0000000..db35475 --- /dev/null +++ b/dataset_importer.py @@ -0,0 +1,138 @@ +from typing import List, Dict +import mysql.connector +import model + + +def import_order(res) -> Dict[str, model.Order]: + """ + 导入订单 + :param res: 数据库返回的行对象 + :return: 订单对象集合 + """ + + orders: Dict[str, model.Order] = {} + + for record in res: + order: model.Order = model.Order(record[0], record[1]) + order.set_time(record[2], record[3]) + orders[order.order_id] = order + + return orders + + +def import_product(res) -> Dict[str, model.Product]: + """ + 导入产品 + :param res: 数据库返回的行对象 + :return: 产品对象集合 + """ + + products: Dict[str, model.Product] = {} + + for record in res: + product: model.Product = model.Product(record[0], record[1]) + products[product.product_id] = product + + return products + + +def import_order_product(res, orders: Dict[str, model.Order], products: Dict[str, model.Product]) -> None: + for record in res: + orders[record[0]].add_product(products[record[1]], record[2]) + + +def import_product_component(res, products: Dict[str, model.Product]): + for record in res: + products[record[0]].add_semi_product(products[record[1]], record[2]) + + +def import_process(res, products: Dict[str, model.Product]) -> Dict[str, model.Process]: + processes: Dict[str, model.Process] = {} + + for record in res: + process: model.Process = model.Process(record[0], record[1], products[record[2]], record[9]) + process.set_mode_quantity(record[5], record[6], record[7]) + process.set_product_time(record[8]) + products[record[2]].set_process(process) + processes[process.pcs_id] = process + + for record in res: + + pre_process = None + if record[3] is not None: + pre_process = processes[record[3]] + + last_process = None + if record[4] is not None: + last_process = processes[record[4]] + + processes[record[0]].set_pre_last_pcs(pre_process, last_process) + + return processes + + +def import_resource(res) -> Dict[str, model.Resource]: + resources: Dict[str, model.Resource] = {} + + for record in res: + resource = model.Resource(record[0], record[1], record[2], record[4]) + resource.set_amount(record[3]) + resources[resource.rsc_id] = resource + + return resources + + +def import_resource_attributes(res, resources: Dict[str, model.Resource]): + for record in res: + resources[record[0]].set_basic_attr(record[1]) + resources[record[0]].add_attr(record[2]) + + +def import_dataset(): + conn = mysql.connector.connect( + host="gz-cynosdbmysql-grp-4ynd0gkb.sql.tencentcdb.com", + port="23027", + user="outsoursing", + password="Npu1234!", + database="outsoursing_dataset") + + cur = conn.cursor() + + cur.execute("SELECT * FROM aps_order;") + res = cur.fetchall() + + orders = import_order(res) + + cur.execute("SELECT * FROM aps_product;") + res = cur.fetchall() + + products = import_product(res) + + cur.execute("SELECT * FROM aps_order_product;") + res = cur.fetchall() + + import_order_product(res, orders, products) + + cur.execute("SELECT * FROM aps_product_component;") + res = cur.fetchall() + + import_product_component(res, products) + + cur.execute("SELECT * FROM aps_process;") + res = cur.fetchall() + + processes = import_process(res, products) + + cur.execute("SELECT * FROM aps_resource;") + res = cur.fetchall() + + resources = import_resource(res) + + cur.execute("SELECT * FROM aps_resource_arrtibutes;") + res = cur.fetchall() + + import_resource_attributes(res, resources) + + conn.close() + + return orders, products, processes, resources diff --git a/model.py b/model.py index 1a5311a..278d524 100644 --- a/model.py +++ b/model.py @@ -1,8 +1,11 @@ from __future__ import annotations from datetime import datetime -from typing import List, Dict, Set +from typing import List, Dict, Set, Optional +from utils import * +@auto_str +@auto_repr class Order: def __init__(self, order_id: str, description: str): @@ -23,27 +26,43 @@ class Order: }) +@auto_str +@auto_repr class Product: def __init__(self, product_id: str, product_name: str): self.product_id: str = product_id self.product_name: str = product_name + self.semi_products: List[Dict[str, any]] = [] + self.process: Optional[Process] = None + + def add_semi_product(self, semi_product: Product, amount): + if semi_product.product_id != self.product_id: + self.semi_products.append({ + "semi_product": semi_product, + "amount": amount + }) + + def set_process(self, process): + self.process = process +@auto_str +@auto_repr class Workspace: def __init__(self, name: str): self.name: str = name +@auto_str +@auto_repr class Process: def __init__(self, pcs_id: str, pcs_name: str, product: Product, - prev_pcs: Process, - last_pcs: Process, workspace: Workspace): self.pcs_id: str = pcs_id @@ -56,11 +75,16 @@ class Process: self.pdt_time: int = 0 - self.prev_pcs: Process = prev_pcs - self.last_pcs: Process = last_pcs + self.prev_pcs: Optional[Process] = None + self.last_pcs: Optional[Process] = None + self.res_needs: List[Dict[str, any]] = [] self.workspace: Workspace = workspace + def set_pre_last_pcs(self, prev_pcs: Optional[Process], last_pcs: Optional[Process]): + self.prev_pcs: Process = prev_pcs + self.last_pcs: Process = last_pcs + def set_mode_quantity(self, production_mode: int, min_quantity: int, max_quantity: int): self.production_mode: int = production_mode self.min_quantity: int = max_quantity @@ -76,20 +100,26 @@ class Process: }) +@auto_str +@auto_repr class Resource: def __init__(self, rsc_id: str, rsc_name: str, rsc_type: str, workspace: Workspace): self.rsc_id: str = rsc_id self.rsc_name: str = rsc_name self.rsc_type: str = rsc_type + self.amount: int = 0 - self.attr: str = "" - self.basic_attrs: Set = set() + self.basic_attr: Optional[str] = None + self.attrs: Set = set() self.workspace: Workspace = workspace - def set_attr(self, attr: str, basic_attrs: List[str]): - if attr not in basic_attrs: - raise Exception("Attr NOT IN Basic_Attrs") + def set_amount(self, amount: int): + self.amount: int = amount - self.attr: str = attr - self.basic_attrs: List[str] = basic_attrs + def set_basic_attr(self, basic_attr: Optional[str]): + self.basic_attr = basic_attr + self.attrs.add(basic_attr) + + def add_attr(self, attr: str): + self.attrs.add(attr) diff --git a/runtime.py b/runtime.py index 214729b..e079455 100644 --- a/runtime.py +++ b/runtime.py @@ -1,6 +1,6 @@ import model from datetime import datetime, timedelta -from typing import List +from typing import List, Dict class RuntimeProduct: @@ -25,6 +25,47 @@ class ProductLine: self.runtime_products.append(runtime_product) +class RuntimeProductLines: + + def __init__(self): + self.product_lines: Dict[str, ProductLine] = {} + self.product_lines_list: List[ProductLine] = [] + + def add_runtime_product(self, runtime_product: RuntimeProduct): + + if runtime_product.product.product_id not in self.product_lines.keys(): + self.product_lines[runtime_product.product.product_id] = ProductLine(runtime_product.product) + self.product_lines_list = list(self.product_lines.values()) + + self.product_lines[runtime_product.product.product_id].add_runtime_product(runtime_product) + + def pop_runtime_product(self): + if self.product_lines_list is None: + return None + + earliest_end_time_runtime_product_line = self.product_lines_list[0] + + earliest_end_time_runtime_product = None + if len(earliest_end_time_runtime_product_line.runtime_products) > 0: + earliest_end_time_runtime_product = earliest_end_time_runtime_product_line.runtime_products[0] + + for product_line in self.product_lines_list: + if len(product_line.runtime_products) > 0: + runtime_product = product_line.runtime_products[0] + if earliest_end_time_runtime_product is None \ + or runtime_product.ddl < earliest_end_time_runtime_product.ddl: + earliest_end_time_runtime_product = runtime_product + earliest_end_time_runtime_product_line = product_line + + if len(earliest_end_time_runtime_product_line.runtime_products) > 0: + earliest_end_time_runtime_product_line.runtime_products.pop(0) + + return earliest_end_time_runtime_product + + def reset(self): + self.product_lines_list = list(self.product_lines) + + class RuntimeProcess: def __init__(self, runtime_product: RuntimeProduct, process: model.Process): diff --git a/scheduling.py b/scheduling.py index 53ddade..413fddb 100644 --- a/scheduling.py +++ b/scheduling.py @@ -1,14 +1,66 @@ import runtime import model import csv -from typing import List +from typing import List, Dict from datetime import datetime import time +import dataset_importer -def read_dataset(): - order_list: List[model.Order] = [] +def orders_processor(orders: Dict[str, model.Order]) -> List[runtime.RuntimeProduct]: + orders_list = list(orders.values()) + sorted_orders_list = sorted(orders_list, key=lambda order: order.latest_end_time) + products_lines = runtime.RuntimeProductLines() + + for sorted_order in sorted_orders_list: + for item in sorted_order.products: + runtime_product = runtime.RuntimeProduct(item["product"], item["amount"]) + runtime_product.set_ddl(sorted_order.latest_end_time) + products_lines.add_runtime_product(runtime_product) + + runtime_product = products_lines.pop_runtime_product() + + produce_tree = [] + + produce_list = [] + + while runtime_product is not None: + search_semi_products(0, produce_tree, produce_list, runtime_product) + runtime_product = products_lines.pop_runtime_product() + + return produce_list + + +def search_semi_products(floor, produce_tree, produce_list, runtime_product): + + runtime_semi_products = [] + produce_tree.append({"runtime_product": runtime_product, "runtime_semi_products": runtime_semi_products}) + # print("F", runtime_product.product.product_id, runtime_product.ddl) + if len(runtime_product.product.semi_products) > 0: + + for item in runtime_product.product.semi_products: + + runtime_semi_product = runtime.RuntimeProduct(item["semi_product"], item["amount"]) + runtime_semi_product.set_ddl(runtime_product.ddl) + + # print("C", runtime_semi_product.product.product_id, runtime_semi_product.ddl) + + search_semi_products(floor+1, runtime_semi_products, produce_list, runtime_semi_product) + + print("L", floor, runtime_product.product.product_id, runtime_product.ddl) + produce_list.append(runtime_product) + + +def products_processor(runtime_products: List[runtime.RuntimeProduct]): + processes_list: List[runtime.RuntimeProcess] = [] + + for runtime_product in runtime_products: + runtime_process: runtime.RuntimeProcess = \ + runtime.RuntimeProcess(runtime_product, runtime_product.product.process) + + processes_list.append(runtime_process) if __name__ == "__main__": - read_dataset() \ No newline at end of file + orders, products, processes, resources = dataset_importer.import_dataset() + orders_processor(orders) \ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..e119428 --- /dev/null +++ b/utils.py @@ -0,0 +1,17 @@ +def auto_str(cls): + def __str__(self): + return '%s(%s)' % ( + type(self).__name__, + ', '.join('%s=%s' % item for item in vars(self).items()) + ) + + cls.__str__ = __str__ + return cls + + +def auto_repr(cls): + def __repr__(self): + return str(self.__dict__) + + cls.__repr__ = __repr__ + return cls