Implement exclude flags on CH using shared core

The core is fully contracted for each exclude flag
and stored in a merged graph data structure.
This commit is contained in:
Patrick Niklaus
2017-08-20 23:24:05 +00:00
committed by Patrick Niklaus
parent 4b75cb8b0e
commit 61c430c098
42 changed files with 1468 additions and 418 deletions
+13 -1
View File
@@ -2,6 +2,10 @@ file(GLOB EngineTestsSources
engine_tests.cpp
engine/*.cpp)
file(GLOB ContractorTestsSources
contractor_tests.cpp
contractor/*.cpp)
file(GLOB ExtractorTestsSources
extractor_tests.cpp
extractor/*.cpp)
@@ -44,6 +48,11 @@ add_executable(engine-tests
${EngineTestsSources}
$<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
add_executable(contractor-tests
EXCLUDE_FROM_ALL
${ContractorTestsSources}
$<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:UTIL>)
add_executable(extractor-tests
EXCLUDE_FROM_ALL
${ExtractorTestsSources}
@@ -104,6 +113,7 @@ target_compile_definitions(library-tests PRIVATE COMPILE_DEFINITIONS OSRM_TEST_D
target_compile_definitions(library-extract-tests PRIVATE COMPILE_DEFINITIONS OSRM_TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(library-contract-tests PRIVATE COMPILE_DEFINITIONS OSRM_TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(updater-tests PRIVATE COMPILE_DEFINITIONS TEST_DATA_DIR="${UPDATER_TEST_DATA_DIR}")
target_compile_definitions(contractor-tests PRIVATE COMPILE_DEFINITIONS TEST_DATA_DIR="${TEST_DATA_DIR}")
target_include_directories(engine-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(library-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
@@ -113,6 +123,7 @@ target_include_directories(util-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(partition-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(customizer-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(updater-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(contractor-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(engine-tests ${ENGINE_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(extractor-tests ${EXTRACTOR_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
@@ -124,6 +135,7 @@ target_link_libraries(library-extract-tests osrm_extract ${Boost_UNIT_TEST_FRAME
target_link_libraries(library-contract-tests osrm_contract ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(server-tests osrm ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(util-tests ${UTIL_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(contractor-tests ${CONTRACTOR_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_custom_target(tests
DEPENDS engine-tests extractor-tests partition-tests updater-tests customizer-tests library-tests library-extract-tests server-tests util-tests)
DEPENDS engine-tests extractor-tests contractor-tests partition-tests updater-tests customizer-tests library-tests library-extract-tests server-tests util-tests)
@@ -0,0 +1,109 @@
#include "contractor/contracted_edge_container.hpp"
#include "../common/range_tools.hpp"
#include <boost/test/unit_test.hpp>
using namespace osrm;
using namespace osrm::contractor;
namespace osrm
{
namespace contractor
{
bool operator!=(const QueryEdge &lhs, const QueryEdge &rhs) { return !(lhs == rhs); }
std::ostream &operator<<(std::ostream &out, const QueryEdge::EdgeData &data)
{
out << "{" << data.turn_id << ", " << data.shortcut << ", " << data.duration << ", "
<< data.weight << ", " << data.forward << ", " << data.backward << "}";
return out;
}
std::ostream &operator<<(std::ostream &out, const QueryEdge &edge)
{
out << "{" << edge.source << ", " << edge.target << ", " << edge.data << "}";
return out;
}
}
}
BOOST_AUTO_TEST_SUITE(contracted_edge_container)
BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_graph)
{
ContractedEdgeContainer container;
util::DeallocatingVector<QueryEdge> edges;
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
edges.push_back(QueryEdge{2, 0, {3, false, 3, 6, false, true}});
edges.push_back(QueryEdge{2, 1, {4, false, 3, 6, false, true}});
container.Insert(edges);
edges.clear();
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
container.Merge(edges);
edges.clear();
edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
container.Merge(edges);
util::DeallocatingVector<QueryEdge> reference_edges;
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{2, 0, {3, false, 3, 6, false, true}});
reference_edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
reference_edges.push_back(QueryEdge{2, 1, {4, false, 3, 6, false, true}});
reference_edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
CHECK_EQUAL_COLLECTIONS(container.edges, reference_edges);
auto filters = container.MakeEdgeFilters();
BOOST_CHECK_EQUAL(filters.size(), 2);
REQUIRE_SIZE_RANGE(filters[0], 7);
CHECK_EQUAL_RANGE(filters[0], true, true, false, true, true, true, true);
REQUIRE_SIZE_RANGE(filters[1], 7);
CHECK_EQUAL_RANGE(filters[1], true, true, true, true, false, true, false);
}
BOOST_AUTO_TEST_CASE(merge_edge_of_multiple_disjoint_graph)
{
ContractedEdgeContainer container;
util::DeallocatingVector<QueryEdge> edges;
edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
container.Merge(edges);
edges.clear();
edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
container.Merge(edges);
util::DeallocatingVector<QueryEdge> reference_edges;
reference_edges.push_back(QueryEdge{0, 1, {1, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 2, {2, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{1, 4, {5, false, 3, 6, true, false}});
reference_edges.push_back(QueryEdge{2, 0, {3, false, 12, 24, false, true}});
reference_edges.push_back(QueryEdge{2, 1, {4, false, 12, 24, false, true}});
CHECK_EQUAL_COLLECTIONS(container.edges, reference_edges);
auto filters = container.MakeEdgeFilters();
BOOST_CHECK_EQUAL(filters.size(), 2);
REQUIRE_SIZE_RANGE(filters[0], 5);
CHECK_EQUAL_RANGE(filters[0], true, true, false, true, true);
REQUIRE_SIZE_RANGE(filters[1], 5);
CHECK_EQUAL_RANGE(filters[1], false, false, true, false, false);
}
BOOST_AUTO_TEST_SUITE_END()
+156
View File
@@ -0,0 +1,156 @@
#include "contractor/graph_contractor.hpp"
#include "../common/range_tools.hpp"
#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>
#include <tbb/task_scheduler_init.h>
using namespace osrm;
using namespace osrm::contractor;
BOOST_AUTO_TEST_SUITE(graph_contractor)
using TestEdge = std::tuple<unsigned, unsigned, int>;
ContractorGraph makeGraph(const std::vector<TestEdge> &edges)
{
std::vector<ContractorEdge> input_edges;
auto id = 0u;
auto max_id = 0u;
for (const auto &edge : edges)
{
unsigned start;
unsigned target;
int weight;
std::tie(start, target, weight) = edge;
max_id = std::max(std::max(start, target), max_id);
input_edges.push_back(ContractorEdge{
start, target, ContractorEdgeData{weight, weight * 2, id++, 0, false, true, false}});
input_edges.push_back(ContractorEdge{
target, start, ContractorEdgeData{weight, weight * 2, id++, 0, false, false, true}});
}
std::sort(input_edges.begin(), input_edges.end());
return ContractorGraph{max_id + 1, std::move(input_edges)};
}
BOOST_AUTO_TEST_CASE(contract_graph)
{
tbb::task_scheduler_init scheduler(1);
/*
* <--1--<
* (0) >--3--> (1) >--3--> (3)
* v ^ v ^
* \ / \ |
* 1 1 1 1
* \ ^ \ /
* >(5) > (4) >
*/
std::vector<TestEdge> edges = {TestEdge{0, 1, 3},
TestEdge{0, 5, 1},
TestEdge{1, 3, 3},
TestEdge{1, 4, 1},
TestEdge{3, 1, 1},
TestEdge{4, 3, 1},
TestEdge{5, 1, 1}};
auto reference_graph = makeGraph(edges);
auto contracted_graph = reference_graph;
std::vector<bool> core = contractGraph(contracted_graph, {1, 1, 1, 1, 1, 1});
// This contraction order is dependent on the priority caculation in the contractor
// but deterministic for the same graph.
CHECK_EQUAL_RANGE(core, false, false, false, false, false, false);
/* After contracting 0 and 2:
*
* Deltes edges 5 -> 0, 1 -> 0
*
* <--1--<
* (0) ---3--> (1) >--3--> (3)
* \ ^ v ^
* \ / \ |
* 1 1 1 1
* \ ^ \ /
* >(5) > (4) >
*/
reference_graph.DeleteEdgesTo(5, 0);
reference_graph.DeleteEdgesTo(1, 0);
/* After contracting 5:
*
* Deletes edges 1 -> 5
*
* <--1--<
* (0) ---3--> (1) >--3--> (3)
* \ ^ v ^
* \ / \ |
* 1 1 1 1
* \ / \ /
* >(5) > (4) >
*/
reference_graph.DeleteEdgesTo(5, 0);
reference_graph.DeleteEdgesTo(1, 0);
/* After contracting 3:
*
* Deletes edges 1 -> 3
* Deletes edges 4 -> 3
* Insert edge 4 -> 1
*
* <--1---
* (0) ---3--> (1) >--3--- (3)
* \ ^ v ^ |
* \ / \ \ |
* 1 1 1 2 1
* \ / \ \ /
* >(5) > (4) >
*/
reference_graph.DeleteEdgesTo(1, 3);
reference_graph.DeleteEdgesTo(4, 3);
// Insert shortcut
reference_graph.InsertEdge(4, 1, {2, 4, 3, 0, true, true, false});
/* After contracting 4:
*
* Delete edges 1 -> 4
*
* <--1---
* (0) ---3--> (1) >--3--- (3)
* \ ^ v ^ |
* \ / \ \ |
* 1 1 1 2 1
* \ / \ \ /
* >(5) \ (4) >
*/
reference_graph.DeleteEdgesTo(1, 4);
/* After contracting 1:
*
* Delete no edges.
*
* <--1---
* (0) ---3--> (1) >--3--- (3)
* \ ^ v ^ |
* \ / \ \ |
* 1 1 1 2 1
* \ / \ \ /
* >(5) \ (4) >
*/
REQUIRE_SIZE_RANGE(contracted_graph.GetAdjacentEdgeRange(0), 2);
BOOST_CHECK(contracted_graph.FindEdge(0, 1) != SPECIAL_EDGEID);
BOOST_CHECK(contracted_graph.FindEdge(0, 5) != SPECIAL_EDGEID);
REQUIRE_SIZE_RANGE(contracted_graph.GetAdjacentEdgeRange(1), 0);
REQUIRE_SIZE_RANGE(contracted_graph.GetAdjacentEdgeRange(2), 0);
REQUIRE_SIZE_RANGE(contracted_graph.GetAdjacentEdgeRange(3), 3);
BOOST_CHECK(contracted_graph.FindEdge(3, 1) != SPECIAL_EDGEID);
BOOST_CHECK(contracted_graph.FindEdge(3, 4) != SPECIAL_EDGEID);
REQUIRE_SIZE_RANGE(contracted_graph.GetAdjacentEdgeRange(4), 2);
BOOST_CHECK(contracted_graph.FindEdge(4, 1) != SPECIAL_EDGEID);
REQUIRE_SIZE_RANGE(contracted_graph.GetAdjacentEdgeRange(5), 1);
BOOST_CHECK(contracted_graph.FindEdge(5, 1) != SPECIAL_EDGEID);
}
BOOST_AUTO_TEST_SUITE_END()
+7
View File
@@ -0,0 +1,7 @@
#define BOOST_TEST_MODULE contractor tests
#include <boost/test/unit_test.hpp>
/*
* This file will contain an automatically generated main function.
*/
+2 -4
View File
@@ -280,11 +280,9 @@ class MockAlgorithmDataFacade<engine::datafacade::CH>
unsigned GetOutDegree(const NodeID /* n */) const override { return 0; }
NodeID GetTarget(const EdgeID /* e */) const override { return SPECIAL_NODEID; }
const EdgeData &GetEdgeData(const EdgeID /* e */) const override { return foo; }
EdgeID BeginEdges(const NodeID /* n */) const override { return SPECIAL_EDGEID; }
EdgeID EndEdges(const NodeID /* n */) const override { return SPECIAL_EDGEID; }
osrm::engine::datafacade::EdgeRange GetAdjacentEdgeRange(const NodeID /* node */) const override
EdgeRange GetAdjacentEdgeRange(const NodeID /* node */) const override
{
return util::irange(static_cast<EdgeID>(0), static_cast<EdgeID>(0));
return EdgeRange(static_cast<EdgeID>(0), static_cast<EdgeID>(0), {});
}
EdgeID FindEdge(const NodeID /* from */, const NodeID /* to */) const override
{
+1 -1
View File
@@ -1,6 +1,6 @@
#include "partition/bisection_graph_view.hpp"
#include "partition/dinic_max_flow.hpp"
#include "partition/graph_generator.hpp"
#include "partition/bisection_graph_view.hpp"
#include "partition/recursive_bisection_state.hpp"
#include <algorithm>
+1 -1
View File
@@ -1,5 +1,5 @@
#include "partition/graph_generator.hpp"
#include "partition/bisection_graph_view.hpp"
#include "partition/graph_generator.hpp"
#include "partition/recursive_bisection_state.hpp"
#include <algorithm>
+39
View File
@@ -1,6 +1,8 @@
#include "util/dynamic_graph.hpp"
#include "util/typedefs.hpp"
#include "../common/range_tools.hpp"
#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>
@@ -120,4 +122,41 @@ BOOST_AUTO_TEST_CASE(renumber_test)
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2);
}
BOOST_AUTO_TEST_CASE(filter_test)
{
/*
* (0) -1-> (1)
* ^ ^ ^
* 2 5 1
* | | |
* (3) -3-> (4)
* <-4-
*/
std::vector<TestInputEdge> input_edges = {TestInputEdge{0, 1, TestData{1}},
TestInputEdge{3, 0, TestData{2}},
TestInputEdge{3, 0, TestData{5}},
TestInputEdge{3, 4, TestData{3}},
TestInputEdge{4, 1, TestData{1}},
TestInputEdge{4, 3, TestData{4}}};
TestDynamicGraph simple_graph(5, input_edges);
// only keep 0, 1, 4 -> filter out all edges from/to 3
auto filtered_simple_graph =
simple_graph.Filter([](const NodeID node) { return node == 0 || node == 1 || node == 4; });
REQUIRE_SIZE_RANGE(filtered_simple_graph.GetAdjacentEdgeRange(0), 1);
CHECK_EQUAL_RANGE(filtered_simple_graph.GetAdjacentEdgeRange(0),
filtered_simple_graph.FindEdge(0, 1));
REQUIRE_SIZE_RANGE(filtered_simple_graph.GetAdjacentEdgeRange(1), 0);
REQUIRE_SIZE_RANGE(filtered_simple_graph.GetAdjacentEdgeRange(2), 0);
REQUIRE_SIZE_RANGE(filtered_simple_graph.GetAdjacentEdgeRange(3), 0);
REQUIRE_SIZE_RANGE(filtered_simple_graph.GetAdjacentEdgeRange(4), 1);
CHECK_EQUAL_RANGE(filtered_simple_graph.GetAdjacentEdgeRange(4),
filtered_simple_graph.FindEdge(4, 1));
}
BOOST_AUTO_TEST_SUITE_END()
@@ -0,0 +1,38 @@
#include "util/filtered_integer_range.hpp"
#include "../common/range_tools.hpp"
#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(bit_range_test)
using namespace osrm;
using namespace osrm::util;
BOOST_AUTO_TEST_CASE(filtered_irange_test)
{
std::vector<bool> filter = {// 0 1 2 3 4 5
true,
false,
false,
true,
true,
false};
CHECK_EQUAL_RANGE(filtered_irange<std::uint8_t>(0, 2, filter), 0);
CHECK_EQUAL_RANGE(filtered_irange<std::uint8_t>(1, 4, filter), 3);
CHECK_EQUAL_RANGE(filtered_irange<std::uint8_t>(1, 5, filter), 3, 4);
CHECK_EQUAL_RANGE(filtered_irange<std::uint8_t>(0, 6, filter), 0, 3, 4);
auto empty_1 = filtered_irange<std::uint8_t>(1, 3, filter);
auto empty_2 = filtered_irange<std::uint8_t>(3, 3, filter);
auto empty_3 = filtered_irange<std::uint8_t>(4, 4, filter);
auto empty_4 = filtered_irange<std::uint8_t>(5, 5, filter);
BOOST_CHECK(empty_1.begin() == empty_1.end());
BOOST_CHECK(empty_2.begin() == empty_2.end());
BOOST_CHECK(empty_3.begin() == empty_3.end());
BOOST_CHECK(empty_4.begin() == empty_4.end());
}
BOOST_AUTO_TEST_SUITE_END()