ItemTreePtr RuleIntroductionSolver::compute() { const auto nodeStackElement = app.getPrinter().visitNode(decomposition); assert(decomposition.getChildren().size() == 1); Decomposition& childNode = **decomposition.getChildren().begin(); ItemTreePtr childResult = childNode.getSolver().compute(); ItemTreePtr result; if(childResult) { result = extendRoot(childResult); assert(childResult->getChildren().empty() == false); for(const ItemTreePtr& childCandidate : childResult->getChildren()) { // Make introducedAtom false ItemTreeNode::Items candidateItems = childCandidate->getNode()->getItems(); ItemTreeNode::Items candidateAuxItems = childCandidate->getNode()->getAuxItems(); // Calculate false atoms of this candidate Hypergraph::Vertices candidateFalseAtoms; std::set_symmetric_difference(decomposition.getNode().getBag().begin(), decomposition.getNode().getBag().end(), candidateItems.begin(), candidateItems.end(), std::inserter(candidateFalseAtoms, candidateFalseAtoms.begin())); const bool introducedRuleDisappears = doesIntroducedRuleDisappear(candidateItems); if(introducedRuleDisappears || isIntroducedRuleSatisfied(candidateItems, candidateFalseAtoms)) candidateAuxItems.insert(introducedRule); ItemTreePtr candidate = extendCandidate(std::move(candidateItems), std::move(candidateAuxItems), childCandidate); for(const ItemTreePtr& childCertificate : childCandidate->getChildren()) { ItemTreeNode::Items certificateItems = childCertificate->getNode()->getItems(); ItemTreeNode::Items certificateAuxItems = childCertificate->getNode()->getAuxItems(); if(introducedRuleDisappears) certificateAuxItems.insert(introducedRule); else { // Calculate false atoms of this certificate Hypergraph::Vertices certificateFalseAtoms; std::set_symmetric_difference(decomposition.getNode().getBag().begin(), decomposition.getNode().getBag().end(), certificateItems.begin(), certificateItems.end(), std::inserter(certificateFalseAtoms, certificateFalseAtoms.begin())); if(isIntroducedRuleSatisfied(certificateItems, certificateFalseAtoms)) certificateAuxItems.insert(introducedRule); } candidate->addChildAndMerge(extendCertificate(std::move(certificateItems), std::move(certificateAuxItems), childCertificate)); } result->addChildAndMerge(std::move(candidate)); } assert(!decomposition.isRoot()); if(result->finalize(app, false, app.isPruningDisabled() == false || decomposition.isRoot()) == false) result.reset(); } app.getPrinter().solverInvocationResult(decomposition, result.get()); return result; }
ItemTreePtr AtomRemovalSolver::compute() { const auto nodeStackElement = app.getPrinter().visitNode(decomposition); assert(decomposition.getChildren().size() == 1); Decomposition& childNode = **decomposition.getChildren().begin(); ItemTreePtr childResult = childNode.getSolver().compute(); ItemTreePtr result; if(childResult) { result = extendRoot(childResult); assert(childResult->getChildren().empty() == false); // Guess node to extend at depth 1 for(const ItemTreePtr& childCandidate : childResult->getChildren()) { ItemTreeNode::Items candidateItems = childCandidate->getNode()->getItems(); candidateItems.erase(removedAtom); ItemTreeNode::Items candidateAuxItems = childCandidate->getNode()->getAuxItems(); ItemTreePtr candidate = extendCandidate(std::move(candidateItems), std::move(candidateAuxItems), childCandidate); for(const ItemTreePtr& childCertificate : childCandidate->getChildren()) { ItemTreeNode::Items certificateItems = childCertificate->getNode()->getItems(); certificateItems.erase(removedAtom); ItemTreeNode::Items certificateAuxItems = childCertificate->getNode()->getAuxItems(); const ItemTreeNode::Type type = decomposition.isRoot() ? (certificateAuxItems.find(String("smaller")) == certificateAuxItems.end() ? ItemTreeNode::Type::ACCEPT : ItemTreeNode::Type::REJECT) : ItemTreeNode::Type::UNDEFINED; candidate->addChildAndMerge(extendCertificate(std::move(certificateItems), std::move(certificateAuxItems), childCertificate, type)); } result->addChildAndMerge(std::move(candidate)); } if(result->finalize(app, decomposition.isRoot(), app.isPruningDisabled() == false || decomposition.isRoot()) == false) result.reset(); } app.getPrinter().solverInvocationResult(decomposition, result.get()); return result; }
void Solver::handleRowCandidate(long costBound) { // ++models; assert(asyncResult); const Clasp::Model& m = asyncResult->model(); // Get items {{{ ItemTreeNode::Items items; asp_utils::forEachTrue(m, itemAtomInfos, [&items](const GringoOutputProcessor::ItemAtomArguments& arguments) { items.insert(arguments.item); }); ItemTreeNode::Items auxItems; asp_utils::forEachTrue(m, auxItemAtomInfos, [&auxItems](const GringoOutputProcessor::AuxItemAtomArguments& arguments) { auxItems.insert(arguments.item); }); ASP_CHECK(std::find_if(items.begin(), items.end(), [&auxItems](const String& item) { return auxItems.find(item) != auxItems.end(); }) == items.end(), "Items and auxiliary items not disjoint"); // }}} // FIXME Do proper cost computations, not this item-set cardinality proof of concept // Compute cost {{{ // ASP_CHECK(asp_utils::countTrue(m, costAtomInfos) <= 1, "More than one true cost/1 atom"); // long cost = 0; // asp_utils::forFirstTrue(m, costAtomInfos, [&cost](const GringoOutputProcessor::CostAtomArguments& arguments) { // cost = arguments.cost; // }); // node->setCost(cost); long cost = items.size(); for(const auto& row : getCurrentRowCombination()) { const auto& oldItems = row->getItems(); ItemTreeNode::Items intersection; std::set_intersection(items.begin(), items.end(), oldItems.begin(), oldItems.end(), std::inserter(intersection, intersection.begin())); cost += row->getCost() - intersection.size(); } // }}} if(cost >= costBound) { // ++discardedModels; newestRow = itemTree->getChildren().end(); return; } assert(itemTree); // Create item tree node {{{ std::shared_ptr<ItemTreeNode> node(new ItemTreeNode(std::move(items), std::move(auxItems), {getCurrentRowCombination()})); // }}} if(!app.isOptimizationDisabled()) { // Set cost {{{ node->setCost(cost); // }}} // Set current cost {{{ // ASP_CHECK(asp_utils::countTrue(m, currentCostAtomInfos) <= 1, "More than one true currentCost/1 atom"); // ASP_CHECK(asp_utils::countTrue(m, currentCostAtomInfos) == 0 || asp_utils::countTrue(m, costAtomInfos) == 1, "True currentCost/1 atom without true cost/1 atom"); // long currentCost = 0; // asp_utils::forFirstTrue(m, currentCostAtomInfos, [¤tCost](const GringoOutputProcessor::CurrentCostAtomArguments& arguments) { // currentCost = arguments.currentCost; // }); // node->setCurrentCost(currentCost); node->setCurrentCost(node->getItems().size()); // }}} // Possibly update cost of root {{{ itemTree->getNode()->setCost(std::min(itemTree->getNode()->getCost(), cost)); // }}} } // Add node to item tree {{{ //ItemTree::Children::const_iterator newChild = itemTree->addChildAndMerge(ItemTree::ChildPtr(new ItemTree(std::move(node)))); newestRow = itemTree->costChangeAfterAddChildAndMerge(ItemTree::ChildPtr(new ItemTree(std::move(node)))); // }}} //if(newChild != itemTree->getChildren().end()) // newestRow = newChild; }
ItemTreePtr AtomIntroductionSolver::compute() { const auto nodeStackElement = app.getPrinter().visitNode(decomposition); assert(decomposition.getChildren().size() == 1); Decomposition& childNode = **decomposition.getChildren().begin(); ItemTreePtr childResult = childNode.getSolver().compute(); ItemTreePtr result; if(childResult) { result = extendRoot(childResult); assert(childResult->getChildren().empty() == false); // Find out which rules are satisfied by setting introducedAtom to true or false, respectively, and which disappear from the reduct by setting introducedAtom to true. // TODO unordered_set? Rules rulesSatisfiedByTrue; Rules rulesSatisfiedByFalse; Rules rulesDisappearingByTrue; for(String bagElement : decomposition.getNode().getBag()) { AtomsInRule::const_iterator it = heads.find(bagElement); if(it != heads.end() && it->second.find(introducedAtom) != it->second.end()) rulesSatisfiedByTrue.insert(bagElement); it = positiveBody.find(bagElement); if(it != positiveBody.end() && it->second.find(introducedAtom) != it->second.end()) rulesSatisfiedByFalse.insert(bagElement); it = negativeBody.find(bagElement); if(it != negativeBody.end() && it->second.find(introducedAtom) != it->second.end()) { rulesSatisfiedByTrue.insert(bagElement); rulesDisappearingByTrue.insert(bagElement); } } // Guess node to extend at depth 1 for(const ItemTreePtr& childCandidate : childResult->getChildren()) { // Make introducedAtom false ItemTreeNode::Items candidateItems = childCandidate->getNode()->getItems(); ItemTreeNode::Items candidateAuxItems = childCandidate->getNode()->getAuxItems(); // Add satisfied rules candidateAuxItems.insert(rulesSatisfiedByFalse.begin(), rulesSatisfiedByFalse.end()); ItemTreePtr candidate = extendCandidate(std::move(candidateItems), std::move(candidateAuxItems), childCandidate); for(const ItemTreePtr& childCertificate : childCandidate->getChildren()) { ItemTreeNode::Items certificateItems = childCertificate->getNode()->getItems(); ItemTreeNode::Items certificateAuxItems = childCertificate->getNode()->getAuxItems(); // Add satisfied rules certificateAuxItems.insert(rulesSatisfiedByFalse.begin(), rulesSatisfiedByFalse.end()); candidate->addChildAndMerge(extendCertificate(std::move(certificateItems), std::move(certificateAuxItems), childCertificate)); } result->addChildAndMerge(std::move(candidate)); // Make introducedAtom true candidateItems = childCandidate->getNode()->getItems(); candidateItems.insert(introducedAtom); candidateAuxItems = childCandidate->getNode()->getAuxItems(); // Add satisfied rules candidateAuxItems.insert(rulesSatisfiedByTrue.begin(), rulesSatisfiedByTrue.end()); candidate = extendCandidate(std::move(candidateItems), std::move(candidateAuxItems), childCandidate); for(const ItemTreePtr& childCertificate : childCandidate->getChildren()) { // Make introducedAtom false in certificate (and add "smaller" flag) ItemTreeNode::Items certificateItems = childCertificate->getNode()->getItems(); ItemTreeNode::Items certificateAuxItems = childCertificate->getNode()->getAuxItems(); certificateAuxItems.emplace("smaller"); certificateAuxItems.insert(rulesDisappearingByTrue.begin(), rulesDisappearingByTrue.end()); certificateAuxItems.insert(rulesSatisfiedByFalse.begin(), rulesSatisfiedByFalse.end()); candidate->addChildAndMerge(extendCertificate(std::move(certificateItems), std::move(certificateAuxItems), childCertificate)); // Make introducedAtom true in certificate certificateItems = childCertificate->getNode()->getItems(); certificateItems.insert(introducedAtom); certificateAuxItems = childCertificate->getNode()->getAuxItems(); certificateAuxItems.insert(rulesSatisfiedByTrue.begin(), rulesSatisfiedByTrue.end()); candidate->addChildAndMerge(extendCertificate(std::move(certificateItems), std::move(certificateAuxItems), childCertificate)); } result->addChildAndMerge(std::move(candidate)); } assert(!decomposition.isRoot()); if(result->finalize(app, false, app.isPruningDisabled() == false || decomposition.isRoot()) == false) result.reset(); } app.getPrinter().solverInvocationResult(decomposition, result.get()); return result; }