/* $Id$ */ // Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #include "CoinPragma.hpp" #include #include "CoinHelperFunctions.hpp" #include "ClpInterior.hpp" #include "ClpMatrixBase.hpp" #include "ClpLsqr.hpp" #include "ClpPdcoBase.hpp" #include "CoinDenseVector.hpp" #include "ClpMessage.hpp" #include "ClpHelperFunctions.hpp" #include "ClpCholeskyDense.hpp" #include "ClpLinearObjective.hpp" #include "ClpQuadraticObjective.hpp" #include #include #include #include //############################################################################# ClpInterior::ClpInterior() : ClpModel() , largestPrimalError_(0.0) , largestDualError_(0.0) , sumDualInfeasibilities_(0.0) , sumPrimalInfeasibilities_(0.0) , worstComplementarity_(0.0) , xsize_(0.0) , zsize_(0.0) , lower_(NULL) , rowLowerWork_(NULL) , columnLowerWork_(NULL) , upper_(NULL) , rowUpperWork_(NULL) , columnUpperWork_(NULL) , cost_(NULL) , rhs_(NULL) , x_(NULL) , y_(NULL) , dj_(NULL) , lsqrObject_(NULL) , pdcoStuff_(NULL) , mu_(0.0) , objectiveNorm_(1.0e-12) , rhsNorm_(1.0e-12) , solutionNorm_(1.0e-12) , dualObjective_(0.0) , primalObjective_(0.0) , diagonalNorm_(1.0e-12) , stepLength_(0.995) , linearPerturbation_(1.0e-12) , diagonalPerturbation_(1.0e-15) , gamma_(0.0) , delta_(0) , targetGap_(1.0e-12) , projectionTolerance_(1.0e-7) , maximumRHSError_(0.0) , maximumBoundInfeasibility_(0.0) , maximumDualError_(0.0) , diagonalScaleFactor_(0.0) , scaleFactor_(1.0) , actualPrimalStep_(0.0) , actualDualStep_(0.0) , smallestInfeasibility_(0.0) , complementarityGap_(0.0) , baseObjectiveNorm_(0.0) , worstDirectionAccuracy_(0.0) , maximumRHSChange_(0.0) , errorRegion_(NULL) , rhsFixRegion_(NULL) , upperSlack_(NULL) , lowerSlack_(NULL) , diagonal_(NULL) , solution_(NULL) , workArray_(NULL) , deltaX_(NULL) , deltaY_(NULL) , deltaZ_(NULL) , deltaW_(NULL) , deltaSU_(NULL) , deltaSL_(NULL) , primalR_(NULL) , dualR_(NULL) , rhsB_(NULL) , rhsU_(NULL) , rhsL_(NULL) , rhsZ_(NULL) , rhsW_(NULL) , rhsC_(NULL) , zVec_(NULL) , wVec_(NULL) , cholesky_(NULL) , numberComplementarityPairs_(0) , numberComplementarityItems_(0) , maximumBarrierIterations_(200) , gonePrimalFeasible_(false) , goneDualFeasible_(false) , algorithm_(-1) { memset(historyInfeasibility_, 0, LENGTH_HISTORY * sizeof(CoinWorkDouble)); solveType_ = 3; // say interior based life form cholesky_ = new ClpCholeskyDense(); // put in placeholder } // Subproblem constructor ClpInterior::ClpInterior(const ClpModel *rhs, int numberRows, const int *whichRow, int numberColumns, const int *whichColumn, bool dropNames, bool dropIntegers) : ClpModel(rhs, numberRows, whichRow, numberColumns, whichColumn, dropNames, dropIntegers) , largestPrimalError_(0.0) , largestDualError_(0.0) , sumDualInfeasibilities_(0.0) , sumPrimalInfeasibilities_(0.0) , worstComplementarity_(0.0) , xsize_(0.0) , zsize_(0.0) , lower_(NULL) , rowLowerWork_(NULL) , columnLowerWork_(NULL) , upper_(NULL) , rowUpperWork_(NULL) , columnUpperWork_(NULL) , cost_(NULL) , rhs_(NULL) , x_(NULL) , y_(NULL) , dj_(NULL) , lsqrObject_(NULL) , pdcoStuff_(NULL) , mu_(0.0) , objectiveNorm_(1.0e-12) , rhsNorm_(1.0e-12) , solutionNorm_(1.0e-12) , dualObjective_(0.0) , primalObjective_(0.0) , diagonalNorm_(1.0e-12) , stepLength_(0.99995) , linearPerturbation_(1.0e-12) , diagonalPerturbation_(1.0e-15) , gamma_(0.0) , delta_(0) , targetGap_(1.0e-12) , projectionTolerance_(1.0e-7) , maximumRHSError_(0.0) , maximumBoundInfeasibility_(0.0) , maximumDualError_(0.0) , diagonalScaleFactor_(0.0) , scaleFactor_(0.0) , actualPrimalStep_(0.0) , actualDualStep_(0.0) , smallestInfeasibility_(0.0) , complementarityGap_(0.0) , baseObjectiveNorm_(0.0) , worstDirectionAccuracy_(0.0) , maximumRHSChange_(0.0) , errorRegion_(NULL) , rhsFixRegion_(NULL) , upperSlack_(NULL) , lowerSlack_(NULL) , diagonal_(NULL) , solution_(NULL) , workArray_(NULL) , deltaX_(NULL) , deltaY_(NULL) , deltaZ_(NULL) , deltaW_(NULL) , deltaSU_(NULL) , deltaSL_(NULL) , primalR_(NULL) , dualR_(NULL) , rhsB_(NULL) , rhsU_(NULL) , rhsL_(NULL) , rhsZ_(NULL) , rhsW_(NULL) , rhsC_(NULL) , zVec_(NULL) , wVec_(NULL) , cholesky_(NULL) , numberComplementarityPairs_(0) , numberComplementarityItems_(0) , maximumBarrierIterations_(200) , gonePrimalFeasible_(false) , goneDualFeasible_(false) , algorithm_(-1) { memset(historyInfeasibility_, 0, LENGTH_HISTORY * sizeof(CoinWorkDouble)); solveType_ = 3; // say interior based life form cholesky_ = new ClpCholeskyDense(); } //----------------------------------------------------------------------------- ClpInterior::~ClpInterior() { gutsOfDelete(); } //############################################################################# /* This does housekeeping */ int ClpInterior::housekeeping() { numberIterations_++; return 0; } // Copy constructor. ClpInterior::ClpInterior(const ClpInterior &rhs) : ClpModel(rhs) , largestPrimalError_(0.0) , largestDualError_(0.0) , sumDualInfeasibilities_(0.0) , sumPrimalInfeasibilities_(0.0) , worstComplementarity_(0.0) , xsize_(0.0) , zsize_(0.0) , lower_(NULL) , rowLowerWork_(NULL) , columnLowerWork_(NULL) , upper_(NULL) , rowUpperWork_(NULL) , columnUpperWork_(NULL) , cost_(NULL) , rhs_(NULL) , x_(NULL) , y_(NULL) , dj_(NULL) , lsqrObject_(NULL) , pdcoStuff_(NULL) , errorRegion_(NULL) , rhsFixRegion_(NULL) , upperSlack_(NULL) , lowerSlack_(NULL) , diagonal_(NULL) , solution_(NULL) , workArray_(NULL) , deltaX_(NULL) , deltaY_(NULL) , deltaZ_(NULL) , deltaW_(NULL) , deltaSU_(NULL) , deltaSL_(NULL) , primalR_(NULL) , dualR_(NULL) , rhsB_(NULL) , rhsU_(NULL) , rhsL_(NULL) , rhsZ_(NULL) , rhsW_(NULL) , rhsC_(NULL) , zVec_(NULL) , wVec_(NULL) , cholesky_(NULL) { gutsOfDelete(); gutsOfCopy(rhs); solveType_ = 3; // say interior based life form } // Copy constructor from model ClpInterior::ClpInterior(const ClpModel &rhs) : ClpModel(rhs) , largestPrimalError_(0.0) , largestDualError_(0.0) , sumDualInfeasibilities_(0.0) , sumPrimalInfeasibilities_(0.0) , worstComplementarity_(0.0) , xsize_(0.0) , zsize_(0.0) , lower_(NULL) , rowLowerWork_(NULL) , columnLowerWork_(NULL) , upper_(NULL) , rowUpperWork_(NULL) , columnUpperWork_(NULL) , cost_(NULL) , rhs_(NULL) , x_(NULL) , y_(NULL) , dj_(NULL) , lsqrObject_(NULL) , pdcoStuff_(NULL) , mu_(0.0) , objectiveNorm_(1.0e-12) , rhsNorm_(1.0e-12) , solutionNorm_(1.0e-12) , dualObjective_(0.0) , primalObjective_(0.0) , diagonalNorm_(1.0e-12) , stepLength_(0.99995) , linearPerturbation_(1.0e-12) , diagonalPerturbation_(1.0e-15) , gamma_(0.0) , delta_(0) , targetGap_(1.0e-12) , projectionTolerance_(1.0e-7) , maximumRHSError_(0.0) , maximumBoundInfeasibility_(0.0) , maximumDualError_(0.0) , diagonalScaleFactor_(0.0) , scaleFactor_(0.0) , actualPrimalStep_(0.0) , actualDualStep_(0.0) , smallestInfeasibility_(0.0) , complementarityGap_(0.0) , baseObjectiveNorm_(0.0) , worstDirectionAccuracy_(0.0) , maximumRHSChange_(0.0) , errorRegion_(NULL) , rhsFixRegion_(NULL) , upperSlack_(NULL) , lowerSlack_(NULL) , diagonal_(NULL) , solution_(NULL) , workArray_(NULL) , deltaX_(NULL) , deltaY_(NULL) , deltaZ_(NULL) , deltaW_(NULL) , deltaSU_(NULL) , deltaSL_(NULL) , primalR_(NULL) , dualR_(NULL) , rhsB_(NULL) , rhsU_(NULL) , rhsL_(NULL) , rhsZ_(NULL) , rhsW_(NULL) , rhsC_(NULL) , zVec_(NULL) , wVec_(NULL) , cholesky_(NULL) , numberComplementarityPairs_(0) , numberComplementarityItems_(0) , maximumBarrierIterations_(200) , gonePrimalFeasible_(false) , goneDualFeasible_(false) , algorithm_(-1) { memset(historyInfeasibility_, 0, LENGTH_HISTORY * sizeof(CoinWorkDouble)); solveType_ = 3; // say interior based life form cholesky_ = new ClpCholeskyDense(); } // Assignment operator. This copies the data ClpInterior & ClpInterior::operator=(const ClpInterior &rhs) { if (this != &rhs) { gutsOfDelete(); ClpModel::operator=(rhs); gutsOfCopy(rhs); } return *this; } void ClpInterior::gutsOfCopy(const ClpInterior &rhs) { lower_ = ClpCopyOfArray(rhs.lower_, numberColumns_ + numberRows_); rowLowerWork_ = lower_ + numberColumns_; columnLowerWork_ = lower_; upper_ = ClpCopyOfArray(rhs.upper_, numberColumns_ + numberRows_); rowUpperWork_ = upper_ + numberColumns_; columnUpperWork_ = upper_; //cost_ = ClpCopyOfArray(rhs.cost_,2*(numberColumns_+numberRows_)); cost_ = ClpCopyOfArray(rhs.cost_, numberColumns_); rhs_ = ClpCopyOfArray(rhs.rhs_, numberRows_); x_ = ClpCopyOfArray(rhs.x_, numberColumns_); y_ = ClpCopyOfArray(rhs.y_, numberRows_); dj_ = ClpCopyOfArray(rhs.dj_, numberColumns_ + numberRows_); lsqrObject_ = rhs.lsqrObject_ != NULL ? new ClpLsqr(*rhs.lsqrObject_) : NULL; pdcoStuff_ = rhs.pdcoStuff_ != NULL ? rhs.pdcoStuff_->clone() : NULL; largestPrimalError_ = rhs.largestPrimalError_; largestDualError_ = rhs.largestDualError_; sumDualInfeasibilities_ = rhs.sumDualInfeasibilities_; sumPrimalInfeasibilities_ = rhs.sumPrimalInfeasibilities_; worstComplementarity_ = rhs.worstComplementarity_; xsize_ = rhs.xsize_; zsize_ = rhs.zsize_; solveType_ = rhs.solveType_; mu_ = rhs.mu_; objectiveNorm_ = rhs.objectiveNorm_; rhsNorm_ = rhs.rhsNorm_; solutionNorm_ = rhs.solutionNorm_; dualObjective_ = rhs.dualObjective_; primalObjective_ = rhs.primalObjective_; diagonalNorm_ = rhs.diagonalNorm_; stepLength_ = rhs.stepLength_; linearPerturbation_ = rhs.linearPerturbation_; diagonalPerturbation_ = rhs.diagonalPerturbation_; gamma_ = rhs.gamma_; delta_ = rhs.delta_; targetGap_ = rhs.targetGap_; projectionTolerance_ = rhs.projectionTolerance_; maximumRHSError_ = rhs.maximumRHSError_; maximumBoundInfeasibility_ = rhs.maximumBoundInfeasibility_; maximumDualError_ = rhs.maximumDualError_; diagonalScaleFactor_ = rhs.diagonalScaleFactor_; scaleFactor_ = rhs.scaleFactor_; actualPrimalStep_ = rhs.actualPrimalStep_; actualDualStep_ = rhs.actualDualStep_; smallestInfeasibility_ = rhs.smallestInfeasibility_; complementarityGap_ = rhs.complementarityGap_; baseObjectiveNorm_ = rhs.baseObjectiveNorm_; worstDirectionAccuracy_ = rhs.worstDirectionAccuracy_; maximumRHSChange_ = rhs.maximumRHSChange_; errorRegion_ = ClpCopyOfArray(rhs.errorRegion_, numberRows_); rhsFixRegion_ = ClpCopyOfArray(rhs.rhsFixRegion_, numberRows_); deltaY_ = ClpCopyOfArray(rhs.deltaY_, numberRows_); upperSlack_ = ClpCopyOfArray(rhs.upperSlack_, numberRows_ + numberColumns_); lowerSlack_ = ClpCopyOfArray(rhs.lowerSlack_, numberRows_ + numberColumns_); diagonal_ = ClpCopyOfArray(rhs.diagonal_, numberRows_ + numberColumns_); deltaX_ = ClpCopyOfArray(rhs.deltaX_, numberRows_ + numberColumns_); deltaZ_ = ClpCopyOfArray(rhs.deltaZ_, numberRows_ + numberColumns_); deltaW_ = ClpCopyOfArray(rhs.deltaW_, numberRows_ + numberColumns_); deltaSU_ = ClpCopyOfArray(rhs.deltaSU_, numberRows_ + numberColumns_); deltaSL_ = ClpCopyOfArray(rhs.deltaSL_, numberRows_ + numberColumns_); primalR_ = ClpCopyOfArray(rhs.primalR_, numberRows_ + numberColumns_); dualR_ = ClpCopyOfArray(rhs.dualR_, numberRows_ + numberColumns_); rhsB_ = ClpCopyOfArray(rhs.rhsB_, numberRows_); rhsU_ = ClpCopyOfArray(rhs.rhsU_, numberRows_ + numberColumns_); rhsL_ = ClpCopyOfArray(rhs.rhsL_, numberRows_ + numberColumns_); rhsZ_ = ClpCopyOfArray(rhs.rhsZ_, numberRows_ + numberColumns_); rhsW_ = ClpCopyOfArray(rhs.rhsW_, numberRows_ + numberColumns_); rhsC_ = ClpCopyOfArray(rhs.rhsC_, numberRows_ + numberColumns_); solution_ = ClpCopyOfArray(rhs.solution_, numberRows_ + numberColumns_); workArray_ = ClpCopyOfArray(rhs.workArray_, numberRows_ + numberColumns_); zVec_ = ClpCopyOfArray(rhs.zVec_, numberRows_ + numberColumns_); wVec_ = ClpCopyOfArray(rhs.wVec_, numberRows_ + numberColumns_); cholesky_ = rhs.cholesky_->clone(); numberComplementarityPairs_ = rhs.numberComplementarityPairs_; numberComplementarityItems_ = rhs.numberComplementarityItems_; maximumBarrierIterations_ = rhs.maximumBarrierIterations_; gonePrimalFeasible_ = rhs.gonePrimalFeasible_; goneDualFeasible_ = rhs.goneDualFeasible_; algorithm_ = rhs.algorithm_; } void ClpInterior::gutsOfDelete() { delete[] lower_; lower_ = NULL; rowLowerWork_ = NULL; columnLowerWork_ = NULL; delete[] upper_; upper_ = NULL; rowUpperWork_ = NULL; columnUpperWork_ = NULL; delete[] cost_; cost_ = NULL; delete[] rhs_; rhs_ = NULL; delete[] x_; x_ = NULL; delete[] y_; y_ = NULL; delete[] dj_; dj_ = NULL; delete lsqrObject_; lsqrObject_ = NULL; //delete pdcoStuff_; // FIXME pdcoStuff_ = NULL; delete[] errorRegion_; errorRegion_ = NULL; delete[] rhsFixRegion_; rhsFixRegion_ = NULL; delete[] deltaY_; deltaY_ = NULL; delete[] upperSlack_; upperSlack_ = NULL; delete[] lowerSlack_; lowerSlack_ = NULL; delete[] diagonal_; diagonal_ = NULL; delete[] deltaX_; deltaX_ = NULL; delete[] deltaZ_; deltaZ_ = NULL; delete[] deltaW_; deltaW_ = NULL; delete[] deltaSU_; deltaSU_ = NULL; delete[] deltaSL_; deltaSL_ = NULL; delete[] primalR_; primalR_ = NULL; delete[] dualR_; dualR_ = NULL; delete[] rhsB_; rhsB_ = NULL; delete[] rhsU_; rhsU_ = NULL; delete[] rhsL_; rhsL_ = NULL; delete[] rhsZ_; rhsZ_ = NULL; delete[] rhsW_; rhsW_ = NULL; delete[] rhsC_; rhsC_ = NULL; delete[] solution_; solution_ = NULL; delete[] workArray_; workArray_ = NULL; delete[] zVec_; zVec_ = NULL; delete[] wVec_; wVec_ = NULL; delete cholesky_; } 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; } void ClpInterior::deleteWorkingData() { int i; if (optimizationDirection_ != 1.0 || objectiveScale_ != 1.0) { CoinWorkDouble scaleC = optimizationDirection_ / objectiveScale_; // and modify all dual signs for (i = 0; i < numberColumns_; i++) reducedCost_[i] = scaleC * dj_[i]; for (i = 0; i < numberRows_; i++) dual_[i] *= scaleC; } if (rowScale_) { CoinWorkDouble scaleR = 1.0 / rhsScale_; for (i = 0; i < numberColumns_; i++) { CoinWorkDouble scaleFactor = columnScale_[i]; CoinWorkDouble valueScaled = columnActivity_[i]; columnActivity_[i] = valueScaled * scaleFactor * scaleR; CoinWorkDouble valueScaledDual = reducedCost_[i]; reducedCost_[i] = valueScaledDual / scaleFactor; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble scaleFactor = rowScale_[i]; CoinWorkDouble valueScaled = rowActivity_[i]; rowActivity_[i] = (valueScaled * scaleR) / scaleFactor; CoinWorkDouble valueScaledDual = dual_[i]; dual_[i] = valueScaledDual * scaleFactor; } } else if (rhsScale_ != 1.0) { CoinWorkDouble scaleR = 1.0 / rhsScale_; for (i = 0; i < numberColumns_; i++) { CoinWorkDouble valueScaled = columnActivity_[i]; columnActivity_[i] = valueScaled * scaleR; } for (i = 0; i < numberRows_; i++) { CoinWorkDouble valueScaled = rowActivity_[i]; rowActivity_[i] = valueScaled * scaleR; } } delete[] cost_; cost_ = NULL; delete[] solution_; solution_ = NULL; delete[] lower_; lower_ = NULL; delete[] upper_; upper_ = NULL; delete[] errorRegion_; errorRegion_ = NULL; delete[] rhsFixRegion_; rhsFixRegion_ = NULL; delete[] deltaY_; deltaY_ = NULL; delete[] upperSlack_; upperSlack_ = NULL; delete[] lowerSlack_; lowerSlack_ = NULL; delete[] diagonal_; diagonal_ = NULL; delete[] deltaX_; deltaX_ = NULL; delete[] workArray_; workArray_ = NULL; delete[] zVec_; zVec_ = NULL; delete[] wVec_; wVec_ = NULL; delete[] dj_; dj_ = NULL; } // Sanity check on input data - returns true if okay bool ClpInterior::sanityCheck() { // bad if empty if (!numberColumns_ || ((!numberRows_ || !matrix_->getNumElements()) && objective_->type() < 2)) { problemStatus_ = emptyProblem(); return false; } int numberBad; CoinWorkDouble largestBound, smallestBound, minimumGap; CoinWorkDouble smallestObj, largestObj; int firstBad; int modifiedBounds = 0; int i; numberBad = 0; firstBad = -1; minimumGap = 1.0e100; smallestBound = 1.0e100; largestBound = 0.0; smallestObj = 1.0e100; largestObj = 0.0; // If bounds are too close - fix CoinWorkDouble fixTolerance = 1.1 * primalTolerance(); for (i = numberColumns_; i < numberColumns_ + numberRows_; i++) { CoinWorkDouble value; value = CoinAbs(cost_[i]); if (value > 1.0e50) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value) { if (value > largestObj) largestObj = value; if (value < smallestObj) smallestObj = value; } value = upper_[i] - lower_[i]; if (value < -primalTolerance()) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value <= fixTolerance) { if (value) { // modify upper_[i] = lower_[i]; modifiedBounds++; } } else { if (value < minimumGap) minimumGap = value; } if (lower_[i] > -1.0e100 && lower_[i]) { value = CoinAbs(lower_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } if (upper_[i] < 1.0e100 && upper_[i]) { value = CoinAbs(upper_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } } if (largestBound) handler_->message(CLP_RIMSTATISTICS3, messages_) << static_cast< double >(smallestBound) << static_cast< double >(largestBound) << static_cast< double >(minimumGap) << CoinMessageEol; minimumGap = 1.0e100; smallestBound = 1.0e100; largestBound = 0.0; for (i = 0; i < numberColumns_; i++) { CoinWorkDouble value; value = CoinAbs(cost_[i]); if (value > 1.0e50) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value) { if (value > largestObj) largestObj = value; if (value < smallestObj) smallestObj = value; } value = upper_[i] - lower_[i]; if (value < -primalTolerance()) { numberBad++; if (firstBad < 0) firstBad = i; } else if (value <= fixTolerance) { if (value) { // modify upper_[i] = lower_[i]; modifiedBounds++; } } else { if (value < minimumGap) minimumGap = value; } if (lower_[i] > -1.0e100 && lower_[i]) { value = CoinAbs(lower_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } if (upper_[i] < 1.0e100 && upper_[i]) { value = CoinAbs(upper_[i]); if (value > largestBound) largestBound = value; if (value < smallestBound) smallestBound = value; } } char rowcol[] = { 'R', 'C' }; if (numberBad) { handler_->message(CLP_BAD_BOUNDS, messages_) << numberBad << rowcol[isColumn(firstBad)] << sequenceWithin(firstBad) << CoinMessageEol; problemStatus_ = 4; return false; } if (modifiedBounds) handler_->message(CLP_MODIFIEDBOUNDS, messages_) << modifiedBounds << CoinMessageEol; handler_->message(CLP_RIMSTATISTICS1, messages_) << static_cast< double >(smallestObj) << static_cast< double >(largestObj) << CoinMessageEol; if (largestBound) handler_->message(CLP_RIMSTATISTICS2, messages_) << static_cast< double >(smallestBound) << static_cast< double >(largestBound) << static_cast< double >(minimumGap) << CoinMessageEol; return true; } /* Loads a problem (the constraints on the rows are given by lower and upper bounds). If a pointer is 0 then the following values are the default:
  • colub: all columns have upper bound infinity
  • collb: all columns have lower bound 0
  • rowub: all rows have upper bound infinity
  • rowlb: all rows have lower bound -infinity
  • obj: all variables have 0 objective coefficient
