Example #1
0
    def group_commuting(self, qubit_wise=False):
        """Partition a PauliList into sets of commuting Pauli strings.

        Args:
            qubit_wise (bool): whether the commutation rule is applied to the whole operator,
                or on a per-qubit basis.  For example:

                .. code-block:: python

                    >>> from qiskit.quantum_info import PauliList
                    >>> op = PauliList(["XX", "YY", "IZ", "ZZ"])
                    >>> op.group_commuting()
                    [PauliList(['XX', 'YY']), PauliList(['IZ', 'ZZ'])]
                    >>> op.group_commuting(qubit_wise=True)
                    [PauliList(['XX']), PauliList(['YY']), PauliList(['IZ', 'ZZ'])]

        Returns:
            List[PauliList]: List of PauliLists where each PauliList contains commuting Pauli operators.
        """

        graph = self._create_graph(qubit_wise)
        # Keys in coloring_dict are nodes, values are colors
        coloring_dict = rx.graph_greedy_color(graph)
        groups = defaultdict(list)
        for idx, color in coloring_dict.items():
            groups[color].append(idx)
        return [self[group] for group in groups.values()]
Example #2
0
    def group_commuting(self, qubit_wise=False):
        """Partition a SparsePauliOp into sets of commuting Pauli strings.

        Args:
            qubit_wise (bool): whether the commutation rule is applied to the whole operator,
                or on a per-qubit basis.  For example:

                .. code-block:: python

                    >>> op = SparsePauliOp.from_list([("XX", 2), ("YY", 1), ("IZ",2j), ("ZZ",1j)])
                    >>> op.group_commuting()
                    [SparsePauliOp(["IZ", "ZZ"], coeffs=[0.+2.j, 0.+1j]),
                     SparsePauliOp(["XX", "YY"], coeffs=[2.+0.j, 1.+0.j])]
                    >>> op.group_commuting(qubit_wise=True)
                    [SparsePauliOp(['XX'], coeffs=[2.+0.j]),
                     SparsePauliOp(['YY'], coeffs=[1.+0.j]),
                     SparsePauliOp(['IZ', 'ZZ'], coeffs=[0.+2.j, 0.+1.j])]

        Returns:
            List[SparsePauliOp]: List of SparsePauliOp where each SparsePauliOp contains
                commuting Pauli operators.
        """

        graph = self._create_graph(qubit_wise)
        # Keys in coloring_dict are nodes, values are colors
        coloring_dict = rx.graph_greedy_color(graph)
        groups = defaultdict(list)
        for idx, color in coloring_dict.items():
            groups[color].append(idx)
        return [self[group] for group in groups.values()]
Example #3
0
 def test_simple_graph(self):
     graph = retworkx.PyGraph()
     node_a = graph.add_node(1)
     node_b = graph.add_node(2)
     graph.add_edge(node_a, node_b, 1)
     node_c = graph.add_node(3)
     graph.add_edge(node_a, node_c, 1)
     res = retworkx.graph_greedy_color(graph)
     self.assertEqual({0: 0, 1: 1, 2: 1}, res)
