bool CG::valid_solution(){ typedef boost::adjacency_list<vecS, vecS, directedS> Graph; Graph G(n_vertex_); for (int ii = 0; ii < n_vertex_; ii++) { if (not g_[ii].to_delete) { for (int jj = 0; jj < g_[ii].num_edges; jj++) { int to_id = g_[ii].edges[jj].to_id; if (not g_[to_id].to_delete) { add_edge(ii, to_id, G); } } } } vector<int> components(n_vertex_, -1); int num = strong_components(G, &components[0]); // check each connected component being a simple component vector<vector<int> > sccs; sccs.resize(num); for (int ii = 0; ii < n_vertex_; ii++){ assert(components[ii] < num); assert(components[ii] >= 0); sccs[components[ii]].push_back(ii); } for (int ii = 0; ii < num; ii++) { bool none_special_edges = exist_no_special_edge(sccs[ii]); if (none_special_edges) { return false; } } return true; };
inline typename property_traits<ComponentMap>::value_type strong_components(const Graph& g, ComponentMap comp) { typedef typename graph_traits<Graph>::directed_category DirCat; BOOST_STATIC_ASSERT((is_convertible<DirCat*, directed_tag*>::value == true)); bgl_named_params<int, int> params(0); return strong_components(g, comp, params); }
int main(void) { graph g; read_graph(&g, TRUE); print_graph(&g); strong_components(&g); return 0; }
void SFUtils::DoTopologicalSort( SLSF::Subsystem subsystem ) { int vertexIndex = 0; VertexIndexBlockMap vertexIndexBlockMap; BlockVertexIndexMap blockVertexIndexMap; BlockVector blockVector = subsystem.Block_kind_children(); for( BlockVector::iterator blvItr = blockVector.begin(); blvItr != blockVector.end(); ++blvItr, ++vertexIndex ) { SLSF::Block block = *blvItr; vertexIndexBlockMap[ vertexIndex ] = block; blockVertexIndexMap[ block ] = vertexIndex; std::string blockType = block.BlockType(); if ( blockType == "UnitDelay" ) { // check on other delay blocks as well ... ++vertexIndex; // UnitDelay is vertexed twice - one for outputs (timestep n-1), and one for inputs: vertexIndex is as destination, vertexIndex + 1 is as source } } Graph graph( vertexIndex ); LineSet lineSet = subsystem.Line_kind_children(); for( LineSet::iterator lnsItr = lineSet.begin(); lnsItr != lineSet.end() ; ++lnsItr ) { SLSF::Line line = *lnsItr; SLSF::Port sourcePort = line.srcLine_end(); SLSF::Port destinationPort = line.dstLine_end(); SLSF::Block sourceBlock = sourcePort.Block_parent(); SLSF::Block destinationBlock = destinationPort.Block_parent(); if ( sourceBlock == subsystem || destinationBlock == subsystem ) continue; int sourceBlockVertexIndex = blockVertexIndexMap[ sourceBlock ]; if ( static_cast< std::string >( sourceBlock.BlockType() ) == "UnitDelay" ) { ++sourceBlockVertexIndex; } int destinationBlockVertexIndex = blockVertexIndexMap[ destinationBlock ]; boost::add_edge( sourceBlockVertexIndex, destinationBlockVertexIndex, graph ); } LoopDetector loopDetector( graph ); if ( loopDetector.check() ) { // TODO: add support for loops involving integrator and other stateful blocks // Determine what Blocks caused the loop typedef std::map< Vertex, int > VertexStrongComponentIndexMap; VertexStrongComponentIndexMap vertexStrongComponentIndexMap; boost::associative_property_map< VertexStrongComponentIndexMap > apmVertexStrongComponentIndexMap( vertexStrongComponentIndexMap ); strong_components( graph, apmVertexStrongComponentIndexMap ); typedef std::vector< Vertex > VertexVector; typedef std::map< int, VertexVector > StrongComponentIndexVertexGroupMap; StrongComponentIndexVertexGroupMap strongComponentIndexVertexGroupMap; for( VertexStrongComponentIndexMap::iterator vsmItr = vertexStrongComponentIndexMap.begin(); vsmItr != vertexStrongComponentIndexMap.end(); ++vsmItr ) { strongComponentIndexVertexGroupMap[ vsmItr->second ].push_back( vsmItr->first ); } std::string error( "Dataflow Graph '" + static_cast< std::string >( subsystem.Name() ) + "' has unhandled loops: " ); for( StrongComponentIndexVertexGroupMap::iterator svmItr = strongComponentIndexVertexGroupMap.begin(); svmItr != strongComponentIndexVertexGroupMap.end(); ++svmItr ) { VertexVector vertexVector = svmItr->second; if ( vertexVector.size() <= 1 ) continue; error.append( "\n" ); for( VertexVector::iterator vtvItr = vertexVector.begin(); vtvItr != vertexVector.end(); ++vtvItr ) { error.append( blockVector[ *vtvItr ].getPath("/") ); error.append( ", " ); } error.erase( error.size() - 2 ); } throw udm_exception(error); } typedef std::set< Vertex > VertexSet; typedef std::map< int, VertexSet > PriorityVertexSetMap; PriorityVertexSetMap priorityVertexSetMap; for( BlockVector::iterator blvItr = blockVector.begin() ; blvItr != blockVector.end() ; ++blvItr ) { SLSF::Block block = *blvItr; int priority = block.Priority(); if ( priority == 0 ) continue; Vertex vertex = blockVertexIndexMap[ block ]; priorityVertexSetMap[ priority ].insert( vertex ); } if ( priorityVertexSetMap.size() > 1 ) { PriorityVertexSetMap::iterator lstPvmItr = priorityVertexSetMap.end(); --lstPvmItr; for( PriorityVertexSetMap::iterator pvmItr = priorityVertexSetMap.begin() ; pvmItr != lstPvmItr ; ) { PriorityVertexSetMap::iterator nxtPvmItr = pvmItr; ++nxtPvmItr; VertexSet &higherPriorityVertexSet = pvmItr->second; VertexSet &lowerPriorityVertexSet = nxtPvmItr->second; for( VertexSet::iterator hvsItr = higherPriorityVertexSet.begin() ; hvsItr != higherPriorityVertexSet.end() ; ++hvsItr ) { for( VertexSet::iterator lvsItr = lowerPriorityVertexSet.begin() ; lvsItr != lowerPriorityVertexSet.end() ; ++lvsItr ) { boost::add_edge( *hvsItr, *lvsItr, graph ); LoopDetector loopDetector( graph ); if ( loopDetector.check( *hvsItr ) ) { SLSF::Block higherPriorityBlock = vertexIndexBlockMap[ *hvsItr ]; SLSF::Block lowerPriorityBlock = vertexIndexBlockMap[ *lvsItr ]; std::cerr << "WARNING: Cannot implement priority difference between block \"" << higherPriorityBlock.getPath( "/" ) << "\" (Priority = " << *hvsItr << ") and " << std::endl; std::cerr << " block \"" << lowerPriorityBlock.getPath( "/" ) << "\" (Priority = " << *lvsItr << "): contradicts topology of subsystem or other implemented block priority order." << std::endl; boost::remove_edge( *hvsItr, *lvsItr, graph ); } } } pvmItr = nxtPvmItr; } } VertexList vertexList; boost::topological_sort( graph, std::back_inserter( vertexList ) ); /* PUT ALL "DataStoreMemory" BLOCKS AT END OF "C" SO THEY HAVE HIGHEST PRIORITY */ VertexList::reverse_iterator vtlRit = vertexList.rbegin(); while( vtlRit != vertexList.rend() ) { int index = *vtlRit; SLSF::Block block = vertexIndexBlockMap[ index ]; (void)++vtlRit; if ( block != Udm::null && static_cast< std::string >( block.BlockType() ) == "DataStoreMemory" ) { VertexList::reverse_iterator vtlRit2 = vtlRit; vertexList.splice( vertexList.end(), vertexList, vtlRit2.base() ); } } int priority = 0; for( VertexList::reverse_iterator vtlRit = vertexList.rbegin() ; vtlRit != vertexList.rend() ; ++vtlRit ) { int index = *vtlRit; SLSF::Block block = vertexIndexBlockMap[ index ]; if ( block == Udm::null ) { // unit delay as source is not registered - we will invoke it initially, and invoke it as destination in the priority order // const std::string& bt = blk.BlockType(); // assert(bt.compare("UnitDelay") == 0); /* Unit Delay Block as destination */ continue; } block.Priority() = priority++; } }
void CG::round_lp_greedy(vector<int> nodes){ // step0 decide if the sub-problem is solved already map<int, int> ori_2_new_map; for (int ii = 0; ii < nodes.size(); ii++) { ori_2_new_map[nodes[ii]] = ii; } double total_probs = 0.0; // care should be taken when dealing with nodes that have been deleted already vector<double> probs; probs.resize(nodes.size()); for (int ii = 0; ii < nodes.size(); ii++) { if (g_[nodes[ii]].to_delete) { probs[ii] = 0.0; } else { probs[ii] = g_[nodes[ii]].nor_dual_val; total_probs = total_probs + probs[ii]; } } bool exist_none_special_edges = exist_no_special_edge(nodes); if (not exist_none_special_edges) { return; } // step1: sample one node to delete // use a greedy approach to decide which node to delete int delete_index = -1; double max_prob = 0.0; for (int ii = 0; ii < nodes.size(); ii++) { if (probs[ii] > max_prob) { delete_index = ii; max_prob = probs[ii]; } } assert(delete_index != -1); // step2: delete the vertex g_[nodes[delete_index]].to_delete = true; // step 3: construct a graph. Find out the strongly connected components typedef boost::adjacency_list<vecS,vecS,directedS> Graph; Graph G(nodes.size()); for (int ii = 0; ii < nodes.size(); ii++) { if (not g_[nodes[ii]].to_delete) { for (int jj = 0; jj < g_[nodes[ii]].num_edges; jj++) { int to_id = g_[nodes[ii]].edges[jj].to_id; if ((ori_2_new_map.find(to_id) != ori_2_new_map.end()) and (not g_[to_id].to_delete)) { add_edge(ii, ori_2_new_map[to_id], G); } } } } vector<int> components(nodes.size(),-1); int num = strong_components(G,&components[0]); // step4: recurse vector<vector<int> > sccs; sccs.resize(num); for (int ii = 0; ii < nodes.size(); ii++){ assert(components[ii] < num); assert(components[ii] >= 0); sccs[components[ii]].push_back(nodes[ii]); } for (int ii = 0; ii < num; ii++) { round_lp_greedy(sccs[ii]); } };
void CG::round_lp_randomized(vector<int> nodes){ // step0 decide if the sub-problem is solved already map<int, int> ori_2_new_map; for (int ii = 0; ii < nodes.size(); ii++) { ori_2_new_map[nodes[ii]] = ii; } double total_probs = 0.0; // care should be taken when dealing with nodes that have been deleted already vector<double> probs; probs.resize(nodes.size()); for (int ii = 0; ii < nodes.size(); ii++) { if (g_[nodes[ii]].to_delete) { probs[ii] = 0.0; } else { probs[ii] = g_[nodes[ii]].nor_dual_val; total_probs = total_probs + probs[ii]; } } bool exist_none_special_edges = exist_no_special_edge(nodes); if (not exist_none_special_edges) { return; } // step1: sample one node to delete // random_double is a number between 0 and total_probs double random_double = ((rand() + 0.5) / (double(RAND_MAX) + 1)) * total_probs; cout << "dbg print:random_double" << random_double / total_probs << endl; double accumulated_probs = 0.0; int delete_index; for (int ii = 0; ii < nodes.size(); ii++) { delete_index = ii; if (probs[ii] == 0.0) continue; accumulated_probs = accumulated_probs + probs[ii]; if (accumulated_probs > random_double) break; } // step2: delete the vertex g_[nodes[delete_index]].to_delete = true; // step 3: construct a graph. Find out the strongly connected components typedef boost::adjacency_list<vecS,vecS,directedS> Graph; Graph G(nodes.size()); for (int ii = 0; ii < nodes.size(); ii++) { if (not g_[nodes[ii]].to_delete) { for (int jj = 0; jj < g_[nodes[ii]].num_edges; jj++) { int to_id = g_[nodes[ii]].edges[jj].to_id; if ((ori_2_new_map.find(to_id) != ori_2_new_map.end()) and (not g_[to_id].to_delete)) { add_edge(ii, ori_2_new_map[to_id], G); } } } } vector<int> components(nodes.size(),-1); int num = strong_components(G,&components[0]); // step4: recurse vector<vector<int> > sccs; sccs.resize(num); for (int ii = 0; ii < nodes.size(); ii++){ assert(components[ii] < num); assert(components[ii] >= 0); sccs[components[ii]].push_back(nodes[ii]); } for (int ii = 0; ii < num; ii++) { round_lp_randomized(sccs[ii]); } };