Korean
언어
English
Bengali
French
German
Japanese
Korean
Portuguese
Spanish
Tamil

참고

이 페이지는 tutorials/textbook/01_IQPE.ipynb 에서 생성되었다.

반복 양자 위상 추정 알고리즘 (IQPE)

이 튜토리얼의 목표는 Iterative Phase Estimation (IPE, 반복 위상 추정) 알고리즘이 어떻게 작동되는지, 왜 우리가 QPE (Quantum Phase Estimation) 가 아니라 IPE 알고리즘을 사용해야 하는지, 그리고 어떻게 Qiskit을 사용해서 이 알고리즘을 생성할 수 있는지를 이해하는 것이다. 이 알고리즘을 생성할 때에는 초기화 게이트와 c_if 메서드를 포함한 회로를 사용하면 되는데, 이 c_if 메서드는 이전의 측정들에서 비롯된 고전 레지스터에 저장된 값들로 조절된 게이트들을 적용할 수 있게 한다.

참조

[1]:
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute, assemble, Aer
from qiskit.tools.visualization import plot_histogram
from math import pi
import matplotlib.pyplot as plt

조건부 게이트: c_if 메소드

IPE 알고리즘을 시작하기 전에, IPE 회로를 만들어 내는 Qiskit 조건부 메서드 c_if에 관한 간단한 튜토리얼을 제공할 것이다.

(사실상 게이트 클래스의 메서드인) c_if 는 고전 레지스터에 저장된 값을 기반으로 조건부 연산을 하는 함수이다. 이 기능으로 회로의 측정 이후에 측정 결과를 조건부로 가지는 게이트를 적용할 수 있다.

예를 들어, 다음의 코드는 고전 레지스터의 값이 \(0\) 인 경우에 \(X\) 게이트를 실행한다.

[2]:
q = QuantumRegister(1,'q')
c = ClassicalRegister(1,'c')
qc = QuantumCircuit(q, c)
qc.h(0)
qc.measure(0,0)
qc.x(0).c_if(c, 0)
qc.draw(output='mpl')
[2]:
../../_images/tutorials_textbook_01_IQPE_4_0.png

강조할만한 것은 메서드 c_if는 하나의 고전 비트 (또는 고전 비트의 리스트) 가 아닌, 전체 고전 레지스터를 첫 번째 인수로 가지고, 하나의 비트값 0 또는 1 (또는 이진수 리스트/문자열) 이 아닌 (음수가 아닌) 십진수 표현 값을 두 번째 인수로 가질 것으로 기대한다는 것이다.

Let’s make another example. Consider that we want to perform a bit flip on the third qubit after the measurements in the following circuit, when the results of the measurement of \(q_0\) and \(q_1\) are both \(1\).

[3]:
q = QuantumRegister(3,'q')
c = ClassicalRegister(3,'c')
qc = QuantumCircuit(q, c)
qc.h(q[0])
qc.h(q[1])
qc.h(q[2])
qc.barrier()
qc.measure(q,c)
qc.draw('mpl')
[3]:
../../_images/tutorials_textbook_01_IQPE_6_0.png

\(q_0\)\(q_1\) 의 측정 결과값이 모두 \(1\) 인 경우에만 \(X\) 게이트를 적용하고자 한다. c_if에 인수로 전달된 값에 따라 \(X\) 의 적용을 조정하는 c_if 메서드를 사용하여 이 작업을 수행할 수 있다.

\(q_2\) 가 무엇으로 측정되는지는 중요하지 않기 때문에 (이진 표현에서) 011 및 111의 값을 확인하도록 c_if 메서드에 전달될 값을 암호화해야 한다.

두 정수 값의 십진수 표현은 다음과 같다:

5387debd31bf4040b0905b63cfeecf40

Python의 bin() 메서드를 통해 답을 확인할 수 있다 (접두어 0b 는 이진수 형식을 나타낸다).

[4]:
print(bin(3))
print(bin(7))
0b11
0b111

그러므로 값 011 and 111 각각에 해당하도록 \(q_2\)\(X\) 를 두 번 적용해야 한다.

[5]:
q = QuantumRegister(3,'q')
c = ClassicalRegister(3,'c')
qc = QuantumCircuit(q, c)
qc.h(0)
qc.h(1)
qc.h(2)
qc.barrier()
qc.measure(q,c)

qc.x(2).c_if(c, 3) # for the 011 case
qc.x(2).c_if(c, 7) # for the 111 case

qc.draw(output='mpl')
[5]:
../../_images/tutorials_textbook_01_IQPE_12_0.png

IPE

The motivation for using the IPE algorithm is that QPE algorithm works fine for short depth circuits but when the circuit starts to grow, it doesn’t work properly due to gate noise and decoherence times.

알고리즘이 어떻게 동작하는지에 대한 자세한 설명은 Iterative Phase Estimation (IPE, 반복 위상 추정) 알고리즘 에서 찾을 수 있다. QPE를 심도 있게 이해하려면 Ch.3.6 Quantum Phase Estimation (양자 위상 추정) 에서 볼 수 있다.

\(U\) 에 대한 1-큐비트 게이트의 IPE 예제

1-큐비트 연산자 \(U\) 의 위상을 추정하고자 IPE 알고리즘을 적용하고자 한다. 예를 들어, 여기서는 \(S\)-게이트를 사용한다.

Let’s apply the IPE algorithm to estimate the phase for \(S\)-gate. Its matrix is

\[\begin{split} S = \begin{bmatrix} 1 & 0\\ 0 & e^\frac{i\pi}{2}\\ \end{bmatrix}\end{split}\]

이 말은 \(S\)-게이트는 \(|1\rangle\) 상태에 위상 \(\pi/2\) 을 더하고, \(|0\rangle\) 상태의 위상은 변화시키지 않는다

\[S|1\rangle = e^\frac{i\pi}{2}|1\rangle\]

다음부터는 랩 4의 2절 의 표기 및 용법을 사용한다.

Let’s consider to estimate the phase \(\phi=\frac{\pi}{2}\) for the eigenstate \(|1\rangle\), we should find \(\varphi=\frac{1}{4}\) (where \(\phi = 2 \pi \varphi\)). Therefore to estimate the phase we need exactly 2 phase bits, i.e. \(m=2\), since \(1/2^2=1/4\). So \(\varphi=0.\varphi_1\varphi_2\).

IPE 알고리즘에서 \(m\) 은 반복 횟수이기도 한 점을 기억하라. 따라서 \(2\) 번의 반복 또는 단계가 필요하다.

먼저 회로를 초기화한다. IPE는 QPE 알고리즘에서 \(m\) 개의 카운팅 큐비트 (counting qubit) 대신, 1개의 보조 큐비트로 동작한다. 그러므로 1개의 보조 큐비트와 1개의 \(U\)-게이트의 고유 상태인 총 2개의 큐비트와 위상 비트 \(\varphi_1\), \(\varphi_2\) 를 위한 고전 레지스터 2 비트가 필요하다.

[6]:
nq = 2
m = 2
q = QuantumRegister(nq,'q')
c = ClassicalRegister(m,'c')

qc_S = QuantumCircuit(q,c)

첫 번째 단계

첫 번째 단계로써 만들 양자 회로, 즉 첫 번째 반복 알고리즘은 최하위 위상 비트 \(\varphi_m\) 를 추정하는 것이다. 여기서는 \(\varphi_2\) 이다. 첫 번째 단계는 3개의 하위 단계로 나눠진다: - 초기화 - Controlled-\(U\) 게이트의 적용 - x 축 기반의 보조 큐비트의 측정

초기화

초기화는 Hadamard 게이트를 보조 큐비트에 적용하는 것과 고유 상태 \(|1\rangle\) 를 준비하는 것으로 구성되어 있다.

