nawebco / box-packer
针对包装/背包问题的另一种解决方案。
2.2.1
2019-07-26 16:09 UTC
Requires
- php: >=7.2
- ext-json: *
Requires (Dev)
- phpunit/phpunit: ^5.6
README
本模块实现了一个粗略的装箱问题解决方案。最初开发是为了支持一个电子商务商家的愿望,只有在订单中的所有商品都适合某个盒子时才提供送货选项。此实现也支持多个盒子。
装箱问题是NP难的。此实现是一种启发式方法,并不总是提供最优解,但它速度快,并且不太可能提供一个对于人类在装箱实际物品时难以复制的解决方案。
简要来说,此算法的工作原理如下
- 首先包装体积最大的物品。
- 物品按层包装。层的大小与盒子一样宽和长,高度与层中最高的物品一样高。
- 每个层中物品并排放置,最长边在底部,方向使剩余面积最大。
- 如果一个物品不能放入任何现有层,算法将开始一个新的层。
- 每次添加物品时,算法尝试将其添加到任何剩余空间中(包括在其它物品上方),除非这样做会增加层的高度。
- 每次开始新的层时,算法都会检查层总高度是否超过了盒子高度。
使用NAWebCo\BoxPacker
要安装,请在项目的根目录中运行 composer require nawebco/box-packer
。如果您尚未使用Composer的自加载器,请确保在需要访问BoxPacker的地方要求vendor/autoload.php
。
使用示例
<?php
require 'vendor/autoload.php';
use NAWebCo\BoxPacker\Packer;
use NAWebCo\BoxPacker\GenericPackable;
$packer = new Packer();
// Width, length, height, description
// The order of the dimensions doesn't matter.
$packer->addBox(new GenericPackable(10, 15, 6, 'Big box'));
// Width, length, height, description
// The order of the dimensions doesn't matter.
$packer->addItem(new GenericPackable(8.5, 11, 2, 'First book'));
$packer->addItem(new GenericPackable(8.5, 11, 1.2, 'Second book'));
$packer->addItem(new GenericPackable(3, 3, 3, 'Carved wooden block'));
$result = $packer->pack();
if( $result->success() ){
echo "Everything fits!\n\n";
foreach( $result->getPackedBoxes(true) as $boxResults ){
$box = $boxResults['box'];
$contents = $boxResults['contents'];
$containerDescription = $box->getDescription() ?: 'One box';
echo "$containerDescription contains:\n";
foreach( $contents as $item ){
$itemDescription = $item->getDescription() ?: 'Item';
echo "$itemDescription ({$item->getWidth()}, {$item->getLength()}, {$item->getHeight()})\n";
}
}
} else {
echo count($result->getNotPackedItems()) . " items didn't fit.";
}
在上面的示例中,可包装物品由Solid
类表示。任何实现了SolidInterface
的类都可以通过Packer运行。
需求
- PHP版本5.6或更高
许可证
NAWebCo\BoxPacker是MIT许可的。