1 /* $Id: CoinSimpFactorization.cpp 2083 2019-01-06 19:38:09Z unxusr $ */
2 // Copyright (C) 2008, 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 #if COIN_BIG_INDEX == 0
6 #include "CoinUtilsConfig.h"
7 
8 #include <cassert>
9 #include "CoinPragma.hpp"
10 #include "CoinSimpFactorization.hpp"
11 #include "CoinIndexedVector.hpp"
12 #include "CoinHelperFunctions.hpp"
13 #include "CoinPackedMatrix.hpp"
14 #include "CoinFinite.hpp"
15 #include <stdio.h>
16 
17 #define ARRAY 0
18 
FactorPointers(int numRows,int numColumns,int * UrowLengths_,int * UcolLengths_)19 FactorPointers::FactorPointers(int numRows, int numColumns,
20   int *UrowLengths_,
21   int *UcolLengths_)
22 {
23 
24   rowMax = new double[numRows];
25   double *current = rowMax;
26   const double *end = current + numRows;
27   for (; current != end; ++current)
28     *current = -1.0;
29 
30   firstRowKnonzeros = new int[numRows + 1];
31   CoinFillN(firstRowKnonzeros, numRows + 1, -1);
32 
33   prevRow = new int[numRows];
34   nextRow = new int[numRows];
35   firstColKnonzeros = new int[numRows + 1];
36   memset(firstColKnonzeros, -1, (numRows + 1) * sizeof(int));
37 
38   prevColumn = new int[numColumns];
39   nextColumn = new int[numColumns];
40   newCols = new int[numRows];
41 
42   for (int i = numRows - 1; i >= 0; --i) {
43     int length = UrowLengths_[i];
44     prevRow[i] = -1;
45     nextRow[i] = firstRowKnonzeros[length];
46     if (nextRow[i] != -1)
47       prevRow[nextRow[i]] = i;
48     firstRowKnonzeros[length] = i;
49   }
50   for (int i = numColumns - 1; i >= 0; --i) {
51     int length = UcolLengths_[i];
52     prevColumn[i] = -1;
53     nextColumn[i] = firstColKnonzeros[length];
54     if (nextColumn[i] != -1)
55       prevColumn[nextColumn[i]] = i;
56     firstColKnonzeros[length] = i;
57   }
58 }
~FactorPointers()59 FactorPointers::~FactorPointers()
60 {
61   delete[] rowMax;
62   delete[] firstRowKnonzeros;
63   delete[] prevRow;
64   delete[] nextRow;
65   delete[] firstColKnonzeros;
66   delete[] prevColumn;
67   delete[] nextColumn;
68   delete[] newCols;
69 }
70 
71 //:class CoinSimpFactorization.  Deals with Factorization and Updates
72 //  CoinSimpFactorization.  Constructor
CoinSimpFactorization()73 CoinSimpFactorization::CoinSimpFactorization()
74   : CoinOtherFactorization()
75 {
76   gutsOfInitialize();
77 }
78 
79 /// Copy constructor
CoinSimpFactorization(const CoinSimpFactorization & other)80 CoinSimpFactorization::CoinSimpFactorization(const CoinSimpFactorization &other)
81   : CoinOtherFactorization(other)
82 {
83   gutsOfInitialize();
84   gutsOfCopy(other);
85 }
86 // Clone
87 CoinOtherFactorization *
clone() const88 CoinSimpFactorization::clone() const
89 {
90   return new CoinSimpFactorization(*this);
91 }
92 /// The real work of constructors etc
gutsOfDestructor()93 void CoinSimpFactorization::gutsOfDestructor()
94 {
95   delete[] elements_;
96   delete[] pivotRow_;
97   delete[] workArea_;
98   elements_ = NULL;
99   pivotRow_ = NULL;
100   workArea_ = NULL;
101   numberRows_ = 0;
102   numberColumns_ = 0;
103   numberGoodU_ = 0;
104   status_ = -1;
105   maximumRows_ = 0;
106   maximumSpace_ = 0;
107   numberSlacks_ = 0;
108   firstNumberSlacks_ = 0;
109   //
110   delete[] denseVector_;
111   delete[] workArea2_;
112   delete[] workArea3_;
113   delete[] vecLabels_;
114   delete[] indVector_;
115 
116   delete[] auxVector_;
117   delete[] auxInd_;
118 
119   delete[] vecKeep_;
120   delete[] indKeep_;
121 
122   delete[] LrowStarts_;
123   delete[] LrowLengths_;
124   delete[] Lrows_;
125   delete[] LrowInd_;
126 
127   delete[] LcolStarts_;
128   delete[] LcolLengths_;
129   delete[] Lcolumns_;
130   delete[] LcolInd_;
131 
132   delete[] UrowStarts_;
133   delete[] UrowLengths_;
134 #ifdef COIN_SIMP_CAPACITY
135   delete[] UrowCapacities_;
136 #endif
137   delete[] Urows_;
138   delete[] UrowInd_;
139 
140   delete[] prevRowInU_;
141   delete[] nextRowInU_;
142 
143   delete[] UcolStarts_;
144   delete[] UcolLengths_;
145 #ifdef COIN_SIMP_CAPACITY
146   delete[] UcolCapacities_;
147 #endif
148   delete[] Ucolumns_;
149   delete[] UcolInd_;
150   delete[] prevColInU_;
151   delete[] nextColInU_;
152   delete[] colSlack_;
153 
154   delete[] invOfPivots_;
155 
156   delete[] colOfU_;
157   delete[] colPosition_;
158   delete[] rowOfU_;
159   delete[] rowPosition_;
160   delete[] secRowOfU_;
161   delete[] secRowPosition_;
162 
163   delete[] EtaPosition_;
164   delete[] EtaStarts_;
165   delete[] EtaLengths_;
166   delete[] EtaInd_;
167   delete[] Eta_;
168 
169   denseVector_ = NULL;
170   workArea2_ = NULL;
171   workArea3_ = NULL;
172   vecLabels_ = NULL;
173   indVector_ = NULL;
174 
175   auxVector_ = NULL;
176   auxInd_ = NULL;
177 
178   vecKeep_ = NULL;
179   indKeep_ = NULL;
180 
181   LrowStarts_ = NULL;
182   LrowLengths_ = NULL;
183   Lrows_ = NULL;
184   LrowInd_ = NULL;
185 
186   LcolStarts_ = NULL;
187   LcolLengths_ = NULL;
188   Lcolumns_ = NULL;
189   LcolInd_ = NULL;
190 
191   UrowStarts_ = NULL;
192   UrowLengths_ = NULL;
193 #ifdef COIN_SIMP_CAPACITY
194   UrowCapacities_ = NULL;
195 #endif
196   Urows_ = NULL;
197   UrowInd_ = NULL;
198 
199   prevRowInU_ = NULL;
200   nextRowInU_ = NULL;
201 
202   UcolStarts_ = NULL;
203   UcolLengths_ = NULL;
204 #ifdef COIN_SIMP_CAPACITY
205   UcolCapacities_ = NULL;
206 #endif
207   Ucolumns_ = NULL;
208   UcolInd_ = NULL;
209   prevColInU_ = NULL;
210   nextColInU_ = NULL;
211   colSlack_ = NULL;
212 
213   invOfPivots_ = NULL;
214 
215   colOfU_ = NULL;
216   colPosition_ = NULL;
217   rowOfU_ = NULL;
218   rowPosition_ = NULL;
219   secRowOfU_ = NULL;
220   secRowPosition_ = NULL;
221 
222   EtaPosition_ = NULL;
223   EtaStarts_ = NULL;
224   EtaLengths_ = NULL;
225   EtaInd_ = NULL;
226   Eta_ = NULL;
227 }
gutsOfInitialize()228 void CoinSimpFactorization::gutsOfInitialize()
229 {
230   pivotTolerance_ = 1.0e-1;
231   zeroTolerance_ = 1.0e-13;
232 #ifndef COIN_FAST_CODE
233   slackValue_ = -1.0;
234 #endif
235   maximumPivots_ = 200;
236   relaxCheck_ = 1.0;
237   numberRows_ = 0;
238   numberColumns_ = 0;
239   numberGoodU_ = 0;
240   status_ = -1;
241   numberPivots_ = 0;
242   maximumRows_ = 0;
243   maximumSpace_ = 0;
244   numberSlacks_ = 0;
245   firstNumberSlacks_ = 0;
246   elements_ = NULL;
247   pivotRow_ = NULL;
248   workArea_ = NULL;
249 
250   denseVector_ = NULL;
251   workArea2_ = NULL;
252   workArea3_ = NULL;
253   vecLabels_ = NULL;
254   indVector_ = NULL;
255 
256   auxVector_ = NULL;
257   auxInd_ = NULL;
258 
259   vecKeep_ = NULL;
260   indKeep_ = NULL;
261 
262   LrowStarts_ = NULL;
263   LrowLengths_ = NULL;
264   Lrows_ = NULL;
265   LrowInd_ = NULL;
266 
267   LcolStarts_ = NULL;
268   LcolLengths_ = NULL;
269   Lcolumns_ = NULL;
270   LcolInd_ = NULL;
271 
272   UrowStarts_ = NULL;
273   UrowLengths_ = NULL;
274 #ifdef COIN_SIMP_CAPACITY
275   UrowCapacities_ = NULL;
276 #endif
277   Urows_ = NULL;
278   UrowInd_ = NULL;
279 
280   prevRowInU_ = NULL;
281   nextRowInU_ = NULL;
282 
283   UcolStarts_ = NULL;
284   UcolLengths_ = NULL;
285 #ifdef COIN_SIMP_CAPACITY
286   UcolCapacities_ = NULL;
287 #endif
288   Ucolumns_ = NULL;
289   UcolInd_ = NULL;
290   prevColInU_ = NULL;
291   nextColInU_ = NULL;
292   colSlack_ = NULL;
293 
294   invOfPivots_ = NULL;
295 
296   colOfU_ = NULL;
297   colPosition_ = NULL;
298   rowOfU_ = NULL;
299   rowPosition_ = NULL;
300   secRowOfU_ = NULL;
301   secRowPosition_ = NULL;
302 
303   EtaPosition_ = NULL;
304   EtaStarts_ = NULL;
305   EtaLengths_ = NULL;
306   EtaInd_ = NULL;
307   Eta_ = NULL;
308 }
initialSomeNumbers()309 void CoinSimpFactorization::initialSomeNumbers()
310 {
311   keepSize_ = -1;
312   LrowSize_ = -1;
313   // LrowCap_ in allocateSomeArrays
314   LcolSize_ = -1;
315   // LcolCap_ in allocateSomeArrays
316   // UrowMaxCap_ in allocateSomeArrays
317   UrowEnd_ = -1;
318   firstRowInU_ = -1;
319   lastRowInU_ = -1;
320   firstColInU_ = -1;
321   lastColInU_ = -1;
322   //UcolMaxCap_ in allocateSomeArrays
323   UcolEnd_ = -1;
324 
325   EtaSize_ = 0;
326   lastEtaRow_ = -1;
327   //maxEtaRows_ in allocateSomeArrays
328   //EtaMaxCap_ in allocateSomeArrays
329 
330   // minIncrease_ in allocateSomeArrays
331   updateTol_ = 1.0e12;
332 
333   doSuhlHeuristic_ = true;
334   maxU_ = -1.0;
335   maxGrowth_ = 1.e12;
336   maxA_ = -1.0;
337   pivotCandLimit_ = 4;
338   minIncrease_ = 10;
339 }
340 
341 //  ~CoinSimpFactorization.  Destructor
~CoinSimpFactorization()342 CoinSimpFactorization::~CoinSimpFactorization()
343 {
344   gutsOfDestructor();
345 }
346 //  =
operator =(const CoinSimpFactorization & other)347 CoinSimpFactorization &CoinSimpFactorization::operator=(const CoinSimpFactorization &other)
348 {
349   if (this != &other) {
350     gutsOfDestructor();
351     gutsOfInitialize();
352     gutsOfCopy(other);
353   }
354   return *this;
355 }
gutsOfCopy(const CoinSimpFactorization & other)356 void CoinSimpFactorization::gutsOfCopy(const CoinSimpFactorization &other)
357 {
358   pivotTolerance_ = other.pivotTolerance_;
359   zeroTolerance_ = other.zeroTolerance_;
360 #ifndef COIN_FAST_CODE
361   slackValue_ = other.slackValue_;
362 #endif
363   relaxCheck_ = other.relaxCheck_;
364   numberRows_ = other.numberRows_;
365   numberColumns_ = other.numberColumns_;
366   maximumRows_ = other.maximumRows_;
367   maximumSpace_ = other.maximumSpace_;
368   numberGoodU_ = other.numberGoodU_;
369   maximumPivots_ = other.maximumPivots_;
370   numberPivots_ = other.numberPivots_;
371   factorElements_ = other.factorElements_;
372   status_ = other.status_;
373   numberSlacks_ = other.numberSlacks_;
374   firstNumberSlacks_ = other.firstNumberSlacks_;
375   if (other.pivotRow_) {
376     pivotRow_ = new int[2 * maximumRows_ + maximumPivots_];
377     memcpy(pivotRow_, other.pivotRow_, (2 * maximumRows_ + numberPivots_) * sizeof(int));
378     elements_ = new CoinFactorizationDouble[maximumSpace_];
379     memcpy(elements_, other.elements_, (maximumRows_ + numberPivots_) * maximumRows_ * sizeof(CoinFactorizationDouble));
380     workArea_ = new CoinFactorizationDouble[maximumRows_];
381   } else {
382     elements_ = NULL;
383     pivotRow_ = NULL;
384     workArea_ = NULL;
385   }
386 
387   keepSize_ = other.keepSize_;
388 
389   LrowSize_ = other.LrowSize_;
390   LrowCap_ = other.LrowCap_;
391 
392   LcolSize_ = other.LcolSize_;
393   LcolCap_ = other.LcolCap_;
394 
395   UrowMaxCap_ = other.UrowMaxCap_;
396   UrowEnd_ = other.UrowEnd_;
397   firstRowInU_ = other.firstRowInU_;
398   lastRowInU_ = other.lastRowInU_;
399 
400   firstColInU_ = other.firstColInU_;
401   lastColInU_ = other.lastColInU_;
402   UcolMaxCap_ = other.UcolMaxCap_;
403   UcolEnd_ = other.UcolEnd_;
404 
405   EtaSize_ = other.EtaSize_;
406   lastEtaRow_ = other.lastEtaRow_;
407   maxEtaRows_ = other.maxEtaRows_;
408   EtaMaxCap_ = other.EtaMaxCap_;
409 
410   minIncrease_ = other.minIncrease_;
411   updateTol_ = other.updateTol_;
412 
413   if (other.denseVector_) {
414     denseVector_ = new double[maximumRows_];
415     memcpy(denseVector_, other.denseVector_, maximumRows_ * sizeof(double));
416   } else
417     denseVector_ = NULL;
418   if (other.workArea2_) {
419     workArea2_ = new double[maximumRows_];
420     memcpy(workArea2_, other.workArea2_, maximumRows_ * sizeof(double));
421   } else
422     workArea2_ = NULL;
423   if (other.workArea3_) {
424     workArea3_ = new double[maximumRows_];
425     memcpy(workArea3_, other.workArea3_, maximumRows_ * sizeof(double));
426   } else
427     workArea3_ = NULL;
428   if (other.vecLabels_) {
429     vecLabels_ = new int[maximumRows_];
430     memcpy(vecLabels_, other.vecLabels_, maximumRows_ * sizeof(int));
431   } else
432     vecLabels_ = NULL;
433   if (other.indVector_) {
434     indVector_ = new int[maximumRows_];
435     memcpy(indVector_, other.indVector_, maximumRows_ * sizeof(int));
436   } else
437     indVector_ = NULL;
438 
439   if (other.auxVector_) {
440     auxVector_ = new double[maximumRows_];
441     memcpy(auxVector_, other.auxVector_, maximumRows_ * sizeof(double));
442   } else
443     auxVector_ = NULL;
444   if (other.auxInd_) {
445     auxInd_ = new int[maximumRows_];
446     memcpy(auxInd_, other.auxInd_, maximumRows_ * sizeof(int));
447   } else
448     auxInd_ = NULL;
449 
450   if (other.vecKeep_) {
451     vecKeep_ = new double[maximumRows_];
452     memcpy(vecKeep_, other.vecKeep_, maximumRows_ * sizeof(double));
453   } else
454     vecKeep_ = NULL;
455   if (other.indKeep_) {
456     indKeep_ = new int[maximumRows_];
457     memcpy(indKeep_, other.indKeep_, maximumRows_ * sizeof(int));
458   } else
459     indKeep_ = NULL;
460   if (other.LrowStarts_) {
461     LrowStarts_ = new int[maximumRows_];
462     memcpy(LrowStarts_, other.LrowStarts_, maximumRows_ * sizeof(int));
463   } else
464     LrowStarts_ = NULL;
465   if (other.LrowLengths_) {
466     LrowLengths_ = new int[maximumRows_];
467     memcpy(LrowLengths_, other.LrowLengths_, maximumRows_ * sizeof(int));
468   } else
469     LrowLengths_ = NULL;
470   if (other.Lrows_) {
471     Lrows_ = new double[other.LrowCap_];
472     memcpy(Lrows_, other.Lrows_, other.LrowCap_ * sizeof(double));
473   } else
474     Lrows_ = NULL;
475   if (other.LrowInd_) {
476     LrowInd_ = new int[other.LrowCap_];
477     memcpy(LrowInd_, other.LrowInd_, other.LrowCap_ * sizeof(int));
478   } else
479     LrowInd_ = NULL;
480 
481   if (other.LcolStarts_) {
482     LcolStarts_ = new int[maximumRows_];
483     memcpy(LcolStarts_, other.LcolStarts_, maximumRows_ * sizeof(int));
484   } else
485     LcolStarts_ = NULL;
486   if (other.LcolLengths_) {
487     LcolLengths_ = new int[maximumRows_];
488     memcpy(LcolLengths_, other.LcolLengths_, maximumRows_ * sizeof(int));
489   } else
490     LcolLengths_ = NULL;
491   if (other.Lcolumns_) {
492     Lcolumns_ = new double[other.LcolCap_];
493     memcpy(Lcolumns_, other.Lcolumns_, other.LcolCap_ * sizeof(double));
494   } else
495     Lcolumns_ = NULL;
496   if (other.LcolInd_) {
497     LcolInd_ = new int[other.LcolCap_];
498     memcpy(LcolInd_, other.LcolInd_, other.LcolCap_ * sizeof(int));
499   } else
500     LcolInd_ = NULL;
501 
502   if (other.UrowStarts_) {
503     UrowStarts_ = new int[maximumRows_];
504     memcpy(UrowStarts_, other.UrowStarts_, maximumRows_ * sizeof(int));
505   } else
506     UrowStarts_ = NULL;
507   if (other.UrowLengths_) {
508     UrowLengths_ = new int[maximumRows_];
509     memcpy(UrowLengths_, other.UrowLengths_, maximumRows_ * sizeof(int));
510   } else
511     UrowLengths_ = NULL;
512 #ifdef COIN_SIMP_CAPACITY
513   if (other.UrowCapacities_) {
514     UrowCapacities_ = new int[maximumRows_];
515     memcpy(UrowCapacities_, other.UrowCapacities_, maximumRows_ * sizeof(int));
516   } else
517     UrowCapacities_ = NULL;
518 #endif
519   if (other.Urows_) {
520     Urows_ = new double[other.UrowMaxCap_];
521     memcpy(Urows_, other.Urows_, other.UrowMaxCap_ * sizeof(double));
522   } else
523     Urows_ = NULL;
524   if (other.UrowInd_) {
525     UrowInd_ = new int[other.UrowMaxCap_];
526     memcpy(UrowInd_, other.UrowInd_, other.UrowMaxCap_ * sizeof(int));
527   } else
528     UrowInd_ = NULL;
529 
530   if (other.prevRowInU_) {
531     prevRowInU_ = new int[maximumRows_];
532     memcpy(prevRowInU_, other.prevRowInU_, maximumRows_ * sizeof(int));
533   } else
534     prevRowInU_ = NULL;
535   if (other.nextRowInU_) {
536     nextRowInU_ = new int[maximumRows_];
537     memcpy(nextRowInU_, other.nextRowInU_, maximumRows_ * sizeof(int));
538   } else
539     nextRowInU_ = NULL;
540 
541   if (other.UcolStarts_) {
542     UcolStarts_ = new int[maximumRows_];
543     memcpy(UcolStarts_, other.UcolStarts_, maximumRows_ * sizeof(int));
544   } else
545     UcolStarts_ = NULL;
546   if (other.UcolLengths_) {
547     UcolLengths_ = new int[maximumRows_];
548     memcpy(UcolLengths_, other.UcolLengths_, maximumRows_ * sizeof(int));
549   } else
550     UcolLengths_ = NULL;
551 #ifdef COIN_SIMP_CAPACITY
552   if (other.UcolCapacities_) {
553     UcolCapacities_ = new int[maximumRows_];
554     memcpy(UcolCapacities_, other.UcolCapacities_, maximumRows_ * sizeof(int));
555   } else
556     UcolCapacities_ = NULL;
557 #endif
558   if (other.Ucolumns_) {
559     Ucolumns_ = new double[other.UcolMaxCap_];
560     memcpy(Ucolumns_, other.Ucolumns_, other.UcolMaxCap_ * sizeof(double));
561   } else
562     Ucolumns_ = NULL;
563   if (other.UcolInd_) {
564     UcolInd_ = new int[other.UcolMaxCap_];
565     memcpy(UcolInd_, other.UcolInd_, other.UcolMaxCap_ * sizeof(int));
566   } else
567     UcolInd_ = NULL;
568   if (other.prevColInU_) {
569     prevColInU_ = new int[maximumRows_];
570     memcpy(prevColInU_, other.prevColInU_, maximumRows_ * sizeof(int));
571   } else
572     prevColInU_ = NULL;
573   if (other.nextColInU_) {
574     nextColInU_ = new int[maximumRows_];
575     memcpy(nextColInU_, other.nextColInU_, maximumRows_ * sizeof(int));
576   } else
577     nextColInU_ = NULL;
578   if (other.colSlack_) {
579     colSlack_ = new int[maximumRows_];
580     memcpy(colSlack_, other.colSlack_, maximumRows_ * sizeof(int));
581   }
582 
583   if (other.invOfPivots_) {
584     invOfPivots_ = new double[maximumRows_];
585     memcpy(invOfPivots_, other.invOfPivots_, maximumRows_ * sizeof(double));
586   } else
587     invOfPivots_ = NULL;
588 
589   if (other.colOfU_) {
590     colOfU_ = new int[maximumRows_];
591     memcpy(colOfU_, other.colOfU_, maximumRows_ * sizeof(int));
592   } else
593     colOfU_ = NULL;
594   if (other.colPosition_) {
595     colPosition_ = new int[maximumRows_];
596     memcpy(colPosition_, other.colPosition_, maximumRows_ * sizeof(int));
597   } else
598     colPosition_ = NULL;
599   if (other.rowOfU_) {
600     rowOfU_ = new int[maximumRows_];
601     memcpy(rowOfU_, other.rowOfU_, maximumRows_ * sizeof(int));
602   } else
603     rowOfU_ = NULL;
604   if (other.rowPosition_) {
605     rowPosition_ = new int[maximumRows_];
606     memcpy(rowPosition_, other.rowPosition_, maximumRows_ * sizeof(int));
607   } else
608     rowPosition_ = NULL;
609   if (other.secRowOfU_) {
610     secRowOfU_ = new int[maximumRows_];
611     memcpy(secRowOfU_, other.secRowOfU_, maximumRows_ * sizeof(int));
612   } else
613     secRowOfU_ = NULL;
614   if (other.secRowPosition_) {
615     secRowPosition_ = new int[maximumRows_];
616     memcpy(secRowPosition_, other.secRowPosition_, maximumRows_ * sizeof(int));
617   } else
618     secRowPosition_ = NULL;
619 
620   if (other.EtaPosition_) {
621     EtaPosition_ = new int[other.maxEtaRows_];
622     memcpy(EtaPosition_, other.EtaPosition_, other.maxEtaRows_ * sizeof(int));
623   } else
624     EtaPosition_ = NULL;
625   if (other.EtaStarts_) {
626     EtaStarts_ = new int[other.maxEtaRows_];
627     memcpy(EtaStarts_, other.EtaStarts_, other.maxEtaRows_ * sizeof(int));
628   } else
629     EtaStarts_ = NULL;
630   if (other.EtaLengths_) {
631     EtaLengths_ = new int[other.maxEtaRows_];
632     memcpy(EtaLengths_, other.EtaLengths_, other.maxEtaRows_ * sizeof(int));
633   } else
634     EtaLengths_ = NULL;
635   if (other.EtaInd_) {
636     EtaInd_ = new int[other.EtaMaxCap_];
637     memcpy(EtaInd_, other.EtaInd_, other.EtaMaxCap_ * sizeof(int));
638   } else
639     EtaInd_ = NULL;
640   if (other.Eta_) {
641     Eta_ = new double[other.EtaMaxCap_];
642     memcpy(Eta_, other.Eta_, other.EtaMaxCap_ * sizeof(double));
643   } else
644     Eta_ = NULL;
645 
646   doSuhlHeuristic_ = other.doSuhlHeuristic_;
647   maxU_ = other.maxU_;
648   maxGrowth_ = other.maxGrowth_;
649   maxA_ = other.maxA_;
650   pivotCandLimit_ = other.pivotCandLimit_;
651 }
652 
653 //  getAreas.  Gets space for a factorization
654 //called by constructors
getAreas(int numberOfRows,int numberOfColumns,int,int)655 void CoinSimpFactorization::getAreas(int numberOfRows,
656   int numberOfColumns,
657   int,
658   int)
659 {
660 
661   numberRows_ = numberOfRows;
662   numberColumns_ = numberOfColumns;
663   int size = numberRows_ * (numberRows_ + CoinMax(maximumPivots_, (numberRows_ + 1) >> 1));
664   if (size > maximumSpace_) {
665     delete[] elements_;
666     elements_ = new CoinFactorizationDouble[size];
667     maximumSpace_ = size;
668   }
669   if (numberRows_ > maximumRows_) {
670     maximumRows_ = numberRows_;
671     delete[] pivotRow_;
672     delete[] workArea_;
673     pivotRow_ = new int[2 * maximumRows_ + maximumPivots_];
674     workArea_ = new CoinFactorizationDouble[maximumRows_];
675     allocateSomeArrays();
676   }
677 }
678 
679 //  preProcess.
preProcess()680 void CoinSimpFactorization::preProcess()
681 {
682   int put = numberRows_ * numberRows_;
683   int *indexRow = reinterpret_cast< int * >(elements_ + put);
684   int *starts = reinterpret_cast< int * >(pivotRow_);
685   initialSomeNumbers();
686 
687   // compute sizes for Urows_ and Ucolumns_
688   //for ( int row=0; row < numberRows_; ++row )
689   //UrowLengths_[row]=0;
690   int k = 0;
691   for (int column = 0; column < numberColumns_; ++column) {
692     UcolStarts_[column] = k;
693     //for (int j=starts[column];j<starts[column+1];j++) {
694     //  int iRow = indexRow[j];
695     //  ++UrowLengths_[iRow];
696     //	}
697     UcolLengths_[column] = starts[column + 1] - starts[column];
698 #ifdef COIN_SIMP_CAPACITY
699     UcolCapacities_[column] = numberRows_;
700 #endif
701     //k+=UcolLengths_[column]+minIncrease_;
702     k += numberRows_;
703   }
704 
705   // create space for Urows_
706   k = 0;
707   for (int row = 0; row < numberRows_; ++row) {
708     prevRowInU_[row] = row - 1;
709     nextRowInU_[row] = row + 1;
710     UrowStarts_[row] = k;
711     //k+=UrowLengths_[row]+minIncrease_;
712     k += numberRows_;
713     UrowLengths_[row] = 0;
714 #ifdef COIN_SIMP_CAPACITY
715     UrowCapacities_[row] = numberRows_;
716 #endif
717   }
718   UrowEnd_ = k;
719   nextRowInU_[numberRows_ - 1] = -1;
720   firstRowInU_ = 0;
721   lastRowInU_ = numberRows_ - 1;
722   maxA_ = -1.0;
723   // build Ucolumns_ and Urows_
724   int colBeg, colEnd;
725   for (int column = 0; column < numberColumns_; ++column) {
726     prevColInU_[column] = column - 1;
727     nextColInU_[column] = column + 1;
728     k = 0;
729     colBeg = starts[column];
730     colEnd = starts[column + 1];
731     // identify slacks
732     if (colEnd == colBeg + 1 && elements_[colBeg] == slackValue_)
733       colSlack_[column] = 1;
734     else
735       colSlack_[column] = 0;
736     //
737     for (int j = colBeg; j < colEnd; j++) {
738       // Ucolumns_
739       int iRow = indexRow[j];
740       UcolInd_[UcolStarts_[column] + k] = iRow;
741       ++k;
742       // Urow_
743       int ind = UrowStarts_[iRow] + UrowLengths_[iRow];
744       UrowInd_[ind] = column;
745       Urows_[ind] = elements_[j];
746       //maxA_=CoinMax( maxA_, fabs(Urows_[ind]) );
747       ++UrowLengths_[iRow];
748     }
749   }
750   nextColInU_[numberColumns_ - 1] = -1;
751   firstColInU_ = 0;
752   lastColInU_ = numberColumns_ - 1;
753 
754   // Initialize L
755   LcolSize_ = 0;
756   //LcolCap_=numberRows_*minIncrease_;
757   memset(LrowStarts_, -1, numberRows_ * sizeof(int));
758   memset(LrowLengths_, 0, numberRows_ * sizeof(int));
759   memset(LcolStarts_, -1, numberRows_ * sizeof(int));
760   memset(LcolLengths_, 0, numberRows_ * sizeof(int));
761 
762   // initialize permutations
763   for (int i = 0; i < numberRows_; ++i) {
764     rowOfU_[i] = i;
765     rowPosition_[i] = i;
766   }
767   for (int i = 0; i < numberColumns_; ++i) {
768     colOfU_[i] = i;
769     colPosition_[i] = i;
770   }
771   //
772 
773   doSuhlHeuristic_ = true;
774 }
775 
factorize(int numberOfRows,int numberOfColumns,const int colStarts[],const int indicesRow[],const double elements[])776 void CoinSimpFactorization::factorize(int numberOfRows,
777   int numberOfColumns,
778   const int colStarts[],
779   const int indicesRow[],
780   const double elements[])
781 {
782   int maximumL = 0;
783   int maximumU = 0;
784   getAreas(numberOfRows, numberOfColumns, maximumL, maximumU);
785 
786   int put = numberRows_ * numberRows_;
787   int *indexRow = reinterpret_cast< int * >(elements_ + put);
788   int *starts = reinterpret_cast< int * >(pivotRow_);
789   for (int column = 0; column <= numberColumns_; ++column) {
790     starts[column] = colStarts[column];
791   }
792   const int limit = colStarts[numberColumns_];
793   for (int i = 0; i < limit; ++i) {
794     indexRow[i] = indicesRow[i];
795     elements_[i] = elements[i];
796   }
797 
798   preProcess();
799   factor();
800 }
801 
802 //Does factorization
factor()803 int CoinSimpFactorization::factor()
804 {
805   numberPivots_ = 0;
806   status_ = 0;
807 
808   FactorPointers pointers(numberRows_, numberColumns_, UrowLengths_, UcolLengths_);
809   int rc = mainLoopFactor(pointers);
810   // rc=0 success
811   if (rc != 0) { // failure
812     status_ = -1;
813     //return status_; // failure
814   }
815   //if ( rc == -3 ) {  // numerical instability
816   //    status_ = -1;
817   //    return status_;
818   //}
819 
820   //copyLbyRows();
821   copyUbyColumns();
822   copyRowPermutations();
823   firstNumberSlacks_ = numberSlacks_;
824   // row permutations
825   if (status_ == -1 || numberColumns_ < numberRows_) {
826     for (int j = 0; j < numberRows_; j++)
827       pivotRow_[j + numberRows_] = rowOfU_[j];
828     for (int j = 0; j < numberRows_; j++) {
829       int k = pivotRow_[j + numberRows_];
830       pivotRow_[k] = j;
831     }
832   } else // no permutations
833     for (int j = 0; j < numberRows_; j++) {
834       pivotRow_[j] = j;
835       pivotRow_[j + numberRows_] = j;
836     }
837 
838   return status_;
839 }
840 //
841 
842 // Makes a non-singular basis by replacing variables
makeNonSingular(int * sequence,int numberColumns)843 void CoinSimpFactorization::makeNonSingular(int *sequence, int numberColumns)
844 {
845   // Replace bad ones by correct slack
846   int *workArea = reinterpret_cast< int * >(workArea_);
847   int i;
848   for (i = 0; i < numberRows_; i++)
849     workArea[i] = -1;
850   for (i = 0; i < numberGoodU_; i++) {
851     int iOriginal = pivotRow_[i + numberRows_];
852     workArea[iOriginal] = i;
853     //workArea[i]=iOriginal;
854   }
855   int lastRow = -1;
856   for (i = 0; i < numberRows_; i++) {
857     if (workArea[i] == -1) {
858       lastRow = i;
859       break;
860     }
861   }
862   assert(lastRow >= 0);
863   for (i = numberGoodU_; i < numberRows_; i++) {
864     assert(lastRow < numberRows_);
865     // Put slack in basis
866     sequence[i] = lastRow + numberColumns;
867     lastRow++;
868     for (; lastRow < numberRows_; lastRow++) {
869       if (workArea[lastRow] == -1)
870         break;
871     }
872   }
873 }
874 // Does post processing on valid factorization - putting variables on correct rows
postProcess(const int * sequence,int * pivotVariable)875 void CoinSimpFactorization::postProcess(const int *sequence, int *pivotVariable)
876 {
877   for (int i = 0; i < numberRows_; i++) {
878     int k = sequence[i];
879     pivotVariable[pivotRow_[i + numberRows_]] = k;
880   }
881 }
882 /* Replaces one Column to basis,
883    returns 0=OK, 1=Probably OK, 2=singular, 3=no room
884    If checkBeforeModifying is true will do all accuracy checks
885    before modifying factorization.  Whether to set this depends on
886    speed considerations.  You could just do this on first iteration
887    after factorization and thereafter re-factorize
888    partial update already in U */
replaceColumn(CoinIndexedVector *,int pivotRow,double pivotCheck,bool,double)889 int CoinSimpFactorization::replaceColumn(CoinIndexedVector *,
890   int pivotRow,
891   double pivotCheck,
892   bool,
893   double)
894 {
895   if (numberPivots_ == maximumPivots_)
896     return 3;
897 
898   double pivotValue = pivotCheck;
899   if (fabs(pivotValue) < zeroTolerance_)
900     return 2;
901   int realPivotRow = pivotRow_[pivotRow];
902 
903   LUupdate(pivotRow);
904 
905   pivotRow_[2 * numberRows_ + numberPivots_] = realPivotRow;
906   numberPivots_++;
907 
908   return 0;
909 }
updateColumn(CoinIndexedVector * regionSparse,CoinIndexedVector * regionSparse2,bool noPermute) const910 int CoinSimpFactorization::updateColumn(CoinIndexedVector *regionSparse,
911   CoinIndexedVector *regionSparse2,
912   bool noPermute) const
913 {
914   return upColumn(regionSparse, regionSparse2, noPermute, false);
915 }
updateColumnFT(CoinIndexedVector * regionSparse,CoinIndexedVector * regionSparse2,bool noPermute)916 int CoinSimpFactorization::updateColumnFT(CoinIndexedVector *regionSparse,
917   CoinIndexedVector *regionSparse2,
918   bool noPermute)
919 {
920 
921   int rc = upColumn(regionSparse, regionSparse2, noPermute, true);
922   return rc;
923 }
924 
upColumn(CoinIndexedVector * regionSparse,CoinIndexedVector * regionSparse2,bool,bool save) const925 int CoinSimpFactorization::upColumn(CoinIndexedVector *regionSparse,
926   CoinIndexedVector *regionSparse2,
927   bool, bool save) const
928 {
929   assert(numberRows_ == numberColumns_);
930   double *region2 = regionSparse2->denseVector();
931   int *regionIndex = regionSparse2->getIndices();
932   int numberNonZero = regionSparse2->getNumElements();
933   double *region = regionSparse->denseVector();
934   if (!regionSparse2->packedMode()) {
935     region = regionSparse2->denseVector();
936   } else { // packed mode
937     for (int j = 0; j < numberNonZero; j++) {
938       region[regionIndex[j]] = region2[j];
939       region2[j] = 0.0;
940     }
941   }
942 
943   double *solution = workArea2_;
944   ftran(region, solution, save);
945 
946   // get nonzeros
947   numberNonZero = 0;
948   if (!regionSparse2->packedMode()) {
949     for (int i = 0; i < numberRows_; i++) {
950       const double value = solution[i];
951       if (fabs(value) > zeroTolerance_) {
952         region[i] = value;
953         regionIndex[numberNonZero++] = i;
954       } else
955         region[i] = 0.0;
956     }
957   } else { // packed mode
958     memset(region, 0, numberRows_ * sizeof(double));
959     for (int i = 0; i < numberRows_; i++) {
960       const double value = solution[i];
961       if (fabs(value) > zeroTolerance_) {
962         region2[numberNonZero] = value;
963         regionIndex[numberNonZero++] = i;
964       }
965     }
966   }
967   regionSparse2->setNumElements(numberNonZero);
968   return 0;
969 }
970 
updateTwoColumnsFT(CoinIndexedVector * regionSparse1,CoinIndexedVector * regionSparse2,CoinIndexedVector * regionSparse3,bool)971 int CoinSimpFactorization::updateTwoColumnsFT(CoinIndexedVector *regionSparse1,
972   CoinIndexedVector *regionSparse2,
973   CoinIndexedVector *regionSparse3,
974   bool)
975 {
976   assert(numberRows_ == numberColumns_);
977 
978   double *region2 = regionSparse2->denseVector();
979   int *regionIndex2 = regionSparse2->getIndices();
980   int numberNonZero2 = regionSparse2->getNumElements();
981 
982   double *vec1 = regionSparse1->denseVector();
983   if (!regionSparse2->packedMode()) {
984     vec1 = regionSparse2->denseVector();
985   } else { // packed mode
986     for (int j = 0; j < numberNonZero2; j++) {
987       vec1[regionIndex2[j]] = region2[j];
988       region2[j] = 0.0;
989     }
990   }
991   //
992   double *region3 = regionSparse3->denseVector();
993   int *regionIndex3 = regionSparse3->getIndices();
994   int numberNonZero3 = regionSparse3->getNumElements();
995   double *vec2 = auxVector_;
996   if (!regionSparse3->packedMode()) {
997     vec2 = regionSparse3->denseVector();
998   } else { // packed mode
999     memset(vec2, 0, numberRows_ * sizeof(double));
1000     for (int j = 0; j < numberNonZero3; j++) {
1001       vec2[regionIndex3[j]] = region3[j];
1002       region3[j] = 0.0;
1003     }
1004   }
1005 
1006   double *solution1 = workArea2_;
1007   double *solution2 = workArea3_;
1008   ftran2(vec1, solution1, vec2, solution2);
1009 
1010   // get nonzeros
1011   numberNonZero2 = 0;
1012   if (!regionSparse2->packedMode()) {
1013     double value;
1014     for (int i = 0; i < numberRows_; i++) {
1015       value = solution1[i];
1016       if (fabs(value) > zeroTolerance_) {
1017         vec1[i] = value;
1018         regionIndex2[numberNonZero2++] = i;
1019       } else
1020         vec1[i] = 0.0;
1021     }
1022   } else { // packed mode
1023     double value;
1024     for (int i = 0; i < numberRows_; i++) {
1025       vec1[i] = 0.0;
1026       value = solution1[i];
1027       if (fabs(value) > zeroTolerance_) {
1028         region2[numberNonZero2] = value;
1029         regionIndex2[numberNonZero2++] = i;
1030       }
1031     }
1032   }
1033   regionSparse2->setNumElements(numberNonZero2);
1034   //
1035   numberNonZero3 = 0;
1036   if (!regionSparse3->packedMode()) {
1037     double value;
1038     for (int i = 0; i < numberRows_; i++) {
1039       value = solution2[i];
1040       if (fabs(value) > zeroTolerance_) {
1041         vec2[i] = value;
1042         regionIndex3[numberNonZero3++] = i;
1043       } else
1044         vec2[i] = 0.0;
1045     }
1046   } else { // packed mode
1047     double value;
1048     for (int i = 0; i < numberRows_; i++) {
1049       value = solution2[i];
1050       if (fabs(value) > zeroTolerance_) {
1051         region3[numberNonZero3] = value;
1052         regionIndex3[numberNonZero3++] = i;
1053       }
1054     }
1055   }
1056   regionSparse3->setNumElements(numberNonZero3);
1057   return 0;
1058 }
1059 
updateColumnTranspose(CoinIndexedVector * regionSparse,CoinIndexedVector * regionSparse2) const1060 int CoinSimpFactorization::updateColumnTranspose(CoinIndexedVector *regionSparse,
1061   CoinIndexedVector *regionSparse2) const
1062 {
1063   upColumnTranspose(regionSparse, regionSparse2);
1064   return 0;
1065 }
1066 
upColumnTranspose(CoinIndexedVector * regionSparse,CoinIndexedVector * regionSparse2) const1067 int CoinSimpFactorization::upColumnTranspose(CoinIndexedVector *regionSparse,
1068   CoinIndexedVector *regionSparse2) const
1069 {
1070   assert(numberRows_ == numberColumns_);
1071   double *region2 = regionSparse2->denseVector();
1072   int *regionIndex = regionSparse2->getIndices();
1073   int numberNonZero = regionSparse2->getNumElements();
1074   double *region = regionSparse->denseVector();
1075   if (!regionSparse2->packedMode()) {
1076     region = regionSparse2->denseVector();
1077   } else { // packed
1078     for (int j = 0; j < numberNonZero; j++) {
1079       region[regionIndex[j]] = region2[j];
1080       region2[j] = 0.0;
1081     }
1082   }
1083   double *solution = workArea2_;
1084   btran(region, solution);
1085   // get nonzeros
1086   numberNonZero = 0;
1087   if (!regionSparse2->packedMode()) {
1088     double value;
1089     for (int i = 0; i < numberRows_; i++) {
1090       value = solution[i];
1091       if (fabs(value) > zeroTolerance_) {
1092         region[i] = value;
1093         regionIndex[numberNonZero++] = i;
1094       } else
1095         region[i] = 0.0;
1096     }
1097   } else { // packed mode
1098     memset(region, 0, numberRows_ * sizeof(double));
1099     for (int i = 0; i < numberRows_; i++) {
1100       const double value = solution[i];
1101       if (fabs(value) > zeroTolerance_) {
1102         region2[numberNonZero] = value;
1103         regionIndex[numberNonZero++] = i;
1104       }
1105     }
1106   }
1107   regionSparse2->setNumElements(numberNonZero);
1108   return 0;
1109 }
1110 
mainLoopFactor(FactorPointers & pointers)1111 int CoinSimpFactorization::mainLoopFactor(FactorPointers &pointers)
1112 {
1113   numberGoodU_ = 0;
1114   numberSlacks_ = 0;
1115   bool ifSlack = true;
1116   for (int i = 0; i < numberColumns_; ++i) {
1117     int r, s;
1118     //s=i;
1119     if (findPivot(pointers, r, s, ifSlack)) {
1120       return -1;
1121     }
1122     if (ifSlack)
1123       ++numberSlacks_;
1124     const int rowPos = rowPosition_[r];
1125     const int colPos = colPosition_[s];
1126     assert(i <= rowPos && rowPos < numberRows_);
1127     assert(i <= colPos && colPos < numberColumns_);
1128     // permute columns
1129     int j = colOfU_[i];
1130     colOfU_[i] = colOfU_[colPos];
1131     colOfU_[colPos] = j;
1132     colPosition_[colOfU_[i]] = i;
1133     colPosition_[colOfU_[colPos]] = colPos;
1134     // permute rows
1135     j = rowOfU_[i];
1136     rowOfU_[i] = rowOfU_[rowPos];
1137     rowOfU_[rowPos] = j;
1138     rowPosition_[rowOfU_[i]] = i;
1139     rowPosition_[rowOfU_[rowPos]] = rowPos;
1140     GaussEliminate(pointers, r, s);
1141     //if ( maxU_ > maxGrowth_ * maxA_  ){
1142     //  return -3;
1143     //}
1144     ++numberGoodU_;
1145   }
1146   return 0;
1147 }
1148 /// find a pivot in the active part of U
findPivot(FactorPointers & pointers,int & r,int & s,bool & ifSlack)1149 int CoinSimpFactorization::findPivot(FactorPointers &pointers, int &r,
1150   int &s, bool &ifSlack)
1151 {
1152   int *firstRowKnonzeros = pointers.firstRowKnonzeros;
1153   int *nextRow = pointers.nextRow;
1154   int *firstColKnonzeros = pointers.firstColKnonzeros;
1155   int *prevColumn = pointers.prevColumn;
1156   int *nextColumn = pointers.nextColumn;
1157   r = s = -1;
1158   int numCandidates = 0;
1159   double bestMarkowitzCount = COIN_DBL_MAX;
1160   // if there is a column with one element choose it as pivot
1161   int column = firstColKnonzeros[1];
1162   if (column != -1) {
1163     assert(UcolLengths_[column] == 1);
1164     r = UcolInd_[UcolStarts_[column]];
1165     s = column;
1166     if (!colSlack_[column])
1167       ifSlack = false;
1168     return 0;
1169   }
1170   // from now on no more slacks
1171   ifSlack = false;
1172   // if there is a  row with one element choose it
1173   int row = firstRowKnonzeros[1];
1174   if (row != -1) {
1175     assert(UrowLengths_[row] == 1);
1176     s = UrowInd_[UrowStarts_[row]];
1177     r = row;
1178     return 0;
1179   }
1180   // consider other rows and columns
1181   for (int length = 2; length <= numberRows_; ++length) {
1182     int nextCol = -1;
1183     for (column = firstColKnonzeros[length]; column != -1; column = nextCol) {
1184       nextCol = nextColumn[column];
1185       int minRow, minRowLength;
1186       int rc = findShortRow(column, length, minRow, minRowLength, pointers);
1187       if (rc == 0) {
1188         r = minRow;
1189         s = column;
1190         return 0;
1191       }
1192       if (minRow != -1) {
1193         ++numCandidates;
1194         double MarkowitzCount = static_cast< double >(minRowLength - 1) * (length - 1);
1195         if (MarkowitzCount < bestMarkowitzCount) {
1196           r = minRow;
1197           s = column;
1198           bestMarkowitzCount = MarkowitzCount;
1199         }
1200         if (numCandidates == pivotCandLimit_)
1201           return 0;
1202       } else {
1203         if (doSuhlHeuristic_) {
1204           // this column did not give a candidate, it will be
1205           // removed until it becomes a singleton
1206           removeColumnFromActSet(column, pointers);
1207           prevColumn[column] = nextColumn[column] = column;
1208         }
1209       }
1210     } // end for ( column= ....
1211     // now rows
1212     for (row = firstRowKnonzeros[length]; row != -1; row = nextRow[row]) {
1213       int minCol, minColLength;
1214       int rc = findShortColumn(row, length, minCol, minColLength, pointers);
1215       if (rc == 0) {
1216         r = row;
1217         s = minCol;
1218         return 0;
1219       }
1220       if (minCol != -1) {
1221         ++numCandidates;
1222         double MarkowitzCount = static_cast< double >(minColLength - 1) * (length - 1);
1223         if (MarkowitzCount < bestMarkowitzCount) {
1224           r = row;
1225           s = minCol;
1226           bestMarkowitzCount = MarkowitzCount;
1227         }
1228         if (numCandidates == pivotCandLimit_)
1229           return 0;
1230       }
1231       //else abort();
1232     } // end for ( row= ...
1233   } // end for ( int length= ...
1234   if (r == -1 || s == -1)
1235     return 1;
1236   else
1237     return 0;
1238 }
1239 //
findPivotShCol(FactorPointers & pointers,int & r,int & s)1240 int CoinSimpFactorization::findPivotShCol(FactorPointers &pointers, int &r, int &s)
1241 {
1242   int *firstColKnonzeros = pointers.firstColKnonzeros;
1243   r = s = -1;
1244   // if there is a column with one element choose it as pivot
1245   int column = firstColKnonzeros[1];
1246   if (column != -1) {
1247     assert(UcolLengths_[column] == 1);
1248     r = UcolInd_[UcolStarts_[column]];
1249     s = column;
1250     return 0;
1251   }
1252   // consider other columns
1253   for (int length = 2; length <= numberRows_; ++length) {
1254     column = firstColKnonzeros[length];
1255     if (column != -1)
1256       break;
1257   }
1258   if (column == -1)
1259     return 1;
1260   // find largest element
1261   const int colBeg = UcolStarts_[column];
1262   const int colEnd = colBeg + UcolLengths_[column];
1263   double largest = 0.0;
1264   int rowLargest = -1;
1265   for (int j = colBeg; j < colEnd; ++j) {
1266     const int row = UcolInd_[j];
1267     const int columnIndx = findInRow(row, column);
1268     assert(columnIndx != -1);
1269     double coeff = fabs(Urows_[columnIndx]);
1270     if (coeff < largest)
1271       continue;
1272     largest = coeff;
1273     rowLargest = row;
1274   }
1275   assert(rowLargest != -1);
1276   s = column;
1277   r = rowLargest;
1278   return 0;
1279 }
1280 
findPivotSimp(FactorPointers &,int & r,int & s)1281 int CoinSimpFactorization::findPivotSimp(FactorPointers &, int &r, int &s)
1282 {
1283   r = -1;
1284   int column = s;
1285   const int colBeg = UcolStarts_[column];
1286   const int colEnd = colBeg + UcolLengths_[column];
1287   double largest = 0.0;
1288   int rowLargest = -1;
1289   for (int j = colBeg; j < colEnd; ++j) {
1290     const int row = UcolInd_[j];
1291     const int columnIndx = findInRow(row, column);
1292     assert(columnIndx != -1);
1293     double coeff = fabs(Urows_[columnIndx]);
1294     if (coeff < largest)
1295       continue;
1296     largest = coeff;
1297     rowLargest = row;
1298   }
1299   if (rowLargest != -1) {
1300     r = rowLargest;
1301     return 0;
1302   } else
1303     return 1;
1304 }
1305 
findShortRow(const int column,const int length,int & minRow,int & minRowLength,FactorPointers & pointers)1306 int CoinSimpFactorization::findShortRow(const int column,
1307   const int length,
1308   int &minRow,
1309   int &minRowLength,
1310   FactorPointers &pointers)
1311 {
1312   const int colBeg = UcolStarts_[column];
1313   const int colEnd = colBeg + UcolLengths_[column];
1314   minRow = -1;
1315   minRowLength = COIN_INT_MAX;
1316   for (int j = colBeg; j < colEnd; ++j) {
1317     int row = UcolInd_[j];
1318     if (UrowLengths_[row] >= minRowLength)
1319       continue;
1320     double largestInRow = findMaxInRrow(row, pointers);
1321     // find column in row
1322     int columnIndx = findInRow(row, column);
1323     assert(columnIndx != -1);
1324     double coeff = Urows_[columnIndx];
1325     if (fabs(coeff) < pivotTolerance_ * largestInRow)
1326       continue;
1327     minRow = row;
1328     minRowLength = UrowLengths_[row];
1329     if (UrowLengths_[row] <= length)
1330       return 0;
1331   }
1332   return 1;
1333 }
findShortColumn(const int row,const int length,int & minCol,int & minColLength,FactorPointers & pointers)1334 int CoinSimpFactorization::findShortColumn(const int row,
1335   const int length,
1336   int &minCol,
1337   int &minColLength,
1338   FactorPointers &pointers)
1339 {
1340   const int rowBeg = UrowStarts_[row];
1341   const int rowEnd = rowBeg + UrowLengths_[row];
1342   minCol = -1;
1343   minColLength = COIN_INT_MAX;
1344   double largestInRow = findMaxInRrow(row, pointers);
1345   for (int i = rowBeg; i < rowEnd; ++i) {
1346     int column = UrowInd_[i];
1347     if (UcolLengths_[column] >= minColLength)
1348       continue;
1349     double coeff = Urows_[i];
1350     if (fabs(coeff) < pivotTolerance_ * largestInRow)
1351       continue;
1352     minCol = column;
1353     minColLength = UcolLengths_[column];
1354     if (minColLength <= length)
1355       return 0;
1356   }
1357   return 1;
1358 }
1359 // Gaussian elimination
GaussEliminate(FactorPointers & pointers,int & pivotRow,int & pivotCol)1360 void CoinSimpFactorization::GaussEliminate(FactorPointers &pointers, int &pivotRow, int &pivotCol)
1361 {
1362   assert(pivotRow >= 0 && pivotRow < numberRows_);
1363   assert(pivotCol >= 0 && pivotCol < numberRows_);
1364   int *firstColKnonzeros = pointers.firstColKnonzeros;
1365   int *prevColumn = pointers.prevColumn;
1366   int *nextColumn = pointers.nextColumn;
1367   int *colLabels = vecLabels_;
1368   double *denseRow = denseVector_;
1369   removeRowFromActSet(pivotRow, pointers);
1370   removeColumnFromActSet(pivotCol, pointers);
1371   // find column s
1372   int indxColS = findInRow(pivotRow, pivotCol);
1373   assert(indxColS >= 0);
1374   // store the inverse of the pivot and remove it from row
1375   double invPivot = 1.0 / Urows_[indxColS];
1376   invOfPivots_[pivotRow] = invPivot;
1377   int rowBeg = UrowStarts_[pivotRow];
1378   int rowEnd = rowBeg + UrowLengths_[pivotRow];
1379   Urows_[indxColS] = Urows_[rowEnd - 1];
1380   UrowInd_[indxColS] = UrowInd_[rowEnd - 1];
1381   --UrowLengths_[pivotRow];
1382   --rowEnd;
1383   // now remove pivot from column
1384   int indxRowR = findInColumn(pivotCol, pivotRow);
1385   assert(indxRowR >= 0);
1386   const int pivColEnd = UcolStarts_[pivotCol] + UcolLengths_[pivotCol];
1387   UcolInd_[indxRowR] = UcolInd_[pivColEnd - 1];
1388   --UcolLengths_[pivotCol];
1389   // go through pivot row
1390   for (int i = rowBeg; i < rowEnd; ++i) {
1391     int column = UrowInd_[i];
1392     colLabels[column] = 1;
1393     denseRow[column] = Urows_[i];
1394     // remove this column from bucket because it will change
1395     removeColumnFromActSet(column, pointers);
1396     // remove element (pivotRow, column) from column
1397     int indxRow = findInColumn(column, pivotRow);
1398     assert(indxRow >= 0);
1399     const int colEnd = UcolStarts_[column] + UcolLengths_[column];
1400     UcolInd_[indxRow] = UcolInd_[colEnd - 1];
1401     --UcolLengths_[column];
1402   }
1403   //
1404   pivoting(pivotRow, pivotCol, invPivot, pointers);
1405   //
1406   rowBeg = UrowStarts_[pivotRow];
1407   rowEnd = rowBeg + UrowLengths_[pivotRow];
1408   for (int i = rowBeg; i < rowEnd; ++i) {
1409     int column = UrowInd_[i];
1410     // clean back these two arrays
1411     colLabels[column] = 0;
1412     denseRow[column] = 0.0;
1413     // column goes into a bucket, if Suhl' heuristic had removed it, it
1414     // can go back only if it is a singleton
1415     if (UcolLengths_[column] != 1 || prevColumn[column] != column || nextColumn[column] != column) {
1416       prevColumn[column] = -1;
1417       nextColumn[column] = firstColKnonzeros[UcolLengths_[column]];
1418       if (nextColumn[column] != -1)
1419         prevColumn[nextColumn[column]] = column;
1420       firstColKnonzeros[UcolLengths_[column]] = column;
1421     }
1422   }
1423 }
pivoting(const int pivotRow,const int pivotColumn,const double invPivot,FactorPointers & pointers)1424 void CoinSimpFactorization::pivoting(const int pivotRow,
1425   const int pivotColumn,
1426   const double invPivot,
1427   FactorPointers &pointers)
1428 {
1429   // initialize the new column of L
1430   LcolStarts_[pivotRow] = LcolSize_;
1431   // go trough pivot column
1432   const int colBeg = UcolStarts_[pivotColumn];
1433   int colEnd = colBeg + UcolLengths_[pivotColumn];
1434   for (int i = colBeg; i < colEnd; ++i) {
1435     int row = UcolInd_[i];
1436     // remove row from bucket because it will change
1437     removeRowFromActSet(row, pointers);
1438     // find pivot column
1439     int pivotColInRow = findInRow(row, pivotColumn);
1440     assert(pivotColInRow >= 0);
1441     const double multiplier = Urows_[pivotColInRow] * invPivot;
1442     // remove element (row,pivotColumn) from row
1443     const int currentRowEnd = UrowStarts_[row] + UrowLengths_[row];
1444     Urows_[pivotColInRow] = Urows_[currentRowEnd - 1];
1445     UrowInd_[pivotColInRow] = UrowInd_[currentRowEnd - 1];
1446     --UrowLengths_[row];
1447     int newNonZeros = UrowLengths_[pivotRow];
1448     updateCurrentRow(pivotRow, row, multiplier, pointers,
1449       newNonZeros);
1450     // store multiplier
1451     if (LcolSize_ == LcolCap_)
1452       increaseLsize();
1453     Lcolumns_[LcolSize_] = multiplier;
1454     LcolInd_[LcolSize_++] = row;
1455     ++LcolLengths_[pivotRow];
1456   }
1457   // remove elements of pivot column
1458   UcolLengths_[pivotColumn] = 0;
1459   // remove pivot column from Ucol_
1460   if (prevColInU_[pivotColumn] == -1)
1461     firstColInU_ = nextColInU_[pivotColumn];
1462   else {
1463     nextColInU_[prevColInU_[pivotColumn]] = nextColInU_[pivotColumn];
1464 #ifdef COIN_SIMP_CAPACITY
1465     UcolCapacities_[prevColInU_[pivotColumn]] += UcolCapacities_[pivotColumn];
1466     UcolCapacities_[pivotColumn] = 0;
1467 #endif
1468   }
1469   if (nextColInU_[pivotColumn] == -1)
1470     lastColInU_ = prevColInU_[pivotColumn];
1471   else
1472     prevColInU_[nextColInU_[pivotColumn]] = prevColInU_[pivotColumn];
1473 }
1474 
updateCurrentRow(const int pivotRow,const int row,const double multiplier,FactorPointers & pointers,int & newNonZeros)1475 void CoinSimpFactorization::updateCurrentRow(const int pivotRow,
1476   const int row,
1477   const double multiplier,
1478   FactorPointers &pointers,
1479   int &newNonZeros)
1480 {
1481   double *rowMax = pointers.rowMax;
1482   int *firstRowKnonzeros = pointers.firstRowKnonzeros;
1483   int *prevRow = pointers.prevRow;
1484   int *nextRow = pointers.nextRow;
1485   int *colLabels = vecLabels_;
1486   double *denseRow = denseVector_;
1487   const int rowBeg = UrowStarts_[row];
1488   int rowEnd = rowBeg + UrowLengths_[row];
1489   // treat old nonzeros
1490   for (int i = rowBeg; i < rowEnd; ++i) {
1491     const int column = UrowInd_[i];
1492     if (colLabels[column]) {
1493       Urows_[i] -= multiplier * denseRow[column];
1494       const double absNewCoeff = fabs(Urows_[i]);
1495       colLabels[column] = 0;
1496       --newNonZeros;
1497       if (absNewCoeff < zeroTolerance_) {
1498         // remove it from row
1499         UrowInd_[i] = UrowInd_[rowEnd - 1];
1500         Urows_[i] = Urows_[rowEnd - 1];
1501         --UrowLengths_[row];
1502         --i;
1503         --rowEnd;
1504         // remove it from column
1505         int indxRow = findInColumn(column, row);
1506         assert(indxRow >= 0);
1507         const int colEnd = UcolStarts_[column] + UcolLengths_[column];
1508         UcolInd_[indxRow] = UcolInd_[colEnd - 1];
1509         --UcolLengths_[column];
1510       } else {
1511         if (maxU_ < absNewCoeff)
1512           maxU_ = absNewCoeff;
1513       }
1514     }
1515   }
1516   // now add the new nonzeros to the row
1517 #ifdef COIN_SIMP_CAPACITY
1518   if (UrowLengths_[row] + newNonZeros > UrowCapacities_[row])
1519     increaseRowSize(row, UrowLengths_[row] + newNonZeros);
1520 #endif
1521   const int pivotRowBeg = UrowStarts_[pivotRow];
1522   const int pivotRowEnd = pivotRowBeg + UrowLengths_[pivotRow];
1523   int numNew = 0;
1524   int *newCols = pointers.newCols;
1525   for (int i = pivotRowBeg; i < pivotRowEnd; ++i) {
1526     const int column = UrowInd_[i];
1527     if (colLabels[column]) {
1528       const double value = -multiplier * denseRow[column];
1529       const double absNewCoeff = fabs(value);
1530       if (absNewCoeff >= zeroTolerance_) {
1531         const int newInd = UrowStarts_[row] + UrowLengths_[row];
1532         Urows_[newInd] = value;
1533         UrowInd_[newInd] = column;
1534         ++UrowLengths_[row];
1535         newCols[numNew++] = column;
1536         if (maxU_ < absNewCoeff)
1537           maxU_ = absNewCoeff;
1538       }
1539     } else
1540       colLabels[column] = 1;
1541   }
1542   // add the new nonzeros to the columns
1543   for (int i = 0; i < numNew; ++i) {
1544     const int column = newCols[i];
1545 #ifdef COIN_SIMP_CAPACITY
1546     if (UcolLengths_[column] + 1 > UcolCapacities_[column]) {
1547       increaseColSize(column, UcolLengths_[column] + 1, false);
1548     }
1549 #endif
1550     const int newInd = UcolStarts_[column] + UcolLengths_[column];
1551     UcolInd_[newInd] = row;
1552     ++UcolLengths_[column];
1553   }
1554   // the row goes to a new bucket
1555   prevRow[row] = -1;
1556   nextRow[row] = firstRowKnonzeros[UrowLengths_[row]];
1557   if (nextRow[row] != -1)
1558     prevRow[nextRow[row]] = row;
1559   firstRowKnonzeros[UrowLengths_[row]] = row;
1560   //
1561   rowMax[row] = -1.0;
1562 }
1563 #ifdef COIN_SIMP_CAPACITY
1564 
increaseRowSize(const int row,const int newSize)1565 void CoinSimpFactorization::increaseRowSize(const int row,
1566   const int newSize)
1567 {
1568   assert(newSize > UrowCapacities_[row]);
1569   const int newNumElements = newSize + minIncrease_;
1570   if (UrowMaxCap_ < UrowEnd_ + newNumElements) {
1571     enlargeUrow(UrowEnd_ + newNumElements - UrowMaxCap_);
1572   }
1573   int currentCapacity = UrowCapacities_[row];
1574   memcpy(&Urows_[UrowEnd_], &Urows_[UrowStarts_[row]],
1575     UrowLengths_[row] * sizeof(double));
1576   memcpy(&UrowInd_[UrowEnd_], &UrowInd_[UrowStarts_[row]],
1577     UrowLengths_[row] * sizeof(int));
1578   UrowStarts_[row] = UrowEnd_;
1579   UrowCapacities_[row] = newNumElements;
1580   UrowEnd_ += UrowCapacities_[row];
1581   if (firstRowInU_ == lastRowInU_)
1582     return; // only one element
1583   // remove row from list
1584   if (prevRowInU_[row] == -1)
1585     firstRowInU_ = nextRowInU_[row];
1586   else {
1587     nextRowInU_[prevRowInU_[row]] = nextRowInU_[row];
1588     UrowCapacities_[prevRowInU_[row]] += currentCapacity;
1589   }
1590   if (nextRowInU_[row] == -1)
1591     lastRowInU_ = prevRowInU_[row];
1592   else
1593     prevRowInU_[nextRowInU_[row]] = prevRowInU_[row];
1594   // add row at the end of list
1595   nextRowInU_[lastRowInU_] = row;
1596   nextRowInU_[row] = -1;
1597   prevRowInU_[row] = lastRowInU_;
1598   lastRowInU_ = row;
1599 }
1600 #endif
1601 #ifdef COIN_SIMP_CAPACITY
increaseColSize(const int column,const int newSize,const bool ifElements)1602 void CoinSimpFactorization::increaseColSize(const int column,
1603   const int newSize,
1604   const bool ifElements)
1605 {
1606   assert(newSize > UcolCapacities_[column]);
1607   const int newNumElements = newSize + minIncrease_;
1608   if (UcolMaxCap_ < UcolEnd_ + newNumElements) {
1609     enlargeUcol(UcolEnd_ + newNumElements - UcolMaxCap_,
1610       ifElements);
1611   }
1612   int currentCapacity = UcolCapacities_[column];
1613   memcpy(&UcolInd_[UcolEnd_], &UcolInd_[UcolStarts_[column]],
1614     UcolLengths_[column] * sizeof(int));
1615   if (ifElements) {
1616     memcpy(&Ucolumns_[UcolEnd_], &Ucolumns_[UcolStarts_[column]],
1617       UcolLengths_[column] * sizeof(double));
1618   }
1619   UcolStarts_[column] = UcolEnd_;
1620   UcolCapacities_[column] = newNumElements;
1621   UcolEnd_ += UcolCapacities_[column];
1622   if (firstColInU_ == lastColInU_)
1623     return; // only one column
1624   // remove from list
1625   if (prevColInU_[column] == -1)
1626     firstColInU_ = nextColInU_[column];
1627   else {
1628     nextColInU_[prevColInU_[column]] = nextColInU_[column];
1629     UcolCapacities_[prevColInU_[column]] += currentCapacity;
1630   }
1631   if (nextColInU_[column] == -1)
1632     lastColInU_ = prevColInU_[column];
1633   else
1634     prevColInU_[nextColInU_[column]] = prevColInU_[column];
1635   // add column at the end
1636   nextColInU_[lastColInU_] = column;
1637   nextColInU_[column] = -1;
1638   prevColInU_[column] = lastColInU_;
1639   lastColInU_ = column;
1640 }
1641 #endif
findMaxInRrow(const int row,FactorPointers & pointers)1642 double CoinSimpFactorization::findMaxInRrow(const int row,
1643   FactorPointers &pointers)
1644 {
1645   double *rowMax = pointers.rowMax;
1646   double largest = rowMax[row];
1647   if (largest >= 0.0)
1648     return largest;
1649   const int rowBeg = UrowStarts_[row];
1650   const int rowEnd = rowBeg + UrowLengths_[row];
1651   for (int i = rowBeg; i < rowEnd; ++i) {
1652     const double absValue = fabs(Urows_[i]);
1653     if (absValue > largest)
1654       largest = absValue;
1655   }
1656   rowMax[row] = largest;
1657   return largest;
1658 }
increaseLsize()1659 void CoinSimpFactorization::increaseLsize()
1660 {
1661   int newcap = LcolCap_ + minIncrease_;
1662 
1663   double *aux = new double[newcap];
1664   memcpy(aux, Lcolumns_, LcolCap_ * sizeof(double));
1665   delete[] Lcolumns_;
1666   Lcolumns_ = aux;
1667 
1668   int *iaux = new int[newcap];
1669   memcpy(iaux, LcolInd_, LcolCap_ * sizeof(int));
1670   delete[] LcolInd_;
1671   LcolInd_ = iaux;
1672 
1673   LcolCap_ = newcap;
1674 }
enlargeUcol(const int numNewElements,const bool ifElements)1675 void CoinSimpFactorization::enlargeUcol(const int numNewElements, const bool ifElements)
1676 {
1677   int *iaux = new int[UcolMaxCap_ + numNewElements];
1678   memcpy(iaux, UcolInd_, UcolMaxCap_ * sizeof(int));
1679   delete[] UcolInd_;
1680   UcolInd_ = iaux;
1681 
1682   if (ifElements) {
1683     double *aux = new double[UcolMaxCap_ + numNewElements];
1684     memcpy(aux, Ucolumns_, UcolMaxCap_ * sizeof(double));
1685     delete[] Ucolumns_;
1686     Ucolumns_ = aux;
1687   }
1688 
1689   UcolMaxCap_ += numNewElements;
1690 }
enlargeUrow(const int numNewElements)1691 void CoinSimpFactorization::enlargeUrow(const int numNewElements)
1692 {
1693   int *iaux = new int[UrowMaxCap_ + numNewElements];
1694   memcpy(iaux, UrowInd_, UrowMaxCap_ * sizeof(int));
1695   delete[] UrowInd_;
1696   UrowInd_ = iaux;
1697 
1698   double *aux = new double[UrowMaxCap_ + numNewElements];
1699   memcpy(aux, Urows_, UrowMaxCap_ * sizeof(double));
1700   delete[] Urows_;
1701   Urows_ = aux;
1702 
1703   UrowMaxCap_ += numNewElements;
1704 }
1705 
copyUbyColumns()1706 void CoinSimpFactorization::copyUbyColumns()
1707 {
1708   memset(UcolLengths_, 0, numberColumns_ * sizeof(int));
1709   for (int column = 0; column < numberColumns_; ++column) {
1710     prevColInU_[column] = column - 1;
1711     nextColInU_[column] = column + 1;
1712   }
1713   nextColInU_[numberColumns_ - 1] = -1;
1714   firstColInU_ = 0;
1715   lastColInU_ = numberColumns_ - 1;
1716   //int nonZeros=0;
1717   //for ( int row=0; row<numberRows_; ++row ){
1718   //const int rowBeg=UrowStarts_[row];
1719   //const int rowEnd=rowBeg+UrowLengths_[row];
1720   //for ( int j=rowBeg; j<rowEnd; ++j )
1721   //   ++UcolCapacities_[UrowInd_[j]];
1722   //	nonZeros+=UrowLengths_[row];
1723   //   }
1724   //
1725   //memset(UcolCapacities_, numberRows_, numberColumns_ * sizeof(int));
1726 #ifdef COIN_SIMP_CAPACITY
1727   for (int i = 0; i < numberColumns_; ++i)
1728     UcolCapacities_[i] = numberRows_;
1729 #endif
1730   int k = 0;
1731   for (int column = 0; column < numberColumns_; ++column) {
1732     UcolStarts_[column] = k;
1733     //UcolCapacities_[column]+=minIncrease_;
1734     //k+=UcolCapacities_[column];
1735     k += numberRows_;
1736   }
1737   UcolEnd_ = k;
1738   // go through the rows and fill the columns, assume UcolLengths_[]=0
1739   for (int row = 0; row < numberRows_; ++row) {
1740     const int rowBeg = UrowStarts_[row];
1741     int rowEnd = rowBeg + UrowLengths_[row];
1742     for (int j = rowBeg; j < rowEnd; ++j) {
1743       // remove els close to zero
1744       while (fabs(Urows_[j]) < zeroTolerance_) {
1745         --UrowLengths_[row];
1746         --rowEnd;
1747         if (j < rowEnd) {
1748           Urows_[j] = Urows_[rowEnd];
1749           UrowInd_[j] = UrowInd_[rowEnd];
1750         } else
1751           break;
1752       }
1753       if (j == rowEnd)
1754         continue;
1755       //
1756       const int column = UrowInd_[j];
1757       const int indx = UcolStarts_[column] + UcolLengths_[column];
1758       Ucolumns_[indx] = Urows_[j];
1759       UcolInd_[indx] = row;
1760       ++UcolLengths_[column];
1761     }
1762   }
1763 }
copyLbyRows()1764 void CoinSimpFactorization::copyLbyRows()
1765 {
1766   int nonZeros = 0;
1767   memset(LrowLengths_, 0, numberRows_ * sizeof(int));
1768   for (int column = 0; column < numberRows_; ++column) {
1769     const int colBeg = LcolStarts_[column];
1770     const int colEnd = colBeg + LcolLengths_[column];
1771     for (int j = colBeg; j < colEnd; ++j)
1772       ++LrowLengths_[LcolInd_[j]];
1773     nonZeros += LcolLengths_[column];
1774   }
1775   //
1776   LrowSize_ = nonZeros;
1777   int k = 0;
1778   for (int row = 0; row < numberRows_; ++row) {
1779     LrowStarts_[row] = k;
1780     k += LrowLengths_[row];
1781   }
1782 #ifdef COIN_SIMP_CAPACITY
1783   //memset(LrowLengths_,0,numberRows_*sizeof(int));
1784   // fill the rows
1785   for (int column = 0; column < numberRows_; ++column) {
1786     const int colBeg = LcolStarts_[column];
1787     const int colEnd = colBeg + LcolLengths_[column];
1788     for (int j = colBeg; j < colEnd; ++j) {
1789       const int row = LcolInd_[j];
1790       const int indx = LrowStarts_[row]++;
1791       Lrows_[indx] = Lcolumns_[j];
1792       LrowInd_[indx] = column;
1793     }
1794   }
1795   // Put back starts
1796   k = 0;
1797   for (int row = 0; row < numberRows_; ++row) {
1798     int next = LrowStarts_[row];
1799     LrowStarts_[row] = k;
1800     k = next;
1801   }
1802 #else
1803   memset(LrowLengths_, 0, numberRows_ * sizeof(int));
1804   // fill the rows
1805   for (int column = 0; column < numberRows_; ++column) {
1806     const int colBeg = LcolStarts_[column];
1807     const int colEnd = colBeg + LcolLengths_[column];
1808     for (int j = colBeg; j < colEnd; ++j) {
1809       const int row = LcolInd_[j];
1810       const int indx = LrowStarts_[row] + LrowLengths_[row];
1811       Lrows_[indx] = Lcolumns_[j];
1812       LrowInd_[indx] = column;
1813       ++LrowLengths_[row];
1814     }
1815   }
1816 #endif
1817 }
1818 
findInRow(const int row,const int column)1819 int CoinSimpFactorization::findInRow(const int row,
1820   const int column)
1821 {
1822   const int rowBeg = UrowStarts_[row];
1823   const int rowEnd = rowBeg + UrowLengths_[row];
1824   int columnIndx = -1;
1825   for (int i = rowBeg; i < rowEnd; ++i) {
1826     if (UrowInd_[i] == column) {
1827       columnIndx = i;
1828       break;
1829     }
1830   }
1831   return columnIndx;
1832 }
findInColumn(const int column,const int row)1833 int CoinSimpFactorization::findInColumn(const int column,
1834   const int row)
1835 {
1836   int indxRow = -1;
1837   const int colBeg = UcolStarts_[column];
1838   const int colEnd = colBeg + UcolLengths_[column];
1839   for (int i = colBeg; i < colEnd; ++i) {
1840     if (UcolInd_[i] == row) {
1841       indxRow = i;
1842       break;
1843     }
1844   }
1845   return indxRow;
1846 }
removeRowFromActSet(const int row,FactorPointers & pointers)1847 void CoinSimpFactorization::removeRowFromActSet(const int row,
1848   FactorPointers &pointers)
1849 {
1850   int *firstRowKnonzeros = pointers.firstRowKnonzeros;
1851   int *prevRow = pointers.prevRow;
1852   int *nextRow = pointers.nextRow;
1853   if (prevRow[row] == -1)
1854     firstRowKnonzeros[UrowLengths_[row]] = nextRow[row];
1855   else
1856     nextRow[prevRow[row]] = nextRow[row];
1857   if (nextRow[row] != -1)
1858     prevRow[nextRow[row]] = prevRow[row];
1859 }
removeColumnFromActSet(const int column,FactorPointers & pointers)1860 void CoinSimpFactorization::removeColumnFromActSet(const int column,
1861   FactorPointers &pointers)
1862 {
1863   int *firstColKnonzeros = pointers.firstColKnonzeros;
1864   int *prevColumn = pointers.prevColumn;
1865   int *nextColumn = pointers.nextColumn;
1866   if (prevColumn[column] == -1)
1867     firstColKnonzeros[UcolLengths_[column]] = nextColumn[column];
1868   else
1869     nextColumn[prevColumn[column]] = nextColumn[column];
1870   if (nextColumn[column] != -1)
1871     prevColumn[nextColumn[column]] = prevColumn[column];
1872 }
allocateSomeArrays()1873 void CoinSimpFactorization::allocateSomeArrays()
1874 {
1875   if (denseVector_)
1876     delete[] denseVector_;
1877   denseVector_ = new double[numberRows_];
1878   memset(denseVector_, 0, numberRows_ * sizeof(double));
1879   if (workArea2_)
1880     delete[] workArea2_;
1881   workArea2_ = new double[numberRows_];
1882   if (workArea3_)
1883     delete[] workArea3_;
1884   workArea3_ = new double[numberRows_];
1885 
1886   if (vecLabels_)
1887     delete[] vecLabels_;
1888   vecLabels_ = new int[numberRows_];
1889   memset(vecLabels_, 0, numberRows_ * sizeof(int));
1890   if (indVector_)
1891     delete[] indVector_;
1892   indVector_ = new int[numberRows_];
1893 
1894   if (auxVector_)
1895     delete[] auxVector_;
1896   auxVector_ = new double[numberRows_];
1897   if (auxInd_)
1898     delete[] auxInd_;
1899   auxInd_ = new int[numberRows_];
1900 
1901   if (vecKeep_)
1902     delete[] vecKeep_;
1903   vecKeep_ = new double[numberRows_];
1904   if (indKeep_)
1905     delete[] indKeep_;
1906   indKeep_ = new int[numberRows_];
1907 
1908   if (LrowStarts_)
1909     delete[] LrowStarts_;
1910   LrowStarts_ = new int[numberRows_];
1911   if (LrowLengths_)
1912     delete[] LrowLengths_;
1913   LrowLengths_ = new int[numberRows_];
1914 
1915   LrowCap_ = (numberRows_ * (numberRows_ - 1)) / 2;
1916   if (Lrows_)
1917     delete[] Lrows_;
1918   Lrows_ = new double[LrowCap_];
1919   if (LrowInd_)
1920     delete[] LrowInd_;
1921   LrowInd_ = new int[LrowCap_];
1922 
1923   if (LcolStarts_)
1924     delete[] LcolStarts_;
1925   LcolStarts_ = new int[numberRows_];
1926   if (LcolLengths_)
1927     delete[] LcolLengths_;
1928   LcolLengths_ = new int[numberRows_];
1929   LcolCap_ = LrowCap_;
1930   if (Lcolumns_)
1931     delete[] Lcolumns_;
1932   Lcolumns_ = new double[LcolCap_];
1933   if (LcolInd_)
1934     delete[] LcolInd_;
1935   LcolInd_ = new int[LcolCap_];
1936 
1937   if (UrowStarts_)
1938     delete[] UrowStarts_;
1939   UrowStarts_ = new int[numberRows_];
1940   if (UrowLengths_)
1941     delete[] UrowLengths_;
1942   UrowLengths_ = new int[numberRows_];
1943 #ifdef COIN_SIMP_CAPACITY
1944   if (UrowCapacities_)
1945     delete[] UrowCapacities_;
1946   UrowCapacities_ = new int[numberRows_];
1947 #endif
1948 
1949   minIncrease_ = 10;
1950   UrowMaxCap_ = numberRows_ * (numberRows_ + minIncrease_);
1951   if (Urows_)
1952     delete[] Urows_;
1953   Urows_ = new double[UrowMaxCap_];
1954   if (UrowInd_)
1955     delete[] UrowInd_;
1956   UrowInd_ = new int[UrowMaxCap_];
1957 
1958   if (prevRowInU_)
1959     delete[] prevRowInU_;
1960   prevRowInU_ = new int[numberRows_];
1961   if (nextRowInU_)
1962     delete[] nextRowInU_;
1963   nextRowInU_ = new int[numberRows_];
1964 
1965   if (UcolStarts_)
1966     delete[] UcolStarts_;
1967   UcolStarts_ = new int[numberRows_];
1968   if (UcolLengths_)
1969     delete[] UcolLengths_;
1970   UcolLengths_ = new int[numberRows_];
1971 #ifdef COIN_SIMP_CAPACITY
1972   if (UcolCapacities_)
1973     delete[] UcolCapacities_;
1974   UcolCapacities_ = new int[numberRows_];
1975 #endif
1976 
1977   UcolMaxCap_ = UrowMaxCap_;
1978   if (Ucolumns_)
1979     delete[] Ucolumns_;
1980   Ucolumns_ = new double[UcolMaxCap_];
1981   if (UcolInd_)
1982     delete[] UcolInd_;
1983   UcolInd_ = new int[UcolMaxCap_];
1984 
1985   if (prevColInU_)
1986     delete[] prevColInU_;
1987   prevColInU_ = new int[numberRows_];
1988   if (nextColInU_)
1989     delete[] nextColInU_;
1990   nextColInU_ = new int[numberRows_];
1991   if (colSlack_)
1992     delete[] colSlack_;
1993   colSlack_ = new int[numberRows_];
1994 
1995   if (invOfPivots_)
1996     delete[] invOfPivots_;
1997   invOfPivots_ = new double[numberRows_];
1998 
1999   if (colOfU_)
2000     delete[] colOfU_;
2001   colOfU_ = new int[numberRows_];
2002   if (colPosition_)
2003     delete[] colPosition_;
2004   colPosition_ = new int[numberRows_];
2005   if (rowOfU_)
2006     delete[] rowOfU_;
2007   rowOfU_ = new int[numberRows_];
2008   if (rowPosition_)
2009     delete[] rowPosition_;
2010   rowPosition_ = new int[numberRows_];
2011   if (secRowOfU_)
2012     delete[] secRowOfU_;
2013   secRowOfU_ = new int[numberRows_];
2014   if (secRowPosition_)
2015     delete[] secRowPosition_;
2016   secRowPosition_ = new int[numberRows_];
2017 
2018   if (EtaPosition_)
2019     delete[] EtaPosition_;
2020   EtaPosition_ = new int[maximumPivots_];
2021   if (EtaStarts_)
2022     delete[] EtaStarts_;
2023   EtaStarts_ = new int[maximumPivots_];
2024   if (EtaLengths_)
2025     delete[] EtaLengths_;
2026   EtaLengths_ = new int[maximumPivots_];
2027   maxEtaRows_ = maximumPivots_;
2028 
2029   EtaMaxCap_ = maximumPivots_ * minIncrease_;
2030   if (EtaInd_)
2031     delete[] EtaInd_;
2032   EtaInd_ = new int[EtaMaxCap_];
2033   if (Eta_)
2034     delete[] Eta_;
2035   Eta_ = new double[EtaMaxCap_];
2036 }
2037 
Lxeqb(double * b) const2038 void CoinSimpFactorization::Lxeqb(double *b) const
2039 {
2040   double *rhs = b;
2041   int k, colBeg, *ind, *indEnd;
2042   double xk, *Lcol;
2043   // now solve
2044   for (int j = firstNumberSlacks_; j < numberRows_; ++j) {
2045     k = rowOfU_[j];
2046     xk = rhs[k];
2047     if (xk != 0.0) {
2048       //if ( fabs(xk)>zeroTolerance_ ) {
2049       colBeg = LcolStarts_[k];
2050       ind = LcolInd_ + colBeg;
2051       indEnd = ind + LcolLengths_[k];
2052       Lcol = Lcolumns_ + colBeg;
2053       for (; ind != indEnd; ++ind) {
2054         rhs[*ind] -= (*Lcol) * xk;
2055         ++Lcol;
2056       }
2057     }
2058   }
2059 }
2060 
Lxeqb2(double * b1,double * b2) const2061 void CoinSimpFactorization::Lxeqb2(double *b1, double *b2) const
2062 {
2063   double *rhs1 = b1;
2064   double *rhs2 = b2;
2065   double x1, x2, *Lcol;
2066   int k, colBeg, *ind, *indEnd, j;
2067   // now solve
2068   for (j = firstNumberSlacks_; j < numberRows_; ++j) {
2069     k = rowOfU_[j];
2070     x1 = rhs1[k];
2071     x2 = rhs2[k];
2072     if (x1 == 0.0) {
2073       if (x2 == 0.0) {
2074       } else {
2075         colBeg = LcolStarts_[k];
2076         ind = LcolInd_ + colBeg;
2077         indEnd = ind + LcolLengths_[k];
2078         Lcol = Lcolumns_ + colBeg;
2079         for (; ind != indEnd; ++ind) {
2080 #if 0
2081 		    rhs2[ *ind ]-= (*Lcol) * x2;
2082 #else
2083           double value = rhs2[*ind];
2084           rhs2[*ind] = value - (*Lcol) * x2;
2085 #endif
2086           ++Lcol;
2087         }
2088       }
2089     } else {
2090       if (x2 == 0.0) {
2091         colBeg = LcolStarts_[k];
2092         ind = LcolInd_ + colBeg;
2093         indEnd = ind + LcolLengths_[k];
2094         Lcol = Lcolumns_ + colBeg;
2095         for (; ind != indEnd; ++ind) {
2096 #if 0
2097 		    rhs1[ *ind ]-= (*Lcol) * x1;
2098 #else
2099           double value = rhs1[*ind];
2100           rhs1[*ind] = value - (*Lcol) * x1;
2101 #endif
2102           ++Lcol;
2103         }
2104       } else {
2105         colBeg = LcolStarts_[k];
2106         ind = LcolInd_ + colBeg;
2107         indEnd = ind + LcolLengths_[k];
2108         Lcol = Lcolumns_ + colBeg;
2109         for (; ind != indEnd; ++ind) {
2110 #if 0
2111 		    rhs1[ *ind ]-= (*Lcol) * x1;
2112 		    rhs2[ *ind ]-= (*Lcol) * x2;
2113 #else
2114           double value1 = rhs1[*ind];
2115           rhs1[*ind] = value1 - (*Lcol) * x1;
2116           double value2 = rhs2[*ind];
2117           rhs2[*ind] = value2 - (*Lcol) * x2;
2118 #endif
2119           ++Lcol;
2120         }
2121       }
2122     }
2123   }
2124 }
2125 
Uxeqb(double * b,double * sol) const2126 void CoinSimpFactorization::Uxeqb(double *b, double *sol) const
2127 {
2128   double *rhs = b;
2129   int row, column, colBeg, *ind, *indEnd, k;
2130   double x, *uCol;
2131   // now solve
2132   for (k = numberRows_ - 1; k >= numberSlacks_; --k) {
2133     row = secRowOfU_[k];
2134     x = rhs[row];
2135     column = colOfU_[k];
2136     if (x != 0.0) {
2137       //if ( fabs(x) > zeroTolerance_ ) {
2138       x *= invOfPivots_[row];
2139       colBeg = UcolStarts_[column];
2140       ind = UcolInd_ + colBeg;
2141       indEnd = ind + UcolLengths_[column];
2142       uCol = Ucolumns_ + colBeg;
2143       for (; ind != indEnd; ++ind) {
2144 #if 0
2145 		rhs[ *ind ]-= (*uCol) * x;
2146 #else
2147         double value = rhs[*ind];
2148         rhs[*ind] = value - (*uCol) * x;
2149 #endif
2150         ++uCol;
2151       }
2152       sol[column] = x;
2153     } else
2154       sol[column] = 0.0;
2155   }
2156   for (k = numberSlacks_ - 1; k >= 0; --k) {
2157     row = secRowOfU_[k];
2158     column = colOfU_[k];
2159     sol[column] = -rhs[row];
2160   }
2161 }
2162 
Uxeqb2(double * b1,double * sol1,double * b2,double * sol2) const2163 void CoinSimpFactorization::Uxeqb2(double *b1, double *sol1, double *b2, double *sol2) const
2164 {
2165   double *rhs1 = b1;
2166   double *rhs2 = b2;
2167   int row, column, colBeg, *ind, *indEnd;
2168   double x1, x2, *uCol;
2169   // now solve
2170   for (int k = numberRows_ - 1; k >= numberSlacks_; --k) {
2171     row = secRowOfU_[k];
2172     x1 = rhs1[row];
2173     x2 = rhs2[row];
2174     column = colOfU_[k];
2175     if (x1 == 0.0) {
2176       if (x2 == 0.0) {
2177         sol1[column] = 0.0;
2178         sol2[column] = 0.0;
2179       } else {
2180         x2 *= invOfPivots_[row];
2181         colBeg = UcolStarts_[column];
2182         ind = UcolInd_ + colBeg;
2183         indEnd = ind + UcolLengths_[column];
2184         uCol = Ucolumns_ + colBeg;
2185         for (; ind != indEnd; ++ind) {
2186 #if 0
2187 		    rhs2[ *ind ]-= (*uCol) * x2;
2188 #else
2189           double value = rhs2[*ind];
2190           rhs2[*ind] = value - (*uCol) * x2;
2191 #endif
2192           ++uCol;
2193         }
2194         sol1[column] = 0.0;
2195         sol2[column] = x2;
2196       }
2197     } else {
2198       if (x2 == 0.0) {
2199         x1 *= invOfPivots_[row];
2200         colBeg = UcolStarts_[column];
2201         ind = UcolInd_ + colBeg;
2202         indEnd = ind + UcolLengths_[column];
2203         uCol = Ucolumns_ + colBeg;
2204         for (; ind != indEnd; ++ind) {
2205 #if 0
2206 		    rhs1[ *ind ]-= (*uCol) * x1;
2207 #else
2208           double value = rhs1[*ind];
2209           rhs1[*ind] = value - (*uCol) * x1;
2210 #endif
2211           ++uCol;
2212         }
2213         sol1[column] = x1;
2214         sol2[column] = 0.0;
2215       } else {
2216         x1 *= invOfPivots_[row];
2217         x2 *= invOfPivots_[row];
2218         colBeg = UcolStarts_[column];
2219         ind = UcolInd_ + colBeg;
2220         indEnd = ind + UcolLengths_[column];
2221         uCol = Ucolumns_ + colBeg;
2222         for (; ind != indEnd; ++ind) {
2223 #if 0
2224 		    rhs1[ *ind ]-= (*uCol) * x1;
2225 		    rhs2[ *ind ]-= (*uCol) * x2;
2226 #else
2227           double value1 = rhs1[*ind];
2228           rhs1[*ind] = value1 - (*uCol) * x1;
2229           double value2 = rhs2[*ind];
2230           rhs2[*ind] = value2 - (*uCol) * x2;
2231 #endif
2232           ++uCol;
2233         }
2234         sol1[column] = x1;
2235         sol2[column] = x2;
2236       }
2237     }
2238   }
2239   for (int k = numberSlacks_ - 1; k >= 0; --k) {
2240     row = secRowOfU_[k];
2241     column = colOfU_[k];
2242     sol1[column] = -rhs1[row];
2243     sol2[column] = -rhs2[row];
2244   }
2245 }
2246 
xLeqb(double * b) const2247 void CoinSimpFactorization::xLeqb(double *b) const
2248 {
2249   double *rhs = b;
2250   int k, *ind, *indEnd, j;
2251   int colBeg;
2252   double x, *Lcol;
2253   // find last nonzero
2254   int last;
2255   for (last = numberColumns_ - 1; last >= 0; --last) {
2256     if (rhs[rowOfU_[last]])
2257       break;
2258   }
2259   // this seems to be faster
2260   if (last >= 0) {
2261     for (j = last; j >= firstNumberSlacks_; --j) {
2262       k = rowOfU_[j];
2263       x = rhs[k];
2264       colBeg = LcolStarts_[k];
2265       ind = LcolInd_ + colBeg;
2266       indEnd = ind + LcolLengths_[k];
2267       Lcol = Lcolumns_ + colBeg;
2268       for (; ind != indEnd; ++ind) {
2269         x -= (*Lcol) * rhs[*ind];
2270         ++Lcol;
2271       }
2272       rhs[k] = x;
2273     }
2274   } // if ( last >= 0 ){
2275 }
2276 
xUeqb(double * b,double * sol) const2277 void CoinSimpFactorization::xUeqb(double *b, double *sol) const
2278 {
2279   double *rhs = b;
2280   int row, col, *ind, *indEnd, k;
2281   double xr;
2282   // now solve
2283 #if 1
2284   int rowBeg;
2285   double *uRow;
2286   for (k = 0; k < numberSlacks_; ++k) {
2287     row = secRowOfU_[k];
2288     col = colOfU_[k];
2289     xr = rhs[col];
2290     if (xr != 0.0) {
2291       //if ( fabs(xr)> zeroTolerance_ ) {
2292       xr = -xr;
2293       rowBeg = UrowStarts_[row];
2294       ind = UrowInd_ + rowBeg;
2295       indEnd = ind + UrowLengths_[row];
2296       uRow = Urows_ + rowBeg;
2297       for (; ind != indEnd; ++ind) {
2298         rhs[*ind] -= (*uRow) * xr;
2299         ++uRow;
2300       }
2301       sol[row] = xr;
2302     } else
2303       sol[row] = 0.0;
2304   }
2305   for (k = numberSlacks_; k < numberRows_; ++k) {
2306     row = secRowOfU_[k];
2307     col = colOfU_[k];
2308     xr = rhs[col];
2309     if (xr != 0.0) {
2310       //if ( fabs(xr)> zeroTolerance_ ) {
2311       xr *= invOfPivots_[row];
2312       rowBeg = UrowStarts_[row];
2313       ind = UrowInd_ + rowBeg;
2314       indEnd = ind + UrowLengths_[row];
2315       uRow = Urows_ + rowBeg;
2316       for (; ind != indEnd; ++ind) {
2317         rhs[*ind] -= (*uRow) * xr;
2318         ++uRow;
2319       }
2320       sol[row] = xr;
2321     } else
2322       sol[row] = 0.0;
2323   }
2324 #else
2325   for (k = 0; k < numberSlacks_; ++k) {
2326     row = secRowOfU_[k];
2327     col = colOfU_[k];
2328     sol[row] = -rhs[col];
2329   }
2330   for (k = numberSlacks_; k < numberRows_; ++k) {
2331     row = secRowOfU_[k];
2332     col = colOfU_[k];
2333     xr = rhs[col];
2334     int colBeg = UcolStarts_[col];
2335     ind = UcolInd_ + colBeg;
2336     indEnd = ind + UcolLengths_[col];
2337     double *uCol = Ucolumns_ + colBeg;
2338     for (; ind != indEnd; ++ind, ++uCol) {
2339       int iRow = *ind;
2340       double value = sol[iRow];
2341       double elementValue = *uCol;
2342       xr -= value * elementValue;
2343     }
2344     if (xr != 0.0) {
2345       xr *= invOfPivots_[row];
2346       sol[row] = xr;
2347     } else
2348       sol[row] = 0.0;
2349   }
2350 #endif
2351 }
2352 
LUupdate(int newBasicCol)2353 int CoinSimpFactorization::LUupdate(int newBasicCol)
2354 {
2355   //checkU();
2356   // recover vector kept in ftran
2357   double *newColumn = vecKeep_;
2358   int *indNewColumn = indKeep_;
2359   int sizeNewColumn = keepSize_;
2360 
2361   // remove elements of new column of U
2362   const int colBeg = UcolStarts_[newBasicCol];
2363   const int colEnd = colBeg + UcolLengths_[newBasicCol];
2364   for (int i = colBeg; i < colEnd; ++i) {
2365     const int row = UcolInd_[i];
2366     const int colInRow = findInRow(row, newBasicCol);
2367     assert(colInRow >= 0);
2368     // remove from row
2369     const int rowEnd = UrowStarts_[row] + UrowLengths_[row];
2370     Urows_[colInRow] = Urows_[rowEnd - 1];
2371     UrowInd_[colInRow] = UrowInd_[rowEnd - 1];
2372     --UrowLengths_[row];
2373   }
2374   UcolLengths_[newBasicCol] = 0;
2375   // now add new column to U
2376   int lastRowInU = -1;
2377   for (int i = 0; i < sizeNewColumn; ++i) {
2378     //if ( fabs(newColumn[i]) < zeroTolerance_ ) continue;
2379     const int row = indNewColumn[i];
2380     // add to row
2381 #ifdef COIN_SIMP_CAPACITY
2382     if (UrowLengths_[row] + 1 > UrowCapacities_[row])
2383       increaseRowSize(row, UrowLengths_[row] + 1);
2384 #endif
2385     const int rowEnd = UrowStarts_[row] + UrowLengths_[row];
2386     UrowInd_[rowEnd] = newBasicCol;
2387     Urows_[rowEnd] = newColumn[i];
2388     ++UrowLengths_[row];
2389     if (lastRowInU < secRowPosition_[row])
2390       lastRowInU = secRowPosition_[row];
2391   }
2392   // add to Ucolumns
2393 #ifdef COIN_SIMP_CAPACITY
2394   if (sizeNewColumn > UcolCapacities_[newBasicCol])
2395     increaseColSize(newBasicCol, sizeNewColumn, true);
2396 #endif
2397   memcpy(&Ucolumns_[UcolStarts_[newBasicCol]], &newColumn[0],
2398     sizeNewColumn * sizeof(double));
2399   memcpy(&UcolInd_[UcolStarts_[newBasicCol]], &indNewColumn[0],
2400     sizeNewColumn * sizeof(int));
2401   UcolLengths_[newBasicCol] = sizeNewColumn;
2402 
2403   const int posNewCol = colPosition_[newBasicCol];
2404   if (lastRowInU < posNewCol) {
2405     // matrix is singular
2406     return 1;
2407   }
2408   // permutations
2409   const int rowInU = secRowOfU_[posNewCol];
2410   const int colInU = colOfU_[posNewCol];
2411   for (int i = posNewCol; i < lastRowInU; ++i) {
2412     int indx = secRowOfU_[i + 1];
2413     secRowOfU_[i] = indx;
2414     secRowPosition_[indx] = i;
2415     int jndx = colOfU_[i + 1];
2416     colOfU_[i] = jndx;
2417     colPosition_[jndx] = i;
2418   }
2419   secRowOfU_[lastRowInU] = rowInU;
2420   secRowPosition_[rowInU] = lastRowInU;
2421   colOfU_[lastRowInU] = colInU;
2422   colPosition_[colInU] = lastRowInU;
2423   if (posNewCol < numberSlacks_) {
2424     if (lastRowInU >= numberSlacks_)
2425       --numberSlacks_;
2426     else
2427       numberSlacks_ = lastRowInU;
2428   }
2429   // rowInU will be transformed
2430   // denseVector_ is assumed to be initialized to zero
2431   const int rowBeg = UrowStarts_[rowInU];
2432   const int rowEnd = rowBeg + UrowLengths_[rowInU];
2433   for (int i = rowBeg; i < rowEnd; ++i) {
2434     const int column = UrowInd_[i];
2435     denseVector_[column] = Urows_[i];
2436     // remove element
2437     const int indxRow = findInColumn(column, rowInU);
2438     assert(indxRow >= 0);
2439     const int colEnd = UcolStarts_[column] + UcolLengths_[column];
2440     UcolInd_[indxRow] = UcolInd_[colEnd - 1];
2441     Ucolumns_[indxRow] = Ucolumns_[colEnd - 1];
2442     --UcolLengths_[column];
2443   }
2444   UrowLengths_[rowInU] = 0;
2445   // rowInU is empty
2446   // increase Eta by (lastRowInU-posNewCol) elements
2447   newEta(rowInU, lastRowInU - posNewCol);
2448   assert(!EtaLengths_[lastEtaRow_]);
2449   int saveSize = EtaSize_;
2450   ;
2451   for (int i = posNewCol; i < lastRowInU; ++i) {
2452     const int row = secRowOfU_[i];
2453     const int column = colOfU_[i];
2454     if (denseVector_[column] == 0.0)
2455       continue;
2456     const double multiplier = denseVector_[column] * invOfPivots_[row];
2457     denseVector_[column] = 0.0;
2458     const int rowBeg = UrowStarts_[row];
2459     const int rowEnd = rowBeg + UrowLengths_[row];
2460 #if ARRAY
2461     for (int j = rowBeg; j < rowEnd; ++j) {
2462       denseVector_[UrowInd_[j]] -= multiplier * Urows_[j];
2463     }
2464 #else
2465     int *ind = UrowInd_ + rowBeg;
2466     int *indEnd = UrowInd_ + rowEnd;
2467     double *uRow = Urows_ + rowBeg;
2468     for (; ind != indEnd; ++ind) {
2469       denseVector_[*ind] -= multiplier * (*uRow);
2470       ++uRow;
2471     }
2472 #endif
2473     // store multiplier
2474     Eta_[EtaSize_] = multiplier;
2475     EtaInd_[EtaSize_++] = row;
2476   }
2477   if (EtaSize_ != saveSize)
2478     EtaLengths_[lastEtaRow_] = EtaSize_ - saveSize;
2479   else
2480     --lastEtaRow_;
2481   // inverse of diagonal
2482   invOfPivots_[rowInU] = 1.0 / denseVector_[colOfU_[lastRowInU]];
2483   denseVector_[colOfU_[lastRowInU]] = 0.0;
2484   // now store row
2485   int newEls = 0;
2486   for (int i = lastRowInU + 1; i < numberColumns_; ++i) {
2487     const int column = colOfU_[i];
2488     const double coeff = denseVector_[column];
2489     denseVector_[column] = 0.0;
2490     if (fabs(coeff) < zeroTolerance_)
2491       continue;
2492 #ifdef COIN_SIMP_CAPACITY
2493     if (UcolLengths_[column] + 1 > UcolCapacities_[column]) {
2494       increaseColSize(column, UcolLengths_[column] + 1, true);
2495     }
2496 #endif
2497     const int newInd = UcolStarts_[column] + UcolLengths_[column];
2498     UcolInd_[newInd] = rowInU;
2499     Ucolumns_[newInd] = coeff;
2500     ++UcolLengths_[column];
2501     workArea2_[newEls] = coeff;
2502     indVector_[newEls++] = column;
2503   }
2504 #ifdef COIN_SIMP_CAPACITY
2505   if (UrowCapacities_[rowInU] < newEls)
2506     increaseRowSize(rowInU, newEls);
2507 #endif
2508   const int startRow = UrowStarts_[rowInU];
2509   memcpy(&Urows_[startRow], &workArea2_[0], newEls * sizeof(double));
2510   memcpy(&UrowInd_[startRow], &indVector_[0], newEls * sizeof(int));
2511   UrowLengths_[rowInU] = newEls;
2512   //
2513   if (fabs(invOfPivots_[rowInU]) > updateTol_)
2514     return 2;
2515 
2516   return 0;
2517 }
2518 
newEta(int row,int numNewElements)2519 void CoinSimpFactorization::newEta(int row, int numNewElements)
2520 {
2521   if (lastEtaRow_ == maxEtaRows_ - 1) {
2522     int *iaux = new int[maxEtaRows_ + minIncrease_];
2523     memcpy(iaux, EtaPosition_, maxEtaRows_ * sizeof(int));
2524     delete[] EtaPosition_;
2525     EtaPosition_ = iaux;
2526 
2527     int *jaux = new int[maxEtaRows_ + minIncrease_];
2528     memcpy(jaux, EtaStarts_, maxEtaRows_ * sizeof(int));
2529     delete[] EtaStarts_;
2530     EtaStarts_ = jaux;
2531 
2532     int *kaux = new int[maxEtaRows_ + minIncrease_];
2533     memcpy(kaux, EtaLengths_, maxEtaRows_ * sizeof(int));
2534     delete[] EtaLengths_;
2535     EtaLengths_ = kaux;
2536 
2537     maxEtaRows_ += minIncrease_;
2538   }
2539   if (EtaSize_ + numNewElements > EtaMaxCap_) {
2540     int number = CoinMax(EtaSize_ + numNewElements - EtaMaxCap_, minIncrease_);
2541 
2542     int *iaux = new int[EtaMaxCap_ + number];
2543     memcpy(iaux, EtaInd_, EtaSize_ * sizeof(int));
2544     delete[] EtaInd_;
2545     EtaInd_ = iaux;
2546 
2547     double *aux = new double[EtaMaxCap_ + number];
2548     memcpy(aux, Eta_, EtaSize_ * sizeof(double));
2549     delete[] Eta_;
2550     Eta_ = aux;
2551 
2552     EtaMaxCap_ += number;
2553   }
2554   EtaPosition_[++lastEtaRow_] = row;
2555   EtaStarts_[lastEtaRow_] = EtaSize_;
2556   EtaLengths_[lastEtaRow_] = 0;
2557 }
copyRowPermutations()2558 void CoinSimpFactorization::copyRowPermutations()
2559 {
2560   memcpy(&secRowOfU_[0], &rowOfU_[0],
2561     numberRows_ * sizeof(int));
2562   memcpy(&secRowPosition_[0], &rowPosition_[0],
2563     numberRows_ * sizeof(int));
2564 }
2565 
Hxeqb(double * b) const2566 void CoinSimpFactorization::Hxeqb(double *b) const
2567 {
2568   double *rhs = b;
2569   int row, rowBeg, *ind, *indEnd;
2570   double xr, *eta;
2571   // now solve
2572   for (int k = 0; k <= lastEtaRow_; ++k) {
2573     row = EtaPosition_[k];
2574     rowBeg = EtaStarts_[k];
2575     xr = 0.0;
2576     ind = EtaInd_ + rowBeg;
2577     indEnd = ind + EtaLengths_[k];
2578     eta = Eta_ + rowBeg;
2579     for (; ind != indEnd; ++ind) {
2580       xr += rhs[*ind] * (*eta);
2581       ++eta;
2582     }
2583     rhs[row] -= xr;
2584   }
2585 }
2586 
Hxeqb2(double * b1,double * b2) const2587 void CoinSimpFactorization::Hxeqb2(double *b1, double *b2) const
2588 {
2589   double *rhs1 = b1;
2590   double *rhs2 = b2;
2591   int row, rowBeg, *ind, *indEnd;
2592   double x1, x2, *eta;
2593   // now solve
2594   for (int k = 0; k <= lastEtaRow_; ++k) {
2595     row = EtaPosition_[k];
2596     rowBeg = EtaStarts_[k];
2597     x1 = 0.0;
2598     x2 = 0.0;
2599     ind = EtaInd_ + rowBeg;
2600     indEnd = ind + EtaLengths_[k];
2601     eta = Eta_ + rowBeg;
2602     for (; ind != indEnd; ++ind) {
2603       x1 += rhs1[*ind] * (*eta);
2604       x2 += rhs2[*ind] * (*eta);
2605       ++eta;
2606     }
2607     rhs1[row] -= x1;
2608     rhs2[row] -= x2;
2609   }
2610 }
2611 
xHeqb(double * b) const2612 void CoinSimpFactorization::xHeqb(double *b) const
2613 {
2614   double *rhs = b;
2615   int row, rowBeg, *ind, *indEnd;
2616   double xr, *eta;
2617   // now solve
2618   for (int k = lastEtaRow_; k >= 0; --k) {
2619     row = EtaPosition_[k];
2620     xr = rhs[row];
2621     if (xr == 0.0)
2622       continue;
2623     //if ( fabs(xr) <= zeroTolerance_ ) continue;
2624     rowBeg = EtaStarts_[k];
2625     ind = EtaInd_ + rowBeg;
2626     indEnd = ind + EtaLengths_[k];
2627     eta = Eta_ + rowBeg;
2628     for (; ind != indEnd; ++ind) {
2629       rhs[*ind] -= xr * (*eta);
2630       ++eta;
2631     }
2632   }
2633 }
2634 
ftran(double * b,double * sol,bool save) const2635 void CoinSimpFactorization::ftran(double *b, double *sol, bool save) const
2636 {
2637   Lxeqb(b);
2638   Hxeqb(b);
2639   if (save) {
2640     // keep vector
2641     keepSize_ = 0;
2642     for (int i = 0; i < numberRows_; ++i) {
2643       if (fabs(b[i]) < zeroTolerance_)
2644         continue;
2645       vecKeep_[keepSize_] = b[i];
2646       indKeep_[keepSize_++] = i;
2647     }
2648   }
2649   Uxeqb(b, sol);
2650 }
2651 
ftran2(double * b1,double * sol1,double * b2,double * sol2) const2652 void CoinSimpFactorization::ftran2(double *b1, double *sol1, double *b2, double *sol2) const
2653 {
2654   Lxeqb2(b1, b2);
2655   Hxeqb2(b1, b2);
2656   // keep vector
2657   keepSize_ = 0;
2658   for (int i = 0; i < numberRows_; ++i) {
2659     if (fabs(b1[i]) < zeroTolerance_)
2660       continue;
2661     vecKeep_[keepSize_] = b1[i];
2662     indKeep_[keepSize_++] = i;
2663   }
2664   Uxeqb2(b1, sol1, b2, sol2);
2665 }
2666 
btran(double * b,double * sol) const2667 void CoinSimpFactorization::btran(double *b, double *sol) const
2668 {
2669   xUeqb(b, sol);
2670   xHeqb(sol);
2671   xLeqb(sol);
2672 }
2673 
2674 #endif
2675 
2676 /* vi: softtabstop=2 shiftwidth=2 expandtab tabstop=2
2677 */
2678