// -*- coding: utf-8 -*- // Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement // de l'Epita. // // This file is part of Spot, a model checking library. // // Spot is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // Spot is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include "complete.hh" #include "ltlast/constant.hh" #include "dupexp.hh" namespace spot { unsigned tgba_complete_here(tgba_digraph* aut) { unsigned n = aut->num_states(); unsigned sink = -1U; bdd allacc = aut->all_acceptance_conditions(); if (allacc == bddfalse) { // We cannot safely complete an automaton if it has no // acceptance set as the added sink would become accepting. // In this case, add an acceptance set to all transitions. const ltl::formula* t = ltl::constant::true_instance(); int v = aut->get_dict()->register_acceptance_variable(t, aut); allacc = bdd_ithvar(v); aut->set_acceptance_conditions(allacc); for (auto& t: aut->transitions()) t.acc = allacc; } else { // If some acceptance sets were used, loop over the states and // seek a state that has only self loops, and that is not // accepting. This will be our sink state. for (unsigned i = 0; i < n; ++i) { bool selfloop = true; bdd accsum = bddfalse; for (auto& t: aut->out(i)) { if (t.dst != i) // Not a self-loop { selfloop = false; break; } accsum |= t.acc; } if (selfloop && accsum != allacc) // We have found a sink! { sink = i; break; } } } // If we haven't found any sink, simply add one. if (sink == -1U) { sink = aut->new_state(); ++n; } // Now complete all states (including the sink). for (unsigned i = 0; i < n; ++i) { bdd missingcond = bddtrue; bdd acc = bddfalse; for (auto& t: aut->out(i)) { missingcond -= t.cond; // FIXME: This is ugly. // // In case the automaton uses state-based acceptance, we // need to put the new transition in the same set as all // the other. // // In case the automaton uses transition-based acceptance, // it does not matter what acceptance set we put the new // transition into. // // So in both cases, we put the transition in the same // acceptance sets as the last outgoing transition of the // state. acc = t.acc; } // In case the automaton use state-based acceptance, propagate // the acceptance of the first transition to the one we add. if (missingcond != bddfalse) aut->new_transition(i, sink, missingcond, acc); } return sink; } tgba_digraph* tgba_complete(const tgba* aut) { tgba_digraph* res = tgba_dupexp_dfs(aut); tgba_complete_here(res); return res; } }