Scippy

SoPlex

Sequential object-oriented simPlex

clufactor.cpp
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the class library */
4 /* SoPlex --- the Sequential object-oriented simPlex. */
5 /* */
6 /* Copyright (C) 1996-2019 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SoPlex is distributed under the terms of the ZIB Academic Licence. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SoPlex; see the file COPYING. If not email to soplex@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 #include <assert.h>
17 
18 #include "soplex/spxdefines.h"
19 #include "soplex/clufactor.h"
20 #include "soplex/cring.h"
21 #include "soplex/spxalloc.h"
22 #include "soplex/exceptions.h"
23 #include "soplex/stablesum.h"
24 
25 namespace soplex
26 {
27 
28 /* This number is used to decide wether a value is zero
29  * or was explicitly set to zero.
30  */
31 #define SOPLEX_FACTOR_MARKER 1e-100
32 
33 static const Real verySparseFactor = 0.001;
34 static const Real verySparseFactor4right = 0.2;
35 static const Real verySparseFactor4left = 0.1;
36 
37 /* generic heap management */
38 static void enQueueMax(int* heap, int* size, int elem)
39 {
40  int i, j;
41 
42  j = (*size)++;
43 
44  while(j > 0)
45  {
46  i = (j - 1) / 2;
47 
48  if(elem > heap[i])
49  {
50  heap[j] = heap[i];
51  j = i;
52  }
53  else
54  break;
55  }
56 
57  heap[j] = elem;
58 
59 #ifdef SOPLEX_DEBUG
60 
61  // no NDEBUG define, since this block is really expensive
62  for(i = 1; i < *size; ++i)
63  for(j = 0; j < i; ++j)
64  assert(heap[i] != heap[j]);
65 
66 #endif /* SOPLEX_DEBUG */
67 }
68 
69 static int deQueueMax(int* heap, int* size)
70 {
71  int e, elem;
72  int i, j, s;
73  int e1, e2;
74 
75  elem = *heap;
76  e = heap[s = --(*size)];
77  --s;
78 
79  for(j = 0, i = 1; i < s; i = 2 * j + 1)
80  {
81  e1 = heap[i];
82  e2 = heap[i + 1];
83 
84  if(e1 > e2)
85  {
86  if(e < e1)
87  {
88  heap[j] = e1;
89  j = i;
90  }
91  else
92  {
93  heap[j] = e;
94  return elem;
95  }
96  }
97  else
98  {
99  if(e < e2)
100  {
101  heap[j] = e2;
102  j = i + 1;
103  }
104  else
105  {
106  heap[j] = e;
107  return elem;
108  }
109  }
110  }
111 
112  if(i < *size && e < heap[i])
113  {
114  heap[j] = heap[i];
115  j = i;
116  }
117 
118  heap[j] = e;
119 
120  return elem;
121 }
122 
123 static void enQueueMin(int* heap, int* size, int elem)
124 {
125  int i, j;
126 
127  j = (*size)++;
128 
129  while(j > 0)
130  {
131  i = (j - 1) / 2;
132 
133  if(elem < heap[i])
134  {
135  heap[j] = heap[i];
136  j = i;
137  }
138  else
139  break;
140  }
141 
142  heap[j] = elem;
143 
144 #ifdef SOPLEX_DEBUG
145 
146  // no NDEBUG define, since this block is really expensive
147  for(i = 1; i < *size; ++i)
148  for(j = 0; j < i; ++j)
149  assert(heap[i] != heap[j]);
150 
151 #endif /* SOPLEX_DEBUG */
152 }
153 
154 static int deQueueMin(int* heap, int* size)
155 {
156  int e, elem;
157  int i, j, s;
158  int e1, e2;
159 
160  elem = *heap;
161  e = heap[s = --(*size)];
162  --s;
163 
164  for(j = 0, i = 1; i < s; i = 2 * j + 1)
165  {
166  e1 = heap[i];
167  e2 = heap[i + 1];
168 
169  if(e1 < e2)
170  {
171  if(e > e1)
172  {
173  heap[j] = e1;
174  j = i;
175  }
176  else
177  {
178  heap[j] = e;
179  return elem;
180  }
181  }
182  else
183  {
184  if(e > e2)
185  {
186  heap[j] = e2;
187  j = i + 1;
188  }
189  else
190  {
191  heap[j] = e;
192  return elem;
193  }
194  }
195  }
196 
197  if(i < *size && e > heap[i])
198  {
199  heap[j] = heap[i];
200  j = i;
201  }
202 
203  heap[j] = e;
204 
205  return elem;
206 }
207 
208 /************************************************************/
210  : s_mark(0)
211  , s_max(0)
212  , s_cact(0)
213  , stage(0)
214  , pivot_col(0)
215  , pivot_colNZ(0)
216  , pivot_row(0)
217  , pivot_rowNZ(0)
218 {}
219 
220 void CLUFactor::Temp::init(int p_dim)
221 {
222  spx_realloc(s_max, p_dim);
223  spx_realloc(s_cact, p_dim);
224  spx_realloc(s_mark, p_dim);
225  stage = 0;
226 }
227 
229 {
230  if(s_mark != 0)
231  spx_free(s_mark);
232 
233  if(s_cact != 0)
234  spx_free(s_cact);
235 
236  if(s_max != 0)
237  spx_free(s_max);
238 
239  if(pivot_col != 0)
241 
242  if(pivot_colNZ != 0)
244 
245  if(pivot_row != 0)
247 
248  if(pivot_rowNZ != 0)
250 }
251 
253 {
254  clear();
255 }
256 
257 /************************************************************/
259 {
260 
261  for(int i = 0; i < thedim; ++i)
262  row.orig[i] = row.perm[i] = col.orig[i] = col.perm[i] = -1;
263 }
264 
265 /*****************************************************************************/
266 
267 void CLUFactor::setPivot(const int p_stage,
268  const int p_col,
269  const int p_row,
270  const Real val)
271 {
272  assert(row.perm[p_row] < 0);
273  assert(col.perm[p_col] < 0);
274 
275  row.orig[p_stage] = p_row;
276  col.orig[p_stage] = p_col;
277  row.perm[p_row] = p_stage;
278  col.perm[p_col] = p_stage;
279  diag[p_row] = REAL(1.0) / val;
280 
281  if(spxAbs(val) < Param::epsilonPivot())
282  {
283 #ifndef NDEBUG
284  MSG_ERROR(std::cerr
285  << "LU pivot element is almost zero (< "
287  << ") - Basis is numerically singular"
288  << std::endl;
289  )
290 #endif
292  }
293 
294  if(spxAbs(diag[p_row]) > maxabs)
295  maxabs = spxAbs(diag[p_row]);
296 }
297 
298 /*****************************************************************************/
299 /*
300  * Perform garbage collection on row file
301  */
303 {
304  int n, i, j, l_row;
305  Dring* ring, *list;
306 
307  int* l_ridx = u.row.idx;
308  Real* l_rval = u.row.val;
309  int* l_rlen = u.row.len;
310  int* l_rmax = u.row.max;
311  int* l_rbeg = u.row.start;
312 
313  n = 0;
314  list = &(u.row.list);
315 
316  for(ring = list->next; ring != list; ring = ring->next)
317  {
318  l_row = ring->idx;
319 
320  if(l_rbeg[l_row] != n)
321  {
322  do
323  {
324  l_row = ring->idx;
325  i = l_rbeg[l_row];
326  assert(l_rlen[l_row] <= l_rmax[l_row]);
327  l_rbeg[l_row] = n;
328  l_rmax[l_row] = l_rlen[l_row];
329  j = i + l_rlen[l_row];
330 
331  for(; i < j; ++i, ++n)
332  {
333  assert(n <= i);
334  l_ridx[n] = l_ridx[i];
335  l_rval[n] = l_rval[i];
336  }
337 
338  ring = ring->next;
339  }
340  while(ring != list);
341 
342  goto terminatePackRows;
343  }
344 
345  n += l_rlen[l_row];
346 
347  l_rmax[l_row] = l_rlen[l_row];
348  }
349 
350 terminatePackRows:
351 
352  u.row.max[thedim] = 0;
353  u.row.used = n;
354 }
355 
356 /*****************************************************************************/
357 /*
358  * Perform garbage collection on column file
359  */
361 {
362  int n, i, j, colno;
363  Dring* ring, *list;
364 
365  Real* cval = u.col.val;
366  int* cidx = u.col.idx;
367  int* clen = u.col.len;
368  int* cmax = u.col.max;
369  int* cbeg = u.col.start;
370 
371  n = 0;
372  list = &u.col.list;
373 
374  for(ring = list->next; ring != list; ring = ring->next)
375  {
376  colno = ring->idx;
377 
378  if(cbeg[colno] != n)
379  {
380  do
381  {
382  colno = ring->idx;
383  i = cbeg[colno];
384  cbeg[colno] = n;
385  cmax[colno] = clen[colno];
386  j = i + clen[colno];
387 
388  for(; i < j; ++i)
389  {
390  cval[n] = cval[i];
391  cidx[n++] = cidx[i];
392  }
393 
394  ring = ring->next;
395  }
396  while(ring != list);
397 
398  goto terminatePackColumns;
399  }
400 
401  n += clen[colno];
402 
403  cmax[colno] = clen[colno];
404  }
405 
406 terminatePackColumns :
407 
408  u.col.used = n;
409  u.col.max[thedim] = 0;
410 }
411 
412 /*
413  * Make row of fac large enough to hold len nonzeros.
414  */
415 void CLUFactor::remaxRow(int p_row, int len)
416 {
417  assert(u.row.max[p_row] < len);
418 
419  if(u.row.elem[p_row].next == &(u.row.list)) /* last in row file */
420  {
421  int delta = len - u.row.max[p_row];
422 
423  if(delta > u.row.size - u.row.used)
424  {
425  packRows();
426  delta = len - u.row.max[p_row]; // packRows() changes u.row.max[] !
427 
428  if(u.row.size < rowMemMult * u.row.used + len)
429  minRowMem(2 * u.row.used + len);
430 
431  /* minRowMem(rowMemMult * u.row.used + len); */
432  }
433 
434  assert(delta <= u.row.size - u.row.used
435 
436  && "ERROR: could not allocate memory for row file");
437 
438  u.row.used += delta;
439  u.row.max[p_row] = len;
440  }
441  else /* row must be moved to end of row file */
442  {
443  int i, j, k;
444  int* idx;
445  Real* val;
446  Dring* ring;
447 
448  if(len > u.row.size - u.row.used)
449  {
450  packRows();
451 
452  if(u.row.size < rowMemMult * u.row.used + len)
453  minRowMem(2 * u.row.used + len);
454 
455  /* minRowMem(rowMemMult * u.row.used + len);*/
456  }
457 
458  assert(len <= u.row.size - u.row.used
459 
460  && "ERROR: could not allocate memory for row file");
461 
462  j = u.row.used;
463  i = u.row.start[p_row];
464  k = u.row.len[p_row] + i;
465  u.row.start[p_row] = j;
466  u.row.used += len;
467 
468  u.row.max[u.row.elem[p_row].prev->idx] += u.row.max[p_row];
469  u.row.max[p_row] = len;
470  removeDR(u.row.elem[p_row]);
471  ring = u.row.list.prev;
472  init2DR(u.row.elem[p_row], *ring);
473 
474  idx = u.row.idx;
475  val = u.row.val;
476 
477  for(; i < k; ++i, ++j)
478  {
479  val[j] = val[i];
480  idx[j] = idx[i];
481  }
482  }
483 
484  assert(u.row.start[u.row.list.prev->idx] + u.row.max[u.row.list.prev->idx]
485 
486  == u.row.used);
487 }
488 
489 /*************************************************************************/
490 /*
491  * Perform garbage collection on column file
492  */
494 {
495  int n, i, j, l_col;
496  Dring* ring, *list;
497 
498  int* l_cidx = u.col.idx;
499  int* l_clen = u.col.len;
500  int* l_cmax = u.col.max;
501  int* l_cbeg = u.col.start;
502 
503  n = 0;
504  list = &(u.col.list);
505 
506  for(ring = list->next; ring != list; ring = ring->next)
507  {
508  l_col = ring->idx;
509 
510  if(l_cbeg[l_col] != n)
511  {
512  do
513  {
514  l_col = ring->idx;
515  i = l_cbeg[l_col];
516  l_cbeg[l_col] = n;
517  l_cmax[l_col] = l_clen[l_col];
518  j = i + l_clen[l_col];
519 
520  for(; i < j; ++i)
521  l_cidx[n++] = l_cidx[i];
522 
523  ring = ring->next;
524  }
525  while(ring != list);
526 
527  goto terminatePackColumns;
528  }
529 
530  n += l_clen[l_col];
531 
532  l_cmax[l_col] = l_clen[l_col];
533  }
534 
535 terminatePackColumns :
536 
537  u.col.used = n;
538  u.col.max[thedim] = 0;
539 }
540 
541 /*
542  * Make column col of fac large enough to hold len nonzeros.
543  */
544 void CLUFactor::remaxCol(int p_col, int len)
545 {
546  assert(u.col.max[p_col] < len);
547 
548  if(u.col.elem[p_col].next == &(u.col.list)) /* last in column file */
549  {
550  int delta = len - u.col.max[p_col];
551 
552  if(delta > u.col.size - u.col.used)
553  {
554  packColumns();
555  delta = len - u.col.max[p_col];
556 
557  if(u.col.size < colMemMult * u.col.used + len)
558  minColMem(2 * u.col.used + len);
559 
560  /* minColMem(colMemMult * u.col.used + len); */
561  }
562 
563  assert(delta <= u.col.size - u.col.used
564 
565  && "ERROR: could not allocate memory for column file");
566 
567  u.col.used += delta;
568  u.col.max[p_col] = len;
569  }
570 
571  else /* column must be moved to end of column file */
572  {
573  int i, j, k;
574  int* idx;
575  Dring* ring;
576 
577  if(len > u.col.size - u.col.used)
578  {
579  packColumns();
580 
581  if(u.col.size < colMemMult * u.col.used + len)
582  minColMem(2 * u.col.used + len);
583 
584  /* minColMem(colMemMult * u.col.used + len); */
585  }
586 
587  assert(len <= u.col.size - u.col.used
588 
589  && "ERROR: could not allocate memory for column file");
590 
591  j = u.col.used;
592  i = u.col.start[p_col];
593  k = u.col.len[p_col] + i;
594  u.col.start[p_col] = j;
595  u.col.used += len;
596 
597  u.col.max[u.col.elem[p_col].prev->idx] += u.col.max[p_col];
598  u.col.max[p_col] = len;
599  removeDR(u.col.elem[p_col]);
600  ring = u.col.list.prev;
601  init2DR(u.col.elem[p_col], *ring);
602 
603  idx = u.col.idx;
604 
605  for(; i < k; ++i)
606  idx[j++] = idx[i];
607  }
608 }
609 
610 /*
611  * Make column col of fac large enough to hold len nonzeros.
612  */
613 void CLUFactor::forestReMaxCol(int p_col, int len)
614 {
615  assert(u.col.max[p_col] < len);
616 
617  if(u.col.elem[p_col].next == &(u.col.list)) /* last in column file */
618  {
619  int delta = len - u.col.max[p_col];
620 
621  if(delta > u.col.size - u.col.used)
622  {
624  delta = len - u.col.max[p_col];
625 
626  if(u.col.size < colMemMult * u.col.used + len)
627  forestMinColMem(int(colMemMult * u.col.used + len));
628  }
629 
630  assert(delta <= u.col.size - u.col.used
631 
632  && "ERROR: could not allocate memory for column file");
633 
634  u.col.used += delta;
635  u.col.max[p_col] = len;
636  }
637 
638  else /* column must be moved to end of column file */
639  {
640  int i, j, k;
641  int* idx;
642  Real* val;
643  Dring* ring;
644 
645  if(len > u.col.size - u.col.used)
646  {
648 
649  if(u.col.size < colMemMult * u.col.used + len)
650  forestMinColMem(int(colMemMult * u.col.used + len));
651  }
652 
653  assert(len <= u.col.size - u.col.used
654 
655  && "ERROR: could not allocate memory for column file");
656 
657  j = u.col.used;
658  i = u.col.start[p_col];
659  k = u.col.len[p_col] + i;
660  u.col.start[p_col] = j;
661  u.col.used += len;
662 
663  u.col.max[u.col.elem[p_col].prev->idx] += u.col.max[p_col];
664  u.col.max[p_col] = len;
665  removeDR(u.col.elem[p_col]);
666  ring = u.col.list.prev;
667  init2DR(u.col.elem[p_col], *ring);
668 
669  idx = u.col.idx;
670  val = u.col.val;
671 
672  for(; i < k; ++i)
673  {
674  val[j] = val[i];
675  idx[j++] = idx[i];
676  }
677  }
678 }
679 
680 /*****************************************************************************/
681 
682 /**
683  * \brief Performs the Forrest-Tomlin update of the LU factorization.
684  *
685  * BH: I suppose this is implemented as described in UH Suhl, LM Suhl: A fast LU
686  * update for linear programming, Annals of OR 43, p. 33-47, 1993.
687  *
688  * @param p_col Index of basis column to replace.
689  * @param p_work Dense vector to substitute in the basis.
690  * @param num Number of nonzeros in vector represented by p_work.
691  * @param nonz Indices of nonzero elements in vector p_work.
692  *
693  * The parameters num and nonz are used for the following optimization: If both
694  * are nonzero, indices of the nonzero elements provided in nonz (num giving
695  * their number) allow to access only those nonzero entries. Otherwise we have
696  * to go through the entire dense vector element by element.
697  *
698  * After copying p_work into U, p_work is used to expand the row r, which is
699  * needed to restore the triangular structure of U.
700  *
701  * Also num and nonz are used to maintain a heap if there are only very few
702  * nonzeros to be eliminated. This is plainly wrong if the method is called with
703  * nonz==0, see todo at the corresponding place below.
704  *
705  * @throw SPxStatusException if the loaded matrix is singular
706  *
707  * @todo Use an extra member variable as a buffer for working with the dense
708  * row instead of misusing p_work. I think that should be as efficient and
709  * much cleaner.
710  */
711 
712 void CLUFactor::forestUpdate(int p_col, Real* p_work, int num, int* nonz)
713 {
714  int i, j, k, h, m, n;
715  int ll, c, r, rowno;
716  Real x;
717 
718  Real* lval;
719  int* lidx;
720  int* lbeg = l.start;
721 
722  Real* cval;
723  int* cidx = u.col.idx;
724  int* cmax = u.col.max;
725  int* clen = u.col.len;
726  int* cbeg = u.col.start;
727 
728  Real* rval = u.row.val;
729  int* ridx = u.row.idx;
730  int* rmax = u.row.max;
731  int* rlen = u.row.len;
732  int* rbeg = u.row.start;
733 
734  int* rperm = row.perm;
735  int* rorig = row.orig;
736  int* cperm = col.perm;
737  int* corig = col.orig;
738 
739  Real l_maxabs = maxabs;
740  int dim = thedim;
741 
742  /* Remove column p_col from U
743  */
744  j = cbeg[p_col];
745  i = clen[p_col];
746  nzCnt -= i;
747 
748  for(i += j - 1; i >= j; --i)
749  {
750  m = cidx[i]; // remove column p_col from row m
751  k = rbeg[m];
752  h = --(rlen[m]) + k; // decrease length of row m
753 
754  while(ridx[k] != p_col)
755  ++k;
756 
757  assert(k <= h); // k is the position of p_col, h is last position
758 
759  ridx[k] = ridx[h]; // store last index at the position of p_col
760 
761  rval[k] = rval[h];
762  }
763 
764  /* Insert new vector column p_col thereby determining the highest permuted
765  * row index r.
766  *
767  * Distinguish between optimized call (num > 0, nonz != 0) and
768  * non-optimized one.
769  */
770  assert(num); // otherwise the assert( nonz != 0 ) below should fail
771 
772  if(num)
773  {
774  // Optimized call.
775  assert(nonz != 0);
776 
777  clen[p_col] = 0;
778 
779  if(num > cmax[p_col])
780  forestReMaxCol(p_col, num);
781 
782  cidx = u.col.idx;
783 
784  cval = u.col.val;
785 
786  k = cbeg[p_col];
787 
788  r = 0;
789 
790  for(j = 0; j < num; ++j)
791  {
792  i = nonz[j];
793  x = p_work[i];
794  p_work[i] = 0.0;
795 
797  {
798  if(spxAbs(x) > l_maxabs)
799  l_maxabs = spxAbs(x);
800 
801  /* insert to column file */
802  assert(k - cbeg[p_col] < cmax[p_col]);
803 
804  cval[k] = x;
805 
806  cidx[k++] = i;
807 
808  /* insert to row file */
809  if(rmax[i] <= rlen[i])
810  {
811  remaxRow(i, rlen[i] + 1);
812  rval = u.row.val;
813  ridx = u.row.idx;
814  }
815 
816  h = rbeg[i] + (rlen[i])++;
817 
818  rval[h] = x;
819  ridx[h] = p_col;
820 
821  /* check permuted row index */
822 
823  if(rperm[i] > r)
824  r = rperm[i];
825  }
826  }
827 
828  nzCnt += (clen[p_col] = k - cbeg[p_col]);
829  }
830  else
831  {
832  // Non-optimized call: We have to access all elements of p_work.
833  assert(nonz == 0);
834 
835  /*
836  * clen[col] = 0;
837  * reMaxCol(fac, col, dim);
838  */
839  cidx = u.col.idx;
840  cval = u.col.val;
841  k = cbeg[p_col];
842  j = k + cmax[p_col];
843  r = 0;
844 
845  for(i = 0; i < dim; ++i)
846  {
847  x = p_work[i];
848  p_work[i] = 0.0;
849 
851  {
852  if(spxAbs(x) > l_maxabs)
853  l_maxabs = spxAbs(x);
854 
855  /* insert to column file */
856  if(k >= j)
857  {
858  clen[p_col] = k - cbeg[p_col];
859  forestReMaxCol(p_col, dim - i);
860  cidx = u.col.idx;
861  cval = u.col.val;
862  k = cbeg[p_col];
863  j = k + cmax[p_col];
864  k += clen[p_col];
865  }
866 
867  assert(k - cbeg[p_col] < cmax[p_col]);
868 
869  cval[k] = x;
870  cidx[k++] = i;
871 
872  /* insert to row file */
873 
874  if(rmax[i] <= rlen[i])
875  {
876  remaxRow(i, rlen[i] + 1);
877  rval = u.row.val;
878  ridx = u.row.idx;
879  }
880 
881  h = rbeg[i] + (rlen[i])++;
882 
883  rval[h] = x;
884  ridx[h] = p_col;
885 
886  /* check permuted row index */
887 
888  if(rperm[i] > r)
889  r = rperm[i];
890  }
891  }
892 
893  nzCnt += (clen[p_col] = k - cbeg[p_col]);
894 
895  if(cbeg[p_col] + cmax[p_col] == u.col.used)
896  {
897  u.col.used -= cmax[p_col];
898  cmax[p_col] = clen[p_col];
899  u.col.used += cmax[p_col];
900  }
901  }
902 
903  c = cperm[p_col];
904 
905  if(r > c) /* Forest Tomlin update */
906  {
907  /* update permutations
908  */
909  j = rorig[c];
910 
911  // memmove is more efficient than a for loop
912  // for ( i = c; i < r; ++i )
913  // rorig[i] = rorig[i + 1];
914  memmove(&rorig[c], &rorig[c + 1], (unsigned int)(r - c) * sizeof(int));
915 
916  rorig[r] = j;
917 
918  for(i = c; i <= r; ++i)
919  rperm[rorig[i]] = i;
920 
921  j = corig[c];
922 
923  // memmove is more efficient than a for loop
924  // for ( i = c; i < r; ++i )
925  // corig[i] = corig[i + 1];
926  memmove(&corig[c], &corig[c + 1], (unsigned int)(r - c) * sizeof(int));
927 
928  corig[r] = j;
929 
930  for(i = c; i <= r; ++i)
931  cperm[corig[i]] = i;
932 
933 
934  rowno = rorig[r];
935 
936  j = rbeg[rowno];
937 
938  i = rlen[rowno];
939 
940  nzCnt -= i;
941 
942  if(i < verySparseFactor * (dim - c)) // few nonzeros to be eliminated
943  {
944  /**
945  * The following assert is obviously violated if this method is called
946  * with nonzero==0.
947  *
948  * @todo Use an extra member variable as a buffer for the heap instead of
949  * misusing nonz and num. The method enQueueMin() seems to
950  * sort the nonzeros or something, for which it only needs
951  * some empty vector of size num.
952  */
953  assert(nonz != 0);
954 
955  /* move row r from U to p_work
956  */
957  num = 0;
958 
959  for(i += j - 1; i >= j; --i)
960  {
961  k = ridx[i];
962  p_work[k] = rval[i];
963  enQueueMin(nonz, &num, cperm[k]);
964  m = --(clen[k]) + cbeg[k];
965 
966  for(h = m; cidx[h] != rowno; --h)
967  ;
968 
969  cidx[h] = cidx[m];
970 
971  cval[h] = cval[m];
972  }
973 
974 
975  /* Eliminate row r from U to L file
976  */
977  ll = makeLvec(r - c, rowno);
978 
979  lval = l.val;
980 
981  lidx = l.idx;
982 
983  assert((num == 0) || (nonz != 0));
984 
985  /* for(i = c; i < r; ++i) */
986  while(num)
987  {
988 #ifndef NDEBUG
989  // The numbers seem to be often 1e-100, is this ok ?
990 
991  for(i = 0; i < num; ++i)
992  assert(p_work[corig[nonz[i]]] != 0.0);
993 
994 #endif // NDEBUG
995  i = deQueueMin(nonz, &num);
996 
997  if(i == r)
998  break;
999 
1000  k = corig[i];
1001 
1002  assert(p_work[k] != 0.0);
1003 
1004  n = rorig[i];
1005 
1006  x = p_work[k] * diag[n];
1007 
1008  lidx[ll] = n;
1009 
1010  lval[ll] = x;
1011 
1012  p_work[k] = 0.0;
1013 
1014  ll++;
1015 
1016  if(spxAbs(x) > l_maxabs)
1017  l_maxabs = spxAbs(x);
1018 
1019  j = rbeg[n];
1020 
1021  m = rlen[n] + j;
1022 
1023  for(; j < m; ++j)
1024  {
1025  int jj = ridx[j];
1026  Real y = p_work[jj];
1027 
1028  if(y == 0)
1029  enQueueMin(nonz, &num, cperm[jj]);
1030 
1031  y -= x * rval[j];
1032 
1033  p_work[jj] = y + ((y == 0) ? SOPLEX_FACTOR_MARKER : 0.0);
1034  }
1035  }
1036 
1037  if(lbeg[l.firstUnused - 1] == ll)
1038  (l.firstUnused)--;
1039  else
1040  lbeg[l.firstUnused] = ll;
1041 
1042 
1043  /* Set diagonal value
1044  */
1045  if(i != r)
1046  {
1048  throw SPxStatusException("XFORE01 The loaded matrix is singular");
1049  }
1050 
1051  k = corig[r];
1052 
1053  x = p_work[k];
1054  diag[rowno] = 1 / x;
1055  p_work[k] = 0.0;
1056 
1057 
1058  /* make row large enough to fit all nonzeros.
1059  */
1060 
1061  if(rmax[rowno] < num)
1062  {
1063  rlen[rowno] = 0;
1064  remaxRow(rowno, num);
1065  rval = u.row.val;
1066  ridx = u.row.idx;
1067  }
1068 
1069  nzCnt += num;
1070 
1071  /* Insert work to updated row thereby clearing work;
1072  */
1073  n = rbeg[rowno];
1074 
1075  for(i = 0; i < num; ++i)
1076  {
1077  j = corig[nonz[i]];
1078  x = p_work[j];
1079 
1080  // BH 2005-08-24: This if is very important. It may well happen that
1081  // during the elimination of row r a nonzero elements cancels out
1082  // and becomes zero. This would lead to an infinite loop in the
1083  // above elimination code, since the corresponding column index would
1084  // be enqueued for further elimination again and agian.
1085 
1086  if(x != 0.0)
1087  {
1088  if(spxAbs(x) > l_maxabs)
1089  l_maxabs = spxAbs(x);
1090 
1091  ridx[n] = j;
1092 
1093  rval[n] = x;
1094 
1095  p_work[j] = 0.0;
1096 
1097  ++n;
1098 
1099  if(clen[j] >= cmax[j])
1100  {
1101  forestReMaxCol(j, clen[j] + 1);
1102  cidx = u.col.idx;
1103  cval = u.col.val;
1104  }
1105 
1106  cval[cbeg[j] + clen[j]] = x;
1107 
1108  cidx[cbeg[j] + clen[j]++] = rowno;
1109  }
1110  }
1111 
1112  rlen[rowno] = n - rbeg[rowno];
1113  }
1114  else /* few nonzeros to be eliminated */
1115  {
1116  /* move row r from U to p_work
1117  */
1118  for(i += j - 1; i >= j; --i)
1119  {
1120  k = ridx[i];
1121  p_work[k] = rval[i];
1122  m = --(clen[k]) + cbeg[k];
1123 
1124  for(h = m; cidx[h] != rowno; --h)
1125  ;
1126 
1127  cidx[h] = cidx[m];
1128 
1129  cval[h] = cval[m];
1130  }
1131 
1132 
1133  /* Eliminate row r from U to L file
1134  */
1135  ll = makeLvec(r - c, rowno);
1136 
1137  lval = l.val;
1138 
1139  lidx = l.idx;
1140 
1141  for(i = c; i < r; ++i)
1142  {
1143  k = corig[i];
1144 
1145  if(p_work[k] != 0.0)
1146  {
1147  n = rorig[i];
1148  x = p_work[k] * diag[n];
1149  lidx[ll] = n;
1150  lval[ll] = x;
1151  p_work[k] = 0.0;
1152  ll++;
1153 
1154  if(spxAbs(x) > l_maxabs)
1155  l_maxabs = spxAbs(x);
1156 
1157  j = rbeg[n];
1158 
1159  m = rlen[n] + j;
1160 
1161  for(; j < m; ++j)
1162  p_work[ridx[j]] -= x * rval[j];
1163  }
1164  }
1165 
1166  if(lbeg[l.firstUnused - 1] == ll)
1167  (l.firstUnused)--;
1168  else
1169  lbeg[l.firstUnused] = ll;
1170 
1171 
1172  /* Set diagonal value
1173  */
1174  k = corig[r];
1175 
1176  x = p_work[k];
1177 
1178  if(x == 0.0)
1179  {
1181  throw SPxStatusException("XFORE02 The loaded matrix is singular");
1182  // return;
1183  }
1184 
1185  diag[rowno] = 1 / x;
1186 
1187  p_work[k] = 0.0;
1188 
1189 
1190  /* count remaining nonzeros in work and make row large enough
1191  * to fit them all.
1192  */
1193  n = 0;
1194 
1195  for(i = r + 1; i < dim; ++i)
1196  if(p_work[corig[i]] != 0.0)
1197  n++;
1198 
1199  if(rmax[rowno] < n)
1200  {
1201  rlen[rowno] = 0;
1202  remaxRow(rowno, n);
1203  rval = u.row.val;
1204  ridx = u.row.idx;
1205  }
1206 
1207  nzCnt += n;
1208 
1209  /* Insert p_work to updated row thereby clearing p_work;
1210  */
1211  n = rbeg[rowno];
1212 
1213  for(i = r + 1; i < dim; ++i)
1214  {
1215  j = corig[i];
1216  x = p_work[j];
1217 
1218  if(x != 0.0)
1219  {
1220  if(spxAbs(x) > l_maxabs)
1221  l_maxabs = spxAbs(x);
1222 
1223  ridx[n] = j;
1224 
1225  rval[n] = x;
1226 
1227  p_work[j] = 0.0;
1228 
1229  ++n;
1230 
1231  if(clen[j] >= cmax[j])
1232  {
1233  forestReMaxCol(j, clen[j] + 1);
1234  cidx = u.col.idx;
1235  cval = u.col.val;
1236  }
1237 
1238  cval[cbeg[j] + clen[j]] = x;
1239 
1240  cidx[cbeg[j] + clen[j]++] = rowno;
1241  }
1242  }
1243 
1244  rlen[rowno] = n - rbeg[rowno];
1245  }
1246  }
1247 
1248  else if(r == c)
1249  {
1250  /* Move diagonal element to diag. Note, that it must be the last
1251  * element, since it has just been inserted above.
1252  */
1253  rowno = rorig[r];
1254  i = rbeg[rowno] + --(rlen[rowno]);
1255  diag[rowno] = 1 / rval[i];
1256 
1257  for(j = i = --(clen[p_col]) + cbeg[p_col]; cidx[i] != rowno; --i)
1258  ;
1259 
1260  cidx[i] = cidx[j];
1261 
1262  cval[i] = cval[j];
1263  }
1264  else /* r < c */
1265  {
1267  throw SPxStatusException("XFORE03 The loaded matrix is singular");
1268  // return;
1269  }
1270 
1271  maxabs = l_maxabs;
1272 
1273  assert(isConsistent());
1274  stat = SLinSolver::OK;
1275 }
1276 
1277 void CLUFactor::update(int p_col, Real* p_work, const int* p_idx, int num)
1278 {
1279  int ll, i, j;
1280  int* lidx;
1281  Real* lval;
1282  Real x, rezi;
1283 
1284  assert(p_work[p_col] != 0.0);
1285  rezi = 1 / p_work[p_col];
1286  p_work[p_col] = 0.0;
1287 
1288  ll = makeLvec(num, p_col);
1289  // ll = fac->makeLvec(num, col);
1290  lval = l.val;
1291  lidx = l.idx;
1292 
1293  for(i = num - 1; (j = p_idx[i]) != p_col; --i)
1294  {
1295  lidx[ll] = j;
1296  lval[ll] = rezi * p_work[j];
1297  p_work[j] = 0.0;
1298  ++ll;
1299  }
1300 
1301  lidx[ll] = p_col;
1302 
1303  lval[ll] = 1 - rezi;
1304  ++ll;
1305 
1306  for(--i; i >= 0; --i)
1307  {
1308  j = p_idx[i];
1309  lidx[ll] = j;
1310  lval[ll] = x = rezi * p_work[j];
1311  p_work[j] = 0.0;
1312  ++ll;
1313 
1314  if(spxAbs(x) > maxabs)
1315  maxabs = spxAbs(x);
1316  }
1317 
1318  stat = SLinSolver::OK;
1319 }
1320 
1322  int p_col,
1323  const Real* p_work,
1324  const int* p_idx,
1325  int num)
1326 {
1327  int ll, i, j;
1328  int* lidx;
1329  Real* lval;
1330  Real x, rezi;
1331 
1332  assert(p_work[p_col] != 0.0);
1333  rezi = 1 / p_work[p_col];
1334  ll = makeLvec(num, p_col);
1335  //ll = fac->makeLvec(num, col);
1336  lval = l.val;
1337  lidx = l.idx;
1338 
1339  for(i = num - 1; (j = p_idx[i]) != p_col; --i)
1340  {
1341  lidx[ll] = j;
1342  lval[ll] = rezi * p_work[j];
1343  ++ll;
1344  }
1345 
1346  lidx[ll] = p_col;
1347 
1348  lval[ll] = 1 - rezi;
1349  ++ll;
1350 
1351  for(--i; i >= 0; --i)
1352  {
1353  j = p_idx[i];
1354  lidx[ll] = j;
1355  lval[ll] = x = rezi * p_work[j];
1356  ++ll;
1357 
1358  if(spxAbs(x) > maxabs)
1359  maxabs = spxAbs(x);
1360  }
1361 
1362  stat = SLinSolver::OK;
1363 }
1364 
1365 /*****************************************************************************/
1366 /*
1367  * Temporary data structures.
1368  */
1369 
1370 /*
1371  * For the i=th column the situation might look like this:
1372  *
1373  * \begin{verbatim}
1374  * idx = ....................iiiIIIIII-----..............
1375  * cbeg[i] = ^
1376  * cact[i] = +----+
1377  * clen[i] = +-------+
1378  * cmax[i] = +------------+
1379  *
1380  * Indices clen[i]-cbeg[i]: ^^^
1381  * \end{verbatim}
1382  * belong to column i, but have already been pivotal and don't belong to
1383  * the active submatrix.
1384  */
1385 
1386 /****************************************************************************/
1387 /*
1388  * Initialize row and column file of working matrix and
1389  * mark column singletons.
1390  */
1391 void CLUFactor::initFactorMatrix(const SVector** vec, const Real eps)
1392 {
1393 
1394  Real x;
1395  int m;
1396  int tot;
1397  Dring* rring, *lastrring;
1398  Dring* cring, *lastcring;
1399  const SVector* psv;
1400  int* sing = temp.s_mark;
1401 
1402  /* Initialize:
1403  * - column file thereby remembering column singletons in |sing|.
1404  * - nonzeros counts per row
1405  * - total number of nonzeros
1406  */
1407 
1408  for(int i = 0; i < thedim; i++)
1409  u.row.max[i] = u.row.len[i] = 0;
1410 
1411  tot = 0;
1412 
1413  for(int i = 0; i < thedim; i++)
1414  {
1415  int k;
1416 
1417  psv = vec[i];
1418  k = psv->size();
1419 
1420  if(k > 1)
1421  {
1422  tot += k;
1423 
1424  for(int j = 0; j < k; ++j)
1425  u.row.max[psv->index(j)]++;
1426  }
1427  else if(k == 0)
1428  {
1430  return;
1431  }
1432  }
1433 
1434  /* Resize nonzero memory if necessary
1435  */
1436  minRowMem(int(rowMemMult * tot));
1437 
1438  minColMem(int(colMemMult * tot));
1439 
1440  minLMem(int(lMemMult * tot));
1441 
1442 
1443  /* Initialize:
1444  * - row ring lists
1445  * - row vectors in file
1446  * - column ring lists
1447  */
1448  u.row.start[0] = 0;
1449 
1450  rring = u.row.elem;
1451 
1452  lastrring = &(u.row.list);
1453 
1454  lastrring->idx = thedim;
1455 
1456  lastrring->next = rring;
1457 
1458  cring = u.col.elem;
1459 
1460  lastcring = &(u.col.list);
1461 
1462  lastcring->idx = thedim;
1463 
1464  lastcring->next = cring;
1465 
1466  m = 0;
1467 
1468  for(int i = 0; i < thedim; i++)
1469  {
1470  u.row.start[i] = m;
1471  m += u.row.max[i];
1472 
1473  rring->idx = i;
1474  rring->prev = lastrring;
1475  lastrring->next = rring;
1476  lastrring = rring;
1477  ++rring;
1478 
1479  cring->idx = i;
1480  cring->prev = lastcring;
1481  lastcring->next = cring;
1482  lastcring = cring;
1483  ++cring;
1484  }
1485 
1486  u.row.start[thedim] = 0;
1487 
1488  u.row.max[thedim] = 0;
1489  u.row.used = m;
1490 
1491  lastrring->next = &(u.row.list);
1492  lastrring->next->prev = lastrring;
1493 
1494  lastcring->next = &(u.col.list);
1495  lastcring->next->prev = lastcring;
1496 
1497  /* Copy matrix to row and column file
1498  * excluding and marking column singletons!
1499  */
1500  m = 0;
1501  temp.stage = 0;
1502 
1503  initMaxabs = 0;
1504 
1505  for(int i = 0; i < thedim; i++)
1506  {
1507  int nnonzeros;
1508 
1509  psv = vec[i];
1510  u.col.start[i] = m;
1511 
1512  /* check whether number of nonzeros above tolerance is 0, 1 or >= 2 */
1513  nnonzeros = 0;
1514 
1515  for(int j = 0; j < psv->size() && nnonzeros <= 1; j++)
1516  {
1517  if(isNotZero(psv->value(j), eps))
1518  nnonzeros++;
1519  }
1520 
1521  /* basis is singular due to empty column */
1522  if(nnonzeros == 0)
1523  {
1525  return;
1526  }
1527 
1528  /* exclude column singletons */
1529  else if(nnonzeros == 1)
1530  {
1531  int j;
1532 
1533  /* find nonzero */
1534 
1535  for(j = 0; isZero(psv->value(j), eps); j++)
1536  ;
1537 
1538  assert(j < psv->size());
1539 
1540  /* basis is singular due to two linearly dependent column singletons */
1541  if(row.perm[psv->index(j)] >= 0)
1542  {
1544  return;
1545  }
1546 
1547  /* update maximum absolute nonzero value */
1548  x = psv->value(j);
1549 
1550  if(spxAbs(x) > initMaxabs)
1551  initMaxabs = spxAbs(x);
1552 
1553  /* permute to front and mark as singleton */
1554  setPivot(temp.stage, i, psv->index(j), x);
1555 
1556  sing[temp.stage] = i;
1557 
1558  temp.stage++;
1559 
1560  /* set column length to zero */
1561  temp.s_cact[i] = u.col.len[i] = u.col.max[i] = 0;
1562  }
1563 
1564  /* add to active matrix if not a column singleton */
1565  else
1566  {
1567  int end;
1568  int k;
1569 
1570  /* go through all nonzeros in column */
1571  assert(nnonzeros >= 2);
1572  nnonzeros = 0;
1573 
1574  for(int j = 0; j < psv->size(); j++)
1575  {
1576  x = psv->value(j);
1577 
1578  if(isNotZero(x, eps))
1579  {
1580  /* add to column array */
1581  k = psv->index(j);
1582  u.col.idx[m] = k;
1583  m++;
1584 
1585  /* add to row array */
1586  end = u.row.start[k] + u.row.len[k];
1587  u.row.idx[end] = i;
1588  u.row.val[end] = x;
1589  u.row.len[k]++;
1590 
1591  /* update maximum absolute nonzero value */
1592 
1593  if(spxAbs(x) > initMaxabs)
1594  initMaxabs = spxAbs(x);
1595 
1596  nnonzeros++;
1597  }
1598  }
1599 
1600  assert(nnonzeros >= 2);
1601 
1602  /* set column length */
1603  temp.s_cact[i] = u.col.len[i] = u.col.max[i] = nnonzeros;
1604  }
1605  }
1606 
1607  u.col.used = m;
1608 }
1609 
1610 
1611 
1612 /*****************************************************************************/
1613 /*
1614  * Remove column singletons
1615  */
1616 
1618 {
1619  int i, j, k, n;
1620  int len;
1621  int p_col, p_row, newrow;
1622  int* idx;
1623  int* rorig = row.orig;
1624  int* rperm = row.perm;
1625  int* sing = temp.s_mark;
1626 
1627 
1628  /* Iteratively update column counts due to removed column singletons
1629  * thereby removing new arising columns singletons
1630  * and computing the index of the first row singleton (-1)
1631  * until no more can be found.
1632  */
1633 
1634  for(i = 0; i < temp.stage; ++i)
1635  {
1636  p_row = rorig[i];
1637  assert(p_row >= 0);
1638  idx = &(u.row.idx[u.row.start[p_row]]);
1639  len = u.row.len[p_row];
1640 
1641  for(j = 0; j < len; ++j)
1642  {
1643  /* Move pivotal nonzeros to front of column.
1644  */
1645  p_col = idx[j];
1646  assert(temp.s_cact[p_col] > 0);
1647 
1648  n = u.col.start[p_col] + u.col.len[p_col] - temp.s_cact[p_col];
1649 
1650  for(k = n; u.col.idx[k] != p_row; ++k)
1651  ;
1652 
1653  assert(k < u.col.start[p_col] + u.col.len[p_col]);
1654 
1655  u.col.idx[k] = u.col.idx[n];
1656 
1657  u.col.idx[n] = p_row;
1658 
1659  n = --(temp.s_cact[p_col]); /* column nonzeros of ACTIVE matrix */
1660 
1661  if(n == 1) /* Here is another singleton */
1662  {
1663  newrow = u.col.idx[--u.col.len[p_col] + u.col.start[p_col]];
1664 
1665  /* Ensure, matrix not singular
1666  */
1667 
1668  if(rperm[newrow] >= 0)
1669  {
1671  return;
1672  }
1673 
1674  /* Find singleton in row.
1675  */
1676  n = u.row.start[newrow] + (--(u.row.len[newrow]));
1677 
1678  for(k = n; u.row.idx[k] != p_col; --k)
1679  ;
1680 
1681  /* Remove singleton from column.
1682  */
1683  setPivot(temp.stage, p_col, newrow, u.row.val[k]);
1684 
1685  sing[temp.stage++] = p_col;
1686 
1687  /* Move pivot element to diag.
1688  */
1689  u.row.val[k] = u.row.val[n];
1690 
1691  u.row.idx[k] = u.row.idx[n];
1692  }
1693  else if(n == 0)
1694  {
1696  return;
1697  }
1698  }
1699  }
1700 
1701  assert(temp.stage <= thedim);
1702 }
1703 
1704 
1705 /*****************************************************************************/
1706 /*
1707  * Remove row singletons
1708  */
1710 {
1711  Real pval;
1712  int i, j, k, ll, r;
1713  int p_row, p_col, len, rs, lk;
1714  int* idx;
1715  int* rperm = row.perm;
1716  int* sing = temp.s_mark;
1717 
1718  /* Mark row singletons
1719  */
1720  rs = temp.stage;
1721 
1722  for(i = 0; i < thedim; ++i)
1723  {
1724  if(rperm[i] < 0 && u.row.len[i] == 1)
1725  sing[temp.stage++] = i;
1726  }
1727 
1728  /* Eliminate row singletons
1729  * thereby marking newly arising ones
1730  * until no more can be found.
1731  */
1732  for(; rs < temp.stage; ++rs)
1733  {
1734  /* Move pivot element from row file to diag
1735  */
1736  p_row = sing[rs];
1737  j = u.row.start[p_row];
1738  p_col = u.row.idx[j];
1739  pval = u.row.val[j];
1740  setPivot(rs, p_col, p_row, pval);
1741  u.row.len[p_row] = 0;
1742 
1743  /* Remove pivot column form workingmatrix
1744  * thereby building up L vector.
1745  */
1746  idx = &(u.col.idx[u.col.start[p_col]]);
1747  i = temp.s_cact[p_col]; /* nr. nonzeros of new L vector */
1748  lk = makeLvec(i - 1, p_row);
1749  len = u.col.len[p_col];
1750  i = (u.col.len[p_col] -= i); /* remove pivot column from U */
1751 
1752  for(; i < len; ++i)
1753  {
1754  r = idx[i];
1755 
1756  if(r != p_row)
1757  {
1758  /* Find pivot column in row.
1759  */
1760  ll = --(u.row.len[r]);
1761  k = u.row.start[r] + ll;
1762 
1763  for(j = k; u.row.idx[j] != p_col; --j)
1764  ;
1765 
1766  assert(k >= u.row.start[r]);
1767 
1768  /* Initialize L vector
1769  */
1770  l.idx[lk] = r;
1771 
1772  l.val[lk] = u.row.val[j] / pval;
1773 
1774  ++lk;
1775 
1776  /* Remove pivot column from row.
1777  */
1778  u.row.idx[j] = u.row.idx[k];
1779 
1780  u.row.val[j] = u.row.val[k];
1781 
1782  /* Check new row length.
1783  */
1784  if(ll == 1)
1785  sing[temp.stage++] = r;
1786  else if(ll == 0)
1787  {
1789  return;
1790  }
1791  }
1792  }
1793  }
1794 }
1795 
1796 
1797 /*****************************************************************************/
1798 /*
1799  * Init nonzero number Ring lists
1800  * and required entries of arrays max and mark
1801  */
1802 
1804 {
1805  int i;
1806  int* rperm = row.perm;
1807  int* cperm = col.perm;
1808  CLUFactor::Pring* ring;
1809 
1810  assert(thedim >= 0);
1815 
1816  for(i = thedim - temp.stage; i >= 0; --i)
1817  {
1818  initDR(temp.pivot_colNZ[i]);
1819  initDR(temp.pivot_rowNZ[i]);
1820  }
1821 
1822  for(i = 0; i < thedim; ++i)
1823  {
1824  if(rperm[i] < 0)
1825  {
1826  if(u.row.len[i] <= 0)
1827  {
1829  return;
1830  }
1831 
1832  ring = &(temp.pivot_rowNZ[u.row.len[i]]);
1833 
1834  init2DR(temp.pivot_row[i], *ring);
1835  temp.pivot_row[i].idx = i;
1836  temp.s_max[i] = -1;
1837  }
1838 
1839  if(cperm[i] < 0)
1840  {
1841  if(temp.s_cact[i] <= 0)
1842  {
1844  return;
1845  }
1846 
1847  ring = &(temp.pivot_colNZ[temp.s_cact[i]]);
1848 
1849  init2DR(temp.pivot_col[i], *ring);
1850  temp.pivot_col[i].idx = i;
1851  temp.s_mark[i] = 0;
1852  }
1853  }
1854 }
1855 
1857 {
1858 
1859  if(temp.pivot_col)
1861 
1862  if(temp.pivot_colNZ)
1864 
1865  if(temp.pivot_row)
1867 
1868  if(temp.pivot_rowNZ)
1870 }
1871 
1872 
1873 /*
1874  * Eliminate all row singletons from nucleus.
1875  * A row singleton may well be column singleton at the same time!
1876  */
1878 {
1879  int i, j, k, ll, r;
1880  int len, lk;
1881  int pcol, prow;
1882  Real pval;
1883  int* idx;
1884  CLUFactor::Pring* sing;
1885 
1886  for(sing = temp.pivot_rowNZ[1].prev; sing != &(temp.pivot_rowNZ[1]); sing = sing->prev)
1887  {
1888  prow = sing->idx;
1889  i = u.row.start[prow];
1890  pcol = u.row.idx[i];
1891  pval = u.row.val[i];
1892  setPivot(temp.stage++, pcol, prow, pval);
1893  u.row.len[prow] = 0;
1894  removeDR(temp.pivot_col[pcol]);
1895 
1896  /* Eliminate pivot column and build L vector.
1897  */
1898  i = temp.s_cact[pcol];
1899 
1900  if(i > 1)
1901  {
1902  idx = &(u.col.idx[u.col.start[pcol]]);
1903  len = u.col.len[pcol];
1904  lk = makeLvec(i - 1, prow);
1905  i = u.col.len[pcol] -= i;
1906 
1907  for(; (r = idx[i]) != prow; ++i)
1908  {
1909  /* Find pivot column in row.
1910  */
1911  ll = --(u.row.len[r]);
1912  k = u.row.start[r] + ll;
1913 
1914  for(j = k; u.row.idx[j] != pcol; --j)
1915  ;
1916 
1917  assert(j >= u.row.start[r]);
1918 
1919  /* Initialize L vector
1920  */
1921  l.idx[lk] = r;
1922 
1923  l.val[lk] = u.row.val[j] / pval;
1924 
1925  ++lk;
1926 
1927  /* Remove pivot column from row.
1928  */
1929  u.row.idx[j] = u.row.idx[k];
1930 
1931  u.row.val[j] = u.row.val[k];
1932 
1933  /* Move column to appropriate nonzero ring.
1934  */
1935  removeDR(temp.pivot_row[r]);
1936 
1938 
1939  assert(row.perm[r] < 0);
1940 
1941  temp.s_max[r] = -1;
1942  }
1943 
1944  /* skip pivot element */
1945  assert(i < len && "ERROR: pivot column does not contain pivot row");
1946 
1947  for(++i; i < len; ++i)
1948  {
1949  /* Find pivot column in row.
1950  */
1951  r = idx[i];
1952  ll = --(u.row.len[r]);
1953  k = u.row.start[r] + ll;
1954 
1955  for(j = k; u.row.idx[j] != pcol; --j)
1956  ;
1957 
1958  assert(j >= u.row.start[r]);
1959 
1960  /* Initialize L vector
1961  */
1962  l.idx[lk] = r;
1963 
1964  l.val[lk] = u.row.val[j] / pval;
1965 
1966  ++lk;
1967 
1968  /* Remove pivot column from row.
1969  */
1970  u.row.idx[j] = u.row.idx[k];
1971 
1972  u.row.val[j] = u.row.val[k];
1973 
1974  /* Move column to appropriate nonzero ring.
1975  */
1976  removeDR(temp.pivot_row[r]);
1977 
1979 
1980  assert(row.perm[r] < 0);
1981 
1982  temp.s_max[r] = -1;
1983  }
1984  }
1985  else
1986  u.col.len[pcol] -= i;
1987  }
1988 
1989  initDR(temp.pivot_rowNZ[1]); /* Remove all row singletons from list */
1990 }
1991 
1992 
1993 
1994 /*
1995  * Eliminate all column singletons from nucleus.
1996  * A column singleton must not be row singleton at the same time!
1997  */
1999 {
2000  int i, j, k, m, c;
2001  int pcol, prow;
2002  CLUFactor::Pring* sing;
2003 
2004  for(sing = temp.pivot_colNZ[1].prev;
2005  sing != &(temp.pivot_colNZ[1]);
2006  sing = sing->prev)
2007  {
2008  /* Find pivot value
2009  */
2010  pcol = sing->idx;
2011  j = --(u.col.len[pcol]) + u.col.start[pcol]; /* remove pivot column */
2012  prow = u.col.idx[j];
2013  removeDR(temp.pivot_row[prow]);
2014 
2015  j = --(u.row.len[prow]) + u.row.start[prow];
2016 
2017  for(i = j; (c = u.row.idx[i]) != pcol; --i)
2018  {
2019  m = u.col.len[c] + u.col.start[c] - (temp.s_cact[c])--;
2020 
2021  for(k = m; u.col.idx[k] != prow; ++k)
2022  ;
2023 
2024  u.col.idx[k] = u.col.idx[m];
2025 
2026  u.col.idx[m] = prow;
2027 
2028  m = temp.s_cact[c];
2029 
2030  removeDR(temp.pivot_col[c]);
2031 
2033 
2034  assert(col.perm[c] < 0);
2035  }
2036 
2037  /* remove pivot element from pivot row
2038  */
2039  setPivot(temp.stage++, pcol, prow, u.row.val[i]);
2040 
2041  u.row.idx[i] = u.row.idx[j];
2042 
2043  u.row.val[i] = u.row.val[j];
2044 
2045  j = u.row.start[prow];
2046 
2047  for(--i; i >= j; --i)
2048  {
2049  c = u.row.idx[i];
2050  m = u.col.len[c] + u.col.start[c] - (temp.s_cact[c])--;
2051 
2052  for(k = m; u.col.idx[k] != prow; ++k)
2053  ;
2054 
2055  u.col.idx[k] = u.col.idx[m];
2056 
2057  u.col.idx[m] = prow;
2058 
2059  m = temp.s_cact[c];
2060 
2061  removeDR(temp.pivot_col[c]);
2062 
2064 
2065  assert(col.perm[c] < 0);
2066  }
2067  }
2068 
2069  initDR(temp.pivot_colNZ[1]); /* Remove all column singletons from list */
2070 }
2071 
2072 /*
2073  * No singletons available: Select pivot elements.
2074  */
2076 {
2077  int ii;
2078  int i;
2079  int j;
2080  int k;
2081  int ll = -1; // This value should never be used.
2082  int kk;
2083  int m;
2084  int count;
2085  int num;
2086  int rw = -1; // This value should never be used.
2087  int cl = -1; // This value should never be used.
2088  int len;
2089  int beg;
2090  Real l_maxabs;
2091  Real x = REAL(0.0); // This value should never be used.
2092  int mkwtz;
2093  int candidates;
2094 
2095  candidates = thedim - temp.stage - 1;
2096 
2097  if(candidates > 4)
2098  candidates = 4;
2099 
2100  num = 0;
2101 
2102  count = 2;
2103 
2104  for(;;)
2105  {
2106  ii = -1;
2107 
2108  if(temp.pivot_rowNZ[count].next != &(temp.pivot_rowNZ[count]))
2109  {
2110  rw = temp.pivot_rowNZ[count].next->idx;
2111  beg = u.row.start[rw];
2112  len = u.row.len[rw] + beg - 1;
2113 
2114  /* set l_maxabs to maximum absolute value in row
2115  * (compute it if necessary).
2116  */
2117 
2118  if((l_maxabs = temp.s_max[rw]) < 0)
2119  {
2120  l_maxabs = spxAbs(u.row.val[len]);
2121 
2122  for(i = len - 1; i >= beg; --i)
2123  if(l_maxabs < spxAbs(u.row.val[i]))
2124  l_maxabs = spxAbs(u.row.val[i]);
2125 
2126  temp.s_max[rw] = l_maxabs; /* ##### */
2127  }
2128 
2129  l_maxabs *= threshold;
2130 
2131  /* select pivot element with lowest markowitz number in row
2132  */
2133  mkwtz = thedim + 1;
2134 
2135  for(i = len; i >= beg; --i)
2136  {
2137  k = u.row.idx[i];
2138  j = temp.s_cact[k];
2139  x = u.row.val[i];
2140 
2141  if(j < mkwtz && spxAbs(x) > l_maxabs)
2142  {
2143  mkwtz = j;
2144  cl = k;
2145  ii = i;
2146 
2147  if(j <= count) /* ##### */
2148  break;
2149  }
2150  }
2151  }
2152  else if(temp.pivot_colNZ[count].next != &(temp.pivot_colNZ[count]))
2153  {
2154  cl = temp.pivot_colNZ[count].next->idx;
2155  beg = u.col.start[cl];
2156  len = u.col.len[cl] + beg - 1;
2157  beg = len - temp.s_cact[cl] + 1;
2158  assert(count == temp.s_cact[cl]);
2159 
2160  /* select pivot element with lowest markowitz number in column
2161  */
2162  mkwtz = thedim + 1;
2163 
2164  for(i = len; i >= beg; --i)
2165  {
2166  k = u.col.idx[i];
2167  j = u.row.len[k];
2168 
2169  if(j < mkwtz)
2170  {
2171  /* ensure that element (cl,k) is stable.
2172  */
2173  if(temp.s_max[k] > 0)
2174  {
2175  /* case 1: l_maxabs is known
2176  */
2177  for(m = u.row.start[k], kk = m + u.row.len[k] - 1;
2178  kk >= m; --kk)
2179  {
2180  if(u.row.idx[kk] == cl)
2181  {
2182  x = u.row.val[kk];
2183  ll = kk;
2184  break;
2185  }
2186  }
2187 
2188  l_maxabs = temp.s_max[k];
2189  }
2190  else
2191  {
2192  /* case 2: l_maxabs needs to be computed
2193  */
2194  m = u.row.start[k];
2195  l_maxabs = spxAbs(u.row.val[m]);
2196 
2197  for(kk = m + u.row.len[k] - 1; kk >= m; --kk)
2198  {
2199  if(l_maxabs < spxAbs(u.row.val[kk]))
2200  l_maxabs = spxAbs(u.row.val[kk]);
2201 
2202  if(u.row.idx[kk] == cl)
2203  {
2204  x = u.row.val[kk];
2205  ll = kk;
2206  break;
2207  }
2208  }
2209 
2210  for(--kk; kk > m; --kk)
2211  {
2212  if(l_maxabs < spxAbs(u.row.val[kk]))
2213  l_maxabs = spxAbs(u.row.val[kk]);
2214  }
2215 
2216  temp.s_max[k] = l_maxabs;
2217  }
2218 
2219  l_maxabs *= threshold;
2220 
2221  if(spxAbs(x) > l_maxabs)
2222  {
2223  mkwtz = j;
2224  rw = k;
2225  ii = ll;
2226 
2227  if(j <= count + 1)
2228  break;
2229  }
2230  }
2231  }
2232  }
2233  else
2234  {
2235  ++count;
2236  continue;
2237  }
2238 
2239  assert(cl >= 0);
2240 
2241  removeDR(temp.pivot_col[cl]);
2242  initDR(temp.pivot_col[cl]);
2243 
2244  if(ii >= 0)
2245  {
2246  /* Initialize selected pivot element
2247  */
2248  CLUFactor::Pring* pr;
2249  temp.pivot_row[rw].pos = ii - u.row.start[rw];
2250  temp.pivot_row[rw].mkwtz = mkwtz = (mkwtz - 1) * (count - 1);
2251  // ??? mkwtz originally was long,
2252  // maybe to avoid an overflow in this instruction?
2253 
2254  for(pr = temp.pivots.next; pr->idx >= 0; pr = pr->next)
2255  {
2256  if(pr->idx == rw || pr->mkwtz >= mkwtz)
2257  break;
2258  }
2259 
2260  pr = pr->prev;
2261 
2262  if(pr->idx != rw)
2263  {
2264  removeDR(temp.pivot_row[rw]);
2265  init2DR(temp.pivot_row[rw], *pr);
2266  }
2267 
2268  num++;
2269 
2270  if(num >= candidates)
2271  break;
2272  }
2273  }
2274 
2275  /*
2276  * while(temp.temp.next->mkwtz < temp.temp.prev->mkwtz)
2277  * {
2278  * Pring *pr;
2279  * pr = temp.temp.prev;
2280  * removeDR(*pr);
2281  * init2DR (*pr, rowNZ[u.row.len[pr->idx]]);
2282  }
2283  */
2284 
2285  assert(row.perm[rw] < 0);
2286 
2287  assert(col.perm[cl] < 0);
2288 }
2289 
2290 
2291 /*
2292  * Perform L and update loop for row r
2293  */
2295  int lv,
2296  int prow,
2297  int pcol,
2298  Real pval,
2299  Real eps)
2300 {
2301  int fill;
2302  Real x, lx;
2303  int c, i, j, k, ll, m, n;
2304 
2305  n = u.row.start[r];
2306  m = --(u.row.len[r]) + n;
2307 
2308  /* compute L vector entry and
2309  * and remove pivot column form row file
2310  */
2311 
2312  for(j = m; u.row.idx[j] != pcol; --j)
2313  ;
2314 
2315  lx = u.row.val[j] / pval;
2316 
2317  l.val[lv] = lx;
2318 
2319  l.idx[lv] = r;
2320 
2321  ++lv;
2322 
2323  u.row.idx[j] = u.row.idx[m];
2324 
2325  u.row.val[j] = u.row.val[m];
2326 
2327 
2328  /* update loop (I) and
2329  * computing expected fill
2330  */
2331  fill = u.row.len[prow];
2332 
2333  for(j = m - 1; j >= n; --j)
2334  {
2335  c = u.row.idx[j];
2336 
2337  if(temp.s_mark[c])
2338  {
2339  /* count fill elements.
2340  */
2341  temp.s_mark[c] = 0;
2342  --fill;
2343 
2344  /* update row values
2345  */
2346  x = u.row.val[j] -= work[c] * lx;
2347 
2348  if(isZero(x, eps))
2349  {
2350  /* Eliminate zero from row r
2351  */
2352  --u.row.len[r];
2353  --m;
2354  u.row.val[j] = u.row.val[m];
2355  u.row.idx[j] = u.row.idx[m];
2356 
2357  /* Eliminate zero from column c
2358  */
2359  --(temp.s_cact[c]);
2360  k = --(u.col.len[c]) + u.col.start[c];
2361 
2362  for(i = k; u.col.idx[i] != r; --i)
2363  ;
2364 
2365  u.col.idx[i] = u.col.idx[k];
2366  }
2367  }
2368  }
2369 
2370 
2371  /* create space for fill in row file
2372  */
2373  ll = u.row.len[r];
2374 
2375  if(ll + fill > u.row.max[r])
2376  remaxRow(r, ll + fill);
2377 
2378  ll += u.row.start[r];
2379 
2380  /* fill creating update loop (II)
2381  */
2382  for(j = u.row.start[prow], m = j + u.row.len[prow]; j < m; ++j)
2383  {
2384  c = u.row.idx[j];
2385 
2386  if(temp.s_mark[c])
2387  {
2388  x = - work[c] * lx;
2389 
2390  if(isNotZero(x, eps))
2391  {
2392  /* produce fill element in row r
2393  */
2394  u.row.val[ll] = x;
2395  u.row.idx[ll] = c;
2396  ll++;
2397  u.row.len[r]++;
2398 
2399  /* produce fill element in column c
2400  */
2401 
2402  if(u.col.len[c] >= u.col.max[c])
2403  remaxCol(c, u.col.len[c] + 1);
2404 
2405  u.col.idx[u.col.start[c] + (u.col.len[c])++] = r;
2406 
2407  temp.s_cact[c]++;
2408  }
2409  }
2410  else
2411  temp.s_mark[c] = 1;
2412  }
2413 
2414  /* move row to appropriate list.
2415  */
2416  removeDR(temp.pivot_row[r]);
2417 
2419 
2420  assert(row.perm[r] < 0);
2421 
2422  temp.s_max[r] = -1;
2423 
2424  return lv;
2425 }
2426 
2427 /*
2428  * Eliminate pivot element
2429  */
2430 void CLUFactor::eliminatePivot(int prow, int pos, Real eps)
2431 {
2432  int i, j, k, m = -1;
2433  int lv = -1; // This value should never be used.
2434  int pcol;
2435  Real pval;
2436  int pbeg = u.row.start[prow];
2437  int plen = --(u.row.len[prow]);
2438  int pend = pbeg + plen;
2439 
2440 
2441  /* extract pivot element */
2442  i = pbeg + pos;
2443  pcol = u.row.idx[i];
2444  pval = u.row.val[i];
2445  removeDR(temp.pivot_col[pcol]);
2446  initDR(temp.pivot_col[pcol]);
2447 
2448  /* remove pivot from pivot row */
2449  u.row.idx[i] = u.row.idx[pend];
2450  u.row.val[i] = u.row.val[pend];
2451 
2452  /* set pivot element and construct L vector */
2453  setPivot(temp.stage++, pcol, prow, pval);
2454 
2455  /**@todo If this test failes, lv has no value. I suppose that in this
2456  * case none of the loops below that uses lv is executed.
2457  * But this is unproven.
2458  */
2459 
2460  if(temp.s_cact[pcol] - 1 > 0)
2461  lv = makeLvec(temp.s_cact[pcol] - 1, prow);
2462 
2463  /* init working vector,
2464  * remove pivot row from working matrix
2465  * and remove columns from list.
2466  */
2467  for(i = pbeg; i < pend; ++i)
2468  {
2469  j = u.row.idx[i];
2470  temp.s_mark[j] = 1;
2471  work[j] = u.row.val[i];
2472  removeDR(temp.pivot_col[j]);
2473  m = u.col.start[j] + u.col.len[j] - temp.s_cact[j];
2474 
2475  for(k = m; u.col.idx[k] != prow; ++k)
2476  ;
2477 
2478  u.col.idx[k] = u.col.idx[m];
2479 
2480  u.col.idx[m] = prow;
2481 
2482  temp.s_cact[j]--;
2483  }
2484 
2485  /* perform L and update loop
2486  */
2487  for(i = u.col.len[pcol] - temp.s_cact[pcol];
2488  (m = u.col.idx[u.col.start[pcol] + i]) != prow;
2489  ++i)
2490  {
2491  assert(row.perm[m] < 0);
2492  assert(lv >= 0);
2493  updateRow(m, lv++, prow, pcol, pval, eps);
2494  }
2495 
2496  /* skip pivot row */
2497 
2498  m = u.col.len[pcol];
2499 
2500  for(++i; i < m; ++i)
2501  {
2502  assert(lv >= 0);
2503  updateRow(u.col.idx[u.col.start[pcol] + i], lv++, prow, pcol, pval, eps);
2504  }
2505 
2506  /* remove pivot column from column file.
2507  */
2508  u.col.len[pcol] -= temp.s_cact[pcol];
2509 
2510  /* clear working vector and reinsert columns to lists
2511  */
2512  for(i = u.row.start[prow], pend = i + plen; i < pend; ++i)
2513  {
2514  j = u.row.idx[i];
2515  work[j] = 0;
2516  temp.s_mark[j] = 0;
2518  assert(col.perm[j] < 0);
2519  }
2520 }
2521 
2522 
2523 /*
2524  * Factorize nucleus.
2525  */
2527  const Real threshold)
2528 {
2529  int r, c;
2530  CLUFactor::Pring* pivot;
2531 
2532  if(stat == SLinSolver::SINGULAR)
2533  return;
2534 
2535  temp.pivots.mkwtz = -1;
2536 
2537  temp.pivots.idx = -1;
2538 
2539  temp.pivots.pos = -1;
2540 
2541  while(temp.stage < thedim - 1)
2542  {
2543 #ifndef NDEBUG
2544  int i;
2545  // CLUFactorIsConsistent(fac);
2546 
2547  for(i = 0; i < thedim; ++i)
2548  if(col.perm[i] < 0)
2549  assert(temp.s_mark[i] == 0);
2550 
2551 #endif
2552 
2553  if(temp.pivot_rowNZ[1].next != &(temp.pivot_rowNZ[1]))
2554  /* row singleton available */
2556  else if(temp.pivot_colNZ[1].next != &(temp.pivot_colNZ[1]))
2557  /* column singleton available */
2559  else
2560  {
2561  initDR(temp.pivots);
2562  selectPivots(threshold);
2563 
2564  assert(temp.pivots.next != &temp.pivots &&
2565  "ERROR: no pivot element selected");
2566 
2567  for(pivot = temp.pivots.next; pivot != &temp.pivots;
2568  pivot = pivot->next)
2569  {
2570  eliminatePivot(pivot->idx, pivot->pos, eps);
2571  }
2572  }
2573 
2576  {
2578  return;
2579  }
2580  }
2581 
2582  if(temp.stage < thedim)
2583  {
2584  /* Eliminate remaining element.
2585  * Note, that this must be both, column and row singleton.
2586  */
2587  assert(temp.pivot_rowNZ[1].next != &(temp.pivot_rowNZ[1]) &&
2588  "ERROR: one row must be left");
2589  assert(temp.pivot_colNZ[1].next != &(temp.pivot_colNZ[1]) &&
2590  "ERROR: one col must be left");
2591  r = temp.pivot_rowNZ[1].next->idx;
2592  c = temp.pivot_colNZ[1].next->idx;
2593  u.row.len[r] = 0;
2594  u.col.len[c]--;
2595  setPivot(temp.stage, c, r, u.row.val[u.row.start[r]]);
2596  }
2597 }
2598 
2599 /*****************************************************************************/
2600 
2602 {
2603  int i;
2604  int n = thedim;
2605 
2606  if(u.col.val != 0)
2607  spx_free(u.col.val);
2608 
2609  // if we would know the old size of u.col.val, this could be a realloc.
2610  spx_alloc(u.col.val, u.col.size);
2611 
2612  for(i = 0; i < thedim; i++)
2613  u.col.len[i] = 0;
2614 
2615  maxabs = REAL(0.0);
2616 
2617  for(i = 0; i < thedim; i++)
2618  {
2619  int k = u.row.start[i];
2620  int* idx = &u.row.idx[k];
2621  Real* val = &u.row.val[k];
2622  int len = u.row.len[i];
2623 
2624  n += len;
2625 
2626  while(len-- > 0)
2627  {
2628  assert((*idx >= 0) && (*idx < thedim));
2629 
2630  k = u.col.start[*idx] + u.col.len[*idx];
2631 
2632  assert((k >= 0) && (k < u.col.size));
2633 
2634  u.col.len[*idx]++;
2635 
2636  assert(u.col.len[*idx] <= u.col.max[*idx]);
2637 
2638  u.col.idx[k] = i;
2639  u.col.val[k] = *val;
2640 
2641  if(spxAbs(*val) > maxabs)
2642  maxabs = spxAbs(*val);
2643 
2644  idx++;
2645 
2646  val++;
2647  }
2648  }
2649 
2650  return n;
2651 }
2652 
2653 /*****************************************************************************/
2654 
2655 #ifdef WITH_L_ROWS
2657 {
2658  int i, j, k, m;
2659  int vecs, mem;
2660  int* l_row;
2661  int* idx;
2662  Real* val;
2663  int* beg;
2664  int* l_ridx;
2665  Real* l_rval;
2666  int* l_rbeg;
2667  int* rorig;
2668  int* rrorig;
2669  int* rperm;
2670  int* rrperm;
2671 
2672  vecs = l.firstUpdate;
2673  l_row = l.row;
2674  idx = l.idx;
2675  val = l.val;
2676  beg = l.start;
2677  mem = beg[vecs];
2678 
2679  if(l.rval)
2680  spx_free(l.rval);
2681 
2682  if(l.ridx)
2683  spx_free(l.ridx);
2684 
2685  if(l.rbeg)
2686  spx_free(l.rbeg);
2687 
2688  if(l.rorig)
2689  spx_free(l.rorig);
2690 
2691  if(l.rperm)
2692  spx_free(l.rperm);
2693 
2694  spx_alloc(l.rval, mem);
2695 
2696  spx_alloc(l.ridx, mem);
2697 
2698  spx_alloc(l.rbeg, thedim + 1);
2699 
2700  spx_alloc(l.rorig, thedim);
2701 
2702  spx_alloc(l.rperm, thedim);
2703 
2704  l_ridx = l.ridx;
2705 
2706  l_rval = l.rval;
2707 
2708  l_rbeg = l.rbeg;
2709 
2710  rorig = l.rorig;
2711 
2712  rrorig = row.orig;
2713 
2714  rperm = l.rperm;
2715 
2716  rrperm = row.perm;
2717 
2718  for(i = thedim; i--; *l_rbeg++ = 0)
2719  {
2720  *rorig++ = *rrorig++;
2721  *rperm++ = *rrperm++;
2722  }
2723 
2724  *l_rbeg = 0;
2725 
2726  l_rbeg = l.rbeg + 1;
2727 
2728  for(i = mem; i--;)
2729  l_rbeg[*idx++]++;
2730 
2731  idx = l.idx;
2732 
2733  for(m = 0, i = thedim; i--; l_rbeg++)
2734  {
2735  j = *l_rbeg;
2736  *l_rbeg = m;
2737  m += j;
2738  }
2739 
2740  assert(m == mem);
2741 
2742  l_rbeg = l.rbeg + 1;
2743 
2744  for(i = j = 0; i < vecs; ++i)
2745  {
2746  m = l_row[i];
2747  assert(idx == &l.idx[l.start[i]]);
2748 
2749  for(; j < beg[i + 1]; j++)
2750  {
2751  k = l_rbeg[*idx++]++;
2752  assert(k < mem);
2753  l_ridx[k] = m;
2754  l_rval[k] = *val++;
2755  }
2756  }
2757 
2758  assert(l.rbeg[thedim] == mem);
2759 
2760  assert(l.rbeg[0] == 0);
2761 }
2762 
2763 #endif
2764 
2765 /*****************************************************************************/
2766 
2767 void CLUFactor::factor(const SVector** vec, ///< Array of column vector pointers
2768  Real threshold, ///< pivoting threshold
2769  Real eps) ///< epsilon for zero detection
2770 {
2771 
2772  factorTime->start();
2773 
2774  stat = SLinSolver::OK;
2775 
2776  l.start[0] = 0;
2777  l.firstUpdate = 0;
2778  l.firstUnused = 0;
2779 
2780  temp.init(thedim);
2781  initPerm();
2782 
2783  initFactorMatrix(vec, eps);
2784 
2785  if(stat)
2786  goto TERMINATE;
2787 
2788  // initMaxabs = initMaxabs;
2789 
2790  colSingletons();
2791 
2792  if(stat != SLinSolver::OK)
2793  goto TERMINATE;
2794 
2795  rowSingletons();
2796 
2797  if(stat != SLinSolver::OK)
2798  goto TERMINATE;
2799 
2800  if(temp.stage < thedim)
2801  {
2802  initFactorRings();
2803  eliminateNucleus(eps, threshold);
2804  freeFactorRings();
2805  }
2806 
2807 TERMINATE:
2808 
2810 
2811  if(stat == SLinSolver::OK)
2812  {
2813 #ifdef WITH_L_ROWS
2814  setupRowVals();
2815 #endif
2816  nzCnt = setupColVals();
2817  }
2818 
2819  factorTime->stop();
2820 
2821  factorCount++;
2822 }
2823 
2824 void CLUFactor::dump() const
2825 {
2826  int i, j, k;
2827 
2828  // Dump regardless of the verbosity level if this method is called;
2829 
2830  /* Dump U:
2831  */
2832 
2833  for(i = 0; i < thedim; ++i)
2834  {
2835  if(row.perm[i] >= 0)
2836  std::cout << "DCLUFA01 diag[" << i << "]: [" << col.orig[row.perm[i]]
2837  << "] = " << diag[i] << std::endl;
2838 
2839  for(j = 0; j < u.row.len[i]; ++j)
2840  std::cout << "DCLUFA02 u[" << i << "]: ["
2841  << u.row.idx[u.row.start[i] + j] << "] = "
2842  << u.row.val[u.row.start[i] + j] << std::endl;
2843  }
2844 
2845  /* Dump L:
2846  */
2847  for(i = 0; i < thedim; ++i)
2848  {
2849  for(j = 0; j < l.firstUnused; ++j)
2850  if(col.orig[row.perm[l.row[j]]] == i)
2851  {
2852  std::cout << "DCLUFA03 l[" << i << "]" << std::endl;
2853 
2854  for(k = l.start[j]; k < l.start[j + 1]; ++k)
2855  std::cout << "DCLUFA04 l[" << k - l.start[j]
2856  << "]: [" << l.idx[k]
2857  << "] = " << l.val[k] << std::endl;
2858 
2859  break;
2860  }
2861  }
2862 
2863  return;
2864 }
2865 
2866 /*****************************************************************************/
2867 /*
2868  * Ensure that row memory is at least size.
2869  */
2870 void CLUFactor::minRowMem(int size)
2871 {
2872 
2873  if(u.row.size < size)
2874  {
2875  u.row.size = size;
2876  spx_realloc(u.row.val, size);
2877  spx_realloc(u.row.idx, size);
2878  }
2879 }
2880 
2881 /*****************************************************************************/
2882 /*
2883  * Ensure that column memory is at least size.
2884  */
2885 void CLUFactor::minColMem(int size)
2886 {
2887 
2888  if(u.col.size < size)
2889  {
2890  u.col.size = size;
2891  spx_realloc(u.col.idx, size);
2892  }
2893 }
2894 
2896 {
2897 
2898  if(u.col.size < size)
2899  {
2900  u.col.size = size;
2901  spx_realloc(u.col.idx, size);
2902  spx_realloc(u.col.val, size);
2903  }
2904 }
2905 
2906 void CLUFactor::minLMem(int size)
2907 {
2908 
2909  if(size > l.size)
2910  {
2911  l.size = int(0.2 * l.size + size);
2912  spx_realloc(l.val, l.size);
2913  spx_realloc(l.idx, l.size);
2914  }
2915 }
2916 
2917 
2918 int CLUFactor::makeLvec(int p_len, int p_row)
2919 {
2920 
2921  if(l.firstUnused >= l.startSize)
2922  {
2923  l.startSize += 100;
2925  }
2926 
2927  int* p_lrow = l.row;
2928 
2929  int* p_lbeg = l.start;
2930  int first = p_lbeg[l.firstUnused];
2931 
2932  assert(p_len > 0 && "ERROR: no empty columns allowed in L vectors");
2933 
2934  minLMem(first + p_len);
2935  p_lrow[l.firstUnused] = p_row;
2936  l.start[++(l.firstUnused)] = first + p_len;
2937 
2938  assert(l.start[l.firstUnused] <= l.size);
2939  assert(l.firstUnused <= l.startSize);
2940  return first;
2941 }
2942 
2943 
2944 /*****************************************************************************/
2945 
2947 {
2948 #ifdef ENABLE_CONSISTENCY_CHECKS
2949  int i, j, k, ll;
2950  Dring* ring;
2951  CLUFactor::Pring* pring;
2952 
2953  /* Consistency only relevant for real factorizations
2954  */
2955 
2956  if(stat)
2957  return true;
2958 
2959  /* Test column ring list consistency.
2960  */
2961  i = 0;
2962 
2963  for(ring = u.col.list.next; ring != &(u.col.list); ring = ring->next)
2964  {
2965  assert(ring->idx >= 0);
2966  assert(ring->idx < thedim);
2967  assert(ring->prev->next == ring);
2968 
2969  if(ring != u.col.list.next)
2970  {
2971  assert(u.col.start[ring->prev->idx] + u.col.max[ring->prev->idx]
2972  == u.col.start[ring->idx]);
2973  }
2974 
2975  ++i;
2976  }
2977 
2978  assert(i == thedim);
2979 
2980  assert(u.col.start[ring->prev->idx] + u.col.max[ring->prev->idx]
2981  == u.col.used);
2982 
2983 
2984  /* Test row ring list consistency.
2985  */
2986  i = 0;
2987 
2988  for(ring = u.row.list.next; ring != &(u.row.list); ring = ring->next)
2989  {
2990  assert(ring->idx >= 0);
2991  assert(ring->idx < thedim);
2992  assert(ring->prev->next == ring);
2993  assert(u.row.start[ring->prev->idx] + u.row.max[ring->prev->idx]
2994  == u.row.start[ring->idx]);
2995  ++i;
2996  }
2997 
2998  assert(i == thedim);
2999 
3000  assert(u.row.start[ring->prev->idx] + u.row.max[ring->prev->idx]
3001  == u.row.used);
3002 
3003 
3004  /* Test consistency of individual svectors.
3005  */
3006 
3007  for(i = 0; i < thedim; ++i)
3008  {
3009  assert(u.row.max[i] >= u.row.len[i]);
3010  assert(u.col.max[i] >= u.col.len[i]);
3011  }
3012 
3013 
3014  /* Test consistency of column file to row file of U
3015  */
3016  for(i = 0; i < thedim; ++i)
3017  {
3018  for(j = u.row.start[i] + u.row.len[i] - 1; j >= u.row.start[i]; j--)
3019  {
3020  k = u.row.idx[j];
3021 
3022  for(ll = u.col.start[k] + u.col.len[k] - 1; ll >= u.col.start[k]; ll--)
3023  {
3024  if(u.col.idx[ll] == i)
3025  break;
3026  }
3027 
3028  assert(u.col.idx[ll] == i);
3029 
3030  if(row.perm[i] < 0)
3031  {
3032  assert(col.perm[k] < 0);
3033  }
3034  else
3035  {
3036  assert(col.perm[k] < 0 || col.perm[k] > row.perm[i]);
3037  }
3038  }
3039  }
3040 
3041  /* Test consistency of row file to column file of U
3042  */
3043  for(i = 0; i < thedim; ++i)
3044  {
3045  for(j = u.col.start[i] + u.col.len[i] - 1; j >= u.col.start[i]; j--)
3046  {
3047  k = u.col.idx[j];
3048 
3049  for(ll = u.row.start[k] + u.row.len[k] - 1; ll >= u.row.start[k]; ll--)
3050  {
3051  if(u.row.idx[ll] == i)
3052  break;
3053  }
3054 
3055  assert(u.row.idx[ll] == i);
3056 
3057  assert(col.perm[i] < 0 || row.perm[k] < col.perm[i]);
3058  }
3059  }
3060 
3061  /* Test consistency of nonzero count lists
3062  */
3064  {
3065  for(i = 0; i < thedim - temp.stage; ++i)
3066  {
3067  for(pring = temp.pivot_rowNZ[i].next; pring != &(temp.pivot_rowNZ[i]); pring = pring->next)
3068  {
3069  assert(row.perm[pring->idx] < 0);
3070  }
3071 
3072  for(pring = temp.pivot_colNZ[i].next; pring != &(temp.pivot_colNZ[i]); pring = pring->next)
3073  {
3074  assert(col.perm[pring->idx] < 0);
3075  }
3076  }
3077  }
3078 
3079 #endif // CONSISTENCY_CHECKS
3080 
3081  return true;
3082 }
3083 
3084 void CLUFactor::solveUright(Real* wrk, Real* vec) const
3085 {
3086 
3087  for(int i = thedim - 1; i >= 0; i--)
3088  {
3089  int r = row.orig[i];
3090  int c = col.orig[i];
3091  Real x = wrk[c] = diag[r] * vec[r];
3092 
3093  vec[r] = 0.0;
3094 
3095  if(x != 0.0)
3096  //if (isNotZero(x))
3097  {
3098  for(int j = u.col.start[c]; j < u.col.start[c] + u.col.len[c]; j++)
3099  vec[u.col.idx[j]] -= x * u.col.val[j];
3100  }
3101  }
3102 }
3103 
3104 int CLUFactor::solveUrightEps(Real* vec, int* nonz, Real eps, Real* rhs)
3105 {
3106  int i, j, r, c, n;
3107  int* rorig, *corig;
3108  int* cidx, *clen, *cbeg;
3109  Real* cval;
3110  Real x;
3111 
3112  int* idx;
3113  Real* val;
3114 
3115  rorig = row.orig;
3116  corig = col.orig;
3117 
3118  cidx = u.col.idx;
3119  cval = u.col.val;
3120  clen = u.col.len;
3121  cbeg = u.col.start;
3122 
3123  n = 0;
3124 
3125  for(i = thedim - 1; i >= 0; --i)
3126  {
3127  r = rorig[i];
3128  x = diag[r] * rhs[r];
3129 
3130  if(isNotZero(x, eps))
3131  {
3132  c = corig[i];
3133  vec[c] = x;
3134  nonz[n++] = c;
3135  val = &cval[cbeg[c]];
3136  idx = &cidx[cbeg[c]];
3137  j = clen[c];
3138 
3139  while(j-- > 0)
3140  rhs[*idx++] -= x * (*val++);
3141  }
3142  }
3143 
3144  return n;
3145 }
3146 
3148  Real* p_work1, Real* vec1, Real* p_work2, Real* vec2)
3149 {
3150  int i, j, r, c;
3151  int* rorig, *corig;
3152  int* cidx, *clen, *cbeg;
3153  Real* cval;
3154  Real x1, x2;
3155 
3156  int* idx;
3157  Real* val;
3158 
3159  rorig = row.orig;
3160  corig = col.orig;
3161 
3162  cidx = u.col.idx;
3163  cval = u.col.val;
3164  clen = u.col.len;
3165  cbeg = u.col.start;
3166 
3167  for(i = thedim - 1; i >= 0; --i)
3168  {
3169  r = rorig[i];
3170  c = corig[i];
3171  p_work1[c] = x1 = diag[r] * vec1[r];
3172  p_work2[c] = x2 = diag[r] * vec2[r];
3173  vec1[r] = vec2[r] = 0;
3174 
3175  if(x1 != 0.0 && x2 != 0.0)
3176  {
3177  val = &cval[cbeg[c]];
3178  idx = &cidx[cbeg[c]];
3179  j = clen[c];
3180 
3181  while(j-- > 0)
3182  {
3183  vec1[*idx] -= x1 * (*val);
3184  vec2[*idx++] -= x2 * (*val++);
3185  }
3186  }
3187  else if(x1 != 0.0)
3188  {
3189  val = &cval[cbeg[c]];
3190  idx = &cidx[cbeg[c]];
3191  j = clen[c];
3192 
3193  while(j-- > 0)
3194  vec1[*idx++] -= x1 * (*val++);
3195  }
3196  else if(x2 != 0.0)
3197  {
3198  val = &cval[cbeg[c]];
3199  idx = &cidx[cbeg[c]];
3200  j = clen[c];
3201 
3202  while(j-- > 0)
3203  vec2[*idx++] -= x2 * (*val++);
3204  }
3205  }
3206 }
3207 
3209  Real* p_work1, Real* vec1, Real* p_work2, Real* vec2,
3210  int* nonz, Real eps)
3211 {
3212  int i, j, r, c, n;
3213  int* rorig, *corig;
3214  int* cidx, *clen, *cbeg;
3215  bool notzero1, notzero2;
3216  Real* cval;
3217  Real x1, x2;
3218 
3219  int* idx;
3220  Real* val;
3221 
3222  rorig = row.orig;
3223  corig = col.orig;
3224 
3225  cidx = u.col.idx;
3226  cval = u.col.val;
3227  clen = u.col.len;
3228  cbeg = u.col.start;
3229 
3230  n = 0;
3231 
3232  for(i = thedim - 1; i >= 0; --i)
3233  {
3234  c = corig[i];
3235  r = rorig[i];
3236  p_work1[c] = x1 = diag[r] * vec1[r];
3237  p_work2[c] = x2 = diag[r] * vec2[r];
3238  vec1[r] = vec2[r] = 0;
3239  notzero1 = isNotZero(x1, eps);
3240  notzero2 = isNotZero(x2, eps);
3241 
3242  if(notzero1 && notzero2)
3243  {
3244  *nonz++ = c;
3245  n++;
3246  val = &cval[cbeg[c]];
3247  idx = &cidx[cbeg[c]];
3248  j = clen[c];
3249 
3250  while(j-- > 0)
3251  {
3252  vec1[*idx] -= x1 * (*val);
3253  vec2[*idx++] -= x2 * (*val++);
3254  }
3255  }
3256  else if(notzero1)
3257  {
3258  p_work2[c] = 0.0;
3259  *nonz++ = c;
3260  n++;
3261  val = &cval[cbeg[c]];
3262  idx = &cidx[cbeg[c]];
3263  j = clen[c];
3264 
3265  while(j-- > 0)
3266  vec1[*idx++] -= x1 * (*val++);
3267  }
3268  else if(notzero2)
3269  {
3270  p_work1[c] = 0.0;
3271  val = &cval[cbeg[c]];
3272  idx = &cidx[cbeg[c]];
3273  j = clen[c];
3274 
3275  while(j-- > 0)
3276  vec2[*idx++] -= x2 * (*val++);
3277  }
3278  else
3279  {
3280  p_work1[c] = 0.0;
3281  p_work2[c] = 0.0;
3282  }
3283  }
3284 
3285  return n;
3286 }
3287 
3289 {
3290  int i, j, k;
3291  int end;
3292  Real x;
3293  Real* lval, *val;
3294  int* lrow, *lidx, *idx;
3295  int* lbeg;
3296 
3297  lval = l.val;
3298  lidx = l.idx;
3299  lrow = l.row;
3300  lbeg = l.start;
3301 
3302  end = l.firstUpdate;
3303 
3304  for(i = 0; i < end; ++i)
3305  {
3306  if((x = vec[lrow[i]]) != 0.0)
3307  {
3308  MSG_DEBUG(std::cout << "y" << lrow[i] << "=" << vec[lrow[i]] << std::endl;)
3309 
3310  k = lbeg[i];
3311  idx = &(lidx[k]);
3312  val = &(lval[k]);
3313 
3314  for(j = lbeg[i + 1]; j > k; --j)
3315  {
3316  MSG_DEBUG(std::cout << " -> y" << *idx << " -= " << x << " * " << *val <<
3317  " = " << x * (*val) << " -> " << vec[*idx] - x * (*val) << std::endl;)
3318  vec[*idx++] -= x * (*val++);
3319  }
3320  }
3321  }
3322 
3323  if(l.updateType) /* Forest-Tomlin Updates */
3324  {
3325  MSG_DEBUG(std::cout << "performing FT updates..." << std::endl;)
3326 
3327  end = l.firstUnused;
3328 
3329  for(; i < end; ++i)
3330  {
3331  k = lbeg[i];
3332  idx = &(lidx[k]);
3333  val = &(lval[k]);
3334 
3335  StableSum<Real> tmp(-vec[lrow[i]]);
3336 
3337  for(j = lbeg[i + 1]; j > k; --j)
3338  tmp += vec[*idx++] * (*val++);
3339 
3340  vec[lrow[i]] = -tmp;
3341 
3342  MSG_DEBUG(std::cout << "y" << lrow[i] << "=" << vec[lrow[i]] << std::endl;)
3343  }
3344 
3345  MSG_DEBUG(std::cout << "finished FT updates." << std::endl;)
3346  }
3347 }
3348 
3350 {
3351  int i, j, k;
3352  int end;
3353  Real x2;
3354  Real x1;
3355  Real* lval, *val;
3356  int* lrow, *lidx, *idx;
3357  int* lbeg;
3358 
3359  lval = l.val;
3360  lidx = l.idx;
3361  lrow = l.row;
3362  lbeg = l.start;
3363 
3364  end = l.firstUpdate;
3365 
3366  for(i = 0; i < end; ++i)
3367  {
3368  x1 = vec1[lrow[i]];
3369  x2 = vec2[lrow[i]];
3370 
3371  if(x1 != 0 && x2 != 0.0)
3372  {
3373  k = lbeg[i];
3374  idx = &(lidx[k]);
3375  val = &(lval[k]);
3376 
3377  for(j = lbeg[i + 1]; j > k; --j)
3378  {
3379  vec1[*idx] -= x1 * (*val);
3380  vec2[*idx++] -= x2 * (*val++);
3381  }
3382  }
3383  else if(x1 != 0.0)
3384  {
3385  k = lbeg[i];
3386  idx = &(lidx[k]);
3387  val = &(lval[k]);
3388 
3389  for(j = lbeg[i + 1]; j > k; --j)
3390  vec1[*idx++] -= x1 * (*val++);
3391  }
3392  else if(x2 != 0.0)
3393  {
3394  k = lbeg[i];
3395  idx = &(lidx[k]);
3396  val = &(lval[k]);
3397 
3398  for(j = lbeg[i + 1]; j > k; --j)
3399  vec2[*idx++] -= x2 * (*val++);
3400  }
3401  }
3402 
3403  if(l.updateType) /* Forest-Tomlin Updates */
3404  {
3405  end = l.firstUnused;
3406 
3407  for(; i < end; ++i)
3408  {
3409  k = lbeg[i];
3410  idx = &(lidx[k]);
3411  val = &(lval[k]);
3412 
3413  StableSum<Real> tmp1(-vec1[lrow[i]]);
3414  StableSum<Real> tmp2(-vec2[lrow[i]]);
3415 
3416  for(j = lbeg[i + 1]; j > k; --j)
3417  {
3418  tmp1 += vec1[*idx] * (*val);
3419  tmp2 += vec2[*idx++] * (*val++);
3420  }
3421 
3422  vec1[lrow[i]] = -tmp1;
3423  vec2[lrow[i]] = -tmp2;
3424  }
3425  }
3426 }
3427 
3429 {
3430  int i, j, k;
3431  int end;
3432  Real x;
3433  Real* lval, *val;
3434  int* lrow, *lidx, *idx;
3435  int* lbeg;
3436 
3437  assert(!l.updateType); /* no Forest-Tomlin Updates */
3438 
3439  lval = l.val;
3440  lidx = l.idx;
3441  lrow = l.row;
3442  lbeg = l.start;
3443 
3444  end = l.firstUnused;
3445 
3446  for(i = l.firstUpdate; i < end; ++i)
3447  {
3448  if((x = vec[lrow[i]]) != 0.0)
3449  {
3450  k = lbeg[i];
3451  idx = &(lidx[k]);
3452  val = &(lval[k]);
3453 
3454  for(j = lbeg[i + 1]; j > k; --j)
3455  vec[*idx++] -= x * (*val++);
3456  }
3457  }
3458 }
3459 
3461 {
3462  int i, j, k;
3463  int end;
3464  Real x1, x2;
3465  Real* lval;
3466  int* lrow, *lidx;
3467  int* lbeg;
3468 
3469  int* idx;
3470  Real* val;
3471 
3472  assert(!l.updateType); /* no Forest-Tomlin Updates */
3473 
3474  lval = l.val;
3475  lidx = l.idx;
3476  lrow = l.row;
3477  lbeg = l.start;
3478 
3479  end = l.firstUnused;
3480 
3481  for(i = l.firstUpdate; i < end; ++i)
3482  {
3483  x1 = vec1[lrow[i]];
3484  x2 = vec2[lrow[i]];
3485 
3486  if(x1 != 0.0 && x2 != 0.0)
3487  {
3488  k = lbeg[i];
3489  idx = &(lidx[k]);
3490  val = &(lval[k]);
3491 
3492  for(j = lbeg[i + 1]; j > k; --j)
3493  {
3494  vec1[*idx] -= x1 * (*val);
3495  vec2[*idx++] -= x2 * (*val++);
3496  }
3497  }
3498  else if(x1 != 0.0)
3499  {
3500  k = lbeg[i];
3501  idx = &(lidx[k]);
3502  val = &(lval[k]);
3503 
3504  for(j = lbeg[i + 1]; j > k; --j)
3505  vec1[*idx++] -= x1 * (*val++);
3506  }
3507  else if(x2 != 0.0)
3508  {
3509  k = lbeg[i];
3510  idx = &(lidx[k]);
3511  val = &(lval[k]);
3512 
3513  for(j = lbeg[i + 1]; j > k; --j)
3514  vec2[*idx++] -= x2 * (*val++);
3515  }
3516  }
3517 }
3518 
3519 int CLUFactor::solveRight4update(Real* vec, int* nonz, Real eps,
3520  Real* rhs, Real* forest, int* forestNum, int* forestIdx)
3521 {
3522  solveLright(rhs);
3523 
3524  if(forest)
3525  {
3526  int n = 0;
3527 
3528  for(int i = 0; i < thedim; i++)
3529  {
3530  forestIdx[n] = i;
3531  forest[i] = rhs[i];
3532  n += rhs[i] != 0.0 ? 1 : 0;
3533  }
3534 
3535  *forestNum = n;
3536  }
3537 
3538  if(!l.updateType) /* no Forest-Tomlin Updates */
3539  {
3540  solveUright(vec, rhs);
3541  solveUpdateRight(vec);
3542  return 0;
3543  }
3544  else
3545  return solveUrightEps(vec, nonz, eps, rhs);
3546 }
3547 
3549 {
3550  solveLright(rhs);
3551  solveUright(vec, rhs);
3552 
3553  if(!l.updateType) /* no Forest-Tomlin Updates */
3554  solveUpdateRight(vec);
3555 }
3556 
3558  Real* vec2,
3559  Real* rhs1,
3560  Real* rhs2,
3561  int* nonz,
3562  Real eps,
3563  Real* forest,
3564  int* forestNum,
3565  int* forestIdx)
3566 {
3567  solveLright2(rhs1, rhs2);
3568 
3569  if(forest)
3570  {
3571  int n = 0;
3572 
3573  for(int i = 0; i < thedim; i++)
3574  {
3575  forestIdx[n] = i;
3576  forest[i] = rhs1[i];
3577  n += rhs1[i] != 0.0 ? 1 : 0;
3578  }
3579 
3580  *forestNum = n;
3581  }
3582 
3583  if(!l.updateType) /* no Forest-Tomlin Updates */
3584  {
3585  solveUright2(vec1, rhs1, vec2, rhs2);
3586  solveUpdateRight2(vec1, vec2);
3587  return 0;
3588  }
3589  else
3590  return solveUright2eps(vec1, rhs1, vec2, rhs2, nonz, eps);
3591 }
3592 
3594  Real* vec1,
3595  Real* vec2,
3596  Real* rhs1,
3597  Real* rhs2)
3598 {
3599  solveLright2(rhs1, rhs2);
3600 
3601  if(l.updateType) /* Forest-Tomlin Updates */
3602  solveUright2(vec1, rhs1, vec2, rhs2);
3603  else
3604  {
3605  solveUright2(vec1, rhs1, vec2, rhs2);
3606  solveUpdateRight2(vec1, vec2);
3607  }
3608 }
3609 
3610 /*****************************************************************************/
3611 void CLUFactor::solveUleft(Real* p_work, Real* vec)
3612 {
3613  for(int i = 0; i < thedim; ++i)
3614  {
3615  int c = col.orig[i];
3616  int r = row.orig[i];
3617 
3618  assert(c >= 0); // Inna/Tobi: otherwise, vec[c] would be strange...
3619  assert(r >= 0); // Inna/Tobi: otherwise, diag[r] would be strange...
3620 
3621  Real x = vec[c];
3622 
3623  ASSERT_WARN("WSOLVE01", spxAbs(vec[c]) < 1e40);
3624 
3625  vec[c] = 0.0;
3626 
3627  if(x != 0.0)
3628  {
3629  ASSERT_WARN("WSOLVE02", spxAbs(diag[r]) < 1e40);
3630 
3631  x *= diag[r];
3632  p_work[r] = x;
3633 
3634  int end = u.row.start[r] + u.row.len[r];
3635 
3636  for(int m = u.row.start[r]; m < end; m++)
3637  {
3638  vec[u.row.idx[m]] -= x * u.row.val[m];
3639  ASSERT_WARN("WSOLVE03", spxAbs(vec[u.row.idx[m]]) < 1e40);
3640  }
3641  }
3642  }
3643 }
3644 
3646  Real* p_work1, Real* vec1, Real* p_work2, Real* vec2)
3647 {
3648  Real x1;
3649  Real x2;
3650  int i, k, r, c;
3651  int* rorig, *corig;
3652  int* ridx, *rlen, *rbeg, *idx;
3653  Real* rval, *val;
3654 
3655  rorig = row.orig;
3656  corig = col.orig;
3657 
3658  ridx = u.row.idx;
3659  rval = u.row.val;
3660  rlen = u.row.len;
3661  rbeg = u.row.start;
3662 
3663  for(i = 0; i < thedim; ++i)
3664  {
3665  c = corig[i];
3666  r = rorig[i];
3667  x1 = vec1[c];
3668  x2 = vec2[c];
3669 
3670  if((x1 != 0.0) && (x2 != 0.0))
3671  {
3672  x1 *= diag[r];
3673  x2 *= diag[r];
3674  p_work1[r] = x1;
3675  p_work2[r] = x2;
3676  k = rbeg[r];
3677  idx = &ridx[k];
3678  val = &rval[k];
3679 
3680  for(int m = rlen[r]; m != 0; --m)
3681  {
3682  vec1[*idx] -= x1 * (*val);
3683  vec2[*idx] -= x2 * (*val++);
3684  idx++;
3685  }
3686  }
3687  else if(x1 != 0.0)
3688  {
3689  x1 *= diag[r];
3690  p_work1[r] = x1;
3691  k = rbeg[r];
3692  idx = &ridx[k];
3693  val = &rval[k];
3694 
3695  for(int m = rlen[r]; m != 0; --m)
3696  vec1[*idx++] -= x1 * (*val++);
3697  }
3698  else if(x2 != 0.0)
3699  {
3700  x2 *= diag[r];
3701  p_work2[r] = x2;
3702  k = rbeg[r];
3703  idx = &ridx[k];
3704  val = &rval[k];
3705 
3706  for(int m = rlen[r]; m != 0; --m)
3707  vec2[*idx++] -= x2 * (*val++);
3708  }
3709  }
3710 }
3711 
3713  Real* vec1,
3714  int* /* nonz */,
3715  Real* vec2,
3716  Real /* eps */)
3717 {
3718  int i;
3719  int j;
3720  int k;
3721  int end;
3722  Real x1, x2;
3723  Real* lval, *val;
3724  int* lidx, *idx, *lrow;
3725  int* lbeg;
3726 
3727  lval = l.val;
3728  lidx = l.idx;
3729  lrow = l.row;
3730  lbeg = l.start;
3731 
3732  end = l.firstUpdate;
3733 
3734  for(i = l.firstUnused - 1; i >= end; --i)
3735  {
3736  j = lrow[i];
3737  x1 = vec1[j];
3738  x2 = vec2[j];
3739 
3740  if(x1 != 0.0)
3741  {
3742  if(x2 != 0.0)
3743  {
3744  k = lbeg[i];
3745  val = &lval[k];
3746  idx = &lidx[k];
3747 
3748  for(j = lbeg[i + 1]; j > k; --j)
3749  {
3750  vec1[*idx] -= x1 * (*val);
3751  vec2[*idx++] -= x2 * (*val++);
3752  }
3753  }
3754  else
3755  {
3756  k = lbeg[i];
3757  val = &lval[k];
3758  idx = &lidx[k];
3759 
3760  for(j = lbeg[i + 1]; j > k; --j)
3761  vec1[*idx++] -= x1 * (*val++);
3762  }
3763  }
3764  else if(x2 != 0.0)
3765  {
3766  k = lbeg[i];
3767  val = &lval[k];
3768  idx = &lidx[k];
3769 
3770  for(j = lbeg[i + 1]; j > k; --j)
3771  vec2[*idx++] -= x2 * (*val++);
3772  }
3773  }
3774 
3775  return 0;
3776 }
3777 
3779  Real* vec1,
3780  int* /* nonz */,
3781  Real* vec2,
3782  Real /* eps */)
3783 {
3784  int i, j, k, r;
3785  int x1not0, x2not0;
3786  Real x1, x2;
3787 
3788  Real* rval, *val;
3789  int* ridx, *idx;
3790  int* rbeg;
3791  int* rorig;
3792 
3793  ridx = l.ridx;
3794  rval = l.rval;
3795  rbeg = l.rbeg;
3796  rorig = l.rorig;
3797 
3798 #ifndef WITH_L_ROWS
3799  Real* lval = l.val;
3800  int* lidx = l.idx;
3801  int* lrow = l.row;
3802  int* lbeg = l.start;
3803 
3804  i = l.firstUpdate - 1;
3805 
3806  for(; i >= 0; --i)
3807  {
3808  k = lbeg[i];
3809  val = &lval[k];
3810  idx = &lidx[k];
3811  x1 = 0;
3812  x2 = 0;
3813 
3814  for(j = lbeg[i + 1]; j > k; --j)
3815  {
3816  x1 += vec1[*idx] * (*val);
3817  x2 += vec2[*idx++] * (*val++);
3818  }
3819 
3820  vec1[lrow[i]] -= x1;
3821 
3822  vec2[lrow[i]] -= x2;
3823  }
3824 
3825 #else
3826 
3827  for(i = thedim; i--;)
3828  {
3829  r = rorig[i];
3830  x1 = vec1[r];
3831  x2 = vec2[r];
3832  x1not0 = (x1 != 0);
3833  x2not0 = (x2 != 0);
3834 
3835  if(x1not0 && x2not0)
3836  {
3837  k = rbeg[r];
3838  j = rbeg[r + 1] - k;
3839  val = &rval[k];
3840  idx = &ridx[k];
3841 
3842  while(j-- > 0)
3843  {
3844  assert(row.perm[*idx] < i);
3845  vec1[*idx] -= x1 * *val;
3846  vec2[*idx++] -= x2 * *val++;
3847  }
3848  }
3849  else if(x1not0)
3850  {
3851  k = rbeg[r];
3852  j = rbeg[r + 1] - k;
3853  val = &rval[k];
3854  idx = &ridx[k];
3855 
3856  while(j-- > 0)
3857  {
3858  assert(row.perm[*idx] < i);
3859  vec1[*idx++] -= x1 * *val++;
3860  }
3861  }
3862  else if(x2not0)
3863  {
3864  k = rbeg[r];
3865  j = rbeg[r + 1] - k;
3866  val = &rval[k];
3867  idx = &ridx[k];
3868 
3869  while(j-- > 0)
3870  {
3871  assert(row.perm[*idx] < i);
3872  vec2[*idx++] -= x2 * *val++;
3873  }
3874  }
3875  }
3876 
3877 #endif
3878 }
3879 
3880 int CLUFactor::solveLleftForest(Real* vec, int* /* nonz */, Real /* eps */)
3881 {
3882  int i, j, k, end;
3883  Real x;
3884  Real* val, *lval;
3885  int* idx, *lidx, *lrow, *lbeg;
3886 
3887  lval = l.val;
3888  lidx = l.idx;
3889  lrow = l.row;
3890  lbeg = l.start;
3891 
3892  end = l.firstUpdate;
3893 
3894  for(i = l.firstUnused - 1; i >= end; --i)
3895  {
3896  if((x = vec[lrow[i]]) != 0.0)
3897  {
3898  k = lbeg[i];
3899  val = &lval[k];
3900  idx = &lidx[k];
3901 
3902  for(j = lbeg[i + 1]; j > k; --j)
3903  vec[*idx++] -= x * (*val++);
3904  }
3905  }
3906 
3907  return 0;
3908 }
3909 
3910 void CLUFactor::solveLleft(Real* vec) const
3911 {
3912 
3913 #ifndef WITH_L_ROWS
3914  int* idx;
3915  Real* val;
3916  Real* lval = l.val;
3917  int* lidx = l.idx;
3918  int* lrow = l.row;
3919  int* lbeg = l.start;
3920 
3921  for(int i = l.firstUpdate - 1; i >= 0; --i)
3922  {
3923  int k = lbeg[i];
3924  val = &lval[k];
3925  idx = &lidx[k];
3926  x = 0;
3927 
3928  for(int j = lbeg[i + 1]; j > k; --j)
3929  x += vec[*idx++] * (*val++);
3930 
3931  vec[lrow[i]] -= x;
3932  }
3933 
3934 #else
3935 
3936  for(int i = thedim - 1; i >= 0; --i)
3937  {
3938  int r = l.rorig[i];
3939  Real x = vec[r];
3940 
3941  if(x != 0.0)
3942  {
3943  for(int k = l.rbeg[r]; k < l.rbeg[r + 1]; k++)
3944  {
3945  int j = l.ridx[k];
3946 
3947  assert(l.rperm[j] < i);
3948 
3949  vec[j] -= x * l.rval[k];
3950  }
3951  }
3952  }
3953 
3954 #endif // WITH_L_ROWS
3955 }
3956 
3957 int CLUFactor::solveLleftEps(Real* vec, int* nonz, Real eps)
3958 {
3959  int i, j, k, n;
3960  int r;
3961  Real x;
3962  Real* rval, *val;
3963  int* ridx, *idx;
3964  int* rbeg;
3965  int* rorig;
3966 
3967  ridx = l.ridx;
3968  rval = l.rval;
3969  rbeg = l.rbeg;
3970  rorig = l.rorig;
3971  n = 0;
3972 #ifndef WITH_L_ROWS
3973  Real* lval = l.val;
3974  int* lidx = l.idx;
3975  int* lrow = l.row;
3976  int* lbeg = l.start;
3977 
3978  for(i = l.firstUpdate - 1; i >= 0; --i)
3979  {
3980  k = lbeg[i];
3981  val = &lval[k];
3982  idx = &lidx[k];
3983  x = 0;
3984 
3985  for(j = lbeg[i + 1]; j > k; --j)
3986  x += vec[*idx++] * (*val++);
3987 
3988  vec[lrow[i]] -= x;
3989  }
3990 
3991 #else
3992 
3993  for(i = thedim; i--;)
3994  {
3995  r = rorig[i];
3996  x = vec[r];
3997 
3998  if(isNotZero(x, eps))
3999  {
4000  *nonz++ = r;
4001  n++;
4002  k = rbeg[r];
4003  j = rbeg[r + 1] - k;
4004  val = &rval[k];
4005  idx = &ridx[k];
4006 
4007  while(j-- > 0)
4008  {
4009  assert(row.perm[*idx] < i);
4010  vec[*idx++] -= x * *val++;
4011  }
4012  }
4013  else
4014  vec[r] = 0;
4015  }
4016 
4017 #endif
4018 
4019  return n;
4020 }
4021 
4023 {
4024  int i, j, k, end;
4025  Real* lval, *val;
4026  int* lrow, *lidx, *idx;
4027  int* lbeg;
4028 
4029  lval = l.val;
4030  lidx = l.idx;
4031  lrow = l.row;
4032  lbeg = l.start;
4033 
4034  assert(!l.updateType); /* Forest-Tomlin Updates */
4035 
4036  end = l.firstUpdate;
4037 
4038  for(i = l.firstUnused - 1; i >= end; --i)
4039  {
4040  k = lbeg[i];
4041  val = &lval[k];
4042  idx = &lidx[k];
4043  StableSum<Real> tmp(-vec[lrow[i]]);
4044 
4045  for(j = lbeg[i + 1]; j > k; --j)
4046  tmp += vec[*idx++] * (*val++);
4047 
4048  vec[lrow[i]] = -tmp;
4049  }
4050 }
4051 
4053 {
4054  int i, j, k, end;
4055  Real* lval, *val;
4056  int* lrow, *lidx, *idx;
4057  int* lbeg;
4058 
4059  lval = l.val;
4060  lidx = l.idx;
4061  lrow = l.row;
4062  lbeg = l.start;
4063 
4064  assert(!l.updateType); /* Forest-Tomlin Updates */
4065 
4066  end = l.firstUpdate;
4067 
4068  for(i = l.firstUnused - 1; i >= end; --i)
4069  {
4070  k = lbeg[i];
4071  val = &lval[k];
4072  idx = &lidx[k];
4073 
4074  StableSum<Real> tmp1(-vec1[lrow[i]]);
4075  StableSum<Real> tmp2(-vec2[lrow[i]]);
4076 
4077  for(j = lbeg[i + 1]; j > k; --j)
4078  {
4079  tmp1 += vec1[*idx] * (*val);
4080  tmp2 += vec2[*idx++] * (*val++);
4081  }
4082 
4083  vec1[lrow[i]] = -tmp1;
4084  vec2[lrow[i]] = -tmp2;
4085  }
4086 }
4087 
4088 int CLUFactor::solveUpdateLeft(Real eps, Real* vec, int* nonz, int n)
4089 {
4090  int i, j, k, end;
4091  Real y;
4092  Real* lval, *val;
4093  int* lrow, *lidx, *idx;
4094  int* lbeg;
4095 
4096  assert(!l.updateType); /* no Forest-Tomlin Updates! */
4097 
4098  lval = l.val;
4099  lidx = l.idx;
4100  lrow = l.row;
4101  lbeg = l.start;
4102 
4103  end = l.firstUpdate;
4104 
4105  for(i = l.firstUnused - 1; i >= end; --i)
4106  {
4107  k = lbeg[i];
4108  assert(k >= 0 && k < l.size);
4109  val = &lval[k];
4110  idx = &lidx[k];
4111 
4112  k = lrow[i];
4113 
4114  y = vec[k];
4115  StableSum<Real> tmp(-y);
4116 
4117  for(j = lbeg[i + 1]; j > k; --j)
4118  {
4119  assert(*idx >= 0 && *idx < thedim);
4120  tmp += vec[*idx++] * (*val++);
4121  }
4122 
4123  if(y == 0)
4124  {
4125  y = -tmp;
4126 
4127  if(isNotZero(y, eps))
4128  {
4129  nonz[n++] = k;
4130  vec[k] = y;
4131  }
4132  }
4133  else
4134  {
4135  y = -tmp;
4136  vec[k] = (y != 0) ? y : SOPLEX_FACTOR_MARKER;
4137  }
4138  }
4139 
4140  return n;
4141 }
4142 
4144 {
4145 
4146  if(!l.updateType) /* no Forest-Tomlin Updates */
4147  {
4148  solveUpdateLeft(rhs);
4149  solveUleft(vec, rhs);
4150  solveLleft(vec);
4151  }
4152  else
4153  {
4154  solveUleft(vec, rhs);
4155  //@todo is 0.0 the right value for eps here ?
4156  solveLleftForest(vec, 0, 0.0);
4157  solveLleft(vec);
4158  }
4159 }
4160 
4161 int CLUFactor::solveLeftEps(Real* vec, Real* rhs, int* nonz, Real eps)
4162 {
4163 
4164  if(!l.updateType) /* no Forest-Tomlin Updates */
4165  {
4166  solveUpdateLeft(rhs);
4167  solveUleft(vec, rhs);
4168  return solveLleftEps(vec, nonz, eps);
4169  }
4170  else
4171  {
4172  solveUleft(vec, rhs);
4173  solveLleftForest(vec, nonz, eps);
4174  return solveLleftEps(vec, nonz, eps);
4175  }
4176 }
4177 
4179  Real* vec1,
4180  int* nonz,
4181  Real* vec2,
4182  Real eps,
4183  Real* rhs1,
4184  Real* rhs2)
4185 {
4186 
4187  if(!l.updateType) /* no Forest-Tomlin Updates */
4188  {
4189  solveUpdateLeft2(rhs1, rhs2);
4190  solveUleft2(vec1, rhs1, vec2, rhs2);
4191  solveLleft2(vec1, nonz, vec2, eps);
4192  return 0;
4193  }
4194  else
4195  {
4196  solveUleft2(vec1, rhs1, vec2, rhs2);
4197  solveLleft2forest(vec1, nonz, vec2, eps);
4198  solveLleft2(vec1, nonz, vec2, eps);
4199  return 0;
4200  }
4201 }
4202 
4204  Real* vec, int* vecidx,
4205  Real* rhs, int* rhsidx, int rhsn)
4206 {
4207  Real x, y;
4208  int i, j, k, n, r, c;
4209  int* rorig, *corig, *cperm;
4210  int* ridx, *rlen, *rbeg, *idx;
4211  Real* rval, *val;
4212 
4213  rorig = row.orig;
4214  corig = col.orig;
4215  cperm = col.perm;
4216 
4217  /* move rhsidx to a heap
4218  */
4219 
4220  for(i = 0; i < rhsn;)
4221  enQueueMin(rhsidx, &i, cperm[rhsidx[i]]);
4222 
4223  ridx = u.row.idx;
4224 
4225  rval = u.row.val;
4226 
4227  rlen = u.row.len;
4228 
4229  rbeg = u.row.start;
4230 
4231  n = 0;
4232 
4233  while(rhsn > 0)
4234  {
4235  i = deQueueMin(rhsidx, &rhsn);
4236  assert(i >= 0 && i < thedim);
4237  c = corig[i];
4238  assert(c >= 0 && c < thedim);
4239  x = rhs[c];
4240  rhs[c] = 0;
4241 
4242  if(isNotZero(x, eps))
4243  {
4244  r = rorig[i];
4245  assert(r >= 0 && r < thedim);
4246  vecidx[n++] = r;
4247  x *= diag[r];
4248  vec[r] = x;
4249  k = rbeg[r];
4250  assert(k >= 0 && k < u.row.size);
4251  idx = &ridx[k];
4252  val = &rval[k];
4253 
4254  for(int m = rlen[r]; m; --m)
4255  {
4256  j = *idx++;
4257  assert(j >= 0 && j < thedim);
4258  y = rhs[j];
4259 
4260  if(y == 0)
4261  {
4262  y = -x * (*val++);
4263 
4264  if(isNotZero(y, eps))
4265  {
4266  rhs[j] = y;
4267  enQueueMin(rhsidx, &rhsn, cperm[j]);
4268  }
4269  }
4270  else
4271  {
4272  y -= x * (*val++);
4273  rhs[j] = (y != 0) ? y : SOPLEX_FACTOR_MARKER;
4274  }
4275  }
4276  }
4277  }
4278 
4279  return n;
4280 }
4281 
4282 
4284  Real* rhs, int* rhsidx, int rhsn)
4285 {
4286  Real x, y;
4287  int i, j, k, r, c;
4288  int* rorig, *corig, *cperm;
4289  int* ridx, *rlen, *rbeg, *idx;
4290  Real* rval, *val;
4291 
4292  rorig = row.orig;
4293  corig = col.orig;
4294  cperm = col.perm;
4295 
4296  /* move rhsidx to a heap
4297  */
4298 
4299  for(i = 0; i < rhsn;)
4300  enQueueMin(rhsidx, &i, cperm[rhsidx[i]]);
4301 
4302  ridx = u.row.idx;
4303 
4304  rval = u.row.val;
4305 
4306  rlen = u.row.len;
4307 
4308  rbeg = u.row.start;
4309 
4310  while(rhsn > 0)
4311  {
4312  i = deQueueMin(rhsidx, &rhsn);
4313  assert(i >= 0 && i < thedim);
4314  c = corig[i];
4315  assert(c >= 0 && c < thedim);
4316  x = rhs[c];
4317  rhs[c] = 0;
4318 
4319  if(isNotZero(x, eps))
4320  {
4321  r = rorig[i];
4322  assert(r >= 0 && r < thedim);
4323  x *= diag[r];
4324  vec[r] = x;
4325  k = rbeg[r];
4326  assert(k >= 0 && k < u.row.size);
4327  idx = &ridx[k];
4328  val = &rval[k];
4329 
4330  for(int m = rlen[r]; m; --m)
4331  {
4332  j = *idx++;
4333  assert(j >= 0 && j < thedim);
4334  y = rhs[j];
4335 
4336  if(y == 0)
4337  {
4338  y = -x * (*val++);
4339 
4340  if(isNotZero(y, eps))
4341  {
4342  rhs[j] = y;
4343  enQueueMin(rhsidx, &rhsn, cperm[j]);
4344  }
4345  }
4346  else
4347  {
4348  y -= x * (*val++);
4349  rhs[j] = (y != 0) ? y : SOPLEX_FACTOR_MARKER;
4350  }
4351  }
4352  }
4353  }
4354 }
4355 
4356 
4357 int CLUFactor::solveLleftForest(Real eps, Real* vec, int* nonz, int n)
4358 {
4359  int i, j, k, end;
4360  Real x, y;
4361  Real* val, *lval;
4362  int* idx, *lidx, *lrow, *lbeg;
4363 
4364  lval = l.val;
4365  lidx = l.idx;
4366  lrow = l.row;
4367  lbeg = l.start;
4368  end = l.firstUpdate;
4369 
4370  for(i = l.firstUnused - 1; i >= end; --i)
4371  {
4372  assert(i >= 0 && i < l.size);
4373 
4374  if((x = vec[lrow[i]]) != 0.0)
4375  {
4376  k = lbeg[i];
4377  assert(k >= 0 && k < l.size);
4378  val = &lval[k];
4379  idx = &lidx[k];
4380 
4381  for(j = lbeg[i + 1]; j > k; --j)
4382  {
4383  int m = *idx++;
4384  assert(m >= 0 && m < thedim);
4385  y = vec[m];
4386 
4387  if(y == 0)
4388  {
4389  y = -x * (*val++);
4390 
4391  if(isNotZero(y, eps))
4392  {
4393  vec[m] = y;
4394  nonz[n++] = m;
4395  }
4396  }
4397  else
4398  {
4399  y -= x * (*val++);
4400  vec[m] = (y != 0) ? y : SOPLEX_FACTOR_MARKER;
4401  }
4402  }
4403  }
4404  }
4405 
4406  return n;
4407 }
4408 
4409 
4411 {
4412  int i, j, k, end;
4413  Real x;
4414  Real* val, *lval;
4415  int* idx, *lidx, *lrow, *lbeg;
4416 
4417  lval = l.val;
4418  lidx = l.idx;
4419  lrow = l.row;
4420  lbeg = l.start;
4421  end = l.firstUpdate;
4422 
4423  for(i = l.firstUnused - 1; i >= end; --i)
4424  {
4425  if((x = vec[lrow[i]]) != 0.0)
4426  {
4427  assert(i >= 0 && i < l.size);
4428  k = lbeg[i];
4429  assert(k >= 0 && k < l.size);
4430  val = &lval[k];
4431  idx = &lidx[k];
4432 
4433  for(j = lbeg[i + 1]; j > k; --j)
4434  {
4435  assert(*idx >= 0 && *idx < thedim);
4436  vec[*idx++] -= x * (*val++);
4437  }
4438  }
4439  }
4440 }
4441 
4442 
4443 int CLUFactor::solveLleft(Real eps, Real* vec, int* nonz, int rn)
4444 {
4445  int i, j, k, n;
4446  int r;
4447  Real x, y;
4448  Real* rval, *val;
4449  int* ridx, *idx;
4450  int* rbeg;
4451  int* rorig, *rperm;
4452  int* last;
4453 
4454  ridx = l.ridx;
4455  rval = l.rval;
4456  rbeg = l.rbeg;
4457  rorig = l.rorig;
4458  rperm = l.rperm;
4459  n = 0;
4460 
4461  i = l.firstUpdate - 1;
4462 #ifndef WITH_L_ROWS
4463 #pragma warn "Not yet implemented, define WITH_L_ROWS"
4464  Real* lval = l.val;
4465  int* lidx = l.idx;
4466  int* lrow = l.row;
4467  int* lbeg = l.start;
4468 
4469  for(; i >= 0; --i)
4470  {
4471  k = lbeg[i];
4472  val = &lval[k];
4473  idx = &lidx[k];
4474  x = 0;
4475 
4476  for(j = lbeg[i + 1]; j > k; --j)
4477  x += vec[*idx++] * (*val++);
4478 
4479  vec[lrow[i]] -= x;
4480  }
4481 
4482 #else
4483 
4484  /* move rhsidx to a heap
4485  */
4486  for(i = 0; i < rn;)
4487  enQueueMax(nonz, &i, rperm[nonz[i]]);
4488 
4489  last = nonz + thedim;
4490 
4491  while(rn > 0)
4492  {
4493  i = deQueueMax(nonz, &rn);
4494  r = rorig[i];
4495  x = vec[r];
4496 
4497  if(isNotZero(x, eps))
4498  {
4499  *(--last) = r;
4500  n++;
4501  k = rbeg[r];
4502  j = rbeg[r + 1] - k;
4503  val = &rval[k];
4504  idx = &ridx[k];
4505 
4506  while(j-- > 0)
4507  {
4508  assert(l.rperm[*idx] < i);
4509  int m = *idx++;
4510  y = vec[m];
4511 
4512  if(y == 0)
4513  {
4514  y = -x * *val++;
4515 
4516  if(isNotZero(y, eps))
4517  {
4518  vec[m] = y;
4519  enQueueMax(nonz, &rn, rperm[m]);
4520  }
4521  }
4522  else
4523  {
4524  y -= x * *val++;
4525  vec[m] = (y != 0) ? y : SOPLEX_FACTOR_MARKER;
4526  }
4527  }
4528  }
4529  else
4530  vec[r] = 0;
4531  }
4532 
4533  for(i = 0; i < n; ++i)
4534  *nonz++ = *last++;
4535 
4536 #endif
4537 
4538  return n;
4539 }
4540 
4541 
4543 {
4544  int i, j, k;
4545  int r;
4546  Real x;
4547  Real* rval, *val;
4548  int* ridx, *idx;
4549  int* rbeg;
4550  int* rorig;
4551 
4552  ridx = l.ridx;
4553  rval = l.rval;
4554  rbeg = l.rbeg;
4555  rorig = l.rorig;
4556 
4557 #ifndef WITH_L_ROWS
4558  Real* lval = l.val;
4559  int* lidx = l.idx;
4560  int* lrow = l.row;
4561  int* lbeg = l.start;
4562 
4563  i = l.firstUpdate - 1;
4564  assert(i < thedim);
4565 
4566  for(; i >= 0; --i)
4567  {
4568  k = lbeg[i];
4569  assert(k >= 0 && k < l.size);
4570  val = &lval[k];
4571  idx = &lidx[k];
4572  x = 0;
4573 
4574  for(j = lbeg[i + 1]; j > k; --j)
4575  {
4576  assert(*idx >= 0 && *idx < thedim);
4577  x += vec[*idx++] * (*val++);
4578  }
4579 
4580  vec[lrow[i]] -= x;
4581  }
4582 
4583 #else
4584 
4585  for(i = thedim; i--;)
4586  {
4587  r = rorig[i];
4588  x = vec[r];
4589 
4590  if(x != 0.0)
4591  {
4592  k = rbeg[r];
4593  j = rbeg[r + 1] - k;
4594  val = &rval[k];
4595  idx = &ridx[k];
4596 
4597  while(j-- > 0)
4598  {
4599  assert(l.rperm[*idx] < i);
4600  vec[*idx++] -= x * *val++;
4601  }
4602  }
4603  }
4604 
4605 #endif
4606 }
4607 
4608 void inline CLUFactor::updateSolutionVectorLright(Real change, int j, Real& vec, int* idx, int& nnz)
4609 {
4610  // create a new entry in #ridx
4611  if(vec == 0.0)
4612  {
4613  assert(nnz < thedim);
4614  idx[nnz] = j;
4615  ++nnz;
4616  }
4617 
4618  vec -= change;
4619 
4620  // mark the entry where exact eliminiation occurred
4621  if(vec == 0.0)
4622  vec = SOPLEX_FACTOR_MARKER;
4623 }
4624 
4625 // solve Lz = b, inplace, using and preserving sparisity structure in the rhs and solution vector
4626 // arrays #vec and #ridx must be large enough to hold #thedim entries!
4627 void CLUFactor::vSolveLright(Real* vec, int* ridx, int& rn, Real eps)
4628 {
4629  int i, j, k, n;
4630  int end;
4631  Real x;
4632  Real* lval, *val;
4633  int* lrow, *lidx, *idx;
4634  int* lbeg;
4635 
4636  lval = l.val;
4637  lidx = l.idx;
4638  lrow = l.row;
4639  lbeg = l.start;
4640 
4641  end = l.firstUpdate;
4642 
4643  // loop through columns of L
4644  for(i = 0; i < end; ++i)
4645  {
4646  x = vec[lrow[i]];
4647 
4648  // check whether there is a corresponding value in the rhs vector; skipping/ignoring FACTOR_MARKER
4649  if(isNotZero(x, eps))
4650  {
4651  k = lbeg[i];
4652  idx = &(lidx[k]);
4653  val = &(lval[k]);
4654 
4655  // apply \f$- x * L_{k,i}\f$ to all corresponding values in rhs/solution vector
4656  for(j = lbeg[i + 1]; j > k; --j)
4657  {
4658  assert(*idx >= 0 && *idx < thedim);
4659  n = *idx++;
4660  updateSolutionVectorLright(x * (*val), n, vec[n], ridx, rn);
4661  ++val;
4662  }
4663  }
4664  }
4665 
4666  if(l.updateType) /* Forest-Tomlin Updates */
4667  {
4668  end = l.firstUnused;
4669 
4670  for(; i < end; ++i)
4671  {
4672  k = lbeg[i];
4673  idx = &(lidx[k]);
4674  val = &(lval[k]);
4675 
4676  StableSum<Real> tmp;
4677 
4678  for(j = lbeg[i + 1]; j > k; --j)
4679  {
4680  assert(*idx >= 0 && *idx < thedim);
4681  tmp += vec[*idx++] * (*val++);
4682  }
4683 
4684  j = lrow[i];
4685  x = tmp;
4686 
4687  if(isNotZero(x, eps))
4688  updateSolutionVectorLright(x, j, vec[j], ridx, rn);
4689  }
4690  }
4691 }
4692 
4693 // solve with L for two right hand sides
4694 // see above methods for documentation
4696  Real* vec, int* ridx, int& rn, Real eps,
4697  Real* vec2, int* ridx2, int& rn2, Real eps2)
4698 {
4699  int i, j, k, n;
4700  int end;
4701  Real x, x2;
4702  Real* lval, *val;
4703  int* lrow, *lidx, *idx;
4704  int* lbeg;
4705 
4706  lval = l.val;
4707  lidx = l.idx;
4708  lrow = l.row;
4709  lbeg = l.start;
4710 
4711  end = l.firstUpdate;
4712 
4713  // loop through columns of L
4714  for(i = 0; i < end; ++i)
4715  {
4716  j = lrow[i];
4717  x2 = vec2[j];
4718  x = vec[j];
4719 
4720  // check whether there is a corresponding value in the first rhs vector; skipping/ignoring FACTOR_MARKER
4721  if(isNotZero(x, eps))
4722  {
4723  k = lbeg[i];
4724  idx = &(lidx[k]);
4725  val = &(lval[k]);
4726 
4727  // check whether there is also a corresponding value in the second rhs vector; skipping/ignoring FACTOR_MARKER
4728  if(isNotZero(x2, eps2))
4729  {
4730  for(j = lbeg[i + 1]; j > k; --j)
4731  {
4732  assert(*idx >= 0 && *idx < thedim);
4733  n = *idx++;
4734  updateSolutionVectorLright(x * (*val), n, vec[n], ridx, rn);
4735  updateSolutionVectorLright(x2 * (*val), n, vec2[n], ridx2, rn2);
4736  ++val;
4737  }
4738  }
4739  // only the first vector needs to be modified
4740  else
4741  {
4742  for(j = lbeg[i + 1]; j > k; --j)
4743  {
4744  assert(*idx >= 0 && *idx < thedim);
4745  n = *idx++;
4746  updateSolutionVectorLright(x * (*val), n, vec[n], ridx, rn);
4747  ++val;
4748  }
4749  }
4750  }
4751  // only the second vector needs to be modified
4752  else if(isNotZero(x2, eps2))
4753  {
4754  k = lbeg[i];
4755  idx = &(lidx[k]);
4756  val = &(lval[k]);
4757 
4758  for(j = lbeg[i + 1]; j > k; --j)
4759  {
4760  assert(*idx >= 0 && *idx < thedim);
4761  n = *idx++;
4762  updateSolutionVectorLright(x2 * (*val), n, vec2[n], ridx2, rn2);
4763  ++val;
4764  }
4765  }
4766  }
4767 
4768  if(l.updateType) /* Forest-Tomlin Updates */
4769  {
4770  end = l.firstUnused;
4771 
4772  for(; i < end; ++i)
4773  {
4774  k = lbeg[i];
4775  idx = &(lidx[k]);
4776  val = &(lval[k]);
4777 
4778  StableSum<Real> tmp1;
4779  StableSum<Real> tmp2;
4780 
4781  for(j = lbeg[i + 1]; j > k; --j)
4782  {
4783  assert(*idx >= 0 && *idx < thedim);
4784  tmp1 += vec[*idx] * (*val);
4785  tmp2 += vec2[*idx++] * (*val++);
4786  }
4787 
4788  x = tmp1;
4789  x2 = tmp2;
4790 
4791  j = lrow[i];
4792 
4793  if(isNotZero(x, eps))
4794  updateSolutionVectorLright(x, j, vec[j], ridx, rn);
4795 
4796  if(isNotZero(x2, eps2))
4797  updateSolutionVectorLright(x2, j, vec2[j], ridx2, rn2);
4798  }
4799  }
4800 }
4801 
4802 // solve with L for three right hand sides
4803 // see above methods for documentation
4805  Real* vec, int* ridx, int& rn, Real eps,
4806  Real* vec2, int* ridx2, int& rn2, Real eps2,
4807  Real* vec3, int* ridx3, int& rn3, Real eps3)
4808 {
4809  int i, j, k, n;
4810  int end;
4811  Real x, x2, x3;
4812  Real* lval, *val;
4813  int* lrow, *lidx, *idx;
4814  int* lbeg;
4815 
4816  lval = l.val;
4817  lidx = l.idx;
4818  lrow = l.row;
4819  lbeg = l.start;
4820 
4821  end = l.firstUpdate;
4822 
4823  for(i = 0; i < end; ++i)
4824  {
4825  j = lrow[i];
4826  x = vec[j];
4827  x2 = vec2[j];
4828  x3 = vec3[j];
4829 
4830  if(isNotZero(x, eps))
4831  {
4832  k = lbeg[i];
4833  idx = &(lidx[k]);
4834  val = &(lval[k]);
4835 
4836  if(isNotZero(x2, eps2))
4837  {
4838  if(isNotZero(x3, eps3))
4839  {
4840  // case 1: all three vectors are nonzero at j
4841  for(j = lbeg[i + 1]; j > k; --j)
4842  {
4843  assert(*idx >= 0 && *idx < thedim);
4844  n = *idx++;
4845  updateSolutionVectorLright(x * (*val), n, vec[n], ridx, rn);
4846  updateSolutionVectorLright(x2 * (*val), n, vec2[n], ridx2, rn2);
4847  updateSolutionVectorLright(x3 * (*val), n, vec3[n], ridx3, rn3);
4848  ++val;
4849  }
4850  }
4851  else
4852  {
4853  // case 2: 1 and 2 are nonzero at j
4854  for(j = lbeg[i + 1]; j > k; --j)
4855  {
4856  assert(*idx >= 0 && *idx < thedim);
4857  n = *idx++;
4858  updateSolutionVectorLright(x * (*val), n, vec[n], ridx, rn);
4859  updateSolutionVectorLright(x2 * (*val), n, vec2[n], ridx2, rn2);
4860  ++val;
4861  }
4862  }
4863  }
4864  else if(isNotZero(x3, eps3))
4865  {
4866  // case 3: 1 and 3 are nonzero at j
4867  for(j = lbeg[i + 1]; j > k; --j)
4868  {
4869  assert(*idx >= 0 && *idx < thedim);
4870  n = *idx++;
4871  updateSolutionVectorLright(x * (*val), n, vec[n], ridx, rn);
4872  updateSolutionVectorLright(x3 * (*val), n, vec3[n], ridx3, rn3);
4873  ++val;
4874  }
4875  }
4876  else
4877  {
4878  // case 4: only 1 is nonzero at j
4879  for(j = lbeg[i + 1]; j > k; --j)
4880  {
4881  assert(*idx >= 0 && *idx < thedim);
4882  n = *idx++;
4883  updateSolutionVectorLright(x * (*val), n, vec[n], ridx, rn);
4884  ++val;
4885  }
4886  }
4887  }
4888  else if(isNotZero(x2, eps2))
4889  {
4890  k = lbeg[i];
4891  idx = &(lidx[k]);
4892  val = &(lval[k]);
4893 
4894  if(isNotZero(x3, eps3))
4895  {
4896  // case 5: 2 and 3 are nonzero at j
4897  for(j = lbeg[i + 1]; j > k; --j)
4898  {
4899  assert(*idx >= 0 && *idx < thedim);
4900  n = *idx++;
4901  updateSolutionVectorLright(x2 * (*val), n, vec2[n], ridx2, rn2);
4902  updateSolutionVectorLright(x3 * (*val), n, vec3[n], ridx3, rn3);
4903  ++val;
4904  }
4905  }
4906  else
4907  {
4908  // case 6: only 2 is nonzero at j
4909  for(j = lbeg[i + 1]; j > k; --j)
4910  {
4911  assert(*idx >= 0 && *idx < thedim);
4912  n = *idx++;
4913  updateSolutionVectorLright(x2 * (*val), n, vec2[n], ridx2, rn2);
4914  ++val;
4915  }
4916  }
4917  }
4918  else if(isNotZero(x3, eps3))
4919  {
4920  // case 7: only 3 is nonzero at j
4921  k = lbeg[i];
4922  idx = &(lidx[k]);
4923  val = &(lval[k]);
4924 
4925  for(j = lbeg[i + 1]; j > k; --j)
4926  {
4927  assert(*idx >= 0 && *idx < thedim);
4928  n = *idx++;
4929  updateSolutionVectorLright(x3 * (*val), n, vec3[n], ridx3, rn3);
4930  ++val;
4931  }
4932  }
4933  }
4934 
4935  if(l.updateType) /* Forest-Tomlin Updates */
4936  {
4937  end = l.firstUnused;
4938 
4939  for(; i < end; ++i)
4940  {
4941  k = lbeg[i];
4942  idx = &(lidx[k]);
4943  val = &(lval[k]);
4944 
4945  StableSum<Real> tmp1;
4946  StableSum<Real> tmp2;
4947  StableSum<Real> tmp3;
4948 
4949  for(j = lbeg[i + 1]; j > k; --j)
4950  {
4951  assert(*idx >= 0 && *idx < thedim);
4952  tmp1 += vec[*idx] * (*val);
4953  tmp2 += vec2[*idx] * (*val);
4954  tmp3 += vec3[*idx++] * (*val++);
4955  }
4956 
4957  x = tmp1;
4958  x2 = tmp2;
4959  x3 = tmp3;
4960 
4961  j = lrow[i];
4962 
4963  if(isNotZero(x, eps))
4964  updateSolutionVectorLright(x, j, vec[j], ridx, rn);
4965 
4966  if(isNotZero(x2, eps2))
4967  updateSolutionVectorLright(x2, j, vec2[j], ridx2, rn2);
4968 
4969  if(isNotZero(x3, eps3))
4970  updateSolutionVectorLright(x3, j, vec3[j], ridx3, rn3);
4971  }
4972  }
4973 }
4974 
4975 int CLUFactor::vSolveUright(Real* vec, int* vidx,
4976  Real* rhs, int* ridx, int rn, Real eps)
4977 {
4978  int i, j, k, r, c, n;
4979  int* rorig, *corig;
4980  int* rperm;
4981  int* cidx, *clen, *cbeg;
4982  Real* cval;
4983  Real x, y;
4984 
4985  int* idx;
4986  Real* val;
4987 
4988  rorig = row.orig;
4989  corig = col.orig;
4990  rperm = row.perm;
4991 
4992  cidx = u.col.idx;
4993  cval = u.col.val;
4994  clen = u.col.len;
4995  cbeg = u.col.start;
4996 
4997  n = 0;
4998 
4999  while(rn > 0)
5000  {
5001  /* Find nonzero with highest permuted row index and setup i and r
5002  */
5003  i = deQueueMax(ridx, &rn);
5004  assert(i >= 0 && i < thedim);
5005  r = rorig[i];
5006  assert(r >= 0 && r < thedim);
5007 
5008  x = diag[r] * rhs[r];
5009  rhs[r] = 0;
5010 
5011  if(isNotZero(x, eps))
5012  {
5013  c = corig[i];
5014  assert(c >= 0 && c < thedim);
5015  vidx[n++] = c;
5016  vec[c] = x;
5017  val = &cval[cbeg[c]];
5018  idx = &cidx[cbeg[c]];
5019  j = clen[c];
5020 
5021  while(j-- > 0)
5022  {
5023  assert(*idx >= 0 && *idx < thedim);
5024  k = *idx++;
5025  assert(k >= 0 && k < thedim);
5026  y = rhs[k];
5027 
5028  if(y == 0)
5029  {
5030  y = -x * (*val++);
5031 
5032  if(isNotZero(y, eps))
5033  {
5034  rhs[k] = y;
5035  enQueueMax(ridx, &rn, rperm[k]);
5036  }
5037  }
5038  else
5039  {
5040  y -= x * (*val++);
5041  y += (y == 0) ? SOPLEX_FACTOR_MARKER : 0;
5042  rhs[k] = y;
5043  }
5044  }
5045 
5046  if(rn > i * verySparseFactor4right)
5047  {
5048  /* continue with dense case */
5049  for(i = *ridx; i >= 0; --i)
5050  {
5051  r = rorig[i];
5052  assert(r >= 0 && r < thedim);
5053  x = diag[r] * rhs[r];
5054  rhs[r] = 0;
5055 
5056  if(isNotZero(x, eps))
5057  {
5058  c = corig[i];
5059  assert(c >= 0 && c < thedim);
5060  vidx[n++] = c;
5061  vec[c] = x;
5062  val = &cval[cbeg[c]];
5063  idx = &cidx[cbeg[c]];
5064  j = clen[c];
5065 
5066  while(j-- > 0)
5067  {
5068  assert(*idx >= 0 && *idx < thedim);
5069  rhs[*idx++] -= x * (*val++);
5070  }
5071  }
5072  }
5073 
5074  break;
5075  }
5076  }
5077  }
5078 
5079  return n;
5080 }
5081 
5082 
5084  Real* rhs, int* ridx, int rn, Real eps)
5085 {
5086  int i, j, k, r, c;
5087  int* rorig, *corig;
5088  int* rperm;
5089  int* cidx, *clen, *cbeg;
5090  Real* cval;
5091  Real x, y;
5092 
5093  int* idx;
5094  Real* val;
5095 
5096  rorig = row.orig;
5097  corig = col.orig;
5098  rperm = row.perm;
5099 
5100  cidx = u.col.idx;
5101  cval = u.col.val;
5102  clen = u.col.len;
5103  cbeg = u.col.start;
5104 
5105  while(rn > 0)
5106  {
5107  if(rn > *ridx * verySparseFactor4right)
5108  {
5109  /* continue with dense case */
5110  for(i = *ridx; i >= 0; --i)
5111  {
5112  assert(i >= 0 && i < thedim);
5113  r = rorig[i];
5114  assert(r >= 0 && r < thedim);
5115  x = diag[r] * rhs[r];
5116  rhs[r] = 0;
5117 
5118  if(isNotZero(x, eps))
5119  {
5120  c = corig[i];
5121  vec[c] = x;
5122  val = &cval[cbeg[c]];
5123  idx = &cidx[cbeg[c]];
5124  j = clen[c];
5125 
5126  while(j-- > 0)
5127  {
5128  assert(*idx >= 0 && *idx < thedim);
5129  rhs[*idx++] -= x * (*val++);
5130  }
5131  }
5132  }
5133 
5134  break;
5135  }
5136 
5137  /* Find nonzero with highest permuted row index and setup i and r
5138  */
5139  i = deQueueMax(ridx, &rn);
5140 
5141  assert(i >= 0 && i < thedim);
5142 
5143  r = rorig[i];
5144 
5145  assert(r >= 0 && r < thedim);
5146 
5147  x = diag[r] * rhs[r];
5148 
5149  rhs[r] = 0;
5150 
5151  if(isNotZero(x, eps))
5152  {
5153  c = corig[i];
5154  vec[c] = x;
5155  val = &cval[cbeg[c]];
5156  idx = &cidx[cbeg[c]];
5157  j = clen[c];
5158 
5159  while(j-- > 0)
5160  {
5161  k = *idx++;
5162  assert(k >= 0 && k < thedim);
5163  y = rhs[k];
5164 
5165  if(y == 0)
5166  {
5167  y = -x * (*val++);
5168 
5169  if(isNotZero(y, eps))
5170  {
5171  rhs[k] = y;
5172  enQueueMax(ridx, &rn, rperm[k]);
5173  }
5174  }
5175  else
5176  {
5177  y -= x * (*val++);
5178  y += (y == 0) ? SOPLEX_FACTOR_MARKER : 0;
5179  rhs[k] = y;
5180  }
5181  }
5182  }
5183  }
5184 }
5185 
5186 
5188  Real* vec, int* vidx, Real* rhs, int* ridx, int rn, Real eps,
5189  Real* vec2, Real* rhs2, int* ridx2, int rn2, Real eps2)
5190 {
5191  int i, j, k, r, c, n;
5192  int* rorig, *corig;
5193  int* rperm;
5194  int* cidx, *clen, *cbeg;
5195  Real* cval;
5196  Real x, y;
5197  Real x2, y2;
5198 
5199  int* idx;
5200  Real* val;
5201 
5202  rorig = row.orig;
5203  corig = col.orig;
5204  rperm = row.perm;
5205 
5206  cidx = u.col.idx;
5207  cval = u.col.val;
5208  clen = u.col.len;
5209  cbeg = u.col.start;
5210 
5211  n = 0;
5212 
5213  while(rn + rn2 > 0)
5214  {
5215  /* Find nonzero with highest permuted row index and setup i and r
5216  */
5217  if(rn <= 0)
5218  i = deQueueMax(ridx2, &rn2);
5219  else if(rn2 <= 0)
5220  i = deQueueMax(ridx, &rn);
5221  else if(*ridx2 > *ridx)
5222  i = deQueueMax(ridx2, &rn2);
5223  else if(*ridx2 < *ridx)
5224  i = deQueueMax(ridx, &rn);
5225  else
5226  {
5227  (void) deQueueMax(ridx, &rn);
5228  i = deQueueMax(ridx2, &rn2);
5229  }
5230 
5231  assert(i >= 0 && i < thedim);
5232 
5233  r = rorig[i];
5234  assert(r >= 0 && r < thedim);
5235 
5236  x = diag[r] * rhs[r];
5237  x2 = diag[r] * rhs2[r];
5238  rhs[r] = 0;
5239  rhs2[r] = 0;
5240 
5241  if(isNotZero(x, eps))
5242  {
5243  c = corig[i];
5244  vidx[n++] = c;
5245  vec[c] = x;
5246  vec2[c] = x2;
5247  val = &cval[cbeg[c]];
5248  idx = &cidx[cbeg[c]];
5249  j = clen[c];
5250 
5251  if(isNotZero(x2, eps2))
5252  {
5253  while(j-- > 0)
5254  {
5255  k = *idx++;
5256  assert(k >= 0 && k < thedim);
5257  y2 = rhs2[k];
5258 
5259  if(y2 == 0)
5260  {
5261  y2 = -x2 * (*val);
5262 
5263  if(isNotZero(y2, eps2))
5264  {
5265  rhs2[k] = y2;
5266  enQueueMax(ridx2, &rn2, rperm[k]);
5267  }
5268  }
5269  else
5270  {
5271  y2 -= x2 * (*val);
5272  rhs2[k] = (y2 != 0) ? y2 : SOPLEX_FACTOR_MARKER;
5273  }
5274 
5275  y = rhs[k];
5276 
5277  if(y == 0)
5278  {
5279  y = -x * (*val++);
5280 
5281  if(isNotZero(y, eps))
5282  {
5283  rhs[k] = y;
5284  enQueueMax(ridx, &rn, rperm[k]);
5285  }
5286  }
5287  else
5288  {
5289  y -= x * (*val++);
5290  y += (y == 0) ? SOPLEX_FACTOR_MARKER : 0;
5291  rhs[k] = y;
5292  }
5293  }
5294  }
5295  else
5296  {
5297  while(j-- > 0)
5298  {
5299  k = *idx++;
5300  assert(k >= 0 && k < thedim);
5301  y = rhs[k];
5302 
5303  if(y == 0)
5304  {
5305  y = -x * (*val++);
5306 
5307  if(isNotZero(y, eps))
5308  {
5309  rhs[k] = y;
5310  enQueueMax(ridx, &rn, rperm[k]);
5311  }
5312  }
5313  else
5314  {
5315  y -= x * (*val++);
5316  y += (y == 0) ? SOPLEX_FACTOR_MARKER : 0;
5317  rhs[k] = y;
5318  }
5319  }
5320  }
5321  }
5322  else if(isNotZero(x2, eps2))
5323  {
5324  c = corig[i];
5325  assert(c >= 0 && c < thedim);
5326  vec2[c] = x2;
5327  val = &cval[cbeg[c]];
5328  idx = &cidx[cbeg[c]];
5329  j = clen[c];
5330 
5331  while(j-- > 0)
5332  {
5333  k = *idx++;
5334  assert(k >= 0 && k < thedim);
5335  y2 = rhs2[k];
5336 
5337  if(y2 == 0)
5338  {
5339  y2 = -x2 * (*val++);
5340 
5341  if(isNotZero(y2, eps2))
5342  {
5343  rhs2[k] = y2;
5344  enQueueMax(ridx2, &rn2, rperm[k]);
5345  }
5346  }
5347  else
5348  {
5349  y2 -= x2 * (*val++);
5350  rhs2[k] = (y2 != 0) ? y2 : SOPLEX_FACTOR_MARKER;
5351  }
5352  }
5353  }
5354 
5355  if(rn + rn2 > i * verySparseFactor4right)
5356  {
5357  /* continue with dense case */
5358  if(*ridx > *ridx2)
5359  i = *ridx;
5360  else
5361  i = *ridx2;
5362 
5363  for(; i >= 0; --i)
5364  {
5365  assert(i < thedim);
5366  r = rorig[i];
5367  assert(r >= 0 && r < thedim);
5368  x = diag[r] * rhs[r];
5369  x2 = diag[r] * rhs2[r];
5370  rhs[r] = 0;
5371  rhs2[r] = 0;
5372 
5373  if(isNotZero(x2, eps2))
5374  {
5375  c = corig[i];
5376  assert(c >= 0 && c < thedim);
5377  vec2[c] = x2;
5378  val = &cval[cbeg[c]];
5379  idx = &cidx[cbeg[c]];
5380  j = clen[c];
5381 
5382  if(isNotZero(x, eps))
5383  {
5384  vidx[n++] = c;
5385  vec[c] = x;
5386 
5387  while(j-- > 0)
5388  {
5389  assert(*idx >= 0 && *idx < thedim);
5390  rhs[*idx] -= x * (*val);
5391  rhs2[*idx++] -= x2 * (*val++);
5392  }
5393  }
5394  else
5395  {
5396  while(j-- > 0)
5397  {
5398  assert(*idx >= 0 && *idx < thedim);
5399  rhs2[*idx++] -= x2 * (*val++);
5400  }
5401  }
5402  }
5403  else if(isNotZero(x, eps))
5404  {
5405  c = corig[i];
5406  assert(c >= 0 && c < thedim);
5407  vidx[n++] = c;
5408  vec[c] = x;
5409  val = &cval[cbeg[c]];
5410  idx = &cidx[cbeg[c]];
5411  j = clen[c];
5412 
5413  while(j-- > 0)
5414  {
5415  assert(*idx >= 0 && *idx < thedim);
5416  rhs[*idx++] -= x * (*val++);
5417  }
5418  }
5419  }
5420 
5421  break;
5422  }
5423  }
5424 
5425  return n;
5426 }
5427 
5428 int CLUFactor::vSolveUpdateRight(Real* vec, int* ridx, int n, Real eps)
5429 {
5430  int i, j, k;
5431  int end;
5432  Real x, y;
5433  Real* lval, *val;
5434  int* lrow, *lidx, *idx;
5435  int* lbeg;
5436 
5437  assert(!l.updateType); /* no Forest-Tomlin Updates */
5438 
5439  lval = l.val;
5440  lidx = l.idx;
5441  lrow = l.row;
5442  lbeg = l.start;
5443  end = l.firstUnused;
5444 
5445  for(i = l.firstUpdate; i < end; ++i)
5446  {
5447  assert(i >= 0 && i < thedim);
5448  x = vec[lrow[i]];
5449 
5450  if(isNotZero(x, eps))
5451  {
5452  k = lbeg[i];
5453  assert(k >= 0 && k < l.size);
5454  idx = &(lidx[k]);
5455  val = &(lval[k]);
5456 
5457  for(j = lbeg[i + 1]; j > k; --j)
5458  {
5459  int m = ridx[n] = *idx++;
5460  assert(m >= 0 && m < thedim);
5461  y = vec[m];
5462  n += (y == 0) ? 1 : 0;
5463  y = y - x * (*val++);
5464  vec[m] = (y != 0) ? y : SOPLEX_FACTOR_MARKER;
5465  }
5466  }
5467  }
5468 
5469  return n;
5470 }
5471 
5473 {
5474  int i, j, k;
5475  int end;
5476  Real x;
5477  Real* lval, *val;
5478  int* lrow, *lidx, *idx;
5479  int* lbeg;
5480 
5481  assert(!l.updateType); /* no Forest-Tomlin Updates */
5482 
5483  lval = l.val;
5484  lidx = l.idx;
5485  lrow = l.row;
5486  lbeg = l.start;
5487  end = l.firstUnused;
5488 
5489  for(i = l.firstUpdate; i < end; ++i)
5490  {
5491  assert(i >= 0 && i < thedim);
5492 
5493  if((x = vec[lrow[i]]) != 0.0)
5494  {
5495  k = lbeg[i];
5496  assert(k >= 0 && k < l.size);
5497  idx = &(lidx[k]);
5498  val = &(lval[k]);
5499 
5500  for(j = lbeg[i + 1]; j > k; --j)
5501  {
5502  assert(*idx >= 0 && *idx < thedim);
5503  vec[*idx++] -= x * (*val++);
5504  }
5505  }
5506  }
5507 }
5508 
5509 
5511  Real* vec, int* idx, /* result */
5512  Real* rhs, int* ridx, int rn, /* rhs */
5513  Real* forest, int* forestNum, int* forestIdx)
5514 {
5515  vSolveLright(rhs, ridx, rn, eps);
5516  assert(rn >= 0 && rn <= thedim);
5517 
5518  /* turn index list into a heap
5519  */
5520 
5521  if(forest)
5522  {
5523  Real x;
5524  int i, j, k;
5525  int* rperm;
5526  int* it = forestIdx;
5527 
5528  rperm = row.perm;
5529 
5530  for(i = j = 0; i < rn; ++i)
5531  {
5532  k = ridx[i];
5533  assert(k >= 0 && k < thedim);
5534  x = rhs[k];
5535 
5536  if(isNotZero(x, eps))
5537  {
5538  enQueueMax(ridx, &j, rperm[*it++ = k]);
5539  forest[k] = x;
5540  }
5541  else
5542  rhs[k] = 0;
5543  }
5544 
5545  *forestNum = rn = j;
5546  }
5547  else
5548  {
5549  Real x;
5550  int i, j, k;
5551  int* rperm;
5552 
5553  rperm = row.perm;
5554 
5555  for(i = j = 0; i < rn; ++i)
5556  {
5557  k = ridx[i];
5558  assert(k >= 0 && k < thedim);
5559  x = rhs[k];
5560 
5561  if(isNotZero(x, eps))
5562  enQueueMax(ridx, &j, rperm[k]);
5563  else
5564  rhs[k] = 0;
5565  }
5566 
5567  rn = j;
5568  }
5569 
5570  rn = vSolveUright(vec, idx, rhs, ridx, rn, eps);
5571 
5572  if(!l.updateType) /* no Forest-Tomlin Updates */
5573  rn = vSolveUpdateRight(vec, idx, rn, eps);
5574 
5575  return rn;
5576 }
5577 
5579  Real* vec, int* idx, /* result1 */
5580  Real* rhs, int* ridx, int rn, /* rhs1 */
5581  Real* vec2, Real eps2, /* result2 */
5582  Real* rhs2, int* ridx2, int rn2, /* rhs2 */
5583  Real* forest, int* forestNum, int* forestIdx)
5584 {
5585  vSolveLright2(rhs, ridx, rn, eps, rhs2, ridx2, rn2, eps2);
5586  assert(rn >= 0 && rn <= thedim);
5587  assert(rn2 >= 0 && rn2 <= thedim);
5588 
5589  /* turn index list into a heap
5590  */
5591 
5592  if(forest)
5593  {
5594  Real x;
5595  int i, j, k;
5596  int* rperm;
5597  int* it = forestIdx;
5598 
5599  rperm = row.perm;
5600 
5601  for(i = j = 0; i < rn; ++i)
5602  {
5603  k = ridx[i];
5604  assert(k >= 0 && k < thedim);
5605  x = rhs[k];
5606 
5607  if(isNotZero(x, eps))
5608  {
5609  enQueueMax(ridx, &j, rperm[*it++ = k]);
5610  forest[k] = x;
5611  }
5612  else
5613  rhs[k] = 0;
5614  }
5615 
5616  *forestNum = rn = j;
5617  }
5618  else
5619  {
5620  Real x;
5621  int i, j, k;
5622  int* rperm;
5623 
5624  rperm = row.perm;
5625 
5626  for(i = j = 0; i < rn; ++i)
5627  {
5628  k = ridx[i];
5629  assert(k >= 0 && k < thedim);
5630  x = rhs[k];
5631 
5632  if(isNotZero(x, eps))
5633  enQueueMax(ridx, &j, rperm[k]);
5634  else
5635  rhs[k] = 0;
5636  }
5637 
5638  rn = j;
5639  }
5640 
5641  if(rn2 > thedim * verySparseFactor4right)
5642  {
5643  ridx2[0] = thedim - 1;
5644  /* ridx2[1] = thedim - 2; */
5645  }
5646  else
5647  {
5648  Real x;
5649  /* Real maxabs; */
5650  int i, j, k;
5651  int* rperm;
5652 
5653  /* maxabs = 1; */
5654  rperm = row.perm;
5655 
5656  for(i = j = 0; i < rn2; ++i)
5657  {
5658  k = ridx2[i];
5659  assert(k >= 0 && k < thedim);
5660  x = rhs2[k];
5661 
5662  if(x < -eps2)
5663  {
5664  /* maxabs = (maxabs < -x) ? -x : maxabs; */
5665  enQueueMax(ridx2, &j, rperm[k]);
5666  }
5667  else if(x > eps2)
5668  {
5669  /* maxabs = (maxabs < x) ? x : maxabs; */
5670  enQueueMax(ridx2, &j, rperm[k]);
5671  }
5672  else
5673  rhs2[k] = 0;
5674  }
5675 
5676  rn2 = j;
5677 
5678  /* eps2 = maxabs * eps2; */
5679  }
5680 
5681  rn = vSolveUright(vec, idx, rhs, ridx, rn, eps);
5682 
5683  vSolveUrightNoNZ(vec2, rhs2, ridx2, rn2, eps2);
5684 
5685  /*
5686  * rn = vSolveUright2(vec, idx, rhs, ridx, rn, eps, vec2, rhs2, ridx2, rn2, eps2);
5687  */
5688 
5689  if(!l.updateType) /* no Forest-Tomlin Updates */
5690  {
5691  rn = vSolveUpdateRight(vec, idx, rn, eps);
5692  vSolveUpdateRightNoNZ(vec2, eps2);
5693  }
5694 
5695  return rn;
5696 }
5697 
5698 void CLUFactor::vSolveRight4update2sparse(Real eps, Real* vec, int* idx, /* result1 */
5699  Real* rhs, int* ridx, int& rn, /* rhs1 */
5700  Real eps2, Real* vec2, int* idx2, /* result2 */
5701  Real* rhs2, int* ridx2, int& rn2, /* rhs2 */
5702  Real* forest, int* forestNum, int* forestIdx)
5703 {
5704  /* solve with L */
5705  vSolveLright2(rhs, ridx, rn, eps, rhs2, ridx2, rn2, eps2);
5706  assert(rn >= 0 && rn <= thedim);
5707  assert(rn2 >= 0 && rn2 <= thedim);
5708 
5709  Real x;
5710  int i, j, k;
5711  int* rperm = row.perm;
5712 
5713  /* turn index list into a heap for both ridx and ridx2 */
5714  if(forest)
5715  {
5716  int* it = forestIdx;
5717 
5718  for(i = j = 0; i < rn; ++i)
5719  {
5720  k = ridx[i];
5721  assert(k >= 0 && k < thedim);
5722  x = rhs[k];
5723 
5724  if(isNotZero(x, eps))
5725  {
5726  enQueueMax(ridx, &j, rperm[*it++ = k]);
5727  forest[k] = x;
5728  }
5729  else
5730  rhs[k] = 0;
5731  }
5732 
5733  *forestNum = rn = j;
5734  }
5735  else
5736  {
5737  for(i = j = 0; i < rn; ++i)
5738  {
5739  k = ridx[i];
5740  assert(k >= 0 && k < thedim);
5741  x = rhs[k];
5742 
5743  if(isNotZero(x, eps))
5744  enQueueMax(ridx, &j, rperm[k]);
5745  else
5746  rhs[k] = 0;
5747  }
5748 
5749  rn = j;
5750  }
5751 
5752  for(i = j = 0; i < rn2; ++i)
5753  {
5754  k = ridx2[i];
5755  assert(k >= 0 && k < thedim);
5756  x = rhs2[k];
5757 
5758  if(isNotZero(x, eps2))
5759  enQueueMax(ridx2, &j, rperm[k]);
5760  else
5761  rhs2[k] = 0;
5762  }
5763 
5764  rn2 = j;
5765 
5766  /* solve with U */
5767  rn = vSolveUright(vec, idx, rhs, ridx, rn, eps);
5768  rn2 = vSolveUright(vec2, idx2, rhs2, ridx2, rn2, eps2);
5769 
5770  if(!l.updateType) /* no Forest-Tomlin Updates */
5771  {
5772  rn = vSolveUpdateRight(vec, idx, rn, eps);
5773  rn2 = vSolveUpdateRight(vec2, idx2, rn2, eps2);
5774  }
5775 }
5776 
5777 
5779  Real* vec, int* idx, /* result1 */
5780  Real* rhs, int* ridx, int rn, /* rhs1 */
5781  Real* vec2, Real eps2, /* result2 */
5782  Real* rhs2, int* ridx2, int rn2, /* rhs2 */
5783  Real* vec3, Real eps3, /* result3 */
5784  Real* rhs3, int* ridx3, int rn3, /* rhs3 */
5785  Real* forest, int* forestNum, int* forestIdx)
5786 {
5787 
5788  vSolveLright3(rhs, ridx, rn, eps, rhs2, ridx2, rn2, eps2, rhs3, ridx3, rn3, eps3);
5789  assert(rn >= 0 && rn <= thedim);
5790  assert(rn2 >= 0 && rn2 <= thedim);
5791  assert(rn3 >= 0 && rn3 <= thedim);
5792 
5793  /* turn index list into a heap
5794  */
5795 
5796  if(forest)
5797  {
5798  Real x;
5799  int i, j, k;
5800  int* rperm;
5801  int* it = forestIdx;
5802 
5803  rperm = row.perm;
5804 
5805  for(i = j = 0; i < rn; ++i)
5806  {
5807  k = ridx[i];
5808  assert(k >= 0 && k < thedim);
5809  x = rhs[k];
5810 
5811  if(isNotZero(x, eps))
5812  {
5813  enQueueMax(ridx, &j, rperm[*it++ = k]);
5814  forest[k] = x;
5815  }
5816  else
5817  rhs[k] = 0;
5818  }
5819 
5820  *forestNum = rn = j;
5821  }
5822  else
5823  {
5824  Real x;
5825  int i, j, k;
5826  int* rperm;
5827 
5828  rperm = row.perm;
5829 
5830  for(i = j = 0; i < rn; ++i)
5831  {
5832  k = ridx[i];
5833  assert(k >= 0 && k < thedim);
5834  x = rhs[k];
5835 
5836  if(isNotZero(x, eps))
5837  enQueueMax(ridx, &j, rperm[k]);
5838  else
5839  rhs[k] = 0;
5840  }
5841 
5842  rn = j;
5843  }
5844 
5845  if(rn2 > thedim * verySparseFactor4right)
5846  {
5847  ridx2[0] = thedim - 1;
5848  }
5849  else
5850  {
5851  Real x;
5852  int i, j, k;
5853  int* rperm;
5854 
5855  rperm = row.perm;
5856 
5857  for(i = j = 0; i < rn2; ++i)
5858  {
5859  k = ridx2[i];
5860  assert(k >= 0 && k < thedim);
5861  x = rhs2[k];
5862 
5863  if(x < -eps2)
5864  {
5865  enQueueMax(ridx2, &j, rperm[k]);
5866  }
5867  else if(x > eps2)
5868  {
5869  enQueueMax(ridx2, &j, rperm[k]);
5870  }
5871  else
5872  rhs2[k] = 0;
5873  }
5874 
5875  rn2 = j;
5876  }
5877 
5878  if(rn3 > thedim * verySparseFactor4right)
5879  {
5880  ridx3[0] = thedim - 1;
5881  }
5882  else
5883  {
5884  Real x;
5885  int i, j, k;
5886  int* rperm;
5887 
5888  rperm = row.perm;
5889 
5890  for(i = j = 0; i < rn3; ++i)
5891  {
5892  k = ridx3[i];
5893  assert(k >= 0 && k < thedim);
5894  x = rhs3[k];
5895 
5896  if(x < -eps3)
5897  {
5898  enQueueMax(ridx3, &j, rperm[k]);
5899  }
5900  else if(x > eps3)
5901  {
5902  enQueueMax(ridx3, &j, rperm[k]);
5903  }
5904  else
5905  rhs3[k] = 0;
5906  }
5907 
5908  rn3 = j;
5909  }
5910 
5911  rn = vSolveUright(vec, idx, rhs, ridx, rn, eps);
5912 
5913  vSolveUrightNoNZ(vec2, rhs2, ridx2, rn2, eps2);
5914  vSolveUrightNoNZ(vec3, rhs3, ridx3, rn3, eps3);
5915 
5916  if(!l.updateType) /* no Forest-Tomlin Updates */
5917  {
5918  rn = vSolveUpdateRight(vec, idx, rn, eps);
5919  vSolveUpdateRightNoNZ(vec2, eps2);
5920  vSolveUpdateRightNoNZ(vec3, eps3);
5921  }
5922 
5923  return rn;
5924 }
5925 
5926 void CLUFactor::vSolveRight4update3sparse(Real eps, Real* vec, int* idx, /* result1 */
5927  Real* rhs, int* ridx, int& rn, /* rhs1 */
5928  Real eps2, Real* vec2, int* idx2, /* result2 */
5929  Real* rhs2, int* ridx2, int& rn2, /* rhs2 */
5930  Real eps3, Real* vec3, int* idx3, /* result3 */
5931  Real* rhs3, int* ridx3, int& rn3, /* rhs3 */
5932  Real* forest, int* forestNum, int* forestIdx)
5933 {
5934  vSolveLright3(rhs, ridx, rn, eps, rhs2, ridx2, rn2, eps2, rhs3, ridx3, rn3, eps3);
5935  assert(rn >= 0 && rn <= thedim);
5936  assert(rn2 >= 0 && rn2 <= thedim);
5937  assert(rn3 >= 0 && rn3 <= thedim);
5938 
5939  Real x;
5940  int i, j, k;
5941  int* rperm = row.perm;
5942 
5943  /* turn index list into a heap */
5944  if(forest)
5945  {
5946  int* it = forestIdx;
5947 
5948  for(i = j = 0; i < rn; ++i)
5949  {
5950  k = ridx[i];
5951  assert(k >= 0 && k < thedim);
5952  x = rhs[k];
5953 
5954  if(isNotZero(x, eps))
5955  {
5956  enQueueMax(ridx, &j, rperm[*it++ = k]);
5957  forest[k] = x;
5958  }
5959  else
5960  rhs[k] = 0;
5961  }
5962 
5963  *forestNum = rn = j;
5964  }
5965  else
5966  {
5967  for(i = j = 0; i < rn; ++i)
5968  {
5969  k = ridx[i];
5970  assert(k >= 0 && k < thedim);
5971  x = rhs[k];
5972 
5973  if(isNotZero(x, eps))
5974  enQueueMax(ridx, &j, rperm[k]);
5975  else
5976  rhs[k] = 0;
5977  }
5978 
5979  rn = j;
5980  }
5981 
5982  for(i = j = 0; i < rn2; ++i)
5983  {
5984  k = ridx2[i];
5985  assert(k >= 0 && k < thedim);
5986  x = rhs2[k];
5987 
5988  if(isNotZero(x, eps2))
5989  enQueueMax(ridx2, &j, rperm[k]);
5990  else
5991  rhs2[k] = 0;
5992  }
5993 
5994  rn2 = j;
5995 
5996  for(i = j = 0; i < rn3; ++i)
5997  {
5998  k = ridx3[i];
5999  assert(k >= 0 && k < thedim);
6000  x = rhs3[k];
6001 
6002  if(isNotZero(x, eps3))
6003  enQueueMax(ridx3, &j, rperm[k]);
6004  else
6005  rhs3[k] = 0;
6006  }
6007 
6008  rn3 = j;
6009 
6010  rn = vSolveUright(vec, idx, rhs, ridx, rn, eps);
6011  rn2 = vSolveUright(vec2, idx2, rhs2, ridx2, rn2, eps2);
6012  rn3 = vSolveUright(vec3, idx3, rhs3, ridx3, rn3, eps3);
6013 
6014  if(!l.updateType) /* no Forest-Tomlin Updates */
6015  {
6016  rn = vSolveUpdateRight(vec, idx, rn, eps);
6017  rn2 = vSolveUpdateRight(vec2, idx2, rn2, eps2);
6018  rn3 = vSolveUpdateRight(vec3, idx3, rn3, eps3);
6019  }
6020 }
6021 
6023  Real* vec, Real eps, /* result */
6024  Real* rhs, int* ridx, int rn) /* rhs */
6025 {
6026  vSolveLright(rhs, ridx, rn, eps);
6027  assert(rn >= 0 && rn <= thedim);
6028 
6029  if(rn > thedim * verySparseFactor4right)
6030  {
6031  *ridx = thedim - 1;
6032  }
6033  else
6034  {
6035  Real x;
6036  /* Real maxabs; */
6037  int i, j, k;
6038  int* rperm;
6039 
6040  /* maxabs = 1; */
6041  rperm = row.perm;
6042 
6043  for(i = j = 0; i < rn; ++i)
6044  {
6045  k = ridx[i];
6046  assert(k >= 0 && k < thedim);
6047  x = rhs[k];
6048 
6049  if(x < -eps)
6050  {
6051  /* maxabs = (maxabs < -x) ? -x : maxabs; */
6052  enQueueMax(ridx, &j, rperm[k]);
6053  }
6054  else if(x > eps)
6055  {
6056  /* maxabs = (maxabs < x) ? x : maxabs; */
6057  enQueueMax(ridx, &j, rperm[k]);
6058  }
6059  else
6060  rhs[k] = 0;
6061  }
6062 
6063  rn = j;
6064 
6065  /* eps2 = maxabs * eps2; */
6066  }
6067 
6068  vSolveUrightNoNZ(vec, rhs, ridx, rn, eps);
6069 
6070  if(!l.updateType) /* no Forest-Tomlin Updates */
6071  vSolveUpdateRightNoNZ(vec, eps);
6072 }
6073 
6075  Real* vec, int* idx, /* result */
6076  Real* rhs, int* ridx, int rn) /* rhs */
6077 {
6078 
6079  if(!l.updateType) /* no Forest-Tomlin Updates */
6080  {
6081  rn = solveUpdateLeft(eps, rhs, ridx, rn);
6082  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6083  }
6084  else
6085  {
6086  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6087  rn = solveLleftForest(eps, vec, idx, rn);
6088  }
6089 
6090  // TODO verify the correctness of this check
6091  if(rn + l.firstUpdate > verySparseFactor4left * thedim)
6092  {
6093  // perform the dense solve
6094  solveLleftNoNZ(vec);
6095  // signal the caller that the nonzero pattern is lost
6096  return 0;
6097  }
6098  else
6099  return solveLleft(eps, vec, idx, rn);
6100 }
6101 
6103  Real* vec, int* idx, /* result */
6104  Real* rhs, int* ridx, int rn, /* rhs */
6105  Real* vec2, /* result2 */
6106  Real* rhs2, int* ridx2, int rn2) /* rhs2 */
6107 {
6108 
6109  if(!l.updateType) /* no Forest-Tomlin Updates */
6110  {
6111  rn = solveUpdateLeft(eps, rhs, ridx, rn);
6112  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6113  rn2 = solveUpdateLeft(eps, rhs2, ridx2, rn2);
6114  solveUleftNoNZ(eps, vec2, rhs2, ridx2, rn2);
6115  }
6116  else
6117  {
6118  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6119  rn = solveLleftForest(eps, vec, idx, rn);
6120  solveUleftNoNZ(eps, vec2, rhs2, ridx2, rn2);
6121  solveLleftForestNoNZ(vec2);
6122  }
6123 
6124  rn = solveLleft(eps, vec, idx, rn);
6125 
6126  solveLleftNoNZ(vec2);
6127 
6128  return rn;
6129 }
6130 
6132  Real* vec, int* idx, /* result */
6133  Real* rhs, int* ridx, int& rn, /* rhs */
6134  Real* vec2, int* idx2, /* result2 */
6135  Real* rhs2, int* ridx2, int& rn2) /* rhs2 */
6136 {
6137  if(!l.updateType) /* no Forest-Tomlin Updates */
6138  {
6139  rn = solveUpdateLeft(eps, rhs, ridx, rn);
6140  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6141  rn2 = solveUpdateLeft(eps, rhs2, ridx2, rn2);
6142  rn2 = solveUleft(eps, vec2, idx2, rhs2, ridx2, rn2);
6143  }
6144  else
6145  {
6146  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6147  rn = solveLleftForest(eps, vec, idx, rn);
6148  rn2 = solveUleft(eps, vec2, idx2, rhs2, ridx2, rn2);
6149  rn2 = solveLleftForest(eps, vec2, idx2, rn2);
6150 
6151  }
6152 
6153  rn = solveLleft(eps, vec, idx, rn);
6154  rn2 = solveLleft(eps, vec2, idx2, rn2);
6155 }
6156 
6157 
6159  Real* vec, int* idx, /* result */
6160  Real* rhs, int* ridx, int rn, /* rhs */
6161  Real* vec2, /* result2 */
6162  Real* rhs2, int* ridx2, int rn2, /* rhs2 */
6163  Real* vec3, /* result3 */
6164  Real* rhs3, int* ridx3, int rn3) /* rhs3 */
6165 {
6166 
6167  if(!l.updateType) /* no Forest-Tomlin Updates */
6168  {
6169  rn = solveUpdateLeft(eps, rhs, ridx, rn);
6170  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6171  rn2 = solveUpdateLeft(eps, rhs2, ridx2, rn2);
6172  solveUleftNoNZ(eps, vec2, rhs2, ridx2, rn2);
6173  rn3 = solveUpdateLeft(eps, rhs3, ridx3, rn3);
6174  solveUleftNoNZ(eps, vec3, rhs3, ridx3, rn3);
6175  }
6176  else
6177  {
6178  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6179  rn = solveLleftForest(eps, vec, idx, rn);
6180  solveUleftNoNZ(eps, vec2, rhs2, ridx2, rn2);
6181  solveLleftForestNoNZ(vec2);
6182  solveUleftNoNZ(eps, vec3, rhs3, ridx3, rn3);
6183  solveLleftForestNoNZ(vec3);
6184  }
6185 
6186  rn = solveLleft(eps, vec, idx, rn);
6187 
6188  solveLleftNoNZ(vec2);
6189  solveLleftNoNZ(vec3);
6190 
6191  return rn;
6192 }
6193 
6195  Real* vec, int* idx, /* result */
6196  Real* rhs, int* ridx, int& rn, /* rhs */
6197  Real* vec2, int* idx2, /* result2 */
6198  Real* rhs2, int* ridx2, int& rn2, /* rhs2 */
6199  Real* vec3, int* idx3, /* result3 */
6200  Real* rhs3, int* ridx3, int& rn3) /* rhs3 */
6201 {
6202  if(!l.updateType) /* no Forest-Tomlin Updates */
6203  {
6204  rn = solveUpdateLeft(eps, rhs, ridx, rn);
6205  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6206  rn2 = solveUpdateLeft(eps, rhs2, ridx2, rn2);
6207  rn2 = solveUleft(eps, vec2, idx2, rhs2, ridx2, rn2);
6208  rn3 = solveUpdateLeft(eps, rhs3, ridx3, rn3);
6209  rn3 = solveUleft(eps, vec3, idx3, rhs3, ridx3, rn3);
6210  }
6211  else
6212  {
6213  rn = solveUleft(eps, vec, idx, rhs, ridx, rn);
6214  rn = solveLleftForest(eps, vec, idx, rn);
6215  rn2 = solveUleft(eps, vec2, idx2, rhs2, ridx2, rn2);
6216  rn2 = solveLleftForest(eps, vec2, idx2, rn2);
6217  rn3 = solveUleft(eps, vec3, idx3, rhs3, ridx3, rn3);
6218  rn3 = solveLleftForest(eps, vec3, idx3, rn3);
6219  }
6220 
6221  rn = solveLleft(eps, vec, idx, rn);
6222  rn2 = solveLleft(eps, vec2, idx2, rn2);
6223  rn3 = solveLleft(eps, vec3, idx3, rn3);
6224 }
6225 
6226 
6228  Real* vec2, /* result2 */
6229  Real* rhs2, int* ridx2, int rn2) /* rhs2 */
6230 {
6231 
6232  if(!l.updateType) /* no Forest-Tomlin Updates */
6233  {
6234  rn2 = solveUpdateLeft(eps, rhs2, ridx2, rn2);
6235  solveUleftNoNZ(eps, vec2, rhs2, ridx2, rn2);
6236  }
6237  else
6238  {
6239  solveUleftNoNZ(eps, vec2, rhs2, ridx2, rn2);
6240  solveLleftForestNoNZ(vec2);
6241  }
6242 
6243  solveLleftNoNZ(vec2);
6244 }
6245 } // namespace soplex
void solveUleft(Real *work, Real *vec)
Definition: clufactor.cpp:3611
Rational spxAbs(const Rational &r)
Absolute.
Definition: rational.cpp:4102
int * len
used nonzeros per row vectors
Definition: clufactor.h:128
bool isNotZero(Real a, Real eps=Param::epsilon())
returns true iff |a| > eps
Definition: spxdefines.h:418
void solveLleft(Real *vec) const
Definition: clufactor.cpp:3910
int updateType
type of updates to be used.
Definition: clufactor.h:167
void solveUpdateRight2(Real *vec1, Real *vec2)
Definition: clufactor.cpp:3460
void updateNoClear(int p_col, const Real *p_work, const int *p_idx, int num)
Definition: clufactor.cpp:1321
int solveUright2eps(Real *work1, Real *vec1, Real *work2, Real *vec2, int *nonz, Real eps)
Definition: clufactor.cpp:3208
void vSolveLright3(Real *vec, int *ridx, int &rn, Real eps, Real *vec2, int *ridx2, int &rn2, Real eps2, Real *vec3, int *ridx3, int &rn3, Real eps3)
Definition: clufactor.cpp:4804
int solveRight2update(Real *vec1, Real *vec2, Real *rhs1, Real *rhs2, int *nonz, Real eps, Real *forest, int *forestNum, int *forestIdx)
Definition: clufactor.cpp:3557
Dring list
Double linked ringlist of vector indices in the order they appear in the column file.
Definition: clufactor.h:137
int * max
maximum available nonzeros per row: start[i] + max[i] == start[elem[i].next->idx] len[i] <= max[i]...
Definition: clufactor.h:129
static const Real verySparseFactor4left
Definition: clufactor.cpp:35
#define REAL(x)
Definition: spxdefines.h:221
int vSolveRight4update(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int rn, Real *forest, int *forestNum, int *forestIdx)
Definition: clufactor.cpp:5510
void forestMinColMem(int size)
Definition: clufactor.cpp:2895
Memory allocation routines.
void vSolveRight4update3sparse(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int &rn, Real eps2, Real *vec2, int *idx2, Real *rhs2, int *ridx2, int &rn2, Real eps3, Real *vec3, int *idx3, Real *rhs3, int *ridx3, int &rn3, Real *forest, int *forestNum, int *forestIdx)
sparse version of above method
Definition: clufactor.cpp:5926
Pring * pivot_rowNZ
lists for rows to number of nonzeros
Definition: clufactor.h:94
int size() const
Number of used indices.
Definition: svectorbase.h:153
struct soplex::CLUFactor::U::Col col
int * start
starting positions in val and idx
Definition: clufactor.h:147
int solveLleftForest(Real *vec, int *, Real)
Definition: clufactor.cpp:3880
Real * rval
values of rows of L
Definition: clufactor.h:173
Exception classes for SoPlex.
#define init2DR(elem, ring)
Definition: cring.h:25
void solveUleftNoNZ(Real eps, Real *vec, Real *rhs, int *rhsidx, int rhsn)
Definition: clufactor.cpp:4283
Real maxabs
maximum abs number in L and U
Definition: clufactor.h:189
int vSolveRight4update3(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int rn, Real *vec2, Real eps2, Real *rhs2, int *ridx2, int rn2, Real *vec3, Real eps3, Real *rhs3, int *ridx3, int rn3, Real *forest, int *forestNum, int *forestIdx)
Definition: clufactor.cpp:5778
#define removeDR(ring)
Definition: cring.h:33
U u
U matrix.
Definition: clufactor.h:200
void minRowMem(int size)
Definition: clufactor.cpp:2870
void vSolveLeft3sparse(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int &rn, Real *vec2, int *idx2, Real *rhs2, int *ridx2, int &rn2, Real *vec3, int *idx3, Real *rhs3, int *ridx3, int &rn3)
sparse version of solving 3 systems of equations
Definition: clufactor.cpp:6194
Real * s_max
maximum absolute value per row (or -1)
Definition: clufactor.h:87
static void enQueueMin(int *heap, int *size, int elem)
Definition: clufactor.cpp:123
int size
size of array idx
Definition: clufactor.h:141
R & value(int n)
Reference to value of n &#39;th nonzero.
Definition: svectorbase.h:253
int * rorig
original row permutation
Definition: clufactor.h:176
void update(int p_col, Real *p_work, const int *p_idx, int num)
Definition: clufactor.cpp:1277
L l
L matrix.
Definition: clufactor.h:198
void solveUright(Real *wrk, Real *vec) const
Definition: clufactor.cpp:3084
Dring * elem
Array of ring elements.
Definition: clufactor.h:122
void solveLeft(Real *vec, Real *rhs)
Definition: clufactor.cpp:4143
#define ASSERT_WARN(prefix, expr)
Macro to turn some assertions into warnings.
Definition: spxdefines.h:77
Real initMaxabs
maximum abs number in initail Matrix
Definition: clufactor.h:188
int mkwtz
markowitz number of pivot
Definition: clufactor.h:62
Pring * pivot_col
column index handlers for Real linked list
Definition: clufactor.h:91
int vSolveLeft2(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int rn, Real *vec2, Real *rhs2, int *ridx2, int rn2)
Definition: clufactor.cpp:6102
Real * diag
Array of pivot elements.
Definition: clufactor.h:199
Perm row
row permutation matrices
Definition: clufactor.h:195
Dring * elem
Array of ring elements.
Definition: clufactor.h:140
Perm col
column permutation matrices
Definition: clufactor.h:196
void solveUpdateRight(Real *vec)
Definition: clufactor.cpp:3428
int * orig
orig[p] original index from p
Definition: clufactor.h:109
int solveRight4update(Real *vec, int *nonz, Real eps, Real *rhs, Real *forest, int *forestNum, int *forestIdx)
Definition: clufactor.cpp:3519
void vSolveLright(Real *vec, int *ridx, int &rn, Real eps)
Definition: clufactor.cpp:4627
Real lMemMult
factor of minimum Memory * number of nonzeros
Definition: clufactor.h:193
void minColMem(int size)
Definition: clufactor.cpp:2885
void eliminateRowSingletons()
Definition: clufactor.cpp:1877
virtual void start()=0
start timer, resume accounting user, system and real time.
Real * work
Working array: must always be left as 0!
Definition: clufactor.h:202
void forestUpdate(int col, Real *work, int num, int *nonz)
Performs the Forrest-Tomlin update of the LU factorization.
Definition: clufactor.cpp:712
virtual Real stop()=0
stop timer, return accounted user time.
void spx_alloc(T &p, int n=1)
Allocate memory.
Definition: spxalloc.h:48
void solveLleftForestNoNZ(Real *vec)
Definition: clufactor.cpp:4410
static const Real verySparseFactor4right
Definition: clufactor.cpp:34
int * len
used nonzeros per column vector
Definition: clufactor.h:148
#define SOPLEX_FACTOR_MARKER
Definition: clufactor.cpp:31
void solveUpdateLeft2(Real *vec1, Real *vec2)
Definition: clufactor.cpp:4052
double Real
Definition: spxdefines.h:218
#define MSG_DEBUG(x)
Definition: spxdefines.h:132
int & index(int n)
Reference to index of n &#39;th nonzero.
Definition: svectorbase.h:235
int solveLleftEps(Real *vec, int *nonz, Real eps)
Definition: clufactor.cpp:3957
int size
size of arrays val and idx
Definition: clufactor.h:159
void solveUright2(Real *work1, Real *vec1, Real *work2, Real *vec2)
Definition: clufactor.cpp:3147
SLinSolver::Status stat
Status indicator.
Definition: clufactor.h:184
Pring * pivot_row
row index handlers for Real linked list
Definition: clufactor.h:93
#define MSG_ERROR(x)
Prints out message x if the verbosity level is at least SPxOut::ERROR.
Definition: spxdefines.h:114
int used
used entries of arrays idx and val
Definition: clufactor.h:124
void solveLright(Real *vec)
Definition: clufactor.cpp:3288
void vSolveUpdateRightNoNZ(Real *vec, Real)
Definition: clufactor.cpp:5472
int startSize
size of array start
Definition: clufactor.h:162
void vSolveLright2(Real *vec, int *ridx, int &rn, Real eps, Real *vec2, int *ridx2, int &rn2, Real eps2)
Definition: clufactor.cpp:4695
Pring * pivot_colNZ
lists for columns to number of nonzeros
Definition: clufactor.h:92
static Real epsilonUpdate()
Definition: spxdefines.cpp:65
int factorCount
Number of factorizations.
Definition: clufactor.h:205
Real * val
hold nonzero values: this is only initialized in the end of the factorization with DEFAULT updates...
Definition: clufactor.h:144
int stage
stage of the structure
Definition: clufactor.h:89
int pos
position of pivot column in row
Definition: clufactor.h:61
int firstUnused
number of first unused L vector
Definition: clufactor.h:164
Temp temp
Temporary storage.
Definition: clufactor.h:213
void setPivot(const int p_stage, const int p_col, const int p_row, const Real val)
Definition: clufactor.cpp:267
void solveUpdateLeft(Real *vec)
Definition: clufactor.cpp:4022
void eliminateNucleus(const Real eps, const Real threshold)
Definition: clufactor.cpp:2526
void vSolveRight4update2sparse(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int &rn, Real eps2, Real *vec2, int *idx2, Real *rhs2, int *ridx2, int &rn2, Real *forest, int *forestNum, int *forestIdx)
sparse version of above method
Definition: clufactor.cpp:5698
int thedim
dimension of factorized matrix
Definition: clufactor.h:186
struct soplex::CLUFactor::U::Row row
int * start
starting positions in val and idx
Definition: clufactor.h:127
Debugging, floating point type and parameter definitions.
int size
size of arrays val and idx
Definition: clufactor.h:123
void dump() const
Definition: clufactor.cpp:2824
void spx_realloc(T &p, int n)
Change amount of allocated memory.
Definition: spxalloc.h:79
int * idx
indices of L vectors
Definition: clufactor.h:161
void factor(const SVector **vec, Real threshold, Real eps)
epsilon for zero detection
Definition: clufactor.cpp:2767
int * perm
perm[i] permuted index from i
Definition: clufactor.h:110
bool isConsistent() const
Definition: clufactor.cpp:2946
void eliminateColSingletons()
Definition: clufactor.cpp:1998
void solveUleft2(Real *work1, Real *vec1, Real *work2, Real *vec2)
Definition: clufactor.cpp:3645
Everything should be within this namespace.
void vSolveRightNoNZ(Real *vec, Real eps, Real *rhs, int *ridx, int rn)
Definition: clufactor.cpp:6022
void remaxRow(int p_row, int len)
Definition: clufactor.cpp:415
int vSolveLeft(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int rn)
Definition: clufactor.cpp:6074
int solveLleft2forest(Real *vec1, int *, Real *vec2, Real)
Definition: clufactor.cpp:3712
void vSolveLeftNoNZ(Real eps, Real *vec, Real *rhs, int *ridx, int rn)
Definition: clufactor.cpp:6227
int firstUpdate
number of first update L vector
Definition: clufactor.h:163
Pring pivots
ring of selected pivot rows
Definition: clufactor.h:90
int vSolveLeft3(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int rn, Real *vec2, Real *rhs2, int *ridx2, int rn2, Real *vec3, Real *rhs3, int *ridx3, int rn3)
Definition: clufactor.cpp:6158
Real rowMemMult
factor of minimum Memory * number of nonzeros
Definition: clufactor.h:191
void solveLright2(Real *vec1, Real *vec2)
Definition: clufactor.cpp:3349
Dring list
Double linked ringlist of vector indices in the order they appear in the row file.
Definition: clufactor.h:119
int vSolveRight4update2(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int rn, Real *vec2, Real eps2, Real *rhs2, int *ridx2, int rn2, Real *forest, int *forestNum, int *forestIdx)
Definition: clufactor.cpp:5578
Timer * factorTime
Time spent in factorizations.
Definition: clufactor.h:204
void clear()
clears the structure
Definition: clufactor.cpp:228
int solveLeft2(Real *vec1, int *nonz, Real *vec2, Real eps, Real *rhs1, Real *rhs2)
Definition: clufactor.cpp:4178
void init(int p_dim)
initialization
Definition: clufactor.cpp:220
static int deQueueMax(int *heap, int *size)
Definition: clufactor.cpp:69
int solveLeftEps(Real *vec, Real *rhs, int *nonz, Real eps)
Definition: clufactor.cpp:4161
void vSolveUrightNoNZ(Real *vec, Real *rhs, int *ridx, int rn, Real eps)
Definition: clufactor.cpp:5083
void forestReMaxCol(int col, int len)
Definition: clufactor.cpp:613
Implementation of sparse LU factorization.
int * idx
hold row indices of nonzeros
Definition: clufactor.h:143
int idx
index of pivot row
Definition: clufactor.h:60
void eliminatePivot(int prow, int pos, Real eps)
Definition: clufactor.cpp:2430
void remaxCol(int p_col, int len)
Definition: clufactor.cpp:544
int * ridx
indices of rows of L
Definition: clufactor.h:174
int vSolveUright2(Real *vec, int *vidx, Real *rhs, int *ridx, int rn, Real eps, Real *vec2, Real *rhs2, int *ridx2, int rn2, Real eps2)
Definition: clufactor.cpp:5187
#define initDR(ring)
Definition: cring.h:23
Real colMemMult
factor of minimum Memory * number of nonzeros
Definition: clufactor.h:192
int updateRow(int r, int lv, int prow, int pcol, Real pval, Real eps)
Definition: clufactor.cpp:2294
int vSolveUpdateRight(Real *vec, int *ridx, int n, Real eps)
Definition: clufactor.cpp:5428
int * max
maximum available nonzeros per colunn: start[i] + max[i] == start[elem[i].next->idx] len[i] <= max[i]...
Definition: clufactor.h:149
static const Real verySparseFactor
Definition: clufactor.cpp:33
int makeLvec(int p_len, int p_row)
Definition: clufactor.cpp:2918
void updateSolutionVectorLright(Real change, int j, Real &vec, int *idx, int &nnz)
Definition: clufactor.cpp:4608
int * row
column indices of L vectors
Definition: clufactor.h:166
void vSolveLeft2sparse(Real eps, Real *vec, int *idx, Real *rhs, int *ridx, int &rn, Real *vec2, int *idx2, Real *rhs2, int *ridx2, int &rn2)
sparse version of solving 2 systems of equations
Definition: clufactor.cpp:6131
static Real epsilonPivot()
Definition: spxdefines.cpp:75
void minLMem(int size)
Definition: clufactor.cpp:2906
int * rbeg
start of rows in rval and ridx
Definition: clufactor.h:175
int * s_cact
lengths of columns of active submatrix
Definition: clufactor.h:88
void solveRight(Real *vec, Real *rhs)
Definition: clufactor.cpp:3548
void initFactorMatrix(const SVector **vec, const Real eps)
Definition: clufactor.cpp:1391
void solveLleft2(Real *vec1, int *, Real *vec2, Real)
Definition: clufactor.cpp:3778
void forestPackColumns()
Definition: clufactor.cpp:360
static void enQueueMax(int *heap, int *size, int elem)
Definition: clufactor.cpp:38
Exception class for status exceptions during the computationsThis class is derived from the SoPlex ex...
Definition: exceptions.h:89
The loaded matrix is singular.
Definition: slinsolver.h:60
int nzCnt
number of nonzeros in U
Definition: clufactor.h:187
void selectPivots(Real threshold)
Definition: clufactor.cpp:2075
Real * val
hold nonzero values
Definition: clufactor.h:125
bool isZero(Real a, Real eps=Param::epsilon())
returns true iff |a| <= eps
Definition: spxdefines.h:412
int * rperm
original row permutation
Definition: clufactor.h:177
int * start
starting positions in val and idx
Definition: clufactor.h:165
int * idx
hold column indices of nonzeros
Definition: clufactor.h:126
int used
used entries of array idx
Definition: clufactor.h:142
void solveRight2(Real *vec1, Real *vec2, Real *rhs1, Real *rhs2)
Definition: clufactor.cpp:3593
int vSolveUright(Real *vec, int *vidx, Real *rhs, int *ridx, int rn, Real eps)
Definition: clufactor.cpp:4975
int * s_mark
marker
Definition: clufactor.h:86
int solveUrightEps(Real *vec, int *nonz, Real eps, Real *rhs)
Definition: clufactor.cpp:3104
Real * val
values of L vectors
Definition: clufactor.h:160
void spx_free(T &p)
Release memory.
Definition: spxalloc.h:110
void solveLleftNoNZ(Real *vec)
Definition: clufactor.cpp:4542
static int deQueueMin(int *heap, int *size)
Definition: clufactor.cpp:154