mcb_approx.h

Go to the documentation of this file.
00001 //
00002 // This program can be freely used in an academic environment
00003 // ONLY for research purposes, subject to the following restrictions:
00004 //
00005 // 1. The origin of this software must not be misrepresented; you must not
00006 //    claim that you wrote the original software. If you use this software
00007 //    an acknowledgment in the product documentation is required.
00008 // 2. Altered source versions must be plainly marked as such, and must not be
00009 //    misrepresented as being the original software.
00010 // 3. This notice may not be removed or altered from any source distribution.
00011 //
00012 // Any other use is strictly prohibited by the author, without an explicit 
00013 // permission.
00014 //
00015 // Note that this program uses the LEDA library, which is NOT free. For more 
00016 // details visit Algorithmic Solutions at http://www.algorithmic-solutions.com/
00017 // There is also a free version of LEDA 6.0 or newer.
00018 //
00019 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00020 // ! Any commercial use of this software is strictly !
00021 // ! prohibited without explicit permission by the   !
00022 // ! author.                                         !
00023 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00024 //
00025 // This software is distributed in the hope that it will be useful,
00026 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00028 //
00029 // Copyright (C) 2004-2008 - Dimitris Michail <michail@mpi-inf.mpg.de>, <dmixdim@googlemail.com> 
00030 //
00031 // $Id: mcb_approx.h 7025 2008-04-17 15:01:11Z dmichail $ 
00032 //
00033 
00040 #ifndef UMCB_APPROX_H
00041 #define UMCB_APPROX_H
00042 
00043 #include <LEP/mcb/config.h>
00044 #include <LEP/mcb/umcb.h>
00045 #include <LEP/mcb/spanner.h>
00046 #include <LEP/mcb/ushortpath.h>
00047 #include <LEP/mcb/dmcb.h>
00048 
00049 #ifdef LEDA_GE_V5
00050 #include <LEDA/graph/edge_map.h>
00051 #include <LEDA/graph/node_map.h>
00052 #else
00053 #include <LEDA/edge_map.h>
00054 #include <LEDA/node_map.h>
00055 #endif
00056 
00057 namespace mcb 
00058 { 
00059 
00060 #if defined(LEDA_NAMESPACE)
00061     using leda::node;
00062     using leda::node_map;
00063     using leda::edge;
00064     using leda::edge_array;
00065     using leda::edge_map;
00066 #endif
00067 
00068     
00069     template<typename W, class Container>
00070         class mcb_approx { 
00071             public:
00072                 typedef W result_type;
00073 
00074                 mcb_approx( const graph& g_, 
00075                         int k_,
00076                         array< Container >& mcb_, 
00077                         const mcb::edge_num& enumb_ )
00078                     : g(g_), k(k_), mcb(mcb_), enumb(enumb_), Tcycles(0.0), Tsubgraph(0.0)
00079                     { 
00080                     }
00081 
00082                 virtual ~mcb_approx() {}
00083 
00084                 W run() { 
00085                     checkGraphPreconditions();
00086                     checkEdgeLengthPreconditions();
00087                     initialize();
00088 
00089                     constructSpanner();
00090 
00091                     edge_num spanner_enumb( spanner );
00092                     array< Container > spanner_mcb;
00093                     constructSpannerMCB( spanner_enumb, spanner_mcb );
00094 
00095                     constructPartialMCBfromSpanner( spanner_enumb, spanner_mcb );
00096                     translateSpannerMCBToGraphPartialMCB( spanner_enumb, spanner_mcb );
00097 
00098                     return length;
00099                 }
00100 
00101             private:
00102 
00103                 void checkGraphPreconditions() { 
00104 #if ! defined(LEDA_CHECKING_OFF)
00105                     if ( Is_Loopfree( g ) == false )
00106                         error_handler(999,"UMCB_APPROX: illegal graph (loops?)");
00107                     if ( k <= 0 )
00108                         error_handler(999,"UMCB_APPROX: illegal value of k, non-positive?");
00109 #endif
00110                 }
00111 
00112                 virtual void checkEdgeLengthPreconditions() {}
00113 
00114                 void initialize() { 
00115                     length = W();
00116                     N = enumb.dim_cycle_space();
00117                     mcb.resize( N );
00118                 }
00119 
00120                 virtual void constructSpanner() = 0;
00121 
00122                 virtual void constructSpannerMCB( const edge_num& spanner_enumb, array< Container >& spanner_mcb ) = 0;
00123 
00124                 virtual void constructPartialMCBfromSpanner( const edge_num& spanner_enumb, const array< Container >& spanner_mcb )  = 0;
00125 
00126                 virtual void translateSpannerMCBToGraphPartialMCB( const edge_num& spanner_enumb, 
00127                                                            const array<Container>& spanner_mcb ) = 0;
00128 
00129             protected:
00130                 const graph& g;
00131                 int k;
00132                 array< Container >& mcb;
00133                 const mcb::edge_num& enumb;
00134                 W length;
00135                 int N;
00136 
00137                 // spanner related
00138                 graph spanner;
00139                 edge_array<W> spanner_len;
00140                 node_map<node> node_g_to_spanner;
00141                 node_map<node> node_spanner_to_g;
00142                 edge_map<edge> edge_g_to_spanner;
00143                 edge_map<edge> edge_spanner_to_g;
00144 
00145                 // statistics
00146                 float Tcycles, Tsubgraph, Ttemp;
00147         };
00148 
00149 
00150     // undirected case
00151     template<typename W, class Container>
00152         class umcb_approx : public mcb_approx< W, Container > 
00153         { 
00154             public:
00155                 typedef mcb_approx<W,Container> base_type;
00156 
00157                 umcb_approx( const graph& g_, 
00158                         int k_,
00159                         array< Container >& mcb_, 
00160                         const mcb::edge_num& enumb_ )
00161                     : base_type( g_, k_, mcb_, enumb_ )
00162                     { 
00163                     }
00164 
00165                 ~umcb_approx() {}
00166 
00167             private:
00168 
00169                 virtual void constructSpannerMCB( const edge_num& spanner_enumb, array<Container>& spanner_mcb ) 
00170                 { 
00171                     array< Container > spanner_proof;
00172 
00173 #ifdef LEP_DEBUG_OUTPUT
00174                     std::cout << "Computing " << spanner_enumb.dim_cycle_space() << " cycles"; 
00175                     std::cout << " by the MCB of spanner..." << std::endl;
00176 #endif
00177 
00178                     length += UMCB_SVA<W,Container>( spanner, spanner_len,
00179                             spanner_mcb, spanner_proof, spanner_enumb );
00180                 }
00181 
00182                 virtual void translateSpannerMCBToGraphPartialMCB( const edge_num& spanner_enumb, 
00183                                                            const array<Container>& spanner_mcb ) 
00184                 { 
00185                     edge e;
00186                     int extracycles = spanner_enumb.dim_cycle_space();
00187                     for( int i = 0; i < extracycles; ++i ) 
00188                     {
00189                         mcb[ N - extracycles + i ] = Container();
00190 
00191                         int j = 0;
00192                         forall( j, spanner_mcb[ i ] ) 
00193                         { 
00194                             // translate to numbering of original graph 
00195                             // and add to cycle
00196                             e = edge_spanner_to_g[ spanner_enumb(j) ];
00197                             mcb[ N - extracycles + i ].insert( enumb( e ) );
00198                         }
00199                         // fix correct ordering
00200                         mcb[ N - extracycles + i ].sort();
00201                     }
00202 
00203 #ifdef LEP_STATS
00204                     Tsubgraph += leda::used_time( Ttemp );
00205                     std::cout << "LEP_STATS: spanner cycles time: " << Tcycles << std::endl;
00206                     std::cout << "LEP_STATS: subgraph MCB time  : " << Tsubgraph << std::endl;
00207 #endif
00208                 }
00209 
00210                 using base_type::length;
00211                 using base_type::spanner;
00212                 using base_type::spanner_len;
00213                 using base_type::N;
00214                 using base_type::mcb;
00215                 using base_type::edge_spanner_to_g;
00216                 using base_type::enumb;
00217         };
00218 
00219     // directed case
00220     template<typename W>
00221         class dmcb_approx : public mcb_approx<W,mcb::spvecfp> 
00222         { 
00223             public:
00224                 typedef mcb_approx<W,mcb::spvecfp> base_type;
00225 
00226                 dmcb_approx( const graph& g_, 
00227                         int k_,
00228                         array< mcb::spvecfp >& mcb_, 
00229                         const mcb::edge_num& enumb_,
00230                         double error_ 
00231                     )
00232                     : base_type( g_, k_, mcb_, enumb_ ), error(error_), prime(3), minimizeErrorProb(true)
00233                     { 
00234                     }
00235 
00236                 dmcb_approx( const graph& g_, 
00237                         int k_,
00238                         array< mcb::spvecfp >& mcb_, 
00239                         const mcb::edge_num& enumb_,
00240                         ptype prime_
00241                     )
00242                     : base_type( g_, k_, mcb_, enumb_ ), error(0.375), prime(prime_), minimizeErrorProb(false)
00243                     { 
00244                     }
00245 
00246                 ~dmcb_approx() {}
00247 
00248             protected:
00249 
00250                 ptype getPrime( const edge_num& spanner_enumb, const array<mcb::spvecfp>& spanner_mcb ) 
00251                 { 
00252                     return ( spanner_enumb.dim_cycle_space() > 0 ) ? spanner_mcb[0].pvalue() : 3;
00253                 }
00254 
00255             private:
00256 
00257                 virtual void constructSpannerMCB( const edge_num& spanner_enumb, array<mcb::spvecfp>& spanner_mcb ) 
00258                 { 
00259                     array<spvecfp> spanner_proof;
00260 
00261 #ifdef LEP_DEBUG_OUTPUT
00262                     std::cout << "Computing " << spanner_enumb.dim_cycle_space() << " cycles"; 
00263                     std::cout << " by the MCB of spanner..." << std::endl;
00264 #endif
00265 
00266                     if ( minimizeErrorProb )
00267                         length += DMCB<W>( spanner, spanner_len,
00268                                 spanner_mcb, spanner_proof, spanner_enumb, error );
00269                     else 
00270                         length += DMCB<W>( spanner, spanner_len,
00271                                 spanner_mcb, spanner_proof, spanner_enumb, prime );
00272 
00273                 }
00274 
00275                 virtual void translateSpannerMCBToGraphPartialMCB( const edge_num& spanner_enumb, 
00276                                                            const array<spvecfp>& spanner_mcb ) 
00277                 { 
00278                     edge e;
00279                     int extracycles = spanner_enumb.dim_cycle_space();
00280                     for( int i = 0; i < extracycles; ++i )
00281                     {
00282                         mcb[ N - extracycles + i] = mcb::spvecfp( getPrime( spanner_enumb, spanner_mcb ) );
00283 
00284                         leda::list_item it = spanner_mcb[i].first();
00285                         while( it != nil ) {
00286                             e = edge_spanner_to_g[ spanner_enumb( spanner_mcb[i].index( it ) ) ];
00287                             mcb[ N - extracycles + i ].append( enumb(e), spanner_mcb[i].inf( it ) );
00288                             it = spanner_mcb[i].succ( it );
00289                         }
00290                         mcb[ N - extracycles + i ].sort(); // fix ordering
00291                     }
00292 
00293 #ifdef LEP_STATS
00294                     Tsubgraph += leda::used_time( Ttemp );
00295                     std::cout << "LEP_STATS: spanner cycles time: " << Tcycles << std::endl;
00296                     std::cout << "LEP_STATS: subgraph MCB time  : " << Tsubgraph << std::endl;
00297 #endif
00298                 }
00299         
00300                 using base_type::length;
00301                 using base_type::spanner;
00302                 using base_type::spanner_len;
00303                 using base_type::N;
00304                 using base_type::mcb;
00305                 using base_type::edge_spanner_to_g;
00306                 using base_type::enumb;
00307 
00308             private:
00309                 double error;
00310                 ptype  prime;
00311                 bool   minimizeErrorProb;
00312         };
00313 
00314 
00315 
00316                     
00317     // weighted undirected case
00318     template<typename W, class Container>
00319         class weighted_umcb_approx : public umcb_approx<W,Container>
00320         { 
00321             public:
00322                 typedef umcb_approx<W,Container> base_type;
00323 
00324                 weighted_umcb_approx( const graph& g_, 
00325                         const edge_array<W>& len_,
00326                         int k_,
00327                         array< Container >& mcb_, 
00328                         const mcb::edge_num& enumb_ )
00329                     : base_type( g_, k_, mcb_, enumb_ ), len(len_)
00330                     { 
00331                     }
00332 
00333                 weighted_umcb_approx( const graph& g_, 
00334                         int k_,
00335                         array< Container >& mcb_, 
00336                         const mcb::edge_num& enumb_ )
00337                     : base_type( g_, k_, mcb_, enumb_ ), len(g_,1)
00338                     { 
00339                     }
00340 
00341                 virtual ~weighted_umcb_approx() {}
00342 
00343             private:
00344 
00345                 virtual void checkEdgeLengthPreconditions() { 
00346 #if ! defined(LEDA_CHECKING_OFF)
00347                     edge e;
00348                     forall_edges( e , g ) { 
00349                         if ( len[e] < 0 ) 
00350                             error_handler(999,"UMCB_APPROX: illegal edge (negative weight?)");
00351                     }
00352 #endif
00353                 }
00354 
00355                 virtual void constructSpanner() 
00356                 { 
00357 #ifdef LEP_STATS
00358                     leda::used_time( Ttemp );
00359 #endif
00360                     mcb::detail::SPANNER( g, len, k, spanner, 
00361                             node_g_to_spanner, node_spanner_to_g,
00362                             edge_g_to_spanner, edge_spanner_to_g,
00363                             enumb);
00364 
00365                     // construct spanner edge lengths
00366                     edge e;
00367                     spanner_len.init( spanner );
00368                     forall_edges( e, spanner ) { 
00369                         spanner_len[ e ] = len[ edge_spanner_to_g[ e ] ];
00370                     }
00371                 }
00372 
00373                 virtual void constructPartialMCBfromSpanner( const edge_num& spanner_enumb, const array< Container >& spanner_mcb )
00374                 { 
00375                     detail::ushortestpaths<W> usp( spanner, spanner_len );
00376                     int i = 0;
00377                     edge e, f;
00378                     forall_edges( e, g ) { 
00379                         if ( edge_g_to_spanner[e] == nil ) { 
00380                             mcb[i] = Container();
00381 
00382                             // compute shortest path on spanner
00383                             node spanner_s = node_g_to_spanner[ g.source(e) ];
00384                             node spanner_t = node_g_to_spanner[ g.target(e) ];
00385                             usp.compute_shortest_path( spanner_s, spanner_t  );
00386 
00387 #if ! defined(LEDA_CHECKING_OFF)
00388                             assert( usp.is_reachable( spanner_t ) && usp.pred( spanner_s ) == nil );
00389 #endif
00390 
00391                             // form cycle
00392                             W cycle_len = W();
00393                             node spanner_w = spanner_t;
00394                             while( usp.pred( spanner_w ) != nil ) { 
00395                                 f = usp.pred( spanner_w );
00396                                 mcb[i].insert( enumb( edge_spanner_to_g[ f ] ) );
00397                                 cycle_len += len[ edge_spanner_to_g[ f ] ];
00398                                 spanner_w = spanner.opposite( f, spanner_w );
00399                             }
00400                             mcb[i].insert( enumb( e ) );
00401                             cycle_len += len[ e ];
00402                             mcb[i].sort(); // fix correct ordering
00403 
00404                             // now update global cycles length
00405 #if ! defined(LEDA_CHECKING_OFF)
00406                             if ( cycle_len < 0 ) 
00407                                 error_handler(999,"UMCB_APPROX: computed cycle with negative length!");
00408 #endif
00409                             length += cycle_len;
00410 
00411                             i++;
00412                         }
00413                     }
00414 
00415 #ifdef LEP_STATS
00416                     Tcycles += leda::used_time( Ttemp );
00417 #endif
00418 #ifdef LEP_DEBUG_OUTPUT
00419                     std::cout << "Spanner has " << spanner.number_of_edges() << " edges..." << std::endl;
00420                     std::cout << "Computed " << i << " cycles fast..." << std::endl;
00421 #endif
00422                 }
00423 
00424             private:
00425                 const edge_array<W> len;
00426 
00427                 using base_type::g;
00428                 using base_type::k;
00429                 using base_type::length;
00430                 using base_type::enumb;
00431                 using base_type::mcb;
00432                 using base_type::spanner;
00433                 using base_type::spanner_len;
00434                 using base_type::node_g_to_spanner;
00435                 using base_type::node_spanner_to_g;
00436                 using base_type::edge_g_to_spanner;
00437                 using base_type::edge_spanner_to_g;
00438         };
00439 
00440     // weighted directed case
00441     template<typename W>
00442         class weighted_dmcb_approx : public dmcb_approx<W>
00443         { 
00444             public:
00445                 typedef dmcb_approx<W> base_type;
00446 
00447                 weighted_dmcb_approx( const graph& g_, 
00448                         const edge_array<W>& len_,
00449                         int k_,
00450                         array< spvecfp >& mcb_, 
00451                         const mcb::edge_num& enumb_, 
00452                         double error )
00453                     : base_type( g_, k_, mcb_, enumb_, error ), len(len_)
00454                     { 
00455                     }
00456 
00457                 weighted_dmcb_approx( const graph& g_, 
00458                         int k_,
00459                         array< spvecfp >& mcb_, 
00460                         const mcb::edge_num& enumb_, 
00461                         double error )
00462                     : base_type( g_, k_, mcb_, enumb_, error ), len(g_,1)
00463                     { 
00464                     }
00465 
00466                 weighted_dmcb_approx( const graph& g_, 
00467                         const edge_array<W>& len_,
00468                         int k_,
00469                         array< spvecfp >& mcb_, 
00470                         const mcb::edge_num& enumb_, 
00471                         ptype prime )
00472                     : base_type( g_, k_, mcb_, enumb_, prime ), len(len_)
00473                     { 
00474                     }
00475 
00476                 weighted_dmcb_approx( const graph& g_, 
00477                         int k_,
00478                         array< spvecfp >& mcb_, 
00479                         const mcb::edge_num& enumb_, 
00480                         ptype prime )
00481                     : base_type( g_, k_, mcb_, enumb_, prime ), len(g_,1)
00482                     { 
00483                     }
00484 
00485                 virtual ~weighted_dmcb_approx() {}
00486 
00487             private:
00488 
00489                 virtual void checkEdgeLengthPreconditions() { 
00490 #if ! defined(LEDA_CHECKING_OFF)
00491                     edge e;
00492                     forall_edges( e , g ) { 
00493                         if ( len[e] < 0 ) 
00494                             error_handler(999,"DMCB_APPROX: illegal edge (negative weight?)");
00495                     }
00496 #endif
00497                 }
00498 
00499                 virtual void constructSpanner() 
00500                 { 
00501 #ifdef LEP_STATS
00502                     leda::used_time( Ttemp );
00503 #endif
00504                     mcb::detail::SPANNER( g, len, k, spanner, 
00505                             node_g_to_spanner, node_spanner_to_g,
00506                             edge_g_to_spanner, edge_spanner_to_g,
00507                             enumb);
00508 
00509                     // construct spanner edge lengths
00510                     edge e;
00511                     spanner_len.init( spanner );
00512                     forall_edges( e, spanner ) { 
00513                         spanner_len[ e ] = len[ edge_spanner_to_g[ e ] ];
00514                     }
00515                 }
00516 
00517                 virtual void constructPartialMCBfromSpanner( const edge_num& spanner_enumb, const array< spvecfp >& spanner_mcb )
00518                 { 
00519                     detail::ushortestpaths<W> usp( spanner, spanner_len );
00520                     int i = 0;
00521                     edge e, f;
00522                     forall_edges( e, g ) { 
00523                         if ( edge_g_to_spanner[e] == nil ) { 
00524                             mcb[i] = mcb::spvecfp( base_type::getPrime( spanner_enumb, spanner_mcb ) );
00525 
00526                             // compute shortest path on spanner
00527                             node spanner_s = node_g_to_spanner[ g.source(e) ];
00528                             node spanner_t = node_g_to_spanner[ g.target(e) ];
00529                             usp.compute_shortest_path( spanner_s, spanner_t  );
00530 
00531 #if ! defined(LEDA_CHECKING_OFF)
00532                             assert( usp.is_reachable( spanner_t ) && usp.pred( spanner_s ) == nil );
00533 #endif
00534 
00535                             // form cycle
00536                             node spanner_w = spanner_t;
00537                             while( usp.pred( spanner_w ) != nil ) {
00538                                 f = usp.pred( spanner_w );
00539                                 if ( spanner_w == spanner.source(f) ) {
00540                                     mcb[i].append( enumb( edge_spanner_to_g[ f ] ), 1 );
00541                                 }
00542                                 else {
00543                                     mcb[i].append( enumb( edge_spanner_to_g[ f ] ), -1 );
00544                                 }
00545                                 length += len[ edge_spanner_to_g[ f ] ];
00546                                 spanner_w = spanner.opposite( f, spanner_w );
00547                             }
00548                             mcb[i].append( enumb( e ) , 1 );
00549                             length += len[ e ];
00550                             mcb[i].sort(); // fix correct ordering
00551 
00552                             i++;
00553 
00554                         }
00555                     }
00556 
00557 #ifdef LEP_STATS
00558                     Tcycles += leda::used_time( Ttemp );
00559 #endif
00560 #ifdef LEP_DEBUG_OUTPUT
00561                     std::cout << "Spanner has " << spanner.number_of_edges() << " edges..." << std::endl;
00562                     std::cout << "Computed " << i << " cycles fast..." << std::endl;
00563 #endif
00564                 }
00565 
00566             private:
00567                 const edge_array<W> len;
00568 
00569                 using base_type::g;
00570                 using base_type::k;
00571                 using base_type::length;
00572                 using base_type::enumb;
00573                 using base_type::mcb;
00574                 using base_type::spanner;
00575                 using base_type::spanner_len;
00576                 using base_type::node_g_to_spanner;
00577                 using base_type::node_spanner_to_g;
00578                 using base_type::edge_g_to_spanner;
00579                 using base_type::edge_spanner_to_g;
00580         };
00581 
00582 
00583 
00584         // unweighted undirected case
00585         template<class Container>
00586         class unweighted_umcb_approx : public weighted_umcb_approx<int,Container> 
00587         { 
00588             public:
00589                 typedef weighted_umcb_approx<int,Container> base_type;
00590 
00591                 unweighted_umcb_approx( const graph& g_, 
00592                         int k_,
00593                         array< Container >& mcb_, 
00594                         const mcb::edge_num& enumb_ )
00595                     : base_type( g_, k_, mcb_, enumb_ )
00596                     { 
00597                     }
00598 
00599                 ~unweighted_umcb_approx() {}
00600 
00601             private:
00602 
00603                 virtual void checkEdgeLengthPreconditions() {}
00604 
00605                 virtual void constructPartialMCBfromSpanner( const edge_num& spanner_enumb, const array< Container >& spanner_mcb ) 
00606                 { 
00607                     detail::ubfs usp( spanner );
00608                     int i = 0;
00609                     edge e, f;
00610                     forall_edges( e, g ) { 
00611                         if ( edge_g_to_spanner[e] == nil ) { 
00612                             mcb[i] = Container();
00613 
00614                             // compute shortest path on spanner
00615                             node spanner_s = node_g_to_spanner[ g.source(e) ];
00616                             node spanner_t = node_g_to_spanner[ g.target(e) ];
00617                             usp.compute_shortest_path( spanner_s, spanner_t, 2*k-1 );
00618 
00619 #if ! defined(LEDA_CHECKING_OFF)
00620                             assert( usp.is_reachable( spanner_t ) && usp.pred( spanner_s ) == nil );
00621 #endif
00622 
00623                             // form cycle
00624                             node spanner_w = spanner_t;
00625                             while( usp.pred( spanner_w ) != nil ) { 
00626                                 f = usp.pred( spanner_w );
00627                                 mcb[i].insert( enumb( edge_spanner_to_g[ f ] ) );
00628                                 ++length;
00629                                 spanner_w = spanner.opposite( f, spanner_w );
00630                             }
00631                             mcb[i].insert( enumb( e ) );
00632                             ++length;
00633                             mcb[i].sort(); // fix correct ordering
00634 
00635                             ++i;
00636                         }
00637                     }
00638 
00639 #ifdef LEP_STATS
00640                     Tcycles += leda::used_time( Ttemp );
00641 #endif
00642 #ifdef LEP_DEBUG_OUTPUT
00643                     std::cout << "Spanner has " << spanner.number_of_edges() << " edges..." << std::endl;
00644                     std::cout << "Computed " << i << " cycles fast..." << std::endl;
00645 #endif
00646                 }
00647 
00648                 using base_type::g;
00649                 using base_type::enumb;
00650                 using base_type::mcb;
00651                 using base_type::k;
00652                 using base_type::length;
00653                 using base_type::spanner;
00654                 using base_type::edge_g_to_spanner;
00655                 using base_type::edge_spanner_to_g;
00656                 using base_type::node_g_to_spanner;
00657         };
00658 
00691     template<class W>
00692         W UMCB_APPROX( const graph& g,
00693                 const edge_array<W>& len,
00694                 const int k,
00695                 array< mcb::spvecgf2 >& mcb,
00696                 const mcb::edge_num& enumb
00697                 ) 
00698         {
00699             weighted_umcb_approx<W,mcb::spvecgf2> tmp( g, len, k, mcb, enumb );
00700             return tmp.run(); 
00701         }
00702 
00703 
00731     int UMCB_APPROX( const graph& g,
00732             const int k,
00733             array< mcb::spvecgf2 >& mcb,
00734             const mcb::edge_num& enumb
00735             );
00737     
00738 
00739     
00777     template<class W>
00778         W DMCB_APPROX( const graph& g,
00779                 const edge_array<W>& len,
00780                 const int k,
00781                 array< mcb::spvecfp >& mcb,
00782                 const mcb::edge_num& enumb,
00783                 double error = 0.375
00784                 )
00785     { 
00786             weighted_dmcb_approx<W> tmp( g, len, k, mcb, enumb, error );
00787             return tmp.run(); 
00788     }
00789 
00820     template<class W>
00821         W DMCB_APPROX( const graph& g,
00822                 const edge_array<W>& len,
00823                 const int k,
00824                 array< mcb::spvecfp >& mcb,
00825                 const mcb::edge_num& enumb,
00826                 mcb::ptype prime
00827                 )
00828     { 
00829             weighted_dmcb_approx<W> tmp( g, len, k, mcb, enumb, prime );
00830             return tmp.run(); 
00831     }
00832 
00833 
00835 
00836 
00844 
00869     template<class W>
00870         W UMCB( const graph& g,
00871                 const edge_array<W>& len,
00872                 array< mcb::spvecgf2 >& mcb,
00873                 const mcb::edge_num& enumb
00874                 ) 
00875         {
00876             return UMCB_APPROX<W>( g, len, 1, mcb, enumb );
00877         }
00878 
00902     int UMCB( const graph& g,
00903             array< mcb::spvecgf2 >& mcb,
00904             const mcb::edge_num& enumb
00905             );
00907 
00908 }
00909 
00910 #endif  // UMCB_APPROX_H
00911 
00912 /* ex: set ts=4 sw=4 sts=4 et: */
00913 
00914 

Generated on Tue Apr 22 13:40:09 2008 for mcb LEDA Extension Package by  doxygen 1.4.6