[7]:
qc_S.h(0)
qc_S.x(1)
qc_S.draw('mpl')
[7]:
../../_images/tutorials_textbook_01_IQPE_16_0.png

Controlled-\(U\) 게이트의 적용

그러면 Controlled-\(U\) 연산자들을 \(2^t\) 번 적용해야 한다 (문서 두 큐비트 게이트 를 참조하라). 여기서는 Controlled-\(S\) 게이트 (줄여서 \(CS\)) 를 적용한다.

\(CS\) 를 회로에 구현하기 위해선, \(S\) 가 위상 게이트이므로 제어 위상 게이트 \(\text{CP}(\theta)\)\(\theta=\pi/2\) 인 경우를 사용할 수 있다.

[8]:
cu_circ = QuantumCircuit(2)
cu_circ.cp(pi/2,0,1)
cu_circ.draw('mpl')
[8]:
../../_images/tutorials_textbook_01_IQPE_18_0.png

Let’s apply \(2^t\) times \(\text{CP}(\pi/2)\). Since for the first step \(t=m-1\), and \(m=2\), we have \(2^t=2\).

[9]:
for _ in range(2**(m-1)):
    qc_S.cp(pi/2,0,1)
qc_S.draw('mpl')
[9]:
../../_images/tutorials_textbook_01_IQPE_20_0.png

x 기저로 측정

마지막으로, 보조 큐비트를 x 기저에서 측정한다. 따라서 x_measure를 수행하는 함수를 정의하고 적용한다.

[10]:
def x_measurement(qc, qubit, cbit):
    """Measure 'qubit' in the X-basis, and store the result in 'cbit'"""
    qc.h(qubit)
    qc.measure(qubit, cbit)

이 방법으로 위상 비트 \(\varphi_2\) 를 얻고 이를 고전 비트 \(c_0\) 에 저장할 수 있다.

[11]:
x_measurement(qc_S, q[0], c[0])
qc_S.draw('mpl')
[11]:
../../_images/tutorials_textbook_01_IQPE_24_0.png

다음 단계(2번째 단계)

이제 남은 단계들을 위한 양자 회로를 만들어 보자. 이 예에서는 두 번째 단계만을 다룬다. 이 단계는 다음의 4개의 하위 단계가 포함된다: 첫 번째 단계와 같은 3개의 하위 단계와 그 중간의 위상 보정을 위한 추가 단계 - 재설정을 포함한 초기화 - 위상 보정 - Controlled-\(U\) 게이트 적용 - 보조 큐비트의 x 축 측정으로 구성된다.

재설정을 통한 초기화

동일한 회로에서 반복적 알고리즘을 수행하려는 경우, 측정 게이트 이후에 보조 큐비트 \(q0\) 를 재설정하고 이전처럼 다시 초기화하여 큐비트를 재활용해야 한다.

[12]:
qc_S.reset(0)
qc_S.h(0)
qc_S.draw('mpl')
[12]:
../../_images/tutorials_textbook_01_IQPE_26_0.png

위상 보정(2단계를 위한)

As seen in the theory, in order to extract the phase bit \(\varphi_{1}\), we perform a phase correction of \(-\pi\varphi_2/2\). Of course, we need to apply the phase correction in the circuit only if the phase bit \(\varphi_2=1\), i.e. we have to apply the phase correction of \(-\pi/2\) only if the classical bit \(c_0\) is 1.

따라서 재설정 후에는 c_if 매서드를 사용한 고전 비트 \(c_0\) (\(=\varphi_2\)) 로 조절된 위상 \(\theta=-\pi/2\) 를 사용하여 위상 게이트 \(P(\theta)\) 를 적용한다. 이 튜토리얼의 첫 번째 부분에서는 값이 1인 c_if 매서드를 \(1_{10} = 001_{2}\) 로 사용해야 한다(아래에 기입한 \(_{10}\)\(_2\) 은 십진수 및 이진수를 나타냄).

[13]:
qc_S.p(-pi/2,0).c_if(c,1)
qc_S.draw('mpl')
[13]:
../../_images/tutorials_textbook_01_IQPE_28_0.png

Controlled-\(U\) 게이트 및 x-측정의 적용 (2단계의 과정)

첫 단계에서 그랬던 것처럼 \(CU\) 연산을 적용한다. 두 번째 단계에는 \(t=m-2\) 이고, 따라서 \(2^t=1\) 이다. 그래서 우리는 \(\text{CP}(\pi/2)\) 를 한 번 적용한다. 그런 다음 큐비트 \(q_0\) 의 x 측정을 수행하여 결과, 위상 비트 \(\varphi_1\) 를 고전적 레지스터의 비트 \(c_1\) 에 저장한다.

[14]:
## 2^t c-U operations (with t=m-2)
for _ in range(2**(m-2)):
    qc_S.cp(pi/2,0,1)

x_measurement(qc_S, q[0], c[1])

마침내! 최종회로가 완성되었다.

[15]:
qc_S.draw('mpl')
[15]:
../../_images/tutorials_textbook_01_IQPE_32_0.png

Let’s execute the circuit with the qasm_simulator, the simulator without noise that run locally.

[16]:
sim = Aer.get_backend('qasm_simulator')
count0 = execute(qc_S, sim).result().get_counts()

key_new = [str(int(key,2)/2**m) for key in list(count0.keys())]
count1 = dict(zip(key_new, count0.values()))

fig, ax = plt.subplots(1,2)
plot_histogram(count0, ax=ax[0])
plot_histogram(count1, ax=ax[1])
plt.tight_layout()

그림에서 히스토그램은 동일하지만 왼쪽에는 x축에 위상 비트 \(\varphi_1\) , \(\varphi_2\) 가 있는 문자열이 있고 오른쪽에는 10진수 표시의 실제 위상 \(\varphi\) 가 있다.

예상했던 대로 \(100\%\) 확률로 \(\varphi=\frac{1}{4}=0.25\) 를 찾았다.

2-큐비트 게이트를 갖는 IPE의 예제

Now, we want to apply the IPE algorithm to estimate the phase for a 2-qubit gate \(U\). For this example, let’s consider the controlled version of the \(T\) gate, i.e. the gate \(U=\textrm{Controlled-}T\) (that from now we will express more compactly with \(CT\)). Its matrix is

\[\begin{split} CT = \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & e^\frac{i\pi}{4}\\ \end{bmatrix}\end{split}\]

즉, \(CT\) 게이트는 상태 \(|11\rangle\) 에 위상 \(\pi/4\) 를 더하며, 다른 계산 기저 상태들 \(|00\rangle\), \(|01\rangle\), \(|10\rangle\) 의 위상은 변경되지 않는다.

Let’s consider to estimate the phase \(\phi=\pi/4\) for the eigenstate \(|11\rangle\), we should find \(\varphi=1/8\), since \(\phi = 2 \pi \varphi\). Therefore to estimate the phase we need exactly 3 classical bits, i.e. \(m=3\), since \(1/2^3=1/8\). So \(\varphi=0.\varphi_1\varphi_2\varphi_3\).

1큐비트 \(U\) 연산자의 예와 마찬가지로 동일한 단계를 거치지만 이번에는 \(m=3\) 이라서 \(3\) 단계를 거치게 되며 모든 설명을 반복하지는 않을 것이다. 자세한 내용은 위의 1큐비트 \(U\) 게이트 예를 참조하자.

먼저, 3개의 큐비트 (보조 큐비트용 1개 및 2-큐비트 게이트용 2개)와 위상 비트 \(\varphi_1\), \(\varphi_2\), \(\varphi_3\) 를 저장하는 3개의 고전 비트로 회로를 초기화한다.

