{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "509f7bd9-b597-4d23-b3af-0a76a7b4d33d",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"格子ハミルトニアンのクリロフ量子対角化\"\n",
        "description: \"Qiskitのパターン環境内でKrylov量子対角化アルゴリズム（KQD）を実装する。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore prefactors */}\n",
        "\n",
        "<span id=\"krylov-quantum-diagonalization-of-lattice-hamiltonians\" />\n",
        "\n",
        "# 格子ハミルトニアンのクリロフ量子対角化\n",
        "\n",
        "*使用時間の目安：ヘロンで20分 r2 （注：あくまでも目安です。 ランタイムは異なるかもしれない)。*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "921c7b04-5b5d-4cfc-aba0-15a61334e619",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## 背景\n",
        "\n",
        "このチュートリアルでは、クリロフ量子対角化アルゴリズム（KQD）をQiskitパターンのコンテキストで実装する方法を示します。 まずアルゴリズムの背景にある理論について学び、次にQPU上での実行デモをご覧いただきます。\n",
        "\n",
        "分野を超えて、私たちは量子系の基底状態の性質を学ぶことに興味を持っています。 例えば、粒子や力の基本的な性質の理解、複雑な物質の挙動の予測と理解、生物化学的な相互作用や反応の理解などである。 ヒルベルト空間の指数関数的な増大と、もつれシステムで生じる相関のため、古典的アルゴリズムは、サイズが大きくなる量子システムに対してこの問題を解くのに苦労する。 その一端は、量子ハードウェアを活用し、変分量子法（例えば、 [変分量子固有値解法](/docs/tutorials/spin-chain-vqe) ）に焦点を当てた既存のアプローチである。 これらの技術は、最適化プロセスで必要とされる関数呼び出しの数が多く、高度なエラー緩和技術が導入されるとリソースのオーバーヘッドが大きくなるため、現在のデバイスでは課題に直面し、その結果、小規模なシステムでの有効性が制限される。 一方、性能保証のあるフォールトトレラント量子法（例えば、 [量子位相推定](https://arxiv.org/abs/quant-ph/0604193) ）は、フォールトトレラント・デバイス上でのみ実行可能な深い回路を必要とする。 このような理由から、 [本総説では](https://arxiv.org/abs/2312.00178)、部分空間法に基づく量子アルゴリズム、クリロフ量子対角化（KQD）アルゴリズムを紹介する。 このアルゴリズムは、既存の量子ハードウェア上で大規模に実行することができ [\\[1\\]](#references)、位相推定と同様の[性能保証を](https://arxiv.org/abs/2110.07492)共有し、高度なエラー緩和技術と互換性があり、古典的にはアクセスできない結果を提供する可能性がある。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f698c82-95ca-4dc4-b9fa-d6e741e2c02c",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## 要件\n",
        "\n",
        "このチュートリアルを始める前に、以下のものがインストールされていることを確認してください：\n",
        "\n",
        "* Qiskit SDK v2.0 またはそれ以降、 [可視化](/docs/api/qiskit/visualization)サポート付き\n",
        "* Qiskit Runtime v0.22 またはそれ以降 ( `pip install qiskit-ibm-runtime` )\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c44956e4-47ab-4b0f-9d6d-553080110062",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## セットアップ\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "ce7d5adc-3ef2-4654-b865-14d5141ce41a",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import scipy as sp\n",
        "import matplotlib.pylab as plt\n",
        "from typing import Union, List\n",
        "import itertools as it\n",
        "import copy\n",
        "from sympy import Matrix\n",
        "import warnings\n",
        "\n",
        "warnings.filterwarnings(\"ignore\")\n",
        "\n",
        "from qiskit.quantum_info import SparsePauliOp, Pauli, StabilizerState\n",
        "from qiskit.circuit import Parameter, IfElseOp\n",
        "from qiskit import QuantumCircuit, QuantumRegister\n",
        "from qiskit.circuit.library import PauliEvolutionGate\n",
        "from qiskit.synthesis import LieTrotter\n",
        "from qiskit.transpiler import Target, CouplingMap\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "\n",
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    EstimatorV2 as Estimator,\n",
        ")\n",
        "\n",
        "\n",
        "def solve_regularized_gen_eig(\n",
        "    h: np.ndarray,\n",
        "    s: np.ndarray,\n",
        "    threshold: float,\n",
        "    k: int = 1,\n",
        "    return_dimn: bool = False,\n",
        ") -> Union[float, List[float]]:\n",
        "    \"\"\"\n",
        "    Method for solving the generalized eigenvalue problem with regularization\n",
        "\n",
        "    Args:\n",
        "        h (numpy.ndarray):\n",
        "            The effective representation of the matrix in the Krylov subspace\n",
        "        s (numpy.ndarray):\n",
        "            The matrix of overlaps between vectors of the Krylov subspace\n",
        "        threshold (float):\n",
        "            Cut-off value for the eigenvalue of s\n",
        "        k (int):\n",
        "            Number of eigenvalues to return\n",
        "        return_dimn (bool):\n",
        "            Whether to return the size of the regularized subspace\n",
        "\n",
        "    Returns:\n",
        "        lowest k-eigenvalue(s) that are the solution of the\n",
        "        regularized generalized eigenvalue problem\n",
        "\n",
        "\n",
        "    \"\"\"\n",
        "    s_vals, s_vecs = sp.linalg.eigh(s)\n",
        "    s_vecs = s_vecs.T\n",
        "    good_vecs = np.array(\n",
        "        [vec for val, vec in zip(s_vals, s_vecs) if val > threshold]\n",
        "    )\n",
        "    h_reg = good_vecs.conj() @ h @ good_vecs.T\n",
        "    s_reg = good_vecs.conj() @ s @ good_vecs.T\n",
        "    if k == 1:\n",
        "        if return_dimn:\n",
        "            return sp.linalg.eigh(h_reg, s_reg)[0][0], len(good_vecs)\n",
        "        else:\n",
        "            return sp.linalg.eigh(h_reg, s_reg)[0][0]\n",
        "    else:\n",
        "        if return_dimn:\n",
        "            return sp.linalg.eigh(h_reg, s_reg)[0][:k], len(good_vecs)\n",
        "        else:\n",
        "            return sp.linalg.eigh(h_reg, s_reg)[0][:k]\n",
        "\n",
        "\n",
        "def single_particle_gs(H_op, n_qubits):\n",
        "    \"\"\"\n",
        "    Find the ground state of the single particle(excitation) sector\n",
        "    \"\"\"\n",
        "    H_x = []\n",
        "    for p, coeff in H_op.to_list():\n",
        "        H_x.append(set([i for i, v in enumerate(Pauli(p).x) if v]))\n",
        "\n",
        "    H_z = []\n",
        "    for p, coeff in H_op.to_list():\n",
        "        H_z.append(set([i for i, v in enumerate(Pauli(p).z) if v]))\n",
        "\n",
        "    H_c = H_op.coeffs\n",
        "\n",
        "    print(\"n_sys_qubits\", n_qubits)\n",
        "\n",
        "    n_exc = 1\n",
        "    sub_dimn = int(sp.special.comb(n_qubits + 1, n_exc))\n",
        "    print(\"n_exc\", n_exc, \", subspace dimension\", sub_dimn)\n",
        "\n",
        "    few_particle_H = np.zeros((sub_dimn, sub_dimn), dtype=complex)\n",
        "\n",
        "    # list all of the possible sets of n_exc indices of 1s in\n",
        "    # n_exc-particle states\n",
        "    sparse_vecs = [\n",
        "        set(vec) for vec in it.combinations(range(n_qubits + 1), r=n_exc)\n",
        "    ]\n",
        "\n",
        "    m = 0\n",
        "    for i, i_set in enumerate(sparse_vecs):\n",
        "        for j, j_set in enumerate(sparse_vecs):\n",
        "            m += 1\n",
        "\n",
        "            if len(i_set.symmetric_difference(j_set)) <= 2:\n",
        "                for p_x, p_z, coeff in zip(H_x, H_z, H_c):\n",
        "                    if i_set.symmetric_difference(j_set) == p_x:\n",
        "                        sgn = ((-1j) ** len(p_x.intersection(p_z))) * (\n",
        "                            (-1) ** len(i_set.intersection(p_z))\n",
        "                        )\n",
        "                    else:\n",
        "                        sgn = 0\n",
        "\n",
        "                    few_particle_H[i, j] += sgn * coeff\n",
        "\n",
        "    gs_en = min(np.linalg.eigvalsh(few_particle_H))\n",
        "    print(\"single particle ground state energy: \", gs_en)\n",
        "    return gs_en"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "76a1c616-a749-48a2-b5fd-8beff760760b",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "## ステップ1：古典的な入力を量子問題にマッピングする\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a166e2a1-3003-4799-9c15-59f5e78b6ea8",
      "metadata": {},
      "source": [
        "<span id=\"the-krylov-space\" />\n",
        "\n",
        "### クリロフ空間\n",
        "\n",
        "次数 $r$ のクリロフ空間 $\\mathcal{K}^r$ は、行列 $A$ の高次乗、 $r-1$ までの行列と参照ベクトル $\\vert v \\rangle$ との乗算によって得られるベクトルによってスパンされる空間である。\n",
        "\n",
        "$$\n",
        "\\mathcal{K}^r = \\left\\{ \\vert v \\rangle, A \\vert v \\rangle, A^2 \\vert v \\rangle, ..., A^{r-1} \\vert v \\rangle \\right\\}\n",
        "$$\n",
        "\n",
        "行列 $A$ がハミルトニアン $H$ の場合、対応する空間をべき乗クリロフ空間 $\\mathcal{K}_P$ と呼ぶことにする。 $A$ がハミルトニアンによって生成される時間発展作用素 $U=e^{-iHt}$ の場合、その空間をユニタリー・クリロフ空間 $\\mathcal{K}_U$ と呼ぶことにする。 $H$ はユニタリー演算子ではないので、私たちが古典的に用いているパワークリロフ部分空間を量子コンピュータ上で直接生成することはできません。 その代わりに、時間発展演算子 $U = e^{-iHt}$、べき乗法と同様の[収束保証が](https://arxiv.org/abs/2110.07492)得られることを示すことができる。 $U$ のべき乗は、異なる時間ステップ $U^k = e^{-iH(kt)}$ となる。\n",
        "\n",
        "$$\n",
        "\\mathcal{K}_U^r = \\left\\{ \\vert \\psi \\rangle, U \\vert \\psi \\rangle, U^2 \\vert \\psi \\rangle, ..., U^{r-1} \\vert \\psi \\rangle \\right\\}\n",
        "$$\n",
        "\n",
        "ユニタリー・クリロフ空間がどのように低エネルギー固有状態を正確に表すことができるかについての詳細な導出は付録を参照。\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "5573ca7e-ab16-4488-88b3-d8d1eba9e20c",
      "metadata": {},
      "source": [
        "<span id=\"krylov-quantum-diagonalization-algorithm\" />\n",
        "\n",
        "### クリロフ量子対角化アルゴリズム\n",
        "\n",
        "対角化したいハミルトニアン $H$ が与えられたら、まず対応するユニタリー・クリロフ空間 $\\mathcal{K}_U$ を考える。そのゴールは、 $\\mathcal{K}_U$ におけるハミルトニアンのコンパクトな表現を見つけることであり、これを $\\tilde{H}$ と呼ぶことにする。クリロフ空間におけるハミルトニアンの射影である $\\tilde{H}$ の行列要素は、以下の期待値を計算することによって求めることができる\n",
        "\n",
        "$$\n",
        "\\tilde{H}_{mn} = \\langle \\psi_m \\vert H \\vert \\psi_n \\rangle =\n",
        "$$\n",
        "\n",
        "$$\n",
        "= \\langle \\psi \\vert  e^{i H t_m}   H e^{-i H t_n} \\vert \\psi \\rangle\n",
        "$$\n",
        "\n",
        "$$\n",
        "= \\langle \\psi \\vert  e^{i H m dt}   H e^{-i H n dt} \\vert \\psi \\rangle\n",
        "$$\n",
        "\n",
        "ここで、 $\\vert \\psi_n \\rangle = e^{-i H t_n} \\vert \\psi \\rangle$ はユニタリー・クリロフ空間のベクトル、 $t_n = n dt$ は時間ステップの倍数 $dt$。 量子コンピュータ上では、各行列要素の計算は、量子状態間のオーバーラップを得ることができる任意のアルゴリズムで行うことができる。 このチュートリアルでは、ハダマード検定に焦点を当てます。 $\\mathcal{K}_U$ の次元が $r$ であることを考えると、その部分空間に投影されるハミルトニアンの次元は $r \\times r$ となる。 $r$ が十分に小さければ（一般に固有エネルギーの推定値の収束を得るには $r<<100$ で十分である）、投影されたハミルトニアン $\\tilde{H}$ を簡単に対角化することができる。しかし、クリロフ空間ベクトルの非直交性のため、 $\\tilde{H}$ を直接対角化することはできません。 重なり具合を測定し、マトリックスを作る必要がある $\\tilde{S}$\n",
        "\n",
        "$$\n",
        "\\tilde{S}_{mn} = \\langle \\psi_m \\vert \\psi_n \\rangle\n",
        "$$\n",
        "\n",
        "これにより、非直交空間における固有値問題（一般化固有値問題とも呼ばれる）を解くことができる\n",
        "\n",
        "$$\n",
        "\\tilde{H} \\ \\vec{c} = E \\ \\tilde{S} \\ \\vec{c}\n",
        "$$\n",
        "\n",
        "$H$ $\\tilde{H}$ 例えば、基底状態のエネルギーの推定値は、最小の固有値 $c$ と、対応する固有ベクトル $\\vec{c}$ から基底状態を求めることで得られる。 $\\vec{c}$ の係数は、 $\\mathcal{K}_U$ にまたがるさまざまなベクトルの寄与を決定する。\n",
        "\n",
        "![fig1.png](https://quantum.cloud.ibm.com/docs/images/tutorials/krylov-subspace-diagonalization/fc662b76-8ad7-4a6c-8c49-5f08c125aee8.avif)\n",
        "\n",
        "図に示すのは、異なる量子状態間の重なりを計算するために用いられる修正ハダマールテストの回路図である。 各行列要素 $\\tilde{H}_{i,j}$、状態 $\\vert \\psi_i \\rangle$、 $\\vert \\psi_j \\rangle$ の間のハダマード検定が行われる。 図では、行列要素と対応する $\\text{Prep} \\; \\psi_i$、 $\\text{Prep} \\; \\psi_j$ の操作の配色によって、このことが強調されている。 したがって、投影ハミルトニアン $\\tilde{H}$ のすべての行列要素を計算するために、クリロフ空間ベクトルのすべての可能な組み合わせに対するハダマルド検定のセットが必要となる。ハダマルド検定回路の一番上のワイヤーはアンシラ量子ビットで、XまたはY基底で測定され、その期待値は状態間の重なりの値を決定します。 一番下のワイヤーは、システム・ハミルトニアンのすべての量子ビットを表している。 $\\text{Prep} \\; \\psi_i$ $\\vert \\psi_i \\rangle$ （ ）、 （ ）はシステム・ハミルトニアンのパウリ分解を表します。ハダマルド検定によって計算される演算のより詳細な導出を以下に示す。 $\\text{Prep} \\; \\psi_j$ $P$ $H = \\sum_i P_i$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1a6d7a4f-6c1f-4069-93d1-f5b670645d7f",
      "metadata": {},
      "source": [
        "<span id=\"define-hamiltonian\" />\n",
        "\n",
        "#### ハミルトニアンを定義する\n",
        "\n",
        "$N$、線形鎖上の量子ビットに対するハイゼンベルグ・ハミルトニアンを考えてみよう： $H= \\sum_{i,j}^N X_i X_j + Y_i Y_j - J Z_i Z_j$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "82163249-bafd-4bc6-9741-20a4077971a7",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[('ZZIIIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IZZIIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIZZIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIZZIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIZZIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIZZIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIZZIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIZZIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIZZIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIZZIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIZZIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIZZIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIZZIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIZZIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIZZIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIZZIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIZZIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIZZIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIZZIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIZZIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIZZIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIZZIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIZZIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIZZIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIZZIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIZZIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIZZII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIIZZI', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIIIZZ', 1), ('XXIIIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IXXIIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIXXIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIXXIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIXXIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIXXIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIXXIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIXXIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIXXIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIXXIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIXXIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIXXIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIXXIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIXXIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIXXIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIXXIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIXXIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIXXIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIXXIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIXXIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIXXIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIXXIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIXXIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIXXIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIXXIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIXXIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIXXII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIIXXI', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIIIXX', 1), ('YYIIIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IYYIIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIYYIIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIYYIIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIYYIIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIYYIIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIYYIIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIYYIIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIYYIIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIYYIIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIYYIIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIYYIIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIYYIIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIYYIIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIYYIIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIYYIIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIYYIIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIYYIIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIYYIIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIYYIIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIYYIIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIYYIIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIYYIIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIYYIIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIYYIIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIYYIII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIYYII', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIIYYI', 1), ('IIIIIIIIIIIIIIIIIIIIIIIIIIIIYY', 1)]\n"
          ]
        }
      ],
      "source": [
        "# Define problem Hamiltonian.\n",
        "n_qubits = 30\n",
        "J = 1  # coupling strength for ZZ interaction\n",
        "\n",
        "# Define the Hamiltonian:\n",
        "H_int = [[\"I\"] * n_qubits for _ in range(3 * (n_qubits - 1))]\n",
        "for i in range(n_qubits - 1):\n",
        "    H_int[i][i] = \"Z\"\n",
        "    H_int[i][i + 1] = \"Z\"\n",
        "for i in range(n_qubits - 1):\n",
        "    H_int[n_qubits - 1 + i][i] = \"X\"\n",
        "    H_int[n_qubits - 1 + i][i + 1] = \"X\"\n",
        "for i in range(n_qubits - 1):\n",
        "    H_int[2 * (n_qubits - 1) + i][i] = \"Y\"\n",
        "    H_int[2 * (n_qubits - 1) + i][i + 1] = \"Y\"\n",
        "H_int = [\"\".join(term) for term in H_int]\n",
        "H_tot = [(term, J) if term.count(\"Z\") == 2 else (term, 1) for term in H_int]\n",
        "\n",
        "# Get operator\n",
        "H_op = SparsePauliOp.from_list(H_tot)\n",
        "print(H_tot)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f26578ba-24ad-42f3-baad-c348d3c05699",
      "metadata": {},
      "source": [
        "<span id=\"set-parameters-for-the-algorithm\" />\n",
        "\n",
        "#### アルゴリズムのパラメータを設定する\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8d376c0e-fb7a-4a41-838a-ae041d5c9afa",
      "metadata": {},
      "source": [
        "我々は（ハミルトニアンノルムの上限に基づいて）時間ステップ `dt` の値を発見的に選択する。 文献 [\\[2\\]](#references) は、十分に小さなタイムステップが $\\pi/\\vert \\vert H \\vert \\vert$、この値を過大評価するよりも過小評価する方がある点までは望ましいことを示した。過大評価すると、高エネルギー状態からの寄与がクリロフ空間の最適状態さえも破壊してしまうからである。 一方、 $dt$ を小さくしすぎると、クリロフ基底ベクトルのタイムステップごとの違いが小さくなるため、クリロフ部分空間のコンディショニングが悪くなる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "963dd2e9-f4ea-456d-b4ed-e3d05a114082",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "np.float64(0.10833078115826875)"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get Hamiltonian restricted to single-particle states\n",
        "single_particle_H = np.zeros((n_qubits, n_qubits))\n",
        "for i in range(n_qubits):\n",
        "    for j in range(i + 1):\n",
        "        for p, coeff in H_op.to_list():\n",
        "            p_x = Pauli(p).x\n",
        "            p_z = Pauli(p).z\n",
        "            if all(\n",
        "                p_x[k] == ((i == k) + (j == k)) % 2 for k in range(n_qubits)\n",
        "            ):\n",
        "                sgn = (\n",
        "                    (-1j) ** sum(p_z[k] and p_x[k] for k in range(n_qubits))\n",
        "                ) * ((-1) ** p_z[i])\n",
        "            else:\n",
        "                sgn = 0\n",
        "            single_particle_H[i, j] += sgn * coeff\n",
        "for i in range(n_qubits):\n",
        "    for j in range(i + 1, n_qubits):\n",
        "        single_particle_H[i, j] = np.conj(single_particle_H[j, i])\n",
        "\n",
        "# Set dt according to spectral norm\n",
        "dt = np.pi / np.linalg.norm(single_particle_H, ord=2)\n",
        "dt"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d2bcc2b9-ca7c-4147-8e6b-0f15208297ce",
      "metadata": {},
      "source": [
        "そして、アルゴリズムの他のパラメータを設定する。 このチュートリアルでは、5次元のクリロフ空間を使うことに限定する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "ddde76b8-446f-4cd5-bc4b-8f00e2ec726c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Set parameters for quantum Krylov algorithm\n",
        "krylov_dim = 5  # size of Krylov subspace\n",
        "num_trotter_steps = 6\n",
        "dt_circ = dt / num_trotter_steps"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3c0dcc08-6963-4e14-a50c-21c5dd7f8ade",
      "metadata": {},
      "source": [
        "<span id=\"state-preparation\" />\n",
        "\n",
        "#### 状態準備\n",
        "\n",
        "基底状態と重なる参照状態（ $\\vert \\psi \\rangle$ ）を選ぶ。 このハミルトニアンでは、中央の量子ビット（ $\\vert 00..010...00 \\rangle$ ）が励起された状態を参照状態として用いる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "70161afe-8ace-4642-894a-cd21ed77a3b9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/krylov-quantum-diagonalization/extracted-outputs/70161afe-8ace-4642-894a-cd21ed77a3b9-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc_state_prep = QuantumCircuit(n_qubits)\n",
        "qc_state_prep.x(int(n_qubits / 2) + 1)\n",
        "qc_state_prep.draw(\"mpl\", scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1786de6b-476f-47ea-9c20-3464d3cfbbdb",
      "metadata": {},
      "source": [
        "<span id=\"time-evolution\" />\n",
        "\n",
        "#### 時間発展\n",
        "\n",
        "我々は、与えられたハミルトニアンによって生成される時間発展演算子を実現することができる。 $U=e^{-iHt}$、 [リー・トロッター近似を](/docs/api/qiskit/qiskit.synthesis.LieTrotter)経由する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "a23b9e9c-5dc8-447f-8c73-b4fa01630c8f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<qiskit.circuit.instructionset.InstructionSet at 0x11eef9be0>"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "t = Parameter(\"t\")\n",
        "\n",
        "## Create the time-evo op circuit\n",
        "evol_gate = PauliEvolutionGate(\n",
        "    H_op, time=t, synthesis=LieTrotter(reps=num_trotter_steps)\n",
        ")\n",
        "\n",
        "qr = QuantumRegister(n_qubits)\n",
        "qc_evol = QuantumCircuit(qr)\n",
        "qc_evol.append(evol_gate, qargs=qr)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "41c2cc43-51a2-42c3-88ee-a3b7b30eabb4",
      "metadata": {},
      "source": [
        "<span id=\"hadamard-test\" />\n",
        "\n",
        "#### ハダマール検定\n",
        "\n",
        "![fig2.png](https://quantum.cloud.ibm.com/docs/images/tutorials/krylov-subspace-diagonalization/c5263851-6067-4ca2-8e0c-a835631cdc7f.avif)\n",
        "\n",
        "$$\n",
        "\\begin{equation*}\n",
        "    |0\\rangle|0\\rangle^N \\quad\\longrightarrow\\quad \\frac{1}{\\sqrt{2}}\\Big(|0\\rangle + |1\\rangle \\Big)|0\\rangle^N \\quad\\longrightarrow\\quad \\frac{1}{\\sqrt{2}}\\Big(|0\\rangle|0\\rangle^N+|1\\rangle |\\psi_i\\rangle\\Big) \\quad\\longrightarrow\\quad \\frac{1}{\\sqrt{2}}\\Big(|0\\rangle |0\\rangle^N+|1\\rangle P |\\psi_i\\rangle\\Big) \\quad\\longrightarrow\\quad\\frac{1}{\\sqrt{2}}\\Big(|0\\rangle |\\psi_j\\rangle+|1\\rangle P|\\psi_i\\rangle\\Big)\n",
        "\\end{equation*}\n",
        "$$\n",
        "\n",
        "ここで、 $P$ はハミルトニアンの分解の項のひとつであり、 $H=\\sum P$、 $\\text{Prep} \\; \\psi_i$、 $\\text{Prep} \\; \\psi_j$ はユニタリー・クリロフ空間の $|\\psi_i\\rangle$、 $|\\psi_j\\rangle$ ベクトルを準備する制御操作であり、 $|\\psi_k\\rangle = e^{-i H k dt } \\vert \\psi \\rangle = e^{-i H k dt } U_{\\psi} \\vert 0 \\rangle^N$。 $X$ を測定するには，まず $H$ を適用する．\n",
        "\n",
        "$$\n",
        "\\begin{equation*}\n",
        "    \\longrightarrow\\quad\\frac{1}{2}|0\\rangle\\Big( |\\psi_j\\rangle + P|\\psi_i\\rangle\\Big) + \\frac{1}{2}|1\\rangle\\Big(|\\psi_j\\rangle - P|\\psi_i\\rangle\\Big)\n",
        "\\end{equation*}\n",
        "$$\n",
        "\n",
        "...それから測定する：\n",
        "\n",
        "$$\n",
        "\\begin{equation*}\n",
        "\\begin{split}\n",
        "    \\Rightarrow\\quad\\langle X\\rangle &= \\frac{1}{4}\\Bigg(\\Big\\|| \\psi_j\\rangle + P|\\psi_i\\rangle \\Big\\|^2-\\Big\\||\\psi_j\\rangle - P|\\psi_i\\rangle\\Big\\|^2\\Bigg) \\\\\n",
        "    &= \\text{Re}\\Big[\\langle\\psi_j| P|\\psi_i\\rangle\\Big].\n",
        "\\end{split}\n",
        "\\end{equation*}\n",
        "$$\n",
        "\n",
        "恒等式から $|a + b\\|^2 = \\langle a + b | a + b \\rangle = \\|a\\|^2 + \\|b\\|^2 + 2\\text{Re}\\langle a | b \\rangle$。同様に、 $Y$ を測定すると、次のようになる\n",
        "\n",
        "$$\n",
        "\\begin{equation*}\n",
        "    \\langle Y\\rangle = \\text{Im}\\Big[\\langle\\psi_j| P|\\psi_i\\rangle\\Big].\n",
        "\\end{equation*}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "7c1efca7-7db9-43a9-bcb7-053ba274d6f6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Circuit for calculating the real part of the overlap in S via Hadamard test\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/krylov-quantum-diagonalization/extracted-outputs/7c1efca7-7db9-43a9-bcb7-053ba274d6f6-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "## Create the time-evo op circuit\n",
        "evol_gate = PauliEvolutionGate(\n",
        "    H_op, time=dt, synthesis=LieTrotter(reps=num_trotter_steps)\n",
        ")\n",
        "\n",
        "## Create the time-evo op dagger circuit\n",
        "evol_gate_d = PauliEvolutionGate(\n",
        "    H_op, time=dt, synthesis=LieTrotter(reps=num_trotter_steps)\n",
        ")\n",
        "evol_gate_d = evol_gate_d.inverse()\n",
        "\n",
        "# Put pieces together\n",
        "qc_reg = QuantumRegister(n_qubits)\n",
        "qc_temp = QuantumCircuit(qc_reg)\n",
        "qc_temp.compose(qc_state_prep, inplace=True)\n",
        "for _ in range(num_trotter_steps):\n",
        "    qc_temp.append(evol_gate, qargs=qc_reg)\n",
        "for _ in range(num_trotter_steps):\n",
        "    qc_temp.append(evol_gate_d, qargs=qc_reg)\n",
        "qc_temp.compose(qc_state_prep.inverse(), inplace=True)\n",
        "\n",
        "# Create controlled version of the circuit\n",
        "controlled_U = qc_temp.to_gate().control(1)\n",
        "\n",
        "# Create hadamard test circuit for real part\n",
        "qr = QuantumRegister(n_qubits + 1)\n",
        "qc_real = QuantumCircuit(qr)\n",
        "qc_real.h(0)\n",
        "qc_real.append(controlled_U, list(range(n_qubits + 1)))\n",
        "qc_real.h(0)\n",
        "\n",
        "print(\n",
        "    \"Circuit for calculating the real part of the overlap in S via Hadamard test\"\n",
        ")\n",
        "qc_real.draw(\"mpl\", fold=-1, scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c72fd5e5-a586-498e-bbc1-0f48ecea49d5",
      "metadata": {},
      "source": [
        "ハダマード・テスト回路は、ネイティブ・ゲートに分解すれば、深い回路になる（デバイスのトポロジーを考慮すれば、さらに増える）\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "06f22c05-6e1c-4540-9dac-884b3400a50e",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Number of layers of 2Q operations 112753\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    \"Number of layers of 2Q operations\",\n",
        "    qc_real.decompose(reps=2).depth(lambda x: x[0].num_qubits == 2),\n",
        ")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "8e15903d-d4a8-4fbe-8f9e-e960e686629e",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "## ステップ2：量子ハードウェア実行に向けた問題の最適化\n",
        "\n",
        "<span id=\"efficient-hadamard-test\" />\n",
        "\n",
        "### 効率的なハダマール検定\n",
        "\n",
        "いくつかの近似を導入し、モデル・ハミルトニアンに関するいくつかの仮定に依存することで、得られたハダマルド・テストの深層回路を最適化することができる。 例えば、次のようなハダマード・テストの回路を考えてみよう：\n",
        "\n",
        "![fig3.png](https://quantum.cloud.ibm.com/docs/images/tutorials/krylov-subspace-diagonalization/35b13797-5a46-486c-b50e-97c205cc9747.avif)\n",
        "\n",
        "ハミルトニアン $H$ の下での $|0\\rangle^N$ の固有値 $E_0$ を古典的に計算できると仮定する。 これはハミルトニアンがU(1)対称性を保存しているときに満たされる。 これは強い仮定のように思えるかもしれないが、ハミルトニアンの作用に影響されない真空状態（この場合、 $|0\\rangle^N$ 状態に対応する）が存在すると仮定しても安全な場合がたくさんある。 これは例えば、安定な分子（電子の数が保存されている）を記述する化学のハミルトニアンに当てはまります。\n",
        "ゲート $\\text{Prep} \\; \\psi$、所望の参照状態 $\\ket{psi} = \\text{Prep} \\; \\psi \\ket{0} = e^{-i H 0 dt} U_{\\psi} \\ket{0}$ を準備することを考えると、例えば、化学のためのHF状態 $\\text{Prep} \\; \\psi$ を準備することは、単一量子ビットNOTの積になるので、制御された- $\\text{Prep} \\; \\psi$ は単なるCNOTの積である。\n",
        "すると、上記の回路は、測定前の以下の状態を実現する：\n",
        "\n",
        "$$\n",
        "\\begin{equation}\n",
        "\\begin{split}\n",
        "    \\ket{0} \\ket{0}^N\\xrightarrow{H}&\\frac{1}{\\sqrt{2}}\n",
        "    \\left(\n",
        "    \\ket{0}\\ket{0}^N+ \\ket{1} \\ket{0}^N\n",
        "    \\right)\\\\\n",
        "    \\xrightarrow{\\text{1-ctrl-init}}&\\frac{1}{\\sqrt{2}}\\left(|0\\rangle|0\\rangle^N+|1\\rangle|\\psi\\rangle\\right)\\\\\n",
        "    \\xrightarrow{U}&\\frac{1}{\\sqrt{2}}\\left(e^{i\\phi}\\ket{0}\\ket{0}^N+\\ket{1} U\\ket{\\psi}\\right)\\\\\n",
        "    \\xrightarrow{\\text{0-ctrl-init}}&\\frac{1}{\\sqrt{2}}\n",
        "    \\left(\n",
        "    e^{i\\phi}\\ket{0} \\ket{\\psi}\n",
        "    +\\ket{1} U\\ket{\\psi}\n",
        "    \\right)\\\\\n",
        "    =&\\frac{1}{2}\n",
        "    \\left(\n",
        "    \\ket{+}\\left(e^{i\\phi}\\ket{\\psi}+U\\ket{\\psi}\\right)\n",
        "    +\\ket{-}\\left(e^{i\\phi}\\ket{\\psi}-U\\ket{\\psi}\\right)\n",
        "    \\right)\\\\\n",
        "    =&\\frac{1}{2}\n",
        "    \\left(\n",
        "    \\ket{+i}\\left(e^{i\\phi}\\ket{\\psi}-iU\\ket{\\psi}\\right)\n",
        "    +\\ket{-i}\\left(e^{i\\phi}\\ket{\\psi}+iU\\ket{\\psi}\\right)\n",
        "    \\right)\n",
        "\\end{split}\n",
        "\\end{equation}\n",
        "$$\n",
        "\n",
        "ここでは、3行目に古典的なシミュレート可能な位相シフト $ U\\ket{0}^N = e^{i\\phi}\\ket{0}^N$。 したがって、期待値は次のように求められる\n",
        "\n",
        "$$\n",
        "\\begin{equation}\n",
        "\\begin{split}\n",
        "    \\langle X\\otimes P\\rangle&=\\frac{1}{4}\n",
        "    \\Big(\n",
        "    \\left(e^{-i\\phi}\\bra{\\psi}+\\bra{\\psi}U^\\dagger\\right)P\\left(e^{i\\phi}\\ket{\\psi}+U\\ket{\\psi}\\right)\n",
        "    \\\\\n",
        "    &\\qquad-\\left(e^{-i\\phi}\\bra{\\psi}-\\bra{\\psi}U^\\dagger\\right)P\\left(e^{i\\phi}\\ket{\\psi}-U\\ket{\\psi}\\right)\n",
        "    \\Big)\\\\\n",
        "    &=\\text{Re}\\left[e^{-i\\phi}\\bra{\\psi}PU\\ket{\\psi}\\right],\n",
        "\\end{split}\n",
        "\\end{equation}\n",
        "$$\n",
        "\n",
        "$$\n",
        "\\begin{equation}\n",
        "\\begin{split}\n",
        "    \\langle Y\\otimes P\\rangle&=\\frac{1}{4}\n",
        "    \\Big(\n",
        "    \\left(e^{-i\\phi}\\bra{\\psi}+i\\bra{\\psi}U^\\dagger\\right)P\\left(e^{i\\phi}\\ket{\\psi}-iU\\ket{\\psi}\\right)\n",
        "    \\\\\n",
        "    &\\qquad-\\left(e^{-i\\phi}\\bra{\\psi}-i\\bra{\\psi}U^\\dagger\\right)P\\left(e^{i\\phi}\\ket{\\psi}+iU\\ket{\\psi}\\right)\n",
        "    \\Big)\\\\\n",
        "    &=\\text{Im}\\left[e^{-i\\phi}\\bra{\\psi}PU\\ket{\\psi}\\right].\n",
        "\\end{split}\n",
        "\\end{equation}\n",
        "$$\n",
        "\n",
        "これらの仮定を用いることで、より少ない制御演算で、関心のある演算子の期待値を書くことができた。 実際には、制御された状態準備（ $\\text{Prep} \\; \\psi$ ）だけを実装すればよく、制御された時間発展は必要ない。 上記のように計算を組み直すことで、結果として得られる回路の深さを大幅に減らすことができる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2e29da5f-b5f5-4b9e-96fc-3fa7ab698398",
      "metadata": {},
      "source": [
        "<span id=\"decompose-time-evolution-operator-with-trotter-decomposition\" />\n",
        "\n",
        "### トロッター分解を用いて時間発展演算子を分解する\n",
        "\n",
        "時間発展演算子を正確に実装する代わりに、トロッター分解を使ってその近似を実装することができる。 ある次数のトロッター分解を数回繰り返すことで、近似からもたらされる誤差をさらに減らすことができる。 以下では、我々が考えているハミルトニアンの相互作用グラフ（最近傍相互作用のみ）に対して、最も効率的な方法でトロッター実装を直接構築する。 実際には、パウリ回転 $R_{xx}$、 $R_{yy}$、 $R_{zz}$ を、 $e^{-i (XX + YY + ZZ) t}$ の近似実装に対応するパラメトリック角度 $t$ で挿入する。 パウリ回転の定義の違いと、実装しようとしている時間発展を考慮すると、 $dt$ の時間発展を達成するためには、パラメー タ $2*dt$ を使用しなければならない。さらに、トロッターステップの繰り返しが奇数の場合、演算の順序を逆にする。これは機能的には等価であるが、隣接する演算を単一の $SU(2)$ ユニタリーで合成することができる。 これにより、一般的な `PauliEvolutionGate()` 機能を使用した場合よりもはるかに浅い回路が得られる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "267716dc-fa23-41bd-abe4-6d4e0499a0f4",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/krylov-quantum-diagonalization/extracted-outputs/267716dc-fa23-41bd-abe4-6d4e0499a0f4-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "t = Parameter(\"t\")\n",
        "\n",
        "# Create instruction for rotation about XX+YY-ZZ:\n",
        "Rxyz_circ = QuantumCircuit(2)\n",
        "Rxyz_circ.rxx(t, 0, 1)\n",
        "Rxyz_circ.ryy(t, 0, 1)\n",
        "Rxyz_circ.rzz(t, 0, 1)\n",
        "Rxyz_instr = Rxyz_circ.to_instruction(label=\"RXX+YY+ZZ\")\n",
        "\n",
        "interaction_list = [\n",
        "    [[i, i + 1] for i in range(0, n_qubits - 1, 2)],\n",
        "    [[i, i + 1] for i in range(1, n_qubits - 1, 2)],\n",
        "]  # linear chain\n",
        "\n",
        "qr = QuantumRegister(n_qubits)\n",
        "trotter_step_circ = QuantumCircuit(qr)\n",
        "for i, color in enumerate(interaction_list):\n",
        "    for interaction in color:\n",
        "        trotter_step_circ.append(Rxyz_instr, interaction)\n",
        "    if i < len(interaction_list) - 1:\n",
        "        trotter_step_circ.barrier()\n",
        "reverse_trotter_step_circ = trotter_step_circ.reverse_ops()\n",
        "\n",
        "qc_evol = QuantumCircuit(qr)\n",
        "for step in range(num_trotter_steps):\n",
        "    if step % 2 == 0:\n",
        "        qc_evol = qc_evol.compose(trotter_step_circ)\n",
        "    else:\n",
        "        qc_evol = qc_evol.compose(reverse_trotter_step_circ)\n",
        "\n",
        "qc_evol.decompose().draw(\"mpl\", fold=-1, scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0a9c3a4d-a678-41e4-b9dd-995fe34341fb",
      "metadata": {},
      "source": [
        "<span id=\"use-an-optimized-circuit-for-state-preparation\" />\n",
        "\n",
        "### 状態準備に最適化された回路を使用する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "70411715-eed3-4cf5-961d-06a6f1e04efc",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/krylov-quantum-diagonalization/extracted-outputs/70411715-eed3-4cf5-961d-06a6f1e04efc-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "control = 0\n",
        "excitation = int(n_qubits / 2) + 1\n",
        "controlled_state_prep = QuantumCircuit(n_qubits + 1)\n",
        "controlled_state_prep.cx(control, excitation)\n",
        "controlled_state_prep.draw(\"mpl\", fold=-1, scale=0.5)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2421ff11-d97a-488a-a382-a652df8c94d6",
      "metadata": {},
      "source": [
        "<span id=\"template-circuits-for-calculating-matrix-elements-of-$tilde{s}$-and-$tilde{h}$-via-hadamard-test\" />\n",
        "\n",
        "### $\\tilde{S}$ および $\\tilde{H}$ の行列要素をHadamardテストを用いて計算するためのテンプレート回路\n",
        "\n",
        "ハダマード・テストで使用される回路の違いは、時間発展演算子の位相と測定される観測値だけである。 したがって、時間発展演算子に依存するゲートのプレースホルダーを持つ、ハダマード・テストの一般的な回路を表すテンプレート回路を用意することができる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "2f102112-4ddc-41ea-999c-db5863bc77ac",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Parameters for the template circuits\n",
        "parameters = []\n",
        "for idx in range(1, krylov_dim):\n",
        "    parameters.append(2 * dt_circ * (idx))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "33ec7c29-904e-4445-a654-405214349a4d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/krylov-quantum-diagonalization/extracted-outputs/33ec7c29-904e-4445-a654-405214349a4d-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create modified hadamard test circuit\n",
        "qr = QuantumRegister(n_qubits + 1)\n",
        "qc = QuantumCircuit(qr)\n",
        "qc.h(0)\n",
        "qc.compose(controlled_state_prep, list(range(n_qubits + 1)), inplace=True)\n",
        "qc.barrier()\n",
        "qc.compose(qc_evol, list(range(1, n_qubits + 1)), inplace=True)\n",
        "qc.barrier()\n",
        "qc.x(0)\n",
        "qc.compose(\n",
        "    controlled_state_prep.inverse(), list(range(n_qubits + 1)), inplace=True\n",
        ")\n",
        "qc.x(0)\n",
        "\n",
        "qc.decompose().draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "157356c9-06bb-411c-87ef-cd1d2f73be6f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The optimized circuit has 2Q gates depth:  74\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    \"The optimized circuit has 2Q gates depth: \",\n",
        "    qc.decompose().decompose().depth(lambda x: x[0].num_qubits == 2),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a59bbc4-72c7-4a55-9a9e-57bb7b469021",
      "metadata": {},
      "source": [
        "我々は、トロッター近似と非制御ユニタリーの組み合わせにより、ハダマード・テストの深さを大幅に削減した\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ca78bfe3-684f-4d3a-b8c2-3d4e55c9ec30",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "## ステップ3: `Qiskit primitives`を使用して実行する\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a082f023-d752-40e4-b693-c4d0da5ba102",
      "metadata": {},
      "source": [
        "バックエンドをインスタンス化し、ランタイムパラメータを設定する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "0d90e4df-e262-4852-a811-ff6a1d3232ae",
      "metadata": {},
      "outputs": [],
      "source": [
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "if (\n",
        "    \"if_else\" not in backend.target.operation_names\n",
        "):  # Needed as \"op_name\" could be \"if_else\"\n",
        "    backend.target.add_instruction(IfElseOp, name=\"if_else\")\n",
        "print(backend.name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2b3f7227-e6ef-4a11-93d6-d3696054b9cc",
      "metadata": {},
      "source": [
        "<span id=\"transpiling-to-a-qpu\" />\n",
        "\n",
        "### QPUへのトランスパイル\n",
        "\n",
        "まず、結合写像から「良好な」性能を持つ量子ビット（ここで「良好」はかなり恣意的であり、主に非常に性能の悪い量子ビットを避けたい）のサブセットを選び、トランスピレーション用の新たなターゲットを作成する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "id": "e123fda1-6454-4893-9612-2b8591e8cfb9",
      "metadata": {},
      "outputs": [],
      "source": [
        "target = backend.target\n",
        "cmap = target.build_coupling_map(filter_idle_qubits=True)\n",
        "cmap_list = list(cmap.get_edges())\n",
        "\n",
        "cust_cmap_list = copy.deepcopy(cmap_list)\n",
        "for q in range(target.num_qubits):\n",
        "    meas_err = target[\"measure\"][(q,)].error\n",
        "    t2 = target.qubit_properties[q].t2 * 1e6\n",
        "    if meas_err > 0.02 or t2 < 100:\n",
        "        for q_pair in cmap_list:\n",
        "            if q in q_pair:\n",
        "                try:\n",
        "                    cust_cmap_list.remove(q_pair)\n",
        "                except:\n",
        "                    continue\n",
        "\n",
        "for q in cmap_list:\n",
        "    op_name = list(target.operation_names_for_qargs(q))[0]\n",
        "    twoq_gate_err = target[f\"{op_name}\"][q].error\n",
        "    if twoq_gate_err > 0.005:\n",
        "        for q_pair in cmap_list:\n",
        "            if q == q_pair:\n",
        "                try:\n",
        "                    cust_cmap_list.remove(q)\n",
        "                except:\n",
        "                    continue\n",
        "\n",
        "\n",
        "cust_cmap = CouplingMap(cust_cmap_list)\n",
        "cust_target = Target.from_configuration(\n",
        "    basis_gates=backend.configuration().basis_gates,\n",
        "    coupling_map=cust_cmap,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "96f79e35-a265-4de4-b98c-f9c84f58f0d5",
      "metadata": {},
      "source": [
        "次に、この新しいターゲットで最適な物理レイアウトに仮想回路をトランスパイルします\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 36,
      "id": "62109c95-79fe-4076-b591-9bd920fd51f4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "depth 52\n",
            "num 2q ops OrderedDict([('rz', 2058), ('sx', 1703), ('cz', 728), ('x', 84), ('barrier', 8)])\n",
            "physical qubits [91, 92, 93, 94, 95, 98, 99, 108, 109, 110, 111, 113, 114, 115, 119, 127, 132, 133, 134, 135, 137, 139, 147, 148, 149, 150, 151, 152, 153, 154, 155]\n"
          ]
        }
      ],
      "source": [
        "basis_gates = list(target.operation_names)\n",
        "pm = generate_preset_pass_manager(\n",
        "    optimization_level=3,\n",
        "    target=cust_target,\n",
        "    basis_gates=basis_gates,\n",
        ")\n",
        "\n",
        "qc_trans = pm.run(qc)\n",
        "\n",
        "print(\"depth\", qc_trans.depth(lambda x: x[0].num_qubits == 2))\n",
        "print(\"num 2q ops\", qc_trans.count_ops())\n",
        "print(\n",
        "    \"physical qubits\",\n",
        "    sorted(\n",
        "        [\n",
        "            idx\n",
        "            for idx, qb in qc_trans.layout.initial_layout.get_physical_bits().items()\n",
        "            if qb._register.name != \"ancilla\"\n",
        "        ]\n",
        "    ),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9b9b0170-b96a-47b9-b5ab-5112d02338a3",
      "metadata": {},
      "source": [
        "<span id=\"create-pubs-for-execution-with-estimator\" />\n",
        "\n",
        "### Estimatorによる実行用のPUBを作成する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bcfd6693-d1fb-44e4-9b06-c70e6766e877",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Define observables to measure for S\n",
        "observable_S_real = \"I\" * (n_qubits) + \"X\"\n",
        "observable_S_imag = \"I\" * (n_qubits) + \"Y\"\n",
        "\n",
        "observable_op_real = SparsePauliOp(\n",
        "    observable_S_real\n",
        ")  # define a sparse pauli operator for the observable\n",
        "observable_op_imag = SparsePauliOp(observable_S_imag)\n",
        "\n",
        "layout = qc_trans.layout  # get layout of transpiled circuit\n",
        "observable_op_real = observable_op_real.apply_layout(\n",
        "    layout\n",
        ")  # apply physical layout to the observable\n",
        "observable_op_imag = observable_op_imag.apply_layout(layout)\n",
        "observable_S_real = (\n",
        "    observable_op_real.paulis.to_labels()\n",
        ")  # get the label of the physical observable\n",
        "observable_S_imag = observable_op_imag.paulis.to_labels()\n",
        "\n",
        "observables_S = [[observable_S_real], [observable_S_imag]]\n",
        "\n",
        "\n",
        "# Define observables to measure for H\n",
        "# Hamiltonian terms to measure\n",
        "observable_list = []\n",
        "for pauli, coeff in zip(H_op.paulis, H_op.coeffs):\n",
        "    # print(pauli)\n",
        "    observable_H_real = pauli[::-1].to_label() + \"X\"\n",
        "    observable_H_imag = pauli[::-1].to_label() + \"Y\"\n",
        "    observable_list.append([observable_H_real])\n",
        "    observable_list.append([observable_H_imag])\n",
        "\n",
        "layout = qc_trans.layout\n",
        "\n",
        "observable_trans_list = []\n",
        "for observable in observable_list:\n",
        "    observable_op = SparsePauliOp(observable)\n",
        "    observable_op = observable_op.apply_layout(layout)\n",
        "    observable_trans_list.append([observable_op.paulis.to_labels()])\n",
        "\n",
        "observables_H = observable_trans_list\n",
        "\n",
        "\n",
        "# Define a sweep over parameter values\n",
        "params = np.vstack(parameters).T\n",
        "\n",
        "\n",
        "# Estimate the expectation value for all combinations of\n",
        "# observables and parameter values, where the pub result will have\n",
        "# shape (# observables, # parameter values).\n",
        "pub = (qc_trans, observables_S + observables_H, params)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8bd27e84-d673-4326-9004-f3be5a65aed3",
      "metadata": {},
      "source": [
        "<span id=\"run-circuits\" />\n",
        "\n",
        "### 回路を実行する\n",
        "\n",
        "$t=0$ の回路は古典的に計算可能である\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "768cd443-2ed8-4ba2-ba9d-98491b36fa54",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "(25+0j)\n"
          ]
        }
      ],
      "source": [
        "qc_cliff = qc.assign_parameters({t: 0})\n",
        "\n",
        "\n",
        "# Get expectation values from experiment\n",
        "S_expval_real = StabilizerState(qc_cliff).expectation_value(\n",
        "    Pauli(\"I\" * (n_qubits) + \"X\")\n",
        ")\n",
        "S_expval_imag = StabilizerState(qc_cliff).expectation_value(\n",
        "    Pauli(\"I\" * (n_qubits) + \"Y\")\n",
        ")\n",
        "\n",
        "# Get expectation values\n",
        "S_expval = S_expval_real + 1j * S_expval_imag\n",
        "\n",
        "H_expval = 0\n",
        "for obs_idx, (pauli, coeff) in enumerate(zip(H_op.paulis, H_op.coeffs)):\n",
        "    # Get expectation values from experiment\n",
        "    expval_real = StabilizerState(qc_cliff).expectation_value(\n",
        "        Pauli(pauli[::-1].to_label() + \"X\")\n",
        "    )\n",
        "    expval_imag = StabilizerState(qc_cliff).expectation_value(\n",
        "        Pauli(pauli[::-1].to_label() + \"Y\")\n",
        "    )\n",
        "    expval = expval_real + 1j * expval_imag\n",
        "\n",
        "    # Fill-in matrix elements\n",
        "    H_expval += coeff * expval\n",
        "\n",
        "\n",
        "print(H_expval)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "794edf4c-d539-4864-865d-52a88a450b5c",
      "metadata": {},
      "source": [
        "Estimatorを使用して、 $S$ および $\\tilde{H}$ の回路を実行する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "9059dc9e-9203-4572-92c4-76e9c85dfed9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Experiment options\n",
        "num_randomizations = 300\n",
        "num_randomizations_learning = 30\n",
        "shots_per_randomization = 100\n",
        "noise_factors = [1, 1.2, 1.4]\n",
        "learning_pair_depths = [0, 4, 24, 48]\n",
        "\n",
        "\n",
        "experimental_opts = {}\n",
        "experimental_opts[\"resilience\"] = {\n",
        "    \"measure_mitigation\": True,\n",
        "    \"measure_noise_learning\": {\n",
        "        \"num_randomizations\": num_randomizations_learning,\n",
        "        \"shots_per_randomization\": shots_per_randomization,\n",
        "    },\n",
        "    \"zne_mitigation\": True,\n",
        "    \"zne\": {\"noise_factors\": noise_factors},\n",
        "    \"layer_noise_learning\": {\n",
        "        \"max_layers_to_learn\": 10,\n",
        "        \"layer_pair_depths\": learning_pair_depths,\n",
        "        \"shots_per_randomization\": shots_per_randomization,\n",
        "        \"num_randomizations\": num_randomizations_learning,\n",
        "    },\n",
        "    \"zne\": {\n",
        "        \"amplifier\": \"pea\",\n",
        "        \"extrapolated_noise_factors\": [0] + noise_factors,\n",
        "    },\n",
        "}\n",
        "experimental_opts[\"twirling\"] = {\n",
        "    \"num_randomizations\": num_randomizations,\n",
        "    \"shots_per_randomization\": shots_per_randomization,\n",
        "    \"strategy\": \"all\",\n",
        "}\n",
        "\n",
        "estimator = Estimator(mode=backend, options=experimental_opts)\n",
        "\n",
        "\n",
        "job = estimator.run([pub])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9524e609-b457-42e9-9de7-8dbd4464ac74",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "## ステップ4：後処理を行い、結果を希望の古典形式で返す\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 46,
      "id": "30d72032-02e4-40e7-af28-cadda2f7f3bd",
      "metadata": {},
      "outputs": [],
      "source": [
        "results = job.result()[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8149d431-f069-4567-a0be-0cc4ed8d523b",
      "metadata": {},
      "source": [
        "<span id=\"calculate-effective-hamiltonian-and-overlap-matrices\" />\n",
        "\n",
        "### 有効ハミルトニアンとオーバーラップ行列を計算する\n",
        "\n",
        "まず、制御されていない時間発展中に $\\vert 0 \\rangle$ 状態によって蓄積された位相を計算する\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 47,
      "id": "34ba8b05-d52c-4b0f-8d28-acaf7a5ddffc",
      "metadata": {},
      "outputs": [],
      "source": [
        "prefactors = [\n",
        "    np.exp(-1j * sum([c for p, c in H_op.to_list() if \"Z\" in p]) * i * dt)\n",
        "    for i in range(1, krylov_dim)\n",
        "]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36875c8b-36c8-464b-9f0e-7a79e17d5fef",
      "metadata": {},
      "source": [
        "回路の実行結果が得られたら、データを後処理して、以下の行列要素を計算することができる。 $S$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 48,
      "id": "16dd2534-8d5f-40f7-a938-5d519475fd8d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Assemble S, the overlap matrix of dimension D:\n",
        "S_first_row = np.zeros(krylov_dim, dtype=complex)\n",
        "S_first_row[0] = 1 + 0j\n",
        "\n",
        "# Add in ancilla-only measurements:\n",
        "for i in range(krylov_dim - 1):\n",
        "    # Get expectation values from experiment\n",
        "    expval_real = results.data.evs[0][0][\n",
        "        i\n",
        "    ]  # automatic extrapolated evs if ZNE is used\n",
        "    expval_imag = results.data.evs[1][0][\n",
        "        i\n",
        "    ]  # automatic extrapolated evs if ZNE is used\n",
        "\n",
        "    # Get expectation values\n",
        "    expval = expval_real + 1j * expval_imag\n",
        "    S_first_row[i + 1] += prefactors[i] * expval\n",
        "\n",
        "S_first_row_list = S_first_row.tolist()  # for saving purposes\n",
        "\n",
        "\n",
        "S_circ = np.zeros((krylov_dim, krylov_dim), dtype=complex)\n",
        "\n",
        "# Distribute entries from first row across matrix:\n",
        "for i, j in it.product(range(krylov_dim), repeat=2):\n",
        "    if i >= j:\n",
        "        S_circ[j, i] = S_first_row[i - j]\n",
        "    else:\n",
        "        S_circ[j, i] = np.conj(S_first_row[j - i])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 49,
      "id": "01c6563d-87ca-4bd6-b487-dcdaece2d8c2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/latex": [
              "$$\n",
              "\\displaystyle \\left[\\begin{matrix}1.0 & -0.723052998582984 - 0.345085413575966 i & 0.467051960502366 + 0.516197865254034 i & -0.180546747798251 - 0.492624093654174 i & 0.0012070853532697 + 0.312052218182462 i\\\\-0.723052998582984 + 0.345085413575966 i & 1.0 & -0.723052998582984 - 0.345085413575966 i & 0.467051960502366 + 0.516197865254034 i & -0.180546747798251 - 0.492624093654174 i\\\\0.467051960502366 - 0.516197865254034 i & -0.723052998582984 + 0.345085413575966 i & 1.0 & -0.723052998582984 - 0.345085413575966 i & 0.467051960502366 + 0.516197865254034 i\\\\-0.180546747798251 + 0.492624093654174 i & 0.467051960502366 - 0.516197865254034 i & -0.723052998582984 + 0.345085413575966 i & 1.0 & -0.723052998582984 - 0.345085413575966 i\\\\0.0012070853532697 - 0.312052218182462 i & -0.180546747798251 + 0.492624093654174 i & 0.467051960502366 - 0.516197865254034 i & -0.723052998582984 + 0.345085413575966 i & 1.0\\end{matrix}\\right]\n",
              "$$"
            ],
            "text/plain": [
              "Matrix([\n",
              "[                                     1.0, -0.723052998582984 - 0.345085413575966*I,  0.467051960502366 + 0.516197865254034*I, -0.180546747798251 - 0.492624093654174*I, 0.0012070853532697 + 0.312052218182462*I],\n",
              "[-0.723052998582984 + 0.345085413575966*I,                                      1.0, -0.723052998582984 - 0.345085413575966*I,  0.467051960502366 + 0.516197865254034*I, -0.180546747798251 - 0.492624093654174*I],\n",
              "[ 0.467051960502366 - 0.516197865254034*I, -0.723052998582984 + 0.345085413575966*I,                                      1.0, -0.723052998582984 - 0.345085413575966*I,  0.467051960502366 + 0.516197865254034*I],\n",
              "[-0.180546747798251 + 0.492624093654174*I,  0.467051960502366 - 0.516197865254034*I, -0.723052998582984 + 0.345085413575966*I,                                      1.0, -0.723052998582984 - 0.345085413575966*I],\n",
              "[0.0012070853532697 - 0.312052218182462*I, -0.180546747798251 + 0.492624093654174*I,  0.467051960502366 - 0.516197865254034*I, -0.723052998582984 + 0.345085413575966*I,                                      1.0]])"
            ]
          },
          "execution_count": 49,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "Matrix(S_circ)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a34c72c0-2984-47fb-8579-089ea795ef39",
      "metadata": {},
      "source": [
        "そして $\\tilde{H}$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "id": "9cde2419-8a29-4d7a-b5b1-9ef2d4c126d2",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Assemble S, the overlap matrix of dimension D:\n",
        "H_first_row = np.zeros(krylov_dim, dtype=complex)\n",
        "H_first_row[0] = H_expval\n",
        "\n",
        "for obs_idx, (pauli, coeff) in enumerate(zip(H_op.paulis, H_op.coeffs)):\n",
        "    # Add in ancilla-only measurements:\n",
        "    for i in range(krylov_dim - 1):\n",
        "        # Get expectation values from experiment\n",
        "        expval_real = results.data.evs[2 + 2 * obs_idx][0][\n",
        "            i\n",
        "        ]  # automatic extrapolated evs if ZNE is used\n",
        "        expval_imag = results.data.evs[2 + 2 * obs_idx + 1][0][\n",
        "            i\n",
        "        ]  # automatic extrapolated evs if ZNE is used\n",
        "\n",
        "        # Get expectation values\n",
        "        expval = expval_real + 1j * expval_imag\n",
        "        H_first_row[i + 1] += prefactors[i] * coeff * expval\n",
        "\n",
        "H_first_row_list = H_first_row.tolist()\n",
        "\n",
        "H_eff_circ = np.zeros((krylov_dim, krylov_dim), dtype=complex)\n",
        "\n",
        "# Distribute entries from first row across matrix:\n",
        "for i, j in it.product(range(krylov_dim), repeat=2):\n",
        "    if i >= j:\n",
        "        H_eff_circ[j, i] = H_first_row[i - j]\n",
        "    else:\n",
        "        H_eff_circ[j, i] = np.conj(H_first_row[j - i])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 51,
      "id": "5800d892-5554-4a92-bfe0-3750ef0a3ed7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/latex": [
              "$$\n",
              "\\displaystyle \\left[\\begin{matrix}25.0 & -14.2437089383409 - 6.50486277982165 i & 10.2857217968584 + 9.0431912203186 i & -5.15587257589417 - 8.88280836036843 i & 1.98818301405581 + 5.8897614762563 i\\\\-14.2437089383409 + 6.50486277982165 i & 25.0 & -14.2437089383409 - 6.50486277982165 i & 10.2857217968584 + 9.0431912203186 i & -5.15587257589417 - 8.88280836036843 i\\\\10.2857217968584 - 9.0431912203186 i & -14.2437089383409 + 6.50486277982165 i & 25.0 & -14.2437089383409 - 6.50486277982165 i & 10.2857217968584 + 9.0431912203186 i\\\\-5.15587257589417 + 8.88280836036843 i & 10.2857217968584 - 9.0431912203186 i & -14.2437089383409 + 6.50486277982165 i & 25.0 & -14.2437089383409 - 6.50486277982165 i\\\\1.98818301405581 - 5.8897614762563 i & -5.15587257589417 + 8.88280836036843 i & 10.2857217968584 - 9.0431912203186 i & -14.2437089383409 + 6.50486277982165 i & 25.0\\end{matrix}\\right]\n",
              "$$"
            ],
            "text/plain": [
              "Matrix([\n",
              "[                                  25.0, -14.2437089383409 - 6.50486277982165*I,   10.2857217968584 + 9.0431912203186*I, -5.15587257589417 - 8.88280836036843*I,   1.98818301405581 + 5.8897614762563*I],\n",
              "[-14.2437089383409 + 6.50486277982165*I,                                   25.0, -14.2437089383409 - 6.50486277982165*I,   10.2857217968584 + 9.0431912203186*I, -5.15587257589417 - 8.88280836036843*I],\n",
              "[  10.2857217968584 - 9.0431912203186*I, -14.2437089383409 + 6.50486277982165*I,                                   25.0, -14.2437089383409 - 6.50486277982165*I,   10.2857217968584 + 9.0431912203186*I],\n",
              "[-5.15587257589417 + 8.88280836036843*I,   10.2857217968584 - 9.0431912203186*I, -14.2437089383409 + 6.50486277982165*I,                                   25.0, -14.2437089383409 - 6.50486277982165*I],\n",
              "[  1.98818301405581 - 5.8897614762563*I, -5.15587257589417 + 8.88280836036843*I,   10.2857217968584 - 9.0431912203186*I, -14.2437089383409 + 6.50486277982165*I,                                   25.0]])"
            ]
          },
          "execution_count": 51,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "Matrix(H_eff_circ)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "896553fa-3c28-44cc-89ad-5031d2f8d35f",
      "metadata": {},
      "source": [
        "最後に、 $\\tilde{H}$ の一般化固有値問題を解くことができる：\n",
        "\n",
        "$\\tilde{H} \\vec{c} = c S \\vec{c}$\n",
        "\n",
        "を計算し、基底状態のエネルギーの推定値を得る。 $c_{min}$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 58,
      "id": "8b997d15-ee25-40eb-80e8-1f054a298ee9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The estimated ground state energy is:  25.0\n",
            "The estimated ground state energy is:  22.572154819954875\n",
            "The estimated ground state energy is:  21.691509219286587\n",
            "The estimated ground state energy is:  21.23882298756386\n",
            "The estimated ground state energy is:  20.965499325470294\n"
          ]
        }
      ],
      "source": [
        "gnd_en_circ_est_list = []\n",
        "for d in range(1, krylov_dim + 1):\n",
        "    # Solve generalized eigenvalue problem for different size of the Krylov space\n",
        "    gnd_en_circ_est = solve_regularized_gen_eig(\n",
        "        H_eff_circ[:d, :d], S_circ[:d, :d], threshold=9e-1\n",
        "    )\n",
        "    gnd_en_circ_est_list.append(gnd_en_circ_est)\n",
        "    print(\"The estimated ground state energy is: \", gnd_en_circ_est)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b39943f8-b75f-4bd4-b246-833ea4f9b710",
      "metadata": {},
      "source": [
        "一粒子セクターの場合、ハミルトニアンのこのセクターの基底状態を古典的に効率よく計算することができる\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 59,
      "id": "fcfe07e5-99e4-4276-a4d6-6f1c7e28c5f2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "n_sys_qubits 30\n",
            "n_exc 1 , subspace dimension 31\n",
            "single particle ground state energy:  21.021912418526906\n"
          ]
        }
      ],
      "source": [
        "gs_en = single_particle_gs(H_op, n_qubits)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 60,
      "id": "4bc52594-0376-497f-8a61-0949415a1fe0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/krylov-quantum-diagonalization/extracted-outputs/4bc52594-0376-497f-8a61-0949415a1fe0-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plt.plot(\n",
        "    range(1, krylov_dim + 1),\n",
        "    gnd_en_circ_est_list,\n",
        "    color=\"blue\",\n",
        "    linestyle=\"-.\",\n",
        "    label=\"KQD estimate\",\n",
        ")\n",
        "plt.plot(\n",
        "    range(1, krylov_dim + 1),\n",
        "    [gs_en] * krylov_dim,\n",
        "    color=\"red\",\n",
        "    linestyle=\"-\",\n",
        "    label=\"exact\",\n",
        ")\n",
        "plt.xticks(range(1, krylov_dim + 1), range(1, krylov_dim + 1))\n",
        "plt.legend()\n",
        "plt.xlabel(\"Krylov space dimension\")\n",
        "plt.ylabel(\"Energy\")\n",
        "plt.title(\n",
        "    \"Estimating Ground state energy with Krylov Quantum Diagonalization\"\n",
        ")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2ef2fac9-b4b9-4457-a551-c98999a88710",
      "metadata": {},
      "source": [
        "<span id=\"appendix-krylov-subspace-from-real-time-evolutions\" />\n",
        "\n",
        "## 付録：実時間発展からのクリロフ部分空間\n",
        "\n",
        "ユニタリー・クリロフ空間は次のように定義される\n",
        "\n",
        "$$\n",
        "\\mathcal{K}_U(H, |\\psi\\rangle) = \\text{span}\\left\\{ |\\psi\\rangle,  e^{-iH\\,dt} |\\psi\\rangle, \\dots, e^{-irH\\,dt} |\\psi\\rangle \\right\\}\n",
        "$$\n",
        "\n",
        "後で決めるタイムステップ $dt$。 仮に $r$ が偶数であると仮定する。 $d=r/2$ を定義する。ハミルトニアンを上記のクリロフ空間に射影すると，クリロフ空間と区別がつかないことに注意してください．\n",
        "\n",
        "$$\n",
        "\\mathcal{K}_U(H, |\\psi\\rangle) = \\text{span}\\left\\{ e^{i\\,d\\,H\\,dt}|\\psi\\rangle,  e^{i(d-1)H\\,dt} |\\psi\\rangle, \\dots, e^{-i(d-1)H\\,dt} |\\psi\\rangle, e^{-i\\,d\\,H\\,dt} |\\psi\\rangle \\right\\},\n",
        "$$\n",
        "\n",
        "つまり、すべての時間進化が $d$ タイムステップだけ後ろにシフトしている。\n",
        "見分けがつかない理由は、行列の要素にある\n",
        "\n",
        "$$\n",
        "\\tilde{H}_{j,k} = \\langle\\psi|e^{i\\,j\\,H\\,dt}He^{-i\\,k\\,H\\,dt}|\\psi\\rangle=\\langle\\psi|He^{i(j-k)H\\,dt}|\\psi\\rangle\n",
        "$$\n",
        "\n",
        "は、進化時間の全体的なシフトに対して不変であり、時間進化はハミルトニアンと通約するからである。 奇数 $r$ については、 $r-1$ の分析を使うことができる。\n",
        "\n",
        "このクリロフ空間のどこかに、低エネルギー状態が必ず存在することを示したい。 これは [\\[3\\]](#references) の定理 3.1 ：\n",
        "\n",
        "**請求項1：** ハミルトニアンのスペクトル範囲（つまり、基底状態エネルギーと最大エネルギーの間）のエネルギー $E$ に対して...となるような関数 $f$ が存在する。\n",
        "\n",
        "1. $f(E_0)=1$\n",
        "2. $|f(E)|\\le2\\left(1 + \\delta\\right)^{-d}$ $E_0$ から 離れたところにある のすべての値に対して、つまり指数関数的に抑制される。 $\\ge\\delta$ $E$\n",
        "3. $f(E)$ の $e^{ijE\\,dt}$ の線形結合である。 $j=-d,-d+1,...,d-1,d$\n",
        "\n",
        "以下に証明を示すが、完全で厳密な議論を理解したい人以外は読み飛ばしても構わない。 今のところは、上記の主張の意味に焦点を当てる。 上記の性質3により、上記のシフト・クリロフ空間は状態 $f(H)|\\psi\\rangle$ を含むことがわかる。これが我々の低エネルギー状態である。 その理由を知るために、 $|\\psi\\rangle$ をエネルギー固有ベーシスで書いてみよう：\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle = \\sum_{k=0}^{N}\\gamma_k|E_k\\rangle,\n",
        "$$\n",
        "\n",
        "ここで $|E_k\\rangle$ はk番目のエネルギー固有状態であり、 $\\gamma_k$ は初期状態 $|\\psi\\rangle$ におけるその振幅である。これによって表現すると、 $f(H)|\\psi\\rangle$ は次式で与えられる\n",
        "\n",
        "$$\n",
        "f(H)|\\psi\\rangle = \\sum_{k=0}^{N}\\gamma_kf(E_k)|E_k\\rangle,\n",
        "$$\n",
        "\n",
        "が固有状態 $|E_k\\rangle$ に作用するとき、 $H$ を $E_k$ で置き換えることができるという事実を利用している。したがって、この状態のエネルギー誤差は\n",
        "\n",
        "$$\n",
        "\\text{energy error} = \\frac{\\langle\\psi|f(H)(H-E_0)f(H)|\\psi\\rangle}{\\langle\\psi|f(H)^2|\\psi\\rangle}\n",
        "$$\n",
        "\n",
        "$$\n",
        "= \\frac{\\sum_{k=0}^{N}|\\gamma_k|^2f(E_k)^2(E_k-E_0)}{\\sum_{k=0}^{N}|\\gamma_k|^2f(E_k)^2}.\n",
        "$$\n",
        "\n",
        "これを理解しやすい上界にするために、まず分子の和を $E_k-E_0\\le\\delta$ の項と $E_k-E_0>\\delta$ の項に分ける：\n",
        "\n",
        "$$\n",
        "\\text{energy error} = \\frac{\\sum_{E_k\\le E_0+\\delta}|\\gamma_k|^2f(E_k)^2(E_k-E_0)}{\\sum_{k=0}^{N}|\\gamma_k|^2f(E_k)^2} + \\frac{\\sum_{E_k> E_0+\\delta}|\\gamma_k|^2f(E_k)^2(E_k-E_0)}{\\sum_{k=0}^{N}|\\gamma_k|^2f(E_k)^2}.\n",
        "$$\n",
        "\n",
        "第一項を $\\delta$ で上界することができる、\n",
        "\n",
        "$$\n",
        "\\frac{\\sum_{E_k\\le E_0+\\delta}|\\gamma_k|^2f(E_k)^2(E_k-E_0)}{\\sum_{k=0}^{N}|\\gamma_k|^2f(E_k)^2} < \\frac{\\delta\\sum_{E_k\\le E_0+\\delta}|\\gamma_k|^2f(E_k)^2}{\\sum_{k=0}^{N}|\\gamma_k|^2f(E_k)^2} \\le \\delta,\n",
        "$$\n",
        "\n",
        "ここで、最初のステップは、和のすべての $E_k$ について $E_k-E_0\\le\\delta$、2番目のステップは、分子の和が分母の和の部分集合であるため、続く。 第2項については、まず分母を $|\\gamma_0|^2$。 $f(E_0)^2=1$ ：すべてを足し合わせると、次のようになる\n",
        "\n",
        "$$\n",
        "\\text{energy error} \\le \\delta + \\frac{1}{|\\gamma_0|^2}\\sum_{E_k>E_0+\\delta}|\\gamma_k|^2f(E_k)^2(E_k-E_0).\n",
        "$$\n",
        "\n",
        "残されたものを単純化するために、これらのすべての $E_k$、 $f$ の定義によって、 $f(E_k)^2 \\le 4\\left(1 + \\delta\\right)^{-2d}$。さらに、 $E_k-E_0<2\\|H\\|$ を上界し、 $\\sum_{E_k>E_0+\\delta}|\\gamma_k|^2<1$ を上界すると、次のようになる\n",
        "\n",
        "$$\n",
        "\\text{energy error} \\le \\delta + \\frac{8}{|\\gamma_0|^2}\\|H\\|\\left(1 + \\delta\\right)^{-2d}.\n",
        "$$\n",
        "\n",
        "これは、どのような $\\delta>0$ についても成り立つので、 $\\delta$ を目標誤差に等しく設定すれば、上の誤差境界は、クリロフ次元 $2d=r$ に従って指数関数的に収束する。また、 $\\delta<E_1-E_0$ の場合、 $\\delta$ の項は、上記の境界では実際には完全になくなることに注意してください。\n",
        "\n",
        "議論を完結させるために、上記はクリロフ空間における最低エネルギー状態のエネルギー誤差ではなく、特定の状態 $f(H)|\\psi\\rangle$ のエネルギー誤差に過ぎないことにまず注意する。 しかし、(Rayleigh-Ritz) 変分原理により、クリロフ空間内の最低エネルギー状態のエネルギー誤差は、クリロフ空間内の任意の状態のエネルギー誤差によって上界されるため、上記は最低エネルギー状態のエネルギー誤差、つまりクリロフ量子対角化アルゴリズムの出力に対する上界でもある。\n",
        "\n",
        "上記と同様の分析が、ノイズとノートで説明した閾値処理手順を追加して実施できる。 この分析については [\\[2\\]](#references) と [\\[4\\]](#references) を参照のこと。\n",
        "\n",
        "<span id=\"appendix-proof-of-claim-1\" />\n",
        "\n",
        "## 付録：請求項１の証明\n",
        "\n",
        "以下はほとんど [\\[3\\]](#references) の定理 3.1: $0 < a < b$ とし、 $\\Pi^*_d$ を最大次数 $d$ の残差多項式（0での値が1である多項式）の空間とする。に対する解は\n",
        "\n",
        "$$\n",
        "\\beta(a, b, d) = \\min_{p \\in \\Pi^*_d} \\max_{x \\in [a, b]} |p(x)| \\quad\n",
        "$$\n",
        "\n",
        "次と同一である\n",
        "\n",
        "$$\n",
        "p^*(x) = \\frac{T_d\\left(\\frac{b + a - 2x}{b - a}\\right)}{T_d\\left(\\frac{b + a}{b - a}\\right)}, \\quad\n",
        "$$\n",
        "\n",
        "となり、対応する最小値は\n",
        "\n",
        "$$\n",
        "\\beta(a, b, d) = T_d^{-1}\\left(\\frac{b + a}{b - a}\\right).\n",
        "$$\n",
        "\n",
        "この関数を複素指数で自然に表現できる関数に変換したい。なぜなら、それが量子クリロフ空間を生成する実時間進化だからである。\n",
        "そのためには、ハミルトニアンのスペクトル範囲内のエネルギーを、 $[0,1]$ ：defineの範囲内の数に変換する以下の変換を導入するのが便利である\n",
        "\n",
        "$$\n",
        "g(E) = \\frac{1-\\cos\\big((E-E_0)dt\\big)}{2},\n",
        "$$\n",
        "\n",
        "ここで $dt$ は $-\\pi < E_0dt < E_\\text{max}dt < \\pi$ のようなタイムス テップである。 $E$ が $E_0$ から遠ざかるにつれて、 $g(E_0)=0$ と $g(E)$ が成長することに注意。\n",
        "\n",
        "ここで、パラメータa, b, dを $a = g(E_0 + \\delta)$, $b = 1$, d = int( r/2 ) に設定した多項式 $p^*(x)$ を使い、関数を定義する：\n",
        "\n",
        "$$\n",
        "f(E) = p^* \\left( g(E) \\right) = \\frac{T_d\\left(1 + 2\\frac{\\cos\\big((E-E_0)dt\\big) - \\cos\\big(\\delta\\,dt\\big)}{1 +\\cos\\big(\\delta\\,dt\\big)}\\right)}{T_d\\left(1 + 2\\frac{1-\\cos\\big(\\delta\\,dt\\big)}{1 + \\cos\\big(\\delta\\,dt\\big)}\\right)}\n",
        "$$\n",
        "\n",
        "ここで、 $E_0$ は基底状態のエネルギーである。 $f(E)$ が次数 $d$ の三角多項式、つまり $j=-d,-d+1,...,d-1,d$ に対する $e^{ijE\\,dt}$ の線形結合であることは、 $\\cos(x)=\\frac{e^{ix}+e^{-ix}}{2}$ を挿入することでわかる。さらに、上記の $p^*(x)$ の定義から、 $f(E_0)=p(0)=1$ と、 $\\vert E-E_0 \\vert > \\delta$ のようなスペクトル範囲内の任意の $E$ に対して、次のようになる\n",
        "\n",
        "$$\n",
        "|f(E)| \\le \\beta(a, b, d) = T_d^{-1}\\left(1 + 2\\frac{1-\\cos\\big(\\delta\\,dt\\big)}{1 + \\cos\\big(\\delta\\,dt\\big)}\\right)\n",
        "$$\n",
        "\n",
        "$$\n",
        "\\leq 2\\left(1 + \\delta\\right)^{-d} = 2\\left(1 + \\delta\\right)^{-\\lfloor k/2\\rfloor}.\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ccd6c21d-ed1e-4894-9cbb-8d3a9d91afe2",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## 参照\n",
        "\n",
        "\\[1] N. 吉岡、M.アミコ、W.カービーら、\"量子プロセッサー上での大規模多体ハミルトニアンの対角化\"。 [arXiv:2407.14431](https://arxiv.org/abs/2407.14431)\n",
        "\n",
        "\\[2] イーサン・エッペリー、リン・リン、中務裕司。 「量子部分空間対角化の理論」。 SIAM Journal on Matrix Analysis and Applications 43, 1263-1290 (2022).\n",
        "\n",
        "\\[3] Å. ビョルク 「行列計算における数値的手法」。 応用数学のテキスト。 シュプリンガー・インターナショナル・パブリッシング (2014).\n",
        "\n",
        "\\[4] ウィリアム・カービー 「誤差を含む量子クリロフ・アルゴリズムの解析」。 Quantum 8, 1457 (2024).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74948cc7-041f-412c-ab16-2554bf164061",
      "metadata": {},
      "source": [
        "<span id=\"tutorial-survey\" />\n",
        "\n",
        "## チュートリアル調査\n",
        "\n",
        "このチュートリアルに関するご意見をお聞かせください。 あなたの洞察は、私たちのコンテンツの提供とユーザーエクスペリエンスを向上させるのに役立ちます。\n",
        "\n",
        "[アンケートへのリンク](https://your.feedback.ibm.com/jfe/form/SV_82nennpKIjjD8rQ)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "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"
    },
    "hours": 1.5,
    "qpuSeconds": 1200
  },
  "nbformat": 4,
  "nbformat_minor": 4
}