{ "cells": [ { "cell_type": "code", "execution_count": null, "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": null, "metadata": {}, "outputs": [], "source": [ "# GASettings class\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Copy-Paste select_pool" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Select pool\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Copy-Paste generateIndividual" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# generateIndividual\n" ] }, { "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": null, "metadata": {}, "outputs": [], "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": null, "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", " # write code here" ] }, { "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": null, "metadata": {}, "outputs": [], "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": null, "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", " # Write code here" ] }, { "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": null, "metadata": {}, "outputs": [], "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 }