From 0b09e4ca2ccc7a7d383472cd70105e0c380bf1b2 Mon Sep 17 00:00:00 2001 From: RANDOMFNP Date: Thu, 27 Aug 2026 17:59:08 -0400 Subject: [PATCH] Add files via upload --- detail/add_edges.tpp | 2 +- detail/add_edges_weighted.tpp | 2 +- detail/delete_nodes.tpp | 2 +- detail/delete_nodes_weighted.tpp | 2 +- detail/get_neighbors.tpp | 16 ++++ detail/get_neighbors_weighted.tpp | 22 +++++ detail/print_version.tpp | 3 + include/graphlib.hpp | 14 +++ tests/CMakeLists.txt | 1 + tests/test_core.cpp | 8 ++ tests/test_d_and_g_n.cpp | 153 ++++++++++++++++++++++++++++++ 11 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 detail/get_neighbors.tpp create mode 100644 detail/get_neighbors_weighted.tpp create mode 100644 detail/print_version.tpp create mode 100644 tests/test_d_and_g_n.cpp diff --git a/detail/add_edges.tpp b/detail/add_edges.tpp index 91af277..b33c6ff 100644 --- a/detail/add_edges.tpp +++ b/detail/add_edges.tpp @@ -9,7 +9,7 @@ void add_edge(const std::vector& new_value, const node& key, const std::st auto g_it = graph.find(key); if (g_it == graph.end()) { - std::cout << "Key doesnt exist" << std::endl; + std::cout << "Key doesnt exist" << "\n"; return; } diff --git a/detail/add_edges_weighted.tpp b/detail/add_edges_weighted.tpp index 1378bc5..6f16fdd 100644 --- a/detail/add_edges_weighted.tpp +++ b/detail/add_edges_weighted.tpp @@ -9,7 +9,7 @@ void add_edge(const std::vector>& new_value, const node auto g_it = graph.find(key); if (g_it == graph.end()) { - std::cout << "Key doesnt exist" << std::endl; + std::cout << "Key doesnt exist" << "\n"; return; } diff --git a/detail/delete_nodes.tpp b/detail/delete_nodes.tpp index 87491c7..fbb72ca 100644 --- a/detail/delete_nodes.tpp +++ b/detail/delete_nodes.tpp @@ -1,6 +1,6 @@ namespace graphlib { -void delete_instances(const std::string& node_to_delete, const std::string& input_file) { +inline void delete_instances(const std::string& node_to_delete, const std::string& input_file) { std::vector lines; std::string line; std::regex nodetodeletepattern("^Node " + node_to_delete + "\\b"); diff --git a/detail/delete_nodes_weighted.tpp b/detail/delete_nodes_weighted.tpp index 477ce3f..d7707a5 100644 --- a/detail/delete_nodes_weighted.tpp +++ b/detail/delete_nodes_weighted.tpp @@ -1,6 +1,6 @@ namespace graphlib { -void delete_instances_weighted(const std::string& node_to_delete, const std::string& input_file) { +inline void delete_instances_weighted(const std::string& node_to_delete, const std::string& input_file) { std::vector lines; std::string line; std::regex nodetodeletepattern("^Node " + node_to_delete + "\\b"); diff --git a/detail/get_neighbors.tpp b/detail/get_neighbors.tpp new file mode 100644 index 0000000..9e3eeac --- /dev/null +++ b/detail/get_neighbors.tpp @@ -0,0 +1,16 @@ +namespace graphlib { + +template + +std::vector get_neighbors(const node& key, std::unordered_map>& graph) { + + auto g_it = graph.find(key); + + if (g_it == graph.end()) { + std::cout << "Key doesnt exist" << "\n"; + return {}; + } + + return g_it->second; +} +} \ No newline at end of file diff --git a/detail/get_neighbors_weighted.tpp b/detail/get_neighbors_weighted.tpp new file mode 100644 index 0000000..eb73c93 --- /dev/null +++ b/detail/get_neighbors_weighted.tpp @@ -0,0 +1,22 @@ +namespace graphlib { + +template + +std::vector get_neighbors(const node& key, std::unordered_map>>& graph) { + + auto g_it = graph.find(key); + + if (g_it == graph.end()) { + std::cout << "Key doesnt exist" << "\n"; + return {}; + } + + std::vector neighbors; + + for (const auto& edge_pair : g_it->second) { + neighbors.push_back(edge_pair.first); + } + + return neighbors; +} +} \ No newline at end of file diff --git a/detail/print_version.tpp b/detail/print_version.tpp new file mode 100644 index 0000000..50edced --- /dev/null +++ b/detail/print_version.tpp @@ -0,0 +1,3 @@ +inline void graphlib_version() { + std::cout << "Version 3.1" << '\n'; +} \ No newline at end of file diff --git a/include/graphlib.hpp b/include/graphlib.hpp index 93eab4f..3c5e3d1 100644 --- a/include/graphlib.hpp +++ b/include/graphlib.hpp @@ -32,6 +32,7 @@ template void delete_instances(const std::string& node_to_delete, const std::string& input_file); void print_graph(const std::string& filename); +void graphlib_version(); template requires Number @@ -55,15 +56,27 @@ template requires Number std::unordered_map>> parse_weighted(const std::string& input_file); +template +std::vector get_neighbors(const node& key, std::unordered_map>& graph); + +template +std::vector get_neighbors(const node& key, std::unordered_map>>& graph); + template std::vector dfs_algorithm(const node& starting_value, const std::string& input_file); template std::vector bfs_algorithm(const node& starting_node, const std::string& input_file); +template + +requires Number +std::vector dijkstras_algorithm(const node starting_node, const std::string& input_file); } #include "../detail/txt_to_un_map.tpp" #include "../detail/txt_to_un_map_weighted.tpp" +#include "../detail/get_neighbors.tpp" +#include "../detail/get_neighbors_weighted.tpp" #include "../detail/add_nodes.tpp" #include "../detail/add_nodes_weighted.tpp" #include "../detail/create_graph.tpp" @@ -77,5 +90,6 @@ std::vector bfs_algorithm(const node& starting_node, const std::string& in #include "../detail/bfs.tpp" #include "../detail/dijkstra.tpp" #include "../detail/print_graph.tpp" +#include "../detail/print_version.tpp" #endif \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 260154f..7c7f67d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,7 @@ project(graphlib_tests LANGUAGES CXX) set(TEST_SOURCES "test_core.cpp" + "test_d_and_g_n.cpp" ) add_executable(run_tests ${TEST_SOURCES}) diff --git a/tests/test_core.cpp b/tests/test_core.cpp index 616be7a..9c66515 100644 --- a/tests/test_core.cpp +++ b/tests/test_core.cpp @@ -5,6 +5,9 @@ using namespace std; +// forward declaration for tests in test_d_and_g_n.cpp (merged runner) +extern int run_d_and_g_n_tests(); + namespace { std::atomic g_checks_done{0}; @@ -410,6 +413,11 @@ int main() { << " rss_mb=" << (get_rss_bytes() / 1024 / 1024) << std::endl; std::cout << "Stress tests completed successfully." << std::endl; + + // run additional tests from tests/test_d_and_g_n.cpp + int rc = run_d_and_g_n_tests(); + if (rc != 0) return rc; + return 0; } catch (const std::exception& ex) { std::cerr << ex.what() << std::endl; diff --git a/tests/test_d_and_g_n.cpp b/tests/test_d_and_g_n.cpp new file mode 100644 index 0000000..b30514b --- /dev/null +++ b/tests/test_d_and_g_n.cpp @@ -0,0 +1,153 @@ +#include + +using namespace std; + +#include "graphlib.hpp" + +static inline string unique_temp_path_local(const string& name) { + const auto now = chrono::steady_clock::now().time_since_epoch().count(); + static atomic counter{0}; + const auto id = counter.fetch_add(1); + return "/tmp/graphlib_" + name + "_" + to_string(now) + "_" + to_string(id) + ".txt"; +} + +template +bool same_vector_contents(const vector& actual, const vector& expected) { + if (actual.size() != expected.size()) return false; + vector a = actual; + vector e = expected; + sort(a.begin(), a.end()); + sort(e.begin(), e.end()); + return a == e; +} + +// local Dijkstra implemented the same way as graphlib::dijkstras_algorithm +vector local_dijkstra(const unordered_map>>& graph, int start) { + const long long INF = (1LL<<60); + unordered_map dist; + for (const auto &kv : graph) dist[kv.first] = INF; + if (dist.find(start) == dist.end()) dist[start] = INF; + + using Pair = pair; + priority_queue, greater> q; + dist[start] = 0; + q.push({0, start}); + + vector order; + while (!q.empty()) { + auto [d, u] = q.top(); q.pop(); + auto it = dist.find(u); + if (it != dist.end() && d > it->second) continue; + order.push_back(u); + auto git = graph.find(u); + if (git == graph.end()) continue; + for (const auto &p : git->second) { + int v = p.first; int w = p.second; + long long nd = d + w; + auto vt = dist.find(v); + if (vt == dist.end() || nd < vt->second) { + dist[v] = nd; + q.push({nd, v}); + } + } + } + return order; +} + +int run_d_and_g_n_tests() { + try { + std::mt19937 rng(123456); + std::uniform_int_distribution nodes_dist(0, 300); + std::uniform_int_distribution deg_dist(0, 12); + std::uniform_int_distribution w_dist(1, 200); + + const int ITER = 200; + + for (int it = 0; it < ITER; ++it) { + int N = max(0, nodes_dist(rng)); + + // unweighted graph + unordered_map> ug; + ug.reserve(N); + for (int i = 0; i < N; ++i) { + int deg = deg_dist(rng); + vector adj; + adj.reserve(deg); + for (int e = 0; e < deg; ++e) adj.push_back(rng() % (N + 1)); + ug[i] = adj; + } + + if (!ug.empty()) { + // pick random existing key and check get_neighbors + int pick_idx = rng() % ug.size(); + auto itg = ug.begin(); advance(itg, pick_idx); + int key = itg->first; + auto res = graphlib::get_neighbors(key, ug); + if (!same_vector_contents(res, ug[key])) { + cerr << "get_neighbors (unweighted) mismatch on iteration " << it << "\n"; + return 2; + } + } + + // weighted graph for dijkstra and weighted get_neighbors + unordered_map>> wg; + wg.reserve(N); + for (int i = 0; i < N; ++i) { + int deg = deg_dist(rng); + vector> adj; + adj.reserve(deg); + for (int e = 0; e < deg; ++e) adj.emplace_back(rng() % (N + 1), w_dist(rng)); + wg[i] = adj; + } + + // Test weighted get_neighbors: should return neighbor node ids (first) + if (!wg.empty()) { + int pick_idx = rng() % wg.size(); + auto itw = wg.begin(); advance(itw, pick_idx); + int key = itw->first; + auto got = graphlib::get_neighbors(key, wg); + vector expected; + for (const auto &p : wg[key]) expected.push_back(p.first); + if (!same_vector_contents(got, expected)) { + cerr << "get_neighbors (weighted) returned unexpected values on iteration " << it << "\n"; + cerr << "expected first few: "; + for (size_t i=0;i(expected.size(),5);++i) cerr<(got.size(),5);++i) cerr<(wg, file); + + if (!wg.empty()) { + int pick_idx = rng() % wg.size(); + auto itw = wg.begin(); advance(itw, pick_idx); + int start = itw->first; + + auto lib_order = graphlib::dijkstras_algorithm(start, file); + auto local_order = local_dijkstra(wg, start); + + if (lib_order != local_order) { + cerr << "dijkstra ordering mismatch on iteration " << it << "\n"; + cerr << "start=" << start << " lib_order_size=" << lib_order.size() << " local_order_size=" << local_order.size() << "\n"; + cerr << "lib first 10: "; for (size_t i=0;i(lib_order.size(),10);++i) cerr<(local_order.size(),10);++i) cerr<