metaSMT 2
metaSMT/backend/ClauseWriter.hpp
Go to the documentation of this file.
00001 #pragma once
00002 
00003 #include "../tags/SAT.hpp"
00004 #include "../result_wrapper.hpp"
00005 #include "SAT/model_parser.hpp"
00006 
00007 #include <vector>
00008 #include <exception>
00009 #include <fstream>
00010 #include <iostream>
00011 
00012 #include <boost/foreach.hpp>
00013 #include <boost/format.hpp>
00014 #include <boost/optional.hpp>
00015 #include <boost/algorithm/string/split.hpp>
00016 #include <boost/algorithm/string/classification.hpp>
00017 #include <boost/assign/std/vector.hpp>
00018 #include <boost/lambda/lambda.hpp>
00019 #include <boost/spirit/home/support/iterators/istream_iterator.hpp>
00020  
00021 namespace metaSMT {
00022   namespace solver {
00023     using namespace boost::assign; 
00024 
00025     namespace executable {
00026       struct Glucoser // performs extended resolution 
00027       {
00028         static boost::optional < bool > execute ( std::string const& dimacsFile, std::string const& log, std::string const& err)
00029         {
00030           std::string cmd;
00031           char* env;
00032           if( (env = getenv("GLOCUSER_EXECUTABLE")) ) {
00033             cmd = env;
00034           } else {
00035             cmd = "glucoser";
00036           }
00037           std::string call = boost::str ( boost::format ( "%s %s  %s &> %s" ) % cmd % dimacsFile % log % err ) ;
00038           std::cout << call << std::endl;
00039           int returnValue = system ( call.c_str() ); 
00040           int exitStatus = WEXITSTATUS ( returnValue ); 
00041 
00042           if ( returnValue < 0 )
00043             return boost::optional < bool > (); 
00044 
00045           return boost::optional < bool > ( exitStatus == 10 );  // 10 for satisfiable, 20 for unsatisfiable 
00046         }
00047       }; 
00048 
00049       struct MiniSAT
00050       {
00051         static boost::optional < bool > execute ( std::string const& dimacsFile, std::string const& log, std::string const& err)
00052         {
00053           std::string cmd;
00054           char* env;
00055           if( (env = getenv("MiniSat_EXECUTABLE")) ) {
00056             cmd = env;
00057           } else {
00058             cmd = "minisat";
00059           }
00060           int returnValue = system ( boost::str ( boost::format ( "%s %s  %s &> %s" ) % cmd % dimacsFile % log % err ).c_str() ); 
00061           int exitStatus = WEXITSTATUS ( returnValue ); 
00062 
00063           if ( returnValue < 0 )
00064             return boost::optional < bool > (); 
00065 
00066           return boost::optional < bool > ( exitStatus == 10 );  // 10 for satisfiable, 20 for unsatisfiable 
00067         }
00068       }; 
00069 
00070       struct PicoSAT
00071       {
00072         static boost::optional < bool > execute ( std::string const& dimacsFile, std::string const& log, std::string const& err)
00073         {
00074           std::string cmd;
00075           char* env;
00076           if( (env = getenv("PicoSAT_EXECUTABLE")) ) {
00077             cmd = env;
00078           } else {
00079             cmd = "picosat";
00080           }
00081           int returnValue = system ( boost::str ( boost::format ( "%s %s > %s 2> %s" ) % cmd % dimacsFile % log % err ).c_str() ); 
00082           int exitStatus = WEXITSTATUS ( returnValue ); 
00083 
00084           if ( returnValue < 0 )
00085             return boost::optional < bool > (); 
00086 
00087           bool sat = exitStatus == 10;
00088 
00089           return boost::optional < bool > ( sat  );  // 10 for satisfiable 
00090         }
00091       };
00092 
00093       struct Plingeling
00094       {
00095         static boost::optional < bool > execute ( std::string const& dimacsFile, std::string const& log, std::string const& err)
00096         {
00097           int returnValue = system ( boost::str ( boost::format ( "plingeling -v %s > %s 2> %s" ) % dimacsFile % log % err).c_str() ); 
00098           int exitStatus = WEXITSTATUS ( returnValue ); 
00099 
00100           if ( returnValue < 0 )
00101             return boost::optional < bool > (); 
00102 
00103           bool sat = exitStatus == 10;
00104 
00105           //std::cout << "SAT: " << sat << std::endl;
00106 
00107           return boost::optional < bool > ( sat  );  // 10 for satisfiable 
00108         }
00109       };
00110 
00111     struct PrecoSAT
00112       {
00113         static boost::optional < bool > execute ( std::string const& dimacsFile, std::string const& log, std::string const& err)
00114         {
00115           int returnValue = system ( boost::str ( boost::format ( "precosat -v %s > %s " ) % dimacsFile % err).c_str() ); 
00116           int exitStatus = WEXITSTATUS ( returnValue ); 
00117 
00118           if ( returnValue < 0 )
00119             return boost::optional < bool > (); 
00120 
00121           bool sat = exitStatus == 10;
00122 
00123           //std::cout << "SAT: " << sat << std::endl;
00124 
00125           return boost::optional < bool > ( sat  );  // 10 for satisfiable 
00126         }
00127       };
00128     }
00129 
00130 
00131     template<typename Exec>
00132       struct dimacs_solver
00133       {
00134         dimacs_solver ( std::vector < unsigned >& model ) : model ( model )
00135         {
00136         }
00137 
00138         void readModel ( std::string const& log ) 
00139         {
00140           // open file, disable skipping of whitespace
00141           std::ifstream in(log.c_str());
00142           in.unsetf(std::ios::skipws);
00143 
00144           // wrap istream into iterator
00145           boost::spirit::istream_iterator begin(in);
00146           boost::spirit::istream_iterator end;
00147           SAT::model_grammar<boost::spirit::istream_iterator> p;
00148 
00149           SAT::result_tuple result;
00150           // use iterator to parse file data
00151           bool match = boost::spirit::qi::parse(begin, end, p, result);
00152           assert ( match );
00153 
00154           BOOST_FOREACH ( int val, result.get<1>() )
00155           {
00156             if ( val == 0 ) continue;
00157             unsigned position = abs ( val );
00158             unsigned X = val < 0 ? 0 : 1;
00159             if (position >= model.size()) {
00160               std::cout << model.size() << " " << position << std::endl;
00161             }
00162             assert(model.size() > position);
00163             model[position] = X;
00164           }
00165 
00166           //std::ifstream instream ( log.c_str() );
00167           //
00168           //if ( !instream ) 
00169           //{
00170           //  std::cerr << "Unable to read model." << std::endl;
00171           //  return;
00172           //}
00173 
00174           //std::string line;
00175           //while ( getline ( instream, line  ) )
00176           //{
00177           //  if (line[0] == 'c') continue; // comment
00178           //  if (line[0] == 's') 
00179           //  {
00180           //    if (line.substr (2) != "SATISFIABLE")
00181           //    {
00182           //      std::cerr << "Expected the instance is satisfiable." << std::endl;
00183           //      return;
00184           //    }
00185           //  }
00186           //  if (line[0] == 'v')
00187           //  {
00188           //    std::vector < std::string > pModel;
00189           //    std::string part = line.substr ( 2 ); 
00190           //    boost::split ( pModel, part, boost::is_any_of (" "));
00191           //    BOOST_FOREACH ( std::string const& str, pModel )
00192           //    {
00193           //      int val = atoi ( str.c_str() );
00194           //      if ( val == 0 ) continue;
00195           //      unsigned size = abs ( val );
00196           //      unsigned X = val < 0 ? 0 : 1;
00197           //      if (size >= model.size()) {
00198           //        std::cout << model.size() << " " << size << std::endl;
00199           //      }
00200           //      assert(model.size() > size);
00201           //      model[size] = X;
00202           //    }
00203           //  }
00204           //}
00205         }
00206 
00207         boost::optional < bool > solve ( std::string const& filename )
00208         {
00209           std::string log = "solver.log";
00210           std::string err = "solver.err"; 
00211 
00212           boost::optional < bool > result = Exec::execute ( filename, log, err ); 
00213 
00214           if ( result )
00215           {
00216             //std::cout << "SAT? " << *result << std::endl;
00217             if ( *result )
00218             {
00219               readModel ( log ); 
00220               return true;
00221             }
00222             else
00223               return false;
00224           }
00225           else
00226             return result; 
00227         }
00228 
00229         private:
00230         std::vector < unsigned >& model;
00231       }; 
00232 
00233     template<typename Solver>
00234       class ClauseWriter
00235       {
00236         public:
00237           typedef std::vector < int > clause_vec;
00238           typedef std::vector < clause_vec > clause_db; 
00239 
00240         public:
00241           ClauseWriter () : vars (0)
00242         {
00243         }
00244 
00245           int toLit ( SAT::tag::lit_tag lit )
00246           {
00247             int l = lit.id; 
00248 
00249             if ( unsigned (abs ( l ) ) > vars )
00250               vars = abs ( l ); 
00251 
00252             return l;
00253           }
00254 
00255           void clause ( std::vector < SAT::tag::lit_tag > const& fromClause )
00256           {
00257             clause_vec cls;
00258             BOOST_FOREACH ( SAT::tag::lit_tag const& lit, fromClause )
00259               cls += toLit ( lit );
00260             db += cls;
00261           }
00262 
00263           void assertion ( SAT::tag::lit_tag lit )
00264           {
00265             clause_vec cls;
00266             cls += toLit ( lit ); 
00267             db.push_back ( cls ); 
00268           }
00269 
00270           void assumption ( SAT::tag::lit_tag lit )
00271           {
00272             clause_vec cls;
00273             cls += toLit ( lit ); 
00274             assumptions.push_back ( cls ); 
00275           }
00276 
00277           void write_header ( std::ostream& stream )
00278           {
00279             stream << "p cnf " << vars << " " << db.size() + assumptions.size() << std::endl;
00280           }
00281 
00282           void write_cnf ( std::string const& filename )
00283           {
00284             std::ofstream cnf ( filename.c_str() ) ;
00285             write_header ( cnf ); 
00286 
00287             BOOST_FOREACH ( clause_vec const& cls, db )
00288             {
00289               std::for_each (cls.begin(), cls.end(),
00290                   cnf << boost::lambda::free1 << " "); 
00291               cnf << "0" << std::endl;
00292             }
00293 
00294             BOOST_FOREACH ( clause_vec const& cls, assumptions )
00295             {
00296               std::for_each (cls.begin(), cls.end(),
00297                   cnf << boost::lambda::free1 << " "); 
00298               cnf << "0" << std::endl;
00299             }
00300           }
00301 
00302           bool solve ( )
00303           {
00304             std::string name = "clause-writer.cnf"; 
00305             write_cnf ( name ); 
00306 
00307             //system ("cnf2aig clause-writer.cnf clause-writer.aig");
00308             //system ("optimize_aig.sh clause-writer.aig ");
00309             //system ("aigtocnf clause-writer.aig clause-writer.cnf");
00310 
00311             assumptions.clear(); 
00312 
00313             model.resize ( vars+1, 0 ); 
00314 
00315             Solver solver ( model );
00316             boost::optional < bool > result = solver.solve ( name ); 
00317 
00318             assert ( result );
00319 
00320             if ( *result == false ) return false;
00321 
00322             return true;
00323           }
00324 
00325           result_wrapper read_value ( SAT::tag::lit_tag lit ) 
00326           {
00327             assert ( !model.empty() ); 
00328             assert ( int(model.size()) > toLit ( lit ) ); 
00329 
00330             switch ( model[ abs ( toLit ( lit ) ) ] )
00331             {
00332               case 1:
00333                 return result_wrapper ( '1' );
00334               case 0:
00335                 return result_wrapper ( '0' );
00336               default:
00337                 assert ( false ); 
00338                 return result_wrapper ( 'X' );
00339 
00340             }
00341           }
00342 
00343         private:
00344           clause_db     db; 
00345           clause_db     assumptions;
00346           unsigned      vars;
00347           std::vector < unsigned > model; 
00348       };
00349   } /* solver */
00350 } /* metaSMT */
00351 // vim: ts=2 sw=2 et
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines