기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
안녕하세요 AHS: 첫 아날로그 해밀턴 시뮬레이션을 실행해 보세요.
AHS
아날로그 해밀턴 시뮬레이션 (AHS) 은 양자 회로와는 다른 양자 컴퓨팅의 패러다임입니다. 각 게이트가 한 번에 몇 큐비트에서만 작동하는 일련의 게이트 대신 해당 해밀턴의
AHS를 수행할 수 있는 양자 장치는 매개 변수 (예: 일관된 구동장의 진폭 및 디튜닝) 를 조정하여 사용자 지정 해밀턴식 양자 시스템의 시간 변화를 근사화합니다. AHS 패러다임은 상호 작용하는 여러 입자의 양자 시스템의 정적 및 동적 특성을 시뮬레이션하는 데 적합합니다. 의 Aquila 디바이스와
상호 작용하는 스핀 체인
상호 작용하는 여러 입자로 구성된 시스템의 표준 예를 들어 8개의 스핀으로 이루어진 고리 (각각 “업” ↑‡와 “down” ↓† 상태일 수 있음) 를 생각해 보겠습니다. 비록 작지만 이 모델 시스템은 이미 자연 발생 자성 물질의 흥미로운 현상을 몇 가지 보여주고 있습니다. 이 예제에서는 연속적인 스핀이 반대 방향을 가리키는 이른바 반강자성 오더를 만드는 방법을 보여줍니다.
![위쪽 및 아래쪽 역방향 화살표가 포함된 8개의 원 노드를 연결하는 다이어그램.](images/AntiFerromagnetic.png)
배열
회전할 때마다 하나의 중성 원자를 사용할 것이고, “업” 및 “다운” 스핀 상태는 각각 원자의 들뜬 리드버그 상태와 그라운드 상태로 인코딩될 것입니다. 먼저 2차원 배열을 만듭니다. 다음 코드를 사용하여 위의 스핀 링을 프로그래밍할 수 있습니다.
전제 조건: Braket SDK를 pip 설치해야 합니다.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
![양 축의 양수 값과 음수 값에 분포된 점을 보여주는 스캐터 차트.](images/PlotNeutralAtoms.png)
상호 작용
반강자성 단계를 준비하려면 인접 스핀 간의 상호 작용을 유도해야 합니다. 이를 위해 반 데르 발스 상호작용을
![이 교호작용을 모든 스핀 쌍 (j, k) 에 대한 합으로 표현한 해밀턴 교호작용 방정식입니다.](images/HInteraction.png)
여기서 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 프로그램이 시작될 때 모든 스핀은 (기본적으로) “다운” 상태에서 시작되며, 소위 강자성 단계에 있습니다. 반강자성 위상을 준비한다는 목표를 염두에 두고 스핀을 이 상태에서 “상승” 상태가 선호되는 다물체 상태로 부드럽게 전환하는 시간 종속 일관된 구동 필드를 지정합니다. 해당하는 해밀턴식은 다음과 같이 쓸 수 있습니다.
![해밀턴 구동 함수의 계산을 나타내는 수학 방정식.](images/HDrive.png)
여기서 Ω (t), (t), Δ (t) 는 모든 스핀에 균일하게 영향을 미치는 구동 필드의 시간 종속 글로벌 진폭 (일명 Rabi 주파수
강자성 위상에서 반강자성 위상으로의 원활한 전환을 프로그래밍하기 위해 다음 코드를 사용하여 구동 필드를 지정합니다.
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에 가까운 평평한 선을 나타냅니다.](images/DrivingTimeSeries.png)
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)
![인접한 “업” 상태 구성 없이 많은 수의 샷을 보여 주는 막대형 차트.](images/AHSCounts1.png)
![높은 값에서 낮은 값 순으로 상태가 내림차순으로 정렬된 일부 인접 '작동' 상태 구성의 샷을 보여 주는 막대형 차트입니다.](images/AHSCounts2.png)
도표를 통해 반강자성 위상을 성공적으로 준비했는지 확인할 수 있는 다음 관찰 결과를 확인할 수 있습니다.
-
일반적으로, 적어도 한 쌍의 인접 스핀이 모두 “업” 상태인 상태보다 차단되지 않은 상태 (인접 스핀이 “업” 상태에 있지 않은 상태) 가 더 일반적입니다.
-
일반적으로 구성이 차단되지 않는 한 “상승” 자극이 더 많은 상태가 선호됩니다.
-
가장 일반적인 상태는 완벽한 반강자성 상태와 입니다.
"dudududu"
"udududud"
-
두 번째로 흔한 상태는 1, 2, 2의 연속적인 분리가 있는 “상승” 자극이 3회밖에 없는 상태입니다. 이는 반 데르 발스 교호작용이 그 다음으로 가장 가까운 이웃 국가에도 (비록 작긴 하지만) 영향을 미친다는 것을 보여줍니다.
러닝 온의 Aquila QPU QuEra
전제 조건: Braket SDK를
참고
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)
![인접한 “상승” 상태가 있거나 없는 촬영 컷의 비율을 보여주는 막대형 차트.](images/QPUPlotCounts.png)
참고로, 일부 샷에는 빈 사이트 (“e”로 표시) 가 있습니다. 이는 QPU의 원자당 준비 불완전성 1~ 2% 때문입니다. Aquila 이 외에도 샷 수가 적기 때문에 예상되는 통계적 변동 범위 내에서 결과가 시뮬레이션과 일치합니다.
Next
축하합니다. 이제 로컬 AHS 시뮬레이터와 Aquila QPU를 사용하여 Amazon Braket에서 첫 번째 AHS 워크로드를 실행했습니다.
Rydberg 물리학, 아날로그 해밀턴 시뮬레이션 및 장치에 대한 자세한 내용은 예제 노트북을 Aquila 참조하십시오.