metaSMT git
|
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