metaSMT 2
metaSMT/backend/mathsat_Context.hpp
Go to the documentation of this file.
00001 #pragma once
00002 
00003 #include "../tags/QF_BV.hpp"
00004 #include "../result_wrapper.hpp"
00005 
00006 #include <mathsat.h>
00007 
00008 #include <iostream>
00009 #include <boost/mpl/map.hpp>
00010 #include <boost/tuple/tuple_io.hpp>
00011 #include <boost/lexical_cast.hpp>
00012 
00013 
00014 namespace metaSMT {
00015   namespace solver {
00016 
00017     namespace predtags = ::metaSMT::logic::tag;
00018     namespace bvtags = ::metaSMT::logic::QF_BV::tag;
00019   
00020     class mathsat_Context {
00021 
00022       public:
00023         typedef msat_term result_type;
00024 
00025         mathsat_Context () 
00026         : env_( msat_create_env() )
00027         , assumptions_( msat_make_true(env_) )
00028         {
00029           msat_add_theory(env_, MSAT_WORD);
00030         }
00031 
00032         ~mathsat_Context() {
00033           msat_destroy_env(env_);
00034         }
00035 
00036         void assertion( result_type e ) { 
00037           //char * p = msat_to_msat(env_, e);
00038           //printf(p);
00039           //free(p);
00040           msat_assert_formula(env_, e);
00041         }
00042 
00043         void assumption( result_type e ) { 
00044           //char * p = msat_to_msat(env_, assumptions_);
00045           //printf(p);
00046           //free(p);
00047           assumptions_ = msat_make_and(env_, e, assumptions_);
00048         }
00049         
00050         bool solve() {
00051           msat_pop_backtrack_point(env_);
00052           msat_push_backtrack_point(env_);
00053           msat_assert_formula(env_, assumptions_);
00054           bool ret = msat_solve(env_) == MSAT_SAT;
00055           assumptions_ = msat_make_true(env_);
00056           return ret;
00057         }
00058 
00059         result_wrapper read_value(result_type var)
00060         { 
00061           result_wrapper ret("X");
00062           msat_term t = msat_get_model_value(env_, var);
00063           char* value = msat_to_msat(env_, t);
00064           if( strcmp(value, "FORMULA true\n" ) == 0 ) {
00065             //printf("formular true\n");
00066             return result_wrapper(true);
00067           } else if( strcmp(value, "FORMULA false\n" ) == 0 ) {
00068             //printf("formular false\n");
00069             return result_wrapper(false);
00070           } else if( strncmp(value, "FORMULA (0d", 11) == 0 ) {
00071             //printf("formular d\n");
00072             char* beg = value+11;
00073             while (*beg && *beg != '_') ++beg;
00074             std::string widths (value+11, beg);
00075             ++beg;
00076             assert(*beg);
00077             char* end = beg+1;
00078             while (*end && *end != ')') ++end;
00079             assert(*end);
00080             std::string nums(beg, end);
00081             long width = boost::lexical_cast<long>(widths);
00082             long num = boost::lexical_cast<long>(nums);
00083 
00084             std::vector<bool> v (width);
00085             std::vector<bool>::iterator ite =v.begin();
00086             while (num !=0 ) {
00087               *ite = (num & 1);
00088               num>>=1;
00089               ++ite;
00090             }
00091             ret = result_wrapper(v);
00092 
00093             //printf("<%s> %s %s\n", value, widths.c_str(), nums.c_str());
00094           }
00095           //std::cout << value << ": " << ret << std::endl;
00096           free(value);
00097           return ret;
00098         }
00099 
00100         result_type operator() (predtags::var_tag const & var, boost::any args )
00101         {
00102           char buf[1024];
00103           sprintf(buf, "var%d", var.id);
00104           
00105           msat_decl decl = msat_declare_variable( env_, buf, MSAT_BOOL);
00106           return msat_make_variable(env_, decl);
00107         }
00108 
00109         result_type operator() (predtags::false_tag , boost::any arg ) {
00110           return msat_make_false(env_);
00111         }
00112 
00113         result_type operator() (predtags::true_tag , boost::any arg ) {
00114           return msat_make_true(env_);
00115         }
00116 
00117         result_type operator() (predtags::not_tag , result_type a) {
00118           return msat_make_not(env_, a) ;
00119         }
00120 
00121 
00122         result_type operator() (predtags::equal_tag , result_type a, result_type b) {
00123           return msat_make_equal(env_, a, b) ;
00124         }
00125 
00126         result_type operator() (predtags::nequal_tag , result_type a, result_type b) {
00127           return msat_make_not(env_, msat_make_equal(env_, a, b) ) ;
00128         }
00129 
00130         result_type operator() (predtags::and_tag , result_type a, result_type b) {
00131           return msat_make_and(env_, a, b ) ;
00132         }
00133 
00134         result_type operator() (predtags::xor_tag , result_type a, result_type b) {
00135           return msat_make_xor(env_, a, b ) ;
00136         }
00137         
00138         result_type operator() (predtags::implies_tag , result_type a, result_type b) {
00139           return msat_make_implies(env_, a, b ) ;
00140         }
00141 
00142         result_type operator() (predtags::or_tag , result_type a, result_type b) {
00143           return msat_make_or(env_, a, b ) ;
00144         }
00145 
00146         result_type operator() (bvtags::var_tag const & var, boost::any args )
00147         {
00148           char buf[1024];
00149           sprintf(buf, "var%d", var.id);
00150           
00151           msat_decl decl = msat_declare_variable( env_, buf, MSAT_BV+var.width);
00152           return msat_make_variable(env_, decl);
00153         }
00154 
00155         result_type operator() (bvtags::bit0_tag , boost::any arg ) {
00156           return msat_make_number(env_, "0d1_0");
00157         }
00158 
00159         result_type operator() (bvtags::bit1_tag , boost::any arg ) {
00160           return msat_make_number(env_, "0d1_1");
00161         }
00162         result_type operator() (bvtags::bvhex_tag , boost::any arg ) {
00163           std::string hex = boost::any_cast<std::string>(arg);
00164           char buf[4096];
00165           sprintf(buf, "0h%u_%s", (unsigned)hex.size()*4, hex.c_str());
00166           return msat_make_number(env_, buf);
00167         }
00168 
00169         result_type operator() (bvtags::bvbin_tag , boost::any arg ) {
00170           std::string bin = boost::any_cast<std::string>(arg);
00171           char buf[4096];
00172           sprintf(buf, "0b%u_%s", (unsigned)bin.size(), bin.c_str());
00173           return msat_make_number(env_, buf);
00174         }
00175         result_type operator() (bvtags::bvuint_tag , boost::any arg ) {
00176           typedef boost::tuple<unsigned long, unsigned long> P;
00177           P p = boost::any_cast<P>(arg);
00178           //std::cout << "bvuint "<< p << std::endl;
00179           unsigned value = boost::get<0>(p);
00180           unsigned width = boost::get<1>(p);
00181           char buf[4096];
00182           sprintf(buf, "0d%u_%u", width, value);
00183           return msat_make_number(env_, buf);
00184         }
00185 
00186 
00187         //result_type operator() (bvtags::bvsint_tag , boost::any arg ) {
00188         //  typedef boost::tuple<long, unsigned long> P;
00189         //  P p = boost::any_cast<P>(arg);
00190         //  return boolector_int(_btor, boost::get<0>(p), boost::get<1>(p));
00191         //}
00192 
00193         result_type operator() (bvtags::bvnot_tag , result_type a ) {
00194           return msat_make_bv_not(env_, a);
00195         }
00196 
00197         result_type operator() (bvtags::bvneg_tag , result_type a ) {
00198           return msat_make_bv_neg(env_, a);
00199         }
00200 
00202         // Fallback operators //
00204 
00205         template <typename TagT>
00206         result_type operator() (TagT tag, boost::any args ) {
00207           return msat_make_false(env_);
00208         }
00209 
00210 
00211         template <typename TagT>
00212         result_type operator() (TagT tag, result_type a ) {
00213           return msat_make_false(env_);
00214         }
00215 
00216         template< result_type (*FN) (msat_env, result_type, result_type) > 
00217         struct F2 {
00218           static result_type exec(msat_env e , result_type x, result_type y) 
00219           { return (*FN)(e,x,y);}
00220         };
00221 
00222         result_type operator() (bvtags::bvnor_tag , result_type a, result_type b) {
00223           return msat_make_bv_not(env_, msat_make_bv_or(env_,a,b));
00224         }
00225 
00226         result_type operator() (bvtags::bvnand_tag , result_type a, result_type b) {
00227           return msat_make_bv_not(env_, msat_make_bv_and(env_,a,b));
00228         }
00229 
00230         result_type operator() (bvtags::bvxnor_tag , result_type a, result_type b) {
00231           return msat_make_bv_not(env_, msat_make_bv_xor(env_,a,b));
00232         }
00233 
00234         result_type operator() (bvtags::bvcomp_tag , result_type a, result_type b) {
00235           return msat_make_ite(env_, 
00236               msat_make_equal(env_,a,b)
00237             , msat_make_number(env_, "0b1_1")
00238             , msat_make_number(env_, "0b1_0")
00239           );
00240         }
00241 
00242         template <typename TagT>
00243         result_type operator() (TagT tag, result_type a, result_type b) {
00244           using namespace boost::mpl;
00245 
00246           typedef map<
00247             pair<bvtags::bvand_tag,     F2<&msat_make_bv_and> >
00248           , pair<bvtags::bvor_tag,      F2<&msat_make_bv_or > >
00249           , pair<bvtags::bvxor_tag,     F2<&msat_make_bv_xor> >
00250           , pair<bvtags::bvadd_tag,     F2<&msat_make_bv_plus> >
00251           , pair<bvtags::bvsub_tag,     F2<&msat_make_bv_minus> >
00252           , pair<bvtags::bvmul_tag,     F2<&msat_make_bv_times> >
00253           , pair<bvtags::bvslt_tag,     F2<&msat_make_bv_slt> >
00254           > Opcode_Map;
00255 
00256           typedef 
00257             typename has_key< Opcode_Map, TagT >::type
00258           _has_key;
00259 
00260           if (_has_key::value ) {
00261           typedef typename eval_if<
00262             _has_key
00263             , at< Opcode_Map, TagT >
00264             , identity< F2<msat_make_and> >
00265             >::type opcode;
00266           return opcode::exec(env_, a, b);
00267           } else {
00268             std::cout << "unknown operator: " << tag << std::endl;
00269 
00270             assert(false && "unknown operator");
00271             return msat_make_false(env_);
00272           }
00273         }
00274 
00275 
00276         template <typename TagT>
00277         result_type operator() (TagT tag, result_type a, result_type b, result_type c) {
00278           return msat_make_false(env_);
00279         }
00280 
00281       private:
00282         msat_env env_;
00283         msat_term assumptions_;
00284     };
00285         
00286   } // namespace solver
00287 } // namespace metaSMT
00288 
00289 //  vim: ft=cpp:ts=2:sw=2:expandtab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines