clasp_app.cpp
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2006-2012, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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 // Some helpers
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 // ClaspAppOptions
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 // ClaspAppBase
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                 // multiple threads are active - shutdown was initiated
00227                 info("Shutting down threads...");
00228         }
00229         return false; // ignore all future signals
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                 // split options into formatted lines
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 // Creates output object suitable for given input format
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         /* We don't need the values */
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 // ClaspApp
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 // WriteLemmas
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 // NOTE: ON WINDOWS this function is unsafe if called from time-out handler because
00516 // it has potential races with the main thread
00517 void WriteLemmas::flush(Constraint_t::Set x, uint32 maxLbd) {
00518         if (!ctx_ || !os_) { return; }
00519         // write problem description
00520         os_ << "c clasp " << ctx_->numVars() << "\n";
00521         // write learnt units
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         // write implicit learnt constraints
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         // write explicit learnt conflict constraints matching the current filter
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 // WriteCnf
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 }} // end of namespace Clasp::Cli
00588 


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:38