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()]
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()]
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)
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)
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()]
def peakmem_graph_greedy_coloring(self): retworkx.graph_greedy_color(self.graph)
def time_graph_greedy_coloring(self): retworkx.graph_greedy_color(self.graph)
def test_empty_graph(self): graph = retworkx.PyGraph() res = retworkx.graph_greedy_color(graph) self.assertEqual({}, res)