// 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); } }
int main(int argc, char *argv[]) { ros::init(argc, argv, "hello_world_node"); ros::NodeHandle n("~"); mcr_robinson::helloworld::IHelloWorld* hello_world = new mcr_robinson::helloworld::HelloWorldImpl(); // Connect ports from hello world component EVENT_OUTPUT(hello_world->eventport_output_done).connect( EVENT_INPUT_ROS("event_out", "e_done")); DATAPORT_OUTPUT_ROS(std_msgs::String, std::string, "pin_name").connect( DATAPORT_INPUT(&mcr_robinson::helloworld::IHelloWorld::dataport_input_name, hello_world) ); DATAPORT_OUTPUT(hello_world->dataport_output_answer).connect( DATAPORT_INPUT_ROS(std_msgs::String, std::string, "pout_answer")); ComponentContainer<mcr_robinson::helloworld::IHelloWorld>* container = new ComponentContainer<mcr_robinson::helloworld::IHelloWorld>(hello_world); // Connect events to container EVENT_OUTPUT_ROS("event_in", "e_start").connect( EVENT_INPUT(&ComponentContainer<mcr_robinson::helloworld::IHelloWorld>::eventport_input_start, container) ); EVENT_OUTPUT_ROS("event_in", "e_stop").connect( EVENT_INPUT(&ComponentContainer<mcr_robinson::helloworld::IHelloWorld>::eventport_input_stop, container) ); //Connect data ports to container // trigger update event on incomming data DataPortEvent<std::string>* data_trigger = new DataPortEvent<std::string>( EVENT_INPUT(&ComponentContainer<mcr_robinson::helloworld::IHelloWorld>::update_on_data,container)); DATAPORT_OUTPUT_ROS(std_msgs::String, std::string, "pin_name").connect( *data_trigger ); // choose the operating mode container->setMode(ON_DATA_EVENT); //container->setMode(ON_UPDATE_EVENT); ros::Rate loop_rate(20); while (ros::ok()) { // call the update cycle every iteration container->update_cycle(); ros::spinOnce(); loop_rate.sleep(); } delete container; delete hello_world; delete data_trigger; return 0; }