1 /* $Id: CoinPostsolveMatrix.cpp 2083 2019-01-06 19:38:09Z unxusr $ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others.  All Rights Reserved.
4 // This code is licensed under the terms of the Eclipse Public License (EPL).
5 
6 #include <stdio.h>
7 
8 #include <cassert>
9 #include <iostream>
10 
11 #include "CoinHelperFunctions.hpp"
12 #include "CoinPresolveMatrix.hpp"
13 
14 #if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY
15 #include "CoinPresolvePsdebug.hpp"
16 #endif
17 
18 /*! \file
19 
20   This file contains methods for CoinPostsolveMatrix, the object used during
21   postsolve transformations.
22 */
23 
24 /*
25   Constructor and destructor for CoinPostsolveMatrix.
26 */
27 
28 /*
29   Default constructor
30 
31   Postpone allocation of space until we actually load the object.
32 */
33 
CoinPostsolveMatrix(int ncols_alloc,int nrows_alloc,CoinBigIndex nelems_alloc)34 CoinPostsolveMatrix::CoinPostsolveMatrix(int ncols_alloc, int nrows_alloc, CoinBigIndex nelems_alloc)
35 
36   : CoinPrePostsolveMatrix(ncols_alloc, nrows_alloc, nelems_alloc)
37   , free_list_(0)
38   , maxlink_(nelems_alloc)
39   , link_(0)
40   , cdone_(0)
41   , rdone_(0)
42 
43 { /* nothing to do here */
44 
45   return;
46 }
47 
48 /*
49   Destructor
50 */
51 
~CoinPostsolveMatrix()52 CoinPostsolveMatrix::~CoinPostsolveMatrix()
53 
54 {
55   delete[] link_;
56 
57   delete[] cdone_;
58   delete[] rdone_;
59 
60   return;
61 }
62 
63 /*
64   This routine loads a CoinPostsolveMatrix object from a CoinPresolveMatrix
65   object. The CoinPresolveMatrix object will be stripped, its components
66   transferred to the CoinPostsolveMatrix object, and the empty shell of the
67   CoinPresolveObject will be destroyed.
68 
69   The routine expects an empty CoinPostsolveMatrix object, and will leak
70   any memory already allocated.
71 */
72 
assignPresolveToPostsolve(CoinPresolveMatrix * & preObj)73 void CoinPostsolveMatrix::assignPresolveToPostsolve(CoinPresolveMatrix *&preObj)
74 
75 {
76   /*
77   Start with simple data --- allocated and current size.
78 */
79   ncols0_ = preObj->ncols0_;
80   nrows0_ = preObj->nrows0_;
81   nelems0_ = preObj->nelems0_;
82   bulk0_ = preObj->bulk0_;
83 
84   ncols_ = preObj->ncols_;
85   nrows_ = preObj->nrows_;
86   nelems_ = preObj->nelems_;
87   /*
88   Now bring over the column-major matrix and other problem data.
89 */
90   mcstrt_ = preObj->mcstrt_;
91   preObj->mcstrt_ = 0;
92   hincol_ = preObj->hincol_;
93   preObj->hincol_ = 0;
94   hrow_ = preObj->hrow_;
95   preObj->hrow_ = 0;
96   colels_ = preObj->colels_;
97   preObj->colels_ = 0;
98 
99   cost_ = preObj->cost_;
100   preObj->cost_ = 0;
101   originalOffset_ = preObj->originalOffset_;
102   clo_ = preObj->clo_;
103   preObj->clo_ = 0;
104   cup_ = preObj->cup_;
105   preObj->cup_ = 0;
106   rlo_ = preObj->rlo_;
107   preObj->rlo_ = 0;
108   rup_ = preObj->rup_;
109   preObj->rup_ = 0;
110 
111   originalColumn_ = preObj->originalColumn_;
112   preObj->originalColumn_ = 0;
113   originalRow_ = preObj->originalRow_;
114   preObj->originalRow_ = 0;
115 
116   ztolzb_ = preObj->ztolzb_;
117   ztoldj_ = preObj->ztoldj_;
118   maxmin_ = preObj->maxmin_;
119   /*
120   Now the problem solution. Often this will be empty, but that's not a problem.
121 */
122   sol_ = preObj->sol_;
123   preObj->sol_ = 0;
124   rowduals_ = preObj->rowduals_;
125   preObj->rowduals_ = 0;
126   acts_ = preObj->acts_;
127   preObj->acts_ = 0;
128   rcosts_ = preObj->rcosts_;
129   preObj->rcosts_ = 0;
130   colstat_ = preObj->colstat_;
131   preObj->colstat_ = 0;
132   rowstat_ = preObj->rowstat_;
133   preObj->rowstat_ = 0;
134   /*
135   The CoinPostsolveMatrix comes with messages and a handler, but replace them
136   with the versions from the CoinPresolveObject, in case they've been
137   customized. Let preObj believe it's no longer responsible for the handler.
138 */
139   if (defaultHandler_ == true)
140     delete handler_;
141   handler_ = preObj->handler_;
142   preObj->defaultHandler_ = false;
143   messages_ = preObj->messages_;
144   /*
145   Initialise the postsolve portions of this object. Which amounts to setting
146   up the thread links to match the column-major matrix representation. This
147   would be trivial except that the presolve matrix is loosely packed. We can
148   either compress the matrix, or record the existing free space pattern. Bet
149   that the latter is more efficient. Remember that mcstrt_[ncols_] actually
150   points to the end of the bulk storage area, so when we process the last
151   column in the bulk storage area, we'll add the free space block at the end
152   of bulk storage to the free list.
153 
154   We need to allow for a 0x0 matrix here --- a pathological case, but it slips
155   in when (for example) confirming a solution in an ILP code.
156 */
157   free_list_ = NO_LINK;
158   maxlink_ = bulk0_;
159   link_ = new CoinBigIndex[maxlink_];
160 
161   if (ncols_ > 0) {
162     CoinBigIndex minkcs = -1;
163     for (int j = 0; j < ncols_; j++) {
164       CoinBigIndex kcs = mcstrt_[j];
165       int lenj = hincol_[j];
166       assert(lenj > 0);
167       CoinBigIndex kce = kcs + lenj - 1;
168       CoinBigIndex k;
169 
170       for (k = kcs; k < kce; k++) {
171         link_[k] = k + 1;
172       }
173       link_[k++] = NO_LINK;
174 
175       if (preObj->clink_[j].pre == NO_LINK) {
176         minkcs = kcs;
177       }
178       int nxtj = preObj->clink_[j].suc;
179       assert(nxtj >= 0 && nxtj <= ncols_);
180       CoinBigIndex nxtcs = mcstrt_[nxtj];
181       for (; k < nxtcs; k++) {
182         link_[k] = free_list_;
183         free_list_ = k;
184       }
185     }
186 
187     assert(minkcs >= 0);
188     if (minkcs > 0) {
189       for (CoinBigIndex k = 0; k < minkcs; k++) {
190         link_[k] = free_list_;
191         free_list_ = k;
192       }
193     }
194   } else {
195     for (CoinBigIndex k = 0; k < maxlink_; k++) {
196       link_[k] = free_list_;
197       free_list_ = k;
198     }
199   }
200   /*
201   That's it, preObj can die now.
202 */
203   delete preObj;
204   preObj = 0;
205 
206 #if PRESOLVE_DEBUG || PRESOLVE_CONSISTENCY
207   /*
208   These are used to track the action of postsolve transforms during debugging.
209 */
210   cdone_ = new char[ncols0_];
211   CoinFillN(cdone_, ncols_, PRESENT_IN_REDUCED);
212   CoinZeroN(cdone_ + ncols_, ncols0_ - ncols_);
213   rdone_ = new char[nrows0_];
214   CoinFillN(rdone_, nrows_, PRESENT_IN_REDUCED);
215   CoinZeroN(rdone_ + nrows_, nrows0_ - nrows_);
216 #else
217   cdone_ = 0;
218   rdone_ = 0;
219 #endif
220 
221 #if PRESOLVE_CONSISTENCY
222   presolve_check_free_list(this, true);
223   presolve_check_threads(this);
224 #endif
225 
226   return;
227 }
228 
229 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
230 */
231