/* * 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 DRAOPTIMIZATIONS_HPP #define DRAOPTIMIZATIONS_HPP /** @file * Provides optimizations on complete DRAs, notably quotienting using bisimulation. */ #include "APSet.hpp" #include "common/BitSet.hpp" #include "common/BitSetIterator.hpp" #include #include #include #include #include /** * Provides optimizations on complete DRAs, notably quotienting using bisimulation. */ template class DRAOptimizations { public: /** type of a color */ typedef unsigned int color_t; /** type of vector state indizes */ typedef std::vector state_vector; private: /** Helper class, storing a coloring of the states */ class Coloring { private: /** The number of colors */ unsigned int _nr_of_colors; /** mapping state_id -> color */ std::vector _coloring; /** Keep detailed information of the equivalence classes? */ bool _detailed; /** * mapping from color * -> the state ids which are colored alike * only used when _detailed=true */ std::vector *_color2states; /** * mapping from color -> one representative state */ std::vector _color2state; public: /** * Constructor, get initial size of the coloring from DRA. * @param dra the DRA * @param detailed Keep detailed information on the equivalence classes? */ Coloring(DRA& dra, bool detailed=false) : _nr_of_colors(0), _detailed(detailed) { _coloring.resize(dra.size()); if (_detailed) { _color2states=new std::vector(); } else { _color2states=0; } } /** * Constructor, explicitly set initial size of the coloring * @param size the initial size * @param detailed Keep detailed information on the equivalence classes? */ Coloring(unsigned int size, bool detailed=false) : _nr_of_colors(0), _detailed(detailed) { _coloring.resize(size); if (_detailed) { _color2states=new std::vector(); } else { _color2states=0; } } /** Destructor */ ~Coloring() { delete _color2states; } /** Reset (clear) coloring. */ void reset() {_nr_of_colors=0;} /** Get the flag 'detailed' */ bool getFlagDetailed() {return _detailed;} /** Returns the size (number of states) of this coloring. */ unsigned int size() const {return _coloring.size();} /** * Create a new color * @return the newly created color */ color_t newColor() { _nr_of_colors++; _color2state.resize(_nr_of_colors); if (_detailed) { _color2states->resize(_nr_of_colors); } return _nr_of_colors-1; } /** Return the current (last created) color */ color_t currentColor() const { assert(_nr_of_colors>0); return _nr_of_colors-1; } /** Return the number of colors */ unsigned int countColors() const { return _nr_of_colors; } /** Set the color of a state */ void setColor(unsigned int state, color_t color) { assert(color<_nr_of_colors); _coloring[state]=color; _color2state[color]=state; if (_detailed) { (*_color2states)[color].set(state); } } /** Get the color for a state */ unsigned int state2color(unsigned int state) const { return _coloring[state]; } /** *Get one representative state for the equivalence class with the * specified color. */ unsigned int color2state(color_t color) const { assert(color<_nr_of_colors); return _color2state[color]; } /** * Get the state indizes (in a BitSet) that have the specified color. * Can only be called, when the 'detailed' flag is activated in the * constructor. */ const BitSet& color2states(color_t color) const { assert(color<_nr_of_colors); assert(_detailed && _color2states!=0); return (*_color2states)[color]; } /** Print the coloring */ friend std::ostream& operator<<(std::ostream& out, const Coloring& coloring) { for (unsigned int i=0;i Coloring *generateColoring(state_vector &states, Coloring &coloring, Comparator &comp) { std::sort(states.begin(), states.end(), comp); Coloring* result=new Coloring(coloring.size(), coloring.getFlagDetailed()); if (states.size()==0) {return result;} state_vector::reverse_iterator current=states.rbegin(), last=states.rbegin(); result->setColor(*current, result->newColor()); while (++current != states.rend()) { // because states is sorted and we traverse // from the end, either: // *current < *last with comp(current,last)==true // or *current == *last with !comp(current,last) if (comp(*current, *last)) { // -> we have to start a new color result->setColor(*current, result->newColor()); } else { // -> more of the same, we stay with this color result->setColor(*current, result->currentColor()); } last=current; } return result; } /** * Generate a new DRA from a coloring */ typename DRA::shared_ptr generateDRAfromColoring(DRA &oldDRA, Coloring &coloring, bool detailedStates) { typename DRA::shared_ptr newDRA((DRA*)oldDRA.createInstance(oldDRA.getAPSet_cp())); newDRA->acceptance().newAcceptancePairs(oldDRA.acceptance().size()); for (unsigned int color=0; colornewState(); } unsigned int old_start_state=oldDRA.getStartState()->getName(); unsigned int start_state_color=coloring.state2color(old_start_state); newDRA->setStartState(newDRA->get(start_state_color)); const APSet &apset=newDRA->getAPSet(); for (unsigned int color=0; colorget(color); unsigned int old_state_representative=coloring.color2state(color); typename DRA::state_type *old_state = oldDRA[old_state_representative]; if (detailedStates) { const BitSet& old_states=coloring.color2states(color); // create new description... if (old_states.cardinality()==1) { if (old_state->hasDescription()) { new_state->setDescription(old_state->getDescription()); } } else { std::ostringstream s; s << ""; bool first=true; for (BitSetIterator it=BitSetIterator(old_states); it!=BitSetIterator::end(old_states); ++it) { if (first) { first=false; } else { s << ""; } s << ""; } s << "
{,"; if (!oldDRA[*it]->hasDescription()) { s << *it; } else { s << oldDRA[*it]->getDescription(); } s << "}
"; new_state->setDescription(s.str()); } } // Create appropriate acceptance conditions unsigned int old_state_index=old_state->getName(); for (unsigned int i=0; iacceptance().addTo_L(i); } if (oldDRA.acceptance().isStateInAcceptance_U(i, old_state_index)) { new_state->acceptance().addTo_U(i); } } for (APSet::element_iterator label= apset.all_elements_begin(); label!=apset.all_elements_end(); ++label) { typename DRA::state_type *old_to= old_state->edges().get(*label); unsigned to_color=coloring.state2color(old_to->getName()); new_state->edges().addEdge(*label, newDRA->get(to_color)); } } return newDRA; } }; #endif