00001 #ifndef SCIL_MATCHING_CC
00002 #define SCIL_MATCHING_CC
00003
00004 #define LEPS 1e-8 //must be larger than 1e-10, because of the cut tree alg.
00005
00006
00007
00008
00009
00010
00011
00012 using namespace boost;
00013 using namespace SCIL;
00014 using namespace std;
00015
00016 template <typename Graph>
00017 MATCHING<Graph>::MATCHING(Graph& G_, map<vertex_descriptor, int>& NC_,
00018 var_map<edge_descriptor>& VM_, bool perfect_)
00019 : G(G_), NC(NC_), VM(VM_), perfect(perfect_) {
00020 feps = 1.0e-4;
00021 BGL_FORALL_EDGES_T(e, G, Graph)
00022 if(VM[e].type() != Vartype_Binary) {
00023 cerr << "matching.cc: All variables in VM need to be";
00024 cerr << "Vartype_Binary" << endl;
00025 exit(1);
00026 }
00027 os = new int[num_edges(G) + num_vertices(G)];
00028 ot = new int[num_edges(G) + num_vertices(G)];
00029 oc = new double [num_edges(G) + num_vertices(G)];
00030 cts = new int[num_vertices(G)];
00031 ctt = new int[num_vertices(G)];
00032 ctc = new double[num_vertices(G)];
00033 edg = new edge_descriptor[num_edges(G)];
00034 }
00035
00036 template <typename Graph>
00037 MATCHING<Graph>::~MATCHING() {
00038 delete[]os;
00039 delete[]ot;
00040 delete[]oc;
00041 delete[]cts;
00042 delete[]ctt;
00043 delete[]ctc;
00044 delete[]edg;
00045 }
00046
00047 template <typename Graph>
00048 void MATCHING<Graph>::init(subproblem& S) {
00049 if(S.configuration("MATCHING_Debug_Out")=="true")
00050 cerr << "MATCHING::init\n";
00051
00052 typedef map<vertex_descriptor, int> cn_t;
00053 cn_t cn;
00054 associative_property_map<cn_t> pm_cn(cn);
00055 int comps = connected_components(G, pm_cn);
00056 if( comps != 1 ) {
00057 if(S.configuration("MATCHING_Debug_Out")=="true")
00058 cerr << "G is not connected! " << comps << endl;
00059
00060
00061 }
00062
00063
00064 typedef typename GraphTraits::directed_category directed_category;
00065 if (!(is_same<directed_category,undirected_tag>::value
00066 || is_base_and_derived<undirected_tag, directed_category>::value)) {
00067 cerr << "kconnected.cc: The graph has to be undirected." << endl;
00068 exit(1);
00069 };
00070
00071
00072 BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00073
00074 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept<Graph>));
00075
00076 BOOST_CONCEPT_ASSERT((MutableGraphConcept<Graph>));
00077
00078 int cap = 0;
00079 int i = 1;
00080 BGL_FORALL_VERTICES_T(v, G, Graph) {
00081 nid[v] = i++;
00082 cap += NC[v];
00083
00084 if( NC[v] < 0 ) {
00085 if(S.configuration("MATCHING_Debug_Out")=="true")
00086 cerr << "MATCHING::init Node capacities must be positive!" << endl;
00087 exit(1);
00088 }
00089
00090
00091 row r;
00092 typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00093 for(tie(oe_it, oe_it_end) = out_edges(v, G); oe_it != oe_it_end; oe_it++)
00094 r += VM[*oe_it];
00095 if( perfect )
00096 S.add_basic_constraint(r==NC[v], Static);
00097 else
00098 S.add_basic_constraint(r<=NC[v], Static);
00099 }
00100
00101 if( perfect && cap % 2 != 0 ) {
00102 if(S.configuration("MATCHING_Debug_Out")=="true")
00103 cerr << "MATCHING::init Sum of node capacities must be even for perfect matchings!" << endl;
00104 exit(1);
00105 }
00106
00107 i = 0;
00108 BGL_FORALL_EDGES_T(e, G, Graph) {
00109 os[i] = nid[source(e, G)];
00110 ot[i] = nid[target(e, G)];
00111 edg[i] = e;
00112 i++;
00113 }
00114
00115 return;
00116 }
00117
00118 template <typename Graph>
00119 int MATCHING<Graph>::exactBlossomSeparation(subproblem& S) {
00120 if(S.configuration("MATCHING_Debug_Out")=="true")
00121 cerr << "MATCHING::exactBlossomSeparation\n";
00122
00123 int numfound = 0;
00124 Graph H;
00125 map<edge_descriptor, double> ctc;
00126 map<vertex_descriptor, vertex_descriptor> p;
00127 map<vertex_descriptor, double> fl;
00128 double x;
00129 BGL_FORALL_EDGES_T(b, G, Graph) {
00130 x = S.value(VM[b]);
00131 ctc[b] = (x < .5) ? x: 1. - x;
00132 }
00133 computeCutTree(G, ctc, p, fl);
00134
00135
00136 BGL_FORALL_VERTICES_T(v, G, Graph) {
00137 if( p[v] == v )
00138 continue;
00139 row s;
00140 int rt = 0;
00141
00142
00143 vertex_descriptor ov = p[v];
00144 p[v] = v;
00145
00146
00147 typedef map<vertex_descriptor, set<vertex_descriptor>* > vertex_partition;
00148 vertex_partition vpartition;
00149
00150 BGL_FORALL_VERTICES_T(w, G, Graph) {
00151 vpartition[w] = new set<vertex_descriptor>();
00152 vpartition[w]->insert(w);
00153 }
00154
00155
00156 BGL_FORALL_VERTICES_T(w, G, Graph) {
00157 set<vertex_descriptor> *tmp = vpartition[p[w]];
00158 vpartition[w]->insert(tmp->begin(), tmp->end());
00159 typename set<vertex_descriptor>::iterator it;
00160
00161 for(it = tmp->begin(); it != tmp->end(); it++)
00162 vpartition[*it] = vpartition[w];
00163 }
00164
00165 vertex_descriptor t = *(vertices(G).first);
00166
00167 int bW = 0;
00168 BGL_FORALL_VERTICES_T(w, G, Graph) {
00169 if( *(vpartition[w]) == *(vpartition[t]) )
00170 bW += NC[v]%2;
00171
00172 }
00173
00174 list<edge_descriptor> F;
00175 list<edge_descriptor> delta;
00176 BGL_FORALL_EDGES_T(f, G, Graph) {
00177 if( !(*(vpartition[source(f, G)]) == *(vpartition[target(f, G)])) ) {
00178 if( S.value(VM[f]) > .5 )
00179 F.push_back(f);
00180 else
00181 delta.push_back(f);
00182 }
00183 }
00184
00185
00186
00187
00188
00189 edge_descriptor f;
00190 if( ((bW + F.size()) % 2) == 0 ) {
00191 edge_descriptor ff;
00192 double m;
00193 double minm = 2.;
00194 bool fffound = false;
00195 BOOST_FOREACH(f, delta) {
00196 m = fabs((2. * S.value(VM[f])) - 1.);
00197 if( m <= minm ) {
00198 minm = m;
00199 ff = f;
00200 }
00201 }
00202 BOOST_FOREACH(f, F) {
00203 m = fabs((2. * S.value(VM[f])) - 1.);
00204 if( m <= minm ) {
00205 minm = m;
00206 ff = f;
00207 fffound = true;
00208 }
00209 }
00210
00211
00212 if( fffound ) {
00213 F.remove(ff);
00214 delta.push_back(ff);
00215 }
00216 else {
00217 F.push_back(ff);
00218 delta.remove(ff);
00219 }
00220 }
00221
00222
00223 double rhs = 1. - double(F.size());
00224 row r;
00225 BOOST_FOREACH(f, delta) {
00226 r += VM[f];
00227 }
00228 BOOST_FOREACH(f, F) {
00229 r -= VM[f];
00230 }
00231
00232 if( r.size() > 0 ) {
00233 if(S.configuration("MATCHING_Debug_Out")=="true")
00234 cerr << "constraint found" << endl;
00235 if( !perfect ) {
00236 rhs += double(rt);
00237 r += s;
00238 }
00239
00240
00241 cons_obj* c = (r>=rhs);
00242 if( c->violation(S) > feps ) {
00243 if(S.configuration("MATCHING_Debug_Out")=="true")
00244 cerr << r << " >= " << rhs << endl;
00245 S.add_basic_constraint(r>=rhs);
00246 numfound++;
00247 }
00248 delete c;
00249 }
00250 p[v] = ov;
00251 }
00252 if(S.configuration("MATCHING_Debug_Out")=="true")
00253 cerr << "MAT: " << numfound << endl;
00254 return numfound;
00255 }
00256
00257 template <typename Graph>
00258 typename MATCHING<Graph>::status MATCHING<Graph>::feasible(solution& S) {
00259 if(S.originating_subproblem()->configuration("MATCHING_Debug_Out")=="true")
00260 cerr << "MATCHING::feasible\n";
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 return feasible_solution;
00277 }
00278
00279
00280
00281 template <typename Graph>
00282 int MATCHING<Graph>::heuristicBlossomSeparation(subproblem& S) {
00283 if(S.configuration("MATCHING_Debug_Out")=="true")
00284 cerr << "MATCHING::heuristicBlossomSeparation\n";
00285
00286 int numfound = 0;
00287
00288 list<edge_descriptor> edgesH;
00289 list<edge_descriptor> edgesNotH;
00290 map<vertex_descriptor, vertex_descriptor> verticesHtoG;
00291 map<vertex_descriptor, vertex_descriptor> verticesGtoH;
00292 map<edge_descriptor, edge_descriptor> edgesHtoG;
00293 Graph H;
00294 BGL_FORALL_VERTICES_T(v, G, Graph) {
00295 vertex_descriptor newNodeInH = add_vertex(H);
00296 verticesHtoG[newNodeInH] = v;
00297 verticesGtoH[v] = newNodeInH;
00298 }
00299 BGL_FORALL_EDGES_T(e, G, Graph) {
00300 edge_descriptor newEdgeInH = (add_edge(verticesGtoH[source(e, G)],
00301 verticesGtoH[target(e, G)],
00302 H)).first;
00303 edgesHtoG[newEdgeInH] = e;
00304 }
00305
00306 list<edge_descriptor> toBeDeleted;
00307 BGL_FORALL_EDGES_T(e, H, Graph) {
00308 if( (S.value(VM[edgesHtoG[e]]) < LEPS)
00309 || (S.value(VM[edgesHtoG[e]]) > 1. - LEPS) ) {
00310 edgesNotH.push_back(edgesHtoG[e]);
00311 toBeDeleted.push_back(e);
00312 } else
00313 edgesH.push_back(edgesHtoG[e]);
00314 }
00315 edge_descriptor e;
00316 BOOST_FOREACH(e, toBeDeleted)
00317 remove_edge(e, H);
00318
00319 typedef map<vertex_descriptor, int> compnumH_t;
00320 compnumH_t compnumH;
00321 associative_property_map<compnumH_t> pm_compnumH(compnumH);
00322 int comps = connected_components(H, pm_compnumH);
00323
00324 if( comps < 2 )
00325 return 0;
00326
00327 compnumH_t compnum;
00328 BGL_FORALL_VERTICES_T(v, H, Graph)
00329 compnum[verticesHtoG[v]] = compnumH[v];
00330
00331 for( int i = 0; i < comps; i++ ) {
00332 row r;
00333 double rhs = 1.;
00334 edge_descriptor e;
00335 BOOST_FOREACH(e, edgesNotH) {
00336 vertex_descriptor s = source(e, G);
00337 vertex_descriptor t = target(e, G);
00338 if( ((compnum[s] == i) || (compnum[t] == i)) && compnum[s] != compnum[t] ) {
00339 if( S.value(VM[e]) > 1. - LEPS ) {
00340 r -= VM[e];
00341 rhs -= 1.;
00342 }
00343 else
00344 r += VM[e];
00345 }
00346 }
00347
00348 int b = 0;
00349 int c = 0;
00350 double sl = 0.;
00351 BGL_FORALL_VERTICES_T(v, G, Graph) {
00352 if( compnum[v] == i ) {
00353 rhs -= NC[v];
00354 b += NC[v];
00355 typename GraphTraits::out_edge_iterator it, it_end;
00356 for(tie(it, it_end) = out_edges(v, G); it != it_end; it++) {
00357 r -= VM[*it];
00358 sl += S.value(VM[*it]);
00359 if( S.value(VM[*it]) > 1. - LEPS )
00360 c++;
00361 }
00362 }
00363 }
00364
00365
00366 if( ((b - c) % 2) && (double(b) - sl < 1. - LEPS) ) {
00367
00368 r.normalize();
00369 if( r.size() > 0 ) {
00370 S.add_basic_constraint(r>=rhs);
00371 numfound++;
00372 }
00373 }
00374 }
00375 if(S.configuration("MATCHING_Debug_Out")=="true")
00376 cerr << "h: numfound:" << numfound << endl;
00377 return numfound;
00378 }
00379
00380 template <typename Graph>
00381 typename MATCHING<Graph>::status MATCHING<Graph>::standard_separation(subproblem& S) {
00382 if(S.configuration("MATCHING_Debug_Out")=="true")
00383 cerr << "MATCHING::standard_separation\n";
00384
00385 if( heuristicBlossomSeparation(S) )
00386 return constraint_found;
00387 if( perfect && exactBlossomSeparation(S) )
00388 return constraint_found;
00389 else
00390 return no_constraint_found;
00391 }
00392
00393 template <typename Graph>
00394 typename MATCHING<Graph>::status MATCHING<Graph>::fast_separation(subproblem& S) {
00395 if(S.configuration("MATCHING_Debug_Out")=="true")
00396 cerr << "MATCHING::fast_separation\n";
00397
00398 if( heuristicBlossomSeparation(S) )
00399 return constraint_found;
00400 else
00401 return no_constraint_found;
00402 }
00403
00404
00405 template <typename Graph>
00406 void MATCHING<Graph>::info() {
00407 cout<<"Configurations:\n";
00408 cout<<"MATCHING_Debug_Out [true|false]\n";
00409 };
00410 #endif