forked from seanys/Transportation-and-Optimization-Notes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdw_decomposition.py
167 lines (127 loc) · 5 KB
/
dw_decomposition.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
'''
类型:Dantzig Wolfe Decomposition
原理:该算法主要应对部分约束较为复杂的情况,将其进行分解,与Bender的差异是,
Bender是部分变量较为复杂,求解过程中,Bender是通过求解子问题,给主问题增加
约束,而DW解出子问题后,会增加基变量,这一点类似于Column Generation。
源码:还在写!!!!!!原理和DW
'''
from pulp import * # 基于Pulp
import random # 生成随机数
class MasterProblem:
'''主问题
'''
def __init__(self, maxValue, itemLengths, itemDemands, initialPatterns, problemname):
self.maxValue=maxValue
self.itemLengths=itemLengths
self.itemDemands=itemDemands
self.initialPatterns=initialPatterns
self.prob = LpProblem(problemname,LpMinimize) # 建立初始问题
self.obj = LpConstraintVar("obj") # 建立目标函数的约束变量
self.prob.setObjective(self.obj)
self.PatternVars = []
self.constraintList = [] # 约束函数部分
for i,x in enumerate(itemDemands): # 建立主问题的全部约束
var = LpConstraintVar("C"+str(i),LpConstraintGE,x)
self.constraintList.append(var)
self.prob += var
for i,x in enumerate(self.initialPatterns): # 建立初始的解
temp = []
for j,y in enumerate(x):
if y > 0:
temp.append(j)
var = LpVariable("Pat"+str(i) , 0, None, LpContinuous, lpSum(self.obj+[self.constraintList[v] for v in temp])) # create decision variable: will determine how often pattern x should be produced
self.PatternVars.append(var)
def solve(self):
self.prob.writeLP('res/prob.lp')
self.prob.solve()
return [self.prob.constraints[i].pi for i in self.prob.constraints]
def addPattern(self,pattern):
'''增加新的Pattern'''
self.initialPatterns.append(pattern)
temp = []
for j,y in enumerate(pattern):
if y>0:
temp.append(j)
var = LpVariable("Pat"+str(len(self.initialPatterns)) , 0, None, LpContinuous, lpSum(self.obj+[pattern[v]*self.constraintList[v] for v in temp]))
self.PatternVars.append(var)
def startSub(self,duals):
'''解SubProblem求解新的Pattern'''
newSubProb = SubProblem(duals,self.itemLengths,self.maxValue)
pattern = newSubProb.returnPattern()
return pattern
def setRelaxed(self,relaxed):
'''如果没有找到新的Patterns,那么按照整数规划求解'''
if relaxed == False:
for var in self.prob.variables():
var.cat = LpInteger
def getObjective(self):
return value(self.prob.objective)
def getUsedPatterns(self):
usedPatternList=[]
for i,x in enumerate(self.PatternVars):
if value(x)>0:
usedPatternList.append((value(x),self.initialPatterns[i]))
return usedPatternList
class SubProblem(object):
'''子问题建立
思路:通过对偶问题求目标参数,以及约束,解出后如果目标函数符合
条件,则在Pattern中增加新的变量,然后进入下一轮求解
'''
def __init__(self,duals, itemLengths,maxValue):
self.subprob = LpProblem("Sub problem solver",LpMinimize)
self.varList = [LpVariable('S'+str(i),0,None,LpInteger) for i,x in enumerate(duals)]
self.subprob += -lpSum([duals[i]*x for i,x in enumerate(self.varList)]) # 建立对偶问题
self.subprob += lpSum([itemLengths[i]*x for i,x in enumerate(self.varList)]) <= maxValue
self.subprob.writeLP('res/subprob.lp')
self.subprob.solve()
self.subprob.roundSolution()
def returnPattern(self):
'''判断是否可以解'''
pattern = False
if value(self.subprob.objective) < -1.00001:
pattern = []
for v in self.varList:
pattern.append(value(v))
return pattern
random.seed(2012)
nrItems = 12
lengthSheets=20
itemLengths=[]
itemDemands=[]
# 生成整个的约束变量
while len(itemLengths) != nrItems:
length = random.randint(5, lengthSheets-2)
demand = random.randint(5, 100)
if length not in itemLengths:
itemLengths.append(length)
itemDemands.append(demand)
print("Item lengts : %s" % itemLengths)
print("Item demands : %s\n\n" % itemDemands)
# 随机生成问题
patterns = []
print("Generating start patterns:")
for x in range(nrItems):
temp = [0.0 for y in range(x)]
temp.append(1.0)
temp += [0.0 for y in range(nrItems-x-1)]
patterns.append(temp)
print(temp)
# 解Master Problem
print("\n\nTrying to solve problem")
CGprob = MasterProblem(lengthSheets,itemLengths,itemDemands,patterns,'1D cutting stock')
# 进行持续性松弛,解SubProblem,直到没有更优解
relaxed = True
while relaxed == True:
duals = CGprob.solve()
newPattern = CGprob.startSub(duals)
print('New pattern: %s' % newPattern)
if newPattern:
CGprob.addPattern(newPattern) # 找到新的Pattern就开始求解
else:
CGprob.setRelaxed(False) # 没有找到新的Pattern,就按照整数规划方式求解
CGprob.solve()
relaxed=False
print("\n\nSolution: %s sheets required" % CGprob.getObjective())
t=CGprob.getUsedPatterns()
for i,x in enumerate(t):
print("Pattern %s: selected %s times %s" % (i,x[0],x[1]))