source: trunk/Cbc/src/CoinSolve.cpp

Last change on this file was 2491, checked in by forrest, 3 months ago

better SOS in mipstart, ctrl-c back, improve symmetric

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1/* $Id: CoinSolve.cpp 2491 2019-02-12 13:05:24Z forrest $ */
2// Copyright (C) 2007, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6/*! \file CbcSolver.cpp
7    \brief Main routine for the cbc stand-alone solver.
8*/
9
10#include "CbcConfig.h"
11#include "CoinPragma.hpp"
12#include "CbcModel.hpp"
13#include "CbcSolver.hpp"
14#include "OsiClpSolverInterface.hpp"
15
16/*
17  We have the following compile-time symbols.
18
19  CBC_OTHER_SOLVER      CoinSolve.cpp, CbcSolver.[cpp,hpp], CbcModel.cpp
20
21    A value of 1 says `cplex'. Other values not defined. The intent with
22    cplex is to apply all of cbc's smarts at the root, then hand the problem
23    over to cplex to finish. Cplex is not used as an alternate lp solver
24    under cbc control.
25
26    Usage in CbcModel is a fake; a small bit of code that's now `#if 0'.
27
28
29  CLP_DEBUG_MALLOC
30
31    This ties in with the functions clp_malloc, clp_free, and clp_memory,
32    which are defined in CoinOslFactorization.cpp. (Right where you'd expect
33    to find them, eh?).  Looks to be a relatively nice debugging wrapper for
34    standard C malloc.  Calls standard C malloc/free directly if
35    CLP_DEBUG_MALLOC is not defined.  Worth consideration for breaking out as
36    a separate utility.  The hooks for new and delete defined here should be
37    incorporated.
38
39    Absolutely not thread safe --- lots of static variables.
40
41    Hmmm ... is it still the case that standard C malloc and C++ new/delete
42    do not play well together? 'Cause the hooks here for new and delete will
43    not escape from this file.
44*/
45
46#if CBC_OTHER_SOLVER == 1
47#ifndef COIN_HAS_CPX
48#error "Configuration did not detect cplex installation."
49#else
50#include "OsiCpxSolverInterface.hpp"
51#endif
52#endif
53
54/*
55  Hooks for a debugging wrapper for malloc/free. This bit of definition hooks
56  C++ new / delete and diverts them into the debugging wrapper.
57*/
58//#define CLP_DEBUG_MALLOC
59#ifdef CLP_DEBUG_MALLOC
60/*extern "C" */ void clp_memory(int type);
61/*extern "C" */
62void *clp_malloc(int length);
63/*extern "C" */
64void clp_free(void *array);
65#include <malloc.h>
66#include <exception>
67#include <new>
68void *operator new(size_t size) throw(std::bad_alloc)
69{
70  void *p = clp_malloc(size);
71  return p;
72}
73void operator delete(void *p) throw()
74{
75  clp_free(p);
76}
77#endif // CLP_DEBUG_MALLOC
78
79#include <cassert>
80#include <cstdio>
81#include <cmath>
82#include <cfloat>
83#include <cstring>
84#include <iostream>
85
86// define TEST_MESSAGE_HANDLER to check works on all messages
87// #define TEST_MESSAGE_HANDLER
88#ifdef TEST_MESSAGE_HANDLER
89// This driver shows how to trap messages - this is just as in unitTest.cpp
90// ****** THis code is similar to MyMessageHandler.hpp and MyMessagehandler.cpp
91#include "CoinMessageHandler.hpp"
92
93/** This just adds a model to CoinMessage and a void pointer so
94    user can trap messages and do useful stuff.
95    This is used in Clp/Test/unitTest.cpp
96
97    The file pointer is just there as an example of user stuff.
98
99  -- lh 071026 -- An accurate summary. Nothing is actually happening here
100  except that messages will be prefixed with "==", which serves the purpose
101  of demonstrating that this message handler is active. The extra parameters
102  (CbcModel, FILE) are unused.
103
104*/
105class CbcModel;
106
107class MyMessageHandler2 : public CoinMessageHandler {
108
109public:
110  /**@name Overrides */
111  //@{
112  virtual int print();
113  //@}
114  /**@name set and get */
115  //@{
116  /// Model
117  const CbcModel *model() const;
118  void setModel(CbcModel *model);
119  //@}
120
121  /**@name Constructors, destructor */
122  //@{
123  /** Default constructor. */
124  MyMessageHandler2();
125  /// Constructor with pointer to model
126  MyMessageHandler2(CbcModel *model,
127    FILE *userPointer = NULL);
128  /** Destructor */
129  virtual ~MyMessageHandler2();
130  //@}
131
132  /**@name Copy method */
133  //@{
134  /** The copy constructor. */
135  MyMessageHandler2(const MyMessageHandler2 &);
136  /** The copy constructor from an CoinSimplexMessageHandler. */
137  MyMessageHandler2(const CoinMessageHandler &);
138
139  MyMessageHandler2 &operator=(const MyMessageHandler2 &);
140  /// Clone
141  virtual CoinMessageHandler *clone() const;
142  //@}
143
144protected:
145  /**@name Data members
146       The data members are protected to allow access for derived classes. */
147  //@{
148  /// Pointer back to model
149  CbcModel *model_;
150  //@}
151};
152
153//#############################################################################
154// Constructors / Destructor / Assignment
155//#############################################################################
156
157//-------------------------------------------------------------------
158// Default Constructor
159//-------------------------------------------------------------------
160MyMessageHandler2::MyMessageHandler2()
161  : CoinMessageHandler()
162  , model_(NULL)
163{
164}
165
166//-------------------------------------------------------------------
167// Copy constructor
168//-------------------------------------------------------------------
169MyMessageHandler2::MyMessageHandler2(const MyMessageHandler2 &rhs)
170  : CoinMessageHandler(rhs)
171  , model_(rhs.model_)
172{
173}
174
175MyMessageHandler2::MyMessageHandler2(const CoinMessageHandler &rhs)
176  : CoinMessageHandler()
177  , model_(NULL)
178{
179}
180
181// Constructor with pointer to model
182MyMessageHandler2::MyMessageHandler2(CbcModel *model,
183  FILE *userPointer)
184  : CoinMessageHandler()
185  , model_(model)
186{
187}
188
189//-------------------------------------------------------------------
190// Destructor
191//-------------------------------------------------------------------
192MyMessageHandler2::~MyMessageHandler2()
193{
194}
195
196//----------------------------------------------------------------
197// Assignment operator
198//-------------------------------------------------------------------
199MyMessageHandler2 &
200MyMessageHandler2::operator=(const MyMessageHandler2 &rhs)
201{
202  if (this != &rhs) {
203    CoinMessageHandler::operator=(rhs);
204    model_ = rhs.model_;
205  }
206  return *this;
207}
208//-------------------------------------------------------------------
209// Clone
210//-------------------------------------------------------------------
211CoinMessageHandler *MyMessageHandler2::clone() const
212{
213  return new MyMessageHandler2(*this);
214}
215int MyMessageHandler2::print()
216{
217  // Just add ==
218  fprintf(fp_, " == ");
219  fprintf(fp_, "%s\n", messageBuffer_);
220  return 0;
221}
222const CbcModel *
223MyMessageHandler2::model() const
224{
225  return model_;
226}
227void MyMessageHandler2::setModel(CbcModel *model)
228{
229  model_ = model;
230}
231#endif /* TEST_MESSAGE_HANDLER */
232
233//#############################################################################
234
235// To use USERCBC or USERCLP change 0 to 1 in defines and add in your fake main program(s) and any other code
236//#define USER_HAS_FAKE_CBC
237//#define USER_HAS_FAKE_CLP
238
239#ifdef USER_HAS_FAKE_CBC
240#endif
241void fakeMain(ClpSimplex &model, OsiSolverInterface & /*osiSolver*/, CbcModel &babSolver)
242{
243#ifdef USER_HAS_FAKE_CBC
244#else
245  printf("Dummy user cbc code - model has %d rows and %d columns\n",
246    model.getNumRows(), model.getNumCols());
247  // Reduce printout
248  babSolver.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
249  // Do complete search
250  babSolver.branchAndBound();
251#endif
252}
253
254// Clp stuff
255#ifdef USER_HAS_FAKE_CLP
256#endif
257void fakeMain2(ClpSimplex & /*model*/,
258  OsiClpSolverInterface &osiSolver,
259  int /*options*/)
260{
261#ifdef USER_HAS_FAKE_CLP
262#else
263  ClpSimplex *lpSolver = osiSolver.getModelPtr();
264  printf("Dummy user clp code - model has %d rows and %d columns\n",
265    lpSolver->numberRows(), lpSolver->numberColumns());
266  osiSolver.initialSolve();
267#endif
268}
269//  End any fake main program
270
271//#############################################################################
272
273// void CbcClpUnitTest (const CbcModel & saveModel);
274
275#ifdef CBC_STATISTICS
276int osi_crunch = 0;
277static int cbc_resolve = 0;
278int osi_primal = 0;
279int osi_dual = 0;
280int osi_hot = 0;
281void cbc_resolve_check(const OsiSolverInterface *solver)
282{
283  cbc_resolve++;
284  printf("R %d stats %d %d %d\n",
285    cbc_resolve, solver->getNumRows(), solver->getNumCols(),
286    solver->getMatrixByCol()->getNumElements());
287  if ((cbc_resolve % 1000) == 0)
288    printf("RR %d resolve crunch %d primal %d dual %d hot %d\n",
289      cbc_resolve, osi_crunch, osi_primal, osi_dual, osi_hot);
290}
291#endif
292
293/*
294  Somehow with some BLAS we get multithreaded by default
295  For 99.99% of problems this is not a good idea.
296  The openblas_set_num_threads(1) seems to work even with other blas
297 */
298#if CLP_USE_OPENBLAS
299extern "C" {
300void openblas_set_num_threads(int num_threads);
301}
302#endif
303
304static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/)
305{
306  return 0;
307}
308
309int main(int argc, const char *argv[])
310{
311  int returnCode = 0;
312#ifdef CLP_DEBUG_MALLOC
313  clp_memory(0);
314#endif
315  {
316#ifndef CBC_OTHER_SOLVER
317    OsiClpSolverInterface solver1;
318#if CLP_USE_OPENBLAS
319    openblas_set_num_threads(CLP_USE_OPENBLAS);
320#endif
321#elif CBC_OTHER_SOLVER == 1
322    OsiCpxSolverInterface solver1;
323#endif
324    CbcModel model(solver1);
325
326    // define TEST_MESSAGE_HANDLER at top of file to check works on all messages
327#ifdef TEST_MESSAGE_HANDLER
328    MyMessageHandler2 messageHandler(&model);
329    std::cout << "Testing derived message handler" << std::endl;
330    model.passInMessageHandler(&messageHandler);
331    OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(model.solver());
332    // Could use different handlers (if different log levels)
333    clpSolver->passInMessageHandler(&messageHandler);
334    //clpSolver->getModelPtr()->passInMessageHandler(&messageHandler);
335#endif
336
337    CbcSolverUsefulData cbcData;
338#ifndef CBC_NO_INTERRUPT
339    cbcData.useSignalHandler_ = true;
340#endif
341    cbcData.noPrinting_ = false;
342    // initialize
343    CbcMain0(model, cbcData);
344
345#ifdef TEST_MESSAGE_HANDLER
346    // Set log levels same so can use one message handler
347    clpSolver->messageHandler()->setLogLevel(1);
348    model.messageHandler()->setLogLevel(1);
349    // switch off some printing
350    void setCbcOrClpPrinting(bool yesNo);
351    setCbcOrClpPrinting(false);
352#endif
353
354    returnCode = CbcMain1(argc, argv, model, dummyCallBack, cbcData);
355  }
356
357#ifdef CLP_DEBUG_MALLOC
358  clp_memory(1);
359#endif
360
361  if (returnCode != 777) {
362    return returnCode;
363  } else {
364    return 0;
365  }
366}
367
368/*
369  Version 1.00.00 November 16 2005.
370  This is to stop me (JJF) messing about too much.
371  Tuning changes should be noted here.
372  The testing next version may be activated by CBC_NEXT_VERSION
373  This applies to OsiClp, Clp etc
374  Version 1.00.01 November 24 2005
375  Added several classes for advanced users.  This can't affect code (if you don't use it)
376  Made some tiny changes (for N way branching) which should not change anything.
377  CbcNWay object class - for N way branching this also allows use of CbcConsequence class.
378  CbcBranchAllDifferent object class - for branching on general integer variables
379  to stop them having same value so branches are x >= y+1 and x <= y-1.
380  Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly)
381  and CglStored which just has a list of cuts which can be activated.
382  Modified preprocess option to SOS
383  Version 1.00.02 December 9 2005
384  Added use of CbcStrategy to do clean preprocessing
385  Added use of referenceSolver for cleaner repetition of Cbc
386  Version 1.01.00 February 2 2006
387  Added first try at Ampl interface
388  Made dummy program so real main can be called from other programs
389*/
390
391/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
392*/
Note: See TracBrowser for help on using the repository browser.