Minor code rearrangement
This commit is contained in:
parent
7ea1562cc7
commit
39eaea451e
|
@ -70,10 +70,10 @@ namespace impl {
|
|||
constexpr VertexId NO_VERTEX = std::numeric_limits<VertexId>::max();
|
||||
|
||||
/** Type representing an index in the edge list. */
|
||||
using EdgeIndex = unsigned int;
|
||||
using EdgeId = unsigned int;
|
||||
|
||||
/** Value used to mark an invalid or undefined vertex. */
|
||||
constexpr EdgeIndex NO_EDGE = std::numeric_limits<EdgeIndex>::max();
|
||||
constexpr EdgeId NO_EDGE = std::numeric_limits<EdgeId>::max();
|
||||
|
||||
/** Top-level blossoms may be labeled "S" or "T" or unlabeled. */
|
||||
enum BlossomLabel { LABEL_NONE = 0, LABEL_S = 1, LABEL_T = 2 };
|
||||
|
@ -178,7 +178,7 @@ struct Graph
|
|||
const VertexId num_vertex;
|
||||
|
||||
/** For each vertex, a vector of pointers to its incident edges. */
|
||||
const std::vector<std::vector<EdgeIndex>> adjacent_edges;
|
||||
const std::vector<std::vector<EdgeId>> adjacent_edges;
|
||||
|
||||
/**
|
||||
* Initialize the graph representation and prepare adjacent edge lists.
|
||||
|
@ -244,7 +244,7 @@ struct Graph
|
|||
* @param edges List of edges in the graph.
|
||||
* @return Vector of incident edges for each vertex.
|
||||
*/
|
||||
static std::vector<std::vector<EdgeIndex>> build_adjacent_edges(
|
||||
static std::vector<std::vector<EdgeId>> build_adjacent_edges(
|
||||
const std::vector<EdgeT>& edges,
|
||||
VertexId num_vertex)
|
||||
{
|
||||
|
@ -258,11 +258,11 @@ struct Graph
|
|||
}
|
||||
|
||||
// Build adjacency lists.
|
||||
std::vector<std::vector<EdgeIndex>> adjacent_edges(num_vertex);
|
||||
std::vector<std::vector<EdgeId>> adjacent_edges(num_vertex);
|
||||
for (VertexId i = 0; i < num_vertex; ++i) {
|
||||
adjacent_edges[i].reserve(vertex_degree[i]);
|
||||
}
|
||||
for (EdgeIndex e = 0; e < edges.size(); e++) {
|
||||
for (EdgeId e = 0; e < edges.size(); e++) {
|
||||
const EdgeT& edge = edges[e];
|
||||
adjacent_edges[edge.vt.first].push_back(e);
|
||||
adjacent_edges[edge.vt.second].push_back(e);
|
||||
|
@ -326,8 +326,6 @@ struct Blossom
|
|||
|
||||
// TODO -- vertex_dual_offset
|
||||
|
||||
// TODO -- marker
|
||||
|
||||
// TODO -- remove
|
||||
/**
|
||||
* In case of a top-level S-blossom, "best_edge" is the least-slack edge
|
||||
|
@ -599,8 +597,11 @@ public:
|
|||
|
||||
// TODO -- delta2_queue
|
||||
|
||||
/** Queue of edges between S-vertices in different top-level blossoms. */
|
||||
typedef PriorityQueue<WeightType, EdgeIndex> EdgeQueue;
|
||||
/**
|
||||
* Queue of edges between S-vertices in different top-level blossoms.
|
||||
* Priority of an edge is its slack plus 2 * delta_sum.
|
||||
*/
|
||||
typedef PriorityQueue<WeightType, EdgeId> EdgeQueue;
|
||||
EdgeQueue delta3_queue;
|
||||
|
||||
/** For each edge, a node in delta3_queue. */
|
||||
|
@ -622,11 +623,9 @@ public:
|
|||
/** Queue of S-vertices to be scanned. */
|
||||
std::vector<VertexId> scan_queue;
|
||||
|
||||
// TODO -- delete
|
||||
/** Markers placed while tracing an alternating path. */
|
||||
std::vector<bool> vertex_marker;
|
||||
|
||||
// TODO -- delete
|
||||
/** Vertices marked while tracing an alternating path. */
|
||||
std::vector<VertexId> marked_vertex;
|
||||
|
||||
|
@ -697,7 +696,7 @@ public:
|
|||
* Modified edge slack is related to true edge slack, but adjusted
|
||||
* to make it invariant under delta steps.
|
||||
*/
|
||||
WeightType edge_pseudo_slack(EdgeIndex e) const
|
||||
WeightType edge_pseudo_slack(EdgeId e) const
|
||||
{
|
||||
const EdgeT& edge = graph.edges[e];
|
||||
VertexId x = edge.vt.first;
|
||||
|
@ -737,13 +736,17 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Add edge "e" from an S-vertex to unlabeled vertex or T-vertex "y".
|
||||
* Add edge "e" for delta2 tracking.
|
||||
*
|
||||
* This function takes time O(1) per call.
|
||||
* This function is called O(m) times per stage.
|
||||
* Edge "e" connects an S-vertex to a T-vertex or unlabeled vertex "y".
|
||||
*
|
||||
* This function takes time O(log(n)).
|
||||
*/
|
||||
void lset_add_vertex_edge(VertexId y, const EdgeT* edge, WeightType slack)
|
||||
void delta2_add_edge(EdgeId e, VertexId y, BlossomT* by)
|
||||
{
|
||||
// TODO
|
||||
const EdgeT* edge = &graph.edges[e];
|
||||
WeightType slack = edge_slack(*edge);
|
||||
const EdgeT* cur_best_edge = vertex_best_edge[y];
|
||||
if ((cur_best_edge == nullptr)
|
||||
|| (slack < edge_slack(*cur_best_edge))) {
|
||||
|
@ -752,16 +755,15 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the index and slack of the least-slack edge between
|
||||
* any S-vertex and unlabeled vertex.
|
||||
* Find the least-slack edge between any S-vertex and any unlabeled vertex.
|
||||
*
|
||||
* This function takes time O(n) per call.
|
||||
* This function takes total time O(n**2) per stage.
|
||||
* This function takes time O(n).
|
||||
* TODO -- rework: This function takes time O(log(n)).
|
||||
*
|
||||
* @return Pair (edge, slack) if there is a least-slack edge,
|
||||
* or (nullptr, 0) if there is no suitable edge.
|
||||
* @return Tuple (edge_index, slack) if there is an S-to-unlabeled edge,
|
||||
* or (NO_EDGE, 0) if there is no such edge.
|
||||
*/
|
||||
std::pair<const EdgeT*, WeightType> lset_get_best_vertex_edge()
|
||||
std::tuple<EdgeId, WeightType> delta2_get_min_edge()
|
||||
{
|
||||
const EdgeT* best_edge = nullptr;
|
||||
WeightType best_slack = 0;
|
||||
|
@ -779,7 +781,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
return std::make_pair(best_edge, best_slack);
|
||||
if (best_edge) {
|
||||
return std::make_tuple(best_edge - graph.edges.data(), best_slack);
|
||||
} else {
|
||||
return std::make_tuple(NO_EDGE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -790,7 +796,7 @@ public:
|
|||
*
|
||||
* This function takes time O(log(n)).
|
||||
*/
|
||||
void delta3_add_edge(EdgeIndex e)
|
||||
void delta3_add_edge(EdgeId e)
|
||||
{
|
||||
// The edge may already be in the delta3 queue, if it was previously
|
||||
// iscovered in the opposite direction. In that case do nothing.
|
||||
|
@ -809,7 +815,7 @@ public:
|
|||
*
|
||||
* This function takes time O(log(n)).
|
||||
*/
|
||||
void delta3_remove_edge(EdgeIndex e)
|
||||
void delta3_remove_edge(EdgeId e)
|
||||
{
|
||||
if (delta3_node[e].valid()) {
|
||||
delta3_queue.remove(&delta3_node[e]);
|
||||
|
@ -826,10 +832,10 @@ public:
|
|||
* @return Tuple (edge_index, slack) if there is an S-to-S edge,
|
||||
* or (NO_EDGE, 0) if there is no suitable edge.
|
||||
*/
|
||||
std::tuple<EdgeIndex, WeightType> delta3_get_min_edge()
|
||||
std::tuple<EdgeId, WeightType> delta3_get_min_edge()
|
||||
{
|
||||
while (! delta3_queue.empty()) {
|
||||
EdgeIndex e = delta3_queue.min_elem();
|
||||
EdgeId e = delta3_queue.min_elem();
|
||||
const EdgeT& edge = graph.edges[e];
|
||||
BlossomT* bx = top_level_blossom(edge.vt.first);
|
||||
BlossomT* by = top_level_blossom(edge.vt.second);
|
||||
|
@ -1449,7 +1455,7 @@ public:
|
|||
|
||||
// Scan the edges that are incident on "x".
|
||||
// This loop runs through O(m) iterations per stage.
|
||||
for (EdgeIndex e : graph.adjacent_edges[x]) {
|
||||
for (EdgeId e : graph.adjacent_edges[x]) {
|
||||
const EdgeT& edge = graph.edges[e];
|
||||
VertexId y = (edge.vt.first != x) ? edge.vt.first
|
||||
: edge.vt.second;
|
||||
|
@ -1467,8 +1473,7 @@ public:
|
|||
} else {
|
||||
// Edge to T-vertex or unlabeled vertex.
|
||||
// Add to delta2 tracking.
|
||||
WeightType slack = edge_slack(edge);
|
||||
lset_add_vertex_edge(y, &edge, slack);
|
||||
delta2_add_edge(e, y, by);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1491,7 +1496,7 @@ public:
|
|||
*
|
||||
* @return Tuple (delta_type, delta_value, delta_edge, delta_blossom)
|
||||
*/
|
||||
DeltaStep substage_calc_dual_delta()
|
||||
DeltaStep calc_dual_delta_step()
|
||||
{
|
||||
DeltaStep delta;
|
||||
delta.blossom = nullptr;
|
||||
|
@ -1507,18 +1512,17 @@ public:
|
|||
|
||||
// Compute delta2: minimum slack of any edge between an S-vertex and
|
||||
// an unlabeled vertex.
|
||||
const EdgeT* edge;
|
||||
EdgeId e;
|
||||
WeightType slack;
|
||||
std::tie(edge, slack) = lset_get_best_vertex_edge();
|
||||
if ((edge != nullptr) && (slack <= delta.value)) {
|
||||
std::tie(e, slack) = delta2_get_min_edge();
|
||||
if ((e != NO_EDGE) && (slack <= delta.value)) {
|
||||
delta.kind = 2;
|
||||
delta.value = slack;
|
||||
delta.edge = edge->vt;
|
||||
delta.edge = graph.edges[e].vt;
|
||||
}
|
||||
|
||||
// Compute delta3: half minimum slack of any edge between two
|
||||
// top-level S-blossoms.
|
||||
EdgeIndex e;
|
||||
std::tie(e, slack) = delta3_get_min_edge();
|
||||
if ((e != NO_EDGE) && (slack / 2 <= delta.value)) {
|
||||
delta.kind = 3;
|
||||
|
@ -1567,8 +1571,6 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
delta_sum += delta;
|
||||
}
|
||||
|
||||
/* ********** Main algorithm: ********** */
|
||||
|
@ -1638,11 +1640,14 @@ public:
|
|||
scan_new_s_vertices();
|
||||
|
||||
// Calculate delta step in the dual LPP problem.
|
||||
DeltaStep delta = substage_calc_dual_delta();
|
||||
DeltaStep delta = calc_dual_delta_step();
|
||||
|
||||
// Apply the delta step to the dual variables.
|
||||
substage_apply_delta_step(delta.value);
|
||||
|
||||
// Update the running sum of delta steps.
|
||||
delta_sum += delta.value;
|
||||
|
||||
if (delta.kind == 2) {
|
||||
// Use the edge from S-vertex to unlabeled vertex that got
|
||||
// unlocked through the delta update.
|
||||
|
@ -1891,7 +1896,7 @@ private:
|
|||
// For each incident edge, find the smallest blossom
|
||||
// that contains it.
|
||||
VertexId x = sub->base_vertex;
|
||||
for (EdgeIndex e : graph.adjacent_edges[x]) {
|
||||
for (EdgeId e : graph.adjacent_edges[x]) {
|
||||
const EdgeT* edge = &graph.edges[e];
|
||||
// Only consider edges pointing out from "x".
|
||||
if (edge->vt.first == x) {
|
||||
|
|
Loading…
Reference in New Issue