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

Multi Source / Multi Target routing #1162

Closed
wants to merge 13 commits into from
Closed
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
31 changes: 12 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.8.8)

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE)
if( CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE )
message(FATAL_ERROR "In-source builds are not allowed.
Please create a directory and run cmake from there, passing the path to this source directory as the last argument.
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. Please delete them.")
Expand All @@ -11,7 +11,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CheckCXXCompilerFlag)
include(FindPackageHandleStandardArgs)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription)
git_describe(GIT_DESCRIPTION)

Expand All @@ -30,26 +30,26 @@ endif()
OPTION(WITH_TOOLS "Build OSRM tools" OFF)
OPTION(BUILD_TOOLS "Build OSRM tools" OFF)

include_directories(${CMAKE_SOURCE_DIR}/Include/)
include_directories(${CMAKE_SOURCE_DIR}/third_party/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Include/)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third_party/)

add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp finger_print.cpp.alwaysbuild
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
add_custom_command(OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Util/finger_print.cpp finger_print.cpp.alwaysbuild
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/FingerPrint-Config.cmake
DEPENDS
${CMAKE_SOURCE_DIR}/Util/finger_print.cpp.in
${CMAKE_CURRENT_SOURCE_DIR}/Util/finger_print.cpp.in
COMMENT "Configuring finger_print.cpp"
VERBATIM)

add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/finger_print.cpp)
add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Util/finger_print.cpp)
add_custom_target(tests DEPENDS datastructure-tests algorithm-tests)
add_custom_target(benchmarks DEPENDS rtree-bench)

set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework)

configure_file(
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Util/GitDescription.cpp.in
${CMAKE_CURRENT_SOURCE_DIR}/Util/GitDescription.cpp
)
file(GLOB ExtractorGlob extractor/*.cpp)
file(GLOB ImporterGlob data_structures/import_edge.cpp data_structures/external_memory_node.cpp)
Expand Down Expand Up @@ -104,14 +104,7 @@ add_executable(rtree-bench EXCLUDE_FROM_ALL benchmarks/static_rtree.cpp $<TARGET
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_BUILD_TYPE Release)
endif()
if(CMAKE_BUILD_TYPE MATCHES Debug)
message(STATUS "Configuring OSRM in debug mode")
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
message(STATUS "adding profiling flags")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
endif()
endif()

if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode")
# Check if LTO is available
Expand Down Expand Up @@ -337,7 +330,7 @@ foreach (lib ${Boost_LIBRARIES})
set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}")
endforeach ()

configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)

if(BUILD_DEBIAN_PACKAGE)
Expand Down
5 changes: 4 additions & 1 deletion Library/OSRM_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace boost { namespace interprocess { class named_mutex; } }
#include "../plugins/distance_table.hpp"
#include "../plugins/hello_world.hpp"
#include "../plugins/locate.hpp"
#include "../plugins/multi_target.hpp"
#include "../plugins/nearest.hpp"
#include "../plugins/timestamp.hpp"
#include "../plugins/viaroute.hpp"
Expand Down Expand Up @@ -72,10 +73,12 @@ OSRM_impl::OSRM_impl(ServerPaths server_paths, const bool use_shared_memory)
}

// The following plugins handle all requests.
RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new HelloWorldPlugin());
RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new MultiTargetPlugin<BaseDataFacade<QueryEdge::EdgeData>, true>(query_data_facade));
RegisterPlugin(new MultiTargetPlugin<BaseDataFacade<QueryEdge::EdgeData>, false>(query_data_facade));
RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>, false, false>(query_data_facade));
RegisterPlugin(new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
RegisterPlugin(new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
}
Expand Down
14 changes: 12 additions & 2 deletions data_structures/search_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "search_engine_data.hpp"
#include "../routing_algorithms/alternative_path.hpp"
#include "../routing_algorithms/many_to_many.hpp"
#include "../routing_algorithms/multi_target.hpp"
#include "../routing_algorithms/shortest_path.hpp"

#include <type_traits>
Expand All @@ -44,11 +45,20 @@ template <class DataFacadeT> class SearchEngine
public:
ShortestPathRouting<DataFacadeT> shortest_path;
AlternativeRouting<DataFacadeT> alternative_path;
ManyToManyRouting<DataFacadeT> distance_table;
ManyToManyRouting<DataFacadeT, false, false> distance_table;
ManyToManyRouting<DataFacadeT, true, false> distance_table_single_source;
ManyToManyRouting<DataFacadeT, false, true> distance_table_single_target;
MultiTargetRouting<DataFacadeT, true> multi_target;
MultiTargetRouting<DataFacadeT, false> multi_source;

explicit SearchEngine(DataFacadeT *facade)
: facade(facade), shortest_path(facade, engine_working_data),
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
alternative_path(facade, engine_working_data),
distance_table(facade, engine_working_data),
distance_table_single_source(facade, engine_working_data),
distance_table_single_target(facade, engine_working_data),
multi_target(facade, engine_working_data),
multi_source(facade, engine_working_data)
{
static_assert(!std::is_pointer<DataFacadeT>::value, "don't instantiate with ptr type");
static_assert(std::is_object<DataFacadeT>::value, "don't instantiate with void, function, or reference");
Expand Down
7 changes: 7 additions & 0 deletions data_structures/search_engine_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "binary_heap.hpp"

SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;

void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
{
if (forwardHeap.get())
Expand Down
54 changes: 38 additions & 16 deletions plugins/distance_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../data_structures/query_edge.hpp"
#include "../data_structures/search_engine.hpp"
#include "../descriptors/descriptor_base.hpp"
#include "../Util/integer_range.hpp"
#include "../Util/json_renderer.hpp"
#include "../Util/make_unique.hpp"
#include "../Util/StringUtil.h"
Expand All @@ -48,7 +49,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <vector>

template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
template <class DataFacadeT,
bool single_source,
bool single_target> class DistanceTablePlugin final : public BasePlugin
{
private:
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
Expand All @@ -63,19 +66,15 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin

const std::string GetDescriptor() const final { return descriptor_string; }

void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
std::shared_ptr<std::vector<EdgeWeight>> HandleRequest(
const RouteParameters &route_parameters, unsigned &calctime_in_us)
{
if (!check_all_coordinates(route_parameters.coordinates))
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}
return {};

const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
unsigned max_locations =
std::min(100u, static_cast<unsigned>(route_parameters.coordinates.size()));
PhantomNodeArray phantom_node_vector(max_locations);
for (const auto i : osrm::irange(1u, max_locations))
PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
for (const auto i : osrm::irange(0ul, route_parameters.coordinates.size()))
{
if (checksum_OK && i < route_parameters.hints.size() &&
!route_parameters.hints[i].empty())
Expand All @@ -96,20 +95,43 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
}

// TIMER_START(distance_table);
std::shared_ptr<std::vector<EdgeWeight>> result_table =
search_engine_ptr->distance_table(phantom_node_vector);
// TIMER_STOP(distance_table);
std::shared_ptr<std::vector<EdgeWeight>> result_table;

TIMER_START(distance_table);
if (single_source)
{
result_table = search_engine_ptr->distance_table_single_source(phantom_node_vector);
}
else if (single_target)
{
result_table = search_engine_ptr->distance_table_single_target(phantom_node_vector);
}
else
{
result_table = search_engine_ptr->distance_table(phantom_node_vector);
}
TIMER_STOP(distance_table);

calctime_in_us = TIMER_USEC(distance_table);

return result_table;
}

void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
{
unsigned calctime_in_us = 0;
auto result_table = HandleRequest(route_parameters, calctime_in_us);

if (!result_table)
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}

JSON::Object json_object;
JSON::Array json_array;
const unsigned number_of_locations = static_cast<unsigned>(phantom_node_vector.size());
for (unsigned row = 0; row < number_of_locations; ++row)
const auto number_of_locations = route_parameters.coordinates.size();
for (const auto row : osrm::irange<std::size_t>(0, number_of_locations))
{
JSON::Array json_row;
auto row_begin_iterator = result_table->begin() + (row * number_of_locations);
Expand Down
140 changes: 140 additions & 0 deletions plugins/multi_target.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*

Copyright (c) 2014, Project OSRM, Felix Guendling
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 MULTI_TARGET_PLUGIN_H
#define MULTI_TARGET_PLUGIN_H

#include "plugin_base.hpp"

#include "../Algorithms/object_encoder.hpp"
#include "../data_structures/search_engine.hpp"
#include "../Util/json_renderer.hpp"
#include "../Util/TimingUtil.h"

template <class DataFacadeT, bool forward> class MultiTargetPlugin final : public BasePlugin
{
public:
explicit MultiTargetPlugin(DataFacadeT *facade)
: facade(facade), search_engine_ptr(std::make_shared<SearchEngine<DataFacadeT>>(facade))
{
}

virtual ~MultiTargetPlugin() {}

std::shared_ptr<std::vector<std::pair<EdgeWeight, double>>>
HandleRequest(const RouteParameters &route_parameters,
unsigned &calctime_in_us)
{
// check number of parameters
if (2 > route_parameters.coordinates.size())
{
return nullptr;
}

if (std::any_of(begin(route_parameters.coordinates), end(route_parameters.coordinates),
[&](FixedPointCoordinate coordinate)
{
return !coordinate.is_valid();
}))
{
return nullptr;
}

const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
for (unsigned i = 0; i < route_parameters.coordinates.size(); ++i)
{
if (checksum_OK && i < route_parameters.hints.size() &&
!route_parameters.hints[i].empty())
{
PhantomNode current_phantom_node;
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
if (current_phantom_node.is_valid(facade->GetNumberOfNodes()))
{
phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
continue;
}
}
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
phantom_node_vector[i],
route_parameters.zoom_level,
1);

BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
}

std::shared_ptr<std::vector<std::pair<EdgeWeight, double>>> ret;

TIMER_START(multi_target);
if (forward)
{
ret = search_engine_ptr->multi_target(phantom_node_vector);
}
else
{
ret = search_engine_ptr->multi_source(phantom_node_vector);
}
TIMER_STOP(multi_target);
calctime_in_us = TIMER_USEC(multi_target);

return ret;
}

void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
{
unsigned calctime_in_ms = 0;
auto result_table = HandleRequest(route_parameters, calctime_in_ms);

if (!result_table)
{
reply = http::Reply::StockReply(http::Reply::badRequest);
return;
}

JSON::Object json_object;
JSON::Array json_array;
for (unsigned column = 0; column < route_parameters.coordinates.size() - 1; ++column)
{
auto routing_result = result_table->operator[](column);

JSON::Object result;
result.values["time_cost"] = routing_result.first;
result.values["distance"] = routing_result.second;
json_array.values.emplace_back(result);
}
json_object.values["distances"] = json_array;
JSON::render(reply.content, json_object);
}

const std::string GetDescriptor() const { return forward ? "multitarget" : "multisource"; }

private:
DataFacadeT *facade;
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
};

#endif // MULTI_TARGET_PLUGIN_H
Loading