Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/translations/ko/ch-states/representing-qubit-states.ipynb
3855 views
Kernel: Python 3

큐비트 상태 표현

여러분은 비트가 무엇인지, 그리고 우리에게 익숙한 디지털 컴퓨터가 어떻게 작동하는지 알고 있습니다. 최신 소프트웨어에서 사용되는 모든 복잡한 변수, 객체, 및 데이터 구조는 기본적으로 엄청난 양의 비트 덩어리입니다. 양자 컴퓨팅을 하는 우리는 이들을 고전 변수라고 부릅니다. 여러분이 이 강의를 읽기 위해 사용하는 컴퓨터와 같이 고전 변수를 사용하는 컴퓨터는 고전 컴퓨터라고 부릅니다.

양자 컴퓨터에서는 기본적인 변수는 큐비트, 즉 비트의 양자 버전입니다. 이들은 일반적인 비트와 똑같은 제한을 합니다. 1개의 이진 정보만을 저장할 수 있는 [[0또는 1|-1 또는 1| 0| 1|-1]] 의 출력밖에 낼 수 없습니다. 다만, 양자 역학에서만 설명할 수 있는 방식으로 제어됩니다. 이 특성은 새로운 게이트를 사용해 새로운 방식으로 알고리즘을 설계할 수 있도록 해줍니다.

이러한 새로운 게이트를 완전히 이해하려면 먼저 큐비트 상태를 기록하는 방법을 이해해야 합니다. 이를 위해 우리는 수학의 벡터, 행렬 및 복소수를 사용할 것입니다. 진행 중에도 이러한 개념을 소개할 것이지만 이미 이러한 개념에 익숙해져 있다면 더 좋습니다. 자세한 설명이나 복습이 필요한 경우 여기에서 가이드를 찾을 수 있습니다.

1. 고전 비트 vs 양자 비트

1.1 상태벡터

양자 물리학에서는 시스템의 상태를 표현하기 위해 상태벡터를 사용합니다. 만약 트랙을 따라 달리는 자동차의 위치를 표현하고자 한다면, 이는 고전 계이므로 하나의 숫자 xx를 사용할 수 있습니다.

스칼라 값으로 자동차 표현하기

x=4x=4

하나의 숫자를 사용하는 대신에, 우리는 상태벡터라고 이름 붙은 벡터가 갖는 숫자들을 사용하여 자동차의 상태를 표현할 수도 있습니다. 상태벡터의 각각의 값들은 자동차가 특정한 위치에서 발견될 확률을 나타냅니다.

