From 95c9f715cd1fa6baa55cc87167382bd33e31b226 Mon Sep 17 00:00:00 2001
From: Thibault Hallouin <thibault.hallouin@inrae.fr>
Date: Mon, 23 May 2022 11:29:21 +0200
Subject: [PATCH] replace unordered_set by vector to keep insertion order

The order is which elements and dependencies are specified is important
because some may need to be computed before others (i.e. they are
themselves dependent). Using a vector (rather than a set) is required
because while the set is ordered, the order is not controlled by the
insertion order, but by some other sorting rules.
---
 include/evalhyd/determinist.hpp |  9 +++++----
 include/evalhyd/probabilist.hpp | 18 +++++++++++-------
 include/evalhyd/utils.hpp       | 27 ++++++++++++++++++++++-----
 3 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/include/evalhyd/determinist.hpp b/include/evalhyd/determinist.hpp
index da8e659..b521379 100644
--- a/include/evalhyd/determinist.hpp
+++ b/include/evalhyd/determinist.hpp
@@ -2,7 +2,7 @@
 #define EVALHYD_DETERMINIST_HPP
 
 #include <unordered_map>
-#include <unordered_set>
+#include <vector>
 #include <xtensor/xexpression.hpp>
 
 #include "utils.hpp"
@@ -49,8 +49,8 @@ namespace evalhyd
             // TODO
 
             // determine required elt/dep to be pre-computed
-            std::unordered_set<std::string> req_elt = {};
-            std::unordered_set<std::string> req_dep = {};
+            std::vector<std::string> req_elt;
+            std::vector<std::string> req_dep;
 
             eh::utils::find_requirements(metrics, elt, dep, req_elt, req_dep);
 
@@ -73,7 +73,8 @@ namespace evalhyd
             {
                 if ( metric == "nse" )
                 {
-                    if ( req_dep.find(metric) == req_dep.end() )
+                    if (std::find(req_dep.begin(), req_dep.end(), metric)
+                            == req_dep.end())
                         evaluator.calc_nse();
                     r.emplace_back(evaluator.nse);
                 }
diff --git a/include/evalhyd/probabilist.hpp b/include/evalhyd/probabilist.hpp
index c16780e..f19a3d3 100644
--- a/include/evalhyd/probabilist.hpp
+++ b/include/evalhyd/probabilist.hpp
@@ -3,7 +3,7 @@
 
 #include <utility>
 #include <unordered_map>
-#include <unordered_set>
+#include <vector>
 #include <xtensor/xtensor.hpp>
 #include <xtensor/xview.hpp>
 
@@ -55,8 +55,8 @@ namespace evalhyd
             dep["bss"] = {"bs"};
 
             // determine required elt/dep to be pre-computed
-            std::unordered_set<std::string> req_elt = {};
-            std::unordered_set<std::string> req_dep = {};
+            std::vector<std::string> req_elt;
+            std::vector<std::string> req_dep;
 
             eh::utils::find_requirements(metrics, elt, dep, req_elt, req_dep);
 
@@ -83,25 +83,29 @@ namespace evalhyd
             {
                 if ( metric == "bs" )
                 {
-                    if (req_dep.find(metric) == req_dep.end())
+                    if (std::find(req_dep.begin(), req_dep.end(), metric)
+                            == req_dep.end())
                         evaluator.calc_bs();
                     r.emplace_back(evaluator.bs);
                 }
                 else if ( metric == "bss" )
                 {
-                    if (req_dep.find(metric) == req_dep.end())
+                    if (std::find(req_dep.begin(), req_dep.end(), metric)
+                            == req_dep.end())
                         evaluator.calc_bss();
                     r.emplace_back(evaluator.bss);
                 }
                 else if ( metric == "bs_crd" )
                 {
-                    if (req_dep.find(metric) == req_dep.end())
+                    if (std::find(req_dep.begin(), req_dep.end(), metric)
+                            == req_dep.end())
                         evaluator.calc_bs_crd();
                     r.emplace_back(evaluator.bs_crd);
                 }
                 else if ( metric == "bs_lbd" )
                 {
-                    if (req_dep.find(metric) == req_dep.end())
+                    if (std::find(req_dep.begin(), req_dep.end(), metric)
+                            == req_dep.end())
                         evaluator.calc_bs_lbd();
                     r.emplace_back(evaluator.bs_lbd);
                 }
diff --git a/include/evalhyd/utils.hpp b/include/evalhyd/utils.hpp
index 1378a64..bc8fbb6 100644
--- a/include/evalhyd/utils.hpp
+++ b/include/evalhyd/utils.hpp
@@ -3,6 +3,7 @@
 
 #include <unordered_map>
 #include <unordered_set>
+#include <vector>
 #include <xtensor/xtensor.hpp>
 
 namespace evalhyd
@@ -27,24 +28,40 @@ namespace evalhyd
                 const std::vector<std::string>& metrics,
                 std::unordered_map<std::string, std::vector<std::string>>& elements,
                 std::unordered_map<std::string, std::vector<std::string>>& dependencies,
-                std::unordered_set<std::string>& required_elements,
-                std::unordered_set<std::string>& required_dependencies
+                std::vector<std::string>& required_elements,
+                std::vector<std::string>& required_dependencies
         )
         {
+            std::unordered_set<std::string> found_elements;
+            std::unordered_set<std::string> found_dependencies;
+
             for (const auto& metric : metrics)
             {
                 // add elements to pre-computation set
                 for (const auto& element : elements[metric])
-                    required_elements.insert(element);
+                    if (found_elements.find(element) == found_elements.end())
+                    {
+                        found_elements.insert(element);
+                        required_elements.push_back(element);
+                    }
+
                 // add metric dependencies to pre-computation set
                 if (dependencies.find(metric) != dependencies.end())
                 {
                     for (const auto& dependency : dependencies[metric])
                     {
-                        required_dependencies.insert(dependency);
+                        if (found_dependencies.find(dependency) == found_dependencies.end())
+                        {
+                            found_dependencies.insert(dependency);
+                            required_dependencies.push_back(dependency);
+                        }
                         // add dependency elements to pre-computation set
                         for (const auto& element : elements[dependency])
-                            required_elements.insert(element);
+                            if (found_elements.find(element) == found_elements.end())
+                            {
+                                found_elements.insert(element);
+                                required_elements.push_back(element);
+                            }
                     }
                 }
             }
-- 
GitLab