// trivial strategy: // do a topological sort of the tree // build eval units in that order void EvalHeuristicTrivial::build(EvalGraphBuilder& builder) { const ComponentGraph& compgraph = builder.getComponentGraph(); ComponentContainer comps; evalheur::topologicalSortComponents(compgraph.getInternalGraph(), comps); for(ComponentContainer::const_iterator it = comps.begin(); it != comps.end(); ++it) { std::list<Component> comps, ccomps; comps.push_back(*it); EvalGraphBuilder::EvalUnit u = builder.createEvalUnit(comps, ccomps); LOG(ANALYZE,"component " << *it << " became eval unit " << u); } }
void EvalHeuristicEasy::build(EvalGraphBuilder& builder) { ComponentGraph& compgraph = builder.getComponentGraph(); bool didSomething; do { didSomething = false; // // forall external components e: // merge with all rules that // * depend on e // * do not contain external atoms // * do not depend on something e does not (transitively) depend on // { ComponentIterator cit; // do not use boost::tie here! the container is modified in the loop! for(cit = compgraph.getComponents().first; cit != compgraph.getComponents().second; ++cit) { Component comp = *cit; if( compgraph.propsOf(comp).outerEatoms.empty() ) continue; LOG(ANALYZE,"checking whether to collapse external component " << comp << " with successors"); // get predecessors ComponentSet preds; transitivePredecessorComponents(compgraph, comp, preds); // get successors ComponentSet collapse; bool addedToCollapse; // do this as long as we find new ones // if we do not do this loop, we might miss something // as PredecessorIterator not necessarily honours topological order // (TODO this could be made more efficient) do { addedToCollapse = false; ComponentGraph::SuccessorIterator sit, sit_end; for(boost::tie(sit, sit_end) = compgraph.getProvides(comp); sit != sit_end; ++sit) { Component succ = compgraph.sourceOf(*sit); // skip successors with eatoms if( !compgraph.propsOf(succ).outerEatoms.empty() ) continue; // do not check found stuff twice if( collapse.find(succ) != collapse.end() ) continue; DBGLOG(DBG,"found successor " << succ); ComponentGraph::PredecessorIterator pit, pit_end; bool good = true; for(boost::tie(pit, pit_end) = compgraph.getDependencies(succ); pit != pit_end; ++pit) { Component dependson = compgraph.targetOf(*pit); if( preds.find(dependson) == preds.end() ) { LOG(DBG,"successor bad as it depends on other node " << dependson); good = false; break; } } if( good ) { // collapse with this collapse.insert(succ); preds.insert(succ); addedToCollapse = true; } } } while(addedToCollapse); // collapse if not nonempty if( !collapse.empty() ) { collapse.insert(comp); Component c = compgraph.collapseComponents(collapse); LOG(ANALYZE,"collapse of " << printrange(collapse) << " yielded new component " << c); // restart loop after collapse cit = compgraph.getComponents().first; didSomething = true; } } } // // forall components with only inner rules or constraints: // merge with children that are no eatoms and do not depend on anything else // { ComponentIterator cit = compgraph.getComponents().first; while(cit != compgraph.getComponents().second) { Component comp = *cit; if( !compgraph.propsOf(comp).outerEatoms.empty() ) { cit++; continue; } LOG(ANALYZE,"checking whether to collapse internal-only component " << comp << " with children"); // get successors ComponentSet collapse; ComponentGraph::SuccessorIterator sit, sit_end; for(boost::tie(sit, sit_end) = compgraph.getProvides(comp); sit != sit_end; ++sit) { Component succ = compgraph.sourceOf(*sit); // skip successors with eatoms if( !compgraph.propsOf(succ).outerEatoms.empty() ) continue; DBGLOG(DBG,"found successor " << succ); ComponentGraph::PredecessorIterator pit, pit_end; boost::tie(pit, pit_end) = compgraph.getDependencies(succ); bool good = true; assert(pit != pit_end); if( compgraph.targetOf(*pit) != comp ) { LOG(DBG,"successor bad as it depends on other node " << compgraph.targetOf(*pit)); good = false; } pit++; if( pit != pit_end ) { good = false; LOG(DBG,"successor bad as it depends on more nodes"); } if( good ) collapse.insert(succ); } if( !collapse.empty() ) { // collapse! (decreases graph size) collapse.insert(comp); assert(collapse.size() > 1); Component c = compgraph.collapseComponents(collapse); LOG(ANALYZE,"collapse of " << printrange(collapse) << " yielded new component " << c); // restart loop after collapse cit = compgraph.getComponents().first; didSomething = true; } else { // advance ++cit; } } } // // forall components with only inner rules or constraints: // merge with components that depend on exactly the same predecessors // { ComponentIterator cit = compgraph.getComponents().first; while(cit != compgraph.getComponents().second) { Component comp = *cit; if( !compgraph.propsOf(comp).outerEatoms.empty() ) { cit++; continue; } LOG(ANALYZE,"checking whether to collapse internal-only component " << comp << " with others"); ComponentSet collapse; // get direct predecessors ComponentSet preds; { ComponentGraph::PredecessorIterator pit, pit_end; for(boost::tie(pit, pit_end) = compgraph.getDependencies(comp); pit != pit_end; ++pit) { preds.insert(compgraph.targetOf(*pit)); } } if( preds.empty() ) { // do not combine stuff that depends only on edb cit++; continue; } // compare all further ones (further because of symmetry breaking) ComponentIterator cit2 = cit; cit2++; while( cit2 != compgraph.getComponents().second ) { Component comp2 = *cit2; DBGLOG(DBG,"checking other component " << comp2); ComponentSet preds2; { ComponentGraph::PredecessorIterator pit, pit_end; for(boost::tie(pit, pit_end) = compgraph.getDependencies(comp2); pit != pit_end; ++pit) { preds2.insert(compgraph.targetOf(*pit)); } } if( preds2 == preds ) collapse.insert(comp2); cit2++; } if( !collapse.empty() ) { // collapse! (decreases graph size) collapse.insert(comp); assert(collapse.size() > 1); Component c = compgraph.collapseComponents(collapse); LOG(ANALYZE,"collapse of " << printrange(collapse) << " yielded new component " << c); // restart loop after collapse cit = compgraph.getComponents().first; didSomething = true; } else { // advance ++cit; } } } // // forall components with only inner constraints: // merge with all other constraint-only components // if(false) { ComponentSet collapse; ComponentIterator cit; // do not use boost::tie here! the container is modified in the loop! for(cit = compgraph.getComponents().first; cit != compgraph.getComponents().second; ++cit) { Component comp = *cit; if( compgraph.propsOf(comp).outerEatoms.empty() && compgraph.propsOf(comp).innerRules.empty() ) collapse.insert(comp); } if( !collapse.empty() ) { // collapse! (decreases graph size) LOG(ANALYZE,"collapsing constraint-only nodes " << printrange(collapse)); Component c = compgraph.collapseComponents(collapse); didSomething = true; } } } while(didSomething); // // create eval units using topological sort // ComponentContainer sortedcomps; evalheur::topologicalSortComponents(compgraph.getInternalGraph(), sortedcomps); LOG(ANALYZE,"now creating evaluation units from components " << printrange(sortedcomps)); for(ComponentContainer::const_iterator it = sortedcomps.begin(); it != sortedcomps.end(); ++it) { // just create a unit from each component (we collapsed above) std::list<Component> comps; comps.push_back(*it); std::list<Component> ccomps; EvalGraphBuilder::EvalUnit u = builder.createEvalUnit(comps, ccomps); LOG(ANALYZE,"component " << *it << " became eval unit " << u); } }