Korean
언어
English
Japanese
German
Korean
Portuguese, Brazilian
French
Shortcuts

참고

이 페이지는 tutorials/circuits/1_getting_started_qiskit.ipynb 에서 생성되었다.

IBM 퀀텀 랩 에서 대화식으로 실행하시오.

키스킷 시작하기

여기에서는, 키스킷 프로그래밍의 개요를 제공한다. 키스킷의 기본 패키지는 양자 컴퓨터 프로그래밍에 필요한 기본 구성 요소를 제공하는 테라다. 키스킷의 기본적인 내용은 quantum circuit 에서 확인할 수 있다. 키스킷을 사용하는 기본 작업 방식은 BuildExecute 의 두 단계로 구성된다. Build 는 해결 하고자 하는 문제를 표현하는 몇 가지의 다른 양자 회로들을 만들 수 있으며, Execute 은 이 회로들을 각기 다른 후위처리 장치(Backend)에서 실행할 수 있다. 작업이 실행된 후에는 원하는 출력에 따라 데이터를 수집하고 후 처리한다.

[1]:
import numpy as np
from qiskit import *
%matplotlib inline

회로 기초

회로 만들기

첫 프로그램을 위한 기본 요소는 QuantumCircuit이며 세 개의 큐비트로 구성된 QuantumCircuit 을 만드는 것으로 시작한다.

[2]:
# Create a Quantum Circuit acting on a quantum register of three qubits
circ = QuantumCircuit(3)

레지스터를 가진 회로를 만들고 나서, 그 레지스터를 조작하기 위해 게이트 (“연산들”) 를 추가할 수 있다. 튜토리얼들을 수행해 나가면서, 더 많은 게이트와 회로를 발견하게 될 것이다. 아래에 3-큐비트 GHZ 상태를 만드는 예시가 있다.

\[|\psi\rangle = \left(|000\rangle+|111\rangle\right)/\sqrt{2}.\]

이러한 상태를 만들기 위해서는 우선 세개의 큐비트로 구성된 양자 레지스터를 구성한다. 기본적으로 레지스터의 각 큐비트는 \(|0\rangle\) 로 초기화된다. GHz 상태를 만들기 위해 다음 게이트를 적용한다: - 큐비트 0을 중첩상태 \(\left(|0\rangle+|1\rangle\right)/\sqrt{2}\) 로 만들어 주는 하다마드 게이트 \(H\) 를 큐비트 0에 적용하고, 제어된 반전 게이트(Controlled Not Gate)를 큐비트 0과 큐비트 1에, 다시 제어된 반전 게이트 (Controlled Not)을 큐비트 0과 큐비트 2에 적용한다.삼-큐비트

이상적인 양자 컴퓨터에서는 이 회로에 의해 만들어진 상태는 위에 생성된 GHZ 상태이다.

키스킷에서는 아래와 같이 연산을 회로에 하나씩 추가 할 수 있다.

[3]:
# Add a H gate on qubit 0, putting this qubit in superposition.
circ.h(0)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting
# the qubits in a Bell state.
circ.cx(0, 1)
# Add a CX (CNOT) gate on control qubit 0 and target qubit 2, putting
# the qubits in a GHZ state.
circ.cx(0, 2)
[3]:
<qiskit.circuit.instructionset.InstructionSet at 0x2452282f708>

회로 가시화하기

키스킷의 QuantumCircuit.draw() 를 사용하여 회로를 시각화 할 수 있으며. 여러 교재에 보여진 형태로 회로가 그려진다.

[28]:
circ.draw('mpl')
[28]:
../../_images/tutorials_circuits_1_getting_started_with_qiskit_7_0.png

이 회로에 있는 큐비트들은 순서 대로 배치되며 큐비트 0은 위쪽에 큐비트 2는 아래쪽에 놓이게 된다. 회로는 왼쪽에서 부터 오른쪽으로 읽는다 (가장 왼쪽에 배치된 게이트들이 회로에서 먼저 적용된다는 것을 의미한다)

