00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "clasp_app.h"
00021 #include <clasp/parser.h>
00022 #include <clasp/solver.h>
00023 #include <clasp/dependency_graph.h>
00024 #include <iostream>
00025 #include <fstream>
00026 #include <cstdlib>
00027 #include <climits>
00028 #ifdef _WIN32
00029 #define snprintf _snprintf
00030 #pragma warning (disable : 4996)
00031 #endif
00032 #include <clasp/clause.h>
00033 namespace Clasp {
00035
00037 inline std::ostream& operator << (std::ostream& os, Literal l) {
00038 if (l.sign()) os << '-';
00039 os << l.var();
00040 return os;
00041 }
00042 inline std::istream& operator >> (std::istream& in, Literal& l) {
00043 int i;
00044 if (in >> i) {
00045 l = Literal(i >= 0 ? Var(i) : Var(-i), i < 0);
00046 }
00047 return in;
00048 }
00049 inline bool isStdIn(const std::string& in) { return in == "-" || in == "stdin"; }
00050 inline bool isStdOut(const std::string& out){ return out == "-" || out == "stdout"; }
00052
00054 namespace Cli {
00055 ClaspAppOptions::ClaspAppOptions() : outf(0), ifs(' '), hideAux(false), onlyPre(false), printPort(false), outLbd(Activity::MAX_LBD), inLbd(Activity::MAX_LBD) {
00056 quiet[0] = quiet[1] = quiet[2] = static_cast<uint8>(UCHAR_MAX);
00057 }
00058 void ClaspAppOptions::initOptions(ProgramOptions::OptionContext& root) {
00059 using namespace ProgramOptions;
00060 OptionGroup basic("Basic Options");
00061 basic.addOptions()
00062 ("quiet,q" , notify(this, &ClaspAppOptions::mappedOpts)->implicit("2,2,2")->arg("<levels>"),
00063 "Configure printing of models, costs, and calls\n"
00064 " %A: <mod>[,<opt>][,<call>]\n"
00065 " <mod> : print {0=all|1=last|2=no} models\n"
00066 " <cost>: print {0=all|1=last|2=no} optimize values [<m>]\n"
00067 " <call>: print {0=all|1=last|2=no} call steps [2]")
00068 ("pre" , flag(onlyPre), "Run preprocessing and exit")
00069 ("print-portfolio" , flag(printPort), "Print default portfolio and exit")
00070 ("outf,@1", storeTo(outf)->arg("<n>"), "Use {0=default|1=competition|2=JSON|3=no} output")
00071 ("out-atomf,@1" , storeTo(outAtom), "Set atom format string (<Pre>?%%s<Post>?)")
00072 ("out-ifs,@1" , notify(this, &ClaspAppOptions::mappedOpts), "Set internal field separator")
00073 ("out-hide-aux,@1", flag(hideAux), "Hide auxiliary atoms in answers")
00074 ("lemma-out,@1" , storeTo(lemmaOut)->arg("<file>"), "Write learnt lemmas to %A on exit")
00075 ("lemma-out-lbd,@1",notify(this, &ClaspAppOptions::mappedOpts)->arg("<n>"), "Only write lemmas with lbd <= %A")
00076 ("lemma-in,@1" , storeTo(lemmaIn)->arg("<file>"), "Read additional lemmas from %A")
00077 ("lemma-in-lbd,@1", notify(this, &ClaspAppOptions::mappedOpts)->arg("<n>"), "Initialize lbd of additional lemmas to <n>")
00078 ("hcc-out,@1", storeTo(hccOut)->arg("<file>"), "Write non-hcf programs to %A.#scc")
00079 ("file,f,@2", storeTo(input)->composing(), "Input files")
00080 ;
00081 root.add(basic);
00082 }
00083 bool ClaspAppOptions::mappedOpts(ClaspAppOptions* this_, const std::string& name, const std::string& value) {
00084 uint32 x;
00085 if (name == "quiet") {
00086 const char* err = 0;
00087 uint32 q[3]= {uint32(UCHAR_MAX),uint32(UCHAR_MAX),uint32(UCHAR_MAX)};
00088 int parsed = bk_lib::xconvert(value.c_str(), q, &err, 3);
00089 for (int i = 0; i != parsed; ++i) { this_->quiet[i] = static_cast<uint8>(q[i]); }
00090 return parsed && *err == 0;
00091 }
00092 else if (name == "out-ifs") {
00093 if (value.empty() || value.size() > 2) { return false;}
00094 if (value.size() == 1) { this_->ifs = value[0]; return true; }
00095 if (value[1] == 't') { this_->ifs = '\t'; return true; }
00096 if (value[1] == 'n') { this_->ifs = '\n'; return true; }
00097 if (value[1] == 'v') { this_->ifs = '\v'; return true; }
00098 if (value[1] == '\\') { this_->ifs = '\\'; return true; }
00099 }
00100 else if (name.find("-lbd") != std::string::npos && bk_lib::string_cast(value, x) && x < Activity::MAX_LBD) {
00101 if (name == "lemma-out-lbd") { this_->outLbd = (uint8)x; return true; }
00102 else if (name == "lemma-in-lbd") { this_->inLbd = (uint8)x; return true; }
00103 }
00104 return false;
00105 }
00106 bool ClaspAppOptions::validateOptions(const ProgramOptions::ParsedOptions&) {
00107 if (quiet[1] == static_cast<uint8>(UCHAR_MAX)) { quiet[1] = quiet[0]; }
00108 return true;
00109 }
00111
00113 ClaspAppBase::ClaspAppBase() { }
00114 ClaspAppBase::~ClaspAppBase(){ }
00115 const int* ClaspAppBase::getSignals() const {
00116 static const int signals[] = {
00117 SIGINT, SIGTERM
00118 #if !defined (_WIN32)
00119 , SIGUSR1, SIGUSR2, SIGQUIT, SIGHUP, SIGXCPU, SIGXFSZ
00120 #endif
00121 , 0};
00122 return signals;
00123 }
00124 bool ClaspAppBase::parsePositional(const std::string& t, std::string& out) {
00125 int num;
00126 if (bk_lib::string_cast(t, num)) { out = "number"; }
00127 else { out = "file"; }
00128 return true;
00129 }
00130 void ClaspAppBase::initOptions(ProgramOptions::OptionContext& root) {
00131 claspConfig_.addOptions(root);
00132 claspAppOpts_.initOptions(root);
00133 root.find("verbose")->get()->value()->defaultsTo("1");
00134 }
00135
00136 void ClaspAppBase::validateOptions(const ProgramOptions::OptionContext&, const ProgramOptions::ParsedOptions& parsed, const ProgramOptions::ParsedValues& values) {
00137 if (claspAppOpts_.printPort) {
00138 printTemplate();
00139 exit(E_UNKNOWN);
00140 }
00141 if (!claspAppOpts_.validateOptions(parsed) || !claspConfig_.finalize(parsed, getProblemType(), true)) {
00142 error("command-line error!");
00143 exit(E_NO_RUN);
00144 }
00145 ClaspAppOptions& app = claspAppOpts_;
00146 if (!app.lemmaOut.empty() && !isStdOut(app.lemmaOut)) {
00147 if (std::find(app.input.begin(), app.input.end(), app.lemmaOut) != app.input.end() || app.lemmaIn == app.lemmaOut) {
00148 error("'lemma-out': cowardly refusing to overwrite input file!");
00149 exit(E_NO_RUN);
00150 }
00151 }
00152 if (!app.lemmaIn.empty() && !isStdIn(app.lemmaIn) && !std::ifstream(app.lemmaIn.c_str()).is_open()) {
00153 error("'lemma-in': could not open file!");
00154 exit(E_NO_RUN);
00155 }
00156 for (std::size_t i = 1; i < app.input.size(); ++i) {
00157 if (!isStdIn(app.input[i]) && !std::ifstream(app.input[i].c_str()).is_open()) {
00158 error(clasp_format_error("'%s': could not open input file!", app.input[i].c_str()));
00159 exit(E_NO_RUN);
00160 }
00161 }
00162 storeCommandArgs(values);
00163 }
00164 void ClaspAppBase::setup() {
00165 ProblemType pt = getProblemType();
00166 clasp_ = new ClaspFacade();
00167 if (!claspAppOpts_.onlyPre) {
00168 out_ = createOutput(pt);
00169 Event::Verbosity verb = (Event::Verbosity)std::min(verbose(), (uint32)Event::verbosity_max);
00170 if (out_.get() && out_->verbosity() < (uint32)verb) { verb = (Event::Verbosity)out_->verbosity(); }
00171 EventHandler::setVerbosity(Event::subsystem_facade , verb);
00172 EventHandler::setVerbosity(Event::subsystem_load , verb);
00173 EventHandler::setVerbosity(Event::subsystem_prepare, verb);
00174 EventHandler::setVerbosity(Event::subsystem_solve , verb);
00175 clasp_->ctx.setEventHandler(this);
00176 }
00177 else if (pt != Problem_t::ASP) {
00178 error("Option '--pre' only supported for ASP!");
00179 exit(E_NO_RUN);
00180 }
00181 }
00182
00183 void ClaspAppBase::shutdown() {
00184 if (clasp_.get()) {
00185 const ClaspFacade::Summary& result = clasp_->shutdown();
00186 if (out_.get()) { out_->shutdown(result); }
00187 if (!claspAppOpts_.lemmaOut.empty()) {
00188 std::ofstream file;
00189 std::ostream* os = &std::cout;
00190 if (!isStdOut(claspAppOpts_.lemmaOut)) {
00191 file.open(claspAppOpts_.lemmaOut.c_str());
00192 os = &file;
00193 }
00194 WriteLemmas lemmaOut(*os);
00195 lemmaOut.attach(clasp_->ctx);
00196 Constraint_t::Set x; x.addSet(Constraint_t::learnt_conflict);
00197 lemmaOut.flush(x, claspAppOpts_.outLbd);
00198 lemmaOut.detach();
00199 }
00200 int ec = getExitCode();
00201 ((ec |= exitCode(result)) & E_ERROR) != 0 ? exit(ec) : setExitCode(ec);
00202 }
00203 out_ = 0;
00204 clasp_ = 0;
00205 }
00206
00207 void ClaspAppBase::run() {
00208 if (out_.get()) { out_->run(getName(), getVersion(), &claspAppOpts_.input[0], &claspAppOpts_.input[0] + claspAppOpts_.input.size()); }
00209 try { run(*clasp_); }
00210 catch(...) {
00211 try { blockSignals(); setExitCode(E_ERROR); throw; }
00212 catch (const std::bad_alloc& ) { setExitCode(E_MEMORY); error("std::bad_alloc"); }
00213 catch (const std::exception& e) { error(e.what()); }
00214 catch (...) { ; }
00215 }
00216 }
00217
00218 bool ClaspAppBase::onSignal(int sig) {
00219 if (!clasp_.get() || !clasp_->terminate(sig)) {
00220 info("INTERRUPTED by signal!");
00221 setExitCode(E_INTERRUPT);
00222 shutdown();
00223 exit(getExitCode());
00224 }
00225 else {
00226
00227 info("Shutting down threads...");
00228 }
00229 return false;
00230 }
00231
00232 void ClaspAppBase::onEvent(const Event& ev) {
00233 const LogEvent* log = event_cast<LogEvent>(ev);
00234 if (log && log->isWarning()) {
00235 warn(log->msg);
00236 return;
00237 }
00238 if (out_.get()) {
00239 blockSignals();
00240 out_->onEvent(ev);
00241 unblockSignals(true);
00242 }
00243 }
00244
00245 bool ClaspAppBase::onModel(const Solver& s, const Model& m) {
00246 bool ret = true;
00247 if (out_.get() && !out_->quiet()) {
00248 blockSignals();
00249 ret = out_->onModel(s, m);
00250 unblockSignals(true);
00251 }
00252 return ret;
00253 }
00254
00255 int ClaspAppBase::exitCode(const RunSummary& run) const {
00256 int ec = 0;
00257 if (run.sat()) { ec |= E_SAT; }
00258 if (run.complete()) { ec |= E_EXHAUST; }
00259 if (run.result.interrupted()){ ec |= E_INTERRUPT; }
00260 return ec;
00261 }
00262
00263 void ClaspAppBase::printTemplate() const {
00264 printf(
00265 "# clasp %s configuration file\n"
00266 "# A configuration file contains a (possibly empty) list of configurations.\n"
00267 "# Each of which must have the following format:\n"
00268 "# <name>: <cmd>\n"
00269 "# where <name> is a string that must not contain ':'\n"
00270 "# and <cmd> is a command-line string of clasp options in long-format, e.g.\n"
00271 "# ('--heuristic=vsids --restarts=L,100').\n"
00272 "#\n"
00273 "# SEE: clasp --help\n"
00274 "#\n"
00275 "# NOTE: The options '--configuration' and '--tester' must not occur in a\n"
00276 "# configuration file. Furthermore, global options are ignored in all\n"
00277 "# but the first configuration.\n"
00278 "#\n"
00279 "# NOTE: Options given on the command-line are added to all configurations in a\n"
00280 "# configuration file. If an option is given both on the command-line and\n"
00281 "# in a configuration file, the one from the command-line is preferred.\n"
00282 "#\n"
00283 "# NOTE: If, after adding command-line options, a configuration\n"
00284 "# contains mutually exclusive options an error is raised.\n"
00285 "#\n", CLASP_VERSION);
00286 for (ConfigIter it = ClaspCliConfig::getConfig(Clasp::Cli::config_many); it.valid(); it.next()) {
00287 printf("%s: %s\n", it.name(), it.args());
00288 }
00289 }
00290
00291 void ClaspAppBase::printVersion() {
00292 ProgramOptions::Application::printVersion();
00293 printLibClaspVersion();
00294 }
00295
00296 void ClaspAppBase::printLibClaspVersion() const {
00297 if (strcmp(getName(), "clasp") != 0) {
00298 printf("libclasp version %s\n", CLASP_VERSION);
00299 }
00300 printf("Configuration: WITH_THREADS=%d", WITH_THREADS);
00301 #if WITH_THREADS
00302 printf(" (Intel TBB version %d.%d)", TBB_VERSION_MAJOR, TBB_VERSION_MINOR);
00303 #endif
00304 printf("\n%s\n", CLASP_LEGAL);
00305 fflush(stdout);
00306 }
00307
00308 void ClaspAppBase::printHelp(const ProgramOptions::OptionContext& root) {
00309 ProgramOptions::Application::printHelp(root);
00310 if (root.getActiveDescLevel() >= ProgramOptions::desc_level_e1) {
00311 printf("[asp] %s\n", ClaspCliConfig::getDefaults(Problem_t::ASP));
00312 printf("[cnf] %s\n", ClaspCliConfig::getDefaults(Problem_t::SAT));
00313 printf("[opb] %s\n", ClaspCliConfig::getDefaults(Problem_t::PB));
00314 }
00315 if (root.getActiveDescLevel() >= ProgramOptions::desc_level_e2) {
00316 printf("\nDefault configurations:\n");
00317 printDefaultConfigs();
00318 }
00319 fflush(stdout);
00320 }
00321
00322 void ClaspAppBase::printDefaultConfigs() const {
00323 uint32 minW = 2, maxW = 80;
00324 std::string cmd;
00325 for (int i = Clasp::Cli::config_default+1; i != Clasp::Cli::config_default_max_value; ++i) {
00326 ConfigIter it = ClaspCliConfig::getConfig(static_cast<Clasp::Cli::ConfigKey>(i));
00327 printf("%s:\n%*c", it.name(), minW-1, ' ');
00328 cmd = it.args();
00329
00330 std::size_t sz = cmd.size(), off = 0, n = maxW - minW;
00331 while (n < sz) {
00332 while (n != off && cmd[n] != ' ') { --n; }
00333 if (n != off) { cmd[n] = 0; printf("%s\n%*c", &cmd[off], minW-1, ' '); }
00334 else { break; }
00335 off = n+1;
00336 n = (maxW - minW) + off;
00337 }
00338 printf("%s\n", cmd.c_str()+off);
00339 }
00340 }
00341
00342 void ClaspAppBase::readLemmas(SharedContext& ctx) {
00343 std::ifstream fileStream;
00344 std::istream& file = isStdIn(claspAppOpts_.lemmaIn) ? std::cin : (fileStream.open(claspAppOpts_.lemmaIn.c_str()), fileStream);
00345 Solver& s = *ctx.master();
00346 bool ok = !s.hasConflict();
00347 uint32 numVars;
00348 for (ClauseCreator clause(&s); file && ok; ) {
00349 while (file.peek() == 'c' || file.peek() == 'p') {
00350 const char* m = file.get() == 'p' ? " cnf" : " clasp";
00351 while (file.get() == *m) { ++m; }
00352 if (!*m && (!(file >> numVars) || numVars != ctx.numVars()) ) {
00353 throw std::runtime_error("Wrong number of vars in file: "+claspAppOpts_.lemmaIn);
00354 }
00355 while (file.get() != '\n' && file) {}
00356 }
00357 Literal x; bool elim = false;
00358 clause.start(Constraint_t::learnt_conflict);
00359 clause.setLbd(claspAppOpts_.inLbd);
00360 while ( (file >> x) ) {
00361 if (x.var() == 0) { ok = elim || clause.end(); break; }
00362 elim = elim || ctx.eliminated(x.var());
00363 if (!s.validVar(x.var())) { throw std::runtime_error("Bad variable in file: "+claspAppOpts_.lemmaIn); }
00364 if (!elim) { clause.add(x); }
00365 }
00366 if (x.var() != 0) { throw std::runtime_error("Unrecognized format: "+claspAppOpts_.lemmaIn); }
00367 }
00368 if (ok && !file.eof()){ throw std::runtime_error("Error reading file: "+claspAppOpts_.lemmaIn); }
00369 s.simplify();
00370 }
00371
00372 void ClaspAppBase::writeNonHcfs(const SharedDependencyGraph& graph) const {
00373 uint32 scc = 0;
00374 char buf[10];
00375 std::ofstream file;
00376 for (SharedDependencyGraph::NonHcfIter it = graph.nonHcfBegin(), end = graph.nonHcfEnd(); it != end; ++it, ++scc) {
00377 snprintf(buf, 10, ".%u", scc);
00378 std::string n = claspAppOpts_.hccOut + buf;
00379 if (!isStdOut(claspAppOpts_.hccOut) && (file.open(n.c_str()), !file.is_open())) { throw std::runtime_error("Could not open hcc file!\n"); }
00380 WriteCnf cnf(file.is_open() ? file : std::cout);
00381 const SharedContext& ctx = it->second->ctx();
00382 cnf.writeHeader(ctx.numVars(), ctx.numConstraints());
00383 cnf.write(ctx.numVars(), ctx.shortImplications());
00384 Solver::DBRef db = ctx.master()->constraints();
00385 for (uint32 i = 0; i != db.size(); ++i) {
00386 if (ClauseHead* x = db[i]->clause()) { cnf.write(x); }
00387 }
00388 for (uint32 i = 0; i != ctx.master()->trail().size(); ++i) {
00389 cnf.write(ctx.master()->trail()[i]);
00390 }
00391 cnf.close();
00392 file.close();
00393 }
00394 }
00395 std::istream& ClaspAppBase::getStream() {
00396 ProgramOptions::StringSeq& input = claspAppOpts_.input;
00397 if (input.empty() || isStdIn(input[0])) {
00398 input.resize(1, "stdin");
00399 return std::cin;
00400 }
00401 else {
00402 static std::ifstream file;
00403 if (file.is_open()) return file;
00404 file.open(input[0].c_str());
00405 if (!file) { throw std::runtime_error("Can not read from '"+input[0]+"'"); }
00406 return file;
00407 }
00408 }
00409
00410
00411 Output* ClaspAppBase::createOutput(ProblemType f) {
00412 SingleOwnerPtr<Output> out;
00413 if (claspAppOpts_.outf == ClaspAppOptions::out_none) {
00414 return 0;
00415 }
00416 if (claspAppOpts_.outf != ClaspAppOptions::out_json || claspAppOpts_.onlyPre) {
00417 TextOutput::Format outFormat = TextOutput::format_asp;
00418 if (f == Problem_t::SAT){ outFormat = TextOutput::format_sat09; }
00419 else if (f == Problem_t::PB) { outFormat = TextOutput::format_pb09; }
00420 else if (f == Problem_t::ASP && claspAppOpts_.outf == ClaspAppOptions::out_comp) {
00421 outFormat = TextOutput::format_aspcomp;
00422 }
00423 out.reset(new TextOutput(verbose(), outFormat, claspAppOpts_.outAtom.c_str(), claspAppOpts_.ifs));
00424 }
00425 else {
00426 out.reset(new JsonOutput(verbose()));
00427 }
00428 if (claspAppOpts_.quiet[0] != static_cast<uint8>(UCHAR_MAX)) {
00429 out->setModelQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[0]));
00430 }
00431 if (claspAppOpts_.quiet[1] != static_cast<uint8>(UCHAR_MAX)) {
00432 out->setOptQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[1]));
00433 }
00434 if (claspAppOpts_.quiet[2] != static_cast<uint8>(UCHAR_MAX)) {
00435 out->setCallQuiet((Output::PrintLevel)std::min(uint8(Output::print_no), claspAppOpts_.quiet[2]));
00436 }
00437 if (claspAppOpts_.hideAux) {
00438 out->setHide('_');
00439 }
00440 return out.release();
00441 }
00442 void ClaspAppBase::storeCommandArgs(const ProgramOptions::ParsedValues&) {
00443
00444 }
00445
00446 bool ClaspAppBase::handlePostGroundOptions(ProgramBuilder& prg) {
00447 if (!claspAppOpts_.onlyPre || prg.type() != Problem_t::ASP) { return true; }
00448 if (prg.endProgram()) { static_cast<Asp::LogicProgram&>(prg).write(std::cout); }
00449 else { std::cout << "0\n0\nB+\n1\n0\nB-\n1\n0\n0\n"; }
00450 exit(E_UNKNOWN);
00451 return false;
00452 }
00453 bool ClaspAppBase::handlePreSolveOptions(ClaspFacade& clasp) {
00454 if (!claspAppOpts_.lemmaIn.empty() && clasp.step() == 0) { readLemmas(clasp.ctx); }
00455 if (!claspAppOpts_.hccOut.empty() && clasp.ctx.sccGraph.get()){ writeNonHcfs(*clasp.ctx.sccGraph); }
00456 return true;
00457 }
00458 void ClaspAppBase::run(ClaspFacade& clasp) {
00459 ProblemType pt = getProblemType();
00460 StreamSource input(getStream());
00461 bool inc = pt == Problem_t::ASP && *input == '9';
00462 ProgramBuilder& prg = clasp.start(claspConfig_, pt, inc);
00463 while (prg.parseProgram(input) && handlePostGroundOptions(prg)) {
00464 if (clasp.prepare() && handlePreSolveOptions(clasp)) {
00465 clasp.solve();
00466 }
00467 if (!inc || clasp.result().interrupted() || !input.skipWhite() || *input != '9' || !clasp.update().ok()) { break; }
00468 prg.disposeMinimizeConstraint();
00469 }
00470 }
00472
00474 ClaspApp::ClaspApp() {}
00475
00476 ProblemType ClaspApp::getProblemType() {
00477 InputFormat input = Input_t::detectFormat(getStream());
00478 return Problem_t::format2Type(input);
00479 }
00480
00481 void ClaspApp::run(ClaspFacade& clasp) {
00482 ClaspAppBase::run(clasp);
00483 }
00484
00485 void ClaspApp::printHelp(const ProgramOptions::OptionContext& root) {
00486 ClaspAppBase::printHelp(root);
00487 printf("\nclasp is part of Potassco: %s\n", "http://potassco.sourceforge.net/#clasp");
00488 printf("Get help/report bugs via : http://sourceforge.net/projects/potassco/support\n");
00489 fflush(stdout);
00490 }
00492
00494 WriteLemmas::WriteLemmas(std::ostream& os) : ctx_(0), os_(os) {}
00495 WriteLemmas::~WriteLemmas(){ detach(); }
00496 void WriteLemmas::detach() { if (ctx_) { ctx_ = 0; } }
00497 void WriteLemmas::attach(SharedContext& ctx) {
00498 detach();
00499 ctx_ = &ctx;
00500 }
00501 bool WriteLemmas::unary(Literal p, Literal x) const {
00502 if (!isSentinel(x) && x.asUint() > p.asUint() && (p.watched() + x.watched()) != 0) {
00503 os_ << ~p << " " << x << " 0\n";
00504 ++outShort_;
00505 }
00506 return true;
00507 }
00508 bool WriteLemmas::binary(Literal p, Literal x, Literal y) const {
00509 if (x.asUint() > p.asUint() && y.asUint() > p.asUint() && (p.watched() + x.watched() + y.watched()) != 0) {
00510 os_ << ~p << " " << x << " " << y << " 0\n";
00511 ++outShort_;
00512 }
00513 return true;
00514 }
00515
00516
00517 void WriteLemmas::flush(Constraint_t::Set x, uint32 maxLbd) {
00518 if (!ctx_ || !os_) { return; }
00519
00520 os_ << "c clasp " << ctx_->numVars() << "\n";
00521
00522 Solver& s = *ctx_->master();
00523 const LitVec& t = s.trail();
00524 Antecedent trueAnte(posLit(0));
00525 for (uint32 i = ctx_->numUnary(), end = s.decisionLevel() ? s.levelStart(1) : t.size(); i != end; ++i) {
00526 const Antecedent& a = s.reason(t[i]);
00527 if (a.isNull() || a.asUint() == trueAnte.asUint()) {
00528 os_ << t[i] << " 0\n";
00529 }
00530 }
00531
00532 uint32 numLearnts = ctx_->shortImplications().numLearnt();
00533 outShort_ = 0;
00534 for (Var v = 1; v <= ctx_->numVars() && outShort_ < numLearnts; ++v) {
00535 ctx_->shortImplications().forEach(posLit(v), *this);
00536 ctx_->shortImplications().forEach(negLit(v), *this);
00537 }
00538
00539 LitVec lits; ClauseHead* c;
00540 for (LitVec::size_type i = 0; i != s.numLearntConstraints() && os_; ++i) {
00541 if ((c = s.getLearnt(i).clause()) != 0 && c->lbd() <= maxLbd && x.inSet(c->ClauseHead::type())) {
00542 lits.clear();
00543 c->toLits(lits);
00544 std::copy(lits.begin(), lits.end(), std::ostream_iterator<Literal>(os_, " "));
00545 os_ << "0\n";
00546 }
00547 }
00548 os_.flush();
00549 }
00551
00553 void WriteCnf::writeHeader(uint32 numVars, uint32 numCons) {
00554 os_ << "p cnf " << numVars << " " << numCons << "\n";
00555 }
00556 void WriteCnf::write(ClauseHead* h) {
00557 lits_.clear();
00558 h->toLits(lits_);
00559 std::copy(lits_.begin(), lits_.end(), std::ostream_iterator<Literal>(os_, " "));
00560 os_ << "0\n";
00561 }
00562 void WriteCnf::write(Var maxVar, const ShortImplicationsGraph& g) {
00563 for (Var v = 1; v <= maxVar; ++v) {
00564 g.forEach(posLit(v), *this);
00565 g.forEach(negLit(v), *this);
00566 }
00567 }
00568 void WriteCnf::write(Literal u) {
00569 os_ << u << " 0\n";
00570 }
00571 bool WriteCnf::unary(Literal p, Literal x) const {
00572 if (p.asUint() < x.asUint()) {
00573 os_ << ~p << " " << x << " 0\n";
00574 }
00575 return true;
00576 }
00577 bool WriteCnf::binary(Literal p, Literal x, Literal y) const {
00578 if (p.asUint() < x.asUint() && p.asUint() < y.asUint()) {
00579 os_ << ~p << " " << x << " " << y << " 0\n";
00580 }
00581 return true;
00582 }
00583 void WriteCnf::close() {
00584 os_ << std::flush;
00585 }
00586
00587 }}
00588