From ac67f77201b26c23191bc3fd9bab59cc8bca07c5 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 18 Dec 2024 17:53:10 +0300 Subject: [PATCH 01/36] added a graph class --- CMakeLists.txt | 22 +++-- include/CMakeLists.txt | 0 include/graph/graph.h | 47 +++++++++++ src/CMakeLists.txt | 0 src/graph/CMakeLists.txt | 7 ++ src/graph/graph.cpp | 146 +++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 14 ++-- test/main.cpp | 2 +- test/test_graph.cpp | 173 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 396 insertions(+), 15 deletions(-) delete mode 100644 include/CMakeLists.txt create mode 100644 include/graph/graph.h delete mode 100644 src/CMakeLists.txt create mode 100644 src/graph/CMakeLists.txt create mode 100644 src/graph/graph.cpp create mode 100644 test/test_graph.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a8e8360..be0cd36 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,19 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.15) -project(cpp_template) +set(ProjectName "itlab") -include(cmake/configure.cmake) +project(${ProjectName}) include_directories(include) -enable_testing() - -add_subdirectory(3rdparty) -add_subdirectory(app) -add_subdirectory(include) -add_subdirectory(src) +add_subdirectory(3rdparty/googletest) +add_subdirectory(src/graph) add_subdirectory(test) + +# REPORT +message( STATUS "") +message( STATUS "General configuration for ${PROJECT_NAME}") +message( STATUS "======================================") +message( STATUS "") +message( STATUS " Configuration: ${CMAKE_BUILD_TYPE}") +message( STATUS "") \ No newline at end of file diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt deleted file mode 100644 index e69de29..0000000 diff --git a/include/graph/graph.h b/include/graph/graph.h new file mode 100644 index 0000000..0c68d68 --- /dev/null +++ b/include/graph/graph.h @@ -0,0 +1,47 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include +#include + +class Vertex { +private: + int id; + std::list neighbors; + +public: + Vertex(int id); + void addNeighbor(int neighbor); + void removeNeighbor(int neighbor); + void print() const; + int getId() const; + const std::list& getNeighbors() const; +}; + + + +class Graph { +private: + std::unordered_map vertices; + +public: + + Graph(); + + void addVertex(int id); + void getVertex() const; + void addEdge(int u, int v); + void removeEdge(int u, int v); + void removeVertex(int id); + int vertexCount() const; + int edgeCount() const; + bool empty() const; + void printGraph() const; + bool hasPath(int u, int v); + std::vector BFS(int start); + ~Graph(); +}; + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/graph/CMakeLists.txt b/src/graph/CMakeLists.txt new file mode 100644 index 0000000..af77d7d --- /dev/null +++ b/src/graph/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE HEADER_FILES "${CMAKE_SOURCE_DIR}/include/*.h") +file(GLOB_RECURSE SOURCE_FILES "${CMAKE_SOURCE_DIR}/src/*.cpp") + +add_library(${ProjectName} STATIC ${SOURCE_FILES} ${HEADER_FILES}) +target_sources(${ProjectName} PRIVATE ${HEADER_FILES}) + +target_include_directories(${ProjectName} PUBLIC ${CMAKE_SOURCE_DIR}/src) \ No newline at end of file diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp new file mode 100644 index 0000000..c3cc8b0 --- /dev/null +++ b/src/graph/graph.cpp @@ -0,0 +1,146 @@ +#include "./graph/graph.h" + +Vertex::Vertex(int id) : id(id) {} + +void Vertex::addNeighbor(int neighbor) { + if (neighbor != id) { + neighbors.push_back(neighbor); + } +} + +void Vertex::removeNeighbor(int neighbor) { + neighbors.remove(neighbor); +} + +void Vertex::print() const { + std::cout << id << ": "; + for (const int& neighbor : neighbors) { + std::cout << neighbor << " "; + } + std::cout << std::endl; +} + +int Vertex::getId() const { + return id; +} + +const std::list& Vertex::getNeighbors() const { + return neighbors; +} + +Graph::Graph() {} + +void Graph::addVertex(int id) { + if (vertices.find(id) == vertices.end()) { + vertices[id] = new Vertex(id); + } +} + +void Graph::getVertex() const { + if (!this->empty()) { + for (auto it = vertices.begin(); it != vertices.end(); it++) + std::cout << it->first << " "; + std::cout << std::endl; + } +} + +void Graph::addEdge(int u, int v) { + if (vertices.find(u) == vertices.end()) { addVertex(u); } + if (vertices.find(v) == vertices.end()) { addVertex(v); } + vertices[u]->addNeighbor(v); +} + +void Graph::removeEdge(int u, int v) { + if (vertices.find(u) != vertices.end()) { + vertices[u]->removeNeighbor(v); + } +} + +void Graph::removeVertex(int id) { + for (auto& pair : vertices) { pair.second->removeNeighbor(id); } + auto it = vertices.find(id); + if (it != vertices.end()) { + delete it->second; + vertices.erase(it); + } +} + +int Graph::vertexCount() const { + int count = 0; + for (auto it = vertices.begin(); it != vertices.end(); it++) + count++; + return count; +} + +int Graph::edgeCount() const { + int count = 0; + for (auto it = vertices.begin(); it != vertices.end(); it++) { + count += (it->second->getNeighbors()).size(); + } + return count; +} + + +bool Graph::empty() const { + return vertices.empty(); +} + +void Graph::printGraph() const { + for (const auto& pair : vertices) { + pair.second->print(); + } +} + +bool Graph::hasPath(int u, int v) { + if (vertices.find(u) != vertices.end() && vertices.find(v) != vertices.end()) { + std::unordered_map visited; + std::queue queue; + queue.push(u); + + while (!queue.empty()) { + int current = queue.front(); + queue.pop(); + if (current == v) { return true; } + visited[current] = true; + + for (const int& neighbor : vertices[current]->getNeighbors()) + if (!visited[neighbor]) + queue.push(neighbor); + + } + return false; + } +} + +std::vector Graph::BFS(int start) { + std::vector traversal_order; + std::unordered_map visited; + std::queue queue; + + visited[start] = true; + queue.push(start); + + while (!queue.empty()) { + int current = queue.front(); + queue.pop(); + traversal_order.push_back(current); + + if (vertices.find(current) != vertices.end()) { + for (const int& neighbor : vertices[current]->getNeighbors()) { + if (!visited[neighbor]) { + visited[neighbor] = true; + queue.push(neighbor); + } + } + } + } + //for (int i : traversal_order) + // std::cout << i << " "; + return traversal_order; +} + +Graph::~Graph() { + for (auto& pair : vertices) { + delete pair.second; + } +} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9dada0c..14bf041 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,10 @@ -file(GLOB_RECURSE TEST_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB_RECURSE TEST_FILES ./*.cpp) -add_executable(run_tests ${TEST_SRC_FILES}) -target_link_libraries(run_tests PUBLIC - gtest_main -) +set(TestsName "Tests") + +add_executable(${TestsName} ${TEST_FILES}) + +target_link_libraries(${TestsName} PRIVATE ${ProjectName} gtest) + +enable_testing() +add_test(NAME ${TestsName} COMMAND ${TestsName}) \ No newline at end of file diff --git a/test/main.cpp b/test/main.cpp index 4d820af..a0bda37 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,4 +1,4 @@ -#include +#include int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/test/test_graph.cpp b/test/test_graph.cpp new file mode 100644 index 0000000..d0fe2c0 --- /dev/null +++ b/test/test_graph.cpp @@ -0,0 +1,173 @@ +#include "./graph/graph.h" +#include "./graph/graph.cpp" +#include + + +TEST(Graph, can_create_graph) +{ + ASSERT_NO_THROW(Graph g); +} + +TEST(Graph, can_add_vertex_to_graph) +{ + Graph g; + + ASSERT_NO_THROW(g.addVertex(1)); +} + +TEST(Graph, can_add_edge_to_graph) +{ + Graph g; + + ASSERT_NO_THROW(g.addEdge(1,0)); +} + +TEST(Graph, can_add_edge_with_same_id_to_graph) +{ + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 1)); +} + +TEST(Graph, can_add_vertex_and_edge_to_graph) +{ + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 0)); + ASSERT_NO_THROW(g.addVertex(1)); +} + +TEST(Graph, can_get_vertex) +{ + Graph g; + g.addEdge(1, 0); + + ASSERT_NO_THROW(g.getVertex()); +} + +TEST(Graph, can_remove_vertex) +{ + Graph g; + g.addEdge(1, 0); + + g.removeVertex(1); + + ASSERT_EQ(g.vertexCount(),1); +} + +TEST(Graph, can_get_vertex_count) +{ + Graph g; + + g.addEdge(1, 0); + g.addVertex(2); + g.addVertex(3); + g.removeVertex(1); + g.addVertex(1); + g.removeVertex(3); + + ASSERT_EQ(g.vertexCount(), 3); +} + +TEST(Graph, can_get_edge_count) +{ + Graph g; + + g.addEdge(1, 0); + g.addEdge(2, 0); + g.addEdge(0, 2); + g.addEdge(2, 2); + + ASSERT_EQ(g.edgeCount(), 3); +} + +TEST(Graph, check_graph_is_empty) +{ + Graph g; + + ASSERT_TRUE(g.empty()); +} + +TEST(Graph, check_graph_is_not_empty) +{ + Graph g; + + g.addEdge(1, 0); + + ASSERT_FALSE(g.empty()); +} + +TEST(Graph, check_graph_no_path_between_vertexes) +{ + Graph g; + + g.addEdge(0,1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + + ASSERT_FALSE(g.hasPath(1,0)); +} + +TEST(Graph, check_graph_has_path_between_vertexes) +{ + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + + ASSERT_TRUE(g.hasPath(3,1)); +} + +TEST(Graph, check_graph_can_find_path_between_vertexes_after_delete) +{ + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + g.removeVertex(3); + + ASSERT_FALSE(g.hasPath(3, 1)); + ASSERT_FALSE(g.hasPath(0, 3)); +} + +TEST(Graph, can_create_bfs_path) +{ + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + + ASSERT_NO_THROW(g.BFS(0)); +} + +TEST(Graph, can_create_bfs_path_in_empty_graph) +{ + Graph g; + + ASSERT_NO_THROW(g.BFS(0)); +} + +TEST(Graph, check_bfs_path) +{ + Graph g; + std::vector v1 = { 0,1,3,2,4,6,7,5,8,9 }; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 4); + g.addEdge(4, 5); + g.addEdge(3,6); + g.addEdge(3, 7); + g.addEdge(7,8); + g.addEdge(8, 9); + std::vector v = g.BFS(0); + + ASSERT_EQ(v, v1); +} \ No newline at end of file From 5f36230bfedf2d85a8178acdbea96ff1e4448591 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 20 Dec 2024 02:29:18 +0300 Subject: [PATCH 02/36] gtest dir fix --- CMakeLists.txt | 2 +- test/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be0cd36..75658c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ project(${ProjectName}) include_directories(include) -add_subdirectory(3rdparty/googletest) +add_subdirectory(3rdparty/googletest/gtest) add_subdirectory(src/graph) add_subdirectory(test) diff --git a/test/main.cpp b/test/main.cpp index a0bda37..47f4482 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -3,4 +3,4 @@ int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} +} \ No newline at end of file From 48679371dd0dbce14b7094e026f0a6e8ddb740ea Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Feb 2025 17:47:16 +0300 Subject: [PATCH 03/36] CMake fix 1.0 --- CMakeLists.txt | 4 +-- include/graph/graph.h | 2 +- src/graph/graph.cpp | 72 ++++++++++++++++++++----------------------- 3 files changed, 37 insertions(+), 41 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75658c8..76e8ec1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.20) set(ProjectName "itlab") @@ -6,7 +6,7 @@ project(${ProjectName}) include_directories(include) -add_subdirectory(3rdparty/googletest/gtest) +add_subdirectory(3rdparty) add_subdirectory(src/graph) add_subdirectory(test) diff --git a/include/graph/graph.h b/include/graph/graph.h index 0c68d68..b0d0249 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -29,7 +29,6 @@ class Graph { public: Graph(); - void addVertex(int id); void getVertex() const; void addEdge(int u, int v); @@ -39,6 +38,7 @@ class Graph { int edgeCount() const; bool empty() const; void printGraph() const; + bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord); bool hasPath(int u, int v); std::vector BFS(int start); ~Graph(); diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index c3cc8b0..b650d86 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -92,51 +92,47 @@ void Graph::printGraph() const { } bool Graph::hasPath(int u, int v) { - if (vertices.find(u) != vertices.end() && vertices.find(v) != vertices.end()) { - std::unordered_map visited; - std::queue queue; - queue.push(u); + if (vertices.find(u) == vertices.end() || + vertices.find(v) == vertices.end()) { + return false; + } + return bfs_helper(u, v, true, nullptr); +} - while (!queue.empty()) { - int current = queue.front(); - queue.pop(); - if (current == v) { return true; } - visited[current] = true; +std::vector Graph::BFS(int start) { + std::vector v_ord; + bfs_helper(start, -1, false, &v_ord); + return v_ord; +} - for (const int& neighbor : vertices[current]->getNeighbors()) - if (!visited[neighbor]) - queue.push(neighbor); +bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) { + std::unordered_map visited; + std::queue queue; - } - return false; + queue.push(start); + visited[start] = true; + + while (!queue.empty()) { + int current = queue.front(); + queue.pop(); + + if (flag && current == vert) { + return true; + } + if (v_ord != nullptr) { + v_ord->push_back(current); } -} -std::vector Graph::BFS(int start) { - std::vector traversal_order; - std::unordered_map visited; - std::queue queue; - - visited[start] = true; - queue.push(start); - - while (!queue.empty()) { - int current = queue.front(); - queue.pop(); - traversal_order.push_back(current); - - if (vertices.find(current) != vertices.end()) { - for (const int& neighbor : vertices[current]->getNeighbors()) { - if (!visited[neighbor]) { - visited[neighbor] = true; - queue.push(neighbor); - } - } + if (vertices.find(current) != vertices.end()) { + for (const int& neighbor : vertices[current]->getNeighbors()) { + if (!visited[neighbor]) { + visited[neighbor] = true; + queue.push(neighbor); } + } } - //for (int i : traversal_order) - // std::cout << i << " "; - return traversal_order; + } + return false; } Graph::~Graph() { From fb575540f48ef7ca8a6c426321aa15d930522baa Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Feb 2025 18:05:19 +0300 Subject: [PATCH 04/36] CMake fix 2.0 --- test/main.cpp | 2 +- test/test_graph.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/main.cpp b/test/main.cpp index 47f4482..1659be8 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,4 +1,4 @@ -#include +#include "gtest/gtest.h" int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/test/test_graph.cpp b/test/test_graph.cpp index d0fe2c0..45cf3dc 100644 --- a/test/test_graph.cpp +++ b/test/test_graph.cpp @@ -1,6 +1,5 @@ -#include "./graph/graph.h" -#include "./graph/graph.cpp" -#include +#include "gtest/gtest.h" +#include "graph/graph.cpp" TEST(Graph, can_create_graph) From f2afeea15f5ec92b491b0fa2e2be258ab0317296 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Feb 2025 18:19:02 +0300 Subject: [PATCH 05/36] CMake fix 2.0 --- include/graph/graph.h | 65 +++++++++++++++++++++---------------------- test/main.cpp | 1 + test/test_graph.cpp | 1 - 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/include/graph/graph.h b/include/graph/graph.h index b0d0249..1dcdd53 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -1,47 +1,44 @@ -#ifndef GRAPH_H +#ifndef GRAPH_H #define GRAPH_H #include -#include #include #include +#include class Vertex { -private: - int id; - std::list neighbors; - -public: - Vertex(int id); - void addNeighbor(int neighbor); - void removeNeighbor(int neighbor); - void print() const; - int getId() const; - const std::list& getNeighbors() const; + private: + int id; + std::list neighbors; + + public: + Vertex(int id); + void addNeighbor(int neighbor); + void removeNeighbor(int neighbor); + void print() const; + int getId() const; + const std::list& getNeighbors() const; }; - - class Graph { -private: - std::unordered_map vertices; - -public: - - Graph(); - void addVertex(int id); - void getVertex() const; - void addEdge(int u, int v); - void removeEdge(int u, int v); - void removeVertex(int id); - int vertexCount() const; - int edgeCount() const; - bool empty() const; - void printGraph() const; - bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord); - bool hasPath(int u, int v); - std::vector BFS(int start); - ~Graph(); + private: + std::unordered_map vertices; + + public: + Graph(); + void addVertex(int id); + void getVertex() const; + void addEdge(int u, int v); + void removeEdge(int u, int v); + void removeVertex(int id); + int vertexCount() const; + int edgeCount() const; + bool empty() const; + void printGraph() const; + bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord); + bool hasPath(int u, int v); + std::vector BFS(int start); + ~Graph(); }; #endif diff --git a/test/main.cpp b/test/main.cpp index 1659be8..d6efe14 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,5 +1,6 @@ #include "gtest/gtest.h" + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/test/test_graph.cpp b/test/test_graph.cpp index 45cf3dc..e900440 100644 --- a/test/test_graph.cpp +++ b/test/test_graph.cpp @@ -1,7 +1,6 @@ #include "gtest/gtest.h" #include "graph/graph.cpp" - TEST(Graph, can_create_graph) { ASSERT_NO_THROW(Graph g); From 82f0dc44ed03575591e4fa988a308a89491e8157 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 27 Feb 2025 18:06:24 +0300 Subject: [PATCH 06/36] clang-tidy, clang-format and ubuntu-build fix 1.0 --- include/graph/graph.h | 15 ++--- src/graph/graph.cpp | 146 ++++++++++++++++++------------------------ test/CMakeLists.txt | 2 +- test/test_graph.cpp | 3 +- 4 files changed, 74 insertions(+), 92 deletions(-) diff --git a/include/graph/graph.h b/include/graph/graph.h index 1dcdd53..bf2b478 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -1,18 +1,17 @@ #ifndef GRAPH_H #define GRAPH_H -#include #include -#include #include +#include class Vertex { private: - int id; - std::list neighbors; + int id_; + std::list neighbors_; public: - Vertex(int id); + Vertex(int id_); void addNeighbor(int neighbor); void removeNeighbor(int neighbor); void print() const; @@ -22,15 +21,15 @@ class Vertex { class Graph { private: - std::unordered_map vertices; + std::unordered_map vertices_; public: Graph(); - void addVertex(int id); + void addVertex(int id_); void getVertex() const; void addEdge(int u, int v); void removeEdge(int u, int v); - void removeVertex(int id); + void removeVertex(int id_); int vertexCount() const; int edgeCount() const; bool empty() const; diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index b650d86..679fcc5 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,114 +1,89 @@ #include "./graph/graph.h" -Vertex::Vertex(int id) : id(id) {} +#include +#include +#include +#include + +Vertex::Vertex(int id_) : id_(id_) {} void Vertex::addNeighbor(int neighbor) { - if (neighbor != id) { - neighbors.push_back(neighbor); - } + if (neighbor != id_) { neighbors_.push_back(neighbor); } } -void Vertex::removeNeighbor(int neighbor) { - neighbors.remove(neighbor); -} +void Vertex::removeNeighbor(int neighbor) { neighbors_.remove(neighbor); } void Vertex::print() const { - std::cout << id << ": "; - for (const int& neighbor : neighbors) { - std::cout << neighbor << " "; - } - std::cout << std::endl; + std::cout << id_ << ": "; + for (const int& neighbor : neighbors_) { + std::cout << neighbor << " "; + } + std::cout << '\n'; } -int Vertex::getId() const { - return id; -} +int Vertex::getId() const { return id_; } -const std::list& Vertex::getNeighbors() const { - return neighbors; -} +const std::list& Vertex::getNeighbors() const { return neighbors_; } -Graph::Graph() {} +Graph::Graph() = default; -void Graph::addVertex(int id) { - if (vertices.find(id) == vertices.end()) { - vertices[id] = new Vertex(id); - } +void Graph::addVertex(int id_) { + if (vertices_.find(id_) == vertices_.end()) { vertices_[id_] = new Vertex(id_); } } void Graph::getVertex() const { - if (!this->empty()) { - for (auto it = vertices.begin(); it != vertices.end(); it++) - std::cout << it->first << " "; - std::cout << std::endl; + if (!this->empty()) { + for (auto& vertice : vertices_) { + std::cout << vertice.first << " "; } + std::cout << '\n'; + } } void Graph::addEdge(int u, int v) { - if (vertices.find(u) == vertices.end()) { addVertex(u); } - if (vertices.find(v) == vertices.end()) { addVertex(v); } - vertices[u]->addNeighbor(v); + if (vertices_.find(u) == vertices_.end()) { addVertex(u); } + if (vertices_.find(v) == vertices_.end()) { addVertex(v); } + vertices_[u]->addNeighbor(v); } void Graph::removeEdge(int u, int v) { - if (vertices.find(u) != vertices.end()) { - vertices[u]->removeNeighbor(v); - } + if (vertices_.find(u) != vertices_.end()) { vertices_[u]->removeNeighbor(v); } } -void Graph::removeVertex(int id) { - for (auto& pair : vertices) { pair.second->removeNeighbor(id); } - auto it = vertices.find(id); - if (it != vertices.end()) { - delete it->second; - vertices.erase(it); - } +void Graph::removeVertex(int id_) { + for (auto& pair : vertices_) { + pair.second->removeNeighbor(id_); + } + auto it = vertices_.find(id_); + if (it != vertices_.end()) { + delete it->second; + vertices_.erase(it); + } } int Graph::vertexCount() const { - int count = 0; - for (auto it = vertices.begin(); it != vertices.end(); it++) - count++; - return count; + int count = 0; + for (auto& vertice : vertices_) { + count++; + } + return count; } int Graph::edgeCount() const { - int count = 0; - for (auto it = vertices.begin(); it != vertices.end(); it++) { - count += (it->second->getNeighbors()).size(); - } - return count; + int count = 0; + for (auto it = vertices_.begin(); it != vertices_.end(); it++) count += (it->second->getNeighbors()).size(); + return count; } - -bool Graph::empty() const { - return vertices.empty(); -} +bool Graph::empty() const { return vertices_.empty(); } void Graph::printGraph() const { - for (const auto& pair : vertices) { - pair.second->print(); - } -} - -bool Graph::hasPath(int u, int v) { - if (vertices.find(u) == vertices.end() || - vertices.find(v) == vertices.end()) { - return false; - } - return bfs_helper(u, v, true, nullptr); -} - -std::vector Graph::BFS(int start) { - std::vector v_ord; - bfs_helper(start, -1, false, &v_ord); - return v_ord; + for (const auto& pair : vertices_) { pair.second->print(); } } bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) { std::unordered_map visited; std::queue queue; - queue.push(start); visited[start] = true; @@ -116,15 +91,11 @@ bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) int current = queue.front(); queue.pop(); - if (flag && current == vert) { - return true; - } - if (v_ord != nullptr) { - v_ord->push_back(current); - } + if (flag && current == vert) return true; + if (v_ord != nullptr) v_ord->push_back(current); - if (vertices.find(current) != vertices.end()) { - for (const int& neighbor : vertices[current]->getNeighbors()) { + if (vertices_.find(current) != vertices_.end()) { + for (const int& neighbor : vertices_[current]->getNeighbors()) { if (!visited[neighbor]) { visited[neighbor] = true; queue.push(neighbor); @@ -135,8 +106,19 @@ bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) return false; } +bool Graph::hasPath(int u, int v) { + if (vertices_.find(u) == vertices_.end() || vertices_.find(v) == vertices_.end()) return false; + return bfs_helper(u, v, true, nullptr); +} + +std::vector Graph::BFS(int start) { + std::vector v_ord; + bfs_helper(start, -1, false, &v_ord); + return v_ord; +} + Graph::~Graph() { - for (auto& pair : vertices) { - delete pair.second; - } + for (auto& pair : vertices_) { + delete pair.second; + } } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 14bf041..0ab479f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,6 @@ file(GLOB_RECURSE TEST_FILES ./*.cpp) -set(TestsName "Tests") +set(TestsName "run_tests") add_executable(${TestsName} ${TEST_FILES}) diff --git a/test/test_graph.cpp b/test/test_graph.cpp index e900440..48942ad 100644 --- a/test/test_graph.cpp +++ b/test/test_graph.cpp @@ -1,5 +1,6 @@ #include "gtest/gtest.h" -#include "graph/graph.cpp" +#include "graph/graph.h" +#include TEST(Graph, can_create_graph) { From 2f1141a56c469d55b7984d4af7f5cffaa6998555 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 27 Feb 2025 18:57:27 +0300 Subject: [PATCH 07/36] clang-tidy, clang-format, ubuntu-build and cmake fix 2.0 --- CMakeLists.txt | 11 ++- include/CMakeLists.txt | 2 + src/CMakeLists.txt | 1 + src/graph/CMakeLists.txt | 9 +- src/graph/graph.cpp | 59 +++++++++---- test/CMakeLists.txt | 15 ++-- test/{ => graph}/main.cpp | 0 test/graph/test_graph.cpp | 154 ++++++++++++++++++++++++++++++++++ test/test_graph.cpp | 172 -------------------------------------- 9 files changed, 213 insertions(+), 210 deletions(-) create mode 100644 include/CMakeLists.txt create mode 100644 src/CMakeLists.txt rename test/{ => graph}/main.cpp (100%) create mode 100644 test/graph/test_graph.cpp delete mode 100644 test/test_graph.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 76e8ec1..9a522c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,18 @@ cmake_minimum_required(VERSION 3.20) -set(ProjectName "itlab") +project(itlab_2024) -project(${ProjectName}) +include(cmake/configure.cmake) include_directories(include) +enable_testing() + + add_subdirectory(3rdparty) -add_subdirectory(src/graph) +add_subdirectory(app) +add_subdirectory(include) +add_subdirectory(src) add_subdirectory(test) # REPORT diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..168bbf0 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,2 @@ +file(GLOB_RECURSE graph_headers graph/*.h) +set(GRAPH_HEADERS "${graph_headers}" PARENT_SCOPE) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..eceaa59 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(graph) \ No newline at end of file diff --git a/src/graph/CMakeLists.txt b/src/graph/CMakeLists.txt index af77d7d..fe4c58a 100644 --- a/src/graph/CMakeLists.txt +++ b/src/graph/CMakeLists.txt @@ -1,7 +1,2 @@ -file(GLOB_RECURSE HEADER_FILES "${CMAKE_SOURCE_DIR}/include/*.h") -file(GLOB_RECURSE SOURCE_FILES "${CMAKE_SOURCE_DIR}/src/*.cpp") - -add_library(${ProjectName} STATIC ${SOURCE_FILES} ${HEADER_FILES}) -target_sources(${ProjectName} PRIVATE ${HEADER_FILES}) - -target_include_directories(${ProjectName} PUBLIC ${CMAKE_SOURCE_DIR}/src) \ No newline at end of file +file(GLOB_RECURSE graph_src *.cpp) +add_library(graph_lib STATIC "${GRAPH_HEADERS}" "${graph_src}") \ No newline at end of file diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index 679fcc5..3cd9d99 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,17 +1,20 @@ #include "./graph/graph.h" #include -#include #include +#include +#include #include Vertex::Vertex(int id_) : id_(id_) {} void Vertex::addNeighbor(int neighbor) { - if (neighbor != id_) { neighbors_.push_back(neighbor); } + if (neighbor != id_) { + neighbors_.push_back(neighbor); + } } -void Vertex::removeNeighbor(int neighbor) { neighbors_.remove(neighbor); } +void Vertex::removeNeighbor(int neighbor) { neighbors_.remove(neighbor); } void Vertex::print() const { std::cout << id_ << ": "; @@ -21,19 +24,21 @@ void Vertex::print() const { std::cout << '\n'; } -int Vertex::getId() const { return id_; } +int Vertex::getId() const { return id_; } -const std::list& Vertex::getNeighbors() const { return neighbors_; } +const std::list& Vertex::getNeighbors() const { return neighbors_; } Graph::Graph() = default; void Graph::addVertex(int id_) { - if (vertices_.find(id_) == vertices_.end()) { vertices_[id_] = new Vertex(id_); } + if (vertices_.find(id_) == vertices_.end()) { + vertices_[id_] = new Vertex(id_); + } } void Graph::getVertex() const { if (!this->empty()) { - for (auto& vertice : vertices_) { + for (const auto& vertice : vertices_) { std::cout << vertice.first << " "; } std::cout << '\n'; @@ -41,13 +46,19 @@ void Graph::getVertex() const { } void Graph::addEdge(int u, int v) { - if (vertices_.find(u) == vertices_.end()) { addVertex(u); } - if (vertices_.find(v) == vertices_.end()) { addVertex(v); } + if (vertices_.find(u) == vertices_.end()) { + addVertex(u); + } + if (vertices_.find(v) == vertices_.end()) { + addVertex(v); + } vertices_[u]->addNeighbor(v); } void Graph::removeEdge(int u, int v) { - if (vertices_.find(u) != vertices_.end()) { vertices_[u]->removeNeighbor(v); } + if (vertices_.find(u) != vertices_.end()) { + vertices_[u]->removeNeighbor(v); + } } void Graph::removeVertex(int id_) { @@ -63,7 +74,7 @@ void Graph::removeVertex(int id_) { int Graph::vertexCount() const { int count = 0; - for (auto& vertice : vertices_) { + for (const auto& vertice : vertices_) { count++; } return count; @@ -71,17 +82,22 @@ int Graph::vertexCount() const { int Graph::edgeCount() const { int count = 0; - for (auto it = vertices_.begin(); it != vertices_.end(); it++) count += (it->second->getNeighbors()).size(); + for (const auto& vertice : vertices_) { + count += (vertice.second->getNeighbors()).size(); + } return count; } -bool Graph::empty() const { return vertices_.empty(); } +bool Graph::empty() const { return vertices_.empty(); } void Graph::printGraph() const { - for (const auto& pair : vertices_) { pair.second->print(); } + for (const auto& pair : vertices_) { + pair.second->print(); + } } -bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) { +bool Graph::bfs_helper(int start, int vert, bool flag, + std::vector* v_ord) { std::unordered_map visited; std::queue queue; queue.push(start); @@ -91,8 +107,12 @@ bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) int current = queue.front(); queue.pop(); - if (flag && current == vert) return true; - if (v_ord != nullptr) v_ord->push_back(current); + if (flag && current == vert) { + return true; + } + if (v_ord != nullptr) { + v_ord->push_back(current); + } if (vertices_.find(current) != vertices_.end()) { for (const int& neighbor : vertices_[current]->getNeighbors()) { @@ -107,7 +127,10 @@ bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) } bool Graph::hasPath(int u, int v) { - if (vertices_.find(u) == vertices_.end() || vertices_.find(v) == vertices_.end()) return false; + if (vertices_.find(u) == vertices_.end() || + vertices_.find(v) == vertices_.end()) { + return false; + } return bfs_helper(u, v, true, nullptr); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0ab479f..2048a6b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,10 +1,5 @@ -file(GLOB_RECURSE TEST_FILES ./*.cpp) - -set(TestsName "run_tests") - -add_executable(${TestsName} ${TEST_FILES}) - -target_link_libraries(${TestsName} PRIVATE ${ProjectName} gtest) - -enable_testing() -add_test(NAME ${TestsName} COMMAND ${TestsName}) \ No newline at end of file +file(GLOB_RECURSE TEST_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +add_executable(run_tests ${TEST_SRC_FILES}) +target_link_libraries(run_tests PUBLIC + gtest_main +) \ No newline at end of file diff --git a/test/main.cpp b/test/graph/main.cpp similarity index 100% rename from test/main.cpp rename to test/graph/main.cpp diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp new file mode 100644 index 0000000..daeecf0 --- /dev/null +++ b/test/graph/test_graph.cpp @@ -0,0 +1,154 @@ +#include + +#include "graph/graph.h" +#include "gtest/gtest.h" + +TEST(Graph, can_create_graph) { ASSERT_NO_THROW(Graph g); } + +TEST(Graph, can_add_vertex_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addVertex(1)); +} + +TEST(Graph, can_add_edge_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 0)); +} + +TEST(Graph, can_add_edge_with_same_id_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 1)); +} + +TEST(Graph, can_add_vertex_and_edge_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 0)); + ASSERT_NO_THROW(g.addVertex(1)); +} + +TEST(Graph, can_get_vertex) { + Graph g; + g.addEdge(1, 0); + + ASSERT_NO_THROW(g.getVertex()); +} + +TEST(Graph, can_remove_vertex) { + Graph g; + g.addEdge(1, 0); + + g.removeVertex(1); + + ASSERT_EQ(g.vertexCount(), 1); +} + +TEST(Graph, can_get_vertex_count) { + Graph g; + + g.addEdge(1, 0); + g.addVertex(2); + g.addVertex(3); + g.removeVertex(1); + g.addVertex(1); + g.removeVertex(3); + + ASSERT_EQ(g.vertexCount(), 3); +} + +TEST(Graph, can_get_edge_count) { + Graph g; + + g.addEdge(1, 0); + g.addEdge(2, 0); + g.addEdge(0, 2); + g.addEdge(2, 2); + + ASSERT_EQ(g.edgeCount(), 3); +} + +TEST(Graph, check_graph_is_empty) { + Graph g; + + ASSERT_TRUE(g.empty()); +} + +TEST(Graph, check_graph_is_not_empty) { + Graph g; + + g.addEdge(1, 0); + + ASSERT_FALSE(g.empty()); +} + +TEST(Graph, check_graph_no_path_between_vertexes) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + + ASSERT_FALSE(g.hasPath(1, 0)); +} + +TEST(Graph, check_graph_has_path_between_vertexes) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + + ASSERT_TRUE(g.hasPath(3, 1)); +} + +TEST(Graph, check_graph_can_find_path_between_vertexes_after_delete) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + g.removeVertex(3); + + ASSERT_FALSE(g.hasPath(3, 1)); + ASSERT_FALSE(g.hasPath(0, 3)); +} + +TEST(Graph, can_create_bfs_path) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + + ASSERT_NO_THROW(g.BFS(0)); +} + +TEST(Graph, can_create_bfs_path_in_empty_graph) { + Graph g; + + ASSERT_NO_THROW(g.BFS(0)); +} + +TEST(Graph, check_bfs_path) { + Graph g; + std::vector v1 = {0, 1, 3, 2, 4, 6, 7, 5, 8, 9}; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 4); + g.addEdge(4, 5); + g.addEdge(3, 6); + g.addEdge(3, 7); + g.addEdge(7, 8); + g.addEdge(8, 9); + std::vector v = g.BFS(0); + + ASSERT_EQ(v, v1); +} \ No newline at end of file diff --git a/test/test_graph.cpp b/test/test_graph.cpp deleted file mode 100644 index 48942ad..0000000 --- a/test/test_graph.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "gtest/gtest.h" -#include "graph/graph.h" -#include - -TEST(Graph, can_create_graph) -{ - ASSERT_NO_THROW(Graph g); -} - -TEST(Graph, can_add_vertex_to_graph) -{ - Graph g; - - ASSERT_NO_THROW(g.addVertex(1)); -} - -TEST(Graph, can_add_edge_to_graph) -{ - Graph g; - - ASSERT_NO_THROW(g.addEdge(1,0)); -} - -TEST(Graph, can_add_edge_with_same_id_to_graph) -{ - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 1)); -} - -TEST(Graph, can_add_vertex_and_edge_to_graph) -{ - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 0)); - ASSERT_NO_THROW(g.addVertex(1)); -} - -TEST(Graph, can_get_vertex) -{ - Graph g; - g.addEdge(1, 0); - - ASSERT_NO_THROW(g.getVertex()); -} - -TEST(Graph, can_remove_vertex) -{ - Graph g; - g.addEdge(1, 0); - - g.removeVertex(1); - - ASSERT_EQ(g.vertexCount(),1); -} - -TEST(Graph, can_get_vertex_count) -{ - Graph g; - - g.addEdge(1, 0); - g.addVertex(2); - g.addVertex(3); - g.removeVertex(1); - g.addVertex(1); - g.removeVertex(3); - - ASSERT_EQ(g.vertexCount(), 3); -} - -TEST(Graph, can_get_edge_count) -{ - Graph g; - - g.addEdge(1, 0); - g.addEdge(2, 0); - g.addEdge(0, 2); - g.addEdge(2, 2); - - ASSERT_EQ(g.edgeCount(), 3); -} - -TEST(Graph, check_graph_is_empty) -{ - Graph g; - - ASSERT_TRUE(g.empty()); -} - -TEST(Graph, check_graph_is_not_empty) -{ - Graph g; - - g.addEdge(1, 0); - - ASSERT_FALSE(g.empty()); -} - -TEST(Graph, check_graph_no_path_between_vertexes) -{ - Graph g; - - g.addEdge(0,1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - - ASSERT_FALSE(g.hasPath(1,0)); -} - -TEST(Graph, check_graph_has_path_between_vertexes) -{ - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - - ASSERT_TRUE(g.hasPath(3,1)); -} - -TEST(Graph, check_graph_can_find_path_between_vertexes_after_delete) -{ - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - g.removeVertex(3); - - ASSERT_FALSE(g.hasPath(3, 1)); - ASSERT_FALSE(g.hasPath(0, 3)); -} - -TEST(Graph, can_create_bfs_path) -{ - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - - ASSERT_NO_THROW(g.BFS(0)); -} - -TEST(Graph, can_create_bfs_path_in_empty_graph) -{ - Graph g; - - ASSERT_NO_THROW(g.BFS(0)); -} - -TEST(Graph, check_bfs_path) -{ - Graph g; - std::vector v1 = { 0,1,3,2,4,6,7,5,8,9 }; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 4); - g.addEdge(4, 5); - g.addEdge(3,6); - g.addEdge(3, 7); - g.addEdge(7,8); - g.addEdge(8, 9); - std::vector v = g.BFS(0); - - ASSERT_EQ(v, v1); -} \ No newline at end of file From fdfe528d6172f701e8e6122b220ce7f1e4095112 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 27 Feb 2025 19:36:51 +0300 Subject: [PATCH 08/36] CMake, builts, clang format/tidy fix 3.0 --- CMakeLists.txt | 13 +++++-------- include/CMakeLists.txt | 2 -- src/CMakeLists.txt | 1 - src/graph/CMakeLists.txt | 9 +++++++-- src/graph/graph.cpp | 8 +------- test/CMakeLists.txt | 15 ++++++++++----- test/graph/main.cpp | 3 +-- 7 files changed, 24 insertions(+), 27 deletions(-) delete mode 100644 include/CMakeLists.txt delete mode 100644 src/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a522c9..cf34635 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,15 @@ cmake_minimum_required(VERSION 3.20) -project(itlab_2024) - -include(cmake/configure.cmake) +set(ProjectName "itlab") +project(${ProjectName}) include_directories(include) -enable_testing() +include_directories(include) -add_subdirectory(3rdparty) -add_subdirectory(app) -add_subdirectory(include) -add_subdirectory(src) +add_subdirectory(3rdparty/googletest) +add_subdirectory(src/graph) add_subdirectory(test) # REPORT diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt deleted file mode 100644 index 168bbf0..0000000 --- a/include/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -file(GLOB_RECURSE graph_headers graph/*.h) -set(GRAPH_HEADERS "${graph_headers}" PARENT_SCOPE) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index eceaa59..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(graph) \ No newline at end of file diff --git a/src/graph/CMakeLists.txt b/src/graph/CMakeLists.txt index fe4c58a..af77d7d 100644 --- a/src/graph/CMakeLists.txt +++ b/src/graph/CMakeLists.txt @@ -1,2 +1,7 @@ -file(GLOB_RECURSE graph_src *.cpp) -add_library(graph_lib STATIC "${GRAPH_HEADERS}" "${graph_src}") \ No newline at end of file +file(GLOB_RECURSE HEADER_FILES "${CMAKE_SOURCE_DIR}/include/*.h") +file(GLOB_RECURSE SOURCE_FILES "${CMAKE_SOURCE_DIR}/src/*.cpp") + +add_library(${ProjectName} STATIC ${SOURCE_FILES} ${HEADER_FILES}) +target_sources(${ProjectName} PRIVATE ${HEADER_FILES}) + +target_include_directories(${ProjectName} PUBLIC ${CMAKE_SOURCE_DIR}/src) \ No newline at end of file diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index 3cd9d99..d29061b 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -72,13 +72,7 @@ void Graph::removeVertex(int id_) { } } -int Graph::vertexCount() const { - int count = 0; - for (const auto& vertice : vertices_) { - count++; - } - return count; -} +int Graph::vertexCount() const { return static_cast(vertices_.size()); } int Graph::edgeCount() const { int count = 0; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2048a6b..48c524f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,10 @@ -file(GLOB_RECURSE TEST_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) -add_executable(run_tests ${TEST_SRC_FILES}) -target_link_libraries(run_tests PUBLIC - gtest_main -) \ No newline at end of file +file(GLOB_RECURSE TEST_FILES ./*.cpp) + +set(TestsName "run_tests") + +add_executable(${TestsName} ${TEST_FILES}) + +target_link_libraries(${TestsName} PRIVATE ${ProjectName} gtest) + +enable_testing() +add_test(NAME ${TestsName} COMMAND ${TestsName}) \ No newline at end of file diff --git a/test/graph/main.cpp b/test/graph/main.cpp index d6efe14..9a17845 100644 --- a/test/graph/main.cpp +++ b/test/graph/main.cpp @@ -1,7 +1,6 @@ #include "gtest/gtest.h" - -int main(int argc, char **argv) { +int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } \ No newline at end of file From 116cf4a3505b7fc15a3690c197d0da19d5301d81 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 4 Mar 2025 18:08:12 +0300 Subject: [PATCH 09/36] tensor add 1.0 --- CMakeLists.txt | 2 +- include/tensor/tensor.h | 42 ++++++++++++++++++ src/tensor/CMakeLists.txt | 7 +++ src/tensor/tensor.cpp | 74 +++++++++++++++++++++++++++++++ test/CMakeLists.txt | 3 +- test/tensor/test_tensor.cpp | 88 +++++++++++++++++++++++++++++++++++++ 6 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 include/tensor/tensor.h create mode 100644 src/tensor/CMakeLists.txt create mode 100644 src/tensor/tensor.cpp create mode 100644 test/tensor/test_tensor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cf34635..62c28f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ project(${ProjectName}) include_directories(include) -include_directories(include) +enable_testing() add_subdirectory(3rdparty/googletest) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h new file mode 100644 index 0000000..f58414b --- /dev/null +++ b/include/tensor/tensor.h @@ -0,0 +1,42 @@ +#ifndef TENSOR_H +#define TENSOR_H + +#include +#include +#include +#include +#include +#include +#include +#include + +struct Shape { + std::vector dimensions; + size_t total_elements; + + Shape(std::vector dims); + + size_t get_rank() const; +}; + +enum class Layout { NCHW, NHWC, ND }; + +template +class Tensor { + public: + Shape shape; + Layout layout; + std::vector data; + Tensor(const Shape &sh, Layout l = Layout::ND); + Tensor(std::vector dims, Layout l = Layout::ND); + + size_t get_linear_index(const std::vector &indices) const; + + T &at(const std::vector &indices); + const T &at(const std::vector &indices) const; + +}; + +#endif + + \ No newline at end of file diff --git a/src/tensor/CMakeLists.txt b/src/tensor/CMakeLists.txt new file mode 100644 index 0000000..af77d7d --- /dev/null +++ b/src/tensor/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE HEADER_FILES "${CMAKE_SOURCE_DIR}/include/*.h") +file(GLOB_RECURSE SOURCE_FILES "${CMAKE_SOURCE_DIR}/src/*.cpp") + +add_library(${ProjectName} STATIC ${SOURCE_FILES} ${HEADER_FILES}) +target_sources(${ProjectName} PRIVATE ${HEADER_FILES}) + +target_include_directories(${ProjectName} PUBLIC ${CMAKE_SOURCE_DIR}/src) \ No newline at end of file diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp new file mode 100644 index 0000000..07cab2b --- /dev/null +++ b/src/tensor/tensor.cpp @@ -0,0 +1,74 @@ +#include "./tensor/tensor.h" + +Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { + total_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1ULL, + std::multiplies<>()); +} + +size_t Shape::get_rank() const { return dimensions.size(); } + +template +Tensor::Tensor(const Shape &sh, Layout l) + : shape(sh), layout(l), data(sh.total_elements) { + if (sh.get_rank() == 4 && l == Layout::ND) { + std::cerr << "4D Tensor created with ND layout." << std::endl; + } +} + +template +Tensor::Tensor(std::vector dims, Layout l) + : Tensor(Shape(std::move(dims)), l) {} + + +template +size_t Tensor::get_linear_index(const std::vector &indices) const { + if (indices.size() != shape.get_rank()) { + throw std::runtime_error("Incorrect number of indices provided."); + } + for (size_t i = 0; i < indices.size(); ++i) { + if (indices[i] >= shape.dimensions[i]) { + throw std::out_of_range("Index out of range for dimension"); + } + } + + size_t linear_index = 0; + size_t stride = 1; + + if (shape.get_rank() == 4) { + if (layout == Layout::NCHW) { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } else if (layout == Layout::NHWC) { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } else { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } + } else { + std::vector reversed_dims = shape.dimensions; + std::reverse(reversed_dims.begin(), reversed_dims.end()); + for (int i = static_cast(reversed_dims.size()) - 1; i >= 0; --i) { + linear_index += indices[i] * stride; + stride *= reversed_dims[i]; + } + } + + return linear_index; +} + +template +T &Tensor::at(const std::vector &indices) { + return data[get_linear_index(indices)]; +} + +template +const T &Tensor::at(const std::vector &indices) const { + return data[get_linear_index(indices)]; +} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 48c524f..049ad49 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,7 @@ + file(GLOB_RECURSE TEST_FILES ./*.cpp) -set(TestsName "run_tests") +set(TestsName "run_test") add_executable(${TestsName} ${TEST_FILES}) diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp new file mode 100644 index 0000000..3e11630 --- /dev/null +++ b/test/tensor/test_tensor.cpp @@ -0,0 +1,88 @@ +#include "gtest/gtest.h" +#include "./tensor/tensor.h" +#include "./tensor/tensor.cpp" + +TEST(ShapeTest, ConstructorAndGetRank) { + + Shape s({2, 3, 4}); + + ASSERT_EQ(s.get_rank(), 3); + ASSERT_EQ(s.total_elements, 24); +} + +TEST(TensorTestDouble, ConstructorAndAccess) { + + Tensor t({2, 3}, Layout::ND); + t.at({0, 0}) = 1.0; + t.at({0, 1}) = 2.0; + t.at({0, 2}) = 3.0; + t.at({1, 0}) = 4.0; + t.at({1, 1}) = 5.0; + t.at({1, 2}) = 6.0; + + ASSERT_DOUBLE_EQ(t.at({0, 0}), 1.0); + ASSERT_DOUBLE_EQ(t.at({0, 1}), 2.0); + ASSERT_DOUBLE_EQ(t.at({0, 2}), 4.0); + ASSERT_DOUBLE_EQ(t.at({1, 0}), 4.0); + ASSERT_DOUBLE_EQ(t.at({1, 1}), 5.0); + ASSERT_DOUBLE_EQ(t.at({1, 2}), 6.0); + + const Tensor &ct = t; + + ASSERT_DOUBLE_EQ(ct.at({0, 1}), 2.0); +} + +TEST(TensorTestDouble, GetLinearIndex2D_ND) { + + Tensor t({2, 3}, Layout::ND); + + ASSERT_EQ(t.get_linear_index({0, 0}), 0); + ASSERT_EQ(t.get_linear_index({0, 2}), 2); + ASSERT_EQ(t.get_linear_index({1, 0}), 2); + ASSERT_EQ(t.get_linear_index({1, 2}), 4); +} + +TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { + + Tensor t({2, 3, 4, 5}, Layout::NCHW); + + ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); + ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); +} + +TEST(TensorTestDouble, GetLinearIndex4D_NHWC) { + + Tensor t({2, 3, 4, 5}, Layout::NHWC); + + ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); + ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); +} +TEST(TensorTestDouble, GetLinearIndex4D_ND) { + + Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); + + ASSERT_EQ(t4d_nd.get_linear_index({0, 0, 0, 0}), 0); + ASSERT_EQ(t4d_nd.get_linear_index({1, 2, 3, 4}), 119); +} + +TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { + + Tensor t2d({2, 3}, Layout::ND); + Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); + Tensor t4d_nhwc({2, 3, 4, 5}, Layout::NHWC); + Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); + + EXPECT_THROW(t2d.get_linear_index({2, 0}), std::out_of_range); + EXPECT_THROW(t2d.get_linear_index({0, 3}), std::out_of_range); + EXPECT_THROW(t4d_nchw.get_linear_index({2, 0, 0, 0}), std::out_of_range); + EXPECT_THROW(t4d_nhwc.get_linear_index({0, 3, 0, 0}), std::out_of_range); + EXPECT_THROW(t4d_nd.get_linear_index({0, 0, 4, 0}), std::out_of_range); +} + +TEST(TensorTestDouble, GetLinearIndex_WrongNumberOfIndices) { + Tensor t2d({2, 3}, Layout::ND); + Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); + + EXPECT_THROW(t2d.get_linear_index({0}), std::runtime_error); + EXPECT_THROW(t4d_nchw.get_linear_index({0, 0, 0}), std::runtime_error); +} \ No newline at end of file From 55a9ee81433669d51cd48d0d5f23aa5439578b9b Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 23 Mar 2025 20:52:10 +0300 Subject: [PATCH 10/36] graph pr fix --- include/tensor/tensor.h | 42 ------------------ src/tensor/CMakeLists.txt | 7 --- src/tensor/tensor.cpp | 74 ------------------------------- test/tensor/test_tensor.cpp | 88 ------------------------------------- 4 files changed, 211 deletions(-) delete mode 100644 include/tensor/tensor.h delete mode 100644 src/tensor/CMakeLists.txt delete mode 100644 src/tensor/tensor.cpp delete mode 100644 test/tensor/test_tensor.cpp diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h deleted file mode 100644 index f58414b..0000000 --- a/include/tensor/tensor.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TENSOR_H -#define TENSOR_H - -#include -#include -#include -#include -#include -#include -#include -#include - -struct Shape { - std::vector dimensions; - size_t total_elements; - - Shape(std::vector dims); - - size_t get_rank() const; -}; - -enum class Layout { NCHW, NHWC, ND }; - -template -class Tensor { - public: - Shape shape; - Layout layout; - std::vector data; - Tensor(const Shape &sh, Layout l = Layout::ND); - Tensor(std::vector dims, Layout l = Layout::ND); - - size_t get_linear_index(const std::vector &indices) const; - - T &at(const std::vector &indices); - const T &at(const std::vector &indices) const; - -}; - -#endif - - \ No newline at end of file diff --git a/src/tensor/CMakeLists.txt b/src/tensor/CMakeLists.txt deleted file mode 100644 index af77d7d..0000000 --- a/src/tensor/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -file(GLOB_RECURSE HEADER_FILES "${CMAKE_SOURCE_DIR}/include/*.h") -file(GLOB_RECURSE SOURCE_FILES "${CMAKE_SOURCE_DIR}/src/*.cpp") - -add_library(${ProjectName} STATIC ${SOURCE_FILES} ${HEADER_FILES}) -target_sources(${ProjectName} PRIVATE ${HEADER_FILES}) - -target_include_directories(${ProjectName} PUBLIC ${CMAKE_SOURCE_DIR}/src) \ No newline at end of file diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp deleted file mode 100644 index 07cab2b..0000000 --- a/src/tensor/tensor.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "./tensor/tensor.h" - -Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { - total_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1ULL, - std::multiplies<>()); -} - -size_t Shape::get_rank() const { return dimensions.size(); } - -template -Tensor::Tensor(const Shape &sh, Layout l) - : shape(sh), layout(l), data(sh.total_elements) { - if (sh.get_rank() == 4 && l == Layout::ND) { - std::cerr << "4D Tensor created with ND layout." << std::endl; - } -} - -template -Tensor::Tensor(std::vector dims, Layout l) - : Tensor(Shape(std::move(dims)), l) {} - - -template -size_t Tensor::get_linear_index(const std::vector &indices) const { - if (indices.size() != shape.get_rank()) { - throw std::runtime_error("Incorrect number of indices provided."); - } - for (size_t i = 0; i < indices.size(); ++i) { - if (indices[i] >= shape.dimensions[i]) { - throw std::out_of_range("Index out of range for dimension"); - } - } - - size_t linear_index = 0; - size_t stride = 1; - - if (shape.get_rank() == 4) { - if (layout == Layout::NCHW) { - linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * - shape.dimensions[3]) + - indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + - indices[2] * shape.dimensions[3] + indices[3]; - } else if (layout == Layout::NHWC) { - linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * - shape.dimensions[3]) + - indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + - indices[2] * shape.dimensions[3] + indices[3]; - } else { - linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * - shape.dimensions[3]) + - indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + - indices[2] * shape.dimensions[3] + indices[3]; - } - } else { - std::vector reversed_dims = shape.dimensions; - std::reverse(reversed_dims.begin(), reversed_dims.end()); - for (int i = static_cast(reversed_dims.size()) - 1; i >= 0; --i) { - linear_index += indices[i] * stride; - stride *= reversed_dims[i]; - } - } - - return linear_index; -} - -template -T &Tensor::at(const std::vector &indices) { - return data[get_linear_index(indices)]; -} - -template -const T &Tensor::at(const std::vector &indices) const { - return data[get_linear_index(indices)]; -} \ No newline at end of file diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp deleted file mode 100644 index 3e11630..0000000 --- a/test/tensor/test_tensor.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "gtest/gtest.h" -#include "./tensor/tensor.h" -#include "./tensor/tensor.cpp" - -TEST(ShapeTest, ConstructorAndGetRank) { - - Shape s({2, 3, 4}); - - ASSERT_EQ(s.get_rank(), 3); - ASSERT_EQ(s.total_elements, 24); -} - -TEST(TensorTestDouble, ConstructorAndAccess) { - - Tensor t({2, 3}, Layout::ND); - t.at({0, 0}) = 1.0; - t.at({0, 1}) = 2.0; - t.at({0, 2}) = 3.0; - t.at({1, 0}) = 4.0; - t.at({1, 1}) = 5.0; - t.at({1, 2}) = 6.0; - - ASSERT_DOUBLE_EQ(t.at({0, 0}), 1.0); - ASSERT_DOUBLE_EQ(t.at({0, 1}), 2.0); - ASSERT_DOUBLE_EQ(t.at({0, 2}), 4.0); - ASSERT_DOUBLE_EQ(t.at({1, 0}), 4.0); - ASSERT_DOUBLE_EQ(t.at({1, 1}), 5.0); - ASSERT_DOUBLE_EQ(t.at({1, 2}), 6.0); - - const Tensor &ct = t; - - ASSERT_DOUBLE_EQ(ct.at({0, 1}), 2.0); -} - -TEST(TensorTestDouble, GetLinearIndex2D_ND) { - - Tensor t({2, 3}, Layout::ND); - - ASSERT_EQ(t.get_linear_index({0, 0}), 0); - ASSERT_EQ(t.get_linear_index({0, 2}), 2); - ASSERT_EQ(t.get_linear_index({1, 0}), 2); - ASSERT_EQ(t.get_linear_index({1, 2}), 4); -} - -TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { - - Tensor t({2, 3, 4, 5}, Layout::NCHW); - - ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); - ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); -} - -TEST(TensorTestDouble, GetLinearIndex4D_NHWC) { - - Tensor t({2, 3, 4, 5}, Layout::NHWC); - - ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); - ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); -} -TEST(TensorTestDouble, GetLinearIndex4D_ND) { - - Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); - - ASSERT_EQ(t4d_nd.get_linear_index({0, 0, 0, 0}), 0); - ASSERT_EQ(t4d_nd.get_linear_index({1, 2, 3, 4}), 119); -} - -TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { - - Tensor t2d({2, 3}, Layout::ND); - Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); - Tensor t4d_nhwc({2, 3, 4, 5}, Layout::NHWC); - Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); - - EXPECT_THROW(t2d.get_linear_index({2, 0}), std::out_of_range); - EXPECT_THROW(t2d.get_linear_index({0, 3}), std::out_of_range); - EXPECT_THROW(t4d_nchw.get_linear_index({2, 0, 0, 0}), std::out_of_range); - EXPECT_THROW(t4d_nhwc.get_linear_index({0, 3, 0, 0}), std::out_of_range); - EXPECT_THROW(t4d_nd.get_linear_index({0, 0, 4, 0}), std::out_of_range); -} - -TEST(TensorTestDouble, GetLinearIndex_WrongNumberOfIndices) { - Tensor t2d({2, 3}, Layout::ND); - Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); - - EXPECT_THROW(t2d.get_linear_index({0}), std::runtime_error); - EXPECT_THROW(t4d_nchw.get_linear_index({0, 0, 0}), std::runtime_error); -} \ No newline at end of file From b3e62d481bbdb5dbed31507aee9bc35a14bb97c6 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 23 Mar 2025 21:13:53 +0300 Subject: [PATCH 11/36] tensor class v0.1 --- include/graph/graph.h | 43 -------- include/tensor/tensor.h | 42 ++++++++ src/graph/graph.cpp | 141 ------------------------ src/{graph => tensor}/CMakeLists.txt | 0 src/tensor/tensor.cpp | 74 +++++++++++++ test/graph/main.cpp | 6 -- test/graph/test_graph.cpp | 154 --------------------------- test/tensor/test_tensor.cpp | 88 +++++++++++++++ 8 files changed, 204 insertions(+), 344 deletions(-) delete mode 100644 include/graph/graph.h create mode 100644 include/tensor/tensor.h delete mode 100644 src/graph/graph.cpp rename src/{graph => tensor}/CMakeLists.txt (100%) create mode 100644 src/tensor/tensor.cpp delete mode 100644 test/graph/main.cpp delete mode 100644 test/graph/test_graph.cpp create mode 100644 test/tensor/test_tensor.cpp diff --git a/include/graph/graph.h b/include/graph/graph.h deleted file mode 100644 index bf2b478..0000000 --- a/include/graph/graph.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef GRAPH_H -#define GRAPH_H - -#include -#include -#include - -class Vertex { - private: - int id_; - std::list neighbors_; - - public: - Vertex(int id_); - void addNeighbor(int neighbor); - void removeNeighbor(int neighbor); - void print() const; - int getId() const; - const std::list& getNeighbors() const; -}; - -class Graph { - private: - std::unordered_map vertices_; - - public: - Graph(); - void addVertex(int id_); - void getVertex() const; - void addEdge(int u, int v); - void removeEdge(int u, int v); - void removeVertex(int id_); - int vertexCount() const; - int edgeCount() const; - bool empty() const; - void printGraph() const; - bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord); - bool hasPath(int u, int v); - std::vector BFS(int start); - ~Graph(); -}; - -#endif diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h new file mode 100644 index 0000000..f58414b --- /dev/null +++ b/include/tensor/tensor.h @@ -0,0 +1,42 @@ +#ifndef TENSOR_H +#define TENSOR_H + +#include +#include +#include +#include +#include +#include +#include +#include + +struct Shape { + std::vector dimensions; + size_t total_elements; + + Shape(std::vector dims); + + size_t get_rank() const; +}; + +enum class Layout { NCHW, NHWC, ND }; + +template +class Tensor { + public: + Shape shape; + Layout layout; + std::vector data; + Tensor(const Shape &sh, Layout l = Layout::ND); + Tensor(std::vector dims, Layout l = Layout::ND); + + size_t get_linear_index(const std::vector &indices) const; + + T &at(const std::vector &indices); + const T &at(const std::vector &indices) const; + +}; + +#endif + + \ No newline at end of file diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp deleted file mode 100644 index d29061b..0000000 --- a/src/graph/graph.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include "./graph/graph.h" - -#include -#include -#include -#include -#include - -Vertex::Vertex(int id_) : id_(id_) {} - -void Vertex::addNeighbor(int neighbor) { - if (neighbor != id_) { - neighbors_.push_back(neighbor); - } -} - -void Vertex::removeNeighbor(int neighbor) { neighbors_.remove(neighbor); } - -void Vertex::print() const { - std::cout << id_ << ": "; - for (const int& neighbor : neighbors_) { - std::cout << neighbor << " "; - } - std::cout << '\n'; -} - -int Vertex::getId() const { return id_; } - -const std::list& Vertex::getNeighbors() const { return neighbors_; } - -Graph::Graph() = default; - -void Graph::addVertex(int id_) { - if (vertices_.find(id_) == vertices_.end()) { - vertices_[id_] = new Vertex(id_); - } -} - -void Graph::getVertex() const { - if (!this->empty()) { - for (const auto& vertice : vertices_) { - std::cout << vertice.first << " "; - } - std::cout << '\n'; - } -} - -void Graph::addEdge(int u, int v) { - if (vertices_.find(u) == vertices_.end()) { - addVertex(u); - } - if (vertices_.find(v) == vertices_.end()) { - addVertex(v); - } - vertices_[u]->addNeighbor(v); -} - -void Graph::removeEdge(int u, int v) { - if (vertices_.find(u) != vertices_.end()) { - vertices_[u]->removeNeighbor(v); - } -} - -void Graph::removeVertex(int id_) { - for (auto& pair : vertices_) { - pair.second->removeNeighbor(id_); - } - auto it = vertices_.find(id_); - if (it != vertices_.end()) { - delete it->second; - vertices_.erase(it); - } -} - -int Graph::vertexCount() const { return static_cast(vertices_.size()); } - -int Graph::edgeCount() const { - int count = 0; - for (const auto& vertice : vertices_) { - count += (vertice.second->getNeighbors()).size(); - } - return count; -} - -bool Graph::empty() const { return vertices_.empty(); } - -void Graph::printGraph() const { - for (const auto& pair : vertices_) { - pair.second->print(); - } -} - -bool Graph::bfs_helper(int start, int vert, bool flag, - std::vector* v_ord) { - std::unordered_map visited; - std::queue queue; - queue.push(start); - visited[start] = true; - - while (!queue.empty()) { - int current = queue.front(); - queue.pop(); - - if (flag && current == vert) { - return true; - } - if (v_ord != nullptr) { - v_ord->push_back(current); - } - - if (vertices_.find(current) != vertices_.end()) { - for (const int& neighbor : vertices_[current]->getNeighbors()) { - if (!visited[neighbor]) { - visited[neighbor] = true; - queue.push(neighbor); - } - } - } - } - return false; -} - -bool Graph::hasPath(int u, int v) { - if (vertices_.find(u) == vertices_.end() || - vertices_.find(v) == vertices_.end()) { - return false; - } - return bfs_helper(u, v, true, nullptr); -} - -std::vector Graph::BFS(int start) { - std::vector v_ord; - bfs_helper(start, -1, false, &v_ord); - return v_ord; -} - -Graph::~Graph() { - for (auto& pair : vertices_) { - delete pair.second; - } -} \ No newline at end of file diff --git a/src/graph/CMakeLists.txt b/src/tensor/CMakeLists.txt similarity index 100% rename from src/graph/CMakeLists.txt rename to src/tensor/CMakeLists.txt diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp new file mode 100644 index 0000000..07cab2b --- /dev/null +++ b/src/tensor/tensor.cpp @@ -0,0 +1,74 @@ +#include "./tensor/tensor.h" + +Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { + total_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1ULL, + std::multiplies<>()); +} + +size_t Shape::get_rank() const { return dimensions.size(); } + +template +Tensor::Tensor(const Shape &sh, Layout l) + : shape(sh), layout(l), data(sh.total_elements) { + if (sh.get_rank() == 4 && l == Layout::ND) { + std::cerr << "4D Tensor created with ND layout." << std::endl; + } +} + +template +Tensor::Tensor(std::vector dims, Layout l) + : Tensor(Shape(std::move(dims)), l) {} + + +template +size_t Tensor::get_linear_index(const std::vector &indices) const { + if (indices.size() != shape.get_rank()) { + throw std::runtime_error("Incorrect number of indices provided."); + } + for (size_t i = 0; i < indices.size(); ++i) { + if (indices[i] >= shape.dimensions[i]) { + throw std::out_of_range("Index out of range for dimension"); + } + } + + size_t linear_index = 0; + size_t stride = 1; + + if (shape.get_rank() == 4) { + if (layout == Layout::NCHW) { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } else if (layout == Layout::NHWC) { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } else { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } + } else { + std::vector reversed_dims = shape.dimensions; + std::reverse(reversed_dims.begin(), reversed_dims.end()); + for (int i = static_cast(reversed_dims.size()) - 1; i >= 0; --i) { + linear_index += indices[i] * stride; + stride *= reversed_dims[i]; + } + } + + return linear_index; +} + +template +T &Tensor::at(const std::vector &indices) { + return data[get_linear_index(indices)]; +} + +template +const T &Tensor::at(const std::vector &indices) const { + return data[get_linear_index(indices)]; +} \ No newline at end of file diff --git a/test/graph/main.cpp b/test/graph/main.cpp deleted file mode 100644 index 9a17845..0000000 --- a/test/graph/main.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "gtest/gtest.h" - -int main(int argc, char** argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp deleted file mode 100644 index daeecf0..0000000 --- a/test/graph/test_graph.cpp +++ /dev/null @@ -1,154 +0,0 @@ -#include - -#include "graph/graph.h" -#include "gtest/gtest.h" - -TEST(Graph, can_create_graph) { ASSERT_NO_THROW(Graph g); } - -TEST(Graph, can_add_vertex_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addVertex(1)); -} - -TEST(Graph, can_add_edge_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 0)); -} - -TEST(Graph, can_add_edge_with_same_id_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 1)); -} - -TEST(Graph, can_add_vertex_and_edge_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 0)); - ASSERT_NO_THROW(g.addVertex(1)); -} - -TEST(Graph, can_get_vertex) { - Graph g; - g.addEdge(1, 0); - - ASSERT_NO_THROW(g.getVertex()); -} - -TEST(Graph, can_remove_vertex) { - Graph g; - g.addEdge(1, 0); - - g.removeVertex(1); - - ASSERT_EQ(g.vertexCount(), 1); -} - -TEST(Graph, can_get_vertex_count) { - Graph g; - - g.addEdge(1, 0); - g.addVertex(2); - g.addVertex(3); - g.removeVertex(1); - g.addVertex(1); - g.removeVertex(3); - - ASSERT_EQ(g.vertexCount(), 3); -} - -TEST(Graph, can_get_edge_count) { - Graph g; - - g.addEdge(1, 0); - g.addEdge(2, 0); - g.addEdge(0, 2); - g.addEdge(2, 2); - - ASSERT_EQ(g.edgeCount(), 3); -} - -TEST(Graph, check_graph_is_empty) { - Graph g; - - ASSERT_TRUE(g.empty()); -} - -TEST(Graph, check_graph_is_not_empty) { - Graph g; - - g.addEdge(1, 0); - - ASSERT_FALSE(g.empty()); -} - -TEST(Graph, check_graph_no_path_between_vertexes) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - - ASSERT_FALSE(g.hasPath(1, 0)); -} - -TEST(Graph, check_graph_has_path_between_vertexes) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - - ASSERT_TRUE(g.hasPath(3, 1)); -} - -TEST(Graph, check_graph_can_find_path_between_vertexes_after_delete) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - g.removeVertex(3); - - ASSERT_FALSE(g.hasPath(3, 1)); - ASSERT_FALSE(g.hasPath(0, 3)); -} - -TEST(Graph, can_create_bfs_path) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - - ASSERT_NO_THROW(g.BFS(0)); -} - -TEST(Graph, can_create_bfs_path_in_empty_graph) { - Graph g; - - ASSERT_NO_THROW(g.BFS(0)); -} - -TEST(Graph, check_bfs_path) { - Graph g; - std::vector v1 = {0, 1, 3, 2, 4, 6, 7, 5, 8, 9}; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 4); - g.addEdge(4, 5); - g.addEdge(3, 6); - g.addEdge(3, 7); - g.addEdge(7, 8); - g.addEdge(8, 9); - std::vector v = g.BFS(0); - - ASSERT_EQ(v, v1); -} \ No newline at end of file diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp new file mode 100644 index 0000000..3e11630 --- /dev/null +++ b/test/tensor/test_tensor.cpp @@ -0,0 +1,88 @@ +#include "gtest/gtest.h" +#include "./tensor/tensor.h" +#include "./tensor/tensor.cpp" + +TEST(ShapeTest, ConstructorAndGetRank) { + + Shape s({2, 3, 4}); + + ASSERT_EQ(s.get_rank(), 3); + ASSERT_EQ(s.total_elements, 24); +} + +TEST(TensorTestDouble, ConstructorAndAccess) { + + Tensor t({2, 3}, Layout::ND); + t.at({0, 0}) = 1.0; + t.at({0, 1}) = 2.0; + t.at({0, 2}) = 3.0; + t.at({1, 0}) = 4.0; + t.at({1, 1}) = 5.0; + t.at({1, 2}) = 6.0; + + ASSERT_DOUBLE_EQ(t.at({0, 0}), 1.0); + ASSERT_DOUBLE_EQ(t.at({0, 1}), 2.0); + ASSERT_DOUBLE_EQ(t.at({0, 2}), 4.0); + ASSERT_DOUBLE_EQ(t.at({1, 0}), 4.0); + ASSERT_DOUBLE_EQ(t.at({1, 1}), 5.0); + ASSERT_DOUBLE_EQ(t.at({1, 2}), 6.0); + + const Tensor &ct = t; + + ASSERT_DOUBLE_EQ(ct.at({0, 1}), 2.0); +} + +TEST(TensorTestDouble, GetLinearIndex2D_ND) { + + Tensor t({2, 3}, Layout::ND); + + ASSERT_EQ(t.get_linear_index({0, 0}), 0); + ASSERT_EQ(t.get_linear_index({0, 2}), 2); + ASSERT_EQ(t.get_linear_index({1, 0}), 2); + ASSERT_EQ(t.get_linear_index({1, 2}), 4); +} + +TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { + + Tensor t({2, 3, 4, 5}, Layout::NCHW); + + ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); + ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); +} + +TEST(TensorTestDouble, GetLinearIndex4D_NHWC) { + + Tensor t({2, 3, 4, 5}, Layout::NHWC); + + ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); + ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); +} +TEST(TensorTestDouble, GetLinearIndex4D_ND) { + + Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); + + ASSERT_EQ(t4d_nd.get_linear_index({0, 0, 0, 0}), 0); + ASSERT_EQ(t4d_nd.get_linear_index({1, 2, 3, 4}), 119); +} + +TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { + + Tensor t2d({2, 3}, Layout::ND); + Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); + Tensor t4d_nhwc({2, 3, 4, 5}, Layout::NHWC); + Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); + + EXPECT_THROW(t2d.get_linear_index({2, 0}), std::out_of_range); + EXPECT_THROW(t2d.get_linear_index({0, 3}), std::out_of_range); + EXPECT_THROW(t4d_nchw.get_linear_index({2, 0, 0, 0}), std::out_of_range); + EXPECT_THROW(t4d_nhwc.get_linear_index({0, 3, 0, 0}), std::out_of_range); + EXPECT_THROW(t4d_nd.get_linear_index({0, 0, 4, 0}), std::out_of_range); +} + +TEST(TensorTestDouble, GetLinearIndex_WrongNumberOfIndices) { + Tensor t2d({2, 3}, Layout::ND); + Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); + + EXPECT_THROW(t2d.get_linear_index({0}), std::runtime_error); + EXPECT_THROW(t4d_nchw.get_linear_index({0, 0, 0}), std::runtime_error); +} \ No newline at end of file From f65be878390000bfbb648529c6cc40b228e99cdd Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 24 Mar 2025 23:40:15 +0300 Subject: [PATCH 12/36] tensor v0.2 --- CMakeLists.txt | 2 +- include/graph/graph.h | 43 +++++++++ src/{tensor => }/CMakeLists.txt | 0 src/graph/graph.cpp | 141 +++++++++++++++++++++++++++++ test/graph/test_graph.cpp | 154 ++++++++++++++++++++++++++++++++ test/main.cpp | 6 ++ 6 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 include/graph/graph.h rename src/{tensor => }/CMakeLists.txt (100%) create mode 100644 src/graph/graph.cpp create mode 100644 test/graph/test_graph.cpp create mode 100644 test/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 62c28f8..027fa33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ enable_testing() add_subdirectory(3rdparty/googletest) -add_subdirectory(src/graph) +add_subdirectory(src) add_subdirectory(test) # REPORT diff --git a/include/graph/graph.h b/include/graph/graph.h new file mode 100644 index 0000000..bf2b478 --- /dev/null +++ b/include/graph/graph.h @@ -0,0 +1,43 @@ +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include + +class Vertex { + private: + int id_; + std::list neighbors_; + + public: + Vertex(int id_); + void addNeighbor(int neighbor); + void removeNeighbor(int neighbor); + void print() const; + int getId() const; + const std::list& getNeighbors() const; +}; + +class Graph { + private: + std::unordered_map vertices_; + + public: + Graph(); + void addVertex(int id_); + void getVertex() const; + void addEdge(int u, int v); + void removeEdge(int u, int v); + void removeVertex(int id_); + int vertexCount() const; + int edgeCount() const; + bool empty() const; + void printGraph() const; + bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord); + bool hasPath(int u, int v); + std::vector BFS(int start); + ~Graph(); +}; + +#endif diff --git a/src/tensor/CMakeLists.txt b/src/CMakeLists.txt similarity index 100% rename from src/tensor/CMakeLists.txt rename to src/CMakeLists.txt diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp new file mode 100644 index 0000000..d29061b --- /dev/null +++ b/src/graph/graph.cpp @@ -0,0 +1,141 @@ +#include "./graph/graph.h" + +#include +#include +#include +#include +#include + +Vertex::Vertex(int id_) : id_(id_) {} + +void Vertex::addNeighbor(int neighbor) { + if (neighbor != id_) { + neighbors_.push_back(neighbor); + } +} + +void Vertex::removeNeighbor(int neighbor) { neighbors_.remove(neighbor); } + +void Vertex::print() const { + std::cout << id_ << ": "; + for (const int& neighbor : neighbors_) { + std::cout << neighbor << " "; + } + std::cout << '\n'; +} + +int Vertex::getId() const { return id_; } + +const std::list& Vertex::getNeighbors() const { return neighbors_; } + +Graph::Graph() = default; + +void Graph::addVertex(int id_) { + if (vertices_.find(id_) == vertices_.end()) { + vertices_[id_] = new Vertex(id_); + } +} + +void Graph::getVertex() const { + if (!this->empty()) { + for (const auto& vertice : vertices_) { + std::cout << vertice.first << " "; + } + std::cout << '\n'; + } +} + +void Graph::addEdge(int u, int v) { + if (vertices_.find(u) == vertices_.end()) { + addVertex(u); + } + if (vertices_.find(v) == vertices_.end()) { + addVertex(v); + } + vertices_[u]->addNeighbor(v); +} + +void Graph::removeEdge(int u, int v) { + if (vertices_.find(u) != vertices_.end()) { + vertices_[u]->removeNeighbor(v); + } +} + +void Graph::removeVertex(int id_) { + for (auto& pair : vertices_) { + pair.second->removeNeighbor(id_); + } + auto it = vertices_.find(id_); + if (it != vertices_.end()) { + delete it->second; + vertices_.erase(it); + } +} + +int Graph::vertexCount() const { return static_cast(vertices_.size()); } + +int Graph::edgeCount() const { + int count = 0; + for (const auto& vertice : vertices_) { + count += (vertice.second->getNeighbors()).size(); + } + return count; +} + +bool Graph::empty() const { return vertices_.empty(); } + +void Graph::printGraph() const { + for (const auto& pair : vertices_) { + pair.second->print(); + } +} + +bool Graph::bfs_helper(int start, int vert, bool flag, + std::vector* v_ord) { + std::unordered_map visited; + std::queue queue; + queue.push(start); + visited[start] = true; + + while (!queue.empty()) { + int current = queue.front(); + queue.pop(); + + if (flag && current == vert) { + return true; + } + if (v_ord != nullptr) { + v_ord->push_back(current); + } + + if (vertices_.find(current) != vertices_.end()) { + for (const int& neighbor : vertices_[current]->getNeighbors()) { + if (!visited[neighbor]) { + visited[neighbor] = true; + queue.push(neighbor); + } + } + } + } + return false; +} + +bool Graph::hasPath(int u, int v) { + if (vertices_.find(u) == vertices_.end() || + vertices_.find(v) == vertices_.end()) { + return false; + } + return bfs_helper(u, v, true, nullptr); +} + +std::vector Graph::BFS(int start) { + std::vector v_ord; + bfs_helper(start, -1, false, &v_ord); + return v_ord; +} + +Graph::~Graph() { + for (auto& pair : vertices_) { + delete pair.second; + } +} \ No newline at end of file diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp new file mode 100644 index 0000000..daeecf0 --- /dev/null +++ b/test/graph/test_graph.cpp @@ -0,0 +1,154 @@ +#include + +#include "graph/graph.h" +#include "gtest/gtest.h" + +TEST(Graph, can_create_graph) { ASSERT_NO_THROW(Graph g); } + +TEST(Graph, can_add_vertex_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addVertex(1)); +} + +TEST(Graph, can_add_edge_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 0)); +} + +TEST(Graph, can_add_edge_with_same_id_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 1)); +} + +TEST(Graph, can_add_vertex_and_edge_to_graph) { + Graph g; + + ASSERT_NO_THROW(g.addEdge(1, 0)); + ASSERT_NO_THROW(g.addVertex(1)); +} + +TEST(Graph, can_get_vertex) { + Graph g; + g.addEdge(1, 0); + + ASSERT_NO_THROW(g.getVertex()); +} + +TEST(Graph, can_remove_vertex) { + Graph g; + g.addEdge(1, 0); + + g.removeVertex(1); + + ASSERT_EQ(g.vertexCount(), 1); +} + +TEST(Graph, can_get_vertex_count) { + Graph g; + + g.addEdge(1, 0); + g.addVertex(2); + g.addVertex(3); + g.removeVertex(1); + g.addVertex(1); + g.removeVertex(3); + + ASSERT_EQ(g.vertexCount(), 3); +} + +TEST(Graph, can_get_edge_count) { + Graph g; + + g.addEdge(1, 0); + g.addEdge(2, 0); + g.addEdge(0, 2); + g.addEdge(2, 2); + + ASSERT_EQ(g.edgeCount(), 3); +} + +TEST(Graph, check_graph_is_empty) { + Graph g; + + ASSERT_TRUE(g.empty()); +} + +TEST(Graph, check_graph_is_not_empty) { + Graph g; + + g.addEdge(1, 0); + + ASSERT_FALSE(g.empty()); +} + +TEST(Graph, check_graph_no_path_between_vertexes) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + + ASSERT_FALSE(g.hasPath(1, 0)); +} + +TEST(Graph, check_graph_has_path_between_vertexes) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + + ASSERT_TRUE(g.hasPath(3, 1)); +} + +TEST(Graph, check_graph_can_find_path_between_vertexes_after_delete) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 1); + g.removeVertex(3); + + ASSERT_FALSE(g.hasPath(3, 1)); + ASSERT_FALSE(g.hasPath(0, 3)); +} + +TEST(Graph, can_create_bfs_path) { + Graph g; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + + ASSERT_NO_THROW(g.BFS(0)); +} + +TEST(Graph, can_create_bfs_path_in_empty_graph) { + Graph g; + + ASSERT_NO_THROW(g.BFS(0)); +} + +TEST(Graph, check_bfs_path) { + Graph g; + std::vector v1 = {0, 1, 3, 2, 4, 6, 7, 5, 8, 9}; + + g.addEdge(0, 1); + g.addEdge(0, 3); + g.addEdge(1, 2); + g.addEdge(3, 4); + g.addEdge(4, 5); + g.addEdge(3, 6); + g.addEdge(3, 7); + g.addEdge(7, 8); + g.addEdge(8, 9); + std::vector v = g.BFS(0); + + ASSERT_EQ(v, v1); +} \ No newline at end of file diff --git a/test/main.cpp b/test/main.cpp new file mode 100644 index 0000000..9a17845 --- /dev/null +++ b/test/main.cpp @@ -0,0 +1,6 @@ +#include "gtest/gtest.h" + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From 7e9a38976c6b85d54b6f11a3662e5a4026c3d3e8 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 24 Mar 2025 23:49:52 +0300 Subject: [PATCH 13/36] tensor v0.3 --- src/tensor/tensor.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 07cab2b..7cb945a 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -1,23 +1,20 @@ #include "./tensor/tensor.h" Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { - total_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1ULL, - std::multiplies<>()); + total_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1ULL, std::multiplies()); } size_t Shape::get_rank() const { return dimensions.size(); } template -Tensor::Tensor(const Shape &sh, Layout l) - : shape(sh), layout(l), data(sh.total_elements) { +Tensor::Tensor(const Shape &sh, Layout l) : shape(sh), layout(l), data(sh.total_elements) { if (sh.get_rank() == 4 && l == Layout::ND) { std::cerr << "4D Tensor created with ND layout." << std::endl; } } template -Tensor::Tensor(std::vector dims, Layout l) - : Tensor(Shape(std::move(dims)), l) {} +Tensor::Tensor(std::vector dims, Layout l): Tensor(Shape(std::move(dims)), l) {} template From f2547dadf4b03a5304e5af2375b5229998181d9c Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Mar 2025 12:17:36 +0300 Subject: [PATCH 14/36] tensor v0.3 --- include/tensor/tensor.h | 21 ++++++++------------- src/tensor/tensor.cpp | 16 +++++++++++----- test/tensor/test_tensor.cpp | 22 +++++++++++----------- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index f58414b..7f0b8b2 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -2,12 +2,9 @@ #define TENSOR_H #include -#include -#include -#include +#include #include #include -#include #include struct Shape { @@ -19,24 +16,22 @@ struct Shape { size_t get_rank() const; }; -enum class Layout { NCHW, NHWC, ND }; +enum class Layout { kNchw, kNhwc, kNd }; -template +template class Tensor { public: Shape shape; Layout layout; - std::vector data; - Tensor(const Shape &sh, Layout l = Layout::ND); - Tensor(std::vector dims, Layout l = Layout::ND); + std::vector data; + + Tensor(const Shape &sh, Layout l = Layout::kNd); + Tensor(std::vector dims, Layout l = Layout::kNd); size_t get_linear_index(const std::vector &indices) const; T &at(const std::vector &indices); const T &at(const std::vector &indices) const; - }; -#endif - - \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 7cb945a..85b07e5 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -1,15 +1,21 @@ #include "./tensor/tensor.h" +#include +#include +#include +#include +#include + Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { - total_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1ULL, std::multiplies()); + total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), std::multiplies()); } size_t Shape::get_rank() const { return dimensions.size(); } template Tensor::Tensor(const Shape &sh, Layout l) : shape(sh), layout(l), data(sh.total_elements) { - if (sh.get_rank() == 4 && l == Layout::ND) { - std::cerr << "4D Tensor created with ND layout." << std::endl; + if (sh.get_rank() == 4 && l == Layout::kNd) { + std::cerr << "4D Tensor created with kNd layout." << '\n'; } } @@ -32,12 +38,12 @@ size_t Tensor::get_linear_index(const std::vector &indices) const { size_t stride = 1; if (shape.get_rank() == 4) { - if (layout == Layout::NCHW) { + if (layout == Layout::kNchw) { linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * shape.dimensions[3]) + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + indices[2] * shape.dimensions[3] + indices[3]; - } else if (layout == Layout::NHWC) { + } else if (layout == Layout::kNhwc) { linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * shape.dimensions[3]) + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp index 3e11630..8ef3933 100644 --- a/test/tensor/test_tensor.cpp +++ b/test/tensor/test_tensor.cpp @@ -12,7 +12,7 @@ TEST(ShapeTest, ConstructorAndGetRank) { TEST(TensorTestDouble, ConstructorAndAccess) { - Tensor t({2, 3}, Layout::ND); + Tensor t({2, 3}, Layout::kNd); t.at({0, 0}) = 1.0; t.at({0, 1}) = 2.0; t.at({0, 2}) = 3.0; @@ -34,7 +34,7 @@ TEST(TensorTestDouble, ConstructorAndAccess) { TEST(TensorTestDouble, GetLinearIndex2D_ND) { - Tensor t({2, 3}, Layout::ND); + Tensor t({2, 3}, Layout::kNd); ASSERT_EQ(t.get_linear_index({0, 0}), 0); ASSERT_EQ(t.get_linear_index({0, 2}), 2); @@ -44,7 +44,7 @@ TEST(TensorTestDouble, GetLinearIndex2D_ND) { TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { - Tensor t({2, 3, 4, 5}, Layout::NCHW); + Tensor t({2, 3, 4, 5}, Layout::kNchw); ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); @@ -52,14 +52,14 @@ TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { TEST(TensorTestDouble, GetLinearIndex4D_NHWC) { - Tensor t({2, 3, 4, 5}, Layout::NHWC); + Tensor t({2, 3, 4, 5}, Layout::kNhwc); ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); } TEST(TensorTestDouble, GetLinearIndex4D_ND) { - Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); + Tensor t4d_nd({2, 3, 4, 5}, Layout::kNd); ASSERT_EQ(t4d_nd.get_linear_index({0, 0, 0, 0}), 0); ASSERT_EQ(t4d_nd.get_linear_index({1, 2, 3, 4}), 119); @@ -67,10 +67,10 @@ TEST(TensorTestDouble, GetLinearIndex4D_ND) { TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { - Tensor t2d({2, 3}, Layout::ND); - Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); - Tensor t4d_nhwc({2, 3, 4, 5}, Layout::NHWC); - Tensor t4d_nd({2, 3, 4, 5}, Layout::ND); + Tensor t2d({2, 3}, Layout::kNd); + Tensor t4d_nchw({2, 3, 4, 5}, Layout::kNchw); + Tensor t4d_nhwc({2, 3, 4, 5}, Layout::kNhwc); + Tensor t4d_nd({2, 3, 4, 5}, Layout::kNd); EXPECT_THROW(t2d.get_linear_index({2, 0}), std::out_of_range); EXPECT_THROW(t2d.get_linear_index({0, 3}), std::out_of_range); @@ -80,8 +80,8 @@ TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { } TEST(TensorTestDouble, GetLinearIndex_WrongNumberOfIndices) { - Tensor t2d({2, 3}, Layout::ND); - Tensor t4d_nchw({2, 3, 4, 5}, Layout::NCHW); + Tensor t2d({2, 3}, Layout::kNd); + Tensor t4d_nchw({2, 3, 4, 5}, Layout::kNchw); EXPECT_THROW(t2d.get_linear_index({0}), std::runtime_error); EXPECT_THROW(t4d_nchw.get_linear_index({0, 0, 0}), std::runtime_error); From a89b0ba0158e5607125db46ff0f1ae5b653b2c31 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Mar 2025 12:28:08 +0300 Subject: [PATCH 15/36] tensor v0.4 --- include/tensor/tensor.h | 7 ++----- src/tensor/tensor.cpp | 5 ++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index 7f0b8b2..27e3d3a 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -1,11 +1,8 @@ #ifndef TENSOR_H #define TENSOR_H -#include -#include -#include -#include #include +#include struct Shape { std::vector dimensions; @@ -16,7 +13,7 @@ struct Shape { size_t get_rank() const; }; -enum class Layout { kNchw, kNhwc, kNd }; +enum class Layout : std::uint8_t { kNchw, kNhwc, kNd }; template class Tensor { diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 85b07e5..75ebafe 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -5,9 +5,12 @@ #include #include #include +#include +#include +#include Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { - total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), std::multiplies()); + total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), std::multiplies<>()); } size_t Shape::get_rank() const { return dimensions.size(); } From 9dcf39d1e30bfa7dfd53884e18866824b6a92730 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Mar 2025 12:35:31 +0300 Subject: [PATCH 16/36] tensor built fix --- src/tensor/tensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 75ebafe..3d508e8 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -10,7 +10,7 @@ #include Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { - total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), std::multiplies<>()); + total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), [](size_t a, size_t b) { return a * b; }); } size_t Shape::get_rank() const { return dimensions.size(); } From fbf472edf136f4ede5c2cce91dd3bd5d93620522 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Mar 2025 12:45:13 +0300 Subject: [PATCH 17/36] tensor fix --- include/tensor/tensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index 27e3d3a..869bc66 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -13,7 +13,7 @@ struct Shape { size_t get_rank() const; }; -enum class Layout : std::uint8_t { kNchw, kNhwc, kNd }; +enum class Layout { kNchw, kNhwc, kNd }; template class Tensor { From ad52dd044a0326d882d0aed455a51769ec345b23 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 30 Mar 2025 23:23:40 +0300 Subject: [PATCH 18/36] codecov fix --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 31adbd5..7eea43f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -102,7 +102,7 @@ jobs: cmake --build build --parallel - name: Test run: | - build/bin/run_tests + build/test/run_test env: CTEST_OUTPUT_ON_FAILURE: 1 - name: Generate lcov Coverage Data From 2fc68324b6c5b098a485435b5948882847674f77 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 30 Mar 2025 23:35:30 +0300 Subject: [PATCH 19/36] macos-clang-build --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 027fa33..98d5ae1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 3.20) +set(CMAKE_CXX_STANDARD 11) set(ProjectName "itlab") project(${ProjectName}) From 0efcb04878956849477516b9460b317d03d6405d Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 30 Mar 2025 23:45:58 +0300 Subject: [PATCH 20/36] clang-format --- include/tensor/tensor.h | 2 +- src/tensor/tensor.cpp | 14 +++++++++----- test/tensor/test_tensor.cpp | 12 +++--------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index 869bc66..ac91aed 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -1,8 +1,8 @@ #ifndef TENSOR_H #define TENSOR_H -#include #include +#include struct Shape { std::vector dimensions; diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 3d508e8..269d62c 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -1,29 +1,33 @@ #include "./tensor/tensor.h" #include +#include #include #include #include #include -#include -#include #include +#include Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { - total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), [](size_t a, size_t b) { return a * b; }); + total_elements = std::accumulate(dimensions.begin(), dimensions.end(), + static_cast(1), + [](size_t a, size_t b) { return a * b; }); } size_t Shape::get_rank() const { return dimensions.size(); } template -Tensor::Tensor(const Shape &sh, Layout l) : shape(sh), layout(l), data(sh.total_elements) { +Tensor::Tensor(const Shape &sh, Layout l) + : shape(sh), layout(l), data(sh.total_elements) { if (sh.get_rank() == 4 && l == Layout::kNd) { std::cerr << "4D Tensor created with kNd layout." << '\n'; } } template -Tensor::Tensor(std::vector dims, Layout l): Tensor(Shape(std::move(dims)), l) {} +Tensor::Tensor(std::vector dims, Layout l) + : Tensor(Shape(std::move(dims)), l) {} template diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp index 8ef3933..be9176e 100644 --- a/test/tensor/test_tensor.cpp +++ b/test/tensor/test_tensor.cpp @@ -1,9 +1,9 @@ -#include "gtest/gtest.h" #include "./tensor/tensor.h" #include "./tensor/tensor.cpp" -TEST(ShapeTest, ConstructorAndGetRank) { +#include "gtest/gtest.h" +TEST(ShapeTest, ConstructorAndGetRank) { Shape s({2, 3, 4}); ASSERT_EQ(s.get_rank(), 3); @@ -11,7 +11,6 @@ TEST(ShapeTest, ConstructorAndGetRank) { } TEST(TensorTestDouble, ConstructorAndAccess) { - Tensor t({2, 3}, Layout::kNd); t.at({0, 0}) = 1.0; t.at({0, 1}) = 2.0; @@ -20,7 +19,7 @@ TEST(TensorTestDouble, ConstructorAndAccess) { t.at({1, 1}) = 5.0; t.at({1, 2}) = 6.0; - ASSERT_DOUBLE_EQ(t.at({0, 0}), 1.0); + ASSERT_DOUBLE_EQ(t.at({0, 0}), 1.0); ASSERT_DOUBLE_EQ(t.at({0, 1}), 2.0); ASSERT_DOUBLE_EQ(t.at({0, 2}), 4.0); ASSERT_DOUBLE_EQ(t.at({1, 0}), 4.0); @@ -33,7 +32,6 @@ TEST(TensorTestDouble, ConstructorAndAccess) { } TEST(TensorTestDouble, GetLinearIndex2D_ND) { - Tensor t({2, 3}, Layout::kNd); ASSERT_EQ(t.get_linear_index({0, 0}), 0); @@ -43,7 +41,6 @@ TEST(TensorTestDouble, GetLinearIndex2D_ND) { } TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { - Tensor t({2, 3, 4, 5}, Layout::kNchw); ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); @@ -51,14 +48,12 @@ TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { } TEST(TensorTestDouble, GetLinearIndex4D_NHWC) { - Tensor t({2, 3, 4, 5}, Layout::kNhwc); ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); } TEST(TensorTestDouble, GetLinearIndex4D_ND) { - Tensor t4d_nd({2, 3, 4, 5}, Layout::kNd); ASSERT_EQ(t4d_nd.get_linear_index({0, 0, 0, 0}), 0); @@ -66,7 +61,6 @@ TEST(TensorTestDouble, GetLinearIndex4D_ND) { } TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { - Tensor t2d({2, 3}, Layout::kNd); Tensor t4d_nchw({2, 3, 4, 5}, Layout::kNchw); Tensor t4d_nhwc({2, 3, 4, 5}, Layout::kNhwc); From 4d6849504c09814b6e90d98f31c43c936b560d00 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 30 Mar 2025 23:54:49 +0300 Subject: [PATCH 21/36] clang-format 2 --- src/tensor/tensor.cpp | 1 - test/tensor/test_tensor.cpp | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 269d62c..313868d 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -29,7 +29,6 @@ template Tensor::Tensor(std::vector dims, Layout l) : Tensor(Shape(std::move(dims)), l) {} - template size_t Tensor::get_linear_index(const std::vector &indices) const { if (indices.size() != shape.get_rank()) { diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp index be9176e..78cafb7 100644 --- a/test/tensor/test_tensor.cpp +++ b/test/tensor/test_tensor.cpp @@ -1,6 +1,5 @@ -#include "./tensor/tensor.h" #include "./tensor/tensor.cpp" - +#include "./tensor/tensor.h" #include "gtest/gtest.h" TEST(ShapeTest, ConstructorAndGetRank) { @@ -19,7 +18,6 @@ TEST(TensorTestDouble, ConstructorAndAccess) { t.at({1, 1}) = 5.0; t.at({1, 2}) = 6.0; - ASSERT_DOUBLE_EQ(t.at({0, 0}), 1.0); ASSERT_DOUBLE_EQ(t.at({0, 1}), 2.0); ASSERT_DOUBLE_EQ(t.at({0, 2}), 4.0); ASSERT_DOUBLE_EQ(t.at({1, 0}), 4.0); From 2c2d70868c4c465dd61e7199589ebbf9144bfd61 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Mar 2025 00:09:05 +0300 Subject: [PATCH 22/36] clang-tidy --- include/tensor/tensor.h | 2 +- src/tensor/tensor.cpp | 1 - test/tensor/test_tensor.cpp | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index ac91aed..67a125a 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -13,7 +13,7 @@ struct Shape { size_t get_rank() const; }; -enum class Layout { kNchw, kNhwc, kNd }; +enum class Layout : std::uint8_t { kNchw, kNhwc, kNd }; template class Tensor { diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 313868d..bc05f10 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp index 78cafb7..464fcaa 100644 --- a/test/tensor/test_tensor.cpp +++ b/test/tensor/test_tensor.cpp @@ -1,4 +1,5 @@ -#include "./tensor/tensor.cpp" +#include + #include "./tensor/tensor.h" #include "gtest/gtest.h" From 7d848781c64f4bb27119a8806f56fa5e6d35e0ed Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Mar 2025 00:12:41 +0300 Subject: [PATCH 23/36] errors fix --- include/tensor/tensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index 67a125a..dd33027 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -13,7 +13,7 @@ struct Shape { size_t get_rank() const; }; -enum class Layout : std::uint8_t { kNchw, kNhwc, kNd }; +enum Layout : std::uint8_t { kNchw, kNhwc, kNd }; template class Tensor { From d07c3d8e2d5e72631878cfeea273aa46a36845d4 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Mar 2025 00:17:35 +0300 Subject: [PATCH 24/36] errors fix 2 --- include/tensor/tensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index dd33027..ac91aed 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -13,7 +13,7 @@ struct Shape { size_t get_rank() const; }; -enum Layout : std::uint8_t { kNchw, kNhwc, kNd }; +enum class Layout { kNchw, kNhwc, kNd }; template class Tensor { From 96b403ccc8c644044053c67925c7413dabfb4d22 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Mar 2025 00:37:49 +0300 Subject: [PATCH 25/36] error fix 3 --- include/tensor/tensor.h | 2 +- src/tensor/tensor.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index ac91aed..67a125a 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -13,7 +13,7 @@ struct Shape { size_t get_rank() const; }; -enum class Layout { kNchw, kNhwc, kNd }; +enum class Layout : std::uint8_t { kNchw, kNhwc, kNd }; template class Tensor { diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index bc05f10..5fdb0a8 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -8,6 +8,8 @@ #include #include +template class Tensor; + Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), From 7be04f0aad7f18f30d2c98bb761d0dc25efe944d Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Mar 2025 00:41:59 +0300 Subject: [PATCH 26/36] error fix 4 --- include/tensor/tensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index 67a125a..dd33027 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -13,7 +13,7 @@ struct Shape { size_t get_rank() const; }; -enum class Layout : std::uint8_t { kNchw, kNhwc, kNd }; +enum Layout : std::uint8_t { kNchw, kNhwc, kNd }; template class Tensor { From aaa5d805a53edb2d630d75e19fb302753d024df6 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Mar 2025 00:44:20 +0300 Subject: [PATCH 27/36] errors fix 5 --- include/tensor/tensor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index dd33027..a3bc2a8 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -2,6 +2,7 @@ #define TENSOR_H #include +#include #include struct Shape { From 0ca033164eca980a9211e4834a9e3eece52d8f70 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 31 Mar 2025 00:51:37 +0300 Subject: [PATCH 28/36] errors fix 7 --- src/tensor/tensor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 5fdb0a8..702791b 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -8,8 +8,6 @@ #include #include -template class Tensor; - Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { total_elements = std::accumulate(dimensions.begin(), dimensions.end(), static_cast(1), @@ -81,4 +79,6 @@ T &Tensor::at(const std::vector &indices) { template const T &Tensor::at(const std::vector &indices) const { return data[get_linear_index(indices)]; -} \ No newline at end of file +} + +template class Tensor; \ No newline at end of file From ff1a8f8df3993a8322d66d54464d9f3ee3374c08 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 1 Apr 2025 00:28:23 +0300 Subject: [PATCH 29/36] add layer, change graph --- include/graph/graph.h | 44 ++++---- include/layer/layer.h | 24 ++++ src/graph/graph.cpp | 226 +++++++++++++++++++++++--------------- src/layer/layer.cpp | 9 ++ src/tensor/tensor.cpp | 3 +- test/graph/test_graph.cpp | 151 ------------------------- 6 files changed, 191 insertions(+), 266 deletions(-) create mode 100644 include/layer/layer.h create mode 100644 src/layer/layer.cpp diff --git a/include/graph/graph.h b/include/graph/graph.h index bf2b478..6b2f243 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -1,42 +1,38 @@ #ifndef GRAPH_H #define GRAPH_H + #include #include #include - -class Vertex { - private: - int id_; - std::list neighbors_; - - public: - Vertex(int id_); - void addNeighbor(int neighbor); - void removeNeighbor(int neighbor); - void print() const; - int getId() const; - const std::list& getNeighbors() const; -}; +#include "./layer/layer.h" +#include "./tensor/tensor.h" class Graph { private: - std::unordered_map vertices_; + std::unordered_map layers_; + Tensor inputTensor_; + Tensor* outputTensor_; + int start_ = -1; + int end_ = -1; + bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord) const; public: Graph(); - void addVertex(int id_); - void getVertex() const; - void addEdge(int u, int v); - void removeEdge(int u, int v); - void removeVertex(int id_); - int vertexCount() const; + + void addLayer(Layer& lay); + void getLayers() const; + void addEdge(Layer& layPrev, Layer& layNext); + void removeEdge(Layer& layPrev, Layer& layNext); + void removeLayer(Layer& lay); + int layerCount() const; int edgeCount() const; bool empty() const; - void printGraph() const; - bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord); - bool hasPath(int u, int v); + bool hasPath(Layer& layPrev, Layer& layNext) const; std::vector BFS(int start); + void setInput(Layer& lay, Tensor& vec); + void setOutput(Layer& lay, Tensor& vec); + void inference(); ~Graph(); }; diff --git a/include/layer/layer.h b/include/layer/layer.h new file mode 100644 index 0000000..c45c6d3 --- /dev/null +++ b/include/layer/layer.h @@ -0,0 +1,24 @@ +#ifndef LAYER_H +#define LAYER_H + +#include + +#include "./tensor/tensor.h" + +class Layer { + protected: + int id_; + + public: + Layer() = default; + virtual ~Layer() = default; + void setID(int id) { id_ = id; } + int getID() const { return id_; } + virtual void run(const Tensor& input, Tensor& output) = 0; + virtual Shape get_output_shape() = 0; + + void addNeighbor(Layer* neighbor); + void removeNeighbor(Layer* neighbor); + std::list neighbors_; +}; +#endif \ No newline at end of file diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index d29061b..f7a090c 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,141 +1,187 @@ +#include +#include +#include +#include + #include "./graph/graph.h" +#include "./layer/layer.h" +#include "./tensor/tensor.h" -#include -#include -#include -#include -#include +Graph::Graph() + : inputTensor_({}), outputTensor_(nullptr), start_(-1), end_(-1) {} -Vertex::Vertex(int id_) : id_(id_) {} +bool Graph::bfs_helper(int start, int vert, bool flag, + std::vector* v_ord) const { + std::unordered_map visited; + std::queue queue; -void Vertex::addNeighbor(int neighbor) { - if (neighbor != id_) { - neighbors_.push_back(neighbor); - } -} + queue.push(start); + visited[start] = true; -void Vertex::removeNeighbor(int neighbor) { neighbors_.remove(neighbor); } + while (!queue.empty()) { + int current = queue.front(); + queue.pop(); -void Vertex::print() const { - std::cout << id_ << ": "; - for (const int& neighbor : neighbors_) { - std::cout << neighbor << " "; - } - std::cout << '\n'; -} + if (flag && current == vert) { + return true; + } -int Vertex::getId() const { return id_; } + if (v_ord != nullptr) { + v_ord->push_back(current); + } + + if (layers_.count(current) > 0) { + Layer* currentLayer = layers_.at(current); -const std::list& Vertex::getNeighbors() const { return neighbors_; } + for (Layer* neighbor : currentLayer->neighbors_) { + if (visited.find(neighbor->getID()) == visited.end()) { + visited[neighbor->getID()] = true; + queue.push(neighbor->getID()); + } + } + } + } -Graph::Graph() = default; + return false; +} -void Graph::addVertex(int id_) { - if (vertices_.find(id_) == vertices_.end()) { - vertices_[id_] = new Vertex(id_); +void Graph::addLayer(Layer& lay) { + if (layers_.find(lay.getID()) == layers_.end()) { + layers_[lay.getID()] = &lay; } } -void Graph::getVertex() const { +void Graph::getLayers() const { if (!this->empty()) { - for (const auto& vertice : vertices_) { - std::cout << vertice.first << " "; + for (const auto& layer : layers_) { + std::cout << layer.first << " "; } std::cout << '\n'; } } -void Graph::addEdge(int u, int v) { - if (vertices_.find(u) == vertices_.end()) { - addVertex(u); +void Graph::addEdge(Layer& layPrev, Layer& layNext) { + if (layPrev.getID() == layNext.getID()) { + throw std::invalid_argument("Cannot add edge from a layer to itself."); + } + if (layers_.find(layPrev.getID()) == layers_.end()) { + addLayer(layPrev); } - if (vertices_.find(v) == vertices_.end()) { - addVertex(v); + if (layers_.find(layNext.getID()) == layers_.end()) { + addLayer(layNext); } - vertices_[u]->addNeighbor(v); + layPrev.addNeighbor(&layNext); // Èñïîëüçóåì ìåòîä addNeighbor } -void Graph::removeEdge(int u, int v) { - if (vertices_.find(u) != vertices_.end()) { - vertices_[u]->removeNeighbor(v); +void Graph::removeEdge(Layer& layPrev, Layer& layNext) { + if (layers_.find(layPrev.getID()) != layers_.end()) { + layPrev.removeNeighbor(&layNext); } } -void Graph::removeVertex(int id_) { - for (auto& pair : vertices_) { - pair.second->removeNeighbor(id_); +void Graph::removeLayer(Layer& lay) { + int layerID = lay.getID(); + + if (layers_.find(layerID) == layers_.end()) { + return; + } + + for (auto& pair : layers_) { + pair.second->removeNeighbor(&lay); + } + + auto it = layers_.find(layerID); + if (it != layers_.end()) { + layers_.erase(it); } - auto it = vertices_.find(id_); - if (it != vertices_.end()) { - delete it->second; - vertices_.erase(it); + + if (start_ == layerID) { + start_ = -1; + } + if (end_ == layerID) { + end_ = -1; } } -int Graph::vertexCount() const { return static_cast(vertices_.size()); } +int Graph::layerCount() const { return static_cast(layers_.size()); } int Graph::edgeCount() const { int count = 0; - for (const auto& vertice : vertices_) { - count += (vertice.second->getNeighbors()).size(); + for (const auto& layer : layers_) { + count += layer.second->neighbors_.size(); } return count; } -bool Graph::empty() const { return vertices_.empty(); } +bool Graph::empty() const { return layers_.empty(); } -void Graph::printGraph() const { - for (const auto& pair : vertices_) { - pair.second->print(); +bool Graph::hasPath(Layer& layPrev, Layer& layNext) const { + if (layers_.find(layPrev.getID()) == layers_.end() || + layers_.find(layNext.getID()) == layers_.end()) { + return false; } + return bfs_helper(layPrev.getID(), layNext.getID(), true, nullptr); } -bool Graph::bfs_helper(int start, int vert, bool flag, - std::vector* v_ord) { - std::unordered_map visited; - std::queue queue; - queue.push(start); - visited[start] = true; +std::vector Graph::BFS(int start) { + std::vector v_ord; + bfs_helper(start, -1, false, &v_ord); + return v_ord; +} - while (!queue.empty()) { - int current = queue.front(); - queue.pop(); +void Graph::setInput(Layer& lay, Tensor& vec) { + if (start_ != -1) { + throw std::runtime_error("Input layer already set."); + } + if (!layers_.empty()) { + addLayer(lay); + } + inputTensor_ = vec; + start_ = lay.getID(); +} - if (flag && current == vert) { - return true; - } - if (v_ord != nullptr) { - v_ord->push_back(current); - } +void Graph::setOutput(Layer& lay, Tensor& vec) { + if (end_ != -1) { + throw std::runtime_error("Output layer already set."); + } - if (vertices_.find(current) != vertices_.end()) { - for (const int& neighbor : vertices_[current]->getNeighbors()) { - if (!visited[neighbor]) { - visited[neighbor] = true; - queue.push(neighbor); - } - } - } + if (layers_.find(lay.getID()) == layers_.end()) { + addLayer(lay); } - return false; + + end_ = lay.getID(); + outputTensor_ = &vec; } -bool Graph::hasPath(int u, int v) { - if (vertices_.find(u) == vertices_.end() || - vertices_.find(v) == vertices_.end()) { - return false; +void Graph::inference() { + if (start_ == -1 || end_ == -1) { + throw std::runtime_error("Input or output layer not set."); } - return bfs_helper(u, v, true, nullptr); -} -std::vector Graph::BFS(int start) { - std::vector v_ord; - bfs_helper(start, -1, false, &v_ord); - return v_ord; -} + std::vector traversal = BFS(start_); + + if (traversal.empty() || traversal.back() != end_) { + throw std::runtime_error("No path from start to end layer found."); + } + + Tensor currentTensor = inputTensor_; -Graph::~Graph() { - for (auto& pair : vertices_) { - delete pair.second; + for (int layerID : traversal) { + if (layers_.find(layerID) == layers_.end()) { + throw std::runtime_error("layerID out of range in traversal."); + } + Layer* currentLayer = layers_[layerID]; + Tensor tempOutputTensor(currentLayer->get_output_shape()); + currentLayer->run(currentTensor, tempOutputTensor); + currentTensor = tempOutputTensor; + + if (layerID == end_) { + if (outputTensor_ == nullptr) { + throw std::runtime_error("Output tensor pointer is not set."); + } + *outputTensor_ = currentTensor; + } } -} \ No newline at end of file +} + +Graph::~Graph() {} \ No newline at end of file diff --git a/src/layer/layer.cpp b/src/layer/layer.cpp new file mode 100644 index 0000000..fb20e90 --- /dev/null +++ b/src/layer/layer.cpp @@ -0,0 +1,9 @@ +#include "./layer/layer.h" + +void Layer::addNeighbor(Layer* neighbor) { + if (neighbor != nullptr) { + neighbors_.push_back(neighbor); + } +} + +void Layer::removeNeighbor(Layer* neighbor) { neighbors_.remove(neighbor); } \ No newline at end of file diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 702791b..653202e 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -81,4 +81,5 @@ const T &Tensor::at(const std::vector &indices) const { return data[get_linear_index(indices)]; } -template class Tensor; \ No newline at end of file +template class Tensor; +template class Tensor; \ No newline at end of file diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp index daeecf0..e3add58 100644 --- a/test/graph/test_graph.cpp +++ b/test/graph/test_graph.cpp @@ -1,154 +1,3 @@ -#include - #include "graph/graph.h" #include "gtest/gtest.h" -TEST(Graph, can_create_graph) { ASSERT_NO_THROW(Graph g); } - -TEST(Graph, can_add_vertex_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addVertex(1)); -} - -TEST(Graph, can_add_edge_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 0)); -} - -TEST(Graph, can_add_edge_with_same_id_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 1)); -} - -TEST(Graph, can_add_vertex_and_edge_to_graph) { - Graph g; - - ASSERT_NO_THROW(g.addEdge(1, 0)); - ASSERT_NO_THROW(g.addVertex(1)); -} - -TEST(Graph, can_get_vertex) { - Graph g; - g.addEdge(1, 0); - - ASSERT_NO_THROW(g.getVertex()); -} - -TEST(Graph, can_remove_vertex) { - Graph g; - g.addEdge(1, 0); - - g.removeVertex(1); - - ASSERT_EQ(g.vertexCount(), 1); -} - -TEST(Graph, can_get_vertex_count) { - Graph g; - - g.addEdge(1, 0); - g.addVertex(2); - g.addVertex(3); - g.removeVertex(1); - g.addVertex(1); - g.removeVertex(3); - - ASSERT_EQ(g.vertexCount(), 3); -} - -TEST(Graph, can_get_edge_count) { - Graph g; - - g.addEdge(1, 0); - g.addEdge(2, 0); - g.addEdge(0, 2); - g.addEdge(2, 2); - - ASSERT_EQ(g.edgeCount(), 3); -} - -TEST(Graph, check_graph_is_empty) { - Graph g; - - ASSERT_TRUE(g.empty()); -} - -TEST(Graph, check_graph_is_not_empty) { - Graph g; - - g.addEdge(1, 0); - - ASSERT_FALSE(g.empty()); -} - -TEST(Graph, check_graph_no_path_between_vertexes) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - - ASSERT_FALSE(g.hasPath(1, 0)); -} - -TEST(Graph, check_graph_has_path_between_vertexes) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - - ASSERT_TRUE(g.hasPath(3, 1)); -} - -TEST(Graph, check_graph_can_find_path_between_vertexes_after_delete) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 1); - g.removeVertex(3); - - ASSERT_FALSE(g.hasPath(3, 1)); - ASSERT_FALSE(g.hasPath(0, 3)); -} - -TEST(Graph, can_create_bfs_path) { - Graph g; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - - ASSERT_NO_THROW(g.BFS(0)); -} - -TEST(Graph, can_create_bfs_path_in_empty_graph) { - Graph g; - - ASSERT_NO_THROW(g.BFS(0)); -} - -TEST(Graph, check_bfs_path) { - Graph g; - std::vector v1 = {0, 1, 3, 2, 4, 6, 7, 5, 8, 9}; - - g.addEdge(0, 1); - g.addEdge(0, 3); - g.addEdge(1, 2); - g.addEdge(3, 4); - g.addEdge(4, 5); - g.addEdge(3, 6); - g.addEdge(3, 7); - g.addEdge(7, 8); - g.addEdge(8, 9); - std::vector v = g.BFS(0); - - ASSERT_EQ(v, v1); -} \ No newline at end of file From abd51c995736ea8777d0881978276d6f384f9295 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 1 Apr 2025 00:44:12 +0300 Subject: [PATCH 30/36] clang-tidy fix --- include/graph/graph.h | 6 +++--- src/graph/graph.cpp | 42 ++++++++++++++++++++------------------- test/graph/test_graph.cpp | 3 --- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/include/graph/graph.h b/include/graph/graph.h index 6b2f243..8ec8e83 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -1,10 +1,9 @@ #ifndef GRAPH_H #define GRAPH_H - -#include #include #include + #include "./layer/layer.h" #include "./tensor/tensor.h" @@ -15,7 +14,8 @@ class Graph { Tensor* outputTensor_; int start_ = -1; int end_ = -1; - bool bfs_helper(int start, int vert, bool flag, std::vector* v_ord) const; + bool bfs_helper(int start, int vert, bool flag, + std::vector* v_ord) const; public: Graph(); diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index f7a090c..e29702b 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,14 +1,16 @@ -#include #include #include #include +#include +#include +#include #include "./graph/graph.h" #include "./layer/layer.h" #include "./tensor/tensor.h" Graph::Graph() - : inputTensor_({}), outputTensor_(nullptr), start_(-1), end_(-1) {} + : inputTensor_({}), outputTensor_(nullptr) {} bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) const { @@ -31,9 +33,9 @@ bool Graph::bfs_helper(int start, int vert, bool flag, } if (layers_.count(current) > 0) { - Layer* currentLayer = layers_.at(current); + Layer* current_layer = layers_.at(current); - for (Layer* neighbor : currentLayer->neighbors_) { + for (Layer* neighbor : current_layer->neighbors_) { if (visited.find(neighbor->getID()) == visited.end()) { visited[neighbor->getID()] = true; queue.push(neighbor->getID()); @@ -80,9 +82,9 @@ void Graph::removeEdge(Layer& layPrev, Layer& layNext) { } void Graph::removeLayer(Layer& lay) { - int layerID = lay.getID(); + int layer_id = lay.getID(); - if (layers_.find(layerID) == layers_.end()) { + if (layers_.find(layer_id) == layers_.end()) { return; } @@ -90,15 +92,15 @@ void Graph::removeLayer(Layer& lay) { pair.second->removeNeighbor(&lay); } - auto it = layers_.find(layerID); + auto it = layers_.find(layer_id); if (it != layers_.end()) { layers_.erase(it); } - if (start_ == layerID) { + if (start_ == layer_id) { start_ = -1; } - if (end_ == layerID) { + if (end_ == layer_id) { end_ = -1; } } @@ -164,24 +166,24 @@ void Graph::inference() { throw std::runtime_error("No path from start to end layer found."); } - Tensor currentTensor = inputTensor_; + Tensor current_tensor = inputTensor_; - for (int layerID : traversal) { - if (layers_.find(layerID) == layers_.end()) { - throw std::runtime_error("layerID out of range in traversal."); + for (int layer_id : traversal) { + if (layers_.find(layer_id) == layers_.end()) { + throw std::runtime_error("layer_id out of range in traversal."); } - Layer* currentLayer = layers_[layerID]; - Tensor tempOutputTensor(currentLayer->get_output_shape()); - currentLayer->run(currentTensor, tempOutputTensor); - currentTensor = tempOutputTensor; + Layer* current_layer = layers_[layer_id]; + Tensor temp_output_tensor(current_layer->get_output_shape()); + current_layer->run(current_tensor, temp_output_tensor); + current_tensor = temp_output_tensor; - if (layerID == end_) { + if (layer_id == end_) { if (outputTensor_ == nullptr) { throw std::runtime_error("Output tensor pointer is not set."); } - *outputTensor_ = currentTensor; + *outputTensor_ = current_tensor; } } } -Graph::~Graph() {} \ No newline at end of file +Graph::~Graph() = default; \ No newline at end of file diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp index e3add58..e69de29 100644 --- a/test/graph/test_graph.cpp +++ b/test/graph/test_graph.cpp @@ -1,3 +0,0 @@ -#include "graph/graph.h" -#include "gtest/gtest.h" - From e901675732694688bda9bd57faac73d7dd0d4761 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 1 Apr 2025 00:48:44 +0300 Subject: [PATCH 31/36] clang-tidy and clang-format fix --- include/graph/graph.h | 2 +- src/graph/graph.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/graph/graph.h b/include/graph/graph.h index 8ec8e83..b482d70 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -15,7 +15,7 @@ class Graph { int start_ = -1; int end_ = -1; bool bfs_helper(int start, int vert, bool flag, - std::vector* v_ord) const; + std::vector* v_ord) const; public: Graph(); diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index e29702b..95d7811 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,7 +1,7 @@ -#include -#include #include #include +#include +#include #include #include From f379e5125db3074cf6c3b248a328139a6d4a4159 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 1 Apr 2025 00:56:19 +0300 Subject: [PATCH 32/36] clang-format and clang-tidy fix 2 --- include/graph/graph.h | 2 +- src/graph/graph.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/graph/graph.h b/include/graph/graph.h index b482d70..6dd87b4 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -15,7 +15,7 @@ class Graph { int start_ = -1; int end_ = -1; bool bfs_helper(int start, int vert, bool flag, - std::vector* v_ord) const; + std::vector* v_ord) const; public: Graph(); diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index 95d7811..b74c0a6 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -72,7 +72,7 @@ void Graph::addEdge(Layer& layPrev, Layer& layNext) { if (layers_.find(layNext.getID()) == layers_.end()) { addLayer(layNext); } - layPrev.addNeighbor(&layNext); // Èñïîëüçóåì ìåòîä addNeighbor + layPrev.addNeighbor(&layNext); } void Graph::removeEdge(Layer& layPrev, Layer& layNext) { From b185542e8e4739bf3c3e503e7c61ff23b120e0fd Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 1 Apr 2025 00:59:44 +0300 Subject: [PATCH 33/36] clang-format fix --- src/graph/graph.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index b74c0a6..710305d 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,3 +1,4 @@ +#include "./graph/graph.h" #include #include #include @@ -5,12 +6,10 @@ #include #include -#include "./graph/graph.h" #include "./layer/layer.h" #include "./tensor/tensor.h" -Graph::Graph() - : inputTensor_({}), outputTensor_(nullptr) {} +Graph::Graph() : inputTensor_({}), outputTensor_(nullptr) {} bool Graph::bfs_helper(int start, int vert, bool flag, std::vector* v_ord) const { From 5ae7ad86a77ab48a077752fb8e1709f1ac7699e4 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 1 Apr 2025 01:02:05 +0300 Subject: [PATCH 34/36] clang-format fix 2 --- src/graph/graph.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index 710305d..9521e9e 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,4 +1,5 @@ #include "./graph/graph.h" + #include #include #include From e1350f0994357b05b0b056e767590711813168d0 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 8 Apr 2025 01:23:12 +0300 Subject: [PATCH 35/36] tensor fix --- .github/workflows/main.yml | 3 ++ include/graph/graph.h | 5 +-- include/tensor/tensor.h | 63 ++++++++++++++++++++++++++++ src/graph/graph.cpp | 83 +++++++++++++++++-------------------- src/tensor/tensor.cpp | 73 +------------------------------- test/tensor/test_tensor.cpp | 16 +++---- 6 files changed, 114 insertions(+), 129 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7eea43f..eaf6a59 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,6 +15,7 @@ jobs: submodules: recursive - name: Install dependencies run: | + sudo apt-get update sudo apt-get install -y cmake ninja-build ccache scons - name: ccache uses: hendrikmuhs/ccache-action@v1.2 @@ -37,6 +38,7 @@ jobs: submodules: recursive - name: Install dependencies run: | + sudo apt-get update sudo apt-get install -y cmake ninja-build ccache scons - name: ccache uses: hendrikmuhs/ccache-action@v1.2 @@ -81,6 +83,7 @@ jobs: submodules: true - name: Install dependencies run: | + sudo apt-get update sudo apt-get install -y cmake ninja-build ccache gcovr lcov scons - uses: actions/checkout@v4 with: diff --git a/include/graph/graph.h b/include/graph/graph.h index 6dd87b4..501de3e 100644 --- a/include/graph/graph.h +++ b/include/graph/graph.h @@ -21,12 +21,11 @@ class Graph { Graph(); void addLayer(Layer& lay); - void getLayers() const; void addEdge(Layer& layPrev, Layer& layNext); void removeEdge(Layer& layPrev, Layer& layNext); void removeLayer(Layer& lay); - int layerCount() const; - int edgeCount() const; + int getLayers() const; + int getEdges() const; bool empty() const; bool hasPath(Layer& layPrev, Layer& layNext) const; std::vector BFS(int start); diff --git a/include/tensor/tensor.h b/include/tensor/tensor.h index a3bc2a8..b1df5c4 100644 --- a/include/tensor/tensor.h +++ b/include/tensor/tensor.h @@ -1,8 +1,11 @@ #ifndef TENSOR_H #define TENSOR_H +#include #include #include +#include +#include #include struct Shape { @@ -32,4 +35,64 @@ class Tensor { const T &at(const std::vector &indices) const; }; +template +Tensor::Tensor(const Shape &sh, Layout l) + : shape(sh), layout(l), data(sh.total_elements) {} + +template +Tensor::Tensor(std::vector dims, Layout l) + : Tensor(Shape(std::move(dims)), l) {} + +template +size_t Tensor::get_linear_index(const std::vector &indices) const { + if (indices.size() != shape.get_rank()) { + throw std::runtime_error("Incorrect number of indices provided."); + } + for (size_t i = 0; i < indices.size(); ++i) { + if (indices[i] >= shape.dimensions[i]) { + throw std::out_of_range("Index out of range for dimension"); + } + } + + size_t linear_index = 0; + size_t stride = 1; + + if (shape.get_rank() == 4) { + if (layout == Layout::kNchw) { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } else if (layout == Layout::kNhwc) { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } else { + linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * + shape.dimensions[3]) + + indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + + indices[2] * shape.dimensions[3] + indices[3]; + } + } else { + std::vector reversed_dims = shape.dimensions; + std::reverse(reversed_dims.begin(), reversed_dims.end()); + for (int i = static_cast(reversed_dims.size()) - 1; i >= 0; --i) { + linear_index += indices[i] * stride; + stride *= reversed_dims[i]; + } + } + + return linear_index; +} + +template +T &Tensor::at(const std::vector &indices) { + return data[get_linear_index(indices)]; +} + +template +const T &Tensor::at(const std::vector &indices) const { + return data[get_linear_index(indices)]; +} #endif \ No newline at end of file diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index 9521e9e..61b3417 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -12,56 +12,12 @@ Graph::Graph() : inputTensor_({}), outputTensor_(nullptr) {} -bool Graph::bfs_helper(int start, int vert, bool flag, - std::vector* v_ord) const { - std::unordered_map visited; - std::queue queue; - - queue.push(start); - visited[start] = true; - - while (!queue.empty()) { - int current = queue.front(); - queue.pop(); - - if (flag && current == vert) { - return true; - } - - if (v_ord != nullptr) { - v_ord->push_back(current); - } - - if (layers_.count(current) > 0) { - Layer* current_layer = layers_.at(current); - - for (Layer* neighbor : current_layer->neighbors_) { - if (visited.find(neighbor->getID()) == visited.end()) { - visited[neighbor->getID()] = true; - queue.push(neighbor->getID()); - } - } - } - } - - return false; -} - void Graph::addLayer(Layer& lay) { if (layers_.find(lay.getID()) == layers_.end()) { layers_[lay.getID()] = &lay; } } -void Graph::getLayers() const { - if (!this->empty()) { - for (const auto& layer : layers_) { - std::cout << layer.first << " "; - } - std::cout << '\n'; - } -} - void Graph::addEdge(Layer& layPrev, Layer& layNext) { if (layPrev.getID() == layNext.getID()) { throw std::invalid_argument("Cannot add edge from a layer to itself."); @@ -105,9 +61,9 @@ void Graph::removeLayer(Layer& lay) { } } -int Graph::layerCount() const { return static_cast(layers_.size()); } +int Graph::getLayers() const { return static_cast(layers_.size()); } -int Graph::edgeCount() const { +int Graph::getEdges() const { int count = 0; for (const auto& layer : layers_) { count += layer.second->neighbors_.size(); @@ -117,6 +73,41 @@ int Graph::edgeCount() const { bool Graph::empty() const { return layers_.empty(); } +bool Graph::bfs_helper(int start, int vert, bool flag, + std::vector* v_ord) const { + std::unordered_map visited; + std::queue queue; + + queue.push(start); + visited[start] = true; + + while (!queue.empty()) { + int current = queue.front(); + queue.pop(); + + if (flag && current == vert) { + return true; + } + + if (v_ord != nullptr) { + v_ord->push_back(current); + } + + if (layers_.count(current) > 0) { + Layer* current_layer = layers_.at(current); + + for (Layer* neighbor : current_layer->neighbors_) { + if (visited.find(neighbor->getID()) == visited.end()) { + visited[neighbor->getID()] = true; + queue.push(neighbor->getID()); + } + } + } + } + + return false; +} + bool Graph::hasPath(Layer& layPrev, Layer& layNext) const { if (layers_.find(layPrev.getID()) == layers_.end() || layers_.find(layNext.getID()) == layers_.end()) { diff --git a/src/tensor/tensor.cpp b/src/tensor/tensor.cpp index 653202e..2c57e0b 100644 --- a/src/tensor/tensor.cpp +++ b/src/tensor/tensor.cpp @@ -1,10 +1,7 @@ #include "./tensor/tensor.h" -#include #include -#include #include -#include #include #include @@ -14,72 +11,4 @@ Shape::Shape(std::vector dims) : dimensions(std::move(dims)) { [](size_t a, size_t b) { return a * b; }); } -size_t Shape::get_rank() const { return dimensions.size(); } - -template -Tensor::Tensor(const Shape &sh, Layout l) - : shape(sh), layout(l), data(sh.total_elements) { - if (sh.get_rank() == 4 && l == Layout::kNd) { - std::cerr << "4D Tensor created with kNd layout." << '\n'; - } -} - -template -Tensor::Tensor(std::vector dims, Layout l) - : Tensor(Shape(std::move(dims)), l) {} - -template -size_t Tensor::get_linear_index(const std::vector &indices) const { - if (indices.size() != shape.get_rank()) { - throw std::runtime_error("Incorrect number of indices provided."); - } - for (size_t i = 0; i < indices.size(); ++i) { - if (indices[i] >= shape.dimensions[i]) { - throw std::out_of_range("Index out of range for dimension"); - } - } - - size_t linear_index = 0; - size_t stride = 1; - - if (shape.get_rank() == 4) { - if (layout == Layout::kNchw) { - linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * - shape.dimensions[3]) + - indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + - indices[2] * shape.dimensions[3] + indices[3]; - } else if (layout == Layout::kNhwc) { - linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * - shape.dimensions[3]) + - indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + - indices[2] * shape.dimensions[3] + indices[3]; - } else { - linear_index = indices[0] * (shape.dimensions[1] * shape.dimensions[2] * - shape.dimensions[3]) + - indices[1] * (shape.dimensions[2] * shape.dimensions[3]) + - indices[2] * shape.dimensions[3] + indices[3]; - } - } else { - std::vector reversed_dims = shape.dimensions; - std::reverse(reversed_dims.begin(), reversed_dims.end()); - for (int i = static_cast(reversed_dims.size()) - 1; i >= 0; --i) { - linear_index += indices[i] * stride; - stride *= reversed_dims[i]; - } - } - - return linear_index; -} - -template -T &Tensor::at(const std::vector &indices) { - return data[get_linear_index(indices)]; -} - -template -const T &Tensor::at(const std::vector &indices) const { - return data[get_linear_index(indices)]; -} - -template class Tensor; -template class Tensor; \ No newline at end of file +size_t Shape::get_rank() const { return dimensions.size(); } \ No newline at end of file diff --git a/test/tensor/test_tensor.cpp b/test/tensor/test_tensor.cpp index 464fcaa..f21fd86 100644 --- a/test/tensor/test_tensor.cpp +++ b/test/tensor/test_tensor.cpp @@ -3,14 +3,14 @@ #include "./tensor/tensor.h" #include "gtest/gtest.h" -TEST(ShapeTest, ConstructorAndGetRank) { +TEST(ShapeTest, get_rank_and_elem_checks) { Shape s({2, 3, 4}); ASSERT_EQ(s.get_rank(), 3); ASSERT_EQ(s.total_elements, 24); } -TEST(TensorTestDouble, ConstructorAndAccess) { +TEST(TensorTestDouble, can_at_to_tensor) { Tensor t({2, 3}, Layout::kNd); t.at({0, 0}) = 1.0; t.at({0, 1}) = 2.0; @@ -30,7 +30,7 @@ TEST(TensorTestDouble, ConstructorAndAccess) { ASSERT_DOUBLE_EQ(ct.at({0, 1}), 2.0); } -TEST(TensorTestDouble, GetLinearIndex2D_ND) { +TEST(TensorTestDouble, can_get_linear_index2D_ND) { Tensor t({2, 3}, Layout::kNd); ASSERT_EQ(t.get_linear_index({0, 0}), 0); @@ -39,27 +39,27 @@ TEST(TensorTestDouble, GetLinearIndex2D_ND) { ASSERT_EQ(t.get_linear_index({1, 2}), 4); } -TEST(TensorTestDouble, GetLinearIndex4D_NCHW) { +TEST(TensorTestDouble, can_get_linear_index4D_NCHW) { Tensor t({2, 3, 4, 5}, Layout::kNchw); ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); } -TEST(TensorTestDouble, GetLinearIndex4D_NHWC) { +TEST(TensorTestDouble, can_get_linear_index4D_NHWC) { Tensor t({2, 3, 4, 5}, Layout::kNhwc); ASSERT_EQ(t.get_linear_index({0, 0, 0, 0}), 0); ASSERT_EQ(t.get_linear_index({1, 2, 3, 4}), 119); } -TEST(TensorTestDouble, GetLinearIndex4D_ND) { +TEST(TensorTestDouble, can_get_linear_index4D_ND) { Tensor t4d_nd({2, 3, 4, 5}, Layout::kNd); ASSERT_EQ(t4d_nd.get_linear_index({0, 0, 0, 0}), 0); ASSERT_EQ(t4d_nd.get_linear_index({1, 2, 3, 4}), 119); } -TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { +TEST(TensorTestDouble, cant_get_linear_index_out_of_bounds) { Tensor t2d({2, 3}, Layout::kNd); Tensor t4d_nchw({2, 3, 4, 5}, Layout::kNchw); Tensor t4d_nhwc({2, 3, 4, 5}, Layout::kNhwc); @@ -72,7 +72,7 @@ TEST(TensorTestDouble, GetLinearIndex_OutOfBounds) { EXPECT_THROW(t4d_nd.get_linear_index({0, 0, 4, 0}), std::out_of_range); } -TEST(TensorTestDouble, GetLinearIndex_WrongNumberOfIndices) { +TEST(TensorTestDouble, cant_get_linear_index_with_wrong_num_of_indicies) { Tensor t2d({2, 3}, Layout::kNd); Tensor t4d_nchw({2, 3, 4, 5}, Layout::kNchw); From 3155cd816ef5ba4da055b67cb3360282f6f2dcff Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 8 Apr 2025 01:28:14 +0300 Subject: [PATCH 36/36] clang-tidy fix --- src/graph/graph.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/graph/graph.cpp b/src/graph/graph.cpp index 61b3417..885772e 100644 --- a/src/graph/graph.cpp +++ b/src/graph/graph.cpp @@ -1,6 +1,5 @@ #include "./graph/graph.h" -#include #include #include #include