안녕하세요 AHS: 첫 아날로그 해밀턴 시뮬레이션을 실행해 보세요. - Amazon Braket

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

안녕하세요 AHS: 첫 아날로그 해밀턴 시뮬레이션을 실행해 보세요.

AHS

아날로그 해밀턴 시뮬레이션 (AHS) 은 양자 회로와는 다른 양자 컴퓨팅의 패러다임입니다. 각 게이트가 한 번에 몇 큐비트에서만 작동하는 일련의 게이트 대신 해당 해밀턴의 시간 및 공간 종속 매개변수로 AHS 프로그램을 정의합니다. 시스템의 해밀턴 방식은 시스템의 에너지 준위와 외부 힘의 영향을 암호화하며, 외부 힘은 모두 해당 상태의 시간 변화를 제어합니다. N-큐비트 시스템의 경우 해밀턴은 복소수로 구성된 2N X2 N 정사각형 행렬로 표현할 수 있습니다.

AHS를 수행할 수 있는 양자 장치는 매개 변수 (예: 일관된 구동장의 진폭 및 디튜닝) 를 조정하여 사용자 지정 해밀턴식 양자 시스템의 시간 변화를 근사화합니다. AHS 패러다임은 상호 작용하는 여러 입자의 양자 시스템의 정적 및 동적 특성을 시뮬레이션하는 데 적합합니다. 의 Aquila 디바이스와 같이 특수 목적으로 설계된 QPU는 기존 하드웨어로는 구현할 QuEra 수 없는 크기의 시스템의 시간 변화를 시뮬레이션할 수 있습니다.

상호 작용하는 스핀 체인

상호 작용하는 여러 입자로 구성된 시스템의 표준 예를 들어 8개의 스핀으로 이루어진 고리 (각각 “업” ↑‡와 “down” ↓† 상태일 수 있음) 를 생각해 보겠습니다. 비록 작지만 이 모델 시스템은 이미 자연 발생 자성 물질의 흥미로운 현상을 몇 가지 보여주고 있습니다. 이 예제에서는 연속적인 스핀이 반대 방향을 가리키는 이른바 반강자성 오더를 만드는 방법을 보여줍니다.

위쪽 및 아래쪽 역방향 화살표가 포함된 8개의 원 노드를 연결하는 다이어그램.

배열

회전할 때마다 하나의 중성 원자를 사용할 것이고, “업” 및 “다운” 스핀 상태는 각각 원자의 들뜬 리드버그 상태와 그라운드 상태로 인코딩될 것입니다. 먼저 2차원 배열을 만듭니다. 다음 코드를 사용하여 위의 스핀 링을 프로그래밍할 수 있습니다.

전제 조건: Braket SDK를 pip 설치해야 합니다. (Braket 호스팅 노트북 인스턴스를 사용하는 경우 이 SDK는 노트북과 함께 사전 설치되어 제공됩니다.) 플롯을 재현하려면 셸 명령어를 사용하여 matplotlib를 별도로 설치해야 합니다. pip install matplotlib

import numpy as np import matplotlib.pyplot as plt # required for plotting from braket.ahs.atom_arrangement import AtomArrangement a = 5.7e-6 # nearest-neighbor separation (in meters) register = AtomArrangement() register.add(np.array([0.5, 0.5 + 1/np.sqrt(2)]) * a) register.add(np.array([0.5 + 1/np.sqrt(2), 0.5]) * a) register.add(np.array([0.5 + 1/np.sqrt(2), - 0.5]) * a) register.add(np.array([0.5, - 0.5 - 1/np.sqrt(2)]) * a) register.add(np.array([-0.5, - 0.5 - 1/np.sqrt(2)]) * a) register.add(np.array([-0.5 - 1/np.sqrt(2), - 0.5]) * a) register.add(np.array([-0.5 - 1/np.sqrt(2), 0.5]) * a) register.add(np.array([-0.5, 0.5 + 1/np.sqrt(2)]) * a)

다음과 같이 플롯할 수도 있습니다.

fig, ax = plt.subplots(1, 1, figsize=(7,7)) xs, ys = [register.coordinate_list(dim) for dim in (0, 1)] ax.plot(xs, ys, 'r.', ms=15) for idx, (x, y) in enumerate(zip(xs, ys)): ax.text(x, y, f" {idx}", fontsize=12) plt.show() # this will show the plot below in an ipython or jupyter session
양 축의 양수 값과 음수 값에 분포된 점을 보여주는 스캐터 차트.

상호 작용

