def quad_form(x, P): x,P = map(Expression.cast_to_const, (x,P)) # Check dimensions. n = P.size[0] if P.size[1] != n or x.size != (n,1): raise Exception("Invalid dimensions for arguments.") if x.is_constant(): return x.T*P*x elif P.is_constant(): np_intf = intf.get_matrix_interface(np.ndarray) P = np_intf.const_to_matrix(P.value) # Replace P with symmetric version. P = (P + P.T)/2 # Check if P is PSD. eigvals, V = LA.eig(P) eigvals = eigvals.real if min(eigvals) >= 0: diag_eig = np.diag(np.sqrt(eigvals)) P_sqrt = Constant(diag_eig.dot(V.T)) return square(norm2(P_sqrt*x)) elif max(eigvals) <= 0: diag_eig = np.diag(np.sqrt(-eigvals)) P_sqrt = Constant(diag_eig.dot(V.T)) return -square(norm2(P_sqrt*x)) else: raise Exception("P has both positive and negative eigenvalues.") else: raise Exception("At least one argument to quad_form must be constant.")
def quad_form(x, P): """ Alias for :math:`x^T P x`. """ x, P = map(Expression.cast_to_const, (x, P)) # Check dimensions. n = P.size[0] if P.size[1] != n or x.size != (n, 1): raise Exception("Invalid dimensions for arguments.") if x.is_constant(): return x.T * P * x elif P.is_constant(): np_intf = intf.get_matrix_interface(np.ndarray) P = np_intf.const_to_matrix(P.value) sgn, scale, M = _decomp_quad(P) return sgn * scale * square(norm2(Constant(M.T) * x)) else: raise Exception("At least one argument to quad_form must be constant.")
def quad_form(x, P): """ Alias for :math:`x^T P x`. """ x,P = map(Expression.cast_to_const, (x,P)) # Check dimensions. n = P.size[0] if P.size[1] != n or x.size != (n,1): raise Exception("Invalid dimensions for arguments.") if x.is_constant(): return x.T * P * x elif P.is_constant(): np_intf = intf.get_matrix_interface(np.ndarray) P = np_intf.const_to_matrix(P.value) sgn, scale, M = _decomp_quad(P) return sgn * scale * square(norm2(Constant(M.T) * x)) else: raise Exception("At least one argument to quad_form must be constant.")