Skip to content

Commit

Permalink
Merge pull request #142 from 7ony7he7iger/HW8_branch
Browse files Browse the repository at this point in the history
Homework number eight
  • Loading branch information
jakevdp committed Dec 2, 2014
2 parents 81936e9 + 6955fea commit c45a9c2
Showing 1 changed file with 363 additions and 0 deletions.
363 changes: 363 additions & 0 deletions 7ony7he7iger/HW_8.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,363 @@
{
"metadata": {
"name": "",
"signature": "sha256:a140f096968811b2ba7b846b8556508be75cbbdd43788e97388a5a529f3ecddf"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Homework #8"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Diagnose"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The original code that has errors/bugs. "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"\"\"\"\n",
"A script to compare different root-finding algorithms.\n",
"\n",
"This version of the script is buggy and does not execute. It is your task\n",
"to find an fix these bugs.\n",
"\n",
"The output of the script sould look like:\n",
"\n",
" Benching 1D root-finder optimizers from scipy.optimize:\n",
" brenth: 604678 total function calls\n",
" brentq: 594454 total function calls\n",
" ridder: 778394 total function calls\n",
" bisect: 2148380 total function calls\n",
"\"\"\"\n",
"from itertools import product\n",
"\n",
"import numpy as np\n",
"from scipy import optimize\n",
"\n",
"FUNCTIONS = (np.tan, # Dilating map\n",
" np.tanh, # Contracting map\n",
" lambda x: x**3 + 1e-4*x, # Almost null gradient at the root\n",
" lambda x: x+np.sin(2*x), # Non monotonous function\n",
" lambda x: 1.1*x+np.sin(4*x), # Fonction with several local maxima\n",
" )\n",
"\n",
"OPTIMIZERS = (optimize.brenth, optimize.brentq,\n",
" optimize.ridder, optimize.bisect)\n",
"\n",
"\n",
"def apply_optimizer(optimizer, func, a, b):\n",
" \"\"\" Return the number of function calls given an root-finding optimizer, \n",
" a function and upper and lower bounds.\n",
" \"\"\"\n",
" return optimizer(func, a, b, full_output=True)[1].function_calls,\n",
"\n",
"\n",
"def bench_optimizer(optimizer, param_grid):\n",
" \"\"\" Find roots for all the functions, and upper and lower bounds\n",
" given and return the total number of function calls.\n",
" \"\"\"\n",
" return sum(apply_optimizer(optimizer, func, a, b)\n",
" for func, a, b in param_grid)\n",
"\n",
"\n",
"def compare_optimizers(optimizers):\n",
" \"\"\" Compare all the optimizers given on a grid of a few different\n",
" functions all admitting a signle root in zero and a upper and\n",
" lower bounds.\n",
" \"\"\"\n",
" random_a = -1.3 + np.random.random(size=100)\n",
" random_b = .3 + np.random.random(size=100)\n",
" param_grid = product(FUNCTIONS, random_a, random_b)\n",
" print(\"Benching 1D root-finder optimizers from scipy.optimize:\")\n",
" for optimizer in OPTIMIZERS:\n",
" ncalls = bench_optimizer(optimizer, param_grid)\n",
" print('{name}: {ncalls} total function calls'.format(\n",
" name=optimizer.__name__, ncalls=ncalls))\n",
"\n",
"\n",
"if __name__ == '__main__':\n",
" compare_optimizers(OPTIMIZERS)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Benching 1D root-finder optimizers from scipy.optimize:\n"
]
},
{
"ename": "TypeError",
"evalue": "unsupported operand type(s) for +: 'int' and 'tuple'",
"output_type": "pyerr",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-4-5c834ce551a7>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 60\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 61\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0m__name__\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;34m'__main__'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 62\u001b[1;33m \u001b[0mcompare_optimizers\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mOPTIMIZERS\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-4-5c834ce551a7>\u001b[0m in \u001b[0;36mcompare_optimizers\u001b[1;34m(optimizers)\u001b[0m\n\u001b[0;32m 54\u001b[0m \u001b[1;32mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Benching 1D root-finder optimizers from scipy.optimize:\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 55\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0moptimizer\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mOPTIMIZERS\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 56\u001b[1;33m \u001b[0mncalls\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mbench_optimizer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0moptimizer\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mparam_grid\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 57\u001b[0m print('{name}: {ncalls} total function calls'.format(\n\u001b[0;32m 58\u001b[0m name=optimizer.__name__, ncalls=ncalls))\n",
"\u001b[1;32m<ipython-input-4-5c834ce551a7>\u001b[0m in \u001b[0;36mbench_optimizer\u001b[1;34m(optimizer, param_grid)\u001b[0m\n\u001b[0;32m 41\u001b[0m \"\"\"\n\u001b[0;32m 42\u001b[0m return sum(apply_optimizer(optimizer, func, a, b)\n\u001b[1;32m---> 43\u001b[1;33m for func, a, b in param_grid)\n\u001b[0m\u001b[0;32m 44\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 45\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'tuple'"
]
}
],
"prompt_number": 4
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Debug 1. Fix a runtime error"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, encountered a TypeError in line 43 as above. It says there comes an integer and a tuple in the operand + in the sum() function which are not able to add these two different types of input. To find out where a tuple is generated and further to fix this, I tried debug magic function."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%debug"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"> \u001b[1;32m<ipython-input-4-5c834ce551a7>\u001b[0m(43)\u001b[0;36mbench_optimizer\u001b[1;34m()\u001b[0m\n",
"\u001b[1;32m 42 \u001b[1;33m return sum(apply_optimizer(optimizer, func, a, b)\n",
"\u001b[0m\u001b[1;32m---> 43 \u001b[1;33m for func, a, b in param_grid)\n",
"\u001b[0m\u001b[1;32m 44 \u001b[1;33m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[0m\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"stream": "stdout",
"text": [
"ipdb> print apply_optimizer(optimizer, *param_grid.next())\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"(9,)\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"stream": "stdout",
"text": [
"ipdb> q\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here I found ',' was generated by the function apply_optimizer and that is from the typo '.function_calls,', which made a tuple '(9,)' instead of an integer expected as a return of the function. I fixed this typo for the corrected running the code."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def apply_optimizer(optimizer, func, a, b):\n",
" \"\"\" Return the number of function calls given an root-finding optimizer,\n",
" a function and upper and lower bounds.\n",
" \"\"\"\n",
" return optimizer(func, a, b, full_output=True)[1].function_calls"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"compare_optimizers(OPTIMIZERS)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Benching 1D root-finder optimizers from scipy.optimize:\n",
"brenth: 605054 total function calls"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"brentq: 0 total function calls\n",
"ridder: 0 total function calls\n",
"bisect: 0 total function calls\n"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Fixed the runtime error still got different results from the expected ones; brentq, ridder, and bisect produced nothing. "
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Debug 2. Fix a semantic error"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It appears that the same iterable generated by the random number function was not input in to 'brentq', 'ridder', and 'bisect' optimizers; the entire loop for each optimizer suddenly broke after 'brenth' ran. So I fixed this adding list() in front of the ouput of 'param_grid' liner to create the same iterable for each optimizer and applied this to the original code."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def compare_optimizers(optimizers):\n",
" \"\"\" Compare all the optimizers given on a grid of a few different\n",
" functions all admitting a signle root in zero and a upper and\n",
" lower bounds.\n",
" \"\"\"\n",
" random_a = -1.3 + np.random.random(size=100)\n",
" random_b = .3 + np.random.random(size=100)\n",
" param_grid = list(product(FUNCTIONS, random_a, random_b))\n",
" print(\"Benching 1D root-finder optimizers from scipy.optimize:\")\n",
" for optimizer in OPTIMIZERS:\n",
" ncalls = bench_optimizer(optimizer, param_grid)\n",
" print('{name}: {ncalls} total function calls'.format(\n",
" name=optimizer.__name__, ncalls=ncalls))"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Test the fixed code again."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"compare_optimizers(OPTIMIZERS)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Benching 1D root-finder optimizers from scipy.optimize:\n",
"brenth: 601987 total function calls"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"brentq: 592551 total function calls"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"ridder: 771204 total function calls"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n",
"bisect: 2147060 total function calls"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
}
],
"prompt_number": 14
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Summary"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, it worked pretty well as we expected. \n",
"\n",
"To summarize, there were a runtime error (TypeError) and a semantic error (Failure to the for looping) in the given code. I debugged these first with 'debug magic' function to point out the typo and fix the runtime error. Then with an investigation of the iterating process, I found a dead end of the code's inputting the iterable to the loop and eventually fixed 'param_grid' to generate the same iterable to be input for each optimizer."
]
}
],
"metadata": {}
}
]
}

0 comments on commit c45a9c2

Please sign in to comment.