def partial_trace(expr, dims: Tuple[int], axis: Optional[int] = 0): """ Assumes :math:`\\texttt{expr} = X_1 \\otimes \\cdots \\otimes X_n` is a 2D Kronecker product composed of :math:`n = \\texttt{len(dims)}` implicit subsystems. Letting :math:`k = \\texttt{axis}`, the returned expression represents the *partial trace* of :math:`\\texttt{expr}` along its :math:`k^{\\text{th}}` implicit subsystem: .. math:: \\text{tr}(X_k) (X_1 \\otimes \\cdots \\otimes X_{k-1} \\otimes X_{k+1} \\otimes \\cdots \\otimes X_n). Parameters ---------- expr : :class:`~cvxpy.expressions.expression.Expression` The 2D expression to take the partial trace of. dims : tuple of ints. A tuple of integers encoding the dimensions of each subsystem. axis : int The index of the subsystem to be traced out from the tensor product that defines expr. """ expr = Atom.cast_to_const(expr) if expr.ndim < 2 or expr.shape[0] != expr.shape[1]: raise ValueError("Only supports square matrices.") if axis < 0 or axis >= len(dims): raise ValueError( f"Invalid axis argument, should be between 0 and {len(dims)}, got {axis}." ) if expr.shape[0] != np.prod(dims): raise ValueError( "Dimension of system doesn't correspond to dimension of subsystems." ) return sum([_term(expr, j, dims, axis) for j in range(dims[axis])])
def partial_transpose(expr, dims: Tuple[int], axis: Optional[int] = 0): """Partial transpose of a matrix. Assumes :math:`expr = X1 \\odots ... \\odots Xn` is a 2D tensor product composed implicitly of n subsystems. Here :math:`\\odots` denotes the Kronecker product, and axis=k is the index of the subsystem to be transposed from the tensor product that defines expr. Returns :math:`X1 \\odots ... \\odots Xk^T \\odots ... \\odots Xn` Parameters ---------- expr : :class:`~cvxpy.expressions.expression.Expression` The 2D expression to take the partial transpose of. dims : tuple of ints. A tuple of integers encoding the dimensions of each subsystem. axis : int The index of the subsystem to be transposed from the tensor product that defines expr. """ expr = Atom.cast_to_const(expr) if expr.ndim < 2 or expr.shape[0] != expr.shape[1]: raise ValueError("Only supports square matrices.") if axis < 0 or axis >= len(dims): raise ValueError( f"Invalid axis argument, should be between 0 and {len(dims)}, got {axis}." ) if expr.shape[0] != np.prod(dims): raise ValueError( "Dimension of system doesn't correspond to dimension of subsystems." ) return sum([ _term(expr, i, j, dims, axis) for i in range(dims[axis]) for j in range(dims[axis]) ])
def __init__(self, y, parent): """ Parameters ---------- y : cvxpy.expressions.expression.Expression Must satisfy ``y.is_affine() == True``. parent : cvxpy.transforms.suppfunc.SuppFunc The object containing data for the convex set associated with this atom. """ self.id = lu.get_id() self.args = [Atom.cast_to_const(y)] self._parent = parent self._eta = None # store for debugging purposes self._shape = tuple() self.validate_arguments()
def __init__(self, A, X): # NB: It is important that the exponent is an attribute, not # an argument. This prevents parametrized exponents from being replaced # with their logs in Dgp2Dcp. self.A = Atom.cast_to_const(A) super(gmatmul, self).__init__(X)
def __init__(self, A, X): self.A = Atom.cast_to_const(A) super(gmatmul, self).__init__(X)