From b0e6e85aac806820780059acb6f4426a394e2582 Mon Sep 17 00:00:00 2001
From: chihebabid <chiheb.abid@fst.utm.tn>
Date: Wed, 6 Jul 2022 22:34:42 +0100
Subject: [PATCH] Fixed code for NDFS algorithm

---
 src/algorithm/CNDFS.cpp | 106 ++++++++++++++++------------------------
 src/algorithm/CNDFS.h   |  13 ++---
 2 files changed, 48 insertions(+), 71 deletions(-)

diff --git a/src/algorithm/CNDFS.cpp b/src/algorithm/CNDFS.cpp
index b093999..54edc1f 100644
--- a/src/algorithm/CNDFS.cpp
+++ b/src/algorithm/CNDFS.cpp
@@ -44,7 +44,12 @@ void CNDFS::spawnThreads() {
 }
 
 void CNDFS::threadHandler(void *context) {
-    ((CNDFS *) context)->dfsBlue(((CNDFS *) context)->mInitStatePtr);
+    ((CNDFS *) context)->threadRun();
+}
+void CNDFS::threadRun() {
+    uint16_t idThread = mIdThread++;
+    vector<myState_t*> Rp;
+    dfsBlue(mInitStatePtr,Rp,idThread);
 }
 
 //get initial state of the product automata
