{ "cells": [ { "cell_type": "code", "execution_count": 4, "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 Support Code\n", "\n", "We begin by implementing a class called GASsetting that will store all the settings for the algorithm. Fields include\n", "\n", "" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "class GASettings:\n", " def __init__( self, numParents = 10, numChildren = 50 ):\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write select_pool\n", "\n", "We will build the genetic algorith bottom-up. First, write the select_pool function, with the members of the previous generation and their costs as input (along with the settings). \n", "\n", "Select pool should return a tuple (P, Pcost)\n", "\n", "where P is the numParents x numParameter matrix of individuals in the breeding pool and Pcost is the array of their costs.\n", "\n", "If settings.selection is 'uniform', then each member of P is chosen randomly from G (where each invidivual in G is equally likely to be chosen).\n", "\n", "If settings.selection is 'truncation', then each member of P is chosen randomly from settings.numParents lowest cost individuals in G (where each individual in that set is equally likely to be chosen and it is OK if an individual is chosen more than once). We can assume that G is sorted by cost, so this means we choose from the first settings.numParents individuals." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "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", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test the selection operators\n", "\n", "Test the selection operators by generating a fake original generation of 10,000 individuals with costs ranging from 0.1 to 500. For each operator, select a pool of 1,000 individuals and plot a histogram of their costs." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Test the selection operators\n", "# Make fake parameters, using the index as the values (so we can differentiate them)\n", "lam = 10000 # number of individuals in generation\n", "mu = 1000 # number of individuals in breeding pool\n", "NP = 5 # num of parameters per individual\n", "G = np.zeros( (lam,NP) )\n", "for i in range(lam):\n", " G[i,:] = i\n", "Gcost = np.linspace(0.1,500,lam)\n", "settings = GASettings(numParents=mu, numChildren=lam)\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write generateIndividual\n", "\n", "Write the code that will generate a random individual in parameter space. The individual should have entries between the lower bound and upper bound and should have finite cost. We make 1000 attempts to find a parameter set that leads to a finite code before giving up and just returning np.inf." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "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", " '''\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test generateIndividual\n", "\n", "Run generateIndividual with the pattern cost function to generate 1000 individuals, storing each one as a row in a 1000x7 matrix. Use [0,4,1,1,2,2,0] as the lower bounds and [5,6,3,2,4,4,2] as the upper bounds.\n", "\n", "Test it by plotting the result as 5 columns of values (i.e. x-axis is 1:7 and the y-axis is the parameter value). This isn't much of a test, but it makes sure that the points are in the expected ranges. We wil also plot the costs (individual's index on x-axis, cost on y-axis) just to see that it was computed within a range that makes sense. It should look like a busy rectangle full or asterisks." ] }, { "cell_type": "code", "execution_count": 1, "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" ] } ], "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 }