Skip to content

Latest commit

 

History

History
920 lines (805 loc) · 35.6 KB

温泽瑞 杨猛.md

File metadata and controls

920 lines (805 loc) · 35.6 KB

温泽瑞 杨猛 组

说明

运行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)货物不能浮空。

structure.py

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

Solver.py

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])

drawer.py

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)

main.py

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)