dlvhex  2.5.0
src/EvalHeuristicFromFile.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 
00038 #ifdef HAVE_CONFIG_H
00039 #include "config.h"
00040 #endif                           // HAVE_CONFIG_H
00041 
00042 #include "dlvhex2/EvalHeuristicFromFile.h"
00043 #include "dlvhex2/EvalHeuristicShared.h"
00044 #include "dlvhex2/Logger.h"
00045 
00046 #include <boost/unordered_map.hpp>
00047 #include <boost/graph/properties.hpp>
00048 
00049 //#define BOOST_SPIRIT_DEBUG
00050 #include <boost/spirit/include/qi.hpp>
00051 
00052 #include <fstream>
00053 #include <sstream>
00054 
00055 DLVHEX_NAMESPACE_BEGIN
00056 
00057 using namespace evalheur;
00058 
00059 namespace
00060 {
00061 
00062     typedef std::vector<unsigned> IdxVector;
00063 
00064     struct IdxBuildCommand
00065     {
00066         // components to collapse to unit
00067         IdxVector collapse;
00068         // components to share into unit (constraint components)
00069         IdxVector share;
00070     };
00071     typedef std::vector<IdxBuildCommand> IdxCommandVector;
00072 
00073     void translateIdxBuildCommandsToBuildCommands(
00074         const IdxCommandVector& icommands,
00075         const ComponentGraph& cg,
00076     CommandVector& commands) {
00077         // get components in order of iteration into vector
00078         std::vector<Component> indexableComps;
00079         {
00080             ComponentGraph::ComponentIterator cit, cit_end;
00081             for(boost::tie(cit, cit_end) = cg.getComponents();
00082             cit != cit_end; ++cit) {
00083                 indexableComps.push_back(*cit);
00084             }
00085         }
00086 
00087         BOOST_FOREACH(const IdxBuildCommand& ibc, icommands) {
00088             BuildCommand bc;
00089             BOOST_FOREACH(unsigned idx, ibc.collapse) {
00090                 assert(idx < indexableComps.size() && "got bad component index");
00091                 bc.collapse.push_back(indexableComps[idx]);
00092             }
00093             BOOST_FOREACH(unsigned idx, ibc.share) {
00094                 assert(idx < indexableComps.size() && "got bad component index");
00095                 bc.share.push_back(indexableComps[idx]);
00096             }
00097             commands.push_back(bc);
00098         }
00099     }
00100 
00101 }
00102 
00103 
00104 EvalHeuristicFromFile::EvalHeuristicFromFile(const std::string& fname):
00105 Base(),
00106 fname(fname)
00107 {
00108 }
00109 
00110 
00111 EvalHeuristicFromFile::~EvalHeuristicFromFile()
00112 {
00113 }
00114 
00115 
00116 // for an example command file with only collapsing see examples/extatom3_evalplan.txt
00117 // for an example command file with collapsing and cloning see examples/extatom3_evalplanb.txt
00118 void parseCommandFile(const std::string& fname, IdxCommandVector& commands);
00119 
00120 // manual strategy:
00121 // get commands from file
00122 void EvalHeuristicFromFile::build(EvalGraphBuilder& builder)
00123 {
00124     const ComponentGraph& compgraph = builder.getComponentGraph();
00125 
00126     // get commands from file
00127     IdxCommandVector icommands;
00128     parseCommandFile(fname, icommands);
00129 
00130     CommandVector commands;
00131     translateIdxBuildCommandsToBuildCommands(
00132         icommands, compgraph, commands);
00133 
00134     executeBuildCommands(commands, builder);
00135 
00136     // create eval units for all components not specified in the file and warn
00137 
00138     // topologically sort all components that are still left at that point
00139     ComponentContainer sortedleftovers;
00140     topologicalSortComponents(builder.getComponentGraphRest(), sortedleftovers);
00141 
00142     // create evaluation units
00143     for(ComponentContainer::const_iterator it = sortedleftovers.begin();
00144     it != sortedleftovers.end(); ++it) {
00145         std::list<Component> comps, ccomps;
00146         comps.push_back(*it);
00147         EvalGraphBuilder::EvalUnit u = builder.createEvalUnit(comps, ccomps);
00148         LOG(WARNING,"component " << *it << " was not specified in input file "
00149             "and became eval unit " << u);
00150     }
00151 }
00152 
00153 
00154 namespace
00155 {
00156 
00157     struct sem
00158     {
00159         // this is just to create useful compiler/linker errors
00160         template<typename Attrib, typename Context>
00161             void operator()(const Attrib& attrib, Context& c, boost::spirit::qi::unused_type) const;
00162 
00163         template<typename Context>
00164             void operator()(const
00165             boost::fusion::vector2<
00166             std::vector<unsigned int>,
00167             boost::optional<std::vector<unsigned int> >
00168             >& attrib, Context& c, boost::spirit::qi::unused_type) const
00169         {
00170             IdxBuildCommand& target = boost::fusion::at_c<0>(c.attributes);
00171             const std::vector<unsigned int>& collapse = boost::fusion::at_c<0>(attrib);
00172             target.collapse = collapse;
00173             if( !!boost::fusion::at_c<1>(attrib) ) {
00174                 const std::vector<unsigned int>& share = boost::fusion::at_c<1>(attrib).get();
00175                 target.share = share;
00176             }
00177         }
00178     };
00179 
00180 }
00181 
00182 
00183 // for an example command file see examples/extatom3_evalplan.txt
00184 void parseCommandFile(const std::string& fname, IdxCommandVector& commands)
00185 {
00186     std::string input;
00187     WARNING("we should directly parse from stream") {
00188         std::ifstream in(fname.c_str());
00189         std::ostringstream buf;
00190         buf << in.rdbuf();
00191         input = buf.str();
00192     }
00193     std::string::const_iterator inp_begin = input.begin(), inp_end = input.end();
00194 
00195     namespace spirit = ::boost::spirit;
00196     namespace qi = ::boost::spirit::qi;
00197     qi::rule<std::string::const_iterator, IdxBuildCommand(), spirit::ascii::space_type> cmd;
00198     cmd = (qi::lit("collapse") >> +(qi::uint_) >> -(qi::lit("share") >> +(qi::uint_))) [ sem() ];
00199     qi::rule<std::string::const_iterator, IdxCommandVector(), spirit::ascii::space_type> root;
00200     root = *( cmd );
00201     #ifdef BOOST_SPIRIT_DEBUG
00202     BOOST_SPIRIT_DEBUG_NODE(root);
00203     #endif
00204     bool success =
00205         qi::phrase_parse(
00206         inp_begin, inp_end,
00207         root >> qi::eoi,
00208         spirit::ascii::space, commands);
00209     if (!success || inp_begin != inp_end) {
00210         LOG(ERROR,"success=" << success << " (begin!=end)=" << (inp_begin != inp_end));
00211         throw SyntaxError("Could not parse complete collapse command file!");
00212     }
00213 }
00214 
00215 
00216 DLVHEX_NAMESPACE_END
00217 
00218 
00219 // vim:expandtab:ts=4:sw=4:
00220 // mode: C++
00221 // End: