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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
// $Id: CbcObject.hpp 1899 2013-04-09 18:12:08Z stefan $
// Copyright (C) 2002, International Business Machines
// Corporation and others. All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
// Edwin 11/12/2009 carved from CbcBranchBase
#ifndef CbcObject_H
#define CbcObject_H
#include <string>
#include <vector>
#include "OsiBranchingObject.hpp"
class OsiSolverInterface;
class OsiSolverBranch;
class CbcModel;
class CbcNode;
class CbcNodeInfo;
class CbcBranchingObject;
class OsiChooseVariable;
class CbcObjectUpdateData;
//#############################################################################
/** Abstract base class for `objects'.
It now just has stuff that OsiObject does not have
The branching model used in Cbc is based on the idea of an <i>object</i>.
In the abstract, an object is something that has a feasible region, can be
evaluated for infeasibility, can be branched on (<i>i.e.</i>, there's some
constructive action to be taken to move toward feasibility), and allows
comparison of the effect of branching.
This class (CbcObject) is the base class for an object. To round out the
branching model, the class CbcBranchingObject describes how to perform a
branch, and the class CbcBranchDecision describes how to compare two
CbcBranchingObjects.
To create a new type of object you need to provide three methods:
#infeasibility(), #feasibleRegion(), and #createCbcBranch(), described below.
This base class is primarily virtual to allow for any form of structure.
Any form of discontinuity is allowed.
\todo The notion that all branches are binary (two arms) is wired into the
implementation of CbcObject, CbcBranchingObject, and
CbcBranchDecision. Changing this will require a moderate amount of
recoding.
*/
// This can be used if object wants to skip strong branching
typedef struct {
CbcBranchingObject * possibleBranch; // what a branch would do
double upMovement; // cost going up (and initial away from feasible)
double downMovement; // cost going down
int numIntInfeasUp ; // without odd ones
int numObjInfeasUp ; // just odd ones
bool finishedUp; // true if solver finished
int numItersUp ; // number of iterations in solver
int numIntInfeasDown ; // without odd ones
int numObjInfeasDown ; // just odd ones
bool finishedDown; // true if solver finished
int numItersDown; // number of iterations in solver
int objectNumber; // Which object it is
int fix; // 0 if no fix, 1 if we can fix up, -1 if we can fix down
} CbcStrongInfo;
class CbcObject : public OsiObject {
public:
// Default Constructor
CbcObject ();
// Useful constructor
CbcObject (CbcModel * model);
// Copy constructor
CbcObject ( const CbcObject &);
// Assignment operator
CbcObject & operator=( const CbcObject& rhs);
/// Clone
virtual CbcObject * clone() const = 0;
/// Destructor
virtual ~CbcObject ();
/** Infeasibility of the object
This is some measure of the infeasibility of the object. It should be
scaled to be in the range [0.0, 0.5], with 0.0 indicating the object
is satisfied.
The preferred branching direction is returned in preferredWay,
This is used to prepare for strong branching but should also think of
case when no strong branching
The object may also compute an estimate of cost of going "up" or "down".
This will probably be based on pseudo-cost ideas
*/
#ifdef CBC_NEW_STYLE_BRANCH
virtual double infeasibility(const OsiBranchingInformation * info,
int &preferredWay) const = 0;
#else
virtual double infeasibility(const OsiBranchingInformation * /*info*/,
int &preferredWay) const {
return infeasibility(preferredWay);
}
virtual double infeasibility(int &/*preferredWay*/) const {
throw CoinError("Need code", "infeasibility", "CbcBranchBase");
}
#endif
/** For the variable(s) referenced by the object,
look at the current solution and set bounds to match the solution.
*/
virtual void feasibleRegion() = 0;
/// Dummy one for compatibility
virtual double feasibleRegion(OsiSolverInterface * solver, const OsiBranchingInformation * info) const;
/** For the variable(s) referenced by the object,
look at the current solution and set bounds to match the solution.
Returns measure of how much it had to move solution to make feasible
*/
virtual double feasibleRegion(OsiSolverInterface * solver) const ;
/** Create a branching object and indicate which way to branch first.
The branching object has to know how to create branches (fix
variables, etc.)
*/
#ifdef CBC_NEW_STYLE_BRANCH
virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) = 0;
#else
virtual CbcBranchingObject * createCbcBranch(OsiSolverInterface *
/* solver */,
const OsiBranchingInformation *
/* info */, int /* way */) {
// return createBranch(solver, info, way);
return NULL;
}
virtual OsiBranchingObject * createBranch(OsiSolverInterface * /*solver*/,
const OsiBranchingInformation * /*info*/, int /*way*/) const {
throw CoinError("Need code", "createBranch", "CbcBranchBase");
}
#endif
/** Create an Osibranching object and indicate which way to branch first.
The branching object has to know how to create branches (fix
variables, etc.)
*/
virtual OsiBranchingObject * createOsiBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int way) const;
/** Create an OsiSolverBranch object
This returns NULL if branch not represented by bound changes
*/
virtual OsiSolverBranch * solverBranch() const;
/** \brief Given a valid solution (with reduced costs, etc.),
return a branching object which would give a new feasible
point in a good direction.
If the method cannot generate a feasible point (because there aren't
any, or because it isn't bright enough to find one), it should
return null.
*/
virtual CbcBranchingObject * preferredNewFeasible() const {
return NULL;
}
/** \brief Given a valid solution (with reduced costs, etc.),
return a branching object which would give a new feasible
point in a bad direction.
If the method cannot generate a feasible point (because there aren't
any, or because it isn't bright enough to find one), it should
return null.
*/
virtual CbcBranchingObject * notPreferredNewFeasible() const {
return NULL;
}
/** Reset variable bounds to their original values.
Bounds may be tightened, so it may be good to be able to set this info in object.
*/
virtual void resetBounds(const OsiSolverInterface * ) {}
/** Returns floor and ceiling i.e. closest valid points
*/
virtual void floorCeiling(double & floorValue, double & ceilingValue, double value,
double tolerance) const;
/** Pass in information on branch just done and create CbcObjectUpdateData instance.
If object does not need data then backward pointer will be NULL.
Assumes can get information from solver */
virtual CbcObjectUpdateData createUpdateInformation(const OsiSolverInterface * solver,
const CbcNode * node,
const CbcBranchingObject * branchingObject);
/// Update object by CbcObjectUpdateData
virtual void updateInformation(const CbcObjectUpdateData & ) {}
/// Identifier (normally column number in matrix)
inline int id() const {
return id_;
}
/** Set identifier (normally column number in matrix)
but 1000000000 to 1100000000 means optional branching object
i.e. code would work without it */
inline void setId(int value) {
id_ = value;
}
/** Return true if optional branching object
i.e. code would work without it */
inline bool optionalObject() const {
return (id_ >= 1000000000 && id_ < 1100000000);
}
/// Get position in object_ list
inline int position() const {
return position_;
}
/// Set position in object_ list
inline void setPosition(int position) {
position_ = position;
}
/// update model
inline void setModel(CbcModel * model) {
model_ = model;
}
/// Return model
inline CbcModel * model() const {
return model_;
}
/// If -1 down always chosen first, +1 up always, 0 normal
inline int preferredWay() const {
return preferredWay_;
}
/// Set -1 down always chosen first, +1 up always, 0 normal
inline void setPreferredWay(int value) {
preferredWay_ = value;
}
/// Redoes data when sequence numbers change
virtual void redoSequenceEtc(CbcModel * , int , const int * ) {}
/// Initialize for branching
virtual void initializeForBranching(CbcModel * ) {}
protected:
/// data
/// Model
CbcModel * model_;
/// Identifier (normally column number in matrix)
int id_;
/// Position in object list
int position_;
/// If -1 down always chosen first, +1 up always, 0 normal
int preferredWay_;
};
#endif
|