From f8d9e0e0b184c25a7b6b4cbccbe0dfb576a0d580 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Fri, 16 Jun 2023 22:18:30 -0400 Subject: [PATCH 1/3] Improve `separate_circuit` docstring I've also added `circuit_knitting/` to the paths passed to pytest, as this is required for doctests to be discovered. --- circuit_knitting/utils/transforms.py | 42 ++++++++++++++++++++++++++-- tox.ini | 2 +- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/circuit_knitting/utils/transforms.py b/circuit_knitting/utils/transforms.py index efa0c6ab7..a78f210d4 100644 --- a/circuit_knitting/utils/transforms.py +++ b/circuit_knitting/utils/transforms.py @@ -18,6 +18,11 @@ :toctree: ../stubs separate_circuit + +.. autosummary:: + :toctree: ../stubs + :template: autosummary/class_no_inherited_members.rst + SeparatedCircuits """ from __future__ import annotations @@ -40,7 +45,14 @@ class SeparatedCircuits(NamedTuple): - """Named tuple for result of :class:`separate_circuit`.""" + """Named tuple for result of :func:`separate_circuit`. + + ``subcircuits`` is a dict of circuits, keyed by each partition label. + ``qubit_map`` is a list of length number of qubits in the original circuit. + Each element of that list is a 2-tuple which includes the partition label + of that qubit, together with the index of that qubit in the corresponding + subcircuit. + """ subcircuits: dict[Hashable, QuantumCircuit] qubit_map: list[tuple[Hashable, int]] @@ -52,15 +64,41 @@ def separate_circuit( ) -> SeparatedCircuits: """Separate the circuit into its disconnected components. + If ``partition_labels`` is provided, then the circuit will be separated + according to those labels. If it is ``None``, then the circuit will be + fully separated into its disconnected components, each of which will be + labeled with consecutive integers starting with 0. + + >>> qc = QuantumCircuit(4) + >>> _ = qc.x(0) + >>> _ = qc.cx(1, 2) + >>> _ = qc.h(3) + >>> separate_circuit(qc, "ABBA").subcircuits.keys() + dict_keys(['A', 'B']) + >>> separate_circuit(qc, "ABBA").qubit_map + [('A', 0), ('B', 0), ('B', 1), ('A', 1)] + >>> separate_circuit(qc, "BAAC").subcircuits.keys() + dict_keys(['B', 'A', 'C']) + >>> separate_circuit(qc, "BAAC").qubit_map + [('B', 0), ('A', 0), ('A', 1), ('C', 0)] + >>> separate_circuit(qc).subcircuits.keys() + dict_keys([0, 1, 2]) + >>> separate_circuit(qc).qubit_map + [(0, 0), (1, 0), (1, 1), (2, 0)] + Args: circuit: The circuit to separate into disconnected subcircuits + partition_labels: A sequence of length ``num_qubits``. Qubits with the + same label will end up in the same subcircuit. Returns: - A named tuple containing the subcircuits and qubit map + A :class:`SeparatedCircuits` named tuple containing the ``subcircuits`` + and ``qubit_map``. Raises: ValueError: The number of partition labels does not equal the number of qubits in the input circuit. + ValueError: Operation spans more than one partition. """ # Split barriers into single-qubit barriers before separating new_qc = circuit.copy() diff --git a/tox.ini b/tox.ini index eb9587d99..d61ec93c5 100644 --- a/tox.ini +++ b/tox.ini @@ -8,7 +8,7 @@ extras = test cplex commands = - pytest test/ {posargs} + pytest circuit_knitting/ test/ {posargs} [testenv:style] extras = From ead01aa4850574d96a7676ef6f266217aeaa7452 Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Fri, 16 Jun 2023 22:27:23 -0400 Subject: [PATCH 2/3] Fix doctest discovery when DOcplex is not available --- circuit_knitting/cutting/cutqc/mip_model.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/circuit_knitting/cutting/cutqc/mip_model.py b/circuit_knitting/cutting/cutqc/mip_model.py index cf013ac9f..9b03a9124 100644 --- a/circuit_knitting/cutting/cutqc/mip_model.py +++ b/circuit_knitting/cutting/cutqc/mip_model.py @@ -17,15 +17,6 @@ import numpy as np -try: - from docplex.mp.model import Model - from docplex.mp.utils import DOcplexException -except ModuleNotFoundError as ex: # pragma: no cover - raise ModuleNotFoundError( - "DOcplex is not installed. For automatic cut finding to work, both " - "DOcplex and cplex must be available." - ) from ex - class MIPModel(object): """ @@ -100,6 +91,14 @@ def __init__( num_in_qubits += 1 self.vertex_weight[node] = num_in_qubits + try: + from docplex.mp.model import Model + except ModuleNotFoundError as ex: # pragma: no cover + raise ModuleNotFoundError( + "DOcplex is not installed. For automatic cut finding to work, both " + "DOcplex and cplex must be available." + ) from ex + self.model = Model("docplex_cutter") self.model.log_output = False self._add_variables() @@ -465,6 +464,8 @@ def solve(self, min_postprocessing_cost: float) -> bool: # print('solving for %d subcircuits'%self.num_subcircuit) # print('model has %d variables, %d linear constraints,%d quadratic constraints, %d general constraints' # % (self.model.NumVars,self.model.NumConstrs, self.model.NumQConstrs, self.model.NumGenConstrs)) + from docplex.mp.utils import DOcplexException + print( "Exporting as a LP file to let you check the model that will be solved : ", min_postprocessing_cost, From 6ede313aa63f71bf1d5c228f931eaa2e0ba53f7b Mon Sep 17 00:00:00 2001 From: Jim Garrison Date: Mon, 19 Jun 2023 20:27:34 -0400 Subject: [PATCH 3/3] Update circuit_knitting/utils/transforms.py Co-authored-by: Caleb Johnson --- circuit_knitting/utils/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circuit_knitting/utils/transforms.py b/circuit_knitting/utils/transforms.py index a78f210d4..a88898adb 100644 --- a/circuit_knitting/utils/transforms.py +++ b/circuit_knitting/utils/transforms.py @@ -48,7 +48,7 @@ class SeparatedCircuits(NamedTuple): """Named tuple for result of :func:`separate_circuit`. ``subcircuits`` is a dict of circuits, keyed by each partition label. - ``qubit_map`` is a list of length number of qubits in the original circuit. + ``qubit_map`` is a list with length equal to the number of qubits in the original circuit. Each element of that list is a 2-tuple which includes the partition label of that qubit, together with the index of that qubit in the corresponding subcircuit.