2016-03-17 6 views
0

У меня есть несколько «процессов», каждый из которых реализован как класс (реализующий интерфейс - process) и ряд «наборов данных», снова представленных классом - dataset.генерировать и выполнять графики обработки в сетиx

Направленный ациклический граф наборов данных и их dependecies может быть created..It может выглядеть примерно так:

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

Чтобы добраться до каждого набора данных, процесс (представленный process класс) должен быть применен. В настоящее время я создаю DiGraph с сетью x, где каждый объект набора данных является узлом, а процесс для перехода на узел X является атрибутом узла, указывающего на объект process. ROOT - всего лишь фиктивный узел, обеспечивающий исходный узел.

Является ли это хорошим способом представления графика с помощью networkx? Учитывая, что dataset1a и dataset1b существуют и их decendants должны быть созданы (где каждый предыдущий набор данных является входом в process класс) ... что это хороший способ обхода графа таким образом, что:

  • узел является не посещаются до тех пор, пока не будут посещены все его «иждивенцы» (и, следовательно, создаваемые массивы данных)
  • Зависимый «узел» может быть найден ... например если я нахожусь на узле dataset3a4a, я должен быть в состоянии обнаружить все «входы» для создания этого набора данных - dset3a, dset4a и dataset2.

ответ

0

Python предоставляет некоторые инструменты самоанализа, которые вы могли бы использовать вместо networkx. Метод __subclasses__ возвращает список прямого subclasess данного класса:

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