[17]:
nq = 3    # number of qubits
m = 3    # number of classical bits
q = QuantumRegister(nq,'q')
c = ClassicalRegister(m,'c')

qc = QuantumCircuit(q,c)

첫 번째 단계

이제 최하위 위상 비트 \(\varphi_m=\varphi_3\) 를 추정하기 위해 첫 번째 단계로 양자 회로를 구축한다.

초기화

고유 상태 \(|11\rangle\) 로 보조 큐비트와 다른 큐비트들을 초기화한다.

[18]:
qc.h(0)
qc.x([1,2])
qc.draw('mpl')
[18]:
../../_images/tutorials_textbook_01_IQPE_39_0.png

Controlled-\(U\) 게이트의 적용

그런 다음 \(CU\) 연산자를 여러 번 적용해야 한다. 이 예에서는 Controlled-\(CT\) 게이트(줄여서 \(CCT\)) 이다.

\(CCT\) 를 회로에 구현할 때, \(T\) 가 위상 게이트이므로 다중 제어 위상 게이트 \(\text{MCP}(\theta)\)\(\theta=\pi/4\) 를 함께 사용한다.

[19]:
cu_circ = QuantumCircuit(nq)
cu_circ.mcp(pi/4,[0,1],2)
cu_circ.draw('mpl')
[19]:
../../_images/tutorials_textbook_01_IQPE_41_0.png

Let’s apply \(2^t\) times \(\text{MCP}(\pi/4)\). Since for the first step \(t=m-1\) and \(m=3\), we have \(2^t=4\).

[20]:
for _ in range(2**(m-1)):
    qc.mcp(pi/4,[0,1],2)
qc.draw('mpl')
[20]:
../../_images/tutorials_textbook_01_IQPE_43_0.png

x 기저로 측정

마지막으로 보조 큐비트의 측정을 x-basis로 수행한다. 1-큐비트 게이트의 예에서 위에 정의된 x_measurement 함수를 사용할 수 있다. 이 방법으로 얻어진 위상 비트 \(\varphi_3\) 는 고전 비트 \(c_0\) 에 저장된다.

[21]:
x_measurement(qc, q[0], c[0])
qc.draw('mpl')
[21]:
../../_images/tutorials_textbook_01_IQPE_45_0.png

다음 단계(2번째, 3번째)

이제 나머지 단계, 즉 두 번째 단계와 세 번째 단계를 위한 양자 회로를 구축한다. 첫 번째 예에서 말했듯이 이 단계에는 위상 보정의 추가 하위 단계가 있다.

재설정을 통한 초기화

[22]:
qc.reset(0)
qc.h(0)
qc.draw('mpl')
[22]:
../../_images/tutorials_textbook_01_IQPE_47_0.png

위상 보정(2단계를 위한)

위상 비트 \(\varphi_{2}\) 를 추출하기 위해 \(-\pi\varphi_3/2\) 의 위상 보정을 실시한다.

따라서 재설정 후 고전 비트 \(c_0\) (\(=\varphi_3\)) 로 조절된 위상 \(\theta=-\pi/2\) 를 사용하여 위상 게이트 \(P(\theta)\) 를 적용한다.

[23]:
qc.p(-pi/2,0).c_if(c,1)
qc.draw('mpl')
[23]:
../../_images/tutorials_textbook_01_IQPE_49_0.png

Controlled-\(U\) 게이트 및 x-측정의 적용 (2단계의 과정)

첫 단계에서 그랬던 것처럼 \(CU\) 연산을 적용한다. 두 번째 단계에는 \(t=m-2\) 가 있고, 따라서 \(2^t=2\) 이다. 그래서 우리는 \(\text{MCP}(\pi/4)\)\(2\) 번 적용한다. 그런 다음 큐비트 \(q_0\) 의 x 측정을 수행하여 결과, 위상 비트 \(\varphi_2\) 를 비트 \(c_1\) 에 저장한다.

