source: trunk/Cbc/src/CbcGenCbcParamUtils.cpp @ 2464

Last change on this file since 2464 was 2464, checked in by unxusr, 22 months ago

.clang-format with proposal for formatting code

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/*
2  Copyright (C) 2007, Lou Hafer, International Business Machines Corporation
3  and others.  All Rights Reserved.
4
5  This code is licensed under the terms of the Eclipse Public License (EPL).
6
7  $Id: CbcGenCbcParamUtils.cpp 2464 2019-01-03 19:03:23Z unxusr $
8*/
9/*
10  This file is part of cbc-generic.
11*/
12
13#if defined(_MSC_VER)
14// Turn off compiler warning about long names
15#pragma warning(disable : 4786)
16#endif
17
18#include <string>
19#include <cassert>
20
21#include "CoinFinite.hpp"
22#include "CoinParam.hpp"
23
24#include "CbcModel.hpp"
25
26#include "CbcGenCtlBlk.hpp"
27#include "CbcGenParam.hpp"
28#include "CbcGenCbcParam.hpp"
29
30/*! \file CbcGenParamUtils
31    \brief Implementation functions for CbcGenParam parameters.
32*/
33
34namespace {
35
36char svnid[] = "$Id: CbcGenCbcParamUtils.cpp 2464 2019-01-03 19:03:23Z unxusr $";
37
38}
39
40namespace CbcCbcParamUtils {
41
42/* Function to set up cbc (CbcModel) parameters.  */
43
44void addCbcCbcParams(int &numberParameters, CoinParamVec &parameters,
45  CbcModel *model)
46
47{
48  CbcCbcParam *param;
49
50  param = new CbcCbcParam(CbcCbcParam::ALLOWABLEGAP,
51    "allow!ableGap",
52    "Stop when gap between best possible and incumbent is less than this",
53    0.0, 1.0e20);
54  param->setDblVal(0.0);
55  param->setPushFunc(pushCbcCbcDbl);
56  param->setObj(model);
57  param->setLongHelp(
58    "If the gap between best solution and best possible solution is less than this then the search will be terminated. Also see ratioGap.");
59  parameters.push_back(param);
60
61  param = new CbcCbcParam(CbcCbcParam::CUTOFF,
62    "cuto!ff", "All solutions must be better than this", -1.0e60, 1.0e60);
63  param->setDblVal(1.0e50);
64  param->setPushFunc(pushCbcCbcDbl);
65  param->setObj(model);
66  param->setLongHelp(
67    "All solutions must be better than this value (in a minimization sense).  This is also set by cbc whenever it obtains a solution and is set to the value of the objective for the solution minus the cutoff increment.");
68  parameters.push_back(param);
69
70  param = new CbcCbcParam(CbcCbcParam::DIRECTION,
71    "direction", "Minimize or maximize", "min!imize", 0);
72  param->appendKwd("max!imize");
73  param->appendKwd("zero");
74  param->setObj(model);
75  param->setLongHelp(
76    "The default is minimize - use 'direction maximize' for maximization.\nYou can also use the parameters 'maximize' or 'minimize'.");
77  parameters.push_back(param);
78
79  param = new CbcCbcParam(CbcCbcParam::INCREMENT,
80    "inc!rement",
81    "A new solution must be at least this much better than the incumbent",
82    -1.0e20, 1.0e20, model->getDblParam(CbcModel::CbcCutoffIncrement));
83  param->setPushFunc(pushCbcCbcDbl);
84  param->setObj(model);
85  param->setLongHelp(
86    "Whenever a solution is found the bound on future solutions is set to the objective of the solution (in a minimization sense) plus the specified increment.  If this option is not specified, the code will try and work out an increment.  E.g., if all objective coefficients are multiples of 0.01 and only integer variables have entries in objective then the increment can be set to 0.01.  Be careful if you set this negative!");
87  parameters.push_back(param);
88
89  param = new CbcCbcParam(CbcCbcParam::INFEASIBILITYWEIGHT,
90    "inf!easibilityWeight",
91    "Each integer infeasibility is expected to cost this much",
92    0.0, 1.0e20, model->getDblParam(CbcModel::CbcInfeasibilityWeight));
93  param->setPushFunc(pushCbcCbcDbl);
94  param->setObj(model);
95  param->setLongHelp(
96    "A primitive way of deciding which node to explore next.  Satisfying each integer infeasibility is expected to cost this much.");
97  parameters.push_back(param);
98
99  param = new CbcCbcParam(CbcCbcParam::INTEGERTOLERANCE,
100    "integerT!olerance",
101    "For an optimal solution, no integer variable may be farther than this from an integer value",
102    1.0e-20, 0.5, model->getDblParam(CbcModel::CbcIntegerTolerance));
103  param->setPushFunc(pushCbcCbcDbl);
104  param->setObj(model);
105  param->setLongHelp(
106    "When checking a solution for feasibility, if the difference between the value of a variable and the nearest integer is less than the integer tolerance, the value is considered to be integral. Beware of setting this smaller than the primal tolerance.");
107  parameters.push_back(param);
108
109  param = new CbcCbcParam(CbcCbcParam::LOGLEVEL,
110    "bclog!Level", "Level of detail in Coin branch and Cut output",
111    -1, 63, model->messageHandler()->logLevel());
112  param->setPushFunc(pushCbcCbcInt);
113  param->setObj(model);
114  param->setLongHelp(
115    "If set to 0 then there should be no output in normal circumstances. A value of 1 is probably the best value for most uses, while 2 and 3 give more information.");
116  parameters.push_back(param);
117
118  param = new CbcCbcParam(CbcCbcParam::MAXIMIZE,
119    "max!imize", "Set optimization direction to maximize");
120  param->setObj(model);
121  param->setLongHelp(
122    "The default is minimize - use 'maximize' for maximization.\n A synonym for 'direction maximize'.");
123  parameters.push_back(param);
124
125  param = new CbcCbcParam(CbcCbcParam::MAXNODES,
126    "maxN!odes", "Maximum number of nodes to evaluate", 1, 2147483647);
127  param->setObj(model);
128  param->setLongHelp(
129    "This is a repeatable way to limit search.  Normally using time is easier but then the results may not be repeatable.");
130  parameters.push_back(param);
131
132  param = new CbcCbcParam(CbcCbcParam::MINIMIZE,
133    "min!imize", "Set optimization direction to minimize");
134  param->setObj(model);
135  param->setLongHelp(
136    "The default is minimize - use 'maximize' for maximization.\nThis should only be necessary if you have previously set maximization. A synonym for 'direction minimize'.");
137  parameters.push_back(param);
138
139  param = new CbcCbcParam(CbcCbcParam::MIPOPTIONS,
140    "mipO!ptions", "Dubious options for mip", 0, COIN_INT_MAX, 0, false);
141  parameters.push_back(param);
142
143  param = new CbcCbcParam(CbcCbcParam::MOREMIPOPTIONS,
144    "more!MipOptions", "More dubious options for mip", -1, COIN_INT_MAX, 0, false);
145  parameters.push_back(param);
146
147  param = new CbcCbcParam(CbcCbcParam::NUMBERMINI,
148    "miniT!ree", "Size of fast mini tree", 0, COIN_INT_MAX, 0, false);
149  param->setObj(model);
150  param->setLongHelp(
151    "The idea is that I can do a small tree fast. This is a first try and will hopefully become more sophisticated.");
152  parameters.push_back(param);
153
154  param = new CbcCbcParam(CbcCbcParam::NUMBERANALYZE,
155    "numberA!nalyze",
156    "Number of analysis iterations", -COIN_INT_MAX, COIN_INT_MAX, false);
157  param->setObj(model);
158  param->setLongHelp(
159    "This says how many iterations to spend at the root node analyzing the problem.  This is a first try and will hopefully become more sophisticated.");
160  parameters.push_back(param);
161
162  param = new CbcCbcParam(CbcCbcParam::CUTPASS,
163    "passC!uts", "Number of cut passes at root node",
164    -999999, 999999, model->getMaximumCutPassesAtRoot());
165  param->setObj(model);
166  param->setLongHelp(
167    "The default is 100 passes if less than 500 columns, 100 passes (but stop if the drop is small) if less than 5000 columns, 20 otherwise.");
168  parameters.push_back(param);
169
170  param = new CbcCbcParam(CbcCbcParam::GAPRATIO,
171    "ratio!Gap",
172    "Stop when the gap between the best possible solution and the incumbent is less than this fraction of the larger of the two",
173    0.0, 1.0e20, model->getDblParam(CbcModel::CbcAllowableFractionGap));
174  param->setPushFunc(pushCbcCbcDbl);
175  param->setObj(model);
176  param->setLongHelp(
177    "If the gap between the best solution and the best possible solution is less than this fraction of the objective value at the root node then the search will terminate.  See 'allowableGap' for a way of using absolute value rather than fraction.");
178  parameters.push_back(param);
179
180  param = new CbcCbcParam(CbcCbcParam::TIMELIMIT_BAB,
181    "sec!onds", "Maximum seconds for branch and cut", -1.0, 1.0e12);
182  param->setPushFunc(pushCbcCbcDbl);
183  param->setObj(model);
184  param->setLongHelp(
185    "After this many seconds the program will act as if maximum nodes had been reached.");
186  parameters.push_back(param);
187
188  param = new CbcCbcParam(CbcCbcParam::STRONGBRANCHING,
189    "strong!Branching",
190    "Number of variables to look at in strong branching", 0, 999999,
191    model->numberStrong());
192  param->setObj(model);
193  param->setLongHelp(
194    "In order to decide which variable to branch on, the code will choose up to this number of unsatisfied variables and try mini up and down branches.  The most effective one is chosen. If a variable is branched on many times then the previous average up and down costs may be used - see number before trust.");
195  parameters.push_back(param);
196
197  param = new CbcCbcParam(CbcCbcParam::NUMBERBEFORE,
198    "trust!PseudoCosts", "Number of branches before we trust pseudocosts",
199    -1, 2000000, model->numberBeforeTrust());
200  param->setObj(model);
201  param->setPushFunc(pushCbcCbcInt);
202  param->setLongHelp(
203    "Using strong branching computes pseudo-costs.  After this many times for a variable we just trust the pseudo costs and do not do any more strong branching.");
204  parameters.push_back(param);
205
206  numberParameters = parameters.size();
207
208  assert(numberParameters <= parameters.capacity());
209}
210
211void loadCbcParamObj(const CoinParamVec paramVec, int first, int last,
212  CbcModel *obj)
213
214{
215  int i;
216
217  /*
218      Load the CbcModel object into the parameters
219    */
220  for (i = first; i <= last; i++) {
221    CbcCbcParam *cbcParam = dynamic_cast<CbcCbcParam *>(paramVec[i]);
222    assert(cbcParam != 0);
223    cbcParam->setObj(obj);
224  }
225
226  return;
227}
228
229/*
230  Set CbcModel defaults appropriate for cbc-generic.
231*/
232
233void setCbcModelDefaults(CbcModel *model)
234
235{
236  model->setIntParam(CbcModel::CbcMaxNumNode, (COIN_INT_MAX / 2));
237  model->setIntParam(CbcModel::CbcMaxNumSol, 999999);
238  model->setIntParam(CbcModel::CbcFathomDiscipline, 0);
239
240  model->setDblParam(CbcModel::CbcIntegerTolerance, 1.0e-6);
241  model->setDblParam(CbcModel::CbcInfeasibilityWeight, 0.0);
242  model->setDblParam(CbcModel::CbcCutoffIncrement, 1.0e-5);
243  model->setDblParam(CbcModel::CbcAllowableGap, 1.0e-10);
244  model->setDblParam(CbcModel::CbcAllowableFractionGap, 0.0);
245  // One year is 60x60x24x365 = 31,536,000 seconds.
246  model->setDblParam(CbcModel::CbcMaximumSeconds, 3.0e7);
247  model->setDblParam(CbcModel::CbcCurrentCutoff, 1.0e100);
248  model->setDblParam(CbcModel::CbcOptimizationDirection, 1.0);
249  model->setDblParam(CbcModel::CbcCurrentObjectiveValue, 1.0e100);
250  model->setDblParam(CbcModel::CbcCurrentMinimizationObjectiveValue, 1.0e100);
251  model->setDblParam(CbcModel::CbcStartSeconds, 0.0);
252
253  model->setNumberBeforeTrust(5);
254  model->setNumberStrong(5);
255
256  return;
257}
258
259/*
260  Function to push a double parameter.
261*/
262
263int pushCbcCbcDbl(CoinParam *param)
264
265{
266  assert(param != 0);
267
268  CbcCbcParam *cbcParam = dynamic_cast<CbcCbcParam *>(param);
269  assert(cbcParam != 0);
270
271  CbcModel *model = cbcParam->obj();
272  double val = cbcParam->dblVal();
273  CbcCbcParam::CbcCbcParamCode code = cbcParam->paramCode();
274
275  assert(model != 0);
276
277  int retval = 0;
278  /*
279      Translate the parameter code from CbcCbcParamCode into the correct key for
280      CbcDblParam.
281    */
282  CbcModel::CbcDblParam key;
283  switch (code) {
284  case CbcCbcParam::INTEGERTOLERANCE: {
285    key = CbcModel::CbcIntegerTolerance;
286    break;
287  }
288  case CbcCbcParam::INFEASIBILITYWEIGHT: {
289    key = CbcModel::CbcInfeasibilityWeight;
290    break;
291  }
292  case CbcCbcParam::INCREMENT: {
293    key = CbcModel::CbcCutoffIncrement;
294    break;
295  }
296  case CbcCbcParam::ALLOWABLEGAP: {
297    key = CbcModel::CbcAllowableGap;
298    break;
299  }
300  case CbcCbcParam::GAPRATIO: {
301    key = CbcModel::CbcAllowableFractionGap;
302    break;
303  }
304  case CbcCbcParam::TIMELIMIT_BAB: {
305    key = CbcModel::CbcMaximumSeconds;
306    break;
307  }
308  case CbcCbcParam::CUTOFF: {
309    key = CbcModel::CbcCurrentCutoff;
310    break;
311  }
312  default: {
313    std::cerr << "pushCbcCbcDbl: no equivalent CbcDblParam for "
314              << "parameter code `" << code << "'." << std::endl;
315    retval = -1;
316    break;
317  }
318  }
319
320  bool result = model->setDblParam(key, val);
321  if (result == false) {
322    retval = -1;
323  }
324
325  return (retval);
326}
327
328/*
329  Function to push an integer parameter.
330*/
331
332int pushCbcCbcInt(CoinParam *param)
333
334{
335  assert(param != 0);
336
337  CbcCbcParam *cbcParam = dynamic_cast<CbcCbcParam *>(param);
338  assert(cbcParam != 0);
339
340  CbcModel *model = cbcParam->obj();
341  int val = cbcParam->intVal();
342  CbcCbcParam::CbcCbcParamCode code = cbcParam->paramCode();
343
344  assert(model != 0);
345
346  int retval = 0;
347  /*
348      Translate the parameter code from CbcCbcParamCode into the correct key for
349      CbcIntParam, or call the appropriate method directly.
350    */
351  CbcModel::CbcIntParam key = CbcModel::CbcLastIntParam;
352  switch (code) {
353  case CbcCbcParam::CUTPASS: {
354    model->setMaximumCutPassesAtRoot(val);
355    break;
356  }
357  case CbcCbcParam::LOGLEVEL: {
358    CoinMessageHandler *hndl = model->messageHandler();
359    assert(hndl != 0);
360    hndl->setLogLevel(val);
361    break;
362  }
363  case CbcCbcParam::NUMBERBEFORE: {
364    model->setNumberBeforeTrust(val);
365    break;
366  }
367  default: {
368    std::cerr << "pushCbcCbcInt: no equivalent CbcIntParam for "
369              << "parameter code `" << code << "'." << std::endl;
370    retval = -1;
371    break;
372  }
373  }
374
375  if (key != CbcModel::CbcLastIntParam) {
376    bool result = model->setIntParam(key, val);
377    if (result == false) {
378      retval = -1;
379    }
380  }
381
382  return (retval);
383}
384
385} // end namespace CbcCbcParamUtils
Note: See TracBrowser for help on using the repository browser.