面对Flow-shop调度问题如何优化?可用MindOpt来决策

简介: mindopt案例——Flow shop-流线型调度问题

生产调度

生产调度是组织执行生产进度计划的工作。现代工业企业,生产环节、协助关系复杂,情况变化快,如果某一措施没有按期实现,常常会波及整个生产系统的运行。因此,加强生产调度工作,对于及时了解、掌握生产进度,研究分析影响生产的各种因素,根据不同情况采取相应对策,使差距缩小或恢复正常是非常重要的。

流线型调度问题- Flow shop

Flow-shop的调度问题可以描述为:已知条件为有一批k个需要n道工序进行加工的工件,分别在n台不同的机器上进行加工,并且加工的顺序是一致的并且给定的,任一工件j(1<=j<=m)的l工序(1<=l<=n)的生产时间是已知的,要求合理地调度各工件的各生产工序在每台机器上的顺序。

Flow-shop特征:


1. 各工件均需在所有机器(集)上加工;

2. 每个工件的各操作仅能在某一台机器(集)上加工;

3. 所有工件预先给定工艺路线,且工艺路线相同;

4. 工件不可重入。


Flow Shop 是调度领域中的经典模型:


  • 给定一组机器和一批工件,所有工件都按相同顺序依次流过这些机器;
  • 工件在各台机器上的加工时长为给定值,一旦工件进入机器的时长已达相应加工时长,工件立即离开该机器;
  • 在任何时刻,一台机器仅能加工最多一个工件;
  • 优化的目标为最小化makespan,即最后完成所有加工的时间;
  • 决策为确定工件之间的先后顺序。

image.png


该问题可以通过黑盒方法或混合整数规划的方法进行求解,在求解过程中,对某个候选解与理论最优解的距离进行估计,可以帮助我们评估解的质量。为获得下界的估计,我们可以松弛混合整数规划模型中的整数约束,得到一个线性规划,求解该松弛问题,即可得到原问题的一个下界。


Flow Shop 调度的MIP模型及其LP松弛


变量


  • image.png , 工件 image.png 比工件 image.png 先加工时取 1;否则取 0;( image.png )
  • image.png , 工件 image.png 比在机器 image.png 上开始加工的时间;( image.png )
  • image.png ,最大完工时间,即 makespan


目标

  • image.png



约束


  • 工件 image.png 比工件 image.png 先加工,则工件 image.png 必然比工件 image.png 后加工,即 image.png 时, image.png ,反之亦然,因此,我们有: image.png
  • 当工件 image.png 比工件 image.png 先加工,在任何机器上工件 image.png 的开始时间都不早于工件 image.png 的结束时间(即 image.png ),用 Z 表示某一“足够大”的正实数,我们有: image.png
  • 工件在后续机器上的开始时间不得早于当前机器上的结束时间,即: image.png
  • 据最大完工时间的定义,有: image.png
  • 变量的取值范围:对任意 image.png image.png

MIP模型


image.png


LP松弛模型


将上述MIP模型中的整数要求( image.png )化成区间约束: image.png ,即得到相应的LP松弛:


image.png


数据


假设有如下的数据(实际业务数据会更多)。下面我们将用如下数据,会在代码中体现。


# the flow shop scheduling instance ta001 from the Taillard Flow Shop Scheduling Benchmarks

#number of machines
M = 5 

#number of jobs
J = 20   

TA001_Proc_Times = [54,83,15,71,77,36,53,38,27,87,76,91,14,29,12,77,32,87,68,94, \
              79,3,11,99,56,70,99,60,5,56,3,61,73,75,47,14,21,86,5,77, \
              16,89,49,15,89,45,60,23,57,64,7,1,63,41,63,47,26,75,77,40, \
              66,58,31,68,78,91,13,59,49,85,85,9,39,41,56,40,54,77,51,31, \
              58,56,20,85,53,35,53,41,69,13,86,72,8,49,47,87,58,18,68,28]


2.使用MindOpt求解器的API


直接采用求解器的API,需要查阅API文档来理解API的意思,没有建模语言可读性高。请参阅https://solver.damo.alibaba.com/doc/html/API%20reference/API-python/index.html来查看PythonAPI的使用说明。


关于Python的例子,在使用文档的5.建模与优化求解章节有Python的示例。这里是个LP的问题,我们可以参考:https://solver.damo.alibaba.com/doc/html/model/lp/linear%20optimization-python.html


下面我们分两种方式描述在本平台环境中的运行方法:


方法1:cell中直接输入代码运行


请运行下面cell中的代码,点击本窗口上面的播放△运行,或者摁shift+enter键运行:

# LP_3_flowshop.py

'''
Lower Bound Calculation for Flow Shop Scheduling Optimization
with MindOpt LP Solver

This program builds linear program relaxation (LPR) for the flow shop scheduling
instance ta001 from the Taillard Flow Shop Scheduling Benchmarks, and solve
the LPR with the LP Solver of the MindOpt Optimization Suite.
'''

from mindoptpy import *

##############################
#model data
##############################

#number of machines
M = 5 

#number of jobs
J = 20   

#processing time data from the benchmark:
TA001_Proc_Times = [54,83,15,71,77,36,53,38,27,87,76,91,14,29,12,77,32,87,68,94, \
              79,3,11,99,56,70,99,60,5,56,3,61,73,75,47,14,21,86,5,77, \
              16,89,49,15,89,45,60,23,57,64,7,1,63,41,63,47,26,75,77,40, \
              66,58,31,68,78,91,13,59,49,85,85,9,39,41,56,40,54,77,51,31, \
              58,56,20,85,53,35,53,41,69,13,86,72,8,49,47,87,58,18,68,28]

#data utility function
def processTimeOf(m, j):
    '''
    m: int, index of a machine
    j: int, index of a job
    retrieve the processing time of job j on machine m
    '''
    i = m*J+j                    #the index in the data array
    return TA001_Proc_Times[i]   #the processing of job j at machine m

# the large enough number Z (usually referred to as bigM)
Z = 1.0e7

##############################
#setup and solve the model 
##############################


if __name__ == "__main__":
    '''
    call MindOpt to build and solve the LPR
    '''
    try:
        ###################################
        #step1: initialize MindOpt model 
        model = MdoModel()
        
        ###########################################
        #step2: build the linear programming model
        
        #2.1 setup the optimization direction/sense to 'min'
        model.set_int_attr('MinSense', 1)
        
        #2.2 setup variables
        INF = MdoModel.get_infinity()

        #lowerbound, upperbound, coefficient in objective
        cmax = model.add_var(0.0, INF, 1.0, None, 'Cmax', False)
        
        s = {}
        for m in range(M):
            for i in range(J):
                sname = 's_%d_%d'%(m,i)
                s[sname] = model.add_var(0.0, INF, 0.0,None,sname,False)
        
        x = {}
        for i in range(J):
            for j in range(J):
                if i != j:
                    xname = 'x_%d_%d'%(i,j)
                    x[xname] = model.add_var(0.0, 1.0, 0.0, None, xname, False)

        #2.3 setup constraints
        
        # x_ij + x_ji = 1
        for i in range(J):
            for j in range(J):
                if i<j:
                    cname = 'ExclusiveOrder_%d_%d'%(i,j)
                    expr = MdoExprLinear()
                    expr += x['x_%d_%d'%(i,j)]+ x['x_%d_%d'%(j,i)]
                    model.add_cons(1.0, 1.0, expr, cname)

        # s_mj >= s_mi + P_im + (x_ij -1) Z
        # => s_mi + Z x_ij - s_mj <= Z - P_im
        for m in range(M):
            for i in range(J):
                for j in range(J):
                    if i != j:
                        cname = 'Following_%d_%d_%d'%(m,i,j)
                        expr = MdoExprLinear()
                        expr += s['s_%d_%d'%(m,i)] + Z*x['x_%d_%d'%(i,j)] - s['s_%d_%d'%(m,j)]
                        rub = Z - processTimeOf(m,i) # Z - P_im
                        model.add_cons(-INF, rub, expr, cname)

        #s_(m+1),i >= s_mi + P_mi
        # => s_(m+1)i - s_mi >= P_mi
        for m in range(M-1):
            for i in range(J):
                cname='NextStart_%d_%d'%(m,i)
                proctm = processTimeOf(m,i)
                expr = MdoExprLinear()
                expr += s['s_%d_%d'%(m+1,i)] - s['s_%d_%d'%(m,i)]
                model.add_cons(proctm, INF, expr, cname)
        
        
        #cmax >= s_Mi + P_iM
        # => cmax - s_Mi >= P_iM
        for i in range(J):
            m = M-1
            cname = 'Cmax_%d'%(i)
            expr = MdoExprLinear()
            expr += cmax - s['s_%d_%d'%(m,i)]
            proctm = processTimeOf(m,i)
            model.add_cons(proctm, INF, expr, cname)
        

        #optional step: write to LP file for further use
        model.write_prob('model/LP_3_flowshop_ta001.lp')
        
        ###########################################
        #step 3: Serialize the model and settings for further submission
        
        model.set_int_param('NumThreads', 4)
        model.set_real_param('MaxTime', 3600.0)

        # Step 3. Solve the problem and populate the result.
        model.solve_prob()
        model.display_results()
        time.sleep(1) #for print

        status_code, status_msg = model.get_status()

        if status_msg == "OPTIMAL":
            print("----\n")

            model.write_soln('model/LP_3_flowshop_ta001.sol')

            print("The solver terminated with an OPTIMAL status (code {0}).".format(status_code))

            print("目标函数总收益是: {0}".format(model.get_real_attr("PrimalObjVal")))
            
            '''# 打印内容长
            print("原始解是:")
            for var_name,var_val in s.items():
                primal_soln = var_val.get_real_attr("PrimalSoln")
                print("{0:>20} : {1}".format(var_name,primal_soln))
            for var_name,var_val in x.items():
                primal_soln = var_val.get_real_attr("PrimalSoln")
                print("{0:>20} : {1}".format(var_name,primal_soln))
            '''
        else:
            print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))

    except MdoError as e:
        print("Received Mindopt exception.")
        print(" - Code          : {}".format(e.code))
        print(" - Reason        : {}".format(e.message))
    except Exception as e:
        print("Received exception.")
        print(" - Reason        : {}".format(e))
    finally:
        # Step 4. Free the model.
        model.free_mdl()

运行之后,得到如下结果:

Start license validation (current time : 17-JAN-2023 23:54:32).
License validation terminated. Time : 0.003s

Concurrent optimization started.
 - Num. threads       : 4
 - Num. optimizers    : 2
 - Registered optimizers.
   +                  : Simplex method (1 thread, enabled output)
   +                  : Interior point method (3 threads, disabled output)

Model summary.
 - Num. variables     : 481
 - Num. constraints   : 2190
 - Num. nonzeros      : 6280
 - Bound range        : [1.0e+00,1.0e+07]
 - Objective range    : [1.0e+00,1.0e+00]
 - Matrix range       : [1.0e+00,1.0e+07]

Presolver started.
Presolver terminated. Time : 0.013s

Simplex method started.
Model fingerprint: md3ZudWY3dmbmV2dm5WZ

    Iteration       Objective       Dual Inf.     Primal Inf.     Time
            0     1.01171e+12      1.0114e-01      4.9321e+10     0.02s    
          417     3.53000e+02      0.0000e+00      0.0000e+00     0.05s    
Postsolver started.
Simplex method terminated. Time : 0.037s

Concurrent optimization terminated.
Optimizer summary.
 - Optimizer used     : Simplex method
 - Optimizer status   : OPTIMAL
 - Total time         : 0.056s

Solution summary.       Primal solution
 - Objective          : 3.5300000000e+02 
----

The solver terminated with an OPTIMAL status (code 1).
目标函数总收益是: 353.0



方法2:命令行直接运行.py文件


上面是直接在cell中运行所有的脚本,我们也可以建立个新文档,将Python代码存在src/python_src文件夹的LP_3_flowshop.py文件,注意存文件的相对目录调整。然后在Launcher中打开Terminal,执行python xx.py文件来运行。


您也可以下载本.py文件,在自己的电脑上安装MindOpt求解器,然后在自己电脑的环境运行。


Luancher可以点击左上角的+打方块打开,Terminal在最下方,如截图示意。打开的窗口可以拖动调整位置

image.png

然后在Terminal命令行里运行如下指令:


cd src/python_src
python LP_3_flowshop.py


运行得到的结果同方法1:

image.png

方法3:  云上建模平台复制项目运行

此案例已经在案例广场中,可以直接复制:生产调度

image.png

3.求解结果


目标函数最优值是: 353.0。文件src/model/LP_3_flowshop.sol存了本问题的优化解。部分结果示例如下:


NAME             : 
PRIMAL OBJECTIVE : +3.53000000000000E+02
DUAL OBJECTIVE   : +3.53000000000000E+02
PROBLEM STATUS   : OPTIMAL

