Skip to content

Commit

Permalink
Add triangle counting implementation and simple test
Browse files Browse the repository at this point in the history
  • Loading branch information
kdeweese committed Nov 26, 2023
1 parent 95f3c4d commit ff79ed6
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 0 deletions.
16 changes: 16 additions & 0 deletions data/tc_test.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM,TO,DIST
A,B,1
A,C,1
A,D,1
A,E,1
B,C,1
B,D,1
B,E,1
C,D,1
E,C,1
D,E,1
B,F,1
E,F,1
E,G,1
F,H,1
G,H,1
73 changes: 73 additions & 0 deletions include/graph/algorithm/tc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* @file tc.hpp
*
* @brief Minimum spanning tree using Kruskal's and Prim's algorithms.
*
* @copyright Copyright (c) 2022
*
* SPDX-License-Identifier: BSL-1.0
*
* @authors
* Andrew Lumsdaine
* Phil Ratzloff
* Kevin Deweese
*/

#include "graph/graph.hpp"

#ifndef GRAPH_MST_HPP
# define GRAPH_MST_HPP

namespace std::graph {

/**
* @ingroup graph_algorithms
* @brief Find the number of triangles in a graph.
*
* Complexity: O(|V|^3)
*
* @tparam G The graph type.
*
* @param g The graph.
*/
template <adjacency_list G>
requires ranges::random_access_range<vertex_range_t<G>> && integral<vertex_id_t<G>>
size_t triangle_count(G&& g) {
size_t N(size(vertices(g)));
size_t triangles(0);

for (vertex_id_t<G> uid = 0; uid < N; ++uid) {
std::graph::incidence_iterator<G> i(g, uid);
auto ie = ranges::end(edges(g, uid));
while (i != ie) {
auto&& [vid, uv] = *i;
if(vid < uid) {
++i;
continue;
}
std::graph::incidence_iterator<G> j(g, vid);
auto je = ranges::end(edges(g, vid));
auto i2 = i;

// Alternatively use std::set_intersection(i2, ie, j, je, counter) but this is slower
while (i2 != ie && j != je) {
auto&& [wid1, uw] = *i2;
auto&& [wid2, vw] = *j;
if (wid1 < wid2) {
++i2;
} else if (wid2 < wid1) {
++j;
} else {
++triangles;
++i2;
++j;
}
}
++i;
}
}
return triangles;
}
} // namespace std::graph

#endif //GRAPH_MST_HPP
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ set(UNITTEST_SOURCES
"mis_tests.cpp"
"pagerank_tests.cpp"
"mst_tests.cpp"
"tc_tests.cpp"
)

foreach(SOURCE IN LISTS UNITTEST_SOURCES)
Expand Down
25 changes: 25 additions & 0 deletions tests/tc_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <catch2/catch.hpp>
#include "csv_routes.hpp"
#include "graph/graph.hpp"
#include "graph/algorithm/tc.hpp"
#include "graph/container/dynamic_graph.hpp"
#include "graph/views/incidence.hpp"
#ifdef _MSC_VER
# include "Windows.h"
#endif

using std::cout;
using std::endl;

using routes_vol_graph_traits = std::graph::container::vol_graph_traits<double, std::string, std::string>;
using routes_vol_graph_type = std::graph::container::dynamic_adjacency_graph<routes_vol_graph_traits>;

TEST_CASE("triangle counting test", "[tc]") {
init_console();

using G = routes_vol_graph_type;
auto&& g = load_ordered_graph<G>(TEST_DATA_ROOT_DIR "tc_test.csv", name_order_policy::alphabetical, true);

size_t triangles = std::graph::triangle_count(g);
REQUIRE(triangles == 11);
}

0 comments on commit ff79ed6

Please sign in to comment.