diff --git a/CMakeLists.txt b/CMakeLists.txt
index eb31e4d9f2804f346645b15cafe7d2974802cdc5..d56af45406dc07a86c6e3c47f104c610985113e4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
 
 # project name and language
 project(pmc-sog C CXX)
+project(pmc-sog VERSION 0.4.0)
+
+configure_file(PMCSOGConfig.h.in src/PMCSOGConfig.h)
 
 
 #set(CMAKE_CXX_STANDARD 14)
@@ -12,7 +15,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
 # Add compiler flags
 if(CMAKE_COMPILER_IS_GNUCC)
     #used flags -Og -DNDEBUG
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -std=c++17 -pthread -DNDEBUG -funswitch-loops -floop-interchange -floop-unroll-and-jam -fpeel-loops -fpredictive-commoning -fsplit-loops -fsplit-paths -fexpensive-optimizations  -fcse-follow-jumps -fthread-jumps -finline-functions -finline-small-functions -findirect-inlining -foptimize-strlen -fpartial-inlining -fexpensive-optimizations -falign-functions  -falign-jumps -falign-labels  -falign-loops -fcaller-saves -fdelete-null-pointer-checks") #-Og
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -std=c++17 -pthread -g3")#-DNDEBUG -funswitch-loops -floop-interchange -floop-unroll-and-jam -fpeel-loops -fpredictive-commoning -fsplit-loops -fsplit-paths -fexpensive-optimizations  -fcse-follow-jumps -fthread-jumps -finline-functions -finline-small-functions -findirect-inlining -foptimize-strlen -fpartial-inlining -fexpensive-optimizations -falign-functions  -falign-jumps -falign-labels  -falign-loops -fcaller-saves -fdelete-null-pointer-checks") #
 
 endif()
 
diff --git a/PMCSOGConfig.h.in b/PMCSOGConfig.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..837c7b2c8caff27babb76b643575054aed371fce
--- /dev/null
+++ b/PMCSOGConfig.h.in
@@ -0,0 +1,3 @@
+#define PMCSOG_VERSION_MAJOR @pmc-sog_VERSION_MAJOR@
+#define PMCSOG_VERSION_MINOR @pmc-sog_VERSION_MINOR@
+#define PMCSOG_VERSION_PATCH @pmc-sog_VERSION_PATCH@
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 90327eb43d168ef0581fccbb5a9da89a0fa78e0a..f4deee428652c9431dc47cc7314d57822a7f9ce4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,6 +21,7 @@ else()
   set_target_properties(bddx PROPERTIES IMPORTED_LOCATION ${SPOT_LIBRARY})
 endif()
 
