Skip to content

Commit cb3d378

Browse files
Revise C0-A30
1 parent ab2fc58 commit cb3d378

File tree

1 file changed

+118
-34
lines changed

1 file changed

+118
-34
lines changed

chapter0-exercises/chapter_0_part2.ipynb

Lines changed: 118 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,55 +2902,128 @@
29022902
"id": "cognitive-toolbox"
29032903
},
29042904
"source": [
2905-
"## Activity: Compound function\n",
2905+
"## Activity 30: Function Composition\n",
29062906
"\n",
2907-
"- For a given function (f), starting point (a0) and number of iteration (m), write a function that calculates f(a0), f(f(a0)), ..., f(f(f(...f(a0)))))"
2907+
"At this point, we presume you understand how functions work: \n",
2908+
"- they take in values, \n",
2909+
"- and output values. \n",
2910+
"\n",
2911+
"When the output of one function becomes the input for another, we have a special name for it: *function composition*.\n",
2912+
"\n",
2913+
"In this activity, you are given a function `f`, an initial value `a0`, and some number of iterations to perform, `m`. How would you write Python code to show how the value of `a` changes as it is passed to `f`, over `m` iterations?\n",
2914+
"\n",
2915+
"Return the values $a$<sub>1</sub>, $a$<sub>2</sub>, $a$<sub>3</sub>, and $a$<sub>4</sub>, using a `list`. Please round your answers to 8 decimal places."
29082916
],
29092917
"id": "cognitive-toolbox"
29102918
},
2919+
{
2920+
"cell_type": "markdown",
2921+
"metadata": {
2922+
"id": "xClzxxP1Fkyv"
2923+
},
2924+
"source": [
2925+
"### Example Input\n",
2926+
"In mathematics, whenever we have a function that takes in the output of another as a parameter, then we call that a *compound function*.\n",
2927+
"\n",
2928+
"In this activity, `f` is a compound function (note that you could also call it a *recursive function*, since it takes the output of itself as a parameter). \n",
2929+
"\n",
2930+
"Consider the function $f(x) = \\frac{x + n}{2x}$. Let's see how an initial value of `1.0` changes over `4` iterations:\n",
2931+
"```\n",
2932+
"Input:\n",
2933+
"f = lambda x: (x+n/x)/2 # our function\n",
2934+
"n = 2 \n",
2935+
"a0 = 1.0 # the initial value\n",
2936+
"m = 4 # the number of iterations\n",
2937+
"\n",
2938+
"Output\n",
2939+
"[1.5, 1.41666667, 1.41421569, 1.41421356]\n",
2940+
"\n",
2941+
"Explanation:\n",
2942+
"This output is the result of the following:\n",
2943+
"[\n",
2944+
" round(output, 8) for output in (\n",
2945+
" f(a0), \n",
2946+
" f(f(a0)), \n",
2947+
" f(f(f(a0))), \n",
2948+
" f(f(f(f(a0))))\n",
2949+
" )\n",
2950+
"]\n",
2951+
"``` "
2952+
],
2953+
"id": "xClzxxP1Fkyv"
2954+
},
29112955
{
29122956
"cell_type": "code",
29132957
"metadata": {
2914-
"id": "rubber-terry",
2915-
"outputId": "5b8b3558-ff3f-4d57-e9bf-b4f2cce63acc"
2958+
"id": "I3DzpHX2Kj6w"
29162959
},
29172960
"source": [
2918-
"f= lambda x: (x+n/x)/2\n",
2919-
"n = 2\n",
2920-
"a0 = 1.0\n",
2921-
"m = 4\n",
2922-
"# This implementation is not good as it is hard-coded\n",
2923-
"print([round(x, 8) for x in (f(a0), f(f(a0)), f(f(f(a0))), f(f(f(f(a0)))))])"
2961+
"f = lambda x: (x+n/x)/2 # our function\n",
2962+
"n = 2 \n",
2963+
"a0 = 1.0 # the initial value\n",
2964+
"m = 4 # the number of iterations"
29242965
],
2925-
"id": "rubber-terry",
2926-
"execution_count": null,
2927-
"outputs": [
2928-
{
2929-
"output_type": "stream",
2930-
"text": [
2931-
"[1.5, 1.41666667, 1.41421569, 1.41421356]\n"
2932-
],
2933-
"name": "stdout"
2934-
}
2935-
]
2966+
"id": "I3DzpHX2Kj6w",
2967+
"execution_count": 27,
2968+
"outputs": []
2969+
},
2970+
{
2971+
"cell_type": "markdown",
2972+
"metadata": {
2973+
"id": "WJVrZ1HUJqG1"
2974+
},
2975+
"source": [
2976+
"### Solution 1: Using a Generator\n",
2977+
"While you could simply implement the code in the \"Explanation\" section above, it wouldn't be very readable, and it would stop working the moment the value of `m` changes.\n",
2978+
"\n",
2979+
"Therefore, it is much more preferable to create a function to complete this activity. In a separate activity we can do something like this using a `generator` function in Python, via the `yield` keyword:"
2980+
],
2981+
"id": "WJVrZ1HUJqG1"
29362982
},
29372983
{
29382984
"cell_type": "code",
29392985
"metadata": {
2940-
"id": "informational-cuisine",
2941-
"outputId": "6f95ea62-721a-487a-dcae-f52014b273ec"
2986+
"id": "informational-cuisine"
29422987
},
29432988
"source": [
2944-
"def repeat(f, a, m):\n",
2989+
"def compound_function(f, a, m):\n",
2990+
" # compute the value of a after each iteration\n",
29452991
" for _ in range(m):\n",
2992+
" # apply the function\n",
29462993
" a = f(a) \n",
2947-
" yield a\n",
2948-
" \n",
2949-
"for i in repeat(f, 1, 4):\n",
2950-
" print(round(i, 8))"
2994+
" # output the result (don't forget to round!)\n",
2995+
" yield round(a, 8)"
29512996
],
29522997
"id": "informational-cuisine",
2953-
"execution_count": null,
2998+
"execution_count": 28,
2999+
"outputs": []
3000+
},
3001+
{
3002+
"cell_type": "markdown",
3003+
"metadata": {
3004+
"id": "MBBobFw7LfQN"
3005+
},
3006+
"source": [
3007+
"#### Test Out Solution 1\n",
3008+
"Recall we can use a `for` loop to iterate over the values returned by a `generator` object:"
3009+
],
3010+
"id": "MBBobFw7LfQN"
3011+
},
3012+
{
3013+
"cell_type": "code",
3014+
"metadata": {
3015+
"colab": {
3016+
"base_uri": "https://localhost:8080/"
3017+
},
3018+
"id": "uOI3asirLtG8",
3019+
"outputId": "b311d371-d4b9-4797-ab95-ab2048e34b58"
3020+
},
3021+
"source": [
3022+
"for output in compound_function(f, a0, m):\n",
3023+
" print(output)"
3024+
],
3025+
"id": "uOI3asirLtG8",
3026+
"execution_count": 29,
29543027
"outputs": [
29553028
{
29563029
"output_type": "stream",
@@ -2970,23 +3043,34 @@
29703043
"id": "close-trinity"
29713044
},
29723045
"source": [
2973-
"### Note: the above compound iteration will converge to $\\sqrt{n}$ "
3046+
"### Special Note: Convergence\n",
3047+
"Did you notice anything special about $f(x)$ in Activity 30? *Hint:* try increasing the number of iterations `m`, and trying out different values of `n` - then see if you spot a familiar pattern!\n",
3048+
"\n",
3049+
"<hr>\n",
3050+
"\n",
3051+
"#### The Answer:\n",
3052+
"\n",
3053+
"As the number of iterations `m` increases, the outputs of the compound function $f(x)$ converges to $\\sqrt{n}$. \n",
3054+
"\n",
3055+
"We can even verify this by comparing it with the result of the `numpy.sqrt` function!\n"
29743056
],
29753057
"id": "close-trinity"
29763058
},
29773059
{
29783060
"cell_type": "code",
29793061
"metadata": {
29803062
"id": "freelance-skiing",
2981-
"outputId": "20727ae8-d2b0-46da-ee6a-323aa61279c8"
3063+
"colab": {
3064+
"base_uri": "https://localhost:8080/"
3065+
},
3066+
"outputId": "7a137816-a27f-496b-c772-a67ac7b782cd"
29823067
},
29833068
"source": [
2984-
"# Note: the above coumpound iteration will converge to np.sqrt(n) \n",
29853069
"import numpy as np\n",
29863070
"np.sqrt(n)"
29873071
],
29883072
"id": "freelance-skiing",
2989-
"execution_count": null,
3073+
"execution_count": 32,
29903074
"outputs": [
29913075
{
29923076
"output_type": "execute_result",
@@ -2998,7 +3082,7 @@
29983082
"metadata": {
29993083
"tags": []
30003084
},
3001-
"execution_count": 203
3085+
"execution_count": 32
30023086
}
30033087
]
30043088
}

0 commit comments

Comments
 (0)