苹果 python 返回32512_(FOCUS)有容量限制的 VRP 模型的分支切割法的实现 by python3 & Gurobi...

虽然很忙,挤出时间也要写啊!

CVRP (capacitated vehicle routing problem)

首先,我们来描述CVRP。车辆从仓库出发,经过多个顾客之后,再回到仓库。

车辆的最大载重量 (容量) 已知。

顾客的位置已知,并且各个顾客的需求量已知。

各地点之间的移动费用已知

一条路径的顾客需求量不能超过车辆的最大载重量。

车辆种类假定有一种,且车辆数提前设定。

Modeling

这里我们开始建模。

首先,我们设定车辆数为

,点 (仓库和顾客) 的数为

。顾客

的需求里为

其次,车辆

的载重量上限为

。一般的情况下,我们假定顾客需求量的最大值

不超过

然后,车辆从点

到点

的移动费用为

,并且我们假定

最后,我们给定变量

,如果对于和仓库不相接的枝,车辆通过的时候

,否则,

,但是,如果从仓库向某个点

移动之后,立马返回仓库的时候,

经过以上准备我们可以得到以下模型:

第一个约束条件是从仓库有

台车辆,第二个约束条件保证对于各个顾客有一辆车辆访问。第三个约束条件是禁止车辆的容量约束和部分巡回路。

这里

为了满足顾客的部分集合

内的需求,必要的车辆数。为了计算

,我们通常用以下的下界代用。

Code

下面我们给出代码。

"""vrp.py: model for the vehicle routing problem using callback for adding cuts.approach:- start with assignment model- add cuts until all components of the graph are connectedreference: Prof. KUBO's code"""

import math

import random

import networkx

from gurobipy import *

def vrp(V,c,m,q,Q):

"""solve_vrp -- solve the vehicle routing problem.- start with assignment model (depot has a special status)- add cuts until all components of the graph are connectedParameters:- V: set/list of nodes in the graph- c[i,j]: cost for traversing edge (i,j)- m: number of vehicles available- q[i]: demand for customer i- Q: vehicle capacityReturns the optimum objective value and the list of edges used."""

def vrp_callback(model,where):

"""vrp_callback: add constraint to eliminate infeasible solutionsParameters: gurobi standard:- model: current model- where: indicator for location in the searchIf solution is infeasible, adds a cut using cbLazy"""

# remember to set model.params.DualReductions = 0 before using!

# remember to set model.params.LazyConstraints = 1 before using!

if where != GRB.callback.MIPSOL:

return

edges = []

for (i,j) in x:

if model.cbGetSolution(x[i,j]) > .5:

if i != V[0] and j != V[0]:

edges.append( (i,j) )

G = networkx.Graph()

G.add_edges_from(edges)

Components = networkx.connected_components(G)

for S in Components:

S_card = len(S)

q_sum = sum(q[i] for i in S)

NS = int(math.ceil(float(q_sum)/Q))

