Exemplo n.º 1
0
 function MatrixFitRoute($route)
 {
     require_once 'matrix.php';
     $this->refreshPosibleTruck();
     $route_possible_trucks = $this->getPossibleTrucks($route);
     $copy_possible_trucks = $this->truck_possible;
     $list_all_possible_trucks = array();
     foreach ($copy_possible_trucks as $value) {
         $list_all_possible_trucks = array_merge($list_all_possible_trucks, $value);
     }
     $list_all_possible_trucks = array_unique(array_merge($list_all_possible_trucks, $route_possible_trucks));
     $pending_routes = array_keys($this->routes);
     array_push($pending_routes, "new");
     $assigned_trucks = array();
     //create white_matrix
     $white_matrix = array();
     foreach ($list_all_possible_trucks as $truck_id) {
         $white_matrix[$truck_id] = array();
         foreach ($pending_routes as $route_id) {
             if ($route_id == "new") {
                 $white_matrix[$truck_id][$route_id] = in_array($truck_id, $route_possible_trucks) ? 1 : 0;
             } else {
                 $white_matrix[$truck_id][$route_id] = in_array($truck_id, $copy_possible_trucks[$route_id]) ? 1 : 0;
             }
         }
     }
     $grey_matrix = new Matrix($white_matrix);
     //basic required condition for solution
     if (!$grey_matrix->possible()) {
         return false;
     }
     //cardinality==1 check for $route. this means that the route has only one truck that it can use.
     foreach ($grey_matrix->getColumnKeys() as $route_id) {
         if ($grey_matrix->getColumnCardinal($route_id) == 1) {
             $truck_id = $grey_matrix->getFirstPositiveRow($route_id);
             if ($truck_id === false) {
                 trigger_error("Looked for positive row but found none", E_USER_ERROR);
             } else {
                 $assigned_trucks[$truck_id] = $route_id;
                 $grey_matrix->deleteRow($truck_id);
                 $grey_matrix->deleteColumn($route_id);
             }
         }
     }
     //cardinality==1 check for $truck. this means that there is only one route that can use this truck
     foreach ($grey_matrix->getRowKeys() as $truck_id) {
         if ($grey_matrix->getRowCardinal($truck_id) == 1) {
             $route_id = $grey_matrix->getFirstPositiveColumn($truck_id);
             if ($route_id === false) {
                 trigger_error("Looked for positive col but found none", E_USER_ERROR);
             } else {
                 $assigned_trucks[$truck_id] = $route_id;
                 $grey_matrix->deleteRow($truck_id);
                 $grey_matrix->deleteColumn($route_id);
             }
         }
     }
     //trivial solution found
     if (count($grey_matrix->getColumnKeys()) < 1) {
         return $assigned_trucks;
     }
     //check again for basic condition before continuing
     if (!$grey_matrix->possible()) {
         return false;
     }
     //iterate while there are still routes to be fit, we will include exit statments under certain conditions inside the loop
     $black_matrix = new Matrix($grey_matrix->getMatrix());
     $ignores = array();
     $routes_ids = $black_matrix->getColumnKeys();
     $last_route_id = end($routes_ids);
     $first_route_id = reset($routes_ids);
     $max_loop = $black_matrix->maximumIterations();
     $loop_count = 0;
     while (true) {
         if ($loop_count >= $max_loop) {
             trigger_error("loops count exceeded logical max loop, please check the code for errors", E_USER_ERROR);
         }
         $black_matrix = new Matrix($grey_matrix->getMatrix());
         //recreate for loop
         $routes_ids = $black_matrix->getColumnKeys();
         //recreate for loop
         $assignments = array();
         // list of assignments for solution
         $previous_route_id = false;
         $previous_route_value = false;
         $n = 1;
         //for slice porpuses
         foreach ($routes_ids as $route_id) {
             if ($black_matrix->possible() === false) {
                 return false;
             }
             if (count($black_matrix->getColumnKeys()) == 0 || count($black_matrix->getRowKeys()) == 0) {
                 return false;
             }
             if (!isset($ignores[$route_id])) {
                 $ignores[$route_id] = array();
             }
             $fix_truck = $black_matrix->getFirstPositiveRow($route_id, $ignores[$route_id]);
             //there are no more positive values availables
             if ($fix_truck === false) {
                 //no more subsitituions left
                 if ($route_id == $first_route_id) {
                     return false;
                 } else {
                     $previous_step = $previous_route_value;
                     if ($previous_step === false) {
                         trigger_error("something went wrong while searching for the previous positive of {$previous_route_id}", E_USER_ERROR);
                     } else {
                         array_push($ignores[$previous_route_id], $previous_step);
                     }
                     $ignores = array_slice($ignores, 0, $n, TRUE);
                     break;
                     //restart loop
                 }
             } else {
                 $n += 1;
                 $assignments[$fix_truck] = $route_id;
                 $black_matrix->deleteRow($fix_truck);
                 $black_matrix->deleteColumn($route_id);
                 $previous_route_id = $route_id;
                 $previous_route_value = $fix_truck;
                 //A solution was found, hurray!
                 if ($route_id == $last_route_id) {
                     return array_merge($assigned_trucks, $assignments);
                 }
             }
         }
     }
 }