Hướng dẫn python graphlib - đồ thị python

Mã nguồn: lib/graphlib.py Lib/graphlib.py


classgraphlib.topologicalsorter (graph = none) ¶ graphlib.TopologicalSorter(graph=None)

Cung cấp chức năng để sắp xếp cấu trúc liên kết một biểu đồ của các nút có thể băm.

Một thứ tự tôpô là thứ tự tuyến tính của các đỉnh trong một biểu đồ sao cho mỗi cạnh được định hướng u -> v từ đỉnh U đến vertex v, vertex u đến trước vertex v theo thứ tự. Chẳng hạn, các đỉnh của biểu đồ có thể biểu thị các tác vụ được thực hiện và các cạnh có thể biểu thị các ràng buộc mà một tác vụ phải được thực hiện trước một tác vụ khác; Trong ví dụ này, một thứ tự tôpô chỉ là một chuỗi hợp lệ cho các nhiệm vụ. Một thứ tự tô màu hoàn chỉnh là có thể nếu và chỉ khi biểu đồ không có chu kỳ theo hướng, nghĩa là, nếu đó là một biểu đồ acyclic có hướng.

Nếu đối số đồ thị tùy chọn được cung cấp, nó phải là một từ điển đại diện cho một biểu đồ acyclic có hướng trong đó các phím là nút và các giá trị là lặp lại của tất cả các yếu tố của nút đó trong biểu đồ (các nút có các cạnh chỉ vào giá trị trong khóa ). Các nút bổ sung có thể được thêm vào biểu đồ bằng phương pháp add().

Trong trường hợp chung, các bước cần thiết để thực hiện việc sắp xếp một biểu đồ nhất định như sau:

  • Tạo một thể hiện của TopologicalSorter với biểu đồ ban đầu tùy chọn.

  • Thêm các nút bổ sung vào biểu đồ.

  • Gọi prepare() trên biểu đồ.

  • Trong khi is_active()True, lặp lại các nút được trả về bởi get_ready() và xử lý chúng. Gọi

    topological_sorter = TopologicalSorter()
    
    # Add nodes to 'topological_sorter'...
    
    topological_sorter.prepare()
    while topological_sorter.is_active():
        for node in topological_sorter.get_ready():
            # Worker threads or processes take nodes to work on off the
            # 'task_queue' queue.
            task_queue.put(node)
    
        # When the work for a node is done, workers put the node in
        # 'finalized_tasks_queue' so we can get more nodes to work on.
        # The definition of 'is_active()' guarantees that, at this point, at
        # least one node has been placed on 'task_queue' that hasn't yet
        # been passed to 'done()', so this blocking 'get()' must (eventually)
        # succeed.  After calling 'done()', we loop back to call 'get_ready()'
        # again, so put newly freed nodes on 'task_queue' as soon as
        # logically possible.
        node = finalized_tasks_queue.get()
        topological_sorter.done(node)
    
    0 trên mỗi nút khi hoàn thành việc xử lý.

Trong trường hợp chỉ cần sắp xếp ngay các nút trong biểu đồ và không có sự song song nào, phương pháp tiện lợi

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
1 có thể được sử dụng trực tiếp:

>>> graph = {"D": {"B", "C"}, "C": {"A"}, "B": {"A"}}
>>> ts = TopologicalSorter(graph)
>>> tuple(ts.static_order())
('A', 'C', 'B', 'D')

Lớp học được thiết kế để dễ dàng hỗ trợ xử lý song song các nút khi chúng sẵn sàng. Ví dụ:

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)

Thêm (nút, *người tiền nhiệm) ¶(node, *predecessors)

Thêm một nút mới và người tiền nhiệm của nó vào biểu đồ. Cả nút và tất cả các yếu tố trong người tiền nhiệm phải có thể băm.

Nếu được gọi là nhiều lần với cùng một đối số nút, tập hợp các phụ thuộc sẽ là sự kết hợp của tất cả các phụ thuộc được truyền vào.

Có thể thêm một nút không có sự phụ thuộc (không được cung cấp) hoặc cung cấp sự phụ thuộc hai lần. Nếu một nút chưa được cung cấp trước đó được bao gồm trong số các tiền thân, nó sẽ được tự động thêm vào biểu đồ mà không có người tiền nhiệm của riêng mình.

Tăng

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
2 nếu được gọi sau prepare().

chuẩn bị các()¶()

Đánh dấu biểu đồ khi hoàn thành và kiểm tra các chu kỳ trong biểu đồ. Nếu bất kỳ chu kỳ nào được phát hiện,

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
4 sẽ được nâng lên, nhưng get_ready() vẫn có thể được sử dụng để có được càng nhiều nút càng tốt cho đến khi các chu kỳ chặn tiến độ hơn. Sau khi gọi đến hàm này, biểu đồ không thể được sửa đổi và do đó không có thêm nút nào được thêm vào bằng add().

đang hoạt động()¶()

Trả về True nếu có thể thực hiện nhiều tiến độ hơn và

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
8 nếu không. Có thể thực hiện tiến độ nếu các chu kỳ không chặn độ phân giải và vẫn có các nút sẵn sàng mà thiên đường chưa được trả về bởi
topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
9 hoặc số nút được đánh dấu
def static_order(self):
    self.prepare()
    while self.is_active():
        node_group = self.get_ready()
        yield from node_group
        self.done(*node_group)
0 ít hơn số lượng đã được trả về bởi
topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
9.

Phương pháp

def static_order(self):
    self.prepare()
    while self.is_active():
        node_group = self.get_ready()
        yield from node_group
        self.done(*node_group)
2 của lớp này bảo vệ chức năng này, vì vậy thay vì:

Có thể chỉ đơn giản là làm:

Tăng

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
2 nếu được gọi mà không gọi prepare() trước đó.

Xong (*nút)(*nodes)

Đánh dấu một tập hợp các nút được trả về bởi

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
9 là được xử lý, bỏ chặn bất kỳ người kế thừa nào của mỗi nút trong các nút để được trả lại trong tương lai bằng một cuộc gọi đến
topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
9.

Tăng

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
2 Nếu bất kỳ nút nào trong các nút đã được đánh dấu là được xử lý bởi một cuộc gọi trước đó cho phương thức này hoặc nếu một nút không được thêm vào biểu đồ bằng cách sử dụng
def static_order(self):
    self.prepare()
    while self.is_active():
        node_group = self.get_ready()
        yield from node_group
        self.done(*node_group)
8, nếu được gọi mà không gọi prepare() hoặc nếu nút chưa được trả về bởi get_ready().

chuẩn bị()¶()

Trả về một

>>> ts = TopologicalSorter()
>>> ts.add(3, 2, 1)
>>> ts.add(1, 0)
>>> print([*ts.static_order()])
[2, 0, 1, 3]

>>> ts2 = TopologicalSorter()
>>> ts2.add(1, 0)
>>> ts2.add(3, 2, 1)
>>> print([*ts2.static_order()])
[0, 2, 1, 3]
1 với tất cả các nút đã sẵn sàng. Ban đầu, nó trả về tất cả các nút không có người tiền nhiệm và một khi chúng được đánh dấu là được xử lý bằng cách gọi
def static_order(self):
    self.prepare()
    while self.is_active():
        node_group = self.get_ready()
        yield from node_group
        self.done(*node_group)
0, các cuộc gọi tiếp theo sẽ trả về tất cả các nút mới có tất cả những người tiền nhiệm đã được xử lý. Một khi không có tiến trình nào có thể được thực hiện, các bộ dữ liệu trống được trả lại.

Tăng

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
2 nếu được gọi mà không gọi prepare() trước đó.

Xong (*nút)()

Đánh dấu một tập hợp các nút được trả về bởi

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
9 là được xử lý, bỏ chặn bất kỳ người kế thừa nào của mỗi nút trong các nút để được trả lại trong tương lai bằng một cuộc gọi đến
topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
9.

def static_order(self):
    self.prepare()
    while self.is_active():
        node_group = self.get_ready()
        yield from node_group
        self.done(*node_group)

Tăng

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
2 Nếu bất kỳ nút nào trong các nút đã được đánh dấu là được xử lý bởi một cuộc gọi trước đó cho phương thức này hoặc nếu một nút không được thêm vào biểu đồ bằng cách sử dụng
def static_order(self):
    self.prepare()
    while self.is_active():
        node_group = self.get_ready()
        yield from node_group
        self.done(*node_group)
8, nếu được gọi mà không gọi prepare() hoặc nếu nút chưa được trả về bởi get_ready().

>>> ts = TopologicalSorter()
>>> ts.add(3, 2, 1)
>>> ts.add(1, 0)
>>> print([*ts.static_order()])
[2, 0, 1, 3]

>>> ts2 = TopologicalSorter()
>>> ts2.add(1, 0)
>>> ts2.add(3, 2, 1)
>>> print([*ts2.static_order()])
[0, 2, 1, 3]

chuẩn bị()¶

Nếu bất kỳ chu kỳ được phát hiện,

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
4 sẽ được nâng lên.

Mới trong phiên bản 3.9.

Ngoại lệ ha

Mô -đun

>>> ts = TopologicalSorter()
>>> ts.add(3, 2, 1)
>>> ts.add(1, 0)
>>> print([*ts.static_order()])
[2, 0, 1, 3]

>>> ts2 = TopologicalSorter()
>>> ts2.add(1, 0)
>>> ts2.add(3, 2, 1)
>>> print([*ts2.static_order()])
[0, 2, 1, 3]
9 xác định các lớp ngoại lệ sau:

ngoại lệgraphlib.cycleerror¶ graphlib.CycleError

Lớp con của

topological_sorter = TopologicalSorter()

# Add nodes to 'topological_sorter'...

topological_sorter.prepare()
while topological_sorter.is_active():
    for node in topological_sorter.get_ready():
        # Worker threads or processes take nodes to work on off the
        # 'task_queue' queue.
        task_queue.put(node)

    # When the work for a node is done, workers put the node in
    # 'finalized_tasks_queue' so we can get more nodes to work on.
    # The definition of 'is_active()' guarantees that, at this point, at
    # least one node has been placed on 'task_queue' that hasn't yet
    # been passed to 'done()', so this blocking 'get()' must (eventually)
    # succeed.  After calling 'done()', we loop back to call 'get_ready()'
    # again, so put newly freed nodes on 'task_queue' as soon as
    # logically possible.
    node = finalized_tasks_queue.get()
    topological_sorter.done(node)
2 được nâng lên bởi add()1 nếu các chu kỳ tồn tại trong biểu đồ làm việc.Nếu nhiều chu kỳ tồn tại, chỉ có một lựa chọn không xác định trong số chúng sẽ được báo cáo và bao gồm trong ngoại lệ.

Chu kỳ được phát hiện có thể được truy cập thông qua phần tử thứ hai trong thuộc tính add()2 của thể hiện ngoại lệ và bao gồm trong một danh sách các nút, sao cho mỗi nút, trong biểu đồ, là người tiền nhiệm ngay lập tức của nút tiếp theo trong danh sách.Trong danh sách được báo cáo, nút đầu tiên và cuối cùng sẽ giống nhau, để làm rõ rằng nó là theo chu kỳ.