The 2D Bin Packing Problem involves efficiently packing a set of rectangular items into a limited number of fixed-size bins while optimizing certain criteria, such as maximizing space utilization or minimizing the number of bins used.
In this project, We propose a Hybrid Evolutionary Algorithm and a Tabu Search Algorithm for solving the 2D bin packing problem in which the items can be rotated and must follow the guillotine cut property.
First, ensure all the required packages are installed by executing this command: pip install -r requirements.txt
To run the program, go to main.py
and unselect the parts of the code based on your needs:
- Compile Code: Select this to compile all necessary functions using Numba.
- You can set the
advanced
flag to True to get more insights into the compilation time of each function.
- You can set the
- Generate ALl Solutions: Select this to generate the solution of every file in the input folder.
- Generate Single Solutions: Select this to generate the solution of a single file.
- Visualize Solutions: Select this to visualize the solution of a specific packing scenario.
At the top of main.py
you can tweak the parameters.
Parameters for Genetic Algorithm
-
POPULATION_SIZE
: Determines the number of individuals (solutions) in each generation of the genetic algorithm. -
NB_GENERATIONS
: Specifies the number of generations (iterations) that the genetic algorithm will run. -
CROSSOVER_RATE
: Represents the proportion of the new generation that is created through crossover. -
MUTATION_RATE
: Indicates the likelihood that a mutation will occur in an individual. -
DELTA
: Controls the diversity in the crossover. Lower values encourage higher diversity among parent selection.- Must be
$\ge 1$
- Must be
Parameters for the Unified Tabu Search
-
ITERATION_NUMBER
: Specifies the maximum number of iterations (or moves) that the Tabu Search Algorithm will execute. -
TABU_LIST_SIZE
: Sets the size of the tabu list.
Shared Genetic and Tabu Search Parameters
-
KAPPA
: Controls the degree to which the initial population of solutions favors items based on their area ranking. Lower values encourage higher diversity among solutions.- Must be
$\ge 1$
- Must be
General Options
-
GUILLOTINE
: Boolean flag indicating whether guillotine cuts are included. -
ROTATION
: Boolean flag indicating whether rotating an items is allowed. -
SELECTED_METAHEURISTIC
: Specifies the metaheuristic selected for optimization.
The 2D Bin Packing Problem can be categorized based on whether the items can be rotated and whether the items must adhere to the guillotine cut property. Each version addresses different constraints:
-
Rotation (0 or R):
- When rotation is not allowed (0), items must be placed in their original orientation.
- When rotation is allowed (R), items can be rotated to better fit within the bin, which can lead to higher space utilization.
-
Guillotine Cut Property (F or G):
- Guillotine free (F) allows for more flexibility in item placement as cuts don't need to be considered.
- Guillotine cut property (G) requires that items be placed in a manner that allows for them to be separated from the bin using a series of edge-to-edge cuts. This mimics real-world cutting processes and often adds complexity to the problem.
By considering these variations, we can tackle different scenarios of the 2D Bin Packing Problem:
- 2DBP | 0 | F: Simplest form where items are placed in their original orientation without the need for guillotine cuts.
- 2DBP | 0 | G: Items must be placed in their original orientation and follow the guillotine cut property.
- 2DBP | R | F: Items can be rotated, offering flexibility, without needing to follow the guillotine cut property.
- 2DBP | R | G: Most complex form where items can be rotated and must follow the guillotine cut property.
Traditional methods represent solutions as static configurations of bins with assigned items. However, it becomes computationally expensive when we to compute all the neighbors, which are the possible moves from one solution to another. Each move involves checking all possible spaces where each item can potentially fit into another bin while ensuring that these moves adhere to the guillotine rule.
To address this problem, we redefined how solutions are represented. Instead of fixed assignments of items to bins, solutions are now represented as ordered sequences or permutations of items. This permutation-based approach serves as input to a heuristic algorithm responsible for dynamically constructing the bin configuration.
This transformation simplifies the computation of neighbors to essentially rearranging the order of items in the sequence. Each rearrangement represents a potential new solution configuration. Compared to traditional methods where each move would require checking multiple bins and ensuring guillotine rules are followed, the permutation-based approach focuses solely on rearranging the item order. This significantly reduces computational complexity and speeds up the process of exploring alternative solutions.
We use the Improved Lowest Gap Fill (LGFI) Heuristic to pack items into bins. This algorithm is designed to minimize wasted areas. Here’s how it works:
Input: LGFI takes an ordered sequence of items as input. This sequence determines the order in which items will be considered for placement.
-
Identifying the Current Position: The bottom-leftmost position in the bin where an item may be placed is identified as the
current position
. -
Determining the Current Gap:
- Horizontal Gap: This is the distance between the current position and either the right border of the bin or the left edge of the first item encountered between the current position and the bin's right border.
- Vertical Gap: This is the distance between the current position and the upper border of the bin.
The current gap is defined as the smaller of the horizontal and vertical gaps. It represents the immediate space available for placing the next item.
-
Item Placement Strategy:
- The algorithm attempts to place the first item from the list that can completely fill the current gap.
- If no perfect fit exists, the first item that fits without overlapping others is placed.
- If neither condition is met, a wastage area is declared.
-
Opening New Bins: If no suitable current position is found for placing an item, and there are still unpacked items left, a new bin is opened to continue the packing process.
To manage guillotine cuts, our approach involves representing a bin as a collection of placed items
with specific coordinates and a list of free spaces
that divide the utilized area of the bin into distinct free rectangles. The borders of these free rectangles ensure that items cannot violate the guillotine rule.
When an item is placed within a free rectangle, the algorithm creates two new free rectangles by splitting the original free rectangle
around the newly placed item. This splitting process can occur either horizontally or vertically, starting from the top-right corner of the placed item.
But then, How is the splitting direction decided ?
We Implemented 3 differents methods
to determine the direction of the cut:
Let
Let
-
Shorter Leftover : cut is Horizontal if
$Wr−Wi < Hr−Hi$ , and Vertical otherwise. -
Min Area : cut is Horizontal if
$Hi\times(Wr−Wi ) < Wi\times(Hr−Hi )$ , and Hertical otherwise. -
Custom Hybrid Fit :
Let$N$ denote the number of newly created free rectangle where at least one unpacked item can fit ($0$ ,$1$ or$2$ ).
Let$F$ denote the maximum fill percentage achieved by an unpacked item when placed into a free rectangle.- cut is Horizontal if
$N_{horizontal} < N_{vertical}$ - cut is Vertical if
$N_{vertical} < N_{horizontal}$ - If they are equal :
- cut is Horizontal if
$F_{horizontal} > F_{vertical}$ - cut is Vertical if
$F_{horizontal} \le F_{vertical}$
- cut is Horizontal if
- cut is Horizontal if
We created a custom function to try to converge even faster than the existing methods1. It was evident that in certain cases, the placement could be optimized. The Custom Hybrid Fit method was developed to maximize the use of available space
by considering not only the dimensions of the newly created spaces but also their ability to accommodate remaining items
, ensuring a more optimal utilization of the bin's total volume.
The fitness function is formulated to address the dual objectives of reducing the number of bins and maximizing the space utilization within the last bin. The fitness
Let
Both the Hybrid Evolutionary Algorithm and the Tabu Search Algorithm are designed to minimize this fitness function.
We implemented the Hybrid Genetic Algorithm proposed in the paper "A Hybrid Genetic Algorithm for the 2D Guillotine Cutting Problem"2 (original paper), to which we added new features to handle rotation and the guillotine cut property, as well as mutations.
We implemented two different types of mutations:
- Rotation: This mutation rotates one element randomly within the sequence.
- Permutation: This mutation swaps two elements in the sequence.
We also implemented a classic Tabu Search Algorithm with 3 kinds of neighbourhood :
-
Rotations : rotate 1 item (
$n$ neighbours) -
Permutations : swap 2 side-by-side items (
$n-1$ neighbours) -
Insertions : insert 1 item to the first position and shift the others to the right to fill the gap (
$n-1$ neighbours)
Numba is a Just-In-Time (JIT) compiler for Python that translates a subset of Python and NumPy code into fast machine code. This significantly improves the performance of numerical computations. It allows developers to write code in Python while achieving performance close to that of lower-level languages. Numba also allows for easy parallelization of for
loops.
To further enhance performance, we use Numba's caching technique, which avoids recompilation at every execution by storing the compiled machine code. This means that the first time a function runs, Numba compiles and caches it, and subsequent executions retrieve the compiled code from the cache, reducing overhead and improving runtime efficiency.
Exemple:
We timed the execution of the Genetic Algorithm for binpacking2d-04.bp2d
(50 items) for (only) 100 iterations, both with and without Numba optimizations (CPU : i7-7700K):
- Without Numba :
123.6 seconds
- With Numba :
0.3 seconds
😆 (compilation +for
loops parallelization)
Considering a set of items and a particular size of bin, if with assume that it is possible to perfectly fit all the items into bins, the minimal number of bin will be :
For our dataset, here are the results and the theoretical minimal number of bins according to the formula :
File Name | Theoretical Result | Actual Result |
---|---|---|
binpacking2d-01.bp2d | 3 | 4 |
binpacking2d-02.bp2d | 5 | 6 |
binpacking2d-03.bp2d | 7 | 8 |
binpacking2d-04.bp2d | 12 | 13 |
binpacking2d-05.bp2d | 3 | 3 |
binpacking2d-06.bp2d | 5 | 6 |
binpacking2d-07.bp2d | 9 | 10 |
binpacking2d-08.bp2d | 12 | 13 |
binpacking2d-09.bp2d | 3 | 3 |
binpacking2d-10.bp2d | 6 | 7 |
binpacking2d-11.bp2d | 7 | 8 |
binpacking2d-12.bp2d | 13 | 15 |
binpacking2d-13.bp2d | 2 | 2 |
Note: The theoretical minimal number of bins serves as a lower bound for reference. Actual results may exceed this bound due to guillotine constraints or the specific shapes of the items being packed.
Here are examples of solutions generated by the genetic algorithm for the 2DBP | R | G scenario (items can be rotated and must follow the guillotine cut property):
Example Solution 8: Items are packed using rotations and guillotine cuts to maximize space utilization.
Example Solution 13: Another scenario showing efficient packing with rotations and guillotine cuts.
These examples illustrate how our hybrid genetic algorithm effectively optimizes space utilization and adheres to the guillotine cut property.
In order to compare the Hybrid Genetic Algorithm and the Tabu Search Algorithm we decided to run them on entire dataset 100 times and compute the average execution time. For these tests we used the following parameter :
Genetic Algorithm Parameters
POPULATION_SIZE
: 20NB_GENERATIONS
: 500CROSSOVER_RATE
: 0.7MUTATION_RATE
: 0.3DELTA
: 2
Tabu Search Parameters
ITERATION_NUMBER
: 500TABU_LIST_SIZE
: 5
Shared Parameters
KAPPA
: 2
File Name | LGFI | LGFI (shorter leftover) | LGFI (minimum area) | LGFI (hybrid cut) | Hybrid Genetic | Tabu Search | ||
---|---|---|---|---|---|---|---|---|
Execution time (s) | Number of bin | Number of bin | Number of bin | Number of bin | Execution time (s) | Number of bin | Execution time (s) | |
binpacking2d-01.bp2d | 0.0001 | 4 | 4 | 4 | 4 | 0.25 | 4 | 1.48 |
binpacking2d-02.bp2d | 0.0001 | 6 | 6 | 6 | 6 | 0.52 | 6 | 1.36 |
binpacking2d-03.bp2d | 0.0001 | 9 | 9 | 8 | 8 | 1.08 | 8 | 3.17 |
binpacking2d-04.bp2d | 0.0001 | 14 | 15 | 14 | 13 | 2.52 | 13 | 11.78 |
binpacking2d-05.bp2d | 0.0001 | 3 | 4 | 4 | 3 | 0.29 | 3 | 0.33 |
binpacking2d-06.bp2d | 0.0001 | 7 | 7 | 7 | 6 | 0.56 | 6 | 1.15 |
binpacking2d-07.bp2d | 0.0001 | 11 | 12 | 11 | 10 | 1.01 | 10 | 4.03 |
binpacking2d-08.bp2d | 0.0001 | 14 | 13 | 13 | 13 | 2.2 | 13 | 14.12 |
binpacking2d-09.bp2d | 0.0001 | 3 | 3 | 3 | 3 | 0.23 | 3 | 0.29 |
binpacking2d-10.bp2d | 0.0001 | 8 | 8 | 7 | 7 | 0.55 | 7 | 1.15 |
binpacking2d-11.bp2d | 0.0001 | 8 | 9 | 9 | 8 | 1.13 | 8 | 3.66 |
binpacking2d-12.bp2d | 0.0001 | 17 | 17 | 15 | 15 | 2.42 | 15 | 13.87 |
binpacking2d-13.bp2d | 0.0001 | 2 | 3 | 2 | 2 | 0.90 | 2 | 3.00 |
Solution Quality : Both algorithms generally converge to solutions with the same number of bins.
Execution Time : The Tabu Search algorithm is slower than the Genetic algorithm. This can be attributed to the computational overhead of evaluating the fitness of all neighbors using LGFI. Specifically, Tabu Search evaluates fitness for 3 times the number of items, whereas the Genetic algorithm evaluates fitness only for each element in its population (20 times in this case).
Hybrid Cut Improvment : We can see that the hybrid cut method generally performs better than the shorter leftover and minimum area cutting methods.
LGFI Efficiency : Even without optimization, LGFI performs well, though it does not always yield the best solution. This can impact our evaluation of metaheuristics because it provides a very small margin for further optimization.
We attempted to tweak the different parameters to assess their impact on algorithm efficiency. However, both algorithms converged quickly to a very good solution, resulting in only slight differences when parameters were changed. The results were inconsistent across different cases in the dataset and between executions.
Therefore, we decided not to conduct a detailed study of parameter impact, as our fitness function and the current dataset do not allow for a proper comparison of different setups. This can be explained by our representation based on LGFI, which leads to a small margin for optimization and quick convergence of the algorithms.
Footnotes
-
Enrico Pietrobuoni, "Two-Dimensional Bin Packing Problem with Guillotine Restrictions," 2015, https://amsdottorato.unibo.it/6810/1/PhD_Pietrobuoni.pdf. ↩
-
Christian Blum, Verena Schmid, "Solving the 2D Bin Packing Problem by Means of a Hybrid Evolutionary Algorithm," https://doi.org/10.1016/j.procs.2013.05.255. ↩