/* $Id$ */ // Copyright (C) 2003, International Business Machines // Corporation and others. All Rights Reserved. // This code is licensed under the terms of the Eclipse Public License (EPL). #ifndef ClpGubMatrix_H #define ClpGubMatrix_H #include "CoinPragma.hpp" #include "ClpPackedMatrix.hpp" class ClpSimplex; /** This implements Gub rows plus a ClpPackedMatrix. There will be a version using ClpPlusMinusOne matrix but there is no point doing one with ClpNetworkMatrix (although an embedded network is attractive). */ class CLPLIB_EXPORT ClpGubMatrix : public ClpPackedMatrix { public: /**@name Main functions provided */ //@{ /** Returns a new matrix in reverse order without gaps (GUB wants NULL) */ virtual ClpMatrixBase *reverseOrderedCopy() const; /// Returns number of elements in column part of basis virtual int countBasis(const int *whichColumn, int &numberColumnBasic); /// Fills in column part of basis virtual void fillBasis(ClpSimplex *model, const int *whichColumn, int &numberColumnBasic, int *row, int *start, int *rowCount, int *columnCount, CoinFactorizationDouble *element); /** Unpacks a column into an CoinIndexedvector */ virtual void unpack(const ClpSimplex *model, CoinIndexedVector *rowArray, int column) const; /** Unpacks a column into an CoinIndexedvector ** in packed foramt Note that model is NOT const. Bounds and objective could be modified if doing column generation (just for this variable) */ virtual void unpackPacked(ClpSimplex *model, CoinIndexedVector *rowArray, int column) const; /** Adds multiple of a column into an CoinIndexedvector You can use quickAdd to add to vector */ virtual void add(const ClpSimplex *model, CoinIndexedVector *rowArray, int column, double multiplier) const; /** Adds multiple of a column into an array */ virtual void add(const ClpSimplex *model, double *array, int column, double multiplier) const; /// Partial pricing virtual void partialPricing(ClpSimplex *model, double start, double end, int &bestSequence, int &numberWanted); /// Returns number of hidden rows e.g. gub virtual int hiddenRows() const; //@} /**@name Matrix times vector methods */ //@{ using ClpPackedMatrix::transposeTimes; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex */ virtual void transposeTimes(const ClpSimplex *model, double scalar, const CoinIndexedVector *x, CoinIndexedVector *y, CoinIndexedVector *z) const; /** Return x * scalar * A + y in z. Can use y as temporary array (will be empty at end) Note - If x packed mode - then z packed mode Squashes small elements and knows about ClpSimplex. This version uses row copy*/ virtual void transposeTimesByRow(const ClpSimplex *model, double scalar, const CoinIndexedVector *x, CoinIndexedVector *y, CoinIndexedVector *z) const; /** Return x *A in z but just for indices in y. Note - z always packed mode */ virtual void subsetTransposeTimes(const ClpSimplex *model, const CoinIndexedVector *x, const CoinIndexedVector *y, CoinIndexedVector *z) const; /** expands an updated column to allow for extra rows which the main solver does not know about and returns number added if mode 0. If mode 1 deletes extra entries This active in Gub */ virtual int extendUpdated(ClpSimplex *model, CoinIndexedVector *update, int mode); /** mode=0 - Set up before "update" and "times" for primal solution using extended rows mode=1 - Cleanup primal solution after "times" using extended rows. mode=2 - Check (or report on) primal infeasibilities */ virtual void primalExpanded(ClpSimplex *model, int mode); /** mode=0 - Set up before "updateTranspose" and "transposeTimes" for duals using extended updates array (and may use other if dual values pass) mode=1 - Update dual solution after "transposeTimes" using extended rows. mode=2 - Compute all djs and compute key dual infeasibilities mode=3 - Report on key dual infeasibilities mode=4 - Modify before updateTranspose in partial pricing */ virtual void dualExpanded(ClpSimplex *model, CoinIndexedVector *array, double *other, int mode); /** mode=0 - Create list of non-key basics in pivotVariable_ using number as numberBasic in and out mode=1 - Set all key variables as basic mode=2 - return number extra rows needed, number gives maximum number basic mode=3 - before replaceColumn mode=4 - return 1 if can do primal, 2 if dual, 3 if both mode=5 - save any status stuff (when in good state) mode=6 - restore status stuff mode=7 - flag given variable (normally sequenceIn) mode=8 - unflag all variables mode=9 - synchronize costs mode=10 - return 1 if there may be changing bounds on variable (column generation) mode=11 - make sure set is clean (used when a variable rejected - but not flagged) mode=12 - after factorize but before permute stuff mode=13 - at end of simplex to delete stuff */ virtual int generalExpanded(ClpSimplex *model, int mode, int &number); /** update information for a pivot (and effective rhs) */ virtual int updatePivot(ClpSimplex *model, double oldInValue, double oldOutValue); /// Sets up an effective RHS and does gub crash if needed virtual void useEffectiveRhs(ClpSimplex *model, bool cheapest = true); /** Returns effective RHS offset if it is being used. This is used for long problems or big gub or anywhere where going through full columns is expensive. This may re-compute */ virtual double *rhsOffset(ClpSimplex *model, bool forceRefresh = false, bool check = false); /** This is local to Gub to allow synchronization: mode=0 when status of basis is good mode=1 when variable is flagged mode=2 when all variables unflagged (returns number flagged) mode=3 just reset costs (primal) mode=4 correct number of dual infeasibilities mode=5 return 4 if time to re-factorize mode=6 - return 1 if there may be changing bounds on variable (column generation) mode=7 - do extra restores for column generation mode=8 - make sure set is clean mode=9 - adjust lower, upper on set by incoming */ virtual int synchronize(ClpSimplex *model, int mode); /// Correct sequence in and out to give true value virtual void correctSequence(const ClpSimplex *model, int &sequenceIn, int &sequenceOut); //@} /**@name Constructors, destructor */ //@{ /** Default constructor. */ ClpGubMatrix(); /** Destructor */ virtual ~ClpGubMatrix(); //@} /**@name Copy method */ //@{ /** The copy constructor. */ ClpGubMatrix(const ClpGubMatrix &); /** The copy constructor from an CoinPackedMatrix. */ ClpGubMatrix(const CoinPackedMatrix &); /** Subset constructor (without gaps). Duplicates are allowed and order is as given */ ClpGubMatrix(const ClpGubMatrix &wholeModel, int numberRows, const int *whichRows, int numberColumns, const int *whichColumns); ClpGubMatrix(const CoinPackedMatrix &wholeModel, int numberRows, const int *whichRows, int numberColumns, const int *whichColumns); /** This takes over ownership (for space reasons) */ ClpGubMatrix(CoinPackedMatrix *matrix); /** This takes over ownership (for space reasons) and is the real constructor*/ ClpGubMatrix(ClpPackedMatrix *matrix, int numberSets, const int *start, const int *end, const double *lower, const double *upper, const unsigned char *status = NULL); ClpGubMatrix &operator=(const ClpGubMatrix &); /// Clone virtual ClpMatrixBase *clone() const; /** Subset clone (without gaps). Duplicates are allowed and order is as given */ virtual ClpMatrixBase *subsetClone( int numberRows, const int *whichRows, int numberColumns, const int *whichColumns) const; /** redoes next_ for a set. */ void redoSet(ClpSimplex *model, int newKey, int oldKey, int iSet); //@} /**@name gets and sets */ //@{ /// Status inline ClpSimplex::Status getStatus(int sequence) const { return static_cast< ClpSimplex::Status >(status_[sequence] & 7); } inline void setStatus(int sequence, ClpSimplex::Status status) { unsigned char &st_byte = status_[sequence]; st_byte = static_cast< unsigned char >(st_byte & ~7); st_byte = static_cast< unsigned char >(st_byte | status); } /// To flag a variable inline void setFlagged(int sequence) { status_[sequence] = static_cast< unsigned char >(status_[sequence] | 64); } inline void clearFlagged(int sequence) { status_[sequence] = static_cast< unsigned char >(status_[sequence] & ~64); } inline bool flagged(int sequence) const { return ((status_[sequence] & 64) != 0); } /// To say key is above ub inline void setAbove(int sequence) { unsigned char iStat = status_[sequence]; iStat = static_cast< unsigned char >(iStat & ~24); status_[sequence] = static_cast< unsigned char >(iStat | 16); } /// To say key is feasible inline void setFeasible(int sequence) { unsigned char iStat = status_[sequence]; iStat = static_cast< unsigned char >(iStat & ~24); status_[sequence] = static_cast< unsigned char >(iStat | 8); } /// To say key is below lb inline void setBelow(int sequence) { unsigned char iStat = status_[sequence]; iStat = static_cast< unsigned char >(iStat & ~24); status_[sequence] = iStat; } inline double weight(int sequence) const { int iStat = status_[sequence] & 31; iStat = iStat >> 3; return static_cast< double >(iStat - 1); } /// Starts inline int *start() const { return start_; } /// End inline int *end() const { return end_; } /// Lower bounds on sets inline double *lower() const { return lower_; } /// Upper bounds on sets inline double *upper() const { return upper_; } /// Key variable of set inline int *keyVariable() const { return keyVariable_; } /// Backward pointer to set number inline int *backward() const { return backward_; } /// Number of sets (gub rows) inline int numberSets() const { return numberSets_; } /// Switches off dj checking each factorization (for BIG models) void switchOffCheck(); //@} protected: /**@name Data members The data members are protected to allow access for derived classes. */ //@{ /// Sum of dual infeasibilities double sumDualInfeasibilities_; /// Sum of primal infeasibilities double sumPrimalInfeasibilities_; /// Sum of Dual infeasibilities using tolerance based on error in duals double sumOfRelaxedDualInfeasibilities_; /// Sum of Primal infeasibilities using tolerance based on error in primals double sumOfRelaxedPrimalInfeasibilities_; /// Infeasibility weight when last full pass done double infeasibilityWeight_; /// Starts int *start_; /// End int *end_; /// Lower bounds on sets double *lower_; /// Upper bounds on sets double *upper_; /// Status of slacks mutable unsigned char *status_; /// Saved status of slacks unsigned char *saveStatus_; /// Saved key variables int *savedKeyVariable_; /// Backward pointer to set number int *backward_; /// Backward pointer to pivot row !!! int *backToPivotRow_; /// Change in costs for keys double *changeCost_; /// Key variable of set mutable int *keyVariable_; /** Next basic variable in set - starts at key and end with -(set+1). Now changes to -(nonbasic+1). next_ has extra space for 2* longest set */ mutable int *next_; /// Backward pointer to index in CoinIndexedVector int *toIndex_; // Reverse pointer from index to set int *fromIndex_; /// Pointer back to model ClpSimplex *model_; /// Number of dual infeasibilities int numberDualInfeasibilities_; /// Number of primal infeasibilities int numberPrimalInfeasibilities_; /** If pricing will declare victory (i.e. no check every factorization). -1 - always check 0 - don't check 1 - in don't check mode but looks optimal */ int noCheck_; /// Number of sets (gub rows) int numberSets_; /// Number in vector without gub extension int saveNumber_; /// Pivot row of possible next key int possiblePivotKey_; /// Gub slack in (set number or -1) int gubSlackIn_; /// First gub variables (same as start_[0] at present) int firstGub_; /// last gub variable (same as end_[numberSets_-1] at present) int lastGub_; /** type of gub - 0 not contiguous, 1 contiguous add 8 bit to say no ubs on individual variables */ int gubType_; //@} }; #endif /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2 */