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
00013
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
00027
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
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
00137 BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00138
00139 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<Graph>));
00140
00141 BOOST_CONCEPT_ASSERT((MutableGraphConcept<Graph>));
00142
00143
00144 vector<int> component(num_vertices(G));
00145 int num_components = connected_components(G, &component[0]);
00146
00147
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
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
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
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
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
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
00275
00276
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
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
00334
00335 }
00336 if( S.originating_subproblem()->configuration("CUT_Debug_Out")=="true" )
00337 cerr << "exactCycleSeparation: costs initialized\n";
00338
00339
00340
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
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
00357 pred_t pred;
00358
00359 dist_t dist;
00360 vertex_descriptor s,t;
00361
00362
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
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
00382
00383
00384
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
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
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
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
00432 cycle.push_back(f);
00433
00434
00435 if ( isCrossEdge[e] ) {
00436 r += VM[f];
00437 rhs += 1.;
00438 oddset[f] = true;
00439 }
00440 else
00441 r -= VM[f];
00442
00443
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
00457
00458
00459
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
00478 r.normalize(true);
00479 cons_obj* c = (r<=rhs);
00480
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
00518 typedef map<edge_descriptor, double> weight_map_t;
00519 typedef map<vertex_descriptor, size_t> vertex_index_t;
00520
00521
00522 weight_map_t tc;
00523 vertex_descriptor v, s, t;
00524 edge_descriptor e;
00525 BGL_FORALL_EDGES_T(e, G, Graph){
00526
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
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
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
00572
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
00642 if( !(int(rhs) % 2) ) {
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++;
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
00682
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) {
00689 col[w] = col[v];
00690 if(S.value(VM[*oe_it]) > leps)
00691 col[w] *= -1;
00692 } else {
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