예제 #1
0
 protected static function createPointsFromArray($data)
 {
     $points = [];
     $pairCount = count($data) / 2;
     $i = 1;
     foreach ($data as $display_id => $pointInfo) {
         $id = $display_id == 0 ? Point::DEPOT_ID : $i++;
         $newPoint = new Point(['id' => $id, 'display_id' => $display_id, 'x' => floatval($pointInfo[0]), 'y' => floatval($pointInfo[1]), 'box_dimensions' => isset($pointInfo[2]) ? ['x' => floatval($pointInfo[2]), 'y' => floatval($pointInfo[3]), 'z' => floatval($pointInfo[4])] : null, 'box_weight' => isset($pointInfo[5]) ? floatval($pointInfo[5]) : null, 'combinatorial_value' => $id]);
         if ($id == Point::DEPOT_ID) {
             $newPoint->setType(Point::TYPE_DEPOT);
             $newPoint->setPairId(Point::DEPOT_ID);
             $newPoint->setBoxWeight(0);
             $depot = $newPoint;
         } else {
             $isPickup = $id <= $pairCount;
             $newPoint->addData(['type' => $isPickup ? Point::TYPE_PICKUP : Point::TYPE_DELIVERY, 'pair_id' => $isPickup ? $id + $pairCount : $id - $pairCount]);
         }
         $points[$id] = $newPoint;
     }
     // assign to each delivery point box weight = -1*<box weight of correspoding pickup>
     // also validate all points
     foreach ($points as $point) {
         if ($point->getType() == Point::TYPE_DELIVERY) {
             $point->setBoxWeight(-$points[$point->getPairId()]->getBoxWeight());
             $point->setBoxDimensions($points[$point->getPairId()]->getBoxDimensions());
         }
         if ($point->isInvalid()) {
             throw new \Exception("Point #" . $point->getId() . " is invalid: " . print_r($point->getValidationErrors(), true));
         }
     }
     return count($points) > 1 ? $points : reset($points);
 }
 public function getDistanceBetweenPoints(\Litvinenko\Combinatorics\Pdp\Point $firstPoint, \Litvinenko\Combinatorics\Pdp\Point $secondPoint)
 {
     $id1 = $firstPoint->getId();
     $id2 = $secondPoint->getId();
     if (!isset($this->distanceCache[$id1][$id2])) {
         $this->distanceCache[$id1][$id2] = $this->_getDistanceBetweenPoints($firstPoint, $secondPoint);
     }
     return $this->distanceCache[$id1][$id2];
 }
