Giảm các cạnh thừa từ biểu đồ phụ thuộc


8

Tôi có một DAG của các phụ thuộc có chứa nhiều cạnh dư thừa (xem ví dụ bên dưới). Tôi muốn một thuật toán "nhanh" (nghĩa là có thể xử lý một biểu đồ với hàng ngàn nút / cạnh) để tìm một biểu đồ con tối thiểu.

Ví dụ:

A -> B -> C
A -> C

trong các từ A là điều kiện tiên quyết đối với B và B là điều kiện tiên quyết đối với C và A cũng là điều kiện tiên quyết đối với C. Trong trường hợp này A -> C là dự phòng (vì B đã cần đến C và A cần thiết để đạt B) .

Đã được một thời gian kể từ khi tôi nghiên cứu các thuật toán, và tôi không biết bắt đầu từ đâu.

Nhân tiện, thuật toán tìm thấy mức tối thiểu toàn cầu, tối thiểu cục bộ là không quan trọng (việc giảm cạnh chỉ là tối ưu hóa thời gian chạy cho giai đoạn xử lý tiếp theo).

Ngoài ra, tôi nhận ra đây là CS QA và không lập trình, nhưng chương trình của tôi được viết bằng Python, vì vậy tôi sẽ rất vui khi biết về mô-đun python hoặc mã nguồn mở để thực hiện việc giảm này, chỉ trong trường hợp bạn biết về nó.

cảm ơn trước!


Tôi đã tự hỏi nếu DFS có thể giúp đỡ ở đây?
Pratik Deoghare

3
Bạn đang tìm kiếm "giảm chuyển tiếp" của biểu đồ phụ thuộc của bạn.
Dave Clarke

Tìm các thành phần kết nối mạnh mẽ. Chỉ để lại một cạnh giữa mỗi cặp thành phần. Đối với mỗi thành phần được kết nối mạnh, bạn cần tìm một số chu kỳ tối thiểu sẽ bao phủ nó. Việc tìm kiếm một số chu kỳ tối thiểu dường như là NP hoàn chỉnh vì nó sẽ quyết định Tính độc lập, nhưng vì bạn chỉ cần tối thiểu cục bộ chỉ cần loại bỏ các cạnh khỏi mỗi thành phần cho đến khi nó mất kết nối mạnh mẽ.
Kaveh

Câu trả lời:


13

Sự giảm dần của một đồ thị có hướng AV Aho, MR Garey và JD Ullman

Theo wikipedia , thuật toán này được sử dụng bởi tredđây là công cụ để giảm quá độ có sẵn trong gói GraphViz. Bạn có thể chạy nó trên biểu đồ của bạn và nhận được biểu đồ giảm.

Câu hỏi này là bản sao của câu hỏi stackoverflow này .

mã ở đây graphviz/tools/src/tred.c không sử dụng DFS. ;-)


2
Tôi không biết tred, cảm ơn.
Anthony Labarre

1
Cảm ơn bạn MachineCharmer. Tôi ở bên ngoài một trường đại học và không thể tải xuống bài báo mà không trả 25 đô la ... có nguồn trực tuyến miễn phí nào mô tả thuật toán này không? Nguồn tred là nhỏ và có thể đọc được, nhưng không có giải thích.
Iftah

Không. Không có liên kết tải xuống miễn phí cho bài báo đó. Nhưng bạn có thể có bạn bè ở một số trường đại học :)
Pratik Deoghare

-1

Tôi đã kết thúc việc giải quyết nó theo cách này:

Cấu trúc dữ liệu của tôi được làm bằng dependends từ điển, từ id nút đến danh sách các nút phụ thuộc vào nó (nghĩa là người theo dõi trong DAG).

Tôi đã không tính được độ phức tạp chính xác của nó, nhưng nó đã nuốt đồ thị của tôi vài nghìn trong một tích tắc.

_transitive_closure_cache = {}
def transitive_closure(self, node_id):
    """returns a set of all the nodes (ids) reachable from given node(_id)"""
    global _transitive_closure_cache
    if node_id in _transitive_closure_cache:
        return _transitive_closure_cache[node_id]
    c = set(d.id for d in dependents[node_id])
    for d in dependents[node_id]:
        c.update(transitive_closure(d.id))  # for the non-pythonists - update is update self to Union result
    _transitive_closure_cache[node_id] = c
    return c

def can_reduce(self, source_id, dest_id):
    """returns True if the edge (source_id, dest_id) is redundant (can reach from source_id to dest_id without it)"""
    for d in dependents[source_id]:
        if d.id == dest_id:
            continue
        if dest_id in transitive_closure(d.id):
            return True # the dest node can be reached in a less direct path, then this link is redundant
    return False

# Reduce redundant edges:
for node in nodes:      
    dependents[node.id] = [d for d in dependents[node.id] if not can_reduce(node.id, d.id)]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.