function getTotalDistanceViaNathurOrder($orders_list, $orgion)
{
    foreach ($orders_list as $carNum => &$orders) {
        $preNode = $orgion;
        foreach ($orders as $num => &$ord) {
            $pathInfo = MapPoint::getRealDistance($preNode, $ord);
            //            $carList[$carNum] += $pathInfo['distance'];
            $ord['time'] = $pathInfo['time'];
            $ord['distance'] = $pathInfo['distance'];
            $preNode = $ord;
        }
    }
    return $orders_list;
}
Example #2
0
 /**
  * 节省法
  * $orders {
  * lat=>float
  * lng=>float
  * link=>[int, int] //保存相邻上下节点,前者是上节点,后者是下节点
  * vehicle=>int //保存车辆的序号
  * }
  * @return array
  * @Author: WangBo <*****@*****.**>
  */
 private function saveMethod()
 {
     $orders =& $this->orders;
     $distances = $this->getStraitDistanceArray($orders);
     $savingsArray = $this->getSortedSavingData($distances);
     //        unset($distances);
     $count = count($orders);
     //获取原点到其他点之间的真实耗时和里程
     $realPathInfoArray = array();
     //初始化,一个点一辆车,并计算里程
     /**
      * $vehicle:{
      * cost     //耗时
      * head=>[int, int] //两个端点,前者是起点,后者是终点
      * }
      */
     $vehicle = array();
     for ($key = 1; $key < $count; $key++) {
         //            $pathInfo = MapPoint::getRealDistance($orders[0], $orders[$key]);
         //            $realPathInfoArray[0][$key] = $pathInfo;
         //耗时是直线距离的两倍
         $delivery = $this->getDeliveryTime($orders[$key]);
         $vehicle[$key]['cost'] = $distances[0][$key] / $this->velocity + $delivery;
         $vehicle[$key]['rcost'] = $delivery;
         //            $vehicle[$key]['cost'] = 2 * $pathInfo['time'] + $this->getDeliveryTime($orders[$key]);
         $vehicle[$key]['head'][] = $key;
         $vehicle[$key]['head'][] = $key;
         $orders[$key]['vehicle'] = $key;
     }
     //按节省里程由多到少的顺序,合并车辆
     $newCostCalCount = 0;
     $canCombineCount = 0;
     foreach ($savingsArray as $conn) {
         $i = $conn['i'];
         $j = $conn['j'];
         if ($this->canCombine($i, $j)) {
             //判断是否可以合并
             //开始复杂的连接操作
             $newCostCalCount++;
             if ($orders[$i]['link'][1] !== null) {
                 //保证$i的车辆的终点是$i
                 //交换i,j
                 $this->exchange($i, $j);
             }
             if ($orders[$j]['link'][1] === null) {
                 $ihead = $vehicle[$orders[$i]['vehicle']]['head'][0];
                 $jhead = $vehicle[$orders[$j]['vehicle']]['head'][0];
                 if ($distances[0][$jhead] < $distances[0][$ihead]) {
                     //始终保证$i这条线前
                     $this->exchange($i, $j);
                 }
             }
             if ($orders[$j]['link'][0] === 0) {
                 $tail = $j;
                 $jCost = $vehicle[$orders[$j]['vehicle']]['cost'] - $distances[0][$tail] / $this->velocity;
             } else {
                 $tail = $vehicle[$orders[$j]['vehicle']]['head'][0];
                 $jCost = $vehicle[$orders[$j]['vehicle']]['rcost'];
             }
             $iCost = $vehicle[$orders[$i]['vehicle']]['cost'];
             //                $newCost = $vehicle[$orders[$i]['vehicle']]['cost'] + $vehicle[$orders[$j]['vehicle']]['cost'] + $distances[$i][$j]/$this->velocity - $distances[0][$tail] / $this->velocity;
             $newCost = $iCost + $jCost + $distances[$i][$j] / $this->velocity;
             if ($newCost < $this->maxCost) {
                 $canCombineCount++;
                 $pathInfo = MapPoint::getRealDistance($orders[$i], $orders[$j]);
                 $realPathInfoArray[$i][$j] = $pathInfo;
                 $newCost = $iCost + $jCost + $pathInfo['time'];
                 if ($newCost >= $this->maxCost) {
                     continue;
                 }
                 $canCombineCount++;
                 $rpathInfo = MapPoint::getRealDistance($orders[$j], $orders[$i]);
                 $realPathInfoArray[$j][$i] = $rpathInfo;
                 $veh = array();
                 $orders[$i]['link'][1] = $j;
                 if ($orders[$j]['link'][0] !== 0) {
                     $orders[$j]['link'][1] = $orders[$j]['link'][0];
                     $orders[$tail]['link'][0] = $orders[$tail]['link'][1];
                     $orders[$tail]['link'][1] = null;
                     $veh['head'][1] = $tail;
                 } else {
                     $veh['head'][1] = $vehicle[$orders[$j]['vehicle']]['head'][1];
                 }
                 $orders[$j]['link'][0] = $i;
                 $veh['cost'] = $newCost;
                 $veh['rcost'] = $vehicle[$orders[$j]['vehicle']]['cost'] + $rpathInfo['time'] + $vehicle[$orders[$i]['vehicle']]['rcost'];
                 $veh['head'][0] = $vehicle[$orders[$i]['vehicle']]['head'][0];
                 $vehicle[] = $veh;
                 end($vehicle);
                 $last = key($vehicle);
                 unset($vehicle[$orders[$i]['vehicle']]);
                 unset($vehicle[$orders[$j]['vehicle']]);
                 unset($orders[$i]['vehicle']);
                 unset($orders[$j]['vehicle']);
                 $orders[$veh['head'][0]]['vehicle'] = $last;
                 $orders[$veh['head'][1]]['vehicle'] = $last;
             }
         }
     }
     unset($savingsArray);
     echo "<!-- 计算次数 {$newCostCalCount}, {$canCombineCount} -->";
     $vehicle_list = array();
     foreach ($vehicle as $key => $vc) {
         $vc['list'][] = 0;
         $node = $vc['head'][0];
         $pre = 0;
         do {
             $vc['list'][] = $node;
             $tmp = $node;
             $node = $pre === $orders[$node]['link'][0] ? $orders[$node]['link'][1] : $orders[$node]['link'][0];
             $pre = $tmp;
         } while ($node && ($orders[$node]['link'][0] || $orders[$node]['link'][1]));
         $vehicle_list[] = $vc;
     }
     //组装结果
     $result = array();
     foreach ($vehicle_list as $num => $vehicle) {
         $tmp = array("orders" => [["node" => ["longitude" => $orders[0]['lng'], "latitude" => $orders[0]['lat'], 'ids' => "O"], "distance" => 0, "time" => 0]]);
         $listCount = count($vehicle['list']);
         $ttime = 0;
         $tdis = 0;
         for ($ordNum = 1; $ordNum < $listCount; $ordNum++) {
             $orderIndex = $vehicle['list'][$ordNum];
             $preOrderIndex = $vehicle['list'][$ordNum - 1];
             $tmp['orders'][$ordNum]["node"]['longitude'] = $orders[$orderIndex]['lng'];
             $tmp['orders'][$ordNum]["node"]['latitude'] = $orders[$orderIndex]['lat'];
             $tmp['orders'][$ordNum]["node"]['ids'] = $orders[$orderIndex]['ids'];
             //            $tmp['orders'][$ordNum]['distance'] = $distances[$preOrderIndex][$orderIndex];
             //            $tmp['orders'][$ordNum]['time'] = $tmp['orders'][$ordNum]['distance'] / $this->velocity;
             $pathInfo = isset($realPathInfoArray[$preOrderIndex][$orderIndex]) ? $realPathInfoArray[$preOrderIndex][$orderIndex] : MapPoint::getRealDistance($orders[$preOrderIndex], $orders[$orderIndex]);
             $tmp['orders'][$ordNum]['distance'] = floatval($pathInfo['distance']);
             $tmp['orders'][$ordNum]['time'] = intval($pathInfo['time']);
             $ttime += $tmp['orders'][$ordNum]['time'] + $this->getDeliveryTime($orders[$orderIndex]);
             $tdis += $tmp['orders'][$ordNum]['distance'];
         }
         $tmp['tatol_distance'] = $tdis;
         $tmp['tatol_time'] = $ttime;
         $result[] = $tmp;
     }
     return $result;
 }