spot  0.9.1
tgbaexplicit.hh
Go to the documentation of this file.
00001 // -*- coding: utf-8 -*-
00002 // Copyright (C) 2009, 2010, 2011, 2012 Laboratoire de Recherche et
00003 // Développement de l'Epita.
00004 // Copyright (C) 2003, 2004, 2006 Laboratoire d'Informatique de Paris
00005 // 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
00006 // Université Pierre et Marie Curie.
00007 //
00008 // This file is part of Spot, a model checking library.
00009 //
00010 // Spot is free software; you can redistribute it and/or modify it
00011 // under the terms of the GNU General Public License as published by
00012 // the Free Software Foundation; either version 2 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // Spot is distributed in the hope that it will be useful, but WITHOUT
00016 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00017 // or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
00018 // License for more details.
00019 //
00020 // You should have received a copy of the GNU General Public License
00021 // along with Spot; see the file COPYING.  If not, write to the Free
00022 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00023 // 02111-1307, USA.
00024 
00025 #ifndef SPOT_TGBA_TGBAEXPLICIT_HH
00026 # define SPOT_TGBA_TGBAEXPLICIT_HH
00027 
00028 #include <sstream>
00029 #include <list>
00030 
00031 #include "tgba.hh"
00032 #include "sba.hh"
00033 #include "tgba/formula2bdd.hh"
00034 #include "misc/hash.hh"
00035 #include "misc/bddop.hh"
00036 #include "ltlast/formula.hh"
00037 #include "ltlvisit/tostring.hh"
00038 
00039 namespace spot
00040 {
00041   // How to destroy the label of a state.
00042   template<typename T>
00043   struct destroy_key
00044   {
00045     void destroy(T t)
00046     {
00047       (void) t;
00048     }
00049   };
00050 
00051   template<>
00052   struct destroy_key<const ltl::formula*>
00053   {
00054     void destroy(const ltl::formula* t)
00055     {
00056       t->destroy();
00057     }
00058   };
00059 
00062   template<typename Label, typename label_hash>
00063   class state_explicit: public spot::state
00064   {
00065   public:
00066     state_explicit()
00067     {
00068     }
00069 
00070     state_explicit(const Label& l):
00071       label_(l)
00072     {
00073     }
00074 
00075     virtual ~state_explicit()
00076     {
00077     }
00078 
00079     virtual void destroy() const
00080     {
00081     }
00082 
00083     typedef Label label_t;
00084     typedef label_hash label_hash_t;
00085 
00086     struct transition
00087     {
00088       bdd condition;
00089       bdd acceptance_conditions;
00090       const state_explicit<Label, label_hash>* dest;
00091     };
00092 
00093     typedef std::list<transition> transitions_t;
00094     transitions_t successors;
00095 
00096     const Label& label() const
00097     {
00098       return label_;
00099     }
00100 
00101     bool empty() const
00102     {
00103       return successors.empty();
00104     }
00105 
00106     virtual int compare(const state* other) const
00107     {
00108       const state_explicit<Label, label_hash>* s =
00109         down_cast<const state_explicit<Label, label_hash>*>(other);
00110       assert (s);
00111 
00112       // Do not simply return "o - this", it might not fit in an int.
00113       if (s < this)
00114         return -1;
00115       if (s > this)
00116         return 1;
00117       return 0;
00118     }
00119 
00120     virtual size_t hash() const
00121     {
00122       return
00123         reinterpret_cast<const char*>(this) - static_cast<const char*>(0);
00124     }
00125 
00126     virtual state_explicit<Label, label_hash>*
00127     clone() const
00128     {
00129       return const_cast<state_explicit<Label, label_hash>*>(this);
00130     }
00131 
00132   protected:
00133     Label label_;
00134   };
00135 
00138   class state_explicit_number:
00139     public state_explicit<int, identity_hash<int> >
00140   {
00141   public:
00142     state_explicit_number()
00143       : state_explicit<int, identity_hash<int> >()
00144     {
00145     }
00146 
00147     state_explicit_number(int label)
00148       : state_explicit<int, identity_hash<int> >(label)
00149     {
00150     }
00151 
00152     static const int default_val;
00153   };
00154 
00157   class state_explicit_string:
00158     public state_explicit<std::string, string_hash>
00159   {
00160   public:
00161     state_explicit_string():
00162       state_explicit<std::string, string_hash>()
00163     {
00164     }
00165 
00166     state_explicit_string(const std::string& label)
00167       : state_explicit<std::string, string_hash>(label)
00168     {
00169     }
00170 
00171     static const std::string default_val;
00172   };
00173 
00176   class state_explicit_formula:
00177     public state_explicit<const ltl::formula*, ltl::formula_ptr_hash>
00178   {
00179   public:
00180     state_explicit_formula():
00181       state_explicit<const ltl::formula*, ltl::formula_ptr_hash>()
00182     {
00183     }
00184 
00185     state_explicit_formula(const ltl::formula* label)
00186       : state_explicit<const ltl::formula*, ltl::formula_ptr_hash>(label)
00187     {
00188     }
00189 
00190     static const ltl::formula* default_val;
00191   };
00192 
00195   template<typename State>
00196   class tgba_explicit_succ_iterator: public tgba_succ_iterator
00197   {
00198   public:
00199     tgba_explicit_succ_iterator(const State* start,
00200                                 bdd all_acc)
00201       : start_(start),
00202         all_acceptance_conditions_(all_acc)
00203     {
00204     }
00205 
00206     virtual void first()
00207     {
00208       it_ = start_->successors.begin();
00209     }
00210 
00211     virtual void next()
00212     {
00213       ++it_;
00214     }
00215 
00216     virtual bool done() const
00217     {
00218       return it_ == start_->successors.end();
00219     }
00220 
00221     virtual State* current_state() const
00222     {
00223       assert(!done());
00224 
00225       //ugly but I can't see any other wayout
00226       const State* res = down_cast<const State*>(it_->dest);
00227       assert(res);
00228 
00229       return
00230         const_cast<State*>(res);
00231     }
00232 
00233     virtual bdd current_condition() const
00234     {
00235       assert(!done());
00236       return it_->condition;
00237     }
00238 
00239     virtual bdd current_acceptance_conditions() const
00240     {
00241       assert(!done());
00242       return it_->acceptance_conditions;
00243     }
00244 
00245     typename State::transitions_t::const_iterator
00246     get_iterator() const
00247     {
00248       return it_;
00249     }
00250 
00251   private:
00252     const State* start_;
00253     typename State::transitions_t::const_iterator it_;
00254     bdd all_acceptance_conditions_;
00255   };
00256 
00259   template<typename State, typename Type>
00260   class explicit_graph: public Type
00261   {
00262   public:
00263     typedef typename State::label_t label_t;
00264     typedef typename State::label_hash_t label_hash_t;
00265     typedef typename State::transitions_t transitions_t;
00266     typedef typename State::transition transition;
00267     typedef State state;
00268   protected:
00269     typedef Sgi::hash_map<label_t, State, label_hash_t> ls_map;
00270     typedef Sgi::hash_map<const State*, label_t, ptr_hash<State> > sl_map;
00271 
00272   public:
00273 
00274     explicit_graph(bdd_dict* dict)
00275       : ls_(),
00276         sl_(),
00277         init_(0),
00278         dict_(dict),
00279         all_acceptance_conditions_(bddfalse),
00280         all_acceptance_conditions_computed_(false),
00281         neg_acceptance_conditions_(bddtrue)
00282     {
00283     }
00284 
00285     State* add_default_init()
00286     {
00287       return add_state(State::default_val);
00288     }
00289 
00290     transition*
00291     create_transition(State* source, const State* dest)
00292     {
00293       transition t;
00294 
00295       t.dest = dest;
00296       t.condition = bddtrue;
00297       t.acceptance_conditions = bddfalse;
00298 
00299       typename transitions_t::iterator i =
00300         source->successors.insert(source->successors.end(), t);
00301 
00302       return &*i;
00303     }
00304 
00305     transition*
00306     create_transition(const label_t& source, const label_t& dest)
00307     {
00308       // It's important that the source be created before the
00309       // destination, so the first source encountered becomes the
00310       // default initial state.
00311       State* s = add_state(source);
00312       return create_transition(s, add_state(dest));
00313     }
00314 
00315     transition*
00316     get_transition(const tgba_explicit_succ_iterator<State>* si)
00317     {
00318       return const_cast<transition*>(&(*(si->get_iterator())));
00319     }
00320 
00321     void add_condition(transition* t, const ltl::formula* f)
00322     {
00323       t->condition &= formula_to_bdd(f, dict_, this);
00324       f->destroy();
00325     }
00326 
00328     void add_conditions(transition* t, bdd f)
00329     {
00330       dict_->register_propositions(f, this);
00331       t->condition &= f;
00332     }
00333 
00334     bool has_acceptance_condition(const ltl::formula* f) const
00335     {
00336       return dict_->is_registered_acceptance_variable(f, this);
00337     }
00338 
00339     //old tgba explicit labelled interface
00340     bool has_state(const label_t& name)
00341     {
00342       return ls_.find(name) != ls_.end();
00343     }
00344 
00345     const label_t& get_label(const State* s) const
00346     {
00347       typename sl_map::const_iterator i = sl_.find(s);
00348       assert(i != sl_.end());
00349       return i->second;
00350     }
00351 
00352     const label_t& get_label(const spot::state* s) const
00353     {
00354       const State* se = down_cast<const State*>(s);
00355       assert(se);
00356       return get_label(se);
00357     }
00358 
00359     transition*
00360     create_trainsition(const label_t& source, const label_t& dest)
00361     {
00362       // It's important that the source be created before the
00363       // destination, so the first source encountered becomes the
00364       // default initial state.
00365       State* s = add_state(source);
00366       return create_transition(s, add_state(dest));
00367     }
00368 
00369     void
00370     complement_all_acceptance_conditions()
00371     {
00372       bdd all = this->all_acceptance_conditions();
00373       typename ls_map::iterator i;
00374       for (i = ls_.begin(); i != ls_.end(); ++i)
00375         {
00376           typename transitions_t::iterator i2;
00377           for (i2 = i->second.successors.begin();
00378                i2 != i->second.successors.end(); ++i2)
00379             i2->acceptance_conditions = all - i2->acceptance_conditions;
00380         }
00381     }
00382 
00383     void
00384     merge_transitions()
00385     {
00386       typename ls_map::iterator i;
00387       for (i = ls_.begin(); i != ls_.end(); ++i)
00388       {
00389         typename transitions_t::iterator t1;
00390         for (t1 = i->second.successors.begin();
00391              t1 != i->second.successors.end(); ++t1)
00392         {
00393           bdd acc = t1->acceptance_conditions;
00394           const state_explicit<label_t, label_hash_t>* dest = t1->dest;
00395 
00396           // Find another transition with the same destination and
00397           // acceptance conditions.
00398           typename transitions_t::iterator t2 = t1;
00399           ++t2;
00400           while (t2 != i->second.successors.end())
00401           {
00402             typename transitions_t::iterator t2copy = t2++;
00403             if (t2copy->acceptance_conditions == acc && t2copy->dest == dest)
00404             {
00405               t1->condition |= t2copy->condition;
00406               i->second.successors.erase(t2copy);
00407             }
00408           }
00409         }
00410       }
00411     }
00412 
00415     State* add_state(const label_t& name)
00416     {
00417       typename ls_map::iterator i = ls_.find(name);
00418       if (i == ls_.end())
00419         {
00420           State s(name);
00421           ls_[name] = s;
00422           sl_[&ls_[name]] = name;
00423 
00424           // The first state we add is the inititial state.
00425           // It can also be overridden with set_init_state().
00426           if (!init_)
00427             init_ = &ls_[name];
00428 
00429           return &(ls_[name]);
00430         }
00431       return &(i->second);
00432     }
00433 
00434     State*
00435     set_init_state(const label_t& state)
00436     {
00437       State* s = add_state(state);
00438       init_ = s;
00439       return s;
00440     }
00441 
00442     // tgba interface
00443     virtual ~explicit_graph()
00444     {
00445       typename ls_map::iterator i = ls_.begin();
00446 
00447       while (i != ls_.end())
00448       {
00449         label_t s = i->first;
00450 
00451         // Do not erase the same state twice(Because of possible aliases).
00452         if (sl_.erase(&(i->second)))
00453           i->second.destroy();
00454 
00455         ++i;
00456         destroy_key<label_t> dest;
00457         dest.destroy(s);
00458       }
00459 
00460       this->dict_->unregister_all_my_variables(this);
00461       // These have already been destroyed by subclasses.
00462       // Prevent destroying by tgba::~tgba.
00463       this->last_support_conditions_input_ = 0;
00464       this->last_support_variables_input_ = 0;
00465     }
00466 
00467     virtual State* get_init_state() const
00468     {
00469       if (!init_)
00470         const_cast<explicit_graph<State, Type>*>(this)->add_default_init();
00471 
00472       return init_;
00473     }
00474 
00475     virtual tgba_explicit_succ_iterator<State>*
00476     succ_iter(const spot::state* state,
00477               const spot::state* global_state = 0,
00478               const tgba* global_automaton = 0) const
00479     {
00480       const State* s = down_cast<const State*>(state);
00481       assert(s);
00482 
00483       (void) global_state;
00484       (void) global_automaton;
00485 
00486       return
00487         new tgba_explicit_succ_iterator<State>(s,
00488                                                this
00489                                                ->all_acceptance_conditions());
00490     }
00491 
00492 
00493     typedef std::string (*to_string_func_t)(const label_t& t);
00494 
00495     void set_to_string_func(to_string_func_t f)
00496     {
00497       to_string_func_ = f;
00498     }
00499 
00500     to_string_func_t get_to_string_func() const
00501     {
00502       return to_string_func_;
00503     }
00504 
00505     virtual std::string format_state(const spot::state* state) const
00506     {
00507       const State* se = down_cast<const State*>(state);
00508       assert(se);
00509       typename sl_map::const_iterator i = sl_.find(se);
00510       assert(i != sl_.end());
00511       assert(to_string_func_);
00512       return to_string_func_(i->second);
00513     }
00514 
00518     void add_state_alias(const label_t& alias, const label_t& real)
00519     {
00520       ls_[alias] = *(add_state(real));
00521     }
00522 
00523 
00528     void copy_acceptance_conditions_of(const tgba *a)
00529     {
00530       assert(neg_acceptance_conditions_ == bddtrue);
00531       assert(all_acceptance_conditions_computed_ == false);
00532       bdd f = a->neg_acceptance_conditions();
00533       this->dict_->register_acceptance_variables(f, this);
00534       neg_acceptance_conditions_ = f;
00535     }
00536 
00537 
00539     void set_acceptance_conditions(bdd acc)
00540     {
00541       assert(neg_acceptance_conditions_ == bddtrue);
00542       assert(all_acceptance_conditions_computed_ == false);
00543 
00544       this->dict_->register_acceptance_variables(bdd_support(acc), this);
00545       neg_acceptance_conditions_ = compute_neg_acceptance_conditions(acc);
00546       all_acceptance_conditions_computed_ = true;
00547       all_acceptance_conditions_ = acc;
00548     }
00549 
00550     void add_acceptance_condition(transition* t, const ltl::formula* f)
00551     {
00552       bdd c = get_acceptance_condition(f);
00553       t->acceptance_conditions |= c;
00554     }
00555 
00558     void add_acceptance_conditions(transition* t, bdd f)
00559     {
00560       bdd sup = bdd_support(f);
00561       this->dict_->register_acceptance_variables(sup, this);
00562       while (sup != bddtrue)
00563         {
00564           neg_acceptance_conditions_ &= bdd_nithvar(bdd_var(sup));
00565           sup = bdd_high(sup);
00566         }
00567       t->acceptance_conditions |= f;
00568     }
00569 
00570     virtual bdd all_acceptance_conditions() const
00571     {
00572       if (!all_acceptance_conditions_computed_)
00573       {
00574         all_acceptance_conditions_ =
00575           compute_all_acceptance_conditions(neg_acceptance_conditions_);
00576         all_acceptance_conditions_computed_ = true;
00577       }
00578       return all_acceptance_conditions_;
00579     }
00580 
00581     virtual bdd_dict* get_dict() const
00582     {
00583       return this->dict_;
00584     }
00585 
00586     virtual bdd neg_acceptance_conditions() const
00587     {
00588       return neg_acceptance_conditions_;
00589     }
00590 
00591     void
00592     declare_acceptance_condition(const ltl::formula* f)
00593     {
00594       int v = this->dict_->register_acceptance_variable(f, this);
00595       f->destroy();
00596       bdd neg = bdd_nithvar(v);
00597       neg_acceptance_conditions_ &= neg;
00598 
00599       // Append neg to all acceptance conditions.
00600       typename explicit_graph<State, tgba>::ls_map::iterator i;
00601       for (i = this->ls_.begin(); i != this->ls_.end(); ++i)
00602         {
00603           typename transitions_t::iterator i2;
00604           for (i2 = i->second.successors.begin();
00605                i2 != i->second.successors.end(); ++i2)
00606             i2->acceptance_conditions &= neg;
00607         }
00608 
00609       all_acceptance_conditions_computed_ = false;
00610     }
00611 
00612   protected:
00613 
00614     bdd get_acceptance_condition(const ltl::formula* f)
00615     {
00616       bdd_dict::fv_map::iterator i = this->dict_->acc_map.find(f);
00617       assert(this->has_acceptance_condition(f));
00618       f->destroy();
00619       bdd v = bdd_ithvar(i->second);
00620       v &= bdd_exist(neg_acceptance_conditions_, v);
00621       return v;
00622     }
00623 
00624     virtual bdd compute_support_conditions(const spot::state* in) const
00625     {
00626       const State* s = down_cast<const State*>(in);
00627       assert(s);
00628       const transitions_t& st = s->successors;
00629 
00630       bdd res = bddfalse;
00631 
00632       typename transitions_t::const_iterator i;
00633       for (i = st.begin(); i != st.end(); ++i)
00634         res |= i->condition;
00635 
00636       return res;
00637     }
00638 
00639     virtual bdd compute_support_variables(const spot::state* in) const
00640     {
00641       const State* s = down_cast<const State*>(in);
00642       assert(s);
00643       const transitions_t& st = s->successors;
00644 
00645       bdd res = bddtrue;
00646 
00647       typename transitions_t::const_iterator i;
00648       for (i = st.begin(); i != st.end(); ++i)
00649         res &= bdd_support(i->condition);
00650 
00651       return res;
00652     }
00653 
00654     ls_map ls_;
00655     sl_map sl_;
00656     State* init_;
00657 
00658     bdd_dict* dict_;
00659 
00660     mutable bdd all_acceptance_conditions_;
00661     mutable bool all_acceptance_conditions_computed_;
00662     bdd neg_acceptance_conditions_;
00663     to_string_func_t to_string_func_;
00664   };
00665 
00666   template <typename State>
00667   class tgba_explicit: public explicit_graph<State, tgba>
00668   {
00669   public:
00670     tgba_explicit(bdd_dict* dict): explicit_graph<State,tgba>(dict)
00671     {
00672     }
00673 
00674     virtual ~tgba_explicit()
00675     {
00676     }
00677 
00678   private:
00679     // Disallow copy.
00680     tgba_explicit(const tgba_explicit<State>& other);
00681     tgba_explicit& operator=(const tgba_explicit& other);
00682   };
00683 
00684   template <typename State>
00685   class sba_explicit: public explicit_graph<State, sba>
00686   {
00687   public:
00688     sba_explicit(bdd_dict* dict): explicit_graph<State, sba>(dict)
00689     {
00690     }
00691 
00692     virtual ~sba_explicit()
00693     {
00694     }
00695 
00696     virtual bool state_is_accepting(const spot::state* s) const
00697     {
00698       // Assume that an accepting state has only accepting output transitions
00699       // So we need only to check one to decide
00700       tgba_explicit_succ_iterator<State>* it = this->succ_iter(s);
00701       it->first();
00702 
00703       // no transition
00704       if (it->done())
00705       {
00706         delete it;
00707         return false;
00708       }
00709 
00710       bool res = it->current_acceptance_conditions() != bddfalse;
00711       delete it;
00712 
00713       return res;
00714     }
00715 
00716   private:
00717     // Disallow copy.
00718     sba_explicit(const sba_explicit<State>& other);
00719     sba_explicit& operator=(const sba_explicit& other);
00720   };
00721 
00722 
00723   // It is tempting to write
00724   //
00725   // template<template<typename T>class graph, typename Type>
00726   // class explicit_conf: public graph<T>
00727   //
00728   // to simplify the typedefs at the end of the file, however swig
00729   // cannot parse this syntax.
00730 
00733   template<class graph, typename Type>
00734   class explicit_conf: public graph
00735   {
00736   public:
00737     explicit_conf(bdd_dict* d): graph(d)
00738     {
00739       this->set_to_string_func(to_string);
00740     };
00741 
00742     static std::string to_string(const typename Type::label_t& l)
00743     {
00744       std::stringstream ss;
00745       ss << l;
00746       return ss.str();
00747     }
00748   };
00749 
00750   template<class graph>
00751   class explicit_conf<graph, state_explicit_string>: public graph
00752   {
00753   public:
00754     explicit_conf(bdd_dict* d): graph(d)
00755     {
00756       this->set_to_string_func(to_string);
00757     };
00758 
00759     static std::string to_string(const std::string& l)
00760     {
00761       return l;
00762     }
00763   };
00764 
00765   template<class graph>
00766   class explicit_conf<graph, state_explicit_formula>: public graph
00767   {
00768   public:
00769     explicit_conf(bdd_dict* d): graph(d)
00770     {
00771       this->set_to_string_func(to_string);
00772     };
00773 
00774     // Enable UTF8 output for the formulae that label states.
00775     void enable_utf8()
00776     {
00777       this->set_to_string_func(to_utf8_string);
00778     }
00779 
00780     static std::string to_string(const ltl::formula* const& l)
00781     {
00782       return ltl::to_string(l);
00783     }
00784 
00785     static std::string to_utf8_string(const ltl::formula* const& l)
00786     {
00787       return ltl::to_utf8_string(l);
00788     }
00789   };
00790 
00791 
00792   // Typedefs for tgba
00793   typedef explicit_conf<tgba_explicit<state_explicit_string>,
00794                         state_explicit_string> tgba_explicit_string;
00795   typedef explicit_conf<tgba_explicit<state_explicit_formula>,
00796                         state_explicit_formula> tgba_explicit_formula;
00797   typedef explicit_conf<tgba_explicit<state_explicit_number>,
00798                         state_explicit_number> tgba_explicit_number;
00799 
00800   // Typedefs for sba
00801   typedef explicit_conf<sba_explicit<state_explicit_string>,
00802                         state_explicit_string> sba_explicit_string;
00803   typedef explicit_conf<sba_explicit<state_explicit_formula>,
00804                         state_explicit_formula> sba_explicit_formula;
00805   typedef explicit_conf<sba_explicit<state_explicit_number>,
00806                         state_explicit_number> sba_explicit_number;
00807 }
00808 
00809 #endif // SPOT_TGBA_TGBAEXPLICIT_HH

Please comment this page and report errors about it on the RefDocComments page.
Generated on Wed May 23 2012 12:06:45 for spot by doxygen 1.7.6.1