-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph.py
66 lines (57 loc) · 1.82 KB
/
graph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
"""
Graph class stores relationships.
"""
class Graph:
""" Graph structure. """
def __init__(self)->None:
self.nodes:dict[str,set[str]]={}
def add(self,a:str,b:str)->None:
""" Add relation a -> b """
# Ignore self-references.
if a==b:
return
if not self.nodes.get(a):
self.nodes[a]=set()
self.nodes[a].add(b)
def remove(self,node_name:str)->None:
""" Remove <node_name> from the graph. """
self.nodes.pop(node_name)
for s in self.nodes.values():
s.discard(node_name)
def contains(self,node_name:str)->bool:
""" Check if graph has <node_name>. """
is_key:bool=node_name in self.nodes
is_value:bool=[node_name in x for x in self.nodes.values()].count(True)>=1
return is_key or is_value
def count_downstream(self,node_name:str)->int:
""" Count nodes downstream of <node_name>. """
deps:set[str]=self.nodes.get(node_name,set())
i:int=len(deps)
for subnode in deps:
i+=self.count_downstream(subnode)
return i
def count_upstream(self,node_name:str,recurse:bool=True)->int:
""" Count nodes upstream of <node_name>. """
i=0
for k,v in self.nodes.items():
for n in v:
if n==node_name:
i+=1
if recurse:
i+=self.count_upstream(k)
return i
def is_bidirectional(self,a:str,b:str)->bool:
""" Check a <-> b. """
return b in self.nodes.get(a,{}) and a in self.nodes.get(b,{})
# def rank(self)->str:
# """ Rank nodes and return string containing DOT rank instructions. """
# rank_dict:dict=swapped_dict({k:len(v) for k,v in self.nodes.items()})
# sorted_ranks:list=sorted(rank_dict.items(),reverse=True)
# print(sorted_ranks)
# return "\n".join(["{rank=same;"+";".join(x[1])+";}" for x in sorted_ranks])
def swapped_dict(d:dict)->dict:
""" Return new dict where keys and values are swapped. """
x:dict={}
for k,v in d.items():
x.setdefault(v,[]).append(k)
return x