# Preface

The purpose of this tutorial is to introduce students in APMA 0340 (Methods of Applied Mathematics - I) to a Python library for symbolic mathematics, called SymPy (Symbolic Python). It aims to become a full-featured computer algebra system while keeping the code as simple as possible in order to be comprehensible and easily extensible. SymPy can be used to study elementary and advanced, pure and applied mathematics. This includes a huge range of mathematics, including basic algebra, calculus, elementary to very advanced number theory, cryptography, numerical computation, commutative algebra, group theory, combinatorics, graph theory, exact linear algebra and much more. It utilizes various software packages and seamlessly integrates their functionality into a common experience.

This tutorial contains many scripts. You, as the user, are free to use all codes for your needs, and have the right to distribute this tutorial and refer to this tutorial as long as this tutorial is accredited appropriately. Any comments and/or contributions for this tutorial are welcome; you can send your remarks to <Vladimir_Dobrushkin@brown.edu> The tutorial accompanies the textbook Applied Differential Equations. The Primary Course by Vladimir Dobrushkin, CRC Press, 2015; http://www.crcpress.com/product/isbn/9781439851043

### Contents

Introduction
Case Sensitivity
Basic Arithmetic Operations
Complex numbers
Arrays
Functions (explicit and implicit)
Calculus

Part I: Plotting

Plotting functions (Cartesian and polar coordinates)
(a) explicitly
(b) implicitly
vertical and horizontal lines
lables and texts
arrows
polar plot

Part II: First Order ODEs

Solving ODEs
(a) Using DSolve
(b) Verification
(c) Plotting
Direction fields
Separable equations
Equations reducible to separable equations.
Exact equations
Integrating Factors
Linear and Bernoulli equations
Riccati equation

Existence and Uniqueness of solutions
Qualitative analysis
Applications

Part III: Numerical Methods and Applications

Recurrences
Numerical solutions

a) Euler methods
b) Polynomial approximations
c) Runge-Kutta methods
d) Multistep methods
4) Numerov's method

Applications

Part IV: Second and Higher Order Differential Equations

Fundamental set of solutions. Wronskian
General solution
Reduction of order
Non-homogeneous equations.
Lagrange's method
Method of undetermined coefficients

Operator methods (not sure yet)
Applications

Part V: Fourier Series

Recurrences
Power series solutions to ODEs
Bessel functions
Airy functions
Orthogonal polynomials
a. Chebyshev
b. Legendre
c. Hermite
d. Laguerre
Euler Systems of equations

Part VI: Partial Differential Equations

Laplace transform
Heaviside function and discontinuous functions
Inverse Laplace transformation
Laplace transformation in differential equations
ODE with discontinuous functions

Mechanical and Electrical Vibrations
Other applications

«

# Introduction¶

SymPy is a Python library for symbolic mathematics. It aims become a full featured computer algebra system. SymPy is written entirely in Python and does not require any external libraries. Ondřej Čertík started the project in 2006; on Jan 4, 2011, he passed the project leadership to Aaron Meurer.

# Distribution¶

The SymPy CAS can be installed on virtually any computer with Python 2.6 or above. SymPy does require mpmath Python library to be installed first. The current recommended method of installation is through Anaconda, which includes mpmath, as well as several other useful libraries. Alternatively, executables are available for Windows, and some Linux distributions have SymPy packages available.

## Anaconda¶

Anaconda is a free Python distribution from Continuum Analytics that includes SymPy, Matplotlib, IPython, NumPy, and many more useful packages for scientific computing. This is recommended because many nice features of SymPy are only enabled when certain libraries are installed. For example, without Matplotlib, only simple text-based plotting is enabled. With the IPython notebook or qtconsole, you can get nicer $$\LaTeX$$ printing by running init_printing().

conda update sympy

## Git¶

If you wish to contribute to SymPy or like to get the latest updates as they come, install SymPy from git. To download the repository, execute the following from the command line:

git clone git://github.com/sympy/sympy.git

git pull origin master

If you want to install SymPy, but still want to use the git version, you can run from your repository:

setupegg.py develop

This will cause the installed version to always point to the version in the git directory.

## Other Methods¶

An installation executable (.exe) is available for Windows users at the downloads site. In addition, various Linux distributions have SymPy available as a package. You may also install SymPy from source or using pip.

## Run SymPy¶

After installation, it is best to verify that your freshly-installed SymPy works. To do this, start up Python and import the SymPy libraries:

\$ python
>>> from sympy import *

From here, execute some simple SymPy statements like the ones below:

>>> x = Symbol('x')
>>> limit(sin(x)/x, x, 0)
1
>>> integrate(1/x, x)
log(x)