다중 큐비트 시스템의 상태를 나타낼 때, 키스킷은 대부분의 물리 교재에서 사용되는 텐서(tensor)의 순서와는 반대 되는 순서를 사용한다. \(n\) 개의 큐비트가 있고, 큐비트 \(j\)\(Q_{j}\) 로 표시된다고 가정하자. 키스킷에서는 (기저 벡터들을 \(Q_{n-1}\otimes \cdots \otimes Q_1\otimes Q_0\) 로 표현하기 위하여) \(n^{\mathrm{th}}\) 큐비트를 텐서 곱의 가장 왼편에 위치하도록 만드는 순서체계(ordering)를 사용한다.

예를 들어, 0번째 큐비트가 상태 0이고 1번째 큐비트가 상태 0이며 2번째 큐비트가 상태 1일 때, 키스킷은 이를 \(|100\rangle\) 으로 표현하는데, 대부분의 물리 교재들에서는 \(|001\rangle\) 으로 표현한다.

이러한 표현의 차이는 다중 큐비트 연산이 매트릭스로 표현될 때 나타나게 된다. 예를 들어 큐비트 0이 제어 큐비트이고, 큐비트 1이 목표 큐비트일 때, 조절된 X (\(C_{X}\)) 연산은 키스킷에서 다음과 같이 표현된다.

\[\begin{split}C_X = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\\end{pmatrix}.\end{split}\]

키스킷 에어(Aer) 를 사용하여 회로 시뮬레이션 하기

키스킷 에어는 양자 회로 시뮬레이션을 위한 패키지이다. 시뮬레이션을 수행하기 위한 다양한 후위 처리장치들을 제공한다. 아래 예제에서는 Aer 를 (drop-in으로) 대체할 수 있는 키스킷 테라의 BasicAer 라는 (파이썬 전용) 기본 구현도 확인할 수 있다.

상태벡터 후위 처리 장치

키스킷 에어에서 가장 일반적으로 사용되는 후위 처리장치는 statevector_simulator 이다. 이 시뮬레이터는 양자 상태를 반환하는데, 이는 큐비트의 갯수가 \(n\) 일 때, \(2^n\) 의 차원을 가지는 복소수 벡터이다. (따라서 실행시 빠르게 그 크기가 늘어나기 때문에 주의해야 한다.)

위의 회로를 상태벡터 시뮬레이터를 이용하여 실행할 때, 우선 에어를 import하고 후위 처리 장치를 statevector_simulator 로 설정해야 한다.

[5]:
# Import Aer
from qiskit import Aer

# Run the quantum circuit on a statevector simulator backend
backend = Aer.get_backend('statevector_simulator')

이제 후위 처리장치 장치를 정했으니, 양자 회로를 컴파일하고 실행할 시간이다. 키스킷에서는 이를 위해 execute 함수를 제공한다. execute 는 후위처리 장치에 제출된 작업에 대한 정보를 함축하고 있는 job 객체를 되돌려 준다.

팁: 주피터(Jupyter) 에서는 위의 매개 변수들을 손쉽게 얻을 수 있다. 단순히 문자 커서(text cursor) 를 함수 위에 놓고 Shift+Tab을 누르면 된다.

[6]:
# Create a Quantum Program for execution
job = execute(circ, backend)

프로그램을 실행할 때, 작업 객체는 다음의 두 메소드 job.status()job.result() 를 가지는데, 각각은 작업의 대한 상태와 그 결과를 돌려준다.

참고: 작업은 비동기화 방식으로 실행되지만, 결과 메소드가 호출되면, 동기화 방식으로 전환되어서 다른 작업으로 옮겨가기 전에 작업이 끝날 때까지 기다리게 된다.

[7]:
result = job.result()

결과 객체는 데이터를 가지고 있으며, 키스킷은 양자 회로에 대한 상태 벡터를 돌려주는 result.get_statevector(circ) 메소드를 제공한다.

[8]:
outputstate = result.get_statevector(circ, decimals=3)
print(outputstate)
[0.707+0.j 0.   +0.j 0.   +0.j 0.   +0.j 0.   +0.j 0.   +0.j 0.   +0.j
 0.707+0.j]

또한 키스킷은 이러한 결과들을 확인할 수 있도록 시각화 도구상자를 제공한다.

Below, we use the visualization function to plot the real and imaginary components of the state density matrix \(\rho\).

[9]:
from qiskit.visualization import plot_state_city
plot_state_city(outputstate)
[9]:
../../_images/tutorials_circuits_1_getting_started_with_qiskit_20_0.png

단일 후위 장치

또한 키스킷 에어는 회로의 모든 요소가 단일 연산일 때에 작동하는 unitary_simulator 를 포함하고 있다. 이 후위 처리장치는 양자 회로에서 게이트를 나타내는 \(2^n \times 2^n\) 행렬을 계산한다.

[10]:
# Run the quantum circuit on a unitary simulator backend
backend = Aer.get_backend('unitary_simulator')
job = execute(circ, backend)
result = job.result()

# Show the results
print(result.get_unitary(circ, decimals=3))
[[ 0.707+0.j  0.707-0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j
   0.   +0.j  0.   +0.j]
 [ 0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j
   0.707+0.j -0.707+0.j]
 [ 0.   +0.j  0.   +0.j  0.707+0.j  0.707-0.j  0.   +0.j  0.   +0.j
   0.   +0.j  0.   +0.j]
 [ 0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.707+0.j -0.707+0.j
   0.   +0.j  0.   +0.j]
 [ 0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.707+0.j  0.707-0.j
   0.   +0.j  0.   +0.j]
 [ 0.   +0.j  0.   +0.j  0.707+0.j -0.707+0.j  0.   +0.j  0.   +0.j
   0.   +0.j  0.   +0.j]
 [ 0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j
   0.707+0.j  0.707-0.j]
 [ 0.707+0.j -0.707+0.j  0.   +0.j  0.   +0.j  0.   +0.j  0.   +0.j
   0.   +0.j  0.   +0.j]]

OpenQASM 후위 처리 장치

이러한 시뮬레이터들은 회로의 행렬 상태를 나타내고 이상적인 회로의 결과에 대한 정보를 주기 때문에 유용하다. 그러나 실제의 실험은 각각의 큐비트 (보통 계산적인 \(|0\rangle, |1\rangle\) 베이스로 표현되는)를 측정(measuring) 함으로서 종료 된다. 측정 없이는, 상태에 대한 정보를 얻을 수 없다. 그 이유는 측정을 통해서 양자 시스템은 고전적인 비트로 변환되기 때문이다.

예를 들어 삼-큐비트인 GHZ 상태의 각각의 큐비트를 독립적으로 측정한다고 가정해보자.

\[|\psi\rangle = (|000\rangle +|111\rangle)/\sqrt{2},\]

그리고 \(xyz\) 는 큐비트 1, 그리고 :math:`z`는 큐비트 0에 해당한다는 사실을 기억하자.

참고: 이러한 비트열 표기는 가장 중요한 비트 (MSB) 를 왼쪽에 가정 덜 중요한 비트 (LSB) 를 오른쪽에 둔다. 이는 이진 비트열을 표기하는 일반적인 순서이다. 우리는 큐비트도 이 규칙에 따라 배열한다. 따라서 MSB에 해당하는 큐비트는 0으로 인덱스 되며 이는 일반적인 텐서 곱 순서와는 다르다.

\(xyz\) 의 결과를 얻는 확률은 다음과 같이 주어진다

\[\mathrm{Pr}(xyz) = |\langle xyz | \psi \rangle |^{2}\]

그러므로 GHZ 상태에서 000 혹은 111 상태를 얻을 확률은 둘 다 1/2 이다.

