1 | // Copyright (C) 2000, International Business Machines |
2 | // Corporation and others. All Rights Reserved. |
3 | // This code is licensed under the terms of the Eclipse Public License (EPL). |
4 | |
5 | #include <cfloat> |
6 | #include <cstdlib> |
7 | #include <cstdio> |
8 | #include <iostream> |
9 | |
10 | #include "CoinPragma.hpp" |
11 | #include "CoinFinite.hpp" |
12 | #include "OsiRowCut.hpp" |
13 | |
14 | #ifndef OSI_INLINE_ROWCUT_METHODS |
15 | |
16 | // //------------------------------------------------------------------- |
17 | // // Set/Get lower & upper bounds |
18 | // //------------------------------------------------------------------- |
19 | double OsiRowCut::lb() const { return lb_; } |
20 | |
21 | void OsiRowCut::setLb(double lb) { lb_ = lb; } |
22 | |
23 | double OsiRowCut::ub() const { return ub_; } |
24 | |
25 | void OsiRowCut::setUb(double ub) { ub_ = ub; } |
26 | |
27 | //------------------------------------------------------------------- |
28 | // Set row elements |
29 | //------------------------------------------------------------------- |
30 | void OsiRowCut::setRow(int size, |
31 | const int* colIndices, const double* elements, |
32 | bool testForDuplicateIndex) |
33 | { |
34 | row_.setVector(size, colIndices, elements, testForDuplicateIndex); |
35 | } |
36 | |
37 | void OsiRowCut::setRow( const CoinPackedVector & v ) |
38 | { |
39 | row_ = v; |
40 | } |
41 | |
42 | //------------------------------------------------------------------- |
43 | // Get the row |
44 | //------------------------------------------------------------------- |
45 | const CoinPackedVector & OsiRowCut::row() const |
46 | { |
47 | return row_; |
48 | } |
49 | |
50 | //------------------------------------------------------------------- |
51 | // Get the row for changing |
52 | //------------------------------------------------------------------- |
53 | CoinPackedVector & OsiRowCut::mutableRow() |
54 | { |
55 | return row_; |
56 | } |
57 | |
58 | //---------------------------------------------------------------- |
59 | // == operator |
60 | //------------------------------------------------------------------- |
61 | bool |
62 | OsiRowCut::operator==(const OsiRowCut& rhs) const |
63 | { |
64 | if ( this->OsiCut::operator!=(rhs) ) return false; |
65 | if ( row() != rhs.row() ) return false; |
66 | if ( lb() != rhs.lb() ) return false; |
67 | if ( ub() != rhs.ub() ) return false; |
68 | |
69 | return true; |
70 | } |
71 | |
72 | bool |
73 | OsiRowCut::operator!=(const OsiRowCut& rhs) const |
74 | { |
75 | return !( (*this)==rhs ); |
76 | } |
77 | |
78 | |
79 | //---------------------------------------------------------------- |
80 | // consistent & infeasible |
81 | //------------------------------------------------------------------- |
82 | bool OsiRowCut::consistent() const |
83 | { |
84 | const CoinPackedVector& r = row(); |
85 | r.duplicateIndex("consistent" , "OsiRowCut" ); |
86 | if ( r.getMinIndex() < 0 ) return false; |
87 | return true; |
88 | } |
89 | |
90 | bool OsiRowCut::consistent(const OsiSolverInterface& im) const |
91 | { |
92 | const CoinPackedVector& r = row(); |
93 | if ( r.getMaxIndex() >= im.getNumCols() ) return false; |
94 | |
95 | return true; |
96 | } |
97 | |
98 | bool OsiRowCut::infeasible(const OsiSolverInterface &) const |
99 | { |
100 | if ( lb() > ub() ) return true; |
101 | |
102 | return false; |
103 | } |
104 | |
105 | #endif |
106 | /* Returns infeasibility of the cut with respect to solution |
107 | passed in i.e. is positive if cuts off that solution. |
108 | solution is getNumCols() long.. |
109 | */ |
110 | double |
111 | OsiRowCut::violated(const double * solution) const |
112 | { |
113 | int i; |
114 | double sum = 0.0; |
115 | const int* column = row_.getIndices(); |
116 | int number = row_.getNumElements(); |
117 | const double* element = row_.getElements(); |
118 | for ( i = 0; i < number; i++ ) { |
119 | int colIndx = column[i]; |
120 | sum += solution[colIndx] * element[i]; |
121 | } |
122 | if ( sum > ub_ ) |
123 | return sum-ub_; |
124 | else if ( sum < lb_ ) |
125 | return lb_-sum; |
126 | else |
127 | return 0.0; |
128 | } |
129 | |
130 | //------------------------------------------------------------------- |
131 | // Row sense, rhs, range |
132 | //------------------------------------------------------------------- |
133 | char OsiRowCut::sense() const |
134 | { |
135 | if ( lb_ == ub_ ) return 'E'; |
136 | else if ( lb_ == -COIN_DBL_MAX && ub_ == COIN_DBL_MAX ) return 'N'; |
137 | else if ( lb_ == -COIN_DBL_MAX ) return 'L'; |
138 | else if ( ub_ == COIN_DBL_MAX ) return 'G'; |
139 | else return 'R'; |
140 | } |
141 | |
142 | double OsiRowCut::rhs() const |
143 | { |
144 | if ( lb_ == ub_ ) return ub_; |
145 | else if ( lb_ == -COIN_DBL_MAX && ub_ == COIN_DBL_MAX ) return 0.0; |
146 | else if ( lb_ == -COIN_DBL_MAX ) return ub_; |
147 | else if ( ub_ == COIN_DBL_MAX ) return lb_; |
148 | else return ub_; |
149 | } |
150 | |
151 | double OsiRowCut::range() const |
152 | { |
153 | if ( lb_ == ub_ ) return 0.0; |
154 | else if ( lb_ == -COIN_DBL_MAX && ub_ == COIN_DBL_MAX ) return 0.0; |
155 | else if ( lb_ == -COIN_DBL_MAX ) return 0.0; |
156 | else if ( ub_ == COIN_DBL_MAX ) return 0.0; |
157 | else return ub_ - lb_; |
158 | } |
159 | |
160 | //------------------------------------------------------------------- |
161 | // Default Constructor |
162 | //------------------------------------------------------------------- |
163 | OsiRowCut::OsiRowCut () : OsiCut(), |
164 | row_(), |
165 | lb_(-COIN_DBL_MAX), |
166 | ub_( COIN_DBL_MAX) |
167 | { |
168 | //#ifdef NDEBUG |
169 | //row_.setTestForDuplicateIndex(false); |
170 | //#endif |
171 | } |
172 | |
173 | //------------------------------------------------------------------- |
174 | // Ownership constructor |
175 | //------------------------------------------------------------------- |
176 | |
177 | OsiRowCut::OsiRowCut(double cutlb, double cutub, |
178 | int capacity, int size, |
179 | int *&colIndices, double *&elements): |
180 | OsiCut(), |
181 | row_(capacity, size, colIndices, elements), |
182 | lb_(cutlb), |
183 | ub_(cutub) |
184 | {} |
185 | |
186 | //------------------------------------------------------------------- |
187 | // Copy constructor |
188 | //------------------------------------------------------------------- |
189 | OsiRowCut::OsiRowCut (const OsiRowCut & source) : |
190 | OsiCut(source), |
191 | row_(source.row_), |
192 | lb_(source.lb_), |
193 | ub_(source.ub_) |
194 | { |
195 | // Nothing to do here |
196 | } |
197 | |
198 | |
199 | //---------------------------------------------------------------- |
200 | // Clone |
201 | //---------------------------------------------------------------- |
202 | OsiRowCut * OsiRowCut::clone() const |
203 | { return (new OsiRowCut(*this)); } |
204 | |
205 | |
206 | //------------------------------------------------------------------- |
207 | // Destructor |
208 | //------------------------------------------------------------------- |
209 | OsiRowCut::~OsiRowCut () |
210 | { |
211 | // Nothing to do here |
212 | } |
213 | |
214 | //---------------------------------------------------------------- |
215 | // Assignment operator |
216 | //------------------------------------------------------------------- |
217 | OsiRowCut & |
218 | OsiRowCut::operator=(const OsiRowCut& rhs) |
219 | { |
220 | if ( this != &rhs ) { |
221 | OsiCut::operator=(rhs); |
222 | row_ = rhs.row_; |
223 | lb_ = rhs.lb_; |
224 | ub_ = rhs.ub_; |
225 | } |
226 | return *this; |
227 | } |
228 | |
229 | //---------------------------------------------------------------- |
230 | // Print |
231 | //------------------------------------------------------------------- |
232 | |
233 | void |
234 | OsiRowCut::print() const |
235 | { |
236 | int i; |
237 | std::cout << "Row cut has " << row_.getNumElements() |
238 | << " elements" ; |
239 | if ( lb_ < -1.0e20 && ub_<1.0e20 ) |
240 | std::cout << " with upper rhs of " << ub_; |
241 | else if ( lb_ > -1.0e20 && ub_ > 1.0e20 ) |
242 | std::cout << " with lower rhs of " << lb_; |
243 | else |
244 | std::cout << " !!! with lower, upper rhs of " << lb_ << " and " << ub_; |
245 | std::cout << std::endl; |
246 | for ( i = 0; i < row_.getNumElements(); i++ ) { |
247 | int colIndx = row_.getIndices()[i]; |
248 | double element = row_.getElements()[i]; |
249 | if ( i > 0 && element > 0 ) |
250 | std::cout << " +" ; |
251 | std::cout << element << " * x" << colIndx << " " ; |
252 | } |
253 | std::cout << std::endl; |
254 | } |
255 | |
256 | //------------------------------------------------------------------- |
257 | // Default Constructor |
258 | //------------------------------------------------------------------- |
259 | OsiRowCut2::OsiRowCut2(int row) : |
260 | OsiRowCut(), |
261 | whichRow_(row) |
262 | { |
263 | // nothing to do here |
264 | } |
265 | |
266 | //------------------------------------------------------------------- |
267 | // Copy constructor |
268 | //------------------------------------------------------------------- |
269 | OsiRowCut2::OsiRowCut2(const OsiRowCut2 & source) : |
270 | OsiRowCut(source), |
271 | whichRow_(source.whichRow_) |
272 | { |
273 | // Nothing to do here |
274 | } |
275 | |
276 | |
277 | //---------------------------------------------------------------- |
278 | // Clone |
279 | //---------------------------------------------------------------- |
280 | OsiRowCut * OsiRowCut2::clone() const |
281 | { return (new OsiRowCut2(*this)); } |
282 | |
283 | |
284 | //------------------------------------------------------------------- |
285 | // Destructor |
286 | //------------------------------------------------------------------- |
287 | OsiRowCut2::~OsiRowCut2 () |
288 | { |
289 | // Nothing to do here |
290 | } |
291 | |
292 | //---------------------------------------------------------------- |
293 | // Assignment operator |
294 | //------------------------------------------------------------------- |
295 | OsiRowCut2 & |
296 | OsiRowCut2::operator=(const OsiRowCut2& rhs) |
297 | { |
298 | if ( this != &rhs ) { |
299 | OsiRowCut::operator = (rhs); |
300 | whichRow_ = rhs.whichRow_; |
301 | } |
302 | return *this; |
303 | } |
304 | |