def run(y, A): """ Run the specified SL0 reconstruction algorithm. The available SL0 reconstruction algorithms are the original SL0 and the modified SL0. Which of the available SL0 reconstruction algorithms is used, is specified as a configuration option. Parameters ---------- y : ndarray The m x 1 measurement vector. A : ndarray The m x n matrix which is the product of the measurement matrix and the dictionary matrix. Returns ------- alpha : ndarray The n x 1 reconstructed coefficient vector. See Also -------- magni.cs.reconstruction.sl0.config : Configuration options. magni.cs.reconstruction.sl0._original.run : The original SL0 reconstruction algorithm. magni.cs.reconstruction.sl0._modified.run : The modified SL0 reconstruction algorithm. Examples -------- See the individual run functions in the implementations of the original and modified SL0 reconstruction algorithms. """ _validate_run(y, A) algorithm = _config.get('algorithm') if algorithm == 'std': x = _original.run(y, A) elif algorithm == 'mod': x = _modified.run(y, A) return x
def _run_proj(y, A): """ Run the original *projection* SL0 reconstruction algorithm. This function implements the algorithm with an unconstrained gradient step followed by a projection back onto the feasible set. Parameters ---------- y : ndarray The m x 1 measurement vector. A : ndarray The m x n matrix which is the product of the measurement matrix and the dictionary matrix. Returns ------- alpha : ndarray The n x 1 reconstructed coefficient vector. """ param = _config.get() sigma_min = param['sigma_min'] L = int(np.round(param['L'])) mu = param['mu'] sigma_update = param['sigma_update'] Q, R = scipy.linalg.qr(A.T, mode='economic') A_pinv = Q.dot(scipy.linalg.inv(R.T)) x = A_pinv.dot(y) sigma = param['precision_float'](2) * np.abs(x).max() while sigma > sigma_min: for j in range(L): d = x * np.exp(-x ** 2 / (2 * sigma ** 2)) x = x - mu * d x = x - A_pinv.dot(A.dot(x) - y) # Projection sigma = sigma * sigma_update return x
def _run_feas(y, A): """ Run the original *feasibility* SL0 reconstruction algorithm. This function implements the algorithm with a search on the feasible set. Parameters ---------- y : ndarray The m x 1 measurement vector. A : ndarray The m x n matrix which is the product of the measurement matrix and the dictionary matrix. Returns ------- alpha : ndarray The n x 1 reconstructed coefficient vector. """ param = _config.get() sigma_min = param['sigma_min'] L = int(np.round(param['L'])) mu = param['mu'] sigma_update = param['sigma_update'] Q, R = scipy.linalg.qr(A.T, mode='economic') IP = np.eye(A.shape[1]) - Q.dot(Q.T) x = Q.dot(scipy.linalg.solve_triangular(R, y, trans='T')) sigma = param['precision_float'](2) * np.abs(x).max() while sigma > sigma_min: for j in range(L): d = np.exp(-x ** 2 / (2 * sigma ** 2)) * x x = x - mu * IP.dot(d) # Search on feasible set sigma = sigma * sigma_update return x
def _run_proj(y, A): """ Run the original *projection* SL0 reconstruction algorithm. This function implements the algorithm with an unconstrained gradient step followed by a projection back onto the feasible set. Parameters ---------- y : ndarray The m x 1 measurement vector. A : ndarray The m x n matrix which is the product of the measurement matrix and the dictionary matrix. Returns ------- alpha : ndarray The n x 1 reconstructed coefficient vector. """ param = _config.get() sigma_update = param['sigma_update'] sigma_min = param['sigma_min'] L = param['L'] L_update = param['L_update'] mu_start = param['mu_start'] mu_end = param['mu_end'] epsilon = param['epsilon'] Q, R = scipy.linalg.qr(A.T, mode='economic') A_pinv = Q.dot(scipy.linalg.inv(R.T)) x = A_pinv.dot(y) mult = _calc_sigma_start(A.shape[0] / A.shape[1]) sigma = mult * np.abs(x).max() x_zeros = np.zeros(x.shape) i = 0 while sigma > sigma_min: if i < 4 or mult * sigma_update**i > 0.75: if A.shape[0] / A.shape[1] <= 0.5: mu = 50 * mu_start else: mu = mu_start else: mu = mu_end x_prev = x_zeros j = 0 while scipy.linalg.norm(x - x_prev) > sigma * epsilon and j <= L: x_prev = x.copy() d = np.exp(-(x ** 2) / (2 * sigma ** 2)) * x x = x - mu * d x = x - A_pinv.dot(A.dot(x) - y) # Projection j = j + 1 sigma = sigma * sigma_update L = L * L_update i = i + 1 return x
def _run_feas(y, A): """ Run the modified *feasibility* SL0 reconstruction algorithm. This function implements the algorithm with a search on the feasible set. Parameters ---------- y : ndarray The m x 1 measurement vector. A : ndarray The m x n matrix which is the product of the measurement matrix and the dictionary matrix. Returns ------- alpha : ndarray The n x 1 reconstructed coefficient vector. """ param = _config.get() sigma_update = param['sigma_update'] sigma_min = param['sigma_min'] L = param['L'] L_update = param['L_update'] mu_start = param['mu_start'] mu_end = param['mu_end'] epsilon = param['epsilon'] Q, R = scipy.linalg.qr(A.T) Q1 = Q[:, :A.shape[0]] Q2 = Q[:, A.shape[0]:] R = R[:R.shape[1], :] x = Q1.dot(scipy.linalg.solve_triangular(R, y, trans='T')) mult = _calc_sigma_start(A.shape[0] / A.shape[1]) sigma = mult * np.abs(x).max() x_zeros = np.zeros(x.shape) i = 0 while sigma > sigma_min: if i < 4 or mult * sigma_update**i > 0.75: if A.shape[0] / A.shape[1] <= 0.5: mu = 50 * mu_start else: mu = mu_start else: mu = mu_end x_prev = x_zeros j = 0 while scipy.linalg.norm(x - x_prev) > sigma * epsilon and j <= L: x_prev = x.copy() d = np.exp(-(x ** 2) / (2 * sigma ** 2)) * x nabla = Q2.T.dot(d) x = x - Q2.dot(mu * nabla) # Search on feasible set j = j + 1 sigma = sigma * sigma_update L = L * L_update i = i + 1 return x