• 90、一维装箱


    数据集

    Bin packing - one-dimensional

    整数规划建模

    1. import pyscipopt
    2. import re
    3. import time
    4. import math
    5. #记录每个函数执行的时间
    6. loop = 1
    7. def timeLog(f):
    8. def wrapper(*args, **kw):
    9. global loop
    10. now = time.perf_counter()
    11. res = f(*args, **kw)
    12. print("%s-%s:"%(loop, f.__name__), time.perf_counter()-now)
    13. loop += 1
    14. return res
    15. return wrapper
    16. class Case:
    17. def __init__(self, name, box, goods, boxUsedMin):
    18. self.name = name
    19. self.box = box
    20. self.goods = goods
    21. self.boxUsedMin = boxUsedMin
    22. def __repr__(self):
    23. return str([self.name, self.box, self.goods, self.boxUsedMin])
    24. def dataRead():
    25. data_paths = [r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack1.txt",
    26. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack2.txt",
    27. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack3.txt",
    28. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack4.txt",
    29. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack5.txt",
    30. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack6.txt",
    31. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack7.txt",
    32. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack8.txt"]
    33. cases = []
    34. for path in data_paths:
    35. f = open(path)
    36. #一个文件中的case个数
    37. num = int(f.readline())
    38. for _ in range(num):
    39. name = f.readline().replace('\n', '').strip()
    40. row = f.readline().replace('\n', '').strip()
    41. row = [float(w) for w in re.split(" ", row)]
    42. box, numGoods, boxUsedMin = row[0], int(row[1]), int(row[2])
    43. goods = []
    44. for _ in range(numGoods):
    45. goods.append(float(f.readline()))
    46. cases.append(Case(name, box, goods, boxUsedMin))
    47. return cases
    48. def caseStandardization(cases):
    49. for case in cases:
    50. #确认需要乘多少
    51. n = 1
    52. while case.box * n != int(case.box * n):
    53. n *= 10
    54. for good in case.goods:
    55. while good * n != int(good * n):
    56. n *= 10
    57. #都乘以这个数,化为整数
    58. case.box = int(case.box * n)
    59. for i in range(len(case.goods)):
    60. case.goods[i] = int(case.goods[i] * n)
    61. #启发式方法得到箱子数上界
    62. def NF(case):
    63. L_goods = [[]]
    64. box = case.box
    65. boxLeft = box
    66. for good in case.goods:
    67. if good <= boxLeft:
    68. boxLeft -= good
    69. L_goods[-1].append(good)
    70. else:
    71. boxLeft = box - good
    72. L_goods.append([good])
    73. return len(L_goods)
    74. def IPBPP1D(case, time_limit = 1000, printLog = False):
    75. m = NF(case)
    76. n = len(case.goods)
    77. W = case.goods
    78. V = case.box
    79. mMin = math.ceil(sum(case.goods)/case.box)
    80. model = pyscipopt.Model("IPBPP1D")
    81. Y = [model.addVar(vtype="B", name="Y[%s]" % i) for i in range(m)]
    82. X = [[model.addVar(vtype="B", name="X[%s,%s]" % (i, j)) for j in range(n)] for i in range(m)]
    83. model.setObjective(pyscipopt.quicksum(Y[i] for i in range(m)), "minimize")
    84. #每个箱子启用后才能进行装载
    85. for i in range(m):
    86. model.addCons(pyscipopt.quicksum(W[j]*X[i][j] for j in range(n)) <= V*Y[i])
    87. #每个good都被装下
    88. for j in range(n):
    89. model.addCons(pyscipopt.quicksum(X[i][j] for i in range(m)) == 1)
    90. #体积约束
    91. model.addCons(pyscipopt.quicksum(Y[i] for i in range(m)) >= mMin)
    92. # 设置求解时间
    93. model.setRealParam("limits/time", time_limit)
    94. if not printLog:
    95. model.hideOutput()
    96. model.optimize()
    97. print("\ngap:", model.getGap())
    98. # 拿结果
    99. Y1 = [round(model.getVal(Y[i])) for i in range(m)]
    100. X1 = [[round(model.getVal(X[i][j])) for j in range(n)] for i in range(m)]
    101. return Y1, X1
    102. if __name__ == '__main__':
    103. cases = dataRead()
    104. caseStandardization(cases)
    105. case = cases[0]
    106. Y, X = IPBPP1D(case, printLog=True)

    启发式算法

    1. import re
    2. import time
    3. from BPP.meta_heuristic.Two_opt import two_opt
    4. #记录每个函数执行的时间
    5. loop = 1
    6. def timeLog(f):
    7. def wrapper(*args, **kw):
    8. global loop
    9. now = time.perf_counter()
    10. res = f(*args, **kw)
    11. print("%s-%s:"%(loop, f.__name__), time.perf_counter()-now)
    12. loop += 1
    13. return res
    14. return wrapper
    15. class Case:
    16. def __init__(self, name, box, goods, boxUsedMin):
    17. self.name = name
    18. self.box = box
    19. self.goods = goods
    20. self.boxUsedMin = boxUsedMin
    21. def __repr__(self):
    22. return str([self.name, self.box, self.goods, self.boxUsedMin])
    23. def dataRead():
    24. data_paths = [r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack1.txt",
    25. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack2.txt",
    26. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack3.txt",
    27. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack4.txt",
    28. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack5.txt",
    29. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack6.txt",
    30. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack7.txt",
    31. r"/Users/zhangchaoyu/PycharmProjects/pythonProject/OR_Library/BPP1D/data/binpack8.txt"]
    32. cases = []
    33. for path in data_paths:
    34. f = open(path)
    35. #一个文件中的case个数
    36. num = int(f.readline())
    37. for _ in range(num):
    38. name = f.readline().replace('\n', '').strip()
    39. row = f.readline().replace('\n', '').strip()
    40. row = [float(w) for w in re.split(" ", row)]
    41. box, numGoods, boxUsedMin = row[0], int(row[1]), int(row[2])
    42. goods = []
    43. for _ in range(numGoods):
    44. goods.append(float(f.readline()))
    45. cases.append(Case(name, box, goods, boxUsedMin))
    46. return cases
    47. def caseStandardization(cases):
    48. for case in cases:
    49. #确认需要乘多少
    50. n = 1
    51. while case.box * n != int(case.box * n):
    52. n *= 10
    53. for good in case.goods:
    54. while good * n != int(good * n):
    55. n *= 10
    56. #都乘以这个数,化为整数
    57. case.box = int(case.box * n)
    58. for i in range(len(case.goods)):
    59. case.goods[i] = int(case.goods[i] * n)
    60. #next fit,一个个的打开箱子,将物品装进去,如果装不下就开一个新的箱子
    61. def NF(box, goods):
    62. L_goods = [[]]
    63. boxLeft = box
    64. for good in goods:
    65. if good <= boxLeft:
    66. boxLeft -= good
    67. L_goods[-1].append(good)
    68. else:
    69. boxLeft = box - good
    70. L_goods.append([good])
    71. return len(L_goods)
    72. #first fit,检查所有非空箱子,找第一个非空箱子放进去
    73. def FF(box, goods):
    74. L_goods = [[]]
    75. L_boxLeft = [box]
    76. for good in goods:
    77. flag = False
    78. for i in range(len(L_boxLeft)):
    79. if good <= L_boxLeft[i]:
    80. L_boxLeft[i] -= good
    81. L_goods[i].append(good)
    82. flag = True
    83. break
    84. if not flag:
    85. L_boxLeft.append(box - good)
    86. L_goods.append([good])
    87. return len(L_goods)
    88. #first fit Decreasing,先降序排序,再FF
    89. def FFD(box, goods):
    90. goods1 = sorted(goods, reverse=True)
    91. return FF(box, goods1)
    92. #best fit,检查所有非空箱子,找剩余空间最小的放进去
    93. def BF(box, goods):
    94. L_goods = [[]]
    95. L_boxLeft = [box]
    96. for good in goods:
    97. idx, leftMin = None, None
    98. for i in range(len(L_boxLeft)):
    99. if good <= L_boxLeft[i]:
    100. if leftMin is None or leftMin > L_boxLeft[i]:
    101. idx = i
    102. leftMin = L_boxLeft[i]
    103. if idx is not None:
    104. L_boxLeft[idx] -= good
    105. L_goods[idx].append(good)
    106. else:
    107. L_boxLeft.append(box - good)
    108. L_goods.append([good])
    109. return len(L_goods)
    110. #best fit Decreasing,先降序排序,再BF
    111. def BFD(box, goods):
    112. goods1 = sorted(goods, reverse=True)
    113. return BF(box, goods1)
    114. #打散顺序,然后采用FF和BF尝试
    115. def twoOpt(box, goods):
    116. goods1 = sorted(goods, reverse=True)
    117. X = goods1
    118. def f(X, **kwargs):
    119. return FF(kwargs['box'], X)
    120. def f2(X, **kwargs):
    121. return BF(kwargs['box'], X)
    122. def c(X):
    123. return True
    124. def e(x,y):
    125. if x == y:
    126. return True
    127. return False
    128. X1 = two_opt(X, f, c, e, False, 100, box=box)
    129. X2 = two_opt(X, f2, c, e, False, 100, box=box)
    130. return min(FF(box, X1),BF(box, X2))
    131. def runOne(case):
    132. box, goods = case.box, case.goods
    133. #NF
    134. boxUsedNF = NF(box, goods)
    135. #FF
    136. boxUsedFF = FF(box, goods)
    137. boxUsedFFD = FFD(box, goods)
    138. #BF
    139. boxUsedBF = BF(box, goods)
    140. boxUsedBFD = BFD(box, goods)
    141. #twoOpt
    142. boxUsedTwoOpt = twoOpt(box, goods)
    143. print("\nname: ", case.name)
    144. print("opt: ", case.boxUsedMin)
    145. print("boxUsedNF: ", boxUsedNF)
    146. print("boxUsedFF: ", boxUsedFF)
    147. print("boxUsedFFD: ", boxUsedFFD)
    148. print("boxUsedBF: ", boxUsedBF)
    149. print("boxUsedBFD: ", boxUsedBFD)
    150. print("boxUsedTwoOpt: ", boxUsedTwoOpt)
    151. return case.boxUsedMin, boxUsedNF, boxUsedFF, boxUsedFFD, boxUsedBF, boxUsedBFD, boxUsedTwoOpt
    152. def gapCount(L_opt, L):
    153. L_gap = [(L[i]-L_opt[i])/L_opt[i] for i in range(len(L_opt))]
    154. return sum(L_gap)/len(L_gap)
    155. def runAll(cases):
    156. L_opt = []
    157. L_NF = []
    158. L_FF = []
    159. L_FFD = []
    160. L_BF = []
    161. L_BFD = []
    162. L_twoOpt = []
    163. for case in cases:
    164. boxUsedMin, boxUsedNF, boxUsedFF, boxUsedFFD, boxUsedBF, boxUsedBFD, boxUsedTwoOpt = runOne(case)
    165. L_opt.append(boxUsedMin)
    166. L_NF.append(boxUsedNF)
    167. L_FF.append(boxUsedFF)
    168. L_FFD.append(boxUsedFFD)
    169. L_BF.append(boxUsedBF)
    170. L_BFD.append(boxUsedBFD)
    171. L_twoOpt.append(boxUsedTwoOpt)
    172. #统计gap
    173. gapNF = gapCount(L_opt, L_NF)
    174. gapFF = gapCount(L_opt, L_FF)
    175. gapFFD = gapCount(L_opt, L_FFD)
    176. gapBF = gapCount(L_opt, L_BF)
    177. gapBFD = gapCount(L_opt, L_BFD)
    178. gaptwoOpt = gapCount(L_opt, L_twoOpt)
    179. print("\ngapNF: ", gapNF)
    180. print("gapFF: ", gapFF)
    181. print("gapFFD: ", gapFFD)
    182. print("gapBF: ", gapBF)
    183. print("gapBFD: ", gapBFD)
    184. print("gaptwoOpt: ", gaptwoOpt)
    185. if __name__ == '__main__':
    186. cases = dataRead()
    187. caseStandardization(cases)
    188. runAll(cases)

  • 相关阅读:
    【优化算法】最小均值 (LMF) 和最小均方 (LMS) 算法【含Matlab源码 2134期】
    vue3使用router.push()页面跳转后,该页面不刷新问题
    什么是智能视频美颜SDK?
    2023年【电工(中级)】考试题库及电工(中级)模拟考试
    【论文|复现]Vertebra-Focused Landmark Detection For Scoliosis Assessment
    【Linux从0到1】第十七篇:高级IO
    隐写术----LSB隐写
    java 连接SSH工具操作服务器 (构建者模式+Util类) 分享
    深度学习——动物数据集大合集(附下载地址)
    C语言刷题(一)
  • 原文地址:https://blog.csdn.net/chaoyuzhang/article/details/133269602