WPDS.hpp

Go to the documentation of this file.
00001 #ifndef wali_wpds_WPDS_GUARD
00002 #define wali_wpds_WPDS_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/HashMap.hpp"
00012 #include "wali/KeyContainer.hpp"
00013 #include "wali/SemElem.hpp"
00014 #include "wali/Worklist.hpp"
00015 
00016 // ::wali::wfa
00017 #include "wali/wfa/WFA.hpp"
00018 #include "wali/wfa/TransFunctor.hpp"
00019 
00020 // ::wali::wpds
00021 #include "wali/wpds/Wrapper.hpp"
00022 
00023 // std c++
00024 #include <iostream>
00025 #include <set>
00026 
00027 namespace wali
00028 {
00029   template< typename T > class Worklist;
00030 
00031   namespace wfa
00032   {
00033     class ITrans;
00034   }
00035 
00036   namespace wpds
00037   {
00038 
00039     class Config;
00040     class rule_t;
00041     class RuleFunctor;
00042     class ConstRuleFunctor;
00043 
00044     /**
00045      * @class WPDS
00046      */
00047     class WPDS : public Printable, public wfa::ConstTransFunctor
00048     {
00049 
00050       public:
00051         static const std::string XMLTag;
00052 
00053       protected:
00054         typedef HashMap< KeyPair,Config * > chash_t;
00055         typedef chash_t::iterator iterator;
00056         typedef chash_t::const_iterator const_iterator;
00057 
00058         /**
00059          * r2hash_t is a map from key to list of rules. The key
00060          * is the second RHS stack symbol of a rule. For example, 
00061          * the rule R1 = < s1,a > -> < s2, b c > will add R1 to 
00062          * the list that is mapped to by the stack symbol c.
00063          */
00064         typedef HashMap< Key, std::list< rule_t > > r2hash_t;
00065 
00066       private:
00067 
00068       public:
00069 
00070         WPDS();
00071         WPDS( ref_ptr<Wrapper> wrapper );
00072         WPDS( const WPDS& w );
00073         virtual ~WPDS();
00074 
00075         /**
00076          * Clears all rules from the WPDS
00077          */
00078         virtual void clear();
00079 
00080         /**
00081          * Set the worklist used for pre and poststar queries.
00082          */
00083         void setWorklist( ref_ptr< Worklist<wfa::ITrans> > wl );
00084 
00085 
00086         /** 
00087          * @brief create rule with no r.h.s. stack symbols
00088          * @return true if rule existed
00089          *
00090          * @see sem_elem_t
00091          * @see Key
00092          */
00093         virtual bool add_rule(
00094             Key from_state,
00095             Key from_stack,
00096             Key to_state,
00097             sem_elem_t se );
00098 
00099         /** @brief create rule with one r.h.s. stack symbol
00100          *
00101          * @return true if rule existed
00102          *
00103          * @see sem_elem_t
00104          * @see Key
00105          */
00106         virtual bool add_rule(
00107             Key from_state,
00108             Key from_stack,
00109             Key to_state,
00110             Key to_stack1,
00111             sem_elem_t se );
00112 
00113         /** @brief create rule with two r.h.s. stack symbols
00114          *
00115          * @return true if rule existed
00116          *
00117          * @see sem_elem_t
00118          * @see Key
00119          */
00120         virtual bool add_rule(
00121             Key from_state,
00122             Key from_stack,
00123             Key to_state,
00124             Key to_stack1,
00125             Key to_stack2,
00126             sem_elem_t se );
00127 
00128         /** 
00129          * @brief create rule with no r.h.s. stack symbols
00130      * @brief Replace the weight if the rule already existed
00131          * @return true if rule existed
00132          *
00133          * @see sem_elem_t
00134          * @see Key
00135          */
00136         virtual bool replace_rule(
00137             Key from_state,
00138             Key from_stack,
00139             Key to_state,
00140             sem_elem_t se );
00141 
00142         /** @brief create rule with one r.h.s. stack symbol
00143      * @brief Replace the weight if the rule already existed
00144          *
00145          * @return true if rule existed
00146          *
00147          * @see sem_elem_t
00148          * @see Key
00149          */
00150         virtual bool replace_rule(
00151             Key from_state,
00152             Key from_stack,
00153             Key to_state,
00154             Key to_stack1,
00155             sem_elem_t se );
00156 
00157         /** @brief create rule with two r.h.s. stack symbols
00158      * @brief Replace the weight if the rule already existed
00159          *
00160          * @return true if rule existed
00161          *
00162          * @see sem_elem_t
00163          * @see Key
00164          */
00165         virtual bool replace_rule(
00166             Key from_state,
00167             Key from_stack,
00168             Key to_state,
00169             Key to_stack1,
00170             Key to_stack2,
00171             sem_elem_t se );
00172 
00173         /**
00174          * @brief Perform prestar reachability query
00175          *
00176          * @return wfa::WFA
00177          *
00178          * @see wfa::WFA
00179          */
00180         virtual wfa::WFA prestar( wfa::WFA const & input );
00181 
00182         /**
00183          * @brief Perform prestar reachability query
00184          * The result of the query is stored in
00185          * the parameter WFA& output. Any transitions
00186          * in output before the query will be there
00187          * after the query but will have no effect
00188          * on the reachability query.
00189          *
00190          * @return void
00191          *
00192          * @see wfa::WFA
00193          */
00194         virtual void prestar( wfa::WFA const & input, wfa::WFA & output );
00195 
00196         /**
00197          * @brief Perform poststar reachability query
00198          *
00199          * @return WFA
00200          *
00201          * @see wfa::WFA
00202          */
00203         virtual wfa::WFA poststar( wfa::WFA const & input );
00204 
00205         /**
00206          * @brief Perform poststar reachability query.
00207          * The result of the query is stored in
00208          * the parameter WFA& output. Any transitions
00209          * in output before the query will be there
00210          * after the query but will have no effect
00211          * on the reachability query.
00212          *
00213          * @return wfa::WFA
00214          *
00215          * @see wfa::WFA
00216          */
00217         virtual void poststar( wfa::WFA const & input, wfa::WFA & output );
00218 
00219         /**
00220          * This method writes the WPDS to the passed in 
00221          * std::ostream parameter. Implements Printable::print.
00222          *
00223          * @param o the std::ostream this is written to
00224          * @return std::ostream this was written to
00225          *
00226          * @see Printable
00227          */
00228         virtual std::ostream & print( std::ostream & o ) const;
00229 
00230         /**
00231          * This method marshalls the WPDS into the passed
00232          * in std::ostream parameter.  Marshalling simply
00233          * writes the WPDS in XML form.
00234          *
00235          * @return std::ostream the WPDS was marshalled into
00236          */
00237         virtual std::ostream & marshall( std::ostream & o ) const;
00238 
00239         /**
00240          * Print the WPDS in dot format. The format is a little strange:
00241          * by default it does not print state information (since there is
00242          * typically only one state in a WPDS), however, it can be included
00243          * optionally.
00244          *
00245          * Additionally, delta-0 edges are drawn as edges to nowhere
00246          * (indicating "I don't know where this goes, since it is dynamic"),
00247          * and delta-2 edges use the stack symbol which is pushed as the edge
00248          * label, and call the top of stack symbol the state.
00249          *
00250          * Printing weights is not currently supported, though it would not be
00251          * difficult to add.
00252          */
00253         virtual std::ostream & print_dot( 
00254             std::ostream & o,
00255             bool print_state=false) const;
00256 
00257         /**
00258          * @brief Return the number of rules in the WPDS.
00259          * Note that this function takes time O(num rules), not
00260          * constant time.
00261          *
00262          */
00263         virtual int count_rules( ) const;
00264 
00265         /**
00266          * @brief apply ConstRuleFunctor to each rule in WPDS
00267          *
00268          * @see ConstRuleFunctor
00269          * @see Rule
00270          * @see rule_t
00271          */
00272         virtual void for_each( ConstRuleFunctor &func ) const;
00273 
00274         /**
00275          * @brief apply RuleFunctor to each rule in WPDS
00276          *
00277          * @see RuleFunctor
00278          * @see Rule
00279          * @see rule_t
00280          */
00281         virtual void for_each( RuleFunctor &func );
00282 
00283         /**
00284          * Implementation of TransFunctor
00285          */
00286         virtual void operator()( wfa::ITrans const * t );
00287 
00288         bool is_pds_state(wali::Key k) const;
00289         int num_pds_states() const { return (int) pds_states.size(); }
00290         const std::set<wali::Key>& get_states() const { return pds_states; }
00291  
00292         /** @brief Runs a poststar query on the following automaton
00293          * to get one that represents the program CFG.
00294          *
00295          * Ainit = { (p, e, <p,e>) | e \in Procedure Entry Point }
00296          *
00297          * returns the PDS state p; a map [e -> <p,e>]; and poststar(Ainit)
00298          */
00299         Key constructCFG(std::set<Key> &entries, std::map<Key, Key> &entryState, wfa::WFA &cfg);
00300 
00301         sem_elem_t get_theZero() {return theZero; }
00302       protected:
00303 
00304         /** @brief Actually creates the rule, hanldes the mappings,
00305          * etc.
00306      * @brief Replace the weight if the rule already existed and replace_weight is set,
00307      * otherwise take a combine of the weights
00308          *
00309          * @return true if rule existed
00310          *
00311          * @see sem_elem_t
00312          * @see Key
00313          */
00314         virtual bool add_rule(
00315             Key from_state,
00316             Key from_stack,
00317             Key to_state,
00318             Key to_stack1,
00319             Key to_stack2,
00320             sem_elem_t se,
00321         bool replace_weight,
00322             rule_t& r );
00323 
00324         /** @brief Actually creates the rule, hanldes the mappings,
00325          * etc.
00326          *
00327          * @return true if rule existed
00328          *
00329          * @see sem_elem_t
00330          * @see Key
00331          */
00332         virtual bool add_rule(
00333             Key from_state,
00334             Key from_stack,
00335             Key to_state,
00336             Key to_stack1,
00337             Key to_stack2,
00338             sem_elem_t se,
00339             rule_t& r );
00340 
00341         /**
00342          * @brief copy relevant material from input WFA to output WFA
00343          */
00344         virtual void setupOutput( wfa::WFA const & input, wfa::WFA& fa );
00345 
00346         /**
00347          * @brief For each t \in fa, t->setConfig(0)
00348          */
00349         virtual void unlinkOutput( wfa::WFA& fa );
00350 
00351         /**
00352          * @brief Gets WPDS ready for fixpoint
00353          */
00354         virtual void prestarSetupFixpoint( wfa::WFA const & input, wfa::WFA& fa );
00355 
00356         /**
00357          * @brief Performs the fixpoint computation
00358          */
00359         virtual void prestarComputeFixpoint( wfa::WFA& fa );
00360 
00361         /**
00362          * @brief Performs pre for 1 ITrans
00363          */
00364         virtual void pre( wfa::ITrans * t, wfa::WFA& fa );
00365 
00366         /**
00367          * @brief helper method for prestar
00368          */
00369         virtual void prestar_handle_call(
00370             wfa::ITrans * t1 ,
00371             wfa::ITrans * t2,
00372             rule_t & r,
00373             sem_elem_t delta
00374             );
00375 
00376         /**
00377          * @brief helper method for prestar
00378          */
00379         virtual void prestar_handle_trans(
00380             wfa::ITrans * t,
00381             wfa::WFA & ca  ,
00382             rule_t & r,
00383             sem_elem_t delta );
00384 
00385         /**
00386          * @brief Gets WPDS ready for fixpoint
00387          */
00388         virtual void poststarSetupFixpoint( wfa::WFA const & input, wfa::WFA& fa );
00389 
00390         /**
00391          * @brief Performs the fixpoint computation
00392          */
00393         virtual void poststarComputeFixpoint( wfa::WFA& fa );
00394 
00395         /**
00396          * @brief Performs post for 1 ITrans
00397          */
00398         virtual void post( wfa::ITrans * t, wfa::WFA& fa );
00399 
00400         /**
00401          * @brief helper method for poststar
00402          */
00403         virtual void poststar_handle_eps_trans(
00404             wfa::ITrans *teps, 
00405             wfa::ITrans *tprime, 
00406             sem_elem_t delta
00407             );
00408 
00409         /**
00410          * @brief helper method for poststar
00411          */
00412         virtual void poststar_handle_trans(
00413             wfa::ITrans * t ,
00414             wfa::WFA & ca   ,
00415             rule_t & r,
00416             sem_elem_t delta
00417             );
00418 
00419         /**
00420          * @brief create a new temp state from two existing states
00421          *
00422          * gen_state is only used by poststar
00423          *
00424          * @return Key for new state
00425          */
00426         virtual Key gen_state( Key state, Key stack );
00427 
00428         /**
00429          * @brief link input WFA transitions to Configs
00430          *
00431          * @see Config
00432          * @see wfa::ITrans
00433          * 
00434          */
00435         //virtual void copy_and_link( wfa::WFA & in, wfa::WFA & out );
00436 
00437         /**
00438          * Create the Config for the state and stack KeyPair.
00439          * If the Config already exists just return that.
00440          *
00441          * @return Config pointer
00442          */
00443         virtual Config * make_config( Key state, Key stack );
00444 
00445         /**
00446          * Creates a rule that links two configurations.
00447          * If rule exists then (combines the weight if replace_weight is false) or
00448      * (replace the weight if replace_weight is true)
00449          *
00450          * @return true if Rule already existed
00451          *
00452          * @see Config
00453          * @see sem_elem_t
00454          * @see rule_t
00455          */
00456         virtual bool make_rule(
00457             Config *f,
00458             Config *t,
00459             Key stk2,
00460         bool replace_weight,
00461             rule_t& r );
00462 
00463         /**
00464          * Creates a rule that links two configurations.
00465          * If rule exists then combines the weight
00466          *
00467          * @return true if Rule already existed
00468          *
00469          * @see Config
00470          * @see sem_elem_t
00471          * @see rule_t
00472          */
00473         virtual bool make_rule(
00474             Config *f,
00475             Config *t,
00476             Key stk2,
00477 
00478             rule_t& r );
00479 
00480         /**
00481          * Find config with KeyPair(state,stack)
00482          *
00483          * @return the Config * or 0 if it doesn't exist
00484          *
00485          * @see Config
00486          * @see KeyPair
00487          */
00488         virtual Config * find_config( Key state, Key stack );
00489 
00490         /** @brief helper method for fixpoint loop
00491          *
00492          * return true if wfa::ITrans was retrieved from
00493          * worklist, false if worklist is empty
00494          */
00495         virtual bool get_from_worklist( wfa::ITrans * & );
00496 
00497         /**
00498          * @brief helper function to create and link a transition
00499          *
00500          */
00501         virtual void update(
00502             Key from, Key stack, Key to, 
00503             sem_elem_t se, Config * cfg );
00504 
00505         /**
00506          * update_prime does not need to take a Config b/c no Config
00507          * will match a transition that is created here. The from state
00508          * is not \in WFA.P. Therefore we do not need to add it to the
00509          * worklist.
00510          *
00511          * @return generated transition
00512          */
00513         virtual wfa::ITrans* update_prime(
00514             Key from, //<! Guaranteed to be a generated state
00515             wfa::ITrans* call, //<! The call transition
00516             rule_t r, //<! The push rule
00517             sem_elem_t delta, //<! Delta change on the call transition
00518             sem_elem_t wWithRule //<! delta \extends r->weight()
00519             );
00520 
00521         /**
00522          * @return const chash_t reference
00523          */
00524         const chash_t & config_map() const {
00525           return configs;
00526         }
00527 
00528         /**
00529          * @return chash_t reference
00530          */
00531         chash_t & config_map() {
00532           return configs;
00533         }
00534       private: // methods
00535 
00536       protected: // data members
00537         ref_ptr<Wrapper> wrapper;
00538         ref_ptr< Worklist<wfa::ITrans> > worklist;
00539         chash_t configs;
00540         std::set< Config * > rule_zeroes;
00541         r2hash_t r2hash;
00542 
00543         /**
00544          * Points to the output automaton during a pre or poststar
00545          * query. Is NULL all other times.
00546          */
00547         wfa::WFA* currentOutputWFA; //!< Point
00548 
00549         /**
00550          * theZero holds onto the semiring zero weight
00551          * for this WPDS. It is set the very first time a
00552          * rule is added to the WPDS.
00553          * 
00554          * WARNING: FWPDS relies on theZero being valid.
00555          *          If you go changing theZero, fix FWPDS.
00556          */
00557         sem_elem_t theZero; 
00558         std::set<wali::Key> pds_states; // set of PDS states
00559 
00560       private:
00561 
00562     };
00563 
00564   } // namespace wpds
00565 
00566 } // namespace wali
00567 
00568 #endif  // wali_wpds_WPDS_GUARD
00569