| { |
| "cells": [ |
| { |
| "cell_type": "markdown", |
| "metadata": { |
| "id": "PZtRtMMUZHJS" |
| }, |
| "source": [ |
| "##### Copyright 2020 Google LLC.\n", |
| "\n", |
| "Licensed under the Apache License, Version 2.0 (the \"License\");" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": null, |
| "metadata": { |
| "cellView": "form", |
| "id": "TouZL3JZZSQe" |
| }, |
| "outputs": [], |
| "source": [ |
| "#@title License header\n", |
| "# Copyright 2020 Google LLC\n", |
| "#\n", |
| "# 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": "O6c3qfq5Zv57" |
| }, |
| "source": [ |
| "# MNIST Model TensorFlow Training, IREE Execution\n", |
| "\n", |
| "## Overview\n", |
| "\n", |
| "This notebook creates and trains a TensorFlow 2.0 model for recognizing handwritten digits using the [MNIST dataset](https://en.wikipedia.org/wiki/MNIST_database), then compiles and executes that trained model using IREE.\n", |
| "\n", |
| "## Running Locally\n", |
| "\n", |
| "* Refer to [using_colab.md](https://google.github.io/iree/using-iree/using-colab) for general information\n", |
| "* Ensure that you have a recent version of TensorFlow 2.0 [installed on your system](https://www.tensorflow.org/install)\n", |
| "* Enable IREE/TF integration by adding to your user.bazelrc: `build --define=iree_tensorflow=true`\n", |
| "* Start colab by running `python colab/start_colab_kernel.py` (see that file for additional instructions)\n", |
| "* Note: you may need to restart your runtime in order to re-run certain cells. Some of the APIs are not yet stable enough for repeated invocations" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 1, |
| "metadata": { |
| "cellView": "both", |
| "executionInfo": { |
| "elapsed": 12184, |
| "status": "ok", |
| "timestamp": 1601949421367, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "EPF7RGQDYK-M", |
| "outputId": "2c6d6e18-56e8-4431-91b8-9021589b68d0" |
| }, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "TensorFlow version: 2.4.0\n", |
| "Numpy version: 1.16.4\n" |
| ] |
| } |
| ], |
| "source": [ |
| "#@title Imports\n", |
| "\n", |
| "from pyiree import rt as ireert\n", |
| "from pyiree.tf import compiler as ireec\n", |
| "from pyiree.tf.support import tf_utils\n", |
| "\n", |
| "from matplotlib import pyplot as plt\n", |
| "import numpy as np\n", |
| "import tensorflow as tf\n", |
| "\n", |
| "plt.style.use(\"seaborn-whitegrid\")\n", |
| "plt.rcParams[\"font.family\"] = \"monospace\"\n", |
| "\n", |
| "# Print version information for future notebook users to reference.\n", |
| "print(\"TensorFlow version: \", tf.__version__)\n", |
| "print(\"Numpy version: \", np.__version__)" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": { |
| "id": "5vkQOMOMbXdy" |
| }, |
| "source": [ |
| "# Create and Train MNIST Model in TensorFlow\n", |
| "\n", |
| "The specific details of the training process here aren't critical to the model compilation and execution through IREE." |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 17, |
| "metadata": { |
| "cellView": "both", |
| "colab": { |
| "height": 316 |
| }, |
| "executionInfo": { |
| "elapsed": 2328, |
| "status": "ok", |
| "timestamp": 1601949599195, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "XPo8ATGqqZbW", |
| "outputId": "a62fb08a-84a4-445e-efad-6899432fe1f5" |
| }, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "Sample image from the dataset:\n" |
| ] |
| }, |
| { |
| "data": { |
| "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQwAAAEaCAYAAADkA2kVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAED5JREFUeJzt3X1szef/x/FXT9sN07KJGTFVlrir\ncrRpUbT6nY4xrJgYi2QWtZXQsptks5lZRuamUzchGYtlk5DYjCFt52braoxUGLqoGatNNzOtdhTn\n9PfHfj1ZY855V+9Un4+/ml6fm+sc8TzXOT4+x6+8vLxcAGDgqO8JAGg4CAYAM4IBwIxgADAjGADM\nCAYAM4JRhwoLC+V0OtWzZ09NmDChvqdzV5o/f76cTqe6du2qnJycKu0bHx9f5X2qe87GplEH49Sp\nU5o8ebIiIyPVr18/zZgxo1bP16ZNG+Xm5urtt9+uleNnZ2dr1qxZkqRBgwbp77//liRlZWVp/Pjx\nCgsL02uvvVZpn/T0dPXo0UNOp1NOp1Px8fGesfLyci1atEj9+/dXdHS0UlNTVVJS4hn/5ZdfNGXK\nFDmdTsXExGjLli3VfgxvvvmmcnNz1a5du2ofq77POXz4cM/z6nQ61b17d73zzjs1eo66FlDfE6hP\nycnJmjBhgtatW6fS0lLt3LmzvqdULcePH1ePHj1UWFio4OBgNWvWTJIUFBSkKVOmKCcnR9euXbtl\nv2HDhmnx4sW3/H7Hjh3auXOnPvvsMwUFBWnGjBlauXKlXn31VblcLk2bNk2xsbFavny5/Pz89Pvv\nv9f6Y2xIvvzyS8/Pbrdb8fHxSkhIqMcZVV+jXWFcunRJZ8+e1dixY+Xv76/g4GCNHz/eM75v3z6N\nGjVKffr00eOPP661a9eq4qLY+Ph4JSUlKSYmRmvWrFFMTIzmzp0rSSooKFCXLl20atUqRUREaOTI\nkTpx4oRpTi6XSytWrFB8fLz69++vBQsW6MaNG+bH9MMPPygsLEzHjh1Tz549Pb+Pjo5WQkKCWrRo\nYT6WJJ0/f15Op1Nt2rRRs2bNFBcXp9OnT0uSDh06pKKiIqWmpuqBBx5Qs2bN1LFjxyod/06kpKSo\nf//+ioqK0uTJk/Xzzz9XGv/22281YMAAxcbGVlrxVPe5zczM1NChQ1VYWHhH887JyZHD4VBUVNQd\n7X+3aLTBaNmypdq1a6e5c+fq4MGDun79eqXx8vJyzZ07VwcOHND69eu1fv167d692zM+adIkJSYm\nKisrS7t27dK2bdtUVlbmGb98+bL279+vcePGafbs2bJcgb9+/Xp99dVX2rhxozIyMpSfn6+PP/7Y\n535LlixRZGSksrKyNH36dKWkpGjHjh0aNGiQ6bnYs2ePoqOjNWrUqEqPcfjw4SooKNBvv/2m0tJS\n7d27V7GxsZKkvLw8derUSXPmzFF0dLQmTpyo/Px80/mqo1u3btq2bZv279+vsLAwpaSkVBo/fPiw\ndu3apfT0dM2fP1/nz5+XdOfPbYUrV67ozJkzVYrMv23ZskVPPfWU/Pz87mj/u0WjDYbD4dBHH30k\nf39/JScnq3///lqxYoVnPC4uTpGRkQoMDNSjjz6q6OhonTx50jMeEhKiDh06qGPHjgoKClJwcLAu\nX77sGZ88ebLuu+8+TZgwQefPn9fZs2d9zmnz5s1KTk5WmzZt1Lx5c02cOFEZGRk+95s9e7ZWrlyp\n+Ph4HTx4UCEhIcrKytLXX3/tc98nn3xSmZmZys7OVnJyslJTU/XTTz9Jklq3bq1evXpp8ODBioyM\nlMPh8KzCSkpKdPjwYQ0YMEDffPONBgwYoNTUVJ/nq66pU6eqVatW8vf3V2JiovLy8iqNjx8/Xs2b\nN1d4eLh69+6t7OxsSXf+3FZITEzUjz/+qPbt21d5zsXFxcrKytLo0aOrvO/dplF/hhESEqIlS5bI\n7XbrwIEDmjlzpnr27KnY2FgdPXpU77//vk6dOqWbN2/q2rVrlZbcDodD/v7+8vf3lyQFBATo5s2b\nnvFWrVp5fh8cHKyLFy/6XLJfuHBBr7zyihyOfzrudrvVunVrr/scOXJEL7zwgq5du6aAgABFRkbq\n+vXrGjZsmNLT09WvXz+v+3fu3Nnzc0JCgjZv3qzs7Gx16tRJK1euVF5ennJycnT//ffrjTfe0IIF\nCzRv3jw1bdpULVq00NixYyVJzz33nNLS0lRUVFTltz5WLpdLaWlp2rlzpy5fviy32y232y2Xy+X5\nc3jooYc827dq1Up//vmnpDt7bmvK9u3b1bVrV4WGhtbJ+WpTow5GBYfDoX79+ikqKkr5+fmKjY1V\namqqJk2apHXr1ikwMFDTp0/3+bbi3+MXL15U+/btdfPmTRUXF3sCIkmBgYFyu9237P/II49o4cKF\n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\n", |
| "text/plain": [ |
| "\u003cFigure size 600x400 with 1 Axes\u003e" |
| ] |
| }, |
| "metadata": { |
| "tags": [] |
| }, |
| "output_type": "display_data" |
| } |
| ], |
| "source": [ |
| "#@title Load MNIST dataset, setup training and evaluation\n", |
| "\n", |
| "# Keras datasets don't provide metadata.\n", |
| "NUM_CLASSES = 10\n", |
| "NUM_ROWS, NUM_COLS = 28, 28\n", |
| "\n", |
| "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()\n", |
| "\n", |
| "# Reshape into grayscale images:\n", |
| "x_train = np.reshape(x_train, (-1, NUM_ROWS, NUM_COLS, 1))\n", |
| "x_test = np.reshape(x_test, (-1, NUM_ROWS, NUM_COLS, 1))\n", |
| "\n", |
| "# Rescale uint8 pixel values into floats:\n", |
| "x_train = x_train / 255\n", |
| "x_test = x_test / 255\n", |
| "\n", |
| "# Explicitly cast to float32 because numpy defaults to double precision and\n", |
| "# IREE uses single precision:\n", |
| "x_train = x_train.astype(np.float32)\n", |
| "x_test = x_test.astype(np.float32)\n", |
| "\n", |
| "print(\"Sample image from the dataset:\")\n", |
| "sample_index = np.random.randint(x_train.shape[0])\n", |
| "plt.imshow(x_train[sample_index].reshape(NUM_ROWS, NUM_COLS), cmap=\"gray\")\n", |
| "plt.title(f\"Sample #{sample_index}, label: {y_train[sample_index]}\")\n", |
| "plt.axis(\"off\")\n", |
| "plt.tight_layout()" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 18, |
| "metadata": { |
| "cellView": "both", |
| "executionInfo": { |
| "elapsed": 39, |
| "status": "ok", |
| "timestamp": 1601949599280, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "tHq96SIJcNfx" |
| }, |
| "outputs": [], |
| "source": [ |
| "#@title Define a DNN model using tf.keras API\n", |
| "\n", |
| "def simple_dnn(num_classes):\n", |
| " \"\"\"Creates a simple multi-layer perceptron model.\"\"\"\n", |
| "\n", |
| " model = tf.keras.models.Sequential()\n", |
| " # Flatten to a 1d array (e.g. 28x28x1 -\u003e 784).\n", |
| " model.add(tf.keras.layers.Flatten())\n", |
| " # Fully-connected neural layer with 128 neurons, RELU activation.\n", |
| " model.add(tf.keras.layers.Dense(128, activation=\"relu\"))\n", |
| " # Fully-connected neural layer returning probability scores for each class.\n", |
| " model.add(tf.keras.layers.Dense(num_classes, activation=\"softmax\"))\n", |
| " return model" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 19, |
| "metadata": { |
| "cellView": "both", |
| "executionInfo": { |
| "elapsed": 256, |
| "status": "ok", |
| "timestamp": 1601949599540, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "43BH_9YcsGs8" |
| }, |
| "outputs": [], |
| "source": [ |
| "#@markdown ### Training Parameters\n", |
| "\n", |
| "batch_size = 32 #@param { type: \"slider\", min: 10, max: 400 }\n", |
| "num_epochs = 8 #@param { type: \"slider\", min: 1, max: 20 }" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 20, |
| "metadata": { |
| "cellView": "both", |
| "executionInfo": { |
| "elapsed": 87216, |
| "status": "ok", |
| "timestamp": 1601949686760, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "7Gdxh7qWcPSO", |
| "outputId": "e81040b3-bd89-44e7-e306-6bd07e775ee1" |
| }, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "Epoch 1/8\n", |
| "1688/1688 [==============================] - 11s 6ms/step - loss: 1.0898 - accuracy: 0.7126 - val_loss: 0.3258 - val_accuracy: 0.9160\n", |
| "Epoch 2/8\n", |
| "1688/1688 [==============================] - 10s 6ms/step - loss: 0.3779 - accuracy: 0.8967 - val_loss: 0.2643 - val_accuracy: 0.9245\n", |
| "Epoch 3/8\n", |
| "1688/1688 [==============================] - 12s 7ms/step - loss: 0.3127 - accuracy: 0.9120 - val_loss: 0.2379 - val_accuracy: 0.9325\n", |
| "Epoch 4/8\n", |
| "1688/1688 [==============================] - 11s 7ms/step - loss: 0.2817 - accuracy: 0.9203 - val_loss: 0.2160 - val_accuracy: 0.9375\n", |
| "Epoch 5/8\n", |
| "1688/1688 [==============================] - 10s 6ms/step - loss: 0.2612 - accuracy: 0.9264 - val_loss: 0.1988 - val_accuracy: 0.9452\n", |
| "Epoch 6/8\n", |
| "1688/1688 [==============================] - 12s 7ms/step - loss: 0.2411 - accuracy: 0.9316 - val_loss: 0.1853 - val_accuracy: 0.9487\n", |
| "Epoch 7/8\n", |
| "1688/1688 [==============================] - 10s 6ms/step - loss: 0.2234 - accuracy: 0.9380 - val_loss: 0.1739 - val_accuracy: 0.9525\n", |
| "Epoch 8/8\n", |
| "1688/1688 [==============================] - 10s 6ms/step - loss: 0.2089 - accuracy: 0.9414 - val_loss: 0.1637 - val_accuracy: 0.9567\n" |
| ] |
| }, |
| { |
| "data": { |
| "text/plain": [ |
| "\u003ctensorflow.python.keras.callbacks.History at 0x7f36690b9ac8\u003e" |
| ] |
| }, |
| "execution_count": 20, |
| "metadata": { |
| "tags": [] |
| }, |
| "output_type": "execute_result" |
| } |
| ], |
| "source": [ |
| "#@title Train the Keras model\n", |
| "\n", |
| "tf_model = simple_dnn(NUM_CLASSES)\n", |
| "# Stateful optimizers like Adam create variable incompatible with compilation as\n", |
| "# currently implemented.\n", |
| "tf_model.compile(\n", |
| " optimizer=\"sgd\", loss=\"sparse_categorical_crossentropy\", metrics=\"accuracy\")\n", |
| "tf_model.fit(x_train, y_train, batch_size, num_epochs, validation_split=0.1)" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "metadata": { |
| "id": "nZdVUd_dgTtc" |
| }, |
| "source": [ |
| "# Compile and Execute MNIST Model using IREE" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 21, |
| "metadata": { |
| "executionInfo": { |
| "elapsed": 857, |
| "status": "ok", |
| "timestamp": 1601949746337, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "DmespEaFcSEL" |
| }, |
| "outputs": [], |
| "source": [ |
| "#@title Wrap the model in a tf.Module with IREE-compatible settings and convert to MLIR.\n", |
| "\n", |
| "# Since the model was written in sequential style, explicitly wrap in a module.\n", |
| "inference_module = tf.Module()\n", |
| "inference_module.model = tf_model\n", |
| "\n", |
| "# Hack: Convert to static shape. Won't be necessary once dynamic shapes are in.\n", |
| "input_shape = list(tf_model.inputs[0].shape)\n", |
| "input_shape[0] = 1 # Make fixed (batch=1)\n", |
| "\n", |
| "# Produce a concrete function to compile.\n", |
| "inference_module.predict = tf.function(input_signature=[\n", |
| " tf.TensorSpec(input_shape, tf_model.inputs[0].dtype)\n", |
| "])(lambda x: tf_model.call(x, training=False))\n", |
| "\n", |
| "# Only try to compile the function we care about:\n", |
| "exported_names = [\"predict\"]" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 22, |
| "metadata": { |
| "executionInfo": { |
| "elapsed": 37, |
| "status": "ok", |
| "timestamp": 1601949746512, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "G7v-2EbjyggO" |
| }, |
| "outputs": [], |
| "source": [ |
| "#@markdown ### Backend Configuration\n", |
| "\n", |
| "backend_choice = \"iree_vmla (CPU)\" #@param [ \"iree_vmla (CPU)\", \"iree_llvmjit (CPU)\", \"iree_vulkan (GPU/SwiftShader)\" ]\n", |
| "backend_choice = backend_choice.split(\" \")[0]\n", |
| "backend = tf_utils.BackendInfo(backend_choice)" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 23, |
| "metadata": { |
| "executionInfo": { |
| "elapsed": 3314, |
| "status": "ok", |
| "timestamp": 1601949752845, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "IDHI7h3khJr9", |
| "outputId": "9e3b76b1-85ec-4e37-aa10-df6ed9e65ae5" |
| }, |
| "outputs": [ |
| { |
| "name": "stderr", |
| "output_type": "stream", |
| "text": [ |
| "Created IREE driver vmla: \u003ciree.bindings.python.pyiree.rt.binding.HalDriver object at 0x7f35f9c46458\u003e\n", |
| "SystemContext driver=\u003ciree.bindings.python.pyiree.rt.binding.HalDriver object at 0x7f35f9c46458\u003e\n" |
| ] |
| } |
| ], |
| "source": [ |
| "#@title Compile the mhlo MLIR to an IREE backend and prepare a context to execute it\n", |
| "\n", |
| "iree_module = tf_utils.IreeCompiledModule.create_from_instance(\n", |
| " inference_module, backend, exported_names)" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 24, |
| "metadata": { |
| "colab": { |
| "height": 299 |
| }, |
| "executionInfo": { |
| "elapsed": 1131, |
| "status": "ok", |
| "timestamp": 1601949755542, |
| "user": { |
| "displayName": "", |
| "photoUrl": "", |
| "userId": "" |
| }, |
| "user_tz": 420 |
| }, |
| "id": "S2FYao92Xd6r", |
| "outputId": "d844dcac-949f-4caa-f78d-778af7d64203" |
| }, |
| "outputs": [ |
| { |
| "data": { |
| "image/png": "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\nRK5CYII=\n", |
| "text/plain": [ |
| "\u003cFigure size 1200x400 with 2 Axes\u003e" |
| ] |
| }, |
| "metadata": { |
| "tags": [] |
| }, |
| "output_type": "display_data" |
| } |
| ], |
| "source": [ |
| "#@title Execute the compiled module and compare the results with TensorFlow\n", |
| "\n", |
| "# Invoke the 'predict' function with a single image as an argument\n", |
| "iree_prediction = iree_module.predict(x_train[sample_index][None, :])[0]\n", |
| "tf_prediction = tf_model.predict(x_train[sample_index][None, :])[0]\n", |
| "error = tf_prediction - iree_prediction\n", |
| "\n", |
| "fig, axs = plt.subplots(1, 2)\n", |
| "fig.set_figwidth(12)\n", |
| "\n", |
| "ax = axs[0]\n", |
| "ax.plot(iree_prediction, linewidth=2, label=backend.backend_name)\n", |
| "ax.plot(tf_prediction, linewidth=2, label=\"tf\")\n", |
| "\n", |
| "ax.set_title(\"Predictions\")\n", |
| "ax.set_ylabel(\"Softmax 'Probability'\")\n", |
| "ax.set_xlabel(\"Digit\")\n", |
| "ax.set_ylim(0, 1)\n", |
| "ax.set_xlim(0, 9)\n", |
| "ax.legend(frameon=True)\n", |
| "\n", |
| "\n", |
| "ax = axs[1]\n", |
| "ax.plot(error)\n", |
| "\n", |
| "ax.set_title(\"Error\")\n", |
| "ax.set_ylabel(\"Numerical between TF and IREE\")\n", |
| "ax.set_xlabel(\"Digit\")\n", |
| "ylim = 1.25 * np.max(np.abs(error))\n", |
| "ax.set_ylim(-ylim, ylim)\n", |
| "ax.set_xlim(0, 9)\n", |
| "\n", |
| "fig.tight_layout()" |
| ] |
| } |
| ], |
| "metadata": { |
| "colab": { |
| "collapsed_sections": [], |
| "last_runtime": { |
| "build_target": "", |
| "kind": "local" |
| }, |
| "name": "mnist_tensorflow.ipynb", |
| "provenance": [] |
| }, |
| "kernelspec": { |
| "display_name": "Python 3", |
| "name": "python3" |
| } |
| }, |
| "nbformat": 4, |
| "nbformat_minor": 0 |
| } |