VARIABLES
Cmax                                     +3.53000000000000E+02
s_0_0                                    +0.00000000000000E+00
s_0_1                                    +0.00000000000000E+00
s_0_2                                    +0.00000000000000E+00
s_0_3                                    +6.00000000000000E+00
s_0_4                                    +0.00000000000000E+00
s_0_5                                    +0.00000000000000E+00
s_0_6                                    +4.50000000000000E+01
s_0_7                                    +0.00000000000000E+00
s_0_8                                    +0.00000000000000E+00
s_0_9                                    +0.00000000000000E+00
s_0_10                                   +0.00000000000000E+00
s_0_11                                   +0.00000000000000E+00
s_0_12                                   +6.60000000000000E+01
s_0_13                                   +0.00000000000000E+00
s_0_14                                   +8.00000000000000E+00
s_0_15                                   +0.00000000000000E+00
s_0_16                                   +0.00000000000000E+00
s_0_17                                   +0.00000000000000E+00
s_0_18                                   +0.00000000000000E+00
s_0_19                                   +0.00000000000000E+00
s_1_0                                    +5.40000000000000E+01

联系我们

钉钉:damodi

邮箱地址:solver.damo@list.alibaba-inc.com

相关文章
|
C语言 Perl 存储
优化求解器之MPS文件的格式简介
在使用MindOpt优化求解器解决实际问题时,其中重要的一环在于如何建立优化模型,以及存储优化模型以便于作为求解器的输入文件。存储优化模型的文件,其关键在于定义一种清晰的格式,用来说明优化模型的数学结构和相关的数据。接下来我们将发布一系列文章,对常见的MPS/LP等格式的模型文件和命名规范进行简要的介绍。
优化求解器之MPS文件的格式简介
|
人工智能 机器人 计算机视觉
微软最新 Sora 分析论文,从中可以看到 Sora 哪些典型的应用场景?
【2月更文挑战第14天】微软最新 Sora 分析论文,从中可以看到 Sora 哪些典型的应用场景?
470 6
微软最新 Sora 分析论文,从中可以看到 Sora 哪些典型的应用场景?
鲁棒优化入门(三)——鲁棒优化工具箱RSOME快速上手与应用实例
本文主要参考RSOME工具箱的用户手册《Users Guide for RSOME》 RSOME的用户手册并不是很长,但一些地方可能不是特别好理解,在这里我主要是通过写博客分享一下我的使用方法,和大家一起学习,也能加深自己的理解。
|
4月前
|
机器学习/深度学习 算法 Java
基于改进粒子群优化算法的柔性车间调度问题(Python代码实现)
基于改进粒子群优化算法的柔性车间调度问题(Python代码实现)
160 4
|
3月前
|
机器学习/深度学习 算法 调度
基于NSGA-III算法求解微电网多目标优化调度研究(Matlab代码实现)
基于NSGA-III算法求解微电网多目标优化调度研究(Matlab代码实现)
171 3
|
算法 调度
基于or-tools解决物流调度问题(一)
基于or-tools解决物流调度问题(一)
465 3
|
关系型数据库 MySQL 数据库
Navicat备份数据库
涵盖`Navicat`数据库备份、数据安全及备份策略等主题。文库采用精美主题,提升阅读体验。
323 1
Navicat备份数据库
|
网络协议 安全 Linux
在Linux中,当一台服务器无法ping通其他主机时,可能有哪些原因?
在Linux中,当一台服务器无法ping通其他主机时,可能有哪些原因?
|
jenkins 持续交付 网络安全
Jenkins——使用Docker部署Jenkins详解
Jenkins——使用Docker部署Jenkins详解
747 0
|
达摩院 供应链 调度
【FlowShop流水线作业排班问题【数学规划的应用(含代码)】阿里达摩院MindOpt】
本文探讨了使用阿里巴巴达摩院的MindOpt工具解决FlowShop流水线作业排班的数学规划问题。FlowShop涉及到多台机器、多个工序和多个作业,目标是通过优化排班最小化总生产耗时。MindOpt通过数学规划方法,如线性或混合整数线性规划,将问题建模并转化为代码,利用云建模平台MindOpt Studio和MindOpt APL建模语言进行求解。案例中详细介绍了参数定义、变量解析、约束设置和目标函数,展示了如何通过MindOpt进行建模和求解,以达到最优化的生产调度。此外,文章还提供了代码示例和结果解析,帮助读者理解如何实际应用MindOpt解决这类问题。