1
0
Fork 0

Minor code rearrangement

This commit is contained in:
Joris van Rantwijk 2024-11-10 00:10:26 +01:00
parent 7ea1562cc7
commit 39eaea451e
1 changed files with 47 additions and 42 deletions

View File

@ -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) {