我有一个总是会聚到一个固定点的函数,例如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
。
答案 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()
答案 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])
>>>