| 1 | /* $Id: ClpConstraintQuadratic.cpp 1665 2011-01-04 17:55:54Z lou $ */ | 
|---|
| 2 | // Copyright (C) 2007, International Business Machines | 
|---|
| 3 | // Corporation and others.  All Rights Reserved. | 
|---|
| 4 | // This code is licensed under the terms of the Eclipse Public License (EPL). | 
|---|
| 5 |  | 
|---|
| 6 | #include "CoinPragma.hpp" | 
|---|
| 7 | #include "CoinHelperFunctions.hpp" | 
|---|
| 8 | #include "CoinIndexedVector.hpp" | 
|---|
| 9 | #include "ClpSimplex.hpp" | 
|---|
| 10 | #include "ClpConstraintQuadratic.hpp" | 
|---|
| 11 | #include "CoinSort.hpp" | 
|---|
| 12 | //############################################################################# | 
|---|
| 13 | // Constructors / Destructor / Assignment | 
|---|
| 14 | //############################################################################# | 
|---|
| 15 |  | 
|---|
| 16 | //------------------------------------------------------------------- | 
|---|
| 17 | // Default Constructor | 
|---|
| 18 | //------------------------------------------------------------------- | 
|---|
| 19 | ClpConstraintQuadratic::ClpConstraintQuadratic () | 
|---|
| 20 | : ClpConstraint() | 
|---|
| 21 | { | 
|---|
| 22 | type_ = 0; | 
|---|
| 23 | start_ = NULL; | 
|---|
| 24 | column_ = NULL; | 
|---|
| 25 | coefficient_ = NULL; | 
|---|
| 26 | numberColumns_ = 0; | 
|---|
| 27 | numberCoefficients_ = 0; | 
|---|
| 28 | numberQuadraticColumns_ = 0; | 
|---|
| 29 | } | 
|---|
| 30 |  | 
|---|
| 31 | //------------------------------------------------------------------- | 
|---|
| 32 | // Useful Constructor | 
|---|
| 33 | //------------------------------------------------------------------- | 
|---|
| 34 | ClpConstraintQuadratic::ClpConstraintQuadratic (int row, int numberQuadraticColumns , | 
|---|
| 35 | int numberColumns, const CoinBigIndex * start, | 
|---|
| 36 | const int * column, const double * coefficient) | 
|---|
| 37 | : ClpConstraint() | 
|---|
| 38 | { | 
|---|
| 39 | type_ = 0; | 
|---|
| 40 | rowNumber_ = row; | 
|---|
| 41 | numberColumns_ = numberColumns; | 
|---|
| 42 | numberQuadraticColumns_ = numberQuadraticColumns; | 
|---|
| 43 | start_ = CoinCopyOfArray(start, numberQuadraticColumns + 1); | 
|---|
| 44 | int numberElements = start_[numberQuadraticColumns_]; | 
|---|
| 45 | column_ = CoinCopyOfArray(column, numberElements); | 
|---|
| 46 | coefficient_ = CoinCopyOfArray(coefficient, numberElements); | 
|---|
| 47 | char * mark = new char [numberQuadraticColumns_]; | 
|---|
| 48 | memset(mark, 0, numberQuadraticColumns_); | 
|---|
| 49 | int iColumn; | 
|---|
| 50 | for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { | 
|---|
| 51 | CoinBigIndex j; | 
|---|
| 52 | for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { | 
|---|
| 53 | int jColumn = column_[j]; | 
|---|
| 54 | if (jColumn >= 0) { | 
|---|
| 55 | assert (jColumn < numberQuadraticColumns_); | 
|---|
| 56 | mark[jColumn] = 1; | 
|---|
| 57 | } | 
|---|
| 58 | mark[iColumn] = 1; | 
|---|
| 59 | } | 
|---|
| 60 | } | 
|---|
| 61 | numberCoefficients_ = 0; | 
|---|
| 62 | for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { | 
|---|
| 63 | if (mark[iColumn]) | 
|---|
| 64 | numberCoefficients_++; | 
|---|
| 65 | } | 
|---|
| 66 | delete [] mark; | 
|---|
| 67 | } | 
|---|
| 68 |  | 
|---|
| 69 | //------------------------------------------------------------------- | 
|---|
| 70 | // Copy constructor | 
|---|
| 71 | //------------------------------------------------------------------- | 
|---|
| 72 | ClpConstraintQuadratic::ClpConstraintQuadratic (const ClpConstraintQuadratic & rhs) | 
|---|
| 73 | : ClpConstraint(rhs) | 
|---|
| 74 | { | 
|---|
| 75 | numberColumns_ = rhs.numberColumns_; | 
|---|
| 76 | numberCoefficients_ = rhs.numberCoefficients_; | 
|---|
| 77 | numberQuadraticColumns_ = rhs.numberQuadraticColumns_; | 
|---|
| 78 | start_ = CoinCopyOfArray(rhs.start_, numberQuadraticColumns_ + 1); | 
|---|
| 79 | int numberElements = start_[numberQuadraticColumns_]; | 
|---|
| 80 | column_ = CoinCopyOfArray(rhs.column_, numberElements); | 
|---|
| 81 | coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberElements); | 
|---|
| 82 | } | 
|---|
| 83 |  | 
|---|
| 84 |  | 
|---|
| 85 | //------------------------------------------------------------------- | 
|---|
| 86 | // Destructor | 
|---|
| 87 | //------------------------------------------------------------------- | 
|---|
| 88 | ClpConstraintQuadratic::~ClpConstraintQuadratic () | 
|---|
| 89 | { | 
|---|
| 90 | delete [] start_; | 
|---|
| 91 | delete [] column_; | 
|---|
| 92 | delete [] coefficient_; | 
|---|
| 93 | } | 
|---|
| 94 |  | 
|---|
| 95 | //---------------------------------------------------------------- | 
|---|
| 96 | // Assignment operator | 
|---|
| 97 | //------------------------------------------------------------------- | 
|---|
| 98 | ClpConstraintQuadratic & | 
|---|
| 99 | ClpConstraintQuadratic::operator=(const ClpConstraintQuadratic& rhs) | 
|---|
| 100 | { | 
|---|
| 101 | if (this != &rhs) { | 
|---|
| 102 | delete [] start_; | 
|---|
| 103 | delete [] column_; | 
|---|
| 104 | delete [] coefficient_; | 
|---|
| 105 | numberColumns_ = rhs.numberColumns_; | 
|---|
| 106 | numberCoefficients_ = rhs.numberCoefficients_; | 
|---|
| 107 | numberQuadraticColumns_ = rhs.numberQuadraticColumns_; | 
|---|
| 108 | start_ = CoinCopyOfArray(rhs.start_, numberQuadraticColumns_ + 1); | 
|---|
| 109 | int numberElements = start_[numberQuadraticColumns_]; | 
|---|
| 110 | column_ = CoinCopyOfArray(rhs.column_, numberElements); | 
|---|
| 111 | coefficient_ = CoinCopyOfArray(rhs.coefficient_, numberElements); | 
|---|
| 112 | } | 
|---|
| 113 | return *this; | 
|---|
| 114 | } | 
|---|
| 115 | //------------------------------------------------------------------- | 
|---|
| 116 | // Clone | 
|---|
| 117 | //------------------------------------------------------------------- | 
|---|
| 118 | ClpConstraint * ClpConstraintQuadratic::clone() const | 
|---|
| 119 | { | 
|---|
| 120 | return new ClpConstraintQuadratic(*this); | 
|---|
| 121 | } | 
|---|
| 122 |  | 
|---|
| 123 | // Returns gradient | 
|---|
| 124 | int | 
|---|
| 125 | ClpConstraintQuadratic::gradient(const ClpSimplex * model, | 
|---|
| 126 | const double * solution, | 
|---|
| 127 | double * gradient, | 
|---|
| 128 | double & functionValue, | 
|---|
| 129 | double & offset, | 
|---|
| 130 | bool useScaling, | 
|---|
| 131 | bool refresh) const | 
|---|
| 132 | { | 
|---|
| 133 | if (refresh || !lastGradient_) { | 
|---|
| 134 | offset_ = 0.0; | 
|---|
| 135 | functionValue_ = 0.0; | 
|---|
| 136 | if (!lastGradient_) | 
|---|
| 137 | lastGradient_ = new double[numberColumns_]; | 
|---|
| 138 | CoinZeroN(lastGradient_, numberColumns_); | 
|---|
| 139 | bool scaling = (model && model->rowScale() && useScaling); | 
|---|
| 140 | if (!scaling) { | 
|---|
| 141 | int iColumn; | 
|---|
| 142 | for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { | 
|---|
| 143 | double valueI = solution[iColumn]; | 
|---|
| 144 | CoinBigIndex j; | 
|---|
| 145 | for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { | 
|---|
| 146 | int jColumn = column_[j]; | 
|---|
| 147 | if (jColumn >= 0) { | 
|---|
| 148 | double valueJ = solution[jColumn]; | 
|---|
| 149 | double elementValue = coefficient_[j]; | 
|---|
| 150 | if (iColumn != jColumn) { | 
|---|
| 151 | offset_ -= valueI * valueJ * elementValue; | 
|---|
| 152 | double gradientI = valueJ * elementValue; | 
|---|
| 153 | double gradientJ = valueI * elementValue; | 
|---|
| 154 | lastGradient_[iColumn] += gradientI; | 
|---|
| 155 | lastGradient_[jColumn] += gradientJ; | 
|---|
| 156 | } else { | 
|---|
| 157 | offset_ -= 0.5 * valueI * valueI * elementValue; | 
|---|
| 158 | double gradientI = valueI * elementValue; | 
|---|
| 159 | lastGradient_[iColumn] += gradientI; | 
|---|
| 160 | } | 
|---|
| 161 | } else { | 
|---|
| 162 | // linear part | 
|---|
| 163 | lastGradient_[iColumn] += coefficient_[j]; | 
|---|
| 164 | functionValue_ += valueI * coefficient_[j]; | 
|---|
| 165 | } | 
|---|
| 166 | } | 
|---|
| 167 | } | 
|---|
| 168 | functionValue_ -= offset_; | 
|---|
| 169 | } else { | 
|---|
| 170 | abort(); | 
|---|
| 171 | // do scaling | 
|---|
| 172 | const double * columnScale = model->columnScale(); | 
|---|
| 173 | for (int i = 0; i < numberCoefficients_; i++) { | 
|---|
| 174 | int iColumn = column_[i]; | 
|---|
| 175 | double value = solution[iColumn]; // already scaled | 
|---|
| 176 | double coefficient = coefficient_[i] * columnScale[iColumn]; | 
|---|
| 177 | functionValue_ += value * coefficient; | 
|---|
| 178 | lastGradient_[iColumn] = coefficient; | 
|---|
| 179 | } | 
|---|
| 180 | } | 
|---|
| 181 | } | 
|---|
| 182 | functionValue = functionValue_; | 
|---|
| 183 | offset = offset_; | 
|---|
| 184 | CoinMemcpyN(lastGradient_, numberColumns_, gradient); | 
|---|
| 185 | return 0; | 
|---|
| 186 | } | 
|---|
| 187 | // Resize constraint | 
|---|
| 188 | void | 
|---|
| 189 | ClpConstraintQuadratic::resize(int newNumberColumns) | 
|---|
| 190 | { | 
|---|
| 191 | if (numberColumns_ != newNumberColumns) { | 
|---|
| 192 | abort(); | 
|---|
| 193 | #ifndef NDEBUG | 
|---|
| 194 | int lastColumn = column_[numberCoefficients_-1]; | 
|---|
| 195 | #endif | 
|---|
| 196 | assert (newNumberColumns > lastColumn); | 
|---|
| 197 | delete [] lastGradient_; | 
|---|
| 198 | lastGradient_ = NULL; | 
|---|
| 199 | numberColumns_ = newNumberColumns; | 
|---|
| 200 | } | 
|---|
| 201 | } | 
|---|
| 202 | // Delete columns in  constraint | 
|---|
| 203 | void | 
|---|
| 204 | ClpConstraintQuadratic::deleteSome(int numberToDelete, const int * which) | 
|---|
| 205 | { | 
|---|
| 206 | if (numberToDelete) { | 
|---|
| 207 | abort(); | 
|---|
| 208 | int i ; | 
|---|
| 209 | char * deleted = new char[numberColumns_]; | 
|---|
| 210 | memset(deleted, 0, numberColumns_ * sizeof(char)); | 
|---|
| 211 | for (i = 0; i < numberToDelete; i++) { | 
|---|
| 212 | int j = which[i]; | 
|---|
| 213 | if (j >= 0 && j < numberColumns_ && !deleted[j]) { | 
|---|
| 214 | deleted[j] = 1; | 
|---|
| 215 | } | 
|---|
| 216 | } | 
|---|
| 217 | int n = 0; | 
|---|
| 218 | for (i = 0; i < numberCoefficients_; i++) { | 
|---|
| 219 | int iColumn = column_[i]; | 
|---|
| 220 | if (!deleted[iColumn]) { | 
|---|
| 221 | column_[n] = iColumn; | 
|---|
| 222 | coefficient_[n++] = coefficient_[i]; | 
|---|
| 223 | } | 
|---|
| 224 | } | 
|---|
| 225 | numberCoefficients_ = n; | 
|---|
| 226 | } | 
|---|
| 227 | } | 
|---|
| 228 | // Scale constraint | 
|---|
| 229 | void | 
|---|
| 230 | ClpConstraintQuadratic::reallyScale(const double * ) | 
|---|
| 231 | { | 
|---|
| 232 | abort(); | 
|---|
| 233 | } | 
|---|
| 234 | /* Given a zeroed array sets nonquadratic columns to 1. | 
|---|
| 235 | Returns number of nonlinear columns | 
|---|
| 236 | */ | 
|---|
| 237 | int | 
|---|
| 238 | ClpConstraintQuadratic::markNonlinear(char * which) const | 
|---|
| 239 | { | 
|---|
| 240 | int iColumn; | 
|---|
| 241 | for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { | 
|---|
| 242 | CoinBigIndex j; | 
|---|
| 243 | for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { | 
|---|
| 244 | int jColumn = column_[j]; | 
|---|
| 245 | if (jColumn >= 0) { | 
|---|
| 246 | assert (jColumn < numberQuadraticColumns_); | 
|---|
| 247 | which[jColumn] = 1; | 
|---|
| 248 | which[iColumn] = 1; | 
|---|
| 249 | } | 
|---|
| 250 | } | 
|---|
| 251 | } | 
|---|
| 252 | int numberCoefficients = 0; | 
|---|
| 253 | for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { | 
|---|
| 254 | if (which[iColumn]) | 
|---|
| 255 | numberCoefficients++; | 
|---|
| 256 | } | 
|---|
| 257 | return numberCoefficients; | 
|---|
| 258 | } | 
|---|
| 259 | /* Given a zeroed array sets possible nonzero coefficients to 1. | 
|---|
| 260 | Returns number of nonzeros | 
|---|
| 261 | */ | 
|---|
| 262 | int | 
|---|
| 263 | ClpConstraintQuadratic::markNonzero(char * which) const | 
|---|
| 264 | { | 
|---|
| 265 | int iColumn; | 
|---|
| 266 | for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { | 
|---|
| 267 | CoinBigIndex j; | 
|---|
| 268 | for (j = start_[iColumn]; j < start_[iColumn+1]; j++) { | 
|---|
| 269 | int jColumn = column_[j]; | 
|---|
| 270 | if (jColumn >= 0) { | 
|---|
| 271 | assert (jColumn < numberQuadraticColumns_); | 
|---|
| 272 | which[jColumn] = 1; | 
|---|
| 273 | } | 
|---|
| 274 | which[iColumn] = 1; | 
|---|
| 275 | } | 
|---|
| 276 | } | 
|---|
| 277 | int numberCoefficients = 0; | 
|---|
| 278 | for (iColumn = 0; iColumn < numberQuadraticColumns_; iColumn++) { | 
|---|
| 279 | if (which[iColumn]) | 
|---|
| 280 | numberCoefficients++; | 
|---|
| 281 | } | 
|---|
| 282 | return numberCoefficients; | 
|---|
| 283 | } | 
|---|
| 284 | // Number of coefficients | 
|---|
| 285 | int | 
|---|
| 286 | ClpConstraintQuadratic::numberCoefficients() const | 
|---|
| 287 | { | 
|---|
| 288 | return numberCoefficients_; | 
|---|
| 289 | } | 
|---|
| 290 |  | 
|---|