运行main函数即可,Solver中的0~3的参数代表四种策略,详见实验报告,完整项目也可在https://github.com/Team-of-Touching-Fish/Advanced-Algorithm-Homework-Bin-Packing中查看。
structure.py 为数据结构
draw.py 为画出结果
main.py 主程序
Solver.py 主要包含Solver对象,集合了算法
对于整个装箱问题,我们首先进行建模,首先我们用点去确定摆放位置,设摆放点为o这样整体物体所占的空间就是[o.x+length,o.y+length,o.z+height]由于物体的长宽高由pose决定,可以变换,所以对于任意摆放方式,只需要单一的建模成上述形式。摆放之后因此会产生3个新点作为新的摆放点。
(1)非在线情况,对于非在线情况我们采取贪心算法,最初始的贪心是选择体积大的物体先放,因为利用率为物体体积/容器体积。利用率只与物体体积相关。在这种算法中,点的选取我们按照人类直觉来选,人总是像先把大的放在放在底层,之后一层一层的累上去。
(2) 在线和非在线通用,贪心与启发式搜索。在这里在线与非在线的区别只是送入货物的种类不同,非在线我们仍认为我们先选取大的货物,对于在线,我们认为到达的货物是随机的,并且只要新的货物放不下了,就失败。之后所有方法都是如此。
对于评分函数,第一个选择是我们希望能产生更多可以放置的点,所以对每个点进行防止,然后看产生的新点,选取最多的作为放置点。
(3) 对于评分函数,我们可以选取其他方法,在这里,我们选取放入之后,其新产生的点,能够放入更多的其他种类的物体,这样能避免新产生的点都是不可放置的点,确保状态树能走到更深,在在线的情况下放入更多的货物。以下代码是个在线的例子。
Drawer.py提供了3D可视化方法,drawer接受整个容器Container作为输入,根据容器信息,即可绘制出当前状态的3D装箱示意图,引入3D图,能很好的展示每个块摆放的是否合法,也能很直观的看出利用率。绘图主要依靠matplotlib库。
place摆放:
(1) 首先将(货物类型,位置)对放入放置好的物品列表。
(2) 从可用点中删除目前的摆放点
(3) 计算新产生的可摆放点。并验证合法性。
合法性:
通过引申点实现
(1)该类货物需要有足够的数量
(2)该货物必须摆放在箱体内。
(3)货物之间不能相交或包含。
(4)货物不能浮空。
import operator from operator import *
class Point(object): def init(self, x: int, y: int, z: int) -> None: self.x = x self.y = y self.z = z
self.capable = 0
@property
def show(self):
return [self.x, self.y, self.z]
def point_equal(point1:Point, point2:Point): if point1.x == point2.x and point1.y == point2.y and point1.z == point2.z: return True else: return False
class CargoType(object): def init(self, length: int, width: int, height: int, number:int, style:int) -> None: self._shape = [length, width, height] self._number = number self._style = style self._pose = -1 # self.pose = 0
@property
def pose(self):
return self._pose
@pose.setter
def pose(self, new_pose: int):
edges = sorted(self._shape)
# max side down
if new_pose == 0:
self._shape = [edges[2], edges[1], edges[0]]
if new_pose == 1:
self._shape = [edges[1], edges[2], edges[0]]
# mid side down
if new_pose == 2:
self._shape = [edges[2], edges[0], edges[1]]
if new_pose == 3:
self._shape = [edges[0], edges[2], edges[1]]
# small side down
if new_pose == 4:
self._shape = [edges[1], edges[0], edges[2]]
if new_pose == 5:
self._shape = [edges[0], edges[1], edges[2]]
self._pose = new_pose
@property
def shape(self):
return self._shape
@property
def volume(self) -> int:
vol = self._shape[0] * self._shape[1] * self._shape[2]
return vol
@property
def length(self) -> int:
return self._shape[0]
@property
def width(self) -> int:
return self._shape[1]
@property
def height(self) -> int:
return self._shape[2]
@property
def number(self) -> int:
return self._number
@number.setter
def number(self, n):
self._number += n
class CargoPos(object): def init(self, cargo:CargoType, pos:Point) -> None: self.cargo = cargo self.pos = pos
class Cargo(object): def init(self) -> None: self.cargos = [] self._len = 0
@property
def len(self):
return self._len
@len.setter
def len(self, n):
self._len += n
# sorted by volume
def extend(self, cargo):
self.cargos.append(cargo)
sortKey = operator.attrgetter('volume')
self.cargos.sort(key=sortKey)
self.len = 1
class Container(object): def init(self, length: int, width: int, height: int) -> None: self.length = length self.width = width self.height = height self.available_points = [Point(0, 0, 0)] # expected CargoPos self.set_cargo = [] self.used = []
def place(self, cargo: CargoType, pos: Point):
flag_float = True
flag = True
if cargo.number <= 0:
flag = False
return flag
if cargo.length + pos.x > self.length:
flag = False
return flag
if cargo.width + pos.y > self.width:
flag = False
return flag
if cargo.height + pos.z > self.height:
flag = False
return flag
# all vertex should not inside other cargo
vertexs = []
vertex1 = Point(pos.x + cargo.length, pos.y, pos.z)
vertex2 = Point(pos.x, pos.y + cargo.width, pos.z)
vertex3 = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z)
vertex4 = Point(pos.x, pos.y, pos.z + cargo.height)
vertex5 = Point(pos.x + cargo.length, pos.y, pos.z + cargo.height)
vertex6 = Point(pos.x, pos.y + cargo.width, pos.z + cargo.height)
vertex7 = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z + cargo.height)
# set inside point to judge the situation that vertex lay on the edge
far_average_x = pos.x + cargo.length / 2
far_average_y = pos.y + cargo.width - 1
far_average_z = pos.z + cargo.height / 2
inside1 = Point(int(far_average_x), far_average_y, int(far_average_z))
up_average_x = pos.x + cargo.length / 2
up_average_y = pos.y + cargo.width / 2
up_average_z = pos.z + cargo.height - 1
inside2 = Point(int(up_average_x), int(up_average_y), int(up_average_z))
ri_average_x = pos.x + cargo.length - 1
ri_average_y = pos.y + cargo.width / 2
ri_average_z = pos.z + cargo.height / 2
inside3 = Point(int(ri_average_x), int(ri_average_y), int(ri_average_z))
do_average_x = pos.x + cargo.length / 2
do_average_y = pos.y + cargo.width / 2
do_average_z = pos.z + 1
inside4 = Point(int(do_average_x), int(do_average_y), int(do_average_z))
vertexs.append(vertex1)
vertexs.append(vertex2)
vertexs.append(vertex3)
vertexs.append(vertex4)
vertexs.append(vertex5)
vertexs.append(vertex6)
vertexs.append(vertex7)
vertexs.append(inside1)
vertexs.append(inside2)
vertexs.append(inside3)
vertexs.append(inside4)
# prevent floating
op = Point(pos.x, pos.y, pos.z - 1)
x_p = Point(pos.x + cargo.length, pos.y, pos.z - 1)
xf_p = Point(pos.x, pos.y + cargo.width, pos.z - 1)
f_p = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z - 1)
floatp = [op, x_p, xf_p, f_p]
for eachcargo in self.set_cargo:
if not flag:
return False
x_min = eachcargo.pos.x
x_max = eachcargo.pos.x + eachcargo.cargo.length
y_min = eachcargo.pos.y
y_max = eachcargo.pos.y + eachcargo.cargo.width
z_min = eachcargo.pos.z
z_max = eachcargo.pos.z + eachcargo.cargo.height
for vertex in vertexs:
if x_min < vertex.x < x_max and y_min < vertex.y < y_max and z_min < vertex.z < z_max:
flag = False
for downp in floatp:
if downp.z <= 0:
flag_float = False
if x_min < downp.x < x_max and y_min < downp.y < y_max and z_min < downp.z < z_max:
flag_float = False
if self.set_cargo != [] and flag_float:
flag = False
if flag:
# Cargo
newCargo = CargoPos(cargo, pos)
self.set_cargo.append(newCargo)
# Point
self.used.append(pos)
self.available_points.remove(pos)
newPointX = Point(pos.x + cargo.length, pos.y, pos.z)
newPointY = Point(pos.x, pos.y + cargo.width, pos.z)
newPointZ = Point(pos.x, pos.y, pos.z + cargo.height)
flagX = False
flagY = False
flagZ = False
for point in self.used:
if point_equal(newPointX, point):
flagX = True
if point_equal(newPointY, point):
flagY = True
if point_equal(newPointZ, point):
flagZ = True
if not flagX:
self.available_points.append(newPointX)
self.used.append(newPointX)
if not flagY:
self.available_points.append(newPointY)
self.used.append(newPointY)
if not flagZ:
self.available_points.append(newPointZ)
self.used.append(newPointZ)
# debug
# print(newPointX.show)
# print(newPointY.show)
# print(newPointZ.show)
# reduce Cargo
cargo.number = -1
return flag
def place_test(self, cargo: CargoType, pos: Point):
'''
This function is used to say whether this point can be placed in this point
:param cargo:
:param pos:
:return:
'''
flag_float = True
flag = True
if cargo.number <= 0:
flag = False
return flag, 0
if cargo.length + pos.x > self.length:
flag = False
return flag, 0
if cargo.width + pos.y > self.width:
flag = False
return flag, 0
if cargo.height + pos.z > self.height:
flag = False
return flag, 0
vertexs = []
vertex1 = Point(pos.x + cargo.length, pos.y, pos.z)
vertex2 = Point(pos.x, pos.y + cargo.width, pos.z)
vertex3 = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z)
vertex4 = Point(pos.x, pos.y, pos.z + cargo.height)
vertex5 = Point(pos.x + cargo.length, pos.y, pos.z + cargo.height)
vertex6 = Point(pos.x, pos.y + cargo.width, pos.z + cargo.height)
vertex7 = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z + cargo.height)
# set inside point to judge the situation that vertex lay on the edge
far_average_x = pos.x + cargo.length / 2
far_average_y = pos.y + cargo.width - 1
far_average_z = pos.z + cargo.height / 2
inside1 = Point(int(far_average_x), far_average_y, int(far_average_z))
up_average_x = pos.x + cargo.length / 2
up_average_y = pos.y + cargo.width / 2
up_average_z = pos.z + cargo.height - 1
inside2 = Point(int(up_average_x), int(up_average_y), int(up_average_z))
ri_average_x = pos.x + cargo.length - 1
ri_average_y = pos.y + cargo.width / 2
ri_average_z = pos.z + cargo.height / 2
inside3 = Point(int(ri_average_x), int(ri_average_y), int(ri_average_z))
do_average_x = pos.x + cargo.length / 2
do_average_y = pos.y + cargo.width / 2
do_average_z = pos.z + 1
inside4 = Point(int(do_average_x), int(do_average_y), int(do_average_z))
vertexs.append(vertex1)
vertexs.append(vertex2)
vertexs.append(vertex3)
vertexs.append(vertex4)
vertexs.append(vertex5)
vertexs.append(vertex6)
vertexs.append(vertex7)
vertexs.append(inside1)
vertexs.append(inside2)
vertexs.append(inside3)
vertexs.append(inside4)
# prevent floating
op = Point(pos.x, pos.y, pos.z - 1)
x_p = Point(pos.x + cargo.length, pos.y, pos.z - 1)
xf_p = Point(pos.x, pos.y + cargo.width, pos.z - 1)
f_p = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z - 1)
floatp = [op, x_p, xf_p, f_p]
for eachcargo in self.set_cargo:
if not flag:
return False, 0
x_min = eachcargo.pos.x
x_max = eachcargo.pos.x + eachcargo.cargo.length
y_min = eachcargo.pos.y
y_max = eachcargo.pos.y + eachcargo.cargo.width
z_min = eachcargo.pos.z
z_max = eachcargo.pos.z + eachcargo.cargo.height
for vertex in vertexs:
if x_min < vertex.x < x_max and y_min < vertex.y < y_max and z_min < vertex.z < z_max:
flag = False
for downp in floatp:
if downp.z <= 0:
flag_float = False
if x_min < downp.x < x_max and y_min < downp.y < y_max and z_min < downp.z < z_max:
flag_float = False
if self.set_cargo != [] and flag_float:
flag = False
newPointX = Point(pos.x + cargo.length, pos.y, pos.z)
newPointY = Point(pos.x, pos.y + cargo.width, pos.z)
newPointZ = Point(pos.x, pos.y, pos.z + cargo.height)
flagX = False
flagY = False
flagZ = False
for point in self.used:
if point_equal(newPointX, point):
flagX = True
if point_equal(newPointY, point):
flagY = True
if point_equal(newPointZ, point):
flagZ = True
newPointCount = 0
pointlist = []
if not flagX:
pointlist.append(newPointX)
newPointCount += 1
if not flagY:
pointlist.append(newPointY)
newPointCount += 1
if not flagZ:
pointlist.append(newPointZ)
newPointCount += 1
return flag, newPointCount
def place_test2(self, cargo: CargoType, pos: Point):
'''
This function is used to say whether this point can be placed in this point
:param cargo:
:param pos:
:return:
'''
flag_float = True
flag = True
if cargo.number <= 0:
flag = False
return flag, 0
if cargo.length + pos.x > self.length:
flag = False
return flag, 0
if cargo.width + pos.y > self.width:
flag = False
return flag, 0
if cargo.height + pos.z > self.height:
flag = False
return flag, 0
vertexs = []
vertex1 = Point(pos.x + cargo.length, pos.y, pos.z)
vertex2 = Point(pos.x, pos.y + cargo.width, pos.z)
vertex3 = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z)
vertex4 = Point(pos.x, pos.y, pos.z + cargo.height)
vertex5 = Point(pos.x + cargo.length, pos.y, pos.z + cargo.height)
vertex6 = Point(pos.x, pos.y + cargo.width, pos.z + cargo.height)
vertex7 = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z + cargo.height)
# set inside point to judge the situation that vertex lay on the edge
far_average_x = pos.x + cargo.length / 2
far_average_y = pos.y + cargo.width - 1
far_average_z = pos.z + cargo.height / 2
inside1 = Point(int(far_average_x), far_average_y, int(far_average_z))
up_average_x = pos.x + cargo.length / 2
up_average_y = pos.y + cargo.width / 2
up_average_z = pos.z + cargo.height - 1
inside2 = Point(int(up_average_x), int(up_average_y), int(up_average_z))
ri_average_x = pos.x + cargo.length - 1
ri_average_y = pos.y + cargo.width / 2
ri_average_z = pos.z + cargo.height / 2
inside3 = Point(int(ri_average_x), int(ri_average_y), int(ri_average_z))
do_average_x = pos.x + cargo.length / 2
do_average_y = pos.y + cargo.width / 2
do_average_z = pos.z + 1
inside4 = Point(int(do_average_x), int(do_average_y), int(do_average_z))
vertexs.append(vertex1)
vertexs.append(vertex2)
vertexs.append(vertex3)
vertexs.append(vertex4)
vertexs.append(vertex5)
vertexs.append(vertex6)
vertexs.append(vertex7)
vertexs.append(inside1)
vertexs.append(inside2)
vertexs.append(inside3)
vertexs.append(inside4)
# prevent floating
op = Point(pos.x, pos.y, pos.z - 1)
x_p = Point(pos.x + cargo.length, pos.y, pos.z - 1)
xf_p = Point(pos.x, pos.y + cargo.width, pos.z - 1)
f_p = Point(pos.x + cargo.length, pos.y + cargo.width, pos.z - 1)
floatp = [op, x_p, xf_p, f_p]
for eachcargo in self.set_cargo:
if not flag:
return False, 0
x_min = eachcargo.pos.x
x_max = eachcargo.pos.x + eachcargo.cargo.length
y_min = eachcargo.pos.y
y_max = eachcargo.pos.y + eachcargo.cargo.width
z_min = eachcargo.pos.z
z_max = eachcargo.pos.z + eachcargo.cargo.height
for vertex in vertexs:
if x_min < vertex.x < x_max and y_min < vertex.y < y_max and z_min < vertex.z < z_max:
flag = False
for downp in floatp:
if downp.z <= 0:
flag_float = False
if x_min < downp.x < x_max and y_min < downp.y < y_max and z_min < downp.z < z_max:
flag_float = False
if self.set_cargo != [] and flag_float:
flag = False
newPointX = Point(pos.x + cargo.length, pos.y, pos.z)
newPointY = Point(pos.x, pos.y + cargo.width, pos.z)
newPointZ = Point(pos.x, pos.y, pos.z + cargo.height)
flagX = False
flagY = False
flagZ = False
for point in self.used:
if point_equal(newPointX, point):
flagX = True
if point_equal(newPointY, point):
flagY = True
if point_equal(newPointZ, point):
flagZ = True
newPointCount = 0
pointlist = []
if not flagX:
pointlist.append(newPointX)
if not flagY:
pointlist.append(newPointY)
if not flagZ:
pointlist.append(newPointZ)
return flag, pointlist
def status_save(self):
file = open("test.csv", 'w', encoding='utf-8')
file.write(f"index,x,y,z,length,width,height\n")
i = 1
for carogPos in self.set_cargo:
file.write(f"{i},{carogPos.pos.x},{carogPos.pos.y},{carogPos.pos.z},")
file.write(f"{carogPos.cargo.length},{carogPos.cargo.width},{carogPos.cargo.height}\n")
i += 1
file.write(f"container,,,,{self}\n")
file.close()
@property
def volume(self) -> int:
vol = self.length * self.width * self.height
return vol
def useage(self):
sumV = 0
for cargoSet in self.set_cargo:
sumV += cargoSet.cargo.volume
print(sumV)
return sumV / self.volume
import random
from structure import * import operator import drawer from drawer import *
class Solver(object): def init(self, cargo: Cargo, container: Container, strategy) -> None: self.cargos = cargo self.container = container self.strategy = strategy
def solve(self):
# strategy choose
if self.strategy == 0:
cargoIndex = -1
count = 0
while cargoIndex >= -self.cargos.len:
# choose point
self.container.available_points.sort(key=lambda x: x.x)
self.container.available_points.sort(key=lambda x: x.y)
self.container.available_points.sort(key=lambda x: x.z)
# for point in self.container.available_points:
# print(point.show)
# print('\n')
# sortKey = operator.attrgetter('x')
# self.container.available_points.sort(key=sortKey, reverse=True)
m = len(self.container.available_points)
for i in range(0, m):
flag = self.container.place(self.cargos.cargos[cargoIndex], self.container.available_points[i])
if flag:
# self.container.available_points.sort(key=lambda x: x.x)
# self.container.available_points.sort(key=lambda x: x.y)
# self.container.available_points.sort(key=lambda x: x.z)
# for p in self.container.available_points:
# print(p.show)
# print('/n')
cargoIndex += 1
break
cargoIndex -= 1
# cargoIndex = -1
# count = 0
# while cargoIndex >= -self.cargos.len:
# # choose point
# self.container.available_points.sort(key=lambda x: x.x)
# self.container.available_points.sort(key=lambda x: x.y)
# self.container.available_points.sort(key=lambda x: x.z)
#
# # for point in self.container.available_points:
# # print(point.show)
# # print('\n')
# # sortKey = operator.attrgetter('x')
# # self.container.available_points.sort(key=sortKey, reverse=True)
# m = len(self.container.available_points)
# for i in range(0, m):
# flag = self.container.place(self.cargos.cargos[cargoIndex], self.container.available_points[i])
# if flag:
# # self.container.available_points.sort(key=lambda x: x.x)
# # self.container.available_points.sort(key=lambda x: x.y)
# # self.container.available_points.sort(key=lambda x: x.z)
# # for p in self.container.available_points:
# # print(p.show)
# # print('/n')
# cargoIndex += 1
# break
#
# cargoIndex -= 1
if self.strategy == 1:
cargoIndex = -1
count = 0
while cargoIndex >= -self.cargos.len:
print(cargoIndex)
# choose point
self.container.available_points.sort(key=lambda x: x.x)
self.container.available_points.sort(key=lambda x: x.y)
self.container.available_points.sort(key=lambda x: x.z)
# for point in self.container.available_points:
# print(point.show)
# print('\n')
# sortKey = operator.attrgetter('x')
# self.container.available_points.sort(key=sortKey, reverse=True)
m = len(self.container.available_points)
morePointMax = 0
indexSaver = -1
pointindex = -1
for i in range(0, m):
success, pointIncrease = self.container.place_test(self.cargos.cargos[cargoIndex],
self.container.available_points[i])
if success and pointIncrease > morePointMax:
morePointMax = pointIncrease
indexSaver = cargoIndex
pointindex = i
if indexSaver != -1 and pointindex != -1:
flag = self.container.place(self.cargos.cargos[indexSaver],
self.container.available_points[pointindex])
if flag:
self.container.available_points.sort(key=lambda x: x.x)
self.container.available_points.sort(key=lambda x: x.y)
self.container.available_points.sort(key=lambda x: x.z)
cargoIndex += 1
cargoIndex -= 1
if self.strategy == 2:
cargoIndex = -1
count = 0
chance = True
while cargoIndex >= -self.cargos.len:
print(cargoIndex)
# choose point
self.container.available_points.sort(key=lambda x: x.x)
self.container.available_points.sort(key=lambda x: x.y)
self.container.available_points.sort(key=lambda x: x.z)
# for point in self.container.available_points:
# print(point.show)
# print('\n')
# sortKey = operator.attrgetter('x')
# self.container.available_points.sort(key=sortKey, reverse=True)
m = len(self.container.available_points)
maxsocre = 0
carndex = 0
posindex = -1
allflag = True
# 为每个点计算分数
for i in range(0, m):
addPoint = []
socre = 0
success, addPoint = self.container.place_test2(self.cargos.cargos[cargoIndex],
self.container.available_points[i])
if success:
allflag = False
if addPoint == 0:
continue
if success:
for j in range(len(addPoint)):
for k in range(self.cargos.len):
success2, morePoint = self.container.place_test(self.cargos.cargos[k],
addPoint[j])
if success2:
socre += 1
if maxsocre < socre:
maxsocre = socre
carndex = cargoIndex
posindex = i
# print(str(carndex) + ' cargoindex')
# print(str(posindex) + ' psoindex')
if carndex != 0 and posindex != -1:
print('a')
flag = self.container.place(self.cargos.cargos[carndex],
self.container.available_points[posindex])
if flag:
print('place')
if allflag or maxsocre == 0:
cargoIndex -= 1
if self.strategy == 3:
# 在线
loopflag = True
chance = 3
while loopflag:
cargoIndex = random.randint(0, self.cargos.len - 1)
while self.cargos.cargos[cargoIndex].number <= 0:
cargoIndex = random.randint(0, self.cargos.len - 1)
# sort point
self.container.available_points.sort(key=lambda x: x.x)
self.container.available_points.sort(key=lambda x: x.y)
self.container.available_points.sort(key=lambda x: x.z)
m = len(self.container.available_points)
maxsocre = 0
carndex = 0
posindex = -1
poseindex = -1
allflag = True
# 为每个点计算分数
for i in range(0, m):
for j in range(6):
self.cargos.cargos[cargoIndex].pose = j
success, addPoint = self.container.place_test2(self.cargos.cargos[cargoIndex],
self.container.available_points[i])
socre = 0
if success:
allflag = False
for jj in range(len(addPoint)):
for kk in range(self.cargos.len):
for kkk in range(6):
or_pose = self.cargos.cargos[kk].pose
if or_pose == -1:
or_pose = 0
self.cargos.cargos[kk].pose = kkk
success2, morePoint = self.container.place_test(self.cargos.cargos[kk],
addPoint[jj])
self.cargos.cargos[kk].pose = or_pose
if success2:
socre += 1
# if j == 0 and socre != 0:
# socre += 20
self.cargos.cargos[cargoIndex].pose = j
if maxsocre < socre:
maxsocre = socre
carndex = cargoIndex
posindex = i
poseindex = j
if maxsocre == 0:
self.cargos.cargos[carndex].pose = poseindex
flag = self.container.place(self.cargos.cargos[carndex],
self.container.available_points[posindex])
break
if allflag:
if chance >= 0:
chance -= 1
else:
loopflag = False
else:
print(poseindex)
self.cargos.cargos[carndex].pose = poseindex
print(self.cargos.cargos[carndex].pose)
print(self.cargos.cargos[carndex].shape)
flag = self.container.place(self.cargos.cargos[carndex],
self.container.available_points[posindex])
from matplotlib import pyplot as plt from matplotlib.figure import Figure import numpy as np from structure import *
plt.rcParams['axes.unicode_minus'] = False plt.rcParams['font.sans-serif'] = ['SimHei'] fig:Figure = plt.figure() ax = fig.add_subplot(1, 1, 1, projection='3d') ax.view_init(elev=20, azim=40) plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
def draw_reslut(setted_container:Container): plt.gca().set_box_aspect(( setted_container.length, setted_container.width, setted_container.height )) _draw_container(setted_container) for cargowp in setted_container.set_cargo: _draw_cargo(cargowp) plt.show()
def _draw_container(container:Container): _plot_linear_cube( 0,0,0, container.length, container.width, container.height )
def _draw_cargo(cargo:CargoPos): _plot_opaque_cube( cargo.pos.x, cargo.pos.y, cargo.pos.z, cargo.cargo.length, cargo.cargo.width, cargo.cargo.height )
def _plot_opaque_cube(x=10, y=20, z=30, dx=40, dy=50, dz=60): xx = np.linspace(x, x+dx, 2) yy = np.linspace(y, y+dy, 2) zz = np.linspace(z, z+dz, 2) xx2, yy2 = np.meshgrid(xx, yy) ax.plot_surface(xx2, yy2, np.full_like(xx2, z)) ax.plot_surface(xx2, yy2, np.full_like(xx2, z+dz)) yy2, zz2 = np.meshgrid(yy, zz) ax.plot_surface(np.full_like(yy2, x), yy2, zz2) ax.plot_surface(np.full_like(yy2, x+dx), yy2, zz2) xx2, zz2= np.meshgrid(xx, zz) ax.plot_surface(xx2, np.full_like(yy2, y), zz2) ax.plot_surface(xx2, np.full_like(yy2, y+dy), zz2)
def _plot_linear_cube(x, y, z, dx, dy, dz, color='red'): # ax = Axes3D(fig) xx = [x, x, x+dx, x+dx, x] yy = [y, y+dy, y+dy, y, y] kwargs = {'alpha': 1, 'color': color} ax.plot3D(xx, yy, [z]*5, **kwargs) ax.plot3D(xx, yy, [z+dz]*5, **kwargs) ax.plot3D([x, x], [y, y], [z, z+dz], **kwargs) ax.plot3D([x, x], [y+dy, y+dy], [z, z+dz], **kwargs) ax.plot3D([x+dx, x+dx], [y+dy, y+dy], [z, z+dz], **kwargs) ax.plot3D([x+dx, x+dx], [y, y], [z, z+dz], **kwargs)
import drawer from drawer import * from structure import * from Solver import Solver import time
if name == "main": # c1 = CargoType(49, 25, 21, 13, 0) # c2 = CargoType(60, 51, 41, 9, 1) # c3 = CargoType(103, 76, 64, 8, 2) # c4 = CargoType(95, 70, 62, 6, 3) # c5 = CargoType(111, 49, 26, 10, 4) # c6 = CargoType(74, 42, 40, 4, 5) # c7 = CargoType(85, 84, 72, 10, 6) # c8 = CargoType(48, 36, 31, 10, 7) # c9 = CargoType(86, 76, 38, 12, 8) # c10 = CargoType(71, 48, 47, 14, 9) # c11 = CargoType(90, 43, 33, 9, 10) # c12 = CargoType(98, 52, 44, 9, 11) # c13 = CargoType(73, 37, 23, 10, 12) # c14 = CargoType(61, 48, 39, 14, 13) # c15 = CargoType(75, 75, 63, 11, 14) # # # cargo = Cargo() # cargo.extend(c1) # cargo.extend(c2) # cargo.extend(c3) # cargo.extend(c4) # cargo.extend(c5) # cargo.extend(c6) # cargo.extend(c7) # cargo.extend(c8) # cargo.extend(c9) # cargo.extend(c10) # cargo.extend(c11) # cargo.extend(c12) # cargo.extend(c13) # cargo.extend(c14) # cargo.extend(c15) cargo = Cargo() for i in range(24): c = CargoType(108, 76, 30, 1, 1) cargo.extend(c) for i in range(7): c = CargoType(110,43, 25, 1, 1) cargo.extend(c) for i in range(22): c = CargoType(92, 81, 55, 1, 1) cargo.extend(c) for i in range(13): c = CargoType(81, 33, 28, 1, 1) cargo.extend(c) for i in range(15): c = CargoType(120, 99, 73, 1, 1) cargo.extend(c) container = Container(587, 233, 220) case = Solver(cargo, container, 0) # case = Solver(cargo, container, 0) # case = Solver(cargo, container, 1) time_start = time.time() case.solve() time_end = time.time() # print(container.volume) print(container.useage()) time_c = time_end - time_start # 运行所花时间 print('time cost', time_c, 's') container.status_save() drawer.draw_reslut(container)