Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/pyqasm/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

from pyqasm.analyzer import Qasm3Analyzer
from pyqasm.exceptions import ValidationError, raise_qasm3_error
from pyqasm.maps import CONSTANTS_MAP, qasm3_expression_op_map
from pyqasm.maps.expressions import CONSTANTS_MAP, qasm3_expression_op_map
from pyqasm.validator import Qasm3Validator


Expand Down
38 changes: 38 additions & 0 deletions src/pyqasm/maps/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (C) 2024 qBraid
#
# This file is part of pyqasm
#
# Pyqasm 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 pyqasm, as per Section 15 of the GPL v3.

"""
Module mapping supported QASM gates/operations to lower level gate operations.

"""

from openqasm3.ast import (
ClassicalDeclaration,
QuantumBarrier,
QuantumGate,
QuantumGateDefinition,
QuantumMeasurementStatement,
QuantumReset,
QubitDeclaration,
SubroutineDefinition,
)

# Reference : https://openqasm.com/language/classical.html#the-switch-statement
# Paragraph 14
SWITCH_BLACKLIST_STMTS = {
QubitDeclaration,
ClassicalDeclaration,
SubroutineDefinition,
QuantumGateDefinition,
}

SUPPORTED_QASM_VERSIONS = {"3.0", "3", "2", "2.0"}

QUANTUM_STATEMENTS = (QuantumGate, QuantumBarrier, QuantumReset, QuantumMeasurementStatement)
158 changes: 158 additions & 0 deletions src/pyqasm/maps/expressions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# Copyright (C) 2024 qBraid
#
# This file is part of pyqasm
#
# Pyqasm 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 pyqasm, as per Section 15 of the GPL v3.

"""
Module mapping supported QASM expressions to lower level gate operations.

"""

from typing import Callable, Union

import numpy as np
from openqasm3.ast import AngleType, BitType, BoolType, ComplexType, FloatType, IntType, UintType

from pyqasm.exceptions import ValidationError

# Define the type for the operator functions
OperatorFunction = Union[
Callable[[Union[int, float, bool]], Union[int, float, bool]],
Callable[[Union[int, float, bool], Union[int, float, bool]], Union[int, float, bool]],
]


OPERATOR_MAP: dict[str, OperatorFunction] = {
"+": lambda x, y: x + y,
"-": lambda x, y: x - y,
"*": lambda x, y: x * y,
"/": lambda x, y: x / y,
"%": lambda x, y: x % y,
"==": lambda x, y: x == y,
"!=": lambda x, y: x != y,
"<": lambda x, y: x < y,
">": lambda x, y: x > y,
"<=": lambda x, y: x <= y,
">=": lambda x, y: x >= y,
"&&": lambda x, y: x and y,
"||": lambda x, y: x or y,
"^": lambda x, y: x ^ y,
"&": lambda x, y: x & y,
"|": lambda x, y: x | y,
"<<": lambda x, y: x << y,
">>": lambda x, y: x >> y,
"~": lambda x: ~x,
"!": lambda x: not x,
"UMINUS": lambda x: -x,
}


def qasm3_expression_op_map(op_name: str, *args) -> Union[float, int, bool]:
"""
Return the result of applying the given operator to the given operands.

Args:
op_name (str): The operator name.
*args: The operands of type Union[int, float, bool]
1. For unary operators, a single operand (e.g., ~3)
2. For binary operators, two operands (e.g., 3 + 2)

Returns:
(Union[float, int, bool]): The result of applying the operator to the operands.
"""
try:
operator = OPERATOR_MAP[op_name]
return operator(*args)
except KeyError as exc:
raise ValidationError(f"Unsupported / undeclared QASM operator: {op_name}") from exc


# pylint: disable=inconsistent-return-statements
def qasm_variable_type_cast(openqasm_type, var_name, base_size, rhs_value):
"""Cast the variable type to the type to match, if possible.

Args:
openqasm_type : The type of the variable.
type_of_rhs (type): The type to match.

Returns:
The casted variable type.

Raises:
ValidationError: If the cast is not possible.
"""
type_of_rhs = type(rhs_value)

if type_of_rhs not in VARIABLE_TYPE_CAST_MAP[openqasm_type]:
raise ValidationError(
f"Cannot cast {type_of_rhs} to {openqasm_type}. "
f"Invalid assignment of type {type_of_rhs} to variable {var_name} "
f"of type {openqasm_type}"
)

if openqasm_type == BoolType:
return bool(rhs_value)
if openqasm_type == IntType:
return int(rhs_value)
if openqasm_type == UintType:
return int(rhs_value) % (2**base_size)
if openqasm_type == FloatType:
return float(rhs_value)
# not sure if we wanna hande array bit assignments too.
# For now, we only cater to single bit assignment.
if openqasm_type == BitType:
return rhs_value != 0
if openqasm_type == AngleType:
return rhs_value # not sure


# IEEE 754 Standard for floats
# https://openqasm.com/language/types.html#floating-point-numbers
LIMITS_MAP = {"float_32": 1.70141183 * (10**38), "float_64": 10**308}

CONSTANTS_MAP = {
"π": 3.141592653589793,
"pi": 3.141592653589793,
"ℇ": 2.718281828459045,
"euler": 2.718281828459045,
"τ": 6.283185307179586,
"tau": 6.283185307179586,
}

VARIABLE_TYPE_MAP = {
BitType: bool,
IntType: int,
UintType: int,
BoolType: bool,
FloatType: float,
ComplexType: complex,
# AngleType: None, # not sure
}

# Reference: https://openqasm.com/language/types.html#allowed-casts
VARIABLE_TYPE_CAST_MAP = {
BoolType: (int, float, bool, np.int64, np.float64, np.bool_),
IntType: (bool, int, float, np.int64, np.float64, np.bool_),
BitType: (bool, int, np.int64, np.bool_),
UintType: (bool, int, float, np.int64, np.uint64, np.float64, np.bool_),
FloatType: (bool, int, float, np.int64, np.float64, np.bool_),
AngleType: (float, np.float64),
}

ARRAY_TYPE_MAP = {
BitType: np.bool_,
IntType: np.int64,
UintType: np.uint64,
FloatType: np.float64,
ComplexType: np.complex128,
BoolType: np.bool_,
AngleType: np.float64,
}

# Reference : https://openqasm.com/language/types.html#arrays
MAX_ARRAY_DIMENSIONS = 7
Loading