Skip to content

Commit

Permalink
Merge pull request #20 from yasuhito/feature/ouqu-tp-support
Browse files Browse the repository at this point in the history
add ouqu-tp support
  • Loading branch information
snuffkin authored Dec 25, 2024
2 parents e17f095 + eb60d2c commit 95d14c1
Show file tree
Hide file tree
Showing 24 changed files with 693 additions and 135 deletions.
19 changes: 19 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,23 @@ ARG DEBIAN_VERSION=bookworm
FROM ghcr.io/astral-sh/uv:$UV_VERSION AS uv
FROM mcr.microsoft.com/vscode/devcontainers/base:$DEBIAN_VERSION

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential=12.9 \
cmake=3.25.1-1 \
git=1:2.39.5-0+deb12u1 \
bison=2:3.8.2+dfsg-1+b1 \
flex=2.6.4-8.2 \
libboost-all-dev=1.74.0.3 \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /tmp/staq
RUN git clone https://github.com/softwareQinc/staq.git . \
&& mkdir build

WORKDIR /tmp/staq/build
RUN cmake .. \
&& make -j8 \
&& make install \
&& rm -rf /tmp/staq

COPY --from=uv --chown=vscode: /uv /uvx /bin/
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"njpwerner.autodocstring",
"redhat.vscode-yaml",
"shardulm94.trailing-spaces",
"tamasfe.even-better-toml"
"tamasfe.even-better-toml",
"ms-python.mypy-type-checker"
]
}
},
Expand Down
28 changes: 28 additions & 0 deletions .github/actions/setup-staq/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Setup Staq
description: Install Staq quantum compiler

runs:
using: composite
steps:
- name: Install dependencies
run: |
sudo apt-get update && sudo apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
bison \
flex \
libboost-all-dev
shell: bash

- name: Build and install Staq
run: |
cd /tmp
git clone https://github.com/softwareQinc/staq.git
cd staq
mkdir build
cd build
cmake ..
make -j8
sudo make install
shell: bash
3 changes: 3 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Staq
uses: ./.github/actions/setup-staq

- name: Setup Python ${{ matrix.python-version }} with uv
uses: ./.github/actions/setup-python-with-uv
with:
Expand Down
3 changes: 2 additions & 1 deletion docs/usage/how_it_works.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@
"\n",
"| Transpiler Library | Description |\n",
"|--------------------|------------------------------------------|\n",
"| `\"qiskit\"` | Transpile quantum circuits using Qiskit. |"
"| `\"qiskit\"` | Transpile quantum circuits using Qiskit. |\n",
"| `\"ouqu-tp\"` | Transpile quantum circuits using ouqu-tp.|"
]
},
{
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dependencies = [
"qiskit_qasm3_import>=0.5.0",
"pytket>=1.33.0",
"pytket-qiskit>=0.56.0",
"ouqu-tp>=1.0.0",
]

[project.urls]
Expand Down
4 changes: 4 additions & 0 deletions src/tranqu/device_converter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
DeviceConverterManager,
DeviceConverterNotFoundError,
)
from .oqtopus_to_ouqu_tp_device_converter import OqtopusToOuquTpDeviceConverter
from .oqtopus_to_qiskit_device_converter import OqtoqusToQiskitDeviceConverter
from .pass_through_device_converter import PassThroughDeviceConverter
from .qiskit_device import QiskitDevice
from .qiskit_to_ouqu_tp_device_converter import QiskitToOuquTpDeviceConverter

__all__ = [
"DeviceConverter",
"DeviceConverterAlreadyRegisteredError",
"DeviceConverterError",
"DeviceConverterManager",
"DeviceConverterNotFoundError",
"OqtopusToOuquTpDeviceConverter",
"OqtoqusToQiskitDeviceConverter",
"PassThroughDeviceConverter",
"QiskitDevice",
"QiskitToOuquTpDeviceConverter",
]
21 changes: 21 additions & 0 deletions src/tranqu/device_converter/oqtopus_to_ouqu_tp_device_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import json
from typing import Any

from .device_converter import DeviceConverter


class OqtopusToOuquTpDeviceConverter(DeviceConverter):
"""Device converter for converting from Oqtopus to ouqu-tp format."""

@staticmethod
def convert(device: dict[str, Any]) -> str:
"""Convert a Oqtopus device to ouqu-tp format.
Args:
device (dict[str, Any]): The Oqtopus device to be converted.
Returns:
str: The converted ouqu-tp format device.
"""
return json.dumps(device)
89 changes: 89 additions & 0 deletions src/tranqu/device_converter/qiskit_to_ouqu_tp_device_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import json
from typing import Any, ClassVar

from qiskit.providers import BackendV2 # type: ignore[import-untyped]
from qiskit.transpiler import InstructionProperties # type: ignore[import-untyped]

from .device_converter import DeviceConverter


class QiskitToOuquTpDeviceConverter(DeviceConverter):
"""Device converter for converting from Qiskit to ouqu-tp format."""

_SINGLE_QUBIT_GATES: ClassVar[list[str]] = ["x", "sx", "rz"]
_TWO_QUBIT_GATE = "cx"
_NANO_SECONDS = 1e9

def convert(self, device: BackendV2) -> str:
"""Convert a Qiskit device to ouqu-tp format.
Args:
device (BackendV2): The Qiskit device to be converted.
Returns:
str: The converted ouqu-tp format device.
"""
ouqu_tp_device = {
"name": device.name,
"qubits": self._convert_qubits(device),
"couplings": self._convert_couplings(device),
}

return json.dumps(ouqu_tp_device)

def _convert_qubits(self, device: BackendV2) -> list[dict[str, Any]]:
qubits = []
target = device.target

for qubit in range(device.num_qubits):
qubit_info = {"id": qubit, "gate_duration": {}, "fidelity": None}

for gate_name in self._SINGLE_QUBIT_GATES:
if target.instruction_supported(gate_name, (qubit,)):
props = target[gate_name][qubit,]
if props:
self._update_properties(qubit_info, props, gate_name)

qubits.append(qubit_info)

return qubits

def _convert_couplings(self, device: BackendV2) -> list[dict[str, Any]]:
couplings = []
target = device.target
coupling_map = device.coupling_map

if coupling_map:
for control, target_qubit in coupling_map:
coupling_info = {
"control": control,
"target": target_qubit,
"gate_duration": {},
"fidelity": None,
}

qargs = (control, target_qubit)
if target.instruction_supported(self._TWO_QUBIT_GATE, qargs):
props = target[self._TWO_QUBIT_GATE][qargs]
if props:
self._update_properties(
coupling_info,
props,
self._TWO_QUBIT_GATE,
)

couplings.append(coupling_info)

return couplings

def _update_properties(
self,
info: dict[str, Any],
props: InstructionProperties,
gate_name: str,
) -> None:
if props.duration is not None:
info["gate_duration"][gate_name] = props.duration * self._NANO_SECONDS
if props.error is not None:
info["fidelity"] = 1 - props.error
8 changes: 8 additions & 0 deletions src/tranqu/program_converter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from .openqasm3_to_ouqu_tp_program_converter import Openqasm3ToOuquTpProgramConverter
from .openqasm3_to_qiskit_program_converter import Openqasm3ToQiskitProgramConverter
from .openqasm3_to_tket_program_converter import Openqasm3ToTketProgramConverter
from .ouqu_tp_to_openqasm3_program_converter import OuquTpToOpenqasm3ProgramConverter
from .ouqu_tp_to_qiskit_program_converter import OuquTpToQiskitProgramConverter
from .pass_through_program_converter import PassThroughProgramConverter
from .program_converter import ProgramConverter
from .program_converter_manager import (
Expand All @@ -8,19 +11,24 @@
ProgramConverterNotFoundError,
)
from .qiskit_to_openqasm3_program_converter import QiskitToOpenqasm3ProgramConverter
from .qiskit_to_ouqu_tp_program_converter import QiskitToOuquTpProgramConverter
from .qiskit_to_tket_program_converter import QiskitToTketProgramConverter
from .tket_to_openqasm3_program_converter import TketToOpenqasm3ProgramConverter
from .tket_to_qiskit_program_converter import TketToQiskitProgramConverter

