From aca6e0b3331844e86206ba54c6b04731389662f0 Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Wed, 17 Sep 2025 18:27:35 +0300 Subject: [PATCH 01/11] Find subgraph --- app/Converters/requirements.txt | 2 +- include/CMakeLists.txt | 3 + include/graph/graph.hpp | 39 ++++++++-- .../graph_transformations.hpp | 9 +++ src/CMakeLists.txt | 1 + src/graph_transformations/CMakeLists.txt | 3 + .../graph_transformations.cpp | 71 +++++++++++++++++++ test/benchmarking/test_layers_time.cpp | 4 +- test/graph/test_graph.cpp | 27 +++++++ 9 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 include/graph_transformations/graph_transformations.hpp create mode 100644 src/graph_transformations/CMakeLists.txt create mode 100644 src/graph_transformations/graph_transformations.cpp diff --git a/app/Converters/requirements.txt b/app/Converters/requirements.txt index 1bdca87c1..0e76b5807 100644 --- a/app/Converters/requirements.txt +++ b/app/Converters/requirements.txt @@ -1,4 +1,4 @@ -tensorflow==2.19.0 +tensorflow>=2.19.0 onnx>=1.15.0 ultralytics>=8.0.0 numpy>=1.21.0 diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 465b79f8e..1bc48bb39 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,6 +1,9 @@ file(GLOB_RECURSE graph_headers graph/*.h graph/*.hpp) set(GRAPH_HEADERS "${graph_headers}" PARENT_SCOPE) +file(GLOB_RECURSE graphT_headers graph_transformations/*.h graph_transformation/*.hpp) +set(GRAPHT_HEADERS "${graphT_headers}" PARENT_SCOPE) + file(GLOB_RECURSE layers_headers layers/*.h layers/*.hpp) set(LAYERS_HEADERS "${layers_headers}" PARENT_SCOPE) diff --git a/include/graph/graph.hpp b/include/graph/graph.hpp index 82b0a79e6..252c35b48 100644 --- a/include/graph/graph.hpp +++ b/include/graph/graph.hpp @@ -23,17 +23,17 @@ struct BranchState { class Graph { int BiggestSize_; - int V_; - std::vector layers_; - std::vector arrayV_; - std::vector arrayE_; + int V_; // amount of ids + std::vector layers_; // layers vector with some ids + std::vector arrayV_; // vertices (id -> vertex number) + std::vector arrayE_; // edges (vertex number -> id) std::vector inten_; std::vector outten_; Tensor* outtenres_; int start_; int end_; std::list branch_list_; - std::vector> in_edges_; + std::vector> in_edges_; // next -> prev std::vector>> split_distribution_; int count_used_split_distribution_; #ifdef ENABLE_STATISTIC_TENSORS @@ -67,6 +67,35 @@ class Graph { in_edges_.clear(); } + int getVertexValue(size_t layerID) const { + if (layerID >= arrayV_.size()) { + throw std::invalid_argument("ArrayV does not contain this ID."); + } + return arrayV_[layerID]; + } + + int getEdgeValue(size_t pos) const { + if (pos >= arrayE_.size()) { + throw std::invalid_argument("ArrayE does not contain this."); + } + return arrayE_[pos]; + } + + size_t getInputsSize(size_t layerID) const { + if (layerID >= in_edges_.size()) { + throw std::invalid_argument("Input edges array do not contain this ID."); + } + return in_edges_[layerID].size(); + } + + int getLayersCount() const { return V_; } + const Layer* getLayerFromID(size_t layerID) const { + if (layerID >= layers_.size()) { + throw std::invalid_argument("Layers do not contain this ID."); + } + return layers_[layerID]; + } + void setInput(Layer& lay, Tensor& vec) { lay.setID(0); layers_.push_back(&lay); diff --git a/include/graph_transformations/graph_transformations.hpp b/include/graph_transformations/graph_transformations.hpp new file mode 100644 index 000000000..7bef3874d --- /dev/null +++ b/include/graph_transformations/graph_transformations.hpp @@ -0,0 +1,9 @@ +#include "graph/graph.hpp" +#include "layers/Layer.hpp" +#include + +namespace it_lab_ai { +std::vector find_subgraphs(const Graph& graph, const Graph& subgraph); +bool layer_conditions(const Layer& layer, const Layer& layer_sub); +bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter); +} // namespace it_lab_ai diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 49a64a8b0..ba0d466da 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(graph) +add_subdirectory(graph_transformations) add_subdirectory(perf) add_subdirectory(layers) add_subdirectory(Weights_Reader) \ No newline at end of file diff --git a/src/graph_transformations/CMakeLists.txt b/src/graph_transformations/CMakeLists.txt new file mode 100644 index 000000000..6942b48fb --- /dev/null +++ b/src/graph_transformations/CMakeLists.txt @@ -0,0 +1,3 @@ +file(GLOB_RECURSE graphT_src *.cpp) +add_library(graphT_lib STATIC "${GRAPHT_HEADERS}" "${graphT_src}") +target_link_libraries(graphT_lib PUBLIC TBB_unified) diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp new file mode 100644 index 000000000..8fe074900 --- /dev/null +++ b/src/graph_transformations/graph_transformations.cpp @@ -0,0 +1,71 @@ +#include "graph/graph_transformations.hpp" + +namespace it_lab_ai { + +std::vector find_subgraphs(const Graph& graph, const Graph& subgraph) { + // requirements for subgraph: + // 1 input, 1 output + // requirements for graph: + // can't be connected with subgraph from _outside_, except input and output + std::vector result; + for (int i = 0; i < graph.getLayersCount(); i++) { + bool temp = check_child(graph, subgraph, i, 0); // recursion starts + if (temp) { + result.push_back(i); + } + } + return result; +} + +bool layer_conditions(const Layer& layer, const Layer& layer_sub) { + return layer.getName() == layer_sub.getName(); +} + +bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter) { + int amount_connected1 = + (i < graph.getLayersCount() - 1) + ? (graph.getVertexValue(i + 1) - graph.getVertexValue(i)) + : 0; + int amount_connected2 = + (iter < subgraph.getLayersCount() - 1) + ? (subgraph.getVertexValue(iter + 1) - subgraph.getVertexValue(iter)) + : 0; + if ((amount_connected2 != 0 && amount_connected1 != amount_connected2) || + !layer_conditions(*graph.getLayerFromID(i), + *subgraph.getLayerFromID(iter))) { + return false; + } + if (amount_connected2 != 0) { + using id_name = std::pair; + std::vector orderA; + std::vector orderB; + for (int j = 0; j < amount_connected1; j++) { + orderA.push_back(id_name( + graph.getEdgeValue(graph.getVertexValue(i) + j), + graph.getLayerFromID(graph.getEdgeValue(graph.getVertexValue(i) + j)) + ->getName())); + orderB.push_back(id_name( + subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j), + subgraph + .getLayerFromID( + subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j)) + ->getName())); + } + std::sort(orderA.begin(), orderA.end(), + [&](id_name a1, id_name a2) { return a1.second < a2.second; }); + // ^ interested in LayerType order to prevent any shuffling for childs + for (int j = 0; j < amount_connected1; j++) { + if (graph.getInputsSize(j) != subgraph.getInputsSize(iter)) { + return false; + } + bool temp = + check_child(graph, subgraph, orderA[j].first, orderB[j].second); + if (!temp) { + return false; + } + } + } + return true; +} + +} // namespace it_lab_ai \ No newline at end of file diff --git a/test/benchmarking/test_layers_time.cpp b/test/benchmarking/test_layers_time.cpp index f4923a134..be9115c8c 100644 --- a/test/benchmarking/test_layers_time.cpp +++ b/test/benchmarking/test_layers_time.cpp @@ -17,7 +17,7 @@ void test_func(Layer& p, const Tensor& input, Tensor& output) { } TEST(pooling_test, is_pooling_tbb_ok) { - size_t n = 10; + size_t n = 5; size_t c = 3; size_t h = 224; size_t w = 224; @@ -38,7 +38,7 @@ TEST(pooling_test, is_pooling_tbb_ok) { } TEST(conv_test, is_conv_stl_ok) { - size_t n = 10; + size_t n = 5; size_t c = 3; size_t h = 224; size_t w = 224; diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp index 932db254b..df0b8993e 100644 --- a/test/graph/test_graph.cpp +++ b/test/graph/test_graph.cpp @@ -1,6 +1,7 @@ #include #include "graph/graph.hpp" +#include "graph/graph_transformations.hpp" #include "gtest/gtest.h" #include "layers/EWLayer.hpp" #include "layers/FCLayer.hpp" @@ -116,3 +117,29 @@ TEST(graph, check_connection_when_not_connection2) { ASSERT_EQ(graph.areLayerNext(fcLayer2, fcLayer4), 0); } + +TEST(graph_transformations, check_subgraphs_search) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + Graph subgraph(2); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer, fcLayer4); + graph.setOutput(fcLayer4, output); + + subgraph.setInput(fcLayer, input); + subgraph.makeConnection(fcLayer, fcLayer2); + + ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector(1, 1)); +} From 3593b67f0afb328cb5f525d589b86af0b1038b3f Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Thu, 18 Sep 2025 15:19:47 +0300 Subject: [PATCH 02/11] Changed logic --- include/CMakeLists.txt | 2 +- .../graph_transformations.cpp | 43 +++++-- test/CMakeLists.txt | 2 + test/benchmarking/test_layers_time.cpp | 4 +- test/graph/test_graph.cpp | 116 +++++++++++++++++- 5 files changed, 149 insertions(+), 18 deletions(-) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 1bc48bb39..418c50061 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE graph_headers graph/*.h graph/*.hpp) set(GRAPH_HEADERS "${graph_headers}" PARENT_SCOPE) -file(GLOB_RECURSE graphT_headers graph_transformations/*.h graph_transformation/*.hpp) +file(GLOB_RECURSE graphT_headers graph_transformations/*.h graph_transformations/*.hpp) set(GRAPHT_HEADERS "${graphT_headers}" PARENT_SCOPE) file(GLOB_RECURSE layers_headers layers/*.h layers/*.hpp) diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp index 8fe074900..497ad13df 100644 --- a/src/graph_transformations/graph_transformations.cpp +++ b/src/graph_transformations/graph_transformations.cpp @@ -1,4 +1,4 @@ -#include "graph/graph_transformations.hpp" +#include "graph_transformations/graph_transformations.hpp" namespace it_lab_ai { @@ -21,17 +21,27 @@ bool layer_conditions(const Layer& layer, const Layer& layer_sub) { return layer.getName() == layer_sub.getName(); } +//void erase_inequality_for_first( +// std::vector>& vec1, +// const std::vector>& vec2) { +// for (int i = 0; i < std::min(vec1.size(), vec2.size()); i++) { +// if (vec1[i].second != vec2[i].second) { +// vec1.erase(vec1.begin() + i); +// } +// } +// if (vec1.size() > vec2.size()) { +// vec1.resize(vec2.size()); +// } +//} + bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter) { - int amount_connected1 = - (i < graph.getLayersCount() - 1) - ? (graph.getVertexValue(i + 1) - graph.getVertexValue(i)) - : 0; + int amount_connected1 = graph.getVertexValue(i + 1) - graph.getVertexValue(i); int amount_connected2 = - (iter < subgraph.getLayersCount() - 1) - ? (subgraph.getVertexValue(iter + 1) - subgraph.getVertexValue(iter)) - : 0; - if ((amount_connected2 != 0 && amount_connected1 != amount_connected2) || - !layer_conditions(*graph.getLayerFromID(i), + subgraph.getVertexValue(iter + 1) - subgraph.getVertexValue(iter); + if (amount_connected1 != amount_connected2 && amount_connected2 != 0) { + return false; + } + if (!layer_conditions(*graph.getLayerFromID(i), *subgraph.getLayerFromID(iter))) { return false; } @@ -53,13 +63,20 @@ bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter) { } std::sort(orderA.begin(), orderA.end(), [&](id_name a1, id_name a2) { return a1.second < a2.second; }); + std::sort(orderB.begin(), orderB.end(), + [&](id_name a1, id_name a2) { return a1.second < a2.second; }); // ^ interested in LayerType order to prevent any shuffling for childs + //if (first_inequally) { + // erase_inequality_for_first(orderA, orderB); + //} for (int j = 0; j < amount_connected1; j++) { - if (graph.getInputsSize(j) != subgraph.getInputsSize(iter)) { + int id1 = graph.getEdgeValue(graph.getVertexValue(i) + j); + int id2 = subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j); + if (graph.getInputsSize(id1) != subgraph.getInputsSize(id2)) { return false; } bool temp = - check_child(graph, subgraph, orderA[j].first, orderB[j].second); + check_child(graph, subgraph, orderA[j].first, orderB[j].first); if (!temp) { return false; } @@ -68,4 +85,4 @@ bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter) { return true; } -} // namespace it_lab_ai \ No newline at end of file +} // namespace it_lab_ai diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dc4df1bb7..b766fc03e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,6 +8,8 @@ target_link_libraries(run_test PUBLIC perf_lib layers_lib) target_link_libraries(run_test PUBLIC gtest) target_link_libraries(run_test PUBLIC ReadLib) target_link_libraries(run_test PUBLIC reader_lib) +target_link_libraries(run_test PUBLIC graph_lib) +target_link_libraries(run_test PUBLIC graphT_lib) target_include_directories(run_test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/test/benchmarking/test_layers_time.cpp b/test/benchmarking/test_layers_time.cpp index be9115c8c..9bb33fd48 100644 --- a/test/benchmarking/test_layers_time.cpp +++ b/test/benchmarking/test_layers_time.cpp @@ -17,7 +17,7 @@ void test_func(Layer& p, const Tensor& input, Tensor& output) { } TEST(pooling_test, is_pooling_tbb_ok) { - size_t n = 5; + size_t n = 1; size_t c = 3; size_t h = 224; size_t w = 224; @@ -38,7 +38,7 @@ TEST(pooling_test, is_pooling_tbb_ok) { } TEST(conv_test, is_conv_stl_ok) { - size_t n = 5; + size_t n = 1; size_t c = 3; size_t h = 224; size_t w = 224; diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp index df0b8993e..16344a2d5 100644 --- a/test/graph/test_graph.cpp +++ b/test/graph/test_graph.cpp @@ -1,7 +1,7 @@ #include #include "graph/graph.hpp" -#include "graph/graph_transformations.hpp" +#include "graph_transformations/graph_transformations.hpp" #include "gtest/gtest.h" #include "layers/EWLayer.hpp" #include "layers/FCLayer.hpp" @@ -141,5 +141,117 @@ TEST(graph_transformations, check_subgraphs_search) { subgraph.setInput(fcLayer, input); subgraph.makeConnection(fcLayer, fcLayer2); - ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector(1, 1)); + ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({1})); +} + +TEST(graph_transformations, check_subgraphs_search1) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + Graph subgraph(2); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + FCLayer fcLayer5(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer, fcLayer4); + graph.makeConnection(fcLayer4, fcLayer5); + graph.setOutput(fcLayer5, output); + + subgraph.setInput(fcLayer, input); + subgraph.makeConnection(fcLayer, fcLayer2); + + ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({1, 3})); +} + +TEST(graph_transformations, check_subgraphs_search2) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + Graph subgraph(2); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer3, fcLayer); + graph.makeConnection(fcLayer3, fcLayer4); + graph.setOutput(fcLayer4, output); + + subgraph.setInput(fcLayer, input); + subgraph.makeConnection(fcLayer, fcLayer2); + subgraph.makeConnection(fcLayer2, fcLayer3); + + ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({0})); +} + +TEST(graph_transformations, check_subgraphs_search3) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + Graph subgraph(2); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer3, fcLayer); + graph.makeConnection(fcLayer2, fcLayer4); + graph.setOutput(fcLayer4, output); + + subgraph.setInput(fcLayer, input); + subgraph.makeConnection(fcLayer, fcLayer2); + subgraph.makeConnection(fcLayer2, fcLayer3); + + ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({2})); +} + +TEST(graph_transformations, check_subgraphs_search4) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + Graph subgraph(2); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer3, fcLayer); + graph.makeConnection(fcLayer, fcLayer4); + graph.setOutput(fcLayer4, output); + + subgraph.setInput(fcLayer, input); + subgraph.makeConnection(fcLayer, fcLayer2); + subgraph.makeConnection(fcLayer2, fcLayer3); + + ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({1})); } From 8ad92e8aa97b9f12e36b0804e28115dcd6d1be69 Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Wed, 8 Oct 2025 19:50:42 +0300 Subject: [PATCH 03/11] Changes for ci --- include/graph/graph.hpp | 8 +-- .../graph_transformations.hpp | 5 +- .../graph_transformations.cpp | 57 +++++++++++-------- test/benchmarking/test_layers_time.cpp | 4 +- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/include/graph/graph.hpp b/include/graph/graph.hpp index 252c35b48..be3b09efa 100644 --- a/include/graph/graph.hpp +++ b/include/graph/graph.hpp @@ -23,10 +23,10 @@ struct BranchState { class Graph { int BiggestSize_; - int V_; // amount of ids - std::vector layers_; // layers vector with some ids - std::vector arrayV_; // vertices (id -> vertex number) - std::vector arrayE_; // edges (vertex number -> id) + int V_; // amount of ids + std::vector layers_; // layers vector with some ids + std::vector arrayV_; // vertices (id -> vertex number) + std::vector arrayE_; // edges (vertex number -> id) std::vector inten_; std::vector outten_; Tensor* outtenres_; diff --git a/include/graph_transformations/graph_transformations.hpp b/include/graph_transformations/graph_transformations.hpp index 7bef3874d..12790f3cc 100644 --- a/include/graph_transformations/graph_transformations.hpp +++ b/include/graph_transformations/graph_transformations.hpp @@ -1,9 +1,10 @@ +#include + #include "graph/graph.hpp" #include "layers/Layer.hpp" -#include namespace it_lab_ai { std::vector find_subgraphs(const Graph& graph, const Graph& subgraph); bool layer_conditions(const Layer& layer, const Layer& layer_sub); -bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter); +bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, int recursionDepth); } // namespace it_lab_ai diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp index 497ad13df..c6ab391f6 100644 --- a/src/graph_transformations/graph_transformations.cpp +++ b/src/graph_transformations/graph_transformations.cpp @@ -9,7 +9,7 @@ std::vector find_subgraphs(const Graph& graph, const Graph& subgraph) { // can't be connected with subgraph from _outside_, except input and output std::vector result; for (int i = 0; i < graph.getLayersCount(); i++) { - bool temp = check_child(graph, subgraph, i, 0); // recursion starts + bool temp = check_child(graph, subgraph, i, 0, 0); // recursion starts if (temp) { result.push_back(i); } @@ -21,67 +21,74 @@ bool layer_conditions(const Layer& layer, const Layer& layer_sub) { return layer.getName() == layer_sub.getName(); } -//void erase_inequality_for_first( -// std::vector>& vec1, -// const std::vector>& vec2) { -// for (int i = 0; i < std::min(vec1.size(), vec2.size()); i++) { -// if (vec1[i].second != vec2[i].second) { -// vec1.erase(vec1.begin() + i); -// } -// } -// if (vec1.size() > vec2.size()) { -// vec1.resize(vec2.size()); -// } -//} +// void erase_inequality_for_first( +// std::vector>& vec1, +// const std::vector>& vec2) { +// for (int i = 0; i < std::min(vec1.size(), vec2.size()); i++) { +// if (vec1[i].second != vec2[i].second) { +// vec1.erase(vec1.begin() + i); +// } +// } +// if (vec1.size() > vec2.size()) { +// vec1.resize(vec2.size()); +// } +// } -bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter) { +bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, + int recursionDepth) { int amount_connected1 = graph.getVertexValue(i + 1) - graph.getVertexValue(i); int amount_connected2 = subgraph.getVertexValue(iter + 1) - subgraph.getVertexValue(iter); if (amount_connected1 != amount_connected2 && amount_connected2 != 0) { + std::cerr << "Depth " << recursionDepth << " false by outputs\n"; return false; } if (!layer_conditions(*graph.getLayerFromID(i), *subgraph.getLayerFromID(iter))) { + std::cerr << "Depth " << recursionDepth << " false by layertypes\n"; return false; } if (amount_connected2 != 0) { using id_name = std::pair; - std::vector orderA; - std::vector orderB; + std::vector order_a; + std::vector order_b; for (int j = 0; j < amount_connected1; j++) { - orderA.push_back(id_name( + order_a.emplace_back(id_name( graph.getEdgeValue(graph.getVertexValue(i) + j), graph.getLayerFromID(graph.getEdgeValue(graph.getVertexValue(i) + j)) ->getName())); - orderB.push_back(id_name( + order_b.emplace_back(id_name( subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j), subgraph .getLayerFromID( subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j)) ->getName())); } - std::sort(orderA.begin(), orderA.end(), + std::sort(order_a.begin(), order_a.end(), [&](id_name a1, id_name a2) { return a1.second < a2.second; }); - std::sort(orderB.begin(), orderB.end(), + std::sort(order_b.begin(), order_b.end(), [&](id_name a1, id_name a2) { return a1.second < a2.second; }); // ^ interested in LayerType order to prevent any shuffling for childs - //if (first_inequally) { - // erase_inequality_for_first(orderA, orderB); - //} + // if (first_inequally) { + // erase_inequality_for_first(order_a, order_b); + // } for (int j = 0; j < amount_connected1; j++) { int id1 = graph.getEdgeValue(graph.getVertexValue(i) + j); int id2 = subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j); if (graph.getInputsSize(id1) != subgraph.getInputsSize(id2)) { + std::cerr << "Depth " << recursionDepth << " false by child inputs\n"; return false; } - bool temp = - check_child(graph, subgraph, orderA[j].first, orderB[j].first); + bool temp = check_child(graph, subgraph, order_a[j].first, + order_b[j].first, recursionDepth + 1); if (!temp) { + std::cerr << "Depth " << recursionDepth + << " false by child conditions\n"; return false; } } } + std::cerr << "Depth " << recursionDepth << " true\n"; return true; } diff --git a/test/benchmarking/test_layers_time.cpp b/test/benchmarking/test_layers_time.cpp index 9bb33fd48..f4923a134 100644 --- a/test/benchmarking/test_layers_time.cpp +++ b/test/benchmarking/test_layers_time.cpp @@ -17,7 +17,7 @@ void test_func(Layer& p, const Tensor& input, Tensor& output) { } TEST(pooling_test, is_pooling_tbb_ok) { - size_t n = 1; + size_t n = 10; size_t c = 3; size_t h = 224; size_t w = 224; @@ -38,7 +38,7 @@ TEST(pooling_test, is_pooling_tbb_ok) { } TEST(conv_test, is_conv_stl_ok) { - size_t n = 1; + size_t n = 10; size_t c = 3; size_t h = 224; size_t w = 224; From 05bd229f6c64d4b56cb7839302be9fdff1305172 Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Wed, 8 Oct 2025 20:02:31 +0300 Subject: [PATCH 04/11] Change from const Layer* to const Layer& --- include/graph/graph.hpp | 6 +++--- src/graph_transformations/graph_transformations.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/graph/graph.hpp b/include/graph/graph.hpp index be3b09efa..94a070f80 100644 --- a/include/graph/graph.hpp +++ b/include/graph/graph.hpp @@ -33,7 +33,7 @@ class Graph { int start_; int end_; std::list branch_list_; - std::vector> in_edges_; // next -> prev + std::vector> in_edges_; // next -> prev std::vector>> split_distribution_; int count_used_split_distribution_; #ifdef ENABLE_STATISTIC_TENSORS @@ -89,11 +89,11 @@ class Graph { } int getLayersCount() const { return V_; } - const Layer* getLayerFromID(size_t layerID) const { + const Layer& getLayerFromID(size_t layerID) const { if (layerID >= layers_.size()) { throw std::invalid_argument("Layers do not contain this ID."); } - return layers_[layerID]; + return *layers_[layerID]; } void setInput(Layer& lay, Tensor& vec) { diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp index c6ab391f6..e1b05d386 100644 --- a/src/graph_transformations/graph_transformations.cpp +++ b/src/graph_transformations/graph_transformations.cpp @@ -43,8 +43,8 @@ bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, std::cerr << "Depth " << recursionDepth << " false by outputs\n"; return false; } - if (!layer_conditions(*graph.getLayerFromID(i), - *subgraph.getLayerFromID(iter))) { + if (!layer_conditions(graph.getLayerFromID(i), + subgraph.getLayerFromID(iter))) { std::cerr << "Depth " << recursionDepth << " false by layertypes\n"; return false; } @@ -56,13 +56,13 @@ bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, order_a.emplace_back(id_name( graph.getEdgeValue(graph.getVertexValue(i) + j), graph.getLayerFromID(graph.getEdgeValue(graph.getVertexValue(i) + j)) - ->getName())); + .getName())); order_b.emplace_back(id_name( subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j), subgraph .getLayerFromID( subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j)) - ->getName())); + .getName())); } std::sort(order_a.begin(), order_a.end(), [&](id_name a1, id_name a2) { return a1.second < a2.second; }); From 3aca648fc7cd9a93616b2e589ea73fe03874fa82 Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Wed, 8 Oct 2025 20:14:52 +0300 Subject: [PATCH 05/11] Logs --- include/graph_transformations/graph_transformations.hpp | 3 ++- src/graph_transformations/graph_transformations.cpp | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/graph_transformations/graph_transformations.hpp b/include/graph_transformations/graph_transformations.hpp index 12790f3cc..7cd11cf52 100644 --- a/include/graph_transformations/graph_transformations.hpp +++ b/include/graph_transformations/graph_transformations.hpp @@ -6,5 +6,6 @@ namespace it_lab_ai { std::vector find_subgraphs(const Graph& graph, const Graph& subgraph); bool layer_conditions(const Layer& layer, const Layer& layer_sub); -bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, int recursionDepth); +bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, + int recursionDepth); } // namespace it_lab_ai diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp index e1b05d386..d439fd037 100644 --- a/src/graph_transformations/graph_transformations.cpp +++ b/src/graph_transformations/graph_transformations.cpp @@ -18,6 +18,8 @@ std::vector find_subgraphs(const Graph& graph, const Graph& subgraph) { } bool layer_conditions(const Layer& layer, const Layer& layer_sub) { + std::cerr << "Comparing type " << static_cast(layer.getName()) << " and " + << static_cast(layer_sub.getName()) << std::endl; return layer.getName() == layer_sub.getName(); } From c3b621186937816ce6ad30b5c64477c2743df3fb Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Wed, 8 Oct 2025 21:52:46 +0300 Subject: [PATCH 06/11] New issue with namings --- app/Graph/build.cpp | 7 ----- include/layers/BinaryOpLayer.hpp | 7 +++-- include/layers/ConcatLayer.hpp | 4 +-- include/layers/ConvLayer.hpp | 10 +++++-- include/layers/DropOutLayer.hpp | 4 +-- include/layers/EWLayer.hpp | 8 +++--- include/layers/FCLayer.hpp | 5 ++-- include/layers/FlattenLayer.hpp | 6 ++--- include/layers/InputLayer.hpp | 11 +++++--- include/layers/Layer.hpp | 2 +- include/layers/OutputLayer.hpp | 5 ++-- include/layers/PoolingLayer.hpp | 6 ++--- include/layers/ReduceLayer.hpp | 2 -- include/layers/SplitLayer.hpp | 6 ++--- include/layers/TransposeLayer.hpp | 4 +-- src/layers/ReduceLayer.cpp | 2 +- test/inference/test_inference.cpp | 34 ------------------------ test/single_layer/test_binaryoplayer.cpp | 4 --- test/single_layer/test_dropoutlayer.cpp | 4 --- test/single_layer/test_ewlayer.cpp | 4 --- test/single_layer/test_fclayer.cpp | 4 --- test/single_layer/test_flattenlayer.cpp | 4 --- test/single_layer/test_outputlayer.cpp | 4 --- 23 files changed, 41 insertions(+), 106 deletions(-) diff --git a/app/Graph/build.cpp b/app/Graph/build.cpp index ccd83bb9c..7974db61c 100644 --- a/app/Graph/build.cpp +++ b/app/Graph/build.cpp @@ -73,14 +73,12 @@ void build_graph(it_lab_ai::Tensor& input, it_lab_ai::Tensor& output, it_lab_ai::Tensor tmp_bias = it_lab_ai::make_tensor(tensor.get_bias()); auto conv_layer = std::make_shared( 1, pads, 1, tmp_values, tmp_bias, impl2); - conv_layer->setName(it_lab_ai::kConvolution); layers.push_back(conv_layer); layerpostop.push_back(false); if (comments) std::cout << "ConvLayer added to layers." << std::endl; } if (layer_type.find("relu") != std::string::npos) { auto ew_layer = std::make_shared("relu"); - ew_layer->setName(it_lab_ai::kElementWise); layers.push_back(ew_layer); layerpostop.push_back(true); if (comments) @@ -101,7 +99,6 @@ void build_graph(it_lab_ai::Tensor& input, it_lab_ai::Tensor& output, // tensor = tmp_tensor; auto fc_layer = std::make_shared(tensor, tmp_bias); - fc_layer->setName(it_lab_ai::kFullyConnected); layers.push_back(fc_layer); layerpostop.push_back(false); if (comments) std::cout << "DenseLayer added to layers." << std::endl; @@ -120,7 +117,6 @@ void build_graph(it_lab_ai::Tensor& input, it_lab_ai::Tensor& output, << std::endl; auto pool_layer = std::make_shared(shape, pooltype, impl1); - pool_layer->setName(it_lab_ai::kPooling); layers.push_back(pool_layer); layerpostop.push_back(false); if (comments) std::cout << "PoolingLayer added to layers." << std::endl; @@ -129,7 +125,6 @@ void build_graph(it_lab_ai::Tensor& input, it_lab_ai::Tensor& output, if (layer_type.find("Flatten") != std::string::npos) { auto flatten_layer = std::make_shared( std::vector({0, 3, 2, 1})); - flatten_layer->setName(it_lab_ai::kFlatten); layers.push_back(flatten_layer); layerpostop.push_back(false); if (comments) std::cout << "FlattenLayer added to layers." << std::endl; @@ -137,7 +132,6 @@ void build_graph(it_lab_ai::Tensor& input, it_lab_ai::Tensor& output, if (layer_type.find("Dropout") != std::string::npos) { auto dropout_layer = std::make_shared(0.0); - dropout_layer->setName(it_lab_ai::kDropout); layers.push_back(dropout_layer); layerpostop.push_back(false); if (comments) @@ -151,7 +145,6 @@ void build_graph(it_lab_ai::Tensor& input, it_lab_ai::Tensor& output, std::cout << "number of layers - " << layers.size() + 1 << std::endl; it_lab_ai::Graph graph(static_cast(layers.size())); it_lab_ai::InputLayer a1(it_lab_ai::kNchw, it_lab_ai::kNchw); - a1.setName(it_lab_ai::kInput); if (comments) std::cout << "InputLayer created." << std::endl; diff --git a/include/layers/BinaryOpLayer.hpp b/include/layers/BinaryOpLayer.hpp index bc4683613..10e4298a0 100644 --- a/include/layers/BinaryOpLayer.hpp +++ b/include/layers/BinaryOpLayer.hpp @@ -14,10 +14,9 @@ class BinaryOpLayer : public Layer { public: enum class Operation : uint8_t { kMul, kAdd, kSub, kDiv }; - BinaryOpLayer() = default; - explicit BinaryOpLayer(Operation op) : op_(op) {} + BinaryOpLayer() : Layer(kBinaryOp), op_(Operation::kMul) {} + explicit BinaryOpLayer(Operation op) : op_(op), Layer(kBinaryOp) {} - static std::string get_name() { return "Binary Operation Layer"; } void run(const std::vector& input, std::vector& output) override; static bool is_scalar_tensor(const Tensor& t); @@ -30,7 +29,7 @@ class BinaryOpLayer : public Layer { #endif private: - Operation op_ = Operation::kMul; + Operation op_; template void run_with_scalar_impl(const Tensor& input, ValueType scalar, diff --git a/include/layers/ConcatLayer.hpp b/include/layers/ConcatLayer.hpp index 99d80a673..f669bc406 100644 --- a/include/layers/ConcatLayer.hpp +++ b/include/layers/ConcatLayer.hpp @@ -11,13 +11,11 @@ namespace it_lab_ai { class ConcatLayer : public Layer { public: - explicit ConcatLayer(int64_t axis = 0) : axis_(axis) {} + explicit ConcatLayer(int64_t axis = 0) : axis_(axis), Layer(kConcat) {} void run(const std::vector& input, std::vector& output) override; - static std::string get_name() { return "ConcatLayer"; } - #ifdef ENABLE_STATISTIC_WEIGHTS Tensor get_weights() override { return Tensor(); } #endif diff --git a/include/layers/ConvLayer.hpp b/include/layers/ConvLayer.hpp index 899e0de95..483bc1e60 100644 --- a/include/layers/ConvLayer.hpp +++ b/include/layers/ConvLayer.hpp @@ -18,10 +18,16 @@ class ConvolutionalLayer : public Layer { ImplType implType_; public: - ConvolutionalLayer() = default; + ConvolutionalLayer() : Layer(kConvolution) { + stride_ = 0; + pads_ = 0; + dilations_ = 0; + implType_ = kDefault; + } ConvolutionalLayer(size_t step, size_t pads, size_t dilations, const Tensor& kernel, const Tensor& bias = Tensor(), - ImplType implType = kDefault) { + ImplType implType = kDefault) + : Layer(kConvolution) { stride_ = step; pads_ = pads; dilations_ = dilations; diff --git a/include/layers/DropOutLayer.hpp b/include/layers/DropOutLayer.hpp index 5a76b11e5..42df300f6 100644 --- a/include/layers/DropOutLayer.hpp +++ b/include/layers/DropOutLayer.hpp @@ -10,9 +10,7 @@ class DropOutLayer : public Layer { double drop_rate_; public: - DropOutLayer() = default; - DropOutLayer(double drop_rate) { drop_rate_ = drop_rate; } - static std::string get_name() { return "DropOut layer"; } + DropOutLayer(double drop_rate = 0.0) : Layer(kDropout) { drop_rate_ = drop_rate; } void run(const std::vector& input, std::vector& output) override; #ifdef ENABLE_STATISTIC_WEIGHTS diff --git a/include/layers/EWLayer.hpp b/include/layers/EWLayer.hpp index 83aa3c759..7361689c1 100644 --- a/include/layers/EWLayer.hpp +++ b/include/layers/EWLayer.hpp @@ -19,11 +19,13 @@ T relu(const T& value) { class EWLayer : public Layer { public: - EWLayer() = default; + EWLayer() : Layer(kElementWise), func_("none"), alpha_(0.0F), beta_(0.0F) {} EWLayer(std::string function, float alpha = 0.0F, float beta = 0.0F) - : func_(std::move(function)), alpha_(alpha), beta_(beta) {} + : Layer(kElementWise), + func_(std::move(function)), + alpha_(alpha), + beta_(beta) {} - static std::string get_name() { return "Element-wise layer"; } void run(const std::vector& input, std::vector& output) override; #ifdef ENABLE_STATISTIC_WEIGHTS diff --git a/include/layers/FCLayer.hpp b/include/layers/FCLayer.hpp index ae3e850f9..0e44501f0 100644 --- a/include/layers/FCLayer.hpp +++ b/include/layers/FCLayer.hpp @@ -15,10 +15,9 @@ class FCLayer : public Layer { Tensor bias_; public: - FCLayer() = default; + FCLayer() : Layer(kFullyConnected) {} FCLayer(Tensor weights, const Tensor& bias) - : weights_(std::move(weights)), bias_(bias) {} - static std::string get_name() { return "Fully-connected layer"; } + : Layer(kFullyConnected), weights_(std::move(weights)), bias_(bias) {} void run(const std::vector& input, std::vector& output) override; #ifdef ENABLE_STATISTIC_WEIGHTS diff --git a/include/layers/FlattenLayer.hpp b/include/layers/FlattenLayer.hpp index ad3c47e2c..ae475203b 100644 --- a/include/layers/FlattenLayer.hpp +++ b/include/layers/FlattenLayer.hpp @@ -13,9 +13,9 @@ class FlattenLayer : public Layer { std::vector order_; public: - FlattenLayer() : order_({0, 1, 2, 3}) {} - FlattenLayer(const std::vector& order) : order_(order) {} - static std::string get_name() { return "Flatten layer"; } + FlattenLayer() : Layer(kFlatten), order_({0, 1, 2, 3}) {} + FlattenLayer(const std::vector& order) + : Layer(kFlatten), order_(order) {} void run(const std::vector& input, std::vector& output) override; #ifdef ENABLE_STATISTIC_WEIGHTS diff --git a/include/layers/InputLayer.hpp b/include/layers/InputLayer.hpp index 4fa0f968a..0bbd36ec2 100644 --- a/include/layers/InputLayer.hpp +++ b/include/layers/InputLayer.hpp @@ -19,9 +19,14 @@ class InputLayer : public Layer { int std_; public: - InputLayer() = default; - InputLayer(LayInOut layin, LayInOut layout, int mean = 0, int std = 1) { - type_ = LayerType::kInput; + InputLayer() : Layer(kInput) { + layin_ = kNchw; + layout_ = kNchw; + mean_ = 0; + std_ = 1; + } + InputLayer(LayInOut layin, LayInOut layout, int mean = 0, int std = 1) + : Layer(kInput) { layin_ = layin; layout_ = layout; mean_ = mean; diff --git a/include/layers/Layer.hpp b/include/layers/Layer.hpp index dd2eaff99..f3b7c6f99 100644 --- a/include/layers/Layer.hpp +++ b/include/layers/Layer.hpp @@ -40,12 +40,12 @@ struct PostOperations { class Layer { public: Layer() = default; + Layer(LayerType type) : type_(type) {} virtual ~Layer() = default; PostOperations postops; int getID() const { return id_; } void setID(int id) { id_ = id; } LayerType getName() const { return type_; } - void setName(LayerType type) { type_ = type; } virtual void run(const std::vector& input, std::vector& output) = 0; #ifdef ENABLE_STATISTIC_WEIGHTS diff --git a/include/layers/OutputLayer.hpp b/include/layers/OutputLayer.hpp index 3849d1bdc..b00f063c9 100644 --- a/include/layers/OutputLayer.hpp +++ b/include/layers/OutputLayer.hpp @@ -11,9 +11,8 @@ namespace it_lab_ai { class OutputLayer : public Layer { public: - OutputLayer() = default; - OutputLayer(const std::vector& labels) : labels_(labels) {} - static std::string get_name() { return "Output layer"; } + OutputLayer() : Layer(kOutput) {} + OutputLayer(const std::vector& labels) : Layer(kOutput), labels_(labels) {} void run(const std::vector& input, std::vector& output) override { output = input; diff --git a/include/layers/PoolingLayer.hpp b/include/layers/PoolingLayer.hpp index 253f0b5de..aef42281c 100644 --- a/include/layers/PoolingLayer.hpp +++ b/include/layers/PoolingLayer.hpp @@ -12,13 +12,13 @@ enum PoolingType : uint8_t { kAverage, kMax }; class PoolingLayer : public Layer { public: - PoolingLayer() = default; + PoolingLayer() : Layer(kPooling), implType_(kDefault) {} PoolingLayer(const Shape& pooling_shape, std::string pooling_type = "average", ImplType implType = kDefault) - : poolingShape_(pooling_shape), + : Layer(kPooling), + poolingShape_(pooling_shape), poolingType_(std::move(pooling_type)), implType_(implType) {} - static std::string get_name() { return "Pooling layer"; } void run(const std::vector& input, std::vector& output) override; #ifdef ENABLE_STATISTIC_WEIGHTS diff --git a/include/layers/ReduceLayer.hpp b/include/layers/ReduceLayer.hpp index c05e4d2d9..b9efee72d 100644 --- a/include/layers/ReduceLayer.hpp +++ b/include/layers/ReduceLayer.hpp @@ -19,8 +19,6 @@ class ReduceLayer : public Layer { void run(const std::vector& input, std::vector& output) override; - static std::string get_name() { return "ReduceLayer"; } - #ifdef ENABLE_STATISTIC_WEIGHTS Tensor get_weights() override { return Tensor(); } #endif diff --git a/include/layers/SplitLayer.hpp b/include/layers/SplitLayer.hpp index 2eb0cb5a1..ac21c9572 100644 --- a/include/layers/SplitLayer.hpp +++ b/include/layers/SplitLayer.hpp @@ -11,15 +11,13 @@ namespace it_lab_ai { class SplitLayer : public Layer { public: SplitLayer(int axis, std::vector splits) - : axis_(axis), splits_(std::move(splits)) {} + : Layer(kSplit), axis_(axis), splits_(std::move(splits)) {} SplitLayer(int axis, int num_outputs) - : axis_(axis), num_outputs_(num_outputs) {} + : Layer(kSplit), axis_(axis), num_outputs_(num_outputs) {} void run(const std::vector& input, std::vector& output) override; - static std::string get_name() { return "SplitLayer"; } - #ifdef ENABLE_STATISTIC_WEIGHTS Tensor get_weights() override { return Tensor(); } #endif diff --git a/include/layers/TransposeLayer.hpp b/include/layers/TransposeLayer.hpp index 4e0630ec3..5372ac816 100644 --- a/include/layers/TransposeLayer.hpp +++ b/include/layers/TransposeLayer.hpp @@ -9,7 +9,7 @@ namespace it_lab_ai { class TransposeLayer : public Layer { public: explicit TransposeLayer(std::vector perm = {}) - : perm_(std::move(perm)) {} + : Layer(kTranspose), perm_(std::move(perm)) {} void run(const std::vector& input, std::vector& output) override; @@ -18,8 +18,6 @@ class TransposeLayer : public Layer { Tensor get_weights() override { return Tensor(); } #endif - static std::string get_name() { return "TransposeLayer"; } - private: std::vector perm_; diff --git a/src/layers/ReduceLayer.cpp b/src/layers/ReduceLayer.cpp index 1c9a87c84..766c1a296 100644 --- a/src/layers/ReduceLayer.cpp +++ b/src/layers/ReduceLayer.cpp @@ -7,7 +7,7 @@ namespace it_lab_ai { ReduceLayer::ReduceLayer(Operation op, int64_t keepdims, const Tensor& axes) - : op_(op), keepdims_(keepdims), axes_(axes) {} + : Layer(kReduce), op_(op), keepdims_(keepdims), axes_(axes) {} void ReduceLayer::normalize_axes(const Shape& input_shape, std::vector& axes) { diff --git a/test/inference/test_inference.cpp b/test/inference/test_inference.cpp index 3250afa98..f1f862bd3 100644 --- a/test/inference/test_inference.cpp +++ b/test/inference/test_inference.cpp @@ -27,7 +27,6 @@ TEST(bfs, check_struct_graph) { Tensor input = make_tensor(vec, sh1); Tensor output = make_tensor(vec, sh1); InputLayer a1(kNhwc, kNchw, 1, 2); - a1.setName(kInput); std::vector kernelvec = {1, 1, 1, 1, 1, 1, 1, 1, 1}; Shape sh2({3, 3}); Tensor kernel = make_tensor(kernelvec, sh2); @@ -47,7 +46,6 @@ TEST(bfs, check_struct_graph) { ConcatLayer a7(0); // EWLayer a8("relu"); SplitLayer a8(1, 3); - a8.setName(kSplit); EWLayer a9_1("relu"); EWLayer a9_2("relu"); @@ -58,11 +56,6 @@ TEST(bfs, check_struct_graph) { ConcatLayer a12(0); - a2.setName(kConvolution); - a3_1.setName(kConvolution); - a3_2.setName(kConvolution); - a4.setName(kConcat); - graph.setInput(a1, input); graph.makeConnection(a1, a2); graph.makeConnection(a2, a3_1); @@ -125,11 +118,6 @@ TEST(bfs, check_struct_graph_not_used_yolo) { ConcatLayer a4(0); - a2.setName(kSplit); - a3_1.setName(kConvolution); - a3_2.setName(kConvolution); - a4.setName(kConcat); - graph.setInput(a2, input); graph.makeConnection(a2, a3_1); graph.makeConnection(a2, a3_2); @@ -177,8 +165,6 @@ TEST(bfs, check_struct_graph_resnet1) { BinaryOpLayer a3(BinaryOpLayer::Operation::kAdd); EWLayer a4("relu"); - a2.setName(kSplit); - graph.setInput(a2, input); graph.makeConnection(a2, a2_1); graph.makeConnection(a2, a2_2); @@ -222,8 +208,6 @@ TEST(bfs, check_struct_graph_resnet2) { BinaryOpLayer a3(BinaryOpLayer::Operation::kAdd); EWLayer a4("relu"); - a2.setName(kSplit); - graph.setInput(a2, input); graph.makeConnection(a2, a2_1); graph.makeConnection(a2_1, a2_1_1); @@ -298,15 +282,11 @@ TEST(bfs, check_result_vec) { Tensor output = make_tensor(vec, sh1); InputLayer a1(kNhwc, kNchw, 1, 2); InputLayer a3(kNhwc, kNhwc, 1, 1); - a1.setName(kInput); - a3.setName(kInput); std::vector kernelvec = {1, 1, 1, 1, 1, 1, 1, 1, 1}; Shape sh2({3, 3}); Tensor kernel = make_tensor(kernelvec, sh2); ConvolutionalLayer a2(1, 0, 1, kernel); ConvolutionalLayer a4(1, 0, 1, kernel); - a2.setName(kConvolution); - a4.setName(kConvolution); graph.setInput(a1, input); graph.makeConnection(a1, a2); graph.makeConnection(a2, a4); @@ -432,7 +412,6 @@ TEST(bfs, check_struct_layer) { Tensor input = make_tensor(vec, sh1); Tensor output = make_tensor(vec, sh1); InputLayer a1(kNhwc, kNchw, 1, 2); - a1.setName(kInput); std::vector kernelvec = {1, 1, 1, 1, 1, 1, 1, 1, 1}; Shape sh2({3, 3}); Tensor kernel = make_tensor(kernelvec, sh2); @@ -442,9 +421,6 @@ TEST(bfs, check_struct_layer) { // EWLayer a4("linear", 2.0F, 3.0F); // a2.ewops.layers.push_back(&a4); // a2.ewops.countlayers++; - - a2.setName(kConvolution); - a3.setName(kConvolution); graph.setInput(a1, input); graph.makeConnection(a1, a2); graph.makeConnection(a2, a3); @@ -465,7 +441,6 @@ TEST(bfs, check_struct_layer_added) { Tensor input = make_tensor(vec, sh1); Tensor output = make_tensor(vec, sh1); InputLayer a1(kNhwc, kNchw, 1, 2); - a1.setName(kInput); std::vector kernelvec = {1, 1, 1, 1, 1, 1, 1, 1, 1}; Shape sh2({3, 3}); Tensor kernel = make_tensor(kernelvec, sh2); @@ -476,8 +451,6 @@ TEST(bfs, check_struct_layer_added) { a2.postops.layers.push_back(&a4); a2.postops.count++; - a2.setName(kConvolution); - a3.setName(kConvolution); graph.setInput(a1, input); graph.makeConnection(a1, a2); graph.makeConnection(a2, a3); @@ -501,7 +474,6 @@ FLAKY_TEST(bfs, check_struct_graph_split) { Tensor input = make_tensor(vec, sh1); Tensor output = make_tensor(vec, sh1); InputLayer a1(kNhwc, kNchw, 1, 2); - a1.setName(kInput); std::vector kernelvec = {1, 1, 1, 1, 1, 1, 1, 1, 1}; Shape sh2({3, 3}); Tensor kernel = make_tensor(kernelvec, sh2); @@ -521,7 +493,6 @@ FLAKY_TEST(bfs, check_struct_graph_split) { ConcatLayer a7(0); // EWLayer a8("relu"); SplitLayer a8(1, 3); - a8.setName(kSplit); EWLayer a9_1("relu"); EWLayer a9_2("relu"); @@ -532,11 +503,6 @@ FLAKY_TEST(bfs, check_struct_graph_split) { ConcatLayer a12(0); - a2.setName(kConvolution); - a3_1.setName(kConvolution); - a3_2.setName(kConvolution); - a4.setName(kConcat); - graph.setInput(a1, input); graph.makeConnection(a1, a2); graph.makeConnection(a2, a3_1); diff --git a/test/single_layer/test_binaryoplayer.cpp b/test/single_layer/test_binaryoplayer.cpp index 07160abb3..16f2852d2 100644 --- a/test/single_layer/test_binaryoplayer.cpp +++ b/test/single_layer/test_binaryoplayer.cpp @@ -173,10 +173,6 @@ TEST_F(BinaryOpLayerTests, IncompatibleShapes) { EXPECT_THROW(layer.run(in, output), std::runtime_error); } -TEST_F(BinaryOpLayerTests, LayerName) { - EXPECT_EQ(BinaryOpLayer::get_name(), "Binary Operation Layer"); -} - TEST_F(BinaryOpLayerTests, EmptyTensors) { BinaryOpLayer layer(BinaryOpLayer::Operation::kMul); Tensor empty1({}, Type::kFloat); diff --git a/test/single_layer/test_dropoutlayer.cpp b/test/single_layer/test_dropoutlayer.cpp index f6007081d..f8ce1cce2 100644 --- a/test/single_layer/test_dropoutlayer.cpp +++ b/test/single_layer/test_dropoutlayer.cpp @@ -84,7 +84,3 @@ TEST(DropOutLayer, dropoutlayer_float_70proc) { std::vector vec = *out[0].as(); EXPECT_NEAR(std::accumulate(vec.begin(), vec.end(), 0.0F), 0.3, 0.2); } - -TEST(DropOutLayer, get_layer_name) { - EXPECT_EQ(DropOutLayer::get_name(), "DropOut layer"); -} diff --git a/test/single_layer/test_ewlayer.cpp b/test/single_layer/test_ewlayer.cpp index ba9e42a46..5015b8c0e 100644 --- a/test/single_layer/test_ewlayer.cpp +++ b/test/single_layer/test_ewlayer.cpp @@ -133,10 +133,6 @@ TEST(ewlayer, new_ewlayer_throws_with_invalid_function) { ASSERT_ANY_THROW(layer.run(in, out)); } -TEST(ewlayer, get_layer_name) { - EXPECT_EQ(EWLayer::get_name(), "Element-wise layer"); -} - TEST(ewlayer, new_ewlayer_can_sigmoid_float) { EWLayer layer("sigmoid"); Tensor input = make_tensor({0.0F, -1.0F, 1.0F, 2.0F}); diff --git a/test/single_layer/test_fclayer.cpp b/test/single_layer/test_fclayer.cpp index b83ea3cea..e4036fba1 100644 --- a/test/single_layer/test_fclayer.cpp +++ b/test/single_layer/test_fclayer.cpp @@ -216,7 +216,3 @@ TEST(fclayer, new_fc_layer_throws_with_incorrect_input_type) { std::vector out{output}; ASSERT_ANY_THROW(layer.run(in, out)); } - -TEST(fclayer, get_layer_name) { - EXPECT_EQ(FCLayer::get_name(), "Fully-connected layer"); -} diff --git a/test/single_layer/test_flattenlayer.cpp b/test/single_layer/test_flattenlayer.cpp index ddce024b7..07bae484a 100644 --- a/test/single_layer/test_flattenlayer.cpp +++ b/test/single_layer/test_flattenlayer.cpp @@ -83,7 +83,3 @@ TEST(flattenlayer, new_flattenlayer_can_flatten_int_reorder) { layer3.run(in, out); EXPECT_EQ(*out[0].as(), expected_3); } - -TEST(flattenlayer, get_layer_name) { - EXPECT_EQ(FlattenLayer::get_name(), "Flatten layer"); -} diff --git a/test/single_layer/test_outputlayer.cpp b/test/single_layer/test_outputlayer.cpp index 2be69a299..daf738396 100644 --- a/test/single_layer/test_outputlayer.cpp +++ b/test/single_layer/test_outputlayer.cpp @@ -144,10 +144,6 @@ TEST(OutputLayer, topk_throws_when_too_big_k) { ASSERT_ANY_THROW(auto topk1 = layer.top_k(input_tensor, k)); } -TEST(OutputLayer, get_layer_name) { - EXPECT_EQ(OutputLayer::get_name(), "Output layer"); -} - TEST(OutputLayer, softmax_works) { std::vector input = {1.0, 2.5, 4.0, 5.5}; std::vector converted_input = {0.008657, 0.038774, 0.173774, From 522b8eee15e1d7acd197f9190c2cef2698e615ea Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Wed, 8 Oct 2025 22:01:43 +0300 Subject: [PATCH 07/11] New issue with namings --- include/layers/BinaryOpLayer.hpp | 2 +- include/layers/ConcatLayer.hpp | 2 +- include/layers/DropOutLayer.hpp | 4 +++- include/layers/OutputLayer.hpp | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/layers/BinaryOpLayer.hpp b/include/layers/BinaryOpLayer.hpp index 10e4298a0..06bed60cf 100644 --- a/include/layers/BinaryOpLayer.hpp +++ b/include/layers/BinaryOpLayer.hpp @@ -15,7 +15,7 @@ class BinaryOpLayer : public Layer { enum class Operation : uint8_t { kMul, kAdd, kSub, kDiv }; BinaryOpLayer() : Layer(kBinaryOp), op_(Operation::kMul) {} - explicit BinaryOpLayer(Operation op) : op_(op), Layer(kBinaryOp) {} + explicit BinaryOpLayer(Operation op) : Layer(kBinaryOp), op_(op) {} void run(const std::vector& input, std::vector& output) override; diff --git a/include/layers/ConcatLayer.hpp b/include/layers/ConcatLayer.hpp index f669bc406..f21ec823e 100644 --- a/include/layers/ConcatLayer.hpp +++ b/include/layers/ConcatLayer.hpp @@ -11,7 +11,7 @@ namespace it_lab_ai { class ConcatLayer : public Layer { public: - explicit ConcatLayer(int64_t axis = 0) : axis_(axis), Layer(kConcat) {} + explicit ConcatLayer(int64_t axis = 0) : Layer(kConcat), axis_(axis) {} void run(const std::vector& input, std::vector& output) override; diff --git a/include/layers/DropOutLayer.hpp b/include/layers/DropOutLayer.hpp index 42df300f6..c5b891ed0 100644 --- a/include/layers/DropOutLayer.hpp +++ b/include/layers/DropOutLayer.hpp @@ -10,7 +10,9 @@ class DropOutLayer : public Layer { double drop_rate_; public: - DropOutLayer(double drop_rate = 0.0) : Layer(kDropout) { drop_rate_ = drop_rate; } + DropOutLayer(double drop_rate = 0.0) : Layer(kDropout) { + drop_rate_ = drop_rate; + } void run(const std::vector& input, std::vector& output) override; #ifdef ENABLE_STATISTIC_WEIGHTS diff --git a/include/layers/OutputLayer.hpp b/include/layers/OutputLayer.hpp index b00f063c9..20be5be05 100644 --- a/include/layers/OutputLayer.hpp +++ b/include/layers/OutputLayer.hpp @@ -12,7 +12,8 @@ namespace it_lab_ai { class OutputLayer : public Layer { public: OutputLayer() : Layer(kOutput) {} - OutputLayer(const std::vector& labels) : Layer(kOutput), labels_(labels) {} + OutputLayer(const std::vector& labels) + : Layer(kOutput), labels_(labels) {} void run(const std::vector& input, std::vector& output) override { output = input; From 5d6f2667044addc65e7812e2ed7be696fa3cbb23 Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Wed, 8 Oct 2025 23:24:24 +0300 Subject: [PATCH 08/11] Add some tests --- .../graph_transformations.cpp | 8 +- test/graph/test_graph.cpp | 84 +++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp index d439fd037..f355f0b80 100644 --- a/src/graph_transformations/graph_transformations.cpp +++ b/src/graph_transformations/graph_transformations.cpp @@ -55,16 +55,16 @@ bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, std::vector order_a; std::vector order_b; for (int j = 0; j < amount_connected1; j++) { - order_a.emplace_back(id_name( + order_a.emplace_back( graph.getEdgeValue(graph.getVertexValue(i) + j), graph.getLayerFromID(graph.getEdgeValue(graph.getVertexValue(i) + j)) - .getName())); - order_b.emplace_back(id_name( + .getName()); + order_b.emplace_back( subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j), subgraph .getLayerFromID( subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j)) - .getName())); + .getName()); } std::sort(order_a.begin(), order_a.end(), [&](id_name a1, id_name a2) { return a1.second < a2.second; }); diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp index 16344a2d5..9e4bf8181 100644 --- a/test/graph/test_graph.cpp +++ b/test/graph/test_graph.cpp @@ -118,6 +118,90 @@ TEST(graph, check_connection_when_not_connection2) { ASSERT_EQ(graph.areLayerNext(fcLayer2, fcLayer4), 0); } +TEST(graph, vertex_out_of_range) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer, fcLayer4); + graph.setOutput(fcLayer4, output); + ASSERT_ANY_THROW(graph.getVertexValue(5)); +} + +TEST(graph, edges_out_of_range) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer, fcLayer4); + graph.setOutput(fcLayer4, output); + ASSERT_ANY_THROW(graph.getEdgeValue(999)); +} + +TEST(graph, inputs_out_of_range) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer, fcLayer4); + graph.setOutput(fcLayer4, output); + ASSERT_ANY_THROW(graph.getInputsSize(999)); +} + +TEST(graph, get_layer_out_of_range) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer, fcLayer4); + graph.setOutput(fcLayer4, output); + ASSERT_ANY_THROW(graph.getLayerFromID(999)); +} + TEST(graph_transformations, check_subgraphs_search) { const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; Tensor weights = make_tensor(vec1, {3, 2}); From 4c0f5b2ac3402130daca8e039e173516f91e1b7b Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Mon, 13 Oct 2025 01:34:55 +0300 Subject: [PATCH 09/11] New implementation --- include/graph/graph.hpp | 23 +++ .../graph_transformations.hpp | 13 +- .../graph_transformations.cpp | 154 +++++++++--------- test/graph/test_graph.cpp | 108 ++++++++++-- 4 files changed, 207 insertions(+), 91 deletions(-) diff --git a/include/graph/graph.hpp b/include/graph/graph.hpp index 94a070f80..e50b5b0e5 100644 --- a/include/graph/graph.hpp +++ b/include/graph/graph.hpp @@ -105,6 +105,29 @@ class Graph { V_++; in_edges_.resize(1); } + + void addSingleLayer(Layer& lay) { + bool layer_exists = false; + for (const auto* layer : layers_) { + if (layer == &lay) { + layer_exists = true; + break; + } + } + + if (!layer_exists) { + lay.setID(V_); + layers_.push_back(&lay); + arrayV_.push_back(static_cast(arrayE_.size())); + + if (V_ >= static_cast(in_edges_.size())) { + in_edges_.resize(V_ + 1); + } + + V_++; + } + } + void makeConnection(const Layer& layPrev, Layer& layNext) { bool layer_exists = false; for (const auto* layer : layers_) { diff --git a/include/graph_transformations/graph_transformations.hpp b/include/graph_transformations/graph_transformations.hpp index 7cd11cf52..0ff658a3e 100644 --- a/include/graph_transformations/graph_transformations.hpp +++ b/include/graph_transformations/graph_transformations.hpp @@ -1,11 +1,16 @@ +#include #include #include "graph/graph.hpp" #include "layers/Layer.hpp" namespace it_lab_ai { -std::vector find_subgraphs(const Graph& graph, const Graph& subgraph); -bool layer_conditions(const Layer& layer, const Layer& layer_sub); -bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, - int recursionDepth); +std::vector> find_subgraphs(const Graph& graph, + const Graph& subgraph); +bool has_edge(const Graph& graph, int id_from, int id_to); +bool is_root(const Graph& graph, int id); +bool is_leaf(const Graph& graph, int id); +bool run_search(const Graph& graph, const Graph& subgraph, + std::vector& assignments, + std::vector>& results); } // namespace it_lab_ai diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp index f355f0b80..34874a66b 100644 --- a/src/graph_transformations/graph_transformations.cpp +++ b/src/graph_transformations/graph_transformations.cpp @@ -2,96 +2,98 @@ namespace it_lab_ai { -std::vector find_subgraphs(const Graph& graph, const Graph& subgraph) { +bool layer_conditions(const Layer& layer, const Layer& layer_sub) { + return layer.getName() == layer_sub.getName(); +} + +std::vector> find_subgraphs(const Graph& graph, + const Graph& subgraph) { // requirements for subgraph: - // 1 input, 1 output + // one or multiple inputs, one or multiple outputs // requirements for graph: - // can't be connected with subgraph from _outside_, except input and output - std::vector result; - for (int i = 0; i < graph.getLayersCount(); i++) { - bool temp = check_child(graph, subgraph, i, 0, 0); // recursion starts - if (temp) { - result.push_back(i); + // can't be connected from outside, except IO for input and O for output + std::vector assignments; // cur assumption for graph + std::vector> results; + run_search(graph, subgraph, assignments, results); + return results; +} + +bool has_edge(const Graph& graph, int id_from, int id_to) { + for (int i = graph.getVertexValue(id_from); + i < graph.getVertexValue(id_from + 1); i++) { + if (graph.getEdgeValue(i) == id_to) { + return true; } } - return result; + return false; } -bool layer_conditions(const Layer& layer, const Layer& layer_sub) { - std::cerr << "Comparing type " << static_cast(layer.getName()) << " and " - << static_cast(layer_sub.getName()) << std::endl; - return layer.getName() == layer_sub.getName(); +bool is_root(const Graph& graph, int id) { + return graph.getInputsSize(id) == 0; } -// void erase_inequality_for_first( -// std::vector>& vec1, -// const std::vector>& vec2) { -// for (int i = 0; i < std::min(vec1.size(), vec2.size()); i++) { -// if (vec1[i].second != vec2[i].second) { -// vec1.erase(vec1.begin() + i); -// } -// } -// if (vec1.size() > vec2.size()) { -// vec1.resize(vec2.size()); -// } -// } +bool is_leaf(const Graph& graph, int id) { + return graph.getVertexValue(id + 1) - graph.getVertexValue(id) == 0; +} -bool check_child(const Graph& graph, const Graph& subgraph, int i, int iter, - int recursionDepth) { - int amount_connected1 = graph.getVertexValue(i + 1) - graph.getVertexValue(i); - int amount_connected2 = - subgraph.getVertexValue(iter + 1) - subgraph.getVertexValue(iter); - if (amount_connected1 != amount_connected2 && amount_connected2 != 0) { - std::cerr << "Depth " << recursionDepth << " false by outputs\n"; - return false; +bool run_search(const Graph& graph, const Graph& subgraph, + std::vector& assignments, + std::vector>& results) { + size_t cur_size = assignments.size(); + for (int prev_id = 0; prev_id < subgraph.getLayersCount(); prev_id++) { + size_t amount_connected_s = + subgraph.getVertexValue(prev_id + 1) - subgraph.getVertexValue(prev_id); + for (int j = 0; j < amount_connected_s; j++) { + int next_id = subgraph.getEdgeValue(subgraph.getVertexValue(prev_id) + j); + if (prev_id < cur_size && next_id < cur_size) { + if (!has_edge(graph, assignments[prev_id], assignments[next_id])) { + return false; + } + std::vector ids = {prev_id, next_id}; + for (int k = 0; k < 2; k++) { + if (!layer_conditions(subgraph.getLayerFromID(ids[k]), + graph.getLayerFromID(assignments[ids[k]]))) { + return false; + } + // input node shouldn't be checked for it's inputs + if (!is_root(subgraph, ids[k]) && + subgraph.getInputsSize(ids[k]) != + graph.getInputsSize(assignments[ids[k]])) { + return false; + } + // input & output node shouldn't be checked for it's outputs + if (!is_leaf(subgraph, ids[k]) && !is_root(subgraph, ids[k])) { + size_t amount_connected_s1 = subgraph.getVertexValue(ids[k] + 1) - + subgraph.getVertexValue(ids[k]); + size_t amount_connected_1 = + graph.getVertexValue(assignments[ids[k]] + 1) - + graph.getVertexValue(assignments[ids[k]]); + if (amount_connected_1 != amount_connected_s1) { + return false; + } + } + } + } + } } - if (!layer_conditions(graph.getLayerFromID(i), - subgraph.getLayerFromID(iter))) { - std::cerr << "Depth " << recursionDepth << " false by layertypes\n"; - return false; + + // assumption is good -> return true + if (cur_size == subgraph.getLayersCount()) { + return true; } - if (amount_connected2 != 0) { - using id_name = std::pair; - std::vector order_a; - std::vector order_b; - for (int j = 0; j < amount_connected1; j++) { - order_a.emplace_back( - graph.getEdgeValue(graph.getVertexValue(i) + j), - graph.getLayerFromID(graph.getEdgeValue(graph.getVertexValue(i) + j)) - .getName()); - order_b.emplace_back( - subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j), - subgraph - .getLayerFromID( - subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j)) - .getName()); - } - std::sort(order_a.begin(), order_a.end(), - [&](id_name a1, id_name a2) { return a1.second < a2.second; }); - std::sort(order_b.begin(), order_b.end(), - [&](id_name a1, id_name a2) { return a1.second < a2.second; }); - // ^ interested in LayerType order to prevent any shuffling for childs - // if (first_inequally) { - // erase_inequality_for_first(order_a, order_b); - // } - for (int j = 0; j < amount_connected1; j++) { - int id1 = graph.getEdgeValue(graph.getVertexValue(i) + j); - int id2 = subgraph.getEdgeValue(subgraph.getVertexValue(iter) + j); - if (graph.getInputsSize(id1) != subgraph.getInputsSize(id2)) { - std::cerr << "Depth " << recursionDepth << " false by child inputs\n"; - return false; - } - bool temp = check_child(graph, subgraph, order_a[j].first, - order_b[j].first, recursionDepth + 1); - if (!temp) { - std::cerr << "Depth " << recursionDepth - << " false by child conditions\n"; - return false; + + // add new nodes for assumption and try recursion + for (int id = 0; id < graph.getLayersCount(); id++) { + auto it = std::find(assignments.begin(), assignments.end(), id); + if (it == assignments.end()) { + assignments.push_back(id); + if (run_search(graph, subgraph, assignments, results)) { + results.emplace_back(assignments); } + assignments.pop_back(); } } - std::cerr << "Depth " << recursionDepth << " true\n"; - return true; + return false; } } // namespace it_lab_ai diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp index 9e4bf8181..653891137 100644 --- a/test/graph/test_graph.cpp +++ b/test/graph/test_graph.cpp @@ -1,3 +1,5 @@ +#include +#include #include #include "graph/graph.hpp" @@ -6,6 +8,7 @@ #include "layers/EWLayer.hpp" #include "layers/FCLayer.hpp" #include "layers/InputLayer.hpp" +#include "perf/benchmarking.hpp" using namespace it_lab_ai; @@ -224,8 +227,9 @@ TEST(graph_transformations, check_subgraphs_search) { subgraph.setInput(fcLayer, input); subgraph.makeConnection(fcLayer, fcLayer2); - - ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({1})); + auto res = find_subgraphs(graph, subgraph); + auto it = std::find(res.begin(), res.end(), std::vector({1, 2})); + ASSERT_NE(it, res.end()); } TEST(graph_transformations, check_subgraphs_search1) { @@ -241,19 +245,20 @@ TEST(graph_transformations, check_subgraphs_search1) { FCLayer fcLayer2(weights, bias); FCLayer fcLayer3(weights, bias); FCLayer fcLayer4(weights, bias); - FCLayer fcLayer5(weights, bias); + EWLayer ewLayer5("relu"); graph.setInput(fcLayer, input); graph.makeConnection(fcLayer, fcLayer2); graph.makeConnection(fcLayer2, fcLayer3); graph.makeConnection(fcLayer, fcLayer4); - graph.makeConnection(fcLayer4, fcLayer5); - graph.setOutput(fcLayer5, output); + graph.makeConnection(fcLayer4, ewLayer5); + graph.setOutput(ewLayer5, output); subgraph.setInput(fcLayer, input); - subgraph.makeConnection(fcLayer, fcLayer2); - - ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({1, 3})); + subgraph.makeConnection(fcLayer, ewLayer5); + auto res = find_subgraphs(graph, subgraph); + auto it = std::find(res.begin(), res.end(), std::vector({3, 4})); + ASSERT_NE(it, res.end()); } TEST(graph_transformations, check_subgraphs_search2) { @@ -281,7 +286,9 @@ TEST(graph_transformations, check_subgraphs_search2) { subgraph.makeConnection(fcLayer, fcLayer2); subgraph.makeConnection(fcLayer2, fcLayer3); - ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({0})); + auto res = find_subgraphs(graph, subgraph); + auto it = std::find(res.begin(), res.end(), std::vector({0, 1, 2})); + ASSERT_NE(it, res.end()); } TEST(graph_transformations, check_subgraphs_search3) { @@ -309,7 +316,9 @@ TEST(graph_transformations, check_subgraphs_search3) { subgraph.makeConnection(fcLayer, fcLayer2); subgraph.makeConnection(fcLayer2, fcLayer3); - ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({2})); + auto res = find_subgraphs(graph, subgraph); + auto it = std::find(res.begin(), res.end(), std::vector({2, 0, 1})); + ASSERT_NE(it, res.end()); } TEST(graph_transformations, check_subgraphs_search4) { @@ -337,5 +346,82 @@ TEST(graph_transformations, check_subgraphs_search4) { subgraph.makeConnection(fcLayer, fcLayer2); subgraph.makeConnection(fcLayer2, fcLayer3); - ASSERT_EQ(find_subgraphs(graph, subgraph), std::vector({1})); + auto res = find_subgraphs(graph, subgraph); + auto it = std::find(res.begin(), res.end(), std::vector({1, 2, 0})); + ASSERT_NE(it, res.end()); +} + +TEST(graph_transformations, check_subgraphs_search5) { + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + + Graph graph(5); + Graph subgraph(2); + FCLayer fcLayer(weights, bias); + FCLayer fcLayer2(weights, bias); + FCLayer fcLayer3(weights, bias); + FCLayer fcLayer4(weights, bias); + EWLayer ewLayer5("relu"); + + graph.setInput(fcLayer, input); + graph.makeConnection(fcLayer, fcLayer2); + graph.makeConnection(fcLayer, fcLayer4); + graph.makeConnection(fcLayer2, fcLayer3); + graph.makeConnection(fcLayer4, ewLayer5); + graph.setOutput(ewLayer5, output); + + subgraph.setInput(fcLayer, input); + subgraph.makeConnection(fcLayer, fcLayer2); + subgraph.addSingleLayer(fcLayer3); + subgraph.makeConnection(fcLayer3, ewLayer5); + + auto res = find_subgraphs(graph, subgraph); + auto it = std::find(res.begin(), res.end(), std::vector({1, 3, 2, 4})); + ASSERT_NE(it, res.end()); +} + +TEST(graph_transformations, check_subgraphs_big_random) { + const int num_vertices = 1000; + const std::vector vec1 = {2.0F, 1.5F, 0.1F, 1.9F, 0.0F, 5.5F}; + Tensor weights = make_tensor(vec1, {3, 2}); + Tensor bias = make_tensor({0.5F, 0.5F, 1.0F}); + Tensor input = make_tensor({1.0F, 2.0F}, {2}); + Tensor output; + Graph graph(num_vertices); + Graph subgraph(3); + std::vector> layers; + for (int i = 0; i < num_vertices / 2; i++) { + layers.push_back(std::make_shared(weights, bias)); + } + for (int i = 0; i < num_vertices / 2; i++) { + layers.push_back(std::make_shared("relu")); + } + graph.setInput(*layers[0], input); + for (int i = 0; i < num_vertices; i++) { + int rFirst = rand() % (num_vertices - 1); + int rSecond = 1 + rand() % (num_vertices - 1); + if ((rFirst == rSecond) || + ((*layers[rFirst]).getID() == (*layers[rSecond]).getID()) && + ((*layers[rFirst]).getID() != 0)) { + continue; + } + if (((*layers[rFirst]).getID() >= graph.getLayersCount()) || + (rFirst != 0 && (*layers[rFirst]).getID() == 0)) { + graph.addSingleLayer(*layers[rFirst]); + } + graph.makeConnection(*layers[rFirst], *layers[rSecond]); + } + graph.setOutput(*layers[num_vertices - 1], output); + + subgraph.setInput(*layers[0], input); + subgraph.makeConnection(*layers[0], *layers[50]); + subgraph.makeConnection(*layers[50], *layers[1]); + + std::vector> res1 = find_subgraphs(graph, subgraph); + double res1_time = + elapsed_time_avg(10, find_subgraphs, graph, subgraph); + std::cerr << "Find subgraphs time in ms " << res1_time << std::endl; } From b441d290ee11d383f2f476885e49147c89cd98ac Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Mon, 13 Oct 2025 01:41:50 +0300 Subject: [PATCH 10/11] New implementation --- src/graph_transformations/graph_transformations.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/graph_transformations/graph_transformations.cpp b/src/graph_transformations/graph_transformations.cpp index 34874a66b..3bb283b16 100644 --- a/src/graph_transformations/graph_transformations.cpp +++ b/src/graph_transformations/graph_transformations.cpp @@ -41,11 +41,12 @@ bool run_search(const Graph& graph, const Graph& subgraph, std::vector>& results) { size_t cur_size = assignments.size(); for (int prev_id = 0; prev_id < subgraph.getLayersCount(); prev_id++) { - size_t amount_connected_s = + int amount_connected_s = subgraph.getVertexValue(prev_id + 1) - subgraph.getVertexValue(prev_id); for (int j = 0; j < amount_connected_s; j++) { int next_id = subgraph.getEdgeValue(subgraph.getVertexValue(prev_id) + j); - if (prev_id < cur_size && next_id < cur_size) { + if (prev_id < static_cast(cur_size) && + next_id < static_cast(cur_size)) { if (!has_edge(graph, assignments[prev_id], assignments[next_id])) { return false; } @@ -63,9 +64,9 @@ bool run_search(const Graph& graph, const Graph& subgraph, } // input & output node shouldn't be checked for it's outputs if (!is_leaf(subgraph, ids[k]) && !is_root(subgraph, ids[k])) { - size_t amount_connected_s1 = subgraph.getVertexValue(ids[k] + 1) - - subgraph.getVertexValue(ids[k]); - size_t amount_connected_1 = + int amount_connected_s1 = subgraph.getVertexValue(ids[k] + 1) - + subgraph.getVertexValue(ids[k]); + int amount_connected_1 = graph.getVertexValue(assignments[ids[k]] + 1) - graph.getVertexValue(assignments[ids[k]]); if (amount_connected_1 != amount_connected_s1) { @@ -78,7 +79,7 @@ bool run_search(const Graph& graph, const Graph& subgraph, } // assumption is good -> return true - if (cur_size == subgraph.getLayersCount()) { + if (static_cast(cur_size) == subgraph.getLayersCount()) { return true; } From 2d93a810a78d229a15c7c5cc9399650deedc8ba6 Mon Sep 17 00:00:00 2001 From: NeiroYT Date: Mon, 13 Oct 2025 01:46:27 +0300 Subject: [PATCH 11/11] New implementation --- test/graph/test_graph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/graph/test_graph.cpp b/test/graph/test_graph.cpp index 653891137..5aa428904 100644 --- a/test/graph/test_graph.cpp +++ b/test/graph/test_graph.cpp @@ -404,8 +404,8 @@ TEST(graph_transformations, check_subgraphs_big_random) { int rFirst = rand() % (num_vertices - 1); int rSecond = 1 + rand() % (num_vertices - 1); if ((rFirst == rSecond) || - ((*layers[rFirst]).getID() == (*layers[rSecond]).getID()) && - ((*layers[rFirst]).getID() != 0)) { + (((*layers[rFirst]).getID() == (*layers[rSecond]).getID()) && + ((*layers[rFirst]).getID() != 0))) { continue; } if (((*layers[rFirst]).getID() >= graph.getLayersCount()) ||