python - 由于舍入错误,无法使用 interp1d
问题描述
我正在尝试使用密度函数拉伸网格点。例如,给定以下点分布(均匀分布):
import numpy as np
from scipy.integrate import quad
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
from scipy.special import erf
# the x interval limits
a = 0.0
b = 3.0
# The density function, normalize it
_density_func = lambda x: 5*x
density_func = lambda x: _density_func(x) / quad(_density_func, a, b)[0]*(b-a)
# The xarr and yarr
Npts = 50
xarr = np.linspace(a, b, Npts)
yarr = np.zeros_like(xarr)
# Calculate the primitive function F = integral of density_func, from a, to t normalized by the int(density_func, a, b)
# F = np.vectorize(lambda t: quad(density_func, a, t)[0] / quad(density_func, a, b)[0])
F = np.vectorize(lambda t: quad(density_func, a, t)[0])
# if debug is true, print some info
debug = True
if debug:
print('The range of xarr is: [', a, b, ']')
print('The range of F(xarr) is: [', F(xarr).min(), F(xarr).max(), ']')
# Calculate the new x distribution of points using the inverse function of F.
# Use the trick of interpolation to calculate the inverse function,i.e: interp1d(y, x)(x)
xnew = interp1d(F(xarr), xarr)(xarr)
# plot the result
plt.scatter(xnew, yarr, facecolors='none', edgecolors='black')
plt.show()
当我运行此脚本时,我收到以下错误:
The range of xarr is: [ 0.0 3.0 ]
The range of F(xarr) is: [ 0.0 2.9999999999999996 ]
Traceback (most recent call last):
File "meshDensity.py", line 38, in <module>
xnew = interp1d(F(xarr), xarr)(xarr)
File "C:\Users\navaro\Anaconda3\lib\site-packages\scipy\interpolate\polyint.py", line 79, in __call__
y = self._evaluate(x)
File "C:\Users\navaro\Anaconda3\lib\site-packages\scipy\interpolate\interpolate.py", line 664, in _evaluate
below_bounds, above_bounds = self._check_bounds(x_new)
File "C:\Users\navaro\Anaconda3\lib\site-packages\scipy\interpolate\interpolate.py", line 696, in _check_bounds
raise ValueError("A value in x_new is above the interpolation "
ValueError: A value in x_new is above the interpolation range.
如您所见,问题在于 is 的正确限制F(xarr)
而2.9999999999999996
不是确切值3.0
。
您能否建议任何解决此舍入错误问题的方法?我很感激任何帮助。
编辑:临时解决方案是使用mpmath.quad
函数,mpmath.mp.dps = 20
但这会使脚本相对较慢。
解决方案
我使用任意精度算术模块解决了我的问题,mpmath
.
import numpy as np
import mpmath as mp
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
mp.mp.dps = 18
# the x interval limits
a = 0.0
b = 3.0
# The density function, normalize it
_density_func = lambda x: 5*x
density_func = lambda x: _density_func(x) / mp.quad(_density_func, [a, b])*(b-a)
# The xarr and yarr
Npts = 50
xarr = np.linspace(a, b, Npts)
yarr = np.zeros_like(xarr)
# Calculate the primitive function F = integral of density_func, from a, to t.
F = np.vectorize(lambda t: mp.quad(density_func, [a, t]))
# if debug is true, print some info
debug = True
if debug:
print('The range of xarr is: [', a, b, ']')
print('The range of F(xarr) is: [', F(xarr).min(), F(xarr).max(), ']')
# Calculate the new x distribution of points using the inverse function of F.
# Use the trick of interpolation to calculate the inverse function,i.e: interp1d(y, x)(x)
xnew = interp1d(F(xarr), xarr)(xarr)
# plot the result
plt.scatter(xnew, yarr, facecolors='none', edgecolors='black')
plt.show()
运行脚本后,我得到:
The range of xarr is: [ 0.0 3.0 ]
The range of F(xarr) is: [ 0.0 3.0 ]
推荐阅读
- javascript - JS:在 addEventListener 中添加命名函数
- r - 将大型数据框从 R 推送/导出到 Vertica 数据库
- android - 连接到 Firebase 时出现 Build.gradle 文件错误
- mathematical-optimization - 优化 min{x/(x+1)}
- django - 如何从 Django REST 框架(JWT 令牌)获取真实密码。对于用户列表视图
- flutter - NoSuchMethodError : 在 null 上调用了 setter 'text='。接收方:null 尝试调用:text="2020-12-10 00:00:00.000"
- xslt - XSLT 中不同 Xpath 之间的分组
- java - 如何将巨大的 id 列表(例如)传递给 apache spark 自定义数据源
- javascript - 使用 webpack 4.41 和 workbox 6 生成 ServiceWorker
- reactjs - React-Intl 同时使用多个语言环境