00001 #ifndef SCIL_STABLESET_CC
00002 #define SCIL_STABLESET_CC
00003
00004 #define HIDE_THRES 5
00005 #define LEPS 1e-8
00006
00007 using namespace SCIL;
00008 using namespace boost;
00009 using namespace std;
00010
00011
00012
00013
00014 template <typename Graph>
00015 STABLESET<Graph>::STABLESET(Graph& G_, var_map<vertex_descriptor>& VM_)
00016 : G(G_), VM(VM_) {
00017 feps = 1.0e-4;
00018 BGL_FORALL_VERTICES_T(v, G, Graph)
00019 if(VM[v].type() != Vartype_Binary) {
00020 cerr << "stableset.cc: All variables in VM need to be";
00021 cerr << "Vartype_Binary" << endl;
00022 exit(1);
00023 }
00024 };
00025
00026
00027 template <typename Graph>
00028 void STABLESET<Graph>::init(subproblem& S) {
00029 if(S.configuration("STABLESET_Debug_Out")=="true")
00030 cerr << "STABLESET::init\n";
00031
00032 typedef typename GraphTraits::directed_category directed_category;
00033 if (!(is_same<directed_category,undirected_tag>::value
00034 || is_base_and_derived<undirected_tag, directed_category>::value)) {
00035 cerr << "kconnected.cc: The graph has to be undirected." << endl;
00036 exit(1);
00037 }
00038
00039 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<Graph>));
00040
00041 BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00042
00043 BOOST_CONCEPT_ASSERT((MutableGraphConcept<Graph>));
00044
00045 int i = 0;
00046 BGL_FORALL_EDGES_T(e, G, Graph) {
00047 row r;
00048 r += VM[source(e, G)];
00049 r += VM[target(e, G)];
00050 S.add_basic_constraint(r<=1., Static);
00051 }
00052
00053 return;
00054 };
00055
00056 template <typename Graph>
00057 int STABLESET<Graph>::exactOddCycleSeparation(subproblem& S, int maxnum) {
00058 if(S.configuration("STABLESET_Debug_Out")=="true")
00059 cerr << "STABLESET::exactOddCycleSeparation\n";
00060
00061 Graph G1;
00062 map<vertex_descriptor, bool> node_mapG1;
00063 map<edge_descriptor, bool> edge_mapG1;
00064 map<vertex_descriptor, vertex_descriptor> GtoG1a;
00065 map<vertex_descriptor, vertex_descriptor> GtoG1b;
00066 map<vertex_descriptor, int> node_used;
00067 map<vertex_descriptor, vertex_descriptor> G1toG;
00068 map<edge_descriptor, edge_descriptor> back;
00069 BGL_FORALL_VERTICES_T(v, G, Graph)
00070 node_used[v] = 0;
00071
00072
00073 BGL_FORALL_VERTICES_T(v, G, Graph) {
00074 vertex_descriptor new_vertex;
00075 new_vertex = add_vertex(G1);
00076 GtoG1a[v] = new_vertex;
00077 node_mapG1[new_vertex] = false;
00078 new_vertex = add_vertex(G1);
00079 GtoG1b[v] = new_vertex;
00080 node_mapG1[new_vertex] = true;
00081 G1toG[GtoG1a[v]]=v;
00082 G1toG[GtoG1b[v]]=v;
00083 }
00084 if(S.configuration("STABLESET_Debug_Out")=="true")
00085 cerr << "exactOddCycleSeparation: nodes added\n";
00086
00087
00088
00089 BGL_FORALL_EDGES_T(e, G, Graph) {
00090 edge_descriptor new_edge;
00091 new_edge = (add_edge(GtoG1a[source(e,G)], GtoG1b[target(e,G)], G1)).first;
00092 back[new_edge] = e;
00093 edge_mapG1[new_edge] = true;
00094 new_edge = (add_edge(GtoG1b[source(e,G)], GtoG1a[target(e,G)], G1)).first;
00095 back[new_edge] = e;
00096 edge_mapG1[new_edge] = true;
00097 }
00098
00099 if(S.configuration("STABLESET_Debug_Out")=="true")
00100 cerr << "exactOddCycleSeparation: edges added\n";
00101
00102 typedef map<edge_descriptor, double> costs_t;
00103 typedef map<vertex_descriptor, size_t> vertex_index_t;
00104 typedef map<vertex_descriptor, vertex_descriptor> pred_t;
00105 typedef map<vertex_descriptor, double> dist_t;
00106
00107 costs_t costs;
00108 BGL_FORALL_EDGES_T(e, G1, Graph) {
00109 double co = 1. - S.value(VM[G1toG[source(e, G1)]]);
00110 co += S.value(VM[G1toG[target(e, G1)]]);
00111 costs[e] = ( co > 0. ) ? co : 0.;
00112 }
00113
00114
00115 vertex_index_t vertex_index_map;
00116 int i = 0;
00117 BGL_FORALL_VERTICES_T(v, G, Graph)
00118 vertex_index_map[v] = i++;
00119
00120 if(S.configuration("STABLESET_Debug_Out")=="true")
00121 cerr << "exactOddCycleSeparation: costs initialized\n";
00122
00123
00124 pred_t pred;
00125
00126 dist_t dist;
00127 int numfound = 0;
00128
00129
00130 associative_property_map<costs_t> pm_costs(costs);
00131 associative_property_map<vertex_index_t> pm_vertex_index(vertex_index_map);
00132 associative_property_map<pred_t> pm_pred(pred);
00133 associative_property_map<dist_t> pm_dist(dist);
00134
00135 vertex_descriptor s, t;
00136
00137
00138
00139 Graph G_bak = G, G1_bak = G1;
00140
00141
00142 BGL_FORALL_VERTICES_T(v, G, Graph) {
00143 if( numfound >= maxnum )
00144 break;
00145
00146 BGL_FORALL_VERTICES_T(s, G, Graph) {
00147 if( node_used[s] > HIDE_THRES && out_degree(s, G) != 0 ) {
00148 clear_vertex(s, G);
00149 clear_vertex(GtoG1a[s], G1);
00150 clear_vertex(GtoG1b[s], G1);
00151 }
00152 }
00153
00154 if ( out_degree(v, G) == 0 )
00155 continue;
00156
00157 s = GtoG1a[v];
00158 t = GtoG1b[v];
00159 if(S.configuration("STABLESET_Debug_Out")=="true")
00160 cerr << "exactOddCycleSeparation: DIJKSTRA START:\n";
00161 dijkstra_shortest_paths(G1, s, weight_map(pm_costs).vertex_index_map
00162 (pm_vertex_index).distance_map(pm_dist).predecessor_map(pm_pred));
00163 double w = dist[t];
00164
00165 if(S.configuration("STABLESET_Debug_Out")=="true")
00166 cerr << "exactOddCycleSeparation: DIJKSTRA w:" << 1 << 1 << w << endl;
00167
00168 if( (w < 1. - LEPS) && (pred[t] != t) ) {
00169
00170 bool duplicates = false;
00171 std::list<vertex_descriptor> cycle;
00172 std::list<double> cyclecosts;
00173 map<vertex_descriptor, bool> seen;
00174 BGL_FORALL_VERTICES_T(v, G, Graph)
00175 seen[v] = false;
00176 row r;
00177
00178 vertex_descriptor a, b;
00179 double z = 0;
00180
00181
00182 seen[G1toG[t]] = true;
00183 node_used[G1toG[t]]++;
00184
00185 while( !duplicates ) {
00186 edge_descriptor e = (edge(t, pred[t], G1)).first;
00187
00188
00189 a = G1toG[t];
00190 b = G1toG[pred[t]];
00191
00192
00193 cycle.push_back(a);
00194 r += VM[a];
00195 z += costs[e];
00196 cyclecosts.push_back(costs[e]);
00197
00198 if( seen[b] )
00199 duplicates = true;
00200 else {
00201 seen[b] = true;
00202 node_used[b]++;
00203 }
00204
00205 t = pred[t];
00206 }
00207
00208
00209
00210
00211
00212 s = G1toG[s];
00213 while( cycle.front() != b ) {
00214 t = cycle.front();
00215 cycle.pop_front();
00216 r -= VM[t];
00217 node_used[t]--;
00218 z -= cyclecosts.front();
00219 cyclecosts.pop_front();
00220 }
00221
00222
00223 if( z < 1. - feps ) {
00224 r.normalize();
00225 double rhs = floor((double(cycle.size()) - 1.) / 2.);
00226 S.add_basic_constraint(r<=rhs);
00227 if(S.configuration("STABLESET_Debug_Out")=="true") {
00228 cerr << "exactOddCycleSeparation: added constraint! rhs = ";
00229 cerr << 1 << 1 << rhs << endl;
00230 }
00231 numfound++;
00232 }
00233 }
00234 }
00235 if(S.configuration("STABLESET_Debug_Out")=="true") {
00236 cerr << "exactOddCycleSeparation: constraints added:" ;
00237 cerr << 1 << 0 << numfound << endl;
00238 }
00239 G = G_bak;
00240 G1 = G1_bak;
00241
00242 return numfound;
00243 }
00244
00245 template <typename Graph>
00246 int STABLESET<Graph>::heuristicCliqueSeparation(subproblem& S, int maxnum){
00247 vertex_descriptor v;
00248
00249 for(int strat = 0; strat < 2; strat++){
00250 vertex_descriptor startVertex = NULL;
00251 BGL_FORALL_VERTICES_T(v, G, Graph){
00252 if(startVertex == NULL){
00253 startVertex = v;
00254 continue;
00255 }
00256 if(strat == 0)
00257 if(fabs(S.value(VM[v])-.5) < fabs(S.value(VM[startVertex])-.5))
00258 startVertex = v;
00259 else
00260 if(S.value(VM[v]) < 1 && (S.value(VM[v]) > S.value(VM[startVertex])))
00261 startVertex = v;
00262 }
00263 map<vertex_descriptor, bool> vertex_map;
00264 pair<adjacency_iterator, adjacency_iterator> vertexRange = adjacent_vertices(startVertex, G);
00265 adjacency_iterator adIt;
00266
00267 for(adIt = vertexRange.first; adIt != vertexRange.second; adIt++)
00268 vertex_map.insert(make_pair(*adIt,false));
00269 vertex_map.insert(make_pair(startVertex, true));
00270 bool cliqueFound = false;
00271 typename map<vertex_descriptor, bool> ::iterator mapIt;
00272 typename map<vertex_descriptor, bool> ::iterator mapIt2;
00273
00274 while(! cliqueFound) {
00275 for(mapIt = vertex_map.begin(); mapIt != vertex_map.end(); mapIt++){
00276 if(mapIt->second == true)
00277 continue;
00278 vertexRange = adjacent_vertices(mapIt->first, G);
00279 for(mapIt2 = vertex_map.begin(); mapIt2 != vertex_map.end(); mapIt2++){
00280 if(mapIt2 != mapIt) {
00281 for(adIt = vertexRange.first; adIt != vertexRange.second; adIt++)
00282 if(*adIt == mapIt2->first)
00283 break;
00284 if(adIt == vertexRange.second)
00285 vertex_map.erase(mapIt2);
00286 }
00287 }
00288 mapIt->second = true;
00289 break;
00290 }
00291 if(mapIt == vertex_map.end())
00292 cliqueFound = true;
00293 }
00294 row r;
00295
00296 for(mapIt = vertex_map.begin(); mapIt != vertex_map.end(); mapIt++)
00297 r += VM[mapIt->first];
00298 cons_obj* c = r<=1;
00299 if(c->violated(S)){
00300 S.add_basic_constraint(c);
00301 return 1;
00302 }
00303 delete c;
00304 }
00305 return 0;
00306 }
00307
00308
00309
00310 template <typename Graph>
00311 typename STABLESET<Graph>::status STABLESET<Graph>::feasible(solution& S) {
00312 if(S.originating_subproblem()->configuration("STABLESET_Debug_Out")=="true")
00313 cerr << "STABLESET::feasible\n";
00314
00315
00316
00317
00318
00319
00320 BGL_FORALL_EDGES_T(e, G, Graph) {
00321 if( S.value(VM[source(e, G)]) && S.value(VM[target(e, G)]))
00322 return infeasible_solution;
00323 }
00324
00325 return feasible_solution;
00326 }
00327
00328 template <typename Graph>
00329 typename STABLESET<Graph>::status
00330 STABLESET<Graph>::standard_separation(subproblem& S) {
00331 if(S.configuration("STABLESET_Debug_Out")=="true")
00332 cerr << "STABLESET::standard_separation\n";
00333 int num = 2000;
00334 if( heuristicCliqueSeparation(S, num) )
00335 return constraint_found;
00336 else {
00337 if( exactOddCycleSeparation(S, num) )
00338 return constraint_found;
00339 else
00340 return no_constraint_found;
00341 }
00342 }
00343
00344 template <typename Graph>
00345 typename STABLESET<Graph>::status
00346 STABLESET<Graph>::fast_separation(subproblem& S) {
00347 if(S.configuration("STABLESET_Debug_Out")=="true")
00348 cerr << "STABLESET::fast_separation\n";
00349 int num = 2000;
00350 if( heuristicCliqueSeparation(S, num) )
00351 return constraint_found;
00352 else
00353 return no_constraint_found;
00354 }
00355
00356 template <typename Graph>
00357 void STABLESET<Graph>::info() {
00358 cout<<"Configurations:\n";
00359 cout<<"STABLESET_Debug_Out [true|false]\n";
00360 };
00361 #endif