1 | /* $Id: ClpLinearObjective.cpp 1665 2011-01-04 17:55:54Z lou $ */ |
2 | // Copyright (C) 2003, 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 "CoinIndexedVector.hpp" |
8 | #include "ClpFactorization.hpp" |
9 | #include "ClpSimplex.hpp" |
10 | #include "ClpLinearObjective.hpp" |
11 | #include "CoinHelperFunctions.hpp" |
12 | |
13 | //############################################################################# |
14 | // Constructors / Destructor / Assignment |
15 | //############################################################################# |
16 | |
17 | //------------------------------------------------------------------- |
18 | // Default Constructor |
19 | //------------------------------------------------------------------- |
20 | ClpLinearObjective::ClpLinearObjective () |
21 | : ClpObjective() |
22 | { |
23 | type_ = 1; |
24 | objective_ = NULL; |
25 | numberColumns_ = 0; |
26 | } |
27 | |
28 | //------------------------------------------------------------------- |
29 | // Useful Constructor |
30 | //------------------------------------------------------------------- |
31 | ClpLinearObjective::ClpLinearObjective (const double * objective , |
32 | int numberColumns) |
33 | : ClpObjective() |
34 | { |
35 | type_ = 1; |
36 | numberColumns_ = numberColumns; |
37 | objective_ = CoinCopyOfArray(objective, numberColumns_, 0.0); |
38 | } |
39 | |
40 | //------------------------------------------------------------------- |
41 | // Copy constructor |
42 | //------------------------------------------------------------------- |
43 | ClpLinearObjective::ClpLinearObjective (const ClpLinearObjective & rhs) |
44 | : ClpObjective(rhs) |
45 | { |
46 | numberColumns_ = rhs.numberColumns_; |
47 | objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_); |
48 | } |
49 | /* Subset constructor. Duplicates are allowed |
50 | and order is as given. |
51 | */ |
52 | ClpLinearObjective::ClpLinearObjective (const ClpLinearObjective &rhs, |
53 | int numberColumns, |
54 | const int * whichColumn) |
55 | : ClpObjective(rhs) |
56 | { |
57 | objective_ = NULL; |
58 | numberColumns_ = 0; |
59 | if (numberColumns > 0) { |
60 | // check valid lists |
61 | int numberBad = 0; |
62 | int i; |
63 | for (i = 0; i < numberColumns; i++) |
64 | if (whichColumn[i] < 0 || whichColumn[i] >= rhs.numberColumns_) |
65 | numberBad++; |
66 | if (numberBad) |
67 | throw CoinError("bad column list" , "subset constructor" , |
68 | "ClpLinearObjective" ); |
69 | numberColumns_ = numberColumns; |
70 | objective_ = new double[numberColumns_]; |
71 | for (i = 0; i < numberColumns_; i++) |
72 | objective_[i] = rhs.objective_[whichColumn[i]]; |
73 | } |
74 | } |
75 | |
76 | |
77 | //------------------------------------------------------------------- |
78 | // Destructor |
79 | //------------------------------------------------------------------- |
80 | ClpLinearObjective::~ClpLinearObjective () |
81 | { |
82 | delete [] objective_; |
83 | } |
84 | |
85 | //---------------------------------------------------------------- |
86 | // Assignment operator |
87 | //------------------------------------------------------------------- |
88 | ClpLinearObjective & |
89 | ClpLinearObjective::operator=(const ClpLinearObjective& rhs) |
90 | { |
91 | if (this != &rhs) { |
92 | ClpObjective::operator=(rhs); |
93 | numberColumns_ = rhs.numberColumns_; |
94 | delete [] objective_; |
95 | objective_ = CoinCopyOfArray(rhs.objective_, numberColumns_); |
96 | } |
97 | return *this; |
98 | } |
99 | |
100 | // Returns gradient |
101 | double * |
102 | ClpLinearObjective::gradient(const ClpSimplex * /*model*/, |
103 | const double * /*solution*/, double & offset, |
104 | bool /*refresh*/, |
105 | int /*includeLinear*/) |
106 | { |
107 | // not sure what to do about scaling |
108 | //assert (!model); |
109 | //assert (includeLinear==2); //otherwise need to return all zeros |
110 | offset = 0.0; |
111 | return objective_; |
112 | } |
113 | |
114 | /* Returns reduced gradient.Returns an offset (to be added to current one). |
115 | */ |
116 | double |
117 | ClpLinearObjective::reducedGradient(ClpSimplex * model, double * region, |
118 | bool /*useFeasibleCosts*/) |
119 | { |
120 | int numberRows = model->numberRows(); |
121 | //work space |
122 | CoinIndexedVector * workSpace = model->rowArray(0); |
123 | |
124 | CoinIndexedVector arrayVector; |
125 | arrayVector.reserve(numberRows + 1); |
126 | |
127 | int iRow; |
128 | #ifdef CLP_DEBUG |
129 | workSpace->checkClear(); |
130 | #endif |
131 | double * array = arrayVector.denseVector(); |
132 | int * index = arrayVector.getIndices(); |
133 | int number = 0; |
134 | const double * cost = model->costRegion(); |
135 | //assert (!useFeasibleCosts); |
136 | const int * pivotVariable = model->pivotVariable(); |
137 | for (iRow = 0; iRow < numberRows; iRow++) { |
138 | int iPivot = pivotVariable[iRow]; |
139 | double value = cost[iPivot]; |
140 | if (value) { |
141 | array[iRow] = value; |
142 | index[number++] = iRow; |
143 | } |
144 | } |
145 | arrayVector.setNumElements(number); |
146 | |
147 | int numberColumns = model->numberColumns(); |
148 | |
149 | // Btran basic costs |
150 | double * work = workSpace->denseVector(); |
151 | model->factorization()->updateColumnTranspose(workSpace, &arrayVector); |
152 | ClpFillN(work, numberRows, 0.0); |
153 | // now look at dual solution |
154 | double * rowReducedCost = region + numberColumns; |
155 | double * dual = rowReducedCost; |
156 | double * rowCost = model->costRegion(0); |
157 | for (iRow = 0; iRow < numberRows; iRow++) { |
158 | dual[iRow] = array[iRow]; |
159 | } |
160 | double * dj = region; |
161 | ClpDisjointCopyN(model->costRegion(1), numberColumns, dj); |
162 | model->transposeTimes(-1.0, dual, dj); |
163 | for (iRow = 0; iRow < numberRows; iRow++) { |
164 | // slack |
165 | double value = dual[iRow]; |
166 | value += rowCost[iRow]; |
167 | rowReducedCost[iRow] = value; |
168 | } |
169 | return 0.0; |
170 | } |
171 | /* Returns step length which gives minimum of objective for |
172 | solution + theta * change vector up to maximum theta. |
173 | |
174 | arrays are numberColumns+numberRows |
175 | */ |
176 | double |
177 | ClpLinearObjective::stepLength(ClpSimplex * model, |
178 | const double * solution, |
179 | const double * change, |
180 | double maximumTheta, |
181 | double & currentObj, |
182 | double & predictedObj, |
183 | double & thetaObj) |
184 | { |
185 | const double * cost = model->costRegion(); |
186 | double delta = 0.0; |
187 | int numberRows = model->numberRows(); |
188 | int numberColumns = model->numberColumns(); |
189 | currentObj = 0.0; |
190 | thetaObj = 0.0; |
191 | for (int iColumn = 0; iColumn < numberColumns + numberRows; iColumn++) { |
192 | delta += cost[iColumn] * change[iColumn]; |
193 | currentObj += cost[iColumn] * solution[iColumn]; |
194 | } |
195 | thetaObj = currentObj + delta * maximumTheta; |
196 | predictedObj = currentObj + delta * maximumTheta; |
197 | if (delta < 0.0) { |
198 | return maximumTheta; |
199 | } else { |
200 | printf("odd linear direction %g\n" , delta); |
201 | return 0.0; |
202 | } |
203 | } |
204 | // Return objective value (without any ClpModel offset) (model may be NULL) |
205 | double |
206 | ClpLinearObjective::objectiveValue(const ClpSimplex * model, const double * solution) const |
207 | { |
208 | const double * cost = objective_; |
209 | if (model && model->costRegion()) |
210 | cost = model->costRegion(); |
211 | double currentObj = 0.0; |
212 | for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { |
213 | currentObj += cost[iColumn] * solution[iColumn]; |
214 | } |
215 | return currentObj; |
216 | } |
217 | //------------------------------------------------------------------- |
218 | // Clone |
219 | //------------------------------------------------------------------- |
220 | ClpObjective * ClpLinearObjective::clone() const |
221 | { |
222 | return new ClpLinearObjective(*this); |
223 | } |
224 | /* Subset clone. Duplicates are allowed |
225 | and order is as given. |
226 | */ |
227 | ClpObjective * |
228 | ClpLinearObjective::subsetClone (int numberColumns, |
229 | const int * whichColumns) const |
230 | { |
231 | return new ClpLinearObjective(*this, numberColumns, whichColumns); |
232 | } |
233 | // Resize objective |
234 | void |
235 | ClpLinearObjective::resize(int newNumberColumns) |
236 | { |
237 | if (numberColumns_ != newNumberColumns) { |
238 | int i; |
239 | double * newArray = new double[newNumberColumns]; |
240 | if (objective_) |
241 | CoinMemcpyN(objective_, CoinMin(newNumberColumns, numberColumns_), newArray); |
242 | delete [] objective_; |
243 | objective_ = newArray; |
244 | for (i = numberColumns_; i < newNumberColumns; i++) |
245 | objective_[i] = 0.0; |
246 | numberColumns_ = newNumberColumns; |
247 | } |
248 | |
249 | } |
250 | // Delete columns in objective |
251 | void |
252 | ClpLinearObjective::deleteSome(int numberToDelete, const int * which) |
253 | { |
254 | if (objective_) { |
255 | int i ; |
256 | char * deleted = new char[numberColumns_]; |
257 | int numberDeleted = 0; |
258 | CoinZeroN(deleted, numberColumns_); |
259 | for (i = 0; i < numberToDelete; i++) { |
260 | int j = which[i]; |
261 | if (j >= 0 && j < numberColumns_ && !deleted[j]) { |
262 | numberDeleted++; |
263 | deleted[j] = 1; |
264 | } |
265 | } |
266 | int newNumberColumns = numberColumns_ - numberDeleted; |
267 | double * newArray = new double[newNumberColumns]; |
268 | int put = 0; |
269 | for (i = 0; i < numberColumns_; i++) { |
270 | if (!deleted[i]) { |
271 | newArray[put++] = objective_[i]; |
272 | } |
273 | } |
274 | delete [] objective_; |
275 | objective_ = newArray; |
276 | delete [] deleted; |
277 | numberColumns_ = newNumberColumns; |
278 | } |
279 | } |
280 | // Scale objective |
281 | void |
282 | ClpLinearObjective::reallyScale(const double * columnScale) |
283 | { |
284 | for (int iColumn = 0; iColumn < numberColumns_; iColumn++) { |
285 | objective_[iColumn] *= columnScale[iColumn]; |
286 | } |
287 | } |
288 | |