Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

cut.cc

00001 #ifndef SCIL_CUT_CC
00002 #define SCIL_CUT_CC
00003 
00004 #define HIDE_THRES 5
00005 
00006 using namespace SCIL;
00007 using std::cout;
00008 using std::cerr;
00009 using std::endl;
00010 
00012 /*  This visitor records the distances of the vertices and stores the order
00013     in which the vertices are discovered in the list bfs_order
00014  */
00015 template <typename Graph>
00016 class CUT<Graph>::bfs_dist_visitor : public default_bfs_visitor {
00017    public:
00018       bfs_dist_visitor(map<vertex_descriptor, int>* _distmap,
00019                        list<vertex_descriptor>* _bfs_order,
00020                        int start_vertex)
00021          : distmap(_distmap), bfs_order(_bfs_order) {
00022          (*distmap)[start_vertex] = 0;
00023          bfs_order->clear();
00024       }
00026       /* The source of e is the predecessor of the target of e, which is the
00027          newly discovered vertex.
00028        */
00029       void tree_edge(edge_descriptor e, const Graph &G) const {
00030          vertex_descriptor s = source(e, G), t = target(e, G);
00031          (*distmap)[t] = (*distmap)[s]+1;
00032       }
00034       void discover_vertex(vertex_descriptor u, const Graph &G) const {
00035          bfs_order->push_back(u);
00036       }
00038       map<vertex_descriptor, int> *distmap;
00040       list<vertex_descriptor> *bfs_order; 
00041 };
00042 
00043 template <typename Graph>
00044 void CUT<Graph>::undirected_bfs(Graph &H, vertex_descriptor r,
00045                                 map<vertex_descriptor, int> &dst,
00046                                 map<vertex_descriptor, edge_descriptor> &pred) {
00047    vertex_descriptor v;
00048    BGL_FORALL_VERTICES_T(v, H, Graph) {
00049       dst[v] = -1;
00050    }
00051    std::queue<vertex_descriptor> q;
00052    vertex_descriptor s, t;
00053    edge_descriptor e;
00054    dst[r] = 0;
00055    q.push(r);
00056    while( !q.empty() ) {
00057       s = q.front();
00058       q.pop();
00059       typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00060       for(tie(oe_it, oe_it_end)=out_edges(s,H); oe_it != oe_it_end; oe_it++) {
00061          t = target(*oe_it, H);
00062          if( dst[t] == -1 ) {
00063             dst[t] = dst[s] + 1;
00064             pred[t] = *oe_it;
00065             q.push(t);
00066          }
00067       }
00068    }
00069 }
00070 
00071 template <typename Graph, typename vertex_descriptor, typename edge_descriptor>
00072 bool color_graph(Graph& H, vertex_descriptor& r, 
00073                  map<edge_descriptor,double>& cut, 
00074                  map<vertex_descriptor, bool>& color) {
00075 
00076    typedef graph_traits<Graph> GraphTraits;
00077 
00078    map<vertex_descriptor, int> dst;
00079    vertex_descriptor v;
00080    BGL_FORALL_VERTICES_T(v, H, Graph) {
00081       dst[v] = -1;
00082       color[v] = false;
00083    }
00084 
00085    std::queue<vertex_descriptor> q;
00086    vertex_descriptor s, t;
00087    edge_descriptor e;
00088    dst[r] = 0;
00089    q.push(r);
00090    while( !q.empty() ) {
00091       s = q.pop();
00092       typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00093       for(tie(oe_it, oe_it_end)=out_edges(s, H); oe_it != oe_it_end; oe_it++) {
00094          if( cut[*oe_it] < -.5 )
00095             continue;
00096          (s == source(*oe_it,H)) ? t = target(*oe_it,H) : t = source(*oe_it,H);
00097          if( dst[t] == -1 ) {
00098             dst[t] = dst[s] + 1;
00099             if(cut[*oe_it] > .5)
00100                color[t] = !color[s];
00101             else
00102               color[t] = color[s];
00103             q.append(t);
00104          } else {
00105             if( (cut[*oe_it] > .5 && color[t] == color[s]) 
00106                  || cut[*oe_it] <= .5 && color[t] != color[s] )
00107                return false;
00108          }
00109       }
00110    }
00111    return true;
00112 }
00113 
00114 template <typename Graph>
00115 CUT<Graph>::CUT(Graph &G_, row_map<edge_descriptor> &VM_, int nc_)
00116    : G(G_), VM(VM_), updateConfiguration(false), nc(nc_), initialized(false) {
00117    edge_descriptor e;
00118    feps = .01;
00119 
00120    //Check whether Graph is undirected
00121    typedef typename GraphTraits::directed_category directed_category;
00122    bool graph_is_undirected = is_same<directed_category,undirected_tag>::value
00123       || is_base_and_derived<undirected_tag, directed_category>::value;
00124    BOOST_ASSERT(graph_is_undirected);
00125 
00126    BGL_FORALL_EDGES_T(e, G, Graph) {
00127       row_entry::list_iterator it;
00128       foreach( it, VM[e] )
00129          if( it->Var != NULL )
00130          if( it->Var.type() != Vartype_Binary ) {
00131              cerr << "cut.cc: All variables in VM need to be Vartype_Binary";
00132              cerr << endl;
00133              exit(1);
00134          }
00135    }
00136    //Graph has to provide vertices() and edges()
00137    BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00138    //Graph has to provide out_edges()
00139    BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<Graph>));
00140    //Graph has to provide clear_vertex()
00141    BOOST_CONCEPT_ASSERT((MutableGraphConcept<Graph>));
00142 
00143    //Compute connected components of G
00144    vector<int> component(num_vertices(G));
00145    int num_components = connected_components(G, &component[0]);
00146 
00147    //cout<<"Connected Components: "<<num_components<<endl;
00148    for(int i = 0; i < num_components; i++){
00149       row_map<edge_descriptor> tmpVM;
00150       Graph tmp(num_vertices(G));
00151       graph_components.push_back(tmp);
00152       Graph& U = graph_components.back();
00153       BGL_FORALL_EDGES_T(e, G, Graph)
00154          tmpVM[add_edge(source(e,G), target(e,G), U).first]=VM[e];
00155       for(int j = num_vertices(G) - 1; j >= 0 ; j--){
00156          if(component[j] != i){
00157             clear_vertex(vertices(U).first[j], U);
00158             remove_vertex(vertices(U).first[j], U);
00159          }
00160       }
00161       VML.push_back(tmpVM);
00162    }
00163 }
00164 
00165 template <typename Graph>
00166 int CUT<Graph>::generate_triangle_inequalities(subproblem& S) {
00167    if( S.configuration("CUT_Debug_Out")=="true" )
00168       cerr << "CUT::generate_triangle_inequalities\n";
00169 
00170    unordered_map<std::string, tuple<edge_descriptor, edge_descriptor, edge_descriptor> > tris;
00171 
00172    //Check if the Graph has at least 3 edges
00173    if(num_edges(G)<3)
00174       return 0;
00175 
00176    map<vertex_descriptor,int> vertex_index_map;
00177    int i = 0;
00178    BGL_FORALL_VERTICES_T(v, G, Graph)
00179       vertex_index_map[v] = i++;
00180    stringstream ss;
00181    int index1,index2,index3;
00182 
00183    typename GraphTraits::edge_iterator e_it, f_it, g_it, e_it_end;
00184 
00185    //Search triangles by checking all combinations of three adjacent edges
00186    for(tie(e_it, e_it_end) = edges(G); e_it != e_it_end; e_it++){
00187       for (typename GraphTraits::out_edge_iterator f_it = out_edges(target(*e_it, G), G).first; f_it != out_edges(target(*e_it, G), G).second; f_it++){
00188          for (typename GraphTraits::out_edge_iterator g_it = out_edges(target(*f_it, G), G).first; g_it != out_edges(target(*f_it, G), G).second; g_it++){
00189             if (target(*g_it, G) == source(*e_it, G)){
00190                index1 = min(vertex_index_map[target(*e_it, G)], min(vertex_index_map[target(*f_it, G)], vertex_index_map[target(*g_it, G)]));
00191                index3 = max(vertex_index_map[target(*e_it, G)], max(vertex_index_map[target(*f_it, G)], vertex_index_map[target(*g_it, G)]));
00192                index2 = vertex_index_map[target(*e_it, G)] + vertex_index_map[target(*f_it, G)] + vertex_index_map[target(*g_it, G)] - index1 - index3;
00193                ss.str("");
00194                ss.clear();
00195                ss<<index1<<"#"<<index2<<"#"<<index3;
00196                tris.insert(make_pair(ss.str(), tuple <edge_descriptor, edge_descriptor, edge_descriptor> (*e_it, *f_it, *g_it)));
00197             }
00198          }
00199       }
00200    }
00201 
00202    //create the inequalities and add them
00203    typename unordered_map<std::string, tuple<edge_descriptor, 
00204             edge_descriptor, 
00205             edge_descriptor> >::const_iterator triangle;
00206    int gen = 0;
00207    foreach(triangle, tris) {
00208       row r1, r2, r3, r4;
00209       r1 += VM[get<0>(triangle->second)];
00210       r1 -= VM[get<1>(triangle->second)];
00211       r1 -= VM[get<2>(triangle->second)];
00212 
00213       r2 += VM[get<0>(triangle->second)];
00214       r2 += VM[get<1>(triangle->second)];
00215       r2 += VM[get<2>(triangle->second)];
00216 
00217       r3 -= VM[get<0>(triangle->second)];
00218       r3 += VM[get<1>(triangle->second)];
00219       r3 -= VM[get<2>(triangle->second)];
00220 
00221       r4 -= VM[get<0>(triangle->second)];
00222       r4 -= VM[get<1>(triangle->second)];
00223       r4 += VM[get<2>(triangle->second)];
00224 
00225       S.add_basic_constraint(r1<=0., Dynamic);
00226       S.add_basic_constraint(r2<=2., Dynamic);
00227       S.add_basic_constraint(r3<=0., Dynamic);
00228       S.add_basic_constraint(r4<=0., Dynamic);
00229       gen += 4;
00230    }
00231    return 0;
00232 }
00233 
00234 template <typename Graph>
00235 void CUT<Graph>::init(subproblem& S) {
00236    if( S.configuration("CUT_Debug_Out")=="true" )
00237       cerr << "CUT::init\n";
00238    //Check whether Graph is undirected
00239    typedef typename GraphTraits::directed_category directed_category;
00240    bool graph_is_undirected = is_same<directed_category,undirected_tag>::value
00241       || is_base_and_derived<undirected_tag, directed_category>::value;
00242    BOOST_ASSERT(graph_is_undirected);
00243    generate_triangle_inequalities(S);
00244    return;
00245 };
00246 
00247 template <typename Graph>
00248 void CUT<Graph>::initAuxGraph(solution S) {
00249    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00250       cerr << "CUT::initAuxGraph\n";
00251 
00252    G1.clear();
00253    back.clear();
00254    GtoG1a.clear();
00255    GtoG1b.clear();
00256    G1toG.clear();
00257    isCrossEdge.clear();
00258    vertex_descriptor v;
00259    edge_descriptor e;
00260 
00261    /* G1 consists of two copies G' and G" of the original graph G. */
00262    BGL_FORALL_VERTICES_T (v, G, Graph) {
00263       GtoG1a[v] = add_vertex(G1);
00264       GtoG1b[v] = add_vertex(G1);
00265       G1toG[GtoG1a[v]] = v;
00266       G1toG[GtoG1b[v]] = v;
00267    }
00268 
00269    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00270       cerr << "initAuxGraph: nodes added\n";
00271 
00272    vertex_descriptor s, t;
00273 
00274    /* G' and G" each contain copies of the original edges
00275       and are joined by cross edges v' -- v" and v" -- v'
00276       for every node v of the original graph G. */
00277    BGL_FORALL_EDGES_T (e, G, Graph) {
00278       edge_descriptor f;
00279       s = source(e,G);
00280       t = target(e,G);
00281       f = (add_edge(GtoG1a[s], GtoG1a[t], G1)).first;
00282       back[f] = e;
00283       isCrossEdge[f] = false;
00284       f = (add_edge(GtoG1b[s], GtoG1b[t], G1)).first;
00285       back[f] = e;
00286       isCrossEdge[f] = false;
00287       f = (add_edge(GtoG1a[s], GtoG1b[t], G1)).first;
00288       back[f] = e;
00289       isCrossEdge[f] = true;
00290       f = (add_edge(GtoG1b[s], GtoG1a[t], G1)).first;
00291       back[f] = e;
00292       isCrossEdge[f] = true;
00293    }
00294 
00295    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00296       cerr << "initAuxGraph: G1 initialized\n";
00297 
00298    initialized = true;
00299    return;
00300 }
00301 
00302 template <typename Graph>
00303 int CUT<Graph>::exactCycleSeparation(solution& S, 
00304                                      int maxnum, 
00305                                      std::list<cons_obj*>& newCons) {
00306    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00307       cerr << "CUT::exactCycleSeparation\n";
00308 
00309    initAuxGraph(S);
00310 
00311    //Typedefs for Dijkstra In- and Output
00312    typedef map<edge_descriptor, double> costs_t;
00313    typedef map<vertex_descriptor, size_t> vertex_index_t;
00314    typedef map<vertex_descriptor, double> dist_t;
00315    typedef map<vertex_descriptor, vertex_descriptor> pred_t;
00316 
00317    vertex_descriptor v;
00318    map<vertex_descriptor, int> node_used;
00319    BGL_FORALL_VERTICES_T(v, G, Graph)
00320       node_used[v] = 0;
00321 
00322    double leps = .001;
00323    row lastCon = nil;
00324  
00325    edge_descriptor e;
00326    costs_t costs;
00327    BGL_FORALL_EDGES_T(e, G1, Graph) {
00328       if( isCrossEdge[e] )
00329          costs[e] = 1. - S.value(VM[back[e]]);
00330       else
00331          costs[e] = S.value(VM[back[e]]);
00332       if( costs[e] < 0. ) costs[e] = 0.;
00333       //assert(costs[e]>=0.);
00334       //assert(costs[e]<=1.);
00335    }
00336    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00337       cerr << "exactCycleSeparation: costs initialized\n";
00338 
00339    /* Shortest paths between two nodes v' and v" in G1 with weight < 1 
00340       correspond to violated odd cycle inequalities. */
00341    vector<vertex_descriptor> ln;
00342    BGL_FORALL_VERTICES_T(v, G, Graph)
00343       ln.push_back(v);
00344    int nn = num_vertices(G);
00345    if( nc > 0 ) {
00346       random_shuffle(ln.begin(), ln.end());
00347       nn = num_vertices(G)/nc;
00348    }
00349 
00350    //Vertex_index_map is needed if vertices are stored in a std::list
00351    vertex_index_t vertex_index_map;
00352    int i = 0;
00353    BGL_FORALL_VERTICES_T(v, G1, Graph)
00354       vertex_index_map[v] = i++;
00355    int numfound = 0;
00356    //Stores predecessor of vertices
00357    pred_t pred;
00358    //Stores distance of vertices to source vertex
00359    dist_t dist;
00360    vertex_descriptor s,t;
00361 
00362    //Property-maps required for Dijkstra
00363    associative_property_map<costs_t> pm_costs(costs);
00364    associative_property_map<vertex_index_t> pm_vertex_index(vertex_index_map);
00365    associative_property_map<pred_t> pm_pred(pred);
00366    associative_property_map<dist_t> pm_dist(dist);
00367 
00368    int ntc = 0;
00369 
00370    //Create copy of Graph G
00371    Graph G2;
00372    map<vertex_descriptor, vertex_descriptor> GtoG2;
00373    BGL_FORALL_VERTICES_T(v, G, Graph)
00374       GtoG2[v] = add_vertex(G2);
00375    BGL_FORALL_EDGES_T(e, G, Graph)
00376       add_edge(GtoG2[source(e,G)], GtoG2[target(e,G)], G2);
00377 
00378    BOOST_FOREACH(v, ln) {
00379       if( numfound >= maxnum || ntc >= nn )
00380          break;
00381       /* Hide nodes that have already been used in several constraints. Since
00382          the adjacency_list does not provide functionality to hide vertices
00383          the edges adjacent to the vertices are removed, so that the nodes will
00384          not be used again by Dijkstra and the vertex_iterators remain intact.
00385        */
00386       BGL_FORALL_VERTICES_T(s, G, Graph) {
00387          if( node_used[s] > HIDE_THRES && out_degree(GtoG2[s], G2) != 0 ) {
00388             clear_vertex(GtoG2[s], G2);
00389             clear_vertex(GtoG1a[s], G1);
00390             clear_vertex(GtoG1b[s], G1);
00391          }
00392       }
00393 
00394       // Degree of 0 = hidden vertex
00395       if( out_degree(GtoG2[v], G2) == 0 ) 
00396          continue;
00397 
00398       ntc++;
00399 
00400       s = GtoG1a[v];
00401       t = GtoG1b[v];
00402 
00403       dijkstra_shortest_paths(G1, s, weight_map(pm_costs).vertex_index_map
00404          (pm_vertex_index).distance_map(pm_dist).predecessor_map(pm_pred));
00405       double w = dist[t];
00406 
00407       if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00408          cerr << "exactCycleSeparation: DIJKSTRA w:" << w << endl;
00409       if( (w < 1. - leps) && (pred[t] != t) ) {
00410          // Follow the path starting with pred[t] until s is reached
00411          bool duplicates = false;
00412          list<edge_descriptor> cycle;
00413          map<edge_descriptor, bool> oddset;
00414          BGL_FORALL_EDGES_T(e, G, Graph)
00415             oddset[e] = false;
00416          map<vertex_descriptor, bool> seen;
00417          BGL_FORALL_VERTICES_T(v, G, Graph)
00418             seen[v] = false;
00419          row r;
00420          vertex_descriptor a, b;
00421          double rhs = -1.;
00422 
00423          /* Mark the start node. */
00424          seen[G1toG[t]] = true;
00425          node_used[G1toG[t]]++;
00426 
00427          edge_descriptor f;
00428          while( !duplicates ) {
00429             e = (edge(t, pred[t], G1)).first;
00430             f = back[e];
00431             /* Append the edge of the original graph to the cycle list. */
00432             cycle.push_back(f);
00433 
00434             /* Mark the original edge as belonging to the odd set or not. */
00435             if ( isCrossEdge[e] ) {
00436                r += VM[f];
00437                rhs += 1.;
00438                oddset[f] = true;
00439             }
00440             else
00441                r -= VM[f];
00442 
00443             /* Determine the nodes in the original graph. */
00444             a = G1toG[t];
00445             b = G1toG[pred[t]];
00446             if( seen[b] )
00447                duplicates = true;
00448             else {
00449                seen[b] = true;
00450                node_used[b]++;
00451             }
00452 
00453             t = pred[t];
00454          }
00455 
00456          /* If b is the start node, we are done.
00457             Otherwise we have to remove edges from the front of the path 
00458             until we reach the first duplicate node.
00459             We also have to adapt the constraint. */
00460            s = G1toG[s];
00461          if( b != s ) {
00462             do {
00463                e = cycle.front();
00464                cycle.pop_front();            
00465                if( oddset[e] ) {
00466                   r -= VM[e];
00467                   rhs -= 1.;
00468                }
00469                else 
00470                   r += VM[e];
00471 
00472                node_used[source(e, G)]--;
00473                node_used[target(e, G)]--;
00474             } while((source(e, G) != b) && (target(e, G) != b));
00475             node_used[b]++;
00476          }
00477          /* Add the constraint to the subproblem. */
00478          r.normalize(true);
00479          cons_obj* c = (r<=rhs);
00480          //FIXME compare
00481          if( c->violation(S) > feps && compare(r, lastCon) != 0 ) {
00482             lastCon = r;
00483             newCons.push_back(r<=rhs);
00484             if(S.originating_subproblem()->configuration("CUT_Debug_Out")=="true")
00485                if( rhs <= -1.)
00486                   cerr << r << " <= " << rhs << endl;
00487             numfound++;
00488             if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00489                cerr << "exactCycleSeparation: added constraint! rhs = " << 1 << 1 << rhs << endl;
00490          }
00491          delete c;
00492       }
00493    }
00494    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00495       cerr << "exactCycleSeparation: constraints added:" << 1 << 0 << numfound << endl;
00496 
00497    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00498       cerr << "numfound: " << numfound << endl;
00499    return numfound;
00500 }
00501 
00502 template <typename Graph>
00503 int CUT<Graph>::forestCycleSeparation(solution& S, int maxnum, 
00504       list<cons_obj*>& newCons) {
00505    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00506       cerr << "CUT::forestCycleSeparation\n";
00507 
00508    int numfound = 0;
00509    
00510    typename list<row_map<edge_descriptor> >::iterator it2 = VML.begin();
00511 
00512    for(typename list<Graph>::iterator it=graph_components.begin(); it != graph_components.end(); it++){
00513 
00514       Graph& G = *it;
00515       row_map<edge_descriptor> VM = *it2;
00516 
00517       //Typedefs for MST INPUT
00518       typedef map<edge_descriptor, double> weight_map_t;
00519       typedef map<vertex_descriptor, size_t> vertex_index_t;   
00520 
00521       //compute a spanning tree of maximum fractionality
00522       weight_map_t tc;
00523       vertex_descriptor v, s, t;
00524       edge_descriptor e;
00525       BGL_FORALL_EDGES_T(e, G, Graph){
00526          //negative weights because we need a maximum spanning tree
00527          tc[e] = - fabs(S.value(VM[e]) - .5);
00528       }
00529       vertex_index_t vertex_index_map;
00530       int i = 0;
00531       BGL_FORALL_VERTICES_T(v, G, Graph)
00532          vertex_index_map[v] = i++;
00533 
00534       //Property-maps required by MST
00535       associative_property_map<weight_map_t> pm_weight(tc);
00536       associative_property_map<vertex_index_t> pm_vertex_index(vertex_index_map);
00537 
00538       list<edge_descriptor> tree;
00539 
00540 
00541       vector < vertex_descriptor> p(num_vertices(G));
00542 
00543       kruskal_minimum_spanning_tree(G, back_inserter(tree), boost::weight_map
00544             (pm_weight).vertex_index_map(pm_vertex_index));
00545 
00546       if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00547          cerr << "CUT::forestCycleSeparation: MIN_SPANNING_TREE computed\n";
00548 
00549       Graph T;
00550       map<vertex_descriptor, vertex_descriptor> TtoG, GtoT;
00551       BGL_FORALL_VERTICES_T(v, G, Graph) {
00552          t = add_vertex(T);
00553          TtoG[t] = v;
00554          GtoT[v] = t;
00555       }
00556       map<edge_descriptor, edge_descriptor> edgeTtoG;
00557       BOOST_FOREACH(e, tree)
00558          edgeTtoG[(add_edge(GtoT[source(e, G)], GtoT[target(e, G)], T)).first] = e;
00559 
00560       if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00561          cerr << "CUT::forestCycleSeparation: Graph Copy T created\n";
00562 
00563       map<vertex_descriptor, int> dst;
00564       map<vertex_descriptor, edge_descriptor> pred;
00565       //FIXME choose start node
00566       undirected_bfs(T, *(vertices(T).first), dst, pred);
00567 
00568       if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00569          cerr << "CUT::forestCycleSeparation: undirected_bfs done\n";
00570 
00571       // construct the fundamental cycles induced by the non-tree edges
00572       // and check whether a violated cycle inequality has been found
00573       BGL_FORALL_EDGES_T(e, G, Graph) {
00574          bool edgeInTree = false;
00575          edge_descriptor f;
00576          BOOST_FOREACH(f, tree)
00577             if (f == e) edgeInTree = true;
00578          if( edgeInTree )
00579             continue;
00580          if( numfound >= maxnum )
00581             break;
00582          s = GtoT[source(e, G)];
00583          t = GtoT[target(e, G)];
00584          int offset = dst[s] - dst[t];
00585          v = s;
00586          if( dst[s] - dst[t] < 0 ) {
00587             offset *= -1;
00588             v = t;
00589          }
00590          if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00591             cerr << "CUT::forestCycleSeparation: offset computed\n";
00592          if( offset > 5 )
00593             continue;
00594          row r;
00595          double rhs = -1;
00596          if( S.value(VM[e]) > .5 ) {
00597             r += VM[e];
00598             rhs += 1.;
00599          }
00600          else
00601             r -= VM[e];
00602          if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00603             cerr << "CUT::forestCycleSeparation: initial edge added\n";
00604 
00605          for( int i = 0; i < offset; i++ ) {
00606             if( S.value(VM[edgeTtoG[pred[v]]]) > .5 ) {
00607                r += VM[edgeTtoG[pred[v]]];
00608                rhs += 1.;
00609             }
00610             else 
00611                r -= VM[edgeTtoG[pred[v]]];
00612             (v == source(pred[v], T)) ? v = target(pred[v], T) 
00613                : v = source(pred[v], T);
00614          }
00615          if( dst[s] - dst[t] < 0 )
00616             t = v;
00617          else
00618             s = v;
00619 
00620          while( s != t ) {
00621             if( S.value(VM[edgeTtoG[pred[s]]]) > .5 ) {
00622                r += VM[edgeTtoG[pred[s]]];
00623                rhs += 1.;
00624             }
00625             else 
00626                r -= VM[edgeTtoG[pred[s]]];
00627 
00628             if( S.value(VM[edgeTtoG[pred[t]]]) > .5 ) {
00629                r += VM[edgeTtoG[pred[t]]];
00630                rhs += 1.;
00631             }
00632             else 
00633                r -= VM[edgeTtoG[pred[t]]];
00634             (s == source(pred[s], T)) ? s = target(pred[s], T) 
00635                : s = source(pred[s], T);
00636             (t == source(pred[t], T)) ? t = target(pred[t], T) 
00637                : t = source(pred[t], T);
00638          }
00639 
00640          r.normalize();
00641          //FIXME length
00642          if( !(int(rhs) % 2) ) { //&& r.size() < 20 ) 
00643             cons_obj* c = (r<=rhs);
00644             if( c->violation(S) > feps ) {
00645                newCons.push_back(r<=rhs);
00646                numfound++;
00647             }
00648             delete c;
00649          }
00650       }
00651       it2++;//connected components var_map iterator
00652    }
00653    if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00654       cerr << "fcs: " << numfound << endl;
00655    return numfound;
00656 }
00657 
00658 template <typename Graph>
00659 typename CUT<Graph>::status CUT<Graph>::feasible(solution& S) {
00660    if( S.has_os() && S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00661       cerr << "CUT::feasible\n";
00662 
00663    double leps = .0000001;
00664    map<vertex_descriptor, int> dist, col;
00665    vertex_descriptor s;
00666 
00667    BGL_FORALL_VERTICES_T (s, G, Graph) {
00668       dist[s] = -1;
00669       col[s] = 0;
00670    }
00671 
00672    BGL_FORALL_VERTICES_T (s, G, Graph)
00673       if( dist[s] == -1 ) {
00674          list<vertex_descriptor> bfs_order;
00675          bfs_dist_visitor vis(&dist, &bfs_order, s);
00676          breadth_first_search(G, s, visitor(vis));
00677          vertex_descriptor v, w;
00678          col[bfs_order.front()] = 1;
00679          BOOST_FOREACH(v, bfs_order) {
00680             typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00681             /* Since G is undirected out_edges() returns iterator range to
00682                all adjacent edges.
00683              */
00684             for (tie(oe_it, oe_it_end) = out_edges(v, G);
00685                  oe_it != oe_it_end; oe_it++) {
00686                w = (source(*oe_it, G) == v) ? target(*oe_it, G) 
00687                                             : source(*oe_it, G);
00688                if(col[w] == 0) { //node w is not colored
00689                   col[w] = col[v];
00690                   if(S.value(VM[*oe_it]) > leps)
00691                      col[w] *= -1;
00692                } else { //node has already been colored
00693                   if(!(((col[w] == col[v]) && (S.value(VM[*oe_it]) <= leps))
00694                        || ((col[w] != col[v]) && (S.value(VM[*oe_it]) >= 1.-leps)))) {
00695                      if(S.originating_subproblem()->configuration("CUT_Debug_Out") == "true")
00696                         cerr << "feasible: Solution is not a feasible cut.\n";
00697                      return infeasible_solution;
00698                   }
00699                }
00700             }
00701          }
00702       }
00703 
00704    if( S.has_os() && S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00705       cerr << "feasible: Solution is a feasible cut.\n";
00706    if( updateConfiguration ) {
00707       conf.clear();
00708       tconf.clear();
00709       BGL_FORALL_VERTICES_T(s, G, Graph) 
00710          (col[s] == 1) ? conf.push_back(s) : tconf.push_back(s);
00711       conf.sort();
00712       tconf.sort();
00713    }
00714    return feasible_solution;
00715 }
00716 
00717 template <typename Graph>
00718 typename CUT<Graph>::status CUT<Graph>::standard_separation(subproblem& S) {
00719    if( S.configuration("CUT_Debug_Out")=="true" )
00720       cerr << "CUT::standard_separation\n";
00721    int numf = 1000;
00722    int nume = 100;
00723 
00724    list<cons_obj*> newCons;
00725    list<cons_obj*>::const_iterator ci;
00726    solution sol;
00727    cons_obj* c;
00728    cons nc;
00729 
00730    sol.save_solution(S);
00731    if( forestCycleSeparation(sol, numf, newCons) ) {
00732       foreach(ci, newCons)
00733          nc = S.add_basic_constraint(*ci);
00734       return constraint_found;
00735    }
00736    else if( exactCycleSeparation(sol, nume, newCons) ) {
00737       foreach(ci, newCons)
00738          nc = S.add_basic_constraint(*ci);
00739       return constraint_found;
00740    }
00741    else
00742       return no_constraint_found;
00743 }
00744 
00745 template <typename Graph>
00746 typename CUT<Graph>::status CUT<Graph>::fast_separation(subproblem& S) {
00747    if( S.configuration("CUT_Debug_Out")=="true" )
00748       cerr << "CUT::fast_separation\n";
00749    int numf = 1000;
00750 
00751    list<cons_obj*> newCons;
00752    list<cons_obj*>::const_iterator ci;
00753    solution sol;
00754    cons_obj* c;
00755    cons nc;
00756 
00757    sol.save_solution(S);
00758    if( forestCycleSeparation(sol, numf, newCons) ) {
00759       foreach(ci, newCons)
00760          nc = S.add_basic_constraint(*ci);
00761       return constraint_found;
00762    } else
00763       return no_constraint_found;
00764 }
00765 
00766 
00767 template <typename Graph>
00768 list<typename CUT<Graph>::vertex_descriptor> CUT<Graph>::getConfiguration(solution& S) {
00769    if( S.has_os() && S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00770       cerr << "CUT::getConfiguration\n";
00771    updateConfiguration = true;
00772    feasible(S);
00773    updateConfiguration = false;
00774    return (conf.size() < tconf.size()) ? conf : tconf;
00775 }
00776 
00777 template <typename Graph>
00778 void CUT<Graph>::info() {
00779    cout<<"Configurations:\n";
00780    cout<<"CUT_Debug_Out [true|false]\n";
00781 };
00782 #endif
Generated on Mon Mar 28 22:03:48 2011 for SCIL by  doxygen 1.6.3