[24]:
for _ in range(2**(m-2)):
    qc.mcp(pi/4,[0,1],2)
x_measurement(qc, q[0], c[1])
qc.draw('mpl')
[24]:
../../_images/tutorials_textbook_01_IQPE_51_0.png

세 번째 단계의 모든 하위 단계

세 번째 및 마지막 단계의 경우 두 번째 단계에서 수행된 대로 보조 큐비트의 재설정 및 초기화를 수행한다.

그런 다음 세 번째 단계에서 \(-2\pi 0.0\varphi_{2}\varphi_{3}= -2\pi \left(\frac{\varphi_2}{4}+\frac{\varphi_3}{8}\right)=-\frac{\varphi_2\pi}{2}-\frac{ \varphi_3\pi}{4}\) 의 위상 보정을 수행해야 한다. 따라서 두 개의 조건부 위상 보정을 적용해야 하는데, 하나는 \(\varphi_3\) (\(=c_0\)) 에 의해 적용된 것이고, 다른 하나는 \(\varphi_2\) (\(=c_1\)) 에 의해 적용된 것이다. 이를 위해서는 다음과 같이 실행한다: - 게이트 \(P(-\pi/4)\)\(c=001\) (c 값이 \(1\)) 일 때 \(c_0=1\) 로 적용된다. - 게이트 \(P(-\pi/2)\)\(c=010\) (c 값이 \(2\)) 일 때 \(c_1=1\) 로 적용된다. - 게이트 \(P(-3\pi/4)\)\(c=011\) (c 값이 \(3\)) 일 때 \(c_1=1\)\(c_0=1\) 로 적용된다.

다음으로 \(CU\) 연산자: \(\text{MCP}(\pi/4)\) 게이트를 \(2^t\) 번 적용하고 3단계 \(t=m-3=0\) 에서는 게이트를 한 번만 적용한다.

[25]:
# initialization of qubit q0
qc.reset(0)
qc.h(0)

# phase correction
qc.p(-pi/4,0).c_if(c,1)

qc.p(-pi/2,0).c_if(c,2)
qc.p(-3*pi/4,0).c_if(c,3)

# c-U operations
for _ in range(2**(m-3)):
    qc.mcp(pi/4,[0,1],2)

# X measurement
qc.h(0)
qc.measure(0,2)

qc.draw('mpl')
[25]:
../../_images/tutorials_textbook_01_IQPE_53_0.png

이제 잡음 없이 시뮬레이터로 회로를 실행한다.

[26]:
count0 = execute(qc, sim).result().get_counts()

key_new = [str(int(key,2)/2**m) for key in list(count0.keys())]
count1 = dict(zip(key_new, count0.values()))

fig, ax = plt.subplots(1,2)
plot_histogram(count0, ax=ax[0])
plot_histogram(count1, ax=ax[1])
fig.tight_layout()

예상대로 \(100\%\) 확률로 \(\varphi=0.125\), 즉 \(1/8\) 를 찾을 수 있게 되었다.

[27]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
/opt/miniconda3/envs/qiskit/lib/python3.9/site-packages/qiskit/aqua/operators/operator_globals.py:48: DeprecationWarning: `from_label` is deprecated and will be removed no earlier than 3 months after the release date. Use Pauli(label) instead.
  X = make_immutable(PrimitiveOp(Pauli.from_label('X')))

Version Information

Qiskit SoftwareVersion
Qiskit0.24.1
Terra0.17.3
Aer0.7.6
Ignis0.5.2
Aqua0.8.2
IBM Q Provider0.13.1
System information
Python3.9.5 (default, May 18 2021, 12:31:01) [Clang 10.0.0 ]
OSDarwin
CPUs4
Memory (Gb)16.0
Fri Jul 02 06:38:27 2021 EDT

This code is a part of Qiskit

© Copyright IBM 2017, 2021.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.