Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,088 changes: 2,088 additions & 0 deletions 2025-04-10.ipynb

Large diffs are not rendered by default.

572 changes: 572 additions & 0 deletions 2025-04-17.ipynb

Large diffs are not rendered by default.

1,076 changes: 1,076 additions & 0 deletions 2025-05-15.ipynb

Large diffs are not rendered by default.

910 changes: 910 additions & 0 deletions 2025-05-22.ipynb

Large diffs are not rendered by default.

403 changes: 403 additions & 0 deletions assignment_2025-04-17.ipynb

Large diffs are not rendered by default.

632 changes: 632 additions & 0 deletions assignment_2025-05-15.ipynb

Large diffs are not rendered by default.

318 changes: 318 additions & 0 deletions assignment_2025-05-22.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"editable": true,
"id": "view-in-github",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"source": [
"<a href=\"https://colab.research.google.com/github/UTokyo-ICEPP/qc-workbook-lecturenotes/blob/branch-2025/assignment_2025-05-22.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"editable": true,
"id": "-wDjEijm7mbx",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"source": [
"# 【課題】量子フーリエ変換と量子ダイナミクスシミュレーション"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"editable": true,
"id": "928gcrwyYnke",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"outputs": [],
"source": [
"import sys\n",
"import shutil\n",
"import tarfile\n",
"from google.colab import drive\n",
"drive.mount('/content/gdrive')\n",
"shutil.copy('/content/gdrive/MyDrive/qcintro.tar.gz', '.')\n",
"with tarfile.open('qcintro.tar.gz', 'r:gz') as tar:\n",
" tar.extractall(path='/root/.local')\n",
"\n",
"sys.path.append('/root/.local/lib/python3.11/site-packages')\n",
"\n",
"!git clone -b branch-2024 https://github.com/UTokyo-ICEPP/qc-workbook-lecturenotes\n",
"!cp -r qc-workbook-lecturenotes/qc_workbook /root/.local/lib/python3.11/site-packages/"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"editable": true,
"id": "a6494e44-e1ca-4af8-8b79-b3750fcee037",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"outputs": [],
"source": [
"# まずは全てインポート\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from IPython.display import Math\n",
"from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, transpile\n",
"from qiskit.circuit import Parameter\n",
"from qiskit.providers import JobStatus\n",
"from qiskit_aer import AerSimulator\n",
"from qiskit_aer.primitives import SamplerV2 as Sampler\n",
"from qc_workbook.dynamics import make_heisenberg_circuits, plot_heisenberg_spins"
]
},
{
"cell_type": "markdown",
"metadata": {
"editable": true,
"id": "AXZ6tdfD7rcj",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"source": [
"## 問題1: cos型の確率分布を作る\n",
"\n",
"測定でビット列 $k$ を得る確率が $\\frac{1}{2}[1+\\cos(8\\pi k /2^5)]$ となるような量子回路を作ってください。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"editable": true,
"id": "GG80puvq7r5X",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"outputs": [],
"source": [
"num_qubits = 5\n",
"\n",
"circuit = QuantumCircuit(num_qubits)\n",
"\n",
"##################\n",
"### EDIT BELOW ###\n",
"##################\n",
"\n",
"# Set up a superposition of computational basis states\n",
"\n",
"##################\n",
"### EDIT ABOVE ###\n",
"##################\n",
"\n",
"# 実習の量子フーリエ変換回路\n",
"\n",
"for itarg in range(num_qubits - 1, -1, -1):\n",
" # 標的ビットにアダマールゲートをかける\n",
" circuit.h(itarg)\n",
" # target - 1から0まで制御ビットについてループ\n",
" for ictrl in range(itarg - 1, -1, -1):\n",
" # 標的と制御ビットのインデックスに応じた角度で制御Pゲートをかける\n",
" power = ictrl - itarg - 1 + num_qubits\n",
" circuit.cp((2 ** power) * 2. * np.pi / (2 ** num_qubits), ictrl, itarg)\n",
"\n",
" # 回路図を見やすくするためにバリアを入れる\n",
" circuit.barrier()\n",
"\n",
"# 最後にビットの順番を反転させる\n",
"for i in range(num_qubits // 2):\n",
" circuit.swap(i, num_qubits - 1 - i)\n",
"\n",
"circuit.measure_all()\n",
"\n",
"# シミュレータ上のSamplerを利用\n",
"simulator = AerSimulator()\n",
"sampler = Sampler()\n",
"shots = 100000\n",
"\n",
"circuit = transpile(circuit, backend=simulator)\n",
"sim_job = sampler.run([circuit], shots=shots)\n",
"counts_dict = sim_job.result()[0].data.meas.get_counts()\n",
"\n",
"# 測定結果をプロットしやすいようにアレイに変換\n",
"counts = np.zeros(2 ** num_qubits)\n",
"for key, value in counts_dict.items():\n",
" counts[int(key, 2)] = value\n",
"counts /= shots\n",
"\n",
"# 測定結果と理論曲線をプロット\n",
"plt.scatter(np.arange(2 ** num_qubits), counts, label='observed')\n",
"x = np.linspace(0., 2 ** num_qubits, 400)\n",
"y = (1. + np.cos(8. * np.pi * x / 2 ** num_qubits)) / 2 ** num_qubits\n",
"plt.plot(x, y, label='target')\n",
"plt.legend();"
]
},
{
"cell_type": "markdown",
"metadata": {
"editable": true,
"id": "xzDk3oCi78FH",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"source": [
"## 問題2: ハイゼンベルグモデル、X方向のスピン\n",
"\n",
"講義で扱ったハイゼンベルグモデルのシミュレーションで、各スピンの$X$方向の期待値の時間発展を測定する回路を書き、実習時と同様に時間に対してプロットしてください。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"editable": true,
"id": "llzpae9-8IrO",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"outputs": [],
"source": [
"n = 5\n",
"M = 10\n",
"omegadt = 0.1\n",
"\n",
"shots = 100000\n",
"\n",
"# Define the circuits\n",
"circuits = []\n",
"\n",
"circuit = QuantumCircuit(n)\n",
"\n",
"# Bit 0 in state 1/sqrt(2)(|0> + |1>)\n",
"circuit.h(0)\n",
"\n",
"for istep in range(M):\n",
" for j in range(n - 1):\n",
" # ZZ\n",
" circuit.cx(j, j + 1)\n",
" circuit.rz(-omegadt, j + 1)\n",
" circuit.cx(j, j + 1)\n",
"\n",
" # XX\n",
" circuit.h(j)\n",
" circuit.h(j + 1)\n",
" circuit.cx(j, j + 1)\n",
" circuit.rz(-omegadt, j + 1)\n",
" circuit.cx(j, j + 1)\n",
" circuit.h(j)\n",
" circuit.h(j + 1)\n",
"\n",
" # YY\n",
" circuit.p(-np.pi / 2., j)\n",
" circuit.p(-np.pi / 2., j + 1)\n",
" circuit.h(j)\n",
" circuit.h(j + 1)\n",
" circuit.cx(j, j + 1)\n",
" circuit.rz(-omegadt, j + 1)\n",
" circuit.cx(j, j + 1)\n",
" circuit.h(j)\n",
" circuit.h(j + 1)\n",
" circuit.p(np.pi / 2., j)\n",
" circuit.p(np.pi / 2., j + 1)\n",
"\n",
" # Copy of the circuit up to this point\n",
" snapshot = circuit.copy()\n",
"\n",
" ##################\n",
" ### EDIT BELOW ###\n",
" ##################\n",
"\n",
" # Set up the observable for this snapshot\n",
" #snapshot.?\n",
"\n",
" ##################\n",
" ### EDIT ABOVE ###\n",
" ##################\n",
"\n",
" snapshot.measure_all()\n",
" circuits.append(snapshot)\n",
"\n",
"simulator = AerSimulator()\n",
"\n",
"circuits = transpile(circuits, backend=simulator)\n",
"sampler = Sampler()\n",
"sim_job = sampler.run(circuits, shots=shots)\n",
"sim_counts_list = [result.data.meas.get_counts() for result in sim_job.result()]\n",
"\n",
"# Initial state as a statevector\n",
"initial_state = np.zeros(2 ** n, dtype=np.complex128)\n",
"initial_state[0:2] = np.sqrt(0.5)\n",
"\n",
"plot_heisenberg_spins(sim_counts_list, n, initial_state, omegadt, add_theory_curve=True, spin_component='x')"
]
},
{
"cell_type": "markdown",
"metadata": {
"editable": true,
"id": "EhR2r2MM8OyR",
"slideshow": {
"slide_type": ""
},
"tags": []
},
"source": [
"**提出するもの**\n",
"\n",
"- 問題1、2の完成した回路のコードとシミュレーション結果によるプロット\n",
"- 問題2で一般の方向のスピンの期待値を測定するためにはどうすればいいかの説明"
]
}
],
"metadata": {
"colab": {
"authorship_tag": "ABX9TyPOjpqNR/dhnEPHqQx+Kzya",
"include_colab_link": true,
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
19 changes: 11 additions & 8 deletions qc_workbook/dynamics.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ def plot_heisenberg_spins(counts_list, num_spins, initial_state, omegadt, add_th
legend_items = []
legend_labels = []

spin_basis_change = None
if spin_component == 'x':
spin_basis_change = np.array([[1., 1.], [1., -1.]], dtype=np.complex128) * np.sqrt(0.5)
elif spin_component == 'y':
spin_basis_change = np.array([[1., -1.j], [-1.j, 1.]], dtype=np.complex128) * np.sqrt(0.5)
if spin_basis_change is not None:
basis_change = tensor_product([spin_basis_change] * num_spins)

if add_theory_curve:
# Construct the numerical Hamiltonian matrix from a list of Pauli operators
paulis = list()
Expand All @@ -143,16 +151,8 @@ def plot_heisenberg_spins(counts_list, num_spins, initial_state, omegadt, add_th
# Compute the statevector as a function of time from Hamiltonian diagonalization
time_points, statevectors = diagonalized_evolution(-0.5 * hamiltonian, initial_state, omegadt * num_steps)

spin_basis_change = None
if spin_component == 'x':
spin_basis_change = np.array([[1., 1.], [1., -1.]], dtype=np.complex128) * np.sqrt(0.5)
elif spin_component == 'y':
spin_basis_change = np.array([[1., -1.j], [-1.j, 1.]], dtype=np.complex128) * np.sqrt(0.5)

if spin_basis_change is not None:
basis_change = tensor_product([spin_basis_change] * num_spins)
statevectors = basis_change @ statevectors
initial_state = basis_change @ initial_state

x, y = bit_expectations_sv(time_points, statevectors)

Expand All @@ -171,6 +171,9 @@ def plot_heisenberg_spins(counts_list, num_spins, initial_state, omegadt, add_th
else:
colors = None

if spin_basis_change is not None:
initial_state = basis_change @ initial_state

# Time points
time_points = np.linspace(0., num_steps * omegadt, num_steps + 1, endpoint=True)

Expand Down
8 changes: 2 additions & 6 deletions qc_workbook/grover.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ def make_grover_circuit(n_qubits):
##################
oracle.x(1)
oracle.x(4)
oracle.h(n_qubits-1)
oracle.mct(list(range(n_qubits-1)), n_qubits-1)
oracle.h(n_qubits-1)
oracle.mcp(np.pi, list(range(n_qubits-1)), n_qubits-1)
oracle.x(1)
oracle.x(4)
##################
Expand All @@ -42,9 +40,7 @@ def diffuser(n):
qc.x(list(range(n)))

# multi-controlled Zゲート
qc.h(n-1)
qc.mct(list(range(n-1)), n-1)
qc.h(n-1)
qc.mcp(np.pi, list(range(n-1)), n-1)

qc.x(list(range(n)))
##################
Expand Down
Loading