summaryrefslogtreecommitdiff
path: root/lecture-notes/advanced-python/scipy.rst
diff options
context:
space:
mode:
Diffstat (limited to 'lecture-notes/advanced-python/scipy.rst')
-rw-r--r--lecture-notes/advanced-python/scipy.rst270
1 files changed, 270 insertions, 0 deletions
diff --git a/lecture-notes/advanced-python/scipy.rst b/lecture-notes/advanced-python/scipy.rst
new file mode 100644
index 0000000..fd0508a
--- /dev/null
+++ b/lecture-notes/advanced-python/scipy.rst
@@ -0,0 +1,270 @@
+In this section we shall look at using scipy to do various common
+scientific computation tasks. We shall be looking at solving equations
+(linear and non-linear) and solving ODEs. We shall also briefly look at
+FFTs.
+
+Solving Equations
+=================
+
+Let us begin with solving equations, specifically linear equations.
+
+Consider the set of equations,
+::
+
+ 3x + 2y -z = 1,
+ 2x-2y + 4z = -2,
+ -x+ 1/2 y-z = 0
+
+We shall use the ``solve`` function, to solve the given system of linear
+equations. ``solve`` requires the coefficients and the constants to be in
+the form of matrices, of the form ``Ax = b`` to solve the system.
+
+We begin by entering the coefficients and the constants as matrices.
+
+::
+
+ A = array([[3,2,-1],
+ [2,-2,4],
+ [-1, 0.5, -1]])
+
+A is a 3X3 matrix of the coefficients of x, y and z
+
+::
+
+ b = array([1, -2, 0])
+
+Now, we can use the solve function to solve the given system.
+
+::
+
+ x = solve(A, b)
+
+Type x, to look at the solution obtained.
+
+The equation is of the form ``Ax = b``, so we verify the solution by
+obtaining a matrix product of ``A`` and ``x``, and comparing it with ``b``.
+As we have seen earlier, we should use the dot function, for a matrix
+product and not the * operator.
+
+::
+
+ Ax = dot(A, x)
+ Ax
+
+The result ``Ax``, doesn't look exactly like ``b``, but if we carefully
+observe, we will see that it is the same as ``b``. To save ourself all this
+trouble, we can use the ``allclose`` function.
+
+``allclose`` checks if two matrices are close enough to each other (with-in
+the specified tolerance level). Here we shall use the default tolerance
+level of the function.
+
+::
+ allclose(Ax, b)
+
+The function returns ``True``, which implies that the product of ``A`` &
+``x`` is very close to the value of ``b``. This validates our solution.
+
+Let's move to finding the roots of a polynomial. We shall use the ``roots``
+function for this.
+
+The function requires an array of the coefficients of the polynomial in the
+descending order of powers. Consider the polynomial x^2-5x+6 = 0
+
+::
+
+ coeffs = [1, -5, 6]
+ roots(coeffs)
+
+As we can see, roots returns the result in an array. It even works for
+polynomials with imaginary roots.
+
+::
+
+ roots([1, 1, 1])
+
+As you can see, the roots of that equation are complex.
+
+What if, we want the solution of non linear equations?
+
+For that we shall use the ``fsolve`` function. We shall use the equation
+sin(x)+cos^2(x), as an example. ``fsolve`` is not part of the pylab package
+which we imported at the beginning, so we will have to import it. It is
+part of ``scipy`` package. Let's import it,
+
+::
+
+ from scipy.optimize import fsolve
+
+We shall look at the details of importing, later.
+
+Now, let's look at the documentation of fsolve by typing fsolve?
+
+::
+
+ fsolve?
+
+As mentioned in documentation the first argument, ``func``, is a python
+function that takes atleast one argument. The second argument, ``x0``, is
+the initial estimate of the roots of the function. Based on this initial
+guess, ``fsolve`` returns a root.
+
+Let's define a function called f, that returns the value of
+``(sin(x)+cos^2(x))`` evaluated at the input value ``x``.
+
+::
+
+ def f(x):
+ return sin(x)+cos(x)*cos(x)
+
+We can test our function, by calling it with an argument for which the
+output value is known, say x = 0. We can see that
+
+Let's check our function definition, by calling it with 0 as an argument.
+
+::
+
+ f(0)
+
+
+We can see that the output is 1 as expected, since sin(x) + cos^2(x) has a
+value of 1, when x = 0.
+
+Now, that we have our function, we can use ``fsolve`` to obtain a root of
+the expression sin(x)+cos^2(x). Let's use 0 as our initial guess.
+
+::
+
+ fsolve(f, 0)
+
+fsolve has returned a root of sin(x)+cos^2(x) that is close to 0.
+
+That brings us to the end of our discussion on solving equations. We
+discussed solution of linear equations, finding roots of polynomials and
+non-linear equations.
+
+
+ODEs
+====
+
+Let's see how to solve Ordinary Differential Equations (ODEs), using
+Python. Let's consider the classic problem of the spread of an epidemic in
+a population, as an example.
+
+This is given by the ordinary differential equation ``dy/dt = ky(L-y)``
+where L is the total population and k is an arbitrary constant.
+
+For our problem, let us use L=250000, k=0.00003. Let the boundary condition
+be y(0)=250.
+
+We shall use the ``odeint`` function to solve this ODE. As before, this
+function resides in a submodule of SciPy and doesn't come along with Pylab.
+We import it,
+::
+
+ from scipy.integrate import odeint
+
+We can represent the given ODE as a Python function. This function takes
+the dependent variable y and the independent variable t as arguments and
+returns the ODE.
+
+::
+
+ def epid(y, t):
+ k = 0.00003
+ L = 250000
+ return k*y*(L-y)
+
+Independent variable t can be assigned the values in the interval of 0 and
+12 with 60 points using linspace:
+
+ In []: t = linspace(0, 12, 60)
+
+Now obtaining the solution of the ode we defined, is as simple as calling
+the Python's ``odeint`` function which we just imported
+
+::
+
+ y = odeint(epid, 250, t)
+
+We can plot the the values of y against t to get a graphical picture our ODE.
+
+::
+
+ plot(y, t)
+
+Let's now try and solve an ODE of second order. Let's take the example of a
+simple pendulum.
+
+The equations can be written as a system of two first order ODEs
+
+ d(theta)/dt = omega
+
+and
+
+ d(omega)/dt = - g/L sin(theta)
+
+Let us define the boundary conditions as: at t = 0, theta = theta-naught =
+10 degrees and omega = 0
+
+Let us first define our system of equations as a Python function,
+``pend_int``. As in the earlier case of single ODE we shall use ``odeint``
+function to solve this system of equations.
+
+::
+
+ def pend_int(initial, t):
+ theta = initial[0]
+ omega = initial[1]
+ g = 9.81
+ L = 0.2
+ f=[omega, -(g/L)*sin(theta)]
+ return f
+
+It takes two arguments. The first argument itself containing two dependent
+variables in the system, theta and omega. The second argument is the
+independent variable t.
+
+In the function we assign the first and second values of the initial
+argument to theta and omega respectively. Acceleration due to gravity, as
+we know is 9.81 meter per second sqaure. Let the length of the the pendulum
+be 0.2 meter.
+
+We create a list, f, of two equations which corresponds to our two ODEs,
+that is ``d(theta)/dt = omega`` and ``d(omega)/dt = - g/L sin(theta)``. We
+return this list of equations f.
+
+Now we can create a set of values for our time variable t over which we need
+to integrate our system of ODEs. Let us say,
+
+::
+
+ t = linspace(0, 20, 100)
+
+We shall assign the boundary conditions to the variable initial.
+
+::
+
+ initial = [10*2*pi/360, 0]
+
+Now solving this system is just a matter of calling the odeint function with
+the correct arguments.
+
+::
+
+ pend_sol = odeint(pend_int, initial,t)
+
+ plot(pend_sol)
+
+This gives us 2 plots, omega vs t and theta vs t.
+
+That brings us to the end of our discussion on ODEs and solving them in
+Python.
+
+..
+ Local Variables:
+ mode: rst
+ indent-tabs-mode: nil
+ sentence-end-double-space: nil
+ fill-column: 75
+ End: