我使用SQLAlchemy实现了一个具有Partially Ordered Set的数学特性的结构,其中我需要能够一次添加和删除一条边。我使用两个邻接列表,一个是赋值列表(Hass图中的近似边),因为我需要保留哪些对明确设置为有序,而另一个邻接list是第一个的传递闭包,所以我可以高效地查询一个节点是否相对于另一个节点进行排序。现在,每当向分配邻接列表中添加或删除边缘时,我都会重新计算传递闭包。poset的高效增量实现
它看起来是这样的:
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中反映的更改,我必须再次清空会话。我认为,如果我能够用orm来表达重新计算的祖先操作,那将会容易得多。