source: trunk/src/Cbc_C_Interface.cpp @ 2870

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

C interface: Cbc_solveLinearProgram to solve only LP relaxation

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