Skip to content

Commit

Permalink
[routing] Cross-country penalty.
Browse files Browse the repository at this point in the history
  • Loading branch information
mesozoic-drones authored and bykoianko committed Jul 29, 2020
1 parent 1ffb492 commit 670dfae
Show file tree
Hide file tree
Showing 14 changed files with 192 additions and 19 deletions.
2 changes: 2 additions & 0 deletions routing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ set(
maxspeeds.hpp
maxspeeds_serialization.cpp
maxspeeds_serialization.hpp
mwm_hierarchy_handler.cpp
mwm_hierarchy_handler.hpp
nearest_edge_finder.cpp
nearest_edge_finder.hpp
online_absent_fetcher.cpp
Expand Down
3 changes: 1 addition & 2 deletions routing/index_graph_starter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ size_t IndexGraphStarter::GetRouteNumPoints(vector<Segment> const & segments)
}

IndexGraphStarter::IndexGraphStarter(FakeEnding const & startEnding,
FakeEnding const & finishEnding,
uint32_t fakeNumerationStart,
FakeEnding const & finishEnding, uint32_t fakeNumerationStart,
bool strictForward, WorldGraph & graph)
: m_graph(graph)
{
Expand Down
10 changes: 7 additions & 3 deletions routing/index_router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "routing/junction_visitor.hpp"
#include "routing/leaps_graph.hpp"
#include "routing/leaps_postprocessor.hpp"
#include "routing/mwm_hierarchy_handler.hpp"
#include "routing/pedestrian_directions.hpp"
#include "routing/route.hpp"
#include "routing/routing_exceptions.hpp"
Expand Down Expand Up @@ -294,6 +295,7 @@ IndexRouter::IndexRouter(VehicleType vehicleType, bool loadAltitudes,
m_vehicleType, CalcMaxSpeed(*m_numMwmIds, *m_vehicleModelFactory, m_vehicleType),
CalcOffroadSpeed(*m_vehicleModelFactory), m_trafficStash))
, m_directionsEngine(CreateDirectionsEngine(m_vehicleType, m_numMwmIds, m_dataSource))
, m_countryParentNameGetterFn(countryParentNameGetterFn)
{
CHECK(!m_name.empty(), ());
CHECK(m_numMwmIds, ());
Expand Down Expand Up @@ -561,6 +563,7 @@ RouterResultCode IndexRouter::DoCalculateRoute(Checkpoints const & checkpoints,
for (auto const & checkpoint : checkpoints.GetPoints())
{
string const countryName = m_countryFileFn(checkpoint);

if (countryName.empty())
{
LOG(LWARNING, ("For point", mercator::ToLatLon(checkpoint),
Expand Down Expand Up @@ -841,7 +844,7 @@ RouterResultCode IndexRouter::CalculateSubrouteLeapsOnlyMode(
RouterDelegate const & delegate, shared_ptr<AStarProgress> const & progress,
vector<Segment> & subroute)
{
LeapsGraph leapsGraph(starter);
LeapsGraph leapsGraph(starter, MwmHierarchyHandler(m_numMwmIds, m_countryParentNameGetterFn));

using Vertex = LeapsGraph::Vertex;
using Edge = LeapsGraph::Edge;
Expand Down Expand Up @@ -1001,8 +1004,9 @@ unique_ptr<WorldGraph> IndexRouter::MakeWorldGraph()

if (m_vehicleType != VehicleType::Transit)
{
auto graph = make_unique<SingleVehicleWorldGraph>(move(crossMwmGraph), move(indexGraphLoader),
m_estimator);
auto graph = make_unique<SingleVehicleWorldGraph>(
move(crossMwmGraph), move(indexGraphLoader), m_estimator,
MwmHierarchyHandler(m_numMwmIds, m_countryParentNameGetterFn));
graph->SetRoutingOptions(routingOptions);
return graph;
}
Expand Down
2 changes: 2 additions & 0 deletions routing/index_router.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,5 +251,7 @@ class IndexRouter : public IRouter

// If a ckeckpoint is near to the guide track we need to build route through this track.
GuidesConnections m_guides;

CountryParentNameGetterFn m_countryParentNameGetterFn;
};
} // namespace routing
11 changes: 7 additions & 4 deletions routing/leaps_graph.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#include "routing/leaps_graph.hpp"

#include "routing_common/num_mwm_id.hpp"

#include "base/assert.hpp"

#include <set>
#include <utility>

namespace routing
{
LeapsGraph::LeapsGraph(IndexGraphStarter & starter) : m_starter(starter)
LeapsGraph::LeapsGraph(IndexGraphStarter & starter, MwmHierarchyHandler && hierarchyHandler)
: m_starter(starter), m_hierarchyHandler(std::move(hierarchyHandler))
{
m_startPoint = m_starter.GetPoint(m_starter.GetStartSegment(), true /* front */);
m_finishPoint = m_starter.GetPoint(m_starter.GetFinishSegment(), true /* front */);
Expand Down Expand Up @@ -59,12 +59,15 @@ void LeapsGraph::GetEdgesList(Segment const & segment, bool isOutgoing,
return;

auto & crossMwmGraph = m_starter.GetGraph().GetCrossMwmGraph();

if (crossMwmGraph.IsTransition(segment, isOutgoing))
{
auto const segMwmId = segment.GetMwmId();

std::vector<Segment> twins;
m_starter.GetGraph().GetTwinsInner(segment, isOutgoing, twins);
for (auto const & twin : twins)
edges.emplace_back(twin, RouteWeight(0.0));
edges.emplace_back(twin, m_hierarchyHandler.GetCrossBorderPenalty(segMwmId, twin.GetMwmId()));

return;
}
Expand Down
6 changes: 4 additions & 2 deletions routing/leaps_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include "routing/base/astar_graph.hpp"
#include "routing/base/astar_vertex_data.hpp"

#include "routing/index_graph_starter.hpp"
#include "routing/mwm_hierarchy_handler.hpp"
#include "routing/route_weight.hpp"
#include "routing/segment.hpp"

Expand All @@ -16,7 +16,7 @@ namespace routing
class LeapsGraph : public AStarGraph<Segment, SegmentEdge, RouteWeight>
{
public:
explicit LeapsGraph(IndexGraphStarter & starter);
explicit LeapsGraph(IndexGraphStarter & starter, MwmHierarchyHandler && hierarchyHandler);

// AStarGraph overrides:
// @{
Expand Down Expand Up @@ -45,5 +45,7 @@ class LeapsGraph : public AStarGraph<Segment, SegmentEdge, RouteWeight>
Segment m_finishSegment;

IndexGraphStarter & m_starter;

MwmHierarchyHandler m_hierarchyHandler;
};
} // namespace routing
103 changes: 103 additions & 0 deletions routing/mwm_hierarchy_handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include "routing/mwm_hierarchy_handler.hpp"

#include "base/logging.hpp"

#include <unordered_set>

namespace routing
{
// Time penalty in seconds for crossing the country border.
// We add no penalty for crossing borders of the countries that have officially abolished
// passport and other types of border control at their mutual borders.
inline size_t constexpr kCrossCountryPenaltyS = 60 * 60 * 2;

// The Eurasian Economic Union (EAEU) list of countries.
std::unordered_set<std::string> kEAEU{"Armenia", "Belarus", "Kazakhstan", "Kyrgyzstan",
"Russian Federation"};

// The Schengen Area list of countries.
std::unordered_set<std::string> kSchengenArea{
"Austria", "Belgium", "Czech Republic", "Denmark", "Estonia", "Finland",
"France", "Germany", "Greece", "Hungary", "Iceland", "Italy",
"Latvia", "Liechtenstein", "Lithuania", "Luxembourg", "Malta", "Netherlands",
"Norway", "Poland", "Portugal", "Slovakia", "Slovenia", "Spain",
"Sweden", "Switzerland"};

std::string GetCountryByMwmName(std::string const & mwmName, CountryParentNameGetterFn fn)
{
static std::string const CountriesRoot = "Countries";
std::string country;

if (!fn)
return country;

std::string parent = mwmName;

while (parent != CountriesRoot)
{
country = parent;
if (country.empty())
break;

parent = fn(parent);
}

return country;
}

std::string GetCountryByMwmId(NumMwmId mwmId, CountryParentNameGetterFn fn,
std::shared_ptr<NumMwmIds> const & numMwmIds)
{
if (numMwmIds != nullptr && numMwmIds->ContainsFileForMwm(mwmId))
{
std::string const mwmName = numMwmIds->GetFile(mwmId).GetName();
return GetCountryByMwmName(mwmName, fn);
}
return {};
}

MwmHierarchyHandler::MwmHierarchyHandler(std::shared_ptr<NumMwmIds> numMwmIds,
CountryParentNameGetterFn countryParentNameGetterFn)
: m_numMwmIds(numMwmIds), m_countryParentNameGetterFn(countryParentNameGetterFn)
{
}

std::string const & MwmHierarchyHandler::GetParentCountryByMwmId(NumMwmId mwmId)
{
auto [it, inserted] = m_mwmCountriesCache.emplace(mwmId, "");
if (inserted)
it->second = GetCountryByMwmId(mwmId, m_countryParentNameGetterFn, m_numMwmIds);

return it->second;
}

bool MwmHierarchyHandler::HasCrossBorderPenalty(NumMwmId mwmId1, NumMwmId mwmId2)
{
if (mwmId1 == mwmId2)
return false;

std::string const country1 = GetParentCountryByMwmId(mwmId1);
std::string const country2 = GetParentCountryByMwmId(mwmId2);

// If one of the mwms belongs to the territorial dispute we add penalty for crossing its borders.
if (country1.empty() || country2.empty())
return true;

if (country1 == country2)
return false;

if (kEAEU.find(country1) != kEAEU.end() && kEAEU.find(country2) != kEAEU.end())
return false;

return kSchengenArea.find(country1) == kSchengenArea.end() ||
kSchengenArea.find(country2) == kSchengenArea.end();
}

RouteWeight MwmHierarchyHandler::GetCrossBorderPenalty(NumMwmId mwmId1, NumMwmId mwmId2)
{
if (HasCrossBorderPenalty(mwmId1, mwmId2))
return RouteWeight(kCrossCountryPenaltyS);

return RouteWeight(0.0);
}
} // namespace routing
35 changes: 35 additions & 0 deletions routing/mwm_hierarchy_handler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include "routing/route_weight.hpp"
#include "routing/router.hpp"

#include "routing_common/num_mwm_id.hpp"

#include <memory>
#include <string>
#include <unordered_map>

namespace routing
{
using MwmToCountry = std::unordered_map<NumMwmId, std::string>;

// Class for calculating penalty while crossing country borders. Also finds parent country for mwm.
class MwmHierarchyHandler
{
public:
MwmHierarchyHandler(std::shared_ptr<NumMwmIds> numMwmIds,
CountryParentNameGetterFn countryParentNameGetterFn);

RouteWeight GetCrossBorderPenalty(NumMwmId mwmId1, NumMwmId mwmId2);

private:
bool HasCrossBorderPenalty(NumMwmId mwmId1, NumMwmId mwmId2);

// Returns parent country name for |mwmId|.
std::string const & GetParentCountryByMwmId(NumMwmId mwmId);

std::shared_ptr<NumMwmIds> m_numMwmIds = nullptr;
CountryParentNameGetterFn m_countryParentNameGetterFn = nullptr;
MwmToCountry m_mwmCountriesCache;
};
} // namespace routing
4 changes: 2 additions & 2 deletions routing/routing_tests/index_graph_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ unique_ptr<SingleVehicleWorldGraph> BuildWorldGraph(unique_ptr<TestGeometryLoade
auto indexLoader = make_unique<TestIndexGraphLoader>();
indexLoader->AddGraph(kTestNumMwmId, move(graph));
return make_unique<SingleVehicleWorldGraph>(nullptr /* crossMwmGraph */, move(indexLoader),
estimator);
estimator, MwmHierarchyHandler(nullptr, nullptr));
}

unique_ptr<IndexGraph> BuildIndexGraph(unique_ptr<TestGeometryLoader> geometryLoader,
Expand All @@ -442,7 +442,7 @@ unique_ptr<SingleVehicleWorldGraph> BuildWorldGraph(unique_ptr<ZeroGeometryLoade
auto indexLoader = make_unique<TestIndexGraphLoader>();
indexLoader->AddGraph(kTestNumMwmId, move(graph));
return make_unique<SingleVehicleWorldGraph>(nullptr /* crossMwmGraph */, move(indexLoader),
estimator);
estimator, MwmHierarchyHandler(nullptr, nullptr));
}

unique_ptr<TransitWorldGraph> BuildWorldGraph(unique_ptr<TestGeometryLoader> geometryLoader,
Expand Down
2 changes: 1 addition & 1 deletion routing/segment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class SegmentEdge final

Segment const & GetTarget() const { return m_target; }
RouteWeight const & GetWeight() const { return m_weight; }

RouteWeight & GetWeight() { return m_weight; }
bool operator==(SegmentEdge const & edge) const;
bool operator<(SegmentEdge const & edge) const;

Expand Down
20 changes: 16 additions & 4 deletions routing/single_vehicle_world_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ SingleVehicleWorldGraph::AStarParents<JointSegment>::kEmpty = {};

SingleVehicleWorldGraph::SingleVehicleWorldGraph(unique_ptr<CrossMwmGraph> crossMwmGraph,
unique_ptr<IndexGraphLoader> loader,
shared_ptr<EdgeEstimator> estimator)
: m_crossMwmGraph(move(crossMwmGraph)), m_loader(move(loader)), m_estimator(move(estimator))
shared_ptr<EdgeEstimator> estimator,
MwmHierarchyHandler && hierarchyHandler)
: m_crossMwmGraph(move(crossMwmGraph))
, m_loader(move(loader))
, m_estimator(move(estimator))
, m_hierarchyHandler(std::move(hierarchyHandler))
{
CHECK(m_loader, ());
CHECK(m_estimator, ());
Expand All @@ -35,13 +39,19 @@ void SingleVehicleWorldGraph::CheckAndProcessTransitFeatures(Segment const & par
{
bool opposite = !isOutgoing;
vector<JointEdge> newCrossMwmEdges;

NumMwmId const mwmId = parent.GetMwmId();

for (size_t i = 0; i < jointEdges.size(); ++i)
{
JointSegment const & target = jointEdges[i].GetTarget();
if (!m_crossMwmGraph->IsFeatureTransit(target.GetMwmId(), target.GetFeatureId()))

NumMwmId const edgeMwmId = target.GetMwmId();

if (!m_crossMwmGraph->IsFeatureTransit(edgeMwmId, target.GetFeatureId()))
continue;

auto & currentIndexGraph = GetIndexGraph(parent.GetMwmId());
auto & currentIndexGraph = GetIndexGraph(mwmId);

vector<Segment> twins;
m_crossMwmGraph->GetTwinFeature(target.GetSegment(true /* start */), isOutgoing, twins);
Expand All @@ -66,6 +76,8 @@ void SingleVehicleWorldGraph::CheckAndProcessTransitFeatures(Segment const & par
newCrossMwmEdges.emplace_back(*edge);
newCrossMwmEdges.back().GetTarget().SetFeatureId(twinFeatureId);
newCrossMwmEdges.back().GetTarget().SetMwmId(twinMwmId);
newCrossMwmEdges.back().GetWeight() +=
m_hierarchyHandler.GetCrossBorderPenalty(mwmId, twinMwmId);

parentWeights.emplace_back(parentWeights[i]);
}
Expand Down
6 changes: 5 additions & 1 deletion routing/single_vehicle_world_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "routing/index_graph.hpp"
#include "routing/index_graph_loader.hpp"
#include "routing/joint_segment.hpp"
#include "routing/mwm_hierarchy_handler.hpp"
#include "routing/road_graph.hpp"
#include "routing/route.hpp"
#include "routing/segment.hpp"
Expand All @@ -29,7 +30,8 @@ class SingleVehicleWorldGraph final : public WorldGraph
public:
SingleVehicleWorldGraph(std::unique_ptr<CrossMwmGraph> crossMwmGraph,
std::unique_ptr<IndexGraphLoader> loader,
std::shared_ptr<EdgeEstimator> estimator);
std::shared_ptr<EdgeEstimator> estimator,
MwmHierarchyHandler && hierarchyHandler);

// WorldGraph overrides:
// @{
Expand Down Expand Up @@ -141,5 +143,7 @@ class SingleVehicleWorldGraph final : public WorldGraph

AStarParents<Segment> m_parentsForSegments;
AStarParents<JointSegment> m_parentsForJoints;

MwmHierarchyHandler m_hierarchyHandler;
};
} // namespace routing
1 change: 1 addition & 0 deletions routing/world_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class WorldGraph
virtual CrossMwmGraph & GetCrossMwmGraph();
virtual void GetTwinsInner(Segment const & segment, bool isOutgoing,
std::vector<Segment> & twins) = 0;

protected:
void GetTwins(Segment const & segment, bool isOutgoing, bool useRoutingOptions,
std::vector<SegmentEdge> & edges);
Expand Down
6 changes: 6 additions & 0 deletions routing_common/num_mwm_id.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ class NumMwmIds final
return m_fileToId.find(file) != m_fileToId.cend();
}

bool ContainsFileForMwm(NumMwmId mwmId) const
{
size_t const index = base::asserted_cast<size_t>(mwmId);
return index < m_idToFile.size();
}

platform::CountryFile const & GetFile(NumMwmId mwmId) const
{
size_t const index = base::asserted_cast<size_t>(mwmId);
Expand Down

0 comments on commit 670dfae

Please sign in to comment.