// $Id$ // Copyright (C) 2000, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef CglTreeInfo_H #define CglTreeInfo_H #include "OsiCuts.hpp" #include "OsiSolverInterface.hpp" #include "CoinHelperFunctions.hpp" class CglStored; /** Information about where the cut generator is invoked from. */ class CglTreeInfo { public: /// The level of the search tree node int level; /** How many times the cut generator was already invoked in this search tree node */ int pass; /** The number of rows in the original formulation. Some generators may not want to consider already generated rows when generating new ones. */ int formulation_rows; /** Options 1 - treat costed integers as important 2 - switch off some stuff as variables semi-integer 4 - set global cut flag if at root node 8 - set global cut flag if at root node and first pass 16 - set global cut flag and make cuts globally valid 32 - last round of cuts did nothing - maybe be more aggressive 64 - in preprocessing stage 128 - looks like solution 256 - want alternate cuts 512 - in sub tree (i.e. parent model) 1024 - in must call again mode or after everything mode */ int options; /// Set true if in tree (to avoid ambiguity at first branch) bool inTree; /** nonzero if called from child of main model 1 if heuristic run 2 if doing full search */ int hasParent; /// parent solver OsiSolverInterface *parentSolver; /// Original columns (if preprocessed) int *originalColumns; /** Replacement array. Before Branch and Cut it may be beneficial to strengthen rows rather than adding cuts. If this array is not NULL then the cut generator can place a pointer to the stronger cut in this array which is number of rows in size. A null (i.e. zero elements and free rhs) cut indicates that the row is useless and can be removed. The calling function can then replace those rows. */ OsiRowCut **strengthenRow; /// Optional pointer to thread specific random number generator CoinThreadRandom *randomNumberGenerator; /// Default constructor CglTreeInfo(); /// Copy constructor CglTreeInfo( const CglTreeInfo &); /// Clone virtual CglTreeInfo *clone() const; /// Assignment operator CglTreeInfo & operator=( const CglTreeInfo &rhs); /// Destructor virtual ~CglTreeInfo(); /// Take action if cut generator can fix a variable (toValue -1 for down, +1 for up) virtual bool fixes(int, int, int, bool) { return false; } /** Initalizes fixing arrays etc - returns >0 if we want to save info 0 if we don't and -1 if is to be used */ virtual int initializeFixing(const OsiSolverInterface *) { return 0; } }; /** Derived class to pick up probing info. */ typedef struct { //unsigned int oneFixed:1; // nonzero if variable to 1 fixes all //unsigned int sequence:31; // variable (in matrix) (but also see cliqueRow_) unsigned int fixes; } CliqueEntry; class CglTreeProbingInfo : public CglTreeInfo { public: /// Default constructor CglTreeProbingInfo(); /// Constructor from model CglTreeProbingInfo(const OsiSolverInterface *model); /// Copy constructor CglTreeProbingInfo( const CglTreeProbingInfo &); /// Clone virtual CglTreeInfo *clone() const; /// Assignment operator CglTreeProbingInfo & operator=( const CglTreeProbingInfo &rhs); /// Destructor virtual ~CglTreeProbingInfo(); OsiSolverInterface *analyze(const OsiSolverInterface &si, int createSolver = 0, int numberExtraCliques = 0, const CoinBigIndex *starts = NULL, const CliqueEntry *entries = NULL, const char *type = NULL); /** Take action if cut generator can fix a variable (toValue -1 for down, +1 for up) Returns true if still room, false if not */ virtual bool fixes(int variable, int toValue, int fixedVariable, bool fixedToLower); /** Initalizes fixing arrays etc - returns >0 if we want to save info 0 if we don't and -1 if is to be used */ virtual int initializeFixing(const OsiSolverInterface *model); /// Fix entries in a solver using implications int fixColumns(OsiSolverInterface &si) const; /// Fix entries in a solver using implications for one variable int fixColumns(int iColumn, int value, OsiSolverInterface &si) const; /// Packs down entries int packDown(); /// Generate cuts from implications void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, const CglTreeInfo info) const; /// Entries for fixing variables inline CliqueEntry *fixEntries() { convert(); return fixEntry_; } /// Starts of integer variable going to zero inline int *toZero() { convert(); return toZero_; } /// Starts of integer variable going to one inline int *toOne() { convert(); return toOne_; } /// List of 0-1 integer variables inline int *integerVariable() const { return integerVariable_; } /// Backward look up inline int *backward() const { return backward_; } /// Number of variables inline int numberVariables() const { return numberVariables_; } /// Number of 0-1 variables inline int numberIntegers() const { return numberIntegers_; } private: /// Converts to ordered void convert(); protected: /// Entries for fixing variables CliqueEntry *fixEntry_; /// Starts of integer variable going to zero int *toZero_; /// Starts of integer variable going to one int *toOne_; /// List of 0-1 integer variables int *integerVariable_; /// Backward look up int *backward_; /// Entries for fixing variable when collecting int *fixingEntry_; /// Number of variables int numberVariables_; /// Number of 0-1 variables int numberIntegers_; /// Maximum number in fixEntry_ int maximumEntries_; /// Number entries in fixingEntry_ (and fixEntry_) or -2 if correct style int numberEntries_; }; inline int sequenceInCliqueEntry(const CliqueEntry &cEntry) { return cEntry.fixes & 0x7fffffff; } inline void setSequenceInCliqueEntry(CliqueEntry &cEntry, int sequence) { cEntry.fixes = sequence | (cEntry.fixes & 0x80000000); } inline bool oneFixesInCliqueEntry(const CliqueEntry &cEntry) { return (cEntry.fixes & 0x80000000) != 0; } inline void setOneFixesInCliqueEntry(CliqueEntry &cEntry, bool oneFixes) { cEntry.fixes = (oneFixes ? 0x80000000 : 0) | (cEntry.fixes & 0x7fffffff); } #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */