【问题标题】:generate and execute processing graphs in networkx在networkx中生成和执行处理图
【发布时间】:2016-03-17 14:46:09
【问题描述】:

我有许多“进程”,每个都实现为一个类(实现一个接口 -process)和一些“数据集”,同样由一个类表示 -dataset

可以创建数据集及其依赖项的有向无环图。它可能看起来像:

            root
           /   \
  dataset1a     dataset1b
     |              |
  dataset2      dataset2b
   /   |  \        /     \
dset3a | dset3b  dset4a dset4b
   \   |        /
    \  |       /
     \ |      /
     dataset3a4a

要获取每个数据集,必须应用一个进程(由 process 类表示)。目前,我正在使用网络 x 创建一个DiGraph,其中每个数据集对象都是一个节点,到达X 节点的过程是指向process 对象的节点上的一个属性。 ROOT 只是一个提供起始节点的虚拟节点。

这是用 networkx 表示图形的好方法吗? 鉴于dataset1adataset1b 存在并且必须创建它们的后代(其中每个先前的数据集都是process 类的输入)...什么是遍历图形的好方法,这样:

  • 一个节点只有在其所有依赖项都被访问后才会被访问(并因此创建了数据集)
  • 可以找到依赖的“节点”...例如如果我在 dataset3a4a 节点,我必须能够发现所有“输入”来创建该数据集 - dset3adset4adataset2

【问题讨论】:

    标签: python graph networkx dataflow


    【解决方案1】:

    Python 提供了一些内省工具,您可以使用它们来代替 networkx。 __subclasses__ 方法返回给定类的直接子类列表:

    In [36]: Root.__subclasses__()
    Out[38]: [__main__.DataSet1a, __main__.DataSet1b]
    In [61]: DataSet2.__subclasses__()
    Out[61]: [__main__.DSet3a, __main__.DSet3b, __main__.DataSet3a4a]
    In [62]: DataSet3a4a.__subclasses__()
    Out[62]: []
    

    __bases__ 属性返回类的基类(直接父类):

    In [63]: DataSet3a4a.__bases__
    Out[63]: (__main__.DSet3a, __main__.DataSet2, __main__.DSet4a)
    

    __bases__ 属性为您的第二个问题提供了答案 如何找到输入来创建数据集。

    要回答第一个问题,您可以使用__subclasses____bases__ 来 构建自己的遍历函数:

    import collections
    class Root(object): pass
    class DataSet1a(Root): pass
    class DataSet1b(Root): pass
    class DataSet2(DataSet1a): pass
    class DataSet2b(DataSet1b): pass
    class DSet3a(DataSet2): pass
    class DSet3b(DataSet2): pass
    class DSet4a(DataSet2b): pass
    class DSet4b(DataSet2b): pass
    class DataSet3a4a(DSet3a, DataSet2, DSet4a): pass
    
    def visit(cls):
        seen = set([cls])
        queue = collections.deque(cls.__subclasses__())
        while queue:
            subcls = queue.popleft()
            if subcls in seen: continue
            # check that all its bases have been seen
            for base in subcls.__bases__:
                if base not in seen:
                    # if a base has not been seen, push subcls to the back of the queue
                    queue.append(subcls)
                    break
            else:
                # all the bases of subcls have already been seen
                seen.add(subcls)
                yield subcls
            # add all the subclasses of subcls to the queue
            queue.extend(subcls.__subclasses__())
    
    for cls in visit(Root):
        print(cls.__name__)
    

    产量

    DataSet1a
    DataSet1b
    DataSet2
    DataSet2b
    DSet3a
    DSet3b
    DSet4a
    DSet4b
    DataSet3a4a
    

    【讨论】:

      猜你喜欢
      • 2021-09-15
      • 2016-12-21
      • 1970-01-01
      • 2020-04-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-17
      • 2014-06-25
      • 1970-01-01
      相关资源
      最近更新 更多