예제 #1
0
/* Returns reduced gradient.Returns an offset (to be added to current one).
 */
double
ClpLinearObjective::reducedGradient(ClpSimplex * model, double * region,
                                    bool /*useFeasibleCosts*/)
{
     int numberRows = model->numberRows();
     //work space
     CoinIndexedVector  * workSpace = model->rowArray(0);

     CoinIndexedVector arrayVector;
     arrayVector.reserve(numberRows + 1);

     int iRow;
#ifdef CLP_DEBUG
     workSpace->checkClear();
#endif
     double * array = arrayVector.denseVector();
     int * index = arrayVector.getIndices();
     int number = 0;
     const double * cost = model->costRegion();
     //assert (!useFeasibleCosts);
     const int * pivotVariable = model->pivotVariable();
     for (iRow = 0; iRow < numberRows; iRow++) {
          int iPivot = pivotVariable[iRow];
          double value = cost[iPivot];
          if (value) {
               array[iRow] = value;
               index[number++] = iRow;
          }
     }
     arrayVector.setNumElements(number);

     int numberColumns = model->numberColumns();

     // Btran basic costs
     double * work = workSpace->denseVector();
     model->factorization()->updateColumnTranspose(workSpace, &arrayVector);
     ClpFillN(work, numberRows, 0.0);
     // now look at dual solution
     double * rowReducedCost = region + numberColumns;
     double * dual = rowReducedCost;
     double * rowCost = model->costRegion(0);
     for (iRow = 0; iRow < numberRows; iRow++) {
          dual[iRow] = array[iRow];
     }
     double * dj = region;
     ClpDisjointCopyN(model->costRegion(1), numberColumns, dj);
     model->transposeTimes(-1.0, dual, dj);
     for (iRow = 0; iRow < numberRows; iRow++) {
          // slack
          double value = dual[iRow];
          value += rowCost[iRow];
          rowReducedCost[iRow] = value;
     }
     return 0.0;
}
예제 #2
0
//--------------------------------------------------------------------------
void
CoinIndexedVectorUnitTest()
{
  
  int i;
  // Test default constructor
  {
    CoinIndexedVector r;
    assert( r.indices_==NULL );
    assert( r.elements_==NULL );
    assert( r.getNumElements()==0 );
    assert( r.capacity_==0);
  }
  
  // Test set and get methods
  const int ne = 4;
  int inx[ne] = { 1, 3, 4, 7 };
  double el[ne] = { 1.2, 3.4, 5.6, 7.8 };
  {
    CoinIndexedVector r;    
    assert( r.getNumElements()==0 );
    
    // Test setting/getting elements with int* & float* vectors
    r.setVector( ne, inx, el );
    assert( r.getNumElements()==ne );
    for ( i=0; i<ne; i++ ) {
      assert( r.getIndices()[i]  == inx[i] );
      assert( r[inx[i]]  == el[i] );
    }
    
    // Test setting/getting elements with indices out of order  
    const int ne2 = 5;
    int inx2[ne2] = { 2, 4, 8, 14, 3 };
    double el2[ne2] = { 2.2, 4.4, 6.6, 8.8, 3.3 };
    
    r.setVector(ne2,inx2,el2);
    
    assert( r.getNumElements()==ne2 );    
    
    assert( r.getIndices()[0]==inx2[0] );
    
    assert( r.getIndices()[1]==inx2[1] );
    
    assert( r.getIndices()[2]==inx2[2] );
    
    assert( r.getIndices()[3]==inx2[3] );
    
    assert( r.getIndices()[4]==inx2[4] );
    

    CoinIndexedVector r1(ne2,inx2,el2);
    assert( r == r1 );   
  }    
  CoinIndexedVector r;
  
  
  {
    CoinIndexedVector r;
    const int ne = 3;
    int inx[ne] = { 1, 2, 3 };
    double el[ne] = { 2.2, 4.4, 8.8};
    r.setVector(ne,inx,el);
    int c = r.capacity();
    // Test swap function
    r.swap(0,2);
    assert( r.getIndices()[0]==3 );
    assert( r.getIndices()[1]==2 );
    assert( r.getIndices()[2]==1 );
    assert( r.capacity() == c );
    
    // Test the append function
    CoinIndexedVector s;
    const int nes = 4;
    int inxs[nes] = { 11, 12, 13, 14 };
    double els[nes] = { .122, 14.4, 18.8, 19.9};
    s.setVector(nes,inxs,els);
    r.append(s);
    assert( r.getNumElements()==7 );
    assert( r.getIndices()[0]==3 );
    assert( r.getIndices()[1]==2 );
    assert( r.getIndices()[2]==1 );
    assert( r.getIndices()[3]==11 );
    assert( r.getIndices()[4]==12 );
    assert( r.getIndices()[5]==13 );
    assert( r.getIndices()[6]==14 );
    
    // Test the resize function
    c = r.capacity();
    r.truncate(4);
    // we will lose 11
    assert( r.getNumElements()==3 );
    assert( r.getIndices()[0]==3 );
    assert( r.getIndices()[1]==2 );
    assert( r.getIndices()[2]==1 );
    assert( r.getMaxIndex() == 3 );
    assert( r.getMinIndex() == 1 );
    assert( r.capacity() == c );
  }
  
  // Test borrow and return vector
  {
    CoinIndexedVector r,r2;
    const int ne = 3;
    int inx[ne] = { 1, 2, 3 };
    double el[ne] = { 2.2, 4.4, 8.8};
    double els[4] = { 0.0,2.2, 4.4, 8.8};
    r.setVector(ne,inx,el);
    r2.borrowVector(4,ne,inx,els);
    assert (r==r2);
    r2.returnVector();
    assert (!r2.capacity());
    assert (!r2.getNumElements());
    assert (!r2.denseVector());
    assert (!r2.getIndices());
  }
  
  // Test copy constructor and assignment operator
  {
    CoinIndexedVector rhs;
    {
      CoinIndexedVector r;
      {
	CoinIndexedVector rC1(r);      
	assert( 0==r.getNumElements() );
	assert( 0==rC1.getNumElements() );
	
	
	r.setVector( ne, inx, el ); 
	
	assert( ne==r.getNumElements() );
	assert( 0==rC1.getNumElements() ); 
      }
      
      CoinIndexedVector rC2(r);   
      
      assert( ne==r.getNumElements() );
      assert( ne==rC2.getNumElements() );
      
      for ( i=0; i<ne; i++ ) {
	assert( r.getIndices()[i] == rC2.getIndices()[i] );
      }
      
      rhs=rC2;
    }
    // Test that rhs has correct values even though lhs has gone out of scope
    assert( rhs.getNumElements()==ne );
    
    for ( i=0; i<ne; i++ ) {
      assert( inx[i] == rhs.getIndices()[i] );
    } 
  }
  
  // Test operator==
  {
    CoinIndexedVector v1,v2;
    assert( v1==v2 );
    assert( v2==v1 );
    assert( v1==v1 );
    assert( !(v1!=v2) );
    
    v1.setVector( ne, inx, el );
    assert ( !(v1==v2) );
    assert ( v1!=v2 );
    
    CoinIndexedVector v3(v1);
    assert( v3==v1 );
    assert( v3!=v2 );
    
    CoinIndexedVector v4(v2);
    assert( v4!=v1 );
    assert( v4==v2 );
  }
  
  {
    // Test sorting of indexed vectors    
    const int ne = 4;
    int inx[ne] = { 1, 4, 0, 2 };
    double el[ne] = { 10., 40., 1., 20. };
    CoinIndexedVector r;
    r.setVector(ne,inx,el);
    
    // Test that indices are in increasing order
    r.sort();
    for ( i=1; i<ne; i++ ) assert( r.getIndices()[i-1] < r.getIndices()[i] );

  }    
  {
    // Test operator[] and indexExists()
    const int ne = 4;
    int inx[ne] =   {  1,   4,  0,   2 };
    double el[ne] = { 10., 40., 1., 50. };
    CoinIndexedVector r;
    bool errorThrown = false;
    try {
      assert( r[1]==0. );
    }
    catch (CoinError& e) {
      errorThrown = true;
    }
    assert( errorThrown );
    
    r.setVector(ne,inx,el);
    
    errorThrown = false;
    try {
      assert( r[-1]==0. );
    }
    catch (CoinError& e) {
      errorThrown = true;
    }
    assert( errorThrown );
    
    assert( r[ 0]==1. );
    assert( r[ 1]==10.);
    assert( r[ 2]==50.);
    assert( r[ 3]==0. );
    assert( r[ 4]==40.);
    errorThrown = false;
    try {
      assert( r[5]==0. );
    }
    catch (CoinError& e) {
      errorThrown = true;
    }
    assert( errorThrown );
    
    assert ( r.getMaxIndex()==4 );
    assert ( r.getMinIndex()==0 );
  }
  
  // Test that attemping to get min/max index of a 0,
  // length vector 
  {
    CoinIndexedVector nullVec;
    assert( nullVec.getMaxIndex() == -COIN_INT_MAX/*0*/ );
    assert( nullVec.getMinIndex() == COIN_INT_MAX/*0*/ );
  } 
  
  // Test CoinFltEq with equivalent method
  {    
    const int ne = 4;
    int inx1[ne] = { 1, 3, 4, 7 };
    double el1[ne] = { 1.2, 3.4, 5.6, 7.8 };
    int inx2[ne] = { 7, 4, 3, 1 };
    double el2[ne] = { 7.8+.5, 5.6+.5, 3.4+.5, 1.2+.5 };
    CoinIndexedVector v1,v2;
    v1.setVector(ne,inx1,el1);
    v2.setVector(ne,inx2,el2);
  }
  
  {
    // Test reserve
    CoinIndexedVector v1,v2;
    assert( v1.capacity()==0 );
    v1.reserve(6);
    assert( v1.capacity()==6 );
    assert( v1.getNumElements()==0 );
    v2=v1;
    assert( v2.capacity() == 6 );
    assert( v2.getNumElements()==0 );
    assert( v2==v1 );
    v1.setVector(0,NULL,NULL);
    assert( v1.capacity()==6 );
    assert( v1.getNumElements()==0 );
    assert( v2==v1 );
    v2=v1;
    assert( v2.capacity() == 6 );
    assert( v2.getNumElements()==0 );
    assert( v2==v1 );
    
    const int ne = 2;
    int inx[ne] = { 1, 3 };
    double el[ne] = { 1.2, 3.4 };
    v1.setVector(ne,inx,el);
    assert( v1.capacity()==6 );
    assert( v1.getNumElements()==2 );
    v2=v1;
    assert( v2.capacity()==6 );
    assert( v2.getNumElements()==2 );
    assert( v2==v1 );
    
    const int ne1 = 5;
    int inx1[ne1] = { 1, 3, 4, 5, 6 };
    double el1[ne1] = { 1.2, 3.4, 5., 6., 7. };
    v1.setVector(ne1,inx1,el1);
    assert( v1.capacity()==7 );
    assert( v1.getNumElements()==5 );
    v2=v1;
    assert( v2.capacity()==7 );
    assert( v2.getNumElements()==5 );
    assert( v2==v1 );
    
    const int ne2 = 8;
    int inx2[ne2] = { 1, 3, 4, 5, 6, 7, 8, 9 };
    double el2[ne2] = { 1.2, 3.4, 5., 6., 7., 8., 9., 10. };
    v1.setVector(ne2,inx2,el2);
    assert( v1.capacity()==10 );
    assert( v1.getNumElements()==8 );
    v2=v1;
    assert( v2.getNumElements()==8 );    
    assert( v2==v1 );
    
    v1.setVector(ne1,inx1,el1);
    assert( v1.capacity()==10 );
    assert( v1.getNumElements()==5 );
    v2=v1;    
    assert( v2.capacity()==10 );
    assert( v2.getNumElements()==5 );
    assert( v2==v1 );
    
    v1.reserve(7);
    assert( v1.capacity()==10 );
    assert( v1.getNumElements()==5 );
    v2=v1;
    assert( v2.capacity()==10 );
    assert( v2.getNumElements()==5 );
    assert( v2==v1 );
    
  }
  
  // Test the insert method
  {
    CoinIndexedVector v1;
    assert( v1.getNumElements()==0 );
    assert( v1.capacity()==0 );
    
    v1.insert(1,1.);
    assert( v1.getNumElements()==1 );
    assert( v1.capacity()==2 );
    assert( v1.getIndices()[0] == 1 );
    
    v1.insert(10,10.);
    assert( v1.getNumElements()==2 );
    assert( v1.capacity()==11 );
    assert( v1.getIndices()[1] == 10 );
    
    v1.insert(20,20.);
    assert( v1.getNumElements()==3 );
    assert( v1.capacity()==21 );
    assert( v1.getIndices()[2] == 20 );
    
    v1.insert(30,30.);
    assert( v1.getNumElements()==4 );
    assert( v1.capacity()==31 );
    assert( v1.getIndices()[3] == 30 );

    v1.insert(40,40.);
    assert( v1.getNumElements()==5 );
    assert( v1.capacity()==41 );
    assert( v1.getIndices()[4] == 40 );
    
    v1.insert(50,50.);
    assert( v1.getNumElements()==6 );
    assert( v1.capacity()==51 );
    assert( v1.getIndices()[5] == 50 );
    
    CoinIndexedVector v2;
    const int ne1 = 3;
    int inx1[ne1] = { 1, 3, 4 };
    double el1[ne1] = { 1.2, 3.4, 5. };
    v2.setVector(ne1,inx1,el1);    
    assert( v2.getNumElements()==3 );
    assert( v2.capacity()==5 );

    // Test clean method - get rid of 1.2
    assert(v2.clean(3.0)==2);
    assert(v2.denseVector()[1]==0.0);

    // Below are purely for debug - so use assert
    // so we won't try with false
    // Test checkClean 
#ifndef NO_CHECK_CL
    v2.checkClean();
    assert( v2.getNumElements()==2 );

    // Get rid of all
    int numberRemaining = v2.clean(10.0);
    assert(numberRemaining==0);
    v2.checkClear();
#endif    
  }
  
  {
    //Test setConstant and setElement     
    CoinIndexedVector v2;
    const int ne1 = 3;
    int inx1[ne1] = { 1, 3, 4 };
    v2.setConstant(ne1,inx1,3.14);    
    assert( v2.getNumElements()==3 );
    assert( v2.capacity()==5 );
    assert( v2.getIndices()[0]==1 );
    assert( v2.getIndices()[1]==3 );
    assert( v2.getIndices()[2]==4 );
    
    assert( v2[3] == 3.14 );
    
    CoinIndexedVector v2X(ne1,inx1,3.14);
    assert( v2 == v2X );
    
  }
  
  {
    //Test setFull 
    CoinIndexedVector v2;
    const int ne2 = 3;
    double el2[ne2] = { 1., 3., 4. };
    v2.setFull(ne2,el2);    
    assert( v2.getNumElements()==3 );
    assert( v2.capacity()==3 );
    assert( v2.getIndices()[0]==0 );
    assert( v2.getIndices()[1]==1 );
    assert( v2.getIndices()[2]==2 );
    
    assert( v2[1] == 3. );
    
    CoinIndexedVector v2X(ne2,el2);
    assert( v2 == v2X ); 
    
    v2.setFull(0,el2); 
    assert( v2[2] == 0. );  
  }
  
  
#if 0
  // what happens when someone sets 
  // the number of elements to be a negative number
  {    
    const int ne = 4;
    int inx1[ne] = { 1, 3, 4, 7 };
    double el1[ne] = { 1.2, 3.4, 5.6, 7.8 };
    CoinIndexedVector v1;
    v1.set(-ne,inx1,el1);
  }
#endif
  
  
  // Test copy constructor from ShallowPackedVector
  {
    const int ne = 4;
    int inx[ne] =   {  1,   4,  0,   2 };
    double el[ne] = { 10., 40., 1., 50. };
    CoinIndexedVector std(ne,inx,el);
    CoinShallowPackedVector * spvP = new CoinShallowPackedVector(ne,inx,el);
    CoinIndexedVector pv(*spvP);
    assert( pv == std );
    delete spvP;
    assert( pv == std );
  }
  
  // Test assignment from ShallowPackedVector
  {
    const int ne = 4;
    int inx[ne] =   {  1,   4,  0,   2 };
    double el[ne] = { 10., 40., 1., 50. };
    CoinIndexedVector std(ne,inx,el);
    CoinShallowPackedVector * spvP = new CoinShallowPackedVector(ne,inx,el);
    CoinIndexedVector pv;
    pv = *spvP;
    assert( pv == std );
    delete spvP;
    assert( pv == std );
  }
  
  {
    // Test that sample usage works
    
    const int ne = 4;
    int inx[ne] =   {  1,   4,  0,   2 };
    double el[ne] = { 10., 40., 1., 50. };
    CoinIndexedVector r(ne,inx,el);
    
    assert( r.getIndices()[0]== 1  );
    assert( r.getIndices()[1]== 4  );
    assert( r.getIndices()[2]== 0  );
    assert( r.getIndices()[3]== 2  );
    
    assert( r[ 0]==1. );
    assert( r[ 1]==10.);
    assert( r[ 2]==50.);
    assert( r[ 3]==0. );
    assert( r[ 4]==40.);
    
    r.sortIncrElement();
    
    assert( r.getIndices()[0]== 0  );
    assert( r.getIndices()[1]== 1  );
    assert( r.getIndices()[2]== 4  );
    assert( r.getIndices()[3]== 2  );
    
    assert( r[ 0]==1. );
    assert( r[ 1]==10.);
    assert( r[ 2]==50.);
    assert( r[ 3]==0. );
    assert( r[ 4]==40.);
    
    CoinIndexedVector r1;
    r1=r;
    assert( r==r1 );
    
    CoinIndexedVector add = r + r1;
    assert( add[0] ==  1.+ 1. );
    assert( add[1] == 10.+10. );
    assert( add[2] == 50.+50. );
    assert( add[3] ==  0.+ 0. );
    assert( add[4] == 40.+40. );
    
  }
  
}
예제 #3
0
/* Return <code>x *A</code> in <code>z</code> but
   just for number indices in y.
   Default cheats with fake CoinIndexedVector and
   then calls subsetTransposeTimes */
