Skip to content

Commit

Permalink
remove list, add auto inc
Browse files Browse the repository at this point in the history
  • Loading branch information
cqc-melf committed Nov 7, 2023
1 parent d8cd3f1 commit 080f453
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 64 deletions.
2 changes: 1 addition & 1 deletion docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ unreleased
* Update qiskit-ibm-runtime version to 0.13.0.
* Update qiskit-aer version to 0.13.0.
* Introduce dependency on qiskit-algorithms.
* Add possibility to submit list of seeds to backend in batch submission
* Add option for automatic incrementing seed on ``process_circuits()``.

0.45.0 (October 2023)
---------------------
Expand Down
17 changes: 12 additions & 5 deletions pytket/extensions/qiskit/backends/aer.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,14 @@ def process_circuits(
circuits: Sequence[Circuit],
n_shots: Union[None, int, Sequence[Optional[int]]] = None,
valid_check: bool = True,
**kwargs: Union[int, float, str, None, Sequence[Optional[int]]],
**kwargs: Union[bool, int, float, str, None],
) -> List[ResultHandle]:
"""
See :py:meth:`pytket.backends.Backend.process_circuits`.
Supported kwargs: `seed`, `postprocess`, `seed_auto_increase`.
seed_auto_increase=True will automatically increase the seed by one for the
different batches when more than one circuit is submitted
"""
circuits = list(circuits)
n_shots_list = Backend._get_n_shots_as_list(
n_shots,
Expand All @@ -258,13 +264,12 @@ def process_circuits(
circuits = noisy_circuits

handle_list: List[Optional[ResultHandle]] = [None] * len(circuits)
circuit_batches, batch_order = _batch_circuits(
circuits, n_shots_list, kwargs.get("seed")
)
seed = kwargs.get("seed")
circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list)

replace_implicit_swaps = self.supports_state or self.supports_unitary

for (n_shots, seed, batch), indices in zip(circuit_batches, batch_order):
for (n_shots, batch), indices in zip(circuit_batches, batch_order):
qcs = []
for tkc in batch:
qc = tk_to_qiskit(tkc, replace_implicit_swaps)
Expand All @@ -284,6 +289,8 @@ def process_circuits(
seed_simulator=seed,
noise_model=self._noise_model,
)
if kwargs.get("seed_auto_increase") and type(seed) is int:
seed += 1
jobid = job.job_id()
for i, ind in enumerate(indices):
handle = ResultHandle(jobid, i)
Expand Down
8 changes: 3 additions & 5 deletions pytket/extensions/qiskit/backends/ibm.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ def process_circuits(
circuits: Sequence[Circuit],
n_shots: Union[None, int, Sequence[Optional[int]]] = None,
valid_check: bool = True,
**kwargs: Union[int, float, str, None, Sequence[Optional[int]]],
**kwargs: Union[bool, int, float, str, None],
) -> List[ResultHandle]:
"""
See :py:meth:`pytket.backends.Backend.process_circuits`.
Expand All @@ -464,15 +464,13 @@ def process_circuits(
)

handle_list: List[Optional[ResultHandle]] = [None] * len(circuits)
circuit_batches, batch_order = _batch_circuits(
circuits, n_shots_list, kwargs.get("seed")
)
circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list)

postprocess = kwargs.get("postprocess", False)
simplify_initial = kwargs.get("simplify_initial", False)

batch_id = 0 # identify batches for debug purposes only
for (n_shots, _, batch), indices in zip(circuit_batches, batch_order):
for (n_shots, batch), indices in zip(circuit_batches, batch_order):
for chunk in itertools.zip_longest(
*([iter(zip(batch, indices))] * self._max_per_job)
):
Expand Down
58 changes: 16 additions & 42 deletions pytket/extensions/qiskit/backends/ibm_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
def _batch_circuits(
circuits: Sequence["Circuit"],
n_shots: Sequence[Optional[int]],
seed: Union[int, float, str, None, Sequence[Optional[int]]],
) -> Tuple[List[Tuple[Optional[int], Optional[int], List["Circuit"]]], List[List[int]]]:
) -> Tuple[List[Tuple[Optional[int], List["Circuit"]]], List[List[int]]]:
"""
Groups circuits into sets of circuits with the same number of shots.
Expand All @@ -52,47 +51,22 @@ def _batch_circuits(
:type circuits: Sequence[Circuit]
:param n_shots: Number of shots for each circuit.
:type n_shots: Sequence[int]
:param seed: RNG Seed for each circuit.
:type seed: Union[int, None, Sequence[Optional[int]]]
"""

n_seeds: list[Optional[int]] = []
if type(seed) == list:
n_seeds = seed
elif type(seed) == int:
n_seeds = [seed for _ in range(len(circuits))]
elif seed == None:
n_seeds = [None for _ in range(len(circuits))]
else:
raise ValueError(
f"""unknown seed type, type should be None,
int, or list[int], type found {type(seed)}"""
)

assert len(n_seeds) == len(n_shots)
assert len(n_seeds) == len(circuits)

batches: List[Tuple[Optional[int], Optional[int], List["Circuit"]]] = []
batch_order: List[List[int]] = []

if all(seed == n_seeds[0] for seed in n_seeds):
# take care of None entries
n_shots_int = list(map(lambda x: x if x is not None else -1, n_shots))

order: Collection[int] = np.argsort(n_shots_int)

batches = [
(n, n_seeds[0], [circuits[i] for i in indices])
for n, indices in itertools.groupby(order, key=lambda i: n_shots[i])
]
batch_order = [
list(indices)
for n, indices in itertools.groupby(order, key=lambda i: n_shots[i])
]
else:

for i in range(len(circuits)):
batches.append((n_shots[i], n_seeds[i], [circuits[i]]))
batch_order.append([i])
assert len(n_shots) == len(circuits)

# take care of None entries
n_shots_int = list(map(lambda x: x if x is not None else -1, n_shots))

order: Collection[int] = np.argsort(n_shots_int)

batches: List[Tuple[Optional[int], List["Circuit"]]] = [
(n, [circuits[i] for i in indices])
for n, indices in itertools.groupby(order, key=lambda i: n_shots[i])
]
batch_order: List[List[int]] = [
list(indices)
for n, indices in itertools.groupby(order, key=lambda i: n_shots[i])
]

return batches, batch_order
15 changes: 9 additions & 6 deletions pytket/extensions/qiskit/backends/ibmq_emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,13 @@ def process_circuits(
circuits: Sequence[Circuit],
n_shots: Union[None, int, Sequence[Optional[int]]] = None,
valid_check: bool = True,
**kwargs: Union[int, float, str, None, Sequence[Optional[int]]],
**kwargs: Union[bool, int, float, str, None],
) -> List[ResultHandle]:
"""
See :py:meth:`pytket.backends.Backend.process_circuits`.
Supported kwargs: `seed`, `postprocess`.
Supported kwargs: `seed`, `postprocess`, `seed_auto_increase`.
seed_auto_increase=True will automatically increase the seed by one for the
different batches when more than one circuit is submitted
"""
circuits = list(circuits)
n_shots_list = Backend._get_n_shots_as_list(
Expand All @@ -139,12 +141,11 @@ def process_circuits(
)

handle_list: List[Optional[ResultHandle]] = [None] * len(circuits)
circuit_batches, batch_order = _batch_circuits(
circuits, n_shots_list, kwargs.get("seed")
)
seed = kwargs.get("seed")
circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list)

batch_id = 0 # identify batches for debug purposes only
for (n_shots, seed, batch), indices in zip(circuit_batches, batch_order):
for (n_shots, batch), indices in zip(circuit_batches, batch_order):
for chunk in itertools.zip_longest(
*([iter(zip(batch, indices))] * self._ibmq._max_per_job)
):
Expand Down Expand Up @@ -176,6 +177,8 @@ def process_circuits(
options.execution.shots = n_shots
options.simulator.noise_model = self._noise_model
options.seed_simulator = seed
if kwargs.get("seed_auto_increase") and type(seed) is int:
seed += 1
sampler = Sampler(session=self._session, options=options)
job = sampler.run(circuits=qcs)
job_id = job.job_id()
Expand Down
12 changes: 7 additions & 5 deletions tests/backend_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,9 +473,10 @@ def test_nshots_nseeds_batching(perth_backend: IBMQBackend) -> None:
c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all()
cs = [c1, c2, c3, c4]
n_shots = [10, 12, 10, 13]
n_seeds = [10, 10, 10, 10]
cs = backend.get_compiled_circuits(cs)
handles = backend.process_circuits(cs, n_shots=n_shots, seed=n_seeds)
handles = backend.process_circuits(
cs, n_shots=n_shots, seed=10, seed_auto_increase=False
)

from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX

Expand All @@ -502,17 +503,18 @@ def test_nshots_nseeds_batching_ii(perth_backend: IBMQBackend) -> None:
c4 = Circuit(2, 2).Rx(0.5, 0).CX(0, 1).CX(1, 0).measure_all()
cs = [c1, c2, c3, c4]
n_shots = [10, 12, 10, 13]
n_seeds = [10, 11, 12, 13]
cs = backend.get_compiled_circuits(cs)
handles = backend.process_circuits(cs, n_shots=n_shots, seed=n_seeds)
handles = backend.process_circuits(
cs, n_shots=n_shots, seed=10, seed_auto_increase=True
)

from pytket.extensions.qiskit.backends.ibm import _DEBUG_HANDLE_PREFIX

assert all(
cast(str, hand[0]) == _DEBUG_HANDLE_PREFIX + suffix
for hand, suffix in zip(
handles,
[f"{(10, 0)}", f"{(12, 1)}", f"{(10, 2)}", f"{(13, 3)}"],
[f"{(10, 0)}", f"{(12, 1)}", f"{(10, 0)}", f"{(13, 2)}"],
)
)
finally:
Expand Down

0 comments on commit 080f453

Please sign in to comment.