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
19 changes: 17 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
# Changelog

## v0.3.0 (2026-03-13)

### What's Changed
* fix: call ProgramContext constructor by @rmshaffer in https://github.com/amazon-braket/autoqasm/pull/93
* fix: updated config file by @sesmart in https://github.com/amazon-braket/autoqasm/pull/81
* update error message for index error by @yitchen-tim in https://github.com/amazon-braket/autoqasm/pull/82
* depr: drop Python 3.10 support by @rmshaffer in https://github.com/amazon-braket/autoqasm/pull/92

### New Contributors
* @sesmart made their first contribution in https://github.com/amazon-braket/autoqasm/pull/81
* @yitchen-tim made their first contribution in https://github.com/amazon-braket/autoqasm/pull/82
* @speller26 made their first contribution in https://github.com/amazon-braket/autoqasm/pull/84

**Full Changelog**: https://github.com/amazon-braket/autoqasm/compare/v0.2.0...v0.3.0

## v0.2.0 (2025-08-26)

## What's Changed
### What's Changed
* infra: update supported python versions by @rmshaffer in https://github.com/amazon-braket/autoqasm/pull/77
* change: Use Ankaa-2 instead of Aspen-M-3 in pulse examples by @rmshaffer in https://github.com/amazon-braket/autoqasm/pull/48
* infra: onboard to use ruff by @AbeCoull in https://github.com/amazon-braket/autoqasm/pull/53
* feature: Use hybrid_job from braket.jobs by @rmshaffer in https://github.com/amazon-braket/autoqasm/pull/66

## New Contributors
### New Contributors
* @AbeCoull made their first contribution in https://github.com/amazon-braket/autoqasm/pull/53

**Full Changelog**: https://github.com/amazon-braket/autoqasm/compare/v0.1.2...v0.1.3
Expand Down
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

setup(
name="autoqasm",
version="0.2.0",
version="0.3.0",
license="Apache License 2.0",
python_requires=">= 3.11",
packages=find_namespace_packages(where="src", exclude=("test",)),
Expand All @@ -27,13 +27,12 @@
"amazon-braket-sdk>=1.89.1",
"amazon-braket-default-simulator>=1.23.2",
"oqpy~=0.3.5",
"diastatic-malt",
"diastatic-malt>=2.15.3",
"numpy",
"openpulse",
"openqasm3",
"sympy",
"astunparse",
"gast",
"termcolor",
"openqasm_pygments",
],
Expand Down
31 changes: 16 additions & 15 deletions src/autoqasm/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
import copy
import functools
import inspect
from collections.abc import Callable
from collections.abc import Callable, Iterable
from types import FunctionType
from typing import Any, Iterable, get_args
from typing import Any, get_args

