<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Qiskit on kenji.blog</title><link>http://kenji.blog/ko/tags/qiskit/</link><description>Recent content in Qiskit on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ko</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 20:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ko/tags/qiskit/index.xml" rel="self" type="application/rss+xml"/><item><title>Qiskit을 사용한 양자 프로그래밍 초입문</title><link>http://kenji.blog/ko/p/qiskit-quantum-programming-intro/</link><pubDate>Fri, 11 Sep 2026 20:00:00 +0900</pubDate><guid>http://kenji.blog/ko/p/qiskit-quantum-programming-intro/</guid><description>&lt;img src="http://kenji.blog/p/qiskit-quantum-programming-intro/img/eyecatch.jpg" alt="Featured image of post Qiskit을 사용한 양자 프로그래밍 초입문" />&lt;h2 id="1-시작하며">1. 시작하며
&lt;/h2>&lt;p>현대의 컴퓨터(고전 컴퓨터)는 우리의 삶을 극적으로 변화시켰고, 고도의 계산 능력으로 사회의 모든 측면을 지탱하고 있습니다. 그러나 일부 특정 문제(예를 들어, 거대한 수의 소인수분해, 복잡한 분자 구조의 시뮬레이션, 최적화 문제 등)에 있어서는 현재 최첨단 슈퍼컴퓨터라 하더라도 우주의 나이보다 더 긴 시간이 필요할 수 있음이 알려져 있습니다.&lt;/p>
&lt;p>이러한 &amp;lsquo;고전 컴퓨터의 한계&amp;rsquo;를 뛰어넘을 가능성을 비장하고 있는 것이 **양자 컴퓨터(Quantum Computer)**입니다. 양자역학의 신비한 성질(중첩이나 양자 얽힘)을 계산 자원으로 활용함으로써 특정 문제를 극적으로 고속화할 수 있을 것으로 생각됩니다.&lt;/p>
&lt;p>본 기사에서는 IBM이 오픈소스로 제공하는 양자 컴퓨팅 프레임워크인 **Qiskit(키스킷)**을 사용하여 양자 프로그래밍의 세계로 첫걸음을 내딛습니다. 물리나 수학의 기초부터 친절하게 해설하고, 실제로 Python으로 코드를 작성하여 시뮬레이터 상에서 양자 회로를 구동하기까지의 프로세스를 망라한 매우 상세한 입문 가이드입니다.&lt;/p>
&lt;hr>
&lt;h2 id="2-양자-계산을-지탱하는-물리와-수학의-기초">2. 양자 계산을 지탱하는 물리와 수학의 기초
&lt;/h2>&lt;p>양자 프로그래밍을 이해하기 위해서는 먼저 양자역학의 기본적인 개념을 이해할 필요가 있습니다. 여기서는 양자 비트, 중첩, 양자 얽힘이라는 3가지 중요한 기둥에 대해 해설합니다.&lt;/p>
&lt;h3 id="21-고전-비트와-양자-비트qubit">2.1 고전 비트와 양자 비트(Qubit)
&lt;/h3>&lt;p>고전 컴퓨터의 정보 단위는 &amp;lsquo;비트(Bit)&amp;lsquo;입니다. 비트는 항상 &lt;code>0&lt;/code> 또는 &lt;code>1&lt;/code> 중 하나의 상태를 취합니다.&lt;/p>
&lt;p>반면, 양자 컴퓨터 정보의 최소 단위는 **양자 비트(Qubit: Quantum bit)**라고 불립니다. 양자 비트는 &lt;code>0&lt;/code>과 &lt;code>1&lt;/code>의 상태를 취할 수 있을 뿐만 아니라, &lt;strong>그 두 가지 상태를 동시에 유지하는&lt;/strong> 것이 가능합니다.&lt;/p>
&lt;p>수학적으로 양자 비트의 상태 $|\psi\rangle$는 기저 상태 $|0\rangle$과 $|1\rangle$의 선형 결합(중첩)으로 표현됩니다.&lt;/p>
$$
|\psi\rangle = \alpha|0\rangle + \beta|1\rangle
$$
&lt;p>여기서 $\alpha$와 $\beta$는 복소수이며, 각각 상태 $|0\rangle$과 $|1\rangle$이 관측될 확률 진폭을 나타냅니다. 양자역학의 기본 원리에 따라 확률의 합은 1이 되어야 하므로 다음의 규격화 조건을 만족합니다.&lt;/p>
$$
|\alpha|^2 + |\beta|^2 = 1
$$
&lt;p>즉, 이 양자 비트를 &amp;lsquo;측정(관측)&amp;lsquo;했을 때 $|0\rangle$을 얻을 확률은 $|\alpha|^2$, $|1\rangle$을 얻을 확률은 $|\beta|^2$가 됩니다. 측정 전에는 상태가 확률적으로만 결정되어 있다는 점이 고전 비트와의 결정적인 차이입니다.&lt;/p>
&lt;div class="mermaid">graph LR
A["고전 비트 (Classical Bit)"] --> B["확정된 상태: 0 또는 1"]
C["양자 비트 (Qubit)"] --> D["중첩: 0과 1 양쪽 모두"]
D --> E["측정에 의해 확률적으로 상태가 확정"]&lt;/div>
&lt;h3 id="22-중첩superposition">2.2 중첩(Superposition)
&lt;/h3>&lt;p>앞서 언급했듯이, $|0\rangle$과 $|1\rangle$의 상태가 섞여 있는 상태를 **중첩(Superposition)**이라고 부릅니다.&lt;/p>
&lt;p>예를 들어, 1개의 양자 비트가 완전히 균등한 중첩 상태에 있을 경우 $\alpha = \frac{1}{\sqrt{2}}$, $\beta = \frac{1}{\sqrt{2}}$가 됩니다.&lt;/p>
$$
|\psi\rangle = \frac{1}{\sqrt{2}}|0\rangle + \frac{1}{\sqrt{2}}|1\rangle
$$
&lt;p>이 상태를 측정하면 $|0\rangle$과 $|1\rangle$이 각각 50%의 확률로 관측됩니다.
만약 2개의 양자 비트가 있다면, $|00\rangle, |01\rangle, |10\rangle, |11\rangle$의 4가지 상태의 중첩을 만들 수 있습니다. $n$개의 양자 비트가 있다면 $2^n$개의 상태를 동시에 표현할 수 있게 되며, 이것이 양자 컴퓨터의 병렬 처리 능력의 원천 중 하나가 됩니다.&lt;/p>
&lt;h3 id="23-양자-얽힘entanglement">2.3 양자 얽힘(Entanglement)
&lt;/h3>&lt;p>양자 계산에서 가장 강력하고도 신비한 성질이 **양자 얽힘(Entanglement)**입니다. 아인슈타인이 &amp;lsquo;기분 나쁜 원격 작용&amp;rsquo;이라고 불렀던 이 현상은, 2개 이상의 양자 비트가 서로 강하게 결합되어 한쪽 양자 비트의 상태가 결정되면 물리적으로 아무리 떨어져 있더라도 다른 쪽 양자 비트의 상태가 순식간에 결정된다는 성질입니다.&lt;/p>
&lt;p>가장 유명한 양자 얽힘 상태인 &amp;lsquo;벨 상태(Bell State)&amp;rsquo; 중 하나인 $\Phi^+$ 상태는 다음과 같이 표현됩니다.&lt;/p>
$$
|\Phi^+\rangle = \frac{|00\rangle + |11\rangle}{\sqrt{2}}
$$
&lt;p>이 상태에서는 $|01\rangle$이나 $|10\rangle$이라는 상태가 존재하지 않습니다. 따라서 1번째 양자 비트를 측정하여 $|0\rangle$이 나왔을 경우, 2번째 양자 비트를 측정할 것도 없이 확실하게 $|0\rangle$임이 확정됩니다. 반대로 1번째가 $|1\rangle$이라면 2번째도 반드시 $|1\rangle$이 됩니다.&lt;/p>
&lt;hr>
&lt;h2 id="3-양자-논리-게이트quantum-logic-gates">3. 양자 논리 게이트(Quantum Logic Gates)
&lt;/h2>&lt;p>고전 컴퓨터가 AND, OR, NOT 등의 논리 게이트를 사용하여 계산을 수행하는 것처럼, 양자 컴퓨터도 &lt;strong>양자 게이트&lt;/strong>를 사용하여 양자 비트의 상태를 조작합니다. 양자 상태는 벡터이므로 양자 게이트는 그 벡터에 작용하는 &amp;lsquo;유니터리 행렬&amp;rsquo;로 표현됩니다.&lt;/p>
&lt;h3 id="31-파울리-게이트pauli-x-y-z">3.1 파울리 게이트(Pauli-X, Y, Z)
&lt;/h3>&lt;p>파울리 게이트는 1 양자 비트에 대한 기본적인 조작입니다.&lt;/p>
&lt;p>&lt;strong>· Pauli-X 게이트 (NOT 게이트)&lt;/strong>
고전 컴퓨터의 NOT 게이트에 해당합니다. $|0\rangle$을 $|1\rangle$로, $|1\rangle$을 $|0\rangle$로 반전시킵니다. (블로흐 구에서 X축을 기준으로 180도 회전)&lt;/p>
$$
X = \begin{pmatrix} 0 &amp; 1 \\ 1 &amp; 0 \end{pmatrix}
$$
&lt;p>&lt;strong>· Pauli-Y 게이트&lt;/strong>
Y축을 기준으로 180도 회전합니다. 위상과 비트 모두를 반전시키는 효과가 있습니다.&lt;/p>
$$
Y = \begin{pmatrix} 0 &amp; -i \\ i &amp; 0 \end{pmatrix}
$$
&lt;p>&lt;strong>· Pauli-Z 게이트 (위상 반전 게이트)&lt;/strong>
$|0\rangle$의 상태는 그대로 두고, $|1\rangle$ 상태의 위상을 반전($-1$을 곱함)시킵니다. (Z축을 기준으로 180도 회전)&lt;/p>
$$
Z = \begin{pmatrix} 1 &amp; 0 \\ 0 &amp; -1 \end{pmatrix}
$$
&lt;h3 id="32-아다마르-게이트hadamard-gate">3.2 아다마르 게이트(Hadamard Gate)
&lt;/h3>&lt;p>아다마르 게이트(H 게이트)는 확정된 상태($|0\rangle$나 $|1\rangle$)를 중첩 상태로 변환하는 매우 중요한 게이트입니다.&lt;/p>
$$
H = \frac{1}{\sqrt{2}}
\begin{pmatrix}
1 &amp; 1 \\
1 &amp; -1
\end{pmatrix}
$$
&lt;p>$|0\rangle$에 H 게이트를 적용하면 균등한 중첩 상태인 $|+\rangle$이 됩니다.&lt;/p>
$$
H|0\rangle = \frac{1}{\sqrt{2}}|0\rangle + \frac{1}{\sqrt{2}}|1\rangle = |+\rangle
$$
&lt;h3 id="33-위상-게이트phase-gates">3.3 위상 게이트(Phase Gates)
&lt;/h3>&lt;p>위상 게이트는 Z 게이트를 일반화한 것으로, $|1\rangle$ 상태의 위상을 지정된 각도 $\theta$만큼 회전시킵니다.&lt;/p>
$$
P(\theta) = \begin{pmatrix} 1 &amp; 0 \\ 0 &amp; e^{i\theta} \end{pmatrix}
$$
&lt;p>대표적인 것으로 S 게이트($\theta = \pi/2$)나 T 게이트($\theta = \pi/4$)가 있습니다.&lt;/p>
&lt;h3 id="34-cnot-게이트controlled-not-gate">3.4 CNOT 게이트(Controlled-NOT Gate)
&lt;/h3>&lt;p>CNOT 게이트(CX 게이트)는 2개의 양자 비트 간에 조작을 수행하는 게이트로, 양자 얽힘을 생성하기 위해 필수 불가결합니다. &amp;lsquo;제어(Control) 비트&amp;rsquo;와 &amp;lsquo;표적(Target) 비트&amp;rsquo;로 구성됩니다.&lt;/p>
&lt;p>제어 비트가 $|1\rangle$일 경우에만 표적 비트에 X 게이트(NOT 조작)를 적용하고, 제어 비트가 $|0\rangle$일 경우에는 아무것도 하지 않습니다.&lt;/p>
$$
CNOT = \begin{pmatrix}
1 &amp; 0 &amp; 0 &amp; 0 \\
0 &amp; 1 &amp; 0 &amp; 0 \\
0 &amp; 0 &amp; 0 &amp; 1 \\
0 &amp; 0 &amp; 1 &amp; 0
\end{pmatrix}
$$
&lt;hr>
&lt;h2 id="4-qiskit의-기본과-환경-구축">4. Qiskit의 기본과 환경 구축
&lt;/h2>&lt;p>여기부터는 실제로 Python과 Qiskit을 사용하여 양자 프로그램을 작성해 보겠습니다.&lt;/p>
&lt;h3 id="41-qiskit이란">4.1 Qiskit이란?
&lt;/h3>&lt;p>&lt;strong>Qiskit&lt;/strong>은 IBM Quantum이 개발한 오픈소스 양자 컴퓨팅용 소프트웨어 개발 키트(SDK)입니다. Python을 사용하여 직관적으로 양자 회로를 구축하고 로컬 시뮬레이터나 클라우드를 통해 실제 IBM의 양자 컴퓨터 실기에서 실행할 수 있습니다.&lt;/p>
&lt;h3 id="42-설치-방법">4.2 설치 방법
&lt;/h3>&lt;p>Qiskit을 이용하기 위해서는 Python 환경이 필요합니다. 다음 명령어로 Qiskit과 관련 패키지(시뮬레이터 및 그리기용 라이브러리)를 설치합니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install qiskit qiskit-aer qiskit-ibm-runtime matplotlib pylatexenc
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="43-프로그래밍의-기본-흐름">4.3 프로그래밍의 기본 흐름
&lt;/h3>&lt;p>Qiskit을 사용한 양자 프로그래밍은 주로 다음 단계로 진행됩니다.&lt;/p>
&lt;div class="mermaid">graph TD
A["1. 회로 구축 (Build)"] --> B["2. 컴파일/트랜스파일 (Compile)"]
B --> C["3. 실행 (Execute)"]
C --> D["4. 결과 분석 및 시각화 (Analyze)"]&lt;/div>
&lt;ol>
&lt;li>&lt;strong>회로 구축&lt;/strong>: &lt;code>QuantumCircuit&lt;/code> 객체를 생성하고 게이트를 추가해 나간다.&lt;/li>
&lt;li>&lt;strong>컴파일&lt;/strong>: 실행할 백엔드(실기나 시뮬레이터)에 맞춰 회로를 최적화.&lt;/li>
&lt;li>&lt;strong>실행&lt;/strong>: 백엔드에 작업을 전송하고 결과를 획득.&lt;/li>
&lt;li>&lt;strong>분석&lt;/strong>: 측정 결과의 히스토그램 등을 플롯.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="5-실전-벨-상태양자-얽힘를-만드는-회로-구축">5. 실전: 벨 상태(양자 얽힘)를 만드는 회로 구축
&lt;/h2>&lt;p>이론에서 배운 &amp;lsquo;양자 얽힘(벨 상태)&amp;lsquo;을 실제로 Qiskit으로 만들어 봅시다. 목표로 하는 상태는 $|\Phi^+\rangle = \frac{|00\rangle + |11\rangle}{\sqrt{2}}$입니다.&lt;/p>
&lt;h3 id="51-회로-설계">5.1 회로 설계
&lt;/h3>&lt;p>벨 상태를 만들려면 다음 절차를 거칩니다.&lt;/p>
&lt;ol>
&lt;li>2개의 양자 비트를 준비한다(초기 상태는 둘 다 $|0\rangle$).&lt;/li>
&lt;li>1번째 양자 비트에 아다마르 게이트(H)를 적용하여 중첩 상태로 만든다.&lt;/li>
&lt;li>1번째 양자 비트를 &amp;lsquo;제어 비트&amp;rsquo;, 2번째 양자 비트를 &amp;lsquo;표적 비트&amp;rsquo;로 하여 CNOT 게이트를 적용한다.&lt;/li>
&lt;li>결과를 읽어내기 위해 측정(Measure)을 수행한다.&lt;/li>
&lt;/ol>
&lt;h3 id="52-pythonqiskit-코드-구현">5.2 Python/Qiskit 코드 구현
&lt;/h3>&lt;p>그러면 실제 코드를 살펴봅시다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">qiskit&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">QuantumCircuit&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">transpile&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">qiskit_aer&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Aer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">qiskit.visualization&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">plot_histogram&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">matplotlib.pyplot&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">plt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. 회로 초기화&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2개의 양자 비트와 2개의 고전 비트를 가지는 양자 회로 생성&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">qc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QuantumCircuit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. H 게이트 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 양자 비트 0 (q0)에 아다마르 게이트 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. CNOT 게이트 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># q0을 제어 비트로, q1을 표적 비트로 CNOT 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cx&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 4. 측정&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 양자 비트 0과 1을 측정하여 각각 고전 비트 0과 1에 쓰기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">measure&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 회로도 그리기 (matplotlib 사용)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># qc.draw(&amp;#39;mpl&amp;#39;)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">draw&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>이 코드를 실행하면 콘솔 상에 아스키 아트로 다음과 같은 양자 회로도가 표시됩니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"> ┌───┐ ┌─┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">q_0: ┤ H ├──■──┤M├───
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └───┘┌─┴─┐└╥┘┌─┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">q_1: ─────┤ X ├─╫─┤M├
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └───┘ ║ └╥┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">c: 2/═══════════╩══╩═
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> 0 1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>H&lt;/code>가 아다마르 게이트, &lt;code>■&lt;/code>와 &lt;code>X&lt;/code>의 조합이 CNOT 게이트, &lt;code>M&lt;/code>이 측정을 나타냅니다.&lt;/p>
&lt;h3 id="53-시뮬레이터에서의-실행-및-결과-해석">5.3 시뮬레이터에서의 실행 및 결과 해석
&lt;/h3>&lt;p>다음으로 이 회로를 IBM의 고성능 시뮬레이터 &lt;code>Aer&lt;/code>에서 실행하여 결과를 확인합니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Aer 시뮬레이터 백엔드 가져오기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">simulator&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Aer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_backend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;qasm_simulator&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 시뮬레이터용으로 회로 트랜스파일(최적화)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">compiled_circuit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">transpile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">qc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">simulator&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 회로 실행(여기서는 1000 샷 실행)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">job&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">simulator&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">compiled_circuit&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">shots&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1000&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 결과 가져오기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">job&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 상태 관측 횟수(카운트) 가져오기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">counts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_counts&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">compiled_circuit&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">측정 결과:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">counts&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 히스토그램 플롯&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># plot_histogram(counts)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># plt.show()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>결과 해석&lt;/strong>&lt;/p>
&lt;p>콘솔의 출력은 다음과 같이 나타날 것입니다.
&lt;code>측정 결과: {'00': 495, '11': 505}&lt;/code>
(※확률은 무작위이므로 실행할 때마다 수치는 약간 변동합니다)&lt;/p>
&lt;p>이상적인 시뮬레이션 환경에서는 측정 결과 &lt;code>00&lt;/code>과 &lt;code>11&lt;/code>이 대략 50%씩 관측되며, &lt;code>01&lt;/code>이나 &lt;code>10&lt;/code>은 전혀 관측되지 않습니다.
이것은 바로 우리가 작성한 벨 상태 $|\Phi^+\rangle = \frac{|00\rangle + |11\rangle}{\sqrt{2}}$의 이론적 예측과 완전히 일치합니다. 1번째 양자 비트가 0이면 2번째도 반드시 0, 1이면 반드시 1이 된다는 &amp;lsquo;양자 얽힘&amp;rsquo;이 정확하게 시뮬레이트된 것입니다.&lt;/p>
&lt;p>참고로 실기 양자 컴퓨터(IBM Quantum Hardware)에서 실행할 경우, 노이즈(양자 결어긋남이나 게이트 오류)의 영향으로 인해 드물게 &lt;code>01&lt;/code>이나 &lt;code>10&lt;/code>이 관측될 수도 있습니다. 이 노이즈를 어떻게 줄일 것인가(양자 오류 정정)가 현재 양자 컴퓨터 개발의 가장 큰 과제 중 하나입니다.&lt;/p>
&lt;hr>
&lt;h2 id="6-더-고도화된-알고리즘으로의-스케일업">6. 더 고도화된 알고리즘으로의 스케일업
&lt;/h2>&lt;p>벨 상태의 생성은 양자 프로그래밍의 &amp;lsquo;Hello World&amp;rsquo;라고도 할 수 있습니다. 이를 바탕으로 더욱 발전시킴으로써 고전 컴퓨터를 능가하는 강력한 알고리즘을 구축할 수 있습니다.&lt;/p>
&lt;h3 id="61-도이치-조사-알고리즘deutsch-jozsa-algorithm">6.1 도이치-조사 알고리즘(Deutsch-Jozsa Algorithm)
&lt;/h3>&lt;p>주어진 함수 $f(x)$가 &amp;lsquo;상수 함수(입력에 상관없이 항상 0 또는 항상 1을 출력)&amp;lsquo;인지 &amp;lsquo;균형 함수(입력의 절반에 대해 0, 나머지 절반에 대해 1을 출력)&amp;lsquo;인지 판정하는 문제입니다.
고전 컴퓨터에서는 최악의 경우 $2^{n-1} + 1$번의 함수 평가가 필요하지만, 도이치-조사 알고리즘을 사용하면 양자의 병렬성을 이용하여 &lt;strong>단 1번의 평가&lt;/strong>만으로 판정할 수 있습니다. 이는 중첩 상태를 입력하고 간섭(Interference)을 이용해 불필요한 상태를 상쇄하여 원하는 답을 증폭시키는 양자 알고리즘의 기본 패턴을 보여줍니다.&lt;/p>
&lt;h3 id="62-그로버의-알고리즘grovers-algorithm">6.2 그로버의 알고리즘(Grover&amp;rsquo;s Algorithm)
&lt;/h3>&lt;p>정렬되지 않은 $N$개의 데이터베이스에서 특정 데이터를 찾는 검색 문제에 있어, 고전 알고리즘이 평균 $N/2$번의 계산을 요구하는 반면 그로버의 알고리즘은 $\sqrt{N}$번 만에 원하는 데이터를 찾아낼 수 있습니다.
이 알고리즘은 &amp;lsquo;오라클(Oracle)&amp;lsquo;이라 불리는 블랙박스를 사용하여 목적 해의 위상을 반전시키고, 나아가 &amp;lsquo;진폭 증폭(Amplitude Amplification)&amp;lsquo;을 수행함으로써 목적 해가 관측될 확률을 극적으로 높입니다.&lt;/p>
&lt;div class="mermaid">graph TD
A["초기화 (모든 상태의 중첩)"] --> B["오라클 (정답의 위상을 반전)"]
B --> C["확산 연산자 (평균값 기준 반전에 의한 진폭 증폭)"]
C --> D{"충분한 확률에 도달했는가?"}
D -- "No" --> B
D -- "Yes" --> E["측정"]&lt;/div>
&lt;hr>
&lt;h2 id="7-마무리-및-향후-학습">7. 마무리 및 향후 학습
&lt;/h2>&lt;p>이 기사에서는 양자 컴퓨팅의 근본적인 개념인 중첩과 양자 얽힘에서 시작하여, Qiskit을 이용한 양자 논리 게이트의 조작, 그리고 실제로 벨 상태를 구축하고 시뮬레이션하여 결과를 해석하기까지 자세히 해설했습니다.&lt;/p>
&lt;p>Qiskit은 Python이라는 친숙한 언어로 작성할 수 있어 수학적, 물리적인 장벽을 넘어 알고리즘 구축에 집중할 수 있게 해주는 강력한 도구입니다. 양자 컴퓨터는 현재 노이즈를 동반하는 중간 규모 양자 장치(NISQ: Noisy Intermediate-Scale Quantum) 시대에 접어들었지만, 기계 학습(Quantum Machine Learning), 화학 시뮬레이션(Quantum Chemistry), 암호 해독 등 수많은 분야에서의 응용 연구가 전 세계적으로 빠르게 진행되고 있습니다.&lt;/p>
&lt;p>부디 이번 기회에 Qiskit을 사용하여 다양한 양자 회로를 직접 만들고, 실제 IBM Quantum 프로세서에서 구동해 보시길 바랍니다. 미래의 컴퓨팅 패러다임을 직접 체험할 수 있을 것입니다.&lt;/p>
&lt;h3 id="참고-자료">참고 자료
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://qiskit.org/documentation/" target="_blank" rel="noopener"
>Qiskit 공식 문서&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://qiskit.org/textbook/ja/preface.html" target="_blank" rel="noopener"
>Qiskit Textbook&lt;/a> - 수학적 배경이나 알고리즘을 더 깊이 배우고 싶은 분들에게 추천하는 공식 텍스트&lt;/li>
&lt;li>IBM Quantum Learning&lt;/li>
&lt;/ul>
&lt;p>양자의 세계로 오신 것을 환영합니다!&lt;/p></description></item><item><title>쇼어의 알고리즘을 Python으로 시뮬레이션해 보았다</title><link>http://kenji.blog/ko/p/shors-algorithm-simulation-python/</link><pubDate>Fri, 11 Sep 2026 08:00:00 +0900</pubDate><guid>http://kenji.blog/ko/p/shors-algorithm-simulation-python/</guid><description>&lt;img src="http://kenji.blog/p/shors-algorithm-simulation-python/img/eyecatch.jpg" alt="Featured image of post 쇼어의 알고리즘을 Python으로 시뮬레이션해 보았다" />&lt;h1 id="1-서론-양자-컴퓨터가-가져올-암호의-위기">1. 서론: 양자 컴퓨터가 가져올 암호의 위기
&lt;/h1>&lt;p>현대 인터넷 사회에서 보안의 대부분은 &lt;strong>공개키 암호 방식&lt;/strong>(특히 RSA 암호)에 의존하고 있습니다. 우리가 온라인 쇼핑에서 신용카드 정보를 전송할 때나 기밀성이 높은 데이터를 주고받을 때, 그 통신 내용은 RSA 암호에 의해 강력하게 보호받고 있습니다.&lt;/p>
&lt;p>RSA 암호 안전성의 근거는 &amp;ldquo;&lt;strong>거대한 정수의 소인수분해는 고전 컴퓨터(우리가 평소 사용하는 PC나 슈퍼컴퓨터)로는 극히 어렵다&lt;/strong>&amp;ldquo;라는 수학적인 사실에 의존하고 있습니다. 그러나 1994년 피터 쇼어(Peter Shor)가 발표한 &amp;ldquo;&lt;strong>쇼어의 알고리즘(Shor&amp;rsquo;s Algorithm)&lt;/strong>&amp;ldquo;은 이 전제를 근본부터 뒤엎는 것이었습니다. 쇼어의 알고리즘을 대규모 양자 컴퓨터에서 실행하면 고전 컴퓨터로는 우주의 나이 이상의 시간이 걸리는 소인수분해를 불과 수 분에서 수 시간 만에 풀 수 있다는 것이 수학적으로 증명된 것입니다.&lt;/p>
&lt;p>본 문서에서는 이 쇼어의 알고리즘이 어떻게 소인수분해를 고속으로 수행하는지, 그 수학적인 구조부터 Python과 양자 계산 프레임워크인 &lt;strong>Qiskit&lt;/strong>을 이용한 구체적인 시뮬레이션 구현까지 철저하고 상세하게 해설해 나가겠습니다.&lt;/p>
&lt;hr>
&lt;h1 id="2-계산량의-극적인-변화-지수-함수에서-다항식-시간으로">2. 계산량의 극적인 변화: 지수 함수에서 다항식 시간으로
&lt;/h1>&lt;p>왜 소인수분해가 어려운 것일까요? 고전 컴퓨터에서 최고의 소인수분해 알고리즘으로 알려진 &amp;lsquo;일반 수체 체(General Number Field Sieve, GNFS)&amp;lsquo;를 사용하더라도 그 계산량은 준지수 함수적이 됩니다.&lt;/p>
&lt;p>자릿수가 $N$인 합성수를 소인수분해하는 데 걸리는 시간 계산량은 고전적인 기법에서는 다음과 같습니다.&lt;/p>
$$ O\left(\exp\left( c (\log N)^{1/3} (\log \log N)^{2/3} \right)\right) $$
&lt;p>이 때문에 키 길이를 늘리는(예를 들어 2048비트나 4096비트로 만드는) 것만으로도 고전 컴퓨터로 해독하는 데 수천 년, 수만 년이라는 비현실적인 시간이 걸리게 됩니다.&lt;/p>
&lt;p>그러나 양자 컴퓨터에서 &lt;strong>쇼어의 알고리즘&lt;/strong>을 사용하면 계산량은 입력 비트 수 $\log N$에 대해 다항식 시간으로 극적으로 단축됩니다.&lt;/p>
$$ O((\log N)^3) $$
&lt;p>이것은 비트 수를 2배로 늘렸을 때, 고전 컴퓨터에서는 계산 시간이 천문학적으로 증가하는 반면, 양자 컴퓨터에서는 계산 시간이 기껏해야 8배 정도밖에 늘어나지 않음을 의미합니다. 이 **지수 함수 시간에서 다항식 시간으로의 계산량 클래스 단축(BQP 클래스로의 포함)**이야말로 쇼어 알고리즘의 진정한 대단함입니다.&lt;/p>
&lt;div class="mermaid">graph TD
A["입력 크기(비트 수) N의 증가"] --> B{"알고리즘의 선택"}
B -->|고전: 일반 수체 체| C["준지수 함수적 증가 O(exp(...))"]
B -->|양자: 쇼어의 알고리즘| D["다항식 시간 O((log N)^3)"]
C --> E["수천 년~수십억 년 (해독 불가능)"]
D --> F["수 분~수 시간 (현실적인 시간 내 해독)"]&lt;/div>
&lt;hr>
&lt;h1 id="3-알고리즘의-전체상과-수학적-배경">3. 알고리즘의 전체상과 수학적 배경
&lt;/h1>&lt;p>쇼어의 알고리즘은 사실 모든 것을 양자 컴퓨터로 하는 것은 아닙니다. 고전 컴퓨터를 통한 전처리·후처리와 양자 컴퓨터를 통한 핵심 부분(주기 발견 알고리즘)의 연계를 통해 이루어집니다.&lt;/p>
&lt;p>알고리즘의 전체적인 흐름은 다음과 같습니다.&lt;/p>
&lt;div class="mermaid">graph TD
A["입력: 소인수분해하고 싶은 합성수 N"] --> B["a &lt; N 인 난수 a 를 선택"]
B --> C{"gcd(a, N) > 1 ?"}
C -- "Yes" --> D["자명한 인수 gcd(a, N) 을 출력하고 종료"]
C -- "No" --> E["양자 알고리즘으로 f(x) = a^x mod N 의 주기 r 을 찾음"]
E --> F{"r 이 짝수이고 a^(r/2) ≢ -1 mod N ?"}
F -- "No" --> B
F -- "Yes" --> G["인수 p = gcd(a^(r/2) - 1, N), q = gcd(a^(r/2) + 1, N) 을 계산"]
G --> H["출력: p, q"]&lt;/div>
&lt;h2 id="소인수분해에서-주기-발견-문제로의-귀착">소인수분해에서 주기 발견 문제로의 귀착
&lt;/h2>&lt;p>쇼어의 천재적인 번뜩임은 &amp;ldquo;&lt;strong>소인수분해 문제&lt;/strong>&amp;ldquo;를 &amp;ldquo;&lt;strong>주기 발견 문제(Order Finding Problem)&lt;/strong>&amp;ldquo;로 변환한 것에 있습니다.&lt;/p>
&lt;p>정수 $N$(소인수분해하고 싶은 수)과 서로소인 정수 $a$($1 &lt; a &lt; N$)를 생각해 봅시다. 다음과 같은 모듈러 지수 함수를 정의합니다.&lt;/p>
$$ f(x) = a^x \bmod N $$
&lt;p>이 함수는 어떤 주기 $r$을 가집니다. 즉, 임의의 $x$에 대하여 $f(x+r) = f(x)$가 성립합니다. 특히 $x=0$일 때,&lt;/p>
$$ a^r \equiv 1 \pmod N $$
&lt;p>이 되는 최소의 양의 정수 $r$을 &amp;ldquo;$a$의 $N$을 법으로 하는 위수(Order)&amp;ldquo;라고 부릅니다. 이 주기 $r$을 찾을 수 있다면, 다음과 같이 소인수를 도출해 낼 수 있습니다.&lt;/p>
&lt;p>식을 변형하면,
&lt;/p>
$$ a^r - 1 \equiv 0 \pmod N $$
&lt;p>
만약 $r$이 짝수라면, 합차 공식을 사용하여 인수분해할 수 있습니다.
&lt;/p>
$$ (a^{r/2} - 1)(a^{r/2} + 1) \equiv 0 \pmod N $$
&lt;p>이것은 $N$이 $(a^{r/2} - 1)$ 또는 $(a^{r/2} + 1)$ 중 하나와 공약수를 가짐을 의미합니다(단, $a^{r/2} \not\equiv -1 \pmod N$이라는 조건을 만족해야 합니다). 따라서 유클리드 호제법을 사용하여,&lt;/p>
$$ p = \gcd(a^{r/2} - 1, N) $$
$$ q = \gcd(a^{r/2} + 1, N) $$
&lt;p>을 계산하면, $N$의 비자명한 소인수 $p, q$를 찾을 수 있는 것입니다. 이 계산(최대공약수 계산이나 난수 생성)은 고전 컴퓨터에서 매우 고속으로 수행할 수 있습니다. 문제는 &lt;strong>주기 $r$을 어떻게 고속으로 찾을 것인가&lt;/strong> 하는 점으로 좁혀집니다. 고전 컴퓨터에서는 이 주기 $r$을 찾는 것 자체에 지수 함수적인 시간이 소요되어 버립니다. 여기서 양자 컴퓨터가 나설 차례가 됩니다.&lt;/p>
&lt;hr>
&lt;h1 id="4-양자-알고리즘-부분-주기-발견의-구조">4. 양자 알고리즘 부분: 주기 발견의 구조
&lt;/h1>&lt;p>양자 컴퓨터를 사용하여 주기 $r$을 찾기 위한 서브루틴은 다음의 4가지 단계로 구성됩니다.&lt;/p>
&lt;div class="mermaid">graph LR
subgraph "양자 상태의 전이"
S1["|0⟩|0⟩ (초기화)"] --> S2["H 게이트: 중첩 Σ|x⟩|0⟩"]
S2 --> S3["오라클 U: Σ|x⟩|a^x mod N⟩"]
S3 --> S4["QFT: 간섭에 의한 주기 추출"]
S4 --> S5["측정: 근사치 y 획득"]
end&lt;/div>
&lt;h2 id="1단계-양자-레지스터의-초기화와-중첩">1단계: 양자 레지스터의 초기화와 중첩
&lt;/h2>&lt;p>먼저, 2개의 양자 레지스터를 준비합니다. 제1 레지스터는 상태를 입력하기 위한 것이고, 제2 레지스터는 함수의 계산 결과를 저장하기 위한 것입니다.
초기 상태는 모두 $|0\rangle$입니다.&lt;/p>
$$ |\psi_0\rangle = |0\rangle_1 |0\rangle_2 $$
&lt;p>제1 레지스터의 모든 양자 비트에 아다마르 게이트(Hadamard Gate)를 적용하여, 생각할 수 있는 모든 입력 $x$ ($0$에서 $Q-1$까지, $Q=2^n$)에 대해 동일한 확률의 중첩 상태를 만들어 냅니다.&lt;/p>
$$ |\psi_1\rangle = \frac{1}{\sqrt{Q}} \sum_{x=0}^{Q-1} |x\rangle_1 |0\rangle_2 $$
&lt;p>이로 인해 양자 컴퓨터는 한 번의 연산으로 $Q$개의 모든 입력에 대한 상태를 동시에 유지하게 됩니다. 이것이 &lt;strong>양자 병렬성&lt;/strong>의 강력한 원천입니다.&lt;/p>
&lt;h2 id="2단계-오라클-함수모듈러-거듭제곱의-적용">2단계: 오라클 함수(모듈러 거듭제곱)의 적용
&lt;/h2>&lt;p>다음으로, 양자 연산 회로 $U_f$를 사용하여 함수 $f(x) = a^x \bmod N$을 계산하고 그 결과를 제2 레지스터에 저장합니다.&lt;/p>
$$ |\psi_2\rangle = \frac{1}{\sqrt{Q}} \sum_{x=0}^{Q-1} |x\rangle_1 |a^x \bmod N\rangle_2 $$
&lt;p>이 시점에서 제1 레지스터와 제2 레지스터는 &lt;strong>양자 얽힘(Entanglement)&lt;/strong> 상태에 있습니다. 만약 (가정하여) 제2 레지스터를 관측하여 특정 값 $k = a^{x_0} \bmod N$을 얻었다고 하면, 제1 레지스터의 상태는 그 값 $k$를 주는 $x$의 중첩 상태로 붕괴됩니다. 함수의 주기가 $r$이므로, 남는 상태는 $x_0, x_0+r, x_0+2r, \dots$ 이라는 $r$ 간격의 값이 됩니다.&lt;/p>
$$ |\psi_3\rangle = \sqrt{\frac{r}{Q}} \sum_{j=0}^{M-1} |x_0 + j r\rangle_1 |k\rangle_2 $$
&lt;p>그러나 우리는 $x_0$을 알고 싶은 것이 아니라 주기 $r$ 자체를 알고 싶어 합니다. 이 상태에서 $r$을 직접 관측하는 것은 불가능합니다. 그래서 양자 푸리에 변환을 사용합니다.&lt;/p>
&lt;h2 id="3단계-양자-푸리에-변환qft에-의한-위상-간섭">3단계: 양자 푸리에 변환(QFT)에 의한 위상 간섭
&lt;/h2>&lt;p>제1 레지스터에 대해 **양자 푸리에 변환(Quantum Fourier Transform, QFT)**을 적용합니다. QFT는 고전적인 이산 푸리에 변환의 양자 버전으로, 상태 벡터의 진폭을 변환합니다. 기저 상태 $|x\rangle$에 대한 QFT의 작용은 다음과 같이 정의됩니다.&lt;/p>
$$ QFT |x\rangle = \frac{1}{\sqrt{Q}} \sum_{y=0}^{Q-1} \omega^{xy} |y\rangle $$
&lt;p>여기서 $\omega = e^{2\pi i / Q}$입니다.&lt;/p>
&lt;p>QFT를 적용하면 상태의 진폭이 간섭을 일으킵니다. 수학적인 세부 사항은 생략하겠지만, 주기 $r$을 갖는 상태에 대해 QFT를 적용하면 파동이 **보강 간섭(Constructive Interference)**을 일으키는 것은 $y$가 $Q/r$의 정수배에 극히 가까운 값일 때뿐입니다. 그 이외의 상태는 **상쇄 간섭(Destructive Interference)**에 의해 확률 진폭이 상쇄되어 0에 가까워집니다.&lt;/p>
&lt;h2 id="4단계-측정과-연분수-전개">4단계: 측정과 연분수 전개
&lt;/h2>&lt;p>마지막으로 제1 레지스터를 측정합니다. 측정에 의해 얻어지는 값 $y$는 높은 확률로 다음 조건을 만족합니다.&lt;/p>
$$ y \approx c \frac{Q}{r} \implies \frac{y}{Q} \approx \frac{c}{r} $$
&lt;p>($c$는 $0 \le c &lt; r$인 미지의 정수입니다)&lt;/p>
&lt;p>얻어진 유리수 $y/Q$에 대해 고전 알고리즘인 **연분수 전개(Continued Fraction Expansion)**를 적용함으로써 근사 분수 $c/r$을 계산하고, 분모에서 주기 $r$을 추출합니다.&lt;/p>
&lt;hr>
&lt;h1 id="5-python과-qiskit을-이용한-시뮬레이션-구현">5. Python과 Qiskit을 이용한 시뮬레이션 구현
&lt;/h1>&lt;p>이론만으로는 실감이 나지 않으므로, 실제로 Python과 IBM의 양자 계산 프레임워크인 &lt;strong>Qiskit&lt;/strong>을 사용하여 쇼어의 알고리즘을 시뮬레이션해 봅시다.&lt;/p>
&lt;p>여기서는 가장 고전적이고 유명한 예인 **&amp;quot;$N=15$를 $a=7$을 사용하여 소인수분해하기&amp;rdquo;**라는 시나리오를 구현합니다.&lt;/p>
&lt;h2 id="실행-환경-준비">실행 환경 준비
&lt;/h2>&lt;p>미리 Qiskit을 설치해 둡니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install qiskit qiskit-aer numpy
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="python-구현-코드의-전체상">Python 구현 코드의 전체상
&lt;/h2>&lt;p>다음 코드는 $N=15, a=7$에 특화된 쇼어의 알고리즘 구현 예입니다. 범용적인 모듈러 거듭제곱 회로를 구성하는 것은 현재의 시뮬레이터에서는 계산 비용이 너무 높기 때문에, 특정한 $a=7$인 경우의 게이트 동작을 하드코딩하고 있습니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">qiskit&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">QuantumCircuit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">qiskit_aer&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AerSimulator&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">qiskit.visualization&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">plot_histogram&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">fractions&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Fraction&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. 역 양자 푸리에 변환 (QFT†) 을 구성하는 함수&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">qft_dagger&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;n 양자 비트의 역 양자 푸리에 변환 회로를 생성한다&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QuantumCircuit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 순서를 반전하기 위한 SWAP 게이트&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">qubit&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">qubit&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">qubit&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 제어 위상 게이트와 H 게이트의 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">j&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">j&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="nb">float&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">j&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">)),&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">j&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">j&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;QFT_dagger&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">qc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. 7^x mod 15 의 제어 모듈러 거듭제곱 연산을 구성하는 함수&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">c_amod15&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">power&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;특정 a와 거듭제곱에 대한 제어 U 게이트를 생성한다(N=15 전용)&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QuantumCircuit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">power&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># a=7인 경우의 7^x mod 15 의 하드코딩 논리&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">13&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">8&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">11&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">11&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="mi">13&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to_gate&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">^&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">power&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> mod 15&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">c_U&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">U&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">control&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">c_U&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. 메인 양자 회로 구성&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">shor_circuit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_count&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># n_count: 제어 레지스터의 비트 수&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 타겟 레지스터는 0~15 를 표현하기 위해 4비트&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">QuantumCircuit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_count&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 제1 레지스터(제어 레지스터)의 초기화(중첩의 생성)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">h&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 제2 레지스터(타겟 레지스터)를 |1&amp;gt; (0001) 로 초기화&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">n_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 제어 모듈러 거듭제곱 연산(오라클)의 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">q&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2^q 승의 연산을 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c_amod15&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="n">q&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="n">q&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">n_count&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">)])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 제1 레지스터에 역 양자 푸리에 변환을 적용&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">qft_dagger&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 제1 레지스터를 측정&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">measure&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">qc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># --- 실행 섹션 ---&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">N&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">15&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">8&lt;/span> &lt;span class="c1"># 제어 레지스터에 8 양자 비트를 사용 (Q=256)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;탐색 설정: N=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">N&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, a=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, 제어 양자 비트 수=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 회로의 생성&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">qc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">shor_circuit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 시뮬레이터에서의 실행&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sim&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AerSimulator&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 최신 Qiskit에서는 transpile을 권장&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">from&lt;/span> &lt;span class="nn">qiskit&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">transpile&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">compiled_circuit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">transpile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">qc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sim&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">job&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sim&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">compiled_circuit&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">shots&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1024&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">job&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">counts&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_counts&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">측정 결과(비트열: 관측 횟수):&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">bitstring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">count&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">counts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">bitstring&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">회&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 고전적 후처리: 연분수 전개에 의한 주기 r의 특정&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">--- 주기의 계산과 소인수분해 ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phases&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">output&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">counts&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 비트열을 10진수로 변환&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decimal&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">output&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 위상 = 측정값 / 2^n_count&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phase&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">decimal&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="n">n_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phases&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">phase&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 연분수 전개에 의해 근사 분수를 획득. 분모의 상한은 N=15&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">frac&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Fraction&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">phase&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">limit_denominator&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">15&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">frac&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">denominator&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;관측값: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decimal&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">3d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> | 위상: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">phase&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.4f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> | 연분수: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">frac&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> | 추정 주기 r = &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 주기 r이 짝수이고 유효한 결과를 가져오는지 확인&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">guess1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">guess2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="o">**&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">guess1&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="n">guess2&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; =&amp;gt; 성공! &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">N&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 의 소인수는 &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">guess1&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 와(과) &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">guess2&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> 입니다.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; =&amp;gt; 자명한 인수뿐임. 다시 시도.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; =&amp;gt; 주기가 홀수이므로 실패.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="코드의-해설과-실행-결과의-해석">코드의 해설과 실행 결과의 해석
&lt;/h2>&lt;p>위의 코드를 실행하면 제어 레지스터의 측정 결과로서 높은 확률로 특정 피크(관측값)를 얻을 수 있습니다. &lt;code>n_count=8&lt;/code>($Q=256$)인 경우, 이상적인 양자 컴퓨터(또는 시뮬레이터)라면 관측값으로 &lt;code>0&lt;/code>, &lt;code>64&lt;/code>, &lt;code>128&lt;/code>, &lt;code>192&lt;/code>와 같은 수치가 압도적인 확률로 출현합니다.&lt;/p>
&lt;p>이것들을 $Q=256$으로 나누면 위상 $y/Q$는 각각 $0.0$, $0.25$, $0.5$, $0.75$가 됩니다.
이 위상을 연분수 전개하면:&lt;/p>
&lt;ul>
&lt;li>$0.25 \to 1/4$ (추정 주기 $r=4$)&lt;/li>
&lt;li>$0.50 \to 1/2$ (추정 주기 $r=2$)&lt;/li>
&lt;li>$0.75 \to 3/4$ (추정 주기 $r=4$)&lt;/li>
&lt;/ul>
&lt;p>여기서 얻어진 주기 $r=4$를 사용하여 소인수를 계산합니다.
$a=7, r=4$이므로,
$p = \gcd(7^2 - 1, 15) = \gcd(48, 15) = 3$
$q = \gcd(7^2 + 1, 15) = \gcd(50, 15) = 5$&lt;/p>
&lt;p>훌륭하게 $15 = 3 \times 5$의 소인수분해에 성공했습니다.&lt;/p>
&lt;blockquote>
&lt;p>[!TIP]
측정값으로 $y=128$(위상 $0.5$)을 얻은 경우, 분모는 $2$가 되어 참값인 주기 $r=4$가 아니라 그 약수를 얻게 됩니다. 이런 경우에는 알고리즘을 여러 번 실행하거나 얻어진 $r$의 배수를 조사함으로써 진짜 주기에 도달할 수 있습니다.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h1 id="6-실용화를-향한-과제와-nisq-시대의-한계">6. 실용화를 향한 과제와 NISQ 시대의 한계
&lt;/h1>&lt;p>시뮬레이터 상에서 $N=15$를 소인수분해하는 것은 간단하게 할 수 있었지만, 실제 사회에서 사용되고 있는 RSA-2048(617자리의 10진수)을 소인수분해하려면 현실의 양자 컴퓨터에는 아직 수많은 장벽이 존재합니다.&lt;/p>
&lt;p>현재 우리가 살고 있는 시대는 &lt;strong>NISQ(Noisy Intermediate-Scale Quantum: 노이즈가 있는 중간 규모 양자) 시대&lt;/strong>라고 불립니다. 양자 비트는 외부 환경의 노이즈에 극히 취약하여, 계산 도중에 &amp;lsquo;결어긋남(데코히어런스)&amp;lsquo;을 일으켜 상태가 깨져 버립니다.&lt;/p>
&lt;p>쇼어의 알고리즘과 같이 깊은(게이트 수가 많은) 회로를 정확하게 실행하기 위해서는 노이즈를 정정하는 **양자 오류 정정(Quantum Error Correction)**이 필수적입니다. 하나의 노이즈 없는 &amp;lsquo;논리 양자 비트&amp;rsquo;를 만들어 내기 위해 수천 개의 &amp;lsquo;물리 양자 비트&amp;rsquo;를 표면 부호(Surface Code) 등으로 인코딩해야 합니다.&lt;/p>
&lt;p>2048비트의 RSA 암호를 깨기 위해서는 수천 개의 완벽한 논리 양자 비트가 필요하며, 이를 실현하려면 &lt;strong>수백만에서 수천만 개의 물리 양자 비트&lt;/strong>를 탑재한 결함 허용(오류 내성) 양자 컴퓨터가 필요할 것으로 추산되고 있습니다. 현재 최첨단 양자 프로세서도 수백~수천 물리 양자 비트 정도이기 때문에, 당장 전 세계의 암호가 깨지는 것은 아닙니다.&lt;/p>
&lt;blockquote>
&lt;p>[!WARNING]
그러나 &amp;ldquo;Store Now, Decrypt Later(지금 저장하고, 나중에 해독한다)&amp;ldquo;라는 위협 모델이 존재합니다. 공격자는 현재 암호화되어 있는 기밀 통신을 암호 데이터인 채로 대량으로 저장해 두고, 10~20년 후에 강력한 양자 컴퓨터가 완성되는 순간에 모든 것을 해독하려는 전략을 취할 가능성이 있습니다.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h1 id="7-양자-내성-암호pqc로의-전환">7. 양자 내성 암호(PQC)로의 전환
&lt;/h1>&lt;p>이러한 &amp;lsquo;Q-Day(양자 컴퓨터가 암호를 깨는 날)&amp;lsquo;의 도래에 대비하여, 미국 국립표준기술연구소(NIST)를 필두로 전 세계 암호학자들이 **양자 내성 암호(Post-Quantum Cryptography, PQC)**의 제정을 추진하고 있습니다.&lt;/p>
&lt;p>PQC는 쇼어의 알고리즘을 사용해도 (혹은 그로버의 알고리즘을 사용해도) 효율적으로 풀 수 없을 것으로 수학적으로 여겨지는 새로운 수학적 문제(격자 문제, 다변수 다항식 문제, 해시 함수 기반 등)를 기반으로 하고 있습니다. 이미 &amp;lsquo;CRYSTALS-Kyber&amp;rsquo;나 &amp;lsquo;CRYSTALS-Dilithium&amp;rsquo;과 같은 알고리즘이 표준 규격으로 선정되어, Apple의 iMessage나 각종 웹 브라우저의 통신 프로토콜에 도입이 서서히 시작되고 있습니다.&lt;/p>
&lt;p>IT 인프라를 관리하는 엔지니어에게 있어, 기존의 RSA나 타원곡선 암호에서 PQC로의 &amp;lsquo;크립토 어질리티(암호 민첩성: 빠르게 암호 방식을 전환할 수 있는 설계)&amp;lsquo;를 시스템에 통합하는 것이 향후 큰 과제가 될 것입니다.&lt;/p>
&lt;hr>
&lt;h1 id="8-맺음말">8. 맺음말
&lt;/h1>&lt;p>본 기사에서는 쇼어 알고리즘의 이론적인 수학적 배경에서 시작하여 양자 푸리에 변환을 사용한 주기 추출의 메커니즘, 그리고 Python과 Qiskit을 이용한 구체적인 시뮬레이션 코드까지 1만 자 규모의 분량으로 철저하게 해설했습니다.&lt;/p>
&lt;p>양자역학이라는 미시적 세계의 물리 법칙이 거시적 정보과학의 근간인 계산량 이론이나 암호 이론을 근본부터 뒤엎어 버린다는 사실은 과학의 역사에 있어 가장 흥미진진한 패러다임 전환 중 하나입니다. 현재 진행형으로 계속 발전하고 있는 양자 컴퓨팅 기술과 그에 맞서는 새로운 암호 기술의 공방전에서 앞으로도 눈을 뗄 수 없습니다.&lt;/p>
&lt;p>꼭 이번에 소개한 Python 코드를 자신의 환경에서 실행해 보시고, 양자 상태의 중첩과 간섭이 만들어 내는 &amp;lsquo;계산의 마법&amp;rsquo;을 체감해 보시기 바랍니다.&lt;/p>
&lt;hr>
&lt;p>&lt;strong>참고 문헌&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Shor, P. W. (1994). &amp;ldquo;Algorithms for quantum computation: discrete logarithms and factoring&amp;rdquo;. Proceedings 35th Annual Symposium on Foundations of Computer Science.&lt;/li>
&lt;li>Nielsen, M. A., &amp;amp; Chuang, I. L. (2010). &amp;ldquo;Quantum Computation and Quantum Information&amp;rdquo;. Cambridge University Press.&lt;/li>
&lt;li>Qiskit Documentation: &lt;a class="link" href="https://qiskit.org/documentation/" target="_blank" rel="noopener"
>https://qiskit.org/documentation/&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>