S_edges = [(i,j) for i in S for j in S if i

if S_card >= 3 and (len(S_edges) >= S_card or NS > 1):

model.cbLazy(quicksum(x[i,j] for i in S for j in S if j > i) <= S_card-NS)

print ("adding cut for",S_edges)

return

model = Model("vrp")

x = {}

for i in V:

for j in V:

if j > i and i == V[0]: # depot

x[i,j] = model.addVar(ub=2, vtype="I", name="x(%s,%s)"%(i,j))

elif j > i:

x[i,j] = model.addVar(ub=1, vtype="I", name="x(%s,%s)"%(i,j))

model.update()

model.addConstr(quicksum(x[V[0],j] for j in V[1:]) == 2*m, "DegreeDepot")

for i in V[1:]:

model.addConstr(quicksum(x[j,i] for j in V if j < i) +

quicksum(x[i,j] for j in V if j > i) == 2, "Degree(%s)"%i)

model.setObjective(quicksum(c[i,j]*x[i,j] for i in V for j in V if j>i), GRB.MINIMIZE)

model.update()

model.__data = x

return model,vrp_callback

def distance(x1,y1,x2,y2):

"""distance: euclidean distance between (x1,y1) and (x2,y2)"""

return math.sqrt((x2-x1)**2 + (y2-y1)**2)

def make_data(n):

"""make_data: compute matrix distance based on euclidean distance"""

V = range(1,n+1)

x = dict([(i,random.random()) for i in V])

y = dict([(i,random.random()) for i in V])

c,q = {},{}

Q = 100

for i in V:

q[i] = random.randint(10,20)

for j in V:

if j > i:

c[i,j] = distance(x[i],y[i],x[j],y[j])

return V,c,q,Q

if __name__ == "__main__":

import sys

n = 19

m = 3

seed = 1

random.seed(seed)

V,c,q,Q = make_data(n)

model,vrp_callback = vrp(V,c,m,q,Q)

# model.Params.OutputFlag = 0 # silent mode

model.params.DualReductions = 0

model.params.LazyConstraints = 1

model.optimize(vrp_callback)

x = model.__data

edges = []

for (i,j) in x:

if x[i,j].X > .5:

if i != V[0] and j != V[0]:

edges.append( (i,j) )

print ("Optimal solution:",model.ObjVal)

print ("Edges in the solution:")

print (sorted(edges))

下面给去数据。

20 3 100

12 6 8 12 6 12 19 2 15 1 14 18 17 4 14 2 8 3 17 13

0 1 0.8854

0 2 0.347

0 3 0.0657

0 4 0.7677

0 5 0.6219

0 6 0.1078

0 7 0.421

0 8 0.1479

0 9 0.214

0 10 0.5961

0 11 0.2563

0 12 0.2391

0 13 0.4847

0 14 0.7771

0 15 0.5314

0 16 0.2772

0 17 0.3874

0 18 0.3692

0 19 0.5806

1 2 0.2748

1 3 0.8172

1 4 0.3031

1 5 0.0957

1 6 0.1769

1 7 0.2286

1 8 0.8382

1 9 0.193

1 10 0.2046

1 11 0.0724

1 12 0.1526

1 13 0.1958

1 14 0.693

1 15 0.2348

1 16 0.8967

1 17 0.5607

1 18 0.8567

1 19 0.1045

2 3 0.0817

2 4 0.1047

2 5 0.3185

2 6 0.4131

2 7 0.0962

2 8 0.2928

2 9 0.8978

2 10 0.6085

2 11 0.8242

2 12 0.0102

2 13 0.0959

2 14 0.2935

2 15 0.326

2 16 0.1059

2 17 0.8459

2 18 0.3644

2 19 0.2017

3 4 0.758

3 5 0.593

3 6 0.1399

3 7 0.051

3 8 0.7976

3 9 0.8476

3 10 0.8388

3 11 0.7286

3 12 0.6406

3 13 0.1736

3 14 0.7253

3 15 0.3014

3 16 0.7656

3 17 0.565

3 18 0.1183

3 19 0.6055

4 5 0.6187

4 6 0.5314

4 7 0.7017

4 8 0.0115

4 9 0.2644

4 10 0.4103

4 11 0.571

4 12 0.0099

4 13 0.2414

4 14 0.8645

4 15 0.3359

4 16 0.3474

4 17 0.5456

4 18 0.4355

4 19 0.2843

5 6 0.4037

5 7 0.7638

5 8 0.1594

5 9 0.1899

5 10 0.6614

5 11 0.107

5 12 0.1288

5 13 0.2253

5 14 0.7477

5 15 0.0376

5 16 0.6858

5 17 0.7843

5 18 0.8032

5 19 0.3509

6 7 0.6378

6 8 0.2439

6 9 0.0696

6 10 0.2693

6 11 0.0457

6 12 0.7164

6 13 0.2689

6 14 0.1912

6 15 0.3874

6 16 0.2788

6 17 0.1678

6 18 0.0871

6 19 0.35

7 8 0.2504

7 9 0.6327

7 10 0.5207

7 11 0.5347

7 12 0.1364

7 13 0.3845

7 14 0.6942

7 15 0.0616

7 16 0.7812

7 17 0.5364

7 18 0.1904

7 19 0.7417

8 9 0.3841

8 10 0.8632

8 11 0.5275

8 12 0.0036

8 13 0.7665

8 14 0.6136

8 15 0.6415

8 16 0.7456

8 17 0.6833

8 18 0.646

8 19 0.7913

9 10 0.2349

9 11 0.6501

9 12 0.7177

9 13 0.6223

9 14 0.6642

9 15 0.6208

9 16 0.7094

9 17 0.7494

9 18 0.8712

9 19 0.1773

10 11 0.3701

10 12 0.2412

10 13 0.049

10 14 0.7547

10 15 0.0354

10 16 0.1106

10 17 0.6359

10 18 0.5718

10 19 0.0362

11 12 0.4776

11 13 0.6912

11 14 0.8994

11 15 0.7403

11 16 0.43

11 17 0.5011

11 18 0.454

11 19 0.8067

12 13 0.3468

12 14 0.8725

12 15 0.5527

12 16 0.8733

12 17 0.2074

12 18 0.0381

12 19 0.6911

13 14 0.5649

13 15 0.7023

13 16 0.4119

13 17 0.1095

13 18 0.5517

13 19 0.1183

14 15 0.022

14 16 0.0218

14 17 0.3595

14 18 0.071

14 19 0.5117

15 16 0.1301

15 17 0.8168

15 18 0.8828

15 19 0.702

16 17 0.853

16 18 0.1956

16 19 0.2284

17 18 0.5877

17 19 0.036

18 19 0.6584

结果部分截图如下。

大家如果有时间一定要亲自尝试一下哦!

如果有什么疑问或者建议,可以给我发邮件。➡ zhaoyou728 at outlook.com

你可能感兴趣的:(苹果,python,返回32512)