source: branches/devel-1/PresolveMatrix.cpp

Last change on this file was 49, checked in by ladanyi, 17 years ago

everything compiles

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.4 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(CoinBigIndex *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 CoinBigIndex *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(CoinBigIndex *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, CoinBigIndex kcs, CoinBigIndex kce, const int *hrow)
147{
148  CoinBigIndex 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, CoinBigIndex kcs, CoinBigIndex kce, const int *hrow)
157{
158  CoinBigIndex 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, CoinBigIndex 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, CoinBigIndex 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 CoinBigIndex *mrstrt,
191                     int *hinrow, int *hcol, double *dels)
192{
193  CoinBigIndex krs = mrstrt[row];
194  CoinBigIndex kre = krs + hinrow[row];
195
196  CoinBigIndex 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                      CoinBigIndex *mrstrt,
206                     int *hinrow, int *hcol, double *dels, int *link, 
207                               CoinBigIndex *free_listp)
208{
209  CoinBigIndex k = mrstrt[row];
210
211  if (hcol[k] == col) {
212    mrstrt[row] = link[k];
213    link[k] = *free_listp;
214    *free_listp = k;
215    check_free_list(k);
216    hinrow[row]--;
217  } else {
218    int n = hinrow[row] - 1;
219    CoinBigIndex k0 = k;
220    k = link[k];
221    for (int i=0; i<n; ++i) {
222      if (hcol[k] == col) {
223        link[k0] = link[k];
224        link[k] = *free_listp;
225        *free_listp = k;
226        check_free_list(k);
227        hinrow[row]--;
228        return;
229      }
230      k0 = k;
231      k = link[k];
232    }
233    abort();
234  }
235}
236
237static inline double getTolerance(const ClpSimplex &si, ClpDblParam key)
238{
239  double tol;
240  if (! si.getDblParam(key, tol)) {
241    PresolveAction::throwCoinError("getDblParam failed",
242                                      "PrePostsolveMatrix::PrePostsolveMatrix");
243  }
244  return (tol);
245}
246
247#if 0
248PresolveAction::~PresolveAction()
249{
250  cout << "OOPS\n";
251}
252#endif
253
254// Assumptions:
255// 1. nrows>=m.getNumRows()
256// 2. ncols>=m.getNumCols()
257//
258// In presolve, these values are equal.
259// In postsolve, they may be inequal, since the reduced problem
260// may be smaller, but we need room for the large problem.
261// ncols may be larger than si.getNumCols() in postsolve,
262// this at that point si will be the reduced problem,
263// but we need to reserve enough space for the original problem.
264PrePostsolveMatrix::PrePostsolveMatrix(const ClpSimplex& si,
265                                             int ncols_in,
266                                             int nrows_in,
267                                             CoinBigIndex nelems_in) :
268  ncols_(si.getNumCols()),
269  ncols0_(ncols_in),
270  nelems_(si.getNumElements()),
271
272  mcstrt_(new CoinBigIndex[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{
290  si.getDblParam(ClpObjOffset,originalOffset_);
291  int ncols = si.getNumCols();
292  int nrows = si.getNumRows();
293
294  ClpDisjointCopyN(si.getColLower(), ncols, clo_);
295  ClpDisjointCopyN(si.getColUpper(), ncols, cup_);
296  ClpDisjointCopyN(si.getObjCoefficients(), ncols, cost_);
297  ClpDisjointCopyN(si.getRowLower(), nrows,  rlo_);
298  ClpDisjointCopyN(si.getRowUpper(), nrows,  rup_);
299  int i;
300  for (i=0;i<ncols_in;i++) 
301    originalColumn_[i]=i;
302  sol_=NULL;
303  rowduals_=NULL;
304  acts_=NULL;
305
306  rcosts_=NULL;
307  colstat_=NULL;
308  rowstat_=NULL;
309}
310
311
312PrePostsolveMatrix::~PrePostsolveMatrix()
313{
314  delete[]mcstrt_;
315  delete[]hrow_;
316  delete[]colels_;
317  delete[]hincol_;
318
319  delete[]cost_;
320  delete[]clo_;
321  delete[]cup_;
322  delete[]rlo_;
323  delete[]rup_;
324  delete[]originalColumn_;
325  delete[]rowduals_;
326
327  delete[]rcosts_;
328}
329
330// Sets status (non -basic ) using value
331void 
332PrePostsolveMatrix::setRowStatusUsingValue(int iRow)
333{
334  double value = acts_[iRow];
335  double lower = rlo_[iRow];
336  double upper = rup_[iRow];
337  if (lower<-1.0e20&&upper>1.0e20) {
338    setRowStatus(iRow,isFree);
339  } else if (fabs(lower-value)<=ztolzb_) {
340    setRowStatus(iRow,atLowerBound);
341  } else if (fabs(upper-value)<=ztolzb_) {
342    setRowStatus(iRow,atUpperBound);
343  } else {
344    setRowStatus(iRow,superBasic);
345  }
346}
347void 
348PrePostsolveMatrix::setColumnStatusUsingValue(int iColumn)
349{
350  double value = sol_[iColumn];
351  double lower = clo_[iColumn];
352  double upper = cup_[iColumn];
353  if (lower<-1.0e20&&upper>1.0e20) {
354    setColumnStatus(iColumn,isFree);
355  } else if (fabs(lower-value)<=ztolzb_) {
356    setColumnStatus(iColumn,atLowerBound);
357  } else if (fabs(upper-value)<=ztolzb_) {
358    setColumnStatus(iColumn,atUpperBound);
359  } else {
360    setColumnStatus(iColumn,superBasic);
361  }
362}
363
364// I am not familiar enough with CoinPackedMatrix to be confident
365// that I will implement a row-ordered version of toColumnOrderedGapFree
366// properly.
367static bool isGapFree(const CoinPackedMatrix& matrix)
368{
369  const CoinBigIndex * start = matrix.getVectorStarts();
370  const int * length = matrix.getVectorLengths();
371  int i;
372  for (i = matrix.getSizeVectorLengths() - 1; i >= 0; --i) {
373    if (start[i+1] - start[i] != length[i])
374      break;
375  }
376  return (! (i >= 0));
377}
378
379
380#if     DEBUG_PRESOLVE
381static void matrix_bounds_ok(const double *lo, const double *up, int n)
382{
383  int i;
384  for (i=0; i<n; i++) {
385    PRESOLVEASSERT(lo[i] <= up[i]);
386    PRESOLVEASSERT(lo[i] < PRESOLVE_INF);
387    PRESOLVEASSERT(-PRESOLVE_INF < up[i]);
388  }
389}
390#endif
391
392PresolveMatrix::PresolveMatrix(int ncols0_in,
393                                     double maxmin_,
394                                     // end prepost members
395
396                                     ClpSimplex &si,
397
398                                     // rowrep
399                                     int nrows_in,
400                                     CoinBigIndex nelems_in,
401                               bool doStatus) :
402
403  PrePostsolveMatrix(si,
404                        ncols0_in, nrows_in, nelems_in),
405  clink_(new presolvehlink[ncols0_in+1]),
406  rlink_(new presolvehlink[nrows_in+1]),
407
408  dobias_(0.0),
409
410  nrows_(si.getNumRows()),
411
412  // temporary init
413  mrstrt_(new CoinBigIndex[nrows_in+1]),
414  hinrow_(new int[nrows_in+1]),
415  rowels_(new double[2*nelems_in]),
416  hcol_(new int[2*nelems_in]),
417  integerType_(new char[ncols0_in]),
418  feasibilityTolerance_(0.0),
419  status_(-1),
420  rowsToDo_(new int [nrows_in]),
421  numberRowsToDo_(0),
422  nextRowsToDo_(new int[nrows_in]),
423  numberNextRowsToDo_(0),
424  colsToDo_(new int [ncols0_in]),
425  numberColsToDo_(0),
426  nextColsToDo_(new int[ncols0_in]),
427  numberNextColsToDo_(0)
428
429{
430  const int bufsize = 2*nelems_in;
431
432  // Set up change bits
433  rowChanged_ = new unsigned int[(nrows_+31)>>5];
434  memset(rowChanged_,0,((nrows_+31)>>5)*sizeof(unsigned int));
435  colChanged_ = new unsigned int[(ncols_+31)>>5];
436  memset(colChanged_,0,((ncols_+31)>>5)*sizeof(unsigned int));
437  CoinPackedMatrix * m = si.matrix();
438
439  // The coefficient matrix is a big hunk of stuff.
440  // Do the copy here to try to avoid running out of memory.
441
442  const CoinBigIndex * start = m->getVectorStarts();
443  const int * length = m->getVectorLengths();
444  const int * row = m->getIndices();
445  const double * element = m->getElements();
446  int icol,nel=0;
447  mcstrt_[0]=0;
448  for (icol=0;icol<ncols_;icol++) {
449    int j;
450    for (j=start[icol];j<start[icol]+length[icol];j++) {
451      hrow_[nel]=row[j];
452      colels_[nel++]=element[j];
453    }
454    mcstrt_[icol+1]=nel;
455  }
456  assert(mcstrt_[ncols_] == nelems_);
457  ClpDisjointCopyN(m->getVectorLengths(),ncols_,  hincol_);
458
459  // same thing for row rep
460  m = new CoinPackedMatrix();
461  m->reverseOrderedCopyOf(*si.matrix());
462  m->removeGaps();
463
464
465  ClpDisjointCopyN(m->getVectorStarts(),  nrows_,  mrstrt_);
466  mrstrt_[nrows_] = nelems_;
467  ClpDisjointCopyN(m->getVectorLengths(), nrows_,  hinrow_);
468  ClpDisjointCopyN(m->getIndices(),       nelems_, hcol_);
469  ClpDisjointCopyN(m->getElements(),      nelems_, rowels_);
470
471  delete m;
472  if (si.integerInformation()) {
473    memcpy(integerType_,si.integerInformation(),ncols_*sizeof(char));
474  } else {
475    ClpFillN<char>(integerType_, ncols_, 0);
476  }
477
478  if (doStatus) {
479    // allow for status and solution
480    sol_ = new double[ncols_];
481    memcpy(sol_,si.primalColumnSolution(),ncols_*sizeof(double));;
482    acts_ = new double [nrows_];
483    memcpy(acts_,si.primalRowSolution(),nrows_*sizeof(double));
484    if (!si.statusArray())
485      si.createStatus();
486    colstat_ = new unsigned char [nrows_+ncols_];
487    memcpy(colstat_,si.statusArray(),
488           (nrows_+ncols_)*sizeof(unsigned char));
489    rowstat_ = colstat_+ncols_;
490  }
491
492  // the original model's fields are now unneeded - free them
493 
494  si.resize(0,0);
495
496#if     DEBUG_PRESOLVE
497  matrix_bounds_ok(rlo_, rup_, nrows_);
498  matrix_bounds_ok(clo_, cup_, ncols_);
499#endif
500
501#if 0
502  for (i=0; i<nrows; ++i)
503    printf("NR: %6d\n", hinrow[i]);
504  for (int i=0; i<ncols; ++i)
505    printf("NC: %6d\n", hincol[i]);
506#endif
507
508  presolve_make_memlists(mcstrt_, hincol_, clink_, ncols_);
509  presolve_make_memlists(mrstrt_, hinrow_, rlink_, nrows_);
510
511  // this allows last col/row to expand up to bufsize-1 (22);
512  // this must come after the calls to presolve_prefix
513  mcstrt_[ncols_] = bufsize-1;
514  mrstrt_[nrows_] = bufsize-1;
515
516#if     CHECK_CONSISTENCY
517  consistent(false);
518#endif
519}
520
521PresolveMatrix::~PresolveMatrix()
522{
523  delete[]clink_;
524  delete[]rlink_;
525 
526  delete[]mrstrt_;
527  delete[]hinrow_;
528  delete[]rowels_;
529  delete[]hcol_;
530
531  delete[]integerType_;
532  delete[] rowChanged_;
533  delete[] rowsToDo_;
534  delete[] nextRowsToDo_;
535  delete[] colChanged_;
536  delete[] colsToDo_;
537  delete[] nextColsToDo_;
538}
539
540
541void PresolveMatrix::update_model(ClpSimplex& si,
542                                     int nrows0,
543                                     int ncols0,
544                                     CoinBigIndex nelems0)
545{
546  si.loadProblem(ncols_, nrows_, mcstrt_, hrow_, colels_, hincol_,
547                 clo_, cup_, cost_, rlo_, rup_);
548
549  delete [] si.integerInformation();
550  int numberIntegers=0;
551  for (int i=0; i<ncols_; i++) {
552    if (integerType_[i])
553      numberIntegers++;
554  }
555  if (numberIntegers) 
556    si.copyInIntegerInformation(integerType_);
557  else
558    si.copyInIntegerInformation(NULL);
559
560#if     PRESOLVE_SUMMARY
561  printf("NEW NCOL/NROW/NELS:  %d(-%d) %d(-%d) %d(-%d)\n",
562         ncols_, ncols0-ncols_,
563         nrows_, nrows0-nrows_,
564         si.getNumElements(), nelems0-si.getNumElements());
565#endif
566  si.setDblParam(ClpObjOffset,originalOffset_-dobias_);
567
568}
569
570
571// The matrix is represented redundantly in both row and column format,
572// in what I call "loosely packed" format.
573// "packed" format would be as in normal OSL:  a vector of column starts,
574// together with two vectors that give the row indices and coefficients.
575//
576// This format is "loosely packed" because some of the elements may correspond
577// to empty rows.  This is so that we can quickly delete rows without having
578// to update the column rep and vice versa.
579//
580// Checks whether an entry is in the col rep iff it is also in the row rep,
581// and also that their values are the same (if testvals is non-zero).
582//
583// Note that there may be entries in a row that correspond to empty columns
584// and vice-versa.  --- HUH???
585static void matrix_consistent(const CoinBigIndex *mrstrt, const int *hinrow, const int *hcol,
586                              const CoinBigIndex *mcstrt, const int *hincol, const int *hrow,
587                              const double *rowels,
588                              const double *colels,
589                              int nrows, int testvals,
590                              const char *ROW, const char *COL)
591{
592#if     CHECK_CONSISTENCY
593  for (int irow=0; irow<nrows; irow++) {
594    if (hinrow[irow] > 0) {
595      CoinBigIndex krs = mrstrt[irow];
596      CoinBigIndex kre = krs + hinrow[irow];
597
598      for (CoinBigIndex k=krs; k<kre; k++) {
599        int jcol = hcol[k];
600        CoinBigIndex kcs = mcstrt[jcol];
601        CoinBigIndex kce = kcs + hincol[jcol];
602
603        CoinBigIndex kk = presolve_find_row1(irow, kcs, kce, hrow);
604        if (kk == kce) {
605          printf("MATRIX INCONSISTENT:  can't find %s %d in %s %d\n",
606                 ROW, irow, COL, jcol);
607          fflush(stdout);
608          abort();
609        }
610        if (testvals && colels[kk] != rowels[k]) {
611          printf("MATRIX INCONSISTENT:  value for %s %d and %s %d\n",
612                 ROW, irow, COL, jcol);
613          fflush(stdout);
614          abort();
615        }
616      }
617    }
618  }
619#endif
620}
621
622
623void PresolveMatrix::consistent(bool testvals)
624{
625#if     CHECK_CONSISTENCY
626  matrix_consistent(mrstrt_, hinrow_, hcol_,
627                    mcstrt_, hincol_, hrow_,
628                    rowels_, colels_,
629                    nrows_, testvals,
630                    "row", "col");
631  matrix_consistent(mcstrt_, hincol_, hrow_,
632                    mrstrt_, hinrow_, hcol_,
633                    colels_, rowels_, 
634                    ncols_, testvals,
635                    "col", "row");
636#endif
637}
638
639
640
641
642
643
644
645
646
647
648
649////////////////  POSTSOLVE
650
651PostsolveMatrix::PostsolveMatrix(ClpSimplex& si,
652                                       int ncols0_in,
653                                       int nrows0_in,
654                                       CoinBigIndex nelems0,
655                                   
656                                       double maxmin_,
657                                       // end prepost members
658
659                                       double *sol_in,
660                                       double *acts_in,
661
662                                       unsigned char *colstat_in,
663                                       unsigned char *rowstat_in) :
664  PrePostsolveMatrix(si,
665                        ncols0_in, nrows0_in, nelems0),
666
667  free_list_(0),
668  // link, free_list, maxlink
669  maxlink_(2*nelems0),
670  link_(new int[/*maxlink*/ 2*nelems0]),
671     
672  cdone_(new char[ncols0_]),
673  rdone_(new char[nrows0_in]),
674
675  nrows_(si.getNumRows()),
676  nrows0_(nrows0_in)
677{
678
679  sol_=sol_in;
680  rowduals_=NULL;
681  acts_=acts_in;
682
683  rcosts_=NULL;
684  colstat_=colstat_in;
685  rowstat_=rowstat_in;
686
687  // this is the *reduced* model, which is probably smaller
688  int ncols1 = si.getNumCols();
689  int nrows1 = si.getNumRows();
690
691  const CoinPackedMatrix * m = si.matrix();
692
693  if (! isGapFree(*m)) {
694    PresolveAction::throwCoinError("Matrix not gap free",
695                                      "PostsolveMatrix");
696  }
697
698  const CoinBigIndex nelemsr = m->getNumElements();
699
700  ClpDisjointCopyN(m->getVectorStarts(), ncols1, mcstrt_);
701  mcstrt_[ncols_] = nelems0;    // ??
702  ClpDisjointCopyN(m->getVectorLengths(),ncols1,  hincol_);
703  ClpDisjointCopyN(m->getIndices(),      nelemsr, hrow_);
704  ClpDisjointCopyN(m->getElements(),     nelemsr, colels_);
705
706
707#if     0 && DEBUG_PRESOLVE
708  presolve_check_costs(model, &colcopy);
709#endif
710
711  // This determines the size of the data structure that contains
712  // the matrix being postsolved.  Links are taken from the free_list
713  // to recreate matrix entries that were presolved away,
714  // and links are added to the free_list when entries created during
715  // presolve are discarded.  There is never a need to gc this list.
716  // Naturally, it should contain
717  // exactly nelems0 entries "in use" when postsolving is done,
718  // but I don't know whether the matrix could temporarily get
719  // larger during postsolving.  Substitution into more than two
720  // rows could do that, in principle.  I am being very conservative
721  // here by reserving much more than the amount of space I probably need.
722  // If this guess is wrong, check_free_list may be called.
723  //  int bufsize = 2*nelems0;
724
725  memset(cdone_, -1, ncols0_);
726  memset(rdone_, -1, nrows0_);
727
728  rowduals_ = new double[nrows0_];
729  ClpDisjointCopyN(si.getRowPrice(), nrows1, rowduals_);
730
731  rcosts_ = new double[ncols0_];
732  ClpDisjointCopyN(si.getReducedCost(), ncols1, rcosts_);
733  if (maxmin_<0.0) {
734    // change so will look as if minimize
735    int i;
736    for (i=0;i<nrows1;i++)
737      rowduals_[i] = - rowduals_[i];
738    for (i=0;i<ncols1;i++) {
739      rcosts_[i] = - rcosts_[i];
740    }
741  }
742
743  //ClpDisjointCopyN(si.getRowUpper(), nrows1, rup_);
744  //ClpDisjointCopyN(si.getRowLower(), nrows1, rlo_);
745
746  ClpDisjointCopyN(si.getColSolution(), ncols1, sol_);
747  si.setDblParam(ClpObjOffset,originalOffset_);
748
749  for (int j=0; j<ncols1; j++) {
750    CoinBigIndex kcs = mcstrt_[j];
751    CoinBigIndex kce = kcs + hincol_[j];
752    for (CoinBigIndex k=kcs; k<kce; ++k) {
753      link_[k] = k+1;
754    }
755  }
756  {
757    int ml = maxlink_;
758    for (CoinBigIndex k=nelemsr; k<ml; ++k)
759      link_[k] = k+1;
760    link_[ml-1] = NO_LINK;
761  }
762  free_list_ = nelemsr;
763}
764
765PostsolveMatrix::~PostsolveMatrix()
766{
767  delete[]link_;
768
769  delete[]cdone_;
770  delete[]rdone_;
771}
772
773
774void PostsolveMatrix::check_nbasic()
775{
776  int nbasic = 0;
777
778  for (int i=0; i<ncols_; i++)
779    if (columnIsBasic(i))
780      nbasic++;
781
782  for (int i=0; i<nrows_; i++)
783    if (rowIsBasic(i))
784      nbasic++;
785
786  if (nbasic != nrows_) {
787    printf("WRONG NUMBER NBASIC:  is:  %d  should be:  %d\n",
788           nbasic, nrows_);
789    fflush(stdout);
790  }
791}
792
793
794
795
796
797
Note: See TracBrowser for help on using the repository browser.