1
- """
2
- Weighted undirected sparse graphs.
1
+ """Weighted undirected sparse graphs.
3
2
4
3
Original source:
5
4
https://github.com/marcharper/stationary/blob/master/stationary/utils/graph.py
9
8
10
9
11
10
class Graph (object ):
12
- """Weighted and directed graph object intended for the graph associated to a
13
- Markov process. Gives easy access to the neighbors of a particular state
14
- needed for various calculations.
15
-
16
- Vertices can be any hashable / immutable python object. Initialize with a
17
- list of edges:
11
+ """Weighted and directed graph class.
12
+
13
+ This class is intended for the graph associated to a Markov process,
14
+ since it gives easy access to the neighbors of a particular state.
15
+
16
+ Vertices can be any hashable Python object.
17
+
18
+ Initialize with a list of edges:
18
19
[[node1, node2, weights], ...]
19
20
Weights can be omitted for an undirected graph.
20
21
21
- For efficiency, neighbors are cached in dictionaries. Undirected graphs
22
- are implemented as directed graphs in which every edge (s, t) has the
23
- opposite edge (t, s).
22
+ For efficiency, neighbors are cached in dictionaries. Undirected
23
+ graphs are implemented as directed graphs in which every edge (s, t)
24
+ has the opposite edge (t, s).
25
+
26
+ Attributes
27
+ ----------
28
+ directed: Boolean indicating whether the graph is directed
29
+ original_edges: the edges passed into the initializer
30
+ out_mapping: a dictionary mapping all heads to dictionaries that map
31
+ all tails to their edge weights (None means no weight)
32
+ in_mapping: a dictionary mapping all tails to dictionaries that map
33
+ all heads to their edge weights (none means to weight)
34
+
35
+ Properties
36
+ ----------
37
+ vertices: the set of vertices in the graph
38
+ edges: the set of current edges in the graph
24
39
"""
25
40
26
41
def __init__ (self , edges = None , directed = False ):
@@ -30,9 +45,9 @@ def __init__(self, edges=None, directed=False):
30
45
self .in_mapping = defaultdict (lambda : defaultdict (float ))
31
46
self ._edges = []
32
47
if edges :
33
- self .add_edges (edges )
48
+ self ._add_edges (edges )
34
49
35
- def add_edge (self , source , target , weight = None ):
50
+ def _add_edge (self , source , target , weight = None ):
36
51
if (source , target ) not in self ._edges :
37
52
self ._edges .append ((source , target ))
38
53
self .out_mapping [source ][target ] = weight
@@ -46,21 +61,20 @@ def add_edge(self, source, target, weight=None):
46
61
self .out_mapping [target ][source ] = weight
47
62
self .in_mapping [source ][target ] = weight
48
63
49
- def add_edges (self , edges ):
64
+ def _add_edges (self , edges ):
50
65
for edge in edges :
51
- self .add_edge (* edge )
66
+ self ._add_edge (* edge )
52
67
53
68
def add_loops (self ):
54
- """
55
- Add all loops to edges.
56
- """
57
- self .add_edges ((x , x ) for x in self .vertices ())
69
+ """Add all loops to edges."""
70
+ self ._add_edges ((x , x ) for x in self .vertices )
58
71
72
+ @property
59
73
def edges (self ):
60
74
return self ._edges
61
75
76
+ @property
62
77
def vertices (self ):
63
- """Returns the set of vertices of the graph."""
64
78
return list (self .out_mapping .keys ())
65
79
66
80
def out_dict (self , source ):
@@ -84,53 +98,46 @@ def __repr__(self):
84
98
return s
85
99
86
100
87
- # Example Graphs
101
+ # Example graph factories.
88
102
89
103
90
104
def cycle (length , directed = False ):
91
- """
92
- Produces a cycle of length `length`.
105
+ """Produces a cycle of a specified length.
106
+
93
107
Parameters
94
108
----------
95
109
length: int
96
110
Number of vertices in the cycle
97
111
directed: bool, False
98
112
Is the cycle directed?
113
+
99
114
Returns
100
115
-------
101
- a Graph object
116
+ a Graph object for the cycle
102
117
"""
103
-
104
- graph = Graph (directed = directed )
105
- edges = []
106
- for i in range (length - 1 ):
107
- edges .append ((i , i + 1 ))
118
+ edges = [(i , i + 1 ) for i in range (length - 1 )]
108
119
edges .append ((length - 1 , 0 ))
109
- graph .add_edges (edges )
110
- return graph
120
+ return Graph (edges = edges , directed = directed )
111
121
112
122
113
- def complete_graph (length , loops = True ):
114
- """
115
- Produces a complete graph of size `length`, with loops.
116
- https://en.wikipedia.org/wiki/Complete_graph
123
+ def complete_graph (size , loops = True ):
124
+ """ Produces a complete graph of specificies size.
125
+
126
+ See https://en.wikipedia.org/wiki/Complete_graph for details.
117
127
118
128
Parameters
119
129
----------
120
- length : int
130
+ size : int
121
131
Number of vertices in the cycle
122
132
directed: bool, False
123
133
Is the graph directed?
134
+
124
135
Returns
125
136
-------
126
- a Graph object
137
+ a Graph object for the complete graph
127
138
"""
128
- graph = Graph (directed = False )
129
- edges = []
130
- for i in range (length ):
131
- for j in range (i + 1 , length ):
132
- edges .append ((i , j ))
133
- graph .add_edges (edges )
139
+ edges = [(i , j ) for i in range (size ) for j in range (i + 1 , size )]
140
+ graph = Graph (edges = edges , directed = False )
134
141
135
142
if loops :
136
143
graph .add_loops ()
0 commit comments