计算算术运算

时间:2015-11-02 17:46:00

标签: python numpy recursion scipy

有没有办法评估函数/表达式中的数值运算(+, - ,/,*)的数量?

在示例中,我们来看一个简单的线性代数问题(Ax = b):

A_data = np.array([[1, -4, 1],
                  [1, 6, -1],
                  [2, -1, 2]], dtype=float)

b_data = np.array([[7],
                  [13],
                  [5]], dtype=float)

接下来,让我们应用高斯消除程序:

def gauss_elim(A, b):
    Ab = np.column_stack((A, b))
    for k, pivot_row in enumerate(Ab[:-1]):
        for row in Ab[k+1:]:
            if pivot_row[k] != 0:
                row[k:] = row[k:] - pivot_row[k:] * row[k]/pivot_row[k]
    return Ab

结果是:

array([[  1. ,  -4. ,   1. ,   7. ],
       [  0. ,  10. ,  -2. ,   6. ],
       [  0. ,   0. ,   1.4, -13.2]])

我如何计算操作?

注意:我知道可以事先用数学方法评估操作次数(即Gaussian elimination是O(n ^ 3))。

2 个答案:

答案 0 :(得分:1)

我假设您正在尝试降低此处的复杂性以提高性能。在这篇文章中列出了 kill Gauss-elimination的内循环broadcasting的方法,给我们一个部分向量化的解决方案,就像这样 -

# Concatenate A and b into a single 2D array
Ab = np.concatenate((A,b),axis=1)

for k, pivot_row in enumerate(Ab[:-1]):

    # Vectorized broadcasting magic happens here : 
    # Calculate offsets corresponding to "pivot_row[k:] * row[k]/pivot_row[k]" 
    offsets = (Ab[k+1:,k][:,None] * pivot_row[k:])/pivot_row[k]

    # Update each row
    Ab[k+1:,k:] -= offsets

运行时测试并验证输出 -

In [137]: def partvect_gauss_elim(A,b):
     ...:     Ab = np.concatenate((A,b),axis=1)
     ...:     for k, pivot_row in enumerate(Ab[:-1]):
     ...:         offsets = (Ab[k+1:,k][:,None] * pivot_row[k:])/pivot_row[k]
     ...:         Ab[k+1:,k:] -= offsets
     ...:     return Ab
     ...: 
     ...: def original_gauss_elim(A,b):
     ...:     Ab = np.concatenate((A,b),axis=1)
     ...:     for k, pivot_row in enumerate(Ab[:-1]):
     ...:         for row in Ab[k+1:]:
     ...:             if pivot_row[k] != 0:
     ...:                 row[k:] = row[k:] - pivot_row[k:] * row[k]/pivot_row[k]
     ...:     return Ab
     ...: 

In [138]: A = np.random.randint(0,9,(50,50))
     ...: b = np.random.randint(0,9,(50,1))
     ...: 

In [139]: np.allclose(original_gauss_elim(A,b),partvect_gauss_elim(A,b))
Out[139]: True

In [140]: %timeit original_gauss_elim(A,b)
100 loops, best of 3: 12.1 ms per loop

In [141]: %timeit partvect_gauss_elim(A,b)
100 loops, best of 3: 2.56 ms per loop

答案 1 :(得分:1)

如果您可以花一点时间,它应该有一种方法:创建一类数字并覆盖基本的算术方法:__add____mul____sub__,{ {1}}通过在其中嵌入一个计数器系统(例如与一些全局变量相关)。然后,您应该能够通过使用__div__参数(在创建数组时)强制Numpy使用您的类型,以确保Numpy不会将您的数字转换为任何其他类型。我有时会为简单的任务而做;我从来没有和Numpy一起做过,但它应该可行。希望它可以提供帮助。