Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Primitives support the dynamic circuits with control flow #9231

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions qiskit/primitives/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
"""
from __future__ import annotations

from collections.abc import Iterable

import numpy as np

from qiskit.circuit import Instruction, ParameterExpression, QuantumCircuit
Expand Down Expand Up @@ -125,6 +127,16 @@ def _bits_key(bits: tuple[Bit, ...], circuit: QuantumCircuit) -> tuple:
)


def _format_params(param):
if isinstance(param, np.ndarray):
return param.data.tobytes()
elif isinstance(param, QuantumCircuit):
return _circuit_key(param)
elif isinstance(param, Iterable):
return tuple(param)
return param


def _circuit_key(circuit: QuantumCircuit, functional: bool = True) -> tuple:
"""Private key function for QuantumCircuit.

Expand All @@ -147,10 +159,7 @@ def _circuit_key(circuit: QuantumCircuit, functional: bool = True) -> tuple:
_bits_key(data.qubits, circuit), # qubits
_bits_key(data.clbits, circuit), # clbits
data.operation.name, # operation.name
tuple(
param.data.tobytes() if isinstance(param, np.ndarray) else param
for param in data.operation.params
), # operation.params
tuple(_format_params(param) for param in data.operation.params), # operation.params
)
for data in circuit.data
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
features:
- |
Primitives support the dynamic circuits with control flow.
If backend supports it, users can run the circuits using :class:`~BackendSampler`
and :class:`~BackendEstimator`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change apply to only the BackendSampler and BackendEstimator, or is this a general improvement that affects all BaseSampler and BaseEstimator subclasses?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. When I wrote this document, I thought that if a backend did not support control flow, primitives also did not support, but I was wrong.

14 changes: 14 additions & 0 deletions test/python/primitives/test_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

"""Tests for Sampler."""

import json
import unittest
from test import combine

Expand Down Expand Up @@ -783,6 +784,19 @@ def test_circuit_with_unitary(self):
sampler_result = sampler.run([circuit]).result()
self.assertDictAlmostEqual(sampler_result.quasi_dists[0], {0: 1, 1: 0})

def test_circuit_key_controlflow(self):
"""Test for a circuit with control flow."""
qc = QuantumCircuit(2, 1)

with qc.for_loop(range(5)):
qc.h(0)
qc.cx(0, 1)
qc.measure(0, 0)
qc.break_loop().c_if(0, True)

self.assertIsInstance(hash(_circuit_key(qc)), int)
self.assertIsInstance(json.dumps(_circuit_key(qc)), str)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aer supports control flow - would it be possible to try executing a simple Sampler and Estimator run on a BackendX backed by AerSimulator (with the appropriate @unittest.skipUnless(optionals.HAS_AER)).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I'll try it.


if __name__ == "__main__":
unittest.main()