{
  "cells": [
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "2a246d14-ed2b-4573-bf97-939c3628b3bb",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"最適化ループ\"\n",
        "description: \"このレッスンでは、量子計算にパラメータを入力するための古典的最適化ループの使用方法を順を追って説明します。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore nabla */}\n",
        "\n",
        "<span id=\"optimization-loops\" />\n",
        "\n",
        "# 最適化ループ\n",
        "\n",
        "このレッスンでは、 *オプティマイザを使って*、アサッツのパラメータ化された量子状態を繰り返し探索する方法を学びます：\n",
        "\n",
        "* 最適化ループのブートストラップ\n",
        "* ローカル・オプティマイザとグローバル・オプティマイザを使用する際のトレードオフを理解する\n",
        "* 不毛のプラトーとその回避法を探る\n",
        "\n",
        "高レベルでは、オプティマイザーは探索空間を探索するための中心的存在だ。 オプティマイザは、コスト関数の評価を用いて変分ループの中で次のパラメータセットを選択し、安定した状態に達するまでそのプロセスを繰り返す。 この段階で、パラメータ値の最適セット $\\vec\\theta^*$ が返される。\n",
        "\n",
        "![不毛のプラトー、勾配オプティマイザーと勾配なしオプティマイザー、ブートストラップなど、最適化におけるいくつかの重要な要素の図。](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-workflow.svg)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "110421e7-0d2a-4653-a195-1925c809ca61",
      "metadata": {},
      "source": [
        "<span id=\"local-and-global-optimizers\" />\n",
        "\n",
        "## 局所最適化と全局最適化\n",
        "\n",
        "各オプティマイザー・クラスを調べる前に、まず問題を設定する。 まず、8つの変分パラメータを含む回路から始める：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "15cf7810-1d25-4c54-aff0-91d3a0c51cec",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/variational-algorithm-design/optimization-loops/extracted-outputs/15cf7810-1d25-4c54-aff0-91d3a0c51cec-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.circuit.library import TwoLocal\n",
        "import numpy as np\n",
        "\n",
        "theta_list = (2 * np.pi * np.random.rand(1, 8)).tolist()\n",
        "observable = SparsePauliOp.from_list([(\"XX\", 1), (\"YY\", -3)])\n",
        "\n",
        "reference_circuit = QuantumCircuit(2)\n",
        "reference_circuit.x(0)\n",
        "\n",
        "variational_form = TwoLocal(\n",
        "    2,\n",
        "    rotation_blocks=[\"rz\", \"ry\"],\n",
        "    entanglement_blocks=\"cx\",\n",
        "    entanglement=\"linear\",\n",
        "    reps=1,\n",
        ")\n",
        "ansatz = reference_circuit.compose(variational_form)\n",
        "\n",
        "ansatz.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "950569c0-4e8f-49b5-b118-7cd227bd5ce1",
      "metadata": {},
      "outputs": [],
      "source": [
        "def cost_func_vqe(params, ansatz, hamiltonian, estimator):\n",
        "    \"\"\"Return estimate of energy from estimator\n",
        "\n",
        "    Parameters:\n",
        "        params (ndarray): Array of ansatz parameters\n",
        "        ansatz (QuantumCircuit): Parameterized ansatz circuit\n",
        "        hamiltonian (SparsePauliOp): Operator representation of Hamiltonian\n",
        "        estimator (Estimator): Estimator primitive instance\n",
        "\n",
        "    Returns:\n",
        "        float: Energy estimate\n",
        "    \"\"\"\n",
        "    pub = (ansatz, hamiltonian, params)\n",
        "    cost = estimator.run([pub]).result()[0].data.evs\n",
        "    return cost"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "f536ee50-373f-4873-b258-66c5c07c65c5",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.primitives import StatevectorEstimator\n",
        "\n",
        "estimator = StatevectorEstimator()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c9dcec4d-5b84-4731-8b5a-cb8a0f7572d5",
      "metadata": {},
      "source": [
        "<span id=\"local-optimizers\" />\n",
        "\n",
        "### 局所最適化器\n",
        "\n",
        "ローカル・オプティマイザは、初期点（複数可） $C(\\vec{\\theta_0})$ を起点として、コスト関数を最小化する点を探索し、連続的な反復で現在評価中の領域で観察される内容に基づいて、異なる点に移動する。 このことは、これらのアルゴリズムの収束は通常速いことを意味するが、初期点に大きく依存する可能性がある。 ローカル・オプティマイザは、自分が評価している領域以外を見ることができないため、特にローカル・ミニマムに弱く、ローカル・ミニマムを見つけると収束を報告し、より有利な評価を持つ他の状態を無視することがある。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "447df742-13bd-4d4a-a364-41d34380cbc9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              " message: Optimization terminated successfully\n",
              " success: True\n",
              "  status: 0\n",
              "     fun: -3.9999999964520634\n",
              "       x: [ 1.000e+00  1.000e+00 -1.571e+00 -4.556e-05 -1.207e+00\n",
              "           -1.935e+00  4.079e-01 -4.079e-01]\n",
              "     nit: 12\n",
              "     jac: [ 0.000e+00  0.000e+00 -7.957e-04  2.543e-04  1.381e-03\n",
              "            1.381e-03  5.430e-04  5.431e-04]\n",
              "    nfev: 112\n",
              "    njev: 12"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# SciPy minimizer routine\n",
        "from scipy.optimize import minimize\n",
        "\n",
        "x0 = np.ones(8)\n",
        "\n",
        "result = minimize(\n",
        "    cost_func_vqe, x0, args=(ansatz, observable, estimator), method=\"SLSQP\"\n",
        ")\n",
        "\n",
        "result"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "25fee3f4-9d3e-45ce-a104-dfde5e132b2b",
      "metadata": {},
      "source": [
        "<span id=\"global-optimizers\" />\n",
        "\n",
        "### グローバル最適化アルゴリズム\n",
        "\n",
        "グローバル・オプティマイザは、オプティマイザによって決定されたパラメー タ・ベクトル（ $\\Theta_i := \\\\{ {\\vec\\theta_{i,j} | j \\in \\mathcal{J}_\\text{opt}^i} \\\\}$ ）のセットに対して、コスト関数を反復的 （すなわち、反復 $i$ ）に評価しながら、その領域の複数の領域にわたって （すなわち、非局所的に）コスト関数を最小化する点を探索する。 このため、局所極小値の影響を受けにくく、初期化にもある程度依存しないが、提案された解に収束するまでの時間が大幅に遅くなる。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8d794038-8e75-4649-a978-a9e832ebed60",
      "metadata": {},
      "source": [
        "<span id=\"bootstrapping-optimization\" />\n",
        "\n",
        "### ブートストラップ最適化\n",
        "\n",
        "*ブートストラップ*、つまり事前の最適化に基づいてパラメータ $\\vec\\theta$ の初期値を設定することで、オプティマイザがより早く解に収束することができます。 これを初期点 $\\vec\\theta_0$、 $|\\psi(\\vec\\theta_0)\\rangle = U_V(\\vec\\theta_0)|\\rho\\rangle$ を初期状態と呼ぶ。 この初期状態は、我々の参照状態 $|\\rho\\rangle$ とは異なる。前者は最適化ループ中に設定された初期パラメータに焦点を当てるのに対し、後者は既知の「参照」解を使用することに焦点を当てるからである。 もし $U_V(\\vec\\theta_0) \\equiv I$ （つまり同一性演算）であれば、これらは一致するかもしれない。\n",
        "\n",
        "ローカル・オプティマイザーが最適でないローカル・ミニマムに収束する場合、最適化をグローバルにブートストラップし、ローカルに収束を改善することができます。 これには2つの変分作業負荷を設定する必要があるが、オプティマイザはローカル・オプティマイザだけよりも最適解を見つけることができる。\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "07ba982e-9280-4e15-9d8c-4b6460b1deea",
      "metadata": {
        "gloss": {
          "hyperparameter": {
            "text": "A hyperparameter is a parameter that we use to control our algorithm. The ‘hyper’ distinguishes it from the parameters (θ) that our algorithm is trying to find.",
            "title": "Hyperparameter"
          },
          "local-minimum": {
            "text": "A local minimum is the lowest point of the function, for a small range of values of theta. In contrast, a global minimum is <i>the</i> lowest point, anywhere in our function (that is, for any value of theta). <a href='https://en.wikipedia.org/wiki/Maxima_and_minima'>Read more</a>.",
            "title": "Local minimum"
          }
        }
      },
      "source": [
        "<span id=\"gradient-based-and-gradient-free-optimizers\" />\n",
        "\n",
        "## 勾配ベースおよび勾配フリー最適化アルゴリズム\n",
        "\n",
        "<span id=\"gradient-based\" />\n",
        "\n",
        "### 勾配ベースの\n",
        "\n",
        "私たちのコスト関数 $C(\\vec\\theta)$、初期点から始まる関数 $\\vec{\\nabla} C(\\vec\\theta)$ の勾配にアクセスできる場合、関数を最小化する最も簡単な方法は、関数の急降下方向に向かってパラメータを更新することです。 つまり、 $\\vec\\theta_{n+1} = \\vec\\theta_n - \\eta \\vec{\\nabla} C(\\vec\\theta)$ としてパラメータを更新する。 $\\eta$ は学習率で、更新の大きさを制御する小さな正の <DefinitionTooltip definition=\"ハイパーパラメータとは、アルゴリズムを制御するためのパラメータである。 ハイパーという言葉は、我々のアルゴリズムが見つけようとしているパラメータ（θ）と区別するためのものである。\">ハイパーパラメーター</DefinitionTooltip> である。 コスト関数の <DefinitionTooltip definition=\"局所最小値とは、θの値の小さな範囲における関数の最低点のことである。 対照的に、グローバル・ミニマムとは、関数のどこにおいても（つまり、θのどの値においても）最低点である。\">ローカルミニマム</DefinitionTooltip> $C({\\vec\\theta^*})$ に収束するまでこれを続ける。\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "0897260d-f3f8-4caa-8a79-f258e41f8e21",
      "metadata": {},
      "source": [
        "このコスト関数とオプティマイザを使って、最適なパラメータを計算することができる\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "aad81101-3c19-4946-8453-3db9df3369c0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "  message: Optimization terminated successfully.\n",
              "  success: True\n",
              "   status: 0\n",
              "      fun: -3.9999999999997025\n",
              "        x: [ 1.000e+00  1.000e+00  1.571e+00  3.220e-07  2.009e-01\n",
              "            -2.009e-01  6.342e-01 -6.342e-01]\n",
              "      nit: 14\n",
              "      jac: [-1.192e-07 -2.980e-08  8.345e-07  1.103e-06  5.960e-08\n",
              "             0.000e+00 -5.960e-08  2.980e-08]\n",
              " hess_inv: [[ 1.000e+00  1.872e-10 ...  5.077e-05  3.847e-05]\n",
              "            [ 1.872e-10  1.000e+00 ... -5.208e-05 -4.060e-05]\n",
              "            ...\n",
              "            [ 5.077e-05 -5.208e-05 ...  7.243e-01 -2.604e-01]\n",
              "            [ 3.847e-05 -4.060e-05 ... -2.604e-01  8.179e-01]]\n",
              "     nfev: 144\n",
              "     njev: 16"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# SciPy minimizer routine\n",
        "from scipy.optimize import minimize\n",
        "\n",
        "x0 = np.ones(8)\n",
        "\n",
        "result = minimize(\n",
        "    cost_func_vqe, x0, args=(ansatz, observable, estimator), method=\"BFGS\"\n",
        ")\n",
        "\n",
        "result"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "0f7d55f8-e3a2-4223-b456-17b39a81f524",
      "metadata": {},
      "source": [
        "このタイプの最適化の主な欠点は、収束速度が非常に遅く、最適解が得られる保証がないことです。\n",
        "\n",
        "![θに対するf(θ)のグラフで、複数の点は曲線の最小値を求める勾配降下アルゴリズムの異なる状態を示している。](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-gradient-descent.svg)\n",
        "\n",
        "<span id=\"gradient-free\" />\n",
        "\n",
        "### 勾配なし\n",
        "\n",
        "勾配を必要としない最適化アルゴリズムは、勾配情報を必要としないため、勾配の計算が困難であったり、計算コストが高かったり、ノイズが多すぎたりする場合に有効です。 また、勾配ベースの手法が局所最適に収束する傾向があるのに対して、大域的な最適値を見つけるのに頑健な傾向がある。 ここでは、勾配のないオプティマイザが不毛な停滞を避けるのに役立つ例をいくつか紹介する。 しかし、勾配を用いない方法は、特に高次元の探索空間を持つ問題に対して、より高い計算資源を必要とする。\n",
        "\n",
        "代わりに [`COBYLA`](https://docs.scipy.org/doc/scipy/reference/optimize.minimize-cobyla.html#optimize-minimize-cobyla) オプティマイザを使用する例である：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "c749695b-3124-47d8-8a23-10c9d5965a7f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              " message: Optimization terminated successfully.\n",
              " success: True\n",
              "  status: 1\n",
              "     fun: -3.999999973369678\n",
              "       x: [ 1.631e+00  1.492e+00  1.571e+00  3.142e+00  1.375e+00\n",
              "           -1.767e+00  1.484e+00  1.658e+00]\n",
              "    nfev: 137\n",
              "   maxcv: 0.0"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# SciPy minimizer routine\n",
        "from scipy.optimize import minimize\n",
        "\n",
        "x0 = np.ones(8)\n",
        "\n",
        "result = minimize(\n",
        "    cost_func_vqe, x0, args=(ansatz, observable, estimator), method=\"COBYLA\"\n",
        ")\n",
        "\n",
        "result"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "396d0617-9f20-48cb-b57c-30dfa54293ff",
      "metadata": {
        "gloss": {
          "barren-plateaus": {
            "text": "When gradients of parametrized quantum circuits become exponentially small with respect to the number of qubits, making optimization difficult and potentially impossible.",
            "title": "Barren Plateaus"
          }
        }
      },
      "source": [
        "<span id=\"barren-plateaus\" />\n",
        "\n",
        "## 不毛の高原\n",
        "\n",
        "実際、下の例の山あり谷ありのように、コスト環境はかなり複雑になる。 最適化メソッドは、黒い点と線で示されるように、最小値を探しながらコストランドスケープをナビゲートする。 3つの探索のうち2つは、大局的な最小値ではなく、局所的な最小値で終わっていることがわかる。\n",
        "\n",
        "![山あり谷ありの複雑な曲線のマニホールド。](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-loss-landscape.svg)\n",
        "\n",
        "使用される最適化手法の種類にかかわらず、コスト・ランドスケープが比較的平坦である場合、その手法が適切な探索方向を決定するのは困難な場合がある。 このシナリオは、 <DefinitionTooltip definition=\"パラメトリック量子回路の勾配が量子ビット数に対して指数関数的に小さくなると、最適化が困難になり、不可能になる可能性がある。\">不毛の高原、</DefinitionTooltip> と呼ばれ、コストのランドスケープが徐々に平坦になる（したがって、最小値への方向性を決定するのがより困難になる）。 パラメータ化された広範な量子回路において、合理的な方向に沿った勾配がある一定の精度でゼロでない確率は、量子ビット数が増加するにつれて指数関数的に減少する。\n",
        "\n",
        "![なぜ勾配は最小値を見つけるのに役立ち、台地はその努力を妨げるのかを説明するために、地理的な台地と山の勾配を比較した図。](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-barren-plateaus.svg)\n",
        "\n",
        "この分野ではまだ活発な研究が行われているが、最適化のパフォーマンスを向上させるための推奨事項がいくつかある：\n",
        "\n",
        "* **ブートストラップは**、最適化ループが勾配が小さいパラメータ空間で立ち往生するのを避けるのに役立つ。\n",
        "* **ハードウェア的に効率的なansatzの実験** ：ブラックボックスのオラクルとしてノイズの多い量子システムを使用しているため、これらの評価の質はオプティマイザのパフォーマンスに影響を与える可能性があります。 のようなハードウェア効率の良いansatzを使用することで、指数関数的に小さな勾配を生成することを避けることができる。 [`EfficientSU2`](/docs/api/qiskit/qiskit.circuit.library.EfficientSU2)のようなハードウェア効率に優れたアサッツを使用することで、指数関数的に小さな勾配が発生するのを避けることができる。\n",
        "* **エラー抑制とエラー軽減の実験** ： IBM Quantum プリミティブは `resilience_setting`、それぞれ `optimization_level` とについてさまざまな値を試すためのシンプルなインターフェースを提供します。 これにより、ノイズの影響を軽減し、最適化プロセスの効率を高めることができます。\n",
        "* **勾配のないオプティマイザを使った実験** ：勾配ベースの最適化アルゴリズムとは異なり、 `COBYLA` のようなオプティマイザは、パラメータを最適化するために勾配情報に依存しないため、不毛のプラトーの影響を受けにくい。\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "182110bc-f952-4460-8048-d1df961ba860",
      "metadata": {},
      "source": [
        "<span id=\"summary\" />\n",
        "\n",
        "## サマリー\n",
        "\n",
        "このレッスンでは、最適化ループを定義する方法を学びました：\n",
        "\n",
        "* 最適化ループのブートストラップ\n",
        "* ローカル・オプティマイザとグローバル・オプティマイザを使用する際のトレードオフを理解する\n",
        "* 不毛のプラトーとその回避法を探る\n",
        "\n",
        "高レベルの変分作業負荷は完了した：\n",
        "\n",
        "![量子回路は、参照状態を準備するためのユニタリーと、変分パラメータを使って状態を変化させるための第2のユニタリーの両方を備えている。](https://quantum.cloud.ibm.com/learning/images/courses/variational-algorithm-design/optimization-loops/optimization-circuit.svg)\n",
        "\n",
        "次に、このフレームワークを念頭に置いて、具体的な変分アルゴリズムを探求する。\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"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}