def prox_quad_form(v, t=1, Q=None, method="lsqr", *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f(x) = x^TQx` for symmetric :math:`Q \\succeq 0`, scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(v): v = np.array([v]) if Q is None: raise ValueError("Q must be a matrix.") elif np.isscalar(Q): Q = np.array([[Q]]) if Q.shape[0] != Q.shape[1]: raise ValueError("Q must be a square matrix.") if Q.shape[0] != v.shape[0]: raise ValueError("Dimension mismatch: nrow(Q) != nrow(v).") if sparse.issparse(Q): Q_min_eigval = sparse.linalg.eigsh(Q, k=1, which="SA", return_eigenvectors=False)[0] if np.iscomplex(Q_min_eigval) or Q_min_eigval < 0: raise ValueError( "Q must be a symmetric positive semidefinite matrix.") else: if not np.all(np.linalg.eigvalsh(Q) >= 0): raise ValueError( "Q must be a symmetric positive semidefinite matrix.") if method not in ["lsqr", "lstsq"]: raise ValueError("method must be either 'lsqr' or 'lstsq'") return prox_scale(prox_quad_form_base, Q=Q, method=method, *args, **kwargs)(v, t)
def prox_exp(v, t=1, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f(x) = \\exp(x)` applied elementwise for scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ return prox_scale(prox_exp_base, *args, **kwargs)(v, t)
def prox_sum_squares_affine(v, t=1, F=None, g=None, method="lsqr", *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f(x) = \\|Fx - g\\|_2^2` for matrix F, vector g, scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(v): v = np.array([v]) if F is None: raise ValueError("F must be a matrix.") elif np.isscalar(F): F = np.array([[F]]) if g is None: raise ValueError("g must be a vector.") elif np.isscalar(g): g = np.array([g]) if F.shape[0] != g.shape[0]: raise ValueError("Dimension mismatch: nrow(F) != nrow(g).") if F.shape[1] != v.shape[0]: raise ValueError("Dimension mismatch: ncol(F) != nrow(v).") if method not in ["lsqr", "lstsq"]: raise ValueError("method must be either 'lsqr' or 'lstsq'.") return prox_scale(prox_sum_squares_affine_base, F=F, g=g, method=method, *args, **kwargs)(v, t)
def prox_box_constr(v, t=1, v_lo=-np.inf, v_hi=np.inf, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f` is the set indicator that :math:`\\underline x \\leq x \\leq \\overline x`. Here the lower/upper bounds are (v_lo, v_hi), which default to (-Inf, Inf). The scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ return prox_scale(prox_box_constr_base, v_lo, v_hi, *args, **kwargs)(v, t)
def prox_sigma_max(B, t = 1, *args, **kwargs): """Proximal operator of :math:`tf(aB-b) + cB + d\\|B\\|_F^2`, where :math:`f(B) = \\sigma_{\\max}(B)` is the maximum singular value of :math:`B`, for scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ return prox_scale(prox_sigma_max_base, *args, **kwargs)(B, t)
def prox_max(v, t = 1, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f(x) = \\max_i x_i` for scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(v): v = np.array([v]) return prox_scale(prox_max_base, *args, **kwargs)(v, t)
def prox_norm_fro(B, t = 1, *args, **kwargs): """Proximal operator of :math:`tf(aB-b) + cB + d\\|B\\|_F^2`, where :math:`f(B) = \\|B\\|_2` for scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(B): B = np.array([[B]]) return prox_scale(prox_norm_fro_base, *args, **kwargs)(B, t)
def prox_kl(v, t = 1, u = None, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f(x) = \\sum_i x_i*\\log(x_i/u_i)` for scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(v): v = np.array([v]) if u is None: u = np.ones(v.shape) return prox_scale(prox_kl_base, u, *args, **kwargs)(v, t)
def prox_neg_log_det(B, t = 1, *args, **kwargs): """Proximal operator of :math:`tf(aB-b) + cB + d\\|B\\|_F^2`, where :math:`f(B) = -\\log\\det(B)`, where `B` is a symmetric matrix. The scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if B.shape[0] != B.shape[1]: raise ValueError("B must be a square matrix.") B_symm = (B + B.T) / 2.0 if not (np.allclose(B, B_symm)): raise ValueError("B must be a symmetric matrix.") return prox_scale(prox_neg_log_det_base, *args, **kwargs)(B_symm, t)
def prox_soc(v, t=1, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f` is the set indicator that :math:`\\|x_{1:n}\\|_2 \\leq x_{n+1}`. The scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(v) or not (len(v.shape) == 1 or (len(v.shape) == 2 and v.shape[1] == 1)): raise ValueError("v must be a vector") if v.shape[0] < 2: raise ValueError("v must have at least 2 elements.") return prox_scale(prox_soc_base, *args, **kwargs)(v, t)
def prox_huber(v, t=1, M=1, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where .. math:: f(x) = \\begin{cases} 2M|x|-M^2 & \\text{for } |x| \\geq |M| \\\\ |x|^2 & \\text{for } |x| \\leq |M| \\end{cases} applied elementwise for scalar M > 0, t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have M > 0, t > 0, a = non-zero, and d >= 0. By default, M = 1, t = 1, a = 1, b = 0, c = 0, and d = 0. """ return prox_scale(prox_huber_base, M, *args, **kwargs)(v, t)
def prox_logistic(v, t = 1, x0 = None, y = None, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f(x) = \\sum_i \\log(1 + \\exp(-y_i*x_i))` for scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(v): v = np.array([v]) if x0 is None: # x0 = np.random.randn(*v.shape) x0 = v if y is None: y = -np.ones(v.shape) return prox_scale(prox_logistic_base, x0, y, *args, **kwargs)(v, t)
def prox_psd_cone(B, t=1, *args, **kwargs): """Proximal operator of :math:`tf(aB-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f` is the set indicator that :math:`B \\succeq 0` for :math:`B` a symmetric matrix. The scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(B): B = np.array([[B]]) if B.shape[0] != B.shape[1]: raise ValueError("B must be a square matrix.") B_symm = (B + B.T) / 2.0 if not np.allclose(B, B_symm): raise ValueError("B must be a symmetric matrix.") return prox_scale(prox_psd_cone_base, *args, **kwargs)(B_symm, t)
def prox_trace(B, t = 1, C = None, *args, **kwargs): """Proximal operator of :math:`tf(aB-b) + cB + d\\|B\\|_F^2`, where :math:`f(B) = tr(C^TB)` is the trace of :math:`C^TB`, where C is a given matrix quantity. By default, C is the identity matrix, so :math:`f(B) = tr(B)`. The scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if np.isscalar(B): B = np.array([[B]]) if C is None: C = sparse.eye(B.shape[0]) if B.shape[0] != C.shape[0]: raise ValueError("Dimension mismatch: nrow(B) != nrow(C)") if B.shape[1] != C.shape[1]: raise ValueError("Dimension mismatch: ncol(B) != ncol(C)") return prox_scale(prox_trace_base, C=C, *args, **kwargs)(B, t)
def prox_qp(v, t=1, Q=None, q=None, F=None, g=None, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f(x) = x^TQx+q^Tx+I{Fx<=g}` for scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ if Q is None: raise ValueError("Q must be a matrix") if q is None: raise ValueError("q must be a vector") if F is None: raise ValueError("F must be a matrix") if g is None: raise ValueError("g must be a vector") if Q.shape[0] != Q.shape[1]: raise ValueError("Q must be square") if Q.shape[0] != q.shape[0]: raise ValueError("Dimension mismatch: nrow(Q) != nrow(q)") if Q.shape[1] != v.shape[0]: raise ValueError("Dimension mismatch: ncol(Q) != nrow(v)") if F.shape[0] != g.shape[0]: raise ValueError("Dimension mismatch: nrow(F) != nrow(g)") if F.shape[1] != v.shape[0]: raise ValueError("Dimension mismatch: ncol(F) != nrow(v)") return prox_scale(prox_qp_base(Q, q, F, g), *args, **kwargs)(v, t)
def prox_nonpos_constr(v, t=1, *args, **kwargs): """Proximal operator of :math:`tf(ax-b) + c^Tx + d\\|x\\|_2^2`, where :math:`f` is the set indicator that :math:`x \\leq 0`. The scalar t > 0, and the optional arguments are a = scale, b = offset, c = lin_term, and d = quad_term. We must have t > 0, a = non-zero, and d >= 0. By default, t = 1, a = 1, b = 0, c = 0, and d = 0. """ return prox_scale(prox_nonpos_constr_base, *args, **kwargs)(v, t)