metaSMT git

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