在之前已经跑出来一个3交换机,4端节点的简单模型(秒出结果)在相似的目标函数和约束条件下我将交换机增加到4个,端节点增加到5个,相同的方法添加目标函数和约束条件。但是运行了很久却跑不出结果了
交换机序号: 1——4
端结点: 5——9
端节点和交换机的挂靠关系如下,所有交换机1-4之间是全连接的可以任意通信,端节点5-9必须通过相应的交换机之间进行转发通信,
例如5想给9发业务1信息,则路径为5—1—4—9
每个端节点都要给其他端节点发送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目标函数和约束条件的时候出了什么问题,希望能得到专家们的指导
你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,技术专家团超时未为您做出解答
本次提问扣除的有问必答次数,将会以问答VIP体验卡(1次有问必答机会、商城购买实体图书享受95折优惠)的形式为您补发到账户。
因为有问必答VIP体验卡有效期仅有1天,您在需要使用的时候【私信】联系我,我会为您补发。