For a starter guide on using SymPy effectively, refer to the SymPy Tutorial.

## Mpmath¶

Versions of SymPy prior to 1.0 included mpmath, but it now depends on it as an external dependency. If you installed SymPy with Anaconda, it will already include mpmath. Use:

conda install mpmath

to ensure that it is installed.

If you do not wish to use Anaconda, you can use pip install mpmath.

If you use mpmath via sympy.mpmath in your code, you will need to change this to use just mpmath. If you depend on code that does this that you cannot easily change, you can work around it by doing:

import sys
import mpmath
sys.modules['sympy.mpmath'] = mpmath


before the code that imports sympy.mpmath. It is recommended to change code that uses sympy.mpmath to use mpmath directly wherever possible.

# Case Sensitivity¶

Sage is case sensitive for both variables can be defined and for commands. The variable "a" (lower case) is different from "A" (upper case). You will know if the command that you enter is correct because the color of the command will change to black. The irartional constant Pi (=3.141926...) can be entered either as pi or, its numerical value float(pi), which gives output: 3.141592653589793.
One of the key aspects of using Sage is knowing how to enter a command. Once you have typed the command, then hit enter.

## Basic Arithmetic Operations¶

The goal of this document is not to teach you numerical analysis, but to explain how to express your ideas in Sage. By numerical computation, we essentially mean machine precision floating point computations.

Type in the first cell, hold the shift key down, and press the enter key.

sage: a=1
You may be surprised that nothing appeared to happen. In fact, the value 1 was assigned to the variable a, but this result was not echoed. Repeat on the cell below; click on the cell, then se "shift-enter" or click on "evaluate". So if you type
sage: a
Sage will provide you the numerical value: 1 Similarly,
sage: b=2; b

This time the value 2 was assigned to b and then the value of b was echoed. The semicolon is used to separate commands appearing on the same line. The same thing could be done by typing "b=2", pressing enter, typing "b".

Feel free to use whichever of these approaches is most comfortable to you.

You may type more than one command in a window by placing semicolons between them.
sage: 2+3/5; 34*18-333/5579
The underscore character refers to the previous result.
sage: factor(_) 3 * 193

## Numerical Evaluations¶

To echo a floating point number, you have to use the float() function with the
variable you assigned the expression or fraction.

sage: b=2/3sage: float(b)0.6666666666666666

Basic functions which normally are built-in are also available in Sage. Such as:

gcd()
sqrt()

sage: q = cos(2*pi/50)sage: numerical_approx(q))0.992114701314478sage: q.n()0.992114701314478sage: q.n(prec=100) # bits0.99211470131447783104979304279sage: q.n(digits=50) # decimal digitssage: n(q)0.992114701314478sage: N(q)0.992114701314478
sage: RealField(100) # Real Field with 100 bits of precisionsage: RealField(100)(q)0.99211470131447783104979304279sage: RR  # Real Field with 53 bits of precisiosage: RR(q)0.992114701314478sage: RealField(100)  # Real Field with 100 bits of precision0.99211470131447783104979304279
Sage is using simple arithmetic expressions using “+”, “−”, “∗”, and “∕” as for instance,
sage: a=2/pi*sqrt(3)sage: RealField(100)(a)1.1026577908435840990226529966
The function exp(x) is an alternate form of e^x
sage: e^2; exp(2) e^2
The solve function solves equations. To use it, first specify some variables; then the arguments to solve are an equation (or a system of equations), together with the variables for which to solve:
sage: u = var('u')sage: diff(sin(u), u)cos(u)

## Some Numbers¶

Sage understands π, e, and i or j (the square of j is −1).
sage: 3*pi; n(_); n(e); I^23*pi9.424777960769382.71828182845905-1

Sage knows some famous numbers. For instance, the golden ratio $$\phi = \dfrac{1 + \sqrt{5}}{2} \approx 1.618$$ can be invoked as follows

sage: R = RealField(n) #n is the number of decimal places you wantsage: Rsage: R(golden_ratio)

For example,

sage: R = RealField(16)sage: RReal Field with 16 bits of precisionsage: R(golden_ratio)1.618sage: R = RealField(50)sage: R(golden_ratio)
1.6180339887499

Multinomial coefficients $$\binom{n}{a,b,c,\ldots} = \dfrac{n!}{a! \,b! \,c!\, \cdots} , \quad n=a+b+c+\cdots ,$$ (and in particular, binomial coefficients $$\binom{n}{a} = \dfrac{n!}{a! \,(n-a)!}$$ ) can be evaluated using the factorial operator. For instance, multinomial coefficient $$\binom{213}{14\,26\,43\, 53\, 77}$$ is divisible by 2^(13), but divisible by 2^(14):

