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
00072 #ifndef DMCB_H
00073 #define DMCB_H
00074
00075 #include <LEP/mcb/config.h>
00076
00077
00078 #ifdef LEDA_GE_V5
00079 #include <LEDA/graph/graph.h>
00080 #include <LEDA/graph/edge_array.h>
00081 #include <LEDA/core/array.h>
00082 #include <LEDA/core/random_source.h>
00083 #include <LEDA/numbers/integer.h>
00084 #else
00085 #include <LEDA/graph.h>
00086 #include <LEDA/array.h>
00087 #include <LEDA/edge_array.h>
00088 #include <LEDA/integer.h>
00089 #include <LEDA/random_source.h>
00090 #endif
00091
00092 #include <LEP/mcb/edge_num.h>
00093 #include <LEP/mcb/fp.h>
00094 #include <LEP/mcb/spvecfp.h>
00095 #include <LEP/mcb/arithm.h>
00096 #include <LEP/mcb/transform.h>
00097 #include <LEP/mcb/dsigned.h>
00098
00099 namespace mcb {
00100
00101 #if defined(LEDA_NAMESPACE)
00102 using leda::graph;
00103 using leda::edge;
00104 using leda::edge_array;
00105 using leda::node;
00106 using leda::node_array;
00107 using leda::array;
00108 using leda::integer;
00109 using leda::random_source;
00110 using leda::pq_item;
00111 #endif
00112
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 template<class W>
00153 W DMCB( const graph& g,
00154 const edge_array<W>& len,
00155 array< mcb::spvecfp >& mcb,
00156 array< mcb::spvecfp >& proof,
00157 const mcb::edge_num& enumb,
00158 ptype& p
00159 )
00160 {
00161 #if ! defined(LEDA_CHECKING_OFF)
00162 if ( Is_Simple( g ) == false )
00163 error_handler(999,"DMCB: illegal graph (non-simple?)");
00164 if ( Is_Loopfree( g ) == false )
00165 error_handler(999,"DMCB: illegal graph (has loops?)");
00166
00167 edge e1;
00168 forall_edges( e1 , g ) {
00169 if ( len[e1] <= 0 )
00170 error_handler(999,"MIN_CYCLE_BASIS: illegal edge (non-positive weight)");
00171 }
00172
00173 if ( ! primes<ptype>::is_prime( p ) )
00174 error_handler(999,"DMCB: p is not a prime number!");
00175
00176 #endif
00177 int d = enumb.dim_cycle_space();
00178 if ( d <= 0 ) return W(0);
00179
00180 mcb.resize( d );
00181 array< spvecfp >& B = mcb;
00182 proof.resize( d );
00183 array< spvecfp >& X = proof;
00184
00185
00186 dirsp<W,ptype> SP( g, len, p, enumb );
00187
00188 #if defined(LEP_DEBUG_OUTPUT)
00189 std::cout << "executing with prime p = " << p << std::endl;
00190 #endif
00191
00192
00193
00194
00195 indextype i,j;
00196 for( i = 0; i < d; i++ ) {
00197 X[i] = spvecfp( p );
00198 X[i] = i;
00199 B[i] = spvecfp( p );
00200 }
00201
00202
00203 spvecfp tmp = spvecfp( p );
00204 ptype tmpi;
00205 W min = W(0);
00206 for( i = 0; i < d; i++ ) {
00207
00208
00209 W mini;
00210 B[i] = SP.get_shortest_cycle( X[i], mini );
00211 min += mini;
00212
00213
00214
00215
00216
00217
00218
00219 tmpi = X[i]*B[i];
00220 while( tmpi < 0 ) tmpi += p;
00221 while( tmpi >= p ) tmpi -= p;
00222 tmp = X[i] * fp<ptype>::get_mult_inverse( tmpi, p );
00223
00224
00225 for( j = i+1; j < d; j++ )
00226 X[j] -= tmp * (B[i] * X[j]) ;
00227 }
00228
00229 return min;
00230
00231 }
00232
00267 template<class W>
00268 W DMCB( const graph& g,
00269 const edge_array<W>& len,
00270 array< mcb::spvecfp >& mcb,
00271 array< mcb::spvecfp >& proof,
00272 const mcb::edge_num& enumb,
00273 double error = 0.375
00274 )
00275 {
00276 #if ! defined(LEDA_CHECKING_OFF)
00277 if ( Is_Simple( g ) == false )
00278 error_handler(999,"MIN_CYCLE_BASIS: illegal graph (non-simple?)");
00279 if ( Is_Loopfree( g ) == false )
00280 error_handler(999,"MIN_CYCLE_BASIS: illegal graph (has loops?)");
00281 if ( error <= 0 || error >= 1 )
00282 error_handler(999,"MIN_CYCLE_BASIS: error probability is out of range");
00283
00284 edge e1;
00285 forall_edges( e1 , g ) {
00286 if ( len[e1] <= 0 )
00287 error_handler(999,"MIN_CYCLE_BASIS: illegal edge (non-positive weight)");
00288 }
00289 #endif
00290 int d = enumb.dim_cycle_space();
00291 if ( d <= 0 ) return W(0);
00292
00293 mcb.resize( d );
00294 proof.resize( d );
00295
00296
00297 int times = (int) ceil( log(error)/log(0.375) );
00298
00299 #if defined(LEP_DEBUG_OUTPUT)
00300 std::cout << "Executing " << times;
00301 std::cout << " number of times to achieve error probability ";
00302 std::cout << error << std::endl;
00303 #endif
00304
00305
00306 array< spvecfp > X ( d );
00307 array< spvecfp > B ( d );
00308 W min_so_far = W(0);
00309 bool min_so_far_inf = true;
00310
00311
00312 while( times-- > 0 ) {
00313
00314
00315 ptype p;
00316 {
00317 int logd = log( integer( d + 1 ) );
00318 int loglogd = log( integer( logd + 1 ) );
00319 int randbits = 7 + 2 * logd + loglogd;
00320 int failsafe = 50 * randbits;
00321 int count = 0;
00322
00323 while( true ) {
00324
00325 if ( count++ > failsafe ) {
00326 randbits++;
00327 failsafe += 50;
00328 count = 0;
00329 }
00330
00331
00332 p = ptype::random( randbits );
00333 p += d*d;
00334
00335
00336
00337 if ( p > 1 && primes<ptype>::is_prime( p ) ) break;
00338 }
00339 }
00340
00341 #if defined(LEP_DEBUG_OUTPUT)
00342 std::cout << "executing with prime p = " << p << std::endl;
00343 #endif
00344
00345 W min = DMCB( g, len, B, X, enumb, p );
00346
00347
00348 if ( ( min_so_far_inf == true ) ||
00349 ( min_so_far_inf == false && min < min_so_far ) ) {
00350 #if defined(LEP_DEBUG_OUTPUT)
00351 if ( min_so_far_inf == false )
00352 std::cout << "found better solution with weight " << min << std::endl;
00353 #endif
00354 mcb = B;
00355 proof = X;
00356 min_so_far_inf = false;
00357 min_so_far = min;
00358 }
00359
00360 }
00361 return min_so_far;
00362 }
00363
00393 template<class W>
00394 W DMCB( const graph& g,
00395 const edge_array<W>& len,
00396 array< mcb::spvecfp >& mcb,
00397 const mcb::edge_num& enumb,
00398 double error = 0.375
00399 )
00400 {
00401 array< spvecfp > proof_tmp;
00402 return DMCB(g, len, mcb, proof_tmp, enumb, error );
00403 }
00404
00434 template<class W>
00435 W DMCB( const graph& g,
00436 const edge_array<W>& len,
00437 array< array<etype> >& mcb,
00438 const mcb::edge_num& enumb,
00439 double error = 0.375
00440 )
00441 {
00442 array< spvecfp > mcb_tmp;
00443 array< spvecfp > proof_tmp;
00444
00445 int d = enumb.dim_cycle_space();
00446
00447
00448 W min = DMCB<W>( g, len, mcb_tmp, \
00449 proof_tmp, enumb, error );
00450
00451
00452 ptype p = proof_tmp[0].pvalue();
00453
00454
00455 mcb.resize( d );
00456 for ( int i = 0; i < d; i++ )
00457 spvecfp_to_array_ints( g, enumb, p, mcb_tmp[i], mcb[i] );
00458
00459 return min;
00460 }
00461
00463
00464 }
00465
00466 #endif // DMCB_H
00467
00468