SciPy - 科学计算库(上)

一、实验说明

SciPy 库建立在 Numpy 库之上,提供了大量科学算法,主要包括这些主题:

在本实验中我们将了解其中一些包的使用方法。

(ps:因本节只讲工具的用法,对这些科学主题不展开讨论,所以根据自己所学的知识挑选食用就好了,强迫症不要纠结哈~)

1. 环境登录

无需密码自动登录,系统用户名shiyanlou

2. 环境介绍

本课程实验环境使用Spyder。首先打开terminal,然后输入以下命令:

  1. spyder -w scientific-python-lectures

关于Spyder的使用可参考文档:https://pythonhosted.org/spyder/

本实验基本在控制台下进行,可关闭其余窗口,只保留控制台。如需要调出窗口,可以通过 view->windows and toolbar 调出。比如希望在py文件中编写代码,可以 view->windows and toolbar->Editor 调出编辑器窗口。

二、实验内容

让我们先导入必要的库

  1. from numpy import *
  2. from scipy import *

特定函数

在计算科学问题时,常常会用到很多特定的函数,SciPy 提供了一个非常广泛的特定函数集合。函数列表可参考:http://docs.scipy.org/doc/scipy/reference/special.html#module-scipy.special

为了演示特定函数的一般用法我们拿贝塞尔函数举例:

  1. #
  2. # The scipy.special module includes a large number of Bessel-functions
  3. # Here we will use the functions jn and yn, which are the Bessel functions
  4. # of the first and second kind and real-valued order. We also include the
  5. # function jn_zeros and yn_zeros that gives the zeroes of the functions jn
  6. # and yn.
  7. #
  8. %matplotlib qt
  9. from scipy.special import jn, yn, jn_zeros, yn_zeros
  10. import matplotlib.pyplot as plt
  11. n = 0 # order
  12. x = 0.0
  13. # Bessel function of first kind
  14. print "J_%d(%f) = %f" % (n, x, jn(n, x))
  15. x = 1.0
  16. # Bessel function of second kind
  17. print "Y_%d(%f) = %f" % (n, x, yn(n, x))
  18. => J_0(0.000000) = 1.000000
  19. Y_0(1.000000) = 0.088257
  20. x = linspace(0, 10, 100)
  21. fig, ax = plt.subplots()
  22. for n in range(4):
  23. ax.plot(x, jn(n, x), label=r"$J_%d(x)$" % n)
  24. ax.legend();
  25. fig

  1. # zeros of Bessel functions
  2. n = 0 # order
  3. m = 4 # number of roots to compute
  4. jn_zeros(n, m)
  5. => array([ 2.40482556, 5.52007811, 8.65372791, 11.79153444])

积分

数值积分: 求积

 被称作 数值求积,Scipy提供了一些列不同类型的求积函数,像是 quaddblquad 还有 tplquad 分别对应单积分,双重积分,三重积分。

  1. from scipy.integrate import quad, dblquad, tplquad

quad 函数有许多参数选项来调整该函数的行为(详情见help(quad))。

一般用法如下:

  1. # define a simple function for the integrand
  2. def f(x):
  3. return x
  4. x_lower = 0 # the lower limit of x
  5. x_upper = 1 # the upper limit of x
  6. val, abserr = quad(f, x_lower, x_upper)
  7. print "integral value =", val, ", absolute error =", abserr
  8. => integral value = 0.5 , absolute error = 5.55111512313e-15

如果我们需要传递额外的参数,可以使用 args 关键字:

  1. def integrand(x, n):
  2. """
  3. Bessel function of first kind and order n.
  4. """
  5. return jn(n, x)
  6. x_lower = 0 # the lower limit of x
  7. x_upper = 10 # the upper limit of x
  8. val, abserr = quad(integrand, x_lower, x_upper, args=(3,))
  9. print val, abserr
  10. => 0.736675137081 9.38925687719e-13

对于简单的函数我们可以直接使用匿名函数:

  1. val, abserr = quad(lambda x: exp(-x ** 2), -Inf, Inf)
  2. print "numerical =", val, abserr
  3. analytical = sqrt(pi)
  4. print "analytical =", analytical
  5. => numerical = 1.77245385091 1.42026367809e-08
  6. analytical = 1.77245385091

