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 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; }