2017-10-05 45 views
1

雖然我試圖在大量使用numpy的情況下解決此問題(因此優雅的基於numpy的解決方案將受到特別的歡迎),但基本問題無關緊要與numpy(甚至Python)等。驗證點是否位於指定節點的網格

任務是爲一個算法創建一個自動測試,該算法應該產生分佈在一個網格上的點,該網格的音調被指定爲該算法的輸入。該絕對職位的點並不重要,但他們的相對職位做。例如,以下

collection_of_points = algorithm(data, pitch=[1.3, 1.5, 2]) 

collection_of_points應該只包含點,其x座標由1.3倍數不同,其y座標爲1.5的倍數不同且其z座標以2

倍數不同測試應該驗證這個條件是否滿足。

一兩件事,我已經盡力了,這似乎並不太難看,但不工作是

points = algo(data, pitch=requested_pitch) 
for p1, p2 in itertools.combinations(points, 2): 
    distance_between_points = np.array(p2) - np.array(p1) 
    assert np.allclose(distance_between_points % requested_pitch, 0) 

[除了對那些不熟悉Python或numpy的:

  • itertools.combinations(points, 2)是迭代所有點對的簡單方法
  • np.array的算術運算是按元素執行的,所以np.array([5,6,7]) % np.array([2,3,4])通過計算爲個
  • np.allclose檢查在兩個輸入端的所有對應的元件是否陣列大約相等,並且numpy的自動假裝被傳遞在作爲第二個參數的0,確實是一個全零陣列正確大小的

]

爲了明白爲什麼上面顯示的想法失敗,考慮的其通過8.9999999在相關尺寸分離3和兩個點的期望間距。 8.999999 % 3大約是2.999999,這遠遠不符合要求的0

在這一切,我不禁感到,我失去了一些明顯的東西,或者我正在重新發明一些車輪。

你能提出一個寫這種支票的優雅方式嗎?如果你想使其更具可讀性,你應該官能聲明

np.all(np.logical_or(np.isclose(x % y, 0), np.isclose((x % y) - y, 0))) 

+1

當然,8.9999999999%3 = 2.999999? – Paul

+0

@保羅是的,當然。固定。 – jacg

回答

1

你的說法更改爲。喜歡的東西:

def is_multiple(x, y, rtol=1e-05, atol=1e-08): 
    """ 
    Test if x is a multiple of y. 
    """ 
    remainder = x % y 
    is_zero = np.isclose(remainder, 0., rtol, atol) 
    is_y = np.isclose(remainder, y, rtol, atol) 
    return np.logical_or(is_zero, is_y) 

然後:

assert np.all(is_multiple(distance_between_points, requested_pitch)) 
+1

我認爲你的意思是'isclose'而不是'allclose',最後加上'.all()'標記。另外,你可以用',y'代替' - y,0'。我已經在循環中做了類似的事情。你的時間稍短;我的(我認爲)更容易被隨機路人所理解。但整件事仍然感覺太沉重和神祕。 – jacg

+0

是的,你是對的。修正答案。 – Paul