Skip to content

Commit

Permalink
General update (#24)
Browse files Browse the repository at this point in the history
* Update backward scheduling

* Update

---------

Co-authored-by: LongxingTan <tanlongxing888@163.com>
  • Loading branch information
yuetan1988 and LongxingTan committed Jul 21, 2023
1 parent e59f208 commit 5a443c2
Show file tree
Hide file tree
Showing 44 changed files with 1,349 additions and 171 deletions.
15 changes: 14 additions & 1 deletion docs/source/application.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,27 @@ BOM: Bill Of Materials
- 物料中心


理解
过程
----------

实际APS会涉及到各个车间,各个工序的复杂区分,以及BOM中涉及到多工厂的部分。
- 其实和APS关系不大,APS只要把最后一层工序展开,最后一层BOM展开,按实际的资源约束进行计算,最后只是展现形式上的区别

首先解决m个工序、n个机器的车间排产问题,然后把实际问题往车间问题靠。

1、根据一定的规则(产品总工作时长、工序B的最早开工时间等)获得产品的优先级
2、初始化任务的初始状态,除了每个产品的工序A为可开工状态其余皆为不可开工状态;
3、根据优先级对工序A对应的任务进行加工,并更新任务的状态及紧后工序的状态;
4、对机器的空闲时间进行排序,取最早可开工机器k;
5、根据机器k的空闲开始时间以及任务状态检索任务,存储为任务列表R;
6、判断任务列表R是否为空,是则k=k+1,返回步骤五,否则进行下一步;
7、根据任务的最早可加工时间进行排序,选择最早开始的任务进行加工,更新机器状态、任务状态及后续的工序状态;
·确定任务的开工时间及结束时间
·更新机器的释放时间
·更新当前任务的状态、开工时间、完工时间
·更新当前任务后续节点的最早开工时间,若当前任务为产品的最后一个工序则无须更新
8、判断所有任务是否均已完工,是则结束,否则返回步骤四。


可视化
------------
Expand Down
11 changes: 0 additions & 11 deletions docs/source/constraints.rst

This file was deleted.

26 changes: 26 additions & 0 deletions docs/source/heuristics.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
heuristics
============


禁忌搜索
------------


遗传算法
-------------

遗传算法应用在排产中的关键就是如何将排产结果进行编码、以及如何计算fitness。

每一个可行解被称为一个染色体,一个染色体由多个元素构成,这个元素称为基因。

遗传算法应用在排产问题时,以及TSP、VRP等经典问题,模型的解不表示数量,而表示顺序。
对于m个job,n个机器的排产问题。基因序列的长度是 m * n,因为每个job都需要在n台机器上加工。

两个序列表示模型的解,一个是工序的OS,一个是机器的MS。其中,OS基因序列的数值表示第i个job,这个数值第几次出现决定的是该job的第几道工序。MS同理表示的选择的机器。



强化学习
-------------

Q-learning方法的关键是在agent探索过程中保存一个状态收益表。
18 changes: 13 additions & 5 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,31 @@ python-lekin documentation

排产是一个分配任务,将有限的资源分配给需求。因此需求需要有优先级,约束主要有产能约束与物料约束。产能约束,将订单中的成品按工艺路线分解为工序,而每一道工序有对应的生产机器;物料约束,将订单的成品按BOM(bill of materials)展开为原材料需求,每一道工序开始前需要对应原材料齐套。

下标,机器k kk加工为任务i ii后加工任务j jj

其中,:math:`A_\text{c} = (\pi/4) d^2`


subject to:

.. math:: \alpha{}_t(i) = P(O_1, O_2, … O_t, q_t = S_i \lambda{})



Finite Capacity Planning

.. toctree::
:maxdepth: 5
:caption: Contents:

tutorials
models
constraints
rules
heuristics
rl
application
api
CHANGELOG
GitHub <https://github.com/LongxingTan/python-lekin>



Indices and tables
==================

Expand Down
2 changes: 1 addition & 1 deletion docs/source/tutorials.rst → docs/source/rl.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Tutorials
rl
=========
25 changes: 9 additions & 16 deletions docs/source/models.rst → docs/source/rules.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Models
Rules
============


SPT最短加工时间
--------------------

按任务所需工序时间长短,从短到长顺序排列
按任务所需工序时间长短,从短到长顺序排列.
实现中,为保证工艺路径的先后约束关系,构造规则法通过循环的先后关系来保证满足约束。


EDD最早预定交货期规则
Expand Down Expand Up @@ -36,25 +38,16 @@ SPT—EDD规则
正推方法确定每个任务的最早开始时间和最早完成时间,逆推方法确定每个任务的最晚完成时间和最晚开始时间。


倒排
---------------

- 每一个MO最早开始时间初始化:max(ESD, today)。确保开始时间不早于今天


正排
顺排
-------------

顺排和倒排,和其他规则启发式算法一样,一个工序集一个工序集的排。每排一个工序,工序job完成后,更新机器、job状态、后续job状态。


倒排
---------------

禁忌搜索
------------


遗传算法
-------------


强化学习
-------------
- 每一个MO最早开始时间初始化:max(ESD, today)。确保开始时间不早于今天
40 changes: 40 additions & 0 deletions lekin/dashboard/gantt.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
"""
class CRScheduler:
# ... (rest of the class code)
def schedule_job(self, job):
# ... (rest of the method code)
for operation in job.route.operations:
# ... (rest of the method code)
# Store the scheduling result for each operation
self.schedule_result[operation] = (operation.start_time, operation.end_time)
"""

from matplotlib import ticker
import matplotlib.patches as patches
import matplotlib.pyplot as plt


def plot_gantt_chart(schedule_result):
fig, ax = plt.subplots()

# Set y-axis limits
ax.set_ylim(0, 10)
ax.set_xlim(0, max([end_time for (_, end_time) in schedule_result.values()]))

for i, (operation, (start_time, end_time)) in enumerate(schedule_result.items()):
# Draw Gantt chart bar for each operation
y = 5 - i # Position the bar on the y-axis
height = 1 # Bar height
width = end_time - start_time
rect = patches.Rectangle((start_time, y), width, height, linewidth=1, edgecolor="black", facecolor="blue")
ax.add_patch(rect)

# Add text label for the operation name
ax.text(
start_time + width / 2, y + height / 2, f"Operation {operation.id}", ha="center", va="center", color="white"
)

plt.xlabel("Time")
plt.ylabel("Operations")
plt.title("Gantt Chart - Scheduling Result")
plt.show()
Empty file removed lekin/evaluator/__init__.py
Empty file.
1 change: 0 additions & 1 deletion lekin/evaluator/metrics.py

This file was deleted.

6 changes: 3 additions & 3 deletions lekin/lekin_struct/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"""

from lekin.lekin_struct.job import Job
from lekin.lekin_struct.machine import Machine # 机器
from lekin.lekin_struct.job import Job # 成品需求
from lekin.lekin_struct.operation import Operation # 工序
from lekin.lekin_struct.order import Order
from lekin.lekin_struct.resource import Machine # 机器
from lekin.lekin_struct.route import Route
from lekin.lekin_struct.timeslot import TimeSlot
11 changes: 0 additions & 11 deletions lekin/lekin_struct/activity.py

This file was deleted.

83 changes: 80 additions & 3 deletions lekin/lekin_struct/job.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Struct Job/作业
Struct Job/订单作业
- a job could finish one product while finished
- job/mo/operation/activity
Expand All @@ -16,14 +16,91 @@
method
ob1 = Job(1, datetime(2023, 7, 25), 1, 1)
job2 = Job(2, datetime(2023, 7, 26), 2, 1)
operation1 = Operation(1, [1, 2], 2, 2, None)
operation2 = Operation(2, [3], 3, None, 1)
job_collector = JobCollector()
job_collector.add_job(job1)
job_collector.add_job(job2)
job_collector.add_operation(operation1)
job_collector.add_operation(operation2)
# Get operations for Job 1 and Route 1
job1_operations_route1 = job_collector.get_operations_by_job_and_route(1, 1)
print("Job 1 Operations (Route 1):")
for op in job1_operations_route1:
print("Operation ID:", op.operation_id)
"""

from typing import Any, Callable, Dict, List, Optional, Tuple


class JobCollector:
def __init__(self):
self.jobs = [] # List to store Job objects
self.operations = []
self.routes = []
self.resources = []
self.time_slots = []

def add_job(self, job):
self.jobs.append(job)

def add_operation(self, operation):
self.operations.append(operation)

def get_job_by_id(self, job_id):
for job in self.jobs:
if job.job_id == job_id:
return job
return None

def get_operations_by_job_and_route(self, job_id, route_id):
job_operations = []
for operation in self.operations:
if operation.parent_operation_id is None and operation.route_id == route_id:
# If the operation is the first operation in the route
current_operation = operation
while current_operation:
if current_operation.job_id == job_id:
job_operations.append(current_operation)
next_operation_id = current_operation.next_operation_id
current_operation = next(
(op for op in self.operations if op.operation_id == next_operation_id), None
)
return job_operations

def get_schedule(self):
schedule = {}

for resource in self.resources:
scheduled_operations = []
for operation in self.operations:
if operation.resource == resource:
scheduled_operations.append({"operation_id": operation.id, "start_time": operation.start_time})

if scheduled_operations:
schedule[resource.id] = scheduled_operations

return schedule


class Job(object):
def __init__(self, route_id, route_name, route_color, task_id, machine_id, machine_name, duration):
self.route_id = route_id
def __init__(self, job_id, priority, demand_time, assigned_route, assigned_tree):
self.job_id = job_id
self.priority = priority
self.demand_time = demand_time
self.assigned_route = None # Route object assigned to this job
self.assigned_operations = [] # List of Operation objects assigned to this job

def assign_route(self, route):
self.assigned_route = route

def assign_operation(self, operation):
self.assigned_operations.append(operation)

def __eq__(self, other):
return
Expand Down
22 changes: 0 additions & 22 deletions lekin/lekin_struct/machine.py

This file was deleted.

29 changes: 26 additions & 3 deletions lekin/lekin_struct/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,32 @@
"""


class Operation(object):
def __init__(self, name):
self.name = name
class OperationCollector:
def __init__(self):
self.operations = [] # List to store Operation objects

def add_operation(self, operation):
self.operations.append(operation)

def get_operation_by_id(self, operation_id):
for operation in self.operations:
if operation.operation_id == operation_id:
return operation
return None


class Operation:
def __init__(self, operation_id, operation_name, processing_time, demand_time, route_constraint):
self.operation_id = operation_id
self.operation_name = operation_name
self.processing_time = processing_time
self.demand_time = demand_time
self.resource_requirements = []
self.route_constraint = route_constraint
self.earliest_start_time = None
self.latest_start_time = None
self.earliest_end_time = None
self.latest_end_time = None

def __str__(self):
pass
9 changes: 0 additions & 9 deletions lekin/lekin_struct/order.py

This file was deleted.

0 comments on commit 5a443c2

Please sign in to comment.