Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

cross.cpp

Go to the documentation of this file.
00001 #include "cross.hpp"
00002 #include <math.h>
00003 
00004 Cross::Cross(const Matrix &M)
00005     : Skeleton(0), A(M), U(M.GetNumRows(), rank), 
00006     V(M.GetNumCols(), rank), fnorm2(0)
00007 { }
00008 
00009 Cross::~Cross() { }
00010 
00011 const Matrix& Cross::GetM() const
00012 {
00013     return A;
00014 }
00015 
00016 const Matrix& Cross::GetU() const
00017 {
00018     return U;
00019 }
00020 
00021 const Matrix& Cross::GetV() const
00022 {
00023     return V;
00024 }
00025 
00026 unsigned Cross::GetNumRows() const
00027 {
00028     return A.GetNumRows();
00029 }
00030 
00031 unsigned Cross::GetNumCols() const
00032 {
00033     
00034     return A.GetNumCols();
00035 }
00036 
00037 double Cross::GetEps() const
00038 {
00039     return eps;
00040 }
00041 
00042 double Cross::elem(unsigned i, unsigned j) const
00043 {
00044     unsigned k;
00045     double res = 0;
00046 #if HANDLEXCEPTION
00047     if((i < GetNumRows()) && (j < GetNumCols()))
00048         throw "assume i < num_rows and j < num_cols";
00049     }
00050 #endif
00051     // calc (U * V.T)[i][j]
00052     for(k = 0; k < rank; ++k) {
00053         res += U.elem(i, k) * V.elem(j, k);
00054     }
00055     return res;
00056 }
00057 
00058 
00059 /* return argmax of abs value in Vector
00060  * ignoring some index */
00061 static unsigned
00062 argmax_ignore_idx(const Vector& vec, const IndexList& ignore_idx)
00063 {
00064     unsigned res, i, j, size;
00065     double tmp, max_a = 0;
00066     size = ignore_idx.GetCurrentSize();
00067     i = ignore_idx.GetFirstNotListed();
00068     res = i;
00069     for(j = i; j < size; ++j) {
00070         for(; i < ignore_idx[j]; ++i) {
00071             tmp = fabs(vec.elem(i));
00072             if(tmp > max_a) {
00073                 max_a = tmp;
00074                 res = i;
00075             }
00076         }
00077         i = ignore_idx[j] + 1;
00078     }
00079     return res;
00080 }
00081 
00082 /* recalculate frobenius norm after add one
00083  * column to u and v */
00084 void Cross::RecalcFnorm()
00085 {
00086     unsigned i, k, num_cols, num_rows;
00087     double tmp1, tmp2;
00088     num_cols = GetNumCols();
00089     num_rows = GetNumRows();
00090     /* add dotproduts*/
00091     for(k = 0; k + 1 < rank; ++k) {
00092         for(tmp1 = 0, i = 0; i < num_rows; ++i) {
00093             tmp1 += U.elem(i, k) * U.elem(i, rank - 1);
00094         }
00095         for(tmp2 = 0, i = 0; i < num_cols; ++i) {
00096             tmp2 += V.elem(i, k) * V.elem(i, rank - 1);
00097         }
00098         fnorm2 += 2 * tmp1 * tmp2;
00099     }
00100     for(tmp1 = 0, i = 0; i < num_rows; ++i) {
00101         tmp1 += U.elem(i, rank - 1) * U.elem(i, rank - 1);
00102     }
00103     for(tmp2 = 0, i = 0; i < num_cols; ++i) {
00104         tmp2 += V.elem(i, rank - 1) * V.elem(i, rank - 1);
00105     }
00106     /* add ||u[r-1]||_2^2 * ||v[r-1]||_2^2 */
00107     fnorm2 += tmp1 * tmp2;
00108 }
00109 
00110 void Cross::Approximate(double _eps)
00111 {
00112     unsigned i, j, t, num_cols, num_rows;
00113     double tmp;
00114     MatrixSub M(A, *this);
00115     num_cols = GetNumCols();
00116     num_rows = GetNumRows();
00117     eps = _eps;
00118     row_marked_index.AddIndex(num_rows);
00119     col_marked_index.AddIndex(num_cols);
00120     for(;;) {
00121         /* find argmax */
00122         i = argmax_ignore_idx(
00123                 M.GetCol(col_marked_index.GetFirstNotListed()), 
00124                 row_marked_index
00125             );
00126         j = argmax_ignore_idx(M.GetRow(i), col_marked_index);
00127 
00128         /* check criteria */
00129         tmp = M.elem(i, j);
00130         if(fabs(tmp) * 
00131             sqrt((num_rows - (rank + 1)) * (num_cols - (rank + 1))) <=
00132             eps * sqrt(fnorm2))
00133         {
00134             break;
00135         }
00136 
00137         /* add new columns to U and V */
00138         U.Resize(rank + 1);
00139         for(t = 0; t < num_rows; ++t) {
00140             U.elem(t, rank) = (M.elem(t, j)) / sqrt(fabs(tmp));
00141         }
00142         V.Resize(rank + 1);
00143         for(t = 0; t < num_cols; ++t) {
00144             V.elem(t, rank) = (M.elem(i, t)) * sqrt(fabs(tmp)) / tmp;
00145         }
00146 
00147         /* increase rank */
00148         rank++;
00149 
00150         /* recalc Frobenius norm*/
00151         RecalcFnorm();
00152 
00153         /* update marked_index */
00154         row_marked_index.AddIndex(i);
00155         col_marked_index.AddIndex(j);
00156     }
00157 }
00158 

Generated on Sun May 25 01:58:04 2025 for SmoluchowskiSolver by Doxygen