Skip to content

Commit

Permalink
started
Browse files Browse the repository at this point in the history
register visit completed

exploring measurements

complete measurements

start gates

add reset
  • Loading branch information
TheGupta2012 committed Mar 1, 2024
1 parent 6a87ac1 commit 1daf009
Show file tree
Hide file tree
Showing 24 changed files with 851 additions and 27 deletions.
2 changes: 2 additions & 0 deletions qbraid_qir/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,7 @@
"""
from ._version import __version__
from .cirq import cirq_to_qir
from .exceptions import QbraidQirError, QirConversionError
from .qasm3 import qasm3_to_qir
from .serialization import dumps
1 change: 0 additions & 1 deletion qbraid_qir/cirq/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

"""
Module defining Cirq LLVM Module elements.
"""

import hashlib
Expand Down
17 changes: 16 additions & 1 deletion qbraid_qir/qasm3/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@

import openqasm3
from pyqir import Context, Module, qir_module
from qiskit.qasm3 import loads
from qiskit.qasm3.exporter import Exporter

from qbraid_qir.exceptions import QirConversionError
from qbraid_qir.qasm3.elements import Qasm3Module
from qbraid_qir.qasm3.elements import Qasm3Module, generate_module_id
from qbraid_qir.qasm3.visitor import BasicQisVisitor


Expand All @@ -45,13 +47,26 @@ def qasm3_to_qir(
QirConversionError: If the conversion fails.
"""
if isinstance(program, str):
# Supported conversions qasm3 -> qiskit :
# https://github.com/Qiskit/qiskit-qasm3-import/blob/main/src/qiskit_qasm3_import/converter.py

# PROPOSED SEMANTIC + DECOMPOSITION PASS
# qiskit_circuit = loads(program).decompose(reps=3)
# decomposed_qasm = Exporter().dumps(qiskit_circuit)
# PROPOSED SEMANTIC + DECOMPOSITION PASS

# program = openqasm3.parse(decomposed_qasm)

program = openqasm3.parse(program)

elif not isinstance(program, openqasm3.ast.Program):
raise TypeError(
"Input quantum program must be of type openqasm3.ast.Program or str."
)

if name is None:
name = generate_module_id()

llvm_module = qir_module(Context(), name)
module = Qasm3Module.from_program(program, llvm_module)

Expand Down
49 changes: 34 additions & 15 deletions qbraid_qir/qasm3/elements.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
# Copyright (C) 2023 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 defining Qasm3 Converter elements.
"""

import uuid
from abc import ABCMeta, abstractmethod
from typing import List, Optional, Tuple

from openqasm3.ast import (
BitType,
ClassicalDeclaration,
Program,
QubitDeclaration,
Statement,
)
from openqasm3.ast import (BitType, ClassicalDeclaration, Program,
QubitDeclaration, Statement)
from pyqir import Context, Module


def generate_module_id(program: Program) -> str:
def generate_module_id() -> str:
"""
Generates a QIR module ID from a given openqasm3 program.
"""
Expand All @@ -33,11 +43,15 @@ def accept(self, visitor):


class _Register(_ProgramElement):
def __init__(self, register: Tuple(str, Optional[int])):
def __init__(self, register: Tuple[str, Optional[int]], is_qubit: bool = True):
self._register = register
self._is_qubit = is_qubit

def accept(self, visitor):
visitor.visit_register(self._register)
visitor.visit_register(self._register, self._is_qubit)

def __str__(self) -> str:
return f"Register({self._register}, is_qubit = {self._is_qubit})"


class _Statement(_ProgramElement):
Expand All @@ -47,6 +61,9 @@ def __init__(self, statement: Statement):
def accept(self, visitor):
visitor.visit_statement(self._statement)

def __str__(self) -> str:
return f"Statement({self._statement})"


class Qasm3Module:
"""
Expand Down Expand Up @@ -97,30 +114,32 @@ def from_program(cls, program: Program, module: Optional[Module] = None):
"""
elements: List[Statement] = []

qubits = []
clbits = []
num_qubits = 0
num_clbits = 0
for statement in program.statements:
if isinstance(statement, QubitDeclaration):
name = statement.qubit.name
size = None if statement.size is None else statement.size.value
qubits.append((name, size))
num_qubits += 1 if size is None else size
elements.append(_Register((name, size), True))

elif isinstance(statement, ClassicalDeclaration) and isinstance(
statement.type, BitType
):
name = statement.identifier.name
size = (
None if statement.type.size is None else statement.type.size.value
)
clbits.append((name, size))
num_clbits += 1 if size is None else size
elements.append(statement)
elements.append(_Register((name, size), False))
else:
elements.append(_Statement(statement))

if module is None:
module = Module(Context(), generate_module_id(program))

# for element in elements:
# print(element,"\n")
return cls(
name="main",
module=module,
Expand Down
70 changes: 70 additions & 0 deletions qbraid_qir/qasm3/oq3_maps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Copyright (C) 2023 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 mapping supported QASM gates/operations to pyqir functions.
"""

import pyqir


def id_gate(builder, qubits):
pyqir._native.x(builder, qubits)
pyqir._native.x(builder, qubits)


PYQIR_ONE_QUBIT_OP_MAP = {
# Identity Gate
"id": id_gate,
# Single-Qubit Clifford Gates
"h": pyqir._native.h,
"x": pyqir._native.x,
"y": pyqir._native.y,
"z": pyqir._native.z,
# Single-Qubit Non-Clifford Gates
"s": pyqir._native.s,
"t": pyqir._native.t,
"sdg": pyqir._native.s_adj,
"tdg": pyqir._native.t_adj,
# Single-Qubit Rotation Gates
"rx": pyqir._native.rx,
"ry": pyqir._native.ry,
"rz": pyqir._native.rz,

# Classical Gates/Operations
"measure": pyqir._native.mz,
"reset": pyqir._native.reset,
}

PYQIR_TWO_QUBIT_OP_MAP = {
"cx": pyqir._native.cx,
"CX" : pyqir._native.cx,
"cz": pyqir._native.cz,
"swap": pyqir._native.swap,
}

PYQIR_THREE_QUBIT_OP_MAP = {
"ccx": pyqir._native.ccx,
}

def map_qasm_op_to_pyqir_callable(op_name: str):
try:
return PYQIR_ONE_QUBIT_OP_MAP[op_name], 1
except KeyError:
pass
try:
return PYQIR_TWO_QUBIT_OP_MAP[op_name], 2
except KeyError:
pass
try:
return PYQIR_THREE_QUBIT_OP_MAP[op_name], 3
except KeyError:
raise ValueError(f"Unsupported QASM operation: {op_name}")
14 changes: 14 additions & 0 deletions qbraid_qir/qasm3/preprocess.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Use this for qasm3 equivalent too.
# custom gate definitions should be decomposed into the basic gates
# supported by the QIR conversion.
# The supported gates are defined in the opsets module.


# can use this -
# https://github.com/qBraid/qBraid/blob/eec41d1d4a2cbda0385191d041884fbe2965328e/qbraid/programs/qasm3.py#L108


# run simulations with both qasm3 and qir programs and compare the results for final tests


# can use rigetti simulator for qir programs and qiskit for qasm3 programs
Loading

0 comments on commit 1daf009

Please sign in to comment.