对标题不是100%肯定,可以随意编辑,使其更加通用,对所有用户都有帮助
我有一个订单捕获'门户',允许捕获订单。订单的一部分是数量或订单。
我现在需要处理订单,以便可以构建托盘,以便最佳地使用托盘。
例如,包装托盘尺寸可以是1.62立方米(1x1.2x1.35)
然后我在订单上有以下项目
产品代码,数量,总量
1,10,0.5立方米
2,3,0.2立方米
3,5,1.2立方米
4,1,0.15立方米
5,15,0.6立方米
我想处理这个,我假设使用mysql事务,以便实现以下输出:
托盘1:产品1,2,5。总容积= 1.3立方米
托盘2:产品3,4。总体积= 1.35立方米
因此,为了澄清,脚本将采用0.5个立方体的第一个托盘,然后查找列表中最接近0.85的下一个订单,以实现1.35立方米目标。在这种情况下,它将是0.6。现在总共1.1个立方体。剩余空间现在是0.25立方体。列表中最近的项目现在是产品2 @ 0.2 cube。现在总共有1.3个立方体,没有产品是0.05立方体或更少,所以托盘是完整的。下一个可用产品现在是产品3 @ 1.2立方体。所以需要0.15或更少的产品。产品4是准确的体积,因此添加到托盘并关闭。
我希望这有助于澄清我的要求。
是否存在可以帮助解决此问题的mysql事务,或者是否需要使用php处理它。
任何对此的帮助都会受到赞赏,只是不确定如何构建这种逻辑。
感谢您一如既往的时光,
mysql表如下:
答案 0 :(得分:2)
这是经典的bin packing problem,它是NP难的(也就是说,我们还没有弄清楚问题是否可以在多项式时间内解决)。找到最佳包装就等于尝试了所有可能的组合。
如果您不关心找到最优解,那么您在问题中描述的贪婪启发式(称为first fit decreasing)是一个合理的近似值;还有其他的启发式方法可以保证整体的最佳结果,但它们变得相当复杂。
您可以在PHP中实现FFD,如下所示(使用PDO进行数据库访问):
define('PALLET_SIZE', 1 * 1.2 * 1.35);
$dbh = new PDO("mysql:dbname=$dbname", $username, $password);
$qry = $dbh->prepare('
SELECT code, qty, volume
FROM orders
WHERE order_id = :order
ORDER BY volume DESC
');
$qry->execute(array(':order' => 123));
$pallets = array();
while ($order = $qry->fetch()) {
if ($order['volume'] > PALLET_SIZE) die('item too big');
for ($i = 1; $i <= $order['qty']; $i++) { // remove this loop if not needed
$placed = false;
foreach ($pallets as &$pallet) {
if ($pallet['remaining'] >= $order['volume']) {
$pallet['remaining'] -= $order['volume'];
$pallet['items'][] = $order['code'];
$placed = true;
break;
}
}
if (!$placed) $pallets[] = array(
'remaining' => PALLET_SIZE - $order['volume'],
'items' => array($order['code'])
);
}
}
print_r($pallets);
答案 1 :(得分:1)
是否有mysql事务
我认为你的意思是一个mysql函数。
不,mysql中没有任何东西可以帮助您解决这个问题。这是一个NP难题。解决问题的最有效方法可能是genetic algorithm,但是数据中没有足够的信息来准确实现这一点 - 包装取决于形状(即所有尺寸)和体积一样多。
如果您确实拥有尺寸,那么允许人类设置包装而不是尝试在代码中执行此操作仍然要容易得多。
作为一个快速的解决方案,我将比较一组N个列表的副本,随机排序,遍历每个副本创建完整的托盘然后选择最少托盘的列表(或其他所需的特征)。为N选择正确的值取决于大小的分布以及您希望花费多少时间来处理数据。
答案 2 :(得分:1)
这类似于背包问题;这是一个只能通过尝试所有可能的组合才能完美解决的问题。随着可能组合的数量增加,这迅速成为问题。在你的例子中,会有33个!组合 - 相当大的数量。所以这条路线可能不是我们想要去的路线......
虽然有背包问题here的示例代码,但没有“开箱即用”的解决方案。这可能有所帮助。
几年前我写了一个程序,在类似的问题上做了一个合理的工作;伪代码就像:for each order
while (unallocated items on order)
create new pallet
while not (pallet = full)
allocate largest remaining item smaller than remaining capacity to pallet
loop
loop
next order
这个算法做得不错 - 船厂里的人喜欢它,因为最大的物品总是在包装清单的顶部(因此最终位于堆栈的底部)。该企业接受该算法不能保证是最优的;在实践中,这只会对巨大的订单产生影响,因为算法的轻微改进可能会为我们节省一个托盘;在大多数情况下,使算法更有效意味着货物中的最后一个托盘几乎是空的。