Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BENCH] Bron-Kerbosch clique detection #157

Merged
merged 63 commits into from
Oct 19, 2023
Merged
Changes from 1 commit
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
3fe9e21
- added DFS cycle detection for directed and undirected graph
Hromz Jul 24, 2023
a629352
- corrected code according to comments
Hromz Jul 25, 2023
99f77cd
Apply suggestions from code review
bobluppes Jul 25, 2023
956eac3
Merge branch 'bobluppes:main' into main
Hromz Jul 28, 2023
3ec396d
Merge branch 'bobluppes:main' into main
Hromz Jul 29, 2023
3ba348d
Merge branch 'bobluppes:main' into main
Hromz Aug 1, 2023
432b6b4
- First example of potential use of the library
Hromz Aug 1, 2023
97ccea7
- small fixes
Hromz Aug 1, 2023
3e55e23
Update transport-example.md
Hromz Aug 2, 2023
286e9ce
Merge remote-tracking branch 'upstream/main'
bobluppes Aug 5, 2023
419b663
clang format fix
bobluppes Aug 5, 2023
2408835
Merge remote-tracking branch 'upstream/main'
bobluppes Aug 5, 2023
7e459bf
reflect breaking changes on main
bobluppes Aug 5, 2023
6fc3af0
clang format fix
bobluppes Aug 5, 2023
767a532
- corrected according to git comments
Hromz Aug 12, 2023
8ebb5f4
small fixes
Hromz Aug 12, 2023
ffe4553
small fixes
Hromz Aug 12, 2023
bb28f8c
Merge remote-tracking branch 'upstream/main'
bobluppes Aug 13, 2023
ce5df25
fix issues after merge
bobluppes Aug 13, 2023
1c82f04
fix syntax highlighting code blocks
bobluppes Aug 13, 2023
1c644a0
clang format
bobluppes Aug 13, 2023
a0fde77
Merge branch 'bobluppes:main' into main
Hromz Aug 13, 2023
2ae7d97
Merge branch 'bobluppes:main' into main
Hromz Aug 13, 2023
a3a3b31
Merge branch 'bobluppes:main' into main
Hromz Aug 15, 2023
c05cd27
- Added MST algorithm
Hromz Aug 18, 2023
b5db653
clang style correction
Hromz Aug 18, 2023
057ee77
Apply suggestions from code review
bobluppes Aug 31, 2023
9e92f3f
Merge remote-tracking branch 'upstream/main'
bobluppes Aug 31, 2023
665a484
Merge branch 'bobluppes:main' into main
Hromz Sep 1, 2023
5dce08b
Added topological sort algorithm DFS-based
Hromz Sep 5, 2023
03200f7
Merge branch 'main' into main
Hromz Sep 5, 2023
f8cd4fb
small fixes
Hromz Sep 5, 2023
21cde40
Merge branch 'main' of https://github.com/Hromz/graaf
Hromz Sep 5, 2023
14f0b8d
clang format fix
Hromz Sep 5, 2023
7efd134
added test
Hromz Sep 5, 2023
0bcad82
more tests
Hromz Sep 5, 2023
f96849a
Minor fixes
Hromz Sep 10, 2023
57d3c47
Clang format
Hromz Sep 10, 2023
c5ddba1
Update topological-sort.md
Hromz Sep 10, 2023
3c94ab6
Merge branch 'bobluppes:main' into main
Hromz Sep 13, 2023
19ea438
DOCS for DFS based cycle detection
Hromz Sep 14, 2023
68c2c2b
small fixes
Hromz Sep 14, 2023
55d3972
Update dfs-based.md
Hromz Sep 18, 2023
39487bd
Merge branch 'bobluppes:main' into main
Hromz Sep 19, 2023
da97d62
Added Floyd-WArshall algorithm
Hromz Sep 24, 2023
7a1ca3c
clang tidy
Hromz Sep 24, 2023
4a43bce
removed redundant negative cicle check and according tests, added two…
Hromz Sep 27, 2023
773a708
Merge branch 'bobluppes:main' into main
Hromz Sep 28, 2023
e0a2978
Merge branch 'bobluppes:main' into main
Hromz Sep 30, 2023
8441998
Merge branch 'bobluppes:main' into main
Hromz Sep 30, 2023
4e843a9
Merge branch 'bobluppes:main' into main
Hromz Oct 2, 2023
f3274c9
Bron-Kerbosch algorithm
Hromz Oct 6, 2023
9ac7524
Added to readme
Hromz Oct 6, 2023
14ccc5a
corrected according to comments
Hromz Oct 9, 2023
27e6894
Update README.md
Hromz Oct 9, 2023
f7ce62d
Merge branch 'main' into main
Hromz Oct 9, 2023
6969839
folder name correction, added json to docs
Hromz Oct 9, 2023
7f19ab7
Merge branch 'main' of https://github.com/Hromz/graaf
Hromz Oct 9, 2023
0f9ffe8
small correction in name and headers
Hromz Oct 9, 2023
0fb11b1
Merge branch 'bobluppes:main' into main
Hromz Oct 10, 2023
116e1f5
Merge branch 'bobluppes:main' into main
Hromz Oct 11, 2023
ef490b8
benchmark test Bron-Kerbosch
Hromz Oct 12, 2023
7b42950
Changed according to comments
Hromz Oct 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
- First example of potential use of the library
Hromz committed Aug 1, 2023
commit 432b6b437212f4ebc50a8cb13d31bedb4cfad652
118 changes: 118 additions & 0 deletions docs/docs/examples/example-basics/transport-example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
sidebar_position: 2
---

