dlvhex
2.5.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005-2007 Roman Schindlauer 00003 * Copyright (C) 2006-2015 Thomas Krennwallner 00004 * Copyright (C) 2009-2016 Peter Schüller 00005 * Copyright (C) 2011-2016 Christoph Redl 00006 * Copyright (C) 2015-2016 Tobias Kaminski 00007 * Copyright (C) 2015-2016 Antonius Weinzierl 00008 * 00009 * This file is part of dlvhex. 00010 * 00011 * dlvhex is free software; you can redistribute it and/or modify it 00012 * under the terms of the GNU Lesser General Public License as 00013 * published by the Free Software Foundation; either version 2.1 of 00014 * the License, or (at your option) any later version. 00015 * 00016 * dlvhex is distributed in the hope that it will be useful, but 00017 * WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with dlvhex; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00024 * 02110-1301 USA. 00025 */ 00026 00034 #ifdef HAVE_CONFIG_H 00035 #include "config.h" 00036 #endif // HAVE_CONFIG_H 00037 00038 //#define BOOST_SPIRIT_DEBUG 00039 00040 #include "dlvhex2/WeakConstraintPlugin.h" 00041 #include "dlvhex2/PlatformDefinitions.h" 00042 #include "dlvhex2/ProgramCtx.h" 00043 #include "dlvhex2/Registry.h" 00044 #include "dlvhex2/Printer.h" 00045 #include "dlvhex2/Printhelpers.h" 00046 #include "dlvhex2/PredicateMask.h" 00047 #include "dlvhex2/Logger.h" 00048 #include "dlvhex2/HexParser.h" 00049 #include "dlvhex2/HexParserModule.h" 00050 #include "dlvhex2/HexGrammar.h" 00051 00052 #include <boost/algorithm/string/predicate.hpp> 00053 #include <boost/lexical_cast.hpp> 00054 00055 DLVHEX_NAMESPACE_BEGIN 00056 00057 WeakConstraintPlugin::CtxData::CtxData(): 00058 enabled(false) 00059 { 00060 } 00061 00062 00063 WeakConstraintPlugin::WeakConstraintPlugin(): 00064 PluginInterface() 00065 { 00066 setNameVersion("dlvhex-weakconstraintplugin[internal]", 2, 0, 0); 00067 } 00068 00069 00070 WeakConstraintPlugin::~WeakConstraintPlugin() 00071 { 00072 } 00073 00074 00075 // output help message for this plugin 00076 void WeakConstraintPlugin::printUsage(std::ostream& o) const 00077 { 00078 // 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789- 00079 o << " --weak-enable[=true,false]" << std::endl 00080 << " Enable or disable weak constraint plugin (default is enabled)." 00081 << " --weak-allmodels Display all models also under weak constraints."; 00082 } 00083 00084 00085 // accepted options: --weak-enable 00086 // 00087 // processes options for this plugin, and removes recognized options from pluginOptions 00088 // (do not free the pointers, the const char* directly come from argv) 00089 void WeakConstraintPlugin::processOptions( 00090 std::list<const char*>& pluginOptions, 00091 ProgramCtx& ctx) 00092 { 00093 DBGLOG(DBG, "WeakConstraintPlugin::processOptions"); 00094 WeakConstraintPlugin::CtxData& ctxdata = ctx.getPluginData<WeakConstraintPlugin>(); 00095 ctxdata.enabled = true; 00096 ctxdata.allmodels = false; 00097 00098 typedef std::list<const char*>::iterator Iterator; 00099 Iterator it; 00100 WARNING("create (or reuse, maybe from potassco?) cmdline option processing facility") 00101 it = pluginOptions.begin(); 00102 while( it != pluginOptions.end() ) { 00103 bool processed = false; 00104 const std::string str(*it); 00105 if( boost::starts_with(str, "--weak-enable" ) ) { 00106 std::string m = str.substr(std::string("--weak-enable").length()); 00107 if (m == "" || m == "=true") { 00108 ctxdata.enabled = true; 00109 } 00110 else if (m == "=false") { 00111 ctxdata.enabled = false; 00112 } 00113 else { 00114 std::stringstream ss; 00115 ss << "Unknown --weak-enable option: " << m; 00116 throw PluginError(ss.str()); 00117 } 00118 processed = true; 00119 // --allmodels is for backwards compatibility (option was renamed) 00120 }else if( str == "--weak-allmodels" || str == "--allmodels" ) 00121 { 00122 ctxdata.allmodels = true; 00123 processed = true; 00124 } 00125 00126 if( processed ) { 00127 // return value of erase: element after it, maybe end() 00128 DBGLOG(DBG,"WeakConstraintPlugin successfully processed option " << str); 00129 it = pluginOptions.erase(it); 00130 } 00131 else { 00132 it++; 00133 } 00134 } 00135 } 00136 00137 00138 namespace 00139 { 00140 00141 typedef WeakConstraintPlugin::CtxData CtxData; 00142 00143 class WeakRewriter: 00144 public PluginRewriter 00145 { 00146 private: 00147 WeakConstraintPlugin::CtxData& ctxdata; 00148 std::vector<ID> newIdb; 00149 void rewriteRule(ProgramCtx& ctx, std::vector<ID>& idb, ID ruleID); 00150 00151 public: 00152 WeakRewriter(WeakConstraintPlugin::CtxData& ctxdata) : ctxdata(ctxdata) {} 00153 virtual ~WeakRewriter() {} 00154 00155 virtual void rewrite(ProgramCtx& ctx); 00156 }; 00157 00158 void WeakRewriter::rewriteRule(ProgramCtx& ctx, std::vector<ID>& idb, ID ruleID) { 00159 00160 // if it is a weak constraint, add a head atom 00161 if (ruleID.isWeakConstraint()) { 00162 RegistryPtr reg = ctx.registry(); 00163 const Rule& rule = reg->rules.getByID(ruleID); 00164 00165 // take the rule as it is, but change the rule type 00166 Rule newRule = rule; 00167 newRule.kind &= (ID::ALL_ONES ^ ID::SUBKIND_RULE_WEAKCONSTRAINT); 00168 newRule.kind |= ID::SUBKIND_RULE_REGULAR; 00169 // newRule.kind = ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR; 00170 // if (ruleID.doesRuleContainExtatoms()) newRule.kind |= ID::PROPERTY_RULE_EXTATOMS; 00171 // if (ruleID.doesRuleContainModatoms()) newRule.kind |= ID::PROPERTY_RULE_MODATOMS; 00172 00173 std::set<ID> bodyVars; 00174 BOOST_FOREACH (ID b, rule.body) { 00175 reg->getVariablesInID(b, bodyVars, false, false); 00176 } 00177 00178 bool ground = bodyVars.size() == 0 && !rule.weight.isVariableTerm() && !rule.level.isVariableTerm(); 00179 OrdinaryAtom oatom(ID::MAINKIND_ATOM | ID::PROPERTY_AUX); 00180 if (ground) oatom.kind |= ID::SUBKIND_ATOM_ORDINARYG; 00181 else oatom.kind |= ID::SUBKIND_ATOM_ORDINARYN; 00182 oatom.tuple.push_back(reg->getAuxiliaryConstantSymbol('w', ruleID)); 00183 // add weight and level 00184 oatom.tuple.push_back(rule.weight); 00185 oatom.tuple.push_back(rule.level); 00186 if (rule.weakconstraintVector.size() > 0 && rule.weakconstraintVector[0] == ID_FAIL){ 00187 // DLV-style 00188 BOOST_FOREACH (ID v, bodyVars) { 00189 oatom.tuple.push_back(v); 00190 } 00191 }else{ 00192 // ASP-Core-2-style 00193 BOOST_FOREACH (ID v, rule.weakconstraintVector) { 00194 oatom.tuple.push_back(v); 00195 } 00196 } 00197 00198 ID hid = ground ? reg->storeOrdinaryGAtom(oatom) : reg->storeOrdinaryNAtom(oatom); 00199 newRule.head.push_back(hid); 00200 00201 // add the new rule to the IDB 00202 ID newRuleID = reg->storeRule(newRule); 00203 idb.push_back(newRuleID); 00204 00205 // we have at least one weak constraint --> enable optimization! (for performance reasons, do not enable it if not necessary!) 00206 // let both dlvhex and the solver backend optimize (dlvhex is required for soundness wrt. minimality semantics, backend is for efficiency reasons) 00207 00208 // note that we need to do some kind of optimization (influences EvaluateState) 00209 ctx.config.setOption("Optimization", 1); 00210 if (!ctxdata.allmodels) ctx.config.setOption("OptimizationByDlvhex", 1); 00211 if (!ctxdata.allmodels) ctx.config.setOption("OptimizationByBackend", 1); 00212 // suppress non-optimal models preceeding the optimal ones 00213 if (!ctxdata.allmodels) ctx.config.setOption("OptimizationFilterNonOptimal", 1); 00214 //ctx.config.setOption("OptimizationFilterNonOptimal", 0); 00215 //ctx.config.setOption("OptimizationByBackend", 1); 00216 //ctx.config.setOption("OptimizationByDlvhex", 0); 00217 if( ctx.config.getOption("OptimizationTwoStep") == 0 ) 00218 LOG(WARNING,"optimization might be slow because it cannot be done in a strictly decreasing manner" 00219 "(TODO perhaps it could be done but we currently cannot detect if weight constraints are in single unit)"); 00220 LOG(INFO,"WeakRewriter activated Optimization"); 00221 } 00222 else { 00223 idb.push_back(ruleID); 00224 } 00225 } 00226 00227 void WeakRewriter::rewrite(ProgramCtx& ctx) { 00228 BOOST_FOREACH (ID rid, ctx.idb) { 00229 rewriteRule(ctx, newIdb, rid); 00230 } 00231 ctx.idb = newIdb; 00232 00233 #ifndef NDEBUG 00234 std::stringstream programstring; 00235 RawPrinter printer(programstring, ctx.registry()); 00236 BOOST_FOREACH (ID ruleId, newIdb) { 00237 printer.print(ruleId); 00238 programstring << std::endl; 00239 } 00240 DBGLOG(DBG, "weak-constraint-free rewritten program:" << std::endl << programstring.str()); 00241 #endif 00242 } 00243 00244 } // anonymous namespace 00245 00246 00247 // rewrite program 00248 PluginRewriterPtr WeakConstraintPlugin::createRewriter(ProgramCtx& ctx) 00249 { 00250 WeakConstraintPlugin::CtxData& ctxdata = ctx.getPluginData<WeakConstraintPlugin>(); 00251 DBGLOG(DBG, "WeakConstraintPlugin::createRewriter: enabled=" << ctxdata.enabled); 00252 if( !ctxdata.enabled ) 00253 return PluginRewriterPtr(); 00254 00255 return PluginRewriterPtr(new WeakRewriter(ctxdata)); 00256 } 00257 00258 00259 // register auxiliary printer for strong negation auxiliaries 00260 void WeakConstraintPlugin::setupProgramCtx(ProgramCtx& ctx) 00261 { 00262 WeakConstraintPlugin::CtxData& ctxdata = ctx.getPluginData<WeakConstraintPlugin>(); 00263 DBGLOG(DBG, "WeakConstraintPlugin::setupProgramCtx: enabled=" << ctxdata.enabled); 00264 if( !ctxdata.enabled ) 00265 return; 00266 } 00267 00268 00269 std::vector<PluginAtomPtr> WeakConstraintPlugin::createAtoms(ProgramCtx& ctx) const 00270 { 00271 std::vector<PluginAtomPtr> ret; 00272 return ret; 00273 } 00274 00275 00276 DLVHEX_NAMESPACE_END 00277 00278 // this would be the code to use this plugin as a "real" plugin in a .so file 00279 // but we directly use it in dlvhex.cpp 00280 #if 0 00281 WeakConstraintPlugin theWeakConstraintPlugin; 00282 00283 // return plain C type s.t. all compilers and linkers will like this code 00284 extern "C" 00285 void * PLUGINIMPORTFUNCTION() 00286 { 00287 return reinterpret_cast<void*>(& DLVHEX_NAMESPACE theWeakConstraintPlugin); 00288 } 00289 #endif 00290 00291 00292 // vim:expandtab:ts=4:sw=4: 00293 // mode: C++ 00294 // End: