forked from bobluppes/graaf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[BENCH] Bron-Kerbosch clique detection (bobluppes#157)
* - added DFS cycle detection for directed and undirected graph - added tests * - corrected code according to comments * Apply suggestions from code review * - First example of potential use of the library * - small fixes * Update transport-example.md Corrected trailling slashes * clang format fix * reflect breaking changes on main * clang format fix * - corrected according to git comments - relative railway example - corrected png files * small fixes * small fixes * fix issues after merge * fix syntax highlighting code blocks * clang format * - Added MST algorithm - Added test cases and docs * clang style correction * Apply suggestions from code review * Added topological sort algorithm DFS-based * small fixes * clang format fix * added test * more tests * Minor fixes Added one test * Clang format * Update topological-sort.md Corrected doc file * DOCS for DFS based cycle detection * small fixes * Update dfs-based.md * Added Floyd-WArshall algorithm - algorithm - test - documentation * clang tidy * removed redundant negative cicle check and according tests, added two new tests * Bron-Kerbosch algorithm * Added to readme * corrected according to comments * Update README.md * folder name correction, added json to docs * small correction in name and headers * benchmark test Bron-Kerbosch * Changed according to comments --------- Co-authored-by: Bob Luppes <[email protected]>
- Loading branch information
Showing
1 changed file
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
#include <benchmark/benchmark.h> | ||
#include <graaflib/algorithm/clique_detection/bron_kerbosch.h> | ||
#include <graaflib/graph.h> | ||
|
||
#include <random> | ||
#include <vector> | ||
|
||
namespace { | ||
// Generating random number of vertices (1- 30) for a clique | ||
std::random_device dev; | ||
std::mt19937 rng(dev()); | ||
std::uniform_int_distribution<std::mt19937::result_type> random_clique_size(1, | ||
30); | ||
template <typename EDGE_T> | ||
[[nodiscard]] std::vector<graaf::vertex_id_t> create_vertices( | ||
graaf::undirected_graph<int, EDGE_T>& graph, size_t n) { | ||
std::vector<graaf::vertex_id_t> vertices{}; | ||
vertices.reserve(n); | ||
|
||
for (size_t i{0}; i < n; ++i) { | ||
vertices.push_back(graph.add_vertex(i)); | ||
} | ||
|
||
return vertices; | ||
} | ||
|
||
template <typename EDGE_T> | ||
void add_clique(graaf::undirected_graph<int, EDGE_T>& graph, | ||
const std::vector<graaf::vertex_id_t>& vertices, | ||
size_t start_vertex, size_t clique_size) { | ||
// We are in range of vector of vertices | ||
size_t end_vertex = std::min(start_vertex + clique_size, vertices.size()); | ||
|
||
// Constructing a clique | ||
for (size_t i{start_vertex}; i < end_vertex; ++i) { | ||
for (size_t j{i + 1}; j < end_vertex; ++j) { | ||
graph.add_edge(vertices[i], vertices[j], 1); | ||
} | ||
} | ||
} | ||
} // namespace | ||
|
||
static void bron_kerbosh_cliques(benchmark::State& state) { | ||
const auto number_of_edges{static_cast<size_t>(state.range(0))}; | ||
|
||
graaf::undirected_graph<int, int> graph{}; | ||
|
||
// We create enough vertices to construct the requested number of edges | ||
const auto number_of_vertices{number_of_edges + 1}; | ||
const auto vertices{create_vertices(graph, number_of_vertices)}; | ||
const auto clique_size = static_cast<size_t>(state.range(1)); | ||
|
||
for (size_t i{0}; i < number_of_edges; i += clique_size) { | ||
add_clique(graph, vertices, i, clique_size); | ||
} | ||
|
||
for (auto _ : state) { | ||
auto result = graaf::algorithm::bron_kerbosch(graph); | ||
benchmark::DoNotOptimize(result); | ||
} | ||
|
||
state.SetComplexityN(state.range(1)); | ||
} | ||
|
||
static void bron_kerbosh_connected_cliques(benchmark::State& state) { | ||
const auto number_of_edges{static_cast<size_t>(state.range(0))}; | ||
|
||
graaf::undirected_graph<int, int> graph{}; | ||
|
||
// We create enough vertices to construct the requested number of edges | ||
const auto number_of_vertices{number_of_edges + 1}; | ||
const auto vertices{create_vertices(graph, number_of_vertices)}; | ||
const auto clique_size = static_cast<size_t>(state.range(1)); | ||
|
||
// Connecting all cliques | ||
for (size_t i{0}; i + clique_size < number_of_edges; i += clique_size) { | ||
graph.add_edge(vertices[i], vertices[i + clique_size], 1); | ||
} | ||
|
||
for (size_t i{0}; i < number_of_edges; i += clique_size) { | ||
add_clique(graph, vertices, i, clique_size); | ||
} | ||
|
||
for (auto _ : state) { | ||
auto result = graaf::algorithm::bron_kerbosch(graph); | ||
benchmark::DoNotOptimize(result); | ||
} | ||
|
||
state.SetComplexityN(state.range(1)); | ||
} | ||
|
||
static void bron_kerbosh_random_cliques(benchmark::State& state) { | ||
const auto number_of_edges{static_cast<size_t>(state.range(0))}; | ||
|
||
graaf::undirected_graph<int, int> graph{}; | ||
|
||
// We create enough vertices to construct the requested number of edges | ||
const auto number_of_vertices{number_of_edges + 1}; | ||
const auto vertices{create_vertices(graph, number_of_vertices)}; | ||
size_t clique_size = random_clique_size(rng); | ||
|
||
for (size_t i{0}; i + clique_size < number_of_edges; i += clique_size) { | ||
add_clique(graph, vertices, i, clique_size++); | ||
clique_size = random_clique_size(rng); | ||
} | ||
|
||
for (auto _ : state) { | ||
auto result = graaf::algorithm::bron_kerbosch(graph); | ||
benchmark::DoNotOptimize(result); | ||
} | ||
|
||
state.SetComplexityN(state.range(0)); | ||
} | ||
|
||
static void bron_kerbosh_connected_random_cliques(benchmark::State& state) { | ||
const auto number_of_edges{static_cast<size_t>(state.range(0))}; | ||
|
||
graaf::undirected_graph<int, int> graph{}; | ||
|
||
// We create enough vertices to construct the requested number of edges | ||
const auto number_of_vertices{number_of_edges + 1}; | ||
const auto vertices{create_vertices(graph, number_of_vertices)}; | ||
size_t clique_size = random_clique_size(rng); | ||
|
||
// Connecting all cliques | ||
for (size_t i{0}; i < number_of_edges; ++i) { | ||
graph.add_edge(vertices[i], vertices[i + 1], 1); | ||
} | ||
|
||
for (size_t i{0}; i + clique_size < number_of_edges; i += clique_size) { | ||
add_clique(graph, vertices, i, clique_size++); | ||
clique_size = random_clique_size(rng); | ||
} | ||
|
||
for (auto _ : state) { | ||
auto result = graaf::algorithm::bron_kerbosch(graph); | ||
benchmark::DoNotOptimize(result); | ||
} | ||
|
||
state.SetComplexityN(state.range(0)); | ||
} | ||
|
||
BENCHMARK(bron_kerbosh_cliques) | ||
->Ranges({{100, 10000}, {2, 32}}) /* clique size 2 ^ n */ | ||
->Unit(benchmark::kMillisecond) | ||
->Complexity(); | ||
BENCHMARK(bron_kerbosh_connected_cliques) | ||
->Ranges({{100, 10000}, {2, 32}}) /* clique size 2 ^ n */ | ||
->Unit(benchmark::kMillisecond) | ||
->Complexity(); | ||
BENCHMARK(bron_kerbosh_cliques) | ||
->Ranges({{100, 1000}, | ||
{1000, 1000}}) /* Dense graph, number of vertices are | ||
min(state.range(1), vertex.size()) */ | ||
->Unit(benchmark::kMillisecond) | ||
->Complexity(); | ||
BENCHMARK(bron_kerbosh_cliques) | ||
->Ranges({{100, 10000}, {10, 60}}) /* large cliques */ | ||
->Unit(benchmark::kMillisecond) | ||
->Complexity(); | ||
BENCHMARK(bron_kerbosh_connected_cliques) | ||
->Ranges({{100, 10000}, {10, 60}}) /* large cliques */ | ||
->Unit(benchmark::kMillisecond) | ||
->Complexity(); | ||
BENCHMARK(bron_kerbosh_random_cliques) /* random clique size between 1-30 */ | ||
->Range(100, 10000) | ||
->Unit(benchmark::kMillisecond) | ||
->Complexity(); | ||
BENCHMARK( | ||
bron_kerbosh_connected_random_cliques) /* random clique size between 1-30 */ | ||
->Range(100, 10000) | ||
->Unit(benchmark::kMillisecond) | ||
->Complexity(); |