Cyclops Tensor Framework
parallel arithmetic on multidimensional arrays
svd.cxx
Go to the documentation of this file.
1 
8 #include <ctf.hpp>
9 #include "conj.h"
10 using namespace CTF;
11 
12 
13 template <typename dtype>
15  int m,
16  int n,
17  int k,
18  World & dw){
19 
20  // Perform SVD
21  Matrix<dtype> U,VT;
22  Vector<dtype> S;
23  A.svd(U,S,VT,k);
24  // Test orthogonality
25  Matrix<dtype> E(k,k,dw);
26 
27  E["ii"] = 1.;
28 
29  E["ij"] -= U["ki"]*conj<dtype>(U)["kj"];
30 
31  bool pass_orthogonality = true;
32 
33  double nrm1, nrm2, nrm3;
34  E.norm2(nrm1);
35  if (nrm1 > m*n*1.E-6){
36  pass_orthogonality = false;
37  }
38 
39  E["ii"] = 1.;
40 
41  E["ij"] -= VT["ik"]*conj<dtype>(VT)["jk"];
42 
43  E.norm2(nrm2);
44  if (nrm2 > m*n*1.E-6){
45  pass_orthogonality = false;
46  }
47 
48  A["ij"] -= U["ik"]*S["k"]*VT["kj"];
49 
50  bool pass_residual = true;
51  A.norm2(nrm3);
52  if (nrm3 > m*n*n*1.E-6){
53  pass_residual = false;
54  }
55 
56 #ifndef TEST_SUITE
57  if (dw.rank == 0){
58  printf("SVD orthogonality check returned %d, residual check %d\n", pass_orthogonality, pass_residual);
59  }
60 #else
61  if (!pass_residual || ! pass_orthogonality){
62  if (dw.rank == 0){
63  printf("SVD orthogonality check returned %d (%lf, %lf), residual check %d (%lf)\n", pass_orthogonality, nrm1, nrm2, pass_residual, nrm3);
64  }
65  }
66 #endif
67  return pass_residual & pass_orthogonality;
68 }
69 
70 bool test_svd(int m, int n, int k, World dw){
71  bool pass = true;
72  Matrix<float> A(m,n,dw);
73  Matrix<float> AA(m,n,dw);
74  A.fill_random(0.,1.);
75  AA.fill_random(0.,1.);
76  pass = pass & svd<float>(A,m,n,k,dw);
77 
78  Matrix<double> B(m,n,dw);
79  Matrix<double> BB(m,n,dw);
80  B.fill_random(0.,1.);
81  BB.fill_random(0.,1.);
82  pass = pass & svd<double>(B,m,n,k,dw);
83 
84  Matrix<std::complex<float>> cA(m,n,dw);
85  cA["ij"] = Function<float,float,std::complex<float>>([](float a, float b){ return std::complex<float>(a,b); })(A["ij"],AA["ij"]);
86  pass = pass & svd<std::complex<float>>(cA,m,n,k,dw);
87 
88 
89  Matrix<std::complex<double>> cB(m,n,dw);
90  cB["ij"] = Function<double,double,std::complex<double>>([](double a, double b){ return std::complex<double>(a,b); })(B["ij"],BB["ij"]);
91  pass = pass & svd<std::complex<double>>(cB,m,n,k,dw);
92  if (dw.rank == 0){
93  if (pass){
94  printf("{ A = USVT and U^TU = I } passed\n");
95  } else {
96  printf("{ A = USVT and U^TU = I } failed\n");
97  }
98  }
99 
100 
101  return pass;
102 }
103 
104 #ifndef TEST_SUITE
105 char* getCmdOption(char ** begin,
106  char ** end,
107  const std::string & option){
108  char ** itr = std::find(begin, end, option);
109  if (itr != end && ++itr != end){
110  return *itr;
111  }
112  return 0;
113 }
114 
115 
116 int main(int argc, char ** argv){
117  int rank, np, m, n, k, pass;
118  int const in_num = argc;
119  char ** input_str = argv;
120 
121  MPI_Init(&argc, &argv);
122  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
123  MPI_Comm_size(MPI_COMM_WORLD, &np);
124 
125  if (getCmdOption(input_str, input_str+in_num, "-m")){
126  m = atoi(getCmdOption(input_str, input_str+in_num, "-m"));
127  if (m < 0) m = 13;
128  } else m = 13;
129 
130 
131  if (getCmdOption(input_str, input_str+in_num, "-n")){
132  n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
133  if (n < 0) n = 5;
134  } else n = 5;
135 
136 
137  if (getCmdOption(input_str, input_str+in_num, "-k")){
138  k = atoi(getCmdOption(input_str, input_str+in_num, "-k"));
139  if (k < 0) k = std::min(m,n);
140  } else k = std::min(m,n);
141 
142  assert(k<=std::min(m,n));
143 
144 
145  {
146  World dw(argc, argv);
147 
148  if (rank == 0){
149  printf("Testing rank %d %d-by-%d SVD factorization\n", k, m, n);
150  }
151  pass = test_svd(m, n, k, dw);
152  assert(pass);
153  }
154 
155  MPI_Finalize();
156  return 0;
157 }
163 #endif
Matrix class which encapsulates a 2D tensor.
Definition: matrix.h:18
def rank(self)
Definition: core.pyx:312
bool svd(Matrix< dtype > A, int m, int n, int k, World &dw)
Definition: svd.cxx:14
char * getCmdOption(char **begin, char **end, const std::string &option)
Definition: svd.cxx:105
Vector class which encapsulates a 1D tensor.
Definition: vector.h:14
an instance of the CTF library (world) on a MPI communicator
Definition: world.h:19
string
Definition: core.pyx:456
dtype norm2()
computes the frobenius norm of the tensor (needs sqrt()!)
Definition: tensor.h:811
void fill_random(dtype rmin, dtype rmax)
fills local unique tensor elements to random values in the range [min,max] works only for dtype in {f...
Definition: tensor.cxx:928
int rank
rank of local processor
Definition: world.h:24
void svd(Matrix< dtype > &U, Vector< dtype > &S, Matrix< dtype > &VT, int rank=0)
Definition: matrix.cxx:481
bool test_svd(int m, int n, int k, World dw)
Definition: svd.cxx:70
Definition: apsp.cxx:17
int main(int argc, char **argv)
Definition: svd.cxx:116
def np(self)
Definition: core.pyx:315