00001 #line 6220 "MIN_CYCLE_BASIS.lw"
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
00034
00035
00036
00037 #line 6081 "MIN_CYCLE_BASIS.lw"
00038
00079 #ifndef DIR_MIN_CYCLE_BASIS_H
00080 #define DIR_MIN_CYCLE_BASIS_H
00081
00082 #ifdef LEDA_GE_V5
00083 #include <LEDA/graph/graph.h>
00084 #include <LEDA/graph/edge_array.h>
00085 #include <LEDA/core/array.h>
00086 #include <LEDA/core/list.h>
00087 #include <LEDA/core/p_queue.h>
00088 #include <LEDA/core/random_source.h>
00089 #include <LEDA/core/sortseq.h>
00090 #include <LEDA/core/tuple.h>
00091 #include <LEDA/numbers/integer.h>
00092 #else
00093 #include <LEDA/graph.h>
00094 #include <LEDA/array.h>
00095 #include <LEDA/edge_array.h>
00096 #include <LEDA/list.h>
00097 #include <LEDA/integer.h>
00098 #include <LEDA/p_queue.h>
00099 #include <LEDA/random_source.h>
00100 #include <LEDA/sortseq.h>
00101 #include <LEDA/tuple.h>
00102 #endif
00103
00104 #include <LEP/mcb/edge_num.h>
00105 #include <LEP/mcb/fp.h>
00106 #include <LEP/mcb/arithm.h>
00107
00108 namespace mcb {
00109
00110 #if defined(LEDA_NAMESPACE)
00111 using leda::graph;
00112 using leda::edge;
00113 using leda::edge_array;
00114 using leda::node;
00115 using leda::node_array;
00116 using leda::array;
00117 using leda::list;
00118 using leda::node_list;
00119 using leda::integer;
00120 using leda::random_source;
00121 using leda::p_queue;
00122 using leda::pq_item;
00123 using leda::sortseq;
00124 using leda::seq_item;
00125 using leda::three_tuple;
00126 using leda::four_tuple;
00127 #endif
00128
00129
00130 #line 6256 "MIN_CYCLE_BASIS.lw"
00131
00132 void spvecfp_to_list_edges( const graph& g, const edge_num& enumb,
00133 const spvecfp& in, list<edge>& out );
00134
00135
00136 void spvecfp_to_array_ints( const graph& g, const edge_num& enumb,
00137 const ptype& p, const spvecfp& in, array<etype>& out );
00138
00139
00140 bool DMCB_verify_cycle( const graph& g,
00141 const edge_num& enumb,
00142 const spvecfp& cycle );
00143
00144
00145
00146 bool DMCB_verify_cycles( const graph& g,
00147 const edge_num& enumb,
00148 const array< spvecfp >& cycles );
00149
00150
00151 bool DMCB_verify_basis( const graph& g,
00152 const edge_num& enumb,
00153 const array< spvecfp >& B,
00154 const array< spvecfp >& X );
00155
00156
00157
00158 #line 6723 "MIN_CYCLE_BASIS.lw"
00159
00160 #define mcb_revi() first()
00161 #define mcb_dist() second()
00162 #define mcb_num_edges() third()
00163 #define mcb_pred() fourth()
00164
00165
00166 #define mcb_edge() first()
00167 #define mcb_other_node_index() second()
00168 #define mcb_other_node() third()
00169
00170
00171
00172
00173 template<class T, class PT>
00174 class dirsp {
00175
00176 typedef three_tuple< edge, PT, node > preditem;
00177 typedef four_tuple< pq_item, T, indextype, preditem > SSitem;
00178 typedef two_tuple< node, PT > pnode;
00179
00180 public:
00181
00182
00183 #line 6755 "MIN_CYCLE_BASIS.lw"
00184
00185 dirsp( const graph& g, const edge_array<T>& length ,
00186 const PT& pin, const edge_num& en ) :
00187 n(g.number_of_nodes()),
00188 m(g.number_of_edges()),
00189 p( pin ),
00190 G( g ),
00191 len ( length ),
00192 enumb( en ),
00193 SS( mcb::compare ),
00194 cycle ( m ),
00195 nodeid( g ),
00196 marked( g, 0 ),
00197 Xe( g )
00198 {
00199
00200 indextype i = 0;
00201 node v;
00202 forall_nodes( v, g ) {
00203 nodeid[ v ] = i;
00204 i++;
00205 }
00206 }
00207
00208
00209
00210
00211 void reinit( const PT& pin ) {
00212 p = pin;
00213 }
00214
00215
00216 ~dirsp() {
00217 }
00218
00219
00220 #line 6807 "MIN_CYCLE_BASIS.lw"
00221
00222 spvecfp get_shortest_cycle( const spvecfp& X , T& weight ) {
00223
00224
00225 fill_X( X );
00226
00227
00228 weight = run_shortest_paths();
00229
00230
00231 spvecfp ret( m, p );
00232 for( indextype i = 0; i < m; i++ ) {
00233 if ( cycle[ i ] != 0 ) {
00234 ret.append( i + 1 , cycle[i] );
00235 }
00236 }
00237
00238 return ret;
00239 }
00240
00241 private:
00242
00243
00244 void fill_X( const spvecfp& X ) {
00245 edge e;
00246 forall_edges( e, G )
00247 Xe[ e ] = 0;
00248
00249 list_item li = X.first();
00250 while( li != nil ) {
00251
00252
00253 Xe[ enumb( X.index( li ) - 1 ) ] = X.inf( li ) ;
00254 li = X.succ( li );
00255 }
00256 }
00257
00258
00259 #line 6851 "MIN_CYCLE_BASIS.lw"
00260
00261 void record_cycle( const PT& t, array< etype >& cyc ) {
00262 cyc.init( 0 );
00263
00264 PT cur = t;
00265 seq_item sicur = SS.lookup( cur );
00266 node u;
00267 edge e;
00268 while( SS[ sicur ].mcb_pred().mcb_edge() != nil ) {
00269
00270 u = SS[ sicur ].mcb_pred().mcb_other_node();
00271 e = SS[ sicur ].mcb_pred().mcb_edge();
00272 if ( u == G.target( e ) ) {
00273 cyc[ enumb( e ) ] = 1;
00274 }
00275 else {
00276 cyc[ enumb( e ) ] = -1;
00277 }
00278
00279 cur = SS[ sicur ].mcb_pred().mcb_other_node_index();
00280 sicur = SS.lookup( cur );
00281 }
00282 }
00283
00284
00285 #line 6883 "MIN_CYCLE_BASIS.lw"
00286
00287 inline PT get_revi_index( const node& v, const PT& level ) {
00288 return level * n + nodeid[ v ];
00289 }
00290
00291
00292 #line 6899 "MIN_CYCLE_BASIS.lw"
00293
00294 void init_used_dijkstra() {
00295
00296 while( marked_touched.empty() == false )
00297 marked[ marked_touched.pop() ] = 0;
00298
00299
00300 SS.clear();
00301
00302
00303 PQ.clear();
00304 }
00305
00306
00307 #line 6972 "MIN_CYCLE_BASIS.lw"
00308
00309 T run_shortest_paths( ) {
00310
00311 T minall = T(0);
00312 indextype minall_num_edges = 0;
00313 bool is_minall_inf = true;
00314
00315
00316 #line 6991 "MIN_CYCLE_BASIS.lw"
00317 node v;
00318 forall_nodes( v, G ) {
00319
00320 T min = T(0);
00321 indextype min_num_edges = 0;
00322 bool is_min_inf = true;
00323
00324
00325 PT vi = get_revi_index( v, 0 );
00326 SS.insert( vi ,
00327 SSitem( PQ.insert( T(0) , pnode( v, 0 ) ),
00328 T( 0 ),
00329 0,
00330 preditem( nil, 0 , nil )
00331 )
00332 );
00333
00334
00335 #line 7021 "MIN_CYCLE_BASIS.lw"
00336
00337 pq_item pqi;
00338 node u, w;
00339 PT ul, wl;
00340 PT uindex, windex;
00341 seq_item siu, siw;
00342 edge e;
00343 while( PQ.empty() == false ) {
00344
00345 pqi = PQ.find_min();
00346 u = PQ[ pqi ].first();
00347 ul = PQ[ pqi ].second();
00348 PQ.del_item( pqi );
00349
00350
00351 uindex = get_revi_index( u, ul );
00352 siu = SS.lookup( uindex );
00353
00354
00355 if ( u == v && ul != 0 ) {
00356 min = SS[ siu ].mcb_dist();
00357 min_num_edges = SS[ siu ].mcb_num_edges();
00358 is_min_inf = false;
00359 break;
00360 }
00361
00362
00363 #line 7059 "MIN_CYCLE_BASIS.lw"
00364
00365 if ( marked[ u ] >= 2 ) continue;
00366
00367
00368 marked[ u ] = marked[ u ] + 1;
00369 if ( marked[ u ] == 1 ) marked_touched.append( u );
00370
00371
00372
00373 #line 7086 "MIN_CYCLE_BASIS.lw"
00374
00375 forall_inout_edges( e, u ) {
00376
00377 w = G.opposite( e, u );
00378
00379
00380 if ( w == G.target( e ) ) {
00381 wl = ( ul + Xe[ e ] ) % p;
00382 }
00383 else {
00384 wl = ( ul - Xe[ e ] ) % p;
00385 }
00386 while ( wl < 0 ) wl += p;
00387
00388
00389 #line 7110 "MIN_CYCLE_BASIS.lw"
00390
00391 windex = get_revi_index( w, wl );
00392 siw = SS.lookup( windex );
00393
00394
00395 T c = SS[ siu ].mcb_dist() + len [ e ];
00396 if ( siw == nil ) {
00397
00398 if ( is_minall_inf == false && c > minall )
00399 continue;
00400
00401 siw = SS.insert( windex,
00402 SSitem( PQ.insert( c, pnode( w , wl ) ),
00403 c ,
00404 0 ,
00405 preditem( nil, 0, nil ) ) );
00406 }
00407 else if ( c < SS[ siw ].mcb_dist() ) {
00408 PQ.decrease_p( SS[ siw ].mcb_revi() , c );
00409 }
00410 else continue;
00411
00412
00413 SS[ siw ].mcb_dist() = c;
00414 SS[ siw ].mcb_num_edges() = SS[ siu ].mcb_num_edges() + 1;
00415 SS[ siw ].mcb_pred().mcb_edge() = e;
00416 SS[ siw ].mcb_pred().mcb_other_node_index() = uindex;
00417 SS[ siw ].mcb_pred().mcb_other_node() = u;
00418 }
00419
00420 }
00421
00422
00423
00424 #line 7163 "MIN_CYCLE_BASIS.lw"
00425
00426 if ( is_min_inf == false ) {
00427 if ( ( is_minall_inf == true ) ||
00428 ( min < minall ) ||
00429 ( ( min == minall ) && ( min_num_edges < minall_num_edges ) )
00430 ) {
00431
00432
00433
00434
00435 record_cycle( get_revi_index( u, ul ), cycle );
00436 minall = min;
00437 minall_num_edges = min_num_edges;
00438 is_minall_inf = false;
00439 }
00440 }
00441
00442
00443 init_used_dijkstra();
00444 }
00445
00446
00447 if ( is_minall_inf == true )
00448 leda::error_handler(999,"MIN_CYCLE_BASIS: no cycle found :(");
00449
00450 return minall;
00451 }
00452
00453
00454
00455 #line 7198 "MIN_CYCLE_BASIS.lw"
00456
00457 int n,m;
00458 PT p;
00459 const graph& G;
00460 const edge_array< T > &len;
00461 const edge_num& enumb;
00462 p_queue<T,pnode> PQ;
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 sortseq< PT, SSitem > SS;
00480
00481 array< etype > cycle;
00482
00483 node_array< PT > nodeid;
00484 node_array< unsigned short > marked;
00485 node_list marked_touched;
00486 edge_array< PT > Xe;
00487 };
00488
00489
00490 #undef mcb_revi
00491 #undef mcb_dist
00492 #undef mcb_num_edges
00493 #undef mcb_pred
00494 #undef mcb_edge
00495 #undef mcb_other_node_index
00496 #undef mcb_other_node
00497
00498 #line 6294 "MIN_CYCLE_BASIS.lw"
00499
00500
00501
00535 template<class W>
00536 W DIR_MIN_CYCLE_BASIS( const graph& g,
00537 const edge_array<W>& len,
00538 array< spvecfp >& mcb,
00539 array< spvecfp >& proof,
00540 const edge_num& enumb,
00541 double error = 0.375
00542 )
00543 {
00544
00545 #line 6348 "MIN_CYCLE_BASIS.lw"
00546 #if ! defined(LEDA_CHECKING_OFF)
00547 if ( Is_Simple( g ) == false )
00548 error_handler(999,"MIN_CYCLE_BASIS: illegal graph (non-simple?)");
00549 if ( Is_Loopfree( g ) == false )
00550 error_handler(999,"MIN_CYCLE_BASIS: illegal graph (has loops?)");
00551 if ( error <= 0 || error >= 1 )
00552 error_handler(999,"MIN_CYCLE_BASIS: error probability is out of range");
00553
00554 edge e1;
00555 forall_edges( e1 , g ) {
00556 if ( len[e1] <= 0 )
00557 error_handler(999,"MIN_CYCLE_BASIS: illegal edge (non-positive weight)");
00558 }
00559 #endif
00560
00561 #line 6373 "MIN_CYCLE_BASIS.lw"
00562 int d = enumb.dim_cycle_space();
00563
00564
00565 if ( d <= 0 ) return W(0);
00566
00567 mcb.resize( d );
00568 proof.resize( d );
00569
00570 int m = g.number_of_edges();
00571
00572
00573
00574 #line 6409 "MIN_CYCLE_BASIS.lw"
00575
00576 int times = (int) ceil( log(error)/log(0.375) );
00577
00578 #if defined(LEP_DEBUG_OUTPUT)
00579 std::cout << "Executing " << times;
00580 std::cout << " number of times to achieve error probability ";
00581 std::cout << error << std::endl;
00582 #endif
00583
00584
00585 array< spvecfp > X ( d );
00586 array< spvecfp > B ( d );
00587 W min_so_far = W(0);
00588 bool min_so_far_inf = true;
00589
00590
00591
00592 dirsp<W,ptype> SP( g, len, 7, enumb );
00593
00594
00595 while( times-- > 0 ) {
00596
00597
00598 ptype p;
00599 {
00600 int logd = log( integer( d + 1 ) );
00601 int loglogd = log( integer( logd + 1 ) );
00602 int randbits = 7 + 2 * logd + loglogd;
00603 int failsafe = 50 * randbits;
00604 int count = 0;
00605
00606 while( true ) {
00607
00608 if ( count++ > failsafe ) {
00609 randbits++;
00610 failsafe += 50;
00611 count = 0;
00612 }
00613
00614
00615 p = ptype::random( randbits );
00616 p += d*d;
00617
00618
00619
00620 if ( p > 1 && primes<ptype>::is_prime( p ) ) break;
00621 }
00622 }
00623
00624 #if defined(LEP_DEBUG_OUTPUT)
00625 std::cout << "executing with prime p = " << p << std::endl;
00626 #endif
00627
00628
00629 SP.reinit( p );
00630
00631 #line 6479 "MIN_CYCLE_BASIS.lw"
00632
00633
00634
00635 indextype i,j;
00636 for( i = 0; i < d; i++ ) {
00637 X[i] = spvecfp( m , p );
00638 X[i] = i + 1;
00639 B[i] = spvecfp( m , p );
00640 B[i] = 0;
00641 }
00642
00643
00644 #line 6510 "MIN_CYCLE_BASIS.lw"
00645
00646 spvecfp tmp = spvecfp( m, p );
00647 ptype tmpi;
00648 W min = W(0);
00649 for( i = 0; i < d; i++ ) {
00650
00651
00652 W mini;
00653 B[i] = SP.get_shortest_cycle( X[i], mini );
00654 min += mini;
00655
00656
00657
00658
00659
00660
00661
00662 tmpi = X[i]*B[i];
00663 while( tmpi < 0 ) tmpi += p;
00664 while( tmpi >= p ) tmpi -= p;
00665 tmp = X[i] * fp<ptype>::get_mult_inverse( tmpi, p );
00666
00667
00668 for( j = i+1; j < d; j++ )
00669 X[j] -= tmp * (B[i] * X[j]) ;
00670 }
00671
00672
00673 #line 6545 "MIN_CYCLE_BASIS.lw"
00674
00675 if ( ( min_so_far_inf == true ) ||
00676 ( min_so_far_inf == false && min < min_so_far ) ) {
00677 #if defined(LEP_DEBUG_OUTPUT)
00678 if ( min_so_far_inf == false )
00679 std::cout << "found better solution with weight " << min << std::endl;
00680 #endif
00681 mcb = B;
00682 proof = X;
00683 min_so_far_inf = false;
00684 min_so_far = min;
00685 }
00686
00687 }
00688
00689
00690 return min_so_far;
00691 }
00692
00693
00694 #line 6574 "MIN_CYCLE_BASIS.lw"
00695
00723 template<class W>
00724 W DIR_MIN_CYCLE_BASIS( const graph& g,
00725 const edge_array<W>& len,
00726 array< array<etype> >& mcb,
00727 const edge_num& enumb,
00728 double error = 0.375
00729 )
00730 {
00731 array< spvecfp > mcb_tmp;
00732 array< spvecfp > proof_tmp;
00733
00734 int d = enumb.dim_cycle_space();
00735
00736
00737 W min = DIR_MIN_CYCLE_BASIS<W>( g, len, mcb_tmp, \
00738 proof_tmp, enumb, error );
00739
00740
00741 ptype p = proof_tmp[0].pvalue();
00742
00743
00744 mcb.resize( d );
00745 for ( int i = 0; i < d; i++ )
00746 spvecfp_to_array_ints( g, enumb, p, mcb_tmp[i], mcb[i] );
00747
00748 return min;
00749 }
00750
00751
00752 #line 6638 "MIN_CYCLE_BASIS.lw"
00753
00776 template<class W>
00777 W DIR_MIN_CYCLE_BASIS( const graph& g,
00778 const edge_array<W>& len,
00779 array< list<edge> >& mcb,
00780 double error = 0.375
00781 )
00782 {
00783 edge_num enumb( g );
00784 array< spvecfp > mcb_tmp;
00785 array< spvecfp > proof_tmp;
00786
00787 int d = enumb.dim_cycle_space();
00788
00789
00790 W min = DIR_MIN_CYCLE_BASIS<W>( g, len, mcb_tmp, \
00791 proof_tmp, enumb, error );
00792
00793
00794 mcb.resize( d );
00795 for( int i = 0; i < d; i++ )
00796 spvecfp_to_list_edges( g, enumb, mcb_tmp[i], mcb[i] );
00797
00798 return min;
00799 }
00800
00801
00802 #line 8037 "MIN_CYCLE_BASIS.lw"
00803
00804 void array_ints_to_spvecfp( const graph& g, const edge_num& enumb, const ptype &p,
00805 const array<etype>& in, spvecfp& out )
00806 {
00807 int m = g.number_of_edges();
00808 out.reset( m, p );
00809
00810 indextype i;
00811 for( i = 0; i < m; i++ ) {
00812 if ( in[ i ] != 0 ) {
00813 out.append( i+1, ptype(in[i]) );
00814 }
00815 }
00816 }
00817
00818
00819
00820
00821 #line 6180 "MIN_CYCLE_BASIS.lw"
00822 }
00823
00824 #endif // DIR_MIN_CYCLE_BASIS_H
00825
00826 #line 6217 "MIN_CYCLE_BASIS.lw"
00827
00828
00829