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 simulating the elephant population in Kruger National Part, 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.
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.
- Implement binary search on a sorted list
Create a new file, search.py. Then create a function searchSortedList that takes in two parameters, a list and a value. You can use the following template.
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.
- Write a function to generate a default parameter list
The next task is to add a function to your elephant.py file. The function should be called defaultParameters. It should take no arguments and return a list with all of the necessary parameters for the simulation with their default values.
For this project, set the default carrying capacity to 1000
- Write an elephant simulation function
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 ):
First, set up the parameters. If inputParameters is equal to the value None, then assign to parameters the result of calling your defaultParameters 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/replace 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.
Think of the return value as specifying whether too many or too few elephants are being darted. If the return value is negative, then the population is too big and it needs to shrink. If the return value is positive, then the population is too small and it needs to grow.
- Test your elephantSim function
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.