def loggamma(x): """Elementwise log of the gamma function. Implementation has modest accuracy over the full range, approaching perfect accuracy as x goes to infinity. """ return maximum( 2.18382 - 3.62887 * x, 1.79241 - 2.4902 * x, 1.21628 - 1.37035 * x, 0.261474 - 0.28904 * x, 0.577216 - 0.577216 * x, -0.175517 + 0.03649 * x, -1.27572 + 0.621514 * x, -0.845568 + 0.422784 * x, -0.577216 * x - log(x), 0.918939 - x - entr(x) - 0.5 * log(x), )
def loggamma(x): """Elementwise log of the gamma function. Implementation has modest accuracy over the full range, approaching perfect accuracy as x goes to infinity. For details on the nature of the approximation, refer to `CVXPY GitHub Issue #228 <https://github.com/cvxpy/cvxpy/issues/228#issuecomment-544281906>`_. """ return maximum( 2.18382 - 3.62887*x, 1.79241 - 2.4902*x, 1.21628 - 1.37035*x, 0.261474 - 0.28904*x, 0.577216 - 0.577216*x, -0.175517 + 0.03649*x, -1.27572 + 0.621514*x, -0.845568 + 0.422784*x, -0.577216*x - log(x), 0.918939 - x - entr(x) - 0.5*log(x), )
def log_det_canon(expr, args): """Reduces the atom to an affine expression and list of constraints. Creates the equivalent problem:: maximize sum(log(D[i, i])) subject to: D diagonal diag(D) = diag(Z) Z is upper triangular. [D Z; Z.T A] is positive semidefinite The problem computes the LDL factorization: .. math:: A = (Z^TD^{-1})D(D^{-1}Z) This follows from the inequality: .. math:: \\det(A) >= \\det(D) + \\det([D, Z; Z^T, A])/\\det(D) >= \\det(D) because (Z^TD^{-1})D(D^{-1}Z) is a feasible D, Z that achieves det(A) = det(D) and the objective maximizes det(D). Parameters ---------- expr : log_det args : list The arguments for the expression Returns ------- tuple (Variable for objective, list of constraints) """ A = args[0] # n by n matrix. n, _ = A.shape z = Variable(shape=(n * (n + 1) // 2, )) Z = vec_to_upper_tri(z, strict=False) d = diag_mat(Z) # a vector D = diag_vec(d) # a matrix X = bmat([[D, Z], [Z.T, A]]) constraints = [PSD(X)] log_expr = log(d) obj, constr = log_canon(log_expr, log_expr.args) constraints += constr return sum(obj), constraints
def one_minus_pos_canon(expr, args): return log(expr._ones - exp(args[0])), []
def log_det_canon(expr, args): """Reduces the atom to an affine expression and list of constraints. Creates the equivalent problem:: maximize sum(log(D[i, i])) subject to: D diagonal diag(D) = diag(Z) Z is upper triangular. [D Z; Z.T A] is positive semidefinite The problem computes the LDL factorization: .. math:: A = (Z^TD^{-1})D(D^{-1}Z) This follows from the inequality: .. math:: \\det(A) >= \\det(D) + \\det([D, Z; Z^T, A])/\\det(D) >= \\det(D) because (Z^TD^{-1})D(D^{-1}Z) is a feasible D, Z that achieves det(A) = det(D) and the objective maximizes det(D). Parameters ---------- expr : log_det args : list The arguments for the expression Returns ------- tuple (Variable for objective, list of constraints) """ A = args[0] # n by n matrix. n, _ = A.shape # Require that X and A are PSD. X = Variable((2 * n, 2 * n), PSD=True) constraints = [PSD(A)] # Fix Z as upper triangular # TODO represent Z as upper tri vector. Z = Variable((n, n)) Z_lower_tri = upper_tri(transpose(Z)) constraints.append(Z_lower_tri == 0) # Fix diag(D) = diag(Z): D[i, i] = Z[i, i] D = Variable(n) constraints.append(D == diag_mat(Z)) # Fix X using the fact that A must be affine by the DCP rules. # X[0:n, 0:n] == D constraints.append(X[0:n, 0:n] == diag_vec(D)) # X[0:n, n:2*n] == Z, constraints.append(X[0:n, n:2 * n] == Z) # X[n:2*n, n:2*n] == A constraints.append(X[n:2 * n, n:2 * n] == A) # Add the objective sum(log(D[i, i]) log_expr = log(D) obj, constr = log_canon(log_expr, log_expr.args) constraints += constr return sum(obj), constraints
def log_canon(expr, args): return log(args[0]), []