简体   繁体   English

以动态pythonic方式查找部分有序集中的最小元素

[英]Find in a dynamic pythonic way the minimum elements in a partially ordered set

Let Os be a partially ordered set, and given any two objects O1 and O2 in Os, F(O1,O2) will return 1 if O1 is bigger than O2, -1 if O1 is smaller than O2, 2 if they are incomparable, and 0 if O1 is equal to O2. 假设Os是一个部分有序的集合,并且在Os中给出任意两个对象O1和O2,如果O1大于O2,则F(O1,O2)将返回1,如果O1小于O2则返回-1,如果它们是无比的则为2,如果O1等于O2则为0。

I need to find the subset Mn of elements is Os that are the minimum. 我需要找到元素的子集Mn是最小的Os。 That is for each A in Mn, and for each B in Os, F(A,B) is never equal to 1. 对于Mn中的每个A,对于Os中的每个B,F(A,B)永远不等于1。

It is not hard to do, but I am convinced it could be done in a more pythonic way. 这并不难,但我确信它可以用更加pythonic的方式完成。

The fast and dirty way is: 快速而肮脏的方式是:

def GetMinOs(Os):
    Mn=set([])
    NotMn=set([])
    for O1 in Os:
       for O2 in Os:
           rel=f(O1,O2)
           if rel==1:       NotMn|=set([O1])
           elif rel==-1:    NotMn|=set([O2])
    Mn=Os-NotMn
    return Mn

In particular I am not happy with the fact that I am essentially going through all the elements N^2 times. 特别是我对我基本上经历所有元素N ^ 2次的事实感到不满意。 I wonder if there could be a dynamic way. 我想知道是否会有一种动态的方式。 By "dynamic" I don't mean merely fast, but also such that once something is discovered being not a possible in the minimum, maybe it could be taken off. 通过“动态”我并不仅仅意味着快速,而且一旦被发现某事物是最不可能的,也许它可以被取消。 And doing all this in a pythonic , elegant way 并以pythonic ,优雅的方式完成所有这些

GetMinOs2 below, "dynamically" removes elements which are known to be non-minimal. 下面的GetMinOs2 ,“动态”删除已知非最小的元素。 It uses a list Ol which starts with all the elements of Os . 它使用一个列表Ol ,它以Os所有元素开头。 A "pointer" index l points to the "end" of the list Ol . “指针”索引l指向列表Ol的“结尾”。 When a non-minimal element is found, its position is swapped with the value in Ol[l] and the pointer l is decremented so the effective length of Ol is shrunk. 当找到非最小元素时,其位置与Ol[l]的值交换,并且指针l递减,因此Ol的有效长度缩小。 Doing so removes non-minimal elements, so you don't check them again. 这样做会删除非最小元素,因此不要再次检查它们。

GetMinOs2 assumes f has the normal properties of a comparison function: transitivity, commutativity, etc. GetMinOs2假设f具有比较函数的正常属性:传递性,交换性等。

In the test code below, with a dreamt-up f , my timeit run shows about a 54x improvement in speed: 在下面的测试代码中,使用梦想的f ,我的timeit运行显示速度提高了54倍:

def f(O1,O2):
    if O1%4==3 or O2%4==3: return 2
    return cmp(O1,O2)

def GetMinOs(Os):
    Mn=set([])
    NotMn=set([])
    for O1 in Os:
       for O2 in Os:
           rel=f(O1,O2)
           if rel==1:       NotMn|=set([O1])
           elif rel==-1:    NotMn|=set([O2])
    Mn=Os-NotMn
    return Mn

def GetMinOs2(Os):
    Ol=list(Os)
    l=len(Ol)
    i=0
    j=1
    while i<l:
        while j<l:
            rel=f(Ol[i],Ol[j])
            if rel==1:
                l-=1
                Ol[i]=Ol[l]
                j=i+1
                break
            elif rel==-1:
                l-=1
                Ol[j]=Ol[l]
            else:
                j+=1
        else:
            i+=1
            j=i+1
    return set(Ol[:l])


Os=set(range(1000))

if __name__=='__main__':
    answer=GetMinOs(Os)
    result=GetMinOs2(Os)
    assert answer==result

The timeit results are: 时间结果是:

% python -mtimeit -s'import test' 'test.GetMinOs2(test.Os)'
1000 loops, best of 3: 22.7 msec per loop
% python -mtimeit -s'import test' 'test.GetMinOs(test.Os)'
10 loops, best of 3: 1.23 sec per loop

PS. PS。 Please be warned: I haven't thoroughly checked the algorithm in GetMinOs2, but I think the general idea is right. 请注意:我没有彻底检查GetMinOs2中的算法,但我认为一般的想法是正确的。 I've put a little test at the end of the script which shows it works at least on the sample data set(range(1000)) . 我在脚本的末尾进行了一些测试,显示它至少在样本数据set(range(1000))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Pythonic方法从字典中查找加权最小值和最大值的关键字 - Pythonic way to find key of weighted minimum and maximum from a dictionary 在列表中查找具有值的最小字典键的 Pythonic 方法? - Pythonic way to find a minimum dictionary key with value in a list? 什么是查找具有所有常见元素的列表集的pythonic方法? - What is a pythonic way to find set of lists which have all common elements? 部分有序集的可折叠子集 - Collapsible subset of partially ordered set 用Python方式合并列表中的部分冗余对象 - Pythonic way to consolidate partially redundant objects in a list 在列表中找到与其他元素不同的元素的最pythonic方法是什么? - what is most pythonic way to find a element in a list that is different with other elements? 是否有任何 pythonic 方法来查找数组中特定元组元素的平均值? - Is there any pythonic way to find average of specific tuple elements in array? 查找列表中两个元素之间关系的最pythonic方法 - Most pythonic way to find relation between two elements in a list 基于条件将循环的元素设置为常量的pythonic方法 - pythonic way to set the elements of a loop to a constant based on a condition pythonic方法来检查一个列表的任何元素是否存在于集合中 - pythonic way to check if any elements of a list is present in a set
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM