请教关于利用Gurobi求解短结点业务转发的问题(多节点无法跑出结果)

在之前已经跑出来一个3交换机,4端节点的简单模型(秒出结果)在相似的目标函数和约束条件下我将交换机增加到4个,端节点增加到5个,相同的方法添加目标函数和约束条件。但是运行了很久却跑不出结果了

交换机序号: 1——4
端结点: 5——9
端节点和交换机的挂靠关系如下,所有交换机1-4之间是全连接的可以任意通信,端节点5-9必须通过相应的交换机之间进行转发通信,
例如5想给9发业务1信息,则路径为5—1—4—9

img

每个端节点都要给其他端节点发送1个业务信息,如5要给6,7,8,9都要发业务,所以一共会产生 4*5=20个业务

例如:业务0发送路径为 5—→1—→2—→6 则将其放在一个list_yewu[]的列表里
List_yewu = [0, 5, 1, 2, 6] 列表第一个元素为业务号,后面为发送经过的链路结点信息
[0, 5, 1, 2, 6] : 业务0发送路径为 5—→1—→2—→6
[1, 5, 1, 3, 7] : 业务1发送路径为 5—→1—→3—→7
[2, 5, 1, 3, 7] : 业务1发送路径为 5—→1—→4—→8
[3, 5, 1, 3, 7] : 业务1发送路径为 5—→1—→4—→9
…… ….
[17, 9, 4, 2, 6] : 业务17发送路径为 9—→4—→2—→6
[18, 9, 4, 3, 7] : 业务18发送路径为 9—→4—→3—→7
[19, 9, 4, 8] : 业务19发送路径为 9—→4—→8

其次还需要产生另一个链路集list_lianlu 表示一条链路下的所有业务号,
前两个元素是链路结点,后面的全是业务序号
[5, 1, 0, 1, 2, 3]: 链路5-1上有业务0 1 2 3
[1, 2, 0]: 链路1-2上有业务0
[2, 6, 0, 9, 13, 17]:链路2-6上有业务0 9 13 17
……

现通过编写函数every_items_route 产生想要的所有list_yewu
list_yewu= [[0, 5, 1, 2, 6], [1, 5, 1, 3, 7], [2, 5, 1, 4, 8], …….. , [18, 9, 4, 3, 7], [19, 9, 4, 8]]

通过编写函数oneroute_items 产生想要的所有list_lianlu
list_lianlu = [[5, 1, 0, 1, 2, 3], [1, 2, 0], [2, 6, 0, 9, 13, 17], ,…..., [4, 3, 14, 18], [9, 4, 16, 17, 18, 19]]

目标函数:
每个业务尽可能以最快的发送速度到达端节点
如果在gurobi中将变量设置为Cij表示发送时刻,i表示业务序号,j表示链路上的某个端点,则整体意思就是i业务在j点的发送时刻。[0, 5, 1, 2, 6] ,业务0的目的地是节点6,当
C[0,2]尽可能小的时候才是我们想要的最佳发送时刻,后面[1, 5, 1, 3, 7]和所有业务都如此
故Obj1 = Min( C[0,2] + C[1,3] + C[2,4]……+C[18,3]+C[19,4])

最好Obj1还在业务的所有起始发送时刻最小的前提下满足,[0, 5, 1, 2, 6] 故设置Obj2
Obj2 = Min( C[0,5] + C[1,5] + C[2,5]……+C[18,9]+C[19,9])

约束条件:
list_yewu= [[0, 5, 1, 2, 6], [1, 5, 1, 3, 7], [2, 5, 1, 4, 8], …….. , [18, 9, 4, 3, 7], [19, 9, 4, 8]]
list_lianlu = [[5, 1, 0, 1, 2, 3], [1, 2, 0], [2, 6, 0, 9, 13, 17], ,…..., [4, 3, 14, 18], [9, 4, 16, 17, 18, 19]]
约束条件又分为业务约束和链路约束

链路约束:list_yewu= [[0, 5, 1, 2, 6]….],拿业务0的链路信息举例,要保证业务0在端点5的发送时刻加链路上的传递时间等消耗应该小于等于端点1的发送时刻,而端点1的发送时刻又要小于端点2的发送时刻,
即C[0,5] + t1 <= C[0,1] C[0,1] + t2 <=C[0,2] … 其中t全为一个常数
由于端点6就是目的地,故不需要再考虑C[0,6],同样其他业务的链路约束也如此

业务约束:list_lianlu = [[5, 1, 0, 1, 2, 3]…] 拿链路5—1上的业务举例
需要保证,在链路5—1上业务号0,1,2,3这4个业务之间也有个先后发送顺序
因为不知道它们谁先谁后故需要引入M和Z来约束它们之间的先后顺序



C[0,5]  +  t  <=  C[1,5]  +  M * Z[1] ] 
C[1,5]  +  t  <=  C[0,5]  + (1- Z[1])*M

C[0,5]  +  t  <=  C[2,5]  +  M * Z[2] ] 
C[2,5]  +  t  <=  C[0,5]  + (1- Z[2])*M

C[0,5]  +  t  <=  C[3,5]  +  M * Z[3] ] 
C[3,5]  +  t  <=  C[0,5]  + (1- Z[3])*M

C[1,5]  +  t  <=  C[2,5]  +  M * Z[4] ] 
C[2,5]  +  t  <=  C[1,5]  + (1- Z[4])*M

C[1,5]  +  t  <=  C[3,5]  +  M * Z[5] ] 
C[3,5]  +  t  <=  C[1,5]  + (1- Z[5])*M

C[2,5]  +  t  <=  C[3,5]  +  M * Z[6] ] 
C[3,5]  +  t  <=  C[2,5]  + (1- Z[6])*M
……

后续就是在Gurobi中建立模型


```python
import random
import gurobipy as gp
from gurobipy import *
from gurobipy import GRB
import numpy as np
from every_items_route import creat_itemsroute_list
from oneroute_items import creat_routeitems

# 创建业务号的路径集
list_yewu = creat_itemsroute_list()
# 创建路径下的业务集
list_lianlu = creat_routeitems(list_yewu)

# 现在需要做的工作就是开始对整个业务表进行遍历
print('一条链路下的所有业务号:',list_lianlu)
print('不同业务所走的路径(第一个元素为业务号):',list_yewu)

try:
    m = gp.Model("TTE_test")

    C = m.addVars( 20, range(1, 10), vtype='C', name="C") #第一个下标上限为业务总数,第二个为结点总数

    M = m.addVar(lb=0, ub=gurobipy.GRB.INFINITY, vtype=GRB.SEMIINT, name='M')

    Z = m.addVars(67, vtype=GRB.BINARY, name='Z')
    m.ModelSense = GRB.MINIMIZE

    # ③设置目标函数,让业务在发送的最后一条路径上的发送时间是最低的
    obj1 = LinExpr()
    for i in range(len(list_yewu)):
        for j in range(len(list_yewu[i])):
            # 检索到最后一次发送路径的起始点
            if j == len(list_yewu[i])-2:
                #将目标函数系数与决策变量相乘,并进行连加
                obj1.addTerms(1, C[list_yewu[i][0], list_yewu[i][j] ] ) #1为系数,也可用对应系数矩阵替代
    '''将表示目标函数的线性表达式加入模型'''
    m.setObjectiveN(obj1, index=0, priority=2, abstol=0, reltol=0, name='obj1')

    # 让所有业务的初始发送时间尽可能小
    obj2 = LinExpr(0)
    for i in range(len(list_yewu)):
            obj2.addTerms(1, C[list_yewu[i][0], list_yewu[i][1]])
    m.setObjectiveN(obj2, index=1,priority=1, abstol=0, reltol=0, name='obj2')


    '''创建业务约束条件'''
    k = 0
    for i in range(len(list_lianlu)):
        for j in range(2, len(list_lianlu[i]) - 1):
            for u in range(j + 1, len(list_lianlu[i])):
                k = k + 1
                m.addConstr(C[list_lianlu[i][j], list_lianlu[i][0]] + np.random.uniform(0,1) <= C[list_lianlu[i][u], list_lianlu[i][0]] + Z[k] *     
  M,'')
                m.addConstr(C[list_lianlu[i][u], list_lianlu[i][0]] + np.random.uniform(0,1) <= C[list_lianlu[i][j], list_lianlu[i][0]] + (1 - Z[k]) * M, '')

    '''创建链路约束条件 '''
    for i in range(0, len(list_yewu)):
        for j in range(1, len(list_yewu[i]) - 2):
            m.addConstr(C[i, list_yewu[i][j]] + np.random.uniform(0,1) <= C[i, list_yewu[i][j + 1]])


    m.write('Test_10_point.lp')

    '''启动NoRel启发式算法'''
    # m.Params.NoRelHeurtime = 300
    # m.Params.MIPFocus = 2

    #⑤开始求解
    m.optimize()
    m.discardMultiobjEnvs()

    '''循环遍历你设置的所有变量值'''
    for v in m.getVars():
        print('%s %g' % (v.varName, v.x))

    for i in range(m.NumObj):  # 可以使用NumObj属性查询(或修改)模型中的目标数量,它的值是目标函数的数量。遍历它,得到的是一个个index的值
        m.setParam(GRB.Param.ObjNumber, i)
        print('Obj%d = ' % (i + 1), m.ObjNVal)

except gp.GurobiError as e:
    print('Error code ' + str(e.errno) + ': ' + str(e))
except AttributeError:  # 属性错误
    print('Encountered an attribute error')

def creat_itemsroute_list():
    list_yewu = []
    first_point = 5
    last_point = 9
    fist_swap = 1
    last_sawp = 4
    item_num = 0   #用来表示业务号
    for i in range(first_point, last_point+1):                              # i:端节点
        if i <= 7:                                                          # 与交换机1-11相连接的端结点
            p = i - 4                                                       #  经过的第一个交换机
            for j in range(fist_swap, last_sawp+1):                         # j 表示业务经过的第二个交换机
                if j != p:                                                  # 自己不给自己发业务
                    if j == 4:                                              # 经过交换机12转接的业务
                        for k in range(8, 10):
                            list_yewu.append([])
                            list_yewu[item_num].append(item_num)
                            list_yewu[item_num].append(i)
                            list_yewu[item_num].append(p)
                            list_yewu[item_num].append(j)
                            list_yewu[item_num].append(k)
                            item_num += 1
                    else:      #不经过交换机4的业务
                        y = j + 4
                        list_yewu.append([])
                        list_yewu[item_num].append(item_num)
                        list_yewu[item_num].append(i)
                        list_yewu[item_num].append(p)
                        list_yewu[item_num].append(j)
                        list_yewu[item_num].append(y)
                        item_num += 1
        else:    #与交换机4相连接的端结点
            z = 4
            for k in range(5, 10):
                if k <= 7:
                    list_yewu.append([])
                    list_yewu[item_num].append(item_num)
                    list_yewu[item_num].append(i)
                    list_yewu[item_num].append(z)
                    list_yewu[item_num].append(k - 4)
                    list_yewu[item_num].append(k)
                    item_num += 1
                else:
                    if k == i:
                        continue
                    else:
                        list_yewu.append([])
                        list_yewu[item_num].append(item_num)
                        list_yewu[item_num].append(i)
                        list_yewu[item_num].append(z)
                        list_yewu[item_num].append(k)
                        item_num += 1
    return list_yewu
# print(r'业务号的路径',creat_itemsroute_list())





```python
def creat_routeitems(list_yewu):
    list_lianlu = [[]]
    list_fz = []
    list_fz.append(list_yewu[0][1])
    list_fz.append(list_yewu[0][2])
    list_lianlu[0].append(list_yewu[0][1])
    list_lianlu[0].append(list_yewu[0][2])

    for i in range(0, len(list_yewu)):
        for j in range(1, len(list_yewu[i]) - 1):
            for k in range(0, len(list_fz), 2):
                if list_fz[k] == list_yewu[i][j] and list_fz[k + 1] == list_yewu[i][j + 1]:
                    break
                else:
                    if k < len(list_fz) - 2:
                        continue
                    else:
                        list_fz.append(list_yewu[i][j])
                        list_fz.append(list_yewu[i][j + 1])
                        list_lianlu.append([])
                        list_lianlu[len(list_lianlu) - 1].append(list_yewu[i][j])
                        list_lianlu[len(list_lianlu) - 1].append(list_yewu[i][j + 1])
    for i in range(0, len(list_yewu)):
        for j in range(1, len(list_yewu[i]) - 1):
            for k in range(0, len(list_fz), 2):
                if list_fz[k] == list_yewu[i][j] and list_fz[k + 1] == list_yewu[i][j + 1]:
                    list_lianlu[int(k / 2)].append(list_yewu[i][0])
                    break
    # print(r'list_fz', list_fz) # list_fz存放了一维的链路,两个一跳
    return list_lianlu