반강자성 단계를 준비하려면 인접 스핀 간의 상호 작용을 유도해야 합니다. 이를 위해 반 데르 발스 상호작용을 사용하는데, 이는 기본적으로 중성 원자 장치 (예: 의 장치) 에 의해 구현됩니다. Aquila QuEra 스핀 표현을 사용하면 이 상호작용에 대한 해밀턴 항을 모든 스핀 쌍 (j, k) 에 대한 합으로 표현할 수 있습니다.

이 교호작용을 모든 스핀 쌍 (j, k) 에 대한 합으로 표현한 해밀턴 교호작용 방정식입니다.

여기서 nj=↑ ‡↑ j 는 스핀 j가 “up” 상태인 경우에만 값 1을 취하고, 그렇지 않으면 0을 취하는 연산자입니다. j 강도는 V j,k =C6/(dj,k​) 6입니다. 여기서 C는 고정 계수이고 6 d는 스핀 j와 k 사이의 유클리드 j,k 거리입니다. 이 교호작용 항의 즉각적인 효과는 스핀 j와 스핀 k가 모두 “업”인 모든 상태에서는 에너지가 (V만큼) 상승한다는 것입니다. j,k AHS 프로그램의 나머지 부분을 신중하게 설계함으로써 이 상호 작용은 인접한 스핀이 모두 “업” 상태에 있는 것을 방지할 수 있으며, 이러한 효과를 일반적으로 “리드버그 봉쇄”라고 합니다.

드라이빙 필드

AHS 프로그램이 시작될 때 모든 스핀은 (기본적으로) “다운” 상태에서 시작되며, 소위 강자성 단계에 있습니다. 반강자성 위상을 준비한다는 목표를 염두에 두고 스핀을 이 상태에서 “상승” 상태가 선호되는 다물체 상태로 부드럽게 전환하는 시간 종속 일관된 구동 필드를 지정합니다. 해당하는 해밀턴식은 다음과 같이 쓸 수 있습니다.

해밀턴 구동 함수의 계산을 나타내는 수학 방정식.

여기서 Ω (t), (t), Δ (t) 는 모든 스핀에 균일하게 영향을 미치는 구동 필드의 시간 종속 글로벌 진폭 (일명 Rabi 주파수), 위상 및 디튜닝입니다. 여기서 S −,k =↓ k​ §↑ k 와 S +,k =( S−,k) =↑ k​ ‡↓↓ k 는 각각 스핀 k의 하강 연산자와 상승 연산자이고 n k =↑ k k ‡↑는 이전과 동일한 연산자입니다. 주행장의 Ω 부분은 모든 스핀의 “다운” 상태와 “업” 상태를 동시에 일관되게 연결하는 반면 Δ 부분은 “업” 상태에 대한 에너지 보상을 제어합니다.

강자성 위상에서 반강자성 위상으로의 원활한 전환을 프로그래밍하기 위해 다음 코드를 사용하여 구동 필드를 지정합니다.

from braket.timings.time_series import TimeSeries from braket.ahs.driving_field import DrivingField # smooth transition from "down" to "up" state time_max = 4e-6 # seconds time_ramp = 1e-7 # seconds omega_max = 6300000.0 # rad / sec delta_start = -5 * omega_max delta_end = 5 * omega_max omega = TimeSeries() omega.put(0.0, 0.0) omega.put(time_ramp, omega_max) omega.put(time_max - time_ramp, omega_max) omega.put(time_max, 0.0) delta = TimeSeries() delta.put(0.0, delta_start) delta.put(time_ramp, delta_start) delta.put(time_max - time_ramp, delta_end) delta.put(time_max, delta_end) phi = TimeSeries().put(0.0, 0.0).put(time_max, 0.0) drive = DrivingField( amplitude=omega, phase=phi, detuning=delta )

다음 스크립트를 사용하여 구동장의 시계열을 시각화할 수 있습니다.

fig, axes = plt.subplots(3, 1, figsize=(12, 7), sharex=True) ax = axes[0] time_series = drive.amplitude.time_series ax.plot(time_series.times(), time_series.values(), '.-'); ax.grid() ax.set_ylabel('Omega [rad/s]') ax = axes[1] time_series = drive.detuning.time_series ax.plot(time_series.times(), time_series.values(), '.-'); ax.grid() ax.set_ylabel('Delta [rad/s]') ax = axes[2] time_series = drive.phase.time_series # Note: time series of phase is understood as a piecewise constant function ax.step(time_series.times(), time_series.values(), '.-', where='post'); ax.set_ylabel('phi [rad]') ax.grid() ax.set_xlabel('time [s]') plt.show() # this will show the plot below in an ipython or jupyter session
시간 경과에 따른 파이, 델타, 오메가를 보여주는 세 개의 그래프. 위쪽 서브플롯은 6rads/s를 약간 상회하는 성장률을 보여 주며, 다시 0으로 떨어질 때까지 4초 동안 유지됩니다. 가운데 서브플롯은 도함수의 관련 선형 성장을 나타내고 아래쪽 서브플롯은 0에 가까운 평평한 선을 나타냅니다.

