ItemTreePtr Solver::compute() { const auto nodeStackElement = app.getPrinter().visitNode(decomposition); // Compute item trees of child nodes ChildItemTrees childItemTrees; for(const auto& child : decomposition.getChildren()) { ItemTreePtr itree = child->getSolver().compute(); if(!itree) return itree; childItemTrees.emplace(child->getNode().getGlobalId(), std::move(itree)); } // Input: Child item trees std::unique_ptr<std::stringstream> childItemTreesInput(new std::stringstream); *childItemTreesInput << "% Child item tree facts" << std::endl; for(const auto& childItemTree : childItemTrees) { std::ostringstream rootItemSetName; rootItemSetName << 'n' << childItemTree.first; asp_utils::declareItemTree(*childItemTreesInput, childItemTree.second.get(), tableMode, childItemTree.first, rootItemSetName.str()); } app.getPrinter().solverInvocationInput(decomposition, childItemTreesInput->str()); // Input: Induced subinstance std::unique_ptr<std::stringstream> instanceInput(new std::stringstream); asp_utils::induceSubinstance(*instanceInput, app.getInstance(), decomposition.getNode().getBag()); app.getPrinter().solverInvocationInput(decomposition, instanceInput->str()); // Input: Decomposition std::unique_ptr<std::stringstream> decompositionInput(new std::stringstream); asp_utils::declareDecomposition(decomposition, *decompositionInput); app.getPrinter().solverInvocationInput(decomposition, decompositionInput->str()); // Set up ASP solver Clasp::ClaspConfig config; config.solve.numModels = 0; Clasp::ClaspFacade clasp; // TODO The last parameter of clasp.startAsp in the next line is "allowUpdate". Does setting it to false have benefits? Clasp::Asp::LogicProgram& claspProgramBuilder = dynamic_cast<Clasp::Asp::LogicProgram&>(clasp.startAsp(config)); std::unique_ptr<Gringo::Output::LparseOutputter> lpOut(newGringoOutputProcessor(claspProgramBuilder, childItemTrees, tableMode)); std::unique_ptr<Gringo::Output::OutputBase> out(new Gringo::Output::OutputBase({}, *lpOut)); Gringo::Input::Program program; asp_utils::DummyGringoModule module; Gringo::Scripts scripts(module); Gringo::Defines defs; Gringo::Input::NongroundProgramBuilder gringoProgramBuilder(scripts, program, *out, defs); Gringo::Input::NonGroundParser parser(gringoProgramBuilder); // Pass input to ASP solver for(const auto& file : encodingFiles) parser.pushFile(std::string(file)); parser.pushStream("<instance>", std::move(instanceInput)); parser.pushStream("<decomposition>", std::move(decompositionInput)); parser.pushStream("<child_itrees>", std::move(childItemTreesInput)); parser.parse(); // Ground and solve program.rewrite(defs); program.check(); if(Gringo::message_printer()->hasError()) throw std::runtime_error("Grounding stopped because of errors"); auto gPrg = program.toGround(out->domains); Gringo::Ground::Parameters params; params.add("base", {}); gPrg.ground(params, scripts, *out); params.clear(); // Finalize ground program and create solver variables claspProgramBuilder.endProgram(); std::unique_ptr<asp_utils::ClaspCallback> cb(newClaspCallback(tableMode, *lpOut, childItemTrees, app, decomposition.isRoot(), decomposition, cardinalityCost)); cb->prepare(claspProgramBuilder); clasp.prepare(); clasp.solve(cb.get()); if(printStatistics) { std::cout << "Solver statistics for decomposition node " << decomposition.getNode().getGlobalId() << ':' << std::endl; Clasp::Cli::TextOutput{true, Clasp::Cli::TextOutput::format_asp}.printStatistics(clasp.summary(), true); } ItemTreePtr result = cb->finalize(decomposition.isRoot(), app.isPruningDisabled() == false || decomposition.isRoot()); app.getPrinter().solverInvocationResult(decomposition, result.get()); return result; }