diff --git a/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp b/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp
index 2f6066ba4cd97284c43b509c9d5eb988b65b53a5..36d09db47d23395d649a688252f2af803cb1bc9d 100644
--- a/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp
+++ b/include/aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp
@@ -10,164 +10,162 @@
 #include "aidge/graph/Node.hpp"
 
 
-
 namespace Aidge{
 
-    class FsmNode;
+class FsmNode;
+
+/**
+ * @brief a class used to save the execution context of state machines, that is the actual state in the FSM, the actual node in the graph
+ * all node that have been Validate,Rejecte or Considered common
+*/
+class FsmRunTimeContext
+{
+private:
+    /**
+     * @brief the list of node rejected for all the context
+    */
+    static std::vector<std::set<NodePtr>> mRejectedNodes;
+    /**
+     * @brief the actual state of this Context (where it's in the FSM graph)
+    */
+    std::shared_ptr<FsmNode> mActState;
+    /**
+     * @brief the actual node of this Context (where it's in the graph)
+    */
+    NodePtr mActOpNode;
+    /**
+     * @brief the map of the node consider as common and the common ID
+     * @details we need to store what node it's consider as common because of the end
+     * resolution of the matching, all node consider as common need to be the same in all context
+    */
+    std::map<NodePtr,std::size_t> mCommonNodes;
+    /**
+     * @brief the map of the node that as been valid in this context , and the test that valide the node
+    */
+    std::map<std::shared_ptr<ConditionalInterpreter>,std::set<NodePtr>> mValidNodes;
+    /**
+     * @brief the index in the rejected node of this context
+    */
+    std::size_t mLocalIdxRejeced;
+public:
+    /**
+     * @brief constructor
+     * @param actState the actual state in the FSM
+     * @param actOpNode the actual node in the graph
+     * @param idxRejeced the idx in the global regected node vector init max() as sentinel value of undefind
+    */
+    FsmRunTimeContext(std::shared_ptr<FsmNode> actState ,NodePtr actOpNode ,std::size_t idxRejeced =std::numeric_limits<std::size_t>::max() );
+    FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime);
+    FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime,std::shared_ptr<FsmNode> actState ,NodePtr actOpNode );
+
+    virtual ~FsmRunTimeContext()=default;
+
+    /**
+     * @defgroup FsmRunTimeContextRejected Function for managing rejected nodes
+     */
+
+    /**
+     * @ingroup FsmRunTimeContextRejected
+     * @brief Add a node as rejected in this context
+     */
+    void addRejectedNode(NodePtr node);
+
+    /**
+     * @ingroup FsmRunTimeContextRejected
+     * @brief get the rejected nodes of this context
+     */
+    inline std::set<NodePtr> getRejectedNodes(void) const {
+        return mRejectedNodes[mLocalIdxRejeced];
+    }
+
+
+    /**
+     * @defgroup FsmRunTimeContextTest Function for test the context
+     */
 
-    class FsmNode;
+    /**
+     * @ingroup FsmRunTimeContextTest
+     * @brief test if the actual state is valide
+     * @return bool
+     */
+    bool isOnValidState(void);
+    /**
+     * @ingroup FsmRunTimeContextTest
+     * @brief test if the node is considered as common in this context
+     * @param node node to test
+     * @return bool
+     */
+    bool isCommonDefined(NodePtr node);
+    /**
+     * @ingroup FsmRunTimeContextTest
+     * @brief test if has already validated in this context
+     * @param node node to test
+     * @return bool
+     */
+    bool isAlreadyValid(NodePtr node);
+    /**
+     * @ingroup FsmRunTimeContextTest
+     * @brief test if this context is compatible with an others
+     * @details to say that two contexts are compatible is to check :
+     *  that the contexts do not validate the same nodes (other than the common ones)
+     *  and that the common ones have the same idx
+     * @param fsmContext the others context
+     * @return bool
+     */
+    bool areCompatible(std::shared_ptr<FsmRunTimeContext> fsmContext);
+    /**
+     * @ingroup FsmRunTimeContextTest
+     * @brief test if this context is strictly equal with an others
+     * @param fsmContext the others context
+     * @return bool
+     */
+    bool areEqual(std::shared_ptr<FsmRunTimeContext> fsmContext);
 
     /**
-     * @brief a class used to save the execution context of state machines, that is the actual state in the FSM, the actual node in the graph
-     * all node that have been Validate,Rejecte or Considered common
+     * @defgroup FsmRunTimeContextSet Function set context
     */
-    class FsmRunTimeContext
-    {
-    private:
-        /**
-         * @brief the list of node rejected for all the context
-        */
-        static std::vector<std::set<NodePtr>> mRejectedNodes;
-        /**
-         * @brief the actual state of this Context (where it's in the FSM graph)
-        */
-        std::shared_ptr<FsmNode> mActState;
-        /**
-         * @brief the actual node of this Context (where it's in the graph)
-        */
-        NodePtr mActOpNode;
-        /**
-         * @brief the map of the node consider as common and the common ID
-         * @details we need to store what node it's consider as common because of the end
-         * resolution of the matching, all node consider as common need to be the same in all context
-        */
-        std::map<NodePtr,std::size_t> mCommonNodes;
-        /**
-         * @brief the map of the node that as been valid in this context , and the test that valide the node
-        */
-        std::map<std::shared_ptr<ConditionalInterpreter>,std::set<NodePtr>> mValidNodes;
-        /**
-         * @brief the index in the rejected node of this context
-        */
-        std::size_t mLocalIdxRejeced;
-    public:
-        /**
-         * @brief constructor
-         * @param actState the actual state in the FSM
-         * @param actOpNode the actual node in the graph
-         * @param idxRejeced the idx in the global regected node vector init max() as sentinel value of undefind
-        */
-        FsmRunTimeContext(std::shared_ptr<FsmNode> actState ,NodePtr actOpNode ,std::size_t idxRejeced =std::numeric_limits<std::size_t>::max() );
-        FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime);
-        FsmRunTimeContext(std::shared_ptr<FsmRunTimeContext> fsmRunTime,std::shared_ptr<FsmNode> actState ,NodePtr actOpNode );
-
-        virtual ~FsmRunTimeContext()=default;
-
-        /**
-         * @defgroup FsmRunTimeContextRejected Function for managing rejected nodes
-         */
-
-        /**
-         * @ingroup FsmRunTimeContextRejected
-         * @brief Add a node as rejected in this context
-         */
-        void addRejectedNode(NodePtr node);
-
-        /**
-         * @ingroup FsmRunTimeContextRejected
-         * @brief get the rejected nodes of this context
-         */
-        std::set<NodePtr> getRejectedNodes(void);
-
-
-        /**
-         * @defgroup FsmRunTimeContextTest Function for test the context
-         */
-
-        /**
-         * @ingroup FsmRunTimeContextTest
-         * @brief test if the actual state is valide
-         * @return bool
-         */
-        bool isOnValidState(void);
-        /**
-         * @ingroup FsmRunTimeContextTest
-         * @brief test if the node is considered as common in this context
-         * @param node node to test
-         * @return bool
-         */
-        bool isCommonDefined(NodePtr node);
-        /**
-         * @ingroup FsmRunTimeContextTest
-         * @brief test if has already validated in this context
-         * @param node node to test
-         * @return bool
-         */
-        bool isAlreadyValid(NodePtr node);
-        /**
-         * @ingroup FsmRunTimeContextTest
-         * @brief test if this context is compatible with an others
-         * @details to say that two contexts are compatible is to check :
-         *  that the contexts do not validate the same nodes (other than the common ones)
-         *  and that the common ones have the same idx
-         * @param fsmContext the others context
-         * @return bool
-         */
-        bool areCompatible(std::shared_ptr<FsmRunTimeContext> fsmContext);
-        /**
-         * @ingroup FsmRunTimeContextTest
-         * @brief test if this context is strictly equal with an others
-         * @param fsmContext the others context
-         * @return bool
-         */
-        bool areEqual(std::shared_ptr<FsmRunTimeContext> fsmContext);
-
-        /**
-         * @defgroup FsmRunTimeContextSet Function set context
-        */
-
-
-        void setCommon(NodePtr node,std::size_t commonIdx);
-
-
-        void setValid(NodePtr node,std::shared_ptr<ConditionalInterpreter> tag);
-
-        /**
-         * @defgroup FsmRunTimeContextGet Function get context
-         */
-
-
-        /**
-         * @ingroup FsmRunTimeContextGet
-         * @brief get the sub idx state
-         * @return bool
-         */
-        std::size_t getSubStmId(void);
-
-        NodePtr getCommonNodeFromIdx(std::size_t commonIdx);
-        std::size_t getCommonNodeIdx(NodePtr node);
-        std::set<NodePtr> getCommonNodes(void);
-
-        std::map<NodePtr,std::size_t> getCommon(void);
-        std::set<NodePtr> getValidNodes(void);
-
-        std::set<NodePtr> getValidNodesNoCommon(void);
-        std::map<std::shared_ptr<ConditionalInterpreter>,std::set<NodePtr>>& getValid(void);
-
-
-        NodePtr getActNode(void);
-        std::shared_ptr<FsmNode> getActState(void);
-
-
-        /**
-         * @defgroup FsmRunTimeContextMem
-         */
-
-        void rst(void);
-
-
-    };
-
-}
-
-#endif //AIDGE_CORE_FSM_RUN_TIME_CONTEXT_H_
+
+
+    void setCommon(NodePtr node,std::size_t commonIdx);
+
+
+    void setValid(NodePtr node,std::shared_ptr<ConditionalInterpreter> tag);
+
+    /**
+     * @defgroup FsmRunTimeContextGet Function get context
+     */
+
+
+    /**
+     * @ingroup FsmRunTimeContextGet
+     * @brief get the sub idx state
+     * @return bool
+     */
+    std::size_t getSubStmId(void);
+
+    NodePtr getCommonNodeFromIdx(std::size_t commonIdx);
+    std::size_t getCommonNodeIdx(NodePtr node);
+    std::set<NodePtr> getCommonNodes(void);
+
+    std::map<NodePtr,std::size_t> getCommon(void);
+    std::set<NodePtr> getValidNodes(void);
+
+    std::set<NodePtr> getValidNodesNoCommon(void);
+    std::map<std::shared_ptr<ConditionalInterpreter>,std::set<NodePtr>>& getValid(void);
+
+
+    NodePtr getActNode(void);
+    std::shared_ptr<FsmNode> getActState(void);
+
+
+    /**
+     * @defgroup FsmRunTimeContextMem
+     */
+
+    void rst(void);
+
+
+};
+} // namespace Aidge
+
+#endif // AIDGE_CORE_FSM_RUN_TIME_CONTEXT_H_
diff --git a/include/aidge/graphRegex/matchFsm/MatchResult.hpp b/include/aidge/graphRegex/matchFsm/MatchResult.hpp
index 4f7f9bf1dd9b0612e71a1f7894bfc382713c0ad0..7954e932a20940946f444cf7277e2bf359f7f15a 100644
--- a/include/aidge/graphRegex/matchFsm/MatchResult.hpp
+++ b/include/aidge/graphRegex/matchFsm/MatchResult.hpp
@@ -24,8 +24,10 @@ private:
     const std::vector<NodePtr> mStartNode;
 
 public:
+    MatchSolution() = delete;
     MatchSolution(std::vector<std::shared_ptr<FsmRunTimeContext>>& precedence,const std::string query,const std::vector<NodePtr> startNode);
-    inline const std::set<NodePtr>& at(const std::string key) {
+
+    inline const std::set<NodePtr>& at(const std::string& key) {
         return mSolution[key];
     }
     const std::set<NodePtr> getAll();
@@ -33,7 +35,6 @@ public:
 
     inline const std::string& getQuery() const noexcept { return mQueryFrom; }
     inline const std::vector<NodePtr>& getStartNode() const noexcept { return mStartNode; }
-
 };
 
 
@@ -60,14 +61,18 @@ private:
 
 
 public:
-    MatchResult(std::vector<std::shared_ptr<FsmRunTimeContext>> allValid, std::size_t nbSubStm,
-     const std::string& query,const std::vector<NodePtr>& startNodes);
+    MatchResult() = delete;
+    MatchResult(std::vector<std::shared_ptr<FsmRunTimeContext>> allValid,
+                std::size_t nbSubStm,
+                const std::string& query,const std::vector<NodePtr>& startNodes);
 
     /**
      * @brief get the set of the node match for une expression
      * @return the set of node of the graph that corresponding to an expression
     */
-    std::shared_ptr<MatchSolution> getBiggerSolution(void);
+    inline std::shared_ptr<MatchSolution> getBiggerSolution(void) const noexcept {
+        return mSolve.empty() ? nullptr : mSolve[0];
+    }
 
     inline std::vector<std::shared_ptr<MatchSolution>> getSolutions(void) const noexcept {
         return mSolve;
diff --git a/include/aidge/recipies/GraphViewHelper.hpp b/include/aidge/recipies/GraphViewHelper.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d7bcec713087054640c87c6fd229fee53d1ed4a6
--- /dev/null
+++ b/include/aidge/recipies/GraphViewHelper.hpp
@@ -0,0 +1,40 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#ifndef AIDGE_CORE_UTILS_RECIPIES_H_
+#define AIDGE_CORE_UTILS_RECIPIES_H_
+
+#include <memory>
+#include <set>
+
+#include "aidge/graph/Node.hpp"
+#include "aidge/graph/GraphView.hpp"
+
+
+namespace Aidge {
+
+/**
+ * @brief Getter for every Producer operator in a GraphView.
+ * @param graphview GraphView instance where Producers should be searched.
+ * @return std::set<std::shared_ptr<Node>>
+ */
+std::set<std::shared_ptr<Aidge::Node>> producers(std::shared_ptr<Aidge::GraphView> graphview) {
+    std::set<std::shared_ptr<Node>> res;
+    const std::set<std::shared_ptr<Node>> nodes = graphview->getNodes();
+
+    std::copy_if(nodes.cbegin(),
+                    nodes.cend(),
+                    std::inserter(res, res.begin()),
+                    [](std::shared_ptr<Node> n){ return n->type() == "Producer"; });
+
+    return res;
+}
+} // namespace Aidge
\ No newline at end of file
diff --git a/python_binding/graphRegex/pybind_GraphRegex.cpp b/python_binding/graphRegex/pybind_GraphRegex.cpp
index be3cd9e9124ba1306226dcbdc13ee39748cf0606..921f204d017f90823b9c4a1a024efa271a4691e5 100644
--- a/python_binding/graphRegex/pybind_GraphRegex.cpp
+++ b/python_binding/graphRegex/pybind_GraphRegex.cpp
@@ -10,6 +10,7 @@
  ********************************************************************************/
 
 #include <pybind11/pybind11.h>
+#include <pybind11/functional.h>
 #include "aidge/graphRegex/GraphRegex.hpp"
 
 namespace py = pybind11;
@@ -20,7 +21,7 @@ void init_GraphRegex(py::module& m){
     py::class_<GraphRegex, std::shared_ptr<GraphRegex>>(m, "GraphRegex", "GraphRegex class describes a regex to test a graph.")
     .def(py::init<>())
 
-    .def("add_query", &GraphRegex::addQuery, R"mydelimiter(
+    .def("add_query", &GraphRegex::addQuery, py::arg("query"), py::arg("f") = nullptr, R"mydelimiter(
     :rtype: str
     )mydelimiter")
 
@@ -47,10 +48,10 @@ void init_GraphRegex(py::module& m){
     Add a node test
     :param key: the key of the node test to use in the query.
     :param conditionalExpressions: the test to do .
-    
+
     )mydelimiter")
 
-    
+
     .def("set_node_key",
             (void (GraphRegex::*)(const std::string, std::function<bool(NodePtr)>)) &
                     GraphRegex::setNodeKey,
@@ -59,7 +60,7 @@ void init_GraphRegex(py::module& m){
     Add a node test
     :param key: the key of the lambda test to use in the conditional expressions.
     :param f: bool lambda (nodePtr) .
-    
+
     )mydelimiter")
 
 
diff --git a/python_binding/graphRegex/pybind_MatchSolution.cpp b/python_binding/graphRegex/pybind_MatchSolution.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81d39f86ed6da5b7b63a2d43b3a4fcbb2f8e9043
--- /dev/null
+++ b/python_binding/graphRegex/pybind_MatchSolution.cpp
@@ -0,0 +1,40 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+#include "aidge/graphRegex/matchFsm/MatchResult.hpp"
+
+namespace py = pybind11;
+namespace Aidge {
+void init_MatchSolution(py::module& m){
+
+
+    py::class_<MatchSolution, std::shared_ptr<MatchSolution>>(m, "MatchSolution", "MatchSolution class contains the result of one match and the associated key, the query and the start node.")
+    .def("at", &MatchSolution::at, py::arg("key"),
+    R"mydelimiter(
+    :rtype: str
+    )mydelimiter")
+
+    .def("get_all",  &MatchSolution::getAll,
+    R"mydelimiter(
+    )mydelimiter")
+
+    .def("get_query",  &MatchSolution::getQuery,
+    R"mydelimiter(
+    )mydelimiter")
+
+    .def("get_start_node",  &MatchSolution::getStartNode,
+    R"mydelimiter(
+    )mydelimiter")
+    ;
+}
+} // namespace Aidge
diff --git a/python_binding/pybind_core.cpp b/python_binding/pybind_core.cpp
index 0353953fda39cd6dc283d20a0a3e36659dd891a4..be0d357b7f73e26aad44994f407696f70617ad71 100644
--- a/python_binding/pybind_core.cpp
+++ b/python_binding/pybind_core.cpp
@@ -56,6 +56,7 @@ void init_OpArgs(py::module&);
 void init_Connector(py::module&);
 
 void init_GraphRegex(py::module&);
+void init_MatchSolution(py::module&);
 
 void init_Recipies(py::module&);
 
@@ -106,7 +107,9 @@ void init_Aidge(py::module& m){
     init_Identity(m);
 
     init_Producer(m);
+
     init_GraphRegex(m);
+    init_MatchSolution(m);
 
     init_Recipies(m);
     init_Scheduler(m);
diff --git a/src/graphRegex/matchFsm/FsmRunTimeContext.cpp b/src/graphRegex/matchFsm/FsmRunTimeContext.cpp
index ddf6a46cc7c75dc853d71ba98b051b4263a31164..7a09908e5629e299b6b264fbfaac97bdaf7fa316 100644
--- a/src/graphRegex/matchFsm/FsmRunTimeContext.cpp
+++ b/src/graphRegex/matchFsm/FsmRunTimeContext.cpp
@@ -1,7 +1,7 @@
 #include "aidge/graphRegex/matchFsm/FsmRunTimeContext.hpp"
 #include "aidge/graphRegex/matchFsm/FsmNode.hpp"
 
-using namespace Aidge; 
+using namespace Aidge;
 
 std::vector<std::set<NodePtr>> FsmRunTimeContext::mRejectedNodes;
 
@@ -42,10 +42,6 @@ void FsmRunTimeContext::addRejectedNode(NodePtr node){
     mRejectedNodes[mLocalIdxRejeced].insert(node);
 }
 
-std::set<NodePtr> FsmRunTimeContext::getRejectedNodes(void){
-    return mRejectedNodes[mLocalIdxRejeced];
-}
-
 bool FsmRunTimeContext::isOnValidState(void){
     return mActState->isValid();
 }
@@ -57,7 +53,7 @@ bool FsmRunTimeContext::isCommonDefined(NodePtr node){
     for(const auto& nodeC : nodes){
         if(nodeC.get() == node.get()){
             return true;
-        } 
+        }
     }
     return false;
 }
@@ -68,7 +64,7 @@ bool FsmRunTimeContext::isAlreadyValid(NodePtr node){
     for(const auto& nodeV : nodes){
         if(nodeV.get() == node.get()){
             return true;
-        } 
+        }
     }
     return false;
 
@@ -82,7 +78,7 @@ bool FsmRunTimeContext::areCompatible(std::shared_ptr<FsmRunTimeContext> fsmCont
     and the same idx for the common
     */
 
-   //common node 
+   //common node
 
    for (const auto& ref : getCommon()) {
         for (const auto& test : fsmContext->getCommon()) {
@@ -97,20 +93,15 @@ bool FsmRunTimeContext::areCompatible(std::shared_ptr<FsmRunTimeContext> fsmCont
 
    //valid nodes
     std::set<NodePtr> commonElements;
-   std::set<NodePtr> A = getValidNodesNoCommon();
-   std::set<NodePtr> B = fsmContext->getValidNodesNoCommon();
+    std::set<NodePtr> A = getValidNodesNoCommon();
+    std::set<NodePtr> B = fsmContext->getValidNodesNoCommon();
     std::set_intersection(
         A.begin(),A.end(),
         B.begin(),  B.end(),
         std::inserter(commonElements, commonElements.end())
        );
 
-
-    if (!commonElements.empty()) {
-        return false;
-    }
-
-    return true;
+    return (commonElements.empty()) ? true : false;
 }
 
 bool FsmRunTimeContext::areEqual(std::shared_ptr<FsmRunTimeContext> fsmContext){
@@ -142,7 +133,7 @@ void FsmRunTimeContext::setCommon(NodePtr node,std::size_t commonIdx){
 }
 
 void FsmRunTimeContext::setValid(NodePtr node,std::shared_ptr<ConditionalInterpreter> tag){
-    //we already find a node of this type 
+    //we already find a node of this type
     if(mValidNodes.find(tag) != mValidNodes.end()){
         if(isAlreadyValid(node) && !isCommonDefined(node) ){
             throw std::runtime_error("setValid you valid tow time");
@@ -151,7 +142,7 @@ void FsmRunTimeContext::setValid(NodePtr node,std::shared_ptr<ConditionalInterpr
     }else{
         mValidNodes[tag] = {node};
     }
-    
+
 }
 
 std::size_t FsmRunTimeContext::getSubStmId(void){
diff --git a/src/graphRegex/matchFsm/MatchResult.cpp b/src/graphRegex/matchFsm/MatchResult.cpp
index 08be00dea66c66a46dbbf2b225efd0df3f332188..99df00e198a9a30be21e0ad18b4933a40b9b7a06 100644
--- a/src/graphRegex/matchFsm/MatchResult.cpp
+++ b/src/graphRegex/matchFsm/MatchResult.cpp
@@ -132,8 +132,4 @@ void Aidge::MatchResult::_generateCombination( std::size_t idxSubStm,
     }
     return;
 
-}
-
-std::shared_ptr<Aidge::MatchSolution> Aidge::MatchResult::getBiggerSolution(void){
-    return mSolve.empty() ? nullptr : mSolve[0];
 }
\ No newline at end of file