AHS 프로그램

레지스터, 드라이빙 필드 (및 암시적 반 데르 발스 상호작용) 는 아날로그 해밀턴 시뮬레이션 프로그램을 구성합니다. ahs_program

from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation ahs_program = AnalogHamiltonianSimulation( register=register, hamiltonian=drive )

로컬 시뮬레이터에서 실행

이 예제는 크기가 작기 때문에 (15회전 미만) AHS 호환 QPU에서 실행하기 전에 Braket SDK와 함께 제공되는 로컬 AHS 시뮬레이터에서 실행할 수 있습니다. 로컬 시뮬레이터는 Braket SDK와 함께 무료로 제공되므로 코드를 올바르게 실행할 수 있도록 하는 것이 가장 좋습니다.

여기서는 샷 수를 높은 값 (예: 100만 개) 으로 설정할 수 있습니다. 로컬 시뮬레이터가 양자 상태의 시간 변화를 추적하고 최종 상태에서 샘플을 추출하기 때문에 샷 수는 늘리고 총 런타임은 약간만 늘리기 때문입니다.

from braket.devices import LocalSimulator device = LocalSimulator("braket_ahs") result_simulator = device.run( ahs_program, shots=1_000_000 ).result() # takes about 5 seconds

시뮬레이터 결과 분석

다음 함수를 사용하여 각 스핀의 상태 (“다운”의 경우 “d”, “업”의 경우 “u”, 빈 사이트의 경우 “e”일 수 있음) 를 유추하고 전체 샷에서 각 구성이 발생한 횟수를 계산하는 다음 함수를 사용하여 샷 결과를 집계할 수 있습니다.

from collections import Counter def get_counts(result): """Aggregate state counts from AHS shot results A count of strings (of length = # of spins) are returned, where each character denotes the state of a spin (site): e: empty site u: up state spin d: down state spin Args: result (braket.tasks.analog_hamiltonian_simulation_quantum_task_result.AnalogHamiltonianSimulationQuantumTaskResult) Returns dict: number of times each state configuration is measured """ state_counts = Counter() states = ['e', 'u', 'd'] for shot in result.measurements: pre = shot.pre_sequence post = shot.post_sequence state_idx = np.array(pre) * (1 + np.array(post)) state = "".join(map(lambda s_idx: states[s_idx], state_idx)) state_counts.update((state,)) return dict(state_counts) counts_simulator = get_counts(result_simulator) # takes about 5 seconds print(counts_simulator)
{'udududud': 330944, 'dudududu': 329576, 'dududdud': 38033, ...}

counts다음은 샷 전체에서 각 상태 구성이 관찰된 횟수를 세는 사전입니다. 다음 코드를 사용하여 시각화할 수도 있습니다.

from collections import Counter def has_neighboring_up_states(state): if 'uu' in state: return True if state[0] == 'u' and state[-1] == 'u': return True return False def number_of_up_states(state): return Counter(state)['u'] def plot_counts(counts): non_blockaded = [] blockaded = [] for state, count in counts.items(): if not has_neighboring_up_states(state): collection = non_blockaded else: collection = blockaded collection.append((state, count, number_of_up_states(state))) blockaded.sort(key=lambda _: _[1], reverse=True) non_blockaded.sort(key=lambda _: _[1], reverse=True) for configurations, name in zip((non_blockaded, blockaded), ('no neighboring "up" states', 'some neighboring "up" states')): plt.figure(figsize=(14, 3)) plt.bar(range(len(configurations)), [item[1] for item in configurations]) plt.xticks(range(len(configurations))) plt.gca().set_xticklabels([item[0] for item in configurations], rotation=90) plt.ylabel('shots') plt.grid(axis='y') plt.title(f'{name} configurations') plt.show() plot_counts(counts_simulator)
인접한 “업” 상태 구성 없이 많은 수의 샷을 보여 주는 막대형 차트.
높은 값에서 낮은 값 순으로 상태가 내림차순으로 정렬된 일부 인접 '작동' 상태 구성의 샷을 보여 주는 막대형 차트입니다.