void
ClpMatrixBase::listTransposeTimes(const ClpSimplex * model,
                                  double * x,
                                  int * y,
                                  int number,
                                  double * z) const
{
     CoinIndexedVector pi;
     CoinIndexedVector list;
     CoinIndexedVector output;
     int * saveIndices = list.getIndices();
     list.setNumElements(number);
     list.setIndexVector(y);
     double * savePi = pi.denseVector();
     pi.setDenseVector(x);
     double * saveOutput = output.denseVector();
     output.setDenseVector(z);
     output.setPacked();
     subsetTransposeTimes(model, &pi, &list, &output);
     // restore settings
     list.setIndexVector(saveIndices);
     pi.setDenseVector(savePi);
     output.setDenseVector(saveOutput);
}
예제 #4
0
/* Saves any weights round factorization as pivot rows may change
   1) before factorization
   2) after factorization
   3) just redo infeasibilities
   4) restore weights
*/
void
ClpDualRowSteepest::saveWeights(ClpSimplex * model, int mode)
{
     // alternateWeights_ is defined as indexed but is treated oddly
     model_ = model;
     int numberRows = model_->numberRows();
     int numberColumns = model_->numberColumns();
     const int * pivotVariable = model_->pivotVariable();
     int i;
     if (mode == 1) {
          if(weights_) {
               // Check if size has changed
               if (infeasible_->capacity() == numberRows) {
                    alternateWeights_->clear();
                    // change from row numbers to sequence numbers
                    int * which = alternateWeights_->getIndices();
                    for (i = 0; i < numberRows; i++) {
                         int iPivot = pivotVariable[i];
                         which[i] = iPivot;
                    }
                    state_ = 1;
               } else {
                    // size has changed - clear everything
                    delete [] weights_;
                    weights_ = NULL;
                    delete [] dubiousWeights_;
                    dubiousWeights_ = NULL;
                    delete infeasible_;
                    infeasible_ = NULL;
                    delete alternateWeights_;
                    alternateWeights_ = NULL;
                    delete savedWeights_;
                    savedWeights_ = NULL;
                    state_ = -1;
               }
          }
     } else if (mode == 2 || mode == 4 || mode >= 5) {
          // restore
          if (!weights_ || state_ == -1 || mode == 5) {
               // initialize weights
               delete [] weights_;
               delete alternateWeights_;
               weights_ = new double[numberRows];
               alternateWeights_ = new CoinIndexedVector();
               // enough space so can use it for factorization
               alternateWeights_->reserve(numberRows +
                                          model_->factorization()->maximumPivots());
               if (mode_ != 1 || mode == 5) {
                    // initialize to 1.0 (can we do better?)
                    for (i = 0; i < numberRows; i++) {
                         weights_[i] = 1.0;
                    }
               } else {
                    CoinIndexedVector * temp = new CoinIndexedVector();
                    temp->reserve(numberRows +
                                  model_->factorization()->maximumPivots());
                    double * array = alternateWeights_->denseVector();
                    int * which = alternateWeights_->getIndices();
                    for (i = 0; i < numberRows; i++) {
                         double value = 0.0;
                         array[0] = 1.0;
                         which[0] = i;
                         alternateWeights_->setNumElements(1);
                         alternateWeights_->setPackedMode(true);
                         model_->factorization()->updateColumnTranspose(temp,
                                   alternateWeights_);
                         int number = alternateWeights_->getNumElements();
                         int j;
                         for (j = 0; j < number; j++) {
                              value += array[j] * array[j];
                              array[j] = 0.0;
                         }
                         alternateWeights_->setNumElements(0);
                         weights_[i] = value;
                    }
                    delete temp;
               }
               // create saved weights (not really indexedvector)
               savedWeights_ = new CoinIndexedVector();
               savedWeights_->reserve(numberRows);

               double * array = savedWeights_->denseVector();
               int * which = savedWeights_->getIndices();
               for (i = 0; i < numberRows; i++) {
                    array[i] = weights_[i];
                    which[i] = pivotVariable[i];
               }
          } else if (mode != 6) {
               int * which = alternateWeights_->getIndices();
               CoinIndexedVector * rowArray3 = model_->rowArray(3);
               rowArray3->clear();
               int * back = rowArray3->getIndices();
               // In case something went wrong
               for (i = 0; i < numberRows + numberColumns; i++)
                    back[i] = -1;
               if (mode != 4) {
                    // save
                    CoinMemcpyN(which,	numberRows, savedWeights_->getIndices());
                    CoinMemcpyN(weights_,	numberRows, savedWeights_->denseVector());
               } else {
                    // restore
                    //memcpy(which,savedWeights_->getIndices(),
                    //     numberRows*sizeof(int));
                    //memcpy(weights_,savedWeights_->denseVector(),
                    //     numberRows*sizeof(double));
                    which = savedWeights_->getIndices();
               }
               // restore (a bit slow - but only every re-factorization)
               double * array = savedWeights_->denseVector();
               for (i = 0; i < numberRows; i++) {
                    int iSeq = which[i];
                    back[iSeq] = i;
               }
               for (i = 0; i < numberRows; i++) {
                    int iPivot = pivotVariable[i];
                    iPivot = back[iPivot];
                    if (iPivot >= 0) {
                         weights_[i] = array[iPivot];
                         if (weights_[i] < DEVEX_TRY_NORM)
                              weights_[i] = DEVEX_TRY_NORM; // may need to check more
                    } else {
                         // odd
                         weights_[i] = 1.0;
                    }
               }
          } else {
               // mode 6 - scale back weights as primal errors
               double primalError = model_->largestPrimalError();
               double allowed ;
               if (primalError > 1.0e3)
                    allowed = 10.0;
               else if (primalError > 1.0e2)
                    allowed = 50.0;
               else if (primalError > 1.0e1)
                    allowed = 100.0;
               else
                    allowed = 1000.0;
               double allowedInv = 1.0 / allowed;
               for (i = 0; i < numberRows; i++) {
                    double value = weights_[i];
                    if (value < allowedInv)
                         value = allowedInv;
                    else if (value > allowed)
                         value = allowed;
                    weights_[i] = allowed;
               }
          }
          state_ = 0;
          // set up infeasibilities
          if (!infeasible_) {
               infeasible_ = new CoinIndexedVector();
               infeasible_->reserve(numberRows);
          }
     }
     if (mode >= 2) {
          // Get dubious weights
          //if (!dubiousWeights_)
          //dubiousWeights_=new int[numberRows];
          //model_->factorization()->getWeights(dubiousWeights_);
          infeasible_->clear();
          int iRow;
          const int * pivotVariable = model_->pivotVariable();
          double tolerance = model_->currentPrimalTolerance();
          for (iRow = 0; iRow < numberRows; iRow++) {
               int iPivot = pivotVariable[iRow];
               double value = model_->solution(iPivot);
               double lower = model_->lower(iPivot);
               double upper = model_->upper(iPivot);
               if (value < lower - tolerance) {
                    value -= lower;
                    value *= value;
#ifdef CLP_DUAL_COLUMN_MULTIPLIER
                    if (iPivot < numberColumns)
                         value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns
#endif
#ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER
                    if (lower == upper)
                         value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables
#endif
                    // store square in list
                    infeasible_->quickAdd(iRow, value);
               } else if (value > upper + tolerance) {
                    value -= upper;
                    value *= value;
#ifdef CLP_DUAL_COLUMN_MULTIPLIER
                    if (iPivot < numberColumns)
                         value *= CLP_DUAL_COLUMN_MULTIPLIER; // bias towards columns
#endif
#ifdef CLP_DUAL_FIXED_COLUMN_MULTIPLIER
                    if (lower == upper)
                         value *= CLP_DUAL_FIXED_COLUMN_MULTIPLIER; // bias towards taking out fixed variables
#endif
                    // store square in list
                    infeasible_->quickAdd(iRow, value);
               }
          }
     }
}
예제 #5
0
/* Updates weights and returns pivot alpha.
   Also does FT update */
