Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[not ready] Add flag to only partially contract graph #1582

Merged
merged 1 commit into from
Aug 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions contractor/contractor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class Contractor

~Contractor() {}

void Run()
void Run( double core_factor = 1.0 )
{
// for the preperation we can use a big grain size, which is much faster (probably cache)
constexpr size_t InitGrainSize = 100000;
Expand Down Expand Up @@ -333,9 +333,9 @@ class Contractor
<< std::flush;

bool flushed_contractor = false;
while (number_of_nodes > 2 && number_of_contracted_nodes < number_of_nodes)
while (number_of_nodes > 2 && number_of_contracted_nodes < static_cast<NodeID>(number_of_nodes * core_factor) )
{
if (!flushed_contractor && (number_of_contracted_nodes > (number_of_nodes * 0.65)))
if (!flushed_contractor && (number_of_contracted_nodes > static_cast<NodeID>(number_of_nodes * 0.65 * core_factor)))
{
DeallocatingVector<ContractorEdge> new_edge_set; // this one is not explicitely
// cleared since it goes out of
Expand Down Expand Up @@ -524,7 +524,7 @@ class Contractor
// unsigned quaddegree = 0;
//
// for(unsigned i = 0; i < remaining_nodes.size(); ++i) {
// unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].first)
// unsigned degree = contractor_graph->EndEdges(remaining_nodes[i].id)
// -
// contractor_graph->BeginEdges(remaining_nodes[i].first);
// if(degree > maxdegree)
Expand All @@ -546,6 +546,8 @@ class Contractor
p.printStatus(number_of_contracted_nodes);
}

SimpleLogger().Write() << "[core] " << remaining_nodes.size() << " nodes " << contractor_graph->GetNumberOfEdges() << " edges." << std::endl;

thread_data_list.data.clear();
}

Expand Down
6 changes: 5 additions & 1 deletion contractor/contractor_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ ContractorOptions::ParseArguments(int argc, char *argv[], ContractorConfig &cont
"Path to LUA routing profile")(
"threads,t", boost::program_options::value<unsigned int>(&contractor_config.requested_num_threads)
->default_value(tbb::task_scheduler_init::default_num_threads()),
"Number of threads to use");
"Number of threads to use")(
"core,k", boost::program_options::value<double>(&contractor_config.core_factor)
->default_value(1.0),"Percentage of the graph (in vertices) to contract [0.1]");



// hidden options, will be allowed both on command line and in config file, but will not be
// shown to the user
Expand Down
6 changes: 6 additions & 0 deletions contractor/contractor_options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ struct ContractorConfig
std::string rtree_leafs_output_path;

unsigned requested_num_threads;

//A percentage of vertices that will be contracted for the hierarchy.
//Offers a trade-off between preprocessing and query time.
//The remaining vertices form the core of the hierarchy
//(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%)
double core_factor;
};

struct ContractorOptions
Expand Down
2 changes: 1 addition & 1 deletion contractor/processing_chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ void Prepare::ContractGraph(const unsigned max_edge_id,
DeallocatingVector<QueryEdge>& contracted_edge_list)
{
Contractor contractor(max_edge_id + 1, edge_based_edge_list);
contractor.Run();
contractor.Run(config.core_factor);
contractor.GetEdges(contracted_edge_list);
}

Expand Down
5 changes: 5 additions & 0 deletions data_structures/binary_heap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ class BinaryHeap
return inserted_nodes[heap[1].index].node;
}

Weight MinKey() const {
BOOST_ASSERT(heap.size() > 1);
return heap[1].weight;
}

NodeID DeleteMin()
{
BOOST_ASSERT(heap.size() > 1);
Expand Down
3 changes: 3 additions & 0 deletions data_structures/search_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../routing_algorithms/many_to_many.hpp"
#include "../routing_algorithms/map_matching.hpp"
#include "../routing_algorithms/shortest_path.hpp"
#include "../routing_algorithms/direct_shortest_path.hpp"

#include <type_traits>

Expand All @@ -44,13 +45,15 @@ template <class DataFacadeT> class SearchEngine

public:
ShortestPathRouting<DataFacadeT> shortest_path;
DirectShortestPathRouting<DataFacadeT> direct_shortest_path;
AlternativeRouting<DataFacadeT> alternative_path;
ManyToManyRouting<DataFacadeT> distance_table;
MapMatching<DataFacadeT> map_matching;

explicit SearchEngine(DataFacadeT *facade)
: facade(facade),
shortest_path(facade, engine_working_data),
direct_shortest_path(facade, engine_working_data),
alternative_path(facade, engine_working_data),
distance_table(facade, engine_working_data),
map_matching(facade, engine_working_data)
Expand Down
9 changes: 6 additions & 3 deletions features/options/prepare/help.feature
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ Feature: osrm-prepare command line options: help
And stdout should contain "--restrictions"
And stdout should contain "--profile"
And stdout should contain "--threads"
And stdout should contain 15 lines
And stdout should contain "--core"
And stdout should contain 17 lines
And it should exit with code 1

Scenario: osrm-prepare - Help, short
Expand All @@ -31,7 +32,8 @@ Feature: osrm-prepare command line options: help
And stdout should contain "--restrictions"
And stdout should contain "--profile"
And stdout should contain "--threads"
And stdout should contain 15 lines
And stdout should contain "--core"
And stdout should contain 17 lines
And it should exit with code 0

Scenario: osrm-prepare - Help, long
Expand All @@ -46,5 +48,6 @@ Feature: osrm-prepare command line options: help
And stdout should contain "--restrictions"
And stdout should contain "--profile"
And stdout should contain "--threads"
And stdout should contain 15 lines
And stdout should contain "--core"
And stdout should contain 17 lines
And it should exit with code 0
15 changes: 12 additions & 3 deletions plugins/viaroute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../util/json_renderer.hpp"
#include "../util/make_unique.hpp"
#include "../util/simple_logger.hpp"
#include "../util/timing_util.hpp"

#include <osrm/json_container.hpp>

Expand Down Expand Up @@ -153,10 +154,18 @@ template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
};
osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs);

if (route_parameters.alternate_route && 1 == raw_route.segment_end_coordinates.size())
if (1 == raw_route.segment_end_coordinates.size())
{
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
raw_route);
if (route_parameters.alternate_route)
{
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
raw_route);
}
else
{
search_engine_ptr->direct_shortest_path(raw_route.segment_end_coordinates,
route_parameters.uturns, raw_route);
}
}
else
{
Expand Down
165 changes: 165 additions & 0 deletions routing_algorithms/direct_shortest_path.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*

Copyright (c) 2015, Project OSRM contributors
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 DIRECT_SHORTEST_PATH_HPP
#define DIRECT_SHORTEST_PATH_HPP

#include <boost/assert.hpp>

#include "routing_base.hpp"
#include "../data_structures/search_engine_data.hpp"
#include "../util/integer_range.hpp"
#include "../util/timing_util.hpp"
#include "../typedefs.h"

/// This is a striped down version of the general shortest path algorithm.
/// The general algorithm always computes two queries for each leg. This is only
/// necessary in case of vias, where the directions of the start node is constrainted
/// by the previous route.
/// This variation is only an optimazation for graphs with slow queries, for example
/// not fully contracted graphs.
template <class DataFacadeT>
class DirectShortestPathRouting final
: public BasicRoutingInterface<DataFacadeT, DirectShortestPathRouting<DataFacadeT>>
{
using super = BasicRoutingInterface<DataFacadeT, DirectShortestPathRouting<DataFacadeT>>;
using QueryHeap = SearchEngineData::QueryHeap;
SearchEngineData &engine_working_data;

public:
DirectShortestPathRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
: super(facade), engine_working_data(engine_working_data)
{
}

~DirectShortestPathRouting() {}

void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
const std::vector<bool> &uturn_indicators,
InternalRouteResult &raw_route_data) const
{
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes());

QueryHeap &forward_heap = *(engine_working_data.forward_heap_1);
QueryHeap &reverse_heap = *(engine_working_data.reverse_heap_1);

// Get distance to next pair of target nodes.
BOOST_ASSERT_MSG(1 == phantom_nodes_vector.size(),
"Direct Shortest Path Query only accepts a single source and target pair. Multiple ones have been specified.");

const auto& phantom_node_pair = phantom_nodes_vector.front();

forward_heap.Clear();
reverse_heap.Clear();
int distance = INVALID_EDGE_WEIGHT;
NodeID middle = SPECIAL_NODEID;

const EdgeWeight min_edge_offset =
std::min(-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset());

// insert new starting nodes into forward heap, adjusted by previous distances.
if (phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID)
{
forward_heap.Insert(
phantom_node_pair.source_phantom.forward_node_id,
-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.source_phantom.forward_node_id);
}
if ( phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID)
{
forward_heap.Insert(
phantom_node_pair.source_phantom.reverse_node_id,
-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.source_phantom.reverse_node_id);
}

// insert new backward nodes into backward heap, unadjusted.
if (phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID)
{
reverse_heap.Insert(phantom_node_pair.target_phantom.forward_node_id,
phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(),
phantom_node_pair.target_phantom.forward_node_id);
}

if (phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID)
{
reverse_heap.Insert(phantom_node_pair.target_phantom.reverse_node_id,
phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(),
phantom_node_pair.target_phantom.reverse_node_id);
}

// run two-Target Dijkstra routing step.
while (0 < (forward_heap.Size() + reverse_heap.Size()) )
{
if (!forward_heap.Empty())
{
super::RoutingStep(forward_heap, reverse_heap, &middle, &distance,
min_edge_offset, true);
}
if (!reverse_heap.Empty())
{
super::RoutingStep(reverse_heap, forward_heap, &middle, &distance,
min_edge_offset, false);
}
}

// No path found for both target nodes?
if ((INVALID_EDGE_WEIGHT == distance))
{
raw_route_data.shortest_path_length = INVALID_EDGE_WEIGHT;
raw_route_data.alternative_path_length = INVALID_EDGE_WEIGHT;
return;
}

// Was a paths over one of the forward/reverse nodes not found?
BOOST_ASSERT_MSG((SPECIAL_NODEID == middle || INVALID_EDGE_WEIGHT != distance),
"no path found");

// Unpack paths if they exist
std::vector<NodeID> packed_leg;
if (INVALID_EDGE_WEIGHT != distance)
{
super::RetrievePackedPathFromHeap(forward_heap, reverse_heap, middle, packed_leg);

BOOST_ASSERT_MSG(!packed_leg.empty(), "packed path empty");

raw_route_data.unpacked_path_segments.resize(1);
raw_route_data.source_traversed_in_reverse.push_back(
(packed_leg.front() != phantom_node_pair.source_phantom.forward_node_id));
raw_route_data.target_traversed_in_reverse.push_back(
(packed_leg.back() != phantom_node_pair.target_phantom.forward_node_id));

super::UnpackPath(packed_leg, phantom_node_pair, raw_route_data.unpacked_path_segments.front());
}

raw_route_data.shortest_path_length = distance;
}
};

#endif /* DIRECT_SHORTEST_PATH_HPP */
2 changes: 2 additions & 0 deletions unit_tests/data_structures/binary_heap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,15 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(decrease_key_test, T, storage_types, RandomData
{
heap.DecreaseKey(id, weights[id]);
BOOST_CHECK_EQUAL(heap.Min(), min_id);
BOOST_CHECK_EQUAL(heap.MinKey(), min_weight);
weights[id]--;
}

// make weight smaller than min
weights[id] -= 2;
heap.DecreaseKey(id, weights[id]);
BOOST_CHECK_EQUAL(heap.Min(), id);
BOOST_CHECK_EQUAL(heap.MinKey(), weights[id]);
}
}

Expand Down