//  [python]
def get_postprocessing(bo_type, manifold):
        if bo_type == "GaBO":
            return symmetric_matrix_to_vector_mandel_torch

        elif bo_type == "CholBO":
            # Define sampling post processing function to ensure that constraints are satisfied for sampled points
            def post_processing_init(x):
                d_vec = x.shape[-1]
                d_mat = int((-1.0 + (1.0 + 8.0 * d_vec) ** 0.5) / 2.0)

                # Tranform the samples in a Mandel notation form. We can do it by squaring the d first elements and
                # squaring the next ones by keeping the original sign. We can do this operation because we defined
                # the bounds of the  Cholesky decomposition equivalent to sqrt of the corresponding bounds for
                # Mandel notation.
                proc_x = x.clone()
                proc_x = proc_x.view(-1, proc_x.shape[-1])
                proc_x[:, 0:d_mat] = torch.mul(proc_x[:, 0:d_mat], proc_x[:, 0:d_mat])
                proc_x[:, d_mat:] = torch.mul(torch.sign(proc_x[:, d_mat])[:, None],
                                              torch.mul(proc_x[:, d_mat:], proc_x[:, d_mat:]))

                # Transform into a matrix to check the constraints
                x_mat = vector_to_symmetric_matrix_mandel_torch(proc_x)

                # Cholesky vector initialization
                x_chol = torch.zeros(proc_x.shape, dtype=x.dtype)
                indices = np.tril_indices(x_mat.shape[-1])

                for n in range(x_mat.shape[0]):
                    # Check constraints
                    eigdec = torch.linalg.eig(x_mat[n])
                    eigvals = eigdec.eigenvalues
                    eigvecs = eigdec.eigenvectors

                    eigvals[eigvals.real <= 0.] = manifold.min_eig  # PD constraint
                    eigvals[eigvals.real > manifold.max_eig] = manifold.max_eig  # Max eigenvalue constraint

                    x_mat[n] = torch.mm(torch.mm(eigvecs, torch.diag(eigvals)), torch.inverse(eigvecs))

                    # Cholesky decomposition
                    x_chol[n] = torch.cholesky(x_mat[n])[indices]

                return x_chol.view(x.shape)

            return post_processing_init

        else:
            # Define sampling post processing function to ensure that constraints are satisfied for sampled points
            def post_processing_init(x):
                x_mat = vector_to_symmetric_matrix_mandel_torch(x)
                init_shape = x_mat.shape
                x_mat = x_mat.view(-1, x_mat.shape[-2], x_mat.shape[-1])

                for n in range(x_mat.shape[0]):
                    eigdec = torch.linalg.eig(x_mat[n])
                    eigvals = eigdec.eigenvalues
                    eigvecs = eigdec.eigenvectors

                    eigvals[eigvals.real <= 0.] = manifold.min_eig  # PD constraint
                    eigvals[eigvals.real > manifold.max_eig] = manifold.max_eig  # Max eigenvalue constraint

                    x_mat[n] = torch.mm(torch.mm(eigvecs, torch.diag(eigvals)), torch.inverse(eigvecs))

                x_mat = x_mat.view(init_shape)
                return symmetric_matrix_to_vector_mandel_torch(x_mat)
            return post_processing_init