Skip to content

Commit

Permalink
Fix node merging to allow for splitting later on
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMarex committed Jun 1, 2017
1 parent 8fbe528 commit 5c7288a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 48 deletions.
8 changes: 6 additions & 2 deletions include/partition/edge_based_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ struct EdgeBasedGraphEdgeData : extractor::EdgeBasedEdge::EdgeData
{
using Base = extractor::EdgeBasedEdge::EdgeData;
using Base::Base;
// We need to write out the full edge based graph again.

// TODO: in case we want to modify the graph we need to store a boundary_arc flag here
EdgeBasedGraphEdgeData(const EdgeBasedGraphEdgeData&) = default;
EdgeBasedGraphEdgeData(EdgeBasedGraphEdgeData&&) = default;
EdgeBasedGraphEdgeData& operator=(const EdgeBasedGraphEdgeData&) = default;
EdgeBasedGraphEdgeData& operator=(EdgeBasedGraphEdgeData&&) = default;
EdgeBasedGraphEdgeData(const Base& base) : Base(base) {}
EdgeBasedGraphEdgeData() : Base() {}
};

struct DynamicEdgeBasedGraph : util::DynamicGraph<EdgeBasedGraphEdgeData>
Expand Down
105 changes: 59 additions & 46 deletions include/partition/edge_based_graph_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,80 +60,88 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
template <typename OutputEdgeT>
std::vector<OutputEdgeT> prepareEdgesForUsageInGraph(std::vector<extractor::EdgeBasedEdge> edges)
{
std::sort(begin(edges), end(edges));
// sort into blocks of edges with same source + target
// the we partition by the forward flag to sort all edges with a forward direction first.
// the we sort by weight to ensure the first forward edge is the smallest forward edge
std::sort(begin(edges), end(edges), [](const auto &lhs, const auto &rhs) {
return std::tie(lhs.source, lhs.target, rhs.data.forward, lhs.data.weight) <
std::tie(rhs.source, rhs.target, lhs.data.forward, rhs.data.weight);
});

std::vector<OutputEdgeT> graph_edges;
graph_edges.reserve(edges.size());
std::vector<OutputEdgeT> output_edges;
output_edges.reserve(edges.size());

for (NodeID i = 0; i < edges.size();)
for (auto begin_interval = edges.begin(); begin_interval != edges.end();)
{
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
const NodeID source = begin_interval->source;
const NodeID target = begin_interval->target;

auto end_interval =
std::find_if_not(begin_interval, edges.end(), [source, target](const auto &edge) {
return std::tie(edge.source, edge.target) == std::tie(source, target);
});
BOOST_ASSERT(begin_interval != end_interval);

// remove eigenloops
if (source == target)
{
++i;
begin_interval = end_interval;
continue;
}

OutputEdgeT forward_edge;
OutputEdgeT reverse_edge;
forward_edge.source = reverse_edge.source = source;
forward_edge.target = reverse_edge.target = target;
forward_edge.data.turn_id = reverse_edge.data.turn_id = edges[i].data.turn_id;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION_INT_30;
forward_edge.data.forward = reverse_edge.data.backward = true;
forward_edge.data.backward = reverse_edge.data.forward = false;

// remove parallel edges
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
BOOST_ASSERT_MSG(begin_interval->data.forward != begin_interval->data.backward,
"The forward and backward flag need to be mutally exclusive");

// find smallest backward edge and check if we can merge
auto first_backward = std::find_if(
begin_interval, end_interval, [](const auto &edge) { return edge.data.backward; });

// thanks to the sorting we know this is the smallest backward edge
// and there is no forward edge
if (begin_interval == first_backward)
{
if (edges[i].data.forward)
{
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
forward_edge.data.duration =
std::min(edges[i].data.duration, forward_edge.data.duration);
}
if (edges[i].data.backward)
{
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
reverse_edge.data.duration =
std::min(edges[i].data.duration, reverse_edge.data.duration);
}
++i;
output_edges.push_back(OutputEdgeT{source, target, first_backward->data});
}
// merge edges (s,t) and (t,s) into bidirectional edge
if (forward_edge.data.weight == reverse_edge.data.weight)
// only a forward edge, thanks to the sorting this is the smallest
else if (first_backward == end_interval)
{
if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT)
{
forward_edge.data.backward = true;
graph_edges.push_back(forward_edge);
}
output_edges.push_back(OutputEdgeT{source, target, begin_interval->data});
}
// we have both a forward and a backward edge, we need to evaluate
// if we can merge them
else
{ // insert seperate edges
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
{
BOOST_ASSERT(begin_interval->data.forward);
BOOST_ASSERT(first_backward->data.backward);
BOOST_ASSERT(first_backward != end_interval);

// same weight, so we can just merge them
if (begin_interval->data.weight == first_backward->data.weight)
{
graph_edges.push_back(forward_edge);
OutputEdgeT merged{source, target, begin_interval->data};
merged.data.backward = true;
output_edges.push_back(std::move(merged));
}
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
// we need to insert separate forward and reverse edges
else
{
graph_edges.push_back(reverse_edge);
output_edges.push_back(OutputEdgeT{source, target, begin_interval->data});
output_edges.push_back(OutputEdgeT{source, target, first_backward->data});
}
}

begin_interval = end_interval;
}

return graph_edges;
return output_edges;
}

std::vector<extractor::EdgeBasedEdge> graphToEdges(const DynamicEdgeBasedGraph &edge_based_graph)
{
auto range = tbb::blocked_range<NodeID>(0, edge_based_graph.GetNumberOfNodes());
auto max_turn_id =
tbb::parallel_reduce(range, NodeID{0},
tbb::parallel_reduce(range,
NodeID{0},
[&edge_based_graph](const auto range, NodeID initial) {
NodeID max_turn_id = initial;
for (auto node = range.begin(); node < range.end(); ++node)
Expand All @@ -160,11 +168,16 @@ std::vector<extractor::EdgeBasedEdge> graphToEdges(const DynamicEdgeBasedGraph &
if (data.forward)
{
auto target = edge_based_graph.GetTarget(edge);
BOOST_ASSERT(data.turn_id <= max_turn_id);
edges[data.turn_id] = extractor::EdgeBasedEdge{node, target, data};
// only save the forward edge
edges[data.turn_id].data.forward = true;
edges[data.turn_id].data.backward = false;
}
}
}
});

return edges;
}

Expand Down

0 comments on commit 5c7288a

Please sign in to comment.