2015-11-02 143 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,但它應該可行。希望它可以幫助。