Skip to content

Commit e2042ed

Browse files
committed
NEW
1 parent bd353b0 commit e2042ed

File tree

20 files changed

+4204
-0
lines changed

20 files changed

+4204
-0
lines changed

extend/backup/VRP&MST/data.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
| | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P |
2+
|----|----|----|------|--------|------|-------|--------|----|-----|------|------|------|--------|------|---------|------|
3+
| A | | 4 | | 3.5 | | 6.2 | 3.5 | 6 | | | | | | | | |
4+
| B | | | 3.7 | | 4.5 | | | | 3 | | | | | | | |
5+
| C | | | | 3.4 | | | | | | 5.9 | | | | | | |
6+
| D | | | | | | | | | | | | | | | | |
7+
| E | | | | | | 3.3 | | | | | | | | | | |
8+
| F | | | | | | | | | | | 7.2 | 3 | | | | |
9+
| G | | | | | | | | | | | 7 | | 7.3 | | | |
10+
| H | | | | | | | | | | | | | 8.8 | | 5.8 | 3.4 |
11+
| I | | | | | | | | | | | | 11 | | | | |
12+
| J | | | | | | | | | | | | | | | 4.5 | |
13+
| K | | | | | | | | | | | | 7.5 | 3.1 | | | |
14+
| L | | | | | | | | | | | | | | | | |
15+
| M | | | | | | | | | | | | | | 4.3 | | |
16+
| N | | | | | | | | | | | | | | | | 8.4 |
17+
| O | | | | | | | | | | | | | | | | 6.9 |
18+
| P | | | | | | | | | | | | | | | | |
19+

extend/backup/VRP&MST/demo1.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import gurobipy
2+
3+
model = gurobipy.Model("model")
4+
xs : gurobipy.tupledict = model.addVars(3, 4, lb=1, ub=5)
5+
6+
cs = model.addConstrs((xs.sum(i, "*") == 1 for i in range(3)))
7+
model.setObjective()
8+
model.update()
9+
model.write('test.lp')

