ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/math/SVD.hpp
Revision: 3520
Committed: Mon Sep 7 16:31:51 2009 UTC (14 years, 10 months ago) by cli2
File size: 10806 byte(s)
Log Message:
Added new restraint infrastructure
Added MolecularRestraints
Added ObjectRestraints
Added RestraintStamp
Updated thermodynamic integration to use ObjectRestraints
Added Quaternion mathematics for twist swing decompositions
Significantly updated RestWriter and RestReader to use dump-like files
Added selections for x, y, and z coordinates of atoms
Removed monolithic Restraints class
Fixed a few bugs in gradients of Euler angles in DirectionalAtom and RigidBody
Added some rotational capabilities to prinicpalAxisCalculator

File Contents

# User Rev Content
1 cli2 3509 #ifndef JAMA_SVD_H
2     #define JAMA_SVD_H
3    
4     #include "math/DynamicRectMatrix.hpp"
5    
6     #include <algorithm>
7     // for min(), max() below
8     #include <cmath>
9     // for abs() below
10    
11     using namespace oopse;
12     using namespace std;
13    
14     namespace JAMA
15     {
16     /** Singular Value Decomposition.
17     <P>
18     For an m-by-n matrix A with m >= n, the singular value decomposition is
19     an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and
20     an n-by-n orthogonal matrix V so that A = U*S*V'.
21     <P>
22     The singular values, sigma(k) = S(k,k), are ordered so that
23     sigma(0) >= sigma(1) >= ... >= sigma(n-1).
24     <P>
25     The singular value decompostion always exists, so the constructor will
26     never fail. The matrix condition number and the effective numerical
27     rank can be computed from this decomposition.
28    
29     <p>
30     (Adapted from JAMA, a Java Matrix Library, developed by jointly
31     by the Mathworks and NIST; see http://math.nist.gov/javanumerics/jama).
32     */
33     template <class Real>
34     class SVD
35     {
36    
37     DynamicRectMatrix<Real> U, V;
38     DynamicVector<Real> s;
39     int m, n;
40    
41     public:
42    
43    
44     SVD (const DynamicRectMatrix<Real> &Arg) {
45     m = Arg.getNRow();
46     n = Arg.getNCol();
47     int nu = min(m,n);
48     s = DynamicVector<Real>(min(m+1,n));
49     U = DynamicRectMatrix<Real>(m, nu, Real(0));
50     V = DynamicRectMatrix<Real>(n,n);
51     DynamicVector<Real> e(n);
52     DynamicVector<Real> work(m);
53     DynamicRectMatrix<Real> A(Arg);
54 cli2 3520
55     int wantu = 1; /* boolean */
56     int wantv = 1; /* boolean */
57 cli2 3509 int i=0, j=0, k=0;
58    
59     // Reduce A to bidiagonal form, storing the diagonal elements
60     // in s and the super-diagonal elements in e.
61    
62     int nct = min(m-1,n);
63     int nrt = max(0,min(n-2,m));
64 cli2 3520
65 cli2 3509 for (k = 0; k < max(nct,nrt); k++) {
66     if (k < nct) {
67    
68     // Compute the transformation for the k-th column and
69     // place the k-th diagonal in s(k).
70     // Compute 2-norm of k-th column without under/overflow.
71     s(k) = 0;
72     for (i = k; i < m; i++) {
73     s(k) = hypot(s(k),A(i,k));
74     }
75     if (s(k) != 0.0) {
76     if (A(k,k) < 0.0) {
77     s(k) = -s(k);
78     }
79     for (i = k; i < m; i++) {
80     A(i,k) /= s(k);
81     }
82     A(k,k) += 1.0;
83     }
84     s(k) = -s(k);
85     }
86     for (j = k+1; j < n; j++) {
87     if ((k < nct) && (s(k) != 0.0)) {
88    
89     // Apply the transformation.
90    
91     Real t(0.0);
92     for (i = k; i < m; i++) {
93     t += A(i,k)*A(i,j);
94     }
95     t = -t/A(k,k);
96     for (i = k; i < m; i++) {
97     A(i,j) += t*A(i,k);
98     }
99     }
100    
101     // Place the k-th row of A into e for the
102     // subsequent calculation of the row transformation.
103    
104     e(j) = A(k,j);
105     }
106     if (wantu & (k < nct)) {
107    
108     // Place the transformation in U for subsequent back
109     // multiplication.
110    
111     for (i = k; i < m; i++) {
112     U(i,k) = A(i,k);
113     }
114     }
115     if (k < nrt) {
116    
117     // Compute the k-th row transformation and place the
118     // k-th super-diagonal in e(k).
119     // Compute 2-norm without under/overflow.
120     e(k) = 0;
121     for (i = k+1; i < n; i++) {
122     e(k) = hypot(e(k),e(i));
123     }
124     if (e(k) != 0.0) {
125     if (e(k+1) < 0.0) {
126     e(k) = -e(k);
127     }
128     for (i = k+1; i < n; i++) {
129     e(i) /= e(k);
130     }
131     e(k+1) += 1.0;
132     }
133     e(k) = -e(k);
134     if ((k+1 < m) & (e(k) != 0.0)) {
135    
136     // Apply the transformation.
137    
138     for (i = k+1; i < m; i++) {
139     work(i) = 0.0;
140     }
141     for (j = k+1; j < n; j++) {
142     for (i = k+1; i < m; i++) {
143     work(i) += e(j)*A(i,j);
144     }
145     }
146     for (j = k+1; j < n; j++) {
147     Real t(-e(j)/e(k+1));
148     for (i = k+1; i < m; i++) {
149     A(i,j) += t*work(i);
150     }
151     }
152     }
153     if (wantv) {
154    
155     // Place the transformation in V for subsequent
156     // back multiplication.
157    
158     for (i = k+1; i < n; i++) {
159     V(i,k) = e(i);
160     }
161     }
162     }
163     }
164    
165     // Set up the final bidiagonal matrix or order p.
166    
167     int p = min(n,m+1);
168     if (nct < n) {
169     s(nct) = A(nct,nct);
170     }
171     if (m < p) {
172     s(p-1) = 0.0;
173     }
174     if (nrt+1 < p) {
175     e(nrt) = A(nrt,p-1);
176     }
177     e(p-1) = 0.0;
178    
179     // If required, generate U.
180    
181     if (wantu) {
182     for (j = nct; j < nu; j++) {
183     for (i = 0; i < m; i++) {
184     U(i,j) = 0.0;
185     }
186     U(j,j) = 1.0;
187     }
188     for (k = nct-1; k >= 0; k--) {
189     if (s(k) != 0.0) {
190     for (j = k+1; j < nu; j++) {
191     Real t(0.0);
192     for (i = k; i < m; i++) {
193     t += U(i,k)*U(i,j);
194     }
195     t = -t/U(k,k);
196     for (i = k; i < m; i++) {
197     U(i,j) += t*U(i,k);
198     }
199     }
200     for (i = k; i < m; i++ ) {
201     U(i,k) = -U(i,k);
202     }
203     U(k,k) = 1.0 + U(k,k);
204     for (i = 0; i < k-1; i++) {
205     U(i,k) = 0.0;
206     }
207     } else {
208     for (i = 0; i < m; i++) {
209     U(i,k) = 0.0;
210     }
211     U(k,k) = 1.0;
212     }
213     }
214     }
215    
216     // If required, generate V.
217    
218     if (wantv) {
219     for (k = n-1; k >= 0; k--) {
220     if ((k < nrt) & (e(k) != 0.0)) {
221     for (j = k+1; j < nu; j++) {
222     Real t(0.0);
223     for (i = k+1; i < n; i++) {
224     t += V(i,k)*V(i,j);
225     }
226     t = -t/V(k+1,k);
227     for (i = k+1; i < n; i++) {
228     V(i,j) += t*V(i,k);
229     }
230     }
231     }
232     for (i = 0; i < n; i++) {
233     V(i,k) = 0.0;
234     }
235     V(k,k) = 1.0;
236     }
237     }
238    
239     // Main iteration loop for the singular values.
240    
241     int pp = p-1;
242     int iter = 0;
243     Real eps(pow(2.0,-52.0));
244     while (p > 0) {
245     int k=0;
246     int kase=0;
247    
248     // Here is where a test for too many iterations would go.
249    
250     // This section of the program inspects for
251     // negligible elements in the s and e arrays. On
252     // completion the variables kase and k are set as follows.
253    
254     // kase = 1 if s(p) and e(k-1) are negligible and k<p
255     // kase = 2 if s(k) is negligible and k<p
256     // kase = 3 if e(k-1) is negligible, k<p, and
257     // s(k), ..., s(p) are not negligible (qr step).
258     // kase = 4 if e(p-1) is negligible (convergence).
259    
260     for (k = p-2; k >= -1; k--) {
261     if (k == -1) {
262     break;
263     }
264     if (abs(e(k)) <= eps*(abs(s(k)) + abs(s(k+1)))) {
265     e(k) = 0.0;
266     break;
267     }
268     }
269     if (k == p-2) {
270     kase = 4;
271     } else {
272     int ks;
273     for (ks = p-1; ks >= k; ks--) {
274     if (ks == k) {
275     break;
276     }
277     Real t( (ks != p ? abs(e(ks)) : 0.) +
278     (ks != k+1 ? abs(e(ks-1)) : 0.));
279     if (abs(s(ks)) <= eps*t) {
280     s(ks) = 0.0;
281     break;
282     }
283     }
284     if (ks == k) {
285     kase = 3;
286     } else if (ks == p-1) {
287     kase = 1;
288     } else {
289     kase = 2;
290     k = ks;
291     }
292     }
293     k++;
294    
295     // Perform the task indicated by kase.
296    
297     switch (kase) {
298    
299     // Deflate negligible s(p).
300    
301     case 1: {
302     Real f(e(p-2));
303     e(p-2) = 0.0;
304     for (j = p-2; j >= k; j--) {
305     Real t( hypot(s(j),f));
306     Real cs(s(j)/t);
307     Real sn(f/t);
308     s(j) = t;
309     if (j != k) {
310     f = -sn*e(j-1);
311     e(j-1) = cs*e(j-1);
312     }
313     if (wantv) {
314     for (i = 0; i < n; i++) {
315     t = cs*V(i,j) + sn*V(i,p-1);
316     V(i,p-1) = -sn*V(i,j) + cs*V(i,p-1);
317     V(i,j) = t;
318     }
319     }
320     }
321     }
322     break;
323    
324     // Split at negligible s(k).
325    
326     case 2: {
327     Real f(e(k-1));
328     e(k-1) = 0.0;
329     for (j = k; j < p; j++) {
330     Real t(hypot(s(j),f));
331     Real cs( s(j)/t);
332     Real sn(f/t);
333     s(j) = t;
334     f = -sn*e(j);
335     e(j) = cs*e(j);
336     if (wantu) {
337     for (i = 0; i < m; i++) {
338     t = cs*U(i,j) + sn*U(i,k-1);
339     U(i,k-1) = -sn*U(i,j) + cs*U(i,k-1);
340     U(i,j) = t;
341     }
342     }
343     }
344     }
345     break;
346    
347     // Perform one qr step.
348    
349     case 3: {
350    
351     // Calculate the shift.
352    
353     Real scale = max(max(max(max(
354     abs(s(p-1)),abs(s(p-2))),abs(e(p-2))),
355     abs(s(k))),abs(e(k)));
356     Real sp = s(p-1)/scale;
357     Real spm1 = s(p-2)/scale;
358     Real epm1 = e(p-2)/scale;
359     Real sk = s(k)/scale;
360     Real ek = e(k)/scale;
361     Real b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
362     Real c = (sp*epm1)*(sp*epm1);
363     Real shift = 0.0;
364     if ((b != 0.0) || (c != 0.0)) {
365     shift = sqrt(b*b + c);
366     if (b < 0.0) {
367     shift = -shift;
368     }
369     shift = c/(b + shift);
370     }
371     Real f = (sk + sp)*(sk - sp) + shift;
372     Real g = sk*ek;
373    
374     // Chase zeros.
375    
376     for (j = k; j < p-1; j++) {
377     Real t = hypot(f,g);
378     Real cs = f/t;
379     Real sn = g/t;
380     if (j != k) {
381     e(j-1) = t;
382     }
383     f = cs*s(j) + sn*e(j);
384     e(j) = cs*e(j) - sn*s(j);
385     g = sn*s(j+1);
386     s(j+1) = cs*s(j+1);
387     if (wantv) {
388     for (i = 0; i < n; i++) {
389     t = cs*V(i,j) + sn*V(i,j+1);
390     V(i,j+1) = -sn*V(i,j) + cs*V(i,j+1);
391     V(i,j) = t;
392     }
393     }
394     t = hypot(f,g);
395     cs = f/t;
396     sn = g/t;
397     s(j) = t;
398     f = cs*e(j) + sn*s(j+1);
399     s(j+1) = -sn*e(j) + cs*s(j+1);
400     g = sn*e(j+1);
401     e(j+1) = cs*e(j+1);
402     if (wantu && (j < m-1)) {
403     for (i = 0; i < m; i++) {
404     t = cs*U(i,j) + sn*U(i,j+1);
405     U(i,j+1) = -sn*U(i,j) + cs*U(i,j+1);
406     U(i,j) = t;
407     }
408     }
409     }
410     e(p-2) = f;
411     iter = iter + 1;
412     }
413     break;
414    
415     // Convergence.
416    
417     case 4: {
418    
419     // Make the singular values positive.
420    
421     if (s(k) <= 0.0) {
422     s(k) = (s(k) < 0.0 ? -s(k) : 0.0);
423     if (wantv) {
424     for (i = 0; i <= pp; i++) {
425     V(i,k) = -V(i,k);
426     }
427     }
428     }
429    
430     // Order the singular values.
431    
432     while (k < pp) {
433     if (s(k) >= s(k+1)) {
434     break;
435     }
436     Real t = s(k);
437     s(k) = s(k+1);
438     s(k+1) = t;
439     if (wantv && (k < n-1)) {
440     for (i = 0; i < n; i++) {
441     t = V(i,k+1); V(i,k+1) = V(i,k); V(i,k) = t;
442     }
443     }
444     if (wantu && (k < m-1)) {
445     for (i = 0; i < m; i++) {
446     t = U(i,k+1); U(i,k+1) = U(i,k); U(i,k) = t;
447     }
448     }
449     k++;
450     }
451     iter = 0;
452     p--;
453     }
454     break;
455     }
456     }
457     }
458    
459    
460     void getU (DynamicRectMatrix<Real> &A) {
461    
462     int minm = min(m+1,n);
463    
464     A = DynamicRectMatrix<Real>(m, minm);
465    
466     for (int i=0; i<m; i++)
467     for (int j=0; j<minm; j++)
468     A(i,j) = U(i,j);
469     }
470    
471     /* Return the right singular vectors */
472     void getV (DynamicRectMatrix<Real> &A) {
473     A = V;
474     }
475    
476     /** Return the one-dimensional array of singular values */
477     void getSingularValues (DynamicVector<Real> &x) {
478     x = s;
479     }
480    
481     /** Return the diagonal matrix of singular values
482     @return S
483     */
484     void getS (DynamicRectMatrix<Real> &A) {
485     A = DynamicRectMatrix<Real>(n,n);
486     for (int i = 0; i < n; i++) {
487     for (int j = 0; j < n; j++) {
488     A(i,j) = 0.0;
489     }
490     A(i,i) = s(i);
491     }
492     }
493    
494     /** Two norm (max(S)) */
495     Real norm2 () {
496     return s(0);
497     }
498    
499     /** Two norm of condition number (max(S)/min(S)) */
500     Real cond () {
501     return s(0)/s(min(m,n)-1);
502     }
503    
504     /** Effective numerical matrix rank
505     @return Number of nonnegligible singular values.
506     */
507     int rank () {
508     Real eps = pow(2.0,-52.0);
509     Real tol = max(m,n)*s(0)*eps;
510     int r = 0;
511     for (int i = 0; i < s.dim(); i++) {
512     if (s(i) > tol) {
513     r++;
514     }
515     }
516     return r;
517     }
518     };
519     }
520     #endif
521     // JAMA_SVD_H