2015-11-02 104 views
2

有没有一种方法来评估函数/表达式中的数字操作数(+, - ,/,*)?计数算术运算

在示例,让我们简单的线性代数问题(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) 

接着,让应用Gauss消去过程:

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))。

+1

“数字”是什么意思? – Divakar

+0

*“是否有一种方法可以用数字方式评估数字操作的数量(+, - ,/,*)。”* - 其中有四个? – jonrsharpe

+0

你可以使用['unittest.mock.Mock.call_count'](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_count)和使用'对象'数组 –

回答

1

我假设您正试图降低性能的复杂性。上市在这个岗位是的方法杀死Gauss-eliminationbroadcasting内环给我们一个部分量化的解决方案,像这样 -

# 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

如果您可能需要一点时间,应该有这样一种方法:创建一类数字并覆盖基本算术方法:__add__,__mul__,__sub__,__div__通过在其中嵌入一个计数器系统(涉及到一些全局变量例如)。然后,您应该能够使用dtype=object参数(在创建数组时)强制Numpy使用您的类型,以确保Numpy不会将您的数字转换为任何其他类型。我有时为了更简单的任务做了这件事。我从来没有用过Numpy,但它应该可行。希望它可以帮助。