123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- #ifndef CERES_INTERNAL_GRAPH_ALGORITHMS_H_
- #define CERES_INTERNAL_GRAPH_ALGORITHMS_H_
- #include <algorithm>
- #include <memory>
- #include <unordered_map>
- #include <unordered_set>
- #include <utility>
- #include <vector>
- #include "ceres/graph.h"
- #include "ceres/internal/export.h"
- #include "ceres/wall_time.h"
- #include "glog/logging.h"
- namespace ceres::internal {
- template <typename Vertex>
- class CERES_NO_EXPORT VertexTotalOrdering {
- public:
- explicit VertexTotalOrdering(const Graph<Vertex>& graph) : graph_(graph) {}
- bool operator()(const Vertex& lhs, const Vertex& rhs) const {
- if (graph_.Neighbors(lhs).size() == graph_.Neighbors(rhs).size()) {
- return lhs < rhs;
- }
- return graph_.Neighbors(lhs).size() < graph_.Neighbors(rhs).size();
- }
- private:
- const Graph<Vertex>& graph_;
- };
- template <typename Vertex>
- class VertexDegreeLessThan {
- public:
- explicit VertexDegreeLessThan(const Graph<Vertex>& graph) : graph_(graph) {}
- bool operator()(const Vertex& lhs, const Vertex& rhs) const {
- return graph_.Neighbors(lhs).size() < graph_.Neighbors(rhs).size();
- }
- private:
- const Graph<Vertex>& graph_;
- };
- template <typename Vertex>
- int IndependentSetOrdering(const Graph<Vertex>& graph,
- std::vector<Vertex>* ordering) {
- const std::unordered_set<Vertex>& vertices = graph.vertices();
- const int num_vertices = vertices.size();
- CHECK(ordering != nullptr);
- ordering->clear();
- ordering->reserve(num_vertices);
-
- const char kWhite = 0;
- const char kGrey = 1;
- const char kBlack = 2;
-
- std::unordered_map<Vertex, char> vertex_color;
- std::vector<Vertex> vertex_queue;
- for (const Vertex& vertex : vertices) {
- vertex_color[vertex] = kWhite;
- vertex_queue.push_back(vertex);
- }
- std::sort(vertex_queue.begin(),
- vertex_queue.end(),
- VertexTotalOrdering<Vertex>(graph));
-
-
- for (const Vertex& vertex : vertex_queue) {
- if (vertex_color[vertex] != kWhite) {
- continue;
- }
- ordering->push_back(vertex);
- vertex_color[vertex] = kBlack;
- const std::unordered_set<Vertex>& neighbors = graph.Neighbors(vertex);
- for (const Vertex& neighbor : neighbors) {
- vertex_color[neighbor] = kGrey;
- }
- }
- int independent_set_size = ordering->size();
-
-
-
- for (const Vertex& vertex : vertex_queue) {
- DCHECK(vertex_color[vertex] != kWhite);
- if (vertex_color[vertex] != kBlack) {
- ordering->push_back(vertex);
- }
- }
- CHECK_EQ(ordering->size(), num_vertices);
- return independent_set_size;
- }
- template <typename Vertex>
- int StableIndependentSetOrdering(const Graph<Vertex>& graph,
- std::vector<Vertex>* ordering) {
- CHECK(ordering != nullptr);
- const std::unordered_set<Vertex>& vertices = graph.vertices();
- const int num_vertices = vertices.size();
- CHECK_EQ(vertices.size(), ordering->size());
-
- const char kWhite = 0;
- const char kGrey = 1;
- const char kBlack = 2;
- std::vector<Vertex> vertex_queue(*ordering);
- std::stable_sort(vertex_queue.begin(),
- vertex_queue.end(),
- VertexDegreeLessThan<Vertex>(graph));
-
- std::unordered_map<Vertex, char> vertex_color;
- for (const Vertex& vertex : vertices) {
- vertex_color[vertex] = kWhite;
- }
- ordering->clear();
- ordering->reserve(num_vertices);
-
-
- for (int i = 0; i < vertex_queue.size(); ++i) {
- const Vertex& vertex = vertex_queue[i];
- if (vertex_color[vertex] != kWhite) {
- continue;
- }
- ordering->push_back(vertex);
- vertex_color[vertex] = kBlack;
- const std::unordered_set<Vertex>& neighbors = graph.Neighbors(vertex);
- for (const Vertex& neighbor : neighbors) {
- vertex_color[neighbor] = kGrey;
- }
- }
- int independent_set_size = ordering->size();
-
-
-
- for (const Vertex& vertex : vertex_queue) {
- DCHECK(vertex_color[vertex] != kWhite);
- if (vertex_color[vertex] != kBlack) {
- ordering->push_back(vertex);
- }
- }
- CHECK_EQ(ordering->size(), num_vertices);
- return independent_set_size;
- }
- template <typename Vertex>
- Vertex FindConnectedComponent(const Vertex& vertex,
- std::unordered_map<Vertex, Vertex>* union_find) {
- auto it = union_find->find(vertex);
- DCHECK(it != union_find->end());
- if (it->second != vertex) {
- it->second = FindConnectedComponent(it->second, union_find);
- }
- return it->second;
- }
- template <typename Vertex>
- std::unique_ptr<WeightedGraph<Vertex>> Degree2MaximumSpanningForest(
- const WeightedGraph<Vertex>& graph) {
-
- std::vector<std::pair<double, std::pair<Vertex, Vertex>>> weighted_edges;
- auto forest = std::make_unique<WeightedGraph<Vertex>>();
-
-
- std::unordered_map<Vertex, Vertex> disjoint_set;
-
-
-
-
- const std::unordered_set<Vertex>& vertices = graph.vertices();
- for (const Vertex& vertex1 : vertices) {
- forest->AddVertex(vertex1, graph.VertexWeight(vertex1));
- disjoint_set[vertex1] = vertex1;
- const std::unordered_set<Vertex>& neighbors = graph.Neighbors(vertex1);
- for (const Vertex& vertex2 : neighbors) {
- if (vertex1 >= vertex2) {
- continue;
- }
- const double weight = graph.EdgeWeight(vertex1, vertex2);
- weighted_edges.push_back(
- std::make_pair(weight, std::make_pair(vertex1, vertex2)));
- }
- }
-
-
-
- std::sort(weighted_edges.rbegin(), weighted_edges.rend());
-
-
- for (int i = 0; i < weighted_edges.size(); ++i) {
- const std::pair<Vertex, Vertex>& edge = weighted_edges[i].second;
- const Vertex vertex1 = edge.first;
- const Vertex vertex2 = edge.second;
-
-
-
- if ((forest->Neighbors(vertex1).size() == 2) ||
- (forest->Neighbors(vertex2).size() == 2)) {
- continue;
- }
-
-
-
-
- Vertex root1 = FindConnectedComponent(vertex1, &disjoint_set);
- Vertex root2 = FindConnectedComponent(vertex2, &disjoint_set);
- if (root1 == root2) {
- continue;
- }
-
-
- const double edge_weight = graph.EdgeWeight(vertex1, vertex2);
- forest->AddEdge(vertex1, vertex2, edge_weight);
- forest->AddEdge(vertex2, vertex1, edge_weight);
-
-
-
-
-
- if (root2 < root1) {
- std::swap(root1, root2);
- }
- disjoint_set[root2] = root1;
- }
- return forest;
- }
- }
- #endif
|