extend/backup/VRP&MST/demo2.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
max: x + y + 2z
3+
s.t. x + 2y + 3z <= 4
4+
x + y >= 1
5+
6+
x, y, z ∈{0, 1}
7+
"""
8+
9+
10+
from gurobipy import *
11+
12+
model = Model("model")
13+
14+
x = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='xaxis')
15+
y = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='yaxis')
16+
z = model.addVar(lb=0, ub=1, vtype=GRB.BINARY, name='zaxis')
17+
18+
objectFunc = model.setObjective(x + y + 2 * z, sense=GRB.MAXIMIZE)
19+
20+
constraint1 = model.addConstr(x + 2 * y + 3 * z <= 4, name='constraint1')
21+
constraint2 = model.addConstr(x + y >= 1, name='constraint2')
22+
23+
model.update()
24+
model.optimize()
25+
26+
xvar : Var = model.getVarByName('xaxis')
27+
print(xvar.x)

extend/backup/VRP&MST/demo3.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from gurobipy import *
2+
3+
dic = multidict({
4+
"k1" : [1, 2, 45],
5+
"k2" : [3, 65, 1]
6+
})
7+
8+
print(dic)
9+
10+
from pympler import asizeof
11+
12+
class MyClass:
13+
def __init__(self, data):
14+
self.data : list = data
15+
16+
obj = MyClass([1, 2, 3, 67, 1, 2, 3, 671, 1, 2, 3, 617, 1, 2, 3, 67, 1, 2, 3, 67, 1, 2, 11])
17+
print(asizeof.asizeof(obj.data))
18+
19+

extend/backup/VRP&MST/demo4.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import gurobipy
2+
from gurobipy import GRB
3+
import numpy
4+
5+
# https://zhuanlan.zhihu.com/p/651080846
6+
7+
# 边的定义和距离矩阵的初始化
8+
edges = {
9+
(0, 1): 4, (0, 3): 3.5, (0, 5): 6.2, (0, 7): 3.5, (0, 8): 6,
10+
(1, 2): 3.7, (1, 4): 4.5, (1, 9): 3,
11+
(2, 3): 3.4, (2, 10): 5.9,
12+
(4, 5): 3.3,
13+
(5, 10): 7.2, (5, 11): 3,
14+
(6, 10): 7, (6, 12): 7.3,
15+
(7, 12): 8.8, (7, 14): 5.8, (7, 15): 3.4,
16+
(8, 11): 11,
17+
(9, 14): 4.5,
18+
(10, 12): 7.5, (10, 13): 3.1,
19+
(12, 13): 4.3,
20+
(13, 15): 8.4,
21+
(14, 15): 6.9
22+
}
23+
24+
distances = numpy.full((16, 16), GRB.INFINITY)
25+
for k, v in edges.items():
26+
i, j = k
27+
distances[i][j] = v
28+
distances[j][i] = v
29+
30+
numpy.fill_diagonal(distances, 0) # 自己到自己的距离为0
31+
32+
# 问题参数:客户数量和车辆数
33+
n = 15 # 客户点数目
34+
m = 3 # 车辆数目
35+
36+
# 创建优化模型
37+
model = gurobipy.Model("VRP")
38+
39+
# 决策变量:X[k, i, j] 表示车辆k是否从i点行驶到j点
40+
X = model.addVars(m, 1 + n, 1 + n, vtype=GRB.BINARY, name='X')
41+
42+
# 目标函数:最小化总行驶距离
43+
objFunc = gurobipy.quicksum(
44+
distances[i, j] * X[k, i, j]
45+
for k in range(m)
46+
for i in range(n + 1)
47+
for j in range(n + 1)
48+
)
49+
50+
model.setObjective(objFunc, GRB.MINIMIZE)
51+
52+
# 约束条件:每辆车从起点出发
53+
for k in range(m):
54+
model.addConstr(gurobipy.quicksum(X[k, 0, j] for j in range(1, n + 1)) == 1)
55+
56+
# 约束条件:每辆车必须回到起点
57+
for k in range(m):
58+
model.addConstr(gurobipy.quicksum(X[k, j, 0] for j in range(1, n + 1)) == 1)
59+
60+
# 流量平衡约束:每个客户点的进出流量必须相同
61+
for k in range(m):
62+
for j in range(1, n + 1):
63+
model.addConstr(
64+
gurobipy.quicksum(X[k, i, j] for i in range(n + 1) if i != j) ==
65+
gurobipy.quicksum(X[k, j, i] for i in range(n + 1) if i != j),
66+
name=''
67+
)
68+
69+
# 访问所有客户点的约束:每个客户点必须被访问一次
70+
for j in range(1, n + 1):
71+
model.addConstr(
72+
gurobipy.quicksum(X[k, i, j] for k in range(m) for i in range(n + 1) if i != j) == 1
73+
)
74+
75+
# 禁止不可达的路径
76+
for k in range(m):
77+
for i in range(n + 1):
78+
for j in range(n + 1):
79+
if distances[i, j] == GRB.INFINITY:
80+
model.addConstr(X[k, i, j] == 0)
81+
if i == j:
82+
model.addConstr(X[k, i, j] == 0)
83+
84+
# https://zhuanlan.zhihu.com/p/159270139
85+
# 子回路消除约束:基于 MTZ
86+
U = model.addVars(m, 1 + n, lb=0, ub=n, vtype=GRB.INTEGER, name='U')
87+
88+
# MTZ 约束:防止车辆走子回路
89+
for k in range(m):
90+
for i in range(1, n + 1):
91+
for j in range(1, n + 1):
92+
if i != j:
93+
model.addConstr(U[k, i] - U[k, j] + n * X[k, i, j] <= n - 1)
94+
95+
# 起点顺序号为0
96+
for k in range(m):
97+
model.addConstr(U[k, 0] == 0)
98+
99+
# 更新模型并求解
100+
model.update()
101+
model.optimize()
102+
103+
# 检查是否找到最优解
104+
if model.status == GRB.OPTIMAL:
105+
print(f"最小总行驶距离: {model.objVal}")
106+
else:
107+
print(f"没有找到最优解,状态码: {model.status}")
108+
109+
model.computeIIS()
110+
model.write("model.lp")

extend/backup/VRP&MST/demo5.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import gurobipy
2+
from gurobipy import GRB
3+
4+
# 点数目
5+
n = 16
6+
# 点名字
7+
nodes = [chr(x) for x in range(n + 65)]
8+
9+
# 距离邻接矩阵
10+
edges = [
11+
('A', 'B', 4), ('A', 'D', 3.5), ('A', 'F', 6.2), ('A', 'G', 3.5), ('A', 'H', 6),
12+
('B', 'C', 3.7), ('B', 'E', 4.5), ('B', 'I', 3),
13+
('C', 'D', 3.4), ('C', 'J', 5.9),
14+
('E', 'F', 3.3),
15+
('F', 'K', 7.2), ('F', 'L', 3),
16+
('G', 'K', 7), ('G', 'M', 7.3),
17+
('H', 'M', 8.8), ('H', 'O', 5.8), ('H', 'P', 3.4),
18+
('I', 'L', 11),
19+
('J', 'O', 4.5),
20+
('K', 'L', 7.5), ('K', 'M', 3.1),
21+
('M', 'N', 4.3),
22+
('N', 'P', 8.4),
23+
('O', 'P', 6.9)
24+
] # len == 25
25+
26+
# 创建模型
27+
model = gurobipy.Model('mst')
28+
29+
# 建立变量,X[i,j]表示边(i,j)是否被选中
30+
X = model.addVars(edges, vtype=GRB.BINARY, name="X")
31+
32+
# 目标函数:最小化边的权重和
33+
model.setObjective(gurobipy.quicksum(X.select(i, j, '*')[0] * w for i, j, w in edges), GRB.MINIMIZE)
34+
35+
# 添加约束:选择的边数等于节点数减一
36+
model.addConstr(gurobipy.quicksum(X.select(i, j, '*')[0] for i, j, w in edges) == n - 1, "edge_count")
37+
38+
# 求解模型
39+
model.update()
40+
model.optimize()
41+
42+
# 输出结果
43+
if model.status == GRB.OPTIMAL:
44+
print("最优解找到")
45+
ws = 0.0
46+
for i, j, w in edges:
47+
if X.select(i, j, '*')[0].X > 0.5:
48+
print(f"边 ({i}, {j}) 被选中,权重: {w}")
49+
ws += w
50+
print("总权重:%f" % ws)
51+
else:
52+
print("没有找到最优解")

extend/backup/VRP&MST/demo6.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import gurobipy
2+
from gurobipy import GRB
3+
import numpy
4+
from itertools import combinations
5+
6+
# 边的定义和距离矩阵的初始化
7+
edges = {
8+
(0, 1): 4, (0, 3): 3.5, (0, 5): 6.2, (0, 7): 3.5, (0, 8): 6,
9+
(1, 2): 3.7, (1, 4): 4.5, (1, 9): 3,
10+
(2, 3): 3.4, (2, 10): 5.9,
11+
(4, 5): 3.3,
12+
(5, 10): 7.2, (5, 11): 3,
13+
(6, 10): 7, (6, 12): 7.3,
14+
(7, 12): 8.8, (7, 14): 5.8, (7, 15): 3.4,
15+
(8, 11): 11,
16+
(9, 14): 4.5,
17+
(10, 12): 7.5, (10, 13): 3.1,
18+
(12, 13): 4.3,
19+
(13, 15): 8.4,
20+
(14, 15): 6.9
21+
}
22+
23+
distances = numpy.full((16, 16), GRB.INFINITY)
24+
for k, v in edges.items():
25+
i, j = k
26+
distances[i][j] = v
27+
distances[j][i] = v
28+
29+
numpy.fill_diagonal(distances, 0) # 自己到自己的距离为0
30+
31+
# 问题参数:客户数量和车辆数
32+
n = 15 # 客户点数目
33+
m = 3 # 车辆数目
34+
35+
# 创建优化模型
36+
model = gurobipy.Model("VRP")
37+
38+
# 决策变量:X[k, i, j] 表示车辆k是否从i点行驶到j点
39+
X = model.addVars(m, 1 + n, 1 + n, vtype=GRB.BINARY, name='X')
40+
41+
# 目标函数:最小化总行驶距离
42+
objFunc = gurobipy.quicksum(
43+
distances[i, j] * X[k, i, j]
44+
for k in range(m)
45+
for i in range(n + 1)
46+
for j in range(n + 1)
47+
)
48+
49+
model.setObjective(objFunc, GRB.MINIMIZE)
50+
51+
# 约束条件:每辆车从起点出发
52+
for k in range(m):
53+
model.addConstr(gurobipy.quicksum(X[k, 0, j] for j in range(1, n + 1)) == 1)
54+
55+
# 约束条件:每辆车必须回到起点
56+
for k in range(m):
57+
model.addConstr(gurobipy.quicksum(X[k, j, 0] for j in range(1, n + 1)) == 1)
58+
59+
# 流量平衡约束:每个客户点的进出流量必须相同
60+
for k in range(m):
61+
for j in range(1, n + 1):
62+
model.addConstr(
63+
gurobipy.quicksum(X[k, i, j] for i in range(n + 1) if i != j) ==
64+
gurobipy.quicksum(X[k, j, i] for i in range(n + 1) if i != j)
65+
)
66+
67+
# 访问所有客户点的约束:每个客户点必须被访问一次
68+
for j in range(1, n + 1):
69+
model.addConstr(
70+
gurobipy.quicksum(X[k, i, j] for k in range(m) for i in range(n + 1) if i != j) == 1
71+
)
72+
73+
# 禁止不可达的路径
74+
for k in range(m):
75+
for i in range(n + 1):
76+
for j in range(n + 1):
77+
if distances[i, j] == GRB.INFINITY:
78+
model.addConstr(X[k, i, j] == 0)
79+
if i == j:
80+
model.addConstr(X[k, i, j] == 0)
81+
82+
# DFJ子回路消除约束:对于每一个真子集S,确保边数不超过|S|-1
83+
for k in range(m):
84+
for S_size in range(2, n + 1): # 从大小2的子集开始
85+
for S in combinations(range(1, n + 1), S_size): # 获取顶点集合V的真子集S
86+
# 计算集合S中每一对节点i, j的连通边数
87+
model.addConstr(
88+
gurobipy.quicksum(X[k, i, j] for i in S for j in range(1, n + 1) if j not in S) +
89+
gurobipy.quicksum(X[k, j, i] for j in S for i in range(1, n + 1) if i not in S)
90+
<= S_size - 1
91+
)
92+
93+
# 更新模型并求解
94+
model.update()
95+
model.optimize()
96+
97+
# 检查是否找到最优解
98+
if model.status == GRB.OPTIMAL:
99+
print(f"最小总行驶距离: {model.objVal}")
100+
101+
else:
102+
# print(f"没有找到最优解,状态码: {model.status}")
103+
model.computeIIS()
104+
model.write("model.lp")

extend/backup/VRP&MST/facilityPY.lp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
\ Model facility
2+
\ LP format - for model browsing. Use MPS format to capture full model detail.
3+
Minimize
4+
12000 open[0] + 15000 open[1] + 17000 open[2] + 13000 open[3]
5+
+ 16000 open[4] + 4000 trans[0,0] + 2000 trans[0,1] + 3000 trans[0,2]
6+
+ 2500 trans[0,3] + 4500 trans[0,4] + 2500 trans[1,0] + 2600 trans[1,1]
7+
+ 3400 trans[1,2] + 3000 trans[1,3] + 4000 trans[1,4] + 1200 trans[2,0]
8+
+ 1800 trans[2,1] + 2600 trans[2,2] + 4100 trans[2,3] + 3000 trans[2,4]
9+
+ 2200 trans[3,0] + 2600 trans[3,1] + 3100 trans[3,2] + 3700 trans[3,3]
10+
+ 3200 trans[3,4]
11+
Subject To
12+
Capacity[0]: - 20 open[0] + trans[0,0] + trans[1,0] + trans[2,0]
13+
+ trans[3,0] <= 0
14+
Capacity[1]: - 22 open[1] + trans[0,1] + trans[1,1] + trans[2,1]
15+
+ trans[3,1] <= 0
16+
Capacity[2]: - 17 open[2] + trans[0,2] + trans[1,2] + trans[2,2]
17+
+ trans[3,2] <= 0
18+
Capacity[3]: - 19 open[3] + trans[0,3] + trans[1,3] + trans[2,3]
19+
+ trans[3,3] <= 0
20+
Capacity[4]: - 18 open[4] + trans[0,4] + trans[1,4] + trans[2,4]
21+
+ trans[3,4] <= 0
22+
Demand[0]: trans[0,0] + trans[0,1] + trans[0,2] + trans[0,3] + trans[0,4]
23+
= 15
24+
Demand[1]: trans[1,0] + trans[1,1] + trans[1,2] + trans[1,3] + trans[1,4]
25+
= 18
26+
Demand[2]: trans[2,0] + trans[2,1] + trans[2,2] + trans[2,3] + trans[2,4]
27+
= 14
28+
Demand[3]: trans[3,0] + trans[3,1] + trans[3,2] + trans[3,3] + trans[3,4]
29+
= 20
30+
Bounds
31+
Binaries
32+
open[0] open[1] open[2] open[3] open[4]
33+
End

extend/backup/VRP&MST/gurobi-mst.png

63.4 KB
Loading

0 commit comments

Comments
 (0)