Factorize a channel permutation circuit according the block
        structure of the upstream circuit.  This allows to move as much of the
        permutation as possible *around* a reducible circuit upstream.  It
        basically decomposes

            ``permutation << rhs --> permutation' << rhs' << residual'``

        where rhs' is just a block permutated version of rhs and residual'
        is the maximal part of the permutation that one may move around rhs.

        Args:
            rhs (Circuit): An upstream circuit object

        Returns:
            tuple: new_lhs_circuit, permuted_rhs_circuit, new_rhs_circuit

        Raises:
            .BadPermutationError

def _factorize_for_rhs(self, rhs):
        """Factorize a channel permutation circuit according the block
        structure of the upstream circuit.  This allows to move as much of the
        permutation as possible *around* a reducible circuit upstream.  It
        basically decomposes

            ``permutation << rhs --> permutation' << rhs' << residual'``

        where rhs' is just a block permutated version of rhs and residual'
        is the maximal part of the permutation that one may move around rhs.

        Args:
            rhs (Circuit): An upstream circuit object

        Returns:
            tuple: new_lhs_circuit, permuted_rhs_circuit, new_rhs_circuit

        Raises:
            .BadPermutationError
        """
        block_structure = rhs.block_structure

        block_perm, perms_within_blocks \
            = block_perm_and_perms_within_blocks(self.permutation,
                                                 block_structure)
        fblockp = full_block_perm(block_perm, block_structure)

        if not sorted(fblockp) == list(range(self.cdim)):
            raise BadPermutationError()

        new_rhs_circuit = CPermutation.create(fblockp)
        within_blocks = [CPermutation.create(within_block)
                         for within_block in perms_within_blocks]
        within_perm_circuit = Concatenation.create(*within_blocks)
        rhs_blocks = rhs.get_blocks(block_structure)

        summands = [SeriesProduct.create(within_blocks[p], rhs_blocks[p])
                    for p in invert_permutation(block_perm)]
        permuted_rhs_circuit = Concatenation.create(*summands)

        new_lhs_circuit = (self << within_perm_circuit.series_inverse() <<
                           new_rhs_circuit.series_inverse())

        return new_lhs_circuit, permuted_rhs_circuit, new_rhs_circuit