簡體   English   中英

從 arrays 列表中查找唯一代表(元素)列表

[英]Find a list of unique representatives (elements) from a list of arrays

我有一個由n arrays 組成的列表(或數組)。 每個數組攜帶從0n-1的任意整數子集(數組中不重復數字)。 n=3的示例是:

l = [np.array([0, 1]), np.array([0]), np.array([1, 2])]

我想從每個數組中選擇一個數字作為其代表,這樣沒有兩個 arrays 具有相同的代表,並按照與 arrays 相同的順序列出它們。 換句話說,為 arrays 選擇的數字必須是唯一的,並且整個代表集將是數字0n-1的排列。 對於上面的列表,它將是唯一的:

representatives = [1, 0, 2]

可以保證我們的名單中存在這樣的代表名單,但我們如何找到他們。 如果有多個可能的代表列表,則可以隨機選擇其中任何一個。

這是你要找的嗎?

def pick_one(a, index, buffer, visited):
    if index == len(a):
        return True
    for item in a[index]:
        if item not in visited:
            buffer.append(item)
            visited.add(item)
            if pick_one(a, index + 1, buffer, visited):
                return True
            buffer.pop()
            visited.remove(item)
    return False


a = [[0, 1], [0], [1, 2]]
buffer = []
pick_one(a, 0, buffer, set())
print(buffer)

Output:

[1, 0, 2]

您要求的是二分圖的最大匹配,其左右集分別由您的 arrays 及其唯一元素索引。

networkx模塊知道如何找到這樣的最大匹配:

import numpy as np
import networkx as nx
import operator as op

def make_example(n,density=0.1):
    rng = np.random.default_rng()
    M = np.unique(np.concatenate([rng.integers(0,n,(int(n*n*density),2)),
                                  np.stack([np.arange(n),rng.permutation(n)],
                                           axis=1)],axis=0),axis=0)
    return np.split(M[:,1],(M[:-1,0] != M[1:,0]).nonzero()[0])

def find_matching(M):
    G = nx.Graph()
    m = len(M)
    n = 1+max(map(max,M))
    G.add_nodes_from(range(n,m+n), biparite=0)
    G.add_nodes_from(range(n),biparite=1)
    G.add_edges_from((i,j) for i,r in enumerate(M,n) for j in r)
    return op.itemgetter(*range(n,m+n))(nx.bipartite.maximum_matching(G))

例子:

>>> M = make_example(10,0.4)
>>> M
[array([0, 4, 8]), array([9, 3, 5]), array([7, 1, 3, 4, 5, 7, 8]), array([9, 0, 4, 5]), array([9, 0, 1, 3, 5]), array([6, 0, 1, 2, 8]), array([9, 3, 5, 7]), array([8, 1, 2, 5]), array([6]), array([7, 0, 1, 4, 6])]
>>> find_matching(M)
(0, 9, 5, 4, 1, 2, 3, 8, 6, 7)

這可以在幾秒鍾內完成數千個元素:

>>> M = make_example(10000,0.01)
>>> t0,sol,t1 = [time.perf_counter(),find_matching(M),time.perf_counter()]
>>> print(t1-t0)
3.822795882006176

暫無
暫無

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

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