ClpDynamicMatrix.hpp 12.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
/* $Id$ */
// Copyright (C) 2004, International Business Machines
// Corporation and others.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).

#ifndef ClpDynamicMatrix_H
#define ClpDynamicMatrix_H

#include "CoinPragma.hpp"

#include "ClpPackedMatrix.hpp"
class ClpSimplex;
/** This implements  a dynamic matrix when we have a limit on the number of
    "interesting rows". This version inherits from ClpPackedMatrix and knows that
    the real matrix is gub.  A later version could use shortest path to generate columns.

*/

class ClpDynamicMatrix : public ClpPackedMatrix {

public:
  /// enums for status of various sorts
  enum DynamicStatus {
    soloKey = 0x00,
    inSmall = 0x01,
    atUpperBound = 0x02,
    atLowerBound = 0x03
  };
  /**@name Main functions provided */
  //@{
  /// Partial pricing
  virtual void partialPricing(ClpSimplex *model, double start, double end,
    int &bestSequence, int &numberWanted);

  /**
        update information for a pivot (and effective rhs)
     */
  virtual int updatePivot(ClpSimplex *model, double oldInValue, double oldOutValue);
  /** Returns effective RHS offset if it is being used.  This is used for long problems
         or big dynamic 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;
  /// Modifies rhs offset
  void modifyOffset(int sequence, double amount);
  /// Gets key value when none in small
  double keyValue(int iSet) const;
  /**
         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);
  /** Purely for column generation and similar ideas.  Allows
         matrix and any bounds or costs to be updated (sensibly).
         Returns non-zero if any changes.
     */
  virtual int refresh(ClpSimplex *model);
  /** Creates a variable.  This is called after partial pricing and will modify matrix.
         Will update bestSequence.
     */
  virtual void createVariable(ClpSimplex *model, int &bestSequence);
  /// Returns reduced cost of a variable
  virtual double reducedCost(ClpSimplex *model, int sequence) const;
  /// Does gub crash
  void gubCrash();
  /// Writes out model (without names)
  void writeMps(const char *name);
  /// Populates initial matrix from dynamic status
  void initialProblem();
  /** Adds in a column to gub structure (called from descendant) and returns sequence */
  int addColumn(CoinBigIndex numberEntries, const int *row, const double *element,
    double cost, double lower, double upper, int iSet,
    DynamicStatus status);
  /** If addColumn forces compression then this allows descendant to know what to do.
         If >=0 then entry stayed in, if -1 then entry went out to lower bound.of zero.
         Entries at upper bound (really nonzero) never go out (at present).
     */
  virtual void packDown(const int *, int) {}
  /// Gets lower bound (to simplify coding)
  inline double columnLower(int sequence) const
  {
    if (columnLower_)
      return columnLower_[sequence];
    else
      return 0.0;
  }
  /// Gets upper bound (to simplify coding)
  inline double columnUpper(int sequence) const
  {
    if (columnUpper_)
      return columnUpper_[sequence];
    else
      return COIN_DBL_MAX;
  }

  //@}

  /**@name Constructors, destructor */
  //@{
  /** Default constructor. */
  ClpDynamicMatrix();
  /** This is the real constructor.
         It assumes factorization frequency will not be changed.
         This resizes model !!!!
         The contents of original matrix in model will be taken over and original matrix
         will be sanitized so can be deleted (to avoid a very small memory leak)
      */
  ClpDynamicMatrix(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 *columnLower = NULL, const double *columnUpper = NULL,
    const unsigned char *status = NULL,
    const unsigned char *dynamicStatus = NULL);

  /** Destructor */
  virtual ~ClpDynamicMatrix();
  //@}

  /**@name Copy method */
  //@{
  /** The copy constructor. */
  ClpDynamicMatrix(const ClpDynamicMatrix &);
  /** The copy constructor from an CoinPackedMatrix. */
  ClpDynamicMatrix(const CoinPackedMatrix &);

