矢量化迭代定点搜索

时间:2017-08-18 14:20:50

标签: python numpy scipy vectorization

我有一个总是会聚到一个固定点的函数,例如compile 'com.google.firebase:firebase-database:11.0.0' 。我有一个函数,可以通过重复调用函数来找到这个修复点:

f(x)= (x-a)/2+a

哪个工作正常,现在我想为矢量化版本执行此操作;

def find_fix_point(f,x):
    while f(x)>0.1:
        x = f(x)
    return x

然而,这是非常低效的,如果大多数实例只需要大约10次迭代而且需要1000次。什么是删除已找到的x的快速方法?

代码可以使用def find_fix_point(f,x): while (f(x)>0.1).any(): x = f(x) return x numpy

4 个答案:

答案 0 :(得分:1)

解决此问题的一种方法是使用递归:

def find_fix_point_recursive(f, x):
    ind = x > 0.1
    if ind.any():
        x[ind] = find_fix_point_recursive(f, f(x[ind]))
    return x

通过此实现,我们只需要在需要更新的点上调用f

请注意,通过使用递归,我们可以避免必须一直进行检查x > 0.1,每次调用都会处理越来越小的数组。

%timeit x = np.zeros(10000); x[0] = 10000; find_fix_point(f, x)
1000 loops, best of 3: 1.04 ms per loop

%timeit x = np.zeros(10000); x[0] = 10000; find_fix_point_recursive(f, x)
10000 loops, best of 3: 141 µs per loop

答案 1 :(得分:1)

首先,我更改标准以适应定点定义:我们在|x-f(x)|<=epsilon时停止。

您可以混合boolean indexing and integer indexing以保留每次活动积分。这是一种方法:

def find_fix_point(f,x,epsilon):
    ind=np.mgrid[:len(x)] # initial indices.
    while ind.size>0:
        xind=x[ind]  # integer indexing
        yind=f(xind)
        x[ind]=yind
        ind=ind[abs(yind-xind)>epsilon]  # boolean indexing

有很多修复点的例子:

from matplotlib.pyplot import plot,show
x0=np.linspace(0,1,1000) 
x = x0.copy() 
def f(x): return x*np.sin(1/x)     
find_fix_point(f,x,1e-5)        
plot(x0,x,'.');show()    

enter image description here

答案 2 :(得分:0)

一般方法是使用布尔索引来仅计算尚未达到平衡的那些。

我调整了Jonas Adler给出的算法,以避免最大递归深度:

def find_fix_point_vector(f,x):
    x = x.copy()
    x_fix = np.empty(x.shape)
    unfixed = np.full(x.shape, True, dtype = bool)
    while unfixed.any():
        x_new = f(x) #iteration
        x_fix[unfixed] = x_new # copy the values
        cond = np.abs(x_new-x)>1
        unfixed[unfixed] = cond #find out which ones are fixed
        x = x_new[cond] # update the x values that still need to be computed
    return x_fix

编辑: 在这里,我回顾了提出的3个解决方我将根据他们的提议者find_fix_Jonas, find_fix_Jurg, find_fix_BM来称呼不同的功能。我根据BM更改了所有函数中的fixpoint条件(最后请参阅Jonas的更新功能)。

速度:

%timeit find_fix_BM(f, np.linspace(0,100000,10000),1)
100 loops, best of 3: 2.31 ms per loop

%timeit find_fix_Jonas(f, np.linspace(0,100000,10000))
1000 loops, best of 3: 1.52 ms per loop

%timeit find_fix_Jurg(f, np.linspace(0,100000,10000))
1000 loops, best of 3: 1.28 ms per loop

根据可读性,我认为Jonas的版本是最容易理解的版本,因此在速度无关紧要时应该选择。

然而,当达到修复点的迭代次数很大(> 1000)时,Jonas的版本可能会引发Runtimeerror。另外两种解决方案没有这个缺点。

B.M.的角色然而,比我提出的版本更容易理解。

Jonas的版本使用:

def find_fix_Jonas(f, x):
    fx = f(x)
    ind = np.abs(fx-x)>1
    if ind.any():
        fx[ind] = find_fix_Jonas(f, fx[ind])
    return fx

答案 3 :(得分:-2)

  

...删除已经找到的`x?

使用您的条件使用布尔索引创建一个新数组。

>>> a = np.array([3,1,6,3,9])
>>> a != 3
array([False,  True,  True, False,  True], dtype=bool)
>>> b = a[a != 3]
>>> b
array([1, 6, 9])
>>>