簡體   English   中英

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

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

假設Os是一個部分有序的集合,並且在Os中給出任意兩個對象O1和O2,如果O1大於O2,則F(O1,O2)將返回1,如果O1小於O2則返回-1,如果它們是無比的則為2,如果O1等於O2則為0。

我需要找到元素的子集Mn是最小的Os。 對於Mn中的每個A,對於Os中的每個B,F(A,B)永遠不等於1。

這並不難,但我確信它可以用更加pythonic的方式完成。

快速而骯臟的方式是:

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

特別是我對我基本上經歷所有元素N ^ 2次的事實感到不滿意。 我想知道是否會有一種動態的方式。 通過“動態”我並不僅僅意味着快速,而且一旦被發現某事物是最不可能的,也許它可以被取消。 並以pythonic ,優雅的方式完成所有這些

下面的GetMinOs2 ,“動態”刪除已知非最小的元素。 它使用一個列表Ol ,它以Os所有元素開頭。 “指針”索引l指向列表Ol的“結尾”。 當找到非最小元素時,其位置與Ol[l]的值交換,並且指針l遞減,因此Ol的有效長度縮小。 這樣做會刪除非最小元素,因此不要再次檢查它們。

GetMinOs2假設f具有比較函數的正常屬性:傳遞性,交換性等。

在下面的測試代碼中,使用夢想的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

時間結果是:

% 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。 請注意:我沒有徹底檢查GetMinOs2中的算法,但我認為一般的想法是正確的。 我在腳本的末尾進行了一些測試,顯示它至少在樣本數據set(range(1000))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM