{ "cells": [ { "cell_type": "markdown", "id": "d2aec813", "metadata": {}, "source": [ "# Demo Play" ] }, { "cell_type": "markdown", "id": "62c3757f", "metadata": {}, "source": [ "ここでは`PItBE`を用いてBlock-Encoding法を実行する際の手順を紹介する。\\\n", "本モジュールを用いる際には一読することを推奨する。" ] }, { "cell_type": "markdown", "id": "695e742b", "metadata": {}, "source": [ "### 計算条件\n", "\n", "- 量子回路上で再現したい行列\\\n", " 粒子6個の系に対する横磁場イジングモデルのハミルトニアン$\\hat{H}$\n", " $$\n", " \\hat{H} = 0.5\\sum_i^{6}\\hat{Z}_i\\hat{Z}_{i+1} + 0.8\\sum_i^{6}\\hat{X}_i\n", " $$\n", "- 行列を作用させたい量子状態\\\n", " スピンが$+z$方向にそろった系\n", " $$\n", " |\\psi\\rangle = |000000\\rangle\n", " $$" ] }, { "cell_type": "markdown", "id": "bf9f130a", "metadata": {}, "source": [ "### 実行" ] }, { "cell_type": "markdown", "id": "18584b39", "metadata": {}, "source": [ "#### 実行に向けての準備\n", "\n", "初めに補助ビット部分の量子状態を決定する行列を作成する。\\\n", "理想としてはPauli回転ゲートの積によって表現したいが、任意の状態を生成するPauli回転ゲートの積を作成する方法は現状提案されていない。\\\n", "そのため今回は全て0の状態をとる補助ビットに対して作用させることで、任意の量子状態に変換させるユニタリゲートを用いることとする。" ] }, { "cell_type": "code", "execution_count": null, "id": "5397d364", "metadata": {}, "outputs": [], "source": [ "import math\n", "import numpy as np \n", "import pitbe\n", "\n", "# The coefficients and Pauli matrix production \n", "# in the linear combination representation of the matrix to be Block-Encoded\n", "coefficients = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8]\n", "paulies = ['Z0Z1', 'Z1Z2', 'Z2Z3', 'Z3Z4', 'Z4Z5', 'Z5Z0', \n", " 'X0', 'X1', 'X2', 'X3', 'X4', 'X5']\n", "\n", "# Normalize coefficients\n", "norm_cf = np.sum(np.abs(coefficients))\n", "alphas = (np.sqrt(np.abs(coefficients)) / np.sqrt(np.sum(np.abs(coefficients))))\n", "if math.floor(np.log2(len(alphas))) != np.log2(len(alphas)):\n", " zero_list = np.zeros(2**(math.floor(np.log2(len(alphas))) + 1) - len(alphas))\n", " alphas = np.append(alphas, zero_list)\n", "\n", "# Creating a matrix for adjusting coefficient signs\n", "opposite_list = np.ones(len(alphas))\n", "for j in range(len(coefficients)):\n", " if (coefficients[j] < 0):\n", " opposite_list[j] = -1\n", "\n", "# Creating a matrix for adjusting ancilla qubits\n", "cf = pitbe.coeff_make(alphas)\n", "mat_for_anci = pitbe.mat_maker(alphas, cf)\n" ] }, { "cell_type": "markdown", "id": "13a988f5", "metadata": {}, "source": [ "#### 量子回路の作成\n", "\n", "次にBlock-Encoding法を実行する量子回路を作成する。\\\n", "量子回路の流れはBlock-Encoding法について説明したページを参照。\\\n", "今回は`Qulacs`をシュミレータとして選択して実行する。" ] }, { "cell_type": "code", "execution_count": null, "id": "ea37a203", "metadata": {}, "outputs": [], "source": [ "from qulacs import QuantumState, QuantumCircuit\n", "from qulacs.state import inner_product\n", "from qulacs.gate import X, Y, Z, DenseMatrix, H, CNOT, to_matrix_gate, CZ, RY, RZ, merge\n", "from qulacs.observable import create_observable_from_openfermion_text\n", "from qulacs.quantum_operator import create_quantum_operator_from_openfermion_file\n", "from qulacs.quantum_operator import create_quantum_operator_from_openfermion_text\n", "from qulacsvis import circuit_drawer\n", "\n", "# Detect the number of main qubits and ancilla qubits\n", "main = pitbe.total_search(paulies)\n", "anci = int(np.log2(len(alphas)))\n", "\n", "# Prepare the control qubit information\n", "cont_list = []\n", "for j in range(len(paulies)):\n", " cont_list.append(pitbe.cont_order(j, anci))\n", "\n", "# Create quantum circuit and quantum state\n", "total = anci + main\n", "state = QuantumState(total)\n", "state.set_zero_state()\n", "circ = QuantumCircuit(total)\n", "\n", "# Convert matrices into quantum gates\n", "gate = DenseMatrix([j for j in range(anci)], mat_for_anci)\n", "opp_gate = DenseMatrix([j for j in range(anci)], np.diag(opposite_list))\n", "gate_dag = gate.get_inverse()\n", "\n", "# Create quantum circuit\n", "circ.add_gate(gate)\n", "circ.add_gate(opp_gate) \n", "for j in range(len(cont_list)):\n", " pitbe.circ_make(paulies[j], cont_list[j], circ, total, anci)\n", "circ.add_gate(gate_dag)\n" ] }, { "cell_type": "markdown", "id": "90da9e49", "metadata": {}, "source": [ "#### 量子回路の実行・結果の分析\n", "\n", "最後に量子回路を実行し、結果を分析する。\\\n", "具体的には実行結果から補助ビット部分の値が全て`0`のものを選び取り、係数を調節して出力する。\\\n", "なおBlock-Encoding法について解説したページでも触れたように、実行後に得られるのはあくまでも再現した行列を作用させた量子状態についての情報であり、固有値が直接出力されるわけではない。" ] }, { "cell_type": "code", "execution_count": null, "id": "cea4de9a", "metadata": {}, "outputs": [], "source": [ "# Run the quantum circuit\n", "circ.update_quantum_state(state)\n", "\n", "# Calculate probability to get the result of Block-Encoding\n", "obser_order = []\n", "for j in range(anci):\n", " obser_order.append(0)\n", "for j in range(main):\n", " obser_order.append(2) \n", "prob = state.get_marginal_probability(obser_order)\n", "\n", "# Analyze the result of Block-Encoding\n", "res_state = state.get_vector()\n", "desire_state = []\n", "for i in range(2**anci):\n", " desire_state.append(res_state[2**anci*i]/prob**0.5*norm_cf)\n", "print(desire_state)" ] }, { "cell_type": "markdown", "id": "0438da75", "metadata": {}, "source": [ "この結果は実際にハミルトニアン$\\hat{H}$を量子状態$|\\psi\\rangle$に作用させた結果\n", "$\\hat{H}|\\psi\\rangle$と一致している。\\\n", "以上までが本モジュール`PItBE`を用いてBlock-Encoding法を実行する一連の流れである。" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.11.6" } }, "nbformat": 4, "nbformat_minor": 5 }