Permalink
Browse files

- Updated the method to calculate the products inside boxes ( better …

…way to do, using total volume )

- Sum weight of products inside boxes.
- Return boxes that have products.
- Added name of boxes.
- Started always with the bigger box to minor.
  • Loading branch information...
1 parent cc678bf commit 2a2d1834024e1604e1b0ac9f6832897ccf526a5e @luizwbr committed Nov 21, 2011
Showing with 156 additions and 61 deletions.
  1. +156 −61 boxing.class.php
View
217 boxing.class.php
@@ -1,4 +1,35 @@
<?php
+/*
+this some kind of box packing algorithm,
+check if n boxes fit in n bigger boxes
+i use this for checking if items will fit a packaging box
+if this algorithm says true: they do definitely fit
+if this algorithm says false: they most probably will not fit, but this is a program, not a cop.
+
+disclaimer:
+
+this is not an accurate solution for knapsack or any of those fancy np-complete combinatory problems
+i am not a mathematican, i have no idea what i am talking about, and also the german wikipedia sucks on this topic
+quick and dirty, works for me, public domain, donations very welcome
+
+author: sebastian vollnhals <sebastian at vollnhals dot info>
+
+usage:
+
+$b = new boxing();
+
+$b -> add_outer_box(40,30,30); // our quantum box; l, w, h
+
+$b -> add_inner_box(20,30,40); // schroedingers cat; l, w, h
+$b -> add_inner_box(10,5,5); // the poison; l, w, h
+$b -> add_inner_box(5,5,10); // some katzenstreu; l, w, h
+
+if ($b -> fits()) {
+
+ // schroedingers cat and schroedingers stuff do fit in the box
+
+}
+*/
class boxing {
@@ -14,31 +45,30 @@ public function boxing() {
}
- public function add_outer_box($l,$w,$h) {
+ public function add_outer_box($id=false, $l,$w,$h, $vol=0) {
if ($l > 0 && $w > 0 && $h > 0) {
-
$this -> outer_boxes[] = array(
-
- "dimensions" => $this -> sort_dimensions($l,$w,$h),
- "packed" => false
-
+ "dimensions" => $this -> sort_dimensions($l,$w,$h),
+ "packed" => false,
+ "weight" => 0,
+ "volume" => $vol,
+ "name" => $id
);
-
}
-
return true;
}
- public function add_inner_box($l,$w,$h) {
+ public function add_inner_box($l,$w,$h, $weight) {
if ($l > 0 && $w > 0 && $h > 0) {
$this -> inner_boxes[] = array(
- "dimensions" => $this -> sort_dimensions($l,$w,$h),
- "packed" => false
+ "dimensions" => $this -> sort_dimensions($l,$w,$h),
+ "weight" => $weight,
+ "packed" => false
);
@@ -54,9 +84,7 @@ public function fits() {
/* first we do a simple volume check, this can save a lot of calculations */
if (!$this -> fits_volume()) {
-
return false;
-
}
/* get next inner box */
@@ -66,44 +94,54 @@ public function fits() {
$inner_box_id = $this->next_inner_box();
if ($inner_box_id === false) {
-
break;
-
}
- $this -> sort_outer_boxes(); // smallest first
+ $this -> sort_outer_boxes(); // smallest first
+ if ( count($this->inner_boxes) > 1 ) {
+ arsort($this->outer_boxes); // biggest first
+ }
$found_fitting_box = false;
-
+ $arr_fits_inside = array();
+
+ $menor_perda = 0;
+
foreach ($this->outer_boxes as $outer_box_id => $outer_box) {
- if (!$outer_box["packed"] && $this->fits_inside($inner_box_id, $outer_box_id)) {
-
- /* matches! */
-
- $this -> inner_boxes[$inner_box_id]["packed"] = true;
- $this -> outer_boxes[$outer_box_id]["packed"] = true;
-
+ // if (!$outer_box["packed"] && $this->fits_inside($inner_box_id, $outer_box_id)) {
+ if ($this->fits_inside($inner_box_id, $outer_box_id)) {
+
$this -> find_subboxes($inner_box_id, $outer_box_id);
- $found_fitting_box = true;
-
- break;
-
+ /* faz a verificação da menor perda de pacote */
+ $volume_atual = $this->outer_boxes[$outer_box_id]["volume"] - $this->inner_boxes[$inner_box_id]["volume"];
+ $perda_atual = 1-($volume_atual/$this->outer_boxes[$outer_box_id]["volume"]);
+
+ if ($perda_atual > $menor_perda) {
+ $menor_perda = $perda_atual;
+ $pacote_menor = $outer_box_id;
+ // produto empacotado
+ $this -> inner_boxes[$inner_box_id]["packed"] = true;
+ }
+
+ //$found_fitting_box = true;
+ //break;
}
-
}
+
+ // para cada um encontrado, separa o menor espaço sobrando
+ $this->outer_boxes[$pacote_menor]["volume"] -= $this->inner_boxes[$inner_box_id]["volume"];
+ $this->outer_boxes[$pacote_menor]["packed"] = true;
+ // sum product weight
+ $this -> outer_boxes[$pacote_menor]["weight"] += $this -> inner_boxes[$inner_box_id]["weight"];
if (!$found_fitting_box) {
-
- return false;
-
+ // do it recursive later
}
}
-
/* we ran out of inner boxes but have outer boxes left */
-
return true;
}
@@ -113,28 +151,29 @@ public function fits_volume() {
$inner_volume = 0;
$outer_volume = 0;
- foreach ($this -> inner_boxes as $inner) {
+ foreach ($this -> inner_boxes as $k=>$inner) {
- $inner_volume += ($inner["dimensions"][0] * $inner["dimensions"][1] * $inner["dimensions"][2]);
+ $inner_box = ($inner["dimensions"][0] * $inner["dimensions"][1] * $inner["dimensions"][2]);
+ $inner_volume +=$inner_box;
+ // adiciona o volume
+ $this->inner_boxes[$k]["volume"] = $inner_box;
}
-
- foreach ($this -> outer_boxes as $outer) {
-
- $outer_volume += ($outer["dimensions"][0] * $outer["dimensions"][1] * $outer["dimensions"][2]);
+
+ foreach ($this -> outer_boxes as $k=>$outer) {
+
+ $outer_box = ($outer["dimensions"][0] * $outer["dimensions"][1] * $outer["dimensions"][2]);
+ $outer_volume += $outer_box;
+ // adiciona o volume
+ $this->outer_boxes[$k]["volume"] = $outer_box;
}
-
+
if ($inner_volume > $outer_volume) {
-
- /* inner boxes have more volume than outer ones */
-
+ # inner boxes have more volume than outer ones
return false;
-
} else {
-
return true;
-
}
}
@@ -144,7 +183,7 @@ private function find_subboxes($inner_box_id, $outer_box_id) {
$inner_dimensions = $this->inner_boxes[$inner_box_id]["dimensions"];
$outer_dimensions = $this->outer_boxes[$outer_box_id]["dimensions"];
- sort($outer_dimensions);
+ rsort($outer_dimensions);
$pairs = array();
@@ -160,7 +199,7 @@ private function find_subboxes($inner_box_id, $outer_box_id) {
"inner" => $inner_value,
"outer" => $outer_value,
- "diff" => $outer_value-$inner_value
+ "diff" => $outer_value-$inner_value,
);
@@ -178,7 +217,7 @@ private function find_subboxes($inner_box_id, $outer_box_id) {
$pairs = $this-> _diffsort($pairs);
- $this -> add_outer_box($pairs[0]["diff"], $pairs[1]["outer"], $pairs[2]["outer"]);
+ $this -> add_outer_box(false,$pairs[0]["diff"], $pairs[1]["outer"], $pairs[2]["outer"]);
$pairs[0]["diff"] = 0;
$pairs[0]["outer"] = $pairs[0]["inner"];
@@ -193,15 +232,21 @@ private function find_subboxes($inner_box_id, $outer_box_id) {
private function fits_inside($inner_box_id, $outer_box_id) {
if (
-
- $this->inner_boxes[$inner_box_id]["dimensions"][0] <= $this->outer_boxes[$outer_box_id]["dimensions"][0] &&
+ $this->inner_boxes[$inner_box_id]["volume"] <= $this->outer_boxes[$outer_box_id]["volume"]
+ /*$this->inner_boxes[$inner_box_id]["dimensions"][0] <= $this->outer_boxes[$outer_box_id]["dimensions"][0] &&
$this->inner_boxes[$inner_box_id]["dimensions"][1] <= $this->outer_boxes[$outer_box_id]["dimensions"][1] &&
- $this->inner_boxes[$inner_box_id]["dimensions"][2] <= $this->outer_boxes[$outer_box_id]["dimensions"][2]
+ $this->inner_boxes[$inner_box_id]["dimensions"][2] <= $this->outer_boxes[$outer_box_id]["dimensions"][2]*/
) {
-
- /* fits */
-
+ // trocar este metodo de calculo
+ /*
+ echo "volume: ".$outer_box_id.' - ';
+ echo $this->outer_boxes[$outer_box_id]["volume"];
+ echo "<hr>";
+ */
+ // entra na caixa e já diminui do volume total
+ #$this->outer_boxes[$outer_box_id]["volume"] -= $this->inner_boxes[$inner_box_id]["volume"] ;
+
return true;
} else {
@@ -281,18 +326,17 @@ private function next_inner_box() {
private function _sksort($array, $subkey, $sort_descending=false, $keep_keys_in_sub=false) {
// slightly modified since stolen from http://www.php.net/manual/de/function.sort.php#93473
-
foreach ($array as $key => &$value) {
$sort = array();
foreach ($value as $index => $val) {
- $sort[$index] = $val[$subkey];
+ @$sort[$index] = $val[$subkey];
}
- asort($sort);
+ asort($sort);
$keys = array_keys($sort);
@@ -358,6 +402,57 @@ function _diffsort($array) {
}
-}
+ function get_inner_boxes(){
+ return $this->inner_boxes;
+ }
+
+ function get_outer_boxes(){
+ return $this->outer_boxes;
+ }
+
+ function set_inner_boxes($inner_boxes){
+ $this->inner_boxes = $inner_boxes;
+ }
+
+ function set_outer_boxes($outer_boxes){
+ $this->outer_boxes = $outer_boxes;
+ }
+
+ // fits box packages
+ function get_fits_outer_boxes(){
+ $vt = array();
+ foreach ($this->outer_boxes as $key=>$box){
+ // only packed boxes
+ if ($box["packed"]) {
+ $vt[$key] = $box;
+ }
+ }
+ return $vt;
+ }
+
+ // not fits products
+ function get_not_fits_inner_boxes(){
+ $prd = array();
+ foreach ($this->inner_boxes as $key=>$box){
+ // only packed boxes
+ if (!$box["packed"]) {
+ $prd[$key] = $box;
+ }
+ }
+ return $prd;
+ }
-?>
+ // fits products
+ function get_fits_inner_boxes(){
+ $prd = array();
+ foreach ($this->inner_boxes as $key=>$box){
+ // only packed boxes
+ if ($box["packed"]) {
+ $prd[$key] = $box;
+ }
+ }
+ return $prd;
+ }
+
+
+}

1 comment on commit 2a2d183

@yetzt

i see, you changes the approach. :)

Please sign in to comment.