├── .gitignore ├── AutoReProCS.m ├── Calc_SubspaceError.m ├── Curtain_AutoReProCS_InitAltProj_alpha60_rank40.avi ├── Data ├── Curtain.mat ├── Lake.mat ├── Lake_MC.mat ├── Lobby.mat ├── Person.mat ├── SwitchLight.mat ├── WaterSurface.mat ├── WavingTree.mat ├── escalator_data.mat └── lake_bgnd.mat ├── DemoDynRPCA.m ├── DemoFB.m ├── DisplayVideo.m ├── FigGenReProCS.m ├── LICENSE ├── Lobby_AutoReProCS_InitAltProj_alpha60_rank40.avi ├── Offline_ReProCS_PCA.m ├── PROPACK ├── Afunc.m ├── AtAfunc.m ├── Atransfunc.m ├── Cfunc.m ├── bdsqr.m ├── bdsqr.mexglx ├── bdsqr.mexsg ├── bdsqr.mexsg64 ├── bdsqr.mexsol ├── bdsqr.mexw32 ├── bdsqr_mex.c ├── compute_int.m ├── dbdqr.f ├── helio.mat ├── lanbpro.doc ├── lanbpro.m ├── lanbpro.txt ├── laneig.doc ├── laneig.m ├── laneig.txt ├── lanpro.doc ├── lanpro.m ├── lanpro.txt ├── lansvd.doc ├── lansvd.m ├── lansvd.txt ├── mminfo.m ├── mmread.m ├── mmwrite.m ├── pythag.m ├── refinebounds.m ├── reorth.f ├── reorth.m ├── reorth.mexglx ├── reorth.mexsg ├── reorth.mexsg64 ├── reorth.mexsol ├── reorth_mex.c ├── test.m ├── testtqlb.m ├── tqlb.f ├── tqlb.m ├── tqlb.mexglx ├── tqlb.mexsg ├── tqlb.mexsg64 ├── tqlb.mexsol ├── tqlb_mex.c └── update_gbound.m ├── README.md ├── ReProCS.m ├── ReProCS_PCA.m ├── ReProCS_pca_real.m ├── WrapperSimulatedDataComparison.m ├── WrapperSimulatedDataComparison_Rotation.m ├── YALL1_v1.4 ├── COPYING ├── Demos │ ├── demo_1d.m │ ├── demo_2d.m │ ├── demo_2dw.m │ ├── demo_L1L2.m │ ├── demo_L1L2con.m │ ├── demo_all.m │ ├── demo_complex.m │ ├── demo_dB.m │ ├── demo_hard.m │ ├── demo_nonneg.m │ ├── demo_rand.m │ ├── demo_weights.m │ ├── hard150.mat │ └── hard8nz.mat ├── Readme.txt ├── Run_Me_1st.m ├── Utilities │ ├── fWHtrans.cpp │ ├── fWHtrans.mexa64 │ ├── fWHtrans.mexmaci64 │ ├── fWHtrans.mexw32 │ ├── ifWHtrans.m │ ├── pdct_operator.m │ ├── pdft_operator.m │ ├── pdwht_operator.m │ ├── snr.m │ └── wavelet_basis.m ├── quick_start.m ├── quick_start2.m └── yall1.m ├── cgls.m ├── chksvds.m ├── compare_same_outlier_frac.m ├── cosamp_cgls.m ├── demo_fb_reprocs_pca.m ├── err_L_dynrpca_reprocspca ├── err_L_dynrpca_reprocspca.dat ├── err_L_dynrpca_reprocspca_bern.dat ├── lanbpro.m ├── lansvd.m ├── medropplusrpca.jpg ├── ncrpca.m ├── orth_proj.m ├── proj_PCA.m ├── proj_PCA_thresh.m ├── reprocs_pca_compare.jpg ├── simpleEVD.m ├── temp_altproj_alpha.jpg ├── temp_altproj_alpha_se.jpg └── temp_t_j_Se.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | #exclude MATLAB temp files 2 | *.m~ 3 | 4 | #exclude vim swp files 5 | *.swp 6 | 7 | #exclude videos, photos etc 8 | *.avi, *.jpg, *.jpeg, *.eps, *.pdf 9 | 10 | #exclude temporary files 11 | wrapper_compare_real_videos.m 12 | figures_new/ 13 | data/ 14 | comparison/ 15 | PROPACK/ 16 | 17 | -------------------------------------------------------------------------------- /AutoReProCS.m: -------------------------------------------------------------------------------- 1 | function [L_hat, P_hat, S_hat, T_hat, t_hat, ... 2 | P_track_full, P_track_new, T_calc]= AutoReProCS(M, ... 3 | P_init, ev_thresh, alpha, K, omega, outc, K_CS) 4 | %%%This is the automatic version of ReProCS algorithm under the latest 5 | %%%subspace change and support model. 6 | 7 | %This folder contains the code accompanying pre-print. 8 | %[1] "Provable Dynamic Robust PCA or Robust Subspace Tracking", Praneeth Narayanamurthy and Namrata Vaswani, IEEE Trans. Info. Theory, 2019. 9 | % 10 | %If you use this code please also cite the following papers 11 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 12 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 13 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 14 | 15 | 16 | %%% Inputs %%% 17 | %%% M - measurement matrix %%% 18 | %%% ev_thres - threshold for subspace change detection %%% 19 | %%% P_init - an initial estimate of the subspace %%% 20 | %%% t_train - the dimension of the training data %%% 21 | 22 | 23 | %%% Algorithm parameters %%% 24 | %%% alpha - frame length %%% 25 | %%% K - number of projection PCA steps %%% 26 | %%% omega - threshold for non-zero value in S %%% 27 | %%% K_CS - number of CoSaMP iterations %%% 28 | %%% outc - an upper bound on estimate of fraction of outliers per column 29 | 30 | %%% Outputs %%% 31 | %%% L_hat - estimate of the low rank matrix %%% 32 | %%% P_hat - estimate of the subspace in which L lies %%% 33 | %%% S_hat - estimate of the sparse signal %%% 34 | %%% t_hat - estimate of subspace change times %%% 35 | 36 | %% Initializations 37 | %thresh = ev_thresh / 2; 38 | P_hat_old = P_init; 39 | P_hat_new = []; 40 | P_hat = [P_hat_old, P_hat_new]; 41 | 42 | [n, t_max] = size(M); 43 | T_hat = zeros(n, t_max); 44 | S_hat = zeros(n, t_max); 45 | L_hat = zeros(n, t_max); 46 | t_hat = []; 47 | 48 | % L_hat(:, 1 : t_train) = M(:, 1 : t_train); 49 | k = 0; 50 | cnt = 1; 51 | phi_t = (eye(n) - P_hat * P_hat'); 52 | % In = eye(n); 53 | ph = 0; %ph - 0 => detect, 1 => ppca 54 | 55 | %% Main Algorithm Loop 56 | for ii = 1 : t_max 57 | %% Estimate support 58 | y_t = M(:, ii) - (P_hat * (P_hat' * M(:, ii))); 59 | DecayRate = 0.9; %other values work, may make it slower 60 | x_t_hat_cs = cosamp_cgls(phi_t, ... 61 | y_t, outc, DecayRate, K_CS, 1e-6); 62 | t_hat_temp = find(abs(x_t_hat_cs) > omega); 63 | % T_hat(t_hat_temp, ii) = 1; 64 | 65 | %% Estimate signal components 66 | % % [S_hat(t_hat_temp, ii), ~] = ... 67 | % % lsqr(phi_t(:, t_hat_temp), y_t, 1e-6, 50); 68 | % S_hat(t_hat_temp, ii) = phi_t(:, t_hat_temp) \ y_t; 69 | S_hat(t_hat_temp, ii) = cgls(phi_t(:, t_hat_temp), y_t, ... 70 | 0, 1e-10, 10); 71 | L_hat(:, ii) = M(:, ii) - S_hat(:, ii); 72 | 73 | 74 | %% Subspace update 75 | if(~mod(ii + 1 , alpha)) 76 | u = (ii + 1) / alpha; 77 | idx = (u-1) * alpha + 1 : u * alpha ; 78 | L_temp = L_hat(:, idx); 79 | 80 | MM = L_temp - (P_hat_old *(P_hat_old' * L_temp)); 81 | 82 | if(~ph) %%detect phase 83 | % phi_t = eye(n) - P_hat * P_hat'; 84 | if(svds(MM, 1) >= sqrt(alpha * ev_thresh)) 85 | ph = 1; 86 | t_hat = [t_hat, ii]; 87 | k = 0; 88 | end 89 | else %%ppca phase 90 | P_hat_new = proj_PCA_thresh(MM, sqrt(alpha * ev_thresh)); 91 | P_hat = [P_hat_old, P_hat_new]; 92 | phi_t = eye(n) - P_hat * P_hat'; 93 | 94 | if(k == K) 95 | P_hat_old = P_hat; 96 | P_hat = P_hat_old; 97 | end 98 | 99 | k = k + 1; 100 | 101 | if(k == K + 1) %%deletion 102 | P_hat_old = proj_PCA(L_temp, [], rank(P_init)); 103 | P_hat_new = []; 104 | P_hat = P_hat_old; 105 | k = 1; 106 | ph = 0; 107 | phi_t = eye(n) - P_hat * P_hat'; 108 | end 109 | end 110 | 111 | end 112 | 113 | 114 | %% Return subspace 115 | if((ii == 1) || ~(mod(ii + 1, alpha))) 116 | P_track_full{cnt} = P_hat; 117 | P_track_new{cnt} = P_hat_new; 118 | T_calc(cnt) = ii; 119 | cnt = cnt + 1; 120 | end 121 | end 122 | end 123 | 124 | 125 | -------------------------------------------------------------------------------- /Calc_SubspaceError.m: -------------------------------------------------------------------------------- 1 | function[SE_err] = Calc_SubspaceError(A, B) 2 | %% Calculate subspace error of two subspaces 3 | 4 | %Calculate the basis (orthonormal column vectors) of span(A), span(B) 5 | if(~isempty(A) && ~isempty(B)) 6 | [QA, ~] = qr(A); 7 | [QB, ~] = qr(B); 8 | 9 | ra = rank(A); 10 | rb = rank(B); 11 | 12 | [m,~] = size(A); 13 | SE_err = norm((eye(m) - QA(:, 1 : ra) * QA(:, 1 : ra)') ... 14 | * QB(:, 1 : rb), 2); 15 | else 16 | SE_err = eps; 17 | end 18 | end -------------------------------------------------------------------------------- /Curtain_AutoReProCS_InitAltProj_alpha60_rank40.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Curtain_AutoReProCS_InitAltProj_alpha60_rank40.avi -------------------------------------------------------------------------------- /Data/Curtain.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/Curtain.mat -------------------------------------------------------------------------------- /Data/Lake.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/Lake.mat -------------------------------------------------------------------------------- /Data/Lake_MC.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/Lake_MC.mat -------------------------------------------------------------------------------- /Data/Lobby.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/Lobby.mat -------------------------------------------------------------------------------- /Data/Person.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/Person.mat -------------------------------------------------------------------------------- /Data/SwitchLight.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/SwitchLight.mat -------------------------------------------------------------------------------- /Data/WaterSurface.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/WaterSurface.mat -------------------------------------------------------------------------------- /Data/WavingTree.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/WavingTree.mat -------------------------------------------------------------------------------- /Data/escalator_data.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/escalator_data.mat -------------------------------------------------------------------------------- /Data/lake_bgnd.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Data/lake_bgnd.mat -------------------------------------------------------------------------------- /DemoDynRPCA.m: -------------------------------------------------------------------------------- 1 | %%%Demo to implement the automatic ReProCS algorithm for simulated data. 2 | %This folder contains the code accompanying pre-print. 3 | % 4 | %[1] "Provable Dynamic Robust PCA or Robust Subspace Tracking", Praneeth Narayanamurthy and Namrata Vaswani, IEEE Trans. Info. Theory, 2019. 5 | % 6 | %If you use this code please also cite the following papers 7 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 8 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 9 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 10 | 11 | %%%If you want to include more than one subspace change, uncomment sections starting with SS2 12 | clear; 13 | clc; 14 | close all 15 | 16 | 17 | tic 18 | %% Data Generation 19 | n = 1000; 20 | t_max = 5000; 21 | s = ceil(0.05 * n); 22 | t_train = 200; 23 | miss_s = 0; 24 | alpha = 500; 25 | alpha1 = 100; 26 | f = 1; 27 | cnt = 1; 28 | MC = 1; 29 | err_t = zeros(MC, 16); 30 | 31 | %% varing initial error and angles 32 | sigmarange = [1e-3, 1e-5, 1e-7, 1e-9]; 33 | thetarange = [1, 15, 35, 45]; 34 | 35 | for ss = 1 : length(sigmarange) 36 | sigma = sigmarange(ss); 37 | for ll = 1 : length(thetarange) 38 | theta_degree = thetarange(ll); 39 | fprintf('log(Sigma): %d,\t theta: %d\n', ... 40 | log10(sigma), theta_degree); 41 | temp_err_L = zeros(MC, t_max - t_train); 42 | temp_err_SE = zeros(MC, ceil((t_max - t_train)/alpha)); 43 | 44 | for mc = 1 : MC 45 | 46 | fprintf('Monte-Carlo iteration %d in progress\n', mc); 47 | 48 | %%%Generating support set and sparse vectors 49 | S = zeros(n, t_max); 50 | rho = 1; 51 | b0 = 0.1; 52 | beta = ceil(b0 * alpha1); 53 | x_max = 25; 54 | x_min = 10; 55 | alpha1 = 100; 56 | num_changes = floor((t_max -t_train)/beta); 57 | 58 | num_changes1 = floor(alpha1 / beta); 59 | 60 | flag = 0; 61 | ii1 = 1; 62 | fval1 = 0; 63 | for ii = 1 : num_changes 64 | if(~flag) %%downward motion 65 | if(ii1 <= num_changes1) 66 | bind = fval1 + (ii1 - 1) * s/rho + 1; 67 | sind = min(bind - 1 + s, n); 68 | ii1 = ii1 + 1; 69 | if(ii1 == num_changes1 + 1) 70 | flag = 1; 71 | ii1 = 1; 72 | fval2 = bind; 73 | end 74 | end 75 | else 76 | if(ii1 <= num_changes1) 77 | bind = max(fval2 - (ii1 - 1) * s/rho , 1); 78 | sind = bind - 1 + s; 79 | ii1 = ii1 + 1; 80 | if(ii1 == num_changes1 + 1) 81 | flag = 0; 82 | ii1 = 1; 83 | end 84 | end 85 | end 86 | idx = bind : sind; 87 | jdx = t_train + (ii-1) * beta + 1 : t_train + ii * beta; 88 | S(idx, jdx) = x_min + ... 89 | (x_max - x_min) * rand(length(idx), beta); 90 | T(idx, jdx) = 1; 91 | end 92 | 93 | %%%Generate low-rank matrix 94 | r_0 = 1; 95 | r_1 = 1; 96 | r_2 = 1; 97 | 98 | %%SS2 99 | % r = r_0 + r_1 + r_2; 100 | r = r_0 + r_1; 101 | L = zeros(n, t_max); 102 | % diag_entries = [linspace(sqrt(f), sqrt(f)/2, r_0 - r_1), ... 103 | % ones(1 , r_1)]; 104 | diag_entries = [sqrt(f) * ones(1, r_0), 1]; 105 | 106 | 107 | t_1 = 1000; 108 | %%SS2 109 | % t_2 = 3000; 110 | P = orth(randn(n, r)); 111 | coeff_train = zeros(r_0, t_max); 112 | 113 | for cc = 1 : r_0 114 | coeff_train(cc, :) = -diag_entries(cc) + ... 115 | 2 * diag_entries(cc) * rand(1, t_max); 116 | end 117 | 118 | theta1 = theta_degree * pi / 180; 119 | %%SS2 120 | % theta2 = 1.01 * theta1; 121 | temp_rot1 = [cos(theta1), sin(theta1); ... 122 | -sin(theta1) cos(theta1)]; 123 | rot_matrix1 = blkdiag(eye(r_0 - 1), temp_rot1); 124 | 125 | %%SS2 126 | % temp_rot2 = [cos(theta2), sin(theta2); ... 127 | % -sin(theta2) cos(theta2)]; 128 | % rot_matrix2 = blkdiag(eye(r_0 - 1), temp_rot2); 129 | 130 | Irr = eye(r_0 + r_1); 131 | PP1 = P(:, 1 : r_0 + r_1) * rot_matrix1 * Irr(:, 1 : r_0); 132 | %%SS2 133 | % PP2 = [PP1, P(:, end)] * rot_matrix2 * Irr(:, 1 : r_0); 134 | L(:, 1:t_1) = P(:, 1:r_0) * coeff_train(:, 1:t_1); 135 | %%SS2 136 | % L(:, t_1+1:t_2) = PP1 * coeff_train(:, t_1+1:t_2); 137 | L(:, t_1 + 1 : end) = PP1 * coeff_train(:, t_1+1:end); 138 | M = L + S; 139 | 140 | %% Main online robust PCA algorithm section 141 | 142 | %%%Algorithm parameters 143 | K = 5; 144 | omega = x_min/2; 145 | %jugaad for init errors 146 | P_init = orth(P(:, 1 : r_0) + sigma * randn(n, r_0)/2.5); 147 | ev_thresh = 2e-3; 148 | % ev_thresh = 0.1/3 * (sin(theta1))^2; 149 | 150 | %%%Call to online RPCA function 151 | [L_hat, P_hat, S_hat, T_hat, t_hat, ... 152 | P_track_full, P_track_new, t_calc] = ... 153 | AutoReProCS(M(:, t_train + 1 : end), P_init, ... 154 | ev_thresh, alpha, K, omega, s, 5); 155 | 156 | %%Compute performance metrics 157 | temp_err_L(mc, :) = ... 158 | sqrt(mean((L(:, t_train + 1 : end) - L_hat).^2, 1)) ./ ... 159 | sqrt(mean(L(:, t_train + 1 : end).^2, 1)); 160 | miss_s = ... 161 | miss_s + (length(find(S_hat))- length(find(S)))/numel(S); 162 | 163 | Ea1 = orth(PP1(:, end) - (P_init * (P_init'* PP1(:, end)))); 164 | 165 | % err_t(mc, cnt) = t_hat(end) + t_train - t_1; 166 | %%SS2 167 | % Ea2 = orth(PP2(:, end) - (P_init * (P_init'* PP2(:, end)))); 168 | 169 | %%Calculate the subspace error 170 | for jj = 1 : length(t_calc) 171 | if (t_calc(jj) + t_train < t_1) 172 | temp_SE_Prot_Erot(mc, jj) = ... 173 | Calc_SubspaceError([], []); 174 | temp_SE_Phat_Prot(mc, jj) = ... 175 | Calc_SubspaceError(P_init, []); 176 | temp_SE_Phat_P(mc, jj) = ... 177 | Calc_SubspaceError(P_init, ... 178 | P(:, 1:r_0)); 179 | 180 | %%SS2 181 | % elseif((t_calc(jj) + t_train >= t_1) && ... 182 | % (t_calc(jj) +t_train < t_2)) 183 | % temp_SE_Prot_Erot(mc, jj) = ... 184 | % Calc_SubspaceError(P_track_new{jj}, Ea1); 185 | % temp_SE_Phat_Prot(mc, jj) = ... 186 | % Calc_SubspaceError(P_track_full{jj}, PP1(:, end)); 187 | % temp_SE_Phat_P(mc, jj) = ... 188 | % Calc_SubspaceError(P_track_full{jj}, PP1); 189 | 190 | %%SS2 replace the t_1 in next line with t_2, and make Ea1 - Ea2 etc 191 | elseif (t_calc(jj) + t_train >= t_1) 192 | temp_SE_Prot_Erot(mc, jj) = ... 193 | Calc_SubspaceError(P_track_new{jj}, Ea1); 194 | temp_SE_Phat_Prot(mc, jj) = ... 195 | Calc_SubspaceError(P_track_full{jj}, PP1(:, end)); 196 | temp_SE_Phat_P(mc, jj) = ... 197 | Calc_SubspaceError(P_track_full{jj}, PP1); 198 | end 199 | end 200 | %fprintf('\n\n'); 201 | end 202 | err_L(cnt, :) = mean(temp_err_L, 1); 203 | SE_Prot_Erot(cnt, :) = mean(temp_SE_Prot_Erot, 1); 204 | SE_Phat_Prot(cnt, :) = mean(temp_SE_Phat_Prot, 1); 205 | SE_Phat_P(cnt, :) = mean(temp_SE_Phat_P, 1); 206 | cnt = cnt + 1; 207 | end 208 | end 209 | toc 210 | 211 | %%call to this works only when there are 16 sigma-theta combination, otherwise need to manually generate figures 212 | FigGenReProCS 213 | 214 | -------------------------------------------------------------------------------- /DemoFB.m: -------------------------------------------------------------------------------- 1 | %%%Wrapper for foreground-background separation 2 | %This folder contains the code accompanying pre-print. 3 | % 4 | %[1] "New Results for Provable Dynamic Robust PCA", Praneeth Narayanamurthy and Namrata Vaswani, arXiv:1705.08948, 2017. 5 | % 6 | %If you use this code please also cite the following papers 7 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 8 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 9 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 10 | 11 | 12 | %%Read video 13 | clear; 14 | clc; 15 | close all 16 | 17 | addpath('YALL1_v1.4/'); 18 | addpath('PROPACK/'); 19 | 20 | load('Data/Curtain.mat'); 21 | %I = M; 22 | 23 | 24 | %% Training data processing 25 | %%option 1 -- init using batch RPCA 26 | t_train = 400; 27 | TrainData = I(:, 1 : t_train); 28 | rank_init = 40; 29 | 30 | L_hat_init = ncrpca(TrainData, rank_init); 31 | 32 | mu = mean(L_hat_init, 2); 33 | 34 | 35 | [Utemp, Stemp, ~] = svd(1 / sqrt(t_train) * (L_hat_init - ... 36 | repmat(mu, 1, t_train))); 37 | ss1 = diag(Stemp); 38 | L_init = Utemp(:, 1 : rank_init); 39 | 40 | %% option 2 -- init using outlier free data 41 | % mu = mean(DataTrain, 2); 42 | % t_train = size(DataTrain, 2); 43 | % [Utemp, Stemp, ~] = svd(1 / sqrt(t_train) * ... 44 | % (DataTrain - repmat(mu, 1, t_train))); 45 | % ss1 = diag(Stemp); 46 | % b = 0.95; 47 | % rank_init = min(find(cumsum(ss1.^2) >= b * sum(ss1.^2))); 48 | % L_init = Utemp(:, 1 : rank_init); 49 | 50 | 51 | fprintf('Initialized\n'); 52 | theta_thresh = 20 * pi / 180; 53 | ev_thresh = 0.1 * ss1(rank_init) * sin(theta_thresh)^2; 54 | 55 | 56 | %%Main online robust PCA algorithm section 57 | %% Call to online RPCA function 58 | 59 | K = 3; 60 | alpha = 60; 61 | 62 | 63 | tic 64 | fprintf('alpha = %d\tK = %d\n', alpha, K); 65 | [BG, FG, L_hat, S_hat, T_hat, t_hat, P_track_full, P_track_new] ... 66 | = ReProCS(I(:, t_train + 1 : end), ... 67 | L_init, mu, ev_thresh, alpha, K); 68 | toc 69 | 70 | 71 | 72 | VidName = ['Lobby_AutoReProCS_InitAltProj_alpha', num2str(alpha), ... 73 | '_rank', num2str(rank_init)]; 74 | DisplayVideo(I(:, t_train + 1 : end), FG, BG, T_hat, imSize, VidName); 75 | 76 | -------------------------------------------------------------------------------- /DisplayVideo.m: -------------------------------------------------------------------------------- 1 | function DisplayVideo( Data1, Data2, Data3, Data4, imSize, VideoName ) 2 | 3 | 4 | writerObj = VideoWriter(VideoName); % 5 | writerObj.FrameRate = 20; % How many frames per second. 6 | open(writerObj); 7 | figure; 8 | 9 | for i = 1: size(Data1,2) 10 | 11 | img1 = Data1(:,i); 12 | img1 = reshape(img1,imSize); 13 | 14 | img2 = Data2(:,i); 15 | img2 = reshape(img2,imSize); 16 | 17 | img3 = Data3(:,i); 18 | img3 = reshape(img3, imSize); 19 | 20 | img4 = Data4(:,i); 21 | img4 = reshape(img4, imSize); 22 | 23 | 24 | h = subplot('position',[0.01,0.50,0.47, 0.42]); 25 | imshow(img1/255); 26 | title(['time = ', num2str(i)]) 27 | 28 | h = subplot('position',[0.49,0.50,0.47, 0.42]); 29 | imshow(img2,[]); 30 | title('sparse signal') 31 | 32 | h = subplot('position',[0.01,0.001,0.47, 0.42]); 33 | imshow(img3/255); 34 | title('bg') 35 | 36 | h = subplot('position',[0.49,0.001,0.47, 0.42]); 37 | imshow(img4/255); 38 | title('fg(support)') 39 | 40 | 41 | frame = getframe(gcf); % 'gcf' can handle if you zoom in to take a movie. 42 | writeVideo(writerObj, frame); 43 | 44 | 45 | end 46 | 47 | hold off 48 | close(writerObj); 49 | close all 50 | -------------------------------------------------------------------------------- /FigGenReProCS.m: -------------------------------------------------------------------------------- 1 | %%Code to generate preliminary figures for ReProCS algo 2 | 3 | %clear 4 | %load data/ReProCS_cosamp_varyzz_varytheta_mc30.mat 5 | %addpath('/home/pkurpadn/Downloads/matlab2tikz-master/src/'); 6 | 7 | str1 = '$$\theta =\ $$'; 8 | str3 = '$$\log_{10}SE(\hat{P_0},P_0)=\ $$'; 9 | str2 = '$$\log SE(\hat{P}_{\mathrm{rot}}, E_{\mathrm{rot}})$$'; 10 | str4 = '$$t$$'; 11 | 12 | TheInd = [1, 5, 15, 30]; 13 | SigInd = [-2, -4, -6, -8]; 14 | 15 | % t_calc = t_calc(2:end) / 10000; 16 | % SE_Prot_Erot = SE_Prot_Erot(:, 2:end); 17 | % SE_Phat_Prot = SE_Phat_Prot(:, 2:end); 18 | % SE_Phat_P = SE_Phat_P(:, 2:end); 19 | 20 | 21 | for i = 1 : 4 22 | figure; 23 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) + 1, :)), ... 24 | 'r-.', 'LineWidth', 1); 25 | hold on; 26 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) +2, :)), ... 27 | 'k--', 'LineWidth', 1); 28 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) +3, :)), ... 29 | 'b:', 'LineWidth', 1); 30 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) +4, :)), ... 31 | 'm-', 'LineWidth', 1); 32 | 33 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) +1, :)), ... 34 | 'rs', 'MarkerFaceColor', [1 0 0], 'LineWidth', 1); 35 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) +2, :)), ... 36 | 'ks', 'MarkerFaceColor', [0 0 0], 'LineWidth', 1); 37 | 38 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) +3, :)), ... 39 | 'bs', 'MarkerFaceColor', [0 0 1], 'LineWidth', 1); 40 | plot(t_calc, log10(SE_Prot_Erot(4* (i - 1) +4, :)), ... 41 | 'ms', 'MarkerFaceColor', 'magenta', 'LineWidth', 1); 42 | 43 | h11 = legend('$\theta =\ 1^{\circ}$', '$\theta =\ 5^{\circ}$',... 44 | '$\theta =\ 15^{\circ}$', '$\theta =\ 30^{\circ}$'); 45 | 46 | % STRtitle = [str3, num2str(SigInd(i))]; 47 | % title(STRtitle, 'interpreter', 'latex'); 48 | % xlabel(str4, 'interpreter', 'latex'); 49 | % ylabel(str2, 'interpreter', 'latex'); 50 | yt = get(gca, 'YTick'); 51 | set(gca, 'FontSize', 16) 52 | xt = get(gca, 'XTick'); 53 | set(gca, 'FontSize', 16) 54 | set(h11, 'Interpreter', 'latex', 'FontSize', 10); 55 | %axis tight 56 | ylim([-10 -1]) 57 | %grid on 58 | % figname = ['figures/SE_Prot_Erot_zz_', num2str(-SigInd(i)), '.tex']; 59 | % matlab2tikz(figname, 'width','3.5cm','height','4cm'); 60 | % close; 61 | % figname = ['figures/SE_Prot_Erot_zz_', num2str(-SigInd(i)), '.eps']; 62 | % saveas(gca, figname, 'epsc') 63 | % close 64 | end 65 | %close all; 66 | str2 = '$$\log SE(\hat{P}, P_{\mathrm{rot}})$$'; 67 | 68 | for i = 1 : 4 69 | figure; 70 | plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) + 1, :)), ... 71 | 'r-.', 'LineWidth', 1.5); 72 | hold on; 73 | plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) +2, :)), ... 74 | 'k--', 'LineWidth', 1.5); 75 | plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) +3, :)), ... 76 | 'b:', 'LineWidth', 1.5); 77 | plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) +4, :)), ... 78 | 'm-', 'LineWidth', 1.5); 79 | 80 | % plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) +1, :)), ... 81 | % 'rs', 'MarkerFaceColor', [1 0 0], 'LineWidth', 1); 82 | % plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) +2, :)), ... 83 | % 'ks', 'MarkerFaceColor', [0 0 0], 'LineWidth', 1); 84 | % plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) +3, :)), ... 85 | % 'bs', 'MarkerFaceColor', [0 0 1], 'LineWidth', 1); 86 | % plot(t_calc, log10(SE_Phat_Prot(4* (i - 1) +4, :)), ... 87 | % 'ms', 'MarkerFaceColor', 'magenta', 'LineWidth', 1); 88 | 89 | h11 = legend('$\theta =\ 1^{\circ}$', '$\theta =\ 5^{\circ}$',... 90 | '$\theta =\ 15^{\circ}$', '$\theta =\ 30^{\circ}$'); 91 | 92 | % STRtitle = [str3, num2str(SigInd(i))]; 93 | % title(STRtitle, 'interpreter', 'latex'); 94 | set(h11, 'Interpreter', 'latex'); 95 | % xlabel(str4, 'interpreter', 'latex'); 96 | % ylabel(str2, 'interpreter', 'latex'); 97 | % yt = get(gca, 'YTick'); 98 | % set(gca, 'FontSize', 16) 99 | % xt = get(gca, 'XTick'); 100 | % set(gca, 'FontSize', 16) 101 | axis tight 102 | ylim([-10 1.1]) 103 | % figname = ['figures/SE_Phat_Prot_zz_', num2str(-SigInd(i)), '.tex']; 104 | % matlab2tikz(figname, 'width','3.5cm','height','4cm'); 105 | % close; 106 | 107 | % grid on 108 | % figname = ['figures/SE_Phat_Prot_zz_', num2str(-SigInd(i)), '.eps']; 109 | % saveas(gca, figname, 'epsc') 110 | % close 111 | end 112 | 113 | str2 = '$$\log SE(\hat{P}, P)$$'; 114 | for i = 1 : 4 115 | figure; 116 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) + 1, :)), ... 117 | 'r', 'LineWidth', 2); 118 | hold on; 119 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) +2, :)), ... 120 | 'k', 'LineWidth', 2); 121 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) +3, :)), ... 122 | 'b', 'LineWidth', 2); 123 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) +4, :)), ... 124 | 'g', 'LineWidth', 2); 125 | 126 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) +1, :)), ... 127 | 'rs', 'MarkerFaceColor', [1 0 0], 'LineWidth', 2); 128 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) +2, :)), ... 129 | 'ko', 'MarkerFaceColor', [0 0 0], 'LineWidth', 2); 130 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) +3, :)), ... 131 | 'b*', 'MarkerFaceColor', [0 0 1], 'LineWidth', 1); 132 | plot(t_calc, log10(SE_Phat_P(4* (i - 1) +4, :)), ... 133 | 'g+', 'MarkerFaceColor', [0 1 0], 'LineWidth', 2); 134 | 135 | h11 = legend('$\theta =\ 1^{\circ}$', '$\theta =\ 5^{\circ}$',... 136 | '$\theta =\ 15^{\circ}$', '$\theta =\ 30^{\circ}$'); 137 | 138 | STRtitle = [str3, num2str(SigInd(i))]; 139 | title(STRtitle, 'interpreter', 'latex'); 140 | set(h11, 'Interpreter', 'latex'); 141 | xlabel(str4, 'interpreter', 'latex'); 142 | ylabel(str2, 'interpreter', 'latex'); 143 | yt = get(gca, 'YTick'); 144 | set(gca, 'FontSize', 16) 145 | xt = get(gca, 'XTick'); 146 | set(gca, 'FontSize', 16) 147 | grid on 148 | axis tight 149 | 150 | % axes('position', [.65 .25 .25 .25]) 151 | % box on 152 | % indexofInterest = (t_calc >= 2000) & (t_calc<= 8000); 153 | % plot(t_calc(indexofInterest), ... 154 | % log10(SE_Phat_P(4* (i - 1) + 1, (indexofInterest))), ... 155 | % 'r', 'LineWidth', 2); 156 | % hold on; 157 | % plot(t_calc(indexofInterest), ... 158 | % log10(SE_Phat_P(4* (i - 1) +2, (indexofInterest))), ... 159 | % 'k', 'LineWidth', 2); 160 | % plot(t_calc(indexofInterest), ... 161 | % log10(SE_Phat_P(4* (i - 1) +3, (indexofInterest))), ... 162 | % 'b', 'LineWidth', 2); 163 | % plot(t_calc(indexofInterest), ... 164 | % log10(SE_Phat_P(4* (i - 1) +4, (indexofInterest))), ... 165 | % 'g', 'LineWidth', 2); 166 | % 167 | % plot(t_calc(indexofInterest), ... 168 | % log10(SE_Phat_P(4* (i - 1) +1, (indexofInterest))), ... 169 | % 'rs', 'MarkerFaceColor', [1 0 0], 'LineWidth', 2); 170 | % plot(t_calc(indexofInterest), ... 171 | % log10(SE_Phat_P(4* (i - 1) +2, (indexofInterest))), ... 172 | % 'ko', 'MarkerFaceColor', [0 0 0], 'LineWidth', 2); 173 | % plot(t_calc(indexofInterest), ... 174 | % log10(SE_Phat_P(4* (i - 1) +3, (indexofInterest))), ... 175 | % 'b*', 'MarkerFaceColor', [0 0 1], 'LineWidth', 1); 176 | % plot(t_calc(indexofInterest), ... 177 | % log10(SE_Phat_P(4* (i - 1) +4, (indexofInterest))), ... 178 | % 'g+', 'MarkerFaceColor', [0 1 0], 'LineWidth', 2); 179 | % grid on 180 | % axis tight 181 | % figname = ['figures/SE_Phat_P_zz_', num2str(-SigInd(i)), '.eps']; 182 | % saveas(gca, figname, 'epsc') 183 | % close 184 | end 185 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Praneeth Narayanamurthy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Lobby_AutoReProCS_InitAltProj_alpha60_rank40.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/Lobby_AutoReProCS_InitAltProj_alpha60_rank40.avi -------------------------------------------------------------------------------- /Offline_ReProCS_PCA.m: -------------------------------------------------------------------------------- 1 | function [L_hat_offline, P_hat, S_hat_offline, T_hat, t_hat, ... 2 | P_track_full, P_track_new, T_calc]= Offline_ReProCS_PCA(M, ... 3 | P_init, ev_thresh, alpha, K, omega, outc, K_CS) 4 | %%%This is the automatic version of ReProCS algorithm under the latest 5 | %%%subspace change and support model. 6 | 7 | %This folder contains the code accompanying pre-print. 8 | % 9 | %[1] "Provable Dynamic Robust PCA or Robust Subspace Tracking", Praneeth Narayanamurthy and Namrata Vaswani, IEEE Trans. Info. Theory., 2019. 10 | % 11 | %If you use this code please also cite the following papers 12 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 13 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 14 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 15 | 16 | 17 | %%% Inputs %%% 18 | %%% M - measurement matrix %%% 19 | %%% ev_thres - threshold for subspace change detection %%% 20 | %%% P_init - an initial estimate of the subspace %%% 21 | %%% t_train - the dimension of the training data %%% 22 | 23 | 24 | %%% Algorithm parameters %%% 25 | %%% alpha - frame length %%% 26 | %%% K - number of projection PCA steps %%% 27 | %%% omega - threshold for non-zero value in S %%% 28 | %%% K_CS - number of CoSaMP iterations %%% 29 | %%% outc - an upper bound on estimate of fraction of outliers per column 30 | 31 | %%% Outputs %%% 32 | %%% L_hat - estimate of the low rank matrix %%% 33 | %%% P_hat - estimate of the subspace in which L lies %%% 34 | %%% S_hat - estimate of the sparse signal %%% 35 | %%% t_hat - estimate of subspace change times %%% 36 | 37 | %% Initializations 38 | %thresh = ev_thresh / 2; 39 | [~, r_init] = size(P_init); 40 | P_hat_old = P_init; 41 | P_hat_new = []; 42 | P_hat = [P_hat_old, P_hat_new]; 43 | 44 | [n, t_max] = size(M); 45 | T_hat = zeros(n, t_max); 46 | S_hat = zeros(n, t_max); 47 | L_hat = zeros(n, t_max); 48 | S_hat_offline = zeros(n, t_max); 49 | L_hat_offline = zeros(n, t_max); 50 | 51 | t_hat = [1]; 52 | 53 | % L_hat(:, 1 : t_train) = M(:, 1 : t_train); 54 | k = 0; 55 | cnt = 1; 56 | phi_t = (eye(n) - P_hat * P_hat'); 57 | % In = eye(n); 58 | ph = 1; %ph - 0 => detect, 1 => ppca 59 | 60 | %% Main Algorithm Loop 61 | for ii = 1 : t_max 62 | %% Estimate support 63 | y_t = M(:, ii) - (P_hat * (P_hat' * M(:, ii))); 64 | DecayRate = 0.9; %other values work, may make it slower 65 | x_t_hat_cs = cosamp_cgls(phi_t, ... 66 | y_t, outc, DecayRate, K_CS, 1e-6); 67 | t_hat_temp = find(abs(x_t_hat_cs) > omega); 68 | % T_hat(t_hat_temp, ii) = 1; 69 | 70 | %% Estimate signal components 71 | % % [S_hat(t_hat_temp, ii), ~] = ... 72 | % % lsqr(phi_t(:, t_hat_temp), y_t, 1e-6, 50); 73 | % S_hat(t_hat_temp, ii) = phi_t(:, t_hat_temp) \ y_t; 74 | S_hat(t_hat_temp, ii) = cgls(phi_t(:, t_hat_temp), y_t, ... 75 | 0, 1e-10, 10); 76 | L_hat(:, ii) = M(:, ii) - S_hat(:, ii); 77 | 78 | 79 | %% Subspace update 80 | if(~mod(ii + 1 , alpha)) 81 | u = (ii + 1) / alpha; 82 | idx = (u-1) * alpha + 1 : u * alpha ; 83 | L_temp = L_hat(:, idx); 84 | 85 | MM = L_temp - (P_hat_old *(P_hat_old' * L_temp)); 86 | 87 | if(~ph) %%detect phase 88 | % phi_t = eye(n) - P_hat * P_hat'; 89 | if(svds(MM, 1) >= sqrt(alpha * ev_thresh)) 90 | ph = 1; 91 | t_hat = [t_hat, ii]; 92 | k = 0; 93 | end 94 | else %%ppca phase 95 | P_hat = simpleEVD((L_hat(:, max(1, ii - alpha + 1) : ii)), r_init); 96 | phi_t = speye(n) - P_hat * P_hat'; 97 | k = k + 1; 98 | 99 | if(k==K + 1) 100 | P_hat_old = P_hat; 101 | if(length(t_hat) == 1) 102 | idx_offline = t_hat(end) : ii; 103 | else 104 | idx_offline = t_hat(end - 1) + (K) * alpha : ii; 105 | end 106 | %idx_offline = t_hat(end) : ii; 107 | for kk = idx_offline 108 | yy = M(:, kk) - (P_hat * (P_hat' * M(:, kk))); 109 | DecayRate = 0.9; 110 | x_t_hat_cs = cosamp_cgls(phi_t, ... 111 | yy, outc, DecayRate, K_CS, 1e-6); 112 | t_hat_temp = find(abs(x_t_hat_cs) > omega); 113 | S_hat_offline(t_hat_temp, kk) = ... 114 | cgls(phi_t(:, t_hat_temp), yy, ... 115 | 0, 1e-10, 10); 116 | L_hat_offline(:, kk) = M(:, kk) - ... 117 | S_hat_offline(:, kk); 118 | end 119 | k = 1; 120 | ph = 0; 121 | phi_t = speye(n) - P_hat * P_hat'; 122 | end 123 | end 124 | end 125 | 126 | 127 | %% Return subspace 128 | if((ii == 1) || ~(mod(ii + 1, alpha))) 129 | P_track_full{cnt} = P_hat; 130 | P_track_new{cnt} = P_hat_new; 131 | T_calc(cnt) = ii; 132 | cnt = cnt + 1; 133 | end 134 | end 135 | end 136 | -------------------------------------------------------------------------------- /PROPACK/Afunc.m: -------------------------------------------------------------------------------- 1 | function y=Afunc(x) 2 | % y=Afunc(x) 3 | % Testfunction returning a linear operator applied to x. 4 | % Used for testing lansvd. 5 | % 6 | % y = A'*x 7 | 8 | % Rasmus Munk Larsen, DAIMI, 1998 9 | 10 | global A MxV 11 | y = A*x; 12 | MxV = MxV + 1; -------------------------------------------------------------------------------- /PROPACK/AtAfunc.m: -------------------------------------------------------------------------------- 1 | function y=AtAfunc(x) 2 | % y=AtAfunc(x) 3 | % Testfunction defining a linear operator applied to x. 4 | % Used for testing laneig. 5 | % 6 | % y = A'*(A*x) 7 | 8 | % Rasmus Munk Larsen, DAIMI, 1998 9 | 10 | 11 | global A MxV 12 | y = A'*(A*x); 13 | MxV = MxV + 2; 14 | -------------------------------------------------------------------------------- /PROPACK/Atransfunc.m: -------------------------------------------------------------------------------- 1 | function y=Atransfunc(x) 2 | % y=Atransfunc(x) 3 | % Testfunction returning the transpose of a linear operator applied to x. 4 | % Used for testing lansvd. 5 | % 6 | % y = A'*x 7 | 8 | % Rasmus Munk Larsen, DAIMI, 1998 9 | 10 | global A MxV 11 | y = A'*x; 12 | MxV = MxV + 1; 13 | -------------------------------------------------------------------------------- /PROPACK/Cfunc.m: -------------------------------------------------------------------------------- 1 | function y = Cfunc(x) 2 | % y=Cfunc(x) 3 | % Testfunction defining a linear operator applied to x. 4 | % Used for testing laneig. 5 | % 6 | % y = [ 0 A ] * x 7 | % [ A' 0 ] 8 | 9 | % Rasmus Munk Larsen, DAIMI, 1998 10 | 11 | 12 | global A MxV 13 | [m n] = size(A); 14 | y = [A*x(m+1:end,:); A'*x(1:m,:)]; 15 | MxV = MxV + 2; -------------------------------------------------------------------------------- /PROPACK/bdsqr.m: -------------------------------------------------------------------------------- 1 | function [sigma,bnd] = bdsqr(alpha,beta) 2 | 3 | % BDSQR: Compute the singular values and bottom element of 4 | % the left singular vectors of a (k+1) x k lower bidiagonal 5 | % matrix with diagonal alpha(1:k) and lower bidiagonal beta(1:k), 6 | % where length(alpha) = length(beta) = k. 7 | % 8 | % [sigma,bnd] = bdsqr(alpha,beta) 9 | % 10 | % Input parameters: 11 | % alpha(1:k) : Diagonal elements. 12 | % beta(1:k) : Sub-diagonal elements. 13 | % Output parameters: 14 | % sigma(1:k) : Computed eigenvalues. 15 | % bnd(1:k) : Bottom elements in left singular vectors. 16 | 17 | % Below is a very slow replacement for the BDSQR MEX-file. 18 | 19 | % warning('PROPACK:NotUsingMex','Using slow matlab code for bdsqr.') 20 | k = length(alpha); 21 | if min(size(alpha)') ~= 1 | min(size(beta)') ~= 1 22 | error('alpha and beta must be vectors') 23 | elseif length(beta) ~= k 24 | error('alpha and beta must have the same lenght') 25 | end 26 | B = spdiags([alpha(:),beta(:)],[0,-1],k+1,k); 27 | [U,S,V] = svd(full(B),0); 28 | sigma = diag(S); 29 | bnd = U(end,1:k)'; 30 | 31 | 32 | -------------------------------------------------------------------------------- /PROPACK/bdsqr.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/bdsqr.mexglx -------------------------------------------------------------------------------- /PROPACK/bdsqr.mexsg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/bdsqr.mexsg -------------------------------------------------------------------------------- /PROPACK/bdsqr.mexsg64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/bdsqr.mexsg64 -------------------------------------------------------------------------------- /PROPACK/bdsqr.mexsol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/bdsqr.mexsol -------------------------------------------------------------------------------- /PROPACK/bdsqr.mexw32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/bdsqr.mexw32 -------------------------------------------------------------------------------- /PROPACK/bdsqr_mex.c: -------------------------------------------------------------------------------- 1 | /* 2 | MEX interface for LAPACK routine bdsqr. 3 | Matlab calling sequence: 4 | [sigma,bnd] = bdsqr(alpha,beta) 5 | */ 6 | 7 | #include 8 | #include 9 | #include "mex.h" 10 | 11 | /* Templates for FORTRAN routines: */ 12 | void dbdqr_(int *n, double *d, double *e, double *c1, double *c2); 13 | void dbdsqr_(char *uplo, int *n, int *ncvt, int *nru, int *ncc, 14 | double *d, double *e, double *vt, int *ldt, double *u, 15 | int *ldu, double *c, int *ldc, double *work, int *info); 16 | 17 | /* Here comes the gateway function to be called by Matlab: */ 18 | void mexFunction(int nlhs, mxArray *plhs[], 19 | int nrhs, const mxArray *prhs[]) 20 | { 21 | int m, n, i, info, zero=0, one=1; 22 | double *d,*e,dummy, *wrk, *bnd; 23 | 24 | if (nrhs != 2) 25 | mexErrMsgTxt("bdsqr requires two input arguments"); 26 | else if (nlhs != 2) 27 | mexErrMsgTxt("bdsqr requires two output arguments"); 28 | 29 | m = mxGetM(prhs[0]); /* get the dimensions of the input */ 30 | n = mxGetN(prhs[0]); 31 | /* make sure input input vectors are same length */ 32 | if (m != mxGetM(prhs[1]) ) 33 | mexErrMsgTxt("alpha and beta must have the same size"); 34 | /* make sure input is m x 1 */ 35 | if ( n != 1 || mxGetN(prhs[1]) != 1 || n != mxGetN(prhs[1])) 36 | mexErrMsgTxt("alpha and beta must be a m x 1 vectors"); 37 | 38 | /* Create/allocate return arguments */ 39 | for (i=0; i<2; i++) { 40 | plhs[i]=mxCreateDoubleMatrix(m,1,mxREAL); 41 | } 42 | 43 | e = mxCalloc(m,sizeof(double)); 44 | wrk = mxCalloc(4*m-4,sizeof(double)); 45 | d = mxGetPr(plhs[0]); 46 | memcpy(d,mxGetPr(prhs[0]), m*sizeof(double)); 47 | memcpy(e,mxGetPr(prhs[1]), m*sizeof(double)); 48 | bnd = mxGetPr(plhs[1]); 49 | for (i=0; i 0) 63 | mexWarnMsgTxt("DBDSQR: singular values did not converge"); 64 | 65 | /* Free work arrays */ 66 | mxFree(e); 67 | mxFree(wrk); 68 | } 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /PROPACK/compute_int.m: -------------------------------------------------------------------------------- 1 | function int = compute_int(mu,j,delta,eta,LL,strategy,extra) 2 | %COMPUTE_INT: Determine which Lanczos vectors to reorthogonalize against. 3 | % 4 | % int = compute_int(mu,eta,LL,strategy,extra)) 5 | % 6 | % Strategy 0: Orthogonalize vectors v_{i-r-extra},...,v_{i},...v_{i+s+extra} 7 | % with nu>eta, where v_{i} are the vectors with mu>delta. 8 | % Strategy 1: Orthogonalize all vectors v_{r-extra},...,v_{s+extra} where 9 | % v_{r} is the first and v_{s} the last Lanczos vector with 10 | % mu > eta. 11 | % Strategy 2: Orthogonalize all vectors with mu > eta. 12 | % 13 | % Notice: The first LL vectors are excluded since the new Lanczos 14 | % vector is already orthogonalized against them in the main iteration. 15 | 16 | % Rasmus Munk Larsen, DAIMI, 1998. 17 | 18 | if (delta= ETA.') 20 | end 21 | switch strategy 22 | case 0 23 | I0 = find(abs(mu(1:j))>=delta); 24 | if length(I0)==0 25 | [mm,I0] = max(abs(mu(1:j))); 26 | end 27 | int = zeros(j,1); 28 | for i = 1:length(I0) 29 | for r=I0(i):-1:1 30 | if abs(mu(r))0 47 | int(1:LL) = 0; 48 | end 49 | int = find(int); 50 | case 1 51 | int=find(abs(mu(1:j))>eta); 52 | int = max(LL+1,min(int)-extra):min(max(int)+extra,j); 53 | case 2 54 | int=find(abs(mu(1:j))>=eta); 55 | end 56 | int = int(:); -------------------------------------------------------------------------------- /PROPACK/dbdqr.f: -------------------------------------------------------------------------------- 1 | 2 | subroutine dbdqr(n, D, E, c1, c2) 3 | implicit none 4 | integer n 5 | double precision D(*),E(*),c1,c2 6 | 7 | integer i 8 | double precision cs,sn,r 9 | 10 | if (n.lt.2) return 11 | do i=1,n-1 12 | call dlartg(d(i),e(i),cs,sn,r) 13 | d(i) = r 14 | e(i) = sn*d(i+1) 15 | d(i+1) = cs*d(i+1) 16 | enddo 17 | call dlartg(d(n),e(n),cs,sn,r) 18 | d(n) = r 19 | e(n) = 0.0 20 | c1 = sn 21 | c2 = cs 22 | end 23 | 24 | -------------------------------------------------------------------------------- /PROPACK/helio.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/helio.mat -------------------------------------------------------------------------------- /PROPACK/lanbpro.doc: -------------------------------------------------------------------------------- 1 | LANBPRO Lanczos bidiagonalization with partial reorthogonalization. 2 | 3 | LANBPRO computes the Lanczos bidiagonalization of a real 4 | matrix using the with partial reorthogonalization. 5 | 6 | [U_k,B_k,V_k,R,ierr,work] = LANBPRO(A,K,R0,OPTIONS,U_old,B_old,V_old) 7 | [U_k,B_k,V_k,R,ierr,work] = LANBPRO('Afun','Atransfun',M,N,K,R0, ... 8 | OPTIONS,U_old,B_old,V_old) 9 | 10 | Computes K steps of the Lanczos bidiagonalization algorithm with partial 11 | reorthogonalization (BPRO) with M-by-1 starting vector R0, producing a 12 | lower bidiagonal K-by-K matrix B_k, an N-by-K matrix V_k, an M-by-K 13 | matrix U_k and a M-by-1 vector such that 14 | A*V_k = U_k*B_k + R 15 | Partial reorthogonalization is used to keep the columns of V_K and U_k 16 | semiorthogonal: 17 | MAX(DIAG((EYE(K) - V_K'*V_K))) <= OPTIONS.delta 18 | and 19 | MAX(DIAG((EYE(K) - U_K'*U_K))) <= OPTIONS.delta. 20 | 21 | B_k = LANBPRO(...) returns the bidiagonal matrix only. 22 | 23 | The first input argument is either a real matrix, or a string 24 | containing the name of an M-file which applies a linear operator 25 | to the columns of a given matrix. In the latter case, the second 26 | input must be the name of an M-file which applies the transpose of 27 | the same linear operator to the columns of a given matrix, 28 | and the third and fourth arguments must be M and N, the dimensions 29 | of then problem. 30 | 31 | The OPTIONS structure is used to control the reorthogonalization: 32 | OPTIONS.delta: Desired level of orthogonality 33 | (default = sqrt(eps/K)). 34 | OPTIONS.eta : Level of orthogonality after reorthogonalization 35 | (default = eps^(3/4)/sqrt(K)). 36 | OPTIONS.cgs : Flag for switching between different reorthogonalization 37 | algorithms: 38 | 0 = iterated modified Gram-Schmidt (default) 39 | 1 = iterated classical Gram-Schmidt 40 | OPTIONS.elr : If OPTIONS.elr = 1 (default) then extended local 41 | reorthogonalization is enforced. 42 | OPTIONS.onesided 43 | : If OPTIONS.onesided = 0 (default) then both the left 44 | (U) and right (V) Lanczos vectors are kept 45 | semiorthogonal. 46 | OPTIONS.onesided = 1 then only the columns of U are 47 | are reorthogonalized. 48 | OPTIONS.onesided = -1 then only the columns of V are 49 | are reorthogonalized. 50 | OPTIONS.waitbar 51 | : The progress of the algorithm is display graphically. 52 | 53 | If both R0, U_old, B_old, and V_old are provided, they must 54 | contain a partial Lanczos bidiagonalization of A on the form 55 | 56 | A V_old = U_old B_old + R0 . 57 | 58 | In this case the factorization is extended to dimension K x K by 59 | continuing the Lanczos bidiagonalization algorithm with R0 as a 60 | starting vector. 61 | 62 | The output array work contains information about the work used in 63 | reorthogonalizing the u- and v-vectors. 64 | work = [ RU PU ] 65 | [ RV PV ] 66 | where 67 | RU = Number of reorthogonalizations of U. 68 | PU = Number of inner products used in reorthogonalizing U. 69 | RV = Number of reorthogonalizations of V. 70 | PV = Number of inner products used in reorthogonalizing V. 71 | 72 | References: 73 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 74 | 75 | G. H. Golub & C. F. Van Loan, "Matrix Computations", 76 | 3. Ed., Johns Hopkins, 1996. Section 9.3.4. 77 | 78 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 79 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 80 | 81 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 82 | Math. Comp. 42 (1984), no. 165, 115--142. 83 | 84 | 85 | Rasmus Munk Larsen, DAIMI, 1998. 86 | -------------------------------------------------------------------------------- /PROPACK/lanbpro.txt: -------------------------------------------------------------------------------- 1 | LANBPRO Lanczos bidiagonalization with partial reorthogonalization. 2 | 3 | LANBPRO computes the Lanczos bidiagonalization of a real 4 | matrix using the with partial reorthogonalization. 5 | 6 | [U_k,B_k,V_k,R,ierr,work] = LANBPRO(A,K,R0,OPTIONS,U_old,B_old,V_old) 7 | [U_k,B_k,V_k,R,ierr,work] = LANBPRO('Afun','Atransfun',M,N,K,R0, ... 8 | OPTIONS,U_old,B_old,V_old) 9 | 10 | Computes K steps of the Lanczos bidiagonalization algorithm with partial 11 | reorthogonalization (BPRO) with M-by-1 starting vector R0, producing a 12 | lower bidiagonal K-by-K matrix B_k, an N-by-K matrix V_k, an M-by-K 13 | matrix U_k and a M-by-1 vector such that 14 | A*V_k = U_k*B_k + R 15 | Partial reorthogonalization is used to keep the columns of V_K and U_k 16 | semiorthogonal: 17 | MAX(DIAG((EYE(K) - V_K'*V_K))) <= OPTIONS.delta 18 | and 19 | MAX(DIAG((EYE(K) - U_K'*U_K))) <= OPTIONS.delta. 20 | 21 | B_k = LANBPRO(...) returns the bidiagonal matrix only. 22 | 23 | The first input argument is either a real matrix, or a string 24 | containing the name of an M-file which applies a linear operator 25 | to the columns of a given matrix. In the latter case, the second 26 | input must be the name of an M-file which applies the transpose of 27 | the same linear operator to the columns of a given matrix, 28 | and the third and fourth arguments must be M and N, the dimensions 29 | of then problem. 30 | 31 | The OPTIONS structure is used to control the reorthogonalization: 32 | OPTIONS.delta: Desired level of orthogonality 33 | (default = sqrt(eps/K)). 34 | OPTIONS.eta : Level of orthogonality after reorthogonalization 35 | (default = eps^(3/4)/sqrt(K)). 36 | OPTIONS.cgs : Flag for switching between different reorthogonalization 37 | algorithms: 38 | 0 = iterated modified Gram-Schmidt (default) 39 | 1 = iterated classical Gram-Schmidt 40 | OPTIONS.elr : If OPTIONS.elr = 1 (default) then extended local 41 | reorthogonalization is enforced. 42 | OPTIONS.onesided 43 | : If OPTIONS.onesided = 0 (default) then both the left 44 | (U) and right (V) Lanczos vectors are kept 45 | semiorthogonal. 46 | OPTIONS.onesided = 1 then only the columns of U are 47 | are reorthogonalized. 48 | OPTIONS.onesided = -1 then only the columns of V are 49 | are reorthogonalized. 50 | OPTIONS.waitbar 51 | : The progress of the algorithm is display graphically. 52 | 53 | If both R0, U_old, B_old, and V_old are provided, they must 54 | contain a partial Lanczos bidiagonalization of A on the form 55 | 56 | A V_old = U_old B_old + R0 . 57 | 58 | In this case the factorization is extended to dimension K x K by 59 | continuing the Lanczos bidiagonalization algorithm with R0 as a 60 | starting vector. 61 | 62 | The output array work contains information about the work used in 63 | reorthogonalizing the u- and v-vectors. 64 | work = [ RU PU ] 65 | [ RV PV ] 66 | where 67 | RU = Number of reorthogonalizations of U. 68 | PU = Number of inner products used in reorthogonalizing U. 69 | RV = Number of reorthogonalizations of V. 70 | PV = Number of inner products used in reorthogonalizing V. 71 | 72 | References: 73 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 74 | 75 | G. H. Golub & C. F. Van Loan, "Matrix Computations", 76 | 3. Ed., Johns Hopkins, 1996. Section 9.3.4. 77 | 78 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 79 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 80 | 81 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 82 | Math. Comp. 42 (1984), no. 165, 115--142. 83 | 84 | 85 | Rasmus Munk Larsen, DAIMI, 1998. 86 | -------------------------------------------------------------------------------- /PROPACK/laneig.doc: -------------------------------------------------------------------------------- 1 | LANEIG Compute a few eigenvalues and eigenvectors. 2 | LANEIG solves the eigenvalue problem A*v=lambda*v, when A is 3 | real and symmetric using the Lanczos algorithm with partial 4 | reorthogonalization (PRO). 5 | 6 | [V,D] = LANEIG(A) 7 | [V,D] = LANEIG('Afun',N) 8 | 9 | The first input argument is either a real symmetric matrix, or a 10 | string containing the name of an M-file which applies a linear 11 | operator to the columns of a given matrix. In the latter case, 12 | the second input argument must be N, the order of the problem. 13 | 14 | The full calling sequence is 15 | 16 | [V,D,ERR] = LANEIG(A,K,SIGMA,OPTIONS) 17 | [V,D,ERR] = LANEIG('Afun',N,K,SIGMA,OPTIONS) 18 | 19 | On exit ERR contains the computed error bounds. K is the number of 20 | eigenvalues desired and SIGMA is numerical shift or a two letter string 21 | which specifies which part of the spectrum should be computed: 22 | 23 | SIGMA Specified eigenvalues 24 | 25 | 'AL' Algebraically Largest 26 | 'AS' Algebraically Smallest 27 | 'LM' Largest Magnitude (default) 28 | 'SM' Smallest Magnitude (does not work when A is an m-file) 29 | 'BE' Both Ends. Computes k/2 eigenvalues 30 | from each end of the spectrum (one more 31 | from the high end if k is odd.) 32 | 33 | The OPTIONS structure specifies certain parameters in the algorithm. 34 | 35 | Field name Parameter Default 36 | 37 | OPTIONS.tol Convergence tolerance 16*eps 38 | OPTIONS.lanmax Dimension of the Lanczos basis. 39 | OPTIONS.v0 Starting vector for the Lanczos rand(n,1)-0.5 40 | iteration. 41 | OPTIONS.delta Level of orthogonality among the sqrt(eps/K) 42 | Lanczos vectors. 43 | OPTIONS.eta Level of orthogonality after 10*eps^(3/4) 44 | reorthogonalization. 45 | OPTIONS.cgs reorthogonalization method used 0 46 | '0' : iterated modified Gram-Schmidt 47 | '1' : iterated classical Gram-Schmidt 48 | OPTIONS.elr If equal to 1 then extended local 1 49 | reorthogonalization is enforced. 50 | 51 | See also LANPRO, EIGS, EIG. 52 | 53 | References: 54 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 55 | 56 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 57 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 58 | 59 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 60 | Math. Comp. 42 (1984), no. 165, 115--142. 61 | 62 | Rasmus Munk Larsen, DAIMI, 1998 63 | -------------------------------------------------------------------------------- /PROPACK/laneig.txt: -------------------------------------------------------------------------------- 1 | LANEIG Compute a few eigenvalues and eigenvectors. 2 | LANEIG solves the eigenvalue problem A*v=lambda*v, when A is 3 | real and symmetric using the Lanczos algorithm with partial 4 | reorthogonalization (PRO). 5 | 6 | [V,D] = LANEIG(A) 7 | [V,D] = LANEIG('Afun',N) 8 | 9 | The first input argument is either a real symmetric matrix, or a 10 | string containing the name of an M-file which applies a linear 11 | operator to the columns of a given matrix. In the latter case, 12 | the second input argument must be N, the order of the problem. 13 | 14 | The full calling sequence is 15 | 16 | [V,D,ERR] = LANEIG(A,K,SIGMA,OPTIONS) 17 | [V,D,ERR] = LANEIG('Afun',N,K,SIGMA,OPTIONS) 18 | 19 | On exit ERR contains the computed error bounds. K is the number of 20 | eigenvalues desired and SIGMA is numerical shift or a two letter string 21 | which specifies which part of the spectrum should be computed: 22 | 23 | SIGMA Specified eigenvalues 24 | 25 | 'AL' Algebraically Largest 26 | 'AS' Algebraically Smallest 27 | 'LM' Largest Magnitude (default) 28 | 'SM' Smallest Magnitude (does not work when A is an m-file) 29 | 'BE' Both Ends. Computes k/2 eigenvalues 30 | from each end of the spectrum (one more 31 | from the high end if k is odd.) 32 | 33 | The OPTIONS structure specifies certain parameters in the algorithm. 34 | 35 | Field name Parameter Default 36 | 37 | OPTIONS.tol Convergence tolerance 16*eps 38 | OPTIONS.lanmax Dimension of the Lanczos basis. 39 | OPTIONS.v0 Starting vector for the Lanczos rand(n,1)-0.5 40 | iteration. 41 | OPTIONS.delta Level of orthogonality among the sqrt(eps/K) 42 | Lanczos vectors. 43 | OPTIONS.eta Level of orthogonality after 10*eps^(3/4) 44 | reorthogonalization. 45 | OPTIONS.cgs reorthogonalization method used 0 46 | '0' : iterated modified Gram-Schmidt 47 | '1' : iterated classical Gram-Schmidt 48 | OPTIONS.elr If equal to 1 then extended local 1 49 | reorthogonalization is enforced. 50 | 51 | See also LANPRO, EIGS, EIG. 52 | 53 | References: 54 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 55 | 56 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 57 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 58 | 59 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 60 | Math. Comp. 42 (1984), no. 165, 115--142. 61 | 62 | Rasmus Munk Larsen, DAIMI, 1998 63 | -------------------------------------------------------------------------------- /PROPACK/lanpro.doc: -------------------------------------------------------------------------------- 1 | LANPRO Lanczos tridiagonalization with partial reorthogonalization 2 | LANPRO computes the Lanczos tridiagonalization of a real symmetric 3 | matrix using the symmetric Lanczos algorithm with partial 4 | reorthogonalization. 5 | 6 | [Q_K,T_K,R,ANORM,IERR,WORK] = LANPRO(A,K,R0,OPTIONS,Q_old,T_old) 7 | [Q_K,T_K,R,ANORM,IERR,WORK] = LANPRO('Afun',N,K,R0,OPTIONS,Q_old,T_old) 8 | 9 | Computes K steps of the Lanczos algorithm with starting vector R0, 10 | and returns the K x K tridiagonal T_K, the N x K matrix Q_K 11 | with semiorthonormal columns and the residual vector R such that 12 | 13 | A*Q_K = Q_K*T_K + R . 14 | 15 | Partial reorthogonalization is used to keep the columns of Q_K 16 | semiorthogonal: 17 | MAX(DIAG((eye(k) - Q_K'*Q_K))) <= OPTIONS.delta. 18 | 19 | 20 | The first input argument is either a real symmetric matrix, a struct with 21 | components A.L and A.U or a string containing the name of an M-file which 22 | applies a linear operator to the columns of a given matrix. In the latter 23 | case, the second input argument must be N, the order of the problem. 24 | 25 | If A is a struct with components A.L and A.U, such that 26 | L*U = (A - sigma*I), a shift-and-invert Lanczos iteration is performed 27 | 28 | The OPTIONS structure is used to control the reorthogonalization: 29 | OPTIONS.delta: Desired level of orthogonality 30 | (default = sqrt(eps/K)). 31 | OPTIONS.eta : Level of orthogonality after reorthogonalization 32 | (default = eps^(3/4)/sqrt(K)). 33 | OPTIONS.cgs : Flag for switching between different reorthogonalization 34 | algorithms: 35 | 0 = iterated modified Gram-Schmidt (default) 36 | 1 = iterated classical Gram-Schmidt 37 | OPTIONS.elr : If OPTIONS.elr = 1 (default) then extended local 38 | reorthogonalization is enforced. 39 | OPTIONS.Y : The lanczos vectors are reorthogonalized against 40 | the columns of the matrix OPTIONS.Y. 41 | 42 | If both R0, Q_old and T_old are provided, they must contain 43 | a partial Lanczos tridiagonalization of A on the form 44 | 45 | A Q_old = Q_old T_old + R0 . 46 | 47 | In this case the factorization is extended to dimension K x K by 48 | continuing the Lanczos algorithm with R0 as starting vector. 49 | 50 | On exit ANORM contains an approximation to ||A||_2. 51 | IERR = 0 : K steps were performed succesfully. 52 | IERR > 0 : K steps were performed succesfully, but the algorithm 53 | switched to full reorthogonalization after IERR steps. 54 | IERR < 0 : Iteration was terminated after -IERR steps because an 55 | invariant subspace was found, and 3 deflation attempts 56 | were unsuccessful. 57 | On exit WORK(1) contains the number of reorthogonalizations performed, and 58 | WORK(2) contains the number of inner products performed in the 59 | reorthogonalizations. 60 | 61 | See also LANEIG, REORTH, COMPUTE_INT 62 | 63 | References: 64 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 65 | 66 | G. H. Golub & C. F. Van Loan, "Matrix Computations", 67 | 3. Ed., Johns Hopkins, 1996. Chapter 9. 68 | 69 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 70 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 71 | 72 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 73 | Math. Comp. 42 (1984), no. 165, 115--142. 74 | 75 | Rasmus Munk Larsen, DAIMI, 1998 76 | -------------------------------------------------------------------------------- /PROPACK/lanpro.txt: -------------------------------------------------------------------------------- 1 | LANPRO Lanczos tridiagonalization with partial reorthogonalization 2 | LANPRO computes the Lanczos tridiagonalization of a real symmetric 3 | matrix using the symmetric Lanczos algorithm with partial 4 | reorthogonalization. 5 | 6 | [Q_K,T_K,R,ANORM,IERR,WORK] = LANPRO(A,K,R0,OPTIONS,Q_old,T_old) 7 | [Q_K,T_K,R,ANORM,IERR,WORK] = LANPRO('Afun',N,K,R0,OPTIONS,Q_old,T_old) 8 | 9 | Computes K steps of the Lanczos algorithm with starting vector R0, 10 | and returns the K x K tridiagonal T_K, the N x K matrix Q_K 11 | with semiorthonormal columns and the residual vector R such that 12 | 13 | A*Q_K = Q_K*T_K + R . 14 | 15 | Partial reorthogonalization is used to keep the columns of Q_K 16 | semiorthogonal: 17 | MAX(DIAG((eye(k) - Q_K'*Q_K))) <= OPTIONS.delta. 18 | 19 | 20 | The first input argument is either a real symmetric matrix, a struct with 21 | components A.L and A.U or a string containing the name of an M-file which 22 | applies a linear operator to the columns of a given matrix. In the latter 23 | case, the second input argument must be N, the order of the problem. 24 | 25 | If A is a struct with components A.L and A.U, such that 26 | L*U = (A - sigma*I), a shift-and-invert Lanczos iteration is performed 27 | 28 | The OPTIONS structure is used to control the reorthogonalization: 29 | OPTIONS.delta: Desired level of orthogonality 30 | (default = sqrt(eps/K)). 31 | OPTIONS.eta : Level of orthogonality after reorthogonalization 32 | (default = eps^(3/4)/sqrt(K)). 33 | OPTIONS.cgs : Flag for switching between different reorthogonalization 34 | algorithms: 35 | 0 = iterated modified Gram-Schmidt (default) 36 | 1 = iterated classical Gram-Schmidt 37 | OPTIONS.elr : If OPTIONS.elr = 1 (default) then extended local 38 | reorthogonalization is enforced. 39 | OPTIONS.Y : The lanczos vectors are reorthogonalized against 40 | the columns of the matrix OPTIONS.Y. 41 | 42 | If both R0, Q_old and T_old are provided, they must contain 43 | a partial Lanczos tridiagonalization of A on the form 44 | 45 | A Q_old = Q_old T_old + R0 . 46 | 47 | In this case the factorization is extended to dimension K x K by 48 | continuing the Lanczos algorithm with R0 as starting vector. 49 | 50 | On exit ANORM contains an approximation to ||A||_2. 51 | IERR = 0 : K steps were performed succesfully. 52 | IERR > 0 : K steps were performed succesfully, but the algorithm 53 | switched to full reorthogonalization after IERR steps. 54 | IERR < 0 : Iteration was terminated after -IERR steps because an 55 | invariant subspace was found, and 3 deflation attempts 56 | were unsuccessful. 57 | On exit WORK(1) contains the number of reorthogonalizations performed, and 58 | WORK(2) contains the number of inner products performed in the 59 | reorthogonalizations. 60 | 61 | See also LANEIG, REORTH, COMPUTE_INT 62 | 63 | References: 64 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 65 | 66 | G. H. Golub & C. F. Van Loan, "Matrix Computations", 67 | 3. Ed., Johns Hopkins, 1996. Chapter 9. 68 | 69 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 70 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 71 | 72 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 73 | Math. Comp. 42 (1984), no. 165, 115--142. 74 | 75 | Rasmus Munk Larsen, DAIMI, 1998 76 | -------------------------------------------------------------------------------- /PROPACK/lansvd.doc: -------------------------------------------------------------------------------- 1 | LANSVD Compute a few singular values and singular vectors. 2 | LANSVD computes singular triplets (u,v,sigma) such that 3 | A*u = sigma*v and A'*v = sigma*u. Only a few singular values 4 | and singular vectors are computed using the Lanczos 5 | bidiagonalization algorithm with partial reorthogonalization (BPRO). 6 | 7 | S = LANSVD(A) 8 | S = LANSVD('Afun','Atransfun',M,N) 9 | 10 | The first input argument is either a matrix or a 11 | string containing the name of an M-file which applies a linear 12 | operator to the columns of a given matrix. In the latter case, 13 | the second input must be the name of an M-file which applies the 14 | transpose of the same operator to the columns of a given matrix, 15 | and the third and fourth arguments must be M and N, the dimensions 16 | of the problem. 17 | 18 | [U,S,V] = LANSVD(A,K,'L',...) computes the K largest singular values. 19 | 20 | [U,S,V] = LANSVD(A,K,'S',...) computes the K smallest singular values. 21 | 22 | The full calling sequence is 23 | 24 | [U,S,V] = LANSVD(A,K,SIGMA,OPTIONS) 25 | [U,S,V] = LANSVD('Afun','Atransfun',M,N,K,SIGMA,OPTIONS) 26 | 27 | where K is the number of singular values desired and 28 | SIGMA is 'L' or 'S'. 29 | 30 | The OPTIONS structure specifies certain parameters in the algorithm. 31 | Field name Parameter Default 32 | 33 | OPTIONS.tol Convergence tolerance 16*eps 34 | OPTIONS.lanmax Dimension of the Lanczos basis. 35 | OPTIONS.p0 Starting vector for the Lanczos rand(n,1)-0.5 36 | iteration. 37 | OPTIONS.delta Level of orthogonality among the sqrt(eps/K) 38 | Lanczos vectors. 39 | OPTIONS.eta Level of orthogonality after 10*eps^(3/4) 40 | reorthogonalization. 41 | OPTIONS.cgs reorthogonalization method used 0 42 | '0' : iterated modified Gram-Schmidt 43 | '1' : iterated classical Gram-Schmidt 44 | OPTIONS.elr If equal to 1 then extended local 1 45 | reorthogonalization is enforced. 46 | 47 | See also LANBPRO, SVDS, SVD 48 | 49 | References: 50 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 51 | 52 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 53 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 54 | 55 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 56 | Math. Comp. 42 (1984), no. 165, 115--142. 57 | 58 | Rasmus Munk Larsen, DAIMI, 1998 59 | -------------------------------------------------------------------------------- /PROPACK/lansvd.m: -------------------------------------------------------------------------------- 1 | function [U,S,V,bnd,j] = lansvd(varargin) 2 | 3 | %LANSVD Compute a few singular values and singular vectors. 4 | % LANSVD computes singular triplets (u,v,sigma) such that 5 | % A*u = sigma*v and A'*v = sigma*u. Only a few singular values 6 | % and singular vectors are computed using the Lanczos 7 | % bidiagonalization algorithm with partial reorthogonalization (BPRO). 8 | % 9 | % S = LANSVD(A) 10 | % S = LANSVD('Afun','Atransfun',M,N) 11 | % 12 | % The first input argument is either a matrix or a 13 | % string containing the name of an M-file which applies a linear 14 | % operator to the columns of a given matrix. In the latter case, 15 | % the second input must be the name of an M-file which applies the 16 | % transpose of the same operator to the columns of a given matrix, 17 | % and the third and fourth arguments must be M and N, the dimensions 18 | % of the problem. 19 | % 20 | % [U,S,V] = LANSVD(A,K,'L',...) computes the K largest singular values. 21 | % 22 | % [U,S,V] = LANSVD(A,K,'S',...) computes the K smallest singular values. 23 | % 24 | % The full calling sequence is 25 | % 26 | % [U,S,V] = LANSVD(A,K,SIGMA,OPTIONS) 27 | % [U,S,V] = LANSVD('Afun','Atransfun',M,N,K,SIGMA,OPTIONS) 28 | % 29 | % where K is the number of singular values desired and 30 | % SIGMA is 'L' or 'S'. 31 | % 32 | % The OPTIONS structure specifies certain parameters in the algorithm. 33 | % Field name Parameter Default 34 | % 35 | % OPTIONS.tol Convergence tolerance 16*eps 36 | % OPTIONS.lanmax Dimension of the Lanczos basis. 37 | % OPTIONS.p0 Starting vector for the Lanczos rand(n,1)-0.5 38 | % iteration. 39 | % OPTIONS.delta Level of orthogonality among the sqrt(eps/K) 40 | % Lanczos vectors. 41 | % OPTIONS.eta Level of orthogonality after 10*eps^(3/4) 42 | % reorthogonalization. 43 | % OPTIONS.cgs reorthogonalization method used 0 44 | % '0' : iterated modified Gram-Schmidt 45 | % '1' : iterated classical Gram-Schmidt 46 | % OPTIONS.elr If equal to 1 then extended local 1 47 | % reorthogonalization is enforced. 48 | % 49 | % See also LANBPRO, SVDS, SVD 50 | 51 | % References: 52 | % R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 53 | % 54 | % B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 55 | % Prentice-Hall, Englewood Cliffs, NJ, 1980. 56 | % 57 | % H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 58 | % Math. Comp. 42 (1984), no. 165, 115--142. 59 | 60 | % Rasmus Munk Larsen, DAIMI, 1998 61 | 62 | 63 | %%%%%%%%%%%%%%%%%%%%% Parse and check input arguments. %%%%%%%%%%%%%%%%%%%%%% 64 | 65 | if nargin<1 | length(varargin)<1 66 | error('Not enough input arguments.'); 67 | end 68 | 69 | A = varargin{1}; 70 | if ~isstr(A) 71 | if ~isreal(A) 72 | error('A must be real') 73 | end 74 | [m n] = size(A); 75 | if length(varargin) < 2, k=min(min(m,n),6); else k=varargin{2}; end 76 | if length(varargin) < 3, sigma = 'L'; else sigma=varargin{3}; end 77 | if length(varargin) < 4, options = []; else options=varargin{4}; end 78 | else 79 | if length(varargin)<4 80 | error('Not enough input arguments.'); 81 | end 82 | Atrans = varargin{2}; 83 | if ~isstr(Atrans) 84 | error('Atransfunc must be the name of a function') 85 | end 86 | m = varargin{3}; 87 | n = varargin{4}; 88 | if length(varargin) < 5, k=min(min(m,n),6); else k=varargin{5}; end 89 | if length(varargin) < 6, sigma = 'L'; else sigma=varargin{6}; end 90 | if length(varargin) < 7, options = []; else options=varargin{7}; end 91 | end 92 | 93 | if ~isnumeric(n) | real(abs(fix(n))) ~= n | ~isnumeric(m) | ... 94 | real(abs(fix(m))) ~= m | ~isnumeric(k) | real(abs(fix(k))) ~= k 95 | error('M, N and K must be positive integers.') 96 | end 97 | 98 | 99 | % Quick return for min(m,n) equal to 0 or 1 or for zero A. 100 | if min(n,m) < 1 | k<1 101 | if nargout<3 102 | U = zeros(k,1); 103 | else 104 | U = eye(m,k); S = zeros(k,k); V = eye(n,k); bnd = zeros(k,1); 105 | end 106 | return 107 | elseif min(n,m) == 1 & k>0 108 | if isstr(A) 109 | % Extract the single column or row of A 110 | if n==1 111 | A = feval(A,1); 112 | else 113 | A = feval(Atrans,1)'; 114 | end 115 | end 116 | if nargout==1 117 | U = norm(A); 118 | else 119 | [U,S,V] = svd(full(A)); 120 | bnd = 0; 121 | end 122 | return 123 | end 124 | 125 | % A is the matrix of all zeros (not detectable if A is defined by an m-file) 126 | if isnumeric(A) 127 | if nnz(A)==0 128 | if nargout<3 129 | U = zeros(k,1); 130 | else 131 | U = eye(m,k); S = zeros(k,k); V = eye(n,k); bnd = zeros(k,1); 132 | end 133 | return 134 | end 135 | end 136 | 137 | lanmax = min(m,n); 138 | tol = 16*eps; 139 | p = rand(m,1)-0.5; 140 | % Parse options struct 141 | if isstruct(options) 142 | c = fieldnames(options); 143 | for i=1:length(c) 144 | if any(strcmp(c(i),'p0')), p = getfield(options,'p0'); p=p(:); end 145 | if any(strcmp(c(i),'tol')), tol = getfield(options,'tol'); end 146 | if any(strcmp(c(i),'lanmax')), lanmax = getfield(options,'lanmax'); end 147 | end 148 | end 149 | 150 | % Protect against absurd options. 151 | tol = max(tol,eps); 152 | lanmax = min(lanmax,min(m,n)); 153 | if size(p,1)~=m 154 | error('p0 must be a vector of length m') 155 | end 156 | 157 | lanmax = min(lanmax,min(m,n)); 158 | if k>lanmax 159 | error('K must satisfy K <= LANMAX <= MIN(M,N).'); 160 | end 161 | 162 | 163 | 164 | %%%%%%%%%%%%%%%%%%%%% Here begins the computation %%%%%%%%%%%%%%%%%%%%%% 165 | 166 | if strcmp(sigma,'S') 167 | if isstr(A) 168 | error('Shift-and-invert works only when the matrix A is given explicitly.'); 169 | else 170 | % Prepare for shift-and-invert Lanczos. 171 | if issparse(A) 172 | pmmd = colmmd(A); 173 | A.A = A(:,pmmd); 174 | else 175 | A.A = A; 176 | end 177 | if m>=n 178 | if issparse(A.A) 179 | A.R = qr(A.A,0); 180 | A.Rt = A.R'; 181 | p = A.Rt\(A.A'*p); % project starting vector on span(Q1) 182 | else 183 | [A.Q,A.R] = qr(A.A,0); 184 | A.Rt = A.R'; 185 | p = A.Q'*p; % project starting vector on span(Q1) 186 | end 187 | else 188 | error('Sorry, shift-and-invert for m 1/eps 194 | error(['A is rank deficient or too ill-conditioned to do shift-and-' ... 195 | ' invert.']) 196 | end 197 | end 198 | end 199 | 200 | ksave = k; 201 | neig = 0; nrestart=-1; 202 | j = min(k+max(8,k)+1,lanmax); 203 | U = []; V = []; B = []; anorm = []; work = zeros(2,2); 204 | 205 | while neig < k 206 | 207 | %%%%%%%%%%%%%%%%%%%%% Compute Lanczos bidiagonalization %%%%%%%%%%%%%%%%% 208 | if ~isstr(A) 209 | [U,B,V,p,ierr,w] = lanbpro(A,j,p,options,U,B,V,anorm); 210 | else 211 | [U,B,V,p,ierr,w] = lanbpro(A,Atrans,m,n,j,p,options,U,B,V,anorm); 212 | end 213 | work= work + w; 214 | 215 | if ierr<0 % Invariant subspace of dimension -ierr found. 216 | j = -ierr; 217 | end 218 | 219 | %%%%%%%%%%%%%%%%%% Compute singular values and error bounds %%%%%%%%%%%%%%%% 220 | % Analyze B 221 | resnrm = norm(p); 222 | % We might as well use the extra info. in p. 223 | % S = svd(full([B;[zeros(1,j-1),resnrm]]),0); 224 | % [P,S,Q] = svd(full([B;[zeros(1,j-1),resnrm]]),0); 225 | % S = diag(S); 226 | % bot = min(abs([P(end,1:j);Q(end,1:j)]))'; 227 | 228 | [S,bot] = bdsqr(diag(B),[diag(B,-1); resnrm]); 229 | 230 | % Use Largest Ritz value to estimate ||A||_2. This might save some 231 | % reorth. in case of restart. 232 | anorm=S(1); 233 | 234 | % Set simple error bounds 235 | bnd = resnrm*abs(bot); 236 | 237 | % Examine gap structure and refine error bounds 238 | bnd = refinebounds(S.^2,bnd,n*eps*anorm); 239 | 240 | %%%%%%%%%%%%%%%%%%% Check convergence criterion %%%%%%%%%%%%%%%%%%%% 241 | i=1; 242 | neig = 0; 243 | while i<=min(j,k) 244 | if (bnd(i) <= tol*abs(S(i))) 245 | neig = neig + 1; 246 | i = i+1; 247 | else 248 | i = min(j,k)+1; 249 | end 250 | end 251 | 252 | %%%%%%%%%% Check whether to stop or to extend the Krylov basis? %%%%%%%%%% 253 | if ierr<0 % Invariant subspace found 254 | if j=lanmax % Maximal dimension of Krylov subspace reached. Bail out 261 | if j>=min(m,n) 262 | neig = ksave; 263 | break; 264 | end 265 | if neig0 274 | % increase j by approx. half the average number of steps pr. converged 275 | % singular value (j/neig) times the number of remaining ones (k-neig). 276 | j = j + min(100,max(2,0.5*(k-neig)*j/(neig+1))); 277 | else 278 | % As long a very few singular values have converged, increase j rapidly. 279 | % j = j + ceil(min(100,max(8,2^nrestart*k))); 280 | j = max(1.5*j,j+10); 281 | end 282 | j = ceil(min(j+1,lanmax)); 283 | nrestart = nrestart + 1; 284 | end 285 | 286 | 287 | 288 | %%%%%%%%%%%%%%%% Lanczos converged (or failed). Prepare output %%%%%%%%%%%%%%% 289 | k = min(ksave,j); 290 | 291 | if nargout>2 292 | j = size(B,2); 293 | % Compute singular vectors 294 | [P,S,Q] = svd(full([B;[zeros(1,j-1),resnrm]]),0); 295 | S = diag(S); 296 | if size(Q,2)~=k 297 | Q = Q(:,1:k); 298 | P = P(:,1:k); 299 | end 300 | % Compute and normalize Ritz vectors (overwrites U and V to save memory). 301 | if resnrm~=0 302 | U = U*P(1:j,:) + (p/resnrm)*P(j+1,:); 303 | else 304 | U = U*P(1:j,:); 305 | end 306 | V = V*Q; 307 | for i=1:k 308 | nq = norm(V(:,i)); 309 | if isfinite(nq) & nq~=0 & nq~=1 310 | V(:,i) = V(:,i)/nq; 311 | end 312 | nq = norm(U(:,i)); 313 | if isfinite(nq) & nq~=0 & nq~=1 314 | U(:,i) = U(:,i)/nq; 315 | end 316 | end 317 | end 318 | 319 | % Pick out desired part the spectrum 320 | S = S(1:k); 321 | bnd = bnd(1:k); 322 | 323 | if strcmp(sigma,'S') 324 | [S,p] = sort(-1./S); 325 | S = -S; 326 | bnd = bnd(p); 327 | if nargout>2 328 | if issparse(A.A) 329 | U = A.A*(A.R\U(:,p)); 330 | V(pmmd,:) = V(:,p); 331 | else 332 | U = A.Q(:,1:min(m,n))*U(:,p); 333 | V = V(:,p); 334 | end 335 | end 336 | end 337 | 338 | if nargout<3 339 | U = S; 340 | S = B; % Undocumented feature - for checking B. 341 | else 342 | S = diag(S); 343 | end 344 | -------------------------------------------------------------------------------- /PROPACK/lansvd.txt: -------------------------------------------------------------------------------- 1 | LANSVD Compute a few singular values and singular vectors. 2 | LANSVD computes singular triplets (u,v,sigma) such that 3 | A*u = sigma*v and A'*v = sigma*u. Only a few singular values 4 | and singular vectors are computed using the Lanczos 5 | bidiagonalization algorithm with partial reorthogonalization (BPRO). 6 | 7 | S = LANSVD(A) 8 | S = LANSVD('Afun','Atransfun',M,N) 9 | 10 | The first input argument is either a matrix or a 11 | string containing the name of an M-file which applies a linear 12 | operator to the columns of a given matrix. In the latter case, 13 | the second input must be the name of an M-file which applies the 14 | transpose of the same operator to the columns of a given matrix, 15 | and the third and fourth arguments must be M and N, the dimensions 16 | of the problem. 17 | 18 | [U,S,V] = LANSVD(A,K,'L',...) computes the K largest singular values. 19 | 20 | [U,S,V] = LANSVD(A,K,'S',...) computes the K smallest singular values. 21 | 22 | The full calling sequence is 23 | 24 | [U,S,V] = LANSVD(A,K,SIGMA,OPTIONS) 25 | [U,S,V] = LANSVD('Afun','Atransfun',M,N,K,SIGMA,OPTIONS) 26 | 27 | where K is the number of singular values desired and 28 | SIGMA is 'L' or 'S'. 29 | 30 | The OPTIONS structure specifies certain parameters in the algorithm. 31 | Field name Parameter Default 32 | 33 | OPTIONS.tol Convergence tolerance 16*eps 34 | OPTIONS.lanmax Dimension of the Lanczos basis. 35 | OPTIONS.p0 Starting vector for the Lanczos rand(n,1)-0.5 36 | iteration. 37 | OPTIONS.delta Level of orthogonality among the sqrt(eps/K) 38 | Lanczos vectors. 39 | OPTIONS.eta Level of orthogonality after 10*eps^(3/4) 40 | reorthogonalization. 41 | OPTIONS.cgs reorthogonalization method used 0 42 | '0' : iterated modified Gram-Schmidt 43 | '1' : iterated classical Gram-Schmidt 44 | OPTIONS.elr If equal to 1 then extended local 1 45 | reorthogonalization is enforced. 46 | 47 | See also LANBPRO, SVDS, SVD 48 | 49 | References: 50 | R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 51 | 52 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 53 | Prentice-Hall, Englewood Cliffs, NJ, 1980. 54 | 55 | H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 56 | Math. Comp. 42 (1984), no. 165, 115--142. 57 | 58 | Rasmus Munk Larsen, DAIMI, 1998 59 | -------------------------------------------------------------------------------- /PROPACK/mminfo.m: -------------------------------------------------------------------------------- 1 | function [rows, cols, entries, rep, field, symm] = mminfo(filename) 2 | % 3 | % function [rows, cols, entries, rep, field, symmetry] = mminfo(filename) 4 | % 5 | % Reads the contents of the Matrix Market file 'filename' 6 | % and extracts size and storage information. 7 | % 8 | % In the case of coordinate matrices, entries refers to the 9 | % number of coordinate entries stored in the file. The number 10 | % of non-zero entries in the final matrix cannot be determined 11 | % until the data is read (and symmetrized, if necessary). 12 | % 13 | % In the case of array matrices, entries is the product 14 | % rows*cols, regardless of whether symmetry was used to 15 | % store the matrix efficiently. 16 | % 17 | % 18 | 19 | mmfile = fopen(filename,'r'); 20 | if ( mmfile == -1 ) 21 | disp(filename); 22 | error('File not found'); 23 | end; 24 | 25 | header = fgets(mmfile); 26 | if (header == -1 ) 27 | error('Empty file.') 28 | end 29 | 30 | % NOTE: If using a version of Matlab for which strtok is not 31 | % defined, substitute 'gettok' for 'strtok' in the 32 | % following lines, and download gettok.m from the 33 | % Matrix Market site. 34 | [head0,header] = strtok(header); % see note above 35 | [head1,header] = strtok(header); 36 | [rep,header] = strtok(header); 37 | [field,header] = strtok(header); 38 | [symm,header] = strtok(header); 39 | head1 = lower(head1); 40 | rep = lower(rep); 41 | field = lower(field); 42 | symm = lower(symm); 43 | if ( length(symm) == 0 ) 44 | disp('Not enough words in header line.') 45 | disp('Recognized format: ') 46 | disp('%%MatrixMarket matrix representation field symmetry') 47 | error('Check header line.') 48 | end 49 | if ( ~ strcmp(head0,'%%MatrixMarket') ) 50 | error('Not a valid MatrixMarket header.') 51 | end 52 | if ( ~ strcmp(head1,'matrix') ) 53 | disp(['This seems to be a MatrixMarket ',head1,' file.']); 54 | disp('This function only knows how to read MatrixMarket matrix files.'); 55 | disp(' '); 56 | error(' '); 57 | end 58 | 59 | % Read through comments, ignoring them 60 | 61 | commentline = fgets(mmfile); 62 | while length(commentline) > 0 & commentline(1) == '%', 63 | commentline = fgets(mmfile); 64 | end 65 | 66 | % Read size information, then branch according to 67 | % sparse or dense format 68 | 69 | if ( strcmp(rep,'coordinate')) % read matrix given in sparse 70 | % coordinate matrix format 71 | 72 | [sizeinfo,count] = sscanf(commentline,'%d%d%d'); 73 | while ( count == 0 ) 74 | commentline = fgets(mmfile); 75 | if (commentline == -1 ) 76 | error('End-of-file reached before size information was found.') 77 | end 78 | [sizeinfo,count] = sscanf(commentline,'%d%d%d'); 79 | if ( count > 0 & count ~= 3 ) 80 | error('Invalid size specification line.') 81 | end 82 | end 83 | rows = sizeinfo(1); 84 | cols = sizeinfo(2); 85 | entries = sizeinfo(3); 86 | 87 | elseif ( strcmp(rep,'array') ) % read matrix given in dense 88 | % array (column major) format 89 | 90 | [sizeinfo,count] = sscanf(commentline,'%d%d'); 91 | while ( count == 0 ) 92 | commentline = fgets(mmfile); 93 | if (commentline == -1 ) 94 | error('End-of-file reached before size information was found.') 95 | end 96 | [sizeinfo,count] = sscanf(commentline,'%d%d'); 97 | if ( count > 0 & count ~= 2 ) 98 | error('Invalid size specification line.') 99 | end 100 | end 101 | rows = sizeinfo(1); 102 | cols = sizeinfo(2); 103 | entries = rows*cols; 104 | end 105 | 106 | fclose(mmfile); 107 | % Done. 108 | 109 | -------------------------------------------------------------------------------- /PROPACK/mmread.m: -------------------------------------------------------------------------------- 1 | function [A,rows,cols,entries,rep,field,symm] = mmread(filename) 2 | % 3 | % function [A] = mmread(filename) 4 | % 5 | % function [A,rows,cols,entries,rep,field,symm] = mmread(filename) 6 | % 7 | % Reads the contents of the Matrix Market file 'filename' 8 | % into the matrix 'A'. 'A' will be either sparse or full, 9 | % depending on the Matrix Market format indicated by 10 | % 'coordinate' (coordinate sparse storage), or 11 | % 'array' (dense array storage). The data will be duplicated 12 | % as appropriate if symmetry is indicated in the header. 13 | % 14 | % Optionally, size information about the matrix can be 15 | % obtained by using the return values rows, cols, and 16 | % entries, where entries is the number of nonzero entries 17 | % in the final matrix. Type information can also be retrieved 18 | % using the optional return values rep (representation), field, 19 | % and symm (symmetry). 20 | % 21 | 22 | mmfile = fopen(filename,'r'); 23 | if ( mmfile == -1 ) 24 | disp(filename); 25 | error('File not found'); 26 | end; 27 | 28 | header = fgets(mmfile); 29 | if (header == -1 ) 30 | error('Empty file.') 31 | end 32 | 33 | % NOTE: If using a version of Matlab for which strtok is not 34 | % defined, substitute 'gettok' for 'strtok' in the 35 | % following lines, and download gettok.m from the 36 | % Matrix Market site. 37 | [head0,header] = strtok(header); % see note above 38 | [head1,header] = strtok(header); 39 | [rep,header] = strtok(header); 40 | [field,header] = strtok(header); 41 | [symm,header] = strtok(header); 42 | head1 = lower(head1); 43 | rep = lower(rep); 44 | field = lower(field); 45 | symm = lower(symm); 46 | if ( length(symm) == 0 ) 47 | disp(['Not enough words in header line of file ',filename]) 48 | disp('Recognized format: ') 49 | disp('%%MatrixMarket matrix representation field symmetry') 50 | error('Check header line.') 51 | end 52 | if ( ~ strcmp(head0,'%%MatrixMarket') ) 53 | error('Not a valid MatrixMarket header.') 54 | end 55 | if ( ~ strcmp(head1,'matrix') ) 56 | disp(['This seems to be a MatrixMarket ',head1,' file.']); 57 | disp('This function only knows how to read MatrixMarket matrix files.'); 58 | disp(' '); 59 | error(' '); 60 | end 61 | 62 | % Read through comments, ignoring them 63 | 64 | commentline = fgets(mmfile); 65 | while length(commentline) > 0 & commentline(1) == '%', 66 | commentline = fgets(mmfile); 67 | end 68 | 69 | % Read size information, then branch according to 70 | % sparse or dense format 71 | 72 | if ( strcmp(rep,'coordinate')) % read matrix given in sparse 73 | % coordinate matrix format 74 | 75 | [sizeinfo,count] = sscanf(commentline,'%d%d%d'); 76 | while ( count == 0 ) 77 | commentline = fgets(mmfile); 78 | if (commentline == -1 ) 79 | error('End-of-file reached before size information was found.') 80 | end 81 | [sizeinfo,count] = sscanf(commentline,'%d%d%d'); 82 | if ( count > 0 & count ~= 3 ) 83 | error('Invalid size specification line.') 84 | end 85 | end 86 | rows = sizeinfo(1); 87 | cols = sizeinfo(2); 88 | entries = sizeinfo(3); 89 | 90 | if ( strcmp(field,'real') ) % real valued entries: 91 | 92 | [T,count] = fscanf(mmfile,'%f',3); 93 | T = [T; fscanf(mmfile,'%f')]; 94 | if ( size(T) ~= 3*entries ) 95 | message = ... 96 | str2mat('Data file does not contain expected amount of data.',... 97 | 'Check that number of data lines matches nonzero count.'); 98 | disp(message); 99 | error('Invalid data.'); 100 | end 101 | T = reshape(T,3,entries)'; 102 | A = sparse(T(:,1), T(:,2), T(:,3), rows , cols); 103 | 104 | elseif ( strcmp(field,'complex')) % complex valued entries: 105 | 106 | T = fscanf(mmfile,'%f',4); 107 | T = [T; fscanf(mmfile,'%f')]; 108 | if ( size(T) ~= 4*entries ) 109 | message = ... 110 | str2mat('Data file does not contain expected amount of data.',... 111 | 'Check that number of data lines matches nonzero count.'); 112 | disp(message); 113 | error('Invalid data.'); 114 | end 115 | T = reshape(T,4,entries)'; 116 | A = sparse(T(:,1), T(:,2), T(:,3) + T(:,4)*sqrt(-1), rows , cols); 117 | 118 | elseif ( strcmp(field,'pattern')) % pattern matrix (no values given): 119 | 120 | T = fscanf(mmfile,'%f',2); 121 | T = [T; fscanf(mmfile,'%f')]; 122 | if ( size(T) ~= 2*entries ) 123 | message = ... 124 | str2mat('Data file does not contain expected amount of data.',... 125 | 'Check that number of data lines matches nonzero count.'); 126 | disp(message); 127 | error('Invalid data.'); 128 | end 129 | T = reshape(T,2,entries)'; 130 | A = sparse(T(:,1), T(:,2), ones(entries,1) , rows , cols); 131 | 132 | end 133 | 134 | elseif ( strcmp(rep,'array') ) % read matrix given in dense 135 | % array (column major) format 136 | 137 | [sizeinfo,count] = sscanf(commentline,'%d%d'); 138 | while ( count == 0 ) 139 | commentline = fgets(mmfile); 140 | if (commentline == -1 ) 141 | error('End-of-file reached before size information was found.') 142 | end 143 | [sizeinfo,count] = sscanf(commentline,'%d%d'); 144 | if ( count > 0 & count ~= 2 ) 145 | error('Invalid size specification line.') 146 | end 147 | end 148 | rows = sizeinfo(1); 149 | cols = sizeinfo(2); 150 | entries = rows*cols; 151 | if ( strcmp(field,'real') ) % real valued entries: 152 | A = fscanf(mmfile,'%f',1); 153 | A = [A; fscanf(mmfile,'%f')]; 154 | if ( strcmp(symm,'symmetric') | strcmp(symm,'hermitian') | strcmp(symm,'skew-symmetric') ) 155 | for j=1:cols-1, 156 | currenti = j*rows; 157 | A = [A(1:currenti); zeros(j,1);A(currenti+1:length(A))]; 158 | end 159 | elseif ( ~ strcmp(symm,'general') ) 160 | disp('Unrecognized symmetry') 161 | disp(symm) 162 | disp('Recognized choices:') 163 | disp(' symmetric') 164 | disp(' hermitian') 165 | disp(' skew-symmetric') 166 | disp(' general') 167 | error('Check symmetry specification in header.'); 168 | end 169 | A = reshape(A,rows,cols); 170 | elseif ( strcmp(field,'complex')) % complx valued entries: 171 | tmpr = fscanf(mmfile,'%f',1); 172 | tmpi = fscanf(mmfile,'%f',1); 173 | A = tmpr+tmpi*i; 174 | for j=1:entries-1 175 | tmpr = fscanf(mmfile,'%f',1); 176 | tmpi = fscanf(mmfile,'%f',1); 177 | A = [A; tmpr + tmpi*i]; 178 | end 179 | if ( strcmp(symm,'symmetric') | strcmp(symm,'hermitian') | strcmp(symm,'skew-symmetric') ) 180 | for j=1:cols-1, 181 | currenti = j*rows; 182 | A = [A(1:currenti); zeros(j,1);A(currenti+1:length(A))]; 183 | end 184 | elseif ( ~ strcmp(symm,'general') ) 185 | disp('Unrecognized symmetry') 186 | disp(symm) 187 | disp('Recognized choices:') 188 | disp(' symmetric') 189 | disp(' hermitian') 190 | disp(' skew-symmetric') 191 | disp(' general') 192 | error('Check symmetry specification in header.'); 193 | end 194 | A = reshape(A,rows,cols); 195 | elseif ( strcmp(field,'pattern')) % pattern (makes no sense for dense) 196 | disp('Matrix type:',field) 197 | error('Pattern matrix type invalid for array storage format.'); 198 | else % Unknown matrix type 199 | disp('Matrix type:',field) 200 | error('Invalid matrix type specification. Check header against MM documentation.'); 201 | end 202 | end 203 | 204 | % 205 | % If symmetric, skew-symmetric or Hermitian, duplicate lower 206 | % triangular part and modify entries as appropriate: 207 | % 208 | 209 | if ( strcmp(symm,'symmetric') ) 210 | A = A + A.' - diag(diag(A)); 211 | entries = nnz(A); 212 | elseif ( strcmp(symm,'hermitian') ) 213 | A = A + A' - diag(diag(A)); 214 | entries = nnz(A); 215 | elseif ( strcmp(symm,'skew-symmetric') ) 216 | A = A - A'; 217 | entries = nnz(A); 218 | end 219 | 220 | fclose(mmfile); 221 | % Done. 222 | 223 | -------------------------------------------------------------------------------- /PROPACK/mmwrite.m: -------------------------------------------------------------------------------- 1 | function [ err ] = mmwrite(filename,A,comment,field,precision) 2 | % 3 | % Function: mmwrite(filename,A,comment,field,precision) 4 | % 5 | % Writes the sparse or dense matrix A to a Matrix Market (MM) 6 | % formatted file. 7 | % 8 | % Required arguments: 9 | % 10 | % filename - destination file 11 | % 12 | % A - sparse or full matrix 13 | % 14 | % Optional arguments: 15 | % 16 | % comment - matrix of comments to prepend to 17 | % the MM file. To build a comment matrix, 18 | % use str2mat. For example: 19 | % 20 | % comment = str2mat(' Comment 1' ,... 21 | % ' Comment 2',... 22 | % ' and so on.',... 23 | % ' to attach a date:',... 24 | % [' ',date]); 25 | % If ommitted, a single line date stamp comment 26 | % will be included. 27 | % 28 | % field - 'real' 29 | % 'complex' 30 | % 'integer' 31 | % 'pattern' 32 | % If ommitted, data will determine type. 33 | % 34 | % precision - number of digits to display for real 35 | % or complex values 36 | % If ommitted, full working precision is used. 37 | % 38 | 39 | if ( nargin == 5) 40 | precision = 16; 41 | elseif ( nargin == 4) 42 | precision = 16; 43 | elseif ( nargin == 3) 44 | mattype = 'real'; % placeholder, will check after FIND-ing A 45 | precision = 16; 46 | elseif ( nargin == 2) 47 | comment = ''; 48 | % Check whether there is an imaginary part: 49 | mattype = 'real'; % placeholder, will check after FIND-ing A 50 | precision = 16; 51 | end 52 | 53 | mmfile = fopen([filename],'w'); 54 | if ( mmfile == -1 ) 55 | error('Cannot open file for output'); 56 | end; 57 | 58 | 59 | [M,N] = size(A); 60 | 61 | %%%%%%%%%%%%% This part for sparse matrices %%%%%%%%%%%%%%%% 62 | if ( issparse(A) ) 63 | 64 | [I,J,V] = find(A); 65 | if ( sum(abs(imag(nonzeros(V)))) > 0 ) 66 | Vreal = 0; 67 | else 68 | Vreal = 1; 69 | end 70 | 71 | if ( ~ strcmp(mattype,'pattern') & Vreal ) 72 | mattype = 'real'; 73 | elseif ( ~ strcmp(mattype,'pattern') ) 74 | mattype = 'complex'; 75 | end 76 | % 77 | % Determine symmetry: 78 | % 79 | if ( M ~= N ) 80 | symm = 'general'; 81 | issymm = 0; 82 | NZ = length(V); 83 | else 84 | issymm = 1; 85 | NZ = length(V); 86 | for i=1:NZ 87 | if ( A(J(i),I(i)) ~= V(i) ) 88 | issymm = 0; 89 | break; 90 | end 91 | end 92 | if ( issymm ) 93 | symm = 'symmetric'; 94 | ATEMP = tril(A); 95 | [I,J,V] = find(ATEMP); 96 | NZ = nnz(ATEMP); 97 | else 98 | isskew = 1; 99 | for i=1:NZ 100 | if ( A(J(i),I(i)) ~= - V(i) ) 101 | isskew = 0; 102 | break; 103 | end 104 | end 105 | if ( isskew ) 106 | symm = 'skew-symmetric'; 107 | ATEMP = tril(A); 108 | [I,J,V] = find(ATEMP); 109 | NZ = nnz(ATEMP); 110 | elseif ( strcmp(mattype,'complex') ) 111 | isherm = 1; 112 | for i=1:NZ 113 | if ( A(J(i),I(i)) ~= conj(V(i)) ) 114 | isherm = 0; 115 | break; 116 | end 117 | end 118 | if ( isherm ) 119 | symm = 'hermitian'; 120 | ATEMP = tril(A); 121 | [I,J,V] = find(ATEMP); 122 | NZ = nnz(ATEMP); 123 | else 124 | symm = 'general'; 125 | NZ = nnz(A); 126 | end 127 | else 128 | symm = 'general'; 129 | NZ = nnz(A); 130 | end 131 | end 132 | end 133 | 134 | % Sparse coordinate format: 135 | 136 | rep = 'coordinate'; 137 | 138 | 139 | fprintf(mmfile,'%%%%MatrixMarket matrix %s %s %s\n',rep,mattype,symm); 140 | [MC,NC] = size(comment); 141 | if ( MC == 0 ) 142 | fprintf(mmfile,'%% Generated %s\n',[date]); 143 | else 144 | for i=1:MC, 145 | fprintf(mmfile,'%%%s\n',comment(i,:)); 146 | end 147 | end 148 | fprintf(mmfile,'%d %d %d\n',M,N,NZ); 149 | cplxformat = sprintf('%%d %%d %% .%dg %% .%dg\n',precision,precision); 150 | realformat = sprintf('%%d %%d %% .%dg\n',precision); 151 | if ( strcmp(mattype,'real') ) 152 | for i=1:NZ 153 | fprintf(mmfile,realformat,I(i),J(i),V(i)); 154 | end; 155 | elseif ( strcmp(mattype,'complex') ) 156 | for i=1:NZ 157 | fprintf(mmfile,cplxformat,I(i),J(i),real(V(i)),imag(V(i))); 158 | end; 159 | elseif ( strcmp(mattype,'pattern') ) 160 | for i=1:NZ 161 | fprintf(mmfile,'%d %d\n',I(i),J(i)); 162 | end; 163 | else 164 | err = -1; 165 | disp('Unsupported mattype:') 166 | mattype 167 | end; 168 | 169 | %%%%%%%%%%%%% This part for dense matrices %%%%%%%%%%%%%%%% 170 | else 171 | if ( sum(abs(imag(nonzeros(A)))) > 0 ) 172 | Areal = 0; 173 | else 174 | Areal = 1; 175 | end 176 | if ( ~strcmp(mattype,'pattern') & Areal ) 177 | mattype = 'real'; 178 | elseif ( ~strcmp(mattype,'pattern') ) 179 | mattype = 'complex'; 180 | end 181 | % 182 | % Determine symmetry: 183 | % 184 | if ( M ~= N ) 185 | issymm = 0; 186 | symm = 'general'; 187 | else 188 | issymm = 1; 189 | for j=1:N 190 | for i=j+1:N 191 | if (A(i,j) ~= A(j,i) ) 192 | issymm = 0; 193 | break; 194 | end 195 | end 196 | if ( ~ issymm ) break; end 197 | 198 | end 199 | if ( issymm ) 200 | symm = 'symmetric'; 201 | else 202 | isskew = 1; 203 | for j=1:N 204 | for i=j+1:N 205 | if (A(i,j) ~= - A(j,i) ) 206 | isskew = 0; 207 | break; 208 | end 209 | end 210 | if ( ~ isskew ) break; end 211 | end 212 | if ( isskew ) 213 | symm = 'skew-symmetric'; 214 | elseif ( strcmp(mattype,'complex') ) 215 | isherm = 1; 216 | for j=1:N 217 | for i=j+1:N 218 | if (A(i,j) ~= conj(A(j,i)) ) 219 | isherm = 0; 220 | break; 221 | end 222 | end 223 | if ( ~ isherm ) break; end 224 | end 225 | if ( isherm ) 226 | symm = 'hermitian'; 227 | else 228 | symm = 'general'; 229 | end 230 | else 231 | symm = 'general'; 232 | end 233 | end 234 | end 235 | 236 | % Dense array format: 237 | 238 | rep = 'array'; 239 | [MC,NC] = size(comment); 240 | fprintf(mmfile,'%%%%MatrixMarket mtx %s %s %s\n',rep,mattype,symm); 241 | for i=1:MC, 242 | fprintf(mmfile,'%%%s\n',comment(i,:)); 243 | end; 244 | fprintf(mmfile,'%d %d\n',M,N); 245 | cplxformat = sprintf('%% .%dg %% .%dg\n', precision,precision); 246 | realformat = sprintf('%% .%dg\n', precision); 247 | if ( ~ strcmp(symm,'general') ) 248 | rowloop = 'j'; 249 | else 250 | rowloop = '1'; 251 | end 252 | if ( strcmp(mattype,'real') ) 253 | for j=1:N 254 | for i=eval(rowloop):M 255 | fprintf(mmfile,realformat,A(i,j)); 256 | end 257 | end 258 | elseif ( strcmp(mattype,'complex') ) 259 | for j=1:N 260 | for i=eval(rowloop):M 261 | fprintf(mmfile,cplxformat,real(A(i,j)),imag(A(i,j))); 262 | end 263 | end 264 | elseif ( strcmp(mattype,'pattern') ) 265 | err = -2 266 | disp('Pattern type inconsistant with dense matrix') 267 | else 268 | err = -2 269 | disp('Unknown matrix type:') 270 | mattype 271 | end 272 | end 273 | 274 | fclose(mmfile); 275 | -------------------------------------------------------------------------------- /PROPACK/pythag.m: -------------------------------------------------------------------------------- 1 | function x = pythag(y,z) 2 | %PYTHAG Computes sqrt( y^2 + z^2 ). 3 | % 4 | % x = pythag(y,z) 5 | % 6 | % Returns sqrt(y^2 + z^2) but is careful to scale to avoid overflow. 7 | 8 | % Christian H. Bischof, Argonne National Laboratory, 03/31/89. 9 | 10 | [m n] = size(y); 11 | if m>1 | n>1 12 | y = y(:); z=z(:); 13 | rmax = max(abs([y';z']))'; 14 | id=find(rmax==0); 15 | if length(id)>0 16 | rmax(id) = 1; 17 | x = rmax.*sqrt((y./rmax).^2 + (z./rmax).^2); 18 | x(id)=0; 19 | else 20 | x = rmax.*sqrt((y./rmax).^2 + (z./rmax).^2); 21 | end 22 | x = reshape(x,m,n); 23 | else 24 | rmax = max(abs([y;z])); 25 | if (rmax==0) 26 | x = 0; 27 | else 28 | x = rmax*sqrt((y/rmax)^2 + (z/rmax)^2); 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /PROPACK/refinebounds.m: -------------------------------------------------------------------------------- 1 | function [bnd,gap] = refinebounds(D,bnd,tol1) 2 | %REFINEBONDS Refines error bounds for Ritz values based on gap-structure 3 | % 4 | % bnd = refinebounds(lambda,bnd,tol1) 5 | % 6 | % Treat eigenvalues closer than tol1 as a cluster. 7 | 8 | % Rasmus Munk Larsen, DAIMI, 1998 9 | 10 | j = length(D); 11 | 12 | if j<=1 13 | return 14 | end 15 | % Sort eigenvalues to use interlacing theorem correctly 16 | [D,PERM] = sort(D); 17 | bnd = bnd(PERM); 18 | 19 | 20 | % Massage error bounds for very close Ritz values 21 | eps34 = sqrt(eps*sqrt(eps)); 22 | [y,mid] = max(bnd); 23 | for l=[-1,1] 24 | for i=((j+1)-l*(j-1))/2:l:mid-l 25 | if abs(D(i+l)-D(i)) < eps34*abs(D(i)) 26 | if bnd(i)>tol1 & bnd(i+l)>tol1 27 | bnd(i+l) = pythag(bnd(i),bnd(i+l)); 28 | bnd(i) = 0; 29 | end 30 | end 31 | end 32 | end 33 | % Refine error bounds 34 | gap = inf*ones(1,j); 35 | gap(1:j-1) = min([gap(1:j-1);[D(2:j)-bnd(2:j)-D(1:j-1)]']); 36 | gap(2:j) = min([gap(2:j);[D(2:j)-D(1:j-1)-bnd(1:j-1)]']); 37 | gap = gap(:); 38 | I = find(gap>bnd); 39 | bnd(I) = bnd(I).*(bnd(I)./gap(I)); 40 | 41 | bnd(PERM) = bnd; -------------------------------------------------------------------------------- /PROPACK/reorth.f: -------------------------------------------------------------------------------- 1 | subroutine reorth(n,k,V,ldv,vnew,normv,index,alpha,work, 2 | c iflag,nre) 3 | c 4 | c FORTRAN 77 version of MATLAB routine REORTH: 5 | c 6 | c REORTH Reorthogonalize a vector using iterated Gram-Schmidt 7 | c 8 | c [R_NEW,NORMR_NEW,NRE] = reorth(Q,R,NORMR,INDEX,ALPHA,METHOD) 9 | c reorthogonalizes R against the subset of columns of Q given by INDEX. 10 | c If INDEX==[] then R is reorthogonalized all columns of Q. 11 | c If the result R_NEW has a small norm, i.e. if norm(R_NEW) < ALPHA*NORMR, 12 | c then a second reorthogonalization is performed. If the norm of R_NEW 13 | c is once more decreased by more than a factor of ALPHA then R is 14 | c numerically in span(Q(:,INDEX)) and a zero-vector is returned for R_NEW. 15 | c 16 | c If method==0 then iterated modified Gram-Schmidt is used. 17 | c If method==1 then iterated classical Gram-Schmidt is used. 18 | c 19 | c The default value for ALPHA is 0.5. 20 | c NRE is the number of reorthogonalizations performed (1 or 2). 21 | 22 | c References: 23 | c Aake Bjorck, "Numerical Methods for Least Squares Problems", 24 | c SIAM, Philadelphia, 1996, pp. 68-69. 25 | c 26 | c J.~W. Daniel, W.~B. Gragg, L. Kaufman and G.~W. Stewart, 27 | c ``Reorthogonalization and Stable Algorithms Updating the 28 | c Gram-Schmidt QR Factorization'', Math. Comp., 30 (1976), no. 29 | c 136, pp. 772-795. 30 | c 31 | c B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 32 | c Prentice-Hall, Englewood Cliffs, NJ, 1980. pp. 105-109 33 | 34 | c Rasmus Munk Larsen, DAIMI, 1998. 35 | implicit none 36 | integer n,k,ldv,i,iflag,nre 37 | double precision V(ldv,*),vnew(*),normv,index(*),work(*) 38 | double precision alpha,normv_old,dnrm2 39 | integer MAXTRY 40 | parameter (MAXTRY=4) 41 | external dgemv,dnrm2 42 | 43 | c Hack: If index .ne. 1:k we do MGS to avoid reshuffling. 44 | if (iflag.eq.1) then 45 | do i=1,k 46 | if (int(index(i)).ne.i) then 47 | iflag=0 48 | goto 100 49 | endif 50 | enddo 51 | endif 52 | 100 normv_old = 0 53 | nre = 0 54 | normv = dnrm2(n,vnew,1) 55 | do while ((normv.lt.alpha*normv_old .or. nre.eq.0)) 56 | if (iflag.eq.1) then 57 | c CGS: 58 | call dgemv('T',n,k,1D0,V,ldv,vnew,1,0D0,work,1) 59 | call dgemv('N',n,k,-1D0,V,ldv,work,1,1D0,vnew,1) 60 | else 61 | c MGS: 62 | call MGS(n,k,V,ldv,vnew,index) 63 | endif 64 | normv_old = normv 65 | normv = dnrm2(n,vnew,1) 66 | nre = nre + 1 67 | 68 | if ( nre.gt.MAXTRY ) then 69 | c 70 | c vnew is numerically in span(V) => return vnew = (0,0,...,0)^T 71 | normv = 0d0 72 | do i=1,n 73 | vnew(i) = 0d0 74 | enddo 75 | return 76 | endif 77 | enddo 78 | end 79 | c 80 | c**************************************************************************** 81 | c 82 | 83 | subroutine MGS(n,k,V,ldv,vnew,index) 84 | implicit none 85 | integer n,k,ldv 86 | double precision V(ldv,*),vnew(*),index(*) 87 | integer i,j,idx 88 | double precision s 89 | 90 | c 91 | c Modified Gram-Schmidt orthogonalization: 92 | c Orthogalizes vnew against the k vectors in V by the 93 | c iterative process 94 | c 95 | c FOR i=1...k DO 96 | c vnew = vnew - DOT( V(:,i), vnew ) * V(:,i) 97 | c 98 | 99 | c This simple version is faster on Pentium machines. 100 | c Compile with "g77 -O6 -funroll-all-loops -fomit-frame-pointer" 101 | 102 | do i=1,k 103 | idx = int(index(i)) 104 | s = 0 105 | do j=1,n 106 | s = s + V(j,idx)*vnew(j) 107 | enddo 108 | do j=1,n 109 | vnew(j) = vnew(j) - s*V(j,idx) 110 | enddo 111 | enddo 112 | end 113 | c 114 | c**************************************************************************** 115 | c 116 | 117 | -------------------------------------------------------------------------------- /PROPACK/reorth.m: -------------------------------------------------------------------------------- 1 | function [r,normr,nre,s] = reorth(Q,r,normr,index,alpha,method) 2 | 3 | %REORTH Reorthogonalize a vector using iterated Gram-Schmidt 4 | % 5 | % [R_NEW,NORMR_NEW,NRE] = reorth(Q,R,NORMR,INDEX,ALPHA,METHOD) 6 | % reorthogonalizes R against the subset of columns of Q given by INDEX. 7 | % If INDEX==[] then R is reorthogonalized all columns of Q. 8 | % If the result R_NEW has a small norm, i.e. if norm(R_NEW) < ALPHA*NORMR, 9 | % then a second reorthogonalization is performed. If the norm of R_NEW 10 | % is once more decreased by more than a factor of ALPHA then R is 11 | % numerically in span(Q(:,INDEX)) and a zero-vector is returned for R_NEW. 12 | % 13 | % If method==0 then iterated modified Gram-Schmidt is used. 14 | % If method==1 then iterated classical Gram-Schmidt is used. 15 | % 16 | % The default value for ALPHA is 0.5. 17 | % NRE is the number of reorthogonalizations performed (1 or 2). 18 | 19 | % References: 20 | % Aake Bjorck, "Numerical Methods for Least Squares Problems", 21 | % SIAM, Philadelphia, 1996, pp. 68-69. 22 | % 23 | % J.~W. Daniel, W.~B. Gragg, L. Kaufman and G.~W. Stewart, 24 | % ``Reorthogonalization and Stable Algorithms Updating the 25 | % Gram-Schmidt QR Factorization'', Math. Comp., 30 (1976), no. 26 | % 136, pp. 772-795. 27 | % 28 | % B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 29 | % Prentice-Hall, Englewood Cliffs, NJ, 1980. pp. 105-109 30 | 31 | % Rasmus Munk Larsen, DAIMI, 1998. 32 | 33 | % Check input arguments. 34 | % warning('PROPACK:NotUsingMex','Using slow matlab code for reorth.') 35 | if nargin<2 36 | error('Not enough input arguments.') 37 | end 38 | [n k1] = size(Q); 39 | if nargin<3 | isempty(normr) 40 | % normr = norm(r); 41 | normr = sqrt(r'*r); 42 | end 43 | if nargin<4 | isempty(index) 44 | k=k1; 45 | index = [1:k]'; 46 | simple = 1; 47 | else 48 | k = length(index); 49 | if k==k1 & index(:)==[1:k]' 50 | simple = 1; 51 | else 52 | simple = 0; 53 | end 54 | end 55 | if nargin<5 | isempty(alpha) 56 | alpha=0.5; % This choice garanties that 57 | % || Q^T*r_new - e_{k+1} ||_2 <= 2*eps*||r_new||_2, 58 | % cf. Kahans ``twice is enough'' statement proved in 59 | % Parletts book. 60 | end 61 | if nargin<6 | isempty(method) 62 | method = 0; 63 | end 64 | if k==0 | n==0 65 | return 66 | end 67 | if nargout>3 68 | s = zeros(k,1); 69 | end 70 | 71 | 72 | normr_old = 0; 73 | nre = 0; 74 | while normr < alpha*normr_old | nre==0 75 | if method==1 76 | if simple 77 | t = Q'*r; 78 | r = r - Q*t; 79 | else 80 | t = Q(:,index)'*r; 81 | r = r - Q(:,index)*t; 82 | end 83 | else 84 | for i=index, 85 | t = Q(:,i)'*r; 86 | r = r - Q(:,i)*t; 87 | end 88 | end 89 | if nargout>3 90 | s = s + t; 91 | end 92 | normr_old = normr; 93 | % normr = norm(r); 94 | normr = sqrt(r'*r); 95 | nre = nre + 1; 96 | if nre > 4 97 | % r is in span(Q) to full accuracy => accept r = 0 as the new vector. 98 | r = zeros(n,1); 99 | normr = 0; 100 | return 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /PROPACK/reorth.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/reorth.mexglx -------------------------------------------------------------------------------- /PROPACK/reorth.mexsg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/reorth.mexsg -------------------------------------------------------------------------------- /PROPACK/reorth.mexsg64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/reorth.mexsg64 -------------------------------------------------------------------------------- /PROPACK/reorth.mexsol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/reorth.mexsol -------------------------------------------------------------------------------- /PROPACK/reorth_mex.c: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------- 3 | GATEWAY ROUTINE FOR CALLING REORTH FROM MATLAB. 4 | 5 | REORTH Reorthogonalize a vector using iterated Gram-Schmidt 6 | 7 | [R_NEW,NORMR_NEW,NRE] = reorth(Q,R,NORMR,INDEX,ALPHA,METHOD) 8 | reorthogonalizes R against the subset of columns of Q given by INDEX. 9 | If INDEX==[] then R is reorthogonalized all columns of Q. 10 | If the result R_NEW has a small norm, i.e. if norm(R_NEW) < ALPHA*NORMR, 11 | then a second reorthogonalization is performed. If the norm of R_NEW 12 | is once more decreased by more than a factor of ALPHA then R is 13 | numerically in span(Q(:,INDEX)) and a zero-vector is returned for R_NEW. 14 | 15 | If method==0 then iterated modified Gram-Schmidt is used. 16 | If method==1 then iterated classical Gram-Schmidt is used. 17 | 18 | The default value for ALPHA is 0.5. 19 | NRE is the number of reorthogonalizations performed (1 or 2). 20 | 21 | References: 22 | Aake Bjorck, "Numerical Methods for Least Squares Problems", 23 | SIAM, Philadelphia, 1996, pp. 68-69. 24 | 25 | J.~W. Daniel, W.~B. Gragg, L. Kaufman and G.~W. Stewart, 26 | ``Reorthogonalization and Stable Algorithms Updating the 27 | Gram-Schmidt QR Factorization'', Math. Comp., 30 (1976), no. 28 | 136, pp. 772-795. 29 | 30 | B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 31 | Prentice-Hall, Englewood Cliffs, NJ, 1980. pp. 105-109 32 | 33 | Rasmus Munk Larsen, DAIMI, 1998. 34 | ------------------------------------------------------------------------- 35 | */ 36 | 37 | #include 38 | #include "mex.h" 39 | 40 | /* Template for reorth: */ 41 | 42 | void reorth_(int *n, int *k, double *V, int *ldv, double *vnew, 43 | double *normvnew, double *index, double *alpha, double *work, 44 | int *iflag, int *nre); 45 | 46 | /* Here comes the gateway function to be called by Matlab: */ 47 | void mexFunction(int nlhs, mxArray *plhs[], 48 | int nrhs, const mxArray *prhs[]) 49 | { 50 | int n, k1, k, imethod, inre; 51 | double *work; 52 | 53 | if (nrhs != 6) 54 | mexErrMsgTxt("reorth requires 6 input arguments"); 55 | else if (nlhs < 2) 56 | mexErrMsgTxt("reorth requires at least 2 output arguments"); 57 | 58 | n = mxGetM(prhs[0]); /* get the dimensions of the input */ 59 | k1 = mxGetN(prhs[0]); 60 | k = mxGetM(prhs[3]) * mxGetN(prhs[3]); 61 | 62 | /* Create/allocate return argument, a 1x1 real-valued Matrix */ 63 | plhs[0]=mxCreateDoubleMatrix(n,1,mxREAL); 64 | plhs[1]=mxCreateDoubleMatrix(1,1,mxREAL); 65 | if (nlhs>2) 66 | plhs[2]=mxCreateDoubleMatrix(1,1,mxREAL); 67 | 68 | work = mxCalloc(k,sizeof(double)); 69 | 70 | memcpy(mxGetPr(plhs[0]),mxGetPr(prhs[1]), n*sizeof(double)); 71 | memcpy(mxGetPr(plhs[1]),mxGetPr(prhs[2]), sizeof(double)); 72 | imethod = (int) mxGetScalar(prhs[5]); 73 | 74 | reorth_(&n, &k, mxGetPr(prhs[0]), &n, mxGetPr(plhs[0]), 75 | mxGetPr(plhs[1]), mxGetPr(prhs[3]), mxGetPr(prhs[4]), 76 | work,&imethod,&inre); 77 | if (nlhs>2) 78 | *(mxGetPr(plhs[2])) = (double) inre*k; 79 | 80 | mxFree(work); 81 | } 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /PROPACK/testtqlb.m: -------------------------------------------------------------------------------- 1 | % Script for comparing speed an accuracy of original TQLB, optimized TQLB 2 | % and builtin EIG command. 3 | 4 | % Rasmus Munk Larsen, DAIMI, 1998. 5 | 6 | n=1000; 7 | 8 | % Use 2. order difference matrix as testproblem. 9 | e = ones(n,1); 10 | T = spdiags([-e 2*e -e], -1:1, n, n); 11 | true = 4*cos(pi/2*[n:-1:1]'./(n+1)).^2; 12 | alpha = 2*ones(n,1); 13 | beta = -ones(n,1); 14 | 15 | fprintf('-----------------------------------------------------------------\n') 16 | disp('Modified tqlb:') 17 | fprintf('\n') 18 | tic, flops(0) 19 | [lambda,top,bot,err] = tqlb(alpha,beta); 20 | fprintf('Elapsed time = %f\n',toc); 21 | fprintf('Number of flops = %f\n',flops); 22 | fprintf('Max rel. error = %e\n',max(abs((lambda-true)./true))) 23 | 24 | 25 | fprintf('-----------------------------------------------------------------\n') 26 | disp('Original tqlb:') 27 | fprintf('\n') 28 | tic, flops(0); 29 | [lambda2,top,bot,err2] = tqlb_orig(alpha,beta); 30 | fprintf('Elapsed time = %f\n',toc); 31 | fprintf('Number of flops = %f\n',flops); 32 | fprintf('Max rel. error = %e\n',max(abs((lambda2-true)./true))) 33 | 34 | 35 | fprintf('-----------------------------------------------------------------\n') 36 | disp('eig:') 37 | fprintf('\n') 38 | tic, flops(0); 39 | lambda1 = eig(T); 40 | lambda1 =sort(lambda1); 41 | fprintf('Elapsed time = %f\n',toc); 42 | fprintf('Number of flops = %f\n',flops); 43 | fprintf('Max rel. error = %e\n',max(abs((lambda1-true)./true))) 44 | 45 | fprintf('-----------------------------------------------------------------\n') 46 | disp('eig:') 47 | fprintf('\n') 48 | tic, flops(0); 49 | lambda1 = eig(full(T)); 50 | lambda1 =sort(lambda1); 51 | fprintf('Elapsed time = %f\n',toc); 52 | fprintf('Number of flops = %f\n',flops); 53 | fprintf('Max rel. error = %e\n',max(abs((lambda1-true)./true))) 54 | 55 | 56 | -------------------------------------------------------------------------------- /PROPACK/tqlb.f: -------------------------------------------------------------------------------- 1 | C 2 | C @(#)TQLB.F 1.1 (BNP) 5/9/89 3 | C 4 | SUBROUTINE TQLB(N,D,E,BND,BND2,IERR) 5 | C 6 | INTEGER I,J,L,M,N,II,L1,L2,MML,IERR 7 | DOUBLE PRECISION D(N),E(N),BND(N),BND2(N) 8 | DOUBLE PRECISION C,C2,C3,DL1,EL1,F,G,H,H1,P,R,S,S2,TST1,TST2 9 | C 10 | C THIS SUBROUTINE IS A MODIFICATION OF THE ALGOL PROCEDURE TQL1, 11 | C NUM. MATH. 11, 293-306(1968) BY BOWDLER, MARTIN, REINSCH, AND 12 | C WILKINSON. 13 | C HANDBOOK FOR AUTO. COMP., VOL.II-LINEAR ALGEBRA, 227-240(1971). 14 | C 15 | C THIS SUBROUTINE FINDS THE EIGENVALUES OF A SYMMETRIC 16 | C TRIDIAGONAL MATRIX BY THE QL METHOD. 17 | C 18 | C ON INPUT 19 | C 20 | C N IS THE ORDER OF THE MATRIX. 21 | C 22 | C D CONTAINS THE DIAGONAL ELEMENTS OF THE INPUT MATRIX. 23 | C 24 | C E CONTAINS THE SUBDIAGONAL ELEMENTS OF THE INPUT MATRIX 25 | C IN ITS LAST N-1 POSITIONS. E(1) IS ARBITRARY. 26 | C 27 | C ON OUTPUT 28 | C 29 | C D CONTAINS THE EIGENVALUES IN ASCENDING ORDER. IF AN 30 | C ERROR EXIT IS MADE, THE EIGENVALUES ARE CORRECT AND 31 | C ORDERED FOR INDICES 1,2,...IERR-1, BUT MAY NOT BE 32 | C THE SMALLEST EIGENVALUES. 33 | C 34 | C E HAS BEEN DESTROYED. 35 | C 36 | C BND WILL HOLD THE TOP ELEMENTS OF THE NORMALIZED EIGENVECTORS. 37 | C 38 | C IERR IS SET TO 39 | C ZERO FOR NORMAL RETURN, 40 | C J IF THE J-TH EIGENVALUE HAS NOT BEEN 41 | C DETERMINED AFTER 30 ITERATIONS. 42 | C 43 | C calls to PYTHAG for SQRT(A*A + B*B) have been replaced by inline code. 44 | C 45 | C QUESTIONS AND COMMENTS SHOULD BE DIRECTED TO BURTON S. GARBOW, 46 | C MATHEMATICS AND COMPUTER SCIENCE DIV, ARGONNE NATIONAL LABORATORY 47 | C 48 | C THIS VERSION DATED AUGUST 1983 (AUGUST 1998). 49 | C 50 | C ------------------------------------------------------------------ 51 | C 52 | IERR = 0 53 | BND(1) = 1.0D0 54 | IF (N .EQ. 1) GO TO 1001 55 | BND2(N) = 1.0D0 56 | C 57 | DO 100 I = 2, N 58 | BND(I) = 0.0D0 59 | BND2(I-1) = 0.0D0 60 | 100 E(I-1) = E(I) 61 | C 62 | F = 0.0D0 63 | TST1 = 0.0D0 64 | E(N) = 0.0D0 65 | C 66 | DO 290 L = 1, N 67 | J = 0 68 | H = ABS(D(L)) + ABS(E(L)) 69 | IF (TST1 .LT. H) TST1 = H 70 | C .......... LOOK FOR SMALL SUB-DIAGONAL ELEMENT .......... 71 | DO 110 M = L, N 72 | TST2 = TST1 + ABS(E(M)) 73 | IF (TST2 .EQ. TST1) GO TO 120 74 | C .......... E(N) IS ALWAYS ZERO, SO THERE IS NO EXIT 75 | C THROUGH THE BOTTOM OF THE LOOP .......... 76 | 110 CONTINUE 77 | C 78 | 120 IF (M .EQ. L) GO TO 210 79 | 130 IF (J .EQ. 30) GO TO 1000 80 | J = J + 1 81 | C .......... FORM SHIFT .......... 82 | L1 = L + 1 83 | L2 = L1 + 1 84 | G = D(L) 85 | P = (D(L1) - G) / (2.0D0 * E(L)) 86 | if (abs(p).le.1.0e0) then 87 | p = p + sign(sqrt(1.0e0 + p*p),p) 88 | else 89 | p = p * (1.0e0 + sqrt(1.0e0 + (1.0e0/p)**2)) 90 | endif 91 | d(l) = e(l) / p 92 | d(l1) = e(l) * p 93 | c********** Original code: ******************** 94 | c R = PYTHAG(P,1.0D0) 95 | c D(L) = E(L) / (P + SIGN(R,P)) 96 | c D(L1) = E(L) * (P + SIGN(R,P)) 97 | c********************************************* 98 | DL1 = D(L1) 99 | H = G - D(L) 100 | IF (L2 .GT. N) GO TO 145 101 | C 102 | DO 140 I = L2, N 103 | 140 D(I) = D(I) - H 104 | C 105 | 145 F = F + H 106 | C .......... QL TRANSFORMATION .......... 107 | P = D(M) 108 | C = 1.0D0 109 | C2 = C 110 | EL1 = E(L1) 111 | S = 0.0D0 112 | MML = M - L 113 | C .......... FOR I=M-1 STEP -1 UNTIL L DO -- .......... 114 | DO 200 II = 1, MML 115 | C3 = C2 116 | C2 = C 117 | S2 = S 118 | I = M - II 119 | G = C * E(I) 120 | H = C * P 121 | c inlined call to PYTHAG. This code corresponds to LAPACK rutine DLAPY2. 122 | c Speeds tqlb up by a factor of 3 on MIPS R10000. 123 | IF(DABS(P).GE.DABS(E(I))) then 124 | S=E(I)/P 125 | R=SQRT(1D0+S*S) 126 | E(I+1)=S2*P*R 127 | C=1D0/R 128 | S=S*C 129 | else 130 | C=P/E(I) 131 | R=SQRT(1D0+C*C) 132 | E(I+1)=S2*E(I)*R 133 | S=1D0/R 134 | C=C*S 135 | endif 136 | P = C * D(I) - S * G 137 | D(I+1) = H + S * (C * G + S * D(I)) 138 | H = BND(I+1) 139 | BND(I+1) = S*BND(I)+C*H 140 | BND(I) = C*BND(I)-S*H 141 | H = BND2(I+1) 142 | BND2(I+1) = S*BND2(I)+C*H 143 | BND2(I) = C*BND2(I)-S*H 144 | 200 CONTINUE 145 | C 146 | P = -S * S2 * C3 * EL1 * E(L) / DL1 147 | E(L) = S * P 148 | D(L) = C * P 149 | TST2 = TST1 + ABS(E(L)) 150 | IF (TST2 .GT. TST1) GO TO 130 151 | 210 P = D(L) + F 152 | H = BND(L) 153 | H1 = BND2(L) 154 | C .......... ORDER EIGENVALUES .......... 155 | IF (L .EQ. 1) GO TO 250 156 | C .......... FOR I=L STEP -1 UNTIL 2 DO -- .......... 157 | DO 230 II = 2, L 158 | I = L + 2 - II 159 | IF (P .GE. D(I-1)) GO TO 270 160 | D(I) = D(I-1) 161 | BND(I) = BND(I-1) 162 | BND2(I) = BND2(I-1) 163 | 230 CONTINUE 164 | C 165 | 250 I = 1 166 | 270 D(I) = P 167 | BND(I) = H 168 | BND2(I)= H1 169 | 290 CONTINUE 170 | C 171 | GO TO 1001 172 | C .......... SET ERROR -- NO CONVERGENCE TO AN 173 | C EIGENVALUE AFTER 30 ITERATIONS .......... 174 | 1000 IERR = L 175 | 1001 RETURN 176 | END 177 | -------------------------------------------------------------------------------- /PROPACK/tqlb.m: -------------------------------------------------------------------------------- 1 | function [lambda,top,bot,err] = tqlb(alpha,beta) 2 | 3 | % TQLB: Compute eigenvalues and top and bottom elements of 4 | % eigenvectors of a symmetric tridiagonal matrix T. 5 | % 6 | % [lambda,top,bot,err] = tqlb(alpha,beta) 7 | % 8 | % Input parameters: 9 | % alpha(1:n) : Diagonal elements. 10 | % beta(2:n) : Off-diagonal elements. 11 | % Output parameters: 12 | % lambda(1:n) : Computed eigenvalues. 13 | % top(1:n) : Top elements in eigenvectors. 14 | % bot(1:n) : Bottom elements in eigenvectors. 15 | % err : dummy argument. 16 | 17 | 18 | % Rasmus Munk Larsen, DAIMI, 1998 19 | 20 | 21 | % 22 | % This is a slow Matlab substitute for the 23 | % TQLB MEX-file. 24 | % 25 | 26 | warning('PROPACK:NotUsingMex','Using slow matlab code for tqlb.') 27 | n = length(alpha); 28 | T = spdiags([[beta(2:n);0] alpha(1:n) beta(1:n)],-1:1,n,n); 29 | 30 | [V,lambda] = eig(full(T)); lambda = diag(lambda); 31 | bot = V(end,:)'; 32 | top = V(1,:)'; 33 | err=0; 34 | 35 | 36 | -------------------------------------------------------------------------------- /PROPACK/tqlb.mexglx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/tqlb.mexglx -------------------------------------------------------------------------------- /PROPACK/tqlb.mexsg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/tqlb.mexsg -------------------------------------------------------------------------------- /PROPACK/tqlb.mexsg64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/tqlb.mexsg64 -------------------------------------------------------------------------------- /PROPACK/tqlb.mexsol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/PROPACK/tqlb.mexsol -------------------------------------------------------------------------------- /PROPACK/tqlb_mex.c: -------------------------------------------------------------------------------- 1 | /* 2 | MEX interface for TQLB. Matlab calling sequence: 3 | [lambda,top,bot,err] = tqlb(alpha,beta) 4 | */ 5 | 6 | 7 | #include 8 | #include "mex.h" 9 | 10 | /* Template for tqlb: */ 11 | void tqlb_(int *n, double *d__, double *e, double *bnd, 12 | double *bnd2, int *ierr); 13 | 14 | /* Here comes the gateway function to be called by Matlab: */ 15 | void mexFunction(int nlhs, mxArray *plhs[], 16 | int nrhs, const mxArray *prhs[]) 17 | { 18 | int m, n,i, ierr; 19 | double x, *tmp; 20 | 21 | if (nrhs != 2) 22 | mexErrMsgTxt("tqlb requires two input arguments"); 23 | else if (nlhs != 4) 24 | mexErrMsgTxt("tqlb requires four output arguments"); 25 | 26 | for (i=0; i<2; i++) { 27 | m = mxGetM(prhs[i]); /* get the dimensions of the input */ 28 | n = mxGetN(prhs[i]); 29 | 30 | /* make sure input is m x 1 */ 31 | if (n != 1) 32 | mexErrMsgTxt("Input must be a m x 1 vectors"); 33 | } 34 | 35 | /* Create/allocate return argument, a 1x1 real-valued Matrix */ 36 | for (i=0; i<3; i++) { 37 | plhs[i]=mxCreateDoubleMatrix(m,1,mxREAL); 38 | } 39 | plhs[3] = mxCreateDoubleMatrix(1,1,mxREAL); 40 | tmp = mxCalloc(m,sizeof(double)); 41 | 42 | memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]),m*sizeof(double)); 43 | memcpy(tmp,mxGetPr(prhs[1]), m*sizeof(double)); 44 | tqlb_(&m,mxGetPr(plhs[0]),tmp,mxGetPr(plhs[1]), 45 | mxGetPr(plhs[2]),&ierr); 46 | 47 | *(mxGetPr(plhs[3])) = (double) ierr; 48 | mxFree(tmp); 49 | } 50 | -------------------------------------------------------------------------------- /PROPACK/update_gbound.m: -------------------------------------------------------------------------------- 1 | function anorm = update_gbound(anorm,alpha,beta,j) 2 | %UPDATE_GBOUND Update Gerscgorin estimate of 2-norm 3 | % ANORM = UPDATE_GBOUND(ANORM,ALPHA,BETA,J) updates the Gersgorin bound 4 | % for the tridiagonal in the Lanczos process after the J'th step. 5 | % Applies Gerscgorins circles to T_K'*T_k instead of T_k itself 6 | % since this gives a tighter bound. 7 | 8 | if j==1 % Apply Gerscgorin circles to T_k'*T_k to estimate || A ||_2 9 | i=j; 10 | % scale to avoid overflow 11 | scale = max(abs(alpha(i)),abs(beta(i+1))); 12 | alpha(i) = alpha(i)/scale; 13 | beta(i) = beta(i)/scale; 14 | anorm = 1.01*scale*sqrt(alpha(i)^2+beta(i+1)^2 + abs(alpha(i)*beta(i+1))); 15 | elseif j==2 16 | i=1; 17 | % scale to avoid overflow 18 | scale = max(max(abs(alpha(1:2)),max(abs(beta(2:3))))); 19 | alpha(1:2) = alpha(1:2)/scale; 20 | beta(2:3) = beta(2:3)/scale; 21 | 22 | anorm = max(anorm, scale*sqrt(alpha(i)^2+beta(i+1)^2 + ... 23 | abs(alpha(i)*beta(i+1) + alpha(i+1)*beta(i+1)) + ... 24 | abs(beta(i+1)*beta(i+2)))); 25 | i=2; 26 | anorm = max(anorm,scale*sqrt(abs(beta(i)*alpha(i-1) + alpha(i)*beta(i)) + ... 27 | beta(i)^2+alpha(i)^2+beta(i+1)^2 + ... 28 | abs(alpha(i)*beta(i+1))) ); 29 | elseif j==3 30 | % scale to avoid overflow 31 | scale = max(max(abs(alpha(1:3)),max(abs(beta(2:4))))); 32 | alpha(1:3) = alpha(1:3)/scale; 33 | beta(2:4) = beta(2:4)/scale; 34 | i=2; 35 | anorm = max(anorm,scale*sqrt(abs(beta(i)*alpha(i-1) + alpha(i)*beta(i)) + ... 36 | beta(i)^2+alpha(i)^2+beta(i+1)^2 + ... 37 | abs(alpha(i)*beta(i+1) + alpha(i+1)*beta(i+1)) + ... 38 | abs(beta(i+1)*beta(i+2))) ); 39 | i=3; 40 | anorm = max(anorm,scale*sqrt(abs(beta(i)*beta(i-1)) + ... 41 | abs(beta(i)*alpha(i-1) + alpha(i)*beta(i)) + ... 42 | beta(i)^2+alpha(i)^2+beta(i+1)^2 + ... 43 | abs(alpha(i)*beta(i+1))) ); 44 | else 45 | % scale to avoid overflow 46 | % scale = max(max(abs(alpha(j-2:j)),max(abs(beta(j-2:j+1))))); 47 | % alpha(j-2:j) = alpha(j-2:j)/scale; 48 | % beta(j-2:j+1) = beta(j-2:j+1)/scale; 49 | 50 | % Avoid scaling, which is slow. At j>3 the estimate is usually quite good 51 | % so just make sure that anorm is not made infinite by overflow. 52 | i = j-1; 53 | anorm1 = sqrt(abs(beta(i)*beta(i-1)) + ... 54 | abs(beta(i)*alpha(i-1) + alpha(i)*beta(i)) + ... 55 | beta(i)^2+alpha(i)^2+beta(i+1)^2 + ... 56 | abs(alpha(i)*beta(i+1) + alpha(i+1)*beta(i+1)) + ... 57 | abs(beta(i+1)*beta(i+2))); 58 | if isfinite(anorm1) 59 | anorm = max(anorm,anorm1); 60 | end 61 | i = j; 62 | anorm1 = sqrt(abs(beta(i)*beta(i-1)) + ... 63 | abs(beta(i)*alpha(i-1) + alpha(i)*beta(i)) + ... 64 | beta(i)^2+alpha(i)^2+beta(i+1)^2 + ... 65 | abs(alpha(i)*beta(i+1))); 66 | if isfinite(anorm1) 67 | anorm = max(anorm,anorm1); 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This folder contains the code accompanying the following paper. 2 | 3 | [1] "Provable Dynamic Robust PCA or Robust Subspace Tracking", Praneeth Narayanamurthy and Namrata Vaswani, IEEE Trans. Info. Theory, 2019 (available at arXiv:1705.08948). 4 | 5 | List of main files: 6 | 7 | 1. DemoFB.m - Wrapper containing the real video foreground background separation. The sparse recovery step here uses ell-1 minimization. 8 | 2. DemoDynRPCA.m - Wrapper containing the simulated data experiments. The sparse recovery step here uses CoSAMP. We can use ell-1 too if necessary. 9 | 3. AutoReProCS - main function which implements the ReProCS algororithm using CoSaMP. 10 | 4. ReProCS_real - main function which implements the ReProCS algorithm using ell-1. 11 | 12 | Folders: 13 | 14 | 1. Data folder (120 MB) contains .mat files for videos. Pushing this too, because the original source web-page (http://perception.i2r.a-star.edu.sg/bk_model/bk_index.html) is down. 15 | 2. YALL1 - folder containing files to implement ell-1 minimization. 16 | 17 | 18 | Helper files: 19 | 20 | 1. ncrpca -- code implemented Non-convex Robust PCA, NIPS 14 downloaded from authors' website and its accompaniments 21 | 2. cgls -- fast method to implement least squares 22 | 23 | 24 | For any further questions/suggestions please contact me @ pkurpadn iastate edu (insert obvious symbols) 25 | 26 | -------------------------------------------------------------------------------- /ReProCS.m: -------------------------------------------------------------------------------- 1 | function [BG, FG, L_hat, S_hat, T_hat, t_hat, ... 2 | P_track_full, P_track_new, T_calc]= ... 3 | ReProCS(M1, P_init, mu, ev_thresh, alpha, K) 4 | %%%This is the ReProCS algorithm under the latest subspace change and 5 | %%%support model. This is the main function for the real video Background- 6 | %%%Foreground separation problem. 7 | 8 | %This folder contains the code accompanying pre-print. 9 | % 10 | %[1] "New Results for Provable Dynamic Robust PCA", Praneeth Narayanamurthy and Namrata Vaswani, arXiv:1705.08948, 2017. 11 | % 12 | %If you use this code please also cite the following papers 13 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 14 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 15 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 16 | 17 | 18 | %%% Inputs %%% 19 | %%% M - measurement matrix %%% 20 | %%% ev_thres - threshold for subspace change detection %%% 21 | %%% P_init - an initial estimate of the subspace %%% 22 | %%% t_train - the dimension of the training data %%% 23 | 24 | 25 | %%% Algorithm parameters %%% 26 | %%% alpha - frame length %%% 27 | %%% mu - column-averages of data %%% 28 | %%% K - number of projection PCA steps %%% 29 | %%% omega - threshold for non-zero value in S %%% 30 | 31 | 32 | %%% Outputs %%% 33 | %%% BG - Estimated Background %%% 34 | %%% FG - Estimated Foreground %%% 35 | %%% L_hat - estimate of the low rank matrix %%% 36 | %%% P_hat - estimate of the subspace in which L lies %%% 37 | %%% S_hat - estimate of the sparse signal %%% 38 | %%% t_hat - estimate of subspace change times %%% 39 | 40 | %% Initializations 41 | 42 | P_hat_old = P_init; 43 | P_hat_new = []; 44 | P_hat = [P_hat_old, P_hat_new]; 45 | 46 | [n, t_max] = size(M1); 47 | T_hat = zeros(n, t_max); 48 | S_hat = zeros(n, t_max); 49 | L_hat = zeros(n, t_max); 50 | 51 | FG = zeros(n, t_max); 52 | BG = zeros(n, t_max); 53 | 54 | t_hat = []; 55 | M = M1 - repmat(mu, 1, t_max); 56 | k = 0; 57 | cnt = 1; 58 | ph = 0; %ph - 0 => detect, 1 => ppca 59 | opts.delta = 0.4; 60 | 61 | phi_t = speye(n) - P_hat * P_hat'; 62 | %% Main Algorithm Loop 63 | for ii = 2 : t_max 64 | %% Estimate support 65 | Atf.times = @(x) x - (P_hat * (P_hat' * x)); 66 | Atf.trans = @(y) y - (P_hat * (P_hat' * y)); 67 | phi.times = @(x) x - (P_hat_old * (P_hat_old' * x)); 68 | y_t = Atf.times(M(:, ii)); 69 | opts.tol = 1e-3; 70 | opts.print = 0; 71 | 72 | opts.delta = norm(Atf.times(L_hat(:, ii - 1))); 73 | 74 | x_t_hat_cs = yall1(Atf, y_t, opts); 75 | omega = sqrt(M(:, ii)' * M(:, ii) / n); 76 | 77 | t_hat_temp = find(abs(x_t_hat_cs) > omega); 78 | T_hat(t_hat_temp, ii) = 255; 79 | 80 | LS.times = @(x) phi(:, t_hat_temp) * x; 81 | LS.trans = @(y) phi(:, t_hat_temp)' * x; 82 | 83 | %% Estimate signal components 84 | 85 | S_hat(t_hat_temp, ii) = cgls(phi_t(:, t_hat_temp), y_t, 0, 1e-3); 86 | L_hat(:, ii) = M(:, ii) - S_hat(:, ii); 87 | FG(t_hat_temp, ii) = M1(t_hat_temp, ii); 88 | BG(:, ii) = L_hat(:, ii) + mu; 89 | %% Subspace update 90 | if(~mod(ii - 1 , alpha)) 91 | MM = (1 / sqrt(alpha)) * phi.times(L_hat(:, ii - alpha + 1 : ii)); 92 | 93 | if(~ph) %%detect phase 94 | aa = svds(MM, 1); 95 | if(aa >= sqrt(ev_thresh)) 96 | ph = 1; 97 | t_hat = [t_hat, ii]; 98 | k = 0; 99 | end 100 | else %%ppca phase 101 | P_hat_new = proj_PCA_thresh(MM, sqrt(alpha *ev_thresh)); 102 | P_hat = [P_hat_old, P_hat_new]; 103 | phi_t = speye(n) - P_hat * P_hat'; 104 | k = k + 1; 105 | 106 | if(k==K + 1) 107 | P_hat = [P_hat_old, P_hat_new]; 108 | P_hat_old = P_hat; 109 | P_hat_new = []; 110 | k = 1; 111 | ph = 0; 112 | phi_t = speye(n) - P_hat * P_hat'; 113 | end 114 | end 115 | end 116 | 117 | %% Return subspace estimates 118 | if((ii == 0) || (~(mod(ii - 1, alpha)))) 119 | P_track_full{cnt} = P_hat; 120 | P_track_new{cnt} = P_hat_new; 121 | T_calc(cnt) = ii; 122 | cnt = cnt + 1; 123 | end 124 | end 125 | %L_hat = L_hat + repmat(mu, n, 1); 126 | end 127 | 128 | 129 | -------------------------------------------------------------------------------- /ReProCS_PCA.m: -------------------------------------------------------------------------------- 1 | function [L_hat, P_hat, S_hat, T_hat, t_hat, ... 2 | P_track_full, P_track_new, T_calc]= ReProCS_PCA(M, ... 3 | P_init, ev_thresh, alpha, K, omega, outc, K_CS) 4 | %%%This is the automatic version of ReProCS algorithm under the latest 5 | %%%subspace change and support model. 6 | 7 | %This folder contains the code accompanying pre-print. 8 | % 9 | %[1] "New Results for Provable Dynamic Robust PCA", Praneeth Narayanamurthy and Namrata Vaswani, arXiv:1705.08948, 2017. 10 | % 11 | %If you use this code please also cite the following papers 12 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 13 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 14 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 15 | 16 | 17 | %%% Inputs %%% 18 | %%% M - measurement matrix %%% 19 | %%% ev_thres - threshold for subspace change detection %%% 20 | %%% P_init - an initial estimate of the subspace %%% 21 | %%% t_train - the dimension of the training data %%% 22 | 23 | 24 | %%% Algorithm parameters %%% 25 | %%% alpha - frame length %%% 26 | %%% K - number of projection PCA steps %%% 27 | %%% omega - threshold for non-zero value in S %%% 28 | %%% K_CS - number of CoSaMP iterations %%% 29 | %%% outc - an upper bound on estimate of fraction of outliers per column 30 | 31 | %%% Outputs %%% 32 | %%% L_hat - estimate of the low rank matrix %%% 33 | %%% P_hat - estimate of the subspace in which L lies %%% 34 | %%% S_hat - estimate of the sparse signal %%% 35 | %%% t_hat - estimate of subspace change times %%% 36 | 37 | %% Initializations 38 | %thresh = ev_thresh / 2; 39 | [~, r_init] = size(P_init); 40 | P_hat_old = P_init; 41 | P_hat_new = []; 42 | P_hat = [P_hat_old, P_hat_new]; 43 | 44 | [n, t_max] = size(M); 45 | T_hat = zeros(n, t_max); 46 | S_hat = zeros(n, t_max); 47 | L_hat = zeros(n, t_max); 48 | t_hat = []; 49 | 50 | % L_hat(:, 1 : t_train) = M(:, 1 : t_train); 51 | k = 0; 52 | cnt = 1; 53 | phi_t = (eye(n) - P_hat * P_hat'); 54 | % In = eye(n); 55 | ph = 1; %ph - 0 => detect, 1 => ppca 56 | 57 | %% Main Algorithm Loop 58 | for ii = 1 : t_max 59 | %% Estimate support 60 | y_t = M(:, ii) - (P_hat * (P_hat' * M(:, ii))); 61 | DecayRate = 0.9; %other values work, may make it slower 62 | x_t_hat_cs = cosamp_cgls(phi_t, ... 63 | y_t, outc, DecayRate, K_CS, 1e-6); 64 | t_hat_temp = find(abs(x_t_hat_cs) > omega); 65 | % T_hat(t_hat_temp, ii) = 1; 66 | 67 | %% Estimate signal components 68 | % % [S_hat(t_hat_temp, ii), ~] = ... 69 | % % lsqr(phi_t(:, t_hat_temp), y_t, 1e-6, 50); 70 | % S_hat(t_hat_temp, ii) = phi_t(:, t_hat_temp) \ y_t; 71 | S_hat(t_hat_temp, ii) = cgls(phi_t(:, t_hat_temp), y_t, ... 72 | 0, 1e-10, 10); 73 | L_hat(:, ii) = M(:, ii) - S_hat(:, ii); 74 | 75 | 76 | %% Subspace update 77 | if(~mod(ii + 1 , alpha)) 78 | u = (ii + 1) / alpha; 79 | idx = (u-1) * alpha + 1 : u * alpha ; 80 | L_temp = L_hat(:, idx); 81 | 82 | MM = L_temp - (P_hat_old *(P_hat_old' * L_temp)); 83 | 84 | if(~ph) %%detect phase 85 | % phi_t = eye(n) - P_hat * P_hat'; 86 | if(svds(MM, 1) >= sqrt(alpha * ev_thresh)) 87 | ph = 1; 88 | t_hat = [t_hat, ii]; 89 | k = 0; 90 | end 91 | else %%ppca phase 92 | P_hat = simpleEVD((L_hat(:, max(1, ii - alpha + 1) : ii)), r_init); 93 | phi_t = speye(n) - P_hat * P_hat'; 94 | k = k + 1; 95 | 96 | if(k==K + 1) 97 | P_hat_old = P_hat; 98 | k = 1; 99 | ph = 0; 100 | phi_t = speye(n) - P_hat * P_hat'; 101 | end 102 | end 103 | end 104 | 105 | 106 | %% Return subspace 107 | if((ii == 1) || ~(mod(ii + 1, alpha))) 108 | P_track_full{cnt} = P_hat; 109 | P_track_new{cnt} = P_hat_new; 110 | T_calc(cnt) = ii; 111 | cnt = cnt + 1; 112 | end 113 | end 114 | end -------------------------------------------------------------------------------- /ReProCS_pca_real.m: -------------------------------------------------------------------------------- 1 | function [BG, FG, L_hat, S_hat, T_hat, t_hat, ... 2 | P_track_full, T_calc]= ... 3 | ReProCS_pca_real(M1, P_init, mu, ev_thresh, alpha, K) 4 | %%%This is the ReProCS-PCA algorithm. This is the main function for the real video Background- 5 | %%%Foreground separation problem. 6 | 7 | %This folder contains the code accompanying pre-print. 8 | % 9 | %[1] "New Results for Provable Dynamic Robust PCA", Praneeth Narayanamurthy and Namrata Vaswani, arXiv:1705.08948, 2017. 10 | % 11 | %If you use this code please also cite the following papers 12 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 13 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 14 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 15 | 16 | 17 | %%% Inputs %%% 18 | %%% M - measurement matrix %%% 19 | %%% ev_thres - threshold for subspace change detection %%% 20 | %%% P_init - an initial estimate of the subspace %%% 21 | %%% t_train - the dimension of the training data %%% 22 | 23 | 24 | %%% Algorithm parameters %%% 25 | %%% alpha - frame length %%% 26 | %%% mu - column-averages of data %%% 27 | %%% K - number of projection PCA steps %%% 28 | %%% omega - threshold for non-zero value in S %%% 29 | 30 | 31 | %%% Outputs %%% 32 | %%% BG - Estimated Background %%% 33 | %%% FG - Estimated Foreground %%% 34 | %%% L_hat - estimate of the low rank matrix %%% 35 | %%% P_hat - estimate of the subspace in which L lies %%% 36 | %%% S_hat - estimate of the sparse signal %%% 37 | %%% t_hat - estimate of subspace change times %%% 38 | 39 | %% Initializations 40 | 41 | P_hat_old = P_init; 42 | [~, r] = size(P_init); 43 | P_hat = P_hat_old; 44 | 45 | [n, t_max] = size(M1); 46 | T_hat = zeros(n, t_max); 47 | S_hat = zeros(n, t_max); 48 | L_hat = zeros(n, t_max); 49 | 50 | FG = zeros(n, t_max); 51 | BG = zeros(n, t_max); 52 | 53 | t_hat = []; 54 | M = M1 - repmat(mu, 1, t_max); 55 | k = 0; 56 | cnt = 1; 57 | ph = 0; %ph - 0 => detect, 1 => ppca 58 | opts.delta = 0.4; 59 | 60 | phi_t = speye(n) - P_hat * P_hat'; 61 | %% Main Algorithm Loop 62 | for ii = 2 : t_max 63 | %% Estimate support 64 | Atf.times = @(x) x - (P_hat * (P_hat' * x)); 65 | Atf.trans = @(y) y - (P_hat * (P_hat' * y)); 66 | phi.times = @(x) x - (P_hat_old * (P_hat_old' * x)); 67 | y_t = Atf.times(M(:, ii)); 68 | opts.tol = 1e-3; 69 | opts.print = 0; 70 | 71 | opts.delta = norm(Atf.times(L_hat(:, ii - 1))); 72 | 73 | x_t_hat_cs = yall1(Atf, y_t, opts); 74 | omega = sqrt(M(:, ii)' * M(:, ii) / n); 75 | 76 | t_hat_temp = find(abs(x_t_hat_cs) > omega); 77 | T_hat(t_hat_temp, ii) = 255; 78 | 79 | LS.times = @(x) phi(:, t_hat_temp) * x; 80 | LS.trans = @(y) phi(:, t_hat_temp)' * x; 81 | 82 | %% Estimate signal components 83 | 84 | S_hat(t_hat_temp, ii) = cgls(phi_t(:, t_hat_temp), y_t, 0, 1e-3); 85 | L_hat(:, ii) = M(:, ii) - S_hat(:, ii); 86 | FG(t_hat_temp, ii) = M1(t_hat_temp, ii); 87 | BG(:, ii) = L_hat(:, ii) + mu; 88 | %% Subspace update 89 | if(~mod(ii - 1 , alpha)) 90 | MM = (1 / sqrt(alpha)) * phi.times(L_hat(:, ii - alpha + 1 : ii)); 91 | 92 | if(~ph) %%detect phase 93 | aa = svds(MM, 1); 94 | if(aa >= sqrt(ev_thresh)) 95 | ph = 1; 96 | t_hat = [t_hat, ii]; 97 | k = 0; 98 | end 99 | else %%ppca phase 100 | P_hat = simpleEVD((L_hat(:, ii - alpha + 1 : ii)), r); 101 | phi_t = speye(n) - P_hat * P_hat'; 102 | k = k + 1; 103 | 104 | if(k==K + 1) 105 | P_hat_old = P_hat; 106 | k = 1; 107 | ph = 0; 108 | phi_t = speye(n) - P_hat * P_hat'; 109 | end 110 | end 111 | end 112 | 113 | %% Return subspace estimates 114 | if((ii == 0) || (~(mod(ii - 1, alpha)))) 115 | P_track_full{cnt} = P_hat; 116 | %P_track_new{cnt} = P_hat_new; 117 | T_calc(cnt) = ii; 118 | cnt = cnt + 1; 119 | end 120 | end 121 | %L_hat = L_hat + repmat(mu, n, 1); 122 | end -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_1d.m: -------------------------------------------------------------------------------- 1 | function demo_1d(n) 2 | 3 | close all; 4 | if nargin == 0; n = 1024*2; end 5 | m = floor(n/8); k = floor(m/5); 6 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 7 | 8 | % generate xs 9 | db = 40; 10 | xs = getxs(n,k,db); 11 | 12 | % set opts parameters 13 | sigma = 0.01; 14 | digit = 5; if sigma > 0; digit = 3; end 15 | opts.tol = 5*10^(-digit); 16 | 17 | % Used by all three kinds 18 | p = randperm(n); 19 | picks = sort(p(1:m)); picks(1) = 1; 20 | noise = sigma*randn(m,1); 21 | perm = randperm(n); 22 | Mtype = {' pdct','pdwht',' pdft'}; 23 | 24 | % call solver 25 | 26 | for j = 1:2 27 | 28 | opts.rho = (j-1)*5e-4; 29 | t0 = cputime; 30 | for k = 1:3 31 | op_A = eval(['@' Mtype{k} '_operator']); 32 | A = feval(op_A,picks,perm); 33 | b = A.times(xs) + noise; 34 | [x,Out] = yall1(A, b, opts); 35 | x = real(x); rerr = norm(x-xs)/norm(xs); 36 | Mat = upper(Mtype{k}); 37 | fprintf([Mat ': iter %4i Rel_err = %6.2e\n'],... 38 | Out.iter,rerr); 39 | end 40 | fprintf(' rho = %4.1e, CPU %6.2f sec.\n\n',... 41 | opts.rho,cputime-t0); 42 | 43 | end 44 | 45 | 46 | %%%%%%%%%%%%%%%%%%%%%%%%%%% 47 | function xs = getxs(n,k,db) 48 | % generate xs with range db 49 | 50 | xs = zeros(n,1); 51 | p = randperm(n); 52 | nz = rand(k,1); 53 | zmin = min(nz); 54 | zmax = max(nz); 55 | r = 10^(db/10); 56 | s = (zmax - r*zmin)/(r-1); 57 | nz = sign(randn(k,1)).*(nz + s); 58 | xs(p(1:k)) = db*nz; 59 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_2d.m: -------------------------------------------------------------------------------- 1 | function demo_2d(imgsize) 2 | 3 | % Tests on 2D data: phantom images 4 | % Requires Image Processing Toolbox 5 | 6 | if nargin == 0; imgsize = 256; end 7 | 8 | xsize = [imgsize imgsize]; 9 | n = prod(xsize); 10 | m = floor(.66*n); 11 | 12 | % generate xs 13 | Img = phantom(imgsize); 14 | xs = Img(:); 15 | k = sum(xs ~= 0); 16 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 17 | 18 | % noise and picks 19 | sigma = 0.00; 20 | noise = sigma*randn(m,1); 21 | p = randperm(n); 22 | picks = sort(p(1:m)); picks(1) = 1; 23 | perm = randperm(n); 24 | 25 | % set options 26 | digit = 3; 27 | opts.tol = 2*10^(-digit); 28 | Mtype = {' pdct','pdwht',' pdft'}; 29 | 30 | %opts.nonorth = 1; 31 | for j = 1:2 32 | 33 | figure(j) 34 | opts.rho = (j-1)*1e-5; 35 | subplot(221); set(gca,'fontsize',16); 36 | imshow(reshape(xs,xsize),[]); title('Original'); 37 | 38 | t0 = cputime; 39 | for k = 1:3 40 | op_handle = ['@' Mtype{k} '_operator']; 41 | A = feval(eval(op_handle),picks,perm); 42 | b = A.times(xs) + noise; 43 | [x,Out] = yall1(A, b, opts); 44 | x = real(x); rerr = norm(x-xs)/norm(xs); 45 | Mat = upper(Mtype{k}); 46 | fprintf([Mat ': iter %3i Rel_err = %6.2e\n'],... 47 | Out.iter,rerr); 48 | subplot(221+k); set(gca,'fontsize',16); 49 | imshow(reshape(x,xsize),[]); title(Mat); 50 | end 51 | fprintf(' rho = %4.1e, CPU %6.2f sec.\n\n',... 52 | opts.rho,cputime-t0); 53 | 54 | end 55 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_2dw.m: -------------------------------------------------------------------------------- 1 | function demo_2dw(imgsize) 2 | 3 | % Tests on 2D phantom images with wavelet basis 4 | % Requires Image Processing and wavelet Toolboxes 5 | 6 | if nargin == 0; imgsize = 256; end 7 | 8 | xsize = [imgsize imgsize]; 9 | n = prod(xsize); 10 | m = floor(.5*n); 11 | sigma = 0.005; 12 | 13 | % generate xs 14 | ph = phantom(imgsize); 15 | xs = ph(:); 16 | k = sum(xs ~= 0); 17 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 18 | 19 | p = randperm(n); 20 | picks = sort(p(1:m)); picks(1) = 1; 21 | noise = sigma*randn(m,1); 22 | perm = randperm(n); 23 | 24 | % set options 25 | digit = 4; if sigma > 0; digit = 2; end 26 | opts.tol = 2*10^(-digit); 27 | 28 | if exist('wavedec2','file') 29 | opts.basis = wavelet_basis(xsize); 30 | Mtype = {' pdct','pdwht'}; 31 | else 32 | disp('Wavelet not available, using DCT.') 33 | opts.basis.times = @(x)reshape( dct2(reshape(x,xsize)),numel(xs),1); 34 | opts.basis.trans = @(x)reshape(idct2(reshape(x,xsize)),numel(xs),1); 35 | Mtype = {' pdft','pdwht'}; 36 | end 37 | 38 | for j = 1:2 39 | 40 | opts.rho = (j-1)*1e-3; 41 | fprintf('--- rho = %g ---\n',opts.rho) 42 | figure(j) 43 | 44 | % Original Image 45 | 46 | subplot(1,3,1); set(gca,'fontsize',16); 47 | imshow(reshape(xs,xsize),[]); title('Original'); 48 | xlabel([int2str(imgsize) ' x ' int2str(imgsize)]); 49 | 50 | t0 = cputime; 51 | for k = 1:length(Mtype) 52 | op_A = eval(['@' Mtype{k} '_operator']); 53 | A = feval(op_A,picks,perm); 54 | b = A.times(xs) + noise; 55 | [x,Out] = yall1(A,b,opts); 56 | x = real(x); rerr = norm(x-xs)/norm(xs); 57 | Mat = upper(Mtype{k}); 58 | fprintf([Mat ': iter %i Rel_err = %6.2e\n'],... 59 | Out.iter,rerr); 60 | subplot(1,3,1+k); set(gca,'fontsize',16); 61 | imshow(reshape(x,xsize),[]); title(Mat); 62 | xlabel([int2str(m/n*100) '% data']); 63 | end 64 | fprintf('*CPU*: %6.2f sec.\n',cputime-t0); 65 | 66 | end 67 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_L1L2.m: -------------------------------------------------------------------------------- 1 | % solve the L1/L2 model and compare with l1_ls 2 | % edit the following line to access l1_ls 3 | addpath(genpath('/Users/yin/Documents/matlab/l1_ls_matlab/')); 4 | clear 5 | n = 400; 6 | m = floor(.4*n); 7 | k = floor(.2*m); 8 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 9 | 10 | % generate (A,b,xs) 11 | sigma = 0.5; 12 | A = randn(m,n); 13 | xs = zeros(n,1); 14 | p = randperm(n); 15 | xs(p(1:k)) = 2*(rand(k,1) > 0.5) - 1; 16 | b = A*xs + sigma*randn(m,1); 17 | 18 | % orthogonalize rows of A 19 | opts.nonorth = randn > 0; 20 | fprintf('nonorth = %i\n',opts.nonorth); 21 | if opts.nonorth; 22 | d = 1./sqrt(sum(A.^2,2)); 23 | A = sparse(1:m,1:m,d)*A; 24 | b = b.*d; 25 | else 26 | [Q, R] = qr(A',0); 27 | A = Q'; b = R' \ b; 28 | end 29 | rho = 1e-3; 30 | 31 | % call YALL1 32 | disp('--- YALL1 ---'); 33 | opts.tol = 1e-3; opts.rho = rho; 34 | tic; [x1,Out] = yall1(A, b, opts); toc 35 | 36 | % call l1_ls 37 | disp('--- l1_ls ---'); 38 | if ~exist('l1_ls','file'); error('Solver l1_ls is not found.'); end 39 | tic; x2 = l1_ls(A, b, 2*rho, opts.tol, 1); toc 40 | 41 | dx12 = norm(x1-x2)/norm(x1); 42 | fprintf('Diff. of the two: %6.4e\n\n',dx12) 43 | 44 | set(gca,'fontsize',18) 45 | plot(1:n,x1,'bo',1:n,x2,'r.',1:n,xs,'k*'); 46 | legend('YALL1','l1-ls','Exact') 47 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_L1L2con.m: -------------------------------------------------------------------------------- 1 | % solve the L1/L2con model and compare with SPGL1 2 | % edit the following line to access SPGL1 3 | 4 | addpath(genpath('/Users/yin/Documents/matlab/spgl1-1.7/')); 5 | clear; 6 | 7 | n = 1000; 8 | m = round(.2*n); 9 | k = round(.25*m); 10 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 11 | 12 | % generate (A,b,xs) 13 | A = randn(m,n); 14 | xs = zeros(n,1); 15 | p = randperm(n); 16 | xs(p(1:k)) = 4*(rand(k,1)>.5) - 2; 17 | % nonnegative signal 18 | xs = abs(xs); 19 | 20 | sigma = 0.001; 21 | noise = sigma*randn(m,1); 22 | b = A*xs + noise; 23 | delta = norm(noise); 24 | fprintf('sigma = %6.3e, delta = %6.3e\n\n',sigma,delta); 25 | 26 | if all(xs >= 0); J = [1 0]; else J = 0; end 27 | % orthogonalize rows of A 28 | [Q, R] = qr(A',0); 29 | A = Q'; b = R' \ b; 30 | 31 | % call YALL1 32 | disp('--- YALL1 ---'); 33 | opts.tol = 1e-3; 34 | opts.delta = delta; 35 | opts.print = 1; 36 | for j = J 37 | opts.nonneg = j; fprintf('nonneg set to %i\n',j); 38 | tic; [x1,Out] = yall1(A, b, opts); toc 39 | fprintf('||Ax-b|| = %6.3e: ||x||_1 = %6.3e\n',... 40 | norm(A*x1-b), norm(x1,1)); 41 | rerr = norm(x1-xs)/norm(xs); 42 | fprintf('[nA,nAt]=[%i,%i]: Rel_err = %6.2e\n\n',... 43 | Out.cntA,Out.cntAt,rerr); 44 | end 45 | 46 | % call SPGL1 47 | disp('--- SPGL1 ---'); 48 | if ~exist('spgSetParms','file'); error('Solver SPGL1 is not found.'); end 49 | spg_opts = spgSetParms('verbosity',0,'optTol',opts.tol); 50 | tic; [x2,r,g,info] = spgl1(A,b,0,delta,[],spg_opts); toc 51 | fprintf('||Ax-b|| = %6.3e: ||x||_1 = %6.3e\n',... 52 | norm(A*x2-b), norm(x2,1)); 53 | rerr = norm(x2-xs)/norm(xs); 54 | fprintf('[nA,nAt]=[%i,%i]: Rel_err = %6.2e\n\n',... 55 | info.nProdA,info.nProdAt,rerr); 56 | 57 | dx12 = norm(x1-x2)/norm(x1); 58 | fprintf('Diff. of last two: %6.2e\n\n',dx12) 59 | 60 | % 61 | figure; set(gca,'fontsize',12) 62 | plot(1:n,x1,'b.',1:n,x2,'ro',1:n,xs,'k*'); 63 | legend('YALL1','SPGL1','Exact') 64 | %} -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_all.m: -------------------------------------------------------------------------------- 1 | close all 2 | demo_1d 3 | demo_2d 4 | demo_2dw 5 | demo_rand 6 | demo_hard 7 | demo_L1L2 8 | demo_nonneg 9 | demo_complex 10 | demo_weights 11 | demo_L1L2con 12 | demo_dB 13 | pause(2) 14 | close all 15 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_complex.m: -------------------------------------------------------------------------------- 1 | function demo_complex(n) 2 | 3 | % test solver for complex BP 4 | 5 | close all; 6 | 7 | opts.nonorth = 1; 8 | if nargin == 0; 9 | if opts.nonorth; n = 1200; else n = 1024*16; end 10 | end 11 | m = floor(n/4); k = floor(m/4); 12 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 13 | 14 | % generate xs 15 | xs = zeros(n,1); 16 | p = randperm(n); p = p(1:k); 17 | xs(p) = randn(k,1) + 1i*randn(k,1); 18 | 19 | % generate partial DFT data 20 | p = randperm(n); 21 | picks = sort(p(1:m)); picks(1) = 1; 22 | perm = 1:n; % column permutations allowable 23 | 24 | if opts.nonorth 25 | A = randn(m,n) + 1i*randn(m,n); 26 | d = 1./sqrt(sum(abs(A).^2)); 27 | A = A*sparse(1:n,1:n,d); 28 | b = A*xs; 29 | else 30 | A = pdft_operator(picks,perm); 31 | b = A.times(xs); 32 | end 33 | 34 | % add noise 35 | sigma = norm(b,inf)*0.001; % noise std 36 | noise = randn(m,1) + 1i*randn(m,1); 37 | b = b + sigma*noise; 38 | 39 | % set solver options 40 | digit = 6; if sigma > 0; digit = 3; end 41 | opts.tol = 5*10^(-digit); 42 | plotting = 1; 43 | 44 | for j = 1:2 45 | 46 | opts.rho = (j-1)*1e-3; 47 | fprintf('--- rho = %g ---\n',opts.rho); 48 | % call solver 49 | tic; [x,Out] = yall1(A, b, opts); toc 50 | rerr = norm(x-xs)/norm(xs); 51 | fprintf('iter %4i Rel_err = %6.2e\n',Out.iter,rerr); 52 | 53 | % plot 54 | if plotting 55 | figure(j); 56 | subplot(211); set(gca,'fontsize',16) 57 | plot(1:n,real(xs),'ro',1:n,real(x),'b.'); 58 | title('Real Part') 59 | subplot(212); set(gca,'fontsize',16) 60 | plot(1:n,imag(xs),'ro',1:n,imag(x),'b.'); 61 | title('Imag Part') 62 | end 63 | 64 | end 65 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_dB.m: -------------------------------------------------------------------------------- 1 | clear 2 | 3 | n = 64^2; % signal length 4 | m = n/4; % number of measurements 5 | k = m/8; % number of nonzeros 6 | 7 | Dyna = 100:50:300; 8 | 9 | for dyna = Dyna 10 | 11 | % random signal with dyna-dB dynamic range 12 | valx = dyna/20*rand(k,1); 13 | valx = valx - min(valx); 14 | valx = valx/max(valx)*dyna/20; 15 | xs = zeros(n,1); p = randperm(n); 16 | xs(p(1:k)) = 10.^valx.*sign(randn(k,1)); 17 | 18 | l1_opt = norm(xs,1); 19 | fprintf('dyna = %g, |x*|_1 = %6.3e\n',dyna,l1_opt); 20 | 21 | % partial dct measurement matrix 22 | Omega = randperm(n); 23 | Omega = Omega(1:m); 24 | Omega = sort(Omega); 25 | op_A = @pdct_operator; 26 | A = feval(op_A,Omega,1:n); 27 | 28 | % observations 29 | b = A.times(xs); 30 | 31 | opts.tol = eps; opts.maxit = 1000; 32 | tic, [x,Out] = yall1(A, b, opts); toc 33 | fprintf('Iter: %i\n',Out.iter) 34 | fprintf('Abs. Ax-b Residual: %6.3e\n',norm(A.times(x)-b)); 35 | fprintf('Abs. solution error: %6.3e\n',norm(x-xs)); 36 | fprintf('Rel. Ax-b Residual: %6.3e\n',norm(A.times(x)-b)/norm(b)); 37 | fprintf('Rel. solution error: %6.3e\n\n',norm(x-xs)/norm(xs)); 38 | 39 | end 40 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_hard.m: -------------------------------------------------------------------------------- 1 | % Two ``hard'' problems 2 | % prob 1: 150 nonzeros 3 | % prob 2: 8 nonzeros 4 | 5 | if ~exist('hard150.mat','file') || ~exist('hard8nz.mat','file') 6 | error('Data files hard150.mat and hard8nz.mat are not found. Please download them from the YALL1 website.'); 7 | end 8 | 9 | % edit the following line to access SPGL1 10 | addpath(genpath('/Users/yin/Documents/matlab/spgl1-1.7/')); 11 | % edit the following line to access hard150 and hard8nz 12 | addpath(genpath('/Users/yin/1st/matlab/YALL1/working/TestProbs/')); 13 | 14 | clear 15 | for prob = 1:2 16 | 17 | switch prob 18 | case 1; 19 | load hard150; 20 | case 2; 21 | load hard8nz; 22 | [Q,R] = qr(A',0); 23 | A = Q'; b = R'\b; 24 | clear Q R; 25 | end 26 | 27 | [m,n] = size(A); k = sum(xs ~= 0); 28 | fprintf('\n*** Prob %i: size [n,m,k] = [%i,%i,%i]\n',prob,n,m,k); 29 | 30 | % call yall1 solver 31 | disp('--- YALL1 ---'); 32 | opts.tol = 1e-5; 33 | opts.rho = 1e-5; 34 | opts.maxit = 3000; 35 | opts.mu = 1/prob; 36 | tic; [x,Out] = yall1(A, b, opts); toc; 37 | rerr = norm(x-xs)/norm(xs); 38 | fprintf('Iter %i: Rel_err = %6.2e\n',Out.iter,rerr); 39 | fprintf('||x||_1 = %g\n',norm(x,1)); 40 | %close all; plot(1:n,xs,'ro',1:n,x,'b.'); drawnow 41 | 42 | if exist('spgl1','file') 43 | disp('--- SPGL1 ---'); 44 | spg_opts = spgSetParms('verbosity',0,'bpTol',opts.tol); 45 | tic; [x,r,g,info] = spgl1(A, b, 0, 0, [], spg_opts); toc 46 | rerr = norm(x-xs)/norm(xs); 47 | fprintf('[nA,nAt]=[%i,%i]: Rel_err = %6.2e\n',... 48 | info.nProdA,info.nProdAt,rerr); 49 | fprintf('||x||_1 = %g\n',norm(x,1)); 50 | end 51 | fprintf('\n') 52 | 53 | end 54 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_nonneg.m: -------------------------------------------------------------------------------- 1 | % solve the L1/L2 model with nonnegativity and compare with l1_ls 2 | % edit the following line to access l1_ls 3 | addpath(genpath('/Users/yin/Documents/matlab/l1_ls_matlab/')); 4 | clear 5 | n = 1000; 6 | m = floor(.3*n); 7 | k = floor(.2*m); 8 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 9 | 10 | % generate (A,b,xs) 11 | A = randn(m,n); 12 | d = 1./sqrt(sum(A.^2)); 13 | A = A*sparse(1:n,1:n,d); 14 | xs = zeros(n,1); 15 | p = randperm(n); 16 | xs(p(1:k)) = 1; %rand(k,1); 17 | b = A*xs; 18 | 19 | % orthogonalize rows of A 20 | opts.nonorth = 0; 21 | if ~opts.nonorth; 22 | [Q, R] = qr(A',0); 23 | A = Q'; b = R'\b; 24 | end 25 | 26 | % call YALL1 27 | opts.tol = 1e-6; 28 | opts.nonneg = 1; 29 | disp('--- YALL1: BP'); 30 | tic; [x,Out] = yall1(A, b, opts); toc 31 | fprintf('iter: %4i, rel_err = %6.2e\n',... 32 | Out.iter,norm(x-xs)/norm(xs)); 33 | 34 | disp('--- YALL1: L1/L1 (with wrong b)'); 35 | j = 3; 36 | b(end-j:end) = -b(end-j:end); % wrong b 37 | opts.nu = .5; 38 | tic; [x,Out] = yall1(A, b, opts); toc 39 | fprintf('iter: %4i, rel_err = %6.2e\n',... 40 | Out.iter,norm(x-xs)/norm(xs)); 41 | b(end-j:end) = -b(end-j:end); % restore b 42 | 43 | sigma = .01; 44 | rho = 1e-2; 45 | tol = 1e-8; 46 | 47 | disp('--- YALL1: L1L2'); 48 | b = b + sigma*randn(m,1); 49 | opts.tol = tol; 50 | opts.nu = 0; 51 | opts.rho = rho; 52 | tic; [x1,Out] = yall1(A, b, opts); toc 53 | 54 | % call l1_ls 55 | disp('--- l1_ls'); 56 | if ~exist('l1_ls_nonneg','file'); error('Solver l1_ls_nonneg is not found.'); end 57 | tic; x2 = l1_ls_nonneg(A, b, 2*rho, tol, 1); toc 58 | 59 | fprintf('f_yall = %9.4f\n',norm(x1)+norm(A*x1-b)^2/2/rho); 60 | fprintf('f_l1ls = %9.4f\n',norm(x2)+norm(A*x2-b)^2/2/rho); 61 | fprintf('Rel_dist: %6.4e\n\n',norm(x1-x2)/norm(x1)) 62 | 63 | set(gca,'fontsize',18) 64 | plot(1:n,x1,'bo',1:n,x2,'r.',1:n,xs,'k*'); 65 | legend('YALL1','l1-ls','Exact','location','best') 66 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_rand.m: -------------------------------------------------------------------------------- 1 | function demo_rand(n) 2 | 3 | % Test on rand problems with Gaussian matrices 4 | % Data can contain white or impulsive noise or both 5 | 6 | % uncomment and edit the following line to run SPGL1 7 | %addpath(genpath('/Users/yin/Documents/matlab/spgl1-1.7/')); 8 | 9 | if nargin == 0; n = 1000; end 10 | m = floor(0.3*n); 11 | k = floor(0.2*m); 12 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 13 | 14 | % generate A, b, xs 15 | sigma = 0.00; % white noise std 16 | perc = 0; % impulsive noise percentage 17 | nonorth = 1; 18 | [A,b,xs] = gen_data(m,n,k,sigma,perc,nonorth); 19 | 20 | % call solver 21 | digit = 6; if sigma > 0; digit = 3; end 22 | opts.tol = 5*10^(-digit); 23 | opts.print = 0; 24 | opts.nonorth = nonorth; 25 | disp('--- YALL1: BP'); 26 | opts.nu = 0; 27 | opts.rho = 0; 28 | tic; [x,Out] = yall1(A,b,opts); toc 29 | rerr = norm(x-xs)/norm(xs); 30 | fprintf('Iter %4i: Rel_err = %6.2e\n\n',Out.iter,rerr); 31 | 32 | disp('--- YALL1: L1/L1'); 33 | opts.nu = .5; 34 | opts.rho = 0; 35 | tic; [x,Out] = yall1(A,b,opts); toc 36 | rerr = norm(x-xs)/norm(xs); 37 | fprintf('Iter %4i: Rel_err = %6.2e\n\n',Out.iter,rerr); 38 | 39 | disp('--- YALL1: L1/L2'); 40 | opts.nu = 0; 41 | opts.rho = 1e-3; 42 | tic; [x,Out] = yall1(A,b,opts); toc 43 | rerr = norm(x-xs)/norm(xs); 44 | fprintf('Iter %4i: Rel_err = %6.2e\n\n',Out.iter,rerr); 45 | 46 | if exist('spgl1','file') 47 | disp('--- SPGL1:'); 48 | spg_opts = spgSetParms('verbosity',0,'bpTol',opts.tol); 49 | tic; [x,~,~,info] = spgl1(A, b, 0, 0, [], spg_opts); toc 50 | rerr = norm(x-xs)/norm(xs); 51 | fprintf('[nA,nAt]=[%i,%i]: Rel_err = %6.2e\n\n',... 52 | info.nProdA,info.nProdAt,rerr); 53 | end 54 | 55 | 56 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 | function [A,b,xs] = gen_data(m,n,k,sigma,perc,nonorth) 58 | 59 | A = randn(m,n); 60 | d = 1./sqrt(sum(A.^2)); 61 | A = A*sparse(1:n,1:n,d); 62 | xs = zeros(n,1); 63 | p = randperm(n); 64 | xs(p(1:k)) = randn(k,1); 65 | b = A*xs; 66 | if ~nonorth 67 | [Q,R] = qr(A',0); 68 | A = Q'; b = R'\b; 69 | end 70 | 71 | % white noise 72 | white = sigma*randn(m,1); 73 | b = b + white; 74 | 75 | % impulsive noise 76 | p = randperm(m); 77 | L = floor(m*perc/100); 78 | b(p(1:L)) = 2*(rand(L,1) > 0) - 1; 79 | -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/demo_weights.m: -------------------------------------------------------------------------------- 1 | function demo_weights(n) 2 | 3 | % Test weighted 1-norm on rand problems 4 | % with Gaussian matrices 5 | 6 | if nargin == 0; n = 1000; end 7 | 8 | m = floor(0.3*n); 9 | k = floor(0.4*m); 10 | fprintf('\nSize [n,m,k] = [%i,%i,%i]\n',n,m,k); 11 | 12 | % generate A, b, xs 13 | sigma = 0.001; % noise std 14 | opts.nonorth = 1; 15 | [A,b,xs,w] = gen_data(m,n,k,sigma,opts.nonorth); 16 | 17 | % set options 18 | digit = 6; if sigma > 0; digit = 3; end 19 | opts.tol = 10^(-digit); 20 | opts.weights = w; 21 | opts.print = 0; 22 | 23 | % call solver 24 | disp('--- BP:') 25 | tic; [x,Out] = yall1(A,b,opts); toc 26 | rerr = norm(x-xs)/norm(xs); 27 | fprintf('Iter %4i: Rel_err = %6.2e\n',Out.iter,rerr); 28 | 29 | disp('--- L1L1:') 30 | opts.nu = .5; 31 | tic; [x,Out] = yall1(A,b,opts); toc 32 | rerr = norm(x-xs)/norm(xs); 33 | fprintf('Iter %4i: Rel_err = %6.2e\n',Out.iter,rerr); 34 | 35 | disp('--- L1L2:') 36 | opts.nu = 0; opts.rho = 1e-3; 37 | tic; [x,Out] = yall1(A,b,opts); toc 38 | rerr = norm(x-xs)/norm(xs); 39 | fprintf('Iter %4i: Rel_err = %6.2e\n',Out.iter,rerr); 40 | 41 | 42 | 43 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 44 | function [A,b,xs,w] = gen_data(m,n,k,sigma,nonorth) 45 | 46 | A = randn(m,n); 47 | d = 1./sqrt(sum(A.^2)); 48 | A = A*sparse(1:n,1:n,d); 49 | xs = zeros(n,1); 50 | p = randperm(n); 51 | xs(p(1:k)) = randn(k,1); 52 | b = A*xs; 53 | if ~nonorth 54 | [Q,R] = qr(A',0); 55 | A = Q'; b = R'\b; 56 | end 57 | b = b + sigma*randn(m,1); 58 | 59 | % weights 60 | w = ones(n,1); 61 | pk = randperm(k); 62 | iw0 = p(pk(1:floor(k/2))); 63 | w(iw0) = 0; -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/hard150.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/YALL1_v1.4/Demos/hard150.mat -------------------------------------------------------------------------------- /YALL1_v1.4/Demos/hard8nz.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/YALL1_v1.4/Demos/hard8nz.mat -------------------------------------------------------------------------------- /YALL1_v1.4/Readme.txt: -------------------------------------------------------------------------------- 1 | YALL1: Your ALgorithms for L1 2 | 3 | Version 1.4 4 | 5 | COPYRIGHT (c) 2010 Yin Zhang, Junfeng Yang, and Wotao Yin. 6 | 7 | YALL1 is distributed under the terms of the GNU General Public License 3.0. 8 | 9 | http://www.gnu.org/copyleft/gpl.html 10 | 11 | Permission to use, copy, modify, and distribute this software for 12 | any purpose without fee is hereby granted, provided that this entire 13 | notice is included in all copies of any software which is or includes 14 | a copy or modification of this software and in all copies of the 15 | supporting documentation for such software. 16 | This software is being provided "as is", without any express or 17 | implied warranty. In particular, the authors do not make any 18 | representation or warranty of any kind concerning the merchantability 19 | of this software or its fitness for any particular purpose. 20 | 21 | -------------------------------------------------------------------------------- 22 | 23 | First run "Run_me_1st" from this directory. Then, you can try 24 | any of the demo files, but in order to run the 3rd-party codes 25 | SPGl1 and l1_ls (provided you already installed them), you will 26 | need to edit relevant demo files. 27 | 28 | In order to run demo_hard.m, you need to download from the 29 | YALL1 site the 2 data files: hard150.mat and hard8nz.mat, and 30 | put them in the same folder or the search path. 31 | 32 | In order to use the discrete Walsh-Hadamard transform, the script 33 | Run_Me_1st.m will try to "mex" the file fastWHtrans.cpp in the 34 | Utilities directory, which will require a relevant compiler 35 | installed on your system. 36 | -------------------------------------------------------------------------------- /YALL1_v1.4/Run_Me_1st.m: -------------------------------------------------------------------------------- 1 | path(path,genpath(pwd)) 2 | % if exist('fWHtrans','file') ~= 3 3 | % cd Utilities; 4 | % mex -O fWHtrans.cpp 5 | % cd ..; 6 | % end 7 | disp('Welcome to YALL1') 8 | -------------------------------------------------------------------------------- /YALL1_v1.4/Utilities/fWHtrans.cpp: -------------------------------------------------------------------------------- 1 | /*================================================================= 2 | * 3 | * \file fWHtrans.cpp 4 | * 5 | * 6 | * This code computes the (real) fast discrete Walsh-Hadamard transform with sequency order according to the K.G. Beauchamp's book -- Applications of Walsh and Related Functions. 7 | * 8 | * 9 | * This file is written by Chengbo Li from Computational and Applied Mathematics Department of Rice University. 10 | * 11 | * 12 | * This is a MEX-file for MATLAB. 13 | * 14 | * 02/15/2010 15 | * 16 | *=================================================================*/ 17 | #include 18 | #include "mex.h" 19 | #include "matrix.h" 20 | //#include 21 | //#include 22 | // #include 23 | // #include 24 | 25 | 26 | //! Matlab entry function 27 | /*! 28 | * \param nlhs number of left-hand-side output arguments 29 | * \param plhs mxArray of output arguments 30 | * \param nrhs number of right-hand-side input arguments 31 | * \param prhs mxArray of input arguments 32 | */ 33 | void mexFunction( int nlhs, mxArray *plhs[], 34 | int nrhs, const mxArray*prhs[] ) 35 | 36 | { 37 | int p, nStage, L, clm; 38 | int i, j, m, n, N, J, K, M; 39 | double *v_in, *v_out, *v_ext, *v_final, *temp; 40 | 41 | /* Check for proper number of arguments */ 42 | if (nrhs != 1) { 43 | mexErrMsgTxt("Only one input arguments required."); 44 | } 45 | else if (nlhs > 1) { 46 | mexErrMsgTxt("Too many output arguments."); 47 | } 48 | 49 | /* Get the size and pointers to input data. */ 50 | m = mxGetM(prhs[0]); 51 | n = mxGetN(prhs[0]); 52 | 53 | 54 | /* Make sure that both input and output vectors have the length with 2^p where p is some integer. */ 55 | p = (int)ceil(log2(m)); 56 | N = 1< 0 7 | % picks = sub-vector of a permutation of 1:n 8 | % Output: 9 | % A = struct of 2 fields 10 | % 1) A.times: A*x 11 | % 2) A.trans: A'*y 12 | 13 | if exist('dct','file') 14 | DCT = @dct; IDCT = @idct; 15 | elseif exist('dct2','file') 16 | DCT = @dct2; IDCT = @idct2; 17 | else 18 | error('DCT functions not found'); 19 | end 20 | 21 | A.times = @(x) pdct_n2m( DCT,x,picks,perm); 22 | A.trans = @(y) pdct_m2n(IDCT,y,picks,perm); 23 | 24 | 25 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 26 | function y = pdct_n2m(DCT,x,picks,perm) 27 | 28 | % Calculate y = A*x, 29 | % where A is m x n, and consists of m rows of the 30 | % n by n discrete-cosine transform (DCT) matrix 31 | % with columns permuted by perm. 32 | % The row indices are stored in picks. 33 | 34 | x = x(:); 35 | tx = DCT(x(perm)); 36 | y = tx(picks); 37 | 38 | 39 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 40 | function x = pdct_m2n(IDCT,y,picks,perm) 41 | 42 | % Calculate x = A'*y, 43 | % where A is m x n, and consists of m rows of the 44 | % n by n inverse discrete-cosine transform (IDCT) 45 | % matrix with columns permuted by perm. 46 | % The row indices are stored in picks. 47 | 48 | n = length(perm); 49 | tx = zeros(n,1); 50 | tx(picks) = y; 51 | x = zeros(n,1); 52 | x(perm) = IDCT(tx); 53 | -------------------------------------------------------------------------------- /YALL1_v1.4/Utilities/pdft_operator.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | function A = pdft_operator(picks,perm) 3 | 4 | % Define A*x and A'*y for a partial DFT matrix A 5 | % Input: 6 | % n = interger > 0 7 | % picks = sub-vector of a permutation of 1:n 8 | % Output: 9 | % A = struct of 2 fields 10 | % 1) A.times: A*x 11 | % 2) A.trans: A'*y 12 | 13 | A.times = @(x) pdft_n2m(x,picks,perm); 14 | A.trans = @(y) pdft_m2n(y,picks,perm); 15 | 16 | 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | function y = pdft_n2m(x,picks,perm) 19 | 20 | % Calculate y = A*x, 21 | % where A is m x n, and consists of m rows of the 22 | % n by n discrete-Fourier transform (FFT) matrix. 23 | % The row indices are stored in picks. 24 | 25 | x = x(:); 26 | n = length(x); 27 | tx = fft(x(perm))/sqrt(n); 28 | y = tx(picks); 29 | 30 | 31 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 32 | function x = pdft_m2n(y,picks,perm) 33 | 34 | % Calculate x = A'*y, 35 | % where A is m x n, and consists of m rows of the 36 | % n by n inverse discrete-Fourier transform (IFFT) 37 | % matrix. The row indices are stored in picks. 38 | 39 | n = length(perm); 40 | tx = zeros(n,1); 41 | tx(picks) = y; 42 | x = zeros(n,1); 43 | x(perm) = ifft(tx)*sqrt(n); 44 | -------------------------------------------------------------------------------- /YALL1_v1.4/Utilities/pdwht_operator.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | function A = pdwht_operator(picks,perm) 3 | 4 | % Define A*x and A'*y for a partial DWHT matrix A 5 | % Input: 6 | % n = interger of a power of 2 7 | % picks = sub-vector of a permutation of 1:n 8 | % Output: 9 | % A = struct of 2 fields 10 | % 1) A.times: A*x 11 | % 2) A.trans: A'*y 12 | 13 | A.times = @(x) pfwht_n2m(x,picks,perm); 14 | A.trans = @(y) pfwht_m2n(y,picks,perm); 15 | 16 | 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | function y = pfwht_n2m(x,picks,perm) 19 | 20 | % Calculate y = A*x, 21 | % where A is m x n, and consists of m rows of the 22 | % n by n discrete-Walsh-Hadamard transform matrix 23 | % with permuted columns by perm. 24 | % The row indices are stored in picks. 25 | 26 | x = x(:); 27 | n = length(x); 28 | tx = fWHtrans(x(perm))*sqrt(n); 29 | y = tx(picks); 30 | 31 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 32 | function x = pfwht_m2n(y,picks,perm) 33 | 34 | % Calculate x = A'*y, 35 | % where A is m x n, and consists of m rows of the 36 | % n by n discrete-Walsh-Hadamard transform matrix 37 | % with permuted columns by perm. 38 | % The row indices are stored in picks. 39 | 40 | n = length(perm); 41 | tx = zeros(n,1); 42 | tx(picks) = y/sqrt(n); 43 | x = zeros(n,1); 44 | x(perm) = ifWHtrans(tx); 45 | -------------------------------------------------------------------------------- /YALL1_v1.4/Utilities/snr.m: -------------------------------------------------------------------------------- 1 | function SNR = snr(sig, ref) 2 | % Compute Signal-to-Noise Ratio for signal 3 | % relative to a reference 4 | % 5 | % Usage: 6 | % SNR = snr(sig, ref) -- 1st time or 7 | % SNR = snr(sig) -- afterwards 8 | % 9 | % Input: 10 | % sig signal 11 | % ref Reference 12 | % 13 | % Output: 14 | % SNR SNR value 15 | 16 | persistent ref_sav ref_var 17 | 18 | if nargin == 2 19 | ref_sav = ref; 20 | ref_var = var(ref(:),1); 21 | end 22 | 23 | mse = mean((ref_sav(:)-sig(:)).^2); 24 | SNR = 10*log10(ref_var/mse); 25 | -------------------------------------------------------------------------------- /YALL1_v1.4/Utilities/wavelet_basis.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | function W = wavelet_basis(xsize) 3 | 4 | % Define W*x and W'*y for a wavelet transform W 5 | % Input: 6 | % xsize = a vector of 2 positive integers 7 | % Output: 8 | % W = struct of 2 fields 9 | % 1) W.times: W*x 10 | % 2) W.trans: W'*y 11 | 12 | W.times = @(x) Wavedb1(x,xsize,0); 13 | W.trans = @(x) Wavedb1(x,xsize,1); 14 | 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | function y = Wavedb1(x,xsize,trans) 17 | persistent s; 18 | level = 2; 19 | wname = 'db1'; 20 | 21 | if ~trans; % W*X 22 | [Y,s] = wavedec2(reshape(x,xsize),level,wname); 23 | else % W'*X 24 | if ~exist('s','var') 25 | [~,s] = wavedec2(reshape(x,xsize),level,wname); 26 | end 27 | Y = waverec2(x,s,'db1'); 28 | end 29 | y = Y(:); 30 | 31 | -------------------------------------------------------------------------------- /YALL1_v1.4/quick_start.m: -------------------------------------------------------------------------------- 1 | clear; 2 | if ~exist('Utilities','dir'); Run_Me_1st; end 3 | 4 | % problem sizes 5 | n = 1000; m = 300; k = 60; 6 | sigma = 0.01; 7 | opts.rho = eps; 8 | 9 | nrun = 10; 10 | Iter = zeros(nrun,1); 11 | Err = zeros(nrun,1); 12 | T = zeros(nrun,1); 13 | 14 | for j = 1:nrun 15 | 16 | % generate (A,xs,b) 17 | A = randn(m,n); 18 | xs = zeros(n,1); 19 | p = randperm(n); 20 | xs(p(1:k)) = randn(k,1); 21 | b = A*xs + sigma*randn(m,1); 22 | 23 | % (orth)normalize the rows of A 24 | if ~exist('nonorth','var'); 25 | nonorth = randn > 0; 26 | end 27 | 28 | if nonorth; 29 | d = 1./sqrt(sum(A.^2,2)); 30 | A = sparse(1:m,1:m,d)*A; 31 | b = d.*b; 32 | else 33 | [Q, R] = qr(A',0); 34 | A = Q'; b = R'\b; 35 | end 36 | 37 | % call YALL1 38 | opts.tol = 5e-8; 39 | if sigma > 0; 40 | opts.tol = 5e-3; 41 | opts.rho = sigma; 42 | end 43 | opts.print = 0; 44 | t0 = tic; [x,Out] = yall1(A, b, opts); 45 | err = norm(x-xs)/norm(xs); 46 | fprintf('nonorth: %i, iter = %4i, relative error = %e\n',... 47 | nonorth,Out.iter,err) 48 | Iter(j) = Out.iter; 49 | Err(j) = err; 50 | T(j) = toc(t0); 51 | end 52 | 53 | fprintf('\n[n,m,k] = [%i,%i,%i], %i runs\n',n,m,k,nrun); 54 | fprintf('Average: iter %3i, rel_err %6.2e, time %6.2e\n\n',... 55 | round(mean(Iter)),mean(Err),mean(T)) 56 | -------------------------------------------------------------------------------- /YALL1_v1.4/quick_start2.m: -------------------------------------------------------------------------------- 1 | % Use partial discrete Walsh-Hadamart transform matrix 2 | % (see function Utilities/pdwht_operator.m) 3 | % 4 | % Use DCT as sparsifying basis 5 | % (requires signal processing toolbox) 6 | 7 | clear; 8 | if ~exist('Utilities','dir'); Run_Me_1st; end 9 | if ~exist('fWHtrans','file'); 10 | error('This demo requires the discrete Walsh-Hadamart transform. Please compile fWHtrans.cpp in the folder Utilities by calling ''mex -O fWHtrans.cpp'''); 11 | end 12 | 13 | % problem sizes 14 | n = 1024*8; % must be a power of 2 15 | m = n/8; 16 | fprintf('[n,m] = [%i,%i]\n',n,m); 17 | 18 | % generate xs (non-sparse) 19 | xs = 100*cumsum(randn(n,1)); 20 | 21 | % A = partial DWHT matrix 22 | p = randperm(n); 23 | picks = sort(p(1:m),'ascend'); picks(1) = 1; 24 | A = pdwht_operator(picks,randperm(n)); 25 | 26 | % b = A*xs + noise 27 | sigma = 0.2; % noise level 28 | b = A.times(xs) + sigma*randn(m,1); 29 | 30 | % set options 31 | opts.tol = 5e-4; 32 | opts.rho = 5e-4; 33 | opts.basis.times = @(x) dct(x); % sparsfying basis 34 | opts.basis.trans = @(x) idct(x); % inverse of basis 35 | 36 | % call YALL1 37 | tic; [x,Out] = yall1(A, b, opts); toc 38 | relerr = norm(x-xs)/norm(xs); 39 | fprintf('iter = %4i, error = %e\n',Out.iter,relerr) 40 | plot(1:n,xs,'b-',1:n,x,'r:'); 41 | legend('Original','Recovered','location','best') -------------------------------------------------------------------------------- /cgls.m: -------------------------------------------------------------------------------- 1 | function [x,flag,resNE,iter] = cgls(A,b,shift,tol,maxit,prnt,x0) 2 | %CGLS Conjugate Gradient Least Squares 3 | % X = CGLS(A,B) attempts to solve the system of linear equations A*X=B 4 | % for X. The M-by-N coefficient matrix A and right hand side column 5 | % vector B of length N are required input arguments. 6 | % 7 | % X = CGLS(AFUN,B) accepts a function handle AFUN instead of the matrix 8 | % A. AFUN(X,1) accepts a vector input X and returns the matrix-vector 9 | % product A*X. AFUN(X,2) returns the matrix-vector product A'*X instead. 10 | % In all of the following syntaxes, you can replace A by AFUN. 11 | % 12 | % X = CGLS(A,B,SHIFT) specifies a regularization parameter SHIFT. If 13 | % SHIFT is 0, then CGLS is Hestenes and Stiefel's specialized form of the 14 | % conjugate-gradient method for least-squares problems. If SHIFT is 15 | % nonzero, the system (A'*A + SHIFT*I)*X = A'*B is solved. Here I is the 16 | % N-by-N identity matrix. 17 | % 18 | % X = CGLS(A,B,SHIFT,TOL) specifies the tolerance of the method. If TOL 19 | % is [] then CGLS uses the default, 1e-6. 20 | % 21 | % X = CGLS(A,B,SHIFT,TOL,MAXIT) specifies the maximum number of 22 | % iterations. If MAXIT is [] then CGLS uses the default, 20. 23 | % 24 | % X = CGLS(A,B,SHIFT,TOL,MAXIT,PRNT) specifies if output should be 25 | % generated during each iteration (PRNT == true). If PRNT is [] then no 26 | % output is given. 27 | % 28 | % X = CGLS(A,B,SHIFT,TOL,MAXIT,PRNT,X0) specifies the N-by-1 initial 29 | % solution that is used. If X0 is [] then CGLS uses the default, 30 | % X0 = zeros(N,1). 31 | % 32 | % [X,FLAG] = CGLS(A,B,...) also returns a convergence FLAG: 33 | % 1. CGLS converged to the desired tolerance TOL within MAXIT 34 | % iterations. 35 | % 2. CGLS iterated MAXIT times but did not converge. 36 | % 3. Matrix (A'*A + SHIFT*I) seems to be singular or indefinite. 37 | % 4. Instability seems likely meaning (A'*A + SHIFT*I) indefinite and 38 | % NORM(X) decreased. 39 | % 40 | % [X,FLAG,RESNE] = CGLS(A,B,...) also returns the relative residual for 41 | % the normal equations NORM(A'*B - (A'*A + SHIFT*I)*X)/NORM(A'*B). 42 | % 43 | % [X,FLAG,RESNE,ITER] = CGLS(A,B,...) also returns the iteration number 44 | % at which X was computed: 0 <= ITER <= MAXIT. 45 | % 46 | % See also LSQR, PCG, FUNCTION_HANDLE. 47 | 48 | % 01 Sep 1999: First version. 49 | % Per Christian Hansen (DTU) and Michael Saunders (visiting 50 | % DTU). 51 | % 22 Jan 2013: Updated syntax and documentation. 52 | % Folkert Bleichrodt (CWI). 53 | 54 | 55 | % Assign default values to unspecified parameters 56 | if (nargin < 3 || isempty(shift)), shift = 0; end 57 | if (nargin < 4 || isempty(tol)) , tol = 1e-6; end 58 | if (nargin < 5) , maxit = []; end 59 | if (nargin < 6 || isempty(prnt)) , prnt = 0; end 60 | if (nargin < 7) , x0 = []; end 61 | 62 | 63 | if isa(A, 'numeric') 64 | explicitA = true; 65 | elseif isa(A, 'function_handle') 66 | explicitA = false; 67 | else 68 | error('A must be numeric or a function handle.'); 69 | end 70 | 71 | % handle initial guess, if passed as argument 72 | if explicitA 73 | [m,n] = size(A); 74 | 75 | if ~isempty(x0) 76 | x = x0; 77 | else 78 | x = zeros(n,1); 79 | end 80 | 81 | r = b - A*x; 82 | s = A'*r-shift*x; 83 | else 84 | m = size(b,1); 85 | 86 | if ~isempty(x0) 87 | x = x0; 88 | r = b - A(x,1); 89 | s = A(r,2) - shift*x; 90 | n = size(s,1); 91 | else 92 | r = b; 93 | s = A(b,2); 94 | n = size(s,1); 95 | x = zeros(n,1); 96 | end 97 | 98 | end 99 | 100 | % determine default for maxit 101 | if isempty(maxit) 102 | maxit = min([m,n,20]); 103 | end 104 | 105 | % Initialize 106 | p = s; 107 | norms0 = norm(s); 108 | gamma = norms0^2; 109 | normx = norm(x); 110 | xmax = normx; 111 | k = 0; 112 | flag = 0; 113 | 114 | if prnt 115 | head = ' k x(1) x(n) normx resNE'; 116 | form = '%5.0f %16.10g %16.10g %9.2g %12.5g\n'; 117 | disp(' '); disp(head); 118 | fprintf(form, k, x(1), x(n), normx, 1); 119 | end 120 | 121 | indefinite = 0; 122 | 123 | %-------------------------------------------------------------------------- 124 | % Main loop 125 | %-------------------------------------------------------------------------- 126 | while (k < maxit) && (flag == 0) 127 | 128 | k = k+1; 129 | 130 | % q = A p 131 | if explicitA 132 | q = A*p; 133 | else 134 | q = A(p,1); 135 | end 136 | 137 | delta = norm(q)^2 + shift*norm(p)^2; 138 | if delta <= 0, indefinite = 1; end 139 | if delta == 0, delta = eps; end 140 | alpha = gamma / delta; 141 | 142 | x = x + alpha*p; 143 | r = r - alpha*q; 144 | 145 | if explicitA 146 | s = A'*r - shift*x; 147 | else 148 | s = A(r,2) - shift*x; 149 | end 150 | 151 | norms = norm(s); 152 | gamma1 = gamma; 153 | gamma = norms^2; 154 | beta = gamma / gamma1; 155 | p = s + beta*p; 156 | 157 | % Convergence 158 | normx = norm(x); 159 | xmax = max(xmax, normx); 160 | flag = (norms <= norms0 * tol) || (normx * tol >= 1); 161 | 162 | % Output 163 | resNE = norms / norms0; 164 | if prnt, fprintf(form, k, x(1), x(n), normx, resNE); end 165 | end % while 166 | 167 | iter = k; 168 | 169 | shrink = normx/xmax; 170 | if k == maxit, flag = 2; end 171 | if indefinite, flag = 3; end 172 | if shrink <= sqrt(tol), flag = 4; end 173 | -------------------------------------------------------------------------------- /chksvds.m: -------------------------------------------------------------------------------- 1 | %%checking speed of svds 2 | 3 | clear 4 | clc 5 | 6 | n = 1000; 7 | t_max = 5000; 8 | 9 | r_1 = 100; 10 | r_0 = 1; 11 | t_0 = 0; 12 | t_1 = 0; 13 | 14 | k = 500; 15 | 16 | for ii = 1 : 100 17 | DataTemp = randn(n, k); 18 | Data = DataTemp * DataTemp'; 19 | 20 | tt0 = tic; 21 | X_0 = svds(Data, r_0); 22 | t_0 = t_0 + toc(tt0); 23 | 24 | tt1 = tic; 25 | X_1 = svds(Data, r_1); 26 | t_1 = t_1 + toc(tt1); 27 | end 28 | 29 | 30 | t_0/100 31 | t_1/100 -------------------------------------------------------------------------------- /cosamp_cgls.m: -------------------------------------------------------------------------------- 1 | function Sest = cosamp_cgls(Phi,u,K,tol,maxiterations, err_tol) 2 | 3 | % Cosamp algorithm 4 | % Input 5 | % K : sparsity of Sest 6 | % Phi : measurement matrix 7 | % u: measured vector 8 | % tol : tolerance for approximation between successive solutions. 9 | % Output 10 | % Sest: Solution found by the algorithm 11 | % 12 | % Algorithm as described in "CoSaMP: Iterative signal recovery from 13 | % incomplete and inaccurate samples" by Deanna Needell and Joel Tropp. 14 | % 15 | 16 | 17 | % This implementation was written by David Mary, 18 | % but modified 20110707 by Bob L. Sturm to make it much clearer, 19 | % and corrected multiple times again and again. 20 | % To begin with, see: http://media.aau.dk/null_space_pursuits/2011/07/ ... 21 | % algorithm-power-hour-compressive-sampling-matching-pursuit-cosamp.html 22 | % 23 | % This script/program is released under the Commons Creative Licence 24 | % with Attribution Non-commercial Share Alike (by-nc-sa) 25 | % http://creativecommons.org/licenses/by-nc-sa/3.0/ 26 | % Short Disclaimer: this script is for educational purpose only. 27 | % Longer Disclaimer see http://igorcarron.googlepages.com/disclaimer 28 | 29 | %%Code modified by Praneeth 14March2017 to include case when there is no 30 | %%signal to estimate;replaced pinv() by A\b syntax for speed. 31 | % Initialization 32 | Sest = zeros(size(Phi,2),1); 33 | v = u; 34 | t = 1; 35 | numericalprecision = 1e-12; 36 | T = []; 37 | while ((t <= maxiterations) && (norm(v)/norm(u) > tol) ... 38 | && (norm(Phi'*v) > err_tol)) 39 | 40 | y = abs(Phi'*v); 41 | [vals,z] = sort(y,'descend'); 42 | Omega = find(y >= vals(2*K) & y > numericalprecision); 43 | 44 | T = union(Omega,T); 45 | x = v(T); 46 | %b = pinv(Phi(:,T))*u; 47 | % b = Phi(:,T) \ u; %% edit PKN -- 3/3/17 48 | b = cgls(Phi(:, T), u, 0, err_tol, 3, 0, x); 49 | [vals,z] = sort(abs(b),'descend'); 50 | Kgoodindices = (abs(b) >= vals(K) & abs(b) > numericalprecision); 51 | T = T(Kgoodindices); 52 | Sest = zeros(size(Phi,2),1); 53 | b = b(Kgoodindices); 54 | Sest(T) = b; 55 | v = u - Phi(:,T)*b; 56 | t = t+1; 57 | end -------------------------------------------------------------------------------- /demo_fb_reprocs_pca.m: -------------------------------------------------------------------------------- 1 | %%%Wrapper for foreground-background separation using ReProCS-PCA algorithm 2 | %This folder contains the code accompanying pre-print. 3 | % 4 | %[1] "Provable Dynamic Robust PCA or Robust Subspace Tracking", Praneeth Narayanamurthy and Namrata Vaswani, IEEE Trans. Info. Theory, 2019. 5 | % 6 | %If you use this code please also cite the following papers 7 | %[2] "An online algorithm for separating sparse and low-dimensional signal sequences from their sum", Han Guo, Chenlu Qiu, and Namrata Vaswani, IEEE Trans. Sig. Proc., 2014. 8 | %[3] "Recursive Robust PCA or Recursive Sparse Recovery in Large but Structure Noise", Chenlu Qiu, Namrata Vaswani, Brain Lois, and Leslie Hogben, IEEE Trans. Info. Theory., 2014. 9 | %[4] "Real-time Robust Principal Components' Pursuit", Chenlu Qiu, and Namrata Vaswani, Allerton, 2010. 10 | 11 | 12 | %%Read video 13 | clear; 14 | clc; 15 | close all 16 | 17 | addpath('YALL1_v1.4/'); 18 | 19 | load('Data/Curtain.mat'); 20 | %I = M; 21 | 22 | 23 | %% Training data processing 24 | %%option 1 -- init using batch RPCA 25 | t_train = 400; 26 | TrainData = I(:, 1 : t_train); 27 | rank_init = 40; 28 | 29 | L_hat_init = ncrpca(TrainData, rank_init); 30 | 31 | mu = mean(L_hat_init, 2); 32 | 33 | 34 | [Utemp, Stemp, ~] = svd(1 / sqrt(t_train) * (L_hat_init - ... 35 | repmat(mu, 1, t_train))); 36 | ss1 = diag(Stemp); 37 | L_init = Utemp(:, 1 : rank_init); 38 | 39 | %% option 2 -- init using outlier free data 40 | % mu = mean(DataTrain, 2); 41 | % t_train = size(DataTrain, 2); 42 | % [Utemp, Stemp, ~] = svd(1 / sqrt(t_train) * ... 43 | % (DataTrain - repmat(mu, 1, t_train))); 44 | % ss1 = diag(Stemp); 45 | % b = 0.95; 46 | % rank_init = min(find(cumsum(ss1.^2) >= b * sum(ss1.^2))); 47 | % L_init = Utemp(:, 1 : rank_init); 48 | 49 | 50 | fprintf('Initialized\n'); 51 | theta_thresh = 20 * pi / 180; 52 | ev_thresh = 0.1 * ss1(rank_init) * sin(theta_thresh)^2; 53 | 54 | 55 | %% Call to online ReProCS-PCA function 56 | 57 | K = 3; 58 | alpha = 60; 59 | 60 | 61 | tic 62 | fprintf('alpha = %d\tK = %d\n', alpha, K); 63 | [BG, FG, L_hat, S_hat, T_hat, t_hat, P_track_full] ... 64 | = ReProCS_pca_real(I(:, t_train + 1 : end), ... 65 | L_init, mu, ev_thresh, alpha, K); 66 | toc 67 | 68 | %save('data/reprocs_pca_sl_test.mat') 69 | 70 | VidName = ['Curtain_AutoReProCS_InitAltProj_alpha', num2str(alpha), ... 71 | '_rank', num2str(rank_init)]; 72 | DisplayVideo(I(:, t_train + 1 : end), FG, BG, T_hat, imSize, VidName); 73 | 74 | -------------------------------------------------------------------------------- /err_L_dynrpca_reprocspca: -------------------------------------------------------------------------------- 1 | 1.0014,0.98943,0.00026103,0.0012874,2.3814e-07,3.4018,3.3255,3.1424 2 | 0.98022,0.8406,0.00066022,0.00068782,1.604e-07,3.3185,3.2091,3.1828 3 | 0.9597,0.84136,0.00067267,0.00025982,1.7008e-07,3.4835,3.3081,3.2597 4 | 0.93621,0.82303,0.00024751,6.5974e-05,1.3901e-07,3.3799,3.2911,3.2493 5 | 0.9005,0.82114,0.00034625,2.0236e-05,1.8224e-07,3.155,3.132,3.0262 6 | 0.87007,0.79877,0.00051152,9.1657e-06,1.9238e-07,3.5177,3.4834,3.3951 7 | 0.82836,0.80939,0.00053997,4.3885e-06,1.8756e-07,3.6385,3.5011,3.344 8 | 0.82154,0.80253,0.00032514,1.1493e-06,2.0413e-07,3.3366,2.9627,3.031 9 | 0.75024,0.79961,0.00020976,3.2604e-07,1.9051e-05,3.1966,3.1356,3.1113 10 | 0.71277,0.77908,0.00026478,2.039e-07,1.9051e-05,3.3863,3.3215,3.3702 11 | 0.97287,0.96912,0.11393,0.11393,1.5394e-05,3.1369,3.0184,2.9489 12 | 0.96197,0.99242,2.9575,0.018832,1.5013e-05,3.4308,3.3263,3.2839 13 | 0.93644,0.97894,3.1965,0.014349,8.3145e-06,3.236,3.2324,3.1925 14 | 0.89292,0.9787,3.045,0.004019,9.9422e-06,3.0529,2.9582,3.0301 15 | 0.85459,0.98195,2.929,0.0010832,2.7266e-05,3.0113,2.9213,3.0025 16 | 0.81143,0.98172,3.0532,0.00062187,1.7506e-05,3.0909,3.0816,3.0556 17 | 0.80959,0.97151,3.2868,0.00026735,1.9227e-05,3.2504,3.2084,3.2952 18 | 0.78134,0.98335,3.2234,0.00010037,2.6821e-05,3.2819,3.1574,3.2372 19 | 0.73175,0.96835,3.2613,4.8445e-05,3.1852e-06,3.3654,3.2754,3.2498 20 | 0.69924,0.96706,3.2689,1.0933e-05,3.1852e-06,3.5162,3.1822,3.2925 21 | 0.72149,0.96255,3.2548,0.032706,5.3844e-06,3.19,3.1526,3.2382 22 | 0.69086,0.97557,2.9791,0.0073352,3.5548e-06,2.991,2.9679,2.9649 23 | 0.70868,0.976,3.1976,0.001824,4.8663e-06,3.1796,3.1027,3.2011 24 | 0.64153,0.98632,3.4223,0.001043,3.7119e-06,3.3042,3.3467,3.3864 25 | 0.62997,0.99558,3.1436,0.00029508,4.6862e-06,2.9582,2.9141,3.1372 26 | 0.62258,0.96342,3.209,0.00016561,4.9994e-06,3.2132,3.1382,3.2125 27 | 0.56275,0.97973,3.2907,3.1469e-05,3.8877e-06,3.4716,3.3952,3.3125 28 | 0.61982,0.98886,3.0683,1.3056e-05,4.0988e-06,3.0136,2.9864,3.0884 29 | 0.56023,0.97429,3.2155,6.2373e-06,3.5414e-06,3.2227,3.0764,3.1952 30 | 0.5529,0.96097,3.5698,6.7776e-06,0,3.7335,3.6031,1 31 | 0.53418,0.96097,2.9604,2.908e-06,0,3.0206,2.8118,1 32 | 0.51405,0.99287,3.2929,6.8111e-06,0,3.3695,3.2677,1 33 | 0.53932,0.97345,3.3487,3.4126e-06,0,1,1,1 34 | -------------------------------------------------------------------------------- /err_L_dynrpca_reprocspca.dat: -------------------------------------------------------------------------------- 1 | 1,1.0014,0.98943,0.00026103,0.0012874,2.3814e-07,3.4018,3.3255,3.1424 2 | 301,0.98022,0.8406,0.00066022,0.00068782,1.604e-07,3.3185,3.2091,3.1828 3 | 601,0.9597,0.84136,0.00067267,0.00025982,1.7008e-07,3.4835,3.3081,3.2597 4 | 901,0.93621,0.82303,0.00024751,6.5974e-05,1.3901e-07,3.3799,3.2911,3.2493 5 | 1201,0.9005,0.82114,0.00034625,2.0236e-05,1.8224e-07,3.155,3.132,3.0262 6 | 1501,0.87007,0.79877,0.00051152,9.1657e-06,1.9238e-07,3.5177,3.4834,3.3951 7 | 1801,0.82836,0.80939,0.00053997,4.3885e-06,1.8756e-07,3.6385,3.5011,3.344 8 | 2101,0.82154,0.80253,0.00032514,1.1493e-06,2.0413e-07,3.3366,2.9627,3.031 9 | 2401,0.75024,0.79961,0.00020976,3.2604e-07,1.9051e-05,3.1966,3.1356,3.1113 10 | 2701,0.71277,0.77908,0.00026478,2.039e-07,1.9051e-05,3.3863,3.3215,3.3702 11 | 3001,0.97287,0.96912,0.11393,0.11393,1.5394e-05,3.1369,3.0184,2.9489 12 | 3301,0.96197,0.99242,2.9575,0.018832,1.5013e-05,3.4308,3.3263,3.2839 13 | 3601,0.93644,0.97894,3.1965,0.014349,8.3145e-06,3.236,3.2324,3.1925 14 | 3901,0.89292,0.9787,3.045,0.004019,9.9422e-06,3.0529,2.9582,3.0301 15 | 4201,0.85459,0.98195,2.929,0.0010832,2.7266e-05,3.0113,2.9213,3.0025 16 | 4501,0.81143,0.98172,3.0532,0.00062187,1.7506e-05,3.0909,3.0816,3.0556 17 | 4801,0.80959,0.97151,3.2868,0.00026735,1.9227e-05,3.2504,3.2084,3.2952 18 | 5101,0.78134,0.98335,3.2234,0.00010037,2.6821e-05,3.2819,3.1574,3.2372 19 | 5401,0.73175,0.96835,3.2613,4.8445e-05,3.1852e-06,3.3654,3.2754,3.2498 20 | 5701,0.69924,0.96706,3.2689,1.0933e-05,3.1852e-06,3.5162,3.1822,3.2925 21 | 6001,0.72149,0.96255,3.2548,0.032706,5.3844e-06,3.19,3.1526,3.2382 22 | 6301,0.69086,0.97557,2.9791,0.0073352,3.5548e-06,2.991,2.9679,2.9649 23 | 6601,0.70868,0.976,3.1976,0.001824,4.8663e-06,3.1796,3.1027,3.2011 24 | 6901,0.64153,0.98632,3.4223,0.001043,3.7119e-06,3.3042,3.3467,3.3864 25 | 7201,0.62997,0.99558,3.1436,0.00029508,4.6862e-06,2.9582,2.9141,3.1372 26 | 7501,0.62258,0.96342,3.209,0.00016561,4.9994e-06,3.2132,3.1382,3.2125 27 | 7801,0.56275,0.97973,3.2907,3.1469e-05,3.8877e-06,3.4716,3.3952,3.3125 28 | 8101,0.61982,0.98886,3.0683,1.3056e-05,4.0988e-06,3.0136,2.9864,3.0884 29 | 8401,0.56023,0.97429,3.2155,6.2373e-06,3.5414e-06,3.2227,3.0764,3.1952 30 | 8701,0.5529,0.96097,3.5698,6.7776e-06,0,3.7335,3.6031,1 31 | 9001,0.53418,0.96097,2.9604,2.908e-06,0,3.0206,2.8118,1 32 | 9301,0.51405,0.99287,3.2929,6.8111e-06,0,3.3695,3.2677,1 33 | 9601,0.53932,0.97345,3.3487,3.4126e-06,0,1,1,1 34 | -------------------------------------------------------------------------------- /err_L_dynrpca_reprocspca_bern.dat: -------------------------------------------------------------------------------- 1 | 1,1.1944,0.9898,9.4586e-05,0.001747,3.6601e-10,0.90922,0.7805,0.73427 2 | 201,1.1379,0.87037,6.9307e-05,0.0002459,3.3081e-10,0.94542,0.79656,0.66875 3 | 401,1.203,0.85788,6.3125e-05,2.8981e-05,3.4671e-10,0.92442,0.7045,1.5236 4 | 601,2.0642,0.85634,0.00012645,9.9377e-06,7.2541e-10,1.0114,0.72782,1.3344 5 | 801,1.7813,0.87972,8.0585e-05,1.476e-06,4.1692e-10,0.97287,0.8396,1.5111 6 | 1001,1.1787,0.84298,6.4415e-05,1.6964e-07,3.1987e-10,0.93146,0.76441,0.90943 7 | 1201,2.2831,0.84066,9.0477e-05,3.979e-08,1.922e-10,0.96646,0.8131,1.5089 8 | 1401,1.873,0.83814,6.217e-05,5.8785e-09,5.8308e-10,0.99683,0.87815,0.90663 9 | 1601,1.869,0.83477,0.00010084,1.3262e-09,2.0003e-08,0.99198,0.89599,1.4796 10 | 1801,2.2304,0.81529,6.9489e-05,4.4789e-10,2.0003e-08,1.0083,0.76108,1.3009 11 | 2001,1.5688,0.85643,5.3977e-05,2.1325e-10,2.0003e-08,0.89848,0.79418,0.9187 12 | 2201,2.4831,0.78066,7.0185e-05,2.369e-10,2.0003e-08,0.94014,0.72178,7.4713e-05 13 | 2401,1.3611,0.82664,8.3277e-05,1.7499e-10,2.0003e-08,0.98198,0.83126,1.424 14 | 2601,2.2183,0.8303,7.188e-05,7.3168e-10,2.0003e-08,1.0027,0.73453,1.3459 15 | 2801,1.2777,0.99819,0.26305,0.26306,2.0003e-08,0.63481,0.59048,1.7923 16 | 3001,2.6412,0.98212,0.33802,0.33802,3.2963e-08,0.63321,0.5541,1.552 17 | 3201,1.1965,0.98091,0.047795,0.045098,2.3313e-08,0.63404,0.6185,1.2934 18 | 3401,1.652,0.97408,0.0078407,0.0076876,2.3305e-08,0.59334,0.55601,0.88794 19 | 3601,1.6826,0.99439,0.0053278,0.0017904,3.551e-08,0.55691,0.50935,1.0616 20 | 3801,1.777,0.9365,0.000812,0.00026239,3.0094e-08,0.5575,0.51591,1.4278 21 | 4001,1.4954,1.0163,0.00010003,2.9347e-05,3.8121e-08,0.52765,0.52145,1.484 22 | 4201,1.4794,0.96731,1.4104e-05,6.8819e-06,3.1432e-08,0.6455,0.55547,0.69207 23 | 4401,1.1358,0.93614,2.5024e-06,7.7887e-07,2.6329e-08,0.59962,0.52534,0.094868 24 | 4601,1.8098,0.99869,8.7647e-07,1.7775e-07,0,0.61253,0.63392,1.3289 25 | 4801,2.2698,1.0256,0.0045868,3.3927e-08,0,0.526,0.45898,1.8836 26 | 5001,1.6423,0.9669,0.036896,2.1142e-08,0,0.5529,0.51093,2.1844 27 | 5201,1.4747,0.99509,0.00082166,4.6663e-09,0,0.51143,0.64056,1.5962 28 | 5401,1.9442,0.91232,7.1867e-06,9.6307e-10,0,0.55645,0.48734,2.4252 29 | 5601,2.167,0.95241,0.92781,0.0063428,0,0.47675,0.4325,2.1652 30 | 5801,1.7333,0.96093,1.1868,0.14371,5.6751e-05,0.20638,0.29346,1.55 31 | 6001,1.2022,0.98468,0.86432,0.020185,3.7659e-05,0.43336,0.42157,1.2766 32 | 6201,1.1382,0.93761,0.99359,0.0046735,5.4926e-05,0.38299,0.50186,1.7352 33 | 6401,1.8798,1.0054,0.016467,0.0013202,6.5387e-05,0.39732,0.3962,1.9354 34 | 6601,2.124,0.98117,0.79487,0.00041057,0.00023354,0.33994,0.39601,1.4778 35 | 6801,1.9189,0.99268,1.8404,5.3567e-05,0.0006129,0.60614,0.59445,2.3454 36 | 7001,1.5759,0.96842,1.7699,0.00014154,0.00041675,0.32737,0.43815,2.3905 37 | 7201,2.0656,0.99844,0.75168,0.0039016,0.00035595,0.37997,0.34348,1.7168 38 | 7401,2.1296,0.91402,1.7308,0.00077683,0.0036255,0.2964,0.38808,2.2706 39 | 7601,1.8503,0.94638,1.456,0.0047049,0.00057633,0.23498,0.66175,1.6667 40 | 7801,2.0586,0.91696,2.823,0.0016678,0.00070423,0.29695,0.35055,2.4248 41 | 8001,1.6599,0.96983,2.516,0.0044097,0.00040762,0.56375,0.51554,2.3838 42 | 8201,1.5098,0.95609,1.9071,0.0070122,0.0012489,0.22179,0.62905,2.5365 43 | 8401,1.9018,0.9731,1.5172,0.0027795,0.00056581,0.31703,0.38801,2.4199 44 | 8601,2.0301,0.99442,2.4881,0.0012034,0.00044829,0.36959,0.57975,2.157 45 | 8801,1.3056,0.98398,1.1413,0.00060203,1,0.44656,0.37147,1 46 | 9001,1.787,0.98785,1.8259,0.00034245,1,0.34705,0.77781,1 47 | 9201,1.4529,0.96089,2.0071,0.0011078,1,0.46589,0.45256,1 48 | 9401,1.8825,0.96488,1.7258,0.012912,1,0.25952,0.3852,1 49 | 9601,1.5267,0.95699,1.6906,0.013285,1,1,1,1 50 | -------------------------------------------------------------------------------- /lansvd.m: -------------------------------------------------------------------------------- 1 | function [U,S,V,bnd,j] = lansvd(varargin) 2 | 3 | %LANSVD Compute a few singular values and singular vectors. 4 | % LANSVD computes singular triplets (u,v,sigma) such that 5 | % A*u = sigma*v and A'*v = sigma*u. Only a few singular values 6 | % and singular vectors are computed using the Lanczos 7 | % bidiagonalization algorithm with partial reorthogonalization (BPRO). 8 | % 9 | % S = LANSVD(A) 10 | % S = LANSVD('Afun','Atransfun',M,N) 11 | % 12 | % The first input argument is either a matrix or a 13 | % string containing the name of an M-file which applies a linear 14 | % operator to the columns of a given matrix. In the latter case, 15 | % the second input must be the name of an M-file which applies the 16 | % transpose of the same operator to the columns of a given matrix, 17 | % and the third and fourth arguments must be M and N, the dimensions 18 | % of the problem. 19 | % 20 | % [U,S,V] = LANSVD(A,K,'L',...) computes the K largest singular values. 21 | % 22 | % [U,S,V] = LANSVD(A,K,'S',...) computes the K smallest singular values. 23 | % 24 | % The full calling sequence is 25 | % 26 | % [U,S,V] = LANSVD(A,K,SIGMA,OPTIONS) 27 | % [U,S,V] = LANSVD('Afun','Atransfun',M,N,K,SIGMA,OPTIONS) 28 | % 29 | % where K is the number of singular values desired and 30 | % SIGMA is 'L' or 'S'. 31 | % 32 | % The OPTIONS structure specifies certain parameters in the algorithm. 33 | % Field name Parameter Default 34 | % 35 | % OPTIONS.tol Convergence tolerance 16*eps 36 | % OPTIONS.lanmax Dimension of the Lanczos basis. 37 | % OPTIONS.p0 Starting vector for the Lanczos rand(n,1)-0.5 38 | % iteration. 39 | % OPTIONS.delta Level of orthogonality among the sqrt(eps/K) 40 | % Lanczos vectors. 41 | % OPTIONS.eta Level of orthogonality after 10*eps^(3/4) 42 | % reorthogonalization. 43 | % OPTIONS.cgs reorthogonalization method used 0 44 | % '0' : iterated modified Gram-Schmidt 45 | % '1' : iterated classical Gram-Schmidt 46 | % OPTIONS.elr If equal to 1 then extended local 1 47 | % reorthogonalization is enforced. 48 | % 49 | % See also LANBPRO, SVDS, SVD 50 | 51 | % References: 52 | % R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998. 53 | % 54 | % B. N. Parlett, ``The Symmetric Eigenvalue Problem'', 55 | % Prentice-Hall, Englewood Cliffs, NJ, 1980. 56 | % 57 | % H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'', 58 | % Math. Comp. 42 (1984), no. 165, 115--142. 59 | 60 | % Rasmus Munk Larsen, DAIMI, 1998 61 | 62 | 63 | %%%%%%%%%%%%%%%%%%%%% Parse and check input arguments. %%%%%%%%%%%%%%%%%%%%%% 64 | 65 | if nargin<1 | length(varargin)<1 66 | error('Not enough input arguments.'); 67 | end 68 | 69 | A = varargin{1}; 70 | if ~isstr(A) 71 | if ~isreal(A) 72 | error('A must be real') 73 | end 74 | [m n] = size(A); 75 | if length(varargin) < 2, k=min(min(m,n),6); else k=varargin{2}; end 76 | if length(varargin) < 3, sigma = 'L'; else sigma=varargin{3}; end 77 | if length(varargin) < 4, options = []; else options=varargin{4}; end 78 | else 79 | if length(varargin)<4 80 | error('Not enough input arguments.'); 81 | end 82 | Atrans = varargin{2}; 83 | if ~isstr(Atrans) 84 | error('Atransfunc must be the name of a function') 85 | end 86 | m = varargin{3}; 87 | n = varargin{4}; 88 | if length(varargin) < 5, k=min(min(m,n),6); else k=varargin{5}; end 89 | if length(varargin) < 6, sigma = 'L'; else sigma=varargin{6}; end 90 | if length(varargin) < 7, options = []; else options=varargin{7}; end 91 | end 92 | 93 | if ~isnumeric(n) | real(abs(fix(n))) ~= n | ~isnumeric(m) | ... 94 | real(abs(fix(m))) ~= m | ~isnumeric(k) | real(abs(fix(k))) ~= k 95 | error('M, N and K must be positive integers.') 96 | end 97 | 98 | 99 | % Quick return for min(m,n) equal to 0 or 1 or for zero A. 100 | if min(n,m) < 1 | k<1 101 | if nargout<3 102 | U = zeros(k,1); 103 | else 104 | U = eye(m,k); S = zeros(k,k); V = eye(n,k); bnd = zeros(k,1); 105 | end 106 | return 107 | elseif min(n,m) == 1 & k>0 108 | if isstr(A) 109 | % Extract the single column or row of A 110 | if n==1 111 | A = feval(A,1); 112 | else 113 | A = feval(Atrans,1)'; 114 | end 115 | end 116 | if nargout==1 117 | U = norm(A); 118 | else 119 | [U,S,V] = svd(full(A)); 120 | bnd = 0; 121 | end 122 | return 123 | end 124 | 125 | % A is the matrix of all zeros (not detectable if A is defined by an m-file) 126 | if isnumeric(A) 127 | if nnz(A)==0 128 | if nargout<3 129 | U = zeros(k,1); 130 | else 131 | U = eye(m,k); S = zeros(k,k); V = eye(n,k); bnd = zeros(k,1); 132 | end 133 | return 134 | end 135 | end 136 | 137 | lanmax = min(m,n); 138 | tol = 16*eps; 139 | p = rand(m,1)-0.5; 140 | % Parse options struct 141 | if isstruct(options) 142 | c = fieldnames(options); 143 | for i=1:length(c) 144 | if any(strcmp(c(i),'p0')), p = getfield(options,'p0'); p=p(:); end 145 | if any(strcmp(c(i),'tol')), tol = getfield(options,'tol'); end 146 | if any(strcmp(c(i),'lanmax')), lanmax = getfield(options,'lanmax'); end 147 | end 148 | end 149 | 150 | % Protect against absurd options. 151 | tol = max(tol,eps); 152 | lanmax = min(lanmax,min(m,n)); 153 | if size(p,1)~=m 154 | error('p0 must be a vector of length m') 155 | end 156 | 157 | lanmax = min(lanmax,min(m,n)); 158 | if k>lanmax 159 | error('K must satisfy K <= LANMAX <= MIN(M,N).'); 160 | end 161 | 162 | 163 | 164 | %%%%%%%%%%%%%%%%%%%%% Here begins the computation %%%%%%%%%%%%%%%%%%%%%% 165 | 166 | if strcmp(sigma,'S') 167 | if isstr(A) 168 | error('Shift-and-invert works only when the matrix A is given explicitly.'); 169 | else 170 | % Prepare for shift-and-invert Lanczos. 171 | if issparse(A) 172 | pmmd = colmmd(A); 173 | A.A = A(:,pmmd); 174 | else 175 | A.A = A; 176 | end 177 | if m>=n 178 | if issparse(A.A) 179 | A.R = qr(A.A,0); 180 | A.Rt = A.R'; 181 | p = A.Rt\(A.A'*p); % project starting vector on span(Q1) 182 | else 183 | [A.Q,A.R] = qr(A.A,0); 184 | A.Rt = A.R'; 185 | p = A.Q'*p; % project starting vector on span(Q1) 186 | end 187 | else 188 | error('Sorry, shift-and-invert for m 1/eps 194 | error(['A is rank deficient or too ill-conditioned to do shift-and-' ... 195 | ' invert.']) 196 | end 197 | end 198 | end 199 | 200 | ksave = k; 201 | neig = 0; nrestart=-1; 202 | j = min(k+max(8,k)+1,lanmax); 203 | U = []; V = []; B = []; anorm = []; work = zeros(2,2); 204 | 205 | while neig < k 206 | 207 | %%%%%%%%%%%%%%%%%%%%% Compute Lanczos bidiagonalization %%%%%%%%%%%%%%%%% 208 | if ~isstr(A) 209 | [U,B,V,p,ierr,w] = lanbpro(A,j,p,options,U,B,V,anorm); 210 | else 211 | [U,B,V,p,ierr,w] = lanbpro(A,Atrans,m,n,j,p,options,U,B,V,anorm); 212 | end 213 | work= work + w; 214 | 215 | if ierr<0 % Invariant subspace of dimension -ierr found. 216 | j = -ierr; 217 | end 218 | 219 | %%%%%%%%%%%%%%%%%% Compute singular values and error bounds %%%%%%%%%%%%%%%% 220 | % Analyze B 221 | resnrm = norm(p); 222 | % We might as well use the extra info. in p. 223 | % S = svd(full([B;[zeros(1,j-1),resnrm]]),0); 224 | % [P,S,Q] = svd(full([B;[zeros(1,j-1),resnrm]]),0); 225 | % S = diag(S); 226 | % bot = min(abs([P(end,1:j);Q(end,1:j)]))'; 227 | 228 | [S,bot] = bdsqr(diag(B),[diag(B,-1); resnrm]); 229 | 230 | % Use Largest Ritz value to estimate ||A||_2. This might save some 231 | % reorth. in case of restart. 232 | anorm=S(1); 233 | 234 | % Set simple error bounds 235 | bnd = resnrm*abs(bot); 236 | 237 | % Examine gap structure and refine error bounds 238 | bnd = refinebounds(S.^2,bnd,n*eps*anorm); 239 | 240 | %%%%%%%%%%%%%%%%%%% Check convergence criterion %%%%%%%%%%%%%%%%%%%% 241 | i=1; 242 | neig = 0; 243 | while i<=min(j,k) 244 | if (bnd(i) <= tol*abs(S(i))) 245 | neig = neig + 1; 246 | i = i+1; 247 | else 248 | i = min(j,k)+1; 249 | end 250 | end 251 | 252 | %%%%%%%%%% Check whether to stop or to extend the Krylov basis? %%%%%%%%%% 253 | if ierr<0 % Invariant subspace found 254 | if j=lanmax % Maximal dimension of Krylov subspace reached. Bail out 261 | if j>=min(m,n) 262 | neig = ksave; 263 | break; 264 | end 265 | if neig0 274 | % increase j by approx. half the average number of steps pr. converged 275 | % singular value (j/neig) times the number of remaining ones (k-neig). 276 | j = j + min(100,max(2,0.5*(k-neig)*j/(neig+1))); 277 | else 278 | % As long a very few singular values have converged, increase j rapidly. 279 | % j = j + ceil(min(100,max(8,2^nrestart*k))); 280 | j = max(1.5*j,j+10); 281 | end 282 | j = ceil(min(j+1,lanmax)); 283 | nrestart = nrestart + 1; 284 | end 285 | 286 | 287 | 288 | %%%%%%%%%%%%%%%% Lanczos converged (or failed). Prepare output %%%%%%%%%%%%%%% 289 | k = min(ksave,j); 290 | 291 | if nargout>2 292 | j = size(B,2); 293 | % Compute singular vectors 294 | [P,S,Q] = svd(full([B;[zeros(1,j-1),resnrm]]),0); 295 | S = diag(S); 296 | if size(Q,2)~=k 297 | Q = Q(:,1:k); 298 | P = P(:,1:k); 299 | end 300 | % Compute and normalize Ritz vectors (overwrites U and V to save memory). 301 | if resnrm~=0 302 | U = U*P(1:j,:) + (p/resnrm)*P(j+1,:); 303 | else 304 | U = U*P(1:j,:); 305 | end 306 | V = V*Q; 307 | for i=1:k 308 | nq = norm(V(:,i)); 309 | if isfinite(nq) & nq~=0 & nq~=1 310 | V(:,i) = V(:,i)/nq; 311 | end 312 | nq = norm(U(:,i)); 313 | if isfinite(nq) & nq~=0 & nq~=1 314 | U(:,i) = U(:,i)/nq; 315 | end 316 | end 317 | end 318 | 319 | % Pick out desired part the spectrum 320 | S = S(1:k); 321 | bnd = bnd(1:k); 322 | 323 | if strcmp(sigma,'S') 324 | [S,p] = sort(-1./S); 325 | S = -S; 326 | bnd = bnd(p); 327 | if nargout>2 328 | if issparse(A.A) 329 | U = A.A*(A.R\U(:,p)); 330 | V(pmmd,:) = V(:,p); 331 | else 332 | U = A.Q(:,1:min(m,n))*U(:,p); 333 | V = V(:,p); 334 | end 335 | end 336 | end 337 | 338 | if nargout<3 339 | U = S; 340 | S = B; % Undocumented feature - for checking B. 341 | else 342 | S = diag(S); 343 | end 344 | -------------------------------------------------------------------------------- /medropplusrpca.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/medropplusrpca.jpg -------------------------------------------------------------------------------- /ncrpca.m: -------------------------------------------------------------------------------- 1 | function [L_t, S_t, iters, frob_err] = ncrpca(M, true_r, EPS, MAX_ITER, EPS_S, incoh, TOL) 2 | 3 | % This matlab code implements Non-convex Robust PCA (NcRPCA) 4 | % Input: 5 | % M = given low rank+sparse matrix to be decomposed 6 | % true_r = maximum rank of the low rank rank component 7 | % EPS (optional) = convergence threshold for ||M-(L_t+S_t)||_F; default is 1e-3 8 | % MAX_ITER (optional) = maximum iterations for NcRPCA; default is 51 9 | % EPS_S (optional) = threshold for removing small entries in the sparse component; default is 1e-3 10 | % incoh (optional) = incoherence of the low rank component; default is 1 11 | % TOL (optional) = tolerance for relative error in ||M-(L_t+S_t)||_F in consecutive iterations; default is 1e-1 12 | % Output: 13 | % M_t = thresholded M at each iteration 14 | % L_t = rank-k approximation of M_t 15 | % S_t = sparse component, computed as M-M_t 16 | % iters = number of iteration of NcRPCA 17 | % frob_err = ||M-(L_t+S_t)||_F at each iteration 18 | 19 | if nargin < 7, TOL = 1e-1; end 20 | if nargin < 6, incoh = 1; end 21 | if nargin < 5, EPS_S = 1e-3; end 22 | if nargin < 4, MAX_ITER = 51; end 23 | if nargin < 3, EPS = 1e-3; end 24 | 25 | %addpath code_ncrpca/PROPACK; 26 | %addpath PROPACK; 27 | frob_err(1) = inf; 28 | [~, n] = size(M); 29 | t = 1; 30 | idx = []; 31 | thresh_const = incoh; % threshold constant: can be tuned depending on incoherence 32 | thresh_red = 0.9; % parameter to reduce the threshold constant: can be tuned 33 | r_hat = 1; % initial rank for stagewise algorithm 34 | L_t = zeros(size(M)); 35 | Sig_t = lansvd(M,1,'L'); 36 | D_t = M-L_t; 37 | thresh = thresh_const*Sig_t/sqrt(n); 38 | idx = unique([find(abs(D_t) > thresh); idx]); 39 | S_t = zeros(size(M)); 40 | S_t(idx) = D_t(idx); % initial thresholding 41 | if max(idx(:))==0 42 | idx = []; 43 | end 44 | while frob_err(t)/norm(M, 'fro')>=EPS && t thresh); idx]); 55 | S_t(idx) = D_t(idx); 56 | frob_err(t) = norm(M-(L_t+S_t), 'fro'); 57 | if ((frob_err(t-1)-frob_err(t))/frob_err(t-1) <= TOL) && r_hat= thresh))); 17 | Q = U(:, 1 : num_comp); 18 | end 19 | -------------------------------------------------------------------------------- /reprocs_pca_compare.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/reprocs_pca_compare.jpg -------------------------------------------------------------------------------- /simpleEVD.m: -------------------------------------------------------------------------------- 1 | function P_hat = simpleEVD(X, r) 2 | 3 | %%%Function to implement the Simple-EVD algorithm and returns a basis 4 | %%%matrix for the new subspace -- edit these comments before Gitting 5 | 6 | %%% Inputs %%% 7 | %%% X - Emperical Covariance data matrix (m X m) %%% 8 | %%% r - Target rank of output %%% 9 | 10 | %%% Outputs %%% 11 | %%% P_hat - Basis matrix for output (m X r) %%% 12 | 13 | [P_hat, ~] = svds(X, r); 14 | end -------------------------------------------------------------------------------- /temp_altproj_alpha.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/temp_altproj_alpha.jpg -------------------------------------------------------------------------------- /temp_altproj_alpha_se.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/temp_altproj_alpha_se.jpg -------------------------------------------------------------------------------- /temp_t_j_Se.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/praneethmurthy/ReProCS/c8b6218e10d8b737f41c4feb15534356118844ad/temp_t_j_Se.jpg --------------------------------------------------------------------------------