CS 152: Lab 6

Title image Project 6
Spring 2017

Lab Exercise 6: Searching

The purpose of this project is to get you thinking about automating a scientific experiment and optimizing the parameters of a process.

This is the second part of a three-part project where we'll be simulating the elephant population in Kruger National Park, South Africa. This week we'll be focusing on how varying the parameters changes the management strategies. Rather than manually exploring the parameter, space, however, we'll automate the process and use a search method to find the optimal darting percentage given the simulation parameters.


Tasks

If you have not already done so, mount your personal space, create a new project6 folder and bring up TextWrangler and a Terminal. Also, copy your elephant.py file from project 5 into your project 6 working directory. You will need it later in the project.

  1. Implement the binary search algorithm in a function that will search a sorted list of numbers for a particular number. Create a new file, search.py. Then create a function searchSortedList that takes in two parameters, a list and a value.
    1. Copy the template below into search.py
    2. Read through the template.
    3. Write a docstring that describes what the function does, and what each of the parameters are for (including the type of values you are expecting them to have).
    4. Write the code.
    def searchSortedList( mylist, value ):
        # assign to the variable done, the value False
        # assign to the variable found, the value False
        # assign to the variable count, the value 0
        # assign to the variable maxIdx, the one less than the length of mylist 
        # assign to the variable minIdx, the value 0
    
        # start a while loop that executes while done is not True    
            # increment count  (which keeps track of how many times the loop executes
    
            # assign to testIndex the average of maxIdx and minIdx (use integer math)        
    
            # if the myList value at testIndex is less than value
                # assign to minIdx the value testIndex + 1
            # elif the myList value at testIndex is greater than value
                # assign to maxIdx the value testIndex - 1
            # else
                # set done to True
                # set found to True
    
            # if maxIdx is less than minIdx
                # set done to True
                # set found to False
    
        return (found, count)
    

    Once you have coded that up, import the random package, copy the following test function, and run it see if your function finds the value 42 in the list (it should). Think about why it can take a different number of steps each time you run the program.

    def test():
    
        a = []
        for i in range(10000):
            a.append( random.randint(0,100000) )
    
        a.append(42)
    
        a.sort()
    
        print searchSortedList( a, 42 )
    
    if __name__ == "__main__":
        test()
    

    This function is practice for creating the optimization function for the elephant simulation. That function will have a similar structure, and it will also execute a binary search, but it will have more parameters and be more flexible in how it works.

  2. The next task is to add a function to your elephant.py file. The function should be called defaultSimParameters. It should take no arguments and return a list with all of the necessary parameters for the simulation with their default values. Since we are going to be running the simulation many many many times, we will also be changing the default carrying capacity to 2000 (instead of 7000).
  3. Next, also in your elephant.py file, create a function elephantSim. The arguments to the function should be the percent darted (percDart) and a parameter list, which should have a default value of None. In other words, set it up as the following.
    def elephantSim( percDart, inputParameters = None ):
    

    The first thing to do is set up the parameters. If inputParameters is None, then assign to parameters the result of calling your defaultSimParameters function. Otherwise, assign to parameters the value of inputParameters. Next, assign to the percented darted element of the parameters list the value of the percDart parameter (this should overwrite the default parameter value for percent darted). Next, assign to a variable results the result of calling the runSimulation function with the parameters list. Then loop 4 times, each time adding the result of calling runSimulation to the results.

    results = results + runSimulation(parameters)

    This should repeat the simulation five times and collect all of the results in a single list. The structure of the results list is that it is a list of lists. Each sub-list consists of the total population and other statistics for a given simulation year.

    Finally, loop over the results list and calculate the average total population. Remember, the total population for each year is the first element in each sublist. The function should return the carrying capacity minus the average total population of the simulations, cast as an integer.

    When you are finished with this, use the following test function to evaluate your elephantSim function. It tests the percent darted for five different values. The difference value should go from negative to positive for the default simulation parameters.

When you are done with the lab exercises, you may begin the project.