Я реализую в терминах SQLAlchemy структуру, которая имеет математическую характеристику Частично упорядоченный набор , в которой мне нужно иметь возможность добавлять и удалять ребра по одному за раз.
В моем текущем, лучшем дизайне я использую два списка смежности, один из которых является списком назначений (приблизительно ребрами в Hass Diagram), так как мне нужно сохранить, какие пары узлов явно установлены в порядке, а другой список смежноститранзитивное замыкание первого, так что я могу эффективно запросить, упорядочен ли один узел относительно другого.Прямо сейчас я пересчитываю транзитивное замыкание каждый раз, когда ребро добавляется или удаляется из списка смежных назначений.
Это выглядит примерно так:
assignment = Table('assignment', metadata,
Column('parent', Integer, ForeignKey('node.id')),
Column('child', Integer, ForeignKey('node.id')))
closure = Table('closure', metadata,
Column('ancestor', Integer, ForeignKey('node.id')),
Column('descendent', Integer, ForeignKey('node.id')))
class Node(Base):
__tablename__ = 'node'
id = Column(Integer, primary_key=True)
parents = relationship(Node, secondary=assignment,
backref='children',
primaryjoin=id == assignment.c.parent,
secondaryjoin=id == assignment.c.child)
ancestors = relationship(Node, secondary=closure,
backref='descendents',
primaryjoin=id == closure.c.ancestor,
secondaryjoin=id == closure.c.descendent,
viewonly=True)
@classmethod
def recompute_ancestry(cls.conn):
conn.execute(closure.delete())
adjacent_values = conn.execute(assignment.select()).fetchall()
conn.execute(closure.insert(), floyd_warshall(adjacent_values))
, где floyd_warshall()
-Реализация алгоритма с тем же именем.
Это приводит меня к двум проблемам.Во-первых, кажется, что это не очень эффективно, но я не уверен, какой алгоритм я мог бы использовать вместо этого.
Второй - больше о практичности необходимости явного вызова Node.recompute_ancestry()
каждый раз, когда происходит назначение, и только после назначения сбрасываются в сеанс и с надлежащими соединениями.Если я хочу увидеть изменения, отраженные в ORM, мне придется сбросить сеанс снова .Думаю, было бы намного проще, если бы я мог выразить операцию пересчета предков в виде нормы.