sage: (factorial(213)/(factorial(14)*factorial(26)*factorial(43)*factorial(53)*factorial(77)))/(2^13)93363309484444679588239580775138831058136467706688777059897484314845545215474470906701382347877254311222104806441347873998876875

## Complex Numbers¶

sage: z = complex(-3,4);
sage: z(-3+4j)sage: real(z)-3.0sage: imag(z)4.0sage: abs(z)5.0sage: arg(z)(2.214297435588181+0j)sage: conjugate(z)(-3-4j)sage: z1 = complex(-3,4);sage: z1(-3+4j)sage: z2=z1*i;sage: z2(-4-3j)sage: a = arrow((0,0),(real(z1),imag(z1)))sage: asage: plot(a)
sage: b = arrow((0,0),(real(z2),imag(z2)))sage: bsage: plot(b)
sage: plot(a+b)
sage: z = 1+isage: a = arg(z)sage: a1/4*pisage: b = abs(z)sage: bsqrt(2)sage: c = abs(z)*e^(I*(arg(z)));sage: csqrt(2)*e^(1/4*I*pi)sage: simplify(c)I + 1sage: sqrt(-8,all=true)[2*sqrt(-2), -2*sqrt(-2)]sage: solve( x^3 == -8, x )[x == I*sqrt(3)*(-1)^(1/3) - (-1)^(1/3), x == -I*sqrt(3)*(-1)^(1/3) - (-1)^(1/3), x == 2*(-1)^(1/3)]

## I. How to define functions

To define a function, just type in the formula. There are some examples.

sage: f(x)=(cos(x)-1)/x^2# f(x) is now defined and values can be passedsage: f(3)1/9*cos(3) - 1/9sage: f(pi)-2/pi^2sage: f(pi).n()-0.202642367284676

Symbolic variables must be defined as such
sage: var('a b')(a, b)sage: f(a+b)(cos(a + b) - 1)/(a + b)^2
Simple example of constructing useful 2D function plot:
sage: f(x).plot()
# plot(function, (starting x pass to function, ending x pass to function), ymin = graphical range min, ymax = graphical range maxsage: plot(f(x), (-2*pi, 2*pi),ymin = -1, ymax = 1)

## II. Discontinuous functions

To define a discontinous function, intervals must be continuos and individually discrete i.e., intervals must connect to next but must be over a defined interval; variable definition is optional.

sage: f1 = x^2sage: f2 = 4-xsage: f = piecewise([[(0,2),f1],[(2,4),f2]], x)# examplessage: f(1)1sage: f(2.5)1.50000000000000sage: f(1.5)2.25000000000000#important note!!!!!sage: f(2)3#function at the interval junction returns (f1(2)+f2(2))/2, true for all junctions

Plot of piecewise function

sage: f.plot()
A derivative of a peicewise continuous function returns derivative of pieces
sage: f.derivative()Piecewise defined function with 2 parts, [[(0, 2), x |--> 2*x], [(2, 4), x |--> -1]]

# Usefule attributes

# Critical points only defined over individual functions, does not include interval points

sage: f.critical_points()[]
sage: f.domain()(0, 4)sage: f.intervals()[(0, 2), (2, 4)]sage: f.end_points()[0, 2, 4]sage: f.which_function(1)x |--> x^2sage: f.which_function(3)x |--> -x + 4


# Calculus

Sage knows how to differentiate and integrate many functions. For example, to
differentiate $$\sin (u)$$ with respect to u, do the following:

sage: u = var('u')sage: diff(sin(u), u)cos(u)

To compute the fourth derivative of $$\sin(x^2)$$:

sage: diff(sin(x^2), x, 4)16*x^4*sin(x^2) - 48*x^2*cos(x^2) - 12*sin(x^2)
We move on to integrals, both indefinite and definite. To compute $$\int x\sin(x^2)\,{\text d}x$$ and $$\int_0^1 \frac{x}{x^2+1}\, {\text d}x:$$
sage: integral(x*sin(x^2), x)-1/2*cos(x^2)sage: integral(x/(x^2+1), x, 0, 1)1/2*log(2)

To compute the partial fraction decomposition of $$\frac{1}{x^2-1}:$$

sage: f = 1/((1+x)*(x-1))sage:  f.partial_fraction(x)1/2/(x - 1) - 1/2/(x + 1)

Numerical integration:

sage:  numerical_integral(sin(1/x)*sin(x),0,pi)(1.1839699090568376, 7.755356113813495e-07)sage: a=2/pisage: RealField(100)(a)0.63661977236758134307553505349sage: (_)*1.18396990905683760.7537386539938299


# Probablistic problems

Example. Consider the following probabalistic problem.
The distribution of IQ scores can be modeled by a normal distribution with mean 95 and standard deviation 10. Estimate the fraction of population with IQ between 100 and 110.

sage:  mu=95 sage:  s=10 sage:  var('x')sage:  p(x)=(1/s/sqrt(2*pi))*exp(-(x-mu)^2 /2/s^2)sage:  integral(p(x),x,100,110)sage:  n(_)  0.241730337457129



Example. Consider the following probabalistic problem.
The probability density function of a certain random variable $$X$$ is $$p(x) =2k\,e^{-kx}$$ The range of $$X$$ is from 0 to 4.

What is the value of $$k$$ ?

sage:  var('x')sage:  var('k') sage:  p(x)=2*k*exp(-k*x)sage:  integral(p(x),x,0,4)-2*k*(e^(-4*k)/k - 1/k)
# if you want to find antiderivative first, type: sage:  p.integral(x)
x |--> -2*e^(-k*x)sage:  solve(-2*k*(e^(-4*k)/k - 1/k) ==1,k)  [k == log(I*2^(1/4)), k == log(-2^(1/4)), k == log(-I*2^(1/4)), k == 1/4*log(2)]

Another way:

sage: A=integral(p(x),x,0,4)
sage: A.full_simplify()
2*(e^(4*k) - 1)*e^(-4*k)
sage: k = 1/4*log(2)

Derive the formula for cumulative distribution function $$P(x)$$

sage: var('t')
sage: PP(x)=integral(p(t),t,0,x)
sage: PP(x)
-2*k*(e^(-4*k)/k - 1/k)

Find the mean.

sage: integral(t*p(t),t,0,4)
-2*k*((4*k + 1)*e^(-4*k)/k^2 - 1/k^2)
sage: mu(k)=-2*k*((4*k + 1)*e^(-4*k)/k^2 - 1/k^2)
sage: mu(1/4*log(2))
sage: n(_)
1.77078016355585

What is the median ?

sage: solve(PP(t)==1/2,t)
[t == log(4/3)/k]
sage: n(log(4/3)*4/log(2))
1.66014999711537
# another way:
sage: PPP(x,k)=-2*k*(e^(-k*x)/k - 1/k)
sage: PPP(x,1/4*log(2))
-2*(e^(-1/4*x*log(2))/log(2) - 1/log(2))*log(2)
sage: find_root(-2*(e^(-1/4*x*log(2))/log(2) - 1/log(2))*log(2) ==1/2,0,4)
1.6601499971153482

sage: f = PP(x)==.5
sage: f.roots(x)
sage: n(_)
[(log(4/3)/k, 1)]

Estimate of the fraction of the population between 2 and 4.

sage: pp(k)=integral(p(t),t,2,4)
sage: pp(1/4*log(2))
sage: n(_)
0.414213562373095

### Critical points¶

You can find critical points of a piecewise defined function:

sage: x = PolynomialRing(RationalField(), 'x').gen()
sage: f1 = x^0
sage: f2 = 1-x
sage: f3 = 2*x
sage: f4 = 10*x-x^2
sage: f = Piecewise([[(0,1),f1],[(1,2),f2],[(2,3),f3],[(3,10),f4]])
sage: f.critical_points()
[5.0]


# 1. Part 1: Plotting

Part I. Plotting

Plotting functions
Implicit plot
Vertical and horizontal lines
Lables and texts
Arrows
Pollar plot
Direction fields

# 1. Part 2: First Order ODEs

Solving ODEs
Direction fields
Separable equations
Equations reducible to separable equations.
Exact equations
Integrating Factors
Linear and Bernoulli equations
Riccati equation

Existence and Uniqueness of solutions
Qualitative analysis
Applications

# 1. Part 3: Numerical Methods and Applications

Recurrences
Numerical solutions

a) Euler methods
b) Polynomial approximations
c) Runge-Kutta methods
d) Multistep methods
4) Numerov's method

Applications

# 1. Part 4: Second and Higher Order ODEs

Second order differential equations

Fundamental set of solutions. Wronskian
General solution
Reduction of order
Non-homogeneous equations.
Lagrange's method
Method of undetermined coefficients

Operator methods (not sure yet)
Applications

# 1. Part 5: Series and Recurrences

First order recurrences
Second order recurrences
Generating functions
Series solutions for the first order equations
Series solutions for the second order equations
Generalized series solutions.
Bessel equation
Airy equation
Chebyshev equations
Legendre equation
Hermite equation
Laguerre equation
Applications

# 1. Part 6: Laplace Transform

Laplace transform
Heaviside function
Laplace Transform of Discontinuous Functions
Inverse Laplace transformation
Laplace transformation in differential equations

Mechanical and Electrical Vibrations
Other applications