{"id":16685350,"url":"https://github.com/wadaboa/3d-bpp","last_synced_at":"2025-07-26T02:34:02.231Z","repository":{"id":47085014,"uuid":"356802020","full_name":"Wadaboa/3d-bpp","owner":"Wadaboa","description":"3D bin packing solutions with layers and superitems, for Artificial Intelligence in Industry class at UNIBO","archived":false,"fork":false,"pushed_at":"2023-04-18T21:49:00.000Z","size":86260,"stargazers_count":119,"open_issues_count":8,"forks_count":27,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-03T23:32:42.343Z","etag":null,"topics":["3d-bin-packing","3d-bpp","bin-packing","column-generation","cp","layers","maxrects","mip","or-tools","superitems"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Wadaboa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-11T07:46:48.000Z","updated_at":"2025-03-19T08:14:11.000Z","dependencies_parsed_at":"2024-10-28T11:39:53.352Z","dependency_job_id":null,"html_url":"https://github.com/Wadaboa/3d-bpp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Wadaboa/3d-bpp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wadaboa%2F3d-bpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wadaboa%2F3d-bpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wadaboa%2F3d-bpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wadaboa%2F3d-bpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Wadaboa","download_url":"https://codeload.github.com/Wadaboa/3d-bpp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Wadaboa%2F3d-bpp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267107781,"owners_count":24037323,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d-bin-packing","3d-bpp","bin-packing","column-generation","cp","layers","maxrects","mip","or-tools","superitems"],"created_at":"2024-10-12T14:47:02.903Z","updated_at":"2025-07-26T02:34:02.136Z","avatar_url":"https://github.com/Wadaboa.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 3D Bin Packing\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"assets/bin-example.png\" /\u003e\n\u003c/p\u003e\n\nThis repository contains different implementations of heuristics-based and mathematical programming approaches to solve the 3D bin packing problem (3D-BPP):\n1. Baseline MP model [[1]](#1)\n2. Maxrects generalized to 3D (2D implementation based on [rectpack](https://github.com/secnot/rectpack)) [[3]](#3)\n3. Column generation MP model [[1]](#1)\n\nAll solutions are based on the concept of layers, which are collections of items having similar heights (within a pre-specified tolerance) that are thus having the same base z-coordinate. Using layers we are able to relax the 3D problem to a set of 2D ones, boosting efficiency-related metrics. Moreover, the usage of superitems (i.e. compounding similar items together in a bigger item) enables us to both lower the amount of items we are effectively dealing with and also to maximize layer density, thanks to the compact stacking of items in a superitem.\n\nThe bins building procedure is always handled in a procedural way, stacking layers on top of each other until a bin is full and opening new bins as needed. Before layers are placed in a bin, they are filtered based on a set of criteria (as described in [[1]](#1)), such as item coverage and layer density. After layers are placed in a bin, some items could still be \"flying\" (i.e. have zero support at their base): to solve this issue, we let items \"fall\" to the ground as much as possible, without allowing intersections, thus ensuring compactness and correctness.\n\n## Dataset\n\nThe dataset in use is based on the benchmark dataset introduced in [[1]](#1). As the original code is not publicly available, we made our best effort to reproduce the dataset as closely as possible. A pre-computed dataset with 1M examples is available in the `data/` folder (`products.pkl`).\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"assets/dataset.png\" /\u003e\n\u003c/p\u003e\n\n## Solutions\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"assets/flow.png\" /\u003e\n\u003c/p\u003e\n\nBelow you can find a broad explanation of each implemented solution. Every procedure can be called through the same function (`main()` in module `main.py`), by changing the `procedure` parameter (it could be `bl` for baseline, `mr` for maxrects or `cg` for the column generation approach). Down below you can find a MWE on how to use the library:\n```python\nfrom src import config, dataset, main\n\n# Load dataset\nproduct_dataset = dataset.ProductDataset(\n    \"data/products.pkl\",\n    config.NUM_PRODUCTS,\n    config.MIN_PRODUCT_WIDTH,\n    config.MAX_PRODUCT_WIDTH,\n    config.MIN_PRODUCT_DEPTH,\n    config.MAX_PRODUCT_DEPTH,\n    config.MIN_PRODUCT_HEIGHT,\n    config.MAX_PRODUCT_HEIGHT,\n    config.MIN_PRODUCT_WEIGHT,\n    config.MAX_PRODUCT_WEIGHT,\n    force_overload=False,\n)\n\n# Get random order\norder = product_dataset.get_order(50)\n\n# Solve bin packing using the specified procedure to get\n# a pool of bins without \"flying\" products\nbin_pool = main.main(\n    order,\n    procedure=\"bl\",\n)\n\n# Plot the bin pool\nbin_pool.plot()\n```\n\n### Baseline\n\nThe baseline model directly assigns superitems to layers and positions them by taking into account overlapment and layer height minimization. It reproduces model [SPPSI] of [[1]](#1). Beware that it might be very slow and we advice using it only for orders under 30 items.\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"assets/sppsi.png\" /\u003e\n\u003c/p\u003e\n\n### Maxrects\nMaxrects [[3]](#3) is an heuristic algorithm that was built to solve the 2D bin packing problem. In our solution, maxrects is generalized to 3D thanks to the use of layers and height groups. In particular, items are grouped together based on their 3rd dimension (the height) and a specified tolerance. Such groups of items are then used as inputs for a custom maxrects procedure in which layers are thought of as bins. The maxrects algorithm itself is implemented in the [rectpack](https://github.com/secnot/rectpack) library.\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"assets/maxrects.png\" /\u003e\n\u003c/p\u003e\n\n### Column generation\n\nThe column generation solution aims to decompose the [SPPSI] approach in 2 components: the main and the pricing sub-problems. Column generation acts by iteratively solving both sub-problems ([RMP] and then [SP]) and incorporates more and more variables along the way. In this way, the main problem [RMP] selects the best layers so far and provides dual variables (one for each item) to be used in the pricing sub-problem [SP], which determines the best subset of items to compose a new layer, that will be carried forward (in the next iteration) iff its reduced cost is non-negative (otherwise column generation terminates). Moreover, column generation is given a set of columns as warm start and such layers are computed by either the maxrects procedure or by adding one layer for each item (each layer having only one item).\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"assets/cg.png\" /\u003e\u003cbr\u003e\n\t\u003cimg src=\"assets/rmp.png\" /\u003e\u003cbr\u003e\n\t\u003cimg src=\"assets/sp.png\" /\u003e\n\u003c/p\u003e\n\nAuthors in [[1]](#1) further decompose the pricing sub-problem [SP] in two components: the no-placement and placement strategies. The former [SP-NP] serves as an item selection mechanism, thus ignoring the expensive placement constraints. The algorithm then checks whether there is a feasible placement of the selected items in a layer [SP-P]: if such a feasible placement exists, the column is added to the master problem, otherwise a new call to [SP-NP] is necessary, with an additional feasibility constraint (on the maximum number of selectable items). The no-placement/placement procedure continues until a feasible placement is found. In our implementation, we used a MIP solution for [SP-NP] (the `sp_np_type` parameter of the `main.main` function also allows to select a CP-based approach) and maxrects for [SP-P] (the `sp_p_type` parameter of the `main.main` function also allows to select exact MIP-based or CP-based approaches).\n\nDiffering from the author's description, our implementation does not incorporate column generation in a branch-and-price scheme. \n\n## Utilities\n\n### Lower bounds \n\nMartello, Pisinger and Vigo [[2]](#2) provided 3 different formulations to compute lower bounds on the number of required bins to pack the set of items we have at our disposal. In their paper, they present the following bounds:\n1. **L0** (or continuous lower bound): comes from a relaxation in which each item's occupied space is associated with its liquid volume, thus ignoring the actual item placements and other constraints (it is shown to have a worst-case performance ratio of 1 / 8)\n2. **L1**: better suited for instances with a large number of items and still computable in linear time (its worst-case performance can be arbitrarily bad)\n3. **L2**: better suited for instances with a large number of items, but requires quadratic time to be computed (it is shown to have a worst-case performance ratio of 2 / 3)\n\nTo compute such lower bounds, you can rely on functions implemented in the `utils` module: `get_l0_lb`, `get_l1_lb` and `get_l2_lb` for L0, L1 and L2, respectively. All functions have the same interface: they require an `order` and a `pallet_dims` attribute. The former should be taken from the `ProductDataset` class using the `get_order` function, while the latter should be an instance of the `Dimension` class (available in the `utils` module). L0 returns a single value, while L1 and L2 return 4 values, with the first one being the actual lower bound and the other 3 values being lower bounds on 2 dimensions (as described in [[2]](#2)).\n\n## Installation\n\nIn order to install all the dependecies required by the project, you can either rely on `pip` or `conda`. If you want to use the former, `cd` to the root folder of the project and run the following commands:\n```bash\npython3 -m venv venv\nsource venv/bin/activate\npip install -r init/requirements.txt\n```\n\nInstead, for the latter you'd have to run the following commands (after changing directory to the project's root):\n```bash\nconda env create --name 3d-bpp -f init/environment.yml\nconda activate environment.yml\n```\n\n## Execution\n\nThe library can be used from another project, by importing the necessary sources from `src/` or it can be used as a standalone bin packing library, by leveraging the interface functions in `src/main.py`.\n\nIf you want to see a working example, please check out the `bpp.ipynb` Jupyter notebook, that contains an explanation of the dataset in use, along with a comparison of all the implemented solutions.\n\nFor a more entertaining and interactive solution, you can also run the implemented [Streamlit](https://streamlit.io/) dashboard, by simply running the following command from the root of the project:\n```bash\npython3 -m streamlit run src/dashboard.py\n```\n\n## Slides\n\nTo start the slide show:\n\n1. Change directory to `slides/`\n1. Run `npm install` and `npm run dev`\n2. Visit http://localhost:3030\n\nEdit the [slides.md](./slides/slides.md) to see the changes.\n\nLearn more about Slidev on [documentations](https://sli.dev/).\n\n## References\n- \u003ca id=\"1\"\u003e[1]\u003c/a\u003e\n  _Samir Elhedhli, Fatma Gzara and Burak Yildiz (2019)_,\\\n  **Three-Dimensional Bin Packing and Mixed-Case Palletization**,\\\n  INFORMS Journal on Optimization.\n- \u003ca id=\"2\"\u003e[2]\u003c/a\u003e\n  _Silvano Martello, David Pisinger and Daniele Vigo (1998)_,\\\n  **The Three-Dimensional Bin Packing Problem**,\\\n  Operations Research.\n- \u003ca id=\"3\"\u003e[3]\u003c/a\u003e\n  _Jukka Jylänki (2010)_.\\\n  **A Thousand Ways to Pack the Bin - A Practical Approach to Two-Dimensional Rectangle Bin Packing**.\\\n  -.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwadaboa%2F3d-bpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwadaboa%2F3d-bpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwadaboa%2F3d-bpp/lists"}