//------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpCholeskyTaucs::ClpCholeskyTaucs (const ClpCholeskyTaucs & rhs) : ClpCholeskyBase(rhs) { type_ = rhs.type_; // For Taucs stuff is done by malloc matrix_ = rhs.matrix_; sizeFactorT_ = rhs.sizeFactorT_; if (matrix_) { choleskyStartT_ = (int *) malloc((numberRows_ + 1) * sizeof(int)); CoinMemcpyN(rhs.choleskyStartT_, (numberRows_ + 1), choleskyStartT_); choleskyRowT_ = (int *) malloc(sizeFactorT_ * sizeof(int)); CoinMemcpyN(rhs.choleskyRowT_, sizeFactorT_, choleskyRowT_); sparseFactorT_ = (double *) malloc(sizeFactorT_ * sizeof(double)); CoinMemcpyN(rhs.sparseFactorT_, sizeFactorT_, sparseFactorT_); matrix_->colptr = choleskyStartT_; matrix_->rowind = choleskyRowT_; matrix_->values.d = sparseFactorT_; } else { sparseFactorT_ = NULL; choleskyStartT_ = NULL; choleskyRowT_ = NULL; } factorization_ = NULL, rowCopyT_ = rhs.rowCopyT_->clone(); }
void CoinWarmStartBasis::assignBasisStatus(int ns, int na, char*& sStat, char*& aStat) { // Round all so arrays multiple of 4 int nintS = (ns+15) >> 4; int nintA = (na+15) >> 4; int size = nintS+nintA; if (size) { if (size>maxSize_) { delete[] structuralStatus_; maxSize_ = size+10; structuralStatus_ = new char[4*maxSize_]; } CoinMemcpyN( sStat,(4*nintS), structuralStatus_); artificialStatus_ = structuralStatus_+4*nintS; CoinMemcpyN( aStat,(4*nintA), artificialStatus_); } else { artificialStatus_ = NULL; } numStructural_ = ns; numArtificial_ = na; delete [] sStat; delete [] aStat; sStat = NULL; aStat = NULL; }
//---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpCholeskyTaucs & ClpCholeskyTaucs::operator=(const ClpCholeskyTaucs& rhs) { if (this != &rhs) { ClpCholeskyBase::operator=(rhs); taucs_ccs_free(matrix_); if (factorization_) taucs_supernodal_factor_free(factorization_); factorization_ = NULL; sizeFactorT_ = rhs.sizeFactorT_; matrix_ = rhs.matrix_; if (matrix_) { choleskyStartT_ = (int *) malloc((numberRows_ + 1) * sizeof(int)); CoinMemcpyN(rhs.choleskyStartT_, (numberRows_ + 1), choleskyStartT_); choleskyRowT_ = (int *) malloc(sizeFactorT_ * sizeof(int)); CoinMemcpyN(rhs.choleskyRowT_, sizeFactorT_, choleskyRowT_); sparseFactorT_ = (double *) malloc(sizeFactorT_ * sizeof(double)); CoinMemcpyN(rhs.sparseFactorT_, sizeFactorT_, sparseFactorT_); matrix_->colptr = choleskyStartT_; matrix_->rowind = choleskyRowT_; matrix_->values.d = sparseFactorT_; } else { sparseFactorT_ = NULL; choleskyStartT_ = NULL; choleskyRowT_ = NULL; } delete rowCopyT_; rowCopyT_ = rhs.rowCopyT_->clone(); } return *this; }
// Load up quadratic objective void ClpQuadraticObjective::loadQuadraticObjective(const int numberColumns, const CoinBigIndex *start, const int *column, const double *element, int numberExtended) { fullMatrix_ = false; delete quadraticObjective_; quadraticObjective_ = new CoinPackedMatrix(true, numberColumns, numberColumns, start[numberColumns], element, column, start, NULL); numberColumns_ = numberColumns; if (numberExtended > numberExtendedColumns_) { if (objective_) { // make correct size double *newArray = new double[numberExtended]; CoinMemcpyN(objective_, numberColumns_, newArray); delete[] objective_; objective_ = newArray; memset(objective_ + numberColumns_, 0, (numberExtended - numberColumns_) * sizeof(double)); } if (gradient_) { // make correct size double *newArray = new double[numberExtended]; CoinMemcpyN(gradient_, numberColumns_, newArray); delete[] gradient_; gradient_ = newArray; memset(gradient_ + numberColumns_, 0, (numberExtended - numberColumns_) * sizeof(double)); } numberExtendedColumns_ = numberExtended; } else { numberExtendedColumns_ = numberColumns_; } }
CoinWarmStartBasis::CoinWarmStartBasis(int ns, int na, const char* sStat, const char* aStat) : numStructural_(ns), numArtificial_(na), structuralStatus_(NULL), artificialStatus_(NULL) { // Round all so arrays multiple of 4 int nintS = ((ns+15) >> 4); int nintA = ((na+15) >> 4); maxSize_ = nintS+nintA; if (maxSize_ > 0) { structuralStatus_ = new char[4*maxSize_]; if (nintS>0) { structuralStatus_[4*nintS-3]=0; structuralStatus_[4*nintS-2]=0; structuralStatus_[4*nintS-1]=0; CoinMemcpyN( sStat,((ns+3)/4), structuralStatus_); } artificialStatus_ = structuralStatus_+4*nintS; if (nintA > 0) { artificialStatus_[4*nintA-3]=0; artificialStatus_[4*nintA-2]=0; artificialStatus_[4*nintA-1]=0; CoinMemcpyN( aStat,((na+3)/4), artificialStatus_); } } }
//---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpQuadraticObjective & ClpQuadraticObjective::operator=(const ClpQuadraticObjective &rhs) { if (this != &rhs) { fullMatrix_ = rhs.fullMatrix_; delete quadraticObjective_; quadraticObjective_ = NULL; delete[] objective_; delete[] gradient_; ClpObjective::operator=(rhs); numberColumns_ = rhs.numberColumns_; numberExtendedColumns_ = rhs.numberExtendedColumns_; if (rhs.objective_) { objective_ = new double[numberExtendedColumns_]; CoinMemcpyN(rhs.objective_, numberExtendedColumns_, objective_); } else { objective_ = NULL; } if (rhs.gradient_) { gradient_ = new double[numberExtendedColumns_]; CoinMemcpyN(rhs.gradient_, numberExtendedColumns_, gradient_); } else { gradient_ = NULL; } if (rhs.quadraticObjective_) { quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_); } else { quadraticObjective_ = NULL; } } return *this; }
/* Uses factorization to solve. */ void ClpCholeskyUfl::solve (double * region) { cholmod_dense *x, *b; b = cholmod_allocate_dense (numberRows_, 1, numberRows_, CHOLMOD_REAL, c_) ; CoinMemcpyN(region, numberRows_, (double *) b->x); x = cholmod_solve (CHOLMOD_A, L_, b, c_) ; CoinMemcpyN((double *) x->x, numberRows_, region); cholmod_free_dense (&x, c_) ; cholmod_free_dense (&b, c_) ; }
/* Uses factorization to solve. */ void ClpCholeskyWssmpKKT::solveKKT (double * region1, double * region2, const double * diagonal, double diagonalScaleFactor) { int numberRowsModel = model_->numberRows(); int numberColumns = model_->numberColumns(); int numberTotal = numberColumns + numberRowsModel; double * array = new double [numberRows_]; CoinMemcpyN(region1, numberTotal, array); CoinMemcpyN(region2, numberRowsModel, array + numberTotal); int i1 = 1; int i0 = 0; integerParameters_[1] = 4; integerParameters_[2] = 4; #if 0 integerParameters_[5] = 3; doubleParameters_[5] = 1.0e-10; integerParameters_[6] = 6; #endif F77_FUNC(wssmp,WSSMP)(&numberRows_, choleskyStart_, choleskyRow_, sparseFactor_, NULL, permute_, permuteInverse_, array, &numberRows_, &i1, NULL, &i0, NULL, integerParameters_, doubleParameters_); #if 0 int iRow; for (iRow = 0; iRow < numberTotal; iRow++) { if (rowsDropped_[iRow] && fabs(array[iRow]) > 1.0e-8) { printf("row region1 %d dropped %g\n", iRow, array[iRow]); } } for (; iRow < numberRows_; iRow++) { if (rowsDropped_[iRow] && fabs(array[iRow]) > 1.0e-8) { printf("row region2 %d dropped %g\n", iRow, array[iRow]); } } #endif CoinMemcpyN(array + numberTotal, numberRowsModel, region2); #if 1 CoinMemcpyN(array, numberTotal, region1); #else multiplyAdd(region2, numberRowsModel, -1.0, array + numberColumns, 0.0); CoinZeroN(array, numberColumns); model_->clpMatrix()->transposeTimes(1.0, region2, array); for (int iColumn = 0; iColumn < numberTotal; iColumn++) region1[iColumn] = diagonal[iColumn] * (array[iColumn] - region1[iColumn]); #endif delete [] array; #if 0 if (integerParameters_[5]) { std::cout << integerParameters_[5] << " refinements "; } std::cout << doubleParameters_[6] << std::endl; #endif }
CoinWarmStartBasis::CoinWarmStartBasis(const CoinWarmStartBasis& ws) : numStructural_(ws.numStructural_), numArtificial_(ws.numArtificial_), structuralStatus_(NULL), artificialStatus_(NULL) { // Round all so arrays multiple of 4 int nintS = (numStructural_+15) >> 4; int nintA = (numArtificial_+15) >> 4; maxSize_ = nintS+nintA; if (maxSize_ > 0) { structuralStatus_ = new char[4*maxSize_]; CoinMemcpyN( ws.structuralStatus_, (4*nintS), structuralStatus_); artificialStatus_ = structuralStatus_+4*nintS; CoinMemcpyN( ws.artificialStatus_, (4*nintA), artificialStatus_); } }
//------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpQuadraticObjective::ClpQuadraticObjective(const double *objective, int numberColumns, const CoinBigIndex *start, const int *column, const double *element, int numberExtendedColumns) : ClpObjective() { type_ = 2; numberColumns_ = numberColumns; if (numberExtendedColumns >= 0) numberExtendedColumns_ = CoinMax(numberColumns_, numberExtendedColumns); else numberExtendedColumns_ = numberColumns_; if (objective) { objective_ = new double[numberExtendedColumns_]; CoinMemcpyN(objective, numberColumns_, objective_); memset(objective_ + numberColumns_, 0, (numberExtendedColumns_ - numberColumns_) * sizeof(double)); } else { objective_ = new double[numberExtendedColumns_]; memset(objective_, 0, numberExtendedColumns_ * sizeof(double)); } if (start) quadraticObjective_ = new CoinPackedMatrix(true, numberColumns, numberColumns, start[numberColumns], element, column, start, NULL); else quadraticObjective_ = NULL; gradient_ = NULL; activated_ = 1; fullMatrix_ = false; }
virtual int read (void *buffer, int size) override { if (size <= 0) return 0; // return value int r = 0; // treat destination as char * char *dest = static_cast<char *>(buffer); // First consume data from buffer if available. if (dataStart_ < dataEnd_) { int amount = static_cast<int>(dataEnd_ - dataStart_); if (amount > size) amount = size; CoinMemcpyN( dataStart_, amount, dest); dest += amount; size -= amount; dataStart_ += amount; r = amount; } // If we require more data, use readRaw. // We don't use the buffer here, as readRaw is ecpected to be efficient. if (size > 0) r += readRaw (dest, size); return r; }
char* CoinMempool::alloc() { lock_mutex(); if (first_free_ == NULL) { unlock_mutex(); char* block = allocate_new_block(); lock_mutex(); #if (COIN_MEMPOOL_SAVE_BLOCKHEADS==1) // see if we can record another block head. If not, then resize // block_heads if (max_block_num_ == block_num_) { max_block_num_ = 2 * block_num_ + 10; char** old_block_heads = block_heads_; block_heads_ = (char**)malloc(max_block_num_ * sizeof(char*)); CoinMemcpyN( old_block_heads,block_num_,block_heads_); free(old_block_heads); } // save the new block block_heads_[block_num_++] = block; #endif // link in the new block *(char**)(block+((last_block_size_-1)*entry_size_)) = first_free_; first_free_ = block; } char* p = first_free_; first_free_ = *(char**)p; unlock_mutex(); return p; }
// For debug check vector is clean i.e. elements match indices void CoinIndexedVector::checkClean() { int i; if (packedMode_) { for (i=0; i<nElements_; i++) assert(elements_[i]); for (; i<capacity_; i++) assert(!elements_[i]); } else { double * copy = new double[capacity_]; CoinMemcpyN(elements_,capacity_,copy); for (i=0; i<nElements_; i++) { int indexValue = indices_[i]; copy[indexValue]=0.0; } for (i=0; i<capacity_; i++) assert(!copy[i]); delete [] copy; } #ifndef NDEBUG // check mark array zeroed char * mark = reinterpret_cast<char *> (indices_+capacity_); for (i=0; i<capacity_; i++) { assert(!mark[i]); } #endif }
/* Subset constructor. Duplicates are allowed and order is as given. */ ClpQuadraticObjective::ClpQuadraticObjective(const ClpQuadraticObjective &rhs, int numberColumns, const int *whichColumn) : ClpObjective(rhs) { fullMatrix_ = rhs.fullMatrix_; objective_ = NULL; int extra = rhs.numberExtendedColumns_ - rhs.numberColumns_; numberColumns_ = 0; numberExtendedColumns_ = numberColumns + extra; if (numberColumns > 0) { // check valid lists int numberBad = 0; int i; for (i = 0; i < numberColumns; i++) if (whichColumn[i] < 0 || whichColumn[i] >= rhs.numberColumns_) numberBad++; if (numberBad) throw CoinError("bad column list", "subset constructor", "ClpQuadraticObjective"); numberColumns_ = numberColumns; objective_ = new double[numberExtendedColumns_]; for (i = 0; i < numberColumns_; i++) objective_[i] = rhs.objective_[whichColumn[i]]; CoinMemcpyN(rhs.objective_ + rhs.numberColumns_, (numberExtendedColumns_ - numberColumns_), objective_ + numberColumns_); if (rhs.gradient_) { gradient_ = new double[numberExtendedColumns_]; for (i = 0; i < numberColumns_; i++) gradient_[i] = rhs.gradient_[whichColumn[i]]; CoinMemcpyN(rhs.gradient_ + rhs.numberColumns_, (numberExtendedColumns_ - numberColumns_), gradient_ + numberColumns_); } else { gradient_ = NULL; } } else { gradient_ = NULL; objective_ = NULL; } if (rhs.quadraticObjective_) { quadraticObjective_ = new CoinPackedMatrix(*rhs.quadraticObjective_, numberColumns, whichColumn, numberColumns, whichColumn); } else { quadraticObjective_ = NULL; } }
const CoinPresolveAction *drop_zero_coefficients_action::presolve (CoinPresolveMatrix *prob, int *checkcols, int ncheckcols, const CoinPresolveAction *next) { double *colels = prob->colels_; int *hrow = prob->hrow_; CoinBigIndex *mcstrt = prob->mcstrt_; int *hincol = prob->hincol_; presolvehlink *clink = prob->clink_ ; presolvehlink *rlink = prob->rlink_ ; // int i; int nzeros; if (ncheckcols==prob->ncols_) { // can do faster nzeros = count_col_zeros2(ncheckcols,checkcols, mcstrt,colels,/*hrow,*/hincol); } else { nzeros = count_col_zeros(ncheckcols,checkcols, mcstrt,colels,/*hrow,*/hincol); } if (nzeros == 0) { return (next); } else { dropped_zero * zeros = new dropped_zero[nzeros]; nzeros=drop_col_zeros((ncheckcols==prob->ncols_) ? nzeros : ncheckcols, checkcols, mcstrt,colels,hrow,hincol,clink, zeros); double *rowels = prob->rowels_; int *hcol = prob->hcol_; CoinBigIndex *mrstrt = prob->mrstrt_; int *hinrow = prob->hinrow_; // int nrows = prob->nrows_; # if PRESOLVE_SUMMARY printf("NZEROS: %d\n", nzeros); # endif // make the row rep consistent drop_row_zeros(nzeros,zeros,mrstrt,rowels,hcol,hinrow,rlink) ; dropped_zero *zeros1 = new dropped_zero[nzeros]; CoinMemcpyN(zeros, nzeros, zeros1); delete [] zeros; return (new drop_zero_coefficients_action(nzeros, zeros1, next)); } }
// Resize objective void ClpQuadraticObjective::resize(int newNumberColumns) { if (numberColumns_ != newNumberColumns) { int newExtended = newNumberColumns + (numberExtendedColumns_ - numberColumns_); int i; double *newArray = new double[newExtended]; if (objective_) CoinMemcpyN(objective_, CoinMin(newExtended, numberExtendedColumns_), newArray); delete[] objective_; objective_ = newArray; for (i = numberColumns_; i < newNumberColumns; i++) objective_[i] = 0.0; if (gradient_) { newArray = new double[newExtended]; if (gradient_) CoinMemcpyN(gradient_, CoinMin(newExtended, numberExtendedColumns_), newArray); delete[] gradient_; gradient_ = newArray; for (i = numberColumns_; i < newNumberColumns; i++) gradient_[i] = 0.0; } if (quadraticObjective_) { if (newNumberColumns < numberColumns_) { int *which = new int[numberColumns_ - newNumberColumns]; int i; for (i = newNumberColumns; i < numberColumns_; i++) which[i - newNumberColumns] = i; quadraticObjective_->deleteRows(numberColumns_ - newNumberColumns, which); quadraticObjective_->deleteCols(numberColumns_ - newNumberColumns, which); delete[] which; } else { quadraticObjective_->setDimensions(newNumberColumns, newNumberColumns); } } numberColumns_ = newNumberColumns; numberExtendedColumns_ = newExtended; } }
CoinWarmStartBasis& CoinWarmStartBasis::operator=(const CoinWarmStartBasis& rhs) { if (this != &rhs) { numStructural_=rhs.numStructural_; numArtificial_=rhs.numArtificial_; // Round all so arrays multiple of 4 int nintS = (numStructural_+15) >> 4; int nintA = (numArtificial_+15) >> 4; int size = nintS+nintA; if (size>maxSize_) { delete[] structuralStatus_; maxSize_ = size+10; structuralStatus_ = new char[4*maxSize_]; } if (size > 0) { CoinMemcpyN( rhs.structuralStatus_, (4*nintS), structuralStatus_); artificialStatus_ = structuralStatus_+4*nintS; CoinMemcpyN( rhs.artificialStatus_, (4*nintA), artificialStatus_); } else { artificialStatus_ = NULL; } }
template <typename T> void CoinDenseVector<T>::resize(int newsize, T value) { if (newsize != nElements_){ assert(newsize > 0); T *newarray = new T[newsize]; int cpysize = CoinMin(newsize, nElements_); CoinMemcpyN( elements_,cpysize,newarray); delete[] elements_; elements_ = newarray; nElements_ = newsize; for(int i=cpysize; i<newsize; i++) elements_[i] = value; } }
// Resize objective void ClpLinearObjective::resize(int newNumberColumns) { if (numberColumns_ != newNumberColumns) { int i; double * newArray = new double[newNumberColumns]; if (objective_) CoinMemcpyN(objective_, CoinMin(newNumberColumns, numberColumns_), newArray); delete [] objective_; objective_ = newArray; for (i = numberColumns_; i < newNumberColumns; i++) objective_[i] = 0.0; numberColumns_ = newNumberColumns; } }
// Returns gradient int ClpConstraintLinear::gradient(const ClpSimplex * model, const double * solution, double * gradient, double & functionValue, double & offset, bool useScaling, bool refresh) const { if (refresh || !lastGradient_) { functionValue_ = 0.0; if (!lastGradient_) lastGradient_ = new double[numberColumns_]; CoinZeroN(lastGradient_, numberColumns_); bool scaling = (model && model->rowScale() && useScaling); if (!scaling) { for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; double value = solution[iColumn]; double coefficient = coefficient_[i]; functionValue_ += value * coefficient; lastGradient_[iColumn] = coefficient; } } else { // do scaling const double * columnScale = model->columnScale(); for (int i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; double value = solution[iColumn]; // already scaled double coefficient = coefficient_[i] * columnScale[iColumn]; functionValue_ += value * coefficient; lastGradient_[iColumn] = coefficient; } } } functionValue = functionValue_; offset = 0.0; CoinMemcpyN(lastGradient_, numberColumns_, gradient); return 0; }
void CoinPresolveMatrix::setMatrix (const CoinPackedMatrix *mtx) { /* Check to make sure the matrix will fit and is column ordered. */ if (mtx->isColOrdered() == false) { throw CoinError("source matrix must be column ordered", "setMatrix","CoinPrePostsolveMatrix") ; } int numCols = mtx->getNumCols() ; if (numCols > ncols0_) { throw CoinError("source matrix exceeds allocated capacity", "setMatrix","CoinPrePostsolveMatrix") ; } /* Acquire the actual size, but allocate the matrix storage to the requested capacity. The column-major rep is part of the PrePostsolve object, the row-major rep belongs to the Presolve object. */ ncols_ = numCols ; nrows_ = mtx->getNumRows() ; nelems_ = mtx->getNumElements() ; bulk0_ = static_cast<CoinBigIndex> (bulkRatio_*nelems0_) ; if (mcstrt_ == 0) mcstrt_ = new CoinBigIndex [ncols0_+1] ; if (hincol_ == 0) hincol_ = new int [ncols0_+1] ; if (hrow_ == 0) hrow_ = new int [bulk0_] ; if (colels_ == 0) colels_ = new double [bulk0_] ; if (mrstrt_ == 0) mrstrt_ = new CoinBigIndex [nrows0_+1] ; if (hinrow_ == 0) hinrow_ = new int [nrows0_+1] ; if (hcol_ == 0) hcol_ = new int [bulk0_] ; if (rowels_ == 0) rowels_ = new double [bulk0_] ; /* Grab the corresponding vectors from the source matrix. */ const CoinBigIndex *src_mcstrt = mtx->getVectorStarts() ; const int *src_hincol = mtx->getVectorLengths() ; const double *src_colels = mtx->getElements() ; const int *src_hrow = mtx->getIndices() ; /* Bulk copy the column starts and lengths. */ CoinMemcpyN(src_mcstrt,mtx->getSizeVectorStarts(),mcstrt_) ; CoinMemcpyN(src_hincol,mtx->getSizeVectorLengths(),hincol_) ; /* Copy the coefficients column by column in case there are gaps between the columns in the bulk storage area. The assert is just in case the gaps are *really* big. */ assert(src_mcstrt[ncols_] <= bulk0_) ; int j; for ( j = 0 ; j < numCols ; j++) { int lenj = src_hincol[j] ; CoinBigIndex offset = mcstrt_[j] ; CoinMemcpyN(src_colels+offset,lenj,colels_+offset) ; CoinMemcpyN(src_hrow+offset,lenj,hrow_+offset) ; } /* Now make a row-major copy. Start by counting the number of coefficients in each row; we can do this directly in hinrow. Given the number of coefficients in a row, we know how to lay out the bulk storage area. */ CoinZeroN(hinrow_,nrows0_+1) ; for ( j = 0 ; j < ncols_ ; j++) { int *rowIndices = hrow_+mcstrt_[j] ; int lenj = hincol_[j] ; for (int k = 0 ; k < lenj ; k++) { int i = rowIndices[k] ; hinrow_[i]++ ; } } /* Initialize mrstrt[i] to the start of row i+1. As we drop each coefficient and column index into the bulk storage arrays, we'll decrement and store. When we're done, mrstrt[i] will point to the start of row i, as it should. */ int totalCoeffs = 0 ; int i; for ( i = 0 ; i < nrows_ ; i++) { totalCoeffs += hinrow_[i] ; mrstrt_[i] = totalCoeffs ; } mrstrt_[nrows_] = totalCoeffs ; for ( j = ncols_-1 ; j >= 0 ; j--) { int lenj = hincol_[j] ; double *colCoeffs = colels_+mcstrt_[j] ; int *rowIndices = hrow_+mcstrt_[j] ; for (int k = 0 ; k < lenj ; k++) { int ri; ri = rowIndices[k] ; double aij = colCoeffs[k] ; CoinBigIndex l = --mrstrt_[ri] ; rowels_[l] = aij ; hcol_[l] = j ; } } /* Now the support structures. The entry for original column j should start out as j; similarly for row i. originalColumn_ and originalRow_ belong to the PrePostsolve object. */ if (originalColumn_ == 0) originalColumn_ = new int [ncols0_] ; if (originalRow_ == 0) originalRow_ = new int [nrows0_] ; for ( j = 0 ; j < ncols0_ ; j++) originalColumn_[j] = j ; for ( i = 0 ; i < nrows0_ ; i++) originalRow_[i] = i ; /* We have help to set up the clink_ and rlink_ vectors (aids for matrix bulk storage management). clink_ and rlink_ belong to the Presolve object. Once this is done, it's safe to set mrstrt_[nrows_] and mcstrt_[ncols_] to the full size of the bulk storage area. */ if (clink_ == 0) clink_ = new presolvehlink [ncols0_+1] ; if (rlink_ == 0) rlink_ = new presolvehlink [nrows0_+1] ; presolve_make_memlists(/*mcstrt_,*/hincol_,clink_,ncols_) ; presolve_make_memlists(/*mrstrt_,*/hinrow_,rlink_,nrows_) ; mcstrt_[ncols_] = bulk0_ ; mrstrt_[nrows_] = bulk0_ ; /* No rows or columns have been changed just yet. colChanged_ and rowChanged_ belong to the Presolve object. */ if (colChanged_ == 0) colChanged_ = new unsigned char [ncols0_] ; CoinZeroN(colChanged_,ncols0_) ; if (rowChanged_ == 0) rowChanged_ = new unsigned char [nrows0_] ; CoinZeroN(rowChanged_,nrows0_) ; /* Finally, allocate the various *ToDo arrays. These are used to track the rows and columns which should be processed in a given round of presolve transforms. These belong to the Presolve object. Setting number*ToDo to 0 is all the initialization that's required here. */ rowsToDo_ = new int [nrows0_] ; numberRowsToDo_ = 0 ; nextRowsToDo_ = new int [nrows0_] ; numberNextRowsToDo_ = 0 ; colsToDo_ = new int [ncols0_] ; numberColsToDo_ = 0 ; nextColsToDo_ = new int [ncols0_] ; numberNextColsToDo_ = 0 ; initializeStuff(); return ; }
template <typename T> void CoinDenseVector<T>::setVector(int size, const T * elems) { resize(size); CoinMemcpyN( elems,size,elements_); }
/* Returns effective RHS if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ double * ClpMatrixBase::rhsOffset(ClpSimplex * model, bool forceRefresh, bool #ifdef CLP_DEBUG check #endif ) { if (rhsOffset_) { #ifdef CLP_DEBUG if (check) { // no need - but check anyway // zero out basic int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; double * rhs = new double[numberRows]; const double * solutionSlack = model->solutionRegion(0); CoinMemcpyN(model->solutionRegion(), numberColumns, solution); int iRow; for (iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) != ClpSimplex::basic) rhs[iRow] = solutionSlack[iRow]; else rhs[iRow] = 0.0; } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) solution[iColumn] = 0.0; } times(-1.0, solution, rhs); delete [] solution; for (iRow = 0; iRow < numberRows; iRow++) { if (fabs(rhs[iRow] - rhsOffset_[iRow]) > 1.0e-3) printf("** bad effective %d - true %g old %g\n", iRow, rhs[iRow], rhsOffset_[iRow]); } } #endif if (forceRefresh || (refreshFrequency_ && model->numberIterations() >= lastRefresh_ + refreshFrequency_)) { // zero out basic int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; const double * solutionSlack = model->solutionRegion(0); CoinMemcpyN(model->solutionRegion(), numberColumns, solution); for (int iRow = 0; iRow < numberRows; iRow++) { if (model->getRowStatus(iRow) != ClpSimplex::basic) rhsOffset_[iRow] = solutionSlack[iRow]; else rhsOffset_[iRow] = 0.0; } for (int iColumn = 0; iColumn < numberColumns; iColumn++) { if (model->getColumnStatus(iColumn) == ClpSimplex::basic) solution[iColumn] = 0.0; } times(-1.0, solution, rhsOffset_); delete [] solution; lastRefresh_ = model->numberIterations(); } } return rhsOffset_; }
/* This is the real constructor*/ ClpDynamicExampleMatrix::ClpDynamicExampleMatrix(ClpSimplex * model, int numberSets, int numberGubColumns, const int * starts, const double * lower, const double * upper, const CoinBigIndex * startColumn, const int * row, const double * element, const double * cost, const double * columnLower, const double * columnUpper, const unsigned char * status, const unsigned char * dynamicStatus, int numberIds, const int *ids) : ClpDynamicMatrix(model, numberSets, 0, NULL, lower, upper, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) { setType(25); numberColumns_ = numberGubColumns; // start with safe values - then experiment maximumGubColumns_ = numberColumns_; maximumElements_ = startColumn[numberColumns_]; // delete odd stuff created by ClpDynamicMatrix constructor delete [] startSet_; startSet_ = new int [numberSets_]; delete [] next_; next_ = new int [maximumGubColumns_]; delete [] row_; delete [] element_; delete [] startColumn_; delete [] cost_; delete [] columnLower_; delete [] columnUpper_; delete [] dynamicStatus_; delete [] status_; delete [] id_; // and size correctly row_ = new int [maximumElements_]; element_ = new double [maximumElements_]; startColumn_ = new CoinBigIndex [maximumGubColumns_+1]; // say no columns yet numberGubColumns_ = 0; startColumn_[0] = 0; cost_ = new double[maximumGubColumns_]; dynamicStatus_ = new unsigned char [2*maximumGubColumns_]; memset(dynamicStatus_, 0, maximumGubColumns_); id_ = new int[maximumGubColumns_]; if (columnLower) columnLower_ = new double[maximumGubColumns_]; else columnLower_ = NULL; if (columnUpper) columnUpper_ = new double[maximumGubColumns_]; else columnUpper_ = NULL; // space for ids idGen_ = new int [maximumGubColumns_]; int iSet; for (iSet = 0; iSet < numberSets_; iSet++) startSet_[iSet] = -1; // This starts code specific to this storage method CoinBigIndex i; fullStartGen_ = ClpCopyOfArray(starts, numberSets_ + 1); startColumnGen_ = ClpCopyOfArray(startColumn, numberColumns_ + 1); CoinBigIndex numberElements = startColumnGen_[numberColumns_]; rowGen_ = ClpCopyOfArray(row, numberElements); elementGen_ = new double[numberElements]; for (i = 0; i < numberElements; i++) elementGen_[i] = element[i]; costGen_ = new double[numberColumns_]; for (i = 0; i < numberColumns_; i++) { costGen_[i] = cost[i]; // I don't think I need sorted but ... CoinSort_2(rowGen_ + startColumnGen_[i], rowGen_ + startColumnGen_[i+1], elementGen_ + startColumnGen_[i]); } if (columnLower) { columnLowerGen_ = new double[numberColumns_]; for (i = 0; i < numberColumns_; i++) { columnLowerGen_[i] = columnLower[i]; if (columnLowerGen_[i]) { printf("Non-zero lower bounds not allowed - subtract from model\n"); abort(); } } } else { columnLowerGen_ = NULL; } if (columnUpper) { columnUpperGen_ = new double[numberColumns_]; for (i = 0; i < numberColumns_; i++) columnUpperGen_[i] = columnUpper[i]; } else { columnUpperGen_ = NULL; } // end specific coding if (columnUpper_) { // set all upper bounds so we have enough space double * columnUpper = model->columnUpper(); for(i = firstDynamic_; i < lastDynamic_; i++) columnUpper[i] = 1.0e10; } status_ = new unsigned char [2*numberSets_+4]; if (status) { memcpy(status_,status, numberSets_ * sizeof(char)); assert (dynamicStatus); CoinMemcpyN(dynamicStatus, numberIds, dynamicStatus_); assert (numberIds); } else { assert (!numberIds); memset(status_, 0, numberSets_); for (i = 0; i < numberSets_; i++) { // make slack key setStatus(i, ClpSimplex::basic); } } dynamicStatusGen_ = new unsigned char [numberColumns_]; memset(dynamicStatusGen_, 0, numberColumns_); // for clarity for (i = 0; i < numberColumns_; i++) setDynamicStatusGen(i, atLowerBound); // Populate with enough columns if (!numberIds) { // This could be made more sophisticated for (iSet = 0; iSet < numberSets_; iSet++) { int sequence = fullStartGen_[iSet]; CoinBigIndex start = startColumnGen_[sequence]; addColumn(startColumnGen_[sequence+1] - start, rowGen_ + start, elementGen_ + start, costGen_[sequence], columnLowerGen_ ? columnLowerGen_[sequence] : 0, columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30, iSet, getDynamicStatusGen(sequence)); idGen_[iSet] = sequence; // say which one in setDynamicStatusGen(sequence, inSmall); } } else { // put back old ones int * set = new int[numberColumns_]; for (iSet = 0; iSet < numberSets_; iSet++) { for (CoinBigIndex j = fullStartGen_[iSet]; j < fullStartGen_[iSet+1]; j++) set[j] = iSet; } for (int i = 0; i < numberIds; i++) { int sequence = ids[i]; CoinBigIndex start = startColumnGen_[sequence]; addColumn(startColumnGen_[sequence+1] - start, rowGen_ + start, elementGen_ + start, costGen_[sequence], columnLowerGen_ ? columnLowerGen_[sequence] : 0, columnUpperGen_ ? columnUpperGen_[sequence] : 1.0e30, set[sequence], getDynamicStatus(i)); idGen_[iSet] = sequence; // say which one in setDynamicStatusGen(sequence, inSmall); } delete [] set; } if (!status) { gubCrash(); } else { initialProblem(); } }
const CoinPresolveAction *implied_free_action::presolve ( CoinPresolveMatrix *prob, const CoinPresolveAction *next, int &fill_level) { # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 # if PRESOLVE_DEBUG > 0 std::cout << "Entering implied_free_action::presolve, fill level " << fill_level << "." << std::endl ; # endif presolve_consistent(prob) ; presolve_links_ok(prob) ; presolve_check_sol(prob) ; presolve_check_nbasic(prob) ; # endif # if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0 const int startEmptyRows = prob->countEmptyRows() ; const int startEmptyColumns = prob->countEmptyCols() ; # if COIN_PRESOLVE_TUNING > 0 double startTime = 0.0 ; if (prob->tuning_) startTime = CoinCpuTime() ; # endif # endif /* Unpack the row- and column-major representations. */ const int m = prob->nrows_ ; const int n = prob->ncols_ ; const CoinBigIndex *rowStarts = prob->mrstrt_ ; int *rowLengths = prob->hinrow_ ; const int *colIndices = prob->hcol_ ; const double *rowCoeffs = prob->rowels_ ; presolvehlink *rlink = prob->rlink_ ; CoinBigIndex *colStarts = prob->mcstrt_ ; int *colLengths = prob->hincol_ ; int *rowIndices = prob->hrow_ ; double *colCoeffs = prob->colels_ ; presolvehlink *clink = prob->clink_ ; /* Column bounds, row bounds, cost, integrality. */ double *clo = prob->clo_ ; double *cup = prob->cup_ ; double *rlo = prob->rlo_ ; double *rup = prob->rup_ ; double *cost = prob->cost_ ; const unsigned char *integerType = prob->integerType_ ; /* Documented as `inhibit x+y+z = 1 mods'. From the code below, it's clear that this is intended to avoid removing SOS equalities with length >= 5 (hardcoded). */ const bool stopSomeStuff = ((prob->presolveOptions()&0x04) != 0) ; /* Ignore infeasibility. `Fix' is overly optimistic. */ const bool fixInfeasibility = ((prob->presolveOptions_&0x4000) != 0) ; /* Defaults to 0.0. */ const double feasTol = prob->feasibilityTolerance_ ; # if 0 /* Tentatively moved to be a front-end function for useless_constraint_action, much as make_fixed is a front-end for make_fixed_action. This bit of code left for possible tuning. -- lh, 121127 -- Original comment: This needs to be made faster. */ # ifdef COIN_LIGHTWEIGHT_PRESOLVE if (prob->pass_ == 1) { #else if (prob->presolveOptions_&0x10) { # endif next = testRedundant(prob,next) ; if (prob->status_&0x01 != 0) { if ((prob->presolveOptions_&0x4000) != 0) prob->status_ &= !0x01 ; else return (next) ; } # if 1 //def COIN_LIGHTWEIGHT_PRESOLVE } # endif # endif /* implied_free and subst take a fair bit of effort to scan for candidates. This is a hook to allow a presolve driver to avoid that work. */ if (prob->pass_ > 15 && (prob->presolveOptions_&0x10000) != 0) { fill_level = 2 ; return (next) ; } /* Set up to collect implied_free actions. */ action *actions = new action [n] ; # ifdef ZEROFAULT CoinZeroN(reinterpret_cast<char *>(actions),n*sizeof(action)) ; # endif int nactions = 0 ; int *implied_free = prob->usefulColumnInt_ ; int *whichFree = implied_free+n ; int numberFree = 0 ; /* Arrays to hold row activity (row lhs) min and max values. Each row lhs bound is held as two components: a sum of finite column bounds and a count of infinite column bounds. */ int *infiniteDown = new int[m] ; int *infiniteUp = new int[m] ; double *maxDown = new double[m] ; double *maxUp = new double[m] ; /* Overload infiniteUp with row status codes: -1: L(i)/U(i) not yet computed, -2: do not use (empty or useless row), -3: give up (infeasible) -4: chosen as implied free row */ for (int i = 0 ; i < m ; i++) { if (rowLengths[i] > 1) infiniteUp[i] = -1 ; else infiniteUp[i] = -2 ; } // Get rid of rows with prohibited columns if (prob->anyProhibited_) { for (int i = 0 ; i < m ; i++) { CoinBigIndex rStart = rowStarts[i]; CoinBigIndex rEnd = rStart+rowLengths[i]; bool badRow=false; for (CoinBigIndex j = rStart; j < rEnd; ++j) { if (prob->colProhibited(colIndices[j])) { badRow=true; break; } } if (badRow) infiniteUp[i] = -2 ; } } // Can't go on without a suitable finite infinity, can we? #ifdef USE_SMALL_LARGE const double large = 1.0e10 ; #else const double large = 1.0e20 ; #endif /* Decide which columns we're going to look at. There are columns already queued in colsToDo_, but sometimes we want to look at all of them. Don't suck in prohibited columns. See comments at the head of the routine for fill_level. NOTE the overload on usefulColumnInt_. It was assigned above to whichFree (indices of interesting columns). We'll be ok because columns are consumed out of look at one per main loop iteration, but not all columns are interesting. Original comment: if gone from 2 to 3 look at all */ int numberLook = prob->numberColsToDo_ ; int iLook ; int *look = prob->colsToDo_ ; if (fill_level < 0) { look = prob->usefulColumnInt_+n ; if (!prob->anyProhibited()) { CoinIotaN(look,n,0) ; numberLook = n ; } else { numberLook = 0 ; for (iLook = 0 ; iLook < n ; iLook++) if (!prob->colProhibited(iLook)) look[numberLook++] = iLook ; } } /* Step through the columns of interest looking for suitable x(tgt). Interesting columns are limited by number of nonzeros to minimise fill-in during substitution. */ bool infeas = false ; const int maxLook = abs(fill_level) ; for (iLook = 0 ; iLook < numberLook ; iLook++) { const int tgtcol = look[iLook] ; const int tgtcol_len = colLengths[tgtcol] ; if (tgtcol_len <= 0 || tgtcol_len > maxLook) continue ; /* Set up to reconnoiter the column. The initial value for ait_max is chosen to make sure that anything that satisfies the stability check is big enough to use (though we'd clearly like something better). */ const CoinBigIndex kcs = colStarts[tgtcol] ; const CoinBigIndex kce = kcs+tgtcol_len ; const bool singletonCol = (tgtcol_len == 1) ; bool possibleRow = false ; bool singletonRow = false ; double ait_max = 20*ZTOLDP2 ; /* If this is a singleton column, the only concern is that the row is not a singleton row (that has its own, simpler, transform: slack_doubleton). But make sure we're not dealing with some tiny a(it). Note that there's no point in marking a singleton row. By definition, we won't encounter it again. */ if (singletonCol) { const int i = rowIndices[kcs] ; singletonRow = (rowLengths[i] == 1) ; possibleRow = (fabs(colCoeffs[kcs]) > ZTOLDP2) ; } else { /* If the column is not a singleton, we'll need a numerically stable substitution formula. Check that this is possible. One of the entangled rows must be an equality with a numerically stable coefficient, at least .1*MAX{i}a(it). */ for (CoinBigIndex kcol = kcs ; kcol < kce ; ++kcol) { const int i = rowIndices[kcol] ; if (rowLengths[i] == 1) { singletonRow = true ; break ; } const double abs_ait = fabs(colCoeffs[kcol]) ; ait_max = CoinMax(ait_max,abs_ait) ; if (fabs(rlo[i]-rup[i]) < feasTol && abs_ait > .1*ait_max) { possibleRow = true ; } } } if (singletonRow || !possibleRow) continue ; /* The column has possibilities. Walk the column, calculate row activity bounds L(i) and U(i) for suitable entangled rows, then calculate the improvement (if any) on the column bounds for l(j) and u(j). The goal is to satisfy the implied free condition over all entangled rows and find at least one row suitable for a substitution formula (if the column is not a natural singleton). Suitable: If this is a natural singleton, we need to look at the single entangled constraint. If we're attempting to create a singleton by substitution, only look at equalities with stable coefficients. If x(t) is integral, make sure the scaled rhs will be integral. */ # if PRESOLVE_DEBUG > 2 std::cout << " Checking x(" << tgtcol << "), " << tgtcol_len << " nonzeros" << ", l(" << tgtcol << ") " << clo[tgtcol] << ", u(" << tgtcol << ") " << cup[tgtcol] << ", c(" << tgtcol << ") " << cost[tgtcol] << "." << std::endl ; # endif const double lt = clo[tgtcol] ; const double ut = cup[tgtcol] ; double impliedLow = -COIN_DBL_MAX ; double impliedHigh = COIN_DBL_MAX ; int subst_ndx = -1 ; int subst_len = n ; for (CoinBigIndex kcol = kcs ; kcol < kce ; ++kcol) { const int i = rowIndices[kcol] ; assert(infiniteUp[i] != -3) ; if (infiniteUp[i] <= -2) continue ; const double ait = colCoeffs[kcol] ; const int leni = rowLengths[i] ; const double rloi = rlo[i] ; const double rupi = rup[i] ; /* A suitable row for substitution must * be an equality; * the entangled coefficient must be large enough to be numerically stable; * if x(t) is integer, the constant term in the substitution formula must be integer. */ bool rowiOK = (fabs(rloi-rupi) < feasTol) && (fabs(ait) > .1*ait_max) ; rowiOK = rowiOK && ((integerType[tgtcol] == 0) || (fabs((rloi/ait)-floor((rloi/ait)+0.5)) < feasTol)) ; /* If we don't already have L(i) and U(i), calculate now. Check for useless and infeasible constraints when that's done. */ int infUi = 0 ; int infLi = 0 ; double maxUi = 0.0 ; double maxLi = 0.0 ; const CoinBigIndex krs = rowStarts[i] ; const CoinBigIndex kre = krs+leni ; if (infiniteUp[i] == -1) { for (CoinBigIndex krow = krs ; krow < kre ; ++krow) { const double aik = rowCoeffs[krow] ; const int k = colIndices[krow] ; const double lk = clo[k] ; const double uk = cup[k] ; if (aik > 0.0) { if (uk < large) maxUi += uk*aik ; else ++infUi ; if (lk > -large) maxLi += lk*aik ; else ++infLi ; } else if (aik < 0.0) { if (uk < large) maxLi += uk*aik ; else ++infLi ; if (lk > -large) maxUi += lk*aik ; else ++infUi ; } } const double maxUinf = maxUi+infUi*1.0e31 ; const double maxLinf = maxLi-infLi*1.0e31 ; if (maxUinf <= rupi+feasTol && maxLinf >= rloi-feasTol) { infiniteUp[i] = -2 ; } else if (maxUinf < rloi-feasTol && !fixInfeasibility) { prob->status_|= 1 ; infeas = true ; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) << i << rloi << rupi << CoinMessageEol ; infiniteUp[i] = -3 ; } else if (maxLinf > rupi+feasTol && !fixInfeasibility) { prob->status_|= 1 ; infeas = true ; prob->messageHandler()->message(COIN_PRESOLVE_ROWINFEAS, prob->messages()) << i << rloi << rupi << CoinMessageEol ; infiniteUp[i] = -3 ; } else { infiniteUp[i] = infUi ; infiniteDown[i] = infLi ; maxUp[i] = maxUi ; maxDown[i] = maxLi ; } } else { infUi = infiniteUp[i] ; infLi = infiniteDown[i] ; maxUi = maxUp[i] ; maxLi = maxDown[i] ; } # if PRESOLVE_DEBUG > 2 std::cout << " row(" << i << ") " << leni << " nonzeros, blow " << rloi << ", L (" << infLi << "," << maxLi << "), U (" << infUi << "," << maxUi << "), b " << rupi ; if (infeas) std::cout << " infeas" ; if (infiniteUp[i] == -2) std::cout << " useless" ; std::cout << "." << std::endl ; # endif /* If we're infeasible, no sense checking further; escape the implied bound loop. The other possibility is that we've just discovered the constraint is useless, in which case we just move on to the next one in the column. */ if (infeas) break ; if (infiniteUp[i] == -2) continue ; assert(infiniteUp[i] >= 0 && infiniteUp[i] <= leni) ; /* At this point we have L(i) and U(i), expressed as finite and infinite components, and constraint i is neither useless or infeasible. Calculate the implied bounds l'(t) and u'(t) on x(t). The calculation (for a(it) > 0) is u'(t) <= (b(i) - (L(i)-a(it)l(t)))/a(it) = l(t)+(b(i)-L(i))/a(it) l'(t) >= (blow(i) - (U(i)-a(it)u(t)))/a(it) = u(t)+(blow(i)-U(i))/a(it) Insert the appropriate flips for a(it) < 0. Notice that if there's exactly one infinite contribution to L(i) or U(i) and x(t) is responsible, then the finite portion of L(i) or U(i) is already correct. Cut some slack for possible numerical inaccuracy if the finite portion of L(i) or U(i) is very large. If the new bound is very large, force it to infinity. */ double ltprime = -COIN_DBL_MAX ; double utprime = COIN_DBL_MAX ; if (ait > 0.0) { if (rloi > -large) { if (!infUi) { assert(ut < large) ; ltprime = ut+(rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxUi) ; } else if (infUi == 1 && ut > large) { ltprime = (rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxUi) ; } else { ltprime = -COIN_DBL_MAX ; } impliedLow = CoinMax(impliedLow,ltprime) ; } if (rupi < large) { if (!infLi) { assert(lt > -large) ; utprime = lt+(rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxLi) ; } else if (infLi == 1 && lt < -large) { utprime = (rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxLi) ; } else { utprime = COIN_DBL_MAX ; } impliedHigh = CoinMin(impliedHigh,utprime) ; } } else { if (rloi > -large) { if (!infUi) { assert(lt > -large) ; utprime = lt+(rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxUi) ; } else if (infUi == 1 && lt < -large) { utprime = (rloi-maxUi)/ait ; if (fabs(maxUi) > 1.0e8 && !singletonCol) utprime += 1.0e-12*fabs(maxUi) ; } else { utprime = COIN_DBL_MAX ; } impliedHigh = CoinMin(impliedHigh,utprime) ; } if (rupi < large) { if (!infLi) { assert(ut < large) ; ltprime = ut+(rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxLi) ; } else if (infLi == 1 && ut > large) { ltprime = (rupi-maxLi)/ait ; if (fabs(maxLi) > 1.0e8 && !singletonCol) ltprime -= 1.0e-12*fabs(maxLi) ; } else { ltprime = -COIN_DBL_MAX ; } impliedLow = CoinMax(impliedLow,ltprime) ; } } # if PRESOLVE_DEBUG > 2 std::cout << " row(" << i << ") l'(" << tgtcol << ") " << ltprime << ", u'(" << tgtcol << ") " << utprime ; if (lt <= impliedLow && impliedHigh <= ut) std::cout << "; implied free satisfied" ; std::cout << "." << std::endl ; # endif /* For x(t) integral, see if a substitution formula based on row i will preserve integrality. The final check in this clause aims to preserve SOS equalities (i.e., don't eliminate a non-trivial SOS equality from the system using this transform). Note that this can't be folded into the L(i)/U(i) loop because the answer changes with x(t). Original comment: can only accept if good looking row */ if (integerType[tgtcol]) { possibleRow = true ; bool allOnes = true ; for (CoinBigIndex krow = krs ; krow < kre ; ++krow) { const int j = colIndices[krow] ; const double scaled_aij = rowCoeffs[krow]/ait ; if (fabs(scaled_aij) != 1.0) allOnes = false ; if (!integerType[j] || fabs(scaled_aij-floor(scaled_aij+0.5)) > feasTol) { possibleRow = false ; break ; } } if (rloi == 1.0 && leni >= 5 && stopSomeStuff && allOnes) possibleRow = false ; rowiOK = rowiOK && possibleRow ; } /* Do we have a winner? If we have an incumbent, prefer the one with fewer coefficients. */ if (rowiOK) { if (subst_ndx < 0 || (leni < subst_len)) { # if PRESOLVE_DEBUG > 2 std::cout << " row(" << i << ") now candidate for x(" << tgtcol << ")." << std::endl ; # endif subst_ndx = i ; subst_len = leni ; } } } if (infeas) break ; /* Can we do the transform? If so, subst_ndx will have a valid row. Record the implied free variable and the equality we'll use to substitute it out. Take the row out of the running --- we can't use the same row for two substitutions. */ if (lt <= impliedLow && impliedHigh <= ut && (subst_ndx >= 0 || singletonRow)) { implied_free[numberFree] = subst_ndx ; infiniteUp[subst_ndx] = -4 ; whichFree[numberFree++] = tgtcol ; # if PRESOLVE_DEBUG > 1 std::cout << " x(" << tgtcol << ") implied free by row " << subst_ndx << std::endl ; # endif } } delete[] infiniteDown ; delete[] infiniteUp ; delete[] maxDown ; delete[] maxUp ; /* If we're infeasible, there's nothing more to be done. */ if (infeas) { # if PRESOLVE_SUMMARY > 0 || PRESOLVE_DEBUG > 0 std::cout << " IMPLIED_FREE: infeasible." << std::endl ; # endif return (next) ; } /* We have a list of implied free variables, each with a row that can be used to substitute the variable to singleton status if the variable is not a natural singleton. The loop here will only process natural singletons. We'll hand the remainder to subst_constraint_action below, if there is a remainder. The natural singletons processed here are compressed out of whichFree and implied_free. */ int unprocessed = 0 ; for (iLook = 0 ; iLook < numberFree ; iLook++) { const int tgtcol = whichFree[iLook] ; if (colLengths[tgtcol] != 1) { whichFree[unprocessed] = whichFree[iLook] ; implied_free[unprocessed] = implied_free[iLook] ; unprocessed++ ; continue ; } const int tgtrow = implied_free[iLook] ; const int tgtrow_len = rowLengths[tgtrow] ; const CoinBigIndex kcs = colStarts[tgtcol] ; const double tgtcol_coeff = colCoeffs[kcs] ; const double tgtcol_cost = cost[tgtcol] ; const CoinBigIndex krs = rowStarts[tgtrow] ; const CoinBigIndex kre = krs+tgtrow_len ; if (tgtcol_cost != 0.0) { // Check costs don't make unstable //double minOldCost=COIN_DBL_MAX; double maxOldCost=0.0; //double minNewCost=COIN_DBL_MAX; double maxNewCost=0.0; for (CoinBigIndex krow = krs ; krow < kre ; krow++) { const int j = colIndices[krow] ; if (j != tgtcol) { double oldCost = cost[j] ; double newCost = oldCost - (tgtcol_cost*rowCoeffs[krow])/tgtcol_coeff ; oldCost = fabs(oldCost); newCost = fabs(newCost); //minOldCost=CoinMin(minOldCost,oldCost); maxOldCost=CoinMax(maxOldCost,oldCost); //minNewCost=CoinMin(minNewCost,newCost); maxNewCost=CoinMax(maxNewCost,newCost); } } if (maxNewCost>1000.0*(maxOldCost+1.0) && maxOldCost) { //printf("too big %d tgtcost %g maxOld %g maxNew %g\n", // tgtcol,tgtcol_cost,maxOldCost,maxNewCost); continue; } } /* Initialise the postsolve action. We need to remember the row and column. */ action *s = &actions[nactions++] ; s->row = tgtrow ; s->col = tgtcol ; s->clo = clo[tgtcol] ; s->cup = cup[tgtcol] ; s->rlo = rlo[tgtrow] ; s->rup = rup[tgtrow] ; s->ninrow = tgtrow_len ; s->rowels = presolve_dupmajor(rowCoeffs,colIndices,tgtrow_len,krs) ; s->costs = NULL ; /* We're processing a singleton, hence no substitutions in the matrix, but we do need to fix up the cost vector. The substitution formula is x(t) = (rhs(i) - SUM{j\t}a(ik)x(k))/a(it) hence c'(k) = c(k)-c(t)a(ik)/a(it) and there's a constant offset c(t)rhs(i)/a(it). where rhs(i) is one of blow(i) or b(i). For general constraints where blow(i) != b(i), we need to take a bit of care. If only one of blow(i) or b(i) is finite, that's the one to use. Where we have two finite but unequal bounds, choose the bound that will result in the most favourable value for x(t). For minimisation, if c(t) < 0 we want to maximise x(t), so choose b(i) if a(it) > 0, blow(i) if a(it) < 0. A bit of case analysis says choose b(i) when c(t)a(it) < 0, blow(i) when c(t)a(it) > 0. We shouldn't be here if both row bounds are infinite. Fortunately, the objective coefficients are not affected by this. */ if (tgtcol_cost != 0.0) { double tgtrow_rhs = rup[tgtrow] ; if (fabs(rlo[tgtrow]-rup[tgtrow]) > feasTol) { const double rlot = rlo[tgtrow] ; const double rupt = rup[tgtrow] ; if (rlot > -COIN_DBL_MAX && rupt < COIN_DBL_MAX) { if ((tgtcol_cost*tgtcol_coeff) > 0) tgtrow_rhs = rlot ; else tgtrow_rhs = rupt ; } else if (rupt >= COIN_DBL_MAX) { tgtrow_rhs = rlot ; } } assert(fabs(tgtrow_rhs) <= large) ; double *save_costs = new double[tgtrow_len] ; for (CoinBigIndex krow = krs ; krow < kre ; krow++) { const int j = colIndices[krow] ; save_costs[krow-krs] = cost[j] ; cost[j] -= (tgtcol_cost*rowCoeffs[krow])/tgtcol_coeff ; } prob->change_bias((tgtcol_cost*tgtrow_rhs)/tgtcol_coeff) ; cost[tgtcol] = 0.0 ; s->costs = save_costs ; } /* Remove the row from the column-major representation, queuing up each column for reconsideration. Then remove the row from the row-major representation. */ for (CoinBigIndex krow = krs ; krow < kre ; krow++) { const int j = colIndices[krow] ; presolve_delete_from_col(tgtrow,j,colStarts,colLengths,rowIndices, colCoeffs) ; if (colLengths[j] == 0) { PRESOLVE_REMOVE_LINK(prob->clink_,j) ; } else { prob->addCol(j) ; } } PRESOLVE_REMOVE_LINK(clink,tgtcol) ; colLengths[tgtcol] = 0 ; PRESOLVE_REMOVE_LINK(rlink,tgtrow) ; rowLengths[tgtrow] = 0 ; rlo[tgtrow] = 0.0 ; rup[tgtrow] = 0.0 ; } /* We're done with the natural singletons. Trim actions to length and create the postsolve object. */ if (nactions) { # if PRESOLVE_SUMMARY > 0 || PRESOLVE_DEBUG > 0 printf("NIMPLIED FREE: %d\n", nactions) ; # endif action *actions1 = new action[nactions] ; CoinMemcpyN(actions, nactions, actions1) ; next = new implied_free_action(nactions,actions1,next) ; } delete [] actions ; # if PRESOLVE_DEBUG > 0 std::cout << " IMPLIED_FREE: identified " << numberFree << " implied free transforms, processed " << numberFree-unprocessed << " natural singletons." << std::endl ; # endif /* Now take a stab at the columns that aren't natural singletons, if there are any left. */ if (unprocessed != 0) { // if not integer - don't allow much fill if (!prob->anyInteger()) { int numberFree=unprocessed; int nBad=0; unprocessed=0; // Take out ones that make much denser or might lead to instability /* Unpack the row- and column-major representations. */ CoinBigIndex *rowStarts = prob->mrstrt_ ; int *rowLengths = prob->hinrow_ ; double *rowCoeffs = prob->rowels_ ; int *colIndices = prob->hcol_ ; CoinBigIndex *colStarts = prob->mcstrt_ ; int *colLengths = prob->hincol_ ; double *colCoeffs = prob->colels_ ; int *rowIndices = prob->hrow_ ; /* This array is used to hold the indices of columns involved in substitutions, where we have the potential for cancellation. At the end they'll be checked to eliminate any actual zeros that may result. NOTE that usefulColumnInt_ is already in use for parameters implied_free and whichFree when this routine is called from implied_free. */ int *rowsUsed = &prob->usefulRowInt_[0] ; int nRowsUsed = 0 ; /* Open a loop to process the (equality r, implied free variable t) pairs in whichFree and implied_free. It can happen that removal of (row, natural singleton) pairs back in implied_free will reduce the length of column t. It can also happen that previous processing here has resulted in fillin or cancellation. So check again for column length and exclude natural singletons and overly dense columns. */ for (int iLook = 0 ; iLook < numberFree ; iLook++) { const int tgtcol = whichFree[iLook] ; const int tgtrow = implied_free[iLook] ; if (colLengths[tgtcol] < 2 || colLengths[tgtcol] > maxLook) { # if PRESOLVE_DEBUG > 3 std::cout << " skipping eqn " << tgtrow << " x(" << tgtcol << "); length now " << colLengths[tgtcol] << "." << std::endl ; # endif continue ; } CoinBigIndex tgtcs = colStarts[tgtcol] ; CoinBigIndex tgtce = tgtcs+colLengths[tgtcol] ; /* A few checks to make sure that the candidate pair is still suitable. Processing candidates earlier in the list can eliminate coefficients. * Don't use this pair if any involved row i has become a row singleton or empty. * Don't use this pair if any involved row has been modified as part of the processing for a previous candidate pair on this call. * Don't use this pair if a(i,tgtcol) has become zero. The checks on a(i,tgtcol) seem superfluous but it's possible that implied_free identified two candidate pairs to eliminate the same column. If we've already processed one of them, we could be in trouble. */ double tgtcoeff = 0.0 ; bool dealBreaker = false ; for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) { const int i = rowIndices[kcol] ; if (rowLengths[i] < 2 || prob->rowUsed(i)) { dealBreaker = true ; break ; } const double aij = colCoeffs[kcol] ; if (fabs(aij) <= ZTOLDP2) { dealBreaker = true ; break ; } if (i == tgtrow) tgtcoeff = aij ; } if (dealBreaker == true) { # if PRESOLVE_DEBUG > 3 std::cout << " skipping eqn " << tgtrow << " x(" << tgtcol << "); deal breaker (1)." << std::endl ; # endif continue ; } /* Check for numerical stability.A large coeff_factor will inflate the coefficients in the substitution formula. */ dealBreaker = false ; for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) { const double coeff_factor = fabs(colCoeffs[kcol]/tgtcoeff) ; if (coeff_factor > 10.0) dealBreaker = true ; } if (dealBreaker == true) { # if PRESOLVE_DEBUG > 3 std::cout << " skipping eqn " << tgtrow << " x(" << tgtcol << "); deal breaker (2)." << std::endl ; # endif continue ; } /* Count up the total number of coefficients in entangled rows and mark them as contaminated. */ int ntotels = 0 ; for (CoinBigIndex kcol = tgtcs ; kcol < tgtce ; ++kcol) { const int i = rowIndices[kcol] ; ntotels += rowLengths[i] ; PRESOLVEASSERT(!prob->rowUsed(i)) ; prob->setRowUsed(i) ; rowsUsed[nRowsUsed++] = i ; } CoinBigIndex tgtrs = rowStarts[tgtrow] ; CoinBigIndex tgtre = tgtrs+rowLengths[tgtrow] ; // kill small if wanted int relax= (prob->presolveOptions()&0x60000)>>17; double tolerance = 1.0e-12; for (int i=0;i<relax;i++) tolerance *= 10.0; /* Sort the target row for efficiency */ CoinSort_2(colIndices+tgtrs,colIndices+tgtre,rowCoeffs+tgtrs) ; CoinBigIndex start=colStarts[tgtcol]; CoinBigIndex end = start+colLengths[tgtcol]; numberBadElements=0; int numberFill=-rowLengths[tgtrow]; for (int colndx = start ; colndx < end ; ++colndx) { int i = rowIndices[colndx] ; if (i == tgtrow) continue ; double ait = colCoeffs[colndx] ; double coeff_factor = -ait/tgtcoeff ; CoinBigIndex krs = rowStarts[i] ; CoinBigIndex kre = krs+rowLengths[i] ; /* Sort the row for efficiency and call add_row to do the actual business of changing coefficients due to substitution. This has the potential to trigger compaction of the row-major bulk store, so update bulk store indices. */ CoinSort_2(colIndices+krs,colIndices+kre,rowCoeffs+krs) ; numberFill += check_row(rowStarts,rowCoeffs,colIndices, rowLengths,coeff_factor,tolerance,i,tgtrow); } if (numberBadElements||3*numberFill>2*(colLengths[tgtcol]+rowLengths[tgtrow])) { //printf("Bad subst col %d row %d - %d small elements, fill %d\n", // tgtcol,tgtrow,numberBadElements,numberFill); if (numberBadElements) nBad++; } else { whichFree[unprocessed]=tgtcol; implied_free[unprocessed++]=tgtrow; //printf("Good subst col %d row %d - fill %d\n", // tgtcol,tgtrow,numberFill); } } /* That's it, we've processed all the candidate pairs. Clear the row used flags. */ for (int i = 0 ; i < nRowsUsed ; i++) prob->unsetRowUsed(rowsUsed[i]) ; #if CLP_USEFUL_PRINTOUT printf("%d allowed through out of %d - %d on coefficient\n", unprocessed,numberFree,nBad); #endif } next = subst_constraint_action::presolve(prob,implied_free,whichFree, unprocessed,next,maxLook) ; } /* Give some feedback to the presolve driver. If we aren't finding enough candidates and haven't reached the limit, bump fill_level and return a negated value. The presolve driver can tweak this value or simply return it on the next call. See the top of the routine for a full explanation. */ if (numberFree < 30 && maxLook < prob->maxSubstLevel_) { fill_level = -(maxLook+1) ; } else { fill_level = maxLook ; } # if COIN_PRESOLVE_TUNING > 0 double thisTime ; if (prob->tuning_) thisTime = CoinCpuTime() ; # endif # if PRESOLVE_CONSISTENCY > 0 || PRESOLVE_DEBUG > 0 presolve_consistent(prob) ; presolve_links_ok(prob) ; presolve_check_sol(prob) ; presolve_check_nbasic(prob) ; # endif # if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0 int droppedRows = prob->countEmptyRows()-startEmptyRows ; int droppedColumns = prob->countEmptyCols()-startEmptyColumns ; std::cout << "Leaving implied_free_action::presolve, fill level " << fill_level << ", " << droppedRows << " rows, " << droppedColumns << " columns dropped" ; # if COIN_PRESOLVE_TUNING > 0 std::cout << " in " << thisTime-startTime << "s" ; # endif std::cout << "." << std::endl ; # endif return (next) ; }
bool ClpInterior::createWorkingData() { bool goodMatrix = true; //check matrix if (!matrix_->allElementsInRange(this, 1.0e-12, 1.0e20)) { problemStatus_ = 4; goodMatrix = false; } int nTotal = numberRows_ + numberColumns_; delete [] solution_; solution_ = new CoinWorkDouble[nTotal]; CoinMemcpyN(columnActivity_, numberColumns_, solution_); CoinMemcpyN(rowActivity_, numberRows_, solution_ + numberColumns_); delete [] cost_; cost_ = new CoinWorkDouble[nTotal]; int i; CoinWorkDouble direction = optimizationDirection_ * objectiveScale_; // direction is actually scale out not scale in if (direction) direction = 1.0 / direction; const double * obj = objective(); for (i = 0; i < numberColumns_; i++) cost_[i] = direction * obj[i]; memset(cost_ + numberColumns_, 0, numberRows_ * sizeof(CoinWorkDouble)); // do scaling if needed if (scalingFlag_ > 0 && !rowScale_) { if (matrix_->scale(this)) scalingFlag_ = -scalingFlag_; // not scaled after all } delete [] lower_; delete [] upper_; lower_ = new CoinWorkDouble[nTotal]; upper_ = new CoinWorkDouble[nTotal]; rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; CoinMemcpyN(rowLower_, numberRows_, rowLowerWork_); CoinMemcpyN(rowUpper_, numberRows_, rowUpperWork_); CoinMemcpyN(columnLower_, numberColumns_, columnLowerWork_); CoinMemcpyN(columnUpper_, numberColumns_, columnUpperWork_); // clean up any mismatches on infinity for (i = 0; i < numberColumns_; i++) { if (columnLowerWork_[i] < -1.0e30) columnLowerWork_[i] = -COIN_DBL_MAX; if (columnUpperWork_[i] > 1.0e30) columnUpperWork_[i] = COIN_DBL_MAX; } // clean up any mismatches on infinity for (i = 0; i < numberRows_; i++) { if (rowLowerWork_[i] < -1.0e30) rowLowerWork_[i] = -COIN_DBL_MAX; if (rowUpperWork_[i] > 1.0e30) rowUpperWork_[i] = COIN_DBL_MAX; } // check rim of problem okay if (!sanityCheck()) goodMatrix = false; if(rowScale_) { for (i = 0; i < numberColumns_; i++) { CoinWorkDouble multiplier = rhsScale_ / columnScale_[i]; cost_[i] *= columnScale_[i]; if (columnLowerWork_[i] > -1.0e50) columnLowerWork_[i] *= multiplier; if (columnUpperWork_[i] < 1.0e50) columnUpperWork_[i] *= multiplier; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble multiplier = rhsScale_ * rowScale_[i]; if (rowLowerWork_[i] > -1.0e50) rowLowerWork_[i] *= multiplier; if (rowUpperWork_[i] < 1.0e50) rowUpperWork_[i] *= multiplier; } } else if (rhsScale_ != 1.0) { for (i = 0; i < numberColumns_ + numberRows_; i++) { if (lower_[i] > -1.0e50) lower_[i] *= rhsScale_; if (upper_[i] < 1.0e50) upper_[i] *= rhsScale_; } } assert (!errorRegion_); errorRegion_ = new CoinWorkDouble [numberRows_]; assert (!rhsFixRegion_); rhsFixRegion_ = new CoinWorkDouble [numberRows_]; assert (!deltaY_); deltaY_ = new CoinWorkDouble [numberRows_]; CoinZeroN(deltaY_, numberRows_); assert (!upperSlack_); upperSlack_ = new CoinWorkDouble [nTotal]; assert (!lowerSlack_); lowerSlack_ = new CoinWorkDouble [nTotal]; assert (!diagonal_); diagonal_ = new CoinWorkDouble [nTotal]; assert (!deltaX_); deltaX_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaX_, nTotal); assert (!deltaZ_); deltaZ_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaZ_, nTotal); assert (!deltaW_); deltaW_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaW_, nTotal); assert (!deltaSU_); deltaSU_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaSU_, nTotal); assert (!deltaSL_); deltaSL_ = new CoinWorkDouble [nTotal]; CoinZeroN(deltaSL_, nTotal); assert (!primalR_); assert (!dualR_); // create arrays if we are doing KKT if (cholesky_->type() >= 20) { primalR_ = new CoinWorkDouble [nTotal]; CoinZeroN(primalR_, nTotal); dualR_ = new CoinWorkDouble [numberRows_]; CoinZeroN(dualR_, numberRows_); } assert (!rhsB_); rhsB_ = new CoinWorkDouble [numberRows_]; CoinZeroN(rhsB_, numberRows_); assert (!rhsU_); rhsU_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsU_, nTotal); assert (!rhsL_); rhsL_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsL_, nTotal); assert (!rhsZ_); rhsZ_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsZ_, nTotal); assert (!rhsW_); rhsW_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsW_, nTotal); assert (!rhsC_); rhsC_ = new CoinWorkDouble [nTotal]; CoinZeroN(rhsC_, nTotal); assert (!workArray_); workArray_ = new CoinWorkDouble [nTotal]; CoinZeroN(workArray_, nTotal); assert (!zVec_); zVec_ = new CoinWorkDouble [nTotal]; CoinZeroN(zVec_, nTotal); assert (!wVec_); wVec_ = new CoinWorkDouble [nTotal]; CoinZeroN(wVec_, nTotal); assert (!dj_); dj_ = new CoinWorkDouble [nTotal]; if (!status_) status_ = new unsigned char [numberRows_+numberColumns_]; memset(status_, 0, numberRows_ + numberColumns_); return goodMatrix; }
/* 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); } } } }
/* Orders rows and saves pointer to matrix.and model */ int ClpCholeskyTaucs::order(ClpInterior * model) { numberRows_ = model->numberRows(); rowsDropped_ = new char [numberRows_]; memset(rowsDropped_, 0, numberRows_); numberRowsDropped_ = 0; model_ = model; rowCopyT_ = model->clpMatrix()->reverseOrderedCopy(); const CoinBigIndex * columnStart = model_->clpMatrix()->getVectorStarts(); const int * columnLength = model_->clpMatrix()->getVectorLengths(); const int * row = model_->clpMatrix()->getIndices(); const CoinBigIndex * rowStart = rowCopyT_->getVectorStarts(); const int * rowLength = rowCopyT_->getVectorLengths(); const int * column = rowCopyT_->getIndices(); // We need two arrays for counts int * which = new int [numberRows_]; int * used = new int[numberRows_]; CoinZeroN(used, numberRows_); int iRow; sizeFactorT_ = 0; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactorT_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; } } delete [] which; // Now we have size - create arrays and fill in matrix_ = taucs_ccs_create(numberRows_, numberRows_, sizeFactorT_, TAUCS_DOUBLE | TAUCS_SYMMETRIC | TAUCS_LOWER); if (!matrix_) return 1; // Space for starts choleskyStartT_ = matrix_->colptr; choleskyRowT_ = matrix_->rowind; sparseFactorT_ = matrix_->values.d; sizeFactorT_ = 0; which = choleskyRowT_; for (iRow = 0; iRow < numberRows_; iRow++) { int number = 1; // make sure diagonal exists which[0] = iRow; used[iRow] = 1; choleskyStartT_[iRow] = sizeFactorT_; if (!rowsDropped_[iRow]) { CoinBigIndex startRow = rowStart[iRow]; CoinBigIndex endRow = rowStart[iRow] + rowLength[iRow]; for (CoinBigIndex k = startRow; k < endRow; k++) { int iColumn = column[k]; CoinBigIndex start = columnStart[iColumn]; CoinBigIndex end = columnStart[iColumn] + columnLength[iColumn]; for (CoinBigIndex j = start; j < end; j++) { int jRow = row[j]; if (jRow >= iRow && !rowsDropped_[jRow]) { if (!used[jRow]) { used[jRow] = 1; which[number++] = jRow; } } } } sizeFactorT_ += number; int j; for (j = 0; j < number; j++) used[which[j]] = 0; // Sort std::sort(which, which + number); // move which on which += number; } } choleskyStartT_[numberRows_] = sizeFactorT_; delete [] used; permuteInverse_ = new int [numberRows_]; permute_ = new int[numberRows_]; int * perm, *invp; // There seem to be bugs in ordering if model too small if (numberRows_ > 10) taucs_ccs_order(matrix_, &perm, &invp, (const char *) "genmmd"); else taucs_ccs_order(matrix_, &perm, &invp, (const char *) "identity"); CoinMemcpyN(perm, numberRows_, permuteInverse_); free(perm); CoinMemcpyN(invp, numberRows_, permute_); free(invp); // need to permute taucs_ccs_matrix * permuted = taucs_ccs_permute_symmetrically(matrix_, permuteInverse_, permute_); // symbolic factorization_ = taucs_ccs_factor_llt_symbolic(permuted); taucs_ccs_free(permuted); return factorization_ ? 0 : 1; }
void ClpInterior::checkSolution() { int iRow, iColumn; CoinWorkDouble * reducedCost = reinterpret_cast<CoinWorkDouble *>(reducedCost_); CoinWorkDouble * dual = reinterpret_cast<CoinWorkDouble *>(dual_); CoinMemcpyN(cost_, numberColumns_, reducedCost); matrix_->transposeTimes(-1.0, dual, reducedCost); // Now modify reduced costs for quadratic CoinWorkDouble quadraticOffset = quadraticDjs(reducedCost, solution_, scaleFactor_); objectiveValue_ = 0.0; // now look at solution sumPrimalInfeasibilities_ = 0.0; sumDualInfeasibilities_ = 0.0; CoinWorkDouble dualTolerance = 10.0 * dblParam_[ClpDualTolerance]; CoinWorkDouble primalTolerance = dblParam_[ClpPrimalTolerance]; CoinWorkDouble primalTolerance2 = 10.0 * dblParam_[ClpPrimalTolerance]; worstComplementarity_ = 0.0; complementarityGap_ = 0.0; // Done scaled - use permanent regions for output // but internal for bounds const CoinWorkDouble * lower = lower_ + numberColumns_; const CoinWorkDouble * upper = upper_ + numberColumns_; for (iRow = 0; iRow < numberRows_; iRow++) { CoinWorkDouble infeasibility = 0.0; CoinWorkDouble distanceUp = CoinMin(upper[iRow] - rowActivity_[iRow], static_cast<CoinWorkDouble>(1.0e10)); CoinWorkDouble distanceDown = CoinMin(rowActivity_[iRow] - lower[iRow], static_cast<CoinWorkDouble>(1.0e10)); if (distanceUp > primalTolerance2) { CoinWorkDouble value = dual[iRow]; // should not be negative if (value < -dualTolerance) { sumDualInfeasibilities_ += -dualTolerance - value; value = - value * distanceUp; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (distanceDown > primalTolerance2) { CoinWorkDouble value = dual[iRow]; // should not be positive if (value > dualTolerance) { sumDualInfeasibilities_ += value - dualTolerance; value = value * distanceDown; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (rowActivity_[iRow] > upper[iRow]) { infeasibility = rowActivity_[iRow] - upper[iRow]; } else if (rowActivity_[iRow] < lower[iRow]) { infeasibility = lower[iRow] - rowActivity_[iRow]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance; } } lower = lower_; upper = upper_; for (iColumn = 0; iColumn < numberColumns_; iColumn++) { CoinWorkDouble infeasibility = 0.0; objectiveValue_ += cost_[iColumn] * columnActivity_[iColumn]; CoinWorkDouble distanceUp = CoinMin(upper[iColumn] - columnActivity_[iColumn], static_cast<CoinWorkDouble>(1.0e10)); CoinWorkDouble distanceDown = CoinMin(columnActivity_[iColumn] - lower[iColumn], static_cast<CoinWorkDouble>(1.0e10)); if (distanceUp > primalTolerance2) { CoinWorkDouble value = reducedCost[iColumn]; // should not be negative if (value < -dualTolerance) { sumDualInfeasibilities_ += -dualTolerance - value; value = - value * distanceUp; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (distanceDown > primalTolerance2) { CoinWorkDouble value = reducedCost[iColumn]; // should not be positive if (value > dualTolerance) { sumDualInfeasibilities_ += value - dualTolerance; value = value * distanceDown; if (value > worstComplementarity_) worstComplementarity_ = value; complementarityGap_ += value; } } if (columnActivity_[iColumn] > upper[iColumn]) { infeasibility = columnActivity_[iColumn] - upper[iColumn]; } else if (columnActivity_[iColumn] < lower[iColumn]) { infeasibility = lower[iColumn] - columnActivity_[iColumn]; } if (infeasibility > primalTolerance) { sumPrimalInfeasibilities_ += infeasibility - primalTolerance; } } #if COIN_LONG_WORK // ok as packs down CoinMemcpyN(reducedCost, numberColumns_, reducedCost_); #endif // add in offset objectiveValue_ += 0.5 * quadraticOffset; }
/* It is always the case that one of the variables of a doubleton is, or can be made, implied free, but neither will necessarily be a singleton. Since in the case of a doubleton the number of non-zero entries will never increase if one is eliminated, it makes sense to always eliminate them. The col rep and row rep must be consistent. */ const CoinPresolveAction *doubleton_action::presolve (CoinPresolveMatrix *prob, const CoinPresolveAction *next) { # if PRESOLVE_DEBUG > 0 || PRESOLVE_CONSISTENCY > 0 # if PRESOLVE_DEBUG > 0 std::cout << "Entering doubleton_action::presolve; considering " << prob->numberRowsToDo_ << " rows." << std::endl ; # endif presolve_consistent(prob) ; presolve_links_ok(prob) ; presolve_check_sol(prob) ; presolve_check_nbasic(prob) ; # endif # if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0 int startEmptyRows = 0 ; int startEmptyColumns = 0 ; startEmptyRows = prob->countEmptyRows() ; startEmptyColumns = prob->countEmptyCols() ; # if COIN_PRESOLVE_TUNING > 0 double startTime = 0.0 ; if (prob->tuning_) startTime = CoinCpuTime() ; # endif # endif const int n = prob->ncols_ ; const int m = prob->nrows_ ; /* Unpack column-major and row-major representations, along with rim vectors. */ CoinBigIndex *colStarts = prob->mcstrt_ ; int *colLengths = prob->hincol_ ; double *colCoeffs = prob->colels_ ; int *rowIndices = prob->hrow_ ; presolvehlink *clink = prob->clink_ ; double *clo = prob->clo_ ; double *cup = prob->cup_ ; CoinBigIndex *rowStarts = prob->mrstrt_ ; int *rowLengths = prob->hinrow_ ; double *rowCoeffs = prob->rowels_ ; int *colIndices = prob->hcol_ ; presolvehlink *rlink = prob->rlink_ ; double *rlo = prob->rlo_ ; double *rup = prob->rup_ ; const unsigned char *integerType = prob->integerType_ ; double *cost = prob->cost_ ; int numberLook = prob->numberRowsToDo_ ; int *look = prob->rowsToDo_ ; const double ztolzb = prob->ztolzb_ ; const double ztolzero = 1.0e-12 ; action *actions = new action [m] ; int nactions = 0 ; /* zeros will hold columns that should be groomed to remove explicit zeros when we're finished. fixed will hold columns that have ended up as fixed variables. */ int *zeros = prob->usefulColumnInt_ ; int nzeros = 0 ; int *fixed = zeros+n ; int nfixed = 0 ; unsigned char *rowstat = prob->rowstat_ ; double *acts = prob->acts_ ; double *sol = prob->sol_ ; /* More like `ignore infeasibility'. */ bool fixInfeasibility = ((prob->presolveOptions_&0x4000) != 0) ; /* Open the main loop to scan for doubleton candidates. */ for (int iLook = 0 ; iLook < numberLook ; iLook++) { const int tgtrow = look[iLook] ; /* We need an equality with two coefficients. Avoid isolated constraints, lest both variables vanish. Failure of the assert indicates that the row- and column-major representations are out of sync. */ if ((rowLengths[tgtrow] != 2) || (fabs(rup[tgtrow]-rlo[tgtrow]) > ZTOLDP)) continue ; const CoinBigIndex krs = rowStarts[tgtrow] ; int tgtcolx = colIndices[krs] ; int tgtcoly = colIndices[krs+1] ; PRESOLVEASSERT(colLengths[tgtcolx] > 0 || colLengths[tgtcoly] > 0) ; if (colLengths[tgtcolx] == 1 && colLengths[tgtcoly] == 1) continue ; /* Avoid prohibited columns and fixed columns. Make sure the coefficients are nonzero. JJF - test should allow one to be prohibited as long as you leave that one. I modified earlier code but hope I have got this right. */ if (prob->colProhibited(tgtcolx) && prob->colProhibited(tgtcoly)) continue ; if (fabs(rowCoeffs[krs]) < ZTOLDP2 || fabs(rowCoeffs[krs+1]) < ZTOLDP2) continue ; if ((fabs(cup[tgtcolx]-clo[tgtcolx]) < ZTOLDP) || (fabs(cup[tgtcoly]-clo[tgtcoly]) < ZTOLDP)) continue ; # if PRESOLVE_DEBUG > 2 std::cout << " row " << tgtrow << " colx " << tgtcolx << " coly " << tgtcoly << " passes preliminary eval." << std::endl ; # endif /* Find this row in each column. The indices are not const because we may flip them below, once we decide which column will be eliminated. */ CoinBigIndex krowx = presolve_find_row(tgtrow,colStarts[tgtcolx], colStarts[tgtcolx]+colLengths[tgtcolx],rowIndices) ; double coeffx = colCoeffs[krowx] ; CoinBigIndex krowy = presolve_find_row(tgtrow,colStarts[tgtcoly], colStarts[tgtcoly]+colLengths[tgtcoly],rowIndices) ; double coeffy = colCoeffs[krowy] ; const double rhs = rlo[tgtrow] ; /* Avoid obscuring a requirement for integrality. If only one variable is integer, keep it and substitute for the continuous variable. If both are integer, substitute only for the forms x = k*y (k integral and non-empty intersection on bounds on x) or x = 1-y, where both x and y are binary. flag bits for integerStatus: 0x01: x integer; 0x02: y integer This bit of code works because 0 is continuous, 1 is integer. Make sure that's true. */ assert((integerType[tgtcolx] == 0) || (integerType[tgtcolx] == 1)) ; assert((integerType[tgtcoly] == 0) || (integerType[tgtcoly] == 1)) ; int integerX = integerType[tgtcolx]; int integerY = integerType[tgtcoly]; /* if one prohibited then treat that as integer. This may be pessimistic - but will catch SOS etc */ if (prob->colProhibited2(tgtcolx)) integerX=1; if (prob->colProhibited2(tgtcoly)) integerY=1; int integerStatus = (integerY<<1)|integerX ; if (integerStatus == 3) { int good = 0 ; double rhs2 = rhs ; if (coeffx < 0.0) { coeffx = -coeffx ; rhs2 += 1 ; } if ((cup[tgtcolx] == 1.0) && (clo[tgtcolx] == 0.0) && (fabs(coeffx-1.0) < 1.0e-7) && !prob->colProhibited2(tgtcoly)) good = 1 ; if (coeffy < 0.0) { coeffy = -coeffy ; rhs2 += 1 ; } if ((cup[tgtcoly] == 1.0) && (clo[tgtcoly] == 0.0) && (fabs(coeffy-1.0) < 1.0e-7) && !prob->colProhibited2(tgtcolx)) good |= 2 ; if (!(good == 3 && fabs(rhs2-1.0) < 1.0e-7)) integerStatus = -1 ; /* Not x+y = 1. Try for ax+by = 0 */ if (integerStatus < 0 && rhs == 0.0) { coeffx = colCoeffs[krowx] ; coeffy = colCoeffs[krowy] ; double ratio ; bool swap = false ; if (fabs(coeffx) > fabs(coeffy)) { ratio = coeffx/coeffy ; } else { ratio = coeffy/coeffx ; swap = true ; } ratio = fabs(ratio) ; if (fabs(ratio-floor(ratio+0.5)) < ztolzero) { integerStatus = swap ? 2 : 1 ; } } /* One last try --- just require an integral substitution formula. But ax+by = 0 above is a subset of ax+by = c below and should pass the test below. For that matter, so will x+y = 1. Why separate special cases above? -- lh, 121106 -- */ if (integerStatus < 0) { bool canDo = false ; coeffx = colCoeffs[krowx] ; coeffy = colCoeffs[krowy] ; double ratio ; bool swap = false ; double rhsRatio ; if (fabs(coeffx) > fabs(coeffy)) { ratio = coeffx/coeffy ; rhsRatio = rhs/coeffx ; } else { ratio = coeffy/coeffx ; rhsRatio = rhs/coeffy ; swap = true ; } ratio = fabs(ratio) ; if (fabs(ratio-floor(ratio+0.5)) < ztolzero) { // possible integerStatus = swap ? 2 : 1 ; // but check rhs if (rhsRatio==floor(rhsRatio+0.5)) canDo=true ; } # ifdef COIN_DEVELOP2 if (canDo) printf("Good CoinPresolveDoubleton tgtcolx %d (%g and bounds %g %g) tgtcoly %d (%g and bound %g %g) - rhs %g\n", tgtcolx,colCoeffs[krowx],clo[tgtcolx],cup[tgtcolx], tgtcoly,colCoeffs[krowy],clo[tgtcoly],cup[tgtcoly],rhs) ; else printf("Bad CoinPresolveDoubleton tgtcolx %d (%g) tgtcoly %d (%g) - rhs %g\n", tgtcolx,colCoeffs[krowx],tgtcoly,colCoeffs[krowy],rhs) ; # endif if (!canDo) continue ; } } /* We've resolved integrality concerns. If we concluded that we need to switch the roles of x and y because of integrality, do that now. If both variables are continuous, we may still want to swap for numeric stability. Eliminate the variable with the larger coefficient. */ if (integerStatus == 2) { CoinSwap(tgtcoly,tgtcolx) ; CoinSwap(krowy,krowx) ; } else if (integerStatus == 0) { if (fabs(colCoeffs[krowy]) < fabs(colCoeffs[krowx])) { CoinSwap(tgtcoly,tgtcolx) ; CoinSwap(krowy,krowx) ; } } /* Don't eliminate y just yet if it's entangled in a singleton row (we want to capture that explicit bound in a column bound). */ const CoinBigIndex kcsy = colStarts[tgtcoly] ; const CoinBigIndex kcey = kcsy+colLengths[tgtcoly] ; bool singletonRow = false ; for (CoinBigIndex kcol = kcsy ; kcol < kcey ; kcol++) { if (rowLengths[rowIndices[kcol]] == 1) { singletonRow = true ; break ; } } // skip if y prohibited if (singletonRow || prob->colProhibited2(tgtcoly)) continue ; coeffx = colCoeffs[krowx] ; coeffy = colCoeffs[krowy] ; # if PRESOLVE_DEBUG > 2 std::cout << " doubleton row " << tgtrow << ", keep x(" << tgtcolx << ") elim x(" << tgtcoly << ")." << std::endl ; # endif PRESOLVE_DETAIL_PRINT(printf("pre_doubleton %dC %dC %dR E\n", tgtcoly,tgtcolx,tgtrow)) ; /* Capture the existing columns and other information before we start to modify the constraint system. Save the shorter column. */ action *s = &actions[nactions] ; nactions++ ; s->row = tgtrow ; s->icolx = tgtcolx ; s->clox = clo[tgtcolx] ; s->cupx = cup[tgtcolx] ; s->costx = cost[tgtcolx] ; s->icoly = tgtcoly ; s->costy = cost[tgtcoly] ; s->rlo = rlo[tgtrow] ; s->coeffx = coeffx ; s->coeffy = coeffy ; s->ncolx = colLengths[tgtcolx] ; s->ncoly = colLengths[tgtcoly] ; if (s->ncoly < s->ncolx) { s->colel = presolve_dupmajor(colCoeffs,rowIndices,colLengths[tgtcoly], colStarts[tgtcoly],tgtrow) ; s->ncolx = 0 ; } else { s->colel = presolve_dupmajor(colCoeffs,rowIndices,colLengths[tgtcolx], colStarts[tgtcolx],tgtrow) ; s->ncoly = 0 ; } /* Move finite bound information from y to x, so that y is implied free. a x + b y = c l1 <= x <= u1 l2 <= y <= u2 l2 <= (c - a x) / b <= u2 b/-a > 0 ==> (b l2 - c) / -a <= x <= (b u2 - c) / -a b/-a < 0 ==> (b u2 - c) / -a <= x <= (b l2 - c) / -a */ { double lo1 = -PRESOLVE_INF ; double up1 = PRESOLVE_INF ; if (-PRESOLVE_INF < clo[tgtcoly]) { if (coeffx*coeffy < 0) lo1 = (coeffy*clo[tgtcoly]-rhs)/-coeffx ; else up1 = (coeffy*clo[tgtcoly]-rhs)/-coeffx ; } if (cup[tgtcoly] < PRESOLVE_INF) { if (coeffx*coeffy < 0) up1 = (coeffy*cup[tgtcoly]-rhs)/-coeffx ; else lo1 = (coeffy*cup[tgtcoly]-rhs)/-coeffx ; } /* Don't forget the objective coefficient. costy y = costy ((c - a x) / b) = (costy c)/b + x (costy -a)/b */ cost[tgtcolx] += (cost[tgtcoly]*-coeffx)/coeffy ; prob->change_bias((cost[tgtcoly]*rhs)/coeffy) ; /* The transfer of bounds could make x infeasible. Patch it up if the problem is minor or if the user was so incautious as to instruct us to ignore it. Prefer an integer value if there's one nearby. If there's nothing to be done, break out of the main loop. */ { double lo2 = CoinMax(clo[tgtcolx],lo1) ; double up2 = CoinMin(cup[tgtcolx],up1) ; if (lo2 > up2) { if (lo2 <= up2+prob->feasibilityTolerance_ || fixInfeasibility) { double nearest = floor(lo2+0.5) ; if (fabs(nearest-lo2) < 2.0*prob->feasibilityTolerance_) { lo2 = nearest ; up2 = nearest ; } else { lo2 = up2 ; } } else { prob->status_ |= 1 ; prob->messageHandler()->message(COIN_PRESOLVE_COLINFEAS, prob->messages()) << tgtcolx << lo2 << up2 << CoinMessageEol ; break ; } } # if PRESOLVE_DEBUG > 2 std::cout << " x(" << tgtcolx << ") lb " << clo[tgtcolx] << " --> " << lo2 << ", ub " << cup[tgtcolx] << " --> " << up2 << std::endl ; # endif clo[tgtcolx] = lo2 ; cup[tgtcolx] = up2 ; /* Do we have a solution to maintain? If so, take a stab at it. If x ends up at bound, prefer to set it nonbasic, but if we're short of basic variables after eliminating y and the logical for the row, make it basic. This code will snap the value of x to bound if it's within the primal feasibility tolerance. */ if (rowstat && sol) { int numberBasic = 0 ; double movement = 0 ; if (prob->columnIsBasic(tgtcolx)) numberBasic++ ; if (prob->columnIsBasic(tgtcoly)) numberBasic++ ; if (prob->rowIsBasic(tgtrow)) numberBasic++ ; if (sol[tgtcolx] <= lo2+ztolzb) { movement = lo2-sol[tgtcolx] ; sol[tgtcolx] = lo2 ; prob->setColumnStatus(tgtcolx, CoinPrePostsolveMatrix::atLowerBound) ; } else if (sol[tgtcolx] >= up2-ztolzb) { movement = up2-sol[tgtcolx] ; sol[tgtcolx] = up2 ; prob->setColumnStatus(tgtcolx, CoinPrePostsolveMatrix::atUpperBound) ; } if (numberBasic > 1) prob->setColumnStatus(tgtcolx,CoinPrePostsolveMatrix::basic) ; /* We need to compensate if x was forced to move. Beyond that, even if x didn't move, we've forced y = (c-ax)/b, and that might not have been true before. So even if x didn't move, y may have moved. Note that the constant term c/b is subtracted out as the constraints are modified, so we don't include it when calculating movement for y. */ if (movement) { const CoinBigIndex kkcsx = colStarts[tgtcolx] ; const CoinBigIndex kkcex = kkcsx+colLengths[tgtcolx] ; for (CoinBigIndex kcol = kkcsx ; kcol < kkcex ; kcol++) { int row = rowIndices[kcol] ; if (rowLengths[row]) acts[row] += movement*colCoeffs[kcol] ; } } movement = ((-coeffx*sol[tgtcolx])/coeffy)-sol[tgtcoly] ; if (movement) { const CoinBigIndex kkcsy = colStarts[tgtcoly] ; const CoinBigIndex kkcey = kkcsy+colLengths[tgtcoly] ; for (CoinBigIndex kcol = kkcsy ; kcol < kkcey ; kcol++) { int row = rowIndices[kcol] ; if (rowLengths[row]) acts[row] += movement*colCoeffs[kcol] ; } } } if (lo2 == up2) fixed[nfixed++] = tgtcolx ; } } /* We're done transferring bounds from y to x, and we've patched up the solution if one existed to patch. One last thing to do before we eliminate column y and the doubleton row: put column x and the entangled rows on the lists of columns and rows to look at in the next round of transforms. */ { prob->addCol(tgtcolx) ; const CoinBigIndex kkcsy = colStarts[tgtcoly] ; const CoinBigIndex kkcey = kkcsy+colLengths[tgtcoly] ; for (CoinBigIndex kcol = kkcsy ; kcol < kkcey ; kcol++) { int row = rowIndices[kcol] ; prob->addRow(row) ; } const CoinBigIndex kkcsx = colStarts[tgtcolx] ; const CoinBigIndex kkcex = kkcsx+colLengths[tgtcolx] ; for (CoinBigIndex kcol = kkcsx ; kcol < kkcex ; kcol++) { int row = rowIndices[kcol] ; prob->addRow(row) ; } } /* Empty tgtrow in the column-major matrix. Deleting the coefficient for (tgtrow,tgtcoly) is a bit costly (given that we're about to drop the whole column), but saves the trouble of checking for it in elim_doubleton. */ presolve_delete_from_col(tgtrow,tgtcolx, colStarts,colLengths,rowIndices,colCoeffs) ; presolve_delete_from_col(tgtrow,tgtcoly, colStarts,colLengths,rowIndices,colCoeffs) ; /* Drop tgtrow in the row-major representation: set the length to 0 and reclaim the major vector space in bulk storage. */ rowLengths[tgtrow] = 0 ; PRESOLVE_REMOVE_LINK(rlink,tgtrow) ; /* Transfer the colx factors to coly. This modifies coefficients in column x as it removes coefficients in column y. */ bool no_mem = elim_doubleton("ELIMD", colStarts,rlo,rup,colCoeffs, rowIndices,colIndices,rowLengths,colLengths, clink,n, rowStarts,rowCoeffs, -coeffx/coeffy, rhs/coeffy, tgtrow,tgtcolx,tgtcoly) ; if (no_mem) throwCoinError("out of memory","doubleton_action::presolve") ; /* Eliminate coly entirely from the col rep. We'll want to groom colx to remove explicit zeros. */ colLengths[tgtcoly] = 0 ; PRESOLVE_REMOVE_LINK(clink, tgtcoly) ; cost[tgtcoly] = 0.0 ; rlo[tgtrow] = 0.0 ; rup[tgtrow] = 0.0 ; zeros[nzeros++] = tgtcolx ; # if PRESOLVE_CONSISTENCY > 0 presolve_consistent(prob) ; presolve_links_ok(prob) ; # endif } /* Tidy up the collected actions and clean up explicit zeros and fixed variables. Don't bother unless we're feasible (status of 0). */ if (nactions && !prob->status_) { # if PRESOLVE_SUMMARY > 0 printf("NDOUBLETONS: %d\n", nactions) ; # endif action *actions1 = new action[nactions] ; CoinMemcpyN(actions, nactions, actions1) ; next = new doubleton_action(nactions, actions1, next) ; if (nzeros) next = drop_zero_coefficients_action::presolve(prob, zeros, nzeros, next) ; if (nfixed) next = remove_fixed_action::presolve(prob, fixed, nfixed, next) ; } deleteAction(actions,action*) ; # if COIN_PRESOLVE_TUNING > 0 if (prob->tuning_) double thisTime = CoinCpuTime() ; # endif # if PRESOLVE_CONSISTENCY > 0 || PRESOLVE_DEBUG > 0 presolve_check_sol(prob) ; # endif # if PRESOLVE_DEBUG > 0 || COIN_PRESOLVE_TUNING > 0 int droppedRows = prob->countEmptyRows()-startEmptyRows ; int droppedColumns = prob->countEmptyCols()-startEmptyColumns ; std::cout << "Leaving doubleton_action::presolve, " << droppedRows << " rows, " << droppedColumns << " columns dropped" ; # if COIN_PRESOLVE_TUNING > 0 std::cout << " in " << thisTime-startTime << "s" ; # endif std::cout << "." << std::endl ; # endif return (next) ; }