source: trunk/src/Cbc_C_Interface.cpp @ 3042

Last change on this file since 3042 was 3042, checked in by unxusr, 21 months ago

C interface: flush model before quering conflict graph

  • 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 3042 2020-05-12 20:13:27Z 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  Cbc_flush(model);
1423  model->solver_->checkCGraph();
1424}
1425
1426int CBC_LINKAGE
1427Cbc_getNumIntegers(Cbc_Model *model)
1428{
1429  return model->solver_->getNumIntegers() + model->nInt;
1430}
1431
1432// Column starts in matrix
1433const CoinBigIndex *CBC_LINKAGE
1434Cbc_getVectorStarts(Cbc_Model *model)
1435{
1436  Cbc_flush(model);
1437
1438  const CoinPackedMatrix *matrix = NULL;
1439  matrix = model->solver_->getMatrixByCol();
1440  return (matrix == NULL) ? NULL : matrix->getVectorStarts();
1441}
1442
1443// Row indices in matrix
1444const int *CBC_LINKAGE
1445Cbc_getIndices(Cbc_Model *model)
1446{
1447  Cbc_flush(model);
1448
1449  const int *result = NULL;
1450  const CoinPackedMatrix *matrix = NULL;
1451  matrix = model->solver_->getMatrixByCol();
1452  result = (matrix == NULL) ? NULL : matrix->getIndices();
1453
1454  return result;
1455}
1456
1457// Element values in matrix
1458const double *CBC_LINKAGE
1459Cbc_getElements(Cbc_Model *model)
1460{
1461  Cbc_flush(model);
1462
1463  const double *result = NULL;
1464  const CoinPackedMatrix *matrix = NULL;
1465  matrix = model->solver_->getMatrixByCol();
1466  result = (matrix == NULL) ? NULL : matrix->getElements();
1467
1468  return result;
1469}
1470// ======================================================================
1471
1472/* Pass in Callback function */
1473void CBC_LINKAGE
1474Cbc_registerCallBack(Cbc_Model *model,
1475  cbc_callback userCallBack)
1476{
1477  model->userCallBack = userCallBack;
1478}
1479/* Unset Callback function */
1480void CBC_LINKAGE
1481Cbc_clearCallBack(Cbc_Model *model)
1482{
1483  model->userCallBack = NULL;
1484}
1485
1486/* length of names (0 means no names0 */
1487size_t CBC_LINKAGE
1488Cbc_maxNameLength(Cbc_Model *model)
1489{
1490  size_t result = 0;
1491  OsiSolverInterface::OsiNameVec const &rownames = model->solver_->getRowNames();
1492  for (size_t i = 0; i < rownames.size(); i++) {
1493    if (rownames[i].length() > result)
1494      result = rownames[i].length();
1495  }
1496  OsiSolverInterface::OsiNameVec const &colnames = model->solver_->getColNames();
1497  for (size_t i = 0; i < colnames.size(); i++) {
1498    if (colnames[i].length() > result)
1499      result = colnames[i].length();
1500  }
1501
1502  // go trough buffered names also
1503  for ( size_t i=0 ; (i<(size_t)model->nCols) ; ++i )
1504    result = max( result, strlen(model->cNames+model->cNameStart[i]) );
1505
1506  for ( size_t i=0 ; (i<(size_t)model->nRows) ; ++i )
1507    result = max( result, strlen(model->rNames+model->rNameStart[i]) );
1508
1509  return result;
1510}
1511
1512void CBC_LINKAGE
1513Cbc_getRowName(Cbc_Model *model, int iRow, char *name, size_t maxLength)
1514{
1515  VALIDATE_ROW_INDEX( iRow, model );
1516
1517  if (iRow < model->solver_->getNumRows()) {
1518    std::string rowname = model->solver_->getRowName(iRow);
1519    strncpy(name, rowname.c_str(), maxLength);
1520    name[maxLength - 1] = '\0';
1521  } else {
1522    int idxRowBuffer = iRow - model->solver_->getNumRows();
1523    strncpy( name, model->rNames+model->rNameStart[idxRowBuffer], maxLength );
1524  }
1525}
1526
1527void CBC_LINKAGE
1528Cbc_getColName(Cbc_Model *model, int iColumn, char *name, size_t maxLength)
1529{
1530  VALIDATE_COL_INDEX( iColumn, model );
1531
1532  if (iColumn < model->solver_->getNumCols()) {
1533    std::string colname = model->solver_->getColName(iColumn);
1534    strncpy(name, colname.c_str(), maxLength);
1535    name[maxLength - 1] = '\0';
1536  } else {
1537    int idxColBuffer = iColumn - model->solver_->getNumCols();
1538    strncpy( name, model->cNames+model->cNameStart[idxColBuffer], maxLength );
1539  }
1540
1541}
1542
1543void CBC_LINKAGE
1544Cbc_setColName(Cbc_Model *model, int iColumn, const char *name)
1545{
1546  VALIDATE_COL_INDEX( iColumn, model );
1547
1548  Cbc_flush(model);
1549  OsiSolverInterface *solver = model->solver_;
1550  std::string previousName = solver->getColName(iColumn);
1551  solver->setColName(iColumn, name);
1552
1553  if (!model->colNameIndex)
1554    return;
1555  NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
1556  NameIndex::iterator it = colNameIndex.find(previousName);
1557  if (it!=colNameIndex.end())
1558    colNameIndex.erase(it);
1559  colNameIndex[name] = iColumn;
1560}
1561
1562void CBC_LINKAGE
1563Cbc_setRowName(Cbc_Model *model, int iRow, const char *name)
1564{
1565  VALIDATE_ROW_INDEX( iRow, model );
1566
1567  Cbc_flush(model);
1568  OsiSolverInterface *solver = model->solver_;
1569  std::string previousName = solver->getRowName(iRow);
1570  solver->setRowName(iRow, name);
1571
1572  if (!model->rowNameIndex)
1573    return;
1574  NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
1575  NameIndex::iterator it = rowNameIndex.find(std::string(previousName));
1576  if (it!=rowNameIndex.end())
1577    rowNameIndex.erase(it);
1578  rowNameIndex[name] = iRow;
1579}
1580
1581void CBC_LINKAGE
1582Cbc_setSolveRelax(Cbc_Model *model, char solveOnlyRelax)
1583{
1584  model->relax_ = solveOnlyRelax;
1585}
1586
1587static int cbc_callb(CbcModel *cbcModel, int whereFrom) {
1588  Cbc_EventHandler *cbc_eh = dynamic_cast<Cbc_EventHandler *>(cbcModel->getEventHandler());
1589  if (cbc_eh == NULL)
1590    return 0;
1591
1592  if (cbc_eh->progr_callback != NULL)
1593  {
1594    switch (whereFrom)
1595    {
1596      case 1:
1597        cbc_eh->progr_callback(cbcModel, 0, 0, "root lp relax", cbcModel->getCurrentSeconds(),
1598                               cbcModel->getBestPossibleObjValue(), DBL_MAX, 0, NULL, cbc_eh->pgAppData);
1599        break;
1600      case 2:
1601        cbc_eh->progr_callback(cbcModel, 0, 0, "pre-proc", cbcModel->getCurrentSeconds(),
1602                               cbcModel->getBestPossibleObjValue(), cbcModel->getObjValue(), 0, NULL, cbc_eh->pgAppData);
1603        break;
1604    } // where from
1605  } // has progress callback
1606
1607  return 0;
1608}
1609
1610// adds all sos objects to the current cbcModel_ object
1611static void Cbc_addAllSOS( Cbc_Model *model );
1612
1613// adds mipstart if available
1614static void Cbc_addMS( Cbc_Model *model );
1615
1616int CBC_LINKAGE
1617Cbc_solveLinearProgram(Cbc_Model *model) 
1618{
1619  CoinMessages generalMessages = model->solver_->getModelPtr()->messages();
1620  model->solver_->getModelPtr()->setRandomSeed( model->int_param[INT_PARAM_RANDOM_SEED] );
1621
1622  Cbc_flush( model );
1623
1624  OsiSolverInterface *solver = model->solver_;
1625
1626  solver->setDblParam( OsiPrimalTolerance, model->dbl_param[DBL_PARAM_PRIMAL_TOL]);
1627  solver->setDblParam( OsiDualTolerance, model->dbl_param[DBL_PARAM_DUAL_TOL]);
1628
1629  OsiClpSolverInterface *clpSolver = dynamic_cast< OsiClpSolverInterface * >(solver);
1630  assert(clpSolver);
1631  ClpSimplex *clps = clpSolver->getModelPtr();
1632  assert(clps);
1633  clps->setPerturbation(model->int_param[INT_PARAM_PERT_VALUE]);
1634  solver->messageHandler()->setLogLevel( model->int_param[INT_PARAM_LOG_LEVEL] );
1635
1636  if (! cbc_annouced) {
1637    char generalPrint[512];
1638      sprintf(generalPrint,
1639        "Welcome to the CBC MILP Solver \n");
1640      if (strcmp(CBC_VERSION, "trunk")) {
1641        sprintf(generalPrint + strlen(generalPrint),
1642          "Version: %s \n", CBC_VERSION);
1643      } else {
1644        sprintf(generalPrint + strlen(generalPrint),
1645          "Version: Trunk\n");
1646      }
1647      sprintf(generalPrint + strlen(generalPrint),
1648        "Build Date: %s \n", __DATE__);
1649#ifdef CBC_SVN_REV
1650      sprintf(generalPrint + strlen(generalPrint),
1651        "Revision Number: %d \n", CBC_SVN_REV);
1652#endif
1653      solver->messageHandler()->setPrefix(false);
1654      solver->messageHandler()->message(CLP_GENERAL, generalMessages)
1655        << generalPrint
1656        << CoinMessageEol;
1657      solver->messageHandler()->setPrefix(true);
1658      cbc_annouced = 1;
1659  }
1660
1661  model->lastOptimization = ContinuousOptimization;
1662
1663  if (solver->basisIsAvailable()) {
1664    solver->resolve();
1665    if (solver->isProvenOptimal())
1666      return 0;
1667    if (solver->isIterationLimitReached())
1668      return 1;
1669    if (solver->isProvenDualInfeasible())
1670      return 3;
1671    if (solver->isProvenPrimalInfeasible())
1672      return 2;
1673  } // resolve
1674
1675  /* checking if options should be automatically tuned */
1676  if (model->lp_method == LPM_Auto) {
1677    ClpSimplexOther *clpo = static_cast<ClpSimplexOther *>(clps);
1678    assert(clpo);
1679    char *opts = clpo->guess(0);
1680    if (strstr(opts, "-primals") != NULL) {
1681      model->lp_method = LPM_Primal;
1682      //printf("Using primal;\n");
1683    }
1684    else if (strstr(opts, "-duals") != NULL) {
1685      model->lp_method = LPM_Dual;
1686      //printf("Using dual;\n");
1687    }
1688    else if (strstr(opts, "-barrier") != NULL) {
1689      //printf("Using barrier;\n");
1690      model->lp_method = LPM_Barrier;
1691    }
1692   
1693    char *s = NULL;
1694    char str[256] = "";
1695    if ((s=strstr(opts, "-idiot"))) {
1696      s = strstr(s+1, " ");
1697      if (s) {
1698        strcpy(str, s+1);
1699        if ((s = strstr(str+1, " ")))
1700          *s = '\0';
1701        int idiot = atoi(str);
1702        //printf("Setting idiot to %d\n", idiot);
1703        model->int_param[INT_PARAM_IDIOT] = idiot;
1704      }
1705    } // idiot
1706    if ((s=strstr(opts, "-pertv"))) {
1707      s = strstr(s+1, " ");
1708      if (s) {
1709        strcpy(str, s+1);
1710        if ((s = strstr(str+1, " ")))
1711          *s = '\0';
1712        int pertv = atoi(str);
1713        //printf("Setting pertv to %d\n", pertv);
1714        model->int_param[INT_PARAM_PERT_VALUE] = pertv;
1715      }
1716    } // perturbation value
1717    if ((s=strstr(opts, "-psi"))) {
1718      s = strstr(s+1, " ");
1719      if (s) {
1720        strcpy(str, s+1);
1721        if ((s = strstr(str+1, " ")))
1722          *s = '\0';
1723        double psi = atof(str);
1724        //printf("Setting psi to %g\n", psi);
1725        model->int_param[DBL_PARAM_PSI] = psi;
1726      }
1727    } // perturbation value
1728    if ((s=strstr(opts, "-dualpivot"))) {
1729        strcpy(str, s+1);
1730        if ((s = strstr(str+1, " ")))
1731          *s = '\0';
1732        if (strstr(str, "pesteep")) {
1733          model->dualp = DP_PESteepest;
1734          //printf("Setting dual pivot to pesteep.\n");
1735        }
1736    } // dual pivot
1737    delete[] opts;
1738  }
1739
1740  /* for integer or linear optimization starting with LP relaxation */
1741  ClpSolve clpOptions;
1742  char methodName[256] = "";
1743  switch (model->lp_method) {
1744    case LPM_Auto:
1745      fprintf(stderr, "Method should be already configured.\n");
1746      exit(1);
1747      break;
1748    case LPM_Primal:
1749      if (model->int_param[INT_PARAM_IDIOT] > 0) 
1750        clpOptions.setSpecialOption(1, 2, model->int_param[INT_PARAM_IDIOT]);
1751      clpOptions.setSolveType( ClpSolve::usePrimal );
1752      sprintf(methodName, "Primal Simplex");
1753      break;
1754    case LPM_Dual:
1755      clpOptions.setSolveType( ClpSolve::useDual );
1756      sprintf(methodName, "Dual Simplex");
1757      break;
1758    case LPM_Barrier:
1759      clpOptions.setSolveType( ClpSolve::useBarrier );
1760      clpOptions.setSpecialOption(4, 4);
1761      sprintf(methodName, "Barrier");
1762      break;
1763  }
1764  clpSolver->setSolveOptions(clpOptions);
1765
1766  switch (model->dualp) {
1767    case DP_Auto:
1768      {
1769        ClpDualRowSteepest asteep(3);
1770        clps->setDualRowPivotAlgorithm(asteep);
1771        break;
1772      }
1773    case DP_Dantzig:
1774      {
1775        ClpDualRowDantzig dantzig;
1776        clps->setDualRowPivotAlgorithm(dantzig);
1777        break;
1778      }
1779    case DP_Partial:
1780      {
1781        ClpDualRowSteepest bsteep(2);
1782        clps->setDualRowPivotAlgorithm(bsteep);
1783        break;
1784      }
1785    case DP_Steepest:
1786      {
1787        ClpDualRowSteepest csteep;
1788        clps->setDualRowPivotAlgorithm(csteep);
1789        break;
1790      }
1791    case DP_PESteepest:
1792      {
1793        ClpPEDualRowSteepest p(model->dbl_param[DBL_PARAM_PSI]);
1794        clps->setDualRowPivotAlgorithm(p);
1795        break;
1796      }
1797  }
1798 
1799  if (model->int_param[INT_PARAM_LOG_LEVEL] > 0)
1800  {
1801    char phaseName[128] = "";
1802    if (solver->getNumIntegers() && (!model->relax_))
1803      sprintf(phaseName, "Linear programming relaxation problem");
1804    else
1805      sprintf(phaseName, "Linear programming problem");
1806
1807    char msg[512] = "";
1808    sprintf(msg, "Starting solution of the %s using %s\n", phaseName, methodName );
1809    printf("%s\n", msg); fflush(stdout);
1810  }
1811
1812  model->lastOptimization = ContinuousOptimization;
1813  solver->initialSolve();
1814
1815  if (solver->isProvenOptimal()) {
1816    model->obj_value = solver->getObjValue();
1817    return 0;
1818  }
1819  if (solver->isIterationLimitReached()) {
1820    model->obj_value = solver->getObjValue();
1821    return 1;
1822  }
1823  if (solver->isProvenDualInfeasible())
1824    return 3;
1825  if (solver->isProvenPrimalInfeasible())
1826    return 2;
1827
1828  return -1;
1829}
1830
1831static void Cbc_updateSlack( Cbc_Model *model) {
1832  if (model->slack_) {
1833    free(model->slack_);
1834  }
1835
1836  int nRows = model->solver_->getNumRows(); 
1837  model->slack_ = (double *) xmalloc( sizeof(double)*nRows );
1838  const char *sense = model->solver_->getRowSense();
1839  const double *rrhs = model->solver_->getRightHandSide();
1840  const double *ractivity = model->lastOptimization == IntegerOptimization ? model->cbcModel_->getRowActivity() : model->solver_->getRowActivity();
1841  for ( int i=0 ; (i<nRows) ; ++i ) {
1842    const double rhs = rrhs[i];
1843    const double activity = ractivity[i];
1844    switch (sense[i]) {
1845      case 'L':
1846        model->slack_[i] = rhs-activity;
1847        break;
1848      case 'G':
1849        model->slack_[i] = activity-rhs;
1850        break;
1851      case 'E':
1852        model->slack_[i] = fabs(activity-rhs);
1853        break;
1854      case 'R':
1855        model->slack_[i] = min( model->solver_->getRowUpper()[i] - activity, 
1856                                activity - model->solver_->getRowLower()[i] );
1857        break;
1858    }
1859  }
1860}
1861
1862
1863void Cbc_strengthenPacking(Cbc_Model *model) {
1864  OsiSolverInterface *solver = model->solver_;
1865  CglCliqueStrengthening clqStr;
1866  clqStr.strengthenCliques(*solver);
1867}
1868
1869int CBC_LINKAGE
1870Cbc_solve(Cbc_Model *model)
1871{
1872  CoinMessages generalMessages = model->solver_->getModelPtr()->messages();
1873
1874  model->obj_value = COIN_DBL_MAX;
1875  model->lastOptNCols = Cbc_getNumCols(model);
1876  model->lastOptNRows = Cbc_getNumRows(model);
1877
1878  int res = Cbc_solveLinearProgram(model);
1879  if (res == 1)
1880    return 1;
1881  if (res==2 || res==3)
1882    return 0;
1883
1884  OsiSolverInterface *solver = model->solver_;
1885
1886  if (solver->isProvenPrimalInfeasible() || solver->isProvenDualInfeasible() ||
1887      solver->isAbandoned() || solver->isIterationLimitReached() || model->relax_ == 1
1888      || solver->getNumIntegers() == 0) {
1889    if (solver->isProvenOptimal() || solver->isIterationLimitReached()) {
1890      model->obj_value = solver->getObjValue();
1891      Cbc_updateSlack(model);
1892    }
1893
1894    return 0;
1895  }
1896
1897  // MIP Optimization
1898  if (model->cbcModel_) {
1899    delete model->cbcModel_;
1900  }
1901
1902  OsiClpSolverInterface *linearProgram = dynamic_cast<OsiClpSolverInterface *>( model->solver_->clone() );
1903  model->lastOptimization = IntegerOptimization;
1904  CbcModel *cbcModel = model->cbcModel_ = new CbcModel( *linearProgram );
1905
1906  try {
1907    if (model->lazyConstrs) {
1908      cbcModel->addCutGenerator(model->lazyConstrs, 1, "Stored LazyConstraints", true, 1);
1909      model->cutCBAtSol = 1;
1910    }
1911
1912    Cbc_EventHandler *cbc_eh = NULL;
1913    if (model->inc_callback!=NULL || model->progr_callback!=NULL)
1914    {
1915      cbc_eh = new Cbc_EventHandler(model->cbcModel_);
1916#ifdef CBC_THREAD
1917      cbc_eh->cbcMutex = &(model->cbcMutexEvent);
1918#endif
1919
1920      if (model->inc_callback) {
1921        cbc_eh->inc_callback = model->inc_callback;
1922        cbc_eh->appData = model->icAppData;
1923      }
1924      if (model->progr_callback) {
1925        cbc_eh->progr_callback = model->progr_callback;
1926        cbc_eh->pgAppData = model->pgrAppData;
1927      }
1928
1929      cbcModel->passInEventHandler(cbc_eh);
1930    }
1931
1932    if (model->iniSol)
1933      cbcModel->setBestSolution(&((*model->iniSol)[0]), Cbc_getNumCols(model), model->iniObj, true);
1934
1935    // add cut generator if necessary
1936    if (model->cut_callback) {
1937      cbcModel->setKeepNamesPreproc(true);
1938
1939      CglCallback cglCb;
1940      cglCb.appdata = model->cutCBData;
1941      cglCb.cut_callback_ = model->cut_callback;
1942#ifdef CBC_THREAD
1943      cglCb.cbcMutex = &(model->cbcMutexCG);
1944#endif
1945      cbcModel->addCutGenerator( &cglCb, model->cutCBhowOften, model->cutCBName.c_str(), true, model->cutCBAtSol );
1946    }
1947    if (model->cutCBAtSol) {
1948      Cbc_setParameter(model, "preprocess", "off");
1949      Cbc_setParameter(model, "heur", "off");       
1950    }
1951
1952    Cbc_MessageHandler *cbcmh  = NULL;
1953
1954    if (model->userCallBack) {
1955      cbcmh = new Cbc_MessageHandler(*cbcModel->messageHandler());
1956      cbcmh->setCallBack(model->userCallBack);
1957      cbcmh->setModel(model);
1958      cbcModel->passInMessageHandler(cbcmh);
1959    }
1960
1961    CbcSolverUsefulData cbcData;
1962    CbcMain0(*cbcModel, cbcData);
1963    cbcData.printWelcome_ = false;
1964
1965    cbcModel->solver()->setDblParam( OsiPrimalTolerance, model->dbl_param[DBL_PARAM_PRIMAL_TOL] );
1966    cbcModel->solver()->setDblParam( OsiDualTolerance, model->dbl_param[DBL_PARAM_DUAL_TOL] );
1967    // adds SOSs if any
1968    Cbc_addAllSOS(model);
1969
1970    // adds MIPStart if any
1971    Cbc_addMS( model );
1972
1973    // parameters
1974    if (model->dbl_param[DBL_PARAM_TIME_LIMIT] != COIN_DBL_MAX)
1975      cbcModel->setMaximumSeconds( model->dbl_param[DBL_PARAM_TIME_LIMIT] );
1976    if ( model->int_param[INT_PARAM_MAX_SOLS] != INT_MAX && model->int_param[INT_PARAM_MAX_SOLS] != -1 )
1977      cbcModel->setMaximumSolutions( model->int_param[INT_PARAM_MAX_SOLS] );
1978    cbcModel->setAllowableGap( model->dbl_param[DBL_PARAM_ALLOWABLE_GAP] );
1979    cbcModel->setAllowableFractionGap( model->dbl_param[DBL_PARAM_GAP_RATIO] );
1980    if ( model->int_param[INT_PARAM_MAX_NODES] != INT_MAX )
1981      cbcModel->setMaximumNodes( model->int_param[INT_PARAM_MAX_NODES] );
1982    cbcModel->setLogLevel( model->int_param[INT_PARAM_LOG_LEVEL] );
1983    if ( model->dbl_param[DBL_PARAM_CUTOFF] != COIN_DBL_MAX )
1984      cbcModel->setCutoff( model->dbl_param[DBL_PARAM_CUTOFF] );
1985
1986    // trying to reuse integer solution found in previous optimization
1987    if (model->lastOptNCols == model->solver_->getNumCols() && model->lastOptMIPSol) {
1988      const double *x = model->lastOptMIPSol;
1989      double maxViolRow, maxViolCol;
1990      int idxRow, idxCol;
1991      if (Cbc_checkFeasibility(model, x, &maxViolRow, &idxRow, &maxViolCol, &idxCol)) {
1992        double obj = 0;
1993        for ( int j=0 ; j<Cbc_getNumCols(model) ; ++j )
1994          obj += Cbc_getColObj(model, j)*x[j];
1995        cbcModel->setBestSolution(x, Cbc_getNumCols(model), obj);
1996      }
1997    } // try to reuse solution found in last optimization
1998
1999    std::vector< string > argv;
2000    argv.push_back("Cbc_C_Interface");
2001
2002    for ( size_t i=0 ; i<model->vcbcOptions.size() ; ++i ) {
2003      string param = model->vcbcOptions[i];
2004      string val = model->cbcOptions[param];
2005      if (val.size()) {
2006        stringstream ss;
2007        ss << "-" << param << "=" << val;
2008        argv.push_back(ss.str().c_str());
2009      } else {
2010        stringstream ss;
2011        ss << "-" << param;
2012        argv.push_back(ss.str());
2013      }
2014    }
2015
2016    argv.push_back("-solve");
2017    argv.push_back("-quit");
2018
2019    cbcData.noPrinting_= false;
2020
2021    char **charCbcOpts = to_char_vec(argv);
2022    const int nargs = (int) argv.size();
2023    const char **args = (const char **)charCbcOpts;
2024
2025    OsiBabSolver defaultC;
2026    if (model->cutCBAtSol) {
2027      defaultC.setSolverType(4);
2028      model->cbcModel_->solver()->setAuxiliaryInfo(&defaultC);
2029      model->cbcModel_->passInSolverCharacteristics(&defaultC);
2030    }
2031
2032    if (model->int_param[INT_PARAM_LOG_LEVEL] >= 1) {
2033      printf("\nStarting MIP optimization\n");
2034      fflush(stdout);
2035    }
2036#ifdef CBC_THREAD
2037    {
2038      int numberThreads = model->int_param[INT_PARAM_THREADS];
2039      if (numberThreads > 1) {
2040        model->cbcModel_->setNumberThreads(numberThreads);
2041        model->cbcModel_->setThreadMode(CoinMin(numberThreads / 100, 7));
2042      }
2043    }
2044#endif
2045    model->cbcModel_->setRoundIntegerVariables( model->int_param[INT_PARAM_ROUND_INT_VARS] );
2046    model->cbcModel_->setRandomSeed(model->int_param[INT_PARAM_RANDOM_SEED]);
2047    model->cbcModel_->setUseElapsedTime( (model->int_param[INT_PARAM_ELAPSED_TIME] == 1) );
2048
2049    CbcMain1( nargs, args, *model->cbcModel_, cbc_callb, cbcData );
2050
2051    if (Cbc_numberSavedSolutions(model)) {
2052      if (model->int_param[INT_PARAM_ROUND_INT_VARS]) {
2053        model->cbcModel_->roundIntVars();
2054      }
2055
2056      Cbc_updateSlack(model);
2057
2058      if (model->lastOptMIPSol && (model->lastOptNCols < Cbc_getNumCols(model))) {
2059        delete[] model->lastOptMIPSol;
2060        model->lastOptMIPSol = NULL;
2061      }
2062      if (!model->lastOptMIPSol)
2063        model->lastOptMIPSol = new double[Cbc_getNumCols(model)];
2064
2065      memcpy(model->lastOptMIPSol, cbcModel->bestSolution(), sizeof(double)*Cbc_getNumCols(model) );
2066      model->lastOptNCols = Cbc_getNumCols(model);
2067
2068      model->obj_value = cbcModel->getObjValue();
2069
2070      if (cbcModel->getObjSense()==-1) {
2071        model->obj_value = 0.0;
2072
2073        for (int j=0 ; j<solver->getNumCols() ; ++j )
2074          model->obj_value += cbcModel->bestSolution()[j] * solver->getObjCoefficients()[j];
2075      } // circunvent CBC bug
2076    }
2077
2078    free(charCbcOpts);
2079    delete linearProgram;
2080
2081    if (cbc_eh)
2082      delete cbc_eh;
2083
2084    if (cbcmh)
2085      delete cbcmh;
2086  } catch (CoinError &e) {
2087    fprintf( stderr, "%s ERROR: %s::%s, %s\n", "Cbc_solve",
2088      e.className().c_str(), e.methodName().c_str(), e.message().c_str());
2089    abort();
2090  }
2091 
2092  return cbcModel->status();
2093}
2094
2095void CBC_LINKAGE Cbc_addIncCallback(
2096    Cbc_Model *model, cbc_incumbent_callback inccb,
2097    void *appData )
2098{
2099  model->inc_callback = inccb;
2100  model->icAppData = appData;
2101}
2102
2103void CBC_LINKAGE Cbc_addProgrCallback(
2104  Cbc_Model *model, cbc_progress_callback prgcbc,
2105  void *appData)
2106{
2107  model->progr_callback = prgcbc;
2108  model->pgrAppData = appData;
2109}
2110
2111void CBC_LINKAGE Cbc_addCutCallback( 
2112    Cbc_Model *model, 
2113    cbc_cut_callback cutcb, 
2114    const char *name, 
2115    void *appData, 
2116    int howOften,
2117    char atSolution )
2118{
2119  model->cut_callback = cutcb;
2120  model->cutCBName = string(name);
2121  model->cutCBData = appData;
2122  model->cutCBhowOften = howOften;
2123  model->cutCBAtSol = atSolution;
2124}
2125
2126int CBC_LINKAGE
2127Cbc_getNumCols(Cbc_Model *model)
2128{
2129  return model->solver_->getNumCols() + model->nCols;
2130}
2131
2132int CBC_LINKAGE
2133Cbc_getNumRows(Cbc_Model *model)
2134{
2135  return model->solver_->getNumRows() + model->nRows;
2136}
2137
2138
2139int CBC_LINKAGE
2140Cbc_getIterationCount(Cbc_Model *model) {
2141  return model->cbcModel_->getIterationCount();
2142}
2143
2144/** Number of non-zero entries in a row */
2145int CBC_LINKAGE
2146Cbc_getRowNz(Cbc_Model *model, int row)
2147{
2148  VALIDATE_ROW_INDEX( row, model);
2149  Cbc_flush(model);
2150
2151  const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow();
2152  return cpmRow->getVectorLengths()[row];
2153}
2154
2155/** Indices of variables that appear on this row */
2156const int *CBC_LINKAGE
2157Cbc_getRowIndices(Cbc_Model *model, int row)
2158{
2159  VALIDATE_ROW_INDEX( row, model);
2160  Cbc_flush(model);
2161
2162  const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow();
2163  const CoinBigIndex *starts = cpmRow->getVectorStarts();
2164  const int *ridx = cpmRow->getIndices() + starts[row];
2165  return ridx;
2166}
2167
2168/** Coefficients of variables that appear on this row */
2169const double *CBC_LINKAGE
2170Cbc_getRowCoeffs(Cbc_Model *model, int row)
2171{
2172  VALIDATE_ROW_INDEX( row, model);
2173  Cbc_flush(model);
2174
2175  const CoinPackedMatrix *cpmRow = model->solver_->getMatrixByRow();
2176  const CoinBigIndex *starts = cpmRow->getVectorStarts();
2177  const double *rcoef = cpmRow->getElements() + starts[row];
2178  return rcoef;
2179}
2180
2181/** Number of non-zero entries in a column */
2182int CBC_LINKAGE
2183Cbc_getColNz(Cbc_Model *model, int col)
2184{
2185  VALIDATE_COL_INDEX( col, model );
2186  Cbc_flush(model);
2187
2188  const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol();
2189  return cpmCol->getVectorLengths()[col];
2190}
2191
2192/** Indices of rows that a column appears */
2193const int *CBC_LINKAGE
2194Cbc_getColIndices(Cbc_Model *model, int col)
2195{
2196  VALIDATE_COL_INDEX( col, model );
2197  Cbc_flush(model);
2198
2199  const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol();
2200  const CoinBigIndex *starts = cpmCol->getVectorStarts();
2201  const int *cidx = cpmCol->getIndices() + starts[col];
2202  return cidx;
2203}
2204
2205/** Coefficients that a column appear in rows */
2206const double *CBC_LINKAGE
2207Cbc_getColCoeffs(Cbc_Model *model, int col)
2208{
2209  VALIDATE_COL_INDEX( col, model );
2210  Cbc_flush(model);
2211
2212  const CoinPackedMatrix *cpmCol = model->solver_->getMatrixByCol();
2213  const CoinBigIndex *starts = cpmCol->getVectorStarts();
2214  const double *ccoef = cpmCol->getElements() + starts[col];
2215  return ccoef;
2216}
2217
2218/** Right hand side of a row */
2219double CBC_LINKAGE
2220Cbc_getRowRHS(Cbc_Model *model, int row)
2221{
2222  VALIDATE_ROW_INDEX( row, model );
2223
2224  if (row<model->solver_->getNumRows()) {
2225    return model->solver_->getRightHandSide()[row];
2226  } else {
2227    int idxRowBuffer = row - model->solver_->getNumRows();
2228    if (model->rUB[idxRowBuffer] < COIN_DBL_MAX) 
2229      return model->rUB[idxRowBuffer];
2230    else 
2231      return model->rLB[idxRowBuffer];
2232  }
2233}
2234
2235/** Sense a row */
2236char CBC_LINKAGE
2237Cbc_getRowSense(Cbc_Model *model, int row)
2238{
2239  VALIDATE_ROW_INDEX( row, model );
2240
2241  if (row<model->solver_->getNumRows()) {
2242    return model->solver_->getRowSense()[row];
2243  } else {
2244    int idxRowBuffer = row - model->solver_->getNumRows();
2245    if (fabs(model->rLB[idxRowBuffer]-model->rUB[idxRowBuffer]) <= 1e-15)
2246      return 'E';
2247    if (model->rUB[idxRowBuffer] == COIN_DBL_MAX) 
2248      return 'G';
2249    if (model->rLB[idxRowBuffer] == -COIN_DBL_MAX) 
2250      return 'L';
2251
2252    return 'R';
2253  }
2254}
2255
2256/** Are there a numerical difficulties? */
2257int CBC_LINKAGE
2258Cbc_isAbandoned(Cbc_Model *model)
2259{
2260  switch (model->lastOptimization) {
2261    case ModelNotOptimized:
2262      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2263      abort();
2264      break;
2265    case ContinuousOptimization:
2266      return model->solver_->isAbandoned();
2267      break;
2268    case IntegerOptimization:
2269      return model->cbcModel_->isAbandoned();
2270  }
2271
2272  return false;
2273}
2274
2275/** Is optimality proven? */
2276int CBC_LINKAGE
2277Cbc_isProvenOptimal(Cbc_Model *model)
2278{
2279  switch (model->lastOptimization) {
2280    case ModelNotOptimized:
2281      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2282      abort();
2283      break;
2284    case ContinuousOptimization:
2285      return model->solver_->isProvenOptimal();
2286    case IntegerOptimization:
2287      return model->cbcModel_->isProvenOptimal();
2288  }
2289
2290  return false;
2291}
2292
2293int CBC_LINKAGE
2294Cbc_isProvenInfeasible(Cbc_Model *model)
2295{
2296  switch (model->lastOptimization) {
2297    case ModelNotOptimized:
2298      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2299      abort();
2300      break;
2301    case ContinuousOptimization:
2302      return model->solver_->isProvenPrimalInfeasible();
2303    case IntegerOptimization:
2304      if (model->cbcModel_->status() == -1)
2305        return model->solver_->isProvenPrimalInfeasible();
2306      return model->cbcModel_->isProvenInfeasible();
2307  }
2308
2309  return false;
2310}
2311
2312double CBC_LINKAGE
2313Cbc_getObjValue(Cbc_Model *model)
2314{
2315  return model->obj_value;
2316}
2317
2318const double *CBC_LINKAGE
2319Cbc_getReducedCost(Cbc_Model *model)
2320{
2321  switch (model->lastOptimization) {
2322    case ModelNotOptimized:
2323      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2324      abort();
2325      break;
2326    case ContinuousOptimization:
2327      return model->solver_->getReducedCost();
2328    case IntegerOptimization:
2329      fprintf( stderr, "Information only available when optimizing continuous models.\n");
2330      abort();
2331      break;
2332  }
2333
2334  return NULL;
2335}
2336
2337const double *CBC_LINKAGE
2338Cbc_getRowPrice(Cbc_Model *model)
2339{
2340  switch (model->lastOptimization) {
2341    case ModelNotOptimized:
2342      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2343      abort();
2344      break;
2345    case ContinuousOptimization:
2346      return model->solver_->getRowPrice();
2347    case IntegerOptimization:
2348      fprintf( stderr, "Information only available when optimizing continuous models.\n");
2349      abort();
2350      break;
2351  }
2352
2353  return NULL;
2354}
2355
2356int CBC_LINKAGE
2357Cbc_numberSavedSolutions(Cbc_Model *model)
2358{
2359  switch (model->lastOptimization) {
2360    case ModelNotOptimized:
2361      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2362      abort();
2363      break;
2364    case ContinuousOptimization:
2365      if (model->solver_->isProvenOptimal())
2366        return 1;
2367      else
2368        return 0;
2369    case IntegerOptimization:
2370      return model->cbcModel_->numberSavedSolutions();
2371  }
2372
2373  return 0;
2374}
2375
2376const double *CBC_LINKAGE
2377Cbc_savedSolution(Cbc_Model *model, int whichSol)
2378{
2379  switch (model->lastOptimization) {
2380    case ModelNotOptimized:
2381      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2382      abort();
2383      break;
2384    case ContinuousOptimization:
2385      fprintf( stderr, "Information only available when optimizing integer models.\n");
2386      abort();
2387      break;
2388    case IntegerOptimization:
2389      return model->cbcModel_->savedSolution(whichSol);
2390  }
2391
2392  return NULL;
2393}
2394
2395double CBC_LINKAGE
2396Cbc_savedSolutionObj(Cbc_Model *model, int whichSol)
2397{
2398  switch (model->lastOptimization) {
2399    case ModelNotOptimized:
2400      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2401      abort();
2402      break;
2403    case ContinuousOptimization:
2404      fprintf( stderr, "Information only available when optimizing integer models.\n");
2405      abort();
2406      break;
2407    case IntegerOptimization:
2408      return model->cbcModel_->savedSolutionObjective(whichSol);
2409  }
2410
2411  return COIN_DBL_MAX;
2412}
2413
2414const double *CBC_LINKAGE
2415Cbc_getColSolution(Cbc_Model *model)
2416{
2417  switch (model->lastOptimization) {
2418    case ModelNotOptimized:
2419      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2420      abort();
2421      break;
2422    case ContinuousOptimization:
2423      return model->solver_->getColSolution();
2424    case IntegerOptimization:
2425      return model->cbcModel_->bestSolution();
2426  }
2427
2428  return NULL;
2429}
2430
2431/** @brief Upper bound of ranged constraint
2432  *
2433  * @param model problem object
2434  * @param row row index
2435  * @return row upper bound
2436  **/
2437double 
2438Cbc_getRowUB(Cbc_Model *model, int row) {
2439  if (row<model->solver_->getNumRows()) {
2440    return model->solver_->getRowUpper()[row];
2441  } else {
2442    int nridx = row - model->solver_->getNumRows();
2443    return model->rUB[nridx];
2444  }
2445}
2446
2447/** @brief Lower bound of ranged constraint
2448  *
2449  * @param model problem object
2450  * @param row row index
2451  * @return row lower bound
2452  **/
2453CBCSOLVERLIB_EXPORT double CBC_LINKAGE
2454Cbc_getRowLB(Cbc_Model *model, int row) {
2455  if (row<model->solver_->getNumRows()) {
2456    return model->solver_->getRowLower()[row];
2457  } else {
2458    int nridx = row - model->solver_->getNumRows();
2459    return model->rLB[nridx];
2460  }
2461}
2462
2463char Cbc_checkFeasibility(Cbc_Model *model, const double x[],
2464    double *maxViolRow, int *rowIdx, 
2465    double *maxViolCol, int *colIdx) {
2466  *maxViolRow = *maxViolCol = -1.0;
2467  *rowIdx = *colIdx = -1;
2468  const double primalTol = model->dbl_param[DBL_PARAM_PRIMAL_TOL];
2469  const double intTol = model->dbl_param[DBL_PARAM_INT_TOL];
2470
2471  char feasible = 1;
2472  int nRows = Cbc_getNumRows(model);
2473  for ( int i=0 ; (i<nRows) ; ++i ) {
2474    int nzRow = Cbc_getRowNz(model, i);
2475    const int *cidx = Cbc_getRowIndices(model, i);
2476    const double *coef = Cbc_getRowCoeffs(model, i);
2477
2478    double lhs = 0.0;
2479    for ( int j=0 ; (j<nzRow) ; ++j ) {
2480      int ic = cidx[j];
2481      lhs += x[ic] * coef[j];
2482    }
2483
2484    double rowUB = Cbc_getRowUB(model, i);
2485    double rowLB = Cbc_getRowLB(model, i);
2486
2487    double viol = 0.0;
2488   
2489    if (lhs>rowUB) {
2490      viol = lhs-rowUB;
2491    } else {
2492      if (lhs<rowLB) {
2493        viol = rowLB-lhs;
2494      }
2495    }
2496
2497    if (viol>(*maxViolRow)) {
2498      if (viol>primalTol)
2499        feasible = 0;
2500      *maxViolRow = viol;
2501      *rowIdx = i;
2502    }
2503  } // all rows
2504 
2505  int nCols = Cbc_getNumCols(model);
2506  for ( int j=0 ; (j<nCols) ; ++j ) {
2507    const double clb = Cbc_getColLB(model, j);   
2508    const double cub = Cbc_getColUB(model, j);
2509 
2510    double viol = 0.0;
2511    if (x[j]>cub) {
2512      viol = x[j] - cub;
2513    } else {
2514      if (x[j]<clb) {
2515        viol = clb-x[j];
2516      }
2517    }
2518    if (viol>primalTol)
2519      feasible = 0;
2520
2521    if (Cbc_isInteger(model, j)) {
2522      double vint = floor(x[j] + 0.5);
2523      double intviol = fabs(x[j]-vint);
2524      if (intviol > intTol)
2525        feasible = 0;
2526      viol = std::max(viol, intTol);
2527    }
2528
2529    if ( viol > *maxViolCol ) {
2530      *maxViolCol = viol;
2531      *colIdx = j;
2532    }
2533  } // all columns
2534
2535  return feasible;
2536}
2537
2538int CBC_LINKAGE
2539Cbc_isContinuousUnbounded(Cbc_Model *model) {
2540  switch (model->lastOptimization) {
2541    case ModelNotOptimized:
2542      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2543      abort();
2544      break;
2545    case ContinuousOptimization:
2546      return model->solver_->isProvenDualInfeasible();
2547    case IntegerOptimization:
2548      if (model->cbcModel_->status() == -1)
2549        return model->solver_->isProvenDualInfeasible();
2550
2551      return model->cbcModel_->isContinuousUnbounded();
2552  }
2553
2554  return false;
2555}
2556
2557
2558int CBC_LINKAGE
2559Cbc_isNodeLimitReached(Cbc_Model *model) {
2560  switch (model->lastOptimization) {
2561    case ModelNotOptimized:
2562      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2563      abort();
2564      break;
2565    case ContinuousOptimization:
2566      fprintf( stderr, "Information not available when optimizing continuous models.\n");
2567      abort();
2568      break;
2569    case IntegerOptimization:
2570      return model->cbcModel_->isNodeLimitReached();
2571  }
2572
2573  return false;
2574}
2575
2576
2577int CBC_LINKAGE
2578Cbc_isSecondsLimitReached(Cbc_Model *model) {
2579  switch (model->lastOptimization) {
2580    case ModelNotOptimized:
2581      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2582      abort();
2583      break;
2584    case ContinuousOptimization:
2585      fprintf( stderr, "Information only available when optimizing integer models.\n");
2586      abort();
2587      break;
2588    case IntegerOptimization:
2589      return model->cbcModel_->isSecondsLimitReached();
2590  }
2591
2592  return false;
2593
2594}
2595
2596int CBC_LINKAGE
2597Cbc_isSolutionLimitReached(Cbc_Model *model) {
2598  switch (model->lastOptimization) {
2599    case ModelNotOptimized:
2600      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2601      abort();
2602      break;
2603    case ContinuousOptimization:
2604      fprintf( stderr, "Information only available when optimizing integer models.\n");
2605      abort();
2606      break;
2607    case IntegerOptimization:
2608      return model->cbcModel_->isSolutionLimitReached();
2609  }
2610
2611  return false;
2612}
2613
2614
2615
2616
2617int CBC_LINKAGE
2618Cbc_isInitialSolveAbandoned(Cbc_Model *model) {
2619  switch (model->lastOptimization) {
2620    case ModelNotOptimized:
2621      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2622      abort();
2623      break;
2624    case ContinuousOptimization:
2625      fprintf( stderr, "Information only available when optimizing integer models.\n");
2626      abort();
2627      break;
2628    case IntegerOptimization:
2629      return model->cbcModel_->isInitialSolveAbandoned();
2630  }
2631
2632  return false;
2633}
2634
2635int CBC_LINKAGE
2636Cbc_isInitialSolveProvenOptimal(Cbc_Model *model) {
2637  switch (model->lastOptimization) {
2638    case ModelNotOptimized:
2639      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2640      abort();
2641      break;
2642    case ContinuousOptimization:
2643      fprintf( stderr, "Information only available when optimizing integer models.\n");
2644      abort();
2645      break;
2646    case IntegerOptimization:
2647      return model->cbcModel_->isInitialSolveProvenOptimal();
2648  }
2649
2650  return false;
2651}
2652
2653
2654int CBC_LINKAGE
2655Cbc_isInitialSolveProvenPrimalInfeasible(Cbc_Model *model) {
2656  switch (model->lastOptimization) {
2657    case ModelNotOptimized:
2658      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2659      abort();
2660      break;
2661    case ContinuousOptimization:
2662      fprintf( stderr, "Information only available when optimizing integer models.\n");
2663      abort();
2664      break;
2665    case IntegerOptimization:
2666      return model->cbcModel_->isInitialSolveProvenPrimalInfeasible();
2667  }
2668
2669  return false;
2670
2671}
2672
2673double CBC_LINKAGE
2674Cbc_getObjSense(Cbc_Model *model) {
2675  return model->solver_->getObjSense();
2676}
2677
2678void CBC_LINKAGE
2679Cbc_setObjSense(Cbc_Model *model, double sense)
2680{
2681  Cbc_flush(model);
2682  model->solver_->setObjSense(sense);
2683}
2684
2685void CBC_LINKAGE
2686Cbc_setRowLower(Cbc_Model *model, int index, double value)
2687{
2688  Cbc_flush(model);
2689  VALIDATE_ROW_INDEX(index, model);
2690
2691  OsiSolverInterface *solver = model->solver_;
2692  solver->setRowLower(index, value);
2693}
2694
2695void CBC_LINKAGE
2696Cbc_setRowUpper(Cbc_Model *model, int index, double value)
2697{
2698  Cbc_flush(model);
2699  VALIDATE_ROW_INDEX(index, model);
2700  OsiSolverInterface *solver = model->solver_;
2701  solver->setRowUpper(index, value);
2702}
2703
2704void CBC_LINKAGE
2705Cbc_setRowRHS(Cbc_Model *model, int row, double rhs)
2706{
2707  VALIDATE_ROW_INDEX(row, model);
2708
2709  Cbc_flush(model);
2710  char sense = Cbc_getRowSense(model, row);
2711  switch (sense)
2712  {
2713    case 'L':
2714      Cbc_setRowUpper(model, row, rhs);
2715      break;
2716    case 'G':
2717      Cbc_setRowLower(model, row, rhs);
2718      break;
2719    case 'E':
2720      Cbc_setRowLower(model, row, rhs);
2721      Cbc_setRowUpper(model, row, rhs);
2722      break;
2723    default:
2724      fprintf(stderr, "Could not change RHS in row %d to %g in row with sense: %c\n",
2725          row, rhs, sense);
2726      exit(1);
2727  }
2728}
2729
2730
2731
2732/** @brief Constraint lower bounds
2733  *
2734  * @param model problem object
2735  * @return vector with lower bounds of constraints
2736  **/
2737const double *CBC_LINKAGE
2738Cbc_getRowLower(Cbc_Model *model)
2739{
2740  Cbc_flush(model);
2741  OsiSolverInterface *solver = model->solver_;
2742  return solver->getRowLower();
2743}
2744
2745/** @brief Constraint upper bounds
2746  *
2747  * @param model problem object
2748  * @return constraint upper bounds
2749  **/
2750const double *CBC_LINKAGE
2751Cbc_getRowUpper(Cbc_Model *model)
2752{
2753  Cbc_flush(model);
2754  OsiSolverInterface *solver = model->solver_;
2755  return solver->getRowUpper();
2756}
2757
2758
2759const double *CBC_LINKAGE
2760Cbc_getRowActivity(Cbc_Model *model) {
2761  switch (model->lastOptimization) {
2762    case ModelNotOptimized:
2763      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2764      abort();
2765      break;
2766    case ContinuousOptimization:
2767      return model->solver_->getRowActivity();
2768    case IntegerOptimization:
2769      return model->cbcModel_->getRowActivity();
2770  }
2771
2772  return NULL;
2773
2774}
2775
2776
2777CBCSOLVERLIB_EXPORT const double *CBC_LINKAGE
2778Cbc_getRowSlack(Cbc_Model *model) {
2779  if (model->lastOptimization==ModelNotOptimized) {
2780      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2781      abort();
2782  }
2783
2784  return model->slack_;
2785}
2786
2787const double *CBC_LINKAGE
2788Cbc_getColLower(Cbc_Model *model)
2789{
2790  Cbc_flush(model);
2791  return model->solver_->getColLower();
2792}
2793
2794const double *CBC_LINKAGE
2795Cbc_getColUpper(Cbc_Model *model)
2796{
2797  Cbc_flush(model);
2798  return model->solver_->getColUpper();
2799}
2800
2801double Cbc_getColObj(Cbc_Model *model, int colIdx) {
2802  VALIDATE_COL_INDEX(colIdx, model);
2803
2804  if (colIdx < model->solver_->getNumCols()) {
2805    return model->solver_->getObjCoefficients()[colIdx];
2806  } else {
2807    int ncIdx = colIdx - model->solver_->getNumCols();
2808    return model->cObj[ncIdx];
2809  }
2810}
2811
2812double Cbc_getColLB(Cbc_Model *model, int colIdx) {
2813  VALIDATE_COL_INDEX(colIdx, model);
2814
2815  if (colIdx < model->solver_->getNumCols()) {
2816    return model->solver_->getColLower()[colIdx];
2817  } else {
2818    int ncIdx = colIdx - model->solver_->getNumCols();
2819    return model->cLB[ncIdx];
2820  }
2821}
2822
2823double Cbc_getColUB(Cbc_Model *model, int colIdx) {
2824  VALIDATE_COL_INDEX(colIdx, model);
2825
2826  if (colIdx < model->solver_->getNumCols()) {
2827    return model->solver_->getColUpper()[colIdx];
2828  } else {
2829    int ncIdx = colIdx - model->solver_->getNumCols();
2830    return model->cUB[ncIdx];
2831  }
2832}
2833
2834double CBC_LINKAGE
2835Cbc_getBestPossibleObjValue(Cbc_Model *model) {
2836  switch (model->lastOptimization) {
2837    case ModelNotOptimized:
2838      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2839      abort();
2840      break;
2841    case ContinuousOptimization:
2842      return model->solver_->getObjValue();
2843    case IntegerOptimization:
2844      return model->cbcModel_->getBestPossibleObjValue();
2845  }
2846
2847  return COIN_DBL_MIN;
2848}
2849
2850const double *CBC_LINKAGE
2851Cbc_getObjCoefficients(Cbc_Model *model)
2852{
2853  Cbc_flush(model);
2854  return model->solver_->getObjCoefficients();
2855}
2856
2857void CBC_LINKAGE
2858Cbc_setObjCoeff(Cbc_Model *model, int index, double value)
2859{
2860  Cbc_flush( model);
2861  VALIDATE_COL_INDEX(index, model);
2862
2863  model->solver_->setObjCoeff( index, value );
2864}
2865
2866void CBC_LINKAGE
2867Cbc_setColLower(Cbc_Model *model, int index, double value)
2868{
2869  Cbc_flush(model);
2870  VALIDATE_COL_INDEX(index, model);
2871  model->solver_->setColLower( index, value );
2872}
2873
2874void CBC_LINKAGE
2875Cbc_setColUpper(Cbc_Model *model, int index, double value)
2876{
2877  Cbc_flush(model);
2878  VALIDATE_COL_INDEX(index, model);
2879  model->solver_->setColUpper( index, value );
2880}
2881
2882
2883const double *CBC_LINKAGE
2884Cbc_bestSolution(Cbc_Model *model)
2885{
2886  switch (model->lastOptimization) {
2887    case ModelNotOptimized:
2888      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2889      abort();
2890      break;
2891    case ContinuousOptimization:
2892      return model->solver_->getColSolution();
2893    case IntegerOptimization:
2894      return model->cbcModel_->bestSolution();
2895  }
2896
2897  return NULL;
2898}
2899
2900
2901int CBC_LINKAGE
2902Cbc_isInteger(Cbc_Model *model, int i)
2903{
2904  Cbc_flush(model);
2905  VALIDATE_COL_INDEX( i, model );
2906  return model->solver_->isInteger(i);
2907}
2908
2909
2910int CBC_LINKAGE
2911Cbc_getNodeCount(Cbc_Model *model) {
2912  switch (model->lastOptimization) {
2913    case ModelNotOptimized:
2914      fprintf( stderr, "Information not available, model was not optimized yet.\n");
2915      abort();
2916      break;
2917    case ContinuousOptimization:
2918      fprintf( stderr, "Information only available when optimizing integer models.\n");
2919      abort();
2920      break;
2921    case IntegerOptimization:
2922      return model->cbcModel_->getNodeCount();
2923  }
2924
2925  return false;
2926
2927}
2928
2929
2930/** Return a copy of this model */
2931Cbc_Model *CBC_LINKAGE
2932Cbc_clone(Cbc_Model *model)
2933{
2934  Cbc_flush(model);
2935  Cbc_Model *result = new Cbc_Model();
2936
2937  result->slack_ = NULL;
2938  result->solver_ = dynamic_cast<OsiClpSolverInterface *>(model->solver_->clone());
2939
2940  if (model->cbcModel_)
2941    result->cbcModel_ = model->cbcModel_->clone(true);
2942  else
2943    result->cbcModel_ = NULL;
2944
2945  result->relax_ = model->relax_;
2946
2947  result->inc_callback = model->inc_callback;
2948  result->progr_callback = model->progr_callback;
2949  result->userCallBack = model->userCallBack;
2950
2951  result->cut_callback = model->cut_callback;
2952  result->cutCBData = model->cutCBData;
2953  result->cutCBhowOften = model->cutCBhowOften;
2954  result->cutCBAtSol = model->cutCBAtSol;
2955
2956  result->obj_value = model->obj_value;
2957
2958
2959  result->lastOptimization = model->lastOptimization;
2960  result->lastOptNCols = model->lastOptNCols;
2961  if (model->lastOptMIPSol) {
2962    result->lastOptMIPSol = new double[model->lastOptNCols];
2963    memcpy(result->lastOptMIPSol, model->lastOptMIPSol, sizeof(double)*model->lastOptNCols );
2964  }
2965
2966  if (model->slack_) {
2967    result->slack_ = (double *) xmalloc( sizeof(double)*model->lastOptNRows );
2968    memcpy(result->slack_, model->slack_, sizeof(double)*model->lastOptNRows);
2969  }
2970
2971  result->icAppData = model->icAppData;
2972  result->pgrAppData = model->pgrAppData;
2973  result->colNameIndex = NULL;
2974  result->rowNameIndex = NULL;
2975  if (model->colNameIndex)
2976    Cbc_storeNameIndexes(result, 1);
2977
2978  Cbc_iniBuffer(result);
2979
2980  if (model->iniSol) {
2981    result->iniSol = new vector<double>( model->iniSol->begin(), model->iniSol->end() );
2982    result->iniObj = model->iniObj;
2983  }
2984  else
2985  {
2986    result->iniSol = NULL;
2987    result->iniObj = COIN_DBL_MAX;
2988  }
2989
2990  if (model->nColsMS) {
2991    result->nColsMS = model->nColsMS;
2992    result->colNamesMS = (char **) xmalloc( sizeof(char *)*model->nColsMS );
2993    result->charSpaceMS = model->charSpaceMS;
2994    result->colNamesMS[0] = (char *) xmalloc( result->charSpaceMS );
2995    memcpy( result->colNamesMS[0], model->colNamesMS[0], model->charSpaceMS );
2996    for ( int i=1 ; (i<model->nColsMS) ; ++i )
2997      result->colNamesMS[i] = result->colNamesMS[i-1] + strlen(result->colNamesMS[i-1]);
2998  }
2999  else
3000  {
3001    result->nColsMS = 0;
3002    result->colNamesMS = NULL;
3003    result->colValuesMS = NULL;
3004    result->charSpaceMS = 0;
3005  }
3006
3007  if ( model->nSos ) {
3008    result->nSos = model->nSos;
3009    result->sosSize = model->sosSize;
3010    result->sosElSize = model->sosElSize;
3011
3012    result->sosCap = result->nSos;
3013    result->sosElCap = model->sosElCap;
3014
3015    result->sosRowStart = (int*) xmalloc( sizeof(int)*(result->sosCap+1) );
3016    result->sosEl = (int*) xmalloc( sizeof(int)*(result->sosElCap) );
3017    result->sosElWeight = (double*) xmalloc( sizeof(double)*(result->sosElCap) );
3018
3019    memcpy( result->sosRowStart, model->sosRowStart, sizeof(int)*(result->nSos+1) );
3020    memcpy( result->sosEl, model->sosEl, sizeof(int)*(result->sosElSize) );
3021    memcpy( result->sosElWeight, model->sosElWeight, sizeof(double)*(result->sosElSize) );
3022  }
3023
3024#ifdef CBC_THREAD
3025  pthread_mutex_init(&(result->cbcMutexCG), NULL);
3026  pthread_mutex_init(&(result->cbcMutexEvent), NULL);
3027#endif
3028
3029  // copying parameters
3030  result->lp_method = model->lp_method;
3031  result->dualp = model->dualp;
3032
3033  memcpy(result->int_param, model->int_param, sizeof(result->int_param));
3034  memcpy(result->dbl_param, model->dbl_param, sizeof(result->dbl_param));
3035
3036  return result;
3037}
3038
3039/** Set this the variable to be continuous */
3040void CBC_LINKAGE
3041Cbc_setContinuous(Cbc_Model *model, int iColumn)
3042{
3043  Cbc_flush(model);
3044  VALIDATE_COL_INDEX( iColumn, model );
3045
3046  model->solver_->setContinuous(iColumn);
3047}
3048
3049/** Set this the variable to be integer */
3050void CBC_LINKAGE
3051Cbc_setInteger(Cbc_Model *model, int iColumn)
3052{
3053  Cbc_flush(model);
3054  VALIDATE_COL_INDEX( iColumn, model );
3055
3056  model->solver_->setInteger(iColumn);
3057}
3058
3059/** Adds a new column */
3060void CBC_LINKAGE
3061Cbc_addCol(Cbc_Model *model, const char *name, double lb,
3062  double ub, double obj, char isInteger,
3063  int nz, int *rows, double *coefs)
3064{
3065  OsiSolverInterface *solver = model->solver_;
3066
3067  if (nz >= 1 && model->rStart && model->rStart[model->nRows] >= 1) {
3068    // new columns have reference to rows which have references to columns, flushing
3069    Cbc_flush(model);
3070  }
3071
3072  Cbc_addColBuffer( model, name, nz, rows, coefs,  lb, ub, obj,  isInteger );
3073
3074  if (model->colNameIndex)
3075  {
3076    NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
3077    colNameIndex[std::string(name)] = Cbc_getNumCols(model)-1;
3078  }
3079}
3080
3081/** Adds a new row */
3082void CBC_LINKAGE
3083Cbc_addRow(Cbc_Model *model, const char *name, int nz,
3084  const int *cols, const double *coefs, char sense, double rhs)
3085{
3086  if (nz >= 1 && model->cStart && model->cStart[model->nCols] >= 1) {
3087    // new rows have reference to columns which have references to rows, flushing
3088    Cbc_flush(model);
3089  }
3090
3091  double rowLB = -DBL_MAX, rowUB = DBL_MAX;
3092  switch (toupper(sense)) {
3093  case '=':
3094    rowLB = rowUB = rhs;
3095    break;
3096  case 'E':
3097    rowLB = rowUB = rhs;
3098    break;
3099  case '<':
3100    rowUB = rhs;
3101    break;
3102  case 'L':
3103    rowUB = rhs;
3104    break;
3105  case '>':
3106    rowLB = rhs;
3107    break;
3108  case 'G':
3109    rowLB = rhs;
3110    break;
3111  default:
3112    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3113    abort();
3114  }
3115
3116  Cbc_addRowBuffer(model, nz, cols, coefs, rowLB, rowUB, name);
3117
3118  if (model->rowNameIndex)
3119  {
3120    NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
3121    rowNameIndex[std::string(name)] = Cbc_getNumRows(model)-1;
3122  }
3123}
3124
3125
3126void CBC_LINKAGE
3127Cbc_addLazyConstraint(Cbc_Model *model, int nz,
3128  int *cols, double *coefs, char sense, double rhs)
3129{
3130  if (model->lazyConstrs==NULL)
3131    model->lazyConstrs = new CglStored();
3132
3133  OsiRowCut orc;
3134  orc.setRow( nz, cols, coefs );
3135
3136  orc.setLb(-DBL_MAX);
3137  orc.setUb(DBL_MAX);
3138
3139  switch (toupper(sense)) {
3140  case '=':
3141    orc.setLb(rhs);
3142    orc.setUb(rhs);
3143    break;
3144  case 'E':
3145    orc.setLb(rhs);
3146    orc.setUb(rhs);
3147    break;
3148  case '<':
3149    orc.setUb(rhs);
3150    break;
3151  case 'L':
3152    orc.setUb(rhs);
3153    break;
3154  case '>':
3155    orc.setLb(rhs);
3156    break;
3157  case 'G':
3158    orc.setLb(rhs);
3159    break;
3160  default:
3161    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3162    abort();
3163  }
3164
3165  model->lazyConstrs->addCut(orc);
3166}
3167
3168void CBC_LINKAGE
3169Cbc_readMIPStart(Cbc_Model *model, const char fileName[]) {
3170  std::vector< std::pair< std::string, double > > colValues;
3171  double obj;
3172  CoinMessages generalMessages = model->solver_->getModelPtr()->messages();
3173  CoinMessageHandler *messHandler = model->solver_->messageHandler();
3174  CbcMipStartIO::read(model->solver_, fileName, colValues, obj, messHandler, &generalMessages);
3175 
3176  char **cnames = new char*[colValues.size()];
3177  size_t charSpace = 0;
3178  for ( int i=0 ; (i<(int)colValues.size()) ; ++i )
3179    charSpace += colValues[i].first.size() + 1;
3180  cnames[0] = new char[charSpace];
3181  for ( int i=1 ; (i<(int)colValues.size()) ; ++i )
3182    cnames[i] = cnames[i-1] + colValues[i-1].first.size() + 1;
3183
3184  double *cval = new double[colValues.size()];
3185  for ( int i=0 ; (i<(int)colValues.size()) ; ++i ) {
3186    cval[i] = colValues[i].second;
3187    strcpy(cnames[i], colValues[i].first.c_str());
3188  }
3189
3190  Cbc_setMIPStart(model, colValues.size(), (const char **) cnames, cval);
3191  delete[] cnames[0];
3192  delete[] cnames;
3193  delete[] cval;
3194}
3195
3196void CBC_LINKAGE
3197Osi_addRow(void *osi, const char *name, int nz,
3198  const int *cols, const double *coefs, char sense, double rhs)
3199{
3200  OsiSolverInterface *solver = (OsiSolverInterface *) osi;
3201  double rowLB = -DBL_MAX, rowUB = DBL_MAX;
3202  switch (toupper(sense)) {
3203  case '=':
3204    rowLB = rowUB = rhs;
3205    break;
3206  case 'E':
3207    rowLB = rowUB = rhs;
3208    break;
3209  case '<':
3210    rowUB = rhs;
3211    break;
3212  case 'L':
3213    rowUB = rhs;
3214    break;
3215  case '>':
3216    rowLB = rhs;
3217    break;
3218  case 'G':
3219    rowLB = rhs;
3220    break;
3221  default:
3222    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3223    abort();
3224  }
3225
3226  solver->addRow(nz, cols, coefs, rowLB, rowUB);
3227  solver->setRowName(solver->getNumRows()-1, std::string(name));
3228}
3229
3230void CBC_LINKAGE
3231Osi_setObjSense(void *osi, double sense)
3232{
3233  OsiSolverInterface *solver = (OsiSolverInterface *) osi;
3234  solver->setObjSense(sense);
3235}
3236
3237void CBC_LINKAGE
3238Cbc_deleteRows(Cbc_Model *model, int numRows, const int rows[])
3239{
3240  Cbc_flush(model);
3241  OsiSolverInterface *solver = model->solver_;
3242
3243  if (model->rowNameIndex)
3244  {
3245    NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
3246    for ( int i=0 ; i<numRows; ++i )
3247      rowNameIndex.erase(solver->getRowName(rows[i]));
3248  }
3249
3250  solver->deleteRows(numRows, rows);
3251}
3252
3253void CBC_LINKAGE
3254Cbc_deleteCols(Cbc_Model *model, int numCols, const int cols[])
3255{
3256  Cbc_flush(model);
3257  OsiSolverInterface *solver = model->solver_;
3258
3259  if (model->colNameIndex)
3260  {
3261    NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
3262    for ( int i=0 ; i<numCols; ++i )
3263      colNameIndex.erase(solver->getColName(cols[i]));
3264  }
3265
3266  solver->deleteCols(numCols, cols);
3267}
3268
3269/** Add SOS constraints to the model using row-order matrix */
3270void CBC_LINKAGE
3271Cbc_addSOS(Cbc_Model *model, int numRows, const int *rowStarts,
3272  const int *colIndices, const double *weights, const int type)
3273{
3274  int newEl = rowStarts[numRows] - rowStarts[0];
3275
3276  if (numRows + model->nSos > model->sosCap) {
3277    int prevCap = model->sosCap;
3278    if (prevCap) {
3279      model->sosCap = std::max( 2*model->sosCap, numRows + model->nSos);
3280      model->sosRowStart = (int *) xrealloc(model->sosRowStart, sizeof(int)*(model->sosCap+1) );
3281      model->sosType = (int *) xrealloc(model->sosRowStart, sizeof(int)*(model->sosCap) );
3282    } else {
3283      model->sosCap = max(1024, numRows);
3284      model->sosRowStart = (int *) xmalloc(sizeof(int)*(model->sosCap+1) );
3285      model->sosType = (int *) xmalloc(sizeof(int)*(model->sosCap) );
3286      model->sosRowStart[0] = 0;
3287      model->sosElCap = std::max(8192, newEl);
3288      model->sosEl = (int *) xmalloc( sizeof(int)*model->sosElCap );
3289      model->sosElWeight = (double *) xmalloc( sizeof(double)*model->sosElCap );
3290      model->sosElSize = 0;
3291      model->nSos = 0;
3292    }
3293  }
3294
3295  for ( int i=0 ; i<numRows ; ++i )
3296    model->sosType[model->nSos+i] = type;
3297
3298  if ( model->sosElSize + newEl > model->sosElCap ) {
3299    model->sosElCap = max( 2*model->sosElCap, newEl );
3300    model->sosEl = (int *) xrealloc( model->sosEl, sizeof(int)*model->sosElCap );
3301    model->sosElWeight  = (double *) xrealloc( model->sosElWeight, sizeof(double)*model->sosElCap );
3302  }
3303
3304  memcpy( model->sosEl + model->sosElSize, colIndices, sizeof(int)*newEl );
3305  memcpy( model->sosElWeight + model->sosElSize, weights, sizeof(double)*newEl );
3306
3307  for ( int i=0 ; (i<numRows) ; ++i ) {
3308    int size = rowStarts[i+1] - rowStarts[i];
3309    model->sosRowStart[model->nSos+1] = model->sosRowStart[model->nSos] + size;
3310    model->nSos++;
3311  }
3312
3313  model->sosElSize += newEl;
3314}
3315
3316void CBC_LINKAGE
3317Cbc_setMIPStart(Cbc_Model *model, int count, const char **colNames, const double colValues[])
3318{
3319  if (model->nColsMS) {
3320    if (model->colNamesMS) {
3321      free( model->colNamesMS[0]);
3322      free( model->colNamesMS);
3323    }
3324    free( model->colValuesMS );
3325  }
3326
3327  int nameSpace = 0;
3328  for ( int i=0 ; (i<count) ; ++i )
3329    nameSpace += strlen(colNames[i]);
3330  nameSpace += count;
3331
3332  model->colValuesMS = (double *) xmalloc( sizeof(double)*count );
3333  model->colNamesMS = (char **) xmalloc( sizeof(char*)*count );
3334  model->charSpaceMS = sizeof(char)*nameSpace;
3335  model->colNamesMS[0] = (char *) xmalloc( model->charSpaceMS );
3336
3337
3338  for ( int i=1 ; (i<count) ; ++i )
3339    model->colNamesMS[i] = model->colNamesMS[i-1] + 1 + strlen(colNames[i-1]);
3340
3341  for ( int i=0 ; (i<count) ; ++i )
3342    strcpy( model->colNamesMS[i], colNames[i] );
3343
3344  memcpy(model->colValuesMS, colValues, sizeof(double)*count );
3345  model->nColsMS = count;
3346}
3347
3348void CBC_LINKAGE
3349Cbc_setMIPStartI(Cbc_Model *model, int count, const int colIdxs[], const double colValues[])
3350{
3351  OsiSolverInterface *solver = model->solver_;
3352
3353  if (model->nColsMS) {
3354    if (model->colNamesMS) {
3355      free( model->colNamesMS[0]);
3356      free( model->colNamesMS);
3357    }
3358    free( model->colValuesMS );
3359  }
3360
3361  int nameSpace = 0;
3362  for ( int i=0 ; (i<count) ; ++i )
3363    nameSpace += solver->getColName(colIdxs[i]).size();
3364  nameSpace += count;
3365
3366  model->colValuesMS = (double *) xmalloc( sizeof(double)*count );
3367  model->colNamesMS = (char **) xmalloc( sizeof(char*)*count );
3368  model->charSpaceMS = sizeof(char)*nameSpace;
3369  model->colNamesMS[0] = (char *) xmalloc( model->charSpaceMS );
3370
3371  for ( int i=1 ; (i<count) ; ++i )
3372    model->colNamesMS[i] = model->colNamesMS[i-1] + 1 + solver->getColName(colIdxs[i-1]).size();
3373
3374  for ( int i=0 ; (i<count) ; ++i ) {
3375    strcpy( model->colNamesMS[i], solver->getColName(colIdxs[i]).c_str() );
3376    model->colValuesMS[i] = colValues[i];
3377  }
3378
3379  memcpy(model->colValuesMS, colValues, sizeof(double)*count );
3380  model->nColsMS = count;
3381}
3382
3383
3384/** @brief Creates a new OsiClpSolverInterface and returns a pointer to an OsiSolverInterface object */
3385void * CBC_LINKAGE
3386Osi_newSolver()
3387{
3388  OsiClpSolverInterface *clp = new OsiClpSolverInterface();
3389
3390  return dynamic_cast<OsiSolverInterface *>(clp);
3391}
3392
3393void CBC_LINKAGE
3394Osi_setObjCoef(void *osi, int index, double obj)
3395{
3396  OsiSolverInterface *osis = (OsiSolverInterface *)osi;
3397  osis->setObjCoeff( index, obj );
3398}
3399
3400/** @brief Solves initial LP relaxation */
3401void CBC_LINKAGE
3402Osi_initialSolve(void *osi)
3403{
3404  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3405  osis->initialSolve();
3406}
3407
3408/** @brief Reoptimizes linear program  */
3409void CBC_LINKAGE
3410Osi_resolve(void *osi)
3411{
3412  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3413  osis->resolve();
3414}
3415
3416/** @brief Performs branch and bound */
3417void CBC_LINKAGE
3418Osi_branchAndBound(void *osi)
3419{
3420  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3421  osis->branchAndBound();
3422}
3423
3424// solution query methods
3425/** @brief Checks if optimization was abandoned */
3426char CBC_LINKAGE
3427Osi_isAbandoned(void *osi)
3428{
3429  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3430  return (char)osis->isAbandoned();
3431}
3432
3433/** @brief Checks if optimal solution was found */
3434char CBC_LINKAGE
3435Osi_isProvenOptimal(void *osi)
3436{
3437  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3438  return (char)osis->isProvenOptimal();
3439}
3440
3441/** @brief Checks if problem is primal infeasible */
3442char CBC_LINKAGE
3443Osi_isProvenPrimalInfeasible(void *osi)
3444{
3445  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3446  return (char)osis->isProvenPrimalInfeasible();
3447}
3448
3449/** @brief Checks if problem is dual infeasible */
3450char CBC_LINKAGE
3451Osi_isProvenDualInfeasible(void *osi)
3452{
3453  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3454  return (char)osis->isProvenDualInfeasible();
3455}
3456
3457/** @brief Checks if primal objective limit was reached */
3458char CBC_LINKAGE
3459Osi_isPrimalObjectiveLimitReached(void *osi)
3460{
3461  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3462  return (char)osis->isPrimalObjectiveLimitReached();
3463}
3464
3465/** @brief Checks if dual objective limit was reached */
3466char CBC_LINKAGE
3467Osi_isDualObjectiveLimitReached(void *osi)
3468{
3469  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3470  return (char)osis->isDualObjectiveLimitReached();
3471}
3472
3473/** @brief Checks if iteration limit was reached */
3474char CBC_LINKAGE
3475Osi_isIterationLimitReached(void *osi)
3476{
3477  OsiSolverInterface *osis = ( OsiSolverInterface *)osi;
3478  return (char)osis->isIterationLimitReached();
3479}
3480
3481
3482int CBC_LINKAGE
3483Osi_getNumCols( void *osi )
3484{
3485  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3486  return osiSolver->getNumCols();
3487}
3488
3489
3490/** @brief Creates (it not yet) the conflict graph  */
3491void 
3492Osi_checkCGraph( void *osi ) {
3493  OsiSolverInterface *solver = (OsiSolverInterface *)(osi);
3494  solver->checkCGraph();
3495}
3496
3497/** @brief Returns the conflict graph */
3498CBCSOLVERLIB_EXPORT const void * CBC_LINKAGE
3499Osi_CGraph( void *osi ) {
3500  OsiSolverInterface *solver = (OsiSolverInterface *)(osi);
3501  return solver->getCGraph();
3502}
3503
3504size_t CG_nodes( void *cgraph ) {
3505  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3506  return cg->size();
3507}
3508
3509char CG_conflicting( void *cgraph, size_t n1, size_t n2 ) {
3510  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3511  return (char) cg->conflicting(n1, n2);
3512}
3513
3514/** @brief Density of the conflict graph */
3515double CG_density( void *cgraph ) {
3516  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3517  return cg->density();
3518}
3519
3520
3521CGNeighbors CG_conflictingNodes(Cbc_Model *model, void *cgraph, size_t node) {
3522  CGNeighbors result;
3523
3524#ifdef CBC_THREAD
3525    pthread_mutex_lock(&model->cbcMutexCG);
3526#endif
3527
3528  if (model->cg_space < Cbc_getNumCols(model)*2) {
3529    if (model->cg_space) {
3530      free( model->cg_neighs);
3531      free(model->cg_iv);
3532    }
3533
3534    model->cg_space = Cbc_getNumCols(model)*2;
3535
3536    model->cg_neighs  = (size_t *) xmalloc( sizeof(size_t)*model->cg_space );
3537    model->cg_iv  = (bool *) xmalloc( sizeof(bool)*model->cg_space );
3538    memset(model->cg_iv, 0, sizeof(bool)*model->cg_space);
3539  }
3540
3541  const CoinStaticConflictGraph *cg = (CoinStaticConflictGraph *)cgraph;
3542
3543  std::pair< size_t, const size_t* > r = cg->conflictingNodes( node, model->cg_neighs, model->cg_iv);
3544#ifdef CBC_THREAD
3545    pthread_mutex_unlock(&model->cbcMutexCG);
3546#endif
3547
3548  result.n = r.first;
3549  result.neigh = r.second;
3550
3551  return result;
3552}
3553
3554
3555
3556
3557
3558/** @brief Returns column name in OsiSolverInterface object */
3559void CBC_LINKAGE
3560Osi_getColName( void *osi, int i, char *name, int maxLen )
3561{
3562  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3563  strncpy( name, osiSolver->getColName(i).c_str(), maxLen );
3564}
3565
3566/** @brief Returns column lower bounds in OsiSolverInterface object */
3567const double * CBC_LINKAGE
3568Osi_getColLower( void *osi )
3569{
3570  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3571  return osiSolver->getColLower();
3572}
3573
3574/** @brief Returns column upper bounds in OsiSolverInterface object */
3575const double * CBC_LINKAGE
3576Osi_getColUpper( void *osi )
3577{
3578  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3579  return osiSolver->getColUpper();
3580}
3581
3582/** @brief Returns integrality information for columns in OsiSolverInterface object */
3583int CBC_LINKAGE
3584Osi_isInteger( void *osi, int col )
3585{
3586  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3587  return osiSolver->isInteger(col);
3588}
3589
3590/** @brief Returns number of rows in OsiSolverInterface object */
3591int CBC_LINKAGE
3592Osi_getNumRows( void *osi )
3593{
3594  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3595  return osiSolver->getNumRows();
3596}
3597
3598/** @brief Returns number non-zeros in the constraint matrix */
3599int CBC_LINKAGE
3600Osi_getNumNz( void *osi )
3601{
3602  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3603  return osiSolver->getNumElements();
3604}
3605
3606/** @brief Returns number integer/binary variables */
3607int CBC_LINKAGE
3608Osi_getNumIntegers( void *osi )
3609{
3610  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3611  return osiSolver->getNumIntegers();
3612}
3613
3614int CBC_LINKAGE
3615Osi_getRowNz(void *osi, int row)
3616{
3617  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3618
3619  const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow();
3620  return cpmRow->getVectorLengths()[row];
3621}
3622
3623/** @brief Indices of variables that appear on a row */
3624const int *CBC_LINKAGE
3625Osi_getRowIndices(void *osi, int row)
3626{
3627  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3628
3629  const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow();
3630  const CoinBigIndex *starts = cpmRow->getVectorStarts();
3631  const int *ridx = cpmRow->getIndices() + starts[row];
3632  return ridx;
3633}
3634
3635/** @brief Coefficients of variables that appear on this row  */
3636const double *CBC_LINKAGE
3637Osi_getRowCoeffs(void *osi, int row)
3638{
3639  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3640
3641  const CoinPackedMatrix *cpmRow = osiSolver->getMatrixByRow();
3642  const CoinBigIndex *starts = cpmRow->getVectorStarts();
3643  const double *rcoef = cpmRow->getElements() + starts[row];
3644  return rcoef;
3645}
3646
3647/** @brief Right hand side of a row  */
3648double CBC_LINKAGE
3649Osi_getRowRHS(void *osi, int row)
3650{
3651  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3652  return osiSolver->getRightHandSide()[row];
3653}
3654
3655/** @brief Sense a row
3656     * @param model problem object
3657     * @param row row index
3658     * @return row sense: E for =, L for <=, G for >= and R for ranged row
3659     **/
3660char CBC_LINKAGE
3661Osi_getRowSense(void *osi, int row)
3662{
3663  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3664
3665  return osiSolver->getRowSense()[row];
3666}
3667
3668/** Generates cutting planes */
3669void CBC_LINKAGE Cgl_generateCuts( void *osiClpSolver, enum CutType ct, void *oc, int strength ) {
3670  OsiClpSolverInterface *solver = (OsiClpSolverInterface *) osiClpSolver;
3671  CglCutGenerator *cg[2] = {NULL, NULL};
3672  OsiCuts *osiCuts = (OsiCuts *) oc;
3673
3674  switch (ct) {
3675    case CT_Gomory:
3676      cg[0] = new CglGomory();
3677      break;
3678    case CT_Clique:
3679      if (solver->getCGraph())
3680        cg[0] = new CglBKClique();
3681      else {
3682        CglClique *clqgen = new CglClique();
3683        clqgen->setStarCliqueReport(false);
3684        clqgen->setRowCliqueReport(false);
3685        clqgen->setMinViolation(1e-4);
3686        cg[0] = clqgen;
3687      }
3688      break;
3689    case CT_KnapsackCover:
3690      cg[0] = new CglKnapsackCover();
3691      break;
3692    case CT_MIR:
3693      {
3694        CglMixedIntegerRounding2 *cgMIR = new CglMixedIntegerRounding2(1, true, 1);
3695        cg[0] = cgMIR;
3696        cgMIR->setDoPreproc(1); // safer (and better)
3697        cg[1] = new CglTwomir();
3698      }
3699      break;
3700    case CT_ZeroHalf:
3701      cg[0] = new CglZeroHalf();
3702      break;
3703    case CT_LiftAndProject:
3704      cg[0] = new CglLandP();
3705      break;
3706  }
3707
3708  for ( int i=0 ; i<2 ; ++i ) {
3709    if (cg[i] == NULL) 
3710      continue;
3711    cg[i]->generateCuts(*solver, *osiCuts);
3712
3713    delete cg[i];
3714  }
3715}
3716
3717/** Creates a new cut pool and returns its pointer */
3718void * CBC_LINKAGE
3719OsiCuts_new() {
3720  OsiCuts *oc = new OsiCuts();
3721  return (void *) oc;
3722}
3723
3724/** Deletes a cut pool */
3725void CBC_LINKAGE
3726OsiCuts_delete( void *osiCuts ) {
3727  OsiCuts *oc = (OsiCuts *) osiCuts;
3728  delete oc;
3729}
3730
3731/** Returns the number of row cuts stored */
3732int CBC_LINKAGE
3733OsiCuts_sizeRowCuts( void *osiCuts ) {
3734  OsiCuts *oc = (OsiCuts *)osiCuts;
3735  return oc->sizeRowCuts();
3736}
3737
3738/** Returns the number of row cuts stored */
3739int CBC_LINKAGE
3740OsiCuts_nzRowCut( void *osiCuts, int iRowCut ) {
3741  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3742  OsiCuts *oc = (OsiCuts *)osiCuts;
3743  const OsiRowCut &rc = oc->rowCut(iRowCut);
3744  return rc.row().getNumElements();
3745}
3746
3747/** Returns the variable indexes in a row cut */
3748const int * CBC_LINKAGE
3749OsiCuts_idxRowCut( void *osiCuts, int iRowCut ) {
3750  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3751  OsiCuts *oc = (OsiCuts *)osiCuts;
3752  const OsiRowCut &rc = oc->rowCut(iRowCut);
3753  return rc.row().getIndices();
3754}
3755
3756/** Returns the variable coefficients in a row cut */
3757const double * CBC_LINKAGE
3758OsiCuts_coefRowCut( void *osiCuts, int iRowCut ) {
3759  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3760  OsiCuts *oc = (OsiCuts *)osiCuts;
3761  const OsiRowCut &rc = oc->rowCut(iRowCut);
3762  return rc.row().getElements();
3763}
3764
3765/** Returns the variable coefficients in a row cut */
3766double CBC_LINKAGE
3767OsiCuts_rhsRowCut( void *osiCuts, int iRowCut ) {
3768  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3769  OsiCuts *oc = (OsiCuts *)osiCuts;
3770  const OsiRowCut &rc = oc->rowCut(iRowCut);
3771  return rc.rhs();
3772}
3773
3774/** Returns the sense of a row cut */
3775char CBC_LINKAGE
3776OsiCuts_senseRowCut( void *osiCuts, int iRowCut ) {
3777  assert(iRowCut >= 0 && iRowCut < OsiCuts_sizeRowCuts(osiCuts) );
3778  OsiCuts *oc = (OsiCuts *)osiCuts;
3779  const OsiRowCut &rc = oc->rowCut(iRowCut);
3780  return rc.sense();
3781}
3782
3783void CBC_LINKAGE
3784OsiCuts_addRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs )
3785{
3786  sense = toupper(sense);
3787  OsiCuts *oc = (OsiCuts *) osiCuts;
3788
3789  OsiRowCut orc;
3790  orc.setRow( nz, idx, coef );
3791
3792
3793  orc.setLb(-DBL_MAX);
3794  orc.setUb(DBL_MAX);
3795
3796  switch (toupper(sense)) {
3797  case '=':
3798    orc.setLb(rhs);
3799    orc.setUb(rhs);
3800    break;
3801  case 'E':
3802    orc.setLb(rhs);
3803    orc.setUb(rhs);
3804    break;
3805  case '<':
3806    orc.setUb(rhs);
3807    break;
3808  case 'L':
3809    orc.setUb(rhs);
3810    break;
3811  case '>':
3812    orc.setLb(rhs);
3813    break;
3814  case 'G':
3815    orc.setLb(rhs);
3816    break;
3817  default:
3818    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3819    abort();
3820  }
3821
3822  oc->insert(orc);
3823}
3824
3825/** adds a row cut (used in callback), stating that this is a globally valid cut */
3826void CBC_LINKAGE
3827OsiCuts_addGlobalRowCut( void *osiCuts, int nz, const int *idx, const double *coef, char sense, double rhs )
3828{
3829  sense = toupper(sense);
3830  OsiCuts *oc = (OsiCuts *) osiCuts;
3831
3832  OsiRowCut orc;
3833  orc.setRow( nz, idx, coef );
3834
3835
3836  orc.setLb(-DBL_MAX);
3837  orc.setUb(DBL_MAX);
3838
3839  switch (toupper(sense)) {
3840  case '=':
3841    orc.setLb(rhs);
3842    orc.setUb(rhs);
3843    break;
3844  case 'E':
3845    orc.setLb(rhs);
3846    orc.setUb(rhs);
3847    break;
3848  case '<':
3849    orc.setUb(rhs);
3850    break;
3851  case 'L':
3852    orc.setUb(rhs);
3853    break;
3854  case '>':
3855    orc.setLb(rhs);
3856    break;
3857  case 'G':
3858    orc.setLb(rhs);
3859    break;
3860  default:
3861    fprintf(stderr, "unknow row sense %c.", toupper(sense));
3862    abort();
3863  }
3864
3865  orc.setGloballyValid(true);
3866  oc->insert(orc);
3867}
3868
3869
3870/** @brief Sets a variable to integer */
3871void CBC_LINKAGE
3872Osi_setInteger(void *osi, int index)
3873{
3874  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3875
3876  osiSolver->setInteger(index);
3877}
3878
3879/** @brief Sets a variable to continuous */
3880void CBC_LINKAGE
3881Osi_setContinuous(void *osi, int index)
3882{
3883  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3884
3885  osiSolver->setContinuous(index);
3886}
3887
3888int CBC_LINKAGE
3889Osi_getColNz(void *osi, int col)
3890{
3891  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3892  const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol();
3893  return cpmCol->getVectorLengths()[col];
3894}
3895
3896/** @brief Indices of rows that a column appears
3897     *
3898     * @param model problem object
3899     * @param col column index
3900     * @return indices of rows that this column appears
3901     **/
3902const int *CBC_LINKAGE
3903Osi_getColIndices(void *osi, int col)
3904{
3905  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3906  const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol();
3907  const CoinBigIndex *starts = cpmCol->getVectorStarts();
3908  const int *cidx = cpmCol->getIndices() + starts[col];
3909  return cidx;
3910}
3911
3912/** @brief Coefficients that a column appear in rows
3913     *
3914     * @param model problem object
3915     * @param col column index
3916     * @return coefficients of this column in rows
3917     **/
3918const double *CBC_LINKAGE
3919Osi_getColCoeffs(void *osi, int col)
3920{
3921  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3922
3923  const CoinPackedMatrix *cpmCol = osiSolver->getMatrixByCol();
3924  const CoinBigIndex *starts = cpmCol->getVectorStarts();
3925  const double *rcoef = cpmCol->getElements() + starts[col];
3926  return rcoef;
3927}
3928
3929/** @brief Returns solution vector in OsiSolverInterface object */
3930const double * CBC_LINKAGE
3931Osi_getColSolution( void *osi )
3932{
3933  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3934
3935  return osiSolver->getColSolution();
3936}
3937
3938/** Adds a new column */
3939void CBC_LINKAGE
3940Osi_addCol(void *osi, const char *name, double lb,
3941  double ub, double obj, char isInteger,
3942  int nz, int *rows, double *coefs)
3943{
3944  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3945
3946    osiSolver->addCol(nz, rows, coefs, lb, ub, obj, std::string(name));
3947    if (isInteger)
3948      osiSolver->setInteger(osiSolver->getNumCols() - 1);
3949}
3950
3951/** @brief Returns vector of reduced costs */
3952const double * CBC_LINKAGE
3953Osi_getReducedCost( void *osi )
3954{
3955  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3956
3957  return osiSolver->getColSolution();
3958}
3959
3960/** @brief Returns vector dual variables */
3961const double * CBC_LINKAGE
3962Osi_getRowPrice( void *osi )
3963{
3964  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3965
3966  return osiSolver->getRowPrice();
3967}
3968
3969double CBC_LINKAGE
3970Osi_getObjValue( void *osi )
3971{
3972  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3973
3974  return osiSolver->getObjValue();
3975}
3976
3977/** @brief Sets column upper bound */
3978void CBC_LINKAGE
3979Osi_setColUpper (void *osi, int elementIndex, double ub)
3980{
3981  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3982  osiSolver->setColUpper(elementIndex, ub);
3983}
3984
3985/** @brief Sets column upper bound */
3986void CBC_LINKAGE
3987Osi_setColLower(void *osi, int elementIndex, double lb)
3988{
3989  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3990  osiSolver->setColLower(elementIndex, lb);
3991}
3992
3993/** @brief integer tolerance */
3994double CBC_LINKAGE
3995Osi_getIntegerTolerance(void *osi)
3996{
3997  OsiSolverInterface *osiSolver = (OsiSolverInterface *) osi;
3998  return osiSolver->getIntegerTolerance();
3999}
4000
4001double CBC_LINKAGE
4002Cbc_getAllowableGap(Cbc_Model* model)
4003{
4004  return model->dbl_param[DBL_PARAM_ALLOWABLE_GAP];
4005}
4006
4007void CBC_LINKAGE
4008Cbc_setAllowableGap(Cbc_Model* model, double allowedGap)
4009{
4010  model->dbl_param[DBL_PARAM_ALLOWABLE_GAP] = allowedGap;
4011}
4012
4013double CBC_LINKAGE
4014Cbc_getAllowableFractionGap(Cbc_Model* model)
4015{
4016  return model->dbl_param[DBL_PARAM_GAP_RATIO];
4017}
4018
4019void CBC_LINKAGE
4020Cbc_setAllowableFractionGap(Cbc_Model* model, double allowedFracionGap)
4021{
4022  model->dbl_param[DBL_PARAM_GAP_RATIO] = allowedFracionGap;
4023}
4024
4025/** returns the maximum number of nodes that can be explored in the search tree
4026 */
4027int CBC_LINKAGE
4028Cbc_getMaximumNodes(Cbc_Model *model)
4029{
4030  return model->int_param[INT_PARAM_MAX_NODES];
4031}
4032
4033/** sets the maximum number of nodes that can be explored in the search tree
4034 */
4035void CBC_LINKAGE
4036Cbc_setMaximumNodes(Cbc_Model *model, int maxNodes)
4037{
4038  model->int_param[INT_PARAM_MAX_NODES] = maxNodes;
4039}
4040
4041/** returns solution limit for the search process
4042 */
4043int CBC_LINKAGE
4044Cbc_getMaximumSolutions(Cbc_Model *model)
4045{
4046  return model->int_param[INT_PARAM_MAX_SOLS];
4047}
4048
4049/** sets a solution limit as a stopping criterion
4050 */
4051void CBC_LINKAGE
4052Cbc_setMaximumSolutions(Cbc_Model *model, int maxSolutions)
4053{
4054  model->int_param[INT_PARAM_MAX_SOLS] = maxSolutions;
4055}
4056
4057/** returns the current log leven
4058 */
4059int CBC_LINKAGE
4060Cbc_getLogLevel(Cbc_Model *model)
4061{
4062  return model->int_param[INT_PARAM_LOG_LEVEL];
4063}
4064
4065/** sets the log level
4066 */
4067void CBC_LINKAGE
4068Cbc_setLogLevel(Cbc_Model *model, int logLevel)
4069{
4070  model->int_param[INT_PARAM_LOG_LEVEL] = logLevel;
4071}
4072
4073/** gets the tolerance for infeasibility in the LP solver
4074 */
4075double CBC_LINKAGE
4076Cbc_getPrimalTolerance(Cbc_Model *model)
4077{
4078  return model->dbl_param[DBL_PARAM_PRIMAL_TOL];
4079}
4080
4081/** sets the tolerance for infeasibility in the LP solver
4082 */
4083void CBC_LINKAGE
4084Cbc_setPrimalTolerance(Cbc_Model *model, double tol)
4085{
4086  model->dbl_param[DBL_PARAM_PRIMAL_TOL] = tol;
4087}
4088
4089/** gets the tolerance for optimality in the LP solver
4090 */
4091double CBC_LINKAGE
4092Cbc_getDualTolerance(Cbc_Model *model)
4093{
4094  return model->dbl_param[DBL_PARAM_DUAL_TOL];
4095}
4096
4097/** sets the tolerance for optimality in the LP solver
4098 */
4099void CBC_LINKAGE
4100Cbc_setDualTolerance(Cbc_Model *model, double tol)
4101{
4102  model->dbl_param[DBL_PARAM_DUAL_TOL] = tol;
4103}
4104
4105double CBC_LINKAGE
4106Cbc_getCutoff(Cbc_Model* model)
4107{
4108  return model->dbl_param[DBL_PARAM_CUTOFF];
4109}
4110
4111void CBC_LINKAGE
4112Cbc_setCutoff(Cbc_Model* model, double cutoff)
4113{
4114  model->dbl_param[DBL_PARAM_CUTOFF] = cutoff;
4115}
4116
4117void CBC_LINKAGE
4118Cbc_setLPmethod(Cbc_Model *model, enum LPMethod lpm ) {
4119  model->lp_method = lpm;
4120}
4121
4122
4123void * CBC_LINKAGE
4124Cbc_getSolverPtr(Cbc_Model *model) {
4125  return model->solver_;
4126}
4127
4128void CBC_LINKAGE
4129Cbc_setDualPivot(Cbc_Model *model, enum DualPivot dp ) {
4130  model->dualp = dp;
4131}
4132
4133double CBC_LINKAGE
4134Cbc_getMaximumSeconds(Cbc_Model *model)
4135{
4136  return model->dbl_param[DBL_PARAM_TIME_LIMIT];
4137}
4138
4139void CBC_LINKAGE
4140Cbc_setMaximumSeconds(Cbc_Model *model, double maxSeconds)
4141{
4142  model->dbl_param[DBL_PARAM_TIME_LIMIT] = maxSeconds;
4143}
4144
4145void CBC_LINKAGE
4146Cbc_storeNameIndexes(Cbc_Model *model, char _store)
4147{
4148  if (_store)
4149  {
4150    if (model->colNameIndex==NULL)
4151    {
4152      assert(model->rowNameIndex==NULL);
4153      model->colNameIndex = new NameIndex();
4154      model->rowNameIndex = new NameIndex();
4155    }
4156  }
4157  else
4158  {
4159    if (model->colNameIndex!=NULL)
4160    {
4161      NameIndex *m = (NameIndex *)model->colNameIndex;
4162      delete m;
4163      m = (NameIndex *)model->rowNameIndex;
4164      assert( m != NULL );
4165      delete m;
4166
4167      model->colNameIndex = model->rowNameIndex = NULL;
4168    }
4169  }
4170}
4171
4172int CBC_LINKAGE
4173Cbc_getColNameIndex(Cbc_Model *model, const char *name)
4174{
4175  if (!model->colNameIndex)
4176  {
4177    fprintf(stderr, "Call Cbc_storeNameIndex to enable name index search.");
4178    abort();
4179  }
4180
4181  NameIndex &colNameIndex = *((NameIndex  *)model->colNameIndex);
4182  NameIndex::iterator it = colNameIndex.find(std::string(name));
4183  if (it == colNameIndex.end())
4184    return -1;
4185
4186  return it->second;
4187}
4188
4189int CBC_LINKAGE
4190Cbc_getRowNameIndex(Cbc_Model *model, const char *name)
4191{
4192  if (!model->rowNameIndex)
4193  {
4194    fprintf(stderr, "Call Cbc_storeNameIndex to enable name index search.");
4195    abort();
4196  }
4197
4198  NameIndex &rowNameIndex = *((NameIndex  *)model->rowNameIndex);
4199  NameIndex::iterator it = rowNameIndex.find(std::string(name));
4200  if (it == rowNameIndex.end())
4201    return -1;
4202
4203  return it->second;
4204}
4205
4206static char **to_char_vec( const vector< string > names )
4207{
4208    size_t spaceVec = (sizeof(char*)*names.size());
4209    size_t totLen = names.size(); // all \0
4210    for ( int i=0 ; (i<(int)names.size()) ; ++i )
4211        totLen += names[i].size();
4212    totLen *= sizeof(char);
4213
4214    char **r = (char **)xmalloc(spaceVec+totLen);
4215    assert( r );
4216    r[0] = (char *)(r + names.size());
4217    for ( size_t i=1 ; (i<names.size()) ; ++i )
4218        r[i] = r[i-1] + names[i-1].size() + 1;
4219
4220    for ( size_t i=0 ; (i<names.size()) ; ++i )
4221        strcpy(r[i], names[i].c_str());
4222
4223    return r;
4224}
4225
4226static void *xmalloc( const size_t size )
4227{
4228   void *result = malloc( size );
4229   if (!result)
4230   {
4231      fprintf(stderr, "No more memory available. Trying to allocate %zu bytes.", size);
4232      abort();
4233   }
4234
4235   return result;
4236}
4237
4238
4239static void *xrealloc( void *ptr, const size_t newSize ) {
4240  void *res = realloc( ptr, newSize );
4241
4242  if (!res) {
4243      fprintf(stderr, "No more memory available. Trying to allocate %zu bytes.", newSize);
4244      abort();
4245   }
4246
4247  return res;
4248}
4249
4250void Cbc_addAllSOS( Cbc_Model *model ) {
4251  if (model->nSos == 0)
4252    return;
4253
4254  CbcModel *cbcModel = model->cbcModel_;
4255
4256  vector< CbcObject *> objects;
4257  objects.reserve( model->nSos );
4258  for ( int i=0 ; i<model->nSos ; ++i ) {
4259    objects.push_back(
4260        new CbcSOS( 
4261            cbcModel, 
4262            model->sosRowStart[i+1]-model->sosRowStart[i],
4263            model->sosEl + model->sosRowStart[i],
4264            model->sosElWeight + model->sosRowStart[i],
4265            (int)objects.size(),
4266            model->sosType[i]
4267          ) 
4268        ); // add in objects
4269  }
4270
4271  cbcModel->addObjects( (int) objects.size(), &objects[0] );
4272
4273  for ( int i=0 ; i<model->nSos ; ++i ) 
4274    delete objects[i];
4275}
4276
4277static void Cbc_addMS( Cbc_Model *model ) {
4278  if ( model->nColsMS == 0 )
4279    return;
4280
4281  CbcModel *cbc = model->cbcModel_;
4282
4283  cbc->setMIPStart( model->nColsMS, (const char **)model->colNamesMS, model->colValuesMS );
4284}
4285
4286void Cbc_iniParams( Cbc_Model *model ) {
4287  model->lp_method = LPM_Auto;
4288  model->dualp = DP_Auto;
4289  model->cg_space = 0;
4290  model->cg_iv = NULL;
4291  model->cg_neighs = NULL;
4292  memset(model->int_param, 0, sizeof(model->int_param) );
4293  for ( int i=0 ; (i<N_DBL_PARAMS) ; ++i )
4294    model->dbl_param[i] = 0.0;
4295
4296  model->int_param[INT_PARAM_PERT_VALUE]       =       50;
4297  model->int_param[INT_PARAM_IDIOT]            =       -1;
4298  model->int_param[INT_PARAM_STRONG_BRANCHING] =        5;
4299  model->int_param[INT_PARAM_CUT_DEPTH]        =       -1;
4300  model->int_param[INT_PARAM_MAX_NODES]        =  INT_MAX;
4301  model->int_param[INT_PARAM_NUMBER_BEFORE]    =        5;
4302  model->int_param[INT_PARAM_FPUMP_ITS]        =       30;
4303  model->int_param[INT_PARAM_MAX_SOLS]         =       -1;
4304  model->int_param[INT_PARAM_CUT_PASS_IN_TREE] =        1;
4305  model->int_param[INT_PARAM_LOG_LEVEL]        =        1;
4306  model->int_param[INT_PARAM_MAX_SAVED_SOLS]   =       -1;
4307  model->int_param[INT_PARAM_MULTIPLE_ROOTS]   =        0;
4308  model->int_param[INT_PARAM_THREADS]          =       -1;
4309  model->int_param[INT_PARAM_ROUND_INT_VARS]   =        1;
4310  model->int_param[INT_PARAM_RANDOM_SEED]      =        1;
4311  model->int_param[INT_PARAM_ELAPSED_TIME]     =        1;
4312
4313  model->dbl_param[DBL_PARAM_PRIMAL_TOL]       =          1e-6;
4314  model->dbl_param[DBL_PARAM_DUAL_TOL]         =          1e-6;
4315  model->dbl_param[DBL_PARAM_ZERO_TOL]         =         1e-20;
4316  model->dbl_param[DBL_PARAM_INT_TOL]          =          1e-6;
4317  model->dbl_param[DBL_PARAM_PRESOLVE_TOL]     =          1e-8;
4318  model->dbl_param[DBL_PARAM_TIME_LIMIT]       =  COIN_DBL_MAX;
4319  model->dbl_param[DBL_PARAM_PSI]              =          -1.0;
4320  model->dbl_param[DBL_PARAM_CUTOFF]           =  COIN_DBL_MAX;
4321  model->dbl_param[DBL_PARAM_ALLOWABLE_GAP]    =         1e-10;
4322  model->dbl_param[DBL_PARAM_GAP_RATIO]        =        0.0001;
4323}
4324
4325#if defined(__MWERKS__)
4326#pragma export off
4327#endif
4328
4329/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
4330*/
Note: See TracBrowser for help on using the repository browser.