diff --git a/example_travelling_salesman.ipynb b/example_travelling_salesman.ipynb new file mode 100644 index 0000000..179b94d --- /dev/null +++ b/example_travelling_salesman.ipynb @@ -0,0 +1,26535 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "95ba26f7" + }, + "source": [ + "# The Travelling Coffee Drinker - Genetic Algorithm\n", + "\n", + "Solving a travelling salesman problem for United Kingdom Starbucks Cafés" + ], + "id": "95ba26f7" + }, + { + "cell_type": "markdown", + "source": [ + "## 1. Load and transform data\n", + "\n", + "The data comes from Kaggle, which is accessed using the API wrapper.\n", + "\n", + "The transformation needed is just to filter only GB Starbucks restaurants with a valid lon/lat pair." + ], + "metadata": { + "id": "sEtmfvLsvMC2" + }, + "id": "sEtmfvLsvMC2" + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_HBlGrIyYa7G", + "outputId": "cf89fc50-e566-4fe2-f54c-178b9d6e1acd" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n", + "Requirement already satisfied: pygad==2.17 in /usr/local/lib/python3.7/dist-packages (2.17.0)\n", + "Requirement already satisfied: numpy in /usr/local/lib/python3.7/dist-packages (from pygad==2.17) (1.21.6)\n", + "Requirement already satisfied: matplotlib in /usr/local/lib/python3.7/dist-packages (from pygad==2.17) (3.2.2)\n", + "Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib->pygad==2.17) (2.8.2)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib->pygad==2.17) (1.4.4)\n", + "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.7/dist-packages (from matplotlib->pygad==2.17) (3.0.9)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.7/dist-packages (from matplotlib->pygad==2.17) (0.11.0)\n", + "Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from kiwisolver>=1.0.1->matplotlib->pygad==2.17) (4.1.1)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.7/dist-packages (from python-dateutil>=2.1->matplotlib->pygad==2.17) (1.15.0)\n" + ] + } + ], + "source": [ + "!pip install pygad==2.17" + ], + "id": "_HBlGrIyYa7G" + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": { + "id": "buoFAtjz2duB" + }, + "outputs": [], + "source": [ + "!pip install -q kaggle" + ], + "id": "buoFAtjz2duB" + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 375, + "resources": { + "http://localhost:8080/nbextensions/google.colab/files.js": { + "data": "Ly8gQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQwovLwovLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgovLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKLy8KLy8gICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKLy8KLy8gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQovLyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAovLyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KLy8gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAovLyBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KCi8qKgogKiBAZmlsZW92ZXJ2aWV3IEhlbHBlcnMgZm9yIGdvb2dsZS5jb2xhYiBQeXRob24gbW9kdWxlLgogKi8KKGZ1bmN0aW9uKHNjb3BlKSB7CmZ1bmN0aW9uIHNwYW4odGV4dCwgc3R5bGVBdHRyaWJ1dGVzID0ge30pIHsKICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpOwogIGVsZW1lbnQudGV4dENvbnRlbnQgPSB0ZXh0OwogIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0eWxlQXR0cmlidXRlcykpIHsKICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IHN0eWxlQXR0cmlidXRlc1trZXldOwogIH0KICByZXR1cm4gZWxlbWVudDsKfQoKLy8gTWF4IG51bWJlciBvZiBieXRlcyB3aGljaCB3aWxsIGJlIHVwbG9hZGVkIGF0IGEgdGltZS4KY29uc3QgTUFYX1BBWUxPQURfU0laRSA9IDEwMCAqIDEwMjQ7CgpmdW5jdGlvbiBfdXBsb2FkRmlsZXMoaW5wdXRJZCwgb3V0cHV0SWQpIHsKICBjb25zdCBzdGVwcyA9IHVwbG9hZEZpbGVzU3RlcChpbnB1dElkLCBvdXRwdXRJZCk7CiAgY29uc3Qgb3V0cHV0RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG91dHB1dElkKTsKICAvLyBDYWNoZSBzdGVwcyBvbiB0aGUgb3V0cHV0RWxlbWVudCB0byBtYWtlIGl0IGF2YWlsYWJsZSBmb3IgdGhlIG5leHQgY2FsbAogIC8vIHRvIHVwbG9hZEZpbGVzQ29udGludWUgZnJvbSBQeXRob24uCiAgb3V0cHV0RWxlbWVudC5zdGVwcyA9IHN0ZXBzOwoKICByZXR1cm4gX3VwbG9hZEZpbGVzQ29udGludWUob3V0cHV0SWQpOwp9CgovLyBUaGlzIGlzIHJvdWdobHkgYW4gYXN5bmMgZ2VuZXJhdG9yIChub3Qgc3VwcG9ydGVkIGluIHRoZSBicm93c2VyIHlldCksCi8vIHdoZXJlIHRoZXJlIGFyZSBtdWx0aXBsZSBhc3luY2hyb25vdXMgc3RlcHMgYW5kIHRoZSBQeXRob24gc2lkZSBpcyBnb2luZwovLyB0byBwb2xsIGZvciBjb21wbGV0aW9uIG9mIGVhY2ggc3RlcC4KLy8gVGhpcyB1c2VzIGEgUHJvbWlzZSB0byBibG9jayB0aGUgcHl0aG9uIHNpZGUgb24gY29tcGxldGlvbiBvZiBlYWNoIHN0ZXAsCi8vIHRoZW4gcGFzc2VzIHRoZSByZXN1bHQgb2YgdGhlIHByZXZpb3VzIHN0ZXAgYXMgdGhlIGlucHV0IHRvIHRoZSBuZXh0IHN0ZXAuCmZ1bmN0aW9uIF91cGxvYWRGaWxlc0NvbnRpbnVlKG91dHB1dElkKSB7CiAgY29uc3Qgb3V0cHV0RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKG91dHB1dElkKTsKICBjb25zdCBzdGVwcyA9IG91dHB1dEVsZW1lbnQuc3RlcHM7CgogIGNvbnN0IG5leHQgPSBzdGVwcy5uZXh0KG91dHB1dEVsZW1lbnQubGFzdFByb21pc2VWYWx1ZSk7CiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXh0LnZhbHVlLnByb21pc2UpLnRoZW4oKHZhbHVlKSA9PiB7CiAgICAvLyBDYWNoZSB0aGUgbGFzdCBwcm9taXNlIHZhbHVlIHRvIG1ha2UgaXQgYXZhaWxhYmxlIHRvIHRoZSBuZXh0CiAgICAvLyBzdGVwIG9mIHRoZSBnZW5lcmF0b3IuCiAgICBvdXRwdXRFbGVtZW50Lmxhc3RQcm9taXNlVmFsdWUgPSB2YWx1ZTsKICAgIHJldHVybiBuZXh0LnZhbHVlLnJlc3BvbnNlOwogIH0pOwp9CgovKioKICogR2VuZXJhdG9yIGZ1bmN0aW9uIHdoaWNoIGlzIGNhbGxlZCBiZXR3ZWVuIGVhY2ggYXN5bmMgc3RlcCBvZiB0aGUgdXBsb2FkCiAqIHByb2Nlc3MuCiAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dElkIEVsZW1lbnQgSUQgb2YgdGhlIGlucHV0IGZpbGUgcGlja2VyIGVsZW1lbnQuCiAqIEBwYXJhbSB7c3RyaW5nfSBvdXRwdXRJZCBFbGVtZW50IElEIG9mIHRoZSBvdXRwdXQgZGlzcGxheS4KICogQHJldHVybiB7IUl0ZXJhYmxlPCFPYmplY3Q+fSBJdGVyYWJsZSBvZiBuZXh0IHN0ZXBzLgogKi8KZnVuY3Rpb24qIHVwbG9hZEZpbGVzU3RlcChpbnB1dElkLCBvdXRwdXRJZCkgewogIGNvbnN0IGlucHV0RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlucHV0SWQpOwogIGlucHV0RWxlbWVudC5kaXNhYmxlZCA9IGZhbHNlOwoKICBjb25zdCBvdXRwdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob3V0cHV0SWQpOwogIG91dHB1dEVsZW1lbnQuaW5uZXJIVE1MID0gJyc7CgogIGNvbnN0IHBpY2tlZFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gewogICAgaW5wdXRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIChlKSA9PiB7CiAgICAgIHJlc29sdmUoZS50YXJnZXQuZmlsZXMpOwogICAgfSk7CiAgfSk7CgogIGNvbnN0IGNhbmNlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpOwogIGlucHV0RWxlbWVudC5wYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKGNhbmNlbCk7CiAgY2FuY2VsLnRleHRDb250ZW50ID0gJ0NhbmNlbCB1cGxvYWQnOwogIGNvbnN0IGNhbmNlbFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gewogICAgY2FuY2VsLm9uY2xpY2sgPSAoKSA9PiB7CiAgICAgIHJlc29sdmUobnVsbCk7CiAgICB9OwogIH0pOwoKICAvLyBXYWl0IGZvciB0aGUgdXNlciB0byBwaWNrIHRoZSBmaWxlcy4KICBjb25zdCBmaWxlcyA9IHlpZWxkIHsKICAgIHByb21pc2U6IFByb21pc2UucmFjZShbcGlja2VkUHJvbWlzZSwgY2FuY2VsUHJvbWlzZV0pLAogICAgcmVzcG9uc2U6IHsKICAgICAgYWN0aW9uOiAnc3RhcnRpbmcnLAogICAgfQogIH07CgogIGNhbmNlbC5yZW1vdmUoKTsKCiAgLy8gRGlzYWJsZSB0aGUgaW5wdXQgZWxlbWVudCBzaW5jZSBmdXJ0aGVyIHBpY2tzIGFyZSBub3QgYWxsb3dlZC4KICBpbnB1dEVsZW1lbnQuZGlzYWJsZWQgPSB0cnVlOwoKICBpZiAoIWZpbGVzKSB7CiAgICByZXR1cm4gewogICAgICByZXNwb25zZTogewogICAgICAgIGFjdGlvbjogJ2NvbXBsZXRlJywKICAgICAgfQogICAgfTsKICB9CgogIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykgewogICAgY29uc3QgbGkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpOwogICAgbGkuYXBwZW5kKHNwYW4oZmlsZS5uYW1lLCB7Zm9udFdlaWdodDogJ2JvbGQnfSkpOwogICAgbGkuYXBwZW5kKHNwYW4oCiAgICAgICAgYCgke2ZpbGUudHlwZSB8fCAnbi9hJ30pIC0gJHtmaWxlLnNpemV9IGJ5dGVzLCBgICsKICAgICAgICBgbGFzdCBtb2RpZmllZDogJHsKICAgICAgICAgICAgZmlsZS5sYXN0TW9kaWZpZWREYXRlID8gZmlsZS5sYXN0TW9kaWZpZWREYXRlLnRvTG9jYWxlRGF0ZVN0cmluZygpIDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ24vYSd9IC0gYCkpOwogICAgY29uc3QgcGVyY2VudCA9IHNwYW4oJzAlIGRvbmUnKTsKICAgIGxpLmFwcGVuZENoaWxkKHBlcmNlbnQpOwoKICAgIG91dHB1dEVsZW1lbnQuYXBwZW5kQ2hpbGQobGkpOwoKICAgIGNvbnN0IGZpbGVEYXRhUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7CiAgICAgIHJlYWRlci5vbmxvYWQgPSAoZSkgPT4gewogICAgICAgIHJlc29sdmUoZS50YXJnZXQucmVzdWx0KTsKICAgICAgfTsKICAgICAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGZpbGUpOwogICAgfSk7CiAgICAvLyBXYWl0IGZvciB0aGUgZGF0YSB0byBiZSByZWFkeS4KICAgIGxldCBmaWxlRGF0YSA9IHlpZWxkIHsKICAgICAgcHJvbWlzZTogZmlsZURhdGFQcm9taXNlLAogICAgICByZXNwb25zZTogewogICAgICAgIGFjdGlvbjogJ2NvbnRpbnVlJywKICAgICAgfQogICAgfTsKCiAgICAvLyBVc2UgYSBjaHVua2VkIHNlbmRpbmcgdG8gYXZvaWQgbWVzc2FnZSBzaXplIGxpbWl0cy4gU2VlIGIvNjIxMTU2NjAuCiAgICBsZXQgcG9zaXRpb24gPSAwOwogICAgZG8gewogICAgICBjb25zdCBsZW5ndGggPSBNYXRoLm1pbihmaWxlRGF0YS5ieXRlTGVuZ3RoIC0gcG9zaXRpb24sIE1BWF9QQVlMT0FEX1NJWkUpOwogICAgICBjb25zdCBjaHVuayA9IG5ldyBVaW50OEFycmF5KGZpbGVEYXRhLCBwb3NpdGlvbiwgbGVuZ3RoKTsKICAgICAgcG9zaXRpb24gKz0gbGVuZ3RoOwoKICAgICAgY29uc3QgYmFzZTY0ID0gYnRvYShTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGNodW5rKSk7CiAgICAgIHlpZWxkIHsKICAgICAgICByZXNwb25zZTogewogICAgICAgICAgYWN0aW9uOiAnYXBwZW5kJywKICAgICAgICAgIGZpbGU6IGZpbGUubmFtZSwKICAgICAgICAgIGRhdGE6IGJhc2U2NCwKICAgICAgICB9LAogICAgICB9OwoKICAgICAgbGV0IHBlcmNlbnREb25lID0gZmlsZURhdGEuYnl0ZUxlbmd0aCA9PT0gMCA/CiAgICAgICAgICAxMDAgOgogICAgICAgICAgTWF0aC5yb3VuZCgocG9zaXRpb24gLyBmaWxlRGF0YS5ieXRlTGVuZ3RoKSAqIDEwMCk7CiAgICAgIHBlcmNlbnQudGV4dENvbnRlbnQgPSBgJHtwZXJjZW50RG9uZX0lIGRvbmVgOwoKICAgIH0gd2hpbGUgKHBvc2l0aW9uIDwgZmlsZURhdGEuYnl0ZUxlbmd0aCk7CiAgfQoKICAvLyBBbGwgZG9uZS4KICB5aWVsZCB7CiAgICByZXNwb25zZTogewogICAgICBhY3Rpb246ICdjb21wbGV0ZScsCiAgICB9CiAgfTsKfQoKc2NvcGUuZ29vZ2xlID0gc2NvcGUuZ29vZ2xlIHx8IHt9OwpzY29wZS5nb29nbGUuY29sYWIgPSBzY29wZS5nb29nbGUuY29sYWIgfHwge307CnNjb3BlLmdvb2dsZS5jb2xhYi5fZmlsZXMgPSB7CiAgX3VwbG9hZEZpbGVzLAogIF91cGxvYWRGaWxlc0NvbnRpbnVlLAp9Owp9KShzZWxmKTsK", + "headers": [ + [ + "content-type", + "application/javascript" + ] + ], + "ok": true, + "status": 200, + "status_text": "" + } + } + }, + "id": "WYcYq9YV2gi9", + "outputId": "aef25ebb-cdaf-449f-c280-05f0faf1157f" + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + " \n", + " \n", + " Upload widget is only available when the cell has been executed in the\n", + " current browser session. Please rerun this cell to enable.\n", + " \n", + " " + ] + }, + "metadata": {} + }, + { + "output_type": "error", + "ename": "KeyboardInterrupt", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mgoogle\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcolab\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mfiles\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mfiles\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mupload\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/google/colab/files.py\u001b[0m in \u001b[0;36mupload\u001b[0;34m()\u001b[0m\n\u001b[1;32m 39\u001b[0m \"\"\"\n\u001b[1;32m 40\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 41\u001b[0;31m \u001b[0muploaded_files\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_upload_files\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmultiple\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 42\u001b[0m \u001b[0;31m# Mapping from original filename to filename as saved locally.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 43\u001b[0m \u001b[0mlocal_filenames\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/google/colab/files.py\u001b[0m in \u001b[0;36m_upload_files\u001b[0;34m(multiple)\u001b[0m\n\u001b[1;32m 116\u001b[0m result = _output.eval_js(\n\u001b[1;32m 117\u001b[0m 'google.colab._files._uploadFiles(\"{input_id}\", \"{output_id}\")'.format(\n\u001b[0;32m--> 118\u001b[0;31m input_id=input_id, output_id=output_id))\n\u001b[0m\u001b[1;32m 119\u001b[0m \u001b[0mfiles\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_collections\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdefaultdict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbytes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 120\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/google/colab/output/_js.py\u001b[0m in \u001b[0;36meval_js\u001b[0;34m(script, ignore_result, timeout_sec)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mignore_result\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[0;32mreturn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 40\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_message\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_reply_from_input\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrequest_id\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtimeout_sec\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 41\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 42\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.7/dist-packages/google/colab/_message.py\u001b[0m in \u001b[0;36mread_reply_from_input\u001b[0;34m(message_id, timeout_sec)\u001b[0m\n\u001b[1;32m 95\u001b[0m \u001b[0mreply\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_read_next_input_message\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 96\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mreply\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0m_NOT_READY\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreply\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdict\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 97\u001b[0;31m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0.025\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 98\u001b[0m \u001b[0;32mcontinue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 99\u001b[0m if (reply.get('type') == 'colab_reply' and\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "from google.colab import files\n", + "files.upload() # upload a Kaggle JSON file to make request for data " + ], + "id": "WYcYq9YV2gi9" + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "TBtskqtn29H3" + }, + "outputs": [], + "source": [ + "!mkdir kaggle " + ], + "id": "TBtskqtn29H3" + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "oK1Z1Yr12tEv" + }, + "outputs": [], + "source": [ + "!cp kaggle.json ~/.kaggle/\n", + "!chmod 600 ~/.kaggle/kaggle.json" + ], + "id": "oK1Z1Yr12tEv" + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "8U2rpJ1j191n" + }, + "outputs": [], + "source": [ + "!kaggle datasets download kukuroo3/starbucks-locations-worldwide-2021-version -p /content/sample_data/ --unzip" + ], + "id": "8U2rpJ1j191n" + }, + { + "cell_type": "code", + "execution_count": 165, + "metadata": { + "id": "sTkY5cLb3age", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "a064aedc-8e4d-4712-d223-e35db3d1d7ae" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "Index(['Unnamed: 0', 'storeNumber', 'countryCode', 'ownershipTypeCode',\n", + " 'schedule', 'slug', 'latitude', 'longitude', 'streetAddressLine1',\n", + " 'streetAddressLine2', 'streetAddressLine3', 'city',\n", + " 'countrySubdivisionCode', 'postalCode', 'currentTimeOffset',\n", + " 'windowsTimeZoneId', 'olsonTimeZoneId'],\n", + " dtype='object')" + ] + }, + "metadata": {}, + "execution_count": 165 + } + ], + "source": [ + "import pandas as pd \n", + "\n", + "# read in data and check column names \n", + "data = pd.read_csv('/content/sample_data/startbucks.csv')\n", + "data.columns" + ], + "id": "sTkY5cLb3age" + }, + { + "cell_type": "code", + "execution_count": 166, + "metadata": { + "id": "SImMYnfe3n_w", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "4ee033d9-9f66-489a-c470-b45a1a3b0ac0" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "0" + ] + }, + "metadata": {}, + "execution_count": 166 + } + ], + "source": [ + "df = data[data['countryCode']=='GB']\n", + "df.reset_index(inplace=True)\n", + "\n", + "# check for invalid lon/lat pairs\n", + "len(df.dropna(subset=['latitude', 'longitude'])) - len(df)" + ], + "id": "SImMYnfe3n_w" + }, + { + "cell_type": "markdown", + "source": [ + "## 2. Exploratory analysis\n", + "\n", + "Find the distribution of cafés across the United Kingdom. \n", + "\n", + "How are restaurants distributed across towns?\n", + "What does a geospatial representation of the data look like?" + ], + "metadata": { + "id": "ovWqqNFIvydy" + }, + "id": "ovWqqNFIvydy" + }, + { + "cell_type": "markdown", + "source": [ + "### 2.1 Distribution of cafés by town" + ], + "metadata": { + "id": "SokLPN9j2fn1" + }, + "id": "SokLPN9j2fn1" + }, + { + "cell_type": "code", + "source": [ + "import plotly.express as px\n", + "vis = df.groupby('city').storeNumber.count().reset_index()\n", + "px.bar(vis, x='city', y='storeNumber', template='seaborn')" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "HGOBgqnX2lIo", + "outputId": "0f19d0f2-0063-458a-cd02-987e30b3d9cf" + }, + "id": "HGOBgqnX2lIo", + "execution_count": 167, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "
\n", + "
\n", + "\n", + "" + ] + }, + "metadata": {} + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "\n", + "### 2.2 Map of cafés in the UK" + ], + "metadata": { + "id": "z9a3NPSM2lb4" + }, + "id": "z9a3NPSM2lb4" + }, + { + "cell_type": "code", + "source": [ + "import folium" + ], + "metadata": { + "id": "dAq1AQyfwN_l" + }, + "id": "dAq1AQyfwN_l", + "execution_count": 168, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "map = folium.Map(location=[51.509685, -0.118092], zoom_start=6, tiles=\"stamentoner\")" + ], + "metadata": { + "id": "V9b0_8g_xM5K" + }, + "id": "V9b0_8g_xM5K", + "execution_count": 169, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "for _, r in df.iterrows():\n", + " folium.Marker(\n", + " [r['latitude'], r['longitude']], popup=f'{r[\"storeNumber\"]}'\n", + " ).add_to(map)" + ], + "metadata": { + "id": "ZiprKw6ExhQR" + }, + "id": "ZiprKw6ExhQR", + "execution_count": 170, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "map" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "iVnEBooHc0ze", + "outputId": "b6ee729b-739f-4db5-975f-12a6a2c82246" + }, + "id": "iVnEBooHc0ze", + "execution_count": 171, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "
Make this Notebook Trusted to load map: File -> Trust Notebook
" + ] + }, + "metadata": {}, + "execution_count": 171 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## 3. Testing the distance methodology\n", + "\n", + "To assess how good each solution is there needs to be a measure of fitness. For the purpose of this example the distance 'as the crow flies' is used without taking into account actual road distances however this could be explored in future." + ], + "metadata": { + "id": "1sg-1A4Ih1L4" + }, + "id": "1sg-1A4Ih1L4" + }, + { + "cell_type": "code", + "source": [ + "from geopy.distance import geodesic" + ], + "metadata": { + "id": "IbG9XRkLh0Aj" + }, + "id": "IbG9XRkLh0Aj", + "execution_count": 173, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "The tested origin is the first Starbucks in the data and the destination is the second Starbucks in the dataset." + ], + "metadata": { + "id": "zgmh6b1l3liN" + }, + "id": "zgmh6b1l3liN" + }, + { + "cell_type": "code", + "execution_count": 174, + "metadata": { + "id": "TyoeO2I-4bGq" + }, + "outputs": [], + "source": [ + "origin = (df['latitude'][0], df['longitude'][0])\n", + "dest = (df['latitude'][100], df['longitude'][100])" + ], + "id": "TyoeO2I-4bGq" + }, + { + "cell_type": "markdown", + "source": [ + "The distance between the two points as the crow flies in kilometres is given below." + ], + "metadata": { + "id": "VUr7ZAzw3srI" + }, + "id": "VUr7ZAzw3srI" + }, + { + "cell_type": "code", + "execution_count": 175, + "metadata": { + "id": "zXo1I-5Q4Lwn", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "4672edf2-9142-4276-ab6a-2b35b65b8b3d" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "81.63683980420957" + ] + }, + "metadata": {}, + "execution_count": 175 + } + ], + "source": [ + "geodesic(origin, dest).kilometers" + ], + "id": "zXo1I-5Q4Lwn" + }, + { + "cell_type": "markdown", + "source": [ + "## 4. Preparing data structures\n", + "\n", + "The data structures needed for testing solutions are the \"genes\" or store options to select from named *genes*\n", + "\n", + "A lookup to access these genes known as *stores* \n", + "\n", + "A *check_range* which is used to check that every option is given in a solution (a key criteria in the TSP).\n" + ], + "metadata": { + "id": "GeRIsd5G378L" + }, + "id": "GeRIsd5G378L" + }, + { + "cell_type": "code", + "source": [ + "test = df.head(10)\n", + "genes = {store_num:[lat, lon] for store_num, lat, lon in zip(test['storeNumber'], test['latitude'], test['longitude'])}\n", + "stores = list(genes.keys())\n", + "check_range = [i for i in range(0, 10)]" + ], + "metadata": { + "id": "rkKStcn4iIrN" + }, + "id": "rkKStcn4iIrN", + "execution_count": 176, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "## 5. Defining functions \n", + "\n", + "The algorithm requires a set of functions to be pre-defined as the out of the box genetic algorithm does not support a TSP.\n", + "\n", + " 1. build_population: builds a population of chromosomes to test with proper restrictions applied\n", + " 2. fitness_func: Used to test a solution to see how well it performs, in this case the fitness_func will be assessed based on the distance as the crow flies between each successive point\n", + " 3. pmx_crossover: performs the crossover of a parent and child with proper Partially Matched Crossover (PMX) logic\n", + " 4. crossover_func: applies the crossover\n", + " 5. on_crossover: applies the mutation after crossover\n", + " 6. on_generation: used to print the progress and results at each generation" + ], + "metadata": { + "id": "5mKC2lKO4tRY" + }, + "id": "5mKC2lKO4tRY" + }, + { + "cell_type": "code", + "source": [ + "import random\n", + "import numpy as np\n", + "from geopy.distance import geodesic" + ], + "metadata": { + "id": "15-IiuRNljOC" + }, + "id": "15-IiuRNljOC", + "execution_count": 177, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "Assess the quality or fitness of a solution so that only the fittest are selected for the next generation and to breed." + ], + "metadata": { + "id": "BhCEN9165in3" + }, + "id": "BhCEN9165in3" + }, + { + "cell_type": "code", + "source": [ + "def build_population(size, chromosome_size):\n", + " population = []\n", + " for i in range(size):\n", + " home_city = 0\n", + " added = {home_city:'Added'}\n", + " chromosome = [home_city]\n", + "\n", + " while len(chromosome) < chromosome_size:\n", + " proposed_gene = random.randint(0, chromosome_size-1)\n", + " if added.get(proposed_gene) is None:\n", + " chromosome.append(proposed_gene)\n", + " added.update({proposed_gene:'Added'})\n", + " else:\n", + " pass\n", + "\n", + " chromosome.append(home_city)\n", + "\n", + " population.append(chromosome)\n", + "\n", + " return np.array(population)" + ], + "metadata": { + "id": "BLz2sU2n78Ui" + }, + "id": "BLz2sU2n78Ui", + "execution_count": 178, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "population = build_population(100, 10)\n", + "population.shape" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vs8CrTNV9iqe", + "outputId": "4178c652-2593-44e9-ca0d-1829f11c6d5e" + }, + "id": "vs8CrTNV9iqe", + "execution_count": 179, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(100, 11)" + ] + }, + "metadata": {}, + "execution_count": 179 + } + ] + }, + { + "cell_type": "code", + "source": [ + "def fitness_func(solution, solution_idx):\n", + " # loop through the length of the chromosome finding the distance between each\n", + " # gene added \n", + "\n", + " # to increment\n", + " total_dist = 0\n", + "\n", + " for gene in range(0, len(solution)):\n", + "\n", + " # get the lon lat of the two points\n", + " a = genes.get(stores[solution[gene]])\n", + " \n", + " try:\n", + " b = genes.get(stores[solution[gene + 1]])\n", + "\n", + " # find the distance (crow flies)\n", + " dist = geodesic(a, b).kilometers\n", + "\n", + " except IndexError:\n", + " dist = 0\n", + "\n", + " total_dist += dist\n", + "\n", + " # to optimise this value in the positive direction the inverse of dist is used\n", + " fitness = 1 / total_dist\n", + "\n", + " return fitness " + ], + "metadata": { + "id": "5u-5msoj-84i" + }, + "id": "5u-5msoj-84i", + "execution_count": 180, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def pmx_crossover(parent1, parent2, sequence_start, sequence_end):\n", + " # initialise a child\n", + " child = np.zeros(parent1.shape[0])\n", + "\n", + " # get the genes for parent one that are passed on to child one\n", + " parent1_to_child1_genes = parent1[sequence_start:sequence_end]\n", + "\n", + " # get the position of genes for each respective combination\n", + " parent1_to_child1 = np.isin(parent1,parent1_to_child1_genes).nonzero()[0]\n", + "\n", + " for gene in parent1_to_child1:\n", + " child[gene] = parent1[gene]\n", + "\n", + " # gene of parent 2 not in the child\n", + " genes_not_in_child = parent2[np.isin(parent2, parent1_to_child1_genes, invert=True).nonzero()[0]]\n", + " \n", + " # if the gene is not already\n", + " if genes_not_in_child.shape[0] >= 1:\n", + " for gene in genes_not_in_child:\n", + " if gene >= 1:\n", + " lookup = gene\n", + " not_in_sequence = True\n", + "\n", + " while not_in_sequence:\n", + " position_in_parent2 = np.where(parent2==lookup)[0][0]\n", + "\n", + " if position_in_parent2 in range(sequence_start, sequence_end):\n", + " lookup = parent1[position_in_parent2]\n", + "\n", + " else:\n", + " child[position_in_parent2] = gene\n", + " not_in_sequence = False\n", + "\n", + " return child" + ], + "metadata": { + "id": "OpbfyShQes_q" + }, + "id": "OpbfyShQes_q", + "execution_count": 181, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def crossover_func(parents, offspring_size, ga_instance):\n", + " offspring = []\n", + " idx = 0\n", + " while len(offspring) != offspring_size[0]:\n", + "\n", + " # locate the parents\n", + " parent1 = parents[idx % parents.shape[0], :].copy()\n", + " parent2 = parents[(idx + 1) % parents.shape[0], :].copy()\n", + "\n", + " # find gene sequence in parent 1 \n", + " sequence_start = random.randint(1, parent1.shape[0]-4)\n", + " sequence_end = random.randint(sequence_start, parent1.shape[0]-1)\n", + "\n", + " # perform crossover\n", + " child1 = pmx_crossover(parent1, parent2, sequence_start, sequence_end)\n", + " child2 = pmx_crossover(parent2, parent1, sequence_start, sequence_end) \n", + "\n", + " offspring.append(child1)\n", + " offspring.append(child2)\n", + "\n", + "\n", + " idx += 1\n", + "\n", + " return np.array(offspring)" + ], + "metadata": { + "id": "shgFWqH2NinO" + }, + "id": "shgFWqH2NinO", + "execution_count": 182, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "The mutation function chosen is inversion as it does not invalidate the solution." + ], + "metadata": { + "id": "bCjaaeofA7Bg" + }, + "id": "bCjaaeofA7Bg" + }, + { + "cell_type": "code", + "source": [ + "def mutation_func(offspring, ga_instance):\n", + "\n", + " for chromosome_idx in range(offspring.shape[0]):\n", + " # define a sequence of genes to reverse\n", + " sequence_start = random.randint(1, offspring[chromosome_idx].shape[0] - 2)\n", + " sequence_end = random.randint(sequence_start, offspring[chromosome_idx].shape[0] - 1)\n", + " \n", + " genes = offspring[chromosome_idx, sequence_start:sequence_end]\n", + "\n", + " # start at the start of the sequence assigning the reverse sequence back to the chromosome\n", + " index = 0\n", + " if len(genes) > 0:\n", + " for gene in range(sequence_start, sequence_end):\n", + "\n", + " offspring[chromosome_idx, gene] = genes[index]\n", + "\n", + " index += 1\n", + "\n", + " return offspring" + ], + "metadata": { + "id": "0kMm7J1WAsvH" + }, + "id": "0kMm7J1WAsvH", + "execution_count": 183, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "Used in the genetic algorithm flow to apply the custom mutation after crossover" + ], + "metadata": { + "id": "HTeKwuPl5vVt" + }, + "id": "HTeKwuPl5vVt" + }, + { + "cell_type": "code", + "source": [ + "def on_crossover(ga_instance, offspring_crossover):\n", + " # apply mutation to ensure uniqueness \n", + " offspring_mutation = mutation_func(offspring_crossover, ga_instance)\n", + "\n", + " # save the new offspring set as the parents of the next generation\n", + " ga_instance.last_generation_offspring_mutation = offspring_mutation" + ], + "metadata": { + "id": "ucwYe4rgwLQC" + }, + "id": "ucwYe4rgwLQC", + "execution_count": 184, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "Added for debugging and assessing progress by generation at runtime" + ], + "metadata": { + "id": "Xf7rgtuO532X" + }, + "id": "Xf7rgtuO532X" + }, + { + "cell_type": "code", + "source": [ + "def on_generation(ga):\n", + " print(\"Generation\", ga.generations_completed)\n", + " print(ga.population)" + ], + "metadata": { + "id": "eqRwVsSBMf_B" + }, + "id": "eqRwVsSBMf_B", + "execution_count": 185, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "## 6. Executing the algorithm\n", + "\n", + "The genetic algorithm is set up as instance and at initialisation several parameters are given. \n", + "\n", + "The algorithm then runs to find the best solution for a set number of generations." + ], + "metadata": { + "id": "C9AtXoqx58x0" + }, + "id": "C9AtXoqx58x0" + }, + { + "cell_type": "code", + "source": [ + "import pygad" + ], + "metadata": { + "id": "BrJVLZlBW07R" + }, + "id": "BrJVLZlBW07R", + "execution_count": 186, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "### 6.1 Example Initialising the algorithm\n", + "\n", + "The algorithm is initialised below.\n", + "\n", + "Notable parameters include:\n", + " - The use of gene space to limit the possible genes chosen to just be those in the TSP range\n", + " - Mutations being turned off temporarily\n", + " - Implementation of custom on_ functions \n", + " - Allow duplication of genes parameter set to false to ensure any newly introduced chromosomes/chromosomes created as population is initialised have no duplicate genes" + ], + "metadata": { + "id": "6ni9VkQv6TJR" + }, + "id": "6ni9VkQv6TJR" + }, + { + "cell_type": "code", + "source": [ + "ga_instance = pygad.GA(num_generations=100,\n", + " num_parents_mating=40,\n", + " fitness_func=fitness_func,\n", + " sol_per_pop=200,\n", + " initial_population=population,\n", + " gene_space=range(0, 10),\n", + " gene_type=int,\n", + " mutation_type=mutation_func,\n", + " on_generation=on_generation,\n", + " crossover_type=crossover_func, \n", + " keep_parents=6,\n", + " mutation_probability=0.4)" + ], + "metadata": { + "id": "FfFdncf-G3Mr" + }, + "id": "FfFdncf-G3Mr", + "execution_count": 187, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "### 6.2 Running the algorithm \n", + "\n", + "The genetic algorithm is run with a simple function call" + ], + "metadata": { + "id": "sfqme_5461A4" + }, + "id": "sfqme_5461A4" + }, + { + "cell_type": "code", + "source": [ + "ga_instance.run()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "g-3CjxWYZh3H", + "outputId": "dc1fbda5-6b22-4245-9b99-e22b0e41684f" + }, + "id": "g-3CjxWYZh3H", + "execution_count": 188, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Generation 1\n", + "[[0 3 2 ... 4 5 0]\n", + " [0 3 6 ... 1 2 0]\n", + " [0 8 3 ... 6 1 0]\n", + " ...\n", + " [0 9 5 ... 7 4 0]\n", + " [0 2 7 ... 8 6 0]\n", + " [0 3 5 ... 6 8 0]]\n", + "Generation 2\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 9 ... 8 3 0]\n", + " [0 3 2 ... 4 5 0]\n", + " ...\n", + " [0 3 6 ... 1 2 0]\n", + " [0 3 6 ... 1 2 0]\n", + " [0 3 1 ... 6 2 0]]\n", + "Generation 3\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 9 ... 8 3 0]\n", + " [0 3 2 ... 4 5 0]\n", + " [0 9 2 ... 8 3 0]]\n", + "Generation 4\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 5\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 6\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 7\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 8\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 9\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 10\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 11\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 12\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 13\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 14\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 15\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 16\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 17\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 18\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 19\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 20\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 21\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 22\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 23\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 24\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 25\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 26\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 27\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 28\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 29\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 30\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 31\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 32\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 33\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 34\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 35\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 36\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 37\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 38\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 39\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 40\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 41\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 42\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 43\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 44\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 45\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 46\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 47\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 48\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 49\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 50\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 51\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 52\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 53\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 54\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 55\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 56\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 57\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 58\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 59\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 60\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 61\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 62\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 63\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 64\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 65\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 66\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 67\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 68\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 69\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 70\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 71\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 72\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 73\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 74\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 75\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 76\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 77\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 78\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 79\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 80\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 81\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 82\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 83\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 84\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 85\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 86\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 87\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 88\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 89\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 90\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 91\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 92\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 93\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 94\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 95\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 96\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 97\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 98\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 99\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n", + "Generation 100\n", + "[[0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " ...\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]\n", + " [0 1 2 ... 8 6 0]]\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## 7. Assessing results \n", + "\n", + "The result solution can be checked and analysed using the ga_instance itself" + ], + "metadata": { + "id": "woJTWlOrYLwl" + }, + "id": "woJTWlOrYLwl" + }, + { + "cell_type": "code", + "source": [ + "solution, solution_fitness, solution_idx = ga_instance.best_solution()" + ], + "metadata": { + "id": "BZxvMCZ-aFtJ" + }, + "id": "BZxvMCZ-aFtJ", + "execution_count": 189, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "solution, solution_fitness, solution_idx = ga_instance.best_solution()\n", + "print(f'Generation of best solution: {ga_instance.best_solution_generation}')\n", + "print(\"Fitness value of the best solution = {solution_fitness}\".format(solution_fitness=solution_fitness))\n", + "print(\"Index of the best solution : {solution_idx}\".format(solution_idx=solution_idx))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "IOTGnna-QXsB", + "outputId": "30d494d6-e88e-4061-a453-9a44a9409176" + }, + "id": "IOTGnna-QXsB", + "execution_count": 190, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Generation of best solution: 1\n", + "Fitness value of the best solution = 0.010681933534441102\n", + "Index of the best solution : 0\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "if ga_instance.best_solution_generation != -1:\n", + " print(\"Best fitness value reached after {best_solution_generation} generations.\".format(best_solution_generation=ga_instance.best_solution_generation))\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WsjTUVloQhez", + "outputId": "fdd41ccb-9ead-49d7-d180-ccc1dd2d13f9" + }, + "id": "WsjTUVloQhez", + "execution_count": 191, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Best fitness value reached after 1 generations.\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 7.1 Verifying a solution\n", + "\n", + "For a solution to be valid it needs to have:\n", + " - A maximum gene value that matches the total number of stores \n", + " - A minimum gene value of 0 \n", + " - Each gene must be unique" + ], + "metadata": { + "id": "FiLlGlILYWhw" + }, + "id": "FiLlGlILYWhw" + }, + { + "cell_type": "code", + "source": [ + "def verify_solution(solution, max_gene):\n", + " if min(solution) != 0:\n", + " print('Failed values below 0')\n", + "\n", + " if max(solution) != max_gene:\n", + " print('Failed values less than or above max possible value')\n", + "\n", + " if len(set(solution)) - len(solution) != -1:\n", + " print(len(set(solution)) - len(solution))\n", + " print('Failed solution does not contain unique values')" + ], + "metadata": { + "id": "vEhveNG4VQBF" + }, + "id": "vEhveNG4VQBF", + "execution_count": 192, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "verify_solution(solution, 9)" + ], + "metadata": { + "id": "IQg1sULKYRZe" + }, + "id": "IQg1sULKYRZe", + "execution_count": 193, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "solution" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VqjdGMGnYqz-", + "outputId": "152c6b82-4787-4776-b9e9-bc3ceb1ccec1" + }, + "id": "VqjdGMGnYqz-", + "execution_count": 194, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([0, 1, 2, 3, 4, 5, 7, 9, 8, 6, 0])" + ] + }, + "metadata": {}, + "execution_count": 194 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 7.2 Interpreting the result \n", + "\n", + "The result sequence can be used to access latitude and longitude for each store in the solution." + ], + "metadata": { + "id": "5ixLDfvtY3cI" + }, + "id": "5ixLDfvtY3cI" + }, + { + "cell_type": "code", + "source": [ + "points = [genes.get(stores[id]) + [stores[id]] for id in solution]\n", + "points[:5]" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tv-AjzcoQwGc", + "outputId": "a5187ac8-ea84-4dc9-992c-60cfa4dcab8a" + }, + "id": "tv-AjzcoQwGc", + "execution_count": 195, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[[51.483556, -1.557143, '9155-152277'],\n", + " [51.482387, -1.555109, '22194-218828'],\n", + " [51.481264, -1.556526, '18362-190424'],\n", + " [51.481177, -1.557422, '9136-152279'],\n", + " [51.562617, -1.798111, '47832-260044']]" + ] + }, + "metadata": {}, + "execution_count": 195 + } + ] + }, + { + "cell_type": "code", + "source": [ + "import folium \n", + "\n", + "map = folium.Map(location=[51.509685, -0.118092], zoom_start=6, tiles=\"stamentoner\")\n", + "\n", + "for point in range(0, len(points)):\n", + " folium.Marker(\n", + " [points[point][0], points[point][1]], popup=f'{points[point][2]}'\n", + " ).add_to(map)\n", + "\n", + " try:\n", + " folium.PolyLine([(points[point][0], points[point][1]), \n", + " (points[point+1][0], points[point+1][1])],\n", + " color='red',\n", + " weight=5,\n", + " opacity=0.8).add_to(map)\n", + "\n", + " except IndexError:\n", + " pass\n", + " " + ], + "metadata": { + "id": "Tq0hTc5cstWX" + }, + "id": "Tq0hTc5cstWX", + "execution_count": 196, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "map" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 0 + }, + "id": "ebkOuHleuGU1", + "outputId": "801c457d-49d9-452d-9c4b-872aef5816d4" + }, + "id": "ebkOuHleuGU1", + "execution_count": 197, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "
Make this Notebook Trusted to load map: File -> Trust Notebook
" + ] + }, + "metadata": {}, + "execution_count": 197 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "The map shows the shortest path that has been found. So that the travelling coffee drinker can maximise the time on coffee and minimise the time on travelling.\n", + "\n", + "Now the algorithm can be scaled up for the whole of the UK, or tailored to just one town. An example of the solution scaled to the UK is given below." + ], + "metadata": { + "id": "5Sz8ykeEYDS3" + }, + "id": "5Sz8ykeEYDS3" + }, + { + "cell_type": "markdown", + "source": [ + "## 8. Scaling up the solution\n", + "\n", + "This is where the fun begins!" + ], + "metadata": { + "id": "gscT4SjxZ9h4" + }, + "id": "gscT4SjxZ9h4" + }, + { + "cell_type": "code", + "source": [ + "df = df[df['city'] == 'London']\n", + "genes = {store_num:[lat, lon] for store_num, lat, lon in zip(df['storeNumber'], df['latitude'], df['longitude'])}\n", + "stores = list(genes.keys())\n", + "len(stores)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "yYY3-gP1aFkH", + "outputId": "907e2a7c-3292-4409-e83e-4db372f09a45" + }, + "id": "yYY3-gP1aFkH", + "execution_count": 157, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "165" + ] + }, + "metadata": {}, + "execution_count": 157 + } + ] + }, + { + "cell_type": "code", + "source": [ + "population = build_population(200, 165)\n", + "len(population[0])" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "oykOz7l4KhJE", + "outputId": "fe7fdabc-a909-40c4-e69a-daba8169b07c" + }, + "id": "oykOz7l4KhJE", + "execution_count": 155, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "166" + ] + }, + "metadata": {}, + "execution_count": 155 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### 8.1 Building the final algorithm\n", + "\n", + "The code to build the algorithm has to be re-run with the above data structures altered." + ], + "metadata": { + "id": "ioy8EGjEbnBJ" + }, + "id": "ioy8EGjEbnBJ" + }, + { + "cell_type": "code", + "source": [ + "def fitness_func(solution, solution_idx):\n", + " # loop through the length of the chromosome finding the distance between each\n", + " # gene added \n", + "\n", + " # to increment\n", + " total_dist = 0\n", + "\n", + " for gene in range(0, len(solution)):\n", + "\n", + " # get the lon lat of the two points\n", + " a = genes.get(stores[solution[gene]])\n", + " \n", + " try:\n", + " b = genes.get(stores[solution[gene + 1]])\n", + "\n", + " # find the distance (crow flies)\n", + " dist = geodesic(a, b).kilometers\n", + "\n", + " except IndexError:\n", + " dist = 0\n", + "\n", + " total_dist += dist\n", + "\n", + " # to optimise this value in the positive direction the inverse of dist is used\n", + " fitness = 1 / total_dist\n", + "\n", + " return fitness " + ], + "metadata": { + "id": "uBfcikkma5hP" + }, + "id": "uBfcikkma5hP", + "execution_count": 108, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def pmx_crossover(parent1, parent2, sequence_start, sequence_end):\n", + " # initialise a child\n", + " child = np.zeros(parent1.shape[0])\n", + "\n", + " # get the genes for parent one that are passed on to child one\n", + " parent1_to_child1_genes = parent1[sequence_start:sequence_end]\n", + "\n", + " # get the position of genes for each respective combination\n", + " parent1_to_child1 = np.isin(parent1,parent1_to_child1_genes).nonzero()[0]\n", + "\n", + " for gene in parent1_to_child1:\n", + " child[gene] = parent1[gene]\n", + "\n", + " # gene of parent 2 not in the child\n", + " genes_not_in_child = parent2[np.isin(parent2, parent1_to_child1_genes, invert=True).nonzero()[0]]\n", + " \n", + " if genes_not_in_child.shape[0] >= 1:\n", + " for gene in genes_not_in_child:\n", + " if gene >= 1:\n", + " lookup = gene\n", + " not_in_sequence = True\n", + "\n", + " while not_in_sequence:\n", + " position_in_parent2 = np.where(parent2==lookup)[0][0]\n", + "\n", + " if position_in_parent2 in range(sequence_start, sequence_end):\n", + " lookup = parent1[position_in_parent2]\n", + "\n", + " else:\n", + " child[position_in_parent2] = gene\n", + " not_in_sequence = False\n", + "\n", + " return child" + ], + "metadata": { + "id": "FuOkiStta7Pz" + }, + "id": "FuOkiStta7Pz", + "execution_count": 109, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def crossover_func(parents, offspring_size, ga_instance):\n", + " offspring = []\n", + " idx = 0\n", + " while len(offspring) != offspring_size[0]:\n", + "\n", + " # locate the parents\n", + " parent1 = parents[idx % parents.shape[0], :].copy()\n", + " parent2 = parents[(idx + 1) % parents.shape[0], :].copy()\n", + "\n", + " # find gene sequence in parent 1 \n", + " sequence_start = random.randint(1, parent1.shape[0]-4)\n", + " sequence_end = random.randint(sequence_start, parent1.shape[0]-1)\n", + "\n", + " # perform crossover\n", + " child1 = pmx_crossover(parent1, parent2, sequence_start, sequence_end)\n", + " child2 = pmx_crossover(parent2, parent1, sequence_start, sequence_end)\n", + " \n", + "\n", + " offspring.append(child1)\n", + " offspring.append(child2)\n", + "\n", + " idx += 1\n", + "\n", + " return np.array(offspring)" + ], + "metadata": { + "id": "O10ZgScUa_bj" + }, + "id": "O10ZgScUa_bj", + "execution_count": 130, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def mutation_func(offspring, ga_instance):\n", + "\n", + " for chromosome_idx in range(offspring.shape[0]):\n", + " # define a sequence of genes to reverse\n", + " sequence_start = random.randint(1, offspring[chromosome_idx].shape[0] - 2)\n", + " sequence_end = random.randint(sequence_start, offspring[chromosome_idx].shape[0] - 1)\n", + " \n", + " genes = offspring[chromosome_idx, sequence_start:sequence_end]\n", + "\n", + " # start at the start of the sequence assigning the reverse sequence back to the chromosome\n", + " index = 0\n", + " if len(genes) > 0:\n", + " for gene in range(sequence_start, sequence_end):\n", + "\n", + " offspring[chromosome_idx, gene] = genes[index]\n", + "\n", + " index += 1\n", + "\n", + " return offspring" + ], + "metadata": { + "id": "mLLY7Ub4K_Y5" + }, + "id": "mLLY7Ub4K_Y5", + "execution_count": 144, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def on_crossover(ga_instance, offspring_crossover):\n", + " # apply mutation to ensure uniqueness \n", + " offspring_mutation = mutation_func(offspring_crossover, ga_instance)\n", + "\n", + " # save the new offspring set as the parents of the next generation\n", + " ga_instance.last_generation_offspring_mutation = offspring_mutation" + ], + "metadata": { + "id": "QLtP6in4LFSw" + }, + "id": "QLtP6in4LFSw", + "execution_count": 126, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "def on_generation(ga):\n", + " print(\"Generation\", ga.generations_completed)\n", + " print(ga.population)" + ], + "metadata": { + "id": "SnR2LaDJLGRj" + }, + "id": "SnR2LaDJLGRj", + "execution_count": 127, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "ga_instance = pygad.GA(num_generations=100,\n", + " num_parents_mating=40,\n", + " fitness_func=fitness_func,\n", + " sol_per_pop=200,\n", + " initial_population=population,\n", + " gene_space=range(0, 165),\n", + " gene_type=int,\n", + " mutation_type=mutation_func,\n", + " on_generation=on_generation,\n", + " crossover_type=crossover_func, \n", + " keep_parents=6,\n", + " mutation_probability=0.4)" + ], + "metadata": { + "id": "j2J5jlh9bDxR" + }, + "id": "j2J5jlh9bDxR", + "execution_count": 145, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "ga_instance.run()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "lhW7JkMAbS6E", + "outputId": "c6130b2a-1e6b-4b7d-c2d6-f891b178fef9" + }, + "id": "lhW7JkMAbS6E", + "execution_count": 146, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Generation 1\n", + "[[ 0 1 111 ... 127 108 0]\n", + " [ 0 62 141 ... 26 161 0]\n", + " [ 0 137 155 ... 158 3 0]\n", + " ...\n", + " [ 0 142 162 ... 2 159 0]\n", + " [ 0 161 159 ... 112 66 0]\n", + " [ 0 152 108 ... 72 58 0]]\n", + "Generation 2\n", + "[[ 0 1 111 ... 127 108 0]\n", + " [ 0 1 111 ... 127 108 0]\n", + " [ 0 62 141 ... 26 161 0]\n", + " ...\n", + " [ 0 137 155 ... 135 76 0]\n", + " [ 0 137 155 ... 158 3 0]\n", + " [ 0 96 40 ... 135 5 0]]\n", + "Generation 3\n", + "[[ 0 1 145 ... 26 94 0]\n", + " [ 0 1 111 ... 127 108 0]\n", + " [ 0 1 111 ... 127 108 0]\n", + " ...\n", + " [ 0 89 155 ... 158 32 0]\n", + " [ 0 1 110 ... 127 94 0]\n", + " [ 0 96 40 ... 64 90 0]]\n", + "Generation 4\n", + "[[ 0 1 56 ... 26 81 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 110 ... 127 94 0]\n", + " ...\n", + " [ 0 1 111 ... 127 108 0]\n", + " [ 0 1 145 ... 26 22 0]\n", + " [ 0 1 77 ... 127 142 0]]\n", + "Generation 5\n", + "[[ 0 1 111 ... 127 108 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 56 ... 127 81 0]\n", + " ...\n", + " [ 0 1 60 ... 127 118 0]\n", + " [ 0 1 154 ... 127 7 0]\n", + " [ 0 1 164 ... 127 94 0]]\n", + "Generation 6\n", + "[[ 0 1 56 ... 26 81 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " ...\n", + " [ 0 1 93 ... 127 108 0]\n", + " [ 0 1 30 ... 127 108 0]\n", + " [ 0 1 111 ... 127 108 0]]\n", + "Generation 7\n", + "[[ 0 1 56 ... 127 81 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 94 0]\n", + " ...\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 56 ... 26 81 0]\n", + " [ 0 1 56 ... 127 81 0]]\n", + "Generation 8\n", + "[[ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 26 108 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " ...\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 56 ... 127 94 0]]\n", + "Generation 9\n", + "[[ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " ...\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 33 ... 26 94 0]\n", + " [ 0 1 110 ... 127 108 0]]\n", + "Generation 10\n", + "[[ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 26 108 0]]\n", + "Generation 11\n", + "[[ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 81 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " ...\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 81 0]]\n", + "Generation 12\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " ...\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 81 0]\n", + " [ 0 1 164 ... 127 81 0]]\n", + "Generation 13\n", + "[[ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 81 0]\n", + " ...\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 81 0]]\n", + "Generation 14\n", + "[[ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 81 0]\n", + " ...\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 108 0]]\n", + "Generation 15\n", + "[[ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 81 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " ...\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 94 0]\n", + " [ 0 1 164 ... 127 108 0]]\n", + "Generation 16\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 81 0]\n", + " ...\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 94 0]]\n", + "Generation 17\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 81 0]\n", + " [ 0 1 164 ... 127 108 0]\n", + " [ 0 1 164 ... 127 108 0]]\n", + "Generation 18\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 108 0]]\n", + "Generation 19\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 20\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 21\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 22\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 23\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 24\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 25\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 26\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 27\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 28\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 29\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 30\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 31\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 32\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 33\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 34\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 35\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 36\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 37\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 38\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 39\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 40\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 41\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 42\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 43\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 44\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 45\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 46\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 47\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 48\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 49\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 50\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 51\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 52\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 53\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 54\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 55\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 56\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 57\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 58\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 59\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 60\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 61\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 62\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 63\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 64\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 65\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 66\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 67\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 68\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 69\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 70\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 71\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 72\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 73\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 74\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 75\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 76\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 77\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 78\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 79\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 80\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 81\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 82\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 83\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 84\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 85\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 86\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 87\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 88\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 89\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 90\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 91\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 92\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 93\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 94\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 95\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 96\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 97\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 98\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 99\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n", + "Generation 100\n", + "[[ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " ...\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]\n", + " [ 0 1 164 ... 127 119 0]]\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## 8.2 Evaluating the final algorithm \n", + "\n", + "The overall solution can now be assessed." + ], + "metadata": { + "id": "KJY5PcFabWdL" + }, + "id": "KJY5PcFabWdL" + }, + { + "cell_type": "code", + "source": [ + "solution, solution_fitness, solution_idx = ga_instance.best_solution()\n", + "print(f'Generation of best solution: {ga_instance.best_solution_generation}')\n", + "print(\"Fitness value of the best solution = {solution_fitness}\".format(solution_fitness=solution_fitness))\n", + "print(\"Index of the best solution : {solution_idx}\".format(solution_idx=solution_idx))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "yxGGtFfE3j_1", + "outputId": "d5b68eaa-167f-47c8-aadd-10ecb3eb080c" + }, + "id": "yxGGtFfE3j_1", + "execution_count": 147, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Generation of best solution: 25\n", + "Fitness value of the best solution = 0.0010087414431375688\n", + "Index of the best solution : 0\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "verify_solution(solution, len(stores))\n", + "solution" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "NKvGE63abjmU", + "outputId": "75249196-afeb-4ee6-9b96-9674ea8493c9" + }, + "id": "NKvGE63abjmU", + "execution_count": 148, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Failed values less than or above max possible value\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([ 0, 1, 164, 19, 77, 23, 10, 9, 154, 158, 157, 26, 22,\n", + " 92, 42, 137, 75, 143, 149, 12, 100, 85, 86, 124, 128, 135,\n", + " 147, 54, 24, 3, 58, 123, 153, 51, 29, 69, 20, 110, 59,\n", + " 95, 113, 115, 121, 91, 36, 64, 65, 32, 53, 35, 105, 52,\n", + " 21, 34, 133, 109, 47, 71, 98, 106, 131, 89, 108, 56, 152,\n", + " 150, 7, 38, 43, 94, 8, 132, 155, 4, 16, 84, 90, 27,\n", + " 2, 144, 151, 39, 45, 159, 125, 79, 156, 40, 6, 74, 139,\n", + " 141, 145, 76, 104, 50, 37, 129, 130, 72, 142, 97, 25, 93,\n", + " 134, 126, 138, 140, 148, 120, 96, 28, 160, 116, 18, 112, 31,\n", + " 41, 55, 63, 73, 122, 162, 161, 163, 66, 107, 17, 87, 103,\n", + " 80, 81, 88, 83, 82, 14, 33, 11, 46, 61, 60, 136, 146,\n", + " 15, 70, 44, 48, 67, 78, 111, 13, 62, 30, 118, 114, 99,\n", + " 102, 5, 68, 49, 57, 101, 117, 127, 119, 0])" + ] + }, + "metadata": {}, + "execution_count": 148 + } + ] + }, + { + "cell_type": "code", + "source": [ + "points = [genes.get(stores[id]) + [stores[id]] for id in solution]\n", + "points[:5]" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "G8bOm7PGcPx_", + "outputId": "f78d25f6-3679-489b-c533-2971ac389941" + }, + "id": "G8bOm7PGcPx_", + "execution_count": 150, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[[51.877854, -0.376379, '12851-253386'],\n", + " [51.877854, -0.376289, '7187-253385'],\n", + " [51.655847, -0.277039, '47771-259784'],\n", + " [51.51402, -0.13925, '12021-10341'],\n", + " [51.54541, -0.16269, '12158-22023']]" + ] + }, + "metadata": {}, + "execution_count": 150 + } + ] + }, + { + "cell_type": "code", + "source": [ + "map = folium.Map(location=[51.509685, -0.118092], zoom_start=6, tiles=\"stamentoner\")\n", + "\n", + "for point in range(0, len(points)):\n", + " folium.Marker(\n", + " [points[point][0], points[point][1]], popup=f'{points[point][2]}'\n", + " ).add_to(map)\n", + "\n", + " try:\n", + " folium.PolyLine([(points[point][0], points[point][1]), \n", + " (points[point+1][0], points[point+1][1])],\n", + " color='red',\n", + " weight=5,\n", + " opacity=0.8).add_to(map)\n", + "\n", + " except IndexError:\n", + " pass" + ], + "metadata": { + "id": "_KtJJkkvcY-E" + }, + "id": "_KtJJkkvcY-E", + "execution_count": 151, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "map" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 531 + }, + "id": "PMH_yECHcaH8", + "outputId": "708aca8b-c6c9-4008-cc54-e14bb37b180f" + }, + "id": "PMH_yECHcaH8", + "execution_count": 152, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "
Make this Notebook Trusted to load map: File -> Trust Notebook
" + ] + }, + "metadata": {}, + "execution_count": 152 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## 10. Total result \n", + "\n", + "The total resulting distance around London after optimising the solution is:" + ], + "metadata": { + "id": "4ek_Es2DcbXU" + }, + "id": "4ek_Es2DcbXU" + }, + { + "cell_type": "code", + "source": [ + "def distance(solution):\n", + " # loop through the length of the chromosome finding the distance between each\n", + " # gene added \n", + "\n", + " # to increment\n", + " total_dist = 0\n", + "\n", + " for gene in range(0, len(solution)):\n", + "\n", + " # get the lon lat of the two points\n", + " a = genes.get(stores[solution[gene]])\n", + " \n", + " try:\n", + " b = genes.get(stores[solution[gene + 1]])\n", + "\n", + " # find the distance (crow flies)\n", + " dist = geodesic(a, b).kilometers\n", + "\n", + " except IndexError:\n", + " dist = 0\n", + "\n", + " \n", + " total_dist += dist\n", + "\n", + " # to optimise this value in the positive direction the inverse of dist is used\n", + "\n", + " return total_dist " + ], + "metadata": { + "id": "SiCFxx7WcwxV" + }, + "id": "SiCFxx7WcwxV", + "execution_count": 153, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "distance(solution)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nds6G5tmnJ8K", + "outputId": "fe4ccfc6-a5c0-4e53-c0cd-acfe62bd6052" + }, + "id": "nds6G5tmnJ8K", + "execution_count": 154, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "991.3343075204886" + ] + }, + "metadata": {}, + "execution_count": 154 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "Which is not too bad for 975 cups of joe. 🥤" + ], + "metadata": { + "id": "bukLealWcxOz" + }, + "id": "bukLealWcxOz" + } + ], + "metadata": { + "colab": { + "provenance": [], + "collapsed_sections": [ + "sEtmfvLsvMC2", + "1sg-1A4Ih1L4" + ], + "toc_visible": true + }, + "gpuClass": "standard", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.7.3" + }, + "accelerator": "GPU" + }, + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file