00001 #line 2 "cp_knapsack.lw"
00002 #include <LEDA/map.h>
00003 #include <LEDA/set.h>
00004 #include <LEDA/basic.h>
00005 #include <LEDA/d_array.h>
00006 #include <LEDA/window.h>
00007 #include <LEDA/file.h>
00008 #include <LEDA/array.h>
00009
00010 class cmp_by_fractional: public leda_cmp_base<int>
00011 {
00012 private:
00013
00014 map<int,double>* fractional_point ;
00015
00016 public:
00017
00018 cmp_by_fractional(map<int,double>* fract)
00019 {
00020 fractional_point = fract ;
00021 }
00022 int operator()(const int& a, const int& b) const
00023
00024 {
00025
00026 if ( (*fractional_point) [ a ] < (*fractional_point) [ b ] )
00027 { return 1 ;}
00028 if ( (*fractional_point) [ a ] > (*fractional_point) [ b ] )
00029 { return -1 ;}
00030 return 0 ;
00031
00032 }
00033
00034 } ;
00035
00036 class cmp_by_coefficient: public leda_cmp_base<int>
00037 {
00038 private:
00039
00040 array<int>* coeffs ;
00041
00042 public:
00043
00044 cmp_by_coefficient(array<int>* coeff)
00045 {
00046 coeffs = coeff ;
00047 }
00048 int operator()(const int& a, const int& b) const
00049
00050 {
00051
00052 if ( (*coeffs) [ a ] > (*coeffs) [ b ] )
00053 { return 1 ;}
00054 if ( (*coeffs) [ a ] < (*coeffs) [ b ] )
00055 { return -1 ;}
00056 return 0 ;
00057 }
00058 } ;
00059
00060 class cmp_decrease: public leda_cmp_base<double>
00061 {
00062
00063 public:
00064
00065 cmp_decrease()
00066 {}
00067 int operator()(const double& a, const double& b) const
00068
00069 {
00070
00071 if ( a > b )
00072 { return -1 ;}
00073 if ( a < b )
00074 { return 1 ;}
00075 return 0 ;
00076 }
00077 } ;
00078
00079 class cmp_increase_by_coefficient: public leda_cmp_base<int>
00080 {
00081 private:
00082
00083 array<int>* coeffs ;
00084
00085 public:
00086
00087 cmp_increase_by_coefficient(array<int>* coeff)
00088 {
00089 coeffs = coeff ;
00090 }
00091 int operator()(const int& a, const int& b) const
00092
00093 {
00094
00095 if ( (*coeffs) [ a ] > (*coeffs) [ b ] )
00096 { return 1 ;}
00097 if ( (*coeffs) [ a ] < (*coeffs) [ b ] )
00098 { return -1 ;}
00099 return 0 ;
00100 }
00101 } ;
00102
00103 class cmp_nondecrease_by_reduced_costs: public leda_cmp_base<int>
00104 {
00105 private:
00106
00107 map<int,double>* red_costs ;
00108
00109 public:
00110
00111 cmp_nondecrease_by_reduced_costs(map<int,double>* redcosts)
00112 {
00113 red_costs = redcosts ;
00114 }
00115 int operator()(const int& a, const int& b) const
00116
00117 {
00118
00119 if ( (*red_costs) [ a ] > (*red_costs) [ b ] )
00120 { return 1 ;}
00121 if ( (*red_costs) [ a ] < (*red_costs) [ b ] )
00122 { return -1 ;}
00123 return 0 ;
00124 }
00125 } ;
00126
00127
00128
00129 class LCI : public cons_obj {
00130
00131 public:
00132 array<int> coeff_array ;
00133 int rhs ;
00134 map<int,var>& item_index_map ;
00135 LCI(array<int>coeff,int r, map<int,var>& map)
00136 : cons_obj(Less, r), item_index_map(map) {
00137 coeff_array=coeff ;
00138 rhs = r ;
00139 }
00140
00141 ~LCI()
00142 {};
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 virtual void non_zero_entries(row& r) {
00153 for(int i=0; i<=coeff_array.high(); i++) {
00154 if(coeff_array[i]!=0)
00155 r+=item_index_map[i]*coeff_array[i];
00156 }
00157 };
00158 };
00159
00160
00161 class cp_knapsack : public sym_constraint {
00162 private:
00163
00164 int my_count;
00165 cons_obj* KC ;
00166 map<int,var> item_index_map;
00167 cons_obj* new_constraint ;
00168 double violation_tolerance ;
00169 bool lifted_in_C2 ;
00170 bool TESTDONE ;
00171 bool lifted_in_F ;
00172 bool cover_found ;
00173 bool minimal_cover ;
00174 bool negative_coeffs ;
00175 bool test ;
00176 bool violated ;
00177 double contribute ;
00178 int id ;
00179 int constraint_count ;
00180 int var1, var2 ;
00181 int index ;
00182 int z ;
00183 int a ;
00184 int c ;
00185 int sum ;
00186 int x ;
00187 double RHS ;
00188 double C1_size ;
00189 int rightsum ;
00190 int gammasum ;
00191 int Ti ;
00192 int number_variables ;
00193 int number_cover_candidates ;
00194 int sort_array_size ;
00195 int index1 ;
00196 int index2 ;
00197 int coeff ;
00198 double g ;
00199 int r ;
00200 int T ;
00201 int previous_T ;
00202 int lift_index ;
00203 int previous_lift_index ;
00204 int lift_coeff ;
00205 int actual_lift_coeff ;
00206 int righthandside ;
00207 bool no_sep ;
00208 double fractional ;
00209 list<int> negative_coeff_indizes ;
00210 array<int> liftcoeffs ;
00211 map<int,double> red_costs ;
00212 array<int> coeffs ;
00213 array<int> cover_candidates ;
00214 map<int,double> fractional_point ;
00215
00216 int zippl ;
00217 array<bool> coeffs_sign ;
00218 array<int> sort_array ;
00219 array<int> liftsequence_on_R ;
00220 array<int> liftsequence_on_C2 ;
00221 array<int>* W1 ;
00222 array<int>* W2 ;
00223 set<int> F ;
00224 set<int> R ;
00225 set<int> C1 ;
00226 set<int> C2 ;
00227 set<int> to_lift_in_F ;
00228 set<int> to_lift_in_C2 ;
00229 set<int> to_lift_in_R ;
00230 set<int> N_C ;
00231 set<int> C ;
00232 set<int> L ;
00233 set<int> N ;
00234
00235 public:
00236
00237 cp_knapsack(cons_obj* KCt, double tolerance=0.001) : KC(KCt) {
00238 violation_tolerance = tolerance ;
00239 }
00240
00241 void init(subproblem& S) {
00242 S.add_basic_constraint(KC);
00243
00244 number_variables = S.nVar() ;
00245 righthandside = (int) KC->rhs() ;
00246 coeffs.resize(number_variables) ;
00247 liftcoeffs.resize(number_variables) ;
00248
00250
00252
00253 for (int index=0; index <= number_variables-1; index++ )
00254 {
00255 item_index_map[index]=S.get_var(index);
00256 coeff =(int) KC->coeff (((var) item_index_map[index]).var_pointer() ) ;
00257
00258 if ( coeff < 0 )
00259 {
00260 coeffs[index] = - coeff ;
00261 righthandside -= coeff ;
00262 }
00263 else
00264 {
00265 coeffs[index] = coeff ;
00266 }
00267 }
00268
00270
00271
00272
00274
00275
00276 for (int index=0; index <= number_variables-1; index++ )
00277 {
00278 if ( (coeffs[index] <= righthandside) && ( coeffs[index] != 0 ) )
00279 {
00280 N.insert( index ) ;
00281
00282 if ( KC->coeff ( ((var) item_index_map[index]).var_pointer() ) < 0 )
00283 {
00284 negative_coeff_indizes.push(index) ;
00285 }
00286 }
00287
00288 }
00289
00290
00291 if ( ( N.size() > 0 ) )
00292 {
00293 cover_candidates.resize( N.size() ) ;
00294 sort_array.resize( N.size() ) ;
00295 liftsequence_on_C2.resize( N.size() ) ;
00296 liftsequence_on_R.resize( N.size() ) ;
00297 no_sep = 0 ;
00298 }
00299
00300 else
00301 {
00302 no_sep = 1 ;
00303 }
00304
00305 }
00306
00307
00308 public:
00309
00311
00312
00314
00315 {
00316 Ti += liftcoeffs [ x ] ;
00317 }
00318
00320
00321
00322
00324
00325 {
00326 gammasum += liftcoeffs[x];
00327 }
00329
00330
00332
00333 {
00334 rightsum = 0 ;
00335 forall (x,C2)
00336 {
00337
00338 rightsum += coeffs [ x ] ;
00339 }
00340 return rightsum ;
00341 }
00343
00344
00346
00347 {
00348 rightsum -= coeffs[x] ;
00349 return rightsum ;
00350 }
00351
00352
00353 bool compute_cover()
00354 {
00355
00357
00359
00361
00362
00364
00365 index1 = 0 ;
00366 forall(index,N)
00367 {
00368 if ( (fractional_point[index] > 0.00001) )
00369 {
00370 cover_candidates [ index1 ] = index ;
00371 index1++;
00372 }
00373 }
00374
00375 if ( index1 == 0 )
00376 {
00377 return 1 ;
00378 }
00379 number_cover_candidates = index1 ;
00380
00382
00384
00385 cover_candidates.sort(nonincrease_by_fractional,0 , number_cover_candidates-1) ;
00386
00388
00389
00390
00392
00393 cover_found = 0 ;
00394 sum = 0 ;
00395 index1 = 0 ;
00396
00397 while ( (cover_found == 0) && ( index1 < number_cover_candidates ) )
00398 {
00399 sum += coeffs [ cover_candidates[ index1 ] ];
00400 C.insert( cover_candidates[ index1 ] ) ;
00401 sort_array[ index1 ] = cover_candidates[ index1 ] ;
00402 index1 ++ ;
00403
00404 if ( sum > righthandside )
00405 {
00406 cover_found = 1 ;
00407 }
00408
00409 }
00410
00411 if ( cover_found == 0 )
00412 {
00413 return 1 ;
00414 }
00415
00416
00418
00420
00421
00423
00425
00426 sort_array.sort(nondecrease_by_coeff,0,sort_array_size) ;
00427
00429
00430
00432
00433 index1 = 0 ;
00434
00435 while( (!minimal_cover) && (index1 < sort_array_size-1 ) )
00436 {
00437 sum -= coeffs [ (sort_array[ index1 ]) ] ;
00438
00439 if ( sum > righthandside )
00440 {
00441 C.del( sort_array [ index1 ] ) ;
00442 index1 ++ ;
00443 }
00444 else
00445 {
00446 minimal_cover = 1 ;
00447 }
00448 }
00449
00451
00453
00454 index1 = 0 ;
00455 sum = 0 ;
00456
00457 forall (x,C)
00458 {
00459 if ( ( fractional_point[ x ] == 1 ) )
00460 {
00461 sum += coeffs[x] ;
00462 C2.insert( x ) ;
00463 }
00464 else
00465 {
00466 sum += coeffs[x] ;
00467 C1.insert( x ) ;
00468 index1 ++ ;
00469 }
00470
00471 }
00472
00473
00475
00477
00478 if ( ( C1.size() <= 1 ) && ( C2.size() > 1 ) )
00479 {
00480
00481 C1 += C2 ;
00482 C2.clear() ;
00483 }
00484
00485 if ( C1.size() <= 1 )
00486 {
00487 return 1 ;
00488 }
00489
00490 N_C = N - ( C1 + C2 ) ;
00491
00492 forall(x , N_C )
00493 {
00494 if ( fractional_point[ x ] > 0.00001 )
00495 {
00496 F.insert(x) ;
00497 }
00498 else
00499 {
00500 R.insert(x) ;
00501 }
00502 }
00503
00504
00506
00508
00509 cmp_nondecrease_by_reduced_costs reduced( &red_costs ) ;
00510
00512
00513
00515
00516
00517 if ( C2.size() != 0 )
00518 {
00519 forall( x, C2 )
00520 {
00521 liftsequence_on_C2[ index1 ] = x ;
00522 index1++ ;
00523 }
00524 liftsequence_on_C2.sort( reduced,0,index1-1) ;
00525
00526 }
00527
00528
00529 index1 = 0 ;
00530
00531 if ( R.size() != 0 )
00532 {
00533 forall( x, R )
00534 {
00535 liftsequence_on_R[ index1 ] = x ;
00536 index1 ++ ;
00537 }
00538 liftsequence_on_R.sort( reduced,0,index1-1) ;
00539
00540 }
00541
00542
00543 return 0 ;
00544
00545 }
00546
00547
00548
00549
00550
00551 void lift_on_F( array<int>* W )
00552 {
00553 contribute = -1 ;
00554 lift_index = -1 ;
00555 actual_lift_coeff = -1 ;
00556 lift_coeff = -1 ;
00557
00558 forall( x, to_lift_in_F )
00559 {
00560 RHS = righthandside - (rightsum+coeffs[x]) ; ;
00561
00562 if ( RHS >= 0 )
00563 {
00564 z = (*W).binary_locate( RHS ) ;
00565 actual_lift_coeff = r - 1 + gammasum - z ;
00566 if ( actual_lift_coeff * fractional_point[ x ] > contribute )
00567 {
00568 lift_coeff = actual_lift_coeff ;
00569 contribute = lift_coeff * fractional_point[ x ] ;
00570 lift_index = x ;
00571 }
00572
00573 }
00574
00575 }
00576
00577 if ( lift_index != -1 )
00578 {
00579
00580 liftcoeffs[ lift_index ] = lift_coeff ;
00581 to_lift_in_F.del( lift_index ) ;
00582 L.insert( lift_index ) ;
00583 update_Ti(lift_index) ;
00584 previous_lift_index = lift_index ;
00585 lifted_in_F = 1 ;
00586 }
00587
00588 }
00589
00590
00591 void lift_on_C2 ( array<int>* W )
00592 {
00593
00594 x = C2.size() - to_lift_in_C2.size() ;
00595 lift_index = liftsequence_on_C2[ x ] ;
00596 RHS = righthandside - update_righthandsum( lift_index ) ;
00597 z = (*W).binary_locate( RHS ) ;
00598 lift_coeff = z - r +1 - gammasum ;
00599 liftcoeffs[ lift_index ] = lift_coeff ;
00600 update_gammasum(lift_index) ;
00601 to_lift_in_C2.del( lift_index ) ;
00602 L.insert( lift_index ) ;
00603 update_Ti(lift_index) ;
00604 previous_lift_index = lift_index ;
00605 lifted_in_C2 = 1 ;
00606
00607
00608 }
00609
00610
00611 void lift_on_R ( array<int>* W )
00612 {
00613
00614 x = R.size() - to_lift_in_R.size() ;
00615 lift_index = liftsequence_on_R[ x ] ;
00616 RHS = righthandside - (rightsum+coeffs[lift_index]) ;
00617 z = (*W).binary_locate( RHS ) ;
00618 lift_coeff = r - 1 + gammasum - z ;
00619 liftcoeffs[ lift_index ] = lift_coeff ;
00620 to_lift_in_R.del( lift_index ) ;
00621 L.insert( lift_index ) ;
00622 update_Ti(lift_index) ;
00623 previous_lift_index = lift_index ;
00624
00625 }
00626
00627 void compute_first_row()
00628
00629 {
00630 r = C1.size() ;
00631 index1 = 0;
00632
00633 forall( x, C1 )
00634 {
00635 sort_array[ index1 ] = coeffs[ x ] ;
00636 index1 ++ ;
00637 }
00638 sort_array.sort(0,index1-1) ;
00639
00640
00641
00642 W1 = new array<int>(0,r) ;
00643 (*W1)[0] = 0 ;
00644
00645 for (int t=0; t <= r-1 ; t++ )
00646 {
00647 (*W1)[ t+1 ] = (*W1)[ t ] + sort_array[ t ] ;
00648 }
00649
00650 W2 = W1 ;
00651 }
00652
00653 void compute_next_row()
00654 {
00655 T = Ti ;
00656 W2 = new array<int>(0,T) ;
00657 c = liftcoeffs[ previous_lift_index ] ;
00658 a = coeffs [ previous_lift_index ] ;
00659 for( int index=0; index <= (*W1).size()-1 ; index++)
00660 {
00661 var1 = (*W1)[ index ] ;
00662 if ( index-c > 0 )
00663 {
00664 var2 = (*W1)[ index - c] ;
00665 }
00666 else
00667 {
00668 var2 = 0 ;
00669 }
00670
00671 var2 = var2 + a ;
00672
00673 if ( var1 < var2 )
00674 {
00675 (*W2)[ index ] = var1 ;
00676 }
00677 else
00678 {
00679 (*W2)[ index ] = var2 ;
00680
00681 }
00682
00683 }
00684
00685 for( int index = (*W1).size() ; index<=T; index++)
00686 {
00687 if ( index-c > 0 )
00688 {
00689 var1 = (*W1)[ index - c] ;
00690
00691 }
00692 else
00693 {
00694 var1 = 0 ;
00695 }
00696
00697 (*W2)[ index ] = var1 + a ;
00698 }
00699 delete W1;
00700 W1 = W2 ;
00701 }
00702
00703
00704
00705 void setup_values(subproblem& S)
00706 {
00707
00708
00709 for (int index=0; index <= number_variables-1; index++ )
00710 {
00711 coeff = (int) KC->coeff (((var) item_index_map[index]).var_pointer() ) ;
00712
00713 if ( coeff >= 0 )
00714 {
00715 fractional_point[index] = S.value( item_index_map[ index ] ) ;
00716 }
00717 else
00718 {
00719 fractional_point[index] = 1 - S.value( item_index_map[ index ] ) ;
00720 }
00721
00722
00723
00724 }
00725 red_costs.clear() ;
00726 forall(x,N)
00727 {
00728 red_costs[x] = S.red_cost( item_index_map[ x ] ) ;
00729 }
00730
00731 test = 0 ;
00732 F.clear() ;
00733 R.clear() ;
00734 C1.clear() ;
00735 C2.clear() ;
00736 to_lift_in_F.clear() ;
00737 to_lift_in_C2.clear() ;
00738 to_lift_in_R.clear() ;
00739 N_C.clear() ;
00740 C.clear() ;
00741 liftcoeffs.init(0) ;
00742
00743 }
00744
00745
00746 status separate(subproblem& S)
00747 {
00748
00749 if ( no_sep == 1)
00750 {
00751 return no_constraint_found ;
00752 }
00753
00754 setup_values(S) ;
00755
00756
00757 if ( compute_cover() == 1 )
00758 {
00759 return no_constraint_found ;
00760 }
00761
00762 forall (x,C1)
00763 {
00764 liftcoeffs[ x ] = 1 ;
00765 }
00766
00767 init_righthandsum();
00768 Ti=C1.size() ;
00769 gammasum = 0 ;
00770
00771 compute_first_row() ;
00772
00773
00774 to_lift_in_F = F ;
00775 to_lift_in_C2 = C2 ;
00776 to_lift_in_R = R ;
00777
00778 TESTDONE = 0 ;
00779
00783
00784 while ( (to_lift_in_R.size() != 0 ) || (to_lift_in_C2.size() != 0) || ( to_lift_in_F.size() != 0) )
00785 {
00786
00787 lifted_in_F = 0 ;
00788 lifted_in_C2 = 0 ;
00789
00790
00791 if ( to_lift_in_F.size() != 0 )
00792
00793 {
00794 lift_on_F(W2) ;
00795 }
00796
00800
00801 if ( ( to_lift_in_F.size() == 0 ) && ( !TESTDONE ) )
00802 {
00803
00804 C1_size = C1.size()-1 ;
00805
00806
00807
00808 g = 0 ;
00809
00810 forall (x, F)
00811 {
00812 if ( KC->coeff ( ((var) item_index_map[x]).var_pointer() ) < 0 )
00813 {
00814
00815 g -= liftcoeffs[x]* S.value( item_index_map[ x ] ) ;
00816 C1_size -= liftcoeffs[x] ;
00817 }
00818 else
00819 {
00820 g += liftcoeffs[x]* S.value( item_index_map[ x ] ) ;
00821
00822 }
00823 }
00824
00825 forall (x, C1)
00826 {
00827 if ( KC->coeff ( ((var) item_index_map[x]).var_pointer() ) < 0 )
00828 {
00829 g -= S.value( item_index_map[ x ] ) ;
00830 C1_size -= liftcoeffs[x] ;
00831 }
00832 else
00833 {
00834 g += S.value( item_index_map[ x ] ) ;
00835
00836 }
00837 }
00838
00839 if ( g-violation_tolerance <= C1_size )
00840 {
00841 return no_constraint_found ;
00842 }
00843
00844 TESTDONE = 1 ;
00845 }
00846
00847
00848
00849 if ( (!lifted_in_F ) && ( to_lift_in_C2.size() != 0 ) )
00850
00851 {
00852 lift_on_C2(W2) ;
00853 }
00854
00855 if ( (!lifted_in_C2) && (!lifted_in_F) && ( to_lift_in_C2.size() == 0) && ( to_lift_in_R.size() != 0 ) && ( to_lift_in_F.size() == 0 ) )
00856
00857 {
00858 lift_on_R(W2) ;
00859 }
00860
00861 if ( (to_lift_in_R.size() != 0 ) || (to_lift_in_C2.size() != 0) || ( to_lift_in_F.size() != 0) )
00862
00863 {
00864 compute_next_row() ;
00865 }
00866
00867
00868
00869 }
00870
00874
00875 RHS = C1.size()-1 + gammasum ;
00876
00877 forall ( index, negative_coeff_indizes)
00878 {
00879 liftcoeffs [index] = -(liftcoeffs [index]) ;
00880 RHS += liftcoeffs[index] ;
00881 }
00882
00883 new_constraint = new LCI(liftcoeffs,RHS,item_index_map) ;
00884 S.add_basic_constraint( new_constraint, Dynamic ) ;
00885 my_count ++ ;
00886 cout<<"cp knapsack constraint\n";
00887 return constraint_found ;
00888
00889
00890
00891 }
00892 };
00893