diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a042d27f9947f696921e586c1d8ade70a4034042..4a476dd2cd49c0eb5e8c05334843f7488fda8c6e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -66,6 +66,14 @@ add_executable(hybrid-sog main.cpp
   SogKripkeIteratorOTF.h
   SogKripkeOTF.cpp
   SogKripkeOTF.h
+  SogKripkeTh.cpp
+  SogKripkeTh.h
+  SogKripkeStateTh.cpp
+  SogKripkeStateTh.h
+  SogKripkeIteratorTh.cpp
+  SogKripkeIteratorTh.h
+  ModelCheckerTh.cpp
+  ModelCheckerTh.h
   )
 
 target_link_libraries(hybrid-sog
diff --git a/src/ModelCheckerTh.cpp b/src/ModelCheckerTh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..013532a069ea10d89456fc8fa21a350b3e3213e3
--- /dev/null
+++ b/src/ModelCheckerTh.cpp
@@ -0,0 +1,289 @@
+#include "ModelCheckerTh.h"
+
+#include "sylvan.h"
+#include "sylvan_seq.h"
+#include <sylvan_sog.h>
+#include <sylvan_int.h>
+
+using namespace sylvan;
+ModelCheckerTh::ModelCheckerTh(const NewNet &R, int BOUND,int nbThread)
+{
+    m_nb_thread=nbThread;
+    lace_init(1, 0);
+    lace_startup(0, NULL, NULL);
+
+    sylvan_set_limits(2LL<<30, 16, 3);
+    sylvan_init_package();
+    sylvan_init_ldd();
+//    LACE_ME;
+    m_net=R;
+
+
+    int  i;
+    vector<Place>::const_iterator it_places;
+
+
+    init_gc_seq();
+
+
+    //_______________
+    transitions=R.transitions;
+    m_observable=R.Observable;
+    m_place_proposition=R.m_formula_place;
+    m_nonObservable=R.NonObservable;
+
+    m_transitionName=R.transitionName;
+    m_placeName=R.m_placePosName;
+
+    cout<<"Toutes les Transitions:"<<endl;
+    map<string,int>::iterator it2=m_transitionName.begin();
+    for (; it2!=m_transitionName.end(); it2++)
+    {
+        cout<<(*it2).first<<" : "<<(*it2).second<<endl;
+    }
+
+
+
+    cout<<"Transitions observables :"<<endl;
+    Set::iterator it=m_observable.begin();
+    for (; it!=m_observable.end(); it++)
+    {
+        cout<<*it<<"  ";
+    }
+    cout<<endl;
+    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;
+
+    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_initalMarking=lddmc_cube(liste_marques,R.places.size());
+
+
+
+
+
+    uint32_t *prec = new uint32_t[m_nbPlaces];
+    uint32_t *postc= new uint32_t [m_nbPlaces];
+    // Transition relation
+    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;
+        }
+        // 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);
+            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);
+            postc[it->first] = postc[it->first] + it->second;
+
+        }
+        for(set<int>::const_iterator it=adjacentPlace.begin(); it!=adjacentPlace.end(); it++)
+        {
+            MDD Precond=lddmc_true;
+            Precond = Precond & ((*it) >= prec[*it]);
+        }
+
+        MDD _minus=lddmc_cube(prec,m_nbPlaces);
+        ldd_refs_push(_minus);
+        MDD _plus=lddmc_cube(postc,m_nbPlaces);
+        ldd_refs_push(_plus);
+        m_tb_relation.push_back(TransSylvan(_minus,_plus));
+    }
+    delete [] prec;
+    delete [] postc;
+    m_graph=new LDDGraph(this);
+    m_graph->setTransition(m_transitionName);
+    m_graph->setPlace(m_placeName);
+}
+
+
+string ModelCheckerTh::getTransition(int pos)
+{
+    return m_graph->getTransition(pos);
+}
+
+string ModelCheckerTh::getPlace(int pos)
+{
+    return m_graph->getPlace(pos);
+}
+
+
+LDDState * ModelCheckerTh::buildInitialMetaState()
+{        Set fire;
+
+        LDDState *c=new LDDState;
+        LDDState *reached_class;
+         MDD initial_meta_state(Accessible_epsilon(m_initalMarking));
+        ldd_refs_push(initial_meta_state);
+        fire=firable_obs(initial_meta_state);
+
+        c->m_lddstate=initial_meta_state;
+       // m_old_size=lddmc_nodecount(c->m_lddstate);
+        m_graph->setInitialState(c);
+        m_graph->insert(c);
+
+    // Compute successors
+
+   /* for (unsigned int i=0; i<onb_it; i++)
+    {
+        Set::iterator it = fire.end();
+        it--;
+        int t=*it;
+        fire.erase(it);
+        MDD Complete_meta_state=Accessible_epsilon(it);
+        reached_class=new LDDState;
+        reached_class->m_lddstate=Complete_meta_state;
+        m_graph->addArc();
+        m_graph->insert(reached_class);
+        c->Successors.insert(c->Successors.begin(),LDDEdge(reached_class,t));
+        reached_class->Predecessors.insert(reached_class->Predecessors.begin(),LDDEdge(c,t));
+    } */
+
+    return c;
+}
+
+void ModelCheckerTh::buildSucc(LDDState *agregate)
+{
+   if (!agregate->isVisited()) {
+   agregate->setVisited();
+   LDDState *reached_class=nullptr;
+
+}
+}
+
+/*void * ModelCheckerTh::Compute_successors()
+{
+    int id_thread;
+    int nb_it=0,nb_failed=0,max_succ=0;
+    pthread_mutex_lock(&m_mutex);
+    id_thread=m_id_thread++;
+    pthread_mutex_unlock(&m_mutex);
+    Set fire;
+    LDDState* reached_class;
+    // size_t max_meta_state_size;
+    // int min_charge;
+    do
+    {
+
+        while (!m_st[id_thread].empty())
+        {
+
+            nb_it++;
+            m_terminaison[id_thread]=false;
+            pthread_spin_lock(&m_spin_stack[id_thread]);
+            Pair  e=m_st[id_thread].top();
+            //pthread_spin_lock(&m_accessible);
+            m_st[id_thread].pop();
+
+            pthread_spin_unlock(&m_spin_stack[id_thread]);
+            m_nbmetastate--;
+
+            m_charge[id_thread]--;
+            while(!e.second.empty())
+            {
+                int t = *e.second.begin();
+                e.second.erase(t);
+                reached_class=new LDDState();
+                if (id_thread)
+                {
+                    pthread_mutex_lock(&m_supervise_gc_mutex);
+                    m_gc++;
+                    if (m_gc==1) {
+                        pthread_mutex_lock(&m_gc_mutex);
+                    }
+                    pthread_mutex_unlock(&m_supervise_gc_mutex);
+                }
+
+
+                MDD Complete_meta_state=Accessible_epsilon(get_successor(e.first.second,t));
+
+                ldd_refs_push(Complete_meta_state);
+
+                if (id_thread==0)
+                {
+                    pthread_mutex_lock(&m_gc_mutex);
+                    sylvan_gc_seq();
+
+                    pthread_mutex_unlock(&m_gc_mutex);
+                }
+                reached_class->m_lddstate=Complete_meta_state;
+
+                pthread_mutex_lock(&m_graph_mutex);
+
+                LDDState* pos=m_graph->find(reached_class);
+
+                if(!pos)
+                {
+
+                    m_graph->addArc();
+                    m_graph->insert(reached_class);
+                    pthread_mutex_unlock(&m_graph_mutex);
+
+                    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_nbmetastate++;
+                    //pthread_mutex_lock(&m_mutex);
+                    fire=firable_obs(Complete_meta_state);
+                    //if (max_succ<fire.size()) max_succ=fire.size();
+                    //pthread_mutex_unlock(&m_mutex);
+                    m_min_charge= minCharge();
+                    //m_min_charge=(m_min_charge+1) % m_nb_thread;
+                    pthread_spin_lock(&m_spin_stack[m_min_charge]);
+                    m_st[m_min_charge].push(Pair(couple(reached_class,Complete_meta_state),fire));
+                    pthread_spin_unlock(&m_spin_stack[m_min_charge]);
+                    m_charge[m_min_charge]++;
+                }
+                else
+                {
+                    nb_failed++;
+                    m_graph->addArc();
+                    pthread_mutex_unlock(&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));
+                    delete reached_class;
+
+                }
+                if (id_thread)
+                {
+                    pthread_mutex_lock(&m_supervise_gc_mutex);
+                    m_gc--;
+                    if (m_gc==0) pthread_mutex_unlock(&m_gc_mutex);
+                    pthread_mutex_unlock(&m_supervise_gc_mutex);
+                }
+            }
+        }
+        m_terminaison[id_thread]=true;
+
+
+
+    }
+    while (isNotTerminated());
+    //cout<<"Thread :"<<id_thread<<"  has performed "<<nb_it<<" itérations avec "<<nb_failed<<" échecs"<<endl;
+    //cout<<"Max succ :"<<max_succ<<endl;
+}
+
+
+void * ModelCheckerTh::threadHandler(void *context)
+{
+    return ((ModelCheckerTh*)context)->Compute_successors();
+} */
diff --git a/src/ModelCheckerTh.h b/src/ModelCheckerTh.h
new file mode 100644
index 0000000000000000000000000000000000000000..12bb4a635ee46e5b149bca7590b268a5fbc858af
--- /dev/null
+++ b/src/ModelCheckerTh.h
@@ -0,0 +1,36 @@
+#ifndef MODELCHECKERTH_H
+#define MODELCHECKERTH_H
+#include "CommonSOG.h"
+class ModelCheckerTh : public CommonSOG
+{
+public:
+    ModelCheckerTh(const NewNet &R, int BOUND,int nbThread);
+    LDDState * buildInitialMetaState();
+    string getTransition(int pos);
+    string getPlace(int pos);
+    void buildSucc(LDDState *agregate);
+   // static void *threadHandler(void *context);
+   // void *Compute_successors();
+
+
+
+private:
+    int m_nb_thread;
+    MDD m_initalMarking;
+
+    pile m_st[128];
+    int m_charge[128];
+    bool m_terminaison[128];
+
+
+    pthread_mutex_t m_mutex;
+    pthread_mutex_t m_graph_mutex;
+    pthread_mutex_t m_gc_mutex;
+    pthread_mutex_t m_supervise_gc_mutex;
+    unsigned int m_gc;
+
+    pthread_mutex_t m_mutex_stack[128];
+    pthread_spinlock_t m_spin_stack[128];
+    pthread_t m_list_thread[128];
+};
+#endif
diff --git a/src/main.cpp b/src/main.cpp
index 7dc13f6a179ad529ac7db51526e408f595587324..4c29dd70af7565b735485b63d2845710cab4a404 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,6 +13,7 @@
 #include "HybridSOG.h"
 #include "LDDGraph.h"
 #include "ModelCheckLace.h"
