forked from ZW-ZHANG/TIMERS
-
Notifications
You must be signed in to change notification settings - Fork 1
/
RefineBound.m
38 lines (34 loc) · 1.51 KB
/
RefineBound.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
function Loss_Bound = RefineBound(S_ori, S_add, Loss_ori, K)
% S_ori is n x n symmetric sparse original similarity matrix
% S_add is n x n symmetric sparse new similarity, may overlap with S_ori
% Loss_ori is the value or lower bound of loss for S_ori
% K is embedding dimension
% Return a lower bound of loss for S_ori + S_add by matrix perturbation inequality
% In short, Loss_Bound = Loss_ori + trace_change(S * S^T) - eigs(delta(S *S^T),K)
% Check our paper for detail:
% Zhang, Ziwei, et al. "TIMERS: Error-Bounded SVD Restart on Dynamic Networks". AAAI, 2018.
% Calculate trace change
S_overlap = (S_add ~= 0) .* S_ori ;
S_temp = S_add + S_overlap;
trace_change = sum(sum(S_temp .* S_temp)) - sum(sum(S_overlap .* S_overlap));
clear S_overlap S_temp;
% Calculate eigenvalues sum of delta(S * S^T)
% Notice we only need to deal with non-zero rows/columns
S_temp = S_ori * S_add;
S_temp = S_temp + S_temp' + S_add * S_add;
[~,S_choose,~] = find(sum(S_temp));
S_temp = S_temp(S_choose,S_choose);
clear S_choose;
% note eigs return largest absolute value, instead of largest
temp_eigs = eigs(S_temp,min(round(2 * K),length(S_temp)));
temp_eigs = temp_eigs(temp_eigs >= 0);
temp_eigs = sort(temp_eigs,'descend');
if (length(temp_eigs) >= K)
eigen_sum = sum(temp_eigs(1:K));
else % if doesn't calculate enough, add another inequality
temp_l = length(temp_eigs);
eigen_sum = sum(temp_eigs) + temp_eigs(temp_l) * (K - temp_l);
end
% Calculate loss lower bound
Loss_Bound = Loss_ori + trace_change - eigen_sum;
end