/* * This file is part of the program ltl2dstar (http://www.ltl2dstar.de/). * Copyright (C) 2005-2007 Joachim Klein * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef STUTTERSENSITIVENESSINFORMATION_H #define STUTTERSENSITIVENESSINFORMATION_H /** @file * Provide class StutterSensitivenessInformation */ #include "NBAStutterClosure.hpp" #include "NBAAnalysis.hpp" #include "LTLFormula.hpp" #include "common/TimeKeeper.hpp" /** Calculate and store information about which symbols from 2^APSet * are insensitive to stuttering. */ class StutterSensitivenessInformation { public: /** Constructor */ StutterSensitivenessInformation() : _completelyStutterInsensitive(false), _partiallyStutterInsensitive(false), _hasCheckedLTL(false), _hasCheckedNBAs(false) {} /** Check the LTLFormula syntacticly for * stutter insensitiveness */ void checkLTL(LTLFormula_ptr& ltl) { if (hasTimekeeping()) {getTimeKeeper().start();} if (ltl->hasNextStep()) { _completelyStutterInsensitive=false; _partiallyStutterInsensitive=false; } else { _completelyStutterInsensitive=true; _partiallyStutterInsensitive=false; } _hasCheckedLTL=true; if (hasTimekeeping()) {getTimeKeeper().stop();} } /** Check for partial stutter insensitiveness using * the nba and the complement nba */ template void checkNBAs(NBA_t& nba, NBA_t& nba_complement) { if (hasTimekeeping()) {getTimeKeeper().start();} APSet_cp apset=nba.getAPSet_cp(); bool nba_is_smaller=(nba.size() < nba_complement.size()); if (_printInfo) { std::cerr << "Checking for insensitiveness" << std::endl; } bool one_insensitive=false; bool all_insensitive=true; for (APSet::element_iterator it=apset->all_elements_begin(); it!=apset->all_elements_end(); ++it) { APElement elem(*it); if (_partiallyInsensitive.get(elem)) { // don't recheck something we already now is stutter insensitive one_insensitive=true; continue; } if (_printInfo) { std::cerr << "Checking " << elem.toString(*apset) << ": "; std::cerr.flush(); } bool insensitive; if (nba_is_smaller) { insensitive=is_stutter_insensitive(nba, nba_complement, elem); } else { insensitive=is_stutter_insensitive(nba_complement, nba, elem); } if (insensitive) { _partiallyInsensitive.set(elem); one_insensitive=true; if (_printInfo) { std::cerr << "+" << std::endl; } } else { all_insensitive=false; if (_printInfo) { std::cerr << "-" << std::endl; } } } _hasCheckedNBAs=true; _partiallyStutterInsensitive=one_insensitive; if (hasTimekeeping()) {getTimeKeeper().stop();} } /** Check for partial stutter insensitiveness for a LTL formula. * @param ltl the LTL formula * @param llt2nba the LTL2NBA translator, has to provide function ltl2nba(ltl) */ template void checkPartial(LTLFormula& ltl, LTL2NBA_Calc& ltl2nba) { if (hasTimekeeping()) {getTimeKeeper().start();} checkNBAs(*ltl2nba.ltl2nba(ltl, true), *ltl2nba.ltl2nba(*ltl.negate()->toPNF(), true)); if (hasTimekeeping()) {getTimeKeeper().stop();} } /** Check for partial stutter insensitiveness for a LTL formula, using an * already calculated NBA. * @param nba an NBA for the positive formula * @param ltl_neg the negated LTL formula (in PNF) * @param llt2nba the LTL2NBA translator, has to provide function ltl2nba(ltl) */ template void checkPartial(NBA_t& nba, LTLFormula& ltl_neg, LTL2NBA_Calc& ltl2nba) { if (hasTimekeeping()) {getTimeKeeper().start();} checkNBAs(nba, *ltl2nba.ltl2nba(ltl_neg)); if (hasTimekeeping()) {getTimeKeeper().stop();} } /** Return true iff all symbols are completely stutter * insensitive. */ bool isCompletelyInsensitive() const { return _completelyStutterInsensitive; } /** Return true iff some (or all) symbols are stutter insensitive, * result is undefined if isCompletelyInsensitive()==true */ bool isPartiallyInsensitive() const { return _partiallyStutterInsensitive; } /** Get the set of the stutter insensitive symbols from 2^APSet */ const BitSet& getPartiallyInsensitiveSymbols() const { return _partiallyInsensitive; } /** shared_ptr */ typedef boost::shared_ptr ptr; /** Static, do Timekeeping? */ static bool hasTimekeeping() { return _enableTimekeeping; } /** Static, enable Timekeeping? */ static void enableTimekeeping() { _enableTimekeeping=true; } /** Static, enable printing of verbose information */ static void enablePrintInfo() { _printInfo=true; } /** Get the timekeeper object */ static TimeKeeper& getTimeKeeper() { return _timekeeper; } private: bool _completelyStutterInsensitive; bool _partiallyStutterInsensitive; bool _hasCheckedLTL; bool _hasCheckedNBAs; BitSet _partiallyInsensitive; static bool _enableTimekeeping; static bool _printInfo; static TimeKeeper _timekeeper; // -- private member functions /** Check that symbol label is stutter insensitive, * using nba and complement_nba */ template bool is_stutter_insensitive(NBA_t& nba, NBA_t& nba_complement, APElement label) { typedef boost::shared_ptr NBA_ptr; NBA_ptr stutter_closed_nba=NBAStutterClosure::stutter_closure(nba, label); NBA_ptr product=NBA_t::product_automaton(*stutter_closed_nba, nba_complement); NBAAnalysis analysis_product(*product); bool empty=analysis_product.emptinessCheck(); // std::cerr << "NBA is " << (empty ? "empty" : "not empty") << std::endl; return empty; } }; #endif