Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: build autoqasm program directly from main decorator #804

Merged
merged 50 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
621ae7c
feat: remove *args from api decorators
ajberdy Nov 16, 2023
ce413b5
draft: refactor main to build programs directly
ajberdy Nov 17, 2023
1b2ebcb
lint
ajberdy Nov 17, 2023
802c1f9
clean up main logic and add test
ajberdy Nov 17, 2023
71041f8
support free parameter expressions for qubit indices
ajberdy Nov 17, 2023
39ed22d
update test_types
ajberdy Nov 17, 2023
c082e83
update test_converters
ajberdy Nov 17, 2023
53ad41b
update test_devices
ajberdy Nov 17, 2023
a2193e7
update test_gate_calibrations
ajberdy Nov 17, 2023
264aaa5
update test_gate_decorator
ajberdy Nov 17, 2023
79e3c08
update test_gate_definitions
ajberdy Nov 17, 2023
3b0807c
update test_operators and lint
ajberdy Nov 17, 2023
805b816
add closure test to py_if and py_assert tests
ajberdy Nov 17, 2023
d4d5430
update test_parameters and add GateParameterType
ajberdy Nov 17, 2023
552c9d0
update test_pragmas and lint
ajberdy Nov 17, 2023
0d27fb0
update test_program and lint
ajberdy Nov 17, 2023
d61dddb
update test_pulse and lint
ajberdy Nov 17, 2023
b5a7e5d
update test_serialization_config
ajberdy Nov 17, 2023
87f07c0
update testtranspiler
ajberdy Nov 17, 2023
9282b8d
Merge branch 'feature/autoqasm' into build-program
ajberdy Nov 17, 2023
42a8b18
post-merge lint
ajberdy Nov 17, 2023
ef30424
lint
ajberdy Nov 17, 2023
e189311
add comment
ajberdy Nov 17, 2023
1f76b13
utilize function wrapper (#807)
ajberdy Nov 20, 2023
b8757da
utilize function wrapper
ajberdy Nov 20, 2023
073a11b
keep args/kwargs in _convert_main for now
ajberdy Nov 20, 2023
608a5f3
capture todo to fix main_main test
ajberdy Nov 21, 2023
3c64370
add xfail to main main test
ajberdy Nov 21, 2023
3e9d8d8
put the xfail on the right test
ajberdy Nov 21, 2023
4f7b7d3
address feedback for program.py
ajberdy Nov 28, 2023
5319f02
update api.py
ajberdy Nov 28, 2023
6af70b7
add issue numbers to code todos
ajberdy Nov 28, 2023
0ffb40f
update test_api
ajberdy Nov 28, 2023
4077c12
update test_operators
ajberdy Nov 28, 2023
d69312c
update test_parameters
ajberdy Nov 28, 2023
d1ba303
update test_program
ajberdy Nov 28, 2023
3635dee
capitalize todos
ajberdy Nov 28, 2023
3f2529e
update first two examples
ajberdy Nov 28, 2023
6fb0644
update example 1 text
ajberdy Nov 28, 2023
b555794
remove vague todo
ajberdy Nov 28, 2023
18daf11
update example 3
ajberdy Nov 28, 2023
448fda4
update example 4
ajberdy Nov 28, 2023
55e2e7b
update example 5
ajberdy Nov 28, 2023
cafe0ae
update final example
ajberdy Nov 28, 2023
598af87
remove classmethod test
ajberdy Nov 29, 2023
af6acec
readd (modified) classmethod test for coverage
ajberdy Nov 29, 2023
b1590fe
remove xfailing test and update partial test in test_transpiler
ajberdy Nov 29, 2023
b2bcd7e
remove todo from example 3
ajberdy Nov 29, 2023
679bade
add issue # to xfail
ajberdy Nov 30, 2023
4406d4c
remove example todo and fix docstring
ajberdy Nov 30, 2023
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
13 changes: 5 additions & 8 deletions examples/autoqasm/1_Getting_started_with_AutoQASM.ipynb
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note, please also run tox -e notebooks to test the service-dependent example notebooks that currently don't run in CI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thanks for pointing this out! Just confirmed that it passes with the latest updates; I'll note this in the PR description

Large diffs are not rendered by default.

25 changes: 9 additions & 16 deletions examples/autoqasm/2_Expressing_classical_control_flow.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/braket/experimental/autoqasm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def my_program():
result[0] = measure __qubits__[0];
result[1] = measure __qubits__[1];
"""

from . import errors, operators # noqa: F401
from .api import gate, gate_calibration, main, subroutine # noqa: F401
from .instructions import QubitIdentifierType as Qubit # noqa: F401
from .program import Program, build_program, verbatim # noqa: F401
Expand Down
48 changes: 34 additions & 14 deletions src/braket/experimental/autoqasm/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@
from braket.experimental.autoqasm.instructions.qubits import QubitIdentifierType as Qubit
from braket.experimental.autoqasm.instructions.qubits import is_qubit_identifier_type
from braket.experimental.autoqasm.program.gate_calibrations import GateCalibration
from braket.parametric import FreeParameter


def main(
func: Optional[Callable] = None,
*,
num_qubits: Optional[int] = None,
device: Optional[Union[Device, str]] = None,
) -> Callable[..., aq_program.Program]:
"""Decorator that converts a function into a callable that returns
a Program object containing the quantum program.
) -> aq_program.Program | functools.partial:
"""Decorator that converts a function into a Program object containing the quantum program.

The decorator re-converts the target function whenever the decorated
function is called, and a new Program object is returned each time.
Expand All @@ -65,13 +65,22 @@ def main(
program. Can be either an Device object or a valid Amazon Braket device ARN.

Returns:
Callable[..., Program]: A callable which returns the converted
quantum program when called.
Program | partial: A callable
which returns the converted quantum program when called.
rmshaffer marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Program | partial: A callable
which returns the converted quantum program when called.
Program | partial: The Program object containing the converted quantum program, or a partial function
which returns the converted quantum program when called.

Copy link
Contributor Author

@ajberdy ajberdy Nov 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Still a bit reminiscent of the old interface, so I've updated this doc string to

Program | partial: The Program object containing the converted quantum program, or a
partial function of the `main` decorator.

(Technically the partial function returns the Program when called on the decorated function, but the language seems to imply an interface like we previously had)

"""
if isinstance(device, str):
device = AwsDevice(device)

return _function_wrapper(
# decorator is called on a Program
if isinstance(func, aq_program.Program):
return func

# decorator is used with parentheses
# (see _function_wrapper for more details)
if not (func and callable(func)):
return functools.partial(main, num_qubits=num_qubits, device=device)

program_builder = _function_wrapper(
func,
converter_callback=_convert_main,
converter_args={
Expand All @@ -82,6 +91,8 @@ def main(
},
)

return program_builder()


def subroutine(func: Optional[Callable] = None) -> Callable[..., aq_program.Program]:
"""Decorator that converts a function into a callable that will insert a subroutine into
Expand Down Expand Up @@ -182,7 +193,7 @@ def _wrapper(*args, **kwargs) -> Callable:
optional_features=_autograph_optional_features(),
)
# Call the appropriate function converter
return converter_callback(func, options, args, kwargs, **converter_args)
return converter_callback(func, options=options, args=args, kwargs=kwargs, **converter_args)

if inspect.isfunction(func) or inspect.ismethod(func):
_wrapper = functools.update_wrapper(_wrapper, func)
Expand All @@ -204,7 +215,7 @@ def _convert_main(
args: tuple[Any],
kwargs: dict[str, Any],
user_config: aq_program.UserConfig,
) -> None:
) -> aq_program.Program:
"""Convert the initial callable `f` into a full AutoQASM program `program`.
Puts the contents of `f` at the global level of the program, rather than
putting it into a subroutine as done in `_convert_subroutine`.
Expand All @@ -218,16 +229,25 @@ def _convert_main(
args (tuple[Any]): Arguments passed to the program when called.
kwargs (dict[str, Any]): Keyword arguments passed to the program when called.
user_config (UserConfig): User-specified settings that influence program building.

Returns:
aq_program.Program: Generated AutoQASM Program.
"""
if aq_program.in_active_program_conversion_context():
raise errors.AutoQasmTypeError(
f"Cannot call main function '{f.__name__}' from another main function. Did you mean "
"to use '@aq.subroutine'?"
)
kwargs = {}
parameters = inspect.signature(f).parameters

with aq_program.build_program(user_config) as program_conversion_context:
# Capture inputs to decorated function as `FreeParameter` inputs for the Program
for param in parameters.values():
if param.kind == param.POSITIONAL_OR_KEYWORD:
kwargs[param.name] = FreeParameter(param.name)
param_type = param.annotation if param.annotation is not param.empty else float
program_conversion_context.register_parameter(param.name, param_type)
else:
raise NotImplementedError

# Process the program
aq_transpiler.converted_call(f, args, kwargs, options=options)
aq_transpiler.converted_call(f, (), kwargs, options=options)

# Modify program to add global declarations if necessary
_add_qubit_declaration(program_conversion_context)
Expand Down
Loading
Loading