Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

cp_knapsack.cc

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    double LCI::coeff(var_obj* v) {
00017    int index ;
00018    index = item_index_map[ v ] ;
00019    return coeff_array[ index ] ;
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    //Check whether val was found in vec
00033    if (index != vec.end())
00034    {
00035       //Increase index to index of last element with a value equal to val
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    // substitute negative coeffs  //
00059   
00060    for (int index=0; index <= number_variables-1; index++ )
00061    {
00062       item_index_map[index]=S.get_var(index); // TODO von mir!  
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    //  insert indices of coeffs a_j, with   //
00076    // (a_j <= righthandside) && ( a_j != 0) //
00077    // in set N.                             //
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 //Comparison function to sort input by nonincreasing values
00128 bool nonincreasing (double i, double j) { return (i>j); }
00129 
00130 bool CP_KNAPSACK::compute_cover()
00131 {
00132   
00134    // COVER GENEARTION //                                                  
00136 
00137    std::vector<int> cover_candidates; // Indices of cover candidates
00138   
00140    // write all indices of variables with fractional value > 0 in       //
00141    // array cover_candidates                                            //
00143   
00144    int index1 = 0 ;  
00145    BOOST_FOREACH(index,N) // check all variables 
00146    { 
00147       if ( (fractional_point[index] > 0.00001) ) 
00148       {
00149          cover_candidates [ index1 ] = index ;
00150          index1++; 
00151       }
00152    }
00153   
00154    if ( index1 == 0 )   // STOP, all variables equal to zero
00155    {    
00156       return 1 ;
00157    }
00158    int number_cover_candidates = index1; //save size of array 'cover_candidates'
00159 
00161    // sort array by nonincreasing values of fractional point            //
00163    std::sort(cover_candidates.begin(), cover_candidates.end(),nonincreasing);
00164 
00166    // try to generate a cover, by summing up  the coefficients of the      //
00167    // variables in order of nonincreasing values of fractional points      //  
00168    // The resulting cover indices are stored in array 'sort_array'         //
00170   
00171    bool cover_found = 0 ; //true if cover was found
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 ) // STOP, no cover found  
00191    {           
00192       return 1 ;
00193    }
00194  
00195  
00197    // MINIMAL COVER CONVERSION //                                                  
00199    int sort_array_size = index1-1 ; // save size of array 'sort_candidates'
00200 
00202    // sort cover indices array by nondecreasing values of coefficients  //
00204    std::sort(sort_array.begin(), sort_array.end());
00205   
00207    // try to eleminate the variables of the Cover in order of  //
00208    // nondecreasing value of coefficients                      //
00210    bool minimal_cover = 0 ; //true if minimal cover was found
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    // COVER PARTITION // 
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 ) // STOP, cardinality C_1 is too small to generate LCI
00264    {
00265       return 1 ;
00266    }
00267 
00268    //Calculates N - (C1 + C2) and stores result in N_C 
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    // LIFTINGORDER     // 
00293   
00295    // lift variables in R in order of           //
00296    // nonincreasing value of fractional point   //
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    // write array containing the current fractional solution according to the substitution 
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 ; //True if test is done
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       //delete W2 ;
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 ; // one LCI added 
00643 }
00644 void CP_KNAPSACK::info() {
00645    cout<<"Configurations:\n";
00646    cout<<"CP_KNAPSACK_Debug_Out [true|false]\n";
00647 };
00648 
00649 }
Generated on Mon Mar 28 22:03:47 2011 for SCIL by  doxygen 1.6.3