source: branches/devel/Cbc/src/CbcGenSolvers.cpp @ 649

Last change on this file since 649 was 608, checked in by lou, 13 years ago

Cbc-generic: Add message handler, separate libCbc and cbc-generic main log
level parameters.

  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
1/*
2  Copyright (C) 2007, Lou Hafer, International Business Machines Corporation
3  and others.  All Rights Reserved.
4
5  This file is part of cbc-generic.
6*/
7
8/*
9  This file contains routines related to handling Osi solvers. The technique
10  is to maintain a map of OsiSolverInterface objects as prototypes of the
11  available solvers.
12*/
13
14#include "CbcConfig.h"
15#include "CoinPragma.hpp"
16
17#include "OsiSolverInterface.hpp"
18
19/*
20  Include class definitions for the solvers that are available. If
21  CBC_DEFAULT_SOLVER is not defined in CbcConfig.h, set it to the first
22  available solver.
23
24  NOTE: Processing of keyword parameters is made case-independent by forcing
25        lower case comparison. Maps, on the other hand, are case-sensitive.
26        The solver names given here must contain only lower case letters and
27        must match the keywords used when defining the keywords for the
28        solver parameter.
29*/
30
31#ifdef COIN_HAS_CLP
32# include "OsiClpSolverInterface.hpp"
33# ifndef CBC_DEFAULT_SOLVER
34#   define CBC_DEFAULT_SOLVER "clp"
35# endif
36#endif
37
38#ifdef COIN_HAS_DYLP
39# include "OsiDylpSolverInterface.hpp"
40# ifndef CBC_DEFAULT_SOLVER
41#   define CBC_DEFAULT_SOLVER "dylp"
42# endif
43#endif
44
45#ifdef COIN_HAS_GLPK
46# include "OsiGlpkSolverInterface.hpp"
47# ifndef CBC_DEFAULT_SOLVER
48#   define CBC_DEFAULT_SOLVER "glpk"
49# endif
50#endif
51
52#include "CoinParam.hpp"
53
54#include "CbcModel.hpp"
55#include "CbcGenCtlBlk.hpp"
56
57#include "CbcGenParam.hpp"
58#include "CbcGenCbcParam.hpp"
59#include "CbcGenOsiParam.hpp"
60
61namespace {
62
63  char svnid[] = "$Id$" ;
64
65}
66
67/*
68  Unnamed local namespace to hide the data structures used to maintain the
69  vector of OsiSolverInterface objects.
70*/
71
72namespace {
73
74/*
75  Data types for a vector of OsiSolverInterface objects.
76*/
77typedef std::map<std::string,OsiSolverInterface*> solverMap_t ;
78typedef solverMap_t::const_iterator solverMapIter_t ;
79
80/*
81  The solver map.
82*/
83
84solverMap_t solvers ;
85
86} // end unnamed local namespace
87
88
89namespace CbcGenSolvers {
90
91/*
92  Create a vector of solver prototypes and establish a default solver.
93
94  Creating multiple solvers is moderately expensive; if you're not interested
95  in experimenting with solvers other than clp, you're likely better off just
96  working with the cbc main program (CoinSolve.cpp).
97
98  The businesss with CBC_DEFAULT_SOLVER will select the first available
99  solver as the default, unless overridden at compile time.
100
101*/
102
103OsiSolverInterface *setupSolvers ()
104
105{
106/*
107  Populate the vector of OsiSolverInterface objects.
108*/
109# ifdef COIN_HAS_CLP
110  solvers["clp"] = new OsiClpSolverInterface ;
111# endif
112# ifdef COIN_HAS_DYLP
113  solvers["dylp"] = new OsiDylpSolverInterface  ;
114# endif
115# ifdef COIN_HAS_GLPK
116  solvers["glpk"] = new OsiGlpkSolverInterface  ;
117# endif
118/*
119  Set the standard default values in each solver.
120*/
121  for (solverMapIter_t solverIter = solvers.begin() ;
122         solverIter != solvers.end() ;
123         solverIter++)
124  { OsiSolverInterface *osi = solverIter->second ;
125    osi->messageHandler()->setLogLevel(0) ;
126    CbcOsiParamUtils::setOsiSolverInterfaceDefaults(osi) ; }
127/*
128  If we don't have a default solver, we're deeply confused.
129*/
130  OsiSolverInterface *dflt_solver = solvers[CBC_DEFAULT_SOLVER] ;
131  if (dflt_solver)
132  { std::cout << "Default solver is " << CBC_DEFAULT_SOLVER << std::endl ; }
133  else
134  { std::cerr << "No solvers!" << std::endl ; }
135
136  return (dflt_solver) ;
137}
138
139
140/*
141  Cleanup routine to delete the vector of OsiSolverInterface objects.
142*/
143
144void deleteSolvers ()
145{
146  for (solverMapIter_t solverIter = solvers.begin() ;
147         solverIter != solvers.end() ;
148         solverIter++)
149    { if (solverIter->second) delete solverIter->second ; }
150}
151
152/*
153  The `push' routine for the solver parameter.
154
155  The basic operation is to clone the requested solver and assign it to the
156  current CbcModel object.
157*/
158
159int changeCbcSolver (CoinParam *param)
160
161{ assert (param != 0) ;
162  CbcGenParam *genParam = dynamic_cast<CbcGenParam *>(param) ;
163  assert (genParam != 0) ;
164  CbcGenCtlBlk *ctlBlk = genParam->obj() ;
165  assert (ctlBlk != 0) ;
166  CoinMessageHandler *msghandler = ctlBlk->messageHandler() ;
167/*
168  Setup to return nonfatal/fatal error (1/-1) by default.
169*/
170  int retval ;
171  if (CoinParamUtils::isInteractive())
172  { retval = 1 ; }
173  else
174  { retval = -1 ; }
175/*
176  Try to locate the solver specified by the user.
177*/
178  const std::string solverName = genParam->kwdVal() ;
179  OsiSolverInterface *protoOsi = solvers[solverName] ;
180  if (protoOsi == 0)
181  { std::cerr
182      << "Can't find solver \"" << solverName
183      << "\" in the solvers vector." << std::endl ;
184    return (retval) ; }
185  ctlBlk->dfltSolver_ = protoOsi ;
186/*
187  We have a solver.
188*/
189  ctlBlk->message(CBCGEN_NEW_SOLVER)
190    << solverName << CoinMessageEol ;
191  CbcModel *model = ctlBlk->model_ ;
192  assert (model != 0) ;
193  OsiSolverInterface *newOsi = protoOsi->clone() ;
194  model->assignSolver(newOsi) ;
195
196  return (0) ; }
197
198
199/*
200  This routine sets up a solver parameter object. It doesn't initialise the
201  object being acted upon (a CbcGenCtlBlk); that's done back in the calling
202  routine where we're setting up the cbc-generic parameter vector.
203*/
204
205void setupSolverParam (CbcGenParam &solverParam)
206
207{
208/*
209  Basic setup: parameter type, name, parameter code.
210*/
211  solverParam.setType(CoinParam::coinParamKwd) ;
212  solverParam.setName("solver") ;
213  solverParam.setParamCode(CbcGenParam::SOLVER) ;
214/*
215  Add the solvers and set the default value.
216*/
217  for (solverMapIter_t solverIter = solvers.begin() ;
218       solverIter != solvers.end() ;
219       solverIter++)
220  { solverParam.appendKwd(solverIter->first) ; }
221  solverParam.setKwdVal(CBC_DEFAULT_SOLVER) ;
222  solverParam.setDisplay(true) ;
223  solverParam.setPushFunc(changeCbcSolver) ;
224/*
225  And add the help strings.
226*/
227  solverParam.setShortHelp("Specify underlying LP solver") ;
228  solverParam.setLongHelp(
229        "Select the underlying LP solver that will be used to solve the continuous relaxations of subproblems."
230        ) ;
231}
232
233} // end namespace CbcGenSolvers
234
Note: See TracBrowser for help on using the repository browser.