Skip to content

Commit 0602e67

Browse files
committed
added Lancsoz method
1 parent 1c471ac commit 0602e67

File tree

1 file changed

+148
-7
lines changed

1 file changed

+148
-7
lines changed

src/pyclassify/QR_alg_Wilkison.cpp

Lines changed: 148 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,130 @@
66
#include <array>
77
#include <iomanip>
88
#include <chrono>
9+
#include <future>
10+
#include <algorithm>
11+
#include <numeric>
12+
13+
std::vector<std::vector<double>>
14+
GivensProduct(const std::vector<std::array<double, 2>>& Matrix_trigonometric,
15+
unsigned int start,
16+
unsigned int end,
17+
unsigned int n)
18+
{
19+
// Create identity matrix Q of size n x n.
20+
std::vector<std::vector<double>> Q(n, std::vector<double>(n, 0.0));
21+
for (unsigned int row = 0; row < n; ++row) {
22+
Q[row][row] = 1.0;
23+
}
24+
25+
// For each rotation from start to end-1, update columns i and i+1.
26+
for (unsigned int i = start; i < end; ++i)
27+
{
28+
double c = Matrix_trigonometric[i][0];
29+
double s = Matrix_trigonometric[i][1];
30+
31+
// Rotate columns i and i+1 in Q (parallelizing over rows)
32+
#pragma omp parallel for
33+
for (int row = start; row < i+2; ++row)
34+
{
35+
double tmp = Q[row][i];
36+
Q[row][i] = c * tmp - s * Q[row][i + 1];
37+
Q[row][i+1] = s * tmp + c * Q[row][i + 1];
38+
}
39+
}
40+
return Q;
41+
}
42+
43+
void operator/=(std::vector<double> & x, const double scale_factor){
44+
std::for_each(x.begin(), x.end(), [scale_factor](double element){return element/scale_factor;});
45+
}
46+
std::vector<double> operator/(const std::vector<double> & x, const double scale_factor){
47+
std::vector<double> z;
48+
std::transform(x.cbegin(), x.cend(), std::front_inserter(z), [scale_factor](double element){return element/scale_factor;});
49+
return z;
50+
}
51+
std::vector<double> operator*(std::vector<double> & x, const double scale_factor){
52+
std::for_each(x.begin(), x.end(), [scale_factor](double element){return element*scale_factor;});
53+
return x;
54+
}
55+
56+
double norm_2(std::vector<double> & x){
57+
double sum=std::accumulate(x.begin(), x.end(), 0, [](double a, double b) { return a + b*b; });
58+
return std::sqrt(sum);
59+
}
60+
void operator-=(std::vector<double> & x, const std::vector<double>& y){
61+
std::transform(x.begin(), x.end(), y.begin(), x.begin(), std::minus<double>());
62+
}
63+
std::vector<double> operator-(std::vector<double> & x, const std::vector<double>& y){
64+
std::vector<double> z;
65+
std::transform(x.begin(), x.end(), y.begin(), std::front_inserter(z), std::minus<double>());
66+
return z;
67+
}
68+
std::vector<double> operator*(const std::vector<std::vector<double>> & A, const std::vector<double> & b){
69+
std::vector<double> x(A.size(), 0);
70+
71+
// Parallelize this loop
72+
for(unsigned int i=0; i<A.size(); ++i){
73+
x[i]=std::inner_product(A[i].begin(), A[i].end(), b.begin(), 0);
74+
}
75+
return x;
76+
}
77+
78+
double operator*(const std::vector<double> & x, const std::vector<double> & y){
79+
80+
return std::inner_product(x.cbegin(), x.cend(), y.cbegin(), 0);
81+
82+
}
83+
84+
void Lanczos_PRO(std::vector<std::vector<double>> A, std::vector<double> q, const unsigned int m, const double toll=1e-6){
85+
86+
q/=norm_2(q);
87+
std::vector<std::vector<double>> Q{q};
88+
89+
std::vector<double> r=A*q;
90+
91+
std::vector<double> alpha, beta;
92+
93+
alpha.push_back(q*r);
94+
r=r-q*alpha[0];
95+
96+
beta.push_back(norm_2(r));
97+
std::vector<double> res;
98+
99+
for (unsigned int j = 1; j < m; j++)
100+
{
101+
q= r/beta[j-1];
102+
res= Q*q;
103+
104+
for(auto const ele: res){
105+
if(std::abs(ele)>toll){
106+
107+
for(unsigned int i=0;i<Q.size(); ++i){
108+
double h=(q*Q[i]);
109+
q=q-Q[i]*h;
110+
}
111+
break;
112+
}
113+
}
114+
q/=norm_2(q);
115+
Q.push_back(q);
116+
r=A*q-(Q[j-1]*beta[j-1]);
117+
alpha.push_back(q * r);
118+
r = r - q *alpha[j];
119+
beta.push_back(norm_2(r));
120+
121+
if (std::abs(beta[j]) < 1e-15){
122+
123+
}
124+
125+
return Q, alpha, beta[:-1]
126+
127+
128+
}
129+
130+
131+
132+
}
9133

10134

11135
//std::pair<std::vector<double>, std::vector<std::vector<double>> >
@@ -122,14 +246,31 @@ void QR_algorithm(std::vector<double> diag, std::vector<double> off_diag, cons
122246

123247
}
124248

249+
250+
251+
125252
//Uncomment to compute the eigenvalue
126-
// for(unsigned int i=0; i<n-1; i++){
127-
// for(unsigned j=0; j<n;j++){
128-
// tmp=Q[j][i];
129-
// Q[j][i]=tmp*Matrix_trigonometric[i][0]-Q[j][i+1]*Matrix_trigonometric[i][1];
130-
// Q[j][i+1]=tmp*Matrix_trigonometric[i][1]+Q[j][i+1]*Matrix_trigonometric[i][0];
131-
// }
132-
// }
253+
for(unsigned int i=0; i<n-1; i++){
254+
for(unsigned j=0; j<n;j++){
255+
tmp=Q[j][i];
256+
Q[j][i]=tmp*Matrix_trigonometric[i][0]-Q[j][i+1]*Matrix_trigonometric[i][1];
257+
Q[j][i+1]=tmp*Matrix_trigonometric[i][1]+Q[j][i+1]*Matrix_trigonometric[i][0];
258+
}
259+
}
260+
261+
262+
unsigned int n_processor, delta_i=n/n_processor;
263+
std::future<std::vector<std::vector<double>>> future1 = std::async(std::launch::async, GivensProduct, Matrix_trigonometric, 0, 250 - 1, 500);
264+
std::future<std::vector<std::vector<double>>> future2 = std::async(std::launch::async, GivensProduct, Matrix_trigonometric, 250, 500 - 1 ,500);
265+
266+
std::vector< std::future<std::vector<std::vector<double>>> > vector_thread;
267+
std::vector <unsigned int> index;
268+
for(unsigned int i=0;i<n_processor;i++){
269+
index.push_back(i*delta_i);
270+
}
271+
272+
index.push_back(n-1);
273+
133274
iter++;
134275
if ( std::abs(off_diag[m-1]) < toll*( std::abs(diag[m]) + std::abs(diag[m-1]) ) )
135276
{

0 commit comments

Comments
 (0)