在PHP中实现切割库存算法

时间:2013-01-02 20:56:11

标签: php algorithm

我需要用PHP脚本实现Cutting Stock Problem。 因为我的数学技能不是那么好,所以我只是试图强迫它。

从这些参数开始

  • $ inventory是一系列可以剪切的长度。
  • $ requestedPieces是由...请求的长度数组 顾客。
  • $ solution是一个空数组

我目前已经制定了这个递归函数来提出所有可能的解决方案:

function branch($inventory, $requestedPieces, $solution){
    // Loop through the requested pieces and find all inventory that can fulfill them
    foreach($requestedPieces as $requestKey => $requestedPiece){
        foreach($inventory as $inventoryKey => $piece){
            if($requestedPiece <= $piece){
                $solution2 = $solution;
                array_push($solution2, array($requestKey, $inventoryKey));
                $requestedPieces2 = $requestedPieces;
                unset($requestedPieces2[$requestKey]);
                $inventory2 = $inventory;
                $inventory2[$inventoryKey] = $piece - $requestedPiece;
                if(count($requestedPieces2) > 0){
                    branch($inventory2, $requestedPieces2, $solution2);
                }else{
                    global $solutions;
                    array_push($solutions, $solution2);
                }
            }
        }
    }
}

我发现的最大的低效率是它会多次找到相同的解决方案,但步骤的顺序不同。

例如:

  • $ inventory = array(1.83,20.66);
  • $ requestedPieces = array(0.5,0.25);

该功能将提供8种解决方案,其中应该提供4种解决方案。 什么是解决这个问题的好方法。

1 个答案:

答案 0 :(得分:2)

这不能回答你的问题,但我认为值得一提:

您还有其他几种方法可以解决您的问题,而不是强行解决问题。关于这个主题的wikipedia page非常详尽,但我只会描述另外两个更简单的想法。我将对某些单词使用维基百科术语,即 master 表示库存件, cut 表示所请求的单件。我将使用 set 来表示与给定母版有关的一组剪切。

第一个基于greedy algorithm,并且包括填充具有最大可用切割的集合,直到不再适合切割,并且为每个主体重复相同的过程,为每个主体生成一组他们

第二个更多dynamic:它使用递归(与你的一样),并寻找最佳拟合主要的剩余长度并在递归的每一步切割,目标是最小化浪费当没有更多的削减可以适应的长度。

function branch($master, $cuts, $set){
     $goods = array_filter($cuts, function($v) use ($master) { return $v <= $master;});
     $res = array($master,$set,$cuts);
     if (empty($goods))
         return $res;
     $remaining = array_diff($cuts, $goods);
     foreach($goods as $k => $g){
         $t = $set;
         array_push($t, $g);
         $r = $remaining;
         $c = $goods;
         for ($i = 0; $i < $k; $i++)
             array_push($r,array_shift($c));
         array_shift($c);
         $t = branch($master - $g, $c, $t);
         array_walk($r, function($k,$v) use ($t) {array_push($t[2], $v);});
         if ($t[0] == 0) return $t;
         if ($t[0] < $res[0])
             $res = $t;
     }
     return $res;
}

上面的函数应该为您提供给定主控的最佳设置。它返回一个包含3个值的数组:

  • 主人的浪费长度
  • 集合
  • 剩余的剪辑

参数是

  • 主人长度,
  • 要执行的剪辑(必须按降序排序),
  • 已安排的剪辑集(预先存在的集合,对于每个主人的第一次调用将为空)

警告:这取决于主人的顺序,你当然可以编写一个功能,尝试所有相关的可能性来找到最佳的主人顺序。