source: branches/devel-1/PresolveMatrix.cpp @ 29

Last change on this file since 29 was 29, checked in by forrest, 18 years ago

Presolve (no changes to Makefile)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.7 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3
4#define CHECK_CONSISTENCY       1
5
6#include <stdio.h>
7
8#include <assert.h>
9#include <iostream>
10
11#include "CoinHelperFunctions.hpp"
12
13#include "CoinPackedMatrix.hpp"
14#include "ClpSimplex.hpp"
15
16#include "PresolveMatrix.hpp"
17#include "Presolve.hpp"
18
19void PresolveAction::throwCoinError(const char *error,
20                                       const char *ps_routine)
21{
22  throw CoinError(error, ps_routine, "Presolve");
23}
24
25
26  class presolvehlink;
27
28void presolve_make_memlists(int *starts, int *lengths,
29                       presolvehlink *link,
30                       int n);
31
32/*static*/ void presolve_prefix(const int *starts, int *diffs, int n, int limit);
33
34/*static*/ void presolve_prefix(const int *starts, int *diffs, int n, int limit)
35{
36  int i;
37
38  for (i=0; i<n; i++) {
39    diffs[i] = starts[i+1] - starts[i];
40  }
41}
42
43// afterward, link[i].pre is the largest index less than i st lengths[i]!=0
44//  (or -1 if all such lengths are 0).
45// link[i].suc is the opposite.
46// That is, it is the same thing as setting link[i].pre = i-1 and link[i].suc = i+1
47// and then deleting all the empty elements.
48// This list is maintained together with hrow/hcol so that as we relocate
49// columns or rows, we can quickly determine what column/row precedes a given
50// column/row in the memory region hrow/hcol.
51// Note that n itself has a pre and a suc.
52void presolve_make_memlists(int *starts, int *lengths, presolvehlink *link, int n)
53{
54  int i;
55  int pre = NO_LINK;
56 
57  for (i=0; i<n; i++) {
58    if (lengths[i]) {
59      link[i].pre = pre;
60      if (pre != NO_LINK)
61        link[pre].suc = i;
62      pre = i;
63    }
64    else {
65      link[i].pre = NO_LINK;
66      link[i].suc = NO_LINK;
67    }
68  }
69  if (pre != NO_LINK)
70    link[pre].suc = n;
71
72  // (1) Arbitrarily place the last non-empty entry in link[n].pre
73  link[n].pre = pre;
74
75  link[n].suc = NO_LINK;
76}
77
78
79
80double *presolve_duparray(const double *d, int n, int n2)
81{
82  double *d1 = new double[n2];
83  memcpy(d1, d, n*sizeof(double));
84  return (d1);
85}
86double *presolve_duparray(const double *d, int n)
87{
88  return presolve_duparray(d, n, n);
89}
90
91int *presolve_duparray(const int *d, int n, int n2)
92{
93  int *d1 = new int[n2];
94  memcpy(d1, d, n*sizeof(int));
95  return (d1);
96}
97int *presolve_duparray(const int *d, int n)
98{
99  return presolve_duparray(d, n, n);
100}
101
102char *presolve_duparray(const char *d, int n, int n2)
103{
104  char *d1 = new char[n2];
105  memcpy(d1, d, n*sizeof(char));
106  return (d1);
107}
108char *presolve_duparray(const char *d, int n)
109{
110  return presolve_duparray(d, n, n);
111}
112
113#if 0
114double *presolve_duparray(const double *d, int n, char **end_mmapp)
115{
116  double *d1 = (double*)*end_mmapp;
117  bcopy(d, d1, n*sizeof(double));
118  *end_mmapp += ALIGN_DOUBLE(n*sizeof(double));
119  return (d1);
120}
121int *presolve_duparray(const int *d, int n, char **end_mmapp)
122{
123  int *d1 = (int*)*end_mmapp;
124  bcopy(d, d1, n*sizeof(int));
125  *end_mmapp += ALIGN_DOUBLE(n*sizeof(int));
126  return (d1);
127}
128
129double *presolve_duparray(const double *d, int n, int n2, char **end_mmapp)
130{
131  double *d1 = (double*)*end_mmapp;
132  bcopy(d, d1, n*sizeof(double));
133  *end_mmapp += ALIGN_DOUBLE(n2*sizeof(double));
134  return (d1);
135}
136int *presolve_duparray(const int *d, int n, int n2, char **end_mmapp)
137{
138  int *d1 = (int*)*end_mmapp;
139  bcopy(d, d1, n*sizeof(int));
140  *end_mmapp += ALIGN_DOUBLE(n2*sizeof(int));
141  return (d1);
142}
143#endif
144
145
146int presolve_find_row(int row, int kcs, int kce, const int *hrow)
147{
148  int k;
149  for (k=kcs; k<kce; k++)
150    if (hrow[k] == row)
151      return (k);
152  DIE("FIND_ROW");
153  return (0);
154}
155
156int presolve_find_row1(int row, int kcs, int kce, const int *hrow)
157{
158  int k;
159  for (k=kcs; k<kce; k++)
160    if (hrow[k] == row)
161      return (k);
162  return (kce);
163}
164
165int presolve_find_row2(int irow, int ks, int nc, const int *hrow, const int *link)
166{
167  for (int i=0; i<nc; ++i) {
168    if (hrow[ks] == irow)
169      return (ks);
170    ks = link[ks];
171  }
172  abort();
173}
174
175int presolve_find_row3(int irow, int ks, int nc, const int *hrow, const int *link)
176{
177  for (int i=0; i<nc; ++i) {
178    if (hrow[ks] == irow)
179      return (ks);
180    ks = link[ks];
181  }
182  return (-1);
183}
184
185
186// delete the entry for col from row
187// this keeps the row loosely packed
188// if we didn't want to maintain that property, we could just decrement hinrow[row].
189void presolve_delete_from_row(int row, int col /* thing to delete */,
190                     const int *mrstrt,
191                     int *hinrow, int *hcol, double *dels)
192{
193  int krs = mrstrt[row];
194  int kre = krs + hinrow[row];
195
196  int kcol = presolve_find_row(col, krs, kre, hcol);
197
198  swap(hcol[kcol], hcol[kre-1]);
199  swap(dels[kcol], dels[kre-1]);
200  hinrow[row]--;
201}
202
203
204void presolve_delete_from_row2(int row, int col /* thing to delete */,
205                      int *mrstrt,
206                     int *hinrow, int *hcol, double *dels, int *link, int *free_listp)
207{
208  int k = mrstrt[row];
209
210  if (hcol[k] == col) {
211    mrstrt[row] = link[k];
212    link[k] = *free_listp;
213    *free_listp = k;
214    check_free_list(k);
215    hinrow[row]--;
216  } else {
217    int n = hinrow[row] - 1;
218    int k0 = k;
219    k = link[k];
220    for (int i=0; i<n; ++i) {
221      if (hcol[k] == col) {
222        link[k0] = link[k];
223        link[k] = *free_listp;
224        *free_listp = k;
225        check_free_list(k);
226        hinrow[row]--;
227        return;
228      }
229      k0 = k;
230      k = link[k];
231    }
232    abort();
233  }
234}
235
236static inline double getTolerance(const ClpSimplex &si, ClpDblParam key)
237{
238  double tol;
239  if (! si.getDblParam(key, tol)) {
240    PresolveAction::throwCoinError("getDblParam failed",
241                                      "PrePostsolveMatrix::PrePostsolveMatrix");
242  }
243  return (tol);
244}
245
246#if 0
247PresolveAction::~PresolveAction()
248{
249  cout << "OOPS\n";
250}
251#endif
252
253// Assumptions:
254// 1. nrows>=m.getNumRows()
255// 2. ncols>=m.getNumCols()
256//
257// In presolve, these values are equal.
258// In postsolve, they may be inequal, since the reduced problem
259// may be smaller, but we need room for the large problem.
260// ncols may be larger than si.getNumCols() in postsolve,
261// this at that point si will be the reduced problem,
262// but we need to reserve enough space for the original problem.
263PrePostsolveMatrix::PrePostsolveMatrix(const ClpSimplex& si,
264                                             int ncols_in,
265                                             int nrows_in,
266                                             int nelems_in) :
267  originalModel_(&si),
268  ncols_(si.getNumCols()),
269  ncols0_(ncols_in),
270  nelems_(si.getNumElements()),
271
272  mcstrt_(new int[ncols_in+1]),
273  hincol_(new int[ncols_in+1]),
274  hrow_  (new int   [2*nelems_in]),
275  colels_(new double[2*nelems_in]),
276
277  cost_(new double[ncols_in]),
278  clo_(new double[ncols_in]),
279  cup_(new double[ncols_in]),
280  rlo_(new double[nrows_in]),
281  rup_(new double[nrows_in]),
282  originalColumn_(new int[ncols_in]),
283
284  ztolzb_(getTolerance(si, ClpPrimalTolerance)),
285  ztoldj_(getTolerance(si, ClpDualTolerance)),
286
287  maxmin_(si.getObjSense()),
288
289  whichpass_(0)
290{
291  si.getDblParam(ClpObjOffset,originalOffset_);
292  int ncols = si.getNumCols();
293  int nrows = si.getNumRows();
294
295  CoinDisjointCopyN(si.getColLower(), ncols, clo_);
296  CoinDisjointCopyN(si.getColUpper(), ncols, cup_);
297  CoinDisjointCopyN(si.getObjCoefficients(), ncols, cost_);
298  CoinDisjointCopyN(si.getRowLower(), nrows,  rlo_);
299  CoinDisjointCopyN(si.getRowUpper(), nrows,  rup_);
300  int i;
301  for (i=0;i<ncols_in;i++) 
302    originalColumn_[i]=i;
303  sol_=NULL;
304  rowduals_=NULL;
305  acts_=NULL;
306
307  rcosts_=NULL;
308  colstat_=NULL;
309  rowstat_=NULL;
310}
311
312
313PrePostsolveMatrix::~PrePostsolveMatrix()
314{
315  delete[]mcstrt_;
316  delete[]hrow_;
317  delete[]colels_;
318  delete[]hincol_;
319
320  delete[]cost_;
321  delete[]clo_;
322  delete[]cup_;
323  delete[]rlo_;
324  delete[]rup_;
325  delete[]originalColumn_;
326  delete[]rowduals_;
327
328  delete[]rcosts_;
329}
330
331// Sets status (non -basic ) using value
332void 
333PrePostsolveMatrix::setRowStatusUsingValue(int iRow)
334{
335  double value = acts_[iRow];
336  double lower = rlo_[iRow];
337  double upper = rup_[iRow];
338  if (lower<-1.0e20&&upper>1.0e20) {
339    setRowStatus(iRow,isFree);
340  } else if (fabs(lower-value)<=ztolzb_) {
341    setRowStatus(iRow,atLowerBound);
342  } else if (fabs(upper-value)<=ztolzb_) {
343    setRowStatus(iRow,atUpperBound);
344  } else {
345    setRowStatus(iRow,superBasic);
346  }
347}
348void 
349PrePostsolveMatrix::setColumnStatusUsingValue(int iColumn)
350{
351  double value = sol_[iColumn];
352  double lower = clo_[iColumn];
353  double upper = cup_[iColumn];
354  if (lower<-1.0e20&&upper>1.0e20) {
355    setColumnStatus(iColumn,isFree);
356  } else if (fabs(lower-value)<=ztolzb_) {
357    setColumnStatus(iColumn,atLowerBound);
358  } else if (fabs(upper-value)<=ztolzb_) {
359    setColumnStatus(iColumn,atUpperBound);
360  } else {
361    setColumnStatus(iColumn,superBasic);
362  }
363}
364
365// I am not familiar enough with CoinPackedMatrix to be confident
366// that I will implement a row-ordered version of toColumnOrderedGapFree
367// properly.
368static bool isGapFree(const CoinPackedMatrix& matrix)
369{
370  const int * start = matrix.getVectorStarts();
371  const int * length = matrix.getVectorLengths();
372  int i;
373  for (i = matrix.getSizeVectorLengths() - 1; i >= 0; --i) {
374    if (start[i+1] - start[i] != length[i])
375      break;
376  }
377  return (! (i >= 0));
378}
379
380
381#if     DEBUG_PRESOLVE
382static void matrix_bounds_ok(const double *lo, const double *up, int n)
383{
384  int i;
385  for (i=0; i<n; i++) {
386    PRESOLVEASSERT(lo[i] <= up[i]);
387    PRESOLVEASSERT(lo[i] < PRESOLVE_INF);
388    PRESOLVEASSERT(-PRESOLVE_INF < up[i]);
389  }
390}
391#endif
392
393PresolveMatrix::PresolveMatrix(int ncols0_in,
394                                     double maxmin_,
395                                     // end prepost members
396
397                                     ClpSimplex &si,
398
399                                     // rowrep
400                                     int nrows_in,
401                                     int nelems_in,
402                               bool doStatus) :
403
404  PrePostsolveMatrix(si,
405                        ncols0_in, nrows_in, nelems_in),
406  clink_(new presolvehlink[ncols0_in+1]),
407  rlink_(new presolvehlink[nrows_in+1]),
408
409  dobias_(0.0),
410
411  nrows_(si.getNumRows()),
412
413  // temporary init
414  mrstrt_(new int[nrows_in+1]),
415  hinrow_(new int[nrows_in+1]),
416  rowels_(new double[2*nelems_in]),
417  hcol_(new int[2*nelems_in]),
418  integerType_(new char[ncols0_in]),
419  feasibilityTolerance_(0.0),
420  status_(-1),
421  rowsToDo_(new int [nrows_in]),
422  numberRowsToDo_(0),
423  nextRowsToDo_(new int[nrows_in]),
424  numberNextRowsToDo_(0),
425  colsToDo_(new int [ncols0_in]),
426  numberColsToDo_(0),
427  nextColsToDo_(new int[ncols0_in]),
428  numberNextColsToDo_(0)
429
430{
431  const int bufsize = 2*nelems_in;
432
433  // Set up change bits
434  rowChanged_ = new unsigned int[(nrows_+31)>>5];
435  memset(rowChanged_,0,((nrows_+31)>>5)*sizeof(unsigned int));
436  colChanged_ = new unsigned int[(ncols_+31)>>5];
437  memset(colChanged_,0,((ncols_+31)>>5)*sizeof(unsigned int));
438  CoinPackedMatrix * m = si.matrix();
439
440  // The coefficient matrix is a big hunk of stuff.
441  // Do the copy here to try to avoid running out of memory.
442
443  if (! isGapFree(*m)) {
444    PresolveAction::throwCoinError("getMatrixByCol not gap free",
445                                      "PrePostsolveMatrix");
446  }
447
448  CoinDisjointCopyN<int>(m->getVectorStarts(), ncols_, mcstrt_);
449  mcstrt_[ncols_] = nelems_;
450  CoinDisjointCopyN(m->getVectorLengths(),ncols_,  hincol_);
451  CoinDisjointCopyN(m->getIndices(),      nelems_, hrow_);
452  CoinDisjointCopyN(m->getElements(),     nelems_, colels_);
453
454  // same thing for row rep
455  m = new CoinPackedMatrix();
456  m->reverseOrderedCopyOf(*si.matrix());
457  m->removeGaps();
458
459
460  CoinDisjointCopyN(m->getVectorStarts(),  nrows_,  mrstrt_);
461  mrstrt_[nrows_] = nelems_;
462  CoinDisjointCopyN(m->getVectorLengths(), nrows_,  hinrow_);
463  CoinDisjointCopyN(m->getIndices(),       nelems_, hcol_);
464  CoinDisjointCopyN(m->getElements(),      nelems_, rowels_);
465
466  delete m;
467  if (si.integerInformation()) {
468    memcpy(integerType_,si.integerInformation(),ncols_*sizeof(char));
469  } else {
470    CoinFillN<char>(integerType_, ncols_, 0);
471  }
472
473  if (doStatus) {
474    // allow for status and solution
475    sol_ = new double[ncols_];
476    memcpy(sol_,si.primalColumnSolution(),ncols_*sizeof(double));;
477    acts_ = new double [nrows_];
478    memcpy(acts_,si.primalRowSolution(),nrows_*sizeof(double));
479    colstat_ = new unsigned char [nrows_+ncols_];
480    memcpy(colstat_,si.statusArray(),
481           (nrows_+ncols_)*sizeof(unsigned char));
482    rowstat_ = colstat_+ncols_;
483  }
484
485  // the original model's fields are now unneeded - free them
486 
487  si.resize(0,0);
488
489#if     DEBUG_PRESOLVE
490  matrix_bounds_ok(rlo_, rup_, nrows_);
491  matrix_bounds_ok(clo_, cup_, ncols_);
492#endif
493
494#if 0
495  for (int i=0; i<nrows; ++i)
496    printf("NR: %6d\n", hinrow[i]);
497  for (int i=0; i<ncols; ++i)
498    printf("NC: %6d\n", hincol[i]);
499#endif
500
501  presolve_make_memlists(mcstrt_, hincol_, clink_, ncols_);
502  presolve_make_memlists(mrstrt_, hinrow_, rlink_, nrows_);
503
504  // this allows last col/row to expand up to bufsize-1 (22);
505  // this must come after the calls to presolve_prefix
506  mcstrt_[ncols_] = bufsize-1;
507  mrstrt_[nrows_] = bufsize-1;
508
509#if     CHECK_CONSISTENCY
510  consistent(false);
511#endif
512}
513
514PresolveMatrix::~PresolveMatrix()
515{
516  delete[]clink_;
517  delete[]rlink_;
518 
519  delete[]mrstrt_;
520  delete[]hinrow_;
521  delete[]rowels_;
522  delete[]hcol_;
523
524  delete[]integerType_;
525  delete[] rowChanged_;
526  delete[] rowsToDo_;
527  delete[] nextRowsToDo_;
528  delete[] colChanged_;
529  delete[] colsToDo_;
530  delete[] nextColsToDo_;
531}
532
533
534void PresolveMatrix::update_model(ClpSimplex& si,
535                                     int nrows0,
536                                     int ncols0,
537                                     int nelems0)
538{
539  si.loadProblem(ncols_, nrows_, mcstrt_, hrow_, colels_, hincol_,
540                 clo_, cup_, cost_, rlo_, rup_);
541
542  delete [] si.integerInformation();
543  int numberIntegers=0;
544  for (int i=0; i<ncols_; i++) {
545    if (integerType_[i])
546      numberIntegers++;
547  }
548  if (numberIntegers) 
549    si.copyInIntegerInformation(integerType_);
550  else
551    si.copyInIntegerInformation(NULL);
552
553#if     PRESOLVE_SUMMARY
554  printf("NEW NCOL/NROW/NELS:  %d(-%d) %d(-%d) %d(-%d)\n",
555         ncols_, ncols0-ncols_,
556         nrows_, nrows0-nrows_,
557         si.getNumElements(), nelems0-si.getNumElements());
558#endif
559  si.setDblParam(ClpObjOffset,originalOffset_-dobias_);
560
561}
562
563
564// The matrix is represented redundantly in both row and column format,
565// in what I call "loosely packed" format.
566// "packed" format would be as in normal OSL:  a vector of column starts,
567// together with two vectors that give the row indices and coefficients.
568//
569// This format is "loosely packed" because some of the elements may correspond
570// to empty rows.  This is so that we can quickly delete rows without having
571// to update the column rep and vice versa.
572//
573// Checks whether an entry is in the col rep iff it is also in the row rep,
574// and also that their values are the same (if testvals is non-zero).
575//
576// Note that there may be entries in a row that correspond to empty columns
577// and vice-versa.  --- HUH???
578static void matrix_consistent(const int *mrstrt, const int *hinrow, const int *hcol,
579                              const int *mcstrt, const int *hincol, const int *hrow,
580                              const double *rowels,
581                              const double *colels,
582                              int nrows, int testvals,
583                              const char *ROW, const char *COL)
584{
585#if     CHECK_CONSISTENCY
586  for (int irow=0; irow<nrows; irow++) {
587    if (hinrow[irow] > 0) {
588      int krs = mrstrt[irow];
589      int kre = krs + hinrow[irow];
590
591      for (int k=krs; k<kre; k++) {
592        int jcol = hcol[k];
593        int kcs = mcstrt[jcol];
594        int kce = kcs + hincol[jcol];
595
596        int kk = presolve_find_row1(irow, kcs, kce, hrow);
597        if (kk == kce) {
598          printf("MATRIX INCONSISTENT:  can't find %s %d in %s %d\n",
599                 ROW, irow, COL, jcol);
600          fflush(stdout);
601          abort();
602        }
603        if (testvals && colels[kk] != rowels[k]) {
604          printf("MATRIX INCONSISTENT:  value for %s %d and %s %d\n",
605                 ROW, irow, COL, jcol);
606          fflush(stdout);
607          abort();
608        }
609      }
610    }
611  }
612#endif
613}
614
615
616void PresolveMatrix::consistent(bool testvals)
617{
618#if     CHECK_CONSISTENCY
619  matrix_consistent(mrstrt_, hinrow_, hcol_,
620                    mcstrt_, hincol_, hrow_,
621                    rowels_, colels_,
622                    nrows_, testvals,
623                    "row", "col");
624  matrix_consistent(mcstrt_, hincol_, hrow_,
625                    mrstrt_, hinrow_, hcol_,
626                    colels_, rowels_, 
627                    ncols_, testvals,
628                    "col", "row");
629#endif
630}
631
632
633
634
635
636
637
638
639
640
641
642////////////////  POSTSOLVE
643
644PostsolveMatrix::PostsolveMatrix(ClpSimplex& si,
645                                       int ncols0_in,
646                                       int nrows0_in,
647                                       int nelems0,
648                                   
649                                       double maxmin_,
650                                       // end prepost members
651
652                                       double *sol_in,
653                                       double *acts_in,
654
655                                       unsigned char *colstat_in,
656                                       unsigned char *rowstat_in) :
657  PrePostsolveMatrix(si,
658                        ncols0_in, nrows0_in, nelems0),
659
660  free_list_(0),
661  // link, free_list, maxlink
662  maxlink_(2*nelems0),
663  link_(new int[/*maxlink*/ 2*nelems0]),
664     
665  cdone_(new char[ncols0_]),
666  rdone_(new char[nrows0_in]),
667
668  nrows_(si.getNumRows()),
669  nrows0_(nrows0_in)
670{
671
672  sol_=sol_in;
673  rowduals_=NULL;
674  acts_=acts_in;
675
676  rcosts_=NULL;
677  colstat_=colstat_in;
678  rowstat_=rowstat_in;
679
680  // this is the *reduced* model, which is probably smaller
681  int ncols1 = si.getNumCols();
682  int nrows1 = si.getNumRows();
683
684  const CoinPackedMatrix * m = si.matrix();
685
686  if (! isGapFree(*m)) {
687    PresolveAction::throwCoinError("Matrix not gap free",
688                                      "PostsolveMatrix");
689  }
690
691  const int nelemsr = m->getNumElements();
692
693  CoinDisjointCopyN(m->getVectorStarts(), ncols1, mcstrt_);
694  mcstrt_[ncols_] = nelems0;    // ??
695  CoinDisjointCopyN(m->getVectorLengths(),ncols1,  hincol_);
696  CoinDisjointCopyN(m->getIndices(),      nelemsr, hrow_);
697  CoinDisjointCopyN(m->getElements(),     nelemsr, colels_);
698
699
700#if     0 && DEBUG_PRESOLVE
701  presolve_check_costs(model, &colcopy);
702#endif
703
704  // This determines the size of the data structure that contains
705  // the matrix being postsolved.  Links are taken from the free_list
706  // to recreate matrix entries that were presolved away,
707  // and links are added to the free_list when entries created during
708  // presolve are discarded.  There is never a need to gc this list.
709  // Naturally, it should contain
710  // exactly nelems0 entries "in use" when postsolving is done,
711  // but I don't know whether the matrix could temporarily get
712  // larger during postsolving.  Substitution into more than two
713  // rows could do that, in principle.  I am being very conservative
714  // here by reserving much more than the amount of space I probably need.
715  // If this guess is wrong, check_free_list may be called.
716  int bufsize = 2*nelems0;
717
718  memset(cdone_, -1, ncols0_);
719  memset(rdone_, -1, nrows0_);
720
721  rowduals_ = new double[nrows0_];
722  CoinDisjointCopyN(si.getRowPrice(), nrows1, rowduals_);
723
724  rcosts_ = new double[ncols0_];
725  CoinDisjointCopyN(si.getReducedCost(), ncols1, rcosts_);
726
727  //CoinDisjointCopyN(si.getRowUpper(), nrows1, rup_);
728  //CoinDisjointCopyN(si.getRowLower(), nrows1, rlo_);
729
730  CoinDisjointCopyN(si.getColSolution(), ncols1, sol_);
731  si.setDblParam(ClpObjOffset,originalOffset_);
732
733  for (int j=0; j<ncols1; j++) {
734    int kcs = mcstrt_[j];
735    int kce = kcs + hincol_[j];
736    for (int k=kcs; k<kce; ++k) {
737      link_[k] = k+1;
738    }
739  }
740  {
741    int ml = maxlink_;
742    for (int k=nelemsr; k<ml; ++k)
743      link_[k] = k+1;
744    link_[ml-1] = NO_LINK;
745  }
746  free_list_ = nelemsr;
747}
748
749PostsolveMatrix::~PostsolveMatrix()
750{
751  delete[]link_;
752
753  delete[]cdone_;
754  delete[]rdone_;
755}
756
757
758void PostsolveMatrix::check_nbasic()
759{
760  int nbasic = 0;
761
762  for (int i=0; i<ncols_; i++)
763    if (columnIsBasic(i))
764      nbasic++;
765
766  for (int i=0; i<nrows_; i++)
767    if (rowIsBasic(i))
768      nbasic++;
769
770  if (nbasic != nrows_) {
771    printf("WRONG NUMBER NBASIC:  is:  %d  should be:  %d\n",
772           nbasic, nrows_);
773    fflush(stdout);
774  }
775}
776
777
778
779
780
781
Note: See TracBrowser for help on using the repository browser.