From 5ff1d75c5222e3a6203828bfb5807c8c0a5f6815 Mon Sep 17 00:00:00 2001
From: cmoineau <cyril.moineau@cea.fr>
Date: Fri, 20 Sep 2024 11:51:29 +0000
Subject: [PATCH] getAvailableImplSpecs now return a vector for binding
 purposes.

---
 include/aidge/backend/OperatorImpl.hpp        | 25 +++++++++++--------
 .../backend/pybind_OperatorImpl.cpp           | 10 +++++---
 2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/include/aidge/backend/OperatorImpl.hpp b/include/aidge/backend/OperatorImpl.hpp
index 4af7da64e..649898dd1 100644
--- a/include/aidge/backend/OperatorImpl.hpp
+++ b/include/aidge/backend/OperatorImpl.hpp
@@ -28,7 +28,7 @@ class Operator;
 
 /**
  * @brief ImplSpec stores the requirements or the specifications of an implementation.
- * 
+ *
  */
 struct ImplSpec {
     struct IOSpec {
@@ -73,10 +73,15 @@ inline bool operator<(const ImplSpec& lhs, const ImplSpec& rhs) {
         || (lhs.inputs == rhs.inputs && lhs.outputs == rhs.outputs && lhs.attrs < rhs.attrs);
 }
 
+
+inline bool operator==(const ImplSpec& lhs, const ImplSpec& rhs) {
+    return !(lhs < rhs) && !(rhs < lhs);
+}
+
 /**
  * @brief Impl stores the details of a specific implementation.
  * It is associated to a ImplSpec in a registry.
- * 
+ *
  */
 template <class FwdFunc, class BwdFunc>
 struct Impl {
@@ -108,7 +113,7 @@ public:
     /**
      * @brief Get the operator required implementation specification, according
      * to the current operator configuration.
-     * 
+     *
      */
     ImplSpec getRequiredSpec() const;
 
@@ -116,15 +121,15 @@ public:
      * @brief Get the best implementation that matches \p requiredSpecs.
      * If no implementation matches \p requiredSpecs, \p requiredSpecs is
      * returned.
-     * 
+     *
      */
     ImplSpec getBestMatch(const ImplSpec& requiredSpecs) const;
 
     /**
-     * @brief Get an adapted meta operator corresponding to the required 
+     * @brief Get an adapted meta operator corresponding to the required
      * specifications \p requiredSpecs from the implementation specifications
      * \p spec.
-     * 
+     *
      * @param spec Implementation specification
      * @param requiredSpecs Required specifications
      * @return std::shared_ptr<Node> Adapted meta op or nullptr
@@ -132,12 +137,12 @@ public:
     std::shared_ptr<Node> getAdaptation(const ImplSpec& spec, const ImplSpec& requiredSpecs) const;
 
     /**
-     * @brief Get the best adapted meta operator corresponding to the required 
+     * @brief Get the best adapted meta operator corresponding to the required
      * specifications \p requiredSpecs.
      * The best adaptation is the one with the lowest overhead cost.
-     * Currently, it is the one requiring the least number of additionnal 
+     * Currently, it is the one requiring the least number of additionnal
      * operators to match the available implementations.
-     * 
+     *
      * @param requiredSpecs Required specifications
      * @return std::shared_ptr<Node> Adapted meta op or nullptr
      */
@@ -147,7 +152,7 @@ public:
 
 protected:
     virtual std::shared_ptr<ProdConso> getProdConso() const;
-    virtual std::set<ImplSpec> getAvailableImplSpecs() const;
+    virtual std::vector<ImplSpec> getAvailableImplSpecs() const;
     bool checkIOSpec(const ImplSpec::IOSpec& required, const ImplSpec::IOSpec& spec) const;
 
     const Operator &mOp;
diff --git a/python_binding/backend/pybind_OperatorImpl.cpp b/python_binding/backend/pybind_OperatorImpl.cpp
index 04172c3ff..0c5aac004 100644
--- a/python_binding/backend/pybind_OperatorImpl.cpp
+++ b/python_binding/backend/pybind_OperatorImpl.cpp
@@ -55,9 +55,9 @@ public:
         );
     }
 
-    std::set<ImplSpec> getAvailableImplSpecs() const noexcept override {
+    std::vector<ImplSpec> getAvailableImplSpecs() const noexcept override {
         PYBIND11_OVERRIDE_NAME(
-            std::set<ImplSpec>,
+            std::vector<ImplSpec>,
             OperatorImpl,
             "get_available_impl_specs",
             getAvailableImplSpecs
@@ -81,6 +81,10 @@ void init_OperatorImpl(py::module& m){
     .def(py::init<const DynamicAttributes&>(), py::arg("attr") = DynamicAttributes())
     .def(py::init<const ImplSpec::IOSpec&, const DynamicAttributes&>(), py::arg("io"), py::arg("attr") = DynamicAttributes())
     .def(py::init<const ImplSpec::IOSpec&, const ImplSpec::IOSpec&, const DynamicAttributes&>(), py::arg("i"), py::arg("o"), py::arg("attr") = DynamicAttributes())
+    .def("__eq__", static_cast<bool(*)(const ImplSpec&, const ImplSpec&)>(&operator==))
+    .def("__repr__", [](ImplSpec self){
+        return fmt::format("{}\n", self);
+    })
     ;
 
     py::class_<OperatorImpl, std::shared_ptr<OperatorImpl>, pyOperatorImpl>(m, "OperatorImpl", py::dynamic_attr())
@@ -98,4 +102,4 @@ void init_OperatorImpl(py::module& m){
     .def("get_available_impl_specs", &OperatorImpl_Publicist::getAvailableImplSpecs)
     ;
 }
-}
+} // namespace Aidge
-- 
GitLab