00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00063 #ifndef UMCB_H
00064 #define UMCB_H
00065
00066 #include <LEP/mcb/config.h>
00067
00068 #ifdef LEDA_GE_V5
00069 #include <LEDA/graph/graph.h>
00070 #include <LEDA/graph/edge_array.h>
00071 #include <LEDA/graph/node_array.h>
00072 #include <LEDA/core/d_int_set.h>
00073 #include <LEDA/core/array.h>
00074 #include <LEDA/core/list.h>
00075 #else
00076 #include <LEDA/graph.h>
00077 #include <LEDA/d_int_set.h>
00078 #include <LEDA/edge_array.h>
00079 #include <LEDA/node_array.h>
00080 #include <LEDA/array.h>
00081 #include <LEDA/list.h>
00082 #endif
00083
00084 #include <LEP/mcb/spvecgf2.h>
00085 #include <LEP/mcb/signed.h>
00086 #include <LEP/mcb/superset.h>
00087 #include <LEP/mcb/sptrees.h>
00088 #include <LEP/mcb/transform.h>
00089 #include <LEP/mcb/verify.h>
00090
00091
00092 namespace mcb
00093 {
00094
00095 #if defined(LEDA_NAMESPACE)
00096 using leda::graph;
00097 using leda::array;
00098 using leda::edge;
00099 using leda::edge_array;
00100 using leda::d_int_set;
00101 using leda::list;
00102 #endif
00103
00104 template<typename W, class Container>
00105 class SupportMCB
00106 {
00107 public:
00108 typedef W result_type;
00109
00110 SupportMCB( const graph& g_,
00111 array< Container >& mcb_,
00112 array< Container >& proof_,
00113 const mcb::edge_num& enumb_
00114 )
00115 : g(g_), C(mcb_), S(proof_), enumb(enumb_), N(enumb_.dim_cycle_space())
00116 {
00117 #if ! defined(LEDA_CHECKING_OFF)
00118 if ( Is_Undirected_Simple( g ) == false )
00119 error_handler(999,"MIN_CYCLE_BASIS: illegal graph (parallel,anti-parallel edges or loops?)");
00120 #endif
00121 C.resize(N);
00122 S.resize(N);
00123 }
00124
00125 virtual ~SupportMCB() {}
00126
00127 W run() {
00128 checkPreconditions();
00129
00130 #ifdef LEP_STATS
00131 float Tcycle = 0.0, Torthog = 0.0, Ttemp;
00132 #endif
00133
00134 initializeSupportVectors();
00135
00136 W min = W();
00137 for( int k = 0; k < N; ++k ) {
00138 #ifdef LEP_STATS
00139 leda::used_time( Ttemp );
00140 #endif
00141 chooseSparsestSupportHeuristic( k );
00142
00143 #ifdef LEP_STATS
00144 Torthog += leda::used_time( Ttemp );
00145 #endif
00146
00147 min += computeShortestOddCycle( k );
00148
00149 #ifdef LEP_STATS
00150 Tcycle += leda::used_time( Ttemp );
00151 #endif
00152 updateSupportVectors( k );
00153
00154 #ifdef LEP_STATS
00155 Torthog += leda::used_time( Ttemp );
00156 #endif
00157
00158 }
00159
00160 #ifdef LEP_STATS
00161 std::cout << "LEP_STATS: cycle computation time: " << Tcycle << std::endl;
00162 std::cout << "LEP_STATS: orthogonal base maintain time: " << Torthog << std::endl;
00163 #endif
00164
00165 return min;
00166 }
00167
00168 private:
00169
00170 virtual void checkPreconditions() = 0;
00171
00172 void initializeSupportVectors() {
00173 for( int i = 0; i < N; ++i ) {
00174 S[i].clear();
00175 S[i].insert(i);
00176 }
00177 }
00178
00179 void chooseSparsestSupportHeuristic( int k ) {
00180 #ifndef MCB_LEP_UNDIR_NO_EXCHANGE_HEURISTIC
00181 int minS = k;
00182 for( int r = k+1; r < N; ++r ) {
00183 if ( S[r].size() < S[minS].size() )
00184 minS = r;
00185 }
00186 if ( minS != k ) {
00187 std::swap( S[k], S[minS] );
00188 }
00189 #endif
00190 }
00191
00192 virtual W computeShortestOddCycle( int k ) = 0;
00193
00194 void updateSupportVectors( int k ) {
00195 for( int l = k+1; l < N; ++l ) {
00196 if ( (C[k].intersect(S[l])).size() % 2 == 1 ) {
00197 S[ l ] %= S[k];
00198 }
00199 }
00200 }
00201
00202 protected:
00203 const graph& g;
00204 array<Container>& C;
00205 array<Container>& S;
00206 const mcb::edge_num& enumb;
00207 int N;
00208 };
00209
00210 template<typename W, class Container>
00211 class WeightedSupportMCB: public SupportMCB< W, Container>
00212 {
00213 public:
00214 typedef SupportMCB< W, Container> base_type;
00215
00216 WeightedSupportMCB( const graph& g_,
00217 const edge_array<W>& len_,
00218 array< Container >& mcb_,
00219 array< Container >& proof_,
00220 const mcb::edge_num& enumb_ )
00221 : base_type( g_, mcb_, proof_, enumb_ ), len(len_)
00222 {
00223 }
00224
00225 private:
00226
00227 void checkPreconditions() {
00228 #if ! defined(LEDA_CHECKING_OFF)
00229 edge e;
00230 forall_edges( e , g ) {
00231 if ( len[e] < 0 )
00232 error_handler(999,"MIN_CYCLE_BASIS: illegal edge (negative weight)");
00233 }
00234 #endif
00235 }
00236
00237 protected:
00238 const edge_array<W>& len;
00239 using base_type::g;
00240 };
00241
00242 template<typename W, class Container>
00243 class WeightedSignedSupportMCB: public WeightedSupportMCB< W, Container>
00244 {
00245 public:
00246 typedef WeightedSupportMCB< W, Container> base_type;
00247
00248 WeightedSignedSupportMCB( const graph& g_,
00249 const edge_array<W>& len_,
00250 array< Container >& mcb_,
00251 array< Container >& proof_,
00252 const mcb::edge_num& enumb_ )
00253 : base_type( g_, len_, mcb_, proof_, enumb_ ), sg(g_, len_, enumb_)
00254 {
00255 }
00256
00257 private:
00258
00259 W computeShortestOddCycle( int k ) {
00260 return sg.get_shortest_odd_cycle( S[k], C[k] );
00261 }
00262
00263 private:
00264 detail::WeightedSignedGraph<W,leda::bin_heap> sg;
00265 using base_type::C;
00266 using base_type::S;
00267 };
00268
00269 template<class Container>
00270 class UnweightedSignedSupportMCB: public SupportMCB< int, Container >
00271 {
00272 public:
00273 typedef SupportMCB< int, Container> base_type;
00274
00275 UnweightedSignedSupportMCB( const graph& g_,
00276 array< Container >& mcb_,
00277 array< Container >& proof_,
00278 const mcb::edge_num& enumb_
00279 )
00280 : base_type( g_, mcb_, proof_, enumb_ ), sg( g_, enumb_ )
00281 {
00282 }
00283
00284 ~UnweightedSignedSupportMCB() {}
00285
00286 private:
00287 int computeShortestOddCycle( int k ) {
00288 return sg.get_shortest_odd_cycle( S[k], C[k] );
00289 }
00290
00291 void checkPreconditions() {}
00292
00293 private:
00294 detail::UnweightedSignedGraph sg;
00295 using base_type::C;
00296 using base_type::S;
00297 };
00298
00299 template<typename W, class Container>
00300 class WeightedHortonSupportMCB: public WeightedSupportMCB<W, Container>
00301 {
00302 public:
00303 typedef WeightedSupportMCB<W, Container> base_type;
00304
00305 WeightedHortonSupportMCB( const graph& g_,
00306 const edge_array<W>& len_,
00307 array< Container >& mcb_,
00308 array< Container >& proof_,
00309 const mcb::edge_num& enumb_ )
00310 : base_type( g_, len_, mcb_, proof_, enumb_ ), HS( g_, len_, enumb_ )
00311 {
00312 }
00313
00314 private:
00315
00316 W computeShortestOddCycle( int k ) {
00317 return HS.get_shortest_odd_cycle( S[k], C[k] );
00318 }
00319
00320 HortonSuperset<W> HS;
00321 using base_type::C;
00322 using base_type::S;
00323 };
00324
00325 template<typename W, class Container>
00326 class WeightedSPTreesSupportMCB: public WeightedSupportMCB<W, Container>
00327 {
00328 public:
00329 typedef WeightedSupportMCB<W, Container> base_type;
00330
00331 WeightedSPTreesSupportMCB( const graph& g_,
00332 const edge_array<W>& len_,
00333 array< Container >& mcb_,
00334 array< Container >& proof_,
00335 const mcb::edge_num& enumb_ )
00336 : base_type( g_, len_, mcb_, proof_, enumb_ ), uhst( g_, len_, enumb_ )
00337 {
00338 }
00339
00340 private:
00341
00342 W computeShortestOddCycle( int k ) {
00343 uhst.updateTreeLabels( S[k] );
00344 return uhst.getShortestOddCycle( S[k], C[k] );
00345 }
00346
00347 UndirectedHortonSupersetTrees<W> uhst;
00348 using base_type::C;
00349 using base_type::S;
00350 };
00351
00352
00353
00370
00399 template<class Container>
00400 int UMCB_SVA( const graph& g,
00401 array< Container >& mcb,
00402 array< Container >& proof,
00403 const mcb::edge_num& enumb
00404 )
00405 {
00406 UnweightedSignedSupportMCB<Container> tmp( g, mcb, proof, enumb );
00407 return tmp.run();
00408 }
00409
00434 template<class Container>
00435 int UMCB_SVA( const graph& g,
00436 array< Container >& mcb,
00437 const mcb::edge_num& enumb
00438 )
00439 {
00440 array< Container > proof;
00441 return UMCB_SVA( g, mcb, proof, enumb );
00442 }
00443
00476 template<class W, class Container>
00477 W UMCB_SVA( const graph& g,
00478 const edge_array<W>& len,
00479 array< Container >& mcb,
00480 array< Container >& proof,
00481 const mcb::edge_num& enumb
00482 )
00483 {
00484 WeightedSignedSupportMCB<W,Container> tmp( g, len, mcb, proof, enumb );
00485 return tmp.run();
00486 }
00487
00516 template<class W, class Container>
00517 W UMCB_SVA( const graph& g,
00518 const edge_array<W>& len,
00519 array< Container >& mcb,
00520 const mcb::edge_num& enumb
00521 )
00522 {
00523 array< Container > proof;
00524 WeightedSignedSupportMCB<W,Container> tmp( g, len, mcb, proof, enumb );
00525 return tmp.run();
00526 }
00527
00555 extern int UMCB_HYBRID( const leda::graph& g,
00556 leda::array< leda::d_int_set >& mcb,
00557 leda::array< leda::d_int_set >& proof,
00558 const mcb::edge_num& enumb
00559 );
00560
00582 extern int UMCB_HYBRID( const leda::graph& g,
00583 leda::array< leda::d_int_set >& mcb,
00584 const mcb::edge_num& enumb
00585 );
00586
00587
00617 template<class W>
00618 W UMCB_HYBRID( const graph& g,
00619 const edge_array<W>& len,
00620 array< d_int_set >& mcb,
00621 array< d_int_set >& proof,
00622 const mcb::edge_num& enumb
00623 )
00624 {
00625 WeightedHortonSupportMCB<W, d_int_set> tmp( g, len, mcb, proof, enumb );
00626 return tmp.run();
00627 }
00628
00629
00653 template<class W>
00654 W UMCB_HYBRID( const graph& g,
00655 const edge_array<W>& len,
00656 array< d_int_set >& mcb,
00657 const mcb::edge_num& enumb
00658 )
00659 {
00660 array< d_int_set > proof_temp;
00661 return UMCB_HYBRID( g, len, mcb, proof_temp, enumb );
00662 }
00663
00694 template<class W>
00695 W UMCB_FH( const graph& g,
00696 const edge_array<W>& len,
00697 array< mcb::spvecgf2 >& mcb,
00698 array< mcb::spvecgf2 >& proof,
00699 const mcb::edge_num& enumb )
00700 {
00701 WeightedSPTreesSupportMCB<W,mcb::spvecgf2> tmp( g, len, mcb, proof, enumb );
00702 return tmp.run();
00703 }
00704
00731 template<class W>
00732 W UMCB_FH( const graph& g,
00733 const edge_array<W>& len,
00734 array< mcb::spvecgf2 >& mcb,
00735 const mcb::edge_num& enumb )
00736 {
00737 array< mcb::spvecgf2 > proof;
00738 WeightedSPTreesSupportMCB<W,mcb::spvecgf2> tmp( g, len, mcb, proof, enumb );
00739 return tmp.run();
00740 }
00741
00743
00744 }
00745
00746 #endif // UMCB_H
00747
00748
00749
00750