dlvhex  2.5.0
src/ExtSourceProperties.cpp
Go to the documentation of this file.
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 #include "dlvhex2/ExtSourceProperties.h"
00039 #include "dlvhex2/Atoms.h"
00040 #include "dlvhex2/PluginInterface.h"
00041 
00042 #include "boost/lexical_cast.hpp"
00043 
00044 DLVHEX_NAMESPACE_BEGIN
00045 
00046 ExtSourceProperties& ExtSourceProperties::operator|=(const ExtSourceProperties& prop2)
00047 {
00048     monotonicInputPredicates.insert(prop2.monotonicInputPredicates.begin(), prop2.monotonicInputPredicates.end());
00049     antimonotonicInputPredicates.insert(prop2.antimonotonicInputPredicates.begin(), prop2.antimonotonicInputPredicates.end());
00050     predicateParameterNameIndependence.insert(prop2.predicateParameterNameIndependence.begin(), prop2.predicateParameterNameIndependence.end());
00051     finiteOutputDomain.insert(prop2.finiteOutputDomain.begin(), prop2.finiteOutputDomain.end());
00052     relativeFiniteOutputDomain.insert(prop2.relativeFiniteOutputDomain.begin(), prop2.relativeFiniteOutputDomain.end());
00053     functional |= prop2.functional;
00054     functionalStart = functionalStart > prop2.functionalStart ? functionalStart : prop2.functionalStart;
00055     atomlevellinear |= prop2.atomlevellinear;
00056     tuplelevellinear |= prop2.tuplelevellinear;
00057     usesEnvironment |= prop2.usesEnvironment;
00058     finiteFiber |= prop2.finiteFiber;
00059     BOOST_FOREACH (int i, prop2.finiteOutputDomain) finiteOutputDomain.insert(i);
00060     wellorderingStrlen.insert(prop2.wellorderingStrlen.begin(), prop2.wellorderingStrlen.end());
00061     wellorderingNatural.insert(prop2.wellorderingNatural.begin(), prop2.wellorderingNatural.end());
00062     onlySafeSupportSets |= prop2.onlySafeSupportSets;
00063     supportSets |= prop2.supportSets;
00064     completePositiveSupportSets |= prop2.completePositiveSupportSets;
00065     completeNegativeSupportSets |= prop2.completeNegativeSupportSets;
00066     variableOutputArity |= prop2.variableOutputArity;
00067     caresAboutAssigned |= prop2.caresAboutAssigned;
00068     caresAboutChanged |= prop2.caresAboutChanged;
00069     providesPartialAnswer |= prop2.providesPartialAnswer;
00070     return *this;
00071 }
00072 
00076 bool ExtSourceProperties::isMonotonic() const
00077 {
00078 
00079     PluginAtom* pa = ea ? ea->pluginAtom : this->pa;
00080     assert (pa);
00081     const std::vector<PluginAtom::InputType>& it = pa->getInputTypes();
00082     int i = 0;
00083     BOOST_FOREACH (PluginAtom::InputType t, it) {
00084         if (t == PluginAtom::PREDICATE && !isMonotonic(i)) return false;
00085         i++;
00086     }
00087     return true;
00088 }
00089 
00090 
00094 bool ExtSourceProperties::isAntimonotonic() const
00095 {
00096 
00097     PluginAtom* pa = ea ? ea->pluginAtom : this->pa;
00098     assert (pa);
00099     const std::vector<PluginAtom::InputType>& it = pa->getInputTypes();
00100     int i = 0;
00101     BOOST_FOREACH (PluginAtom::InputType t, it) {
00102         if (t == PluginAtom::PREDICATE && !isAntimonotonic(i)) return false;
00103         i++;
00104     }
00105     return true;
00106 }
00107 
00111 bool ExtSourceProperties::isNonmonotonic() const
00112 {
00113     return !isMonotonic();
00114 }
00115 
00116 void ExtSourceProperties::interpretProperties(RegistryPtr reg, const ExternalAtom& atom, const std::vector<std::vector<std::string> >& props)
00117 {
00118 
00119     DBGLOG(DBG, "Interpreting external source properties");
00120     typedef std::vector<std::string> Prop;
00121     BOOST_FOREACH (Prop p, props) {
00122         // parameter interpretation
00123         ID param1 = ID_FAIL;
00124         ID param2 = ID_FAIL;
00125         if (p.size() > 1) {
00126             try
00127             {
00128                 param1 = ID::termFromInteger(boost::lexical_cast<int>(p[1]));
00129             }
00130             catch(boost::bad_lexical_cast&) {
00131                 param1 = reg->storeConstantTerm(p[1]);
00132             }
00133         }
00134         if (p.size() > 2) {
00135             try
00136             {
00137                 param2 = ID::termFromInteger(boost::lexical_cast<int>(p[2]));
00138             }
00139             catch(boost::bad_lexical_cast&) {
00140                 param2 = reg->storeConstantTerm(p[2]);
00141             }
00142         }
00143 
00144         // property interpretation
00145         std::string name = p[0];
00146         if (name == "functional") {
00147             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"functional\" expects no parameters");
00148             DBGLOG(DBG, "External Atom is functional");
00149             functional = true;
00150         }
00151         else if (name == "monotonic") {
00152             if (param2 != ID_FAIL) throw GeneralError("Property \"monotonic\" expects less than two parameters");
00153             if (param1 == ID_FAIL) {
00154                 DBGLOG(DBG, "External Atom is monotonic in all input parameters");
00155                 for (uint32_t i = 0; i < atom.inputs.size(); ++i) {
00156                     monotonicInputPredicates.insert(i);
00157                 }
00158             }
00159             else {
00160                 bool found = false;
00161                 for (uint32_t i = 0; i < atom.inputs.size(); ++i) {
00162                     if (atom.inputs[i] == param1) {
00163                         DBGLOG(DBG, "External Atom is monotonic in parameter " << i);
00164                         monotonicInputPredicates.insert(i);
00165                         found = true;
00166                         break;
00167                     }
00168                 }
00169                 if (!found) throw SyntaxError("Property refers to invalid input parameter");
00170             }
00171         }
00172         else if (name == "antimonotonic") {
00173             if (param2 != ID_FAIL) throw GeneralError("Property \"antimonotonic\" expects less than two parameters");
00174             if (param1 == ID_FAIL) {
00175                 DBGLOG(DBG, "External Atom is antimonotonic in all input parameters");
00176                 for (uint32_t i = 0; i < atom.inputs.size(); ++i) {
00177                     antimonotonicInputPredicates.insert(i);
00178                 }
00179             }
00180             else {
00181                 bool found = false;
00182                 for (uint32_t i = 0; i < atom.inputs.size(); ++i) {
00183                     if (atom.inputs[i] == param1) {
00184                         DBGLOG(DBG, "External Atom is antimonotonic in parameter " << i);
00185                         antimonotonicInputPredicates.insert(i);
00186                         found = true;
00187                         break;
00188                     }
00189                 }
00190                 if (!found) throw SyntaxError("Property refers to invalid input parameter");
00191             }
00192         }
00193         else if (name == "atomlevellinear" || name == "fullylinear") {
00194             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"atomlevellinear\" expects no parameters");
00195             DBGLOG(DBG, "External Atom is linear on atom level");
00196             atomlevellinear = true;
00197         }
00198         else if (name == "tuplelevellinear") {
00199             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"tuplelevellinear\" expects no parameters");
00200             DBGLOG(DBG, "External Atom is linear on tuple level");
00201             tuplelevellinear = true;
00202         }
00203         else if (name == "usesenvironment") {
00204             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"usesenvironment\" expects no parameters");
00205             DBGLOG(DBG, "External Atom uses environment");
00206             usesEnvironment = true;
00207         }
00208         else if (name == "finitedomain") {
00209             if (param2 != ID_FAIL) throw GeneralError("Property \"finitedomain\" expects less than two parameters");
00210             if (param1 == ID_FAIL) {
00211                 DBGLOG(DBG, "External Atom has a finite domain in all output positions");
00212                 for (uint32_t i = 0; i < atom.tuple.size(); ++i) {
00213                     finiteOutputDomain.insert(i);
00214                 }
00215             }
00216             else {
00217                 bool found = false;
00218                 if (!param1.isIntegerTerm()) throw GeneralError("The parameter of property \"finitedomain\" must be an integer");
00219                 finiteOutputDomain.insert(param1.address);
00220             }
00221         }
00222         else if (name == "relativefinitedomain") {
00223             if (param1 == ID_FAIL || param2 == ID_FAIL) throw GeneralError("Property \"relativefinitedomain\" expects two parameters");
00224             int wrt;
00225             bool found = false;
00226             for (uint32_t i = 0; i < atom.inputs.size(); ++i) {
00227                 if (atom.inputs[i] == param2) {
00228                     wrt = i;
00229                     found = true;
00230                     break;
00231                 }
00232             }
00233             if (!found) throw SyntaxError("Property refers to invalid input parameter");
00234             if (!param1.isIntegerTerm()) throw GeneralError("The first parameter of property \"relativefinitedomain\" must be an integer");
00235             relativeFiniteOutputDomain.insert(std::pair<int, int>(param1.address, wrt));
00236         }
00237         else if (name == "finitefiber") {
00238             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"finitefiber\" expects no parameters");
00239             DBGLOG(DBG, "External Atom has a finite fiber");
00240             finiteFiber = true;
00241         }
00242         else if (name == "wellorderingstrlen") {
00243             if (param1 == ID_FAIL || param2 == ID_FAIL) throw GeneralError("Property \"wellordering\" expects two parameters");
00244             DBGLOG(DBG, "External Atom has a wellordering using strlen");
00245             wellorderingStrlen.insert(std::pair<int, int>(param1.address, param2.address));
00246         }
00247         else if (name == "wellordering") {
00248             if (param1 == ID_FAIL || param2 == ID_FAIL) throw GeneralError("Property \"wellordering\" expects two parameters");
00249             DBGLOG(DBG, "External Atom has a wellordering using natural");
00250             wellorderingNatural.insert(std::pair<int, int>(param1.address, param2.address));
00251         }
00252         else if (name == "onlysafesupportsets") {
00253             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"onlysafesupportsets\" expects no parameters");
00254             DBGLOG(DBG, "External Atom provides only safe support sets");
00255             onlySafeSupportSets = true;
00256         }
00257         else if (name == "supportsets") {
00258             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"supportsets\" expects no parameters");
00259             DBGLOG(DBG, "External Atom provides support sets");
00260             supportSets = true;
00261         }
00262         else if (name == "completepositivesupportsets") {
00263             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"completepositivesupportsets\" expects no parameters");
00264             DBGLOG(DBG, "External Atom provides complete positive support sets");
00265             supportSets = true;
00266             completePositiveSupportSets = true;
00267         }
00268         else if (name == "completenegativesupportsets") {
00269             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"completepositivesupportsets\" expects no parameters");
00270             DBGLOG(DBG, "External Atom provides complete negative support sets");
00271             supportSets = true;
00272             completeNegativeSupportSets = true;
00273         }
00274         else if (name == "variableoutputarity") {
00275             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"variableoutputarity\" expects no parameters");
00276             DBGLOG(DBG, "External Atom has a variable output arity");
00277             variableOutputArity = true;
00278         }
00279         else if (name == "caresaboutassigned") {
00280             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"caresaboutassigned\" expects no parameters");
00281             DBGLOG(DBG, "External Atom cares about assigned atoms");
00282             caresAboutAssigned = true;
00283         }
00284         else if (name == "caresaboutchanged") {
00285             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"caresaboutchanged\" expects no parameters");
00286             DBGLOG(DBG, "External Atom has a variable output arity");
00287             caresAboutChanged = true;
00288         }
00289         else if (name == "providespartialanswer") {
00290             if (param1 != ID_FAIL || param2 != ID_FAIL) throw GeneralError("Property \"providesPartialAnswer\" expects no parameters");
00291             DBGLOG(DBG, "External Atom provides partial answer");
00292             providesPartialAnswer = true;
00293         }
00294         else {
00295             throw SyntaxError("Property \"" + name + "\" unrecognized");
00296         }
00297     }
00298 }
00299 
00300 
00301 DLVHEX_NAMESPACE_END
00302 
00303 // vim:expandtab:ts=4:sw=4:
00304 // mode: C++
00305 // End: