WFA.hpp

Go to the documentation of this file.
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