+#include "ModelCheckerTh.h"
 
 #include <spot/misc/version.hh>
 #include <spot/twaalgos/dot.hh>
@@ -25,6 +26,7 @@
 #include "SogTwa.h"
 #include "SogKripke.h"
 #include "SogKripkeOTF.h"
+#include "SogKripkeTh.h"
 
 
 
@@ -125,7 +127,7 @@ int main(int argc, char** argv)
     MPI_Comm_rank(MPI_COMM_WORLD,&task_id);
 
     //
-    if (n_tasks==1 && !strcmp(argv[1],"otf"))
+    if (n_tasks==1 && !strcmp(argv[1],"otfL"))
     {
         cout<<"Multi-threaded on the fly Model checking..."<<endl;
         cout<<"Building automata for not(formula)\n";
@@ -168,6 +170,50 @@ int main(int argc, char** argv)
             std::cout << "formula is verified\n";
 
     }
+    else if (n_tasks==1 && !strcmp(argv[1],"otfTh"))
+    {
+     cout<<"Multi-threaded on the fly Model checking..."<<endl;
+        cout<<"Building automata for not(formula)\n";
+        auto d = spot::make_bdd_dict();
+        // d->register_ap("jbhkj");
+        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();
+        }
+        // Initialize SOG builder
+        ModelCheckerTh* mcl=new ModelCheckerTh(R,bound,nb_th);
+        cout<<"Created"<<endl;
+        auto k =
+            std::make_shared<SogKripkeTh>(d,mcl,R.getListTransitionAP(),R.getListPlaceAP());                                 ;
+        // Performing on the fly Modelchecking
+        cout<<"Performing on the fly Modelchecking"<<endl;
+
+        if (auto run = k->intersecting_run(af))
+        {
+            std::cout << "formula is violated by the following run:\n"<<*run<<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";
+
+    }
+
     else if (n_tasks==1)
     {
         cout<<"number of task = 1 \n " <<endl;