double
ClpDualRowSteepest::updateWeights(CoinIndexedVector * input,
                                  CoinIndexedVector * spare,
                                  CoinIndexedVector * spare2,
                                  CoinIndexedVector * updatedColumn)
{
     //#define CLP_DEBUG 3
#if CLP_DEBUG>2
     // Very expensive debug
     {
          int numberRows = model_->numberRows();
          CoinIndexedVector * temp = new CoinIndexedVector();
          temp->reserve(numberRows +
                        model_->factorization()->maximumPivots());
          double * array = alternateWeights_->denseVector();
          int * which = alternateWeights_->getIndices();
          alternateWeights_->clear();
          int i;
          for (i = 0; i < numberRows; i++) {
               double value = 0.0;
               array[i] = 1.0;
               which[0] = i;
               alternateWeights_->setNumElements(1);
               model_->factorization()->updateColumnTranspose(temp,
                         alternateWeights_);
               int number = alternateWeights_->getNumElements();
               int j;
               for (j = 0; j < number; j++) {
                    int iRow = which[j];
                    value += array[iRow] * array[iRow];
                    array[iRow] = 0.0;
               }
               alternateWeights_->setNumElements(0);
               double w = CoinMax(weights_[i], value) * .1;
               if (fabs(weights_[i] - value) > w) {
                    printf("%d old %g, true %g\n", i, weights_[i], value);
                    weights_[i] = value; // to reduce printout
               }
               //else
               //printf("%d matches %g\n",i,value);
          }
          delete temp;
     }
#endif
     assert (input->packedMode());
     if (!updatedColumn->packedMode()) {
          // I think this means empty
#ifdef COIN_DEVELOP
          printf("updatedColumn not packed mode ClpDualRowSteepest::updateWeights\n");
#endif
          return 0.0;
     }
     double alpha = 0.0;
     if (!model_->factorization()->networkBasis()) {
          // clear other region
          alternateWeights_->clear();
          double norm = 0.0;
          int i;
          double * work = input->denseVector();
          int numberNonZero = input->getNumElements();
          int * which = input->getIndices();
          double * work2 = spare->denseVector();
          int * which2 = spare->getIndices();
          // ftran
          //permute and move indices into index array
          //also compute norm
          //int *regionIndex = alternateWeights_->getIndices (  );
          const int *permute = model_->factorization()->permute();
          //double * region = alternateWeights_->denseVector();
          if (permute) {
               for ( i = 0; i < numberNonZero; i ++ ) {
                    int iRow = which[i];
                    double value = work[i];
                    norm += value * value;
                    iRow = permute[iRow];
                    work2[iRow] = value;
                    which2[i] = iRow;
               }
          } else {
               for ( i = 0; i < numberNonZero; i ++ ) {
                    int iRow = which[i];
                    double value = work[i];
                    norm += value * value;
                    //iRow = permute[iRow];
                    work2[iRow] = value;
                    which2[i] = iRow;
               }
          }
          spare->setNumElements ( numberNonZero );
          // Do FT update
#if 0
          ft_count_in += updatedColumn->getNumElements();
          up_count_in += spare->getNumElements();
#endif
          if (permute || true) {
#if CLP_DEBUG>2
               printf("REGION before %d els\n", spare->getNumElements());
               spare->print();
#endif
               model_->factorization()->updateTwoColumnsFT(spare2, updatedColumn,
                         spare, permute != NULL);
#if CLP_DEBUG>2
               printf("REGION after %d els\n", spare->getNumElements());
               spare->print();
#endif
          } else {
               // Leave as old way
               model_->factorization()->updateColumnFT(spare2, updatedColumn);
               model_->factorization()->updateColumn(spare2, spare, false);
          }
#undef CLP_DEBUG
#if 0
          ft_count += updatedColumn->getNumElements();
          up_count += spare->getNumElements();
          xx_count++;
          if ((xx_count % 1000) == 0)
               printf("zz %d ft %g up %g (in %g %g)\n", xx_count, ft_count, up_count,
                      ft_count_in, up_count_in);
#endif
          numberNonZero = spare->getNumElements();
          // alternateWeights_ should still be empty
          int pivotRow = model_->pivotRow();
#ifdef CLP_DEBUG
          if ( model_->logLevel (  ) > 4  &&
                    fabs(norm - weights_[pivotRow]) > 1.0e-3 * (1.0 + norm))
               printf("on row %d, true weight %g, old %g\n",
                      pivotRow, sqrt(norm), sqrt(weights_[pivotRow]));
#endif
          // could re-initialize here (could be expensive)
          norm /= model_->alpha() * model_->alpha();
          assert(model_->alpha());
          assert(norm);
          // pivot element
          alpha = 0.0;
          double multiplier = 2.0 / model_->alpha();
          // look at updated column
          work = updatedColumn->denseVector();
          numberNonZero = updatedColumn->getNumElements();
          which = updatedColumn->getIndices();

          int nSave = 0;
          double * work3 = alternateWeights_->denseVector();
          int * which3 = alternateWeights_->getIndices();
          const int * pivotColumn = model_->factorization()->pivotColumn();
          for (i = 0; i < numberNonZero; i++) {
               int iRow = which[i];
               double theta = work[i];
               if (iRow == pivotRow)
                    alpha = theta;
               double devex = weights_[iRow];
               work3[nSave] = devex; // save old
               which3[nSave++] = iRow;
               // transform to match spare
               int jRow = permute ? pivotColumn[iRow] : iRow;
               double value = work2[jRow];
               devex +=  theta * (theta * norm + value * multiplier);
               if (devex < DEVEX_TRY_NORM)
                    devex = DEVEX_TRY_NORM;
               weights_[iRow] = devex;
          }
          alternateWeights_->setPackedMode(true);
          alternateWeights_->setNumElements(nSave);
          if (norm < DEVEX_TRY_NORM)
               norm = DEVEX_TRY_NORM;
          // Try this to make less likely will happen again and stop cycling
          //norm *= 1.02;
          weights_[pivotRow] = norm;
          spare->clear();
#ifdef CLP_DEBUG
          spare->checkClear();
#endif
     } else {
          // Do FT update
          model_->factorization()->updateColumnFT(spare, updatedColumn);
          // clear other region
          alternateWeights_->clear();
          double norm = 0.0;
          int i;
          double * work = input->denseVector();
          int number = input->getNumElements();
          int * which = input->getIndices();
          double * work2 = spare->denseVector();
          int * which2 = spare->getIndices();
          for (i = 0; i < number; i++) {
               int iRow = which[i];
               double value = work[i];
               norm += value * value;
               work2[iRow] = value;
               which2[i] = iRow;
          }
          spare->setNumElements(number);
          // ftran
#ifndef NDEBUG
          alternateWeights_->checkClear();
#endif
          model_->factorization()->updateColumn(alternateWeights_, spare);
          // alternateWeights_ should still be empty
#ifndef NDEBUG
          alternateWeights_->checkClear();
#endif
          int pivotRow = model_->pivotRow();
#ifdef CLP_DEBUG
          if ( model_->logLevel (  ) > 4  &&
                    fabs(norm - weights_[pivotRow]) > 1.0e-3 * (1.0 + norm))
               printf("on row %d, true weight %g, old %g\n",
                      pivotRow, sqrt(norm), sqrt(weights_[pivotRow]));
#endif
          // could re-initialize here (could be expensive)
          norm /= model_->alpha() * model_->alpha();

          assert(norm);
          //if (norm < DEVEX_TRY_NORM)
          //norm = DEVEX_TRY_NORM;
          // pivot element
          alpha = 0.0;
          double multiplier = 2.0 / model_->alpha();
          // look at updated column
          work = updatedColumn->denseVector();
          number = updatedColumn->getNumElements();
          which = updatedColumn->getIndices();

          int nSave = 0;
          double * work3 = alternateWeights_->denseVector();
          int * which3 = alternateWeights_->getIndices();
          for (i = 0; i < number; i++) {
               int iRow = which[i];
               double theta = work[i];
               if (iRow == pivotRow)
                    alpha = theta;
               double devex = weights_[iRow];
               work3[nSave] = devex; // save old
               which3[nSave++] = iRow;
               double value = work2[iRow];
               devex +=  theta * (theta * norm + value * multiplier);
               if (devex < DEVEX_TRY_NORM)
                    devex = DEVEX_TRY_NORM;
               weights_[iRow] = devex;
          }
          if (!alpha) {
               // error - but carry on
               alpha = 1.0e-50;
          }
          alternateWeights_->setPackedMode(true);
          alternateWeights_->setNumElements(nSave);
          if (norm < DEVEX_TRY_NORM)
               norm = DEVEX_TRY_NORM;
          weights_[pivotRow] = norm;
          spare->clear();
     }
#ifdef CLP_DEBUG
     spare->checkClear();
#endif
     return alpha;
}
예제 #6
0
void CglGMI::generateCuts(OsiCuts &cs)
{
  isInteger = new bool[ncol]; 
  
  computeIsInteger();

  cstat = new int[ncol];
  rstat = new int[nrow];


  solver->getBasisStatus(cstat, rstat);   // 0: free  1: basic  
                                          // 2: upper 3: lower


#if defined GMI_TRACETAB
  printvecINT("cstat", cstat, ncol);
  printvecINT("rstat", rstat, nrow);
#endif

  // list of basic integer fractional variables
  int *listFracBasic = new int[nrow];
  int numFracBasic = 0;
  for (int i = 0; i < ncol; ++i) {
    // j is the variable which is basic in row i
    if ((cstat[i] == 1) && (isInteger[i])) {
      if (CoinMin(aboveInteger(xlp[i]),
		  1-aboveInteger(xlp[i])) > param.getAway()) {
	listFracBasic[numFracBasic] = i;
	numFracBasic++;
      }
#if defined TRACK_REJECT || defined TRACK_REJECT_SIMPLE
      else if (trackRejection) {	
	// Say that we tried to generate a cut, but it was discarded
	// because of small fractionality
	if (!isIntegerValue(xlp[i])) {
	  fracFail++;
	  numGeneratedCuts++;
	}
      }
#endif
    }
  }

#if defined GMI_TRACE
  printf("CglGMI::generateCuts() : %d fractional rows\n", numFracBasic);
#endif
  
  if (numFracBasic == 0) {
    delete[] listFracBasic;
    delete[] cstat;
    delete[] rstat;
    delete[] isInteger;
    return;
  }

  // there are rows with basic integer fractional variables, so we can
  // generate cuts

  // Basis index for columns and rows; each element is -1 if corresponding
  // variable is nonbasic, and contains the basis index if basic.
  // The basis index is the row in which the variable is basic.
  int* colBasisIndex = new int[ncol];
  int* rowBasisIndex = new int[nrow];

#if defined OSI_TABLEAU
  memset(colBasisIndex, -1, ncol*sizeof(int));
  memset(rowBasisIndex, -1, nrow*sizeof(int));
  solver->enableFactorization();
  int* basicVars = new int[nrow];
  solver->getBasics(basicVars);
  for (int i = 0; i < nrow; ++i) {
    if (basicVars[i] < ncol) {
      colBasisIndex[basicVars[i]] = i;
    }
    else {
      rowBasisIndex[basicVars[i] - ncol] = i;
    }
  }
#else
  CoinFactorization factorization;
  if (factorize(factorization, colBasisIndex, rowBasisIndex)) {
    printf("### WARNING: CglGMI::generateCuts(): error during factorization!\n");
    return;
  }
#endif


  // cut in sparse form
  double* cutElem = new double[ncol];
  int* cutIndex = new int[ncol];
  int cutNz = 0;
  double cutRhs;

  // cut in dense form
  double* cut = new double[ncol];

  double *slackVal = new double[nrow];

  for (int i = 0; i < nrow; ++i) {
    slackVal[i] = rowRhs[i] - rowActivity[i];
  }

#if defined OSI_TABLEAU
  // Column part and row part of a row of the simplex tableau
  double* tableauColPart = new double[ncol];
  double* tableauRowPart = new double[nrow];
#else
  // Need some more data for simplex tableau computation
  const int * row = byCol->getIndices();
  const CoinBigIndex * columnStart = byCol->getVectorStarts();
  const int * columnLength = byCol->getVectorLengths(); 
  const double * columnElements = byCol->getElements();

  // Create work arrays for factorization
  // two vectors for updating: the first one is needed to do the computations
  // but we do not use it, the second one contains a row of the basis inverse
  CoinIndexedVector work;
  CoinIndexedVector array;
  // Make sure they large enough
  work.reserve(nrow);
  array.reserve(nrow);
  int * arrayRows = array.getIndices();
  double * arrayElements = array.denseVector();
  // End of code to create work arrays
  double one = 1.0;
#endif

  // Matrix elements by row for slack substitution
  const double *elements = byRow->getElements();
  const int *rowStart = byRow->getVectorStarts();
  const int *indices = byRow->getIndices();
  const int *rowLength = byRow->getVectorLengths(); 

  // Indices of basic and slack variables, and cut elements
  int iBasic, slackIndex;
  double cutCoeff;
  double rowElem;
  // Now generate the cuts: obtain a row of the simplex tableau
  // where an integer variable is basic and fractional, and compute the cut
  for (int i = 0; i < numFracBasic; ++i) {
    if (!computeCutFractionality(xlp[listFracBasic[i]], cutRhs)) {
      // cut is discarded because of the small fractionalities involved
#if defined TRACK_REJECT || defined TRACK_REJECT_SIMPLE
      if (trackRejection) {	
	// Say that we tried to generate a cut, but it was discarded
	// because of small fractionality
	fracFail++;
	numGeneratedCuts++;
      }
#endif
      continue;
    }

    // the variable listFracBasic[i] is basic in row iBasic
    iBasic = colBasisIndex[listFracBasic[i]];

#if defined GMI_TRACE
    printf("Row %d with var %d basic, f0 = %f\n", i, listFracBasic[i], f0);
#endif

#if defined OSI_TABLEAU
    solver->getBInvARow(iBasic, tableauColPart, tableauRowPart);
#else
    array.clear();
    array.setVector(1, &iBasic, &one);

    factorization.updateColumnTranspose (&work, &array);

    int numberInArray=array.getNumElements();
#endif

    // reset the cut
    memset(cut, 0, ncol*sizeof(double));

    // columns
    for (int j = 0; j < ncol; ++j) {
      if ((colBasisIndex[j] >= 0) || 
	  (areEqual(colLower[j], colUpper[j], 
		    param.getEPS(), param.getEPS()))) {
	// Basic or fixed variable -- skip
	continue;
      }
#ifdef OSI_TABLEAU
      rowElem = tableauColPart[j];
#else
      rowElem = 0.0;
      // add in row of tableau
      for (int h = columnStart[j]; h < columnStart[j]+columnLength[j]; ++h) {
	rowElem += columnElements[h]*arrayElements[row[h]];
      }
#endif
      if (!isZero(fabs(rowElem))) {
	// compute cut coefficient
	flip(rowElem, j);
	cutCoeff = computeCutCoefficient(rowElem, j);
	if (isZero(cutCoeff)) {
	  continue;
	}
	unflipOrig(cutCoeff, j, cutRhs);
	cut[j] = cutCoeff;
#if defined GMI_TRACE
	printf("var %d, row %f, cut %f\n", j, rowElem, cutCoeff);
#endif
      }
    }

    // now do slacks part
#if defined OSI_TABLEAU
    for (int j = 0 ; j < nrow; ++j) {
      // index of the row corresponding to the slack variable
      slackIndex = j;
      if (rowBasisIndex[j] >= 0) {
	// Basic variable -- skip it
	continue;
      }
      rowElem = tableauRowPart[j];
#else
    for (int j = 0 ; j < numberInArray ; ++j) {
      // index of the row corresponding to the slack variable
      slackIndex = arrayRows[j];
      rowElem = arrayElements[slackIndex];
#endif
      if (!isZero(fabs(rowElem))) {
	slackIndex += ncol;
	// compute cut coefficient
	flip(rowElem, slackIndex);
	cutCoeff = computeCutCoefficient(rowElem, slackIndex);
	if (isZero(fabs(cutCoeff))) {
	  continue;
	}
	unflipSlack(cutCoeff, slackIndex, cutRhs, slackVal);
	eliminateSlack(cutCoeff, slackIndex, cut, cutRhs,
		       elements, rowStart, indices, rowLength, rowRhs);
#if defined GMI_TRACE
	printf("var %d, row %f, cut %f\n", slackIndex, rowElem, cutCoeff);
#endif
      }
    }

    packRow(cut, cutElem, cutIndex, cutNz);
    if (cutNz == 0)
      continue;

#if defined GMI_TRACE
    printvecDBL("final cut:", cutElem, cutIndex, cutNz);
    printf("cutRhs: %f\n", cutRhs);
#endif
    
#if defined TRACK_REJECT || defined TRACK_REJECT_SIMPLE
    if (trackRejection) {
      numGeneratedCuts++;
    }
#endif
    if (cleanCut(cutElem, cutIndex, cutNz, cutRhs, xlp) && cutNz > 0) {
      OsiRowCut rc;
      rc.setRow(cutNz, cutIndex, cutElem);
      rc.setLb(-param.getINFINIT());
      rc.setUb(cutRhs);
      if (!param.getCHECK_DUPLICATES()) {
	cs.insert(rc);
      }
      else{
	cs.insertIfNotDuplicate(rc, CoinAbsFltEq(param.getEPS_COEFF()));
      }
    }

  }

#if defined GMI_TRACE
  printf("CglGMI::generateCuts() : number of cuts : %d\n", cs.sizeRowCuts());
#endif

#if defined OSI_TABLEAU
  solver->disableFactorization();
  delete[] basicVars;
  delete[] tableauColPart;
  delete[] tableauRowPart;
#endif

  delete[] colBasisIndex;
  delete[] rowBasisIndex;
  delete[] cut;
  delete[] slackVal;
  delete[] cutElem;
  delete[] cutIndex;
  delete[] listFracBasic;
  delete[] cstat;
  delete[] rstat;
  delete[] isInteger;

} /* generateCuts */

/***********************************************************************/
void CglGMI::setParam(const CglGMIParam &source) {
  param = source;
} /* setParam */

/***********************************************************************/
void CglGMI::computeIsInteger() {
  for (int i = 0; i < ncol; ++i) {
    if(solver->isInteger(i)) {
      isInteger[i] = true;
    }
    else {
      if((areEqual(colLower[i], colUpper[i], 
		   param.getEPS(), param.getEPS()))
	 && (isIntegerValue(colUpper[i]))) {	
	// continuous variable fixed to an integer value
	isInteger[i] = true;
      }
      else {
	isInteger[i] = false;
      }
    }
  }    
} /* computeIsInteger */

/***********************************************************************/
void CglGMI::printOptTab(OsiSolverInterface *lclSolver) const
{
  int *cstat = new int[ncol];
  int *rstat = new int[nrow];

  lclSolver->enableFactorization();
  lclSolver->getBasisStatus(cstat, rstat);   // 0: free  1: basic  
  // 2: upper 3: lower

  int *basisIndex = new int[nrow]; // basisIndex[i] = 
                                    //        index of pivot var in row i
                                    //        (slack if number >= ncol) 
  lclSolver->getBasics(basisIndex);

  double *z = new double[ncol];  // workspace to get row of the tableau
  double *slack = new double[nrow];  // workspace to get row of the tableau
  double *slackVal = new double[nrow];

  for (int i = 0; i < nrow; i++) {
    slackVal[i] = rowRhs[i] - rowActivity[i];
  }

  const double *rc = lclSolver->getReducedCost();
  const double *dual = lclSolver->getRowPrice();
  const double *solution = lclSolver->getColSolution();

  printvecINT("cstat", cstat, ncol);
  printvecINT("rstat", rstat, nrow);
  printvecINT("basisIndex", basisIndex, nrow);

  printvecDBL("solution", solution, ncol);
  printvecDBL("slackVal", slackVal, nrow);
  printvecDBL("reduced_costs", rc, ncol);
  printvecDBL("dual solution", dual, nrow);

  printf("Optimal Tableau:\n");

  for (int i = 0; i < nrow; i++) {
    lclSolver->getBInvARow(i, z, slack);
    for (int ii = 0; ii < ncol; ++ii) {
      printf("%5.2f ", z[ii]);
    }
    printf(" | ");
    for (int ii = 0; ii < nrow; ++ii) {
      printf("%5.2f ", slack[ii]);
    }
    printf(" | ");
    if(basisIndex[i] < ncol) {
      printf("%5.2f ", solution[basisIndex[i]]);
    }
    else {
      printf("%5.2f ", slackVal[basisIndex[i]-ncol]);
    }
    printf("\n");
  }
  for (int ii = 0; ii < 7*(ncol+nrow+1); ++ii) {
    printf("-");
  }
  printf("\n");

  for (int ii = 0; ii < ncol; ++ii) {
    printf("%5.2f ", rc[ii]);    
  }
  printf(" | ");
  for (int ii = 0; ii < nrow; ++ii) {
    printf("%5.2f ", -dual[ii]);
  }
  printf(" | ");
  printf("%5.2f\n", -lclSolver->getObjValue());
  lclSolver->disableFactorization();

  delete[] cstat;
  delete[] rstat;
  delete[] basisIndex;
  delete[] slack;
  delete[] z;
  delete[] slackVal;
} /* printOptTab */