如例子所示,'Inf' 与 '-Inf' 可以表示数值极限。

高阶积分用法类似:

  1. def integrand(x, y):
  2. return exp(-x**2-y**2)
  3. x_lower = 0
  4. x_upper = 10
  5. y_lower = 0
  6. y_upper = 10
  7. val, abserr = dblquad(integrand, x_lower, x_upper, lambda x : y_lower, lambda x: y_upper)
  8. print val, abserr
  9. => 0.785398163397 1.63822994214e-13

注意到我们为y积分的边界传参的方式,这样写是因为y可能是关于x的函数。

常微分方程 (ODEs)

SciPy 提供了两种方式来求解常微分方程:基于函数 odeint 的API与基于 ode 类的面相对象的API。通常 odeint 更好上手一些,而 ode 类更灵活一些。

这里我们将使用 odeint 函数,首先让我们载入它:

  1. from scipy.integrate import odeint, ode

常微分方程组的标准形式如下:

为了求解常微分方程我们需要知道方程  与初始条件 注意到高阶常微分方程常常写成引入新的变量作为中间导数的形式。 一旦我们定义了函数 f 与数组y_0 我们可以使用 odeint 函数:

  1. y_t = odeint(f, y_0, t)

我们将会在下面的例子中看到 Python 代码是如何实现 f 与 y_0 。

示例: 双摆

让我们思考一个物理学上的例子:双摆

关于双摆,参考:http://en.wikipedia.org/wiki/Double_pendulum

  1. Image(url='http://upload.wikimedia.org/wikipedia/commons/c/c9/Double-compound-pendulum-dimensioned.svg')

维基上已给出双摆的运动方程:

为了使 Python 代码更容易实现,让我们介绍新的变量名与向量表示法: 

  1. g = 9.82
  2. L = 0.5
  3. m = 0.1
  4. def dx(x, t):
  5. """
  6. The right-hand side of the pendulum ODE
  7. """
  8. x1, x2, x3, x4 = x[0], x[1], x[2], x[3]
  9. dx1 = 6.0/(m*L**2) * (2 * x3 - 3 * cos(x1-x2) * x4)/(16 - 9 * cos(x1-x2)**2)
  10. dx2 = 6.0/(m*L**2) * (8 * x4 - 3 * cos(x1-x2) * x3)/(16 - 9 * cos(x1-x2)**2)
  11. dx3 = -0.5 * m * L**2 * ( dx1 * dx2 * sin(x1-x2) + 3 * (g/L) * sin(x1))
  12. dx4 = -0.5 * m * L**2 * (-dx1 * dx2 * sin(x1-x2) + (g/L) * sin(x2))
  13. return [dx1, dx2, dx3, dx4]
  14. # choose an initial state
  15. x0 = [pi/4, pi/2, 0, 0]
  16. # time coodinate to solve the ODE for: from 0 to 10 seconds
  17. t = linspace(0, 10, 250)
  18. # solve the ODE problem
  19. x = odeint(dx, x0, t)
  20. # plot the angles as a function of time
  21. fig, axes = plt.subplots(1,2, figsize=(12,4))
  22. axes[0].plot(t, x[:, 0], 'r', label="theta1")
  23. axes[0].plot(t, x[:, 1], 'b', label="theta2")
  24. x1 = + L * sin(x[:, 0])
  25. y1 = - L * cos(x[:, 0])
  26. x2 = x1 + L * sin(x[:, 1])
  27. y2 = y1 - L * cos(x[:, 1])
  28. axes[1].plot(x1, y1, 'r', label="pendulum1")
  29. axes[1].plot(x2, y2, 'b', label="pendulum2")
  30. axes[1].set_ylim([-1, 0])
  31. axes[1].set_xlim([1, -1]);
  32. fig

