Source code for qbraid.transpiler.conversions.qasm2.qasm2_to_ionq

# Copyright (C) 2024 qBraid
#
# This file is part of the qBraid-SDK
#
# The qBraid-SDK is free software released under the GNU General Public License v3
# or later. You can redistribute and/or modify it under the terms of the GPL v3.
# See the LICENSE file in the project root or <https://www.gnu.org/licenses/gpl-3.0.html>.
#
# THERE IS NO WARRANTY for the qBraid-SDK, as per Section 15 of the GPL v3.

"""
Module containing functions to convert between OpenQASM 2 and IonQ JSON format.

"""
from __future__ import annotations

import re
from typing import TYPE_CHECKING, Any

import openqasm3.ast

from qbraid.passes.qasm3.compat import convert_qasm_pi_to_decimal
from qbraid.programs.circuits.qasm import OpenQasm2Program
from qbraid.transpiler.annotations import weight

if TYPE_CHECKING:
    from qbraid.programs.typer import IonQDictType, Qasm2StringType


[docs] @weight(1) def qasm2_to_ionq(qasm: Qasm2StringType) -> IonQDictType: """Returns an IonQ JSON format representation the input OpenQASM 2 string. Args: qasm (str): OpenQASM 2 string to convert to a pytket circuit. Returns: dict: IonQ JSON format equivalent to input OpenQASM 2 string. """ qprogram = OpenQasm2Program(qasm) num_qubits = qprogram.num_qubits program = qprogram.parsed() gates: list[dict[str, Any]] = [] for statement in program.statements: if isinstance(statement, openqasm3.ast.QuantumGate): name = statement.name.name qubits = statement.qubits qubit_values = [] for qubit in qubits: _ = qubit.name.name indices = qubit.indices for index in indices: qubit_values.extend(literal.value for literal in index) # support gates defined in `stdgates.inc` from OpenQASM 3 if len(qubit_values) == 1: # IonQ supported gates: if name in ["x", "not", "y", "z", "h", "s", "si", "t", "ti", "v", "vi"]: gate_data = {"gate": name, "target": qubit_values[0]} elif name in ["rx", "ry", "rz"]: # convert "rz(3 * pi / 4) q[0];" to "3 * pi / 4" angle_str = re.findall(r"\((.+)\)", openqasm3.dumps(statement))[0] gate_data = { "gate": name, "target": qubit_values[0], "rotation": float(convert_qasm_pi_to_decimal(angle_str)), } # OpenQASM 3 aliases: elif name == "sdg": gate_data = {"gate": "si", "target": qubit_values[0]} elif name == "tdg": gate_data = {"gate": "ti", "target": qubit_values[0]} elif name == "sx": gate_data = {"gate": "v", "target": qubit_values[0]} elif name == "sxdg": gate_data = {"gate": "vi", "target": qubit_values[0]} else: raise NotImplementedError(f"'{name}' gate not yet supported") elif len(qubit_values) == 2: if name in ["cnot", "cx", "CX"]: gate_data = { "gate": "cnot", "control": qubit_values[0], "target": qubit_values[1], } elif name == "swap": gate_data = { "gate": "swap", "targets": qubit_values, } else: raise NotImplementedError(f"'{name}' gate not yet supported") elif len(qubit_values) == 3: if name in ["ccx", "toffoli"]: gate_data = { "gate": "cnot", "controls": qubit_values[:2], "target": qubit_values[2], } else: raise NotImplementedError(f"'{name}' gate not yet supported") gates.append(gate_data) return {"qubits": num_qubits, "circuit": gates}