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 OsiCuts_H
6#define OsiCuts_H
7
8#include "CoinPragma.hpp"
9
10#include <cmath>
11#include <cfloat>
12#include "OsiCollections.hpp"
13#include "OsiRowCut.hpp"
14#include "OsiColCut.hpp"
15#include "CoinFloatEqual.hpp"
16
17/** Collections of row cuts and column cuts
18*/
19class OsiCuts {
20 friend void OsiCutsUnitTest();
21
22public:
23 /**@name Iterator classes
24 */
25 //@{
26 /** Iterator
27
28 This is a class for iterating over the collection of cuts.
29 */
30 class iterator {
31 friend class OsiCuts;
32 public:
33 iterator(OsiCuts& cuts);
34 iterator(const iterator & src);
35 iterator & operator=( const iterator& rhs);
36 ~iterator ();
37 OsiCut* operator*() const { return cutP_; }
38 iterator operator++();
39
40 iterator operator++(int)
41 {
42 iterator temp = *this;
43 ++*this;
44 return temp;
45 }
46
47 bool operator==(const iterator& it) const {
48 return (colCutIndex_+rowCutIndex_)==(it.colCutIndex_+it.rowCutIndex_);
49 }
50
51 bool operator!=(const iterator& it) const {
52 return !((*this)==it);
53 }
54
55 bool operator<(const iterator& it) const {
56 return (colCutIndex_+rowCutIndex_)<(it.colCutIndex_+it.rowCutIndex_);
57 }
58
59 private:
60 iterator();
61 // *THINK* : how to inline these without sticking the code here (ugly...)
62 iterator begin();
63 iterator end();
64 OsiCuts& cuts_;
65 int rowCutIndex_;
66 int colCutIndex_;
67 OsiCut * cutP_;
68 };
69
70 /** Const Iterator
71
72 This is a class for iterating over the collection of cuts.
73 */
74 class const_iterator {
75 friend class OsiCuts;
76 public:
77 typedef std::bidirectional_iterator_tag iterator_category;
78 typedef OsiCut* value_type;
79 typedef size_t difference_type;
80 typedef OsiCut ** pointer;
81 typedef OsiCut *& reference;
82
83 public:
84 const_iterator(const OsiCuts& cuts);
85 const_iterator(const const_iterator & src);
86 const_iterator & operator=( const const_iterator& rhs);
87 ~const_iterator ();
88 const OsiCut* operator*() const { return cutP_; }
89
90 const_iterator operator++();
91
92 const_iterator operator++(int)
93 {
94 const_iterator temp = *this;
95 ++*this;
96 return temp;
97 }
98
99 //hedtke: Visual Studio 2014 asks for "--" operator, so here is one.
100 const_iterator operator--();
101
102 bool operator==(const const_iterator& it) const {
103 return (colCutIndex_+rowCutIndex_)==(it.colCutIndex_+it.rowCutIndex_);
104 }
105
106 bool operator!=(const const_iterator& it) const {
107 return !((*this)==it);
108 }
109
110 bool operator<(const const_iterator& it) const {
111 return (colCutIndex_+rowCutIndex_)<(it.colCutIndex_+it.rowCutIndex_);
112 }
113 private:
114 inline const_iterator();
115 // *THINK* : how to inline these without sticking the code here (ugly...)
116 const_iterator begin();
117 const_iterator end();
118 const OsiCuts * cutsPtr_;
119 int rowCutIndex_;
120 int colCutIndex_;
121 const OsiCut * cutP_;
122 };
123 //@}
124
125 //-------------------------------------------------------------------
126 //
127 // Cuts class definition begins here:
128 //
129 //-------------------------------------------------------------------
130
131 /** \name Inserting a cut into collection */
132 //@{
133 /** \brief Insert a row cut */
134 inline void insert( const OsiRowCut & rc );
135 /** \brief Insert a row cut unless it is a duplicate - cut may get sorted.
136 Duplicate is defined as CoinAbsFltEq says same*/
137 void insertIfNotDuplicate( OsiRowCut & rc , CoinAbsFltEq treatAsSame=CoinAbsFltEq(1.0e-12) );
138 /** \brief Insert a row cut unless it is a duplicate - cut may get sorted.
139 Duplicate is defined as CoinRelFltEq says same*/
140 void insertIfNotDuplicate( OsiRowCut & rc , CoinRelFltEq treatAsSame );
141 /** \brief Insert a column cut */
142 inline void insert( const OsiColCut & cc );
143
144 /** \brief Insert a row cut.
145
146 The OsiCuts object takes control of the cut object.
147 On return, \c rcPtr is NULL.
148 */
149 inline void insert( OsiRowCut * & rcPtr );
150 /** \brief Insert a column cut.
151
152 The OsiCuts object takes control of the cut object.
153 On return \c ccPtr is NULL.
154 */
155 inline void insert( OsiColCut * & ccPtr );
156#if 0
157 inline void insert( OsiCut * & cPtr );
158#endif
159
160 /** \brief Insert a set of cuts */
161 inline void insert(const OsiCuts & cs);
162
163 //@}
164
165 /**@name Number of cuts in collection */
166 //@{
167 /// Number of row cuts in collection
168 inline int sizeRowCuts() const;
169 /// Number of column cuts in collection
170 inline int sizeColCuts() const;
171 /// Number of cuts in collection
172 inline int sizeCuts() const;
173 //@}
174
175 /**@name Debug stuff */
176 //@{
177 /// Print cuts in collection
178 inline void printCuts() const;
179 //@}
180
181 /**@name Get a cut from collection */
182 //@{
183 /// Get pointer to i'th row cut
184 inline OsiRowCut * rowCutPtr(int i);
185 /// Get const pointer to i'th row cut
186 inline const OsiRowCut * rowCutPtr(int i) const;
187 /// Get pointer to i'th column cut
188 inline OsiColCut * colCutPtr(int i);
189 /// Get const pointer to i'th column cut
190 inline const OsiColCut * colCutPtr(int i) const;
191
192 /// Get reference to i'th row cut
193 inline OsiRowCut & rowCut(int i);
194 /// Get const reference to i'th row cut
195 inline const OsiRowCut & rowCut(int i) const;
196 /// Get reference to i'th column cut
197 inline OsiColCut & colCut(int i);
198 /// Get const reference to i'th column cut
199 inline const OsiColCut & colCut(int i) const;
200
201 /// Get const pointer to the most effective cut
202 inline const OsiCut * mostEffectiveCutPtr() const;
203 /// Get pointer to the most effective cut
204 inline OsiCut * mostEffectiveCutPtr();
205 //@}
206
207 /**@name Deleting cut from collection */
208 //@{
209 /// Remove i'th row cut from collection
210 inline void eraseRowCut(int i);
211 /// Remove i'th column cut from collection
212 inline void eraseColCut(int i);
213 /// Get pointer to i'th row cut and remove ptr from collection
214 inline OsiRowCut * rowCutPtrAndZap(int i);
215 /*! \brief Clear all row cuts without deleting them
216
217 Handy in case one wants to use CGL without managing cuts in one of
218 the OSI containers. Client is ultimately responsible for deleting the
219 data structures holding the row cuts.
220 */
221 inline void dumpCuts() ;
222 /*! \brief Selective delete and clear for row cuts.
223
224 Deletes the cuts specified in \p to_erase then clears remaining cuts
225 without deleting them. A hybrid of eraseRowCut(int) and dumpCuts().
226 Client is ultimately responsible for deleting the data structures
227 for row cuts not specified in \p to_erase.
228 */
229 inline void eraseAndDumpCuts(const std::vector<int> &to_erase) ;
230 //@}
231
232 /**@name Sorting collection */
233 //@{
234 /// Cuts with greatest effectiveness are first.
235 inline void sort();
236 //@}
237
238
239 /**@name Iterators
240 Example of using an iterator to sum effectiveness
241 of all cuts in the collection.
242 <pre>
243 double sumEff=0.0;
244 for ( OsiCuts::iterator it=cuts.begin(); it!=cuts.end(); ++it )
245 sumEff+= (*it)->effectiveness();
246 </pre>
247 */
248 //@{
249 /// Get iterator to beginning of collection
250 inline iterator begin() { iterator it(*this); it.begin(); return it; }
251 /// Get const iterator to beginning of collection
252 inline const_iterator begin() const { const_iterator it(*this); it.begin(); return it; }
253 /// Get iterator to end of collection
254 inline iterator end() { iterator it(*this); it.end(); return it; }
255 /// Get const iterator to end of collection
256 inline const_iterator end() const { const_iterator it(*this); it.end(); return it; }
257 //@}
258
259
260 /**@name Constructors and destructors */
261 //@{
262 /// Default constructor
263 OsiCuts ();
264
265 /// Copy constructor
266 OsiCuts ( const OsiCuts &);
267
268 /// Assignment operator
269 OsiCuts & operator=( const OsiCuts& rhs);
270
271 /// Destructor
272 virtual ~OsiCuts ();
273 //@}
274
275private:
276 //*@name Function operator for sorting cuts by efectiveness */
277 //@{
278 class OsiCutCompare
279 {
280 public:
281 /// Function for sorting cuts by effectiveness
282 inline bool operator()(const OsiCut * c1P,const OsiCut * c2P)
283 { return c1P->effectiveness() > c2P->effectiveness(); }
284 };
285 //@}
286
287 /**@name Private methods */
288 //@{
289 /// Copy internal data
290 void gutsOfCopy( const OsiCuts & source );
291 /// Delete internal data
292 void gutsOfDestructor();
293 //@}
294
295 /**@name Private member data */
296 //@{
297 /// Vector of row cuts pointers
298 OsiVectorRowCutPtr rowCutPtrs_;
299 /// Vector of column cuts pointers
300 OsiVectorColCutPtr colCutPtrs_;
301 //@}
302
303};
304
305
306//-------------------------------------------------------------------
307// insert cuts into collection
308//-------------------------------------------------------------------
309void OsiCuts::insert( const OsiRowCut & rc )
310{
311 OsiRowCut * newCutPtr = rc.clone();
312 //assert(dynamic_cast<OsiRowCut*>(newCutPtr) != NULL );
313 rowCutPtrs_.push_back(static_cast<OsiRowCut*>(newCutPtr));
314}
315void OsiCuts::insert( const OsiColCut & cc )
316{
317 OsiColCut * newCutPtr = cc.clone();
318 //assert(dynamic_cast<OsiColCut*>(newCutPtr) != NULL );
319 colCutPtrs_.push_back(static_cast<OsiColCut*>(newCutPtr));
320}
321
322void OsiCuts::insert( OsiRowCut* & rcPtr )
323{
324 rowCutPtrs_.push_back(rcPtr);
325 rcPtr = nullptr;
326}
327void OsiCuts::insert( OsiColCut* &ccPtr )
328{
329 colCutPtrs_.push_back(ccPtr);
330 ccPtr = nullptr;
331}
332#if 0
333void OsiCuts::insert( OsiCut* & cPtr )
334{
335 OsiRowCut * rcPtr = dynamic_cast<OsiRowCut*>(cPtr);
336 if ( rcPtr != NULL ) {
337 insert( rcPtr );
338 cPtr = rcPtr;
339 }
340 else {
341 OsiColCut * ccPtr = dynamic_cast<OsiColCut*>(cPtr);
342 assert( ccPtr != NULL );
343 insert( ccPtr );
344 cPtr = ccPtr;
345 }
346}
347#endif
348
349// LANNEZ SEBASTIEN added Thu May 25 01:22:51 EDT 2006
350void OsiCuts::insert(const OsiCuts & cs)
351{
352 for (OsiCuts::const_iterator it = cs.begin (); it != cs.end (); ++it)
353 {
354 const OsiRowCut * rCut = dynamic_cast <const OsiRowCut * >(*it);
355 const OsiColCut * cCut = dynamic_cast <const OsiColCut * >(*it);
356 assert (rCut || cCut);
357 if (rCut)
358 insert (*rCut);
359 else
360 insert (*cCut);
361 }
362}
363
364//-------------------------------------------------------------------
365// sort
366//-------------------------------------------------------------------
367void OsiCuts::sort()
368{
369 std::sort(colCutPtrs_.begin(),colCutPtrs_.end(),OsiCutCompare());
370 std::sort(rowCutPtrs_.begin(),rowCutPtrs_.end(),OsiCutCompare());
371}
372
373
374//-------------------------------------------------------------------
375// Get number of in collections
376//-------------------------------------------------------------------
377int OsiCuts::sizeRowCuts() const {
378 return static_cast<int>(rowCutPtrs_.size()); }
379int OsiCuts::sizeColCuts() const {
380 return static_cast<int>(colCutPtrs_.size()); }
381int OsiCuts::sizeCuts() const {
382 return static_cast<int>(sizeRowCuts()+sizeColCuts()); }
383
384//----------------------------------------------------------------
385// Get i'th cut from the collection
386//----------------------------------------------------------------
387const OsiRowCut * OsiCuts::rowCutPtr(int i) const { return rowCutPtrs_[i]; }
388const OsiColCut * OsiCuts::colCutPtr(int i) const { return colCutPtrs_[i]; }
389OsiRowCut * OsiCuts::rowCutPtr(int i) { return rowCutPtrs_[i]; }
390OsiColCut * OsiCuts::colCutPtr(int i) { return colCutPtrs_[i]; }
391
392const OsiRowCut & OsiCuts::rowCut(int i) const { return *rowCutPtr(i); }
393const OsiColCut & OsiCuts::colCut(int i) const { return *colCutPtr(i); }
394OsiRowCut & OsiCuts::rowCut(int i) { return *rowCutPtr(i); }
395OsiColCut & OsiCuts::colCut(int i) { return *colCutPtr(i); }
396
397//----------------------------------------------------------------
398// Get most effective cut from collection
399//----------------------------------------------------------------
400const OsiCut * OsiCuts::mostEffectiveCutPtr() const
401{
402 const_iterator b=begin();
403 const_iterator e=end();
404 return *(std::min_element(b,e,OsiCutCompare()));
405}
406OsiCut * OsiCuts::mostEffectiveCutPtr()
407{
408 iterator b=begin();
409 iterator e=end();
410 //return *(std::min_element(b,e,OsiCutCompare()));
411 OsiCut * retVal = nullptr;
412 double maxEff = COIN_DBL_MIN;
413 for ( OsiCuts::iterator it=b; it!=e; ++it ) {
414 if (maxEff < (*it)->effectiveness() ) {
415 maxEff = (*it)->effectiveness();
416 retVal = *it;
417 }
418 }
419 return retVal;
420}
421
422//----------------------------------------------------------------
423// Print all cuts
424//----------------------------------------------------------------
425void
426OsiCuts::printCuts() const
427{
428 // do all column cuts first
429 int i;
430 int numberColCuts=sizeColCuts();
431 for (i=0;i<numberColCuts;i++) {
432 const OsiColCut * cut = colCutPtr(i);
433 cut->print();
434 }
435 int numberRowCuts=sizeRowCuts();
436 for (i=0;i<numberRowCuts;i++) {
437 const OsiRowCut * cut = rowCutPtr(i);
438 cut->print();
439 }
440}
441
442//----------------------------------------------------------------
443// Erase i'th cut from the collection
444//----------------------------------------------------------------
445void OsiCuts::eraseRowCut(int i)
446{
447 delete rowCutPtrs_[i];
448 rowCutPtrs_.erase( rowCutPtrs_.begin()+i );
449}
450void OsiCuts::eraseColCut(int i)
451{
452 delete colCutPtrs_[i];
453 colCutPtrs_.erase( colCutPtrs_.begin()+i );
454}
455/// Get pointer to i'th row cut and remove ptr from collection
456OsiRowCut *
457OsiCuts::rowCutPtrAndZap(int i)
458{
459 OsiRowCut * cut = rowCutPtrs_[i];
460 rowCutPtrs_[i]=nullptr;
461 rowCutPtrs_.erase( rowCutPtrs_.begin()+i );
462 return cut;
463}
464void OsiCuts::dumpCuts()
465{
466 rowCutPtrs_.clear() ;
467}
468void OsiCuts::eraseAndDumpCuts(const std::vector<int> &to_erase)
469{
470 for (unsigned i=0; i<to_erase.size(); i++) {
471 delete rowCutPtrs_[to_erase[i]];
472 }
473 rowCutPtrs_.clear();
474}
475
476
477#endif
478