After much frustration and stress, I finally was able to complete the final aspect of this Problem Set. Here is a description of the 4th problem.
Write a function, called findMaxExpenses, which takes five arguments: a salary
(salary), a percentage of your salary to save (save), a list of annual growth percentages
on investments while you are still working (preRetireGrowthRates), a list of annual
growth percentages on investments while you are retired (postRetireGrowthRates), and
a value for epsilon (epsilon). As with problems 2 and 3, the lengths of
and postRetireGrowthRates determine the number of years you
plan to be working and retired, respectively.
Use the idea of binary search to find a value for the amount of expenses you can
withdraw each year from your retirement fund, such that at the end of your retirement,
the absolute value of the amount remaining in your retirement fund is less than epsilon
(note that you can overdraw by a small amount). Start with a range of possible values
for your annual expenses between 0 and your savings at the start of your retirement
(HINT #1: this can be determined by utilizing your solution to problem 2). Your function
should print out the current estimate for the amount of expenses on each iteration
through the binary search (HINT #2: your binary search should make use of your
solution to problem 3), and should return the estimate for the amount of expenses to
withdraw. (HINT #3
As you can tell from the description, this function is more complicated than the other functions from this Problem Set. I have to use several of my previous functions, create the final function. What does this final function do? It takes the total amount you are depositing into your retirement account, the years you are employed and the interest rates, and determines what your total savings upon retirement will be (otherwise known as problem 2). Then, you must determine what your total budget is for your years in retirement. Your total retirement account value is different each year during retirement, because of A, the amount you withdraw each year, and B, the interest that is accrued on the total value of your account. These two aspects are processed by the function from problem 3. To determine my ultimate budget for each year during retirement, I must use the final function from problem three, and search until I find a value for expenses, that will not put me in the hole upon the last year of my life. That means search through all the possible values to determine which one will leave me with a value greater than zero, but less than .01 (epsilon in this problem). Using binary search, I can cut down the time it would take to solve the problem. Binary search uses the following idea. Choose a number which lies between zero and 1000. How does someone else determine that number? Once can find the solution by systematically choosing the midway point, while also using a higher or lower game. Start with the first question. What is the midway point? It is 500. Is the answer higher or lower than 500? It is lower. Now your minimum and maximum points have changed. Your minimum value is still zero, but your maximum is now 500. What is the midway point? It is 250. Is the answer higher or lower than 250? Higher. Your maximum value is still 500, but your minimum value is now 250. Slowly but surely you’ll find the answer. That is the basic idea of binary search. Now returning to my function for problem 4.
def findMaxExpenses(salary,save,preRetireGrowthRates,postRetireGrowthRates,epsilon): savings = nestEggVariable(salary,save,preRetireGrowthRates) endtotal = savings[-1] minguess = 0 maxguess = endtotal + epsilon finalexpenses = postRetirement(endtotal,postRetireGrowthRates,endtotal/2) while finalexpenses[-1] < 0 or finalexpenses[-1] > epsilon: guess = (maxguess-minguess)/2 + minguess finalexpenses = postRetirement(endtotal,postRetireGrowthRates,guess) if finalexpenses[-1] < 0: maxguess = guess elif finalexpenses[-1] > epsilon: minguess = guess else: return guess |
First I define my total savings from each year by using my function nestEggVariable from problem 2 of 4. This creates a list of the total amount I saved each year. Next I identify the last entry in that list, as my endtotal. Then I identify my minguess and maxguess. Therefore I have the minimum and maximum for my binary search model. The last part of identification is the finalexpenses. finalexpenses is the variable used for my postRetirement function. This function will process, for each year in retirement, the growth rate of my retirement accounts. The result is a list, indicating how much I have left at the end of each year during retirement. Looking at the variables one will see the endtotal savings, the postRetireGrowthRates list, and the first guess in my binary search model. They are all variables for the function. My first guess as you can see is the midway point, or half of the endtotal.
I use a ‘while’ loop to run the binary search. I state that as long as my last entry in the finalexpenses list (last year of retirement) IS NOT greater than zero and less than epsilon it is to process the following. First it defines guess as the halfway point between the maxguess and the minguess. Then it runs the postRetirement function, replacing endtotal/2 with the guess variable. Now for the actual binary search piece. I indicate that ‘if’ the last entry of finalexpenses is less than zero my new maxguess is guess. I am lowering the maximum(maxguess) on my scale because my total account value was less than zero in the end, which means I spent too much money each year during retirement. However ‘elif’ (else if), my final entry is above epsilon (.01), it seems I spent too little each year during retirement. Therefore I would increase my minimum guess(minguess) to the value to guess, so that my scale adjusts to include only higher values, and thus bring me closer to my solution.
Once the binary search has run its course and I have found a value not only above zero, but also below epsilon, I have found the solution to the problem. Thus my ‘else’ will ‘return’ from the function with the guess last found. Final answer? Off of these starting numbers: findMaxExpenses(10000,10,[3,4,5,0,3],[10,5,0,5,1],.01), the answer is: 1229.9528031.
Overview
Just a quick reflection on the difficulties I found when working on this Problem Set. I think one of the hardest part of this Problem Set was the relative ease I found when completing the first 3 problems. The final culmination function was the most difficult and it made me implement a binary search. This was something I hadn’t done before. But I get ahead of myself.
I wanted to mention the first thing that I had to learn before I could complete the first three problems in this Problem Set. The first three made me learn to use slices within a function. Learning to use the last item in a list, whenever and wheresoever needed, by taking a slice of the list. The next aspect, which was a little more difficult to learn, was how to use lists as variables for functions. That was a more difficult challenge. Understanding how to think about lists as you input them into the variable, and how to process their information within the function. I also have a much better understanding of appending.
Back to the fourth problem. I’m still getting used to using multiple functions within one master function. Making sure I understand the information each of my functions spit out, and knowing how to use them in a function is still taking some work. The most difficult part was learning how to use and write a binary search. I attempted to do so on my own several times before I asked for help. Even then I was still having difficulties because I didn’t understand the need for a minimum value. Frustrating for myself as well as my helper. On top of that I had written my code incorrectly, and yet I kept referring to it when trying to understand what I was doing wrong. Each time I referenced it, it made me more and more confused as to what I was doing wrong, and where the error was.
After some serious discussion, I finally started understanding what I was misunderstanding. What I think might have been more helpful for myself, was if I allowed myself to have multiple versions of the same function on different files, without looking at the former functions, so I didn’t have them there to visually confuse me. In all honesty, although I understand how my function works, I realise I still have some holes when it comes to simply understanding binary function in a mathematical sense. I can’t simply visualize it. I know that is causing me some difficulties, and it will be something I work on in the coming weeks. I know that I can recreate things that I’ve seen and had explained to me, but I fear for my ability to understand something I’ve never seen before.
That’s it for today. I wish everyone a happy, happy weekend!