import openqasm3.ast as qasm_ast
import oqpy.base
Expand Down Expand Up @@ -227,7 +227,7 @@ def _convert_main(
Returns:
aq_program.Program: Generated AutoQASM Program.
"""
if "device" in kwargs and kwargs["device"]:
if kwargs.get("device"):
user_config.device = kwargs["device"]

param_dict = {}
Expand Down Expand Up @@ -479,8 +479,8 @@ def _clone_function(f_source: Callable) -> Callable:
copy.deepcopy(f_source.__defaults__),
copy.copy(f_source.__closure__),
)
setattr(f_clone, "__signature__", copy.deepcopy(inspect.signature(f_source)))
setattr(f_clone, "__annotations__", copy.deepcopy(f_source.__annotations__))
f_clone.__signature__ = copy.deepcopy(inspect.signature(f_source))
f_clone.__annotations__ = copy.deepcopy(f_source.__annotations__)
return f_clone


Expand All @@ -492,15 +492,15 @@ def f_dummy(*args, **kwargs) -> Any:

f_dummy.__name__ = copy.deepcopy(f_source.__name__)
f_dummy.__defaults__ = copy.deepcopy(f_source.__defaults__)
setattr(f_dummy, "__signature__", copy.deepcopy(inspect.signature(f_source)))
setattr(f_dummy, "__annotations__", copy.deepcopy(f_source.__annotations__))
f_dummy.__signature__ = copy.deepcopy(inspect.signature(f_source))
f_dummy.__annotations__ = copy.deepcopy(f_source.__annotations__)
return f_dummy


def _make_return_instance_from_f_annotation(f: Callable) -> Any:
# TODO: Recursive functions should work even if the user's type hint is wrong
annotations = f.__annotations__
return_type = annotations["return"] if "return" in annotations else None
return_type = annotations.get("return", None)
return return_type() if return_type else None


Expand Down Expand Up @@ -609,9 +609,8 @@ def _get_gate_args(f: Callable) -> aq_program.GateArgs:

if param.annotation == aq_instructions.QubitIdentifierType:
gate_args.append_qubit(param.name)
elif param.annotation == float or any( # noqa: E721
type_ == float # noqa: E721
for type_ in get_args(param.annotation)
elif param.annotation == float or any(
type_ == float for type_ in get_args(param.annotation)
):
gate_args.append_angle(param.name)
else:
Expand Down Expand Up @@ -675,11 +674,13 @@ def _convert_calibration(
},
}

with aq_program.build_program() as program_conversion_context:
with program_conversion_context.calibration_definition(
with (
aq_program.build_program() as program_conversion_context,
program_conversion_context.calibration_definition(
gate_function.__name__, gate_calibration_qubits, gate_calibration_angles
):
aq_transpiler.converted_call(f, [], func_call_kwargs, options=options)
),
):
aq_transpiler.converted_call(f, [], func_call_kwargs, options=options)

return GateCalibration(
gate_function=gate_function,
Expand Down
7 changes: 2 additions & 5 deletions src/autoqasm/converters/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@

import ast

import gast
from malt.core import ag_ctx, converter
from malt.pyct import templates

ARITHMETIC_OPERATORS = {
gast.FloorDiv: "ag__.floor_div",
ast.FloorDiv: "ag__.floor_div",
}


Expand All @@ -41,15 +40,13 @@ def visit_BinOp(self, node: ast.stmt) -> ast.stmt:

template = f"{ARITHMETIC_OPERATORS[op_type]}(lhs_,rhs_)"

new_node = templates.replace(
return templates.replace(
template,
lhs_=node.left,
rhs_=node.right,
original=node,
)[0].value

return new_node


def transform(node: ast.stmt, ctx: ag_ctx.ControlStatusCtx) -> ast.stmt:
"""Transform arithmetic nodes.
Expand Down
5 changes: 2 additions & 3 deletions src/autoqasm/converters/assignments.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import ast

import gast
from malt.core import ag_ctx, converter
from malt.pyct import templates

Expand Down Expand Up @@ -52,8 +51,8 @@ def visit_Assign(self, node: ast.stmt) -> ast.stmt:
if len(node.targets) > 1:
raise NotImplementedError

if isinstance(node.targets[0], gast.Name):
target_name = gast.Constant(node.targets[0].id, None)
if isinstance(node.targets[0], ast.Name):
target_name = ast.Constant(node.targets[0].id, None)
new_node = templates.replace(
template,
tar_name_=target_name,
Expand Down
9 changes: 4 additions & 5 deletions src/autoqasm/converters/comparisons.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@

import ast

import gast
from malt.core import ag_ctx, converter
from malt.pyct import templates

COMPARISON_OPERATORS = {
gast.Lt: "ag__.lt_",
gast.LtE: "ag__.lteq_",
gast.Gt: "ag__.gt_",
gast.GtE: "ag__.gteq_",
ast.Lt: "ag__.lt_",
ast.LtE: "ag__.lteq_",
ast.Gt: "ag__.gt_",
ast.GtE: "ag__.gteq_",
}


Expand Down
8 changes: 3 additions & 5 deletions src/autoqasm/converters/return_statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import ast

import gast
from malt.converters import return_statements
from malt.core import ag_ctx, converter
from malt.pyct import templates
Expand Down Expand Up @@ -45,17 +44,16 @@ def visit_Return(self, node: ast.stmt) -> ast.stmt:
)

name = constants.MAIN_RETURN_VAL_NAME
if isinstance(node.value, gast.Name):
if isinstance(node.value, ast.Name):
name = node.value.id

node = templates.replace(
return templates.replace(
template,
name_=name,
name_const_=gast.Constant(name, None),
name_const_=ast.Constant(name, None),
value_=node.value,
original=node,
)
return node


def transform(
Expand Down
6 changes: 3 additions & 3 deletions src/autoqasm/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ class UnsupportedConditionalExpressionError(AutoQasmError):
def __init__(self, true_type: type | None, false_type: type | None):
if_type = true_type.__name__ if true_type else "None"
else_type = false_type.__name__ if false_type else "None"
self.message = """\
`if` clause resolves to {}, but `else` clause resolves to {}. \
self.message = f"""\
`if` clause resolves to {if_type}, but `else` clause resolves to {else_type}. \
Both the `if` and `else` clauses of an inline conditional expression \
must resolve to the same type.""".format(if_type, else_type)
must resolve to the same type."""

def __str__(self):
return self.message
Expand Down
2 changes: 1 addition & 1 deletion src/autoqasm/instructions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def bell():
measure([0, 1])
"""

from .gates import * # noqa: F401, F403
from .gates import *
from .instructions import reset # noqa: F401
from .measurements import measure # noqa: F401
from .qubits import global_qubit_register # noqa: F401
4 changes: 1 addition & 3 deletions src/autoqasm/instructions/gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@

"""Quantum gates, unitary instructions, that apply to qubits."""

from typing import Union

import oqpy

from autoqasm.instructions.instructions import _qubit_instruction
from autoqasm.types import QubitIdentifierType
from braket.circuits.free_parameter_expression import FreeParameterExpression

GateParameterType = Union[float, FreeParameterExpression, oqpy._ClassicalVar]
GateParameterType = float | FreeParameterExpression | oqpy._ClassicalVar


def ccnot(
Expand Down
4 changes: 2 additions & 2 deletions src/autoqasm/instructions/qubits.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from __future__ import annotations

import re
from collections.abc import Iterable
from collections.abc import Iterator
from functools import singledispatch
from typing import Any

Expand Down Expand Up @@ -58,7 +58,7 @@ def __init__(self, size: int | None):
def __len__(self) -> int:
return self.size

def __iter__(self) -> Iterable:
def __iter__(self) -> Iterator:
return iter(range(len(self)))


Expand Down
16 changes: 8 additions & 8 deletions src/autoqasm/operators/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@


def floor_div(
num: aq_types.IntVar | aq_types.FloatVar | int | float,
den: aq_types.IntVar | aq_types.FloatVar | int | float,
num: aq_types.IntVar | aq_types.FloatVar | float,
den: aq_types.IntVar | aq_types.FloatVar | float,
) -> int | aq_types.IntVar:
"""Functional form of "//".
Args:
num (IntVar | FloatVar | int | float) : The numerator of the integer division
den (IntVar | FloatVar | int | float) : The denominator of the integer division
num (IntVar | FloatVar | float) : The numerator of the integer division
den (IntVar | FloatVar | float) : The denominator of the integer division
Returns :
int | IntVar : integer division, IntVar if either numerator or denominator
are QASM types, else int
Expand All @@ -40,8 +40,8 @@ def floor_div(


def _oqpy_floor_div(
num: aq_types.IntVar | aq_types.FloatVar | int | float,
den: aq_types.IntVar | aq_types.FloatVar | int | float,
num: aq_types.IntVar | aq_types.FloatVar | float,
den: aq_types.IntVar | aq_types.FloatVar | float,
) -> aq_types.IntVar | aq_types.FloatVar:
num, den = _register_and_convert_parameters(num, den)
oqpy_program = program.get_program_conversion_context().get_oqpy_program()
Expand Down Expand Up @@ -75,7 +75,7 @@ def _oqpy_floor_div(


def _py_floor_div(
num: int | float,
den: int | float,
num: float,
den: float,
) -> int | float:
return num // den
3 changes: 2 additions & 1 deletion src/autoqasm/operators/logical.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

from __future__ import annotations

from typing import Any, Callable
from collections.abc import Callable
from typing import Any

import oqpy.base
from openpulse import ast
Expand Down
2 changes: 1 addition & 1 deletion src/autoqasm/operators/slices.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def _oqpy_get_item(target: Any, i: Any, opts: GetItemOpts) -> Any:
elif isinstance(target, oqpy.BitVar):
base_type = type(target)
else:
raise TypeError(f"{str(type(target))} object is not subscriptable")
raise TypeError(f"{type(target)!s} object is not subscriptable")

var = base_type()
oqpy_program.set(var, target[i])
Expand Down
2 changes: 1 addition & 1 deletion src/autoqasm/program/pragmas.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def pragma_example() -> None:
from __future__ import annotations

import contextlib
from collections.abc import Iterable
from enum import StrEnum
from typing import Iterable

from autoqasm import errors, program
from braket.device_schema import DeviceActionType
Expand Down
Loading
Loading