优化查找可以比较的阵列对

时间:2013-02-20 14:34:51

标签: python algorithm optimization numpy

定义:数组A(a1,a2,...,an) >=B(b1,b2,...bn) a_i>=b_i i 1 n. [1,2,3] >= [1,2,0] [1,2,0] not comparable with [1,0,2] [1,0,2] >= [1,0,0] B A >= B A O(n^2) import numpy as np import time import random def filter_minimal(lst): n = len(lst) to_delete = set() for i in xrange(n-1): if i in to_delete: continue for j in xrange(i+1,n): if j in to_delete: continue if all(lst[i]>=lst[j]): to_delete.add(i) break elif all(lst[i]<=lst[j]): to_delete.add(j) return [lst[i] for i in xrange(len(lst)) if i not in to_delete] def test(number_of_arrays,size): x = map(np.array,[[random.randrange(0,10) for _ in xrange(size)] for i in xrange(number_of_arrays)]) return filter_minimal(x) a = time.time() result = test(400,10) print time.time()-a print len(result) numpy.all all 1}}

例如:

{{1}}

我有一个列表,其中包含大量此类数组(大约10000,但可以更大)。数组的元素是正整数。我需要删除此列表中比至少其中一个数组大的所有数组。换句话说:如果存在{{1}} {{1}} {{1}},则删除{{1}}。

这是我当前的{{1}}方法,这种方法非常慢。我只是将每个数组与所有其他数组进行比较,如果它更大则将其删除。有没有办法加快速度。

{{1}}

P.S。我注意到使用{{1}}而不是内置python {{1}}会大大减慢程序的速度。可能是什么原因?

2 个答案:

答案 0 :(得分:1)

可能不是你要求的,但这应该让你开始。

import numpy as np
import time
import random

def compare(x,y):
    #Reshape x to a higher dimensional array
    compare_array=x.reshape(-1,1,x.shape[-1])
    #You can now compare every x with every y element wise simultaneously
    mask=(y>=compare_array)
    #Create a mask that first ensures that all elements of y are greater then x and
    #then ensure that this is the case at least once.
    mask=np.any(np.all(mask,axis=-1),axis=-1)
    #Places this mask on x
    return x[mask]

def test(number_of_arrays,size,maxval):
    #Create arrays of size (number_of_arrays,size) with maximum value maxval.
    x = np.random.randint(maxval, size=(number_of_arrays,size))
    y=  np.random.randint(maxval, size=(number_of_arrays,size))
    return compare(x,y)

print test(50,10,20)

答案 1 :(得分:0)

首先,我们需要仔细检查目标。我们删除任何&gt;的数组是真的吗?任何其他数组,甚至是删除的数组?例如,如果A> B和C> A和B = C,那么我们是否只需删除A或A和C两者?如果我们只需要删除INCOMPATIBLE数组,那么这是一个更难的问题。这是一个非常困难的问题,因为这组数组的不同分区可能兼容,因此您遇到了找到最大有效分区的问题。

假设容易出问题,更好的定义问题的方法是你想要保留所有至少有一个元素的数组&lt;所有其他数组中的相应元素。 (在硬问题中,它是其他KEPT数组中的相应元素。我们不会考虑这个。)

第1阶段

要解决此问题,您要做的是将数组排列在列中,然后对每行进行排序,同时保持数组的键以及每个数组行到位置的映射(POSITION列表)。例如,您最终可能会在第1阶段得到如下结果:

第1行:B C D A E
第2行:C A E B D
第3行:E D B C A

意味着对于第一个元素(第1行),数组B的值为&gt; = C,C> = D等等。

现在,对此矩阵的最后一列进行排序和迭代(示例中为{E D A})。对于每个项目,检查元素是否小于其行中的上一个元素。例如,在第1行中,您将检查E&lt; A.如果这是真的,您立即返回并保留结果。例如,如果E_row1&lt; A_row1然后您可以保留数组E.只有当行中的值相等时,您才需要进行第2阶段测试(见下文)。

在显示的示例中,您将保留E,D,A(只要他们通过上述测试)。

第二阶段

这将离开B和C.为每个排序POSITION列表。例如,这将告诉您具有B的最小位置的行是第2行。现在直接比较B和它下面的每个数组在mininum行,这里是第2行。这里只有一个这样的数组,D。 B和D之间的直接比较。这表明B

现在我们对C做同样的事情。在C的情况下,我们只需要进行一次直接比较,而A.C支配A,所以我们不保留C.

请注意,除了测试最后一列中没有出现的项目之外,我们还需要测试第1阶段中具有相同性的项目。例如,假设第1行中D = A = E.在这种情况下,我们必须对最后一列中涉及数组的每个相等进行直接比较。因此,在这种情况下,我们将E与A和E直接比较为D.这表明E支配D,因此不保留E.

最终结果是我们保留A,B和D. C和E被丢弃。

此算法的整体性能在阶段1中为n2 * log n +阶段2中的{n下限,n * log n - 上限}。因此,最大运行时间为n2 * log n + nlogn且最小运行时间时间是n2logn + n。请注意,算法的运行时间为n-cubed n3。由于你比较每个矩阵(n * n),每个比较是n个元素比较= n * n * n。

一般来说,这比蛮力方法要快得多。大部分时间都用于对原始矩阵进行排序,这或多或少是不可避免的任务。请注意,您可以通过使用优先级队列而不是排序来改进我的算法,但生成的算法会复杂得多。