Skip to content

Commit

Permalink
Merge branch 'main' into elide-swaps
Browse files Browse the repository at this point in the history
  • Loading branch information
mtreinish authored May 1, 2024
2 parents f5b6778 + a41690d commit 5cbc67d
Show file tree
Hide file tree
Showing 14 changed files with 775 additions and 86 deletions.
10 changes: 10 additions & 0 deletions qiskit/circuit/controlflow/control_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

if typing.TYPE_CHECKING:
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.classical import expr


class ControlFlowOp(Instruction, ABC):
Expand Down Expand Up @@ -72,3 +73,12 @@ def map_block(block: QuantumCircuit) -> QuantumCircuit:
Returns:
New :class:`ControlFlowOp` with replaced blocks.
"""

def iter_captured_vars(self) -> typing.Iterable[expr.Var]:
"""Get an iterator over the unique captured variables in all blocks of this construct."""
seen = set()
for block in self.blocks:
for var in block.iter_captured_vars():
if var not in seen:
seen.add(var)
yield var
6 changes: 3 additions & 3 deletions qiskit/circuit/library/overlap.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class UnitaryOverlap(QuantumCircuit):
names `"p1"` (for circuit ``unitary1``) and `"p2"` (for circuit ``unitary_2``) in the output
circuit.
This circuit is usually employed in computing the fidelity::
This circuit is usually employed in computing the fidelity:
.. math::
.. math::
\left|\langle 0| U_2^{\dag} U_1|0\rangle\right|^{2}
\left|\langle 0| U_2^{\dag} U_1|0\rangle\right|^{2}
by computing the probability of being in the all-zeros bit-string, or equivalently,
the expectation value of projector :math:`|0\rangle\langle 0|`.
Expand Down
7 changes: 7 additions & 0 deletions qiskit/converters/circuit_to_dag.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ def circuit_to_dag(circuit, copy_operations=True, *, qubit_order=None, clbit_ord
dagcircuit.add_qubits(qubits)
dagcircuit.add_clbits(clbits)

for var in circuit.iter_input_vars():
dagcircuit.add_input_var(var)
for var in circuit.iter_captured_vars():
dagcircuit.add_captured_var(var)
for var in circuit.iter_declared_vars():
dagcircuit.add_declared_var(var)

for register in circuit.qregs:
dagcircuit.add_qreg(register)

Expand Down
2 changes: 2 additions & 0 deletions qiskit/converters/circuit_to_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ def circuit_to_gate(circuit, parameter_map=None, equivalence_library=None, label

if circuit.clbits:
raise QiskitError("Circuit with classical bits cannot be converted to gate.")
if circuit.num_vars:
raise QiskitError("circuits with realtime classical variables cannot be converted to gates")

for instruction in circuit.data:
if not _check_is_gate(instruction.operation):
Expand Down
22 changes: 22 additions & 0 deletions qiskit/converters/circuit_to_instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,28 @@ def circuit_to_instruction(circuit, parameter_map=None, equivalence_library=None
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit

if circuit.num_input_vars:
# This could be supported by moving the `input` variables to be parameters of the
# instruction, but we don't really have a good reprssentation of that yet, so safer to
# forbid it.
raise QiskitError("Circuits with 'input' variables cannot yet be converted to instructions")
if circuit.num_captured_vars:
raise QiskitError("Circuits that capture variables cannot be converted to instructions")
if circuit.num_declared_vars:
# This could very easily be supported in representations, since the variables are allocated
# and freed within the instruction itself. The reason to initially forbid it is to avoid
# needing to support unrolling such instructions within the transpiler; we would potentially
# need to remap variables to unique names in the larger context, and we don't yet have a way
# to return that information from the transpiler. We have to catch that in the transpiler
# as well since a user could manually make an instruction with such a definition, but
# forbidding it here means users get a more meaningful error at the point that the
# instruction actually gets created (since users often aren't aware that
# `QuantumCircuit.append(QuantumCircuit)` implicitly converts to an instruction).
raise QiskitError(
"Circuits with internal variables cannot yet be converted to instructions."
" You may be able to use `QuantumCircuit.compose` to inline this circuit into another."
)

if parameter_map is None:
parameter_dict = {p: p for p in circuit.parameters}
else:
Expand Down
4 changes: 4 additions & 0 deletions qiskit/converters/dag_to_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ def dag_to_circuit(dag, copy_operations=True):
*dag.cregs.values(),
name=name,
global_phase=dag.global_phase,
inputs=dag.iter_input_vars(),
captures=dag.iter_captured_vars(),
)
for var in dag.iter_declared_vars():
circuit.add_uninitialized_var(var)
circuit.metadata = dag.metadata
circuit.calibrations = dag.calibrations

Expand Down
Loading

0 comments on commit 5cbc67d

Please sign in to comment.