1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
// $Id: CglTreeInfo.hpp 1201 2014-03-07 17:24:04Z forrest $
// Copyright (C) 2000, International Business Machines
// Corporation and others. All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
#ifndef CglTreeInfo_H
#define CglTreeInfo_H
#include "OsiCuts.hpp"
#include "OsiSolverInterface.hpp"
#include "CoinHelperFunctions.hpp"
class CglStored;
/** Information about where the cut generator is invoked from. */
class CglTreeInfo {
public:
/// The level of the search tree node
int level;
/** How many times the cut generator was already invoked in this search tree
node */
int pass;
/** The number of rows in the original formulation. Some generators may not
want to consider already generated rows when generating new ones. */
int formulation_rows;
/** Options
1 - treat costed integers as important
2 - switch off some stuff as variables semi-integer
4 - set global cut flag if at root node
8 - set global cut flag if at root node and first pass
16 - set global cut flag and make cuts globally valid
32 - last round of cuts did nothing - maybe be more aggressive
64 - in preprocessing stage
128 - looks like solution
256 - want alternate cuts
512 - in sub tree (i.e. parent model)
1024 - in must call again mode or after everything mode
*/
int options;
/// Set true if in tree (to avoid ambiguity at first branch)
bool inTree;
/** Replacement array. Before Branch and Cut it may be beneficial to strengthen rows
rather than adding cuts. If this array is not NULL then the cut generator can
place a pointer to the stronger cut in this array which is number of rows in size.
A null (i.e. zero elements and free rhs) cut indicates that the row is useless
and can be removed.
The calling function can then replace those rows.
*/
OsiRowCut ** strengthenRow;
/// Optional pointer to thread specific random number generator
CoinThreadRandom * randomNumberGenerator;
/// Default constructor
CglTreeInfo ();
/// Copy constructor
CglTreeInfo (
const CglTreeInfo &);
/// Clone
virtual CglTreeInfo * clone() const;
/// Assignment operator
CglTreeInfo &
operator=(
const CglTreeInfo& rhs);
/// Destructor
virtual
~CglTreeInfo ();
/// Take action if cut generator can fix a variable (toValue -1 for down, +1 for up)
virtual bool fixes(int , int , int ,bool) {return false;}
/** Initalizes fixing arrays etc - returns >0 if we want to save info
0 if we don't and -1 if is to be used */
virtual int initializeFixing(const OsiSolverInterface * ) {return 0;}
};
/** Derived class to pick up probing info. */
typedef struct {
//unsigned int oneFixed:1; // nonzero if variable to 1 fixes all
//unsigned int sequence:31; // variable (in matrix) (but also see cliqueRow_)
unsigned int fixes;
} CliqueEntry;
class CglTreeProbingInfo : public CglTreeInfo {
public:
/// Default constructor
CglTreeProbingInfo ();
/// Constructor from model
CglTreeProbingInfo (const OsiSolverInterface * model);
/// Copy constructor
CglTreeProbingInfo (
const CglTreeProbingInfo &);
/// Clone
virtual CglTreeInfo * clone() const;
/// Assignment operator
CglTreeProbingInfo &
operator=(
const CglTreeProbingInfo& rhs);
/// Destructor
virtual
~CglTreeProbingInfo ();
OsiSolverInterface * analyze(const OsiSolverInterface & si, int createSolver=0,
int numberExtraCliques=0,const int * starts=NULL,
const CliqueEntry * entries=NULL,const char * type=NULL);
/** Take action if cut generator can fix a variable
(toValue -1 for down, +1 for up)
Returns true if still room, false if not */
virtual bool fixes(int variable, int toValue, int fixedVariable,bool fixedToLower);
/** Initalizes fixing arrays etc - returns >0 if we want to save info
0 if we don't and -1 if is to be used */
virtual int initializeFixing(const OsiSolverInterface * model) ;
/// Fix entries in a solver using implications
int fixColumns(OsiSolverInterface & si) const;
/// Fix entries in a solver using implications for one variable
int fixColumns(int iColumn, int value, OsiSolverInterface & si) const;
/// Packs down entries
int packDown();
/// Generate cuts from implications
void generateCuts(const OsiSolverInterface & si, OsiCuts & cs,
const CglTreeInfo info) const;
/// Entries for fixing variables
inline CliqueEntry * fixEntries()
{ convert(); return fixEntry_;}
/// Starts of integer variable going to zero
inline int * toZero()
{ convert(); return toZero_;}
/// Starts of integer variable going to one
inline int * toOne()
{ convert(); return toOne_;}
/// List of 0-1 integer variables
inline int * integerVariable() const
{ return integerVariable_;}
/// Backward look up
inline int * backward() const
{ return backward_;}
/// Number of variables
inline int numberVariables() const
{ return numberVariables_;}
/// Number of 0-1 variables
inline int numberIntegers() const
{ return numberIntegers_;}
private:
/// Converts to ordered
void convert();
protected:
/// Entries for fixing variables
CliqueEntry * fixEntry_;
/// Starts of integer variable going to zero
int * toZero_;
/// Starts of integer variable going to one
int * toOne_;
/// List of 0-1 integer variables
int * integerVariable_;
/// Backward look up
int * backward_;
/// Entries for fixing variable when collecting
int * fixingEntry_;
/// Number of variables
int numberVariables_;
/// Number of 0-1 variables
int numberIntegers_;
/// Maximum number in fixEntry_
int maximumEntries_;
/// Number entries in fixingEntry_ (and fixEntry_) or -2 if correct style
int numberEntries_;
};
inline int sequenceInCliqueEntry(const CliqueEntry & cEntry)
{ return cEntry.fixes&0x7fffffff;}
inline void setSequenceInCliqueEntry(CliqueEntry & cEntry,int sequence)
{ cEntry.fixes = sequence|(cEntry.fixes&0x80000000);}
inline bool oneFixesInCliqueEntry(const CliqueEntry & cEntry)
{ return (cEntry.fixes&0x80000000)!=0;}
inline void setOneFixesInCliqueEntry(CliqueEntry & cEntry,bool oneFixes)
{ cEntry.fixes = (oneFixes ? 0x80000000 : 0)|(cEntry.fixes&0x7fffffff);}
#endif
|