我编写了一个使用Cox-de Boor递归算法来计算B样条基函数的Numpy实现。我想为给定的memoize
order
对象实例,但相对于xi
保留可调用的功能。
换句话说,在实例化对象之后,应“设置”递归函数,但在xi
处仍可对其进行调用。我确实需要这样做以提高速度,因为我将多次调用该函数,并且不想一遍又一遍地构造递归函数。
这是当前的实现:
import numpy as np
#Turn off divide by zero warning because we explicitly check for it
np.seterr(divide='ignore')
class Bspline():
def __init__(self, knot_vector, order):
self.knot_vector = knot_vector
self.p = order
def __basis0(self, xi):
return np.where(np.all([self.knot_vector[:-1] <= xi,
xi < self.knot_vector[1:]],axis=0), 1.0, 0.0)
def __basis(self, xi, p):
if p == 0:
return self.__basis0(xi)
else:
basis_p_minus_1 = self.__basis(xi, p - 1)
first_term_numerator = xi - self.knot_vector[:-p]
first_term_denominator = self.knot_vector[p:] - self.knot_vector[:-p]
second_term_numerator = self.knot_vector[(p + 1):] - xi
second_term_denominator = self.knot_vector[(p + 1):] - self.knot_vector[1:-p]
first_term = np.where(first_term_denominator > 1.0e-12,
first_term_numerator / first_term_denominator, 0)
second_term = np.where(second_term_denominator > 1.0e-12,
second_term_numerator / second_term_denominator, 0)
return first_term[:-1] * basis_p_minus_1[:-1] + second_term * basis_p_minus_1[1:]
def __call__(self, xi):
return self.__basis(xi, self.p)
并用作
knot_vector = np.array([0,0,0,0,0,1,2,2,3,3,3,4,4,4,4,5,5,5,5,5])
basis = Bspline(knot_vector,4)
basis(1.2)
它返回在
1.2
处求值的基函数。但是,我需要多次调用此函数,并且如现在所写,每次调用都将重建递归函数,这是不必要的,因为在实例化时将递归级别设置为4
最佳答案
在Python3中使用functools.lru_cache
或在Python2.7中使用this之类的东西来记住任何东西非常容易:
class Bspline(object):
...
# Python2.7
@memoize
# or, Python3*
@functools.lru_cache()
def op(self, args):
return self._internal_op(xi)
关于python - 记住Python方法中的单个参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30462639/