/* $Id$ */
// Copyright (C) 2002, International Business Machines
// Corporation and others, Copyright (C) 2012, FasterCoin. All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).
#ifndef AbcMatrix_H
#define AbcMatrix_H
#include "CoinPragma.hpp"
#include "ClpMatrixBase.hpp"
#include "AbcSimplex.hpp"
#include "CoinAbcHelperFunctions.hpp"
/** This implements a scaled version of CoinPackedMatrix
It may have THREE! copies
1) scaled CoinPackedMatrix without gaps
2) row copy non-basic,basic, fixed
3) vector copy
*/
class AbcMatrix2;
class AbcMatrix3;
class AbcMatrix {
public:
/**@name Useful methods */
//@{
/// Return a complete CoinPackedMatrix
inline CoinPackedMatrix *getPackedMatrix() const
{
return matrix_;
}
/** Whether the packed matrix is column major ordered or not. */
inline bool isColOrdered() const
{
return true;
}
/** Number of entries in the packed matrix. */
inline CoinBigIndex getNumElements() const
{
return matrix_->getNumElements();
}
/** Number of columns. */
inline int getNumCols() const
{
assert(matrix_->getNumCols() == model_->numberColumns());
return matrix_->getNumCols();
}
/** Number of rows. */
inline int getNumRows() const
{
assert(matrix_->getNumRows() == model_->numberRows());
return matrix_->getNumRows();
}
/// Sets model
void setModel(AbcSimplex *model);
/// A vector containing the elements in the packed matrix.
inline const double *getElements() const
{
return matrix_->getElements();
}
/// Mutable elements
inline double *getMutableElements() const
{
return matrix_->getMutableElements();
}
/// A vector containing the minor indices of the elements in the packed matrix.
inline const int *getIndices() const
{
return matrix_->getIndices();
}
/// A vector containing the minor indices of the elements in the packed matrix.
inline int *getMutableIndices() const
{
return matrix_->getMutableIndices();
}
/// Starts
inline const CoinBigIndex *getVectorStarts() const
{
return matrix_->getVectorStarts();
}
inline CoinBigIndex *getMutableVectorStarts() const
{
return matrix_->getMutableVectorStarts();
}
/** The lengths of the major-dimension vectors. */
inline const int *getVectorLengths() const
{
return matrix_->getVectorLengths();
}
/** The lengths of the major-dimension vectors. */
inline int *getMutableVectorLengths() const
{
return matrix_->getMutableVectorLengths();
}
/// Row starts
CoinBigIndex *rowStart() const;
/// Row ends
CoinBigIndex *rowEnd() const;
/// Row elements
double *rowElements() const;
/// Row columns
CoinSimplexInt *rowColumns() const;
/** Returns a new matrix in reverse order without gaps */
CoinPackedMatrix *reverseOrderedCopy() const;
/// Returns number of elements in column part of basis
CoinBigIndex countBasis(const int *whichColumn,
int &numberColumnBasic);
/// Fills in column part of basis
void fillBasis(const int *whichColumn,
int &numberColumnBasic,
int *row, int *start,
int *rowCount, int *columnCount,
CoinSimplexDouble *element);
/// Fills in column part of basis
void fillBasis(const int *whichColumn,
int &numberColumnBasic,
int *row, int *start,
int *rowCount, int *columnCount,
long double *element);
/** Scales and creates row copy
*/
void scale(int numberRowsAlreadyScaled);
/// Creates row copy
void createRowCopy();
/// Take out of useful
void takeOutOfUseful(int sequence, CoinIndexedVector &spare);
/// Put into useful
void putIntofUseful(int sequence, CoinIndexedVector &spare);
/// Put in and out for useful
void inOutUseful(int sequenceIn, int sequenceOut);
/// Make all useful
void makeAllUseful(CoinIndexedVector &spare);
/// Sort into useful
void sortUseful(CoinIndexedVector &spare);
/// Move largest in column to beginning (not used as doesn't help factorization)
void moveLargestToStart();
/** Unpacks a column into an CoinIndexedVector
*/
void unpack(CoinIndexedVector &rowArray,
int column) const;
/** Adds multiple of a column (or slack) into an CoinIndexedvector
You can use quickAdd to add to vector */
void add(CoinIndexedVector &rowArray, int column, double multiplier) const;
//@}
/**@name Matrix times vector methods */
//@{
/** Return y + A * scalar *x
in y
.
@pre x
must be of size numColumns()
@pre y
must be of size numRows()
*/
void timesModifyExcludingSlacks(double scalar,
const double *x, double *y) const;
/** Return y + A * scalar(+-1) *x
in y
.
@pre x
must be of size numColumns()+numRows()
@pre y
must be of size numRows()
*/
void timesModifyIncludingSlacks(double scalar,
const double *x, double *y) const;
/** Return A * scalar(+-1) *x
in y
.
@pre x
must be of size numColumns()+numRows()
@pre y
must be of size numRows()
*/
void timesIncludingSlacks(double scalar,
const double *x, double *y) const;
/** Return A * scalar(+-1) *x + y in y
.
@pre x
must be of size numRows()
@pre y
must be of size numRows()+numColumns()
*/
void transposeTimesNonBasic(double scalar,
const double *x, double *y) const;
/** Return y - A * x in y
.
@pre x
must be of size numRows()
@pre y
must be of size numRows()+numColumns()
*/
void transposeTimesAll(const double *x, double *y) const;
/** Return y + A * scalar(+-1) *x in y
.
@pre x
must be of size numRows()
@pre y
must be of size numRows()
*/
void transposeTimesBasic(double scalar,
const double *x, double *y) const;
/** Return x * scalar * A/code> in z
.
Note - x unpacked mode - z packed mode including slacks
All these return atLo/atUp first then free/superbasic
number of first set returned
pivotVariable is extended to have that order
reversePivotVariable used to update that list
free/superbasic only stored in normal format
can use spare array to get this effect
may put djs alongside atLo/atUp
Squashes small elements and knows about AbcSimplex */
int transposeTimesNonBasic(double scalar,
const CoinIndexedVector &x,
CoinIndexedVector &z) const;
/// gets sorted tableau row and a possible value of theta
double dualColumn1(const CoinIndexedVector &update,
CoinPartitionedVector &tableauRow,
CoinPartitionedVector &candidateList) const;
/// gets sorted tableau row and a possible value of theta
double dualColumn1Row(int iBlock, double upperThetaSlack, int &freeSequence,
const CoinIndexedVector &update,
CoinPartitionedVector &tableauRow,
CoinPartitionedVector &candidateList) const;
/// gets sorted tableau row and a possible value of theta
double dualColumn1RowFew(int iBlock, double upperThetaSlack, int &freeSequence,
const CoinIndexedVector &update,
CoinPartitionedVector &tableauRow,
CoinPartitionedVector &candidateList) const;
/// gets sorted tableau row and a possible value of theta
double dualColumn1Row2(double upperThetaSlack, int &freeSequence,
const CoinIndexedVector &update,
CoinPartitionedVector &tableauRow,
CoinPartitionedVector &candidateList) const;
/// gets sorted tableau row and a possible value of theta
double dualColumn1Row1(double upperThetaSlack, int &freeSequence,
const CoinIndexedVector &update,
CoinPartitionedVector &tableauRow,
CoinPartitionedVector &candidateList) const;
/** gets sorted tableau row and a possible value of theta
On input first,last give what to scan
On output is number in tableauRow and candidateList */
void dualColumn1Part(int iBlock, int &sequenceIn, double &upperTheta,
const CoinIndexedVector &update,
CoinPartitionedVector &tableauRow,
CoinPartitionedVector &candidateList) const;
/// rebalance for parallel
void rebalance() const;
/// Get sequenceIn when Dantzig
int pivotColumnDantzig(const CoinIndexedVector &updates,
CoinPartitionedVector &spare) const;
/// Get sequenceIn when Dantzig (One block)
int pivotColumnDantzig(int iBlock, bool doByRow, const CoinIndexedVector &updates,
CoinPartitionedVector &spare,
double &bestValue) const;
/// gets tableau row - returns number of slacks in block
int primalColumnRow(int iBlock, bool doByRow, const CoinIndexedVector &update,
CoinPartitionedVector &tableauRow) const;
/// gets tableau row and dj row - returns number of slacks in block
int primalColumnRowAndDjs(int iBlock, const CoinIndexedVector &updateTableau,
const CoinIndexedVector &updateDjs,
CoinPartitionedVector &tableauRow) const;
/** Chooses best weighted dj
*/
int chooseBestDj(int iBlock, const CoinIndexedVector &infeasibilities,
const double *weights) const;
/** does steepest edge double or triple update
If scaleFactor!=0 then use with tableau row to update djs
otherwise use updateForDjs
Returns best sequence
*/
int primalColumnDouble(int iBlock, CoinPartitionedVector &updateForTableauRow,
CoinPartitionedVector &updateForDjs,
const CoinIndexedVector &updateForWeights,
CoinPartitionedVector &spareColumn1,
double *infeasibilities,
double referenceIn, double devex,
// Array for exact devex to say what is in reference framework
unsigned int *reference,
double *weights, double scaleFactor) const;
/** does steepest edge double or triple update
If scaleFactor!=0 then use with tableau row to update djs
otherwise use updateForDjs
Returns best sequence
*/
int primalColumnSparseDouble(int iBlock, CoinPartitionedVector &updateForTableauRow,
CoinPartitionedVector &updateForDjs,
const CoinIndexedVector &updateForWeights,
CoinPartitionedVector &spareColumn1,
double *infeasibilities,
double referenceIn, double devex,
// Array for exact devex to say what is in reference framework
unsigned int *reference,
double *weights, double scaleFactor) const;
/** does steepest edge double or triple update
If scaleFactor!=0 then use with tableau row to update djs
otherwise use updateForDjs
Returns best sequence
*/
int primalColumnDouble(CoinPartitionedVector &updateForTableauRow,
CoinPartitionedVector &updateForDjs,
const CoinIndexedVector &updateForWeights,
CoinPartitionedVector &spareColumn1,
CoinIndexedVector &infeasible,
double referenceIn, double devex,
// Array for exact devex to say what is in reference framework
unsigned int *reference,
double *weights, double scaleFactor) const;
/// gets subset updates
void primalColumnSubset(int iBlock, const CoinIndexedVector &update,
const CoinPartitionedVector &tableauRow,
CoinPartitionedVector &weights) const;
/// Partial pricing
void partialPricing(double startFraction, double endFraction,
int &bestSequence, int &numberWanted);
/** Return x *A
in z
but
just for indices Already in z.
Note - z always packed mode */
void subsetTransposeTimes(const CoinIndexedVector &x,
CoinIndexedVector &z) const;
/// Return -x *A
in z
void transposeTimes(const CoinIndexedVector &x,
CoinIndexedVector &z) const;
//@}
/**@name Other */
//@{
/// Returns CoinPackedMatrix (non const)
inline CoinPackedMatrix *matrix() const
{
return matrix_;
}
/** Partial pricing tuning parameter - minimum number of "objects" to scan.
e.g. number of Gub sets but could be number of variables */
inline int minimumObjectsScan() const
{
return minimumObjectsScan_;
}
inline void setMinimumObjectsScan(int value)
{
minimumObjectsScan_ = value;
}
/// Partial pricing tuning parameter - minimum number of negative reduced costs to get
inline int minimumGoodReducedCosts() const
{
return minimumGoodReducedCosts_;
}
inline void setMinimumGoodReducedCosts(int value)
{
minimumGoodReducedCosts_ = value;
}
/// Current start of search space in matrix (as fraction)
inline double startFraction() const
{
return startFraction_;
}
inline void setStartFraction(double value)
{
startFraction_ = value;
}
/// Current end of search space in matrix (as fraction)
inline double endFraction() const
{
return endFraction_;
}
inline void setEndFraction(double value)
{
endFraction_ = value;
}
/// Current best reduced cost
inline double savedBestDj() const
{
return savedBestDj_;
}
inline void setSavedBestDj(double value)
{
savedBestDj_ = value;
}
/// Initial number of negative reduced costs wanted
inline int originalWanted() const
{
return originalWanted_;
}
inline void setOriginalWanted(int value)
{
originalWanted_ = value;
}
/// Current number of negative reduced costs which we still need
inline int currentWanted() const
{
return currentWanted_;
}
inline void setCurrentWanted(int value)
{
currentWanted_ = value;
}
/// Current best sequence
inline int savedBestSequence() const
{
return savedBestSequence_;
}
inline void setSavedBestSequence(int value)
{
savedBestSequence_ = value;
}
/// Start of each column block
inline int *startColumnBlock() const
{
return startColumnBlock_;
}
/// Start of each block (in stored)
inline const int *blockStart() const
{
return blockStart_;
}
inline bool gotRowCopy() const
{
return rowStart_ != 0;
}
/// Start of each block (in stored)
inline int blockStart(int block) const
{
return blockStart_[block];
}
/// Number of actual column blocks
inline int numberColumnBlocks() const
{
return numberColumnBlocks_;
}
/// Number of actual row blocks
inline int numberRowBlocks() const
{
return numberRowBlocks_;
}
//@}
/**@name Constructors, destructor */
//@{
/** Default constructor. */
AbcMatrix();
/** Destructor */
~AbcMatrix();
//@}
/**@name Copy method */
//@{
/** The copy constructor. */
AbcMatrix(const AbcMatrix &);
/** The copy constructor from an CoinPackedMatrix. */
AbcMatrix(const CoinPackedMatrix &);
/** Subset constructor (without gaps). Duplicates are allowed
and order is as given */
AbcMatrix(const AbcMatrix &wholeModel,
int numberRows, const int *whichRows,
int numberColumns, const int *whichColumns);
AbcMatrix(const CoinPackedMatrix &wholeModel,
int numberRows, const int *whichRows,
int numberColumns, const int *whichColumns);
AbcMatrix &operator=(const AbcMatrix &);
/// Copy contents - resizing if necessary - otherwise re-use memory
void copy(const AbcMatrix *from);
//@}
private:
protected:
/**@name Data members
The data members are protected to allow access for derived classes. */
//@{
/// Data
CoinPackedMatrix *matrix_;
/// Model
mutable AbcSimplex *model_;
#if ABC_PARALLEL == 0
#define NUMBER_ROW_BLOCKS 1
#define NUMBER_COLUMN_BLOCKS 1
#elif ABC_PARALLEL == 1
#define NUMBER_ROW_BLOCKS 4
#define NUMBER_COLUMN_BLOCKS 4
#else
#define NUMBER_ROW_BLOCKS 8
#define NUMBER_COLUMN_BLOCKS 8
#endif
/** Start of each row (per block) - last lot are useless
first all row starts for block 0, then for block2
so NUMBER_ROW_BLOCKS+2 times number rows */
CoinBigIndex *rowStart_;
/// Values by row
double *element_;
/// Columns
int *column_;
/// Start of each column block
mutable int startColumnBlock_[NUMBER_COLUMN_BLOCKS + 1];
/// Start of each block (in stored)
int blockStart_[NUMBER_ROW_BLOCKS + 1];
/// Number of actual column blocks
mutable int numberColumnBlocks_;
/// Number of actual row blocks
int numberRowBlocks_;
//#define COUNT_COPY
#ifdef COUNT_COPY
#define MAX_COUNT 13
/// Start in elements etc
CoinBigIndex countStart_[MAX_COUNT + 1];
/// First column
int countFirst_[MAX_COUNT + 1];
// later int countEndUseful_[MAX_COUNT+1];
int *countRealColumn_;
// later int * countInverseRealColumn_;
CoinBigIndex *countStartLarge_;
int *countRow_;
double *countElement_;
int smallestCount_;
int largestCount_;
#endif
/// Special row copy
//AbcMatrix2 * rowCopy_;
/// Special column copy
//AbcMatrix3 * columnCopy_;
/// Current start of search space in matrix (as fraction)
double startFraction_;
/// Current end of search space in matrix (as fraction)
double endFraction_;
/// Best reduced cost so far
double savedBestDj_;
/// Initial number of negative reduced costs wanted
int originalWanted_;
/// Current number of negative reduced costs which we still need
int currentWanted_;
/// Saved best sequence in pricing
int savedBestSequence_;
/// Partial pricing tuning parameter - minimum number of "objects" to scan
int minimumObjectsScan_;
/// Partial pricing tuning parameter - minimum number of negative reduced costs to get
int minimumGoodReducedCosts_;
//@}
};
#ifdef THREAD
#include
typedef struct {
double acceptablePivot;
const AbcSimplex *model;
double *spare;
int *spareIndex;
double *arrayTemp;
int *indexTemp;
int *numberInPtr;
double *bestPossiblePtr;
double *upperThetaPtr;
int *posFreePtr;
double *freePivotPtr;
int *numberOutPtr;
const unsigned short *count;
const double *pi;
const CoinBigIndex *rowStart;
const double *element;
const unsigned short *column;
int offset;
int numberInRowArray;
int numberLook;
} dualColumn0Struct;
#endif
class AbcMatrix2 {
public:
/**@name Useful methods */
//@{
/** Return x * -1 * A in z
.
Note - x packed and z will be packed mode
Squashes small elements and knows about AbcSimplex */
void transposeTimes(const AbcSimplex *model,
const CoinPackedMatrix *rowCopy,
const CoinIndexedVector &x,
CoinIndexedVector &spareArray,
CoinIndexedVector &z) const;
/// Returns true if copy has useful information
inline bool usefulInfo() const
{
return rowStart_ != NULL;
}
//@}
/**@name Constructors, destructor */
//@{
/** Default constructor. */
AbcMatrix2();
/** Constructor from copy. */
AbcMatrix2(AbcSimplex *model, const CoinPackedMatrix *rowCopy);
/** Destructor */
~AbcMatrix2();
//@}
/**@name Copy method */
//@{
/** The copy constructor. */
AbcMatrix2(const AbcMatrix2 &);
AbcMatrix2 &operator=(const AbcMatrix2 &);
//@}
protected:
/**@name Data members
The data members are protected to allow access for derived classes. */
//@{
/// Number of blocks
int numberBlocks_;
/// Number of rows
int numberRows_;
/// Column offset for each block (plus one at end)
int *offset_;
/// Counts of elements in each part of row
mutable unsigned short *count_;
/// Row starts
mutable CoinBigIndex *rowStart_;
/// columns within block
unsigned short *column_;
/// work arrays
double *work_;
#ifdef THREAD
pthread_t *threadId_;
dualColumn0Struct *info_;
#endif
//@}
};
typedef struct {
CoinBigIndex startElements_; // point to data
int startIndices_; // point to column_
int numberInBlock_;
int numberPrice_; // at beginning
int numberElements_; // number elements per column
} blockStruct3;
class AbcMatrix3 {
public:
/**@name Useful methods */
//@{
/** Return x * -1 * A in z
.
Note - x packed and z will be packed mode
Squashes small elements and knows about AbcSimplex */
void transposeTimes(const AbcSimplex *model,
const double *pi,
CoinIndexedVector &output) const;
/// Updates two arrays for steepest
void transposeTimes2(const AbcSimplex *model,
const double *pi, CoinIndexedVector &dj1,
const double *piWeight,
double referenceIn, double devex,
// Array for exact devex to say what is in reference framework
unsigned int *reference,
double *weights, double scaleFactor);
//@}
/**@name Constructors, destructor */
//@{
/** Default constructor. */
AbcMatrix3();
/** Constructor from copy. */
AbcMatrix3(AbcSimplex *model, const CoinPackedMatrix *columnCopy);
/** Destructor */
~AbcMatrix3();
//@}
/**@name Copy method */
//@{
/** The copy constructor. */
AbcMatrix3(const AbcMatrix3 &);
AbcMatrix3 &operator=(const AbcMatrix3 &);
//@}
/**@name Sort methods */
//@{
/** Sort blocks */
void sortBlocks(const AbcSimplex *model);
/// Swap one variable
void swapOne(const AbcSimplex *model, const AbcMatrix *matrix,
int iColumn);
//@}
protected:
/**@name Data members
The data members are protected to allow access for derived classes. */
//@{
/// Number of blocks
int numberBlocks_;
/// Number of columns
int numberColumns_;
/// Column indices and reverse lookup (within block)
int *column_;
/// Starts for odd/long vectors
CoinBigIndex *start_;
/// Rows
int *row_;
/// Elements
double *element_;
/// Blocks (ordinary start at 0 and go to first block)
blockStruct *block_;
//@}
};
#endif
/* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
*/