+
 # Hybrid SOG executable
 add_executable(mc-sog main.cpp
   NewNet.cpp
@@ -73,7 +74,9 @@ add_executable(mc-sog main.cpp
         threadSOG.cpp threadSOG.h
         HybridSOG.cpp HybridSOG.h
         MCHybridSOG.cpp MCHybridSOG.h
-        ModelCheckThReq.cpp ModelCheckThReq.h)
+        ModelCheckThReq.cpp ModelCheckThReq.h md5_hash.h )
+
+target_include_directories(mc-sog PUBLIC  "${PROJECT_BINARY_DIR}")
 
 target_link_libraries(mc-sog
   bddx
diff --git a/src/CommonSOG.cpp b/src/CommonSOG.cpp
index 45c52184139a1fcd9952807007f0389eb934417a..3bf63d04027488a97f1b247047837066e540c1d0 100644
--- a/src/CommonSOG.cpp
+++ b/src/CommonSOG.cpp
@@ -2,20 +2,10 @@
 #include "SylvanWrapper.h"
 #include "CommonSOG.h"
 
-#include <stack>
+CommonSOG::CommonSOG() =default;
+CommonSOG::~CommonSOG() =default;
 
-
-const vector<class Place> *_places = NULL;
-
-CommonSOG::CommonSOG() {
-    //ctor
-}
-
-CommonSOG::~CommonSOG() {
-    //dtor
-}
-
-LDDGraph *CommonSOG::getGraph() const {
+LDDGraph *CommonSOG::getGraph()  {
     return m_graph;
 }
 
@@ -23,16 +13,12 @@ MDD CommonSOG::Accessible_epsilon(MDD From) {
     MDD M1;
     MDD M2 = From;
     do {
-
         M1 = M2;
-        for (Set::const_iterator i = m_nonObservable.begin(); !(i == m_nonObservable.end()); i++) {
+        for (auto i = m_nonObservable.begin(); !(i == m_nonObservable.end()); i++) {
             //fireTransition
             MDD succ = SylvanWrapper::lddmc_firing_mono(M2, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus());
-
             M2 = SylvanWrapper::lddmc_union_mono(M2, succ);
-
         }
-
     } while (M1 != M2);
     return M2;
 }
@@ -40,13 +26,11 @@ MDD CommonSOG::Accessible_epsilon(MDD From) {
 // Return the set of firable observable transitions from an agregate
 Set CommonSOG::firable_obs(MDD State) {
     Set res;
-    for (Set::const_iterator i = m_observable.begin(); !(i == m_observable.end()); i++) {
-        //cout<<"firable..."<<endl;
-        MDD succ = SylvanWrapper::lddmc_firing_mono(State, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus());
+    for (auto i : m_observable) {
+        MDD succ = SylvanWrapper::lddmc_firing_mono(State, m_tb_relation[i].getMinus(), m_tb_relation[i].getPlus());
         if (succ != lddmc_false) {
-            res.insert(*i);
+            res.insert(i);
         }
-
     }
     return res;
 }
@@ -58,8 +42,8 @@ MDD CommonSOG::get_successor(MDD From, int t) {
 
 MDD CommonSOG::ImageForward(MDD From) {
     MDD Res = lddmc_false;
-    for (Set::const_iterator i = m_nonObservable.begin(); !(i == m_nonObservable.end()); i++) {
-        MDD succ = SylvanWrapper::lddmc_firing_mono(From, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus());
+    for (auto i : m_nonObservable) {
+        MDD succ = SylvanWrapper::lddmc_firing_mono(From, m_tb_relation[i].getMinus(), m_tb_relation[i].getPlus());
         Res = SylvanWrapper::lddmc_union_mono(Res, succ);
     }
     return Res;
@@ -115,7 +99,7 @@ MDD CommonSOG::Canonize(MDD s, unsigned int level) {
     }
 
 
-    MDD Repr = lddmc_false;
+    MDD Repr;
 
     if (SylvanWrapper::isSingleMDD(s0)) {
         Repr = s0;
@@ -137,28 +121,6 @@ MDD CommonSOG::Canonize(MDD s, unsigned int level) {
 
 }
 
-void CommonSOG::printhandler(ostream &o, int var) {
-    o << (*_places)[var / 2].name;
-    if (var % 2) {
-        o << "_p";
-    }
-}
-
-
-vector<TransSylvan> *CommonSOG::getTBRelation() {
-    return &m_tb_relation;
-}
-
-Set *CommonSOG::getNonObservable() {
-    return &m_nonObservable;
-}
-
-
-/*********Returns the count of places******************************************/
-unsigned int CommonSOG::getPlacesCount() {
-    return m_nbPlaces;
-}
-
 /**** Detect divergence in an agregate ****/
 bool CommonSOG::Set_Div(MDD &M) const {
 
@@ -167,8 +129,7 @@ bool CommonSOG::Set_Div(MDD &M) const {
     }
     Set::const_iterator i;
     MDD Reached, From;
-    //cout<<"Ici detect divergence \n";
-    Reached = lddmc_false;
+
     From = M;
     do {
         Reached = lddmc_false;
@@ -178,12 +139,7 @@ bool CommonSOG::Set_Div(MDD &M) const {
         }
 
         if (Reached == From) {
-            /*MDD Reached_obs=lddmc_false;
-            for (i = m_observable.begin(); !(i == m_observable.end()) && (Reached_obs==lddmc_false); i++) {
-                Reached_obs= fireTransition(From, m_tb_relation[(*i)].getMinus(), m_tb_relation[(*i)].getPlus());
-            }
-            if (Reached_obs==lddmc_false) return true;*/
-            return true;
+           return true;
         }
         From = Reached;
     } while (Reached != lddmc_false);
@@ -194,9 +150,9 @@ bool CommonSOG::Set_Div(MDD &M) const {
 bool CommonSOG::Set_Bloc(MDD &M) const {
 
     MDD cur = lddmc_true;
-    for (vector<TransSylvan>::const_iterator i = m_tb_relation.begin(); i != m_tb_relation.end(); i++) {
+    for (auto i : m_tb_relation) {
 
-        cur = cur & (TransSylvan(*i).getMinus());
+        cur = cur & (i.getMinus());
 
     }
     return ((M & cur) != lddmc_false);
@@ -206,12 +162,7 @@ bool CommonSOG::Set_Bloc(MDD &M) const {
 
 
 LDDGraph *CommonSOG::m_graph;
-struct elt_t {
-    MDD cmark;
-    MDD minus;
-    MDD plus;
-    uint32_t level;
-};
+
 
 /*MDD CommonSOG::fireTransition(MDD cmark, MDD minus, MDD plus) {
     return SylvanWrapper::lddmc_firing_mono(cmark,minus,plus);
@@ -224,7 +175,6 @@ struct elt_t {
 //}
 
 string_view CommonSOG::getPlace(int pos) {
-    // cout<<"yes it is : "<<m_transitions.at(pos).name<<endl;
-    // cout<<"Ok "<<m_graph->getPlace(pos)<<endl;
+
     return string_view {m_graph->getPlace(pos)};
 }
\ No newline at end of file
diff --git a/src/CommonSOG.h b/src/CommonSOG.h
index 1598c5b00382111ba9032432e4e7e87f6b25f866..a866a05f3baa9cb728e6659ff1232fff8a40efd9 100644
--- a/src/CommonSOG.h
+++ b/src/CommonSOG.h
@@ -23,20 +23,16 @@ class CommonSOG
     public:
         CommonSOG();
         virtual ~CommonSOG();
-        LDDGraph *getGraph() const;
-        static void printhandler(ostream &o, int var);
-        vector<TransSylvan>* getTBRelation();
-        Set * getNonObservable();
-        unsigned int getPlacesCount();
+        static LDDGraph *getGraph();
+
         inline set<uint16_t> & getPlaceProposition() {return m_place_proposition;}
         inline string_view getTransition(int pos) {
             {
                 return string_view {m_transitions.at(pos).name};
             }
         }
-        string_view getPlace(int pos);
-
-
+        static string_view getPlace(int pos);
+        void finish() {m_finish=true;}
     protected:
         NewNet* m_net;
         int m_nbPlaces = 0;
@@ -60,6 +56,7 @@ class CommonSOG
         uint8_t m_nb_thread;
         std::mutex m_graph_mutex,m_gc_mutex;  
         atomic<uint8_t> m_gc;
+        volatile bool m_finish=false;
     //MDD fireTransition(MDD cmark,MDD minus, MDD plus);
     private:
 
diff --git a/src/HybridKripke.cpp b/src/HybridKripke.cpp
index 9194765858bd6a9e4d83d65b2d7c3771b8ed1eb9..1a2765ad61c3267238839bba2185f6a4f4cafa7b 100644
--- a/src/HybridKripke.cpp
+++ b/src/HybridKripke.cpp
@@ -30,12 +30,12 @@ HybridKripke::HybridKripke(const bdd_dict_ptr &dict_ptr): spot::kripke(dict_ptr)
 HybridKripke::HybridKripke(const spot::bdd_dict_ptr& dict_ptr,set<string> &l_transap,set<string> &l_placeap,NewNet &net_):HybridKripke(dict_ptr) {
     m_net=&net_;
     HybridKripkeIterator::m_net=&net_;
-    for (auto it=l_transap.begin();it!=l_transap.end();it++) {
-        register_ap(*it);
+    for (auto it:l_transap) {
+        register_ap(it);
     }
     
-    for (auto it=l_placeap.begin();it!=l_placeap.end();it++)
-        register_ap(*it);
+    for (auto it:l_placeap)
+        register_ap(it);
     
 
 }
@@ -45,15 +45,13 @@ state* HybridKripke::get_init_state() const {
     int v;
     MPI_Send( &v, 1, MPI_INT, 0, TAG_INITIAL, MPI_COMM_WORLD); 
      char message[23];
-    MPI_Status status; int nbytes;
+    MPI_Status status;
     MPI_Probe(MPI_ANY_SOURCE, TAG_ACK_INITIAL, MPI_COMM_WORLD, &status);
-    MPI_Get_count(&status, MPI_BYTE, &v);
     MPI_Recv(message, 22, MPI_BYTE,MPI_ANY_SOURCE,TAG_ACK_INITIAL,MPI_COMM_WORLD, &status);
     succ_t* elt=new succ_t;    
     memcpy(elt->id,message,16);   
     memcpy(&elt->pcontainer,message+16,2);    
     elt->_virtual=false;
-
     return new HybridKripkeState(*elt);    
 
 }
@@ -69,15 +67,15 @@ std::string HybridKripke::format_state(const spot::state* s) const
 
 HybridKripkeIterator* HybridKripke::succ_iter(const spot::state* s) const {
     //cout<<__func__<<endl;
-    auto ss = static_cast<const HybridKripkeState*>(s);    
+    auto ss = static_cast<const HybridKripkeState*>(s);
     bdd cond = state_condition(ss);
     HybridKripkeState* st=ss;
    if (iter_cache_)
     {
-      auto it = static_cast<HybridKripkeIterator*>(iter_cache_);
+     /* auto it = static_cast<HybridKripkeIterator*>(iter_cache_);
       iter_cache_ = nullptr;    // empty the cache
       it->recycle(*st,cond);
-      return it;
+      return it;*/
     }
 #ifdef TESTENABLE
     SylvanWrapper::m_agg++;
diff --git a/src/HybridKripke.h b/src/HybridKripke.h
index d8caeb85d1c1f577816fd1038b50ac3b73239cea..53f7fc9282acda08e2192a0c5215aad14c03f220 100644
--- a/src/HybridKripke.h
+++ b/src/HybridKripke.h
@@ -9,7 +9,6 @@
 
 class HybridKripke: public spot::kripke {
     public:
-
         HybridKripke(const spot::bdd_dict_ptr& dict_ptr);
         HybridKripke(const spot::bdd_dict_ptr& dict_ptr,set<string> &l_transap,set<string> &l_placeap,NewNet &net_);
         virtual ~HybridKripke();
@@ -17,13 +16,9 @@ class HybridKripke: public spot::kripke {
         HybridKripkeIterator* succ_iter(const spot::state* s) const override;
         std::string format_state(const spot::state* s) const override;
         bdd state_condition(const spot::state* s) const override;
-
-        //ModelCheckBaseMT *m_builder;
-
     protected:
 
     private:
-    std::map<int, int> place_prop;
     NewNet *m_net;
 };
 
diff --git a/src/HybridKripkeIterator.cpp b/src/HybridKripkeIterator.cpp
index 579cbb77078fdd334968833d6cb1b110fc3bb8ab..e6ffd20eefad6ed96394c227ec1bccebc0617e18 100644
--- a/src/HybridKripkeIterator.cpp
+++ b/src/HybridKripkeIterator.cpp
@@ -14,8 +14,7 @@ bool HybridKripkeIterator::first() {
 
     //cout<<"entering "<<__func__<<endl;
     m_current_edge=0;
-    
-    return m_current_state->getListSucc()->size()!=0;
+    return !m_current_state->getListSucc()->empty();
 
 }
 
diff --git a/src/HybridKripkeIterator.h b/src/HybridKripkeIterator.h
index c56a8e84ebf5d8a59b99bdd53c44c58a6801829b..8e597d8cf1092eb1dc334eb9071cccc3857e06f4 100644
--- a/src/HybridKripkeIterator.h
+++ b/src/HybridKripkeIterator.h
@@ -8,8 +8,6 @@
 class HybridKripkeIterator : public spot::kripke_succ_iterator
 {
 public:
-    static LDDState m_deadlock;
-    static LDDState m_div;
     static NewNet * m_net;
     static spot::bdd_dict_ptr* m_dict_ptr;
     
@@ -20,12 +18,12 @@ public:
     bool next() override;
     bool done() const override;
     HybridKripkeState* dst() const override;
-    bdd cond() const override final;
+    bdd cond() const override;
 
    // HybridKripkeState* current_state() const;
 
     void recycle(HybridKripkeState &st, bdd cond);   
-    std::string format_transition() const;
+
     
 
 private:
diff --git a/src/HybridKripkeState.cpp b/src/HybridKripkeState.cpp
index 80744b5d4574debd040f2ace427435e1ed0acaef..7a8966a3c3577e4a6f81c286348fb86a8be8235b 100644
--- a/src/HybridKripkeState.cpp
+++ b/src/HybridKripkeState.cpp
@@ -1,12 +1,8 @@
 #include <spot/kripke/kripke.hh>
-#include "LDDState.h"
 #include "HybridKripkeState.h"
 
 
-HybridKripkeState::~HybridKripkeState()
-{
-    //dtor
-    //cout<<__func__<<endl;
-}
+HybridKripkeState::~HybridKripkeState()=default;
+
 
 //static ModelCheckBaseMT * HybridKripkeState::m_builder;
diff --git a/src/HybridKripkeState.h b/src/HybridKripkeState.h
index e43146644de0486cda224461e004233c6e93adf7..14641f8bc3378b1194fde6be66152e4ac1247aee 100644
--- a/src/HybridKripkeState.h
+++ b/src/HybridKripkeState.h
@@ -7,9 +7,9 @@
 #include "SylvanWrapper.h"
 constexpr auto TAG_ASK_STATE = 9;
 constexpr auto TAG_ACK_STATE = 10;
-#define TAG_ASK_SUCC 4
-#define TAG_ACK_SUCC 11
-#define TAG_NOTCOMPLETED 20
+constexpr auto TAG_ASK_SUCC = 4;
+constexpr auto TAG_ACK_SUCC = 11;
+
 typedef struct {
     char id[16];
     int16_t transition;
@@ -23,7 +23,7 @@ public:
     HybridKripkeState(succ_t &e):m_container(e.pcontainer) {  
       
    if (e._virtual) { //div or deadlock
-            if (e.id[0]=='v') { // div
+            /*if (e.id[0]=='v') { // div
                 //cout<<"div created..."<<endl;
                 m_hashid=0xFFFFFFFFFFFFFFFE;
                 m_id[0]='v';
@@ -32,26 +32,25 @@ public:
                 elt.transition=-1;
                 elt._virtual=true;
                 m_succ.push_back(elt);
-            }
-            else {
+            }*/
+            /*else {*/
                 m_id[0]='d';
                 m_hashid=0xFFFFFFFFFFFFFFFF; // deadlock                
-            }
+           /* }*/
         }
         else {        
-        memcpy(m_id,e.id,16);        
+        memcpy(m_id,e.id,16);
         MPI_Send(m_id,16,MPI_BYTE,e.pcontainer, TAG_ASK_STATE, MPI_COMM_WORLD);
-        
         MPI_Status status; //int nbytes;
         MPI_Probe(MPI_ANY_SOURCE, TAG_ACK_STATE, MPI_COMM_WORLD, &status);
         uint32_t nbytes;
         MPI_Get_count(&status, MPI_BYTE, &nbytes);
         // Receive hash id =idprocess | position
         char message[nbytes];
+
         MPI_Recv(message, nbytes, MPI_BYTE,MPI_ANY_SOURCE,TAG_ACK_STATE,MPI_COMM_WORLD, &status);
-        memcpy(&m_hashid,message,8);     
-        //cout<<"Pos :"<<m_hashid<<endl;
-        //cout<<"Process :"<<m_container<<endl;
+
+        memcpy(&m_hashid,message,8);
         m_hashid=m_hashid | (size_t(m_container)<<56);
         
         // Determine Place propositions
@@ -84,9 +83,9 @@ public:
         indice++; // Added for stats
        memcpy(&m_size,message+indice,8); // Added for stats
 
-        // Get successors 
+        // Get successors
          MPI_Send(m_id,16,MPI_BYTE,m_container, TAG_ASK_SUCC, MPI_COMM_WORLD);
-   
+
      // Receive list of successors     
      
     MPI_Probe(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
@@ -120,12 +119,7 @@ public:
         el.transition=-1;
         m_succ.push_back(el);
     }
-       if (m_div) {
-           /*succ_t el;
-           el.id[0]='v';
-           el.transition=-1;
-           el._virtual=true;
-           m_succ.push_back(el);*/
+      if (m_div) {
            succ_t el=e;
           el._virtual=false;
            el.transition=-1;
@@ -180,7 +174,6 @@ protected:
 
 private:    
     char  m_id[17];
-    uint32_t m_pos; // Added for stats
     size_t m_hashid;
     bool m_div;
     bool m_deadlock;
diff --git a/src/LDDGraph.cpp b/src/LDDGraph.cpp
index 495946519429f5a98a764cc65077762a59e2772b..7af8640b6c836042aa6fe579994b522745c017fa 100644
--- a/src/LDDGraph.cpp
+++ b/src/LDDGraph.cpp
@@ -1,66 +1,63 @@
 #include "LDDGraph.h"
-
-#include <string.h>
+#include <cstring>
 #include <map>
 #include "SylvanWrapper.h"
 
-LDDGraph::~LDDGraph() {
-    //dtor
-}
+LDDGraph::~LDDGraph()=default;
 
 
 void LDDGraph::setInitialState(LDDState *c) {
-    m_currentstate = m_initialstate = c;
+   m_initialstate = c;
 }
 
 
-
 /*----------------------find()----------------*/
 LDDState *LDDGraph::find(LDDState *c) {
-    std::lock_guard<std::mutex>  lock(m_mutex);
+    std::shared_lock<std::shared_mutex> lock(m_mutex);
     for (MetaLDDNodes::const_iterator i = m_GONodes.begin(); !(i == m_GONodes.end()); i++)
         if (c->m_lddstate == (*i)->m_lddstate)
             return *i;
-    return NULL;
+    return nullptr;
 }
 
-LDDState *LDDGraph::insertFind(LDDState *c) {
-    LDDState *res = nullptr;
-    std::lock_guard<std::mutex> lock(m_mutex);
-    for (MetaLDDNodes::const_iterator i = m_GONodes.begin(); !(i == m_GONodes.end()) && res == nullptr; i++) {
-        if (c->m_lddstate == (*i)->m_lddstate)
-            res = *i;
+
+
+LDDState *LDDGraph::insertFindByMDD(MDD md, bool &found) {
+    std::lock_guard lock(m_mutex);
+    {
+
+        for (auto& i : m_GONodes) {
+            if (md == i->m_lddstate) {
+                found = true;
+                return i;
+            }
+        }
     }
-    if (res == nullptr) m_GONodes.push_back(c);
-    return res;
+    LDDState *n = new LDDState;
+    n->m_lddstate = md;
+    found = false;
+    m_GONodes.push_back(n);
+    return n;
 }
 
-/*----------------------find()----------------*/
-bool LDDGraph::cmpSHA(const unsigned char *s1, const unsigned char *s2) {
-    bool res = true;
-    for (int i = 0; i < 16 && res; i++) {
-        res = (s1[i] == s2[i]);
-    }
-    return !res;
 
-}
 
 LDDState *LDDGraph::findSHA(unsigned char *c) {
-    std::lock_guard<std::mutex> lock(m_mutex_sha);
+    std::shared_lock<std::shared_mutex> lock(m_mutex);
     for (MetaLDDNodes::const_iterator i = m_GONodes.begin(); !(i == m_GONodes.end()); i++)
         if ((*i)->isVirtual() == true)
-            if ((cmpSHA(c, (unsigned char *) (*i)->m_SHA2) == 0))
+            if (memcmp((char*)c, (char*) (*i)->m_SHA2,16) == 0)
                 return *i;
-    return NULL;
+    return nullptr;
 }
 
 /***   Try to find an aggregate by its md5 code, else it is inserted***/
 LDDState *LDDGraph::insertFindSha(unsigned char *c, LDDState *agg) {
     LDDState *res = nullptr;
-    std::lock_guard<std::mutex> lock(m_mutex_sha);
+    std::lock_guard<std::shared_mutex> lock(m_mutex);
     for (auto i = m_GONodes.begin(); !(i == m_GONodes.end()) && !res; i++) {
         if ((*i)->isVirtual() == true)
-            if ((cmpSHA(c, (unsigned char *) (*i)->m_SHA2) == 0))
+            if (memcmp((char*)c, (char*) (*i)->m_SHA2,16) == 0)
                 res = *i;
     }
     if (res == nullptr) {
@@ -73,64 +70,39 @@ LDDState *LDDGraph::insertFindSha(unsigned char *c, LDDState *agg) {
 
 /*--------------------------------------------*/
 size_t LDDGraph::findSHAPos(unsigned char *c, bool &res) {
-    size_t i = 0;
+    size_t i;
     res = false;
+    std::shared_lock<std::shared_mutex> lock(m_mutex);
     for (i = 0; i < m_GONodes.size(); i++)
-        if ((cmpSHA(c, m_GONodes.at(i)->m_SHA2) == 0)) {
+        if (memcmp(c, m_GONodes.at(i)->m_SHA2,16) == 0) {
             res = true;
             return i;
         }
-    // cout<<__func__<<" : Aggregate not found!!!"<<endl;
     return i;
 }
 
 /*----------------------insert() ------------*/
 void LDDGraph::insert(LDDState *c) {
-    std::lock_guard<std::mutex> lock(m_mutex);
+    std::lock_guard<std::shared_mutex> lock(m_mutex);
     this->m_GONodes.push_back(c);
-    //m_nbStates++;
 }
 
 
 /*----------------------insert() ------------*/
 void LDDGraph::insertSHA(LDDState *c) {
     c->setVirtual();
+    std::lock_guard<std::shared_mutex> lock(m_mutex);
     this->m_GONodes.push_back(c);
 
 }
 
-/*----------------------NbBddNod()------------------------*/
-int LDDGraph::NbBddNode(LDDState *S, size_t &nb) {
-    /*if(S->m_visited==false)
-    {
-        //cout<<"insertion du meta etat numero :"<<nb<<"son id est :"<<S->class_state.id()<<endl;
-        //cout<<"sa taille est :"<<bdd_nodecount(S->class_state)<<" noeuds \n";
-        Tab[nb-1]=S->class_state;
-        S->Visited=true;
-        int bddnode=bdd_nodecount(S->class_state);
-        int size_succ=0;
-        for(Edges::const_iterator i=S->Successors.begin();!(i==S->Successors.end());i++)
-        {
-            if((*i).first->Visited==false)
-            {
-                nb++;
-                size_succ+=NbBddNode((*i).first,nb);
-            }
-        }
-        return size_succ+bddnode;
-
-    }
-    else*/
-    cout << "Not implemented yet...." << endl;
-    return 0;
-}
 
 /*----------------------Visualisation du graphe------------------------*/
 void LDDGraph::printCompleteInformation() {
     long count_ldd = 0L;
     for (MetaLDDNodes::const_iterator i = m_GONodes.begin(); !(i == m_GONodes.end()); i++) {
         count_ldd += SylvanWrapper::lddmc_nodecount((*i)->m_lddstate);
-        m_nbMarking+= SylvanWrapper::getMarksCount((*i)->m_lddstate);
+        m_nbMarking += SylvanWrapper::getMarksCount((*i)->m_lddstate);
     }
     cout << "\n\nGRAPH SIZE : \n";
     cout << "\n\tNB LDD NODES : " << count_ldd;
@@ -142,19 +114,19 @@ void LDDGraph::printCompleteInformation() {
     cin >> c;*/
     //InitVisit(initialstate,n);
 
-   /* size_t n = 1;
-    //cout<<"NB BDD NODE : "<<NbBdm_current_state->getContainerProcess()dNode(initialstate,n)<<endl;
-    NbBddNode(m_initialstate, n);
-    // cout<<"NB BDD NODE : "<<bdd_anodecount(m_Tab,(int)m_nbStates)<<endl;
-    //cout<<"Shared Nodes : "<<bdd_anodecount(Tab,nbStates)<<endl;
-    InitVisit(m_initialstate, 1);
-    //int toto;cin>>toto;
-    //bdd Union=UnionMetaState(initialstate,1);
-    //cout<<"a titre indicatif taille de l'union : "<<bdd_nodecount(Union)<<endl;
-    if (c == 'y' || c == 'Y') {
-        size_t n = 1;
-        printGraph(m_initialstate, n);
-    }*/
+    /* size_t n = 1;
+     //cout<<"NB BDD NODE : "<<NbBdm_current_state->getContainerProcess()dNode(initialstate,n)<<endl;
+     NbBddNode(m_initialstate, n);
+     // cout<<"NB BDD NODE : "<<bdd_anodecount(m_Tab,(int)m_nbStates)<<endl;
+     //cout<<"Shared Nodes : "<<bdd_anodecount(Tab,nbStates)<<endl;
+     InitVisit(m_initialstate, 1);
+     //int toto;cin>>toto;
+     //bdd Union=UnionMetaState(initialstate,1);
+     //cout<<"a titre indicatif taille de l'union : "<<bdd_nodecount(Union)<<endl;
+     if (c == 'y' || c == 'Y') {
+         size_t n = 1;
+         printGraph(m_initialstate, n);
+     }*/
 }
 
 /*----------------------InitVisit()------------------------*/
@@ -196,16 +168,6 @@ void LDDGraph::printGraph(LDDState *s, size_t &nb) {
 }
 
 
-/*---------void print_successors_class(Class_Of_State *)------------*/
-void LDDGraph::printsuccessors(LDDState *s) {
-    cout << "Not implemented yet!" << endl;
-}
-
-/*---------void printpredescessors(Class_Of_State *)------------*/
-void LDDGraph::printpredecessors(LDDState *s) {
-    cout << "Not implemented yet!" << endl;
-}
-
 /*** Giving a position in m_GONodes Returns an LDDState ****/
 LDDState *LDDGraph::getLDDStateById(unsigned int id) {
     return m_GONodes.at(id);
diff --git a/src/LDDGraph.h b/src/LDDGraph.h
index aebec6ee675879417e6b58993b841895135b593b..0541ce16b2f7ce0d992cdbf25115af6b76c48daa 100755
--- a/src/LDDGraph.h
+++ b/src/LDDGraph.h
@@ -3,6 +3,7 @@
 #include "LDDState.h"
 #include "CommonSOG.h"
 #include <mutex>
+#include <shared_mutex>
 #include <atomic>
 //#include "LDDStateExtend.h"
 using namespace std;
@@ -15,8 +16,7 @@ class CommonSOG;
 class LDDGraph
 {
     private:
-        mutable std::mutex m_mutex;
-        mutable std::mutex m_mutex_sha;
+        mutable std::shared_mutex m_mutex;
         map<string,uint16_t>* m_transition;
         map<uint16_t,string>* m_places;
 		void printGraph(LDDState *, size_t &);
@@ -29,33 +29,26 @@ class LDDGraph
         void setTransition(map<string,uint16_t>& list_transitions);
         MetaLDDNodes m_GONodes;
         LDDState *getLDDStateById(unsigned int id);
-		void Reset();
 		LDDState *m_initialstate=nullptr;
-		LDDState *m_currentstate;
         uint64_t m_nbStates;
 		uint64_t m_nbMarking;
 		atomic<uint32_t> m_nbArcs;
 		LDDState* find(LDDState*);
-        LDDState* insertFind(LDDState*);
+        LDDState* insertFindByMDD(MDD,bool&);
 		LDDState* findSHA(unsigned char*);
 		LDDState* insertFindSha(unsigned char*,LDDState*);
         size_t findSHAPos(unsigned char*,bool &res);
-		bool cmpSHA(const unsigned char *s1, const unsigned char *s2);
 		void insertSHA(LDDState *c);
-		LDDEdges& get_successor(LDDState*);
-		void printsuccessors(LDDState *);
-		int NbBddNode(LDDState*,size_t&);
 		void InitVisit(LDDState * S,size_t nb);
-		void printpredecessors(LDDState *);
+
 		inline void addArc()  {m_nbArcs++;}
 		void insert(LDDState*);
-		LDDGraph(CommonSOG *constuctor) {m_nbArcs=m_nbMarking=0;m_constructor=constuctor;}
+		explicit LDDGraph(CommonSOG *constuctor) {m_nbArcs=m_nbMarking=0;m_constructor=constuctor;}
 		void setInitialState(LDDState*);  //Define the initial state of this graph
-		//LDDState* getInitialState() const;
         LDDState *getInitialState() const {
             return m_GONodes.at(0);
         }
-        LDDState *getInitialAggregate() {
+        LDDState *getInitialAggregate() const {
             return m_initialstate;
         }
 		void printCompleteInformation();
diff --git a/src/LDDState.cpp b/src/LDDState.cpp
index d48f621681a714da6731cb8efd0209076842678f..b92653a9f4a45ea3f00fc5abce013970832fa99a 100644
--- a/src/LDDState.cpp
+++ b/src/LDDState.cpp
@@ -1,13 +1,10 @@
 
 #include "LDDState.h"
 #include "LDDGraph.h"
-#include <iostream>
 #include "SylvanWrapper.h"
 
-LDDState::~LDDState()
-{
-    //dtor
-}
+LDDState::~LDDState()=default;
+
 void LDDState::setLDDValue(MDD m) {
     m_lddstate=m;
 }
@@ -60,4 +57,10 @@ vector<uint16_t> LDDState::getUnmarkedPlaces(set<uint16_t>& lplacesAP) {
     return result;
 }
 
+uint8_t LDDState::getMCurrentLevel() const {
+    return m_currentLevel;
+}
 
+void LDDState::setMCurrentLevel(uint8_t mCurrentLevel) {
+    m_currentLevel = max(m_currentLevel,mCurrentLevel);
+}
diff --git a/src/LDDState.h b/src/LDDState.h
index e261f9e4ab62207cfc29e84d4874cd5b57cdf0c6..d9c448099af63c05e938ebd0538800c51dd82854 100755
--- a/src/LDDState.h
+++ b/src/LDDState.h
@@ -4,6 +4,7 @@
 #include <set>
 #include <vector>
 #include <string>
+#include <atomic>
 #include "SylvanWrapper.h"
 using namespace std;
 
@@ -14,14 +15,13 @@ class LDDState {
 
   LDDState() {
     m_boucle = m_blocage = m_visited = false;m_completed=false;
+    m_currentLevel=0;m_nbSuccessorsToBeProcessed=0;
     m_virtual = false;
   }
   virtual ~LDDState();
-  Set firable;
-  void* Class_Appartenance;
   vector<pair<LDDState*, int>>* getSuccessors();
   vector<pair<LDDState*, int> > Predecessors, Successors;
-  pair<LDDState*, int> LastEdge;
+
   void setLDDValue(MDD m);
   MDD getLDDValue();
   MDD m_lddstate=0;
@@ -29,8 +29,6 @@ class LDDState {
   unsigned char* getSHAValue();
   bool m_boucle=false;
   bool m_blocage=false;
-
-
   bool isVirtual() {return m_virtual;}
   void setVirtual(){m_virtual=true;}
   void setDiv(bool di) {m_boucle=di;}
@@ -38,19 +36,28 @@ class LDDState {
   void setDeadLock(bool de) {m_blocage=de;}
   bool isDeadLock() {return m_blocage;}
   inline void setVisited() {m_visited=true;}
-  inline bool isVisited() {return m_visited;}
+  [[nodiscard]] inline bool isVisited() const {return m_visited;}
   void setCompletedSucc() {m_completed=true;}
   bool isCompletedSucc() {return m_completed;}
   vector<uint16_t> getMarkedPlaces(set<uint16_t>& lplacesAP);
   vector<uint16_t> getUnmarkedPlaces(set<uint16_t>& lplacesAP);
   void setProcess(uint16_t v) {m_process=v;}
-  uint16_t getProcess() {return m_process;}
+  [[nodiscard]] uint16_t getProcess() const {return m_process;}
+  inline void decNbSuccessors() {m_nbSuccessorsToBeProcessed--;}
  protected:
  private:
   bool m_virtual = false;
   bool m_visited=false;
   volatile bool m_completed=false;
   uint16_t m_process=0;
+  uint8_t  m_currentLevel;
+
+public:
+    atomic<uint32_t> m_nbSuccessorsToBeProcessed;
+
+public:
+    [[nodiscard]] uint8_t getMCurrentLevel() const;
+    void setMCurrentLevel(uint8_t mCurrentLevel);
 };
 
 typedef pair<LDDState*, int> LDDEdge;
diff --git a/src/MCHybridSOG.cpp b/src/MCHybridSOG.cpp
index e02c0a8769bdd12a26f88ee7a325781d22a685e5..c1bc2634394a1c43d18235308f7b3bce3fe420e8 100644
--- a/src/MCHybridSOG.cpp
+++ b/src/MCHybridSOG.cpp
@@ -5,7 +5,7 @@
 #include <cstdio>
 
 #include <openssl/md5.h>
-
+#include "md5_hash.h"
 
 #define LENGTH_ID 16
 //#define LENGTH_MSG 180
@@ -21,318 +21,282 @@
 #define TAG_ACK_SUCC 11
 
 //#define DEBUG_GC 1
-
+#define REDUCE 1
 using namespace std;
-MCHybridSOG::MCHybridSOG ( const NewNet &R,MPI_Comm &comm_world,bool init )
-{
 
-    m_comm_world=comm_world;
-    SylvanWrapper::sylvan_set_limits ( 16LL<<30, 8, 0 );
+MCHybridSOG::MCHybridSOG(const NewNet &R, MPI_Comm &comm_world, bool init) {
+
+    m_comm_world = comm_world;
+    SylvanWrapper::sylvan_set_limits(16LL << 29, 8, 0);
 
     //sylvan_init_package();
     SylvanWrapper::sylvan_init_package();
     SylvanWrapper::sylvan_init_ldd();
     SylvanWrapper::init_gc_seq();
+    SylvanWrapper::lddmc_refs_init();
     SylvanWrapper::displayMDDTableInfo();
-    m_net=&R;
+    m_net = &R;
 
-    m_init=init;
-    m_nbPlaces=R.places.size();
+    m_init = init;
+    m_nbPlaces = R.places.size();
     int i, domain;
     vector<Place>::const_iterator it_places;
 
     //#init_gc_seq();
     //_______________
-    m_transitions=R.transitions;
-    m_observable=R.Observable;
-    m_nonObservable=R.NonObservable;
-    m_place_proposition=R.m_formula_place;
-    m_transitionName=&R.transitionName;
-    m_placeName=&R.m_placePosName;
-    InterfaceTrans=R.InterfaceTrans;
-
-    m_nbPlaces=R.places.size();
-    cout<<"Nombre de places : "<<m_nbPlaces<<endl;
-    cout<<"Derniere place : "<<R.places[m_nbPlaces-1].name<<endl;
+    m_transitions = R.transitions;
+    m_observable = R.Observable;
+    m_nonObservable = R.NonObservable;
+    m_place_proposition = R.m_formula_place;
+    m_transitionName = &R.transitionName;
+    m_placeName = &R.m_placePosName;
+    InterfaceTrans = R.InterfaceTrans;
+
+    m_nbPlaces = R.places.size();
+    cout << "Nombre de places : " << m_nbPlaces << endl;
+    cout << "Derniere place : " << R.places[m_nbPlaces - 1].name << endl;
     // place domain, place bvect, place initial marking and place name
 
-    uint32_t * liste_marques=new uint32_t[R.places.size()];
-    for ( i=0,it_places=R.places.begin(); it_places!=R.places.end(); i++,it_places++ ) {
-        liste_marques[i] =it_places->marking;
+    uint32_t *liste_marques = new uint32_t[R.places.size()];
+    for (i = 0, it_places = R.places.begin(); it_places != R.places.end(); i++, it_places++) {
+        liste_marques[i] = it_places->marking;
     }
-    m_initialMarking=SylvanWrapper::lddmc_cube ( liste_marques,R.places.size() );
+    m_initialMarking = SylvanWrapper::lddmc_cube(liste_marques, R.places.size());
     //SylvanWrapper::lddmc_refs_push( m_initialMarking );
 
-    delete []liste_marques;
+    delete[]liste_marques;
     // place names
 
 
 
-    uint32_t *prec = new uint32_t[m_nbPlaces];
-    uint32_t *postc= new uint32_t [m_nbPlaces];
+    auto *prec = new uint32_t[m_nbPlaces];
+    auto *postc = new uint32_t[m_nbPlaces];
     // Transition relation
 
-    for ( vector<Transition>::const_iterator t=R.transitions.begin();
-            t!=R.transitions.end(); t++ ) {
+    for (vector<Transition>::const_iterator t = R.transitions.begin();
+         t != R.transitions.end(); t++) {
         // Initialisation
-        for ( i=0; i<m_nbPlaces; i++ ) {
-            prec[i]=0;
-            postc[i]=0;
+        for (i = 0; i < m_nbPlaces; i++) {
+            prec[i] = 0;
+            postc[i] = 0;
         }
         // Calculer les places adjacentes a la transition t
         set<int> adjacentPlace;
-        for ( vector< pair<int,int> >::const_iterator it=t->pre.begin(); it!=t->pre.end(); it++ ) {
-            adjacentPlace.insert ( it->first );
+        for (vector<pair<int, int> >::const_iterator it = t->pre.begin(); it != t->pre.end(); it++) {
+            adjacentPlace.insert(it->first);
             prec[it->first] = prec[it->first] + it->second;
 
         }
         // arcs post
-        for ( vector< pair<int,int> >::const_iterator it=t->post.begin(); it!=t->post.end(); it++ ) {
-            adjacentPlace.insert ( it->first );
-            postc[it->first] = postc[it->first] + it->second;
+        for (auto it : t->post) {
+            adjacentPlace.insert(it.first);
+            postc[it.first] = postc[it.first] + it.second;
         }
 
-        MDD _minus=SylvanWrapper::lddmc_cube ( prec,m_nbPlaces );
+        MDD _minus = SylvanWrapper::lddmc_cube(prec, m_nbPlaces);
         //SylvanWrapper::lddmc_refs_push ( _minus );
 
-        MDD _plus=SylvanWrapper::lddmc_cube ( postc,m_nbPlaces );
-      //  SylvanWrapper::lddmc_refs_push ( _plus );
-        m_tb_relation.push_back ( TransSylvan ( _minus,_plus ) );
+        MDD _plus = SylvanWrapper::lddmc_cube(postc, m_nbPlaces);
+        //  SylvanWrapper::lddmc_refs_push ( _plus );
+        m_tb_relation.emplace_back(TransSylvan(_minus, _plus));
     }
     //sylvan_gc_seq();
-    delete [] prec;
-    delete [] postc;
+    delete[] prec;
+    delete[] postc;
 
 }
 
+void *MCHybridSOG::doCompute() {
 
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////// Version distribu�e en utilisant les LDD - MPI/////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-void *MCHybridSOG::doCompute()
-{
-    int min_charge=1;
     int id_thread;
 
-    id_thread=m_id_thread++;
+    id_thread = m_id_thread++;
 
     unsigned char Identif[20];
-    m_Terminated=false;
+    m_Terminated = false;
 
     /****************************************** initial state ********************************************/
-    if ( task_id==0 && id_thread==0 ) {
-        string* chaine=new string();
-
-
-        LDDState *c=new LDDState;
-        MDD Complete_meta_state=Accessible_epsilon ( m_initialMarking );
-        c->m_lddstate=Complete_meta_state;
+    if (task_id == 0 && id_thread == 0) {
+        string *chaine = new string();
+        LDDState *c = new LDDState;
+        MDD Complete_meta_state = Accessible_epsilon(m_initialMarking);
+        c->m_lddstate = Complete_meta_state;
         //SylvanWrapper::lddmc_refs_push ( Complete_meta_state );
         //   MDD reduced_initialstate=Canonize(Complete_meta_state,0);
 
-        SylvanWrapper::convert_wholemdd_stringcpp ( Complete_meta_state,*chaine );
-        get_md5 ( *chaine,Identif );
-        //lddmc_getsha(Complete_meta_state, Identif);
-        uint16_t destination= ( uint16_t ) ( Identif[0]%n_tasks );
-        c->setProcess ( destination );
-        if ( destination==0 ) {
+        SylvanWrapper::convert_wholemdd_stringcpp(Complete_meta_state, *chaine);
+        md5_hash::compute(*chaine, Identif);
+
 
+        //lddmc_getsha(Complete_meta_state, Identif);
+        auto destination = (uint16_t) (Identif[0] % n_tasks);
+        c->setProcess(destination);
+        if (destination == 0) {
             m_nbmetastate++;
-            Set fire=firable_obs ( Complete_meta_state );
-            m_st[1].push ( Pair ( couple ( c,Complete_meta_state ),fire ) );
-            m_graph->setInitialState ( c );
-            m_graph->insert ( c );
-            m_charge[1]++;
-            memcpy ( c->m_SHA2,Identif,16 );
+            Set fire = firable_obs(Complete_meta_state);
+            m_graph->setInitialState(c);
+            m_graph->insert(c);
+            memcpy(c->m_SHA2, Identif, 16);
+            m_common_stack.push(Pair(couple(c, Complete_meta_state), fire));
+            m_condStack.notify_one();
         } else {
-            MDD initialstate=Complete_meta_state;
-            //cout<<"Initial marking is sent"<<endl;
-            m_graph->insertSHA ( c );
-            memcpy ( c->m_SHA2,Identif,16 );
-            initialstate=Canonize ( Complete_meta_state,0 );
-
-            //#endif // REDUCE
-            SylvanWrapper::convert_wholemdd_stringcpp ( initialstate,*chaine );
-
+            MDD initialstate = Complete_meta_state;
+            m_graph->insertSHA(c);
+            memcpy(c->m_SHA2, Identif, 16);
+            initialstate = Canonize(Complete_meta_state, 0);
+            //initialstate = Complete_meta_state;
+            SylvanWrapper::convert_wholemdd_stringcpp(initialstate, *chaine);
+            m_tosend_msg.push(MSG(chaine, destination));
 
-            pthread_mutex_lock ( &m_spin_msg[0] );
-            m_msg[0].push ( MSG ( chaine,destination ) );
-            pthread_mutex_unlock ( &m_spin_msg[0] );
-            //delete c;
         }
     }
 
 
-    while ( m_Terminated==false ) {
 
-        /******************************* envoie et reception des aggregats ************************************/
-
-        if ( id_thread==0 ) {
 
+        /******************************* envoie et reception des aggregats ************************************/
+        string chaine;
+        if (id_thread == 0) {
             do {
                 send_state_message();
                 read_message();
-                if ( m_waitingBuild ) {
+                if (m_waitingBuildSucc==state::waitingBuild) {
                     bool res;
-                    size_t pos=m_graph->findSHAPos ( m_id_md5,res );
-                    if ( res ) {
-                        m_waitingBuild=false;
-                        m_aggWaiting=m_graph->getLDDStateById ( pos );
-                        m_waitingSucc=true;
-                        // cout<<"Get build..."<<endl;
+                    size_t pos = m_graph->findSHAPos(m_id_md5, res);
+                    if (res) {
+                        m_waitingBuildSucc=state::waitingSucc;
+                        m_aggWaiting = m_graph->getLDDStateById(pos);
                     }
-
                 }
-                if ( m_waitingSucc ) {
-
-                    if ( m_aggWaiting->isCompletedSucc() ) {
-                        //cout<<"Get succ..."<<endl;
-                        m_waitingSucc=false;
+                if (m_waitingBuildSucc==state::waitingSucc) {
+                    if (m_aggWaiting->isCompletedSucc()) {
+                        m_waitingBuildSucc = state::waitInitial;
                         sendSuccToMC();
                     }
                 }
-                if ( m_waitingAgregate ) {
-                    bool res=false;
-                    size_t pos=m_graph->findSHAPos ( m_id_md5,res );
-                    if ( res ) {
-                        m_waitingAgregate=false;
-                        sendPropToMC ( pos );
+                if (m_waitingAgregate) {
+                    bool res = false;
+                    size_t pos = m_graph->findSHAPos(m_id_md5, res);
+                    if (res) {
+                        m_waitingAgregate = false;
+                        sendPropToMC(pos);
                     }
                 }
-            } while ( !m_Terminated );
+
+            } while (!m_Terminated);
+
         }
-        /******************************* Construction des aggregats ************************************/
+            /******************************* Construction des aggregats ************************************/
 
         else {
-            if ( !m_st[id_thread].empty() || !m_msg[id_thread].empty() ) {
-                if ( id_thread>1 ) {
-                    if ( ++m_gc==1 ) {
-                        m_gc_mutex.lock();
-                    }
+            while (m_Terminated == false) {
+            std::unique_lock<std::mutex> lk(m_mutexCond);
+            m_condStack.wait(lk, [this] { return !m_common_stack.empty() || !m_received_msg.empty() || m_Terminated; });
+            lk.unlock();
+
+            /*if ( id_thread>1 ) {
+                if ( ++m_gc==1 ) {
+                    m_gc_mutex.lock();
                 }
-
-                if ( !m_st[id_thread].empty() ) {
-                    Pair  e;
-                    pthread_mutex_lock ( &m_spin_stack[id_thread] );
-                    e=m_st[id_thread].top();
-                    m_st[id_thread].pop();
-                    pthread_mutex_unlock ( &m_spin_stack[id_thread] );
-                    m_charge[id_thread]--;
-                    LDDState *reached_class=NULL;
-                    while ( !e.second.empty() ) {
-                        int t = * ( e.second.begin() );
-                        e.second.erase ( t );
-                        reached_class=new LDDState();
-
-
-                        MDD ldd_reachedclass=Accessible_epsilon ( get_successor ( e.first.second,t ) );
-                       // SylvanWrapper::lddmc_refs_push ( ldd_reachedclass );
+            }*/
+            if (!m_Terminated) {
+                Pair e;
+                if (m_common_stack.try_pop(e)) {
+                    while (!e.second.empty() && !m_Terminated) {
+                        int t = *(e.second.begin());
+                        e.second.erase(t);
+                        MDD ldd_reachedclass = Accessible_epsilon(get_successor(e.first.second, t));
+                        // SylvanWrapper::lddmc_refs_push ( ldd_reachedclass );
 
                         //if ( id_thread==1 ) {
-                            //displayMDDTableInfo();
-                            //if ( SylvanWrapper::isGCRequired() ) {
-                           //     m_gc_mutex.lock();
+                        //displayMDDTableInfo();
+                        //if ( SylvanWrapper::isGCRequired() ) {
+                        //     m_gc_mutex.lock();
 //#ifdef DEBUG_GC
 
-                             //   SylvanWrapper::displayMDDTableInfo();
+                        // SylvanWrapper::displayMDDTableInfo();
 //#endif // DEBUG_GC
-                               //SylvanWrapper::sylvan_gc_seq();
+                        //SylvanWrapper::sylvan_gc_seq();
 //#ifdef DEBUG_GC
 
-                               // SylvanWrapper::displayMDDTableInfo();
+                        // SylvanWrapper::displayMDDTableInfo();
 //#endif // DEBUG_GC
-                                //m_gc_mutex.unlock();
-                           // }
+                        //m_gc_mutex.unlock();
+                        // }
 
 
                         //pthread_spin_unlock(&m_spin_md5);
 
-                        reached_class->m_lddstate=ldd_reachedclass;
+
 
                         //MDD Reduced=Canonize(ldd_reachedclass,0);
                         // ldd_refs_push(Reduced);
 
                         //MDD Reduced=ldd_reachedclass;
-                        string* message_to_send1=new string();
-                        SylvanWrapper::convert_wholemdd_stringcpp ( ldd_reachedclass,*message_to_send1 );
-                        get_md5 ( *message_to_send1,Identif );
-
-
-                        //lddmc_getsha(ldd_reachedclass, Identif);
-
-                        uint16_t destination= ( uint16_t ) ( Identif[0]%n_tasks );
-
+                        string *message_to_send1 = new string();
+                        SylvanWrapper::convert_wholemdd_stringcpp(ldd_reachedclass, *message_to_send1);
+                        md5_hash::compute(*message_to_send1, Identif);
+                        uint16_t destination = (uint16_t) (Identif[0] % n_tasks);
                         /**************** construction local ******/
                         // cout<<"debut boucle pile process "<<task_id<< " thread "<< id_thread<<endl;
-                        reached_class->setProcess ( destination );
-                        if ( destination==task_id ) {
-                            //      cout << " construction local de l'aggregat " <<endl;
-
-                            LDDState* pos=m_graph->insertFind(reached_class );
-                            if ( !pos ) {
-                                //cout<<"enter A"<<endl;
-                                reached_class->setDiv ( Set_Div ( ldd_reachedclass ) );
-                                reached_class->setDeadLock ( Set_Bloc ( ldd_reachedclass ) );
-                                memcpy ( reached_class->m_SHA2,Identif,16 );
-                                m_graph_mutex.lock();
-                                e.first.first->Successors.insert ( e.first.first->Successors.begin(),LDDEdge ( reached_class,t ) );
-                                reached_class->Predecessors.insert ( reached_class->Predecessors.begin(),LDDEdge ( e.first.first,t ) );
-                                m_graph_mutex.unlock();
-                                m_graph->addArc();
-                                Set fire=firable_obs ( ldd_reachedclass );
-                                min_charge=minCharge();
-                                pthread_mutex_lock ( &m_spin_stack[min_charge] );
-                                m_st[min_charge].push ( Pair ( couple ( reached_class,ldd_reachedclass ),fire ) );
-                                pthread_mutex_unlock ( &m_spin_stack[min_charge] );
-                                //pthread_mutex_lock(&m_spin_charge);
-                                m_charge[min_charge]++;
 
-                            } else {
-                                //cout<<"enter B"<<endl;
-                                m_graph->addArc();
-                                m_graph_mutex.lock();
-                                e.first.first->Successors.insert ( e.first.first->Successors.begin(),LDDEdge ( pos,t ) );
-                                pos->Predecessors.insert ( pos->Predecessors.begin(),LDDEdge ( e.first.first,t ) );
-                                m_graph_mutex.unlock();
-                                delete reached_class;
-                                //cout<<"quit B"<<endl;
+                        if (destination == task_id) {
+                            bool res = false;
+                            //= m_graph->insertFind(reached_class);
+                            LDDState *pos = m_graph->insertFindByMDD(ldd_reachedclass, res);
+                            if (!res) {
+                                pos->setProcess(task_id);
+                                pos->setDiv(Set_Div(ldd_reachedclass));
+                                pos->setDeadLock(Set_Bloc(ldd_reachedclass));
+                                memcpy(pos->m_SHA2, Identif, 16);
+                                Set fire = firable_obs(pos->m_lddstate);
+                                m_common_stack.push(Pair(couple(pos, pos->m_lddstate), fire));
+                                m_condStack.notify_one();
+                            }
+                            m_graph->addArc();
+                            {
+                                std::scoped_lock<std::mutex> guard(m_graph_mutex);
+                                e.first.first->Successors.insert(e.first.first->Successors.begin(),
+                                                                 LDDEdge(pos, t));
+                                pos->Predecessors.insert(pos->Predecessors.begin(), LDDEdge(e.first.first, t));
                             }
 
+
                         }
-                        /**************** construction externe ******/
+                            /**************** construction externe ******/
                         else { // send to another process
-
-                            LDDState* posV=m_graph->insertFindSha( Identif,reached_class );
-                            if ( !posV ) {
+                            LDDState *reached_class = new LDDState;
+                            reached_class->m_lddstate = ldd_reachedclass;
+                            reached_class->setProcess(destination);
+                            LDDState *posV = m_graph->insertFindSha(Identif, reached_class);
+                            if (!posV) {
                                 MDD reached{ldd_reachedclass};
-
+                                reached = Canonize(ldd_reachedclass, 0);
 #ifndef REDUCE
-                                reached=Canonize ( ldd_reachedclass,0 );
-                               // SylvanWrapper::lddmc_refs_push( reached );
+                                reached = Canonize(ldd_reachedclass, 0);
+                                // SylvanWrapper::lddmc_refs_push( reached );
 #endif
 
-                                //MDD Reduced=ldd_reachedclass;
-                                string* message_to_send2=new string();
-                                SylvanWrapper::convert_wholemdd_stringcpp ( reached,*message_to_send2 );
+                                string *message_to_send2 = new string();
+                                SylvanWrapper::convert_wholemdd_stringcpp(reached, *message_to_send2);
                                 m_graph->addArc();
                                 m_graph_mutex.lock();
-                                e.first.first->Successors.insert ( e.first.first->Successors.begin(),LDDEdge ( reached_class,t ) );
-                                reached_class->Predecessors.insert ( reached_class->Predecessors.begin(),LDDEdge ( e.first.first,t ) );
+                                e.first.first->Successors.insert(e.first.first->Successors.begin(),
+                                                                 LDDEdge(reached_class, t));
+                                reached_class->Predecessors.insert(reached_class->Predecessors.begin(),
+                                                                   LDDEdge(e.first.first, t));
                                 m_graph_mutex.unlock();
-                                pthread_mutex_lock ( &m_spin_msg[0] );
-                                m_msg[0].push ( MSG ( message_to_send2,destination ) );
-                                pthread_mutex_unlock ( &m_spin_msg[0] );
+                                m_tosend_msg.push(MSG(message_to_send2, destination));
                                 //cout<<"quit  C"<<endl;
                             } else {
                                 //cout<<"sha found "<<endl;
                                 m_graph->addArc();
-                                m_graph_mutex.lock();
-                                e.first.first->Successors.insert ( e.first.first->Successors.begin(),LDDEdge ( posV,t ) );
-                                posV->Predecessors.insert ( posV->Predecessors.begin(),LDDEdge ( e.first.first,t ) );
-                                m_graph_mutex.unlock();
+                                {
+                                    std::scoped_lock<std::mutex> guard(m_graph_mutex);
+                                    e.first.first->Successors.insert(e.first.first->Successors.begin(),
+                                                                     LDDEdge(posV, t));
+                                    posV->Predecessors.insert(posV->Predecessors.begin(), LDDEdge(e.first.first, t));
+                                }
                                 delete reached_class;
                             }
                         }
@@ -340,418 +304,256 @@ void *MCHybridSOG::doCompute()
                     e.first.first->setCompletedSucc();
                 }
 
-
                 /******************************* Construction des aggregats � partir de pile de messages ************************************/
-
-                if ( !m_msg[id_thread].empty() ) {
-                    MSG popped_msg;
-                    pthread_mutex_lock ( &m_spin_msg[id_thread] );
-                    popped_msg=m_msg[id_thread].top();
-                    m_msg[id_thread].pop();
-                    pthread_mutex_unlock ( &m_spin_msg[id_thread] );
-
-                    m_charge[id_thread]--;
-                    MDD receivedLDD=decodage_message ( popped_msg.first->c_str() );
+                MSG popped_msg;
+                if (m_received_msg.try_pop(popped_msg)) {
+                    MDD receivedLDD = decodage_message(popped_msg.first->c_str());
                     delete popped_msg.first;
-                    LDDState* Agregate=new LDDState();
-                    MDD MState=Accessible_epsilon ( receivedLDD );
-                    Agregate->m_lddstate=MState;
-                    if ( !m_graph->insertFind( Agregate ) ) {
-                        //cout<<"enter D"<<endl;
-                        //#ldd_refs_push ( MState );
-                        Agregate->setDiv ( Set_Div ( MState ) );
-                        Agregate->setDeadLock ( Set_Bloc ( MState ) );
-                        Agregate->setProcess ( task_id );
-                        //m_graph_mutex.lock();
-                        string* chaine=new string();
-                        SylvanWrapper::convert_wholemdd_stringcpp ( MState,*chaine );
-                        get_md5 ( *chaine,Identif );
-                        delete chaine;
-                        memcpy ( Agregate->m_SHA2,Identif,16 );
-                        //m_graph_mutex.unlock();
-                        Set fire=firable_obs ( MState );
-                        min_charge=minCharge();
-                        pthread_mutex_lock ( &m_spin_stack[min_charge] );
-                        m_st[min_charge].push ( Pair ( couple ( Agregate,MState ),fire ) );
-                        pthread_mutex_unlock ( &m_spin_stack[min_charge] );
-                        m_charge[min_charge]++;
-                        //cout<<"quit D"<<endl;
-                    }
-                    else {
-                        delete Agregate;
+                    MDD MState = Accessible_epsilon(receivedLDD);
+                    bool res = false;
+                    LDDState *Agregate = m_graph->insertFindByMDD(MState, res);
+                    if (!res) {
+                        Agregate->setDiv(Set_Div(MState));
+                        Agregate->setDeadLock(Set_Bloc(MState));
+                        Agregate->setProcess(task_id);
+                        SylvanWrapper::convert_wholemdd_stringcpp(MState, chaine);
+                        md5_hash::compute(chaine, Identif);
+                        memcpy(Agregate->m_SHA2, Identif, 16);
+                        Set fire = firable_obs(MState);
+                        m_common_stack.push(Pair(couple(Agregate, MState), fire));
+                        m_condStack.notify_one();
                     }
                 }
 
-                if ( id_thread>1 ) {
-                    if ( --m_gc==0 ) {
-                        m_gc_mutex.unlock();
-                    }
+                /*    if ( id_thread>1 ) {
+                        if ( --m_gc==0 ) {
+                            m_gc_mutex.unlock();
+                        }
 
-                }
+                    }*/
 
 
-            } // End    while (m_msg[id_thread].size()>0 || m_st[id_thread].size()>0);
 
-            // }
 
+                // }
 
+            }
         }    /// End else
 
-       // cout<<"Working process "<<task_id<<" leaved...thread "<<id_thread<<endl;
+        // cout<<"Working process "<<task_id<<" leaved...thread "<<id_thread<<endl;
 
     }
 
-  //  cout<<"Finnnnnn...."<<endl;
+    //  cout<<"Finnnnnn...."<<endl;
 }
 
 
+void MCHybridSOG::read_message() {
+    int flag = 0;
 
+    MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &m_status); // exist a msg to receiv?
+//    int nbytes;
+//    MPI_Get_count(&m_status, MPI_CHAR, &nbytes);
+//    cout<<"Count of bytes "<<nbytes<<endl;
+    while (flag != 0) {
 
-void MCHybridSOG::read_message()
-{
-    int flag=0;
-    MPI_Iprobe ( MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&flag,&m_status ); // exist a msg to receiv?
-    while ( flag!=0 ) {
-        //cout<<"message tag :"<<m_status.MPI_TAG<<" by task "<<task_id<<endl;
-        if ( m_status.MPI_TAG==TAG_ASK_STATE ) {
+        if (m_status.MPI_TAG == TAG_ASK_STATE) {
             //cout<<"TAG ASKSTATE received by task "<<task_id<<" from "<<m_status.MPI_SOURCE<<endl;
             char mess[17];
-            MPI_Recv ( mess,16,MPI_BYTE,m_status.MPI_SOURCE,m_status.MPI_TAG,MPI_COMM_WORLD,&m_status );
+            MPI_Recv(mess, 16, MPI_BYTE, m_status.MPI_SOURCE, m_status.MPI_TAG, MPI_COMM_WORLD, &m_status);
             bool res;
-            m_waitingAgregate=false;
-            size_t pos=m_graph->findSHAPos ( mess,res );
-            if ( !res ) {
-                //cout<<"Not found"<<endl;
-                m_waitingAgregate=true;
-                memcpy ( m_id_md5,mess,16 );
+            m_waitingAgregate = false;
+            size_t pos = m_graph->findSHAPos(mess, res);
+            if (!res) {
+                m_waitingAgregate = true;
+                memcpy(m_id_md5, mess, 16);
             } else {
-                sendPropToMC ( pos );
+                sendPropToMC(pos);
             }
+            //cout<<"TAG ASKSTATE completed by task "<<task_id<<" from "<<m_status.MPI_SOURCE<<endl;
 
 
-        } else if ( m_status.MPI_TAG==TAG_ASK_SUCC ) {
-
+        } else if (m_status.MPI_TAG == TAG_ASK_SUCC) {
+            //cout<<"=============================TAG_ASK_SUCC received by task "<<task_id<<endl;
             char mess[17];
-            MPI_Recv ( mess,16,MPI_BYTE,m_status.MPI_SOURCE,m_status.MPI_TAG,MPI_COMM_WORLD,&m_status );
-            m_waitingBuild=false;
-            m_waitingSucc=false;
+            MPI_Recv(mess, 16, MPI_BYTE, m_status.MPI_SOURCE, m_status.MPI_TAG, MPI_COMM_WORLD, &m_status);
+            m_waitingBuildSucc=state::waitInitial;
             bool res;
-            //cout<<"Before "<<res<<endl;
-            size_t pos=m_graph->findSHAPos ( mess,res );
-            //cout<<"After "<<res<<endl;
-            if ( res ) {
-                LDDState *aggregate=m_graph->getLDDStateById ( pos );
-                m_aggWaiting=aggregate;
-                if ( aggregate->isCompletedSucc() ) {
+
+            size_t pos = m_graph->findSHAPos(mess, res);
+
+            if (res) {
+                m_aggWaiting = m_graph->getLDDStateById(pos);
+                if (m_aggWaiting->isCompletedSucc()) {
                     sendSuccToMC();
                 } else {
-                    m_waitingSucc=true;
-                    //cout<<"Waiting for succ..."<<endl;
+                    m_waitingBuildSucc=state::waitingSucc;
                 }
             } else {
-                m_waitingBuild=true;
-                //cout<<"Waiting for build..."<<endl;
-                memcpy ( m_id_md5,mess,16 );
+                m_waitingBuildSucc=state::waitingBuild;
+                memcpy(m_id_md5, mess, 16);
             }
-
         }
-        int v;
-        switch ( m_status.MPI_TAG ) {
-        case TAG_STATE:
-            //cout<<"=============================TAG STATE received by task "<<task_id<<endl;
-            read_state_message();
-            break;
-        case TAG_FINISH:
-            //cout<<"TAG FINISH received by task "<<task_id<<endl;
-            MPI_Recv ( &v, 1, MPI_INT, m_status.MPI_SOURCE, m_status.MPI_TAG, MPI_COMM_WORLD, &m_status );
-            m_Terminated=true;
-            break;
-        case TAG_INITIAL:
-            // cout<<"TAG INITIAL received by task "<<task_id<<endl;
-            MPI_Recv ( &v, 1, MPI_INT, m_status.MPI_SOURCE, m_status.MPI_TAG, MPI_COMM_WORLD, &m_status );
-            LDDState *i_agregate=m_graph->getInitialState();
-            char message[22];
-            memcpy ( message,i_agregate->getSHAValue(),16 );
-            uint16_t id_p=i_agregate->getProcess();
-            memcpy ( message+16,&id_p,2 );
-            MPI_Send ( message,22,MPI_BYTE,m_status.MPI_SOURCE, TAG_ACK_INITIAL, MPI_COMM_WORLD );
-            break;
-            /*default:  cout<<"unknown received "<<m_status.MPI_TAG<<" by task "<<task_id<<endl;
-                //AbortTerm();
-                //break;    */
+        else if (m_status.MPI_TAG == TAG_STATE) {
+            int nbytes;
+            MPI_Get_count(&m_status, MPI_CHAR, &nbytes);
+            char inmsg[nbytes + 1];
+            MPI_Recv(inmsg, nbytes, MPI_CHAR, m_status.MPI_SOURCE, TAG_STATE, MPI_COMM_WORLD, &m_status);
+            m_nbrecv++;
+            string *msg_receiv = new string(inmsg, nbytes);
+            m_received_msg.push(MSG(msg_receiv, 0));
+            m_condStack.notify_one();
+        }
+        else if (m_status.MPI_TAG == TAG_FINISH) {
+            int v;
+            MPI_Recv(&v, 1, MPI_INT, m_status.MPI_SOURCE, m_status.MPI_TAG, MPI_COMM_WORLD, &m_status);
+            m_Terminated = true;
+            m_condStack.notify_all();
         }
+        else if    (m_status.MPI_TAG == TAG_INITIAL) {
+            int v;
+                MPI_Recv(&v, 1, MPI_INT, m_status.MPI_SOURCE, m_status.MPI_TAG, MPI_COMM_WORLD, &m_status);
+                LDDState *i_agregate = m_graph->getInitialState();
+                char message[22];
+                memcpy(message, i_agregate->getSHAValue(), 16);
+                uint16_t id_p = i_agregate->getProcess();
+                memcpy(message + 16, &id_p, 2);
+                MPI_Send(message, 22, MPI_BYTE, m_status.MPI_SOURCE, TAG_ACK_INITIAL, MPI_COMM_WORLD);
 
-        MPI_Iprobe ( MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&flag,&m_status );
+        }
+        MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &m_status);
     }
 
 }
 
 
 
-void MCHybridSOG::read_state_message()
-{
-    int min_charge;
-    /****************************************** debut reception state ********************************************/
-    int nbytes;
-    MPI_Get_count ( &m_status, MPI_CHAR, &nbytes );
-    char inmsg[nbytes+1];
-    MPI_Recv ( inmsg, nbytes, MPI_CHAR,m_status.MPI_SOURCE,TAG_STATE,MPI_COMM_WORLD, &m_status );
-    m_nbrecv++;
-    string *msg_receiv =new string ( inmsg,nbytes );
-    min_charge=minCharge();
-    m_charge[min_charge]++;
-    pthread_mutex_lock ( &m_spin_msg[min_charge] );
-    m_msg[min_charge].push ( MSG ( msg_receiv,0 ) );
-    pthread_mutex_unlock ( &m_spin_msg[min_charge] );
-}
-
-void MCHybridSOG::send_state_message()
-{
-    while ( !m_msg[0].empty() ) {
-        pthread_mutex_lock ( &m_spin_msg[0] );
-        MSG s=m_msg[0].top();
-        m_msg[0].pop();
-        pthread_mutex_unlock ( &m_spin_msg[0] );
-        unsigned int message_size;
-        message_size=s.first->size()+1;
-        int destination=s.second;
+/**
+ * send a message containing an aggregate
+ */
+void MCHybridSOG::send_state_message() {
+    MSG s;
+    while (m_tosend_msg.try_pop(s) && !m_Terminated) {
+        int message_size;
+        message_size = s.first->size() + 1;
+        int destination = s.second;
+        //MPI_Request request;
         read_message();
-        MPI_Send ( s.first->c_str(), message_size, MPI_CHAR, destination, TAG_STATE, MPI_COMM_WORLD );
+        MPI_Send(s.first->c_str(), message_size, MPI_CHAR, destination, TAG_STATE, MPI_COMM_WORLD);//, &request);
+        /*int flag;
+        do {
+            read_message();
+            MPI_Test(&request, &flag, &m_status);
+        } while (!flag);*/
         m_nbsend++;
-        m_size_mess+=message_size;
+        m_size_mess += message_size;
         delete s.first;
     }
 }
 
-void MCHybridSOG::computeDSOG ( LDDGraph &g )
-
-{
-    m_graph=&g;
-    double tps;
-
-    // double  t1=(double)clock() / (double)CLOCKS_PER_SEC;
-    //cout<<"process with id "<<task_id<<" / "<<n_tasks<<endl;
-    MPI_Barrier ( m_comm_world );
-    // cout<<"After!!!!process with id "<<task_id<<endl;
-    // int nb_th;
-    m_nb_thread=nb_th;
-    //cout<<"nb de thread"<<nb_th<<endl;
-    int rc;
-    m_id_thread=0;
-    m_nbrecv=0;
-    m_nbsend=0;
-    for ( int i=1; i<m_nb_thread; i++ ) {
-        m_charge[i]=0;
-    }
-
-    m_gc=0;
-    pthread_spin_init ( &m_spin_md5,0 );
-    for ( uint8_t i=0; i<m_nb_thread; i++ ) {
-        pthread_mutex_init ( &m_spin_stack[i], 0 );
-        pthread_mutex_init ( &m_spin_msg[i], 0 );
-    }
-
-    timespec start, finish;
-    if ( task_id==0 ) {
-        clock_gettime ( CLOCK_REALTIME, &start );
-    }
-
-    for ( uint8_t i=0; i<m_nb_thread-1; i++ ) {
-        if ( ( rc = pthread_create ( &m_list_thread[i], NULL,threadHandler,this ) ) ) {
-            cout<<"error: pthread_create, rc: "<<rc<<endl;
+/*
+ * Creation of threads
+ */
+void MCHybridSOG::computeDSOG(LDDGraph &g) {
+    m_graph = &g;
+    MPI_Barrier(m_comm_world);
+    m_nb_thread = nb_th;
+    m_id_thread = 0;
+    m_nbrecv = 0;
+    m_nbsend = 0;
+    m_gc = 0;
+
+    for (uint8_t i = 0; i < m_nb_thread - 1; i++) {
+        m_list_thread[i] = new thread(threadHandler, this);
+        if (m_list_thread[i] == nullptr) {
+            cout << "error: thread creation failed..." << endl;
         }
     }
 
     doCompute();
 
-    for ( int i = 0; i < m_nb_thread-1; i++ ) {
-        pthread_join ( m_list_thread[i], NULL );
+    for (int i = 0; i < m_nb_thread - 1; i++) {
+        m_list_thread[i]->join();
+        delete m_list_thread[i];
     }
-
-
-
-    int sum_nbStates=0;
-    int sum_nbArcs=0;
-    int nbstate=g.m_nbStates;
-
-    int nbarcs=g.m_nbArcs;
-    unsigned long  total_size_mess=0;
-    MPI_Reduce ( &nbstate, &sum_nbStates, 1, MPI_INT, MPI_SUM, 0, m_comm_world );
-    MPI_Reduce ( &nbarcs, &sum_nbArcs, 1, MPI_INT, MPI_SUM, 0, m_comm_world );
-    MPI_Reduce ( &m_size_mess, &total_size_mess, 1, MPI_INT, MPI_SUM, 0, m_comm_world );
-
-    if ( task_id==0 ) {
-        clock_gettime ( CLOCK_REALTIME, &finish );
-
-        tps = ( finish.tv_sec - start.tv_sec );
-        tps += ( finish.tv_nsec - start.tv_nsec ) / 1000000000.0;
-        std::cout << " TIME OF CONSTRUCTION OF THE SOG "
-                  << tps
-                  << " seconds\n";
-
-        cout<<"NB AGGREGATES****** "<<sum_nbStates<<endl;
-        cout<<"NB ARCS****** "<<sum_nbArcs<<endl;
-        cout<<" Size of message ***** "<<total_size_mess<<" bytes"<<endl;
-    }
-    //MPI_Finalize();
-
-
 }
 
 
-uint8_t MCHybridSOG::minCharge()
-{
-    uint8_t pos=1;
-    int min_charge=m_charge[1];
-    for ( uint8_t i=1; i<m_nb_thread; i++ ) {
-        if ( m_charge[i]<min_charge ) {
-            min_charge=m_charge[i];
-            pos=i;
-        }
-    }
-    return pos;
-}
-
-
-
-
-
-MCHybridSOG::~MCHybridSOG()
-{
-    //dtor
-}
+MCHybridSOG::~MCHybridSOG()=default;
 
 /******************************************convert char ---> MDD ********************************************/
 
-MDD MCHybridSOG::decodage_message ( const char *chaine )
-{
-    MDD M=lddmc_false;
-    unsigned int nb_marq= ( ( unsigned char ) chaine[1]-1 );
-    nb_marq= ( nb_marq<<7 ) | ( ( unsigned char ) chaine[0]>>1 );
-
-    unsigned int index=2;
+MDD MCHybridSOG::decodage_message(const char *chaine) {
+    MDD M = lddmc_false;
+    unsigned int nb_marq = (((unsigned char) chaine[1] - 1)<<7) | ((unsigned char) chaine[0] >> 1);
+    //nb_marq = (nb_marq << 7) | ((unsigned char) chaine[0] >> 1);
+    unsigned int index = 2;
     uint32_t list_marq[m_nbPlaces];
-    for ( unsigned int i=0; i<nb_marq; i++ ) {
-        for ( unsigned int j=0; j<m_nbPlaces; j++ ) {
-            list_marq[j]= ( uint32_t ) ( ( unsigned char ) chaine[index]-1 );
+    for (unsigned int i = 0; i < nb_marq; i++) {
+        for (unsigned int j = 0; j < m_nbPlaces; j++) {
+            list_marq[j] = (uint32_t) ((unsigned char) chaine[index] - 1);
             index++;
         }
-        MDD N=SylvanWrapper::lddmc_cube ( list_marq,m_nbPlaces );
-        M=SylvanWrapper::lddmc_union_mono ( M,N );
+        MDD N = SylvanWrapper::lddmc_cube(list_marq, m_nbPlaces);
+        M = SylvanWrapper::lddmc_union_mono(M, N);
     }
     return M;
 }
 
-void * MCHybridSOG::threadHandler ( void *context )
-{
-    return ( ( MCHybridSOG* ) context )->doCompute();
+void *MCHybridSOG::threadHandler(void *context) {
+    return ((MCHybridSOG *) context)->doCompute();
 }
 
 
-
-
-void  MCHybridSOG::get_md5 ( const string& chaine,unsigned char *md_chaine )
-{
-    pthread_spin_lock ( &m_spin_md5 );
-    MD5 ( chaine.c_str(), chaine.size(),md_chaine );
-    pthread_spin_unlock ( &m_spin_md5 );
-}
-
-void MCHybridSOG::sendSuccToMC()
-{
-    uint32_t nb_succ=m_aggWaiting->getSuccessors()->size();
-    uint32_t message_size=nb_succ*20+4;
+void MCHybridSOG::sendSuccToMC() {
+    uint32_t nb_succ = m_aggWaiting->getSuccessors()->size();
+    uint32_t message_size = nb_succ * 20 + 4;
     char mess_tosend[message_size];
-    memcpy ( mess_tosend,&nb_succ,4 );
-    uint32_t i_message=4;
+    memcpy(mess_tosend, &nb_succ, 4);
+    uint32_t i_message = 4;
     //cout<<"***************************Number of succesors to send :"<<nb_succ<<endl;
-    for ( uint32_t i=0; i<nb_succ; i++ ) {
-
-        pair<LDDState*,int> elt;
-        elt=m_aggWaiting->getSuccessors()->at ( i );
-        memcpy ( mess_tosend+i_message,elt.first->getSHAValue(),16 );
-        i_message+=16;
-        uint16_t pcontainer=elt.first->getProcess();
-        //cout<<" pcontainer "<<pcontainer<<endl;
-        memcpy ( mess_tosend+i_message,&pcontainer,2 );
-        i_message+=2;
-        memcpy ( mess_tosend+i_message,& ( elt.second ),2 );
-        i_message+=2;
+    for (uint32_t i = 0; i < nb_succ; i++) {
+        pair<LDDState *, int> elt;
+        elt = m_aggWaiting->getSuccessors()->at(i);
+        memcpy(mess_tosend + i_message, elt.first->getSHAValue(), 16);
+        i_message += 16;
+        uint16_t pcontainer = elt.first->getProcess();
+        memcpy(mess_tosend + i_message, &pcontainer, 2);
+        i_message += 2;
+        memcpy(mess_tosend + i_message, &(elt.second), 2);
+        i_message += 2;
     }
-
-    MPI_Send ( mess_tosend,message_size,MPI_BYTE,n_tasks, TAG_ACK_SUCC,MPI_COMM_WORLD );
+    read_message();
+    MPI_Send(mess_tosend, message_size, MPI_BYTE, n_tasks, TAG_ACK_SUCC, MPI_COMM_WORLD);
 
 }
-/*
-set<uint16_t> MCHybridSOG::getMarkedPlaces ( LDDState *agg )
-{
-    set<uint16_t> result;
-    MDD mdd=agg->getLDDValue();
-    uint16_t depth=0;
-    while ( mdd>lddmc_true ) {
-        //printf("mddd : %d \n",mdd);
-        mddnode_t node=GETNODE ( mdd );
-        if ( m_place_proposition.find ( depth ) !=m_place_proposition.end() )
-            if ( mddnode_getvalue ( node ) ==1 ) {
-                result.insert ( depth );
-            }
-
-        mdd=mddnode_getdown ( node );
-        depth++;
-
-    }
-    return result;
-}*/
-
-/*
-set<uint16_t> MCHybridSOG::getUnmarkedPlaces ( LDDState *agg )
-{
-    set<uint16_t> result;
-    MDD mdd=agg->getLDDValue();
-
-    uint16_t depth=0;
-    while ( mdd>lddmc_true ) {
-        //printf("mddd : %d \n",mdd);
-        mddnode_t node=GETNODE ( mdd );
-        if ( m_place_proposition.find ( depth ) !=m_place_proposition.end() )
-            if ( mddnode_getvalue ( node ) ==0 ) {
-                result.insert ( depth );
-
-            }
 
-        mdd=mddnode_getdown ( node );
-        depth++;
-
-    }
-    return result;
-}*/
 // Send propositions to Model checker
-void MCHybridSOG::sendPropToMC ( size_t pos )
-{
-    LDDState *agg=m_graph->getLDDStateById ( pos );
-    vector<uint16_t> marked_places=agg->getMarkedPlaces ( m_place_proposition );
-    vector<uint16_t> unmarked_places=agg->getUnmarkedPlaces ( m_place_proposition );
-    uint16_t s_mp=marked_places.size();
-    uint16_t s_up=unmarked_places.size();
-    char mess_to_send[8+s_mp*2+s_up*2+5];
-    memcpy ( mess_to_send,&pos,8 );
-    //cout<<"************* Pos to send :"<<pos<<endl;
-    size_t indice=8;
-    memcpy ( mess_to_send+indice,&s_mp,2 );
-    indice+=2;
-    for ( auto it=marked_places.begin(); it!=marked_places.end(); it++ ) {
-        memcpy ( mess_to_send+indice,& ( *it ),2 );
-        indice+=2;
+void MCHybridSOG::sendPropToMC(size_t pos) {
+    LDDState *agg = m_graph->getLDDStateById(pos);
+    vector<uint16_t> marked_places = agg->getMarkedPlaces(m_place_proposition);
+    vector<uint16_t> unmarked_places = agg->getUnmarkedPlaces(m_place_proposition);
+    uint16_t s_mp = marked_places.size();
+    uint16_t s_up = unmarked_places.size();
+    char mess_to_send[8 + s_mp * 2 + s_up * 2 + 5];
+    memcpy(mess_to_send, &pos, 8);
+    size_t indice = 8;
+    memcpy(mess_to_send + indice, &s_mp, 2);
+    indice += 2;
+    for (auto it = marked_places.begin(); it != marked_places.end(); it++) {
+        memcpy(mess_to_send + indice, &(*it), 2);
+        indice += 2;
     }
-    memcpy ( mess_to_send+indice,&s_up,2 );
-    indice+=2;
-    for ( auto it=unmarked_places.begin(); it!=unmarked_places.end(); it++ ) {
-        memcpy ( mess_to_send+indice,& ( *it ),2 );
-        indice+=2;
+    memcpy(mess_to_send + indice, &s_up, 2);
+    indice += 2;
+    for (auto it : unmarked_places) {
+        memcpy(mess_to_send + indice, &(it), 2);
+        indice += 2;
     }
-    uint8_t divblock=agg->isDiv();
-    divblock=divblock | ( agg->isDeadLock() <<1 );
-    memcpy ( mess_to_send+indice,&divblock,1 );
+    uint8_t divblock = agg->isDiv();
+    divblock = divblock | (agg->isDeadLock() << 1);
+    memcpy(mess_to_send + indice, &divblock, 1);
     indice++;
-    MPI_Send ( mess_to_send,indice,MPI_BYTE,n_tasks, TAG_ACK_STATE, MPI_COMM_WORLD );
-}
+    read_message();
+    MPI_Send(mess_to_send, indice, MPI_BYTE, n_tasks, TAG_ACK_STATE, MPI_COMM_WORLD);
+}
\ No newline at end of file
diff --git a/src/MCHybridSOG.h b/src/MCHybridSOG.h
index 0251407e2fda74efca7076dc3db9a578a169e16f..43517640e9a6c2f1e29b94111b0a8fe09e18265d 100644
--- a/src/MCHybridSOG.h
+++ b/src/MCHybridSOG.h
@@ -8,7 +8,7 @@
 //#include "MDGraph.h"
 //#include "bvec.h"
 #include <pthread.h>
-#include <stdio.h>
+#include <cstdio>
 #include <sys/types.h>
 #include <unistd.h>
 #include "LDDGraph.h"
@@ -16,7 +16,7 @@
 
 #include <mpi.h>
 #include <sha2.h>
-#include <stdio.h>
+
 #include <sys/ipc.h>
 #include <sys/shm.h>
 #include <sys/types.h>
@@ -26,14 +26,14 @@
 #include <iostream>
 #include <queue>
 #include <string>
-//#include <boost/serialization/string.hpp>
-#include <time.h>
+#include <ctime>
 #include <chrono>
 #include "CommonSOG.h"
 #include <atomic>
 #include <thread>
 #include <mutex>
 #include <condition_variable>
+#include "SafeDequeue.h"
 // namespace mpi = boost::mpi;
 
 //#define MASTER 0
@@ -46,7 +46,7 @@ extern int n_tasks, task_id;
 typedef pair<string *, unsigned int> MSG;
 
 typedef stack<MSG> pile_msg;
-
+enum class state {waitInitial,waitingBuild,waitingSucc};
 // typedef vector<Trans> vec_trans;
 class MCHybridSOG : public CommonSOG
 {
@@ -55,69 +55,39 @@ public:
     void buildFromNet(int index);
     /// principal functions to construct the SOG
     void computeDSOG(LDDGraph &g);
-    virtual ~MCHybridSOG();
+    ~MCHybridSOG() override;
     static void *threadHandler(void *context);
     void *doCompute();
-
 protected:
 private:
+    std::condition_variable m_condStack;
+    mutable std::mutex m_mutexCond;
     MPI_Comm m_comm_world;
     void sendSuccToMC();
     void sendPropToMC(size_t pos);
-    atomic_bool m_waitingAgregate;// (false);
-    atomic_bool m_waitingBuild;
-    atomic_bool m_waitingSucc;
+    atomic<bool> m_waitingAgregate;// (false);
+    atomic<state> m_waitingBuildSucc;
     char m_id_md5[16];
     LDDState * m_aggWaiting=nullptr;
-    
-    
-    /// \ hash function
-    void get_md5(const string &chaine, unsigned char *md_chaine);
-        
-    /// minimum charge function for the load balancing between thread
-    inline uint8_t minCharge();
-
-
-
     int m_nbmetastate;
+    SafeDequeue<Pair> m_common_stack;
+    SafeDequeue<MSG> m_received_msg;
+    SafeDequeue<MSG> m_tosend_msg;
 
-    pile m_st[128];
-    pile_msg m_msg[128];
-
-    // void DisplayMessage(const char *chaine);
-
-    //        int n_tasks, task_id;
-
-    int m_charge[128];
-     int m_init;
-
-
+    int m_init;
     /// Convert a string caracter to an MDD
     MDD decodage_message(const char *chaine);
     /// there is a message to receive?
     void read_message();
     
     /// receive state message
-    void read_state_message();
     void send_state_message();
-
-    pthread_t m_list_thread[128];
-
-    atomic<uint8_t> m_id_thread;      
-    //pthread_mutex_t m_mutex_stack[128];
-    pthread_mutex_t m_spin_stack[128];
-    pthread_mutex_t m_spin_msg[128];
-   
-    pthread_spinlock_t m_spin_md5;
-    
-
+    thread* m_list_thread[128];
+    atomic<uint8_t> m_id_thread;
     volatile bool m_Terminated = false;
     unsigned long m_size_mess = 0;
     int m_nbsend = 0, m_nbrecv = 0;
-
     MPI_Status m_status;
-    /*set<uint16_t> getUnmarkedPlaces(LDDState *agg);
-    set<uint16_t> getMarkedPlaces(LDDState *agg);*/
 
 };
 
diff --git a/src/ModelCheckBaseMT.h b/src/ModelCheckBaseMT.h
index 4139741c8408827e2564f7789fe759ace72d65b2..83bacc64d5003a7cc363b59005bba53206148763 100644
--- a/src/ModelCheckBaseMT.h
+++ b/src/ModelCheckBaseMT.h
@@ -9,6 +9,7 @@ public:
         virtual LDDState * getInitialMetaState();
         virtual void buildSucc(LDDState *agregate);
         void loadNet();
+
         virtual ~ModelCheckBaseMT();
 protected:
     std::condition_variable m_condBuild;
diff --git a/src/ModelCheckThReq.cpp b/src/ModelCheckThReq.cpp
index d65eaf79f8818ea0aea3f2d837a414920fc4a18c..2e87f52296ea142955e50f41f4138a39664da27e 100644
--- a/src/ModelCheckThReq.cpp
+++ b/src/ModelCheckThReq.cpp
@@ -1,6 +1,8 @@
 #include "ModelCheckThReq.h"
 #include <unistd.h>
+#include <thread>
 
+#define LEVEL 3
 
 ModelCheckThReq::ModelCheckThReq(const NewNet &R, int nbThread) : ModelCheckBaseMT(R, nbThread) {
 }
@@ -26,6 +28,7 @@ void ModelCheckThReq::preConfigure() {
     SylvanWrapper::sylvan_init_package();
     SylvanWrapper::sylvan_init_ldd();
     SylvanWrapper::init_gc_seq();
+    SylvanWrapper::lddmc_refs_init();
     SylvanWrapper::displayMDDTableInfo();
     int i;
     vector<Place>::const_iterator it_places;
@@ -91,33 +94,32 @@ void ModelCheckThReq::preConfigure() {
     delete[] prec;
     delete[] postc;
 }
+
 /**
  * Creates builder threads
  */
-void ModelCheckThReq::ComputeTh_Succ()
-{
+void ModelCheckThReq::ComputeTh_Succ() {
     int rc;
-    m_id_thread=0;
+    m_id_thread = 0;
     //cout<<"Enter : "<<__func__ <<endl;
-    pthread_mutex_init(&m_mutex, NULL);
-    pthread_mutex_init(&m_graph_mutex,NULL);
-    pthread_barrier_init(&m_barrier_threads, NULL, m_nb_thread+1);
-    pthread_barrier_init(&m_barrier_builder, NULL, m_nb_thread+1);
-    for (int i=0; i<m_nb_thread; i++)
-    {
-        if ((rc = pthread_create(&m_list_thread[i], NULL,threadHandler,this)))
-        {
-            cout<<"error: pthread_create, rc: "<<rc<<endl;
+    pthread_barrier_init(&m_barrier_threads, NULL, m_nb_thread + 1);
+    for ( int i = 0; i < m_nb_thread; i++ ) {
+        m_list_thread[i]= new thread ( threadHandler,this );
+        if ( m_list_thread[i]==nullptr ) {
+            cout << "error: pthread creation failed"  << endl;
         }
     }
+
 }
 
 /*
  * Build initial aggregate
  */
-LDDState * ModelCheckThReq::getInitialMetaState() {
-    //cout<<"Enter : "<<__func__ <<endl;
-    if (m_graph->getInitialAggregate()!= nullptr) return m_graph->getInitialAggregate();
+LDDState *ModelCheckThReq::getInitialMetaState() {
+
+    if (m_graph->getInitialAggregate() != nullptr) {
+        return m_graph->getInitialAggregate();
+    }
     ComputeTh_Succ();
     LDDState *c = new LDDState;
     MDD initial_meta_state = Accessible_epsilon(m_initialMarking);
@@ -125,100 +127,114 @@ LDDState * ModelCheckThReq::getInitialMetaState() {
     c->m_lddstate = initial_meta_state;
     m_graph->setInitialState(c);
     m_graph->insert(c);
-    Set fire = firable_obs(initial_meta_state);
-    int j = 0;
-    for (auto it = fire.begin(); it != fire.end(); it++, j++)
-        m_st[j % m_nb_thread].push(couple_th(c, *it));
-    pthread_barrier_wait(&m_barrier_threads);
-    pthread_barrier_wait(&m_barrier_builder);
     c->setVisited();
+    Set fire = firable_obs(initial_meta_state);
+    c->m_nbSuccessorsToBeProcessed = fire.size();
+    c->setMCurrentLevel(LEVEL);
+
+    c->setDiv(Set_Div(initial_meta_state));
+    c->setDeadLock(Set_Bloc(initial_meta_state));
+    if (!fire.empty()) {
+        for (auto it = fire.begin(); it != fire.end(); it++)
+            m_common_stack.push(couple_th(c, *it));
+        std::unique_lock<std::mutex> lk(m_mutexBuildCompleted);
+        m_datacondBuildCompleted.wait(lk, [c] { return c->isCompletedSucc(); });
+        lk.unlock();
+    } else c->setCompletedSucc();
     return c;
 }
 
 /*
- * Build successors of @aggregate using PThreads
+ * Build successors of @agregate
  */
 void ModelCheckThReq::buildSucc(LDDState *agregate) {
-    if (!agregate->isVisited())
-    {
-        //SylvanWrapper::displayMDDTableInfo();
+    if (!agregate->isVisited()) {
         agregate->setVisited();
-        Set fire=firable_obs(agregate->getLDDValue());
-        int j=0;
-        for(auto it=fire.begin(); it!=fire.end(); it++,j++)
-            m_st[j%m_nb_thread].push(couple_th(agregate,*it));
-        pthread_barrier_wait(&m_barrier_threads);
-        pthread_barrier_wait(&m_barrier_builder);
+        if (agregate->getMCurrentLevel() == 0) {
+            Set fire = firable_obs(agregate->m_lddstate);
+            agregate->setMCurrentLevel(LEVEL);
+            agregate->m_nbSuccessorsToBeProcessed = fire.size();
+            if (!fire.empty()) {
+                agregate->m_nbSuccessorsToBeProcessed = fire.size();
+                for (auto it = fire.begin(); it != fire.end(); it++)
+                    m_common_stack.push(couple_th(agregate, *it));
+                std::unique_lock<std::mutex> lk(m_mutexBuildCompleted);
+                m_datacondBuildCompleted.wait(lk, [agregate] { return agregate->isCompletedSucc(); });
+                lk.unlock();
+
+            } else agregate->setCompletedSucc();
+        } else {
+            std::unique_lock<std::mutex> lk(m_mutexBuildCompleted);
+            m_datacondBuildCompleted.wait(lk, [agregate] { return agregate->isCompletedSucc(); });
+            lk.unlock();
+        }
     }
 }
 
 
-void * ModelCheckThReq::threadHandler(void *context)
-{
-    return ((ModelCheckThReq*)context)->Compute_successors();
+void *ModelCheckThReq::threadHandler(void *context) {
+    return ((ModelCheckThReq *) context)->Compute_successors();
 }
 
 
+void *ModelCheckThReq::Compute_successors() {
 
-void * ModelCheckThReq::Compute_successors()
-{
-    int id_thread;
-    id_thread=m_id_thread++;
-    LDDState* reached_class=nullptr;
-   // cout<<"Before do : "<<__func__ <<endl;
-    do
-    {
-         pthread_barrier_wait(&m_barrier_threads);
-        while (!m_st[id_thread].empty())
-        {
-            couple_th elt=m_st[id_thread].top();
-            m_st[id_thread].pop();
-            LDDState *aggregate=elt.first;
-            MDD meta_state=aggregate->getLDDValue();
-            int transition=elt.second;
-            MDD complete_state=Accessible_epsilon(get_successor(meta_state,transition));
-            reached_class=new LDDState;
-            reached_class->m_lddstate=complete_state;
-            reached_class->setDiv(Set_Div(complete_state));
-            reached_class->setDeadLock(Set_Bloc(complete_state));
-            pthread_mutex_lock(&m_graph_mutex);
-            LDDState* pos=m_graph->find(reached_class);
-            if(!pos)
+    couple_th elt;
+    LDDState *pos, *aggregate;
+    do {
+        while (!m_finish && m_common_stack.try_pop(elt)) {
+            aggregate = elt.first;
+            int transition = elt.second;
+            MDD meta_state = aggregate->m_lddstate;
+            MDD complete_state = Accessible_epsilon(get_successor(meta_state, transition));
+            bool res;
+            pos = m_graph->insertFindByMDD(complete_state, res);
             {
-                m_graph->insert(reached_class);
-                aggregate->Successors.insert(aggregate->Successors.begin(),LDDEdge(reached_class,transition));
-                reached_class->Predecessors.insert(reached_class->Predecessors.begin(),LDDEdge(aggregate,transition));
-                pthread_mutex_unlock(&m_graph_mutex);
-                m_graph->addArc();
+                std::unique_lock guard(m_graph_mutex);
+                aggregate->Successors.insert(aggregate->Successors.begin(), LDDEdge(pos, transition));
+                pos->Predecessors.insert(pos->Predecessors.begin(),
+                                         LDDEdge(aggregate, transition));
             }
-            else
-            {   aggregate->Successors.insert(aggregate->Successors.begin(),LDDEdge(pos,transition));
-                pos->Predecessors.insert(pos->Predecessors.begin(),LDDEdge(aggregate,transition));
-                pthread_mutex_unlock(&m_graph_mutex);
-                m_graph->addArc();
-                delete reached_class;
+            if (!res) {
+                pos->setDiv(Set_Div(complete_state));
+                pos->setDeadLock(Set_Bloc(complete_state));
             }
+            aggregate->decNbSuccessors();
+            if (aggregate->m_nbSuccessorsToBeProcessed == 0) {
+                aggregate->setCompletedSucc();
+                m_datacondBuildCompleted.notify_one();
+            }
+
+            if (aggregate->getMCurrentLevel() > 0 && pos->getMCurrentLevel() == 0) {
+                pos->setMCurrentLevel(aggregate->getMCurrentLevel() - 1);
+                if (aggregate->getMCurrentLevel() > 1) {
+                    Set fire = firable_obs(pos->getLDDValue());
+                    pos->m_nbSuccessorsToBeProcessed = fire.size();
+                    if (!fire.empty()) {
+                        for (auto it = fire.begin(); it != fire.end(); it++)
+                            m_common_stack.push(couple_th(pos, *it));
+                    } else {
+                        pos->setCompletedSucc();
+                        m_datacondBuildCompleted.notify_one();
+                    }
+
+                }
+
+            }
+            m_graph->addArc();
 
         }
-        //cout<<"Before barrier : "<<__func__ <<endl;
-        pthread_barrier_wait(&m_barrier_builder);
-        //m_finish=m_finish;
-        //cout<<"After barrier : "<<__func__ <<endl;
-    }
-    while (!m_finish);
-    //cout<<"Quit : "<<__func__ <<" ; "<<id_thread<<endl;
+    } while (!m_finish);
+
+
 }
 
 
 ModelCheckThReq::~ModelCheckThReq() {
-    //cout<<"1 : "<<__func__ <<endl;
-    pthread_barrier_wait(&m_barrier_threads);
-    m_finish=true;
-    pthread_barrier_wait(&m_barrier_builder);
-    /*for (int i = 0; i < m_nb_thread; i++)
-    {
-        pthread_join(m_list_thread[i], NULL);
-    }*/
-    //cout<<"3 : "<<__func__ <<endl;
+    //pthread_barrier_wait(&m_barrier_threads);
+    for (int i = 0; i < m_nb_thread; i++) {
+        m_list_thread[i]->join();
+        delete m_list_thread[i];
+    }
 }
 
diff --git a/src/ModelCheckThReq.h b/src/ModelCheckThReq.h
index db4ef2aec484d1649c507ff88331e8750addea37..51dfb7be8efe673af6f332a222bc5728a0b9829d 100644
--- a/src/ModelCheckThReq.h
+++ b/src/ModelCheckThReq.h
@@ -3,29 +3,28 @@
 #include "ModelCheckBaseMT.h"
 #include <atomic>
 #include <mutex>
+#include <thread>
+#include "SafeDequeue.h"
 
 typedef pair<LDDState *, int> couple_th;
-typedef stack<pair<LDDState *,int>> pile_t;
+//typedef stack<pair<LDDState *,int>> pile_t;
 class ModelCheckThReq : public ModelCheckBaseMT {
 public:
     ModelCheckThReq(const NewNet &R,int nbThread);
-    ~ModelCheckThReq();
-
+    ~ModelCheckThReq() override;
     void buildSucc(LDDState *agregate)  override;
     static void *threadHandler(void *context);
     void *Compute_successors();
     void ComputeTh_Succ();
-    LDDState * getInitialMetaState();
+    LDDState * getInitialMetaState() override;
 private:
-    void preConfigure();
-    pile_t m_st[128];
+    void preConfigure() override;
+    SafeDequeue<couple_th> m_common_stack;
     atomic<uint8_t> m_id_thread;
-    pthread_mutex_t m_mutex;
-    pthread_mutex_t m_graph_mutex;
-    pthread_barrier_t m_barrier_threads,m_barrier_builder;
-    pthread_t m_list_thread[128];
-    volatile atomic<bool> m_finish=false;
-
+    thread* m_list_thread[128];
+    mutable std::mutex m_mutexBuildCompleted;
+    std::condition_variable m_datacondBuildCompleted;
+    pthread_barrier_t m_barrier_threads;
 };
 #endif
 
diff --git a/src/ModelCheckerCPPThread.cpp b/src/ModelCheckerCPPThread.cpp
index 6ad7a5afba07a6105f39b4d052e369c055d44e85..3f43d7131aee0ed79204e7b909925cb22e6fdc66 100644
--- a/src/ModelCheckerCPPThread.cpp
+++ b/src/ModelCheckerCPPThread.cpp
@@ -6,23 +6,23 @@
 #include <unistd.h>
 
 #include "SylvanWrapper.h"
+
 #define GETNODE(mdd) ((mddnode_t)llmsset_index_to_ptr(nodes, mdd))
 
 using namespace std;
 
-ModelCheckerCPPThread::ModelCheckerCPPThread ( const NewNet &R, int nbThread ) :
-    ModelCheckBaseMT ( R, nbThread )
-{
+ModelCheckerCPPThread::ModelCheckerCPPThread(const NewNet &R, int nbThread) :
+        ModelCheckBaseMT(R, nbThread) {
 }
+
 size_t
-getMaxMemoryV3()
-{
-    long pages = sysconf ( _SC_PHYS_PAGES );
-    long page_size = sysconf ( _SC_PAGE_SIZE );
+getMaxMemoryV3() {
+    long pages = sysconf(_SC_PHYS_PAGES);
+    long page_size = sysconf(_SC_PAGE_SIZE);
     return pages * page_size;
 }
-void ModelCheckerCPPThread::preConfigure()
-{
+
+void ModelCheckerCPPThread::preConfigure() {
 
     /*lace_init ( 1, 0 );
     lace_startup ( 0, NULL, NULL );
@@ -30,7 +30,7 @@ void ModelCheckerCPPThread::preConfigure()
     if ( max > getMaxMemoryV3() ) {
         max = getMaxMemoryV3() /10*9;
     }*/
-    SylvanWrapper::sylvan_set_limits ( 16LL<<30, 10, 0 );
+    SylvanWrapper::sylvan_set_limits(16LL << 30, 10, 0);
 
     //sylvan_init_package();
     SylvanWrapper::sylvan_init_package();
@@ -54,46 +54,46 @@ void ModelCheckerCPPThread::preConfigure()
 
     uint32_t *liste_marques = new uint32_t[m_net->places.size()];
     uint32_t i;
-    for ( i = 0, it_places = m_net->places.begin(); it_places != m_net->places.end(); i++, it_places++ ) {
+    for (i = 0, it_places = m_net->places.begin(); it_places != m_net->places.end(); i++, it_places++) {
         liste_marques[i] = it_places->marking;
     }
 
-    m_initialMarking = SylvanWrapper::lddmc_cube ( liste_marques, m_net->places.size() );
-    SylvanWrapper::lddmc_refs_push ( m_initialMarking );
+    m_initialMarking = SylvanWrapper::lddmc_cube(liste_marques, m_net->places.size());
+    SylvanWrapper::lddmc_refs_push(m_initialMarking);
 
     uint32_t *prec = new uint32_t[m_nbPlaces];
     uint32_t *postc = new uint32_t[m_nbPlaces];
     // Transition relation
-    for ( vector<Transition>::const_iterator t = m_net->transitions.begin(); t != m_net->transitions.end(); t++ ) {
+    for (vector<Transition>::const_iterator t = m_net->transitions.begin(); t != m_net->transitions.end(); t++) {
         // Initialisation
-        for ( i = 0; i < m_nbPlaces; i++ ) {
+        for (i = 0; i < m_nbPlaces; i++) {
             prec[i] = 0;
             postc[i] = 0;
         }
         // Calculer les places adjacentes a la transition t
         set<int> adjacentPlace;
-        for ( vector<pair<int, int> >::const_iterator it = t->pre.begin(); it != t->pre.end(); it++ ) {
-            adjacentPlace.insert ( it->first );
+        for (vector<pair<int, int> >::const_iterator it = t->pre.begin(); it != t->pre.end(); it++) {
+            adjacentPlace.insert(it->first);
             prec[it->first] = prec[it->first] + it->second;
             //printf("It first %d \n",it->first);
             //printf("In prec %d \n",prec[it->first]);
         }
         // arcs post
-        for ( vector<pair<int, int> >::const_iterator it = t->post.begin(); it != t->post.end(); it++ ) {
-            adjacentPlace.insert ( it->first );
+        for (auto it = t->post.begin(); it != t->post.end(); it++) {
+            adjacentPlace.insert(it->first);
             postc[it->first] = postc[it->first] + it->second;
 
         }
-        for ( set<int>::const_iterator it = adjacentPlace.begin(); it != adjacentPlace.end(); it++ ) {
+        for (set<int>::const_iterator it = adjacentPlace.begin(); it != adjacentPlace.end(); it++) {
             MDD Precond = lddmc_true;
-            Precond = Precond & ( ( *it ) >= prec[*it] );
+            Precond = Precond & ((*it) >= prec[*it]);
         }
 
-        MDD _minus = SylvanWrapper::lddmc_cube ( prec, m_nbPlaces );
-        SylvanWrapper::lddmc_refs_push ( _minus );
-        MDD _plus = SylvanWrapper::lddmc_cube ( postc, m_nbPlaces );
-        SylvanWrapper::lddmc_refs_push ( _plus );
-        m_tb_relation.push_back ( TransSylvan ( _minus, _plus ) );
+        MDD _minus = SylvanWrapper::lddmc_cube(prec, m_nbPlaces);
+        SylvanWrapper::lddmc_refs_push(_minus);
+        MDD _plus = SylvanWrapper::lddmc_cube(postc, m_nbPlaces);
+        SylvanWrapper::lddmc_refs_push(_plus);
+        m_tb_relation.emplace_back(TransSylvan(_minus, _plus));
     }
     delete[] prec;
     delete[] postc;
@@ -103,113 +103,93 @@ void ModelCheckerCPPThread::preConfigure()
 }
 
 
+void ModelCheckerCPPThread::Compute_successors() {
+    int id_thread;
 
+    id_thread = m_id_thread++;
 
-void ModelCheckerCPPThread::Compute_successors()
-{
-    int id_thread;
-   
-   id_thread = m_id_thread++;
-   
     //cout<<" I'm here thread id " <<m_id_thread<<endl;
-    Set fire;    
-    
-    if ( id_thread == 0 ) {
-        LDDState *c = new LDDState;
-        MDD Complete_meta_state=Accessible_epsilon ( m_initialMarking );
-        SylvanWrapper::lddmc_refs_push ( Complete_meta_state );
-
-        fire = firable_obs ( Complete_meta_state );
+    Set fire;
+
+    if (id_thread == 0) {
+        auto *c = new LDDState;
+        MDD Complete_meta_state = Accessible_epsilon(m_initialMarking);
+        SylvanWrapper::lddmc_refs_push(Complete_meta_state);
+
+        fire = firable_obs(Complete_meta_state);
         c->m_lddstate = Complete_meta_state;
-        c->setDeadLock ( Set_Bloc ( Complete_meta_state ) );
-        c->setDiv ( Set_Div ( Complete_meta_state ) );
-        m_graph->setInitialState ( c );
-        m_graph->insert ( c );
-        m_common_stack.push ( Pair ( couple ( c, Complete_meta_state ), fire ) );
+        c->setDeadLock(Set_Bloc(Complete_meta_state));
+        c->setDiv(Set_Div(Complete_meta_state));
+        m_graph->setInitialState(c);
+        m_graph->insert(c);
+        m_common_stack.push(Pair(couple(c, Complete_meta_state), fire));
         m_condStack.notify_one();
         m_finish_initial = true;
     }
-    LDDState *reached_class;
+
     //pthread_barrier_wait ( &m_barrier_builder );
     Pair e;
-    do {        
-        std::unique_lock<std::mutex> lk ( m_mutexStack );
-        m_condStack.wait(lk,std::bind(&ModelCheckerCPPThread::hasToProcess,this));
+    do {
+        std::unique_lock<std::mutex> lk(m_mutexStack);
+        m_condStack.wait(lk, std::bind(&ModelCheckerCPPThread::hasToProcess, this));
         lk.unlock();
-                            
-            if ( m_common_stack.try_pop ( e ) && !m_finish ) {
-                while ( !e.second.empty() && !m_finish ) {
-                    int t = *e.second.begin();
-                    e.second.erase ( t );
-                    MDD reduced_meta = Accessible_epsilon ( get_successor ( e.first.second, t ) );
-                    SylvanWrapper::lddmc_refs_push ( reduced_meta );
-                    reached_class = new LDDState();
-                    reached_class->m_lddstate = reduced_meta;                    
-                    LDDState *pos = m_graph->find ( reached_class );
-                    if ( !pos ) {
-                        m_graph->addArc();
-                        m_graph->insert ( reached_class );
-                        fire = firable_obs ( reduced_meta );
-                        reached_class->setDeadLock ( Set_Bloc ( reduced_meta ) );
-                        reached_class->setDiv ( Set_Div ( reduced_meta ) );
-                        m_common_stack.push ( Pair ( couple ( reached_class, reduced_meta ), fire ) );
-                        m_condStack.notify_one();
-                        m_graph_mutex.lock();
-                        e.first.first->Successors.insert ( e.first.first->Successors.begin(), LDDEdge ( reached_class, t ) );
-                        reached_class->Predecessors.insert ( reached_class->Predecessors.begin(), LDDEdge ( e.first.first, t ) );
-                        m_graph_mutex.unlock();
-                    } else {
-                        delete reached_class;
-                        m_graph->addArc();
-                        m_graph_mutex.lock();
-                        e.first.first->Successors.insert ( e.first.first->Successors.begin(), LDDEdge ( pos, t ) );
-                        pos->Predecessors.insert ( pos->Predecessors.begin(), LDDEdge ( e.first.first, t ) );
-                        m_graph_mutex.unlock();                        
-                    }
-                    
-                }
-                e.first.first->setCompletedSucc();m_condBuild.notify_one();
-            } //end advance
-
-    } while ( !m_finish );
-
 
+        if (m_common_stack.try_pop(e) && !m_finish) {
+            while (!e.second.empty() && !m_finish) {
+                int t = *e.second.begin();
+                e.second.erase(t);
+                MDD reduced_meta = Accessible_epsilon(get_successor(e.first.second, t));
+                SylvanWrapper::lddmc_refs_push(reduced_meta);
+                bool res;
+                LDDState *pos = m_graph->insertFindByMDD(reduced_meta, res);
+                m_graph->addArc();
+                if (!res) {
+                    fire = firable_obs(reduced_meta);
+                    pos->setDeadLock(Set_Bloc(reduced_meta));
+                    pos->setDiv(Set_Div(reduced_meta));
+                    m_common_stack.push(Pair(couple(pos, reduced_meta), fire));
+                    m_condStack.notify_one();
+                }
+                m_graph_mutex.lock();
+                e.first.first->Successors.insert(e.first.first->Successors.begin(), LDDEdge(pos, t));
+                pos->Predecessors.insert(pos->Predecessors.begin(), LDDEdge(e.first.first, t));
+                m_graph_mutex.unlock();
+            }
+            e.first.first->setCompletedSucc();
+            m_condBuild.notify_one();
+        } //end advance
+
+    } while (!m_finish);
 }
 
-void ModelCheckerCPPThread::threadHandler ( void *context )
-{
+void ModelCheckerCPPThread::threadHandler(void *context) {
     SylvanWrapper::lddmc_refs_init();
-    ( ( ModelCheckerCPPThread* ) context )->Compute_successors();
+    ((ModelCheckerCPPThread *) context)->Compute_successors();
 }
 
-void ModelCheckerCPPThread::ComputeTh_Succ()
-{
+void ModelCheckerCPPThread::ComputeTh_Succ() {
 
     m_id_thread = 0;
-
-    pthread_barrier_init ( &m_barrier_builder, NULL, m_nb_thread + 1 );
-   
-    m_finish=false;
-    for ( int i = 0; i < m_nb_thread; i++ ) {
-        int rc;
-        m_list_thread[i]= new thread ( threadHandler,this );
-        if ( m_list_thread==nullptr ) {
-            cout << "error: pthread_create, rc: " << rc << endl;
+    pthread_barrier_init(&m_barrier_builder, nullptr, m_nb_thread + 1);
+    m_finish = false;
+    for (int i = 0; i < m_nb_thread; i++) {
+        m_list_thread[i] = new thread(threadHandler, this);
+        if (m_list_thread[i] == nullptr) {
+            cout << "error: pthread creation failed. "  << endl;
         }
     }
 }
 
-ModelCheckerCPPThread::~ModelCheckerCPPThread()
-{
+ModelCheckerCPPThread::~ModelCheckerCPPThread() {
     m_finish = true;
     m_condStack.notify_all();
-    //pthread_barrier_wait ( &m_barrier_builder );
-    for ( int i = 0; i < m_nb_thread; i++ ) {
+    for (int i = 0; i < m_nb_thread; i++) {
         m_list_thread[i]->join();
         delete m_list_thread[i];
     }
 
 }
+
 bool ModelCheckerCPPThread::hasToProcess() const {
     return m_finish || !m_common_stack.empty();
 }
diff --git a/src/ModelCheckerCPPThread.h b/src/ModelCheckerCPPThread.h
index 204e6c085fba978f3ad41ec5b6f8479c62e8dee2..da9683768beaba9a60e020b82bfc50762f76a636 100644
--- a/src/ModelCheckerCPPThread.h
+++ b/src/ModelCheckerCPPThread.h
@@ -27,8 +27,7 @@ private:
     SafeDequeue<Pair> m_common_stack;       
     atomic<uint8_t> m_id_thread;
     std::mutex m_mutex; 
-    pthread_barrier_t m_barrier_builder;    
-    volatile bool m_finish=false;
+    pthread_barrier_t m_barrier_builder;
     std::condition_variable m_condStack;
     std::mutex m_mutexStack;
     thread* m_list_thread[128];    
diff --git a/src/NewNet.cpp b/src/NewNet.cpp
index b73c7574631b6e82200d4e184fa799ea981266a7..3ab3187e71b48f86cf2af6b566e998147bbe3bf6 100644
--- a/src/NewNet.cpp
+++ b/src/NewNet.cpp
@@ -1,17 +1,8 @@
 #include "NewNet.h"
 #include <spot/misc/version.hh>
-#include <spot/twaalgos/dot.hh>
-#include <spot/tl/parse.hh>
-#include <spot/tl/print.hh>
-#include <spot/twaalgos/translate.hh>
-#include <spot/twaalgos/emptiness.hh>
-
-
 #include <algorithm>
-#include <ext/hash_map>
 #include <iomanip>
 #include <iostream>
-#include <fstream>
 #include <map>
 #include <string>
 #include <vector>
@@ -135,7 +126,7 @@ NewNet::NewNet(const char *f, const set<string> & f_trans)
         m_placeName.clear();
         transitionName.clear();
     }
-    if (f_trans.size() > 0)
+    if (!f_trans.empty())
     {
         cout<<"Transition set of formula is not empty\n";
         for (set<string>::iterator p=f_trans.begin(); p!=f_trans.end(); p++)
@@ -240,7 +231,7 @@ bool NewNet::Set_Formula_Trans(const char *f)
     for (i = 0; i < nb_formula_trans; i++)
     {
         cout << " z: " << z << endl;
-        if (z == NULL)
+        if (z == nullptr)
         {
             cout << "error in formula trans format " << endl;
             return false;
@@ -256,8 +247,8 @@ bool NewNet::Set_Formula_Trans(const char *f)
         else
             Formula_Trans.insert(pos);
         /*cout<<"insertion de :"<<transitions[pos].name<<endl;*/
-        z = strtok(NULL, " \t\n");
-        if (z == NULL)
+        z = strtok(nullptr, " \t\n");
+        if (z == nullptr)
         {
             nb = fread(Buff, 1, TAILLEBUFF - 1, in);
             Buff[nb] = '\0';
@@ -275,7 +266,7 @@ bool NewNet::Set_Interface_Trans(const char *f)
     int pos_trans(TRANSITIONS, string);
     char Buff[TAILLEBUFF], *z;
     in = fopen(f, "r");
-    if (in == NULL)
+    if (in == nullptr)
     {
         cout << "file " << f << " doesn't exist" << endl;
         exit(1);
@@ -289,7 +280,7 @@ bool NewNet::Set_Interface_Trans(const char *f)
     for (i = 0; i < int_trans; i++)
     {
         cout << " z: " << z << endl;
-        if (z == NULL)
+        if (z == nullptr)
         {
             cout << "error in interface format " << endl;
             return false;
@@ -304,8 +295,8 @@ bool NewNet::Set_Interface_Trans(const char *f)
         }
         else
             InterfaceTrans.insert(pos);
-        z = strtok(NULL, " \t\n");
-        if (z == NULL)
+        z = strtok(nullptr, " \t\n");
+        if (z == nullptr)
         {
             nb = fread(Buff, 1, TAILLEBUFF - 1, in);
             Buff[nb] = '\0';
@@ -344,7 +335,7 @@ ostream &operator<<(ostream &os, const Set &s)
 {
     bool b = false;
 
-    if (s.size())
+    if (!s.empty())
     {
         for (Set::const_iterator i = s.begin(); !(i == s.end()); i++)
         {
diff --git a/src/SafeDequeue.cpp b/src/SafeDequeue.cpp
index 429c78fe2027bc326b8269105566be80c769eeea..fdcb4655d56b2083db1317a36fdbb79c977d9f18 100644
--- a/src/SafeDequeue.cpp
+++ b/src/SafeDequeue.cpp
@@ -16,6 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <iostream>
 #include "SafeDequeue.h"
 
 template<typename T>
@@ -46,22 +47,6 @@ void SafeDequeue<T>::push ( T new_value )
 
 }
 
-/*template<typename T>
-void SafeDequeue<T>::wait_and_pop ( T& value )
-{
-    
-}*/
-
-template<typename T>
-std::shared_ptr<T> SafeDequeue<T>::wait_and_pop()
-{
-    std::unique_lock<std::mutex> lk ( mut );
-    data_cond.wait ( lk,[this] {return !data_queue.empty();} );
-    std::shared_ptr<T> res ( std::make_shared<T> ( data_queue.front() ) );
-    data_queue.pop();
-    return res;
-}
-
 template<typename T>
 bool SafeDequeue<T>::try_pop ( T& value )
 {
@@ -75,17 +60,7 @@ bool SafeDequeue<T>::try_pop ( T& value )
 }
 
 
-template<typename T>
-std::shared_ptr<T> SafeDequeue<T>::try_pop()
-{
-    std::lock_guard<std::mutex> lk ( mut );
-    if ( data_queue.empty() ) {
-        return std::shared_ptr<T>();
-    }
-    std::shared_ptr<T> res ( std::make_shared<T> ( data_queue.front() ) );
-    data_queue.pop();
-    return res;
-}
+
 
 template<typename T>
 bool SafeDequeue<T>::empty() const
@@ -98,3 +73,4 @@ bool SafeDequeue<T>::empty() const
 template class SafeDequeue<Pair>;
 typedef pair<string *, unsigned int> MSG;
 template class SafeDequeue<MSG>;
+template class SafeDequeue<couple_th>;
diff --git a/src/SafeDequeue.h b/src/SafeDequeue.h
index 607f0851d35d32f32a28e54ace7aeaf09d892248..d2ffdd42689250a6ec3f3d14b081c262af91046d 100644
--- a/src/SafeDequeue.h
+++ b/src/SafeDequeue.h
@@ -27,6 +27,7 @@
 
 typedef pair<LDDState *, MDD> couple;
 typedef pair<couple, Set> Pair;
+typedef pair<LDDState *, int> couple_th;
 struct empty_queue: std::exception {
     ~empty_queue() {};
     const char* what() const noexcept {return "";}
@@ -62,16 +63,6 @@ class SafeDequeue {
         SafeDequeue& operator= ( const SafeDequeue& ) = delete;
         void push ( T new_value );
         bool try_pop ( T& value );
-        std::shared_ptr<T> try_pop();
-        void wait_and_pop ( T& value ) {
-            std::unique_lock<std::mutex> lk ( mut );
-            data_cond.wait ( lk,[this] {return !data_queue.empty();} );
-            value=data_queue.front();
-            data_queue.pop();
-            };
-
-        
-        std::shared_ptr<T> wait_and_pop();
         bool empty() const;
     };
 
diff --git a/src/SogKripkeIteratorTh.cpp b/src/SogKripkeIteratorTh.cpp
index 74b7e603255476e2ff2a546b56ddbcae3fd85902..e48c97f5281f2dfd6d944bea4d2bd12bc08bcd37 100644
--- a/src/SogKripkeIteratorTh.cpp
+++ b/src/SogKripkeIteratorTh.cpp
@@ -4,7 +4,7 @@
 #include "SogKripkeIteratorTh.h"
 
 
-SogKripkeIteratorTh::SogKripkeIteratorTh ( const LDDState* lddstate, bdd cnd ) :m_lddstate ( lddstate ), kripke_succ_iterator ( cnd )
+SogKripkeIteratorTh::SogKripkeIteratorTh ( LDDState* lddstate, bdd cnd ) :m_lddstate ( lddstate ), kripke_succ_iterator ( cnd )
 {
     for ( int i=0; i<m_lddstate->getSuccessors()->size(); i++ ) {
         m_lsucc.push_back ( m_lddstate->getSuccessors()->at ( i ) );
@@ -50,21 +50,16 @@ SogKripkeStateTh* SogKripkeIteratorTh::dst() const
 
 bdd SogKripkeIteratorTh::cond()  const
 {
-    //cout<<"entering "<<__func__<<endl;
     if ( m_lsucc.at ( m_current_edge ).second==-1 ) {
         return bddtrue;
     }
     spot::formula f=spot::formula::ap (string(m_builder->getTransition ( m_lsucc.at ( m_current_edge ).second )));
     spot::bdd_dict *p=m_dict_ptr->get();
     bdd   result=bdd_ithvar ( ( p->var_map.find ( f ) )->second );
-    //cout<<"leaving "<<__func__<<endl;
     return result & spot::kripke_succ_iterator::cond();
 }
 
-/*spot::acc_cond::mark_t SogKripkeIterator::acc() const {
-  //cout<<"Iterator acc()\n";
-  return 0U;
-}*/
+
 SogKripkeIteratorTh::~SogKripkeIteratorTh()
 {
     //dtor
@@ -79,4 +74,4 @@ void SogKripkeIteratorTh::recycle ( LDDState* aggregate, bdd cond )
 ModelCheckBaseMT * SogKripkeIteratorTh::m_builder;
 spot::bdd_dict_ptr* SogKripkeIteratorTh::m_dict_ptr;
 LDDState SogKripkeIteratorTh::m_deadlock;
-LDDState SogKripkeIteratorTh::m_div;
+//LDDState SogKripkeIteratorTh::m_div;
diff --git a/src/SogKripkeIteratorTh.h b/src/SogKripkeIteratorTh.h
index c5307b4c2549d541dc53ca7998de158de6258cfb..b3069a160b1926ebb89e47562e67b1a5640c7dfd 100644
--- a/src/SogKripkeIteratorTh.h
+++ b/src/SogKripkeIteratorTh.h
@@ -8,11 +8,11 @@ class SogKripkeIteratorTh : public spot::kripke_succ_iterator
 {
 public:
     static LDDState m_deadlock;
-    static LDDState m_div;
+    //static LDDState m_div;
     static ModelCheckBaseMT * m_builder;
     static spot::bdd_dict_ptr* m_dict_ptr;
   //  sog_succ_iterator(const RdPBDD& pn, const SogKripkeState& s, const bdd& c);
-    SogKripkeIteratorTh(const LDDState* lddstate, bdd cnd);
+    SogKripkeIteratorTh(LDDState* lddstate, bdd cnd);
     virtual ~SogKripkeIteratorTh();
     bool first() override;
     bool next() override;
diff --git a/src/SogKripkeTh.cpp b/src/SogKripkeTh.cpp
index f2836b17d8c46cfff59a25b6038211d598b619aa..7391a23938268f0bbbc980baff00133c7b90f650 100644
--- a/src/SogKripkeTh.cpp
+++ b/src/SogKripkeTh.cpp
@@ -19,10 +19,10 @@ SogKripkeTh::SogKripkeTh(const bdd_dict_ptr &dict_ptr,ModelCheckBaseMT *builder)
     SogKripkeIteratorTh::m_deadlock.setLDDValue(1);
     SogKripkeIteratorTh::m_deadlock.setVisited();
     SogKripkeIteratorTh::m_deadlock.setCompletedSucc();
-    SogKripkeIteratorTh::m_div.setLDDValue(0);
+    /*SogKripkeIteratorTh::m_div.setLDDValue(0);
     SogKripkeIteratorTh::m_div.setVisited();
     SogKripkeIteratorTh::m_div.setCompletedSucc();
-    SogKripkeIteratorTh::m_div.Successors.push_back(pair<LDDState*,int>(&SogKripkeIteratorTh::m_div,-1));
+    SogKripkeIteratorTh::m_div.Successors.push_back(pair<LDDState*,int>(&SogKripkeIteratorTh::m_div,-1));*/
 }
 
 SogKripkeTh::SogKripkeTh(const spot::bdd_dict_ptr& dict_ptr,ModelCheckBaseMT *builder,set<string> &l_transap,set<string> &l_placeap):SogKripkeTh(dict_ptr,builder) {
@@ -38,7 +38,7 @@ SogKripkeTh::SogKripkeTh(const spot::bdd_dict_ptr& dict_ptr,ModelCheckBaseMT *bu
 
 state* SogKripkeTh::get_init_state() const {
    LDDState *ss=m_builder->getInitialMetaState();   
-    return new SogKripkeStateTh(ss);//new SpotSogState();
+    return new SogKripkeStateTh(ss);
 
 }
 // Allows to print state label representing its id
@@ -48,7 +48,7 @@ std::string SogKripkeTh::format_state(const spot::state* s) const
     auto ss = static_cast<const SogKripkeStateTh*>(s);
     std::ostringstream out;
     out << "( " << ss->getLDDState()->getLDDValue() <<  ")";
-   // cout << " ( " << ss->getLDDState()->getLDDValue() <<  ")";
+
     return out.str();
   }
 
diff --git a/src/SylvanCacheWrapper.h b/src/SylvanCacheWrapper.h
index 0e651e286432d22f1224c49822ed9ba90cb4f9bb..2a3a255238b2a7f38adb614d21be693aab38197c 100644
--- a/src/SylvanCacheWrapper.h
+++ b/src/SylvanCacheWrapper.h
@@ -14,19 +14,19 @@ extern "C" {
 #endif /* __cplusplus */
 
 // MDD operations
-static const uint64_t CACHE_MDD_RELPROD             = (20LL<<40);
-static const uint64_t CACHE_MDD_MINUS               = (21LL<<40);
-static const uint64_t CACHE_MDD_UNION               = (22LL<<40);
-static const uint64_t CACHE_MDD_INTERSECT           = (23LL<<40);
-static const uint64_t CACHE_MDD_PROJECT             = (24LL<<40);
-static const uint64_t CACHE_MDD_JOIN                = (25LL<<40);
-static const uint64_t CACHE_MDD_MATCH               = (26LL<<40);
-static const uint64_t CACHE_MDD_RELPREV             = (27LL<<40);
-static const uint64_t CACHE_MDD_SATCOUNT            = (28LL<<40);
-static const uint64_t CACHE_MDD_DIVIDE              = (29LL<<40);
-static const uint64_t CACHE_LDD_MINUS               = (30LL<<40);
-static const uint64_t CACHE_LDD_FIRE                = (31LL<<40);
-static const uint64_t CACHE_LDD_UNION                = (32LL<<40);
+static const uint64_t CACHE_MDD_RELPROD             = (10LL<<40);
+static const uint64_t CACHE_MDD_MINUS               = (11LL<<40);
+static const uint64_t CACHE_MDD_UNION               = (12LL<<40);
+static const uint64_t CACHE_MDD_INTERSECT           = (13LL<<40);
+static const uint64_t CACHE_MDD_PROJECT             = (14LL<<40);
+static const uint64_t CACHE_MDD_JOIN                = (15LL<<40);
+static const uint64_t CACHE_MDD_MATCH               = (16LL<<40);
+static const uint64_t CACHE_MDD_RELPREV             = (17LL<<40);
+static const uint64_t CACHE_MDD_SATCOUNT            = (18LL<<40);
+static const uint64_t CACHE_MDD_DIVIDE              = (19LL<<40);
+static const uint64_t CACHE_LDD_MINUS               = (20LL<<40);
+static const uint64_t CACHE_LDD_FIRE                = (21LL<<40);
+static const uint64_t CACHE_LDD_UNION                = (22LL<<40);
 
 
 #ifdef __cplusplus
diff --git a/src/SylvanWrapper.cpp b/src/SylvanWrapper.cpp
index 77a128120a3eba5614baa37e7dfd60f88e073cb0..8c6cd3d1ca7cd5f143171e943f7cc98b8b7dc77b 100644
--- a/src/SylvanWrapper.cpp
+++ b/src/SylvanWrapper.cpp
@@ -13,6 +13,7 @@
 #include <sys/mman.h> // for mmap
 #include <iostream>
 #include <string>
+#include <stack>
 #include "SylvanCacheWrapper.h"
 #include "SylvanWrapper.h"
 
@@ -38,18 +39,18 @@ MDD lddmc_true = 1;
 
 uint64_t SylvanWrapper::getMarksCount(MDD cmark) {
     //typedef pair<string,MDD> Pair_stack;
-    vector<MDD> local_stack;
+    stack<MDD> local_stack;
     uint64_t compteur = 0;
     MDD explore_mdd;
-    local_stack.push_back(cmark);
+    local_stack.push(cmark);
     do {
-        explore_mdd = local_stack.back();
-        local_stack.pop_back();
+        explore_mdd = local_stack.top();
+        local_stack.pop();
         compteur++;
         while (explore_mdd != lddmc_false && explore_mdd != lddmc_true) {
             mddnode_t n_val = GETNODE(explore_mdd);
             if (mddnode_getright(n_val) != lddmc_false) {
-                local_stack.push_back(mddnode_getright(n_val));
+                local_stack.push(mddnode_getright(n_val));
             }
             //unsigned int val = mddnode_getvalue ( n_val );
             explore_mdd = mddnode_getdown(n_val);
@@ -136,7 +137,7 @@ llmsset2_t SylvanWrapper::llmsset_create(size_t initial_size, size_t max_size) {
     // that is a problem with multiple tables.
     // so, for now, do NOT use multiple tables!!
 
-    /*LACE_ME;*/
+
     INIT_THREAD_LOCAL(my_region);
 
     llmsset_reset_region();
@@ -241,10 +242,7 @@ void SylvanWrapper::sylvan_init_package(void) {
 }
 
 void SylvanWrapper::sylvan_init_ldd() {
-    /*sylvan_register_quit(lddmc_quit);
-    sylvan_gc_add_mark(TASK(lddmc_gc_mark_external_refs));
-    sylvan_gc_add_mark(TASK(lddmc_gc_mark_protected));
-    sylvan_gc_add_mark(TASK(lddmc_gc_mark_serialize));*/
+
     //m_lddmc_protected_created=0; // Should be initialized in the constructor
     refs_create(&m_lddmc_refs, 1024);
     if (!m_lddmc_protected_created) {
@@ -252,7 +250,7 @@ void SylvanWrapper::sylvan_init_ldd() {
         m_lddmc_protected_created = 1;
     }
 
-    //LACE_ME;
+
     lddmc_refs_init();
 }
 
@@ -262,8 +260,7 @@ void SylvanWrapper::lddmc_refs_init_task() {
     s->pend = s->pbegin + 1024;
     s->rcur = s->rbegin = (MDD *) malloc(sizeof(MDD) * 1024);
     s->rend = s->rbegin + 1024;
-    /* s->scur = s->sbegin = (lddmc_refs_task_t)malloc(sizeof(struct lddmc_refs_task) * 1024);
-     s->send = s->sbegin + 1024;*/
+
     SET_THREAD_LOCAL(lddmc_refs_key, s);
 }
 
@@ -392,11 +389,7 @@ MDD SylvanWrapper::lddmc_makenode(uint32_t value, MDD ifeq, MDD ifneq) {
         }
     }
 
-    /*if (created) {
-        sylvan_stats_count(LDD_NODES_CREATED);
 
-    }
-    else sylvan_stats_count(LDD_NODES_REUSED);*/
 
     return (MDD) index;
 }
@@ -634,7 +627,7 @@ MDD SylvanWrapper::lddmc_union_mono(MDD a, MDD b) {
     /* Access cache */
     MDD result;
     if (SylvanCacheWrapper::cache_get3(CACHE_LDD_UNION, a, b, 0, &result)) {
-        // std::cout<<"Cache succeeded!"<<std::endl;
+        //cout<<"cache get "<<__func__ <<endl;
         return result;
     }
 
@@ -711,7 +704,6 @@ MDD SylvanWrapper::lddmc_make_copynode(MDD ifeq, MDD ifneq) {
 
 bool SylvanWrapper::isSingleMDD(MDD mdd) {
     mddnode_t node;
-
     while (mdd > lddmc_true) {
         node = GETNODE(mdd);
         if (mddnode_getright(node) != lddmc_false) return false;
@@ -721,7 +713,7 @@ bool SylvanWrapper::isSingleMDD(MDD mdd) {
 }
 
 // Renvoie le nbre de noeuds à un niveau donné
-int SylvanWrapper::get_mddnbr(MDD mdd, int level) {
+int SylvanWrapper::get_mddnbr(MDD mdd, unsigned int level) {
     mddnode_t node;
     for (int j = 0; j < level; j++) {
         node = GETNODE(mdd);
@@ -816,7 +808,7 @@ MDD SylvanWrapper::ldd_minus(MDD a, MDD b) {
 }
 
 
-MDD SylvanWrapper::lddmc_firing_mono(MDD cmark, MDD minus, MDD plus) {
+MDD SylvanWrapper::lddmc_firing_mono(MDD cmark, const MDD minus,const MDD plus) {
     // for an empty set of source states, or an empty transition relation, return the empty set
     if (cmark == lddmc_true) return lddmc_true;
     if (minus == lddmc_false || plus == lddmc_false) return lddmc_false;
@@ -825,6 +817,7 @@ MDD SylvanWrapper::lddmc_firing_mono(MDD cmark, MDD minus, MDD plus) {
     MDD _cmark = cmark, _minus = minus, _plus = plus;
 
     if (SylvanCacheWrapper::cache_get3(CACHE_LDD_FIRE, cmark, minus, plus, &result)) {
+
         return result;
     }
     MDD cache_cmark = cmark;
@@ -911,40 +904,38 @@ MDD SylvanWrapper::lddmc_project(const MDD mdd, const MDD proj) {
 int SylvanWrapper::isGCRequired() {
     return (m_g_created > llmsset_get_size(m_nodes) / 2);
 }
-
+/*
+ * Convert MDD cmark to a string
+ */
 void SylvanWrapper::convert_wholemdd_stringcpp(MDD cmark, string &res) {
     typedef pair<string, MDD> Pair_stack;
-    vector<Pair_stack> local_stack;
-
+    stack<Pair_stack> local_stack;
     unsigned int compteur = 0;
     MDD explore_mdd = cmark;
-
     string chaine;
-
     res = "  ";
-    local_stack.push_back(Pair_stack(chaine, cmark));
+    local_stack.push(Pair_stack(chaine, cmark));
     do {
-        Pair_stack element = local_stack.back();
+        Pair_stack element = local_stack.top();
         chaine = element.first;
         explore_mdd = element.second;
-        local_stack.pop_back();
+        local_stack.pop();
         compteur++;
         while (explore_mdd != lddmc_false && explore_mdd != lddmc_true) {
             mddnode_t n_val = GETNODE(explore_mdd);
             if (mddnode_getright(n_val) != lddmc_false) {
-                local_stack.push_back(Pair_stack(chaine, mddnode_getright(n_val)));
+                local_stack.push(Pair_stack(chaine, mddnode_getright(n_val)));
             }
             unsigned int val = mddnode_getvalue(n_val);
-
             chaine.push_back((unsigned char) (val) + 1);
             explore_mdd = mddnode_getdown(n_val);
         }
-        /*printchaine(&chaine);printf("\n");*/
         res += chaine;
-    } while (local_stack.size() != 0);
+    } while (!local_stack.empty());
     //delete chaine;
 
     compteur = (compteur << 1) | 1;
+    //cout<<"compteur "<<compteur<<endl;
     res[1] = (unsigned char) ((compteur >> 8) + 1);
     res[0] = (unsigned char) (compteur & 255);
 
@@ -952,7 +943,6 @@ void SylvanWrapper::convert_wholemdd_stringcpp(MDD cmark, string &res) {
 
 void SylvanWrapper::sylvan_gc_seq() {
     if (m_g_created > llmsset_get_size(m_nodes) / 1000) {
-        cout<<"Cache executed"<<endl;
         SylvanCacheWrapper::cache_clear();
         llmsset_clear_data(m_nodes);
         ldd_gc_mark_protected();
diff --git a/src/SylvanWrapper.h b/src/SylvanWrapper.h
index 97aeb28dbe46a65304c5679d6e6e5714105efb4e..58030b764c5223763089741028ff6b6272f10d15 100644
--- a/src/SylvanWrapper.h
+++ b/src/SylvanWrapper.h
@@ -6,6 +6,7 @@
 #define PMC_SOG_SYLVANWRAPPER_H
 #include <cstdint>
 #include <cstddef>
+#include <string>
 
 /**
  * Lockless hash table (set) to store 16-byte keys.
@@ -121,7 +122,7 @@ public:
 
     static void sylvan_set_limits(size_t memorycap, int table_ratio, int initial_ratio);
 
-    static void sylvan_init_package(void);
+    static void sylvan_init_package();
 
     inline static mddnode_t GETNODE(MDD mdd) { return ((mddnode_t) llmsset_index_to_ptr(m_nodes, mdd)); }
 
@@ -176,7 +177,7 @@ public:
 
     static bool isSingleMDD(MDD mdd);
 
-    static int get_mddnbr(MDD mdd, int level);
+    static int get_mddnbr(MDD mdd, unsigned int level);
 
     static MDD ldd_divide_rec(MDD a, int level);
 
@@ -184,7 +185,7 @@ public:
 
     static MDD ldd_minus(MDD a, MDD b);
 
-    static MDD lddmc_firing_mono(MDD cmark, MDD minus, MDD plus);
+    static MDD lddmc_firing_mono(MDD cmark, const MDD minus, const MDD plus);
 
     static size_t lddmc_nodecount_mark(MDD mdd);
 
diff --git a/src/TransSylvan.cpp b/src/TransSylvan.cpp
index c72581f05ccdd6ec3767888f9bcddc91380cd9be..fd9e0c8070564657e3c818452a1ae95334e8d63b 100644
--- a/src/TransSylvan.cpp
+++ b/src/TransSylvan.cpp
@@ -1,6 +1,3 @@
-#include <cstdint>
-#include <cstddef>
-#include <string>
 #include "SylvanWrapper.h"
 #include "TransSylvan.h"
 
@@ -9,22 +6,12 @@ TransSylvan::TransSylvan(const MDD &_minus, const MDD &_plus):m_minus(_minus),m_
     //ctor
 }
 
-TransSylvan::~TransSylvan()
-{
-    //dtor
-}
-void TransSylvan::setMinus(MDD _minus) {
-    m_minus=_minus;
-}
-
-void TransSylvan::setPlus(MDD _plus) {
-    m_plus=_plus;
-}
+TransSylvan::~TransSylvan()=default;
 
-MDD TransSylvan::getMinus() {
+MDD TransSylvan::getMinus() const {
     return m_minus;
 }
 
-MDD TransSylvan::getPlus() {
+MDD TransSylvan::getPlus() const {
     return m_plus;
 }
diff --git a/src/TransSylvan.h b/src/TransSylvan.h
index 0c9849c431a8700ea0a764de31386cd87ecb8676..ca24694cbe3817c38d0fc306006782ae0c1db7fd 100755
--- a/src/TransSylvan.h
+++ b/src/TransSylvan.h
@@ -7,12 +7,8 @@ class TransSylvan {
  public:
   TransSylvan(const MDD &_minus, const MDD &_plus);
   virtual ~TransSylvan();
-  void setMinus(MDD _minus);
-  void setPlus(MDD _plus);
-  MDD getMinus();
-  MDD getPlus();
-
- protected:
+  [[nodiscard]] MDD getMinus() const;
+  [[nodiscard]] MDD getPlus() const;
  private:
   MDD m_minus, m_plus;
 };
diff --git a/src/main.cpp b/src/main.cpp
index c0948776fb20e0b77aff46c7bee8d21d5d1b86ba..842624afab5845280b961252ec25da8a7ded4037 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -31,7 +31,7 @@
 #include "SogKripkeTh.h"
 #include "HybridKripke.h"
 #include "SylvanWrapper.h"
-
+#include "PMCSOGConfig.h"
 // #include "RdPBDD.h"
 
 using namespace std;
@@ -78,9 +78,8 @@ void displayCheckResult(bool res) {
 	else
 		cout << "Property is violated..." << endl;
 }
-void displayTime(auto startTime, auto finalTime) {
-	cout << "Verification duration : " << std::chrono::duration_cast < std::chrono::milliseconds
-			> (finalTime - startTime).count() << " milliseconds\n";
+void displayTime(auto startTime,auto finalTime) {
+	cout << "Verification duration : " << std::chrono::duration_cast < std::chrono::milliseconds> (finalTime - startTime).count() << " milliseconds\n";
 
 }
 /***********************************************/
@@ -96,13 +95,18 @@ int main(int argc, char **argv) {
 	}
 
 	nb_th = atoi(argv[2]) == 0 ? 1 : atoi(argv[2]);
-
-	cout << "Net file : " << argv[3] << endl;
-	cout << "Formula file : " << formula << endl;
-	cout << "Checking algorithm : " << algorithm << endl;
-
-	cout << "thread : " << argv[2] << endl;
-
+    MPI_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &n_tasks);
+    MPI_Comm_rank(MPI_COMM_WORLD, &task_id);
+    if (!task_id) {
+        cout << "PMC-SOG : Parallel Model Checking tool based on Symbolic Observation Graphs " << endl;
+        cout << "Version " <<PMCSOG_VERSION_MAJOR<<"."<<PMCSOG_VERSION_MINOR<<"."<<PMCSOG_VERSION_PATCH<<endl;
+        cout << "(c) 2018 - 2020"<<endl;
+        cout << "Net file : " << argv[3] << endl;
+        cout << "Formula file : " << formula << endl;
+        cout << "Checking algorithm : " << algorithm << endl;
+        cout << "#threads : " << nb_th << endl;
+    }
 	if (nb_th == 0) {
 		cout << "number of thread <= 0 " << endl;
 		exit(0);
@@ -111,13 +115,8 @@ int main(int argc, char **argv) {
 	cout << "______________________________________\n";
 	cout << "Fetching formula..." << endl;
 	set<string> list_propositions = buildPropositions(formula);
-
 	NewNet Rnewnet(argv[3], list_propositions);
 
-	MPI_Init(&argc, &argv);
-	MPI_Comm_size(MPI_COMM_WORLD, &n_tasks);
-	MPI_Comm_rank(MPI_COMM_WORLD, &task_id);
-
 
     if (n_tasks == 1) {
         if (n_tasks == 1 && (!strcmp(argv[1], "otfPR") || !strcmp(argv[1], "otfC") || !strcmp(argv[1], "otfP"))) {
@@ -133,22 +132,8 @@ int main(int argc, char **argv) {
 
             spot::twa_graph_ptr af = spot::translator(d).run(not_f);
             cout << "Formula automata built.\n";
-            /*cout << "Want to save the graph in a dot file ?";
-             char c;
-             cin >> c;
-             if (c == 'y') {
-             fstream file;
-             string st(formula);
-             st += ".dot";
-             file.open(st.c_str(), fstream::out);
-             spot::print_dot(file, af);
-             file.close();
-             }
-             cout << "Loading net information..." << endl;*/
             ModelCheckBaseMT *mcl;
-            /*if (!strcmp(argv[1], "otfL"))
-                mcl = new ModelCheckLace(Rnewnet, nb_th);
-            else*/
+
             if (!strcmp(argv[1], "otfP"))
                 mcl = new ModelCheckerTh(Rnewnet, nb_th);
             else if (!strcmp(argv[1], "otfC"))
@@ -177,13 +162,6 @@ int main(int argc, char **argv) {
                 auto finalTime = std::chrono::steady_clock::now();
                 displayTime(startTime, finalTime);
                 displayCheckResult(res);
-                /****************************/
-
-                /*auto startTime = std::chrono::steady_clock::now();
-                 bool res = (check.check() == 0);
-                 auto finalTime = std::chrono::steady_clock::now();
-                 displayTime(startTime, finalTime);
-                 displayCheckResult(res);*/
 
             } else {
                 auto startTime = std::chrono::steady_clock::now();
@@ -191,24 +169,9 @@ int main(int argc, char **argv) {
                 auto finalTime = std::chrono::steady_clock::now();
                 displayTime(startTime, finalTime);
                 displayCheckResult(res);
-                /*
-                 if (!resauto run = k->intersecting_run(af)) {
-                 cout << "formula is violated by the following run:\n" << *run << endl;
-                 cout << "==================================" << endl;
-                 /*run->highlight(5); // 5 is a color number.
-                 fstream file;
-                 file.open("violated.dot",fstream::out);
-                 cout<<"Property is violated!"<<endl;
-                 cout<<"Check the dot file."<<endl;
-                 spot::print_dot(file, k, ".kA");
-                 file.close();*/
-                /*} else {
-                 std::cout << "formula is verified\n";
-                 auto finalTime = std::chrono::high_resolution_clock::now();
-                 displayTime(startTime, finalTime);
-
-                 }*/
             }
+            mcl->finish();
+            cout<<"Number of built aggregates: "<<mcl->getGraph()->m_GONodes.size()<<endl;
             delete mcl;
         }
 
diff --git a/src/md5_hash.h b/src/md5_hash.h
new file mode 100644
index 0000000000000000000000000000000000000000..086defced6893f4f689f8b8e1b181f8561859168
--- /dev/null
+++ b/src/md5_hash.h
@@ -0,0 +1,204 @@
+//
+// Created by chiheb on 10/12/2020.
+//
+
+#ifndef PMC_SOG_MD5_HASH_H
+#define PMC_SOG_MD5_HASH_H
+
+
+#include <string>
+#include <array>
+
+// info and algorithm: https://en.wikipedia.org/wiki/MD5
+class md5_hash
+{
+public:
+
+    /**
+     * \param message message to processing
+     * \return get md5-hash from message
+     */
+    [[nodiscard]] static void compute(const std::string& message,unsigned char *result)
+    {
+        // These vars will contain the hash
+        uint32_t a0 = 0x67452301, b0 = 0xefcdab89, c0 = 0x98badcfe, d0 = 0x10325476;
+        size_t new_len = message.size() + 1;
+
+        //Pre-processing:
+        //append "1" bit to message
+        //append "0" bits until message length in bits ≡ 448 (mod 512)
+        //append length mod (2^64) to message
+        while (new_len % (512 / 8) != 448 / 8)
+            new_len++;
+
+        std::string msg_copy = message; msg_copy.resize(new_len + 8);
+        msg_copy[message.size()] = 0x80; // append the "1" bit; most significant bit is "first"
+
+        std::array<uint8_t, 4> bytes = md5_hash::uint32_to_4_bytes(message.size() * 8);
+        for (size_t i = new_len; i < new_len + 4; i++)
+            msg_copy[i] = bytes[i - new_len];
+
+        bytes = md5_hash::uint32_to_4_bytes(message.size() >> 29);
+        for (size_t i = new_len + 4; i < new_len + 8; i++)
+            msg_copy[i] = bytes[i - new_len - 4];
+
+        // process the message in successive 512-bit chunks
+        for (size_t i = 0; i < new_len; i += (512 / 8))
+        {
+            uint32_t w[16];
+
+            for (size_t j = 0; j < 16; j++)
+            {
+                const std::array<uint8_t, 4> array {
+                        static_cast<uint8_t>(msg_copy[i + j * 4]),
+                        static_cast<uint8_t>(msg_copy[i + j * 4 + 1]),
+                        static_cast<uint8_t>(msg_copy[i + j * 4 + 2]),
+                        static_cast<uint8_t>(msg_copy[i + j * 4 + 3]),
+                };
+
+                w[j] = md5_hash::uint32_from_4_bytes(array);
+            }
+
+            uint32_t a = a0, b = b0, c = c0, d = d0;
+
+            for (size_t j = 0; j < 64; j++)
+            {
+                uint32_t f, g;
+
+                // F(B, C, D)= (B and C) or (not B and D)
+                // G(B, C, D)= (B and D) or (C and not D)
+                // H(B, C, D)= B xor C xor D
+                // I(B, C, D)= C xor (B or not D)
+                if (j < 16)
+                {
+                    f = (b & c) | ((~b) & d);
+                    g = j;
+                }
+                else if (j < 32)
+                {
+                    f = (d & b) | (c & (~d));
+                    g = (5 * j + 1) % 16;
+                }
+                else if (j < 48)
+                {
+                    f = b ^ c ^ d;
+                    g = (3 * j + 5) % 16;
+                }
+                else
+                {
+                    f = c ^ (b | (~d));
+                    g = (7 * j) % 16;
+                }
+
+                const uint32_t temp = d;
+                d = c;
+                c = b;
+                b = b + md5_hash::rotate_left((a + f + md5_hash::k[j] + w[g]), md5_hash::r[j]);
+                a = temp;
+            }
+
+            // add this chunk's hash to result so far:
+            a0 += a;
+            b0 += b;
+            c0 += c;
+            d0 += d;
+        }
+
+        const std::array<uint8_t, 4> a0_arr = md5_hash::uint32_to_4_bytes(a0);
+        const std::array<uint8_t, 4> b0_arr = md5_hash::uint32_to_4_bytes(b0);
+        const std::array<uint8_t, 4> c0_arr = md5_hash::uint32_to_4_bytes(c0);
+        const std::array<uint8_t, 4> d0_arr = md5_hash::uint32_to_4_bytes(d0);
+
+        // append results bytes
+
+        result[0] = a0_arr[0];
+        result[1] = a0_arr[1];
+        result[2] = a0_arr[2];
+        result[3] = a0_arr[3];
+
+        result[4]=b0_arr[0];
+        result[5]=b0_arr[1];
+        result[6]=b0_arr[2];
+        result[7]=b0_arr[3];
+
+        result[8]=c0_arr[0];
+        result[9]=c0_arr[1];
+        result[10]=c0_arr[2];
+        result[11]=c0_arr[3];
+
+        result[12]=d0_arr[0];
+        result[13]=d0_arr[1];
+        result[14]=d0_arr[2];
+        result[15]=d0_arr[3];
+
+
+       // return result;
+    }
+private:
+    md5_hash() = default;
+
+    // rol command: https://www.aldeid.com/wiki/X86-assembly/Instructions/rol
+    static uint32_t rotate_left(const uint32_t x, const int32_t n)
+    {
+        return (x << n) | (x >> (32 - n));
+    }
+
+    // cast unsigned integer to to a four-element array
+    static std::array<uint8_t, 4> uint32_to_4_bytes(uint32_t value)
+    {
+        std::array<uint8_t, 4> bytes{};
+
+        bytes[0] = static_cast<uint8_t>(value);
+        bytes[1] = static_cast<uint8_t>(value >> 8);
+        bytes[2] = static_cast<uint8_t>(value >> 16);
+        bytes[3] = static_cast<uint8_t>(value >> 24);
+
+        return bytes;
+    }
+
+    // cast a four-element array to unsigned integer
+    static uint32_t uint32_from_4_bytes(std::array<uint8_t, 4> bytes)
+    {
+        uint32_t value = 0;
+
+        value = (value << 8) + bytes[3];
+        value = (value << 8) + bytes[2];
+        value = (value << 8) + bytes[1];
+        value = (value << 8) + bytes[0];
+
+        return value;
+    }
+
+    // table, computed by this code:
+    /*
+        for i from 0 to 63
+            K[i] : = floor(232 × abs(sin(i + 1)))
+    */
+    constexpr static uint32_t k[64] = {
+            0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
+            0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
+            0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
+            0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
+            0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
+            0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
+            0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
+            0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
+            0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
+            0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
+            0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
+            0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
+            0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
+            0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
+            0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
+            0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+    };
+
+    // specifies the per-round shift amounts
+    constexpr static uint32_t r[64] = {
+            7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+            5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
+            4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+            6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
+    };
+};
+#endif //PMC_SOG_MD5_HASH_H