벡터를 사용하여 자동차 표현하기

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{x_ket}{|x\rang…

위치뿐만 아니라, 자동차가 가질 수 있는 모든 가능한 속력이나, 모든 가능한 색상 같은 것들도 상태벡터에 넣을 수 있습니다. (위의 자동차 예시와 같은) 고전 계에서는 오직 하나의 숫자만으로도 충분한 상황에서 이처럼 거대한 벡터를 사용하는 것은 어리석은 일입니다. 그러나 우리는 이 챕터에서, 상태벡터가 양자 컴퓨터를 비롯한 양자계의 상태를 추적하는 좋은 방법이 될 수 있다는 것을 배우게 될 것입니다.

1.2 큐비트 표기법

고전적인 비트는 계산 과정의 모든 지점에서 항상 0이나 1값을 갖습니다. 비트의 상태에 대한 설명은 이 정도면 충분할 것 같습니다. 따라서 고전 비트 (c)의 상태를 표기하기 위해서, 우리는 이 두 개의 이진값만을 사용합니다. 예를 들면 다음과 같습니다.

c=0c = 0

이러한 제약은 양자 비트에서는 조금 달라집니다. 하나의 큐비트에서 명확하게 0 값을 얻거나, 1 값을 얻는 것은 출력을 확인하기 위한 측정이 이뤄졌을 때만 가능합니다. 그렇지 않을 경우에는, 이 큐비트의 상태는 하나의 단순한 이진값으로 표현하는 것보다 복잡한 무언가로 존재합니다.

이를 표현하는 방법을 살펴보기 위해, 두 개의 단순한 사례를 먼저 살펴보겠습니다. 마지막 섹션에서 보았던 것처럼, 측정하였을 때 출력값이 언제나 0인 상태로 존재하는 큐비트를 준비할 수 있습니다.

이 상태를 표현하기 위한 이름이 필요합니다. 상상력이 부족한 이름이지만, 이 상태를 00이라고 부릅시다. 비슷하게 출력이 항상 1인 상태도 있을 것입니다. 이것을 11이라고 부릅시다. 이 두 개의 상태는 서로 배타적이지만, 동시에 모든 상태를 표현할 수 있습니다. 큐비트는 명확하게 0을 출력으로 내놓거나, 1을 출력으로 내놓을 것입니다. 하지만 두 출력이 겹치진 않습니다. 이러한 경우를 수학으로 표현하는 한 가지 방법은 두 개의 직교 벡터를 사용하는 것입니다.

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{|0\rangle…

여기에 한꺼번에 받아들이기 많은 표기법이 있습니다. 먼저, 조금 이상해 보이는 |\rangle를 살펴봅시다. 이들의 역할은 그저 우리가 0011이라 이름 붙은 큐비트 상태를 나타내는 벡터에 관해서 이야기하고 있다는 것을 상기시킵니다. 이를 통해 우리는 숫자 0, 1이나 비트 값 0, 1과 같은 것들과 벡터를 구별해낼 수 있습니다. 이러한 표기법은 Dirac이 소개한 bra-ket 표기법의 일부입니다.

만약 벡터와 친숙하지 않다면, 그저 특정한 법칙에 따라 조작할 수 있는 숫자들의 목록이라고 생각해도 좋습니다. 고등학교 물리 수업을 통해 벡터에 익숙해졌다면, 이러한 법칙이 벡터를 방향과 값을 모두 갖는 물리량을 표현하기에 적합하게 만들어 준다는 것을 알고 있을 것입니다. 예를 들어, 어떠한 물체의 속도는 벡터로 완벽하게 표현될 수 있습니다. 그러나 우리가 양자 상태에 벡터를 적용하는 방법은 이와는 조금 다르므로, 이전에 알고 있던 직관에 너무 의존하지는 않기를 바랍니다. 이제는 새로운 것을 해봅시다.

벡터를 이용하여 그저 0|0\rangle이나 1|1\rangle만이 아닌 좀 더 복잡한 상태를 표현할 수 있습니다. 예를 들어, 다음과 같은 벡터를 생각해봅시다.

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{|q_0\rangle…

이 상태가 의미하는 것을 이해하기 위해서는 벡터를 조작하는 수학 규칙들을 사용해야 합니다. 특히 어떻게 벡터끼리 더하고, 어떻게 벡터에 스칼라를 곱하는지를 이해할 필요가 있습니다.

기억 할 것

행렬 수학 두 개의 벡터를 더할 때는 각각의 원소끼리 더합니다.
a=[a0 a1  an],b=[b0 b1  bn]|a\rangle = \begin{bmatrix}a_0 \ a_1 \ \vdots \ a_n \end{bmatrix}, \quad |b\rangle = \begin{bmatrix}b_0 \ b_1 \ \vdots \ b_n \end{bmatrix}a+b=[a0+b0 a1+b1  an+bn]|a\rangle + |b\rangle = \begin{bmatrix}a_0 + b_0 \ a_1 + b_1 \ \vdots \ a_n + b_n \end{bmatrix}

벡터에 스칼라를 곱할 때는 각각의 원소에 스칼라 값을 곱합니다.

xa=[x×a0 x×a1  x×an]x|a\rangle = \begin{bmatrix}x \times a_0 \ x \times a_1 \ \vdots \ x \times a_n \end{bmatrix}

이 두 개의 규칙이 벡터 q0|q_0\rangle를 (위에서 본 것과 같이) 다시 쓰는 데 사용됩니다.

q0amp;=120+i21 amp;=12[1 0]+i2[0 1] amp;=[12 0]+[0 i2] amp;=[12 i2] \begin{aligned} |q_0\rangle &= \tfrac{1}{\sqrt{2}}|0\rangle + \tfrac{i}{\sqrt{2}}|1\rangle \ &= \tfrac{1}{\sqrt{2}}\begin{bmatrix}1 \ 0\end{bmatrix} + \tfrac{i}{\sqrt{2}}\begin{bmatrix}0 \ 1\end{bmatrix} \ &= \begin{bmatrix}\tfrac{1}{\sqrt{2}} \ 0\end{bmatrix} + \begin{bmatrix}0 \ \tfrac{i}{\sqrt{2}}\end{bmatrix} \ &= \begin{bmatrix}\tfrac{1}{\sqrt{2}} \ \tfrac{i}{\sqrt{2}} \end{bmatrix} \ \end{aligned}
정규 직교 기저 이전에 두 개의 벡터 0|0\rangle1|1\rangle이 정규 직교라고 이야기한 바 있는데, 이는 두 벡터가 정규화되어 있고, 서로 직교한다는 의미입니다. 직교한다는 것은 벡터끼리 이루는 각도가 직각임을 의미합니다.

기저

그리고 정규화되어 있다는 것은 벡터의 값 (화살표의 길이)가 1이라는 것을 의미합니다. 두 벡터 0|0\rangle1|1\rangle선형 독립인데, 이는 곧 우리가 0|0\rangle1|1\rangle을 사용하여 표현하거나 혹은 그 반대 경우가 불가능하다는 것을 의미합니다. 그러나 두 개의 벡터인 0|0\rangle1|1\rangle, 그리고 벡터 합과 스칼라 곱을 사용하면 2차원 평면에 존재하는 모든 벡터를 표현할 수 있습니다.

기저

벡터 0|0\rangle1|1\rangle은 선형 독립이고, 2차원 평면의 모든 벡터를 벡터 합과 스칼라 곱으로 나타낼 수 있기 때문에, 0|0\rangle1|1\rangle이 기저를 이룬다고 표현할 수 있습니다. 이 경우에는 두 벡터가 서로 직교하고, 정규화되어 있기 때문에 정규 직교 기저라고 부릅니다.

상태 0|0\rangle1|1\rangle이 정규 직교 기저를 이루므로, 2차원 평면의 임의의 벡터는 두 상태의 조합으로 표현될 수 있습니다. 이로써 우리의 큐비트 상태를 다음과 같이 표현할 수 있게 되었습니다.

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{|q_0\rangle…

이 벡터 q0|q_0\rangle는 큐비트의 상태벡터라고 하며, 이 큐비트에 대해 우리가 알 수 있는 모든 것들을 말해줍니다. 지금 시점에서는 이 상태벡터로부터 간단한 해석만을 이끌어 낼 수 있는데, 이러한 것은 완벽하게 0|0\rangle도 아니고, 완벽하게 1|1\rangle도 아니라는 것을 의미합니다. 대신 상태벡터는 그 두 벡터의 조합으로 표현됩니다. 양자 역학에서는 이와 같은 선형 조합을 '중첩'이라고 부릅니다.

비록 예시 상태 q0|q_0\rangle0|0\rangle1|1\rangle의 중첩으로 표현될 수 있지만, 아직 분명하게 잘 정의된 큐비트 상태인 것은 아닙니다. 이를 확인하기 위해선, 큐비트가 어떻게 조작될 수 있는지부터 탐구해보아야 합니다.

1.3 Qiskit과 함께 큐비트 탐험하기

먼저, 우리에게 필요한 모든 도구를 불러와야야 합니다.

from qiskit import QuantumCircuit, assemble, Aer from qiskit.visualization import plot_histogram, plot_bloch_vector from math import sqrt, pi

Qiskit에서는 회로를 저장하기 위해 QuantumCircuit이라는 객체를 사용하는데, 이 객체는 곧 회로의 양자 연산들과 연산이 적용될 큐비트의 리스트입니다.

qc = QuantumCircuit(1) # 큐비트 한 개로 이루어진 양자 회로를 만듭니다.

양자 회로에서 큐비트는 항상 상태 0|0\rangle으로 시작합니다. 이를 임의의 상태로 바꾸기 위해서 initialize() 메서드를 사용할 수 있습니다. initialize() 메서드에는 리스트의 형태로 표현된 벡터와 이 상태로 초기화하고 싶은 큐비트가 무엇인지를 인자로 넣어줍니다.

qc = QuantumCircuit(1) # 큐비트 한 개로 이루어진 양자 회로를 만듭니다. initial_state = [0,1] # initial_state를 |1>로 정의합니다. qc.initialize(initial_state, 0) # 0번째 큐비트를 초기화합니다. qc.draw() # 우리의 회로를 살펴봅시다.
Image in a Jupyter notebook

우리의 큐비트의 결과 상태를 확인하기 위해, Qiskit 시뮬레이터 중 하나를 사용할 수 있습니다.

sim = Aer.get_backend('aer_simulator') # Qiskit에게 우리의 회로를 어떻게 시뮬레이션할지 알려줍니다.

회로로부터 결과를 얻기 위해선 실행할 회로와 백엔드를 인자로 하는 run 메서드를 사용합니다. 그 후에 .result()를 통해 결과를 얻을 수 있습니다.

qc = QuantumCircuit(1) # 큐비트 한 개로 이루어진 양자 회로를 만듭니다. initial_state = [0,1] # initial_state를 |1>로 정의합니다. qc.initialize(initial_state, 0) # 0번째 큐비트를 초기화합니다. qc.save_statevector() # 시뮬레이터가 상태벡터를 저장하도록 합니다. qobj = assemble(qc) # 시뮬레이터를 돌리기 위해 회로로부터 Qobj를 생성합니다. result = sim.run(qobj).result() # 시뮬레이션을 실행하고 결과를 반환받습니다.

.get_statevector()를 사용하여 result로부터 최종 상태벡터를 얻을 수 있습니다.

out_state = result.get_statevector() print(out_state) # 출력 상태벡터를 표시합니다.
[0.+0.j 1.+0.j]

메모: Python은 복소수의 ii를 표현하기 위해 j를 사용합니다. 우리는 여기서 벡터가 두 개의 복소수 0.+0.j = 0과 1.+0.j = 1로 표현되는 것을 확인할 수 있습니다.

이제 실제 양자 컴퓨터에서 하는 것처럼 큐비트를 측정하고 결과를 확인해봅시다.

qc.measure_all() qc.draw()
Image in a Jupyter notebook

이번에는 상태벡터 대신 .get_counts()를 사용하여 01 상태인 횟수를 측정해봅시다.

qobj = assemble(qc) result = sim.run(qobj).result() counts = result.get_counts() plot_histogram(counts)
Image in a Jupyter notebook

우리는 (놀랍지 않게도) 100%의 확률로 1|1\rangle이 측정됨을 확인할 수 있습니다.

이번에는 우리의 큐비트가 중첩되게 한 후 어떻게 되는지 확인해 봅시다. 이번 섹션의 앞부분에서 보았던 q0|q_0\rangle 상태를 사용할 것입니다.

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 53: …angle + \tfrac{\̲c̲s̲s̲I̲d̲{i}{i}}{\sqrt{2…

Python 리스트에 이 계수들을 더할 필요가 있습니다. 복소수 계수를 더하기 위해서, Python은 허수부를 나타내는 표시로 j를 사용합니다 (일반적으로 수학에서는 "ii"로 표현합니다).

initial_state = [1/sqrt(2), 1j/sqrt(2)] # 상태 |q_0>를 정의합니다.

그리고 큐비트를 초기화하기 위해 밟았던 단계들을 반복합니다.

qc = QuantumCircuit(1) # qc를 다시 정의해야 합니다. qc.initialize(initial_state, 0) # 0번째 큐비트를 `initial_state`로 초기화합니다. qc.save_statevector() # 상태벡터를 저장합니다. qobj = assemble(qc) state = sim.run(qobj).result().get_statevector() # 회로를 실행합니다. print(state) # 결과를 출력합니다.
[0.70710678+0.j 0. +0.70710678j]
qobj = assemble(qc) results = sim.run(qobj).result().get_counts() plot_histogram(results)
Image in a Jupyter notebook

0|0\rangle이 측정될 확률은 1|1\rangle이 측정될 확률에 비교했을 때 [[같다|적다|많다]]는 것을 확인할 수 있습니다. 이를 설명하기 위해선 측정에 대해 이야기해보아야 합니다.

2. 측정의 규칙들

2.1 매우 중요한 규칙

측정에는 간단한 규칙이 하나 있습니다. 상태 ψ|\psi \rangle가 상태 x|x\rangle에 있을 확률을 측정하는 방법은 다음과 같습니다.

p(x)=xψ2p(|x\rangle) = | \langle x| \psi \rangle|^2

기호 \langle|x\langle x |가 행 벡터라는 것을 말해줍니다. 양자 역학에서는 열 벡터를 ket, 행 벡터를 bra라고 부릅니다. 합쳐서 bra-ket 표기법이라고 합니다. 임의의 ket a|a\rangle에는 대응하는 bra a\langle a|가 있고, 서로 켤레 전치함으로써 변환할 수 있습니다.

기억 할 것

내적 벡터를 곱하기 위한 다양한 방법이 있지만, 여기에서는 _내적_을 사용합니다. 내적은 여러분이 이미 친숙할 _점곱셈_의 일반화된 형태입니다. 이 가이드에서는 bra (행벡터)와 ket (열벡터) 간의 내적을 사용하며, 다음과 같이 적용합니다.
a=[a0,amp;a1,amp;amp;an]\langle a| = \begin{bmatrix}a_0, & a_1, & \dots & a_n \end{bmatrix}b=[b0 b1  bn]|b\rangle = \begin{bmatrix}b_0 \ b_1 \ \vdots \ b_n \end{bmatrix}ab=a0b0+a1b1anbn\langle a|b\rangle = a_0 b_0 + a_1 b_1 \dots a_n b_n

두 벡터간의 내적이 언제나 스칼라 값을 내놓는다는 것을 확인할 수 있습니다. 기억할만한 사실은 0|0\rangle, 1|1\rangle과 같은 직교하는 벡터 사이의 내적은 언제나 0이 된다는 것입니다.

10=[0,amp;1][1 0]=0\langle1|0\rangle = \begin{bmatrix} 0 , & 1\end{bmatrix}\begin{bmatrix}1 \ 0\end{bmatrix} = 0

벡터 0|0\rangle1|1\rangle은 정규화되어 있다는 것도 함께 기억해두세요 (크기가 1과 같습니다).

00amp;=[1,amp;0][1 0]=1 11amp;=[0,amp;1][0 1]=1\begin{aligned} \langle0|0\rangle &= \begin{bmatrix} 1 , & 0\end{bmatrix}\begin{bmatrix}1 \ 0\end{bmatrix} = 1 \ \langle1|1\rangle &= \begin{bmatrix} 0 , & 1\end{bmatrix}\begin{bmatrix}0 \ 1\end{bmatrix} = 1 \end{aligned}
켤레 전치 bra와 ket은 켤레 전치법을 사용하여 서로 변환할 수 있습니다. 우리는 ket (열벡터)가 다음과 같이 표현된다는 것을 알고 있습니다.
a=[a0 a1  an]\quad|a\rangle = \begin{bmatrix}a_0 \ a_1 \ \vdots \ a_n \end{bmatrix}

켤레 전치된 결과를 얻기 위해서는, 행렬을 전치하고 행렬의 원소는 ("*" 기호로 표기되는) 켤레로 변경되어야 합니다. 이때, 복소수의 켤레는 실수부는 같고, 허수부는 절댓값이 같지만, 부호가 다른 복소수를 말합니다. 이를 통해 대응되는 bra (열 벡터)를 다음과 같이 얻을 수 있습니다.

a=[a0,amp;a1,amp;amp;an]\langle a| = \begin{bmatrix}a_0^*, & a_1^*, & \dots & a_n^* \end{bmatrix}

위의 식에서 x|x\rangle는 어떠한 큐비트 상태라도 될 수 있습니다. x|x\rangle를 측정할 확률을 얻기 위해서는 측정하고자 하는 상태 (이 경우에는 ψ|\psi\rangle)와 x|x\rangle의 내적을 취하고 크기를 제곱합니다. 이것이 다소 복잡하게 느껴질 수 있지만, 곧 익숙해져 간단하고 자연스러워질 것입니다.

이전에 보았던 q0|q_0\rangle 상태로 돌아가면, 0|0\rangle을 측정할 확률은 실제로 0.5가 될 것입니다.

q0amp;=120+i21 0q0amp;=1200+i201 amp;=121+i20 amp;=12 0q02amp;=12\begin{aligned} |q_0\rangle & = \tfrac{1}{\sqrt{2}}|0\rangle + \tfrac{i}{\sqrt{2}}|1\rangle \ \langle 0| q_0 \rangle & = \tfrac{1}{\sqrt{2}}\langle 0|0\rangle + \tfrac{i}{\sqrt{2}}\langle 0|1\rangle \ & = \tfrac{1}{\sqrt{2}}\cdot 1 + \tfrac{i}{\sqrt{2}} \cdot 0\ & = \tfrac{1}{\sqrt{2}}\ |\langle 0| q_0 \rangle|^2 & = \tfrac{1}{2} \end{aligned}

1|1\rangle을 측정하게 될 확률을 연습삼아 구해봅시다.

이 법칙은 양자 상태에 대한 정보를 어떻게 얻는 지를 알려줍니다. 따라서 이는 양자 계산에서 우리가 할 모든 일에서 아주 중요한 부분을 차지합니다. 또한 몇 가지 중요한 사실들을 내포하고 있습니다.

2.2 이 규칙이 함의하는 것들

#1 정규화

이 규칙은 계수가 곧 확률과 연관되어 있다는 것을 보여줍니다. 만약 확률이 모두 합해 1이 되기를 원한다면 (그리고 반드시 그래야 하죠!) 상태벡터가 알맞게 정규화되어 있다는 것을 보장할 필요가 있습니다. 구체적으로 말하자면, 상태벡터의 크기는 반드시 1이 되어야 합니다.

ψψ=1\langle\psi|\psi\rangle = 1

따라서 만약,

ψ=α0+β1|\psi\rangle = \alpha|0\rangle + \beta|1\rangle

이라면 아래의 식이 성립해야 합니다.

α2+β2=1|\alpha|^2 + |\beta|^2 = 1

이 사실이 여러분이 챕터 전체에 걸쳐 보았던 2\sqrt{2}라는 숫자를 설명해줍니다. 사실, 만약 정규화되어 있지 않은 벡터로 initialize()를 호출하려고 한다면 에러를 반환합니다.

vector = [1,1] qc.initialize(vector, 0)
--------------------------------------------------------------------------- QiskitError Traceback (most recent call last) <ipython-input-12-ddc73828b990> in <module> 1 vector = [1,1] ----> 2 qc.initialize(vector, 0) /usr/local/anaconda3/lib/python3.7/site-packages/qiskit/extensions/quantum_initializer/initializer.py in initialize(self, params, qubits) 453 454 num_qubits = None if not isinstance(params, int) else len(qubits) --> 455 return self.append(Initialize(params, num_qubits), qubits) 456 457 /usr/local/anaconda3/lib/python3.7/site-packages/qiskit/extensions/quantum_initializer/initializer.py in __init__(self, params, num_qubits) 89 if not math.isclose(sum(np.absolute(params) ** 2), 1.0, 90 abs_tol=_EPS): ---> 91 raise QiskitError("Sum of amplitudes-squared does not equal one.") 92 93 num_qubits = int(num_qubits) QiskitError: 'Sum of amplitudes-squared does not equal one.'

간단한 연습

  1. 0|0\rangle을 측정할 확률이 1/31/3인 상태벡터를 만들어보세요.

  2. 같은 측정 확률을 주는 다른 상태 벡터를 만들어 보세요.

  3. 이 두 상태에서 1|1\rangle을 측정할 확률이 2/32/3임을 증명해보세요.

정답은 아래의 위젯에서 확인해볼 수 있습니다 (±1% 정도의 오차가 있을 수 있고, 벡터에 'pi'나 'sqrt()'과 같은 numpy 기호를 사용할 수 있습니다).

# 위젯을 사용하기 위해선 이 셀의 코드를 실행하세요. from qiskit_textbook.widgets import state_vector_exercise state_vector_exercise(target=1/3)

#2 다른 측정 방법

지금까지 살펴본 측정 방법은 상태 ψ|\psi\ranglex|x\rangle로 측정될 확률 p(x)p(|x\rangle)를 구하기 위해 사용됩니다. 어디에도 x|x\rangle0|0\rangle이나 1|1\rangle이어야만 한다고는 하지 않았습니다.

사실, 0|0\rangle1|1\rangle을 사용하는 이 방법은 큐비트를 측정하는 무수히 많은 방법 중 하나일 뿐입니다. 임의의 직교하는 상태쌍에 대해, 큐비트가 두 상태 중 하나가 될 확률을 측정하는 방법을 정의할 수 있습니다.

이 확률은 다음 섹션에서 좀 더 자세히 살펴보겠습니다. 지금으로선 x|x\rangle0|0\rangle1|1\rangle에 한정되지 않는다는 것만 기억해두면 됩니다.

#3 글로벌 위상

상태 1|1\rangle을 측정하면 언제나 1이 출력으로 나옵니다. 그러나 우리는 다음과 같은 상태 또한 생각해 볼 수 있습니다.

[0 i]=i1.\begin{bmatrix}0 \ i\end{bmatrix} = i|1\rangle.

이 상태가 어떻게 행동하는지 확인하기 위해선 측정의 규칙을 적용해야 합니다.

x(i1)2=ix12=x12|\langle x| (i|1\rangle) |^2 = | i \langle x|1\rangle|^2 = |\langle x|1\rangle|^2

여기서 복소수의 크기를 구하면 ii가 사라지는 것을 확인할 수 있습니다. 이 효과는 측정할 상태 x|x\rangle와는 완전히 무관합니다. 어떤 측정을 고려하든지 간에, 상태 i1i|1\rangle의 확률은 1|1\rangle의 확률과 같습니다. 측정만이 큐비트에서 정보를 얻을 수 있는 유일한 방법이므로, 이는 물리적으로 두 상태를 같게 취급할 수 있다는 것을 의미합니다.

더 일반적으로 확장하면, 상태벡터에 곱해진 인자 중에서 γ=1|\gamma|=1인 모든 γ\gamma를 '글로벌 위상'이라고 부릅니다. 글로벌 위상만 다른 상태들은 물리적으로 구분할 수 없습니다.

x(γa)2=γxa2=xa2|\langle x| ( \gamma |a\rangle) |^2 = | \gamma \langle x|a\rangle|^2 = |\langle x|a\rangle|^2

이것이 '상대 위상'이라고 알려진 중첩 사이의 위상차와는 구별된다는 것을 기억해두세요. 다른 타입의 측정과 여러 개의 큐비트를 고려하기 시작한다면 이 차이가 중요해질 것입니다.

#4 관찰자 효과

계수에 큐비트가 특정 상태에 있을 확률에 대한 정보가 있다는 것을 알고 있지만, 만약 한 번이라도 큐비트를 측정한다면 우리는 그 큐비트의 상태가 무엇인지를 확실히 알 수 있습니다. 예를 들어, 아래의 상태에 있는 큐비트를 측정했다고 해봅시다.

q=α0+β1|q\rangle = \alpha|0\rangle + \beta|1\rangle

만약 상태가 0|0\rangle이라는 것을 확인했다면, 우리가 다시 한번 더 측정하더라도 100% 확률로 큐비트는 0|0\rangle 상태에 있을 것입니다. 이는 측정하는 행위가 큐비트의 상태를 바꾸었음을 의미합니다.

q=[α β]Measure 0q=0=[1 0]|q\rangle = \begin{bmatrix} \alpha \ \beta \end{bmatrix} \xrightarrow{\text{Measure }|0\rangle} |q\rangle = |0\rangle = \begin{bmatrix} 1 \ 0 \end{bmatrix}

이것을 큐비트의 상태가 붕괴했다고 표현하기도 합니다. 붕괴는 강력한 효과이므로 현명하게 사용되어야 합니다. 예를 들어, 계산 과정의 모든 지점에서 큐비트를 측정하면서 값을 기록해 나간다면, 그 값은 단순하게 모두 0|0\rangle이거나 1|1\rangle인 값을 갖게 될 것입니다. 그렇게 되면 고전 비트와 다를 바가 없으므로, 계산은 쉽게 고전적 계산으로 대체될 수 있습니다. 진정한 의미의 양자 계산을 하기 위해선 큐비트들이 좀 더 복잡한 상태를 가질 수 있도록 해야 합니다. 따라서 측정은 출력을 알고 싶을 때만 사용되어야 합니다. 이는 곧 모든 측정을 양자 회로의 마지막 지점에서만 사용해야 한다는 것을 의미합니다.

이를 Qiskit의 상태벡터 시뮬레이터를 사용하여 확인해볼 수 있습니다. 큐비트를 중첩 상태로 초기화합시다.

qc = QuantumCircuit(1) # qc를 정의합니다. initial_state = [0.+1.j/sqrt(2),1/sqrt(2)+0.j] qc.initialize(initial_state, 0) qc.draw()
Image in a Jupyter notebook

이는 큐비트를 아래의 상태로 초기화합니다.

q=i20+121|q\rangle = \tfrac{i}{\sqrt{2}}|0\rangle + \tfrac{1}{\sqrt{2}}|1\rangle

시뮬레이터를 통해서 작업한 것을 확인해볼 수 있습니다.

qc.save_statevector() result = sim.run(assemble(qc)).result() state = result.get_statevector() print("Qubit State = " + str(state))
Qubit State = [0. +0.70710678j 0.70710678+0.j ]

큐비트가 예상했던 대로 [0.+0.70710678j 0.70710678+0.j] 상태로 초기화된 것을 볼 수 있습니다.

이제 이 큐비트를 측정할 회로를 만들어 봅시다.

qc = QuantumCircuit(1) # qc를 정의합니다. initial_state = [0.+1.j/sqrt(2),1/sqrt(2)+0.j] qc.initialize(initial_state, 0) qc.measure_all() qc.save_statevector() qc.draw()
Image in a Jupyter notebook

전체 회로를 돌려보면, 계수가 언제나 0임을 확인할 수 있습니다.

qobj = assemble(qc) state = sim.run(qobj).result().get_statevector() print("State of Measured Qubit = " + str(state))
State of Measured Qubit = [0.+1.j 0.+0.j]

이 셀을 여러번 다시 돌려서 큐비트를 다시 초기화하고 측정하는 것을 반복할 수 있습니다. 0과 1, 어떤 출력도 가능하지만 큐비트의 상태가 0|0\rangle1|1\rangle의 중첩은 아닐 것입니다. 재미있게도, 상태 0|0\rangle의 글로벌 위상은 살아있지만 글로벌 위상이기 때문에 우리가 이것을 실제 양자 컴퓨터에서 측정하는 것은 불가능합니다.

양자 시뮬레이터에 대한 주의사항

지금까지 큐비트의 상태를 표현하는 데에는 2개의 복소수가 필요하다는 것을 배웠습니다. 그러나 실제 양자 컴퓨터를 사용할 때는 각각의 큐비트에 대해 오직 예 혹은 아니오 (0 또는 1)만을 답으로 얻을 수 있습니다. 10-큐비트 양자 컴퓨터의 출력은 아래와 같이 생겼을 것입니다.

0110111110

여기에는 어떤 중첩도 복소수 계수도 없이 오직 10개의 비트뿐입니다. 실제 양자 컴퓨터를 사용할 때는 계산 중인 큐비트의 중간 상태를 확인할 수 없는데, 그 행위가 큐비트를 붕괴시키기 때문입니다! 이러한 현상은 학습에는 그다지 이상적이지 않습니다. 따라서 Qiskit은 조금 다른 형태의 양자 시뮬레이터를 제공합니다. 기본적으로 aer_simulator는 실제 양자 컴퓨터의 실행 과정을 따라 하지만, 회로에 특정 명령어를 포함함으로써 측정 전에 양자 상태를 저장해둘 수 있습니다. 예를 들어, 여기서 우리는 .save_statevector() 명령어를 포함시킴으로써 시뮬레이션의 결과에 .get_statevector()를 사용할 수 있게 만들었습니다.

3. 블로흐 구

3.1 제한된 큐빗 상태

우리는 이 장의 앞부분에서 큐비트(q|q\rangle)의 일반적인 상태가 다음과 같은 것을 보았습니다.

q=α0+β1|q\rangle = \alpha|0\rangle + \beta|1\rangleα,βC\alpha, \beta \in \mathbb{C}

(두 번째 줄은 α\alphaβ\beta가 복소수임을 알려줍니다.) 섹션 2의 처음 두 가지 의미는 이러한 상태 중 일부를 구별할 수 없음을 알려줍니다. 이것은 큐비트에 대한 설명에서 더 구체적일 수 있음을 의미합니다.

첫째, 글로벌 위상을 측정할 수 없으므로 0|0\rangle1|1\rangle 상태 간의 위상 차이만 측정할 수 있습니다. α\alphaβ\beta를 복잡하게 만드는 대신, 우리는 그것들을 실수로 한정하고 그들 사이의 상대적 위상을 알려주는 항을 추가할 수 있습니다:

q=α0+eiϕβ1|q\rangle = \alpha|0\rangle + e^{i\phi}\beta|1\rangleα,β,ϕR\alpha, \beta, \phi \in \mathbb{R}

마지막으로 큐비트 상태를 정규화해야 하므로

α2+β2=1\sqrt{\alpha^2 + \beta^2} = 1

삼각 함수의 특성을 사용할 수 있습니다.

sin2x+cos2x=1\sqrt{\sin^2{x} + \cos^2{x}} = 1

이때, 실수 α\alphaβ\beta를 다음과 같이 하나의 변수 θ\theta로 표현할 수 있습니다.

α=cosθ2,β=sinθ2\alpha = \cos{\tfrac{\theta}{2}}, \quad \beta=\sin{\tfrac{\theta}{2}}

이로부터 임의의 큐비트의 상태를 두 개의 변수 ϕ\phiθ\theta를 사용하여 표현할 수 있게 되었습니다.

q=cosθ20+eiϕsinθ21|q\rangle = \cos{\tfrac{\theta}{2}}|0\rangle + e^{i\phi}\sin{\tfrac{\theta}{2}}|1\rangleθ,ϕR\theta, \phi \in \mathbb{R}

3.2 큐비트 상태 시각화

다음과 같은 일반적인 큐비트의 상태를 시각적으로 표현하고 싶습니다.

q=cosθ20+eiϕsinθ21|q\rangle = \cos{\tfrac{\theta}{2}}|0\rangle + e^{i\phi}\sin{\tfrac{\theta}{2}}|1\rangle

θ\thetaϕ\phi를 구면좌표계로 해석하면 (큐비트의 상태의 크기는 11이므로 r=1r = 1입니다), 하나의 큐비트 상태는 블로흐 구이라고 알려진 구 위에 그릴 수 있습니다.

아래에 +|{+}\rangle 상태에 있는 큐비트를 그려보았습니다. 이 경우에는 θ=π/2\theta = \pi/2이고, ϕ=0\phi = 0입니다.

(Qiskit에는 블로흐 구를 그릴 수 있는 함수 plot_bloch_vector()가 있지만, 이 글의 작성 시점에는 직각 좌표계만을 사용할 수 있습니다. 좌표계 변환을 자동으로 해주는 함수를 포함해두었습니다).

블로흐 구 데모에서도 확인해볼 수 있습니다.

from qiskit_textbook.widgets import plot_bloch_vector_spherical coords = [pi/2,0,1] # [Theta, Phi, Radius] plot_bloch_vector_spherical(coords) # 구면 좌표계로 표현된 블로흐 벡터
Image in a Jupyter notebook

주의!

큐비트 상태에 대해 처음 배울 때 큐비트 상태 벡터와 블로흐 벡터 를 혼동하기 쉽습니다. 상태 벡터는 큐비트가 있을 수 있는 두 가지 상태의 진폭을 유지하는 1.1 에서 논의된 벡터임을 기억하십시오. 블로흐 벡터는 2D의 복잡한 상태 벡터를 실제 3D 공간에 매핑하는 시각화 도구입니다.

간단한 연습

plot_bloch_vector() 또는 plot_bloch_sphere_spherical() 을 사용하여 아래 상태의 큐비트를 그립니다.

  1. 0 |0\rangle

  2. 1 |1\rangle

  3. 12(0+1)\tfrac{1}{\sqrt{2}}(|0\rangle + |1\rangle)

  4. 12(0i1)\tfrac{1}{\sqrt{2}}(|0\rangle - i|1\rangle)

  5. ParseError: KaTeX parse error: Undefined control sequence: \1 at position 36: …begin{bmatrix}i\̲1̲\end{bmatrix}

또한 plot_bloch_vector() 와 함께 사용하기 위해 구면좌표계에서 데카르트 좌표계로 변환하는 위젯을 아래에 포함했습니다.

from qiskit_textbook.widgets import bloch_calc bloch_calc()
import qiskit.tools.jupyter %qiskit_version_table