metaSMT git

metaSMT/GraphSolver_Context.hpp

Go to the documentation of this file.
00001 #pragma once
00002 
00003 #include "support/SMT_Graph.hpp"
00004 #include "Graph_Context.hpp"
00005 #include "result_wrapper.hpp"
00006 #include "Features.hpp"
00007 
00008 #include <boost/foreach.hpp>
00009 #include <boost/shared_ptr.hpp>
00010 #include <boost/spirit/include/phoenix_core.hpp>
00011 #include <boost/spirit/include/phoenix_bind.hpp>
00012 
00013 #include <vector>
00014 
00015 namespace metaSMT {
00016 
00017   template <typename Callee, typename T>
00018   struct CallByTag {
00019     CallByTag(Callee * callee, std::vector<T> const & args, boost::any const & arg)
00020       : callee(callee), args(args), arg(arg) {}
00021 
00022 
00023     struct assertion_cmd {};
00024     struct assumption_cmd {};
00025 
00026     typedef typename Callee::result_type result_type;
00027 
00028     template <typename TagT>
00029     result_type operator() (TagT tag) const {
00030       switch(args.size()) {
00031         case 0:
00032           //printf("call op0\n");
00033           return (*callee)( tag, arg );
00034         case 1:
00035           //printf("call op1\n");
00036           return (*callee)( tag, args[0] );
00037         case 2:
00038           //printf("call op2\n");
00039           return (*callee)( tag, args[0], args[1] );
00040         case 3:
00041           //printf("call op3\n");
00042           return (*callee)( tag, args[0], args[1], args[2] );
00043         default:
00044           assert( false && "unexpeced case" );
00045       }
00046       throw std::runtime_error("unexpected");
00047     }
00048 
00049     result_type operator() (metaSMT::logic::QF_BV::tag::extract_tag tag) const {
00050       assert(args.size() > 0);
00051       assert(args.size() == 1);
00052       unsigned long upper, lower;
00053       boost::tie(upper, lower) 
00054         = boost::any_cast<boost::tuple<unsigned long, unsigned long> >(arg);
00055       return (*callee)( tag, upper, lower, args.front() );
00056     }
00057 
00058     result_type operator() (metaSMT::logic::QF_BV::tag::zero_extend_tag tag) const {
00059       assert(args.size() > 0);
00060       assert(args.size() == 1);
00061       unsigned long width
00062         = boost::any_cast< unsigned long >(arg);
00063       return (*callee)( tag, width, args.front() );
00064     }
00065 
00066     result_type operator() (metaSMT::logic::QF_BV::tag::sign_extend_tag tag) const {
00067       assert(args.size() > 0);
00068       assert(args.size() == 1);
00069       unsigned long width
00070         = boost::any_cast< unsigned long >(arg);
00071       return (*callee)( tag, width, args.front() );
00072     }
00073     
00074     mutable Callee       * callee;
00075     std::vector<T> const & args;
00076     boost::any     const & arg;
00077   };
00078 
00079   template <typename Callee, typename T>
00080   CallByTag<Callee, T> make_callByTag(Callee * callee, std::vector<T> const & args, boost::any const & arg) {
00081     return CallByTag<Callee, T>(callee, args, arg);
00082   }
00083 
00084 
00090   template<typename SolverContext>
00091   struct GraphSolver_Context {
00092 
00093     GraphSolver_Context ( ) 
00094       : _gtx( new Graph_Context() )
00095     { }
00096 
00097     GraphSolver_Context ( const GraphSolver_Context & ctx )
00098       : _gtx( ctx._gtx ) // share graph
00099       , _solver() // create new solver
00100       , _lookup() // create new lookup table
00101       , _assertions( ctx._assertions )   // copy assertions
00102       , _assumptions( ctx._assumptions ) // copy assumptions
00103     {
00104       BOOST_FOREACH(SMT_Expression e, _assertions) {
00105         _solver.assertion ( _eval(e) );
00106       }
00107       BOOST_FOREACH(SMT_Expression e, _assumptions) {
00108         _solver.assumption ( _eval(e) );
00109       }
00110     }
00111 
00112     typedef SolverContext solver_type;
00113     typedef SMT_Expression result_type;
00114     typedef typename SolverContext::result_type solver_result;
00115 
00116     void assertion ( SMT_Expression e ) {
00117       namespace ph=boost::phoenix;
00118       _assertions.push_back(e);
00119 
00120       Cmd f = 
00121         ph::bind( &SolverContext::assertion, ph::ref(_solver),
00122           ph::bind(&GraphSolver_Context<SolverContext>::_eval, ph::ref(*this), e )
00123         );
00124       _cmd_queue.push_back(f);
00125     }
00126 
00127     void assumption( SMT_Expression e ) {
00128       _assumptions.push_back(e);
00129     }
00130 
00131     template< typename Context, typename CMD, typename Arg1 >
00132     struct Cmd_Caller1 {
00133       Cmd_Caller1( Context & ctx, CMD c, Arg1 a1)
00134       : ctx(ctx), cmd(c), arg1(a1) { }
00135 
00136       void operator() (){ ctx.command(cmd, arg1); }
00137 
00138       Context & ctx;
00139       CMD cmd;
00140       Arg1 arg1;
00141     };
00142 
00143     template< typename Context, typename CMD >
00144     struct Cmd_Caller0 {
00145       Cmd_Caller0( Context & ctx, CMD c)
00146       : ctx(ctx), cmd(c) { }
00147 
00148       void operator() (){ ctx.command(cmd); }
00149 
00150       Context & ctx;
00151       CMD cmd;
00152     };
00153 
00154     template <typename CMD, typename Arg>
00155     typename boost::enable_if< boost::is_same< typename CMD::result_type, void> >::type
00156     command (CMD const & cmd, Arg arg) 
00157     {
00158       Cmd f = 
00159         Cmd_Caller1<SolverContext, CMD, Arg>(_solver, cmd, arg);
00160       _cmd_queue.push_back(f);
00161     }
00162 
00163     template <typename CMD>
00164     typename boost::enable_if< boost::is_same< typename CMD::result_type, void> >::type
00165     command (CMD const & cmd) 
00166     {
00167       Cmd f = 
00168         Cmd_Caller0<SolverContext, CMD>(_solver, cmd);
00169       _cmd_queue.push_back(f);
00170     }
00171 
00172     template <typename CMD>
00173     typename CMD::result_type command(CMD const & cmd)
00174     {
00175       sync();
00176       return _solver.command(cmd);
00177     }
00178 
00179 
00180     void sync() {
00181       BOOST_FOREACH( Cmd const & f, _cmd_queue) {
00182         f();
00183       }
00184       _cmd_queue.clear();
00185     }
00186 
00187     bool solve() {
00188       sync();
00189       //BOOST_FOREACH(SMT_Expression e, _assertions) {
00190       //  _solver.assertion ( _eval(e) );
00191       //}
00192       BOOST_FOREACH(SMT_Expression e, _assumptions) {
00193         _solver.assumption ( _eval(e) );
00194       }
00195       _assumptions.clear();
00196       return _solver.solve();
00197     }
00198 
00199     void write_smt(std::ostream &os) {
00200       SMT_ExprContainer v;
00201       std::copy(_assertions.begin(), _assertions.end(),
00202                 std::back_inserter(v));
00203       std::copy(_assumptions.begin(), _assumptions.end(),
00204                 std::back_inserter(v));
00205       _gtx->write_smt(os, v);
00206     }
00207 
00208     void write_smt(std::ostream &os, result_type r) {
00209       SMT_ExprContainer v(1,r);
00210       _gtx->write_smt(os, v);
00211     }
00212 
00213     struct create_x_result : boost::static_visitor<result_wrapper> 
00214     {
00215       template<typename T>
00216       result_type operator() (T) const {
00217         return result_wrapper(boost::logic::indeterminate);
00218       }
00219       
00220       result_type operator() (logic::QF_BV::tag::var_tag const & var) const {
00221         std::vector<boost::logic::tribool> ret ( var.width
00222             ,  boost::logic::indeterminate);
00223         return result_wrapper(ret);
00224       }
00225     };
00226 
00227     result_wrapper read_value(SMT_Expression var)
00228     { 
00229       typename LookupT::const_iterator ite
00230         = _lookup.find(var);
00231       if ( ite != _lookup.end() ) {
00232         return _solver.read_value( _eval( var ) ); 
00233       } else {
00234         return boost::apply_visitor(create_x_result()
00235             , boost::get(boost::vertex_tag, _gtx->graph(), var));
00236       }
00237     }
00238 
00239     template <typename Expr>
00240     SMT_Expression evaluate ( Expr e ) { return ::metaSMT::evaluate(*_gtx, e); }
00241 
00242     SMT_Expression evaluate ( result_type r ) { return r; }
00243 
00244     private:
00245       solver_result  _eval( SMT_Expression e) {
00246         typename LookupT::const_iterator ite = _lookup.find(e);
00247         if ( ite != _lookup.end() ) {
00248           return ite->second;
00249         }
00250 
00251         SMT_Graph const & g = _gtx->graph();
00252 
00253         std::vector<solver_result> args;
00254         // ... fill args
00255         BOOST_FOREACH(SMT_Edge k, out_edges(e,g)) {
00256           args.push_back( _eval(target(k,g)) );
00257         }
00258         
00259         boost::any arg = boost::get(boost::vertex_arg, g, e);
00260         Tag tag        = boost::get(boost::vertex_tag, g, e);
00261 
00262         solver_result ret = boost::apply_visitor( make_callByTag(&_solver, args, arg), tag); 
00263         _lookup.insert( std::make_pair(e, ret) );
00264         return ret;
00265       };
00266 
00267       boost::shared_ptr<Graph_Context> _gtx;
00268       solver_type _solver;
00269       typedef typename std::map<SMT_Expression, solver_result> LookupT;
00270       typedef boost::function0<void> Cmd;
00271       typedef std::list< Cmd > Cmd_Queue;
00272       typedef std::vector<SMT_Expression> SMT_ExprContainer;
00273       LookupT _lookup;
00274       SMT_ExprContainer _assertions;
00275       SMT_ExprContainer _assumptions;
00276       Cmd_Queue _cmd_queue;
00277   };
00278 
00279   namespace features {
00280     template<typename Context, typename Feature>
00281     struct supports< GraphSolver_Context<Context>, Feature>
00282     : supports<Context, Feature>::type {};
00283   }
00284 
00285   template <typename SolverTypes, typename Expr>
00286   void assertion( GraphSolver_Context<SolverTypes> & ctx, Expr const & e ) {
00287     ctx.assertion(  ctx.evaluate(e) );
00288   }
00289 
00290   template <typename SolverTypes, typename Expr>
00291   void assumption( GraphSolver_Context<SolverTypes> & ctx, Expr const & e ) {
00292     ctx.assumption(  ctx.evaluate(e) );
00293   }
00294 
00295   template <typename SolverTypes, typename Expr>
00296   SMT_Expression evaluate( GraphSolver_Context<SolverTypes> & ctx, Expr const & e ) {
00297     return  ctx.evaluate(e) ;
00298   }
00299 
00300   template <typename SolverTypes>
00301   bool solve( GraphSolver_Context<SolverTypes> & ctx) {
00302     return ctx.solve();
00303   }
00304 
00305   template <typename SolverTypes>
00306   void write_smt( GraphSolver_Context<SolverTypes> & ctx, std::ostream &os ) {
00307     ctx.write_smt(os);
00308   }
00309 
00310   template <typename SolverTypes>
00311   result_wrapper 
00312   read_value(
00313       GraphSolver_Context<SolverTypes> & ctx
00314     , logic::QF_BV::bitvector const & var) 
00315   {
00316     return ctx.read_value( evaluate(ctx, var) );
00317   }
00318 
00319   template <typename SolverTypes>
00320   result_wrapper 
00321   read_value(
00322       GraphSolver_Context<SolverTypes> & ctx
00323     , logic::predicate const & var) 
00324   {
00325     return ctx.read_value( evaluate(ctx, var) );
00326   }
00327 
00328   template <typename SolverTypes>
00329   result_wrapper 
00330   read_value(
00331       GraphSolver_Context<SolverTypes> & ctx
00332     , SMT_Expression const & var) 
00333   {
00334     return ctx.read_value( var );
00335   }
00336 
00337 } // namespace metaSMT 
00338 
00339 //  vim: ft=cpp:ts=2:sw=2:expandtab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines