# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You # may not use this file except in compliance with the License. A copy of # the License is located at # # http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. import json from decimal import Decimal from unittest.mock import Mock import numpy as np import pytest from braket.ahs.analog_hamiltonian_simulation import ( AnalogHamiltonianSimulation, AtomArrangement, DiscretizationError, DrivingField, ShiftingField, SiteType, ) from braket.ahs.atom_arrangement import AtomArrangementItem from braket.ahs.field import Field from braket.ahs.pattern import Pattern from braket.ir.ahs.program_v1 import Program from braket.timings.time_series import TimeSeries @pytest.fixture def register(): return ( AtomArrangement() .add((0.0, 0.0)) .add((0.0, 3.0e-6)) .add((0.0, 6.0e-6)) .add((3.0e-6, 0.0)) .add((3.0e-6, 3.0e-6)) .add((3.0e-6, 3.0e-6), SiteType.VACANT) .add((3.0e-6, 6.0e-6), SiteType.VACANT) ) @pytest.fixture def driving_field(): return DrivingField( TimeSeries().put(0.0, 0.0).put(3.0e-7, 2.51327e7).put(2.7e-6, 2.51327e7).put(3.0e-6, 0.0), TimeSeries().put(0.0, 0).put(3.0e-6, 0), TimeSeries() .put(0.0, -1.25664e8) .put(3.0e-7, -1.25664e8) .put(2.7e-6, 1.25664e8) .put(3.0e-6, 1.25664e8), ) @pytest.fixture def shifting_field(): return ShiftingField( Field( TimeSeries().put(0.0, -1.25664e8).put(3.0e-6, 1.25664e8), Pattern([0.5, 1.0, 0.5, 0.5, 0.5, 0.5]), ) ) def test_create(): mock0 = Mock() mock1 = Mock() ahs = AnalogHamiltonianSimulation(register=mock0, hamiltonian=mock1) assert mock0 == ahs.register assert mock1 == ahs.hamiltonian def test_to_ir(register, driving_field, shifting_field): hamiltonian = driving_field + shifting_field ahs = AnalogHamiltonianSimulation(register=register, hamiltonian=hamiltonian) problem = ahs.to_ir() assert Program.parse_raw(problem.json()) == problem assert problem == Program.parse_raw_schema(problem.json()) def test_to_ir_empty(): hamiltonian = Mock() hamiltonian.terms = [] ahs = AnalogHamiltonianSimulation(register=AtomArrangement(), hamiltonian=hamiltonian) problem = ahs.to_ir() assert Program.parse_raw(problem.json()) == problem assert problem == Program.parse_raw_schema(problem.json()) @pytest.mark.xfail(raises=TypeError) def test_to_ir_invalid_hamiltonian(register): hamiltonian = Mock() hamiltonian.terms = [Mock()] ahs = AnalogHamiltonianSimulation(register=register, hamiltonian=hamiltonian) ahs.to_ir() @pytest.mark.xfail(raises=DiscretizationError) def test_invalid_action(): action = Mock() action.actionType = "not-a-valid-AHS-action" device = Mock() device.properties.action = {"braket.ir.ahs.program": action} AnalogHamiltonianSimulation(register=Mock(), hamiltonian=Mock()).discretize(device) @pytest.mark.xfail(raises=DiscretizationError) def test_invalid_action_name(): action = Mock() action.actionType = "braket.ir.ahs.program" device = Mock() device.properties.action = {"not-a-valid-AHS-action": action} AnalogHamiltonianSimulation(register=Mock(), hamiltonian=Mock()).discretize(device) def test_discretize(register, driving_field, shifting_field): hamiltonian = driving_field + shifting_field ahs = AnalogHamiltonianSimulation(register=register, hamiltonian=hamiltonian) action = Mock() action.actionType = "braket.ir.ahs.program" device = Mock() device.properties.action = {"braket.ir.ahs.program": action} device.properties.paradigm.lattice.geometry.positionResolution = Decimal("1E-7") device.properties.paradigm.rydberg.rydbergGlobal.timeResolution = Decimal("1E-9") device.properties.paradigm.rydberg.rydbergGlobal.rabiFrequencyResolution = Decimal("400") device.properties.paradigm.rydberg.rydbergGlobal.detuningResolution = Decimal("0.2") device.properties.paradigm.rydberg.rydbergGlobal.phaseResolution = Decimal("5E-7") device.properties.paradigm.rydberg.rydbergLocal.timeResolution = Decimal("1E-9") device.properties.paradigm.rydberg.rydbergLocal.commonDetuningResolution = Decimal("2000.0") device.properties.paradigm.rydberg.rydbergLocal.localDetuningResolution = Decimal("0.01") discretized_ahs = ahs.discretize(device) discretized_ir = discretized_ahs.to_ir() discretized_json = json.loads(discretized_ir.json()) assert discretized_json["setup"]["ahs_register"] == { "filling": [1, 1, 1, 1, 1, 0, 0], "sites": [ ["0E-7", "0E-7"], ["0E-7", "0.0000030"], ["0E-7", "0.0000060"], ["0.0000030", "0E-7"], ["0.0000030", "0.0000030"], ["0.0000030", "0.0000030"], ["0.0000030", "0.0000060"], ], } assert discretized_json["hamiltonian"]["drivingFields"][0]["amplitude"] == { "pattern": "uniform", "time_series": { "times": ["0E-9", "3.00E-7", "0.000002700", "0.000003000"], "values": ["0", "25132800", "25132800", "0"], }, } assert discretized_json["hamiltonian"]["drivingFields"][0]["phase"] == { "pattern": "uniform", "time_series": {"times": ["0E-9", "0.000003000"], "values": ["0E-7", "0E-7"]}, } assert discretized_json["hamiltonian"]["drivingFields"][0]["detuning"] == { "pattern": "uniform", "time_series": { "times": ["0E-9", "3.00E-7", "0.000002700", "0.000003000"], "values": ["-125664000.0", "-125664000.0", "125664000.0", "125664000.0"], }, } assert discretized_json["hamiltonian"]["shiftingFields"][0]["magnitude"] == { "pattern": ["0.50", "1.00", "0.50", "0.50", "0.50", "0.50"], "time_series": { "times": ["0E-9", "0.000003000"], "values": ["-125664000.0", "125664000.0"], }, } def test_converting_numpy_array_sites_to_ir(driving_field): hamiltonian = driving_field sites = np.array( [ [0.0, 0.0], [0.0, 1.0e-6], [1e-6, 2.0e-6], ] ) register = AtomArrangement() for site in sites: register.add(site) ahs = AnalogHamiltonianSimulation(register=register, hamiltonian=hamiltonian) sites_in_ir = ahs.to_ir().setup.ahs_register.sites expected_sites_in_ir = [ [Decimal("0.0"), Decimal("0.0")], [Decimal("0.0"), Decimal("1e-6")], [Decimal("1e-6"), Decimal("2e-6")], ] assert sites_in_ir == expected_sites_in_ir @pytest.mark.xfail(raises=ValueError) def test_site_validation_wrong_length(): register = AtomArrangement() register.add(np.array([0.0, 1e-6, -1e-6])) @pytest.mark.xfail(raises=TypeError) def test_site_validation_non_number(): register = AtomArrangement() register.add( [ "not-a-number", [ "also-not-a-number", ], ] ) @pytest.mark.xfail(raises=TypeError) def test_site_validation_not_a_tuple(): AtomArrangementItem(None, SiteType.FILLED) @pytest.mark.xfail(raises=ValueError) def test_site_validation_invalid_site_type(): register = AtomArrangement() register.add([0.0, 0.0], "not-a-valid-site-type")