<commit_before>{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xLOXFOT5Q40E"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "iiQkM5ZgQ8r2"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "j6331ZSsQGY3"
      },
      "source": [
        "# Hello, many worlds"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "i9Jcnb8bQQyd"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/quantum/tutorials/hello_many_worlds\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />View on TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/quantum/blob/master/docs/tutorials/hello_many_worlds.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/quantum/blob/master/docs/tutorials/hello_many_worlds.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/quantum/docs/tutorials/hello_many_worlds.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Download notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6tYn2HaAUgH0"
      },
      "source": [
        "This tutorial shows how a classical neural network can learn to correct qubit calibration errors. It introduces <a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq\" class=\"external\">Cirq</a>, a Python framework to create, edit, and invoke Noisy Intermediate Scale Quantum (NISQ) circuits, and demonstrates how Cirq interfaces with TensorFlow Quantum."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sPZoNKvpUaqa"
      },
      "source": [
        "## Setup"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "TorxE5tnkvb2"
      },
      "outputs": [],
      "source": [
        "!pip install tensorflow==2.1.0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FxkQA6oblNqI"
      },
      "source": [
        "Install TensorFlow Quantum:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "saFHsRDpkvkH"
      },
      "outputs": [],
      "source": [
        "!pip install tensorflow-quantum"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "F1L8h1YKUvIO"
      },
      "source": [
        "Now import TensorFlow and the module dependencies:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "enZ300Bflq80"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow_quantum as tfq\n",
        "\n",
        "import cirq\n",
        "import sympy\n",
        "import numpy as np\n",
        "\n",
        "# visualization tools\n",
        "%matplotlib inline\n",
        "import matplotlib.pyplot as plt\n",
        "from cirq.contrib.svg import SVGCircuit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b08Mmbs8lr81"
      },
      "source": [
        "## 1. The Basics"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y31qSRCczI-L"
      },
      "source": [
        "### 1.1 Cirq and parameterized quantum circuits\n",
        "\n",
        "Before exploring TensorFlow Quantum (TFQ), let's look at some <a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq\" class=\"external\">Cirq</a> basics. Cirq is a Python library for quantum computing from Google. You use it to define circuits, including static and parameterized gates.\n",
        "\n",
        "Cirq uses <a target=\"_blank\" href=\"https://www.sympy.org\" class=\"external\">SymPy</a> symbols to represent free parameters."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "2yQdmhQLCrzQ"
      },
      "outputs": [],
      "source": [
        "a, b = sympy.symbols('a b')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "itUlpbKmDYNW"
      },
      "source": [
        "The following code creates a two-qubit circuit using your parameters:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Ps-pd2mndXs7"
      },
      "outputs": [],
      "source": [
        "# Create two qubits\n",
        "q0, q1 = cirq.GridQubit.rect(1, 2)\n",
        "\n",
        "# Create a circuit on these qubits using the parameters you created above.\n",
        "circuit = cirq.Circuit(\n",
        "    cirq.rx(a).on(q0),\n",
        "    cirq.ry(b).on(q1), cirq.CNOT(control=q0, target=q1))\n",
        "\n",
        "SVGCircuit(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zcCX109cJUaz"
      },
      "source": [
        "To evaluate circuits, you can use the `cirq.Simulator` interface. You replace free parameters in a circuit with specific numbers by passing in a `cirq.ParamResolver` object. The following code calculates the raw state vector output of your parameterized circuit:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "VMq7EayNRyQb"
      },
      "outputs": [],
      "source": [
        "# Calculate a state vector with a=0.5 and b=-0.5.\n",
        "resolver = cirq.ParamResolver({a: 0.5, b: -0.5})\n",
        "output_state_vector = cirq.Simulator().simulate(circuit, resolver).final_state\n",
        "output_state_vector"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-SUlLpXBeicF"
      },
      "source": [
        "State vectors are not directly accessible outside of simulation (notice the complex numbers in the output above). To be physically realistic, you must specify a measurement, which converts a state vector into a real number that classical computers can understand. Cirq specifies measurements using combinations of the <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Pauli_matrices\" class=\"external\">Pauli operators</a> $\\hat{X}$, $\\hat{Y}$, and $\\hat{Z}$. As illustration, the following code measures $\\hat{Z}_0$ and $\\frac{1}{2}\\hat{Z}_0 + \\hat{X}_1$ on the state vector you just simulated:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "hrSnOCi3ehr_"
      },
      "outputs": [],
      "source": [
        "z0 = cirq.Z(q0)\n",
        "\n",
        "qubit_map={q0: 0, q1: 1}\n",
        "\n",
        "z0.expectation_from_wavefunction(output_state_vector, qubit_map).real"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "OZ0lWFXv6pII"
      },
      "outputs": [],
      "source": [
        "z0x1 = 0.5 * z0 + cirq.X(q1)\n",
        "\n",
        "z0x1.expectation_from_wavefunction(output_state_vector, qubit_map).real"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bkC-yjIolDNr"
      },
      "source": [
        "### 1.2 Quantum circuits as tensors\n",
        "\n",
        "TensorFlow Quantum (TFQ) provides `tfq.convert_to_tensor`, a function that converts Cirq objects into tensors. This allows you to send Cirq objects to our <a target=\"_blank\" href=\"https://www.tensorflow.org/quantum/api_docs/python/tfq/layers\">quantum layers</a> and <a target=\"_blank\" href=\"https://www.tensorflow.org/quantum/api_docs/python/tfq/get_expectation_op\">quantum ops</a>. The function can be called on lists or arrays of Cirq Circuits and Cirq Paulis:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1gLQjA02mIyy"
      },
      "outputs": [],
      "source": [
        "# Rank 1 tensor containing 1 circuit.\n",
        "circuit_tensor = tfq.convert_to_tensor([circuit])\n",
        "\n",
        "print(circuit_tensor.shape)\n",
        "print(circuit_tensor.dtype)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SJy6AkbU6pIP"
      },
      "source": [
        "This encodes the Cirq objects as `tf.string` tensors that `tfq` operations decode as needed."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aX_vEmCKmpQS"
      },
      "outputs": [],
      "source": [
        "# Rank 1 tensor containing 2 Pauli operators.\n",
        "pauli_tensor = tfq.convert_to_tensor([z0, z0x1])\n",
        "pauli_tensor.shape"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FI1JLWe6m8JF"
      },
      "source": [
        "### 1.3 Batching circuit simulation\n",
        "\n",
        "TFQ provides methods for computing expectation values, samples, and state vectors. For now, let's focus on *expectation values*.\n",
        "\n",
        "The highest-level interface for calculating expectation values is the `tfq.layers.Expectation` layer, which is a `tf.keras.Layer`. In its simplest form, this layer is equivalent to simulating a parameterized circuit over many `cirq.ParamResolvers`; however, TFQ allows batching following TensorFlow semantics, and circuits are simulated using efficient C++ code.\n",
        "\n",
        "Create a batch of values to substitute for our `a` and `b` parameters:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1fsVZhF5lIXp"
      },
      "outputs": [],
      "source": [
        "batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=np.float32)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ip7jlGXIf22u"
      },
      "source": [
        "Batching circuit execution over parameter values in Cirq requires a loop:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RsfF53UCJtr9"
      },
      "outputs": [],
      "source": [
        "cirq_results = []\n",
        "cirq_simulator = cirq.Simulator()\n",
        "\n",
        "for vals in batch_vals:\n",
        "    resolver = cirq.ParamResolver({a: vals[0], b: vals[1]})\n",
        "    final_state = cirq_simulator.simulate(circuit, resolver).final_state\n",
        "    cirq_results.append(\n",
        "        [z0.expectation_from_wavefunction(final_state, {\n",
        "            q0: 0,\n",
        "            q1: 1\n",
        "        }).real])\n",
        "\n",
        "print('cirq batch results: \\n {}'.format(np.array(cirq_results)))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "W0JlZEu-f9Ac"
      },
      "source": [
        "The same operation is simplified in TFQ:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kGZVdcZ6y9lC"
      },
      "outputs": [],
      "source": [
        "tfq.layers.Expectation()(circuit,\n",
        "                         symbol_names=[a, b],\n",
        "                         symbol_values=batch_vals,\n",
        "                         operators=z0)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wppQ3TJ23mWC"
      },
      "source": [
        "## 2. Hybrid quantum-classical optimization\n",
        "\n",
        "Now that you've seen the basics, let's use TensorFlow Quantum to construct a *hybrid quantum-classical neural net*. You will train a classical neural net to control a single qubit. The control will be optimized to correctly prepare the qubit in the `0` or `1` state, overcoming a simulated systematic calibration error. This figure shows the architecture:\n",
        "\n",
        " <img src=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/quantum/tutorials/images/nn_control1.png?raw=true\" class=\"\">\n",
        "\n",
        "Even without a neural network this is a straightforward problem to solve, but the theme is similar to the real quantum control problems you might solve using TFQ. It demonstrates an end-to-end example of a quantum-classical computation using the `tfq.layers.ControlledPQC` (Parametrized Quantum Circuit) layer inside of a `tf.keras.Model`."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NlyxF3Q-6pIe"
      },
      "source": [
        "For the implementation of this tutorial, this is architecture is split into 3 parts:\n",
        "\n",
        "- The *input circuit* or *datapoint circuit*: The first three $R$ gates.\n",
        "- The *controlled circuit*: The other three $R$ gates.\n",
        "- The *controller*: The classical neural-network setting the parameters of the controlled circuit."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VjDf-nTM6ZSs"
      },
      "source": [
        "### 2.1 The controlled circuit definition\n",
        "\n",
        "Define a learnable single bit rotation, as indicated in the figure above. This will correspond to our controlled circuit."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "N-j7SCl-51-q"
      },
      "outputs": [],
      "source": [
        "# Parameters that the classical NN will feed values into.\n",
        "control_params = sympy.symbols('theta_1 theta_2 theta_3')\n",
        "\n",
        "# Create the parameterized circuit.\n",
        "qubit = cirq.GridQubit(0, 0)\n",
        "model_circuit = cirq.Circuit(\n",
        "    cirq.rz(control_params[0])(qubit),\n",
        "    cirq.ry(control_params[1])(qubit),\n",
        "    cirq.rx(control_params[2])(qubit))\n",
        "\n",
        "SVGCircuit(model_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wfjSbsvb7g9f"
      },
      "source": [
        "### 2.2 The controller\n",
        "\n",
        "Now define controller network: "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1v4CK2jD6pIj"
      },
      "outputs": [],
      "source": [
        "# The classical neural network layers.\n",
        "controller = tf.keras.Sequential([\n",
        "    tf.keras.layers.Dense(10, activation='elu'),\n",
        "    tf.keras.layers.Dense(3)\n",
        "])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QNimbsAt6pIm"
      },
      "source": [
        "Given a batch of commands, the controller outputs a batch of control signals for the controlled circuit. \n",
        "\n",
        "The controller is randomly initialized so these outputs are not useful, yet."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kZbYRTe16pIm"
      },
      "outputs": [],
      "source": [
        "controller(tf.constant([[0.0],[1.0]])).numpy()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XizLExg56pIp"
      },
      "source": [
        "### 2.3 Connect the controller to the circuit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "I5Pmy5-V6pIq"
      },
      "source": [
        "Use `tfq` to connect the controller to the controlled circuit, as a single `keras.Model`. \n",
        "\n",
        "See the [Keras Functional API guide](https://www.tensorflow.org/guide/keras/functional) for more about this style of model definition.\n",
        "\n",
        "First define the inputs to the model:  "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UfHF8NNE6pIr"
      },
      "outputs": [],
      "source": [
        "# This input is the simulated miscalibration that the model will learn to correct.\n",
        "circuits_input = tf.keras.Input(shape=(),\n",
        "                                # The circuit-tensor has dtype `tf.string` \n",
        "                                dtype=tf.string,\n",
        "                                name='circuits_input')\n",
        "\n",
        "# Commands will be either `0` or `1`, specifying the state to set the qubit to.\n",
        "commands_input = tf.keras.Input(shape=(1,),\n",
        "                                dtype=tf.dtypes.float32,\n",
        "                                name='commands_input')\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y9xN2mNl6pIu"
      },
      "source": [
        "Next apply operations to those inputs, to define the computation."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Zvt2YGmZ6pIu"
      },
      "outputs": [],
      "source": [
        "dense_2 = controller(commands_input)\n",
        "\n",
        "# TFQ layer for classically controlled circuits.\n",
        "expectation_layer = tfq.layers.ControlledPQC(model_circuit,\n",
        "                                             # Observe Z\n",
        "                                             operators = cirq.Z(qubit))\n",
        "expectation = expectation_layer([circuits_input, dense_2])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ip2jNA9h6pIy"
      },
      "source": [
        "Now package this computation as a `tf.keras.Model`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Xs6EMhah6pIz"
      },
      "outputs": [],
      "source": [
        "# The full Keras model is built from our layers.\n",
        "model = tf.keras.Model(inputs=[circuits_input, commands_input],\n",
        "                       outputs=expectation)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "w7kgqm3t6pI3"
      },
      "source": [
        "The network architecture is indicated by the plot of the model below.\n",
        "Compare this model plot to the architecture diagram to verify correctness.\n",
        "\n",
        "Note: May require a system install of the `graphviz` package."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ERXNPe4F6pI4"
      },
      "outputs": [],
      "source": [
        "tf.keras.utils.plot_model(model, show_shapes=True, dpi=70)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-Pbemgww6pI7"
      },
      "source": [
        "This model takes two inputs: The commands for the controller, and the input-circuit whose output the controller is attempting to correct. "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hpnIBK916pI8"
      },
      "source": [
        "### 2.4 The dataset"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yJSC9qH76pJA"
      },
      "source": [
        "The model attempts to output the correct correct measurement value of $\\hat{Z}$ for each command. The commands and correct values are defined below."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ciMIJAuH6pJA"
      },
      "outputs": [],
      "source": [
        "# The command input values to the classical NN.\n",
        "commands = np.array([[0], [1]], dtype=np.float32)\n",
        "\n",
        "# The desired Z expectation value at output of quantum circuit.\n",
        "expected_outputs = np.array([[1], [-1]], dtype=np.float32)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kV1LM_hZ6pJD"
      },
      "source": [
        "This is not the entire training dataset for this task. \n",
        "Each datapoint in the dataset also needs an input circuit."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bbiVHvSYVW4H"
      },
      "source": [
        "### 2.4 Input circuit definition\n",
        "\n",
        "The input-circuit below defines the random miscalibration the model will learn to correct."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_VYfzHffWo7n"
      },
      "outputs": [],
      "source": [
        "random_rotations = np.random.uniform(0, 2 * np.pi, 3)\n",
        "noisy_preparation = cirq.Circuit(\n",
        "  cirq.rx(random_rotations[0])(qubit),\n",
        "  cirq.ry(random_rotations[1])(qubit),\n",
        "  cirq.rz(random_rotations[2])(qubit)\n",
        ")\n",
        "datapoint_circuits = tfq.convert_to_tensor([\n",
        "  noisy_preparation\n",
        "] * 2)  # Make two copied of this circuit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FvOkMyKI6pJI"
      },
      "source": [
        "There are two copies of the circuit, one for each datapoint."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6nk2Yr3e6pJJ"
      },
      "outputs": [],
      "source": [
        "datapoint_circuits.shape"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gB--UhZZYgVY"
      },
      "source": [
        "### 2.5 Training"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jATjqUIv6pJM"
      },
      "source": [
        "With the inputs defined you can test-run the `tfq` model."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Lwphqvs96pJO"
      },
      "outputs": [],
      "source": [
        "model([datapoint_circuits, commands]).numpy()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9gyg5qSL6pJR"
      },
      "source": [
        "Now run a standard training process to adjust these values towards the `expected_outputs`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "dtPYqbNi8zeZ"
      },
      "outputs": [],
      "source": [
        "optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)\n",
        "loss = tf.keras.losses.MeanSquaredError()\n",
        "model.compile(optimizer=optimizer, loss=loss)\n",
        "history = model.fit(x=[datapoint_circuits, commands],\n",
        "                    y=expected_outputs,\n",
        "                    epochs=30,\n",
        "                    verbose=0)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "azE-qV0OaC1o"
      },
      "outputs": [],
      "source": [
        "plt.plot(history.history['loss'])\n",
        "plt.title(\"Learning to Control a Qubit\")\n",
        "plt.xlabel(\"Iterations\")\n",
        "plt.ylabel(\"Error in Control\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GTd5DGcRmmOK"
      },
      "source": [
        "From this plot you can see that the neural network has learned to overcome the systematic miscalibration."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "C2RfWismj66S"
      },
      "source": [
        "### 2.6 Verify outputs\n",
        "Now use the trained model, to correct the qubit calibration errors. With Cirq:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RoIlb7r7j5SY"
      },
      "outputs": [],
      "source": [
        "def check_error(command_values, desired_values):\n",
        "  \"\"\"Based on the value in `command_value` see how well you could prepare\n",
        "  the full circuit to have `desired_value` when taking expectation w.r.t. Z.\"\"\"\n",
        "  params_to_prepare_output = controller(command_values).numpy()\n",
        "  full_circuit = noisy_preparation + model_circuit\n",
        "\n",
        "  # Test how well you can prepare a state to get expectation the expectation\n",
        "  # value in `desired_values`\n",
        "  for index in [0, 1]:\n",
        "    state = cirq_simulator.simulate(\n",
        "        full_circuit,\n",
        "        {s:v for (s,v) in zip(control_params, params_to_prepare_output[index])}\n",
        "    ).final_state\n",
        "    expectation = z0.expectation_from_wavefunction(state, {qubit: 0}).real\n",
        "    print(f'For a desired output (expectation) of {desired_values[index]} with'\n",
        "          f' noisy preparation, the controller\\nnetwork found the following '\n",
        "          f'values for theta: {params_to_prepare_output[index]}\\nWhich gives an'\n",
        "          f' actual expectation of: {expectation}\\n')\n",
        "\n",
        "\n",
        "check_error(commands, expected_outputs)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wvW_ZDwmsws6"
      },
      "source": [
        "The value of the loss function during training provides a rough idea of how well the model is learning. The lower the loss, the closer the expectation values in the above cell is to `desired_values`. If you aren't as concerned with the parameter values, you can always check the outputs from above using `tfq`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aYskLTacs8Ku"
      },
      "outputs": [],
      "source": [
        "model([datapoint_circuits, commands])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jNrW0NXR-lDC"
      },
      "source": [
        "## 3 Learning to prepare eigenstates of different operators\n",
        "\n",
        "The choice of the $\\pm \\hat{Z}$ eigenstates corresponding to 1 and 0 was arbitrary. You could have just as easily wanted 1 to correspond to the $+ \\hat{Z}$ eigenstate and 0 to correspond to the $-\\hat{X}$ eigenstate. One way to accomplish this is by specifying a different measurement operator for each command, as indicated in the figure below:\n",
        "\n",
        " <img src=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/quantum/tutorials/images/nn_control2.png?raw=true\" class=\"\">\n",
        "\n",
        "This requires use of <code>tfq.layers.Expectation</code>. Now your input has grown to include three objects: circuit, command, and operator. The output is still the expectation value."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ci3WMZ9CjEM1"
      },
      "source": [
        "### 3.1 New model definition\n",
        "\n",
        "Lets take a look at the model to accomplish this task:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "hta0G3Nc6pJY"
      },
      "outputs": [],
      "source": [
        "# Define inputs.\n",
        "commands_input = tf.keras.layers.Input(shape=(1),\n",
        "                                       dtype=tf.dtypes.float32,\n",
        "                                       name='commands_input')\n",
        "circuits_input = tf.keras.Input(shape=(),\n",
        "                                # The circuit-tensor has dtype `tf.string` \n",
        "                                dtype=tf.dtypes.string,\n",
        "                                name='circuits_input')\n",
        "operators_input = tf.keras.Input(shape=(1,),\n",
        "                                 dtype=tf.dtypes.string,\n",
        "                                 name='operators_input')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dtdnkrZm6pJb"
      },
      "source": [
        "Here is the controller network:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "n_aTG4g3-y0F"
      },
      "outputs": [],
      "source": [
        "# Define classical NN.\n",
        "controller = tf.keras.Sequential([\n",
        "    tf.keras.layers.Dense(10, activation='elu'),\n",
        "    tf.keras.layers.Dense(3)\n",
        "])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "q9aN2ciy6pJf"
      },
      "source": [
        "Combine the circuit and the controller into a single `keras.Model` using `tfq`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "IMHjiKit6pJg"
      },
      "outputs": [],
      "source": [
        "dense_2 = controller(commands_input)\n",
        "\n",
        "# Since you aren't using a PQC or ControlledPQC you must append\n",
        "# your model circuit onto the datapoint circuit tensor manually.\n",
        "full_circuit = tfq.layers.AddCircuit()(circuits_input, append=model_circuit)\n",
        "expectation_output = tfq.layers.Expectation()(full_circuit,\n",
        "                                              symbol_names=control_params,\n",
        "                                              symbol_values=dense_2,\n",
        "                                              operators=operators_input)\n",
        "\n",
        "# Contruct your Keras model.\n",
        "two_axis_control_model = tf.keras.Model(\n",
        "    inputs=[circuits_input, commands_input, operators_input],\n",
        "    outputs=[expectation_output])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VQTM6CCiD4gU"
      },
      "source": [
        "### 3.2 The dataset\n",
        "\n",
        "Now you will also include the operators you wish to measure for each datapoint you supply for `model_circuit`:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "4gw_L3JG0_G0"
      },
      "outputs": [],
      "source": [
        "# The operators to measure, for each command.\n",
        "operator_data = tfq.convert_to_tensor([[cirq.X(qubit)], [cirq.Z(qubit)]])\n",
        "\n",
        "# The command input values to the classical NN.\n",
        "commands = np.array([[0], [1]], dtype=np.float32)\n",
        "\n",
        "# The desired expectation value at output of quantum circuit.\n",
        "expected_outputs = np.array([[1], [-1]], dtype=np.float32)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ALCKSvwh0_G2"
      },
      "source": [
        "### 3.3 Training\n",
        "\n",
        "Now that you have your new inputs and outputs you can train once again using keras."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "nFuGA73MAA4p"
      },
      "outputs": [],
      "source": [
        "optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)\n",
        "loss = tf.keras.losses.MeanSquaredError()\n",
        "\n",
        "two_axis_control_model.compile(optimizer=optimizer, loss=loss)\n",
        "\n",
        "history = two_axis_control_model.fit(\n",
        "    x=[datapoint_circuits, commands, operator_data],\n",
        "    y=expected_outputs,\n",
        "    epochs=30,\n",
        "    verbose=1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Cf_G-GdturLL"
      },
      "outputs": [],
      "source": [
        "plt.plot(history.history['loss'])\n",
        "plt.title(\"Learning to Control a Qubit\")\n",
        "plt.xlabel(\"Iterations\")\n",
        "plt.ylabel(\"Error in Control\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sdCPDH9NlJBl"
      },
      "source": [
        "The loss function has dropped to zero."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NzY8eSVm6pJs"
      },
      "source": [
        "The `controller` is available as a stand-alone model. Call the controller, and check its response to each command signal. It would take some work to correctly compare these outputs to the contents of `random_rotations`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uXmH0TQ76pJt"
      },
      "outputs": [],
      "source": [
        "controller.predict(np.array([0,1]))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "n2WtXnsxubD2"
      },
      "source": [
        "Success: See if you can adapt the `check_error` function from your first model to work with this new model architecture."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "hello_many_worlds.ipynb",
      "toc_visible": true<commit_msg>Translate hello_many_worlds.ipynb via GitLocalize<commit_after>{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xLOXFOT5Q40E"
      },
      "source": [
        "##### Copyright 2020 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "iiQkM5ZgQ8r2"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "j6331ZSsQGY3"
      },
      "source": [
        "# こんにちは、多くの世界"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "i9Jcnb8bQQyd"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/quantum/tutorials/hello_many_worlds\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">View on TensorFlow.org</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/quantum/blob/master/docs/tutorials/hello_many_worlds.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Run in Google Colab</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/quantum/blob/master/docs/tutorials/hello_many_worlds.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">View source on GitHub</a></td>\n",
        "  <td><a href=\"https://storage.googleapis.com/tensorflow_docs/quantum/docs/tutorials/hello_many_worlds.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\">Download notebook</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6tYn2HaAUgH0"
      },
      "source": [
        "このチュートリアルでは、古典的なニューラルネットワークが量子ビット・キャリブレーションエラーの訂正を学習する方法を紹介します。<a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq\" class=\"external\">Circq</a> は NISQ（ノイズの多い中間スケール量子）回路を作成、編集、呼び出すための Python フレームワークであり、ここでは Cirq が TensorFlow Quantum とどのようにやり取りするかを示します。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sPZoNKvpUaqa"
      },
      "source": [
        "## セットアップ"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "TorxE5tnkvb2"
      },
      "outputs": [],
      "source": [
        "!pip install tensorflow==2.1.0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FxkQA6oblNqI"
      },
      "source": [
        "TensorFlow Quantum をインストールします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "saFHsRDpkvkH"
      },
      "outputs": [],
      "source": [
        "!pip install tensorflow-quantum"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "F1L8h1YKUvIO"
      },
      "source": [
        "次に、TensorFlow とモジュールの依存関係をインポートします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "enZ300Bflq80"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow_quantum as tfq\n",
        "\n",
        "import cirq\n",
        "import sympy\n",
        "import numpy as np\n",
        "\n",
        "# visualization tools\n",
        "%matplotlib inline\n",
        "import matplotlib.pyplot as plt\n",
        "from cirq.contrib.svg import SVGCircuit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b08Mmbs8lr81"
      },
      "source": [
        "## 1. 基本"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y31qSRCczI-L"
      },
      "source": [
        "### 1.1 Cirq とパラメータ化された量子回路\n",
        "\n",
        "TensorFlow Quantum (TFQ) について説明する前に、<a target=\"_blank\" href=\"https://github.com/quantumlib/Cirq\" class=\"external\">Circq</a> の基本をいくつか見てみましょう。Cirq は、Google の量子コンピューティング用の Python ライブラリで、静的ゲートやパラメータ化されたゲートなどの回路の定義に使用します。\n",
        "\n",
        "Cirq は、<a target=\"_blank\" href=\"https://www.sympy.org\" class=\"external\">SymPy</a> シンボルを使用して自由パラメータを表します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "2yQdmhQLCrzQ"
      },
      "outputs": [],
      "source": [
        "a, b = sympy.symbols('a b')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "itUlpbKmDYNW"
      },
      "source": [
        "次のコードは、上記のパラメータを使用して 2 つの量子ビット回路を作成します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Ps-pd2mndXs7"
      },
      "outputs": [],
      "source": [
        "# Create two qubits\n",
        "q0, q1 = cirq.GridQubit.rect(1, 2)\n",
        "\n",
        "# Create a circuit on these qubits using the parameters you created above.\n",
        "circuit = cirq.Circuit(\n",
        "    cirq.rx(a).on(q0),\n",
        "    cirq.ry(b).on(q1), cirq.CNOT(control=q0, target=q1))\n",
        "\n",
        "SVGCircuit(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zcCX109cJUaz"
      },
      "source": [
        "回路を評価するには、`cirq.Simulator`インターフェースを使用します。回路内の自由パラメータを特定の数値に置き換えるには、`cirq.ParamResolver`オブジェクトを渡します。以下のコードは、パラメータ化された回路の生の状態ベクトル出力を計算します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "VMq7EayNRyQb"
      },
      "outputs": [],
      "source": [
        "# Calculate a state vector with a=0.5 and b=-0.5.\n",
        "resolver = cirq.ParamResolver({a: 0.5, b: -0.5})\n",
        "output_state_vector = cirq.Simulator().simulate(circuit, resolver).final_state\n",
        "output_state_vector"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-SUlLpXBeicF"
      },
      "source": [
        "状態ベクトルは、シミュレーションの外から直接アクセスすることはできません（上記の複素数出力に注意してください）。物理的に現実的にするには、状態ベクトルを古典的コンピュータが理解できる実数に変換する測定値を指定する必要があります。Cirq は、<a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Pauli_matrices\" class=\"external\">Pauli 演算子</a> $\\hat{X}$, $\\hat{Y}$ および $\\hat{Z}$ の組み合わせを使用して測定値を指定します。例として、次のコードは、シミュレーションした状態ベクトルで $\\hat{Z}_0$ と $\\frac{1}{2}\\hat{Z}_0 + \\hat{X}_1$ を測定します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "hrSnOCi3ehr_"
      },
      "outputs": [],
      "source": [
        "z0 = cirq.Z(q0)\n",
        "\n",
        "qubit_map={q0: 0, q1: 1}\n",
        "\n",
        "z0.expectation_from_wavefunction(output_state_vector, qubit_map).real"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "OZ0lWFXv6pII"
      },
      "outputs": [],
      "source": [
        "z0x1 = 0.5 * z0 + cirq.X(q1)\n",
        "\n",
        "z0x1.expectation_from_wavefunction(output_state_vector, qubit_map).real"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bkC-yjIolDNr"
      },
      "source": [
        "### 1.2 テンソルとしての量子回路\n",
        "\n",
        "TensorFlow Quantum (TFQ) は、Cirq オブジェクトをテンソルに変換する関数である`tfq.convert_to_tensor`を提供します。これにより、Cirq オブジェクトを<a target=\"_blank\" href=\"https://www.tensorflow.org/quantum/api_docs/python/tfq/layers\">量子レイヤー</a>および<a target=\"_blank\" href=\"https://www.tensorflow.org/quantum/api_docs/python/tfq/get_expectation_op\">量子演算</a>に送信できます。この関数は、Cirq Circuits と Cirq Paulis のリストまたは配列で呼び出すことができます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1gLQjA02mIyy"
      },
      "outputs": [],
      "source": [
        "# Rank 1 tensor containing 1 circuit.\n",
        "circuit_tensor = tfq.convert_to_tensor([circuit])\n",
        "\n",
        "print(circuit_tensor.shape)\n",
        "print(circuit_tensor.dtype)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SJy6AkbU6pIP"
      },
      "source": [
        "これは、Cirq オブジェクトを`tf.string`テンソルとしてエンコードし、`tfq`演算は必要に応じてデコードします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aX_vEmCKmpQS"
      },
      "outputs": [],
      "source": [
        "# Rank 1 tensor containing 2 Pauli operators.\n",
        "pauli_tensor = tfq.convert_to_tensor([z0, z0x1])\n",
        "pauli_tensor.shape"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FI1JLWe6m8JF"
      },
      "source": [
        "### 1.3 バッチ回路シミュレーション\n",
        "\n",
        "TFQ は、期待値、サンプル、および状態ベクトルを計算するためのメソッドを提供します。まず、*期待値*から見ていきましょう。\n",
        "\n",
        "期待値を計算するための最高レベルのインターフェースは、`tf.keras.Layer`である`tfq.layers.Expectation`レイヤーです。最も単純な形式では、このレイヤーは、多くの`cirq.ParamResolvers`でパラメータ化された回路をシミュレートすることと同等ですが、TFQ では TensorFlow セマンティクスに従ったバッチ処理が可能であり、回路は効率的な C++ コードを使用してシミュレートされます。\n",
        "\n",
        "`a`と`b`パラメータの代わりに値のバッチを作成します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1fsVZhF5lIXp"
      },
      "outputs": [],
      "source": [
        "batch_vals = np.array(np.random.uniform(0, 2 * np.pi, (5, 2)), dtype=np.float32)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ip7jlGXIf22u"
      },
      "source": [
        "Cirq のパラメータ値に対するバッチ回路の実行には、ループが必要です。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RsfF53UCJtr9"
      },
      "outputs": [],
      "source": [
        "cirq_results = []\n",
        "cirq_simulator = cirq.Simulator()\n",
        "\n",
        "for vals in batch_vals:\n",
        "    resolver = cirq.ParamResolver({a: vals[0], b: vals[1]})\n",
        "    final_state = cirq_simulator.simulate(circuit, resolver).final_state\n",
        "    cirq_results.append(\n",
        "        [z0.expectation_from_wavefunction(final_state, {\n",
        "            q0: 0,\n",
        "            q1: 1\n",
        "        }).real])\n",
        "\n",
        "print('cirq batch results: \\n {}'.format(np.array(cirq_results)))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "W0JlZEu-f9Ac"
      },
      "source": [
        "TFQ では同じ演算が簡略化されています。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kGZVdcZ6y9lC"
      },
      "outputs": [],
      "source": [
        "tfq.layers.Expectation()(circuit,\n",
        "                         symbol_names=[a, b],\n",
        "                         symbol_values=batch_vals,\n",
        "                         operators=z0)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wppQ3TJ23mWC"
      },
      "source": [
        "## 2. 量子古典ハイブリッドの最適化\n",
        "\n",
        "以上は基本の説明でした。次に、TensorFlow Quantum を使用して*量子古典ハイブリッドニューラルネット*を構築しましょう。古典的なニューラルネットをトレーニングして、1 つの量子ビットを制御します。コントロールは、`0`または`1`の状態の量子ビットを正しく準備するように最適化され、シミュレートされた系統的なキャリブレーションエラーを克服します。以下の図は、アーキテクチャを示しています。\n",
        "\n",
        " <img src=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/quantum/tutorials/images/nn_control1.png?raw=true\" class=\"\">\n",
        "\n",
        "これはニューラルネットワークがなくても簡単に解決できる問題ですが、テーマは TFQ を使用して解決できる実際の量子制御の問題と似ています。これは、`tf.keras.Model`内の`tfq.layers.ControlledPQC` (Parametrized Quantum Circuit) レイヤーを使用した量子古典計算のエンドツーエンドの例を示しています。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NlyxF3Q-6pIe"
      },
      "source": [
        "このチュートリアルの実装では、アーキテクチャは 3 つの部分に分かれています。\n",
        "\n",
        "- *入力回路*または*データポイント回路*：最初の 3 つの $R$ ゲート。\n",
        "- *制御回路*：その他の 3 つの $R$ ゲート。\n",
        "- *コントローラ*：制御回路のパラメータを設定する古典的なニューラルネットワーク。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VjDf-nTM6ZSs"
      },
      "source": [
        "### 2.1 制御回路の定義\n",
        "\n",
        "上の図に示すように、学習可能なシングルビットローテーションを定義します。これは、制御回路に対応します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "N-j7SCl-51-q"
      },
      "outputs": [],
      "source": [
        "# Parameters that the classical NN will feed values into.\n",
        "control_params = sympy.symbols('theta_1 theta_2 theta_3')\n",
        "\n",
        "# Create the parameterized circuit.\n",
        "qubit = cirq.GridQubit(0, 0)\n",
        "model_circuit = cirq.Circuit(\n",
        "    cirq.rz(control_params[0])(qubit),\n",
        "    cirq.ry(control_params[1])(qubit),\n",
        "    cirq.rx(control_params[2])(qubit))\n",
        "\n",
        "SVGCircuit(model_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wfjSbsvb7g9f"
      },
      "source": [
        "### 2.2 コントローラ\n",
        "\n",
        "次に、コントローラネットワークを定義します。 "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1v4CK2jD6pIj"
      },
      "outputs": [],
      "source": [
        "# The classical neural network layers.\n",
        "controller = tf.keras.Sequential([\n",
        "    tf.keras.layers.Dense(10, activation='elu'),\n",
        "    tf.keras.layers.Dense(3)\n",
        "])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QNimbsAt6pIm"
      },
      "source": [
        "コントローラにコマンドのバッチを与えると、制御された回路の制御信号のバッチが出力されます。\n",
        "\n",
        "コントローラはランダムに初期化されるため、これらの出力はまだ有用ではありません。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "kZbYRTe16pIm"
      },
      "outputs": [],
      "source": [
        "controller(tf.constant([[0.0],[1.0]])).numpy()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XizLExg56pIp"
      },
      "source": [
        "### 2.3 コントローラを回路に接続する"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "I5Pmy5-V6pIq"
      },
      "source": [
        "`tfq`を使用して、コントローラを 1 つの`keras.Model`として制御回路に接続します。\n",
        "\n",
        "このスタイルのモデル定義の詳細については、[Keras Functional API ガイド](https://www.tensorflow.org/guide/keras/functional)をご覧ください。\n",
        "\n",
        "まず、モデルへの入力を定義します。 "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UfHF8NNE6pIr"
      },
      "outputs": [],
      "source": [
        "# This input is the simulated miscalibration that the model will learn to correct.\n",
        "circuits_input = tf.keras.Input(shape=(),\n",
        "                                # The circuit-tensor has dtype `tf.string` \n",
        "                                dtype=tf.string,\n",
        "                                name='circuits_input')\n",
        "\n",
        "# Commands will be either `0` or `1`, specifying the state to set the qubit to.\n",
        "commands_input = tf.keras.Input(shape=(1,),\n",
        "                                dtype=tf.dtypes.float32,\n",
        "                                name='commands_input')\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y9xN2mNl6pIu"
      },
      "source": [
        "次に、これらの入力に演算を適用して、計算を定義します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Zvt2YGmZ6pIu"
      },
      "outputs": [],
      "source": [
        "dense_2 = controller(commands_input)\n",
        "\n",
        "# TFQ layer for classically controlled circuits.\n",
        "expectation_layer = tfq.layers.ControlledPQC(model_circuit,\n",
        "                                             # Observe Z\n",
        "                                             operators = cirq.Z(qubit))\n",
        "expectation = expectation_layer([circuits_input, dense_2])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ip2jNA9h6pIy"
      },
      "source": [
        "次に、この計算を`tf.keras.Model`としてパッケージ化します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Xs6EMhah6pIz"
      },
      "outputs": [],
      "source": [
        "# The full Keras model is built from our layers.\n",
        "model = tf.keras.Model(inputs=[circuits_input, commands_input],\n",
        "                       outputs=expectation)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "w7kgqm3t6pI3"
      },
      "source": [
        "ネットワークアーキテクチャは、以下のモデルのプロットで示されています。このモデルプロットをアーキテクチャ図と比較して、正確さを確認します。\n",
        "\n",
        "注意: `graphviz`パッケージのシステムインストールが必要になる場合があります。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ERXNPe4F6pI4"
      },
      "outputs": [],
      "source": [
        "tf.keras.utils.plot_model(model, show_shapes=True, dpi=70)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-Pbemgww6pI7"
      },
      "source": [
        "このモデルは、コントローラのコマンドと、コントローラが出力を修正しようとしている入力回路の 2 つの入力を受け取ります。 "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hpnIBK916pI8"
      },
      "source": [
        "### 2.4 データセット"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yJSC9qH76pJA"
      },
      "source": [
        "モデルは、コマンドごとに $\\hat{Z}$ の正しい測定値の出力を試行します。コマンドと正しい値の定義は以下のとおりです。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ciMIJAuH6pJA"
      },
      "outputs": [],
      "source": [
        "# The command input values to the classical NN.\n",
        "commands = np.array([[0], [1]], dtype=np.float32)\n",
        "\n",
        "# The desired Z expectation value at output of quantum circuit.\n",
        "expected_outputs = np.array([[1], [-1]], dtype=np.float32)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kV1LM_hZ6pJD"
      },
      "source": [
        "これは、このタスクのトレーニングデータセット全体ではありません。データセット内の各データポイントにも入力回路が必要です。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bbiVHvSYVW4H"
      },
      "source": [
        "### 2.4 入力回路の定義\n",
        "\n",
        "以下の入力回路は、モデルが修正することを学習するためのランダムな誤校正を定義します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_VYfzHffWo7n"
      },
      "outputs": [],
      "source": [
        "random_rotations = np.random.uniform(0, 2 * np.pi, 3)\n",
        "noisy_preparation = cirq.Circuit(\n",
        "  cirq.rx(random_rotations[0])(qubit),\n",
        "  cirq.ry(random_rotations[1])(qubit),\n",
        "  cirq.rz(random_rotations[2])(qubit)\n",
        ")\n",
        "datapoint_circuits = tfq.convert_to_tensor([\n",
        "  noisy_preparation\n",
        "] * 2)  # Make two copied of this circuit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FvOkMyKI6pJI"
      },
      "source": [
        "回路には 2 つのコピーがあります（データポイントごとに 1 つずつ）。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6nk2Yr3e6pJJ"
      },
      "outputs": [],
      "source": [
        "datapoint_circuits.shape"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gB--UhZZYgVY"
      },
      "source": [
        "### 2.5 トレーニング"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jATjqUIv6pJM"
      },
      "source": [
        "定義された入力を使用して、`tfq`モデルのテストランを実行します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Lwphqvs96pJO"
      },
      "outputs": [],
      "source": [
        "model([datapoint_circuits, commands]).numpy()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9gyg5qSL6pJR"
      },
      "source": [
        "次に、標準のトレーニングプロセスを実行して、これらの値を`expected_outputs`に向けて調整します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "dtPYqbNi8zeZ"
      },
      "outputs": [],
      "source": [
        "optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)\n",
        "loss = tf.keras.losses.MeanSquaredError()\n",
        "model.compile(optimizer=optimizer, loss=loss)\n",
        "history = model.fit(x=[datapoint_circuits, commands],\n",
        "                    y=expected_outputs,\n",
        "                    epochs=30,\n",
        "                    verbose=0)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "azE-qV0OaC1o"
      },
      "outputs": [],
      "source": [
        "plt.plot(history.history['loss'])\n",
        "plt.title(\"Learning to Control a Qubit\")\n",
        "plt.xlabel(\"Iterations\")\n",
        "plt.ylabel(\"Error in Control\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GTd5DGcRmmOK"
      },
      "source": [
        "このプロットから、ニューラルネットワークが体系的なキャリブレーションエラーを訂正することを学習したことがわかります。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "C2RfWismj66S"
      },
      "source": [
        "### 2.6 出力の確認\n",
        "\n",
        "次に、トレーニング済みモデルを使用して、量子ビット・キャリブレーションエラーを修正します。Cirq を使用する場合は以下のとおりです。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RoIlb7r7j5SY"
      },
      "outputs": [],
      "source": [
        "def check_error(command_values, desired_values):\n",
        "  \"\"\"Based on the value in `command_value` see how well you could prepare\n",
        "  the full circuit to have `desired_value` when taking expectation w.r.t. Z.\"\"\"\n",
        "  params_to_prepare_output = controller(command_values).numpy()\n",
        "  full_circuit = noisy_preparation + model_circuit\n",
        "\n",
        "  # Test how well you can prepare a state to get expectation the expectation\n",
        "  # value in `desired_values`\n",
        "  for index in [0, 1]:\n",
        "    state = cirq_simulator.simulate(\n",
        "        full_circuit,\n",
        "        {s:v for (s,v) in zip(control_params, params_to_prepare_output[index])}\n",
        "    ).final_state\n",
        "    expectation = z0.expectation_from_wavefunction(state, {qubit: 0}).real\n",
        "    print(f'For a desired output (expectation) of {desired_values[index]} with'\n",
        "          f' noisy preparation, the controller\\nnetwork found the following '\n",
        "          f'values for theta: {params_to_prepare_output[index]}\\nWhich gives an'\n",
        "          f' actual expectation of: {expectation}\\n')\n",
        "\n",
        "\n",
        "check_error(commands, expected_outputs)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wvW_ZDwmsws6"
      },
      "source": [
        "トレーニング中の損失関数の値から、モデルの学習がどれほど進んでいるかが大まかに分かります。損失が小さいほど、上記のセルの期待値は`Desired_values`に近くなります。パラメータ値に関心がない場合は、`tfq`を使用して上記からの出力をいつでも確認できます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aYskLTacs8Ku"
      },
      "outputs": [],
      "source": [
        "model([datapoint_circuits, commands])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jNrW0NXR-lDC"
      },
      "source": [
        "## 3 さまざまな演算子の固有状態の準備について学ぶ\n",
        "\n",
        "1 と 0 に対応する $\\pm \\hat{Z}$ 固有状態の選択は任意でした。1 を $+ \\hat{Z}$ 固有状態に対応させ、0 を $-\\hat{X}$ 固有状態に対応させることも簡単にできます。そのためには、次の図に示すように、コマンドごとに異なる測定演算子を指定します。\n",
        "\n",
        " <img src=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/quantum/tutorials/images/nn_control2.png?raw=true\" class=\"\">\n",
        "\n",
        "これには、<code>tfq.layers.Expectation</code>を使用する必要があります。これで、入力は、回路、コマンド、および演算子の 3 つのオブジェクトを含むようになりました。出力は期待値のままです。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ci3WMZ9CjEM1"
      },
      "source": [
        "### 3.1 新しいモデルの定義\n",
        "\n",
        "このタスクを実行するためのモデルを見てみましょう。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "hta0G3Nc6pJY"
      },
      "outputs": [],
      "source": [
        "# Define inputs.\n",
        "commands_input = tf.keras.layers.Input(shape=(1),\n",
        "                                       dtype=tf.dtypes.float32,\n",
        "                                       name='commands_input')\n",
        "circuits_input = tf.keras.Input(shape=(),\n",
        "                                # The circuit-tensor has dtype `tf.string` \n",
        "                                dtype=tf.dtypes.string,\n",
        "                                name='circuits_input')\n",
        "operators_input = tf.keras.Input(shape=(1,),\n",
        "                                 dtype=tf.dtypes.string,\n",
        "                                 name='operators_input')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dtdnkrZm6pJb"
      },
      "source": [
        "コントローラネットワークは次のとおりです。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "n_aTG4g3-y0F"
      },
      "outputs": [],
      "source": [
        "# Define classical NN.\n",
        "controller = tf.keras.Sequential([\n",
        "    tf.keras.layers.Dense(10, activation='elu'),\n",
        "    tf.keras.layers.Dense(3)\n",
        "])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "q9aN2ciy6pJf"
      },
      "source": [
        "`tfq`を使用して、回路とコントローラを 1 つの`keras.Model`に結合します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "IMHjiKit6pJg"
      },
      "outputs": [],
      "source": [
        "dense_2 = controller(commands_input)\n",
        "\n",
        "# Since you aren't using a PQC or ControlledPQC you must append\n",
        "# your model circuit onto the datapoint circuit tensor manually.\n",
        "full_circuit = tfq.layers.AddCircuit()(circuits_input, append=model_circuit)\n",
        "expectation_output = tfq.layers.Expectation()(full_circuit,\n",
        "                                              symbol_names=control_params,\n",
        "                                              symbol_values=dense_2,\n",
        "                                              operators=operators_input)\n",
        "\n",
        "# Contruct your Keras model.\n",
        "two_axis_control_model = tf.keras.Model(\n",
        "    inputs=[circuits_input, commands_input, operators_input],\n",
        "    outputs=[expectation_output])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VQTM6CCiD4gU"
      },
      "source": [
        "### 3.2 データセット\n",
        "\n",
        "`model_circuit`に提供する各データポイントに対して測定する演算子も含めます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "4gw_L3JG0_G0"
      },
      "outputs": [],
      "source": [
        "# The operators to measure, for each command.\n",
        "operator_data = tfq.convert_to_tensor([[cirq.X(qubit)], [cirq.Z(qubit)]])\n",
        "\n",
        "# The command input values to the classical NN.\n",
        "commands = np.array([[0], [1]], dtype=np.float32)\n",
        "\n",
        "# The desired expectation value at output of quantum circuit.\n",
        "expected_outputs = np.array([[1], [-1]], dtype=np.float32)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ALCKSvwh0_G2"
      },
      "source": [
        "### 3.3トレーニング\n",
        "\n",
        "新しい入力と出力を使用し、keras でもう一度トレーニングします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "nFuGA73MAA4p"
      },
      "outputs": [],
      "source": [
        "optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)\n",
        "loss = tf.keras.losses.MeanSquaredError()\n",
        "\n",
        "two_axis_control_model.compile(optimizer=optimizer, loss=loss)\n",
        "\n",
        "history = two_axis_control_model.fit(\n",
        "    x=[datapoint_circuits, commands, operator_data],\n",
        "    y=expected_outputs,\n",
        "    epochs=30,\n",
        "    verbose=1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Cf_G-GdturLL"
      },
      "outputs": [],
      "source": [
        "plt.plot(history.history['loss'])\n",
        "plt.title(\"Learning to Control a Qubit\")\n",
        "plt.xlabel(\"Iterations\")\n",
        "plt.ylabel(\"Error in Control\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sdCPDH9NlJBl"
      },
      "source": [
        "損失関数はゼロに低下しました。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NzY8eSVm6pJs"
      },
      "source": [
        "`controller`はスタンドアロンモデルとして利用できます。コントローラを呼び出し、各コマンド信号に対する応答を確認します。多少手間がかかりますが、これらの出力を`random_rotations`の内容と比較します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uXmH0TQ76pJt"
      },
      "outputs": [],
      "source": [
        "controller.predict(np.array([0,1]))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "n2WtXnsxubD2"
      },
      "source": [
        "成功: 最初のモデルの`check_error`関数を、この新しいモデルアーキテクチャで動作するように適合させることができるかどうかを確認します。"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "hello_many_worlds.ipynb",
      "toc_visible": true
{'fraction_non_alphanumeric': 0.16573479987778797, 'fraction_numerical': 0.011426825542315918, 'mean_word_length': 1.858434129513995, 'pattern_counts': {'":': 830, '<': 79, '<?xml version=': 0, '>': 79, 'https://': 36, 'lorem ipsum': 0, 'www.': 20, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 78, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3307652', 'n_tokens_mistral': 24788, 'n_tokens_neox': 23818, 'n_words': 4076}