def METHOD_NAME(self, problem):
    soc_constraints = []
    other_constraints = []
    for constraint in problem.constraints:
        if type(constraint) is SOC:
            soc_constraints.append(constraint)
        else:
            other_constraints.append(constraint)
    psd_constraints = []
    soc_constraint_ids = []
    soc_id_from_psd = {}
    for constraint in soc_constraints:
        """
        The SOC constraint :math:`\\lVert X \\rVert_2 \leq t` is modeled by `t` and `X`.
        We extract these `t` and `X` from the SOC constraint object.
        """
        t, X = constraint.args
        soc_constraint_ids.append(constraint.id)
        """
        A PSD constraint object will constrain the matrix M specified in its constructor to
        the PSD cone.
        We will create this matrix M using the `t` and `X` extracted from the SOC constraint.
        Since M being PSD means its Schur complement is also PSD, replacing :math:`M >> 0`
        with :math:`SchurComplement(M) >> 0` should give us the original SOC constraint.
        """
        if t.shape==(1,): # when `constraint` object has only one constraint
            scalar_term = t[0]
            vector_term_len = X.shape[0]
            """
            We construct the terms A, B and C that comprise the Schur complement of M
            There are multiple ways to construct A, B and C (and hence M) that are equivalent
            however, this one makes writing `invert` routine simple.
            """
            A = scalar_term * sparse.eye(1)
            B = cp.reshape(X,[-1,1]).T
            C = scalar_term * sparse.eye(vector_term_len)
            """
            Another technique for reference
            A = scalar_term * sparse.eye(vector_term_len)
            B = cp.reshape(X,[-1,1])
            C = scalar_term * sparse.eye(1)
            """
            """
            Construct M from A, B and C
            """
            M = cp.bmat([
                [A, B],
                [B.T, C]
            ])
            """
            Constrain M to the PSD cone.
            """
            new_psd_constraint = PSD(M)
            soc_id_from_psd[new_psd_constraint.id] = constraint.id
            psd_constraints.append(new_psd_constraint)
        else: # when `constraint` object has multiple packed constraints
            if constraint.axis==1:
                X = X.T
            for subidx in range(t.shape[0]):
                scalar_term = t[subidx]
                vector_term_len = X.shape[0]
                A = scalar_term * sparse.eye(1)
                B = X[:,subidx:subidx+1].T
                C = scalar_term * sparse.eye(vector_term_len)
                M = cp.bmat([
                    [A, B],
                    [B.T, C]
                ])
                new_psd_constraint = PSD(M)
                soc_id_from_psd[new_psd_constraint.id] = constraint.id
                psd_constraints.append(new_psd_constraint)
    new_problem = problems.problem.Problem(problem.objective,
                                           other_constraints + psd_constraints)
    inverse_data = (soc_id_from_psd, soc_constraint_ids)
    return new_problem, inverse_data