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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
// Copyright (C) 2006, 2008 International Business Machines
// Corporation and others. All Rights Reserved.
#ifndef BonChooseVariable_H
#define BonChooseVariable_H
#include "OsiChooseVariable.hpp"
#ifdef BONMIN_CURVATURE_BRANCHING
#include "BonCurvatureEstimator.hpp"
#endif
#include "BonOsiTMINLPInterface.hpp"
#include "CoinMessageHandler.hpp"
#include "BonBabSetupBase.hpp"
// Forward declaration
class CbcModel;
#define OLD_USEFULLNESS
namespace Bonmin
{
class HotInfo : public OsiHotInfo {
public:
/// Default constructor
HotInfo();
/// Constructor from usefull information
HotInfo( OsiSolverInterface * solver,
const OsiBranchingInformation *info,
const OsiObject * const * objects, int whichObject);
/// Copy constructor
HotInfo(const HotInfo & other);
/// Assignment operator
HotInfo & operator=(const HotInfo & rhs);
/// Clone
virtual OsiHotInfo * clone() const;
/// Destructor
virtual ~HotInfo();
/// Fill in some usefull information after a strong branching is done:
int updateInformation( const OsiSolverInterface * solver, const OsiBranchingInformation * info,
OsiChooseVariable * choose);
/// up infeasibility
double upInfeasibility() const{
return infeasibilities_[1];
}
/// down infeasibility
double downInfeasibility() const{
return infeasibilities_[0];
}
/// Set the down infeasibility
void setUpInfeasibility(double x){
assert(branchingObject_->numberBranches()==2);
infeasibilities_[1] = x;
}
/// Set the down infeasibility
void setDownInfeasibility(double x){
assert(branchingObject_->numberBranches()==2);
infeasibilities_[0] = x;
}
private:
/// infeasibilities of children
vector<double> infeasibilities_;
};
/** This class chooses a variable to branch on
This is the base class for the branching rules in Bonmin (inherits
from OsiChooseVariable). This class implements a simple strong branching algorithm where the changes in the objective
value induced by branching on a specific object are estimated with the pure virtual function fill_changes.
*/
class BonChooseVariable : public OsiChooseVariable
{
protected:
/** This is a utility function which does strong branching on
a list of objects and stores the results in OsiHotInfo.objects.
On entry the object sequence is stored in the OsiHotInfo object
and maybe more.
It returns -
-1 - one branch was infeasible both ways
0 - all inspected - nothing can be fixed
1 - all inspected - some can be fixed (returnCriterion==0)
2 - may be returning early - one can be fixed (last one done) (returnCriterion==1)
3 - returning because max time
*/
virtual int doStrongBranching( OsiSolverInterface * solver,
OsiBranchingInformation *info,
int numberToDo, int returnCriterion);
#ifndef OLD_USEFULLNESS
/** Criterion applied to sort candidates.*/
enum CandidateSortCriterion {
DecrPs = 0,
IncrPs,
DecrInfeas,
IncrInfeas};
#endif
/** Statuses for strong branching candidates.*/
enum StrongStatus{
NotDone=-1,
Feasible/** Child is proven feasible.*/,
Infeasible /** Child is proven infeasible.*/,
NotFinished /** Child is not finished.*/};
public:
/** \name Message handling.*/
/** @{ */
enum Messages_Types {
PS_COST_HISTORY = 0,
PS_COST_MULT,
PS_COST_ESTIMATES,
CANDIDATE_LIST,
CANDIDATE_LIST2,
CANDIDATE_LIST3,
SB_START,
SB_HEADER,
SB_RES,
BRANCH_VAR,
CHOSEN_VAR,
UPDATE_PS_COST,
BON_CHOOSE_MESSAGES_DUMMY_END
};
class Messages : public CoinMessages
{
public:
Messages();
};
void passInMessageHandler(CoinMessageHandler * handler) {
int logLevel = handler_->logLevel();
delete handler_;
handler_ = handler->clone();
handler_->setLogLevel(logLevel);
}
CoinMessageHandler& message(Messages_Types type) const {
return handler_->message(type, messages_);
}
/** @} */
enum DoStrongReturnStatuses{
provenInfeasible = -1 /** One branch has two infeasible children.*/,
doneNoFixing /** All done no variable can be fixed.*/,
doneCanFix /** Several variable can be fixed.*/,
interuptedCanFix /** Interupted and found a variable to fix.*/,
maxTime /** Interupted because of time limit.*/};
/** Return statuses for chooseVariable.*/
enum chooseVariableReturnStatuses{
infeasibleNode = -1/** Node has been proven infeasible.*/,
hasCandidate /** Normal termination, found a variable to branch on.*/,
feasibleNode /** All variable are feasible, the node is feasible.*/,
canFixAndStrongBranch /** Found variable to fix and also has remaining candidate for strong branching.*/,
canFixAndBranch/** Found variable to fix and also has a (non-strong) branching candidate.*/,
canFixNoCandidate /** Can fix variables but does not have strong branching candidates.*/
};
/// Constructor from solver (so we can set up arrays etc)
BonChooseVariable (BabSetupBase& b, const OsiSolverInterface* solver);
/// Copy constructor
BonChooseVariable (const BonChooseVariable &);
/// Assignment operator
BonChooseVariable & operator= (const BonChooseVariable& rhs);
/// Clone
virtual OsiChooseVariable * clone() const;
/// Destructor
virtual ~BonChooseVariable ();
static void registerOptions(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions);
/** Helper functions for setupList and chooseVariable */
double maxminCrit(const OsiBranchingInformation* info) const;
void computeMultipliers(double& upMult, double& downMult) const;
double computeUsefulness(const double MAXMIN_CRITERION,
const double upMult, const double dowMult,
const double value,
const OsiObject* object, int i,
double& value2) const;
/** Sets up strong list and clears all if initialize is true.
Returns number of infeasibilities. */
virtual int setupList ( OsiBranchingInformation *info, bool initialize);
/** Choose a variable
Returns -
-1 Node is infeasible
0 Normal termination - we have a candidate
1 All looks satisfied - no candidate
2 We can change the bound on a variable - but we also have a strong branching candidate
3 We can change the bound on a variable - but we have a non-strong branching candidate
4 We can change the bound on a variable - no other candidates
We can pick up branch from bestObjectIndex() and bestWhichWay()
We can pick up a forced branch (can change bound) from firstForcedObjectIndex() and firstForcedWhichWay()
If we have a solution then we can pick up from goodObjectiveValue() and goodSolution()
If fixVariables is true then 2,3,4 are all really same as problem changed
*/
virtual int chooseVariable( OsiSolverInterface * solver, OsiBranchingInformation *info, bool fixVariables);
/** This is a utility function which does strong branching on
a list of objects and stores the results in OsiHotInfo.objects.
On entry the object sequence is stored in the OsiHotInfo object
and maybe more.
It returns -
-1 - one branch was infeasible both ways
0 - all inspected - nothing can be fixed
1 - all inspected - some can be fixed (returnCriterion==0)
2 - may be returning early - one can be fixed (last one done) (returnCriterion==1)
3 - returning because max time
*/
/// Given a candidate fill in useful information e.g. estimates
virtual void updateInformation(const OsiBranchingInformation *info,
int branch, OsiHotInfo * hotInfo);
#if 1
/// Given a branch fill in useful information e.g. estimates
virtual void updateInformation( int whichObject, int branch,
double changeInObjective, double changeInValue,
int status);
#endif
/** Method for setting CbcModel, which is used to get statusOfSearch */
void setCbcModel(CbcModel* cbc_model)
{
cbc_model_ = cbc_model;
}
void setOnlyPseudoWhenTrusted(bool only_pseudo_when_trusted)
{
only_pseudo_when_trusted_ = only_pseudo_when_trusted;
}
/** Access to pseudo costs storage.*/
const OsiPseudoCosts & pseudoCosts() const{
return pseudoCosts_;}
/** Access to pseudo costs storage.*/
OsiPseudoCosts & pseudoCosts() {
return pseudoCosts_;}
protected:
/// Holding on the a pointer to the journalist
Ipopt::SmartPtr<Ipopt::Journalist> jnlst_;
/// verbosity level
int bb_log_level_;
/** Stores strong branching results.*/
vector<HotInfo> results_;
/** Determine status of strong branching solution.*/
int determineStatus(OsiSolverInterface * solver) const {
if (solver->isProvenOptimal())
return 0; // optimal
else if (solver->isIterationLimitReached()
&&!solver->isDualObjectiveLimitReached())
return 2; // unknown
else
return 1; // infeasible
}
private:
/** Default Constructor, forbiden for some reason.*/
BonChooseVariable ();
/** Global time limit for algorithm. */
double time_limit_;
/** Starting time of algorithm.*/
double start_time_;
protected:
/// CbcModel, used to get status of search
CbcModel* cbc_model_;
/** Flag indicating whether we don't want to mix strong branching
* and pseudo costs during the decision which variable to branch
* on */
bool only_pseudo_when_trusted_;
/** Number of variables put into the list because there were not
* trusted */
int number_not_trusted_;
/** Message handler.*/
CoinMessageHandler * handler_;
/** Messages.*/
Messages messages_;
// ToDo: Make this options
/** @name Algoirithmic options */
//@{
/** maxmin weight in branching decision when no solution has been
* found yet */
double maxmin_crit_no_sol_;
/** maxmin weight in branching decision when no solution has been
* found yet */
double maxmin_crit_have_sol_;
/** fraction of branching candidates that are not trusted yet */
double setup_pseudo_frac_;
/** number of times a branch has to happen so that it is trusted in
* setupList */
int numberBeforeTrustedList_;
/** number of strong branching points at root node */
int numberStrongRoot_;
/** backup of numberStrong_ before Root node solve */
int numberStrongBackup_;
/** number of look-ahead strong-branching steps */
int numberLookAhead_;
#ifndef OLD_USEFULLNESS
/** Criterion to use in setup list.*/
CandidateSortCriterion sortCrit_;
#endif
/** Always strong branch that many first candidate in the list regardless of numberTrusted.*/
int minNumberStrongBranch_;
/** Stores the pseudo costs. */
OsiPseudoCosts pseudoCosts_;
/** Wether or not to trust strong branching results for updating pseudo costs.*/
int trustStrongForPseudoCosts_;
//@}
/** detecting if this is root node */
bool isRootNode(const OsiBranchingInformation *info) const;
/** Stores the class name for throwing errors.*/
static const std::string CNAME;
};
}
#endif
|