整数规划建模
import random as rd
from pyscipopt import Model, quicksum
from tool.Distance import calculate_distance
from VRP.CVRP.tool.Plot import *
from VRP.CVRP.tool.Print import *
from VRP.CVRP.tool.Data_generate import *
#一维装箱整数规划
def IP_1d(points, capacity, time_limit):
n = len(points)
model = Model("IP_1d")
#i为车子下标,j为点下标
X = [[model.addVar(vtype="B", name="x[%s,%s]" % (i, j)) for j in range(n)] for i in range(n)]
Y = [model.addVar(vtype="B", name="y[%s]" % i) for i in range(n)]
#以总包裹体积最小(即填充率最大)为目标
model.setObjective(quicksum(Y[i] for i in range(n)), "minimize")
#每个车子内货量不超
for i in range(n):
model.addCons(quicksum(points[j].demand*X[i][j] for j in range(n)) - capacity*Y[i] <= 0)
#每个商品都能被装下
for j in range(n):
model.addCons(quicksum(X[i][j] for i in range(n)) == 1)
#设置求解时间
model.setRealParam("limits/time", time_limit)
# model.hideOutput()
model.optimize()
print("\ngap:",model.getGap())
X1 = [[round(model.getVal(X[i][j])) for j in range(n)] for i in range(n)]
Y1 = [round(model.getVal(Y[i])) for i in range(n)]
return sum(Y1)
#附:列出L的所有真子集
def subset(L):
LL = []
n = len(L)
for i in range(1, pow(2, n)-1):
L1 = []
temp = i
for j in range(n):
if temp%2 == 1:
L1.append(L[j])
temp = temp//2
LL.append(L1)
return LL
def CVRP_IP(points, K, capacity, time_limit):
n = len(points)
Dis = [[calculate_distance(points[i].x, points[i].y, points[j].x, points[j].y, "EUC") for j in range(n)] for i in
range(n)]
model = Model("CVRP_IP")
X = [[model.addVar(vtype="B", name="X[%s,%s]" % (i, j)) for j in range(n)] for i in range(n)]
Y = [[model.addVar(vtype="B", name="Y[%s,%s]" % (i, k)) for k in range(K)] for i in range(n)]
f = [[[model.addVar(vtype="B", name="f[%s,%s,%s]" % (i, j, k)) for k in range(K)] for j in range(n)] for i in range(n)]
model.setObjective(quicksum(Dis[i][j] * X[i][j] for i in range(n) for j in range(n)), "minimize")
#几辆车的约束
model.addCons(quicksum(X[0][j] for j in range(1, n)) == K)
model.addCons(quicksum(X[j][0] for j in range(1, n)) == K)
#其余一度约束
for i in range(1, n):
model.addCons(quicksum(X[i][j] for j in range(n) if i != j) == 1)
model.addCons(quicksum(X[j][i] for j in range(n) if i != j) == 1)
#无子环约束
SS = subset([i for i in range(n)])
for S in SS:
model.addCons(quicksum(X[i][j] for i in S for j in range(n) if j not in S) >= 1)
#车辆容积限制
for k in range(K):
model.addCons(quicksum(points[i].demand*Y[i][k] for i in range(n)) <= capacity)
#点必须被分配出去
for i in range(1, n):
model.addCons(quicksum(Y[i][k] for k in range(K)) == 1)
#起点在每辆车上
for k in range(K):
model.addCons(Y[0][k] == 1)
#点放在一起的约束
for i in range(n):
for j in range(n):
model.addCons(X[i][j] <= quicksum(f[i][j][k] for k in range(K)))
for k in range(K):
model.addCons(Y[i][k] + Y[j][k] >= 2*f[i][j][k])
# 设置求解时间
model.setRealParam("limits/time", time_limit)
model.optimize()
print("\ngap:", model.getGap())
X1 = [[round(model.getVal(X[i][j])) for j in range(n)] for i in range(n)]
return X1
def IP(points, capacity, time_limit):
#确定车数
K = IP_1d(points, capacity, time_limit)
print("\nK:", K)
#分配点数
A = CVRP_IP(points, K, capacity, time_limit)
LL_print("\nA: ", A)
return A
def price(A, Dis):
n = len(A)
return sum([Dis[i][j] * A[i][j] for i in range(n) for j in range(n)])
if __name__ == "__main__":
#这里先定义一下标准的CVRP问题,简单的,先看同构车型
#点的范围及个数
x_min, y_min, x_max, y_max, nums = 0,0,100,100,10
#车容量
capacity = 3
#点集生成
points = points_generate_CVRP(x_min, y_min, x_max, y_max, nums, capacity)
print("\npoints", points)
A = IP(points, capacity, 100)
#价值及画图
Dis = [[calculate_distance(points[i].x, points[i].y, points[j].x, points[j].y, "EUC") for j in range(nums)] for i in
range(nums)]
print("A:", price(A, Dis))
A1 = [[1 if i < j and (A[i][j] == 1 or A[j][i] == 1) else 0 for j in range(len(points))] for i in range(len(points))]
A_plot(points, A1, x_min, y_min, x_max, y_max)
横扫式聚类
from tool.Distance import calculate_distance
from VRP.CVRP.tool.Plot import *
from VRP.CVRP.tool.Print import *
from TSP.Heuristic import TSP_insert
from VRP.CVRP.tool.Data_generate import *
from VRP.CVRP.tool.Graph_transform import *
def clustering(points, capacity):
p0 = points[0]
points1 = points[1:]
points1.sort(key=lambda p: p.x)
#横扫式聚类
LLP = []
points1_used = [0 for i in range(len(points1))]
while sum(points1_used) < len(points1_used):
LP = []
start = 0
for i in range(len(points1_used)):
if points1_used[i] == 0:
start = i
LP.append(points1[start])
points1_used[start] = 1
break
dis = [[i, calculate_distance(points1[start].x, points1[start].y, points1[i].x, points1[i].y, "EUC")] for i in range(len(points1)) if points1_used[i] == 0]
dis.sort(key=lambda x:x[1])
if len(dis) > 0:
count = points1[start].demand
i = 0
while i < len(dis):
if count+points1[dis[i][0]].demand > capacity:
break
else:
LP.append(points1[dis[i][0]])
count += points1[dis[i][0]].demand
points1_used[dis[i][0]] = 1
i += 1
LLP.append(LP)
#每片作TSP
edges = set()
for LP in LLP:
pointsi = [[0, p0.x, p0.y]] + [[j+1, LP[j].x, LP[j].y] for j in range(len(LP))]
D = {0:0}
for j in range(len(LP)):
D[j+1] = LP[j].ID
Dis = [[calculate_distance(pointsi[i][1], pointsi[i][2], pointsi[j][1], pointsi[j][2], "EUC") for j in
range(len(pointsi))] for i in range(len(pointsi))]
A_insert = TSP_insert(pointsi, Dis)
for i in range(len(A_insert)):
for j in range(i+1, len(A_insert)):
if A_insert[i][j] == 1:
edges.add((D[i],D[j]))
X = [[1 if (points[i].ID, points[j].ID) in edges or (points[j].ID, points[i].ID) in edges else 0 for j in range(len(points))] for i in range(len(points))]
return Unirected_to_directed(X)
def price(A, Dis):
n = len(A)
return sum([Dis[i][j] * A[i][j] for i in range(n) for j in range(n)])
if __name__ == "__main__":
#这里先定义一下标准的CVRP问题,简单的,先看同构车型
#点的范围及个数
x_min, y_min, x_max, y_max, nums = 0,0,100,100,10
#车容量
capacity = 4
#点集生成
points = points_generate_CVRP(x_min, y_min, x_max, y_max, nums, capacity)
print(points)
A = clustering(points, capacity)
LL_print("A", A)
#价值及画图
Dis = [[calculate_distance(points[i].x, points[i].y, points[j].x, points[j].y, "EUC") for j in range(nums)] for i in range(nums)]
print("A:", price(A, Dis))
A_plot(points, A, x_min, y_min, x_max, y_max)
层次聚类
from tool.Distance import calculate_distance
from VRP.CVRP.tool.Plot import *
from VRP.CVRP.tool.Print import *
from TSP.Heuristic import TSP_insert
from VRP.CVRP.tool.Data_generate import *
from VRP.CVRP.tool.Graph_transform import *
def hierarchical_clustering(points, capacity):
p0 = points[0]
points1 = points[1:]
#以带约束的层次聚类方法初始化
LLP = [[points1[i]] for i in range(len(points1))]
flag = True
while flag:
flag = False
Dis = [[i,j,calculate_distance(sum([point.x for point in LLP[i]])/len(LLP[i]), sum([point.y for point in LLP[i]])/len(LLP[i]),
sum([point.x for point in LLP[j]])/len(LLP[j]), sum([point.y for point in LLP[j]])/len(LLP[j]), "EUC")]
for i in range(len(LLP)) for j in range(i+1, len(LLP))]
Dis.sort(key=lambda x:x[2])
for pair in Dis:
i, j = pair[0], pair[1]
#合并条件:载重,载容,件数,团点
if sum([point.demand for point in LLP[i]]) + sum([point.demand for point in LLP[j]]) <= capacity:
LLP = LLP[:i] + LLP[i+1:j] + LLP[j+1:] + [LLP[i]+LLP[j]]
flag = True
break
edges = set()
for LP in LLP:
pointsi = [[0, p0.x, p0.y]] + [[j+1, LP[j].x, LP[j].y] for j in range(len(LP))]
D = {0:0}
for j in range(len(LP)):
D[j+1] = LP[j].ID
Dis = [[calculate_distance(pointsi[i][1], pointsi[i][2], pointsi[j][1], pointsi[j][2], "EUC") for j in
range(len(pointsi))] for i in range(len(pointsi))]
A_insert = TSP_insert(pointsi, Dis)
for i in range(len(A_insert)):
for j in range(i+1, len(A_insert)):
if A_insert[i][j] == 1:
edges.add((D[i],D[j]))
X = [[1 if (points[i].ID, points[j].ID) in edges or (points[j].ID, points[i].ID) in edges else 0 for j in range(len(points))] for i in range(len(points))]
return Unirected_to_directed(X)
def price(A, Dis):
n = len(A)
return sum([Dis[i][j] * A[i][j] for i in range(n) for j in range(n)])
if __name__ == "__main__":
#这里先定义一下标准的CVRP问题,简单的,先看同构车型
#点的范围及个数
x_min, y_min, x_max, y_max, nums = 0,0,100,100,10
#车容量
capacity = 4
#点集生成
points = points_generate_CVRP(x_min, y_min, x_max, y_max, nums, capacity)
print(points)
A = hierarchical_clustering(points, capacity)
LL_print("A", A)
#价值及画图
Dis = [[calculate_distance(points[i].x, points[i].y, points[j].x, points[j].y, "EUC") for j in range(nums)] for i in range(nums)]
print("A:", price(A, Dis))
A_plot(points, A, x_min, y_min, x_max, y_max)
扫描法
from tool.Distance import calculate_distance
from VRP.CVRP.tool.Plot import *
from VRP.CVRP.tool.Print import *
from TSP.Heuristic import TSP_insert
from VRP.CVRP.tool.Data_generate import *
from VRP.CVRP.tool.Graph_transform import *
import math
def angle_dir(p0, p1):
dx, dy = p1.x-p0.x, p1.y-p0.y
if dx > 0:
if dy >= 0:
angle = math.atan(dy/dx)
else:
angle = math.atan(dy/dx) + 2*math.pi
elif dx == 0:
if dy > 0:
angle = math.pi/2
elif dy == 0:
angle = 0
else:
angle = math.pi*3/2
else:
angle = math.atan(dy/dx)+math.pi
return angle
def sweep(points, capacity):
p0 = points[0]
points1 = points[1:]
#按极坐标排序
LL = [[points1[i], angle_dir(p0, points1[i])] for i in range(len(points1))]
LL.sort(key=lambda x:x[1])
points1 = [L[0] for L in LL]
#初始化片区
LLP = [[]]
c = 0
for p in points1:
if p.demand + c <= capacity:
LLP[-1].append(p)
c += p.demand
else:
LLP.append([p])
c = p.demand
edges = set()
for LP in LLP:
pointsi = [[0, p0.x, p0.y]] + [[j+1, LP[j].x, LP[j].y] for j in range(len(LP))]
D = {0:0}
for j in range(len(LP)):
D[j+1] = LP[j].ID
Dis = [[calculate_distance(pointsi[i][1], pointsi[i][2], pointsi[j][1], pointsi[j][2], "EUC") for j in
range(len(pointsi))] for i in range(len(pointsi))]
A_insert = TSP_insert(pointsi, Dis)
for i in range(len(A_insert)):
for j in range(i+1, len(A_insert)):
if A_insert[i][j] == 1:
edges.add((D[i],D[j]))
X = [[1 if (points[i].ID, points[j].ID) in edges or (points[j].ID, points[i].ID) in edges else 0 for j in range(len(points))] for i in range(len(points))]
return Unirected_to_directed(X)
def price(A, Dis):
n = len(A)
return sum([Dis[i][j] * A[i][j] for i in range(n) for j in range(n)])
if __name__ == "__main__":
#这里先定义一下标准的CVRP问题,简单的,先看同构车型
#点的范围及个数
x_min, y_min, x_max, y_max, nums = 0,0,100,100,30
#车容量
capacity = 10
#点集生成
points = points_generate_CVRP(x_min, y_min, x_max, y_max, nums, capacity)
print(points)
A = sweep(points, capacity)
LL_print("A", A)
#价值及画图
Dis = [[calculate_distance(points[i].x, points[i].y, points[j].x, points[j].y, "EUC") for j in range(nums)] for i in range(nums)]
print("A:", price(A, Dis))
A_plot(points, A, x_min, y_min, x_max, y_max)
T2C
from tool.Distance import calculate_distance
from VRP.CVRP.tool.Plot import *
from VRP.CVRP.tool.Print import *
from TSP.Heuristic import TSP_insert
from VRP.CVRP.tool.Data_generate import *
from VRP.CVRP.tool.Graph_transform import *
def X_init(points):
D = {}
for j in range(len(points)):
D[j] = points[j]
points1 = [[j, points[j].x, points[j].y] for j in range(len(points))]
Dis = [[calculate_distance(points1[i][1], points1[i][2], points1[j][1], points1[j][2], "EUC") for j in range(len(points1))] for i in range(len(points1))]
A_insert = TSP_insert(points1, Dis)
edges = {i:[] for i in range(len(A_insert))}
for i in range(len(A_insert)):
for j in range(i+1, len(A_insert)):
if A_insert[i][j] == 1:
edges[i].append(j)
edges[j].append(i)
X = [0]
now = 0
while True:
next = edges[now][0]
if next in X:
next = edges[now][1]
if next in X:
break
X.append(next)
now = next
return [D[x] for x in X]
def T2C(points, capacity):
p0 = points[0]
#先把所有点串一下
X = X_init(points)
#初始化片区
LLP = [[]]
c = 0
for p in X[1:]:
if p.demand + c <= capacity:
LLP[-1].append(p)
c += p.demand
else:
LLP.append([p])
c = p.demand
#每片作TSP
edges = set()
for LP in LLP:
pointsi = [[0, p0.x, p0.y]] + [[j+1, LP[j].x, LP[j].y] for j in range(len(LP))]
D = {0:0}
for j in range(len(LP)):
D[j+1] = LP[j].ID
Dis = [[calculate_distance(pointsi[i][1], pointsi[i][2], pointsi[j][1], pointsi[j][2], "EUC") for j in
range(len(pointsi))] for i in range(len(pointsi))]
A_insert = TSP_insert(pointsi, Dis)
for i in range(len(A_insert)):
for j in range(i+1, len(A_insert)):
if A_insert[i][j] == 1:
edges.add((D[i],D[j]))
X = [[1 if (points[i].ID, points[j].ID) in edges or (points[j].ID, points[i].ID) in edges else 0 for j in range(len(points))] for i in range(len(points))]
return Unirected_to_directed(X)
def price(A, Dis):
n = len(A)
return sum([Dis[i][j] * A[i][j] for i in range(n) for j in range(n)])
if __name__ == "__main__":
#这里先定义一下标准的CVRP问题,简单的,先看同构车型
#点的范围及个数
x_min, y_min, x_max, y_max, nums = 0,0,100,100,10
#车容量
capacity = 4
#点集生成
points = points_generate_CVRP(x_min, y_min, x_max, y_max, nums, capacity)
print(points)
A = T2C(points, capacity)
LL_print("A", A)
#价值及画图
Dis = [[calculate_distance(points[i].x, points[i].y, points[j].x, points[j].y, "EUC") for j in range(nums)] for i in range(nums)]
print("A:", price(A, Dis))
A_plot(points, A, x_min, y_min, x_max, y_max)