无序的复杂浮点数的近似相等

时间:2014-01-04 02:21:44

标签: python numpy floating-point equality approximate

我想对无序的复杂花车的numpy数组进行鼻子测试。

例如,如果

a = [1+1j, 1-1j, 2+2j, 2-2j, 2+2j, 2-2j]

b = [2+2j, 2-2j, 1+1j, 1.000000000000001-1j, 2+2j, 2-2j]

断言应该成功,因为它们具有大致相同的值相同的次数。订单无关紧要。

对于常规浮点数,assert_array_almost_equal(np.sort(a), np.sort(b))会没问题,但是这在这里不起作用,因为它先按实部按虚数部分进行排序,因此浮动错误将它们排序为:

a: [ 1.-1.j,  1.+1.j,  2.-2.j,  2.-2.j,  2.+2.j,  2.+2.j]    
b: [ 1.+1.j,  1.-1.j,  2.-2.j,  2.-2.j,  2.+2.j,  2.+2.j]

有没有内置的方法来做到这一点?如果没有,我想我可以使用类似cplxreal的东西,但这似乎可以添加到测试文件中。

3 个答案:

答案 0 :(得分:2)

如何根据数量对数组进行排序?

def foo(a):
    return a[np.argsort(a*a.conjugate())]
np.testing.assert_array_almost_equal(foo(a),foo(b))

答案 1 :(得分:0)

我不确定是否有任何方法可以在比O(n^2)最差情况更好的情况下执行此操作,但如果您可以接受,则可以复制其中一个列表并使用修改后的{{1}消除函数以查看它们是否匹配。

equals

然后遍历您的列表,在找到匹配项时删除匹配

def equals(a, b, tolerance):
    return abs(a-b) < tolerance

似乎在最初的情况下工作,至少是粗略的:

def equivalent_lists(a, b, tolerance):
    new_b = b[:]
    for a_item in a:
        truths = [equals(a_item, b_item, tolerance) for b_item in new_b]
        if not any(truths):
            return False
        else:
            new_b.pop(truths.index(True))
    return not bool(new_b)

不是最美丽的解决方案,但至少似乎以一种非常透明的方式工作。

答案 2 :(得分:0)

另一种方法可能是考虑二维空间中的点数。 a是一组点。 b是另一套。 b中的每个点都应该接近a中的一个点。

diff = np.array(a)[None,:]-np.array(b)[:,None]
X = np.round(diff*diff.conjugate())==0  # round to desired error tollerance
X

array([[False, False,  True, False,  True, False],
       [False, False, False,  True, False,  True],
       [ True, False, False, False, False, False],
       [False,  True, False, False, False, False],
       [False, False,  True, False,  True, False],
       [False, False, False,  True, False,  True]], dtype=bool)

下一步是测试X。如果a(和b)中的值不同,则每列和每行应该有一个True。但这里有重复。

In [29]: I,J=np.where(X)

In [30]: I
Out[30]: array([0, 0, 1, 1, 2, 3, 4, 4, 5, 5])

In [31]: J
Out[31]: array([2, 4, 3, 5, 0, 1, 2, 4, 3, 5])

set(I)set(J)都是[0,1,.. 5],因此所有行和列都匹配。即使有重复项,此设置测试也可能足够。我必须探索其他点和不匹配的组合。

这个答案不完整,但可能提供一些有用的想法。