-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathRR_CG.m
104 lines (71 loc) · 1.9 KB
/
RR_CG.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
function conFilter=RR_CG(RX,RN,r,ranks,sigma_square)
x_0=zeros(size(r));
[~,R_total,diag_values,alpha_set]=conjgrad(RX,r,x_0,ranks);
U=R_total(:,1:ranks);
cg_diag=diag_values(1:ranks);
alpha=alpha_set(1:ranks);
% alpha=(U'*r)./cg_diag;
inv_sqrt_cg=1./(sqrt(cg_diag));
U_scale=U.*inv_sqrt_cg';
M=U_scale'*RN*U_scale;
M=(M+M')/2;
[D,EIG_VALUES]=eig(M);
EIG_VALUE_sub_vector=diag(EIG_VALUES);
c=D'*(sqrt(cg_diag).*alpha);
x0=0;
f=@(x) sum(EIG_VALUE_sub_vector.*c.^2./(1+x*EIG_VALUE_sub_vector).^2)-sigma_square;
g=@(x)-2*sum(EIG_VALUE_sub_vector.^2.*c.^2./(1+x*EIG_VALUE_sub_vector).^3);
mu=newton_root_power(f,g,x0);
y=D*(1./(1+mu*EIG_VALUE_sub_vector).*c);
x=y.*inv_sqrt_cg;
conFilter=U*x;
end
function [x,R_total,diag_values,alpha_set,beta_set] = conjgrad(A, b, x,iteration_num)
N=length(b);
R_total=zeros(N,iteration_num);
r = b - A * x;
p = r;
rsold = r' * r;
R_total(:,1)=p;
diag_values=zeros(iteration_num,1);
alpha_set=zeros(iteration_num,1);
beta_set=zeros(iteration_num,1);
for i = 1:iteration_num
Ap = A * p;
diag_values(i,1)=p'*Ap;
alpha = rsold / diag_values(i,1);
x = x + alpha * p;
r = r - alpha * Ap;
rsnew = r' * r;
% if sqrt(rsnew) < 1e-10
% break;
% end
beta_set(i)=rsnew / rsold ;
p = r + beta_set(i) * p;
rsold = rsnew;
R_total(:,i+1)=p;
alpha_set(i,1)=alpha;
end
end
function x0=newton_root_power(f,fprime,x0,maxIterations,tolerance)
if nargin<=3
maxIterations=1e4;
tolerance=1e-7;
end
for i = 1 : maxIterations
y = f(x0);
if y<=0
break;
end
yprime = fprime(x0);
if(abs(yprime) < eps) %Don't want to divide by too small of a number
% denominator is too small
break; %Leave the loop
end
x1 = x0 - y/yprime; %Do Newton's computation
if(norm(x1 - x0)/norm(x0) <= tolerance) %If the result is within the desired tolerance
break; %Done, so leave the loop
end
x0 = x1; %Update x0 to start the process again
end
end