diff --git a/src/braket/ahs/analog_hamiltonian_simulation.py b/src/braket/ahs/analog_hamiltonian_simulation.py index af02471e2..e6deca170 100644 --- a/src/braket/ahs/analog_hamiltonian_simulation.py +++ b/src/braket/ahs/analog_hamiltonian_simulation.py @@ -23,6 +23,9 @@ from braket.ahs.hamiltonian import Hamiltonian from braket.ahs.local_detuning import LocalDetuning from braket.device_schema import DeviceActionType +from braket.ahs.field import Field +from braket.ahs.pattern import Pattern +from braket.timings.time_series import TimeSeries class AnalogHamiltonianSimulation: @@ -39,6 +42,16 @@ def __init__(self, register: AtomArrangement, hamiltonian: Hamiltonian) -> None: self._register = register self._hamiltonian = hamiltonian + def __eq__(self, other: AnalogHamiltonianSimulation): + if isinstance(other, AnalogHamiltonianSimulation): + for item1, item2 in zip(self.register, other.register): + coordinate1 = (float(item1.coordinate[0]), float(item1.coordinate[1])) + coordinate2 = (float(item2.coordinate[0]), float(item2.coordinate[1])) + if coordinate1 != coordinate2: + return False + return True + return NotImplemented + @property def register(self) -> AtomArrangement: """AtomArrangement: The initial atom arrangement for the simulation.""" @@ -77,6 +90,91 @@ def _hamiltonian_to_ir(self) -> ir.Hamiltonian: localDetuning=terms[AnalogHamiltonianSimulation.LOCAL_DETUNING_PROPERTY], ) + @staticmethod + def from_ir(source: ir.Program) -> AnalogHamiltonianSimulation: + """Converts the canonical intermediate representation into the AnalogHamiltonianSimulation + object. + Args: + source (ir.Program): Program object. + + Returns: + AnalogHamiltonianSimulation: Braket AnalogHamiltonianSimulation implementing the Program object. + """ + return AnalogHamiltonianSimulation( + register=AnalogHamiltonianSimulation._register_from_ir(source), + hamiltonian=AnalogHamiltonianSimulation._hamiltonian_from_ir(source) + ) + + def _register_from_ir(source: ir.Program) -> AtomArrangement: + atom_arr = AtomArrangement() + for site, fill in zip(source.setup.ahs_register.sites, source.setup.ahs_register.filling): + atom_arr.add( + coordinate=site, + site_type=SiteType.FILLED if fill == 1 else SiteType.VACANT + ) + return atom_arr + + def _hamiltonian_from_ir(source: ir.program) -> Hamiltonian: + hamiltonian = Hamiltonian() + for term in source.hamiltonian.drivingFields: + amplitude = ( + Field( + time_series=TimeSeries.from_lists( + term.amplitude.time_series.times, + term.amplitude.time_series.values + ), + pattern=term.amplitude.pattern, + ) + if term.amplitude.pattern != "uniform" + else TimeSeries.from_lists( + term.amplitude.time_series.times, + term.amplitude.time_series.values + ) + ) + phase = ( + Field( + time_series=TimeSeries.from_lists( + term.phase.time_series.times, + term.phase.time_series.values + ), + pattern=term.phase.pattern, + ) + if term.phase.pattern != "uniform" + else TimeSeries.from_lists( + term.phase.time_series.times, + term.phase.time_series.values + ) + ) + detuning = ( + Field( + time_series=TimeSeries.from_lists( + term.detuning.time_series.times, + term.detuning.time_series.values + ), + pattern=term.detuning.pattern, + ) + if term.detuning.pattern != "uniform" + else TimeSeries.from_lists( + term.detuning.time_series.times, + term.detuning.time_series.values + ) + ) + hamiltonian += DrivingField( + amplitude=amplitude, + phase=phase, + detuning=detuning, + ) + for term in source.hamiltonian.localDetuning: + magnitude = Field( + time_series=TimeSeries.from_lists( + times=term.magnitude.time_series.times, + values=term.magnitude.time_series.values, + ), + pattern=Pattern(term.magnitude.pattern), + ) + hamiltonian += LocalDetuning(magnitude=magnitude,) + return hamiltonian + def discretize(self, device: AwsDevice) -> AnalogHamiltonianSimulation: # noqa """Creates a new AnalogHamiltonianSimulation with all numerical values represented as Decimal objects with fixed precision based on the capabilities of the device. diff --git a/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py b/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py index 83178c120..dba782407 100644 --- a/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py +++ b/test/unit_tests/braket/ahs/test_analog_hamiltonian_simulation.py @@ -103,6 +103,21 @@ def test_to_ir_invalid_hamiltonian(register): ahs.to_ir() +def test_from_ir(register, driving_field, local_detuning): + hamiltonian = driving_field + local_detuning + ahs = AnalogHamiltonianSimulation(register=register, hamiltonian=hamiltonian) + problem = json.loads(ahs.to_ir().json()) + assert ahs == AnalogHamiltonianSimulation.from_ir(Program(setup=problem['setup'], hamiltonian=problem['hamiltonian'])) + + +def test_from_ir_empty(): + hamiltonian = Mock() + hamiltonian.terms = [] + ahs = AnalogHamiltonianSimulation(register=AtomArrangement(), hamiltonian=hamiltonian) + problem = json.loads(ahs.to_ir().json()) + assert ahs == AnalogHamiltonianSimulation.from_ir(Program(setup=problem['setup'], hamiltonian=problem['hamiltonian'])) + + @pytest.mark.xfail(raises=DiscretizationError) def test_invalid_action(): action = Mock()