0
# Graph Structure
1
2
Core operations for adding, removing, and modifying vertices and edges, plus basic graph properties and transformations. These fundamental operations enable dynamic graph construction and manipulation.
3
4
## Capabilities
5
6
### Vertex Operations
7
8
Add, remove, and manipulate vertices in the graph with support for attributes and batch operations.
9
10
```python { .api }
11
class Graph:
12
def add_vertex(self, name=None, **attrs):
13
"""
14
Add single vertex to the graph.
15
16
Parameters:
17
- name: str, vertex name (stored as 'name' attribute)
18
- **attrs: keyword arguments for vertex attributes
19
20
Returns:
21
int, index of newly added vertex
22
"""
23
24
def add_vertices(self, n, attrs=None):
25
"""
26
Add multiple vertices to the graph.
27
28
Parameters:
29
- n: int or list, number of vertices or list of names
30
- attrs: dict, attribute dictionaries for new vertices
31
32
Returns:
33
None
34
"""
35
36
def delete_vertices(self, vertices):
37
"""
38
Remove vertices from the graph.
39
40
Parameters:
41
- vertices: int, str, list, or VertexSeq, vertices to remove
42
43
Returns:
44
None
45
46
Note: Adjacent edges are automatically removed
47
"""
48
49
def vcount(self):
50
"""
51
Get number of vertices in graph.
52
53
Returns:
54
int, vertex count
55
"""
56
```
57
58
**Usage Examples:**
59
60
```python
61
import igraph as ig
62
63
# Create empty graph and add vertices
64
g = ig.Graph()
65
66
# Add single vertex
67
v1 = g.add_vertex(name="Alice", age=25, city="NYC")
68
v2 = g.add_vertex(name="Bob", age=30, city="LA")
69
70
# Add multiple vertices
71
g.add_vertices(3, {"name": ["Carol", "Dave", "Eve"]})
72
73
# Add with different attributes per vertex
74
attrs = [
75
{"name": "Frank", "age": 35},
76
{"name": "Grace", "age": 28}
77
]
78
g.add_vertices(2)
79
for i, attr_dict in enumerate(attrs):
80
for key, val in attr_dict.items():
81
g.vs[g.vcount() - 2 + i][key] = val
82
83
print(f"Vertices: {g.vcount()}") # 7
84
85
# Delete vertices
86
g.delete_vertices([0, 2]) # Remove Alice and Carol
87
g.delete_vertices("Dave") # Remove by name (if unique)
88
```
89
90
### Edge Operations
91
92
Add, remove, and manipulate edges between vertices with support for weights and other attributes.
93
94
```python { .api }
95
class Graph:
96
def add_edge(self, source, target, **attrs):
97
"""
98
Add single edge to the graph.
99
100
Parameters:
101
- source: int or str, source vertex ID or name
102
- target: int or str, target vertex ID or name
103
- **attrs: keyword arguments for edge attributes
104
105
Returns:
106
int, index of newly added edge
107
"""
108
109
def add_edges(self, edges, attrs=None):
110
"""
111
Add multiple edges to the graph.
112
113
Parameters:
114
- edges: list of tuples, edge list [(source, target), ...]
115
- attrs: dict or list, edge attributes
116
117
Returns:
118
None
119
"""
120
121
def delete_edges(self, edges):
122
"""
123
Remove edges from the graph.
124
125
Parameters:
126
- edges: int, tuple, list, or EdgeSeq, edges to remove
127
128
Returns:
129
None
130
"""
131
132
def ecount(self):
133
"""
134
Get number of edges in graph.
135
136
Returns:
137
int, edge count
138
"""
139
140
def get_edgelist(self):
141
"""
142
Get list of all edges as (source, target) tuples.
143
144
Returns:
145
list of tuples, edge list
146
"""
147
```
148
149
**Usage Examples:**
150
151
```python
152
# Start with vertices
153
g = ig.Graph()
154
g.add_vertices(4, {"name": ["A", "B", "C", "D"]})
155
156
# Add single edge with attributes
157
g.add_edge("A", "B", weight=1.5, type="friendship")
158
g.add_edge(0, 2, weight=2.0) # By index
159
160
# Add multiple edges
161
edges = [(1, 2), (2, 3), (3, 0)]
162
g.add_edges(edges)
163
164
# Add edges with attributes
165
edge_attrs = {"weight": [1, 2, 3], "type": ["work", "family", "friend"]}
166
g.add_edges([(0, 1), (1, 3), (2, 0)], edge_attrs)
167
168
print(f"Edges: {g.ecount()}") # 6
169
print("Edge list:", g.get_edgelist())
170
171
# Delete edges
172
g.delete_edges([(0, 1)]) # Remove specific edge
173
g.delete_edges([0, 2]) # Remove by edge index
174
```
175
176
### Basic Properties
177
178
Query fundamental graph properties and characteristics.
179
180
```python { .api }
181
class Graph:
182
def is_directed(self):
183
"""
184
Check if graph is directed.
185
186
Returns:
187
bool, True if directed
188
"""
189
190
def is_simple(self):
191
"""
192
Check if graph is simple (no loops or multiple edges).
193
194
Returns:
195
bool, True if simple
196
"""
197
198
def is_connected(self, mode=WEAK):
199
"""
200
Check if graph is connected.
201
202
Parameters:
203
- mode: connectivity type (WEAK, STRONG for directed graphs)
204
205
Returns:
206
bool, True if connected
207
"""
208
209
def has_multiple(self):
210
"""
211
Check if graph has multiple edges.
212
213
Returns:
214
bool, True if multiple edges exist
215
"""
216
217
def is_loop(self, edges=None):
218
"""
219
Check which edges are self-loops.
220
221
Parameters:
222
- edges: list/EdgeSeq, edges to check (None for all)
223
224
Returns:
225
list of bool, True for each loop edge
226
"""
227
228
def density(self, loops=False):
229
"""
230
Calculate graph density.
231
232
Parameters:
233
- loops: bool, whether to consider self-loops
234
235
Returns:
236
float, density (0-1)
237
"""
238
```
239
240
**Usage Examples:**
241
242
```python
243
# Create sample graph
244
g = ig.Graph(edges=[(0,1), (1,2), (2,0)], directed=False)
245
246
# Check properties
247
print(f"Directed: {g.is_directed()}") # False
248
print(f"Simple: {g.is_simple()}") # True
249
print(f"Connected: {g.is_connected()}") # True
250
print(f"Density: {g.density():.3f}") # 1.0 (complete triangle)
251
252
# Add self-loop and multiple edge
253
g.add_edge(0, 0) # Self-loop
254
g.add_edge(0, 1) # Multiple edge
255
256
print(f"Simple: {g.is_simple()}") # False
257
print(f"Has multiple: {g.has_multiple()}") # True
258
print("Loop edges:", g.is_loop()) # [False, False, False, True, False]
259
```
260
261
### Graph Transformations
262
263
Convert between directed and undirected graphs and apply structural transformations.
264
265
```python { .api }
266
class Graph:
267
def as_directed(self, mutual=True):
268
"""
269
Convert to directed graph.
270
271
Parameters:
272
- mutual: bool, create mutual edges for undirected edges
273
274
Returns:
275
Graph, directed version
276
"""
277
278
def as_undirected(self, mode="collapse", combine_edges=None):
279
"""
280
Convert to undirected graph.
281
282
Parameters:
283
- mode: str, how to handle directed edges
284
("collapse", "each", "mutual")
285
- combine_edges: str/dict, how to combine edge attributes
286
("ignore", "sum", "prod", "mean", "min", "max", "first", "last",
287
"random", or dict mapping attributes to functions)
288
289
Returns:
290
Graph, undirected version
291
"""
292
293
def simplify(self, multiple=True, loops=True, combine_edges=None):
294
"""
295
Remove multiple edges and/or loops.
296
297
Parameters:
298
- multiple: bool, remove multiple edges
299
- loops: bool, remove self-loops
300
- combine_edges: str/dict, how to combine attributes of multiple edges
301
302
Returns:
303
Graph, simplified version
304
"""
305
306
def copy(self):
307
"""
308
Create deep copy of the graph.
309
310
Returns:
311
Graph, independent copy
312
"""
313
```
314
315
**Usage Examples:**
316
317
```python
318
# Undirected graph with multiple edges
319
g = ig.Graph([(0,1), (1,2), (2,0), (0,1), (1,1)], directed=False)
320
321
# Convert to directed
322
g_dir = g.as_directed(mutual=True)
323
print(f"Directed edges: {g_dir.ecount()}") # 8 (each undirected becomes 2 directed)
324
325
# Back to undirected with edge combining
326
g_undir = g_dir.as_undirected(mode="collapse",
327
combine_edges={"weight": "sum"})
328
329
# Simplify graph
330
g_simple = g.simplify(multiple=True, loops=True)
331
print(f"Simplified edges: {g_simple.ecount()}") # 3 (removed duplicates and loop)
332
333
# Copy for safe manipulation
334
g_copy = g.copy()
335
g_copy.delete_vertices([0]) # Original g unchanged
336
```
337
338
### Subgraphs and Induced Subgraphs
339
340
Extract portions of graphs based on vertex or edge selections.
341
342
```python { .api }
343
class Graph:
344
def subgraph(self, vertices, implementation="auto"):
345
"""
346
Create induced subgraph from vertex subset.
347
348
Parameters:
349
- vertices: list/VertexSeq, vertices to include in subgraph
350
- implementation: str, algorithm choice ("auto", "copy_and_delete", "create_from_scratch")
351
352
Returns:
353
Graph, induced subgraph
354
"""
355
356
def subgraph_edges(self, edges, delete_vertices=True):
357
"""
358
Create subgraph from edge subset.
359
360
Parameters:
361
- edges: list/EdgeSeq, edges to include
362
- delete_vertices: bool, remove isolated vertices
363
364
Returns:
365
Graph, edge-induced subgraph
366
"""
367
368
def induced_subgraph(self, vertices, implementation="auto"):
369
"""
370
Alias for subgraph() method.
371
372
Parameters:
373
- vertices: vertex selection
374
- implementation: algorithm choice
375
376
Returns:
377
Graph, induced subgraph
378
"""
379
```
380
381
**Usage Examples:**
382
383
```python
384
# Create larger graph
385
g = ig.Graph.Ring(10) # 10-vertex cycle
386
g.vs["name"] = [f"v{i}" for i in range(10)]
387
388
# Induced subgraph from vertices
389
subverts = [0, 1, 2, 5, 6]
390
sg1 = g.subgraph(subverts)
391
print(f"Subgraph vertices: {sg1.vcount()}") # 5
392
print(f"Subgraph edges: {sg1.ecount()}") # 2 (only edges within subset)
393
394
# Subgraph from edges
395
subedges = [0, 1, 4, 5, 8] # Select specific edges
396
sg2 = g.subgraph_edges(subedges)
397
398
# Use vertex selection with names
399
sg3 = g.subgraph(["v0", "v1", "v9"]) # vertices 0, 1, 9
400
```
401
402
### Degree Operations
403
404
Query and analyze vertex degrees and degree-related properties.
405
406
```python { .api }
407
class Graph:
408
def degree(self, vertices=None, mode=ALL, loops=True):
409
"""
410
Get vertex degrees.
411
412
Parameters:
413
- vertices: list/VertexSeq, vertices to query (None for all)
414
- mode: degree type (ALL, IN, OUT for directed graphs)
415
- loops: bool, count self-loops
416
417
Returns:
418
list of int, vertex degrees
419
"""
420
421
def strength(self, vertices=None, mode=ALL, loops=True, weights=None):
422
"""
423
Get vertex strengths (weighted degrees).
424
425
Parameters:
426
- vertices: vertex selection (None for all)
427
- mode: degree type (ALL, IN, OUT)
428
- loops: bool, count self-loops
429
- weights: str/list, edge weights or attribute name
430
431
Returns:
432
list of float, vertex strengths
433
"""
434
435
def maxdegree(self, vertices=None, mode=ALL, loops=True):
436
"""
437
Get maximum degree in graph.
438
439
Parameters:
440
- vertices: vertex selection for max calculation
441
- mode: degree type (ALL, IN, OUT)
442
- loops: bool, count self-loops
443
444
Returns:
445
int, maximum degree
446
"""
447
448
def degree_sequence(self, mode=ALL):
449
"""
450
Get sorted degree sequence.
451
452
Parameters:
453
- mode: degree type (ALL, IN, OUT)
454
455
Returns:
456
list of int, degrees in descending order
457
"""
458
```
459
460
**Usage Examples:**
461
462
```python
463
# Create weighted graph
464
g = ig.Graph([(0,1), (1,2), (2,0), (1,3)], directed=False)
465
g.es["weight"] = [1, 2, 3, 4]
466
467
# Get degrees
468
degrees = g.degree()
469
print("Degrees:", degrees) # [2, 3, 2, 1]
470
471
# Get strengths (weighted degrees)
472
strengths = g.strength(weights="weight")
473
print("Strengths:", strengths) # [4, 7, 5, 4]
474
475
# Maximum degree
476
max_deg = g.maxdegree()
477
print("Max degree:", max_deg) # 3
478
479
# Degree sequence
480
deg_seq = g.degree_sequence()
481
print("Degree sequence:", deg_seq) # [3, 2, 2, 1]
482
483
# For directed graphs
484
g_dir = g.as_directed()
485
in_degrees = g_dir.degree(mode=ig.IN)
486
out_degrees = g_dir.degree(mode=ig.OUT)
487
```