forked from coin-or/Clp
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathAbcMatrix.hpp
675 lines (655 loc) · 21 KB
/
AbcMatrix.hpp
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
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
/* $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 <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> */
void timesModifyExcludingSlacks(double scalar,
const double *x, double *y) const;
/** Return <code>y + A * scalar(+-1) *x</code> in <code>y</code>.
@pre <code>x</code> must be of size <code>numColumns()+numRows()</code>
@pre <code>y</code> must be of size <code>numRows()</code> */
void timesModifyIncludingSlacks(double scalar,
const double *x, double *y) const;
/** Return <code>A * scalar(+-1) *x</code> in <code>y</code>.
@pre <code>x</code> must be of size <code>numColumns()+numRows()</code>
@pre <code>y</code> must be of size <code>numRows()</code> */
void timesIncludingSlacks(double scalar,
const double *x, double *y) const;
/** Return A * scalar(+-1) *x + y</code> in <code>y</code>.
@pre <code>x</code> must be of size <code>numRows()</code>
@pre <code>y</code> must be of size <code>numRows()+numColumns()</code> */
void transposeTimesNonBasic(double scalar,
const double *x, double *y) const;
/** Return y - A * x</code> in <code>y</code>.
@pre <code>x</code> must be of size <code>numRows()</code>
@pre <code>y</code> must be of size <code>numRows()+numColumns()</code> */
void transposeTimesAll(const double *x, double *y) const;
/** Return y + A * scalar(+-1) *x</code> in <code>y</code>.
@pre <code>x</code> must be of size <code>numRows()</code>
@pre <code>y</code> must be of size <code>numRows()</code> */
void transposeTimesBasic(double scalar,
const double *x, double *y) const;
/** Return <code>x * scalar * A/code> in <code>z</code>.
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 <code>x *A</code> in <code>z</code> but
just for indices Already in z.
Note - z always packed mode */
void subsetTransposeTimes(const CoinIndexedVector &x,
CoinIndexedVector &z) const;
/// Return <code>-x *A</code> in <code>z</code>
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 <pthread.h>
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 <code>x * -1 * A in <code>z</code>.
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 <code>x * -1 * A in <code>z</code>.
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
*/