# Network Example
The undirected_graph implemented in `graaf::undirected_graph`
The shortest path algorithm implemented in `graaf::algorithm::get_shortest_path`
The graph traversal implemented in `graaf::algorithm::graph_traversal`

Using the following graph:

<pre>
<p align="center">
<img src={require("\static\img\examples\example_usage.png").default}></img>
</p>
</pre>

Custom vertex and edge. In order to use Dijkstra, we should provide the get_weight() function for the edge.

```c++
struct station {
int id{};
std::string name{};
double gaz_capacity{};
};

struct road {
int length{};
int get_weight() { return length; }
};
```

# Initializing graph, start and end vertecies
First, we create data structure and initializing graph with vertices and edges

```c++
struct graph_with_start_and_target {
graaf::undirected_graph<station, road> graph{};
graaf::vertex_id_t start{};
graaf::vertex_id_t target{};
};

graph_with_start_and_target create_graph_with_start_and_target() {
...
}
```

## Visualizing graph traversal result
For shortest path, colouring edges with red to indicate the shortest path for both weighted and unweighted graph

Result of unweighted shortest path, chosen edges are coloured red
<pre>
<p align="center">
<img src={require("\static\img\examples\example_shortest_path_unweighted.png").default}></img>
</p>
</pre>

Result of weighted shortest path, chosen edges are coloured red
<pre>
<p align="center">
<img src={require("\static\img\examples\example_shortest_path_weighted.png").default}></img>
</p>
</pre>


```c++
void print_shortest_path(const graaf::undirected_graph<station, road>& graph,
const std::optional<graaf::algorithm::GraphPath<int>>& path, const std::string & filepath) {
...
}

void print_visited_vertices(const graaf::undirected_graph<station, road>& graph,
seen_vertices_t& seen,
const std::string& filepath) {
...
}
```

Creating a vertex callback structure that will be passed as an argument in the graph traverse function
The function is needed in order to be called inside the traverse function; see graph.tpp file lines 15 and 45 for context.

```c++
using seen_vertices_t = std::unordered_multiset<graaf::vertex_id_t>;
struct record_vertex_callback {
seen_vertices_t& seen_vertices;

record_vertex_callback(seen_vertices_t& seen_vertices)
: seen_vertices{seen_vertices} {}

void operator()(const graaf::vertex_id_t vertex) const {
seen_vertices.insert(vertex);
}
};
```

