1
1
#include <malloc.h>
2
2
#include <omp.h>
3
+ #include <assert.h>
4
+ #include <string.h>
5
+ #include <math.h>
3
6
4
-
7
+ #define TOLERANCE 1e-3
5
8
// /*
6
9
// *****************************************************
7
10
// TODO -- You must implement this function
8
11
// *****************************************************
9
12
// */
10
- void SVD (int M , int N , float * D , float * * U , float * * SIGMA , float * * V_T )
13
+
14
+ void multiply (float * M_1 , int m1 , int n1 , float * M_2 , int m2 , int n2 , float * result )
15
+ {
16
+ assert (n1 == m2 );
17
+ float sum = 0.0 ;
18
+ int i ,j ,k ;
19
+ for (i = 0 ; i < m1 ; i ++ )
20
+ {
21
+ for (j = 0 ; j < n2 ; j ++ )
22
+ {
23
+ for (k = 0 ; k < n1 ; k ++ )
24
+ {
25
+ sum += M_1 [i * n1 + k ]* M_2 [k * n2 + j ];
26
+ }
27
+ result [i * n2 + j ] = sum ;
28
+ sum = 0.0 ;
29
+ }
30
+ }
31
+ }
32
+
33
+ void transpose (float * M , int m , int n , float * M_T )
34
+ {
35
+ int i ,j ;
36
+ for (i = 0 ; i < m ; i ++ )
37
+ {
38
+ for (j = 0 ; j < n ; j ++ )
39
+ {
40
+ M_T [j * m + i ]= M [i * m + j ];
41
+ }
42
+ }
43
+ }
44
+
45
+ float * initialize_identity (int size )
46
+ {
47
+ float * E_0 = (float * ) calloc (P * P , sizeof (float ));
48
+ for (int i = 0 ; i < size ; i ++ )
49
+ {
50
+ E_0 [i * size + i ] = 1.0 ;
51
+ }
52
+ }
53
+
54
+ float l2_norm (float * v_col , int length )
11
55
{
56
+ float norm = 0.0 , sum_sq = 0.0 ;
57
+ for (int i = 0 ; i < length ; i ++ )
58
+ {
59
+ sum_sq += v_col [i ]* v_col [i ];
60
+ }
61
+ return norm = sqrtf (sum_sq );
62
+ }
63
+
64
+ float l2_norm_diagonal_diff (float * A_next , float * A_current , int P )
65
+ {
66
+ float norm , sum_sq = 0.0 ;
67
+ for (int i = 0 ; i < P ; i ++ )
68
+ {
69
+ sum_sq += (A_next [i * P + i ]- A_current [i * P + i ])* (A_next [i * P + i ]- A_current [i * P + i ]);
70
+ }
71
+ return norm = sqrtf (sum_sq );
72
+ }
73
+
74
+ void classicalGS (float * A_current , float * A_T , int P , float * Q_current , float * R_current )
75
+ {
76
+ float * v_col = (float * ) malloc (sizeof (float )* P );
77
+ int col , row , row_ ;
78
+ float result ;
79
+ for (col = 0 ; col < P ; col ++ )
80
+ {
81
+ memcpy (v_col , A_T + col * P , P * sizeof (float ));
82
+ //v_col = a_col
83
+ for (row = 0 ; row < col ; row ++ )
84
+ {
85
+ //perform inner product:
86
+ result = 0.0 ;
87
+ for (row_ = 0 ; row_ < P ; row_ ++ )
88
+ {
89
+ result += (Q_current [row_ * P + row ]* (A_T [col * P + row_ ]));
90
+ }
91
+ R_current [row * P + col ]= result ;
92
+ }
93
+ R_current [col * P + col ] = l2_norm (v_col , P );
94
+ for (row = 0 ; row < P ; row ++ )
95
+ {
96
+ Q_current [row * P + col ]= v_col [row ]/R_current [col * P + col ];
97
+ }
98
+ }
99
+ free (v_col );
100
+ }
101
+
102
+ void SVD (int N , int P , float * D , float * * U , float * * SIGMA , float * * V_T )
103
+ {
104
+ /* 1.Perform SVD for D_T */
105
+ // Get eigen-values & eigen-vectors for D_T*D
106
+ float * D_T = (float * ) malloc (sizeof (float )* N * P );
107
+ transpose (D , N , P , D_T );
108
+ float * A = (float * ) calloc (P * P , sizeof (float )); //A=D_T*D|(PxP)
109
+ float * A_T = (float * ) calloc (P * P , sizeof (float )); //A_T|(PXP)
110
+ multiply (D_T , P , N , D , N , P , A );
111
+
112
+ //begin QR-algorithm for A:
113
+ float * A_current = A ; //PxP; initialised to A_0
114
+ float * E_current = initialize_identity (P ); //PXP; initialised to E_0
115
+ float * A_next = (float * ) calloc (P * P , sizeof (float ));
116
+ float * E_next = (float * ) calloc (P * P , sizeof (float ));
117
+ float * Q_ = (float * ) calloc (P * P , sizeof (float ));
118
+ float * R_ = (float * ) calloc (P * P , sizeof (float ));
119
+ float diff_norm ;
120
+ do //convergence condition for QR-algorithm
121
+ {
122
+ transpose (A_current , P , P , A_T );
123
+ classicalGS (A_current , A_T , P , Q_ , R_ );
124
+ multiply (R_ , P , P , Q_ , P , P , A_next );
125
+ multiply (E_current , P , P , Q_ , P , P , E_next );
126
+ diff_norm = l2_norm_diagonal_diff (A_next , A_current , P );
127
+ A_current = A_next ;
128
+ E_current = E_next ;
129
+ printf ("diff_norm: %f\n" , diff_norm );
130
+ }
131
+ while (diff_norm < TOLERANCE );
12
132
}
13
133
14
134
// /*
@@ -18,5 +138,6 @@ void SVD(int M, int N, float* D, float** U, float** SIGMA, float** V_T)
18
138
// */
19
139
void PCA (int retention , int M , int N , float * D , float * U , float * SIGMA , float * * D_HAT , int * K )
20
140
{
141
+
21
142
22
143
}
0 commit comments