From 3f0ac1bbf4ff7244a1d8d64be00330b33eb22691 Mon Sep 17 00:00:00 2001 From: Phil Ratzloff Date: Mon, 2 Sep 2024 17:05:18 -0400 Subject: [PATCH] Add skeletons for bfs, dfs & topo_sort algos These will be used for training. --- .../graph/algorithm/breadth_first_search.hpp | 115 ++++++++++++++++++ .../graph/algorithm/depth_first_search.hpp | 115 ++++++++++++++++++ .../algorithm/dijkstra_shortest_paths.hpp | 2 +- include/graph/algorithm/topological_sort.hpp | 114 +++++++++++++++++ tests/CMakeLists.txt | 4 + tests/breadth_first_search_tests.cpp | 48 ++++++++ tests/depth_first_search_tests.cpp | 47 +++++++ tests/topological_sort_tests.cpp | 48 ++++++++ 8 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 include/graph/algorithm/breadth_first_search.hpp create mode 100644 include/graph/algorithm/depth_first_search.hpp create mode 100644 include/graph/algorithm/topological_sort.hpp create mode 100644 tests/breadth_first_search_tests.cpp create mode 100644 tests/depth_first_search_tests.cpp create mode 100644 tests/topological_sort_tests.cpp diff --git a/include/graph/algorithm/breadth_first_search.hpp b/include/graph/algorithm/breadth_first_search.hpp new file mode 100644 index 0000000..ed10d45 --- /dev/null +++ b/include/graph/algorithm/breadth_first_search.hpp @@ -0,0 +1,115 @@ +/** + * @file breadth_first_search.hpp + * + * @brief Single-Source & multi-source breadth-first search. + * + * @copyright Copyright (c) 2024 + * + * SPDX-License-Identifier: BSL-1.0 + * + * @authors + */ + +#include "graph/graph.hpp" +#include "graph/views/incidence.hpp" + +#include +#include +#include +#include +#include + +#ifndef GRAPH_BREADTH_FIRST_SEARCH_HPP +# define GRAPH_BREADTH_FIRST_SEARCH_HPP + +namespace graph { + +using vertex_id_type = int; +using Graph = std::vector>; +using Predecessors = std::vector; +using Source = vertex_id_type; +using Sources = std::vector; +using Distance = int; +using Distances = std::vector; + +class dfs_visitor_base { + // Types +public: + // Visitor Functions +public: + // vertex visitor functions + void on_initialize_vertex(const vertex_id_type& uid) {} + void on_discover_vertex(const vertex_id_type& uid) {} + void on_examine_vertex(const vertex_id_type& uid) {} + void on_finish_vertex(const vertex_id_type& uid) {} + + // edge visitor functions + void on_examine_edge(const vertex_id_type& uid) {} +}; + +/** + * @ingroup graph_algorithms + * @brief Returns the largest value used to represent an infinite distance. + * + * @return The largest possible distance value. +*/ +inline Distance bfs_infinite_distance() { return std::numeric_limits::max(); } + +/** + * @ingroup graph_algorithms + * @brief Returns a distance value of zero. + * + * @return A value of zero distance. +*/ +inline Distance bfs_zero() { return 0; } + +/** + * @ingroup graph_algorithms + * @brief Intializes the distance values to the infinite value. + * + * @param distances The range of distance values to initialize. +*/ +inline void init_bfs(Distances& distances) { + for (size_t i = 0; i < distances.size(); ++i) { + distances[i] = bfs_infinite_distance(); + } +} + +/** + * @ingroup graph_algorithms + * @brief Intializes the distance and predecessor values for bfs. + * + * @param distances The range of distance values to initialize. Each value will be assigned the infinite distance. + * @param predecessors The range of predecessors to initialize. Each value will be assigned the vertex id. +*/ +inline void init_bfs(Distances& distances, Predecessors& predecessors) { + init_bfs(distances); + for (size_t i = 0; i < predecessors.size(); ++i) { + predecessors[i] = i; + } +} + +/** + * @brief Single-source breadth-first search. + * + * @param g The graph. + * @param source The source vertex. + * @param predecessors The predecessor vertex for g[uid]. + */ + +// C++ +inline void +breadth_first_search(const Graph& g, const Source& source, Distances& distances, Predecessors& predecessors) {} + +// C +inline void breadth_first_search(const Graph* g, + const Source source, + const size_t distances_len, + Distances* distances, + const size_t predecessors_len, + Predecessors* predecessors) {} + + +} // namespace graph + +#endif // GRAPH_BREADTH_FIRST_SEARCH_HPP diff --git a/include/graph/algorithm/depth_first_search.hpp b/include/graph/algorithm/depth_first_search.hpp new file mode 100644 index 0000000..8dd65a0 --- /dev/null +++ b/include/graph/algorithm/depth_first_search.hpp @@ -0,0 +1,115 @@ +/** + * @file depth_first_search.hpp + * + * @brief Single-Source & multi-source depth-first search. + * + * @copyright Copyright (c) 2024 + * + * SPDX-License-Identifier: BSL-1.0 + * + * @authors + */ + +#include "graph/graph.hpp" +#include "graph/views/incidence.hpp" + +#include +#include +#include +#include +#include + +#ifndef GRAPH_DFS_ALGORITHM_HPP +# define GRAPH_DFS_ALGORITHM_HPP + +namespace graph { + +using vertex_id_type = int; +using Graph = std::vector>; +using Predecessors = std::vector; +using Source = vertex_id_type; +using Sources = std::vector; +using Distance = int; +using Distances = std::vector; + +class dfs_visitor_base { + // Types +public: + // Visitor Functions +public: + // vertex visitor functions + void on_initialize_vertex(const vertex_id_type& uid) {} + void on_discover_vertex(const vertex_id_type& uid) {} + void on_examine_vertex(const vertex_id_type& uid) {} + void on_finish_vertex(const vertex_id_type& uid) {} + + // edge visitor functions + void on_examine_edge(const vertex_id_type& uid) {} +}; + +/** + * @ingroup graph_algorithms + * @brief Returns the largest value used to represent an infinite distance. + * + * @return The largest possible distance value. +*/ +inline Distance dfs_infinite_distance() { return std::numeric_limits::max(); } + +/** + * @ingroup graph_algorithms + * @brief Returns a distance value of zero. + * + * @return A value of zero distance. +*/ +inline Distance dfs_zero() { return 0; } + +/** + * @ingroup graph_algorithms + * @brief Intializes the distance values to the infinite value. + * + * @param distances The range of distance values to initialize. +*/ +inline void init_dfs(Distances& distances) { + for (size_t i = 0; i < distances.size(); ++i) { + distances[i] = dfs_infinite_distance(); + } +} + +/** + * @ingroup graph_algorithms + * @brief Intializes the distance and predecessor values for dfs. + * + * @param distances The range of distance values to initialize. Each value will be assigned the infinite distance. + * @param predecessors The range of predecessors to initialize. Each value will be assigned the vertex id. +*/ +inline void init_dfs(Distances& distances, Predecessors& predecessors) { + init_dfs(distances); + for (size_t i = 0; i < predecessors.size(); ++i) { + predecessors[i] = i; + } +} + +/** + * @brief Single-source depth-first search. + * + * @param g The graph. + * @param source The source vertex. + * @param predecessors The predecessor vertex for g[uid]. + */ + +// C++ +inline void +depth_first_search(const Graph& g, const Source& source, Distances& distances, Predecessors& predecessors) {} + +// C +inline void depth_first_search(const Graph* g, + const Source source, + const size_t distances_len, + Distances* distances, + const size_t predecessors_len, + Predecessors* predecessors) {} + + +} // namespace graph + +#endif // GRAPH_DFS_ALGORITHM_HPP diff --git a/include/graph/algorithm/dijkstra_shortest_paths.hpp b/include/graph/algorithm/dijkstra_shortest_paths.hpp index 667d43e..c409f55 100644 --- a/include/graph/algorithm/dijkstra_shortest_paths.hpp +++ b/include/graph/algorithm/dijkstra_shortest_paths.hpp @@ -1,7 +1,7 @@ /** * @file dijkstra_shortest_paths.hpp * - * @brief Single-Source Shortest paths and shortest distances algorithms using Dijkstra's algorithm. + * @brief Single-Source & multi-source shortest paths & shortest distances algorithms using Dijkstra's algorithm. * * @copyright Copyright (c) 2024 * diff --git a/include/graph/algorithm/topological_sort.hpp b/include/graph/algorithm/topological_sort.hpp new file mode 100644 index 0000000..a58bc6a --- /dev/null +++ b/include/graph/algorithm/topological_sort.hpp @@ -0,0 +1,114 @@ +/** + * @file topological_sort.hpp + * + * @brief Single-Source & multi-source topological sort search. + * + * @copyright Copyright (c) 2024 + * + * SPDX-License-Identifier: BSL-1.0 + * + * @authors + */ + +#include "graph/graph.hpp" +#include "graph/views/incidence.hpp" + +#include +#include +#include +#include +#include + +#ifndef GRAPH_TOPO_SORT_ALGO_HPP +# define GRAPH_TOPO_SORT_ALGO_HPP + +namespace graph { + +using vertex_id_type = int; +using Graph = std::vector>; +using Predecessors = std::vector; +using Source = vertex_id_type; +using Sources = std::vector; +using Distance = int; +using Distances = std::vector; + +class topological_sort_visitor_base { + // Types +public: + // Visitor Functions +public: + // vertex visitor functions + void on_initialize_vertex(const vertex_id_type& uid) {} + void on_discover_vertex(const vertex_id_type& uid) {} + void on_examine_vertex(const vertex_id_type& uid) {} + void on_finish_vertex(const vertex_id_type& uid) {} + + // edge visitor functions + void on_examine_edge(const vertex_id_type& uid) {} +}; + +/** + * @ingroup graph_algorithms + * @brief Returns the largest value used to represent an infinite distance. + * + * @return The largest possible distance value. +*/ +inline Distance topological_sort_infinite_distance() { return std::numeric_limits::max(); } + +/** + * @ingroup graph_algorithms + * @brief Returns a distance value of zero. + * + * @return A value of zero distance. +*/ +inline Distance topological_sort_zero() { return 0; } + +/** + * @ingroup graph_algorithms + * @brief Intializes the distance values to the infinite value. + * + * @param distances The range of distance values to initialize. +*/ +inline void init_topological_sort(Distances& distances) { + for (size_t i = 0; i < distances.size(); ++i) { + distances[i] = topological_sort_infinite_distance(); + } +} + +/** + * @ingroup graph_algorithms + * @brief Intializes the distance and predecessor values for topological sort. + * + * @param distances The range of distance values to initialize. Each value will be assigned the infinite distance. + * @param predecessors The range of predecessors to initialize. Each value will be assigned the vertex id. +*/ +inline void init_topological_sort(Distances& distances, Predecessors& predecessors) { + init_topological_sort(distances); + for (size_t i = 0; i < predecessors.size(); ++i) { + predecessors[i] = i; + } +} + +/** + * @brief Single-source topological sort. + * + * @param g The graph. + * @param source The source vertex. + * @param predecessors The predecessor vertex for g[uid]. + */ + +// C++ +inline void topological_sort(const Graph& g, const Source& source, Distances& distances, Predecessors& predecessors) {} + +// C +inline void topological_sort(const Graph* g, + const Source source, + const size_t distances_len, + Distances* distances, + const size_t predecessors_len, + Predecessors* predecessors) {} + + +} // namespace graph + +#endif // GRAPH_TOPO_SORT_ALGO_HPP diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 49e35a9..f3a5021 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -36,6 +36,10 @@ set(UNITTEST_SOURCES "co_dijkstra_tests.cpp" "visitor_dijkstra_tests.cpp" + "breadth_first_search_tests.cpp" + "depth_first_search_tests.cpp" + "topological_sort_tests.cpp" + "csv_routes_vofl_tests.cpp" "csv_routes.cpp" "csv_routes_dov_tests.cpp" diff --git a/tests/breadth_first_search_tests.cpp b/tests/breadth_first_search_tests.cpp new file mode 100644 index 0000000..a90679b --- /dev/null +++ b/tests/breadth_first_search_tests.cpp @@ -0,0 +1,48 @@ +#include +#include +#include "graph/algorithm/breadth_first_search.hpp" +#include "graph/container/dynamic_graph.hpp" +#include + +#define GRAPH_BFS_ALGORITHM_HPP + +#define TEST_OPTION_OUTPUT (1) +#define TEST_OPTION_GEN (2) +#define TEST_OPTION_TEST (3) +#define TEST_OPTION TEST_OPTION_TEST + +using std::cout; +using std::endl; + +using std::ranges::forward_range; +using std::forward_iterator; + +using namespace graph; + +void init_console(); // init cout for UTF-8 + +TEST_CASE("breadth_first_search algorithm test", "[bfs][single-source][algorithm]") { + init_console(); + + // Create graph instance + + SECTION("verify graph") { + // verify graph + REQUIRE(1 + 1 == 2); + } + +#if TEST_OPTION == TEST_OPTION_OUTPUT + SECTION("bfs algo output") { + // output graph + cout << "graph" << endl; + } +#elif TEST_OPTION == TEST_OPTION_GEN + SECTION("bfs algo test generation") { + // generate test code + } +#elif TEST_OPTION == TEST_OPTION_TEST + SECTION("bfs algo test") { + // production test code + } +#endif // TEST_OPTION +} // TEST_CASE"breadth_first_search algorithm test" diff --git a/tests/depth_first_search_tests.cpp b/tests/depth_first_search_tests.cpp new file mode 100644 index 0000000..552ce60 --- /dev/null +++ b/tests/depth_first_search_tests.cpp @@ -0,0 +1,47 @@ +#include +#include +#include "graph/algorithm/depth_first_search.hpp" +#include "graph/container/dynamic_graph.hpp" +#include + +# define TEST_OPTION_OUTPUT (1) +# define TEST_OPTION_GEN (2) +# define TEST_OPTION_TEST (3) +# define TEST_OPTION TEST_OPTION_TEST + +using std::cout; +using std::endl; + +using std::ranges::forward_range; +using std::forward_iterator; + +using namespace graph; + +void init_console(); // init cout for UTF-8 + +TEST_CASE("depth_first_search algorithm test", "[bfs][single-source][algorithm]") { + init_console(); + + // Create graph instance + + SECTION("verify graph") { + // verify graph + REQUIRE(1 + 1 == 2); + } + +# if TEST_OPTION == TEST_OPTION_OUTPUT + SECTION("dfs algo output") { + // output graph + cout << "graph" << endl; + } +# elif TEST_OPTION == TEST_OPTION_GEN + SECTION("dfs algo test generation") { + // generate test code + } +# elif TEST_OPTION == TEST_OPTION_TEST + SECTION("dfs algo test") { + // production test code + } +# endif // TEST_OPTION +} // TEST_CASE "depth_first_search algorithm test" + diff --git a/tests/topological_sort_tests.cpp b/tests/topological_sort_tests.cpp new file mode 100644 index 0000000..d225ede --- /dev/null +++ b/tests/topological_sort_tests.cpp @@ -0,0 +1,48 @@ +#include +#include +#include "graph/algorithm/topological_sort.hpp" +#include "graph/container/dynamic_graph.hpp" +#include + +#define TEST_OPTION_OUTPUT (1) +#define TEST_OPTION_GEN (2) +#define TEST_OPTION_TEST (3) +#define TEST_OPTION TEST_OPTION_TEST + +using std::cout; +using std::endl; + +using std::ranges::forward_range; +using std::forward_iterator; + +void init_console(); // init cout for UTF-8 + +using namespace graph; + +void init_console(); // init cout for UTF-8 + +TEST_CASE("topological_sort algorithm test", "[topo_sort][single-source][algorithm]") { + init_console(); + + // Create graph instance + + SECTION("verify graph") { + // verify graph + REQUIRE(1 + 1 == 2); + } + +#if TEST_OPTION == TEST_OPTION_OUTPUT + SECTION("topo sort algo output") { + // output graph + cout << "graph" << endl; + } +#elif TEST_OPTION == TEST_OPTION_GEN + SECTION("topo sort algo test generation") { + // generate test code + } +#elif TEST_OPTION == TEST_OPTION_TEST + SECTION("topo sort algo test") { + // production test code + } +#endif // TEST_OPTION +} // TEST_CASE"topological_sort algorithm test"