我们将在第四节课看到如何做出更好的演示动画。

  1. from IPython.display import clear_output
  2. import time
  3. fig, ax = plt.subplots(figsize=(4,4))
  4. for t_idx, tt in enumerate(t[:200]):
  5. x1 = + L * sin(x[t_idx, 0])
  6. y1 = - L * cos(x[t_idx, 0])
  7. x2 = x1 + L * sin(x[t_idx, 1])
  8. y2 = y1 - L * cos(x[t_idx, 1])
  9. ax.cla()
  10. ax.plot([0, x1], [0, y1], 'r.-')
  11. ax.plot([x1, x2], [y1, y2], 'b.-')
  12. ax.set_ylim([-1.5, 0.5])
  13. ax.set_xlim([1, -1])
  14. display(fig)
  15. clear_output()
  16. time.sleep(0.1)
  17. fig

示例:阻尼谐震子

常微分方程问题在计算物理学中非常重要,所以我们接下来要看另一个例子:阻尼谐震子。wiki地址:http://en.wikipedia.org/wiki/Damping

阻尼震子的运动公式:

其中  是震子的位置,  是频率,  是阻尼系数. 为了写二阶标准行事的 ODE 我们引入变量:

:

在这个例子的实现中,我们会加上额外的参数到 RHS 方程中:

  1. def dy(y, t, zeta, w0):
  2. """
  3. The right-hand side of the damped oscillator ODE
  4. """
  5. x, p = y[0], y[1]
  6. dx = p
  7. dp = -2 * zeta * w0 * p - w0**2 * x
  8. return [dx, dp]
  9. # initial state:
  10. y0 = [1.0, 0.0]
  11. # time coodinate to solve the ODE for
  12. t = linspace(0, 10, 1000)
  13. w0 = 2*pi*1.0
  14. # solve the ODE problem for three different values of the damping ratio
  15. y1 = odeint(dy, y0, t, args=(0.0, w0)) # undamped
  16. y2 = odeint(dy, y0, t, args=(0.2, w0)) # under damped
  17. y3 = odeint(dy, y0, t, args=(1.0, w0)) # critial damping
  18. y4 = odeint(dy, y0, t, args=(5.0, w0)) # over damped
  19. fig, ax = plt.subplots()
  20. ax.plot(t, y1[:,0], 'k', label="undamped", linewidth=0.25)
  21. ax.plot(t, y2[:,0], 'r', label="under damped")
  22. ax.plot(t, y3[:,0], 'b', label=r"critical damping")
  23. ax.plot(t, y4[:,0], 'g', label="over damped")
  24. ax.legend();
  25. fig

傅立叶变换

傅立叶变换是计算物理学所用到的通用工具之一。Scipy 提供了使用 NetLib FFTPACK 库的接口,它是用FORTRAN写的。Scipy 还另外提供了很多便捷的函数。不过大致上接口都与 NetLib 的接口差不多。

让我们加载它:

  1. from scipy.fftpack import *

下面演示快速傅立叶变换,例子使用上节阻尼谐震子的例子:

  1. N = len(t)
  2. dt = t[1]-t[0]
  3. # calculate the fast fourier transform
  4. # y2 is the solution to the under-damped oscillator from the previous section
  5. F = fft(y2[:,0])
  6. # calculate the frequencies for the components in F
  7. w = fftfreq(N, dt)
  8. fig, ax = plt.subplots(figsize=(9,3))
  9. ax.plot(w, abs(F));
  10. fig

既然信号是实数,同时频谱是对称的。那么我们只需要画出正频率所对应部分的图:

  1. indices = where(w > 0) # select only indices for elements that corresponds to positive frequencies
  2. w_pos = w[indices]
  3. F_pos = F[indices]
  4. fig, ax = subplots(figsize=(9,3))
  5. ax.plot(w_pos, abs(F_pos))
  6. ax.set_xlim(0, 5);
  7. fig

正如预期的那样,我们可以看到频谱的峰值在1处。1就是我们在上节例子中所选的频率。

SciPy - 科学计算库(上)的更多相关文章

  1. scipy科学计算库

    特定函数 例贝塞尔函数: 积分 quad,dblquad,tplquad对应单重积分,双重积分,三重积分 from scipy.integrate import quad,dblquad,tplqua ...

  2. Python科学计算库

    Python科学计算库 一.numpy库和matplotlib库的学习 (1)numpy库介绍:科学计算包,支持N维数组运算.处理大型矩阵.成熟的广播函数库.矢量运算.线性代数.傅里叶变换.随机数生成 ...

  3. windows下如何快速优雅的使用python的科学计算库?

    Python是一种强大的编程语言,其提供了很多用于科学计算的模块,常见的包括numpy.scipy.pandas和matplotlib.要利用Python进行科学计算,就需要一一安装所需的模块,而这些 ...

  4. 科学计算库Numpy基础&提升(理解+重要函数讲解)

    Intro 对于同样的数值计算任务,使用numpy比直接编写python代码实现 优点: 代码更简洁: numpy直接以数组.矩阵为粒度计算并且支持大量的数学函数,而python需要用for循环从底层 ...

  5. python科学计算库的numpy基础知识,完美抽象多维数组(原创)

    #导入科学计算库 #起别名避免重名 import numpy as np #小技巧:从外往内看==从左往右看 从内往外看==从右往左看 #打印版本号 print(np.version.version) ...

  6. python科学计算库numpy和绘图库PIL的结合,素描图片(原创)

    # 导入绘图库 from PIL import Image #导入科学计算库 import numpy as np #封装一个图像处理工具类 class TestNumpy(object): def ...

  7. numpy科学计算库的基础用法,完美抽象多维数组(原创)

    #起别名避免重名 import numpy as np #小技巧:print从外往内看==shape从左往右看 if __name__ == "__main__": print(' ...

  8. ubuntu14.04 下安装 gsl 科学计算库

    GSL(GNU Scientific Library)作为三大科学计算库之一,除了涵盖基本的线性代数,微分方程,积分,随机数,组合数,方程求根,多项式求根,排序等,还有模拟退火,快速傅里叶变换,小波, ...

  9. Python科学计算库Numpy

    Python科学计算库Numpy NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. 1.简 ...

随机推荐

  1. Echarts自动刷新数据

    1.Echarts自动刷新数据 1.Echarts柱状图的正常配置 注:声明了 myChart.test这两个都有用 官方示例中myChart是声明在 function(ec)里面的 <scri ...

  2. AJAX实现简单的读取文本文档内容到网页--AJAX

    效果图: Demo.html: <!DOCTYPE html><html lang="en"><head> <meta charset=& ...

  3. java实现中文分词

    IK Analyzer是基于lucene实现的分词开源框架 下载路径:http://so.csdn.net/so/search/s.do?q=IKAnalyzer2012.jar&t=doc& ...

  4. [SCOI2008]斜堆

    题目大意 1.题目描述 斜堆(skew heap)是一种常用的数据结构. 它也是二叉树,且满足与二叉堆相同的堆性质: 每个非根结点的值都比它父亲大.因此在整棵斜堆中,根的值最小. . 但斜堆不必是平衡 ...

  5. 【Luogu3398】仓鼠找sugar(树链剖分)

    [Luogu3398]仓鼠找sugar(树链剖分) 题面 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他 ...

  6. 【BZOJ4538】【HNOI2016】网络(树链剖分,线段树,堆)

    题目链接,我是真的懒得调题目的格式... 题解 树链剖分搞一下LCA 把线段树弄出来 这只是形式上的线段树 本质上是维护一段区间的一个堆 每次把堆插入节点, 询问的时候查询线段树上的堆的最大值就行了 ...

  7. 【JSOI2008】星球大战 (并查集)

    题面 Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星 ...

  8. JDBC存在的问题

    1.数据库连接频繁的创建和关闭,缺点是浪费数据库资源,影响操作效率. 设想:使用数据库连接池 2.sql语句是硬编码,如果需求变更需要修改sql,就需要修改java代码,需要重新编译,系统不易维护. ...

  9. MyBatis关联关系

    1.一对多:一个国家对应多个城市 01.实体类 package cn.pb.bean;import java.util.Set;/** * 国家的实体类 */public class Country ...

  10. MySQL多数据源笔记5-ShardingJDBC实战

    Sharding-JDBC集分库分表.读写分离.分布式主键.柔性事务和数据治理与一身,提供一站式的解决分布式关系型数据库的解决方案. 从2.x版本开始,Sharding-JDBC正式将包名.Maven ...