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// //-------------------------------------------------------------------
19double OsiRowCut::lb() const { return lb_; }
20
21void OsiRowCut::setLb(double lb) { lb_ = lb; }
22
23double OsiRowCut::ub() const { return ub_; }
24
25void OsiRowCut::setUb(double ub) { ub_ = ub; }
26
27//-------------------------------------------------------------------
28// Set row elements
29//-------------------------------------------------------------------
30void OsiRowCut::setRow(int size,
31 const int* colIndices, const double* elements,
32 bool testForDuplicateIndex)
33{
34 row_.setVector(size, colIndices, elements, testForDuplicateIndex);
35}
36
37void OsiRowCut::setRow( const CoinPackedVector & v )
38{
39 row_ = v;
40}
41
42//-------------------------------------------------------------------
43// Get the row
44//-------------------------------------------------------------------
45const CoinPackedVector & OsiRowCut::row() const
46{
47 return row_;
48}
49
50//-------------------------------------------------------------------
51// Get the row for changing
52//-------------------------------------------------------------------
53CoinPackedVector & OsiRowCut::mutableRow()
54{
55 return row_;
56}
57
58//----------------------------------------------------------------
59// == operator
60//-------------------------------------------------------------------
61bool
62OsiRowCut::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
72bool
73OsiRowCut::operator!=(const OsiRowCut& rhs) const
74{
75 return !( (*this)==rhs );
76}
77
78
79//----------------------------------------------------------------
80// consistent & infeasible
81//-------------------------------------------------------------------
82bool 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
90bool 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
98bool 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*/
110double
111OsiRowCut::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//-------------------------------------------------------------------
133char 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
142double 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
151double 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//-------------------------------------------------------------------
163OsiRowCut::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
177OsiRowCut::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//-------------------------------------------------------------------
189OsiRowCut::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//----------------------------------------------------------------
202OsiRowCut * OsiRowCut::clone() const
203{ return (new OsiRowCut(*this)); }
204
205
206//-------------------------------------------------------------------
207// Destructor
208//-------------------------------------------------------------------
209OsiRowCut::~OsiRowCut ()
210{
211 // Nothing to do here
212}
213
214//----------------------------------------------------------------
215// Assignment operator
216//-------------------------------------------------------------------
217OsiRowCut &
218OsiRowCut::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
233void
234OsiRowCut::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//-------------------------------------------------------------------
259OsiRowCut2::OsiRowCut2(int row) :
260 OsiRowCut(),
261 whichRow_(row)
262{
263 // nothing to do here
264}
265
266//-------------------------------------------------------------------
267// Copy constructor
268//-------------------------------------------------------------------
269OsiRowCut2::OsiRowCut2(const OsiRowCut2 & source) :
270 OsiRowCut(source),
271 whichRow_(source.whichRow_)
272{
273 // Nothing to do here
274}
275
276
277//----------------------------------------------------------------
278// Clone
279//----------------------------------------------------------------
280OsiRowCut * OsiRowCut2::clone() const
281{ return (new OsiRowCut2(*this)); }
282
283
284//-------------------------------------------------------------------
285// Destructor
286//-------------------------------------------------------------------
287OsiRowCut2::~OsiRowCut2 ()
288{
289 // Nothing to do here
290}
291
292//----------------------------------------------------------------
293// Assignment operator
294//-------------------------------------------------------------------
295OsiRowCut2 &
296OsiRowCut2::operator=(const OsiRowCut2& rhs)
297{
298 if ( this != &rhs ) {
299 OsiRowCut::operator = (rhs);
300 whichRow_ = rhs.whichRow_;
301 }
302 return *this;
303}
304