├── LICENSE ├── README.md ├── TOC_and_ch1.pdf ├── ch5.pdf ├── exercises ├── ch02_functions_exercises.ipynb ├── ch03_functionFamilies_exercises.ipynb ├── ch04_limits_exercises.ipynb ├── ch05_fundamentalsDerivatives_exercises.ipynb ├── ch06_criticalPoints_exercises.ipynb ├── ch07_derivativesRules_exercises.ipynb ├── ch08_derivativesTheorems_exercises.ipynb ├── ch09_applications_exercises.ipynb ├── ch10_multivariableDiff_exercises.ipynb ├── ch12_integrationIntuition_exercises.ipynb ├── ch13_geometryIntegration_exercises.ipynb ├── ch14_integratingFuns_exercises.ipynb ├── ch15_improper_exercises.ipynb ├── ch16_integrationTechniques_exercises.ipynb ├── ch17_integrationGeometry_exercises.ipynb ├── ch18_statistics_exercises.ipynb └── ch19_multivariableIntegration_exercises.ipynb └── figures ├── ch02_functions_figures.ipynb ├── ch03_functionFamilies_figures.ipynb ├── ch04_limits_figures.ipynb ├── ch05_fundamentalsDerivatives_figures.ipynb ├── ch06_criticalPoints_figures.ipynb ├── ch07_derivativesRules_figures.ipynb ├── ch08_derivativesTheorems_figures.ipynb ├── ch09_applications_figures.ipynb ├── ch10_multivariableDiff_figures.ipynb ├── ch11_differentialArt_figures.ipynb ├── ch12_integrationIntuition_figures.ipynb ├── ch13_geometryIntegration_figures.ipynb ├── ch14_integratingFuns_figures.ipynb ├── ch15_improper_figures.ipynb ├── ch16_integrationTechniques_figures.ipynb ├── ch17_integrationGeometry_figures.ipynb ├── ch18_statistics_figures.ipynb └── ch19_multivariableIntegration_figures.ipynb /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Mike X Cohen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Calculus unraveled: Intuition, Proofs, and Python 2 | 3 | ## Hello friends! 4 | 5 | Here's the repo for my shiny new calculus textbook. It's 605 pages of wholesome mathematical goodness :) 6 | 7 | This repository contains all the Python code files to produce the book figures, illustrate the concepts, and show solutions to all exercises. 8 | 9 | ### Table of contents and sample chapters 10 | 11 | You can see the table of contents via the amazon book preview (link below) or the TOC_and_ch1.pdf file uploaded here. Chapter 1 provides an introduction to the book, target audience, and prerequisites. 12 | 13 | Please enjoy the sample chapter on fundamentals of differentiation (ch5.pdf). Looking through this chapter will give you a feel for the quality, formatting, and style of the book and the exercises. 14 | 15 | ## Buy the book: 16 | The full book is available on amazon: https://www.amazon.com/dp/B0DX6BPPZ8 17 | 18 | ## Watch YT videos of exercises and their solutions 19 | Video walk-throughs of instructions and Python solutions to the book exercises can be found on my YT channel: 20 | [https://www.youtube.com/](https://www.youtube.com/playlist?list=PLn0OLiymPak2TFbFj2SD6-p-3-jOah7fe) 21 | 22 | ![Calculart](https://sincxpress.com/images/calcsBookCoverSmall.png) 23 | 24 | -------------------------------------------------------------------------------- /TOC_and_ch1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikexcohen/Calculus_book/acac175d38cd218a1d2ee235fa7cdfae4cb05151/TOC_and_ch1.pdf -------------------------------------------------------------------------------- /ch5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikexcohen/Calculus_book/acac175d38cd218a1d2ee235fa7cdfae4cb05151/ch5.pdf -------------------------------------------------------------------------------- /exercises/ch02_functions_exercises.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [ 8 | { 9 | "file_id": "1lTpHeezI7f2ts1F_hsIM5Ui-2BvuRDhP", 10 | "timestamp": 1735658526046 11 | }, 12 | { 13 | "file_id": "1gr-BRko9gxHM_F2vs-K87_p-QcaeuR-N", 14 | "timestamp": 1716381575893 15 | } 16 | ] 17 | }, 18 | "kernelspec": { 19 | "name": "python3", 20 | "display_name": "Python 3" 21 | }, 22 | "language_info": { 23 | "name": "python" 24 | } 25 | }, 26 | "cells": [ 27 | { 28 | "cell_type": "markdown", 29 | "metadata": { 30 | "id": "S9DjDRBhhX1-" 31 | }, 32 | "source": [ 33 | "\"Open" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "source": [ 39 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 40 | "### Mike X Cohen (sincxpress.com)\n", 41 | "#### https://github.com/mikexcohen/calculus_book\n", 42 | "#### Code for Chapter 2 (functions)\n", 43 | "\n", 44 | "---\n", 45 | "\n", 46 | "# About this code file:\n", 47 | "\n", 48 | "### This notebook contains full code solutions to the exercises in this book chapter. There are many correct ways to solve the exercises; this notebook provides *a* solution, not *THE* solution. Please use this code as a starting point to continue exploring and experimenting with calculus concepts and visualizations.\n", 49 | "\n", 50 | "## **Using the code without the book may lead to confusion or errors.**\n", 51 | "\n", 52 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 53 | ], 54 | "metadata": { 55 | "id": "yeVh6hm2ezCO" 56 | } 57 | }, 58 | { 59 | "cell_type": "code", 60 | "source": [], 61 | "metadata": { 62 | "id": "9ywdeq97hBx0" 63 | }, 64 | "execution_count": null, 65 | "outputs": [] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": null, 70 | "metadata": { 71 | "id": "oYWhHwGQ9OdD" 72 | }, 73 | "outputs": [], 74 | "source": [ 75 | "# import libraries and define global settings\n", 76 | "import numpy as np\n", 77 | "import sympy as sym\n", 78 | "import matplotlib.pyplot as plt\n", 79 | "\n", 80 | "from IPython.display import Math\n", 81 | "\n", 82 | "# define global figure properties used for publication\n", 83 | "import matplotlib_inline.backend_inline\n", 84 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 85 | "plt.rcParams.update({'font.size':14, # font size\n", 86 | " 'savefig.dpi':300, # output resolution\n", 87 | " 'axes.titlelocation':'left',# title location\n", 88 | " 'axes.spines.right':False, # remove axis bounding box\n", 89 | " 'axes.spines.top':False, # remove axis bounding box\n", 90 | " 'lines.linewidth':2 # increase default line thickness\n", 91 | " })" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "source": [], 97 | "metadata": { 98 | "id": "qlnQWAGhRMXf" 99 | }, 100 | "execution_count": null, 101 | "outputs": [] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "source": [ 106 | "# Exercise 2.1" 107 | ], 108 | "metadata": { 109 | "id": "dSU7Vsj4RMbJ" 110 | } 111 | }, 112 | { 113 | "cell_type": "code", 114 | "source": [ 115 | "# circle formula:\n", 116 | "# r^2 = x^2 + y^2\n", 117 | "\n", 118 | "r = 2\n", 119 | "x = np.linspace(-r,r,13)\n", 120 | "yPos = np.sqrt(r**2 - x**2)\n", 121 | "yNeg = -np.sqrt(r**2 - x**2)\n", 122 | "\n", 123 | "_,ax = plt.subplots(1,figsize=(5,5))\n", 124 | "ax.plot(x,yPos,'ks',markersize=12,markerfacecolor='w',label=r'$f_p(x)$')\n", 125 | "ax.plot(x,yNeg,'ko',markersize=9,markerfacecolor='gray',label=r'$f_n(x)$')\n", 126 | "ax.set(xlim=[-r-.1,r+.1],ylim=[-r-.1,r+.1])\n", 127 | "ax.legend()\n", 128 | "\n", 129 | "plt.savefig('funs_ex1.png')\n", 130 | "plt.show()" 131 | ], 132 | "metadata": { 133 | "id": "YBdvlzDKzyjL", 134 | "collapsed": true 135 | }, 136 | "execution_count": null, 137 | "outputs": [] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "source": [], 142 | "metadata": { 143 | "id": "1uvMcILtZ3Mo" 144 | }, 145 | "execution_count": null, 146 | "outputs": [] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "source": [ 151 | "# Exercise 2.2" 152 | ], 153 | "metadata": { 154 | "id": "GWrYiTOwgNo4" 155 | } 156 | }, 157 | { 158 | "cell_type": "code", 159 | "source": [ 160 | "# function for the function (this time a lambda function)\n", 161 | "fx = lambda x : (x+1) / x**3\n", 162 | "\n", 163 | "\n", 164 | "_,ax = plt.subplots(1,figsize=(10,6))\n", 165 | "colors = [ [0,0,0], [.3,.3,.3], [.6,.6,.6] ]\n", 166 | "shapes = 'os^'\n", 167 | "\n", 168 | "for pwr in range(1,4):\n", 169 | "\n", 170 | " # resolution\n", 171 | " resolution = np.floor(np.sqrt(2)*10**pwr).astype(int) #+1\n", 172 | "\n", 173 | " # create x-axis grid\n", 174 | " x = np.linspace(-.1,.1,resolution)\n", 175 | "\n", 176 | " # plot\n", 177 | " ax.plot(x,fx(x)+pwr*1e6,color=colors[pwr-1],marker=shapes[pwr-1],\n", 178 | " markersize=10,alpha=.5,label=f'N={resolution}')\n", 179 | "\n", 180 | "# finalize figure\n", 181 | "ax.set(xlim=x[[0,-1]],ylim=[-1e7,1e7],xlabel='x',ylabel=r'$y=f(x)$')\n", 182 | "ax.set_title(r'$f(x) = (x+1)/x^3$',loc='center')\n", 183 | "ax.legend()\n", 184 | "\n", 185 | "plt.tight_layout()\n", 186 | "plt.savefig('funs_ex2.png')\n", 187 | "plt.show()" 188 | ], 189 | "metadata": { 190 | "id": "kqRrzUakgQxo" 191 | }, 192 | "execution_count": null, 193 | "outputs": [] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "source": [ 198 | "# Why the warning message about 'divide by zero'?\n", 199 | "#\n", 200 | "# That message occurs only for the N=141 case, because it is an odd number. An odd number\n", 201 | "# of numbers between x=-a and x=+a has x=0 in the middle, and for this function, x=0 gives 1/0.\n", 202 | "# With an even resolution, you don't get exactly x=0 as a data point.\n", 203 | "#\n", 204 | "# Observe:\n", 205 | "print( np.linspace(-1,1,9) )\n", 206 | "print( np.linspace(-1,1,10) )" 207 | ], 208 | "metadata": { 209 | "id": "7i3mukxmuIi_" 210 | }, 211 | "execution_count": null, 212 | "outputs": [] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "source": [], 217 | "metadata": { 218 | "id": "BscE_NhPgNlz" 219 | }, 220 | "execution_count": null, 221 | "outputs": [] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "source": [ 226 | "# Exercise 2.3" 227 | ], 228 | "metadata": { 229 | "id": "4ksDYILqNZPX" 230 | } 231 | }, 232 | { 233 | "cell_type": "code", 234 | "source": [ 235 | "# approximate the sqrt 2\n", 236 | "nIters = 5\n", 237 | "\n", 238 | "sqrt2 = np.full(nIters+1,1.) # start at sqrt(2)=1\n", 239 | "\n", 240 | "print(' n :: Approx. :: diff')\n", 241 | "print('...............................')\n", 242 | "\n", 243 | "for i in range(1,nIters+1):\n", 244 | " sqrt2[i] = (sqrt2[i-1] + 2/sqrt2[i-1])/2\n", 245 | " print(f' {i} :: {sqrt2[i]:.6f} :: {sqrt2[i]-np.sqrt(2):>10.6f}')" 246 | ], 247 | "metadata": { 248 | "id": "JZ1AZnZoP5oe" 249 | }, 250 | "execution_count": null, 251 | "outputs": [] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "source": [ 256 | "startvals = np.logspace(np.log10(.5),np.log10(2),10)\n", 257 | "\n", 258 | "sqrt2mat = np.zeros((nIters+1,len(startvals)))\n", 259 | "\n", 260 | "plt.figure(figsize=(8,4))\n", 261 | "for starti,a_s in enumerate(startvals):\n", 262 | "\n", 263 | " # initialize\n", 264 | " sqrt2mat[0,starti] = a_s\n", 265 | "\n", 266 | " # algorithm\n", 267 | " for i in range(1,nIters+1):\n", 268 | " sqrt2mat[i,starti] = (sqrt2mat[i-1,starti] + 2/sqrt2mat[i-1,starti])/2\n", 269 | "\n", 270 | " # plot\n", 271 | " c = (starti+1)/(len(startvals)+2)\n", 272 | " plt.plot(sqrt2mat[:,starti],'o-',color=[c,c,c],markerfacecolor=[c,c,c],\n", 273 | " label=rf'$a_s$={a_s:.2f}')\n", 274 | "\n", 275 | "\n", 276 | "plt.xlabel('Iteration number')\n", 277 | "plt.ylabel(r'Estimate of $\\sqrt{2}$')\n", 278 | "plt.legend(bbox_to_anchor=[1.02,1.02])\n", 279 | "\n", 280 | "plt.tight_layout()\n", 281 | "plt.savefig('funs_ex3.png')\n", 282 | "plt.show()" 283 | ], 284 | "metadata": { 285 | "id": "AciMA_KdP3Fl" 286 | }, 287 | "execution_count": null, 288 | "outputs": [] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "source": [], 293 | "metadata": { 294 | "id": "uf2pMQBqNZJF" 295 | }, 296 | "execution_count": null, 297 | "outputs": [] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "source": [ 302 | "# Exercise 2.4" 303 | ], 304 | "metadata": { 305 | "id": "uo8WYKtkNZGO" 306 | } 307 | }, 308 | { 309 | "cell_type": "code", 310 | "source": [ 311 | "x = np.linspace(-2,3,21)\n", 312 | "\n", 313 | "# function pair 1\n", 314 | "f1a = x[:]\n", 315 | "f1b = -x[:]\n", 316 | "\n", 317 | "# function pair 2\n", 318 | "f2a = abs(x)\n", 319 | "f2b = -abs(x)\n", 320 | "\n", 321 | "# plot both\n", 322 | "fig,axs = plt.subplots(1,2,figsize=(10,4))\n", 323 | "\n", 324 | "axs[0].plot(x,f1a,'ks',markerfacecolor=[.9,.9,.9],label=r'$f_{1a}(x) = x$')\n", 325 | "axs[0].plot(x,f1b,'ko',markerfacecolor=[.2,.2,.2],label=r'$f_{1b}(x) = -x$')\n", 326 | "axs[0].set(xlabel='x',ylabel='y')\n", 327 | "axs[0].legend()\n", 328 | "\n", 329 | "axs[1].plot(x,f2a,'ks',markerfacecolor=[.9,.9,.9],label=r'$f_{2a}(x) = |x|$')\n", 330 | "axs[1].plot(x,f2b,'ko',markerfacecolor=[.2,.2,.2],label=r'$f_{2b}(x) = -|x|$')\n", 331 | "axs[1].set(xlabel='x',ylabel='y')\n", 332 | "axs[1].legend()\n", 333 | "\n", 334 | "plt.tight_layout()\n", 335 | "plt.show()" 336 | ], 337 | "metadata": { 338 | "id": "wvnLheFkOkmA" 339 | }, 340 | "execution_count": null, 341 | "outputs": [] 342 | }, 343 | { 344 | "cell_type": "code", 345 | "source": [ 346 | "plt.figure(figsize=(4,4))\n", 347 | "plt.plot(x,f1a,'ks')\n", 348 | "plt.plot(x,f1b,'ks')\n", 349 | "plt.gca().set(xlabel='x',ylabel='y')\n", 350 | "plt.title(r'$y = \\pm x$',loc='center')\n", 351 | "\n", 352 | "plt.tight_layout()\n", 353 | "plt.savefig('funs_ex4.png')\n", 354 | "plt.show()" 355 | ], 356 | "metadata": { 357 | "id": "MnzsWkBkWCeT" 358 | }, 359 | "execution_count": null, 360 | "outputs": [] 361 | }, 362 | { 363 | "cell_type": "code", 364 | "source": [], 365 | "metadata": { 366 | "id": "5PQG8aM5NZDl" 367 | }, 368 | "execution_count": null, 369 | "outputs": [] 370 | }, 371 | { 372 | "cell_type": "markdown", 373 | "source": [ 374 | "# Exercise 2.5" 375 | ], 376 | "metadata": { 377 | "id": "GslYWPgvNZA4" 378 | } 379 | }, 380 | { 381 | "cell_type": "code", 382 | "source": [ 383 | "# a function\n", 384 | "def fun(intype,outtype):\n", 385 | "\n", 386 | " # function calculation\n", 387 | " if intype == 'int':\n", 388 | " result = int(5) * int(4) / int(3)\n", 389 | " elif intype == 'float':\n", 390 | " result = float(5) * float(4) / float(3)\n", 391 | " else:\n", 392 | " raise ValueError(f'Unsupported input type: {intype}')\n", 393 | "\n", 394 | " # output\n", 395 | " if outtype == 'int':\n", 396 | " return int(result)\n", 397 | " elif outtype == 'float':\n", 398 | " return float(result)\n", 399 | " else:\n", 400 | " raise ValueError(f'Unsupported output type: {outtype}')\n", 401 | "\n", 402 | "\n", 403 | "# test 1: inputs are floats, output is float\n", 404 | "c = fun('float','float')\n", 405 | "print(f'Inputs are floats, output is float, result is {c}')\n", 406 | "\n", 407 | "# test 2: inputs are floats, output is int\n", 408 | "c = fun('float','int')\n", 409 | "print(f'Inputs are floats, output is int, result is {c}')\n", 410 | "\n", 411 | "# test 3: inputs are ints, output is float\n", 412 | "c = fun('int','float')\n", 413 | "print(f'Inputs are ints, output is float, result is {c}')\n", 414 | "\n", 415 | "# test 4: inputs are ints, output is int\n", 416 | "c = fun('int','int')\n", 417 | "print(f'Inputs are ints, output is int, result is {c}')" 418 | ], 419 | "metadata": { 420 | "id": "sCHm6ednTB5H" 421 | }, 422 | "execution_count": null, 423 | "outputs": [] 424 | }, 425 | { 426 | "cell_type": "code", 427 | "source": [ 428 | "N = 10/2\n", 429 | "print(f'Result is {N} and is of type {type(N)}')\n", 430 | "\n", 431 | "np.linspace(0,10,N)" 432 | ], 433 | "metadata": { 434 | "id": "ByFWXf9UizHZ" 435 | }, 436 | "execution_count": null, 437 | "outputs": [] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "source": [], 442 | "metadata": { 443 | "id": "gcUttro7TB2R" 444 | }, 445 | "execution_count": null, 446 | "outputs": [] 447 | }, 448 | { 449 | "cell_type": "markdown", 450 | "source": [ 451 | "# Exercise 2.6" 452 | ], 453 | "metadata": { 454 | "id": "JohXwOWWTBzs" 455 | } 456 | }, 457 | { 458 | "cell_type": "code", 459 | "source": [ 460 | "# number of points on the x-axis\n", 461 | "npnts = 109\n", 462 | "\n", 463 | "# list containing all solutions\n", 464 | "theBigList = [\n", 465 | "# letter, type, function definition\n", 466 | " [ 'a', 'injective', lambda x: x * (x>0) ],\n", 467 | " [ 'b', 'bijective', lambda x: np.sqrt(x) ], # x>pi\n", 468 | " [ 'c', 'neither', lambda x: 2*x**2 + 3*x**2 ],\n", 469 | " [ 'd', 'injective', lambda x: np.exp(x) ],\n", 470 | " [ 'e', 'surjective', lambda x: 2*x*(3*x-1)*(4*x+1) ],\n", 471 | " [ 'f', 'surjective', lambda x: x+np.sin(x) ],\n", 472 | " [ 'g', 'bijective', lambda x: x ],\n", 473 | " [ 'h', 'bijective', lambda x: 2*x + 1 ],\n", 474 | " [ 'i', 'neither', lambda x: np.cos(x) ],\n", 475 | " [ 'j', 'injective', lambda x: np.tanh(x) ],\n", 476 | " [ 'k', 'surjective', lambda x: np.log(x) - 4*np.exp(-(x-1)**2) ], # x>0\n", 477 | " [ 'l', 'neither', lambda x: np.ones(len(x)) ]\n", 478 | "]\n", 479 | "\n", 480 | "# setup the figure\n", 481 | "_,axs = plt.subplots(3,4,figsize=(12,8))\n", 482 | "axs = axs.flatten()\n", 483 | "\n", 484 | "# loop through the list\n", 485 | "for i,(funLetter,funtype,fx) in enumerate(theBigList):\n", 486 | "\n", 487 | " # define the x-axis grid (exceptions for functions b(x) and k(x) )\n", 488 | " if funLetter=='b':\n", 489 | " xx = np.linspace(np.pi,7,npnts)\n", 490 | " elif funLetter=='k':\n", 491 | " xx = np.linspace(.001,7,npnts)\n", 492 | " else:\n", 493 | " xx = np.linspace(-2,4,npnts)\n", 494 | "\n", 495 | " # plot the function and give it a title\n", 496 | " axs[i].plot(xx,fx(xx),'k',linewidth=2)\n", 497 | " axs[i].set(xlim=xx[[0,-1]])\n", 498 | " axs[i].set_title(f'{funLetter}(x) is {funtype}',loc='center')\n", 499 | "\n", 500 | "\n", 501 | "plt.tight_layout()\n", 502 | "plt.savefig('funs_ex6.png')\n", 503 | "plt.show()" 504 | ], 505 | "metadata": { 506 | "id": "0XTi-9syQo_M" 507 | }, 508 | "execution_count": null, 509 | "outputs": [] 510 | }, 511 | { 512 | "cell_type": "code", 513 | "source": [], 514 | "metadata": { 515 | "id": "OerQoNt7DJee" 516 | }, 517 | "execution_count": null, 518 | "outputs": [] 519 | }, 520 | { 521 | "cell_type": "markdown", 522 | "source": [ 523 | "# Exercise 2.7" 524 | ], 525 | "metadata": { 526 | "id": "36JYvMuvUmD9" 527 | } 528 | }, 529 | { 530 | "cell_type": "code", 531 | "source": [ 532 | "# first create the function as a sympy object\n", 533 | "tau = sym.symbols('tau')\n", 534 | "expr = sym.log(tau) - 4*sym.exp(-(tau-1)**2)\n", 535 | "\n", 536 | "# and print it out\n", 537 | "display(Math('k(\\\\tau) = %s' %sym.latex(expr)))" 538 | ], 539 | "metadata": { 540 | "id": "gWPltGE8UmBC" 541 | }, 542 | "execution_count": null, 543 | "outputs": [] 544 | }, 545 | { 546 | "cell_type": "code", 547 | "source": [ 548 | "# get numpy output using lambdafication\n", 549 | "expr_lamb = sym.lambdify(tau,expr)\n", 550 | "expr_lamb(np.array([1,2,3]))" 551 | ], 552 | "metadata": { 553 | "id": "gUUYPcgXUl-j" 554 | }, 555 | "execution_count": null, 556 | "outputs": [] 557 | }, 558 | { 559 | "cell_type": "code", 560 | "source": [ 561 | "# and then using list comprehension\n", 562 | "np.array([ expr.subs(tau,ti).evalf() for ti in [1,2,3] ],dtype=float) # what's the difference with vs. without dtype=float?" 563 | ], 564 | "metadata": { 565 | "id": "AmOkwGk9Ul7_" 566 | }, 567 | "execution_count": null, 568 | "outputs": [] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "source": [], 573 | "metadata": { 574 | "id": "BPoDmw6AUl5O" 575 | }, 576 | "execution_count": null, 577 | "outputs": [] 578 | }, 579 | { 580 | "cell_type": "markdown", 581 | "source": [ 582 | "# Exercise 2.8" 583 | ], 584 | "metadata": { 585 | "id": "-Cq4d0oEv1-I" 586 | } 587 | }, 588 | { 589 | "cell_type": "code", 590 | "source": [ 591 | "# using sym.plot\n", 592 | "sym.plot(expr,(tau,.00001,3),ylim=[-6,1]);\n", 593 | "# note the difference between domain vs range specifications" 594 | ], 595 | "metadata": { 596 | "id": "3wclHyWQv16x" 597 | }, 598 | "execution_count": null, 599 | "outputs": [] 600 | }, 601 | { 602 | "cell_type": "code", 603 | "source": [ 604 | "# using matplotlib\n", 605 | "x = np.linspace(0,3,188)\n", 606 | "y = expr_lamb(x)\n", 607 | "\n", 608 | "plt.plot(x,y)\n", 609 | "plt.gca().set(xlim=x[[0,-1]],ylim=[-6,1])\n", 610 | "plt.show()" 611 | ], 612 | "metadata": { 613 | "id": "Gp-CgZaIwQQZ" 614 | }, 615 | "execution_count": null, 616 | "outputs": [] 617 | }, 618 | { 619 | "cell_type": "code", 620 | "source": [], 621 | "metadata": { 622 | "id": "gzYcANHz6qmi" 623 | }, 624 | "execution_count": null, 625 | "outputs": [] 626 | } 627 | ] 628 | } -------------------------------------------------------------------------------- /exercises/ch08_derivativesTheorems_exercises.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyOEZsdY2+XwKinRZIowNCxK" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 8 (Differentiation theorems)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook contains full code solutions to the exercises in this book chapter. There are many correct ways to solve the exercises; this notebook provides *a* solution, not *THE* solution. Please use this code as a starting point to continue exploring and experimenting with calculus concepts and visualizations.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "4KikZVyDDDXR" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "id": "-AqocO_QYBjQ" 55 | }, 56 | "outputs": [], 57 | "source": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "from IPython.display import Math\n", 72 | "\n", 73 | "# define global figure properties used for publication\n", 74 | "import matplotlib_inline.backend_inline\n", 75 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 76 | "plt.rcParams.update({'font.size':14, # font size\n", 77 | " 'savefig.dpi':300, # output resolution\n", 78 | " 'axes.titlelocation':'left',# title location\n", 79 | " 'axes.spines.right':False, # remove axis bounding box\n", 80 | " 'axes.spines.top':False, # remove axis bounding box\n", 81 | " 'lines.linewidth':2 # increase default line thickness\n", 82 | " })" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "source": [], 88 | "metadata": { 89 | "id": "4ZrOPLxlYmfu" 90 | }, 91 | "execution_count": null, 92 | "outputs": [] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "source": [ 97 | "# Exercise 1: An algorithm to solve the MVT" 98 | ], 99 | "metadata": { 100 | "id": "9V9KhUkEOmDm" 101 | } 102 | }, 103 | { 104 | "cell_type": "code", 105 | "source": [ 106 | "def solveMVT(f,a,c):\n", 107 | "\n", 108 | " # Step 1: compute the derivative\n", 109 | " df = sym.diff(f)\n", 110 | "\n", 111 | " # Step 2: plug in a and c\n", 112 | " f_a = f.subs(x,a)\n", 113 | " f_c = f.subs(x,c)\n", 114 | "\n", 115 | " # Step 3: compute the right-hand-side of the equation for f'(b)\n", 116 | " RHS = (f_c-f_a) / (c-a)\n", 117 | "\n", 118 | " # Step 4: solve for b\n", 119 | " b = sym.solve(df-RHS)\n", 120 | " b = np.array(b).astype(np.float64)\n", 121 | "\n", 122 | " # Step 5: return elements of b that are between a and c\n", 123 | " return b[np.bitwise_and(a let's see what we're trying to solve\n", 298 | "f_a = f.subs(x,a)\n", 299 | "f_c = f.subs(x,c)\n", 300 | "RHS = (f_c-f_a) / (c-a)\n", 301 | "\n", 302 | "# solve for b\n", 303 | "sols = sym.solve(sym.diff(f)-RHS)\n", 304 | "\n", 305 | "# let's see if any are real-valued\n", 306 | "for s in sols:\n", 307 | " print(sym.N(s))" 308 | ], 309 | "metadata": { 310 | "id": "zDTHzELim6co" 311 | }, 312 | "execution_count": null, 313 | "outputs": [] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "source": [ 318 | "# The reason the python function crashes is that it is not designed to handle\n", 319 | "# complex-valued solutions. You can see that this expression has two real-valued\n", 320 | "# solutions, on either side of x=0, which confirms what sym.plot shows.\n", 321 | "#\n", 322 | "# If you like, you can adjust the code to handle this exception and return only\n", 323 | "# real-valued solutions. I presented code for this in Chapter 6, although didn't\n", 324 | "# implement it for this exercise." 325 | ], 326 | "metadata": { 327 | "id": "Cqh-MGzYpG05" 328 | }, 329 | "execution_count": null, 330 | "outputs": [] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "source": [], 335 | "metadata": { 336 | "id": "4yQYysbSpGs8" 337 | }, 338 | "execution_count": null, 339 | "outputs": [] 340 | }, 341 | { 342 | "cell_type": "markdown", 343 | "source": [ 344 | "# Exercise 4" 345 | ], 346 | "metadata": { 347 | "id": "N8oG7TcDpp2y" 348 | } 349 | }, 350 | { 351 | "cell_type": "code", 352 | "source": [ 353 | "# \"simple\" trig function\n", 354 | "f = sym.cos(x**2)\n", 355 | "a,c = -np.pi/2,6*np.pi/7\n", 356 | "\n", 357 | "# quick plot\n", 358 | "sym.plot(f,(x,a,c))\n", 359 | "\n", 360 | "# doesn't work...\n", 361 | "MVTandPlot(f,a,c)\n", 362 | "\n", 363 | "# # why not? -> let's see what we're trying to solve\n", 364 | "# f_a = f.subs(x,a)\n", 365 | "# f_c = f.subs(x,c)\n", 366 | "# RHS = (f_c-f_a) / (c-a)\n", 367 | "\n", 368 | "# # the expression to solve for\n", 369 | "# sym.diff(f)-RHS" 370 | ], 371 | "metadata": { 372 | "id": "zuITdPPVOmLh" 373 | }, 374 | "execution_count": null, 375 | "outputs": [] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "source": [ 380 | "sym.solve(sym.diff(f)-RHS)" 381 | ], 382 | "metadata": { 383 | "id": "SmOJk6m0mkNs" 384 | }, 385 | "execution_count": null, 386 | "outputs": [] 387 | }, 388 | { 389 | "cell_type": "code", 390 | "source": [], 391 | "metadata": { 392 | "id": "DVtzFAC92amB" 393 | }, 394 | "execution_count": null, 395 | "outputs": [] 396 | }, 397 | { 398 | "cell_type": "markdown", 399 | "source": [ 400 | "# Exercise 5: Approximate a solution in numpy" 401 | ], 402 | "metadata": { 403 | "id": "y6lR2S7H2a6w" 404 | } 405 | }, 406 | { 407 | "cell_type": "code", 408 | "source": [ 409 | "# lambdify the function\n", 410 | "mvt_fun = sym.lambdify(x,sym.diff(f)-RHS) # variable 'f' is from previous exercise\n", 411 | "\n", 412 | "# high-res approximation\n", 413 | "xx = np.linspace(a,c,10001)\n", 414 | "gridSearch = mvt_fun(xx)\n", 415 | "\n", 416 | "\n", 417 | "# find critical points\n", 418 | "from scipy.signal import find_peaks\n", 419 | "critMinima = find_peaks(-np.abs(gridSearch))[0]\n", 420 | "b = np.array([])\n", 421 | "for i in critMinima:\n", 422 | " if np.sign(gridSearch[i-1]) + np.sign(gridSearch[i+1]) == 0:\n", 423 | " b = np.append(b,xx[i])\n", 424 | "\n", 425 | "\n", 426 | "\n", 427 | "# visualize the approximation\n", 428 | "plt.figure(figsize=(9,4))\n", 429 | "plt.plot(xx[[0,-1]],[0,0],'--',label='Solutions touch this line',color='gray')\n", 430 | "plt.plot(xx,gridSearch,':',color=[.7,.7,.7],label=\"MVT objective\")\n", 431 | "plt.plot(xx,np.abs(gridSearch),'k',label=\"|MVT objective|\")\n", 432 | "plt.plot(b,mvt_fun(b),'ko',markersize=9,markerfacecolor='w',label='Solutions')\n", 433 | "\n", 434 | "plt.legend()\n", 435 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='x',ylabel='y')\n", 436 | "\n", 437 | "plt.tight_layout()\n", 438 | "plt.savefig('diffTheorems_ex5a.png')\n", 439 | "plt.show()" 440 | ], 441 | "metadata": { 442 | "id": "Z53f-Tzd19yi" 443 | }, 444 | "execution_count": null, 445 | "outputs": [] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "source": [ 450 | "# convert to function\n", 451 | "funLambda = sym.lambdify(x,f)\n", 452 | "funLambda_df = sym.lambdify(x,sym.diff(f))\n", 453 | "\n", 454 | "# get the function values\n", 455 | "xx = np.linspace(a-2,c+2,400)\n", 456 | "yy = funLambda(xx)\n", 457 | "\n", 458 | "\n", 459 | "# set up the figure\n", 460 | "plt.figure(figsize=(12,5))\n", 461 | "\n", 462 | "# plot the function\n", 463 | "plt.plot(xx,yy,'k',label='f(x)')\n", 464 | "\n", 465 | "# plot dots for a & c\n", 466 | "plt.plot([a,c],funLambda(np.array([a,c])),'ko',markerfacecolor='w',markersize=9)\n", 467 | "\n", 468 | "# plot secant line\n", 469 | "plt.plot([a,c],[funLambda(a),funLambda(c)],':',color=[.7,.7,.7],label='Secant',zorder=-4)\n", 470 | "\n", 471 | "# plot the tangent lines\n", 472 | "for i,bb in enumerate(b):\n", 473 | "\n", 474 | " # plot the points\n", 475 | " plt.plot(bb,funLambda(bb),'ks',markerfacecolor='gray',markersize=8)\n", 476 | "\n", 477 | " # create and plot a tangent line with slope = f'\n", 478 | " tangX = [bb-1,bb+1]\n", 479 | " tangY = funLambda_df(bb)*(np.array(tangX)-bb) + funLambda(bb)\n", 480 | " plt.plot(tangX,tangY,'k--',label=f'tangent$_{i}$',zorder=-10)\n", 481 | "\n", 482 | "# make the plot look a bit nicer\n", 483 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='x',ylim=[-1.2,1.2],ylabel=r'$y=f(x)$')\n", 484 | "plt.legend(bbox_to_anchor=(1,1))\n", 485 | "plt.title(f'$f(x) = {sym.latex(f)}$',loc='center')\n", 486 | "\n", 487 | "plt.tight_layout()\n", 488 | "plt.savefig('diffTheorems_ex5b.png')\n", 489 | "plt.show()" 490 | ], 491 | "metadata": { 492 | "id": "QCgbh76C1-Aa" 493 | }, 494 | "execution_count": null, 495 | "outputs": [] 496 | }, 497 | { 498 | "cell_type": "code", 499 | "source": [], 500 | "metadata": { 501 | "id": "zhjLdJZALGBX", 502 | "collapsed": true 503 | }, 504 | "execution_count": null, 505 | "outputs": [] 506 | }, 507 | { 508 | "cell_type": "markdown", 509 | "source": [ 510 | "# Exercise 8.6: Rolle's theorem" 511 | ], 512 | "metadata": { 513 | "id": "fChZEiLL3XwK" 514 | } 515 | }, 516 | { 517 | "cell_type": "code", 518 | "source": [ 519 | "# the function\n", 520 | "x = sym.symbols('x',real=True)\n", 521 | "fx = sym.Abs(sym.sin(x))\n", 522 | "\n", 523 | "# the bounds\n", 524 | "a = np.pi/2\n", 525 | "c = 3*np.pi/2\n", 526 | "\n", 527 | "# step 1: confirm that f(a)=f(c)\n", 528 | "display(Math('f(x) = %s' %sym.latex(fx))), print('')\n", 529 | "display(Math('f\\\\left(%s\\\\right) = %s' %(sym.latex(a),sym.latex(fx.subs(x,a))))), print('')\n", 530 | "display(Math('f\\\\left(%s\\\\right) = %s' %(sym.latex(c),sym.latex(fx.subs(x,c)))))" 531 | ], 532 | "metadata": { 533 | "id": "4Ggrufka3bbT" 534 | }, 535 | "execution_count": null, 536 | "outputs": [] 537 | }, 538 | { 539 | "cell_type": "code", 540 | "source": [ 541 | "# step 2: find the derivative\n", 542 | "df = sym.diff(fx)\n", 543 | "display(Math(\"f'(x) = %s\" %sym.latex(df))), print('')\n", 544 | "\n", 545 | "# and solve for f'=0\n", 546 | "b = sym.solve(df)[0]\n", 547 | "display(Math(\"f'(%s) = %s\" %(b,df.subs(x,b))))" 548 | ], 549 | "metadata": { 550 | "id": "6ESUU2OP3bbY" 551 | }, 552 | "execution_count": null, 553 | "outputs": [] 554 | }, 555 | { 556 | "cell_type": "code", 557 | "source": [ 558 | "# let's see the function!\n", 559 | "sym.plot(fx,(x,a,c));" 560 | ], 561 | "metadata": { 562 | "id": "cqrEsmgQ6pam" 563 | }, 564 | "execution_count": null, 565 | "outputs": [] 566 | }, 567 | { 568 | "cell_type": "code", 569 | "source": [ 570 | "# Based on the plot, finding the minimum is easy:\n", 571 | "\n", 572 | "# lambdify the function\n", 573 | "fx_lam = sym.lambdify(x,fx)\n", 574 | "\n", 575 | "# grid search\n", 576 | "xx = np.linspace(a,c,2531)\n", 577 | "b = xx[ np.argmin(fx_lam(xx)) ]\n", 578 | "\n", 579 | "print(b) # it's pi :)" 580 | ], 581 | "metadata": { 582 | "id": "yZqzCjOG7HyB" 583 | }, 584 | "execution_count": null, 585 | "outputs": [] 586 | }, 587 | { 588 | "cell_type": "code", 589 | "source": [ 590 | "# lambdify the function\n", 591 | "fx_lam = sym.lambdify(x,fx)\n", 592 | "\n", 593 | "# plot\n", 594 | "xx = np.linspace(0,2*np.pi,253)\n", 595 | "\n", 596 | "plt.figure(figsize=(9,3))\n", 597 | "\n", 598 | "plt.plot(xx,fx_lam(xx),'k',label=r'$f(x)=%s$'%sym.latex(fx))\n", 599 | "plt.plot(a,fx_lam(a),'ko',markerfacecolor='gray',markersize=11,label='a')\n", 600 | "plt.plot(c,fx_lam(c),'ks',markerfacecolor='gray',markersize=11,label='c')\n", 601 | "plt.plot(b,fx_lam(b),'kv',markerfacecolor='gray',markersize=11,label='b')\n", 602 | "\n", 603 | "\n", 604 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='x',ylabel='y = f(x)')\n", 605 | "plt.legend()\n", 606 | "\n", 607 | "plt.tight_layout()\n", 608 | "plt.savefig('diffTheorems_ex6.png')\n", 609 | "plt.show()" 610 | ], 611 | "metadata": { 612 | "id": "11uaUdHO3bbY" 613 | }, 614 | "execution_count": null, 615 | "outputs": [] 616 | }, 617 | { 618 | "cell_type": "code", 619 | "source": [], 620 | "metadata": { 621 | "id": "FJpo5Rhqfrq-" 622 | }, 623 | "execution_count": null, 624 | "outputs": [] 625 | }, 626 | { 627 | "cell_type": "markdown", 628 | "source": [ 629 | "# Exercise 8.7" 630 | ], 631 | "metadata": { 632 | "id": "FK_abLtSfroK" 633 | } 634 | }, 635 | { 636 | "cell_type": "code", 637 | "source": [ 638 | "x = np.linspace(0,10*np.pi,1001)\n", 639 | "yc = x + 0\n", 640 | "ys = x + 0\n", 641 | "\n", 642 | "_,axs = plt.subplots(1,3,figsize=(12,4))\n", 643 | "\n", 644 | "for i in range(10):\n", 645 | "\n", 646 | " yc = np.cos(yc)\n", 647 | " ys = np.sin(ys)\n", 648 | "\n", 649 | " axs[0].plot(x,yc,color=np.full(3,10/12-i/12))\n", 650 | " axs[1].plot(x,ys,color=np.full(3,10/12-i/12))\n", 651 | " axs[2].plot(yc,ys,color=np.full(3,10/12-i/12))\n", 652 | "\n", 653 | "\n", 654 | "axs[0].set(title=r'$\\bf{A}$) Iterative cosines',xlabel='$\\\\theta$',ylabel='y',xlim=x[[0,-1]])\n", 655 | "axs[1].set(title=r'$\\bf{B}$) Iterative sines',xlabel='$\\\\theta$',ylabel='y',xlim=x[[0,-1]])\n", 656 | "axs[2].set(title=r'$\\bf{C}$) cos by sin',xlabel='Cosines',ylabel='Sines')\n", 657 | "\n", 658 | "plt.tight_layout()\n", 659 | "plt.savefig('diffTheorems_ex7.png')\n", 660 | "plt.show()" 661 | ], 662 | "metadata": { 663 | "id": "4XVGHjvS3XjV" 664 | }, 665 | "execution_count": null, 666 | "outputs": [] 667 | }, 668 | { 669 | "cell_type": "code", 670 | "source": [], 671 | "metadata": { 672 | "id": "v-p6c8wZNgJz" 673 | }, 674 | "execution_count": null, 675 | "outputs": [] 676 | } 677 | ] 678 | } -------------------------------------------------------------------------------- /exercises/ch12_integrationIntuition_exercises.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyMnlTx0ejklBC8BOfudHy0F" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 12 (Intuition for integration)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook contains full code solutions to the exercises in this book chapter. There are many correct ways to solve the exercises; this notebook provides *a* solution, not *THE* solution. Please use this code as a starting point to continue exploring and experimenting with calculus concepts and visualizations.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "4KikZVyDDDXR" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "_jLEBlAjAbwW" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "\n", 72 | "# define global figure properties used for publication\n", 73 | "import matplotlib_inline.backend_inline\n", 74 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 75 | "plt.rcParams.update({'font.size':14, # font size\n", 76 | " 'savefig.dpi':300, # output resolution\n", 77 | " 'axes.titlelocation':'left',# title location\n", 78 | " 'axes.spines.right':False, # remove axis bounding box\n", 79 | " 'axes.spines.top':False, # remove axis bounding box\n", 80 | " 'lines.linewidth':2 # increase default line thickness\n", 81 | " })" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "source": [], 87 | "metadata": { 88 | "id": "N6Lx2V2IT9aZ" 89 | }, 90 | "execution_count": null, 91 | "outputs": [] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "source": [ 96 | "# Exercise 12.1: Cumulative sum" 97 | ], 98 | "metadata": { 99 | "id": "65YKuSyOT9XU" 100 | } 101 | }, 102 | { 103 | "cell_type": "code", 104 | "source": [ 105 | "numbers = np.arange(1,11)\n", 106 | "\n", 107 | "# initialize\n", 108 | "cumsum1 = np.zeros(len(numbers),dtype=int)\n", 109 | "cumsum2 = np.zeros(len(numbers),dtype=int)\n", 110 | "\n", 111 | "# option 1: summing the original vector from the beginning to each index\n", 112 | "for i in range(len(numbers)):\n", 113 | " cumsum1[i] = np.sum( numbers[:i+1] )\n", 114 | "\n", 115 | "# option 2: summing the previous value from the cumulative sum vector with the current value of the original vector\n", 116 | "cumsum2[0] = numbers[0]\n", 117 | "for i in range(1,len(numbers)):\n", 118 | " cumsum2[i] = cumsum2[i-1] + numbers[i]\n", 119 | "\n", 120 | "# option 3: list comprehension without numpy\n", 121 | "cumsum3 = [ sum(numbers[:i+1]) for i in range(len(numbers)) ]\n", 122 | "\n", 123 | "\n", 124 | "# print the results\n", 125 | "print('Option 1:')\n", 126 | "print(cumsum1), print('')\n", 127 | "\n", 128 | "print('Option 2:')\n", 129 | "print(cumsum2), print('')\n", 130 | "\n", 131 | "print('Option 3:')\n", 132 | "print(cumsum3), print('')\n", 133 | "\n", 134 | "print('Using np.cumsum:')\n", 135 | "print(np.cumsum(numbers))" 136 | ], 137 | "metadata": { 138 | "id": "xSaQcuguvbLk" 139 | }, 140 | "execution_count": null, 141 | "outputs": [] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "source": [], 146 | "metadata": { 147 | "id": "EAv_aI5WmXFL" 148 | }, 149 | "execution_count": null, 150 | "outputs": [] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "source": [ 155 | "# Exercise 12.2: Functions to compute and plot the integral" 156 | ], 157 | "metadata": { 158 | "id": "pgpCVQC5HbEr" 159 | } 160 | }, 161 | { 162 | "cell_type": "code", 163 | "source": [ 164 | "# create a function that computes and outputs the derivative and integral\n", 165 | "def derivAndIntegral(x,fx):\n", 166 | "\n", 167 | " # difference (discrete derivative)\n", 168 | " dx = x[1] - x[0]\n", 169 | " df = np.diff(fx) / dx\n", 170 | " df = np.append(df,df[-1])\n", 171 | "\n", 172 | " # cumulative sum (discrete integral)\n", 173 | " idf = np.cumsum(df) * dx\n", 174 | "\n", 175 | " # normalize the function\n", 176 | " zeroIdx = np.argmin(abs(x)) # x-array index of x=0\n", 177 | " idf -= idf[zeroIdx] # normalize so that idf(0)=0\n", 178 | " idf += fx[zeroIdx] # then add constant from original function\n", 179 | "\n", 180 | " # return the calculations\n", 181 | " return df,idf" 182 | ], 183 | "metadata": { 184 | "id": "F0LtlA4VBU11" 185 | }, 186 | "execution_count": null, 187 | "outputs": [] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "source": [ 192 | "### Confirm by creating the table\n", 193 | "\n", 194 | "# x-axis grid and function\n", 195 | "x = np.linspace(-1,4,6)\n", 196 | "fx = x**2\n", 197 | "\n", 198 | "df,idf = derivAndIntegral(x,fx)\n", 199 | "\n", 200 | "\n", 201 | "# header row\n", 202 | "print(' x | fx | df | idf')\n", 203 | "print('-----------------------------------')\n", 204 | "\n", 205 | "# now for the results\n", 206 | "for i in range(len(x)):\n", 207 | " print(f'{x[i]:>5.2f} | {fx[i]:>5.2f} | {df[i]:>5.2f} | {idf[i]:>5.2f}')\n" 208 | ], 209 | "metadata": { 210 | "id": "8Nu4dOoQVyHu" 211 | }, 212 | "execution_count": null, 213 | "outputs": [] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "source": [], 218 | "metadata": { 219 | "id": "B3hbW0d5VyFB" 220 | }, 221 | "execution_count": null, 222 | "outputs": [] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "source": [ 227 | "# Exercise 12.3: Visualize the approximations" 228 | ], 229 | "metadata": { 230 | "id": "SUwBTGx8fZHo" 231 | } 232 | }, 233 | { 234 | "cell_type": "code", 235 | "source": [ 236 | "# define a function to visualize\n", 237 | "\n", 238 | "# this corresponds to Figure 12.7\n", 239 | "x = np.linspace(-1,4,27)\n", 240 | "fx = x**2\n", 241 | "\n", 242 | "\n", 243 | "# the first additional suggestion\n", 244 | "# x = np.linspace(-1,4,73)\n", 245 | "# fx = x**3 + 4\n", 246 | "\n", 247 | "\n", 248 | "# second suggestion\n", 249 | "# x = np.linspace(-np.pi,np.pi,93)\n", 250 | "# fx = x**3/10 - np.pi*np.exp(-x**2) + np.sin(4*x)\n", 251 | "\n", 252 | "\n", 253 | "# apply the function\n", 254 | "df,idf = derivAndIntegral(x,fx)" 255 | ], 256 | "metadata": { 257 | "id": "k5xPvRPFgTxA" 258 | }, 259 | "execution_count": null, 260 | "outputs": [] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "source": [ 265 | "_,axs = plt.subplots(1,3,figsize=(12,3.5))\n", 266 | "\n", 267 | "# visualize the function (note: panel title is hard-coded to x**2)\n", 268 | "axs[0].plot(x,fx,'ks',markerfacecolor='w',markersize=10,linewidth=2,alpha=.5)\n", 269 | "axs[0].set(xlabel='$x$',ylabel='$y = f(x)$',title=r'$\\bf{A}$) $f(x) = x^2$')\n", 270 | "\n", 271 | "# visualize the derivative\n", 272 | "axs[1].plot(x[:-1],df[:-1],'ko',markerfacecolor='w',markersize=10,linewidth=2,alpha=.5)\n", 273 | "axs[1].set(xlabel='$x$',ylabel='$\\Delta y/\\Delta x$',title=r\"$\\bf{B}$) Approx. derivative\")\n", 274 | "\n", 275 | "# visualize the integral of the derivative\n", 276 | "axs[2].plot(x,idf,'k^',markerfacecolor='w',markersize=10,linewidth=2,label='Approx. integral',alpha=.5)\n", 277 | "\n", 278 | "# and plot the original function underneath\n", 279 | "axs[2].plot(x,fx,'k',linewidth=3,label='Orig. func.',zorder=-3)\n", 280 | "axs[2].set(xlabel='$x$',ylabel=r'$y = f(x) $ or $\\sum df/dx$',title=r\"$\\bf{C}$) Function reconstruction\")\n", 281 | "axs[2].legend()\n", 282 | "\n", 283 | "plt.tight_layout()\n", 284 | "plt.savefig('intint_FTC1a.png')\n", 285 | "plt.show()" 286 | ], 287 | "metadata": { 288 | "id": "fa4TV-aymj1F" 289 | }, 290 | "execution_count": null, 291 | "outputs": [] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "source": [], 296 | "metadata": { 297 | "id": "eF9cmXCRmjxd" 298 | }, 299 | "execution_count": null, 300 | "outputs": [] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "source": [ 305 | " # Exercise 12.4: Geometric approximation" 306 | ], 307 | "metadata": { 308 | "id": "H3t88VETV5Ck" 309 | } 310 | }, 311 | { 312 | "cell_type": "code", 313 | "source": [ 314 | "# function for the function\n", 315 | "def fx(u):\n", 316 | " return u**2 - .5" 317 | ], 318 | "metadata": { 319 | "id": "Z2UimTu7d6DG" 320 | }, 321 | "execution_count": null, 322 | "outputs": [] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "source": [ 327 | "# define dx\n", 328 | "dx = .2\n", 329 | "\n", 330 | "# plot the function\n", 331 | "plt.figure(figsize=(5,5))\n", 332 | "\n", 333 | "\n", 334 | "# define the resolution\n", 335 | "xx = np.arange(-.5,1+dx,dx)\n", 336 | "\n", 337 | "# define the function\n", 338 | "y = fx(xx)\n", 339 | "\n", 340 | "# plot the function\n", 341 | "plt.plot(xx,y,'ks-',linewidth=2,markersize=10,markerfacecolor=[.4,.4,.4])\n", 342 | "\n", 343 | "\n", 344 | "\n", 345 | "# initialize area\n", 346 | "area = 0\n", 347 | "\n", 348 | "# plot rectangles\n", 349 | "for xi in xx:\n", 350 | "\n", 351 | " # draw the rectangle\n", 352 | " plt.fill_between([xi-dx/2,xi+dx/2],[fx(xi),fx(xi)],edgecolor='k',facecolor=[.9,.9,.9])\n", 353 | "\n", 354 | " # sum the area\n", 355 | " area += abs(fx(xi)*dx)\n", 356 | "\n", 357 | "# set the labels (after the for-loop)\n", 358 | "plt.gca().set(xlabel='x',ylabel=r'$y = x^2-.5$')\n", 359 | "plt.title(r'Area = %.3f when $\\Delta$x=%g' %(area,dx),loc='center')\n", 360 | "\n", 361 | "# finalize plot\n", 362 | "plt.tight_layout()\n", 363 | "plt.savefig('intint_ex4.png')\n", 364 | "plt.show()" 365 | ], 366 | "metadata": { 367 | "id": "8rTKq3god6DG" 368 | }, 369 | "execution_count": null, 370 | "outputs": [] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "source": [], 375 | "metadata": { 376 | "id": "_T8MgQ1vV8yo" 377 | }, 378 | "execution_count": null, 379 | "outputs": [] 380 | }, 381 | { 382 | "cell_type": "markdown", 383 | "source": [ 384 | "# Exercise 12.5: Improving approximations by decreasing dx" 385 | ], 386 | "metadata": { 387 | "id": "_Ku5FiYTV9Bc" 388 | } 389 | }, 390 | { 391 | "cell_type": "code", 392 | "source": [ 393 | "# analytical area calculated in sympy (more about this in the next chapter)\n", 394 | "sx = sym.symbols('sx')\n", 395 | "symArea = sym.integrate(sym.Abs(sx**2-.5),(sx,-.5,1.1))\n", 396 | "\n", 397 | "print('Exact area: ',symArea)\n", 398 | "print('numpy approx.: ',area) # from exercise 4" 399 | ], 400 | "metadata": { 401 | "id": "YA7EPNRyiJp4" 402 | }, 403 | "execution_count": null, 404 | "outputs": [] 405 | }, 406 | { 407 | "cell_type": "code", 408 | "source": [ 409 | "# resolutions\n", 410 | "dxs = np.logspace(np.log10(.5),np.log10(.001),20)\n", 411 | "areas = np.zeros(len(dxs))\n", 412 | "\n", 413 | "# function bounds\n", 414 | "bounds = [-.5,1.1]\n", 415 | "\n", 416 | "# loop over resolutions\n", 417 | "for i,dx in enumerate(dxs):\n", 418 | "\n", 419 | " # x-axis grid\n", 420 | " xx = np.arange(bounds[0],bounds[1]+dx,dx)\n", 421 | "\n", 422 | " # compute area using rectangle area formula\n", 423 | " area_tmp = 0\n", 424 | " for xi in xx: area_tmp += abs(fx(xi)*dx)\n", 425 | "\n", 426 | " # store final result\n", 427 | " areas[i] = area_tmp" 428 | ], 429 | "metadata": { 430 | "id": "CDn086heTzlx" 431 | }, 432 | "execution_count": null, 433 | "outputs": [] 434 | }, 435 | { 436 | "cell_type": "code", 437 | "source": [ 438 | "_,ax = plt.subplots(1,figsize=(8,4))\n", 439 | "\n", 440 | "# plot the results\n", 441 | "ax.plot(dxs,areas,'ks-',linewidth=2,markerfacecolor='w',markersize=10,label='Approximations')\n", 442 | "ax.axvline(.2, linestyle=':',color=[.7,.7,.7],zorder=-1,label=r'$\\Delta x$ in Exercise 3')\n", 443 | "ax.axhline(symArea,linestyle='--',color='k',label='Exact value')\n", 444 | "\n", 445 | "ax.invert_xaxis()\n", 446 | "ax.set_xscale('log')\n", 447 | "ax.set(xlabel=r'$\\Delta x$',ylabel='Area (definite integral)')\n", 448 | "ax.legend()\n", 449 | "\n", 450 | "plt.tight_layout()\n", 451 | "plt.savefig('intint_ex5.png')\n", 452 | "plt.show()" 453 | ], 454 | "metadata": { 455 | "id": "f9W0dXBJTzjF" 456 | }, 457 | "execution_count": null, 458 | "outputs": [] 459 | }, 460 | { 461 | "cell_type": "code", 462 | "source": [], 463 | "metadata": { 464 | "id": "WOXBuwwQczWe" 465 | }, 466 | "execution_count": null, 467 | "outputs": [] 468 | } 469 | ] 470 | } -------------------------------------------------------------------------------- /exercises/ch16_integrationTechniques_exercises.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyMOPAjzjvWf5phbMChWhXXU" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 16 (Integration techniques)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook contains full code solutions to the exercises in this book chapter. There are many correct ways to solve the exercises; this notebook provides *a* solution, not *THE* solution. Please use this code as a starting point to continue exploring and experimenting with calculus concepts and visualizations.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "4KikZVyDDDXR" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "fO3nzUazCUN2" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import scipy.integrate as spi\n", 71 | "import matplotlib.pyplot as plt\n", 72 | "from IPython.display import Math\n", 73 | "\n", 74 | "# define global figure properties used for publication\n", 75 | "import matplotlib_inline.backend_inline\n", 76 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 77 | "plt.rcParams.update({'font.size':14, # font size\n", 78 | " 'savefig.dpi':300, # output resolution\n", 79 | " 'axes.titlelocation':'left',# title location\n", 80 | " 'axes.spines.right':False, # remove axis bounding box\n", 81 | " 'axes.spines.top':False, # remove axis bounding box\n", 82 | " 'lines.linewidth':2 # increase default line thickness\n", 83 | " })" 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "source": [], 89 | "metadata": { 90 | "id": "8lwxjMICKChw" 91 | }, 92 | "execution_count": null, 93 | "outputs": [] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "source": [ 98 | "# Exercise 16.1-2: Integration by parts in sympy" 99 | ], 100 | "metadata": { 101 | "id": "Yea0EGgwK2vl" 102 | } 103 | }, 104 | { 105 | "cell_type": "code", 106 | "source": [ 107 | "x,C = sym.symbols('x,C')\n", 108 | "\n", 109 | "fx = x*sym.cos(x)\n", 110 | "# fx = sym.exp(-x*sym.pi)*sym.sin(7*x) # for exercise 2\n", 111 | "antideriv = sym.integrate(fx)\n", 112 | "\n", 113 | "# show the result using latex\n", 114 | "display(Math('%s = %s+C' %(sym.latex(sym.Integral(fx)),sym.latex(antideriv))))" 115 | ], 116 | "metadata": { 117 | "id": "ubSJ0h4zoSMR" 118 | }, 119 | "execution_count": null, 120 | "outputs": [] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "source": [ 125 | "# discretize the function\n", 126 | "xx = np.linspace(-2*np.pi,3*np.pi,803)\n", 127 | "y = [fx.subs(x,xi) for xi in xx]\n", 128 | "F = [antideriv.subs(x,xi) for xi in xx]\n", 129 | "\n", 130 | "# and make some lovely plots :)\n", 131 | "_,axs = plt.subplots(1,2,figsize=(10,4))\n", 132 | "\n", 133 | "axs[0].plot(y,F,'k',linewidth=4)\n", 134 | "axs[0].set(xlabel='f(x)',ylabel='F(x)')\n", 135 | "axs[1].scatter(y,F,s=30,c=xx,cmap='gist_ncar') # FYI: https://matplotlib.org/stable/users/explain/colors/colormaps.html\n", 136 | "axs[1].axis('off')\n", 137 | "\n", 138 | "plt.tight_layout()\n", 139 | "plt.savefig('intTech_ex1.png')\n", 140 | "plt.show()" 141 | ], 142 | "metadata": { 143 | "id": "f7LfEZS8oWIQ" 144 | }, 145 | "execution_count": null, 146 | "outputs": [] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "source": [], 151 | "metadata": { 152 | "id": "6Hk0ufEf9jX7" 153 | }, 154 | "execution_count": null, 155 | "outputs": [] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "source": [ 160 | "# Exercise 16.3" 161 | ], 162 | "metadata": { 163 | "id": "HClQzA6X_wPX" 164 | } 165 | }, 166 | { 167 | "cell_type": "code", 168 | "source": [ 169 | "x,A,B = sym.symbols('x,A,B')\n", 170 | "\n", 171 | "# function\n", 172 | "fx = (5*x+3) / (2*x**2 - 4*x - 6)\n", 173 | "\n", 174 | "# quickie-plot\n", 175 | "sym.plot(fx,(x,-5,5),ylim=[-20,20])\n", 176 | "plt.show()\n", 177 | "\n", 178 | "display(Math('f(x) = %s' %sym.latex(fx)))\n", 179 | "print('')\n", 180 | "display(Math('\\int f(x) \\,dx = \\,?'))" 181 | ], 182 | "metadata": { 183 | "id": "rFB6-Bcd9X-1" 184 | }, 185 | "execution_count": null, 186 | "outputs": [] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "source": [ 191 | "# Step 1: separate numerator and denominator\n", 192 | "numerator, denominator = fx.as_numer_denom()\n", 193 | "\n", 194 | "# and print\n", 195 | "display(Math('\\\\text{The numerator is } %s' %sym.latex(numerator)))\n", 196 | "display(Math('\\\\text{The denominator is } %s' %sym.latex(denominator)))" 197 | ], 198 | "metadata": { 199 | "id": "jbjr0c1gB6TY" 200 | }, 201 | "execution_count": null, 202 | "outputs": [] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "source": [ 207 | "# Step 2: factor the denominator\n", 208 | "den_factors = sym.factor(denominator)\n", 209 | "\n", 210 | "# print them out\n", 211 | "for i,fact in enumerate(den_factors.args):\n", 212 | " display(Math('\\\\text{Demoninator factor } %g: \\; %s' %(i+1,sym.latex(fact))))\n", 213 | " print('')" 214 | ], 215 | "metadata": { 216 | "id": "BHHAmaEjB6QT" 217 | }, 218 | "execution_count": null, 219 | "outputs": [] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "source": [ 224 | "# Step 3: create simple fractions\n", 225 | "simple_fract_1 = A / (den_factors.args[0]*den_factors.args[1])\n", 226 | "simple_fract_2 = B / den_factors.args[2]\n", 227 | "\n", 228 | "display(Math('\\\\text{Simple fraction 1:} \\; %s' %sym.latex(simple_fract_1)))\n", 229 | "print('')\n", 230 | "display(Math('\\\\text{Simple fraction 2:} \\; %s' %sym.latex(simple_fract_2)))" 231 | ], 232 | "metadata": { 233 | "id": "e2iO8HlaLrOm" 234 | }, 235 | "execution_count": null, 236 | "outputs": [] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "source": [ 241 | "# Step 4: solve for A and B\n", 242 | "expression = sym.Eq(numerator , simple_fract_1*sym.prod(den_factors.args) + simple_fract_2*sym.prod(den_factors.args) )\n", 243 | "solutionsAB = sym.solve(expression,(A,B))\n", 244 | "\n", 245 | "solutionsAB" 246 | ], 247 | "metadata": { 248 | "id": "DfN7pGP_B6NZ" 249 | }, 250 | "execution_count": null, 251 | "outputs": [] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "source": [ 256 | "# Step 5: integrate separately\n", 257 | "intPart1 = sym.integrate( simple_fract_1.subs(A,solutionsAB[A]) )\n", 258 | "intPart2 = sym.integrate( simple_fract_2.subs(B,solutionsAB[B]) )\n", 259 | "\n", 260 | "display(Math('\\int %s \\,dx = %s+C' %(sym.latex(simple_fract_1.subs(A,solutionsAB[A])),sym.latex(intPart1))))\n", 261 | "print('')\n", 262 | "display(Math('\\int %s \\,dx = %s+C' %(sym.latex(simple_fract_2.subs(B,solutionsAB[B])),sym.latex(intPart2))))" 263 | ], 264 | "metadata": { 265 | "id": "_jGPmAaoB6KR" 266 | }, 267 | "execution_count": null, 268 | "outputs": [] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "source": [ 273 | "# Step 6: sum the parts\n", 274 | "mysolution = intPart1 + intPart2\n", 275 | "mysolution\n", 276 | "\n", 277 | "display(Math('\\\\int %s \\, dx = %s+C' %(sym.latex(fx),sym.latex(mysolution))))" 278 | ], 279 | "metadata": { 280 | "id": "PmaKcrxmB6HX" 281 | }, 282 | "execution_count": null, 283 | "outputs": [] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "source": [], 288 | "metadata": { 289 | "id": "3jgJs7PF75b_" 290 | }, 291 | "execution_count": null, 292 | "outputs": [] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "source": [ 297 | "# Exercise 16.4: The lemon and the infinite" 298 | ], 299 | "metadata": { 300 | "id": "hdkX3AufVLDO" 301 | } 302 | }, 303 | { 304 | "cell_type": "code", 305 | "source": [ 306 | "# functions\n", 307 | "x = sym.symbols('x')\n", 308 | "f = 10*sym.sin( sym.sin(sym.sin(x)**1)**3 )**5\n", 309 | "g = sym.cos( sym.cos(sym.cos(x)**2)**4 )**6\n", 310 | "\n", 311 | "# derivatives\n", 312 | "df = sym.diff(f,x)\n", 313 | "dg = sym.diff(g,x)\n", 314 | "\n", 315 | "# lambdify\n", 316 | "f_lam = sym.lambdify(x,f,'numpy')\n", 317 | "g_lam = sym.lambdify(x,g,'numpy')\n", 318 | "df_lam = sym.lambdify(x,df,'numpy')\n", 319 | "dg_lam = sym.lambdify(x,dg,'numpy')\n", 320 | "\n", 321 | "# integrals\n", 322 | "xx = np.linspace(0,5*np.pi,5001)\n", 323 | "f_int = spi.cumulative_simpson(f_lam(xx),x=xx,initial=0)\n", 324 | "g_int = spi.cumulative_simpson(g_lam(xx),x=xx,initial=0)\n", 325 | "\n", 326 | "\n", 327 | "# and plot\n", 328 | "_,axs = plt.subplots(2,2,figsize=(14,8))\n", 329 | "axs[0,0].plot(xx,f_lam(xx),'k',label='$f(x)$')\n", 330 | "axs[0,0].plot(xx,g_lam(xx),'--',color=[.7,.7,.7],label='$g(x)$')\n", 331 | "axs[0,0].legend()\n", 332 | "axs[0,0].set(xlabel='$x$',ylabel='$y = f(x)$ or $g(x)$',title=r'$\\bf{A}$) Functions',xlim=xx[[0,-1]])\n", 333 | "\n", 334 | "axs[0,1].plot(f_lam(xx), df_lam(xx),'k',label='$f_1$')\n", 335 | "axs[0,1].plot(g_lam(xx), dg_lam(xx),'--',color=[.7,.7,.7],label='$f_1$')\n", 336 | "axs[0,1].set(xlabel='$f(x)$ or $g(x)$',ylabel=\"$f\\,'(x)$ or $g\\,'(x)$\",title=r'$\\bf{B}$) Derivatives by their functions')\n", 337 | "\n", 338 | "axs[1,0].plot(xx, f_int,'k',label='$F(x)$')\n", 339 | "axs[1,0].plot(xx, g_int,'--',color=[.7,.7,.7],label='$G(x)$')\n", 340 | "axs[1,0].legend()\n", 341 | "axs[1,0].set(xlabel='$x$',ylabel='$Y = F(x)$ or $G(x)$',title=r'$\\bf{C}$) Antiderivatives by $x$',xlim=xx[[0,-1]])\n", 342 | "\n", 343 | "axs[1,1].plot(f_int,g_int,'k')\n", 344 | "axs[1,1].set(xlabel='$F(x)$',ylabel='$G(x)$',title=r'$\\bf{D}$) Antiderivatives with each other')\n", 345 | "\n", 346 | "\n", 347 | "plt.tight_layout()\n", 348 | "plt.savefig('intTech_ex4.png')\n", 349 | "plt.show()" 350 | ], 351 | "metadata": { 352 | "id": "1zeWQv8MVLAa" 353 | }, 354 | "execution_count": null, 355 | "outputs": [] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "source": [], 360 | "metadata": { 361 | "id": "4EB94b1eVK3d" 362 | }, 363 | "execution_count": null, 364 | "outputs": [] 365 | } 366 | ] 367 | } -------------------------------------------------------------------------------- /exercises/ch18_statistics_exercises.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyOSOivcAIStk8d9wdQ6TC4o" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 18 (Integration applications in statistics)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook contains full code solutions to the exercises in this book chapter. There are many correct ways to solve the exercises; this notebook provides *a* solution, not *THE* solution. Please use this code as a starting point to continue exploring and experimenting with calculus concepts and visualizations.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "4KikZVyDDDXR" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "X2nu8jtVmMzn" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import scipy.integrate as spi\n", 71 | "import matplotlib.pyplot as plt\n", 72 | "\n", 73 | "# new in this chapter\n", 74 | "import sympy.stats\n", 75 | "import scipy.stats as stats\n", 76 | "\n", 77 | "# define global figure properties used for publication\n", 78 | "import matplotlib_inline.backend_inline\n", 79 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 80 | "plt.rcParams.update({'font.size':14, # font size\n", 81 | " 'savefig.dpi':300, # output resolution\n", 82 | " 'axes.titlelocation':'left',# title location\n", 83 | " 'axes.spines.right':False, # remove axis bounding box\n", 84 | " 'axes.spines.top':False, # remove axis bounding box\n", 85 | " 'lines.linewidth':2 # increase default line thickness\n", 86 | " })" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "source": [], 92 | "metadata": { 93 | "id": "3HEWzoPonrC6" 94 | }, 95 | "execution_count": null, 96 | "outputs": [] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "source": [ 101 | "# Exercise 18.1: cdfs from pdfs" 102 | ], 103 | "metadata": { 104 | "id": "aomuA544nq_x" 105 | } 106 | }, 107 | { 108 | "cell_type": "code", 109 | "source": [ 110 | "xx = np.linspace(-4,4,9001)\n", 111 | "dx = xx[1]-xx[0]\n", 112 | "sigma = 1\n", 113 | "\n", 114 | "# pdf\n", 115 | "pdf = 1/np.sqrt(2*np.pi*sigma**2) * np.exp( -xx**2/(2*sigma**2) )\n", 116 | "\n", 117 | "# cdf via numpy\n", 118 | "cdf_np = np.cumsum(pdf*dx)\n", 119 | "\n", 120 | "# cdf via scipy.integrate\n", 121 | "cdf_sp = spi.cumulative_simpson(pdf,dx=dx,initial=0)\n", 122 | "\n", 123 | "# cdf via scipy.stats\n", 124 | "cdf_st = stats.norm.cdf(xx)\n", 125 | "\n", 126 | "# compare\n", 127 | "_,axs = plt.subplots(1,2,figsize=(12,4))\n", 128 | "axs[0].plot(xx,pdf*dx,'k')\n", 129 | "axs[0].set(xlim=xx[[0,-1]],xlabel='$x$',ylabel='Probability density',title=r'$\\bf{A}$) pdf')\n", 130 | "\n", 131 | "axs[1].plot(xx,cdf_np,'k',label='np.cumsum')\n", 132 | "axs[1].plot(xx[::200],cdf_sp[::200],'o',color=[.5,.5,.5],markerfacecolor=[.9,.9,.9],label='spi.cumulative_')\n", 133 | "axs[1].plot(xx[::200],cdf_st[::200],'x',color=[.5,.5,.5],markersize=8,label='stats.norm')\n", 134 | "axs[1].set(xlim=xx[[0,-1]],xlabel='$x$',ylabel='Cumulative probability',title=r'$\\bf{B}$) cdfs')\n", 135 | "axs[1].legend()\n", 136 | "\n", 137 | "plt.tight_layout()\n", 138 | "plt.savefig('stats_ex1.png')\n", 139 | "plt.show()" 140 | ], 141 | "metadata": { 142 | "id": "riMwDWT5nuaJ" 143 | }, 144 | "execution_count": null, 145 | "outputs": [] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "source": [], 150 | "metadata": { 151 | "id": "sv93tcdZnq5g" 152 | }, 153 | "execution_count": null, 154 | "outputs": [] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "source": [ 159 | "# Exercise 18.2: non-analytic distribution" 160 | ], 161 | "metadata": { 162 | "id": "nKDsgNVMnq2X" 163 | } 164 | }, 165 | { 166 | "cell_type": "code", 167 | "source": [ 168 | "N = 2000\n", 169 | "# individual datasets\n", 170 | "data1 = stats.logistic.rvs(size=N//2)\n", 171 | "data2 = stats.wald.rvs(2,size=N//2)\n", 172 | "\n", 173 | "# combined dataset\n", 174 | "data = np.zeros(N)\n", 175 | "data[::2] = data1\n", 176 | "data[1::2] = data2\n", 177 | "\n", 178 | "\n", 179 | "# visualize\n", 180 | "_,axs = plt.subplots(1,3,figsize=(14,4))\n", 181 | "\n", 182 | "axs[0].plot(data,'ko',alpha=.3)\n", 183 | "axs[0].set(xlabel='Data index',ylabel='Data value',title=r'$\\bf{A}$) Simulated data')\n", 184 | "\n", 185 | "\n", 186 | "colors = [ [.5,.5,.5],[.7,.7,.7],'k']\n", 187 | "markers = [ 'o','^',None ]\n", 188 | "\n", 189 | "for idx,D in enumerate((data1,data2,data)):\n", 190 | "\n", 191 | " # extract the histogram (empirical distribution)\n", 192 | " heights,bins = np.histogram(D,bins='auto')\n", 193 | " binCenters = (bins[:-1]+bins[1:]) / 2\n", 194 | "\n", 195 | " # estimate the pdf/cdf\n", 196 | " pdfEst = heights / N\n", 197 | " cdfEst = np.cumsum(pdfEst)\n", 198 | "\n", 199 | " axs[1].plot(binCenters,pdfEst,color=colors[idx],marker=markers[idx],markerfacecolor='w')\n", 200 | " axs[1].set(xlim=bins[[0,-1]],xlabel='Data value',ylabel='Probability estimate',title=r'$\\bf{B}$) Histogram (estimated pdf)')\n", 201 | "\n", 202 | " axs[2].plot(binCenters,cdfEst,color=colors[idx],marker=markers[idx],markerfacecolor='w')\n", 203 | " axs[2].set(xlim=bins[[0,-1]],xlabel='Data value',ylabel='Cumulative probability',title=r'$\\bf{C}$) Empirical cdf')\n", 204 | "\n", 205 | "\n", 206 | "axs[1].legend(['Data 1','Data 2','Full data'])\n", 207 | "axs[2].legend(['Data 1','Data 2','Full data'])\n", 208 | "\n", 209 | "plt.tight_layout()\n", 210 | "plt.savefig('stats_ex2.png')\n", 211 | "plt.show()" 212 | ], 213 | "metadata": { 214 | "id": "mHqTV8SC4leG" 215 | }, 216 | "execution_count": null, 217 | "outputs": [] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "source": [], 222 | "metadata": { 223 | "id": "JtvZgvbenqy_" 224 | }, 225 | "execution_count": null, 226 | "outputs": [] 227 | }, 228 | { 229 | "cell_type": "markdown", 230 | "source": [ 231 | "# Exercise 18.3: Triangular pdf from cdf" 232 | ], 233 | "metadata": { 234 | "id": "onjBUmehnqv4" 235 | } 236 | }, 237 | { 238 | "cell_type": "code", 239 | "source": [ 240 | "a = 1\n", 241 | "b = 3\n", 242 | "d = 4\n", 243 | "\n", 244 | "xx = np.linspace(a-1,d+1,901)\n", 245 | "\n", 246 | "# piece 1\n", 247 | "cdf = np.zeros(len(xx))\n", 248 | "\n", 249 | "# piece 2\n", 250 | "whereX = (xx>a) & (xx<=b)\n", 251 | "cdf[whereX] = (xx[whereX]-a)**2 / ((d-a)*(b-a))\n", 252 | "\n", 253 | "# piece 3\n", 254 | "whereX = (xx>b) & (xx=d\n", 259 | "cdf[whereX] = np.ones(np.sum(whereX))\n", 260 | "\n", 261 | "# plot the cdf\n", 262 | "plt.figure(figsize=(10,4))\n", 263 | "plt.plot(xx,cdf,'k')\n", 264 | "\n", 265 | "for p in [a,b,d]:\n", 266 | " plt.plot(p,cdf[np.argmin(abs(xx-p))],'ko',markersize=10,markerfacecolor=[.8,.8,.8])\n", 267 | "\n", 268 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='$x$',ylabel='Cumulative probability',title='Triangular cdf')\n", 269 | "plt.show()" 270 | ], 271 | "metadata": { 272 | "id": "X7rUGXAfADiN" 273 | }, 274 | "execution_count": null, 275 | "outputs": [] 276 | }, 277 | { 278 | "cell_type": "code", 279 | "source": [ 280 | "stats.triang??" 281 | ], 282 | "metadata": { 283 | "id": "MXUbylVywjWE" 284 | }, 285 | "execution_count": null, 286 | "outputs": [] 287 | }, 288 | { 289 | "cell_type": "code", 290 | "source": [ 291 | "# pdf by differentiating the cdf\n", 292 | "pdf = np.append(0,np.diff(cdf))\n", 293 | "\n", 294 | "# pdf via scipy\n", 295 | "pdfS = stats.triang.pdf(xx,loc=a,c=(b-a)/(d-a),scale=d-a)\n", 296 | "pdfS *= xx[1]-xx[0] # needs to be scaled by dx\n", 297 | "\n", 298 | "\n", 299 | "# and plot\n", 300 | "plt.figure(figsize=(9,3.5))\n", 301 | "plt.plot(xx,pdf,'k',label=r'$p_d(x)$')\n", 302 | "plt.plot(xx[::20],pdfS[::20],'kd',markerfacecolor=[.5,.5,.5],label=r'$p_s(x)$')\n", 303 | "plt.plot(a,0,'ks',markersize=12,markerfacecolor='w',label=r'$a=%s$' %a)\n", 304 | "plt.plot(b,pdf[np.argmin(abs(xx-b))],'ko',markersize=12,markerfacecolor=[.7,.7,.7],label=r'$b=%s$' %b)\n", 305 | "plt.plot(d,0,'k^',markersize=12,markerfacecolor=[.3,.3,.3],label=r'$d=%s$' %d)\n", 306 | "\n", 307 | "plt.legend()\n", 308 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='x',ylabel='Probability density')\n", 309 | "\n", 310 | "plt.tight_layout()\n", 311 | "plt.savefig('stats_ex3.png')\n", 312 | "plt.show()" 313 | ], 314 | "metadata": { 315 | "id": "F5zOfAcdurpQ" 316 | }, 317 | "execution_count": null, 318 | "outputs": [] 319 | }, 320 | { 321 | "cell_type": "code", 322 | "source": [], 323 | "metadata": { 324 | "id": "od0lGVA5nqse" 325 | }, 326 | "execution_count": null, 327 | "outputs": [] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "source": [ 332 | "# Exercise 18.4: P-value calculations" 333 | ], 334 | "metadata": { 335 | "id": "EynDNPbeszb4" 336 | } 337 | }, 338 | { 339 | "cell_type": "code", 340 | "source": [ 341 | "zval = 2\n", 342 | "\n", 343 | "# 1) from cdf\n", 344 | "pval = 1 - stats.norm.cdf(zval)\n", 345 | "\n", 346 | "# 2) create the pdf\n", 347 | "N = 1000\n", 348 | "zz = np.linspace(zval,50,N)\n", 349 | "dx = zz[1]-zz[0]\n", 350 | "pdf = stats.norm.pdf(zz)\n", 351 | "\n", 352 | "# from pdf using np.sum\n", 353 | "pFromPdf_np = np.sum(pdf*dx)\n", 354 | "\n", 355 | "# 3) from pdf using spi\n", 356 | "pFromPdf_sp = spi.trapezoid(pdf,dx=dx)\n", 357 | "\n", 358 | "# print the results\n", 359 | "print(f'From cdf : {pval}')\n", 360 | "print(f'From np.sum : {pFromPdf_np}')\n", 361 | "print(f'From spi.trap: {pFromPdf_sp}')" 362 | ], 363 | "metadata": { 364 | "id": "Hg49aYfMszZY" 365 | }, 366 | "execution_count": null, 367 | "outputs": [] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "source": [ 372 | "# e.g.,\n", 373 | "f'{stats.norm.pdf(50):.40f}'" 374 | ], 375 | "metadata": { 376 | "id": "YdlOzCyJszWf" 377 | }, 378 | "execution_count": null, 379 | "outputs": [] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "source": [], 384 | "metadata": { 385 | "id": "QYtzGy7VqtrZ" 386 | }, 387 | "execution_count": null, 388 | "outputs": [] 389 | }, 390 | { 391 | "cell_type": "markdown", 392 | "source": [ 393 | "# Exercise 18.5: Empirical vs. analytic moments" 394 | ], 395 | "metadata": { 396 | "id": "8L6_cOctszvR" 397 | } 398 | }, 399 | { 400 | "cell_type": "code", 401 | "source": [ 402 | "# analytic pdf\n", 403 | "xx = np.linspace(-5,5,555)\n", 404 | "pdf = stats.norm.pdf(xx)\n", 405 | "pdf /= np.max(pdf)\n", 406 | "\n", 407 | "# empirical pdf estimate from random data\n", 408 | "sampsize = 5000\n", 409 | "data = stats.norm.rvs(size=sampsize)\n", 410 | "heights,bins = np.histogram(data,bins=40)\n", 411 | "binCenters = (bins[:-1]+bins[1:]) / 2\n", 412 | "estPdf = heights / np.max(heights)\n", 413 | "\n", 414 | "\n", 415 | "## make the plot\n", 416 | "plt.figure(figsize=(6,4))\n", 417 | "plt.plot(xx,pdf,'--',color=[.7,.7,.7],label='Analytic pdf')\n", 418 | "plt.plot(binCenters,estPdf,'k',label='Empirical pdf')\n", 419 | "\n", 420 | "plt.legend()\n", 421 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='x',ylabel='Probability (norm.)',title=r'$\\bf{A}$) Normal pdf')\n", 422 | "\n", 423 | "plt.tight_layout()\n", 424 | "plt.show()\n", 425 | "\n", 426 | "\n", 427 | "## calculate moments and print table\n", 428 | "momentsData = (np.mean(data),np.var(data),stats.skew(data),stats.kurtosis(data))\n", 429 | "momentsPdf = stats.norm.stats(moments='mvsk')\n", 430 | "\n", 431 | "# the js code below increases the font size to make the table match the figure better\n", 432 | "# https://stackoverflow.com/questions/61957742/how-to-increase-font-size-of-google-colab-cell-output\n", 433 | "from IPython.display import Javascript\n", 434 | "display(Javascript('''for (rule of document.styleSheets[0].cssRules){if (rule.selectorText=='body') {rule.style.fontSize = '17px'; break}}'''))\n", 435 | "\n", 436 | "print(f'Source: Mean : Var. : Skew : Kurtosis')\n", 437 | "print(f'-----------------------------------------------------')\n", 438 | "print(f' Data: {momentsData[0]:5.2f} : {momentsData[1]:5.2f} : {momentsData[2]:5.2f} : {momentsData[3]:5.2f}')\n", 439 | "print(f' pdf : {momentsPdf[0]:5.2f} : {momentsPdf[1]:5.2f} : {momentsPdf[2]:5.2f} : {momentsPdf[3]:5.2f}')" 440 | ], 441 | "metadata": { 442 | "id": "o7u7_2JxA_4c" 443 | }, 444 | "execution_count": null, 445 | "outputs": [] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "source": [ 450 | "# analytic pdf\n", 451 | "xx = np.linspace(.5,5,555)\n", 452 | "pdf = stats.pareto.pdf(xx,b=5)\n", 453 | "pdf /= np.max(pdf)\n", 454 | "\n", 455 | "# empirical pdf estimate from random data\n", 456 | "sampsize = 5000\n", 457 | "data = stats.pareto.rvs(b=5,size=sampsize)\n", 458 | "heights,bins = np.histogram(data,bins=40)\n", 459 | "binCenters = (bins[:-1]+bins[1:]) / 2\n", 460 | "estPdf = heights / np.max(heights)\n", 461 | "\n", 462 | "\n", 463 | "## make the plot\n", 464 | "plt.figure(figsize=(6,4))\n", 465 | "plt.plot(xx,pdf,'--',color=[.7,.7,.7],label='Analytic pdf')\n", 466 | "plt.plot(binCenters,estPdf,'k',label='Empirical pdf')\n", 467 | "\n", 468 | "plt.legend()\n", 469 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='x',ylabel='Probability (norm.)',title=r'$\\bf{B}$) Pareto pdf')\n", 470 | "\n", 471 | "plt.tight_layout()\n", 472 | "plt.show()\n", 473 | "\n", 474 | "\n", 475 | "## calculate moments and print table\n", 476 | "momentsData = (np.mean(data),np.var(data),stats.skew(data),stats.kurtosis(data))\n", 477 | "momentsPdf = stats.pareto.stats(b=5,moments='mvsk')\n", 478 | "\n", 479 | "display(Javascript('''for (rule of document.styleSheets[0].cssRules){if (rule.selectorText=='body') {rule.style.fontSize = '17px'; break}}'''))\n", 480 | "print(f'Source: Mean : Var. : Skew : Kurtosis')\n", 481 | "print(f'-----------------------------------------------------')\n", 482 | "print(f' Data: {momentsData[0]:5.2f} : {momentsData[1]:5.2f} : {momentsData[2]:5.2f} : {momentsData[3]:5.2f}')\n", 483 | "print(f' pdf : {momentsPdf[0]:5.2f} : {momentsPdf[1]:5.2f} : {momentsPdf[2]:5.2f} : {momentsPdf[3]:5.2f}')" 484 | ], 485 | "metadata": { 486 | "id": "xdRUqYCZszsM" 487 | }, 488 | "execution_count": null, 489 | "outputs": [] 490 | }, 491 | { 492 | "cell_type": "code", 493 | "source": [], 494 | "metadata": { 495 | "id": "Hym0XMbnszpt" 496 | }, 497 | "execution_count": null, 498 | "outputs": [] 499 | }, 500 | { 501 | "cell_type": "markdown", 502 | "source": [ 503 | "# Exercise 18.6: areas" 504 | ], 505 | "metadata": { 506 | "id": "ZxL55HcRszhM" 507 | } 508 | }, 509 | { 510 | "cell_type": "code", 511 | "source": [ 512 | "# area calculations\n", 513 | "z1 = 1\n", 514 | "z2 = 2\n", 515 | "\n", 516 | "p_z1z2 = stats.norm.cdf(z2) - stats.norm.cdf(z1)\n", 517 | "p_z2inf = 1 - stats.norm.cdf(z2)\n", 518 | "\n", 519 | "print(f'Area between z = {z1} and z = {z2}: {p_z1z2*100:.2f}%')\n", 520 | "print(f'Area between z = {z2} and z = oo: {p_z2inf*100:.2f}%')" 521 | ], 522 | "metadata": { 523 | "id": "tm5OVchaszew" 524 | }, 525 | "execution_count": null, 526 | "outputs": [] 527 | }, 528 | { 529 | "cell_type": "code", 530 | "source": [ 531 | "# create the pdf\n", 532 | "zz = np.linspace(-4,4,305)\n", 533 | "pdf = stats.norm.pdf(zz) * (zz[1]-zz[0])\n", 534 | "\n", 535 | "# draw the figure\n", 536 | "_,axs = plt.subplots(1,figsize=(10,3.5))\n", 537 | "\n", 538 | "axs.plot(zz,pdf,'k',label='pdf')\n", 539 | "axs.axvline(z1,color='k',linestyle='--',label=fr'$z_1$ = {z1}')\n", 540 | "axs.axvline(z2,color=[.7,.7,.7],linestyle=':',label=fr'$z_2$ = {z2}')\n", 541 | "axs.fill_between(zz[(zz>=z1) & (zz<=z2)],pdf[(zz>=z1) & (zz<=z2)],color='k',alpha=.2,label=r'$A([z_1,z_2]) = %.2f \\%% $' %(p_z1z2*100))\n", 542 | "axs.fill_between(zz[zz>=z2],pdf[zz>=z2],color='k',alpha=.5,label=r'$A([z_2,\\infty)) = %.2f \\%% $' %(p_z2inf*100))\n", 543 | "axs.legend()\n", 544 | "axs.set(xlim=zz[[0,-1]],xlabel='z',ylim=[0,1.1*np.max(pdf)],ylabel='Probability density')\n", 545 | "\n", 546 | "plt.tight_layout()\n", 547 | "plt.savefig('stats_ex6.png')\n", 548 | "plt.show()" 549 | ], 550 | "metadata": { 551 | "id": "OflDSX25A3A2" 552 | }, 553 | "execution_count": null, 554 | "outputs": [] 555 | }, 556 | { 557 | "cell_type": "code", 558 | "source": [], 559 | "metadata": { 560 | "id": "LTumEbAzA29e" 561 | }, 562 | "execution_count": null, 563 | "outputs": [] 564 | } 565 | ] 566 | } -------------------------------------------------------------------------------- /exercises/ch19_multivariableIntegration_exercises.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyMogRPkz4cYOf4mO/EA8aDF" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "view-in-github" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 19 (Multivariable integration)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook contains full code solutions to the exercises in this book chapter. There are many correct ways to solve the exercises; this notebook provides *a* solution, not *THE* solution. Please use this code as a starting point to continue exploring and experimenting with calculus concepts and visualizations.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "yeVh6hm2ezCO" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "id": "oYWhHwGQ9OdD" 55 | }, 56 | "outputs": [], 57 | "source": [ 58 | "# import libraries and define global settings\n", 59 | "import numpy as np\n", 60 | "import sympy as sym\n", 61 | "import scipy.integrate as spi\n", 62 | "import matplotlib.pyplot as plt\n", 63 | "import matplotlib.patches as patches\n", 64 | "from IPython.display import Math\n", 65 | "\n", 66 | "# define global figure properties used for publication\n", 67 | "import matplotlib_inline.backend_inline\n", 68 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 69 | "plt.rcParams.update({'font.size':14, # font size\n", 70 | " 'savefig.dpi':300, # output resolution\n", 71 | " 'axes.titlelocation':'left',# title location\n", 72 | " # 'axes.spines.right':False, # remove axis bounding box\n", 73 | " # 'axes.spines.top':False, # remove axis bounding box\n", 74 | " 'lines.linewidth':2 # increase default line thickness\n", 75 | " })" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "source": [], 81 | "metadata": { 82 | "id": "jwPjgffPjSaY" 83 | }, 84 | "execution_count": null, 85 | "outputs": [] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "source": [ 90 | "# Exercise 19.1" 91 | ], 92 | "metadata": { 93 | "id": "uyB2rHo-jSXY" 94 | } 95 | }, 96 | { 97 | "cell_type": "code", 98 | "source": [ 99 | "## part 1\n", 100 | "# the function\n", 101 | "x,y = sym.symbols('x,y')\n", 102 | "fxy = sym.exp(sym.pi)*x**2 + x*sym.cos(y) - y*sym.exp(sym.pi)*sym.log(x**4)\n", 103 | "\n", 104 | "## part 2\n", 105 | "# the constant factored out\n", 106 | "C = sym.exp(sym.pi)\n", 107 | "fxy_fact = sym.simplify( fxy/C )\n", 108 | "\n", 109 | "# print\n", 110 | "display(Math('f(x,y) = %s' %sym.latex(fxy)))\n", 111 | "print('')\n", 112 | "display(Math('\\qquad\\quad\\, = %s\\Big( %s \\Big)' %(sym.latex(C),sym.latex(fxy_fact))))" 113 | ], 114 | "metadata": { 115 | "id": "np5wjT4ew9D2" 116 | }, 117 | "execution_count": null, 118 | "outputs": [] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "source": [ 123 | "### part 3\n", 124 | "int1 = sym.integrate(fxy,x,y)\n", 125 | "int2 = sym.integrate( C*sym.integrate(fxy_fact,x) ,y)\n", 126 | "int3 = C*sym.integrate( sym.integrate(fxy_fact,x) ,y)\n", 127 | "\n", 128 | "display(Math('\\;\\; %s \\quad=\\quad %s' %(sym.latex(sym.Integral(fxy,x,y)),sym.latex(int1))))\n", 129 | "print('')\n", 130 | "display(Math('\\int %s %s\\,dy \\quad=\\quad %s' %(sym.latex(C),sym.latex(sym.Integral(fxy_fact,x)),sym.latex(int2))))\n", 131 | "print('')\n", 132 | "display(Math('\\;\\; %s %s \\quad=\\quad %s' %(sym.latex(C),sym.latex(sym.Integral(fxy_fact,x,y)),sym.latex(int3))))" 133 | ], 134 | "metadata": { 135 | "id": "rllOPiS0jSUg" 136 | }, 137 | "execution_count": null, 138 | "outputs": [] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "source": [ 143 | "### part 4\n", 144 | "x_a,x_b = 1,3\n", 145 | "y_a,y_b = -sym.pi,sym.pi/4\n", 146 | "\n", 147 | "dint1 = sym.integrate(fxy,(x,x_a,x_b),(y,y_a,y_b))\n", 148 | "dint2 = sym.integrate( C*sym.integrate(fxy_fact,(x,x_a,x_b)) ,(y,y_a,y_b))\n", 149 | "dint3 = C*sym.integrate( sym.integrate(fxy_fact,(x,x_a,x_b)) ,(y,y_a,y_b))\n", 150 | "\n", 151 | "display(Math('%s \\;=\\; %s'\n", 152 | " %(sym.latex(sym.Integral(fxy,(x,x_a,x_b),(y,y_a,y_b))),sym.latex(dint1.evalf()))))\n", 153 | "print('')\n", 154 | "display(Math('\\int_{%s}^{%s} %s %s\\,dy \\;=\\; %s'\n", 155 | " %(sym.latex(y_a),sym.latex(y_b),sym.latex(C),sym.latex(sym.Integral(fxy_fact,(x,x_a,x_b))),sym.latex(dint2.evalf()))))\n", 156 | "print('')\n", 157 | "display(Math('%s %s \\;=\\; %s'\n", 158 | " %(sym.latex(C),sym.latex(sym.Integral(fxy_fact,(x,x_a,x_b),(y,y_a,y_b))),sym.latex(dint3.evalf()))))" 159 | ], 160 | "metadata": { 161 | "id": "SCTdNEEIjSRj" 162 | }, 163 | "execution_count": null, 164 | "outputs": [] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "source": [ 169 | "# exact result\n", 170 | "dint1" 171 | ], 172 | "metadata": { 173 | "id": "MTb3-AuX3vMO" 174 | }, 175 | "execution_count": null, 176 | "outputs": [] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "source": [ 181 | "### part 5\n", 182 | "\n", 183 | "# calculate\n", 184 | "dint1_sp = spi.dblquad(sym.lambdify((x,y),fxy),float(y_a),float(y_b),x_a,x_b)[0]\n", 185 | "dint2_sp = C.evalf() * spi.dblquad(sym.lambdify((x,y),fxy_fact),float(y_a),float(y_b),x_a,x_b)[0]\n", 186 | "\n", 187 | "# and display\n", 188 | "display(Math('%s \\;=\\; %.11f' %(sym.latex(sym.Integral(fxy,(x,x_a,x_b),(y,y_a,y_b))),dint1_sp)))\n", 189 | "print('')\n", 190 | "display(Math('%s%s \\;=\\; %.11f' %(sym.latex(C),sym.latex(sym.Integral(fxy_fact,(x,x_a,x_b),(y,y_a,y_b))),dint2_sp)))" 191 | ], 192 | "metadata": { 193 | "id": "KN0nkTyXjSOz" 194 | }, 195 | "execution_count": null, 196 | "outputs": [] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "source": [ 201 | "### part 6\n", 202 | "\n", 203 | "xx = np.linspace(x_a-2,x_b+3,1601)\n", 204 | "yy = np.linspace(float(y_a)-2,float(y_b)+3,1600)\n", 205 | "\n", 206 | "X,Y = np.meshgrid(xx,yy)\n", 207 | "Z = sym.lambdify((x,y),fxy)(X,Y)\n", 208 | "\n", 209 | "# show the plot\n", 210 | "fig,ax = plt.subplots(1,figsize=(10,3))\n", 211 | "h = ax.imshow(Z,origin='lower',extent=[xx[0],xx[-1],yy[0],yy[-1]],vmin=-500,vmax=500,cmap='gray',aspect='auto')\n", 212 | "ax.set(xlabel='x',ylabel='y')\n", 213 | "ch = fig.colorbar(h,ax=ax,fraction=.04)\n", 214 | "ch.ax.tick_params(labelsize=10)\n", 215 | "\n", 216 | "ax.add_patch( patches.Rectangle(\n", 217 | " (x_a,float(y_a)),x_b-x_a,float(y_b)-float(y_a),\n", 218 | " linestyle='--',linewidth=1,edgecolor='k',facecolor='none') )\n", 219 | "\n", 220 | "plt.tight_layout()\n", 221 | "plt.savefig('multiint_ex1f.png')\n", 222 | "plt.show()" 223 | ], 224 | "metadata": { 225 | "id": "XrPZO2S7jSL8" 226 | }, 227 | "execution_count": null, 228 | "outputs": [] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "source": [], 233 | "metadata": { 234 | "id": "lm29Md8CjSJR" 235 | }, 236 | "execution_count": null, 237 | "outputs": [] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "source": [ 242 | "# Exercise 19.2" 243 | ], 244 | "metadata": { 245 | "id": "MgA148B-_nII" 246 | } 247 | }, 248 | { 249 | "cell_type": "code", 250 | "source": [ 251 | "# function\n", 252 | "x,y = sym.symbols('x,y')\n", 253 | "fxy = sym.exp( -(x**2+y**2) )\n", 254 | "fxy_lam = sym.lambdify((x,y),fxy)\n", 255 | "\n", 256 | "# integration bounds\n", 257 | "x_a = y**3\n", 258 | "x_b = sym.cos(2*sym.pi*y)\n", 259 | "y_a = 0\n", 260 | "y_b = sym.pi/4\n", 261 | "\n", 262 | "# definite integral (try if you have some time to kill...)\n", 263 | "#sym.integrate(fxy,(x,x_a,x_b),(y,y_a,y_b))" 264 | ], 265 | "metadata": { 266 | "id": "fiBILmUwCf6X" 267 | }, 268 | "execution_count": null, 269 | "outputs": [] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "source": [ 274 | "# integration bounds\n", 275 | "y_vals = np.linspace(float(y_a),float(y_b),1000)\n", 276 | "slice_integrals = np.zeros(len(y_vals))\n", 277 | "\n", 278 | "# iterate over y values, integrate along x\n", 279 | "for idx,yi in enumerate(y_vals):\n", 280 | "\n", 281 | " # x bounds for this y\n", 282 | " lo_bnd = float(x_a.subs(y,yi))\n", 283 | " hi_bnd = float(x_b.subs(y,yi))\n", 284 | " x_vals = np.linspace(lo_bnd,hi_bnd,100)\n", 285 | "\n", 286 | " # function values for these coords\n", 287 | " f_vals = fxy_lam(x_vals,yi)\n", 288 | "\n", 289 | " # get the \"mini-integral\" of this slice (fxy is positive-valued function so don't need abs() )\n", 290 | " slice_integrals[idx] = spi.simpson(f_vals,x=x_vals)\n", 291 | "\n", 292 | "# integrate the results along y\n", 293 | "defint_approx = spi.simpson(abs(slice_integrals),x=y_vals)\n", 294 | "\n", 295 | "# print the results\n", 296 | "print(f'Scipy approximation: {defint_approx:.10f}')" 297 | ], 298 | "metadata": { 299 | "id": "NpNQqQ_c97Ma" 300 | }, 301 | "execution_count": null, 302 | "outputs": [] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "source": [ 307 | "# region of integration\n", 308 | "xx4region = np.linspace(float(y_a),float(y_b),100)\n", 309 | "yLo4region = np.array([x_a.subs(y,yi) for yi in xx4region],dtype=float)\n", 310 | "yHi4region = np.array([x_b.subs(y,yi) for yi in xx4region],dtype=float)\n", 311 | "\n", 312 | "# meshgrid for plotting the function\n", 313 | "xx = np.linspace(-1,2,499)\n", 314 | "yy = np.linspace(-1.5,1.5,499)\n", 315 | "X,Y = np.meshgrid(xx,yy)\n", 316 | "Z = fxy_lam(X,Y)\n", 317 | "\n", 318 | "\n", 319 | "### visualization\n", 320 | "fig,ax = plt.subplots(figsize=(12,6))\n", 321 | "\n", 322 | "# function as heatmap\n", 323 | "h = ax.imshow(Z,origin='lower',extent=[xx[0],xx[-1],yy[0],yy[-1]],\n", 324 | " cmap='gray',vmin=0,vmax=1,aspect='auto',alpha=.8)\n", 325 | "fig.colorbar(h, ax=ax, label=r'$z = f(x,y)$')\n", 326 | "\n", 327 | "ax.axhline(0,color=[.5,.5,.5],linestyle=':')\n", 328 | "ax.axvline(0,color=[.5,.5,.5],linestyle=':')\n", 329 | "\n", 330 | "# region of integration\n", 331 | "ax.plot(xx4region,yLo4region,'k--',label=r'Lower bound = $%s$' %sym.latex(x_a))\n", 332 | "ax.plot(xx4region,yHi4region,'k',label=r'Upper bound = $%s$' %sym.latex(x_b))\n", 333 | "ax.fill_between(xx4region,yHi4region,yLo4region,color='k',alpha=.2,label='Integration window')\n", 334 | "ax.legend()\n", 335 | "\n", 336 | "# etc etc\n", 337 | "ax.set(xlabel='$x$',ylabel='$y$')\n", 338 | "ax.set_title(r'$\\int_{%s}^{%s}\\int_{%s}^{%s} \\left(%s\\right) \\,dx\\,dy \\;=\\; %.4f$'\n", 339 | " %(sym.latex(y_a),sym.latex(y_b),sym.latex(x_a),sym.latex(x_b),sym.latex(fxy),defint_approx),\n", 340 | " loc='center')\n", 341 | "\n", 342 | "plt.tight_layout()\n", 343 | "plt.savefig('multiint_ex2.png')\n", 344 | "plt.show()" 345 | ], 346 | "metadata": { 347 | "id": "HjHQ-rVH5Dh9" 348 | }, 349 | "execution_count": null, 350 | "outputs": [] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "source": [], 355 | "metadata": { 356 | "id": "4OOrAWgt6BmU" 357 | }, 358 | "execution_count": null, 359 | "outputs": [] 360 | }, 361 | { 362 | "cell_type": "markdown", 363 | "source": [ 364 | "# Exercise 19.3" 365 | ], 366 | "metadata": { 367 | "id": "AOvcJrJa0WHP" 368 | } 369 | }, 370 | { 371 | "cell_type": "code", 372 | "source": [ 373 | "# Define variables and the function\n", 374 | "x,y = sym.symbols('x,y')\n", 375 | "fxy = x**2 + y\n", 376 | "fxy_lam = sym.lambdify((x,y),fxy)\n", 377 | "\n", 378 | "x_a,x_b = y**2, y+0\n", 379 | "y_a,y_b = 0,1\n", 380 | "\n", 381 | "# exact integral\n", 382 | "sym_def = sym.integrate(fxy,(x,x_a,x_b),(y,y_a,y_b))" 383 | ], 384 | "metadata": { 385 | "id": "W2MPOWnI0cwI" 386 | }, 387 | "execution_count": null, 388 | "outputs": [] 389 | }, 390 | { 391 | "cell_type": "code", 392 | "source": [ 393 | "# integration bounds\n", 394 | "y_vals = np.linspace(y_a,y_b,1000)\n", 395 | "dxs = np.zeros(len(y_vals))\n", 396 | "numXs = np.zeros(len(y_vals))\n", 397 | "deltax = .001\n", 398 | "\n", 399 | "# don't need to integrate; just calculate delta-x\n", 400 | "for idx,yi in enumerate(y_vals):\n", 401 | "\n", 402 | " # get the bounds for this slice\n", 403 | " lo_bnd = float(x_a.subs(y,yi))\n", 404 | " hi_bnd = float(x_b.subs(y,yi))\n", 405 | "\n", 406 | " # get delta-x using a fixed number of points\n", 407 | " x_vals1 = np.linspace(lo_bnd,hi_bnd,100)\n", 408 | " dxs[idx] = x_vals1[1]-x_vals1[0]\n", 409 | "\n", 410 | " # get the number of points based on a fixed delta-x\n", 411 | " x_vals2 = np.arange(lo_bnd,hi_bnd+deltax,deltax)\n", 412 | " numXs[idx] = len(x_vals2)\n", 413 | "\n", 414 | "# show the delta-x's\n", 415 | "_,axs = plt.subplots(1,2,figsize=(11,3))\n", 416 | "\n", 417 | "axs[0].plot(y_vals[::20],dxs[::20],'ks-',markerfacecolor=[.7,.7,.7])\n", 418 | "axs[0].set(xlim=[y_a-.01,y_b+.01],xlabel='$y$-axis value',ylabel=r'$\\Delta x$',title=r'$\\bf{A}$) $\\Delta x$ for fixed number of points')\n", 419 | "\n", 420 | "axs[1].plot(y_vals[::20],numXs[::20],'ks-',markerfacecolor=[.7,.7,.7])\n", 421 | "axs[1].set(xlim=[y_a-.01,y_b+.01],xlabel='$y$-axis value',ylabel='Number of $x$-axis values',title=r'$\\bf{B}$) Number of points for fixed $\\Delta x$')\n", 422 | "\n", 423 | "plt.tight_layout()\n", 424 | "plt.savefig('multiint_ex3a.png')\n", 425 | "plt.show()" 426 | ], 427 | "metadata": { 428 | "id": "YvT50FlN0WED" 429 | }, 430 | "execution_count": null, 431 | "outputs": [] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "source": [ 436 | "# integration bounds\n", 437 | "y_vals = np.linspace(y_a,y_b,1000)\n", 438 | "\n", 439 | "deltaxs = np.linspace(.0001,.01,19)\n", 440 | "approxErrors = np.zeros(len(deltaxs))\n", 441 | "\n", 442 | "# run the experiment\n", 443 | "for didx,deltax in enumerate(deltaxs):\n", 444 | "\n", 445 | " # copy/pasted/condensed code\n", 446 | " slice_integrals = np.zeros(len(y_vals))\n", 447 | " for idx,yi in enumerate(y_vals):\n", 448 | " x_vals = np.arange(float(x_a.subs(y,yi)),float(x_b.subs(y,yi))+deltax,deltax)\n", 449 | " f_vals = fxy_lam(x_vals,yi)\n", 450 | " slice_integrals[idx] = spi.simpson(f_vals,x=x_vals)\n", 451 | "\n", 452 | " # calculate the approximation error\n", 453 | " approxErrors[didx] = abs( spi.simpson(slice_integrals,x=y_vals) - sym_def )" 454 | ], 455 | "metadata": { 456 | "id": "FkBcL7xY0WBQ" 457 | }, 458 | "execution_count": null, 459 | "outputs": [] 460 | }, 461 | { 462 | "cell_type": "code", 463 | "source": [ 464 | "plt.figure(figsize=(10,3))\n", 465 | "plt.plot(deltaxs,approxErrors,'ks',markerfacecolor=[.7,.7,.7],markersize=10)\n", 466 | "plt.gca().set(xlabel=r'$\\Delta x$ (fixed)',ylabel='Approximation error')\n", 467 | "plt.gca().invert_xaxis() # note the x-axis inversion!\n", 468 | "\n", 469 | "plt.tight_layout()\n", 470 | "plt.savefig('multiint_ex3b.png')\n", 471 | "plt.show()" 472 | ], 473 | "metadata": { 474 | "id": "0_437zPD0V-l" 475 | }, 476 | "execution_count": null, 477 | "outputs": [] 478 | }, 479 | { 480 | "cell_type": "code", 481 | "source": [], 482 | "metadata": { 483 | "id": "f6u4TO210V71" 484 | }, 485 | "execution_count": null, 486 | "outputs": [] 487 | } 488 | ] 489 | } -------------------------------------------------------------------------------- /figures/ch08_derivativesTheorems_figures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyNHFDnhSzUxSGM2UUhBVIE/" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "IMCG77qiecTi" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 8 (Differentiation theorems)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook will reproduce the figures in this chapter, and illustrate the mathematical concepts explained in the book. The point of providing the code is not just for you to recreate the figures, but for you to modify, adapt, explore, and experiment with the code.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "jb67RuPgecTj" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "id": "-AqocO_QYBjQ" 55 | }, 56 | "outputs": [], 57 | "source": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "from IPython.display import Math\n", 72 | "\n", 73 | "# define global figure properties used for publication\n", 74 | "import matplotlib_inline.backend_inline\n", 75 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 76 | "plt.rcParams.update({'font.size':14, # font size\n", 77 | " 'savefig.dpi':300, # output resolution\n", 78 | " 'axes.titlelocation':'left',# title location\n", 79 | " 'axes.spines.right':False, # remove axis bounding box\n", 80 | " 'axes.spines.top':False, # remove axis bounding box\n", 81 | " 'lines.linewidth':2 # increase default line thickness\n", 82 | " })" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "source": [], 88 | "metadata": { 89 | "id": "Ui-waOdJYmLe" 90 | }, 91 | "execution_count": null, 92 | "outputs": [] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "source": [ 97 | "# Figure 8.2: Intermediate value theorem" 98 | ], 99 | "metadata": { 100 | "id": "eRIl9lJYO3tb" 101 | } 102 | }, 103 | { 104 | "cell_type": "code", 105 | "source": [ 106 | "# the function and bounds\n", 107 | "x = np.linspace(0,4,101)\n", 108 | "f = lambda x: x**2\n", 109 | "a,b = 1,3\n", 110 | "\n", 111 | "# the plot\n", 112 | "plt.figure(figsize=(10,4))\n", 113 | "plt.plot(x,f(x),'k',label=r'$f(x) = x^2$')\n", 114 | "plt.plot(a,f(a),'ko',markersize=10,markerfacecolor='k')\n", 115 | "plt.plot(b,f(b),'ko',markersize=10,markerfacecolor='k')\n", 116 | "\n", 117 | "plt.plot([a,a],[0,f(a)],':',color=[.6,.6,.6],zorder=-3)\n", 118 | "plt.plot([0,a],[f(a),f(a)],'--',color=[.6,.6,.6],zorder=-3)\n", 119 | "\n", 120 | "plt.plot([b,b],[0,f(b)],':',color=[.6,.6,.6],zorder=-3)\n", 121 | "plt.plot([0,b],[f(b),f(b)],'--',color=[.6,.6,.6],zorder=-3)\n", 122 | "plt.legend(fontsize=20)\n", 123 | "plt.gca().set(xlim=x[[0,-1]],ylim=[-.1,f(x[-1])],xlabel='x',ylabel=r'$y=x^2$')\n", 124 | "\n", 125 | "plt.tight_layout()\n", 126 | "plt.savefig('diffTheorems_IVTillustration.png')\n", 127 | "plt.show()" 128 | ], 129 | "metadata": { 130 | "id": "w5T_mjWPO5NN" 131 | }, 132 | "execution_count": null, 133 | "outputs": [] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "source": [], 138 | "metadata": { 139 | "id": "C_HhLE1NO3qT" 140 | }, 141 | "execution_count": null, 142 | "outputs": [] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "source": [ 147 | "# Figure 8.4: Example of IVT for determining roots" 148 | ], 149 | "metadata": { 150 | "id": "3bMnMDjcO3nV" 151 | } 152 | }, 153 | { 154 | "cell_type": "code", 155 | "source": [ 156 | "# functions\n", 157 | "x = np.linspace(-1.2,1,345)\n", 158 | "f1 = x**4 + x + .4\n", 159 | "f2 = x**4 + x + .5\n", 160 | "\n", 161 | "_,axs = plt.subplots(1,2,figsize=(10,np.pi))\n", 162 | "\n", 163 | "axs[0].plot(x,f1,'k')\n", 164 | "axs[0].set(xlim=x[[0,-1]],ylim=[-.2,2.4],xlabel='x',ylabel=r'$y_1=f_1(x)$',title=r'$\\bf{A}$) $f_1(x) = x^4+x+.4$')\n", 165 | "axs[0].grid(color=[.7,.7,.7],linestyle='--')\n", 166 | "\n", 167 | "axs[1].plot(x,f2,'k')\n", 168 | "axs[1].set(xlim=x[[0,-1]],ylim=[-.2,2.4],xlabel='x',ylabel=r'$y_2=f_2(x)$',title=r'$\\bf{B}$) $f_2(x) = x^4+x+.5$')\n", 169 | "axs[1].grid(color=[.7,.7,.7],linestyle='--')\n", 170 | "\n", 171 | "plt.tight_layout()\n", 172 | "plt.savefig('diffTheorems_IVTdemoPolyRoots.png')\n", 173 | "plt.show()" 174 | ], 175 | "metadata": { 176 | "id": "Pl0lcFXJbEhH" 177 | }, 178 | "execution_count": null, 179 | "outputs": [] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "source": [], 184 | "metadata": { 185 | "id": "f_jxgfqwO3g8" 186 | }, 187 | "execution_count": null, 188 | "outputs": [] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "source": [ 193 | "# Figure 8.6: Rolle's theorem" 194 | ], 195 | "metadata": { 196 | "id": "AG5k5dkqYmO2" 197 | } 198 | }, 199 | { 200 | "cell_type": "code", 201 | "source": [ 202 | "# the function\n", 203 | "x = sym.symbols('x')\n", 204 | "fx = -x**2/3 + 2*x - 3\n", 205 | "\n", 206 | "# the bounds\n", 207 | "a = 3-sym.sqrt(3)\n", 208 | "c = 3+sym.sqrt(3)\n", 209 | "\n", 210 | "# step 1: confirm that f(a)=f(c)\n", 211 | "display(Math('f(x) = %s' %sym.latex(fx))), print('')\n", 212 | "display(Math('f(%s) = %s = %s' %(sym.latex(a),sym.latex(fx.subs(x,a)),fx.subs(x,a).evalf()))), print('')\n", 213 | "display(Math('f(%s) = %s = %s' %(sym.latex(c),sym.latex(fx.subs(x,c)),fx.subs(x,c).evalf())))" 214 | ], 215 | "metadata": { 216 | "id": "mZL3OUp6aleI" 217 | }, 218 | "execution_count": null, 219 | "outputs": [] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "source": [ 224 | "# step 2: find the derivative\n", 225 | "df = sym.diff(fx)\n", 226 | "display(Math(\"f'(x) = %s\" %sym.latex(df))), print('')\n", 227 | "\n", 228 | "# and solve for f'=0\n", 229 | "b = sym.solve(df)[0]\n", 230 | "display(Math(\"f'(%s) = %s\" %(b,df.subs(x,b))))" 231 | ], 232 | "metadata": { 233 | "id": "noCjDMdtYmSN" 234 | }, 235 | "execution_count": null, 236 | "outputs": [] 237 | }, 238 | { 239 | "cell_type": "code", 240 | "source": [ 241 | "# lambdify the function\n", 242 | "fx_lam = sym.lambdify(x,fx)\n", 243 | "\n", 244 | "# plot\n", 245 | "xx = np.linspace(0,6,253)\n", 246 | "\n", 247 | "plt.figure(figsize=(8,3.3))\n", 248 | "\n", 249 | "plt.plot(xx,fx_lam(xx),'k',label=r'$f(x)=%s$'%sym.latex(fx))\n", 250 | "plt.plot(a,fx_lam(a),'ko',markerfacecolor='gray',markersize=11,label='a')\n", 251 | "plt.plot(c,fx_lam(c),'ks',markerfacecolor='gray',markersize=11,label='c')\n", 252 | "plt.plot(b,fx_lam(b),'kv',markerfacecolor='gray',markersize=11,label='b')\n", 253 | "\n", 254 | "plt.plot([a,c],[fx_lam(a),fx_lam(c)],'--',color=[.6,.6,.6],zorder=-5)\n", 255 | "plt.plot([b-1,b+1],[fx_lam(b),fx_lam(b)],':',color=[.6,.6,.6],zorder=-5)\n", 256 | "\n", 257 | "plt.gca().set(xlim=xx[[0,-1]],xlabel='x',ylabel='$y = f(x)$')\n", 258 | "plt.legend()\n", 259 | "\n", 260 | "plt.tight_layout()\n", 261 | "plt.savefig('diffTheorems_rolleExample1.png')\n", 262 | "plt.show()" 263 | ], 264 | "metadata": { 265 | "id": "w2J_JaO5YmVd" 266 | }, 267 | "execution_count": null, 268 | "outputs": [] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "source": [], 273 | "metadata": { 274 | "id": "4ZrOPLxlYmfu" 275 | }, 276 | "execution_count": null, 277 | "outputs": [] 278 | } 279 | ] 280 | } -------------------------------------------------------------------------------- /figures/ch09_applications_figures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyN9IaVTo1zE1G6s7FIsdkFX" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "IMCG77qiecTi" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 9 (Applications of differentiation)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook will reproduce the figures in this chapter, and illustrate the mathematical concepts explained in the book. The point of providing the code is not just for you to recreate the figures, but for you to modify, adapt, explore, and experiment with the code.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "jb67RuPgecTj" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "id": "07lu653hKhXU" 55 | }, 56 | "outputs": [], 57 | "source": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "\n", 72 | "# define global figure properties used for publication\n", 73 | "import matplotlib_inline.backend_inline\n", 74 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 75 | "plt.rcParams.update({'font.size':14, # font size\n", 76 | " 'savefig.dpi':300, # output resolution\n", 77 | " 'axes.titlelocation':'left',# title location\n", 78 | " 'axes.spines.right':False, # remove axis bounding box\n", 79 | " 'axes.spines.top':False, # remove axis bounding box\n", 80 | " 'lines.linewidth':2 # increase default line thickness\n", 81 | " })" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "source": [], 87 | "metadata": { 88 | "id": "2R_kDgWQdsDO" 89 | }, 90 | "execution_count": null, 91 | "outputs": [] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "source": [ 96 | "# Figure 9.2: Linear approximation" 97 | ], 98 | "metadata": { 99 | "id": "_3tFncFOy1yh" 100 | } 101 | }, 102 | { 103 | "cell_type": "code", 104 | "source": [ 105 | "x = np.linspace(0,6,345)\n", 106 | "\n", 107 | "# function and derivative\n", 108 | "fx = lambda u: np.sqrt(u) + 2*u\n", 109 | "df = lambda u: 1/(2*np.sqrt(u)) + 2\n", 110 | "\n", 111 | "# two points\n", 112 | "xs = 4\n", 113 | "xa = 4.37\n", 114 | "\n", 115 | "# linear approximation\n", 116 | "L = df(xs)*(xa-xs) + fx(xs)\n", 117 | "\n", 118 | "# draw the plot\n", 119 | "fig,ax1 = plt.subplots(1,figsize=(10,5))\n", 120 | "ax1.plot(x,fx(x),'k',label=r'$f(x) = \\sqrt{x}+2x$')\n", 121 | "ax1.plot(xs,fx(xs),'ks',markerfacecolor=[.7,.7,.7],markersize=9,label=rf'$f(x_s)=${fx(xs):.1f}')\n", 122 | "ax1.plot(xa,fx(xa),'ko',markerfacecolor='w',markersize=12,label=rf'$f(x_a)=${fx(xa):.4f}')\n", 123 | "ax1.plot(xa,L,'k^',markerfacecolor='gray',markersize=12,label=rf'$L=${L:.4f}')\n", 124 | "ax1.set(xlim=x[[0,-1]],xlabel='$x$',ylabel='$y$')\n", 125 | "ax1.legend()\n", 126 | "\n", 127 | "\n", 128 | "# draw the inset\n", 129 | "ax2 = fig.add_axes([.7,.3,.2,.3])\n", 130 | "ax2.plot(x,fx(x),'k',label=r'$f(x)$')\n", 131 | "ax2.plot(xa,fx(xa),'ko',markerfacecolor='w',markersize=12)\n", 132 | "ax2.plot(xa,L,'k^',markerfacecolor='gray',markersize=12)\n", 133 | "ax2.set(xlim=[4.369,4.3711],ylim=[10.825,10.838])\n", 134 | "ax2.spines[['top','right']].set_visible(True)\n", 135 | "\n", 136 | "# save\n", 137 | "plt.tight_layout()\n", 138 | "plt.savefig('diffApps_linApprox1.png')\n", 139 | "plt.show()" 140 | ], 141 | "metadata": { 142 | "id": "lNUuBLtqy3r5" 143 | }, 144 | "execution_count": null, 145 | "outputs": [] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "source": [], 150 | "metadata": { 151 | "id": "bhYgLFrGy1sy" 152 | }, 153 | "execution_count": null, 154 | "outputs": [] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "source": [ 159 | "# Figure 9.3: Second example of linear approximation" 160 | ], 161 | "metadata": { 162 | "id": "LQWJHggFbWQE" 163 | } 164 | }, 165 | { 166 | "cell_type": "code", 167 | "source": [ 168 | "x = np.linspace(0,2*np.pi,345)\n", 169 | "\n", 170 | "# function and derivative\n", 171 | "fx = lambda u: np.abs(np.sin(u))\n", 172 | "df = lambda u: np.sign(np.sin(u)) * np.cos(u)\n", 173 | "\n", 174 | "# two points\n", 175 | "xs = np.pi/2\n", 176 | "xa = 5*np.pi/8\n", 177 | "\n", 178 | "# linear approximation\n", 179 | "L = df(xs)*(xa-xs) + fx(xs)\n", 180 | "\n", 181 | "# draw the plot\n", 182 | "fig,ax1 = plt.subplots(1,figsize=(10,5))\n", 183 | "ax1.plot(x,fx(x),'k',label=r'$f(x) = |\\,\\sin(x)\\,|$')\n", 184 | "ax1.plot(xs,fx(xs),'ks',markerfacecolor=[.7,.7,.7],markersize=9,label=rf'$f(x_s)=${fx(xs):.1f}')\n", 185 | "ax1.plot(xa,fx(xa),'ko',markerfacecolor='w',markersize=12,label=rf'$f(x_a)=${fx(xa):.4f}')\n", 186 | "ax1.plot(xa,L,'k^',markerfacecolor='gray',markersize=12,label=rf'$L=${L:.4f}')\n", 187 | "ax1.set(xlim=x[[0,-1]],xlabel='$x$',ylabel='$y$')\n", 188 | "ax1.legend()\n", 189 | "\n", 190 | "\n", 191 | "# save\n", 192 | "plt.tight_layout()\n", 193 | "plt.savefig('diffApps_linApprox2.png')\n", 194 | "plt.show()" 195 | ], 196 | "metadata": { 197 | "id": "J_eZG-oby1pm" 198 | }, 199 | "execution_count": null, 200 | "outputs": [] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "source": [], 205 | "metadata": { 206 | "id": "PDcefAA4y1mg" 207 | }, 208 | "execution_count": null, 209 | "outputs": [] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "source": [ 214 | "# Figure 9.4: Newton's method" 215 | ], 216 | "metadata": { 217 | "id": "AzPsT7mndsAb" 218 | } 219 | }, 220 | { 221 | "cell_type": "code", 222 | "source": [ 223 | "# Writing code to create this figure is part of Exercise 9.6." 224 | ], 225 | "metadata": { 226 | "id": "JW1Dw-N1BAMm" 227 | }, 228 | "execution_count": null, 229 | "outputs": [] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "source": [], 234 | "metadata": { 235 | "id": "1rjFw9kmdr9c" 236 | }, 237 | "execution_count": null, 238 | "outputs": [] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "source": [ 243 | "# Figure 9.7: Optimization demo" 244 | ], 245 | "metadata": { 246 | "id": "91E_-zthw4AE" 247 | } 248 | }, 249 | { 250 | "cell_type": "code", 251 | "source": [ 252 | "# formulas\n", 253 | "xx = np.linspace(0,30,299)\n", 254 | "Ax = 50*xx - 2*xx**2\n", 255 | "dA = 50 - 4*xx\n", 256 | "\n", 257 | "_,axs = plt.subplots(2,1,figsize=(10,6))\n", 258 | "\n", 259 | "axs[0].plot(xx,Ax,'k')\n", 260 | "axs[0].set(xlim=xx[[0,-1]],ylim=[-300,400],xlabel='Length of side x',ylabel='Area')\n", 261 | "axs[0].set_title(r'$\\bf{A}$) $A(x) = 50x - 2x^2$')\n", 262 | "\n", 263 | "axs[1].plot(xx,dA,'k')\n", 264 | "axs[1].axhline(0,linestyle='--',color=[.6,.6,.6],zorder=-3)\n", 265 | "axs[1].set(xlim=xx[[0,-1]],ylim=[-70,50],xlabel='Length of side x')\n", 266 | "axs[1].set_title(r\"$\\bf{B}$) $A'(x) = 50 - 4x$\")\n", 267 | "\n", 268 | "plt.tight_layout()\n", 269 | "plt.savefig('diffApps_optimizationDemo.png')\n", 270 | "plt.show()" 271 | ], 272 | "metadata": { 273 | "id": "VpwfL9dGw58t" 274 | }, 275 | "execution_count": null, 276 | "outputs": [] 277 | }, 278 | { 279 | "cell_type": "code", 280 | "source": [], 281 | "metadata": { 282 | "id": "f0vUHYBdeM02" 283 | }, 284 | "execution_count": null, 285 | "outputs": [] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "source": [ 290 | "# Figure 9.9: Optimize for surface area" 291 | ], 292 | "metadata": { 293 | "id": "N9Z8jmeweMyz" 294 | } 295 | }, 296 | { 297 | "cell_type": "code", 298 | "source": [ 299 | "xx = np.linspace(.1,100,299)\n", 300 | "Px = 2*xx + 200/xx\n", 301 | "dP = 2 - 200/(xx**2)\n", 302 | "\n", 303 | "_,axs = plt.subplots(2,1,figsize=(10,6))\n", 304 | "\n", 305 | "axs[0].plot(xx,Px,'k')\n", 306 | "axs[0].set(xlim=xx[[0,-1]],ylim=[0,400],xlabel='Length of garden side x',ylabel='Perimeter')\n", 307 | "axs[0].set_title(r'$\\bf{A}$) $P(x) = 2x + 200x^{-1}$')\n", 308 | "\n", 309 | "axs[1].plot(xx,dP,'k')\n", 310 | "axs[1].axhline(0,linestyle='--',color=[.6,.6,.6])\n", 311 | "axs[1].set(xlim=xx[[0,-1]],ylim=[-5,5],xlabel='Length of garden side x')\n", 312 | "axs[1].set_title(r\"$\\bf{B}$) $P'(x) = 2 - 200x^{-2}$\")\n", 313 | "\n", 314 | "plt.tight_layout()\n", 315 | "plt.savefig('diffApps_OptimizeSurfaceArea.png')\n", 316 | "plt.show()" 317 | ], 318 | "metadata": { 319 | "id": "FZ58cnN5eOyZ" 320 | }, 321 | "execution_count": null, 322 | "outputs": [] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "source": [], 327 | "metadata": { 328 | "id": "sopIUaM8eMuY" 329 | }, 330 | "execution_count": null, 331 | "outputs": [] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "source": [ 336 | "# Figure 9.11: Optimize for volume" 337 | ], 338 | "metadata": { 339 | "id": "sY2ELh7LuIlw" 340 | } 341 | }, 342 | { 343 | "cell_type": "code", 344 | "source": [ 345 | "# formulas\n", 346 | "xx = np.linspace(0,45,299)\n", 347 | "Vx = 4*xx**3 - 250*xx**2 + 3600*xx\n", 348 | "dV = 12*xx**2 - 500*xx + 3600\n", 349 | "\n", 350 | "_,axs = plt.subplots(2,1,figsize=(10,6))\n", 351 | "\n", 352 | "axs[0].plot(xx,Vx,'k')\n", 353 | "axs[0].set(xlim=xx[[0,-1]],ylim=[-10000,20000],xlabel='Size of cutout edge',ylabel='Area')\n", 354 | "axs[0].set_title(r'$\\bf{A}$) $V(x) = 4x^3 - 250x^2 + 3600x$')\n", 355 | "\n", 356 | "axs[1].plot(xx,dV,'k')\n", 357 | "axs[1].axhline(0,linestyle='--',color=[.6,.6,.6],zorder=-3)\n", 358 | "axs[1].set(xlim=xx[[0,-1]],ylim=[-2000,5000],xlabel='Size of cutout edge')\n", 359 | "axs[1].set_title(r\"$\\bf{B}$) $V'(x) = 12x^2 - 500x + 3600$\")\n", 360 | "\n", 361 | "plt.tight_layout()\n", 362 | "plt.savefig('diffApps_OptimizeVolume.png')\n", 363 | "plt.show()" 364 | ], 365 | "metadata": { 366 | "id": "wfQS5U_0uIl4" 367 | }, 368 | "execution_count": null, 369 | "outputs": [] 370 | }, 371 | { 372 | "cell_type": "code", 373 | "source": [ 374 | "# solution to the problem\n", 375 | "x = sym.symbols('x')\n", 376 | "sym.solve(12*x**2 - 500*x + 3600)" 377 | ], 378 | "metadata": { 379 | "id": "WkH7p4CTeMoG" 380 | }, 381 | "execution_count": null, 382 | "outputs": [] 383 | }, 384 | { 385 | "cell_type": "code", 386 | "source": [ 387 | "(x**3 - 250*x**2 + 3600*x).subs(x,sym.solve(12*x**2 - 500*x + 3600)[0]).evalf()" 388 | ], 389 | "metadata": { 390 | "id": "ZZugr5d3eMlR" 391 | }, 392 | "execution_count": null, 393 | "outputs": [] 394 | }, 395 | { 396 | "cell_type": "code", 397 | "source": [], 398 | "metadata": { 399 | "id": "6loOweDNjWeQ" 400 | }, 401 | "execution_count": null, 402 | "outputs": [] 403 | } 404 | ] 405 | } -------------------------------------------------------------------------------- /figures/ch11_differentialArt_figures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyP0rI1tLYgRiiL3nySVVPwW" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "IMCG77qiecTi" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 11 (Differential art!)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook will reproduce the figures in this chapter, and illustrate the mathematical concepts explained in the book. The point of providing the code is not just for you to recreate the figures, but for you to modify, adapt, explore, and experiment with the code.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "jb67RuPgecTj" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "2V_FVoKJKf2V" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "from IPython.display import Math\n", 72 | "\n", 73 | "# define global figure properties used for publication\n", 74 | "import matplotlib_inline.backend_inline\n", 75 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 76 | "plt.rcParams.update({'font.size':14, # font size\n", 77 | " 'savefig.dpi':300, # output resolution\n", 78 | " 'axes.titlelocation':'left',# title location\n", 79 | " 'axes.spines.right':False, # remove axis bounding box\n", 80 | " 'axes.spines.top':False, # remove axis bounding box\n", 81 | " 'lines.linewidth':2 # increase default line thickness\n", 82 | " })" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "source": [], 88 | "metadata": { 89 | "id": "3e1EXYUxAzG0" 90 | }, 91 | "execution_count": null, 92 | "outputs": [] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "source": [ 97 | "# Figures 11.1-2: Elf hat and to infinity" 98 | ], 99 | "metadata": { 100 | "id": "SsdmhFFPXwv5" 101 | } 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": { 107 | "id": "aMh6FjHbbLCq" 108 | }, 109 | "outputs": [], 110 | "source": [ 111 | "# make a function that computes the tangent line, loop through lots of points\n", 112 | "\n", 113 | "def computetangent(f,xa,bnds):\n", 114 | "\n", 115 | " # define function and derivative values at that point\n", 116 | " df = sym.diff(f)\n", 117 | " fa = f.subs(x,xa)\n", 118 | " df_a = df.subs(x,xa)\n", 119 | "\n", 120 | " # Figure 11.1: calculate and return the tangent line\n", 121 | " return df_a * (bnds - xa) + fa\n", 122 | "\n", 123 | " # for Figure 11.2, use the following line (line that is normal to the tangent)\n", 124 | " # return (-1/df_a) * (bnds - xa) + fa" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "source": [ 130 | "x = sym.symbols('x')\n", 131 | "f = -x**2\n", 132 | "xx = np.linspace(-2,2,300)\n", 133 | "\n", 134 | "# plot the tangents\n", 135 | "plt.figure(figsize=(4,5))\n", 136 | "for i in xx:\n", 137 | " yy = computetangent(f,i,xx[[0,-1]]*(abs(i)+2)/4)\n", 138 | " plt.plot(xx[[0,-1]],yy,color=[abs(i)/(1.5*np.max(xx)),.2,abs(i)/np.max(xx)],linewidth=.5)\n", 139 | "\n", 140 | "plt.axis([xx[0],xx[-1],-2,4])\n", 141 | "plt.axis('off')\n", 142 | "\n", 143 | "plt.tight_layout()\n", 144 | "plt.savefig('diffart_elfhat.png')\n", 145 | "plt.show()" 146 | ], 147 | "metadata": { 148 | "id": "5j2pH5R9LPri" 149 | }, 150 | "execution_count": null, 151 | "outputs": [] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "source": [], 156 | "metadata": { 157 | "id": "LNGwl8fyHQbE", 158 | "collapsed": true 159 | }, 160 | "execution_count": null, 161 | "outputs": [] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "source": [ 166 | "# Figure 11.3: Acorn from Ooo" 167 | ], 168 | "metadata": { 169 | "id": "QdUiz5n_X5-a" 170 | } 171 | }, 172 | { 173 | "cell_type": "code", 174 | "source": [ 175 | "x = np.linspace(-1,1,201)\n", 176 | "\n", 177 | "plt.figure(figsize=(10,6))\n", 178 | "for xi in x:\n", 179 | "\n", 180 | " # the bottom (note the - sign to get negative y values)\n", 181 | " y = -np.sqrt(2**2 - (x+xi)**2)\n", 182 | " plt.plot(x,y,color=[.4,abs(xi/2),xi**2])\n", 183 | "\n", 184 | " # the top (all positive y)\n", 185 | " y = np.sqrt((.1+xi**2)**2 - x**2)\n", 186 | " plt.plot(x,y,color=[.2,xi**4,abs(xi/2)])\n", 187 | "\n", 188 | "\n", 189 | "plt.axis('off')\n", 190 | "\n", 191 | "plt.tight_layout()\n", 192 | "plt.savefig('diffart_acornOoo.png')\n", 193 | "plt.show()" 194 | ], 195 | "metadata": { 196 | "id": "ejkE7FGQX8Ed" 197 | }, 198 | "execution_count": null, 199 | "outputs": [] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "source": [], 204 | "metadata": { 205 | "id": "d4Mqm-0_X5sL" 206 | }, 207 | "execution_count": null, 208 | "outputs": [] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "source": [ 213 | "# Figure 11.4: Gray waves" 214 | ], 215 | "metadata": { 216 | "id": "-ORTDCB9kaJk" 217 | } 218 | }, 219 | { 220 | "cell_type": "code", 221 | "source": [ 222 | "# theta variable and offsets\n", 223 | "th = np.linspace(-np.pi,np.pi,500)\n", 224 | "offsets = np.linspace(-.1,.1,20)\n", 225 | "\n", 226 | "\n", 227 | "# loop over offsets to plot each line\n", 228 | "_,axs = plt.subplots(2,2,figsize=(10,5))\n", 229 | "for i in offsets:\n", 230 | "\n", 231 | " # the functions\n", 232 | " fth1 = (th+i)**2 * np.exp(-th**2) * np.log(th**2) * np.sin(th)\n", 233 | " fth2 = th**2 * np.exp(-(th+i)**2) * np.log(th**2) * np.sin(th)\n", 234 | " fth3 = th**2 * np.exp(-th**2) * np.log((th+i)**2) * np.sin(th)\n", 235 | " fth4 = th**2 * np.exp(-th**2) * np.log(th**2) * np.sin(th+i)\n", 236 | "\n", 237 | " # color for this line\n", 238 | " c = abs(i/np.max(offsets))*.7\n", 239 | "\n", 240 | " # draw the lines\n", 241 | " axs[0,0].plot(th,fth1,color=[c,c,c])\n", 242 | " axs[0,1].plot(th,fth2,color=[c,c,c])\n", 243 | " axs[1,0].plot(th,fth3,color=[c,c,c])\n", 244 | " axs[1,1].plot(th,fth4,color=[c,c,c])\n", 245 | "\n", 246 | "\n", 247 | "# final adjustments\n", 248 | "for a in axs.flatten():\n", 249 | " a.set_xlim(th[[0,-1]])\n", 250 | " a.axis('off')\n", 251 | "\n", 252 | "plt.tight_layout()\n", 253 | "plt.savefig('diffart_graywaves.png')\n", 254 | "plt.show()" 255 | ], 256 | "metadata": { 257 | "id": "DpBU7m2SX5pD" 258 | }, 259 | "execution_count": null, 260 | "outputs": [] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "source": [], 265 | "metadata": { 266 | "id": "a-jvXGL4klXS" 267 | }, 268 | "execution_count": null, 269 | "outputs": [] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "source": [ 274 | "# Figure 11.5: Fun by diff" 275 | ], 276 | "metadata": { 277 | "id": "3I94lL3dkh--" 278 | } 279 | }, 280 | { 281 | "cell_type": "code", 282 | "source": [ 283 | "theta = sym.symbols('theta')\n", 284 | "display(Math('f(\\\\theta) = %s' %sym.latex(theta**2 * sym.exp(-theta**2) * sym.log(theta**2) * sym.sin(theta))))\n", 285 | "display(Math('df(\\\\theta) = %s' %sym.latex(sym.diff(theta**2 * sym.exp(-theta**2) * sym.log(theta**2) * sym.sin(theta)))))" 286 | ], 287 | "metadata": { 288 | "id": "ri0txiNOX3Iv" 289 | }, 290 | "execution_count": null, 291 | "outputs": [] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "source": [ 296 | "# Note: In the book I use a white background, but I think it looks good on a black backround as well.\n", 297 | "# Add a 1- when defining the color to get the color-inverted version.\n", 298 | "\n", 299 | "# loop over offsets to plot each line\n", 300 | "plt.figure(figsize=(6,5),facecolor='k')\n", 301 | "for i in offsets:\n", 302 | "\n", 303 | " # the functions\n", 304 | " fth = sym.lambdify(theta, theta**2 * sym.exp(-(theta+i)**2) * sym.log(theta**2) * sym.sin(theta) )\n", 305 | " dfth = sym.lambdify(theta, sym.diff(theta**2 * sym.exp(-theta**2) * sym.log((theta+i)**2) * sym.sin(theta) ))\n", 306 | "\n", 307 | " # color for this line\n", 308 | " c = abs(i/np.max(offsets))*.7\n", 309 | "\n", 310 | " # draw the lines\n", 311 | " plt.plot(fth(th),dfth(th),color=[c,c,c])\n", 312 | "\n", 313 | "\n", 314 | "plt.axis('off')\n", 315 | "plt.tight_layout()\n", 316 | "plt.savefig('diffart_funbydiff.png')\n", 317 | "plt.show()" 318 | ], 319 | "metadata": { 320 | "id": "JX-gfM8TX3MH" 321 | }, 322 | "execution_count": null, 323 | "outputs": [] 324 | }, 325 | { 326 | "cell_type": "code", 327 | "source": [], 328 | "metadata": { 329 | "id": "k9qU8XPrX3FY" 330 | }, 331 | "execution_count": null, 332 | "outputs": [] 333 | }, 334 | { 335 | "cell_type": "markdown", 336 | "source": [ 337 | "# Figure 11.6: Dancing petals" 338 | ], 339 | "metadata": { 340 | "id": "1bmH3skkklUn" 341 | } 342 | }, 343 | { 344 | "cell_type": "code", 345 | "source": [ 346 | "x = np.linspace(-5,5,453)\n", 347 | "\n", 348 | "for i in np.linspace(.001,1,30):\n", 349 | " plt.plot(x,x/(x**2+i),color=np.full(3,np.sqrt(i)))\n", 350 | " plt.plot(x,np.log(x**2+i)/2,color=[(1+np.cos(2*np.pi*i))/2,.2,i],alpha=1-(i-.5)**2)\n", 351 | "\n", 352 | "plt.gca().set(xlim=x[[0,-1]],ylim=[-2.5,2.5])\n", 353 | "plt.axis('off')\n", 354 | "\n", 355 | "plt.tight_layout()\n", 356 | "plt.savefig('diffart_dancingPetals.png')\n", 357 | "plt.show()" 358 | ], 359 | "metadata": { 360 | "id": "MIn9lPOykmWb" 361 | }, 362 | "execution_count": null, 363 | "outputs": [] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "source": [], 368 | "metadata": { 369 | "id": "NEqB1S5QZdWv" 370 | }, 371 | "execution_count": null, 372 | "outputs": [] 373 | }, 374 | { 375 | "cell_type": "markdown", 376 | "source": [ 377 | "# Figure 11.7: Radial curves" 378 | ], 379 | "metadata": { 380 | "id": "OucpAkXfePk7" 381 | } 382 | }, 383 | { 384 | "cell_type": "code", 385 | "source": [ 386 | "fig,axs = plt.subplots(3,3,figsize=(10,8))\n", 387 | "axs = axs.ravel()\n", 388 | "\n", 389 | "t = np.linspace(-6*np.pi,6*np.pi,1000)\n", 390 | "\n", 391 | "for i in range(9):\n", 392 | "\n", 393 | " # define the coordinates\n", 394 | " x = t**i * np.cos(t)**3\n", 395 | " y = t**i * np.sin(t)**3\n", 396 | "\n", 397 | " # plot\n", 398 | " axs[i].plot(x,y,'k')\n", 399 | " axs[i].axis('off')\n", 400 | "\n", 401 | "plt.tight_layout()\n", 402 | "plt.savefig('diffart_radialcurves.png')\n", 403 | "plt.show()" 404 | ], 405 | "metadata": { 406 | "id": "tFNTAg5dkn5U" 407 | }, 408 | "execution_count": null, 409 | "outputs": [] 410 | }, 411 | { 412 | "cell_type": "code", 413 | "source": [], 414 | "metadata": { 415 | "id": "vpZr954Gn20N" 416 | }, 417 | "execution_count": null, 418 | "outputs": [] 419 | }, 420 | { 421 | "cell_type": "markdown", 422 | "source": [ 423 | "# Figure 11.8: Rose curves" 424 | ], 425 | "metadata": { 426 | "id": "CU5HySiJn2vh" 427 | } 428 | }, 429 | { 430 | "cell_type": "code", 431 | "source": [ 432 | "fig,axs = plt.subplots(3,3,figsize=(10,8))\n", 433 | "axs = axs.ravel()\n", 434 | "\n", 435 | "kk = np.linspace(0,1.5,9)\n", 436 | "t = np.linspace(0,4*np.pi,500)\n", 437 | "\n", 438 | "for i in range(9):\n", 439 | "\n", 440 | " k = kk[i]\n", 441 | "\n", 442 | " x = np.cos(k*t) * np.cos(t)\n", 443 | " y = np.cos(k*t) * np.sin(t)\n", 444 | "\n", 445 | " # marker-specific colors\n", 446 | " c = np.vstack(\n", 447 | " (np.linspace(-.6,1,len(t))**2, # red\n", 448 | " np.ones(len(t))*.2, # green\n", 449 | " np.sin(np.linspace(0,2*np.pi,len(t)))/2+.5, # blue\n", 450 | " np.ones(len(t)) # alpha (transparency; not manipulated here but for you to explore)\n", 451 | " ) ).T\n", 452 | "\n", 453 | " axs[i].scatter(x,y,s=np.linspace(2,150,len(t)),c=c)\n", 454 | " axs[i].axis('off')\n", 455 | " axs[i].axis('square')\n", 456 | " axs[i].set_title('k=%s'%k,loc='center')\n", 457 | "\n", 458 | "\n", 459 | "plt.tight_layout()\n", 460 | "plt.savefig('diffart_roseCurves.png')\n", 461 | "plt.show()" 462 | ], 463 | "metadata": { 464 | "id": "CDiojpCsn2sZ" 465 | }, 466 | "execution_count": null, 467 | "outputs": [] 468 | }, 469 | { 470 | "cell_type": "code", 471 | "source": [], 472 | "metadata": { 473 | "id": "DAmjbr3yhgCu" 474 | }, 475 | "execution_count": null, 476 | "outputs": [] 477 | }, 478 | { 479 | "cell_type": "markdown", 480 | "source": [ 481 | "# Figure 11.9: Riemann's complex nondifferentiable ice cream cone" 482 | ], 483 | "metadata": { 484 | "id": "HF1wdS5Whf_3" 485 | } 486 | }, 487 | { 488 | "cell_type": "code", 489 | "source": [ 490 | "x = np.linspace(0,np.pi,5001)\n", 491 | "\n", 492 | "# generate the function\n", 493 | "topN = np.logspace(np.log10(5),np.log10(300),55).astype(int)\n", 494 | "colors = np.linspace(.9,0,len(topN))\n", 495 | "\n", 496 | "plt.figure(figsize=(6,8))\n", 497 | "\n", 498 | "for thisN,color in zip(topN,colors):\n", 499 | "\n", 500 | " # initialize y\n", 501 | " y = np.zeros(len(x),dtype=complex)\n", 502 | "\n", 503 | " # calculate\n", 504 | " for n in range(1,thisN):\n", 505 | " y += np.exp( 1j*np.pi*x*n**2 ) / (1j*np.pi*n**2)\n", 506 | "\n", 507 | " plt.plot(np.real(y),np.imag(y),c=np.full(3,color))\n", 508 | "\n", 509 | "\n", 510 | "plt.axis('off')\n", 511 | "plt.tight_layout()\n", 512 | "plt.savefig('diffart_riemann.png')\n", 513 | "plt.show()" 514 | ], 515 | "metadata": { 516 | "id": "s1eYe-Gphj5k" 517 | }, 518 | "execution_count": null, 519 | "outputs": [] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "source": [], 524 | "metadata": { 525 | "id": "zgusQMaGn2pR" 526 | }, 527 | "execution_count": null, 528 | "outputs": [] 529 | }, 530 | { 531 | "cell_type": "markdown", 532 | "source": [ 533 | "# Figure 11.10: Mandelbrot set" 534 | ], 535 | "metadata": { 536 | "id": "vute7rCCdBzS" 537 | } 538 | }, 539 | { 540 | "cell_type": "code", 541 | "source": [ 542 | "# parameters\n", 543 | "n = 1000 # matrix size (probably not higher than 5k)\n", 544 | "k = 40 # number of iterations\n", 545 | "\n", 546 | "# define ranges of real and imaginary axes\n", 547 | "re = np.linspace(-1.5,.5,n)\n", 548 | "im = np.linspace(-1,1,n)\n", 549 | "\n", 550 | "# define matrices for computations\n", 551 | "[X,Y] = np.meshgrid(re,im)\n", 552 | "C = X + 1j*Y\n", 553 | "Z = np.zeros_like(C,dtype=complex)\n", 554 | "M = np.zeros_like(C,dtype=float)\n", 555 | "\n", 556 | "\n", 557 | "# loop over iterations\n", 558 | "for i in range(k):\n", 559 | "\n", 560 | " # compute quadratic map\n", 561 | " Z = Z**2 + C\n", 562 | "\n", 563 | " # find elements exceeding |Z|>2 at this iteration\n", 564 | " # and set their value to be the iteration\n", 565 | " M[(np.abs(Z)>2) & (M==0)] = i\n", 566 | " # Note: changing only the M==0 elements makes the colors more striking.\n", 567 | "\n", 568 | "\n", 569 | "\n", 570 | "# show the quadratic map matrices\n", 571 | "_,axs = plt.subplots(1,3,figsize=(10,4))\n", 572 | "axs[0].imshow(M,extent=[re[0],re[-1],im[-1],im[0]],cmap='gray')\n", 573 | "axs[0].set(xticks=[],yticks=[],xlabel='Real',ylabel='Imag',title=r'$\\bf{A}$) Exceedance count')\n", 574 | "\n", 575 | "axs[1].imshow(np.abs(Z),extent=[re[0],re[-1],im[-1],im[0]],cmap='gray',vmin=.1,vmax=.6)\n", 576 | "axs[1].set(xticks=[],yticks=[],xlabel='Real',ylabel='Imag',title=r'$\\bf{B}$) Magnitude')\n", 577 | "\n", 578 | "axs[2].imshow(np.angle(Z),extent=[re[0],re[-1],im[-1],im[0]],cmap='gray')\n", 579 | "axs[2].set(xticks=[],yticks=[],xlabel='Real',ylabel='Imag',title=r'$\\bf{C}$) Phase')\n", 580 | "\n", 581 | "plt.tight_layout()\n", 582 | "plt.savefig('diffart_mandelbrot.png')\n", 583 | "plt.show()" 584 | ], 585 | "metadata": { 586 | "id": "FovnhI6yX54b" 587 | }, 588 | "execution_count": null, 589 | "outputs": [] 590 | }, 591 | { 592 | "cell_type": "code", 593 | "source": [], 594 | "metadata": { 595 | "id": "kTdBotRBd0dW" 596 | }, 597 | "execution_count": null, 598 | "outputs": [] 599 | } 600 | ] 601 | } -------------------------------------------------------------------------------- /figures/ch12_integrationIntuition_figures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyOFaAL9TmPoGcQxCOmr79zT" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "IMCG77qiecTi" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 12 (Intuition for integration)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook will reproduce the figures in this chapter, and illustrate the mathematical concepts explained in the book. The point of providing the code is not just for you to recreate the figures, but for you to modify, adapt, explore, and experiment with the code.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "jb67RuPgecTj" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "34Xt73jrJbNe" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "\n", 72 | "# define global figure properties used for publication\n", 73 | "import matplotlib_inline.backend_inline\n", 74 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 75 | "plt.rcParams.update({'font.size':14, # font size\n", 76 | " 'savefig.dpi':300, # output resolution\n", 77 | " 'axes.titlelocation':'left',# title location\n", 78 | " 'axes.spines.right':False, # remove axis bounding box\n", 79 | " 'axes.spines.top':False, # remove axis bounding box\n", 80 | " 'lines.linewidth':2 # increase default line thickness\n", 81 | " })" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "source": [], 87 | "metadata": { 88 | "id": "8lwxjMICKChw" 89 | }, 90 | "execution_count": null, 91 | "outputs": [] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "source": [ 96 | "# Figure 12.1: Cumulative sum" 97 | ], 98 | "metadata": { 99 | "id": "h1i9wYhlKCe5" 100 | } 101 | }, 102 | { 103 | "cell_type": "code", 104 | "source": [ 105 | "# example from the book\n", 106 | "v = np.array([ 1, 3, 0, -2, 4 ])\n", 107 | "c = np.cumsum(v)\n", 108 | "\n", 109 | "# another example of integrated white noise\n", 110 | "n = np.random.randn(100)\n", 111 | "s = np.cumsum(n)\n", 112 | "\n", 113 | "# y\n", 114 | "ymax = np.max(abs(s))+.5\n", 115 | "\n", 116 | "_,axs = plt.subplots(2,2,figsize=(12,6))\n", 117 | "\n", 118 | "# plot the book example\n", 119 | "axs[0,0].plot(v,'ks-',markerfacecolor='w',markersize=10)\n", 120 | "axs[0,0].grid()\n", 121 | "axs[0,0].set(xlim=[-.2,4.2],ylim=[-2.3,6.3],title=r'$\\bf{A}$) Function ($\\bf{v}$)')\n", 122 | "\n", 123 | "axs[1,0].plot(c,'ko-',markerfacecolor=[.7,.7,.7],markersize=10)\n", 124 | "axs[1,0].grid()\n", 125 | "axs[1,0].set(xlim=[-.2,4.2],ylim=[-2.3,6.3],title=r'$\\bf{B}$) Cumulative sum ($\\bf{c}$)')\n", 126 | "\n", 127 | "# plot the noise\n", 128 | "axs[0,1].plot(n,'ks-',markerfacecolor='w',markersize=8)\n", 129 | "axs[0,1].set(xlim=[-2,102],ylim=[-ymax,ymax],title=r'$\\bf{C}$) Data')\n", 130 | "\n", 131 | "axs[1,1].plot(s,'ko-',markerfacecolor=[.7,.7,.7],markersize=8)\n", 132 | "axs[1,1].set(xlim=[-2,102],ylim=[-ymax,ymax],title=r'$\\bf{D}$) Cumulative sum')\n", 133 | "\n", 134 | "\n", 135 | "# save\n", 136 | "plt.tight_layout()\n", 137 | "plt.savefig('intint_cumsum.png')\n", 138 | "plt.show()" 139 | ], 140 | "metadata": { 141 | "id": "bcemJT60KER0" 142 | }, 143 | "execution_count": null, 144 | "outputs": [] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "source": [], 149 | "metadata": { 150 | "id": "7ARr9DcdlYr6" 151 | }, 152 | "execution_count": null, 153 | "outputs": [] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "source": [ 158 | "# Figure 12.2: Comparing approximate and analytic integrals" 159 | ], 160 | "metadata": { 161 | "id": "WRSNVu2VlYpC" 162 | } 163 | }, 164 | { 165 | "cell_type": "code", 166 | "source": [ 167 | "dx = .1\n", 168 | "x = np.arange(-2,4,step=dx)\n", 169 | "\n", 170 | "fx = x**2\n", 171 | "intf_true = x**3/3\n", 172 | "intf_approx = np.cumsum(fx) * dx\n", 173 | "\n", 174 | "# normalize\n", 175 | "zeroidx = np.argmin(abs(x))\n", 176 | "intf_approx -= intf_approx[zeroidx]\n", 177 | "\n", 178 | "plt.figure(figsize=(8,4))\n", 179 | "plt.plot(x,intf_approx,'ko',markerfacecolor='w',markersize=8,label='Empirical integral')\n", 180 | "plt.plot(x,intf_true,'k',label='Analytic integral')\n", 181 | "\n", 182 | "plt.legend()\n", 183 | "plt.gca().set(xlim=[x[0]-dx,x[-1]+dx],xlabel='x',ylabel='y')\n", 184 | "\n", 185 | "plt.tight_layout()\n", 186 | "plt.savefig('intint_intApproxTrue.png')\n", 187 | "plt.show()" 188 | ], 189 | "metadata": { 190 | "id": "ltReFUz_lb8P" 191 | }, 192 | "execution_count": null, 193 | "outputs": [] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "source": [], 198 | "metadata": { 199 | "id": "mXao9gqMT9x2" 200 | }, 201 | "execution_count": null, 202 | "outputs": [] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "source": [ 207 | "# Figure 12.3: Area of a constant function" 208 | ], 209 | "metadata": { 210 | "id": "2SVbx_d7T9u-" 211 | } 212 | }, 213 | { 214 | "cell_type": "code", 215 | "source": [ 216 | "x = np.linspace(0,5,99)\n", 217 | "\n", 218 | "fx = np.ones(len(x)) * 2\n", 219 | "\n", 220 | "plt.figure(figsize=(10,3))\n", 221 | "\n", 222 | "plt.plot(x,fx,'k',label=r'$f(x) = 2$')\n", 223 | "plt.gca().set(xlim=x[[0,-1]],xticks=range(5),xticklabels=[0,'$a$',2,3,'$b$'],\n", 224 | " ylim=[0,2.5],yticks=[0,1,2],xlabel='x',ylabel=r'$y = f(x)$')\n", 225 | "\n", 226 | "plt.fill_between([1,4],[0,0],[2,2],color='k',alpha=.2,label='Bounded region')\n", 227 | "\n", 228 | "plt.legend()\n", 229 | "plt.tight_layout()\n", 230 | "plt.savefig('intint_calcArea1.png')\n", 231 | "plt.show()" 232 | ], 233 | "metadata": { 234 | "id": "VqwYn9TLUAlL" 235 | }, 236 | "execution_count": null, 237 | "outputs": [] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "source": [], 242 | "metadata": { 243 | "id": "4dxp9mgtT9sI" 244 | }, 245 | "execution_count": null, 246 | "outputs": [] 247 | }, 248 | { 249 | "cell_type": "markdown", 250 | "source": [ 251 | "# Figure 12.4: Approximating area using rectangles" 252 | ], 253 | "metadata": { 254 | "id": "MPi-mr4FT9pR" 255 | } 256 | }, 257 | { 258 | "cell_type": "code", 259 | "source": [ 260 | "# function for the function\n", 261 | "def fx(u):\n", 262 | " return u**2 + .2" 263 | ], 264 | "metadata": { 265 | "id": "_xOO301LOt54" 266 | }, 267 | "execution_count": null, 268 | "outputs": [] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "source": [ 273 | "# plot the function\n", 274 | "_,axs = plt.subplots(1,3,figsize=(14,4))\n", 275 | "\n", 276 | "\n", 277 | "## panel A: the analytic result\n", 278 | "x = np.linspace(-.5,1,101)\n", 279 | "axs[0].plot(x,fx(x),'k')\n", 280 | "\n", 281 | "# and its true (analytically calculated) area\n", 282 | "sx = sym.symbols('sx')\n", 283 | "trueArea = sym.integrate(sx**2+.2,(sx,x[0],x[-1]))\n", 284 | "axs[0].fill_between(x,np.zeros(len(x)),fx(x),edgecolor=[.6,.6,.6],facecolor='k',alpha=.2)\n", 285 | "\n", 286 | "\n", 287 | "\n", 288 | "### panel B: one rectangle\n", 289 | "axs[1].plot(x,fx(x),'k')\n", 290 | "axs[1].fill_between(x[[0,-1]],[0,0],np.full(2,np.mean(fx(x[[0,-1]]))),edgecolor=[.6,.6,.6],facecolor='k',alpha=.2)\n", 291 | "area1 = (x[-1]-x[0]) * np.mean(fx(x[[0,-1]]))\n", 292 | "\n", 293 | "\n", 294 | "\n", 295 | "\n", 296 | "### panel C: the low-res approximation\n", 297 | "xx = np.linspace(x[0]+.1,x[-1]-.1,5)\n", 298 | "dx = xx[1] - xx[0]\n", 299 | "\n", 300 | "# initialize area\n", 301 | "area5 = 0\n", 302 | "\n", 303 | "# plot the function again\n", 304 | "axs[2].plot(x,fx(x),'k')\n", 305 | "\n", 306 | "# plot rectangles\n", 307 | "for xi in xx:\n", 308 | "\n", 309 | " # draw the rectangle\n", 310 | " axs[2].fill_between([xi-dx/2,xi+dx/2],[fx(xi),fx(xi)],edgecolor=[.6,.6,.6],facecolor='k',alpha=.2)\n", 311 | "\n", 312 | " # sum the area\n", 313 | " area5 += fx(xi)*dx\n", 314 | "\n", 315 | "# set the labels\n", 316 | "axs[0].set(xlabel='x',ylabel=r'$y = x^2+.5$',xlim=[xx[0]-dx/2,xx[-1]+dx/2],xticks=[-.5,0,.5,1],xticklabels=['$a$',0,.5,'$b$'],\n", 317 | " title=r'$\\bf{A}$) True area = %.3f' %trueArea)\n", 318 | "axs[1].set(xlabel='x',ylabel=r'$y = x^2+.5$',xlim=[xx[0]-dx/2,xx[-1]+dx/2],xticks=[-.5,0,.5,1],xticklabels=['$a$',0,.5,'$b$'],\n", 319 | " title=r'$\\bf{B}$) Approximate area = %.3f' %area1)\n", 320 | "axs[2].set(xlabel='x',ylabel=r'$y = x^2+.5$',xlim=[xx[0]-dx/2,xx[-1]+dx/2],xticks=[-.5,0,.5,1],xticklabels=['$a$',0,.5,'$b$'],\n", 321 | " title=r'$\\bf{C}$) Approximate area = %.3f' %area5)\n", 322 | "axs[0].axhline(0,linestyle='--',color='k',linewidth=1)\n", 323 | "axs[1].axhline(0,linestyle='--',color='k',linewidth=1)\n", 324 | "axs[2].axhline(0,linestyle='--',color='k',linewidth=1)\n", 325 | "\n", 326 | "\n", 327 | "# finalize plot\n", 328 | "plt.tight_layout()\n", 329 | "plt.savefig('intint_approxArea5.png')\n", 330 | "plt.show()" 331 | ], 332 | "metadata": { 333 | "id": "GJI5MiO-Vu-v" 334 | }, 335 | "execution_count": null, 336 | "outputs": [] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "source": [], 341 | "metadata": { 342 | "id": "jQ-Zvq-sKCbx" 343 | }, 344 | "execution_count": null, 345 | "outputs": [] 346 | }, 347 | { 348 | "cell_type": "markdown", 349 | "source": [ 350 | "# Figure 12.6: A wobbly function" 351 | ], 352 | "metadata": { 353 | "id": "SqhQTqJQntpk" 354 | } 355 | }, 356 | { 357 | "cell_type": "code", 358 | "source": [ 359 | "# the function\n", 360 | "x = np.linspace(-5,5,804)\n", 361 | "fx = 4*x + 3*np.sin(3*x) + np.sqrt(abs(x))/np.log(x**2)\n", 362 | "\n", 363 | "# remove specious vertical lines\n", 364 | "fx[np.argmin(abs(x+1))] = np.nan\n", 365 | "fx[np.argmin(abs(x-1))] = np.nan\n", 366 | "\n", 367 | "# and plot\n", 368 | "plt.figure(figsize=(5,4))\n", 369 | "plt.plot(x,fx,'k')\n", 370 | "plt.gca().set(xlim=x[[0,-1]],ylim=[-20,20],xlabel='x',ylabel='y = f(x)')\n", 371 | "\n", 372 | "plt.tight_layout()\n", 373 | "plt.savefig('intint_wobble.png')\n", 374 | "plt.show()" 375 | ], 376 | "metadata": { 377 | "id": "zzaNxuSzmXLH" 378 | }, 379 | "execution_count": null, 380 | "outputs": [] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "source": [], 385 | "metadata": { 386 | "id": "WOXBuwwQczWe" 387 | }, 388 | "execution_count": null, 389 | "outputs": [] 390 | } 391 | ] 392 | } -------------------------------------------------------------------------------- /figures/ch13_geometryIntegration_figures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyMYfjOYT3Vhoq10wHaMGDc6" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "IMCG77qiecTi" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 13 (Geometry of integration)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook will reproduce the figures in this chapter, and illustrate the mathematical concepts explained in the book. The point of providing the code is not just for you to recreate the figures, but for you to modify, adapt, explore, and experiment with the code.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "jb67RuPgecTj" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "ZlcDVQ-m-I-U" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "from IPython.display import Math\n", 72 | "\n", 73 | "# define global figure properties used for publication\n", 74 | "import matplotlib_inline.backend_inline\n", 75 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 76 | "plt.rcParams.update({'font.size':14, # font size\n", 77 | " 'savefig.dpi':300, # output resolution\n", 78 | " 'axes.titlelocation':'left',# title location\n", 79 | " 'axes.spines.right':False, # remove axis bounding box\n", 80 | " 'axes.spines.top':False, # remove axis bounding box\n", 81 | " 'lines.linewidth':2 # increase default line thickness\n", 82 | " })" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "source": [], 88 | "metadata": { 89 | "id": "8lwxjMICKChw" 90 | }, 91 | "execution_count": null, 92 | "outputs": [] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "source": [ 97 | "# Figure 13.1: Overview of Riemann approximation" 98 | ], 99 | "metadata": { 100 | "id": "J3p3BhpYkvir" 101 | } 102 | }, 103 | { 104 | "cell_type": "code", 105 | "source": [ 106 | "xx = np.linspace(.5,4,179)\n", 107 | "fx = lambda u: np.sqrt(u) + np.cos(2*u)\n", 108 | "\n", 109 | "\n", 110 | "# specify bounds\n", 111 | "a,b = 1,3.5\n", 112 | "n = 8\n", 113 | "deltax = (b-a)/n\n", 114 | "breakPoints = [ a+deltax*i for i in range(n+1) ]\n", 115 | "\n", 116 | "\n", 117 | "# show the function, bounds, area, and breakpoints\n", 118 | "plt.figure(figsize=(10,4))\n", 119 | "\n", 120 | "# same for all plots\n", 121 | "plt.plot(xx,fx(xx),'k',linewidth=2,label=r'$f(x) = \\sqrt{x} + \\cos(x)$')\n", 122 | "plt.axvline(a,color=[.4,.4,.4],linestyle='--',label=f'a = {a:.2f}')\n", 123 | "plt.axvline(b,color=[.4,.4,.4],linestyle=':',label=f'b = {b:.2f}')\n", 124 | "plt.gca().set(xlabel='x',ylabel=r'$y=f(x)$',xlim=xx[[0,-1]],ylim=[0,3])\n", 125 | "\n", 126 | "\n", 127 | "# now for the bars\n", 128 | "for i in range(n):\n", 129 | "\n", 130 | " # bars for midpoint rule\n", 131 | " bp = breakPoints[i]\n", 132 | " bp += deltax/2 # shift breakpoint by deltax/2\n", 133 | " plt.fill_between([bp-deltax/2,bp+deltax/2],[fx(bp),fx(bp)],color='k',alpha=.2)\n", 134 | "\n", 135 | "plt.legend()\n", 136 | "plt.tight_layout()\n", 137 | "plt.savefig('geoApprox_riemannIntro.png')\n", 138 | "plt.show()" 139 | ], 140 | "metadata": { 141 | "id": "KBX4UOWzkvfn" 142 | }, 143 | "execution_count": null, 144 | "outputs": [] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "source": [], 149 | "metadata": { 150 | "id": "C2jN21Cdkvci" 151 | }, 152 | "execution_count": null, 153 | "outputs": [] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "source": [ 158 | "# Figure 13.7: Margin figure with negative area" 159 | ], 160 | "metadata": { 161 | "id": "h1i9wYhlKCe5" 162 | } 163 | }, 164 | { 165 | "cell_type": "code", 166 | "source": [ 167 | "x = np.linspace(.5,4,179)\n", 168 | "fx = -np.sqrt(x) + np.cos(2*x)\n", 169 | "\n", 170 | "plt.figure(figsize=(5,5))\n", 171 | "plt.plot(x,fx,'k')\n", 172 | "plt.axhline(0,color=[.7,.7,.7],linestyle='--')\n", 173 | "plt.fill_between(x[(x>1) & (x<3.5)],fx[(x>1) & (x<3.5)],color='k',alpha=.2)\n", 174 | "\n", 175 | "plt.ylim([-2.4,.3])\n", 176 | "plt.xlim(x[[0,-1]])\n", 177 | "\n", 178 | "plt.tight_layout()\n", 179 | "plt.savefig('geoApprox_negNet.png')\n", 180 | "plt.show()" 181 | ], 182 | "metadata": { 183 | "id": "4pHi-kjxlYmK" 184 | }, 185 | "execution_count": null, 186 | "outputs": [] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "source": [], 191 | "metadata": { 192 | "id": "SzdysHe-lYjD" 193 | }, 194 | "execution_count": null, 195 | "outputs": [] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "source": [ 200 | "# Figure 13.8: Margin figure showing zero net area" 201 | ], 202 | "metadata": { 203 | "id": "wn_e2O_Kg0G4" 204 | } 205 | }, 206 | { 207 | "cell_type": "code", 208 | "source": [ 209 | "x = np.linspace(0,3*np.pi,179)\n", 210 | "fx = np.cos(x)\n", 211 | "vals2highlight = (x>np.pi/2) & (x<3*np.pi-np.pi/2)\n", 212 | "\n", 213 | "plt.figure(figsize=(5,5))\n", 214 | "plt.plot(x,fx,'k')\n", 215 | "plt.axhline(0,color=[.7,.7,.7],linestyle='--')\n", 216 | "plt.fill_between(x[vals2highlight],fx[vals2highlight],color='k',alpha=.2)\n", 217 | "plt.xlim(x[[0,-1]])\n", 218 | "\n", 219 | "plt.tight_layout()\n", 220 | "plt.savefig('geoApprox_zeroNet.png')\n", 221 | "plt.show()" 222 | ], 223 | "metadata": { 224 | "id": "3757GAWmlYgL" 225 | }, 226 | "execution_count": null, 227 | "outputs": [] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "source": [], 232 | "metadata": { 233 | "id": "jQ-Zvq-sKCbx" 234 | }, 235 | "execution_count": null, 236 | "outputs": [] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "source": [ 241 | "# Figure 13.10: Calculating total area" 242 | ], 243 | "metadata": { 244 | "id": "iUgYztZgRU1R" 245 | } 246 | }, 247 | { 248 | "cell_type": "code", 249 | "source": [ 250 | "t = np.linspace(0,2*np.pi,503)\n", 251 | "f = np.cos(t)\n", 252 | "\n", 253 | "_,axs = plt.subplots(1,2,figsize=(12,4))\n", 254 | "\n", 255 | "# plot the function and patches\n", 256 | "axs[0].plot(t,f,'k')\n", 257 | "axs[0].fill_between(t[tnp.pi/2) & (t<3*np.pi/2)],f[(t>np.pi/2) & (t<3*np.pi/2)],color='k',alpha=.5)\n", 259 | "axs[0].fill_between(t[t>3*np.pi/2],f[t>3*np.pi/2],color='k',alpha=.2)\n", 260 | "axs[0].set_title(r'$\\bf{A}$) Area by absolute values of segments')\n", 261 | "\n", 262 | "axs[1].plot(t,abs(f),'k')\n", 263 | "axs[1].fill_between(t,abs(f),color='k',alpha=.2)\n", 264 | "axs[1].set_title(r'$\\bf{B}$) Area by absolute value of function')\n", 265 | "\n", 266 | "# ajust the axes\n", 267 | "for a in axs:\n", 268 | " a.set(xlim=t[[0,-1]],ylim=[-1.1,1.1],xlabel='$x$',xticks=[0,np.pi/2,3*np.pi/2,2*np.pi],xticklabels=['a','b','c','d'])\n", 269 | " a.axhline(0,color=[.8,.8,.8],linestyle='--',zorder=-3)\n", 270 | "\n", 271 | "plt.tight_layout()\n", 272 | "plt.savefig('geoApprox_how2total.png')\n", 273 | "plt.show()" 274 | ], 275 | "metadata": { 276 | "id": "fc7ZUpx1RUyU" 277 | }, 278 | "execution_count": null, 279 | "outputs": [] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "source": [], 284 | "metadata": { 285 | "id": "ouWSRCXdsH8C" 286 | }, 287 | "execution_count": null, 288 | "outputs": [] 289 | }, 290 | { 291 | "cell_type": "markdown", 292 | "source": [ 293 | "# Figure 13.11: Definite integrals in sympy" 294 | ], 295 | "metadata": { 296 | "id": "PTOWDx4dT9jh" 297 | } 298 | }, 299 | { 300 | "cell_type": "code", 301 | "source": [ 302 | "x = sym.symbols('x')\n", 303 | "\n", 304 | "# the function and the bounds\n", 305 | "expr = x**2\n", 306 | "a,b = 0,2\n", 307 | "\n", 308 | "# the result\n", 309 | "area = sym.integrate(expr,(x,a,b))\n", 310 | "\n", 311 | "# printed\n", 312 | "display(Math('\\int_{%s}^{%s} %s \\,dx = %s'\n", 313 | " %(a,b,sym.latex(expr),sym.latex(area))))" 314 | ], 315 | "metadata": { 316 | "id": "kPnUMWR8T9ga" 317 | }, 318 | "execution_count": null, 319 | "outputs": [] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "source": [ 324 | "xx = np.linspace(a-.5,b+.5,179)\n", 325 | "vals2highlight = (xx>a) & (xx\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 15 (Improper integrals)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook will reproduce the figures in this chapter, and illustrate the mathematical concepts explained in the book. The point of providing the code is not just for you to recreate the figures, but for you to modify, adapt, explore, and experiment with the code.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "jb67RuPgecTj" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "mS30EfltAyAr" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "\n", 72 | "# define global figure properties used for publication\n", 73 | "import matplotlib_inline.backend_inline\n", 74 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 75 | "plt.rcParams.update({'font.size':14, # font size\n", 76 | " 'savefig.dpi':300, # output resolution\n", 77 | " 'axes.titlelocation':'left',# title location\n", 78 | " 'axes.spines.right':False, # remove axis bounding box\n", 79 | " 'axes.spines.top':False, # remove axis bounding box\n", 80 | " 'lines.linewidth':2 # increase default line thickness\n", 81 | " })" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "source": [], 87 | "metadata": { 88 | "id": "8lwxjMICKChw" 89 | }, 90 | "execution_count": null, 91 | "outputs": [] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "source": [ 96 | "# Figure 15.1: Example improper integral" 97 | ], 98 | "metadata": { 99 | "id": "h1i9wYhlKCe5" 100 | } 101 | }, 102 | { 103 | "cell_type": "code", 104 | "source": [ 105 | "x = np.linspace(-3,20,999)\n", 106 | "f = 1 / x**2\n", 107 | "\n", 108 | "plt.figure(figsize=(4,4))\n", 109 | "plt.plot(x,f,'k',label=r'$f(x)=x^{-2}$')\n", 110 | "plt.fill_between(x[x>1],f[x>1],color='k',alpha=.2,label=r'$\\int_{1}^{\\infty}f(x)\\,dx$')\n", 111 | "\n", 112 | "plt.gca().set(xlim=x[[0,-1]],xlabel='$x$',ylim=[0,1])\n", 113 | "plt.legend(fontsize=16)\n", 114 | "\n", 115 | "plt.tight_layout()\n", 116 | "plt.savefig('improper_oneBndEx1.png')\n", 117 | "plt.show()" 118 | ], 119 | "metadata": { 120 | "id": "6VyoU8GuW8mB" 121 | }, 122 | "execution_count": null, 123 | "outputs": [] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "source": [], 128 | "metadata": { 129 | "id": "yzQZY-wr4XBr" 130 | }, 131 | "execution_count": null, 132 | "outputs": [] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "source": [ 137 | "# Figure 15.2: Example 2" 138 | ], 139 | "metadata": { 140 | "id": "Ul2moNk24W-3" 141 | } 142 | }, 143 | { 144 | "cell_type": "code", 145 | "source": [ 146 | "x = np.linspace(-5,20,999)\n", 147 | "f = np.pi / x**3\n", 148 | "f[np.argmin(abs(x))] = np.nan\n", 149 | "\n", 150 | "plt.figure(figsize=(4,4))\n", 151 | "plt.plot(x,f,'k',label=r'$f(x)=\\pi x^{-3}$')\n", 152 | "plt.fill_between(x[x>1],f[x>1],color='k',alpha=.2,label=r'$\\int_{1}^{\\infty}f(x)\\,dx$')\n", 153 | "\n", 154 | "plt.gca().set(xlim=x[[0,-1]],xlabel='$x$',ylim=[-.6,1])\n", 155 | "plt.legend(fontsize=16)\n", 156 | "\n", 157 | "plt.grid(color=[.8,.8,.8])\n", 158 | "plt.tight_layout()\n", 159 | "plt.savefig('improper_oneBndEx2.png')\n", 160 | "plt.show()" 161 | ], 162 | "metadata": { 163 | "id": "5FPIAqTVW8jJ" 164 | }, 165 | "execution_count": null, 166 | "outputs": [] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "source": [], 171 | "metadata": { 172 | "id": "kq-ncHWF4Zk9" 173 | }, 174 | "execution_count": null, 175 | "outputs": [] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "source": [ 180 | "# Figure 15.3: Example 3" 181 | ], 182 | "metadata": { 183 | "id": "rBl1FARY4ZiF" 184 | } 185 | }, 186 | { 187 | "cell_type": "code", 188 | "source": [ 189 | "x = np.linspace(-20,10,999)\n", 190 | "f = x**4\n", 191 | "\n", 192 | "plt.figure(figsize=(4,4))\n", 193 | "plt.plot(x,f,'k',label=r'$f(x)=x^4$')\n", 194 | "plt.fill_between(x[x<-1],f[x<-1],color='k',alpha=.2,label=r'$\\int_{-\\infty}^{-1}f(x)\\,dx$')\n", 195 | "\n", 196 | "plt.gca().set(xlim=x[[0,-1]],xlabel='$x$')\n", 197 | "plt.legend(fontsize=16)\n", 198 | "\n", 199 | "plt.tight_layout()\n", 200 | "plt.savefig('improper_oneBndEx3.png')\n", 201 | "plt.show()" 202 | ], 203 | "metadata": { 204 | "id": "qz7JBjZSW8gg" 205 | }, 206 | "execution_count": null, 207 | "outputs": [] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "source": [], 212 | "metadata": { 213 | "id": "ekD7GYBS4eie" 214 | }, 215 | "execution_count": null, 216 | "outputs": [] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "source": [ 221 | "# Figure 15.4: Example convergent area" 222 | ], 223 | "metadata": { 224 | "id": "eCkAGvJ44efT" 225 | } 226 | }, 227 | { 228 | "cell_type": "code", 229 | "source": [ 230 | "x = np.linspace(-15,3,999)\n", 231 | "f = 1/(x**2+x)\n", 232 | "f[np.argmin(abs(x))] = np.nan # remove vertical lines from the plot\n", 233 | "f[np.argmin(abs(x--1))] = np.nan\n", 234 | "\n", 235 | "plt.figure(figsize=(4,4))\n", 236 | "plt.plot(x,f,'k',label=r'$f(x)=(x^2+x)^{-1}$')\n", 237 | "plt.fill_between(x[x<-2],f[x<-2],color='k',alpha=.2,label=r'$\\int_{-\\infty}^{-2}f(x)\\,dx$')\n", 238 | "\n", 239 | "plt.gca().set(xlim=x[[0,-1]],xlabel='$x$',ylim=[-.1,1])\n", 240 | "plt.legend(fontsize=16)\n", 241 | "\n", 242 | "plt.tight_layout()\n", 243 | "plt.savefig('improper_convergence.png')\n", 244 | "plt.show()" 245 | ], 246 | "metadata": { 247 | "id": "sjfDTawmW8dY" 248 | }, 249 | "execution_count": null, 250 | "outputs": [] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "source": [], 255 | "metadata": { 256 | "id": "pX7CmKe04lqp" 257 | }, 258 | "execution_count": null, 259 | "outputs": [] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "source": [ 264 | "# Figure 15.5: Example divergent area" 265 | ], 266 | "metadata": { 267 | "id": "wZXqVvmk4lnh" 268 | } 269 | }, 270 | { 271 | "cell_type": "code", 272 | "source": [ 273 | "x = np.linspace(.1,10,999)\n", 274 | "f = 1/np.sqrt(x)\n", 275 | "\n", 276 | "plt.figure(figsize=(4,4))\n", 277 | "plt.plot(x,f,'k',label=r'$f(x)=x^{-1/2}$')\n", 278 | "plt.fill_between(x[x>1],f[x>1],color='k',alpha=.2,label=r'$\\int_{1}^{\\infty}f(x)\\,dx$')\n", 279 | "\n", 280 | "plt.gca().set(xlim=x[[0,-1]],xlabel='$x$',ylim=[0,3])\n", 281 | "plt.legend(fontsize=16)\n", 282 | "\n", 283 | "plt.tight_layout()\n", 284 | "plt.savefig('improper_divergence.png')\n", 285 | "plt.show()" 286 | ], 287 | "metadata": { 288 | "id": "Es-1kG-w6wGF" 289 | }, 290 | "execution_count": null, 291 | "outputs": [] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "source": [], 296 | "metadata": { 297 | "id": "FexNr1Uz6wDJ" 298 | }, 299 | "execution_count": null, 300 | "outputs": [] 301 | }, 302 | { 303 | "cell_type": "markdown", 304 | "source": [ 305 | "# Figure 15.6: Double-infinite bounds" 306 | ], 307 | "metadata": { 308 | "id": "6yVQs6on4uXw" 309 | } 310 | }, 311 | { 312 | "cell_type": "code", 313 | "source": [ 314 | "x = np.linspace(-10,10,999)\n", 315 | "f = np.exp(x) / (1+np.exp(x))\n", 316 | "\n", 317 | "plt.figure(figsize=(10,4))\n", 318 | "plt.plot(x,f,'k',label=r'$f(x) = e^{x-1}\\left(1+e^{x-1}\\right)^{-1}$')\n", 319 | "plt.plot(x,np.log(np.exp(x-1)+1),color=[.3,.3,.3],linestyle='--',label=r'$F(x)=\\ln(e^{x-1}+1)$')\n", 320 | "plt.fill_between(x,f,color='k',alpha=.2,label=r'$\\int_{-\\infty}^{\\infty}f(x)\\,dx$')\n", 321 | "plt.axvline(1,linestyle=':',color=[.7,.7,.7],label=r'$x=1$')\n", 322 | "\n", 323 | "plt.gca().set(xlim=x[[0,-1]],xlabel='$x$',ylabel='$y$ or $Y$',ylim=[0,2])\n", 324 | "plt.legend(fontsize=18)\n", 325 | "\n", 326 | "plt.tight_layout()\n", 327 | "plt.savefig('improper_doubleInfEx1.png')\n", 328 | "plt.show()" 329 | ], 330 | "metadata": { 331 | "id": "qfMQwnKo6wAX" 332 | }, 333 | "execution_count": null, 334 | "outputs": [] 335 | }, 336 | { 337 | "cell_type": "code", 338 | "source": [], 339 | "metadata": { 340 | "id": "126LYypF6v9X" 341 | }, 342 | "execution_count": null, 343 | "outputs": [] 344 | }, 345 | { 346 | "cell_type": "markdown", 347 | "source": [ 348 | "# Figure 15.7: Second example of double-infinite bounds" 349 | ], 350 | "metadata": { 351 | "id": "vDVI9Em143_2" 352 | } 353 | }, 354 | { 355 | "cell_type": "code", 356 | "source": [ 357 | "x = np.linspace(-8,8,999)\n", 358 | "f = 4*x / (x**4+2)\n", 359 | "\n", 360 | "plt.figure(figsize=(10,4))\n", 361 | "plt.plot(x,f,'k',label=r'$f(x) = 4x\\left(x^4+2\\right)^{-1}$')\n", 362 | "plt.plot(x,np.sqrt(2)*np.arctan(np.sqrt(2)*x**2/2),color=[.3,.3,.3],linestyle='--',label=r'$F(x) = \\sqrt{2} \\tan^{-1}{\\left(\\frac{\\sqrt{2} x^{2}}{2} \\right)}$')\n", 363 | "plt.fill_between(x,f,color='k',alpha=.2,label=r'$\\int_{-\\infty}^{\\infty}f(x)\\,dx$')\n", 364 | "\n", 365 | "plt.gca().set(xlim=x[[0,-1]],xlabel='$x$',ylabel='$y$ or $Y$',ylim=[-1.5,2.5])\n", 366 | "plt.legend(fontsize=16,loc=(.01,.4))\n", 367 | "\n", 368 | "plt.tight_layout()\n", 369 | "plt.savefig('improper_doubleInfEx2.png')\n", 370 | "plt.show()" 371 | ], 372 | "metadata": { 373 | "id": "t-4HVXOc6v6d" 374 | }, 375 | "execution_count": null, 376 | "outputs": [] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "source": [], 381 | "metadata": { 382 | "id": "F66C-nYI6v3a" 383 | }, 384 | "execution_count": null, 385 | "outputs": [] 386 | }, 387 | { 388 | "cell_type": "markdown", 389 | "source": [ 390 | "# Figure 15.8: Infinite sin" 391 | ], 392 | "metadata": { 393 | "id": "VkCpMdHW6v0d" 394 | } 395 | }, 396 | { 397 | "cell_type": "code", 398 | "source": [ 399 | "plt.figure(figsize=(4,4))\n", 400 | "th = np.linspace(0,10*np.pi,987)\n", 401 | "\n", 402 | "plt.plot(th,np.sin(th),'k')\n", 403 | "plt.fill_between(th,np.sin(th),color='k',alpha=.2)\n", 404 | "plt.gca().set(xlim=th[[0,-1]],xticks=np.arange(0,th[-1]+.1,2*np.pi),xticklabels=[],\n", 405 | " xlabel='$\\\\theta$',yticks=[-1,0,1])\n", 406 | "\n", 407 | "plt.tight_layout()\n", 408 | "plt.savefig('improper_sin2inf.png')\n", 409 | "plt.show()" 410 | ], 411 | "metadata": { 412 | "id": "f7Y3v2SAh96s" 413 | }, 414 | "execution_count": null, 415 | "outputs": [] 416 | }, 417 | { 418 | "cell_type": "code", 419 | "source": [ 420 | "x = sym.symbols('x')\n", 421 | "f = sym.sin(x)\n", 422 | "sym.integrate(f,(x,0,sym.oo))" 423 | ], 424 | "metadata": { 425 | "id": "aY3gY3YJgam8" 426 | }, 427 | "execution_count": null, 428 | "outputs": [] 429 | }, 430 | { 431 | "cell_type": "code", 432 | "source": [], 433 | "metadata": { 434 | "id": "DpDkRSQlN0q1" 435 | }, 436 | "execution_count": null, 437 | "outputs": [] 438 | }, 439 | { 440 | "cell_type": "markdown", 441 | "source": [ 442 | "# Figures 15.9-10: Morlet wavelet" 443 | ], 444 | "metadata": { 445 | "id": "fqJMjehoN0ho" 446 | } 447 | }, 448 | { 449 | "cell_type": "code", 450 | "source": [ 451 | "# function\n", 452 | "th = np.linspace(-np.pi,np.pi,987)\n", 453 | "f = np.cos(2*np.pi*th)*np.exp(-th**2)\n", 454 | "\n", 455 | "# figure\n", 456 | "plt.figure(figsize=(4,4))\n", 457 | "plt.plot(th,f,'k',linewidth=1)\n", 458 | "plt.fill_between(th,f,color='k',alpha=.2)\n", 459 | "plt.gca().set(xlim=th[[0,-1]],ylim=[-.85,1],yticks=[-.5,0,.5,1])\n", 460 | "\n", 461 | "plt.tight_layout()\n", 462 | "plt.savefig('improper_morlet.png')\n", 463 | "plt.show()" 464 | ], 465 | "metadata": { 466 | "id": "qLx1ka3IN0e-" 467 | }, 468 | "execution_count": null, 469 | "outputs": [] 470 | }, 471 | { 472 | "cell_type": "code", 473 | "source": [ 474 | "theta = sym.symbols('theta')\n", 475 | "\n", 476 | "freq = 2*sym.pi\n", 477 | "f = sym.cos(freq*theta)*sym.exp(-theta**2)\n", 478 | "sym.integrate(f,(theta,-sym.oo,sym.oo))" 479 | ], 480 | "metadata": { 481 | "id": "H8-XBuLmCXwn" 482 | }, 483 | "execution_count": null, 484 | "outputs": [] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "source": [], 489 | "metadata": { 490 | "id": "D-2ew7DX6vup" 491 | }, 492 | "execution_count": null, 493 | "outputs": [] 494 | }, 495 | { 496 | "cell_type": "markdown", 497 | "source": [ 498 | "# Figure 15.12: Jump discontinuity" 499 | ], 500 | "metadata": { 501 | "id": "g8NLooWY6vra" 502 | } 503 | }, 504 | { 505 | "cell_type": "code", 506 | "source": [ 507 | "x = np.linspace(-2.2,1,457)\n", 508 | "\n", 509 | "plt.figure(figsize=(4,4))\n", 510 | "plt.plot(x[x<0],x[x<0]/2,'k')\n", 511 | "plt.fill_between(x[(x<0) & (x>-2)],x[(x<0) & (x>-2)]/2,color='k',alpha=.2)\n", 512 | "\n", 513 | "plt.plot(x[x>=0],x[x>=0]**2+1,'k')\n", 514 | "plt.fill_between(x[x>=0],x[x>=0]**2+1,color='k',alpha=.2)\n", 515 | "\n", 516 | "plt.legend([r'$f(x)$',r'$\\int_{-2}^1 f(x)\\,dx$'],fontsize=17)\n", 517 | "plt.xlim(x[[0,-1]])\n", 518 | "\n", 519 | "plt.tight_layout()\n", 520 | "plt.savefig('improper_jumpDiscontinuity.png')\n", 521 | "plt.show()" 522 | ], 523 | "metadata": { 524 | "id": "caCBcLtPIH49" 525 | }, 526 | "execution_count": null, 527 | "outputs": [] 528 | }, 529 | { 530 | "cell_type": "code", 531 | "source": [], 532 | "metadata": { 533 | "id": "MKZRqIrJ5Lkw" 534 | }, 535 | "execution_count": null, 536 | "outputs": [] 537 | }, 538 | { 539 | "cell_type": "markdown", 540 | "source": [ 541 | "# Figure 15.13: Antiderivative of piecewise function" 542 | ], 543 | "metadata": { 544 | "id": "yr_RLhFI5Lhk" 545 | } 546 | }, 547 | { 548 | "cell_type": "code", 549 | "source": [ 550 | "x = np.linspace(-2,1,457)\n", 551 | "\n", 552 | "plt.figure(figsize=(4,4))\n", 553 | "plt.plot(x[x<0],x[x<0]**2/4,'k')\n", 554 | "plt.plot(x[x>=0],x[x>=0]**3/3+x[x>=0],'--',color=[.7,.7,.7])\n", 555 | "\n", 556 | "plt.legend([r'$\\int f_1(x)\\,dx$',r'$\\int f_2(x)\\,dx$'],fontsize=17)\n", 557 | "\n", 558 | "plt.tight_layout()\n", 559 | "plt.savefig('improper_jumpDiscontinuitySol.png')\n", 560 | "plt.show()" 561 | ], 562 | "metadata": { 563 | "id": "u8IJcRCtIIv_" 564 | }, 565 | "execution_count": null, 566 | "outputs": [] 567 | }, 568 | { 569 | "cell_type": "code", 570 | "source": [], 571 | "metadata": { 572 | "id": "ZtWbsPyZIIys" 573 | }, 574 | "execution_count": null, 575 | "outputs": [] 576 | }, 577 | { 578 | "cell_type": "markdown", 579 | "source": [ 580 | "# Figure 15.14: Infinite discontinuity" 581 | ], 582 | "metadata": { 583 | "id": "SObcaVgTII1S" 584 | } 585 | }, 586 | { 587 | "cell_type": "code", 588 | "source": [ 589 | "x = np.linspace(1.0001,2.2,503)\n", 590 | "\n", 591 | "_,axs = plt.subplots(1,2,figsize=(10,3))\n", 592 | "axs[0].plot(x,1/np.sqrt(x-1),'k')\n", 593 | "axs[0].fill_between(x[x<2],1/np.sqrt(x[x<2]-1),color='k',alpha=.2)\n", 594 | "axs[0].set(ylim=[0,5],title=r'$\\bf{A}$) $f(x)=\\left(\\sqrt{x-1}\\right)^{-1}$')\n", 595 | "\n", 596 | "axs[1].plot(x,2*np.sqrt(x-1),'k')\n", 597 | "axs[1].set(title=r'$\\bf{B}$) $\\int f(x)\\,dx = 2\\sqrt{x-1}+C$')\n", 598 | "\n", 599 | "plt.tight_layout()\n", 600 | "plt.savefig('improper_infDiscontinuity.png')\n", 601 | "plt.show()" 602 | ], 603 | "metadata": { 604 | "id": "ItchIDP9PDaV" 605 | }, 606 | "execution_count": null, 607 | "outputs": [] 608 | }, 609 | { 610 | "cell_type": "code", 611 | "source": [], 612 | "metadata": { 613 | "id": "rLzlESMfPDdm" 614 | }, 615 | "execution_count": null, 616 | "outputs": [] 617 | }, 618 | { 619 | "cell_type": "markdown", 620 | "source": [ 621 | "# Figure 15.15: Removable discontinuity" 622 | ], 623 | "metadata": { 624 | "id": "j_W3uu36PDgO" 625 | } 626 | }, 627 | { 628 | "cell_type": "code", 629 | "source": [ 630 | "x = np.linspace(-.5,4.5,503)\n", 631 | "\n", 632 | "_,axs = plt.subplots(1,2,figsize=(10,3))\n", 633 | "axs[0].plot(x,(x**2-2*x)/(x**2-4),'k')\n", 634 | "whereInt = x[(x>=0) & (x<=4)]\n", 635 | "axs[0].fill_between(whereInt,(whereInt**2-2*whereInt)/(whereInt**2-4),color='k',alpha=.2)\n", 636 | "axs[0].set(xlim=x[[0,-1]],title=r'$\\bf{A}$) $f(x)$')\n", 637 | "\n", 638 | "axs[1].plot(x,x-2*np.log(x+2),'k')\n", 639 | "axs[1].set(title=r'$\\bf{B}$) $\\int f(x)\\,dx$')\n", 640 | "\n", 641 | "plt.tight_layout()\n", 642 | "plt.savefig('improper_popDiscontinuity.png')\n", 643 | "plt.show()" 644 | ], 645 | "metadata": { 646 | "id": "Ymhgjiqna8dC" 647 | }, 648 | "execution_count": null, 649 | "outputs": [] 650 | }, 651 | { 652 | "cell_type": "code", 653 | "source": [], 654 | "metadata": { 655 | "id": "HClQzA6X_wPX" 656 | }, 657 | "execution_count": null, 658 | "outputs": [] 659 | } 660 | ] 661 | } -------------------------------------------------------------------------------- /figures/ch16_integrationTechniques_figures.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "authorship_tag": "ABX9TyNoWk4ZPoWiCHgPzzsnituS" 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "language_info": { 15 | "name": "python" 16 | } 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "markdown", 21 | "metadata": { 22 | "id": "IMCG77qiecTi" 23 | }, 24 | "source": [ 25 | "\"Open" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "source": [ 31 | "# **Calculus unraveled: Intuition, Proofs, and Python**\n", 32 | "### Mike X Cohen (sincxpress.com)\n", 33 | "#### https://github.com/mikexcohen/calculus_book\n", 34 | "#### Code for Chapter 16 (Integration techniques)\n", 35 | "\n", 36 | "---\n", 37 | "\n", 38 | "# About this code file:\n", 39 | "\n", 40 | "### This notebook will reproduce the figures in this chapter, and illustrate the mathematical concepts explained in the book. The point of providing the code is not just for you to recreate the figures, but for you to modify, adapt, explore, and experiment with the code.\n", 41 | "\n", 42 | "## **Using the code without the book may lead to confusion or errors.**\n", 43 | "\n", 44 | "#### This code was written in google-colab. The notebook may require some modifications if you use a different IDE." 45 | ], 46 | "metadata": { 47 | "id": "jb67RuPgecTj" 48 | } 49 | }, 50 | { 51 | "cell_type": "code", 52 | "source": [], 53 | "metadata": { 54 | "id": "WCDwZtBaCLu2" 55 | }, 56 | "execution_count": null, 57 | "outputs": [] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "id": "oYWhHwGQ9OdD" 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "# import libraries and define global settings\n", 68 | "import numpy as np\n", 69 | "import sympy as sym\n", 70 | "import matplotlib.pyplot as plt\n", 71 | "from IPython.display import Math\n", 72 | "\n", 73 | "# define global figure properties used for publication\n", 74 | "import matplotlib_inline.backend_inline\n", 75 | "matplotlib_inline.backend_inline.set_matplotlib_formats('svg') # display figures in vector format\n", 76 | "plt.rcParams.update({'font.size':14, # font size\n", 77 | " 'savefig.dpi':300, # output resolution\n", 78 | " 'axes.titlelocation':'left',# title location\n", 79 | " 'axes.spines.right':False, # remove axis bounding box\n", 80 | " 'axes.spines.top':False, # remove axis bounding box\n", 81 | " 'lines.linewidth':2 # increase default line thickness\n", 82 | " })" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "source": [], 88 | "metadata": { 89 | "id": "8lwxjMICKChw" 90 | }, 91 | "execution_count": null, 92 | "outputs": [] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "source": [ 97 | "# showing my work :P\n", 98 | "x = sym.symbols('x')\n", 99 | "f = (3*x**4 + 5)**6 * x**3\n", 100 | "\n", 101 | "print(sym.latex(sym.expand(f)))\n", 102 | "print(sym.latex(sym.integrate(sym.expand(f))))" 103 | ], 104 | "metadata": { 105 | "id": "6VyoU8GuW8mB" 106 | }, 107 | "execution_count": null, 108 | "outputs": [] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "source": [], 113 | "metadata": { 114 | "id": "5FPIAqTVW8jJ" 115 | }, 116 | "execution_count": null, 117 | "outputs": [] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "source": [ 122 | "# Figure 16.1: u-sub example 1" 123 | ], 124 | "metadata": { 125 | "id": "h1i9wYhlKCe5" 126 | } 127 | }, 128 | { 129 | "cell_type": "code", 130 | "source": [ 131 | "x = np.linspace(-13,13,453)\n", 132 | "fx = x / (x**2+2)\n", 133 | "fi = np.log(x**2+2) / 2\n", 134 | "\n", 135 | "plt.figure(figsize=(8,3))\n", 136 | "plt.plot(x,fx,'k',label=r'$f(x) = x(x^2+2)^{-1}$')\n", 137 | "plt.plot(x,fi,'--',color=[.7,.7,.7],label=r'$F(x) = \\ln(x^2+2)/2$')\n", 138 | "\n", 139 | "plt.legend()\n", 140 | "plt.gca().set(xlim=x[[0,-1]],xlabel='x',ylabel=r'$f(x)$ or $F(x)$')\n", 141 | "\n", 142 | "plt.tight_layout()\n", 143 | "plt.savefig('intTech_usub1.png')\n", 144 | "plt.show()" 145 | ], 146 | "metadata": { 147 | "id": "qz7JBjZSW8gg" 148 | }, 149 | "execution_count": null, 150 | "outputs": [] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "source": [], 155 | "metadata": { 156 | "id": "sjfDTawmW8dY" 157 | }, 158 | "execution_count": null, 159 | "outputs": [] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "source": [ 164 | "# Figure 16.2: u-sub example 2" 165 | ], 166 | "metadata": { 167 | "id": "SKztgrPche9n" 168 | } 169 | }, 170 | { 171 | "cell_type": "code", 172 | "source": [ 173 | "x = np.linspace(-1.5,1.5,453)\n", 174 | "fx = (3*x**4 + 5)**6 * x**3\n", 175 | "fi = (3*x**4 + 5)**7 / 84\n", 176 | "\n", 177 | "plt.figure(figsize=(8,3))\n", 178 | "plt.plot(x,fx,'k',label=r'$f(x) = (3x^4+5)^6x^3$')\n", 179 | "plt.plot(x,fi,'--',color=[.7,.7,.7],label=r'$F(x) = \\left(3x^4+5\\right)^7/84$')\n", 180 | "\n", 181 | "plt.legend()\n", 182 | "plt.gca().set(xlim=x[[0,-1]],ylim=[-1000000,1000000],xlabel='x',ylabel=r'$f(x)$ or $F(x)$')\n", 183 | "\n", 184 | "plt.tight_layout()\n", 185 | "plt.savefig('intTech_usub2.png')\n", 186 | "plt.show()" 187 | ], 188 | "metadata": { 189 | "id": "Es-1kG-w6wGF" 190 | }, 191 | "execution_count": null, 192 | "outputs": [] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "source": [], 197 | "metadata": { 198 | "id": "FexNr1Uz6wDJ" 199 | }, 200 | "execution_count": null, 201 | "outputs": [] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "source": [ 206 | "# Figure 16.3: integration by parts, example 1" 207 | ], 208 | "metadata": { 209 | "id": "qfMQwnKo6wAX" 210 | } 211 | }, 212 | { 213 | "cell_type": "code", 214 | "source": [ 215 | "x = np.linspace(-3*np.pi,3*np.pi,513)\n", 216 | "fx = x*np.cos(x)\n", 217 | "fi = x*np.sin(x) - np.cos(x)\n", 218 | "\n", 219 | "plt.figure(figsize=(8,3))\n", 220 | "plt.plot(x,fx,'k',label=r'$f(x) = x\\cos(x)$')\n", 221 | "plt.plot(x,fi,'--',color=[.7,.7,.7],label=r'$F(x) = x\\sin(x) - \\cos(x)$')\n", 222 | "\n", 223 | "plt.legend()\n", 224 | "plt.gca().set(xlim=x[[0,-1]],xlabel='x',ylabel=r'$f(x)$ or $F(x)$')\n", 225 | "\n", 226 | "plt.tight_layout()\n", 227 | "plt.savefig('intTech_ibp1.png')\n", 228 | "plt.show()" 229 | ], 230 | "metadata": { 231 | "id": "syH884XGhqqM" 232 | }, 233 | "execution_count": null, 234 | "outputs": [] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "source": [], 239 | "metadata": { 240 | "id": "126LYypF6v9X" 241 | }, 242 | "execution_count": null, 243 | "outputs": [] 244 | }, 245 | { 246 | "cell_type": "markdown", 247 | "source": [ 248 | "# Figure 16.4: Integration by parts, example 2" 249 | ], 250 | "metadata": { 251 | "id": "oiZC5Rc9i5hh" 252 | } 253 | }, 254 | { 255 | "cell_type": "code", 256 | "source": [ 257 | "x = np.linspace(-1,3,513)\n", 258 | "fx = np.exp(-np.pi*x) * np.sin(7*x)\n", 259 | "fi = (-np.pi*np.sin(7*x) * np.exp(-np.pi*x) - 7*np.cos(7*x)*np.exp(-np.pi*x)) / (np.pi**2+49)\n", 260 | "\n", 261 | "plt.figure(figsize=(8,3))\n", 262 | "plt.plot(x,fx,'k',label=r'$f(x) = e^{-\\pi x}\\sin(7x)$')\n", 263 | "plt.plot(x,fi,'--',color=[.7,.7,.7],label=r'$F(x) = \\frac{-\\pi\\sin(7x)e^{-\\pi x} - 7\\cos(7x)e^{-\\pi x}}{\\pi^2+49}$')\n", 264 | "\n", 265 | "plt.legend()\n", 266 | "plt.gca().set(xlim=x[[0,-1]],xlabel='x',ylabel=r'$f(x)$ or $F(x)$')\n", 267 | "\n", 268 | "plt.tight_layout()\n", 269 | "plt.savefig('intTech_ibp2.png')\n", 270 | "plt.show()" 271 | ], 272 | "metadata": { 273 | "id": "rAkfopYpi5hl" 274 | }, 275 | "execution_count": null, 276 | "outputs": [] 277 | }, 278 | { 279 | "cell_type": "code", 280 | "source": [], 281 | "metadata": { 282 | "id": "F66C-nYI6v3a" 283 | }, 284 | "execution_count": null, 285 | "outputs": [] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "source": [ 290 | "# Figure 16.5: Partial fractions, example 1" 291 | ], 292 | "metadata": { 293 | "id": "BQpmp2zm9jdN" 294 | } 295 | }, 296 | { 297 | "cell_type": "code", 298 | "source": [ 299 | "x = np.linspace(-2,4,5403)\n", 300 | "fx = (5*x+3) / ((2*x+2)*(x-3))\n", 301 | "fi = np.log(abs(2*x+2))/2 + 9*np.log(abs(x-3))/4\n", 302 | "\n", 303 | "# remove the artifactual lines \"connecting\" -\\infty to +\\infty\n", 304 | "fx[np.argmin(abs(x--1))] = np.nan\n", 305 | "fx[np.argmin(abs(x-3))] = np.nan\n", 306 | "\n", 307 | "plt.figure(figsize=(9,3.5))\n", 308 | "plt.plot(x,fx,'k',label=r'$f(x) = (5x+3)((2x+2)(x-3))^{-1}$')\n", 309 | "plt.plot(x,fi,'--',color=[.7,.7,.7],label=r'$F(x) = \\frac{1}{2}\\ln\\left| 2x+2 \\right| + \\frac{9}{4}\\ln\\left| x-3 \\right|$')\n", 310 | "\n", 311 | "plt.legend(loc=(.2,.01))\n", 312 | "plt.gca().set(xlim=x[[0,-1]],ylim=[-18,18],xlabel='$x$',ylabel=r'$f(x)$ or $F(x)$')\n", 313 | "\n", 314 | "plt.tight_layout()\n", 315 | "plt.savefig('intTech_pf1.png')\n", 316 | "plt.show()" 317 | ], 318 | "metadata": { 319 | "id": "FFULzKp-9jai" 320 | }, 321 | "execution_count": null, 322 | "outputs": [] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "source": [], 327 | "metadata": { 328 | "id": "8b5-IGjhUs0h" 329 | }, 330 | "execution_count": null, 331 | "outputs": [] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "source": [ 336 | "# Figure 16.5: Partial fractions, Example 2" 337 | ], 338 | "metadata": { 339 | "id": "-vRBP_BeUsxP" 340 | } 341 | }, 342 | { 343 | "cell_type": "code", 344 | "source": [ 345 | "x = np.linspace(-.5,2.5,99543)\n", 346 | "fx = (2*x**2-3*x-5) / ((x**2-1)*(x-2))\n", 347 | "fi = 3*np.log(abs(x-1)) - np.log(abs(x-2))\n", 348 | "\n", 349 | "# remove the artifactual lines \"connecting\" -\\infty to +\\infty\n", 350 | "fx[np.argmin(abs(x-1))] = np.nan\n", 351 | "fx[np.argmin(abs(x-2))] = np.nan\n", 352 | "\n", 353 | "plt.figure(figsize=(9,3.5))\n", 354 | "plt.plot(x,fx,'k',label=r'$f(x) = \\frac{2x^2 - 3x - 5}{(x^2-1)(x-2)}$')\n", 355 | "plt.plot(x,fi,'--',color=[.7,.7,.7],label=r'$F(x) = 3\\ln\\left|x-1\\right| - \\ln\\left|x-2\\right|$')\n", 356 | "\n", 357 | "plt.legend(loc=(.005,.65),fontsize=16)\n", 358 | "plt.gca().set(xlim=x[[0,-1]],ylim=[-50,50],xlabel='$x$',ylabel=r'$f(x)$ or $F(x)$')\n", 359 | "\n", 360 | "plt.tight_layout()\n", 361 | "plt.savefig('intTech_pf2.png')\n", 362 | "plt.show()" 363 | ], 364 | "metadata": { 365 | "id": "E_kJM3gPmxF2" 366 | }, 367 | "execution_count": null, 368 | "outputs": [] 369 | }, 370 | { 371 | "cell_type": "code", 372 | "source": [], 373 | "metadata": { 374 | "id": "SsGNDjXZ9Fta" 375 | }, 376 | "execution_count": null, 377 | "outputs": [] 378 | } 379 | ] 380 | } --------------------------------------------------------------------------------