source: trunk/src/Cbc_C_Interface.cpp @ 3041

Last change on this file since 3041 was 3041, checked in by unxusr, 20 months ago

Make it possible to call clique strengthening from C interface

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 111.5 KB
Line 
1// $Id: Cbc_C_Interface.cpp 3041 2020-05-12 19:59:03Z unxusr $
2// Copyright (C) 2004, 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#include <cmath>
7#include <sstream>
8#include <cfloat>
9#include <climits>
10#include <cctype>
11#include <map>
12#include <string>
13#include <vector>
14 
15#include "Cbc_C_Interface.h"
16
17#ifdef CBC_THREAD
18#include <pthread.h>
19#endif
20
21#include "CoinPragma.hpp"
22//#include "CoinHelperFunctions.hpp"
23//#include "CoinPackedMatrix.hpp"
24#include "CoinTime.hpp"
25
26#include "CbcModel.hpp"
27#include "CbcSolver.hpp"
28#include "CbcBranchActual.hpp"
29
30#include "CoinMessageHandler.hpp"
31#include "OsiClpSolverInterface.hpp"
32#include "ClpSimplexOther.hpp"
33#include "CglCutGenerator.hpp"
34#include "CglStored.hpp"
35#include "CglCliqueStrengthening.hpp"
36#include "CglGomory.hpp"
37#include "CglZeroHalf.hpp"
38#include "CglClique.hpp"
39#include "CglBKClique.hpp"
40#include "CglKnapsackCover.hpp"
41#include "CglMixedIntegerRounding2.hpp"
42#include "CglTwomir.hpp"
43#include "CglZeroHalf.hpp"
44#include "CglLandP.hpp"
45#include "CbcCutGenerator.hpp"
46#include "ClpDualRowSteepest.hpp"
47#include "ClpDualRowDantzig.hpp"
48#include "ClpPEDualRowSteepest.hpp"
49#include "ClpPEDualRowDantzig.hpp"
50#include "CbcMipStartIO.hpp"
51#include "ClpMessage.hpp"
52#include "CoinStaticConflictGraph.hpp"
53#include <OsiAuxInfo.hpp>
54#include "CoinFileIO.hpp"
55
56using namespace std;
57
58static char **to_char_vec( const vector< string > names );
59static void *xmalloc( const size_t size );
60static void *xrealloc( void *ptr, const size_t newSize );
61
62#define VALIDATE_ROW_INDEX(iRow, model)  \
63      if (iRow<0 || iRow >= Cbc_getNumRows(model)) { \
64        fprintf( stderr, "Invalid row index (%d), valid range is [0,%d). At %s:%d\n", \
65            iRow, model->solver_->getNumRows()+model->nRows, __FILE__, __LINE__ ); \
66        fflush(stderr); \
67        abort(); \
68      }
69
70#define VALIDATE_COL_INDEX(iColumn , model)  \
71  if ( iColumn<0 || iColumn >= Cbc_getNumCols(model) ) { \
72    fprintf( stderr, "Invalid column index (%d), valid range is [0,%d). At %s:%d\n", \
73        iColumn, model->solver_->getNumCols()+model->nCols, __FILE__, __LINE__ ); \
74    fflush(stderr); \
75    abort(); \
76  }
77
78/* to check if solution (and of which type)
79 * is available */
80enum OptimizationTask {
81  ModelNotOptimized      = 0,
82  ContinuousOptimization = 1,
83  IntegerOptimization    = 2
84};
85
86/**
87  *
88  *  C Interface Routines
89  *
90  */
91
92
93// To allow call backs
94class Cbc_MessageHandler
95  : public CoinMessageHandler {
96
97public:
98  /**@name Overrides */
99  //@{
100  virtual int print();
101  //@}
102  /**@name set and get */
103  //@{
104  /// Model
105  const Cbc_Model *model() const;
106  void setModel(Cbc_Model *model);
107  /// Call back
108  void setCallBack(cbc_callback callback);
109  //@}
110
111  /**@name Constructors, destructor */
112  //@{
113  /** Default constructor. */
114  Cbc_MessageHandler();
115  /// Constructor with pointer to model
116  Cbc_MessageHandler(Cbc_Model *model,
117    FILE *userPointer = NULL);
118  /** Destructor */
119  virtual ~Cbc_MessageHandler();
120  //@}
121
122  /**@name Copy method */
123  //@{
124  /** The copy constructor. */
125  Cbc_MessageHandler(const Cbc_MessageHandler &);
126  /** The copy constructor from an CoinSimplexMessageHandler. */
127  Cbc_MessageHandler(const CoinMessageHandler &);
128
129  Cbc_MessageHandler &operator=(const Cbc_MessageHandler &);
130  /// Clone
131  virtual CoinMessageHandler *clone() const;
132  //@}
133
134protected:
135  /**@name Data members
136       The data members are protected to allow access for derived classes. */
137  //@{
138  /// Pointer back to model
139  Cbc_Model *model_;
140  /// call back
141  cbc_callback callback_;
142  //@}
143};
144
145// command line arguments related to the lp relaxation solution
146//static char cmdLPoptions[][80] =
147//  {"pertv", "idiot", "log", "seconds", "primalt", "dualt", "zerot",
148//   "pretol", "psi", "maxit", "crash", "scal" };
149//static int nCmcLpOptions = 12;
150
151static char cbc_annouced = 0;
152
153
154
155struct Cbc_Model {
156  /**
157   * Problem is stored here: before optimizing
158   * this should be cloned because CBC modifies
159   * directly this object dution the solution process
160   **/
161  OsiClpSolverInterface *solver_;
162
163  vector< string > vcbcOptions; // to keep the order of the options
164  map< string, string > cbcOptions; // to quickly check current value of option
165
166  char relax_;
167
168  // a new CbcModel needs to be created at every
169  // integer optimization, can be ignored for
170  // continuous optimization
171  CbcModel *cbcModel_;
172
173  // buffer for columns
174  int colSpace;
175  int nCols;
176  int cNameSpace;
177  int *cNameStart;
178  char *cInt;
179  char *cNames;
180  double *cLB;
181  double *cUB;
182  double *cObj;
183  int nInt;
184
185  int cElementsSpace;
186  CoinBigIndex *cStart;
187  int *cIdx;
188  double *cCoef;
189
190  vector< double > *iniSol;
191  double iniObj;
192
193  // buffer for rows
194  int rowSpace;
195  int nRows;
196  int rNameSpace;
197  int *rNameStart;
198  char *rNames;
199  double *rLB;
200  double *rUB;
201  int rElementsSpace;
202  CoinBigIndex *rStart;
203  int *rIdx;
204  double *rCoef;
205
206  // for fast search of columns
207  void *colNameIndex;
208  void *rowNameIndex;
209
210  cbc_incumbent_callback inc_callback;
211  cbc_progress_callback progr_callback;
212  cbc_callback userCallBack;
213
214  cbc_cut_callback cut_callback;
215  string cutCBName;
216  void *cutCBData;
217  int cutCBhowOften;
218  char cutCBAtSol;
219
220  enum OptimizationTask lastOptimization;
221
222  /* if number of columns didn't changed since previous
223   * MIP optimization, try to reuse */
224  int lastOptNCols;
225  int lastOptNRows;
226  double *lastOptMIPSol;
227
228  double *slack_;
229
230  /**
231   * Incumbent callback callback data
232   **/
233  void *icAppData;
234
235  /**
236   * Progress callback callback data
237   **/
238  void *pgrAppData;
239
240#ifdef CBC_THREAD
241  pthread_mutex_t cbcMutexCG;
242  pthread_mutex_t cbcMutexEvent;
243#endif
244
245  double obj_value;
246
247  int nSos;
248  int sosCap;
249  int sosSize;
250  int sosElCap;
251  int sosElSize;
252  int *sosRowStart;
253  int *sosType;
254  int *sosEl;
255  double *sosElWeight;
256
257  int nColsMS;
258  char **colNamesMS;
259  double *colValuesMS;
260  int charSpaceMS;
261
262  /* space to query conflict graph */
263  size_t cg_space;
264  size_t *cg_neighs;
265  bool *cg_iv;
266
267
268  // parameters
269  enum LPMethod lp_method;
270  enum DualPivot dualp;
271
272  // lazy constraints
273  CglStored *lazyConstrs;
274
275  int int_param[N_INT_PARAMS];
276  double dbl_param[N_DBL_PARAMS];
277};
278
279/* Buffers sizes */
280#define INI_COL_SPACE 8192
281#define INI_ROW_SPACE 8192
282
283//  bobe including extras.h to get strdup()
284#if defined(__MWERKS__)
285// #include <extras.h>  // bobe 06-02-14
286#endif
287
288#define CbcGetProperty(T, prop) \
289  T CBC_LINKAGE      \
290    Cbc_##prop(Cbc_Model *m)    \
291  {                             \
292    return m->model_->prop();   \
293  }
294
295#define CbcSetSolverProperty(T, prop)          \
296  void CBC_LINKAGE                  \
297    Cbc_##prop(Cbc_Model *m, int index, T val) \
298  {                                            \
299    m->model_->solver()->prop(index, val);     \
300  }
301
302const int VERBOSE = 0;
303
304typedef std::map< std::string, int > NameIndex;
305
306// cut generator to accept callbacks in CBC
307//
308class CglCallback : public CglCutGenerator
309{
310    public:
311        CglCallback();
312
313        cbc_cut_callback cut_callback_;
314        void *appdata;
315#ifdef CBC_THREAD
316        pthread_mutex_t *cbcMutex;
317#endif
318
319        //CbcModel *model;
320
321        /// Copy constructor
322        CglCallback(const CglCallback& rhs);
323
324        /// Clone
325        virtual CglCutGenerator * clone() const;
326
327        virtual void generateCuts( const OsiSolverInterface & si, OsiCuts & cs,
328                const CglTreeInfo info = CglTreeInfo() );
329
330        virtual ~CglCallback();
331    private:
332};
333
334CglCallback::CglCallback()
335    : cut_callback_(NULL),
336    appdata(NULL)
337#ifdef CBC_THREAD
338    ,cbcMutex(NULL)
339#endif
340
341{
342}
343
344CglCallback::CglCallback(const CglCallback& rhs)
345{
346    this->cut_callback_ = rhs.cut_callback_;
347    this->appdata = rhs.appdata;
348#ifdef CBC_THREAD
349    this->cbcMutex = rhs.cbcMutex;
350#endif
351}
352
353CglCutGenerator* CglCallback::clone() const
354{
355    CglCallback *cglcb = new CglCallback();
356    cglcb->cut_callback_ = this->cut_callback_;
357    cglcb->appdata = this->appdata;
358#ifdef CBC_THREAD
359    cglcb->cbcMutex = this->cbcMutex;
360#endif
361
362    return static_cast<CglCutGenerator*>(cglcb);
363}
364
365void CglCallback::generateCuts( const OsiSolverInterface &si, OsiCuts &cs, const CglTreeInfo info )
366{
367#ifdef CBC_THREAD
368    assert(this->cbcMutex);
369    pthread_mutex_lock((this->cbcMutex));
370#endif
371
372  this->cut_callback_( (OsiSolverInterface *) &si, &cs, this->appdata );
373
374#ifdef CBC_THREAD
375    pthread_mutex_unlock((this->cbcMutex));
376#endif
377}
378
379CglCallback::~CglCallback()
380{
381
382}
383
384class Cbc_EventHandler : public CbcEventHandler {
385public:
386  virtual CbcAction event(CbcEvent whichEvent);
387  Cbc_EventHandler();
388  Cbc_EventHandler(CbcModel *model);
389  virtual ~Cbc_EventHandler();
390  Cbc_EventHandler(const Cbc_EventHandler &rhs);
391  Cbc_EventHandler &operator=(const Cbc_EventHandler &rhs);
392  virtual CbcEventHandler *clone() const;
393
394  double bestCost;
395  double bestBound;
396  cbc_incumbent_callback inc_callback;
397  cbc_progress_callback progr_callback;
398  void *appData;
399  void *pgAppData;
400#ifdef CBC_THREAD
401  pthread_mutex_t *cbcMutex;
402#endif
403};
404
405Cbc_EventHandler::Cbc_EventHandler()
406  : CbcEventHandler()
407  , bestCost(COIN_DBL_MAX)
408  , bestBound(COIN_DBL_MIN)
409  , inc_callback(NULL)
410  , progr_callback(NULL)
411  , appData(NULL)
412  , pgAppData(NULL)
413#ifdef CBC_THREAD
414  , cbcMutex(NULL)
415#endif
416{
417}
418
419Cbc_EventHandler::Cbc_EventHandler(const Cbc_EventHandler &rhs)
420  : CbcEventHandler(rhs)
421  , bestCost(rhs.bestCost)
422  , bestBound(rhs.bestBound)
423  , inc_callback(rhs.inc_callback)
424  , progr_callback(rhs.progr_callback)
425  , appData(rhs.appData)
426  , pgAppData(rhs.pgAppData)
427#ifdef CBC_THREAD
428  , cbcMutex(rhs.cbcMutex)
429#endif
430
431{
432}
433
434Cbc_EventHandler::Cbc_EventHandler(CbcModel *model)
435  : CbcEventHandler(model)
436  , bestCost(COIN_DBL_MAX)
437  , bestBound(COIN_DBL_MIN)
438  , inc_callback(NULL)
439  , progr_callback(NULL)
440  , appData(NULL)
441  , pgAppData(NULL)
442#ifdef CBC_THREAD
443  , cbcMutex(NULL)
444#endif
445
446{
447}
448
449Cbc_EventHandler::~Cbc_EventHandler()
450{
451}
452
453Cbc_EventHandler &Cbc_EventHandler::operator=(const Cbc_EventHandler &rhs)
454{
455  if (this != &rhs) {
456    CbcEventHandler::operator=(rhs);
457    this->bestCost = rhs.bestCost;
458    this->bestBound = rhs.bestBound;
459    this->inc_callback = rhs.inc_callback;
460    this->progr_callback = rhs.progr_callback;
461    this->appData = rhs.appData;
462    this->pgAppData = rhs.pgAppData;
463#ifdef CBC_THREAD
464    this->cbcMutex = rhs.cbcMutex;
465#endif
466  }
467  return *this;
468}
469
470CbcEventHandler *Cbc_EventHandler::clone() const
471{
472  return new Cbc_EventHandler(*this);
473}
474
475CbcEventHandler::CbcAction Cbc_EventHandler::event(CbcEvent whichEvent)
476{
477  // if in sub tree carry on
478  if ((model_->specialOptions() & 2048) == 0) {
479    if ((whichEvent == solution || whichEvent == heuristicSolution)) {
480
481      OsiSolverInterface *origSolver = model_->solver();
482      const OsiSolverInterface *pps = model_->postProcessedSolver(1);
483
484      const OsiSolverInterface *solver = pps ? pps : origSolver;
485
486#ifdef CBC_THREAD
487    assert(this->cbcMutex);
488    pthread_mutex_lock((this->cbcMutex));
489#endif
490      if (bestCost >= solver->getObjValue() + 1e-10) {
491          bestCost = solver->getObjValue();
492
493        if (this->inc_callback != NULL) {
494          int charSize = 0;
495          const double *x = solver->getColSolution();
496          std::vector< std::pair<string, double> > sol;
497          for (int i = 0; (i < solver->getNumCols()); ++i) {
498            if (fabs(x[i]) <= 1e-7)
499                continue;
500            sol.push_back( std::pair<std::string, double>( solver->getColName(i), x[i] ));
501            charSize += (int)solver->getColName(i).size()+1;
502          } // checking non zero cols
503          size_t nNZ = sol.size();
504          char **cnames = new char*[nNZ];
505          double *xv = new double[nNZ];
506          cnames[0] = new char[charSize];
507          for ( int i=1 ; (i<(int)sol.size()) ; ++i ) 
508              cnames[i] = cnames[i-1] + sol[i-1].first.size()+1;
509          for ( int i=0 ; (i<(int)sol.size()) ; ++i ) 
510              strcpy( cnames[i], sol[i].first.c_str() );
511          for (int i = 0; (i < (int)nNZ); ++i)
512            xv[i] = sol[i].second;
513
514          this->inc_callback(model_, bestCost, nNZ, cnames, xv, this->appData);
515
516          delete[] xv;
517          delete[] cnames[0];
518          delete[] cnames;
519        } // incumbent callback
520        if (this->progr_callback) {
521          const CbcModel *model = this->getModel();
522          double secs = model->getCurrentSeconds();
523          double lb = model->getBestPossibleObjValue();
524          this->progr_callback((void *) model, 0, model->getNodeCount(), "sol", secs, lb, bestCost, 0, NULL, this->pgAppData);
525        } // incumbent callback
526      } // improved cost
527#ifdef CBC_THREAD
528    assert(this->cbcMutex);
529    pthread_mutex_unlock((this->cbcMutex));
530#endif
531    } // solution found
532
533    if (this->progr_callback)
534    {
535#ifdef CBC_THREAD
536    assert(this->cbcMutex);
537    pthread_mutex_lock((this->cbcMutex));
538#endif
539      if (this->getModel()->getBestPossibleObjValue() >= this->bestBound+1e-5)
540      {
541        this->bestBound = this->getModel()->getBestPossibleObjValue();
542        const CbcModel *model = this->getModel();
543        double secs = model->getCurrentSeconds();
544        this->progr_callback((void *) model, 0, model->getNodeCount(), "bnd", secs, bestBound, bestCost, 0, NULL, this->pgAppData);
545      } // improved lower bound
546#ifdef CBC_THREAD
547    assert(this->cbcMutex);
548    pthread_mutex_unlock((this->cbcMutex));
549#endif
550    } // has progress callback
551  } // not in subtree
552
553  return noAction;
554}
555
556
557//-------------------------------------------------------------------
558// Default Constructor
559//-------------------------------------------------------------------
560Cbc_MessageHandler::Cbc_MessageHandler()
561  : CoinMessageHandler()
562  , model_(NULL)
563  , callback_(NULL)
564{
565}
566
567//-------------------------------------------------------------------
568// Copy constructor
569//-------------------------------------------------------------------
570Cbc_MessageHandler::Cbc_MessageHandler(const Cbc_MessageHandler &rhs)
571  : CoinMessageHandler(rhs)
572  , model_(rhs.model_)
573  , callback_(rhs.callback_)
574{
575}
576
577Cbc_MessageHandler::Cbc_MessageHandler(const CoinMessageHandler &rhs)
578  : CoinMessageHandler(rhs)
579  , model_(NULL)
580  , callback_(NULL)
581{
582}
583
584// Constructor with pointer to model
585Cbc_MessageHandler::Cbc_MessageHandler(Cbc_Model *model,
586  FILE * /*userPointer*/)
587  : CoinMessageHandler()
588  , model_(model)
589  , callback_(NULL)
590{
591}
592
593//-------------------------------------------------------------------
594// Destructor
595//-------------------------------------------------------------------
596Cbc_MessageHandler::~Cbc_MessageHandler()
597{
598}
599
600//----------------------------------------------------------------
601// Assignment operator
602//-------------------------------------------------------------------
603Cbc_MessageHandler &
604Cbc_MessageHandler::operator=(const Cbc_MessageHandler &rhs)
605{
606  if (this != &rhs) {
607    CoinMessageHandler::operator=(rhs);
608    model_ = rhs.model_;
609    callback_ = rhs.callback_;
610  }
611  return *this;
612}
613//-------------------------------------------------------------------
614// Clone
615//-------------------------------------------------------------------
616CoinMessageHandler *Cbc_MessageHandler::clone() const
617{
618  return new Cbc_MessageHandler(*this);
619}
620int Cbc_MessageHandler::print()
621{
622  if (callback_) {
623    int messageNumber = currentMessage().externalNumber();
624    if (currentSource() != "Cbc")
625      messageNumber += 1000000;
626    int i;
627    int nDouble = numberDoubleFields();
628    assert(nDouble <= 200);
629    double vDouble[200];
630    for (i = 0; i < nDouble; i++)
631      vDouble[i] = doubleValue(i);
632    int nInt = numberIntFields();
633    assert(nInt <= 200);
634    int vInt[200];
635    for (i = 0; i < nInt; i++)
636      vInt[i] = intValue(i);
637    int nString = numberStringFields();
638    assert(nString <= 200);
639    char *vString[200];
640    for (i = 0; i < nString; i++) {
641      std::string value = stringValue(i);
642      vString[i] = CoinStrdup(value.c_str());
643    }
644    callback_(model_, messageNumber,
645      nDouble, vDouble,
646      nInt, vInt,
647      nString, vString);
648    for (i = 0; i < nString; i++)
649      free(vString[i]);
650  }
651  return CoinMessageHandler::print();
652  return 0;
653}
654const Cbc_Model *
655Cbc_MessageHandler::model() const
656{
657  return model_;
658}
659void Cbc_MessageHandler::setModel(Cbc_Model *model)
660{
661  model_ = model;
662}
663// Call back
664void Cbc_MessageHandler::setCallBack(cbc_callback callback)
665{
666  callback_ = callback;
667}
668
669#include <string>
670#include <stdio.h>
671#include <iostream>
672
673#if defined(__MWERKS__)
674#pragma export on
675#endif
676
677/* Version */
678const char *CBC_LINKAGE Cbc_getVersion()
679{
680  return CBC_VERSION;
681}
682 
683static void Cbc_flushCols(Cbc_Model *model) {
684  if (model->nCols == 0)
685    return;
686
687  OsiSolverInterface *solver = model->solver_;
688
689  int colsBefore = solver->getNumCols();
690  solver->addCols( model->nCols, model->cStart, model->cIdx, model->cCoef, model->cLB, model->cUB, model->cObj );
691
692  if (model->nInt) {
693    for ( int i=0 ; i<model->nCols; ++i )
694      if (model->cInt[i])
695        solver->setInteger( colsBefore+i );
696  }
697
698  for ( int i=0 ; i<model->nCols; ++i )
699    solver->setColName( colsBefore+i, std::string(model->cNames+model->cNameStart[i]) );
700
701  model->nCols = 0;
702  model->cStart[0] = 0;
703  model->nInt = 0;
704  model->cNameStart[0] = 0;
705}
706
707static void Cbc_flushRows(Cbc_Model *model) {
708  if (model->nRows == 0)
709    return;
710
711  OsiSolverInterface *solver = model->solver_;
712
713  int rowsBefore = solver->getNumRows();
714  solver->addRows(model->nRows, model->rStart, model->rIdx, model->rCoef, model->rLB, model->rUB);
715
716  for ( int i=0 ; i<model->nRows; ++i )
717  {
718    const int rIdx = rowsBefore+i;
719    const std::string rName = std::string(model->rNames+model->rNameStart[i]);
720    solver->setRowName(rIdx, rName);
721  }
722
723  model->nRows = 0;
724  model->rStart[0] = 0;
725  model->rNameStart[0] = 0;
726}
727
728// flushes buffers of new variables
729static void Cbc_flush( Cbc_Model *model)
730{
731#ifdef DEBUG
732  if (model->rStart && model->cStart) {
733    assert( model->rStart[model->nRows] == 0 || model->cStart[model->nCols] == 0 );
734  }
735#endif
736
737  if ( model->rStart && model->rStart[model->nRows] == 0 ) {
738    // rows have no reference to columns, so rows can be added first
739    Cbc_flushRows(model);
740    Cbc_flushCols(model);
741  }
742  else
743  {
744    // cols have no reference to columns, so rows can be added first
745    Cbc_flushCols(model);
746    Cbc_flushRows(model);
747  }
748}
749
750static void Cbc_checkSpaceColBuffer( Cbc_Model *model, int additionlNameSpace, int additionalNzSpace )
751{
752  // initialize buffer
753  if ( model->colSpace == 0 )
754  {
755    // initial buffer allocation
756    model->colSpace = INI_COL_SPACE;
757    int c = model->colSpace;
758    model->nCols = 0;
759    model->cNameSpace = max(INI_COL_SPACE*7, additionlNameSpace*10);
760
761    model->cNameStart = (int *) xmalloc( sizeof(int)*c );
762    model->cNameStart[0] = 0;
763
764    model->cInt = (char *) xmalloc( sizeof(char)*c );
765    model->cNames = (char *) xmalloc( sizeof(char)*model->cNameSpace );
766    model->cLB = (double *) xmalloc( sizeof(double)*c );
767    model->cUB = (double *)xmalloc( sizeof(double)*c );
768    model->cObj = (double *)xmalloc( sizeof(double)*c );
769    model->cStart = (CoinBigIndex *) xmalloc( sizeof(CoinBigIndex)*c );
770    model->cStart[0] = 0;
771
772    model->cElementsSpace = max(INI_COL_SPACE*5, additionalNzSpace*10);
773    model->cIdx = (int *) xmalloc( sizeof(int)*model->cElementsSpace );
774    model->cCoef = (double *) xmalloc( sizeof(double)*model->cElementsSpace );
775  }
776  else
777  {
778    // already allocated, checking for resizes
779
780    // check buffer space
781    if (model->nCols+2 >= model->colSpace)
782    {
783      model->colSpace *= 2;
784      int c = model->colSpace;
785
786      model->cNameStart = (int *) xrealloc( model->cNameStart, sizeof(int)*c );
787      model->cInt = (char *) xrealloc( model->cInt, sizeof(char)*c );
788      model->cLB = (double *) xrealloc( model->cLB, sizeof(double)*c );
789      model->cUB = (double *) xrealloc( model->cUB, sizeof(double)*c );
790      model->cObj = (double *) xrealloc( model->cObj, sizeof(double)*c );
791      model->cStart = (CoinBigIndex *) xrealloc( model->cStart, sizeof(CoinBigIndex)*c );
792    }
793    // check string buffer space
794    int slen = additionlNameSpace + 1;
795    int reqsize = slen + model->cNameStart[model->nCols]+1;
796    if (reqsize>model->cNameSpace)
797    {
798      model->cNameSpace = max(model->cNameSpace*2, additionlNameSpace);
799      model->cNames = (char *) xrealloc( model->cNames, sizeof(char)*model->cNameSpace );
800    }
801
802    if (model->cStart[model->nCols]+additionalNzSpace+1 >= model->cElementsSpace) {
803      model->cElementsSpace = std::max(model->cStart[model->nCols]+additionalNzSpace+1, model->cElementsSpace*2);
804      model->cIdx = (int *) xrealloc( model->cIdx, sizeof(int)*model->cElementsSpace );
805      model->cCoef = (double *) xrealloc( model->cCoef, sizeof(double)*model->cElementsSpace );
806    } // space on column non-zeros
807
808  } // additional allocations
809
810}
811
812static void Cbc_addColBuffer( Cbc_Model *model,
813    const char *name, 
814    int rNz, int *rIdx, double *rCoef,
815    double lb, double ub, double obj,
816    char isInteger )
817{
818#define MAX_COL_NAME_SIZE 1024
819  Cbc_checkSpaceColBuffer( model, MAX_COL_NAME_SIZE, rNz );
820  int p = model->nCols;
821  model->cInt[p] = isInteger;
822  model->cLB[p] = lb;
823  model->cUB[p] = ub;
824  model->cObj[p] = obj;
825  model->nInt += (int)isInteger;
826
827  int ps = model->cNameStart[p];
828  strncpy( model->cNames+ps, name, MAX_COL_NAME_SIZE );
829  int len = min( (int)strlen(name), MAX_COL_NAME_SIZE );
830
831  int stNz = model->cStart[p];
832
833  if (rNz) {
834#ifdef DEBUG
835    for ( int i=0 ; (i<rNz) ; ++i ) {
836      VALIDATE_ROW_INDEX(rIdx[i], model);
837    }
838#endif
839    memcpy( model->cIdx+stNz, rIdx, sizeof(int)*rNz  );
840    memcpy( model->cCoef+stNz, rCoef, sizeof(double)*rNz  );
841  }
842
843  model->nCols++;
844  model->cNameStart[model->nCols] = ps + len + 1;
845  model->cStart[model->nCols] = stNz + rNz;
846#undef MAX_COL_NAME_SIZE
847}
848
849static void Cbc_deleteColBuffer( Cbc_Model *model )
850{
851  if (model->colSpace == 0)
852    return;
853
854  free(model->cNameStart);
855  free(model->cInt);
856  free(model->cNames);
857  free(model->cLB);
858  free(model->cUB);
859  free(model->cObj);
860  free(model->cStart);
861  free(model->cIdx);
862  free(model->cCoef);
863
864  model->cNameStart = NULL;
865  model->cInt = NULL;
866  model->cNames = NULL;
867  model->cLB = NULL;
868  model->cUB = NULL;
869  model->cObj = NULL;
870  model->cStart = NULL;
871  model->cIdx = NULL;
872  model->cCoef = NULL;
873
874  model->colSpace = model->cNameSpace = model->cElementsSpace = model->nCols = model->nInt = 0;
875}
876
877static void Cbc_checkSpaceRowBuffer(Cbc_Model *model, int nzRow, int rowNameLen)
878{
879  if (model->rowSpace == 0)
880  {
881    // allocating buffer
882    model->rowSpace = INI_ROW_SPACE;
883    model->rStart = (CoinBigIndex *)xmalloc(sizeof(CoinBigIndex)*model->rowSpace);
884    model->rStart[0] = 0;
885    model->rLB = (double *)xmalloc(sizeof(double)*model->rowSpace);
886    model->rUB = (double *)xmalloc(sizeof(double)*model->rowSpace);
887    model->rNameStart = (int *)xmalloc(sizeof(int)*model->rowSpace);
888    model->rNameStart[0] = 0;
889
890    model->rElementsSpace = std::max(INI_ROW_SPACE*15, nzRow*10);
891    model->rIdx = (int *)xmalloc(sizeof(int)*model->rElementsSpace);
892    model->rCoef = (double *)xmalloc(sizeof(double)*model->rElementsSpace);
893
894    model->rNameSpace = max(INI_ROW_SPACE*10, rowNameLen*10);
895    model->rNames = (char *)xmalloc(sizeof(char)*model->rNameSpace);
896  }
897  else
898  {
899    // checking if some resize is needed
900    if (model->nRows+2 >= model->rowSpace)
901    {
902      model->rowSpace = std::max(2*model->rowSpace, model->nRows+2);
903      model->rStart = (CoinBigIndex *)xrealloc(model->rStart, sizeof(CoinBigIndex)*model->rowSpace);
904      model->rLB = (double *)xrealloc(model->rLB, sizeof(double)*model->rowSpace);
905      model->rUB = (double *)xrealloc(model->rUB, sizeof(double)*model->rowSpace);
906      model->rNameStart = (int *)xrealloc(model->rNameStart, sizeof(int)*model->rowSpace);
907    } // rowSpace
908
909    if (model->rStart[model->nRows]+nzRow+1 >= model->rElementsSpace)
910    {
911      model->rElementsSpace = std::max(2*model->rElementsSpace, model->rStart[model->nRows]+nzRow+1);
912      model->rIdx = (int *)xrealloc(model->rIdx, sizeof(int)*model->rElementsSpace);
913      model->rCoef = (double *)xrealloc(model->rCoef, sizeof(double)*model->rElementsSpace);
914    } // elements space
915
916    if (model->rNameStart[model->nRows]+rowNameLen+2 >= model->rNameSpace)
917    {
918      model->rNameSpace = std::max(model->rNameSpace*2, model->rNameSpace+rowNameLen+2);
919      model->rNames = (char *)xrealloc(model->rNames, sizeof(char)*model->rNameSpace);
920    } // row names resize
921  } // checks for resize
922} // Cbc_checkSpaceRowBuffer
923
924static void Cbc_addRowBuffer(
925    Cbc_Model *model,
926    int nz,
927    const int *rIdx,
928    const double *rCoef,
929    double rLB,
930    double rUB,
931    const char *rName)
932{
933#ifdef DEBUG
934  {
935    std::vector< char > iv = std::vector<char>( Cbc_getNumCols(model), 0 );
936    for ( int i=0 ; i<nz ; ++i ) {
937      VALIDATE_COL_INDEX(rIdx[i], model);
938      if (iv[rIdx[i]] >= 1) {
939        fprintf(stderr, "Error in Cbc_addRow: adding row with repeated column (%d) indexes \n", rIdx[i] );
940        exit(1);
941      }
942      iv[rIdx[i]]++;
943    }
944  }
945#endif
946  int nameLen = (int)strlen(rName);
947  Cbc_checkSpaceRowBuffer(model, nz, nameLen);
948  const int st = model->rStart[model->nRows];
949
950  model->rLB[model->nRows] = rLB;
951  model->rUB[model->nRows] = rUB;
952  memcpy(model->rIdx + st, rIdx, sizeof(int)*nz);
953  memcpy(model->rCoef + st, rCoef, sizeof(double)*nz);
954
955  char *spcName = model->rNames + model->rNameStart[model->nRows];
956  strcpy(spcName, rName);
957
958  model->nRows++;
959  model->rStart[model->nRows] = st + nz;
960  model->rNameStart[model->nRows] = model->rNameStart[model->nRows-1] + nameLen + 1;
961}
962
963static void Cbc_deleteRowBuffer(Cbc_Model *model)
964{
965  if (model->rowSpace == 0)
966    return;
967
968  free(model->rStart);
969  free(model->rLB);
970  free(model->rUB);
971  free(model->rNameStart);
972  free(model->rIdx);
973  free(model->rCoef);
974  free(model->rNames);
975
976  model->rStart = NULL;
977  model->rLB = NULL;
978  model->rUB = NULL;
979  model->rNameStart = NULL;
980  model->rIdx = NULL;
981  model->rCoef = NULL;
982  model->rNames = NULL;
983
984  model->rowSpace = 0;
985  model->nRows = 0;
986  model->rNameSpace = 0;
987  model->rElementsSpace = 0;
988}
989
990static void Cbc_iniBuffer(Cbc_Model *model) 
991{
992  // initialize columns buffer
993  model->colSpace = 0;
994  model->nCols = 0;
995  model->cNameSpace = 0;
996  model->cNameStart = NULL;
997  model->cInt = NULL;
998  model->cNames= NULL;
999  model->cLB = NULL;
1000  model->cUB = NULL;
1001  model->cObj = NULL;
1002  model->cStart = NULL;
1003  model->cIdx = NULL;
1004  model->cCoef = NULL;
1005  model->nInt = 0;
1006  model->cElementsSpace = 0;
1007
1008  // initialize rows buffer
1009  model->rowSpace = 0;
1010  model->nRows = 0;
1011  model->rNameSpace = 0;
1012  model->rNameStart = 0;
1013  model->rNames = NULL;
1014  model->rLB = NULL;
1015  model->rUB = NULL;
1016  model->rElementsSpace = 0;
1017  model->rStart = NULL;
1018  model->rIdx = NULL;
1019  model->rCoef = NULL;
1020
1021  // SOS buffer
1022  model->nSos = 0;
1023  model->sosCap = 0;
1024  model->sosSize = 0;
1025  model->sosElCap = 0;
1026  model->sosElSize = 0;
1027  model->sosRowStart = NULL;
1028  model->sosEl = NULL;
1029  model->sosElWeight = NULL;
1030  model->sosType = NULL;
1031
1032  model->nColsMS = 0;
1033  model->colNamesMS = NULL;
1034  model->colValuesMS = NULL;
1035}
1036
1037static void Cbc_iniParams( Cbc_Model *model );
1038
1039/* Default Cbc_Model constructor */
1040Cbc_Model *CBC_LINKAGE
1041Cbc_newModel()
1042{
1043  Cbc_Model *model = new Cbc_Model();
1044
1045  Cbc_iniParams(model);
1046 
1047  model->solver_ = new OsiClpSolverInterface();
1048  model->relax_ = 0;
1049  model->obj_value = COIN_DBL_MAX;
1050
1051  model->cbcModel_ = NULL;
1052
1053  model->inc_callback = NULL;
1054  model->progr_callback = NULL;
1055  model->userCallBack = NULL;
1056
1057  model->cut_callback = NULL;
1058  model->cutCBData = NULL;
1059  model->cutCBhowOften = -1;
1060  model->cutCBAtSol = 0;
1061 
1062  model->lastOptimization = ModelNotOptimized;
1063  model->lastOptNCols = 0;
1064  model->lastOptNRows = 0;
1065  model->lastOptMIPSol = NULL;
1066  model->slack_ = NULL;
1067
1068  model->icAppData = NULL;
1069  model->pgrAppData = NULL;
1070  model->colNameIndex = NULL;
1071  model->rowNameIndex = NULL;
1072  model->iniObj = DBL_MAX;
1073
1074  model->iniSol = NULL;
1075
1076
1077  Cbc_iniBuffer(model);
1078
1079#ifdef CBC_THREAD
1080  pthread_mutex_init(&(model->cbcMutexCG), NULL);
1081  pthread_mutex_init(&(model->cbcMutexEvent), NULL);
1082#endif
1083
1084  model->lazyConstrs = NULL;
1085
1086  return model;
1087}
1088
1089/* Cbc_Model Destructor */
1090void CBC_LINKAGE
1091Cbc_deleteModel(Cbc_Model *model)
1092{
1093  Cbc_deleteColBuffer(model);
1094  Cbc_deleteRowBuffer(model);
1095
1096  if (model->sosRowStart) {
1097    free(model->sosRowStart);
1098    free(model->sosEl);
1099    free(model->sosElWeight);
1100    free(model->sosType);
1101  }
1102
1103  if (model->cg_space) {
1104    free( model->cg_iv );
1105    free( model->cg_neighs );
1106  }
1107
1108  if (model->slack_) {
1109    free(model->slack_);
1110  }
1111
1112  if (model->lastOptMIPSol)
1113    delete[] model->lastOptMIPSol;
1114
1115#ifdef CBC_THREAD
1116  pthread_mutex_destroy(&(model->cbcMutexCG));
1117  pthread_mutex_destroy(&(model->cbcMutexEvent));
1118#endif
1119
1120  if (model->colNameIndex)
1121  {
1122    NameIndex *m = (NameIndex *)model->colNameIndex;
1123    delete m;
1124    m = (NameIndex *)model->rowNameIndex;
1125    assert( m != NULL );
1126    delete m;
1127  }
1128
1129  if (model->cbcModel_)
1130    delete model->cbcModel_;
1131
1132  if (model->solver_)
1133    delete model->solver_;
1134
1135  if (model->iniSol)
1136    delete model->iniSol;
1137
1138  if (model->nColsMS) {
1139    if (model->colNamesMS) {
1140      free(model->colNamesMS[0]);
1141      free(model->colNamesMS);
1142    }
1143    free(model->colValuesMS);
1144  }
1145
1146  if (model->lazyConstrs)
1147    delete model->lazyConstrs;
1148
1149  delete model;
1150}
1151
1152/* Loads a problem (the constraints on the
1153    rows are given by lower and upper bounds). If a pointer is NULL then the
1154    following values are the default:
1155    <ul>
1156    <li> <code>colub</code>: all columns have upper bound infinity
1157    <li> <code>collb</code>: all columns have lower bound 0
1158    <li> <code>rowub</code>: all rows have upper bound infinity
1159    <li> <code>rowlb</code>: all rows have lower bound -infinity
1160    <li> <code>obj</code>: all variables have 0 objective coefficient
1161    </ul>
1162
1163   Just like the other loadProblem() method except that the matrix is
1164   given in a standard column major ordered format (without gaps).
1165*/
1166void CBC_LINKAGE
1167Cbc_loadProblem(Cbc_Model *model, const int numcols, const int numrows,
1168  const CoinBigIndex *start, const int *index,
1169  const double *value,
1170  const double *collb, const double *colub,
1171  const double *obj,
1172  const double *rowlb, const double *rowub)
1173{
1174  OsiSolverInterface *solver = model->solver_;
1175
1176  solver->loadProblem(numcols, numrows, start, index, value,
1177    collb, colub, obj, rowlb, rowub);
1178} //  Cbc_loadProblem()
1179
1180/* should be called after reading a new problem */
1181static void fillAllNameIndexes(Cbc_Model *model)
1182{
1183  if (!model->colNameIndex)
1184    return;
1185
1186  OsiSolverInterface *solver = model->solver_;
1187  NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
1188  colNameIndex.clear();
1189  NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
1190  rowNameIndex.clear();
1191
1192  for ( int i=0 ; (i<solver->getNumCols()) ; ++i )
1193    colNameIndex[solver->getColName(i)] = i;
1194
1195  for ( int i=0 ; (i<solver->getNumRows()) ; ++i )
1196    rowNameIndex[solver->getRowName(i)] = i;
1197}
1198
1199/** Reads an MPS file
1200 *
1201 * @param model problem object
1202 * @param fileName file name
1203 **/
1204int CBC_LINKAGE
1205Cbc_readMps(Cbc_Model *model, const char *filename)
1206{
1207  int result = 1;
1208  OsiSolverInterface *solver = model->solver_;
1209  result = solver->readMps(filename);
1210  assert(result == 0);
1211
1212  Cbc_deleteColBuffer(model);
1213  Cbc_deleteRowBuffer(model);
1214  Cbc_iniBuffer(model);
1215
1216  fillAllNameIndexes(model);
1217
1218  return result;
1219}
1220
1221/** Writes an MPS file
1222 *
1223 * @param model problem object
1224 * @param fileName file name
1225 **/
1226void CBC_LINKAGE
1227Cbc_writeMps(Cbc_Model *model, const char *filename)
1228{
1229  Cbc_flush(model);
1230
1231  model->solver_->writeMps(filename, "mps", Cbc_getObjSense(model));
1232}
1233
1234/** Writes an LP file
1235 *
1236 * @param model problem object
1237 * @param fileName file name */
1238void CBC_LINKAGE
1239Cbc_writeLp(Cbc_Model *model, const char *filename)
1240{
1241  Cbc_flush(model);
1242
1243  char outFile[512];
1244  strncpy(outFile, filename, 511);
1245
1246  char *s = NULL;
1247  if ((s = strstr(outFile, ".lp"))) {
1248    if (s != outFile) // not at the start
1249      *s = '\0';
1250  }
1251
1252  model->solver_->writeLp(outFile);
1253}
1254
1255/** Reads an LP file
1256 *
1257 * @param model problem object
1258 * @param fileName file name */
1259int CBC_LINKAGE
1260Cbc_readLp(Cbc_Model *model, const char *filename)
1261{
1262  int result = 1;
1263  OsiSolverInterface *solver = model->solver_;
1264  result = solver->readLp(filename);
1265  assert(result == 0);
1266
1267  Cbc_deleteColBuffer(model);
1268  Cbc_deleteRowBuffer(model);
1269  Cbc_iniBuffer(model);
1270
1271  fillAllNameIndexes(model);
1272
1273  return result;
1274}
1275
1276/** @brief If Cbc was built with gzip compressed files support
1277  *
1278  * @return 1 if yes, 0 otherwise
1279  **/
1280char CBC_LINKAGE
1281Cbc_supportsGzip() {
1282  return (char)CoinFileInput::haveGzipSupport();
1283}
1284
1285/** @brief If Cbc was built with bzip2 compressed files support
1286  *
1287  * @return 1 if yes, 0 otherwise
1288  **/
1289char CBC_LINKAGE
1290Cbc_supportsBzip2() {
1291  return (char)CoinFileInput::haveBzip2Support();
1292}
1293
1294
1295
1296/* Sets an initial feasible solution
1297 *
1298 * @param model problem object
1299 **/
1300void CBC_LINKAGE
1301Cbc_setInitialSolution(Cbc_Model *model, const double *sol)
1302{
1303  Cbc_flush(model);
1304  int n = Cbc_getNumCols(model);
1305  // We need to manually compute the objective here for some reason
1306  const double *objvec = Cbc_getObjCoefficients(model);
1307  double objval = 0;
1308  for (int i = 0; i < n; i++) {
1309    objval += objvec[i] * sol[i];
1310  }
1311
1312  if (model->iniSol) {
1313    model->iniSol->resize( Cbc_getNumCols(model) );
1314    double *iniSol = &((*model->iniSol)[0]);
1315    memcpy( iniSol, sol, sizeof(double)*Cbc_getNumCols(model) );
1316  } else {
1317    model->iniSol = new vector<double>(sol, sol+n);
1318  }
1319
1320  model->iniObj = objval;
1321}
1322
1323
1324void CBC_LINKAGE
1325Cbc_setIntParam(Cbc_Model *model, enum IntParam which, const int val) {
1326  assert(which < N_INT_PARAMS);
1327  model->int_param[which] = val;
1328}
1329
1330void CBC_LINKAGE
1331Cbc_setDblParam(Cbc_Model *model, enum DblParam which, const double val) {
1332  assert(which < N_DBL_PARAMS);
1333  model->dbl_param[which] = val;
1334}
1335
1336void CBC_LINKAGE
1337Cbc_setParameter(Cbc_Model *model, const char *name, const char *value)
1338{
1339  if (model->cbcOptions.find(string(name))==model->cbcOptions.end())
1340    model->vcbcOptions.push_back(string(name));
1341  model->cbcOptions[name] = string(value);
1342}
1343
1344/* Fills in array with problem name  */
1345void CBC_LINKAGE
1346Cbc_problemName(Cbc_Model *model, int maxNumberCharacters, char *array)
1347{
1348  std::string name;
1349  model->solver_->getStrParam(OsiProbName, name);
1350  strncpy(array, name.c_str(), maxNumberCharacters);
1351}
1352/* Sets problem name.  Must have \0 at end.  */
1353int CBC_LINKAGE
1354Cbc_setProblemName(Cbc_Model *model, const char *array)
1355{
1356  bool result = false;
1357  result = model->solver_->setStrParam(OsiProbName, array);
1358
1359  return (result) ? 1 : 0;
1360}
1361
1362int CBC_LINKAGE Cbc_status(Cbc_Model *model) {
1363  switch (model->lastOptimization) {
1364    case ModelNotOptimized:
1365      fprintf( stderr, "Status not available, model was not optimized yet.\n");
1366      abort();
1367      break;
1368    case ContinuousOptimization:
1369      fprintf( stderr, "Cbc_status only available for MIP models.\n");
1370      abort();
1371      break;
1372    case IntegerOptimization:
1373      return model->cbcModel_->status();
1374  }
1375
1376  return INT_MAX;
1377}
1378
1379
1380int CBC_LINKAGE
1381Cbc_secondaryStatus(Cbc_Model *model) {
1382  switch (model->lastOptimization) {
1383    case ModelNotOptimized:
1384      fprintf( stderr, "Status not available, model was not optimized yet.\n");
1385      abort();
1386      break;
1387    case ContinuousOptimization:
1388      fprintf( stderr, "Cbc_status only available for MIP models.\n");
1389      abort();
1390      break;
1391    case IntegerOptimization:
1392      return model->cbcModel_->secondaryStatus();
1393  }
1394
1395  return INT_MAX;
1396}
1397
1398/* Number of elements in matrix */
1399int CBC_LINKAGE
1400Cbc_getNumElements(Cbc_Model *model)
1401{
1402  int tmpNZCols = 0, tmpNZRows = 0;
1403  if (model->cStart)
1404    tmpNZCols = model->cStart[model->nCols];
1405
1406  if (model->rStart)
1407    tmpNZRows = model->rStart[model->nRows];
1408
1409  return model->solver_->getNumElements() +
1410    tmpNZCols + tmpNZRows;
1411}
1412
1413const void *Cbc_conflictGraph( Cbc_Model *model ) {
1414  return model->solver_->getCGraph();
1415}
1416
1417/** @brief Updates (or creates, if first time) the conflict graph
1418 *
1419 * @param model problem object
1420 **/
1421void Cbc_updateConflictGraph( Cbc_Model *model ) {
1422  model->solver_->checkCGraph();
1423}
1424
1425int CBC_LINKAGE
1426Cbc_getNumIntegers(Cbc_Model *model)
1427{
1428  return model->solver_->getNumIntegers() + model->nInt;
1429}
1430
1431// Column starts in matrix
1432const CoinBigIndex *CBC_LINKAGE
1433Cbc_getVectorStarts(Cbc_Model *model)
1434{
1435  Cbc_flush(model);
1436
1437  const CoinPackedMatrix *matrix = NULL;
1438  matrix = model->solver_->getMatrixByCol();
1439  return (matrix == NULL) ? NULL : matrix->getVectorStarts();
1440}
1441
1442// Row indices in matrix
1443const int *CBC_LINKAGE
1444Cbc_getIndices(Cbc_Model *model)
1445{
1446  Cbc_flush(model);
1447
1448  const int *result = NULL;
1449  const CoinPackedMatrix *matrix = NULL;
1450  matrix = model->solver_->getMatrixByCol();
1451  result = (matrix == NULL) ? NULL : matrix->getIndices();
1452
1453  return result;
1454}
1455
1456// Element values in matrix
1457const double *CBC_LINKAGE
1458Cbc_getElements(Cbc_Model *model)
1459{
1460  Cbc_flush(model);
1461
1462  const double *result = NULL;
1463  const CoinPackedMatrix *matrix = NULL;
1464  matrix = model->solver_->getMatrixByCol();
1465  result = (matrix == NULL) ? NULL : matrix->getElements();
1466
1467  return result;
1468}
1469// ======================================================================
1470
1471/* Pass in Callback function */
1472void CBC_LINKAGE
1473Cbc_registerCallBack(Cbc_Model *model,
1474  cbc_callback userCallBack)
1475{
1476  model->userCallBack = userCallBack;
1477}
1478/* Unset Callback function */
1479void CBC_LINKAGE
1480Cbc_clearCallBack(Cbc_Model *model)
1481{
1482  model->userCallBack = NULL;
1483}
1484
1485/* length of names (0 means no names0 */
1486size_t CBC_LINKAGE
1487Cbc_maxNameLength(Cbc_Model *model)
1488{
1489  size_t result = 0;
1490  OsiSolverInterface::OsiNameVec const &rownames = model->solver_->getRowNames();
1491  for (size_t i = 0; i < rownames.size(); i++) {
1492    if (rownames[i].length() > result)
1493      result = rownames[i].length();
1494  }
1495  OsiSolverInterface::OsiNameVec const &colnames = model->solver_->getColNames();
1496  for (size_t i = 0; i < colnames.size(); i++) {
1497    if (colnames[i].length() > result)
1498      result = colnames[i].length();
1499  }
1500
1501  // go trough buffered names also
1502  for ( size_t i=0 ; (i<(size_t)model->nCols) ; ++i )
1503    result = max( result, strlen(model->cNames+model->cNameStart[i]) );
1504
1505  for ( size_t i=0 ; (i<(size_t)model->nRows) ; ++i )
1506    result = max( result, strlen(model->rNames+model->rNameStart[i]) );
1507
1508  return result;
1509}
1510
1511void CBC_LINKAGE
1512Cbc_getRowName(Cbc_Model *model, int iRow, char *name, size_t maxLength)
1513{
1514  VALIDATE_ROW_INDEX( iRow, model );
1515
1516  if (iRow < model->solver_->getNumRows()) {
1517    std::string rowname = model->solver_->getRowName(iRow);
1518    strncpy(name, rowname.c_str(), maxLength);
1519    name[maxLength - 1] = '\0';
1520  } else {
1521    int idxRowBuffer = iRow - model->solver_->getNumRows();
1522    strncpy( name, model->rNames+model->rNameStart[idxRowBuffer], maxLength );
1523  }
1524}
1525
1526void CBC_LINKAGE
1527Cbc_getColName(Cbc_Model *model, int iColumn, char *name, size_t maxLength)
1528{
1529  VALIDATE_COL_INDEX( iColumn, model );
1530
1531  if (iColumn < model->solver_->getNumCols()) {
1532    std::string colname = model->solver_->getColName(iColumn);
1533    strncpy(name, colname.c_str(), maxLength);
1534    name[maxLength - 1] = '\0';
1535  } else {
1536    int idxColBuffer = iColumn - model->solver_->getNumCols();
1537    strncpy( name, model->cNames+model->cNameStart[idxColBuffer], maxLength );
1538  }
1539
1540}
1541
1542void CBC_LINKAGE
1543Cbc_setColName(Cbc_Model *model, int iColumn, const char *name)
1544{
1545  VALIDATE_COL_INDEX( iColumn, model );
1546
1547  Cbc_flush(model);
1548  OsiSolverInterface *solver = model->solver_;
1549  std::string previousName = solver->getColName(iColumn);
1550  solver->setColName(iColumn, name);
1551
1552  if (!model->colNameIndex)
1553    return;
1554  NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
1555  NameIndex::iterator it = colNameIndex.find(previousName);
1556  if (it!=colNameIndex.end())
1557    colNameIndex.erase(it);
1558  colNameIndex[name] = iColumn;
1559}
1560
1561void CBC_LINKAGE
1562Cbc_setRowName(Cbc_Model *model, int iRow, const char *name)
1563{
1564  VALIDATE_ROW_INDEX( iRow, model );
1565
1566  Cbc_flush(model);
1567  OsiSolverInterface *solver = model->solver_;
1568  std::string previousName = solver->getRowName(iRow);
1569  solver->setRowName(iRow, name);
1570
1571  if (!model->rowNameIndex)
1572    return;
1573  NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
1574  NameIndex::iterator it = rowNameIndex.find(std::string(previousName));
1575  if (it!=rowNameIndex.end())
1576    rowNameIndex.erase(it);
1577  rowNameIndex[name] = iRow;
1578}
1579
1580void CBC_LINKAGE
1581Cbc_setSolveRelax(Cbc_Model *model, char solveOnlyRelax)
1582{
1583  model->relax_ = solveOnlyRelax;
1584}
1585
1586static int cbc_callb(CbcModel *cbcModel, int whereFrom) {
1587  Cbc_EventHandler *cbc_eh = dynamic_cast<Cbc_EventHandler *>(cbcModel->getEventHandler());
1588  if (cbc_eh == NULL)
1589    return 0;
1590
1591  if (cbc_eh->progr_callback != NULL)
1592  {
1593    switch (whereFrom)
1594    {
1595      case 1:
1596        cbc_eh->progr_callback(cbcModel, 0, 0, "root lp relax", cbcModel->getCurrentSeconds(),
1597                               cbcModel->getBestPossibleObjValue(), DBL_MAX, 0, NULL, cbc_eh->pgAppData);
1598        break;
1599      case 2:
1600        cbc_eh->progr_callback(cbcModel, 0, 0, "pre-proc", cbcModel->getCurrentSeconds(),
1601                               cbcModel->getBestPossibleObjValue(), cbcModel->getObjValue(), 0, NULL, cbc_eh->pgAppData);
1602        break;
1603    } // where from
1604  } // has progress callback
1605
1606  return 0;
1607}
1608
1609// adds all sos objects to the current cbcModel_ object
1610static void Cbc_addAllSOS( Cbc_Model *model );
1611
1612// adds mipstart if available
1613static void Cbc_addMS( Cbc_Model *model );
1614
1615int CBC_LINKAGE
1616Cbc_solveLinearProgram(Cbc_Model *model) 
1617{
1618  CoinMessages generalMessages = model->solver_->getModelPtr()->messages();
1619  model->solver_->getModelPtr()->setRandomSeed( model->int_param[INT_PARAM_RANDOM_SEED] );
1620
1621  Cbc_flush( model );
1622
1623  OsiSolverInterface *solver = model->solver_;
1624
1625  solver->setDblParam( OsiPrimalTolerance, model->dbl_param[DBL_PARAM_PRIMAL_TOL]);
1626  solver->setDblParam( OsiDualTolerance, model->dbl_param[DBL_PARAM_DUAL_TOL]);
1627
1628  OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
1629  assert(clpSolver);
1630  ClpSimplex *clps = clpSolver->getModelPtr();
1631  assert(clps);
1632  clps->setPerturbation(model->int_param[INT_PARAM_PERT_VALUE]);
1633  solver->messageHandler()->setLogLevel( model->int_param[INT_PARAM_LOG_LEVEL] );
1634
1635  if (! cbc_annouced) {
1636    char generalPrint[512];
1637      sprintf(generalPrint,
1638        "Welcome to the CBC MILP Solver \n");
1639      if (strcmp(CBC_VERSION, "trunk")) {
1640        sprintf(generalPrint + strlen(generalPrint),
1641          "Version: %s \n", CBC_VERSION);
1642      } else {
1643        sprintf(generalPrint + strlen(generalPrint),
1644          "Version: Trunk\n");
1645      }
1646      sprintf(generalPrint + strlen(generalPrint),
1647        "Build Date: %s \n", __DATE__);
1648#ifdef CBC_SVN_REV
1649      sprintf(generalPrint + strlen(generalPrint),
1650        "Revision Number: %d \n", CBC_SVN_REV);
1651#endif
1652      solver->messageHandler()->setPrefix(false);
1653      solver->messageHandler()->message(CLP_GENERAL, generalMessages)
1654        << generalPrint
1655        << CoinMessageEol;
1656      solver->messageHandler()->setPrefix(true);
1657      cbc_annouced = 1;
1658  }
1659
1660  model->lastOptimization = ContinuousOptimization;
1661
1662  if (solver->basisIsAvailable()) {
1663    solver->resolve();
1664    if (solver->isProvenOptimal())
1665      return 0;
1666    if (solver->isIterationLimitReached())
1667      return 1;
1668    if (solver->isProvenDualInfeasible())
1669      return 3;
1670    if (solver->isProvenPrimalInfeasible())
1671      return 2;
1672  } // resolve
1673
1674  /* checking if options should be automatically tuned */
1675  if (model->lp_method == LPM_Auto) {
1676    ClpSimplexOther *clpo = static_cast<ClpSimplexOther *>(clps);
1677    assert(clpo);
1678    char *opts = clpo->guess(0);
1679    if (strstr(opts, "-primals") != NULL) {
1680      model->lp_method = LPM_Primal;
1681      //printf("Using primal;\n");
1682    }
1683    else if (strstr(opts, "-duals") != NULL) {
1684      model->lp_method = LPM_Dual;
1685      //printf("Using dual;\n");
1686    }
1687    else if (strstr(opts, "-barrier") != NULL) {
1688      //printf("Using barrier;\n");
1689      model->lp_method = LPM_Barrier;
1690    }
1691   
1692    char *s = NULL;
1693    char str[256] = "";
1694    if ((s=strstr(opts, "-idiot"))) {
1695      s = strstr(s+1, " ");
1696      if (s) {
1697        strcpy(str, s+1);
1698        if ((s = strstr(str+1, " ")))
1699          *s = '\0';
1700        int idiot = atoi(str);
1701        //printf("Setting idiot to %d\n", idiot);
1702        model->int_param[INT_PARAM_IDIOT] = idiot;
1703      }
1704    } // idiot
1705    if ((s=strstr(opts, "-pertv"))) {
1706      s = strstr(s+1, " ");
1707      if (s) {
1708        strcpy(str, s+1);
1709        if ((s = strstr(str+1, " ")))
1710          *s = '\0';
1711        int pertv = atoi(str);
1712        //printf("Setting pertv to %d\n", pertv);
1713        model->int_param[INT_PARAM_PERT_VALUE] = pertv;
1714      }
1715    } // perturbation value
1716    if ((s=strstr(opts, "-psi"))) {
1717      s = strstr(s+1, " ");
1718      if (s) {
1719        strcpy(str, s+1);
1720        if ((s = strstr(str+1, " ")))
1721          *s = '\0';
1722        double psi = atof(str);
1723        //printf("Setting psi to %g\n", psi);
1724        model->int_param[DBL_PARAM_PSI] = psi;
1725      }
1726    } // perturbation value
1727    if ((s=strstr(opts, "-dualpivot"))) {
1728        strcpy(str, s+1);
1729        if ((s = strstr(str+1, " ")))
1730          *s = '\0';
1731        if (strstr(str, "pesteep")) {
1732          model->dualp = DP_PESteepest;
1733          //printf("Setting dual pivot to pesteep.\n");
1734        }
1735    } // dual pivot
1736    delete[] opts;
1737  }
1738
1739  /* for integer or linear optimization starting with LP relaxation */
1740  ClpSolve clpOptions;
1741  char methodName[256] = "";
1742  switch (model->lp_method) {
1743    case LPM_Auto:
1744      fprintf(stderr, "Method should be already configured.\n");
1745      exit(1);
1746      break;
1747    case LPM_Primal:
1748      if (model->int_param[INT_PARAM_IDIOT] > 0) 
1749        clpOptions.setSpecialOption(1, 2, model->int_param[INT_PARAM_IDIOT]);
1750      clpOptions.setSolveType( ClpSolve::usePrimal );
1751      sprintf(methodName, "Primal Simplex");
1752      break;
1753    case LPM_Dual:
1754      clpOptions.setSolveType( ClpSolve::useDual );
1755      sprintf(methodName, "Dual Simplex");
1756      break;
1757    case LPM_Barrier:
1758      clpOptions.setSolveType( ClpSolve::useBarrier );
1759      clpOptions.setSpecialOption(4, 4);
1760      sprintf(methodName, "Barrier");
1761      break;
1762  }
1763  clpSolver->setSolveOptions(clpOptions);
1764
1765  switch (model->dualp) {
1766    case DP_Auto:
1767      {
1768        ClpDualRowSteepest asteep(3);
1769        clps->setDualRowPivotAlgorithm(asteep);
1770        break;
1771      }
1772    case DP_Dantzig:
1773      {
1774        ClpDualRowDantzig dantzig;
1775        clps->setDualRowPivotAlgorithm(dantzig);
1776        break;
1777      }
1778    case DP_Partial:
1779      {
1780        ClpDualRowSteepest bsteep(2);
1781        clps->setDualRowPivotAlgorithm(bsteep);
1782        break;
1783      }
1784    case DP_Steepest:
1785      {
1786        ClpDualRowSteepest csteep;
1787        clps->setDualRowPivotAlgorithm(csteep);
1788        break;
1789      }
1790    case DP_PESteepest:
1791      {
1792        ClpPEDualRowSteepest p(model->dbl_param[DBL_PARAM_PSI]);
1793        clps->setDualRowPivotAlgorithm(p);
1794        break;
1795      }
1796  }
1797 
1798  if (model->int_param[INT_PARAM_LOG_LEVEL] > 0)
1799  {
1800    char phaseName[128] = "";
1801    if (solver->getNumIntegers() && (!model->relax_))
1802      sprintf(phaseName, "Linear programming relaxation problem");
1803    else
1804      sprintf(phaseName, "Linear programming problem");
1805
1806    char msg[512] = "";
1807    sprintf(msg, "Starting solution of the %s using %s\n", phaseName, methodName );
1808    printf("%s\n", msg); fflush(stdout);
1809  }
1810
1811  model->lastOptimization = ContinuousOptimization;
1812  solver->initialSolve();
1813
1814  if (solver->isProvenOptimal()) {
1815    model->obj_value = solver->getObjValue();
1816    return 0;
1817  }
1818  if (solver->isIterationLimitReached()) {
1819    model->obj_value = solver->getObjValue();
1820    return 1;
1821  }
1822  if (solver->isProvenDualInfeasible())
1823    return 3;
1824  if (solver->isProvenPrimalInfeasible())
1825    return 2;
1826
1827  return -1;
1828}
1829
1830static void Cbc_updateSlack( Cbc_Model *model) {
1831  if (model->slack_) {
1832    free(model->slack_);
1833  }
1834
1835  int nRows = model->solver_->getNumRows(); 
1836  model->slack_ = (double *) xmalloc( sizeof(double)*nRows );
1837  const char *sense = model->solver_->getRowSense();
1838  const double *rrhs = model->solver_->getRightHandSide();
1839  const double *ractivity = model->lastOptimization == IntegerOptimization ? model->cbcModel_->getRowActivity() : model->solver_->getRowActivity();
1840  for ( int i=0 ; (i<nRows) ; ++i ) {
1841    const double rhs = rrhs[i];
1842    const double activity = ractivity[i];
1843    switch (sense[i]) {
1844      case 'L':
1845        model->slack_[i] = rhs-activity;
1846        break;
1847      case 'G':
1848        model->slack_[i] = activity-rhs;
1849        break;
1850      case 'E':
1851        model->slack_[i] = fabs(activity-rhs);
1852        break;
1853      case 'R':
1854        model->slack_[i] = min( model->solver_->getRowUpper()[i] - activity, 
1855                                activity - model->solver_->getRowLower()[i] );
1856        break;
1857    }
1858  }
1859}
1860
1861
1862void Cbc_strengthenPacking(Cbc_Model *model) {
1863  OsiSolverInterface *solver = model->solver_;
1864  CglCliqueStrengthening clqStr;
1865  clqStr.strengthenCliques(*solver);
1866}
1867
1868int CBC_LINKAGE
1869Cbc_solve(Cbc_Model *model)
1870{
1871  CoinMessages generalMessages = model->solver_->getModelPtr()->messages();
1872
1873  model->obj_value = COIN_DBL_MAX;
1874  model->lastOptNCols = Cbc_getNumCols(model);
1875  model->lastOptNRows = Cbc_getNumRows(model);
1876
1877  int res = Cbc_solveLinearProgram(model);
1878  if (res == 1)
1879    return 1;
1880  if (res==2 || res==3)
1881    return 0;
1882
1883  OsiSolverInterface *solver = model->solver_;
1884
1885  if (solver->isProvenPrimalInfeasible() || solver->isProvenDualInfeasible() ||
1886      solver->isAbandoned() || solver->isIterationLimitReached() || model->relax_ == 1
1887      || solver->getNumIntegers() == 0) {
1888    if (solver->isProvenOptimal() || solver->isIterationLimitReached()) {
1889      model->obj_value = solver->getObjValue();
1890      Cbc_updateSlack(model);
1891    }
1892
1893    return 0;
1894  }
1895
1896  // MIP Optimization
1897  if (model->cbcModel_) {
1898    delete model->cbcModel_;
1899  }
1900
1901  OsiClpSolverInterface *linearProgram = dynamic_cast<OsiClpSolverInterface *>( model->solver_->clone() );
1902  model->lastOptimization = IntegerOptimization;
1903  CbcModel *cbcModel = model->cbcModel_ = new CbcModel( *linearProgram );
1904
1905  try {
1906    if (model->lazyConstrs) {
1907      cbcModel->addCutGenerator(model->lazyConstrs, 1, "Stored LazyConstraints", true, 1);
1908      model->cutCBAtSol = 1;
1909    }
1910
1911    Cbc_EventHandler *cbc_eh = NULL;
1912    if (model->inc_callback!=NULL || model->progr_callback!=NULL)
1913    {
1914      cbc_eh = new Cbc_EventHandler(model->cbcModel_);
1915#ifdef CBC_THREAD
1916      cbc_eh->cbcMutex = &(model->cbcMutexEvent);
1917#endif
1918
1919      if (model->inc_callback) {
1920        cbc_eh->inc_callback = model->inc_callback;
1921        cbc_eh->appData = model->icAppData;
1922      }
1923      if (model->progr_callback) {
1924        cbc_eh->progr_callback = model->progr_callback;
1925        cbc_eh->pgAppData = model->pgrAppData;
1926      }
1927
1928      cbcModel->passInEventHandler(cbc_eh);
1929    }
1930
1931    if (model->iniSol)
1932      cbcModel->setBestSolution(&((*model->iniSol)[0]), Cbc_getNumCols(model), model->iniObj, true);
1933
1934    // add cut generator if necessary
1935    if (model->cut_callback) {
1936      cbcModel->setKeepNamesPreproc(true);
1937
1938      CglCallback cglCb;
1939      cglCb.appdata = model->cutCBData;
1940      cglCb.cut_callback_ = model->cut_callback;
1941#ifdef CBC_THREAD
1942      cglCb.cbcMutex = &(model->cbcMutexCG);
1943#endif
1944      cbcModel->addCutGenerator( &cglCb, model->cutCBhowOften, model->cutCBName.c_str(), true, model->cutCBAtSol );
1945    }
1946    if (model->cutCBAtSol) {
1947      Cbc_setParameter(model, "preprocess", "off");
1948      Cbc_setParameter(model, "heur", "off");       
1949    }
1950
1951    Cbc_MessageHandler *cbcmh  = NULL;
1952
1953    if (model->userCallBack) {
1954      cbcmh = new Cbc_MessageHandler(*cbcModel->messageHandler());
1955      cbcmh->setCallBack(model->userCallBack);
1956      cbcmh->setModel(model);
1957      cbcModel->passInMessageHandler(cbcmh);
1958    }
1959
1960    CbcSolverUsefulData cbcData;
1961    CbcMain0(*cbcModel, cbcData);
1962    cbcData.printWelcome_ = false;
1963
1964    cbcModel->solver()->setDblParam( OsiPrimalTolerance, model->dbl_param[DBL_PARAM_PRIMAL_TOL] );
1965    cbcModel->solver()->setDblParam( OsiDualTolerance, model->dbl_param[DBL_PARAM_DUAL_TOL] );
1966    // adds SOSs if any
1967    Cbc_addAllSOS(model);
1968
1969    // adds MIPStart if any
1970    Cbc_addMS( model );
1971
1972    // parameters
1973    if (model->dbl_param[DBL_PARAM_TIME_LIMIT] != COIN_DBL_MAX)
1974      cbcModel->setMaximumSeconds( model->dbl_param[DBL_PARAM_TIME_LIMIT] );
1975    if ( model->int_param[INT_PARAM_MAX_SOLS] != INT_MAX && model->int_param[INT_PARAM_MAX_SOLS] != -1 )
1976      cbcModel->setMaximumSolutions( model->int_param[INT_PARAM_MAX_SOLS] );
1977    cbcModel->setAllowableGap( model->dbl_param[DBL_PARAM_ALLOWABLE_GAP] );
1978    cbcModel->setAllowableFractionGap( model->dbl_param[DBL_PARAM_GAP_RATIO] );
1979    if ( model->int_param[INT_PARAM_MAX_NODES] != INT_MAX )
1980      cbcModel->setMaximumNodes( model->int_param[INT_PARAM_MAX_NODES] );
1981    cbcModel->setLogLevel( model->int_param[INT_PARAM_LOG_LEVEL] );
1982    if ( model->dbl_param[DBL_PARAM_CUTOFF] != COIN_DBL_MAX )
1983      cbcModel->setCutoff( model->dbl_param[DBL_PARAM_CUTOFF] );
1984
1985    // trying to reuse integer solution found in previous optimization
1986    if (model->lastOptNCols == model->solver_->getNumCols() && model->lastOptMIPSol) {
1987      const double *x = model->lastOptMIPSol;
1988      double maxViolRow, maxViolCol;
1989      int idxRow, idxCol;
1990      if (Cbc_checkFeasibility(model, x, &maxViolRow, &idxRow, &maxViolCol, &idxCol)) {
1991        double obj = 0;
1992        for ( int j=0 ; j<Cbc_getNumCols(model) ; ++j )
1993          obj += Cbc_getColObj(model, j)*x[j];
1994        cbcModel->setBestSolution(x, Cbc_getNumCols(model), obj);
1995      }
1996    } // try to reuse solution found in last optimization
1997
1998    std::vector< string > argv;
1999    argv.push_back("Cbc_C_Interface");
2000
2001    for ( size_t i=0 ; i<model->vcbcOptions.size() ; ++i ) {
2002      string param = model->vcbcOptions[i];
2003      string val = model->cbcOptions[param];
2004      if (val.size()) {
2005        stringstream ss;
2006        ss << "-" << param << "=" << val;
2007        argv.push_back(ss.str().c_str());
2008      } else {
2009        stringstream ss;
2010        ss << "-" << param;
2011        argv.push_back(ss.str());
2012      }
2013    }
2014
2015    argv.push_back("-solve");
2016    argv.push_back("-quit");
2017
2018    cbcData.noPrinting_= false;
2019
2020    char **charCbcOpts = to_char_vec(argv);
2021    const int nargs = (int) argv.size();
2022    const char **args = (const char **)charCbcOpts;
2023
2024    OsiBabSolver defaultC;
2025    if (model->cutCBAtSol) {
2026      defaultC.setSolverType(4);
2027      model->cbcModel_->solver()->setAuxiliaryInfo(&defaultC);
2028      model->cbcModel_->passInSolverCharacteristics(&defaultC);
2029    }
2030
2031    if (model->int_param[INT_PARAM_LOG_LEVEL] >= 1) {
2032      printf("\nStarting MIP optimization\n");
2033      fflush(stdout);
2034    }
2035#ifdef CBC_THREAD
2036    {
2037      int numberThreads = model->int_param[INT_PARAM_THREADS];
2038      if (numberThreads > 1) {
2039        model->cbcModel_->setNumberThreads(numberThreads);
2040        model->cbcModel_->setThreadMode(CoinMin(numberThreads / 100, 7));
2041      }
2042    }
2043#endif
2044    model->cbcModel_->setRoundIntegerVariables( model->int_param[INT_PARAM_ROUND_INT_VARS] );
2045    model->cbcModel_->setRandomSeed(model->int_param[INT_PARAM_RANDOM_SEED]);
2046    model->cbcModel_->setUseElapsedTime( (model->int_param[INT_PARAM_ELAPSED_TIME] == 1) );
2047
2048    CbcMain1( nargs, args, *model->cbcModel_, cbc_callb, cbcData );
2049
2050    if (Cbc_numberSavedSolutions(model)) {
2051      if (model->int_param[INT_PARAM_ROUND_INT_VARS]) {
2052        model->cbcModel_->roundIntVars();
2053      }
2054
2055      Cbc_updateSlack(model);
2056
2057      if (model->lastOptMIPSol && (model->lastOptNCols < Cbc_getNumCols(model))) {
2058        delete[] model->lastOptMIPSol;
2059        model->lastOptMIPSol = NULL;
2060      }
2061      if (!model->lastOptMIPSol)
2062        model->lastOptMIPSol = new double[Cbc_getNumCols(model)];
2063
2064      memcpy(model->lastOptMIPSol, cbcModel->bestSolution(), sizeof(double)*Cbc_getNumCols(model) );
2065      model->lastOptNCols = Cbc_getNumCols(model);
2066
2067      model->obj_value = cbcModel->getObjValue();
2068
2069      if (cbcModel->getObjSense()==-1) {
2070        model->obj_value = 0.0;
2071
2072        for (int j=0 ; j<solver->getNumCols() ; ++j )
2073          model->obj_value += cbcModel->bestSolution()[j] * solver->getObjCoefficients()[j];
2074      } // circunvent CBC bug
2075    }
2076
2077    free(charCbcOpts);
2078    delete linearProgram;
2079
2080    if (cbc_eh)
2081      delete cbc_eh;
2082
2083    if (cbcmh)
2084      delete cbcmh;
2085  } catch (CoinError &e) {
2086    fprintf( stderr, "%s ERROR: %s::%s, %s\n", "Cbc_solve",
2087      e.className().c_str(), e.methodName().c_str(), e.message().c_str());
2088    abort();
2089  }
2090 
2091  return cbcModel->status();
2092}
2093
2094void CBC_LINKAGE Cbc_addIncCallback(
2095    Cbc_Model *model, cbc_incumbent_callback inccb,
2096    void *appData )
2097{
2098  model->inc_callback = inccb;
2099  model->icAppData = appData;
2100}
2101
2102void CBC_LINKAGE Cbc_addProgrCallback(
2103  Cbc_Model *model, cbc_progress_callback prgcbc,
2104  void *appData)
2105{
2106  model->progr_callback = prgcbc;
2107  model->pgrAppData = appData;
2108}
2109
2110void CBC_LINKAGE Cbc_addCutCallback( 
2111    Cbc_Model *model, 
2112    cbc_cut_callback cutcb, 
2113    const char *name, 
2114    void *appData, 
2115    int howOften,
2116    char atSolution )
2117{
2118  model->cut_callback = cutcb;
2119  model->cutCBName = string(name);
2120  model->cutCBData = appData;
2121  model->cutCBhowOften = howOften;
2122  model->cutCBAtSol = atSolution;
2123}
2124
2125int CBC_LINKAGE
2126Cbc_getNumCols(Cbc_Model *model)
2127{
2128  return model->solver_->getNumCols() + model->nCols;
2129}
2130
2131int CBC_LINKAGE
2132Cbc_getNumRows(Cbc_Model *model)
2133{
2134  return model->solver_->getNumRows() + model->nRows;
2135}
2136
2137
2138int CBC_LINKAGE
2139Cbc_getIterationCount(Cbc_Model *model) {
2140  return model->cbcModel_->getIterationCount();
2141}
2142
2143/** Number of non-zero entries in a row */
2144int CBC_LINKAGE
2145Cbc_getRowNz(Cbc_Model *model, int row)
2146{
2147  VALIDATE_ROW_INDEX( row, model);
2148  Cbc_flush(model);
2149
2150  const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow();
2151  return cpmRow->getVectorLengths()[row];
2152}
2153
2154/** Indices of variables that appear on this row */
2155const int *CBC_LINKAGE
2156Cbc_getRowIndices(Cbc_Model *model, int row)
2157{
2158  VALIDATE_ROW_INDEX( row, model);
2159  Cbc_flush(model);
2160
2161  const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow();
2162  const CoinBigIndex *starts = cpmRow->getVectorStarts();
2163  const int *ridx = cpmRow->getIndices() + starts[row];
2164  return ridx;
2165}
2166
2167/** Coefficients of variables that appear on this row */
2168const double *CBC_LINKAGE
2169Cbc_getRowCoeffs(Cbc_Model *model, int row)
2170{
2171  VALIDATE_ROW_INDEX( row, model);
2172  Cbc_flush(model);
2173
2174  const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow();
2175  const CoinBigIndex *starts = cpmRow->getVectorStarts();
2176  const double *rcoef = cpmRow->getElements() + starts[row];
2177  return rcoef;
2178}
2179
2180/** Number of non-zero entries in a column */
2181int CBC_LINKAGE
2182Cbc_getColNz(Cbc_Model *model, int col)
2183{
2184  VALIDATE_COL_INDEX( col, model );
2185  Cbc_flush(model);
2186
2187  const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol();
2188  return cpmCol->getVectorLengths()[col];
2189}
2190
2191/** Indices of rows that a column appears */
2192const int *CBC_LINKAGE
2193Cbc_getColIndices(Cbc_Model *model, int col)
2194{
2195  VALIDATE_COL_INDEX( col, model );
2196  Cbc_flush(model);
2197
2198  const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol();
2199  const CoinBigIndex *starts = cpmCol->getVectorStarts();
2200  const int *cidx = cpmCol->getIndices() + starts[col];
2201  return cidx;
2202}
2203
2204/** Coefficients that a column appear in rows */
2205const double *CBC_LINKAGE
2206Cbc_getColCoeffs(Cbc_Model *model, int col)
2207{
2208  VALIDATE_COL_INDEX( col, model );
2209  Cbc_flush(model);
2210
2211  const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol();
2212  const CoinBigIndex *starts = cpmCol->getVectorStarts();
2213  const double *ccoef = cpmCol->getElements() + starts[col];
2214  return ccoef;
2215}
2216
2217/** Right hand side of a row */
2218double CBC_LINKAGE
2219Cbc_getRowRHS(Cbc_Model *model, int row)
2220{
2221  VALIDATE_ROW_INDEX( row, model );
2222
2223  if (row<model->solver_->getNumRows()) {
2224    return model->solver_->getRightHandSide()[row];
2225  } else {
2226    int idxRowBuffer = row - model->solver_->getNumRows();
2227    if (model->rUB[idxRowBuffer] < COIN_DBL_MAX) 
2228      return model->rUB[idxRowBuffer];
2229    else 
2230      return model->rLB[idxRowBuffer];
2231  }
2232}
2233
2234/** Sense a row */
2235char CBC_LINKAGE
2236Cbc_getRowSense(Cbc_Model *model, int row)
2237{
2238  VALIDATE_ROW_INDEX( row, model );
2239
2240  if (row<model->solver_->getNumRows()) {
2241    return model->solver_->getRowSense()[row];
2242  } else {
2243    int idxRowBuffer = row - model->solver_->getNumRows();
2244    if (fabs(model->rLB[idxRowBuffer]-model->rUB[idxRowBuffer]) <= 1e-15)
2245      return 'E';
2246    if (model->rUB[idxRowBuffer] == COIN_DBL_MAX) 
2247      return 'G';
2248    if (model->rLB[idxRowBuffer] == -COIN_DBL_MAX) 
2249      return 'L';
2250
2251    return 'R';
2252  }
2253}
2254
2255/** Are there a numerical difficulties? */
2256int CBC_LINKAGE
2257Cbc_isAbandoned(Cbc_Model *model)
2258{
2259  switch (model->lastOptimization) {
2260    case ModelNotOptimized:
2261      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2262      abort();
2263      break;
2264    case ContinuousOptimization:
2265      return model->solver_->isAbandoned();
2266      break;
2267    case IntegerOptimization:
2268      return model->cbcModel_->isAbandoned();
2269  }
2270
2271  return false;
2272}
2273
2274/** Is optimality proven? */
2275int CBC_LINKAGE
2276Cbc_isProvenOptimal(Cbc_Model *model)
2277{
2278  switch (model->lastOptimization) {
2279    case ModelNotOptimized:
2280      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2281      abort();
2282      break;
2283    case ContinuousOptimization:
2284      return model->solver_->isProvenOptimal();
2285    case IntegerOptimization:
2286      return model->cbcModel_->isProvenOptimal();
2287  }
2288
2289  return false;
2290}
2291
2292int CBC_LINKAGE
2293Cbc_isProvenInfeasible(Cbc_Model *model)
2294{
2295  switch (model->lastOptimization) {
2296    case ModelNotOptimized:
2297      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2298      abort();
2299      break;
2300    case ContinuousOptimization:
2301      return model->solver_->isProvenPrimalInfeasible();
2302    case IntegerOptimization:
2303      if (model->cbcModel_->status() == -1)
2304        return model->solver_->isProvenPrimalInfeasible();
2305      return model->cbcModel_->isProvenInfeasible();
2306  }
2307
2308  return false;
2309}
2310
2311double CBC_LINKAGE
2312Cbc_getObjValue(Cbc_Model *model)
2313{
2314  return model->obj_value;
2315}
2316
2317const double *CBC_LINKAGE
2318Cbc_getReducedCost(Cbc_Model *model)
2319{
2320  switch (model->lastOptimization) {
2321    case ModelNotOptimized:
2322      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2323      abort();
2324      break;
2325    case ContinuousOptimization:
2326      return model->solver_->getReducedCost();
2327    case IntegerOptimization:
2328      fprintf( stderr, "Information only available when optimizing continuous models.\n");
2329      abort();
2330      break;
2331  }
2332
2333  return NULL;
2334}
2335
2336const double *CBC_LINKAGE
2337Cbc_getRowPrice(Cbc_Model *model)
2338{
2339  switch (model->lastOptimization) {
2340    case ModelNotOptimized:
2341      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2342      abort();
2343      break;
2344    case ContinuousOptimization:
2345      return model->solver_->getRowPrice();
2346    case IntegerOptimization:
2347      fprintf( stderr, "Information only available when optimizing continuous models.\n");
2348      abort();
2349      break;
2350  }
2351
2352  return NULL;
2353}
2354
2355int CBC_LINKAGE
2356Cbc_numberSavedSolutions(Cbc_Model *model)
2357{
2358  switch (model->lastOptimization) {
2359    case ModelNotOptimized:
2360      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2361      abort();
2362      break;
2363    case ContinuousOptimization:
2364      if (model->solver_->isProvenOptimal())
2365        return 1;
2366      else
2367        return 0;
2368    case IntegerOptimization:
2369      return model->cbcModel_->numberSavedSolutions();
2370  }
2371
2372  return 0;
2373}
2374
2375const double *CBC_LINKAGE
2376Cbc_savedSolution(Cbc_Model *model, int whichSol)
2377{
2378  switch (model->lastOptimization) {
2379    case ModelNotOptimized:
2380      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2381      abort();
2382      break;
2383    case ContinuousOptimization:
2384      fprintf( stderr, "Information only available when optimizing integer models.\n");
2385      abort();
2386      break;
2387    case IntegerOptimization:
2388      return model->cbcModel_->savedSolution(whichSol);
2389  }
2390
2391  return NULL;
2392}
2393
2394double CBC_LINKAGE
2395Cbc_savedSolutionObj(Cbc_Model *model, int whichSol)
2396{
2397  switch (model->lastOptimization) {
2398    case ModelNotOptimized:
2399      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2400      abort();
2401      break;
2402    case ContinuousOptimization:
2403      fprintf( stderr, "Information only available when optimizing integer models.\n");
2404      abort();
2405      break;
2406    case IntegerOptimization:
2407      return model->cbcModel_->savedSolutionObjective(whichSol);
2408  }
2409
2410  return COIN_DBL_MAX;
2411}
2412
2413const double *CBC_LINKAGE
2414Cbc_getColSolution(Cbc_Model *model)
2415{
2416  switch (model->lastOptimization) {
2417    case ModelNotOptimized:
2418      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2419      abort();
2420      break;
2421    case ContinuousOptimization:
2422      return model->solver_->getColSolution();
2423    case IntegerOptimization:
2424      return model->cbcModel_->bestSolution();
2425  }
2426
2427  return NULL;
2428}
2429
2430/** @brief Upper bound of ranged constraint
2431  *
2432  * @param model problem object
2433  * @param row row index
2434  * @return row upper bound
2435  **/
2436double 
2437Cbc_getRowUB(Cbc_Model *model, int row) {
2438  if (row<model->solver_->getNumRows()) {
2439    return model->solver_->getRowUpper()[row];
2440  } else {
2441    int nridx = row - model->solver_->getNumRows();
2442    return model->rUB[nridx];
2443  }
2444}
2445
2446/** @brief Lower bound of ranged constraint
2447  *
2448  * @param model problem object
2449  * @param row row index
2450  * @return row lower bound
2451  **/
2452CBCSOLVERLIB_EXPORT double CBC_LINKAGE
2453Cbc_getRowLB(Cbc_Model *model, int row) {
2454  if (row<model->solver_->getNumRows()) {
2455    return model->solver_->getRowLower()[row];
2456  } else {
2457    int nridx = row - model->solver_->getNumRows();
2458    return model->rLB[nridx];
2459  }
2460}
2461
2462char Cbc_checkFeasibility(Cbc_Model *model, const double x[],
2463    double *maxViolRow, int *rowIdx, 
2464    double *maxViolCol, int *colIdx) {
2465  *maxViolRow = *maxViolCol = -1.0;
2466  *rowIdx = *colIdx = -1;
2467  const double primalTol = model->dbl_param[DBL_PARAM_PRIMAL_TOL];
2468  const double intTol = model->dbl_param[DBL_PARAM_INT_TOL];
2469
2470  char feasible = 1;
2471  int nRows = Cbc_getNumRows(model);
2472  for ( int i=0 ; (i<nRows) ; ++i ) {
2473    int nzRow = Cbc_getRowNz(model, i);
2474    const int *cidx = Cbc_getRowIndices(model, i);
2475    const double *coef = Cbc_getRowCoeffs(model, i);
2476
2477    double lhs = 0.0;
2478    for ( int j=0 ; (j<nzRow) ; ++j ) {
2479      int ic = cidx[j];
2480      lhs += x[ic] * coef[j];
2481    }
2482
2483    double rowUB = Cbc_getRowUB(model, i);
2484    double rowLB = Cbc_getRowLB(model, i);
2485
2486    double viol = 0.0;
2487   
2488    if (lhs>rowUB) {
2489      viol = lhs-rowUB;
2490    } else {
2491      if (lhs<rowLB) {
2492        viol = rowLB-lhs;
2493      }
2494    }
2495
2496    if (viol>(*maxViolRow)) {
2497      if (viol>primalTol)
2498        feasible = 0;
2499      *maxViolRow = viol;
2500      *rowIdx = i;
2501    }
2502  } // all rows
2503 
2504  int nCols = Cbc_getNumCols(model);
2505  for ( int j=0 ; (j<nCols) ; ++j ) {
2506    const double clb = Cbc_getColLB(model, j);   
2507    const double cub = Cbc_getColUB(model, j);
2508 
2509    double viol = 0.0;
2510    if (x[j]>cub) {
2511      viol = x[j] - cub;
2512    } else {
2513      if (x[j]<clb) {
2514        viol = clb-x[j];
2515      }
2516    }
2517    if (viol>primalTol)
2518      feasible = 0;
2519
2520    if (Cbc_isInteger(model, j)) {
2521      double vint = floor(x[j] + 0.5);
2522      double intviol = fabs(x[j]-vint);
2523      if (intviol > intTol)
2524        feasible = 0;
2525      viol = std::max(viol, intTol);
2526    }
2527
2528    if ( viol > *maxViolCol ) {
2529      *maxViolCol = viol;
2530      *colIdx = j;
2531    }
2532  } // all columns
2533
2534  return feasible;
2535}
2536
2537int CBC_LINKAGE
2538Cbc_isContinuousUnbounded(Cbc_Model *model) {
2539  switch (model->lastOptimization) {
2540    case ModelNotOptimized:
2541      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2542      abort();
2543      break;
2544    case ContinuousOptimization:
2545      return model->solver_->isProvenDualInfeasible();
2546    case IntegerOptimization:
2547      if (model->cbcModel_->status() == -1)
2548        return model->solver_->isProvenDualInfeasible();
2549
2550      return model->cbcModel_->isContinuousUnbounded();
2551  }
2552
2553  return false;
2554}
2555
2556
2557int CBC_LINKAGE
2558Cbc_isNodeLimitReached(Cbc_Model *model) {
2559  switch (model->lastOptimization) {
2560    case ModelNotOptimized:
2561      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2562      abort();
2563      break;
2564    case ContinuousOptimization:
2565      fprintf( stderr, "Information not available when optimizing continuous models.\n");
2566      abort();
2567      break;
2568    case IntegerOptimization:
2569      return model->cbcModel_->isNodeLimitReached();
2570  }
2571
2572  return false;
2573}
2574
2575
2576int CBC_LINKAGE
2577Cbc_isSecondsLimitReached(Cbc_Model *model) {
2578  switch (model->lastOptimization) {
2579    case ModelNotOptimized:
2580      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2581      abort();
2582      break;
2583    case ContinuousOptimization:
2584      fprintf( stderr, "Information only available when optimizing integer models.\n");
2585      abort();
2586      break;
2587    case IntegerOptimization:
2588      return model->cbcModel_->isSecondsLimitReached();
2589  }
2590
2591  return false;
2592
2593}
2594
2595int CBC_LINKAGE
2596Cbc_isSolutionLimitReached(Cbc_Model *model) {
2597  switch (model->lastOptimization) {
2598    case ModelNotOptimized:
2599      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2600      abort();
2601      break;
2602    case ContinuousOptimization:
2603      fprintf( stderr, "Information only available when optimizing integer models.\n");
2604      abort();
2605      break;
2606    case IntegerOptimization:
2607      return model->cbcModel_->isSolutionLimitReached();
2608  }
2609
2610  return false;
2611}
2612
2613
2614
2615
2616int CBC_LINKAGE
2617Cbc_isInitialSolveAbandoned(Cbc_Model *model) {
2618  switch (model->lastOptimization) {
2619    case ModelNotOptimized:
2620      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2621      abort();
2622      break;
2623    case ContinuousOptimization:
2624      fprintf( stderr, "Information only available when optimizing integer models.\n");
2625      abort();
2626      break;
2627    case IntegerOptimization:
2628      return model->cbcModel_->isInitialSolveAbandoned();
2629  }
2630
2631  return false;
2632}
2633
2634int CBC_LINKAGE
2635Cbc_isInitialSolveProvenOptimal(Cbc_Model *model) {
2636  switch (model->lastOptimization) {
2637    case ModelNotOptimized:
2638      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2639      abort();
2640      break;
2641    case ContinuousOptimization:
2642      fprintf( stderr, "Information only available when optimizing integer models.\n");
2643      abort();
2644      break;
2645    case IntegerOptimization:
2646      return model->cbcModel_->isInitialSolveProvenOptimal();
2647  }
2648
2649  return false;
2650}
2651
2652
2653int CBC_LINKAGE
2654Cbc_isInitialSolveProvenPrimalInfeasible(Cbc_Model *model) {
2655  switch (model->lastOptimization) {
2656    case ModelNotOptimized:
2657      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2658      abort();
2659      break;
2660    case ContinuousOptimization:
2661      fprintf( stderr, "Information only available when optimizing integer models.\n");
2662      abort();
2663      break;
2664    case IntegerOptimization:
2665      return model->cbcModel_->isInitialSolveProvenPrimalInfeasible();
2666  }
2667
2668  return false;
2669
2670}
2671
2672double CBC_LINKAGE
2673Cbc_getObjSense(Cbc_Model *model) {
2674  return model->solver_->getObjSense();
2675}
2676
2677void CBC_LINKAGE
2678Cbc_setObjSense(Cbc_Model *model, double sense)
2679{
2680  Cbc_flush(model);
2681  model->solver_->setObjSense(sense);
2682}
2683
2684void CBC_LINKAGE
2685Cbc_setRowLower(Cbc_Model *model, int index, double value)
2686{
2687  Cbc_flush(model);
2688  VALIDATE_ROW_INDEX(index, model);
2689
2690  OsiSolverInterface *solver = model->solver_;
2691  solver->setRowLower(index, value);
2692}
2693
2694void CBC_LINKAGE
2695Cbc_setRowUpper(Cbc_Model *model, int index, double value)
2696{
2697  Cbc_flush(model);
2698  VALIDATE_ROW_INDEX(index, model);
2699  OsiSolverInterface *solver = model->solver_;
2700  solver->setRowUpper(index, value);
2701}
2702
2703void CBC_LINKAGE
2704Cbc_setRowRHS(Cbc_Model *model, int row, double rhs)
2705{
2706  VALIDATE_ROW_INDEX(row, model);
2707
2708  Cbc_flush(model);
2709  char sense = Cbc_getRowSense(model, row);
2710  switch (sense)
2711  {
2712    case 'L':
2713      Cbc_setRowUpper(model, row, rhs);
2714      break;
2715    case 'G':
2716      Cbc_setRowLower(model, row, rhs);
2717      break;
2718    case 'E':
2719      Cbc_setRowLower(model, row, rhs);
2720      Cbc_setRowUpper(model, row, rhs);
2721      break;
2722    default:
2723      fprintf(stderr, "Could not change RHS in row %d to %g in row with sense: %c\n",
2724          row, rhs, sense);
2725      exit(1);
2726  }
2727}
2728
2729
2730
2731/** @brief Constraint lower bounds
2732  *
2733  * @param model problem object
2734  * @return vector with lower bounds of constraints
2735  **/
2736const double *CBC_LINKAGE
2737Cbc_getRowLower(Cbc_Model *model)
2738{
2739  Cbc_flush(model);
2740  OsiSolverInterface *solver = model->solver_;
2741  return solver->getRowLower();
2742}
2743
2744/** @brief Constraint upper bounds
2745  *
2746  * @param model problem object
2747  * @return constraint upper bounds
2748  **/
2749const double *CBC_LINKAGE
2750Cbc_getRowUpper(Cbc_Model *model)
2751{
2752  Cbc_flush(model);
2753  OsiSolverInterface *solver = model->solver_;
2754  return solver->getRowUpper();
2755}
2756
2757
2758const double *CBC_LINKAGE
2759Cbc_getRowActivity(Cbc_Model *model) {
2760  switch (model->lastOptimization) {
2761    case ModelNotOptimized:
2762      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2763      abort();
2764      break;
2765    case ContinuousOptimization:
2766      return model->solver_->getRowActivity();
2767    case IntegerOptimization:
2768      return model->cbcModel_->getRowActivity();
2769  }
2770
2771  return NULL;
2772
2773}
2774
2775
2776CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE
2777Cbc_getRowSlack(Cbc_Model *model) {
2778  if (model->lastOptimization==ModelNotOptimized) {
2779      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2780      abort();
2781  }
2782
2783  return model->slack_;
2784}
2785
2786const double *CBC_LINKAGE
2787Cbc_getColLower(Cbc_Model *model)
2788{
2789  Cbc_flush(model);
2790  return model->solver_->getColLower();
2791}
2792
2793const double *CBC_LINKAGE
2794Cbc_getColUpper(Cbc_Model *model)
2795{
2796  Cbc_flush(model);
2797  return model->solver_->getColUpper();
2798}
2799
2800double Cbc_getColObj(Cbc_Model *model, int colIdx) {
2801  VALIDATE_COL_INDEX(colIdx, model);
2802
2803  if (colIdx < model->solver_->getNumCols()) {
2804    return model->solver_->getObjCoefficients()[colIdx];
2805  } else {
2806    int ncIdx = colIdx - model->solver_->getNumCols();
2807    return model->cObj[ncIdx];
2808  }
2809}
2810
2811double Cbc_getColLB(Cbc_Model *model, int colIdx) {
2812  VALIDATE_COL_INDEX(colIdx, model);
2813
2814  if (colIdx < model->solver_->getNumCols()) {
2815    return model->solver_->getColLower()[colIdx];
2816  } else {
2817    int ncIdx = colIdx - model->solver_->getNumCols();
2818    return model->cLB[ncIdx];
2819  }
2820}
2821
2822double Cbc_getColUB(Cbc_Model *model, int colIdx) {
2823  VALIDATE_COL_INDEX(colIdx, model);
2824
2825  if (colIdx < model->solver_->getNumCols()) {
2826    return model->solver_->getColUpper()[colIdx];
2827  } else {
2828    int ncIdx = colIdx - model->solver_->getNumCols();
2829    return model->cUB[ncIdx];
2830  }
2831}
2832
2833double CBC_LINKAGE
2834Cbc_getBestPossibleObjValue(Cbc_Model *model) {
2835  switch (model->lastOptimization) {
2836    case ModelNotOptimized:
2837      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2838      abort();
2839      break;
2840    case ContinuousOptimization:
2841      return model->solver_->getObjValue();
2842    case IntegerOptimization:
2843      return model->cbcModel_->getBestPossibleObjValue();
2844  }
2845
2846  return COIN_DBL_MIN;
2847}
2848
2849const double *CBC_LINKAGE
2850Cbc_getObjCoefficients(Cbc_Model *model)
2851{
2852  Cbc_flush(model);
2853  return model->solver_->getObjCoefficients();
2854}
2855
2856void CBC_LINKAGE
2857Cbc_setObjCoeff(Cbc_Model *model, int index, double value)
2858{
2859  Cbc_flush( model);
2860  VALIDATE_COL_INDEX(index, model);
2861
2862  model->solver_->setObjCoeff( index, value );
2863}
2864
2865void CBC_LINKAGE
2866Cbc_setColLower(Cbc_Model *model, int index, double value)
2867{
2868  Cbc_flush(model);
2869  VALIDATE_COL_INDEX(index, model);
2870  model->solver_->setColLower( index, value );
2871}
2872
2873void CBC_LINKAGE
2874Cbc_setColUpper(Cbc_Model *model, int index, double value)
2875{
2876  Cbc_flush(model);
2877  VALIDATE_COL_INDEX(index, model);
2878  model->solver_->setColUpper( index, value );
2879}
2880
2881
2882const double *CBC_LINKAGE
2883Cbc_bestSolution(Cbc_Model *model)
2884{
2885  switch (model->lastOptimization) {
2886    case ModelNotOptimized:
2887      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2888      abort();
2889      break;
2890    case ContinuousOptimization:
2891      return model->solver_->getColSolution();
2892    case IntegerOptimization:
2893      return model->cbcModel_->bestSolution();
2894  }
2895
2896  return NULL;
2897}
2898
2899
2900int CBC_LINKAGE
2901Cbc_isInteger(Cbc_Model *model, int i)
2902{
2903  Cbc_flush(model);
2904  VALIDATE_COL_INDEX( i, model );
2905  return model->solver_->isInteger(i);
2906}
2907
2908
2909int CBC_LINKAGE
2910Cbc_getNodeCount(Cbc_Model *model) {
2911  switch (model->lastOptimization) {
2912    case ModelNotOptimized:
2913      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2914      abort();
2915      break;
2916    case ContinuousOptimization:
2917      fprintf( stderr, "Information only available when optimizing integer models.\n");
2918      abort();
2919      break;
2920    case IntegerOptimization:
2921      return model->cbcModel_->getNodeCount();
2922  }
2923
2924  return false;
2925
2926}
2927
2928
2929/** Return a copy of this model */
2930Cbc_Model *CBC_LINKAGE
2931Cbc_clone(Cbc_Model *model)
2932{
2933  Cbc_flush(model);
2934  Cbc_Model *result = new Cbc_Model();
2935
2936  result->slack_ = NULL;
2937  result->solver_ = dynamic_cast<OsiClpSolverInterface *>(model->solver_->clone());
2938
2939  if (model->cbcModel_)
2940    result->cbcModel_ = model->cbcModel_->clone(true);
2941  else
2942    result->cbcModel_ = NULL;
2943
2944  result->relax_ = model->relax_;
2945
2946  result->inc_callback = model->inc_callback;
2947  result->progr_callback = model->progr_callback;
2948  result->userCallBack = model->userCallBack;
2949
2950  result->cut_callback = model->cut_callback;
2951  result->cutCBData = model->cutCBData;
2952  result->cutCBhowOften = model->cutCBhowOften;
2953  result->cutCBAtSol = model->cutCBAtSol;
2954
2955  result->obj_value = model->obj_value;
2956
2957
2958  result->lastOptimization = model->lastOptimization;
2959  result->lastOptNCols = model->lastOptNCols;
2960  if (model->lastOptMIPSol) {
2961    result->lastOptMIPSol = new double[model->lastOptNCols];
2962    memcpy(result->lastOptMIPSol, model->lastOptMIPSol, sizeof(double)*model->lastOptNCols );
2963  }
2964
2965  if (model->slack_) {
2966    result->slack_ = (double *) xmalloc( sizeof(double)*model->lastOptNRows );
2967    memcpy(result->slack_, model->slack_, sizeof(double)*model->lastOptNRows);
2968  }
2969
2970  result->icAppData = model->icAppData;
2971  result->pgrAppData = model->pgrAppData;
2972  result->colNameIndex = NULL;
2973  result->rowNameIndex = NULL;
2974  if (model->colNameIndex)
2975    Cbc_storeNameIndexes(result, 1);
2976
2977  Cbc_iniBuffer(result);
2978
2979  if (model->iniSol) {
2980    result->iniSol = new vector<double>( model->iniSol->begin(), model->iniSol->end() );
2981    result->iniObj = model->iniObj;
2982  }
2983  else
2984  {
2985    result->iniSol = NULL;
2986    result->iniObj = COIN_DBL_MAX;
2987  }
2988
2989  if (model->nColsMS) {
2990    result->nColsMS = model->nColsMS;
2991    result->colNamesMS = (char **) xmalloc( sizeof(char *)*model->nColsMS );
2992    result->charSpaceMS = model->charSpaceMS;
2993    result->colNamesMS[0] = (char *) xmalloc( result->charSpaceMS );
2994    memcpy( result->colNamesMS[0], model->colNamesMS[0], model->charSpaceMS );
2995    for ( int i=1 ; (i<model->nColsMS) ; ++i )
2996      result->colNamesMS[i] = result->colNamesMS[i-1] + strlen(result->colNamesMS[i-1]);
2997  }
2998  else
2999  {
3000    result->nColsMS = 0;
3001    result->colNamesMS = NULL;
3002    result->colValuesMS = NULL;
3003    result->charSpaceMS = 0;
3004  }
3005
3006  if ( model->nSos ) {
3007    result->nSos = model->nSos;
3008    result->sosSize = model->sosSize;
3009    result->sosElSize = model->sosElSize;
3010
3011    result->sosCap = result->nSos;
3012    result->sosElCap = model->sosElCap;
3013
3014    result->sosRowStart = (int*) xmalloc( sizeof(int)*(result->sosCap+1) );
3015    result->sosEl = (int*) xmalloc( sizeof(int)*(result->sosElCap) );
3016    result->sosElWeight = (double*) xmalloc( sizeof(double)*(result->sosElCap) );
3017
3018    memcpy( result->sosRowStart, model->sosRowStart, sizeof(int)*(result->nSos+1) );
3019    memcpy( result->sosEl, model->sosEl, sizeof(int)*(result->sosElSize) );
3020    memcpy( result->sosElWeight, model->sosElWeight, sizeof(double)*(result->sosElSize) );
3021  }
3022
3023#ifdef CBC_THREAD
3024  pthread_mutex_init(&(result->cbcMutexCG), NULL);
3025  pthread_mutex_init(&(result->cbcMutexEvent), NULL);
3026#endif
3027
3028  // copying parameters
3029  result->lp_method = model->lp_method;
3030  result->dualp = model->dualp;
3031
3032  memcpy(result->int_param, model->int_param, sizeof(result->int_param));
3033  memcpy(result->dbl_param, model->dbl_param, sizeof(result->dbl_param));
3034
3035  return result;
3036}
3037
3038/** Set this the variable to be continuous */
3039void CBC_LINKAGE
3040Cbc_setContinuous(Cbc_Model *model, int iColumn)
3041{
3042  Cbc_flush(model);
3043  VALIDATE_COL_INDEX( iColumn, model );
3044
3045  model->solver_->setContinuous(iColumn);
3046}
3047
3048/** Set this the variable to be integer */
3049void CBC_LINKAGE
3050Cbc_setInteger(Cbc_Model *model, int iColumn)
3051{
3052  Cbc_flush(model);
3053  VALIDATE_COL_INDEX( iColumn, model );
3054
3055  model->solver_->setInteger(iColumn);
3056}
3057
3058/** Adds a new column */
3059void CBC_LINKAGE
3060Cbc_addCol(Cbc_Model *model, const char *name, double lb,
3061  double ub, double obj, char isInteger,
3062  int nz, int *rows, double *coefs)
3063{
3064  OsiSolverInterface *solver = model->solver_;
3065
3066  if (nz >= 1 && model->rStart && model->rStart[model->nRows] >= 1) {
3067    // new columns have reference to rows which have references to columns, flushing
3068    Cbc_flush(model);
3069  }
3070
3071  Cbc_addColBuffer( model, name, nz, rows, coefs,  lb, ub, obj,  isInteger );
3072
3073  if (model->colNameIndex)
3074  {
3075    NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
3076    colNameIndex[std::string(name)] = Cbc_getNumCols(model)-1;
3077  }
3078}
3079
3080/** Adds a new row */
3081void CBC_LINKAGE
3082Cbc_addRow(Cbc_Model *model, const char *name, int nz,
3083  const int *cols, const double *coefs, char sense, double rhs)
3084{
3085  if (nz >= 1 && model->cStart && model->cStart[model->nCols] >= 1) {
3086    // new rows have reference to columns which have references to rows, flushing
3087    Cbc_flush(model);
3088  }
3089
3090  double rowLB = -DBL_MAX, rowUB = DBL_MAX;
3091  switch (toupper(sense)) {
3092  case '=':
3093    rowLB = rowUB = rhs;
3094    break;
3095  case 'E':
3096    rowLB = rowUB = rhs;
3097    break;
3098  case '<':
3099    rowUB = rhs;
3100    break;
3101  case 'L':
3102    rowUB = rhs;
3103    break;
3104  case '>':
3105    rowLB = rhs;
3106    break;
3107  case 'G':
3108    rowLB = rhs;
3109    break;
3110  default:
3111    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3112    abort();
3113  }
3114
3115  Cbc_addRowBuffer(model, nz, cols, coefs, rowLB, rowUB, name);
3116
3117  if (model->rowNameIndex)
3118  {
3119    NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
3120    rowNameIndex[std::string(name)] = Cbc_getNumRows(model)-1;
3121  }
3122}
3123
3124
3125void CBC_LINKAGE
3126Cbc_addLazyConstraint(Cbc_Model *model, int nz,
3127  int *cols, double *coefs, char sense, double rhs)
3128{
3129  if (model->lazyConstrs==NULL)
3130    model->lazyConstrs = new CglStored();
3131
3132  OsiRowCut orc;
3133  orc.setRow( nz, cols, coefs );
3134
3135  orc.setLb(-DBL_MAX);
3136  orc.setUb(DBL_MAX);
3137
3138  switch (toupper(sense)) {
3139  case '=':
3140    orc.setLb(rhs);
3141    orc.setUb(rhs);
3142    break;
3143  case 'E':
3144    orc.setLb(rhs);
3145    orc.setUb(rhs);
3146    break;
3147  case '<':
3148    orc.setUb(rhs);
3149    break;
3150  case 'L':
3151    orc.setUb(rhs);
3152    break;
3153  case '>':
3154    orc.setLb(rhs);
3155    break;
3156  case 'G':
3157    orc.setLb(rhs);
3158    break;
3159  default:
3160    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3161    abort();
3162  }
3163
3164  model->lazyConstrs->addCut(orc);
3165}
3166
3167void CBC_LINKAGE
3168Cbc_readMIPStart(Cbc_Model *model, const char fileName[]) {
3169  std::vector< std::pair< std::string, double > > colValues;
3170  double obj;
3171  CoinMessages generalMessages = model->solver_->getModelPtr()->messages();
3172  CoinMessageHandler *messHandler = model->solver_->messageHandler();
3173  CbcMipStartIO::read(model->solver_, fileName, colValues, obj, messHandler, &generalMessages);
3174 
3175  char **cnames = new char*[colValues.size()];
3176  size_t charSpace = 0;
3177  for ( int i=0 ; (i<(int)colValues.size()) ; ++i )
3178    charSpace += colValues[i].first.size() + 1;
3179  cnames[0] = new char[charSpace];
3180  for ( int i=1 ; (i<(int)colValues.size()) ; ++i )
3181    cnames[i] = cnames[i-1] + colValues[i-1].first.size() + 1;
3182
3183  double *cval = new double[colValues.size()];
3184  for ( int i=0 ; (i<(int)colValues.size()) ; ++i ) {
3185    cval[i] = colValues[i].second;
3186    strcpy(cnames[i], colValues[i].first.c_str());
3187  }
3188
3189  Cbc_setMIPStart(model, colValues.size(), (const char **) cnames, cval);
3190  delete[] cnames[0];
3191  delete[] cnames;
3192  delete[] cval;
3193}
3194
3195void CBC_LINKAGE
3196Osi_addRow(void *osi, const char *name, int nz,
3197  const int *cols, const double *coefs, char sense, double rhs)
3198{
3199  OsiSolverInterface *solver = (OsiSolverInterface *) osi;
3200  double rowLB = -DBL_MAX, rowUB = DBL_MAX;
3201  switch (toupper(sense)) {
3202  case '=':
3203    rowLB = rowUB = rhs;
3204    break;
3205  case 'E':
3206    rowLB = rowUB = rhs;
3207    break;
3208  case '<':
3209    rowUB = rhs;
3210    break;
3211  case 'L':
3212    rowUB = rhs;
3213    break;
3214  case '>':
3215    rowLB = rhs;
3216    break;
3217  case 'G':
3218    rowLB = rhs;
3219    break;
3220  default:
3221    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3222    abort();
3223  }
3224
3225  solver->addRow(nz, cols, coefs, rowLB, rowUB);
3226  solver->setRowName(solver->getNumRows()-1, std::string(name));
3227}
3228
3229void CBC_LINKAGE
3230Osi_setObjSense(void *osi, double sense)
3231{
3232  OsiSolverInterface *solver = (OsiSolverInterface *) osi;
3233  solver->setObjSense(sense);
3234}
3235
3236void CBC_LINKAGE
3237Cbc_deleteRows(Cbc_Model *model, int numRows, const int rows[])
3238{
3239  Cbc_flush(model);
3240  OsiSolverInterface *solver = model->solver_;
3241
3242  if (model->rowNameIndex)
3243  {
3244    NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
3245    for ( int i=0 ; i<numRows; ++i )
3246      rowNameIndex.erase(solver->getRowName(rows[i]));
3247  }
3248
3249  solver->deleteRows(numRows, rows);
3250}
3251
3252void CBC_LINKAGE
3253Cbc_deleteCols(Cbc_Model *model, int numCols, const int cols[])
3254{
3255  Cbc_flush(model);
3256  OsiSolverInterface *solver = model->solver_;
3257
3258  if (model->colNameIndex)
3259  {
3260    NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
3261    for ( int i=0 ; i<numCols; ++i )
3262      colNameIndex.erase(solver->getColName(cols[i]));
3263  }
3264
3265  solver->deleteCols(numCols, cols);
3266}
3267
3268/** Add SOS constraints to the model using row-order matrix */
3269void CBC_LINKAGE
3270Cbc_addSOS(Cbc_Model *model, int numRows, const int *rowStarts,
3271  const int *colIndices, const double *weights, const int type)
3272{
3273  int newEl = rowStarts[numRows] - rowStarts[0];
3274
3275  if (numRows + model->nSos > model->sosCap) {
3276    int prevCap = model->sosCap;
3277    if (prevCap) {
3278      model->sosCap = std::max( 2*model->sosCap, numRows + model->nSos);
3279      model->sosRowStart = (int *) xrealloc(model->sosRowStart, sizeof(int)*(model->sosCap+1) );
3280      model->sosType = (int *) xrealloc(model->sosRowStart, sizeof(int)*(model->sosCap) );
3281    } else {
3282      model->sosCap = max(1024, numRows);
3283      model->sosRowStart = (int *) xmalloc(sizeof(int)*(model->sosCap+1) );
3284      model->sosType = (int *) xmalloc(sizeof(int)*(model->sosCap) );
3285      model->sosRowStart[0] = 0;
3286      model->sosElCap = std::max(8192, newEl);
3287      model->sosEl = (int *) xmalloc( sizeof(int)*model->sosElCap );
3288      model->sosElWeight = (double *) xmalloc( sizeof(double)*model->sosElCap );
3289      model->sosElSize = 0;
3290      model->nSos = 0;
3291    }
3292  }
3293
3294  for ( int i=0 ; i<numRows ; ++i )
3295    model->sosType[model->nSos+i] = type;
3296
3297  if ( model->sosElSize + newEl > model->sosElCap ) {
3298    model->sosElCap = max( 2*model->sosElCap, newEl );
3299    model->sosEl = (int *) xrealloc( model->sosEl, sizeof(int)*model->sosElCap );
3300    model->sosElWeight  = (double *) xrealloc( model->sosElWeight, sizeof(double)*model->sosElCap );
3301  }
3302
3303  memcpy( model->sosEl + model->sosElSize, colIndices, sizeof(int)*newEl );
3304  memcpy( model->sosElWeight + model->sosElSize, weights, sizeof(double)*newEl );
3305
3306  for ( int i=0 ; (i<numRows) ; ++i ) {
3307    int size = rowStarts[i+1] - rowStarts[i];
3308    model->sosRowStart[model->nSos+1] = model->sosRowStart[model->nSos] + size;
3309    model->nSos++;
3310  }
3311
3312  model->sosElSize += newEl;
3313}
3314
3315void CBC_LINKAGE
3316Cbc_setMIPStart(Cbc_Model *model, int count, const char **colNames, const double colValues[])
3317{
3318  if (model->nColsMS) {
3319    if (model->colNamesMS) {
3320      free( model->colNamesMS[0]);
3321      free( model->colNamesMS);
3322    }
3323    free( model->colValuesMS );
3324  }
3325
3326  int nameSpace = 0;
3327  for ( int i=0 ; (i<count) ; ++i )
3328    nameSpace += strlen(colNames[i]);
3329  nameSpace += count;
3330
3331  model->colValuesMS = (double *) xmalloc( sizeof(double)*count );
3332  model->colNamesMS = (char **) xmalloc( sizeof(char*)*count );
3333  model->charSpaceMS = sizeof(char)*nameSpace;
3334  model->colNamesMS[0] = (char *) xmalloc( model->charSpaceMS );
3335
3336
3337  for ( int i=1 ; (i<count) ; ++i )
3338    model->colNamesMS[i] = model->colNamesMS[i-1] + 1 + strlen(colNames[i-1]);
3339
3340  for ( int i=0 ; (i<count) ; ++i )
3341    strcpy( model->colNamesMS[i], colNames[i] );
3342
3343  memcpy(model->colValuesMS, colValues, sizeof(double)*count );
3344  model->nColsMS = count;
3345}
3346
3347void CBC_LINKAGE
3348Cbc_setMIPStartI(Cbc_Model *model, int count, const int colIdxs[], const double colValues[])
3349{
3350  OsiSolverInterface *solver = model->solver_;
3351
3352  if (model->nColsMS) {
3353    if (model->colNamesMS) {
3354      free( model->colNamesMS[0]);
3355      free( model->colNamesMS);
3356    }
3357    free( model->colValuesMS );
3358  }
3359
3360  int nameSpace = 0;
3361  for ( int i=0 ; (i<count) ; ++i )
3362    nameSpace += solver->getColName(colIdxs[i]).size();
3363  nameSpace += count;
3364
3365  model->colValuesMS = (double *) xmalloc( sizeof(double)*count );
3366  model->colNamesMS = (char **) xmalloc( sizeof(char*)*count );
3367  model->charSpaceMS = sizeof(char)*nameSpace;
3368  model->colNamesMS[0] = (char *) xmalloc( model->charSpaceMS );
3369
3370  for ( int i=1 ; (i<count) ; ++i )
3371    model->colNamesMS[i] = model->colNamesMS[i-1] + 1 + solver->getColName(colIdxs[i-1]).size();
3372
3373  for ( int i=0 ; (i<count) ; ++i ) {
3374    strcpy( model->colNamesMS[i], solver->getColName(colIdxs[i]).c_str() );
3375    model->colValuesMS[i] = colValues[i];
3376  }
3377
3378  memcpy(model->colValuesMS, colValues, sizeof(double)*count );
3379  model->nColsMS = count;
3380}
3381
3382
3383/** @brief Creates a new OsiClpSolverInterface and returns a pointer to an OsiSolverInterface object */
3384void * CBC_LINKAGE
3385Osi_newSolver()
3386{
3387  OsiClpSolverInterface *clp = new OsiClpSolverInterface();
3388
3389  return dynamic_cast<OsiSolverInterface *>(clp);
3390}
3391
3392void CBC_LINKAGE
3393Osi_setObjCoef(void *osi, int index, double obj)
3394{
3395  OsiSolverInterface *osis = (OsiSolverInterface *)osi;
3396  osis->setObjCoeff( index, obj );
3397}
3398
3399/** @brief Solves initial LP relaxation */
3400void CBC_LINKAGE
3401Osi_initialSolve(void *osi)
3402{
3403  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3404  osis->initialSolve();
3405}
3406
3407/** @brief Reoptimizes linear program  */
3408void CBC_LINKAGE
3409Osi_resolve(void *osi)
3410{
3411  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3412  osis->resolve();
3413}
3414
3415/** @brief Performs branch and bound */
3416void CBC_LINKAGE
3417Osi_branchAndBound(void *osi)
3418{
3419  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3420  osis->branchAndBound();
3421}
3422
3423// solution query methods
3424/** @brief Checks if optimization was abandoned */
3425char CBC_LINKAGE
3426Osi_isAbandoned(void *osi)
3427{
3428  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3429  return (char)osis->isAbandoned();
3430}
3431
3432/** @brief Checks if optimal solution was found */
3433char CBC_LINKAGE
3434Osi_isProvenOptimal(void *osi)
3435{
3436  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3437  return (char)osis->isProvenOptimal();
3438}
3439
3440/** @brief Checks if problem is primal infeasible */
3441char CBC_LINKAGE
3442Osi_isProvenPrimalInfeasible(void *osi)
3443{
3444  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3445  return (char)osis->isProvenPrimalInfeasible();
3446}
3447
3448/** @brief Checks if problem is dual infeasible */
3449char CBC_LINKAGE
3450Osi_isProvenDualInfeasible(void *osi)
3451{
3452  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3453  return (char)osis->isProvenDualInfeasible();
3454}
3455
3456/** @brief Checks if primal objective limit was reached */
3457char CBC_LINKAGE
3458Osi_isPrimalObjectiveLimitReached(void *osi)
3459{
3460  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3461  return (char)osis->isPrimalObjectiveLimitReached();
3462}
3463
3464/** @brief Checks if dual objective limit was reached */
3465char CBC_LINKAGE
3466Osi_isDualObjectiveLimitReached(void *osi)
3467{
3468  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3469  return (char)osis->isDualObjectiveLimitReached();
3470}
3471
3472/** @brief Checks if iteration limit was reached */
3473char CBC_LINKAGE
3474Osi_isIterationLimitReached(void *osi)
3475{
3476  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3477  return (char)osis->isIterationLimitReached();
3478}
3479
3480
3481int CBC_LINKAGE
3482Osi_getNumCols( void *osi )
3483{
3484  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3485  return osiSolver->getNumCols();
3486}
3487
3488
3489/** @brief Creates (it not yet) the conflict graph  */
3490void 
3491Osi_checkCGraph( void *osi ) {
3492  OsiSolverInterface *solver = (OsiSolverInterface *)(osi);
3493  solver->checkCGraph();
3494}
3495
3496/** @brief Returns the conflict graph */
3497CBCSOLVERLIB_EXPORT const void * CBC_LINKAGE
3498Osi_CGraph( void *osi ) {
3499  OsiSolverInterface *solver = (OsiSolverInterface *)(osi);
3500  return solver->getCGraph();
3501}
3502
3503size_t CG_nodes( void *cgraph ) {
3504  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3505  return cg->size();
3506}
3507
3508char CG_conflicting( void *cgraph, size_t n1, size_t n2 ) {
3509  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3510  return (char) cg->conflicting(n1, n2);
3511}
3512
3513/** @brief Density of the conflict graph */
3514double CG_density( void *cgraph ) {
3515  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3516  return cg->density();
3517}
3518
3519
3520CGNeighbors CG_conflictingNodes(Cbc_Model *model, void *cgraph, size_t node) {
3521  CGNeighbors result;
3522
3523#ifdef CBC_THREAD
3524    pthread_mutex_lock(&model->cbcMutexCG);
3525#endif
3526
3527  if (model->cg_space < Cbc_getNumCols(model)*2) {
3528    if (model->cg_space) {
3529      free( model->cg_neighs);
3530      free(model->cg_iv);
3531    }
3532
3533    model->cg_space = Cbc_getNumCols(model)*2;
3534
3535    model->cg_neighs  = (size_t *) xmalloc( sizeof(size_t)*model->cg_space );
3536    model->cg_iv  = (bool *) xmalloc( sizeof(bool)*model->cg_space );
3537    memset(model->cg_iv, 0, sizeof(bool)*model->cg_space);
3538  }
3539
3540  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3541
3542  std::pair< size_t, const size_t* > r = cg->conflictingNodes( node, model->cg_neighs, model->cg_iv);
3543#ifdef CBC_THREAD
3544    pthread_mutex_unlock(&model->cbcMutexCG);
3545#endif
3546
3547  result.n = r.first;
3548  result.neigh = r.second;
3549
3550  return result;
3551}
3552
3553
3554
3555
3556
3557/** @brief Returns column name in OsiSolverInterface object */
3558void CBC_LINKAGE
3559Osi_getColName( void *osi, int i, char *name, int maxLen )
3560{
3561  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3562  strncpy( name, osiSolver->getColName(i).c_str(), maxLen );
3563}
3564
3565/** @brief Returns column lower bounds in OsiSolverInterface object */
3566const double * CBC_LINKAGE
3567Osi_getColLower( void *osi )
3568{
3569  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3570  return osiSolver->getColLower();
3571}
3572
3573/** @brief Returns column upper bounds in OsiSolverInterface object */
3574const double * CBC_LINKAGE
3575Osi_getColUpper( void *osi )
3576{
3577  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3578  return osiSolver->getColUpper();
3579}
3580
3581/** @brief Returns integrality information for columns in OsiSolverInterface object */
3582int CBC_LINKAGE
3583Osi_isInteger( void *osi, int col )
3584{
3585  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3586  return osiSolver->isInteger(col);
3587}
3588
3589/** @brief Returns number of rows in OsiSolverInterface object */
3590int CBC_LINKAGE
3591Osi_getNumRows( void *osi )
3592{
3593  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3594  return osiSolver->getNumRows();
3595}
3596
3597/** @brief Returns number non-zeros in the constraint matrix */
3598int CBC_LINKAGE
3599Osi_getNumNz( void *osi )
3600{
3601  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3602  return osiSolver->getNumElements();
3603}
3604
3605/** @brief Returns number integer/binary variables */
3606int CBC_LINKAGE
3607Osi_getNumIntegers( void *osi )
3608{
3609  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3610  return osiSolver->getNumIntegers();
3611}
3612
3613int CBC_LINKAGE
3614Osi_getRowNz(void *osi, int row)
3615{
3616  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3617
3618  const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow();
3619  return cpmRow->getVectorLengths()[row];
3620}
3621
3622/** @brief Indices of variables that appear on a row */
3623const int *CBC_LINKAGE
3624Osi_getRowIndices(void *osi, int row)
3625{
3626  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3627
3628  const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow();
3629  const CoinBigIndex *starts = cpmRow->getVectorStarts();
3630  const int *ridx = cpmRow->getIndices() + starts[row];
3631  return ridx;
3632}
3633
3634/** @brief Coefficients of variables that appear on this row  */
3635const double *CBC_LINKAGE
3636Osi_getRowCoeffs(void *osi, int row)
3637{
3638  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3639
3640  const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow();
3641  const CoinBigIndex *starts = cpmRow->getVectorStarts();
3642  const double *rcoef = cpmRow->getElements() + starts[row];
3643  return rcoef;
3644}
3645
3646/** @brief Right hand side of a row  */
3647double CBC_LINKAGE
3648Osi_getRowRHS(void *osi, int row)
3649{
3650  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3651  return osiSolver->getRightHandSide()[row];
3652}
3653
3654/** @brief Sense a row
3655     * @param model problem object
3656     * @param row row index
3657     * @return row sense: E for =, L for <=, G for >= and R for ranged row
3658     **/
3659char CBC_LINKAGE
3660Osi_getRowSense(void *osi, int row)
3661{
3662  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3663
3664  return osiSolver->getRowSense()[row];
3665}
3666
3667/** Generates cutting planes */
3668void CBC_LINKAGE Cgl_generateCuts( void *osiClpSolver, enum CutType ct, void *oc, int strength ) {
3669  OsiClpSolverInterface *solver = (OsiClpSolverInterface *) osiClpSolver;
3670  CglCutGenerator *cg[2] = {NULL, NULL};
3671  OsiCuts *osiCuts = (OsiCuts *) oc;
3672
3673  switch (ct) {
3674    case CT_Gomory:
3675      cg[0] = new CglGomory();
3676      break;
3677    case CT_Clique:
3678      if (solver->getCGraph())
3679        cg[0] = new CglBKClique();
3680      else {
3681        CglClique *clqgen = new CglClique();
3682        clqgen->setStarCliqueReport(false);
3683        clqgen->setRowCliqueReport(false);
3684        clqgen->setMinViolation(1e-4);
3685        cg[0] = clqgen;
3686      }
3687      break;
3688    case CT_KnapsackCover:
3689      cg[0] = new CglKnapsackCover();
3690      break;
3691    case CT_MIR:
3692      {
3693        CglMixedIntegerRounding2 *cgMIR = new CglMixedIntegerRounding2(1, true, 1);
3694        cg[0] = cgMIR;
3695        cgMIR->setDoPreproc(1); // safer (and better)
3696        cg[1] = new CglTwomir();
3697      }
3698      break;
3699    case CT_ZeroHalf:
3700      cg[0] = new CglZeroHalf();
3701      break;
3702    case CT_LiftAndProject:
3703      cg[0] = new CglLandP();
3704      break;
3705  }
3706
3707  for ( int i=0 ; i<2 ; ++i ) {
3708    if (cg[i] == NULL) 
3709      continue;
3710    cg[i]->generateCuts(*solver, *osiCuts);
3711
3712    delete cg[i];
3713  }
3714}
3715
3716/** Creates a new cut pool and returns its pointer */
3717void * CBC_LINKAGE
3718OsiCuts_new() {
3719  OsiCuts *oc = new OsiCuts();
3720  return (void *) oc;
3721}
3722
3723/** Deletes a cut pool */
3724void CBC_LINKAGE
3725OsiCuts_delete( void *osiCuts ) {
3726  OsiCuts *oc = (OsiCuts *) osiCuts;
3727  delete oc;
3728}
3729
3730/** Returns the number of row cuts stored */
3731int CBC_LINKAGE
3732OsiCuts_sizeRowCuts( void *osiCuts ) {
3733  OsiCuts *oc = (OsiCuts *)osiCuts;
3734  return oc->sizeRowCuts();
3735}
3736
3737/** Returns the number of row cuts stored */
3738int CBC_LINKAGE
3739OsiCuts_nzRowCut( void *osiCuts, int iRowCut ) {
3740  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3741  OsiCuts *oc = (OsiCuts *)osiCuts;
3742  const OsiRowCut &rc = oc->rowCut(iRowCut);
3743  return rc.row().getNumElements();
3744}
3745
3746/** Returns the variable indexes in a row cut */
3747const int * CBC_LINKAGE
3748OsiCuts_idxRowCut( void *osiCuts, int iRowCut ) {
3749  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3750  OsiCuts *oc = (OsiCuts *)osiCuts;
3751  const OsiRowCut &rc = oc->rowCut(iRowCut);
3752  return rc.row().getIndices();
3753}
3754
3755/** Returns the variable coefficients in a row cut */
3756const double * CBC_LINKAGE
3757OsiCuts_coefRowCut( void *osiCuts, int iRowCut ) {
3758  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3759  OsiCuts *oc = (OsiCuts *)osiCuts;
3760  const OsiRowCut &rc = oc->rowCut(iRowCut);
3761  return rc.row().getElements();
3762}
3763
3764/** Returns the variable coefficients in a row cut */
3765double CBC_LINKAGE
3766OsiCuts_rhsRowCut( void *osiCuts, int iRowCut ) {
3767  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3768  OsiCuts *oc = (OsiCuts *)osiCuts;
3769  const OsiRowCut &rc = oc->rowCut(iRowCut);
3770  return rc.rhs();
3771}
3772
3773/** Returns the sense of a row cut */
3774char CBC_LINKAGE
3775OsiCuts_senseRowCut( void *osiCuts, int iRowCut ) {
3776  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3777  OsiCuts *oc = (OsiCuts *)osiCuts;
3778  const OsiRowCut &rc = oc->rowCut(iRowCut);
3779  return rc.sense();
3780}
3781
3782void CBC_LINKAGE
3783OsiCuts_addRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs )
3784{
3785  sense = toupper(sense);
3786  OsiCuts *oc = (OsiCuts *) osiCuts;
3787
3788  OsiRowCut orc;
3789  orc.setRow( nz, idx, coef );
3790
3791
3792  orc.setLb(-DBL_MAX);
3793  orc.setUb(DBL_MAX);
3794
3795  switch (toupper(sense)) {
3796  case '=':
3797    orc.setLb(rhs);
3798    orc.setUb(rhs);
3799    break;
3800  case 'E':
3801    orc.setLb(rhs);
3802    orc.setUb(rhs);
3803    break;
3804  case '<':
3805    orc.setUb(rhs);
3806    break;
3807  case 'L':
3808    orc.setUb(rhs);
3809    break;
3810  case '>':
3811    orc.setLb(rhs);
3812    break;
3813  case 'G':
3814    orc.setLb(rhs);
3815    break;
3816  default:
3817    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3818    abort();
3819  }
3820
3821  oc->insert(orc);
3822}
3823
3824/** adds a row cut (used in callback), stating that this is a globally valid cut */
3825void CBC_LINKAGE
3826OsiCuts_addGlobalRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs )
3827{
3828  sense = toupper(sense);
3829  OsiCuts *oc = (OsiCuts *) osiCuts;
3830
3831  OsiRowCut orc;
3832  orc.setRow( nz, idx, coef );
3833
3834
3835  orc.setLb(-DBL_MAX);
3836  orc.setUb(DBL_MAX);
3837
3838  switch (toupper(sense)) {
3839  case '=':
3840    orc.setLb(rhs);
3841    orc.setUb(rhs);
3842    break;
3843  case 'E':
3844    orc.setLb(rhs);
3845    orc.setUb(rhs);
3846    break;
3847  case '<':
3848    orc.setUb(rhs);
3849    break;
3850  case 'L':
3851    orc.setUb(rhs);
3852    break;
3853  case '>':
3854    orc.setLb(rhs);
3855    break;
3856  case 'G':
3857    orc.setLb(rhs);
3858    break;
3859  default:
3860    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3861    abort();
3862  }
3863
3864  orc.setGloballyValid(true);
3865  oc->insert(orc);
3866}
3867
3868
3869/** @brief Sets a variable to integer */
3870void CBC_LINKAGE
3871Osi_setInteger(void *osi, int index)
3872{
3873  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3874
3875  osiSolver->setInteger(index);
3876}
3877
3878/** @brief Sets a variable to continuous */
3879void CBC_LINKAGE
3880Osi_setContinuous(void *osi, int index)
3881{
3882  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3883
3884  osiSolver->setContinuous(index);
3885}
3886
3887int CBC_LINKAGE
3888Osi_getColNz(void *osi, int col)
3889{
3890  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3891  const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol();
3892  return cpmCol->getVectorLengths()[col];
3893}
3894
3895/** @brief Indices of rows that a column appears
3896     *
3897     * @param model problem object
3898     * @param col column index
3899     * @return indices of rows that this column appears
3900     **/
3901const int *CBC_LINKAGE
3902Osi_getColIndices(void *osi, int col)
3903{
3904  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3905  const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol();
3906  const CoinBigIndex *starts = cpmCol->getVectorStarts();
3907  const int *cidx = cpmCol->getIndices() + starts[col];
3908  return cidx;
3909}
3910
3911/** @brief Coefficients that a column appear in rows
3912     *
3913     * @param model problem object
3914     * @param col column index
3915     * @return coefficients of this column in rows
3916     **/
3917const double *CBC_LINKAGE
3918Osi_getColCoeffs(void *osi, int col)
3919{
3920  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3921
3922  const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol();
3923  const CoinBigIndex *starts = cpmCol->getVectorStarts();
3924  const double *rcoef = cpmCol->getElements() + starts[col];
3925  return rcoef;
3926}
3927
3928/** @brief Returns solution vector in OsiSolverInterface object */
3929const double * CBC_LINKAGE
3930Osi_getColSolution( void *osi )
3931{
3932  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3933
3934  return osiSolver->getColSolution();
3935}
3936
3937/** Adds a new column */
3938void CBC_LINKAGE
3939Osi_addCol(void *osi, const char *name, double lb,
3940  double ub, double obj, char isInteger,
3941  int nz, int *rows, double *coefs)
3942{
3943  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3944
3945    osiSolver->addCol(nz, rows, coefs, lb, ub, obj, std::string(name));
3946    if (isInteger)
3947      osiSolver->setInteger(osiSolver->getNumCols() - 1);
3948}
3949
3950/** @brief Returns vector of reduced costs */
3951const double * CBC_LINKAGE
3952Osi_getReducedCost( void *osi )
3953{
3954  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3955
3956  return osiSolver->getColSolution();
3957}
3958
3959/** @brief Returns vector dual variables */
3960const double * CBC_LINKAGE
3961Osi_getRowPrice( void *osi )
3962{
3963  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3964
3965  return osiSolver->getRowPrice();
3966}
3967
3968double CBC_LINKAGE
3969Osi_getObjValue( void *osi )
3970{
3971  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3972
3973  return osiSolver->getObjValue();
3974}
3975
3976/** @brief Sets column upper bound */
3977void CBC_LINKAGE
3978Osi_setColUpper (void *osi, int elementIndex, double ub)
3979{
3980  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3981  osiSolver->setColUpper(elementIndex, ub);
3982}
3983
3984/** @brief Sets column upper bound */
3985void CBC_LINKAGE
3986Osi_setColLower(void *osi, int elementIndex, double lb)
3987{
3988  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3989  osiSolver->setColLower(elementIndex, lb);
3990}
3991
3992/** @brief integer tolerance */
3993double CBC_LINKAGE
3994Osi_getIntegerTolerance(void *osi)
3995{
3996  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3997  return osiSolver->getIntegerTolerance();
3998}
3999
4000double CBC_LINKAGE
4001Cbc_getAllowableGap(Cbc_Model* model)
4002{
4003  return model->dbl_param[DBL_PARAM_ALLOWABLE_GAP];
4004}
4005
4006void CBC_LINKAGE
4007Cbc_setAllowableGap(Cbc_Model* model, double allowedGap)
4008{
4009  model->dbl_param[DBL_PARAM_ALLOWABLE_GAP] = allowedGap;
4010}
4011
4012double CBC_LINKAGE
4013Cbc_getAllowableFractionGap(Cbc_Model* model)
4014{
4015  return model->dbl_param[DBL_PARAM_GAP_RATIO];
4016}
4017
4018void CBC_LINKAGE
4019Cbc_setAllowableFractionGap(Cbc_Model* model, double allowedFracionGap)
4020{
4021  model->dbl_param[DBL_PARAM_GAP_RATIO] = allowedFracionGap;
4022}
4023
4024/** returns the maximum number of nodes that can be explored in the search tree
4025 */
4026int CBC_LINKAGE
4027Cbc_getMaximumNodes(Cbc_Model *model)
4028{
4029  return model->int_param[INT_PARAM_MAX_NODES];
4030}
4031
4032/** sets the maximum number of nodes that can be explored in the search tree
4033 */
4034void CBC_LINKAGE
4035Cbc_setMaximumNodes(Cbc_Model *model, int maxNodes)
4036{
4037  model->int_param[INT_PARAM_MAX_NODES] = maxNodes;
4038}
4039
4040/** returns solution limit for the search process
4041 */
4042int CBC_LINKAGE
4043Cbc_getMaximumSolutions(Cbc_Model *model)
4044{
4045  return model->int_param[INT_PARAM_MAX_SOLS];
4046}
4047
4048/** sets a solution limit as a stopping criterion
4049 */
4050void CBC_LINKAGE
4051Cbc_setMaximumSolutions(Cbc_Model *model, int maxSolutions)
4052{
4053  model->int_param[INT_PARAM_MAX_SOLS] = maxSolutions;
4054}
4055
4056/** returns the current log leven
4057 */
4058int CBC_LINKAGE
4059Cbc_getLogLevel(Cbc_Model *model)
4060{
4061  return model->int_param[INT_PARAM_LOG_LEVEL];
4062}
4063
4064/** sets the log level
4065 */
4066void CBC_LINKAGE
4067Cbc_setLogLevel(Cbc_Model *model, int logLevel)
4068{
4069  model->int_param[INT_PARAM_LOG_LEVEL] = logLevel;
4070}
4071
4072/** gets the tolerance for infeasibility in the LP solver
4073 */
4074double CBC_LINKAGE
4075Cbc_getPrimalTolerance(Cbc_Model *model)
4076{
4077  return model->dbl_param[DBL_PARAM_PRIMAL_TOL];
4078}
4079
4080/** sets the tolerance for infeasibility in the LP solver
4081 */
4082void CBC_LINKAGE
4083Cbc_setPrimalTolerance(Cbc_Model *model, double tol)
4084{
4085  model->dbl_param[DBL_PARAM_PRIMAL_TOL] = tol;
4086}
4087
4088/** gets the tolerance for optimality in the LP solver
4089 */
4090double CBC_LINKAGE
4091Cbc_getDualTolerance(Cbc_Model *model)
4092{
4093  return model->dbl_param[DBL_PARAM_DUAL_TOL];
4094}
4095
4096/** sets the tolerance for optimality in the LP solver
4097 */
4098void CBC_LINKAGE
4099Cbc_setDualTolerance(Cbc_Model *model, double tol)
4100{
4101  model->dbl_param[DBL_PARAM_DUAL_TOL] = tol;
4102}
4103
4104double CBC_LINKAGE
4105Cbc_getCutoff(Cbc_Model* model)
4106{
4107  return model->dbl_param[DBL_PARAM_CUTOFF];
4108}
4109
4110void CBC_LINKAGE
4111Cbc_setCutoff(Cbc_Model* model, double cutoff)
4112{
4113  model->dbl_param[DBL_PARAM_CUTOFF] = cutoff;
4114}
4115
4116void CBC_LINKAGE
4117Cbc_setLPmethod(Cbc_Model *model, enum LPMethod lpm ) {
4118  model->lp_method = lpm;
4119}
4120
4121
4122void * CBC_LINKAGE
4123Cbc_getSolverPtr(Cbc_Model *model) {
4124  return model->solver_;
4125}
4126
4127void CBC_LINKAGE
4128Cbc_setDualPivot(Cbc_Model *model, enum DualPivot dp ) {
4129  model->dualp = dp;
4130}
4131
4132double CBC_LINKAGE
4133Cbc_getMaximumSeconds(Cbc_Model *model)
4134{
4135  return model->dbl_param[DBL_PARAM_TIME_LIMIT];
4136}
4137
4138void CBC_LINKAGE
4139Cbc_setMaximumSeconds(Cbc_Model *model, double maxSeconds)
4140{
4141  model->dbl_param[DBL_PARAM_TIME_LIMIT] = maxSeconds;
4142}
4143
4144void CBC_LINKAGE
4145Cbc_storeNameIndexes(Cbc_Model *model, char _store)
4146{
4147  if (_store)
4148  {
4149    if (model->colNameIndex==NULL)
4150    {
4151      assert(model->rowNameIndex==NULL);
4152      model->colNameIndex = new NameIndex();
4153      model->rowNameIndex = new NameIndex();
4154    }
4155  }
4156  else
4157  {
4158    if (model->colNameIndex!=NULL)
4159    {
4160      NameIndex *m = (NameIndex *)model->colNameIndex;
4161      delete m;
4162      m = (NameIndex *)model->rowNameIndex;
4163      assert( m != NULL );
4164      delete m;
4165
4166      model->colNameIndex = model->rowNameIndex = NULL;
4167    }
4168  }
4169}
4170
4171int CBC_LINKAGE
4172Cbc_getColNameIndex(Cbc_Model *model, const char *name)
4173{
4174  if (!model->colNameIndex)
4175  {
4176    fprintf(stderr, "Call Cbc_storeNameIndex to enable name index search.");
4177    abort();
4178  }
4179
4180  NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
4181  NameIndex::iterator it = colNameIndex.find(std::string(name));
4182  if (it == colNameIndex.end())
4183    return -1;
4184
4185  return it->second;
4186}
4187
4188int CBC_LINKAGE
4189Cbc_getRowNameIndex(Cbc_Model *model, const char *name)
4190{
4191  if (!model->rowNameIndex)
4192  {
4193    fprintf(stderr, "Call Cbc_storeNameIndex to enable name index search.");
4194    abort();
4195  }
4196
4197  NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
4198  NameIndex::iterator it = rowNameIndex.find(std::string(name));
4199  if (it == rowNameIndex.end())
4200    return -1;
4201
4202  return it->second;
4203}
4204
4205static char **to_char_vec( const vector< string > names )
4206{
4207    size_t spaceVec = (sizeof(char*)*names.size());
4208    size_t totLen = names.size(); // all \0
4209    for ( int i=0 ; (i<(int)names.size()) ; ++i )
4210        totLen += names[i].size();
4211    totLen *= sizeof(char);
4212
4213    char **r = (char **)xmalloc(spaceVec+totLen);
4214    assert( r );
4215    r[0] = (char *)(r + names.size());
4216    for ( size_t i=1 ; (i<names.size()) ; ++i )
4217        r[i] = r[i-1] + names[i-1].size() + 1;
4218
4219    for ( size_t i=0 ; (i<names.size()) ; ++i )
4220        strcpy(r[i], names[i].c_str());
4221
4222    return r;
4223}
4224
4225static void *xmalloc( const size_t size )
4226{
4227   void *result = malloc( size );
4228   if (!result)
4229   {
4230      fprintf(stderr, "No more memory available. Trying to allocate %zu bytes.", size);
4231      abort();
4232   }
4233
4234   return result;
4235}
4236
4237
4238static void *xrealloc( void *ptr, const size_t newSize ) {
4239  void *res = realloc( ptr, newSize );
4240
4241  if (!res) {
4242      fprintf(stderr, "No more memory available. Trying to allocate %zu bytes.", newSize);
4243      abort();
4244   }
4245
4246  return res;
4247}
4248
4249void Cbc_addAllSOS( Cbc_Model *model ) {
4250  if (model->nSos == 0)
4251    return;
4252
4253  CbcModel *cbcModel = model->cbcModel_;
4254
4255  vector< CbcObject *> objects;
4256  objects.reserve( model->nSos );
4257  for ( int i=0 ; i<model->nSos ; ++i ) {
4258    objects.push_back(
4259        new CbcSOS( 
4260            cbcModel, 
4261            model->sosRowStart[i+1]-model->sosRowStart[i],
4262            model->sosEl + model->sosRowStart[i],
4263            model->sosElWeight + model->sosRowStart[i],
4264            (int)objects.size(),
4265            model->sosType[i]
4266          ) 
4267        ); // add in objects
4268  }
4269
4270  cbcModel->addObjects( (int) objects.size(), &objects[0] );
4271
4272  for ( int i=0 ; i<model->nSos ; ++i ) 
4273    delete objects[i];
4274}
4275
4276static void Cbc_addMS( Cbc_Model *model ) {
4277  if ( model->nColsMS == 0 )
4278    return;
4279
4280  CbcModel *cbc = model->cbcModel_;
4281
4282  cbc->setMIPStart( model->nColsMS, (const char **)model->colNamesMS, model->colValuesMS );
4283}
4284
4285void Cbc_iniParams( Cbc_Model *model ) {
4286  model->lp_method = LPM_Auto;
4287  model->dualp = DP_Auto;
4288  model->cg_space = 0;
4289  model->cg_iv = NULL;
4290  model->cg_neighs = NULL;
4291  memset(model->int_param, 0, sizeof(model->int_param) );
4292  for ( int i=0 ; (i<N_DBL_PARAMS) ; ++i )
4293    model->dbl_param[i] = 0.0;
4294
4295  model->int_param[INT_PARAM_PERT_VALUE]       =       50;
4296  model->int_param[INT_PARAM_IDIOT]            =       -1;
4297  model->int_param[INT_PARAM_STRONG_BRANCHING] =        5;
4298  model->int_param[INT_PARAM_CUT_DEPTH]        =       -1;
4299  model->int_param[INT_PARAM_MAX_NODES]        =  INT_MAX;
4300  model->int_param[INT_PARAM_NUMBER_BEFORE]    =        5;
4301  model->int_param[INT_PARAM_FPUMP_ITS]        =       30;
4302  model->int_param[INT_PARAM_MAX_SOLS]         =       -1;
4303  model->int_param[INT_PARAM_CUT_PASS_IN_TREE] =        1;
4304  model->int_param[INT_PARAM_LOG_LEVEL]        =        1;
4305  model->int_param[INT_PARAM_MAX_SAVED_SOLS]   =       -1;
4306  model->int_param[INT_PARAM_MULTIPLE_ROOTS]   =        0;
4307  model->int_param[INT_PARAM_THREADS]          =       -1;
4308  model->int_param[INT_PARAM_ROUND_INT_VARS]   =        1;
4309  model->int_param[INT_PARAM_RANDOM_SEED]      =        1;
4310  model->int_param[INT_PARAM_ELAPSED_TIME]     =        1;
4311
4312  model->dbl_param[DBL_PARAM_PRIMAL_TOL]       =          1e-6;
4313  model->dbl_param[DBL_PARAM_DUAL_TOL]         =          1e-6;
4314  model->dbl_param[DBL_PARAM_ZERO_TOL]         =         1e-20;
4315  model->dbl_param[DBL_PARAM_INT_TOL]          =          1e-6;
4316  model->dbl_param[DBL_PARAM_PRESOLVE_TOL]     =          1e-8;
4317  model->dbl_param[DBL_PARAM_TIME_LIMIT]       =  COIN_DBL_MAX;
4318  model->dbl_param[DBL_PARAM_PSI]              =          -1.0;
4319  model->dbl_param[DBL_PARAM_CUTOFF]           =  COIN_DBL_MAX;
4320  model->dbl_param[DBL_PARAM_ALLOWABLE_GAP]    =         1e-10;
4321  model->dbl_param[DBL_PARAM_GAP_RATIO]        =        0.0001;
4322}
4323
4324#if defined(__MWERKS__)
4325#pragma export off
4326#endif
4327
4328/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
4329*/
Note: See TracBrowser for help on using the repository browser.