측정이 포함된 회로를 시뮬레이션하기 위해서는, 원래의 회로에 측정 모듈을 추가해야 하며, 이를 위해 다른 아르 후위 처리 장치를 사용한다.

[11]:
# Create a Quantum Circuit
meas = QuantumCircuit(3, 3)
meas.barrier(range(3))
# map the quantum measurement to the classical bits
meas.measure(range(3), range(3))

# The Qiskit circuit object supports composition using
# the addition operator.
qc = circ + meas

#drawing the circuit
qc.draw()
[11]:
        ┌───┐           ░ ┌─┐
q_0: |0>┤ H ├──■────■───░─┤M├──────
        └───┘┌─┴─┐  │   ░ └╥┘┌─┐
q_1: |0>─────┤ X ├──┼───░──╫─┤M├───
             └───┘┌─┴─┐ ░  ║ └╥┘┌─┐
q_2: |0>──────────┤ X ├─░──╫──╫─┤M├
                  └───┘ ░  ║  ║ └╥┘
 c_0: 0 ═══════════════════╩══╬══╬═
                              ║  ║
 c_1: 0 ══════════════════════╩══╬═
                                 ║
 c_2: 0 ═════════════════════════╩═
                                   

이 회로는 클래식 레지스터와, 큐비트의 결과를 고전 비트에 연결하기 위한 세 개의 측정들을 추가한다.

이 회로를 시뮬레이션하기 위해서는 키스킷 에어에 있는 qasm_simulator 를 사용해야 한다. 이 회로 각각의 실행은 비트 문자열 000 혹은 111을 생성하며. 또한 비트 문자열 (예를 들어 \(\mathrm{Pr}(000)\))의 분포에 대한 통계를 얻기 위해서는 회로를 여러 번 실행해야 한다. 회로가 반복되는 횟수를 결정하기 위해서는 execute 함수에 있는 shots 키워드를 조정하면 된다.

[12]:
# Use Aer's qasm_simulator
backend_sim = Aer.get_backend('qasm_simulator')

# Execute the circuit on the qasm simulator.
# We've set the number of repeats of the circuit
# to be 1024, which is the default.
job_sim = execute(qc, backend_sim, shots=1024)

# Grab the results from the job.
result_sim = job_sim.result()

결과 객체를 얻은 후에는 get_counts(circuit) 함수를 통해서 시뮬레이션 횟수에 접근할 수 있다. 이를 통해서 지금까지 실행한 시뮬레이션의 합산된 결과값을 구할 수 있다.

[13]:
counts = result_sim.get_counts(qc)
print(counts)
{'000': 510, '111': 514}

약 50 퍼센트의 확률로 000의 결과 비트 문자열을 가진다. 또한 키스킷의 plot_histogram 함수를 통해 결과를 확인할 수 있다.

[14]:
from qiskit.visualization import plot_histogram
plot_histogram(counts)
[14]:
../../_images/tutorials_circuits_1_getting_started_with_qiskit_32_0.png

예측 값인 확률 \(\mathrm{Pr}(000)\)\(\mathrm{Pr}(111)\) 는 유효 카운트를 모두 더한 후에 (회로가 몇 번 실행되었는지를 의미하는) 시뮬레이션 숫자로 나누어서 계산된다. execute 함수에 있는 shots 키워드를 수정해 보면서 예측 확률 값이 어떻게 변하는지 살펴보자.

[32]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
Qiskit0.14.0
Terra0.11.0
Aer0.3.4
Ignis0.2.0
Aqua0.6.1
IBM Q Provider0.4.4
System information
Python3.7.4 (default, Aug 9 2019, 18:34:13) [MSC v.1915 64 bit (AMD64)]
OSWindows
CPUs2
Memory (Gb)7.9987335205078125
Tue Dec 10 15:25:10 2019 Eastern Standard Time

This code is a part of Qiskit

© Copyright IBM 2017, 2019.

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.