min_cycle_basis.h

Go to the documentation of this file.
00001 #line 6220 "MIN_CYCLE_BASIS.lw"
00002 //---------------------------------------------------------------------
00003 // File automatically generated using notangle from DMIN_CYCLE_BASIS.lw
00004 //
00005 // emails and bugs: Dimitris Michail <michail@mpi-inf.mpg.de>
00006 //---------------------------------------------------------------------
00007 //
00008 // This program can be freely used in an academic environment
00009 // ONLY for research purposes, subject to the following restrictions:
00010 //
00011 // 1. The origin of this software must not be misrepresented; you must not
00012 //    claim that you wrote the original software. If you use this software
00013 //    an acknowledgment in the product documentation is required.
00014 // 2. Altered source versions must be plainly marked as such, and must not be
00015 //    misrepresented as being the original software.
00016 // 3. This notice may not be removed or altered from any source distribution.
00017 //
00018 // Any other use is strictly prohibited by the author, without an explicit 
00019 // permission.
00020 //
00021 // Note that this program uses the LEDA library, which is NOT free. For more 
00022 // details visit Algorithmic Solutions at http://www.algorithmic-solutions.com/
00023 //
00024 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00025 // ! Any commercial use of this software is strictly !
00026 // ! prohibited without explicit permission by the   !
00027 // ! author.                                         !
00028 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00029 //
00030 // This software is distributed in the hope that it will be useful,
00031 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00032 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00033 //
00034 // Copyright (C) 2004-2005 - Dimitris Michail <michail@mpi-inf.mpg.de>
00035 
00036 
00037 #line 1773 "MIN_CYCLE_BASIS.lw"
00038 
00069 #ifndef MIN_CYCLE_BASIS_H
00070 #define MIN_CYCLE_BASIS_H
00071 
00072 #ifdef LEDA_GE_V5
00073 #include <LEDA/graph/graph.h>
00074 #include <LEDA/graph/edge_array.h>
00075 #include <LEDA/graph/node_array.h>
00076 #include <LEDA/graph/shortest_path.h>
00077 #include <LEDA/graph/templates/shortest_path.h>
00078 #include <LEDA/core/d_int_set.h>
00079 #include <LEDA/core/array.h>
00080 #include <LEDA/core/list.h>
00081 #include <LEDA/core/sortseq.h>
00082 #include <LEDA/core/tuple.h>
00083 #else
00084 #include <LEDA/graph.h>
00085 #include <LEDA/d_int_set.h>
00086 #include <LEDA/edge_array.h>
00087 #include <LEDA/node_array.h>
00088 #include <LEDA/array.h>
00089 #include <LEDA/list.h>
00090 #include <LEDA/sortseq.h>
00091 #include <LEDA/shortest_path.h>
00092 #include <LEDA/templates/shortest_path.t>
00093 #include <LEDA/tuple.h>
00094 #endif
00095 
00096 #include <LEP/mcb/SIGNED_GRAPH.h>
00097 
00098 // start our namespace
00099 namespace mcb 
00100 { 
00101 
00102 #if defined(LEDA_NAMESPACE)
00103 using leda::graph;
00104 using leda::array;
00105 using leda::edge;
00106 using leda::edge_array;
00107 using leda::d_int_set;
00108 using leda::list;
00109 using leda::sortseq;
00110 using leda::three_tuple;
00111 using leda::two_tuple;
00112 using leda::DIJKSTRA_T;
00113 using leda::node_set;
00114 #endif
00115 
00116 
00117 
00118 
00119 #line 1873 "MIN_CYCLE_BASIS.lw"
00120 // external 
00121 extern bool MCB_verify_basis( const leda::graph& g,
00122                               leda::array< leda::d_int_set >& mcb,
00123                               const mcb::edge_num& enumb,
00124                               bool check_cycle_basis 
00125                             );
00126 
00127 extern void MCB_output_basis( const leda::graph& g,
00128                               leda::array< leda::d_int_set >& C,
00129                               const mcb::edge_num& enumb,
00130                               leda::array< leda::list< leda::edge > >& mcb );
00131 
00132 extern void MCB_output_basis( const leda::graph& g, 
00133                               const leda::array< leda::list<leda::edge> >& mcb,
00134                               const mcb::edge_num& enumb,
00135                               leda::array< leda::d_int_set >& C );
00136 
00137 extern void MCB_output_basis( const leda::graph& g,
00138                               const leda::array< mcb::spvecgf2 >& C,
00139                               const mcb::edge_num& enumb,
00140                               leda::array< leda::list< leda::edge > >& mcb );
00141 
00142 extern void MCB_output_basis( const leda::graph& g,
00143                               const leda::array< mcb::spvecgf2 >& C,
00144                               const mcb::edge_num& enumb,
00145                               leda::array< leda::d_int_set >& mcb );
00146 
00171 extern int MIN_CYCLE_BASIS_DEPINA( const leda::graph& g,
00172                             leda::array< leda::d_int_set >& mcb,
00173                             leda::array< leda::d_int_set >& proof,
00174                             const mcb::edge_num& enumb
00175                             );
00176 
00197 extern int MIN_CYCLE_BASIS_DEPINA( const leda::graph& g,
00198                             leda::array< leda::d_int_set >& mcb,
00199                             const edge_num& enumb
00200                             );
00201 
00226 extern int MIN_CYCLE_BASIS_DEPINA( const leda::graph& g,
00227                             leda::array< mcb::spvecgf2 >& mcb,
00228                             leda::array< mcb::spvecgf2 >& proof,
00229                             const edge_num& enumb
00230                             );
00231 
00252 extern int MIN_CYCLE_BASIS_DEPINA( const leda::graph& g,
00253                             leda::array< mcb::spvecgf2 >& mcb,
00254                             const edge_num& enumb
00255                             );
00256 
00278 extern int MIN_CYCLE_BASIS_DEPINA( const leda::graph& g,
00279                             leda::array< leda::list<leda::edge> >& mcb,
00280                             leda::array< leda::list<leda::edge> >& proof
00281                             );
00282 
00299 extern int MIN_CYCLE_BASIS_DEPINA( const leda::graph& g,
00300                             leda::array< leda::list<leda::edge> >& mcb
00301                             );
00302 
00303 // unweighted hybrid algorithm
00304 extern void MCB_construct_superset( const leda::graph& G,
00305                                     leda::sortseq< leda::two_tuple<int,int>, leda::d_int_set >& super, 
00306                                     const edge_num& enumb);
00307 
00308 extern void MCB_construct_unweighted_paths( const leda::graph& G,
00309         leda::node_array< leda::node_array<leda::edge> >& pred );
00310 
00337 extern int MIN_CYCLE_BASIS_HYBRID( const leda::graph& g,
00338                                    leda::array< leda::d_int_set >& mcb,
00339                                    leda::array< leda::d_int_set >& proof,
00340                                    const edge_num& enumb
00341                                  );
00342 
00363 extern int MIN_CYCLE_BASIS_HYBRID( const leda::graph& g,
00364                                    leda::array< leda::d_int_set >& mcb,
00365                                    const edge_num& enumb
00366                                  );
00367 
00390 extern int MIN_CYCLE_BASIS_HYBRID( const leda::graph& g,
00391                                    leda::array< leda::list<leda::edge> >& mcb,
00392                                    leda::array< leda::list<leda::edge> >& proof
00393                                  );
00394 
00411 extern int MIN_CYCLE_BASIS_HYBRID( const leda::graph& g,
00412                                    leda::array< leda::list<leda::edge> >& mcb
00413                                    );
00414 
00415 extern void swap( leda::d_int_set& a, leda::d_int_set& b );
00416 
00417 
00418 
00419 #line 2272 "MIN_CYCLE_BASIS.lw"
00420 template<class W, class CONT>
00421 W MIN_CYCLE_BASIS_DEPINA( const graph& g,
00422                           const edge_array<W>& len,
00423                           array< CONT >& mcb,
00424                           array< CONT >& proof,
00425                           const edge_num& enumb
00426                           );
00427 
00456 template<class W>
00457 W MIN_CYCLE_BASIS_DEPINA( const graph& g,
00458                           const edge_array<W>& len,
00459                           array< spvecgf2 >& mcb,
00460                           array< spvecgf2 >& proof,
00461                           const edge_num& enumb
00462                           )
00463 {
00464     return MIN_CYCLE_BASIS_DEPINA< W, spvecgf2 >( g,len,mcb,proof,enumb );
00465 }
00466 
00495 template<class W>
00496 W MIN_CYCLE_BASIS_DEPINA( const graph& g,
00497                           const edge_array<W>& len,
00498                           array< d_int_set >& mcb,
00499                           array< d_int_set >& proof,
00500                           const edge_num& enumb
00501                           )
00502 {
00503     return MIN_CYCLE_BASIS_DEPINA< W, d_int_set >( g,len,mcb,proof,enumb );
00504 }
00505 
00506 
00507 
00508 template<class W, class CONT>
00509 W MIN_CYCLE_BASIS_DEPINA( const graph& g,
00510                           const edge_array<W>& len,
00511                           array< CONT >& mcb,
00512                           array< CONT >& proof,
00513                           const edge_num& enumb
00514                           ) 
00515 { 
00516         
00517 #line 2703 "MIN_CYCLE_BASIS.lw"
00518 #if ! defined(LEDA_CHECKING_OFF)
00519         if ( g.is_undirected() == false )
00520                 error_handler(999,"MIN_CYCLE_BASIS: illegal graph\
00521                                   (directed?)");
00522         if ( Is_Undirected_Simple( g ) == false )
00523                 error_handler(999,"MIN_CYCLE_BASIS: illegal graph\
00524                   (parallel,anti-parallel edges or loops?)");
00525 #endif
00526 
00527 #line 2369 "MIN_CYCLE_BASIS.lw"
00528         
00529 #line 2741 "MIN_CYCLE_BASIS.lw"
00530 #if ! defined(LEDA_CHECKING_OFF)
00531 edge e1;
00532 forall_edges( e1 , g ) { 
00533         if ( len[e1] < 0 ) 
00534                 error_handler(999,"MIN_CYCLE_BASIS: illegal edge \
00535                                   (negative weight)");
00536 }
00537 #endif
00538 
00539 #line 2370 "MIN_CYCLE_BASIS.lw"
00540         
00541 #line 2729 "MIN_CYCLE_BASIS.lw"
00542 int N = enumb.dim_cycle_space();
00543 mcb.resize( N ); // set size of destination array
00544 proof.resize(N);
00545 
00546 
00547 
00548 #line 2372 "MIN_CYCLE_BASIS.lw"
00549 #ifdef LEP_STATS
00550         float Tcycle = 0.0, Torthog = 0.0, Ttemp;
00551 #endif
00552 
00553         array< CONT >& C = mcb;
00554         array< CONT >& S = proof;
00555         
00556 #line 2757 "MIN_CYCLE_BASIS.lw"
00557 // initialize signed graph
00558 sgraph<W,leda::bin_heap> sg( g , len, enumb ) ; 
00559 
00560 
00561 #line 2380 "MIN_CYCLE_BASIS.lw"
00562         // initialize cycles C and initial sets S's
00563         for( int i = 0 ; i < N; i++ ) { S[i].insert( i ); }
00564    
00565         W min = W(), ret = W();
00566         // start computing cycles
00567         for( int k = 0; k < N; k++ ) { 
00568                 
00569 #line 2782 "MIN_CYCLE_BASIS.lw"
00570 #ifdef LEP_STATS
00571 leda::used_time( Ttemp );
00572 #endif
00573 #line 2822 "MIN_CYCLE_BASIS.lw"
00574 #ifndef MCB_LEP_UNDIR_NO_EXCHANGE_HEURISTIC
00575 // choose the sparsest witness from the basis
00576 int minS = k;
00577 for( int r = k+1; r < N; r++ ) { 
00578     if ( S[r].size() < S[minS].size() )
00579         minS = r;
00580 }
00581 if ( minS != k ) {  // swap
00582     mcb::swap( S[k], S[minS] );
00583 }
00584 #endif
00585 
00586 #line 2786 "MIN_CYCLE_BASIS.lw"
00587 #ifdef LEP_STATS
00588 Torthog += leda::used_time( Ttemp );
00589 #endif
00590 #line 2835 "MIN_CYCLE_BASIS.lw"
00591 ret = sg.get_shortest_odd_cycle( S[k], C[k] ); 
00592 min+= ret;
00593 
00594 #line 2790 "MIN_CYCLE_BASIS.lw"
00595 #ifdef LEP_STATS
00596 Tcycle += leda::used_time( Ttemp );
00597 #endif
00598 
00599 #line 2840 "MIN_CYCLE_BASIS.lw"
00600 for( int l = k+1; l < N; l++ )   {
00601     // cycles are smaller than sets, thus it is better
00602     // to intersect C and S than S and C
00603     if ( (C[k].intersect(S[l])).size() %2 == 1 )   {
00604         S[ l ] %= S[k];
00605     }
00606 }
00607 
00608 #line 2794 "MIN_CYCLE_BASIS.lw"
00609 #ifdef LEP_STATS
00610 Torthog += leda::used_time( Ttemp );
00611 #endif
00612 
00613 
00614 #line 2387 "MIN_CYCLE_BASIS.lw"
00615         }
00616 
00617 #ifdef LEP_STATS
00618     std::cout << "LEP_STATS: cycle computation time: " << Tcycle << std::endl;
00619     std::cout << "LEP_STATS: orthogonal base maintain time: " << Torthog << std::endl;
00620 #endif
00621 
00622         return min;
00623 }
00624 
00625 
00626 #line 2403 "MIN_CYCLE_BASIS.lw"
00627 
00651 template<class W>
00652 W MIN_CYCLE_BASIS_DEPINA( const graph& g,
00653                           const edge_array<W>& len,
00654                           array< d_int_set >& mcb,
00655                           const edge_num& enumb
00656                           ) 
00657 { 
00658     array< d_int_set > proof_temp;
00659     return MIN_CYCLE_BASIS_DEPINA( g, len, mcb, proof_temp, enumb );
00660 }
00661 
00686 template<class W>
00687 W MIN_CYCLE_BASIS_DEPINA( const graph& g,
00688                           const edge_array<W>& len,
00689                           array< spvecgf2 >& mcb,
00690                           const edge_num& enumb
00691                           ) 
00692 { 
00693     array< spvecgf2 > proof_temp;
00694     return MIN_CYCLE_BASIS_DEPINA( g, len, mcb, proof_temp, enumb );
00695 }
00696 
00697 
00698 #line 2487 "MIN_CYCLE_BASIS.lw"
00699 
00719 template<class W>
00720 W MIN_CYCLE_BASIS_DEPINA( const graph& g, 
00721                           const edge_array<W>& len, 
00722                           array< list<edge> >& mcb )
00723 {
00724         edge_num enumb(g);
00725         array< d_int_set > mcb_temp, proof_temp;
00726         W min = MIN_CYCLE_BASIS_DEPINA( g, len, mcb_temp, proof_temp, enumb );
00727         // reformat output
00728         MCB_output_basis( g, mcb_temp, enumb, mcb );
00729         return min;
00730 }
00731 
00732 
00733 #line 2527 "MIN_CYCLE_BASIS.lw"
00734 
00760 template<class W>
00761 W MIN_CYCLE_BASIS_DEPINA( const graph& g, 
00762                           const edge_array<W>& len,
00763                           array< list<edge> >& mcb,
00764                           array< list<edge> >& proof) 
00765 {
00766         edge_num enumb(g);
00767         array< d_int_set > mcb_temp, proof_temp;
00768         W min = MIN_CYCLE_BASIS_DEPINA( g, len, mcb_temp, proof_temp, enumb );
00769         // reformat output
00770         MCB_output_basis( g, mcb_temp, enumb, mcb );
00771         MCB_output_basis( g, proof_temp, enumb, proof );
00772         return min;
00773 }
00774 
00775 
00776 #line 4329 "MIN_CYCLE_BASIS.lw"
00777 template<class W>
00778 bool MIN_CYCLE_BASIS_DEPINA_CHECK( const graph& g,
00779                                    const edge_array<W>& len,
00780                                    array< d_int_set >& mcb,
00781                                    array< d_int_set >& proof,
00782                                    const edge_num& enumb ) 
00783 
00784 /*\Mfunc $g$ is an undirected graph and $len$ is a non-negative length function on 
00785 the edges of $g$. $mcb$ is a minimum cycle basis and $proof$ a certificate of 
00786 optimality of $mcb$. \\
00787 $enumb$ is the numbering on the edges of the graph which was used in order to 
00788 construct the minimum cycle basis. \\
00789 The function checks whether the $mcb$ is indeed a minimum cycle basis. \\
00790 The running time is $O( m^3 )$ where $m$ are the number of edges of $g$. \\
00791 \precond $G$ is undirected, simple and loopfree \\
00792 \precond $len$ is non-negative \\
00793 \precond $enumb$ is the same numbering as the one used to construct the $mcb$.
00794 */
00795 {
00796         
00797 #line 2703 "MIN_CYCLE_BASIS.lw"
00798 #if ! defined(LEDA_CHECKING_OFF)
00799         if ( g.is_undirected() == false )
00800                 error_handler(999,"MIN_CYCLE_BASIS: illegal graph\
00801                                   (directed?)");
00802         if ( Is_Undirected_Simple( g ) == false )
00803                 error_handler(999,"MIN_CYCLE_BASIS: illegal graph\
00804                   (parallel,anti-parallel edges or loops?)");
00805 #endif
00806 
00807 #line 4349 "MIN_CYCLE_BASIS.lw"
00808         
00809 #line 2741 "MIN_CYCLE_BASIS.lw"
00810 #if ! defined(LEDA_CHECKING_OFF)
00811 edge e1;
00812 forall_edges( e1 , g ) { 
00813         if ( len[e1] < 0 ) 
00814                 error_handler(999,"MIN_CYCLE_BASIS: illegal edge \
00815                                   (negative weight)");
00816 }
00817 #endif
00818 
00819 #line 4350 "MIN_CYCLE_BASIS.lw"
00820         sgraph<W,leda::bin_heap> sg( g, len, enumb );
00821 
00822         if ( MCB_verify_basis( g, mcb, enumb, true ) == false ||
00823              MCB_verify_basis( g, proof, enumb, false ) == false ||
00824              mcb.size() != proof.size() ) 
00825                 return false;
00826 
00827         // verify cycles
00828         W cycle_len;
00829         list<int> L;
00830         for( int i = 0; i < mcb.size(); i++ ) { 
00831                 d_int_set TEMP;
00832                 W min = sg.get_shortest_odd_cycle( proof[i] , TEMP );
00833 
00834                 // compute cycle length
00835                 cycle_len = W();
00836                 L.clear();
00837                 mcb[i].get_element_list(L);
00838                 int el;
00839                 forall( el, L ) cycle_len += len[ enumb(el) ];
00840         
00841                 if ( cycle_len != min ) 
00842                         return false;
00843         }
00844         return true;
00845 }
00846 
00847 template<class W>
00848 bool MIN_CYCLE_BASIS_DEPINA_CHECK( const graph& g,
00849                                    const edge_array<W>& len,
00850                                    array< spvecgf2 >& mcb,
00851                                    array< spvecgf2 >& proof,
00852                                    const edge_num& enumb ) 
00853 
00854 {
00855 #if ! defined(LEDA_CHECKING_OFF)
00856     if ( mcb.size() != proof.size() || mcb.size() != enumb.dim_cycle_space() ) 
00857         error_handler(999,"MIN_CYCLE_BASIS: wrong array sizes :(");
00858 #endif
00859     array< d_int_set > mcbD;
00860     array< d_int_set > proofD;
00861     mcbD.resize( mcb.size() ); 
00862     proofD.resize( proof.size() );
00863     for( int i = 0; i < mcb.size(); i++ ) { 
00864         mcbD[i] = mcb[i].to_d_int_set();
00865         proofD[i] = proof[i].to_d_int_set();
00866     }
00867     return MIN_CYCLE_BASIS_DEPINA_CHECK( g, len, mcbD, proofD, enumb );
00868 }
00869 
00870 
00871 
00872 #line 4407 "MIN_CYCLE_BASIS.lw"
00873 template<class W>
00874 bool MIN_CYCLE_BASIS_DEPINA_CHECK( const graph& g,
00875                                    const edge_array<W>& len,
00876                                    array< list<edge> >& mcb,
00877                                    array< list<edge> >& proof 
00878                                    )
00879 {
00880         edge_num enumb( g );
00881         array< d_int_set > mcb_temp, proof_temp;
00882         MCB_output_basis( g, mcb, enumb, mcb_temp );
00883         MCB_output_basis( g, proof, enumb, proof_temp );
00884         return MIN_CYCLE_BASIS_DEPINA_CHECK( g, len, mcb_temp, proof_temp, enumb );
00885 }
00886 
00887 
00888 #line 3754 "MIN_CYCLE_BASIS.lw"
00889 // construct unique paths from v to u
00890 template<class W>
00891 void MCB_construct_paths( const graph& G,
00892         const edge_array<W>& len,
00893         node_array< node_array<edge> >& pred
00894         )
00895 {
00896         // initialize
00897         node v;
00898         node_array<W> dist(G);
00899         
00900         // calculate paths
00901         forall_nodes( v, G ) {
00902                 pred[v].init( G, nil );
00903         
00904                 // run dijkstra
00905                 DIJKSTRA_T<W>( G, v, len, dist, pred[v] );
00906         }
00907 }
00908 
00909       
00910 // construct Horton's superset of MCB
00911 template<class W>
00912 void MCB_construct_superset( const graph& G,
00913                 const edge_array<W>& len,
00914                 sortseq< three_tuple<W,int,int>, d_int_set >& super, 
00915                 const edge_num& enumb)
00916 {
00917     
00918 #line 3833 "MIN_CYCLE_BASIS.lw"
00919 // initialize
00920 d_int_set C;
00921 node v,w,u,vz,ezs,ezt; 
00922 edge e,ez;
00923 
00924 int c = 0;
00925 node_array<int> degree(G,0);
00926 node_set touched( G );
00927 bool dege;
00928 
00929 #line 3783 "MIN_CYCLE_BASIS.lw"
00930     W min;
00931 
00932     // construct paths
00933     node_array< node_array<edge> > pred( G );
00934     MCB_construct_paths<W>( G, len, pred );
00935         
00936     // loop - for all nodes
00937     forall_nodes( v , G ) { 
00938 
00939         // loop - for all edges
00940         forall_edges( e, G ) { 
00941             
00942 #line 3853 "MIN_CYCLE_BASIS.lw"
00943 dege = false;
00944 
00945 w = G.source(e);
00946 u = G.target(e);
00947 
00948 // valid?
00949 if ( v == w || v == u || 
00950      pred[ v ][ w ] == nil || pred[ v ][ u ] == nil ||
00951      pred[ v ][ w ] == e || pred[ v ][ u ] == e || 
00952      pred[ w ][ v ] == e || pred[ u ][ v ] == e ) 
00953         continue;
00954 
00955 // try to construct cycle
00956 C.clear();
00957 
00958 // insert e
00959 C.insert( enumb(e) );
00960 ezs = G.source( e );
00961 ezt = G.target( e );
00962 degree[ ezs ]++;
00963 degree[ ezt ]++;
00964 touched.insert( ezs );
00965 touched.insert( ezt );
00966 
00967 
00968 
00969 #line 3796 "MIN_CYCLE_BASIS.lw"
00970             min = len[ e ];
00971 
00972             // create two paths
00973             int en;
00974             node x,y; 
00975 
00976             // make sure path is unique
00977             if ( v->id() < w->id() ) { y = v; x = w; }
00978             else { y = w; x = v; }
00979             
00980 #line 3889 "MIN_CYCLE_BASIS.lw"
00981 while( pred[ y ][ x ] != nil && dege == false ) {
00982         ez = pred[ y ][ x ];
00983         en = enumb( ez );
00984         if ( ! C.member( en ) ) {
00985                 C.insert( en );
00986                 ezs = G.source( ez );
00987                 ezt = G.target( ez );
00988                 degree[ ezs ]++;
00989                 degree[ ezt ]++;
00990                 if ( degree[ ezs ] > 2 || degree[ ezt ] > 2 )
00991                         dege = true;
00992                 touched.insert( ezs );
00993                 touched.insert( ezt );
00994                 min += len[ ez ];
00995         }
00996         x = G.opposite( ez, x );
00997 }
00998 
00999 #line 3805 "MIN_CYCLE_BASIS.lw"
01000                                      
01001             if ( v->id() < u->id() ) { y = v; x = u; }
01002             else { y = u; x = v; }
01003             
01004 #line 3889 "MIN_CYCLE_BASIS.lw"
01005 while( pred[ y ][ x ] != nil && dege == false ) {
01006         ez = pred[ y ][ x ];
01007         en = enumb( ez );
01008         if ( ! C.member( en ) ) {
01009                 C.insert( en );
01010                 ezs = G.source( ez );
01011                 ezt = G.target( ez );
01012                 degree[ ezs ]++;
01013                 degree[ ezt ]++;
01014                 if ( degree[ ezs ] > 2 || degree[ ezt ] > 2 )
01015                         dege = true;
01016                 touched.insert( ezs );
01017                 touched.insert( ezt );
01018                 min += len[ ez ];
01019         }
01020         x = G.opposite( ez, x );
01021 }
01022 
01023 #line 3808 "MIN_CYCLE_BASIS.lw"
01024                                      
01025                         
01026             // init degree array, and check for degeneracy
01027             while( touched.empty() == false ) {
01028                 vz = touched.choose();
01029                 touched.del( vz );
01030                 if ( degree[ vz ] == 1 ) dege = true;
01031                 degree[ vz ] = 0;
01032             }
01033 
01034             if ( dege == true ) continue;
01035 
01036             // add cycle to superset
01037             three_tuple<W,int,int> tt( min, C.size(), c++ ); 
01038             super.insert( tt, C );
01039         }
01040     }
01041 }
01042 
01043 
01044 #line 4011 "MIN_CYCLE_BASIS.lw"
01045 
01073 template<class W>
01074 W MIN_CYCLE_BASIS_HYBRID( const graph& g,
01075                           const edge_array<W>& len,
01076                           array< d_int_set >& mcb,
01077                           array< d_int_set >& proof,
01078                           const edge_num& enumb
01079                           ) 
01080 { 
01081     
01082 #line 2703 "MIN_CYCLE_BASIS.lw"
01083 #if ! defined(LEDA_CHECKING_OFF)
01084         if ( g.is_undirected() == false )
01085                 error_handler(999,"MIN_CYCLE_BASIS: illegal graph\
01086                                   (directed?)");
01087         if ( Is_Undirected_Simple( g ) == false )
01088                 error_handler(999,"MIN_CYCLE_BASIS: illegal graph\
01089                   (parallel,anti-parallel edges or loops?)");
01090 #endif
01091 
01092 #line 4048 "MIN_CYCLE_BASIS.lw"
01093     
01094 #line 2741 "MIN_CYCLE_BASIS.lw"
01095 #if ! defined(LEDA_CHECKING_OFF)
01096 edge e1;
01097 forall_edges( e1 , g ) { 
01098         if ( len[e1] < 0 ) 
01099                 error_handler(999,"MIN_CYCLE_BASIS: illegal edge \
01100                                   (negative weight)");
01101 }
01102 #endif
01103 
01104 #line 4049 "MIN_CYCLE_BASIS.lw"
01105     
01106 #line 2729 "MIN_CYCLE_BASIS.lw"
01107 int N = enumb.dim_cycle_space();
01108 mcb.resize( N ); // set size of destination array
01109 proof.resize(N);
01110 
01111 
01112 
01113 #line 4051 "MIN_CYCLE_BASIS.lw"
01114     array< d_int_set >& C = mcb;
01115     array< d_int_set >& S = proof;
01116     
01117     // initialize cycles C and initial sets S's
01118     for( int i = 0 ; i < N; i++ ) { S[i].insert( i ); }
01119 
01120     // construct superset
01121     sortseq< three_tuple<W,int,int> ,d_int_set> super( leda::compare );
01122     MCB_construct_superset<W>( g, len, super, enumb );
01123 
01124 #ifdef LEP_STATS
01125     static int lep_stats_queries = 0;
01126     std::cout << "LEP_STATS: horton set size: " << super.size() << std::endl;
01127 #endif
01128 
01129     W min = W(), ret = W();
01130     leda::seq_item s;
01131     // start computing cycles
01132     for( int k = 0; k < N; k++ ) { 
01133         
01134 #line 4094 "MIN_CYCLE_BASIS.lw"
01135 #ifdef LEP_STATS
01136 lep_stats_queries++;
01137 #endif
01138 
01139 // compute shortest odd cycle
01140 s = super.min_item();
01141 bool f = false;
01142 while ( s != nil ) { 
01143     if ( ( (super[s]).intersect( S[k] ) ).size() % 2 == 1 ) { // is odd
01144         C[k] = super[s];
01145         ret = super.key( s ).first();
01146         super.del_item( s );
01147         f = true; // found
01148         break;
01149     }
01150     s = super.succ( s );
01151 
01152 #ifdef LEP_STATS
01153     lep_stats_queries++;
01154 #endif
01155 }
01156 if ( f == false )
01157     error_handler(999,"MIN_CYCLE_BASIS (HYBRID):\
01158             superset contains no MCB :(");
01159 min += ret;
01160 
01161 #line 4071 "MIN_CYCLE_BASIS.lw"
01162         
01163 #line 2840 "MIN_CYCLE_BASIS.lw"
01164 for( int l = k+1; l < N; l++ )   {
01165     // cycles are smaller than sets, thus it is better
01166     // to intersect C and S than S and C
01167     if ( (C[k].intersect(S[l])).size() %2 == 1 )   {
01168         S[ l ] %= S[k];
01169     }
01170 }
01171 
01172 #line 4072 "MIN_CYCLE_BASIS.lw"
01173     }
01174 
01175 #ifdef LEP_STATS
01176     std::cout << "LEP_STATS: horton set queries: " << lep_stats_queries << std::endl;
01177 #endif
01178 
01179     return min;
01180 }
01181 
01182 
01183 #line 4127 "MIN_CYCLE_BASIS.lw"
01184 
01206 template<class W>
01207 W MIN_CYCLE_BASIS_HYBRID( const graph& g,
01208                           const edge_array<W>& len,
01209                           array< d_int_set >& mcb,
01210                           const edge_num& enumb
01211                           )
01212 {
01213         array< d_int_set > proof_temp;
01214         return MIN_CYCLE_BASIS_HYBRID( g, len, mcb, proof_temp, enumb );
01215 }
01216 
01241 template<class W>
01242 W MIN_CYCLE_BASIS_HYBRID( const graph& g,
01243                           const edge_array<W>& len,
01244                           array< list<edge> >& mcb,
01245                           array< list<edge> >& proof
01246                           )
01247 {
01248         array< d_int_set > mcb_temp, proof_temp;
01249         edge_num enumb( g );
01250         W min = MIN_CYCLE_BASIS_HYBRID( g, len, mcb_temp, proof_temp, enumb );
01251         MCB_output_basis( g, mcb_temp, enumb, mcb );
01252         MCB_output_basis( g, mcb_temp, enumb, proof );
01253         return min;
01254 }
01255 
01274 template<class W>
01275 W MIN_CYCLE_BASIS_HYBRID( const graph& g,
01276                           const edge_array<W>& len,
01277                           array< list<edge> >& mcb
01278                           )
01279 {
01280         array< d_int_set > mcb_temp, proof_temp;
01281         edge_num enumb( g );
01282         W min = MIN_CYCLE_BASIS_HYBRID( g, len, mcb_temp, proof_temp, enumb );
01283         MCB_output_basis( g, mcb_temp, enumb, mcb );
01284         return min;
01285 }
01286 
01287 
01288 #line 1859 "MIN_CYCLE_BASIS.lw"
01289 } // namespace mcb end
01290 
01291 #endif  // MIN_CYCLE_BASIS_H
01292 
01293 #line 6217 "MIN_CYCLE_BASIS.lw"
01294 /* ex: set ts=8 sw=4 sts=4 noet: */
01295 
01296 

Generated on Thu Mar 30 16:45:43 2006 for mcb LEDA Extension Package by  doxygen 1.4.6