1+ from collections import defaultdict , deque
2+ from typing import Dict , List , Tuple
3+
4+ class Graph :
5+ def __init__ (self ):
6+ self ._nodes :List = []
7+ self ._edges :List [Tuple ] = []
8+
9+ @property
10+ def roots (self ) -> List :
11+ roots :List = []
12+ for node in self ._nodes :
13+ isChild = False
14+ for edge in self ._edges :
15+ if edge [- 1 ] == node :
16+ isChild = True
17+ continue
18+ if isChild == False :
19+ roots .append (node )
20+ return roots .copy ()
21+
22+ @property
23+ def nodes (self ) -> List :
24+ return self ._nodes .copy ()
25+
26+ @property
27+ def edges (self ) -> List :
28+ return self ._edges .copy ()
29+
30+ @nodes .setter
31+ def nodes (self , nodes ):
32+ self ._nodes = list (nodes )
33+
34+ @edges .setter
35+ def edges (self , edges ):
36+ self ._edges = [tuple (e ) for e in edges ]
37+
38+ def add_node (self , node ):
39+ if node not in self ._nodes :
40+ self ._nodes .append (node )
41+
42+ def add_edge (self , source , destination ):
43+ if source not in self ._nodes :
44+ self .add_node (source )
45+ if destination not in self ._nodes :
46+ self .add_node (destination )
47+ if (source , destination ) not in self ._edges :
48+ self ._edges .append ((source , destination ))
49+
50+ def get_connections (self ):
51+ connections = {node : [] for node in self ._nodes }
52+ for source , destination in self ._edges :
53+ connections [source ].append (destination )
54+ return connections
55+
56+ def getParentNodes (self ) -> List :
57+ return [edge [0 ] for edge in self ._edges ]
58+
59+ def getChildNodes (self ) -> List :
60+ return [edge [- 1 ] for edge in self ._edges ]
61+
62+ #Necesita una revisión pero por ahora hace lo que necesito
63+ def prune_to_longest_paths (self ):
64+ connections = self .get_connections ()
65+ roots = [n for n in self ._nodes if n not in self .getChildNodes ()]
66+
67+ longest_paths = []
68+
69+ def dfs (node , path ):
70+ path = path + [node ]
71+ if node not in connections or not connections [node ]:
72+ longest_paths .append (path )
73+ return
74+ for child in connections [node ]:
75+ dfs (child , path )
76+
77+ for root in roots :
78+ dfs (root , [])
79+
80+ leaf_to_path = {}
81+ for path in longest_paths :
82+ leaf = path [- 1 ]
83+ if leaf not in leaf_to_path or len (path ) > len (leaf_to_path [leaf ]):
84+ leaf_to_path [leaf ] = path
85+
86+ new_nodes = set ()
87+ new_edges = set ()
88+ for path in leaf_to_path .values ():
89+ new_nodes .update (path )
90+ new_edges .update ([(path [i ], path [i + 1 ]) for i in range (len (path )- 1 )])
91+
92+ self ._nodes = list (new_nodes )
93+ self ._edges = list (new_edges )
94+
95+ def getAdyacencyTree (self ) -> Dict :
96+ tree = defaultdict (list )
97+ for root in self .roots :
98+ tree ['' ].append (root )
99+ for parent , child in self ._edges :
100+ tree [parent ].append (child )
101+ return tree
102+
103+ def getNodesByLevels (self ) -> List :
104+ adyacencyTree = self .getAdyacencyTree ()
105+ qeue = deque ([('' ,0 )])
106+ nodeList = []
107+ while qeue :
108+ node ,level = qeue .popleft ()
109+ nodeList .append (node )
110+ for child in adyacencyTree [node ]:
111+ qeue .append ((child , level + 1 ))
112+ return nodeList [1 :] #Removes case 0 that is not part of nodes
113+
114+ def _reorderData (self ) -> None :
115+ self ._edges = sorted (self ._edges )
116+ self ._nodes = sorted (self ._nodes )
117+
118+ def __str__ (self ):
119+ return f"Graph(Nodes: { self ._nodes } ,\n Edges: { self ._edges } )"
0 commit comments