Có ai biết nếu có một con trăn xây dựng để tính toán đóng cửa transitive của tuple?transthon đóng cửa python tuples
Tôi có tuples dạng (1,2),(2,3),(3,4)
và tôi đang cố gắng để có được (1,2),(2,3),(3,4),(1,3)(2,4)
Cảm ơn.
Có ai biết nếu có một con trăn xây dựng để tính toán đóng cửa transitive của tuple?transthon đóng cửa python tuples
Tôi có tuples dạng (1,2),(2,3),(3,4)
và tôi đang cố gắng để có được (1,2),(2,3),(3,4),(1,3)(2,4)
Cảm ơn.
Chỉ cần một nỗ lực nhanh chóng:
def transitive_closure(elements):
elements = set([(x,y) if x < y else (y,x) for x,y in elements])
relations = {}
for x,y in elements:
if x not in relations:
relations[x] = []
relations[x].append(y)
closure = set()
def build_closure(n):
def f(k):
for y in relations.get(k, []):
closure.add((n, y))
f(y)
f(n)
for k in relations.keys():
build_closure(k)
return closure
Thi nó, chúng ta sẽ nhận được
In [3]: transitive_closure([(1,2),(2,3),(3,4)])
Out[3]: set([(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)])
hoạt động, cảm ơn! – Duke
có thể 'quan hệ 'không phải là tên chính xác; nó chỉ lưu trữ, cho mỗi số, các số khác "có thể truy cập", xây dựng một DAG. Hàm đệ quy 'build_closure' tạo ra tất cả các đối tượng truy cập đồ thị (giải pháp này có các giả định đầu vào mạnh mẽ, linh hoạt hơn và phức tạp hơn) có thể phù hợp hơn cho các đầu vào khác) [duh, comment removed .. để lại câu trả lời này để tham khảo ] – StefanoP
Điều này sẽ chạy vào đệ quy vô hạn nếu có chu trình trong đầu vào. (Lần đầu tiên tôi hiểu sai mã, bằng cách nào đó nghĩ rằng bạn đang lặp qua các phần tử chứ không phải giải mã các phần tử riêng lẻ trong khi xây dựng 'các mối quan hệ '.) –
Không có BUILTIN cho đóng cửa bắc cầu.
Chúng khá đơn giản để triển khai.
Dưới đây là quan điểm của tôi về nó:
def transitive_closure(a):
closure = set(a)
while True:
new_relations = set((x,w) for x,y in closure for q,w in closure if q == y)
closure_until_now = closure | new_relations
if closure_until_now == closure:
break
closure = closure_until_now
return closure
gọi: transitive_closure([(1,2),(2,3),(3,4)])
kết quả: set([(1, 2), (1, 3), (1, 4), (2, 3), (3, 4), (2, 4)])
gọi: transitive_closure([(1,2),(2,1)])
kết quả: set([(1, 2), (1, 1), (2, 1), (2, 2)])
+1, rất tao nhã. Đừng bận tâm đến bình luận trước của tôi :) Btw., 'New_relations' giữ chặt * các mối quan hệ * theo cách đặt lý thuyết, hoặc * cạnh * trong điều kiện đồ thị. –
chúng tôi không nên có '(2,2)' trong kết quả của cuộc gọi thứ hai. – Duke
@Duke có bạn nên (2,2) = (2,1) * (1,2) – soulcheck
Chúng tôi có thể thực hiện thao tác "đóng cửa" từ "nút bắt đầu" nhất định bằng cách liên tục lấy một liên kết "cạnh đồ thị" từ "điểm cuối" hiện tại cho đến khi không tìm thấy điểm cuối mới. Chúng ta cần phải làm điều này nhiều nhất (số nút - 1) lần, vì đây là chiều dài tối đa của một đường dẫn. (Làm mọi thứ theo cách này tránh bị kẹt trong đệ quy vô hạn nếu có chu kỳ, nó sẽ lãng phí sự lặp lại trong trường hợp chung, nhưng tránh việc kiểm tra xem chúng ta có thực hiện nghĩa là không có thay đổi nào được thực hiện trong một lần lặp lại không.)
from collections import defaultdict
def transitive_closure(elements):
edges = defaultdict(set)
# map from first element of input tuples to "reachable" second elements
for x, y in elements: edges[x].add(y)
for _ in range(len(elements) - 1):
edges = defaultdict(set, (
(k, v.union(*(edges[i] for i in v)))
for (k, v) in edges.items()
))
return set((k, i) for (k, v) in edges.items() for i in v)
(tôi thực sự thử nghiệm nó cho một lần;))
cũng hoạt động. – Duke
dưới mức tối ưu, nhưng khái niệm đơn giản giải pháp:
def transitive_closure(a):
closure = set()
for x, _ in a:
closure |= set((x, y) for y in dfs(x, a))
return closure
def dfs(x, a):
"""Yields single elements from a in depth-first order, starting from x"""
for y in [y for w, y in a if w == x]:
yield y
for z in dfs(y, a):
yield z
này sẽ không hoạt động khi có một chu kỳ trong quan hệ, tức là một điểm phản .
Dưới đây là một cơ bản giống như một từ @soulcheck hoạt động trên danh sách kề chứ không phải là danh sách cạnh:
def inplace_transitive_closure(g):
"""g is an adjacency list graph implemented as a dict of sets"""
done = False
while not done:
done = True
for v0, v1s in g.items():
old_len = len(v1s)
for v2s in [g[v1] for v1 in v1s]:
v1s |= v2s
done = done and len(v1s) == old_len
Nếu bạn có rất nhiều tupels (hơn 5000), bạn có thể muốn xem xét sử dụng mã scipy cho sức mạnh ma trận (xem thêm http://www.ics.uci.edu/~irani/w15-6B/BoardNotes/MatrixMultiplication.pdf)
from scipy.sparse import csr_matrix as csr
M = csr(([True for tup in tups],([tup[0] for tup in tups],[tup[1] for tup in tups])))
M_ = M**n #this is the actual computation
temp = M_.nonzero()
tups_ = [(temp[0][i],temp[1][i]) for i in xrange(len(temp[0]))]
Trong trường hợp tốt nhất, bạn có thể chọn một cách khôn ngoan n
nếu bạn biết một chút thông tin về mối quan hệ của bạn/đồ thị - đó là bao lâu con đường dài nhất có thể . Nếu không, bạn phải chọn M.shape[0]
, điều này có thể thổi phồng vào mặt bạn.
Đường vòng này cũng có giới hạn của nó, đặc biệt bạn nên chắc chắn hơn mức đóng không quá lớn (kết nối không quá mạnh), nhưng bạn sẽ gặp vấn đề tương tự trong việc triển khai python.
Ý nghĩa 'chuyển đổi' và 'đóng cửa' ở đây là gì? Nguyên tắc của sự xuất hiện của (1,3) và (2,4) là gì? Các bộ dữ liệu của bạn luôn có cùng độ dài không? 'Tuples' nghĩa là gì? – eyquem
Thông tin thêm về đóng cửa chuyển tiếp tại đây [transitive_closure] (http://xlinux.nist.gov/dads/HTML/transitiveClosure.html). Về cơ bản, nguyên tắc là nếu trong danh sách gốc của các bộ dữ liệu, chúng ta có hai bộ dữ liệu dạng '(a, b)' và '(c, z)', và 'b' bằng' c', sau đó chúng ta thêm tuple '(a, z) ' Tuples sẽ luôn có hai mục nhập vì đó là một mối quan hệ nhị phân. Bởi 'tuples tính toán' tôi có nghĩa là mở rộng danh sách gốc của bộ dữ liệu để trở thành đóng cửa chuyển tiếp. – Duke
Cảm ơn bạn. Tôi hoàn toàn không biết gì về khái niệm này. – eyquem