renamed: Contractor/* -> contractor/*
This commit is contained in:
		
							parent
							
								
									592034653c
								
							
						
					
					
						commit
						7b3a0c5105
					
				| @ -60,7 +60,7 @@ add_library(PHANTOMNODE OBJECT DataStructures/phantom_node.cpp) | |||||||
| set(ExtractorSources extractor.cpp ${ExtractorGlob}) | set(ExtractorSources extractor.cpp ${ExtractorGlob}) | ||||||
| add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>) | add_executable(osrm-extract ${ExtractorSources} $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>) | ||||||
| 
 | 
 | ||||||
| file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/restriction_map.cpp Util/compute_angle.cpp) | file(GLOB PrepareGlob contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/restriction_map.cpp Util/compute_angle.cpp) | ||||||
| set(PrepareSources prepare.cpp ${PrepareGlob}) | set(PrepareSources prepare.cpp ${PrepareGlob}) | ||||||
| add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>) | add_executable(osrm-prepare ${PrepareSources} $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:LOGGER>) | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										973
									
								
								contractor/contractor.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										973
									
								
								contractor/contractor.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,973 @@ | |||||||
|  | /*
 | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2014, Project OSRM, Dennis Luxen, others | ||||||
|  | All rights reserved. | ||||||
|  | 
 | ||||||
|  | Redistribution and use in source and binary forms, with or without modification, | ||||||
|  | are permitted provided that the following conditions are met: | ||||||
|  | 
 | ||||||
|  | Redistributions of source code must retain the above copyright notice, this list | ||||||
|  | of conditions and the following disclaimer. | ||||||
|  | Redistributions in binary form must reproduce the above copyright notice, this | ||||||
|  | list of conditions and the following disclaimer in the documentation and/or | ||||||
|  | other materials provided with the distribution. | ||||||
|  | 
 | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||||
|  | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | ||||||
|  | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||||
|  | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||||||
|  | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||
|  | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||||
|  | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  | 
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef CONTRACTOR_HPP | ||||||
|  | #define CONTRACTOR_HPP | ||||||
|  | 
 | ||||||
|  | #include "../DataStructures/BinaryHeap.h" | ||||||
|  | #include "../DataStructures/DeallocatingVector.h" | ||||||
|  | #include "../DataStructures/DynamicGraph.h" | ||||||
|  | #include "../DataStructures/Percent.h" | ||||||
|  | #include "../DataStructures/QueryEdge.h" | ||||||
|  | #include "../DataStructures/XORFastHash.h" | ||||||
|  | #include "../DataStructures/XORFastHashStorage.h" | ||||||
|  | #include "../Util/integer_range.hpp" | ||||||
|  | #include "../Util/simple_logger.hpp" | ||||||
|  | #include "../Util/StringUtil.h" | ||||||
|  | #include "../Util/TimingUtil.h" | ||||||
|  | #include "../typedefs.h" | ||||||
|  | 
 | ||||||
|  | #include <boost/assert.hpp> | ||||||
|  | 
 | ||||||
|  | #include <stxxl/vector> | ||||||
|  | 
 | ||||||
|  | #include <tbb/enumerable_thread_specific.h> | ||||||
|  | #include <tbb/parallel_for.h> | ||||||
|  | #include <tbb/parallel_sort.h> | ||||||
|  | 
 | ||||||
|  | #include <algorithm> | ||||||
|  | #include <limits> | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | class Contractor | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |   private: | ||||||
|  |     struct ContractorEdgeData | ||||||
|  |     { | ||||||
|  |         ContractorEdgeData() | ||||||
|  |             : distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), | ||||||
|  |               is_original_via_node_ID(false) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |         ContractorEdgeData(unsigned distance, | ||||||
|  |                            unsigned original_edges, | ||||||
|  |                            unsigned id, | ||||||
|  |                            bool shortcut, | ||||||
|  |                            bool forward, | ||||||
|  |                            bool backward) | ||||||
|  |             : distance(distance), id(id), | ||||||
|  |               originalEdges(std::min((unsigned)1 << 28, original_edges)), shortcut(shortcut), | ||||||
|  |               forward(forward), backward(backward), is_original_via_node_ID(false) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |         unsigned distance; | ||||||
|  |         unsigned id; | ||||||
|  |         unsigned originalEdges : 28; | ||||||
|  |         bool shortcut : 1; | ||||||
|  |         bool forward : 1; | ||||||
|  |         bool backward : 1; | ||||||
|  |         bool is_original_via_node_ID : 1; | ||||||
|  |     } data; | ||||||
|  | 
 | ||||||
|  |     struct ContractorHeapData | ||||||
|  |     { | ||||||
|  |         short hop; | ||||||
|  |         bool target; | ||||||
|  |         ContractorHeapData() : hop(0), target(false) {} | ||||||
|  |         ContractorHeapData(short h, bool t) : hop(h), target(t) {} | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     using ContractorGraph = DynamicGraph<ContractorEdgeData>; | ||||||
|  |     //    using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, ArrayStorage<NodeID, NodeID>
 | ||||||
|  |     //    >;
 | ||||||
|  |     using ContractorHeap = BinaryHeap<NodeID, NodeID, int, ContractorHeapData, XORFastHashStorage<NodeID, NodeID>>; | ||||||
|  |     using ContractorEdge = ContractorGraph::InputEdge; | ||||||
|  | 
 | ||||||
|  |     struct ContractorThreadData | ||||||
|  |     { | ||||||
|  |         ContractorHeap heap; | ||||||
|  |         std::vector<ContractorEdge> inserted_edges; | ||||||
|  |         std::vector<NodeID> neighbours; | ||||||
|  |         explicit ContractorThreadData(NodeID nodes) : heap(nodes) {} | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     struct NodePriorityData | ||||||
|  |     { | ||||||
|  |         int depth; | ||||||
|  |         NodePriorityData() : depth(0) {} | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     struct ContractionStats | ||||||
|  |     { | ||||||
|  |         int edges_deleted_count; | ||||||
|  |         int edges_added_count; | ||||||
|  |         int original_edges_deleted_count; | ||||||
|  |         int original_edges_added_count; | ||||||
|  |         ContractionStats() | ||||||
|  |             : edges_deleted_count(0), edges_added_count(0), original_edges_deleted_count(0), | ||||||
|  |               original_edges_added_count(0) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     struct RemainingNodeData | ||||||
|  |     { | ||||||
|  |         RemainingNodeData() : id(0), is_independent(false) {} | ||||||
|  |         NodeID id : 31; | ||||||
|  |         bool is_independent : 1; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     struct ThreadDataContainer | ||||||
|  |     { | ||||||
|  |         explicit ThreadDataContainer(int number_of_nodes) : number_of_nodes(number_of_nodes)  {} | ||||||
|  | 
 | ||||||
|  |         inline ContractorThreadData* getThreadData() | ||||||
|  |         { | ||||||
|  |             bool exists = false; | ||||||
|  |             auto& ref = data.local(exists); | ||||||
|  |             if (!exists) | ||||||
|  |             { | ||||||
|  |                 ref = std::make_shared<ContractorThreadData>(number_of_nodes); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return ref.get(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         int number_of_nodes; | ||||||
|  |         using EnumerableThreadData = tbb::enumerable_thread_specific<std::shared_ptr<ContractorThreadData>>; | ||||||
|  |         EnumerableThreadData data; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |   public: | ||||||
|  |     template <class ContainerT> Contractor(int nodes, ContainerT &input_edge_list) | ||||||
|  |     { | ||||||
|  |         std::vector<ContractorEdge> edges; | ||||||
|  |         edges.reserve(input_edge_list.size() * 2); | ||||||
|  | 
 | ||||||
|  |         const auto dend = input_edge_list.dend(); | ||||||
|  |         for (auto diter = input_edge_list.dbegin(); diter != dend; ++diter) | ||||||
|  |         { | ||||||
|  |             BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(diter->weight, 1)) > 0, "edge distance < 1"); | ||||||
|  | #ifndef NDEBUG | ||||||
|  |             if (static_cast<unsigned int>(std::max(diter->weight, 1)) > 24 * 60 * 60 * 10) | ||||||
|  |             { | ||||||
|  |                 SimpleLogger().Write(logWARNING) << "Edge weight large -> " | ||||||
|  |                                                  << static_cast<unsigned int>(std::max(diter->weight, 1)); | ||||||
|  |             } | ||||||
|  | #endif | ||||||
|  |             edges.emplace_back(diter->source, diter->target, | ||||||
|  |                 static_cast<unsigned int>(std::max(diter->weight, 1)), | ||||||
|  |                 1, | ||||||
|  |                 diter->edge_id, | ||||||
|  |                 false, | ||||||
|  |                 diter->forward ? true : false, | ||||||
|  |                 diter->backward ? true : false); | ||||||
|  | 
 | ||||||
|  |             edges.emplace_back(diter->target, diter->source, | ||||||
|  |                 static_cast<unsigned int>(std::max(diter->weight, 1)), | ||||||
|  |                 1, | ||||||
|  |                 diter->edge_id, | ||||||
|  |                 false, | ||||||
|  |                 diter->backward ? true : false, | ||||||
|  |                 diter->forward ? true : false); | ||||||
|  |         } | ||||||
|  |         // clear input vector
 | ||||||
|  |         input_edge_list.clear(); | ||||||
|  |         edges.shrink_to_fit(); | ||||||
|  | 
 | ||||||
|  |         tbb::parallel_sort(edges.begin(), edges.end()); | ||||||
|  |         NodeID edge = 0; | ||||||
|  |         for (NodeID i = 0; i < edges.size();) | ||||||
|  |         { | ||||||
|  |             const NodeID source = edges[i].source; | ||||||
|  |             const NodeID target = edges[i].target; | ||||||
|  |             const NodeID id = edges[i].data.id; | ||||||
|  |             // remove eigenloops
 | ||||||
|  |             if (source == target) | ||||||
|  |             { | ||||||
|  |                 ++i; | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             ContractorEdge forward_edge; | ||||||
|  |             ContractorEdge reverse_edge; | ||||||
|  |             forward_edge.source = reverse_edge.source = source; | ||||||
|  |             forward_edge.target = reverse_edge.target = target; | ||||||
|  |             forward_edge.data.forward = reverse_edge.data.backward = true; | ||||||
|  |             forward_edge.data.backward = reverse_edge.data.forward = false; | ||||||
|  |             forward_edge.data.shortcut = reverse_edge.data.shortcut = false; | ||||||
|  |             forward_edge.data.id = reverse_edge.data.id = id; | ||||||
|  |             forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1; | ||||||
|  |             forward_edge.data.distance = reverse_edge.data.distance = | ||||||
|  |                 std::numeric_limits<int>::max(); | ||||||
|  |             // remove parallel edges
 | ||||||
|  |             while (i < edges.size() && edges[i].source == source && edges[i].target == target) | ||||||
|  |             { | ||||||
|  |                 if (edges[i].data.forward) | ||||||
|  |                 { | ||||||
|  |                     forward_edge.data.distance = | ||||||
|  |                         std::min(edges[i].data.distance, forward_edge.data.distance); | ||||||
|  |                 } | ||||||
|  |                 if (edges[i].data.backward) | ||||||
|  |                 { | ||||||
|  |                     reverse_edge.data.distance = | ||||||
|  |                         std::min(edges[i].data.distance, reverse_edge.data.distance); | ||||||
|  |                 } | ||||||
|  |                 ++i; | ||||||
|  |             } | ||||||
|  |             // merge edges (s,t) and (t,s) into bidirectional edge
 | ||||||
|  |             if (forward_edge.data.distance == reverse_edge.data.distance) | ||||||
|  |             { | ||||||
|  |                 if ((int)forward_edge.data.distance != std::numeric_limits<int>::max()) | ||||||
|  |                 { | ||||||
|  |                     forward_edge.data.backward = true; | ||||||
|  |                     edges[edge++] = forward_edge; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { // insert seperate edges
 | ||||||
|  |                 if (((int)forward_edge.data.distance) != std::numeric_limits<int>::max()) | ||||||
|  |                 { | ||||||
|  |                     edges[edge++] = forward_edge; | ||||||
|  |                 } | ||||||
|  |                 if ((int)reverse_edge.data.distance != std::numeric_limits<int>::max()) | ||||||
|  |                 { | ||||||
|  |                     edges[edge++] = reverse_edge; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         std::cout << "merged " << edges.size() - edge << " edges out of " << edges.size() | ||||||
|  |                   << std::endl; | ||||||
|  |         edges.resize(edge); | ||||||
|  |         contractor_graph = std::make_shared<ContractorGraph>(nodes, edges); | ||||||
|  |         edges.clear(); | ||||||
|  |         edges.shrink_to_fit(); | ||||||
|  | 
 | ||||||
|  |         BOOST_ASSERT(0 == edges.capacity()); | ||||||
|  |         //        unsigned maxdegree = 0;
 | ||||||
|  |         //        NodeID highestNode = 0;
 | ||||||
|  |         //
 | ||||||
|  |         //        for(unsigned i = 0; i < contractor_graph->GetNumberOfNodes(); ++i) {
 | ||||||
|  |         //            unsigned degree = contractor_graph->EndEdges(i) -
 | ||||||
|  |         //            contractor_graph->BeginEdges(i);
 | ||||||
|  |         //            if(degree > maxdegree) {
 | ||||||
|  |         //                maxdegree = degree;
 | ||||||
|  |         //                highestNode = i;
 | ||||||
|  |         //            }
 | ||||||
|  |         //        }
 | ||||||
|  |         //
 | ||||||
|  |         //        SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree
 | ||||||
|  |         //        " << maxdegree;
 | ||||||
|  |         //        for(unsigned i = contractor_graph->BeginEdges(highestNode); i <
 | ||||||
|  |         //        contractor_graph->EndEdges(highestNode); ++i) {
 | ||||||
|  |         //            SimpleLogger().Write() << " ->(" << highestNode << "," <<
 | ||||||
|  |         //            contractor_graph->GetTarget(i)
 | ||||||
|  |         //            << "); via: " << contractor_graph->GetEdgeData(i).via;
 | ||||||
|  |         //        }
 | ||||||
|  | 
 | ||||||
|  |         std::cout << "contractor finished initalization" << std::endl; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ~Contractor() { } | ||||||
|  | 
 | ||||||
|  |     void Run() | ||||||
|  |     { | ||||||
|  |         // for the preperation we can use a big grain size, which is much faster (probably cache)
 | ||||||
|  |         constexpr size_t InitGrainSize        = 100000; | ||||||
|  |         constexpr size_t PQGrainSize          = 100000; | ||||||
|  |         // auto_partitioner will automatically increase the blocksize if we have
 | ||||||
|  |         // a lot of data. It is *important* for the last loop iterations
 | ||||||
|  |         // (which have a very small dataset) that it is devisible.
 | ||||||
|  |         constexpr size_t IndependentGrainSize = 1; | ||||||
|  |         constexpr size_t ContractGrainSize    = 1; | ||||||
|  |         constexpr size_t NeighboursGrainSize  = 1; | ||||||
|  |         constexpr size_t DeleteGrainSize      = 1; | ||||||
|  | 
 | ||||||
|  |         const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); | ||||||
|  |         Percent p(number_of_nodes); | ||||||
|  | 
 | ||||||
|  |         ThreadDataContainer thread_data_list(number_of_nodes); | ||||||
|  | 
 | ||||||
|  |         NodeID number_of_contracted_nodes = 0; | ||||||
|  |         std::vector<RemainingNodeData> remaining_nodes(number_of_nodes); | ||||||
|  |         std::vector<float> node_priorities(number_of_nodes); | ||||||
|  |         std::vector<NodePriorityData> node_data(number_of_nodes); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         // initialize priorities in parallel
 | ||||||
|  |         tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, InitGrainSize), | ||||||
|  |             [&remaining_nodes](const tbb::blocked_range<int>& range) | ||||||
|  |             { | ||||||
|  |                 for (int x = range.begin(); x != range.end(); ++x) | ||||||
|  |                 { | ||||||
|  |                     remaining_nodes[x].id = x; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         std::cout << "initializing elimination PQ ..." << std::flush; | ||||||
|  |         tbb::parallel_for(tbb::blocked_range<int>(0, number_of_nodes, PQGrainSize), | ||||||
|  |             [this, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range) | ||||||
|  |             { | ||||||
|  |                 ContractorThreadData *data = thread_data_list.getThreadData(); | ||||||
|  |                 for (int x = range.begin(); x != range.end(); ++x) | ||||||
|  |                 { | ||||||
|  |                     node_priorities[x] = this->EvaluateNodePriority(data, &node_data[x], x); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         ); | ||||||
|  |         std::cout << "ok" << std::endl << "preprocessing " << number_of_nodes << " nodes ..." | ||||||
|  |                   << std::flush; | ||||||
|  | 
 | ||||||
|  |         bool flushed_contractor = false; | ||||||
|  |         while (number_of_nodes > 2 && number_of_contracted_nodes < number_of_nodes) | ||||||
|  |         { | ||||||
|  |             if (!flushed_contractor && (number_of_contracted_nodes > (number_of_nodes * 0.65))) | ||||||
|  |             { | ||||||
|  |                 DeallocatingVector<ContractorEdge> new_edge_set; // this one is not explicitely
 | ||||||
|  |                                                                  // cleared since it goes out of
 | ||||||
|  |                                                                  // scope anywa
 | ||||||
|  |                 std::cout << " [flush " << number_of_contracted_nodes << " nodes] " << std::flush; | ||||||
|  | 
 | ||||||
|  |                 // Delete old heap data to free memory that we need for the coming operations
 | ||||||
|  |                 thread_data_list.data.clear(); | ||||||
|  | 
 | ||||||
|  |                 // Create new priority array
 | ||||||
|  |                 std::vector<float> new_node_priority(remaining_nodes.size()); | ||||||
|  |                 // this map gives the old IDs from the new ones, necessary to get a consistent graph
 | ||||||
|  |                 // at the end of contraction
 | ||||||
|  |                 orig_node_id_to_new_id_map.resize(remaining_nodes.size()); | ||||||
|  |                 // this map gives the new IDs from the old ones, necessary to remap targets from the
 | ||||||
|  |                 // remaining graph
 | ||||||
|  |                 std::vector<NodeID> new_node_id_from_orig_id_map(number_of_nodes, UINT_MAX); | ||||||
|  | 
 | ||||||
|  |                 // build forward and backward renumbering map and remap ids in remaining_nodes and
 | ||||||
|  |                 // Priorities.
 | ||||||
|  |                 for (const auto new_node_id : osrm::irange<std::size_t>(0, remaining_nodes.size())) | ||||||
|  |                 { | ||||||
|  |                     // create renumbering maps in both directions
 | ||||||
|  |                     orig_node_id_to_new_id_map[new_node_id] = remaining_nodes[new_node_id].id; | ||||||
|  |                     new_node_id_from_orig_id_map[remaining_nodes[new_node_id].id] = new_node_id; | ||||||
|  |                     new_node_priority[new_node_id] = | ||||||
|  |                         node_priorities[remaining_nodes[new_node_id].id]; | ||||||
|  |                     remaining_nodes[new_node_id].id = new_node_id; | ||||||
|  |                 } | ||||||
|  |                 // walk over all nodes
 | ||||||
|  |                 for (const auto i : osrm::irange<std::size_t>(0, contractor_graph->GetNumberOfNodes())) | ||||||
|  |                 { | ||||||
|  |                     const NodeID source = i; | ||||||
|  |                     for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source)) | ||||||
|  |                     { | ||||||
|  |                         ContractorGraph::EdgeData &data = | ||||||
|  |                             contractor_graph->GetEdgeData(current_edge); | ||||||
|  |                         const NodeID target = contractor_graph->GetTarget(current_edge); | ||||||
|  |                         if (SPECIAL_NODEID == new_node_id_from_orig_id_map[i]) | ||||||
|  |                         { | ||||||
|  |                             external_edge_list.push_back({source, target, data}); | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             // node is not yet contracted.
 | ||||||
|  |                             // add (renumbered) outgoing edges to new DynamicGraph.
 | ||||||
|  |                             ContractorEdge new_edge = { | ||||||
|  |                                 new_node_id_from_orig_id_map[source], | ||||||
|  |                                 new_node_id_from_orig_id_map[target], | ||||||
|  |                                 data | ||||||
|  |                             }; | ||||||
|  | 
 | ||||||
|  |                             new_edge.data.is_original_via_node_ID = true; | ||||||
|  |                             BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[source], | ||||||
|  |                                              "new source id not resolveable"); | ||||||
|  |                             BOOST_ASSERT_MSG(UINT_MAX != new_node_id_from_orig_id_map[target], | ||||||
|  |                                              "new target id not resolveable"); | ||||||
|  |                             new_edge_set.push_back(new_edge); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 // Delete map from old NodeIDs to new ones.
 | ||||||
|  |                 new_node_id_from_orig_id_map.clear(); | ||||||
|  |                 new_node_id_from_orig_id_map.shrink_to_fit(); | ||||||
|  | 
 | ||||||
|  |                 // Replace old priorities array by new one
 | ||||||
|  |                 node_priorities.swap(new_node_priority); | ||||||
|  |                 // Delete old node_priorities vector
 | ||||||
|  |                 new_node_priority.clear(); | ||||||
|  |                 new_node_priority.shrink_to_fit(); | ||||||
|  |                 // old Graph is removed
 | ||||||
|  |                 contractor_graph.reset(); | ||||||
|  | 
 | ||||||
|  |                 // create new graph
 | ||||||
|  |                 std::sort(new_edge_set.begin(), new_edge_set.end()); | ||||||
|  |                 contractor_graph = | ||||||
|  |                     std::make_shared<ContractorGraph>(remaining_nodes.size(), new_edge_set); | ||||||
|  | 
 | ||||||
|  |                 new_edge_set.clear(); | ||||||
|  |                 flushed_contractor = true; | ||||||
|  | 
 | ||||||
|  |                 // INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
 | ||||||
|  |                 // reinitialize heaps and ThreadData objects with appropriate size
 | ||||||
|  |                 thread_data_list.number_of_nodes = contractor_graph->GetNumberOfNodes(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             const int last = (int)remaining_nodes.size(); | ||||||
|  |             tbb::parallel_for(tbb::blocked_range<int>(0, last, IndependentGrainSize), | ||||||
|  |                 [this, &node_priorities, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range) | ||||||
|  |                 { | ||||||
|  |                     ContractorThreadData *data = thread_data_list.getThreadData(); | ||||||
|  |                     // determine independent node set
 | ||||||
|  |                     for (int i = range.begin(); i != range.end(); ++i) | ||||||
|  |                     { | ||||||
|  |                         const NodeID node = remaining_nodes[i].id; | ||||||
|  |                         remaining_nodes[i].is_independent = | ||||||
|  |                             this->IsNodeIndependent(node_priorities, data, node); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             const auto first = stable_partition(remaining_nodes.begin(), | ||||||
|  |                                                 remaining_nodes.end(), | ||||||
|  |                                                 [](RemainingNodeData node_data) | ||||||
|  |                                                 { return !node_data.is_independent; }); | ||||||
|  |             const int first_independent_node = static_cast<int>(first - remaining_nodes.begin()); | ||||||
|  | 
 | ||||||
|  |             // contract independent nodes
 | ||||||
|  |             tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, ContractGrainSize), | ||||||
|  |                 [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range) | ||||||
|  |                 { | ||||||
|  |                     ContractorThreadData *data = thread_data_list.getThreadData(); | ||||||
|  |                     for (int position = range.begin(); position != range.end(); ++position) | ||||||
|  |                     { | ||||||
|  |                         const NodeID x = remaining_nodes[position].id; | ||||||
|  |                         this->ContractNode<false>(data, x); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             ); | ||||||
|  |             // make sure we really sort each block
 | ||||||
|  |             tbb::parallel_for(thread_data_list.data.range(), | ||||||
|  |                 [&](const ThreadDataContainer::EnumerableThreadData::range_type& range) | ||||||
|  |                 { | ||||||
|  |                     for (auto& data : range) | ||||||
|  |                         std::sort(data->inserted_edges.begin(), | ||||||
|  |                                   data->inserted_edges.end()); | ||||||
|  |                 } | ||||||
|  |             ); | ||||||
|  |             tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, DeleteGrainSize), | ||||||
|  |                 [this, &remaining_nodes, &thread_data_list](const tbb::blocked_range<int>& range) | ||||||
|  |                 { | ||||||
|  |                     ContractorThreadData *data = thread_data_list.getThreadData(); | ||||||
|  |                     for (int position = range.begin(); position != range.end(); ++position) | ||||||
|  |                     { | ||||||
|  |                         const NodeID x = remaining_nodes[position].id; | ||||||
|  |                         this->DeleteIncomingEdges(data, x); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             // insert new edges
 | ||||||
|  |             for (auto& data : thread_data_list.data) | ||||||
|  |             { | ||||||
|  |                 for (const ContractorEdge &edge : data->inserted_edges) | ||||||
|  |                 { | ||||||
|  |                     const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target); | ||||||
|  |                     if (current_edge_ID < contractor_graph->EndEdges(edge.source)) | ||||||
|  |                     { | ||||||
|  |                         ContractorGraph::EdgeData ¤t_data = | ||||||
|  |                             contractor_graph->GetEdgeData(current_edge_ID); | ||||||
|  |                         if (current_data.shortcut && edge.data.forward == current_data.forward && | ||||||
|  |                             edge.data.backward == current_data.backward && | ||||||
|  |                             edge.data.distance < current_data.distance) | ||||||
|  |                         { | ||||||
|  |                             // found a duplicate edge with smaller weight, update it.
 | ||||||
|  |                             current_data = edge.data; | ||||||
|  |                             continue; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     contractor_graph->InsertEdge(edge.source, edge.target, edge.data); | ||||||
|  |                 } | ||||||
|  |                 data->inserted_edges.clear(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             tbb::parallel_for(tbb::blocked_range<int>(first_independent_node, last, NeighboursGrainSize), | ||||||
|  |                 [this, &remaining_nodes, &node_priorities, &node_data, &thread_data_list](const tbb::blocked_range<int>& range) | ||||||
|  |                 { | ||||||
|  |                     ContractorThreadData *data = thread_data_list.getThreadData(); | ||||||
|  |                     for (int position = range.begin(); position != range.end(); ++position) | ||||||
|  |                     { | ||||||
|  |                         NodeID x = remaining_nodes[position].id; | ||||||
|  |                         this->UpdateNodeNeighbours(node_priorities, node_data, data, x); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             // remove contracted nodes from the pool
 | ||||||
|  |             number_of_contracted_nodes += last - first_independent_node; | ||||||
|  |             remaining_nodes.resize(first_independent_node); | ||||||
|  |             remaining_nodes.shrink_to_fit(); | ||||||
|  |             //            unsigned maxdegree = 0;
 | ||||||
|  |             //            unsigned avgdegree = 0;
 | ||||||
|  |             //            unsigned mindegree = UINT_MAX;
 | ||||||
|  |             //            unsigned quaddegree = 0;
 | ||||||
|  |             //
 | ||||||
|  |             //            for(unsigned i = 0; i < remaining_nodes.size(); ++i) {
 | ||||||
|  |             //                unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].first)
 | ||||||
|  |             //                -
 | ||||||
|  |             //                contractor_graph->BeginEdges(remaining_nodes[i].first);
 | ||||||
|  |             //                if(degree > maxdegree)
 | ||||||
|  |             //                    maxdegree = degree;
 | ||||||
|  |             //                if(degree < mindegree)
 | ||||||
|  |             //                    mindegree = degree;
 | ||||||
|  |             //
 | ||||||
|  |             //                avgdegree += degree;
 | ||||||
|  |             //                quaddegree += (degree*degree);
 | ||||||
|  |             //            }
 | ||||||
|  |             //
 | ||||||
|  |             //            avgdegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
 | ||||||
|  |             //            quaddegree /= std::max((unsigned)1,(unsigned)remaining_nodes.size() );
 | ||||||
|  |             //
 | ||||||
|  |             //            SimpleLogger().Write() << "rest: " << remaining_nodes.size() << ", max: "
 | ||||||
|  |             //            << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ",
 | ||||||
|  |             //            quad: " << quaddegree;
 | ||||||
|  | 
 | ||||||
|  |             p.printStatus(number_of_contracted_nodes); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         thread_data_list.data.clear(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     template <class Edge> inline void GetEdges(DeallocatingVector<Edge> &edges) | ||||||
|  |     { | ||||||
|  |         Percent p(contractor_graph->GetNumberOfNodes()); | ||||||
|  |         SimpleLogger().Write() << "Getting edges of minimized graph"; | ||||||
|  |         const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes(); | ||||||
|  |         if (contractor_graph->GetNumberOfNodes()) | ||||||
|  |         { | ||||||
|  |             Edge new_edge; | ||||||
|  |             for (const auto node : osrm::irange(0u, number_of_nodes)) | ||||||
|  |             { | ||||||
|  |                 p.printStatus(node); | ||||||
|  |                 for (auto edge : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |                 { | ||||||
|  |                     const NodeID target = contractor_graph->GetTarget(edge); | ||||||
|  |                     const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge); | ||||||
|  |                     if (!orig_node_id_to_new_id_map.empty()) | ||||||
|  |                     { | ||||||
|  |                         new_edge.source = orig_node_id_to_new_id_map[node]; | ||||||
|  |                         new_edge.target = orig_node_id_to_new_id_map[target]; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         new_edge.source = node; | ||||||
|  |                         new_edge.target = target; | ||||||
|  |                     } | ||||||
|  |                     BOOST_ASSERT_MSG(UINT_MAX != new_edge.source, "Source id invalid"); | ||||||
|  |                     BOOST_ASSERT_MSG(UINT_MAX != new_edge.target, "Target id invalid"); | ||||||
|  |                     new_edge.data.distance = data.distance; | ||||||
|  |                     new_edge.data.shortcut = data.shortcut; | ||||||
|  |                     if (!data.is_original_via_node_ID && !orig_node_id_to_new_id_map.empty()) | ||||||
|  |                     { | ||||||
|  |                         new_edge.data.id = orig_node_id_to_new_id_map[data.id]; | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         new_edge.data.id = data.id; | ||||||
|  |                     } | ||||||
|  |                     BOOST_ASSERT_MSG(new_edge.data.id != INT_MAX, // 2^31
 | ||||||
|  |                                      "edge id invalid"); | ||||||
|  |                     new_edge.data.forward = data.forward; | ||||||
|  |                     new_edge.data.backward = data.backward; | ||||||
|  |                     edges.push_back(new_edge); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         contractor_graph.reset(); | ||||||
|  |         orig_node_id_to_new_id_map.clear(); | ||||||
|  |         orig_node_id_to_new_id_map.shrink_to_fit(); | ||||||
|  | 
 | ||||||
|  |         BOOST_ASSERT(0 == orig_node_id_to_new_id_map.capacity()); | ||||||
|  | 
 | ||||||
|  |         edges.append(external_edge_list.begin(), external_edge_list.end()); | ||||||
|  |         external_edge_list.clear(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   private: | ||||||
|  |     inline void Dijkstra(const int max_distance, | ||||||
|  |                          const unsigned number_of_targets, | ||||||
|  |                          const int maxNodes, | ||||||
|  |                          ContractorThreadData *const data, | ||||||
|  |                          const NodeID middleNode) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         ContractorHeap &heap = data->heap; | ||||||
|  | 
 | ||||||
|  |         int nodes = 0; | ||||||
|  |         unsigned number_of_targets_found = 0; | ||||||
|  |         while (!heap.Empty()) | ||||||
|  |         { | ||||||
|  |             const NodeID node = heap.DeleteMin(); | ||||||
|  |             const int distance = heap.GetKey(node); | ||||||
|  |             const short current_hop = heap.GetData(node).hop + 1; | ||||||
|  | 
 | ||||||
|  |             if (++nodes > maxNodes) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             if (distance > max_distance) | ||||||
|  |             { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Destination settled?
 | ||||||
|  |             if (heap.GetData(node).target) | ||||||
|  |             { | ||||||
|  |                 ++number_of_targets_found; | ||||||
|  |                 if (number_of_targets_found >= number_of_targets) | ||||||
|  |                 { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // iterate over all edges of node
 | ||||||
|  |             for (auto edge : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |             { | ||||||
|  |                 const ContractorEdgeData &data = contractor_graph->GetEdgeData(edge); | ||||||
|  |                 if (!data.forward) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 const NodeID to = contractor_graph->GetTarget(edge); | ||||||
|  |                 if (middleNode == to) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 const int to_distance = distance + data.distance; | ||||||
|  | 
 | ||||||
|  |                 // New Node discovered -> Add to Heap + Node Info Storage
 | ||||||
|  |                 if (!heap.WasInserted(to)) | ||||||
|  |                 { | ||||||
|  |                     heap.Insert(to, to_distance, ContractorHeapData(current_hop, false)); | ||||||
|  |                 } | ||||||
|  |                 // Found a shorter Path -> Update distance
 | ||||||
|  |                 else if (to_distance < heap.GetKey(to)) | ||||||
|  |                 { | ||||||
|  |                     heap.DecreaseKey(to, to_distance); | ||||||
|  |                     heap.GetData(to).hop = current_hop; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline float EvaluateNodePriority(ContractorThreadData *const data, | ||||||
|  |                                       NodePriorityData *const node_data, | ||||||
|  |                                       const NodeID node) | ||||||
|  |     { | ||||||
|  |         ContractionStats stats; | ||||||
|  | 
 | ||||||
|  |         // perform simulated contraction
 | ||||||
|  |         ContractNode<true>(data, node, &stats); | ||||||
|  | 
 | ||||||
|  |         // Result will contain the priority
 | ||||||
|  |         float result; | ||||||
|  |         if (0 == (stats.edges_deleted_count * stats.original_edges_deleted_count)) | ||||||
|  |         { | ||||||
|  |             result = 1.f * node_data->depth; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             result = 2.f * (((float)stats.edges_added_count) / stats.edges_deleted_count) + | ||||||
|  |                      4.f * (((float)stats.original_edges_added_count) / | ||||||
|  |                             stats.original_edges_deleted_count) + | ||||||
|  |                      1.f * node_data->depth; | ||||||
|  |         } | ||||||
|  |         BOOST_ASSERT(result >= 0); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     template <bool RUNSIMULATION> | ||||||
|  |     inline bool | ||||||
|  |     ContractNode(ContractorThreadData *data, const NodeID node, ContractionStats *stats = nullptr) | ||||||
|  |     { | ||||||
|  |         ContractorHeap &heap = data->heap; | ||||||
|  |         int inserted_edges_size = data->inserted_edges.size(); | ||||||
|  |         std::vector<ContractorEdge> &inserted_edges = data->inserted_edges; | ||||||
|  | 
 | ||||||
|  |         for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |         { | ||||||
|  |             const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge); | ||||||
|  |             const NodeID source = contractor_graph->GetTarget(in_edge); | ||||||
|  |             if (RUNSIMULATION) | ||||||
|  |             { | ||||||
|  |                 BOOST_ASSERT(stats != nullptr); | ||||||
|  |                 ++stats->edges_deleted_count; | ||||||
|  |                 stats->original_edges_deleted_count += in_data.originalEdges; | ||||||
|  |             } | ||||||
|  |             if (!in_data.backward) | ||||||
|  |             { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             heap.Clear(); | ||||||
|  |             heap.Insert(source, 0, ContractorHeapData()); | ||||||
|  |             int max_distance = 0; | ||||||
|  |             unsigned number_of_targets = 0; | ||||||
|  | 
 | ||||||
|  |             for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |             { | ||||||
|  |                 const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); | ||||||
|  |                 if (!out_data.forward) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 const NodeID target = contractor_graph->GetTarget(out_edge); | ||||||
|  |                 const int path_distance = in_data.distance + out_data.distance; | ||||||
|  |                 max_distance = std::max(max_distance, path_distance); | ||||||
|  |                 if (!heap.WasInserted(target)) | ||||||
|  |                 { | ||||||
|  |                     heap.Insert(target, INT_MAX, ContractorHeapData(0, true)); | ||||||
|  |                     ++number_of_targets; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (RUNSIMULATION) | ||||||
|  |             { | ||||||
|  |                 Dijkstra(max_distance, number_of_targets, 1000, data, node); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 Dijkstra(max_distance, number_of_targets, 2000, data, node); | ||||||
|  |             } | ||||||
|  |             for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |             { | ||||||
|  |                 const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge); | ||||||
|  |                 if (!out_data.forward) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 const NodeID target = contractor_graph->GetTarget(out_edge); | ||||||
|  |                 const int path_distance = in_data.distance + out_data.distance; | ||||||
|  |                 const int distance = heap.GetKey(target); | ||||||
|  |                 if (path_distance < distance) | ||||||
|  |                 { | ||||||
|  |                     if (RUNSIMULATION) | ||||||
|  |                     { | ||||||
|  |                         BOOST_ASSERT(stats != nullptr); | ||||||
|  |                         stats->edges_added_count += 2; | ||||||
|  |                         stats->original_edges_added_count += | ||||||
|  |                             2 * (out_data.originalEdges + in_data.originalEdges); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         inserted_edges.emplace_back(source, target, path_distance, | ||||||
|  |                                                     out_data.originalEdges + in_data.originalEdges, | ||||||
|  |                                                     node, | ||||||
|  |                                                     true, | ||||||
|  |                                                     true, | ||||||
|  |                                                     false); | ||||||
|  | 
 | ||||||
|  |                         inserted_edges.emplace_back(target, source, path_distance, | ||||||
|  |                                                     out_data.originalEdges + in_data.originalEdges, | ||||||
|  |                                                     node, | ||||||
|  |                                                     true, | ||||||
|  |                                                     false, | ||||||
|  |                                                     true); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (!RUNSIMULATION) | ||||||
|  |         { | ||||||
|  |             int iend = inserted_edges.size(); | ||||||
|  |             for (int i = inserted_edges_size; i < iend; ++i) | ||||||
|  |             { | ||||||
|  |                 bool found = false; | ||||||
|  |                 for (int other = i + 1; other < iend; ++other) | ||||||
|  |                 { | ||||||
|  |                     if (inserted_edges[other].source != inserted_edges[i].source) | ||||||
|  |                     { | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |                     if (inserted_edges[other].target != inserted_edges[i].target) | ||||||
|  |                     { | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |                     if (inserted_edges[other].data.distance != inserted_edges[i].data.distance) | ||||||
|  |                     { | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |                     if (inserted_edges[other].data.shortcut != inserted_edges[i].data.shortcut) | ||||||
|  |                     { | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |                     inserted_edges[other].data.forward |= inserted_edges[i].data.forward; | ||||||
|  |                     inserted_edges[other].data.backward |= inserted_edges[i].data.backward; | ||||||
|  |                     found = true; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 if (!found) | ||||||
|  |                 { | ||||||
|  |                     inserted_edges[inserted_edges_size++] = inserted_edges[i]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             inserted_edges.resize(inserted_edges_size); | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline void DeleteIncomingEdges(ContractorThreadData *data, const NodeID node) | ||||||
|  |     { | ||||||
|  |         std::vector<NodeID> &neighbours = data->neighbours; | ||||||
|  |         neighbours.clear(); | ||||||
|  | 
 | ||||||
|  |         // find all neighbours
 | ||||||
|  |         for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |         { | ||||||
|  |             const NodeID u = contractor_graph->GetTarget(e); | ||||||
|  |             if (u != node) | ||||||
|  |             { | ||||||
|  |                 neighbours.push_back(u); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         // eliminate duplicate entries ( forward + backward edges )
 | ||||||
|  |         std::sort(neighbours.begin(), neighbours.end()); | ||||||
|  |         neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); | ||||||
|  | 
 | ||||||
|  |         for (const auto i : osrm::irange<std::size_t>(0, neighbours.size())) | ||||||
|  |         { | ||||||
|  |             contractor_graph->DeleteEdgesTo(neighbours[i], node); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline bool UpdateNodeNeighbours(std::vector<float> &priorities, | ||||||
|  |                                      std::vector<NodePriorityData> &node_data, | ||||||
|  |                                      ContractorThreadData *const data, | ||||||
|  |                                      const NodeID node) | ||||||
|  |     { | ||||||
|  |         std::vector<NodeID> &neighbours = data->neighbours; | ||||||
|  |         neighbours.clear(); | ||||||
|  | 
 | ||||||
|  |         // find all neighbours
 | ||||||
|  |         for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |         { | ||||||
|  |             const NodeID u = contractor_graph->GetTarget(e); | ||||||
|  |             if (u == node) | ||||||
|  |             { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             neighbours.push_back(u); | ||||||
|  |             node_data[u].depth = (std::max)(node_data[node].depth + 1, node_data[u].depth); | ||||||
|  |         } | ||||||
|  |         // eliminate duplicate entries ( forward + backward edges )
 | ||||||
|  |         std::sort(neighbours.begin(), neighbours.end()); | ||||||
|  |         neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); | ||||||
|  | 
 | ||||||
|  |         // re-evaluate priorities of neighboring nodes
 | ||||||
|  |         for (const NodeID u : neighbours) | ||||||
|  |         { | ||||||
|  |             priorities[u] = EvaluateNodePriority(data, &(node_data)[u], u); | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     inline bool IsNodeIndependent( | ||||||
|  |         const std::vector<float> &priorities, | ||||||
|  |         ContractorThreadData *const data, | ||||||
|  |         NodeID node) const | ||||||
|  |     { | ||||||
|  |         const float priority = priorities[node]; | ||||||
|  | 
 | ||||||
|  |         std::vector<NodeID> &neighbours = data->neighbours; | ||||||
|  |         neighbours.clear(); | ||||||
|  | 
 | ||||||
|  |         for (auto e : contractor_graph->GetAdjacentEdgeRange(node)) | ||||||
|  |         { | ||||||
|  |             const NodeID target = contractor_graph->GetTarget(e); | ||||||
|  |             if (node == target) | ||||||
|  |             { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             const float target_priority = priorities[target]; | ||||||
|  |             BOOST_ASSERT(target_priority >= 0); | ||||||
|  |             // found a neighbour with lower priority?
 | ||||||
|  |             if (priority > target_priority) | ||||||
|  |             { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             // tie breaking
 | ||||||
|  |             if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() && | ||||||
|  |                 bias(node, target)) | ||||||
|  |             { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             neighbours.push_back(target); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         std::sort(neighbours.begin(), neighbours.end()); | ||||||
|  |         neighbours.resize(std::unique(neighbours.begin(), neighbours.end()) - neighbours.begin()); | ||||||
|  | 
 | ||||||
|  |         // examine all neighbours that are at most 2 hops away
 | ||||||
|  |         for (const NodeID u : neighbours) | ||||||
|  |         { | ||||||
|  |             for (auto e : contractor_graph->GetAdjacentEdgeRange(u)) | ||||||
|  |             { | ||||||
|  |                 const NodeID target = contractor_graph->GetTarget(e); | ||||||
|  |                 if (node == target) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 const float target_priority = priorities[target]; | ||||||
|  |                 BOOST_ASSERT(target_priority >= 0); | ||||||
|  |                 // found a neighbour with lower priority?
 | ||||||
|  |                 if (priority > target_priority) | ||||||
|  |                 { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 // tie breaking
 | ||||||
|  |                 if (std::abs(priority - target_priority) < std::numeric_limits<float>::epsilon() && | ||||||
|  |                     bias(node, target)) | ||||||
|  |                 { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // This bias function takes up 22 assembly instructions in total on X86
 | ||||||
|  |     inline bool bias(const NodeID a, const NodeID b) const | ||||||
|  |     { | ||||||
|  |         const unsigned short hasha = fast_hash(a); | ||||||
|  |         const unsigned short hashb = fast_hash(b); | ||||||
|  | 
 | ||||||
|  |         // The compiler optimizes that to conditional register flags but without branching
 | ||||||
|  |         // statements!
 | ||||||
|  |         if (hasha != hashb) | ||||||
|  |         { | ||||||
|  |             return hasha < hashb; | ||||||
|  |         } | ||||||
|  |         return a < b; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::shared_ptr<ContractorGraph> contractor_graph; | ||||||
|  |     std::vector<ContractorGraph::InputEdge> contracted_edge_list; | ||||||
|  |     stxxl::vector<QueryEdge> external_edge_list; | ||||||
|  |     std::vector<NodeID> orig_node_id_to_new_id_map; | ||||||
|  |     XORFastHash fast_hash; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif // CONTRACTOR_HPP
 | ||||||
| @ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| 
 | 
 | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #include "EdgeBasedGraphFactory.h" | #include "edge_based_graph_factory.hpp" | ||||||
| #include "../algorithms/bfs_components.hpp" | #include "../algorithms/bfs_components.hpp" | ||||||
| #include "../DataStructures/Percent.h" | #include "../DataStructures/Percent.h" | ||||||
| #include "../Util/compute_angle.hpp" | #include "../Util/compute_angle.hpp" | ||||||
| @ -27,9 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| 
 | 
 | ||||||
| //  This class constructs the edge-expanded routing graph
 | //  This class constructs the edge-expanded routing graph
 | ||||||
| 
 | 
 | ||||||
| #ifndef EDGEBASEDGRAPHFACTORY_H_ | #ifndef EDGE_BASED_GRAPH_FACTORY_HPP_ | ||||||
| #define EDGEBASEDGRAPHFACTORY_H_ | #define EDGE_BASED_GRAPH_FACTORY_HPP_ | ||||||
| 
 | 
 | ||||||
|  | #include "geometry_compressor.hpp" | ||||||
| #include "../typedefs.h" | #include "../typedefs.h" | ||||||
| #include "../DataStructures/DeallocatingVector.h" | #include "../DataStructures/DeallocatingVector.h" | ||||||
| #include "../DataStructures/EdgeBasedNode.h" | #include "../DataStructures/EdgeBasedNode.h" | ||||||
| @ -38,7 +39,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| #include "../DataStructures/TurnInstructions.h" | #include "../DataStructures/TurnInstructions.h" | ||||||
| #include "../DataStructures/NodeBasedGraph.h" | #include "../DataStructures/NodeBasedGraph.h" | ||||||
| #include "../DataStructures/restriction_map.hpp" | #include "../DataStructures/restriction_map.hpp" | ||||||
| #include "GeometryCompressor.h" |  | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <iosfwd> | #include <iosfwd> | ||||||
| @ -123,4 +123,4 @@ class EdgeBasedGraphFactory | |||||||
|     NodeID max_id; |     NodeID max_id; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif /* EDGEBASEDGRAPHFACTORY_H_ */ | #endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */ | ||||||
| @ -1,6 +1,6 @@ | |||||||
| /*
 | /*
 | ||||||
| 
 | 
 | ||||||
| Copyright (c) 2013, Project OSRM, Dennis Luxen, others | Copyright (c) 2014, Project OSRM, Dennis Luxen, others | ||||||
| All rights reserved. | All rights reserved. | ||||||
| 
 | 
 | ||||||
| Redistribution and use in source and binary forms, with or without modification, | Redistribution and use in source and binary forms, with or without modification, | ||||||
| @ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| 
 | 
 | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #include "GeometryCompressor.h" | #include "geometry_compressor.hpp" | ||||||
| #include "../Util/simple_logger.hpp" | #include "../Util/simple_logger.hpp" | ||||||
| 
 | 
 | ||||||
| #include <boost/assert.hpp> | #include <boost/assert.hpp> | ||||||
| @ -1,6 +1,6 @@ | |||||||
| /*
 | /*
 | ||||||
| 
 | 
 | ||||||
| Copyright (c) 2013, Project OSRM, Dennis Luxen, others | Copyright (c) 2014, Project OSRM, Dennis Luxen, others | ||||||
| All rights reserved. | All rights reserved. | ||||||
| 
 | 
 | ||||||
| Redistribution and use in source and binary forms, with or without modification, | Redistribution and use in source and binary forms, with or without modification, | ||||||
| @ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| 
 | 
 | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #ifndef GEOMETRY_COMPRESSOR_H | #ifndef GEOMETRY_COMPRESSOR_HPP_ | ||||||
| #define GEOMETRY_COMPRESSOR_H | #define GEOMETRY_COMPRESSOR_HPP_ | ||||||
| 
 | 
 | ||||||
| #include "../typedefs.h" | #include "../typedefs.h" | ||||||
| 
 | 
 | ||||||
| @ -64,4 +64,4 @@ class GeometryCompressor | |||||||
|     std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map; |     std::unordered_map<EdgeID, unsigned> m_edge_id_to_list_index_map; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #endif // GEOMETRY_COMPRESSOR_H
 | #endif // GEOMETRY_COMPRESSOR_HPP_
 | ||||||
| @ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| 
 | 
 | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #include "Prepare.h" | #include "processing_chain.hpp" | ||||||
| 
 | 
 | ||||||
| #include "contractor.hpp" | #include "contractor.hpp" | ||||||
| 
 | 
 | ||||||
| @ -1,7 +1,7 @@ | |||||||
| #ifndef PREPARE_H | #ifndef PREPARE_H | ||||||
| #define PREPARE_H | #define PREPARE_H | ||||||
| 
 | 
 | ||||||
| #include "EdgeBasedGraphFactory.h" | #include "edge_based_graph_factory.hpp" | ||||||
| #include "../DataStructures/QueryEdge.h" | #include "../DataStructures/QueryEdge.h" | ||||||
| #include "../DataStructures/StaticGraph.h" | #include "../DataStructures/StaticGraph.h" | ||||||
| class FingerPrint; | class FingerPrint; | ||||||
| @ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||||
| 
 | 
 | ||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| #include "Contractor/Prepare.h" | #include "contractor/processing_chain.hpp" | ||||||
| 
 | 
 | ||||||
| #include <boost/program_options.hpp> | #include <boost/program_options.hpp> | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user