整数规划建模
-
- import pyscipopt
- import re
- import time
- import math
- #记录每个函数执行的时间
- loop = 1
- def timeLog(f):
- def wrapper(*args, **kw):
- global loop
- now = time.perf_counter()
- res = f(*args, **kw)
- print("%s-%s:"%(loop, f.__name__), time.perf_counter()-now)
- loop += 1
- return res
- return wrapper
-
- class Case:
-
- def __init__(self, name, box, goods, boxUsedMin):
- self.name = name
- self.box = box
- self.goods = goods
- self.boxUsedMin = boxUsedMin
-
- def __repr__(self):
- return str([self.name, self.box, self.goods, self.boxUsedMin])
-
- def dataRead():
- data_paths = [r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack1.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack2.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack3.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack4.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack5.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack6.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack7.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack8.txt"]
-
- cases = []
- for path in data_paths:
- f = open(path)
- #一个文件中的case个数
- num = int(f.readline())
- for _ in range(num):
- name = f.readline().replace('\n', '').strip()
- row = f.readline().replace('\n', '').strip()
- row = [float(w) for w in re.split(" ", row)]
- box, numGoods, boxUsedMin = row[0], int(row[1]), int(row[2])
- goods = []
- for _ in range(numGoods):
- goods.append(float(f.readline()))
- cases.append(Case(name, box, goods, boxUsedMin))
-
- return cases
-
- def caseStandardization(cases):
- for case in cases:
- #确认需要乘多少
- n = 1
- while case.box * n != int(case.box * n):
- n *= 10
- for good in case.goods:
- while good * n != int(good * n):
- n *= 10
- #都乘以这个数,化为整数
- case.box = int(case.box * n)
- for i in range(len(case.goods)):
- case.goods[i] = int(case.goods[i] * n)
-
- #启发式方法得到箱子数上界
- def NF(case):
- L_goods = [[]]
- box = case.box
- boxLeft = box
- for good in case.goods:
- if good <= boxLeft:
- boxLeft -= good
- L_goods[-1].append(good)
- else:
- boxLeft = box - good
- L_goods.append([good])
- return len(L_goods)
-
- def IPBPP1D(case, time_limit = 1000, printLog = False):
-
- m = NF(case)
- n = len(case.goods)
- W = case.goods
- V = case.box
- mMin = math.ceil(sum(case.goods)/case.box)
- model = pyscipopt.Model("IPBPP1D")
-
- Y = [model.addVar(vtype="B", name="Y[%s]" % i) for i in range(m)]
- X = [[model.addVar(vtype="B", name="X[%s,%s]" % (i, j)) for j in range(n)] for i in range(m)]
- model.setObjective(pyscipopt.quicksum(Y[i] for i in range(m)), "minimize")
-
- #每个箱子启用后才能进行装载
- for i in range(m):
- model.addCons(pyscipopt.quicksum(W[j]*X[i][j] for j in range(n)) <= V*Y[i])
-
- #每个good都被装下
- for j in range(n):
- model.addCons(pyscipopt.quicksum(X[i][j] for i in range(m)) == 1)
-
- #体积约束
- model.addCons(pyscipopt.quicksum(Y[i] for i in range(m)) >= mMin)
-
- # 设置求解时间
- model.setRealParam("limits/time", time_limit)
- if not printLog:
- model.hideOutput()
- model.optimize()
- print("\ngap:", model.getGap())
-
- # 拿结果
- Y1 = [round(model.getVal(Y[i])) for i in range(m)]
- X1 = [[round(model.getVal(X[i][j])) for j in range(n)] for i in range(m)]
-
- return Y1, X1
-
- if __name__ == '__main__':
- cases = dataRead()
- caseStandardization(cases)
- case = cases[0]
- Y, X = IPBPP1D(case, printLog=True)
-
-
- import re
- import time
- from BPP.meta_heuristic.Two_opt import two_opt
-
- #记录每个函数执行的时间
- loop = 1
- def timeLog(f):
- def wrapper(*args, **kw):
- global loop
- now = time.perf_counter()
- res = f(*args, **kw)
- print("%s-%s:"%(loop, f.__name__), time.perf_counter()-now)
- loop += 1
- return res
- return wrapper
-
- class Case:
-
- def __init__(self, name, box, goods, boxUsedMin):
- self.name = name
- self.box = box
- self.goods = goods
- self.boxUsedMin = boxUsedMin
-
- def __repr__(self):
- return str([self.name, self.box, self.goods, self.boxUsedMin])
-
- def dataRead():
- data_paths = [r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack1.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack2.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack3.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack4.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack5.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack6.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack7.txt",
- r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack8.txt"]
-
- cases = []
- for path in data_paths:
- f = open(path)
- #一个文件中的case个数
- num = int(f.readline())
- for _ in range(num):
- name = f.readline().replace('\n', '').strip()
- row = f.readline().replace('\n', '').strip()
- row = [float(w) for w in re.split(" ", row)]
- box, numGoods, boxUsedMin = row[0], int(row[1]), int(row[2])
- goods = []
- for _ in range(numGoods):
- goods.append(float(f.readline()))
- cases.append(Case(name, box, goods, boxUsedMin))
-
- return cases
-
- def caseStandardization(cases):
- for case in cases:
- #确认需要乘多少
- n = 1
- while case.box * n != int(case.box * n):
- n *= 10
- for good in case.goods:
- while good * n != int(good * n):
- n *= 10
- #都乘以这个数,化为整数
- case.box = int(case.box * n)
- for i in range(len(case.goods)):
- case.goods[i] = int(case.goods[i] * n)
-
- #next fit,一个个的打开箱子,将物品装进去,如果装不下就开一个新的箱子
- def NF(box, goods):
- L_goods = [[]]
- boxLeft = box
- for good in goods:
- if good <= boxLeft:
- boxLeft -= good
- L_goods[-1].append(good)
- else:
- boxLeft = box - good
- L_goods.append([good])
- return len(L_goods)
-
- #first fit,检查所有非空箱子,找第一个非空箱子放进去
- def FF(box, goods):
- L_goods = [[]]
- L_boxLeft = [box]
- for good in goods:
- flag = False
- for i in range(len(L_boxLeft)):
- if good <= L_boxLeft[i]:
- L_boxLeft[i] -= good
- L_goods[i].append(good)
- flag = True
- break
- if not flag:
- L_boxLeft.append(box - good)
- L_goods.append([good])
- return len(L_goods)
-
- #first fit Decreasing,先降序排序,再FF
- def FFD(box, goods):
- goods1 = sorted(goods, reverse=True)
- return FF(box, goods1)
-
- #best fit,检查所有非空箱子,找剩余空间最小的放进去
- def BF(box, goods):
- L_goods = [[]]
- L_boxLeft = [box]
- for good in goods:
- idx, leftMin = None, None
- for i in range(len(L_boxLeft)):
- if good <= L_boxLeft[i]:
- if leftMin is None or leftMin > L_boxLeft[i]:
- idx = i
- leftMin = L_boxLeft[i]
- if idx is not None:
- L_boxLeft[idx] -= good
- L_goods[idx].append(good)
- else:
- L_boxLeft.append(box - good)
- L_goods.append([good])
- return len(L_goods)
-
- #best fit Decreasing,先降序排序,再BF
- def BFD(box, goods):
- goods1 = sorted(goods, reverse=True)
- return BF(box, goods1)
-
- #打散顺序,然后采用FF和BF尝试
- def twoOpt(box, goods):
- goods1 = sorted(goods, reverse=True)
- X = goods1
- def f(X, **kwargs):
- return FF(kwargs['box'], X)
- def f2(X, **kwargs):
- return BF(kwargs['box'], X)
- def c(X):
- return True
- def e(x,y):
- if x == y:
- return True
- return False
-
- X1 = two_opt(X, f, c, e, False, 100, box=box)
- X2 = two_opt(X, f2, c, e, False, 100, box=box)
-
- return min(FF(box, X1),BF(box, X2))
-
- def runOne(case):
- box, goods = case.box, case.goods
-
- #NF
- boxUsedNF = NF(box, goods)
-
- #FF
- boxUsedFF = FF(box, goods)
- boxUsedFFD = FFD(box, goods)
-
- #BF
- boxUsedBF = BF(box, goods)
- boxUsedBFD = BFD(box, goods)
-
- #twoOpt
- boxUsedTwoOpt = twoOpt(box, goods)
-
- print("\nname: ", case.name)
- print("opt: ", case.boxUsedMin)
- print("boxUsedNF: ", boxUsedNF)
- print("boxUsedFF: ", boxUsedFF)
- print("boxUsedFFD: ", boxUsedFFD)
- print("boxUsedBF: ", boxUsedBF)
- print("boxUsedBFD: ", boxUsedBFD)
- print("boxUsedTwoOpt: ", boxUsedTwoOpt)
- return case.boxUsedMin, boxUsedNF, boxUsedFF, boxUsedFFD, boxUsedBF, boxUsedBFD, boxUsedTwoOpt
-
- def gapCount(L_opt, L):
- L_gap = [(L[i]-L_opt[i])/L_opt[i] for i in range(len(L_opt))]
- return sum(L_gap)/len(L_gap)
-
- def runAll(cases):
- L_opt = []
- L_NF = []
- L_FF = []
- L_FFD = []
- L_BF = []
- L_BFD = []
- L_twoOpt = []
- for case in cases:
- boxUsedMin, boxUsedNF, boxUsedFF, boxUsedFFD, boxUsedBF, boxUsedBFD, boxUsedTwoOpt = runOne(case)
- L_opt.append(boxUsedMin)
- L_NF.append(boxUsedNF)
- L_FF.append(boxUsedFF)
- L_FFD.append(boxUsedFFD)
- L_BF.append(boxUsedBF)
- L_BFD.append(boxUsedBFD)
- L_twoOpt.append(boxUsedTwoOpt)
-
- #统计gap
- gapNF = gapCount(L_opt, L_NF)
- gapFF = gapCount(L_opt, L_FF)
- gapFFD = gapCount(L_opt, L_FFD)
- gapBF = gapCount(L_opt, L_BF)
- gapBFD = gapCount(L_opt, L_BFD)
- gaptwoOpt = gapCount(L_opt, L_twoOpt)
- print("\ngapNF: ", gapNF)
- print("gapFF: ", gapFF)
- print("gapFFD: ", gapFFD)
- print("gapBF: ", gapBF)
- print("gapBFD: ", gapBFD)
- print("gaptwoOpt: ", gaptwoOpt)
-
-
- if __name__ == '__main__':
- cases = dataRead()
- caseStandardization(cases)
- runAll(cases)
-
-