\n", "In this lecture, we start by recalling how new **functions** can be defined in Python. Then we show how to **plot** functions in SageMath and discuss concepts from calculus (or analysis) like **limits**, **derivatives** and **integrals**. We finish by discussing **power series**, which are a generalization of the Taylor series from analysis." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python warmup: functions\n", "We have already seen many functions implemented in SageMath (such as ``log``, ``span`` or ``solve``). But it is also possible (and often very useful) to write functions ourselves." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def parabola(x):\n", " x_squared = x^2\n", " return x_squared" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This creates a new function ``parabola``, which we can immediately call on some value:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "parabola(4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The general code pattern for defining a function ``foo`` with $n$ inputs (or **arguments**) looks as follows:\n", "```\n", "def foo(arg1, arg2, ..., argn):\n", " some_code()\n", " more_code()\n", " return result\n", "```\n", "As was the case with ``if`` and ``for``, we have a block of indented code (the **body** of the function) in which we can do what we want (e.g. create new variables, call other functions, use ``if`` and ``for``). Most functions ``foo`` should in the end give back some result, which we do using the ``return`` keyword.\n", "\n", "Let's see a function with more than one argument:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def bigger_than(x,y):\n", " if x > y:\n", " return True\n", " else:\n", " return False" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bigger_than(5,6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "Define the following functions and test them in some examples.\n", "* the function ``sign`` returning the [sign](https://en.wikipedia.org/wiki/Sign_function) of a real number\n", "* the function ``conjugate``, taking $n \\times n$-matrices $A,S$ and returning $S A S^{-1}$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also have functions with **optional arguments**. These are arguments which *can* be given, but don't *have to* be given when calling the function. However, in exchange you need to provide a *default value* for each of them. Let's generalize the function ``parabola`` from above to implement the function $x \\mapsto a \\cdot x^2 + c$:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def parabola(x, a=1, c=0):\n", " x_squared = x^2\n", " return a*x_squared + c" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "parabola(2, 5, 1) # returns 5 * 2^2 +1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "parabola(3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "parabola(3,-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we see above, if a function gets a number of arguments which is smaller than the total number of fixed and optional arguments, it simply fills the optional arguments in the order that was specified in the function definition. \n", "\n", "If we want to explicitly specify the argument ``c`` above, but leave ``a`` to take the default value, we can do so by explicitly specifying the name of the argument that we want:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "parabola(3, c=-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The general pattern looks like this:\n", "```\n", "def foo(arg1, arg2, ..., argn, opt_arg1 = default1, ..., opt_argm = defaultm):\n", " some_code()\n", " more_code()\n", " return result\n", "```\n", "Here, it is **important** that the non-optional arguments come before the optional ones." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "Implement a function ``fibonacci`` computing the Fibonacci-Numbers $F_n$ defined by\n", "$$\n", "F_0 = 0, \\quad F_1 = 1, \\quad F_{n} = F_{n-1} + F_{n-2} \\text{ for }n \\geq 2.\n", "$$\n", "Add the option to specify $F_0, F_1$ by hand." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculus\n", "SageMath can do many computations related to the infinitesimal behaviour of functions, such as limits, derivatives and integrals. In each case, the function should be represented by a symbolic expression, as seen in the last lecture. Since it is useful for illustrating the later computations (and in general), we'll start however with some information how to plot functions (a.k.a. producing pretty pictures)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plotting\n", "The most basic task here is to plot a function in one variable on an interval. For instance, we can give the function as a symbolic expression in ``x``:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot(sin(x),x,-5,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, we can program a function as seen in the first part of the lecture:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def g(x):\n", " if x <= 0:\n", " return cos(x)\n", " else:\n", " return floor(x) # floor is the round-down function, sending 3.14 to 3, etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot(g,x,-5,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Most of the time it's more useful to use the symbolic expressions, though. \n", "\n", "A curiosity: if you type ``plot(g(x),x,-5,5)`` it does not do what you want. If you understand what goes wrong there, you already have a pretty good grasp on symbolic expressions!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "* Plot your favorite function on an interval of your choice." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Plot your second-favorite function on the interval $(-3,3)$, but in green.

\n", "*Hint:* Since unfortunately I forgot to say how to change the color, you will have to find it out yourself!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can guess, there are lots more optional arguments for the ``plot`` function, which you can again find in the documentation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot(sign, x, -3, 3, ymin=-2, ymax=2, axes=False, fill='axis')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The function ``plot`` actually returns a Graphics-object and you can *literally* add multiple such objects to plot multiple functions:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = plot(sin(x),x,-6,6)\n", "g = plot(sin(2*x),x,-6,6,color='red')\n", "f+g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Three more variants of plots:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "var('y')\n", "implicit_plot(x^2+y^2-1, (-3,3), (-2,2)) # plots the solution set of x^2 + y^2 -1 = 0 inside [-3,3] x [-2,2]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "var('t')\n", "parametric_plot((3*cos(t), 2*sin(t)), (t,0,2*pi)) # plots the curve t -> (3 cos(t), 2 sin(t)) for t in [0, 2 pi]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "plot3d(sin(x) + e^cos(y),(x,-3,3),(y,-3,3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "Consider the following system of equations:\n", "$$\n", "7 \\, x^{2} - 11 \\, x y + 14 \\, y^{2} + 4 \\, x - 15 \\, y - 51 = 0\\,,\\\\\n", "-49 \\, x^{2} + 59 \\, x y - 94 \\, x - 43 \\, y + 159 = 0\n", "$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Plot the two solution sets to the two equations in separate colors (in the same coordinate system).\n", "* Solve this system of equations (using the methods from last lecture) and verify graphically that you found all solutions in the first part of the exercise.\n", "\n", "To spare you the typing, here are the left-hand sides of the equations:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "var('x,y')\n", "F1 = 7*x^2 - 11*x*y + 14*y^2 + 4*x - 15*y - 51\n", "F2 = -49*x^2 + 59*x*y - 94*x - 43*y + 159" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Limits\n", "For a function given by a symbolic expression, we can compute its limit at a given point as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "limit((x^2 - 1)/(x - 1), x=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "Compute the limit\n", "$$\n", "\\lim_{x \\to 0} \\frac{\\sinh(x)}{x}\n", "$$\n", "and check with a plot that this is plausible." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also deal with divergent functions, one-sided limits and limits as $x$ goes to $\\pm \\infty$: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "limit(1/x, x=0, dir='+')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "limit((x+1)/x, x=Infinity)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Derivatives and integrals\n", "Of course SageMath can differentiate (symbolic) functions, and for many functions it can also integrate them. Here are three ways to obtain the derivative:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = x * exp(x)\n", "print(diff(f,x))\n", "print(derivative(f,x))\n", "print(f.derivative(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To get the derivative at a specific point, we can evaluate the symbolic expression there, as seen in the last lecture:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = f.derivative()\n", "g(x=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "Write a function ``plot_tangent`` which takes as input\n", "* a symbolic expression ``f`` of a function in the variable ``x``\n", "* a point ``x0``\n", "\n", "and outputs a plot of the function ``f`` on the interval $[x_0-3, x_0+3]$ together with its tangent line at ``x0``.

\n", "*Bonus:* If you are done early, feel free to include optional parameters to change the interval of plotting, the colour of the tangent line etc." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course we can also compute partial derivatives for functions depending on multiple parameters:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "var('a,b')\n", "derivative(a^2*b^3,a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is an example of how to do indefinite integration:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = integral(sin(x)*cos(x),x); g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The syntax for a definite integral like\n", "$$\n", "\\int_0^{2 \\pi} g(x) dx\n", "$$\n", "is as follows:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "integral(g, (x,0,2*pi))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To apply the things we learned, here is a task from an actual [Analysis II-exam](https://www2.math.ethz.ch/education/bachelor/lectures/fs2016/other/analysis2_mavt_matl/pruefungen/pruefung_winter_16.pdf) at ETH Zurich (see Exercise 3).\n", "#### Exercise\n", "Let $a, b > 0$. Let the function $f : \\mathbb{R}^2 \\to \\mathbb{R}$ be defined by\n", "$$\n", "f(x,y) := (a x^2 + b y^2) \\cdot e^{-(x^2 + y^2)}.\n", "$$\n", "Find the global maxima and minima of $f$ for\n", "* $a>b$.\n", "* $a=b=1$.\n", "\n", "*Hint:* The function $f$ slopes down to zero towards infinity.\n", "\n", "In case you have forgotten how these extreme value problems work, you can of course [look it up on wikipedia](https://en.wikipedia.org/wiki/Maxima_and_minima#Functions_of_more_than_one_variable)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can also do some calculus involving vectors. Here is the parametrization $r : [0, 2 \\pi] \\to \\mathbb{R}^3$ of a spiral:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "var('t')\n", "r=vector([cos(t), sin(t), t]); r" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "parametric_plot3d(r, (t, 0, 2*pi))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "v = derivative(r,t); v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The arc length of the path $r$ given by\n", "$$\n", "\\ell(r) = \\int_{0}^{2 \\pi} | \\dot r(t)| dt.\n", "$$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "integrate(v.norm(),t,0, 2*pi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are many more interesting functions, and we don't have time to go through all of them. In particular, see [this](https://doc.sagemath.org/html/en/thematic_tutorials/vector_calculus.html) tutorial on vector calculus in SageMath. There, you learn how to define a vector field, compute its divergence and curl, etc." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Power series\n", "Power series are a very useful part of mathematics. Typically one first encounters them in the form of the Taylor series\n", "$$\n", "\\sum_{k=0}^\\infty \\frac{f^{(k)}(0)}{k!} t^k\n", "$$\n", "of a smooth function $f$ around the point $t_0=0$. However, it is also possible to do calculations with more general series\n", "$$\n", "\\sum_{k=0}^\\infty a_k t^k.\n", "$$\n", "The easiest way to compute with them in SageMath is to create a ``PowerSeriesRing``, with some formal variable ``t``. Here you have to specify a **base ring**, which is the ring containing the possible coefficients $a_k$ above." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "R.

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Assignments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise (short)\n", "Solve Exercise 2 b) from the [Analysis II-exam](https://www2.math.ethz.ch/education/bachelor/lectures/fs2016/other/analysis2_mavt_matl/pruefungen/pruefung_winter_16.pdf) above.

\n", "*Remark:* I couldn't get SageMath to solve Exercise 2 a) since it involves some third roots, which are kind of tricky." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exercise\n", "A partition of a natural number $n \\geq 0$ is one representation of $n$ as an ordered sum of positive integers. For instance, the number $n=5$ has $7$ different partitions:\n", "$$\n", "5,\\quad 4+1,\\quad 3+2,\\quad 3+1+1,\\quad 2+2+1,\\quad 2+1+1+1,\\quad 1+1+1+1+1\n", "$$\n", "If $p(n)$ denotes the number of partitions of $n$, then the infinite product\n", "$$\n", "\\prod_{j=1}^\\infty \\frac{1}{1-t^j} = \\frac{1}{1-t} \\cdot \\frac{1}{1-t^2} \\cdot \\frac{1}{1-t^3} \\cdots\n", "$$\n", "is a generating function of $p(n)$. \n", "* (theoretical) Use the formula for the geometric series to show that the finite product\n", "$$\n", "\\prod_{j=1}^m \\frac{1}{1-t^j} = \\frac{1}{1-t} \\cdots \\frac{1}{1-t^m}\n", "$$\n", "is a generating series for the number $p(n,m)$ of partitions of $n$ with maximal part at most $m$.

\n", "In particular, since for $m \\geq n$ we have $p(n,m)=p(n)$, this explains why the infinite product above is a generating series for $p(n)$.\n", "* Use this knowledge to write a function ``partition_number(n, m=None)`` to compute the numbers $p(n,m)$.

\n", "*Remark:* In the above case, it is useful to set the optional parameter ``m`` to the Python value ``None`` as default. Then, at the beginning of the function, you should check whether ``m`` is ``None`` and if yes give it a reasonable value.\n", "* Check your function in a few cases (e.g. $n=5$ using the enumeration of partitions of $5$ above)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Solution** (uncomment to see)

\n", "" ] } ], "metadata": { "kernelspec": { "display_name": "SageMath 9.1", "language": "sage", "name": "sagemath" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }