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

Last change on this file since 33 was 33, checked in by forrest, 17 years ago

Presolve in as option

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.0 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    if (!si.statusArray())
480      si.createStatus();
481    colstat_ = new unsigned char [nrows_+ncols_];
482    memcpy(colstat_,si.statusArray(),
483           (nrows_+ncols_)*sizeof(unsigned char));
484    rowstat_ = colstat_+ncols_;
485  }
486
487  // the original model's fields are now unneeded - free them
488 
489  si.resize(0,0);
490
491#if     DEBUG_PRESOLVE
492  matrix_bounds_ok(rlo_, rup_, nrows_);
493  matrix_bounds_ok(clo_, cup_, ncols_);
494#endif
495
496#if 0
497  for (int i=0; i<nrows; ++i)
498    printf("NR: %6d\n", hinrow[i]);
499  for (int i=0; i<ncols; ++i)
500    printf("NC: %6d\n", hincol[i]);
501#endif
502
503  presolve_make_memlists(mcstrt_, hincol_, clink_, ncols_);
504  presolve_make_memlists(mrstrt_, hinrow_, rlink_, nrows_);
505
506  // this allows last col/row to expand up to bufsize-1 (22);
507  // this must come after the calls to presolve_prefix
508  mcstrt_[ncols_] = bufsize-1;
509  mrstrt_[nrows_] = bufsize-1;
510
511#if     CHECK_CONSISTENCY
512  consistent(false);
513#endif
514}
515
516PresolveMatrix::~PresolveMatrix()
517{
518  delete[]clink_;
519  delete[]rlink_;
520 
521  delete[]mrstrt_;
522  delete[]hinrow_;
523  delete[]rowels_;
524  delete[]hcol_;
525
526  delete[]integerType_;
527  delete[] rowChanged_;
528  delete[] rowsToDo_;
529  delete[] nextRowsToDo_;
530  delete[] colChanged_;
531  delete[] colsToDo_;
532  delete[] nextColsToDo_;
533}
534
535
536void PresolveMatrix::update_model(ClpSimplex& si,
537                                     int nrows0,
538                                     int ncols0,
539                                     int nelems0)
540{
541  si.loadProblem(ncols_, nrows_, mcstrt_, hrow_, colels_, hincol_,
542                 clo_, cup_, cost_, rlo_, rup_);
543
544  delete [] si.integerInformation();
545  int numberIntegers=0;
546  for (int i=0; i<ncols_; i++) {
547    if (integerType_[i])
548      numberIntegers++;
549  }
550  if (numberIntegers) 
551    si.copyInIntegerInformation(integerType_);
552  else
553    si.copyInIntegerInformation(NULL);
554
555#if     PRESOLVE_SUMMARY
556  printf("NEW NCOL/NROW/NELS:  %d(-%d) %d(-%d) %d(-%d)\n",
557         ncols_, ncols0-ncols_,
558         nrows_, nrows0-nrows_,
559         si.getNumElements(), nelems0-si.getNumElements());
560#endif
561  si.setDblParam(ClpObjOffset,originalOffset_-dobias_);
562
563}
564
565
566// The matrix is represented redundantly in both row and column format,
567// in what I call "loosely packed" format.
568// "packed" format would be as in normal OSL:  a vector of column starts,
569// together with two vectors that give the row indices and coefficients.
570//
571// This format is "loosely packed" because some of the elements may correspond
572// to empty rows.  This is so that we can quickly delete rows without having
573// to update the column rep and vice versa.
574//
575// Checks whether an entry is in the col rep iff it is also in the row rep,
576// and also that their values are the same (if testvals is non-zero).
577//
578// Note that there may be entries in a row that correspond to empty columns
579// and vice-versa.  --- HUH???
580static void matrix_consistent(const int *mrstrt, const int *hinrow, const int *hcol,
581                              const int *mcstrt, const int *hincol, const int *hrow,
582                              const double *rowels,
583                              const double *colels,
584                              int nrows, int testvals,
585                              const char *ROW, const char *COL)
586{
587#if     CHECK_CONSISTENCY
588  for (int irow=0; irow<nrows; irow++) {
589    if (hinrow[irow] > 0) {
590      int krs = mrstrt[irow];
591      int kre = krs + hinrow[irow];
592
593      for (int k=krs; k<kre; k++) {
594        int jcol = hcol[k];
595        int kcs = mcstrt[jcol];
596        int kce = kcs + hincol[jcol];
597
598        int kk = presolve_find_row1(irow, kcs, kce, hrow);
599        if (kk == kce) {
600          printf("MATRIX INCONSISTENT:  can't find %s %d in %s %d\n",
601                 ROW, irow, COL, jcol);
602          fflush(stdout);
603          abort();
604        }
605        if (testvals && colels[kk] != rowels[k]) {
606          printf("MATRIX INCONSISTENT:  value for %s %d and %s %d\n",
607                 ROW, irow, COL, jcol);
608          fflush(stdout);
609          abort();
610        }
611      }
612    }
613  }
614#endif
615}
616
617
618void PresolveMatrix::consistent(bool testvals)
619{
620#if     CHECK_CONSISTENCY
621  matrix_consistent(mrstrt_, hinrow_, hcol_,
622                    mcstrt_, hincol_, hrow_,
623                    rowels_, colels_,
624                    nrows_, testvals,
625                    "row", "col");
626  matrix_consistent(mcstrt_, hincol_, hrow_,
627                    mrstrt_, hinrow_, hcol_,
628                    colels_, rowels_, 
629                    ncols_, testvals,
630                    "col", "row");
631#endif
632}
633
634
635
636
637
638
639
640
641
642
643
644////////////////  POSTSOLVE
645
646PostsolveMatrix::PostsolveMatrix(ClpSimplex& si,
647                                       int ncols0_in,
648                                       int nrows0_in,
649                                       int nelems0,
650                                   
651                                       double maxmin_,
652                                       // end prepost members
653
654                                       double *sol_in,
655                                       double *acts_in,
656
657                                       unsigned char *colstat_in,
658                                       unsigned char *rowstat_in) :
659  PrePostsolveMatrix(si,
660                        ncols0_in, nrows0_in, nelems0),
661
662  free_list_(0),
663  // link, free_list, maxlink
664  maxlink_(2*nelems0),
665  link_(new int[/*maxlink*/ 2*nelems0]),
666     
667  cdone_(new char[ncols0_]),
668  rdone_(new char[nrows0_in]),
669
670  nrows_(si.getNumRows()),
671  nrows0_(nrows0_in)
672{
673
674  sol_=sol_in;
675  rowduals_=NULL;
676  acts_=acts_in;
677
678  rcosts_=NULL;
679  colstat_=colstat_in;
680  rowstat_=rowstat_in;
681
682  // this is the *reduced* model, which is probably smaller
683  int ncols1 = si.getNumCols();
684  int nrows1 = si.getNumRows();
685
686  const CoinPackedMatrix * m = si.matrix();
687
688  if (! isGapFree(*m)) {
689    PresolveAction::throwCoinError("Matrix not gap free",
690                                      "PostsolveMatrix");
691  }
692
693  const int nelemsr = m->getNumElements();
694
695  CoinDisjointCopyN(m->getVectorStarts(), ncols1, mcstrt_);
696  mcstrt_[ncols_] = nelems0;    // ??
697  CoinDisjointCopyN(m->getVectorLengths(),ncols1,  hincol_);
698  CoinDisjointCopyN(m->getIndices(),      nelemsr, hrow_);
699  CoinDisjointCopyN(m->getElements(),     nelemsr, colels_);
700
701
702#if     0 && DEBUG_PRESOLVE
703  presolve_check_costs(model, &colcopy);
704#endif
705
706  // This determines the size of the data structure that contains
707  // the matrix being postsolved.  Links are taken from the free_list
708  // to recreate matrix entries that were presolved away,
709  // and links are added to the free_list when entries created during
710  // presolve are discarded.  There is never a need to gc this list.
711  // Naturally, it should contain
712  // exactly nelems0 entries "in use" when postsolving is done,
713  // but I don't know whether the matrix could temporarily get
714  // larger during postsolving.  Substitution into more than two
715  // rows could do that, in principle.  I am being very conservative
716  // here by reserving much more than the amount of space I probably need.
717  // If this guess is wrong, check_free_list may be called.
718  int bufsize = 2*nelems0;
719
720  memset(cdone_, -1, ncols0_);
721  memset(rdone_, -1, nrows0_);
722
723  rowduals_ = new double[nrows0_];
724  CoinDisjointCopyN(si.getRowPrice(), nrows1, rowduals_);
725
726  rcosts_ = new double[ncols0_];
727  CoinDisjointCopyN(si.getReducedCost(), ncols1, rcosts_);
728  if (maxmin_<0.0) {
729    // change so will look as if minimize
730    int i;
731    for (i=0;i<nrows1;i++)
732      rowduals_[i] = - rowduals_[i];
733    for (i=0;i<ncols1;i++) {
734      rcosts_[i] = - rcosts_[i];
735    }
736  }
737
738  //CoinDisjointCopyN(si.getRowUpper(), nrows1, rup_);
739  //CoinDisjointCopyN(si.getRowLower(), nrows1, rlo_);
740
741  CoinDisjointCopyN(si.getColSolution(), ncols1, sol_);
742  si.setDblParam(ClpObjOffset,originalOffset_);
743
744  for (int j=0; j<ncols1; j++) {
745    int kcs = mcstrt_[j];
746    int kce = kcs + hincol_[j];
747    for (int k=kcs; k<kce; ++k) {
748      link_[k] = k+1;
749    }
750  }
751  {
752    int ml = maxlink_;
753    for (int k=nelemsr; k<ml; ++k)
754      link_[k] = k+1;
755    link_[ml-1] = NO_LINK;
756  }
757  free_list_ = nelemsr;
758}
759
760PostsolveMatrix::~PostsolveMatrix()
761{
762  delete[]link_;
763
764  delete[]cdone_;
765  delete[]rdone_;
766}
767
768
769void PostsolveMatrix::check_nbasic()
770{
771  int nbasic = 0;
772
773  for (int i=0; i<ncols_; i++)
774    if (columnIsBasic(i))
775      nbasic++;
776
777  for (int i=0; i<nrows_; i++)
778    if (rowIsBasic(i))
779      nbasic++;
780
781  if (nbasic != nrows_) {
782    printf("WRONG NUMBER NBASIC:  is:  %d  should be:  %d\n",
783           nbasic, nrows_);
784    fflush(stdout);
785  }
786}
787
788
789
790
791
792
Note: See TracBrowser for help on using the repository browser.