如何有效地结合类设计和矩阵数学?

K.-*_*Aye 7 python oop modeling numpy data-modeling

有一段时间我现在在精神上受到两种物理系统建模设计理念的冲突的困扰,我想知道社区为此提出了什么样的解决方案.

对于复杂(呃)模拟,我喜欢为对象创建类的抽象,以及如何使用我想要研究的真实对象来识别类的对象实例,以及对象的某些属性如何表示现实生活对象的物理特征.让我们把弹道粒子系统作为一个简单的例子:

class Particle(object):
    def __init__(self, x=0, y=0, z=0):
        self.x = x
        self.y = y
        self.z = z
    def __repr__(self):
        return "x={}\ny={}\nz={}".format(self.x, self.y, self.z)
    def apply_lateral_wind(self, dx, dy):
        self.x += dx
        self.y += dy
Run Code Online (Sandbox Code Playgroud)

如果我用一百万个值初始化它,我可能会这样做:

start_values = np.random.random((int(1e6),3))

particles = [Particle(*i) for i in start_values]
Run Code Online (Sandbox Code Playgroud)

现在,让我们假设我需要对我的所有粒子做一个特定的事情,比如添加一个横向风向量,只为这个特定的操作导致ax,y shift,因为我只有一堆(列表)我的所有粒子,我需要遍历所有粒子才能做到这一点,这需要花费这么多时间:

%timeit _ = [p.apply_lateral_wind(0.5, 1.2) for p in particles]
1 loop, best of 3: 551 ms per loop
Run Code Online (Sandbox Code Playgroud)

现在,相反的明显范式,显然更有效,是保持在numpy水平,只是直接在数组上进行数学运算,速度超过10倍:

%timeit start_values[...,:2] += np.array([0.5,1.2])
10 loops, best of 3: 20.3 ms per loop
Run Code Online (Sandbox Code Playgroud)

我现在的问题是,如果有任何设计模式有效地结合这两种方法,那么人们不会失去那么多效率?我觉得从对象方法和属性的角度来说,个人思考起来真的更容易,在我的脑海中更清晰,对我而言,实际上也是面向对象编程成功的根本原因(或者它在(物理)建模中的应用) .但缺点是显而易见的.如果这些方法之间有某种优雅的来回可能,那会不会喜欢?

Dav*_*ker 6

您可以定义一个处理多个粒子的类:

class Particles(object):
    def __init__(self, coords):
        self.coords = coords

    def __repr__(self):
        return "Particles(coords={})".format(self.coords)

    def apply_lateral_wind(self, dx, dy):
        self.coords[:, 0] += dx
        self.coords[:, 1] += dy

start_values = np.random.random((int(1e6), 3))        
particles = Particles(start_values)
Run Code Online (Sandbox Code Playgroud)

我的系统上的时间显示这实际上比你的numpy版本更快,可能是因为它没有构建一个额外的数组而且不必担心广播:

%timeit particles.apply_lateral_wind(0.5, 1.2)
100 loops, best of 3: 3.17 ms per loop
Run Code Online (Sandbox Code Playgroud)

而使用你的numpy例子给出了

%timeit start_values[..., :2] += np.array([0.5, 1.2])
10 loops, best of 3: 21.1 ms per loop
Run Code Online (Sandbox Code Playgroud)