calc_flowdirection.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. '''calc flow direction.
  2. step1. division block.
  3. step2. appoint source.
  4. setp3. calc flow direction.
  5. '''
  6. from relations.src.system_relation import systemdatautils
  7. import networkx as nx
  8. def calc(block_datas,source_datas):
  9. '''
  10. calc block flow direction.
  11. :param project_id:
  12. :param block_id:
  13. :return:
  14. '''
  15. # get roots
  16. roots=list(i.source_id for i in source_datas)
  17. g = nx.Graph()
  18. for item in block_datas:
  19. item.direction=None
  20. g.add_edge(item.id1,item.id2)
  21. G = g.to_directed()
  22. # get leaves
  23. leaves=list(v for v,d in G.out_degree() if d==1)
  24. G_new=nx.DiGraph()
  25. try:
  26. for i in range(len(roots)):
  27. root=roots[i]
  28. sign=1 if source_datas[i].is_source else -1
  29. for leaf in leaves:
  30. paths = nx.all_simple_paths(G, root, leaf)
  31. for path in paths:
  32. # remove contain source path
  33. if is_path_contain_root(path, roots, root):
  34. continue
  35. # set path direction
  36. for j in range(len(path) - 1):
  37. G_new.add_edge(path[j], path[j + 1],weight=(j*sign))
  38. # add source direct to source path.
  39. for j in range(i + 1, len(roots)):
  40. next_root=roots[j]
  41. paths = list(nx.all_simple_paths(G, root, next_root))
  42. for path in paths:
  43. if len(path) == 2:
  44. G_new.add_edge(root, next_root,weight=0)
  45. G_new.add_edge(next_root, root,weight=0)
  46. except Exception as ex:
  47. print(ex)
  48. for edge in G_new.edges:
  49. edge_data=G_new.get_edge_data(edge[0],edge[1])
  50. weight=edge_data["weight"]
  51. set_edge_direction(block_datas,edge,weight)
  52. return block_datas
  53. def is_path_contain_root(path, roots, cur_root):
  54. '''
  55. judge whether path contain root node except cur_root.
  56. :param path:
  57. :param roots:
  58. :param cur_root:
  59. :return:
  60. '''
  61. result = False
  62. for root in roots:
  63. if root == cur_root:
  64. continue
  65. result = (root in path)
  66. if result:
  67. break
  68. return result
  69. def set_edge_direction(block_datas,edge,weight):
  70. '''
  71. set connected_block direction.
  72. connector1 to connector2.sign:1
  73. connector2 to connector1.sign:-1
  74. both way.sign:0
  75. un calc.sign:None
  76. :param block_datas:
  77. :param edge:
  78. :return:
  79. '''
  80. for block_data in block_datas:
  81. # connector1 to connector2.sign:1
  82. if block_data.id1 == edge[0] and block_data.id2 == edge[1]:
  83. j=1
  84. block_data.direction=(block_data.direction+j if block_data.direction else j)
  85. block_data.depth=(weight)
  86. # connector2 to connector1.sing:-1
  87. if block_data.id1 == edge[1] and block_data.id2 == edge[0]:
  88. j = -1
  89. block_data.direction=(block_data.direction+j if block_data.direction else j)
  90. block_data.depth = (weight)