2

以下摘录是我正在尝试为其构建 numpy 查找函数的 500 行表。我的问题是这些值是非线性的。

用户输入densityvolumecontent。所以函数将是:

def capacity_lookup(density, volume, content:

例如,典型的用户条目是capacity_lookup (47, 775, 41.3). 该函数应在值 45 和 50 以及密度 700 和 800 以及内容 40 和 45 之间进行插值。

表格摘录是:

Volume  Density        Content 
                <30 35  40  45  50>=
45.0    <=100   0.1 1.8 0.9 2.0 0.3
45.0    200     1.5 1.6 1.4 2.4 3.0
45.0    400     0.4 2.1 0.9 1.8 2.5
45.0    600     1.3 0.8 0.2 1.7 1.9
45.0    800     0.6 0.9 0.8 0.4 0.2
45.0    1000    0.3 0.8 0.5 0.3 1.0
45.0    1200    0.6 0.0 0.6 0.2 0.2
45.0    1400    0.6 0.4 0.3 0.7 0.1
45.0    >=1600  0.3 0.0 0.6 0.1 0.3
50.0    <=100   0.1 0.0 0.5 0.9 0.2
50.0    200     1.3 0.4 0.8 0.2 2.7
50.0    400     0.4 0.1 0.7 1.3 1.7
50.0    600     0.8 0.7 0.1 1.2 1.6
50.0    800     0.5 0.3 0.4 0.2 0.0
50.0    1000    0.2 0.4 0.4 0.2 0.3
50.0    1200    0.4 0.0 0.0 0.2 0.0
50.0    1400    0.0 0.3 0.1 0.5 0.1
50.0    >=1600  0.1 0.0 0.0 0.0 0.2
55.0    <=100   0.0 0.0 0.4 0.6 0.1
55.0    200     0.8 0.3 0.7 0.1 1.2
55.0    400     0.3 0.1 0.3 1.1 0.7
55.0    600     0.4 0.3 0.0 0.6 0.1
55.0    800     0.0 0.0 0.0 0.2 0.0
55.0    1000    0.2 0.1 0.2 0.1 0.3
55.0    1200    0.1 0.0 0.0 0.1 0.0
55.0    1400    0.0 0.2 0.0 0.2 0.1
55.0    >=1600  0.0 0.0 0.0 0.0 0.1

问题

如何存储 500 行表,以便对其非线性数据进行插值并根据用户输入获得正确的值?

澄清

  1. 如果用户输入以下向量 (775, 47, 41.3),程序应返回以下四个向量之间的插值:45.0, 600, 0.2, 1.745.0, 800, 0.8, 0.450.0, 600, 0.1, 1.250.0, 800, 0.4, 0.2
  2. 假设数据将从数据库中提取为您设计的 numpy 数组
4

2 回答 2

2

我发现的第一个困难是<=>=,我可以处理复制 的末端Density,并将它们的值更改为非常接近的虚拟值991601,这不会影响插值。

Volume  Density        Content 
                <30 35  40  45  50>=
45.0     99   0.1 1.8 0.9 2.0 0.3
45.0    100   0.1 1.8 0.9 2.0 0.3
45.0    200     1.5 1.6 1.4 2.4 3.0
45.0    400     0.4 2.1 0.9 1.8 2.5
45.0    600     1.3 0.8 0.2 1.7 1.9
45.0    800     0.6 0.9 0.8 0.4 0.2
45.0    1000    0.3 0.8 0.5 0.3 1.0
45.0    1200    0.6 0.0 0.6 0.2 0.2
45.0    1400    0.6 0.4 0.3 0.7 0.1
45.0    1600  0.3 0.0 0.6 0.1 0.3
45.0    1601  0.3 0.0 0.6 0.1 0.3
50.0     99   0.1 0.0 0.5 0.9 0.2
50.0    100   0.1 0.0 0.5 0.9 0.2
50.0    200     1.3 0.4 0.8 0.2 2.7
50.0    400     0.4 0.1 0.7 1.3 1.7
50.0    600     0.8 0.7 0.1 1.2 1.6
50.0    800     0.5 0.3 0.4 0.2 0.0
50.0    1000    0.2 0.4 0.4 0.2 0.3
50.0    1200    0.4 0.0 0.0 0.2 0.0
50.0    1400    0.0 0.3 0.1 0.5 0.1
50.0    1600  0.1 0.0 0.0 0.0 0.2
50.0    1601  0.1 0.0 0.0 0.0 0.2
55.0     99   0.0 0.0 0.4 0.6 0.1
55.0    100   0.0 0.0 0.4 0.6 0.1
55.0    200     0.8 0.3 0.7 0.1 1.2
55.0    400     0.3 0.1 0.3 1.1 0.7
55.0    600     0.4 0.3 0.0 0.6 0.1
55.0    800     0.0 0.0 0.0 0.2 0.0
55.0    1000    0.2 0.1 0.2 0.1 0.3
55.0    1200    0.1 0.0 0.0 0.1 0.0
55.0    1400    0.0 0.2 0.0 0.2 0.1
55.0    1600  0.0 0.0 0.0 0.0 0.1
55.0    1601  0.0 0.0 0.0 0.0 0.1

然后,正如@Jaime 已经指出的那样,您必须找到 8 个顶点才能进行三线性插值。

以下算法将为您提供要点:

import numpy as np
def get_8_points(filename, vi, di, ci):
    a = np.loadtxt(filename, skiprows=2)
    vol = a[:,0].repeat(a.shape[1]-2).reshape(-1,)
    den = a[:,1].repeat(a.shape[1]-2).reshape(-1,)
    #FIXME maybe you have to change the next line
    con = np.tile(np.array([30., 35., 40., 45., 50.]),a.shape[0]).reshape(-1,)
    #
    val = a[:,2:].reshape(a.shape[0]*5).reshape(-1,)

    u = np.unique(vol)
    diff = np.absolute(u-vi)
    vols = u[diff.argsort()][:2]

    u = np.unique(den)
    diff = np.absolute(u-di)
    dens = u[diff.argsort()][:2]

    u = np.unique(con)
    diff = np.absolute(u-ci)
    cons = u[diff.argsort()][:2]

    check = np.in1d(vol,vols) & np.in1d(den,dens) & np.in1d(con,cons)

    points = np.vstack((vol[check], den[check], con[check], val[check]))

    return points.T

使用您的示例:

vi, di, ci = 47, 775, 41.3
points = get_8_points(filename, vi, di, ci)
#array([[  4.50e+01,   6.00e+02,   4.00e+01,   2.00e-01],
#       [  4.50e+01,   6.00e+02,   4.50e+01,   1.70e+00],
#       [  4.50e+01,   8.00e+02,   4.00e+01,   8.00e-01],
#       [  4.50e+01,   8.00e+02,   4.50e+01,   4.00e-01],
#       [  5.00e+01,   6.00e+02,   4.00e+01,   1.00e-01],
#       [  5.00e+01,   6.00e+02,   4.50e+01,   1.20e+00],
#       [  5.00e+01,   8.00e+02,   4.00e+01,   4.00e-01],
#       [  5.00e+01,   8.00e+02,   4.50e+01,   2.00e-01]])

现在您可以执行三线性插值...

于 2013-08-19T16:11:00.967 回答
2

为了补充 Saullo 的答案,这里是如何进行三线性插值。您基本上将立方体插入一个正方形,然后将正方形插入一个段,然后将段插入一个点。插值的顺序不会改变最终结果。Saullo 的编号方案已经是正确的了:基础顶点是数字 0,增加最后一维的顶点数加 1,倒数第二个加 2,第一维加 4。所以从他的顶点返回函数,您可以执行以下操作:

coords = np.array([47, 775, 41.3])
ndim = len(coords)
# You would get this with a call to:
# vertices = get_8_points(filename, *coords)
vertices = np.array([[  4.50e+01,   6.00e+02,   4.00e+01,   2.00e-01],
                     [  4.50e+01,   6.00e+02,   4.50e+01,   1.70e+00],
                     [  4.50e+01,   8.00e+02,   4.00e+01,   8.00e-01],
                     [  4.50e+01,   8.00e+02,   4.50e+01,   4.00e-01],
                     [  5.00e+01,   6.00e+02,   4.00e+01,   1.00e-01],
                     [  5.00e+01,   6.00e+02,   4.50e+01,   1.20e+00],
                     [  5.00e+01,   8.00e+02,   4.00e+01,   4.00e-01],
                     [  5.00e+01,   8.00e+02,   4.50e+01,   2.00e-01]])

for dim in xrange(ndim):
   vtx_delta = 2**(ndim - dim - 1)
    for vtx in xrange(vtx_delta):
        vertices[vtx, -1] += ((vertices[vtx + vtx_delta, -1] -
                               vertices[vtx, -1]) *
                              (coords[dim] -
                               vertices[vtx, dim]) /
                              (vertices[vtx + vtx_delta, dim] -
                               vertices[vtx, dim]))

print vertices[0, -1] # prints 0.55075

该函数将顶点数组重用于导致最终值的中间插值,存储在 中,如果以后需要它,则必须vertices[0, -1]复制该数组。vertices

于 2013-08-19T17:31:30.397 回答