source: trunk/Cbc/src/CbcModel.hpp @ 1623

Last change on this file since 1623 was 1623, checked in by forrest, 9 years ago

allow for elapsed time on unix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 96.1 KB
Line 
1/* $Id: CbcModel.hpp 1623 2011-03-25 19:05:04Z forrest $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#ifndef CbcModel_H
7#define CbcModel_H
8#include <string>
9#include <vector>
10#include "CoinFinite.hpp"
11#include "CoinMessageHandler.hpp"
12#include "OsiSolverInterface.hpp"
13#include "OsiBranchingObject.hpp"
14#include "OsiCuts.hpp"
15#include "CoinWarmStartBasis.hpp"
16#include "CbcCompareBase.hpp"
17#include "CbcMessage.hpp"
18#include "CbcEventHandler.hpp"
19#include "ClpDualRowPivot.hpp"
20
21//class OsiSolverInterface;
22
23class CbcCutGenerator;
24class CbcBaseModel;
25class OsiRowCut;
26class OsiBabSolver;
27class OsiRowCutDebugger;
28class CglCutGenerator;
29class CglStored;
30class CbcCutModifier;
31class CglTreeProbingInfo;
32class CbcHeuristic;
33class OsiObject;
34class CbcThread;
35class CbcTree;
36class CbcStrategy;
37class CbcFeasibilityBase;
38class CbcStatistics;
39class CbcEventHandler ;
40class CglPreProcess;
41# ifdef COIN_HAS_CLP
42class ClpNodeStuff;
43#endif
44// #define CBC_CHECK_BASIS 1
45
46//#############################################################################
47
48/** Simple Branch and bound class
49
50  The initialSolve() method solves the initial LP relaxation of the MIP
51  problem. The branchAndBound() method can then be called to finish using
52  a branch and cut algorithm.
53
54  <h3>Search Tree Traversal</h3>
55
56  Subproblems (aka nodes) requiring additional evaluation are stored using
57  the CbcNode and CbcNodeInfo objects. Ancestry linkage is maintained in the
58  CbcNodeInfo object. Evaluation of a subproblem within branchAndBound()
59  proceeds as follows:
60  <ul>
61    <li> The node representing the most promising parent subproblem is popped
62         from the heap which holds the set of subproblems requiring further
63         evaluation.
64    <li> Using branching instructions stored in the node, and information in
65         its ancestors, the model and solver are adjusted to create the
66         active subproblem.
67    <li> If the parent subproblem will require further evaluation
68         (<i>i.e.</i>, there are branches remaining) its node is pushed back
69         on the heap. Otherwise, the node is deleted.  This may trigger
70         recursive deletion of ancestors.
71    <li> The newly created subproblem is evaluated.
72    <li> If the subproblem requires further evaluation, a node is created.
73         All information needed to recreate the subproblem (branching
74         information, row and column cuts) is placed in the node and the node
75         is added to the set of subproblems awaiting further evaluation.
76  </ul>
77  Note that there is never a node representing the active subproblem; the model
78  and solver represent the active subproblem.
79
80  <h3>Row (Constraint) Cut Handling</h3>
81
82  For a typical subproblem, the sequence of events is as follows:
83  <ul>
84    <li> The subproblem is rebuilt for further evaluation: One result of a
85         call to addCuts() is a traversal of ancestors, leaving a list of all
86         cuts used in the ancestors in #addedCuts_. This list is then scanned
87         to construct a basis that includes only tight cuts. Entries for
88         loose cuts are set to NULL.
89    <li> The subproblem is evaluated: One result of a call to solveWithCuts()
90         is the return of a set of newly generated cuts for the subproblem.
91         #addedCuts_ is also kept up-to-date as old cuts become loose.
92    <li> The subproblem is stored for further processing: A call to
93         CbcNodeInfo::addCuts() adds the newly generated cuts to the
94         CbcNodeInfo object associated with this node.
95  </ul>
96  See CbcCountRowCut for details of the bookkeeping associated with cut
97  management.
98*/
99
100class CbcModel  {
101
102public:
103
104    enum CbcIntParam {
105        /** The maximum number of nodes before terminating */
106        CbcMaxNumNode = 0,
107        /** The maximum number of solutions before terminating */
108        CbcMaxNumSol,
109        /** Fathoming discipline
110
111          Controls objective function comparisons for purposes of fathoming by bound
112          or determining monotonic variables.
113
114          If 1, action is taken only when the current objective is strictly worse
115          than the target. Implementation is handled by adding a small tolerance to
116          the target.
117        */
118        CbcFathomDiscipline,
119        /** Adjusts printout
120            1 does different node message with number unsatisfied on last branch
121        */
122        CbcPrinting,
123        /** Number of branches (may be more than number of nodes as may
124            include strong branching) */
125        CbcNumberBranches,
126        /** Just a marker, so that a static sized array can store parameters. */
127        CbcLastIntParam
128    };
129
130    enum CbcDblParam {
131        /** The maximum amount the value of an integer variable can vary from
132            integer and still be considered feasible. */
133        CbcIntegerTolerance = 0,
134        /** The objective is assumed to worsen by this amount for each
135            integer infeasibility. */
136        CbcInfeasibilityWeight,
137        /** The amount by which to tighten the objective function cutoff when
138            a new solution is discovered. */
139        CbcCutoffIncrement,
140        /** Stop when the gap between the objective value of the best known solution
141          and the best bound on the objective of any solution is less than this.
142
143          This is an absolute value. Conversion from a percentage is left to the
144          client.
145        */
146        CbcAllowableGap,
147        /** Stop when the gap between the objective value of the best known solution
148          and the best bound on the objective of any solution is less than this
149          fraction of of the absolute value of best known solution.
150
151          Code stops if either this test or CbcAllowableGap test succeeds
152        */
153        CbcAllowableFractionGap,
154        /** \brief The maximum number of seconds before terminating.
155               A double should be adequate! */
156        CbcMaximumSeconds,
157        /// Cutoff - stored for speed
158        CbcCurrentCutoff,
159        /// Optimization direction - stored for speed
160        CbcOptimizationDirection,
161        /// Current objective value
162        CbcCurrentObjectiveValue,
163        /// Current minimization objective value
164        CbcCurrentMinimizationObjectiveValue,
165        /** \brief The time at start of model.
166               So that other pieces of code can access */
167        CbcStartSeconds,
168        /** Stop doing heuristics when the gap between the objective value of the
169            best known solution and the best bound on the objective of any solution
170            is less than this.
171
172          This is an absolute value. Conversion from a percentage is left to the
173          client.
174        */
175        CbcHeuristicGap,
176        /** Stop doing heuristics when the gap between the objective value of the
177            best known solution and the best bound on the objective of any solution
178            is less than this fraction of of the absolute value of best known
179            solution.
180
181          Code stops if either this test or CbcAllowableGap test succeeds
182        */
183        CbcHeuristicFractionGap,
184        /// Smallest non-zero change on a branch
185        CbcSmallestChange,
186        /// Sum of non-zero changes on a branch
187        CbcSumChange,
188        /// Largest non-zero change on a branch
189        CbcLargestChange,
190        /// Small non-zero change on a branch to be used as guess
191        CbcSmallChange,
192        /** Just a marker, so that a static sized array can store parameters. */
193        CbcLastDblParam
194    };
195
196    //---------------------------------------------------------------------------
197
198public:
199    ///@name Solve methods
200    //@{
201    /** \brief Solve the initial LP relaxation
202
203      Invoke the solver's %initialSolve() method.
204    */
205    void initialSolve();
206
207    /** \brief Invoke the branch \& cut algorithm
208
209      The method assumes that initialSolve() has been called to solve the
210      LP relaxation. It processes the root node, then proceeds to explore the
211      branch & cut search tree. The search ends when the tree is exhausted or
212      one of several execution limits is reached.
213      If doStatistics is 1 summary statistics are printed
214      if 2 then also the path to best solution (if found by branching)
215      if 3 then also one line per node
216    */
217    void branchAndBound(int doStatistics = 0);
218private:
219
220    /** \brief Evaluate a subproblem using cutting planes and heuristics
221
222      The method invokes a main loop which generates cuts, applies heuristics,
223      and reoptimises using the solver's native %resolve() method.
224      It returns true if the subproblem remains feasible at the end of the
225      evaluation.
226    */
227    bool solveWithCuts(OsiCuts & cuts, int numberTries, CbcNode * node);
228    /** Generate one round of cuts - serial mode
229      returns -
230      0 - normal
231      1 - must keep going
232      2 - set numberTries to zero
233      -1 - infeasible
234    */
235    int serialCuts(OsiCuts & cuts, CbcNode * node, OsiCuts & slackCuts, int lastNumberCuts);
236    /** Generate one round of cuts - parallel mode
237        returns -
238        0 - normal
239        1 - must keep going
240        2 - set numberTries to zero
241        -1 - infeasible
242    */
243    int parallelCuts(CbcBaseModel * master, OsiCuts & cuts, CbcNode * node, OsiCuts & slackCuts, int lastNumberCuts);
244    /** Input one node output N nodes to put on tree and optional solution update
245        This should be able to operate in parallel so is given a solver and is const(ish)
246        However we will need to keep an array of solver_ and bases and more
247        status is 0 for normal, 1 if solution
248        Calling code should always push nodes back on tree
249    */
250    CbcNode ** solveOneNode(int whichSolver, CbcNode * node,
251                            int & numberNodesOutput, int & status) ;
252    /// Update size of whichGenerator
253    void resizeWhichGenerator(int numberNow, int numberAfter);
254public:
255#ifdef CBC_KEEP_DEPRECATED
256    // See if anyone is using these any more!!
257    /** \brief create a clean model from partially fixed problem
258
259      The method creates a new model with given bounds and with no tree.
260    */
261    CbcModel *  cleanModel(const double * lower, const double * upper);
262    /** \brief Invoke the branch \& cut algorithm on partially fixed problem
263
264      The method presolves the given model and does branch and cut. The search
265      ends when the tree is exhausted or maximum nodes is reached.
266
267      If better solution found then it is saved.
268
269      Returns 0 if search completed and solution, 1 if not completed and solution,
270      2 if completed and no solution, 3 if not completed and no solution.
271
272      Normally okay to do cleanModel immediately followed by subBranchandBound
273      (== other form of subBranchAndBound)
274      but may need to get at model for advanced features.
275
276      Deletes model2
277    */
278    int subBranchAndBound(CbcModel * model2,
279                          CbcModel * presolvedModel,
280                          int maximumNodes);
281    /** \brief Invoke the branch \& cut algorithm on partially fixed problem
282
283      The method creates a new model with given bounds, presolves it
284      then proceeds to explore the branch & cut search tree. The search
285      ends when the tree is exhausted or maximum nodes is reached.
286
287      If better solution found then it is saved.
288
289      Returns 0 if search completed and solution, 1 if not completed and solution,
290      2 if completed and no solution, 3 if not completed and no solution.
291
292      This is just subModel immediately followed by other version of
293      subBranchandBound.
294
295    */
296    int subBranchAndBound(const double * lower, const double * upper,
297                          int maximumNodes);
298
299    /** \brief Process root node and return a strengthened model
300
301      The method assumes that initialSolve() has been called to solve the
302      LP relaxation. It processes the root node and then returns a pointer
303      to the strengthened model (or NULL if infeasible)
304    */
305    OsiSolverInterface *  strengthenedModel();
306    /** preProcess problem - replacing solver
307        If makeEquality true then <= cliques converted to ==.
308        Presolve will be done numberPasses times.
309
310        Returns NULL if infeasible
311
312        If makeEquality is 1 add slacks to get cliques,
313        if 2 add slacks to get sos (but only if looks plausible) and keep sos info
314    */
315    CglPreProcess * preProcess( int makeEquality = 0, int numberPasses = 5,
316                                int tuning = 5);
317    /** Does postprocessing - original solver back.
318        User has to delete process */
319    void postProcess(CglPreProcess * process);
320#endif
321    /// Adds an update information object
322    void addUpdateInformation(const CbcObjectUpdateData & data);
323    /** Do one node - broken out for clarity?
324        also for parallel (when baseModel!=this)
325        Returns 1 if solution found
326        node NULL on return if no branches left
327        newNode NULL if no new node created
328    */
329    int doOneNode(CbcModel * baseModel, CbcNode * & node, CbcNode * & newNode);
330
331public:
332    /** \brief Reoptimise an LP relaxation
333
334      Invoke the solver's %resolve() method.
335      whereFrom -
336      0 - initial continuous
337      1 - resolve on branch (before new cuts)
338      2 - after new cuts
339      3  - obsolete code or something modified problem in unexpected way
340      10 - after strong branching has fixed variables at root
341      11 - after strong branching has fixed variables in tree
342
343      returns 1 feasible, 0 infeasible, -1 feasible but skip cuts
344    */
345    int resolve(CbcNodeInfo * parent, int whereFrom,
346                double * saveSolution = NULL,
347                double * saveLower = NULL,
348                double * saveUpper = NULL);
349    /// Make given rows (L or G) into global cuts and remove from lp
350    void makeGlobalCuts(int numberRows, const int * which);
351    /// Make given cut into a global cut
352    void makeGlobalCut(const OsiRowCut * cut);
353    /// Make given cut into a global cut
354    void makeGlobalCut(const OsiRowCut & cut);
355    /// Make given column cut into a global cut
356    void makeGlobalCut(const OsiColCut * cut);
357    /// Make given column cut into a global cut
358    void makeGlobalCut(const OsiColCut & cut);
359    //@}
360
361    /** \name Presolve methods */
362    //@{
363
364    /** Identify cliques and construct corresponding objects.
365
366        Find cliques with size in the range
367        [\p atLeastThisMany, \p lessThanThis] and construct corresponding
368        CbcClique objects.
369        If \p makeEquality is true then a new model may be returned if
370        modifications had to be made, otherwise \c this is returned.
371        If the problem is infeasible #numberObjects_ is set to -1.
372        A client must use deleteObjects() before a second call to findCliques().
373        If priorities exist, clique priority is set to the default.
374    */
375    CbcModel * findCliques(bool makeEquality, int atLeastThisMany,
376                           int lessThanThis, int defaultValue = 1000);
377
378    /** Do integer presolve, creating a new (presolved) model.
379
380      Returns the new model, or NULL if feasibility is lost.
381      If weak is true then just does a normal presolve
382
383      \todo It remains to work out the cleanest way of getting a solution to
384            the original problem at the end. So this is very preliminary.
385     */
386    CbcModel * integerPresolve(bool weak = false);
387
388    /** Do integer presolve, modifying the current model.
389
390        Returns true if the model remains feasible after presolve.
391    */
392    bool integerPresolveThisModel(OsiSolverInterface * originalSolver, bool weak = false);
393
394
395    /// Put back information into the original model after integer presolve.
396    void originalModel(CbcModel * presolvedModel, bool weak);
397
398    /** \brief For variables involved in VUB constraints, see if we can tighten
399           bounds by solving lp's
400
401        Returns false if feasibility is lost.
402        If CglProbing is available, it will be tried as well to see if it can
403        tighten bounds.
404        This routine is just a front end for tightenVubs(int,const int*,double).
405
406        If <tt>type = -1</tt> all variables are processed (could be very slow).
407        If <tt>type = 0</tt> only variables involved in VUBs are processed.
408        If <tt>type = n > 0</tt>, only the n most expensive VUB variables
409        are processed, where it is assumed that x is at its maximum so delta
410        would have to go to 1 (if x not at bound).
411
412        If \p allowMultipleBinary is true, then a VUB constraint is a row with
413        one continuous variable and any number of binary variables.
414
415        If <tt>useCutoff < 1.0e30</tt>, the original objective is installed as a
416        constraint with \p useCutoff as a bound.
417    */
418    bool tightenVubs(int type, bool allowMultipleBinary = false,
419                     double useCutoff = 1.0e50);
420
421    /** \brief For variables involved in VUB constraints, see if we can tighten
422           bounds by solving lp's
423
424      This version is just handed a list of variables to be processed.
425    */
426    bool tightenVubs(int numberVubs, const int * which,
427                     double useCutoff = 1.0e50);
428    /**
429      Analyze problem to find a minimum change in the objective function.
430    */
431    void analyzeObjective();
432
433    /**
434      Add additional integers.
435    */
436    void AddIntegers();
437
438    /**
439      Save copy of the model.
440    */
441    void saveModel(OsiSolverInterface * saveSolver, double * checkCutoffForRestart, bool * feasible);
442
443    //@}
444
445    /** \name Object manipulation routines
446
447      See OsiObject for an explanation of `object' in the context of CbcModel.
448    */
449    //@{
450
451    /// Get the number of objects
452    inline int numberObjects() const {
453        return numberObjects_;
454    }
455    /// Set the number of objects
456    inline void setNumberObjects(int number) {
457        numberObjects_ = number;
458    }
459
460    /// Get the array of objects
461    inline OsiObject ** objects() const {
462        return object_;
463    }
464
465    /// Get the specified object
466    const inline OsiObject * object(int which) const {
467        return object_[which];
468    }
469    /// Get the specified object
470    inline OsiObject * modifiableObject(int which) const {
471        return object_[which];
472    }
473
474    void setOptionalInteger(int index);
475
476    /// Delete all object information (and just back to integers if true)
477    void deleteObjects(bool findIntegers = true);
478
479    /** Add in object information.
480
481      Objects are cloned; the owner can delete the originals.
482    */
483    void addObjects(int numberObjects, OsiObject ** objects);
484
485    /** Add in object information.
486
487      Objects are cloned; the owner can delete the originals.
488    */
489    void addObjects(int numberObjects, CbcObject ** objects);
490
491    /// Ensure attached objects point to this model.
492    void synchronizeModel() ;
493
494    /** \brief Identify integer variables and create corresponding objects.
495
496      Record integer variables and create an CbcSimpleInteger object for each
497      one.
498      If \p startAgain is true, a new scan is forced, overwriting any existing
499      integer variable information.
500      If type > 0 then 1==PseudoCost, 2 new ones low priority
501    */
502
503    void findIntegers(bool startAgain, int type = 0);
504
505    //@}
506
507    //---------------------------------------------------------------------------
508
509    /**@name Parameter set/get methods
510
511       The set methods return true if the parameter was set to the given value,
512       false if the value of the parameter is out of range.
513
514       The get methods return the value of the parameter.
515
516    */
517    //@{
518    /// Set an integer parameter
519    inline bool setIntParam(CbcIntParam key, int value) {
520        intParam_[key] = value;
521        return true;
522    }
523    /// Set a double parameter
524    inline bool setDblParam(CbcDblParam key, double value) {
525        dblParam_[key] = value;
526        return true;
527    }
528    /// Get an integer parameter
529    inline int getIntParam(CbcIntParam key) const {
530        return intParam_[key];
531    }
532    /// Get a double parameter
533    inline double getDblParam(CbcDblParam key) const {
534        return dblParam_[key];
535    }
536    /*! \brief Set cutoff bound on the objective function.
537
538      When using strict comparison, the bound is adjusted by a tolerance to
539      avoid accidentally cutting off the optimal solution.
540    */
541    void setCutoff(double value) ;
542
543    /// Get the cutoff bound on the objective function - always as minimize
544    inline double getCutoff() const { //double value ;
545        //solver_->getDblParam(OsiDualObjectiveLimit,value) ;
546        //assert( dblParam_[CbcCurrentCutoff]== value * solver_->getObjSense());
547        return dblParam_[CbcCurrentCutoff];
548    }
549
550    /// Set the \link CbcModel::CbcMaxNumNode maximum node limit \endlink
551    inline bool setMaximumNodes( int value) {
552        return setIntParam(CbcMaxNumNode, value);
553    }
554
555    /// Get the \link CbcModel::CbcMaxNumNode maximum node limit \endlink
556    inline int getMaximumNodes() const {
557        return getIntParam(CbcMaxNumNode);
558    }
559
560    /** Set the
561        \link CbcModel::CbcMaxNumSol maximum number of solutions \endlink
562        desired.
563    */
564    inline bool setMaximumSolutions( int value) {
565        return setIntParam(CbcMaxNumSol, value);
566    }
567    /** Get the
568        \link CbcModel::CbcMaxNumSol maximum number of solutions \endlink
569        desired.
570    */
571    inline int getMaximumSolutions() const {
572        return getIntParam(CbcMaxNumSol);
573    }
574    /// Set the printing mode
575    inline bool setPrintingMode( int value) {
576        return setIntParam(CbcPrinting, value);
577    }
578
579    /// Get the printing mode
580    inline int getPrintingMode() const {
581        return getIntParam(CbcPrinting);
582    }
583
584    /** Set the
585        \link CbcModel::CbcMaximumSeconds maximum number of seconds \endlink
586        desired.
587    */
588    inline bool setMaximumSeconds( double value) {
589        return setDblParam(CbcMaximumSeconds, value);
590    }
591    /** Get the
592        \link CbcModel::CbcMaximumSeconds maximum number of seconds \endlink
593        desired.
594    */
595    inline double getMaximumSeconds() const {
596        return getDblParam(CbcMaximumSeconds);
597    }
598    /// Current time since start of branchAndbound
599    double getCurrentSeconds() const ;
600
601    /// Return true if maximum time reached
602    bool maximumSecondsReached() const ;
603
604    /** Set the
605      \link CbcModel::CbcIntegerTolerance integrality tolerance \endlink
606    */
607    inline bool setIntegerTolerance( double value) {
608        return setDblParam(CbcIntegerTolerance, value);
609    }
610    /** Get the
611      \link CbcModel::CbcIntegerTolerance integrality tolerance \endlink
612    */
613    inline double getIntegerTolerance() const {
614        return getDblParam(CbcIntegerTolerance);
615    }
616
617    /** Set the
618        \link CbcModel::CbcInfeasibilityWeight
619          weight per integer infeasibility \endlink
620    */
621    inline bool setInfeasibilityWeight( double value) {
622        return setDblParam(CbcInfeasibilityWeight, value);
623    }
624    /** Get the
625        \link CbcModel::CbcInfeasibilityWeight
626          weight per integer infeasibility \endlink
627    */
628    inline double getInfeasibilityWeight() const {
629        return getDblParam(CbcInfeasibilityWeight);
630    }
631
632    /** Set the \link CbcModel::CbcAllowableGap allowable gap \endlink
633        between the best known solution and the best possible solution.
634    */
635    inline bool setAllowableGap( double value) {
636        return setDblParam(CbcAllowableGap, value);
637    }
638    /** Get the \link CbcModel::CbcAllowableGap allowable gap \endlink
639        between the best known solution and the best possible solution.
640    */
641    inline double getAllowableGap() const {
642        return getDblParam(CbcAllowableGap);
643    }
644
645    /** Set the \link CbcModel::CbcAllowableFractionGap fraction allowable gap \endlink
646        between the best known solution and the best possible solution.
647    */
648    inline bool setAllowableFractionGap( double value) {
649        return setDblParam(CbcAllowableFractionGap, value);
650    }
651    /** Get the \link CbcModel::CbcAllowableFractionGap fraction allowable gap \endlink
652        between the best known solution and the best possible solution.
653    */
654    inline double getAllowableFractionGap() const {
655        return getDblParam(CbcAllowableFractionGap);
656    }
657    /** Set the \link CbcModel::CbcAllowableFractionGap percentage allowable gap \endlink
658        between the best known solution and the best possible solution.
659    */
660    inline bool setAllowablePercentageGap( double value) {
661        return setDblParam(CbcAllowableFractionGap, value*0.01);
662    }
663    /** Get the \link CbcModel::CbcAllowableFractionGap percentage allowable gap \endlink
664        between the best known solution and the best possible solution.
665    */
666    inline double getAllowablePercentageGap() const {
667        return 100.0*getDblParam(CbcAllowableFractionGap);
668    }
669    /** Set the \link CbcModel::CbcHeuristicGap heuristic gap \endlink
670        between the best known solution and the best possible solution.
671    */
672    inline bool setHeuristicGap( double value) {
673        return setDblParam(CbcHeuristicGap, value);
674    }
675    /** Get the \link CbcModel::CbcHeuristicGap heuristic gap \endlink
676        between the best known solution and the best possible solution.
677    */
678    inline double getHeuristicGap() const {
679        return getDblParam(CbcHeuristicGap);
680    }
681
682    /** Set the \link CbcModel::CbcHeuristicFractionGap fraction heuristic gap \endlink
683        between the best known solution and the best possible solution.
684    */
685    inline bool setHeuristicFractionGap( double value) {
686        return setDblParam(CbcHeuristicFractionGap, value);
687    }
688    /** Get the \link CbcModel::CbcHeuristicFractionGap fraction heuristic gap \endlink
689        between the best known solution and the best possible solution.
690    */
691    inline double getHeuristicFractionGap() const {
692        return getDblParam(CbcHeuristicFractionGap);
693    }
694    /** Set the
695        \link CbcModel::CbcCutoffIncrement  \endlink
696        desired.
697    */
698    inline bool setCutoffIncrement( double value) {
699        return setDblParam(CbcCutoffIncrement, value);
700    }
701    /** Get the
702        \link CbcModel::CbcCutoffIncrement  \endlink
703        desired.
704    */
705    inline double getCutoffIncrement() const {
706        return getDblParam(CbcCutoffIncrement);
707    }
708
709    /** Pass in target solution and optional priorities.
710        If priorities then >0 means only branch if incorrect
711        while <0 means branch even if correct. +1 or -1 are
712        highest priority */
713    void setHotstartSolution(const double * solution, const int * priorities = NULL) ;
714
715    /// Set the minimum drop to continue cuts
716    inline void setMinimumDrop(double value) {
717        minimumDrop_ = value;
718    }
719    /// Get the minimum drop to continue cuts
720    inline double getMinimumDrop() const {
721        return minimumDrop_;
722    }
723
724    /** Set the maximum number of cut passes at root node (default 20)
725        Minimum drop can also be used for fine tuning */
726    inline void setMaximumCutPassesAtRoot(int value) {
727        maximumCutPassesAtRoot_ = value;
728    }
729    /** Get the maximum number of cut passes at root node */
730    inline int getMaximumCutPassesAtRoot() const {
731        return maximumCutPassesAtRoot_;
732    }
733
734    /** Set the maximum number of cut passes at other nodes (default 10)
735        Minimum drop can also be used for fine tuning */
736    inline void setMaximumCutPasses(int value) {
737        maximumCutPasses_ = value;
738    }
739    /** Get the maximum number of cut passes at other nodes (default 10) */
740    inline int getMaximumCutPasses() const {
741        return maximumCutPasses_;
742    }
743    /** Get current cut pass number in this round of cuts.
744        (1 is first pass) */
745    inline int getCurrentPassNumber() const {
746        return currentPassNumber_;
747    }
748
749    /** Set the maximum number of candidates to be evaluated for strong
750      branching.
751
752      A value of 0 disables strong branching.
753    */
754    void setNumberStrong(int number);
755    /** Get the maximum number of candidates to be evaluated for strong
756      branching.
757    */
758    inline int numberStrong() const {
759        return numberStrong_;
760    }
761    /** Set global preferred way to branch
762        -1 down, +1 up, 0 no preference */
763    inline void setPreferredWay(int value) {
764        preferredWay_ = value;
765    }
766    /** Get the preferred way to branch (default 0) */
767    inline int getPreferredWay() const {
768        return preferredWay_;
769    }
770    /// Get at which depths to do cuts
771    inline int whenCuts() const {
772        return whenCuts_;
773    }
774    /// Set at which depths to do cuts
775    inline void setWhenCuts(int value) {
776        whenCuts_ = value;
777    }
778    /** Return true if we want to do cuts
779        If allowForTopOfTree zero then just does on multiples of depth
780        if 1 then allows for doing at top of tree
781        if 2 then says if cuts allowed anywhere apart from root
782    */
783    bool doCutsNow(int allowForTopOfTree) const;
784
785    /** Set the number of branches before pseudo costs believed
786        in dynamic strong branching.
787
788      A value of 0 disables dynamic strong branching.
789    */
790    void setNumberBeforeTrust(int number);
791    /** get the number of branches before pseudo costs believed
792        in dynamic strong branching. */
793    inline int numberBeforeTrust() const {
794        return numberBeforeTrust_;
795    }
796    /** Set the number of variables for which to compute penalties
797        in dynamic strong branching.
798
799      A value of 0 disables penalties.
800    */
801    void setNumberPenalties(int number);
802    /** get the number of variables for which to compute penalties
803        in dynamic strong branching. */
804    inline int numberPenalties() const {
805        return numberPenalties_;
806    }
807    /// Number of analyze iterations to do
808    inline void setNumberAnalyzeIterations(int number) {
809        numberAnalyzeIterations_ = number;
810    }
811    inline int numberAnalyzeIterations() const {
812        return numberAnalyzeIterations_;
813    }
814    /** Get scale factor to make penalties match strong.
815        Should/will be computed */
816    inline double penaltyScaleFactor() const {
817        return penaltyScaleFactor_;
818    }
819    /** Set scale factor to make penalties match strong.
820        Should/will be computed */
821    void setPenaltyScaleFactor(double value);
822    /** Problem type as set by user or found by analysis.  This will be extended
823        0 - not known
824        1 - Set partitioning <=
825        2 - Set partitioning ==
826        3 - Set covering
827        4 - all +- 1 or all +1 and odd
828    */
829    void inline setProblemType(int number) {
830        problemType_ = number;
831    }
832    inline int problemType() const {
833        return problemType_;
834    }
835    /// Current depth
836    inline int currentDepth() const {
837        return currentDepth_;
838    }
839
840    /// Set how often to scan global cuts
841    void setHowOftenGlobalScan(int number);
842    /// Get how often to scan global cuts
843    inline int howOftenGlobalScan() const {
844        return howOftenGlobalScan_;
845    }
846    /// Original columns as created by integerPresolve or preprocessing
847    inline int * originalColumns() const {
848        return originalColumns_;
849    }
850    /// Set original columns as created by preprocessing
851    void setOriginalColumns(const int * originalColumns) ;
852
853    /** Set the print frequency.
854
855      Controls the number of nodes evaluated between status prints.
856      If <tt>number <=0</tt> the print frequency is set to 100 nodes for large
857      problems, 1000 for small problems.
858      Print frequency has very slight overhead if small.
859    */
860    inline void setPrintFrequency(int number) {
861        printFrequency_ = number;
862    }
863    /// Get the print frequency
864    inline int printFrequency() const {
865        return printFrequency_;
866    }
867    //@}
868
869    //---------------------------------------------------------------------------
870    ///@name Methods returning info on how the solution process terminated
871    //@{
872    /// Are there a numerical difficulties?
873    bool isAbandoned() const;
874    /// Is optimality proven?
875    bool isProvenOptimal() const;
876    /// Is  infeasiblity proven (or none better than cutoff)?
877    bool isProvenInfeasible() const;
878    /// Was continuous solution unbounded
879    bool isContinuousUnbounded() const;
880    /// Was continuous solution unbounded
881    bool isProvenDualInfeasible() const;
882    /// Node limit reached?
883    bool isNodeLimitReached() const;
884    /// Time limit reached?
885    bool isSecondsLimitReached() const;
886    /// Solution limit reached?
887    bool isSolutionLimitReached() const;
888    /// Get how many iterations it took to solve the problem.
889    inline int getIterationCount() const {
890        return numberIterations_;
891    }
892    /// Increment how many iterations it took to solve the problem.
893    inline void incrementIterationCount(int value) {
894        numberIterations_ += value;
895    }
896    /// Get how many Nodes it took to solve the problem.
897    inline int getNodeCount() const {
898        return numberNodes_;
899    }
900    /// Increment how many nodes it took to solve the problem.
901    inline void incrementNodeCount(int value) {
902        numberNodes_ += value;
903    }
904    /** Final status of problem
905        Some of these can be found out by is...... functions
906        -1 before branchAndBound
907        0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found
908        (or check value of best solution)
909        1 stopped - on maxnodes, maxsols, maxtime
910        2 difficulties so run was abandoned
911        (5 event user programmed event occurred)
912    */
913    inline int status() const {
914        return status_;
915    }
916    inline void setProblemStatus(int value) {
917        status_ = value;
918    }
919    /** Secondary status of problem
920        -1 unset (status_ will also be -1)
921        0 search completed with solution
922        1 linear relaxation not feasible (or worse than cutoff)
923        2 stopped on gap
924        3 stopped on nodes
925        4 stopped on time
926        5 stopped on user event
927        6 stopped on solutions
928        7 linear relaxation unbounded
929    */
930    inline int secondaryStatus() const {
931        return secondaryStatus_;
932    }
933    inline void setSecondaryStatus(int value) {
934        secondaryStatus_ = value;
935    }
936    /// Are there numerical difficulties (for initialSolve) ?
937    bool isInitialSolveAbandoned() const ;
938    /// Is optimality proven (for initialSolve) ?
939    bool isInitialSolveProvenOptimal() const ;
940    /// Is primal infeasiblity proven (for initialSolve) ?
941    bool isInitialSolveProvenPrimalInfeasible() const ;
942    /// Is dual infeasiblity proven (for initialSolve) ?
943    bool isInitialSolveProvenDualInfeasible() const ;
944
945    //@}
946
947    //---------------------------------------------------------------------------
948    /**@name Problem information methods
949
950       These methods call the solver's query routines to return
951       information about the problem referred to by the current object.
952       Querying a problem that has no data associated with it result in
953       zeros for the number of rows and columns, and NULL pointers from
954       the methods that return vectors.
955
956       Const pointers returned from any data-query method are valid as
957       long as the data is unchanged and the solver is not called.
958    */
959    //@{
960    /// Number of rows in continuous (root) problem.
961    inline int numberRowsAtContinuous() const {
962        return numberRowsAtContinuous_;
963    }
964
965    /// Get number of columns
966    inline int getNumCols() const {
967        return solver_->getNumCols();
968    }
969
970    /// Get number of rows
971    inline int getNumRows() const {
972        return solver_->getNumRows();
973    }
974
975    /// Get number of nonzero elements
976    inline CoinBigIndex getNumElements() const {
977        return solver_->getNumElements();
978    }
979
980    /// Number of integers in problem
981    inline int numberIntegers() const {
982        return numberIntegers_;
983    }
984    // Integer variables
985    inline const int * integerVariable() const {
986        return integerVariable_;
987    }
988    /// Whether or not integer
989    inline char integerType(int i) const {
990        assert (integerInfo_);
991        assert (integerInfo_[i] == 0 || integerInfo_[i] == 1);
992        return integerInfo_[i];
993    }
994    /// Whether or not integer
995    inline const char * integerType() const {
996        return integerInfo_;
997    }
998
999    /// Get pointer to array[getNumCols()] of column lower bounds
1000    inline const double * getColLower() const {
1001        return solver_->getColLower();
1002    }
1003
1004    /// Get pointer to array[getNumCols()] of column upper bounds
1005    inline const double * getColUpper() const {
1006        return solver_->getColUpper();
1007    }
1008
1009    /** Get pointer to array[getNumRows()] of row constraint senses.
1010        <ul>
1011        <li>'L': <= constraint
1012        <li>'E': =  constraint
1013        <li>'G': >= constraint
1014        <li>'R': ranged constraint
1015        <li>'N': free constraint
1016        </ul>
1017    */
1018    inline const char * getRowSense() const {
1019        return solver_->getRowSense();
1020    }
1021
1022    /** Get pointer to array[getNumRows()] of rows right-hand sides
1023        <ul>
1024        <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i]
1025        <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i]
1026        <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i]
1027        <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0
1028        </ul>
1029    */
1030    inline const double * getRightHandSide() const {
1031        return solver_->getRightHandSide();
1032    }
1033
1034    /** Get pointer to array[getNumRows()] of row ranges.
1035        <ul>
1036        <li> if rowsense()[i] == 'R' then
1037        rowrange()[i] == rowupper()[i] - rowlower()[i]
1038        <li> if rowsense()[i] != 'R' then
1039        rowrange()[i] is 0.0
1040        </ul>
1041    */
1042    inline const double * getRowRange() const {
1043        return solver_->getRowRange();
1044    }
1045
1046    /// Get pointer to array[getNumRows()] of row lower bounds
1047    inline const double * getRowLower() const {
1048        return solver_->getRowLower();
1049    }
1050
1051    /// Get pointer to array[getNumRows()] of row upper bounds
1052    inline const double * getRowUpper() const {
1053        return solver_->getRowUpper();
1054    }
1055
1056    /// Get pointer to array[getNumCols()] of objective function coefficients
1057    inline const double * getObjCoefficients() const {
1058        return solver_->getObjCoefficients();
1059    }
1060
1061    /// Get objective function sense (1 for min (default), -1 for max)
1062    inline double getObjSense() const {
1063        //assert (dblParam_[CbcOptimizationDirection]== solver_->getObjSense());
1064        return dblParam_[CbcOptimizationDirection];
1065    }
1066
1067    /// Return true if variable is continuous
1068    inline bool isContinuous(int colIndex) const {
1069        return solver_->isContinuous(colIndex);
1070    }
1071
1072    /// Return true if variable is binary
1073    inline bool isBinary(int colIndex) const {
1074        return solver_->isBinary(colIndex);
1075    }
1076
1077    /** Return true if column is integer.
1078        Note: This function returns true if the the column
1079        is binary or a general integer.
1080    */
1081    inline bool isInteger(int colIndex) const {
1082        return solver_->isInteger(colIndex);
1083    }
1084
1085    /// Return true if variable is general integer
1086    inline bool isIntegerNonBinary(int colIndex) const {
1087        return solver_->isIntegerNonBinary(colIndex);
1088    }
1089
1090    /// Return true if variable is binary and not fixed at either bound
1091    inline bool isFreeBinary(int colIndex) const {
1092        return solver_->isFreeBinary(colIndex) ;
1093    }
1094
1095    /// Get pointer to row-wise copy of matrix
1096    inline const CoinPackedMatrix * getMatrixByRow() const {
1097        return solver_->getMatrixByRow();
1098    }
1099
1100    /// Get pointer to column-wise copy of matrix
1101    inline const CoinPackedMatrix * getMatrixByCol() const {
1102        return solver_->getMatrixByCol();
1103    }
1104
1105    /// Get solver's value for infinity
1106    inline double getInfinity() const {
1107        return solver_->getInfinity();
1108    }
1109    /// Get pointer to array[getNumCols()] (for speed) of column lower bounds
1110    inline const double * getCbcColLower() const {
1111        return cbcColLower_;
1112    }
1113    /// Get pointer to array[getNumCols()] (for speed) of column upper bounds
1114    inline const double * getCbcColUpper() const {
1115        return cbcColUpper_;
1116    }
1117    /// Get pointer to array[getNumRows()] (for speed) of row lower bounds
1118    inline const double * getCbcRowLower() const {
1119        return cbcRowLower_;
1120    }
1121    /// Get pointer to array[getNumRows()] (for speed) of row upper bounds
1122    inline const double * getCbcRowUpper() const {
1123        return cbcRowUpper_;
1124    }
1125    /// Get pointer to array[getNumCols()] (for speed) of primal solution vector
1126    inline const double * getCbcColSolution() const {
1127        return cbcColSolution_;
1128    }
1129    /// Get pointer to array[getNumRows()] (for speed) of dual prices
1130    inline const double * getCbcRowPrice() const {
1131        return cbcRowPrice_;
1132    }
1133    /// Get a pointer to array[getNumCols()] (for speed) of reduced costs
1134    inline const double * getCbcReducedCost() const {
1135        return cbcReducedCost_;
1136    }
1137    /// Get pointer to array[getNumRows()] (for speed) of row activity levels.
1138    inline const double * getCbcRowActivity() const {
1139        return cbcRowActivity_;
1140    }
1141    //@}
1142
1143
1144    /**@name Methods related to querying the solution */
1145    //@{
1146    /// Holds solution at continuous (after cuts if branchAndBound called)
1147    inline double * continuousSolution() const {
1148        return continuousSolution_;
1149    }
1150    /** Array marked whenever a solution is found if non-zero.
1151        Code marks if heuristic returns better so heuristic
1152        need only mark if it wants to on solutions which
1153        are worse than current */
1154    inline int * usedInSolution() const {
1155        return usedInSolution_;
1156    }
1157    /// Increases usedInSolution for nonzeros
1158    void incrementUsed(const double * solution);
1159    /// Record a new incumbent solution and update objectiveValue
1160    void setBestSolution(CBC_Message how,
1161                         double & objectiveValue, const double *solution,
1162                         int fixVariables = 0);
1163    /// Just update objectiveValue
1164    void setBestObjectiveValue( double objectiveValue);
1165    /// Deals with event handler and solution
1166    CbcEventHandler::CbcAction dealWithEventHandler(CbcEventHandler::CbcEvent event,
1167            double objValue,
1168            const double * solution);
1169
1170    /** Call this to really test if a valid solution can be feasible
1171        Solution is number columns in size.
1172        If fixVariables true then bounds of continuous solver updated.
1173        Returns objective value (worse than cutoff if not feasible)
1174        Previously computed objective value is now passed in (in case user does not do solve)
1175    */
1176    double checkSolution(double cutoff, double * solution,
1177                         int fixVariables, double originalObjValue);
1178    /** Test the current solution for feasiblility.
1179
1180      Scan all objects for indications of infeasibility. This is broken down
1181      into simple integer infeasibility (\p numberIntegerInfeasibilities)
1182      and all other reports of infeasibility (\p numberObjectInfeasibilities).
1183    */
1184    bool feasibleSolution(int & numberIntegerInfeasibilities,
1185                          int & numberObjectInfeasibilities) const;
1186
1187    /** Solution to the most recent lp relaxation.
1188
1189      The solver's solution to the most recent lp relaxation.
1190    */
1191
1192    inline double * currentSolution() const {
1193        return currentSolution_;
1194    }
1195    /** For testing infeasibilities - will point to
1196        currentSolution_ or solver-->getColSolution()
1197    */
1198    inline const double * testSolution() const {
1199        return testSolution_;
1200    }
1201    inline void setTestSolution(const double * solution) {
1202        testSolution_ = solution;
1203    }
1204    /// Make sure region there and optionally copy solution
1205    void reserveCurrentSolution(const double * solution = NULL);
1206
1207    /// Get pointer to array[getNumCols()] of primal solution vector
1208    inline const double * getColSolution() const {
1209        return solver_->getColSolution();
1210    }
1211
1212    /// Get pointer to array[getNumRows()] of dual prices
1213    inline const double * getRowPrice() const {
1214        return solver_->getRowPrice();
1215    }
1216
1217    /// Get a pointer to array[getNumCols()] of reduced costs
1218    inline const double * getReducedCost() const {
1219        return solver_->getReducedCost();
1220    }
1221
1222    /// Get pointer to array[getNumRows()] of row activity levels.
1223    inline const double * getRowActivity() const {
1224        return solver_->getRowActivity();
1225    }
1226
1227    /// Get current objective function value
1228    inline double getCurrentObjValue() const {
1229        return dblParam_[CbcCurrentObjectiveValue];
1230    }
1231    /// Get current minimization objective function value
1232    inline double getCurrentMinimizationObjValue() const {
1233        return dblParam_[CbcCurrentMinimizationObjectiveValue];
1234    }
1235
1236    /// Get best objective function value as minimization
1237    inline double getMinimizationObjValue() const {
1238        return bestObjective_;
1239    }
1240    /// Set best objective function value as minimization
1241    inline void setMinimizationObjValue(double value) {
1242        bestObjective_ = value;
1243    }
1244
1245    /// Get best objective function value
1246    inline double getObjValue() const {
1247        return bestObjective_ * solver_->getObjSense() ;
1248    }
1249    /** Get best possible objective function value.
1250        This is better of best possible left on tree
1251        and best solution found.
1252        If called from within branch and cut may be optimistic.
1253    */
1254    double getBestPossibleObjValue() const;
1255    /// Set best objective function value
1256    inline void setObjValue(double value) {
1257        bestObjective_ = value * solver_->getObjSense() ;
1258    }
1259    /// Get solver objective function value (as minimization)
1260    inline double getSolverObjValue() const {
1261        return solver_->getObjValue() * solver_->getObjSense() ;
1262    }
1263
1264    /** The best solution to the integer programming problem.
1265
1266      The best solution to the integer programming problem found during
1267      the search. If no solution is found, the method returns null.
1268    */
1269
1270    inline double * bestSolution() const {
1271        return bestSolution_;
1272    }
1273    /** User callable setBestSolution.
1274        If check false does not check valid
1275        If true then sees if feasible and warns if objective value
1276        worse than given (so just set to COIN_DBL_MAX if you don't care).
1277        If check true then does not save solution if not feasible
1278    */
1279    void setBestSolution(const double * solution, int numberColumns,
1280                         double objectiveValue, bool check = false);
1281
1282    /// Get number of solutions
1283    inline int getSolutionCount() const {
1284        return numberSolutions_;
1285    }
1286
1287    /// Set number of solutions (so heuristics will be different)
1288    inline void setSolutionCount(int value) {
1289        numberSolutions_ = value;
1290    }
1291    /// Number of saved solutions (including best)
1292    int numberSavedSolutions() const;
1293    /// Maximum number of extra saved solutions
1294    inline int maximumSavedSolutions() const {
1295        return maximumSavedSolutions_;
1296    }
1297    /// Set maximum number of extra saved solutions
1298    void setMaximumSavedSolutions(int value);
1299    /// Return a saved solution (0==best) - NULL if off end
1300    const double * savedSolution(int which) const;
1301    /// Return a saved solution objective (0==best) - COIN_DBL_MAX if off end
1302    double savedSolutionObjective(int which) const;
1303
1304    /** Current phase (so heuristics etc etc can find out).
1305        0 - initial solve
1306        1 - solve with cuts at root
1307        2 - solve with cuts
1308        3 - other e.g. strong branching
1309        4 - trying to validate a solution
1310        5 - at end of search
1311    */
1312    inline int phase() const {
1313        return phase_;
1314    }
1315
1316    /// Get number of heuristic solutions
1317    inline int getNumberHeuristicSolutions() const {
1318        return numberHeuristicSolutions_;
1319    }
1320    /// Set number of heuristic solutions
1321    inline void setNumberHeuristicSolutions(int value) {
1322        numberHeuristicSolutions_ = value;
1323    }
1324
1325    /// Set objective function sense (1 for min (default), -1 for max,)
1326    inline void setObjSense(double s) {
1327        dblParam_[CbcOptimizationDirection] = s;
1328        solver_->setObjSense(s);
1329    }
1330
1331    /// Value of objective at continuous
1332    inline double getContinuousObjective() const {
1333        return originalContinuousObjective_;
1334    }
1335    inline void setContinuousObjective(double value) {
1336        originalContinuousObjective_ = value;
1337    }
1338    /// Number of infeasibilities at continuous
1339    inline int getContinuousInfeasibilities() const {
1340        return continuousInfeasibilities_;
1341    }
1342    inline void setContinuousInfeasibilities(int value) {
1343        continuousInfeasibilities_ = value;
1344    }
1345    /// Value of objective after root node cuts added
1346    inline double rootObjectiveAfterCuts() const {
1347        return continuousObjective_;
1348    }
1349    /// Sum of Changes to objective by first solve
1350    inline double sumChangeObjective() const {
1351        return sumChangeObjective1_;
1352    }
1353    /** Number of times global cuts violated.  When global cut pool then this
1354        should be kept for each cut and type of cut */
1355    inline int numberGlobalViolations() const {
1356        return numberGlobalViolations_;
1357    }
1358    inline void clearNumberGlobalViolations() {
1359        numberGlobalViolations_ = 0;
1360    }
1361    /// Whether to force a resolve after takeOffCuts
1362    inline bool resolveAfterTakeOffCuts() const {
1363        return resolveAfterTakeOffCuts_;
1364    }
1365    inline void setResolveAfterTakeOffCuts(bool yesNo) {
1366        resolveAfterTakeOffCuts_ = yesNo;
1367    }
1368    /// Maximum number of rows
1369    inline int maximumRows() const {
1370        return maximumRows_;
1371    }
1372    /// Work basis for temporary use
1373    inline CoinWarmStartBasis & workingBasis() {
1374        return workingBasis_;
1375    }
1376    /// Get number of "iterations" to stop after
1377    inline int getStopNumberIterations() const {
1378        return stopNumberIterations_;
1379    }
1380    /// Set number of "iterations" to stop after
1381    inline void setStopNumberIterations(int value) {
1382        stopNumberIterations_ = value;
1383    }
1384    //@}
1385
1386    /** \name Node selection */
1387    //@{
1388    // Comparison functions (which may be overridden by inheritance)
1389    inline CbcCompareBase * nodeComparison() const {
1390        return nodeCompare_;
1391    }
1392    void setNodeComparison(CbcCompareBase * compare);
1393    void setNodeComparison(CbcCompareBase & compare);
1394    //@}
1395
1396    /** \name Problem feasibility checking */
1397    //@{
1398    // Feasibility functions (which may be overridden by inheritance)
1399    inline CbcFeasibilityBase * problemFeasibility() const {
1400        return problemFeasibility_;
1401    }
1402    void setProblemFeasibility(CbcFeasibilityBase * feasibility);
1403    void setProblemFeasibility(CbcFeasibilityBase & feasibility);
1404    //@}
1405
1406    /** \name Tree methods and subtree methods */
1407    //@{
1408    /// Tree method e.g. heap (which may be overridden by inheritance)
1409    inline CbcTree * tree() const {
1410        return tree_;
1411    }
1412    /// For modifying tree handling (original is cloned)
1413    void passInTreeHandler(CbcTree & tree);
1414    /** For passing in an CbcModel to do a sub Tree (with derived tree handlers).
1415        Passed in model must exist for duration of branch and bound
1416    */
1417    void passInSubTreeModel(CbcModel & model);
1418    /** For retrieving a copy of subtree model with given OsiSolver.
1419        If no subtree model will use self (up to user to reset cutoff etc).
1420        If solver NULL uses current
1421    */
1422    CbcModel * subTreeModel(OsiSolverInterface * solver = NULL) const;
1423    /// Returns number of times any subtree stopped on nodes, time etc
1424    inline int numberStoppedSubTrees() const {
1425        return numberStoppedSubTrees_;
1426    }
1427    /// Says a sub tree was stopped
1428    inline void incrementSubTreeStopped() {
1429        numberStoppedSubTrees_++;
1430    }
1431    /** Whether to automatically do presolve before branch and bound (subTrees).
1432        0 - no
1433        1 - ordinary presolve
1434        2 - integer presolve (dodgy)
1435    */
1436    inline int typePresolve() const {
1437        return presolve_;
1438    }
1439    inline void setTypePresolve(int value) {
1440        presolve_ = value;
1441    }
1442
1443    //@}
1444
1445    /** \name Branching Decisions
1446
1447      See the CbcBranchDecision class for additional information.
1448    */
1449    //@{
1450
1451    /// Get the current branching decision method.
1452    inline CbcBranchDecision * branchingMethod() const {
1453        return branchingMethod_;
1454    }
1455    /// Set the branching decision method.
1456    inline void setBranchingMethod(CbcBranchDecision * method) {
1457        delete branchingMethod_;
1458        branchingMethod_ = method->clone();
1459    }
1460    /** Set the branching method
1461
1462      \overload
1463    */
1464    inline void setBranchingMethod(CbcBranchDecision & method) {
1465        delete branchingMethod_;
1466        branchingMethod_ = method.clone();
1467    }
1468    /// Get the current cut modifier method
1469    inline CbcCutModifier * cutModifier() const {
1470        return cutModifier_;
1471    }
1472    /// Set the cut modifier method
1473    void setCutModifier(CbcCutModifier * modifier);
1474    /** Set the cut modifier method
1475
1476      \overload
1477    */
1478    void setCutModifier(CbcCutModifier & modifier);
1479    //@}
1480
1481    /** \name Row (constraint) and Column (variable) cut generation */
1482    //@{
1483
1484    /** State of search
1485        0 - no solution
1486        1 - only heuristic solutions
1487        2 - branched to a solution
1488        3 - no solution but many nodes
1489    */
1490    inline int stateOfSearch() const {
1491        return stateOfSearch_;
1492    }
1493    inline void setStateOfSearch(int state) {
1494        stateOfSearch_ = state;
1495    }
1496    /// Strategy worked out - mainly at root node for use by CbcNode
1497    inline int searchStrategy() const {
1498        return searchStrategy_;
1499    }
1500    /// Set strategy worked out - mainly at root node for use by CbcNode
1501    inline void setSearchStrategy(int value) {
1502        searchStrategy_ = value;
1503    }
1504
1505    /// Get the number of cut generators
1506    inline int numberCutGenerators() const {
1507        return numberCutGenerators_;
1508    }
1509    /// Get the list of cut generators
1510    inline CbcCutGenerator ** cutGenerators() const {
1511        return generator_;
1512    }
1513    ///Get the specified cut generator
1514    inline CbcCutGenerator * cutGenerator(int i) const {
1515        return generator_[i];
1516    }
1517    ///Get the specified cut generator before any changes
1518    inline CbcCutGenerator * virginCutGenerator(int i) const {
1519        return virginGenerator_[i];
1520    }
1521    /** Add one generator - up to user to delete generators.
1522        howoften affects how generator is used. 0 or 1 means always,
1523        >1 means every that number of nodes.  Negative values have same
1524        meaning as positive but they may be switched off (-> -100) by code if
1525        not many cuts generated at continuous.  -99 is just done at root.
1526        Name is just for printout.
1527        If depth >0 overrides how often generator is called (if howOften==-1 or >0).
1528    */
1529    void addCutGenerator(CglCutGenerator * generator,
1530                         int howOften = 1, const char * name = NULL,
1531                         bool normal = true, bool atSolution = false,
1532                         bool infeasible = false, int howOftenInSub = -100,
1533                         int whatDepth = -1, int whatDepthInSub = -1);
1534//@}
1535    /** \name Strategy and sub models
1536
1537      See the CbcStrategy class for additional information.
1538    */
1539    //@{
1540
1541    /// Get the current strategy
1542    inline CbcStrategy * strategy() const {
1543        return strategy_;
1544    }
1545    /// Set the strategy. Clones
1546    void setStrategy(CbcStrategy & strategy);
1547    /// Set the strategy. assigns
1548    inline void setStrategy(CbcStrategy * strategy) {
1549        strategy_ = strategy;
1550    }
1551    /// Get the current parent model
1552    inline CbcModel * parentModel() const {
1553        return parentModel_;
1554    }
1555    /// Set the parent model
1556    inline void setParentModel(CbcModel & parentModel) {
1557        parentModel_ = &parentModel;
1558    }
1559    //@}
1560
1561
1562    /** \name Heuristics and priorities */
1563    //@{
1564    /*! \brief Add one heuristic - up to user to delete
1565
1566      The name is just used for print messages.
1567    */
1568    void addHeuristic(CbcHeuristic * generator, const char *name = NULL,
1569                      int before = -1);
1570    ///Get the specified heuristic
1571    inline CbcHeuristic * heuristic(int i) const {
1572        return heuristic_[i];
1573    }
1574    /// Get the number of heuristics
1575    inline int numberHeuristics() const {
1576        return numberHeuristics_;
1577    }
1578    /// Pointer to heuristic solver which found last solution (or NULL)
1579    inline CbcHeuristic * lastHeuristic() const {
1580        return lastHeuristic_;
1581    }
1582    /// set last heuristic which found a solution
1583    inline void setLastHeuristic(CbcHeuristic * last) {
1584        lastHeuristic_ = last;
1585    }
1586
1587    /** Pass in branching priorities.
1588
1589        If ifClique then priorities are on cliques otherwise priorities are
1590        on integer variables.
1591        Other type (if exists set to default)
1592        1 is highest priority. (well actually -INT_MAX is but that's ugly)
1593        If hotstart > 0 then branches are created to force
1594        the variable to the value given by best solution.  This enables a
1595        sort of hot start.  The node choice should be greatest depth
1596        and hotstart should normally be switched off after a solution.
1597
1598        If ifNotSimpleIntegers true then appended to normal integers
1599
1600        This is now deprecated except for simple usage.  If user
1601        creates Cbcobjects then set priority in them
1602
1603        \internal Added for Kurt Spielberg.
1604    */
1605    void passInPriorities(const int * priorities, bool ifNotSimpleIntegers);
1606
1607    /// Returns priority level for an object (or 1000 if no priorities exist)
1608    inline int priority(int sequence) const {
1609        return object_[sequence]->priority();
1610    }
1611
1612    /*! \brief Set an event handler
1613
1614      A clone of the handler passed as a parameter is stored in CbcModel.
1615    */
1616    void passInEventHandler(const CbcEventHandler *eventHandler) ;
1617
1618    /*! \brief Retrieve a pointer to the event handler */
1619    inline CbcEventHandler* getEventHandler() const {
1620        return (eventHandler_) ;
1621    }
1622
1623    //@}
1624
1625    /**@name Setting/Accessing application data */
1626    //@{
1627    /** Set application data.
1628
1629    This is a pointer that the application can store into and
1630    retrieve from the solver interface.
1631    This field is available for the application to optionally
1632    define and use.
1633    */
1634    void setApplicationData (void * appData);
1635
1636    /// Get application data
1637    void * getApplicationData() const;
1638    /**
1639        For advanced applications you may wish to modify the behavior of Cbc
1640        e.g. if the solver is a NLP solver then you may not have an exact
1641        optimum solution at each step.  Information could be built into
1642        OsiSolverInterface but this is an alternative so that that interface
1643        does not have to be changed.  If something similar is useful to
1644        enough solvers then it could be migrated
1645        You can also pass in by using solver->setAuxiliaryInfo.
1646        You should do that if solver is odd - if solver is normal simplex
1647        then use this.
1648        NOTE - characteristics are not cloned
1649    */
1650    void passInSolverCharacteristics(OsiBabSolver * solverCharacteristics);
1651    /// Get solver characteristics
1652    inline const OsiBabSolver * solverCharacteristics() const {
1653        return solverCharacteristics_;
1654    }
1655    //@}
1656
1657    //---------------------------------------------------------------------------
1658
1659    /**@name Message handling etc */
1660    //@{
1661    /// Pass in Message handler (not deleted at end)
1662    void passInMessageHandler(CoinMessageHandler * handler);
1663    /// Set language
1664    void newLanguage(CoinMessages::Language language);
1665    inline void setLanguage(CoinMessages::Language language) {
1666        newLanguage(language);
1667    }
1668    /// Return handler
1669    inline CoinMessageHandler * messageHandler() const {
1670        return handler_;
1671    }
1672    /// Return messages
1673    inline CoinMessages & messages() {
1674        return messages_;
1675    }
1676    /// Return pointer to messages
1677    inline CoinMessages * messagesPointer() {
1678        return &messages_;
1679    }
1680    /// Set log level
1681    void setLogLevel(int value);
1682    /// Get log level
1683    inline int logLevel() const {
1684        return handler_->logLevel();
1685    }
1686    /** Set flag to say if handler_ is the default handler.
1687
1688      The default handler is deleted when the model is deleted. Other
1689      handlers (supplied by the client) will not be deleted.
1690    */
1691    inline void setDefaultHandler(bool yesNo) {
1692        defaultHandler_ = yesNo;
1693    }
1694    //@}
1695    //---------------------------------------------------------------------------
1696    ///@name Specialized
1697    //@{
1698
1699    /**
1700        Set special options
1701        0 bit (1) - check if cuts valid (if on debugger list)
1702        1 bit (2) - use current basis to check integer solution (rather than all slack)
1703        2 bit (4) - don't check integer solution (by solving LP)
1704        3 bit (8) - fast analyze
1705        4 bit (16) - non-linear model - so no well defined CoinPackedMatrix
1706        5 bit (32) - keep names
1707        6 bit (64) - try for dominated columns
1708        7 bit (128) - SOS type 1 but all declared integer
1709        8 bit (256) - Set to say solution just found, unset by doing cuts
1710        9 bit (512) - Try reduced model after 100 nodes
1711        10 bit (1024) - Switch on some heuristics even if seems unlikely
1712        11 bit (2048) - Mark as in small branch and bound
1713        12 bit (4096) - Funny cuts so do slow way (in some places)
1714        13 bit (8192) - Funny cuts so do slow way (in other places)
1715        14 bit (16384) - Use Cplex! for fathoming
1716        15 bit (32768) - Try reduced model after 0 nodes
1717        16 bit (65536) - Original model had integer bounds
1718        17 bit (131072) - Perturbation switched off
1719    */
1720    inline void setSpecialOptions(int value) {
1721        specialOptions_ = value;
1722    }
1723    /// Get special options
1724    inline int specialOptions() const {
1725        return specialOptions_;
1726    }
1727    /// Says if normal solver i.e. has well defined CoinPackedMatrix
1728    inline bool normalSolver() const {
1729        return (specialOptions_&16) == 0;
1730    }
1731    /** Set more special options
1732        at present bottom 6 bits used for shadow price mode
1733        1024 for experimental hotstart
1734        2048,4096 breaking out of cuts
1735        8192 slowly increase minimum drop
1736        16384 gomory
1737        32768 more heuristics in sub trees
1738        65536 no cuts in preprocessing
1739        131072 Time limits elapsed
1740    */
1741    inline void setMoreSpecialOptions(int value) {
1742        moreSpecialOptions_ = value;
1743    }
1744    /// Get more special options
1745    inline int moreSpecialOptions() const {
1746        return moreSpecialOptions_;
1747    }
1748  /// Set time method
1749    inline void setUseElapsedTime(bool yesNo) {
1750        if (yesNo)
1751          moreSpecialOptions_ |= 131072;
1752        else
1753          moreSpecialOptions_ &= ~131072;
1754    }
1755    /// Get time method
1756    inline bool useElapsedTime() const {
1757        return (moreSpecialOptions_&131072)!=0;
1758    }
1759    /// Go to dantzig pivot selection if easy problem (clp only)
1760#ifdef COIN_HAS_CLP
1761    void goToDantzig(int numberNodes, ClpDualRowPivot *& savePivotMethod);
1762#endif
1763    /// Now we may not own objects - just point to solver's objects
1764    inline bool ownObjects() const {
1765        return ownObjects_;
1766    }
1767    /// Check original model before it gets messed up
1768    void checkModel();
1769    //@}
1770    //---------------------------------------------------------------------------
1771
1772    ///@name Constructors and destructors etc
1773    //@{
1774    /// Default Constructor
1775    CbcModel();
1776
1777    /// Constructor from solver
1778    CbcModel(const OsiSolverInterface &);
1779
1780    /** Assign a solver to the model (model assumes ownership)
1781
1782      On return, \p solver will be NULL.
1783      If deleteSolver then current solver deleted (if model owned)
1784
1785      \note Parameter settings in the outgoing solver are not inherited by
1786        the incoming solver.
1787    */
1788    void assignSolver(OsiSolverInterface *&solver, bool deleteSolver = true);
1789
1790    /** \brief Set ownership of solver
1791
1792      A parameter of false tells CbcModel it does not own the solver and
1793      should not delete it. Once you claim ownership of the solver, you're
1794      responsible for eventually deleting it. Note that CbcModel clones
1795      solvers with abandon.  Unless you have a deep understanding of the
1796      workings of CbcModel, the only time you want to claim ownership is when
1797      you're about to delete the CbcModel object but want the solver to
1798      continue to exist (as, for example, when branchAndBound has finished
1799      and you want to hang on to the answer).
1800    */
1801    inline void setModelOwnsSolver (bool ourSolver) {
1802        ownership_ = ourSolver ? (ownership_ | 0x80000000) : (ownership_ & (~0x80000000)) ;
1803    }
1804
1805    /*! \brief Get ownership of solver
1806
1807      A return value of true means that CbcModel owns the solver and will
1808      take responsibility for deleting it when that becomes necessary.
1809    */
1810    inline bool modelOwnsSolver () {
1811        return ((ownership_&0x80000000) != 0) ;
1812    }
1813
1814    /** Copy constructor .
1815      If cloneHandler is true then message handler is cloned
1816    */
1817    CbcModel(const CbcModel & rhs, bool cloneHandler = false);
1818
1819    /// Assignment operator
1820    CbcModel & operator=(const CbcModel& rhs);
1821
1822    /// Destructor
1823    ~CbcModel ();
1824
1825    /// Returns solver - has current state
1826    inline OsiSolverInterface * solver() const {
1827        return solver_;
1828    }
1829
1830    /// Returns current solver - sets new one
1831    inline OsiSolverInterface * swapSolver(OsiSolverInterface * solver) {
1832        OsiSolverInterface * returnSolver = solver_;
1833        solver_ = solver;
1834        return returnSolver;
1835    }
1836
1837    /// Returns solver with continuous state
1838    inline OsiSolverInterface * continuousSolver() const {
1839        return continuousSolver_;
1840    }
1841
1842    /// Create solver with continuous state
1843    inline void createContinuousSolver() {
1844        continuousSolver_ = solver_->clone();
1845    }
1846    /// Clear solver with continuous state
1847    inline void clearContinuousSolver() {
1848        delete continuousSolver_;
1849        continuousSolver_ = NULL;
1850    }
1851
1852    /// A copy of the solver, taken at constructor or by saveReferenceSolver
1853    inline OsiSolverInterface * referenceSolver() const {
1854        return referenceSolver_;
1855    }
1856
1857    /// Save a copy of the current solver so can be reset to
1858    void saveReferenceSolver();
1859
1860    /** Uses a copy of reference solver to be current solver.
1861        Because of possible mismatches all exotic integer information is loat
1862        (apart from normal information in OsiSolverInterface)
1863        so SOS etc and priorities will have to be redone
1864    */
1865    void resetToReferenceSolver();
1866
1867    /// Clears out as much as possible (except solver)
1868    void gutsOfDestructor();
1869    /** Clears out enough to reset CbcModel as if no branch and bound done
1870     */
1871    void gutsOfDestructor2();
1872    /** Clears out enough to reset CbcModel cutoff etc
1873     */
1874    void resetModel();
1875    /** Most of copy constructor
1876        mode - 0 copy but don't delete before
1877               1 copy and delete before
1878           2 copy and delete before (but use virgin generators)
1879    */
1880    void gutsOfCopy(const CbcModel & rhs, int mode = 0);
1881    /// Move status, nodes etc etc across
1882    void moveInfo(const CbcModel & rhs);
1883    //@}
1884
1885    /// To do with threads
1886    //@{
1887    /// Get pointer to masterthread
1888    CbcThread * masterThread() const {
1889        return masterThread_;
1890    }
1891    /// Get pointer to walkback
1892    CbcNodeInfo ** walkback() const {
1893        return walkback_;
1894    }
1895    /// Get number of threads
1896    inline int getNumberThreads() const {
1897        return numberThreads_;
1898    }
1899    /// Set number of threads
1900    inline void setNumberThreads(int value) {
1901        numberThreads_ = value;
1902    }
1903    /// Get thread mode
1904    inline int getThreadMode() const {
1905        return threadMode_;
1906    }
1907    /** Set thread mode
1908        always use numberThreads for branching
1909        1 set then deterministic
1910        2 set then use numberThreads for root cuts
1911        4 set then use numberThreads in root mini branch and bound
1912        8 set and numberThreads - do heuristics numberThreads at a time
1913        8 set and numberThreads==0 do all heuristics at once
1914        default is 0
1915    */
1916    inline void setThreadMode(int value) {
1917        threadMode_ = value;
1918    }
1919    /** Return
1920        -2 if deterministic threaded and main thread
1921        -1 if deterministic threaded and serial thread
1922        0 if serial
1923        1 if opportunistic threaded
1924    */
1925    inline int parallelMode() const {
1926        if (!numberThreads_) {
1927            if ((threadMode_&1) == 0)
1928                return 0;
1929            else
1930                return -1;
1931            return 0;
1932        } else {
1933            if ((threadMode_&1) == 0)
1934                return 1;
1935            else
1936                return -2;
1937        }
1938    }
1939    /// From here to end of section - code in CbcThread.cpp until class changed
1940    /// Returns true if locked
1941    bool isLocked() const;
1942#ifdef CBC_THREAD
1943    /**
1944       Locks a thread if parallel so that stuff like cut pool
1945       can be updated and/or used.
1946    */
1947    void lockThread();
1948    /**
1949       Unlocks a thread if parallel to say cut pool stuff not needed
1950    */
1951    void unlockThread();
1952#else
1953    inline void lockThread() {}
1954    inline void unlockThread() {}
1955#endif
1956    /** Set information in a child
1957        -3 pass pointer to child thread info
1958        -2 just stop
1959        -1 delete simple child stuff
1960        0 delete opportunistic child stuff
1961        1 delete deterministic child stuff
1962    */
1963    void setInfoInChild(int type, CbcThread * info);
1964    /** Move/copy information from one model to another
1965        -1 - initialization
1966        0 - from base model
1967        1 - to base model (and reset)
1968        2 - add in final statistics etc (and reset so can do clean destruction)
1969    */
1970    void moveToModel(CbcModel * baseModel, int mode);
1971    /// Split up nodes
1972    int splitModel(int numberModels, CbcModel ** model,
1973                   int numberNodes);
1974    /// Start threads
1975    void startSplitModel(int numberIterations);
1976    /// Merge models
1977    void mergeModels(int numberModel, CbcModel ** model,
1978                     int numberNodes);
1979    //@}
1980
1981    /// semi-private i.e. users should not use
1982    //@{
1983    /// Get how many Nodes it took to solve the problem.
1984    int getNodeCount2() const {
1985        return numberNodes2_;
1986    }
1987    /// Set pointers for speed
1988    void setPointers(const OsiSolverInterface * solver);
1989    /** Perform reduced cost fixing
1990
1991      Fixes integer variables at their current value based on reduced cost
1992      penalties.  Returns number fixed
1993    */
1994    int reducedCostFix() ;
1995    /** Makes all handlers same.  If makeDefault 1 then makes top level
1996        default and rest point to that.  If 2 then each is copy
1997    */
1998    void synchronizeHandlers(int makeDefault);
1999    /// Save a solution to saved list
2000    void saveExtraSolution(const double * solution, double objectiveValue);
2001    /// Save a solution to best and move current to saved
2002    void saveBestSolution(const double * solution, double objectiveValue);
2003    /// Delete best and saved solutions
2004    void deleteSolutions();
2005    /// Encapsulates solver resolve
2006    int resolve(OsiSolverInterface * solver);
2007
2008    /** Encapsulates choosing a variable -
2009        anyAction -2, infeasible (-1 round again), 0 done
2010    */
2011    int chooseBranch(CbcNode * & newNode, int numberPassesLeft,
2012                     CbcNode * oldNode, OsiCuts & cuts,
2013                     bool & resolved, CoinWarmStartBasis *lastws,
2014                     const double * lowerBefore, const double * upperBefore,
2015                     OsiSolverBranch * & branches);
2016    int chooseBranch(CbcNode * newNode, int numberPassesLeft, bool & resolved);
2017
2018    /** Return an empty basis object of the specified size
2019
2020      A useful utility when constructing a basis for a subproblem from scratch.
2021      The object returned will be of the requested capacity and appropriate for
2022      the solver attached to the model.
2023    */
2024    CoinWarmStartBasis *getEmptyBasis(int ns = 0, int na = 0) const ;
2025
2026    /** Remove inactive cuts from the model
2027
2028      An OsiSolverInterface is expected to maintain a valid basis, but not a
2029      valid solution, when loose cuts are deleted. Restoring a valid solution
2030      requires calling the solver to reoptimise. If it's certain the solution
2031      will not be required, set allowResolve to false to suppress
2032      reoptimisation.
2033      If saveCuts then slack cuts will be saved
2034      On input current cuts are cuts and newCuts
2035      on exit current cuts will be correct.  Returns number dropped
2036    */
2037    int takeOffCuts(OsiCuts &cuts,
2038                    bool allowResolve, OsiCuts * saveCuts,
2039                    int numberNewCuts = 0, const OsiRowCut ** newCuts = NULL) ;
2040
2041    /** Determine and install the active cuts that need to be added for
2042      the current subproblem
2043
2044      The whole truth is a bit more complicated. The first action is a call to
2045      addCuts1(). addCuts() then sorts through the list, installs the tight
2046      cuts in the model, and does bookkeeping (adjusts reference counts).
2047      The basis returned from addCuts1() is adjusted accordingly.
2048
2049      If it turns out that the node should really be fathomed by bound,
2050      addCuts() simply treats all the cuts as loose as it does the bookkeeping.
2051
2052      canFix true if extra information being passed
2053    */
2054    int addCuts(CbcNode * node, CoinWarmStartBasis *&lastws, bool canFix);
2055
2056    /** Traverse the tree from node to root and prep the model
2057
2058      addCuts1() begins the job of prepping the model to match the current
2059      subproblem. The model is stripped of all cuts, and the search tree is
2060      traversed from node to root to determine the changes required. Appropriate
2061      bounds changes are installed, a list of cuts is collected but not
2062      installed, and an appropriate basis (minus the cuts, but big enough to
2063      accommodate them) is constructed.
2064
2065      Returns true if new problem similar to old
2066
2067      \todo addCuts1() is called in contexts where it's known in advance that
2068        all that's desired is to determine a list of cuts and do the
2069        bookkeeping (adjust the reference counts). The work of installing
2070        bounds and building a basis goes to waste.
2071    */
2072    bool addCuts1(CbcNode * node, CoinWarmStartBasis *&lastws);
2073    /** Returns bounds just before where - initially original bounds.
2074        Also sets downstream nodes (lower if force 1, upper if 2)
2075    */
2076    void previousBounds (CbcNode * node, CbcNodeInfo * where, int iColumn,
2077                         double & lower, double & upper, int force);
2078    /** Set objective value in a node.  This is separated out so that
2079       odd solvers can use.  It may look at extra information in
2080       solverCharacteriscs_ and will also use bound from parent node
2081    */
2082    void setObjectiveValue(CbcNode * thisNode, const CbcNode * parentNode) const;
2083
2084    /** If numberBeforeTrust >0 then we are going to use CbcBranchDynamic.
2085        Scan and convert CbcSimpleInteger objects
2086    */
2087    void convertToDynamic();
2088    /// Set numberBeforeTrust in all objects
2089    void synchronizeNumberBeforeTrust(int type = 0);
2090    /// Zap integer information in problem (may leave object info)
2091    void zapIntegerInformation(bool leaveObjects = true);
2092    /// Use cliques for pseudocost information - return nonzero if infeasible
2093    int cliquePseudoCosts(int doStatistics);
2094    /// Fill in useful estimates
2095    void pseudoShadow(int type);
2096    /** Return pseudo costs
2097        If not all integers or not pseudo costs - returns all zero
2098        Length of arrays are numberIntegers() and entries
2099        correspond to integerVariable()[i]
2100        User must allocate arrays before call
2101    */
2102    void fillPseudoCosts(double * downCosts, double * upCosts,
2103                         int * priority = NULL,
2104                         int * numberDown = NULL, int * numberUp = NULL,
2105                         int * numberDownInfeasible = NULL,
2106                         int * numberUpInfeasible = NULL) const;
2107    /** Do heuristics at root.
2108        0 - don't delete
2109        1 - delete
2110        2 - just delete - don't even use
2111    */
2112    void doHeuristicsAtRoot(int deleteHeuristicsAfterwards = 0);
2113    /// Adjust heuristics based on model
2114    void adjustHeuristics();
2115    /// Get the hotstart solution
2116    inline const double * hotstartSolution() const {
2117        return hotstartSolution_;
2118    }
2119    /// Get the hotstart priorities
2120    inline const int * hotstartPriorities() const {
2121        return hotstartPriorities_;
2122    }
2123
2124    /// Return the list of cuts initially collected for this subproblem
2125    inline CbcCountRowCut ** addedCuts() const {
2126        return addedCuts_;
2127    }
2128    /// Number of entries in the list returned by #addedCuts()
2129    inline int currentNumberCuts() const {
2130        return currentNumberCuts_;
2131    }
2132    /// Global cuts
2133    inline OsiCuts * globalCuts() {
2134        return &globalCuts_;
2135    }
2136    /// Copy and set a pointer to a row cut which will be added instead of normal branching.
2137    void setNextRowCut(const OsiRowCut & cut);
2138    /// Get a pointer to current node (be careful)
2139    inline CbcNode * currentNode() const {
2140        return currentNode_;
2141    }
2142    /// Get a pointer to probing info
2143    inline CglTreeProbingInfo * probingInfo() const {
2144        return probingInfo_;
2145    }
2146    /// Thread specific random number generator
2147    inline CoinThreadRandom * randomNumberGenerator() {
2148        return &randomNumberGenerator_;
2149    }
2150    /// Set the number of iterations done in strong branching.
2151    inline void setNumberStrongIterations(int number) {
2152        numberStrongIterations_ = number;
2153    }
2154    /// Get the number of iterations done in strong branching.
2155    inline int numberStrongIterations() const {
2156        return numberStrongIterations_;
2157    }
2158    /// Get maximum number of iterations (designed to be used in heuristics)
2159    inline int maximumNumberIterations() const {
2160        return maximumNumberIterations_;
2161    }
2162    /// Set maximum number of iterations (designed to be used in heuristics)
2163    inline void setMaximumNumberIterations(int value) {
2164        maximumNumberIterations_ = value;
2165    }
2166# ifdef COIN_HAS_CLP
2167    /// Set depth for fast nodes
2168    inline void setFastNodeDepth(int value) {
2169        fastNodeDepth_ = value;
2170    }
2171    /// Get depth for fast nodes
2172    inline int fastNodeDepth() const {
2173        return fastNodeDepth_;
2174    }
2175    /// Get anything with priority >= this can be treated as continuous
2176    inline int continuousPriority() const {
2177        return continuousPriority_;
2178    }
2179    /// Set anything with priority >= this can be treated as continuous
2180    inline void setContinuousPriority(int value) {
2181        continuousPriority_ = value;
2182    }
2183    inline void incrementExtra(int nodes, int iterations) {
2184        numberExtraNodes_ += nodes;
2185        numberExtraIterations_ += iterations;
2186    }
2187#endif
2188    /// Number of extra iterations
2189    inline int numberExtraIterations() const {
2190        return numberExtraIterations_;
2191    }
2192    /// Increment strong info
2193    void incrementStrongInfo(int numberTimes, int numberIterations,
2194                             int numberFixed, bool ifInfeasible);
2195    /// Return strong info
2196    inline const int * strongInfo() const {
2197        return strongInfo_;
2198    }
2199
2200    /// Return mutable strong info
2201    inline int * mutableStrongInfo() {
2202        return strongInfo_;
2203    }
2204    /// Get stored row cuts for donor/recipient CbcModel
2205    CglStored * storedRowCuts() const {
2206        return storedRowCuts_;
2207    }
2208    /// Set stored row cuts for donor/recipient CbcModel
2209    void setStoredRowCuts(CglStored * cuts) {
2210        storedRowCuts_ = cuts;
2211    }
2212    /// Says whether all dynamic integers
2213    inline bool allDynamic () const {
2214        return ((ownership_&0x40000000) != 0) ;
2215    }
2216    /// Create C++ lines to get to current state
2217    void generateCpp( FILE * fp, int options);
2218    /// Generate an OsiBranchingInformation object
2219    OsiBranchingInformation usefulInformation() const;
2220    /** Warm start object produced by heuristic or strong branching
2221
2222        If get a valid integer solution outside branch and bound then it can take
2223        a reasonable time to solve LP which produces clean solution.  If this object has
2224        any size then it will be used in solve.
2225    */
2226    inline void setBestSolutionBasis(const CoinWarmStartBasis & bestSolutionBasis) {
2227        bestSolutionBasis_ = bestSolutionBasis;
2228    }
2229    /// Redo walkback arrays
2230    void redoWalkBack();
2231    //@}
2232
2233//---------------------------------------------------------------------------
2234
2235private:
2236    ///@name Private member data
2237    //@{
2238
2239    /// The solver associated with this model.
2240    OsiSolverInterface * solver_;
2241
2242    /** Ownership of objects and other stuff
2243
2244        0x80000000 model owns solver
2245        0x40000000 all variables CbcDynamicPseudoCost
2246    */
2247    unsigned int ownership_ ;
2248
2249    /// A copy of the solver, taken at the continuous (root) node.
2250    OsiSolverInterface * continuousSolver_;
2251
2252    /// A copy of the solver, taken at constructor or by saveReferenceSolver
2253    OsiSolverInterface * referenceSolver_;
2254
2255    /// Message handler
2256    CoinMessageHandler * handler_;
2257
2258    /** Flag to say if handler_ is the default handler.
2259
2260      The default handler is deleted when the model is deleted. Other
2261      handlers (supplied by the client) will not be deleted.
2262    */
2263    bool defaultHandler_;
2264
2265    /// Cbc messages
2266    CoinMessages messages_;
2267
2268    /// Array for integer parameters
2269    int intParam_[CbcLastIntParam];
2270
2271    /// Array for double parameters
2272    double dblParam_[CbcLastDblParam];
2273
2274    /** Pointer to an empty warm start object
2275
2276      It turns out to be useful to have this available as a base from
2277      which to build custom warm start objects. This is typed as CoinWarmStart
2278      rather than CoinWarmStartBasis to allow for the possibility that a
2279      client might want to apply a solver that doesn't use a basis-based warm
2280      start. See getEmptyBasis for an example of how this field can be used.
2281    */
2282    mutable CoinWarmStart *emptyWarmStart_ ;
2283
2284    /// Best objective
2285    double bestObjective_;
2286    /// Best possible objective
2287    double bestPossibleObjective_;
2288    /// Sum of Changes to objective by first solve
2289    double sumChangeObjective1_;
2290    /// Sum of Changes to objective by subsequent solves
2291    double sumChangeObjective2_;
2292
2293    /// Array holding the incumbent (best) solution.
2294    double * bestSolution_;
2295    /// Arrays holding other solutions.
2296    double ** savedSolutions_;
2297
2298    /** Array holding the current solution.
2299
2300      This array is used more as a temporary.
2301    */
2302    double * currentSolution_;
2303    /** For testing infeasibilities - will point to
2304        currentSolution_ or solver-->getColSolution()
2305    */
2306    mutable const double * testSolution_;
2307    /** Warm start object produced by heuristic or strong branching
2308
2309        If get a valid integer solution outside branch and bound then it can take
2310        a reasonable time to solve LP which produces clean solution.  If this object has
2311        any size then it will be used in solve.
2312    */
2313    CoinWarmStartBasis bestSolutionBasis_ ;
2314    /// Global cuts
2315    OsiCuts globalCuts_;
2316
2317    /// Minimum degradation in objective value to continue cut generation
2318    double minimumDrop_;
2319    /// Number of solutions
2320    int numberSolutions_;
2321    /// Number of saved solutions
2322    int numberSavedSolutions_;
2323    /// Maximum number of saved solutions
2324    int maximumSavedSolutions_;
2325    /** State of search
2326        0 - no solution
2327        1 - only heuristic solutions
2328        2 - branched to a solution
2329        3 - no solution but many nodes
2330    */
2331    int stateOfSearch_;
2332    /// At which depths to do cuts
2333    int whenCuts_;
2334    /// Hotstart solution
2335    double * hotstartSolution_;
2336    /// Hotstart priorities
2337    int * hotstartPriorities_;
2338    /// Number of heuristic solutions
2339    int numberHeuristicSolutions_;
2340    /// Cumulative number of nodes
2341    int numberNodes_;
2342    /** Cumulative number of nodes for statistics.
2343        Must fix to match up
2344    */
2345    int numberNodes2_;
2346    /// Cumulative number of iterations
2347    int numberIterations_;
2348    /// Cumulative number of solves
2349    int numberSolves_;
2350    /// Status of problem - 0 finished, 1 stopped, 2 difficulties
2351    int status_;
2352    /** Secondary status of problem
2353        -1 unset (status_ will also be -1)
2354        0 search completed with solution
2355        1 linear relaxation not feasible (or worse than cutoff)
2356        2 stopped on gap
2357        3 stopped on nodes
2358        4 stopped on time
2359        5 stopped on user event
2360        6 stopped on solutions
2361     */
2362    int secondaryStatus_;
2363    /// Number of integers in problem
2364    int numberIntegers_;
2365    /// Number of rows at continuous
2366    int numberRowsAtContinuous_;
2367    /// Maximum number of cuts
2368    int maximumNumberCuts_;
2369    /** Current phase (so heuristics etc etc can find out).
2370        0 - initial solve
2371        1 - solve with cuts at root
2372        2 - solve with cuts
2373        3 - other e.g. strong branching
2374        4 - trying to validate a solution
2375        5 - at end of search
2376    */
2377    int phase_;
2378
2379    /// Number of entries in #addedCuts_
2380    int currentNumberCuts_;
2381
2382    /** Current limit on search tree depth
2383
2384      The allocated size of #walkback_. Increased as needed.
2385    */
2386    int maximumDepth_;
2387    /** Array used to assemble the path between a node and the search tree root
2388
2389      The array is resized when necessary. #maximumDepth_  is the current
2390      allocated size.
2391    */
2392    CbcNodeInfo ** walkback_;
2393    CbcNodeInfo ** lastNodeInfo_;
2394    const OsiRowCut ** lastCut_;
2395    int lastDepth_;
2396    int lastNumberCuts2_;
2397    int maximumCuts_;
2398    int * lastNumberCuts_;
2399
2400    /** The list of cuts initially collected for this subproblem
2401
2402      When the subproblem at this node is rebuilt, a set of cuts is collected
2403      for inclusion in the constraint system. If any of these cuts are
2404      subsequently removed because they have become loose, the corresponding
2405      entry is set to NULL.
2406    */
2407    CbcCountRowCut ** addedCuts_;
2408
2409    /** A pointer to a row cut which will be added instead of normal branching.
2410        After use it should be set to NULL.
2411    */
2412    OsiRowCut * nextRowCut_;
2413
2414    /// Current node so can be used elsewhere
2415    CbcNode * currentNode_;
2416
2417    /// Indices of integer variables
2418    int * integerVariable_;
2419    /// Whether of not integer
2420    char * integerInfo_;
2421    /// Holds solution at continuous (after cuts)
2422    double * continuousSolution_;
2423    /// Array marked whenever a solution is found if non-zero
2424    int * usedInSolution_;
2425    /**
2426        Special options
2427        0 bit (1) - check if cuts valid (if on debugger list)
2428        1 bit (2) - use current basis to check integer solution (rather than all slack)
2429        2 bit (4) - don't check integer solution (by solving LP)
2430        3 bit (8) - fast analyze
2431        4 bit (16) - non-linear model - so no well defined CoinPackedMatrix
2432        5 bit (32) - keep names
2433        6 bit (64) - try for dominated columns
2434        7 bit (128) - SOS type 1 but all declared integer
2435        8 bit (256) - Set to say solution just found, unset by doing cuts
2436        9 bit (512) - Try reduced model after 100 nodes
2437        10 bit (1024) - Switch on some heuristics even if seems unlikely
2438        11 bit (2048) - Mark as in small branch and bound
2439        12 bit (4096) - Funny cuts so do slow way (in some places)
2440        13 bit (8192) - Funny cuts so do slow way (in other places)
2441        14 bit (16384) - Use Cplex! for fathoming
2442        15 bit (32768) - Try reduced model after 0 nodes
2443        16 bit (65536) - Original model had integer bounds
2444        17 bit (131072) - Perturbation switched off
2445        18 bit (262144) - donor CbcModel
2446        19 bit (524288) - recipient CbcModel
2447    */
2448    int specialOptions_;
2449    /** More special options
2450        at present bottom 6 bits used for shadow price mode
2451        1024 for experimental hotstart
2452        2048,4096 breaking out of cuts
2453        8192 slowly increase minimum drop
2454        16384 gomory
2455        32768 more heuristics in sub trees
2456        65536 no cuts in preprocessing
2457        131072 Time limits elapsed
2458    */
2459    int moreSpecialOptions_;
2460    /// User node comparison function
2461    CbcCompareBase * nodeCompare_;
2462    /// User feasibility function (see CbcFeasibleBase.hpp)
2463    CbcFeasibilityBase * problemFeasibility_;
2464    /// Tree
2465    CbcTree * tree_;
2466    /// A pointer to model to be used for subtrees
2467    CbcModel * subTreeModel_;
2468    /// Number of times any subtree stopped on nodes, time etc
2469    int numberStoppedSubTrees_;
2470    /// Variable selection function
2471    CbcBranchDecision * branchingMethod_;
2472    /// Cut modifier function
2473    CbcCutModifier * cutModifier_;
2474    /// Strategy
2475    CbcStrategy * strategy_;
2476    /// Parent model
2477    CbcModel * parentModel_;
2478    /** Whether to automatically do presolve before branch and bound.
2479        0 - no
2480        1 - ordinary presolve
2481        2 - integer presolve (dodgy)
2482    */
2483    /// Pointer to array[getNumCols()] (for speed) of column lower bounds
2484    const double * cbcColLower_;
2485    /// Pointer to array[getNumCols()] (for speed) of column upper bounds
2486    const double * cbcColUpper_;
2487    /// Pointer to array[getNumRows()] (for speed) of row lower bounds
2488    const double * cbcRowLower_;
2489    /// Pointer to array[getNumRows()] (for speed) of row upper bounds
2490    const double * cbcRowUpper_;
2491    /// Pointer to array[getNumCols()] (for speed) of primal solution vector
2492    const double * cbcColSolution_;
2493    /// Pointer to array[getNumRows()] (for speed) of dual prices
2494    const double * cbcRowPrice_;
2495    /// Get a pointer to array[getNumCols()] (for speed) of reduced costs
2496    const double * cbcReducedCost_;
2497    /// Pointer to array[getNumRows()] (for speed) of row activity levels.
2498    const double * cbcRowActivity_;
2499    /// Pointer to user-defined data structure
2500    void * appData_;
2501    /// Presolve for CbcTreeLocal
2502    int presolve_;
2503    /** Maximum number of candidates to consider for strong branching.
2504      To disable strong branching, set this to 0.
2505    */
2506    int numberStrong_;
2507    /** \brief The number of branches before pseudo costs believed
2508           in dynamic strong branching.
2509
2510      A value of 0 is  off.
2511    */
2512    int numberBeforeTrust_;
2513    /** \brief The number of variables for which to compute penalties
2514           in dynamic strong branching.
2515    */
2516    int numberPenalties_;
2517    /// For threads - stop after this many "iterations"
2518    int stopNumberIterations_;
2519    /** Scale factor to make penalties match strong.
2520        Should/will be computed */
2521    double penaltyScaleFactor_;
2522    /// Number of analyze iterations to do
2523    int numberAnalyzeIterations_;
2524    /// Arrays with analysis results
2525    double * analyzeResults_;
2526    /// Number of nodes infeasible by normal branching (before cuts)
2527    int numberInfeasibleNodes_;
2528    /** Problem type as set by user or found by analysis.  This will be extended
2529        0 - not known
2530        1 - Set partitioning <=
2531        2 - Set partitioning ==
2532        3 - Set covering
2533    */
2534    int problemType_;
2535    /// Print frequency
2536    int printFrequency_;
2537    /// Number of cut generators
2538    int numberCutGenerators_;
2539    // Cut generators
2540    CbcCutGenerator ** generator_;
2541    // Cut generators before any changes
2542    CbcCutGenerator ** virginGenerator_;
2543    /// Number of heuristics
2544    int numberHeuristics_;
2545    /// Heuristic solvers
2546    CbcHeuristic ** heuristic_;
2547    /// Pointer to heuristic solver which found last solution (or NULL)
2548    CbcHeuristic * lastHeuristic_;
2549# ifdef COIN_HAS_CLP
2550    /// Depth for fast nodes
2551    int fastNodeDepth_;
2552#endif
2553    /*! Pointer to the event handler */
2554# ifdef CBC_ONLY_CLP
2555    ClpEventHandler *eventHandler_ ;
2556# else
2557    CbcEventHandler *eventHandler_ ;
2558# endif
2559
2560    /// Total number of objects
2561    int numberObjects_;
2562
2563    /** \brief Integer and Clique and ... information
2564
2565      \note The code assumes that the first objects on the list will be
2566        SimpleInteger objects for each integer variable, followed by
2567        Clique objects. Portions of the code that understand Clique objects
2568        will fail if they do not immediately follow the SimpleIntegers.
2569        Large chunks of the code will fail if the first objects are not
2570        SimpleInteger. As of 2003.08, SimpleIntegers and Cliques are the only
2571        objects.
2572    */
2573    OsiObject ** object_;
2574    /// Now we may not own objects - just point to solver's objects
2575    bool ownObjects_;
2576
2577    /// Original columns as created by integerPresolve or preprocessing
2578    int * originalColumns_;
2579    /// How often to scan global cuts
2580    int howOftenGlobalScan_;
2581    /** Number of times global cuts violated.  When global cut pool then this
2582        should be kept for each cut and type of cut */
2583    int numberGlobalViolations_;
2584    /// Number of extra iterations in fast lp
2585    int numberExtraIterations_;
2586    /// Number of extra nodes in fast lp
2587    int numberExtraNodes_;
2588    /** Value of objective at continuous
2589        (Well actually after initial round of cuts)
2590    */
2591    double continuousObjective_;
2592    /** Value of objective before root node cuts added
2593    */
2594    double originalContinuousObjective_;
2595    /// Number of infeasibilities at continuous
2596    int continuousInfeasibilities_;
2597    /// Maximum number of cut passes at root
2598    int maximumCutPassesAtRoot_;
2599    /// Maximum number of cut passes
2600    int maximumCutPasses_;
2601    /// Preferred way of branching
2602    int preferredWay_;
2603    /// Current cut pass number
2604    int currentPassNumber_;
2605    /// Maximum number of cuts (for whichGenerator_)
2606    int maximumWhich_;
2607    /// Maximum number of rows
2608    int maximumRows_;
2609    /// Current depth
2610    int currentDepth_;
2611    /// Thread specific random number generator
2612    mutable CoinThreadRandom randomNumberGenerator_;
2613    /// Work basis for temporary use
2614    CoinWarmStartBasis workingBasis_;
2615    /// Which cut generator generated this cut
2616    int * whichGenerator_;
2617    /// Maximum number of statistics
2618    int maximumStatistics_;
2619    /// statistics
2620    CbcStatistics ** statistics_;
2621    /// Maximum depth reached
2622    int maximumDepthActual_;
2623    /// Number of reduced cost fixings
2624    double numberDJFixed_;
2625    /// Probing info
2626    CglTreeProbingInfo * probingInfo_;
2627    /// Number of fixed by analyze at root
2628    int numberFixedAtRoot_;
2629    /// Number fixed by analyze so far
2630    int numberFixedNow_;
2631    /// Whether stopping on gap
2632    bool stoppedOnGap_;
2633    /// Whether event happened
2634    mutable bool eventHappened_;
2635    /// Number of long strong goes
2636    int numberLongStrong_;
2637    /// Number of old active cuts
2638    int numberOldActiveCuts_;
2639    /// Number of new cuts
2640    int numberNewCuts_;
2641    /// Strategy worked out - mainly at root node
2642    int searchStrategy_;
2643    /// Number of iterations in strong branching
2644    int numberStrongIterations_;
2645    /** 0 - number times strong branching done, 1 - number fixed, 2 - number infeasible
2646        Second group of three is a snapshot at node [6] */
2647    int strongInfo_[7];
2648    /**
2649        For advanced applications you may wish to modify the behavior of Cbc
2650        e.g. if the solver is a NLP solver then you may not have an exact
2651        optimum solution at each step.  This gives characteristics - just for one BAB.
2652        For actually saving/restoring a solution you need the actual solver one.
2653    */
2654    OsiBabSolver * solverCharacteristics_;
2655    /// Whether to force a resolve after takeOffCuts
2656    bool resolveAfterTakeOffCuts_;
2657    /// Maximum number of iterations (designed to be used in heuristics)
2658    int maximumNumberIterations_;
2659    /// Anything with priority >= this can be treated as continuous
2660    int continuousPriority_;
2661    /// Number of outstanding update information items
2662    int numberUpdateItems_;
2663    /// Maximum number of outstanding update information items
2664    int maximumNumberUpdateItems_;
2665    /// Update items
2666    CbcObjectUpdateData * updateItems_;
2667    /// Stored row cuts for donor/recipient CbcModel
2668    CglStored * storedRowCuts_;
2669    /**
2670       Parallel
2671       0 - off
2672       1 - testing
2673       2-99 threads
2674       other special meanings
2675    */
2676    int numberThreads_;
2677    /** thread mode
2678        always use numberThreads for branching
2679        1 set then deterministic
2680        2 set then use numberThreads for root cuts
2681        4 set then use numberThreads in root mini branch and bound
2682        default is 0
2683    */
2684    int threadMode_;
2685    /// Thread stuff for master
2686    CbcBaseModel * master_;
2687    /// Pointer to masterthread
2688    CbcThread * masterThread_;
2689//@}
2690};
2691/// So we can use osiObject or CbcObject during transition
2692void getIntegerInformation(const OsiObject * object, double & originalLower,
2693                           double & originalUpper) ;
2694// So we can call from other programs
2695// Real main program
2696class OsiClpSolverInterface;
2697int CbcMain (int argc, const char *argv[], OsiClpSolverInterface & solver, CbcModel ** babSolver);
2698int CbcMain (int argc, const char *argv[], CbcModel & babSolver);
2699// four ways of calling
2700int callCbc(const char * input2, OsiClpSolverInterface& solver1);
2701int callCbc(const char * input2);
2702int callCbc(const std::string input2, OsiClpSolverInterface& solver1);
2703int callCbc(const std::string input2) ;
2704// When we want to load up CbcModel with options first
2705void CbcMain0 (CbcModel & babSolver);
2706int CbcMain1 (int argc, const char *argv[], CbcModel & babSolver);
2707// two ways of calling
2708int callCbc(const char * input2, CbcModel & babSolver);
2709int callCbc(const std::string input2, CbcModel & babSolver);
2710// And when CbcMain0 already called to initialize
2711int callCbc1(const char * input2, CbcModel & babSolver);
2712int callCbc1(const std::string input2, CbcModel & babSolver);
2713// And when CbcMain0 already called to initialize (with call back) (see CbcMain1 for whereFrom)
2714int callCbc1(const char * input2, CbcModel & babSolver, int (CbcModel * currentSolver, int whereFrom));
2715int callCbc1(const std::string input2, CbcModel & babSolver, int (CbcModel * currentSolver, int whereFrom));
2716int CbcMain1 (int argc, const char *argv[], CbcModel & babSolver, int (CbcModel * currentSolver, int whereFrom));
2717// For uniform setting of cut and heuristic options
2718void setCutAndHeuristicOptions(CbcModel & model);
2719#endif
2720
Note: See TracBrowser for help on using the repository browser.