SciPy - 科学计算库(上)
SciPy - 科学计算库(上)
一、实验说明
SciPy 库建立在 Numpy 库之上,提供了大量科学算法,主要包括这些主题:
- 特殊函数 (scipy.special)
- 积分 (scipy.integrate)
- 最优化 (scipy.optimize)
- 插值 (scipy.interpolate)
- 傅立叶变换 (scipy.fftpack)
- 信号处理 (scipy.signal)
- 线性代数 (scipy.linalg)
- 稀疏特征值 (scipy.sparse)
- 统计 (scipy.stats)
- 多维图像处理 (scipy.ndimage)
- 文件 IO (scipy.io)
在本实验中我们将了解其中一些包的使用方法。
(ps:因本节只讲工具的用法,对这些科学主题不展开讨论,所以根据自己所学的知识挑选食用就好了,强迫症不要纠结哈~)
1. 环境登录
无需密码自动登录,系统用户名shiyanlou
2. 环境介绍
本课程实验环境使用Spyder。首先打开terminal,然后输入以下命令:
spyder -w scientific-python-lectures
关于Spyder的使用可参考文档:https://pythonhosted.org/spyder/
本实验基本在控制台下进行,可关闭其余窗口,只保留控制台。如需要调出窗口,可以通过 view->windows and toolbar 调出。比如希望在py文件中编写代码,可以 view->windows and toolbar->Editor 调出编辑器窗口。
二、实验内容
让我们先导入必要的库
from numpy import *
from scipy import *
特定函数
在计算科学问题时,常常会用到很多特定的函数,SciPy 提供了一个非常广泛的特定函数集合。函数列表可参考:http://docs.scipy.org/doc/scipy/reference/special.html#module-scipy.special
为了演示特定函数的一般用法我们拿贝塞尔函数举例:
#
# The scipy.special module includes a large number of Bessel-functions
# Here we will use the functions jn and yn, which are the Bessel functions
# of the first and second kind and real-valued order. We also include the
# function jn_zeros and yn_zeros that gives the zeroes of the functions jn
# and yn.
#
%matplotlib qt
from scipy.special import jn, yn, jn_zeros, yn_zeros
import matplotlib.pyplot as plt
n = 0 # order
x = 0.0
# Bessel function of first kind
print "J_%d(%f) = %f" % (n, x, jn(n, x))
x = 1.0
# Bessel function of second kind
print "Y_%d(%f) = %f" % (n, x, yn(n, x))
=> J_0(0.000000) = 1.000000
Y_0(1.000000) = 0.088257
x = linspace(0, 10, 100)
fig, ax = plt.subplots()
for n in range(4):
ax.plot(x, jn(n, x), label=r"$J_%d(x)$" % n)
ax.legend();
fig
# zeros of Bessel functions
n = 0 # order
m = 4 # number of roots to compute
jn_zeros(n, m)
=> array([ 2.40482556, 5.52007811, 8.65372791, 11.79153444])
积分
数值积分: 求积
被称作 数值求积,Scipy提供了一些列不同类型的求积函数,像是
quad
, dblquad
还有 tplquad
分别对应单积分,双重积分,三重积分。
from scipy.integrate import quad, dblquad, tplquad
quad
函数有许多参数选项来调整该函数的行为(详情见help(quad)
)。
一般用法如下:
# define a simple function for the integrand
def f(x):
return x
x_lower = 0 # the lower limit of x
x_upper = 1 # the upper limit of x
val, abserr = quad(f, x_lower, x_upper)
print "integral value =", val, ", absolute error =", abserr
=> integral value = 0.5 , absolute error = 5.55111512313e-15
如果我们需要传递额外的参数,可以使用 args
关键字:
def integrand(x, n):
"""
Bessel function of first kind and order n.
"""
return jn(n, x)
x_lower = 0 # the lower limit of x
x_upper = 10 # the upper limit of x
val, abserr = quad(integrand, x_lower, x_upper, args=(3,))
print val, abserr
=> 0.736675137081 9.38925687719e-13
对于简单的函数我们可以直接使用匿名函数:
val, abserr = quad(lambda x: exp(-x ** 2), -Inf, Inf)
print "numerical =", val, abserr
analytical = sqrt(pi)
print "analytical =", analytical
=> numerical = 1.77245385091 1.42026367809e-08
analytical = 1.77245385091
如例子所示,'Inf' 与 '-Inf' 可以表示数值极限。
高阶积分用法类似:
def integrand(x, y):
return exp(-x**2-y**2)
x_lower = 0
x_upper = 10
y_lower = 0
y_upper = 10
val, abserr = dblquad(integrand, x_lower, x_upper, lambda x : y_lower, lambda x: y_upper)
print val, abserr
=> 0.785398163397 1.63822994214e-13
注意到我们为y积分的边界传参的方式,这样写是因为y可能是关于x的函数。
常微分方程 (ODEs)
SciPy 提供了两种方式来求解常微分方程:基于函数 odeint
的API与基于 ode
类的面相对象的API。通常 odeint
更好上手一些,而 ode
类更灵活一些。
这里我们将使用 odeint
函数,首先让我们载入它:
from scipy.integrate import odeint, ode
常微分方程组的标准形式如下:
当
为了求解常微分方程我们需要知道方程 与初始条件
注意到高阶常微分方程常常写成引入新的变量作为中间导数的形式。 一旦我们定义了函数
f
与数组y_0
我们可以使用 odeint
函数:
y_t = odeint(f, y_0, t)
我们将会在下面的例子中看到 Python 代码是如何实现 f
与 y_0
。
示例: 双摆
让我们思考一个物理学上的例子:双摆
关于双摆,参考:http://en.wikipedia.org/wiki/Double_pendulum
Image(url='http://upload.wikimedia.org/wikipedia/commons/c/c9/Double-compound-pendulum-dimensioned.svg')
维基上已给出双摆的运动方程:
为了使 Python 代码更容易实现,让我们介绍新的变量名与向量表示法:
g = 9.82
L = 0.5
m = 0.1
def dx(x, t):
"""
The right-hand side of the pendulum ODE
"""
x1, x2, x3, x4 = x[0], x[1], x[2], x[3]
dx1 = 6.0/(m*L**2) * (2 * x3 - 3 * cos(x1-x2) * x4)/(16 - 9 * cos(x1-x2)**2)
dx2 = 6.0/(m*L**2) * (8 * x4 - 3 * cos(x1-x2) * x3)/(16 - 9 * cos(x1-x2)**2)
dx3 = -0.5 * m * L**2 * ( dx1 * dx2 * sin(x1-x2) + 3 * (g/L) * sin(x1))
dx4 = -0.5 * m * L**2 * (-dx1 * dx2 * sin(x1-x2) + (g/L) * sin(x2))
return [dx1, dx2, dx3, dx4]
# choose an initial state
x0 = [pi/4, pi/2, 0, 0]
# time coodinate to solve the ODE for: from 0 to 10 seconds
t = linspace(0, 10, 250)
# solve the ODE problem
x = odeint(dx, x0, t)
# plot the angles as a function of time
fig, axes = plt.subplots(1,2, figsize=(12,4))
axes[0].plot(t, x[:, 0], 'r', label="theta1")
axes[0].plot(t, x[:, 1], 'b', label="theta2")
x1 = + L * sin(x[:, 0])
y1 = - L * cos(x[:, 0])
x2 = x1 + L * sin(x[:, 1])
y2 = y1 - L * cos(x[:, 1])
axes[1].plot(x1, y1, 'r', label="pendulum1")
axes[1].plot(x2, y2, 'b', label="pendulum2")
axes[1].set_ylim([-1, 0])
axes[1].set_xlim([1, -1]);
fig
我们将在第四节课看到如何做出更好的演示动画。
from IPython.display import clear_output
import time
fig, ax = plt.subplots(figsize=(4,4))
for t_idx, tt in enumerate(t[:200]):
x1 = + L * sin(x[t_idx, 0])
y1 = - L * cos(x[t_idx, 0])
x2 = x1 + L * sin(x[t_idx, 1])
y2 = y1 - L * cos(x[t_idx, 1])
ax.cla()
ax.plot([0, x1], [0, y1], 'r.-')
ax.plot([x1, x2], [y1, y2], 'b.-')
ax.set_ylim([-1.5, 0.5])
ax.set_xlim([1, -1])
display(fig)
clear_output()
time.sleep(0.1)
fig
示例:阻尼谐震子
常微分方程问题在计算物理学中非常重要,所以我们接下来要看另一个例子:阻尼谐震子。wiki地址:http://en.wikipedia.org/wiki/Damping
阻尼震子的运动公式:
其中 是震子的位置,
是频率,
是阻尼系数. 为了写二阶标准行事的 ODE 我们引入变量:
:
在这个例子的实现中,我们会加上额外的参数到 RHS 方程中:
def dy(y, t, zeta, w0):
"""
The right-hand side of the damped oscillator ODE
"""
x, p = y[0], y[1]
dx = p
dp = -2 * zeta * w0 * p - w0**2 * x
return [dx, dp]
# initial state:
y0 = [1.0, 0.0]
# time coodinate to solve the ODE for
t = linspace(0, 10, 1000)
w0 = 2*pi*1.0
# solve the ODE problem for three different values of the damping ratio
y1 = odeint(dy, y0, t, args=(0.0, w0)) # undamped
y2 = odeint(dy, y0, t, args=(0.2, w0)) # under damped
y3 = odeint(dy, y0, t, args=(1.0, w0)) # critial damping
y4 = odeint(dy, y0, t, args=(5.0, w0)) # over damped
fig, ax = plt.subplots()
ax.plot(t, y1[:,0], 'k', label="undamped", linewidth=0.25)
ax.plot(t, y2[:,0], 'r', label="under damped")
ax.plot(t, y3[:,0], 'b', label=r"critical damping")
ax.plot(t, y4[:,0], 'g', label="over damped")
ax.legend();
fig
傅立叶变换
傅立叶变换是计算物理学所用到的通用工具之一。Scipy 提供了使用 NetLib FFTPACK 库的接口,它是用FORTRAN写的。Scipy 还另外提供了很多便捷的函数。不过大致上接口都与 NetLib 的接口差不多。
让我们加载它:
from scipy.fftpack import *
下面演示快速傅立叶变换,例子使用上节阻尼谐震子的例子:
N = len(t)
dt = t[1]-t[0]
# calculate the fast fourier transform
# y2 is the solution to the under-damped oscillator from the previous section
F = fft(y2[:,0])
# calculate the frequencies for the components in F
w = fftfreq(N, dt)
fig, ax = plt.subplots(figsize=(9,3))
ax.plot(w, abs(F));
fig
既然信号是实数,同时频谱是对称的。那么我们只需要画出正频率所对应部分的图:
indices = where(w > 0) # select only indices for elements that corresponds to positive frequencies
w_pos = w[indices]
F_pos = F[indices]
fig, ax = subplots(figsize=(9,3))
ax.plot(w_pos, abs(F_pos))
ax.set_xlim(0, 5);
fig
正如预期的那样,我们可以看到频谱的峰值在1处。1就是我们在上节例子中所选的频率。
SciPy - 科学计算库(上)的更多相关文章
- scipy科学计算库
特定函数 例贝塞尔函数: 积分 quad,dblquad,tplquad对应单重积分,双重积分,三重积分 from scipy.integrate import quad,dblquad,tplqua ...
- Python科学计算库
Python科学计算库 一.numpy库和matplotlib库的学习 (1)numpy库介绍:科学计算包,支持N维数组运算.处理大型矩阵.成熟的广播函数库.矢量运算.线性代数.傅里叶变换.随机数生成 ...
- windows下如何快速优雅的使用python的科学计算库?
Python是一种强大的编程语言,其提供了很多用于科学计算的模块,常见的包括numpy.scipy.pandas和matplotlib.要利用Python进行科学计算,就需要一一安装所需的模块,而这些 ...
- 科学计算库Numpy基础&提升(理解+重要函数讲解)
Intro 对于同样的数值计算任务,使用numpy比直接编写python代码实现 优点: 代码更简洁: numpy直接以数组.矩阵为粒度计算并且支持大量的数学函数,而python需要用for循环从底层 ...
- python科学计算库的numpy基础知识,完美抽象多维数组(原创)
#导入科学计算库 #起别名避免重名 import numpy as np #小技巧:从外往内看==从左往右看 从内往外看==从右往左看 #打印版本号 print(np.version.version) ...
- python科学计算库numpy和绘图库PIL的结合,素描图片(原创)
# 导入绘图库 from PIL import Image #导入科学计算库 import numpy as np #封装一个图像处理工具类 class TestNumpy(object): def ...
- numpy科学计算库的基础用法,完美抽象多维数组(原创)
#起别名避免重名 import numpy as np #小技巧:print从外往内看==shape从左往右看 if __name__ == "__main__": print(' ...
- ubuntu14.04 下安装 gsl 科学计算库
GSL(GNU Scientific Library)作为三大科学计算库之一,除了涵盖基本的线性代数,微分方程,积分,随机数,组合数,方程求根,多项式求根,排序等,还有模拟退火,快速傅里叶变换,小波, ...
- Python科学计算库Numpy
Python科学计算库Numpy NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. 1.简 ...
随机推荐
- Spring 之BeanFactory(转)
BeanFactory是Spring的“心脏”.它就是Spring IoC容器的真面目. Spring使用BeanFactory来实例化.配置和管理Bean.但是,在大多数情况我们并不直接使用Bean ...
- Vue安装依赖npm install时报错问题解决方法
1.vue的安装依赖于node.js,要确保你的计算机上已安装过node.js. 可进入cmd编辑器,输入命令 node -v进行查看.出现版本信息即成功!没有则从浏览器上面下载安装即可,没有安 ...
- 洛谷P2617 Dynamic Ranking(主席树,树套树,树状数组)
洛谷题目传送门 YCB巨佬对此题有详细的讲解.%YCB%请点这里 思路分析 不能套用静态主席树的方法了.因为的\(N\)个线段树相互纠缠,一旦改了一个点,整个主席树统统都要改一遍...... 话说我真 ...
- Luogu4149:[IOI2011]Race
题目 bzoj权限题... Luogu Sol 点分治辣,边权非负,k>=1,开个\(1e6\)的桶就好辣 # include <bits/stdc++.h> # define RG ...
- MySQL的sum()函数
如下图,这是一个关于用户参加活动,每个活动会给这位用户评分的一个表: 用户1参加了A活动,评分100: 用户2参加了B活动,评分98,又参加了D活动,评分10: 用户3参加了C活动,评分99 需求:把 ...
- C语言引用另一个源文件中定义的数组
C语言中是可以引用另外一个源文件的全局数组的,但是不能引用局部数组. 引用方式举例如下: 设a.c文件有有数据定义 int array1[10]; 现有b.c文件中想访问a.c中的array1数组 ...
- windows下远程访问Redis,windows Redis绑定ip无效,Redis设置密码无效,Windows Redis 配置不生效,Windows Redis requirepass不生效,windows下远程访问redis的配置
转载:http://fanshuyao.iteye.com/blog/2384074 一.Redis下载地址: https://github.com/MicrosoftArchive/redis/re ...
- Java反射总结
一. 获取Class对象的3种方法: 1. Class.forName("");例如:Class.forName("java.lang.String"); 2. ...
- python全栈开发-Day4 列表
python全栈开发-Day4 列表 一.首先按照以下几个点展开列表的学习 #一:基本使用 1 用途 2 定义方式 3 常用操作+内置的方法 #二:该类型总结 1 存一个值or存多个值 只能存一个值 ...
- vue v-for输出表格结构
v-for输出表格结构 数据库结构如下: 原理: 两个数组 a, b, 数组a的值,是数组b的键(索引), 变量拼接(红色区域): <table> <tr> <th v ...