/* $Id$ */ // Copyright (C) 2007, 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 "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" #include "ClpSimplex.hpp" #include "ClpConstraintQuadratic.hpp" #include "CoinSort.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpConstraintQuadratic::ClpConstraintQuadratic() : ClpConstraint() { type_ = 0; start_ = NULL; column_ = NULL; coefficient_ = NULL; numberColumns_ = 0; numberCoefficients_ = 0; numberQuadraticColumns_ = 0; } //------------------------------------------------------------------- // Useful Constructor //------------------------------------------------------------------- ClpConstraintQuadratic::ClpConstraintQuadratic(int row, int numberQuadraticColumns, int numberColumns, const CoinBigIndex *start, const int *column, const double *coefficient) : ClpConstraint() { type_ = 0; rowNumber_ = row; numberColumns_ = numberColumns; numberQuadraticColumns_ = numberQuadraticColumns; start_ = CoinCopyOfArray(start, numberQuadraticColumns + 1); CoinBigIndex numberElements = start_[numberQuadraticColumns_]; column_ = CoinCopyOfArray(column, numberElements); coefficient_ = CoinCopyOfArray(coefficient, numberElements); char *mark = new char[numberQuadraticColumns_]; memset(mark, 0, numberQuadraticColumns_); int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn + 1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { assert(jColumn < numberQuadraticColumns_); mark[jColumn] = 1; } mark[iColumn] = 1; } } numberCoefficients_ = 0; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { if (mark[iColumn]) numberCoefficients_++; } delete[] mark; } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpConstraintQuadratic::ClpConstraintQuadratic(const ClpConstraintQuadratic &rhs) : ClpConstraint(rhs) { numberColumns_ = rhs.numberColumns_; numberCoefficients_ = rhs.numberCoefficients_; numberQuadraticColumns_ = rhs.numberQuadraticColumns_; start_ = CoinCopyOfArray(rhs.start_, numberQuadraticColumns_ + 1); CoinBigIndex numberElements = start_[numberQuadraticColumns_]; column_ = CoinCopyOfArray(rhs.column_, numberElements); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberElements); } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpConstraintQuadratic::~ClpConstraintQuadratic() { delete[] start_; delete[] column_; delete[] coefficient_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpConstraintQuadratic & ClpConstraintQuadratic::operator=(const ClpConstraintQuadratic &rhs) { if (this != &rhs) { delete[] start_; delete[] column_; delete[] coefficient_; numberColumns_ = rhs.numberColumns_; numberCoefficients_ = rhs.numberCoefficients_; numberQuadraticColumns_ = rhs.numberQuadraticColumns_; start_ = CoinCopyOfArray(rhs.start_, numberQuadraticColumns_ + 1); CoinBigIndex numberElements = start_[numberQuadraticColumns_]; column_ = CoinCopyOfArray(rhs.column_, numberElements); coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberElements); } return *this; } //------------------------------------------------------------------- // Clone //------------------------------------------------------------------- ClpConstraint *ClpConstraintQuadratic::clone() const { return new ClpConstraintQuadratic(*this); } // Returns gradient int ClpConstraintQuadratic::gradient(const ClpSimplex *model, const double *solution, double *gradient, double &functionValue, double &offset, bool useScaling, bool refresh) const { if (refresh || !lastGradient_) { offset_ = 0.0; functionValue_ = 0.0; if (!lastGradient_) lastGradient_ = new double[numberColumns_]; CoinZeroN(lastGradient_, numberColumns_); bool scaling = (model && model->rowScale() && useScaling); if (!scaling) { int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { double valueI = solution[iColumn]; CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn + 1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { double valueJ = solution[jColumn]; double elementValue = coefficient_[j]; if (iColumn != jColumn) { offset_ -= valueI * valueJ * elementValue; double gradientI = valueJ * elementValue; double gradientJ = valueI * elementValue; lastGradient_[iColumn] += gradientI; lastGradient_[jColumn] += gradientJ; } else { offset_ -= 0.5 * valueI * valueI * elementValue; double gradientI = valueI * elementValue; lastGradient_[iColumn] += gradientI; } } else { // linear part lastGradient_[iColumn] += coefficient_[j]; functionValue_ += valueI * coefficient_[j]; } } } functionValue_ -= offset_; } else { abort(); // 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 = offset_; CoinMemcpyN(lastGradient_, numberColumns_, gradient); return 0; } // Resize constraint void ClpConstraintQuadratic::resize(int newNumberColumns) { if (numberColumns_ != newNumberColumns) { abort(); #ifndef NDEBUG int lastColumn = column_[numberCoefficients_ - 1]; #endif assert(newNumberColumns > lastColumn); delete[] lastGradient_; lastGradient_ = NULL; numberColumns_ = newNumberColumns; } } // Delete columns in constraint void ClpConstraintQuadratic::deleteSome(int numberToDelete, const int *which) { if (numberToDelete) { abort(); int i; char *deleted = new char[numberColumns_]; memset(deleted, 0, numberColumns_ * sizeof(char)); for (i = 0; i < numberToDelete; i++) { int j = which[i]; if (j >= 0 && j < numberColumns_ && !deleted[j]) { deleted[j] = 1; } } int n = 0; for (i = 0; i < numberCoefficients_; i++) { int iColumn = column_[i]; if (!deleted[iColumn]) { column_[n] = iColumn; coefficient_[n++] = coefficient_[i]; } } numberCoefficients_ = n; } } // Scale constraint void ClpConstraintQuadratic::reallyScale(const double *) { abort(); } /* Given a zeroed array sets nonquadratic columns to 1. Returns number of nonlinear columns */ int ClpConstraintQuadratic::markNonlinear(char *which) const { int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn + 1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { assert(jColumn < numberQuadraticColumns_); which[jColumn] = 1; which[iColumn] = 1; } } } int numberCoefficients = 0; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { if (which[iColumn]) numberCoefficients++; } return numberCoefficients; } /* Given a zeroed array sets possible nonzero coefficients to 1. Returns number of nonzeros */ int ClpConstraintQuadratic::markNonzero(char *which) const { int iColumn; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { CoinBigIndex j; for (j = start_[iColumn]; j < start_[iColumn + 1]; j++) { int jColumn = column_[j]; if (jColumn >= 0) { assert(jColumn < numberQuadraticColumns_); which[jColumn] = 1; } which[iColumn] = 1; } } int numberCoefficients = 0; for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { if (which[iColumn]) numberCoefficients++; } return numberCoefficients; } // Number of coefficients int ClpConstraintQuadratic::numberCoefficients() const { return numberCoefficients_; } /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */