spot
0.9.1
|
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