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 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: