From dc1fe72647f4bd319331113b3971030e241e826a Mon Sep 17 00:00:00 2001
From: Olivier BICHLER <olivier.bichler@cea.fr>
Date: Tue, 18 Feb 2025 11:29:09 +0100
Subject: [PATCH 1/4] Implement proposal in #212

---
 src/graph/GraphView.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/graph/GraphView.cpp b/src/graph/GraphView.cpp
index fab9be915..26c693152 100644
--- a/src/graph/GraphView.cpp
+++ b/src/graph/GraphView.cpp
@@ -1115,6 +1115,10 @@ void Aidge::GraphView::insertParent(NodePtr childNode,
 }
 
 bool Aidge::GraphView::replace(const std::set<Aidge::NodePtr>& oldNodes, const std::set<Aidge::NodePtr>& newNodes) {
+    AIDGE_ASSERT(!(oldNodes.size() > 1 && newNodes.size() > 1),
+      "GraphView::replace(): old and new sets cannot both have more than one node (here: {} and {} respectively). Use GraphView instead of set in this case.",
+      oldNodes.size(), newNodes.size());
+
     // (1) create GraphViews from both sets of Nodes
     auto oldG = std::make_shared<GraphView>("oldG");
     oldG->add(oldNodes, false);
-- 
GitLab


From 37355ba95134322ead021618aa59667db208638f Mon Sep 17 00:00:00 2001
From: Olivier BICHLER <olivier.bichler@cea.fr>
Date: Tue, 18 Feb 2025 12:06:57 +0100
Subject: [PATCH 2/4] Changed wrong logic

---
 src/graph/GraphView.cpp | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/graph/GraphView.cpp b/src/graph/GraphView.cpp
index 26c693152..b0d7336e2 100644
--- a/src/graph/GraphView.cpp
+++ b/src/graph/GraphView.cpp
@@ -1115,16 +1115,19 @@ void Aidge::GraphView::insertParent(NodePtr childNode,
 }
 
 bool Aidge::GraphView::replace(const std::set<Aidge::NodePtr>& oldNodes, const std::set<Aidge::NodePtr>& newNodes) {
-    AIDGE_ASSERT(!(oldNodes.size() > 1 && newNodes.size() > 1),
-      "GraphView::replace(): old and new sets cannot both have more than one node (here: {} and {} respectively). Use GraphView instead of set in this case.",
-      oldNodes.size(), newNodes.size());
-
     // (1) create GraphViews from both sets of Nodes
     auto oldG = std::make_shared<GraphView>("oldG");
     oldG->add(oldNodes, false);
     auto newG = std::make_shared<GraphView>("newG");
     newG->add(newNodes, false);
 
+    AIDGE_ASSERT(!(oldG->getOrderedInputs().size() > 1 || newG->getOrderedInputs().size() > 1),
+      "GraphView::replace(): old and new sets cannot have more than one input node (here: {} and {} respectively). Use GraphView instead of set in this case.",
+      oldG->getOrderedInputs().size(), newG->getOrderedInputs().size());
+    AIDGE_ASSERT(!(oldG->getOrderedOutputs().size() > 1 || newG->getOrderedOutputs().size() > 1),
+      "GraphView::replace(): old and new sets cannot have more than one output node (here: {} and {} respectively). Use GraphView instead of set in this case.",
+      oldG->getOrderedOutputs().size() , newG->getOrderedOutputs().size());
+
     return GraphView::replace(oldG, newG);
 }
 
-- 
GitLab


From d456e979b37695e0bd57ddd11747e91b82497871 Mon Sep 17 00:00:00 2001
From: Olivier BICHLER <olivier.bichler@cea.fr>
Date: Tue, 18 Feb 2025 16:03:30 +0100
Subject: [PATCH 3/4] More work was necessary

---
 src/graph/GraphView.cpp             | 33 +++++++++++++++++++++++------
 unit_tests/graph/Test_GraphView.cpp |  7 ++++--
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/src/graph/GraphView.cpp b/src/graph/GraphView.cpp
index b0d7336e2..1f1772c59 100644
--- a/src/graph/GraphView.cpp
+++ b/src/graph/GraphView.cpp
@@ -1114,6 +1114,26 @@ void Aidge::GraphView::insertParent(NodePtr childNode,
   add(newParentNode);
 }
 
+/**
+ *  old    \     new   | 1 node, 1 input  | >1 node, 1 input  | 1 node, >1 inputs  | >1 node, >1 inputs
+ * ----------------------------------------------------------------------------------------------------
+ * 1 node, 1 input     |     trivial      |      trivial      |     broadcast      |    broadcast
+ * >1 node, 1 input    |     trivial      |      trivial      |     broadcast      |    broadcast
+ * 1 node, >1 inputs   |   (take first)   |   (take first)    |     same order     |       X
+ * >1 node, >1 inputs  |       X          |        X          |         X          |       X
+ * 
+ *  old    \     new   | 1 node, 1 output | >1 node, 1 output | 1 node, >1 outputs | >1 node, >1 outputs
+ * -----------------------------------------------------------------------------------------------------
+ * 1 node, 1 output    |     trivial      |      trivial      |     take first     |       X
+ * >1 node, 1 output   |     trivial      |      trivial      |     take first     |       X
+ * 1 node, >1 outputs  |   (take first)   |   (take first)    |     same order     |       X
+ * >1 node, >1 outputs |       X          |        X          |         X          |       X
+ * 
+ * Only the X cases cannot possibly be resolved deterministically with sets of node.
+ * These cases are therefore forbidden for the set-based replace() interface.
+ * The remaining cases are handled by the GraphView-based replace() interface.
+ * If they are not supported, the function returns false.
+ */
 bool Aidge::GraphView::replace(const std::set<Aidge::NodePtr>& oldNodes, const std::set<Aidge::NodePtr>& newNodes) {
     // (1) create GraphViews from both sets of Nodes
     auto oldG = std::make_shared<GraphView>("oldG");
@@ -1121,12 +1141,13 @@ bool Aidge::GraphView::replace(const std::set<Aidge::NodePtr>& oldNodes, const s
     auto newG = std::make_shared<GraphView>("newG");
     newG->add(newNodes, false);
 
-    AIDGE_ASSERT(!(oldG->getOrderedInputs().size() > 1 || newG->getOrderedInputs().size() > 1),
-      "GraphView::replace(): old and new sets cannot have more than one input node (here: {} and {} respectively). Use GraphView instead of set in this case.",
-      oldG->getOrderedInputs().size(), newG->getOrderedInputs().size());
-    AIDGE_ASSERT(!(oldG->getOrderedOutputs().size() > 1 || newG->getOrderedOutputs().size() > 1),
-      "GraphView::replace(): old and new sets cannot have more than one output node (here: {} and {} respectively). Use GraphView instead of set in this case.",
-      oldG->getOrderedOutputs().size() , newG->getOrderedOutputs().size());
+    AIDGE_ASSERT(!((oldNodes.size() > 1 && oldG->getOrderedInputs().size() > 1) || (newNodes.size() > 1 && newG->getOrderedInputs().size() > 1 && oldG->getOrderedInputs().size() > 1)),
+      "GraphView::replace(): don't know how to match {} input(s) from {} node(s) (old set) to {} input(s) from {} node(s) (new set). Use GraphView instead of set in this case.",
+      oldG->getOrderedInputs().size(), oldNodes.size(), newG->getOrderedInputs().size(), newNodes.size());
+
+    AIDGE_ASSERT(!((oldNodes.size() > 1 && oldG->getOrderedOutputs().size() > 1) || (newNodes.size() > 1 && newG->getOrderedOutputs().size() > 1)),
+      "GraphView::replace(): don't know how to match {} output(s) from {} node(s) (old set) to {} output(s) from {} node(s) (new set). Use GraphView instead of set in this case.",
+      oldG->getOrderedOutputs().size(), oldNodes.size(), newG->getOrderedOutputs().size(), newNodes.size());
 
     return GraphView::replace(oldG, newG);
 }
diff --git a/unit_tests/graph/Test_GraphView.cpp b/unit_tests/graph/Test_GraphView.cpp
index 5bd435e28..d2f41269e 100644
--- a/unit_tests/graph/Test_GraphView.cpp
+++ b/unit_tests/graph/Test_GraphView.cpp
@@ -659,9 +659,12 @@ TEST_CASE("[core/graph] GraphView(replace)", "[GraphView][replace]") {
 
         REQUIRE(g->getNodes() == std::set<std::shared_ptr<Node>>({other1, conv1, conv2, conv3, conv4, concat, other2}));
 
-        GraphView::replace({conv1, conv2, conv3, conv4, concat}, {myConv});
+        // This doesn't make sense in the general case: replace() cannot possibly
+        // know how to match the inputs of the 4 conv with the single input of myCond
+        // The implicit assumption here is that they are the same!
+        //GraphView::replace({conv1, conv2, conv3, conv4, concat}, {myConv});
 
-        REQUIRE(g->getNodes() == std::set<std::shared_ptr<Node>>({other1, myConv, other2}));
+        //REQUIRE(g->getNodes() == std::set<std::shared_ptr<Node>>({other1, myConv, other2}));
     }
 
     SECTION("replace same input category 1") {
-- 
GitLab


From 4057db9eb344f694be2963d31187207561786804 Mon Sep 17 00:00:00 2001
From: Olivier BICHLER <olivier.bichler@cea.fr>
Date: Tue, 18 Feb 2025 16:10:57 +0100
Subject: [PATCH 4/4] Fixed table syntax

---
 src/graph/GraphView.cpp | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/src/graph/GraphView.cpp b/src/graph/GraphView.cpp
index 1f1772c59..315844858 100644
--- a/src/graph/GraphView.cpp
+++ b/src/graph/GraphView.cpp
@@ -1115,23 +1115,25 @@ void Aidge::GraphView::insertParent(NodePtr childNode,
 }
 
 /**
- *  old    \     new   | 1 node, 1 input  | >1 node, 1 input  | 1 node, >1 inputs  | >1 node, >1 inputs
- * ----------------------------------------------------------------------------------------------------
- * 1 node, 1 input     |     trivial      |      trivial      |     broadcast      |    broadcast
- * >1 node, 1 input    |     trivial      |      trivial      |     broadcast      |    broadcast
- * 1 node, >1 inputs   |   (take first)   |   (take first)    |     same order     |       X
- * >1 node, >1 inputs  |       X          |        X          |         X          |       X
+ * Inputs conditions:
+ * |  old    \     new   | 1 node, 1 input  | >1 node, 1 input  | 1 node, >1 inputs  | >1 node, >1 inputs |
+ * | ------------------- | ---------------- | ----------------- | ------------------ | ------------------ |
+ * | 1 node, 1 input     |     trivial      |      trivial      |     broadcast      |    broadcast       |
+ * | >1 node, 1 input    |     trivial      |      trivial      |     broadcast      |    broadcast       |
+ * | 1 node, >1 inputs   |   (take first)   |   (take first)    |     same order     |       X            |
+ * | >1 node, >1 inputs  |       X          |        X          |         X          |       X            |
  * 
- *  old    \     new   | 1 node, 1 output | >1 node, 1 output | 1 node, >1 outputs | >1 node, >1 outputs
- * -----------------------------------------------------------------------------------------------------
- * 1 node, 1 output    |     trivial      |      trivial      |     take first     |       X
- * >1 node, 1 output   |     trivial      |      trivial      |     take first     |       X
- * 1 node, >1 outputs  |   (take first)   |   (take first)    |     same order     |       X
- * >1 node, >1 outputs |       X          |        X          |         X          |       X
+ * Outputs conditions:
+ * |  old    \     new   | 1 node, 1 output | >1 node, 1 output | 1 node, >1 outputs | >1 node, >1 outputs |
+ * | ------------------- | ---------------- | ----------------- | ------------------ | ------------------- |
+ * | 1 node, 1 output    |     trivial      |      trivial      |     take first     |       X             |
+ * | >1 node, 1 output   |     trivial      |      trivial      |     take first     |       X             |
+ * | 1 node, >1 outputs  |   (take first)   |   (take first)    |     same order     |       X             |
+ * | >1 node, >1 outputs |       X          |        X          |         X          |       X             |
  * 
  * Only the X cases cannot possibly be resolved deterministically with sets of node.
- * These cases are therefore forbidden for the set-based replace() interface.
- * The remaining cases are handled by the GraphView-based replace() interface.
+ * These cases are therefore forbidden for the set-based `replace()` interface.
+ * The remaining cases are handled by the GraphView-based `replace()` interface.
  * If they are not supported, the function returns false.
  */
 bool Aidge::GraphView::replace(const std::set<Aidge::NodePtr>& oldNodes, const std::set<Aidge::NodePtr>& newNodes) {
-- 
GitLab