  ClpDynamicMatrix &operator=(const ClpDynamicMatrix &);
  /// Clone
  virtual ClpMatrixBase *clone() const;
  //@}
  /**@name gets and sets */
  //@{
  /// Status of row slacks
  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);
  }
  /// Whether flagged slack
  inline bool flaggedSlack(int i) const
  {
    return (status_[i] & 8) != 0;
  }
  inline void setFlaggedSlack(int i)
  {
    status_[i] = static_cast< unsigned char >(status_[i] | 8);
  }
  inline void unsetFlaggedSlack(int i)
  {
    status_[i] = static_cast< unsigned char >(status_[i] & ~8);
  }
  /// Number of sets (dynamic rows)
  inline int numberSets() const
  {
    return numberSets_;
  }
  /// Number of possible gub variables
  inline int numberGubEntries() const
  {
    return startSet_[numberSets_];
  }
  /// Sets
  inline int *startSets() const
  {
    return startSet_;
  }
  /// 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_;
  }
  /// ids of active columns (just index here)
  inline int *id() const
  {
    return id_;
  }
  /// Optional lower bounds on columns
  inline double *columnLower() const
  {
    return columnLower_;
  }
  /// Optional upper bounds on columns
  inline double *columnUpper() const
  {
    return columnUpper_;
  }
  /// Lower bounds on sets
  inline double *lowerSet() const
  {
    return lowerSet_;
  }
  /// 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_;
  }
  /// first dynamic
  inline int firstDynamic() const
  {
    return firstDynamic_;
  }
  /// number of columns in dynamic model
  inline int lastDynamic() const
  {
    return lastDynamic_;
  }
  /// number of rows in original model
  inline int numberStaticRows() const
  {
    return numberStaticRows_;
  }
  /// size of working matrix (max)
  inline CoinBigIndex numberElements() const
  {
    return numberElements_;
  }
  inline int *keyVariable() const
  {
    return keyVariable_;
  }
  /// Switches off dj checking each factorization (for BIG models)
  void switchOffCheck();
  /// 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. */
  //@{
  /// 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_;
  /// Saved best dual on gub row in pricing
  double savedBestGubDual_;
  /// Saved best set in pricing
  int savedBestSet_;
  /// Backward pointer to pivot row !!!
  int *backToPivotRow_;
  /// Key variable of set (only accurate if none in small problem)
  mutable int *keyVariable_;
  /// Backward pointer to extra row
  int *toIndex_;
  // Reverse pointer from index to set
  int *fromIndex_;
  /// Number of sets (dynamic rows)
  int numberSets_;
  /// Number of active sets
  int numberActiveSets_;
  /// Saved value of objective offset
  double objectiveOffset_;
  /// Lower bounds on sets
  double *lowerSet_;
  /// Upper bounds on sets
  double *upperSet_;
  /// Status of slack on set
  unsigned char *status_;
  /// Pointer back to model
  ClpSimplex *model_;
  /// first free
  int firstAvailable_;
  /// first free when iteration started
  int firstAvailableBefore_;
  /// first dynamic
  int firstDynamic_;
  /// number of columns in dynamic model
  int lastDynamic_;
  /// number of rows in original model
  int numberStaticRows_;
  /// size of working matrix (max)
  CoinBigIndex numberElements_;
  /// 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_;
  /// Infeasibility weight when last full pass done
  double infeasibilityWeight_;
  /// size
  int numberGubColumns_;
  /// current maximum number of columns (then compress)
  int maximumGubColumns_;
  /// current maximum number of elemnts (then compress)
  CoinBigIndex maximumElements_;
  /// Start of each set
  int *startSet_;
  /// next in chain
  int *next_;
  /// Starts of each column
  CoinBigIndex *startColumn_;
  /// rows
  int *row_;
  /// elements
  double *element_;
  /// costs
  double *cost_;
  /// ids of active columns (just index here)
  int *id_;
  /// for status and which bound
  unsigned char *dynamicStatus_;
  /// Optional lower bounds on columns
  double *columnLower_;
  /// Optional upper bounds on columns
  double *columnUpper_;
  //@}
};

#endif

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