/* * 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 DRA_H #define DRA_H /** @file * Provide class DRA<> which can store a deterministic Rabin or Streett automaton. */ #include "DA.hpp" #include "DA_State.hpp" #include "RabinAcceptance.hpp" #include "APSet.hpp" #include "APElement.hpp" #include "DAUnionAlgorithm.hpp" #include "common/Index.hpp" #include "common/Exceptions.hpp" #include #include #include #include #include "boost/shared_ptr.hpp" /** * A class representing a deterministic Rabin automaton. *

* For details on the template parameters, see class DA. *

* The DRA can be considered as a Streett automaton, if * a flag is set. */ template class EdgeContainer > class DRA : public DA { public: DRA(APSet_cp ap_set); virtual ~DRA(); /** The type of the states of the DRA. */ typedef typename DA::state_type state_type; /** The type of the label on the edges. */ typedef typename DA::label_type label_type; /** The type of an iterator over the states. */ typedef typename DA::iterator iterator; /** The type of an iterator over the edges of a state. */ typedef typename DA::edge_iterator edge_iterator; /** Type of an iterator over the index of acceptance pairs. */ typedef typename RabinAcceptance::acceptance_pair_iterator acceptance_pair_iterator; typedef RabinAcceptance acceptance_condition_type; /** Type of a reference counted pointer to the DRA (boost::shared_ptr) */ typedef boost::shared_ptr< DRA > shared_ptr; /** Create a new instance of the automaton. */ virtual DA *createInstance(APSet_cp ap_set) { return new DRA(ap_set); } /** Make this automaton into an never accepting automaton */ void constructEmpty() { state_type* n=DA::newState(); this->setStartState(n); for (APSet::element_iterator it_elem= DA::getAPSet().all_elements_begin(); it_elem!=DA::getAPSet().all_elements_end(); ++it_elem) { APElement label=(*it_elem); n->edges().addEdge(label, n); } } /** * Print the DRA/DSA in v2 format to the output stream. * This function can compact the automaton, which may invalidate iterators! */ void print_explicit_v2(std::ostream& out) { if (!this->isCompact()) { this->makeCompact(); } this->print_da_explicit_v2(typeID(), out); } /** * Print the DRA/DSA in DOT format to the output stream. * This function can compact the automaton, which may invalidate iterators! */ void print_dot(std::ostream& out) { if (!this->isCompact()) { this->makeCompact(); } this->print_da_dot(typeID(), out); } /** * Output operator for the DRA/DSA. */ friend std::ostream& operator<<(std::ostream& out, DRA& dra) { dra.print_explicit_v2(out); return out; } /** Output state label for DOT printing. * @param out the output stream * @param state_index the state index */ virtual void formatStateForDOT(std::ostream& out, unsigned int state_index) { state_type* cur_state=this->get(state_index); bool is_html=false; bool has_pos=false, has_neg=false; std::ostringstream acc_sig; for (unsigned int pair_index=0;pair_indexacceptance().size();pair_index++) { if (this->acceptance().isStateInAcceptance_L(pair_index, state_index)) { acc_sig << " +" << pair_index; has_pos=true; } if (this->acceptance().isStateInAcceptance_U(pair_index, state_index)) { acc_sig << " -" << pair_index; has_neg=true; } } std::string label; if (cur_state->hasDescription()) { std::string description=cur_state->getDescription(); is_html=true; std::string acc_color; if (has_pos) { if (has_neg) { acc_color="BGCOLOR=\"lightblue\""; } else { acc_color="BGCOLOR=\"green\""; } } else { if (has_neg) { acc_color="BGCOLOR=\"red\""; } } StringAlgorithms::replace_all(description, "", "
"); out << "label= < "; out << "
"; out << state_index; out << ""; out << acc_sig.str(); out << "
"; out << description; out << "
"; out << " >, shape=box"; } else { out << "label= \"" << state_index; if (acc_sig.str().length()!=0) { out << "\\n" << acc_sig.str(); } out << "\""; if (!has_pos && !has_neg) { out << ", shape=circle"; } else { out << ", shape=box"; } } if (this->getStartState() == cur_state) { out << ", style=filled, color=black, fillcolor=grey"; } } /** * Optimizes the acceptance condition. * This function may delete acceptance pairs, * which can invalidate iterators. */ void optimizeAcceptanceCondition() { RabinAcceptance::acceptance_pair_iterator it=this->acceptance().acceptance_pair_begin(); while (it!=this->acceptance().acceptance_pair_end()) { unsigned int id=*it; // increment iterator here so we can eventually delete // acceptance pair without side effects ++it; // L = L \ U if (this->acceptance().getAcceptance_L(id).intersects(this->acceptance().getAcceptance_U(id))) { BitSet L_minus_U=this->acceptance().getAcceptance_L(id); L_minus_U.Minus(this->acceptance().getAcceptance_U(id)); this->acceptance().getAcceptance_L(id)=L_minus_U; } // remove if L is empty if (this->acceptance().getAcceptance_L(id).isEmpty()) { // no state is in L(id) -> remove this->acceptance().removeAcceptancePair(id); } } } /** Is this DRA considered as a Streett automaton? */ bool isStreett() const {return _isStreett;} /** Consider this DRA as a Streett automaton. */ void considerAsStreett(bool flag=true) {_isStreett=flag;} static shared_ptr calculateUnion(DRA& dra1, DRA& dra2, bool trueloop_check=true, bool detailed_states=false) { if (dra1.isStreett() || dra2.isStreett()) { THROW_EXCEPTION(Exception, "Can not calculate union for Streett automata"); } return DAUnionAlgorithm::calculateUnion(dra1, dra2, trueloop_check, detailed_states); } static shared_ptr calculateUnionStuttered(DRA& dra1, DRA& dra2, StutterSensitivenessInformation::ptr stutter_information, bool trueloop_check=true, bool detailed_states=false) { if (dra1.isStreett() || dra2.isStreett()) { THROW_EXCEPTION(Exception, "Can not calculate union for Streett automata"); } return DAUnionAlgorithm::calculateUnionStuttered(dra1, dra2, stutter_information, trueloop_check, detailed_states); } private: /** Return a string giving the type of the automaton. */ std::string typeID() const { if (isStreett()) { return std::string("DSA"); } else { return std::string("DRA"); } } /** Marker, is this DRA considered as a Streett automaton? */ bool _isStreett; }; /** * Constructor. * @param ap_set the underlying APSet */ template class EdgeContainer > DRA::DRA(APSet_cp ap_set) : DA(ap_set), _isStreett(false) { } /** * Destructor. */ template class EdgeContainer > DRA::~DRA() { } #endif