Вы просто смешиваете дуги и ребра, что приводит к некоторым неожиданным событиям, вам нужно выбирать между любым из двух.
С другой стороны, вы можете иметь ориентированный граф и при этом иметь функцию, которая добавит «ребра» в том смысле, что она добавит как дуги (u, v), так и (v, u).У меня есть ребра в кавычках, потому что они на самом деле не ребра (термин ребро имеет значение только в неориентированном графе).
from collections import defaultdict
class Graph:
def __init__(self):
self._arcs = defaultdict(dict)
def insert_arc(self, u, v, w):
self._arcs[u][v] = w
def is_arc(self, u, v):
return u in self._arcs and v in self._arcs[u]
def is_path_valid(self, path):
for u, v in zip(path, path[1:]):
if not self.is_arc(u, v):
return False
return True
# We add the notion of "edges" with the following methods:
def insert_edge(self, u, v, w):
self.insert_arc(u, v, w)
self.insert_arc(v, u, w)
@property
def edges(self):
return {((u, v), w) for u, Nu in self._arcs.items() for v, w in Nu.items() if self.is_edge(u, v)}
def is_edge(self, u, v):
is_symetric = self.is_arc(u, v) and self.is_arc(v, u)
if not is_symetric:
return False
return self._arcs[u][v] == self._arcs[v][u]
Теперь вы можете добавить ребра или дуги к вашему графику:
g = Graph()
# This is an arc:
g.insert_arc(1, 8, 1.)
# Weight is not symmetric but this still look like an edge:
g.insert_arc(1, 0, 3.)
g.insert_arc(0, 1, 2.)
# These are all symmetric (ie. "edges")
g.insert_edge(1, 2, 7.)
g.insert_edge(2, 3, 5.)
g.insert_edge(0, 3, 13.)
# we added an arc (1, 8):
print(g.is_path_valid([1, 8])) # True
print(g.is_path_valid([8, 1])) # False
# All true:
print(g.is_path_valid([0, 3]))
print(g.is_path_valid([2, 3]))
print(g.is_path_valid([0, 1, 2, 3, 0]))
# Adding one step make this false since (0, 2) doesn't exist:
print(g.is_path_valid([0, 1, 2, 3, 0, 2]))
Мы можем использовать свойство edges
, чтобы найти все «ребра» (симметричные дуги с одинаковым весом в обоих направлениях):
>>> print(g.edges)
{((3, 0), 13.0), ((3, 2), 5.0), ((2, 1), 7.0), ((1, 2), 7.0), ((2, 3), 5.0), ((0, 3), 13.0)}
Обратите внимание, что (0, 1)
не является частьюиз набора ребер, это потому, что ссылка существует в обоих направлениях, но вес не одинаков.Дуги (1, 8)
здесь явно нет, поскольку (8, 1)
не является частью графика.