Skip to content

Commit

Permalink
✨ Add Python interface improvements and Qiskit export support (#859)
Browse files Browse the repository at this point in the history
## Description

This pull request introduces several changes to enhance Python
interoperability and integration with Qiskit. Key updates include:
- Adding a method to natively export `QuantumComputations` objects to
Qiskit `QuantumCircuit`.
- Exposing registers from `QuantumComputation` in the Python interface.
- Addressing issues with calling `name` and `end` on Python registers.
- Fixing the implementation of `__iter__` and providing `items` for
`Permutation`.
- Enhancing `CompoundOperation` to implement the
`MutableSequence[Operation]` interface.

These changes provide better usability and extend functionality when
using the library in Python environments.

Fixes #35

## Checklist:

- [x] The pull request only contains commits that are related to it.
- [x] I have added appropriate tests and documentation.
- [x] I have made sure that all CI jobs on GitHub pass.
- [x] The pull request introduces no new warnings and follows the
project's style guidelines
  • Loading branch information
burgholzer authored Mar 10, 2025
2 parents 5e94260 + 3845da9 commit b7c3cfc
Show file tree
Hide file tree
Showing 12 changed files with 873 additions and 65 deletions.
9 changes: 9 additions & 0 deletions include/mqt-core/ir/operations/CompoundOperation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,16 @@ class CompoundOperation final : public Operation {
return ops.insert(iter, std::forward<decltype(op)>(op));
}

// Element access (pass-through)
[[nodiscard]] const auto& at(const std::size_t i) const { return ops.at(i); }
[[nodiscard]] auto& operator[](const std::size_t i) { return ops[i]; }
[[nodiscard]] const auto& operator[](const std::size_t i) const {
return ops[i];
}
[[nodiscard]] auto& front() { return ops.front(); }
[[nodiscard]] const auto& front() const { return ops.front(); }
[[nodiscard]] auto& back() { return ops.back(); }
[[nodiscard]] const auto& back() const { return ops.back(); }
};
} // namespace qc

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ filterwarnings = [
# Qiskit 1.3 deprecations
'ignore:.*``qiskit.dagcircuit.dagcircuit.DAGCircuit.*`` is deprecated as of qiskit 1.3.0.*:DeprecationWarning:',
'ignore:.*``qiskit.circuit.library.standard_gates.x.*`` is pending deprecation as of qiskit 1.3.*:PendingDeprecationWarning:',
'ignore:.*``qiskit.circuit.instruction.Instruction.condition`` is deprecated as of qiskit 1.3.0.*:DeprecationWarning:',
]
log_cli_level = "info"
testpaths = ["test/python"]
Expand Down
17 changes: 16 additions & 1 deletion src/mqt/core/ir/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

"""MQT Core IR - The MQT Core Intermediate Representation (IR) module."""

from collections.abc import Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Sequence
from collections.abc import ItemsView, Iterable, Iterator, Mapping, MutableMapping, MutableSequence, Sequence
from os import PathLike
from typing import overload

Expand Down Expand Up @@ -59,6 +59,9 @@ class Permutation(MutableMapping[int, int]):
def __iter__(self) -> Iterator[int]:
"""Return an iterator over the indices of the permutation."""

def items(self) -> ItemsView[int, int]:
"""Return an iterable over the items of the permutation."""

def __len__(self) -> int:
"""Return the number of indices in the permutation."""

Expand Down Expand Up @@ -353,6 +356,18 @@ class QuantumComputation(MutableSequence[Operation]):
The unified quantum register.
"""

@property
def qregs(self) -> dict[str, QuantumRegister]:
"""The quantum registers in the quantum computation."""

@property
def cregs(self) -> dict[str, ClassicalRegister]:
"""The classical registers in the quantum computation."""

@property
def ancregs(self) -> dict[str, QuantumRegister]:
"""The ancillary registers in the quantum computation."""

# --------------------------------------------------------------------------
# Initial Layout and Output Permutation
# --------------------------------------------------------------------------
Expand Down
49 changes: 47 additions & 2 deletions src/mqt/core/ir/operations.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Licensed under the MIT License

from abc import ABC, abstractmethod
from collections.abc import Mapping, Sequence
from collections.abc import Iterable, Mapping, MutableSequence, Sequence
from typing import ClassVar, overload

from .registers import ClassicalRegister
Expand Down Expand Up @@ -665,7 +665,7 @@ class NonUnitaryOperation(Operation):
def invert(self) -> None:
"""Non-unitary operations are, per definition, not invertible."""

class CompoundOperation(Operation):
class CompoundOperation(Operation, MutableSequence[Operation]):
"""Compound quantum operation.
This class is used to aggregate and group multiple operations into a single
Expand Down Expand Up @@ -712,12 +712,57 @@ class CompoundOperation(Operation):
This gives direct access to the operations in the compound operation.
"""

@overload
def __setitem__(self, idx: int, op: Operation) -> None:
"""Set the operation at the given index.
Args:
idx: The index of the operation to set.
op: The operation to set at the given index.
"""

@overload
def __setitem__(self, idx: slice, ops: Iterable[Operation]) -> None:
"""Set the operations in the given slice.
Args:
idx: The slice of operations to set.
ops: The operations to set in the given slice.
"""

@overload
def __delitem__(self, idx: int) -> None:
"""Delete the operation at the given index.
Args:
idx: The index of the operation to delete.
"""

@overload
def __delitem__(self, idx: slice) -> None:
"""Delete the operations in the given slice.
Args:
idx: The slice of operations to delete.
"""

def insert(self, idx: int, op: Operation) -> None:
"""Insert an operation at the given index.
Args:
idx: The index to insert the operation at.
op: The operation to insert.
"""

def append(self, op: Operation) -> None:
"""Append an operation to the compound operation."""

def empty(self) -> bool:
"""Check if the compound operation is empty."""

def clear(self) -> None:
"""Clear all operations in the compound operation."""

def add_control(self, control: Control) -> None:
"""Add a control to the operation.
Expand Down
18 changes: 18 additions & 0 deletions src/mqt/core/plugins/qiskit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) 2025 Chair for Design Automation, TUM
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

"""MQT Qiskit Plugin."""

from __future__ import annotations

from .mqt_to_qiskit import mqt_to_qiskit
from .qiskit_to_mqt import qiskit_to_mqt

__all__ = [
"mqt_to_qiskit",
"qiskit_to_mqt",
]
Loading

0 comments on commit b7c3cfc

Please sign in to comment.