콘텐츠로 이동

Lab 2. 양자 측정 — probs, sample, expval

실습 실행: Google Colab에서 바로 실행

학습 목표

  • qml.probs(), qml.sample(), qml.expval() 세 가지 측정 방식의 차이를 이해한다
  • shots 수에 따라 샘플 비율이 이론 확률에 수렴하는 과정을 확인한다
  • 기댓값 \(\langle Z \rangle = \cos(\theta)\)가 샘플 평균과 같음을 검증한다

환경 설정

Colab에서 최초 1회 실행한다.

!pip install pennylane koreanize_matplotlib -q

라이브러리를 import한다.

import pennylane as qml
import numpy as np
import matplotlib.pyplot as plt
import koreanize_matplotlib
plt.rcParams['axes.unicode_minus'] = False

수정 구간

# ===== 수정 =====
theta = np.pi / 4
# 추천값:
# pi/6  → P(|0>) 매우 높음, 거의 |0> 상태
# pi/4  → 중간 중첩, expval = 0.707
# pi/2  → 완전 중첩, P(|0>)=P(|1>)=0.5, expval = 0
# pi    → 완전히 |1> 상태, expval = -1

shots = 1024
# 추천값:
# 10    → 결과 불안정, probs와 큰 차이
# 100   → 어느 정도 수렴
# 1024  → 기본값, 안정적
# 10000 → 이론값에 거의 일치
# ===== 수정 끝 =====

회로 정의

3가지 측정 방식별로 회로를 정의한다. 회로 구조(RX 게이트)는 동일하고 측정만 다르다.

dev = qml.device("default.qubit", wires=1)

@qml.qnode(dev)
def circuit_probs(angle):
    qml.RX(angle, wires=0)
    return qml.probs(wires=0)

@qml.qnode(dev)
def circuit_sample(angle):
    qml.RX(angle, wires=0)
    return qml.sample(qml.PauliZ(0))

@qml.qnode(dev)
def circuit_expval(angle):
    qml.RX(angle, wires=0)
    return qml.expval(qml.PauliZ(0))

# PennyLane 0.44 권장: set_shots transform
circuit_probs_s  = qml.set_shots(circuit_probs,  shots=shots)
circuit_sample_s = qml.set_shots(circuit_sample, shots=shots)
circuit_expval_s = qml.set_shots(circuit_expval, shots=shots)

qml.set_shots는 PennyLane 0.44에서 shots를 회로에 적용하는 권장 방식이다.

확률 측정

양자 상태는 측정 전까지 |0⟩과 |1⟩의 중첩으로 존재한다. qml.probs()는 각 상태가 관측될 확률을 반환한다.

p = circuit_probs_s(theta)
p0_theory = np.cos(theta / 2) ** 2
p1_theory = np.sin(theta / 2) ** 2

print(f"  P(|0>) = {p[0]:.4f}   이론: cos²(θ/2) = {p0_theory:.4f}")
print(f"  P(|1>) = {p[1]:.4f}   이론: sin²(θ/2) = {p1_theory:.4f}")

시각화

확률 측정 결과

해석

theta = pi/4일 때 P(|0>) ≈ 0.854, P(|1>) ≈ 0.146이다. 큐비트가 |0⟩에 가깝지만 |1⟩도 가능한 상태이다. 이 확률은 "측정하기 전"의 정보이며, 실제 측정하면 반드시 0 또는 1 중 하나로 collapse된다.

샘플링 실행

qml.sample()은 실제 양자컴퓨터처럼 매번 +1(|0⟩) 또는 -1(|1⟩) 중 하나를 반환한다. shots번 반복 측정한 결과를 배열로 받는다.

samples = circuit_sample_s(theta)
cnt_p1   = int(np.sum(samples == 1))
cnt_m1   = int(np.sum(samples == -1))
ratio_p1 = cnt_p1 / shots

print(f"  +1(|0>) 횟수: {cnt_p1}   비율: {ratio_p1:.4f}   probs P(|0>): {p[0]:.4f}")
print(f"  -1(|1>) 횟수: {cnt_m1}   비율: {cnt_m1/shots:.4f}   probs P(|1>): {p[1]:.4f}")

시각화 1: 개별 측정 결과

처음 50번의 측정 결과를 막대로 표시한다. +1(파랑)과 -1(빨강)이 무작위로 나타난다.

개별 측정 결과 50회

시각화 2: sample 비율 vs probs 비교

sample의 비율이 probs의 이론 확률에 수렴하는지 확인한다.

sample 비율과 probs 비교

해석

매 측정은 +1 또는 -1 중 하나만 나온다. 이것이 양자 측정의 "collapse"이다. 하지만 충분히 많이 반복하면(shots↑), +1이 나온 비율은 P(|0⟩)에, -1이 나온 비율은 P(|1⟩)에 수렴한다. shots=10이면 비율이 크게 벗어나고, shots=10000이면 거의 일치한다.

기댓값 측정

qml.expval()은 sample 결과의 평균이다. +1과 -1의 가중 평균이 cos(θ)와 일치하는지 검증한다.

\[ \langle Z \rangle = (+1) \times P(|0\rangle) + (-1) \times P(|1\rangle) = \cos(\theta) \]
ev        = float(circuit_expval_s(theta))
ev_theory = np.cos(theta)

시각화: cos(θ) 곡선 위에 회로 결과 표시

cos(θ) 곡선과 회로 결과

3단계 연결

단계 측정 theta=pi/4 결과 의미
1 probs [0.854, 0.146] 측정 전 확률분포
2 sample +1, -1, +1, +1, ... 측정 순간 collapse
3 expval 0.707 sample의 평균 = cos(θ)

probs → sample → expval 순서는 "확률 → 실현 → 통계"의 흐름이다. 양자컴퓨터에서는 probs를 직접 볼 수 없고, sample을 반복해서 probs와 expval을 추정한다.

과제 1: theta = pi/2 (완전 중첩)

theta를 pi/2로 변경하고 전체를 다시 실행하라. P(|0⟩) = P(|1⟩) = 0.5가 되는지, expval이 0에 가까운지 확인하라.

# 수정: theta = np.pi / 2 로 변경 후 전체 재실행

과제 2: shots = 10 vs 10000

theta = pi/4를 유지하고, shots를 10과 10000으로 각각 실행하라. 2-2의 "sample 비율 vs probs 비교" 그래프에서 차이가 얼마나 나는지 관찰하라.

# 수정: shots = 10 으로 변경 후 재실행
# 다시 shots = 10000 으로 변경 후 재실행
# 두 결과를 비교하라

과제 3: 3단계 관계 검증

sample 결과에서 직접 평균을 계산하여 expval과 같은 값이 나오는지 확인하라.

세 값이 유사하면, sample의 평균 = expval = cos(θ)라는 관계가 성립하는 것이다.