source: trunk/Cbc/src/CbcCutGenerator.hpp @ 2074

Last change on this file since 2074 was 2074, checked in by forrest, 5 years ago

make zerohalf work with threads

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.5 KB
RevLine 
[1271]1/* $Id: CbcCutGenerator.hpp 2074 2014-09-14 17:33:13Z forrest $ */
[2]2// Copyright (C) 2003, International Business Machines
3// Corporation and others.  All Rights Reserved.
[1573]4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
[2]6#ifndef CbcCutGenerator_H
7#define CbcCutGenerator_H
8
9#include "OsiSolverInterface.hpp"
10#include "OsiCuts.hpp"
[238]11#include "CglCutGenerator.hpp"
[1314]12#include "CbcCutModifier.hpp"
[2]13
14class CbcModel;
15class OsiRowCut;
16class OsiRowCutDebugger;
17
18//#############################################################################
19
20/** Interface between Cbc and Cut Generation Library.
21
22  \c CbcCutGenerator is intended to provide an intelligent interface between
23  Cbc and the cutting plane algorithms in the CGL. A \c CbcCutGenerator is
24  bound to a \c CglCutGenerator and to an \c CbcModel. It contains parameters
25  which control when and how the \c generateCuts method of the
26  \c CglCutGenerator will be called.
27
28  The builtin decision criteria available to use when deciding whether to
29  generate cuts are limited: every <i>X</i> nodes, when a solution is found,
30  and when a subproblem is found to be infeasible. The idea is that the class
31  will grow more intelligent with time.
32
33  \todo Add a pointer to function member which will allow a client to install
34        their own decision algorithm to decide whether or not to call the CGL
35        \p generateCuts method. Create a default decision method that looks
36        at the builtin criteria.
37
38  \todo It strikes me as not good that generateCuts contains code specific to
39        individual CGL algorithms. Another set of pointer to function members,
40        so that the client can specify the cut generation method as well as
41        pre- and post-generation methods? Taken a bit further, should this
42        class contain a bunch of pointer to function members, one for each
43        of the places where the cut generator might be referenced?
44        Initialization, root node, search tree node, discovery of solution,
45        and termination all come to mind. Initialization and termination would
46        also be useful for instrumenting cbc.
47*/
48
49class CbcCutGenerator  {
[1286]50
[2]51public:
52
[1286]53    /** \name Generate Cuts */
54    //@{
55    /** Generate cuts for the client model.
[2]56
[1286]57      Evaluate the state of the client model and decide whether to generate cuts.
58      The generated cuts are inserted into and returned in the collection of cuts
59      \p cs.
[2]60
[1286]61      If \p fullScan is !=0, the generator is obliged to call the CGL
62      \c generateCuts routine.  Otherwise, it is free to make a local decision.
63      Negative fullScan says things like at integer solution
64      The current implementation uses \c whenCutGenerator_ to decide.
[2]65
[1286]66      The routine returns true if reoptimisation is needed (because the state of
67      the solver interface has been modified).
[2]68
[1286]69      If node then can find out depth
70    */
71    bool generateCuts( OsiCuts &cs, int fullScan, OsiSolverInterface * solver,
72                       CbcNode * node);
73    //@}
[2]74
75
[1286]76    /**@name Constructors and destructors */
77    //@{
78    /// Default constructor
79    CbcCutGenerator ();
[2]80
[1286]81    /// Normal constructor
82    CbcCutGenerator(CbcModel * model, CglCutGenerator * generator,
83                    int howOften = 1, const char * name = NULL,
84                    bool normal = true, bool atSolution = false,
85                    bool infeasible = false, int howOftenInsub = -100,
86                    int whatDepth = -1, int whatDepthInSub = -1, int switchOffIfLessThan = 0);
[2]87
[1286]88    /// Copy constructor
89    CbcCutGenerator (const CbcCutGenerator &);
[2]90
[1286]91    /// Assignment operator
92    CbcCutGenerator & operator=(const CbcCutGenerator& rhs);
[2]93
[1286]94    /// Destructor
95    ~CbcCutGenerator ();
96    //@}
[2]97
[1286]98    /**@name Gets and sets */
99    //@{
100    /** Set the client model.
[2]101
[1286]102      In addition to setting the client model, refreshModel also calls
103      the \c refreshSolver method of the CglCutGenerator object.
104    */
105    void refreshModel(CbcModel * model);
[2]106
[1286]107    /// return name of generator
108    inline const char * cutGeneratorName() const {
109        return generatorName_;
110    }
[2]111
[1286]112    /// Create C++ lines to show how to tune
113    void generateTuning( FILE * fp);
114    /** Set the cut generation interval
[2]115
[1286]116      Set the number of nodes evaluated between calls to the Cgl object's
117      \p generateCuts routine.
[13]118
[1286]119      If \p value is positive, cuts will always be generated at the specified
120      interval.
121      If \p value is negative, cuts will initially be generated at the specified
122      interval, but Cbc may adjust the value depending on the success of cuts
123      produced by this generator.
[13]124
[1286]125      A value of -100 disables the generator, while a value of -99 means
126      just at root.
127    */
128    void setHowOften(int value) ;
[13]129
[1286]130    /// Get the cut generation interval.
131    inline int howOften() const {
132        return whenCutGenerator_;
133    }
134    /// Get the cut generation interval.in sub tree
135    inline int howOftenInSub() const {
136        return whenCutGeneratorInSub_;
137    }
138    /// Get level of cut inaccuracy (0 means exact e.g. cliques)
139    inline int inaccuracy() const {
140        return inaccuracy_;
141    }
142    /// Set level of cut inaccuracy (0 means exact e.g. cliques)
143    inline void setInaccuracy(int level) {
144        inaccuracy_ = level;
145    }
146
147    /** Set the cut generation depth
148
149      Set the depth criterion for calls to the Cgl object's
150      \p generateCuts routine.  Only active if > 0.
151
152      If whenCutGenerator is positive and this is positive then this overrides.
153      If whenCutGenerator is -1 then this is used as criterion if any cuts
154      were generated at root node.
155      If whenCutGenerator is anything else this is ignored.
156    */
157    void setWhatDepth(int value) ;
158    /// Set the cut generation depth in sub tree
159    void setWhatDepthInSub(int value) ;
160    /// Get the cut generation depth criterion.
161    inline int whatDepth() const {
162        return depthCutGenerator_;
163    }
164    /// Get the cut generation depth criterion.in sub tree
165    inline int whatDepthInSub() const {
166        return depthCutGeneratorInSub_;
167    }
[1880]168    /// Set maximum number of times to enter
169    inline void setMaximumTries(int value)
170    { maximumTries_ = value;}
171    /// Get maximum number of times to enter
172    inline int maximumTries() const
173    { return maximumTries_;}
[1286]174
[1656]175    /// Get switches (for debug)
176    inline int switches() const {
177        return switches_;
178    }
[1286]179    /// Get whether the cut generator should be called in the normal place
180    inline bool normal() const {
181        return (switches_&1) != 0;
182    }
183    /// Set whether the cut generator should be called in the normal place
184    inline void setNormal(bool value) {
185        switches_ &= ~1;
186        switches_ |= value ? 1 : 0;
187    }
188    /// Get whether the cut generator should be called when a solution is found
189    inline bool atSolution() const {
190        return (switches_&2) != 0;
191    }
192    /// Set whether the cut generator should be called when a solution is found
193    inline void setAtSolution(bool value) {
194        switches_ &= ~2;
195        switches_ |= value ? 2 : 0;
196    }
197    /** Get whether the cut generator should be called when the subproblem is
198        found to be infeasible.
199    */
200    inline bool whenInfeasible() const {
201        return (switches_&4) != 0;
202    }
203    /** Set whether the cut generator should be called when the subproblem is
204        found to be infeasible.
205    */
206    inline void setWhenInfeasible(bool value) {
207        switches_ &= ~4;
208        switches_ |= value ? 4 : 0;
209    }
210    /// Get whether the cut generator is being timed
211    inline bool timing() const {
212        return (switches_&64) != 0;
213    }
214    /// Set whether the cut generator is being timed
215    inline void setTiming(bool value) {
216        switches_ &= ~64;
217        switches_ |= value ? 64 : 0;
218        timeInCutGenerator_ = 0.0;
219    }
220    /// Return time taken in cut generator
221    inline double timeInCutGenerator() const {
222        return timeInCutGenerator_;
223    }
224    inline void incrementTimeInCutGenerator(double value) {
225        timeInCutGenerator_ += value;
226    }
227    /// Get the \c CglCutGenerator corresponding to this \c CbcCutGenerator.
228    inline CglCutGenerator * generator() const {
229        return generator_;
230    }
231    /// Number times cut generator entered
232    inline int numberTimesEntered() const {
233        return numberTimes_;
234    }
235    inline void setNumberTimesEntered(int value) {
236        numberTimes_ = value;
237    }
238    inline void incrementNumberTimesEntered(int value = 1) {
239        numberTimes_ += value;
240    }
241    /// Total number of cuts added
242    inline int numberCutsInTotal() const {
243        return numberCuts_;
244    }
245    inline void setNumberCutsInTotal(int value) {
246        numberCuts_ = value;
247    }
248    inline void incrementNumberCutsInTotal(int value = 1) {
249        numberCuts_ += value;
250    }
251    /// Total number of elements added
252    inline int numberElementsInTotal() const {
253        return numberElements_;
254    }
255    inline void setNumberElementsInTotal(int value) {
256        numberElements_ = value;
257    }
258    inline void incrementNumberElementsInTotal(int value = 1) {
259        numberElements_ += value;
260    }
261    /// Total number of column cuts
262    inline int numberColumnCuts() const {
263        return numberColumnCuts_;
264    }
265    inline void setNumberColumnCuts(int value) {
266        numberColumnCuts_ = value;
267    }
268    inline void incrementNumberColumnCuts(int value = 1) {
269        numberColumnCuts_ += value;
270    }
271    /// Total number of cuts active after (at end of n cut passes at each node)
272    inline int numberCutsActive() const {
273        return numberCutsActive_;
274    }
275    inline void setNumberCutsActive(int value) {
276        numberCutsActive_ = value;
277    }
278    inline void incrementNumberCutsActive(int value = 1) {
279        numberCutsActive_ += value;
280    }
281    inline void setSwitchOffIfLessThan(int value) {
282        switchOffIfLessThan_ = value;
283    }
284    inline int switchOffIfLessThan() const {
285        return switchOffIfLessThan_;
286    }
287    /// Say if optimal basis needed
288    inline bool needsOptimalBasis() const {
289        return (switches_&128) != 0;
290    }
291    /// Set if optimal basis needed
292    inline void setNeedsOptimalBasis(bool yesNo) {
293        switches_ &= ~128;
294        switches_ |= yesNo ? 128 : 0;
295    }
296    /// Whether generator MUST be called again if any cuts (i.e. ignore break from loop)
297    inline bool mustCallAgain() const {
298        return (switches_&8) != 0;
299    }
300    /// Set whether generator MUST be called again if any cuts (i.e. ignore break from loop)
301    inline void setMustCallAgain(bool yesNo) {
302        switches_ &= ~8;
303        switches_ |= yesNo ? 8 : 0;
304    }
305    /// Whether generator switched off for moment
306    inline bool switchedOff() const {
307        return (switches_&16) != 0;
308    }
309    /// Set whether generator switched off for moment
310    inline void setSwitchedOff(bool yesNo) {
311        switches_ &= ~16;
312        switches_ |= yesNo ? 16 : 0;
313    }
314    /// Whether last round of cuts did little
315    inline bool ineffectualCuts() const {
316        return (switches_&512) != 0;
317    }
318    /// Set whether last round of cuts did little
319    inline void setIneffectualCuts(bool yesNo) {
320        switches_ &= ~512;
321        switches_ |= yesNo ? 512 : 0;
322    }
323    /// Whether to use if any cuts generated
324    inline bool whetherToUse() const {
325        return (switches_&1024) != 0;
326    }
327    /// Set whether to use if any cuts generated
328    inline void setWhetherToUse(bool yesNo) {
329        switches_ &= ~1024;
330        switches_ |= yesNo ? 1024 : 0;
331    }
[1656]332    /// Whether in must call again mode (or after others)
333    inline bool whetherInMustCallAgainMode() const {
334        return (switches_&2048) != 0;
335    }
336    /// Set whether in must call again mode (or after others)
337    inline void setWhetherInMustCallAgainMode(bool yesNo) {
338        switches_ &= ~2048;
339        switches_ |= yesNo ? 2048 : 0;
340    }
341    /// Whether to call at end
342    inline bool whetherCallAtEnd() const {
343        return (switches_&4096) != 0;
344    }
345    /// Set whether to call at end
346    inline void setWhetherCallAtEnd(bool yesNo) {
347        switches_ &= ~4096;
348        switches_ |= yesNo ? 4096 : 0;
349    }
[2074]350    /// Whether needs refresh on copy
351    inline bool needsRefresh() const {
352        return (switches_&8192) != 0;
353    }
354    /// Set whether needs refresh on copy
355    inline void setNeedsRefresh(bool yesNo) {
356        switches_ &= ~8192;
357        switches_ |= yesNo ? 8192 : 0;
358    }
[1286]359    /// Number of cuts generated at root
360    inline int numberCutsAtRoot() const {
361        return numberCutsAtRoot_;
362    }
363    inline void setNumberCutsAtRoot(int value) {
364        numberCutsAtRoot_ = value;
365    }
366    /// Number of cuts active at root
367    inline int numberActiveCutsAtRoot() const {
368        return numberActiveCutsAtRoot_;
369    }
370    inline void setNumberActiveCutsAtRoot(int value) {
371        numberActiveCutsAtRoot_ = value;
372    }
373    /// Number of short cuts at root
374    inline int numberShortCutsAtRoot() const {
375        return numberShortCutsAtRoot_;
376    }
[1839]377    inline void setNumberShortCutsAtRoot(int value) {
378        numberShortCutsAtRoot_ = value;
379    }
[1286]380    /// Set model
381    inline void setModel(CbcModel * model) {
382        model_ = model;
383    }
384    /// Whether global cuts at root
385    inline bool globalCutsAtRoot() const {
386        return (switches_&32) != 0;
387    }
388    /// Set whether global cuts at root
389    inline void setGlobalCutsAtRoot(bool yesNo) {
390        switches_ &= ~32;
391        switches_ |= yesNo ? 32 : 0;
392    }
393    /// Whether global cuts
394    inline bool globalCuts() const {
395        return (switches_&256) != 0;
396    }
397    /// Set whether global cuts
398    inline void setGlobalCuts(bool yesNo) {
399        switches_ &= ~256;
400        switches_ |= yesNo ? 256 : 0;
401    }
[1839]402    /// Add in statistics from other
403    void addStatistics(const CbcCutGenerator * other);
404    /// Scale back statistics by factor
405    void scaleBackStatistics(int factor);
[1286]406    //@}
[1409]407
408private:
409    /**@name Private gets and sets */
410    //@{
411    //@}
[1286]412    /// Saved cuts
413    OsiCuts savedCuts_;
414    /// Time in cut generator
415    double timeInCutGenerator_;
416    /// The client model
417    CbcModel *model_;
[2]418
[1286]419    // The CglCutGenerator object
420    CglCutGenerator * generator_;
[2]421
[1286]422    /// Name of generator
423    char * generatorName_;
[1271]424
[1286]425    /** Number of nodes between calls to the CglCutGenerator::generateCuts
426       routine.
427    */
428    int whenCutGenerator_;
429    /** Number of nodes between calls to the CglCutGenerator::generateCuts
430       routine in sub tree.
431    */
432    int whenCutGeneratorInSub_;
433    /** If first pass at root produces fewer than this cuts then switch off
434     */
435    int switchOffIfLessThan_;
[2]436
[1286]437    /** Depth at which to call the CglCutGenerator::generateCuts
438       routine (If >0 then overrides when and is called if depth%depthCutGenerator==0).
439    */
440    int depthCutGenerator_;
[13]441
[1286]442    /** Depth at which to call the CglCutGenerator::generateCuts
443       routine (If >0 then overrides when and is called if depth%depthCutGenerator==0).
444       In sub tree.
445    */
446    int depthCutGeneratorInSub_;
[13]447
[1286]448    /// Level of cut inaccuracy (0 means exact e.g. cliques)
449    int inaccuracy_;
450    /// Number times cut generator entered
451    int numberTimes_;
452    /// Total number of cuts added
453    int numberCuts_;
454    /// Total number of elements added
455    int numberElements_;
456    /// Total number of column cuts added
457    int numberColumnCuts_;
458    /// Total number of cuts active after (at end of n cut passes at each node)
459    int numberCutsActive_;
460    /// Number of cuts generated at root
461    int numberCutsAtRoot_;
462    /// Number of cuts active at root
463    int numberActiveCutsAtRoot_;
464    /// Number of short cuts at root
465    int numberShortCutsAtRoot_;
466    /// Switches - see gets and sets
467    int switches_;
[1880]468    /// Maximum number of times to enter
469    int maximumTries_;
[2]470};
471
[1286]472// How often to do if mostly switched off (A)
473# define SCANCUTS 1000
[931]474// How often to do if mostly switched off (probing B)
[1286]475# define SCANCUTS_PROBING 1000
[640]476
[2]477#endif
[1432]478
Note: See TracBrowser for help on using the repository browser.