# list_yewu =[[0, 5, 1, 2, 6], [1, 5, 1, 3, 7], [2, 5, 1, 4, 8], [3, 5, 1, 4, 9], [4, 6, 2, 1, 5], [5, 6, 2, 3, 7], [6, 6, 2, 4, 8], [7, 6, 2, 4, 9], [8, 7, 3, 1, 5], [9, 7, 3, 2, 6], [10, 7, 3, 4, 8], [11, 7, 3, 4, 9], [12, 8, 4, 1, 5], [13, 8, 4, 2, 6], [14, 8, 4, 3, 7], [15, 8, 4, 9], [16, 9, 4, 1, 5], [17, 9, 4, 2, 6], [18, 9, 4, 3, 7], [19, 9, 4, 8]]
# print(r'一条链路下的所有业务号:',creat_routeitems(list_yewu))

# 目前位置,list_lianlu中前两列存放了链路结点

约束条件和目标函数确实都已经添加进去了,但是结果如下,不知道是不是我在建立Gurobi目标函数和约束条件的时候出了什么问题,希望能得到专家们的指导

img

img

img

img

你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,技术专家团超时未为您做出解答


本次提问扣除的有问必答次数,将会以问答VIP体验卡(1次有问必答机会、商城购买实体图书享受95折优惠)的形式为您补发到账户。


因为有问必答VIP体验卡有效期仅有1天,您在需要使用的时候【私信】联系我,我会为您补发。