ADMB Documentation  -a65f1c97
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hs_sparse.cpp
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Author: David Fournier
5  * Copyright (c) 2009-2012 ADMB foundation
6  *
7  * This code is inspired by the CSparse package written by Timothy A. Davis.
8  * It has been extensively modified for compliance with ADMB.
9  *
10  * License: LGPL
11  */
12 
13 #include <fvar.hpp>
14 //#include <admodel.h>
15 //#include <df1b2fun.h>
16 //#include <adrndeff.h>
17 #define XCONST const
18 #include "hs.h"
19 //pthread_mutex_t mutex_dfpool = PTHREAD_MUTEX_INITIALIZER;
20 
21 #define USE_ADJOINT_CODE
22 void report_derivatives(const dvar_vector& x);
23 
24 static void xxx(int i){;}
25 static void xxx(ivector& i){;}
26 static void xxxv(ivector& x)
27 {
28  int mmin=x.indexmin();
29  int mmax=x.indexmax();
30  for (int i=mmin;i<=mmax;i++)
31  {
32  switch (x(i))
33  {
34  case 0:
35  cout << "not used" << endl;
36  break;
37  case 1:
38  xxx(x);
39  break;
40  default:
41  xxx(x);
42  break;
43  }
44  }
45 }
46 //int varchol(XCONST dvar_hs_smatrix &A, XCONST hs_symbolic &S,
47 //dvar_hs_smatrix &L, laplace_approximation_calculator * );
48 int varchol(XCONST dvar_hs_smatrix &A, XCONST hs_symbolic &S,
49  dvar_hs_smatrix &L, dcompressed_triplet & sparse_triplet2);
50 
51 int tmpxchol(XCONST hs_smatrix &A, XCONST hs_symbolic &S, hs_smatrix &L,
52  ivector & xcount);
53 
54 hs_smatrix cs_multiply(const hs_smatrix &A, const hs_smatrix &B);
55 int cholnew(XCONST hs_smatrix &A, XCONST hs_symbolic &S, hs_smatrix &L);
56 
57 // Utility function: p [0..n] = cumulative sum of c [0..n-1],
58 // and then copy p [0..n-1] into c
59  double cs_cumsum (ivector &p, ivector &c, int n)
60 {
61  int i, nz = 0 ;
62  double nz2 = 0 ;
63  for (i = 0 ; i < n ; i++)
64  {
65  p [i] = nz ;
66  nz += c [i] ;
67  nz2 += c [i] ;// also in double to avoid int overflow
68  c [i] = p [i] ;// also copy p[0..n-1] back into c[0..n-1]
69  }
70  p [n] = nz ;
71  return (nz2) ; // return sum (c [0..n-1])
72 }
73 
74 // clear w
75  int cs_wclear (int mark, int lemax, ivector &w, int n)
76 {
77  int k ;
78  if (mark < 2 || (mark + lemax < 0))
79  {
80  for (k = 0 ; k < n ; k++) if (w [k] != 0) w [k] = 1 ;
81  mark = 2 ;
82  }
83  return (mark) ; // at this point, w [0..n-1] < mark holds
84 }
85 
86 // Find C = A'
87  void cs_transpose (XCONST hs_smatrix &_A, int values, hs_smatrix &C)
88 {
89  ADUNCONST(hs_smatrix,A)
90  int p, q, j;
91 
92  int n = A.n ;
93  int m = n;
94  ivector & Ap=A.p;
95  ivector & Ai=A.i;
96  dvector & Ax=A.x;
97 
98  ivector & Cp=C.p;
99  ivector & Ci=C.i;
100  dvector & Cx=C.x;
101 
102  ivector w(0,n-1); // workspace
103  w.initialize();
104 
105  for (p = 0 ; p < Ap [n] ; p++)
106  w [Ai [p]]++ ; // row counts
107  cs_cumsum (Cp, w, m) ; // row pointers
108  for (j = 0 ; j < n ; j++)
109  {
110  for (p = Ap [j] ; p < Ap [j+1] ; p++)
111  {
112  Ci [q = w [Ai [p]]++] = j ; // place A(i,j) as entry C(j,i)
113  Cx [q] = Ax [p] ;
114  }
115  }
116  return;
117 }
118 
119  void cs_transpose (XCONST dvar_hs_smatrix &_A, int values, dvar_hs_smatrix &C)
120 {
121  ADUNCONST(dvar_hs_smatrix,A)
122  int p, q, j;
123 
124  int n = A.n ;
125  int m = n;
126  ivector & Ap=A.p;
127  ivector & Ai=A.i;
128  dvar_vector & Ax=A.x;
129 
130  ivector & Cp=C.p;
131  ivector & Ci=C.i;
132  dvar_vector & Cx=C.x;
133 
134  ivector w(0,n-1); // workspace
135  w.initialize();
136 
137  for (p = 0 ; p < Ap [n] ; p++)
138  w [Ai [p]]++ ; // row counts
139  cs_cumsum (Cp, w, m) ; // row pointers
140  for (j = 0 ; j < n ; j++)
141  {
142  for (p = Ap [j] ; p < Ap [j+1] ; p++)
143  {
144  Ci [q = w [Ai [p]]++] = j ; // place A(i,j) as entry C(j,i)
145  Cx [q] = Ax [p] ;
146  }
147  }
148  return;
149 }
150 
151 
152 //Sparse matrix XCONSTructor (compressed format) from dmatrix in triplet format
154 {
155  dmatrix tmp(1,n,1,m);
156  tmp.initialize();
157  int nz = M.indexmax()- M.indexmin() + 1;
158  for (int i=1;i<=nz;i++)
159  {
160  tmp(M(1,i),M(2,i))=M(i);
161  if (M(1,i) != M(2,i))
162  {
163  tmp(M(2,i),M(1,i))=M(i);
164  }
165  }
166  return tmp;
167 }
168 
170 {
171  int n=M.get_n();
172  int m=M.get_m();
173  dvar_matrix tmp(1,n,1,m);
174  tmp.initialize();
175  int nz = M.indexmax()- M.indexmin() + 1;
176  for (int i=1;i<=nz;i++)
177  {
178  tmp(M(1,i),M(2,i))=M(i);
179  if (M(1,i) != M(2,i))
180  {
181  tmp(M(2,i),M(1,i))=M(i);
182  }
183  }
184  return tmp;
185 }
186 
188 {
189  int n=M.get_n();
190  int m=M.get_m();
191  dvar_matrix tmp(1,n,1,m);
192  tmp.initialize();
193  int nz = M.indexmax()- M.indexmin() + 1;
194  for (int i=1;i<=nz;i++)
195  {
196  tmp(M(1,i),M(2,i))=M(i);
197  }
198  return tmp;
199 }
200 
201 
203 {
204  int n=M.get_n();
205  int m=M.get_m();
206  dmatrix tmp(1,n,1,m);
207  tmp.initialize();
208  int nz = M.indexmax()- M.indexmin() + 1;
209  for (int i=1;i<=nz;i++)
210  {
211  tmp(M(1,i),M(2,i))=M(i);
212  }
213  return tmp;
214 }
215 
217 {
218  int n=M.get_n();
219  int m=M.get_m();
220  dmatrix tmp(1,n,1,m);
221  tmp.initialize();
222  int nz = M.indexmax()- M.indexmin() + 1;
223  for (int i=1;i<=nz;i++)
224  {
225  tmp(M(1,i),M(2,i))=M(i);
226  if (M(1,i) != M(2,i))
227  {
228  tmp(M(2,i),M(1,i))=M(i);
229  }
230  }
231  return tmp;
232 }
233 
235 {
236  dvar_matrix tmp(1,n,1,m);
237  int nz = M.indexmax()- M.indexmin() + 1;
238  for (int i=1;i<=nz;i++)
239  {
240  tmp(M(1,i),M(2,i))=M(i);
241  if (M(1,i) != M(2,i))
242  {
243  tmp(M(2,i),M(1,i))=M(i);
244  }
245  }
246  return tmp;
247 }
248 
249 
250 hs_smatrix::hs_smatrix(int _n, XCONST dcompressed_triplet &_M)
251 {
253 
254  n = _n;
255  m = n; // May remove m from code; only square matrices needed
256 
257  int nz = M.indexmax()- M.indexmin() + 1;
258  nzmax = nz;
259 
260  int k;
261 
262  // Matrix in triplet format
263  ivector Ti(1,nz);
264  ivector tmp=(M.get_coords())(1);
265  Ti=tmp-1;
266  Ti.shift(0);
267 
268 
269  ivector Tj(1,nz);
270  ivector tmp1=(M.get_coords())(2);
271  Tj=tmp1-1;
272  Tj.shift(0);
273 
274  dvector Tx(1,nz);
275  Tx = M.get_x();
276  Tx.shift(0);
277 
278  if( min(Ti)<0 || max(Ti)>(n-1) || max(Tj)>(n-1) || min(Tj)<0)
279  cout << "Error #2 in hs_smatrix::hs_smatrix" << endl;
280 
281  int lower_tri=0;
282  for (k = 0 ; k < nz ; k++)
283  lower_tri += Ti[k]>Tj[k];
284  if(lower_tri)
285  cout << "hs_smatrix::hs_smatrix: M must be upper triangular" << endl;
286 
287  // Matrix in compressed format
288  p.allocate(0,n);
289  p = 0;
290  i.allocate(0,nzmax-1);
291  x.allocate(0,nzmax-1);
292  ivector & Cp=p;
293  ivector & Ci=i;
294  dvector & Cx=x;
295 
296  ivector w(0,n-1); // get workspace
297  w.initialize();
298 
299  // Does the compression
300  int P; // Originally p
301  for (k = 0 ; k < nz ; k++) w [Tj [k]]++ ; // column counts
302  cs_cumsum(Cp, w, n) ; // column pointers
303  for (k = 0 ; k < nz ; k++)
304  {
305  P = w [Tj [k]]++;
306  Ci [P] = Ti [k] ;
307  Cx [P] = Tx [k] ;
308  }
309 }
310 
311 hs_smatrix::hs_smatrix(const dcompressed_triplet &_M)
312 {
314 
315  m = M.get_n();
316  n = M.get_m();
317 
318  int nz = M.indexmax()- M.indexmin() + 1;
319  nzmax = nz;
320 
321  int k;
322 
323  // Matrix in triplet format
324  ivector Ti(1,nz);
325  ivector tmp=(M.get_coords())(1);
326  Ti=tmp-1;
327  Ti.shift(0);
328 
329 
330  ivector Tj(1,nz);
331  ivector tmp1=(M.get_coords())(2);
332  Tj=tmp1-1;
333  Tj.shift(0);
334 
335  dvector Tx(1,nz);
336  Tx = M.get_x();
337  Tx.shift(0);
338 
339  if( min(Ti)<0 || max(Ti)>(n-1) || max(Tj)>(m-1) || min(Tj)<0)
340  cout << "Error #2 in hs_smatrix::hs_smatrix" << endl;
341 
342  int lower_tri=0;
343  for (k = 0 ; k < nz ; k++)
344  lower_tri += Ti[k]>Tj[k];
345  if(lower_tri)
346  cout << "hs_smatrix::hs_smatrix: M must be upper triangular" << endl;
347 
348  // Matrix in compressed format
349  p.allocate(0,n);
350  p = 0;
351  i.allocate(0,nzmax-1);
352  x.allocate(0,nzmax-1);
353  ivector & Cp=p;
354  ivector & Ci=i;
355  dvector & Cx=x;
356 
357  ivector w(0,m-1); // get workspace
358  w.initialize();
359 
360  // Does the compression
361  int P; // Originally p
362  for (k = 0 ; k < nz ; k++) w [Tj [k]]++ ; // column counts
363  cs_cumsum(Cp, w, n) ; // column pointers
364  for (k = 0 ; k < nz ; k++)
365  {
366  P = w [Tj [k]]++;
367  Ci [P] = Ti [k];
368  Cx [P] = Tx [k] ;
369  }
370 }
371 
372 dvar_hs_smatrix::dvar_hs_smatrix(int _n, XCONST dvar_compressed_triplet &_M)
373 {
375  n = _n;
376  m = n; // May remove m from code; only square matrices needed
377 
378  int nz = M.indexmax()- M.indexmin() + 1;
379  nzmax = nz;
380 
381  int k;
382 
383  // Matrix in triplet format
384  ivector Ti(1,nz);
385  ivector tmp=(M.get_coords())(1);
386  Ti=tmp-1;
387  Ti.shift(0);
388 
389 
390  ivector Tj(1,nz);
391  ivector tmp1=(M.get_coords())(2);
392  Tj=tmp1-1;
393  Tj.shift(0);
394 
395  dvar_vector Tx(1,nz);
396  Tx = M.get_x();
397  Tx.shift(0);
398 
399  if( min(Ti)<0 || max(Ti)>(n-1) || max(Tj)>(n-1) || min(Tj)<0)
400  cout << "Error #2 in dvar_hs_smatrix::dvar_hs_smatrix" << endl;
401 
402  int lower_tri=0;
403  for (k = 0 ; k < nz ; k++)
404  lower_tri += Ti[k]>Tj[k];
405  if(lower_tri)
406  cout << "dvar_hs_smatrix::dvar_hs_smatrix: M must be upper triangular"
407  << endl;
408 
409  // Matrix in compressed format
410  p.allocate(0,n);
411  p = 0;
412  i.allocate(0,nzmax-1);
413  x.allocate(0,nzmax-1);
414  ivector & Cp=p;
415  ivector & Ci=i;
416  dvar_vector & Cx=x;
417 
418  ivector w(0,n-1); // get workspace
419  w.initialize();
420 
421  // Does the compression
422  int P; // Originally p
423  for (k = 0 ; k < nz ; k++) w [Tj [k]]++ ; // column counts
424  cs_cumsum(Cp, w, n) ; // column pointers
425  for (k = 0 ; k < nz ; k++)
426  {
427  P = w [Tj [k]]++;
428  Ci [P] = Ti [k];
429  Cx [P] = Tx [k] ;
430  }
431 }
432 
433 hs_smatrix::hs_smatrix(int _n, int _nzmax)
434 {
435  nzmax = _nzmax;
436  n = _n;
437  m = _n; // May get rid of m later; only square matrices needed
438 
439  p.allocate(0,n);
440  p = 0;
441  i.allocate(0,nzmax-1);
442  i = 0;
443  x.allocate(0,nzmax-1);
444  x = 0.0;
445 }
446 
447 dvar_hs_smatrix::dvar_hs_smatrix(int _n, int _nzmax)
448 {
449  nzmax = _nzmax;
450  n = _n;
451  m = _n; // May get rid of m later; only square matrices needed
452 
453  p.allocate(0,n);
454  p = 0;
455  i.allocate(0,nzmax-1);
456  i = 0;
457  x.allocate(0,nzmax-1);
458  x = 0.0;
459 }
460 
461 // Convert cs to hs_smatrix
462 hs_smatrix::hs_smatrix(XCONST cs *A)
463 {
464  int j;
465  nzmax = A->nzmax;
466  n = A->n;
467  m = n;
468 
469  p.allocate(0,n);
470  for (j = 0 ; j <= n ; j++)
471  p[j] = A->p[j];
472 
473  i.allocate(0,nzmax-1);
474  for (j = 0 ; j < nzmax ; j++)
475  i[j] = A->i[j];
476 
477  x.allocate(0,nzmax-1);
478  for (j = 0 ; j < nzmax ; j++)
479  x[j] = A->x[j];
480 }
481 
482 // Extends nzmax; new entries initialized to zero
483 void hs_smatrix::reallocate(int _nzmax)
484 {
485  ivector tmp(0,nzmax-1);
486  tmp=i;
487  i.deallocate();
488  i.allocate(0,_nzmax-1);
489  i(nzmax,_nzmax-1) = 0;
490  i(0,nzmax-1) = tmp;
491 
492  dvector tmpx(0,nzmax-1);
493  tmpx=x;
494  x.deallocate();
495  x.allocate(0,_nzmax-1);
496  x(nzmax,_nzmax-1) = 0.0;
497  x(0,nzmax-1) = tmpx;
498 
499  nzmax = _nzmax;
500 }
501 
502 void dvar_hs_smatrix::reallocate(int _nzmax)
503 {
504  ivector tmp(0,nzmax-1);
505  tmp=i;
506  i.deallocate();
507  i.allocate(0,_nzmax-1);
508  i(nzmax,_nzmax-1) = 0;
509  i(0,nzmax-1) = tmp;
510 
511  dvar_vector tmpx(0,nzmax-1);
512  tmpx=x;
513  x.deallocate();
514  x.allocate(0,_nzmax-1);
515  x(nzmax,_nzmax-1) = 0.0;
516  x(0,nzmax-1) = tmpx;
517 
518  nzmax = _nzmax;
519 }
520 
521 dvar_hs_smatrix::dvar_hs_smatrix(XCONST dvar_hs_smatrix &A)
522 {
523  nzmax = A.nzmax;
524  n = A.n;
525  m = n; // May get rid of m later; only square matrices needed
526 
527  p.allocate(0,n);
528  i.allocate(0,nzmax-1);
529  x.allocate(0,nzmax-1);
530  p = A.p;
531  i = A.i;
532  x = A.x;
533 }
534 
535 hs_smatrix::hs_smatrix(XCONST hs_smatrix &A)
536 {
537  nzmax = A.nzmax;
538  n = A.n;
539  m = n; // May get rid of m later; only square matrices needed
540 
541  p.allocate(0,n);
542  i.allocate(0,nzmax-1);
543  x.allocate(0,nzmax-1);
544  p = A.p;
545  i = A.i;
546  x = A.x;
547 }
548 
549 hs_smatrix& hs_smatrix::operator=(XCONST hs_smatrix &A)
550 {
551  if((n != A.n)||(nzmax != A.nzmax))
552  cout << "hs_smatrix&: lhs and rhs dimensions differ" << endl;
553  else
554  {
555  p = A.p;
556  i = A.i;
557  x = A.x;
558  }
559 
560  return *this;
561 }
562 
563 dvar_hs_smatrix& dvar_hs_smatrix::operator=(XCONST dvar_hs_smatrix &A)
564 {
565  if((n != A.n)||(nzmax != A.nzmax))
566  cout << "dvar_hs_smatrix&: lhs and rhs dimensions differ" << endl;
567  else
568  {
569  p = A.p;
570  i = A.i;
571  x = A.x;
572  }
573 
574  return *this;
575 }
576 
577 // Allocate Cholesky factor
578 hs_smatrix::hs_smatrix(XCONST hs_symbolic &S)
579 {
580  nzmax = S.cp[S.n];
581  n = S.n;
582  m = n;
583 
584  p.allocate(0,n);
585  i.allocate(0,nzmax-1);
586  x.allocate(0,nzmax-1);
587 }
588 
589 dvar_hs_smatrix::dvar_hs_smatrix(XCONST hs_symbolic &S)
590 {
591  nzmax = S.cp[S.n];
592  n = S.n;
593  m = n;
594 
595  p.allocate(0,n);
596  i.allocate(0,nzmax-1);
597  x.allocate(0,nzmax-1);
598 }
599 
600 // For determinant calculations: sum(log(diag(L)).
601 double hs_smatrix::trace_log(int & sgn)
602 {
603  sgn=0;
604  double ret = 0.0;
605  for (int j = 0 ; j < n ; j++)
606  {
607  for (int k = p [j] ; k < p [j+1] ; k++)
608  {
609  if(j==i[k])
610  {
611  //cout << " k = " << k << " x[k] = " << x[k] << endl;
612  if(x[k]>0.0)
613  ret += log(x[k]);
614  else if (x[k]<0.0)
615  {
616  ret += log(-x[k]);
617  sgn++;
618  }
619  else
620  {
621  cerr << "!!!! trace_log: zero diagonal element " << endl;
622  sgn=-1;
623  break;
624  }
625  }
626  if (sgn==-1) break;
627  }
628  if (sgn==-1) break;
629  }
630  sgn=sgn%2;
631  return(ret);
632 }
633 
634 dvariable dvar_hs_smatrix::trace_log(int & sgn)
635 {
636  sgn=0;
637  dvariable ret = 0.0;
638  for (int j = 0 ; j < n ; j++)
639  {
640  for (int k = p [j] ; k < p [j+1] ; k++)
641  {
642  if(j==i[k])
643  {
644  //cout << " k = " << k << " x[k] = " << x[k] << endl;
645  if(x[k]>0.0)
646  ret += log(x[k]);
647  else if (x[k]<0.0)
648  {
649  ret += log(-x[k]);
650  sgn++;
651  }
652  else
653  {
654  cerr << "!!!! trace_log: zero diagonal element " << endl;
655  sgn=-1;
656  break;
657  }
658  }
659  if (sgn==-1) break;
660  }
661  if (sgn==-1) break;
662  }
663  sgn=sgn%2;
664  return(ret);
665 }
666 dvariable ln_det(XCONST dvar_hs_smatrix& M)
667 {
668  int sgn;
669  return ln_det(M,sgn);
670 }
671 
672 
673 dvariable ln_det(XCONST dvar_hs_smatrix& _M,int & sgn)
674 {
675  ADUNCONST(dvar_hs_smatrix,M)
676  return M.trace_log(sgn);
677 }
678 
679 double ln_det(XCONST hs_smatrix& _M)
680 {
681  ADUNCONST(hs_smatrix,M)
682  int sgn;
683  return M.trace_log(sgn);
684 }
685 double ln_det(XCONST hs_smatrix& _M,int & sgn)
686 {
687  ADUNCONST(hs_smatrix,M)
688  return M.trace_log(sgn);
689 }
690 
691 int hs_smatrix::print()
692 {
693  cout << "Sparse matrix in compressed form (i,x):" << endl;
694  for (int j = 0 ; j < n ; j++)
695  {
696  cout << " col " << j << " : locations " << p[j] << " to " << p[j+1]-1
697  << endl;
698  for (int P = p [j] ; P < p [j+1] ; P++)
699  cout << i [P] << " " << x [P] << endl;
700  }
701  return(0);
702 }
703 
704 int hs_smatrix::print_pattern()
705 {
706  cout << "Sparseness pattern:" << endl;
707  for (int j = 0 ; j < n ; j++)
708  {
709  for (int k = 0 ; k < n ; k++)
710  {
711  int tmp=0;
712  for (int kk = p[k] ; kk < p[k+1] ; kk++)
713  tmp += (i[kk]==j);
714  if(tmp)
715  cout << "x";
716  else
717  cout << " ";
718  }
719  cout << endl;
720  }
721  return(0);
722 }
723 
724 // Print matrix transpose with zeros
725 int hs_smatrix::print_trans_zeros()
726 {
727  for(int k = 0 ; k < n ; k++) // cols
728  {
729  int kk = p[k];
730  for(int j = 0 ; j < n ; j++) // rows
731  if(i[kk]==j)
732  {
733  cout << x[kk] << "\t";
734  kk++;
735  }
736  else
737  cout << "0\t";
738  cout << endl;
739  }
740  return(0);
741 }
742 
743 // Find nonzero pattern of Cholesky L(k,1:k-1) using etree and triu(A(:,k))
744 int cs_ereach (XCONST hs_smatrix &_A, int k, XCONST ivector &parent, ivector &s,
745  ivector &w)
746 {
747  ADUNCONST(hs_smatrix,A)
748  int i, p, n, len, top;
749 
750  n = A.n;
751  top = n;
752 
753  ivector & Ap=A.p;
754  ivector & Ai=A.i;
755 
756  CS_MARK (w, k) ; /* mark node k as visited */
757  for (p = Ap [k] ; p < Ap [k+1] ; p++)
758  {
759  i = Ai [p] ; /* A(i,k) is nonzero */
760  if (i > k) continue ; /* only use upper triangular part of A */
761  for (len = 0 ; !CS_MARKED (w,i) ; i = parent [i]) /* traverse up etree*/
762  {
763  s [len++] = i ; /* L(k,i) is nonzero */
764  CS_MARK (w, i) ; /* mark i as visited */
765  }
766  while (len > 0) s [--top] = s [--len] ; /* push path onto stack */
767  }
768  for (p = top ; p < n ; p++) CS_MARK (w, s [p]) ; /* unmark all nodes */
769  CS_MARK (w, k) ; /* unmark node k */
770  return (top) ; /* s [top..n-1] contains pattern of L(k,:)*/
771 }
772 
773 int cs_ereach (XCONST dvar_hs_smatrix &_A, int k, XCONST ivector &parent,
774  ivector &s, ivector &w)
775 {
776  ADUNCONST(dvar_hs_smatrix,A)
777  int i, p, n, len, top;
778 
779  n = A.n;
780  top = n;
781 
782  ivector & Ap=A.p;
783  ivector & Ai=A.i;
784 
785  CS_MARK (w, k) ; /* mark node k as visited */
786  for (p = Ap [k] ; p < Ap [k+1] ; p++)
787  {
788  i = Ai [p] ; /* A(i,k) is nonzero */
789  if (i > k) continue ; /* only use upper triangular part of A */
790  for (len = 0 ; !CS_MARKED (w,i) ; i = parent [i]) /* traverse up etree*/
791  {
792  s [len++] = i ; /* L(k,i) is nonzero */
793  CS_MARK (w, i) ; /* mark i as visited */
794  }
795  while (len > 0) s [--top] = s [--len] ; /* push path onto stack */
796  }
797  for (p = top ; p < n ; p++) CS_MARK (w, s [p]) ; /* unmark all nodes */
798  CS_MARK (w, k) ; /* unmark node k */
799  return (top) ; /* s [top..n-1] contains pattern of L(k,:)*/
800 }
801 
802 /* C = A(p,p) where A and C are symmetric the upper part stored; pinv not p */
803 void hs_symperm(XCONST hs_smatrix &_A, XCONST ivector &pinv, hs_smatrix &C)
804 {
805  ADUNCONST(hs_smatrix,A)
806  int i, j, p, q, i2, j2;
807 
808  int n = A.n ;
809  ivector & Ap=A.p;
810  ivector & Ai=A.i;
811  dvector & Ax=A.x;
812  ivector w(0,n-1); /* get workspace */
813  w.initialize();
814  ivector & Cp=C.p;
815  ivector & Ci=C.i;
816  dvector & Cx=C.x;
817 
818  for (j = 0 ; j < n ; j++) /* count entries in each column of C */
819  {
820  j2 = (pinv[0]!=-1) ? pinv [j] : j ;/* column j of A is column j2 of C */
821  for (p = Ap [j] ; p < Ap [j+1] ; p++)
822  {
823  i = Ai [p] ;
824  if (i > j) continue ; /* skip lower triangular part of A */
825  i2 = (pinv[0]!=-1) ? pinv [i] : i ; /* row i of A is row i2 of C */
826  w [CS_MAX (i2, j2)]++ ; /* column count of C */
827  }
828  }
829  cs_cumsum (Cp, w, n) ; /* compute column pointers of C */
830  for (j = 0 ; j < n ; j++)
831  {
832  j2 = (pinv[0]!=-1) ? pinv [j] : j ;/* column j of A is column j2 of C */
833  for (p = Ap [j] ; p < Ap [j+1] ; p++)
834  {
835  i = Ai [p] ;
836  if (i > j) continue ; /* skip lower triangular part of A*/
837  i2 = (pinv[0]!=-1) ? pinv [i] : i ; /* row i of A is row i2 of C */
838 
839  q = w [CS_MAX (i2, j2)]++;
840  Ci [q] = CS_MIN (i2, j2) ;
841  Cx [q] = Ax [p] ;
842  }
843  }
844 }
845 void hs_symperm(XCONST dvar_hs_smatrix &_A, XCONST ivector &pinv,
846  dvar_hs_smatrix &C)
847 {
848  ADUNCONST(dvar_hs_smatrix,A)
849  int i, j, p, q, i2, j2;
850 
851  int n = A.n ;
852  ivector & Ap=A.p;
853  ivector & Ai=A.i;
854  dvar_vector & Ax=A.x;
855  ivector w(0,n-1); /* get workspace */
856  w.initialize();
857  ivector & Cp=C.p;
858  ivector & Ci=C.i;
859  dvar_vector & Cx=C.x;
860 
861  for (j = 0 ; j < n ; j++) /* count entries in each column of C */
862  {
863  j2 = (pinv[0]!=-1) ? pinv [j] : j ;/* column j of A is column j2 of C */
864  for (p = Ap [j] ; p < Ap [j+1] ; p++)
865  {
866  i = Ai [p] ;
867  if (i > j) continue ; /* skip lower triangular part of A */
868  i2 = (pinv[0]!=-1) ? pinv [i] : i ; /* row i of A is row i2 of C */
869  w [CS_MAX (i2, j2)]++ ; /* column count of C */
870  }
871  }
872  cs_cumsum (Cp, w, n) ; /* compute column pointers of C */
873  for (j = 0 ; j < n ; j++)
874  {
875  j2 = (pinv[0]!=-1) ? pinv [j] : j ;/* column j of A is column j2 of C */
876  for (p = Ap [j] ; p < Ap [j+1] ; p++)
877  {
878  i = Ai [p] ;
879  if (i > j) continue ; /* skip lower triangular part of A*/
880  i2 = (pinv[0]!=-1) ? pinv [i] : i ; /* row i of A is row i2 of C */
881 
882  q = w [CS_MAX (i2, j2)]++;
883  Ci [q] = CS_MIN (i2, j2) ;
884  Cx [q] = Ax [p] ;
885  }
886  }
887 }
888 
889 void myacc(int & p,int Lpi1,int ci,const ivector & Li,
890  dvector & x,const dvector & Lx,const double & lki)
891 {
892  for (p = Lpi1 ; p < ci ; p++)
893  {
894  x[Li[p]] -= Lx[p]*lki ;
895  }
896 }
897 
898 // Numeric Cholesky factorization (L is factor). Return 1 on success 0 otherwise
899 int chol(XCONST hs_smatrix& A,
900  XCONST hs_symbolic& T,
901  hs_smatrix& L)
902 {
903  //ADUNCONST(hs_symbolic,S)
904  hs_symbolic& S = (hs_symbolic&)T;
905  double d, lki;
906  int top, i, p, k, n;
907 
908  n = A.n ;
909 
910  ivector c(0,n-1); // int workspace
911  ivector s(0,n-1); // int workspace
912  dvector x(0,n-1) ; // double workspace
913 
914  ivector & cp=S.cp;
915  ivector & pinv=S.pinv;
916  ivector & parent=S.parent;
917 
918  hs_smatrix C(A);
919  C = A;
920  if(S.pinv[0]!=-1)
921  hs_symperm(A,pinv,C);
922 
923  ivector & Cp=C.p;
924  ivector & Ci=C.i;
925  dvector & Cx=C.x;
926 
927  ivector & Lp=L.p;
928  ivector & Li=L.i;
929  dvector & Lx=L.x;
930 
931  for (k = 0 ; k < n ; k++)
932  Lp [k] = c [k] = cp [k] ;
933 
934  for (k = 0 ; k < n ; k++) // compute L(:,k) for L*L' = C
935  {
936  // --- Nonzero pattern of L(k,:) ------------------------------------
937  top = cs_ereach (C, k, parent, s, c) ; // find pattern of L(k,:)
938  x [k] = 0 ; // x (0:k) is now zero
939  for (p = Cp [k] ; p < Cp [k+1] ; p++) // x = full(triu(C(:,k)))
940  {
941  if (Ci [p] <= k) x [Ci [p]] = Cx [p] ;
942  }
943  d = x [k] ; // d = C(k,k)
944  x [k] = 0 ; // clear x for k+1st iteration
945  // --- Triangular solve ---------------------------------------------
946  for ( ; top < n ; top++) // solve L(0:k-1,0:k-1) * x = C(:,k)
947  {
948  i = s [top] ; // s [top..n-1] is pattern of L(k,:)
949  lki = x [i] / Lx [Lp [i]] ; // L(k,i) = x (i) / L(i,i)
950  x [i] = 0 ; // clear x for k+1st iteration
951 
952 
953  int Lpi1=Lp[i]+1;
954  int ci=c[i];
955  for (p = Lpi1; p < ci ; p++)
956  {
957  x [Li [p]] -= Lx [p] * lki ;
958  }
959 
960  d -= lki * lki ; // d = d - L(k,i)*L(k,i)
961  p = c [i]++ ;
962  Li [p] = k ; // store L(k,i) in column i
963  Lx [p] = lki ;
964  }
965  // --- Compute L(k,k) -----------------------------------------------
966  if (d <= 0) return (0) ; // not pos def
967  p = c [k]++ ;
968  Li [p] = k ; // store L(k,k) = sqrt (d) in column k
969  Lx [p] = sqrt (d) ;
970  }
971  Lp [n] = cp [n] ; // finalize L
972  return (1);
973 }
974 // Numeric Cholesky factorization (L is factor).
975 // Return 1 on success; 0 otherwise
976 int tmpxchol1(XCONST hs_smatrix &A, XCONST hs_symbolic& T, hs_smatrix &L,
977  ivector & nxcount)
978 {
979  //ADUNCONST(hs_symbolic,S)
980  hs_symbolic& S = (hs_symbolic&)T;
981  double d, lki;
982  int top, i, p, k, n;
983 
984  n = A.n ;
985 
986  ivector c(0,n-1); /* int workspace */
987  ivector s(0,n-1); /* int workspace */
988  //dvector x(0,n-1) ; /* double workspace */
989  dmatrix x(0,n-1,1,nxcount) ; /* double workspace */
990 
991  ivector & cp=S.cp;
992  ivector & pinv=S.pinv;
993  ivector & parent=S.parent;
994 
995  hs_smatrix C(A);
996  C = A;
997  if(S.pinv[0]!=-1)
998  hs_symperm(A,pinv,C);
999 
1000  ivector & Cp=C.p;
1001  ivector & Ci=C.i;
1002  dvector & Cx=C.x;
1003 
1004  ivector & Lp=L.p;
1005  ivector & Li=L.i;
1006  dvector & Lx=L.x;
1007 
1008  // counters
1009  ivector Licount(Li.indexmin(),Li.indexmax());
1010  Licount.initialize();
1011  ivector Lxcount(Lx.indexmin(),Lx.indexmax());
1012  Lxcount.initialize();
1013  ivector xcount(x.indexmin(),x.indexmax());
1014  xcount.initialize();
1015 
1016  int dcount=0;
1017  int pcount=0;
1018  int icount=0;
1019  int lkicount=0;
1020 
1021  for (k = 0 ; k < n ; k++)
1022  {
1023  Lp [k] = c [k] = cp [k] ;
1024  }
1025 
1026  for (k = 0 ; k < n ; k++) /* compute L(:,k) for L*L' = C */
1027  {
1028  /* --- Nonzero pattern of L(k,:) ------------------------------------ */
1029  top = cs_ereach (C, k, parent, s, c) ; /* find pattern of L(k,:) */
1030  xcount[k]++;
1031  x (k,xcount(k)) = 0 ; /* x (0:k) is now zero */
1032  for (p = Cp [k] ; p < Cp [k+1] ; p++) /* x = full(triu(C(:,k))) */
1033  {
1034  if (Ci [p] <= k)
1035  {
1036  xcount[Ci[p]]++;
1037  x(Ci[p],xcount(Ci[p])) = Cx[p] ;
1038  }
1039  }
1040  d = x(k,xcount[k]) ; /* d = C(k,k) */
1041  dcount++;
1042  xcount[k]++;
1043  x(k,xcount[k]) = 0 ; /* clear x for k+1st iteration */
1044  /* --- Triangular solve --------------------------------------------- */
1045  for ( ; top < n ; top++) /* solve L(0:k-1,0:k-1) * x = C(:,k) */
1046  {
1047  i = s [top] ; /* s [top..n-1] is pattern of L(k,:) */
1048  icount++;
1049  lki = x (i,xcount[i]) / Lx [Lp [i]] ; /* L(k,i) = x (i) / L(i,i) */
1050  lkicount++;
1051  xcount[i]++;
1052  x (i,xcount[i]) = 0.0 ; /* clear x for k+1st iteration */
1053  for (p = Lp [i] + 1 ; p < c [i] ; p++)
1054  {
1055  x [Li [p]] -= Lx [p] * lki ;
1056  }
1057  d -= lki * lki ; /* d = d - L(k,i)*L(k,i) */
1058  p = c [i]++ ;
1059  pcount++;
1060  Li [p] = k ; /* store L(k,i) in column i */
1061  Licount[p]++;
1062  if (Licount(p)>1)
1063  {
1064  cerr << "Error unhandled case in chol" << endl;
1065  }
1066  Lx [p] = lki ;
1067  Lxcount[p]++;
1068  if (Lxcount(p)>1)
1069  {
1070  cerr << "Error unhandled case in chol" << endl;
1071  ad_exit(1);
1072  }
1073  }
1074  /* --- Compute L(k,k) ----------------------------------------------- */
1075  if (d <= 0) return (0) ; /* not pos def */
1076  p = c [k]++ ;
1077  pcount++;
1078  Li [p] = k ; /* store L(k,k) = sqrt (d) in column k */
1079  Licount[p]++;
1080  if (Licount(p)>1)
1081  {
1082  cerr << "Error unhandled case in chol" << endl;
1083  }
1084  Lx [p] = sqrt (d) ;
1085  Lxcount[p]++;
1086  if (Lxcount(p)>1)
1087  {
1088  cerr << "Error unhandled case in chol" << endl;
1089  ad_exit(1);
1090  }
1091  }
1092  Lp [n] = cp [n] ; /* finalize L */
1093  xxx(pcount);
1094  xxx(dcount);
1095  xxx(icount);
1096  xxx(lkicount);
1097  xxxv(Licount);
1098  xxxv(Lxcount);
1099  xxxv(xcount);
1100  return (1);
1101 }
1102 
1103 /* x(p) = b, for dense vectors x and b; p=NULL denotes identity */
1105 {
1106  if(p[0]==-1) // No permutation
1107  return(b);
1108  else
1109  {
1110  int n = p.indexmax()+1;
1111  dvector x(0,n-1);
1112  for (int k = 0 ; k < n ; k++)
1113  x [p [k]] = b [k] ;
1114  return (x) ;
1115  }
1116 }
1117 
1118 /* x = b(p), for dense vectors x and b; p=NULL denotes identity */
1120 {
1121  if(p[0]==-1) // No permutation
1122  return(b);
1123  else
1124  {
1125  int n = p.indexmax()+1;
1126  dvector x(0,n-1);
1127  for (int k = 0 ; k < n ; k++)
1128  x[k] = b[p[k]];
1129  return (x) ;
1130  }
1131 }
1132 
1134 {
1135  if(p[0]==-1) // No permutation
1136  return(b);
1137  else
1138  {
1139  int n = p.indexmax()+1;
1140  dvar_vector x(0,n-1);
1141  for (int k = 0 ; k < n ; k++)
1142  x[k] = b[p[k]];
1143  return (x) ;
1144  }
1145 }
1146 
1147 /* solve Lx=b where x and b are dense. x=b on input, solution on output. */
1148  dvector cs_lsolve (XCONST hs_smatrix & LL, XCONST dvector &y)
1149 {
1150  //ADUNCONST(hs_smatrix,L)
1151  hs_smatrix& L = (hs_smatrix&)LL;
1152  int p, j, n;
1153 
1154  n = L.n;
1155  dvector x(0,n-1);
1156  x=y;
1157 
1158  ivector & Lp=L.p;
1159  ivector & Li=L.i;
1160  dvector & Lx=L.x;
1161 
1162  for (j = 0 ; j < n ; j++)
1163  {
1164  x [j] /= Lx [Lp [j]] ;
1165  for (p = Lp [j]+1 ; p < Lp [j+1] ; p++)
1166  {
1167  x [Li [p]] -= Lx [p] * x [j] ;
1168  }
1169  }
1170  return (x) ;
1171 }
1172 
1173  dvar_vector cs_lsolve (XCONST dvar_hs_smatrix & LL, XCONST dvar_vector &y)
1174 {
1175  //ADUNCONST(dvar_hs_smatrix,L)
1176  dvar_hs_smatrix& L = (dvar_hs_smatrix&)LL;
1177  int p, j, n;
1178 
1179  n = L.n;
1180  dvar_vector x(0,n-1);
1181  x=y;
1182 
1183  ivector & Lp=L.p;
1184  ivector & Li=L.i;
1185  dvar_vector & Lx=L.x;
1186 
1187  for (j = 0 ; j < n ; j++)
1188  {
1189  x [j] /= Lx [Lp [j]] ;
1190  for (p = Lp [j]+1 ; p < Lp [j+1] ; p++)
1191  {
1192  x [Li [p]] -= Lx [p] * x [j] ;
1193  }
1194  }
1195  return (x) ;
1196 }
1197 
1198  dvar_vector cs_lsolve (XCONST dvar_hs_smatrix & LL, XCONST dvector &y)
1199 {
1200  //ADUNCONST(dvar_hs_smatrix,L)
1201  dvar_hs_smatrix& L = (dvar_hs_smatrix&)LL;
1202  int p, j, n;
1203 
1204  n = L.n;
1205  dvar_vector x(0,n-1);
1206  x=y;
1207 
1208  ivector & Lp=L.p;
1209  ivector & Li=L.i;
1210  dvar_vector & Lx=L.x;
1211 
1212  for (j = 0 ; j < n ; j++)
1213  {
1214  x [j] /= Lx [Lp [j]] ;
1215  for (p = Lp [j]+1 ; p < Lp [j+1] ; p++)
1216  {
1217  x [Li [p]] -= Lx [p] * x [j] ;
1218  }
1219  }
1220  return (x) ;
1221 }
1222 
1223 /* solve L'x=b where x and b are dense. x=b on input, solution on output. */
1224  dvector cs_ltsolve (XCONST hs_smatrix &LL, XCONST dvector &y)
1225 {
1226  //ADUNCONST(hs_smatrix,L)
1227  hs_smatrix& L = (hs_smatrix&)LL;
1228  int p, j, n;
1229 
1230  n = L.n;
1231  dvector x(0,n-1);
1232  x=y;
1233  ivector & Lp=L.p;
1234  ivector & Li=L.i;
1235  dvector & Lx=L.x;
1236 
1237  for (j = n-1 ; j >= 0 ; j--)
1238  {
1239  for (p = Lp [j]+1 ; p < Lp [j+1] ; p++)
1240  {
1241  x [j] -= Lx [p] * x [Li [p]] ;
1242  }
1243  x [j] /= Lx [Lp [j]] ;
1244  }
1245  return (x) ;
1246 }
1247 
1248  dvar_vector cs_ltsolve (XCONST dvar_hs_smatrix &LL, XCONST dvar_vector &y)
1249 {
1250  //ADUNCONST(dvar_hs_smatrix,L)
1251  dvar_hs_smatrix& L = (dvar_hs_smatrix&)LL;
1252  int p, j, n;
1253 
1254  n = L.n;
1255  dvar_vector x(0,n-1);
1256  x=y;
1257  ivector & Lp=L.p;
1258  ivector & Li=L.i;
1259  dvar_vector & Lx=L.x;
1260 
1261  for (j = n-1 ; j >= 0 ; j--)
1262  {
1263  for (p = Lp [j]+1 ; p < Lp [j+1] ; p++)
1264  {
1265  x [j] -= Lx [p] * x [Li [p]] ;
1266  }
1267  x [j] /= Lx [Lp [j]] ;
1268  }
1269  return (x) ;
1270 }
1271 
1272 // keep off-diagonal entries; drop diagonal entries
1273  int cs_diag(int i, int j, double aij, void *other) { return (i != j) ; }
1274 int cs_diag(int i, int j, const prevariable& aij, void *other)
1275  { return (i != j) ; }
1276 
1277 /* drop entries for which fkeep(A(i,j)) is false; return nz if OK, else -1 */
1278 int cs_fkeep (hs_smatrix &A, int (*fkeep) (int, int, double, void *),
1279  void *other)
1280 {
1281  int j, p, nz = 0 ;
1282 
1283  int n = A.n ;
1284  ivector & Ap=A.p;
1285  ivector & Ai=A.i;
1286  dvector & Ax=A.x;
1287 
1288  for (j = 0 ; j < n ; j++)
1289  {
1290  p = Ap [j] ; /* get current location of col j */
1291  Ap [j] = nz ; /* record new location of col j */
1292  for ( ; p < Ap [j+1] ; p++)
1293  {
1294  if (fkeep (Ai [p], j, Ax [p], other))
1295  {
1296  Ax [nz] = Ax [p] ; /* keep A(i,j) */
1297  Ai [nz++] = Ai [p] ;
1298  }
1299  }
1300  }
1301  Ap [n] = nz ; /* finalize A */
1302  return (nz) ;
1303 }
1304 
1305 int cs_fkeep (dvar_hs_smatrix &A, int (*fkeep) (int, int, const prevariable&,
1306  void *), void *other)
1307 {
1308  int j, p, nz = 0 ;
1309 
1310  int n = A.n ;
1311  ivector & Ap=A.p;
1312  ivector & Ai=A.i;
1313  dvar_vector & Ax=A.x;
1314 
1315  for (j = 0 ; j < n ; j++)
1316  {
1317  p = Ap [j] ; /* get current location of col j */
1318  Ap [j] = nz ; /* record new location of col j */
1319  for ( ; p < Ap [j+1] ; p++)
1320  {
1321  if (fkeep (Ai [p], j, Ax [p], other))
1322  {
1323  Ax [nz] = Ax [p] ; /* keep A(i,j) */
1324  Ai [nz++] = Ai [p] ;
1325  }
1326  }
1327  }
1328  Ap [n] = nz ; /* finalize A */
1329  return (nz) ;
1330 }
1331 
1332 /* x = x + beta * A(:,j), where x is a dense vector and A(:,j) is sparse */
1333 int cs_scatter(XCONST hs_smatrix &AA, int j, double beta, ivector &w,
1334  dvector &x, int mark, hs_smatrix &C, int nz)
1335 {
1336  //ADUNCONST(hs_smatrix,A)
1337  hs_smatrix& A = (hs_smatrix&)AA;
1338  int i, p;
1339  ivector & Ap=A.p;
1340  ivector & Ai=A.i;
1341  dvector & Ax=A.x;
1342  ivector & Ci=C.i;
1343  for (p = Ap [j] ; p < Ap [j+1] ; p++)
1344  {
1345  i = Ai [p] ; /* A(i,j) is nonzero */
1346  if (w [i] < mark)
1347  {
1348  w [i] = mark ; /* i is new entry in column j */
1349  Ci [nz++] = i ; /* add i to pattern of C(:,j) */
1350  x [i] = beta * Ax [p] ; /* x(i) = beta*A(i,j) */
1351  }
1352  else x [i] += beta * Ax [p] ; /* i exists in C(:,j) already */
1353  }
1354  return (nz) ;
1355 }
1356 
1357  //int cs_scatter(XCONST hs_smatrix &A, int j, double beta, ivector &w,
1358  // dvector &x, int mark, hs_smatrix &C, int nz)
1359  //{
1360  // int i, p;
1361  // ivector & Ap=A.p;
1362  // ivector & Ai=A.i;
1363  // dvector & Ax=A.x;
1364  // ivector & Ci=C.i;
1365  // for (p = Ap [j] ; p < Ap [j+1] ; p++)
1366  // {
1367  // i = Ai [p] ; /* A(i,j) is nonzero */
1368  // if (w [i] < mark)
1369  // {
1370  // w [i] = mark ; /* i is new entry in column j */
1371  // Ci [nz++] = i ; /* add i to pattern of C(:,j) */
1372  // x [i] = beta * Ax [p] ; /* x(i) = beta*A(i,j) */
1373  // }
1374  // else x [i] += beta * Ax [p] ; /* i exists in C(:,j) already */
1375  // }
1376  // return (nz) ;
1377  //}
1378 
1379 int cs_scatter(XCONST dvar_hs_smatrix &AA, int j, double beta, ivector &w,
1380  dvar_vector &x, int mark, dvar_hs_smatrix &C, int nz)
1381 {
1382  //ADUNCONST(dvar_hs_smatrix,A)
1383  dvar_hs_smatrix& A = (dvar_hs_smatrix&)AA;
1384  int i, p;
1385  ivector & Ap=A.p;
1386  ivector & Ai=A.i;
1387  dvar_vector & Ax=A.x;
1388  ivector & Ci=C.i;
1389  for (p = Ap [j] ; p < Ap [j+1] ; p++)
1390  {
1391  i = Ai [p] ; /* A(i,j) is nonzero */
1392  if (w [i] < mark)
1393  {
1394  w [i] = mark ; /* i is new entry in column j */
1395  Ci [nz++] = i ; /* add i to pattern of C(:,j) */
1396  x [i] = beta * Ax [p] ; /* x(i) = beta*A(i,j) */
1397  }
1398  else x [i] += beta * Ax [p] ; /* i exists in C(:,j) already */
1399  }
1400  return (nz) ;
1401 }
1402 
1403 /* C = alpha*A + beta*B */
1404 hs_smatrix cs_add(XCONST hs_smatrix &AA, XCONST hs_smatrix &BB, double alpha,
1405  double beta)
1406 {
1407  //ADUNCONST(hs_smatrix,A)
1408  //ADUNCONST(hs_smatrix,B)
1409  hs_smatrix& A = (hs_smatrix&)AA;
1410  hs_smatrix& B = (hs_smatrix&)BB;
1411  int p, j, nz = 0, anz,m, n, bnz;
1412 
1413  if (A.m != B.m || A.n != B.n)
1414  {
1415  cout << "!!!! Error in cs_add: A.m != B.m || A.n != B.n" << endl;
1416  exit(0);
1417  }
1418 
1419  m = A.m ; anz = A.p [A.n] ;
1420  n = B.n ;
1421 
1422  ivector & Bp=B.p;
1423  bnz = Bp [n] ;
1424  ivector w(0,m-1); // Workspace
1425  w.initialize();
1426 
1427  // Always assumes values == 1
1428  dvector x(0,m-1); // Workspace
1429  x.initialize();
1430 
1431  hs_smatrix C(n,anz + bnz);
1432  ivector & Cp=C.p;
1433  ivector & Ci=C.i;
1434  dvector & Cx=C.x;
1435 
1436  for (j = 0 ; j < n ; j++)
1437  {
1438  Cp [j] = nz ; /* column j of C starts here */
1439  nz = cs_scatter (A, j, alpha, w, x, j+1, C, nz) ; /* alpha*A(:,j)*/
1440  nz = cs_scatter (B, j, beta, w, x, j+1, C, nz) ; /* beta*B(:,j) */
1441  for (p = Cp [j] ; p < nz ; p++)
1442  Cx [p] = x [Ci [p]] ;
1443  }
1444  Cp [n] = nz ; /* finalize the last column of C */
1445  //cs_sprealloc (C, 0) ; Ignoring this. Must be picked up
1446  return (C) ;
1447 }
1448 
1449 dvar_hs_smatrix cs_add(XCONST dvar_hs_smatrix &AA, XCONST dvar_hs_smatrix &BB,
1450  double alpha, double beta)
1451 {
1452  //ADUNCONST(dvar_hs_smatrix,A)
1453  //ADUNCONST(dvar_hs_smatrix,B)
1454  dvar_hs_smatrix& A = (dvar_hs_smatrix&)AA;
1455  dvar_hs_smatrix& B = (dvar_hs_smatrix&)BB;
1456  int p, j, nz = 0, anz,m, n, bnz;
1457 
1458  if (A.m != B.m || A.n != B.n)
1459  {
1460  cout << "!!!! Error in cs_add: A.m != B.m || A.n != B.n" << endl;
1461  exit(0);
1462  }
1463 
1464  m = A.m ; anz = A.p [A.n] ;
1465  n = B.n ;
1466 
1467  ivector & Bp=B.p;
1468  bnz = Bp [n] ;
1469  ivector w(0,m-1); // Workspace
1470  w.initialize();
1471 
1472  // Always assumes values == 1
1473  dvar_vector x(0,m-1); // Workspace
1474  x.initialize();
1475 
1476  dvar_hs_smatrix C(n,anz + bnz);
1477  ivector & Cp=C.p;
1478  ivector & Ci=C.i;
1479  dvar_vector & Cx=C.x;
1480 
1481  for (j = 0 ; j < n ; j++)
1482  {
1483  Cp [j] = nz ; /* column j of C starts here */
1484  nz = cs_scatter (A, j, alpha, w, x, j+1, C, nz) ; /* alpha*A(:,j)*/
1485  nz = cs_scatter (B, j, beta, w, x, j+1, C, nz) ; /* beta*B(:,j) */
1486  for (p = Cp [j] ; p < nz ; p++)
1487  Cx [p] = x [Ci [p]] ;
1488  }
1489  Cp [n] = nz ; /* finalize the last column of C */
1490  //cs_sprealloc (C, 0) ; Ignoring this. Must be picked up
1491  return (C) ;
1492 }
1493 
1494 /* depth-first search and postorder of a tree rooted at node j */
1495 int cs_tdfs (int j, int k, ivector &head, XCONST ivector &next, ivector &post,
1496  ivector &stack)
1497 {
1498  int i, p, top = 0 ;
1499  stack [0] = j ; /* place j on the stack */
1500  while (top >= 0) /* while (stack is not empty) */
1501  {
1502  p = stack [top] ; /* p = top of stack */
1503  i = head [p] ; /* i = youngest child of p */
1504  if (i == -1)
1505  {
1506  top-- ; /* p has no unordered children left */
1507  post [k++] = p ; /* node p is the kth postordered node */
1508  }
1509  else
1510  {
1511  head [p] = next [i] ; /* remove i from children of p */
1512  stack [++top] = i ; /* start dfs on child node i */
1513  }
1514  }
1515  return (k) ;
1516 }
1517 
1522 ivector cs_amd (XCONST hs_smatrix &A) /* Implements only order == 1: Chol*/
1523 {
1524  int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1,
1525  k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi,
1526  ok, cnz, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, t ;
1527  unsigned int h ;
1528  /* --- Construct matrix C ----------------------------------------------- */
1529 
1530  int n = A.n ;
1531 
1532  hs_smatrix AT(n,A.nzmax);
1533  cs_transpose(A,0,AT);
1534 
1535  /* find dense threshold */
1536  dense = CS_MAX (16, (int)(10.0 * sqrt((double)n)));
1537  dense = CS_MIN (n-2, dense) ;
1538 
1539  hs_smatrix C = cs_add(A,AT);
1540  cs_fkeep (C, &cs_diag, NULL); // drop diagonal entries
1541  cnz = C.p [n] ;
1542  ivector P(0,n);
1543 
1544  t = cnz + cnz/5 + 2*n ; // add elbow room to C
1545  C.reallocate(t);
1546  ivector & Cp=C.p;
1547 
1548  ivector len(0,n);
1549  len.initialize();
1550  ivector nv(0,n);
1551  ivector next(0,n);
1552  ivector head(0,n);
1553  head.initialize();
1554  ivector elen(0,n);
1555  ivector degree(0,n);
1556  ivector w(0,n);
1557  ivector hhead(0,n);
1558  ivector &last = P ; /* use P as workspace for last */
1559 
1560  /* --- Initialize quotient graph ---------------------------------------- */
1561  for (k = 0 ; k < n ; k++) len [k] = Cp [k+1] - Cp [k] ;
1562  len [n] = 0 ;
1563  nzmax = C.nzmax ;
1564  ivector & Ci=C.i;
1565  for (i = 0 ; i <= n ; i++)
1566  {
1567  head [i] = -1 ; /* degree list i is empty */
1568  last [i] = -1 ;
1569  next [i] = -1 ;
1570  hhead [i] = -1 ; /* hash list i is empty */
1571  nv [i] = 1 ; /* node i is just one node */
1572  w [i] = 1 ; /* node i is alive */
1573  elen [i] = 0 ; /* Ek of node i is empty */
1574  degree [i] = len [i] ; /* degree of node i */
1575  }
1576  mark = cs_wclear (0, 0, w, n) ; /* clear w */
1577  elen [n] = -2 ; /* n is a dead element */
1578  Cp [n] = -1 ; /* n is a root of assembly tree */
1579  w [n] = 0 ; /* n is a dead element */
1580  /* --- Initialize degree lists ------------------------------------------ */
1581  for (i = 0 ; i < n ; i++)
1582  {
1583  d = degree [i] ;
1584  if (d == 0) /* node i is empty */
1585  {
1586  elen [i] = -2 ; /* element i is dead */
1587  nel++ ;
1588  Cp [i] = -1 ; /* i is a root of assembly tree */
1589  w [i] = 0 ;
1590  }
1591  else if (d > dense) /* node i is dense */
1592  {
1593  nv [i] = 0 ; /* absorb i into element n */
1594  elen [i] = -1 ; /* node i is dead */
1595  nel++ ;
1596  Cp [i] = CS_FLIP (n) ;
1597  nv [n]++ ;
1598  }
1599  else
1600  {
1601  if (head [d] != -1) last [head [d]] = i ;
1602  next [i] = head [d] ; /* put node i in degree list d */
1603  head [d] = i ;
1604  }
1605  }
1606  while (nel < n) /* while (selecting pivots) do */
1607  {
1608  /* --- Select node of minimum approximate degree -------------------- */
1609  for (k = -1 ; mindeg < n && (k = head [mindeg]) == -1 ; mindeg++) ;
1610  if (next [k] != -1) last [next [k]] = -1 ;
1611  head [mindeg] = next [k] ; /* remove k from degree list */
1612  elenk = elen [k] ; /* elenk = |Ek| */
1613  nvk = nv [k] ; /* # of nodes k represents */
1614  nel += nvk ; /* nv[k] nodes of A eliminated */
1615  /* --- Garbage collection ------------------------------------------- */
1616  if (elenk > 0 && cnz + mindeg >= nzmax)
1617  {
1618  for (j = 0 ; j < n ; j++)
1619  {
1620  if ((p = Cp [j]) >= 0) /* j is a live node or element */
1621  {
1622  Cp [j] = Ci [p] ; /* save first entry of object */
1623  Ci [p] = CS_FLIP (j) ; /* first entry is now CS_FLIP(j) */
1624  }
1625  }
1626  for (q = 0, p = 0 ; p < cnz ; ) /* scan all of memory */
1627  {
1628  if ((j = CS_FLIP (Ci [p++])) >= 0) /* found object j */
1629  {
1630  Ci [q] = Cp [j] ; /* restore first entry of object */
1631  Cp [j] = q++ ; /* new pointer to object j */
1632  for (k3 = 0 ; k3 < len [j]-1 ; k3++) Ci [q++] = Ci [p++] ;
1633  }
1634  }
1635  cnz = q ; /* Ci [cnz...nzmax-1] now free */
1636  }
1637  /* --- Construct new element ---------------------------------------- */
1638  dk = 0 ;
1639  nv [k] = -nvk ; /* flag k as in Lk */
1640  p = Cp [k] ;
1641  pk1 = (elenk == 0) ? p : cnz ; /* do in place if elen[k] == 0 */
1642  pk2 = pk1 ;
1643  for (k1 = 1 ; k1 <= elenk + 1 ; k1++)
1644  {
1645  if (k1 > elenk)
1646  {
1647  e = k ; /* search the nodes in k */
1648  pj = p ; /* list of nodes starts at Ci[pj]*/
1649  ln = len [k] - elenk ; /* length of list of nodes in k */
1650  }
1651  else
1652  {
1653  e = Ci [p++] ; /* search the nodes in e */
1654  pj = Cp [e] ;
1655  ln = len [e] ; /* length of list of nodes in e */
1656  }
1657  for (k2 = 1 ; k2 <= ln ; k2++)
1658  {
1659  i = Ci [pj++] ;
1660  if ((nvi = nv [i]) <= 0) continue ; /* node i dead, or seen */
1661  dk += nvi ; /* degree[Lk] += size of node i */
1662  nv [i] = -nvi ; /* negate nv[i] to denote i in Lk*/
1663  Ci [pk2++] = i ; /* place i in Lk */
1664  if (next [i] != -1) last [next [i]] = last [i] ;
1665  if (last [i] != -1) /* remove i from degree list */
1666  {
1667  next [last [i]] = next [i] ;
1668  }
1669  else
1670  {
1671  head [degree [i]] = next [i] ;
1672  }
1673  }
1674  if (e != k)
1675  {
1676  Cp [e] = CS_FLIP (k) ; /* absorb e into k */
1677  w [e] = 0 ; /* e is now a dead element */
1678  }
1679  }
1680  if (elenk != 0) cnz = pk2 ; /* Ci [cnz...nzmax] is free */
1681  degree [k] = dk ; /* external degree of k - |Lk\i| */
1682  Cp [k] = pk1 ; /* element k is in Ci[pk1..pk2-1] */
1683  len [k] = pk2 - pk1 ;
1684  elen [k] = -2 ; /* k is now an element */
1685  /* --- Find set differences ----------------------------------------- */
1686  mark = cs_wclear (mark, lemax, w, n) ; /* clear w if necessary */
1687  for (pk = pk1 ; pk < pk2 ; pk++) /* scan 1: find |Le\Lk| */
1688  {
1689  i = Ci [pk] ;
1690  if ((eln = elen [i]) <= 0) continue ;/* skip if elen[i] empty */
1691  nvi = -nv [i] ; /* nv [i] was negated */
1692  wnvi = mark - nvi ;
1693  for (p = Cp [i] ; p <= Cp [i] + eln - 1 ; p++) /* scan Ei */
1694  {
1695  e = Ci [p] ;
1696  if (w [e] >= mark)
1697  {
1698  w [e] -= nvi ; /* decrement |Le\Lk| */
1699  }
1700  else if (w [e] != 0) /* ensure e is a live element */
1701  {
1702  w [e] = degree [e] + wnvi ; /* 1st time e seen in scan 1 */
1703  }
1704  }
1705  }
1706  /* --- Degree update ------------------------------------------------ */
1707  for (pk = pk1 ; pk < pk2 ; pk++) /* scan2: degree update */
1708  {
1709  i = Ci [pk] ; /* consider node i in Lk */
1710  p1 = Cp [i] ;
1711  p2 = p1 + elen [i] - 1 ;
1712  pn = p1 ;
1713  for (h = 0, d = 0, p = p1 ; p <= p2 ; p++) /* scan Ei */
1714  {
1715  e = Ci [p] ;
1716  if (w [e] != 0) /* e is an unabsorbed element */
1717  {
1718  dext = w [e] - mark ; /* dext = |Le\Lk| */
1719  if (dext > 0)
1720  {
1721  d += dext ; /* sum up the set differences */
1722  Ci [pn++] = e ; /* keep e in Ei */
1723  h += e ; /* compute the hash of node i */
1724  }
1725  else
1726  {
1727  Cp [e] = CS_FLIP (k) ; /* aggressive absorb. e->k */
1728  w [e] = 0 ; /* e is a dead element */
1729  }
1730  }
1731  }
1732  elen [i] = pn - p1 + 1 ; /* elen[i] = |Ei| */
1733  p3 = pn ;
1734  p4 = p1 + len [i] ;
1735  for (p = p2 + 1 ; p < p4 ; p++) /* prune edges in Ai */
1736  {
1737  j = Ci [p] ;
1738  if ((nvj = nv [j]) <= 0) continue ; /* node j dead or in Lk */
1739  d += nvj ; /* degree(i) += |j| */
1740  Ci [pn++] = j ; /* place j in node list of i */
1741  h += j ; /* compute hash for node i */
1742  }
1743  if (d == 0) /* check for mass elimination */
1744  {
1745  Cp [i] = CS_FLIP (k) ; /* absorb i into k */
1746  nvi = -nv [i] ;
1747  dk -= nvi ; /* |Lk| -= |i| */
1748  nvk += nvi ; /* |k| += nv[i] */
1749  nel += nvi ;
1750  nv [i] = 0 ;
1751  elen [i] = -1 ; /* node i is dead */
1752  }
1753  else
1754  {
1755  degree [i] = CS_MIN (degree [i], d) ; /* update degree(i) */
1756  Ci [pn] = Ci [p3] ; /* move first node to end */
1757  Ci [p3] = Ci [p1] ; /* move 1st el. to end of Ei */
1758  Ci [p1] = k ; /* add k as 1st element in of Ei */
1759  len [i] = pn - p1 + 1 ; /* new len of adj. list of node i */
1760  h %= n ; /* finalize hash of i */
1761  next [i] = hhead [h] ; /* place i in hash bucket */
1762  hhead [h] = i ;
1763  last [i] = h ; /* save hash of i in last[i] */
1764  }
1765  } /* scan2 is done */
1766  degree [k] = dk ; /* finalize |Lk| */
1767  lemax = CS_MAX (lemax, dk) ;
1768  mark = cs_wclear (mark+lemax, lemax, w, n) ; /* clear w */
1769  /* --- Supernode detection ------------------------------------------ */
1770  for (pk = pk1 ; pk < pk2 ; pk++)
1771  {
1772  i = Ci [pk] ;
1773  if (nv [i] >= 0) continue ; /* skip if i is dead */
1774  h = last [i] ; /* scan hash bucket of node i */
1775  i = hhead [h] ;
1776  hhead [h] = -1 ; /* hash bucket will be empty */
1777  for ( ; i != -1 && next [i] != -1 ; i = next [i], mark++)
1778  {
1779  ln = len [i] ;
1780  eln = elen [i] ;
1781  for (p = Cp [i]+1 ; p <= Cp [i] + ln-1 ; p++) w [Ci [p]] = mark;
1782  jlast = i ;
1783  for (j = next [i] ; j != -1 ; ) /* compare i with all j */
1784  {
1785  ok = (len [j] == ln) && (elen [j] == eln) ;
1786  for (p = Cp [j] + 1 ; ok && p <= Cp [j] + ln - 1 ; p++)
1787  {
1788  if (w [Ci [p]] != mark) ok = 0 ; /* compare i and j*/
1789  }
1790  if (ok) /* i and j are identical */
1791  {
1792  Cp [j] = CS_FLIP (i) ; /* absorb j into i */
1793  nv [i] += nv [j] ;
1794  nv [j] = 0 ;
1795  elen [j] = -1 ; /* node j is dead */
1796  j = next [j] ; /* delete j from hash bucket */
1797  next [jlast] = j ;
1798  }
1799  else
1800  {
1801  jlast = j ; /* j and i are different */
1802  j = next [j] ;
1803  }
1804  }
1805  }
1806  }
1807  /* --- Finalize new element------------------------------------------ */
1808  for (p = pk1, pk = pk1 ; pk < pk2 ; pk++) /* finalize Lk */
1809  {
1810  i = Ci [pk] ;
1811  if ((nvi = -nv [i]) <= 0) continue ;/* skip if i is dead */
1812  nv [i] = nvi ; /* restore nv[i] */
1813  d = degree [i] + dk - nvi ; /* compute external degree(i) */
1814  d = CS_MIN (d, n - nel - nvi) ;
1815  if (head [d] != -1) last [head [d]] = i ;
1816  next [i] = head [d] ; /* put i back in degree list */
1817  last [i] = -1 ;
1818  head [d] = i ;
1819  mindeg = CS_MIN (mindeg, d) ; /* find new minimum degree */
1820  degree [i] = d ;
1821  Ci [p++] = i ; /* place i in Lk */
1822  }
1823  nv [k] = nvk ; /* # nodes absorbed into k */
1824  if ((len [k] = p-pk1) == 0) /* length of adj list of element k*/
1825  {
1826  Cp [k] = -1 ; /* k is a root of the tree */
1827  w [k] = 0 ; /* k is now a dead element */
1828  }
1829  if (elenk != 0) cnz = p ; /* free unused space in Lk */
1830  }
1831  /* --- Postordering ----------------------------------------------------- */
1832  for (i = 0 ; i < n ; i++) Cp [i] = CS_FLIP (Cp [i]) ;/* fix assembly tree */
1833  for (j = 0 ; j <= n ; j++) head [j] = -1 ;
1834  for (j = n ; j >= 0 ; j--) /* place unordered nodes in lists */
1835  {
1836  if (nv [j] > 0) continue ; /* skip if j is an element */
1837  next [j] = head [Cp [j]] ; /* place j in list of its parent */
1838  head [Cp [j]] = j ;
1839  }
1840  for (e = n ; e >= 0 ; e--) /* place elements in lists */
1841  {
1842  if (nv [e] <= 0) continue ; /* skip unless e is an element */
1843  if (Cp [e] != -1)
1844  {
1845  next [e] = head [Cp [e]] ; /* place e in list of its parent */
1846  head [Cp [e]] = e ;
1847  }
1848  }
1849  for (k = 0, i = 0 ; i <= n ; i++) /* postorder the assembly tree */
1850  {
1851  if (Cp [i] == -1) k = cs_tdfs (i, k, head, next, P, w) ;
1852  }
1853  return (P) ;
1854 }
1855 
1859 ivector cs_amd (XCONST dvar_hs_smatrix &A) /* Implements only order == 1: Chol*/
1860 {
1861  int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1,
1862  k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi,
1863  ok, cnz, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, t ;
1864  unsigned int h ;
1865  /* --- Construct matrix C ----------------------------------------------- */
1866 
1867  int n = A.n ;
1868 
1869  dvar_hs_smatrix AT(n,A.nzmax);
1870  cs_transpose(A,0,AT);
1871  /* find dense threshold */
1872  dense = CS_MAX (16, (int)(10.0 * sqrt((double)n)));
1873  dense = CS_MIN (n-2, dense) ;
1874 
1875  dvar_hs_smatrix C = cs_add(A,AT);
1876  cs_fkeep (C, &cs_diag, NULL); // drop diagonal entries
1877  cnz = C.p [n] ;
1878  ivector P(0,n);
1879 
1880  t = cnz + cnz/5 + 2*n ; // add elbow room to C
1881  C.reallocate(t);
1882  ivector & Cp=C.p;
1883 
1884  ivector len(0,n);
1885  len.initialize();
1886  ivector nv(0,n);
1887  ivector next(0,n);
1888  ivector head(0,n);
1889  head.initialize();
1890  ivector elen(0,n);
1891  ivector degree(0,n);
1892  ivector w(0,n);
1893  ivector hhead(0,n);
1894  ivector &last = P ; /* use P as workspace for last */
1895 
1896  /* --- Initialize quotient graph ---------------------------------------- */
1897  for (k = 0 ; k < n ; k++) len [k] = Cp [k+1] - Cp [k] ;
1898  len [n] = 0 ;
1899  nzmax = C.nzmax ;
1900  ivector & Ci=C.i;
1901  for (i = 0 ; i <= n ; i++)
1902  {
1903  head [i] = -1 ; /* degree list i is empty */
1904  last [i] = -1 ;
1905  next [i] = -1 ;
1906  hhead [i] = -1 ; /* hash list i is empty */
1907  nv [i] = 1 ; /* node i is just one node */
1908  w [i] = 1 ; /* node i is alive */
1909  elen [i] = 0 ; /* Ek of node i is empty */
1910  degree [i] = len [i] ; /* degree of node i */
1911  }
1912  mark = cs_wclear (0, 0, w, n) ; /* clear w */
1913  elen [n] = -2 ; /* n is a dead element */
1914  Cp [n] = -1 ; /* n is a root of assembly tree */
1915  w [n] = 0 ; /* n is a dead element */
1916  /* --- Initialize degree lists ------------------------------------------ */
1917  for (i = 0 ; i < n ; i++)
1918  {
1919  d = degree [i] ;
1920  if (d == 0) /* node i is empty */
1921  {
1922  elen [i] = -2 ; /* element i is dead */
1923  nel++ ;
1924  Cp [i] = -1 ; /* i is a root of assembly tree */
1925  w [i] = 0 ;
1926  }
1927  else if (d > dense) /* node i is dense */
1928  {
1929  nv [i] = 0 ; /* absorb i into element n */
1930  elen [i] = -1 ; /* node i is dead */
1931  nel++ ;
1932  Cp [i] = CS_FLIP (n) ;
1933  nv [n]++ ;
1934  }
1935  else
1936  {
1937  if (head [d] != -1) last [head [d]] = i ;
1938  next [i] = head [d] ; /* put node i in degree list d */
1939  head [d] = i ;
1940  }
1941  }
1942  while (nel < n) /* while (selecting pivots) do */
1943  {
1944  /* --- Select node of minimum approximate degree -------------------- */
1945  for (k = -1 ; mindeg < n && (k = head [mindeg]) == -1 ; mindeg++) ;
1946  if (next [k] != -1) last [next [k]] = -1 ;
1947  head [mindeg] = next [k] ; /* remove k from degree list */
1948  elenk = elen [k] ; /* elenk = |Ek| */
1949  nvk = nv [k] ; /* # of nodes k represents */
1950  nel += nvk ; /* nv[k] nodes of A eliminated */
1951  /* --- Garbage collection ------------------------------------------- */
1952  if (elenk > 0 && cnz + mindeg >= nzmax)
1953  {
1954  for (j = 0 ; j < n ; j++)
1955  {
1956  if ((p = Cp [j]) >= 0) /* j is a live node or element */
1957  {
1958  Cp [j] = Ci [p] ; /* save first entry of object */
1959  Ci [p] = CS_FLIP (j) ; /* first entry is now CS_FLIP(j) */
1960  }
1961  }
1962  for (q = 0, p = 0 ; p < cnz ; ) /* scan all of memory */
1963  {
1964  if ((j = CS_FLIP (Ci [p++])) >= 0) /* found object j */
1965  {
1966  Ci [q] = Cp [j] ; /* restore first entry of object */
1967  Cp [j] = q++ ; /* new pointer to object j */
1968  for (k3 = 0 ; k3 < len [j]-1 ; k3++) Ci [q++] = Ci [p++] ;
1969  }
1970  }
1971  cnz = q ; /* Ci [cnz...nzmax-1] now free */
1972  }
1973  /* --- Construct new element ---------------------------------------- */
1974  dk = 0 ;
1975  nv [k] = -nvk ; /* flag k as in Lk */
1976  p = Cp [k] ;
1977  pk1 = (elenk == 0) ? p : cnz ; /* do in place if elen[k] == 0 */
1978  pk2 = pk1 ;
1979  for (k1 = 1 ; k1 <= elenk + 1 ; k1++)
1980  {
1981  if (k1 > elenk)
1982  {
1983  e = k ; /* search the nodes in k */
1984  pj = p ; /* list of nodes starts at Ci[pj]*/
1985  ln = len [k] - elenk ; /* length of list of nodes in k */
1986  }
1987  else
1988  {
1989  e = Ci [p++] ; /* search the nodes in e */
1990  pj = Cp [e] ;
1991  ln = len [e] ; /* length of list of nodes in e */
1992  }
1993  for (k2 = 1 ; k2 <= ln ; k2++)
1994  {
1995  i = Ci [pj++] ;
1996  if ((nvi = nv [i]) <= 0) continue ; /* node i dead, or seen */
1997  dk += nvi ; /* degree[Lk] += size of node i */
1998  nv [i] = -nvi ; /* negate nv[i] to denote i in Lk*/
1999  Ci [pk2++] = i ; /* place i in Lk */
2000  if (next [i] != -1) last [next [i]] = last [i] ;
2001  if (last [i] != -1) /* remove i from degree list */
2002  {
2003  next [last [i]] = next [i] ;
2004  }
2005  else
2006  {
2007  head [degree [i]] = next [i] ;
2008  }
2009  }
2010  if (e != k)
2011  {
2012  Cp [e] = CS_FLIP (k) ; /* absorb e into k */
2013  w [e] = 0 ; /* e is now a dead element */
2014  }
2015  }
2016  if (elenk != 0) cnz = pk2 ; /* Ci [cnz...nzmax] is free */
2017  degree [k] = dk ; /* external degree of k - |Lk\i| */
2018  Cp [k] = pk1 ; /* element k is in Ci[pk1..pk2-1] */
2019  len [k] = pk2 - pk1 ;
2020  elen [k] = -2 ; /* k is now an element */
2021  /* --- Find set differences ----------------------------------------- */
2022  mark = cs_wclear (mark, lemax, w, n) ; /* clear w if necessary */
2023  for (pk = pk1 ; pk < pk2 ; pk++) /* scan 1: find |Le\Lk| */
2024  {
2025  i = Ci [pk] ;
2026  if ((eln = elen [i]) <= 0) continue ;/* skip if elen[i] empty */
2027  nvi = -nv [i] ; /* nv [i] was negated */
2028  wnvi = mark - nvi ;
2029  for (p = Cp [i] ; p <= Cp [i] + eln - 1 ; p++) /* scan Ei */
2030  {
2031  e = Ci [p] ;
2032  if (w [e] >= mark)
2033  {
2034  w [e] -= nvi ; /* decrement |Le\Lk| */
2035  }
2036  else if (w [e] != 0) /* ensure e is a live element */
2037  {
2038  w [e] = degree [e] + wnvi ; /* 1st time e seen in scan 1 */
2039  }
2040  }
2041  }
2042  /* --- Degree update ------------------------------------------------ */
2043  for (pk = pk1 ; pk < pk2 ; pk++) /* scan2: degree update */
2044  {
2045  i = Ci [pk] ; /* consider node i in Lk */
2046  p1 = Cp [i] ;
2047  p2 = p1 + elen [i] - 1 ;
2048  pn = p1 ;
2049  for (h = 0, d = 0, p = p1 ; p <= p2 ; p++) /* scan Ei */
2050  {
2051  e = Ci [p] ;
2052  if (w [e] != 0) /* e is an unabsorbed element */
2053  {
2054  dext = w [e] - mark ; /* dext = |Le\Lk| */
2055  if (dext > 0)
2056  {
2057  d += dext ; /* sum up the set differences */
2058  Ci [pn++] = e ; /* keep e in Ei */
2059  h += e ; /* compute the hash of node i */
2060  }
2061  else
2062  {
2063  Cp [e] = CS_FLIP (k) ; /* aggressive absorb. e->k */
2064  w [e] = 0 ; /* e is a dead element */
2065  }
2066  }
2067  }
2068  elen [i] = pn - p1 + 1 ; /* elen[i] = |Ei| */
2069  p3 = pn ;
2070  p4 = p1 + len [i] ;
2071  for (p = p2 + 1 ; p < p4 ; p++) /* prune edges in Ai */
2072  {
2073  j = Ci [p] ;
2074  if ((nvj = nv [j]) <= 0) continue ; /* node j dead or in Lk */
2075  d += nvj ; /* degree(i) += |j| */
2076  Ci [pn++] = j ; /* place j in node list of i */
2077  h += j ; /* compute hash for node i */
2078  }
2079  if (d == 0) /* check for mass elimination */
2080  {
2081  Cp [i] = CS_FLIP (k) ; /* absorb i into k */
2082  nvi = -nv [i] ;
2083  dk -= nvi ; /* |Lk| -= |i| */
2084  nvk += nvi ; /* |k| += nv[i] */
2085  nel += nvi ;
2086  nv [i] = 0 ;
2087  elen [i] = -1 ; /* node i is dead */
2088  }
2089  else
2090  {
2091  degree [i] = CS_MIN (degree [i], d) ; /* update degree(i) */
2092  Ci [pn] = Ci [p3] ; /* move first node to end */
2093  Ci [p3] = Ci [p1] ; /* move 1st el. to end of Ei */
2094  Ci [p1] = k ; /* add k as 1st element in of Ei */
2095  len [i] = pn - p1 + 1 ; /* new len of adj. list of node i */
2096  h %= n ; /* finalize hash of i */
2097  next [i] = hhead [h] ; /* place i in hash bucket */
2098  hhead [h] = i ;
2099  last [i] = h ; /* save hash of i in last[i] */
2100  }
2101  } /* scan2 is done */
2102  degree [k] = dk ; /* finalize |Lk| */
2103  lemax = CS_MAX (lemax, dk) ;
2104  mark = cs_wclear (mark+lemax, lemax, w, n) ; /* clear w */
2105  /* --- Supernode detection ------------------------------------------ */
2106  for (pk = pk1 ; pk < pk2 ; pk++)
2107  {
2108  i = Ci [pk] ;
2109  if (nv [i] >= 0) continue ; /* skip if i is dead */
2110  h = last [i] ; /* scan hash bucket of node i */
2111  i = hhead [h] ;
2112  hhead [h] = -1 ; /* hash bucket will be empty */
2113  for ( ; i != -1 && next [i] != -1 ; i = next [i], mark++)
2114  {
2115  ln = len [i] ;
2116  eln = elen [i] ;
2117  for (p = Cp [i]+1 ; p <= Cp [i] + ln-1 ; p++) w [Ci [p]] = mark;
2118  jlast = i ;
2119  for (j = next [i] ; j != -1 ; ) /* compare i with all j */
2120  {
2121  ok = (len [j] == ln) && (elen [j] == eln) ;
2122  for (p = Cp [j] + 1 ; ok && p <= Cp [j] + ln - 1 ; p++)
2123  {
2124  if (w [Ci [p]] != mark) ok = 0 ; /* compare i and j*/
2125  }
2126  if (ok) /* i and j are identical */
2127  {
2128  Cp [j] = CS_FLIP (i) ; /* absorb j into i */
2129  nv [i] += nv [j] ;
2130  nv [j] = 0 ;
2131  elen [j] = -1 ; /* node j is dead */
2132  j = next [j] ; /* delete j from hash bucket */
2133  next [jlast] = j ;
2134  }
2135  else
2136  {
2137  jlast = j ; /* j and i are different */
2138  j = next [j] ;
2139  }
2140  }
2141  }
2142  }
2143  /* --- Finalize new element------------------------------------------ */
2144  for (p = pk1, pk = pk1 ; pk < pk2 ; pk++) /* finalize Lk */
2145  {
2146  i = Ci [pk] ;
2147  if ((nvi = -nv [i]) <= 0) continue ;/* skip if i is dead */
2148  nv [i] = nvi ; /* restore nv[i] */
2149  d = degree [i] + dk - nvi ; /* compute external degree(i) */
2150  d = CS_MIN (d, n - nel - nvi) ;
2151  if (head [d] != -1) last [head [d]] = i ;
2152  next [i] = head [d] ; /* put i back in degree list */
2153  last [i] = -1 ;
2154  head [d] = i ;
2155  mindeg = CS_MIN (mindeg, d) ; /* find new minimum degree */
2156  degree [i] = d ;
2157  Ci [p++] = i ; /* place i in Lk */
2158  }
2159  nv [k] = nvk ; /* # nodes absorbed into k */
2160  if ((len [k] = p-pk1) == 0) /* length of adj list of element k*/
2161  {
2162  Cp [k] = -1 ; /* k is a root of the tree */
2163  w [k] = 0 ; /* k is now a dead element */
2164  }
2165  if (elenk != 0) cnz = p ; /* free unused space in Lk */
2166  }
2167  /* --- Postordering ----------------------------------------------------- */
2168  for (i = 0 ; i < n ; i++) Cp [i] = CS_FLIP (Cp [i]) ;/* fix assembly tree */
2169  for (j = 0 ; j <= n ; j++) head [j] = -1 ;
2170  for (j = n ; j >= 0 ; j--) /* place unordered nodes in lists */
2171  {
2172  if (nv [j] > 0) continue ; /* skip if j is an element */
2173  next [j] = head [Cp [j]] ; /* place j in list of its parent */
2174  head [Cp [j]] = j ;
2175  }
2176  for (e = n ; e >= 0 ; e--) /* place elements in lists */
2177  {
2178  if (nv [e] <= 0) continue ; /* skip unless e is an element */
2179  if (Cp [e] != -1)
2180  {
2181  next [e] = head [Cp [e]] ; /* place e in list of its parent */
2182  head [Cp [e]] = e ;
2183  }
2184  }
2185  for (k = 0, i = 0 ; i <= n ; i++) /* postorder the assembly tree */
2186  {
2187  if (Cp [i] == -1) k = cs_tdfs (i, k, head, next, P, w) ;
2188  }
2189  return (P) ;
2190 }
2191 
2192 /* compute the etree of A (using triu(A), or A'A without forming A'A */
2193 ivector cs_etree (XCONST hs_smatrix &_A)
2194 {
2195  ADUNCONST(hs_smatrix,A)
2196  int i, k, p, inext;
2197 
2198  int n = A.n ;
2199  ivector & Ap=A.p;
2200  ivector & Ai=A.i;
2201 
2202  ivector parent(0,n-1);
2203  parent.initialize();
2204  ivector w(0,n-1); /* get workspace */
2205  w.initialize();
2206  ivector &ancestor = w ;
2207  for (k = 0 ; k < n ; k++)
2208  {
2209  parent [k] = -1 ; /* node k has no parent yet */
2210  ancestor [k] = -1 ; /* nor does k have an ancestor */
2211  for (p = Ap [k] ; p < Ap [k+1] ; p++)
2212  {
2213  i = Ai [p] ;
2214  for ( ; i != -1 && i < k ; i = inext) /* traverse from i to k */
2215  {
2216  inext = ancestor [i] ; /* inext = ancestor of i */
2217  ancestor [i] = k ; /* path compression */
2218  if (inext == -1) parent [i] = k ; /* no anc., parent is k */
2219  }
2220  }
2221  }
2222  return (parent) ;
2223 }
2224 
2225 ivector cs_etree (XCONST dvar_hs_smatrix &_A)
2226 {
2227  ADUNCONST(dvar_hs_smatrix,A)
2228  int i, k, p, inext;
2229 
2230  int n = A.n ;
2231  ivector & Ap=A.p;
2232  ivector & Ai=A.i;
2233 
2234  ivector parent(0,n-1);
2235  parent.initialize();
2236  ivector w(0,n-1); /* get workspace */
2237  w.initialize();
2238  ivector &ancestor = w ;
2239  for (k = 0 ; k < n ; k++)
2240  {
2241  parent [k] = -1 ; /* node k has no parent yet */
2242  ancestor [k] = -1 ; /* nor does k have an ancestor */
2243  for (p = Ap [k] ; p < Ap [k+1] ; p++)
2244  {
2245  i = Ai [p] ;
2246  for ( ; i != -1 && i < k ; i = inext) /* traverse from i to k */
2247  {
2248  inext = ancestor [i] ; /* inext = ancestor of i */
2249  ancestor [i] = k ; /* path compression */
2250  if (inext == -1) parent [i] = k ; /* no anc., parent is k */
2251  }
2252  }
2253  }
2254  return (parent) ;
2255 }
2256 
2257 /* post order a forest */
2258 ivector cs_post (XCONST ivector &parent, int n)
2259 {
2260  int j, k = 0;
2261 
2262  ivector post(0,n-1);
2263  post.initialize();
2264  ivector head(0,n-1);
2265  ivector next(0,n-1);
2266  next.initialize();
2267  ivector stack(0,n-1);
2268  stack.initialize();
2269 
2270  for (j = 0 ; j < n ; j++) head [j] = -1 ; /* empty linked lists */
2271  for (j = n-1 ; j >= 0 ; j--) /* traverse nodes in reverse order*/
2272  {
2273  if (parent [j] == -1) continue ; /* j is a root */
2274  next [j] = head [parent [j]] ; /* add j to list of its parent */
2275  head [parent [j]] = j ;
2276  }
2277  for (j = 0 ; j < n ; j++)
2278  {
2279  if (parent [j] != -1) continue ; /* skip j if it is not a root */
2280  k = cs_tdfs (j, k, head, next, post, stack) ;
2281  }
2282  return (post) ;
2283 }
2284 
2285 
2286 /* consider A(i,j), node j in ith row subtree and return lca(jprev,j) */
2287 int cs_leaf (int i, int j, XCONST ivector &first, ivector &maxfirst,
2288  ivector &prevleaf, ivector &ancestor, int *jleaf)
2289 {
2290  int q, s, sparent, jprev ;
2291  *jleaf = 0 ;
2292  if (i <= j || first [j] <= maxfirst [i]) return (-1) ; /* j not a leaf */
2293  maxfirst [i] = first [j] ; /* update max first[j] seen so far */
2294  jprev = prevleaf [i] ; /* jprev = previous leaf of ith subtree */
2295  prevleaf [i] = j ;
2296  *jleaf = (jprev == -1) ? 1: 2 ; /* j is first or subsequent leaf */
2297  if (*jleaf == 1) return (i) ; /* if 1st leaf, q = root of ith subtree */
2298  for (q = jprev ; q != ancestor [q] ; q = ancestor [q]) ;
2299  for (s = jprev ; s != q ; s = sparent)
2300  {
2301  sparent = ancestor [s] ; /* path compression */
2302  ancestor [s] = q ;
2303  }
2304  return (q) ; /* q = least common ancester (jprev,j) */
2305 }
2306 
2307 /* column counts of LL'=A or LL'=A'A, given parent & post ordering */
2308 ivector cs_counts (XCONST hs_smatrix &A, XCONST ivector &parent,
2309  XCONST ivector &post)
2310 {
2311  int i, j, k, J, p, q, jleaf;
2312 
2313  int n = A.n ;
2314  ivector delta(0,n-1);
2315  delta.initialize();
2316  ivector& colcount = delta;
2317 
2318  hs_smatrix AT(n,A.nzmax);
2319  cs_transpose (A,0,AT) ; /* AT = A' */
2320 
2321  ivector ancestor(0,n-1);
2322  ancestor = -1;
2323  ivector maxfirst(0,n-1);
2324  maxfirst = -1;
2325  ivector prevleaf(0,n-1);
2326  prevleaf = -1;
2327  ivector first(0,n-1);
2328  first = -1;
2329 
2330  for (k = 0 ; k < n ; k++) /* find first [j] */
2331  {
2332  j = post [k] ;
2333  delta [j] = (first [j] == -1) ? 1 : 0 ; /* delta[j]=1 if j is a leaf */
2334  for ( ; j != -1 && first [j] == -1 ; j = parent [j]) first [j] = k ;
2335  }
2336 
2337  ivector & ATp=AT.p;
2338  ivector & ATi=AT.i;
2339 
2340  for (i = 0 ; i < n ; i++) ancestor [i] = i ; /* each node in its own set */
2341  for (k = 0 ; k < n ; k++)
2342  {
2343  j = post [k] ; /* j is the kth node in postordered etree */
2344  if (parent [j] != -1) delta [parent [j]]-- ; /* j is not a root */
2345  for (J = j ; J != -1 ; J = -1) /* J=j for LL'=A case */
2346  {
2347  for (p = ATp [J] ; p < ATp [J+1] ; p++)
2348  {
2349  i = ATi [p] ;
2350  q = cs_leaf (i, j, first, maxfirst, prevleaf, ancestor, &jleaf);
2351  if (jleaf >= 1) delta [j]++ ; /* A(i,j) is in skeleton */
2352  if (jleaf == 2) delta [q]-- ; /* account for overlap in q */
2353  }
2354  }
2355  if (parent [j] != -1) ancestor [j] = parent [j] ;
2356  }
2357  for (j = 0 ; j < n ; j++) /* sum up delta's of each child */
2358  {
2359  if (parent [j] != -1) colcount [parent [j]] += colcount [j] ;
2360  }
2361  return (colcount) ;
2362 }
2363 
2364 ivector cs_counts (XCONST dvar_hs_smatrix &A, XCONST ivector &parent,
2365  XCONST ivector &post)
2366 {
2367  int i, j, k, J, p, q, jleaf;
2368 
2369  int n = A.n ;
2370  ivector delta(0,n-1);
2371  delta.initialize();
2372  ivector& colcount = delta;
2373 
2374  dvar_hs_smatrix AT(n,A.nzmax);
2375  cs_transpose (A,0,AT) ; /* AT = A' */
2376 
2377  ivector ancestor(0,n-1);
2378  ancestor = -1;
2379  ivector maxfirst(0,n-1);
2380  maxfirst = -1;
2381  ivector prevleaf(0,n-1);
2382  prevleaf = -1;
2383  ivector first(0,n-1);
2384  first = -1;
2385 
2386  for (k = 0 ; k < n ; k++) /* find first [j] */
2387  {
2388  j = post [k] ;
2389  delta [j] = (first [j] == -1) ? 1 : 0 ; /* delta[j]=1 if j is a leaf */
2390  for ( ; j != -1 && first [j] == -1 ; j = parent [j]) first [j] = k ;
2391  }
2392 
2393  ivector & ATp=AT.p;
2394  ivector & ATi=AT.i;
2395 
2396  for (i = 0 ; i < n ; i++) ancestor [i] = i ; /* each node in its own set */
2397  for (k = 0 ; k < n ; k++)
2398  {
2399  j = post [k] ; /* j is the kth node in postordered etree */
2400  if (parent [j] != -1) delta [parent [j]]-- ; /* j is not a root */
2401  for (J = j ; J != -1 ; J = -1) /* J=j for LL'=A case */
2402  {
2403  for (p = ATp [J] ; p < ATp [J+1] ; p++)
2404  {
2405  i = ATi [p] ;
2406  q = cs_leaf (i, j, first, maxfirst, prevleaf, ancestor, &jleaf);
2407  if (jleaf >= 1) delta [j]++ ; /* A(i,j) is in skeleton */
2408  if (jleaf == 2) delta [q]-- ; /* account for overlap in q */
2409  }
2410  }
2411  if (parent [j] != -1) ancestor [j] = parent [j] ;
2412  }
2413  for (j = 0 ; j < n ; j++) /* sum up delta's of each child */
2414  {
2415  if (parent [j] != -1) colcount [parent [j]] += colcount [j] ;
2416  }
2417  return (colcount) ;
2418 }
2419 
2420 /* pinv = p', or p = pinv' */
2422 {
2423  int k ;
2424  ivector pinv(0,n-1);
2425  pinv.initialize();
2426  for (k = 0 ; k < n ; k++) pinv [p [k]] = k ;/* invert the permutation */
2427  return (pinv) ; /* return result */
2428 }
2429 
2430 /* Constructor that does symbolic Cholesky */
2431  //hs_symbolic::hs_symbolic(int _n, XCONST dmatrix &T, int order)
2432  //{
2433  //
2434  // if (order != 0 && order != 1 )
2435  // {
2436  // cout << "!!! hs_symbolic: only order = 0,1 allowed" << endl;
2437  // exit(0);
2438  // }
2439  //
2440  // hs_smatrix A(_n,T);
2441  // n = _n;
2442  //
2443  // // Allocate symbolic structure
2444  // pinv.allocate(0,n-1);
2445  // parent.allocate(0,n-1);
2446  // cp.allocate(0,n);
2447  // cp = 0;
2448  //
2449  // hs_smatrix C(A);
2450  // C = A;
2451  //
2452  // if(order==0)
2453  // {
2454  // pinv(0) = -1;
2455  // }
2456  // else
2457  // {
2458  // ivector P = cs_amd (A) ; /* P = amd(A+A'), or natural */
2459  // pinv = cs_pinv (P, n) ; /* find inverse permutation */
2460  // hs_symperm(A,pinv,C);
2461  // }
2462  //
2463  // parent = cs_etree (C) ; /* find etree of C */
2464  // ivector post = cs_post (parent, n) ; /* postorder the etree */
2465  // /* find column counts of chol(C) */
2466  // ivector c = cs_counts (C, parent, post) ;
2467  // lnz = cs_cumsum (cp, c, n) ; /* find column pointers for L */
2468  //
2469  //}
2470  //
2472 {
2473  n = 0;
2474 
2475  // Allocate symbolic structure
2476  pinv.allocate();
2477  parent.allocate();
2478  cp.allocate();
2479 }
2480 
2482 {
2484  int _n=T.get_n();
2485 
2486  if (order != 0 && order != 1 )
2487  {
2488  cout << "!!! hs_symbolic: only order = 0,1 allowed" << endl;
2489  exit(0);
2490  }
2491 
2492  hs_smatrix A(_n,T);
2493  n = _n;
2494 
2495  // Allocate symbolic structure
2496  pinv.allocate(0,n-1);
2497  parent.allocate(0,n-1);
2498  cp.allocate(0,n);
2499  cp = 0;
2500 
2501  hs_smatrix C(A);
2502  C = A;
2503 
2504  if(order==0)
2505  {
2506  pinv(0) = -1;
2507  }
2508  else
2509  {
2510  ivector P = cs_amd (A) ; /* P = amd(A+A'), or natural */
2511  pinv = cs_pinv (P, n) ; /* find inverse permutation */
2512  hs_symperm(A,pinv,C);
2513  }
2514 
2515  parent = cs_etree (C) ; /* find etree of C */
2516  ivector post = cs_post (parent, n) ; /* postorder the etree */
2517  ivector c = cs_counts (C, parent, post) ; /* find column counts of chol(C) */
2518  lnz = cs_cumsum (cp, c, n) ; /* find column pointers for L */
2519 }
2520 
2522 {
2524  int _n=T.get_n();
2525 
2526  if (order != 0 && order != 1 )
2527  {
2528  cout << "!!! hs_symbolic: only order = 0,1 allowed" << endl;
2529  exit(0);
2530  }
2531 
2532  dvar_hs_smatrix A(_n,T);
2533  n = _n;
2534 
2535  // Allocate symbolic structure
2536  pinv.allocate(0,n-1);
2537  parent.allocate(0,n-1);
2538  cp.allocate(0,n);
2539  cp = 0;
2540 
2541  dvar_hs_smatrix C(A);
2542  C = A;
2543 
2544  if(order==0)
2545  {
2546  pinv(0) = -1;
2547  }
2548  else
2549  {
2550  ivector P = cs_amd (A) ; /* P = amd(A+A'), or natural */
2551  pinv = cs_pinv (P, n) ; /* find inverse permutation */
2552  hs_symperm(A,pinv,C);
2553  }
2554 
2555  parent = cs_etree (C) ; /* find etree of C */
2556  ivector post = cs_post (parent, n) ; /* postorder the etree */
2557  ivector c = cs_counts (C, parent, post) ; /* find column counts of chol(C) */
2558  lnz = cs_cumsum (cp, c, n) ; /* find column pointers for L */
2559 }
2561  int _m)
2562 {
2563  allocate(mmin,mmax,_n,_m);
2564 }
2565 
2567 {
2568  x.initialize();
2569 }
2570 
2571 dcompressed_triplet::dcompressed_triplet(int mmin,int mmax,int _n,int _m)
2572 {
2573  allocate(mmin,mmax,_n,_m);
2574 }
2575 
2576 
2577 void dvar_compressed_triplet::allocate(int mmin,int mmax,int _n,int _m)
2578 {
2579  n=_n;
2580  m=_m;
2581  coords.allocate(1,2,mmin,mmax);
2582  x.allocate(mmin,mmax);
2583 }
2584 
2586 {
2587  n=-1;
2588  m=-1;
2589  coords.deallocate();
2590  x.deallocate();
2591 }
2592 
2593 void dcompressed_triplet::allocate(int mmin,int mmax,int _n,int _m)
2594 {
2595  n=_n;
2596  m=_m;
2597  coords.allocate(1,2,mmin,mmax);
2598  x.allocate(mmin,mmax);
2599 }
2600 
2602 {
2603  n=-1;
2604  m=-1;
2605  coords.deallocate();
2606  x.deallocate();
2607 }
2608 
2609 
2610 istream & operator >> (istream & is,dcompressed_triplet & M)
2611 {
2612  int mmin=M.indexmin();
2613  int mmax=M.indexmax();
2614  for (int i=mmin;i<=mmax;i++)
2615  {
2616  is >> M(i,1);
2617  is >> M(i,2);
2618  is >> M(i);
2619  }
2620  return is;
2621 }
2622 
2623 istream & operator >> (istream & is,dvar_compressed_triplet & M)
2624 {
2625  int mmin=M.indexmin();
2626  int mmax=M.indexmax();
2627  for (int i=mmin;i<=mmax;i++)
2628  {
2629  is >> M(i,1);
2630  is >> M(i,2);
2631  is >> M(i);
2632  }
2633  return is;
2634 }
2635 
2637 {
2638  //ADUNCONST(dmatrix,st)
2639  int n=st.get_n();
2640 
2641  hs_smatrix HS(n,st); // Convert triplet to working format
2642 
2643  hs_symbolic S(st,1); // Fill reducing row-col permutation
2644  hs_smatrix * PL = new hs_smatrix(S); // Allocates cholesky factor
2645 
2646  chol(HS,S,*PL); // Does numeric factorization
2647 
2648  PL->set_symbolic(S);
2649 
2650  return PL;
2651 }
2652 
2654 {
2655  //ADUNCONST(dmatrix,st)
2656  int n=st.get_n();
2657 
2658  dvar_hs_smatrix HS(n,st); // Convert triplet to working format
2659 
2660  hs_symbolic S(st,1); // Fill reducing row-col permutation
2661  dvar_hs_smatrix * PL = new dvar_hs_smatrix(S); // Allocates cholesky factor
2662 
2663  chol(HS,S,*PL); // Does numeric factorization
2664 
2665  PL->set_symbolic(S);
2666 
2667  return PL;
2668 }
2669 
2671 {
2672  //ADUNCONST(dmatrix,st)
2673  int n=st.get_n();
2674 
2675  hs_smatrix HS(n,st); // Convert triplet to working format
2676 
2677  hs_symbolic S(st,1); // Fill reducing row-col permutation
2678  hs_smatrix L(S); // Allocates cholesky factor
2679 
2680  chol(HS,S,L); // Does numeric factorization
2681 
2682  dvector x(0,n-1);
2683  eps.shift(0);
2684  x = cs_ipvec(S.pinv, eps);
2685  eps.shift(1);
2686  x = cs_lsolve(L,x);
2687  //x = cs_ltsolve(L,x);
2688  x = cs_pvec(S.pinv,x);
2689  x.shift(1);
2690  return x;
2691 }
2692 
2694 {
2695  //ADUNCONST(dmatrix,st)
2696  hs_smatrix& L= *PL;
2697  int n=L.m;
2698  hs_symbolic & S = L.sym;
2699  dvector x(0,n-1);
2700  eps.shift(0);
2701  x = cs_ipvec(S.pinv, eps);
2702  eps.shift(1);
2703  x = cs_lsolve(L,x);
2704  //x = cs_ltsolve(L,x);
2705  x = cs_pvec(S.pinv,x);
2706  x.shift(1);
2707  return x;
2708 }
2709 
2711 {
2712  //ADUNCONST(dmatrix,st)
2713  dvar_hs_smatrix& L= *PL;
2714  int n=L.m;
2715  hs_symbolic & S = L.sym;
2716  dvar_vector x(0,n-1);
2717  eps.shift(0);
2718  x = cs_ipvec(S.pinv, eps);
2719  eps.shift(1);
2720  x = cs_lsolve(L,x);
2721  //x = cs_ltsolve(L,x);
2722  x = cs_pvec(S.pinv,x);
2723  x.shift(1);
2724  return x;
2725 }
2726 
2727 
2729  dvector& grad)
2730 {
2731  //ADUNCONST(dmatrix,st)
2732  int nz=st.indexmax();
2733  int n=Hess.indexmax();
2734  // fill up compressed triplet with nonzero entries of the Hessian
2735  for (int i=1;i<=nz;i++)
2736  {
2737  st(i)=Hess(st(1,i),st(2,i));
2738  }
2739 
2740  hs_smatrix HS(n,st); // Convert triplet to working format
2741 
2742  hs_symbolic S(st,1); // Fill reducing row-col permutation
2743  hs_smatrix L(S); // Allocates cholesky factor
2744 
2745  chol(HS,S,L); // Does numeric factorization
2746 
2747  dvector x(0,n-1);
2748  grad.shift(0);
2749  x = cs_ipvec(S.pinv, grad);
2750  grad.shift(1);
2751  x = cs_lsolve(L,x);
2752  x = cs_ltsolve(L,x);
2753  x = cs_pvec(S.pinv,x);
2754  x.shift(1);
2755  return x;
2756 }
2757 
2759  dvector& grad,hs_symbolic& S)
2760 {
2761  //ADUNCONST(dmatrix,st)
2762  int nz=st.indexmax();
2763  int n=Hess.indexmax();
2764  // fill up compressed triplet with nonzero entries of the Hessian
2765  for (int i=1;i<=nz;i++)
2766  {
2767  st(i)=Hess(st(1,i),st(2,i));
2768  }
2769 
2770  hs_smatrix HS(n,st); // Convert triplet to working format
2771 
2772  //hs_symbolic S(st,1); // Fill reducing row-col permutation
2773  hs_smatrix L(S); // Allocates cholesky factor
2774  //hs_smatrix L1(S); // Allocates cholesky factor
2775 
2776  //chol(HS,S,L); // Does numeric factorization
2777  ivector nxcount;
2778  chol(HS,S,L); // Does numeric factorization
2779  //tmpxchol(HS,S,L,nxcount); // Does numeric factorization
2780 
2781  //cout << norm2(L.get_x()-L1.get_x()) << endl;
2782  dvector x(0,n-1);
2783  grad.shift(0);
2784  x = cs_ipvec(S.pinv, grad);
2785  grad.shift(1);
2786  x = cs_lsolve(L,x);
2787  x = cs_ltsolve(L,x);
2788  x = cs_pvec(S.pinv,x);
2789  x.shift(1);
2790  return x;
2791 }
2792 
2793 dvector solve(const dcompressed_triplet & _st,const dvector& _grad,
2794  const hs_symbolic& S)
2795  {
2797  ADUNCONST(dvector,grad)
2798  int n=st.get_n();
2799  //int n=Hess.indexmax();
2800  // fill up compressed triplet with nonzero entries of the Hessian
2801 
2802  hs_smatrix HS(n,st); // Convert triplet to working format
2803 
2804  hs_smatrix L(S); // Allocates cholesky factor
2805 
2806  ivector nxcount;
2807  chol(HS,S,L); // Does numeric factorization
2808 
2809  dvector x(0,n-1);
2810  grad.shift(0);
2811  x = cs_ipvec(S.pinv, grad);
2812  grad.shift(1);
2813  x = cs_lsolve(L,x);
2814  x = cs_ltsolve(L,x);
2815  x = cs_pvec(S.pinv,x);
2816  x.shift(1);
2817  return x;
2818  }
2819 
2820 dvector solve(const dcompressed_triplet & _st,const dvector& _grad,
2821  const hs_symbolic& S,int& ierr)
2822  {
2824  ADUNCONST(dvector,grad)
2825  int n=st.get_n();
2826  //int n=Hess.indexmax();
2827  // fill up compressed triplet with nonzero entries of the Hessian
2828 
2829  hs_smatrix HS(n,st); // Convert triplet to working format
2830 
2831  hs_smatrix L(S); // Allocates cholesky factor
2832 
2833  ivector nxcount;
2834  ierr=chol(HS,S,L); // 0 error 1 OK Does numeric factorization
2835 
2836  dvector x(0,n-1);
2837  if (ierr)
2838  {
2839  grad.shift(0);
2840  x = cs_ipvec(S.pinv, grad);
2841  grad.shift(1);
2842  x = cs_lsolve(L,x);
2843  x = cs_ltsolve(L,x);
2844  x = cs_pvec(S.pinv,x);
2845  x.shift(1);
2846  }
2847  else
2848  {
2849  x.initialize();
2850  x.shift(1);
2851  }
2852  return x;
2853 }
2854 
2856 {
2858  return allocated(st.get_coords());
2859 }
2861 {
2863  return allocated(st.get_coords());
2864 }
2866 {
2867  int n=VM.get_n();
2868  dvar_hs_smatrix H(n,VM);
2869  hs_symbolic S(VM,1); // Fill reducing row-col permutation
2870  dvar_hs_smatrix L(S); // Allocates cholesky factor
2871  int ierr=chol(H,S,L); // Does numeric factorization
2872  if (ierr==0)
2873  {
2874  cerr << "Error matrix not positrive definite in chol" << endl;
2875  ad_exit(1);
2876  }
2877  return 2.0*ln_det(L);
2878  //return L.x(0);
2879 }
2880 
2881 
2883 {
2884  int n=VM.get_n();
2885  dvar_hs_smatrix H(n,VM);
2886  //hs_symbolic S(VM,1); // Fill reducing row-col permutation
2887  dvar_hs_smatrix L(S); // Allocates cholesky factor
2888  int ierr=chol(H,S,L); // Does numeric factorization
2889  if (ierr==0)
2890  {
2891  cerr << "Error matrix not positive definite in chol" << endl;
2892  ad_exit(1);
2893  }
2894  return 2.0*ln_det(L);
2895  //return L.x(0);
2896 }
2897 
2898 
2899  int check_flag=0;
2900 
2903 {
2906  int n=VM.get_n();
2907  dvar_hs_smatrix H(n,VM);
2908  //hs_symbolic S(VM,1); // Fill reducing row-col permutation
2909  dvar_hs_smatrix L(S); // Allocates cholesky factor
2910  int ierr = 0;
2911  if (check_flag==0)
2912  {
2913  ierr=varchol(H,S,L,s);
2914  }
2915  else
2916  {
2917  ierr=chol(H,S,L);
2918  }
2919  if (ierr==0)
2920  {
2921  cerr << "Error matrix not positive definite in chol" << endl;
2922  ad_exit(1);
2923  }
2924  //set_gradstack_flag("AAC");
2925  dvariable tmp= 2.0*ln_det(L);
2927  return tmp;
2928  //return L.x(0);
2929 }
2930 
2931 
2932 double ln_det(const dcompressed_triplet& VVM,
2933  const hs_symbolic& T)
2934 {
2935  //ADUNCONST(dcompressed_triplet,VM)
2936  //ADUNCONST(hs_symbolic,S)
2938  hs_symbolic& S = (hs_symbolic&)T;
2939  int n=VM.get_n();
2940  hs_smatrix H(n,VM);
2941  //hs_symbolic S(VM,1); // Fill reducing row-col permutation
2942  hs_smatrix L(S); // Allocates cholesky factor
2943  int ierr=chol(H,S,L); // Does numeric factorization
2944  if (ierr==0)
2945  {
2946  cerr << "Error matrix not positrive definite in chol" << endl;
2947  ad_exit(1);
2948  }
2949  return 2.0*ln_det(L);
2950  //return L.x(0);
2951 }
2952 
2953 
2954 double ln_det(const dcompressed_triplet& VVM)
2955 {
2956  //ADUNCONST(dcompressed_triplet,VM)
2958  int n=VM.get_n();
2959  hs_smatrix H(n,VM);
2960  hs_symbolic S(VM,1); // Fill reducing row-col permutation
2961  hs_smatrix L(S); // Allocates cholesky factor
2962  int ierr=chol(H,S,L); // Does numeric factorization
2963  if (ierr==0)
2964  {
2965  cerr << "Error matrix not positrive definite in chol" << endl;
2966  ad_exit(1);
2967  }
2968  return 2.0*ln_det(L);
2969  //return L.x(0);
2970 }
2971 
2972 
2973 int cholnew(XCONST hs_smatrix &AA, XCONST hs_symbolic &T, hs_smatrix &LL)
2974 {
2975  //ADUNCONST(hs_symbolic,S)
2976  //ADUNCONST(hs_smatrix,L)
2977  //ADUNCONST(hs_smatrix,A)
2978  hs_symbolic& S = (hs_symbolic&)T;
2979  hs_smatrix& A = (hs_smatrix&)AA;
2980  hs_smatrix& L = (hs_smatrix&)LL;
2981  double d, lki;
2982  int top, i, p, k, n;
2983 
2984  n = A.n ;
2985 
2986  ivector c(0,n-1); /* int workspace */
2987  ivector s(0,n-1); /* int workspace */
2988  dvector x(0,n-1) ; /* double workspace */
2989  double xcount=0.0; /* double workspace */
2990 
2991  ivector & cp=S.cp;
2992  ivector & pinv=S.pinv;
2993  ivector & parent=S.parent;
2994 
2995  hs_smatrix C(A);
2996  C = A;
2997  if(S.pinv[0]!=-1)
2998  hs_symperm(A,pinv,C);
2999 
3000  ivector & Cp=C.p;
3001  ivector & Ci=C.i;
3002  dvector & Cx=C.x;
3003 
3004  ivector & Lp=L.p;
3005  ivector & Li=L.i;
3006  dvector & Lx=L.x;
3007 
3008  for (k = 0 ; k < n ; k++)
3009  Lp [k] = c [k] = cp [k] ;
3010 
3011  for (k = 0 ; k < n ; k++) /* compute L(:,k) for L*L' = C */
3012  {
3013  /* --- Nonzero pattern of L(k,:) ------------------------------------ */
3014  top = cs_ereach (C, k, parent, s, c) ; /* find pattern of L(k,:) */
3015  x [k] = 0 ; /* x (0:k) is now zero */
3016  for (p = Cp [k] ; p < Cp [k+1] ; p++) /* x = full(triu(C(:,k))) */
3017  {
3018  if (Ci [p] <= k) x [Ci [p]] = Cx [p] ;
3019  }
3020  d = x [k] ; /* d = C(k,k) */
3021  x [k] = 0 ; /* clear x for k+1st iteration */
3022  /* --- Triangular solve --------------------------------------------- */
3023  for ( ; top < n ; top++) /* solve L(0:k-1,0:k-1) * x = C(:,k) */
3024  {
3025  i = s [top] ; /* s [top..n-1] is pattern of L(k,:) */
3026  lki = x [i] / Lx [Lp [i]] ; /* L(k,i) = x (i) / L(i,i) */
3027  xcount++;
3028  x [i] = 0 ; /* clear x for k+1st iteration */
3029 
3030 
3031  int Lpi1=Lp[i]+1;
3032  int ci=c[i];
3033  if (Lpi1<ci)
3034  {
3035  myacc(p,Lpi1,ci,Li,x,Lx,lki);
3036  }
3037  /*
3038  for (p = Lp [i] + 1 ; p < c [i] ; p++)
3039  {
3040  x [Li [p]] -= Lx [p] * lki ;
3041  }
3042  */
3043 
3044  d -= lki * lki ; /* d = d - L(k,i)*L(k,i) */
3045  p = c [i]++ ;
3046  Li [p] = k ; /* store L(k,i) in column i */
3047  Lx [p] = lki ;
3048  }
3049  /* --- Compute L(k,k) ----------------------------------------------- */
3050  if (d <= 0) return (0) ; /* not pos def */
3051  p = c [k]++ ;
3052  Li [p] = k ; /* store L(k,k) = sqrt (d) in column k */
3053  Lx [p] = sqrt (d) ;
3054  }
3055  Lp [n] = cp [n] ; /* finalize L */
3056  return (1) ;
3057 }
3058 
3059 static void dfcholeski_sparse(void);
3060 
3061 int varchol(XCONST dvar_hs_smatrix &AA, XCONST hs_symbolic &T,
3062  dvar_hs_smatrix &LL, dcompressed_triplet & sparse_triplet2)
3063  //laplace_approximation_calculator * lapprox)
3064 {
3067  gs->RETURN_ARRAYS_INCREMENT(); //Need this statement because the function
3068  //ADUNCONST(hs_symbolic,S)
3069  //ADUNCONST(dvar_hs_smatrix,L)
3070  //ADUNCONST(dvar_hs_smatrix,A)
3071  hs_symbolic& S = (hs_symbolic&)T;
3072  dvar_hs_smatrix& A = (dvar_hs_smatrix&)AA;
3073  dvar_hs_smatrix& L = (dvar_hs_smatrix&)LL;
3074  int icount=0;
3075  double lki;
3076  double d;
3077  int top, i, p, k, n;
3078  n = A.n ;
3079  ivector c(0,n-1); /* int workspace */
3080  ivector s(0,n-1); /* int workspace */
3081  dvector x(0,n-1) ; /* double workspace */
3082 
3083  ivector & cp=S.cp;
3084  ivector & pinv=S.pinv;
3085  ivector & parent=S.parent;
3086 
3087  dvar_hs_smatrix C(A);
3088  C = A;
3089  if(S.pinv[0]!=-1)
3090  hs_symperm(A,pinv,C);
3091 
3092  ivector & Cp=C.p;
3093  ivector & Ci=C.i;
3094  dvector Cx=value(C.x);
3095 
3096  ivector & Lp=L.p;
3097  ivector & Li=L.i;
3098  dvector Lx=value(L.x);
3099  int txcount=0;
3100  int lkicount=0;
3101  int tccount=0;
3102 
3103  for (k = 0 ; k < n ; k++)
3104  {
3105  Lp [k] = c [k] = cp [k] ;
3106  }
3107 
3108  for (k = 0 ; k < n ; k++)
3109  {
3110  top = cs_ereach (C, k, parent, s, c) ;
3111  x [k] = 0 ;
3112  for (p = Cp [k] ; p < Cp [k+1] ; p++)
3113  {
3114  if (Ci[p] <= k) x [Ci[p]] = Cx[p] ;
3115  }
3116  d = x[k] ;
3117  x[k] = 0.0;
3118  for ( ; top < n ; top++)
3119  {
3120  i = s[top] ;
3121  lki = x[i] / Lx[Lp[i]] ;
3122  txcount++;
3123  icount++; // count the number of times lki is overwritten
3124  lkicount++; // count the number of times lki is overwritten
3125  x [i] = 0 ;
3126  for (p = Lp [i] + 1 ; p < c [i] ; p++)
3127  {
3128  x[Li[p]] -= Lx[p] * lki ;
3129  }
3130  d -= lki * lki ;
3131  p = c [i]++ ;
3132  tccount++;
3133  Li [p] = k ;
3134  Lx [p] = lki ;
3135  }
3136  if (d <= 0) return (0) ;
3137  p = c [k]++ ;
3138  tccount++;
3139  Li [p] = k ;
3140  Lx [p] = sqrt (d) ;
3141  }
3142  Lp [n] = cp [n] ;
3143  xxx(txcount);
3144  int mmin=Lx.indexmin();
3145  int mmax=Lx.indexmax();
3146  for (int ii=mmin;ii<=mmax;ii++)
3147  {
3148  value(L.x(ii))=Lx(ii);
3149  }
3150  int nxcount=txcount;
3151  int nccount=tccount;
3152  int nlkicount=lkicount;
3153  save_identifier_string("ty");
3154 
3155  fp->save_int_value(nxcount);
3156  fp->save_int_value(nlkicount);
3157  fp->save_int_value(nccount);
3158 
3159  save_identifier_string("tu");
3160  fp->save_dvar_vector_position(C.x);
3161  save_identifier_string("wy");
3162  fp->save_dvar_vector_position(L.x);
3163  save_identifier_string("iy");
3164  save_ad_pointer(&S);
3165  save_ad_pointer(&sparse_triplet2);
3166  save_identifier_string("dg");
3168  gs->RETURN_ARRAYS_DECREMENT(); //Need this statement because the function
3169  return (1) ;
3170 }
3171 
3172 static void dfcholeski_sparse(void)
3173 {
3175 
3177  dcompressed_triplet * sparse_triplet2 =
3179  hs_symbolic & S =
3186 
3187  int nccount=fp->restore_int_value();
3188  int nlkicount=fp->restore_int_value();
3189  int nxcount=fp->restore_int_value();
3190 
3192 
3194  hs_smatrix A(sparse_triplet2->get_n(),
3195  *(sparse_triplet2) );
3196 
3197  //hs_symbolic& S=*(lapprox->sparse_symbolic2);
3198  double d;
3199  double lki=0;
3200  double dfd=0.0;
3201  double dflki=0.0;
3202  int top, i, p, k, n;
3203  int p2;
3204  n = A.n ;
3205 
3206  ivector cold(0,n-1); /* int workspace */
3207  ivector c(0,n-1); /* int workspace */
3208  imatrix ssave(0,n-1); /* int workspace */
3209  ivector s(0,n-1); /* int workspace */
3210  dvector x(0,n-1) ; /* double workspace */
3211  dvector dfx(0,n-1) ; /* double workspace */
3212  dfx.initialize();
3213 
3214  ivector & cp=S.cp;
3215  ivector & pinv=S.pinv;
3216  ivector & parent=S.parent;
3217 
3218  hs_smatrix C(A);
3219  C = A;
3220  if(S.pinv[0]!=-1)
3221  hs_symperm(A,pinv,C);
3222 
3223  hs_smatrix L(S); // Allocates cholesky factor
3224 
3225  ivector & Cp=C.p;
3226  ivector & Ci=C.i;
3227  dvector & Cx=C.x;
3228  dvector dfCx(C.x.indexmin(),Cx.indexmax());
3229  dfCx.initialize();
3230 
3231  ivector & Lp=L.p;
3232  ivector & Li=L.i;
3233  dvector & Lx=L.x;
3234 
3235  // counters
3236  int tccount=0;
3237  int txcount=0;
3238  ivector ccount(c.indexmin(),c.indexmax());
3239  ccount.initialize();
3240  ivector Licount(Li.indexmin(),Li.indexmax());
3241  Licount.initialize();
3242  ivector Lxcount(Lx.indexmin(),Lx.indexmax());
3243  Lxcount.initialize();
3244  ivector xcount(x.indexmin(),x.indexmax());
3245  xcount.initialize();
3246 
3247  int pcount=0;
3248  int icount=0;
3249  int lkicount=0;
3250 
3251  int p1=0;
3252 
3253  dvector xsave(0,nxcount);
3254  ivector csave(0,nccount);
3255  dvector lkisave(0,nlkicount);
3256 
3257  tccount=0;
3258  txcount=0;
3259  pcount=0;
3260  ccount.initialize();
3261  Licount.initialize();
3262  Lxcount.initialize();
3263  xcount.initialize();
3264  lkicount=0;
3265 
3266  // do it again -- this oulod be the frist time in the adjoint code
3267  for (k = 0 ; k < n ; k++)
3268  {
3269  Lp [k] = c [k] = cp [k] ;
3270  //ccount[k]++;
3271  //tccount++;
3272  }
3273  ivector Top(0,n);
3274 
3275  for (k = 0 ; k < n ; k++) /* compute L(:,k) for L*L' = C */
3276  {
3277  /* --- Nonzero pattern of L(k,:) ------------------------------------ */
3278  Top(k) = cs_ereach (C, k, parent, s, c) ;
3279 
3280  //ssave(k)=s;
3281  if (allocated(ssave(k)))
3282  {
3283  cerr << "This can't happen" << endl;
3284  ad_exit(1);
3285  }
3286  else
3287  {
3288  ssave(k).allocate(Top(k),n-1);
3289  }
3290  ssave(k)=s(Top(k),n-1);
3291  x [k] = 0 ; /* x (0:k) is now zero */
3292  //xcount[k]++;
3293  for (p = Cp [k] ; p < Cp [k+1] ; p++) /* x = full(triu(C(:,k))) */
3294  {
3295  if (Ci [p] <= k)
3296  {
3297  x[Ci[p]] = Cx[p] ;
3298  xcount[Ci[p]]++;
3299  }
3300  }
3301  d = x [k] ; /* d = C(k,k) */
3302  //dcount++;
3303  x [k] = 0 ; /* clear x for k+1st iteration */
3304  //xcount[k]++;
3305  /* --- Triangular solve --------------------------------------------- */
3306  top=Top(k);
3307  for ( ; top < n ; top++) /* solve L(0:k-1,0:k-1) * x = C(:,k) */
3308  {
3309  i = s [top] ;
3310  icount++;
3311  lkisave(lkicount++)=lki;
3312  lki = x [i] / Lx [Lp [i]] ; /* L(k,i) = x (i) / L(i,i) */
3313  xsave(txcount++)=x(i);
3314  x [i] = 0 ; /* clear x for k+1st iteration */
3315  for (p1 = Lp [i] + 1 ; p1 < c [i] ; p1++)
3316  {
3317  x [Li [p1]] -= Lx [p1] * lki ;
3318  }
3319  d -= lki * lki ; /* d = d - L(k,i)*L(k,i) */
3320  csave(tccount++)=c[i];
3321  p2 = c [i] ;
3322  //ofs << ttc++ << " " << p2 << " 2" << endl;
3323  c[i]++;
3324  ccount[i]++;
3325  Li [p2] = k ; /* store L(k,i) in column i */
3326  Licount[p2]++;
3327  if (Licount(p2)>1)
3328  {
3329  cerr << "Error unhandled case in chol" << endl;
3330  }
3331  Lx [p2] = lki ;
3332  Lxcount[p2]++;
3333  if (Lxcount(p2)>1)
3334  {
3335  cerr << "Error unhandled case in chol" << endl;
3336  ad_exit(1);
3337  }
3338  }
3339  /* --- Compute L(k,k) ----------------------------------------------- */
3340  if (d <= 0) return ; /* not pos def */
3341  csave(tccount++)=c[k];
3342  p = c [k];
3343  //ofs << ttc++ << " " << p << " 1"<< endl;
3344  c[k]++;
3345  //ccount[k]++;
3346  pcount++;
3347  Li [p] = k ; /* store L(k,k) = sqrt (d) in column k */
3348  Licount[p]++;
3349  if (Licount(p)>1)
3350  {
3351  cerr << "Error unhandled case in chol" << endl;
3352  }
3353  Lx [p] = sqrt (d) ;
3354  Lxcount[p]++;
3355  if (Lxcount(p)>1)
3356  {
3357  cerr << "Error unhandled case in chol" << endl;
3358  ad_exit(1);
3359  }
3360  }
3361  Lp [n] = cp [n] ; /* finalize L */
3362 
3363 
3364  // now the real adjoint code
3365 
3366  for (k = n-1 ; k >=0 ; k--)
3367  {
3368  c[k]=csave(--tccount);
3369  p=c[k];
3370  s(ssave(k).indexmin(),ssave(k).indexmax())=ssave(k);
3371  //if (k==3)
3372  // cout << "HERE2" << endl;
3373  // Lx [p] = sqrt (d) ;
3374  //ofs << --ttc << " " << p << " 1" << endl;
3375 
3376  dfd+=dfLx(p)/(2.0*Lx(p));
3377  dfLx(p)=0.0;
3378 
3379  //c[k]=csave(--tccount);
3380  //p=c[k];
3381 
3382  for (top=n-1 ; top >=Top[k] ; top--)
3383  {
3384  i=s(top);
3385  //Lx [p] = lki ;
3386  c[i]=csave(--tccount);
3387  p2=c[i];
3388  //ofs << --ttc << " " << p2 << " 2" << endl;
3389  dflki+=dfLx[p2];
3390  dfLx[p2]=0.0;
3391  //d -= lki * lki ; /* d = d - L(k,i)*L(k,i) */
3392  dflki-=2.0*dfd*lki;
3393  for (p1 = Lp [i] + 1 ; p1 < c [i] ; p1++)
3394  {
3395  //x [Li [p1]] -= Lx [p1] * lki ;
3396  dflki-=dfx(Li(p1))*Lx(p1);
3397  dfLx(p1)-=dfx(Li(p1))*lki;
3398  }
3399  dfx[i]=0.0;
3400  // maybe not here
3401  x(i)=xsave(--txcount);
3402  // lki = x[i] / Lx[Lp[i]] ;
3403  dfx(i)+=dflki/Lx(Lp(i));
3404  dfLx(Lp(i))-=dflki*x(i)/square(Lx(Lp(i)));
3405  // but here
3406  dflki=0.0;
3407  lki=lkisave(--lkicount);
3408  }
3409  // x[k]=0.0;
3410  dfx[k]=0.0;
3411  //d = x [k] ; /* d = C(k,k) */
3412  dfx(k)+=dfd;
3413  dfd=0.0;
3414  for (p1 = Cp [k+1]-1 ; p1 >= Cp [k] ; p1--)
3415  {
3416  if (Ci [p1] <= k)
3417  {
3418  //x[Ci[p1]] = Cx[p1] ;
3419  dfCx[p1]+=dfx[Ci[p1]];
3420  dfx[Ci[p1]]=0.0;
3421  }
3422  }
3423  //x [k] = 0 ; /* clear x for k+1st iteration */
3424  dfx(k)=0.0;
3425  }
3426 
3427  dfCx.save_dvector_derivatives(cpos);
3428 
3429  return ;
3430 }
3431 
3432 int chol(XCONST dvar_hs_smatrix &AA, XCONST hs_symbolic &T,
3433  dvar_hs_smatrix &LL)
3434 {
3435  //ADUNCONST(hs_symbolic,S)
3436  //ADUNCONST(dvar_hs_smatrix,L)
3437  //ADUNCONST(dvar_hs_smatrix,A)
3438  dvar_hs_smatrix& A = (dvar_hs_smatrix&)AA;
3439  hs_symbolic& S = (hs_symbolic&)T;
3440  dvar_hs_smatrix& L = (dvar_hs_smatrix&)LL;
3441  int icount=0;
3442  dvariable lki;
3443  dvariable d;
3444  int top, i, p, k, n;
3445  int p1,p2;
3446  n = A.n ;
3447  ivector c(0,n-1); /* int workspace */
3448  ivector s(0,n-1); /* int workspace */
3449  dvar_vector x(0,n-1) ; /* double workspace */
3450 
3451  ivector & cp=S.cp;
3452  ivector & pinv=S.pinv;
3453  ivector & parent=S.parent;
3454 
3455  dvar_hs_smatrix C(A);
3456  C = A;
3457  if(S.pinv[0]!=-1)
3458  hs_symperm(A,pinv,C);
3459 
3460  //dvar_hs_smatrix & E = C;
3461 
3462  ivector & Cp=C.p;
3463  ivector & Ci=C.i;
3464  dvar_vector & Cx=C.x;
3465 
3466  ivector & Lp=L.p;
3467  ivector & Li=L.i;
3468  dvar_vector & Lx=L.x;
3469 
3470  for (k = 0 ; k < n ; k++)
3471  {
3472  Lp [k] = c [k] = cp [k] ;
3473  }
3474 
3475  for (k = 0 ; k < n ; k++)
3476  {
3477  top = cs_ereach (C, k, parent, s, c) ;
3478  x [k] = 0 ;
3479  for (p = Cp [k] ; p < Cp [k+1] ; p++)
3480  {
3481  if (Ci[p] <= k) x [Ci[p]] = Cx[p] ;
3482  }
3483  d = x[k] ;
3484  x[k] = 0.0;
3485  for ( ; top < n ; top++)
3486  {
3487  i = s[top] ;
3488  lki = x[i] / Lx[Lp[i]] ;
3489  icount++; // count the number of times lki is overwritten
3490  x [i] = 0 ;
3491  for (p1 = Lp [i] + 1 ; p1 < c [i] ; p1++)
3492  {
3493  x[Li[p1]] -= Lx[p1] * lki ;
3494  }
3495  d -= lki * lki ;
3496  p2 = c[i]++ ;
3497  Li [p2] = k ;
3498  Lx [p2] = lki ;
3499  }
3500  if (d <= 0) return (0) ;
3501  p = c[k]++ ;
3502  Li [p] = k ;
3503  Lx [p] = sqrt (d) ;
3504  }
3505  Lp [n] = cp [n] ;
3506  xxx(icount);
3507  return (1) ;
3508 }
3509  //class hs_symbolic // Info for symbolic cholesky
3510  //{
3511  // public:
3512  //
3513  // int n ; // Dimension of underlying pos. def. matrix
3514  // ivector pinv ; // inverse row perm. for QR, fill red. perm for Chol
3515  // ivector parent ; // elimination tree for Cholesky and QR
3516  // ivector cp ; // column pointers for Cholesky, row counts for QR
3517  // double lnz ; // # entries in L for LU or Cholesky; in V for QR
3518  //
3519  // hs_symbolic(int, XCONST css *);
3520  // hs_symbolic(int n, XCONST dmatrix &T, int order);
3521  // hs_symbolic(XCONST dcompressed_triplet &T, int order);
3522  // hs_symbolic(XCONST dvar_compressed_triplet &T, int order);
3523  // int is_null();
3524  // int cmp(hs_symbolic &S);
3525  // hs_symbolic(void);
3526  //};
3527 
3528 void hs_smatrix::set_symbolic(hs_symbolic& s)
3529 {
3530  sym.n=s.n;
3531  sym.pinv.allocate(s.pinv.indexmin(),s.pinv.indexmax());
3532  sym.pinv=s.pinv;
3533  sym.parent.allocate(s.parent.indexmin(),s.parent.indexmax());
3534  sym.parent=s.parent;
3535  sym.cp.allocate( s.cp.indexmin(),s.cp.indexmax());
3536  sym.cp=s.cp;
3537  sym.lnz=s.lnz;
3538 }
3539 
3540 void dvar_hs_smatrix::set_symbolic(hs_symbolic& s)
3541 {
3542  sym.n=s.n;
3543  sym.pinv.allocate(s.pinv.indexmin(),s.pinv.indexmax());
3544  sym.pinv=s.pinv;
3545  sym.parent.allocate(s.parent.indexmin(),s.parent.indexmax());
3546  sym.parent=s.parent;
3547  sym.cp.allocate( s.cp.indexmin(),s.cp.indexmax());
3548  sym.cp=s.cp;
3549  sym.lnz=s.lnz;
3550 }
3551 
3553 {
3555 
3557  /*dvar_vector_position dpos=*/fp->restore_dvar_vector_position();
3558  //dvector dfLx=restore_dvar_vector_derivatives(dpos);
3560 }
3561 
3562 
3564 {
3567 
3568  save_identifier_string("jx");
3570 
3572  save_identifier_string("jr");
3573 }
3574 
3576  uostream& ofs1,ofstream& ofs,int usize,int xsize,dvector& u)
3577 {
3578  int n=st.get_n();
3579  hs_smatrix HS(n,st);
3580  hs_smatrix L(S);
3581  chol(HS,S,L);
3582  dvector gr(0,n-1);
3583  dvector x(0,n-1);
3584  gr.initialize();
3585  ofs1 << usize << xsize;
3586  int i;
3587  for (i=1;i<=n;i++)
3588  {
3589  gr(i-1)=1.0;
3590  x = cs_ipvec(S.pinv, gr);
3591  gr(i-1)=0.0;
3592  x = cs_lsolve(L,x);
3593  x = cs_ltsolve(L,x);
3594  x = cs_pvec(S.pinv,x);
3595  ofs << setprecision(5) << setscientific()
3596  << setw(14) << u(i) << " " << sqrt(x(i-1)) << endl;;
3597  x.shift(1);
3598  ofs1 << x;
3599  x.shift(0);
3600  }
3601 }
3602 //#include "cs.h"
3603 /* C = A*B */
3604 hs_smatrix cs_multiply(const hs_smatrix &AA, const hs_smatrix &BB)
3605 {
3606  //ADUNCONST(hs_smatrix,A)
3607  //ADUNCONST(hs_smatrix,B)
3608  hs_smatrix& A = (hs_smatrix&)AA;
3609  hs_smatrix& B = (hs_smatrix&)BB;
3610  int p, j, nz = 0, anz, m, n, bnz;
3611  //hs_smatrix *pC ;
3612  //hs_smatrix C(n,anz + bnz);
3613  //hs_smatrix& C=*pC ;
3614 
3615  // if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ; /* check inputs */
3616  if (A.n != B.m) return (NULL) ;
3617  m = A.m ; anz = A.p[A.n] ;
3618  n = B.n ; ivector & Bp = B.p ; ivector & Bi = B.i ;
3619  dvector & Bx = B.x ; bnz = Bp[n] ;
3620  //w = cs_calloc (m, sizeof (int)) ; /* get workspace */
3621  ivector w(0,m); /* get workspace */
3622  //values = (A.x != NULL) && (Bx != NULL) ;
3623  //x = values ? cs_malloc (m, sizeof (double)) : NULL ;/* get workspace */
3624  dvector x(0,m); /* get workspace */
3625  hs_smatrix C(n,anz + bnz) ; /* allocate result */
3626  //if (!C || !w || (values && !x)) return (cs_done (C, w, x, 0)) ;
3627  ivector & Cp = C.p ;
3628  for (j = 0 ; j < n ; j++)
3629  {
3630  C.reallocate(2*(C.nzmax)+m);
3631 
3632  //if (nz + m > C.nzmax && !cs_sprealloc (C, 2*(C.nzmax)+m))
3633  //{
3634  // return (cs_done (C, w, x, 0)) ; /* out of memory */
3635  //}
3636  ivector& Ci = C.i ;
3637  dvector& Cx = C.x ; /* C->i and C->x may be reallocated */
3638  Cp [j] = nz ; /* column j of C starts here */
3639  for (p = Bp [j] ; p < Bp [j+1] ; p++)
3640  {
3641  nz = cs_scatter (A, Bi [p], Bx[p], w, x, j+1, C, nz) ;
3642  }
3643  for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Ci [p]] ;
3644  }
3645  Cp [n] = nz ; /* finalize the last column of C */
3646 
3647  return C;
3648  //cs_sprealloc (C, 0) ; /* remove extra space from C */
3649  //return (cs_done (C, w, x, 1)) ; /* success; free workspace, return C */
3650 }
3651 
3652 hs_smatrix operator * (const hs_smatrix &A, const hs_smatrix &B)
3653 {
3654  return cs_multiply(A,B);
3655 }
3657 {
3658  int mmin=M.indexmin();
3659  int mmax=M.indexmax();
3660  int n=mmax-mmin+1;
3661  int _jmin=M(mmin).indexmin();
3662  int _jmax=M(mmax).indexmax();
3663  int m=_jmax-_jmin+1;
3664  int ii=0;
3665  for (int i=mmin;i<=mmax;i++)
3666  {
3667  int jmin=M(i).indexmin();
3668  int jmax=M(i).indexmax();
3669  for (int j=jmin;j<=jmax;j++)
3670  {
3671  if (M(i,j) !=0) ii++;
3672  }
3673  }
3674  dcompressed_triplet dct(1,ii,n,m);
3675  ii=0;
3676  for (int i=mmin;i<=mmax;i++)
3677  {
3678  int jmin=M(i).indexmin();
3679  int jmax=M(i).indexmax();
3680  for (int j=jmin;j<=jmax;j++)
3681  {
3682  if (M(i,j) !=0)
3683  {
3684  ii++;
3685  dct(ii)=M(i,j);
3686  dct(1,ii)=i;
3687  dct(2,ii)=j;
3688  }
3689  }
3690  }
3691  return dct;
3692 }
3693 /*
3694 extern "C" {
3695  void ad_boundf(int i)
3696  {
3697  // so we can stop here
3698  exit(i);
3699  }
3700 }
3701 */
3702 
3703 hs_smatrix make_hs_smatrix(const dmatrix & M)
3704 {
3705  return hs_smatrix(make_dcompressed_triplet(M));
3706 }
3707 
3708 ostream& operator << (const ostream& _ofs,const hs_smatrix& M)
3709 {
3710  ADUNCONST(ostream,ofs)
3711  ofs << "nrows " << M.m << " ncols " << M.n << " nzmax " << M.nzmax
3712  << endl;
3713  ofs << "p = " << M.p << endl;
3714  ofs << "i = " << M.i << endl;
3715  ofs << "x = " << M.x << endl;
3716  return ofs;
3717 }
3718 
3719 dmatrix make_dmatrix(const hs_smatrix& M)
3720 {
3721  int n=M.m;
3722  int m=M.n;
3723  dmatrix tmp(1,n,1,m);
3724  tmp.initialize();
3725  int ii=0;
3726  for (int j=1;j<=m;j++)
3727  {
3728  for (int i=M.p(j-1);i<M.p(j);i++)
3729  {
3730  tmp(M.i(ii)+1,j)=M.x(ii);
3731  ii++;
3732  }
3733  }
3734  return tmp;
3735 }
3736 
3737 
3738  //
3739  //main()
3740  //{
3741  //
3742  // ad_exit=&ad_boundf;
3743  // int i,j;
3744  // int n=20;
3745  // int n2=n*n;
3746  // double alpha=0.3;
3747  // double beta=0.4;
3748  // /*
3749  // dmatrix X(1,6,1,5);
3750  // X.initialize();
3751  // X(1,1)=1.;
3752  // X(2,1)=2.;
3753  // X(6,1)=3.;
3754  // X(1,3)=4.;
3755  // X(2,3)=5.;
3756  // X(6,3)=6.;
3757  // X(5,4)=7.;
3758  // dcompressed_triplet dct1=make_dcompressed_triplet(X);
3759  // hs_smatrix Z0=hs_smatrix(dct1);
3760  // cout << Z0 << endl;
3761  // cout << X << endl;
3762  // cout << norm2(X-make_dmatrix(Z0)) << endl;
3763  // cout << make_dmatrix(dct1) << endl;
3764  // X.initialize();
3765  // X(1,1)=1.;
3766  // X(2,2)=2.;
3767  // X(3,3)=3.;
3768  // X(3,1)=5.;
3769  // X(3,2)=9.;
3770  // X(3,4)=7.;
3771  // dcompressed_triplet dct2=make_dcompressed_triplet(X);
3772  // hs_smatrix Z2=hs_smatrix(dct2);
3773  // cout << X << endl;
3774  // cout << make_dmatrix(dct2) << endl;
3775  // */
3776  //
3777  // dmatrix M(1,n2,1,n2);
3778  // M(1,1)=1;
3779  // M(1,2)=beta;
3780  // for (i=2;i<n2;i++)
3781  // {
3782  // M(i,i-1)=alpha;
3783  // M(i,i)=1;
3784  // M(i,i+1)=beta;
3785  // }
3786  // M(n2,n2-1)=alpha;
3787  // M(n2,n2)=1;
3788  // //dcompressed_triplet dct=make_dcompressed_triplet(M);
3789  // hs_smatrix SM=make_hs_smatrix(M);
3790  // //cout << norm2(make_dmatrix(dct)-M) << endl;
3791  //
3792  // dmatrix L(1,n2,1,n2);
3793  // L.initialize();
3794  // int ii=1;
3795  // for (i=1;i<=n;i++)
3796  // {
3797  // for (j=1;j<=n;j++)
3798  // {
3799  // L(ii,(j-1)*n+i)=1;
3800  // ii++;
3801  // }
3802  // }
3803  // hs_smatrix SL=make_hs_smatrix(L);
3804  // dmatrix Y=make_dmatrix(SM*SL);
3805  //
3806  // cout << norm2(Y-M*L) << endl;
3807  // exit(2);
3808  // //cout << L << endl;
3809  //
3810  // //cout << M << endl;
3811  // //cout << trans(L) * M * L << endl;
3812  // dmatrix N= M * trans(L) * M * L;
3813  // dmatrix N2=N*trans(N);
3814  // ii=0;
3815  // for (i=1;i<=n2;i++)
3816  // {
3817  // for (j=1;j<=n2;j++)
3818  // {
3819  // if (fabs(N(i,j))>1.e-8) ii++;
3820  // }
3821  // }
3822  // cout << "N num no zero " << ii << " percentage full "
3823  // << ii/double(n2*n2) << endl;
3824  // ii=0;
3825  // for (i=1;i<=n2;i++)
3826  // {
3827  // for (j=1;j<=n2;j++)
3828  // {
3829  // if (fabs(N2(i,j))>1.e-8) ii++;
3830  // }
3831  // }
3832  // cout << "N*trans(N) num no zero " << ii << " percentage full "
3833  // << ii/double(n2*n2) << endl;
3834  // //cout << setfixed() << setprecision(2) << setw(5) << N << endl;
3835  //}
3836  //
Base class for dvariable.
Definition: fvar.hpp:1315
int cs_fkeep(hs_smatrix &A, int(*fkeep)(int, int, double, void *), void *other)
Definition: hs_sparse.cpp:1278
void * restore_ad_pointer(void)
Description not yet available.
Definition: cmpdif3.cpp:237
void initialize(void)
Definition: hs_sparse.cpp:2566
ivector parent
Definition: fvar.hpp:9420
ivector cs_amd(XCONST hs_smatrix &A)
p = amd(A+A&#39;) if symmetric is true, or amd(A&#39;A) otherwise
Definition: hs_sparse.cpp:1522
ivector pinv
Definition: fvar.hpp:9418
dvar_matrix make_sdvar_matrix(dvar_compressed_triplet &M)
Definition: hs_sparse.cpp:169
int indexmin(void)
Definition: fvar.hpp:9354
void allocate(void)
Does not allocate, but initializes imatrix members.
Definition: imat.cpp:138
dvector cs_lsolve(XCONST hs_smatrix &LL, XCONST dvector &y)
Definition: hs_sparse.cpp:1148
double lnz
Definition: fvar.hpp:9424
dvector cs_ipvec(XCONST ivector &p, XCONST dvector &b)
Definition: hs_sparse.cpp:1104
Description not yet available.
Definition: imatrix.h:69
dvar_vector & shift(int min)
Description not yet available.
Definition: fvar_arr.cpp:28
void allocate(int mmin, int mmax, int n, int m)
Definition: hs_sparse.cpp:2593
dvector cs_pvec(XCONST ivector &p, XCONST dvector &b)
Definition: hs_sparse.cpp:1119
dvar_matrix make_dvar_matrix(dvar_compressed_triplet &M)
Definition: hs_sparse.cpp:187
dcompressed_triplet make_dcompressed_triplet(const dmatrix &M)
Definition: hs_sparse.cpp:3656
hs_symbolic(void)
Definition: hs_sparse.cpp:2471
int indexmax(void)
Definition: fvar.hpp:9358
void deallocate()
Deallocate imatrix memory.
Definition: imat.cpp:248
int check_flag
Definition: hs_sparse.cpp:2899
#define x
int allocated(const ivector &v)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: fvar_a59.cpp:13
#define ADUNCONST(type, obj)
Creates a shallow copy of obj that is not CONST.
Definition: fvar.hpp:140
Vector of double precision numbers.
Definition: dvector.h:50
int indexmin() const
Get minimum valid index.
Definition: dvector.h:199
int indexmin() const
Definition: fvar.hpp:2917
void cs_transpose(XCONST hs_smatrix &_A, int values, hs_smatrix &C)
Definition: hs_sparse.cpp:87
ivector cs_post(XCONST ivector &parent, int n)
Definition: hs_sparse.cpp:2258
hs_smatrix cs_add(XCONST hs_smatrix &AA, XCONST hs_smatrix &BB, double alpha, double beta)
Definition: hs_sparse.cpp:1404
void allocate(int ncl, int ncu)
Allocate memory for a dvector.
Definition: dvector.cpp:409
void initialize(void)
Zero initialize allocated dvar_matrix, then saves adjoint function and position data.
Definition: fvar_ma7.cpp:48
int cholnew(XCONST hs_smatrix &A, XCONST hs_symbolic &S, hs_smatrix &L)
Definition: hs_sparse.cpp:2973
dcompressed_triplet(int mmin, int mmax, int n, int m)
Definition: hs_sparse.cpp:2571
void save_dvector_derivatives(const dvar_vector_position &pos) const
Puts the derivative values in a dvector into a dvar_vector&#39;s guts.
Definition: cmpdif5.cpp:212
Description not yet available.
Definition: fvar.hpp:4814
exitptr ad_exit
Definition: gradstrc.cpp:53
ADMB variable vector.
Definition: fvar.hpp:2172
ivector cs_pinv(XCONST ivector &p, int n)
Definition: hs_sparse.cpp:2421
void verify_identifier_string(const char *)
Verifies gradient stack string.
Definition: cmpdif3.cpp:149
static void dfcholeski_sparse(void)
Definition: hs_sparse.cpp:3172
void save_int_value(int x)
Definition: cmpdif8.cpp:108
int cs_tdfs(int j, int k, ivector &head, XCONST ivector &next, ivector &post, ivector &stack)
Definition: hs_sparse.cpp:1495
int cs_diag(int i, int j, double aij, void *other)
Definition: hs_sparse.cpp:1273
ivector sgn(const dvector &v)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: dvect24.cpp:11
dmatrix operator*(const d3_array &t, const dvector &v)
Description not yet available.
Definition: d3arr12.cpp:17
void set_gradient_stack(void(*func)(void), double *dep_addr, double *ind_addr1=NULL, double mult1=0, double *ind_addr2=NULL, double mult2=0)
Description not yet available.
Definition: fvar.hpp:1045
int varchol(XCONST dvar_hs_smatrix &A, XCONST hs_symbolic &S, dvar_hs_smatrix &L, dcompressed_triplet &sparse_triplet2)
Definition: hs_sparse.cpp:3061
static void xxxv(ivector &x)
Definition: hs_sparse.cpp:26
dvector solve(const dmatrix &aa, const dvector &z)
Solve a linear system using LU decomposition.
Definition: dmat34.cpp:46
void allocate(int mmin, int mmax, int n, int m)
Definition: hs_sparse.cpp:2577
prescientific setscientific(void)
Description not yet available.
Definition: admanip.cpp:80
hs_smatrix make_hs_smatrix(const dmatrix &M)
Definition: hs_sparse.cpp:3703
dvar_compressed_triplet(int mmin, int mmax, int n, int m)
Definition: hs_sparse.cpp:2560
void report_derivatives(const dvar_vector &x)
Definition: hs_sparse.cpp:3563
int cs_scatter(XCONST hs_smatrix &AA, int j, double beta, ivector &w, dvector &x, int mark, hs_smatrix &C, int nz)
Definition: hs_sparse.cpp:1333
prnstream & endl(prnstream &)
void myacc(int &p, int Lpi1, int ci, const ivector &Li, dvector &x, const dvector &Lx, const double &lki)
Definition: hs_sparse.cpp:889
Array of integers(int) with indexes from index_min to indexmax.
Definition: ivector.h:50
d3_array sqrt(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2c.cpp:11
int cs_wclear(int mark, int lemax, ivector &w, int n)
Definition: hs_sparse.cpp:75
hs_smatrix cs_multiply(const hs_smatrix &A, const hs_smatrix &B)
Definition: hs_sparse.cpp:3604
dvector return_choleski_decomp_solve(dcompressed_triplet &dct, dvector &eps)
Definition: hs_sparse.cpp:2670
dvar_vector_position restore_dvar_vector_position()
Definition: cmpdif4.cpp:69
void RETURN_ARRAYS_INCREMENT()
Definition: gradstrc.cpp:478
#define min(a, b)
Definition: cbivnorm.cpp:188
Description not yet available.
Definition: fvar.hpp:3398
int indexmax() const
Get maximum valid index.
Definition: dvector.h:204
ivector cs_etree(XCONST hs_smatrix &_A)
Definition: hs_sparse.cpp:2193
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
int indexmin() const
Definition: ivector.h:99
int tmpxchol1(XCONST hs_smatrix &A, XCONST hs_symbolic &T, hs_smatrix &L, ivector &nxcount)
Definition: hs_sparse.cpp:976
#define M
Definition: rngen.cpp:57
dvector * m
Definition: fvar.hpp:2824
Description not yet available.
Definition: fvar.hpp:9345
dvariable beta(const prevariable &a, const prevariable &b)
Beta density function.
Definition: vbeta.cpp:18
static _THREAD gradient_structure * _instance
double cs_cumsum(ivector &p, ivector &c, int n)
Definition: hs_sparse.cpp:59
int restore_int_value()
Definition: cmpdif8.cpp:201
int indexmax() const
Definition: ivector.h:104
Description not yet available.
Definition: fvar.hpp:2819
void initialize(void)
Initialze all elements of dvector to zero.
Definition: dvect5.cpp:10
dvector & shift(int min)
Shift valid range of subscripts.
Definition: dvector.cpp:52
static void xxx(ivector re_list, ivector fe_list)
Definition: df1b2lp2.cpp:25
values
Definition: adjson.h:22
int save_identifier_string(const char *)
Writes a gradient stack verification string.
Definition: cmpdif2.cpp:315
Description not yet available.
Definition: fvar.hpp:9293
double ln_det(const dmatrix &m1, int &sgn)
Compute log determinant of a constant matrix.
Definition: dmat3.cpp:536
void hs_symperm(XCONST hs_smatrix &_A, XCONST ivector &pinv, hs_smatrix &C)
Definition: hs_sparse.cpp:803
void save_ad_pointer(void *p)
Description not yet available.
Definition: cmpdif3.cpp:226
int indexmax() const
Definition: fvar.hpp:2921
int cs_leaf(int i, int j, XCONST ivector &first, ivector &maxfirst, ivector &prevleaf, ivector &ancestor, int *jleaf)
Definition: hs_sparse.cpp:2287
void save_dvar_vector_position(const dvar_vector &v)
Definition: cmpdif3.cpp:214
void allocate(int, int)
Allocate dvar_vector with indexmin = ncl and indexmax = nch.
Definition: fvar_arr.cpp:270
void initialize(void)
Description not yet available.
Definition: ivec2.cpp:17
static _THREAD DF_FILE * fp
#define XCONST
Definition: hs_sparse.cpp:17
dmatrix make_dmatrix(dcompressed_triplet &M)
Definition: hs_sparse.cpp:202
void reallocate(double size)
Reallocate size of array.
Definition: ivect11.cpp:14
istream & operator>>(const istream &input, const d3_array &arr3)
Read values from input stream into arr3.
Definition: d3_io.cpp:60
ostream & operator<<(const ostream &_s, preshowpoint p)
Description not yet available.
Definition: admanip.cpp:48
ivector cs_counts(XCONST hs_smatrix &A, XCONST ivector &parent, XCONST ivector &post)
Definition: hs_sparse.cpp:2308
int chol(XCONST hs_smatrix &A, XCONST hs_symbolic &T, hs_smatrix &L)
Definition: hs_sparse.cpp:899
Description not yet available.
Definition: fvar.hpp:9410
int tmpxchol(XCONST hs_smatrix &A, XCONST hs_symbolic &S, hs_smatrix &L, ivector &xcount)
Class definition of matrix with derivitive information .
Definition: fvar.hpp:2480
#define w
double eps
Definition: ftweak.cpp:13
Stores the adjoint gradient data that will be processed by gradcalc.
dvector restore_dvar_vector_derivatives(const dvar_vector_position &tmp)
Description not yet available.
Definition: cmpdif5.cpp:150
void get_inverse_sparse_hessian(dcompressed_triplet &st, hs_symbolic &S, uostream &ofs1, ofstream &ofs, int usize, int xsize, dvector &u)
Definition: hs_sparse.cpp:3575
ivector cp
Definition: fvar.hpp:9422
void deallocate()
Deallocate dvar_vector memory.
Definition: fvar_ar1.cpp:15
void RETURN_ARRAYS_DECREMENT()
Definition: gradstrc.cpp:511
void initialize(const dvector &ww)
Description not yet available.
Definition: fvar_a24.cpp:63
dvector value(const df1_one_vector &v)
Definition: df11fun.cpp:69
static _THREAD grad_stack * GRAD_STACK1
#define max(a, b)
Definition: cbivnorm.cpp:189
void report_dvar_vector_derivatives(void)
Definition: hs_sparse.cpp:3552
dvector cs_ltsolve(XCONST hs_smatrix &LL, XCONST dvector &y)
Definition: hs_sparse.cpp:1224
class for things related to the gradient structures, including dimension of arrays, size of buffers, etc.
dvector return_choleski_factor_solve(hs_smatrix *PL, dvector &eps)
Definition: hs_sparse.cpp:2693
void initialize(void)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: dmat7.cpp:12
hs_smatrix * return_choleski_decomp(dcompressed_triplet &st)
Definition: hs_sparse.cpp:2636
dmatrix make_sdmatrix(dcompressed_triplet &M)
Definition: hs_sparse.cpp:216
void allocate(const ad_integer &ncl, const index_type &ncu)
Allocate vector of integers with dimension [_ncl to _nch].
Definition: indextyp.cpp:488
double square(const double value)
Return square of value; constant object.
Definition: d3arr4.cpp:16
Fundamental data type for reverse mode automatic differentiation.
Definition: fvar.hpp:1518
d3_array log(const d3_array &arr3)
Author: David Fournier Copyright (c) 2008-2012 Regents of the University of California.
Definition: d3arr2a.cpp:13
int cs_ereach(XCONST hs_smatrix &_A, int k, XCONST ivector &parent, ivector &s, ivector &w)
Definition: hs_sparse.cpp:744
void deallocate(void)
Called by destructor to deallocate memory for a dvector object.
Definition: dvector.cpp:92
void deallocate(void)
Definition: hs_sparse.cpp:2601