@@ -60,23 +65,19 @@ void CNDFS::getInitialState(){
 
 //this function is to build a state with list of successor initially null
 myState_t* CNDFS::buildState(LDDState* left, spot::state* right, bool acc, bool constructed, bool cyan){
-    bool _cyan{false};
-    mMutex.lock();
-    myState_t * buildStatePtr  = static_cast<myState_t *>(malloc(sizeof(myState_t)));
-    _cyan = cyan;
+    myState_t * buildStatePtr  = new myState_t;
     buildStatePtr->left = left;
     buildStatePtr->right = dynamic_cast<const spot::twa_graph_state *>(right);
     buildStatePtr->isAcceptance = acc;
     buildStatePtr->isConstructed = constructed;
-    buildStatePtr->cyan= _cyan;
-    mMutex.unlock();
+
     return buildStatePtr;
 }
 
 std::ostream & operator<<(std::ostream & Str,myState_t* state) {
-     Str << "({ Sog state= " << state->left << ", BA state= " << state->right << ", acceptance= "  << state->isAcceptance <<  ", constructed= "  << state->isConstructed <<  ", cyan= "  << state->cyan << ", red= "  << state->red << ", blue= "  <<  state->blue <<  " }" << endl;
+     Str << "({ Sog state= " << state->left << ", BA state= " << state->right << ", acceptance= "  << state->isAcceptance <<  ", constructed= "  << state->isConstructed << ", red= "  << state->red << ", blue= "  <<  state->blue <<  " }" << endl;
      int i = 0;
-     for (auto ii : state->new_successors)
+     for (const auto & ii : state->new_successors)
      {
          cout << "succ num " << i << ii.first << " with transition " << ii.second<<  endl;
          i++;
@@ -84,50 +85,34 @@ std::ostream & operator<<(std::ostream & Str,myState_t* state) {
     return Str;
 }
 
-//all visited accepting nodes (non seed, non red) should be red
-atomic_bool CNDFS::awaitCondition(myState_t* state,deque<myState_t*> localDeque)
-{
-    vector<bool> localList ;
-    for (auto qu: localDeque)
-    {
-        if ((qu->isAcceptance) && (qu!=state))
-            localList.push_back(qu->red); // add all the red values
-//            return(qu->red == true);
-    }
-    //test if all elements are true
-    if (all_of(localList.begin(),localList.end(),[] (bool cond) {return cond ==true; }))
-    {
-        return true;
-    }
-    return  false;
-}
+
 
 //block all threads while awaitCondition is false
 //void  CNDFS::WaitForTestCompleted(_state* state) {
 //    while ( awaitCondition(state) == false) ;
 //}
 
-void CNDFS::dfsRed(myState_t* state,deque<myState_t*> localDeque)
+void CNDFS::dfsRed(myState_t *state, vector<myState_t*>& Rp,uint8_t idThread)
 {
     cout << "dfsRed" << endl;
-    localDeque.push_back(state);
+    Rp.push_back(state);
     computeSuccessors(state);
-    for (auto p:state->new_successors) {
-      if (p.first->cyan)
+    for (const auto& succ:state->new_successors) {
+      if (succ.first->cyan[idThread])
       {
           cout << "cycle detected"  << endl;
           exit(0);
       }
       // unvisited and not red state
-      if ((find(localDeque.begin(), localDeque.end(), state) != localDeque.end()) && ! p.first->red )
-          dfsRed(p.first, localDeque);
+      if ((find(Rp.begin(), Rp.end(), state) != Rp.end()) && ! succ.first->red )
+          dfsRed(succ.first, Rp,idThread);
     }
 }
 
 //compute new successors of a product state
 void CNDFS::computeSuccessors(myState_t *state)
 {
-    LDDState* sog_current_state = state->left;
+    auto sog_current_state = state->left;
     const spot::twa_graph_state* ba_current_state = state->right;
     while (!sog_current_state);
     while (!sog_current_state->isCompletedSucc());
@@ -135,7 +120,7 @@ void CNDFS::computeSuccessors(myState_t *state)
     //fetch the state's atomic proposition
     for (const auto & vv: sog_current_state->getMarkedPlaces(mMcl->getPlaceProposition()))
     {
-        string name = string(mMcl->getPlace(vv));
+        auto name = string(mMcl->getPlace(vv));
         auto f = spot::formula::ap(name);
         transitionNames.push(f);
         cv.notify_one();
@@ -143,7 +128,7 @@ void CNDFS::computeSuccessors(myState_t *state)
     //iterate over the successors of a current aggregate
     for (const auto &elt : sog_current_state->Successors)
     {
-        int transition = elt.second; // je récupère le numéro du transition
+        auto transition = elt.second; // je récupère le numéro du transition
         auto name = string(mMcl->getTransition(transition)); // récuprer le nom de la transition
         auto f = spot::formula::ap(name);// récuperer la proposition atomique qui correspond à la transition
         transitionNames.push(f); // push state'S AP to edge'S AP
@@ -157,7 +142,7 @@ void CNDFS::computeSuccessors(myState_t *state)
         while (!tempTransitionNames.empty())
         {
             //iterate over the successors of a BA state
-            spot::twa_succ_iterator *ii = mAa->succ_iter(ba_current_state);
+            auto ii = mAa->succ_iter(ba_current_state);
             if (ii->first())
                 do {
                     if (p->var_map.find(tempTransitionNames.front()) !=p->var_map.end())
@@ -202,29 +187,16 @@ void CNDFS::computeSuccessors(myState_t *state)
     }
 }
 
-int i = 1;
+
 
 //Perform the dfsBlue
-void CNDFS::dfsBlue(myState_t *state) {
-    deque<myState_t*> localDeque;
-    uint16_t idThread = mIdThread++;
-    cout<< "appel recursif " << i  << endl;
-    i++;
-    state->cyan = true;
-//    sharedPool.push(myCouple (state->left,state->right));
-    mSharedPoolTemp.push(state);
-    cv.notify_one();
-//    new_successor.push(coupleSuccessor(state,2));
-    computeSuccessors(state);
-    cout << " \n current state " << state << endl;
-//    cout << "nbr of successors of the current state "<<  state->new_successors.size() << " with thread "<< idThread<< endl;
-    for (auto p:state->new_successors)
+void CNDFS::dfsBlue(myState_t *state, vector<myState_t*>& Rp,uint8_t idThread) {
+
+    for (const auto & succ:state->new_successors)
     {
-//        cout << "state " << p.first << endl;
-        while ((!p.first->cyan) && (!p.first->blue))
+        if (!succ.first->blue && !succ.first->cyan[idThread])
           {
-              transitionNames.try_pop(transitionNames.front());
-              dfsBlue(p.first);
+              dfsBlue(succ.first,Rp,idThread);
           }
     }
     state->blue = true;
@@ -237,24 +209,28 @@ void CNDFS::dfsBlue(myState_t *state) {
             exit(0);
         } else
         {
-            dfsRed(state, localDeque); //looking for an accepting cycle
+            Rp.clear();
+            dfsRed(state, Rp,idThread); //looking for an accepting cycle
     //        the thread processed the current state waits for all visited accepting nodes (non seed, non red) to turn red
     //        the late red coloring forces the other acceptance states to be processed in post-order by the other threads
-            std::unique_lock<std::mutex> lk(mMutex);
-            while (!awaitCondition(state, localDeque)) cv.wait(lk);
-//         cv.wait(lk,[this] {return !awaitCondition(state, localDeque)});
-            lk.unlock();
-    //        notify once we have unlocked - this is important to avoid a pessimization.
-            awaitCondition(state,localDeque)=true;
-            cv.notify_all();
-            for (auto qu: localDeque) // prune other dfsRed
+            bool cond;
+            do {
+                cond = true;
+                for (auto iter = Rp.begin(); iter != Rp.end() && cond; ++iter) {
+                    if ((*iter)->isAcceptance && (*iter != state)) {
+                        if (!(*iter)->red) cond = false;
+                    }
+                }
+            } while (!cond);
+
+            for (const auto& qu: Rp) // prune other dfsRed
             {
                 qu->red = true;
             }
         }
         cout << "no cycle detected" << endl;
     }
-    state->cyan = false;
+    state->cyan[idThread] = false;
 }
 spot::bdd_dict_ptr *CNDFS::m_dict_ptr;
 
diff --git a/src/algorithm/CNDFS.h b/src/algorithm/CNDFS.h
index 32b5b22..8736944 100644
--- a/src/algorithm/CNDFS.h
+++ b/src/algorithm/CNDFS.h
@@ -15,21 +15,21 @@
 
 using namespace std ;
 typedef pair<struct myState_t*, int> coupleSuccessor;
-
+static constexpr uint8_t MAX_THREADS=64;
 struct myState_t {
     LDDState *left;
     const spot::twa_graph_state* right;
     vector<pair<struct myState_t*, int>> new_successors;
     bool isAcceptance {false};
     bool isConstructed {false};
-    bool cyan {false};
+    array<bool,MAX_THREADS> cyan {false};
     atomic<bool> blue {false};
     atomic<bool> red {false};
 };
 
 class CNDFS {
 private:
-    static constexpr uint8_t MAX_THREADS=64;
+
     ModelCheckBaseMT * mMcl;
     spot::twa_graph_ptr mAa;
     uint16_t mNbTh;
@@ -43,6 +43,7 @@ private:
     static spot::bdd_dict_ptr* m_dict_ptr;
     void getInitialState();
     static void threadHandler(void *context);
+    void threadRun();
 public:
 //    SafeDequeue<myCouple> sharedPool;
      SafeDequeue<spot::formula> transitionNames;
@@ -50,10 +51,10 @@ public:
     CNDFS(ModelCheckBaseMT *mcl,const spot::twa_graph_ptr &af,const uint16_t& nbTh);
     virtual ~CNDFS();
     void computeSuccessors(myState_t *state);
-    void dfsBlue(myState_t *state);
-    void dfsRed(myState_t* state, deque<myState_t*> mydeque);
+    void dfsBlue(myState_t *state, vector<myState_t*>& Rp,uint8_t idThread);
+    void dfsRed(myState_t* state, vector<myState_t*>& Rp,uint8_t idThread);
     void WaitForTestCompleted(myState_t* state);
-    atomic_bool awaitCondition(myState_t* state,deque<myState_t*> mydeque);
+
     myState_t* buildState(LDDState* left, spot::state* right, bool acc, bool constructed,bool cyan);
 
 };
-- 
GitLab