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#ifndef OsiColCut_H
6#define OsiColCut_H
7
8#include <string>
9
10#include "CoinPackedVector.hpp"
11
12#include "OsiCollections.hpp"
13#include "OsiCut.hpp"
14
15/** Column Cut Class
16
17Column Cut Class has:
18 <ul>
19 <li>a sparse vector of column lower bounds
20 <li>a sparse vector of column upper bounds
21 </ul>
22*/
23class OsiColCut : public OsiCut {
24 friend void OsiColCutUnitTest(const OsiSolverInterface * baseSiP,
25 const std::string & mpsDir);
26
27public:
28
29 //----------------------------------------------------------------
30
31 /**@name Setting column bounds */
32 //@{
33 /// Set column lower bounds
34 inline void setLbs(
35 int nElements,
36 const int * colIndices,
37 const double * lbElements );
38
39 /// Set column lower bounds from a packed vector
40 inline void setLbs( const CoinPackedVector & lbs );
41
42 /// Set column upper bounds
43 inline void setUbs(
44 int nElements,
45 const int * colIndices,
46 const double * ubElements );
47
48 /// Set column upper bounds from a packed vector
49 inline void setUbs( const CoinPackedVector & ubs );
50 //@}
51
52 //----------------------------------------------------------------
53
54 /**@name Getting column bounds */
55 //@{
56 /// Get column lower bounds
57 inline const CoinPackedVector & lbs() const;
58 /// Get column upper bounds
59 inline const CoinPackedVector & ubs() const;
60 //@}
61
62 /**@name Comparison operators */
63 //@{
64#if __GNUC__ != 2
65 using OsiCut::operator== ;
66#endif
67 /** equal - true if lower bounds, upper bounds,
68 and OsiCut are equal.
69 */
70 inline virtual bool operator==(const OsiColCut& rhs) const;
71
72#if __GNUC__ != 2
73 using OsiCut::operator!= ;
74#endif
75 /// not equal
76 inline virtual bool operator!=(const OsiColCut& rhs) const;
77 //@}
78
79
80 //----------------------------------------------------------------
81
82 /**@name Sanity checks on cut */
83 //@{
84 /** Returns true if the cut is consistent with respect to itself.
85 This checks to ensure that:
86 <ul>
87 <li>The bound vectors do not have duplicate indices,
88 <li>The bound vectors indices are >=0
89 </ul>
90 */
91 inline virtual bool consistent() const override;
92
93 /** Returns true if cut is consistent with respect to the solver
94 interface's model. This checks to ensure that
95 the lower & upperbound packed vectors:
96 <ul>
97 <li>do not have an index >= the number of column is the model.
98 </ul>
99 */
100 inline virtual bool consistent(const OsiSolverInterface& im) const override;
101
102 /** Returns true if the cut is infeasible with respect to its bounds and the
103 column bounds in the solver interface's models.
104 This checks whether:
105 <ul>
106 <li>the maximum of the new and existing lower bounds is strictly
107 greater than the minimum of the new and existing upper bounds.
108</ul>
109 */
110 inline virtual bool infeasible(const OsiSolverInterface &im) const override;
111 /** Returns infeasibility of the cut with respect to solution
112 passed in i.e. is positive if cuts off that solution.
113 solution is getNumCols() long..
114 */
115 virtual double violated(const double * solution) const override;
116 //@}
117
118 //----------------------------------------------------------------
119
120 /**@name Constructors and destructors */
121 //@{
122 /// Assignment operator
123 OsiColCut & operator=( const OsiColCut& rhs);
124
125 /// Copy constructor
126 OsiColCut ( const OsiColCut &);
127
128 /// Default Constructor
129 OsiColCut ();
130
131 /// Clone
132 virtual OsiColCut * clone() const;
133
134 /// Destructor
135 virtual ~OsiColCut ();
136 //@}
137
138 /**@name Debug stuff */
139 //@{
140 /// Print cuts in collection
141 virtual void print() const override;
142 //@}
143
144private:
145
146 /**@name Private member data */
147 //@{
148 /// Lower bounds
149 CoinPackedVector lbs_;
150 /// Upper bounds
151 CoinPackedVector ubs_;
152 //@}
153
154};
155
156
157
158//-------------------------------------------------------------------
159// Set lower & upper bound vectors
160//-------------------------------------------------------------------
161void OsiColCut::setLbs(
162 int size,
163 const int * colIndices,
164 const double * lbElements )
165{
166 lbs_.setVector(size,colIndices,lbElements);
167}
168//
169void OsiColCut::setUbs(
170 int size,
171 const int * colIndices,
172 const double * ubElements )
173{
174 ubs_.setVector(size,colIndices,ubElements);
175}
176//
177void OsiColCut::setLbs( const CoinPackedVector & lbs )
178{
179 lbs_ = lbs;
180}
181//
182void OsiColCut::setUbs( const CoinPackedVector & ubs )
183{
184 ubs_ = ubs;
185}
186
187//-------------------------------------------------------------------
188// Get Column Lower Bounds and Column Upper Bounds
189//-------------------------------------------------------------------
190const CoinPackedVector & OsiColCut::lbs() const
191{
192 return lbs_;
193}
194//
195const CoinPackedVector & OsiColCut::ubs() const
196{
197 return ubs_;
198}
199
200//----------------------------------------------------------------
201// == operator
202//-------------------------------------------------------------------
203bool
204OsiColCut::operator==(
205 const OsiColCut& rhs) const
206{
207 if ( this->OsiCut::operator!=(rhs) )
208 return false;
209 if ( lbs() != rhs.lbs() )
210 return false;
211 if ( ubs() != rhs.ubs() )
212 return false;
213 return true;
214}
215//
216bool
217OsiColCut::operator!=(
218 const OsiColCut& rhs) const
219{
220 return !( (*this)==rhs );
221}
222
223//----------------------------------------------------------------
224// consistent & infeasible
225//-------------------------------------------------------------------
226bool OsiColCut::consistent() const
227{
228 const CoinPackedVector & lb = lbs();
229 const CoinPackedVector & ub = ubs();
230 // Test for consistent cut.
231 // Are packed vectors consistent?
232 lb.duplicateIndex("consistent", "OsiColCut");
233 ub.duplicateIndex("consistent", "OsiColCut");
234 if ( lb.getMinIndex() < 0 ) return false;
235 if ( ub.getMinIndex() < 0 ) return false;
236 return true;
237}
238//
239bool OsiColCut::consistent(const OsiSolverInterface& im) const
240{
241 const CoinPackedVector & lb = lbs();
242 const CoinPackedVector & ub = ubs();
243
244 // Test for consistent cut.
245 if ( lb.getMaxIndex() >= im.getNumCols() ) return false;
246 if ( ub.getMaxIndex() >= im.getNumCols() ) return false;
247
248 return true;
249}
250
251#if 0
252bool OsiColCut::feasible(const OsiSolverInterface &im) const
253{
254 const double * oldColLb = im.getColLower();
255 const double * oldColUb = im.getColUpper();
256 const CoinPackedVector & cutLbs = lbs();
257 const CoinPackedVector & cutUbs = ubs();
258 int i;
259
260 for ( i=0; i<cutLbs.size(); i++ ) {
261 int colIndx = cutLbs.indices()[i];
262 double newLb;
263 if ( cutLbs.elements()[i] > oldColLb[colIndx] )
264 newLb = cutLbs.elements()[i];
265 else
266 newLb = oldColLb[colIndx];
267
268 double newUb = oldColUb[colIndx];
269 if ( cutUbs.indexExists(colIndx) )
270 if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx];
271 if ( newLb > newUb )
272 return false;
273 }
274
275 for ( i=0; i<cutUbs.size(); i++ ) {
276 int colIndx = cutUbs.indices()[i];
277 double newUb = cutUbs.elements()[i] < oldColUb[colIndx] ? cutUbs.elements()[i] : oldColUb[colIndx];
278 double newLb = oldColLb[colIndx];
279 if ( cutLbs.indexExists(colIndx) )
280 if ( cutLbs[colIndx] > newLb ) newLb = cutLbs[colIndx];
281 if ( newUb < newLb )
282 return false;
283 }
284
285 return true;
286}
287#endif
288
289
290bool OsiColCut::infeasible(const OsiSolverInterface &im) const
291{
292 const double * oldColLb = im.getColLower();
293 const double * oldColUb = im.getColUpper();
294 const CoinPackedVector & cutLbs = lbs();
295 const CoinPackedVector & cutUbs = ubs();
296 int i;
297
298 for ( i=0; i<cutLbs.getNumElements(); i++ ) {
299 int colIndx = cutLbs.getIndices()[i];
300 double newLb= cutLbs.getElements()[i] > oldColLb[colIndx] ?
301 cutLbs.getElements()[i] : oldColLb[colIndx];
302
303 double newUb = oldColUb[colIndx];
304 if ( cutUbs.isExistingIndex(colIndx) )
305 if ( cutUbs[colIndx] < newUb ) newUb = cutUbs[colIndx];
306 if ( newLb > newUb )
307 return true;
308 }
309
310 for ( i=0; i<cutUbs.getNumElements(); i++ ) {
311 int colIndx = cutUbs.getIndices()[i];
312 double newUb = cutUbs.getElements()[i] < oldColUb[colIndx] ?
313 cutUbs.getElements()[i] : oldColUb[colIndx];
314 double newLb = oldColLb[colIndx];
315 if ( cutLbs.isExistingIndex(colIndx) )
316 if ( cutLbs[colIndx] > newLb ) newLb = cutLbs[colIndx];
317 if ( newUb < newLb )
318 return true;
319 }
320
321 return false;
322}
323
324#endif
325