*/ void ClpInterior::loadProblem(const ClpMatrixBase &matrix, const double *collb, const double *colub, const double *obj, const double *rowlb, const double *rowub, const double *rowObjective) { ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); } void ClpInterior::loadProblem(const CoinPackedMatrix &matrix, const double *collb, const double *colub, const double *obj, const double *rowlb, const double *rowub, const double *rowObjective) { ClpModel::loadProblem(matrix, collb, colub, obj, rowlb, rowub, rowObjective); } /* Just like the other loadProblem() method except that the matrix is given in a standard column major ordered format (without gaps). */ void ClpInterior::loadProblem(const int numcols, const int numrows, const CoinBigIndex *start, const int *index, const double *value, const double *collb, const double *colub, const double *obj, const double *rowlb, const double *rowub, const double *rowObjective) { ClpModel::loadProblem(numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub, rowObjective); } void ClpInterior::loadProblem(const int numcols, const int numrows, const CoinBigIndex *start, const int *index, const double *value, const int *length, const double *collb, const double *colub, const double *obj, const double *rowlb, const double *rowub, const double *rowObjective) { ClpModel::loadProblem(numcols, numrows, start, index, value, length, collb, colub, obj, rowlb, rowub, rowObjective); } // Read an mps file from the given filename int ClpInterior::readMps(const char *filename, bool keepNames, bool ignoreErrors) { int status = ClpModel::readMps(filename, keepNames, ignoreErrors); return status; } #include "ClpPdco.hpp" /* Pdco algorithm - see ClpPdco.hpp for method */ int ClpInterior::pdco() { return ((ClpPdco *)this)->pdco(); } // ** Temporary version int ClpInterior::pdco(ClpPdcoBase *stuff, Options &options, Info &info, Outfo &outfo) { return ((ClpPdco *)this)->pdco(stuff, options, info, outfo); } #include "ClpPredictorCorrector.hpp" // Primal-Dual Predictor-Corrector barrier int ClpInterior::primalDual() { return (static_cast< ClpPredictorCorrector * >(this))->solve(); } 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; } // Set cholesky (and delete present one) void ClpInterior::setCholesky(ClpCholeskyBase *cholesky) { delete cholesky_; cholesky_ = cholesky; } /* Borrow model. This is so we dont have to copy large amounts of data around. It assumes a derived class wants to overwrite an empty model with a real one - while it does an algorithm. This is same as ClpModel one. */ void ClpInterior::borrowModel(ClpModel &otherModel) { ClpModel::borrowModel(otherModel); } /* Return model - updates any scalars */ void ClpInterior::returnModel(ClpModel &otherModel) { ClpModel::returnModel(otherModel); } // Return number fixed to see if worth presolving int ClpInterior::numberFixed() const { int i; int nFixed = 0; for (i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < 1.0e20 || columnLower_[i] > -1.0e20) { if (columnUpper_[i] > columnLower_[i]) { if (fixedOrFree(i)) nFixed++; } } } for (i = 0; i < numberRows_; i++) { if (rowUpper_[i] < 1.0e20 || rowLower_[i] > -1.0e20) { if (rowUpper_[i] > rowLower_[i]) { if (fixedOrFree(i + numberColumns_)) nFixed++; } } } return nFixed; } // fix variables interior says should be void ClpInterior::fixFixed(bool reallyFix) { // Arrays for change in columns and rhs CoinWorkDouble *columnChange = new CoinWorkDouble[numberColumns_]; CoinWorkDouble *rowChange = new CoinWorkDouble[numberRows_]; CoinZeroN(columnChange, numberColumns_); CoinZeroN(rowChange, numberRows_); matrix_->times(1.0, columnChange, rowChange); int i; CoinWorkDouble tolerance = primalTolerance(); for (i = 0; i < numberColumns_; i++) { if (columnUpper_[i] < 1.0e20 || columnLower_[i] > -1.0e20) { if (columnUpper_[i] > columnLower_[i]) { if (fixedOrFree(i)) { if (columnActivity_[i] - columnLower_[i] < columnUpper_[i] - columnActivity_[i]) { CoinWorkDouble change = columnLower_[i] - columnActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) columnUpper_[i] = columnLower_[i]; columnChange[i] = change; columnActivity_[i] = columnLower_[i]; } } else { CoinWorkDouble change = columnUpper_[i] - columnActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) columnLower_[i] = columnUpper_[i]; columnChange[i] = change; columnActivity_[i] = columnUpper_[i]; } } } } } } CoinZeroN(rowChange, numberRows_); matrix_->times(1.0, columnChange, rowChange); // If makes mess of things then don't do CoinWorkDouble newSum = 0.0; for (i = 0; i < numberRows_; i++) { CoinWorkDouble value = rowActivity_[i] + rowChange[i]; if (value > rowUpper_[i] + tolerance) newSum += value - rowUpper_[i] - tolerance; else if (value < rowLower_[i] - tolerance) newSum -= value - rowLower_[i] + tolerance; } if (newSum > 1.0e-5 + 1.5 * sumPrimalInfeasibilities_) { // put back and skip changes for (i = 0; i < numberColumns_; i++) columnActivity_[i] -= columnChange[i]; } else { CoinZeroN(rowActivity_, numberRows_); matrix_->times(1.0, columnActivity_, rowActivity_); if (reallyFix) { for (i = 0; i < numberRows_; i++) { if (rowUpper_[i] < 1.0e20 || rowLower_[i] > -1.0e20) { if (rowUpper_[i] > rowLower_[i]) { if (fixedOrFree(i + numberColumns_)) { if (rowActivity_[i] - rowLower_[i] < rowUpper_[i] - rowActivity_[i]) { CoinWorkDouble change = rowLower_[i] - rowActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) rowUpper_[i] = rowLower_[i]; rowActivity_[i] = rowLower_[i]; } } else { CoinWorkDouble change = rowLower_[i] - rowActivity_[i]; if (CoinAbs(change) < tolerance) { if (reallyFix) rowLower_[i] = rowUpper_[i]; rowActivity_[i] = rowUpper_[i]; } } } } } } } } delete[] rowChange; delete[] columnChange; } /* Modifies djs to allow for quadratic. returns quadratic offset */ CoinWorkDouble ClpInterior::quadraticDjs(CoinWorkDouble *djRegion, const CoinWorkDouble *solution, CoinWorkDouble scaleFactor) { CoinWorkDouble quadraticOffset = 0.0; #ifndef NO_RTTI ClpQuadraticObjective *quadraticObj = (dynamic_cast< ClpQuadraticObjective * >(objective_)); #else ClpQuadraticObjective *quadraticObj = NULL; if (objective_->type() == 2) quadraticObj = (static_cast< ClpQuadraticObjective * >(objective_)); #endif if (quadraticObj) { CoinPackedMatrix *quadratic = quadraticObj->quadraticObjective(); const int *columnQuadratic = quadratic->getIndices(); const CoinBigIndex *columnQuadraticStart = quadratic->getVectorStarts(); const int *columnQuadraticLength = quadratic->getVectorLengths(); double *quadraticElement = quadratic->getMutableElements(); int numberColumns = quadratic->getNumCols(); for (int iColumn = 0; iColumn < numberColumns; iColumn++) { CoinWorkDouble value = 0.0; for (CoinBigIndex j = columnQuadraticStart[iColumn]; j < columnQuadraticStart[iColumn] + columnQuadraticLength[iColumn]; j++) { int jColumn = columnQuadratic[j]; CoinWorkDouble valueJ = solution[jColumn]; CoinWorkDouble elementValue = quadraticElement[j]; //value += valueI*valueJ*elementValue; value += valueJ * elementValue; quadraticOffset += solution[iColumn] * valueJ * elementValue; } djRegion[iColumn] += scaleFactor * value; } } return quadraticOffset; } /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */