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; }
/** * 节省法 * $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; }