【问题标题】:Mixed Integer Linear Optimization with Pyomo - Travelling salesman problemPyomo 混合整数线性优化 - 旅行商问题
【发布时间】:2021-09-11 02:47:04
【问题描述】:

我正在尝试使用 Pyomo 框架解决旅行推销员问题。但是,我被困住了,因为求解器告诉我我已将其表述为不可行。

    import numpy as np
    import pyomo.environ as pyo
    from pyomo.environ import *
    from pyomo.opt import SolverFactory

    journey_distances = np.array([[0, 28, 34, 45, 36],
                                  [28, 0, 45, 52, 64],
                                  [34, 45, 0, 11, 34],
                                  [45, 52, 11, 0, 34],
                                  [36, 64, 34, 34, 0]])


# create variables - integers

    num_locations = M.shape[0]
    model = pyo.ConcreteModel()
    model.journeys = pyo.Var(range(num_locations), range(num_locations), domain=pyo.Binary, bounds = (0,None))
    journeys = model.journeys
        

# add A to B constraints

    model.AtoB = pyo.ConstraintList()
    model.BtoA = pyo.ConstraintList()
    AtoB = model.AtoB
    BtoA = model.BtoA
    AtoB_sum = [sum([ journeys[i,j] for j in range(num_locations) if i!=j]) for i in range(num_locations)]
    BtoA_sum = [sum([ journeys[i,j] for i in range(num_locations) if j!=i]) for j in range(num_locations)]
    for journey_sum in range(num_locations):
        AtoB.add(AtoB_sum[journey_sum] == 1)
        if journey_sum <num_locations -1:
            BtoA.add(BtoA_sum[journey_sum] == 1)

# add auxilliary variables to ensure that each successive journey ends and starts on the same town. E.g. A to B, then B to C. 
# u_j - u_i >= -(n+1) + num_locations*journeys_{ij} for i,j = 1...n, i!=j 

    model.successive_aux = pyo.Var(range(0,num_locations), domain = pyo.Integers, bounds = (0,num_locations-1))
    model.successive_constr = pyo.ConstraintList()
    successive_aux = model.successive_aux
    successive_constr = model.successive_constr

    successive_constr.add(successive_aux[0] == 1)
    for i in range(num_locations):
        for j in range(num_locations):
            if i!=j:
                successive_constr.add(successive_aux[j] - successive_aux[i] >= -(num_locations - 1) + num_locations*journeys[i,j])

    obj_sum = sum([ sum([journey_distances [i,j]*journeys[i,j] for j in range(num_locations) if i!=j]) for i in range(num_locations)])
    model.obj = pyo.Objective(expr = obj_sum, sense = minimize)


    opt = SolverFactory('cplex')
    opt.solve(model)

    journey_res = np.array([model.journeys[journey].value for journey in journeys])
    print(journey_res)

# results output is:
print(results)

Problem: 
- Lower bound: -inf
  Upper bound: inf
  Number of objectives: 1
  Number of constraints: 31
  Number of variables: 26
  Number of nonzeros: 98
  Sense: unknown
Solver: 
- Status: ok
  User time: 0.02
  Termination condition: infeasible
  Termination message: MIP - Integer infeasible.
  Error rc: 0
  Time: 0.10198116302490234

# model.pprint() 

7 Set Declarations
    AtoB_index : Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    5 : {1, 2, 3, 4, 5}
    BtoA_index : Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    4 : {1, 2, 3, 4}
    journeys_index : Size=1, Index=None, Ordered=False
        Key  : Dimen : Domain                            : Size : Members
        None :     2 : journeys_index_0*journeys_index_1 :   25 : {(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)}
    journeys_index_0 : Size=1, Index=None, Ordered=False
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    5 : {0, 1, 2, 3, 4}
    journeys_index_1 : Size=1, Index=None, Ordered=False
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    5 : {0, 1, 2, 3, 4}
    successive_aux_index : Size=1, Index=None, Ordered=False
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    5 : {0, 1, 2, 3, 4}
    successive_constr_index : Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :   21 : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}

2 Var Declarations
    journeys : Size=25, Index=journeys_index
        Key    : Lower : Value : Upper : Fixed : Stale : Domain
        (0, 0) :     0 :  None :     1 : False :  True : Binary
        (0, 1) :     0 :  None :     1 : False :  True : Binary
        (0, 2) :     0 :  None :     1 : False :  True : Binary
        (0, 3) :     0 :  None :     1 : False :  True : Binary
        (0, 4) :     0 :  None :     1 : False :  True : Binary
        (1, 0) :     0 :  None :     1 : False :  True : Binary
        (1, 1) :     0 :  None :     1 : False :  True : Binary
        (1, 2) :     0 :  None :     1 : False :  True : Binary
        (1, 3) :     0 :  None :     1 : False :  True : Binary
        (1, 4) :     0 :  None :     1 : False :  True : Binary
        (2, 0) :     0 :  None :     1 : False :  True : Binary
        (2, 1) :     0 :  None :     1 : False :  True : Binary
        (2, 2) :     0 :  None :     1 : False :  True : Binary
        (2, 3) :     0 :  None :     1 : False :  True : Binary
        (2, 4) :     0 :  None :     1 : False :  True : Binary
        (3, 0) :     0 :  None :     1 : False :  True : Binary
        (3, 1) :     0 :  None :     1 : False :  True : Binary
        (3, 2) :     0 :  None :     1 : False :  True : Binary
        (3, 3) :     0 :  None :     1 : False :  True : Binary
        (3, 4) :     0 :  None :     1 : False :  True : Binary
        (4, 0) :     0 :  None :     1 : False :  True : Binary
        (4, 1) :     0 :  None :     1 : False :  True : Binary
        (4, 2) :     0 :  None :     1 : False :  True : Binary
        (4, 3) :     0 :  None :     1 : False :  True : Binary
        (4, 4) :     0 :  None :     1 : False :  True : Binary
    successive_aux : Size=5, Index=successive_aux_index
        Key : Lower : Value : Upper : Fixed : Stale : Domain
          0 :     0 :  None :     4 : False :  True : Integers
          1 :     0 :  None :     4 : False :  True : Integers
          2 :     0 :  None :     4 : False :  True : Integers
          3 :     0 :  None :     4 : False :  True : Integers
          4 :     0 :  None :     4 : False :  True : Integers

1 Objective Declarations
    obj : Size=1, Index=None, Active=True
        Key  : Active : Sense    : Expression
        None :   True : minimize : 28*journeys[0,1] + 34*journeys[0,2] + 45*journeys[0,3] + 36*journeys[0,4] + 28*journeys[1,0] + 45*journeys[1,2] + 52*journeys[1,3] + 64*journeys[1,4] + 34*journeys[2,0] + 45*journeys[2,1] + 11*journeys[2,3] + 34*journeys[2,4] + 45*journeys[3,0] + 52*journeys[3,1] + 11*journeys[3,2] + 34*journeys[3,4] + 36*journeys[4,0] + 64*journeys[4,1] + 34*journeys[4,2] + 34*journeys[4,3]