__all__ = [
"Openqasm3ToOuquTpProgramConverter",
"Openqasm3ToQiskitProgramConverter",
"Openqasm3ToTketProgramConverter",
"OuquTpToOpenqasm3ProgramConverter",
"OuquTpToQiskitProgramConverter",
"PassThroughProgramConverter",
"ProgramConverter",
"ProgramConverterAlreadyRegisteredError",
"ProgramConverterManager",
"ProgramConverterNotFoundError",
"QiskitToOpenqasm3ProgramConverter",
"QiskitToOuquTpProgramConverter",
"QiskitToTketProgramConverter",
"TketToOpenqasm3ProgramConverter",
"TketToQiskitProgramConverter",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .pass_through_program_converter import PassThroughProgramConverter

Openqasm3ToOuquTpProgramConverter = PassThroughProgramConverter
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .pass_through_program_converter import PassThroughProgramConverter

OuquTpToOpenqasm3ProgramConverter = PassThroughProgramConverter
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .openqasm3_to_qiskit_program_converter import Openqasm3ToQiskitProgramConverter

OuquTpToQiskitProgramConverter = Openqasm3ToQiskitProgramConverter
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .qiskit_to_openqasm3_program_converter import QiskitToOpenqasm3ProgramConverter

QiskitToOuquTpProgramConverter = QiskitToOpenqasm3ProgramConverter
42 changes: 38 additions & 4 deletions src/tranqu/tranqu.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,27 @@
from .device_converter import (
DeviceConverter,
DeviceConverterManager,
OqtopusToOuquTpDeviceConverter,
OqtoqusToQiskitDeviceConverter,
QiskitToOuquTpDeviceConverter,
)
from .device_type_manager import DeviceTypeManager
from .program_converter import (
Openqasm3ToOuquTpProgramConverter,
Openqasm3ToQiskitProgramConverter,
Openqasm3ToTketProgramConverter,
OuquTpToOpenqasm3ProgramConverter,
OuquTpToQiskitProgramConverter,
ProgramConverter,
ProgramConverterManager,
QiskitToOpenqasm3ProgramConverter,
QiskitToOuquTpProgramConverter,
QiskitToTketProgramConverter,
TketToOpenqasm3ProgramConverter,
TketToQiskitProgramConverter,
)
from .program_type_manager import ProgramTypeManager
from .transpiler import (
QiskitTranspiler,
TranspilerManager,
)
from .transpiler import OuquTpTranspiler, QiskitTranspiler, TranspilerManager
from .transpiler_dispatcher import TranspilerDispatcher

if TYPE_CHECKING:
Expand Down Expand Up @@ -364,6 +367,11 @@ def _register_builtin_program_converters(self) -> None:
"tket",
Openqasm3ToTketProgramConverter(),
)
self.register_program_converter(
"openqasm3",
"ouqu-tp",
Openqasm3ToOuquTpProgramConverter(),
)
self.register_program_converter(
"qiskit",
"openqasm3",
Expand All @@ -389,16 +397,42 @@ def _register_builtin_program_converters(self) -> None:
"qiskit",
TketToQiskitProgramConverter(),
)
self.register_program_converter(
"ouqu-tp",
"openqasm3",
OuquTpToOpenqasm3ProgramConverter(),
)
self.register_program_converter(
"qiskit",
"ouqu-tp",
QiskitToOuquTpProgramConverter(),
)
self.register_program_converter(
"ouqu-tp",
"qiskit",
OuquTpToQiskitProgramConverter(),
)

def _register_builtin_device_converters(self) -> None:
self.register_device_converter(
"oqtopus",
"qiskit",
OqtoqusToQiskitDeviceConverter(),
)
self.register_device_converter(
"oqtopus",
"ouqu-tp",
OqtopusToOuquTpDeviceConverter(),
)
self.register_device_converter( # 追加
"qiskit",
"ouqu-tp",
QiskitToOuquTpDeviceConverter(),
)

def _register_builtin_transpilers(self) -> None:
self.register_transpiler("qiskit", QiskitTranspiler())
self.register_transpiler("ouqu-tp", OuquTpTranspiler())

def _register_builtin_program_types(self) -> None:
self.register_program_type("qiskit", QiskitCircuit)
Expand Down
2 changes: 2 additions & 0 deletions src/tranqu/transpiler/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .ouqu_tp_transpiler import OuquTpTranspiler
from .qiskit_transpiler import QiskitTranspiler
from .transpiler import Transpiler
from .transpiler_manager import (
Expand All @@ -9,6 +10,7 @@

__all__ = [
"DefaultTranspilerLibAlreadyRegisteredError",
"OuquTpTranspiler",
"QiskitTranspiler",
"Transpiler",
"TranspilerAlreadyRegisteredError",
Expand Down
Loading

0 comments on commit 95d14c1

Please sign in to comment.