{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import os.path\n", "import scipy.linalg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Genetic Algorithm \n", "\n", "In this notebook, we write all the code we need to run a genetic algorithm. We build it from the bottom up.\n", "\n", "### Support Code\n", "\n", "We begin by copy-pasting the code from last lecture into this notebook\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# GASettings class\n", "class GASettings:\n", " def __init__( self, numParents = 10, numChildren = 50 ):\n", " self.numParents = numParents;\n", " self.numChildren = numChildren;\n", " self.numGenerations = 5;\n", " self.selection = 'truncation'; \n", " self.mutation = 0.05; # std of normal distribution computed as mutation*value\n", " self.eliteCount = 1;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Copy-Paste select_pool" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Select pool\n", "def select_pool( G, Gcost, settings ):\n", " \"\"\" Select a breding pool from the previous generation.\n", " G is numChildren x numParameters\n", " Gcost is numChildren long and is sorted in ascending order.\n", " Returns (P,Pcost)\n", " where \n", " P is numParents x numParameters\n", " Pcost is numParents long.\n", " \"\"\"\n", " if Gcost.size != settings.numChildren:\n", " print(\"problem\")\n", " return\n", " P = np.zeros( (settings.numParents,G.shape[1]) )\n", " Pcost = np.zeros( (settings.numParents,) )\n", " Pidxs = []\n", " if settings.selection == 'truncation':\n", " for i in range(settings.numParents):\n", " idx = np.random.choice(settings.numParents)\n", " P[i,:] = G[idx,:]\n", " Pcost[i] = Gcost[idx]\n", "\n", " elif settings.selection == 'uniform':\n", " for i in range(settings.numParents):\n", " idx = np.random.choice(G.shape[0])\n", " P[i,:] = G[idx,:]\n", " Pcost[i] = Gcost[idx]\n", "\n", " else:\n", " print( \"Unknown selection operator: \", settings.selection )\n", " return (P, Pcost)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Copy-Paste generateIndividual" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# generateIndividual\n", "def generateIndividual(cost_fcn, lb,ub):\n", " '''\n", " Generate a viable individual (i.e one whos cost function is finite)\n", " and return it and its cost.\n", " If 1000 tries fails to yield an individual, then the paramets and an infinite cost\n", " are returned.\n", " Each individual is generated by randomly chosing each entry params[i] \n", " so that lb[i] <= params[i] <= ub[i]\n", " Input:\n", " cost_fcn: handle to the cost function (which should take a candidate as input)\n", " lb: lower bounds for parameters (array of length NP)\n", " ub: upper bounds for parameters (array of length NP)\n", " Returns:\n", " (params, cost)\n", " where params is the same shape as the lower bounds\n", " and cost is the cost for that set of parameters\n", " '''\n", " params = np.zeros(lb.shape);\n", " cost = np.inf;\n", " for i in range( 1000 ):\n", " params = lb + np.multiply( np.random.random(lb.size), ub-lb);\n", " cost = cost_fcn(params);\n", " if np.isfinite(cost):\n", " return (params, cost);\n", " return (params, np.inf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test with a simple cost function\n", "\n", "This cost function simply captures the distance of an individual in 7-dimensional space to a particular point (1,5,2.5,2,4,3,0). We used this same function in the last lecture." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def pattern_cost_function( params ):\n", " return scipy.linalg.norm( params-np.array([1,5,2.5,2,4,3,0]) )\n", "\n", "lam = 1000 # number of individuals in generation\n", "mu = 100 # number of individuals in breeding pool\n", "NP = 7 # num of parameters per individual\n", "settings = GASettings(numParents=mu, numChildren=lam)\n", "\n", "lb = np.array([0,4,1,1,2,2,0])\n", "ub = np.array([5,6,3,2,4,4,2])\n", "G = np.zeros( (lam,NP) )\n", "Gcost = np.zeros( (lam,))\n", "for i in range(lam):\n", " (G[i,:], Gcost[i]) = generateIndividual(pattern_cost_function,lb,ub)\n", " \n", "plt.subplot( 2, 1, 1 )\n", "plt.plot( np.arange(1,NP+1), G.T, '*');\n", "plt.subplot( 2, 1, 2 )\n", "plt.plot( np.arange(1,lam+1), Gcost, '*');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write generateChild\n", "\n", "Write a function that take the cost function, breeding pool, lower bounds, upper bounds, and settings as input. It should generate children from the breeding pool using cross-over and mutation. \n", "\n", "" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def generateChild(cost_fcn, P, lb, ub, settings):\n", " \"\"\"\n", " Generate a viable child (i.e one whos cost function is finite)\n", " and return it and its cost function.\n", " If 1000 tries fails to yield a parent, then an infinite cost\n", " is returned.\n", " Input Parameters:\n", " cost_fcn: handle to the cost function (which should take a candidate as input)\n", " P: parents (lam x NP ndarray of parameter values)\n", " lb: lower bounds for parameters (array of length NP)\n", " ub: upper bounds for parameters (array of length NP)\n", " settings: a GASettings object\n", " Returns:\n", " (params, cost)\n", " where params is the same shape as the lower bounds\n", " and cost is the cost for that set of parameters\n", " \"\"\"\n", " params = np.zeros(lb.shape);\n", " cost = np.inf;\n", " for i in range(1000):\n", " # Choose two parenst from the breeding pool.\n", " P1idx = np.random.choice(P.shape[0]);\n", " P1 = P[P1idx,:];\n", " P2idx = np.random.choice(P.shape[0]);\n", " P2 = P[P2idx,:];\n", " for j in range(lb.size):\n", " # uniform cross-over\n", " if np.random.random() < 0.5:\n", " params[j] = P1[j];\n", " else:\n", " params[j] = P2[j];\n", " # Mutate optimization variables\n", " params = np.multiply( 1+np.random.randn(params.size)*settings.mutation, params);\n", " # Make sure the mutation hasn't moved us out of bounds\n", " params = np.maximum(params,lb);\n", " params = np.minimum(params,ub);\n", " cost = cost_fcn(params);\n", " if np.isfinite(cost):\n", " return ( params, cost );\n", " return (np.zeros((lb.size)), np.inf)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test generateChild\n", "\n", "We will test it with the pattern_cost_function, so there are 7 parameters in each individual. Randomly create 2 members of the breeding pool and make their entries values between 0 and 4. Then generate a child. Print out the breeding pool and the child. Read the entries to make sure it looks like each one came from one parent and that it is slightly mutated." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Breeding Pool\n", "[[0. 0. 0. 0. 0. 0. 0.]\n", " [1. 1. 1. 1. 1. 1. 1.]]\n", "Child\n", "[0. 0.99516456 0.92507025 0.99980808 1.02349254 0.\n", " 0. ]\n" ] } ], "source": [ "lam = 50 # number of individuals in generation\n", "mu = 2 # number of individuals in breeding pool\n", "NP = 7 # num of parameters per individual\n", "P = np.zeros( (mu,NP) )\n", "for i in range(mu):\n", " P[i,:] = i % 5\n", "settings = GASettings(numParents=mu, numChildren=lam)\n", "\n", "lb = np.zeros((7,))\n", "ub = 5 + np.zeros((7,))\n", "(params,cost) = generateChild( pattern_cost_function, P, lb, ub, settings )\n", "\n", "print( \"Breeding Pool\")\n", "print( P )\n", "print( \"Child\")\n", "print(params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write the genetic algorithm\n", "\n", " \n", "\n" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def GA(cost_fcn, lb, ub, settings):\n", " \"\"\" Run the algorithm described in the notes to find a low-cost\n", " population of parameter sets.\n", " Input:\n", " cost_fcn: handle to cost function (should take a paramer set as input)\n", " lb: lower bounds for parameters (numpy array of length NP)\n", " ub: lower bounds for parameters (numpy array of length NP)\n", " settings: GASettings object\n", " Returns\n", " (params, cost, all_params, all_costs)\n", " where \n", " params is a 1xNP vector with the best parameter set found\n", " cost is a scalar with the cost of the best parameter set\n", " all_params is a list with a (settings.numChildren x NP) ndarray of parameters for each generation\n", " all_costs is a list with an NP-length array of costs for each generation\n", " \"\"\"\n", "\n", " mu = settings.numParents;\n", " lam = settings.numChildren;\n", " numGenerations = settings.numGenerations;\n", "\n", " # Create initial population\n", " G = np.zeros( (lam,lb.size) );\n", " Gcost = np.zeros( (lam,) );\n", " for i in range(lam):\n", " (G[i,:], Gcost[i]) = generateIndividual(cost_fcn, lb, ub);\n", " # sort them by cost\n", " idx = np.argsort(Gcost);\n", " Gcost = Gcost[idx]\n", " G = G[idx,:];\n", " all_params = [G]\n", " all_costs = [Gcost]\n", "\n", " for g in range(numGenerations):\n", " # Promote any elites\n", " elites = G[:settings.eliteCount,:]\n", " eliteCosts = Gcost[:settings.eliteCount]\n", " # select breeding pool\n", " (P, Pcost) = select_pool( G, Gcost, settings )\n", " # Generate the children for generation g\n", " G = np.zeros((lam, lb.size));\n", " Gcost = np.zeros((lam,));\n", " G[:settings.eliteCount,:] = elites\n", " Gcost[:settings.eliteCount] = eliteCosts\n", " for i in range(settings.eliteCount,lam):\n", " (G[i,:], Gcost[i]) = generateChild(cost_fcn, P, lb, ub, settings); \n", " # sort the children of this generation\n", " idx = np.argsort(Gcost);\n", " Gcost = Gcost[idx]\n", " G = G[idx,:];\n", " print('Best of generation ', g+1, ' has cost ', Gcost[0]);\n", " all_params.append(G)\n", " all_costs.append(Gcost)\n", "\n", " params = G[0,:];\n", " cost = Gcost[0];\n", " return (params, cost, all_params, all_costs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test the GA\n", "\n", "Test it with the pattern cost function. Plot the costs for all individuals in all the generations." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Best of generation 1 has cost 2.1178705917890683\n", "Best of generation 2 has cost 1.8376652532070314\n", "Best of generation 3 has cost 1.4338145675162404\n", "Best of generation 4 has cost 1.1200537470506173\n", "Best of generation 5 has cost 0.7648019416337929\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAdoAAAD4CAYAAABL9ycmAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAy6klEQVR4nO3deXhV1b3/8fciIxLEgWhFGuNwC4pIkBRUVJwtlVrsVaQO0MHrzdNCxaHqLVwEi79beLSNF6lg1VarFChexNaJwaLIFZAIAhEcLlMjaAICMphAYP3+OElMQs7ZO2fvfc4+J5/X8/QhydrZe2XT8HWt9V3fZay1iIiISDDaJbsDIiIi6UyBVkREJEAKtCIiIgFSoBUREQmQAq2IiEiAMoO4aefOnW1hYWEQtxYREQmdsrKy7dba/JbaAgm0hYWFrFixIohbi4iIhI4xZnO0Nk0di4iIBEiBVkREJEAKtCIiIgEKZI22JQcPHqSiooLq6upEPVKayc3NpWvXrmRlZSW7KyIibUbCAm1FRQUdO3aksLAQY0yiHit1rLXs2LGDiooKTj311GR3R0SkzUjY1HF1dTXHH3+8gmySGGM4/vjjNaMgIm1e5ZfVDJn2DpV7EvPvYULXaBVkk0vvX0QE/nvhx7y76Qv+e8HHCXmeq6ljY8ydwG2ABdYAP7bWamgkIiIpo9uYV6mpPdzw+XPLtvDcsi3kZLbjwwkDA3uu44jWGHMy8Aug2Fp7NpABDA2sRwH6/PPPuemmmzjttNPo06cP559/PnPmzElKXxYtWsT//u//Nnw+depUnn322bjv91//9V+cccYZdOvWjddff92PLoqIpJXF917KtUVdyM2KhL7crHZ8v6gLi++7NNDnuk2GygTaG2MOAkcBW4Pr0tcqv6xmxF9W8thNvTmhY66ne1lrGTx4MMOHD2f69OkAbN68mZdeesmPrraotraWzMyWX/GiRYvIy8vjggsuAKCkpCTu53zwwQfMmDGD8vJytm7dyhVXXMFHH31ERkZG3PcUEUk3JxydS8ecTGpqD5OT2Y6a2sN0zMn0HF+cOI5orbWfAg8DW4BtwG5r7bzm1xljbjfGrDDGrKiqqvKlc37Oo7/xxhtkZ2c3CWinnHIKI0eO5NChQ/zyl7/k29/+Nueccw7Tpk0DIsHwkksu4frrr6d79+7cfPPNWGsBKCsrY8CAAfTp04err76abdu2AXDJJZcwatQoiouLefTRR/nb3/5Gv3796N27N1dccQWff/45mzZtYurUqfzud7+jqKiIxYsXM27cOB5++GEAVq1axXnnncc555zDddddx86dOxvufd9999G3b1++9a1vsXjxYgDmzp3L0KFDycnJ4dRTT+WMM85g+fLlnt+ZiEi62b63hpv7ncKcn/Xn5n6nULW3JvBnOo5ojTHHAt8HTgV2AX81xtxirX2u8XXW2ieAJwCKi4utl04FMY9eXl7Oueee22LbU089RadOnXj33Xepqamhf//+XHXVVQCsXLmS8vJyunTpQv/+/VmyZAn9+vVj5MiRzJ07l/z8fGbOnMno0aN5+umnAThw4EBDreedO3eydOlSjDE8+eSTTJo0iUceeYSSkhLy8vK45557AFi4cGFDf4YNG8bkyZMZMGAAY8eOZfz48ZSWlgKRUfLy5ct55ZVXGD9+PAsWLODTTz/lvPPOa/j+rl278umnn8b1nkRE0tm0W4sbPp4w+OyEPNPN1PEVwEZrbRWAMeZ/gAuA52J+lweL772UCa+sY175Z1QfPExuVjuu7vENRl9zpm/P+PnPf87bb79NdnY2p5xyCqtXr2b27NkA7N69m48//pjs7Gz69u1L165dASgqKmLTpk0cc8wxrF27liuvvBKAQ4cOcdJJJzXc+8Ybb2z4uKKightvvJFt27Zx4MABxz2su3fvZteuXQwYMACA4cOHc8MNNzS0/+AHPwCgT58+bNq0yfuLEBGRQLkJtFuA84wxRwFfAZcDgR7NE8Q8eo8ePXjhhRcaPp8yZQrbt2+nuLiYgoICJk+ezNVXX93kexYtWkROTk7D5xkZGdTW1mKtpUePHrzzzjstPqtDhw4NH48cOZK77rqLa6+9lkWLFjFu3Li4fwagoT/1fQE4+eST+ec//9lwTUVFBSeffLKn54iIiD/crNEuA2YD7xHZ2tOOuiniIPk9j37ZZZdRXV3N448/3vC1/fv3A3D11Vfz+OOPc/DgQQA++ugj9u3bF/Ve3bp1o6qqqiHQHjx4kPLy8hav3b17d0PQe+aZZxq+3rFjR/bs2XPE9Z06deLYY49tWH/985//3DC6jebaa69lxowZ1NTUsHHjRj7++GP69u0b83tERCQxXGUdW2sfAB4IuC9N+D2PbozhxRdf5M4772TS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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "PN = 7\n", "lb = np.zeros( (PN,) );\n", "ub = 5 + np.zeros( (PN,) );\n", "cost_fcn = pattern_cost_function;\n", "settings = GASettings(numParents=10, numChildren=50)\n", "settings.numGenerations = 5;\n", "settings.eliteCount = 1;\n", "settings.selection = 'truncation';\n", "\n", "(params, cost, all_params, all_costs) = GA(pattern_cost_function, lb, ub, settings);\n", "\n", "plt.figure( figsize=(8,4) )\n", "legs = []\n", "for i in range(len(all_costs)):\n", " plt.plot( np.arange(all_costs[i].size), all_costs[i], '*' )\n", " legs.append( \"Generation\" + str(i) )\n", "plt.legend( legs );" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }