Skip to content
Snippets Groups Projects
CNDFS.cpp 8.88 KiB
Newer Older
//
// Created by ghofrane on 5/4/22.
//
#include "CNDFS.h"
#include "ModelCheckBaseMT.h"
#include <iostream>
#include <spot/twa/twagraph.hh>
#include <thread>
#include <vector>
#include <utility>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include <spot/twa/twa.hh>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include <deque>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include <atomic>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include <condition_variable>
chihebabid's avatar
chihebabid committed
#include <algorithm>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include "misc/stacksafe.h"
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include <spot/twa/formula2bdd.hh>
#include <spot/tl/formula.hh>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include <spot/misc/minato.hh>
#include <spot/twaalgos/contains.hh>
#include <spot/tl/contain.hh>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
#include <random>
#include <algorithm>
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
using namespace std;
chihebabid's avatar
chihebabid committed
CNDFS::CNDFS(ModelCheckBaseMT *mcl, const spot::twa_graph_ptr &af, const uint16_t &nbTh) : mMcl(mcl), mAa(af),
                                                                                           mNbTh(nbTh) {
chihebabid's avatar
chihebabid committed
    getInitialState();
chihebabid's avatar
chihebabid committed
    spawnThreads();
}
chihebabid's avatar
chihebabid committed

CNDFS::~CNDFS() {
    for (int i = 0; i < mNbTh; ++i) {
        mlThread[i]->join();
        delete mlThread[i];
    }
chihebabid's avatar
chihebabid committed
    // Liberate dynamic allocated memory for synchropnized product
    for (const auto & elt : mlBuiltStates)
        delete elt;
chihebabid's avatar
chihebabid committed
}

// Create threads
chihebabid's avatar
chihebabid committed
void CNDFS::spawnThreads() {
    for (int i = 0; i < mNbTh; ++i) {
        mlThread[i] = new thread(threadHandler, this);
        if (mlThread[i] == nullptr) {
            cout << "error: pthread creation failed. " << endl;
        }
    }
}
chihebabid's avatar
chihebabid committed
void CNDFS::threadHandler(void *context) {
    ((CNDFS *) context)->threadRun();
}
void CNDFS::threadRun() {
    uint16_t idThread = mIdThread++;
chihebabid's avatar
chihebabid committed
    vector<myState_t *> Rp;
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    vector<spot::formula> ap_sog;
    dfsBlue(mInitStatePtr, Rp, idThread, ap_sog);
chihebabid's avatar
chihebabid committed
/*
 * Build initial state of the product automata
 */
void CNDFS::getInitialState() {
    mInitStatePtr = new myState_t;
chihebabid's avatar
chihebabid committed
    mInitStatePtr->left = mMcl->getInitialMetaState();
    mInitStatePtr->right = mAa->get_init_state();
    mInitStatePtr->isAcceptance = mAa->state_is_accepting(mAa->get_init_state());
    mInitStatePtr->isConstructed = true;
chihebabid's avatar
chihebabid committed
    mlBuiltStates.push_back(mInitStatePtr);
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed

//this function is to build a state with list of successor initially null
chihebabid's avatar
chihebabid committed
myState_t *CNDFS::buildState(LDDState *left, spot::state *right, bool acc, bool constructed, bool cyan) {
    myState_t *buildStatePtr = new myState_t;
    buildStatePtr->left = left;
chihebabid's avatar
chihebabid committed
    buildStatePtr->right = (spot::twa_graph_state *) right;
    buildStatePtr->isAcceptance = acc;
    buildStatePtr->isConstructed = constructed;
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    mlBuiltStates.push_back(buildStatePtr);
chihebabid's avatar
chihebabid committed
std::ostream &operator<<(std::ostream &Str, myState_t *state) {
    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 (const auto &ii: state->new_successors) {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
        Str << "succ num " << i << ii.first << " with transition " << ii.second << endl;
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    return Str;
}

chihebabid's avatar
chihebabid committed
void CNDFS::dfsRed(myState_t *state, vector<myState_t *> &Rp, uint8_t idThread) {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
//    cout << "dfsRed" << endl;
    Rp.push_back(state);
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
//    computeSuccessors(state);
chihebabid's avatar
chihebabid committed
    for (const auto &succ: state->new_successors) {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
//        cout << "dfs red 1 "  << succ.first->cyan[idThread]<< endl;
chihebabid's avatar
chihebabid committed
        if (succ.first->cyan[idThread]) {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
            cout << "cycle detected with the thread " << unsigned(idThread) << endl;
chihebabid's avatar
chihebabid committed
            exit(0);
        }
        // unvisited and not red state
        if ((find(Rp.begin(), Rp.end(), state) != Rp.end()) && !succ.first->red)
            dfsRed(succ.first, Rp, idThread);
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    }
}
chihebabid's avatar
chihebabid committed
/*
 * Check whether a product state exists or not
 */
myState_t *CNDFS::isStateBuilt(LDDState *sogState, spot::twa_graph_state *spotState) {
    auto compare = [sogState, spotState](myState_t *state) {
        return (state->left == sogState && state->right == spotState);
    };
    auto result = find_if(begin(mlBuiltStates), end(mlBuiltStates), compare);
    return result == end(mlBuiltStates) ? nullptr : *result;
}

//compute new successors of a product state
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
void CNDFS::computeSuccessors(myState_t *state, vector<spot::formula> ap_sog) {
    if (state->succState == SuccState::done) return;
chihebabid's avatar
chihebabid committed
    std::unique_lock lk(mMutexStatus);
    if (state->succState == SuccState::doing) {
        mDataCondWait.wait(lk, [state] { return state->succState == SuccState::done; });
chihebabid's avatar
chihebabid committed
        mMutexStatus.unlock();
chihebabid's avatar
chihebabid committed
        return;
    }
    state->succState = SuccState::doing;
chihebabid's avatar
chihebabid committed
    lk.unlock();
    auto sog_current_state = state->left;
    const spot::twa_graph_state *ba_current_state = state->right;
    while (!sog_current_state->isCompletedSucc());
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    auto p = mAa->get_dict();//avoir le dictionnaire bdd,proposition atomique
    //fetch the state's atomic proposition
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    for (const auto & vv: sog_current_state->getMarkedPlaces(mMcl->getPlaceProposition()))
chihebabid's avatar
chihebabid committed
     {
         auto name = string(mMcl->getPlace(vv));
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
         auto ap_state = spot::formula::ap(name);
         if (p->var_map.find(ap_state) != p->var_map.end()) {
             ap_sog.push_back(ap_state);
             for( auto n: p->var_map)
             {
                 if (n.first != ap_state)
                 {
                     ap_sog.push_back(spot::formula::Not(n.first));
                 }
             }
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
         }
     }
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    //iterate over the successors of a current aggregate
chihebabid's avatar
chihebabid committed
    for (const auto &elt: sog_current_state->Successors) {
        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
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
        auto ap_edge = spot::formula::ap(name);// récuperer la proposition atomique qui correspond à la transition
        if (p->var_map.find(ap_edge) != p->var_map.end()) {
            ap_sog.push_back(ap_edge);
        }
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
        spot::formula pa_sog_result = spot::formula::And(ap_sog);
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
//        cout << "formula sog: " << pa_sog_result << endl;
chihebabid's avatar
chihebabid committed
        //iterate over the successors of a BA state
        auto ii = mAa->succ_iter(ba_current_state);
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
         if (ii->first())
                do {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
                   auto pa_ba_result = spot::bdd_to_formula(ii->cond(), p); // from bdd to formula
                   if (c.contained(pa_sog_result, pa_ba_result) || c.contained(pa_ba_result, pa_sog_result))
                   {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
                            std::unique_lock lk(mMutex);
                            auto result = isStateBuilt(elt.first, (spot::twa_graph_state *) ii->dst());
                            if (result) {
                                state->new_successors.push_back(make_pair(result, transition));
                            } else {
                                myState_t *nd = buildState(elt.first,
                                                           const_cast<spot::state *>(ii->dst()),
                                                           mAa->state_is_accepting(ii->dst()), true, false);
                                state->new_successors.push_back(make_pair(nd, transition));
                            }
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
                } while (ii->next());
         mAa->release_iter(ii);
        }
    state->succState = SuccState::done;
chihebabid's avatar
chihebabid committed
    mDataCondWait.notify_all();
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
//Perform the dfsBlue
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
void CNDFS::dfsBlue(myState_t *state, vector<myState_t *> &Rp, uint8_t idThread, vector<spot::formula> ap_sog) {
chihebabid's avatar
chihebabid committed
    state->cyan[idThread] = true;
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    computeSuccessors(state, ap_sog);
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    std::mt19937 g(rd());
    std::shuffle(state->new_successors.begin(), state->new_successors.end(), g);
chihebabid's avatar
chihebabid committed
    for (const auto &succ: state->new_successors) {
//        cout << "cyan " << succ.first->cyan[idThread] << endl;
chihebabid's avatar
chihebabid committed
        if (!succ.first->blue && !succ.first->cyan[idThread]) {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
            dfsBlue(succ.first, Rp, idThread, ap_sog);
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    }
    state->blue = true;
chihebabid's avatar
chihebabid committed
    if (state->isAcceptance) {
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
//        cout << "Acceptance state detected " << endl;
chihebabid's avatar
chihebabid committed
        if (state->left->isDeadLock() || state->left->isDiv()) {
            cout << "cycle detected: an aggregate with deal_lock or live_lock" << endl;
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
            exit(0);
chihebabid's avatar
chihebabid committed
        } else {
            Rp.clear();
chihebabid's avatar
chihebabid committed
            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
            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);

chihebabid's avatar
chihebabid committed
            for (const auto &qu: Rp) // prune other dfsRed
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
            {
                qu->red = true;
            }
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
        }
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
        cout << "no cycle detected" << endl;
Ghofrane Amaimi's avatar
Ghofrane Amaimi committed
    }
    state->cyan[idThread] = false;
spot::bdd_dict_ptr *CNDFS::m_dict_ptr;