### Graph example usage
First code block: traversing a weighted graph for the shortest path (Dijkstra) and printing the result to *.dot file.
Second code block: traversing an unweighted graph for the shortest path and printing the result to *.dot file.
The last one is traversing the graph from a given vertex and printing the result to *.dot file.

```c++
const auto [graph, start, target]{create_graph_with_start_and_target()};

const auto weighted_shortest_path{graaf::algorithm::get_shortest_path<
graaf::algorithm::edge_strategy::WEIGHTED, station, road,
graaf::graph_spec::UNDIRECTED, int>(graph, start, target)};
print_shortest_path(graph, weighted_shortest_path, "example_weighted_graph.dot");

const auto unweighted_shortest_path{graaf::algorithm::get_shortest_path<
graaf::algorithm::edge_strategy::UNWEIGHTED, station, road,
graaf::graph_spec::UNDIRECTED, int>(graph, start, target)};
print_shortest_path(graph, unweighted_shortest_path, "example_unwieghted_graph.dot");

seen_vertices_t seen_vertices{};
graaf::algorithm::traverse<graaf::algorithm::search_strategy::BFS>(
graph, start, record_vertex_callback{seen_vertices});
print_visited_vertices(graph, seen_vertices, "example_traverse_BFS_graph.dot");
```
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/examples/example_usage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ foreach (EXAMPLE ${EXAMPLES})
add_executable(
${PROJECT_NAME}_${EXAMPLE_NAME}_example
${EXAMPLE}
)
)

# Include src such that we can #include <graaflib/*> in the sources
target_include_directories(${PROJECT_NAME}_${EXAMPLE_NAME}_example PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include)
154 changes: 154 additions & 0 deletions examples/transport/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#include <fmt/core.h>
#include <graaflib/algorithm/graph_traversal.h>
#include <graaflib/algorithm/shortest_path.h>
#include <graaflib/io/dot.h>
#include <graaflib/types.h>
#include <graaflib/undirected_graph.h>

struct station {
std::string name{};
double gaz_capacity{};
};

struct road {
int length{};
int get_weight() { return length; }
};

struct graph_with_start_and_target {
graaf::undirected_graph<station, road> graph{};
graaf::vertex_id_t start{};
graaf::vertex_id_t target{};
};

graph_with_start_and_target create_graph_with_start_and_target() {
graaf::undirected_graph<station, road> my_stations{};

const auto station_1{my_stations.add_vertex(station{"Road 66", 13.5})};
const auto station_2{my_stations.add_vertex(station{"Long road", 7.3})};
const auto station_3{my_stations.add_vertex(station{"Stop & Buy", 25.4})};
const auto station_4{my_stations.add_vertex(station{"GAZilla", 11.3})};
const auto station_5{my_stations.add_vertex(station{"Station 32", 73.12})};
const auto station_6{my_stations.add_vertex(station{"Last stop", 0.5})};
const auto station_7{my_stations.add_vertex(station{"You won't reach it", 55.5})};
const auto station_8{my_stations.add_vertex(station{"Went for lunch break", 66.5})};

my_stations.add_edge(station_1, station_2, road{125});
my_stations.add_edge(station_2, station_4, road{205});
my_stations.add_edge(station_4, station_5, road{325});
my_stations.add_edge(station_5, station_3, road{1725});
my_stations.add_edge(station_6, station_3, road{88});
my_stations.add_edge(station_1, station_5, road{77});
my_stations.add_edge(station_5, station_2, road{93});
my_stations.add_edge(station_5, station_6, road{193});
my_stations.add_edge(station_7, station_8, road{5});

return {my_stations, station_1, station_3};
}

void print_shortest_path(const graaf::undirected_graph<station, road>& graph,
const std::optional<graaf::algorithm::GraphPath<int>>& path,
const std::string& filepath) {

auto shortest_path{path.value()};
std::unordered_set<graaf::edge_id_t, graaf::edge_id_hash>
edges_on_shortest_path{};

graaf::vertex_id_t prev{shortest_path.vertices.front()};
shortest_path.vertices.pop_front();
for (const auto current : shortest_path.vertices) {
edges_on_shortest_path.insert(std::make_pair(prev, current));
prev = current;
}

const auto vertex_writer{
[](graaf::vertex_id_t vertex_id, station vertex) -> std::string {
const auto style{"solid"};
return fmt::format("label=\"{}: {}\", style={}, color=black, fontcolor=black",
vertex.name, style);
}};

const auto edge_writer{[&edges_on_shortest_path](
const graaf::edge_id_t& edge_id,
const auto& edge) -> std::string {
const auto style{"solid"};
if (edges_on_shortest_path.contains({edge_id.first, edge_id.second}) ||
edges_on_shortest_path.contains({edge_id.second, edge_id.first})) {
return fmt::format("label=\"{}\", style={}, color=red, fontcolor=black",
edge->length, style);
}
return fmt::format("label=\"{}\", style={}, color=black, fontcolor=black",
edge->length, style);
}};

const std::filesystem::path output{filepath};
graaf::io::to_dot(graph, output, vertex_writer, edge_writer);
}

using seen_vertices_t = std::unordered_multiset<graaf::vertex_id_t>;
struct record_vertex_callback {
seen_vertices_t& seen_vertices;

record_vertex_callback(seen_vertices_t& seen_vertices)
: seen_vertices{seen_vertices} {}

void operator()(const graaf::vertex_id_t vertex) const {
seen_vertices.insert(vertex);
}
};

void print_visited_vertices(const graaf::undirected_graph<station, road>& graph,
seen_vertices_t& seen,
const std::string& filepath) {
std::unordered_set<graaf::edge_id_t, graaf::edge_id_hash> seen_edges{};

for (const auto current : graph.get_edges()) {
const auto from = current.first.first;
const auto to = current.first.second;
if (seen.contains(from) && seen.contains(to))
seen_edges.insert({from, to});
}

const auto vertex_writer{
[](graaf::vertex_id_t vertex_id, station vertex) -> std::string {
const auto style{"solid"};

return fmt::format(
"label=\"{}: {}\", style={}, color=gray, fontcolor=black",
vertex.name, style);
}};

const auto edge_writer{[&seen_edges](const graaf::edge_id_t& edge_id,
const auto& edge) -> std::string {
const auto style{"solid"};

if (seen_edges.contains({edge_id.first, edge_id.second}) ||
seen_edges.contains({edge_id.second, edge_id.first}))
return fmt::format("label=\"{}\", style={}, color=red, fontcolor=black",
edge->length, style);
return fmt::format("label=\"{}\", style={}, color=black, fontcolor=black",
edge->length, style);
}};

const std::filesystem::path output{filepath};
graaf::io::to_dot(graph, output, vertex_writer, edge_writer);
}

int main() {
const auto [graph, start, target]{create_graph_with_start_and_target()};

const auto weighted_shortest_path{graaf::algorithm::get_shortest_path<
graaf::algorithm::edge_strategy::WEIGHTED, station, road,
graaf::graph_spec::UNDIRECTED, int>(graph, start, target)};
print_shortest_path(graph, weighted_shortest_path, "example_weighted_graph.dot");

const auto unweighted_shortest_path{graaf::algorithm::get_shortest_path<
graaf::algorithm::edge_strategy::UNWEIGHTED, station, road,
graaf::graph_spec::UNDIRECTED, int>(graph, start, target)};
print_shortest_path(graph, unweighted_shortest_path, "example_unwieghted_graph.dot");

seen_vertices_t seen_vertices{};
graaf::algorithm::traverse<graaf::algorithm::search_strategy::BFS>(
graph, start, record_vertex_callback{seen_vertices});
print_visited_vertices(graph, seen_vertices, "example_traverse_BFS_graph.dot");
}