diff --git a/README.md b/README.md
index 77db7b8394d540fc658d43c2efd96bfaed75e6a4..79810f39ebba8d2de4bfc1d921548fa5077aa2ec 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,6 @@ BuDDy used for sequential version and Sylvan for both sequential and parallel co
 
 It is necessary to install Spot [Spot](https://spot.lrde.epita.fr/install.html).
 
-# Hybrid-SOG
 ## Description
 This repository hosts the experiments and results for the Hybrid (MPI/pthreads) approach for the SOG construction and provides a short guide on how to install the tools and reproduce the results.
 
@@ -48,7 +47,8 @@ arg1: specifies method of creating threads or/and specifies if modelchecking sho
      * pc : using pthread library and applying canonization on nodes
      * l : using lace framework
      * lc : using lace framework and applying canonization on nodes
-     * otf : perform modelchecking on the fly using laceframework
+     * otfL : perform modelchecking on the fly using laceframework
+     * otfP : perform modelchecking on the fly using pthread
 arg2: specifies the number of threads/workers to be created
 arg3: specifies the net to build its SOG
 arg4: specifies the LTL formula file
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..55925ec7565590f222c4af507489bda1dbb8346c
--- /dev/null
+++ b/src/ModelCheckerTh.cpp
@@ -0,0 +1,303 @@
+#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_graph->setInitialState(c);
+    m_graph->insert(c);
+    m_st[0].push(c);
+    ComputeTh_Succ();
+    return c;
+}
+
+void ModelCheckerTh::buildSucc(LDDState *agregate)
+{
+    if (!agregate->isVisited())
+    {
+        agregate->setVisited();
+        m_min_charge=minCharge();
+        pthread_spin_lock(&m_spin_stack[m_min_charge]);
+        m_st[m_min_charge].push(agregate);
+        pthread_spin_unlock(&m_spin_stack[m_min_charge]);
+
+    }
+}
+
+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=nullptr;
+    // 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]);
+            LDDState* agregate=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--;
+            MDD meta_state=agregate->getLDDValue();
+            Set fire=firable_obs(meta_state);
+
+            //compute successors
+            Set::const_iterator iter=fire.begin();
+            while(iter!=fire.end())
+            {
+                int t = *iter;
+
+                MDD complete_state=Accessible_epsilon(get_successor(meta_state,t));
+                iter++;
+                reached_class=new LDDState;
+                reached_class->m_lddstate=complete_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);
+
+                    agregate->Successors.insert(agregate->Successors.begin(),LDDEdge(reached_class,t));
+                    reached_class->Predecessors.insert(reached_class->Predecessors.begin(),LDDEdge(agregate,t));
+
+                }
+                else
+                {
+                    m_graph->addArc();
+                    pthread_mutex_unlock(&m_graph_mutex);
+                    agregate->Successors.insert(agregate->Successors.begin(),LDDEdge(pos,t));
+                    pos->Predecessors.insert(pos->Predecessors.begin(),LDDEdge(agregate,t));
+                    delete reached_class;
+                }
+            }
+
+
+        }
+        m_terminaison[id_thread]=true;
+
+
+
+    }
+    while (isNotTerminated());
+
+}
+
+bool ModelCheckerTh::isNotTerminated()
+{
+    bool res=true;
+    int i=0;
+    while (i<m_nb_thread && res)
+    {
+        res=m_terminaison[i];
+        i++;
+    }
+    return !res;
+}
+
+int ModelCheckerTh::minCharge()
+{
+    int pos=0;
+    int min_charge=m_charge[0];
+    for (int i=1; i<m_nb_thread; i++)
+    {
+        if (m_charge[i]<min_charge)
+        {
+            min_charge=m_charge[i];
+            pos=i;
+        }
+    }
+    return pos;
+
+}
+
+void * ModelCheckerTh::threadHandler(void *context)
+{
+    return ((ModelCheckerTh*)context)->Compute_successors();
+}
+
+void ModelCheckerTh::ComputeTh_Succ(){
+
+    cout << "number of threads "<<m_nb_thread<<endl;
+    int rc;
+ //   m_graph=&g;
+ //   m_graph->setTransition(m_transitionName);
+ //   m_graph->setPlace(m_placeName);
+    m_id_thread=0;
+
+    pthread_mutex_init(&m_mutex, NULL);
+    pthread_mutex_init(&m_gc_mutex,NULL);
+    pthread_mutex_init(&m_graph_mutex,NULL);
+    pthread_mutex_init(&m_supervise_gc_mutex,NULL);
+    m_gc=0;
+    for (int i=0; i<m_nb_thread; i++)
+    {
+        pthread_spin_init(&m_spin_stack[i], NULL);
+        m_charge[i]=0;
+        m_terminaison[i]=false;
+    }
+
+    for (int 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;
+        }
+    }
+    Compute_successors();
+    for (int i = 0; i < m_nb_thread-1; i++)
+    {
+        pthread_join(m_list_thread[i], NULL);
+    }
+
+
+}
diff --git a/src/ModelCheckerTh.h b/src/ModelCheckerTh.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d31b0319537583cb9ee2c8752f5132d1191e9d5
--- /dev/null
+++ b/src/ModelCheckerTh.h
@@ -0,0 +1,41 @@
+#ifndef MODELCHECKERTH_H
+#define MODELCHECKERTH_H
+#include "CommonSOG.h"
+typedef stack<LDDState *> pile_t;
+
+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();
+    void ComputeTh_Succ();
+    int minCharge();
+    bool isNotTerminated();
+
+
+private:
+    int m_nb_thread;
+    MDD m_initalMarking;
+    int m_min_charge;
+    pile_t m_st[128];
+    int m_charge[128];
+    bool m_terminaison[128];
+    int m_id_thread;
+
+
+    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/SogKripkeIteratorTh.cpp b/src/SogKripkeIteratorTh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6ae60ab5236533cd2950b48c15820dae38c6000
--- /dev/null
+++ b/src/SogKripkeIteratorTh.cpp
@@ -0,0 +1,76 @@
+#include <spot/kripke/kripke.hh>
+#include "LDDGraph.h"
+#include "SogKripkeStateTh.h"
+#include "SogKripkeIteratorTh.h"
+
+
+SogKripkeIteratorTh::SogKripkeIteratorTh(const LDDState* lddstate, bdd cnd):m_lddstate(lddstate), kripke_succ_iterator(cnd)
+{
+
+    m_lddstate->setDiv(true);
+    for (int i=0;i<m_lddstate->getSuccessors()->size();i++) {
+        m_lsucc.push_back(m_lddstate->getSuccessors()->at(i));
+    }
+   /* if (lddstate->isDeadLock()) {
+        m_lsucc.push_back(pair(,-1));
+    }*/
+    if (lddstate->isDiv()) {
+        m_lsucc.push_back(pair<LDDState*,int>(m_lddstate,-1));
+    }
+
+}
+bool SogKripkeIteratorTh::first() {
+
+   // cout<<"entering "<<__func__<<endl;
+    m_current_edge=0;
+    //cout<<"exciting "<<__func__<<endl;
+    return m_lsucc.size()!=0;
+
+}
+
+bool SogKripkeIteratorTh::next() {
+    //cout<<"entering "<<__func__<<endl;
+    m_current_edge++;
+    return m_current_edge<m_lsucc.size();
+
+}
+
+bool SogKripkeIteratorTh::done() const {
+    //cout<<"entring /excit"<<__func__<<endl;
+    return m_current_edge==m_lsucc.size();
+
+}
+
+SogKripkeStateTh* SogKripkeIteratorTh::dst() const
+  {
+    //cout<<"enter/excit "<<__func__<<endl;
+    return new SogKripkeStateTh(m_lsucc.at(m_current_edge).first);
+  }
+
+bdd SogKripkeIteratorTh::cond()  const {
+    //cout<<"entering "<<__func__<<endl;
+    if (m_lsucc.at(m_current_edge).second==-1) return bddtrue;
+
+    string name=m_builder->getTransition(m_lsucc.at(m_current_edge).second);
+    //cout<<"Value "<<m_lddstate->getSuccessors()->at(m_current_edge).second<<" Transition name "<<name<<endl;
+
+    spot::bdd_dict *p=m_dict_ptr->get();
+    spot::formula f=spot::formula::ap(name);
+    bdd   result=bdd_ithvar((p->var_map.find(f))->second);
+
+    //cout<<"Iterator "<<__func__<<"  "<<m_current_edge<<"\n";*/
+    //cout<<"exciting "<<__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
+}
+
+static ModelCheckerTh * SogKripkeIteratorTh::m_builder;
+static spot::bdd_dict_ptr* SogKripkeIteratorTh::m_dict_ptr;
diff --git a/src/SogKripkeIteratorTh.h b/src/SogKripkeIteratorTh.h
new file mode 100644
index 0000000000000000000000000000000000000000..b3624d6be8d978eb81bb81169c8012e230bbafde
--- /dev/null
+++ b/src/SogKripkeIteratorTh.h
@@ -0,0 +1,39 @@
+#ifndef SOGKRIPKEITERATORTH_H_INCLUDED
+#define SOGKRIPKEITERATORTH_H_INCLUDED
+#include "SogKripkeStateTh.h"
+#include "ModelCheckerTh.h"
+#include <spot/kripke/kripke.hh>
+// Iterator for a SOG graph
+class SogKripkeIteratorTh : public spot::kripke_succ_iterator
+{
+public:
+
+    static ModelCheckerTh * 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);
+    virtual ~SogKripkeIteratorTh();
+    bool first() override;
+    bool next() override;
+    bool done() const override;
+    SogKripkeStateTh* dst() const override;
+    bdd cond() const override final;
+
+    SogKripkeStateTh* current_state() const;
+
+    bdd current_condition() const;
+
+    int current_transition() const;
+
+    bdd current_acceptance_conditions() const;
+
+    std::string format_transition() const;
+
+private:
+    LDDState * m_lddstate;
+    vector<pair<LDDState*, int>> m_lsucc;
+    unsigned int m_current_edge=0;
+};
+
+
+#endif // SOGKRIPKEITERATOR_H_INCLUDED
diff --git a/src/SogKripkeStateTh.cpp b/src/SogKripkeStateTh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..76c38845a939bbf61a9c9ba4c2aca9f92add023a
--- /dev/null
+++ b/src/SogKripkeStateTh.cpp
@@ -0,0 +1,11 @@
+#include <spot/kripke/kripke.hh>
+#include "LDDState.h"
+#include "SogKripkeStateTh.h"
+
+
+SogKripkeStateTh::~SogKripkeStateTh()
+{
+    //dtor
+}
+
+static ModelCheckerTh * SogKripkeStateTh::m_builder;
diff --git a/src/SogKripkeStateTh.h b/src/SogKripkeStateTh.h
new file mode 100644
index 0000000000000000000000000000000000000000..48d64ff99e8eab4d4981030c3548ca76976c81ef
--- /dev/null
+++ b/src/SogKripkeStateTh.h
@@ -0,0 +1,46 @@
+#ifndef SOGKRIPKESTATETH_H_INCLUDED
+#define SOGKRIPKESTATETH_H_INCLUDED
+
+
+#include "LDDState.h"
+#include "ModelCheckerTh.h"
+
+class SogKripkeStateTh : public spot::state
+{
+public:
+    static ModelCheckerTh * m_builder;
+    SogKripkeStateTh(LDDState *st):m_state(st) {
+            m_builder->buildSucc(st);
+    };
+    virtual ~SogKripkeStateTh();
+
+    SogKripkeStateTh* clone() const override
+    {
+        return new SogKripkeStateTh(m_state);
+    }
+    size_t hash() const override
+    {
+        return m_state->getLDDValue();
+    }
+
+    int compare(const spot::state* other) const override
+    {
+        auto o = static_cast<const SogKripkeStateTh*>(other);
+        size_t oh = o->hash();
+        size_t h = hash();
+        if (h < oh)
+            return -1;
+        else
+            return h > oh;
+    }
+    LDDState* getLDDState() {
+        return m_state;
+    }
+protected:
+
+private:
+    LDDState *m_state;
+};
+
+
+#endif // SOGKRIPKESTATE_H_INCLUDED
diff --git a/src/SogKripkeTh.cpp b/src/SogKripkeTh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0e5f86d8b685cb91688e6bc79166b462147b22f3
--- /dev/null
+++ b/src/SogKripkeTh.cpp
@@ -0,0 +1,86 @@
+#include <spot/twaalgos/dot.hh>
+#include <spot/twaalgos/hoa.hh>
+#include <spot/kripke/kripke.hh>
+#include <spot/twa/bdddict.hh>
+
+
+#include "SogKripkeIteratorTh.h"
+#include "SogKripkeStateTh.h"
+
+#include "SogKripkeTh.h"
+#include <map>
+using namespace spot;
+SogKripkeTh::SogKripkeTh(const bdd_dict_ptr &dict_ptr,ModelCheckerTh *builder): spot::kripke(dict_ptr),m_builder(builder)
+{
+    SogKripkeIteratorTh::m_builder=builder;
+    SogKripkeStateTh::m_builder=builder;
+    SogKripkeIteratorTh::m_dict_ptr=&dict_ptr;
+    //cout<<__func__<<endl;
+}
+
+SogKripkeTh::SogKripkeTh(const spot::bdd_dict_ptr& dict_ptr,ModelCheckerTh *builder,set<string> &l_transap,set<string> &l_placeap):SogKripkeTh(dict_ptr,builder) {
+
+    for (auto it=l_transap.begin();it!=l_transap.end();it++) {
+        register_ap(*it);
+    }
+    for (auto it=l_placeap.begin();it!=l_placeap.end();it++)
+        register_ap(*it);
+
+}
+
+
+state* SogKripkeTh::get_init_state() const {
+   // cout<<__func__<<endl;
+    return new SogKripkeStateTh(m_builder->buildInitialMetaState());//new SpotSogState();
+
+}
+// Allows to print state label representing its id
+std::string SogKripkeTh::format_state(const spot::state* s) const
+  {
+    //cout<<__func__<<endl;
+    auto ss = static_cast<const SogKripkeStateTh*>(s);
+    std::ostringstream out;
+    out << "( " << ss->getLDDState()->getLDDValue() <<  ")";
+   // cout << " ( " << ss->getLDDState()->getLDDValue() <<  ")";
+    return out.str();
+  }
+
+SogKripkeIteratorTh* SogKripkeTh::succ_iter(const spot::state* s) const {
+ //  cout<<__func__<<endl;
+
+    auto ss = static_cast<const SogKripkeStateTh*>(s);
+   //////////////////////////////////////////////
+
+    return new SogKripkeIteratorTh(ss->getLDDState(),state_condition(ss));//,b);//s state_condition(ss));
+}
+
+bdd SogKripkeTh::state_condition(const spot::state* s) const
+  {
+
+    auto ss = static_cast<const SogKripkeStateTh*>(s);
+    vector<int> marked_place=ss->getLDDState()->getMarkedPlaces(m_builder->getPlaceProposition());
+
+
+    bdd result=bddtrue;
+    // Marked places
+    for (auto it=marked_place.begin();it!=marked_place.end();it++) {
+    string name=m_builder->getPlace(*it);
+    spot::formula f=spot::formula::ap(name);
+    result&=bdd_ithvar((dict_->var_map.find(f))->second);
+    }
+    vector<int> unmarked_place=ss->getLDDState()->getUnmarkedPlaces(m_builder->getPlaceProposition());
+    for (auto it=unmarked_place.begin();it!=unmarked_place.end();it++) {
+    string name=m_builder->getPlace(*it);
+    spot::formula f=spot::formula::ap(name);
+    result&=!bdd_ithvar((dict_->var_map.find(f))->second);
+    }
+
+  return result;
+  }
+
+
+SogKripkeTh::~SogKripkeTh()
+{
+    //dtor
+}
+
diff --git a/src/SogKripkeTh.h b/src/SogKripkeTh.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f4a114286a9b024fefcb7f5b697f9344b7e6b06
--- /dev/null
+++ b/src/SogKripkeTh.h
@@ -0,0 +1,34 @@
+#ifndef SOGKRIPKETH_H_INCLUDED
+#define SOGKRIPKETH_H_INCLUDED
+#include "LDDGraph.h"
+#include "SogKripkeIteratorTh.h"
+#include <spot/kripke/kripke.hh>
+#include <LDDGraph.h>
+#include <NewNet.h>
+
+
+class SogKripkeTh: public spot::kripke {
+    public:
+
+        SogKripkeTh(const spot::bdd_dict_ptr& dict_ptr,ModelCheckerTh *builder);
+        SogKripkeTh(const spot::bdd_dict_ptr& dict_ptr,ModelCheckerTh *builder,set<string> &l_transap,set<string> &l_placeap);
+        virtual ~SogKripkeTh();
+        spot::state* get_init_state() const;
+        SogKripkeIteratorTh* 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;
+
+          /// \brief Get the graph associated to the automaton.
+       /* const LDDGraph& get_graph() const {
+        return *m_sog;
+  }*/
+        ModelCheckerTh *m_builder;
+
+    protected:
+
+    private:
+    std::map<int, int> place_prop;
+    //LDDGraph* m_sog;
+};
+
+#endif // SOGKRIPKE_H_INCLUDED
diff --git a/src/main.cpp b/src/main.cpp
index 977117ee2f0412824972de1236bfff6cff44ca56..cab03898a3bf6020b3ecfd92b659bb76d0be2548 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,9 +127,9 @@ 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<<"Multi-threaded on the fly Model checking (Lace)..."<<endl;
         cout<<"Building automata for not(formula)\n";
         auto d = spot::make_bdd_dict();
         // d->register_ap("jbhkj");
@@ -168,6 +170,50 @@ int main(int argc, char** argv)
             std::cout << "formula is verified\n";
 
     }
+    else if (n_tasks==1 && !strcmp(argv[1],"otfP"))
+    {
+     cout<<"Multi-threaded on the fly Model checking (Pthread)..."<<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;