metaSMT 2
metaSMT/backend/Boolector.hpp
Go to the documentation of this file.
00001 #pragma once
00002 
00003 #include "../tags/QF_BV.hpp"
00004 #include "../tags/Array.hpp"
00005 #include "../result_wrapper.hpp"
00006 
00007 extern "C" {
00008 #include <boolector.h>
00009 }
00010 
00011 #include <iostream>
00012 #include <boost/mpl/map/map40.hpp>
00013 #include <boost/any.hpp>
00014 #include <boost/tuple/tuple.hpp>
00015 #include <list>
00016 
00017 namespace metaSMT {
00018   namespace solver {
00019 
00020     namespace predtags = ::metaSMT::logic::tag;
00021     namespace bvtags = ::metaSMT::logic::QF_BV::tag;
00022     namespace arraytags = ::metaSMT::logic::Array::tag;
00023 
00024 
00030     class Boolector {
00031 
00032       struct BoolectorAssertion : public std::runtime_error {
00033         BoolectorAssertion(const char* what)
00034           : std::runtime_error(what) {}
00035       };
00036 
00037       static void _boolector_error(int ec) {
00038         throw BoolectorAssertion("internal error in boolector");
00039       }
00040 
00041       public:
00042         typedef BtorExp* result_type;
00043 
00044         result_type ptr(BtorExp* expr) {
00045           _exprs.push_back(expr);
00046           return expr;
00047         }
00048       
00049         Boolector ()
00050         {
00051           _btor = boolector_new();
00052           boolector_enable_model_gen(_btor);
00053           boolector_enable_inc_usage(_btor);
00054           boolector_abort_function(&Boolector::_boolector_error);
00055         }
00056 
00057         ~Boolector() {
00058           for( std::list<BtorExp*>::iterator ite = _exprs.begin(); ite!=_exprs.end(); ++ite)
00059           {
00060             boolector_release(_btor, *ite);
00061           }
00062           boolector_delete(_btor);
00063         }
00064 
00065         void assertion( result_type e ) {
00066           boolector_assert(_btor, e);
00067         }
00068 
00069         void assumption( result_type e ) {
00070           boolector_assume(_btor, e);
00071         }
00072 
00073         bool solve() {
00074           return boolector_sat(_btor) == BOOLECTOR_SAT;
00075         }
00076 
00077         result_wrapper read_value(result_type var)
00078         {
00079           char* value = boolector_bv_assignment(_btor, var);
00080           std::string s(value);
00081           boolector_free_bv_assignment(_btor, value);
00082           return result_wrapper(s);
00083         }
00084 
00085         result_type operator() (predtags::var_tag const & var, boost::any args )
00086         {
00087           return ptr(boolector_var(_btor, 1, NULL));
00088         }
00089 
00090         result_type operator() (predtags::false_tag , boost::any arg ) {
00091           return ptr(boolector_false(_btor));
00092         }
00093 
00094         result_type operator() (predtags::true_tag , boost::any arg ) {
00095           return ptr(boolector_true(_btor));
00096         }
00097 
00098         result_type operator() (predtags::not_tag , result_type a) {
00099           return ptr(boolector_not(_btor, a) );
00100         }
00101 
00102 
00103         result_type operator() (bvtags::var_tag const & var, boost::any args )
00104         {
00105           assert ( var.width != 0 );
00106           return ptr(boolector_var(_btor, var.width, NULL));
00107         }
00108 
00109         result_type operator() (bvtags::bit0_tag , boost::any arg ) {
00110           return ptr(boolector_false(_btor));
00111         }
00112 
00113         result_type operator() (bvtags::bit1_tag , boost::any arg ) {
00114           return ptr(boolector_true(_btor));
00115         }
00116 
00117         result_type operator() (bvtags::bvuint_tag , boost::any arg ) {
00118           typedef boost::tuple<unsigned long, unsigned long> P;
00119           P p = boost::any_cast<P>(arg);
00120           //std::cout << "bvuint "<< p << std::endl;
00121           unsigned value = boost::get<0>(p);
00122           unsigned width = boost::get<1>(p);
00123           return ptr(boolector_unsigned_int(_btor, value , width ));
00124         }
00125 
00126         result_type operator() (bvtags::bvsint_tag , boost::any arg ) {
00127           typedef boost::tuple<long, unsigned long> P;
00128           P p = boost::any_cast<P>(arg);
00129           return ptr(boolector_int(_btor, boost::get<0>(p), boost::get<1>(p)));
00130         }
00131 
00132         result_type operator() (bvtags::bvbin_tag , boost::any arg ) {
00133           std::string val = boost::any_cast<std::string>(arg);
00134           return ptr(boolector_const(_btor, val.c_str()));
00135         }
00136 
00137         result_type operator() (bvtags::bvhex_tag , boost::any arg ) {
00138           std::string hex = boost::any_cast<std::string>(arg);
00139           std::string bin (hex.size()*4,'\0');
00140 
00141           for (unsigned i = 0; i < hex.size(); ++i) {
00142             switch ( tolower(hex[i]) ) {
00143               case '0':
00144                 bin.replace(4*i,4, "0000");
00145                 break;
00146               case '1':
00147                 bin.replace(4*i,4, "0001");
00148                 break;
00149               case '2':
00150                 bin.replace(4*i,4, "0010");
00151                 break;
00152               case '3':
00153                 bin.replace(4*i,4, "0011");
00154                 break;
00155               case '4':
00156                 bin.replace(4*i,4, "0100");
00157                 break;
00158               case '5':
00159                 bin.replace(4*i,4, "0101");
00160                 break;
00161               case '6':
00162                 bin.replace(4*i,4, "0110");
00163                 break;
00164               case '7':
00165                 bin.replace(4*i,4, "0111");
00166                 break;
00167               case '8':
00168                 bin.replace(4*i,4, "1000");
00169                 break;
00170               case '9':
00171                 bin.replace(4*i,4, "1001");
00172                 break;
00173               case 'a':
00174                 bin.replace(4*i,4, "1010");
00175                 break;
00176               case 'b':
00177                 bin.replace(4*i,4, "1011");
00178                 break;
00179               case 'c':
00180                 bin.replace(4*i,4, "1100");
00181                 break;
00182               case 'd':
00183                 bin.replace(4*i,4, "1101");
00184                 break;
00185               case 'e':
00186                 bin.replace(4*i,4, "1110");
00187                 break;
00188               case 'f':
00189                 bin.replace(4*i,4, "1111");
00190                 break;
00191             }
00192           }
00193           //std::cout << bin << std::endl;
00194           return ptr(boolector_const(_btor, bin.c_str()));
00195         }
00196 
00197         result_type operator() (bvtags::bvnot_tag , result_type a ) {
00198           return ptr(boolector_not(_btor, a));
00199         }
00200 
00201         result_type operator() (bvtags::bvneg_tag , result_type a ) {
00202           return ptr(boolector_neg(_btor, a));
00203         }
00204 
00205         result_type operator() (bvtags::extract_tag const &
00206             , unsigned long upper, unsigned long lower
00207             , result_type e)
00208         {
00209           return ptr(boolector_slice(_btor, e, upper, lower));
00210         }
00211 
00212         result_type operator() (bvtags::zero_extend_tag const &
00213             , unsigned long width
00214             , result_type e)
00215         {
00216           return ptr(boolector_uext(_btor, e, width));
00217         }
00218 
00219         result_type operator() (bvtags::sign_extend_tag const &
00220             , unsigned long width
00221             , result_type e)
00222         {
00223           return ptr(boolector_sext(_btor, e, width));
00224         }
00225 
00226         result_type operator() (arraytags::array_var_tag const & var
00227                                 , boost::any args )
00228         {
00229           return ptr(boolector_array(_btor, var.elem_width, var.index_width, NULL));
00230         }
00231 
00232         result_type operator() (arraytags::select_tag const &
00233                                 , result_type array
00234                                 , result_type index) {
00235           return ptr(boolector_read(_btor, array, index));
00236         }
00237 
00238         result_type operator() (arraytags::store_tag const &
00239                                 , result_type array
00240                                 , result_type index
00241                                 , result_type value) {
00242           return ptr(boolector_write(_btor, array, index, value));
00243         }
00244 
00245         result_type operator() (predtags::ite_tag tag, result_type a, result_type b, result_type c) {
00246           return ptr(boolector_cond(_btor, a, b, c));
00247         }
00248 
00250         // Fallback operators //
00252 
00253         template <typename TagT>
00254         result_type operator() (TagT tag, boost::any args ) {
00255           return ptr(boolector_false(_btor));
00256         }
00257 
00258 
00259         template <typename TagT>
00260         result_type operator() (TagT tag, result_type a ) {
00261           return ptr(boolector_false(_btor));
00262         }
00263 
00264         template< BtorExp* (*FN) (Btor*, BtorExp*, BtorExp*) >
00265         struct Btor_F2 {
00266           static BtorExp* exec(Btor* b , BtorExp* x, BtorExp* y)
00267           { return (*FN)(b,x,y);}
00268         };
00269 
00270         template <typename TagT>
00271         result_type operator() (TagT tag, result_type a, result_type b) {
00272           namespace mpl = boost::mpl;
00273 
00274           typedef mpl::map35<
00275           // binary Logic tags
00276             mpl::pair<predtags::equal_tag,   Btor_F2<&boolector_eq> >
00277           , mpl::pair<predtags::nequal_tag,  Btor_F2<&boolector_ne> >
00278           , mpl::pair<predtags::and_tag,     Btor_F2<&boolector_and> >
00279           , mpl::pair<predtags::nand_tag,    Btor_F2<&boolector_nand> >
00280           , mpl::pair<predtags::or_tag,      Btor_F2<&boolector_or> >
00281           , mpl::pair<predtags::nor_tag,     Btor_F2<&boolector_nor> >
00282           , mpl::pair<predtags::xor_tag,     Btor_F2<&boolector_xor> >
00283           , mpl::pair<predtags::xnor_tag,    Btor_F2<&boolector_xnor> >
00284           , mpl::pair<predtags::implies_tag, Btor_F2<&boolector_implies> >
00285           // binary QF_BV tags
00286           , mpl::pair<bvtags::bvand_tag,     Btor_F2<&boolector_and> >
00287           , mpl::pair<bvtags::bvnand_tag,    Btor_F2<&boolector_nand> >
00288           , mpl::pair<bvtags::bvor_tag,      Btor_F2<&boolector_or> >
00289           , mpl::pair<bvtags::bvnor_tag,     Btor_F2<&boolector_nor> >
00290           , mpl::pair<bvtags::bvxor_tag,     Btor_F2<&boolector_xor> >
00291           , mpl::pair<bvtags::bvxnor_tag,    Btor_F2<&boolector_xnor> >
00292           , mpl::pair<bvtags::bvadd_tag,     Btor_F2<&boolector_add> >
00293           , mpl::pair<bvtags::bvsub_tag,     Btor_F2<&boolector_sub> >
00294           , mpl::pair<bvtags::bvmul_tag,     Btor_F2<&boolector_mul> >
00295           , mpl::pair<bvtags::bvudiv_tag,    Btor_F2<&boolector_udiv> >
00296           , mpl::pair<bvtags::bvurem_tag,    Btor_F2<&boolector_urem> >
00297           , mpl::pair<bvtags::bvsdiv_tag,    Btor_F2<&boolector_sdiv> >
00298           , mpl::pair<bvtags::bvsrem_tag,    Btor_F2<&boolector_srem> >
00299           , mpl::pair<bvtags::bvcomp_tag,    Btor_F2<&boolector_eq > >
00300           , mpl::pair<bvtags::bvslt_tag,     Btor_F2<&boolector_slt > >
00301           , mpl::pair<bvtags::bvsle_tag,     Btor_F2<&boolector_slte > >
00302           , mpl::pair<bvtags::bvsgt_tag,     Btor_F2<&boolector_sgt > >
00303           , mpl::pair<bvtags::bvsge_tag,     Btor_F2<&boolector_sgte > >
00304           , mpl::pair<bvtags::bvult_tag,     Btor_F2<&boolector_ult > >
00305           , mpl::pair<bvtags::bvule_tag,     Btor_F2<&boolector_ulte > >
00306           , mpl::pair<bvtags::bvugt_tag,     Btor_F2<&boolector_ugt > >
00307           , mpl::pair<bvtags::bvuge_tag,     Btor_F2<&boolector_ugte > >
00308           , mpl::pair<bvtags::concat_tag,    Btor_F2<&boolector_concat > >
00309           , mpl::pair<bvtags::bvshl_tag,     Btor_F2<&boolector_sll > >
00310           , mpl::pair<bvtags::bvshr_tag,     Btor_F2<&boolector_srl > >
00311           , mpl::pair<bvtags::bvashr_tag,    Btor_F2<&boolector_sra > >
00312           > Opcode_Map;
00313 
00314           typedef
00315             typename mpl::has_key< Opcode_Map, TagT >::type
00316           _has_key;
00317 
00318           if (_has_key::value ) {
00319           typedef typename mpl::eval_if<
00320             _has_key
00321             , mpl::at< Opcode_Map, TagT >
00322             , mpl::identity< Btor_F2<boolector_and> >
00323             >::type opcode;
00324           return ptr(opcode::exec(_btor, a, b));
00325           } else {
00326             std::cout << "unknown operator: " << tag << std::endl;
00327 
00328             assert(false && "unknown operator");
00329             return ptr(boolector_false(_btor));
00330           }
00331         }
00332 
00333 
00334         template <typename TagT>
00335         result_type operator() (TagT tag, result_type a, result_type b, result_type c) {
00336           return ptr(boolector_false(_btor));
00337         }
00338 
00339 
00340         /* pseudo command */
00341         void command ( Boolector const & ) { };
00342 
00343       private:
00344         Btor *_btor;
00345         std::list<BtorExp*> _exprs;
00346     };
00347 
00350   } // namespace solver
00351 } // namespace metaSMT
00352 
00353 //  vim: ft=cpp:ts=2:sw=2:expandtab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines