/* $Id: ClpGubDynamicMatrix.hpp 2385 2019-01-06 19:43:06Z unxusr $ */
// 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 ClpGubDynamicMatrix_H
#define ClpGubDynamicMatrix_H

#include "CoinPragma.hpp"

#include "ClpGubMatrix.hpp"
/** This implements Gub rows plus a ClpPackedMatrix.
    This a dynamic version which stores the gub part and dynamically creates matrix.
    All bounds are assumed to be zero and infinity

    This is just a simple example for real column generation
*/

class ClpGubDynamicMatrix : public ClpGubMatrix {

public:
  /**@name Main functions provided */
  //@{
  /// Partial pricing
  virtual void partialPricing(ClpSimplex *model, double start, double end,
    int &bestSequence, int &numberWanted);
  /** 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=8  - make sure set is clean
         mode=9  - adjust lower, upper on set by incoming
     */
  virtual int synchronize(ClpSimplex *model, int mode);
  /// Sets up an effective RHS and does gub crash if needed
  virtual void useEffectiveRhs(ClpSimplex *model, bool cheapest = true);
  /**
        update information for a pivot (and effective rhs)
     */
  virtual int updatePivot(ClpSimplex *model, double oldInValue, double oldOutValue);
  /// Add a new variable to a set
  void insertNonBasic(int sequence, int iSet);
  /** 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);

  using ClpPackedMatrix::times;
  /** Return <code>y + A * scalar *x</code> in <code>y</code>.
         @pre <code>x</code> must be of size <code>numColumns()</code>
         @pre <code>y</code> must be of size <code>numRows()</code> */
  virtual void times(double scalar,
    const double *x, double *y) const;
  /** Just for debug
         Returns sum and number of primal infeasibilities. Recomputes keys
     */
  virtual int checkFeasible(ClpSimplex *model, double &sum) const;
  /// Cleans data after setWarmStart
  void cleanData(ClpSimplex *model);
  //@}

  /**@name Constructors, destructor */
  //@{
  /** Default constructor. */
  ClpGubDynamicMatrix();
  /** Destructor */
  virtual ~ClpGubDynamicMatrix();
  //@}

  /**@name Copy method */
  //@{
  /** The copy constructor. */
  ClpGubDynamicMatrix(const ClpGubDynamicMatrix &);
  /** This is the real constructor.
         It assumes factorization frequency will not be changed.
         This resizes model !!!!
      */
  ClpGubDynamicMatrix(ClpSimplex *model, int numberSets,
    int numberColumns, const int *starts,
    const double *lower, const double *upper,
    const CoinBigIndex *startColumn, const int *row,
    const double *element, const double *cost,
    const double *lowerColumn = NULL, const double *upperColumn = NULL,
    const unsigned char *status = NULL);

  ClpGubDynamicMatrix &operator=(const ClpGubDynamicMatrix &);
  /// Clone
  virtual ClpMatrixBase *clone() const;
  //@}
  /**@name gets and sets */
  //@{
  /// enums for status of various sorts
  enum DynamicStatus {
    inSmall = 0x01,
    atUpperBound = 0x02,
    atLowerBound = 0x03
  };
  /// Whether flagged
  inline bool flagged(int i) const
  {
    return (dynamicStatus_[i] & 8) != 0;
  }
  inline void setFlagged(int i)
  {
    dynamicStatus_[i] = static_cast< unsigned char >(dynamicStatus_[i] | 8);
  }
  inline void unsetFlagged(int i)
  {
    dynamicStatus_[i] = static_cast< unsigned char >(dynamicStatus_[i] & ~8);
  }
  inline void setDynamicStatus(int sequence, DynamicStatus status)
  {
    unsigned char &st_byte = dynamicStatus_[sequence];
    st_byte = static_cast< unsigned char >(st_byte & ~7);
    st_byte = static_cast< unsigned char >(st_byte | status);
  }
  inline DynamicStatus getDynamicStatus(int sequence) const
  {
    return static_cast< DynamicStatus >(dynamicStatus_[sequence] & 7);
  }
  /// Saved value of objective offset
  inline double objectiveOffset() const
  {
    return objectiveOffset_;
  }
  /// Starts of each column
  inline CoinBigIndex *startColumn() const
  {
    return startColumn_;
  }
  /// rows
  inline int *row() const
  {
    return row_;
  }
  /// elements
  inline double *element() const
  {
    return element_;
  }
  /// costs
  inline double *cost() const
  {
    return cost_;
  }
  /// full starts
  inline int *fullStart() const
  {
    return fullStart_;
  }
  /// ids of active columns (just index here)
  inline int *id() const
  {
    return id_;
  }
  /// Optional lower bounds on columns
  inline double *lowerColumn() const
  {
    return lowerColumn_;
  }
  /// Optional upper bounds on columns
  inline double *upperColumn() const
  {
    return upperColumn_;
  }
  /// Optional true lower bounds on sets
  inline double *lowerSet() const
  {
    return lowerSet_;
  }
  /// Optional true upper bounds on sets
  inline double *upperSet() const
  {
    return upperSet_;
  }
  /// size
  inline int numberGubColumns() const
  {
    return numberGubColumns_;
  }
  /// first free
  inline int firstAvailable() const
  {
    return firstAvailable_;
  }
  /// set first free
  inline void setFirstAvailable(int value)
  {
    firstAvailable_ = value;
  }
  /// first dynamic
  inline int firstDynamic() const
  {
    return firstDynamic_;
  }
  /// number of columns in dynamic model
  inline int lastDynamic() const
  {
    return lastDynamic_;
  }
  /// size of working matrix (max)
  inline CoinBigIndex numberElements() const
  {
    return numberElements_;
  }
  /// Status region for gub slacks
  inline unsigned char *gubRowStatus() const
  {
    return status_;
  }
  /// Status region for gub variables
  inline unsigned char *dynamicStatus() const
  {
    return dynamicStatus_;
  }
  /// Returns which set a variable is in
  int whichSet(int sequence) const;
  //@}

protected:
  /**@name Data members
        The data members are protected to allow access for derived classes. */
  //@{
  /// Saved value of objective offset
  double objectiveOffset_;
  /// Starts of each column
  CoinBigIndex *startColumn_;
  /// rows
  int *row_;
  /// elements
  double *element_;
  /// costs
  double *cost_;
  /// full starts
  int *fullStart_;
  /// ids of active columns (just index here)
  int *id_;
  /// for status and which bound
  unsigned char *dynamicStatus_;
  /// Optional lower bounds on columns
  double *lowerColumn_;
  /// Optional upper bounds on columns
  double *upperColumn_;
  /// Optional true lower bounds on sets
  double *lowerSet_;
  /// Optional true upper bounds on sets
  double *upperSet_;
  /// size
  int numberGubColumns_;
  /// first free
  int firstAvailable_;
  /// saved first free
  int savedFirstAvailable_;
  /// first dynamic
  int firstDynamic_;
  /// number of columns in dynamic model
  int lastDynamic_;
  /// size of working matrix (max)
  CoinBigIndex numberElements_;
  //@}
};

#endif

/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
*/
