1 /* $Id: CoinBuild.cpp 1448 2011-06-19 15:34:41Z stefan $ */
2 // Copyright (C) 2005, 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
7 #include <cstdlib>
8 #include <cmath>
9 #include <cassert>
10 #include <cfloat>
11 #include <cstdio>
12 #include <iostream>
13
14
15 #include "CoinBuild.hpp"
16
17 #include "CoinPragma.hpp"
18 #include "CoinHelperFunctions.hpp"
19
20 /*
21 Format of each item is a bit sleazy.
22 First we have pointer to next item
23 Then we have two ints giving item number and number of elements
24 Then we have three double for objective lower and upper
25 Then we have elements
26 Then indices
27 */
28 struct buildFormat {
29 buildFormat * next;
30 int itemNumber;
31 int numberElements;
32 double objective;
33 double lower;
34 double upper;
35 double restDouble[1];
36 int restInt[1]; // just to make correct size
37 } ;
38
39 //#############################################################################
40 // Constructors / Destructor / Assignment
41 //#############################################################################
42
43 //-------------------------------------------------------------------
44 // Default Constructor
45 //-------------------------------------------------------------------
CoinBuild()46 CoinBuild::CoinBuild ()
47 : numberItems_(0),
48 numberOther_(0),
49 numberElements_(0),
50 currentItem_(NULL),
51 firstItem_(NULL),
52 lastItem_(NULL),
53 type_(-1)
54 {
55 }
56 //-------------------------------------------------------------------
57 // Constructor with type
58 //-------------------------------------------------------------------
CoinBuild(int type)59 CoinBuild::CoinBuild (int type)
60 : numberItems_(0),
61 numberOther_(0),
62 numberElements_(0),
63 currentItem_(NULL),
64 firstItem_(NULL),
65 lastItem_(NULL),
66 type_(type)
67 {
68 if (type<0||type>1)
69 type_=-1; // unset
70 }
71
72 //-------------------------------------------------------------------
73 // Copy constructor
74 //-------------------------------------------------------------------
CoinBuild(const CoinBuild & rhs)75 CoinBuild::CoinBuild (const CoinBuild & rhs)
76 : numberItems_(rhs.numberItems_),
77 numberOther_(rhs.numberOther_),
78 numberElements_(rhs.numberElements_),
79 type_(rhs.type_)
80 {
81 if (numberItems_) {
82 firstItem_=NULL;
83 buildFormat * lastItem = NULL;
84 buildFormat * currentItem = reinterpret_cast<buildFormat *> ( rhs.firstItem_);
85 for (int iItem=0;iItem<numberItems_;iItem++) {
86 buildFormat * item = currentItem;
87 assert (item);
88 int numberElements = item->numberElements;
89 int length = ( CoinSizeofAsInt(buildFormat) + (numberElements-1) *
90 (CoinSizeofAsInt(double)+CoinSizeofAsInt(int)) );
91 int doubles = (length + CoinSizeofAsInt(double)-1)/CoinSizeofAsInt(double);
92 double * copyOfItem = new double [doubles];
93 memcpy(copyOfItem,item,length);
94 if (!firstItem_) {
95 firstItem_ = copyOfItem;
96 } else {
97 // update pointer
98 lastItem->next = reinterpret_cast<buildFormat *> ( copyOfItem);
99 }
100 currentItem = currentItem->next; // on to next
101 lastItem = reinterpret_cast<buildFormat *> ( copyOfItem);
102 }
103 currentItem_=firstItem_;
104 lastItem_=reinterpret_cast<double *> ( lastItem);
105 } else {
106 currentItem_=NULL;
107 firstItem_=NULL;
108 lastItem_=NULL;
109 }
110 }
111
112 //-------------------------------------------------------------------
113 // Destructor
114 //-------------------------------------------------------------------
~CoinBuild()115 CoinBuild::~CoinBuild ()
116 {
117 buildFormat * item = reinterpret_cast<buildFormat *> ( firstItem_);
118 for (int iItem=0;iItem<numberItems_;iItem++) {
119 double * array = reinterpret_cast<double *> ( item);
120 item = item->next;
121 delete [] array;
122 }
123 }
124
125 //----------------------------------------------------------------
126 // Assignment operator
127 //-------------------------------------------------------------------
128 CoinBuild &
operator =(const CoinBuild & rhs)129 CoinBuild::operator=(const CoinBuild& rhs)
130 {
131 if (this != &rhs) {
132 buildFormat * item = reinterpret_cast<buildFormat *> ( firstItem_);
133 for (int iItem=0;iItem<numberItems_;iItem++) {
134 double * array = reinterpret_cast<double *> ( item);
135 item = item->next;
136 delete [] array;
137 }
138 numberItems_=rhs.numberItems_;
139 numberOther_=rhs.numberOther_;
140 numberElements_=rhs.numberElements_;
141 type_=rhs.type_;
142 if (numberItems_) {
143 firstItem_=NULL;
144 buildFormat * lastItem = NULL;
145 buildFormat * currentItem = reinterpret_cast<buildFormat *> ( rhs.firstItem_);
146 for (int iItem=0;iItem<numberItems_;iItem++) {
147 buildFormat * item = currentItem;
148 assert (item);
149 int numberElements = item->numberElements;
150 int length = CoinSizeofAsInt(buildFormat)+(numberElements-1)*(CoinSizeofAsInt(double)+CoinSizeofAsInt(int));
151 int doubles = (length + CoinSizeofAsInt(double)-1)/CoinSizeofAsInt(double);
152 double * copyOfItem = new double [doubles];
153 memcpy(copyOfItem,item,length);
154 if (!firstItem_) {
155 firstItem_ = copyOfItem;
156 } else {
157 // update pointer
158 lastItem->next = reinterpret_cast<buildFormat *> ( copyOfItem);
159 }
160 currentItem = currentItem->next; // on to next
161 lastItem = reinterpret_cast<buildFormat *> ( copyOfItem);
162 }
163 currentItem_=firstItem_;
164 lastItem_=reinterpret_cast<double *> ( lastItem);
165 } else {
166 currentItem_=NULL;
167 firstItem_=NULL;
168 lastItem_=NULL;
169 }
170 }
171 return *this;
172 }
173 // add a row
174 void
addRow(int numberInRow,const int * columns,const double * elements,double rowLower,double rowUpper)175 CoinBuild::addRow(int numberInRow, const int * columns,
176 const double * elements, double rowLower,
177 double rowUpper)
178 {
179 if (type_<0) {
180 type_=0;
181 } else if (type_==1) {
182 printf("CoinBuild:: unable to add a row in column mode\n");
183 abort();
184 }
185 addItem(numberInRow, columns, elements,
186 rowLower,rowUpper,0.0);
187 }
188 /* Returns number of elements in a row and information in row
189 */
190 int
row(int whichRow,double & rowLower,double & rowUpper,const int * & indices,const double * & elements) const191 CoinBuild::row(int whichRow, double & rowLower, double & rowUpper,
192 const int * & indices, const double * & elements) const
193 {
194 assert (type_==0);
195 setMutableCurrent(whichRow);
196 double dummyObjective;
197 return currentItem(rowLower,rowUpper,dummyObjective,indices,elements);
198 }
199 /* Returns number of elements in current row and information in row
200 Used as rows may be stored in a chain
201 */
202 int
currentRow(double & rowLower,double & rowUpper,const int * & indices,const double * & elements) const203 CoinBuild::currentRow(double & rowLower, double & rowUpper,
204 const int * & indices, const double * & elements) const
205 {
206 assert (type_==0);
207 double dummyObjective;
208 return currentItem(rowLower,rowUpper,dummyObjective,indices,elements);
209 }
210 // Set current row
211 void
setCurrentRow(int whichRow)212 CoinBuild::setCurrentRow(int whichRow)
213 {
214 assert (type_==0);
215 setMutableCurrent(whichRow);
216 }
217 // Returns current row number
218 int
currentRow() const219 CoinBuild::currentRow() const
220 {
221 assert (type_==0);
222 return currentItem();
223 }
224 // add a column
225 void
addColumn(int numberInColumn,const int * rows,const double * elements,double columnLower,double columnUpper,double objectiveValue)226 CoinBuild::addColumn(int numberInColumn, const int * rows,
227 const double * elements,
228 double columnLower,
229 double columnUpper, double objectiveValue)
230 {
231 if (type_<0) {
232 type_=1;
233 } else if (type_==0) {
234 printf("CoinBuild:: unable to add a column in row mode\n");
235 abort();
236 }
237 addItem(numberInColumn, rows, elements,
238 columnLower,columnUpper, objectiveValue);
239 }
240 /* Returns number of elements in a column and information in column
241 */
242 int
column(int whichColumn,double & columnLower,double & columnUpper,double & objectiveValue,const int * & indices,const double * & elements) const243 CoinBuild::column(int whichColumn,
244 double & columnLower, double & columnUpper, double & objectiveValue,
245 const int * & indices, const double * & elements) const
246 {
247 assert (type_==1);
248 setMutableCurrent(whichColumn);
249 return currentItem(columnLower,columnUpper,objectiveValue,indices,elements);
250 }
251 /* Returns number of elements in current column and information in column
252 Used as columns may be stored in a chain
253 */
254 int
currentColumn(double & columnLower,double & columnUpper,double & objectiveValue,const int * & indices,const double * & elements) const255 CoinBuild::currentColumn( double & columnLower, double & columnUpper, double & objectiveValue,
256 const int * & indices, const double * & elements) const
257 {
258 assert (type_==1);
259 return currentItem(columnLower,columnUpper,objectiveValue,indices,elements);
260 }
261 // Set current column
262 void
setCurrentColumn(int whichColumn)263 CoinBuild::setCurrentColumn(int whichColumn)
264 {
265 assert (type_==1);
266 setMutableCurrent(whichColumn);
267 }
268 // Returns current column number
269 int
currentColumn() const270 CoinBuild::currentColumn() const
271 {
272 assert (type_==1);
273 return currentItem();
274 }
275 // add a item
276 void
addItem(int numberInItem,const int * indices,const double * elements,double itemLower,double itemUpper,double objectiveValue)277 CoinBuild::addItem(int numberInItem, const int * indices,
278 const double * elements,
279 double itemLower,
280 double itemUpper, double objectiveValue)
281 {
282 buildFormat * lastItem = reinterpret_cast<buildFormat *> ( lastItem_);
283 int length = CoinSizeofAsInt(buildFormat)+(numberInItem-1)*(CoinSizeofAsInt(double)+CoinSizeofAsInt(int));
284 int doubles = (length + CoinSizeofAsInt(double)-1)/CoinSizeofAsInt(double);
285 double * newItem = new double [doubles];
286 if (!firstItem_) {
287 firstItem_ = newItem;
288 } else {
289 // update pointer
290 lastItem->next = reinterpret_cast<buildFormat *> ( newItem);
291 }
292 lastItem_=newItem;
293 currentItem_=newItem;
294 // now fill in
295 buildFormat * item = reinterpret_cast<buildFormat *> ( newItem);
296 double * els = &item->restDouble[0];
297 int * cols = reinterpret_cast<int *> (els+numberInItem);
298 item->next=NULL;
299 item->itemNumber=numberItems_;
300 numberItems_++;
301 item->numberElements=numberInItem;
302 numberElements_ += numberInItem;
303 item->objective=objectiveValue;
304 item->lower=itemLower;
305 item->upper=itemUpper;
306 for (int k=0;k<numberInItem;k++) {
307 int iColumn = indices[k];
308 assert (iColumn>=0);
309 numberOther_ = CoinMax(numberOther_,iColumn+1);
310 els[k]=elements[k];
311 cols[k]=iColumn;
312 }
313 }
314 /* Returns number of elements in a item and information in item
315 */
316 int
item(int whichItem,double & itemLower,double & itemUpper,double & objectiveValue,const int * & indices,const double * & elements) const317 CoinBuild::item(int whichItem,
318 double & itemLower, double & itemUpper, double & objectiveValue,
319 const int * & indices, const double * & elements) const
320 {
321 setMutableCurrent(whichItem);
322 return currentItem(itemLower,itemUpper,objectiveValue,indices,elements);
323 }
324 /* Returns number of elements in current item and information in item
325 Used as items may be stored in a chain
326 */
327 int
currentItem(double & itemLower,double & itemUpper,double & objectiveValue,const int * & indices,const double * & elements) const328 CoinBuild::currentItem(double & itemLower, double & itemUpper,
329 double & objectiveValue,
330 const int * & indices, const double * & elements) const
331 {
332 buildFormat * item = reinterpret_cast<buildFormat *> ( currentItem_);
333 if (item) {
334 int numberElements = item->numberElements;
335 elements = &item->restDouble[0];
336 indices = reinterpret_cast<const int *> (elements+numberElements);
337 objectiveValue=item->objective;
338 itemLower = item->lower;
339 itemUpper=item->upper;
340 return numberElements;
341 } else {
342 return -1;
343 }
344 }
345 // Set current item
346 void
setCurrentItem(int whichItem)347 CoinBuild::setCurrentItem(int whichItem)
348 {
349 setMutableCurrent(whichItem);
350 }
351 // Set current item
352 void
setMutableCurrent(int whichItem) const353 CoinBuild::setMutableCurrent(int whichItem) const
354 {
355 if (whichItem>=0&&whichItem<numberItems_) {
356 int nSkip = whichItem-1;
357 buildFormat * item = reinterpret_cast<buildFormat *> ( firstItem_);
358 // if further on then we can start from where we are
359 buildFormat * current = reinterpret_cast<buildFormat *> ( currentItem_);
360 if (current->itemNumber<=whichItem) {
361 item=current;
362 nSkip = whichItem-current->itemNumber;
363 }
364 for (int iItem=0;iItem<nSkip;iItem++) {
365 item = item->next;
366 }
367 assert (whichItem==item->itemNumber);
368 currentItem_ = reinterpret_cast<double *> ( item);
369 }
370 }
371 // Returns current item number
372 int
currentItem() const373 CoinBuild::currentItem() const
374 {
375 buildFormat * item = reinterpret_cast<buildFormat *> ( currentItem_);
376 if (item)
377 return item->itemNumber;
378 else
379 return -1;
380 }
381