annotate pyCSalgos/GAP/gap.py @ 18:a8ff9a881d2f

GAP test almost working. For some data the results are not the same because of representation error, so the test doesn't fully work for now. But the results seem to be accurate.
author nikcleju
date Mon, 07 Nov 2011 17:48:05 +0000
parents ef63b89b375a
children ef0629f859a3
rev   line source
nikcleju@17 1 # -*- coding: utf-8 -*-
nikcleju@17 2 """
nikcleju@17 3 Created on Thu Oct 13 14:05:22 2011
nikcleju@17 4
nikcleju@17 5 @author: ncleju
nikcleju@17 6 """
nikcleju@17 7
nikcleju@17 8 #from numpy import *
nikcleju@17 9 #from scipy import *
nikcleju@17 10 import numpy as np
nikcleju@17 11 import scipy as sp
nikcleju@18 12 import scipy.stats #from scipy import stats
nikcleju@18 13 import scipy.linalg #from scipy import lnalg
nikcleju@17 14 import math
nikcleju@17 15
nikcleju@17 16 from numpy.random import RandomState
nikcleju@17 17 rng = RandomState()
nikcleju@17 18
nikcleju@17 19 def Generate_Analysis_Operator(d, p):
nikcleju@17 20 # generate random tight frame with equal column norms
nikcleju@17 21 if p == d:
nikcleju@17 22 T = rng.randn(d,d);
nikcleju@17 23 [Omega, discard] = np.qr(T);
nikcleju@17 24 else:
nikcleju@17 25 Omega = rng.randn(p, d);
nikcleju@17 26 T = np.zeros((p, d));
nikcleju@17 27 tol = 1e-8;
nikcleju@17 28 max_j = 200;
nikcleju@17 29 j = 1;
nikcleju@17 30 while (sum(sum(abs(T-Omega))) > np.dot(tol,np.dot(p,d)) and j < max_j):
nikcleju@17 31 j = j + 1;
nikcleju@17 32 T = Omega;
nikcleju@17 33 [U, S, Vh] = sp.linalg.svd(Omega);
nikcleju@17 34 V = Vh.T
nikcleju@17 35 #Omega = U * [eye(d); zeros(p-d,d)] * V';
nikcleju@17 36 Omega2 = np.dot(np.dot(U, np.concatenate((np.eye(d), np.zeros((p-d,d))))), V.transpose())
nikcleju@17 37 #Omega = diag(1./sqrt(diag(Omega*Omega')))*Omega;
nikcleju@18 38 Omega = np.dot(np.diag(1.0 / np.sqrt(np.diag(np.dot(Omega2,Omega2.transpose())))), Omega2)
nikcleju@17 39 #end
nikcleju@17 40 ##disp(j);
nikcleju@18 41 #end
nikcleju@17 42 return Omega
nikcleju@17 43
nikcleju@17 44
nikcleju@17 45 def Generate_Data_Known_Omega(Omega, d,p,m,k,noiselevel, numvectors, normstr):
nikcleju@17 46 #function [x0,y,M,LambdaMat] = Generate_Data_Known_Omega(Omega, d,p,m,k,noiselevel, numvectors, normstr)
nikcleju@17 47
nikcleju@17 48 # Building an analysis problem, which includes the ingredients:
nikcleju@17 49 # - Omega - the analysis operator of size p*d
nikcleju@17 50 # - M is anunderdetermined measurement matrix of size m*d (m<d)
nikcleju@17 51 # - x0 is a vector of length d that satisfies ||Omega*x0||=p-k
nikcleju@17 52 # - Lambda is the true location of these k zeros in Omega*x0
nikcleju@17 53 # - a measurement vector y0=Mx0 is computed
nikcleju@17 54 # - noise contaminated measurement vector y is obtained by
nikcleju@17 55 # y = y0 + n where n is an additive gaussian noise with norm(n,2)/norm(y0,2) = noiselevel
nikcleju@17 56 # Added by Nic:
nikcleju@17 57 # - Omega = analysis operator
nikcleju@17 58 # - normstr: if 'l0', generate l0 sparse vector (unchanged). If 'l1',
nikcleju@17 59 # generate a vector of Laplacian random variables (gamma) and
nikcleju@17 60 # pseudoinvert to find x
nikcleju@17 61
nikcleju@17 62 # Omega is known as input parameter
nikcleju@17 63 #Omega=Generate_Analysis_Operator(d, p);
nikcleju@17 64 # Omega = randn(p,d);
nikcleju@17 65 # for i = 1:size(Omega,1)
nikcleju@17 66 # Omega(i,:) = Omega(i,:) / norm(Omega(i,:));
nikcleju@17 67 # end
nikcleju@17 68
nikcleju@17 69 #Init
nikcleju@17 70 LambdaMat = np.zeros((k,numvectors))
nikcleju@17 71 x0 = np.zeros((d,numvectors))
nikcleju@17 72 y = np.zeros((m,numvectors))
nikcleju@17 73
nikcleju@17 74 M = rng.randn(m,d);
nikcleju@17 75
nikcleju@17 76 #for i=1:numvectors
nikcleju@17 77 for i in range(0,numvectors):
nikcleju@17 78
nikcleju@17 79 # Generate signals
nikcleju@17 80 #if strcmp(normstr,'l0')
nikcleju@17 81 if normstr == 'l0':
nikcleju@17 82 # Unchanged
nikcleju@17 83
nikcleju@17 84 #Lambda=randperm(p);
nikcleju@17 85 Lambda = rng.permutation(int(p));
nikcleju@17 86 Lambda = np.sort(Lambda[0:k]);
nikcleju@17 87 LambdaMat[:,i] = Lambda; # store for output
nikcleju@17 88
nikcleju@17 89 # The signal is drawn at random from the null-space defined by the rows
nikcleju@17 90 # of the matreix Omega(Lambda,:)
nikcleju@17 91 [U,D,Vh] = sp.linalg.svd(Omega[Lambda,:]);
nikcleju@17 92 V = Vh.T
nikcleju@17 93 NullSpace = V[:,k:];
nikcleju@17 94 #print np.dot(NullSpace, rng.randn(d-k,1)).shape
nikcleju@17 95 #print x0[:,i].shape
nikcleju@17 96 x0[:,i] = np.squeeze(np.dot(NullSpace, rng.randn(d-k,1)));
nikcleju@17 97 # Nic: add orthogonality noise
nikcleju@17 98 # orthonoiseSNRdb = 6;
nikcleju@17 99 # n = randn(p,1);
nikcleju@17 100 # #x0(:,i) = x0(:,i) + n / norm(n)^2 * norm(x0(:,i))^2 / 10^(orthonoiseSNRdb/10);
nikcleju@17 101 # n = n / norm(n)^2 * norm(Omega * x0(:,i))^2 / 10^(orthonoiseSNRdb/10);
nikcleju@17 102 # x0(:,i) = pinv(Omega) * (Omega * x0(:,i) + n);
nikcleju@17 103
nikcleju@17 104 #elseif strcmp(normstr, 'l1')
nikcleju@17 105 elif normstr == 'l1':
nikcleju@17 106 print('Nic says: not implemented yet')
nikcleju@17 107 raise Exception('Nic says: not implemented yet')
nikcleju@17 108 #gamma = laprnd(p,1,0,1);
nikcleju@17 109 #x0(:,i) = Omega \ gamma;
nikcleju@17 110 else:
nikcleju@17 111 #error('normstr must be l0 or l1!');
nikcleju@17 112 print('Nic says: not implemented yet')
nikcleju@17 113 raise Exception('Nic says: not implemented yet')
nikcleju@17 114 #end
nikcleju@17 115
nikcleju@17 116 # Acquire measurements
nikcleju@17 117 y[:,i] = np.dot(M, x0[:,i])
nikcleju@17 118
nikcleju@17 119 # Add noise
nikcleju@17 120 t_norm = np.linalg.norm(y[:,i],2);
nikcleju@17 121 n = np.squeeze(rng.randn(m, 1));
nikcleju@17 122 y[:,i] = y[:,i] + noiselevel * t_norm * n / np.linalg.norm(n, 2);
nikcleju@17 123 #end
nikcleju@17 124
nikcleju@17 125 return x0,y,M,LambdaMat
nikcleju@17 126
nikcleju@17 127 #####################
nikcleju@17 128
nikcleju@17 129 #function [xhat, arepr, lagmult] = ArgminOperL2Constrained(y, M, MH, Omega, OmegaH, Lambdahat, xinit, ilagmult, params)
nikcleju@17 130 def ArgminOperL2Constrained(y, M, MH, Omega, OmegaH, Lambdahat, xinit, ilagmult, params):
nikcleju@17 131
nikcleju@17 132 #
nikcleju@17 133 # This function aims to compute
nikcleju@17 134 # xhat = argmin || Omega(Lambdahat, :) * x ||_2 subject to || y - M*x ||_2 <= epsilon.
nikcleju@17 135 # arepr is the analysis representation corresponding to Lambdahat, i.e.,
nikcleju@17 136 # arepr = Omega(Lambdahat, :) * xhat.
nikcleju@17 137 # The function also returns the lagrange multiplier in the process used to compute xhat.
nikcleju@17 138 #
nikcleju@17 139 # Inputs:
nikcleju@17 140 # y : observation/measurements of an unknown vector x0. It is equal to M*x0 + noise.
nikcleju@17 141 # M : Measurement matrix
nikcleju@17 142 # MH : M', the conjugate transpose of M
nikcleju@17 143 # Omega : analysis operator
nikcleju@17 144 # OmegaH : Omega', the conjugate transpose of Omega. Also, synthesis operator.
nikcleju@17 145 # Lambdahat : an index set indicating some rows of Omega.
nikcleju@17 146 # xinit : initial estimate that will be used for the conjugate gradient algorithm.
nikcleju@17 147 # ilagmult : initial lagrange multiplier to be used in
nikcleju@17 148 # params : parameters
nikcleju@17 149 # params.noise_level : this corresponds to epsilon above.
nikcleju@17 150 # params.max_inner_iteration : `maximum' number of iterations in conjugate gradient method.
nikcleju@17 151 # params.l2_accurary : the l2 accuracy parameter used in conjugate gradient method
nikcleju@17 152 # params.l2solver : if the value is 'pseudoinverse', then direct matrix computation (not conjugate gradient method) is used. Otherwise, conjugate gradient method is used.
nikcleju@17 153 #
nikcleju@17 154
nikcleju@17 155 #d = length(xinit)
nikcleju@17 156 d = xinit.size
nikcleju@17 157 lagmultmax = 1e5;
nikcleju@17 158 lagmultmin = 1e-4;
nikcleju@18 159 lagmultfactor = 2.0;
nikcleju@18 160 accuracy_adjustment_exponent = 4/5.;
nikcleju@17 161 lagmult = max(min(ilagmult, lagmultmax), lagmultmin);
nikcleju@17 162 was_infeasible = 0;
nikcleju@17 163 was_feasible = 0;
nikcleju@17 164
nikcleju@17 165 #######################################################################
nikcleju@17 166 ## Computation done using direct matrix computation from matlab. (no conjugate gradient method.)
nikcleju@17 167 #######################################################################
nikcleju@17 168 #if strcmp(params.l2solver, 'pseudoinverse')
nikcleju@18 169 if params['l2solver'] == 'pseudoinverse':
nikcleju@17 170 #if strcmp(class(M), 'double') && strcmp(class(Omega), 'double')
nikcleju@17 171 if M.dtype == 'float64' and Omega.dtype == 'double':
nikcleju@18 172 while True:
nikcleju@17 173 alpha = math.sqrt(lagmult);
nikcleju@18 174 xhat = np.linalg.lstsq(np.concatenate((M, alpha*Omega[Lambdahat,:])), np.concatenate((y, np.zeros(Lambdahat.size))))[0]
nikcleju@17 175 temp = np.linalg.norm(y - np.dot(M,xhat), 2);
nikcleju@17 176 #disp(['fidelity error=', num2str(temp), ' lagmult=', num2str(lagmult)]);
nikcleju@17 177 if temp <= params['noise_level']:
nikcleju@18 178 was_feasible = True;
nikcleju@18 179 if was_infeasible:
nikcleju@17 180 break;
nikcleju@17 181 else:
nikcleju@17 182 lagmult = lagmult*lagmultfactor;
nikcleju@17 183 elif temp > params['noise_level']:
nikcleju@18 184 was_infeasible = True;
nikcleju@18 185 if was_feasible:
nikcleju@18 186 xhat = xprev.copy();
nikcleju@17 187 break;
nikcleju@17 188 lagmult = lagmult/lagmultfactor;
nikcleju@17 189 if lagmult < lagmultmin or lagmult > lagmultmax:
nikcleju@17 190 break;
nikcleju@18 191 xprev = xhat.copy();
nikcleju@17 192 arepr = np.dot(Omega[Lambdahat, :], xhat);
nikcleju@17 193 return xhat,arepr,lagmult;
nikcleju@17 194
nikcleju@17 195
nikcleju@17 196 ########################################################################
nikcleju@17 197 ## Computation using conjugate gradient method.
nikcleju@17 198 ########################################################################
nikcleju@17 199 #if strcmp(class(MH),'function_handle')
nikcleju@17 200 if hasattr(MH, '__call__'):
nikcleju@17 201 b = MH(y);
nikcleju@17 202 else:
nikcleju@17 203 b = np.dot(MH, y);
nikcleju@17 204
nikcleju@17 205 norm_b = np.linalg.norm(b, 2);
nikcleju@18 206 xhat = xinit.copy();
nikcleju@18 207 xprev = xinit.copy();
nikcleju@17 208 residual = TheHermitianMatrix(xhat, M, MH, Omega, OmegaH, Lambdahat, lagmult) - b;
nikcleju@17 209 direction = -residual;
nikcleju@17 210 iter = 0;
nikcleju@17 211
nikcleju@17 212 while iter < params.max_inner_iteration:
nikcleju@17 213 iter = iter + 1;
nikcleju@17 214 alpha = np.linalg.norm(residual,2)**2 / np.dot(direction.T, TheHermitianMatrix(direction, M, MH, Omega, OmegaH, Lambdahat, lagmult));
nikcleju@17 215 xhat = xhat + alpha*direction;
nikcleju@18 216 prev_residual = residual.copy();
nikcleju@17 217 residual = TheHermitianMatrix(xhat, M, MH, Omega, OmegaH, Lambdahat, lagmult) - b;
nikcleju@17 218 beta = np.linalg.norm(residual,2)**2 / np.linalg.norm(prev_residual,2)**2;
nikcleju@17 219 direction = -residual + beta*direction;
nikcleju@17 220
nikcleju@17 221 if np.linalg.norm(residual,2)/norm_b < params['l2_accuracy']*(lagmult**(accuracy_adjustment_exponent)) or iter == params['max_inner_iteration']:
nikcleju@17 222 #if strcmp(class(M), 'function_handle')
nikcleju@17 223 if hasattr(M, '__call__'):
nikcleju@17 224 temp = np.linalg.norm(y-M(xhat), 2);
nikcleju@17 225 else:
nikcleju@17 226 temp = np.linalg.norm(y-np.dot(M,xhat), 2);
nikcleju@17 227
nikcleju@17 228 #if strcmp(class(Omega), 'function_handle')
nikcleju@17 229 if hasattr(Omega, '__call__'):
nikcleju@17 230 u = Omega(xhat);
nikcleju@17 231 u = math.sqrt(lagmult)*np.linalg.norm(u(Lambdahat), 2);
nikcleju@17 232 else:
nikcleju@17 233 u = math.sqrt(lagmult)*np.linalg.norm(Omega[Lambdahat,:]*xhat, 2);
nikcleju@17 234
nikcleju@17 235
nikcleju@17 236 #disp(['residual=', num2str(norm(residual,2)), ' norm_b=', num2str(norm_b), ' omegapart=', num2str(u), ' fidelity error=', num2str(temp), ' lagmult=', num2str(lagmult), ' iter=', num2str(iter)]);
nikcleju@17 237
nikcleju@17 238 if temp <= params['noise_level']:
nikcleju@18 239 was_feasible = True;
nikcleju@18 240 if was_infeasible:
nikcleju@17 241 break;
nikcleju@17 242 else:
nikcleju@17 243 lagmult = lagmultfactor*lagmult;
nikcleju@17 244 residual = TheHermitianMatrix(xhat, M, MH, Omega, OmegaH, Lambdahat, lagmult) - b;
nikcleju@17 245 direction = -residual;
nikcleju@17 246 iter = 0;
nikcleju@17 247 elif temp > params['noise_level']:
nikcleju@17 248 lagmult = lagmult/lagmultfactor;
nikcleju@18 249 if was_feasible:
nikcleju@18 250 xhat = xprev.copy();
nikcleju@17 251 break;
nikcleju@18 252 was_infeasible = True;
nikcleju@17 253 residual = TheHermitianMatrix(xhat, M, MH, Omega, OmegaH, Lambdahat, lagmult) - b;
nikcleju@17 254 direction = -residual;
nikcleju@17 255 iter = 0;
nikcleju@17 256 if lagmult > lagmultmax or lagmult < lagmultmin:
nikcleju@17 257 break;
nikcleju@18 258 xprev = xhat.copy();
nikcleju@17 259 #elseif norm(xprev-xhat)/norm(xhat) < 1e-2
nikcleju@17 260 # disp(['rel_change=', num2str(norm(xprev-xhat)/norm(xhat))]);
nikcleju@17 261 # if strcmp(class(M), 'function_handle')
nikcleju@17 262 # temp = norm(y-M(xhat), 2);
nikcleju@17 263 # else
nikcleju@17 264 # temp = norm(y-M*xhat, 2);
nikcleju@17 265 # end
nikcleju@17 266 #
nikcleju@17 267 # if temp > 1.2*params.noise_level
nikcleju@17 268 # was_infeasible = 1;
nikcleju@17 269 # lagmult = lagmult/lagmultfactor;
nikcleju@17 270 # xprev = xhat;
nikcleju@17 271 # end
nikcleju@17 272
nikcleju@17 273 #disp(['fidelity_error=', num2str(temp)]);
nikcleju@17 274 print 'fidelity_error=',temp
nikcleju@17 275 #if iter == params['max_inner_iteration']:
nikcleju@17 276 #disp('max_inner_iteration reached. l2_accuracy not achieved.');
nikcleju@17 277
nikcleju@17 278 ##
nikcleju@17 279 # Compute analysis representation for xhat
nikcleju@17 280 ##
nikcleju@17 281 #if strcmp(class(Omega),'function_handle')
nikcleju@17 282 if hasattr(Omega, '__call__'):
nikcleju@17 283 temp = Omega(xhat);
nikcleju@17 284 arepr = temp(Lambdahat);
nikcleju@17 285 else: ## here Omega is assumed to be a matrix
nikcleju@17 286 arepr = np.dot(Omega[Lambdahat, :], xhat);
nikcleju@17 287
nikcleju@17 288 return xhat,arepr,lagmult
nikcleju@17 289
nikcleju@17 290
nikcleju@17 291 ##
nikcleju@17 292 # This function computes (M'*M + lm*Omega(L,:)'*Omega(L,:)) * x.
nikcleju@17 293 ##
nikcleju@17 294 #function w = TheHermitianMatrix(x, M, MH, Omega, OmegaH, L, lm)
nikcleju@17 295 def TheHermitianMatrix(x, M, MH, Omega, OmegaH, L, lm):
nikcleju@17 296 #if strcmp(class(M), 'function_handle')
nikcleju@17 297 if hasattr(M, '__call__'):
nikcleju@17 298 w = MH(M(x));
nikcleju@17 299 else: ## M and MH are matrices
nikcleju@17 300 w = np.dot(np.dot(MH, M), x);
nikcleju@17 301
nikcleju@17 302 if hasattr(Omega, '__call__'):
nikcleju@17 303 v = Omega(x);
nikcleju@17 304 vt = np.zeros(v.size);
nikcleju@17 305 vt[L] = v[L].copy();
nikcleju@17 306 w = w + lm*OmegaH(vt);
nikcleju@17 307 else: ## Omega is assumed to be a matrix and OmegaH is its conjugate transpose
nikcleju@17 308 w = w + lm*np.dot(np.dot(OmegaH[:, L],Omega[L, :]),x);
nikcleju@17 309
nikcleju@17 310 return w
nikcleju@18 311
nikcleju@18 312 def GAP(y, M, MH, Omega, OmegaH, params, xinit):
nikcleju@18 313 #function [xhat, Lambdahat] = GAP(y, M, MH, Omega, OmegaH, params, xinit)
nikcleju@18 314
nikcleju@18 315 ##
nikcleju@18 316 # [xhat, Lambdahat] = GAP(y, M, MH, Omega, OmegaH, params, xinit)
nikcleju@18 317 #
nikcleju@18 318 # Greedy Analysis Pursuit Algorithm
nikcleju@18 319 # This aims to find an approximate (sometimes exact) solution of
nikcleju@18 320 # xhat = argmin || Omega * x ||_0 subject to || y - M * x ||_2 <= epsilon.
nikcleju@18 321 #
nikcleju@18 322 # Outputs:
nikcleju@18 323 # xhat : estimate of the target cosparse vector x0.
nikcleju@18 324 # Lambdahat : estimate of the cosupport of x0.
nikcleju@18 325 #
nikcleju@18 326 # Inputs:
nikcleju@18 327 # y : observation/measurement vector of a target cosparse solution x0,
nikcleju@18 328 # given by relation y = M * x0 + noise.
nikcleju@18 329 # M : measurement matrix. This should be given either as a matrix or as a function handle
nikcleju@18 330 # which implements linear transformation.
nikcleju@18 331 # MH : conjugate transpose of M.
nikcleju@18 332 # Omega : analysis operator. Like M, this should be given either as a matrix or as a function
nikcleju@18 333 # handle which implements linear transformation.
nikcleju@18 334 # OmegaH : conjugate transpose of OmegaH.
nikcleju@18 335 # params : parameters that govern the behavior of the algorithm (mostly).
nikcleju@18 336 # params.num_iteration : GAP performs this number of iterations.
nikcleju@18 337 # params.greedy_level : determines how many rows of Omega GAP eliminates at each iteration.
nikcleju@18 338 # if the value is < 1, then the rows to be eliminated are determined by
nikcleju@18 339 # j : |omega_j * xhat| > greedy_level * max_i |omega_i * xhat|.
nikcleju@18 340 # if the value is >= 1, then greedy_level is the number of rows to be
nikcleju@18 341 # eliminated at each iteration.
nikcleju@18 342 # params.stopping_coefficient_size : when the maximum analysis coefficient is smaller than
nikcleju@18 343 # this, GAP terminates.
nikcleju@18 344 # params.l2solver : legitimate values are 'pseudoinverse' or 'cg'. determines which method
nikcleju@18 345 # is used to compute
nikcleju@18 346 # argmin || Omega_Lambdahat * x ||_2 subject to || y - M * x ||_2 <= epsilon.
nikcleju@18 347 # params.l2_accuracy : when l2solver is 'cg', this determines how accurately the above
nikcleju@18 348 # problem is solved.
nikcleju@18 349 # params.noise_level : this corresponds to epsilon above.
nikcleju@18 350 # xinit : initial estimate of x0 that GAP will start with. can be zeros(d, 1).
nikcleju@18 351 #
nikcleju@18 352 # Examples:
nikcleju@18 353 #
nikcleju@18 354 # Not particularly interesting:
nikcleju@18 355 # >> d = 100; p = 110; m = 60;
nikcleju@18 356 # >> M = randn(m, d);
nikcleju@18 357 # >> Omega = randn(p, d);
nikcleju@18 358 # >> y = M * x0 + noise;
nikcleju@18 359 # >> params.num_iteration = 40;
nikcleju@18 360 # >> params.greedy_level = 0.9;
nikcleju@18 361 # >> params.stopping_coefficient_size = 1e-4;
nikcleju@18 362 # >> params.l2solver = 'pseudoinverse';
nikcleju@18 363 # >> [xhat, Lambdahat] = GAP(y, M, M', Omega, Omega', params, zeros(d, 1));
nikcleju@18 364 #
nikcleju@18 365 # Assuming that FourierSampling.m, FourierSamplingH.m, FDAnalysis.m, etc. exist:
nikcleju@18 366 # >> n = 128;
nikcleju@18 367 # >> M = @(t) FourierSampling(t, n);
nikcleju@18 368 # >> MH = @(u) FourierSamplingH(u, n);
nikcleju@18 369 # >> Omega = @(t) FDAnalysis(t, n);
nikcleju@18 370 # >> OmegaH = @(u) FDSynthesis(t, n);
nikcleju@18 371 # >> params.num_iteration = 1000;
nikcleju@18 372 # >> params.greedy_level = 50;
nikcleju@18 373 # >> params.stopping_coefficient_size = 1e-5;
nikcleju@18 374 # >> params.l2solver = 'cg'; # in fact, 'pseudoinverse' does not even make sense.
nikcleju@18 375 # >> [xhat, Lambdahat] = GAP(y, M, MH, Omega, OmegaH, params, zeros(d, 1));
nikcleju@18 376 #
nikcleju@18 377 # Above: FourierSampling and FourierSamplingH are conjugate transpose of each other.
nikcleju@18 378 # FDAnalysis and FDSynthesis are conjugate transpose of each other.
nikcleju@18 379 # These routines are problem specific and need to be implemented by the user.
nikcleju@18 380
nikcleju@18 381 #d = length(xinit(:));
nikcleju@18 382 d = xinit.size
nikcleju@18 383
nikcleju@18 384 #if strcmp(class(Omega), 'function_handle')
nikcleju@18 385 # p = length(Omega(zeros(d,1)));
nikcleju@18 386 #else ## Omega is a matrix
nikcleju@18 387 # p = size(Omega, 1);
nikcleju@18 388 #end
nikcleju@18 389 if hasattr(Omega, '__call__'):
nikcleju@18 390 p = Omega(np.zeros((d,1)))
nikcleju@18 391 else:
nikcleju@18 392 p = Omega.shape[0]
nikcleju@18 393
nikcleju@18 394
nikcleju@18 395 iter = 0
nikcleju@18 396 lagmult = 1e-4
nikcleju@18 397 #Lambdahat = 1:p;
nikcleju@18 398 Lambdahat = np.arange(p)
nikcleju@18 399 #while iter < params.num_iteration
nikcleju@18 400 while iter < params["num_iteration"]:
nikcleju@18 401 iter = iter + 1
nikcleju@18 402 #[xhat, analysis_repr, lagmult] = ArgminOperL2Constrained(y, M, MH, Omega, OmegaH, Lambdahat, xinit, lagmult, params);
nikcleju@18 403 xhat,analysis_repr,lagmult = ArgminOperL2Constrained(y, M, MH, Omega, OmegaH, Lambdahat, xinit, lagmult, params)
nikcleju@18 404 #[to_be_removed, maxcoef] = FindRowsToRemove(analysis_repr, params.greedy_level);
nikcleju@18 405 to_be_removed, maxcoef = FindRowsToRemove(analysis_repr, params["greedy_level"])
nikcleju@18 406 #disp(['** maxcoef=', num2str(maxcoef), ' target=', num2str(params.stopping_coefficient_size), ' rows_remaining=', num2str(length(Lambdahat)), ' lagmult=', num2str(lagmult)]);
nikcleju@18 407 print '** maxcoef=',maxcoef,' target=',params['stopping_coefficient_size'],' rows_remaining=',Lambdahat.size,' lagmult=',lagmult
nikcleju@18 408 if check_stopping_criteria(xhat, xinit, maxcoef, lagmult, Lambdahat, params):
nikcleju@18 409 break
nikcleju@18 410
nikcleju@18 411 xinit = xhat.copy()
nikcleju@18 412 #Lambdahat[to_be_removed] = []
nikcleju@18 413 Lambdahat = np.delete(Lambdahat, to_be_removed)
nikcleju@18 414
nikcleju@18 415 #n = sqrt(d);
nikcleju@18 416 #figure(9);
nikcleju@18 417 #RR = zeros(2*n, n-1);
nikcleju@18 418 #RR(Lambdahat) = 1;
nikcleju@18 419 #XD = ones(n, n);
nikcleju@18 420 #XD(:, 2:end) = XD(:, 2:end) .* RR(1:n, :);
nikcleju@18 421 #XD(:, 1:(end-1)) = XD(:, 1:(end-1)) .* RR(1:n, :);
nikcleju@18 422 #XD(2:end, :) = XD(2:end, :) .* RR((n+1):(2*n), :)';
nikcleju@18 423 #XD(1:(end-1), :) = XD(1:(end-1), :) .* RR((n+1):(2*n), :)';
nikcleju@18 424 #XD = FD2DiagnosisPlot(n, Lambdahat);
nikcleju@18 425 #imshow(XD);
nikcleju@18 426 #figure(10);
nikcleju@18 427 #imshow(reshape(real(xhat), n, n));
nikcleju@18 428
nikcleju@18 429 #return;
nikcleju@18 430 return xhat, Lambdahat
nikcleju@18 431
nikcleju@18 432 def FindRowsToRemove(analysis_repr, greedy_level):
nikcleju@18 433 #function [to_be_removed, maxcoef] = FindRowsToRemove(analysis_repr, greedy_level)
nikcleju@18 434
nikcleju@18 435 #abscoef = abs(analysis_repr(:));
nikcleju@18 436 abscoef = np.abs(analysis_repr)
nikcleju@18 437 #n = length(abscoef);
nikcleju@18 438 n = abscoef.size
nikcleju@18 439 #maxcoef = max(abscoef);
nikcleju@18 440 maxcoef = abscoef.max()
nikcleju@18 441 if greedy_level >= 1:
nikcleju@18 442 #qq = quantile(abscoef, 1.0-greedy_level/n);
nikcleju@18 443 qq = sp.stats.mstats.mquantile(abscoef, 1.0-greedy_level/n, 0.5, 0.5)
nikcleju@18 444 else:
nikcleju@18 445 qq = maxcoef*greedy_level
nikcleju@18 446
nikcleju@18 447 #to_be_removed = find(abscoef >= qq);
nikcleju@18 448 to_be_removed = np.nonzero(abscoef >= qq)
nikcleju@18 449 #return;
nikcleju@18 450 return to_be_removed, maxcoef
nikcleju@18 451
nikcleju@18 452 def check_stopping_criteria(xhat, xinit, maxcoef, lagmult, Lambdahat, params):
nikcleju@18 453 #function r = check_stopping_criteria(xhat, xinit, maxcoef, lagmult, Lambdahat, params)
nikcleju@18 454
nikcleju@18 455 #if isfield(params, 'stopping_coefficient_size') && maxcoef < params.stopping_coefficient_size
nikcleju@18 456 if ('stopping_coefficient_size' in params) and maxcoef < params['stopping_coefficient_size']:
nikcleju@18 457 return 1
nikcleju@18 458
nikcleju@18 459 #if isfield(params, 'stopping_lagrange_multiplier_size') && lagmult > params.stopping_lagrange_multiplier_size
nikcleju@18 460 if ('stopping_lagrange_multiplier_size' in params) and lagmult > params['stopping_lagrange_multiplier_size']:
nikcleju@18 461 return 1
nikcleju@18 462
nikcleju@18 463 #if isfield(params, 'stopping_relative_solution_change') && norm(xhat-xinit)/norm(xhat) < params.stopping_relative_solution_change
nikcleju@18 464 if ('stopping_relative_solution_change' in params) and np.linalg.norm(xhat-xinit)/np.linalg.norm(xhat) < params['stopping_relative_solution_change']:
nikcleju@18 465 return 1
nikcleju@18 466
nikcleju@18 467 #if isfield(params, 'stopping_cosparsity') && length(Lambdahat) < params.stopping_cosparsity
nikcleju@18 468 if ('stopping_cosparsity' in params) and Lambdahat.size() < params['stopping_cosparsity']:
nikcleju@18 469 return 1
nikcleju@18 470
nikcleju@18 471 return 0