clasp_options.cpp
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2006-2013, 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/cli/clasp_options.h>
00021 #include <clasp/minimize_constraint.h>
00022 #include <clasp/lookahead.h>
00023 #include <clasp/unfounded_check.h>
00024 #include <program_opts/program_options.h>
00025 #include <program_opts/typed_value.h>
00026 #include <cstring>
00027 #include <cstdarg>
00028 #include <cfloat>
00029 #include <fstream>
00031 // OPTION ACTION MACROS
00033 // primitives
00034 #define IS_OFF(str)             ( convFlag((str), TEMP) && TEMP == 0 )
00035 #define CONVERT(str, to)        ( bk_lib::string_cast((str), (to)) )
00036 #define CONVERT_EX(str, to, n)  ( xconvert((str), (to), &(str), (n)) && !*(str) )
00037 #define SET_ENUM(x, v, X, ...)  ( findInValueList((v), x, X, ##__VA_ARGS__, MAP(0,0)) )
00038 #define SET_ENUM_U(x, v, X, ...)( findInValueList((v), TEMP, X, ##__VA_ARGS__, MAP(0,0)) && SET(x, TEMP) )
00039 #define SET(x, v)               ( ((x)=(v)) == (v) )
00040 #define SET_LEQ(x, v, m)        ( ((v)<=(m)) && SET((x), (v)) )
00041 #define SET_OR_FILL(x, v)       ( SET((x),(v)) || ((x) = 0, (x) = ~(x),true) ) 
00042 #define SET_OR_ZERO(x,v)        ( SET((x),(v)) || SET((x),uint32(0)) )
00043 #define SET_R(x, v, lo, hi)     ( ((lo)<=(v)) && ((v)<=(hi)) && SET((x), (v)) )
00044 // actions
00045 #define STORE(x)                return bk_lib::string_cast(VALUE, x)
00046 #define STORE_ENUM(x, X, ...)   return SET_ENUM(x, VALUE, X, ##__VA_ARGS__)
00047 #define STORE_ENUM_U(x, X, ...) return SET_ENUM_U(x, VALUE, X, ##__VA_ARGS__)
00048 #define STORE_LEQ(x, y)         STORE(TEMP) && SET_LEQ(x, TEMP, y)
00049 #define STORE_OR_ZERO(x)        STORE(TEMP) && SET_OR_ZERO(x, TEMP)
00050 #define STORE_OR_FILL(x)        STORE(TEMP) && SET_OR_FILL(x, TEMP)
00051 #define STORE_FLAG(x)           return convFlag(VALUE,TEMP) && SET(x, TEMP)
00052 // helpers
00053 #define MAP(x, y) static_cast<const char*>(x), static_cast<int>(y)
00054 #define NO_ARG
00055 #define PAIR(T, U) std::pair<T,U>
00056 #define AGGREGATE(...) { __VA_ARGS__ }
00057 typedef std::pair<uint32, uint32> UPair;
00058 #define ARG(a) ->a
00059 #define VALUE (_val_)
00060 #define TEMP  (_tmp_)
00061 #define HEU_PARAM "hparam"
00062 
00063 // Functions for parsing/converting certain clasp types
00065 namespace bk_lib {
00066 template <class T>
00067 static int xconvert(const char* x, pod_vector<T>& out, const char** errPos, int) {
00068         using bk_lib::xconvert;
00069         const char* n = x;
00070         std::size_t s = out.size();
00071         for (T temp; xconvert(n, temp, &n, 0); ++n) {
00072                 out.push_back(temp);
00073                 if (*n != ',') { break; }
00074         }
00075         if (errPos)   { *errPos = n; }
00076         return static_cast<int>(out.size() - s);
00077 }
00078 }
00079 namespace Clasp {
00080 static int xconvert(const char* x, ScheduleStrategy& out, const char** errPos, int e) {
00081         using bk_lib::xconvert;
00082         if (!x) { return 0; }
00083         const char* next = std::strchr(x, ',');
00084         uint32      base = 0;
00085         int         tok  = 1;
00086         if (errPos) { *errPos = x; }
00087         if (!next || !xconvert(next+1, base, &next, e) || base == 0)         { return 0; }
00088         if (strncasecmp(x, "f,", 2) == 0 || strncasecmp(x, "fixed,", 6) == 0){
00089                 out = ScheduleStrategy::fixed(base);
00090         }
00091         else if (strncasecmp(x, "l,", 2) == 0 || strncasecmp(x, "luby,", 5) == 0) {
00092                 uint32 lim = 0;
00093                 if (*next == ',' && !xconvert(next+1, lim, &next, e)) { return 0; }
00094                 out = ScheduleStrategy::luby(base, lim);
00095         }
00096         else if (strncmp(x, "+,", 2) == 0 || strncasecmp(x, "add,", 4) == 0) {
00097                 std::pair<uint32, uint32> arg(0, 0);
00098                 if (*next != ',' || !xconvert(next+1, arg, &next, e)) { return 0; }
00099                 out = ScheduleStrategy::arith(base, arg.first, arg.second);
00100         }
00101         else if (strncmp(x, "x,", 2) == 0 || strncmp(x, "*,", 2) == 0 || strncasecmp(x, "d,", 2) == 0) {
00102                 std::pair<double, uint32> arg(0, 0);
00103                 if (*next != ',' || !xconvert(next+1, arg, &next, e)) { return 0; }
00104                 if      (strncasecmp(x, "d", 1) == 0 && arg.first > 0.0) { out = ScheduleStrategy(ScheduleStrategy::user_schedule, base, arg.first, arg.second); }
00105                 else if (strncasecmp(x, "d", 1) != 0 && arg.first >= 1.0){ out = ScheduleStrategy::geom(base, arg.first, arg.second); }
00106                 else { return 0; }
00107         }
00108         else { next = x; tok = 0; }
00109         if (errPos) { *errPos = next; }
00110         return tok;
00111 }
00112 namespace Cli {
00113 static bool findInValueListImpl(const char* value, int& out, const char* k1, int v1, va_list args) {
00114         if (strcasecmp(value, k1) == 0) { out = v1; return true; }
00115         while (const char* key = va_arg(args, const char *)) {
00116                 int val = va_arg(args, int);
00117                 if (strcasecmp(value, key) == 0) { out = val; return true; }
00118         }
00119         return false;
00120 }
00121 
00122 template <class T>
00123 static bool findInValueList(const char* value, T& out, const char* k1, int v1, ...) {
00124         va_list args;
00125         va_start(args, v1);
00126         int temp;
00127         bool found;
00128         if ((found = findInValueListImpl(value, temp, k1, v1, args)) == true) {
00129                 out = static_cast<T>(temp);
00130         }
00131         va_end(args);
00132         return found;
00133 }
00134 template <class T>
00135 static bool convFlag(const char* value, T& out) {
00136         bool res;
00137         if (value && bk_lib::xconvert(value, res, &value, 0) && !*value) { out = static_cast<T>(res); return true; }
00138         return false;
00139 }
00141 // Interface to ProgramOptions
00143 // Type for storing one command-line option.
00144 class ClaspCliConfig::ProgOption : public ProgramOptions::Value {
00145 public:
00146         ProgOption(ClaspCliConfig& c, int o) : ProgramOptions::Value(0), config_(&c), option_(o) {}
00147         bool doParse(const std::string&, const std::string& value) {
00148                 return option_ >= 0 ? config_->set(static_cast<Clasp::Cli::OptionKey>(option_), value.c_str()) : config_->set(static_cast<ConfigOption>(option_), value.c_str());
00149         }
00150         int option() const { return option_; }
00151 private:
00152         ClaspCliConfig* config_;
00153         int             option_;
00154 };
00155 // Adapter for parsing a command string.
00156 struct ClaspCliConfig::ParseContext : public ProgramOptions::ParseContext {
00157         typedef ProgramOptions::SharedOptPtr   OptPtr;
00158         typedef OptionContext::option_iterator OptionIter;
00159         ParseContext() : root(0) {}
00160         void init() { 
00161                 first = root->find("configuration"); 
00162                 OptionIter it = root->find(HEU_PARAM);
00163                 root->addAlias("vsids-decay", it);
00164                 root->addAlias("berk-max", it);
00165                 root->addAlias("vmtf-mtf", it);
00166         }
00167         
00168         OptPtr getOption(const char* name, FindType ft) {
00169                 OptionIter it  = (root->begin() + root->findImpl(name, ft, 3u, frame->config).first->second);
00170                 OptionIter end = first + (option_category_end - 4) + 2; // 4 categories + 2 config options
00171                 if (it >= first && it < end && static_cast<const ProgOption*>(it->get()->value())->option() >= frame->minKey) { return *it; }
00172                 throw ProgramOptions::UnknownOption(frame->config, name);
00173         }
00174         OptPtr getOption(int, const char* key) { throw ProgramOptions::UnknownOption(frame->config, key); }
00175         void   addValue(const OptPtr& key, const std::string& value) {
00176                 using namespace ProgramOptions;
00177                 Value::State s  = Value::value_unassigned;
00178                 if (frame->exclude->count(key->name()) == 0) {
00179                         ProgOption* v = static_cast<ProgOption*>(key->value());
00180                         int        id = (v->option() - frame->minKey);
00181                         uint64&    xs = frame->seen[id/64];
00182                         uint64      m = static_cast<uint64>(1u) << (id & 63);
00183                         if ((xs & m) != 0 && !v->isComposing()){ throw ValueError(frame->config, ValueError::multiple_occurences, key->name(), value); }
00184                         if (!v->parse(key->name(), value, s))  { throw ValueError(frame->config, ValueError::invalid_value, key->name(), value); }
00185                         if (frame->out) { frame->out->add(key->name()); }
00186                         xs |= m;
00187                 }
00188         }
00189         RootPtr    root;
00190         OptionIter first;
00191         struct Frame {
00192                 uint64             seen[2];
00193                 const char*        config;
00194                 const ParsedOpts*  exclude;
00195                 ParsedOpts*        out;
00196                 int                minKey;
00197         }*          frame;
00198 };
00200 // Default Configs
00202 ClaspCliConfig::ConfigVec ClaspCliConfig::configs_g;
00203 
00204 void ClaspCliConfig::appendConfig(ConfigKey k, const char* name, const char* cmd) {
00205         for ( name = name ? name : ""; *name == ' '; ++name) { ; }
00206         for ( cmd  = cmd  ? cmd  : ""; *cmd  == ' '; ++cmd ) { ; }
00207         std::string& out = configs_g[k - config_usr];
00208         out.erase(out.end()-1);
00209         out.append(1, '/');
00210         out.append(name);
00211         out.erase(out.find_last_not_of(" \t")+1);
00212         out.append("\0/", 2);
00213         out.append(cmd);
00214         out.erase(out.find_last_not_of(" \t")+1);
00215         out.append(2, '\0');
00216 }
00217 
00218 ConfigKey ClaspCliConfig::allocConfig() {
00219         configs_g.reserve(2);
00220         unsigned key = (unsigned)configs_g.size() + config_usr;
00221         CLASP_FAIL_IF(key > config_usr_max_value, "Too many configs");
00222         configs_g.push_back(std::string());
00223         configs_g.back().reserve(128);
00224         configs_g.back().append(1, '\0');
00225         return static_cast<ConfigKey>(key);
00226 }
00227 
00228 ConfigKey ClaspCliConfig::loadConfig(const char* name) {
00229         std::ifstream file(name);
00230         CLASP_FAIL_IF(!file, "Could not open config file '%s'", name);
00231         ConfigKey key = allocConfig();
00232         uint32 lineNum= 0;
00233         for (std::string line, cont; std::getline(file, line); ) {
00234                 ++lineNum;
00235                 line.erase(0, line.find_first_not_of(" \t"));
00236                 if (line.empty() || line[0] == '#') { continue; }
00237                 if (*line.rbegin() == '\\')         { *line.rbegin() = ' '; cont += line; continue; }
00238                 try {
00239                         if (!cont.empty()) { cont += line; cont.swap(line); cont.clear(); }
00240                         std::string::size_type nEnd = line.find(":");
00241                         CLASP_FAIL_IF(!nEnd, "'%s@%u': Invalid empty name", name, lineNum);
00242                         CLASP_FAIL_IF(nEnd == std::string::npos, "'%s@%u': Expected ':' after name", name, lineNum);
00243                         line[nEnd] = '\0';
00244                         line.append(1, '\0');
00245                         appendConfig(key, &line[0], &line[nEnd+1]);
00246                 }
00247                 catch(...) { releaseConfig(key); throw; }
00248         }
00249         return key;
00250 }
00251 
00252 bool ClaspCliConfig::releaseConfig(ConfigKey key) {
00253         if (key >= config_usr) {
00254                 configs_g.at(unsigned(key - config_usr)).clear();
00255                 while (!configs_g.empty() && configs_g.back().empty()) { configs_g.pop_back(); }
00256                 return true;
00257         }
00258         return false;
00259 }
00260 
00261 ConfigIter ClaspCliConfig::getConfig(ConfigKey key) {
00262         switch(key) {
00263                 #define CONFIG(x,y,z) case config_##x: return ConfigIter("/[" #x "]\0/" y " " z "\0");
00264                 #define CLASP_CLI_DEFAULT_CONFIGS
00265                 #define CLASP_CLI_AUX_CONFIGS
00266                 #include <clasp/cli/clasp_cli_configs.inl>
00267                 case config_many:
00268                 #define CONFIG(x,y,z) "/[" #x "]\0/" z "\0"
00269                 #define CLASP_CLI_DEFAULT_CONFIGS
00270                 #define CLASP_CLI_AUX_CONFIGS
00271                         return ConfigIter(
00272                                 #include <clasp/cli/clasp_cli_configs.inl>
00273                                 );
00274                 case config_default: return ConfigIter("/default\0/\0");
00275                 case config_usr:
00276                 default        : return ConfigIter(configs_g.at(unsigned(key - config_usr)).data());
00277         }
00278 }
00279 const char* ClaspCliConfig::getDefaults(ProblemType t) {
00280         if (t == Problem_t::ASP){ return "--configuration=tweety"; }
00281         else                    { return "--configuration=trendy"; }
00282 }
00283 ConfigIter::ConfigIter(const char* x) : base_(x) {}
00284 const char* ConfigIter::name() const { return base_ + 1; }
00285 const char* ConfigIter::args() const { return base_ + std::strlen(base_) + 2; }
00286 bool        ConfigIter::valid()const { return *base_ != 0; }
00287 bool        ConfigIter::next()       {
00288         base_ = args();
00289         base_+= std::strlen(base_) + 1;
00290         return valid();
00291 }
00293 // ClaspCliConfig
00295 ClaspCliConfig::ScopedSet::ScopedSet(ClaspCliConfig& s, uint8 mode, uint32 sId) : self(&s) {
00296         if (sId) { mode |= mode_solver; }
00297         s.cliId   = static_cast<uint8>(sId);
00298         s.cliMode = mode;
00299 }
00300 ClaspCliConfig::ScopedSet::~ScopedSet() { self->cliId = self->cliMode = 0; }
00301 ClaspCliConfig::RawConfig::RawConfig(const char* name) {
00302         raw.append(1, '/').append(name ? name : "").append("\0/\0", 3); 
00303 }
00304 void ClaspCliConfig::RawConfig::addArg(const char* arg) {
00305         *raw.rbegin() = ' ';
00306         raw.append(arg ? arg : "").append(1, '\0');
00307 }
00308 void ClaspCliConfig::RawConfig::addArg(const std::string& arg) { addArg(arg.c_str()); }
00309 ClaspCliConfig::ClaspCliConfig()  {}
00310 ClaspCliConfig::~ClaspCliConfig() {}
00311 ClaspCliConfig::ProgOption* ClaspCliConfig::createOption(int o) {  return new ProgOption(*this, o); }
00312 
00313 void ClaspCliConfig::init(OptionContext* root, bool owned) {
00314 #if WITH_THREADS
00315 #define MANY_DESC  "        many  : Use default portfolio to configure solver(s)\n"
00316 #define MANY_ARG   "|many"
00317 #else
00318 #define MANY_DESC  
00319 #define MANY_ARG   ""
00320 #endif
00321         using namespace ProgramOptions;
00322         if (opts_.get() == 0) { opts_ = new ParseContext(); }
00323         if (owned || !opts_->root.get() || !opts_->root.is_owner()) {
00324                 opts_->root = root; 
00325                 if (!owned) opts_->root.release();
00326         }
00327         OptionGroup configOpts("Clasp.Config Options");
00328         configOpts.addOptions()
00329                 ("configuration", createOption(opt_configuration)->defaultsTo("auto")->state(Value::value_defaulted), "Configure default configuration [%D]\n"
00330                  "      %A: {auto|frumpy|jumpy|tweety|handy|crafty|trendy" MANY_ARG "|<file>}\n"
00331                  "        auto  : Select configuration based on problem type\n"
00332                  "        frumpy: Use conservative defaults\n"
00333                  "        jumpy : Use aggressive defaults\n"
00334                  "        tweety: Use defaults geared towards asp problems\n"
00335                  "        handy : Use defaults geared towards large problems\n"
00336                  "        crafty: Use defaults geared towards crafted problems\n"
00337                  "        trendy: Use defaults geared towards industrial problems\n"
00338                  MANY_DESC
00339                  "        <file>: Use configuration file to configure solver(s)")
00340                 ("tester", createOption(opt_tester)->arg("<options>"), "Pass (quoted) string of %A to tester")
00341         ;
00342 #undef MANY_DESC
00343 #undef MANY_ARG
00344         OptionGroup solving("Clasp.Solving Options");
00345         OptionGroup asp("Clasp.ASP Options");
00346         OptionGroup search("Clasp.Search Options", ProgramOptions::desc_level_e1);
00347         OptionGroup lookback("Clasp.Lookback Options", ProgramOptions::desc_level_e1);
00348 #define OPTION(n, k, a, d, x) (n,createOption(opt_##k)a, d)
00349 #define GROUP_BEGIN(X) X.addOptions()
00350 #define GROUP_END(X)   ;
00351 #define CLASP_CONTEXT_OPTIONS configOpts
00352 #define CLASP_SOLVE_OPTIONS   solving
00353 #define CLASP_ENUM_OPTIONS    solving
00354 #define CLASP_ASP_OPTIONS     asp
00355 #define CLASP_SOLVER_BASIC_OPTIONS search
00356 #define CLASP_SEARCH_BASIC_OPTIONS  search
00357 #define CLASP_SOLVER_LOOKBACK_OPTIONS lookback
00358 #define CLASP_SEARCH_RESTART_OPTIONS  lookback
00359 #define CLASP_SEARCH_REDUCE_OPTIONS   lookback
00360 #include <clasp/cli/clasp_cli_options.inl>
00361         root->add(configOpts);
00362         root->add(solving);
00363         root->add(asp);
00364         root->add(search);
00365         root->add(lookback);
00366         opts_->init();
00367 }
00368 
00369 void ClaspCliConfig::addOptions(OptionContext& root) {
00370         init(&root, false);
00371 }
00372 
00373 int ClaspCliConfig::get(OptionKey oId, ContextParams*& ctx, SolverParams*& solver, SolveParams*& solve) {
00374         UserConfig* active = this->active();
00375         uint32      sId    = cliId;
00376         if (oId < option_category_search)   { solver = &active->addSolver(sId); return oId; }
00377         if (oId < option_category_context)  { solve  = &active->addSearch(sId); return oId; }
00378         if (oId < option_category_generator || isGenerator()) {
00379                 ctx = active;
00380                 if ((cliMode & mode_solver) == 0) { return oId; }
00381                 if ((cliMode & mode_relaxed)!= 0) { return 0; }
00382         }
00383         return (cliMode & mode_relaxed) != 0 && oId < option_category_end ? 0 : option_category_end;
00384 }
00385 
00386 void ClaspCliConfig::init(uint32 sId, ConfigKey c) {
00387         if (c != config_default) { 
00388                 ScopedSet(*this, mode_relaxed, sId)->set(getConfig(c), false, ParsedOpts(), 0);
00389         }
00390 }
00391 void ClaspCliConfig::initTester(uint32 sId, ConfigKey c) {
00392         if (c != config_default) { 
00393                 ScopedSet(*this, mode_tester|mode_relaxed, sId)->set(getConfig(c), false, ParsedOpts(), 0);
00394         }
00395 }
00396 
00397 bool ClaspCliConfig::setTester(uint32 solverId, OptionKey o, const char* value) {
00398         addTesterConfig();
00399         return ScopedSet(*this, mode_tester, solverId)->set(o, value);
00400 }
00401 bool ClaspCliConfig::set(uint32 id, OptionKey o, const char* value) {
00402         return ScopedSet(*this, 0, id)->set(o,value);
00403 }
00404 bool ClaspCliConfig::set(Clasp::Cli::OptionKey o, const char* _val_) {
00405         using bk_lib::xconvert;
00406         unsigned _tmp_;
00407         SolverOpts*    solver = 0;
00408         SearchOpts*    search = 0;
00409         ContextParams* ctxOpts= 0;
00410         switch(get(o, ctxOpts, solver, search)) {
00411                 case 0: return true;
00412                 default: error(o); return false;
00413                 #define OPTION(n, k, a, d, x)  case opt_##k: x ;
00414                 #define CLASP_CONTEXT_OPTIONS (*ctxOpts)
00415                 #define CLASP_ASP_OPTIONS asp
00416                 #define CLASP_ENUM_OPTIONS enumerate
00417                 #define CLASP_SOLVE_OPTIONS solve
00418                 #define CLASP_SOLVER_BASIC_OPTIONS (*solver)
00419                 #define CLASP_SOLVER_LOOKBACK_OPTIONS (*solver)
00420                 #define CLASP_SEARCH_BASIC_OPTIONS (*search)
00421                 #define CLASP_SEARCH_RESTART_OPTIONS search->restart
00422                 #define CLASP_SEARCH_REDUCE_OPTIONS search->reduce
00423                 #include <clasp/cli/clasp_cli_options.inl>
00424         }
00425 }
00426 bool ClaspCliConfig::set(ConfigOption o, const char* _val_) {
00427         uint8 _tmp_;
00428         if (o == opt_configuration) {
00429                 return SET_ENUM_U(active()->cliConfig, _val_,
00430                         MAP("auto",   config_default), MAP("frumpy", config_frumpy), MAP("jumpy",  config_jumpy),
00431                         MAP("tweety", config_tweety) , MAP("handy" , config_handy) ,
00432                         MAP("crafty", config_crafty) , MAP("trendy", config_trendy), MAP("many", config_many)) 
00433                         || (active()->cliConfig=(uint8)ClaspCliConfig::loadConfig(VALUE)) != 0;
00434         }
00435         else if (o == opt_tester && isGenerator()) {
00436                 ConfigKey key = allocConfig();
00437                 addTesterConfig()->cliConfig = static_cast<uint8>(key);
00438                 appendConfig(key, "<tester>", _val_);
00439                 return true;
00440         }
00441         error(o);
00442         return false;
00443 }
00444 bool ClaspCliConfig::setDefaults(UserConfig* active, uint32 sId, const ParsedOpts& cmdLine, ProblemType t) {
00445         ScopedSet temp(*this, (active == this ? 0 : mode_tester) | mode_relaxed, sId);
00446         if (sId == 0 && t != Problem_t::ASP && cmdLine.count("sat-prepro") == 0) {
00447                 set(opt_sat_prepro, "20,25,120");
00448         }
00449         if (active->addSolver(sId).search == SolverParams::no_learning) {
00450                 if (cmdLine.count("heuristic") == 0) { set(opt_heuristic, "unit"); }
00451                 if (cmdLine.count("lookahead") == 0) { set(opt_lookahead, "atom"); }
00452                 if (cmdLine.count("deletion")  == 0) { set(opt_deletion, "no"); }
00453                 if (cmdLine.count("restarts")  == 0) { set(opt_restarts, "no"); }
00454         }
00455         return true;
00456 }
00457 
00458 bool ClaspCliConfig::set(const ConfigIter& config, bool allowConfig, const ParsedOpts& exclude, ParsedOpts* out) {
00459         if (!opts_.get() || !opts_->root.get()) { init(new OptionContext(), true); }
00460         ParseContext::Frame frame = { {uint64(0),uint64(0)}, config.name(), &exclude, out, (allowConfig ? -2 : 0) };
00461         opts_->frame = &frame;
00462         ProgramOptions::parseCommandString(config.args(), *opts_, ProgramOptions::command_line_allow_flag_value);
00463         return true;
00464 }
00465 
00466 bool ClaspCliConfig::finalize() {
00467         UserConfiguration* arr[3] = { this, testerConfig(), 0 };
00468         UserConfiguration** c     = arr;
00469         char ctx[80];
00470         do {
00471                 for (uint32 i = 0; i != (*c)->numSolver(); ++i) {
00472                         validate(clasp_format(ctx, 80, "<%s>.%u", *c == this ? "<config>":"<tester>", i), (*c)->solver(i), (*c)->search(i));
00473                 }
00474         } while (*++c);
00475         return true;
00476 }
00477 
00478 bool ClaspCliConfig::finalize(const ParsedOpts& x, ProblemType t, bool defs) {
00479         ParsedOpts temp;
00480         if (!finalizeSolvers(this, finalizeParsed(this, x, temp), t, defs)){ return false; }
00481         if (!finalizeTester(defs))                                         { return false; }
00482         if (opts_.get() && !opts_->root.is_owner())                        { opts_->root = 0; }
00483         return true;
00484 }
00485 
00486 bool ClaspCliConfig::finalizeTester(bool defs) {
00487         if (BasicSatConfig* tester = testerConfig()) {
00488                 ParsedOpts ex;
00489                 ConfigKey key = static_cast<ConfigKey>(tester->cliConfig);
00490                 if ((tester->cliConfig & opt_applied) == 0) {
00491                         tester->cliConfig = 0;
00492                         if (!ScopedSet(*this, mode_tester)->set(getConfig(key), true, ParsedOpts(), &ex)) {
00493                                 return false;
00494                         }
00495                         releaseConfig(key);
00496                 }
00497                 return finalizeSolvers(testerConfig(), finalizeParsed(testerConfig(), ex, ex), Problem_t::ASP, defs);
00498         }
00499         return true;
00500 }
00501 
00502 void ClaspCliConfig::addDisabled(ParsedOpts& parsed) {
00503         finalizeParsed(this, parsed, parsed);
00504 }
00505 
00506 const ClaspCliConfig::ParsedOpts& ClaspCliConfig::finalizeParsed(UserConfig* active, const ParsedOpts& parsed, ParsedOpts& exclude) const {
00507         bool copied = &parsed == &exclude;
00508         if (active->search(0).reduce.fReduce() == 0 && parsed.count("deletion") != 0) {
00509                 if (!copied) { exclude = parsed; copied = true; }
00510                 exclude.add("del-cfl");
00511                 exclude.add("del-max");
00512                 exclude.add("del-grow");
00513         }
00514         CLASP_FAIL_IF(parsed.count(HEU_PARAM) && !parsed.count("heuristic"), "'--" HEU_PARAM "' requires '--heuristic'");
00515         if (parsed.count("heuristic") && !parsed.count(HEU_PARAM)) {
00516                 if (!copied) { exclude = parsed; copied = true; }
00517                 exclude.add(HEU_PARAM);
00518                 active->addSolver(0).heuParam = 0;
00519         }
00520         return !copied ? parsed : exclude;
00521 }
00522 
00523 bool ClaspCliConfig::finalizeSolvers(UserConfig* active, const ParsedOpts& parsed, ProblemType t, bool defs) {
00524         if (defs && !setDefaults(active, 0, parsed, t)) { return false; }
00525         SolverParams defSolver = active->solver(0);
00526         SolveParams  defSearch = active->search(0);
00527         const char*  ctx       = active == testerConfig() ? "<tester>" : "<config>";
00528         validate(ctx, defSolver, defSearch);
00529         if ((active->cliConfig & opt_applied) != 0) {
00530                 return true;
00531         }
00532         ConfigKey c = static_cast<ConfigKey>(active->cliConfig);
00533         if (c == config_many && solve.numSolver() == 1) { c = config_default; }
00534         if (c == config_default) {
00535                 if      (defSolver.search == SolverParams::no_learning)       { c = config_nolearn; }
00536                 else if (active == testerConfig())                            { c = config_tester_default; }
00537                 else if (solve.numSolver() == 1 || !solve.defaultPortfolio()) { c = t == Problem_t::ASP ? config_asp_default : config_sat_default; }
00538                 else                                                          { c = config_many; }
00539         }
00540         ConfigIter conf = getConfig(c);
00541         uint8  mode     = (active == testerConfig() ? mode_tester : 0) | mode_relaxed;
00542         uint32 portSize = 0;
00543         char   buf[80];
00544         for (uint32 i = 0; i != solve.numSolver() && conf.valid(); ++i) {
00545                 SolverParams& solver = (active->addSolver(i) = defSolver);
00546                 SolveParams& search  = (active->addSearch(i) = defSearch);
00547                 solver.id            = i;
00548                 if (!ScopedSet(*this, mode, i)->set(conf, false, parsed, 0)) {
00549                         return false;
00550                 }
00551                 validate(clasp_format(buf, 80, "%s.%s", ctx, conf.name()), solver, search);
00552                 ++portSize;
00553                 conf.next();
00554                 mode |= mode_solver;
00555         }
00556         if (portSize != solve.numSolver()) {
00557                 active->seed = (c >= config_many || solve.defaultPortfolio() || c == config_nolearn);
00558         }
00559         if (releaseConfig(c)) {
00560                 active->cliConfig = 0;
00561         }
00562         active->cliConfig |= opt_applied;
00563         return true;
00564 }
00565 
00566 void ClaspCliConfig::error(int opt) const {
00567         const char* optName = "???";
00568         switch(opt) {
00569                 default: break;
00570                 case opt_configuration: optName = "configuration"; break;
00571                 case opt_tester       : optName = "tester"; break;
00572 #define OPTION(n, k, a, d, x)  case opt_##k: optName = n; break;
00573 #define CLASP_CONTEXT_OPTIONS
00574 #define CLASP_ASP_OPTIONS
00575 #define CLASP_ENUM_OPTIONS
00576 #define CLASP_SOLVE_OPTIONS
00577 #define CLASP_SOLVER_BASIC_OPTIONS
00578 #define CLASP_SOLVER_LOOKBACK_OPTIONS
00579 #define CLASP_SEARCH_BASIC_OPTIONS
00580 #define CLASP_SEARCH_RESTART_OPTIONS
00581 #define CLASP_SEARCH_REDUCE_OPTIONS
00582 #include <clasp/cli/clasp_cli_options.inl>
00583         }
00584         const char* end = optName;
00585         while (*end && *end != ',' && *end != '!') { ++end; }
00586         throw ProgramOptions::UnknownOption(isGenerator() ? "<clasp>" : "<tester>", std::string(optName, end - optName));
00587 }
00588 
00589 bool ClaspCliConfig::setConfig(const RawConfig& config, ProblemType t) {
00590         ProgramOptions::ParsedOptions exclude;
00591         reset();
00592         return set(config.iterator(), true, exclude, &exclude) && opts_->root->assignDefaults(exclude) && finalize(exclude, t, true);
00593 }
00594 
00595 void validate(const char* ctx, const SolverParams& solver, const SolveParams& search) {
00596         if (!ctx) { ctx = "<clasp>"; }
00597         const ReduceParams& reduce = search.reduce;
00598         if (solver.search == SolverParams::no_learning) {
00599                 CLASP_FAIL_IF(Heuristic_t::isLookback(solver.heuId), "'%s': Heuristic requires lookback strategy!", ctx);
00600                 CLASP_FAIL_IF(!search.restart.sched.disabled() && !search.restart.sched.defaulted(), "'%s': 'no-lookback': restart options disabled!", ctx);
00601                 CLASP_FAIL_IF(!reduce.cflSched.disabled() || (!reduce.growSched.disabled() && !reduce.growSched.defaulted()) || search.reduce.fReduce() != 0, "'%s': 'no-lookback': deletion options disabled!", ctx);
00602         }
00603         bool  hasSched = !reduce.cflSched.disabled() || !reduce.growSched.disabled() || reduce.maxRange != UINT32_MAX;
00604         CLASP_FAIL_IF(hasSched  && reduce.fReduce() == 0.0f && !reduce.growSched.defaulted(), "'%s': 'no-deletion': deletion strategies disabled!", ctx);
00605         CLASP_FAIL_IF(!hasSched && reduce.fReduce() != 0.0f && !reduce.growSched.defaulted(), "'%s': 'deletion': deletion strategy required!", ctx);
00606 }
00607 
00608 }}


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