Example #4
0
    def group_subops(cls,
                     list_op: ListOp,
                     fast: Optional[bool] = None,
                     use_nx: Optional[bool] = None) -> ListOp:
        """Given a ListOp, attempt to group into Abelian ListOps of the same type.

        Args:
            list_op: The Operator to group into Abelian groups
            fast: Ignored - parameter will be removed in future release
            use_nx: Ignored - parameter will be removed in future release

        Returns:
            The grouped Operator.

        Raises:
            AquaError: If any of list_op's sub-ops is not ``PauliOp``.
        """
        if fast is not None or use_nx is not None:
            warnings.warn(
                'Options `fast` and `use_nx` of `AbelianGrouper.group_subops` are '
                'no longer used and are now deprecated and will be removed no '
                'sooner than 3 months following the 0.8.0 release.')

        # TODO: implement direct way
        if isinstance(list_op, PauliSumOp):
            list_op = list_op.to_pauli_op()

        for op in list_op.oplist:
            if not isinstance(op, PauliOp):
                raise AquaError(
                    'Cannot determine Abelian groups if any Operator in list_op is not '
                    '`PauliOp`. E.g., {} ({})'.format(op, type(op)))

        edges = cls._commutation_graph(list_op)
        nodes = range(len(list_op))

        graph = rx.PyGraph()
        graph.add_nodes_from(nodes)
        graph.add_edges_from_no_data(edges)
        # Keys in coloring_dict are nodes, values are colors
        coloring_dict = rx.graph_greedy_color(graph)

        groups = {}  # type: Dict
        # sort items so that the output is consistent with all options (fast and use_nx)
        for idx, color in sorted(coloring_dict.items()):
            groups.setdefault(color, []).append(list_op[idx])

        group_ops = [
            list_op.__class__(group, abelian=True)
            for group in groups.values()
        ]
        if len(group_ops) == 1:
            return group_ops[0] * list_op.coeff  # type: ignore
        return list_op.__class__(group_ops,
                                 coeff=list_op.coeff)  # type: ignore
    def group_subops(cls, list_op: Union[ListOp, PauliSumOp]) -> ListOp:
        """Given a ListOp, attempt to group into Abelian ListOps of the same type.

        Args:
            list_op: The Operator to group into Abelian groups

        Returns:
            The grouped Operator.

        Raises:
            OpflowError: If any of list_op's sub-ops is not ``PauliOp``.
        """
        if isinstance(list_op, ListOp):
            for op in list_op.oplist:
                if not isinstance(op, PauliOp):
                    raise OpflowError(
                        "Cannot determine Abelian groups if any Operator in list_op is not "
                        f"`PauliOp`. E.g., {op} ({type(op)})")

        edges = cls._anti_commutation_graph(list_op)
        nodes = range(len(list_op))

        graph = rx.PyGraph()
        graph.add_nodes_from(nodes)
        graph.add_edges_from_no_data(edges)
        # Keys in coloring_dict are nodes, values are colors
        coloring_dict = rx.graph_greedy_color(graph)
        groups = defaultdict(list)
        for idx, color in coloring_dict.items():
            groups[color].append(idx)

        if isinstance(list_op, PauliSumOp):
            primitive = list_op.primitive
            return SummedOp(
                [
                    PauliSumOp(primitive[group], grouping_type="TPB")
                    for group in groups.values()
                ],
                coeff=list_op.coeff,
            )

        group_ops: List[ListOp] = [
            list_op.__class__([list_op[idx] for idx in group], abelian=True)
            for group in groups.values()
        ]
        if len(group_ops) == 1:
            return group_ops[0].mul(list_op.coeff)
        return list_op.__class__(group_ops, coeff=list_op.coeff)
Example #6
0
    def group_qubit_wise_commuting(self):
        """Partition a PauliList into sets of mutually qubit-wise commuting Pauli strings.

        Returns:
            List[PauliList]: List of PauliLists where each PauliList contains commutable Pauli operators.
        """
        nodes = range(self._num_paulis)
        edges = self._noncommutation_graph()
        graph = rx.PyGraph()
        graph.add_nodes_from(nodes)
        graph.add_edges_from_no_data(edges)
        # Keys in coloring_dict are nodes, values are colors
        coloring_dict = rx.graph_greedy_color(graph)
        groups = defaultdict(list)
        for idx, color in coloring_dict.items():
            groups[color].append(idx)
        return [PauliList([self[i] for i in x]) for x in groups.values()]
Example #7
0
 def peakmem_graph_greedy_coloring(self):
     retworkx.graph_greedy_color(self.graph)
Example #8
0
 def time_graph_greedy_coloring(self):
     retworkx.graph_greedy_color(self.graph)
Example #9
0
 def test_empty_graph(self):
     graph = retworkx.PyGraph()
     res = retworkx.graph_greedy_color(graph)
     self.assertEqual({}, res)