00001 #include <algorithm>
00002 #include <boost/foreach.hpp>
00003 #include <scil/constraints/cp_knapsack.h>
00004
00005 namespace SCIL {
00006
00007 LCI::LCI(std::vector<int>coeff,int r, std::map<int,var>& map)
00008 : cons_obj(Less, r), item_index_map(map) {
00009 coeff_array=coeff ;
00010 rhs = r ;
00011 }
00012
00013 LCI::~LCI() {};
00014
00015
00016
00017
00018
00019
00020
00021
00022 void LCI::non_zero_entries(row& r) {
00023 for(int i=0; i < int(coeff_array.size()); i++) {
00024 if(coeff_array[i]!=0)
00025 r+=item_index_map[i]*coeff_array[i];
00026 }
00027 }
00028
00029 int CP_KNAPSACK::find_largest_index(std::vector<int> vec, int val) {
00030 std::vector<int>::iterator index;
00031 index = std::find(vec.begin(), vec.end(), val);
00032
00033 if (index != vec.end())
00034 {
00035
00036 while ( *(index+1) == *index ) index++;
00037 return index - vec.begin();
00038 }
00039 return -1;
00040 }
00041
00042 CP_KNAPSACK::CP_KNAPSACK(cons_obj* KCt, double tolerance) : KC(KCt) {
00043 violation_tolerance = tolerance ;
00044 }
00045
00046 void CP_KNAPSACK::init(subproblem& S) {
00047 if (S.configuration("CP_KNAPSACK_Debug_Out")=="true")
00048 cerr << "CP_KNAPSACK::init\n";
00049 S.add_basic_constraint(KC);
00050
00051 number_variables = S.nVar() ;
00052 righthandside = (int) KC->rhs() ;
00053 coeffs.resize(number_variables);
00054 liftcoeffs.resize(number_variables);
00055
00057
00059
00060 for (int index=0; index <= number_variables-1; index++ )
00061 {
00062 item_index_map[index]=S.get_var(index);
00063 int coeff =(int) KC->coeff( ((var) item_index_map[index]).var_pointer() ) ;
00064
00065 if ( coeff < 0 ) {
00066 coeffs[index] = - coeff ;
00067 righthandside -= coeff ;
00068 }
00069 else {
00070 coeffs[index] = coeff ;
00071 }
00072 }
00073
00075
00076
00077
00079
00080
00081 for (int index=0; index <= number_variables-1; index++ ) {
00082 if ( (coeffs[index] <= righthandside) && ( coeffs[index] != 0 ) )
00083 {
00084 N.insert( index ) ;
00085
00086 if ( KC->coeff( ((var) item_index_map[index]).var_pointer() ) < 0 )
00087 {
00088 negative_coeff_indices.push_front(index) ;
00089 }
00090 }
00091
00092 }
00093
00094
00095 if ( ( N.size() > 0 ) ) no_sep = 0 ;
00096 else no_sep = 1 ;
00097
00098 }
00099
00100 void CP_KNAPSACK::update_Ti(int x)
00101 {
00102 Ti += liftcoeffs [ x ] ;
00103 }
00104
00105 void CP_KNAPSACK::update_gammasum(int x)
00106 {
00107 gammasum += liftcoeffs[x];
00108 }
00109
00110 int CP_KNAPSACK::init_righthandsum()
00111 {
00112 rightsum = 0 ;
00113 BOOST_FOREACH(int x,C2)
00114 {
00115
00116 rightsum += coeffs [ x ] ;
00117 }
00118 return rightsum ;
00119 }
00120
00121 int CP_KNAPSACK::update_righthandsum(int x)
00122 {
00123 rightsum -= coeffs[x] ;
00124 return rightsum ;
00125 }
00126
00127
00128 bool nonincreasing (double i, double j) { return (i>j); }
00129
00130 bool CP_KNAPSACK::compute_cover()
00131 {
00132
00134
00136
00137 std::vector<int> cover_candidates;
00138
00140
00141
00143
00144 int index1 = 0 ;
00145 BOOST_FOREACH(index,N)
00146 {
00147 if ( (fractional_point[index] > 0.00001) )
00148 {
00149 cover_candidates [ index1 ] = index ;
00150 index1++;
00151 }
00152 }
00153
00154 if ( index1 == 0 )
00155 {
00156 return 1 ;
00157 }
00158 int number_cover_candidates = index1;
00159
00161
00163 std::sort(cover_candidates.begin(), cover_candidates.end(),nonincreasing);
00164
00166
00167
00168
00170
00171 bool cover_found = 0 ;
00172 int sum = 0 ;
00173 index1 = 0 ;
00174 std::set<int> C ;
00175
00176 while ( (cover_found == 0) && ( index1 < number_cover_candidates ) )
00177 {
00178 sum += coeffs [ cover_candidates[ index1 ] ];
00179 C.insert( cover_candidates[ index1 ] ) ;
00180 sort_array[ index1 ] = cover_candidates[ index1 ] ;
00181 index1 ++ ;
00182
00183 if ( sum > righthandside )
00184 {
00185 cover_found = 1 ;
00186 }
00187
00188 }
00189
00190 if ( cover_found == 0 )
00191 {
00192 return 1 ;
00193 }
00194
00195
00197
00199 int sort_array_size = index1-1 ;
00200
00202
00204 std::sort(sort_array.begin(), sort_array.end());
00205
00207
00208
00210 bool minimal_cover = 0 ;
00211 index1 = 0 ;
00212
00213 while( (!minimal_cover) && (index1 < sort_array_size-1 ) )
00214 {
00215 sum -= coeffs [ (sort_array[ index1 ]) ] ;
00216
00217 if ( sum > righthandside )
00218 {
00219 C.erase( sort_array [ index1 ] ) ;
00220 index1 ++ ;
00221 }
00222 else
00223 {
00224 minimal_cover = 1 ;
00225 }
00226 }
00227
00229
00231
00232 index1 = 0 ;
00233 sum = 0 ;
00234
00235 BOOST_FOREACH (int x,C)
00236 {
00237 if ( ( fractional_point[ x ] == 1 ) )
00238 {
00239 sum += coeffs[x] ;
00240 C2.insert( x ) ;
00241 }
00242 else
00243 {
00244 sum += coeffs[x] ;
00245 C1.insert( x ) ;
00246 index1 ++ ;
00247 }
00248
00249 }
00250
00251
00253
00255
00256 if ( ( C1.size() <= 1 ) && ( C2.size() > 1 ) )
00257 {
00258
00259 C1.insert(C2.begin(), C2.end()) ;
00260 C2.clear() ;
00261 }
00262
00263 if ( C1.size() <= 1 )
00264 {
00265 return 1 ;
00266 }
00267
00268
00269 std::set<int> N_C ;
00270 N_C.insert(C1.begin(), C1.end());
00271 N_C.insert(C2.begin(), C2.end());
00272 std::vector<int> difference;
00273 std::set_difference(N.begin(), N.end(), N_C.begin(), N_C.end(),
00274 difference.begin());
00275 N_C.insert(difference.begin(), difference.end());
00276
00277 BOOST_FOREACH(int x , N_C )
00278 {
00279 if ( fractional_point[ x ] > 0.00001 )
00280 {
00281 F.insert(x) ;
00282 }
00283 else
00284 {
00285 R.insert(x) ;
00286 }
00287 }
00288
00289
00291
00293
00295
00296
00298 std::vector<int>::iterator indx1 = liftsequence_on_C2.begin();
00299
00300 if ( C2.size() != 0 )
00301 {
00302 BOOST_FOREACH(int x, C2)
00303 {
00304 *indx1 = x ;
00305 indx1++ ;
00306 }
00307 std::sort(liftsequence_on_C2.begin(), indx1-1);
00308 }
00309
00310
00311 indx1 = liftsequence_on_R.begin() ;
00312
00313 if ( R.size() != 0 )
00314 {
00315 BOOST_FOREACH(int x, R)
00316 {
00317 *indx1 = x ;
00318 indx1 ++ ;
00319 }
00320 std::sort(liftsequence_on_R.begin(), indx1-1);
00321 }
00322
00323 return 0 ;
00324 }
00325
00326 void CP_KNAPSACK::lift_on_F( std::vector<int>* W )
00327 {
00328 double contribute = -1 ;
00329 int lift_index = -1 ;
00330 int actual_lift_coeff = -1 ;
00331 int lift_coeff = -1 ;
00332
00333 BOOST_FOREACH(int x, to_lift_in_F)
00334 {
00335 int RHS = righthandside - (rightsum+coeffs[x]) ;
00336
00337 if ( RHS >= 0 )
00338 {
00339 int z = find_largest_index(*W, RHS);
00340 actual_lift_coeff = r - 1 + gammasum - z ;
00341 if ( actual_lift_coeff * fractional_point[ x ] > contribute )
00342 {
00343 lift_coeff = actual_lift_coeff ;
00344 contribute = lift_coeff * fractional_point[ x ] ;
00345 lift_index = x ;
00346 }
00347
00348 }
00349
00350 }
00351
00352 if ( lift_index != -1 )
00353 {
00354
00355 liftcoeffs[ lift_index ] = lift_coeff ;
00356 to_lift_in_F.erase( lift_index ) ;
00357 update_Ti(lift_index) ;
00358 previous_lift_index = lift_index ;
00359 lifted_in_F = 1 ;
00360 }
00361
00362 }
00363
00364 void CP_KNAPSACK::lift_on_C2 (std:: vector<int>* W )
00365 {
00366
00367 int x = C2.size() - to_lift_in_C2.size() ;
00368 int lift_index = liftsequence_on_C2[ x ] ;
00369 int RHS = righthandside - update_righthandsum( lift_index ) ;
00370 int z = find_largest_index(*W, RHS);
00371 int lift_coeff = z - r + 1 - gammasum ;
00372 liftcoeffs[ lift_index ] = lift_coeff ;
00373 update_gammasum(lift_index) ;
00374 to_lift_in_C2.erase( lift_index ) ;
00375 update_Ti(lift_index) ;
00376 previous_lift_index = lift_index ;
00377 lifted_in_C2 = 1 ;
00378
00379 }
00380
00381 void CP_KNAPSACK::lift_on_R ( std::vector<int>* W )
00382 {
00383
00384 int x = R.size() - to_lift_in_R.size() ;
00385 int lift_index = liftsequence_on_R[ x ] ;
00386 int RHS = righthandside - (rightsum+coeffs[lift_index]) ;
00387 int z = find_largest_index(*W, RHS);
00388 int lift_coeff = r - 1 + gammasum - z ;
00389 liftcoeffs[ lift_index ] = lift_coeff ;
00390 to_lift_in_R.erase( lift_index ) ;
00391 update_Ti(lift_index) ;
00392 previous_lift_index = lift_index ;
00393 }
00394
00395 void CP_KNAPSACK::compute_first_row()
00396 {
00397
00398 r = C1.size() ;
00399 std::vector<int>::iterator indx1 = sort_array.begin();
00400
00401 BOOST_FOREACH(int x, C1)
00402 {
00403 *indx1 = coeffs[ x ] ;
00404 indx1++ ;
00405 }
00406 std::sort(sort_array.begin(), indx1-1);
00407
00408 W1 = new std::vector<int>() ;
00409 (*W1)[0] = 0 ;
00410
00411 std::vector<int>::iterator it;
00412 for( it = W1->begin(); it != W1->end(); it++)
00413 *(it+1) = *it + sort_array[it - W1->begin()];
00414
00415 W2 = W1 ;
00416 }
00417
00418 void CP_KNAPSACK::compute_next_row()
00419 {
00420 int T = Ti ;
00421 W2 = new std::vector<int>();
00422 int c = liftcoeffs[ previous_lift_index ] ;
00423 int a = coeffs [ previous_lift_index ] ;
00424 int var1 = (*W1)[ index ] ;
00425 for( int index=0; index <= int((*W1).size()-1) ; index++)
00426 {
00427 int var2;
00428 if ( index-c > 0 )
00429 {
00430 var2 = (*W1)[ index - c] ;
00431 }
00432 else
00433 {
00434 var2 = 0 ;
00435 }
00436
00437 var2 = var2 + a ;
00438
00439 if ( var1 < var2 )
00440 {
00441 (*W2)[ index ] = var1 ;
00442 }
00443 else
00444 {
00445 (*W2)[ index ] = var2 ;
00446
00447 }
00448
00449 }
00450
00451 for( int index = (*W1).size() ; index<=T; index++)
00452 {
00453 if ( index-c > 0 )
00454 {
00455 var1 = (*W1)[ index - c] ;
00456
00457 }
00458 else
00459 {
00460 var1 = 0 ;
00461 }
00462
00463 (*W2)[ index ] = var1 + a ;
00464 }
00465 delete W1;
00466 W1 = W2 ;
00467 }
00468
00469 void CP_KNAPSACK::setup_values(subproblem& S)
00470 {
00471 if (S.configuration("CP_KNAPSACK_Debug_Out")=="true")
00472 cerr << "CP_KNAPSACK::setup_values\n";
00473
00474 for (int index=0; index <= number_variables-1; index++ )
00475 {
00476 int coeff = (int) KC->coeff(((var) item_index_map[index]).var_pointer() ) ;
00477
00478 if ( coeff >= 0 )
00479 {
00480 fractional_point[index] = S.value( item_index_map[ index ] ) ;
00481 }
00482 else
00483 {
00484 fractional_point[index] = 1 - S.value( item_index_map[ index ] ) ;
00485 }
00486
00487
00488
00489 }
00490 F.clear() ;
00491 R.clear() ;
00492 C1.clear() ;
00493 C2.clear() ;
00494 to_lift_in_F.clear() ;
00495 to_lift_in_C2.clear() ;
00496 to_lift_in_R.clear() ;
00497 BOOST_FOREACH(int &member, liftcoeffs)
00498 member = 0;
00499 }
00500
00501 CP_KNAPSACK::status CP_KNAPSACK::standard_separation(subproblem& S)
00502 {
00503 if (S.configuration("CP_KNAPSACK_Debug_Out")=="true")
00504 cerr << "CP_KNAPSACK::seperate\n";
00505 if ( no_sep == 1)
00506 {
00507 return no_constraint_found ;
00508 }
00509
00510 setup_values(S) ;
00511
00512
00513 if ( compute_cover() == 1 )
00514 {
00515 return no_constraint_found ;
00516 }
00517
00518 BOOST_FOREACH (int x,C1)
00519 {
00520 liftcoeffs[ x ] = 1 ;
00521 }
00522
00523 init_righthandsum();
00524 Ti=C1.size() ;
00525 gammasum = 0 ;
00526
00527 compute_first_row() ;
00528
00529
00530 to_lift_in_F = F ;
00531 to_lift_in_C2 = C2 ;
00532 to_lift_in_R = R ;
00533
00534 bool TESTDONE = 0 ;
00535
00539
00540 while ( (to_lift_in_R.size() != 0 ) || (to_lift_in_C2.size() != 0)
00541 || ( to_lift_in_F.size() != 0) )
00542 {
00543 lifted_in_F = 0 ;
00544 lifted_in_C2 = 0 ;
00545
00546
00547 if ( to_lift_in_F.size() != 0 )
00548
00549 {
00550 lift_on_F(W2) ;
00551 }
00552
00556
00557 if ( ( to_lift_in_F.size() == 0 ) && ( !TESTDONE ) )
00558 {
00559
00560 double C1_size = C1.size()-1 ;
00561
00562
00563
00564 double g = 0 ;
00565
00566 BOOST_FOREACH (int x, F)
00567 {
00568 if ( KC->coeff ( ((var) item_index_map[x]).var_pointer() ) < 0 )
00569 {
00570
00571 g -= liftcoeffs[x]* S.value( item_index_map[ x ] ) ;
00572 C1_size -= liftcoeffs[x] ;
00573 }
00574 else
00575 {
00576 g += liftcoeffs[x]* S.value( item_index_map[ x ] ) ;
00577
00578 }
00579 }
00580
00581 BOOST_FOREACH (int x, C1)
00582 {
00583 if ( KC->coeff ( ((var) item_index_map[x]).var_pointer() ) < 0 )
00584 {
00585 g -= S.value( item_index_map[ x ] ) ;
00586 C1_size -= liftcoeffs[x] ;
00587 }
00588 else
00589 {
00590 g += S.value( item_index_map[ x ] ) ;
00591
00592 }
00593 }
00594
00595 if ( g-violation_tolerance <= C1_size )
00596 {
00597 return no_constraint_found ;
00598 }
00599
00600 TESTDONE = 1 ;
00601 }
00602
00603
00604
00605 if ( (!lifted_in_F ) && ( to_lift_in_C2.size() != 0 ) )
00606
00607 {
00608 lift_on_C2(W2) ;
00609 }
00610
00611 if ( (!lifted_in_C2) && (!lifted_in_F) && ( to_lift_in_C2.size() == 0)
00612 && ( to_lift_in_R.size() != 0 ) && ( to_lift_in_F.size() == 0 ) )
00613 {
00614 lift_on_R(W2) ;
00615 }
00616
00617 if ( (to_lift_in_R.size() != 0 ) || (to_lift_in_C2.size() != 0)
00618 || ( to_lift_in_F.size() != 0) )
00619 {
00620 compute_next_row() ;
00621 }
00622
00623
00624
00625 }
00626
00630
00631 int RHS = C1.size()-1 + gammasum ;
00632
00633 BOOST_FOREACH ( index, negative_coeff_indices)
00634 {
00635 liftcoeffs [index] = -(liftcoeffs [index]) ;
00636 RHS += liftcoeffs[index] ;
00637 }
00638
00639 cons_obj *new_constraint = new LCI(liftcoeffs,RHS,item_index_map) ;
00640 S.add_basic_constraint( new_constraint, Dynamic ) ;
00641 cout<<"cp knapsack constraint\n";
00642 return constraint_found ;
00643 }
00644 void CP_KNAPSACK::info() {
00645 cout<<"Configurations:\n";
00646 cout<<"CP_KNAPSACK_Debug_Out [true|false]\n";
00647 };
00648
00649 }