openGPMP
Open Source Mathematics Package
graphs.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file.
25  *
26  *
27  *
28  * This software is distributed on an AS IS basis, WITHOUT
29  * WARRANTY OF ANY KIND, either express or implied.
30  *
31  ************************************************************************/
32 #include <algorithm>
33 #include <bitset>
34 #include <cmath>
35 #include <cstdint>
36 #include <iostream>
37 #include <limits>
39 #include <queue>
40 #include <set>
41 #include <stack>
42 #include <vector>
43 
44 void gpmp::Graph::add_edge(int v, int w, int weight) {
45  adj_list[v].emplace_back(w, weight);
46  adj_list[w].emplace_back(v, weight); // uncomment for undirected graph
47 }
48 
49 void gpmp::Graph::dfs(int start) {
50  std::vector<bool> visited(vertices, false);
51  dfs_rec(start, visited);
52 }
53 
54 void gpmp::Graph::dfs_rec(int v, std::vector<bool> &visited) {
55  visited[v] = true;
56  std::cout << v << " ";
57 
58  for (const auto &neighbor : adj_list[v]) {
59  if (!visited[neighbor.first]) {
60  dfs_rec(neighbor.first, visited);
61  }
62  }
63 }
64 
65 void gpmp::Graph::bfs(int start) {
66  std::vector<bool> visited(vertices, false);
67  std::queue<int> bfs_queue;
68 
69  visited[start] = true;
70  bfs_queue.push(start);
71 
72  while (!bfs_queue.empty()) {
73  int v = bfs_queue.front();
74  bfs_queue.pop();
75  std::cout << v << " ";
76 
77  for (const auto &neighbor : adj_list[v]) {
78  if (!visited[neighbor.first]) {
79  visited[neighbor.first] = true;
80  bfs_queue.push(neighbor.first);
81  }
82  }
83  }
84 }
85 
86 void gpmp::Graph::dijkstra(int start) {
87  std::priority_queue<std::pair<int, int>,
88  std::vector<std::pair<int, int>>,
89  std::greater<std::pair<int, int>>>
90  pq;
91  std::vector<int> dist(vertices, std::numeric_limits<int>::max());
92 
93  dist[start] = 0;
94  pq.push({0, start});
95 
96  while (!pq.empty()) {
97  int u = pq.top().second;
98  pq.pop();
99 
100  for (const auto &neighbor : adj_list[u]) {
101  int v = neighbor.first;
102  int weight = neighbor.second;
103 
104  if (dist[u] + weight < dist[v]) {
105  dist[v] = dist[u] + weight;
106  pq.push({dist[v], v});
107  }
108  }
109  }
110 
111  std::cout << "Dijkstra's Shortest Paths from vertex " << start << ":\n";
112  for (int i = 0; i < vertices; ++i)
113  std::cout << "Vertex " << i << ": " << dist[i] << "\n";
114 }
115 
116 void gpmp::Graph::bellman_ford(int start) {
117  std::vector<int> dist(vertices, std::numeric_limits<int>::max());
118  dist[start] = 0;
119 
120  for (int i = 0; i < vertices - 1; ++i) {
121  for (int u = 0; u < vertices; ++u) {
122  for (const auto &neighbor : adj_list[u]) {
123  int v = neighbor.first;
124  int weight = neighbor.second;
125 
126  if (dist[u] != std::numeric_limits<int>::max() &&
127  dist[u] + weight < dist[v]) {
128  dist[v] = dist[u] + weight;
129  }
130  }
131  }
132  }
133 
134  std::cout << "Bellman-Ford Shortest Paths from vertex " << start << ":\n";
135  for (int i = 0; i < vertices; ++i)
136  std::cout << "Vertex " << i << ": " << dist[i] << "\n";
137 }
138 
139 std::vector<std::pair<int, std::pair<int, int>>> gpmp::Graph::kruskal() {
140  std::vector<std::pair<int, std::pair<int, int>>> edges;
141  for (int u = 0; u < vertices; ++u) {
142  for (const auto &neighbor : adj_list[u]) {
143  int v = neighbor.first;
144  int weight = neighbor.second;
145  edges.emplace_back(weight, std::make_pair(u, v));
146  }
147  }
148 
149  std::sort(edges.begin(), edges.end());
150 
151  std::vector<std::pair<int, std::pair<int, int>>> min_span_tree;
152  std::vector<int> parent(vertices, -1);
153 
154  for (const auto &edge : edges) {
155  int u = edge.second.first;
156  int v = edge.second.second;
157 
158  int setU = find(parent, u);
159  int setV = find(parent, v);
160 
161  if (setU != setV) {
162  min_span_tree.push_back(edge);
163  union_sets(parent, setU, setV);
164  }
165  }
166 
167  return min_span_tree;
168 }
169 
171  std::vector<std::vector<int>> dist(
172  vertices,
173  std::vector<int>(vertices, std::numeric_limits<int>::max()));
174 
175  for (int i = 0; i < vertices; ++i) {
176  dist[i][i] = 0;
177  for (const auto &neighbor : adj_list[i]) {
178  int v = neighbor.first;
179  int weight = neighbor.second;
180  dist[i][v] = weight;
181  }
182  }
183 
184  for (int k = 0; k < vertices; ++k) {
185  for (int i = 0; i < vertices; ++i) {
186  for (int j = 0; j < vertices; ++j) {
187  if (dist[i][k] != std::numeric_limits<int>::max() &&
188  dist[k][j] != std::numeric_limits<int>::max() &&
189  dist[i][k] + dist[k][j] < dist[i][j]) {
190  dist[i][j] = dist[i][k] + dist[k][j];
191  }
192  }
193  }
194  }
195 
196  std::cout << "Floyd-Warshall Shortest Paths:\n";
197  for (int i = 0; i < vertices; ++i) {
198  for (int j = 0; j < vertices; ++j) {
199  std::cout << "From " << i << " to " << j << ": ";
200  if (dist[i][j] == std::numeric_limits<int>::max())
201  std::cout << "INF";
202  else
203  std::cout << dist[i][j];
204  std::cout << "\n";
205  }
206  }
207 }
208 
210  std::stack<int> topo_stack;
211  std::vector<bool> visited(vertices, false);
212 
213  for (int i = 0; i < vertices; ++i) {
214  if (!visited[i]) {
215  topo_sort_util(i, visited, topo_stack);
216  }
217  }
218 
219  std::cout << "Topological Sorting: ";
220  while (!topo_stack.empty()) {
221  std::cout << topo_stack.top() << " ";
222  topo_stack.pop();
223  }
224  std::cout << std::endl;
225 }
226 
228  std::vector<bool> &visited,
229  std::stack<int> &topo_stack) {
230  visited[v] = true;
231 
232  for (const auto &neighbor : adj_list[v]) {
233  int u = neighbor.first;
234  if (!visited[u]) {
235  topo_sort_util(u, visited, topo_stack);
236  }
237  }
238 
239  topo_stack.push(v);
240 }
241 
242 int gpmp::Graph::find(std::vector<int> &parent, int i) {
243  if (parent[i] == -1)
244  return i;
245  return find(parent, parent[i]);
246 }
247 
248 void gpmp::Graph::union_sets(std::vector<int> &parent, int x, int y) {
249  int setX = find(parent, x);
250  int setY = find(parent, y);
251  parent[setX] = setY;
252 }
253 
254 std::vector<std::vector<int>> gpmp::Graph::connected_components() {
255  std::vector<std::vector<int>> components;
256  std::vector<bool> visited(vertices, false);
257 
258  for (int v = 0; v < vertices; ++v) {
259  if (!visited[v]) {
260  std::vector<int> component;
261  dfs_connected_components(v, visited, component);
262  components.push_back(component);
263  }
264  }
265 
266  return components;
267 }
268 
270  std::vector<int> color(vertices, -1);
271  std::queue<int> bfs_queue;
272 
273  for (int start = 0; start < vertices; ++start) {
274  if (color[start] == -1) {
275  color[start] = 0;
276  bfs_queue.push(start);
277 
278  while (!bfs_queue.empty()) {
279  int v = bfs_queue.front();
280  bfs_queue.pop();
281 
282  for (const auto &neighbor : adj_list[v]) {
283  int u = neighbor.first;
284  if (color[u] == -1) {
285  color[u] = 1 - color[v];
286  bfs_queue.push(u);
287  } else if (color[u] == color[v]) {
288  return false; // Not bipartite
289  }
290  }
291  }
292  }
293  }
294 
295  return true; // Bipartite
296 }
297 
298 std::vector<double> gpmp::Graph::betweenness_centrality() {
299  std::vector<double> centrality(vertices, 0.0);
300 
301  for (int s = 0; s < vertices; ++s) {
302  std::vector<int> predecessors(vertices, -1);
303  std::vector<int> distance(vertices, -1);
304  std::vector<int> num_shortest_paths(vertices, 0);
305  std::stack<int> stack;
306  std::queue<int> bfs_queue;
307 
308  distance[s] = 0;
309  num_shortest_paths[s] = 1;
310  bfs_queue.push(s);
311 
312  while (!bfs_queue.empty()) {
313  int v = bfs_queue.front();
314  bfs_queue.pop();
315  stack.push(v);
316 
317  for (const auto &neighbor : adj_list[v]) {
318  int w = neighbor.first;
319  if (distance[w] == -1) {
320  distance[w] = distance[v] + 1;
321  bfs_queue.push(w);
322  }
323 
324  if (distance[w] == distance[v] + 1) {
325  num_shortest_paths[w] += num_shortest_paths[v];
326  predecessors[w] = v;
327  }
328  }
329  }
330 
331  std::vector<double> dependency(vertices, 0.0);
332 
333  while (!stack.empty()) {
334  int w = stack.top();
335  stack.pop();
336 
337  for (const auto &predecessor : adj_list[w]) {
338  int v = predecessor.first;
339  dependency[v] += (static_cast<double>(num_shortest_paths[v]) /
340  num_shortest_paths[w]) *
341  (1 + dependency[w]);
342  }
343 
344  if (w != s) {
345  centrality[w] += dependency[w];
346  }
347  }
348  }
349 
350  return centrality;
351 }
352 
354  std::vector<bool> &visited,
355  std::vector<int> &component) {
356  visited[v] = true;
357  component.push_back(v);
358 
359  for (const auto &neighbor : adj_list[v]) {
360  int u = neighbor.first;
361  if (!visited[u]) {
362  dfs_connected_components(u, visited, component);
363  }
364  }
365 }
366 
368  std::vector<int> path;
369  std::vector<bool> visited(vertices, false);
370 
371  for (int v = 0; v < vertices; ++v) {
372  path.clear();
373  if (hamiltonian_circuit_util(v, visited, path, 1)) {
374  return true;
375  }
376  }
377 
378  return false;
379 }
380 
382  // A connected graph has an Eulerian path if and only if it has exactly 0 or
383  // 2 vertices with an odd degree.
384  int odd_degrees = 0;
385 
386  for (int v = 0; v < vertices; ++v) {
387  if (adj_list[v].size() % 2 != 0) {
388  ++odd_degrees;
389  }
390  }
391 
392  return odd_degrees == 0 || odd_degrees == 2;
393 }
394 
396  std::vector<bool> &visited,
397  std::vector<int> &path,
398  int count) {
399  visited[v] = true;
400  path.push_back(v);
401 
402  if (count == vertices) {
403  // all vertices are visited; check if there is an edge from the last
404  // added vertex to the starting vertex
405  for (const auto &neighbor : adj_list[v]) {
406  if (neighbor.first == path[0]) {
407  return true; // Hamiltonian circuit found
408  }
409  }
410  } else {
411  // recursive step to try all vertices as the next one in the Hamiltonian
412  // circuit
413  for (const auto &neighbor : adj_list[v]) {
414  if (!visited[neighbor.first]) {
415  if (hamiltonian_circuit_util(neighbor.first,
416  visited,
417  path,
418  count + 1)) {
419  return true;
420  }
421  }
422  }
423  }
424 
425  // backtrack
426  visited[v] = false;
427  path.pop_back();
428  return false;
429 }
430 
431 int gpmp::Graph::eccentricity(int vertex) {
432  std::vector<int> distance(vertices, std::numeric_limits<int>::max());
433  distance[vertex] = 0;
434 
435  std::queue<int> bfs_queue;
436  bfs_queue.push(vertex);
437 
438  while (!bfs_queue.empty()) {
439  int v = bfs_queue.front();
440  bfs_queue.pop();
441 
442  for (const auto &neighbor : adj_list[v]) {
443  int u = neighbor.first;
444  if (distance[u] == std::numeric_limits<int>::max()) {
445  distance[u] = distance[v] + 1;
446  bfs_queue.push(u);
447  }
448  }
449  }
450 
451  // the eccentricity is the maximum distance from the given vertex
452  return *std::max_element(distance.begin(), distance.end());
453 }
454 
455 // method to calculate the radius of the graph
457  int min_ecntrc = std::numeric_limits<int>::max();
458 
459  for (int v = 0; v < vertices; ++v) {
460  int vEccentricity = eccentricity(v);
461  min_ecntrc = std::min(min_ecntrc, vEccentricity);
462  }
463 
464  return min_ecntrc;
465 }
466 
468  std::vector<int> result(vertices, -1);
469 
470  // assign the first color to the first vertex
471  result[0] = 0;
472 
473  // initialize available colors. For each vertex, remove colors used by its
474  // neighbors.
475  std::vector<bool> available(vertices, false);
476  for (const auto &neighbor : adj_list[0]) {
477  int v = neighbor.first;
478  if (result[v] != -1) {
479  available[result[v]] = true;
480  }
481  }
482 
483  // assign colors to the remaining vertices
484  for (int v = 1; v < vertices; ++v) {
485  for (int c = 0; c < vertices; ++c) {
486  if (!available[c]) {
487  result[v] = c;
488  break;
489  }
490  }
491 
492  // reset available colors for the next vertex
493  std::fill(available.begin(), available.end(), false);
494 
495  // update available colors for neighbors
496  for (const auto &neighbor : adj_list[v]) {
497  int u = neighbor.first;
498  if (result[u] != -1) {
499  available[result[u]] = true;
500  }
501  }
502  }
503 
504  // find the maximum color assigned, which represents the chromatic number
505  int chrom_num = *std::max_element(result.begin(), result.end()) + 1;
506 
507  return chrom_num;
508 }
509 
510 // method to perform graph coloring using the greedy algorithm
511 std::vector<int> gpmp::Graph::greedy_coloring() {
512  std::vector<int> result(vertices, -1);
513 
514  // assign colors to vertices
515  for (int v = 0; v < vertices; ++v) {
516  std::vector<bool> available(vertices, false);
517  for (const auto &neighbor : adj_list[v]) {
518  int u = neighbor.first;
519  if (result[u] != -1) {
520  available[result[u]] = true;
521  }
522  }
523 
524  for (int c = 0; c < vertices; ++c) {
525  if (!available[c]) {
526  result[v] = c;
527  break;
528  }
529  }
530  }
531 
532  return result;
533 }
534 
535 std::vector<std::pair<int, int>> gpmp::Graph::match_cardinality() {
536  std::vector<std::pair<int, int>> matching;
537 
538  // iterate through each vertex and find unmatched neighbors
539  for (int v = 0; v < vertices; ++v) {
540  if (!is_matched[v]) {
541  for (const auto &neighbor : adj_list[v]) {
542  int u = neighbor.first;
543  if (!is_matched[u]) {
544  matching.push_back({v, u});
545  is_matched[v] = true;
546  is_matched[u] = true;
547  break;
548  }
549  }
550  }
551  }
552 
553  return matching;
554 }
555 
556 // method to find a maximum weight matching in the graph using greedy algorithm
557 std::vector<std::pair<int, int>> gpmp::Graph::match_wt() {
558  std::vector<std::pair<int, int>> matching;
559 
560  // sort edges in descending order based on weights
561  std::vector<std::pair<std::pair<int, int>, int>> wt_edges;
562  for (int v = 0; v < vertices; ++v) {
563  for (const auto &neighbor : adj_list[v]) {
564  int u = neighbor.first;
565  int weight = neighbor.second;
566  wt_edges.push_back({{v, u}, weight});
567  }
568  }
569 
570  std::sort(wt_edges.rbegin(),
571  wt_edges.rend(),
572  [](const auto &a, const auto &b) { return a.second < b.second; });
573 
574  // iterate through sorted edges and add to matching if both vertices are
575  // unmatched
576  for (const auto &edge : wt_edges) {
577  int v = edge.first.first;
578  int u = edge.first.second;
579  if (!is_matched[v] && !is_matched[u]) {
580  matching.push_back({v, u});
581  is_matched[v] = true;
582  is_matched[u] = true;
583  }
584  }
585 
586  return matching;
587 }
588 
590  // planar graphs satisfy Kuratowski's theorem: they do not contain a
591  // subgraph that is a subdivision of K5 or K3,3.
592  return !has_k5() && !has_k33();
593 }
594 
595 // method to generate a random planar graph using the random geometric graph
596 // model
597 void gpmp::Graph::planar_gen(int num_vertices, double radius) {
598  vertices = num_vertices;
599  adj_list.resize(vertices);
600 
601  // generate random points in a 2D plane
602  std::vector<std::pair<double, double>> points;
603  for (int v = 0; v < vertices; ++v) {
604  double x = static_cast<double>(rand()) / RAND_MAX;
605  double y = static_cast<double>(rand()) / RAND_MAX;
606  points.push_back({x, y});
607  }
608 
609  // connect vertices if their Euclidean distance is less than the specified
610  // radius
611  for (int v = 0; v < vertices; ++v) {
612  for (int u = v + 1; u < vertices; ++u) {
613  double distance = euclid_dist(points[v], points[u]);
614  if (distance < radius) {
615  // TODO the weight of the generated edges should probably be
616  // determined algorithmically
617  add_edge(v, u, 0);
618  }
619  }
620  }
621 }
622 
623 // method to check if the graph contains a subgraph that is a subdivision of K5
625  for (int v = 0; v < vertices; ++v) {
626  if (adj_list[v].size() >= 5) {
627  std::set<int> neighbors;
628  for (const auto &neighbor : adj_list[v]) {
629  neighbors.insert(neighbor.first);
630  }
631 
632  for (const auto &u : neighbors) {
633  std::set<int> common_neighbors;
634  for (const auto &neighbor : adj_list[u]) {
635  if (neighbors.find(neighbor.first) != neighbors.end()) {
636  common_neighbors.insert(neighbor.first);
637  }
638  }
639 
640  for (const auto &w : common_neighbors) {
641  if (neighbors.find(w) != neighbors.end()) {
642  return true;
643  }
644  }
645  }
646  }
647  }
648 
649  return false;
650 }
651 
652 // method to check if the graph contains a subgraph that is a subdivision of
653 // K3,3
655  for (int v = 0; v < vertices; ++v) {
656  if (adj_list[v].size() >= 3) {
657  std::set<int> neighbors;
658  for (const auto &neighbor : adj_list[v]) {
659  neighbors.insert(neighbor.first);
660  }
661 
662  if (is_k33(neighbors)) {
663  return true;
664  }
665  }
666  }
667 
668  return false;
669 }
670 
671 // helper method to check if a set of vertices forms a K3,3 subgraph
672 bool gpmp::Graph::is_k33(const std::set<int> &k_vertices) {
673  if (k_vertices.size() == 6) {
674  int degree_sum = 0;
675  for (int v : k_vertices) {
676  degree_sum += adj_list[v].size();
677  }
678 
679  // Cast vertices.size() to int to avoid the comparison warning
680  return degree_sum == 2 * static_cast<int>(k_vertices.size());
681  }
682  return false;
683 }
684 
685 // helper method to calculate the Euclidean distance between two points
686 double gpmp::Graph::euclid_dist(const std::pair<double, double> &point1,
687  const std::pair<double, double> &point2) {
688  double dx = point1.first - point2.first;
689  double dy = point1.second - point2.second;
690  return std::sqrt(dx * dx + dy * dy);
691 }
692 
693 std::vector<uint64_t> gpmp::Graph::compress() {
694  std::vector<uint64_t> compressed;
695  compressed.push_back(vertices);
696 
697  for (int v = 0; v < vertices; ++v) {
698  // encode the number of neighbors using Elias Gamma encoding
699  std::bitset<64> binary_representation(adj_list[v].size() + 1);
700  int length = log2(adj_list[v].size() + 1) + 1;
701 
702  // store the length of the encoded number
703  compressed.push_back(length);
704 
705  // store the encoded number
706  compressed.push_back(
707  std::stoull(binary_representation.to_string(), 0, 2));
708 
709  // store the neighbors
710  for (const auto &neighbor : adj_list[v]) {
711  compressed.push_back(neighbor.first);
712  }
713  }
714 
715  return compressed;
716 }
717 
718 // method to decompress a compressed graph using the Elias Gamma encoding
719 void gpmp::Graph::decompress(const std::vector<uint64_t> &compressed) {
720  int index = 0;
721  vertices = compressed[index++];
722 
723  adj_list.resize(vertices);
724 
725  for (int v = 0; v < vertices; ++v) {
726  int length = compressed[index++];
727  uint64_t encoded_neighbors = compressed[index++];
728  std::bitset<64> binary_representation(encoded_neighbors);
729 
730  // decode the number of neighbors
731  int num_neighbors =
732  std::stoi(binary_representation.to_string().substr(64 - length),
733  nullptr,
734  2) -
735  1;
736 
737  // decode and add neighbors
738  for (int i = 0; i < num_neighbors; ++i) {
739  adj_list[v].emplace_back(compressed[index++],
740  0); // TODO assuming unweighted graph
741  }
742  }
743 }
bool has_hamiltonian_circuit()
Checks if the graph contains a Hamiltonian circuit.
Definition: graphs.cpp:367
int radius()
Calculates the radius of the graph.
Definition: graphs.cpp:456
bool has_k5()
Checks if the graph contains a subgraph that is a subdivision of K5.
Definition: graphs.cpp:624
std::vector< std::pair< int, std::pair< int, int > > > kruskal()
Applies Kruskal's algorithm to find the minimum spanning tree of the graph.
Definition: graphs.cpp:139
void dfs(int start)
Performs Depth-First Search (DFS) traversal starting from a given vertex.
Definition: graphs.cpp:49
void bellman_ford(int start)
Applies Bellman-Ford algorithm to find the single-source shortest paths in the graph,...
Definition: graphs.cpp:116
bool is_bipartite()
Determines if a given graph is bipartite using BFS (Breadth First Search)
Definition: graphs.cpp:269
std::vector< std::vector< std::pair< int, int > > > adj_list
Definition: graphs.hpp:52
void add_edge(int v, int w, int weight)
Adds an edge between two vertices with a specified weight.
Definition: graphs.cpp:44
std::vector< std::pair< int, int > > match_wt()
Finds a maximum weight matching in the graph using a greedy algorithm.
Definition: graphs.cpp:557
int chromatic_number()
Calculates the chromatic number of the graph.
Definition: graphs.cpp:467
int eccentricity(int vertex)
Calculates the eccentricity of a specified vertex in the graph.
Definition: graphs.cpp:431
void bfs(int start)
Performs Breadth-First Search (BFS) traversal starting from a given vertex.
Definition: graphs.cpp:65
int find(std::vector< int > &parent, int i)
Finds the representative element of the set that contains the given element.
Definition: graphs.cpp:242
std::vector< double > betweenness_centrality()
Calculates betweenness centrality for each vertex in the graph.
Definition: graphs.cpp:298
std::vector< int > greedy_coloring()
Performs graph coloring using the greedy algorithm.
Definition: graphs.cpp:511
bool hamiltonian_circuit_util(int v, std::vector< bool > &visited, std::vector< int > &path, int count)
Utility function for finding a Hamiltonian circuit.
Definition: graphs.cpp:395
double euclid_dist(const std::pair< double, double > &point1, const std::pair< double, double > &point2)
Calculates the Euclidean distance between two 2D points.
Definition: graphs.cpp:686
std::vector< uint64_t > compress()
Compresses the graph using Elias Gamma encoding.
Definition: graphs.cpp:693
std::vector< std::vector< int > > connected_components()
Finds connected components in an undirected graph using Depth-First Search (DFS)
Definition: graphs.cpp:254
void decompress(const std::vector< uint64_t > &compressed)
Decompresses a compressed graph using Elias Gamma encoding.
Definition: graphs.cpp:719
void dfs_rec(int v, std::vector< bool > &visited)
Helper function for recursive Depth-First Search (DFS) traversal.
Definition: graphs.cpp:54
void topo_sort_util(int v, std::vector< bool > &visited, std::stack< int > &topo_stack)
Helper function for topological sorting.
Definition: graphs.cpp:227
void planar_gen(int num_vertices, double radius)
Generates a random planar graph using the random geometric graph model.
Definition: graphs.cpp:597
std::vector< std::pair< int, int > > match_cardinality()
Finds a maximum cardinality matching in the graph using a greedy algorithm.
Definition: graphs.cpp:535
bool has_eulerian_path()
Checks if the graph contains an Eulerian path.
Definition: graphs.cpp:381
void floyd_warshall()
Applies Floyd-Warshall algorithm to find all-pairs shortest paths in the graph.
Definition: graphs.cpp:170
void dfs_connected_components(int v, std::vector< bool > &visited, std::vector< int > &component)
Performs Depth-First Search (DFS) traversal to find connected components in an undirected graph.
Definition: graphs.cpp:353
void dijkstra(int start)
Applies Dijkstra's algorithm to find the single-source shortest paths in the graph.
Definition: graphs.cpp:86
bool is_k33(const std::set< int > &k_vertices)
Checks if a set of vertices forms a subgraph that is a subdivision of K3,3.
Definition: graphs.cpp:672
void union_sets(std::vector< int > &parent, int x, int y)
Unions two sets by rank in the disjoint set data structure.
Definition: graphs.cpp:248
bool is_planar()
Checks if the graph is planar using Kuratowski's theorem.
Definition: graphs.cpp:589
bool has_k33()
Checks if the graph contains a subgraph that is a subdivision of K3,3.
Definition: graphs.cpp:654
void topo_sort()
Performs topological sorting on a Directed Acyclic Graph (DAG)
Definition: graphs.cpp:209
static GLfloat u