Skip to content

Commit

Permalink
Merge branch 'main' into pr_title
Browse files Browse the repository at this point in the history
  • Loading branch information
AbeCoull authored Jun 19, 2024
2 parents 5a598e5 + 90f9395 commit ad7ae96
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 27 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## v1.81.1 (2024-06-17)

### Bug Fixes and Other Changes

* Error when FreeParameters are named QASM types

## v1.81.0 (2024-06-13)

### Features

* Add IQM to get compiled program convenience method

## v1.80.1 (2024-06-10)

### Bug Fixes and Other Changes

* docs: add stack exchange badge to the readme
* Implement `braket.ahs.AnalogHamiltonianSimulation.from_ir()`

## v1.80.0 (2024-05-22)

### Features
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[![Build status](https://github.com/amazon-braket/amazon-braket-sdk-python/actions/workflows/python-package.yml/badge.svg?branch=main)](https://github.com/amazon-braket/amazon-braket-sdk-python/actions/workflows/python-package.yml)
[![codecov](https://codecov.io/gh/amazon-braket/amazon-braket-sdk-python/branch/main/graph/badge.svg?token=1lsqkZL3Ll)](https://codecov.io/gh/amazon-braket/amazon-braket-sdk-python)
[![Documentation Status](https://img.shields.io/readthedocs/amazon-braket-sdk-python.svg?logo=read-the-docs)](https://amazon-braket-sdk-python.readthedocs.io/en/latest/?badge=latest)
[![Stack Overflow](https://img.shields.io/badge/StackExchange-Ask%20questions-blue?logo=stackexchange)](https://quantumcomputing.stackexchange.com/questions/tagged/amazon-braket)

The Amazon Braket Python SDK is an open source library that provides a framework that you can use to interact with quantum computing hardware devices through Amazon Braket.

Expand Down
2 changes: 1 addition & 1 deletion src/braket/_sdk/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
Version number (major.minor.patch[-label])
"""

__version__ = "1.80.1.dev0"
__version__ = "1.81.2.dev0"
73 changes: 73 additions & 0 deletions src/braket/parametric/free_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,69 @@

from braket.parametric.free_parameter_expression import FreeParameterExpression

PREDEFINED_VARIABLE_NAMES = {"b", "q"}

# The reserved words are picked from below
# https://github.com/openqasm/openqasm/blob/main/source/grammar/qasm3Lexer.g4
# https://github.com/openqasm/openpulse-python/blob/main/source/grammar/openpulseLexer.g4
QASM_RESERVED_WORDS = {
"OPENQASM",
"include",
"defcalgrammar",
"def",
"cal",
"defcal",
"gate",
"extern",
"box",
"let",
"break",
"continue",
"if",
"else",
"end",
"return",
"for",
"while",
"in",
"pragma",
"input",
"output",
"const",
"readonly",
"mutable",
"qreg",
"qubit",
"creg",
"bool",
"bit",
"int",
"uint",
"float",
"angle",
"complex",
"array",
"void",
"duration",
"stretch",
"gphase",
"inv",
"pow",
"ctrl",
"negctrl",
"dim",
"durationof",
"delay",
"reset",
"measure",
"barrier",
"true",
"false",
"waveform",
"port",
"frame",
}


class FreeParameter(FreeParameterExpression):
"""Class 'FreeParameter'
Expand Down Expand Up @@ -94,6 +157,16 @@ def _set_name(self, name: str) -> None:
raise TypeError("FreeParameter names must be strings")
if not name[0].isalpha() and name[0] != "_":
raise ValueError("FreeParameter names must start with a letter or an underscore")
if name in PREDEFINED_VARIABLE_NAMES:
raise ValueError(
f"FreeParameter names must not be one of the Braket reserved variable names: "
f"{PREDEFINED_VARIABLE_NAMES}."
)
if name in QASM_RESERVED_WORDS:
raise ValueError(
f"FreeParameter names must not be one of the OpenQASM or OpenPulse keywords: "
f"{QASM_RESERVED_WORDS}."
)
self._name = Symbol(name)

def to_dict(self) -> dict:
Expand Down
2 changes: 2 additions & 0 deletions src/braket/tasks/gate_model_quantum_task_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ def get_compiled_circuit(self) -> Optional[str]:
return metadata.rigettiMetadata.compiledProgram
elif metadata.oqcMetadata:
return metadata.oqcMetadata.compiledProgram
elif metadata.iqmMetadata:
return metadata.iqmMetadata.compiledProgram
else:
return None

Expand Down
8 changes: 4 additions & 4 deletions test/unit_tests/braket/circuits/test_ascii_circuit_diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,19 +741,19 @@ def test_noise_multi_probabilities():

def test_noise_multi_probabilities_with_parameter():
a = FreeParameter("a")
b = FreeParameter("b")
c = FreeParameter("c")
circ = Circuit().h(0).x(1).pauli_channel(1, a, b, c)
d = FreeParameter("d")
circ = Circuit().h(0).x(1).pauli_channel(1, a, c, d)
expected = (
"T : | 0 |",
" ",
"q0 : -H-----------",
" ",
"q1 : -X-PC(a,b,c)-",
"q1 : -X-PC(a,c,d)-",
"",
"T : | 0 |",
"",
"Unassigned parameters: [a, b, c].",
"Unassigned parameters: [a, c, d].",
)
_assert_correct_diagram(circ, expected)

Expand Down
8 changes: 4 additions & 4 deletions test/unit_tests/braket/circuits/test_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -1069,8 +1069,8 @@ def test_bind_values_pulse_gate():
frame = Frame("user_frame", Port("device_port_x", 1e-9), 1e9)
gate = Gate.PulseGate(
PulseSequence()
.set_frequency(frame, FreeParameter("a") + FreeParameter("b"))
.delay(frame, FreeParameter("c")),
.set_frequency(frame, FreeParameter("a") + FreeParameter("c"))
.delay(frame, FreeParameter("d")),
qubit_count,
)

Expand All @@ -1084,8 +1084,8 @@ def to_ir(pulse_gate):
assert a_bound_ir == "\n".join(
[
"cal {",
" set_frequency(user_frame, 3.0 + b);",
" delay[c * 1s] user_frame;",
" set_frequency(user_frame, 3.0 + c);",
" delay[d * 1s] user_frame;",
"}",
]
)
Expand Down
4 changes: 2 additions & 2 deletions test/unit_tests/braket/circuits/test_noises.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,10 @@ def test_parameter_binding(parameterized_noise, params, expected_noise):


def test_parameterized_noise():
noise = Noise.PauliChannel(FreeParameter("a"), 0.2, FreeParameter("b"))
noise = Noise.PauliChannel(FreeParameter("a"), 0.2, FreeParameter("d"))
assert noise.probX == FreeParameter("a")
assert noise.probY == 0.2
assert noise.probZ == FreeParameter("b")
assert noise.probZ == FreeParameter("d")


# Additional Unitary noise tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -853,20 +853,20 @@ def test_noise_multi_probabilities():

def test_noise_multi_probabilities_with_parameter():
a = FreeParameter("a")
b = FreeParameter("b")
c = FreeParameter("c")
circ = Circuit().h(0).x(1).pauli_channel(1, a, b, c)
d = FreeParameter("d")
circ = Circuit().h(0).x(1).pauli_channel(1, a, c, d)
expected = (
"T : │ 0 │",
" ┌───┐ ",
"q0 : ─┤ H ├───────────────",
" └───┘ ",
" ┌───┐ ┌───────────┐ ",
"q1 : ─┤ X ├─┤ PC(a,b,c) ├─",
"q1 : ─┤ X ├─┤ PC(a,c,d) ├─",
" └───┘ └───────────┘ ",
"T : │ 0 │",
"",
"Unassigned parameters: [a, b, c].",
"Unassigned parameters: [a, c, d].",
)
_assert_correct_diagram(circ, expected)

Expand Down
18 changes: 18 additions & 0 deletions test/unit_tests/braket/parametric/test_free_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,21 @@ def test_sub_successful(free_parameter):

def test_sub_wrong_param(free_parameter):
assert free_parameter.subs({"alpha": 1}) == FreeParameter("theta")


@pytest.mark.parametrize("param_name", ["for", "qubit"])
def test_error_raised_when_reserved_keyword_used(param_name):
with pytest.raises(
ValueError,
match="FreeParameter names must not be one of the OpenQASM or OpenPulse keywords: ",
):
FreeParameter(param_name)


@pytest.mark.parametrize("param_name", ["b", "q"])
def test_error_raised_when_predefined_variable_used(param_name):
with pytest.raises(
ValueError,
match="FreeParameter names must not be one of the Braket reserved variable names: ",
):
FreeParameter(param_name)
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def test_sub_return_expression():
@pytest.mark.parametrize(
"param, kwargs, expected_value, expected_type",
[
(FreeParameter("a") + 2 * FreeParameter("b"), {"a": 0.1, "b": 0.3}, 0.7, float),
(FreeParameter("a") + 2 * FreeParameter("d"), {"a": 0.1, "d": 0.3}, 0.7, float),
(FreeParameter("x"), {"y": 1}, FreeParameter("x"), FreeParameter),
(FreeParameter("y"), {"y": -0.1}, -0.1, float),
(2 * FreeParameter("i"), {"i": 1}, 2.0, float),
Expand Down
22 changes: 11 additions & 11 deletions test/unit_tests/braket/pulse/test_pulse_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def test_pulse_sequence_with_user_defined_frame(user_defined_frame):


def test_pulse_sequence_make_bound_pulse_sequence(predefined_frame_1, predefined_frame_2):
param = FreeParameter("a") + 2 * FreeParameter("b")
param = FreeParameter("a") + 2 * FreeParameter("c")
pulse_sequence = (
PulseSequence()
.set_frequency(predefined_frame_1, param)
Expand Down Expand Up @@ -135,14 +135,14 @@ def test_pulse_sequence_make_bound_pulse_sequence(predefined_frame_1, predefined
" sigma_dg * 1s, 0.2, 1, false);",
" waveform constant_wf = constant(length_c * 1s, 2.0 + 0.3im);",
" waveform arb_wf = {1.0 + 0.4im, 0, 0.3, 0.1 + 0.2im};",
" set_frequency(predefined_frame_1, a + 2.0 * b);",
" shift_frequency(predefined_frame_1, a + 2.0 * b);",
" set_phase(predefined_frame_1, a + 2.0 * b);",
" shift_phase(predefined_frame_1, -1.0 * a + -2.0 * b);",
" set_scale(predefined_frame_1, a + 2.0 * b);",
" set_frequency(predefined_frame_1, a + 2.0 * c);",
" shift_frequency(predefined_frame_1, a + 2.0 * c);",
" set_phase(predefined_frame_1, a + 2.0 * c);",
" shift_phase(predefined_frame_1, -1.0 * a + -2.0 * c);",
" set_scale(predefined_frame_1, a + 2.0 * c);",
" psb[0] = capture_v0(predefined_frame_1);",
" delay[(a + 2.0 * b) * 1s] predefined_frame_1, predefined_frame_2;",
" delay[(a + 2.0 * b) * 1s] predefined_frame_1;",
" delay[(a + 2.0 * c) * 1s] predefined_frame_1, predefined_frame_2;",
" delay[(a + 2.0 * c) * 1s] predefined_frame_1;",
" delay[1.0ms] predefined_frame_1;",
" barrier predefined_frame_1, predefined_frame_2;",
" play(predefined_frame_1, gauss_wf);",
Expand All @@ -156,17 +156,17 @@ def test_pulse_sequence_make_bound_pulse_sequence(predefined_frame_1, predefined
assert pulse_sequence.to_ir() == expected_str_unbound
assert pulse_sequence.parameters == {
FreeParameter("a"),
FreeParameter("b"),
FreeParameter("c"),
FreeParameter("length_g"),
FreeParameter("length_dg"),
FreeParameter("sigma_g"),
FreeParameter("sigma_dg"),
FreeParameter("length_c"),
}
b_bound = pulse_sequence.make_bound_pulse_sequence(
{"b": 2, "length_g": 1e-3, "length_dg": 3e-3, "sigma_dg": 0.4, "length_c": 4e-3}
{"c": 2, "length_g": 1e-3, "length_dg": 3e-3, "sigma_dg": 0.4, "length_c": 4e-3}
)
b_bound_call = pulse_sequence(b=2, length_g=1e-3, length_dg=3e-3, sigma_dg=0.4, length_c=4e-3)
b_bound_call = pulse_sequence(c=2, length_g=1e-3, length_dg=3e-3, sigma_dg=0.4, length_c=4e-3)
expected_str_b_bound = "\n".join(
[
"OPENQASM 3.0;",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ResultTypeValue,
TaskMetadata,
)
from braket.task_result.iqm_metadata_v1 import IqmMetadata
from braket.task_result.oqc_metadata_v1 import OqcMetadata
from braket.task_result.rigetti_metadata_v1 import RigettiMetadata
from braket.tasks import GateModelQuantumTaskResult
Expand Down Expand Up @@ -103,6 +104,22 @@ def additional_metadata_rigetti(quil_program):
return AdditionalMetadata(action=program, rigettiMetadata=rigetti_metadata)


@pytest.fixture
def additional_metadata_iqm():
source = """
OPENQASM 3.0;
bit[2] b;
h $0;
cnot $0, $7;
b[0] = measure $0;
b[1] = measure $7;
"""
program = openqasm.Program(source=source)
iqm_metadata = IqmMetadata(compiledProgram=source)

return AdditionalMetadata(action=program, iqmMetadata=iqm_metadata)


@pytest.fixture
def qasm2_program():
return """
Expand Down Expand Up @@ -160,6 +177,13 @@ def result_oqc(result_obj_1, additional_metadata_oqc):
return result


@pytest.fixture
def result_iqm(result_obj_1, additional_metadata_iqm):
result = GateModelQuantumTaskResult.from_object(result_obj_1)
result.additional_metadata = additional_metadata_iqm
return result


@pytest.fixture
def result_str_1(result_obj_1):
return result_obj_1.json()
Expand Down Expand Up @@ -323,6 +347,11 @@ def test_get_compiled_circuit_oqc(result_oqc, qasm2_program):
assert result_oqc.get_compiled_circuit() == qasm2_program


def test_get_compiled_circuit_iqm(result_iqm):
"""Test get_compiled_circuit method."""
assert result_iqm.get_compiled_circuit() == result_iqm.additional_metadata.action.source


def test_get_compiled_circuit_no_qhp_metadata(result_obj_1):
"""Test get_compiled_circuit method."""
result = GateModelQuantumTaskResult.from_object(result_obj_1)
Expand Down

0 comments on commit ad7ae96

Please sign in to comment.