3 Constraint Declarations
    AtoB : Size=5, Index=AtoB_index, Active=True
        Key : Lower : Body                                                          : Upper : Active
          1 :   1.0 : journeys[0,1] + journeys[0,2] + journeys[0,3] + journeys[0,4] :   1.0 :   True
          2 :   1.0 : journeys[1,0] + journeys[1,2] + journeys[1,3] + journeys[1,4] :   1.0 :   True
          3 :   1.0 : journeys[2,0] + journeys[2,1] + journeys[2,3] + journeys[2,4] :   1.0 :   True
          4 :   1.0 : journeys[3,0] + journeys[3,1] + journeys[3,2] + journeys[3,4] :   1.0 :   True
          5 :   1.0 : journeys[4,0] + journeys[4,1] + journeys[4,2] + journeys[4,3] :   1.0 :   True
    BtoA : Size=4, Index=BtoA_index, Active=True
        Key : Lower : Body                                                          : Upper : Active
          1 :   1.0 : journeys[1,0] + journeys[2,0] + journeys[3,0] + journeys[4,0] :   1.0 :   True
          2 :   1.0 : journeys[0,1] + journeys[2,1] + journeys[3,1] + journeys[4,1] :   1.0 :   True
          3 :   1.0 : journeys[0,2] + journeys[1,2] + journeys[3,2] + journeys[4,2] :   1.0 :   True
          4 :   1.0 : journeys[0,3] + journeys[1,3] + journeys[2,3] + journeys[4,3] :   1.0 :   True
    successive_constr : Size=21, Index=successive_constr_index, Active=True
        Key : Lower : Body                                                           : Upper : Active
          1 :   1.0 :                                              successive_aux[0] :   1.0 :   True
          2 :  -Inf : -4 + 5*journeys[0,1] - (successive_aux[1] - successive_aux[0]) :   0.0 :   True
          3 :  -Inf : -4 + 5*journeys[0,2] - (successive_aux[2] - successive_aux[0]) :   0.0 :   True
          4 :  -Inf : -4 + 5*journeys[0,3] - (successive_aux[3] - successive_aux[0]) :   0.0 :   True
          5 :  -Inf : -4 + 5*journeys[0,4] - (successive_aux[4] - successive_aux[0]) :   0.0 :   True
          6 :  -Inf : -4 + 5*journeys[1,0] - (successive_aux[0] - successive_aux[1]) :   0.0 :   True
          7 :  -Inf : -4 + 5*journeys[1,2] - (successive_aux[2] - successive_aux[1]) :   0.0 :   True
          8 :  -Inf : -4 + 5*journeys[1,3] - (successive_aux[3] - successive_aux[1]) :   0.0 :   True
          9 :  -Inf : -4 + 5*journeys[1,4] - (successive_aux[4] - successive_aux[1]) :   0.0 :   True
         10 :  -Inf : -4 + 5*journeys[2,0] - (successive_aux[0] - successive_aux[2]) :   0.0 :   True
         11 :  -Inf : -4 + 5*journeys[2,1] - (successive_aux[1] - successive_aux[2]) :   0.0 :   True
         12 :  -Inf : -4 + 5*journeys[2,3] - (successive_aux[3] - successive_aux[2]) :   0.0 :   True
         13 :  -Inf : -4 + 5*journeys[2,4] - (successive_aux[4] - successive_aux[2]) :   0.0 :   True
         14 :  -Inf : -4 + 5*journeys[3,0] - (successive_aux[0] - successive_aux[3]) :   0.0 :   True
         15 :  -Inf : -4 + 5*journeys[3,1] - (successive_aux[1] - successive_aux[3]) :   0.0 :   True
         16 :  -Inf : -4 + 5*journeys[3,2] - (successive_aux[2] - successive_aux[3]) :   0.0 :   True
         17 :  -Inf : -4 + 5*journeys[3,4] - (successive_aux[4] - successive_aux[3]) :   0.0 :   True
         18 :  -Inf : -4 + 5*journeys[4,0] - (successive_aux[0] - successive_aux[4]) :   0.0 :   True
         19 :  -Inf : -4 + 5*journeys[4,1] - (successive_aux[1] - successive_aux[4]) :   0.0 :   True
         20 :  -Inf : -4 + 5*journeys[4,2] - (successive_aux[2] - successive_aux[4]) :   0.0 :   True
         21 :  -Inf : -4 + 5*journeys[4,3] - (successive_aux[3] - successive_aux[4]) :   0.0 :   True

13 Declarations: journeys_index_0 journeys_index_1 journeys_index journeys AtoB_index AtoB BtoA_index BtoA successive_aux_index successive_aux successive_constr_index successive_constr obj

如果有人能看出问题所在并告诉我,那将是一个很大的帮助。

【问题讨论】:

  • 将其重新拼合并执行后,求解器报告这是不可行的。一定要包括并检查这个:results = opt.solve(model) print(results) 此外,您要导入两次,只需重命名一次。您正在重命名所有内容,这非常令人困惑。只需留下model. 前缀,它将大大缩短您的代码
  • 另外,当你解决这个问题时,如果你把它扼杀到 3 个点,用model.pprint() 打印你的模型并手动检查你的约束,这会容易得多,这有点难以破译.

标签: optimization pyomo traveling-salesman


【解决方案1】:

我对编码 TSP 问题并不太熟悉,而且我不确定您的代码中的所有细节,但这(下)是个问题。看来您正在将successive_aux(简称为sa)编码为整数序列。在这个sn-p中(我砍到3分),如果你考虑0-1-2-0的合法路线,sa_1>sa_0sa_2>@ 987654326@,那么要求sa_0 > sa_2是不可行的。此外,您对sa 的限制似乎也不可行。在此示例中,sa_0 为 1,sa 的上限为 2。这些是公式中的 2 个“不可行”。

  Key : Lower : Body                                                           : Upper : Active
          1 :   1.0 :                                              successive_aux[0] :   1.0 :   True
          2 :  -Inf : -2 + 3*journeys[0,1] - (successive_aux[1] - successive_aux[0]) :   0.0 :   True
          3 :  -Inf : -2 + 3*journeys[0,2] - (successive_aux[2] - successive_aux[0]) :   0.0 :   True
          4 :  -Inf : -2 + 3*journeys[1,0] - (successive_aux[0] - successive_aux[1]) :   0.0 :   True
          5 :  -Inf : -2 + 3*journeys[1,2] - (successive_aux[2] - successive_aux[1]) :   0.0 :   True
          6 :  -Inf : -2 + 3*journeys[2,0] - (successive_aux[0] - successive_aux[2]) :   0.0 :   True
          7 :  -Inf : -2 + 3*journeys[2,1] - (successive_aux[1] - successive_aux[2]) :   0.0 :   True

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多