1/* $Id: CoinWarmStartBasis.cpp 1373 2011-01-03 23:57:44Z lou $ */
2// Copyright (C) 2000, 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#if defined(_MSC_VER)
7// Turn off compiler warning about long names
8# pragma warning(disable:4786)
9#endif
10
11#include "CoinUtilsConfig.h"
12#include <cassert>
13
14#include "CoinWarmStartBasis.hpp"
15#include "CoinHelperFunctions.hpp"
16#include <cmath>
17#include <iostream>
18
19//#############################################################################
20
21void
22CoinWarmStartBasis::setSize(int ns, int na) {
23 // Round all so arrays multiple of 4
24 int nintS = (ns+15) >> 4;
25 int nintA = (na+15) >> 4;
26 int size = nintS+nintA;
27 if (size) {
28 if (size>maxSize_) {
29 delete[] structuralStatus_;
30 maxSize_ = size+10;
31 structuralStatus_ = new char[4*maxSize_];
32 }
33 memset (structuralStatus_, 0, (4*nintS) * sizeof(char));
34 artificialStatus_ = structuralStatus_+4*nintS;
35 memset (artificialStatus_, 0, (4*nintA) * sizeof(char));
36 } else {
37 artificialStatus_ = NULL;
38 }
39 numArtificial_ = na;
40 numStructural_ = ns;
41}
42
43void
44CoinWarmStartBasis::assignBasisStatus(int ns, int na, char*& sStat,
45 char*& aStat) {
46 // Round all so arrays multiple of 4
47 int nintS = (ns+15) >> 4;
48 int nintA = (na+15) >> 4;
49 int size = nintS+nintA;
50 if (size) {
51 if (size>maxSize_) {
52 delete[] structuralStatus_;
53 maxSize_ = size+10;
54 structuralStatus_ = new char[4*maxSize_];
55 }
56 CoinMemcpyN( sStat,(4*nintS), structuralStatus_);
57 artificialStatus_ = structuralStatus_+4*nintS;
58 CoinMemcpyN( aStat,(4*nintA), artificialStatus_);
59 } else {
60 artificialStatus_ = NULL;
61 }
62 numStructural_ = ns;
63 numArtificial_ = na;
64 delete [] sStat;
65 delete [] aStat;
66 sStat = NULL;
67 aStat = NULL;
68}
69CoinWarmStartBasis::CoinWarmStartBasis(int ns, int na,
70 const char* sStat, const char* aStat) :
71 numStructural_(ns), numArtificial_(na),
72 structuralStatus_(NULL), artificialStatus_(NULL) {
73 // Round all so arrays multiple of 4
74 int nintS = ((ns+15) >> 4);
75 int nintA = ((na+15) >> 4);
76 maxSize_ = nintS+nintA;
77 if (maxSize_ > 0) {
78 structuralStatus_ = new char[4*maxSize_];
79 if (nintS>0) {
80 structuralStatus_[4*nintS-3]=0;
81 structuralStatus_[4*nintS-2]=0;
82 structuralStatus_[4*nintS-1]=0;
83 CoinMemcpyN( sStat,((ns+3)/4), structuralStatus_);
84 }
85 artificialStatus_ = structuralStatus_+4*nintS;
86 if (nintA > 0) {
87 artificialStatus_[4*nintA-3]=0;
88 artificialStatus_[4*nintA-2]=0;
89 artificialStatus_[4*nintA-1]=0;
90 CoinMemcpyN( aStat,((na+3)/4), artificialStatus_);
91 }
92 }
93}
94
95CoinWarmStartBasis::CoinWarmStartBasis(const CoinWarmStartBasis& ws) :
96 numStructural_(ws.numStructural_), numArtificial_(ws.numArtificial_),
97 structuralStatus_(NULL), artificialStatus_(NULL) {
98 // Round all so arrays multiple of 4
99 int nintS = (numStructural_+15) >> 4;
100 int nintA = (numArtificial_+15) >> 4;
101 maxSize_ = nintS+nintA;
102 if (maxSize_ > 0) {
103 structuralStatus_ = new char[4*maxSize_];
104 CoinMemcpyN( ws.structuralStatus_, (4*nintS), structuralStatus_);
105 artificialStatus_ = structuralStatus_+4*nintS;
106 CoinMemcpyN( ws.artificialStatus_, (4*nintA), artificialStatus_);
107 }
108}
109
110CoinWarmStartBasis&
111CoinWarmStartBasis::operator=(const CoinWarmStartBasis& rhs)
112{
113 if (this != &rhs) {
114 numStructural_=rhs.numStructural_;
115 numArtificial_=rhs.numArtificial_;
116 // Round all so arrays multiple of 4
117 int nintS = (numStructural_+15) >> 4;
118 int nintA = (numArtificial_+15) >> 4;
119 int size = nintS+nintA;
120 if (size>maxSize_) {
121 delete[] structuralStatus_;
122 maxSize_ = size+10;
123 structuralStatus_ = new char[4*maxSize_];
124 }
125 if (size > 0) {
126 CoinMemcpyN( rhs.structuralStatus_, (4*nintS), structuralStatus_);
127 artificialStatus_ = structuralStatus_+4*nintS;
128 CoinMemcpyN( rhs.artificialStatus_, (4*nintA), artificialStatus_);
129 } else {
130 artificialStatus_ = NULL;
131 }
132 }
133 return *this;
134}
135
136// Resizes
137void
138CoinWarmStartBasis::resize (int newNumberRows, int newNumberColumns)
139{
140 int i , nCharNewS, nCharOldS, nCharNewA, nCharOldA;
141 if (newNumberRows!=numArtificial_||newNumberColumns!=numStructural_) {
142 nCharOldS = 4*((numStructural_+15)>>4);
143 int nIntS = (newNumberColumns+15)>>4;
144 nCharNewS = 4*nIntS;
145 nCharOldA = 4*((numArtificial_+15)>>4);
146 int nIntA = (newNumberRows+15)>>4;
147 nCharNewA = 4*nIntA;
148 int size = nIntS+nIntA;
149 // Do slowly if number of columns increases or need new array
150 if (newNumberColumns>numStructural_||
151 size>maxSize_) {
152 if (size>maxSize_)
153 maxSize_ = size+10;
154 char * array = new char[4*maxSize_];
155 // zap all for clarity and zerofault etc
156 memset(array,0,4*maxSize_*sizeof(char));
157 CoinMemcpyN(structuralStatus_,(nCharOldS>nCharNewS)?nCharNewS:nCharOldS,array);
158 CoinMemcpyN(artificialStatus_, (nCharOldA>nCharNewA)?nCharNewA:nCharOldA,
159 array+nCharNewS);
160 delete [] structuralStatus_;
161 structuralStatus_ = array;
162 artificialStatus_ = array+nCharNewS;
163 for (i=numStructural_;i<newNumberColumns;i++)
164 setStructStatus(i, atLowerBound);
165 for (i=numArtificial_;i<newNumberRows;i++)
166 setArtifStatus(i, basic);
167 } else {
168 // can do faster
169 if (newNumberColumns!=numStructural_) {
170 memmove(structuralStatus_+nCharNewS,artificialStatus_,
171 (nCharOldA>nCharNewA)?nCharNewA:nCharOldA);
172 artificialStatus_ = structuralStatus_+4*nIntS;
173 }
174 for (i=numArtificial_;i<newNumberRows;i++)
175 setArtifStatus(i, basic);
176 }
177 numStructural_ = newNumberColumns;
178 numArtificial_ = newNumberRows;
179 }
180}
181
182/*
183 compressRows takes an ascending list of target indices without duplicates
184 and removes them, compressing the artificialStatus_ array in place. It will
185 fail spectacularly if the indices are not sorted. Use deleteRows if you
186 need to preprocess the target indices to satisfy the conditions.
187*/
188void CoinWarmStartBasis::compressRows (int tgtCnt, const int *tgts)
189{
190 int i,keep,t,blkStart,blkEnd ;
191/*
192 Depending on circumstances, constraint indices may be larger than the size
193 of the basis. Check for that now. Scan from top, betting that in most cases
194 the majority of indices will be valid.
195*/
196 for (t = tgtCnt-1 ; t >= 0 && tgts[t] >= numArtificial_ ; t--) ;
197 // temporary trap to make sure that scan from top is correct choice.
198 // if ((t+1) < tgtCnt/2)
199 // { printf("CWSB: tgtCnt %d, t %d; BAD CASE",tgtCnt,t+1) ; }
200 if (t < 0) return ;
201 tgtCnt = t+1 ;
202 Status stati ;
203
204# ifdef COIN_DEBUG
205/*
206 If we're debugging, scan to see if we're deleting nonbasic artificials.
207 (In other words, are we deleting tight constraints?) Easiest to just do this
208 up front as opposed to integrating it with the loops below.
209*/
210 int nbCnt = 0 ;
211 for (t = 0 ; t < tgtCnt ; t++)
212 { i = tgts[t] ;
213 stati = getStatus(artificialStatus_,i) ;
214 if (stati != CoinWarmStartBasis::basic)
215 { nbCnt++ ; } }
216 if (nbCnt > 0)
217 { std::cout << nbCnt << " nonbasic artificials deleted." << std::endl ; }
218# endif
219
220/*
221 Preserve all entries before the first target. Skip across consecutive
222 target indices to establish the start of the first block to be retained.
223*/
224 keep = tgts[0] ;
225 for (t = 0 ; t < tgtCnt-1 && tgts[t]+1 == tgts[t+1] ; t++) ;
226 blkStart = tgts[t]+1 ;
227/*
228 Outer loop works through the indices to be deleted. Inner loop copies runs
229 of indices to keep.
230*/
231 while (t < tgtCnt-1)
232 { blkEnd = tgts[t+1]-1 ;
233 for (i = blkStart ; i <= blkEnd ; i++)
234 { stati = getStatus(artificialStatus_,i) ;
235 setStatus(artificialStatus_,keep++,stati) ; }
236 for (t++ ; t < tgtCnt-1 && tgts[t]+1 == tgts[t+1] ; t++) ;
237 blkStart = tgts[t]+1 ; }
238/*
239 Finish off by copying from last deleted index to end of status array.
240*/
241 for (i = blkStart ; i < numArtificial_ ; i++)
242 { stati = getStatus(artificialStatus_,i) ;
243 setStatus(artificialStatus_,keep++,stati) ; }
244
245 numArtificial_ -= tgtCnt ;
246
247 return ; }
248
249/*
250 deleteRows takes an unordered list of target indices with duplicates and
251 removes them from the basis. The strategy is to preprocesses the list into
252 an ascending list without duplicates, suitable for compressRows.
253*/
254void
255CoinWarmStartBasis::deleteRows (int rawTgtCnt, const int *rawTgts)
256{ if (rawTgtCnt <= 0) return ;
257
258 int i;
259 int last=-1;
260 bool ordered=true;
261 for (i=0;i<rawTgtCnt;i++) {
262 int iRow = rawTgts[i];
263 if (iRow>last) {
264 last=iRow;
265 } else {
266 ordered=false;
267 break;
268 }
269 }
270 if (ordered) {
271 compressRows(rawTgtCnt,rawTgts) ;
272 } else {
273 int * tgts = new int[rawTgtCnt] ;
274 CoinMemcpyN(rawTgts,rawTgtCnt,tgts);
275 int *first = &tgts[0] ;
276 int *last = &tgts[rawTgtCnt] ;
277 int *endUnique ;
278 std::sort(first,last) ;
279 endUnique = std::unique(first,last) ;
280 int tgtCnt = static_cast<int>(endUnique-first) ;
281 compressRows(tgtCnt,tgts) ;
282 delete [] tgts ;
283 }
284 return ; }
285
286// Deletes columns
287void
288CoinWarmStartBasis::deleteColumns(int number, const int * which)
289{
290 int i ;
291 char * deleted = new char[numStructural_];
292 int numberDeleted=0;
293 memset(deleted,0,numStructural_*sizeof(char));
294 for (i=0;i<number;i++) {
295 int j = which[i];
296 if (j>=0&&j<numStructural_&&!deleted[j]) {
297 numberDeleted++;
298 deleted[j]=1;
299 }
300 }
301 int nCharNewS = 4*((numStructural_-numberDeleted+15)>>4);
302 int nCharNewA = 4*((numArtificial_+15)>>4);
303 char * array = new char[4*maxSize_];
304# ifdef ZEROFAULT
305 memset(array,0,(4*maxSize_*sizeof(char))) ;
306# endif
307 CoinMemcpyN(artificialStatus_,nCharNewA,array+nCharNewS);
308 int put=0;
309# ifdef COIN_DEBUG
310 int numberBasic=0;
311# endif
312 for (i=0;i<numStructural_;i++) {
313 Status status = getStructStatus(i);
314 if (!deleted[i]) {
315 setStatus(array,put,status) ;
316 put++; }
317# ifdef COIN_DEBUG
318 else
319 if (status==CoinWarmStartBasis::basic)
320 { numberBasic++ ; }
321# endif
322 }
323 delete [] structuralStatus_;
324 structuralStatus_ = array;
325 artificialStatus_ = structuralStatus_ + nCharNewS;
326 delete [] deleted;
327 numStructural_ -= numberDeleted;
328#ifdef COIN_DEBUG
329 if (numberBasic)
330 std::cout<<numberBasic<<" basic structurals deleted"<<std::endl;
331#endif
332}
333
334/*
335 Merge the specified entries from the source basis (src) into the target
336 basis (this). For each entry in xferCols, xferRows, first is the source index,
337 second is the target index, and third is the run length.
338
339 This routine was originally created to solve the problem of correctly
340 expanding an existing basis but can be used in a general context to merge
341 two bases.
342
343 If the xferRows (xferCols) vector is missing, no row (column) information
344 will be transferred from src to tgt.
345*/
346
347void CoinWarmStartBasis::mergeBasis (const CoinWarmStartBasis *src,
348 const XferVec *xferRows,
349 const XferVec *xferCols)
350
351{ assert(src) ;
352 int srcCols = src->getNumStructural() ;
353 int srcRows = src->getNumArtificial() ;
354/*
355 Merge the structural variable status.
356*/
357 if (srcCols > 0 && xferCols != NULL)
358 { XferVec::const_iterator xferSpec = xferCols->begin() ;
359 XferVec::const_iterator xferEnd = xferCols->end() ;
360 for ( ; xferSpec != xferEnd ; xferSpec++)
361 { int srcNdx = (*xferSpec).first ;
362 int tgtNdx = (*xferSpec).second ;
363 int runLen = (*xferSpec).third ;
364 assert(srcNdx >= 0 && srcNdx+runLen <= srcCols) ;
365 assert(tgtNdx >= 0 && tgtNdx+runLen <= getNumStructural()) ;
366 for (int i = 0 ; i < runLen ; i++)
367 { CoinWarmStartBasis::Status stat = src->getStructStatus(srcNdx+i) ;
368 setStructStatus(tgtNdx+i,stat) ; } } }
369/*
370 Merge the row (artificial variable) status.
371*/
372 if (srcRows > 0 && xferRows != NULL)
373 { XferVec::const_iterator xferSpec = xferRows->begin() ;
374 XferVec::const_iterator xferEnd = xferRows->end() ;
375 for ( ; xferSpec != xferEnd ; xferSpec++)
376 { int srcNdx = (*xferSpec).first ;
377 int tgtNdx = (*xferSpec).second ;
378 int runLen = (*xferSpec).third ;
379 assert(srcNdx >= 0 && srcNdx+runLen <= srcRows) ;
380 assert(tgtNdx >= 0 && tgtNdx+runLen <= getNumArtificial()) ;
381 for (int i = 0 ; i < runLen ; i++)
382 { CoinWarmStartBasis::Status stat = src->getArtifStatus(srcNdx+i) ;
383 setArtifStatus(tgtNdx+i,stat) ; } } }
384
385 return ; }
386
387// Prints in readable format (for debug)
388void
389CoinWarmStartBasis::print() const
390{
391 int i ;
392 int numberBasic=0;
393 for (i=0;i<numStructural_;i++) {
394 Status status = getStructStatus(i);
395 if (status==CoinWarmStartBasis::basic)
396 numberBasic++;
397 }
398 int numberStructBasic = numberBasic;
399 for (i=0;i<numArtificial_;i++) {
400 Status status = getArtifStatus(i);
401 if (status==CoinWarmStartBasis::basic)
402 numberBasic++;
403 }
404 std::cout<<"Basis "<<this<<" has "<<numArtificial_<<" rows and "
405 <<numStructural_<<" columns, "
406 <<numberBasic<<" basic, of which "<<numberStructBasic
407 <<" were columns"<<std::endl;
408 std::cout<<"Rows:"<<std::endl;
409 char type[]={'F','B','U','L'};
410
411 for (i=0;i<numArtificial_;i++)
412 std::cout<<type[getArtifStatus(i)];
413 std::cout<<std::endl;
414 std::cout<<"Columns:"<<std::endl;
415
416 for (i=0;i<numStructural_;i++)
417 std::cout<<type[getStructStatus(i)];
418 std::cout<<std::endl;
419}
420CoinWarmStartBasis::CoinWarmStartBasis()
421{
422
423 numStructural_ = 0;
424 numArtificial_ = 0;
425 maxSize_ = 0;
426 structuralStatus_ = NULL;
427 artificialStatus_ = NULL;
428}
429CoinWarmStartBasis::~CoinWarmStartBasis()
430{
431 delete[] structuralStatus_;
432}
433// Returns number of basic structurals
434int
435CoinWarmStartBasis::numberBasicStructurals() const
436{
437 int i ;
438 int numberBasic=0;
439 for (i=0;i<numStructural_;i++) {
440 Status status = getStructStatus(i);
441 if (status==CoinWarmStartBasis::basic)
442 numberBasic++;
443 }
444 return numberBasic;
445}
446// Returns true if full basis (for debug)
447bool
448CoinWarmStartBasis::fullBasis() const
449{
450 int i ;
451 int numberBasic=0;
452 for (i=0;i<numStructural_;i++) {
453 Status status = getStructStatus(i);
454 if (status==CoinWarmStartBasis::basic)
455 numberBasic++;
456 }
457 for (i=0;i<numArtificial_;i++) {
458 Status status = getArtifStatus(i);
459 if (status==CoinWarmStartBasis::basic)
460 numberBasic++;
461 }
462#ifdef COIN_DEVELOP
463 if (numberBasic!=numArtificial_)
464 printf("mismatch - basis has %d rows, %d basic\n",
465 numArtificial_,numberBasic);
466#endif
467 return numberBasic==numArtificial_;
468}
469// Returns true if full basis and fixes up (for debug)
470bool
471CoinWarmStartBasis::fixFullBasis()
472{
473 int i ;
474 int numberBasic=0;
475 for (i=0;i<numStructural_;i++) {
476 Status status = getStructStatus(i);
477 if (status==CoinWarmStartBasis::basic)
478 numberBasic++;
479 }
480 for (i=0;i<numArtificial_;i++) {
481 Status status = getArtifStatus(i);
482 if (status==CoinWarmStartBasis::basic)
483 numberBasic++;
484 }
485#ifdef COIN_DEVELOP
486 if (numberBasic!=numArtificial_)
487 printf("mismatch - basis has %d rows, %d basic\n",
488 numArtificial_,numberBasic);
489#endif
490 bool returnCode = (numberBasic==numArtificial_);
491 if (numberBasic>numArtificial_) {
492 for (i=0;i<numStructural_;i++) {
493 Status status = getStructStatus(i);
494 if (status==CoinWarmStartBasis::basic)
495 setStructStatus(i,atLowerBound);
496 numberBasic--;
497 if (numberBasic==numArtificial_)
498 break;
499 }
500 } else if (numberBasic<numArtificial_) {
501 for (i=0;i<numArtificial_;i++) {
502 Status status = getArtifStatus(i);
503 if (status!=CoinWarmStartBasis::basic) {
504 setArtifStatus(i,basic);
505 numberBasic++;
506 if (numberBasic==numArtificial_)
507 break;
508 }
509 }
510 }
511 return returnCode;
512}
513/*
514 Generate a diff that'll convert oldCWS into the basis pointed to by this.
515
516 This routine is a bit of a hack, for efficiency's sake. Rather than work
517 with individual status vector entries, we're going to treat the vectors as
518 int's --- in effect, we create one diff entry for each block of 16 status
519 entries. Diffs for logicals are tagged with 0x80000000.
520*/
521
522CoinWarmStartDiff*
523CoinWarmStartBasis::generateDiff (const CoinWarmStart *const oldCWS) const
524{
525/*
526 Make sure the parameter is CoinWarmStartBasis or derived class.
527*/
528 const CoinWarmStartBasis *oldBasis =
529 dynamic_cast<const CoinWarmStartBasis *>(oldCWS) ;
530#ifndef NDEBUG
531 if (!oldBasis)
532 { throw CoinError("Old basis not derived from CoinWarmStartBasis.",
533 "generateDiff","CoinWarmStartBasis") ; }
534#endif
535 const CoinWarmStartBasis *newBasis = this ;
536/*
537 Make sure newBasis is equal or bigger than oldBasis. Calculate the worst case
538 number of diffs and allocate vectors to hold them.
539*/
540 const int oldArtifCnt = oldBasis->getNumArtificial() ;
541 const int oldStructCnt = oldBasis->getNumStructural() ;
542 const int newArtifCnt = newBasis->getNumArtificial() ;
543 const int newStructCnt = newBasis->getNumStructural() ;
544
545 assert(newArtifCnt >= oldArtifCnt) ;
546 assert(newStructCnt >= oldStructCnt) ;
547
548 int sizeOldArtif = (oldArtifCnt+15)>>4 ;
549 int sizeNewArtif = (newArtifCnt+15)>>4 ;
550 int sizeOldStruct = (oldStructCnt+15)>>4 ;
551 int sizeNewStruct = (newStructCnt+15)>>4 ;
552 int maxBasisLength = sizeNewArtif+sizeNewStruct ;
553
554 unsigned int *diffNdx = new unsigned int [2*maxBasisLength];
555 unsigned int *diffVal = diffNdx + maxBasisLength;
556/*
557 Ok, setup's over. Now scan the logicals (aka artificials, standing in for
558 constraints). For the portion of the status arrays which overlap, create
559 diffs. Then add any additional status from newBasis.
560
561 I removed the following bit of code & comment:
562
563 if (sizeNew == sizeOld) sizeOld--; // make sure all taken
564
565 I assume this is meant to trap cases where oldBasis does not occupy all of
566 the final int, but I can't see where it's necessary.
567*/
568 const unsigned int *oldStatus =
569 reinterpret_cast<const unsigned int *>(oldBasis->getArtificialStatus()) ;
570 const unsigned int *newStatus =
571 reinterpret_cast<const unsigned int *>(newBasis->getArtificialStatus()) ;
572 int numberChanged = 0 ;
573 int i ;
574 for (i = 0 ; i < sizeOldArtif ; i++)
575 { if (oldStatus[i] != newStatus[i])
576 { diffNdx[numberChanged] = i|0x80000000 ;
577 diffVal[numberChanged++] = newStatus[i] ; } }
578 for ( ; i < sizeNewArtif ; i++)
579 { diffNdx[numberChanged] = i|0x80000000 ;
580 diffVal[numberChanged++] = newStatus[i] ; }
581/*
582 Repeat for structural variables.
583*/
584 oldStatus =
585 reinterpret_cast<const unsigned int *>(oldBasis->getStructuralStatus()) ;
586 newStatus =
587 reinterpret_cast<const unsigned int *>(newBasis->getStructuralStatus()) ;
588 for (i = 0 ; i < sizeOldStruct ; i++)
589 { if (oldStatus[i] != newStatus[i])
590 { diffNdx[numberChanged] = i ;
591 diffVal[numberChanged++] = newStatus[i] ; } }
592 for ( ; i < sizeNewStruct ; i++)
593 { diffNdx[numberChanged] = i ;
594 diffVal[numberChanged++] = newStatus[i] ; }
595/*
596 Create the object of our desire.
597*/
598 CoinWarmStartBasisDiff *diff;
599 if ((numberChanged*2<maxBasisLength+1||!newStructCnt)&&true)
600 diff = new CoinWarmStartBasisDiff(numberChanged,diffNdx,diffVal) ;
601 else
602 diff = new CoinWarmStartBasisDiff(newBasis) ;
603/*
604 Clean up and return.
605*/
606 delete[] diffNdx ;
607
608 return (static_cast<CoinWarmStartDiff *>(diff)) ; }
609
610
611/*
612 Apply a diff to the basis pointed to by this. It's assumed that the
613 allocated capacity of the basis is sufficiently large.
614*/
615void CoinWarmStartBasis::applyDiff (const CoinWarmStartDiff *const cwsdDiff)
616{
617/*
618 Make sure we have a CoinWarmStartBasisDiff
619*/
620 const CoinWarmStartBasisDiff *diff =
621 dynamic_cast<const CoinWarmStartBasisDiff *>(cwsdDiff) ;
622#ifndef NDEBUG
623 if (!diff)
624 { throw CoinError("Diff not derived from CoinWarmStartBasisDiff.",
625 "applyDiff","CoinWarmStartBasis") ; }
626#endif
627/*
628 Application is by straighforward replacement of words in the status arrays.
629 Index entries for logicals (aka artificials) are tagged with 0x80000000.
630*/
631 const int numberChanges = diff->sze_ ;
632 unsigned int *structStatus =
633 reinterpret_cast<unsigned int *>(this->getStructuralStatus()) ;
634 unsigned int *artifStatus =
635 reinterpret_cast<unsigned int *>(this->getArtificialStatus()) ;
636 if (numberChanges>=0) {
637 const unsigned int *diffNdxs = diff->difference_ ;
638 const unsigned int *diffVals = diffNdxs+numberChanges ;
639
640 for (int i = 0 ; i < numberChanges ; i++)
641 { unsigned int diffNdx = diffNdxs[i] ;
642 unsigned int diffVal = diffVals[i] ;
643 if ((diffNdx&0x80000000) == 0)
644 { structStatus[diffNdx] = diffVal ; }
645 else
646 { artifStatus[diffNdx&0x7fffffff] = diffVal ; } }
647 } else {
648 // just replace
649 const unsigned int * diffA = diff->difference_ -1;
650 const int artifCnt = static_cast<int> (diffA[0]);
651 const int structCnt = -numberChanges;
652 int sizeArtif = (artifCnt+15)>>4 ;
653 int sizeStruct = (structCnt+15)>>4 ;
654 CoinMemcpyN(diffA+1,sizeStruct,structStatus);
655 CoinMemcpyN(diffA+1+sizeStruct,sizeArtif,artifStatus);
656 }
657 return ; }
658
659
660/* Routines for CoinWarmStartBasisDiff */
661
662/*
663 Constructor given diff data.
664*/
665CoinWarmStartBasisDiff::CoinWarmStartBasisDiff (int sze,
666 const unsigned int *const diffNdxs, const unsigned int *const diffVals)
667 : sze_(sze),
668 difference_(NULL)
669
670{ if (sze > 0)
671 { difference_ = new unsigned int[2*sze] ;
672 CoinMemcpyN(diffNdxs,sze,difference_);
673 CoinMemcpyN(diffVals,sze,difference_+sze_); }
674
675 return ; }
676/*
677 Constructor when full is smaller than diff!
678*/
679CoinWarmStartBasisDiff::CoinWarmStartBasisDiff (const CoinWarmStartBasis * rhs)
680 : sze_(0),
681 difference_(0)
682{
683 const int artifCnt = rhs->getNumArtificial() ;
684 const int structCnt = rhs->getNumStructural() ;
685 int sizeArtif = (artifCnt+15)>>4 ;
686 int sizeStruct = (structCnt+15)>>4 ;
687 int maxBasisLength = sizeArtif+sizeStruct ;
688 assert (maxBasisLength&&structCnt);
689 sze_ = - structCnt;
690 difference_ = new unsigned int [maxBasisLength+1];
691 difference_[0]=artifCnt;
692 difference_++;
693 CoinMemcpyN(reinterpret_cast<const unsigned int *> (rhs->getStructuralStatus()),sizeStruct,
694 difference_);
695 CoinMemcpyN(reinterpret_cast<const unsigned int *> (rhs->getArtificialStatus()),sizeArtif,
696 difference_+sizeStruct);
697}
698
699/*
700 Copy constructor.
701*/
702
703CoinWarmStartBasisDiff::CoinWarmStartBasisDiff
704 (const CoinWarmStartBasisDiff &rhs)
705 : sze_(rhs.sze_),
706 difference_(0)
707{ if (sze_ >0)
708 { difference_ = CoinCopyOfArray(rhs.difference_,2*sze_); }
709 else if (sze_<0) {
710 const unsigned int * diff = rhs.difference_ -1;
711 const int artifCnt = static_cast<int> (diff[0]);
712 const int structCnt = -sze_;
713 int sizeArtif = (artifCnt+15)>>4 ;
714 int sizeStruct = (structCnt+15)>>4 ;
715 int maxBasisLength = sizeArtif+sizeStruct ;
716 difference_ = CoinCopyOfArray(diff,maxBasisLength+1);
717 difference_++;
718 }
719
720 return ; }
721
722/*
723 Assignment --- for convenience when assigning objects containing
724 CoinWarmStartBasisDiff objects.
725*/
726CoinWarmStartBasisDiff&
727CoinWarmStartBasisDiff::operator= (const CoinWarmStartBasisDiff &rhs)
728
729{ if (this != &rhs)
730 { if (sze_>0 )
731 { delete[] difference_ ; }
732 else if (sze_<0) {
733 unsigned int * diff = difference_ -1;
734 delete [] diff;
735 }
736 sze_ = rhs.sze_ ;
737 if (sze_ > 0)
738 { difference_ = CoinCopyOfArray(rhs.difference_,2*sze_); }
739 else if (sze_<0) {
740 const unsigned int * diff = rhs.difference_ -1;
741 const int artifCnt = static_cast<int> (diff[0]);
742 const int structCnt = -sze_;
743 int sizeArtif = (artifCnt+15)>>4 ;
744 int sizeStruct = (structCnt+15)>>4 ;
745 int maxBasisLength = sizeArtif+sizeStruct ;
746 difference_ = CoinCopyOfArray(diff,maxBasisLength+1);
747 difference_++;
748 }
749 else
750 { difference_ = 0 ; } }
751
752 return (*this) ; }
753/*brief Destructor */
754CoinWarmStartBasisDiff::~CoinWarmStartBasisDiff()
755{
756 if (sze_>0 ) {
757 delete[] difference_ ;
758 } else if (sze_<0) {
759 unsigned int * diff = difference_ -1;
760 delete [] diff;
761 }
762}
763