美文网首页运筹优化
CPLEX杂记(三) 热启动

CPLEX杂记(三) 热启动

作者: ChaoesLuol | 来源:发表于2021-08-21 00:01 被阅读0次

    对于一个MIP问题来说,找初始可行解是一个比较费时的过程,如果我们能够在求解开始时就为问题提供一个较好的初始解(不一定是可行的),那么可以大大减少求解器找初始可行解的计算量,加快求解速度。从我们提供的初始解开始进行问题求解,这就叫做热启动。

    需要注意的是,在MIP的精确求解过程中,热启动并不保证能够缩小求解器的搜索范围,因此如果我们提供的初始解并不可行甚至离可行域相去甚远,那么并不会有好的加速效果。

    下面我们用一个例子来看如何为CPLEX求解器添加热启动,并且简单对比一下热启动和冷启动时的求解速度。

    例子与初始解

    还是以背包问题为例,先进行初始问题的构建和求解:

    # 导入包
    from docplex.mp.model import Model
    import pandas as pd
    import numpy as np
    
    # 创建数据
    np.random.seed(0)
    n_knapsack = 5
    n_item = 20
    def create_data() -> dict:
        data = dict()
        data["KnapsackRange"] = [i for i in range(n_knapsack)]
        data["ItemRange"] = [j for j in range(n_item)]
        data["ItemWeight"] = np.random.randint(n_knapsack, n_item, len(data["ItemRange"]))
        data["KnapsackCapacity"] = np.random.randint(20, 50, len(data["KnapsackRange"]))
        data["Lambda1"] = 1.0
        data["Lambda2"] = 0.0
        return data
    data = create_data()
    
    # 定义约束和目标函数
    class MaxWeightObj(object):
        def __init__(self):
            pass
        def add(self, model, data):
            total_weight_item = model.sum(data["Var"][(i,j)] * data["ItemWeight"][j] for i in data["KnapsackRange"] for j in data["ItemRange"])
            load_balance_item = model.sum(model.abs(
                          model.sum(data["Var"][(i,j)] * data["ItemWeight"][j] for j in data["ItemRange"]) - 30) 
                                                      for i in data["KnapsackRange"])
            model.maximize(data["Lambda1"] * total_weight_item + data["Lambda2"] * load_balance_item)
    
    class CapacityConstraint(object):
        def __init__(self):
            pass
        def add(self, model, data):
            model.add_constraints((model.sum(data["Var"][(i, j)] * data["ItemWeight"][j] 
                                         for j in data["ItemRange"])<=data["KnapsackCapacity"][i] 
                               for i in data["KnapsackRange"]), names = "CapacityConstraint")
    
    class CountConstraint(object):
        def __init__(self):
            pass
        def add(self, model, data):
            model.add_constraints((model.sum(data["Var"][(i, j)] for j in data["ItemRange"]) >= 1 
                                 for i in data["KnapsackRange"]), names = "CountConstraint")
            
    class UniquenessConstraint(object):
        def __init__(self):
            pass
        def add(self, model, data):
            model.add_constraints((model.sum(data["Var"][(i, j)] for i in data["KnapsackRange"]) <= 1 
                                 for j in data["ItemRange"]), names = "UniquenessConstraint")
            
    # 建立模型
    mdl = Model("Test model", cts_by_name=True)
    ### Change the floats to check the outcomings
    data["Lambda1"] = 1.0 # Relative weight of total assigned parcels
    data["Lambda2"] = 1.0 # Relative weight of load balance
    data["Var"] = mdl.binary_var_dict([(i, j) for i in data["KnapsackRange"] for j in data["ItemRange"]], name='x')
    
    constraints = [MaxWeightObj(), CapacityConstraint(), CountConstraint(), UniquenessConstraint()]
    for cons in constraints:
        cons.add(mdl, data)
    # Output model info
    mdl.print_information()
    # Solve model
    sol_run1 = mdl.solve(log_output = True)
    

    求解过程如下:

    Model: Test model
     - number of variables: 120
       - binary=100, integer=0, continuous=20
     - number of constraints: 45
       - linear=45
     - parameters: defaults
     - objective: maximize
     - problem type is: MILP
    Version identifier: 12.10.0.0 | 2019-11-26 | 843d4de
    CPXPARAM_Read_DataCheck                          1
    Tried aggregator 1 time.
    MIP Presolve eliminated 10 rows and 10 columns.
    Reduced MIP has 35 rows, 110 columns, and 410 nonzeros.
    Reduced MIP has 100 binaries, 0 generals, 5 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.23 ticks)
    Probing time = 0.00 sec. (0.07 ticks)
    Tried aggregator 1 time.
    Detecting symmetries...
    Reduced MIP has 35 rows, 110 columns, and 410 nonzeros.
    Reduced MIP has 100 binaries, 0 generals, 5 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.29 ticks)
    Probing time = 0.00 sec. (0.07 ticks)
    Clique table members: 27.
    MIP emphasis: balance optimality and feasibility.
    MIP search method: dynamic search.
    Parallel mode: deterministic, using up to 16 threads.
    Root relaxation solution time = 0.00 sec. (0.17 ticks)
    
            Nodes                                         Cuts/
       Node  Left     Objective  IInf  Best Integer    Best Bound    ItCnt     Gap
    
          0     0     unbounded                                        113         
          0     2     unbounded                                        118         
    Elapsed time = 0.02 sec. (1.15 ticks, tree = 0.02 MB, solutions = 0)
    *    24+    9                          164.0000                           0.00%
    *    34+   13                          180.0000                           0.00%
    *    45    25      integral     0      184.0000                    193    0.00%
    *    46+   13                          186.0000                           0.00%
    *    76    15      integral     0      200.0000                    272    0.00%
    *    99    15      integral     0      204.0000                    353    0.00%
    *   148+   18                          216.0000                           0.00%
    *   162    23      integral     0      218.0000      226.0000      590    3.67%
    *   292    28      integral     0      222.0000      226.0000      720    1.80%
    *   329    22      integral     0      226.0000      226.0000      793    0.00%
    
    Cover cuts applied:  33
    
    Root node processing (before b&c):
      Real time             =    0.02 sec. (1.13 ticks)
    Parallel b&c, 16 threads:
      Real time             =    0.05 sec. (4.54 ticks)
      Sync time (average)   =    0.03 sec.
      Wait time (average)   =    0.00 sec.
                              ------------
    Total (root+branch&cut) =    0.07 sec. (5.67 ticks)
    CPU times: user 481 ms, sys: 76.6 ms, total: 557 ms
    Wall time: 156 ms
    

    为了进行对比,我们将问题稍作变换,修改一下目标函数:

    # 修改目标函数中两项的相对权重,并且修改模型中的目标函数total_weight_item = mdl.sum(data["Var"][(i,j)] * data["ItemWeight"][j] for i in data["KnapsackRange"] for j in data["ItemRange"])
    load_balance_item = mdl.sum(mdl.abs(
                          mdl.sum(data["Var"][(i,j)] * data["ItemWeight"][j] for j in data["ItemRange"]) - 30) 
                                                      for i in data["KnapsackRange"])
    data["Lambda1"] = 2.0
    data["Lambda2"] = 3.0
    mdl.set_objective("max", data["Lambda1"] * total_weight_item + data["Lambda2"] * load_balance_item)
    

    添加初始解,进行热启动

    将原问题的解作为初始解,传入修改之后的问题中,进行求解:

    %%time
    # 添加热启动之后,进行求解
    mdl2 = mdl.clone()
    mdl2.add_mip_start(sol_run1)
    mdl2.solve(log_output = True, clean_before_solve=True)
    

    求解过程如下:

    Version identifier: 12.10.0.0 | 2019-11-26 | 843d4de
    CPXPARAM_Read_DataCheck                          1
    1 of 1 MIP starts provided solutions.
    MIP start 'm1' defined initial solution with objective 512.0000.
    Tried aggregator 1 time.
    MIP Presolve eliminated 20 rows and 20 columns.
    Reduced MIP has 40 rows, 120 columns, and 520 nonzeros.
    Reduced MIP has 100 binaries, 0 generals, 10 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.28 ticks)
    Probing time = 0.00 sec. (0.08 ticks)
    Tried aggregator 1 time.
    Detecting symmetries...
    Reduced MIP has 40 rows, 120 columns, and 520 nonzeros.
    Reduced MIP has 100 binaries, 0 generals, 10 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.35 ticks)
    Probing time = 0.00 sec. (0.08 ticks)
    Clique table members: 27.
    MIP emphasis: balance optimality and feasibility.
    MIP search method: dynamic search.
    Parallel mode: deterministic, using up to 16 threads.
    Root relaxation solution time = 0.00 sec. (0.21 ticks)
    
            Nodes                                         Cuts/
       Node  Left     Objective  IInf  Best Integer    Best Bound    ItCnt     Gap
    
    *     0+    0                          512.0000                           0.00%
          0     0     unbounded            512.0000                    123         
          0     2     unbounded            512.0000                    147         
    Elapsed time = 0.02 sec. (1.57 ticks, tree = 0.02 MB, solutions = 1)
    *   520+   37                          513.0000                           0.00%
    *   572+   18                          514.0000                           0.00%
    *   633    20      integral     0      515.0000                   7775    0.00%
    *   886+   16                          519.0000                           0.00%
    
    Cover cuts applied:  11
    
    Root node processing (before b&c):
      Real time             =    0.02 sec. (1.44 ticks)
    Parallel b&c, 16 threads:
      Real time             =    0.08 sec. (16.46 ticks)
      Sync time (average)   =    0.04 sec.
      Wait time (average)   =    0.00 sec.
                              ------------
    Total (root+branch&cut) =    0.10 sec. (17.90 ticks)
    CPU times: user 639 ms, sys: 42.6 ms, total: 682 ms
    Wall time: 143 ms
    

    可以看到,在639ms之后,得到了新问题的解。

    冷启动进行求解

    我们复制一下问题,清除保存的求解过程(否则CPLEX会自动从保存的求解过程继续向下寻找最优解),然后在冷启动的情况下求解:

    %%time
    # 冷启动进行求解
    mdl3 = mdl.clone()
    mdl3.solve(log_output = True, clean_before_solve=True)
    

    求解过程如下:

    Version identifier: 12.10.0.0 | 2019-11-26 | 843d4de
    CPXPARAM_Read_DataCheck                          1
    Tried aggregator 1 time.
    MIP Presolve eliminated 20 rows and 20 columns.
    Reduced MIP has 40 rows, 120 columns, and 520 nonzeros.
    Reduced MIP has 100 binaries, 0 generals, 10 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.28 ticks)
    Probing time = 0.00 sec. (0.08 ticks)
    Tried aggregator 1 time.
    Detecting symmetries...
    Reduced MIP has 40 rows, 120 columns, and 520 nonzeros.
    Reduced MIP has 100 binaries, 0 generals, 10 SOSs, and 0 indicators.
    Presolve time = 0.00 sec. (0.35 ticks)
    Probing time = 0.00 sec. (0.08 ticks)
    Clique table members: 27.
    MIP emphasis: balance optimality and feasibility.
    MIP search method: dynamic search.
    Parallel mode: deterministic, using up to 16 threads.
    Root relaxation solution time = 0.00 sec. (0.21 ticks)
    
            Nodes                                         Cuts/
       Node  Left     Objective  IInf  Best Integer    Best Bound    ItCnt     Gap
    
          0     0     unbounded                                        123         
          0     2     unbounded                                        147         
    Elapsed time = 0.04 sec. (1.50 ticks, tree = 0.02 MB, solutions = 0)
    *    98    29      integral     0      416.0000                    578    0.00%
    *   281+   44                          442.0000                           0.00%
    *   372    70      integral     0      464.0000                   3591    0.00%
    *   604    60      integral     0      467.0000                   5497    0.00%
    *   609+   52                          469.0000                           0.00%
    *   640    34      integral     0      472.0000                   7543    0.00%
    *   651    33      integral     0      476.0000                   7548    0.00%
    *   657    32      integral     0      477.0000                   7572    0.00%
    *   675    34      integral     0      479.0000                   7767    0.00%
    *   881    41      integral     0      507.0000                   8011    0.00%
    *  1048+   27                          509.0000      519.0000             1.96%
    *  1089+   24                          513.0000      519.0000             1.17%
    *  1106    16      integral     0      518.0000      519.0000    10449    0.19%
    *  1226    16      integral     0      519.0000      519.0000    10476    0.00%
    
    Cover cuts applied:  32
    Mixed integer rounding cuts applied:  1
    
    Root node processing (before b&c):
      Real time             =    0.02 sec. (1.42 ticks)
    Parallel b&c, 16 threads:
      Real time             =    0.15 sec. (20.18 ticks)
      Sync time (average)   =    0.08 sec.
      Wait time (average)   =    0.00 sec.
                              ------------
    Total (root+branch&cut) =    0.17 sec. (21.59 ticks)
    CPU times: user 1.21 s, sys: 66.4 ms, total: 1.27 s
    Wall time: 232 ms
    

    可以看到,在没有热启动的情况下,1.21s之后我们得到了解。这比使用热启动的求解要慢上不少。

    相关文章

      网友评论

        本文标题:CPLEX杂记(三) 热启动

        本文链接:https://www.haomeiwen.com/subject/mjtxiltx.html