source: trunk/src/Cbc_C_Interface.cpp @ 2875

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

export Cgl_generateCuts in windows

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