void LazyConstraintCallback::processGraph( int index ) { Graph const & graph = graphs.graph( index ); GraphVariables const & vars = graphs.variables( index ); IloNumArray x_values{ getEnv(), vars.xVars.getSize() }; getValues( x_values, vars.xVars ); IloNumArray y_values{ getEnv(), vars.yVars.getSize() }; getValues( y_values, vars.yVars ); //printNonZeroX( x_values, index ); //printNonZeroY( y_values, index ); int nCuts = 0; NodeSetVector nonZeroNodesComponents; constructNonZeroComponents( graph, vars, x_values, nonZeroNodesComponents ); if ( nonZeroNodesComponents.size() > 1 ) { Graph::Node root = determineRoot( graph, vars, y_values ); separateConnectedComponents( graph , vars , root , nonZeroNodesComponents , nCuts ); } x_values.end(); y_values.end(); //clog << "Generated " << nCuts << " cuts" << endl; }
void Callback::constructNonZeroComponents( Graph const & g , GraphVariables const & vars , IloNumArray x_values , NodeSetVector & nonZeroNodesComponents ) const { using NodeQueue = std::queue< Graph::Node >; NodeQueue queue; // -3 queued // -2 unvisited // -1 visited and zero // >= 0 visited and non-zero auto compMap = g.createNodeMap< int >( -2 ); int compIdx = 0; for ( Graph::Node n : g.nodes() ) { if ( compMap[n] == -2 && intIsNonZero( x_values[vars.nodeToIndex[n]] ) ) { queue.push( n ); compMap[n] = -3; nonZeroNodesComponents.emplace_back(); // perform bfs while ( !queue.empty() ) { Graph::Node n = queue.front(); assert( compMap[n] == -3 ); queue.pop(); compMap[n] = compIdx; nonZeroNodesComponents.back().insert( n ); for ( Graph::Edge e : g.incEdges( n ) ) { Graph::Node nn = g.oppositeNode( n, e ); if ( compMap[nn] == -2 ) { if ( intIsNonZero( x_values[vars.nodeToIndex[nn]] ) ) { queue.push( nn ); compMap[nn] = -3; } else { compMap[nn] = -1; } } } } ++compIdx; } } }
int TarjanHD::constructCondensedGraph(const Digraph& g, const DoubleArcMap& w, const NodeNodeMap& mapToOrgG, const NodeNodeMap& G2T, const ArcList& sortedArcs, const IntNodeMap& comp, const NodeSetVector& components, const NodeVector& roots, const int j, Digraph& c, DoubleArcMap& ww, NodeNodeMap& mapCToOrgG, NodeNodeMap& C2T, ArcList& newSortedArcs) { // construct the condensed graph: // each strongly connected component is collapsed into a single node, and // from the resulting sets of multiple arcs retain only those with minimum weight lemon::DynArcLookUp<Digraph> lookUpArc(c); // first construct the nodes const size_t numSCC = components.size(); NodeVector nodesOfC(numSCC, lemon::INVALID); for (size_t k = 0; k < numSCC; ++k) { Node v = nodesOfC[k] = c.addNode(); if (components[k].size() == 1) { mapCToOrgG[v] = mapToOrgG[*components[k].begin()]; C2T[v] = G2T[*components[k].begin()]; } else { mapCToOrgG[v] = lemon::INVALID; C2T[v] = roots[k]; } } // next construct the arcs: O(m) time for (ArcListIt arcIt = sortedArcs.begin(); arcIt != sortedArcs.end(); ++arcIt) { Arc a = *arcIt; Node u = g.source(a); Node v = g.target(a); Node uu = nodesOfC[comp[u]]; Node vv = nodesOfC[comp[v]]; if (uu != vv) { Arc aa = lookUpArc(uu, vv); if (aa == lemon::INVALID) { aa = c.addArc(uu, vv); newSortedArcs.push_back(aa); ww[aa] = w[a]; } #ifdef DEBUG else { assert(w[a] > ww[aa]); } #endif } } return get_i(newSortedArcs, ww, w[getArcByRank(sortedArcs, j)]); }