예제 #3
0
 public static function readPointsFromFile($filename)
 {
     $points = [];
     if (file_exists($filename)) {
         $pointData = preg_split("/\\r\\n|\\r|\\n/", file_get_contents($filename));
         $count = (int) $pointData[0];
         unset($pointData[0]);
         foreach ($pointData as $row) {
             try {
                 $pointInfo = explode(' ', $row);
                 $id = $pointInfo[0] == 'depot' ? Point::DEPOT_ID : (int) $pointInfo[0];
                 $newPoint = new Point(['id' => $id, 'x' => floatval($pointInfo[1]), 'y' => floatval($pointInfo[2]), 'box_dimensions' => isset($pointInfo[3]) ? ['x' => floatval($pointInfo[3]), 'y' => floatval($pointInfo[4]), 'z' => floatval($pointInfo[5])] : null, 'box_weight' => isset($pointInfo[6]) ? floatval($pointInfo[6]) : null, 'combinatorial_value' => $id]);
                 if ($id == Point::DEPOT_ID) {
                     $newPoint->setType(Point::TYPE_DEPOT);
                     $newPoint->setPairId(Point::DEPOT_ID);
                     $newPoint->setBoxWeight(0);
                     $depot = $newPoint;
                 } else {
                     $isPickup = $id <= $count / 2;
                     $newPoint->addData(['type' => $isPickup ? Point::TYPE_PICKUP : Point::TYPE_DELIVERY, 'pair_id' => $isPickup ? $id + $count / 2 : $id - $count / 2]);
                     $points[$id] = $newPoint;
                 }
             } catch (Exception $e) {
                 throw new \Exception("Can't read row " . key($pointData) . ": " . $e->getMessage());
             }
         }
         // assign to each delivery point box weight = -1*<box weight of correspoding pickup>
         // also validate all points
         foreach ($points as $point) {
             if ($point->getType() == Point::TYPE_DELIVERY) {
                 $point->setBoxWeight(-$points[$point->getPairId()]->getBoxWeight());
                 $point->setBoxDimensions($points[$point->getPairId()]->getBoxDimensions());
             }
             // if ($point->isInvalid())
             // {
             //     throw new \Exception ("Point #" . $point->getId() . " is invalid: " . print_r($point->getValidationErrors(), true));
             // }
         }
         // validate depot
         // if ($depot->isInvalid())
         // {
         //     throw new \Exception ("Depot is invalid: " . print_r($depot->getValidationErrors(), true));
         // }
         return ['points' => $points, 'depot' => $depot];
     } else {
         throw new \Exception("File {$filename} does not exist!");
     }
 }
 public function getSolution()
 {
     // $this->validate();
     // $this->getHelper()->validateObjects($this->getPoints());
     // $this->_checks=0;
     $generator = new Generator(['tuple_length' => Point::getPointCount($this->getPoints()), 'generating_elements' => Helper::getGeneratorDataFromPoints($this->getPoints()), 'weight_capacity' => $this->getWeightCapacity(), 'load_area' => $this->getLoadArea(), 'precise' => $this->getPrecise(), 'metrics' => $this->getEvaluator()->getMetrics(), 'initial_object' => Helper::getGeneratorDataFromPoints([$this->getDepot()]), 'log_steps' => true]);
     $pointSequences = Helper::getPointSequencesFromGeneratorData($generator->generateAll());
     $bestPointSequence = null;
     foreach ($pointSequences as &$pointSequence) {
         $pointSequence[] = $this->getDepot();
         $currentCost = $this->_getCost($pointSequence);
         if (is_null($bestPointSequence) || $this->_compareCosts($currentCost, $bestCost) === 1) {
             // if needed, check 3D constraints and skip path if it's incorrect
             if ($this->getData('check_final_loading')) {
                 if (!$this->canLoad($pointSequence)) {
                     continue;
                 }
             }
             $bestPointSequence = $pointSequence;
             $bestCost = $currentCost;
         }
     }
     $this->setGeneratedPointSequences($pointSequences);
     // echo $this->_checks."\n";
     return new Path(['points' => $bestPointSequence]);
 }
 protected function _generateNestedPointSequences($node)
 {
     $pointSequence = $node->getContent()->getPoints();
     $generator = new Generator(['tuple_length' => Point::getPointCount($this->getPoints()), 'generating_elements' => Helper::getGeneratorDataFromPoints($this->getPoints()), 'current_path' => $node->getContent(), 'weight_capacity' => $this->getWeightCapacity(), 'load_area' => $this->getLoadArea()]);
     // $generator->validate();
     $points = Helper::getGeneratorDataFromPoints($pointSequence);
     $result = Helper::getPointSequencesFromGeneratorData($generator->generateNextObjects($points));
     if ($result) {
         // hack: if all PDP points except of depot are present, add depot
         $nodeHasAllPointsExceptOfDepot = Helper::pointSequenceIncludesAllPickupsAndDeliveries(reset($result), $this->getPoints());
         if ($nodeHasAllPointsExceptOfDepot) {
             foreach ($result as &$resultPointSequence) {
                 $resultPointSequence = array_merge($resultPointSequence, [$this->getDepot()]);
             }
         }
     }
     return $result;
 }
예제 #6
0
 public function canLoad($pointSequence, $pythonFile, $loadArea, $weightCapacity, $allPoints)
 {
     $result = false;
     $points = self::removeDepotFromPointSequence($pointSequence);
     $boxFileName = dirname($pythonFile) . '/boxes.txt';
     if (!$this->getBoxesFileIsFilled()) {
         file_put_contents($boxFileName, IO::getBoxesTextForExternalPdpHelper($allPoints));
         $this->setBoxesFileIsFilled(true);
     }
     if (!file_exists($pythonFile)) {
         throw new \Exception("Python file '{$pythonFile}' does not exist!");
     }
     $cmdString = "python {$pythonFile}" . " -b {$boxFileName}" . " -n " . (int) (count($allPoints) / 2) . " -c \"" . implode(' ', $loadArea) . ' ' . $weightCapacity . "\"" . " -r \"" . implode(' ', Point::getPointIds($points)) . "  1\"" . " -p";
     $cmdResult = exec($cmdString);
     //  echo $cmdResult . "\n";
     $result = $cmdResult == 'True';
     return $result;
 }
 protected function _getDistanceBetweenPoints(\Litvinenko\Combinatorics\Pdp\Point $firstPoint, \Litvinenko\Combinatorics\Pdp\Point $secondPoint)
 {
     return sqrt(pow($firstPoint->getX() - $secondPoint->getX(), 2) + pow($firstPoint->getY() - $secondPoint->getY(), 2));
 }