使用属性实现“类别”系统

时间:2015-04-01 10:14:11

标签: python igraph

我有大约1000个类别'它覆盖了我的边缘。我使用属性指定这些类别:

g.es[0]["$cat1"]=True

一条边可以属于多个类别。

问题是,这会导致我的所有其他边缘,即使它们与类别1无关,也无法获得属性$cat1=None

所以基本上即使我的边缘是单个类别的一部分,它也会有999个其他属性,例如$catN=None

我需要能够将每个类别(包括它的所有成员节点和边缘)提取到一个单独的子图中。现在,我只是遍历所有边缘,查看$catN = True的位置,并将这些边和节点放入新图中。

  1. 这个方法整体看起来是否可扩展?这似乎有点混乱,因为可能有一百万个节点和一万个类别。这意味着每个边缘将存储2-3 $catN = True,但数千个冗余$catN = None
  2. 如果没有,您是否有任何建议来实施此类别'系统更好?
  3. 如果这是最好的,那么检索特定类别的建议是什么?遍历所有边缘似乎是浪费。我想我可以维护一个单独的数据结构,边缘nos对应于每个类别。尽管如此,这将是一种痛苦。

1 个答案:

答案 0 :(得分:0)

是否有必要将每条边的类别存储为边属性?如果您的图形不会被突变(即您不会从图形中删除边缘),您可以简单地使用将类别ID映射到边缘ID的外部Python dict - 然后您可以使用单个字典查找来获取每个类别的成员。如果你还需要快速告诉边缘属于哪个类别,你还需要反向映射,所以也许最好创建一个单独的“双向映射”类并分别维护映射的两面:

from collections import defaultdict

class CategoryMapping(object):
    def __init__(self):
        self.category_to_members = defaultdict(set)
        self.member_to_categories = defaultdict(set)

    def add(self, category, member):
        self.category_to_members[category].add(member)
        self.member_to_categories[member].add(category)

    def remove(self, category, member):
        self.category_to_members[category].discard(member)
        self.member_to_categories[member].discard(category)

    def categories_of(self, member):
        return self.member_to_categories[member]

    def members_of(self, category):
        return self.category_to_member[category]

修改:如果有时会从图表中删除边缘,您可以为其id边缘属性中的每条边分配唯一ID,然后在{{1}中使用这些ID }。唯一的问题是按属性的边缘查找是O(n)操作,其中n是边数。为了缓解这种情况,您还可以创建边缘ID到索引映射类。这个类可以有一个CategoryMapping方法,每当你从图中删除边时,你必须用删除边的旧ID调用它,并且它应该相应地更新内部ID到索引的映射。 (可悲的是,igraph没有边缘的特殊id类属性,即使它以这种方式处理顶点对象的edges_removed()属性,因此你可以按名称实现顶点的O(1)查找。你可以利用这样一个事实,即如果 k 删除边缘,索引更小,那么边缘 i 的索引将成为 ik 比原始图中的 i