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 | |