도표를 통해 반강자성 위상을 성공적으로 준비했는지 확인할 수 있는 다음 관찰 결과를 확인할 수 있습니다.

  1. 일반적으로, 적어도 한 쌍의 인접 스핀이 모두 “업” 상태인 상태보다 차단되지 않은 상태 (인접 스핀이 “업” 상태에 있지 않은 상태) 가 더 일반적입니다.

  2. 일반적으로 구성이 차단되지 않는 한 “상승” 자극이 더 많은 상태가 선호됩니다.

  3. 가장 일반적인 상태는 완벽한 반강자성 상태와 입니다. "dudududu" "udududud"

  4. 두 번째로 흔한 상태는 1, 2, 2의 연속적인 분리가 있는 “상승” 자극이 3회밖에 없는 상태입니다. 이는 반 데르 발스 교호작용이 그 다음으로 가장 가까운 이웃 국가에도 (비록 작긴 하지만) 영향을 미친다는 것을 보여줍니다.

러닝 온의 Aquila QPU QuEra

전제 조건: Braket SDK를 pip로 설치하는 것 외에도 Amazon Braket을 처음 사용하는 경우 필요한 시작 단계를 완료했는지 확인하십시오.

참고

Braket 호스팅 노트북 인스턴스를 사용하는 경우 Braket SDK가 인스턴스와 함께 사전 설치되어 제공됩니다.

모든 종속성이 설치되었으면 QPU에 연결할 수 있습니다. Aquila

from braket.aws import AwsDevice aquila_qpu = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")

AHS 프로그램을 QuEra 기계에 적합하게 만들려면 QPU에서 허용하는 정밀도 수준을 준수하도록 모든 값을 반올림해야 합니다Aquila. (이러한 요구 사항은 이름에 “해상도”가 포함된 장치 매개변수에 의해 제어됩니다. aquila_qpu.properties.dict()노트북에서 실행하면 확인할 수 있습니다. Aquila의 기능 및 요구 사항에 대한 자세한 내용은 Aquila 소개 노트북을 참조하십시오.) 메서드를 호출하여 이 작업을 수행할 수 있습니다. discretize

discretized_ahs_program = ahs_program.discretize(aquila_qpu)

이제 Aquila QPU에서 프로그램을 실행할 수 있습니다 (현재는 100개의 샷만 실행).

참고

Aquila프로세서에서 이 프로그램을 실행하면 비용이 발생합니다. Amazon Braket SDK에는 고객이 비용 한도를 설정하고 거의 실시간으로 비용을 추적할 수 있는 비용 추적기가 포함되어 있습니다.

task = aquila_qpu.run(discretized_ahs_program, shots=100) metadata = task.metadata() task_arn = metadata['quantumTaskArn'] task_status = metadata['status'] print(f"ARN: {task_arn}") print(f"status: {task_status}")
task ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef task status: CREATED

양자 작업을 실행하는 데 걸리는 시간의 편차가 크기 때문에 (가용성 창과 QPU 사용률에 따라 다름), 나중에 다음 코드 스니펫을 통해 상태를 확인할 수 있도록 양자 작업 ARN을 메모해 두는 것이 좋습니다.

# Optionally, in a new python session from braket.aws import AwsQuantumTask SAVED_TASK_ARN = "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef" task = AwsQuantumTask(arn=SAVED_TASK_ARN) metadata = task.metadata() task_arn = metadata['quantumTaskArn'] task_status = metadata['status'] print(f"ARN: {task_arn}") print(f"status: {task_status}")
*[Output]* task ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef task status: COMPLETED

상태가 COMPLETED (Amazon Braket 콘솔의 양자 작업 페이지에서도 확인 가능) 되면 다음을 사용하여 결과를 쿼리할 수 있습니다.

result_aquila = task.result()

QPU 결과 분석

이전과 동일한 get_counts 함수를 사용하여 개수를 계산할 수 있습니다.

counts_aquila = get_counts(result_aquila) print(counts_aquila)
*[Output]* {'udududud': 24, 'dudududu': 17, 'dududdud': 3, ...}

그리고 다음과 같이 plot_counts 플로팅합니다.

plot_counts(counts_aquila)
인접한 “상승” 상태가 있거나 없는 촬영 컷의 비율을 보여주는 막대형 차트.

참고로, 일부 샷에는 빈 사이트 (“e”로 표시) 가 있습니다. 이는 QPU의 원자당 준비 불완전성 1~ 2% 때문입니다. Aquila 이 외에도 샷 수가 적기 때문에 예상되는 통계적 변동 범위 내에서 결과가 시뮬레이션과 일치합니다.

Next

축하합니다. 이제 로컬 AHS 시뮬레이터와 Aquila QPU를 사용하여 Amazon Braket에서 첫 번째 AHS 워크로드를 실행했습니다.

Rydberg 물리학, 아날로그 해밀턴 시뮬레이션 및 장치에 대한 자세한 내용은 예제 노트북을 Aquila 참조하십시오.