Skip to content

Commit

Permalink
Add representation of expr.Var to DAGCircuit (#12204)
Browse files Browse the repository at this point in the history
* Add representation of `expr.Var` to `DAGCircuit`

This adds basic support for `Var`s to `DAGCircuit`, enabling the base
representation using the same wire structure used for clbits.  This is
known to be an inefficient representation of the dataflow for clbits,
which can be read multiple times without implying an order between those
operations (unlike qubits for which reads and writes are more naturally
linked).  We're using this simpler representation to make a better
initial MVP; optimising the data-flow representation would come as part
of a larger effort within the `DAGCircuit`.

This commit adds support in `DAGCircuit` for:

- representation of `Var` nodes
- appending all operations that might contain `Var` nodes to the DAG and
  updating the wire structure (including control-flow ops and stores)
- equality checking of DAGs with `Var`s (and so enables
  `QuantumCircuit.__eq__` as well)
- `DAGCircuit.copy_empty_like` with `Var`s
- the DAG/circuit converters

The other methods in `DAGCircuit` that might need to be aware of `Var`
nodes will be handled separately.

* Expand test coverage

* Fix copy/paste error
  • Loading branch information
jakelishman committed May 1, 2024
1 parent cd03721 commit c60a1ed
Show file tree
Hide file tree
Showing 6 changed files with 538 additions and 73 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
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
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 c60a1ed

Please sign in to comment.