Skip to content

Commit aaa3855

Browse files
authored
Merge branch 'main' into generic
2 parents 4ca33f0 + c13c1c6 commit aaa3855

File tree

10 files changed

+197
-33
lines changed

10 files changed

+197
-33
lines changed

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Changelog
22

3+
## v1.102.9 (2025-10-14)
4+
5+
### Bug Fixes and Other Changes
6+
7+
* local job decorator integ test
8+
* entry point module name for py312 and up
9+
10+
## v1.102.8 (2025-10-13)
11+
12+
### Bug Fixes and Other Changes
13+
14+
* Allow `Measure` instructions in `to_unitary`
15+
* handle executable result with no input in its program
16+
17+
## v1.102.7 (2025-10-13)
18+
19+
### Bug Fixes and Other Changes
20+
21+
* Always include program inputs in from_ir
22+
323
## v1.102.6 (2025-10-09)
424

525
### Bug Fixes and Other Changes

src/braket/_sdk/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
Version number (major.minor.patch[-label])
1616
"""
1717

18-
__version__ = "1.102.7.dev0"
18+
__version__ = "1.102.10.dev0"

src/braket/circuits/unitary_calculation.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
from collections.abc import Iterable
1515

1616
import numpy as np
17-
from braket.default_simulator.linalg_utils import multiply_matrix
17+
from braket.default_simulator.linalg_utils import controlled_matrix, multiply_matrix
1818
from scipy.linalg import fractional_matrix_power
1919

2020
from braket.circuits.compiler_directive import CompilerDirective
2121
from braket.circuits.gate import Gate
2222
from braket.circuits.instruction import Instruction
23+
from braket.circuits.measure import Measure
2324
from braket.registers.qubit_set import QubitSet
2425

2526

@@ -56,25 +57,25 @@ def calculate_unitary_big_endian(
5657
unitary = np.eye(rank, dtype=complex).reshape([2] * 2 * qubit_count)
5758

5859
for instruction in instructions:
59-
if isinstance(instruction.operator, CompilerDirective):
60+
if isinstance(instruction.operator, (CompilerDirective, Measure)):
6061
continue
6162
if not isinstance(instruction.operator, Gate):
6263
raise TypeError("Only Gate operators are supported to build the unitary")
6364

6465
base_gate_matrix = instruction.operator.to_matrix()
65-
if int(instruction.power) == instruction.power:
66-
gate_matrix = np.linalg.matrix_power(base_gate_matrix, int(instruction.power))
67-
else:
68-
gate_matrix = fractional_matrix_power(base_gate_matrix, instruction.power)
6966

70-
gate_matrix = np.asarray(gate_matrix, dtype=complex)
67+
gate_matrix = (
68+
np.linalg.matrix_power(base_gate_matrix, int(instruction.power))
69+
if int(instruction.power) == instruction.power
70+
else fractional_matrix_power(base_gate_matrix, instruction.power)
71+
)
72+
target = tuple(index_substitutions[qubit] for qubit in instruction.target)
73+
control = tuple(index_substitutions[qubit] for qubit in instruction.control)
7174

7275
unitary = multiply_matrix(
7376
unitary,
74-
gate_matrix,
75-
tuple(index_substitutions[qubit] for qubit in instruction.target),
76-
controls=instruction.control,
77-
control_state=instruction.control_state,
77+
controlled_matrix(np.asarray(gate_matrix, dtype=complex), instruction.control_state),
78+
control + target,
7879
)
7980

8081
return unitary.reshape(rank, rank)

src/braket/experimental_capabilities/experimental_capability_context.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from __future__ import annotations
1515

1616
import types
17+
import warnings
1718

1819

1920
class ExperimentalCapabilityContextError(Exception):
@@ -83,6 +84,18 @@ def __enter__(self) -> None:
8384
"""
8485
GLOBAL_EXPERIMENTAL_CAPABILITY_CONTEXT.enable()
8586

87+
warnings.warn(
88+
(
89+
"You are enabling experimental capabilities. To view descriptions and "
90+
"restrictions of experimental capabilities, please review Amazon Braket "
91+
"Developer Guide ("
92+
"https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html"
93+
")."
94+
),
95+
category=UserWarning,
96+
stacklevel=1,
97+
)
98+
8699
def __exit__(
87100
self,
88101
exc_type: type[BaseException] | None,

src/braket/jobs/hybrid_job.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def job_wrapper(*args: Any, **kwargs: Any) -> Callable:
218218
"device": device or "local:none/none",
219219
"source_module": temp_dir,
220220
"entry_point": (
221-
f"{temp_dir}.{entry_point_file_path.stem}:{entry_point.__name__}"
221+
f"{temp_dir_path.name}.{entry_point_file_path.stem}:{entry_point.__name__}"
222222
),
223223
"wait_until_complete": wait_until_complete,
224224
"job_name": job_name or _generate_default_job_name(func=entry_point),

src/braket/tasks/program_set_quantum_task_result.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,11 @@ def _dispatch_executable_result(
299299
result,
300300
program=program.source,
301301
shots=shots_per_executable,
302-
inputs={k: v[result.inputsIndex] for k, v in program.inputs.items()},
302+
inputs=(
303+
{k: v[result.inputsIndex] for k, v in program.inputs.items()}
304+
if program.inputs is not None
305+
else None
306+
),
303307
observable=(
304308
observables[result.inputsIndex % len(observables)] if observables else None
305309
),

test/integ_tests/test_create_local_quantum_job.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
import json
1515
import os
1616
import re
17+
import subprocess
1718
import tempfile
1819
from pathlib import Path
1920

2021
import pytest
2122

23+
from braket.jobs import hybrid_job
2224
from braket.jobs.local import LocalQuantumJob
2325

2426

@@ -152,3 +154,14 @@ def test_failed_local_job(aws_session, capsys):
152154
assert data in log_data
153155
finally:
154156
os.chdir(current_dir)
157+
158+
159+
def test_decorator_local_job_invalid_image():
160+
@hybrid_job(device=None, image_uri="fake", local=True)
161+
def empty_decorator_job():
162+
pass
163+
164+
with pytest.raises(ValueError, match="specify a valid ECR URL"):
165+
# Should successfully get all the way to LocalQuantumJob.create,
166+
# but image pull or docker call will fail due to invalid image URI.
167+
empty_decorator_job()

test/integ_tests/test_reservation_arn.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,18 @@ def test_create_task_via_reservation_arn_on_simulator(reservation_arn):
6161
reason="Python version mismatch",
6262
)
6363
def test_create_job_with_decorator_via_invalid_reservation_arn(reservation_arn):
64-
with pytest.raises(ClientError, match="Reservation arn is invalid"):
65-
66-
@hybrid_job(
67-
device=Devices.IQM.Garnet,
68-
reservation_arn=reservation_arn,
69-
)
70-
def hello_job():
71-
device = AwsDevice(get_job_device_arn())
72-
bell = Circuit().h(0).cnot(0, 1)
73-
task = device.run(bell, shots=10)
74-
measurements = task.result().measurements
75-
return measurements
76-
77-
hello_job()
64+
if AwsDevice(Devices.IQM.Garnet).status == "ONLINE":
65+
with pytest.raises(ClientError, match="Reservation arn is invalid"):
66+
67+
@hybrid_job(
68+
device=Devices.IQM.Garnet,
69+
reservation_arn=reservation_arn,
70+
)
71+
def hello_job():
72+
device = AwsDevice(get_job_device_arn())
73+
bell = Circuit().h(0).cnot(0, 1)
74+
task = device.run(bell, shots=10)
75+
measurements = task.result().measurements
76+
return measurements
77+
78+
hello_job()

test/unit_tests/braket/circuits/test_circuit.py

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2482,6 +2482,7 @@ def test_to_unitary_with_global_phase():
24822482
(Circuit().h(0).add_result_type(ResultType.Probability(target=[0])), gates.H().to_matrix()),
24832483
(Circuit().h(1), gates.H().to_matrix()),
24842484
(Circuit().h(2), gates.H().to_matrix()),
2485+
(Circuit().h(2).measure(2), gates.H().to_matrix()),
24852486
(Circuit().x(0), gates.X().to_matrix()),
24862487
(Circuit().y(0), gates.Y().to_matrix()),
24872488
(Circuit().z(0), gates.Z().to_matrix()),
@@ -2500,6 +2501,7 @@ def test_to_unitary_with_global_phase():
25002501
(Circuit().cnot(0, 1), gates.CNot().to_matrix()),
25012502
(Circuit().cnot(0, 1).add_result_type(ResultType.StateVector()), gates.CNot().to_matrix()),
25022503
(Circuit().cnot(2, 4), gates.CNot().to_matrix()),
2504+
(Circuit().cnot(2, 4).measure([2, 4]), gates.CNot().to_matrix()),
25032505
(Circuit().swap(0, 1), gates.Swap().to_matrix()),
25042506
(Circuit().swap(1, 0), gates.Swap().to_matrix()),
25052507
(Circuit().iswap(0, 1), gates.ISwap().to_matrix()),
@@ -2592,7 +2594,7 @@ def test_to_unitary_with_global_phase():
25922594
),
25932595
),
25942596
(
2595-
Circuit().x(0, control=1),
2597+
Circuit().x(3, control=7),
25962598
np.array(
25972599
[
25982600
[1.0, 0.0, 0.0, 0.0],
@@ -2628,7 +2630,7 @@ def test_to_unitary_with_global_phase():
26282630
),
26292631
),
26302632
(
2631-
Circuit().ccnot(1, 2, 0),
2633+
Circuit().ccnot(3, 6, 1),
26322634
np.array(
26332635
[
26342636
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
@@ -2644,7 +2646,7 @@ def test_to_unitary_with_global_phase():
26442646
),
26452647
),
26462648
(
2647-
Circuit().ccnot(2, 1, 0),
2649+
Circuit().ccnot(6, 3, 1),
26482650
np.array(
26492651
[
26502652
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
@@ -2660,7 +2662,7 @@ def test_to_unitary_with_global_phase():
26602662
),
26612663
),
26622664
(
2663-
Circuit().ccnot(0, 2, 1),
2665+
Circuit().ccnot(1, 6, 3),
26642666
np.array(
26652667
[
26662668
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
@@ -2676,7 +2678,7 @@ def test_to_unitary_with_global_phase():
26762678
),
26772679
),
26782680
(
2679-
Circuit().ccnot(2, 0, 1),
2681+
Circuit().ccnot(6, 1, 3),
26802682
np.array(
26812683
[
26822684
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
@@ -2691,6 +2693,102 @@ def test_to_unitary_with_global_phase():
26912693
dtype=complex,
26922694
),
26932695
),
2696+
(
2697+
Circuit().cnot([1, 6], 3),
2698+
np.array(
2699+
[
2700+
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2701+
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2702+
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2703+
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
2704+
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
2705+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
2706+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
2707+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
2708+
],
2709+
dtype=complex,
2710+
),
2711+
),
2712+
(
2713+
Circuit().cnot([6, 1], 3),
2714+
np.array(
2715+
[
2716+
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2717+
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2718+
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2719+
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
2720+
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
2721+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
2722+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
2723+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
2724+
],
2725+
dtype=complex,
2726+
),
2727+
),
2728+
(
2729+
Circuit().x(3, control=[6, 1]),
2730+
np.array(
2731+
[
2732+
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2733+
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2734+
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2735+
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
2736+
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
2737+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
2738+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
2739+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
2740+
],
2741+
dtype=complex,
2742+
),
2743+
),
2744+
(
2745+
Circuit().x(3, control=[1, 6]),
2746+
np.array(
2747+
[
2748+
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2749+
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2750+
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2751+
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
2752+
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
2753+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
2754+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
2755+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
2756+
],
2757+
dtype=complex,
2758+
),
2759+
),
2760+
(
2761+
Circuit().i(3).cnot(6, 1),
2762+
np.array(
2763+
[
2764+
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2765+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
2766+
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2767+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
2768+
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
2769+
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2770+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
2771+
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
2772+
],
2773+
dtype=complex,
2774+
),
2775+
),
2776+
(
2777+
Circuit().i(3).x(1, control=[6]),
2778+
np.array(
2779+
[
2780+
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2781+
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
2782+
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2783+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
2784+
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
2785+
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
2786+
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
2787+
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
2788+
],
2789+
dtype=complex,
2790+
),
2791+
),
26942792
(
26952793
Circuit().s(0).v(1).cnot(0, 1).cnot(2, 1),
26962794
np.dot(

test/unit_tests/braket/tasks/test_program_set_quantum_task_result.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,3 +423,17 @@ def test_results_missing(metadata, execution_results_missing, program):
423423
ProgramSetQuantumTaskResult.from_object(
424424
BraketSchemaBase.parse_raw_schema(json.dumps(result))
425425
)
426+
427+
428+
def test_dispatch_executable_result_with_none_inputs(execution_measurement_probabilities):
429+
mock_program = Mock()
430+
mock_program.source = "OPENQASM 3.0;\nbit[2] b;\nqubit[2] q;\nh q[0];\ncnot q[0], q[1];\nb[0] = measure q[0];\nb[1] = measure q[1];"
431+
mock_program.inputs = None
432+
result = BraketSchemaBase.parse_raw_schema(json.dumps(execution_measurement_probabilities))
433+
434+
measured_entry = CompositeEntry._dispatch_executable_result(
435+
result=result, program=mock_program, observables=None, shots_per_executable=40
436+
)
437+
assert isinstance(measured_entry, MeasuredEntry)
438+
assert measured_entry.inputs is None
439+
assert measured_entry.probabilities == {"00": 0.7, "11": 0.3}

0 commit comments

Comments
 (0)