source: trunk/CoinMP/src/CoinCbc.cpp @ 524

Last change on this file since 524 was 447, checked in by bjarni, 8 years ago

Reverting back to void* from const void* for callback UserParam? argument

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