00001 #ifndef wali_wfa_WFA_GUARD 00002 #define wali_wfa_WFA_GUARD 1 00003 00004 /** 00005 * @author Nicholas Kidd 00006 */ 00007 00008 // ::wali 00009 #include "wali/Common.hpp" 00010 #include "wali/Printable.hpp" 00011 #include "wali/SemElem.hpp" 00012 #include "wali/HashMap.hpp" 00013 #include "wali/KeyContainer.hpp" 00014 00015 // ::wali::wfa 00016 #include "wali/wfa/WeightMaker.hpp" 00017 #include "wali/wfa/Trans.hpp" 00018 #include "wali/wfa/TransSet.hpp" 00019 00020 // std::c++ 00021 #include <iostream> 00022 #include <list> 00023 #include <set> 00024 00025 namespace wali 00026 { 00027 template< typename T > class Worklist; 00028 00029 namespace wpds 00030 { 00031 class WPDS; 00032 class DebugWPDS; 00033 class TransCopyLinker; 00034 namespace ewpds 00035 { 00036 class EWPDS; 00037 } 00038 namespace fwpds 00039 { 00040 class FWPDS; 00041 class SWPDS; 00042 } 00043 } 00044 00045 namespace regex { 00046 class Regex; 00047 typedef wali::ref_ptr<Regex> regex_t; 00048 } 00049 00050 namespace wfa 00051 { 00052 class State; 00053 class TransFunctor; 00054 class ConstTransFunctor; 00055 00056 /** @class WFA 00057 * 00058 * TODO: 00059 * - Should state_map_t have type HashMap< Key , ref_ptr<State> > 00060 * This allows for automatic collection of States via HashMap 00061 * State objects can escape the WFA (@see WPDS). 00062 */ 00063 00064 class WFA : public Printable 00065 { 00066 // 00067 // Types 00068 // 00069 public: 00070 /** 00071 * @enum query_t 00072 * query_t determines how the weights are extended 00073 * during path_summary. INORDER is the normal each state's 00074 * weight is the combine of all outgoing transitions's weights 00075 * extended by the "to" state. REVERSE reverses this. INORDER 00076 * corresponds to a prestar query while REVERSE corresponds to 00077 * a poststar query when used with WPDS 00078 */ 00079 enum query_t { INORDER,REVERSE,MAX }; 00080 00081 typedef wali::HashMap< KeyPair, TransSet > kp_map_t; 00082 typedef wali::HashMap< Key , State * > state_map_t; 00083 typedef wali::HashMap< Key , TransSet > eps_map_t; 00084 typedef std::set< State*,State > StateSet_t; 00085 typedef wali::HashMap< Key,StateSet_t > PredHash_t; 00086 00087 friend class ::wali::wpds::WPDS; 00088 friend class ::wali::wpds::DebugWPDS; 00089 friend class ::wali::wpds::ewpds::EWPDS; 00090 friend class ::wali::wpds::fwpds::FWPDS; 00091 friend class ::wali::wpds::fwpds::SWPDS; 00092 00093 static const std::string XMLTag; 00094 static const std::string XMLQueryTag; 00095 static const std::string XMLInorderTag; 00096 static const std::string XMLReverseTag; 00097 00098 protected: 00099 private: 00100 00101 // 00102 // Methods 00103 // 00104 public: 00105 WFA( query_t q = INORDER ); 00106 WFA( const WFA & rhs ); 00107 WFA & operator=( const WFA & rhs ); 00108 00109 virtual ~WFA(); 00110 00111 /** 00112 * Remove all transitions from the WFA 00113 */ 00114 virtual void clear(); 00115 00116 /** 00117 * @brief set initial state 00118 * 00119 * A WFA has 1 initial state. This method will 00120 * set it to the key parameter 00121 * 00122 * @param key the key for the desired initial state 00123 * @return Key that is the old initial stat 00124 */ 00125 Key set_initial_state( Key key ); 00126 00127 /** 00128 * @brief set initial state 00129 * 00130 * A WFA has 1 initial state. This method will 00131 * set it to the key parameter 00132 * 00133 * @param key the key for the desired initial state 00134 * @return Key that is the old initial stat 00135 */ 00136 Key setInitialState( Key key ); 00137 00138 /** 00139 * @brief Return the initial state 00140 * 00141 * @return Key for the initial state 00142 */ 00143 Key initial_state() const; 00144 00145 /** 00146 * @brief Return the initial state 00147 * 00148 * @return Key for the initial state 00149 */ 00150 Key getInitialState() const; 00151 00152 /** 00153 * Test if param key is the initial state. 00154 * 00155 * @return true if key == WFA::initial_state() 00156 */ 00157 bool isInitialState( Key key ) const; 00158 00159 /** 00160 * Add parameter key to the set of final states 00161 */ 00162 void add_final_state( Key key ); 00163 00164 /** 00165 * Add parameter key to the set of final states 00166 */ 00167 void addFinalState( Key key ); 00168 00169 /** 00170 * Return true if parameter key is a final state 00171 */ 00172 bool isFinalState( Key key ) const; 00173 00174 /** 00175 * Set the WFA query mode. 00176 * @return the old query mode 00177 */ 00178 query_t setQuery( query_t newQuery ); 00179 00180 /** 00181 * @return WFA query mode 00182 * 00183 * The query mode effects how weights are extended during 00184 * path summary. 00185 * 00186 * @see WFA::query_t 00187 */ 00188 query_t getQuery() const; 00189 00190 /** 00191 * @return The current generation 00192 * 00193 * Each WFA keeps a generation, which is 00194 * the number of times a reachability query has 00195 * been invoked on the WFA. 00196 */ 00197 size_t getGeneration() const; 00198 00199 /** 00200 * @brief Set the generation to have the value of param g 00201 * @return void 00202 */ 00203 void setGeneration(size_t g); 00204 00205 /** @brief Get a weight from the WFA. This is to get hold 00206 * of the weight domain class 00207 * 00208 * @see sem_elem_t 00209 * @return a weight on some transition in the WFA 00210 */ 00211 virtual sem_elem_t getSomeWeight() const; 00212 00213 /** @brief Add transition (p,g,q) to the WFA 00214 * 00215 * @see Key 00216 * @see sem_elem_t 00217 */ 00218 virtual void addTrans( 00219 Key p, 00220 Key g, 00221 Key q, 00222 sem_elem_t se ); 00223 00224 /** 00225 * @brief Add Trans t to the WFA 00226 * 00227 * @see wali::wfa::Trans 00228 */ 00229 virtual void addTrans( ITrans * t ); 00230 00231 /** 00232 * @brief erase Trans 00233 * 00234 * Removes Trans (from,stack,to) from the WFA if it exists. 00235 */ 00236 virtual void erase( 00237 Key from, 00238 Key stack, 00239 Key to ); 00240 00241 /** 00242 * @brief erase State q and all of its outgoing transitions 00243 * It does not remove incoming transitions -- 00244 * <b><i>that has to be done by the client</i></b>. 00245 * 00246 * This does not delete the wfa::State object. The destructor 00247 * will take care of reclaiming memory. 00248 * 00249 * @return true if it was sucessful 00250 */ 00251 virtual bool eraseState( Key q ); 00252 00253 /** 00254 * @brief return true if transition matching (p,g,q) exists 00255 * and copy that transition into the ref parameter t 00256 * 00257 * If a Trans matching (p,g,q) exists then it is copied into the 00258 * passed in reference "Trans & t". This way the user is not given 00259 * and handle to the WFA's internal Trans * pointer and deleting 00260 * all transitions associated with this WFA when it is deleted is 00261 * safe. However, because the weight of this transition is a 00262 * sem_elem_t (ref_ptr< SemElem >) modifying the weight from 00263 * the Trans & t will result in modification of the weight on 00264 * the interal Trans * object. 00265 * 00266 * @return bool true if transition matching (p,g,q) exists 00267 * @see Trans 00268 * @see SemElem 00269 * @see sem_elem_t 00270 */ 00271 virtual bool find( 00272 Key p, 00273 Key g, 00274 Key q, 00275 Trans & t ); 00276 00277 /** 00278 * @brief invoke TransFunctor tf on each Trans 00279 */ 00280 virtual void for_each( TransFunctor& tf ); 00281 00282 /** 00283 * @brief invoke ConstTransFunctor on each Trans 00284 */ 00285 virtual void for_each( ConstTransFunctor& tf ) const; 00286 00287 /** 00288 * Intersect this with parameter fa. This is a wrapper 00289 * for intersect( WeightMaker&,WFA& ) that passes 00290 * the WeightMaker KeepBoth. 00291 * 00292 * @see wali::wfa::WeightMaker 00293 * @see wali::wfa::KeepBoth 00294 */ 00295 virtual WFA intersect( WFA& fa ); 00296 00297 /** 00298 * Intersect this with parameter fa. This is a wrapper 00299 * for intersect( WeightMaker&,WFA&,WFA& ) that passes 00300 * the WeightMaker KeepBoth. Result is stored in dest. 00301 * 00302 * @see wali::wfa::WeightMaker 00303 * @see wali::wfa::KeepBoth 00304 */ 00305 virtual void intersect( WFA& fa, WFA& dest ); 00306 00307 /** 00308 * Intersect this with parameter fa and return the result 00309 * by value. The parameter WeightMaker determines how 00310 * intersection should join the weights on matching 00311 * transitions. 00312 * 00313 * @see wali::wfa::WeightMaker 00314 */ 00315 WFA intersect( WeightMaker& wmaker , WFA& fa ); 00316 00317 /** 00318 * Intersect this with parameter fa. The result is stored in 00319 * parameter dest. Parameter dest is cleared before any 00320 * results are stored. The parameter WeightMaker determines 00321 * how intersection should join the weights on matching 00322 * transitions. 00323 * 00324 * NOTE: For now this means (dest != this) && (dest != fa). 00325 */ 00326 virtual void intersect( WeightMaker& wmaker , WFA& fa, WFA& dest ); 00327 00328 /** 00329 * Performs path summary. Simply calls the path_summary with 00330 * the default Worklist provided by WALi. 00331 */ 00332 virtual void path_summary(); 00333 00334 /** 00335 * Computes a regular expression for the automaton. 00336 * The regex, when evaluated, produces a weight 00337 * that is equal to calling path_summary and then 00338 * getting the weight on the initial state. I.e., 00339 * 00340 * <code> 00341 * fa.toRegex().solve(); 00342 * <==> 00343 * fa.path_summary(); 00344 * fa.getState( fa.getInitialState() )->weight(); 00345 * 00346 * </code> 00347 */ 00348 virtual regex::regex_t toRegex(); 00349 00350 /** 00351 * Performs path summary with the specified Worklist 00352 */ 00353 virtual void path_summary( Worklist<State>& wl ); 00354 00355 /** 00356 * Performs path summary. Simply calls the path_summary with 00357 * the default Worklist provided by WALi. 00358 * Initializes the weight on the final state to wt (can be 00359 * useful for efficiency in some cases) 00360 */ 00361 virtual void path_summary(sem_elem_t wt); 00362 00363 /** 00364 * Prunes the WFA. This removes any transitions that are 00365 * not in the (getInitialState(),F) chop. 00366 */ 00367 virtual void prune(); 00368 00369 /** 00370 * Intersects the WFA with <init_state, (stk \Gamma^*)> 00371 * that essentially removes transitions and calls prune 00372 */ 00373 virtual void filter(Key stk); 00374 00375 /** 00376 * Intersects the WFA with { <init_state, (stk \Gamma^*)> | stk 00377 * \in stkset } 00378 * This essentially removes transitions and calls prune 00379 */ 00380 virtual void filter(std::set<Key> &stkset); 00381 00382 /** 00383 * For every state s \in st, rename it to s'. Then add 00384 * epsilon transition from s to s' and perform the 00385 * epsilon closure. This uses WFA::getGeneration() to 00386 * produce the renamed states. 00387 * Returns the result in "output" 00388 */ 00389 virtual void duplicateStates(std::set<Key> &st, WFA &output) const; 00390 00391 /** 00392 * Write the WFA to the std::ostream parameter, implements 00393 * Printable::print 00394 * 00395 * @param o the std::ostream this is written to 00396 * @return std::ostream WFA was written to 00397 * 00398 * @see Printable 00399 */ 00400 virtual std::ostream & print( std::ostream & ) const; 00401 00402 /** 00403 * @brief Print WFA in dot format 00404 */ 00405 virtual std::ostream& print_dot( 00406 std::ostream& o, 00407 bool print_weights=false ) const; 00408 00409 /** 00410 * @brief marshall WFA in XML 00411 */ 00412 virtual std::ostream& marshall( std::ostream& o ) const; 00413 00414 virtual std::ostream& marshallState( std::ostream& o, Key key ) const; 00415 00416 /** 00417 * @brief inserts tnew into the WFA 00418 * 00419 * This method inserts Trans * tnew into the WFA. If a transition 00420 * told matching (p,g,q) of tnew already exists, then tnew is 00421 * combined into told. 00422 * 00423 * @warning: Note that insert assumes ownership of the passed 00424 * in parameter tnew 00425 * @warning: insert does assumes the states of tnew 00426 * are already in the WFA. If they are not path_summary 00427 * and other methods might fail 00428 * 00429 * @return pointer to real transition 00430 */ 00431 ITrans * insert( ITrans * tnew ); 00432 00433 /** 00434 * @brief Returns a TransSet containing all 00435 * transitions matching (p,y,?) in the WFA 00436 * 00437 * @see TransSet 00438 */ 00439 TransSet match( Key p, Key y); 00440 00441 /** 00442 * Create a State * for the key Key 00443 */ 00444 void addState( Key key , sem_elem_t zero ); 00445 00446 /** 00447 * @return const pointer to underlying State object or NULL if 00448 * no such state exists. 00449 * 00450 * @note This may throw an exception in the future 00451 */ 00452 const State* getState( Key name ) const; 00453 00454 /** 00455 * @return pointer to underlying State object or NULL if 00456 * no such state exists. 00457 * 00458 * @param name the key for this State 00459 * @note This may throw an exception in the future 00460 * 00461 */ 00462 State * getState( Key name ); 00463 00464 const std::set< Key >& getStates() const; 00465 00466 const std::set< Key >& getFinalStates() const; 00467 00468 /* TODO 00469 size_t size() const; 00470 */ 00471 00472 size_t numStates() const 00473 { 00474 return Q.size(); 00475 } 00476 00477 protected: 00478 00479 /** 00480 * setupFixpoint clears each states markable flag and sets 00481 * the states weight to zero 00482 */ 00483 void setupFixpoint( Worklist<State>& wl, PredHash_t& preds ); 00484 00485 /** 00486 * setupFixpoint clears each states markable flag and sets 00487 * the states weight to zero, and weight of final states to 00488 * wtFinal (or ONE if NULL) 00489 */ 00490 void setupFixpoint( Worklist<State>& wl, PredHash_t& preds, sem_elem_t wtFinal ); 00491 00492 virtual ITrans * find( 00493 Key p, 00494 Key g, 00495 Key q); 00496 00497 /** 00498 * Erases the specified Trans(from,stack,to) from the 00499 * kpmap and epsmap. A null return value means no transition existed. 00500 * 00501 * @return the Trans* that was removed from the maps 00502 */ 00503 ITrans * eraseTransFromMaps( 00504 Key from, 00505 Key stack, 00506 Key to ); 00507 /** 00508 * Erases the specified Trans(from,stack,to) from the 00509 * kpmap. A null return value means no transition existed. 00510 * 00511 * @return the Trans* that was removed from the KpMap 00512 */ 00513 ITrans* eraseTransFromKpMap( 00514 Key from, 00515 Key stack, 00516 Key to ); 00517 00518 ITrans* eraseTransFromKpMap( ITrans* terase ); 00519 00520 /** 00521 * Erases the specified Trans(from,stack,to) from the 00522 * epsmap. A false return value means no transition existed. 00523 * 00524 * @return true if a transition was erased from EpsMap 00525 */ 00526 ITrans* eraseTransFromEpsMap( ITrans* terase ); 00527 00528 /** 00529 * Erases the State 'state' from the WFA and all transitions 00530 * that go to or from the State. 00531 * 00532 * @return true 00533 */ 00534 bool eraseState( State* state ); 00535 00536 /** 00537 * Performs path summary with the specified Worklist 00538 * Initializes the weight on the final state to wt (can be 00539 * useful for efficiency in some cases) 00540 */ 00541 virtual void path_summary( Worklist<State>& wl, sem_elem_t wt ); 00542 00543 /** 00544 * Uses Tarjan's algorithm to build a regular expression 00545 * for this WFA. IIRC, it is the cubic dynamic programming 00546 * algorithm. 00547 */ 00548 regex::regex_t TarjanBasicRegex(); 00549 00550 private: 00551 // Poststar builds backwards WFAs so 00552 // extend needs to take this into account. 00553 regex::regex_t EXTEND(regex::regex_t a,regex::regex_t b); 00554 00555 // 00556 // Variables 00557 // 00558 public: 00559 protected: 00560 kp_map_t kpmap; //! < map from KeyPair to list of trans 00561 state_map_t state_map; //! < map from key to State 00562 eps_map_t eps_map; //! < map from "to state" to list of eps trans ending in "to state" 00563 Key init_state; //! < initial state of WFA 00564 std::set< Key > F; //! < set of final states 00565 std::set< Key > Q; //! < set of all states 00566 query_t query; //! < determine the extend order for path_summary 00567 size_t generation; //! < Each WPDS query increments the generation count. 00568 00569 private: 00570 00571 }; 00572 00573 } // namespace wfa 00574 00575 } // namespace wali 00576 00577 #endif // wali_wfa_WFA_GUARD 00578