source: stable/1.8/CoinMP/src/CoinCbc.cpp

Last change on this file was 580, checked in by bjarni, 6 years ago

Testing for default value logLevel == 1 before adding -log argument to CbcMain1

File size: 49.7 KB
Line 
1
2/*  CoinCbc.cpp  */
3
4#include <stdio.h>
5
6#include "CoinProblem.h"
7#include "CoinResult.h"
8#include "CoinSolver.h"
9#include "CoinOption.h"
10
11#include <cfloat>
12
13#include "CoinHelperFunctions.hpp"
14#include "CoinMessageHandler.hpp"
15
16#include "ClpSimplex.hpp"
17#include "ClpPrimalColumnSteepest.hpp"
18#include "ClpDualRowSteepest.hpp"
19#include "ClpEventHandler.hpp"
20
21#include "OsiSolverInterface.hpp"
22#include "OsiClpSolverInterface.hpp"
23
24#include "CbcModel.hpp"
25#include "CbcSolver.hpp"
26#include "CbcEventHandler.hpp"
27#include "CbcBranchActual.hpp"   // CbcSOS
28#include "CbcBranchLotsize.hpp"  // CbcLotsize
29
30#include "CglProbing.hpp"
31#include "CglGomory.hpp"
32#include "CglKnapsackCover.hpp"
33#include "CglOddHole.hpp"
34#include "CglClique.hpp"
35#include "CglLiftAndProject.hpp"
36#include "CglSimpleRounding.hpp"
37
38
39#include "CoinCbc.h"
40
41#define NEW_STYLE_CBCMAIN
42
43
44typedef void *HCBC;
45
46/************************************************************************/
47/*  Message Callback Handler                                            */
48/************************************************************************/
49
50
51class CBMessageHandler : public CoinMessageHandler {
52public: 
53        void registerCallback(COIN_MSGLOG_CB MsgLogCB, void *MsgLogParam);
54        void setCallback(MSGLOGCALLBACK msgCallback);
55        virtual int print();
56
57        /** Default constructor. */
58        CBMessageHandler();
59        /** Destructor */
60        virtual ~CBMessageHandler();
61        /** The copy constructor. */
62        CBMessageHandler(const CBMessageHandler & rhs);
63        /// Assignment
64        CBMessageHandler& operator=(const CBMessageHandler & rhs);
65        /// Clone
66        virtual CoinMessageHandler * clone() const ;
67
68private:
69        COIN_MSGLOG_CB MsgLogCB_;
70        void *MsgLogParam_;
71        MSGLOGCALLBACK msgCallback_;
72};
73
74
75
76void CBMessageHandler::registerCallback(COIN_MSGLOG_CB MsgLogCB, void *MsgLogParam)
77{
78  MsgLogCB_ = MsgLogCB;
79  MsgLogParam_ = MsgLogParam;
80  msgCallback_ = NULL;
81}
82
83
84void CBMessageHandler::setCallback(MSGLOGCALLBACK msgCallback)
85{
86  msgCallback_ = msgCallback;
87  MsgLogCB_ = NULL;
88  MsgLogParam_ = NULL;
89}
90
91
92
93int CBMessageHandler::print()
94{
95        if (MsgLogCB_)
96                MsgLogCB_(const_cast<char*>(messageBuffer()), MsgLogParam_);
97        else {
98                msgCallback_(const_cast<char*>(messageBuffer()));
99        }
100        return CoinMessageHandler::print();
101}
102
103// Default Constructor
104CBMessageHandler::CBMessageHandler () : CoinMessageHandler() 
105{
106  MsgLogCB_ = NULL;
107  MsgLogParam_ = NULL;
108  msgCallback_ = NULL;
109}
110
111
112// Copy constructor
113CBMessageHandler::CBMessageHandler (const CBMessageHandler & rhs) : CoinMessageHandler(rhs) {}
114
115// Destructor
116CBMessageHandler::~CBMessageHandler () {}
117
118// Assignment operator
119CBMessageHandler & CBMessageHandler::operator=(const CBMessageHandler& rhs)
120{
121  if (this != &rhs) {
122    CoinMessageHandler::operator=(rhs);
123  }
124  return *this;
125}
126
127// Clone
128CoinMessageHandler * CBMessageHandler::clone() const
129{
130        CBMessageHandler * messagehandler;
131
132        messagehandler = new CBMessageHandler(*this);
133        messagehandler->MsgLogCB_ = this->MsgLogCB_;
134        messagehandler->MsgLogParam_ = this->MsgLogParam_;
135        messagehandler->msgCallback_ = this->msgCallback_;
136        return messagehandler;
137}
138
139
140
141/************************************************************************/
142/*  Iteration Callback Handler                                          */
143/************************************************************************/
144
145
146class CBIterHandler : public ClpEventHandler {
147
148public: 
149   void registerLPIterCallback(COIN_LPITER_CB LPIterCB, void* LPIterParam);
150   void setIterCallback(ITERCALLBACK iterCallback);
151
152        virtual int event(Event whichEvent);
153   
154  /** Default constructor. */
155  CBIterHandler();
156  /// Constructor with pointer to model (redundant as setEventHandler does)
157  CBIterHandler(ClpSimplex * model);
158  /** Destructor */
159  virtual ~CBIterHandler();
160  /** The copy constructor. */
161  CBIterHandler(const CBIterHandler & rhs);
162  /// Assignment
163  CBIterHandler& operator=(const CBIterHandler & rhs);
164  /// Clone
165  virtual ClpEventHandler * clone() const ;
166
167
168private:
169        COIN_LPITER_CB LPIterCB_;
170        void* LPIterParam_;
171        ITERCALLBACK iterCallback_;
172};
173
174
175void CBIterHandler::registerLPIterCallback(COIN_LPITER_CB LPIterCB, void* LPIterParam)
176{
177  LPIterCB_ = LPIterCB;
178  LPIterParam_ = LPIterParam;
179  iterCallback_ = NULL;
180}
181
182
183void CBIterHandler::setIterCallback(ITERCALLBACK iterCallback)
184{
185  iterCallback_ = iterCallback;
186  LPIterCB_ = NULL;
187  LPIterParam_ = NULL;
188}
189
190
191
192int CBIterHandler::event(Event whichEvent)
193{
194        int numIter;
195        double objValue;
196        int isPrimalFeasible;
197        int isDualFeasible;
198        double sumPrimalInfeas; 
199        double sumDualInfeas;
200        int cancelAsap;
201
202        if ((whichEvent==endOfIteration)) {
203                numIter = model_->getIterationCount();
204                objValue = model_->getObjValue();
205                sumDualInfeas = model_->sumDualInfeasibilities();
206                sumPrimalInfeas = model_->sumPrimalInfeasibilities();
207                isPrimalFeasible = model_->primalFeasible();
208                isDualFeasible = model_->dualFeasible();
209                if (LPIterCB_)
210                        cancelAsap = LPIterCB_(numIter, objValue, isPrimalFeasible&&isDualFeasible, sumPrimalInfeas, LPIterParam_);
211                else {
212                        cancelAsap = iterCallback_(numIter, objValue, isPrimalFeasible&&isDualFeasible, sumPrimalInfeas);
213                }
214                if (cancelAsap) {
215                        return 5;
216                }
217        }
218        return -1;
219}
220
221
222// Default Constructor
223CBIterHandler::CBIterHandler () : ClpEventHandler() 
224{
225        LPIterCB_ = NULL;
226        LPIterParam_ = NULL;
227        iterCallback_ = NULL;
228}
229
230// Copy constructor
231CBIterHandler::CBIterHandler (const CBIterHandler & rhs) : ClpEventHandler(rhs) {}
232
233// Constructor with pointer to model
234CBIterHandler::CBIterHandler(ClpSimplex * model) : ClpEventHandler(model) {}
235
236// Destructor
237CBIterHandler::~CBIterHandler () {}
238
239// Assignment operator
240CBIterHandler & CBIterHandler::operator=(const CBIterHandler& rhs)
241{
242  if (this != &rhs) {
243    ClpEventHandler::operator=(rhs);
244  }
245  return *this;
246}
247
248// Clone
249ClpEventHandler * CBIterHandler::clone() const
250{
251        CBIterHandler * iterhandler;
252
253        iterhandler = new CBIterHandler(*this);
254        iterhandler->LPIterCB_ = this->LPIterCB_;
255        iterhandler->LPIterParam_ = this->LPIterParam_;
256        iterhandler->iterCallback_ = this->iterCallback_;
257        return iterhandler;
258}
259
260
261
262/************************************************************************/
263/*  MIP Node Callback Handler                                           */
264/************************************************************************/
265
266
267class CBNodeHandler : public CbcEventHandler {
268
269public: 
270        void registerCallback(COIN_MIPNODE_CB MipNodeCB, void* MipNodeParam);
271        void setCallback(MIPNODECALLBACK mipNodeCallback);
272
273        virtual CbcAction event(CbcEvent whichEvent);
274   
275  /** Default constructor. */
276  CBNodeHandler();
277  /// Constructor with pointer to model (redundant as setEventHandler does)
278  //JPF CBNodeHandler(ClpSimplex * model);
279  CBNodeHandler(CbcModel * model);
280 
281
282  /** Destructor */
283  virtual ~CBNodeHandler();
284  /** The copy constructor. */
285  CBNodeHandler(const CBNodeHandler & rhs);
286  /// Assignment
287  CBNodeHandler& operator=(const CBNodeHandler & rhs);
288  /// Clone
289  virtual CbcEventHandler * clone() const ;
290
291
292private:
293        COIN_MIPNODE_CB MipNodeCB_;
294        void* MipNodeParam_;
295        MIPNODECALLBACK mipNodeCallback_;
296        int lastSolCount_;
297};
298
299
300void CBNodeHandler::registerCallback(COIN_MIPNODE_CB MipNodeCB, void* MipNodeParam)
301{
302        MipNodeCB_ = MipNodeCB;
303        MipNodeParam_ = MipNodeParam;
304        mipNodeCallback_ = NULL;
305        lastSolCount_ = 0;
306}
307
308
309void CBNodeHandler::setCallback(MIPNODECALLBACK mipNodeCallback)
310{
311        mipNodeCallback_ = mipNodeCallback;
312        MipNodeCB_ = NULL;
313        MipNodeParam_ = NULL;
314        lastSolCount_ = 0;
315}
316
317
318CBNodeHandler::CbcAction CBNodeHandler::event(CbcEvent whichEvent)
319{
320        int numIter;
321        int numNodes;
322        double bestBound;
323        double objValue;
324        int solCount;
325        int cancelAsap;
326
327        if (whichEvent==node) {
328                numIter = model_->getIterationCount();
329                numNodes = model_->getNodeCount();
330                objValue = model_->getObjValue();
331                bestBound = model_->getBestPossibleObjValue();
332                solCount = model_->getSolutionCount();
333                if (MipNodeCB_) 
334                        cancelAsap = MipNodeCB_(numIter, numNodes, bestBound, objValue, solCount != lastSolCount_, MipNodeParam_);
335                else {
336                        cancelAsap = mipNodeCallback_(numIter, numNodes, bestBound, objValue, solCount != lastSolCount_);
337                }
338                lastSolCount_ = solCount;
339                if (cancelAsap) {
340                        return stop;
341                }
342        }
343        return noAction;
344}
345
346
347// Default Constructor
348CBNodeHandler::CBNodeHandler () : CbcEventHandler() 
349{
350        MipNodeCB_ = NULL;
351        MipNodeParam_ = NULL;
352        mipNodeCallback_ = NULL;
353        lastSolCount_ = 0;
354}
355
356// Copy constructor
357CBNodeHandler::CBNodeHandler (const CBNodeHandler & rhs) : CbcEventHandler(rhs) {}
358
359// Constructor with pointer to model
360//JPF: CBNodeHandler::CBNodeHandler(ClpSimplex * model) : CbcEventHandler(model) {}
361CBNodeHandler::CBNodeHandler(CbcModel * model) : CbcEventHandler(model) {}
362
363// Destructor
364CBNodeHandler::~CBNodeHandler () {}
365
366// Assignment operator
367CBNodeHandler & CBNodeHandler::operator=(const CBNodeHandler& rhs)
368{
369  if (this != &rhs) {
370    CbcEventHandler::operator=(rhs);
371  }
372  return *this;
373}
374
375// Clone
376CbcEventHandler * CBNodeHandler::clone() const
377{
378        CBNodeHandler * nodehandler;
379
380        nodehandler = new CBNodeHandler(*this);
381        nodehandler->MipNodeCB_ = this->MipNodeCB_;
382        nodehandler->MipNodeParam_ = this->MipNodeParam_;
383        nodehandler->lastSolCount_ = this->lastSolCount_;
384        nodehandler->mipNodeCallback_ = this->mipNodeCallback_;
385        return nodehandler;
386}
387
388
389/************************************************************************/
390/*  Coin Problem Info Structure                                         */
391/************************************************************************/
392
393typedef struct {
394                                ClpSimplex *clp;
395                                ClpSolve *clp_presolve;
396                                OsiClpSolverInterface *osi;
397                                CbcModel *cbc;
398
399                                CglProbing *probing;
400                                CglGomory *gomory;
401                                CglKnapsackCover *knapsack;
402                                CglOddHole *oddhole;
403                                CglClique *clique;
404                                CglLiftAndProject *liftpro;
405                                CglSimpleRounding *rounding;
406
407                                // callback handlers
408                                CBMessageHandler *msghandler;
409                                CBIterHandler *iterhandler;
410                                CBNodeHandler *nodehandler;
411
412                                } CBCINFO, *PCBC;
413
414
415HCBC CbcCreateSolverObject(void)
416{
417        PCBC pCbc;
418
419        pCbc = (PCBC)malloc(sizeof(CBCINFO));
420        if (!pCbc) {
421                return NULL;
422        }
423        memset(pCbc, 0, sizeof(CBCINFO));
424
425        pCbc->clp = new ClpSimplex();
426        pCbc->clp_presolve = new ClpSolve();
427        pCbc->osi = new OsiClpSolverInterface(pCbc->clp);
428        pCbc->cbc = NULL;  /* ERRORFIX 2005/2/22: Crashes if not NULL when trying to set message handler */
429
430        pCbc->msghandler = NULL;
431        pCbc->iterhandler = NULL;
432        pCbc->nodehandler = NULL;
433        return (HCBC)pCbc;
434}
435
436
437void CbcClearSolverObject(HCBC hCbc)
438{
439        PCBC pCbc = (PCBC)hCbc;
440        if (!pCbc) {
441                return;
442        }
443        if (pCbc->clp) delete pCbc->clp;
444        if (pCbc->clp_presolve) delete pCbc->clp_presolve;
445        //if (pCbc->osi) delete pCbc->osi;
446        if (pCbc->cbc) delete pCbc->cbc;
447
448        if (pCbc->msghandler)   delete pCbc->msghandler;
449        if (pCbc->iterhandler)  delete pCbc->iterhandler;
450        if (pCbc->nodehandler)  delete pCbc->nodehandler;
451
452        free(pCbc);
453}
454
455/************************************************************************/
456/*  Callback Handling                                                   */
457/************************************************************************/
458
459
460
461int CbcRegisterMsgLogCallback(HCBC hCbc, int LogLevel, COIN_MSGLOG_CB MsgLogCB, void *MsgLogParam)
462{
463        PCBC pCbc = (PCBC)hCbc;
464
465        if (!MsgLogCB) {
466                return CBC_CALL_FAILED;
467        }
468        delete pCbc->msghandler;
469        pCbc->msghandler = new CBMessageHandler();
470        pCbc->msghandler->registerCallback(MsgLogCB, MsgLogParam);
471        pCbc->msghandler->setLogLevel(LogLevel);
472        if (pCbc->clp) pCbc->clp->passInMessageHandler(pCbc->msghandler);
473        if (pCbc->cbc) pCbc->cbc->passInMessageHandler(pCbc->msghandler);
474        if (pCbc->osi) pCbc->osi->passInMessageHandler(pCbc->msghandler);
475        return CBC_CALL_SUCCESS;
476}
477
478
479
480int CbcRegisterLPIterCallback(HCBC hCbc, COIN_LPITER_CB LPIterCB, void* LPIterParam)
481{
482        PCBC pCbc = (PCBC)hCbc;
483
484        if (!LPIterCB) {
485                return CBC_CALL_FAILED;
486        }
487        delete pCbc->iterhandler;
488        pCbc->iterhandler = new CBIterHandler(pCbc->clp);
489        pCbc->iterhandler->registerLPIterCallback(LPIterCB, LPIterParam);
490        if (pCbc->clp) pCbc->clp->passInEventHandler(pCbc->iterhandler);
491        return CBC_CALL_SUCCESS;
492}
493
494
495
496int CbcRegisterMipNodeCallback(HCBC hCbc, COIN_MIPNODE_CB MipNodeCB, void* MipNodeParam)
497{
498        PCBC pCbc = (PCBC)hCbc;
499
500        if (!MipNodeCB) {
501                return CBC_CALL_FAILED;
502        }
503        delete pCbc->nodehandler;
504        pCbc->nodehandler = new CBNodeHandler(pCbc->cbc);
505        pCbc->nodehandler->registerCallback(MipNodeCB, MipNodeParam);
506        if (pCbc->cbc) pCbc->cbc->passInEventHandler(pCbc->nodehandler);
507        return CBC_CALL_SUCCESS;
508}
509
510
511// Depreciated
512int CbcSetMsgLogCallback(HCBC hCbc, int LogLevel, MSGLOGCALLBACK MsgLogCallback)
513{
514        PCBC pCbc = (PCBC)hCbc;
515
516        if (!MsgLogCallback) {
517                return CBC_CALL_FAILED;
518        }
519        delete pCbc->msghandler;
520        pCbc->msghandler = new CBMessageHandler();
521        pCbc->msghandler->setCallback(MsgLogCallback);
522        pCbc->msghandler->setLogLevel(LogLevel);
523        if (pCbc->clp) pCbc->clp->passInMessageHandler(pCbc->msghandler);
524        if (pCbc->cbc) pCbc->cbc->passInMessageHandler(pCbc->msghandler);
525        if (pCbc->osi) pCbc->osi->passInMessageHandler(pCbc->msghandler);
526        return CBC_CALL_SUCCESS;
527}
528
529
530// Depreciated
531int CbcSetIterCallback(HCBC hCbc, ITERCALLBACK IterCallback)
532{
533        PCBC pCbc = (PCBC)hCbc;
534
535        if (!IterCallback) {
536                return CBC_CALL_FAILED;
537        }
538        delete pCbc->iterhandler;
539        pCbc->iterhandler = new CBIterHandler(pCbc->clp);
540        pCbc->iterhandler->setIterCallback(IterCallback);
541        if (pCbc->clp) pCbc->clp->passInEventHandler(pCbc->iterhandler);
542        return CBC_CALL_SUCCESS;
543}
544
545
546// Depreciated
547int CbcSetMipNodeCallback(HCBC hCbc, MIPNODECALLBACK MipNodeCallback)
548{
549        PCBC pCbc = (PCBC)hCbc;
550
551        if (!MipNodeCallback) {
552                return CBC_CALL_FAILED;
553        }
554        delete pCbc->nodehandler;
555        pCbc->nodehandler = new CBNodeHandler(pCbc->cbc);
556        pCbc->nodehandler->setCallback(MipNodeCallback);
557        if (pCbc->cbc) pCbc->cbc->passInEventHandler(pCbc->nodehandler);
558        return CBC_CALL_SUCCESS;
559}
560
561
562int CbcSetAllCallbacks(HCBC hCbc, PSOLVER pSolver, POPTION pOption)
563{
564        int logLevel;
565
566        logLevel = coinGetIntOption(pOption, COIN_INT_LOGLEVEL);
567        CbcRegisterMsgLogCallback(hCbc, logLevel, pSolver->MsgLogCB, pSolver->MsgLogParam);
568        CbcRegisterLPIterCallback(hCbc, pSolver->LPIterCB, pSolver->LPIterParam);
569        CbcRegisterMipNodeCallback(hCbc, pSolver->MipNodeCB, pSolver->MipNodeParam);
570        return CBC_CALL_SUCCESS;
571}
572
573
574
575/************************************************************************/
576/*  Option Setting                                                      */
577/************************************************************************/
578
579
580int CbcSetClpOptions(HCBC hCbc, POPTION pOption)
581{
582        PCBC pCbc = (PCBC)hCbc;
583        ClpSolve::SolveType method;
584        ClpSolve::PresolveType presolve;
585
586        /* check if it has been changed, leave alone otherwise */
587        if (coinGetOptionChanged(pOption, COIN_INT_SCALING))                    pCbc->clp->scaling(coinGetIntOption(pOption, COIN_INT_SCALING));
588        if (coinGetOptionChanged(pOption, COIN_INT_PERTURBATION))               pCbc->clp->setPerturbation(coinGetIntOption(pOption, COIN_INT_PERTURBATION));
589
590        if (coinGetOptionChanged(pOption, COIN_REAL_MAXSECONDS))                pCbc->clp->setMaximumSeconds(coinGetRealOption(pOption, COIN_REAL_MAXSECONDS));
591        if (coinGetOptionChanged(pOption, COIN_INT_MAXITER))                    pCbc->clp->setMaximumIterations(coinGetIntOption(pOption, COIN_INT_MAXITER));
592
593        if (coinGetOptionChanged(pOption, COIN_REAL_PRIMALOBJLIM))      pCbc->clp->setPrimalObjectiveLimit(coinGetRealOption(pOption, COIN_REAL_PRIMALOBJLIM));
594        if (coinGetOptionChanged(pOption, COIN_REAL_DUALOBJLIM))                pCbc->clp->setDualObjectiveLimit(coinGetRealOption(pOption, COIN_REAL_DUALOBJLIM));
595        if (coinGetOptionChanged(pOption, COIN_REAL_PRIMALOBJTOL))      pCbc->clp->setPrimalTolerance(coinGetRealOption(pOption, COIN_REAL_PRIMALOBJTOL));
596        if (coinGetOptionChanged(pOption, COIN_REAL_DUALOBJTOL))                pCbc->clp->setDualTolerance(coinGetRealOption(pOption, COIN_REAL_DUALOBJTOL));
597
598        if (coinGetOptionChanged(pOption, COIN_INT_PRIMALPIVOTALG)) {
599                ClpPrimalColumnSteepest primalSteepest(coinGetIntOption(pOption, COIN_INT_PRIMALPIVOTALG));
600                pCbc->clp->setPrimalColumnPivotAlgorithm(primalSteepest);
601        }
602
603        if (coinGetOptionChanged(pOption, COIN_INT_DUALPIVOTALG)) {
604                ClpDualRowSteepest dualSteepest(coinGetIntOption(pOption, COIN_INT_DUALPIVOTALG));
605                pCbc->clp->setDualRowPivotAlgorithm(dualSteepest);
606        }
607
608        if (coinGetOptionChanged(pOption, COIN_INT_CRASHIND)) { 
609                if (coinGetIntOption(pOption, COIN_INT_CRASHIND)) {
610                        pCbc->clp->crash(coinGetRealOption(pOption, COIN_REAL_CRASHGAP),
611                                                                coinGetIntOption(pOption, COIN_INT_CRASHPIVOT));
612                }
613        }
614
615        if (coinGetOptionChanged(pOption, COIN_INT_SOLVEMETHOD)) {
616                switch (coinGetIntOption(pOption, COIN_INT_SOLVEMETHOD)) {
617                        case 0: method = ClpSolve::useDual;                             break;
618                        case 1: method = ClpSolve::usePrimal;                   break;
619                        case 2: method = ClpSolve::usePrimalorSprint;   break;
620                        case 3: method = ClpSolve::useBarrier;                  break;
621                        case 4: method = ClpSolve::useBarrierNoCross;   break;
622                        case 5: method = ClpSolve::automatic;                   break;
623                        default: method = ClpSolve::usePrimal;
624                }
625                pCbc->clp->setSolveType(method);   //ClpSolve::usePrimal
626        }
627
628        if (coinGetOptionChanged(pOption, COIN_INT_PRESOLVETYPE)) {   
629                switch (coinGetIntOption(pOption, COIN_INT_PRESOLVETYPE)) {
630                        case 0: presolve = ClpSolve::presolveOn;                 break;
631                        case 1: presolve = ClpSolve::presolveOff;                break;
632                        case 2: presolve = ClpSolve::presolveNumber;     break;
633                        default: presolve = ClpSolve::presolveOn;
634                }
635                pCbc->clp_presolve->setPresolveType(presolve);   //ClpSolve::presolveOn
636        }
637        return 1;
638}
639
640
641int CbcSetCbcOptions(HCBC hCbc, POPTION pOption)
642{
643        PCBC pCbc = (PCBC)hCbc;
644
645        if (!pCbc->cbc) {
646                return 0;
647        }
648        if (coinGetOptionChanged(pOption, COIN_INT_MIPMAXNODES))                pCbc->cbc->setMaximumNodes(coinGetIntOption(pOption, COIN_INT_MIPMAXNODES));
649        if (coinGetOptionChanged(pOption, COIN_INT_MIPMAXSOL))          pCbc->cbc->setMaximumSolutions(coinGetIntOption(pOption, COIN_INT_MIPMAXSOL));
650        if (coinGetOptionChanged(pOption, COIN_REAL_MIPMAXSEC))         pCbc->cbc->setDblParam(CbcModel::CbcMaximumSeconds,coinGetRealOption(pOption, COIN_REAL_MIPMAXSEC));
651
652        if (coinGetOptionChanged(pOption, COIN_INT_MIPFATHOMDISC))      pCbc->cbc->setIntParam(CbcModel::CbcFathomDiscipline,coinGetIntOption(pOption, COIN_INT_MIPFATHOMDISC));
653
654        // JPF commented: pCbc->cbc->setHotstartStrategy(coinGetIntOption(pOption, COIN_INT_MIPHOTSTART));
655        //              pCbc->cbc->setForcePriority(coinGetIntOption(pOption, COIN_INT_MIPFORCEPRIOR));
656
657        if (coinGetOptionChanged(pOption, COIN_INT_MIPMINIMUMDROP))     pCbc->cbc->setMinimumDrop(coinGetIntOption(pOption, COIN_INT_MIPMINIMUMDROP));
658        if (coinGetOptionChanged(pOption, COIN_INT_MIPMAXPASSROOT))     pCbc->cbc->setMaximumCutPassesAtRoot(coinGetIntOption(pOption, COIN_INT_MIPMAXPASSROOT));
659        if (coinGetOptionChanged(pOption, COIN_INT_MIPMAXCUTPASS))      pCbc->cbc->setMaximumCutPasses(coinGetIntOption(pOption, COIN_INT_MIPMAXCUTPASS));
660        if (coinGetOptionChanged(pOption, COIN_INT_MIPSTRONGBRANCH))    pCbc->cbc->setNumberStrong(coinGetIntOption(pOption, COIN_INT_MIPSTRONGBRANCH));
661        if (coinGetOptionChanged(pOption, COIN_INT_MIPSCANGLOBCUTS))    pCbc->cbc->setHowOftenGlobalScan(coinGetIntOption(pOption, COIN_INT_MIPSCANGLOBCUTS));
662
663        if (coinGetOptionChanged(pOption, COIN_REAL_MIPINTTOL))         pCbc->cbc->setIntegerTolerance(coinGetRealOption(pOption, COIN_REAL_MIPINTTOL));
664        if (coinGetOptionChanged(pOption, COIN_REAL_MIPINFWEIGHT))      pCbc->cbc->setInfeasibilityWeight(coinGetRealOption(pOption, COIN_REAL_MIPINFWEIGHT));
665        if (coinGetOptionChanged(pOption, COIN_REAL_MIPCUTOFF))         pCbc->cbc->setDblParam(CbcModel::CbcCutoffIncrement,coinGetRealOption(pOption, COIN_REAL_MIPCUTOFF));
666        if (coinGetOptionChanged(pOption, COIN_REAL_MIPABSGAP))         pCbc->cbc->setAllowableGap(coinGetRealOption(pOption, COIN_REAL_MIPABSGAP));
667        if (coinGetOptionChanged(pOption, COIN_REAL_MIPFRACGAP))                pCbc->cbc->setAllowableFractionGap(coinGetRealOption(pOption, COIN_REAL_MIPFRACGAP));
668        return 1;
669}
670
671
672int CbcSetCglOptions(HCBC hCbc, POPTION pOption)
673{
674        PCBC pCbc = (PCBC)hCbc;
675
676        /* see CbcModel.hpp has commments on calling cuts */
677        if (coinGetIntOption(pOption, COIN_INT_MIPCUT_PROBING)) {
678                pCbc->probing = new CglProbing();
679                if (coinGetOptionChanged(pOption, COIN_INT_MIPPROBE_MODE))      pCbc->probing->setMode(coinGetIntOption(pOption, COIN_INT_MIPPROBE_MODE));
680                if (coinGetOptionChanged(pOption, COIN_INT_MIPPROBE_USEOBJ))    pCbc->probing->setUsingObjective(coinGetIntOption(pOption, COIN_INT_MIPPROBE_USEOBJ) ? true : false);
681                if (coinGetOptionChanged(pOption, COIN_INT_MIPPROBE_MAXPASS))   pCbc->probing->setMaxPass(coinGetIntOption(pOption, COIN_INT_MIPPROBE_MAXPASS));
682                if (coinGetOptionChanged(pOption, COIN_INT_MIPPROBE_MAXPROBE))  pCbc->probing->setMaxProbe(coinGetIntOption(pOption, COIN_INT_MIPPROBE_MAXPROBE));
683                if (coinGetOptionChanged(pOption, COIN_INT_MIPPROBE_MAXLOOK))   pCbc->probing->setMaxLook(coinGetIntOption(pOption, COIN_INT_MIPPROBE_MAXLOOK));
684                if (coinGetOptionChanged(pOption, COIN_INT_MIPPROBE_ROWCUTS))   pCbc->probing->setRowCuts(coinGetIntOption(pOption, COIN_INT_MIPPROBE_ROWCUTS));
685                pCbc->cbc->addCutGenerator(pCbc->probing,coinGetIntOption(pOption, COIN_INT_MIPPROBE_FREQ),"Probing");
686        }
687
688        if (coinGetIntOption(pOption, COIN_INT_MIPCUT_GOMORY)) {
689                pCbc->gomory = new CglGomory();
690                if (coinGetOptionChanged(pOption, COIN_INT_MIPGOMORY_LIMIT))    pCbc->gomory->setLimit(coinGetIntOption(pOption, COIN_INT_MIPGOMORY_LIMIT));
691                if (coinGetOptionChanged(pOption, COIN_REAL_MIPGOMORY_AWAY))    pCbc->gomory->setAway(coinGetRealOption(pOption, COIN_REAL_MIPGOMORY_AWAY));
692                pCbc->cbc->addCutGenerator(pCbc->gomory,coinGetIntOption(pOption, COIN_INT_MIPGOMORY_FREQ),"Gomory");
693        }
694
695        if (coinGetIntOption(pOption, COIN_INT_MIPCUT_KNAPSACK)) {
696                pCbc->knapsack = new CglKnapsackCover();
697                if (coinGetOptionChanged(pOption, COIN_INT_MIPKNAPSACK_MAXIN))  pCbc->knapsack->setMaxInKnapsack(coinGetIntOption(pOption, COIN_INT_MIPKNAPSACK_MAXIN));
698                pCbc->cbc->addCutGenerator(pCbc->knapsack,coinGetIntOption(pOption, COIN_INT_MIPKNAPSACK_FREQ),"Knapsack");
699        }
700
701        if (coinGetIntOption(pOption, COIN_INT_MIPCUT_ODDHOLE)) {
702                pCbc->oddhole= new CglOddHole();
703                if (coinGetOptionChanged(pOption, COIN_REAL_MIPODDHOLE_MINVIOL))        pCbc->oddhole->setMinimumViolation(coinGetRealOption(pOption, COIN_REAL_MIPODDHOLE_MINVIOL));
704                if (coinGetOptionChanged(pOption, COIN_REAL_MIPODDHOLE_MINVIOLPER))     pCbc->oddhole->setMinimumViolationPer(coinGetRealOption(pOption, COIN_REAL_MIPODDHOLE_MINVIOLPER));
705                if (coinGetOptionChanged(pOption, COIN_INT_MIPODDHOLE_MAXENTRIES))      pCbc->oddhole->setMaximumEntries(coinGetIntOption(pOption, COIN_INT_MIPODDHOLE_MAXENTRIES));
706                pCbc->cbc->addCutGenerator(pCbc->oddhole,coinGetIntOption(pOption, COIN_INT_MIPODDHOLE_FREQ),"OddHole");
707        }
708
709        if (coinGetIntOption(pOption, COIN_INT_MIPCUT_CLIQUE)) {
710                pCbc->clique= new CglClique(coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_PACKING) ? true : false);
711                if (coinGetOptionChanged(pOption, COIN_INT_MIPCLIQUE_STAR))             pCbc->clique->setDoStarClique(coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_STAR) ? true : false);
712                if (coinGetOptionChanged(pOption, COIN_INT_MIPCLIQUE_STARMETHOD))       pCbc->clique->setStarCliqueNextNodeMethod((CglClique::scl_next_node_method)coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_STARMETHOD));
713                if (coinGetOptionChanged(pOption, COIN_INT_MIPCLIQUE_STARMAXLEN))       pCbc->clique->setStarCliqueCandidateLengthThreshold(coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_STARMAXLEN));
714                if (coinGetOptionChanged(pOption, COIN_INT_MIPCLIQUE_STARREPORT))       pCbc->clique->setStarCliqueReport(coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_STARREPORT) ? true : false);
715                if (coinGetOptionChanged(pOption, COIN_INT_MIPCLIQUE_ROW))              pCbc->clique->setDoRowClique(coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_ROW) ? true : false);
716                if (coinGetOptionChanged(pOption, COIN_INT_MIPCLIQUE_ROWMAXLEN))        pCbc->clique->setRowCliqueCandidateLengthThreshold(coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_ROWMAXLEN));
717                if (coinGetOptionChanged(pOption, COIN_INT_MIPCLIQUE_ROWREPORT))        pCbc->clique->setRowCliqueReport(coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_ROWREPORT) ? true : false);
718                if (coinGetOptionChanged(pOption, COIN_REAL_MIPCLIQUE_MINVIOL)) pCbc->clique->setMinViolation(coinGetRealOption(pOption, COIN_REAL_MIPCLIQUE_MINVIOL));
719                pCbc->cbc->addCutGenerator(pCbc->clique,coinGetIntOption(pOption, COIN_INT_MIPCLIQUE_FREQ),"Clique");
720        }
721
722        if (coinGetIntOption(pOption, COIN_INT_MIPCUT_LIFTPROJECT)) {
723                pCbc->liftpro = new CglLiftAndProject();
724                if (coinGetOptionChanged(pOption, COIN_INT_MIPLIFTPRO_BETAONE)) pCbc->liftpro->setBeta(coinGetIntOption(pOption, COIN_INT_MIPLIFTPRO_BETAONE) ? 1 : -1);
725                pCbc->cbc->addCutGenerator(pCbc->liftpro,coinGetIntOption(pOption, COIN_INT_MIPLIFTPRO_FREQ),"LiftProject");
726        }
727
728        if (coinGetIntOption(pOption, COIN_INT_MIPCUT_SIMPROUND)) {
729                pCbc->rounding = new CglSimpleRounding();
730                pCbc->cbc->addCutGenerator(pCbc->rounding,coinGetIntOption(pOption, COIN_INT_MIPSIMPROUND_FREQ),"Rounding");
731        }
732        return 1;
733}
734
735
736/************************************************************************/
737/*  Setup CBC Objects                                                  */
738/************************************************************************/
739
740
741void CbcCopyNamesList(HCBC hCbc, PPROBLEM pProblem)
742{
743        int i;
744        PCBC pCbc = (PCBC)hCbc;
745
746        /* Load names */
747        if (pProblem->RowNamesList || pProblem->ColNamesList) {
748                std::vector<std::string> rowNamesVect;
749                std::vector<std::string> colNamesVect;
750                rowNamesVect.reserve(pProblem->RowCount);
751                colNamesVect.reserve(pProblem->ColCount);
752                if (pProblem->RowNamesList) {
753                        for (i = 0; i < pProblem->RowCount; i++) {
754                                rowNamesVect.push_back(pProblem->RowNamesList[i]);
755                        }
756                }
757                if (pProblem->ColNamesList) {
758                        for (i = 0; i < pProblem->ColCount; i++) {
759                                colNamesVect.push_back(pProblem->ColNamesList[i]);
760                        }
761                }
762                pCbc->clp->copyNames(rowNamesVect, colNamesVect);
763        }
764}
765
766
767int CbcSetColumnIntegers(HCBC hCbc, PPROBLEM pProblem)
768{
769        int i;
770        PCBC pCbc = (PCBC)hCbc;
771
772        if (pProblem->numInts == 0) {
773                return CBC_CALL_FAILED;
774        }
775        for (i = 0; i < pProblem->ColCount; i++) {
776                if (pProblem->IsInt[i]) {
777                        pCbc->cbc->solver()->setInteger(i);
778                        pCbc->osi->setInteger(i);
779                }
780        }
781        return CBC_CALL_SUCCESS;
782}
783
784
785int CbcAddPriorObjects(HCBC hCbc, PPROBLEM pProblem)
786{
787        int *priorVar;
788        int *priorCbc;
789        int i,k;
790        PCBC pCbc = (PCBC)hCbc;
791
792        if ((pProblem->PriorCount == 0) || (pProblem->numInts == 0)) {
793                return CBC_CALL_FAILED;
794        }
795        priorVar = (int *)malloc(pProblem->ColCount * sizeof(int));
796        if (!priorVar) {
797                return CBC_CALL_FAILED;
798        }
799        //reset the priorVar
800        for (i = 0; i < pProblem->ColCount; i++) {
801                priorVar[i] = 1000;
802        }
803        for (i = 0; i < pProblem->PriorCount; i++) {
804                if ((pProblem->PriorIndex[i] < 0) || 
805                        (pProblem->PriorIndex[i] >= pProblem->ColCount)) {
806                        free(priorVar);
807                        return CBC_CALL_FAILED;
808                }
809                priorVar[pProblem->PriorIndex[i]] = pProblem->PriorValues[i];
810        }
811        //Create an array to give to cbc
812        priorCbc = (int *)malloc(pProblem->numInts * sizeof(int));
813        if (!priorCbc) {
814                free(priorVar);
815                return CBC_CALL_FAILED;
816        }
817        k = 0;
818        for (i = 0; i < pProblem->ColCount; i++) {
819                if (pProblem->IsInt[i]) {
820                        priorCbc[k++] = priorVar[i];
821                }
822        }
823        pCbc->cbc->passInPriorities(priorCbc, false);
824        free(priorCbc);
825        free(priorVar);
826        return CBC_CALL_SUCCESS;
827}
828
829
830int CbcAddSosObjects(HCBC hCbc, PPROBLEM pProblem)
831{
832        int sos, count;
833        int* which;
834        int type;
835        PCBC pCbc = (PCBC)hCbc;
836
837        if (pProblem->SosCount == 0) {
838                return CBC_CALL_FAILED;
839        }
840        for (sos = 0; sos < pProblem->SosCount; sos++) {
841                count = pProblem->SosBegin[sos+1] - pProblem->SosBegin[sos];
842                which = &pProblem->SosIndex[pProblem->SosBegin[sos]];
843                type = pProblem->SosType[sos];
844                CbcObject *sosObject = new CbcSOS(pCbc->cbc, count, which, NULL, 0, type);
845                pCbc->cbc->addObjects(1, &sosObject);
846                delete sosObject;
847        }
848        return CBC_CALL_SUCCESS;
849}
850
851
852int CbcAddSemiContObjects(HCBC hCbc, PPROBLEM pProblem)
853{
854        double points[4];
855        int i, semicol;
856        PCBC pCbc = (PCBC)hCbc;
857
858        if (pProblem->SemiCount == 0) {
859                return CBC_CALL_FAILED;
860        }
861        points[0] = 0.0;
862        points[1] = 0.0;
863        for (i = 0; i < pProblem->SemiCount; i++ ) {
864                semicol = pProblem->SemiIndex[i];
865                points[2] = pProblem->LowerBounds[semicol];
866                points[3] = pProblem->UpperBounds[semicol];
867                CbcObject *semiObject = new CbcLotsize(pCbc->cbc, semicol, 2, points, true);
868                pCbc->cbc->addObjects(1, &semiObject);
869                delete semiObject;
870        }
871        return CBC_CALL_SUCCESS;
872}
873
874
875
876int CbcLoadAllSolverObjects(HCBC hCbc, PPROBLEM pProblem)
877{
878        PCBC pCbc = (PCBC)hCbc;
879        int i, col;
880        int result;
881        double* storeLowerBound = NULL;
882
883        if (pProblem->SemiCount > 0) { 
884                storeLowerBound = (double *)malloc(pProblem->ColCount * sizeof(double));
885                if (!storeLowerBound) {
886                        return CBC_CALL_FAILED;
887                }
888                memcpy(storeLowerBound, pProblem->LowerBounds, pProblem->ColCount * sizeof(double));
889                for (i = 0; i < pProblem->SemiCount; i++) {
890                        col = pProblem->SemiIndex[i];
891                        pProblem->LowerBounds[col] = 0.0;
892                }
893        }
894        pCbc->clp->setOptimizationDirection(pProblem->ObjectSense);
895        pCbc->clp->loadProblem(pProblem->ColCount, pProblem->RowCount, 
896                                                        pProblem->MatrixBegin, pProblem->MatrixIndex, pProblem->MatrixValues,
897                                                        pProblem->LowerBounds, pProblem->UpperBounds, pProblem->ObjectCoeffs, 
898                                                        pProblem->RowLower, pProblem->RowUpper);
899        if (pProblem->SemiCount > 0) { 
900                memcpy(pProblem->LowerBounds, storeLowerBound, pProblem->ColCount * sizeof(double));
901                free(storeLowerBound);
902        }
903        CbcCopyNamesList(hCbc, pProblem);
904        if (pProblem->SolveAsMIP) {
905                if (!pCbc->cbc) {
906                        pCbc->cbc = new CbcModel(*pCbc->osi);
907                }
908                result = CbcSetColumnIntegers(hCbc, pProblem);
909                result = CbcAddPriorObjects(hCbc, pProblem);
910                result = CbcAddSosObjects(hCbc, pProblem);
911                result = CbcAddSemiContObjects(hCbc, pProblem);
912        }
913        return CBC_CALL_SUCCESS;
914}
915
916
917
918extern int CbcOrClpRead_mode;
919
920int CbcSolveProblem(HCBC hCbc, PPROBLEM pProblem, POPTION pOption, int Method)
921{
922        PCBC pCbc = (PCBC)hCbc;
923
924        if (!pProblem->SolveAsMIP) {
925                CbcSetClpOptions(hCbc, pOption);
926                if (coinGetOptionChanged(pOption, COIN_INT_PRESOLVETYPE))                       
927                        pCbc->clp->initialSolve(*pCbc->clp_presolve);
928                else {
929                        pCbc->clp->initialSolve();
930                }
931                }
932        else {
933#ifdef NEW_STYLE_CBCMAIN
934                if (coinGetIntOption(pOption, COIN_INT_MIPUSECBCMAIN)) {
935                        CbcMain0(*pCbc->cbc);
936                        CbcSetClpOptions(hCbc, pOption);
937                        CbcSetCbcOptions(hCbc, pOption);
938                        //CbcSetCglOptions(hProb);  BK: CbcMain1 will call the Cgl's automatically
939                        CbcOrClpRead_mode = 1;  // BK: Fix bug in CbcMain1, CbcOrClpRead_mode not initialized  (CpcSolver.cpp, stable 2.2)
940                        int logLevel = coinGetIntOption(pOption, COIN_INT_LOGLEVEL);
941                        if (logLevel == 1) {
942                                const int argc = 3;
943                                const char* argv[] = {"CoinMP", "-solve", "-quit"};
944                                CbcMain1(argc, argv, *pCbc->cbc);
945                                }
946                        else {
947                                char logstr[100];  // BK 2013/11/28: Allows setting the log level from CoinMP. Thanks to Miles Lubin for suggesting this
948                                sprintf(logstr, "%d", logLevel);
949                                const int argc = 5;
950                                const char* argv[] = {"CoinMP", "-log", logstr, "-solve", "-quit"};
951                                CbcMain1(argc, argv, *pCbc->cbc);
952                        }
953                        }
954                else 
955#endif
956                {
957                        CbcSetClpOptions(hCbc, pOption);
958                        CbcSetCbcOptions(hCbc, pOption);
959                        CbcSetCglOptions(hCbc, pOption);
960
961                        pCbc->cbc->initialSolve();
962                        pCbc->cbc->branchAndBound();
963                }
964        }
965        return CBC_CALL_SUCCESS;
966}
967
968
969int CbcRetrieveSolutionResults(HCBC hCbc, PPROBLEM pProblem, PRESULT pResult)
970{
971        PCBC pCbc = (PCBC)hCbc;
972        const double* columnPrimal;
973        const double* columnDual;
974        const double* rowPrimal;
975        const double* rowDual;
976        int i;
977
978        if (!pProblem->SolveAsMIP) {
979                pResult->SolutionStatus = pCbc->clp->status();
980                pResult->ObjectValue    = pCbc->clp->objectiveValue();
981                pResult->MipBestBound   = 0.0;
982                pResult->IterCount      = pCbc->clp->numberIterations();
983                pResult->MipNodeCount     = 0;
984                }
985        else {
986                pResult->SolutionStatus = pCbc->cbc->status();
987                pResult->ObjectValue    = pCbc->cbc->getObjValue();
988                pResult->MipBestBound   = pCbc->cbc->getBestPossibleObjValue();
989                pResult->IterCount      = pCbc->cbc->getIterationCount();
990                pResult->MipNodeCount   = pCbc->cbc->getNodeCount();
991        }
992
993        switch (pResult->SolutionStatus) {
994                case 0: strcpy(pResult->SolutionText, "Optimal solution found");                break;
995                case 1: strcpy(pResult->SolutionText, "Problem primal infeasible");     break;
996                case 2: strcpy(pResult->SolutionText, "Problem dual infeasible");               break;
997                case 3: strcpy(pResult->SolutionText, "Stopped on iterations");                 break;
998                case 4: strcpy(pResult->SolutionText, "Stopped due to errors");                 break;
999                case 5: strcpy(pResult->SolutionText, "Stopped by user");               break;
1000                default: 
1001                        sprintf(pResult->SolutionText, "Unknown CBC solution status (%d)", pResult->SolutionStatus);
1002                        break;
1003        }
1004
1005        if (!pProblem->SolveAsMIP) {
1006                columnPrimal = pCbc->clp->primalColumnSolution();
1007                columnDual = pCbc->clp->dualColumnSolution();
1008                rowPrimal = pCbc->clp->primalRowSolution();
1009                rowDual = pCbc->clp->dualRowSolution();
1010                pResult->ColActivity = (double*) malloc(pProblem->ColCount * sizeof(double));
1011                pResult->ReducedCost = (double*) malloc(pProblem->ColCount * sizeof(double));
1012                pResult->RowActivity = (double*) malloc(pProblem->RowCount * sizeof(double));
1013                pResult->SlackValues = (double*) malloc(pProblem->RowCount * sizeof(double));
1014                pResult->ShadowPrice = (double*) malloc(pProblem->RowCount * sizeof(double));
1015                if (!pResult->ColActivity ||
1016                        !pResult->ReducedCost || 
1017                        !pResult->RowActivity || 
1018                        !pResult->SlackValues || 
1019                        !pResult->ShadowPrice) {
1020                        return CBC_CALL_FAILED;
1021                }
1022                memcpy(pResult->ColActivity, columnPrimal, pProblem->ColCount * sizeof(double));
1023                memcpy(pResult->ReducedCost, columnDual, pProblem->ColCount * sizeof(double));
1024                memcpy(pResult->RowActivity, rowPrimal, pProblem->RowCount * sizeof(double));
1025                memcpy(pResult->ShadowPrice, rowDual, pProblem->RowCount * sizeof(double));
1026                for (i = 0; i < pProblem->RowCount; i++) {
1027                        pResult->SlackValues[i] = pProblem->RHSValues[i] - pResult->RowActivity[i];
1028                }
1029                }
1030        else {
1031                columnPrimal = pCbc->cbc->solver()->getColSolution();
1032                pResult->ColActivity = (double*) malloc(pProblem->ColCount * sizeof(double));
1033                if (!pResult->ColActivity) {
1034                        return CBC_CALL_FAILED;
1035                }
1036                memcpy(pResult->ColActivity, columnPrimal, pProblem->ColCount * sizeof(double));
1037        }
1038        return CBC_CALL_SUCCESS;
1039}
1040
1041
1042
1043int CbcOptimizeProblem(PPROBLEM pProblem, PRESULT pResult, PSOLVER pSolver, POPTION pOption, int Method)
1044{               
1045        HCBC hCbc;
1046        int result;
1047
1048        hCbc = CbcCreateSolverObject();
1049        result = CbcLoadAllSolverObjects(hCbc, pProblem);
1050        result = CbcSetAllCallbacks(hCbc, pSolver, pOption);
1051        result = CbcSolveProblem(hCbc, pProblem, pOption, Method);
1052        result = CbcRetrieveSolutionResults(hCbc, pProblem, pResult);
1053        CbcClearSolverObject(hCbc);
1054        return CBC_CALL_SUCCESS;
1055}
1056
1057
1058int CbcReadMpsFile(PPROBLEM pProblem, const char *ReadFilename)
1059{
1060        PCBC pCbc;
1061        HCBC hCbc;
1062
1063        hCbc = CbcCreateSolverObject();
1064        pCbc = (PCBC)hCbc;
1065        pCbc->clp->readMps(ReadFilename, 1, 0); 
1066        CbcClearSolverObject(hCbc);
1067        return CBC_CALL_SUCCESS;
1068}
1069
1070
1071int CbcWriteMpsFile(PPROBLEM pProblem, const char *WriteFilename)
1072{
1073        int result;
1074        PCBC pCbc;
1075        HCBC hCbc;
1076        const char* extension;
1077
1078        hCbc = CbcCreateSolverObject();
1079        pCbc = (PCBC)hCbc;
1080        result = CbcLoadAllSolverObjects(hCbc, pProblem);
1081        if (strstr(WriteFilename, ".mps") == NULL)
1082                extension = "mps";
1083        else {
1084                extension = "";
1085        }
1086        pCbc->osi->writeMps(WriteFilename, extension, pProblem->ObjectSense); 
1087        //result = CbcClearAllSolverObjects(hCbc);
1088        CbcClearSolverObject(hCbc);
1089        return CBC_CALL_SUCCESS;
1090}
1091
1092
1093
1094/************************************************************************/
1095/*  Option Table                                                        */
1096/************************************************************************/
1097
1098#define OPTIONCOUNT    68
1099
1100
1101SOLVOPTINFO OptionTable[OPTIONCOUNT] = {
1102
1103        {"SolveMethod",            "SolveMethod",  GRP_SIMPLEX,        0,        0,      0,       5,  OPT_LIST,   0,   COIN_INT_SOLVEMETHOD},
1104      /*enum SolveType { useDual=0, usePrimal, usePrimalorSprint, useBarrier, useBarrierNoCross, automatic*/
1105        {"PresolveType",           "Presolve",     GRP_SIMPLEX,        0,        0,      0,       2,  OPT_LIST,   0,   COIN_INT_PRESOLVETYPE},
1106      /*enum PresolveType { presolveOn=0, presolveOff, presolveNumber }; */
1107        {"Scaling",                "Scaling",      GRP_SIMPLEX,        3,        3,      0,       4,  OPT_LIST,   0,   COIN_INT_SCALING}, 
1108      /* Sets or unsets scaling, 0 -off, 1 equilibrium, 2 geometric, 3, auto, 4 dynamic(later) */
1109        {"Perturbation",           "Perturb",      GRP_SIMPLEX,      100,      100,      0,     100,  OPT_INT,    0,   COIN_INT_PERTURBATION}, 
1110      /* 0 - Off, 50 - On, 100 - Only if clp stalls */
1111        {"PrimalColPivotAlg",      "PrimPivAlg",   GRP_SIMPLEX,        1,        1,      0,       4,  OPT_LIST,   0,   COIN_INT_PRIMALPIVOTALG}, 
1112      /*0 is exact devex, 1 full steepest, 2 is partial exact devex
1113        3 switches between 0 and 2 depending on factorization
1114        4 starts as partial dantzig/devex but then may switch between 0 and 2.*/
1115        {"DualRowPivotAlg",        "DualPivAlg",   GRP_SIMPLEX,        1,        1,      0,       3,  OPT_LIST,   0,   COIN_INT_DUALPIVOTALG}, 
1116      /*0 is uninitialized, 1 full, 2 is partial uninitialized,
1117        3 starts as 2 but may switch to 1.*/
1118        {"LogLevel",               "LogLevel",     GRP_LOGFILE,        1,        1,      0,       4,  OPT_LIST,   0,   COIN_INT_LOGLEVEL}, 
1119        {"MaxIterations",          "MaxIter",      GRP_LIMITS,  99999999, 99999999,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MAXITER}, 
1120        {"MaxSeconds",             "MaxSeconds",   GRP_LIMITS,      -1.0,     -1.0,   -1.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_MAXSECONDS}, 
1121
1122        {"CrashInd",               "CrashInd",     GRP_SIMPLEX,        0,        0,      0,       1,  OPT_ONOFF,  0,   COIN_INT_CRASHIND}, 
1123        {"CrashPivot",             "CrashPivot",   GRP_SIMPLEX,        0,        0,     -1,       2,  OPT_LIST,   0,   COIN_INT_CRASHPIVOT}, 
1124        {"CrashGap",               "CrashGap",     GRP_SIMPLEX,   1000.0,   1000.0,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_CRASHGAP}, 
1125        {"PrimalObjectLimit",      "PrimalObjLim", GRP_SIMPLEX,  MAXREAL,  MAXREAL,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_PRIMALOBJLIM}, 
1126        {"DualObjectLimit",        "DualObjLim",   GRP_SIMPLEX,  MAXREAL,  MAXREAL,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_DUALOBJLIM}, 
1127        {"PrimalTolerance",        "PrimalTol",    GRP_SIMPLEX,     1e-7,     1e-7,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_PRIMALOBJTOL}, 
1128        {"DualTolerance",          "DualTol",      GRP_SIMPLEX,     1e-7,     1e-7,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_DUALOBJTOL}, 
1129
1130        {"MipMaxNodes",            "MipMaxNodes",  GRP_LIMITS,   9999999,  9999999,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPMAXNODES}, 
1131        {"MipMaxSolutions",        "MipMaxSol",    GRP_LIMITS,   9999999,  9999999,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPMAXSOL}, 
1132        {"MipMaxSeconds",          "MipMaxSec",    GRP_LIMITS,     1e100,    1e100,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_MIPMAXSEC}, 
1133
1134        {"MipFathomDiscipline",    "FathomDisc",   GRP_MIPSTRAT,       0,        0,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPFATHOMDISC}, 
1135        {"MipHotStart",            "HotStart",     GRP_MIPSTRAT,       0,        0,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPHOTSTART},
1136//      {"MipForcePriority",       "ForcePrior",   GRP_MIPSTRAT,      -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPFORCEPRIOR},
1137        {"MipMinimumDrop",         "MinimumDrop",  GRP_MIPSTRAT,    1e-4,     1e-4,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPMINIMUMDROP},
1138        {"MipMaxCutPasses",        "MaxCutPass",   GRP_MIPSTRAT,       2,        2,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPMAXCUTPASS},
1139        {"MipMaxCutPassAtRoot",    "MaxPassRoot",  GRP_MIPSTRAT,      50,       50,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPMAXPASSROOT},
1140        {"MipStrongBranching",     "StrongBranch", GRP_MIPSTRAT,       5,        5,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPSTRONGBRANCH},
1141        {"MipScanGlobalCuts",      "ScanGlobCuts", GRP_MIPSTRAT,       1,        1,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPSCANGLOBCUTS},
1142
1143        {"MipIntegerTolerance",    "MipIntTol",    GRP_MIPTOL,      1e-6,     1e-6,    0.0,     1.0,  OPT_REAL,   0,   COIN_REAL_MIPINTTOL}, 
1144        {"MipInfeasWeight",        "MipInfWeight", GRP_MIPTOL,       0.0,      0.0,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_MIPINFWEIGHT}, 
1145        {"MipCutoffIncrement",     "MipCutIncr",   GRP_MIPTOL,      1e-5,     1e-5,    0.0,     1.0,  OPT_REAL,   0,   COIN_REAL_MIPCUTOFF}, 
1146        {"MipAllowableGap",        "MipAbsGap",    GRP_MIPTOL,     1e-10,    1e-10,    0.0, MAXREAL,  OPT_REAL,   0,   COIN_REAL_MIPABSGAP}, 
1147        {"MipFractionalGap",       "MipFracGap",   GRP_MIPTOL,     1e-10,    1e-10,    0.0,     1.0,  OPT_REAL,   0,   COIN_REAL_MIPFRACGAP}, 
1148
1149        /* Probing */
1150        {"MipCutProbing",          "CutProbing",   GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCUT_PROBING},
1151        {"MipProbeFrequency",      "ProbeFreq",    GRP_MIPCUTS,       -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPPROBE_FREQ},
1152        {"MipProbeMode",           "ProbeMode",    GRP_MIPCUTS,        1,        1,      0,       2,  OPT_LIST,   0,   COIN_INT_MIPPROBE_MODE},
1153        {"MipProbeUseObjective",   "UseObject",    GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPPROBE_USEOBJ},
1154        {"MipProbeMaxPass",        "MaxPass",      GRP_MIPCUTS,        3,        3,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPPROBE_MAXPASS},
1155        {"MipProbeMaxProbe",       "MaxProbe",     GRP_MIPCUTS,      100,      100,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPPROBE_MAXPROBE},
1156        {"MipProbeMaxLook",        "MaxLook",      GRP_MIPCUTS,       50,       50,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPPROBE_MAXLOOK},
1157        {"MipProbeRowCuts",        "RowCuts",      GRP_MIPCUTS,        3,        3,      0,       3,  OPT_LIST,   0,   COIN_INT_MIPPROBE_ROWCUTS},
1158
1159        /* Gomory cuts */
1160        {"MipCutGomory",           "CutGomory",    GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCUT_GOMORY},
1161        {"MipGomoryFrequency",     "GomoryFreq",   GRP_MIPCUTS,       -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPGOMORY_FREQ},
1162        {"MipGomoryLimit",         "GomoryLimit",  GRP_MIPCUTS,       50,       50,      1,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPGOMORY_LIMIT},
1163        {"MipGomoryAway",          "GomoryAway",   GRP_MIPCUTS,     0.05,     0.05, 0.0001,     0.5,  OPT_REAL,   0,   COIN_REAL_MIPGOMORY_AWAY},
1164
1165        /* Knapsack cuts */
1166        {"MipCutKnapsack",         "CutKnapsack",  GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCUT_KNAPSACK},
1167        {"MipKnapsackFrequency",   "KrapsackFreq", GRP_MIPCUTS,       -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPKNAPSACK_FREQ},
1168        {"MipKnapsackMaxIn",       "KnapsackMaxIn",GRP_MIPCUTS,       50,       50,      1,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPKNAPSACK_MAXIN},
1169
1170        /* Oddhole cuts */
1171        {"MipCutOddHole",          "CutOddHole",   GRP_MIPCUTS,        0,        0,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCUT_ODDHOLE},
1172        {"MipOddHoleFrequency",    "OddHoleFreq",  GRP_MIPCUTS,       -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPODDHOLE_FREQ},
1173        {"MipOddHoleMinViolation", "MinViolation", GRP_MIPCUTS,    0.001,    0.001,1.01e-8,     0.5,  OPT_REAL,   0,   COIN_REAL_MIPODDHOLE_MINVIOL},
1174        {"MipOddHoleMinViolPer",   "MinViolPer",   GRP_MIPCUTS,   0.0003,   0.0003,1.01e-8,    0.25,  OPT_REAL,   0,   COIN_REAL_MIPODDHOLE_MINVIOLPER},
1175        {"MipOddHoleMaxEntries",   "MaxEntries",   GRP_MIPCUTS,      100,      100,      3,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPODDHOLE_MAXENTRIES},
1176
1177        /* Clique cuts */
1178        {"MipCutClique",           "CutClique",    GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCUT_CLIQUE},
1179        {"MipCliqueFrequency",     "CliqueFreq",   GRP_MIPCUTS,       -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPCLIQUE_FREQ},
1180        {"MipCliquePacking",       "CliquePacking",GRP_MIPCUTS,        0,        0,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCLIQUE_PACKING},
1181        {"MipCliqueStar",          "CliqueStar",   GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCLIQUE_STAR},
1182        {"MipCliqueStarMethod",    "StarMethod",   GRP_MIPCUTS,        2,        2,      0,       2,  OPT_LIST,   0,   COIN_INT_MIPCLIQUE_STARMETHOD},
1183        {"MipCliqueStarMaxLen",    "StarMaxLen",   GRP_MIPCUTS,       12,       12,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPCLIQUE_STARMAXLEN},
1184        {"MipCliqueStarReport",    "StarReport",   GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCLIQUE_STARREPORT},
1185        {"MipCliqueRow",           "CliqueRow",    GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCLIQUE_ROW},
1186        {"MipCliqueRowMaxLen",     "ClqRowMaxLen", GRP_MIPCUTS,       12,       12,      0,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPCLIQUE_ROWMAXLEN},
1187        {"MipCliqueRowReport",     "ClqRowReport", GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCLIQUE_ROWREPORT},
1188        {"MipCliqueMinViolation",  "ClqMinViol",   GRP_MIPCUTS,     -1.0,     -1.0,-MAXREAL,MAXREAL,  OPT_REAL,   0,   COIN_REAL_MIPCLIQUE_MINVIOL},
1189
1190        /* Lift and Project */
1191        {"MipCutLiftAndProject",   "CutLiftPro",   GRP_MIPCUTS,        0,        0,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCUT_LIFTPROJECT},
1192        {"MipLiftCoverFrequency",  "LiftProFreq",  GRP_MIPCUTS,       -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPLIFTPRO_FREQ},
1193        {"MipLiftCoverBetaOne",    "LiftProBeta",  GRP_MIPCUTS,        1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPLIFTPRO_BETAONE},
1194
1195        /* Simple Rounding */
1196        {"MipCutSimpleRounding",   "CutSimpRound", GRP_MIPCUTS,        0,        0,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPCUT_SIMPROUND},
1197        {"MipSimpleRoundFrequency","SimpRoundFreq",GRP_MIPCUTS,       -1,       -1,-MAXINT,  MAXINT,  OPT_INT,    0,   COIN_INT_MIPSIMPROUND_FREQ},
1198
1199        {"MipUseCbcMain",          "UseCbcMain",   GRP_MIPSTRAT,       1,        1,      0,       1,  OPT_ONOFF,  0,   COIN_INT_MIPUSECBCMAIN}
1200        };
1201
1202int CbcGetOptionCount(void)
1203{
1204        return OPTIONCOUNT;
1205}
1206
1207
1208SOLVOPTINFO *CbcGetOptionTable(void)
1209{
1210        return &OptionTable[0];
1211}
1212
1213
1214
1215int CbcGetOptionID(int OptionNr)
1216{
1217        if ((OptionNr < 0) || (OptionNr >= OPTIONCOUNT)) {
1218                return -1;
1219        }
1220        return OptionTable[OptionNr].OptionID;
1221}
1222
1223int CbcLocateOptionID(int OptionID)
1224{
1225        int i;
1226        SOLVOPTINFO *OptionTable;
1227
1228        OptionTable = CbcGetOptionTable();
1229        for (i = 0; i < CbcGetOptionCount(); i++) {
1230                if (OptionID == OptionTable[i].OptionID) {
1231                        return i;
1232                }
1233        }
1234        return -1;
1235}
1236
1237SOLVOPTINFO *CbcGetOptionEntry(int OptionID)
1238{
1239        int OptionNr;
1240        SOLVOPTINFO *OptionTable;
1241
1242        OptionTable = CbcGetOptionTable();
1243        OptionNr = CbcLocateOptionID(OptionID);
1244        if (OptionNr < 0) {
1245                return NULL;
1246        }
1247        return &OptionTable[OptionNr];
1248}
1249
1250
1251int CbcGetOptionChanged(int OptionID)
1252{
1253        SOLVOPTINFO *OptionEntry;
1254
1255        OptionEntry = CbcGetOptionEntry(OptionID);
1256        if (!OptionEntry) {
1257                return 0;
1258        }
1259        return OptionEntry->changed;
1260}
1261
1262
1263int CbcGetIntOption(int OptionID)
1264{   
1265        SOLVOPTINFO *OptionEntry;
1266
1267        OptionEntry = CbcGetOptionEntry(OptionID);
1268        if (!OptionEntry) {
1269                return 0;
1270        }
1271        if (OptionEntry->OptionType == OPT_REAL) {
1272                return 0;
1273        }
1274        return (int)OptionEntry->CurrentValue;
1275}
1276       
1277int CbcSetIntOption(int OptionID, int IntValue)
1278{
1279        SOLVOPTINFO *OptionEntry;
1280
1281        OptionEntry = CbcGetOptionEntry(OptionID);
1282        if (!OptionEntry) {
1283                return CBC_CALL_FAILED;
1284        }
1285        if (OptionEntry->OptionType == OPT_REAL) {
1286                return CBC_CALL_FAILED;
1287        }
1288        //coinWriteMsgLog("%s[%d] = %d (was %d)",OptionEntry->OptionName, OptionNr, IntValue, (int)OptionEntry->CurrentValue);
1289        OptionEntry->CurrentValue = IntValue;
1290        OptionEntry->changed = 1;
1291        return CBC_CALL_SUCCESS;
1292}
1293
1294
1295double CbcGetRealOption(int OptionID)
1296{
1297        SOLVOPTINFO *OptionEntry;
1298
1299        OptionEntry = CbcGetOptionEntry(OptionID);
1300        if (!OptionEntry) {
1301                return 0.0;
1302        }
1303        if (OptionEntry->OptionType != OPT_REAL) {
1304                return 0.0;
1305        }
1306        return OptionEntry->CurrentValue;
1307}
1308
1309
1310int CbcSetRealOption(int OptionID, double RealValue)
1311{
1312        SOLVOPTINFO *OptionEntry;
1313
1314        OptionEntry = CbcGetOptionEntry(OptionID);
1315        if (!OptionEntry) {
1316                return CBC_CALL_FAILED;
1317        }
1318        if (OptionEntry->OptionType != OPT_REAL) {
1319                return CBC_CALL_FAILED;
1320        }
1321        //coinWriteMsgLog("%s[%d] = %lg (was %lg)",OptionTable[OptionNr].OptionName, OptionNr, RealValue, OptionTable[OptionNr].CurrentValue);
1322        OptionEntry->CurrentValue = RealValue;
1323        OptionEntry->changed = 1;
1324        return CBC_CALL_SUCCESS;
1325}
1326
1327//double
1328// DualTolerance
1329// PrimalTolerance
1330// DualBound
1331// PrimalWeight (setInfeasibilityCost)
1332// MaxTime      (setMaximumSeconds)
1333// ObjScale     (setObjectiveScale)
1334// RhsScale     (setRhsScale)
1335
1336//int
1337//LogLevel      (setLogLovel/model->factorization()->messageLevel(8);)
1338//MaxFactor     (model->factorization()->maximumPivots(value);
1339//PertValue     (setPerturbation)
1340//MaxIteration  (setMaximumIterations)
1341
1342//AutoScale     off
1343//Barrier
1344//BiasLU        UU  (UX, LX, LL)
1345//Crash         off
1346//Direction     min
1347//Directory
1348//dualBound     1e-20, 1e12
1349//dualPivot     Automatic, (Dantzig, partial, Steepest)
1350//DualSimplex
1351//dualTolerance 1e-20,1e12
1352//Exit
1353//ErrorsAllowed
1354//FakeBound
1355//Help
1356//Idiot
1357//Import
1358//KeepNames
1359//LogLevel
1360//Maximize
1361//MaxFactor     1, 999999
1362//MaxIteration  0, 99999999
1363//Messages
1364//ObjScale      -1e20, 1e20
1365//PresolvePass  0, 100
1366//PertValue     -5000, 102, false
1367//Perturbation  On, off
1368//PlusMinus     -1, false
1369//Presolve      On
1370//PrimalPivot     Automatic, (Dantzig, partial, Steepest, change, sprint)
1371//PrimalSimplex
1372//PrimalTolerance 1e-20,1e12
1373//PrimalWeight    1e20, 1e20
1374//RhsScale        -1e20, 1.20
1375//Scaling         Off, Equilibrium, geometric, automatic
1376//MaxTime         0.0, 1e12
1377//SparseFactor    On, Off
1378//SprintCrash     -1, 500
1379
Note: See TracBrowser for help on using the repository browser.