Graph Theory Package For Giac/Xcas Graphtheory User Manual

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 136

DownloadGraph Theory Package For Giac/Xcas Graphtheory-user Manual
Open PDF In BrowserView PDF
Graph theory
package for
Giac/Xcas
Reference manual

September 2018

Table of contents
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1. Constructing graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.1. General graphs . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1.1. Undirected graphs . . . . . . . . . . . . . . . . . . . . .
1.1.2. Directed graphs . . . . . . . . . . . . . . . . . . . . . .
1.1.3. Examples . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating vertices . . . . . . . . . . . . . . . . . . .
Creating edges and arcs . . . . . . . . . . . . . . .
Creating paths and trails . . . . . . . . . . . . . .
Specifying adjacency or weight matrix . . . . .
Creating special graphs . . . . . . . . . . . . . . .
1.2. Cycle and path graphs . . . . . . . . . . . . . . . . . . . . .
1.2.1. Cycle graphs . . . . . . . . . . . . . . . . . . . . . . . .
1.2.2. Path graphs . . . . . . . . . . . . . . . . . . . . . . . . .
1.2.3. Trails of edges . . . . . . . . . . . . . . . . . . . . . . .
1.3. Complete graphs . . . . . . . . . . . . . . . . . . . . . . . . .
1.3.1. Complete graphs (with multiple vertex partitions)
1.3.2. Complete trees . . . . . . . . . . . . . . . . . . . . . . .
1.4. Sequence graphs . . . . . . . . . . . . . . . . . . . . . . . . .
1.4.1. Creating graphs from degree sequences . . . . . . .
1.4.2. Validating graphic sequences . . . . . . . . . . . . . .
1.5. Intersection graphs . . . . . . . . . . . . . . . . . . . . . . .
1.5.1. Interval graphs . . . . . . . . . . . . . . . . . . . . . . .
1.5.2. Kneser graphs . . . . . . . . . . . . . . . . . . . . . . .
1.6. Special graphs . . . . . . . . . . . . . . . . . . . . . . . . . .
1.6.1. Hypercube graphs . . . . . . . . . . . . . . . . . . . . .
1.6.2. Star graphs . . . . . . . . . . . . . . . . . . . . . . . . .
1.6.3. Wheel graphs . . . . . . . . . . . . . . . . . . . . . . . .
1.6.4. Web graphs . . . . . . . . . . . . . . . . . . . . . . . . .
1.6.5. Prism graphs . . . . . . . . . . . . . . . . . . . . . . . .
1.6.6. Antiprism graphs . . . . . . . . . . . . . . . . . . . . .
1.6.7. Grid graphs . . . . . . . . . . . . . . . . . . . . . . . . .
1.6.8. Sierpi«ski graphs . . . . . . . . . . . . . . . . . . . . .
1.6.9. Generalized Petersen graphs . . . . . . . . . . . . . .
1.6.10. LCF graphs . . . . . . . . . . . . . . . . . . . . . . . .
1.7. Isomorphic copies of graphs . . . . . . . . . . . . . . . . . .
1.7.1. Creating an isomorphic copy from a permutation .
1.7.2. Permuting vertices . . . . . . . . . . . . . . . . . . . .
1.7.3. Relabeling vertices . . . . . . . . . . . . . . . . . . . .
1.8. Subgraphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.8.1. Extracting subgraphs . . . . . . . . . . . . . . . . . . .
1.8.2. Induced subgraphs . . . . . . . . . . . . . . . . . . . .
1.8.3. Underlying graphs . . . . . . . . . . . . . . . . . . . .
1.8.4. Fundamental cycles . . . . . . . . . . . . . . . . . . . .
1.9. Operations on graphs . . . . . . . . . . . . . . . . . . . . . .
1.9.1. Graph complement . . . . . . . . . . . . . . . . . . . .
1.9.2. Seidel switching . . . . . . . . . . . . . . . . . . . . . .
1.9.3. Transposing graphs . . . . . . . . . . . . . . . . . . . .
3

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. . 9
. . 9
. 10
. 10
. 10
. 10
. 11
. 11
. 12
. 13
. 13
. 13
. 13
. 14
. 14
. 15
. 15
. 15
. 16
. 16
. 16
. 16
. 17
. 17
. 18
. 18
. 18
. 19
. 19
. 19
. 21
. 22
. 22
. 23
. 23
. 24
. 25
. 25
. 25
. 25
. 26
. 26
. 28
. 28
. 29
. 29

4

Table of contents

1.9.4. Union of graphs . . . . . . . . . . . . . . . . . . . . .
1.9.5. Disjoint union of graphs . . . . . . . . . . . . . . . .
1.9.6. Joining two graphs . . . . . . . . . . . . . . . . . . .
1.9.7. Power graphs . . . . . . . . . . . . . . . . . . . . . . .
1.9.8. Graph products . . . . . . . . . . . . . . . . . . . . .
1.9.9. Transitive closure graph . . . . . . . . . . . . . . . .
1.9.10. Line graph . . . . . . . . . . . . . . . . . . . . . . . .
1.9.11. Plane dual graph . . . . . . . . . . . . . . . . . . . .
1.10. Random graphs . . . . . . . . . . . . . . . . . . . . . . . .
1.10.1. Random general graphs . . . . . . . . . . . . . . .
1.10.2. Random bipartite graphs . . . . . . . . . . . . . .
1.10.3. Random trees . . . . . . . . . . . . . . . . . . . . . .
1.10.4. Random planar graphs . . . . . . . . . . . . . . . .
1.10.5. Random graphs from the given degree sequence
1.10.6. Random regular graphs . . . . . . . . . . . . . . .
1.10.7. Random tournaments . . . . . . . . . . . . . . . . .
1.10.8. Random network graphs . . . . . . . . . . . . . . .
1.10.9. Randomizing edge weights . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

30
30
30
31
32
33
34
34
36
36
37
37
40
41
42
43
43
44

2. Modifying graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

2.1. Promoting to directed and weighted graphs . . . . .
2.1.1. Converting edges to arcs . . . . . . . . . . . . .
2.1.2. Assigning weight matrix to unweighted graphs
2.2. Modifying vertices of a graph . . . . . . . . . . . . . .
2.2.1. Adding and removing vertices . . . . . . . . . .
2.3. Modifying edges of a graph . . . . . . . . . . . . . . .
2.3.1. Adding and removing edges . . . . . . . . . . .
2.3.2. Accessing and modifying edge weights . . . . .
2.3.3. Contracting edges . . . . . . . . . . . . . . . . . .
2.3.4. Subdividing edges . . . . . . . . . . . . . . . . . .
2.4. Using attributes . . . . . . . . . . . . . . . . . . . . . .
2.4.1. Graph attributes . . . . . . . . . . . . . . . . . .
2.4.2. Vertex attributes . . . . . . . . . . . . . . . . . .
2.4.3. Edge attributes . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

47
47
47
47
47
48
48
49
50
50
51
51
52
53

. .. .. ... .. .. .. .. .. .. .. ... .. .. .. .. .. .. ...

55

3. Import and export

3.1. Importing graphs . . . . . . . . . . . . . . . . .
3.1.1. Loading graphs from dot les . . . . . . .
3.1.2. The dot le format overview . . . . . . .
3.2. Exporting graphs . . . . . . . . . . . . . . . . .
3.2.1. Saving graphs in dot format . . . . . . .
3.2.2. Saving graph drawings in LATEX format
4. Graph properties

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

59

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.. .. .. ... .. .. .. .. .. .. .. ... .. .. .. .. .. .. ...
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

55
55
55
56
56
56

..
.
..
..
..
..
..
..
..
..
..

.
.
.
.
.
.

. ..
. ..
..
. ..
. ..
. ..
. ..
. ..
. ..
. ..
. ..
. ..
. ..
. ..

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

4.1. Basic properties . . . . . . . . . . . . .
4.1.1. Determining the type of a graph
4.1.2. Listing vertices and edges . . . .
4.1.3. Equality of graphs . . . . . . . .
4.1.4. Vertex degrees . . . . . . . . . . .
4.1.5. Regular graphs . . . . . . . . . . .
4.1.6. Strongly regular graphs . . . . .
4.1.7. Vertex adjacency . . . . . . . . .
4.1.8. Tournament graphs . . . . . . . .
4.1.9. Bipartite graphs . . . . . . . . . .
4.1.10. Edge incidence . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

59
59
59
60
61
62
63
63
65
65
66

Table of contents

4.2. Algebraic properties . . . . . . . . . . . . . . . . . . . . . .
4.2.1. Adjacency matrix . . . . . . . . . . . . . . . . . . . .
4.2.2. Laplacian matrix . . . . . . . . . . . . . . . . . . . .
4.2.3. Incidence matrix . . . . . . . . . . . . . . . . . . . . .
4.2.4. Weight matrix . . . . . . . . . . . . . . . . . . . . . .
4.2.5. Characteristic polynomial . . . . . . . . . . . . . . .
4.2.6. Graph spectrum . . . . . . . . . . . . . . . . . . . . .
4.2.7. Seidel spectrum . . . . . . . . . . . . . . . . . . . . .
4.2.8. Integer graphs . . . . . . . . . . . . . . . . . . . . . .
4.3. Graph isomorphism . . . . . . . . . . . . . . . . . . . . . .
4.3.1. Isomorphic graphs . . . . . . . . . . . . . . . . . . . .
4.3.2. Canonical labeling . . . . . . . . . . . . . . . . . . .
4.3.3. Graph automorphisms . . . . . . . . . . . . . . . . .
4.4. Graph polynomials . . . . . . . . . . . . . . . . . . . . . .
4.4.1. Tutte polynomial . . . . . . . . . . . . . . . . . . . .
4.4.2. Chromatic polynomial . . . . . . . . . . . . . . . . .
4.4.3. Flow polynomial . . . . . . . . . . . . . . . . . . . . .
4.4.4. Reliability polynomial . . . . . . . . . . . . . . . . .
4.5. Connectivity . . . . . . . . . . . . . . . . . . . . . . . . . .
4.5.1. Connected, biconnected and triconnected graphs
4.5.2. Connected and biconnected components . . . . .
4.5.3. Vertex connectivity . . . . . . . . . . . . . . . . . . .
4.5.4. Graph rank . . . . . . . . . . . . . . . . . . . . . . . .
4.5.5. Articulation points . . . . . . . . . . . . . . . . . . .
4.5.6. Strongly connected components . . . . . . . . . . .
4.5.7. Edge connectivity . . . . . . . . . . . . . . . . . . . .
4.5.8. Edge cuts . . . . . . . . . . . . . . . . . . . . . . . . .
4.5.9. Two-edge-connected graphs . . . . . . . . . . . . . .
4.6. Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.6.1. Tree graphs . . . . . . . . . . . . . . . . . . . . . . . .
4.6.2. Forest graphs . . . . . . . . . . . . . . . . . . . . . . .
4.6.3. Height of a tree . . . . . . . . . . . . . . . . . . . . .
4.6.4. Lowest common ancestor of a pair of nodes . . .
4.6.5. Arborescence graphs . . . . . . . . . . . . . . . . . .
4.7. Networks . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.7.1. Network graphs . . . . . . . . . . . . . . . . . . . . .
4.7.2. Maximum ow . . . . . . . . . . . . . . . . . . . . . .
4.7.3. Minimum cut . . . . . . . . . . . . . . . . . . . . . . .
4.8. Distance in graphs . . . . . . . . . . . . . . . . . . . . . . .
4.8.1. Vertex distance . . . . . . . . . . . . . . . . . . . . .
4.8.2. All-pairs vertex distance . . . . . . . . . . . . . . . .
4.8.3. Diameter . . . . . . . . . . . . . . . . . . . . . . . . .
4.8.4. Girth . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.9. Acyclic graphs . . . . . . . . . . . . . . . . . . . . . . . . .
4.9.1. Acyclic graphs . . . . . . . . . . . . . . . . . . . . . .
4.9.2. Topological sorting . . . . . . . . . . . . . . . . . . .
4.9.3. st ordering . . . . . . . . . . . . . . . . . . . . . . . .
4.10. Matching in graphs . . . . . . . . . . . . . . . . . . . . .
4.10.1. Maximum matching . . . . . . . . . . . . . . . . . .
4.10.2. Maximum matching in bipartite graphs . . . . .
4.11. Cliques . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.11.1. Clique graphs . . . . . . . . . . . . . . . . . . . . . .
4.11.2. Maximal cliques . . . . . . . . . . . . . . . . . . . .
4.11.3. Maximum clique . . . . . . . . . . . . . . . . . . . .
4.11.4. Minimum clique cover . . . . . . . . . . . . . . . .
4.11.5. Clique cover number . . . . . . . . . . . . . . . . .

5

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. 67
. 67
. 68
. 69
. 70
. 70
. 71
. 71
. 72
. 72
. 72
. 75
. 75
. 76
. 76
. 78
. 78
. 79
. 81
. 81
. 82
. 83
. 83
. 84
. 84
. 85
. 85
. 86
. 87
. 87
. 87
. 88
. 88
. 89
. 89
. 89
. 90
. 92
. 93
. 93
. 93
. 94
. 95
. 95
. 95
. 96
. 96
. 97
. 97
. 98
. 99
. 99
. 99
. 100
. 101
. 101

6

Table of contents

4.12. Clustering and transitivity in networks
4.12.1. Counting triangles in graphs . . .
4.12.2. Clustering coecient . . . . . . . .
4.12.3. Network transitivity . . . . . . . . .
4.13. Vertex coloring . . . . . . . . . . . . . . .
4.13.1. Greedy vertex coloring . . . . . . .
4.13.2. Minimal vertex coloring . . . . . .
4.13.3. Chromatic number . . . . . . . . .
4.13.4. Mycielski graphs . . . . . . . . . . .
4.13.5. k-coloring . . . . . . . . . . . . . . .
4.14. Edge coloring . . . . . . . . . . . . . . . .
4.14.1. Minimal edge coloring . . . . . . .
4.14.2. Chromatic index . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

102
102
103
104
105
105
106
107
107
108
109
109
110

5. Traversing graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.1. Walks and tours . . . . . . . . . . . . .
5.1.1. Eulerian graphs . . . . . . . . . .
5.1.2. Hamiltonian graphs . . . . . . . .
5.2. Optimal routing . . . . . . . . . . . . .
5.2.1. Shortest unweighted paths . . .
5.2.2. Cheapest weighted paths . . . .
5.2.3. Traveling salesman problem . .
5.3. Spanning trees . . . . . . . . . . . . . .
5.3.1. Construction of spanning trees .
5.3.2. Minimal spanning tree . . . . . .
5.3.3. Counting the spanning trees in a

.. .. .
.. .. .
.. .. .
.. .. .
.. .. .
.. .. .
.. .. .
.. .. .
.. .. .
.. .. .
graph

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

113
113
113
114
114
115
116
118
118
119
119

6. Visualizing graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.1. Drawing graphs . . . . . . . . . . . .
6.1.1. Overview . . . . . . . . . . . .
6.1.2. Drawing disconnected graphs
6.1.3. Spring method . . . . . . . . .
6.1.4. Drawing trees . . . . . . . . .
6.1.5. Drawing planar graphs . . . .
6.1.6. Circular graph drawings . . .
6.2. Vertex positions . . . . . . . . . . .
6.2.1. Setting vertex positions . . .
6.2.2. Generating vertex positions .
6.3. Highlighting parts of graphs . . . .
6.3.1. Highlighting vertices . . . . .
6.3.2. Highlighting edges and trails
6.3.3. Highlighting subgraphs . . .

.. .
.. .
. .
.. .
.. .
.. .
.. .
.. .
.. .
.. .
.. .
.. .
.. .
.. .

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

121
121
121
122
124
125
127
127
127
128
129
129
129
130

Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Command Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

Introduction
This document1 contains an overview of the library of graph theory commands built in Giac
computation kernel and fully supported within Xcas GUI. The library provides an eective and
free replacement for the Graph Theory package in Maple with a high level of syntax compatibility
(although there are some minor dierences).
For each command, the calling syntax is presented along with the detailed description of its
functionality. Several examples are also supplied to illustrate the usage.
In calling syntax, the square brackets [ and ] are used for specifying that an argument should be
a list of particular elements, as well as to indicate that an argument is optional. The character |
stands for or .
The algorithms in this library are implemented according to the relevant scientic publications.
Although the development focus was on simplicity, the algorithms are reasonably fast. Naive implementations (just for the sake of having particular commands available) were avoided. To enable
some dicult tasks, such as traveling salesman problem, graph colorings and graph isomorphism
problem, freely available third party libraries are used, in particular GNU Linear Programming Kit
(GLPK) for solving linear programming problems and nauty for graph isomorphism. These libraries,
included in Giac/Xcas by default, are optional during the compilation. The majority of commands
has no dependencies save Giac itself.
This library was developed and documented by Luka Marohni¢ (luka.marohnic@tvz.hr). Special thanks go to Bernard parisse, the Giac/Xcas project leader, and Jose Capco for their
interest, comments, suggestions and support.
1. This manual was written in GNU TEXMACS , a scientic document editing platform. All the examples were entered
as interactive Giac sessions.

7

Chapter 1
Constructing graphs
1.1. General graphs
The commands graph and digraph are used for constructing general graphs.

1.1.1. Undirected graphs
Syntax: graph(n|V,[opts])
graph(V,E,[opts])
graph(E,[opts])
graph(V,T,[opts])
graph(T,[opts])
graph(V,T1,T2,T3,..,Tk,[opts])
graph(T1,T2,T3,..,Tk,[opts])
graph(A,[opts])
graph(V,E,A,[opts])
graph(V,Perm,[opts])
graph(Str)
The command graph accepts between one and three main arguments, each of them being one of
the following structural elements of the resulting graph:
¡

number n or list of vertices V (a vertex may be any atomic object, such as an integer, a
symbol or a string); it must be the rst argument if used,

¡

set of edges E (each edge is a list containing two vertices), a permutation, a trail of edges
or a sequence of trails; it can be either the rst or the second argument if used,

¡

trail T or sequence of trails T1; T2; :::; Tk,

¡

permutation Perm of vertices,

¡

adjacency or weight matrix A,

¡

string Str, representing a special graph.

Optionally, the following options may be appended to the sequence of arguments:
¡

directed = true or false,

¡

weighted = true or false,

¡

color = an integer or a list of integers representing color(s) of the vertices,

¡

coordinates = a list of vertex 2D or 3D coordinates.

The graph command may also be called by passing a string Str, representing the name of a special
graph, as its only argument. In that case the corresponding graph will be constructed and returned.
The supported graphs and their names are listed below.
1. 2nd Blanu²a snark: blanusa

3. Coxeter graph: coxeter

2. Clebsch graph: clebsch

4. Desargues graph: desargues
9

10

Constructing graphs

5. Dodecahedral graph: dodecahedron

16. Ljubljana graph: ljubljana

6. Dürer graph: durer

17. McGee graph: mcgee

7. Dyck graph: dyck

18. MöbiusKantor graph: mobius-kantor

8. Grinberg graph: grinberg

19. Nauru graph: nauru

9. Grötzsch graph: grotzsch

20. Octahedral graph: octahedron

10. Harries graph: harries

21. Pappus graph: pappus

11. HarriesWong graph: harries-wong

22. Petersen graph: petersen

12. Heawood graph: heawood

23. Robertson graph: robertson

13. Herschel graph: herschel

24. Trunc. icosahedral graph: soccerball

14. Icosahedral graph: icosahedron

25. Shrikhande graph: shrikhande

15. Levi graph: levi

26. Tetrahedral graph: tehtrahedron

1.1.2. Directed graphs
The digraph command is used for creating directed graphs, although it is also possible with the
graph command by specifying the option directed=true. Actually, calling digraph is the same as
calling graph with that option appended to the sequence of arguments. However, creating special
graphs is not supported by digraph since they are all undirected.
Edges in directed graphs are called arcs.

1.1.3. Examples
Creating vertices. A graph consisting only of vertices and no edges can be created simply by
providing the number of vertices or the list of vertex labels.
> graph(5)
an undirected unweighted graph with 5 vertices and 0 edges
> graph([a,b,c])
an undirected unweighted graph with 3 vertices and 0 edges
The commands that return graphs often need to generate vertex labels. In these cases ordinal
integers are used, which are 0-based in Xcas mode and 1-based in Maple mode. Examples throughout
this manual are made by using the default mode (Xcas).
Creating edges and arcs. Edges/arcs must be specied inside a set so that it can be distinguished from a (adjacency or weight) matrix. If only a set of edges/arcs is specied, the vertices
needed to establish these will be created automatically. Note that, when constructing a directed
graph, the order of the vertices in an arc matters; in undirected graphs it is not meaningful.
> graph(%{[a,b],[b,c],[a,c]%})
an undirected unweighted graph with 3 vertices and 3 edges
Edge weights may also be specied.
> graph(%{[[a,b],2],[[b,c],2.3],[[c,a],3/2]%})
an undirected weighted graph with 3 vertices and 3 edges

1.1 General graphs

11

If the graph contains isolated vertices (not connected to any other vertex) or a particular order of
vertices is desired, the list of vertices has to be specied rst.
> graph([d,b,c,a],%{[a,b],[b,c],[a,c]%})
an undirected unweighted graph with 4 vertices and 3 edges
Creating paths and trails. A directed graph can also be created from a list of n vertices and
a permutation of order n. The resulting graph consists of a single directed cycle with the vertices
ordered according to the permutation.
> G:=graph([a,b,c,d],[1,2,3,0])
a directed unweighted graph with 4 vertices and 4 arcs
> draw_graph(G)
a

c

b

d

Alternatively, one may specify edges as a trail.
> digraph([a,b,c,d],trail(b,c,d,a))
a directed unweighted graph with 4 vertices and 3 arcs
Using trails is also possible when creating undirected graphs. Also, some vertices in a trail may be
repeated, which is not allowed in a path.
> G:=graph([a,b,c,d],trail(b,c,d,a,c))
an undirected unweighted graph with 4 vertices and 4 edges
> edges(G)
0
B
B
@

a
a
b
c

c
d
c
d

1
C
C
A

It is possible to specify several trails in a sequence, which is useful when designing more complex
graphs.
> G:=graph(trail(1,2,3,4,2),trail(3,5,6,7,5,4))
an undirected unweighted graph with 7 vertices and 9 edges
> draw_graph(G)
1
7

2

6

3

5

4

Specifying adjacency or weight matrix. A graph can be created from a single square matrix
A = [aij ]n of order n. If it contains only ones and zeros and has zeros on its diagonal, it is assumed
to be the adjacency matrix for the desired graph. Otherwise, if an element outside the set f0; 1g is
encountered, it is assumed that the matrix of edge weights is passed as input, causing the resulting
graph to be weighted accordingly. In each case, exactly n vertices will be created and i-th and
j-th vertex will be connected i aij =
/ 0. If the matrix is symmetric, the resulting graph will be
undirected, otherwise it will be directed.

12

Constructing graphs

> G:=graph([[0,1,1,0],[1,0,0,1],[1,0,0,0],[0,1,0,0]])
an undirected unweighted graph with 4 vertices and 3 edges
> edges(G)
0

1
0 1
@ 0 2 A
1 3

> G:=graph([[0,1.0,2.3,0],[4,0,0,3.1],[0,0,0,0],[0,0,0,0]])
a directed weighted graph with 4 vertices and 4 arcs
> edges(G,weights)
f[[0; 1]; 1.0]; [[0; 2]; 2.3]; [[1; 0]; 4]; [[1; 3]; 3.1]g
List of vertex labels can be specied alongside a matrix.
> graph([a,b,c,d],[[0,1,1,0],[1,0,0,1],[1,0,0,0],[0,1,0,0]])
an undirected unweighted graph with 4 vertices and 3 edges
When creating a weighted graph, one can rst specify the list of n vertices and the set of edges,
followed by a square matrix A of order n. Then for every edge fi; j g or arc (i; j) the element aij
of A is assigned as its weight. Other elements of A are ignored.
> G:=digraph([a,b,c],%{[a,b],[b,c],[a,c]%},[[0,1,2],[3,0,4],[5,6,0]])
a directed weighted graph with 3 vertices and 3 arcs
> edges(G,weights)
f[[a; b]; 1]; [[a; c]; 2]; [[b; c]; 4]g
Creating special graphs. When a special graph is desired, one just needs to pass its name to
the graph command. An undirected unweighted graph will be returned.
> graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> G:=graph("coxeter")
an undirected unweighted graph with 28 vertices and 42 edges
> draw_graph(G)
a1
z1

a7

a2
z7

z2
b1
c1
b7
c7

b2
c2

b6c6

c3b3

z6

z3

a6
c5
b5

z5

a5

c4
b4

z4

a4

a3

1.2 Cycle and path graphs

13

1.2. Cycle and path graphs
1.2.1. Cycle graphs
The command cycle_graph is used for constructing cycle graphs [23, pp. 4].
Syntax: cycle_graph(n)
cycle_graph(V)
cycle_graph accepts a positive integer n or a list of distinct vertices V as its only argument and
returns the graph consisting of a single cycle on the specied vertices in the given order. If n is
specied it is assumed to be the desired number of vertices, in which case they will be created and
labeled with the rst n integers (starting from 0 in Xcas mode and from 1 in Maple mode). The
resulting graph will be given the name Cn, for example C4 for n = 4.
> C5:=cycle_graph(5)
C5: an undirected unweighted graph with 5 vertices and 5 edges
> draw_graph(C5)
0

4

1

3

2

> cycle_graph(["a","b","c","d","e"])
C5: an undirected unweighted graph with 5 vertices and 5 edges

1.2.2. Path graphs
The command path_graph is used for constructing path graphs [23, pp. 4].
Syntax: path_graph(n)
path_graph(V)
path_graph accepts a positive integer n or a list of distinct vertices V as its only argument and
returns a graph consisting of a single path on the specied vertices in the given order. If n is
specied it is assumed to be the desired number of vertices, in which case they will be created and
labeled with the rst n integers (starting from 0 in Xcas mode resp. from 1 in Maple mode).
Note that a path cannot intersect itself. Paths that are allowed to cross themselves are called trails
(see the command trail).
> path_graph(5)
an undirected unweighted graph with 5 vertices and 4 edges
> path_graph(["a","b","c","d","e"])
an undirected unweighted graph with 5 vertices and 4 edges

1.2.3. Trails of edges
Syntax: trail(v1,v2,..,vk)
trail2edges(T)

14

Constructing graphs

If the dummy command trail is called with a sequence of vertices v1; v2; :::; vk as arguments, it
returns the symbolic expression representing the trail which visits the specied vertices in the given
order. The resulting symbolic object is recognizable by some commands, for example graph and
digraph. Note that a trail may cross itself (some vertices may be repeated in the given sequence).
Any trail T is easily converted to the corresponding list of edges by calling the trail2edges
command, which accepts the trail as its only argument.
> T:=trail(1,2,3,4,2):; graph(T)
Done; an undirected unweighted graph with 4 vertices and 4 edges
> trail2edges(T)
0

1
B 2
B
@ 3
4

1
2
3 C
C
4 A
2

1.3. Complete graphs
1.3.1. Complete graphs (with multiple vertex partitions)
The command complete_graph is used for construction of complete (multipartite) graphs.
Syntax: complete_graph(n)
complete_graph(V)
complete_graph(n1,n2,..,nk)
complete_graph can be called with a single argument, a positive integer n or a list of distinct
vertices V , in which case it returns the complete graph [23, pp. 2] on the specied vertices. If integer
n is specied, it is assumed that it is the desired number of vertices and they will be created and
labeled with the rst n integers (starting from 0 in Xcas mode and from 1 in Maple mode).
If complete_graph is given a sequence of positive integers n1; n2; :::; nk as its argument, it returns
a complete multipartite graph with partitions of size n1; n2; :::; nk.
> K5:=complete_graph(5)
an undirected unweighted graph with 5 vertices and 10 edges
> draw_graph(K5)
0

4

1

3

2

> K3:=complete_graph([a,b,c])
an undirected unweighted graph with 3 vertices and 3 edges
> edges(K3)
f[a; b]; [a; c]; [b; c]g
> K33:=complete_graph(3,3)
an undirected unweighted graph with 6 vertices and 9 edges

1.4 Sequence graphs

15

> draw_graph(K33)
0

1

3

2

4

5

1.3.2. Complete trees
The commands complete_binary_tree and complete_kary_tree are used for construction of
complete binary trees and complete k-ary trees, respectively.
Syntax: complete_binary_tree(n)
complete_kary_tree(k,n)
complete_binary_tree accepts a positive integer n as its only argument and returns a complete
binary tree of depth n.
complete_kary_tree accepts positive integers k and n as its arguments and returns the complete
k-ary tree of depth n.
> T1:=complete_binary_tree(2)
an undirected unweighted graph with 7 vertices and 6 edges
> draw_graph(T1)
0

1

3

2

4 5

6

> T2:=complete_kary_tree(3,2)
an undirected unweighted graph with 13 vertices and 12 edges
> draw_graph(T2)
0

1

4

5

2

6 7

8

3

910 11

12

1.4. Sequence graphs
1.4.1. Creating graphs from degree sequences
The command sequence_graph is used for constructing graphs from degree sequences.
Syntax: sequence_graph(L)
sequence_graph accepts a list L of positive integers as its only argument and, if L represents a
graphic sequence, the corresponding graph G with jLj vertices is returned. If the argument is not
a graphic sequence, an error is returned.
> sequence_graph([3,2,4,2,3,4,5,7])
an undirected unweighted graph with 8 vertices and 15 edges

16

Constructing graphs

Sequence graphs are constructed in O(jLj2 log jLj) time by applying the algorithm of Havel and
Hakimi [27].

1.4.2. Validating graphic sequences
The command is_graphic_sequence is used to check whether a list of integers represents the
degree sequence of some graph.
Syntax: is_graphic_sequence(L)
is_graphic_sequence accepts a list L of positive integers as its only argument and returns true if
there exists a graph G(V ; E) with degree sequence fdeg v: v 2 V g equal to L and false otherwise.
The algorithm, which has the complexity O(jLj2), is based on the theorem of Erd®s and Gallai.
> is_graphic_sequence([3,2,4,2,3,4,5,7])
true

1.5. Intersection graphs
1.5.1. Interval graphs
The command interval_graph is used for construction of interval graphs.
Syntax: interval_graph(L)
interval_graph accepts a sequence or list L of real-line intervals as its argument and returns
an undirected unweighted graph with these intervals as vertices (the string representations of the
intervals are used as labels), each two of them being connected with an edge if and only if the
corresponding intervals intersect.
> G:=interval_graph(0..8,1..pi,exp(1)..20,7..18,11..14,17..24,23..25)
an undirected unweighted graph with 7 vertices and 10 edges
> draw_graph(G)

1.5.2. Kneser graphs
The commands kneser_graph and odd_graph are used for construction of Kneser graphs.
Syntax: kneser_graph(n,k)
odd_graph(d)
kneser_graph accepts two positive integers n  20 and k as its arguments and returns the Kneser
graph K(n; k). The latter is obtained by setting all k-subsets of a set of n elements as vertices
and connecting each two of them if and only if the corresponding sets are disjoint. Therefore, each
Kneser graph is the complement of the corresponding intersection graph on the same collection of
subsets.
Kneser graphs can get exceedingly complex even
for relatively small values of n and k. Note that
 
the number of vertices in K(n; k) is equal to nk .

1.6 Special graphs

17

> kneser_graph(5,2)
an undirected unweighted graph with 10 vertices and 15 edges
> G:=kneser_graph(8,1)
an undirected unweighted graph with 8 vertices and 28 edges
> is_clique(G)
true
> draw_graph(G,spring,labels=false)

The command odd_graph is used for creating odd graphs, i.e. Kneser graphs with parameters
n = 2 d + 1 and k = d for d > 1.
odd_graph accepts a positive integer d  8 as its only argument and returns d-th odd graph
K(2 d + 1; d). Note that the odd graphs with d > 8 will not be constructed as they are too big to
handle.
> odd_graph(3)
an undirected unweighted graph with 10 vertices and 15 edges

1.6. Special graphs
1.6.1. Hypercube graphs
The command hypercube_graph is used for construction of hypercube graphs.
Syntax: hypercube_graph(n)
hypercube_graph accepts a positive integer n as its only argument and returns the hypercube
graph of dimension n on 2n vertices. The vertex labels are strings of binary digits of length n.
Two vertices are joined by an edge if and only if their labels dier in exactly one character. The
hypercube graph for n = 2 is a square and for n = 3 it is a cube.
> H:=hypercube_graph(3)
an undirected unweighted graph with 8 vertices and 12 edges
> draw_graph(H,planar)

> H:=hypercube_graph(5)
an undirected unweighted graph with 32 vertices and 80 edges
> draw_graph(H,plot3d,labels=false)

18

Constructing graphs

1.6.2. Star graphs
The command star_graph is used for construction of star graphs.
Syntax: star_graph(n)
star_graph accepts a positive integer n as its only argument and returns the star graph with n + 1
vertices, which is equal to the complete bipartite graph complete_graph(1,n) i.e. a n-ary tree
with one level.
> G:=star_graph(5)
an undirected unweighted graph with 6 vertices and 5 edges
> draw_graph(G)

1.6.3. Wheel graphs
The command wheel_graph is used for construction of wheel graphs.
Syntax: wheel_graph(n)
wheel_graph accepts a positive integer n as its only argument and returns the wheel graph with
n + 1 vertices.
> G:=wheel_graph(5)
an undirected unweighted graph with 6 vertices and 10 edges
> draw_graph(G)

1.6.4. Web graphs
The command web_graph is used for construction of web graphs.
Syntax: web_graph(a,b)
web_graph accepts two positive integers a and b as its arguments and returns the web graph with
parameters a and b, namely the Cartesian product of cycle_graph(a) and path_graph(b).

1.6 Special graphs

19

> G:=web_graph(7,3)
an undirected unweighted graph with 21 vertices and 35 edges
> draw_graph(G,labels=false)

1.6.5. Prism graphs
The command prism_graph is used for construction of prism graphs.
Syntax: prism_graph(n)
prism_graph accepts a positive integer n as its only argument and returns the prism graph with
parameter n, namely petersen_graph(n,1).
> G:=prism_graph(5)
an undirected unweighted graph with 10 vertices and 15 edges
> draw_graph(G)

1.6.6. Antiprism graphs
The command antiprism_graph is used for construction of antiprism graphs.
Syntax: antiprism_graph(n)
antiprism_graph accepts a positive integer n as its only argument and returns the antiprism
graph with parameter n, which is constructed from two concentric cycles of n vertices by joining
each vertex of the inner to two adjacent nodes of the outer cycle.
> G:=antiprism_graph(7)
an undirected unweighted graph with 14 vertices and 28 edges
> draw_graph(G)

1.6.7. Grid graphs
The command grid_graph resp. torus_grid_graph is used for construction of rectangular/triangular resp. torus grid graphs.

20

Constructing graphs

Syntax: grid_graph(m,n)
grid_graph(m,n,triangle)
torus_grid_graph(m,n)
grid_graph accepts two positive integers m and n as its arguments and returns the m by n grid on
m n vertices, namely the Cartesian product of path_graph(m) and path_graph(n). If the option
triangle is passed as the third argument, the returned graph is a triangular grid on m n vertices
dened as the underlying graph of the strong product of two directed path graphs with m and n
vertices, respectively [1, Denition 2, pp. 189]. Strong product is dened as the union of Cartesian
and tensor products.
torus_grid_graph accepts two positive integers m and n as its arguments and returns the m by n
torus grid on m n vertices, namely the Cartesian product of cycle_graph(m) and cycle_graph(n).
> G:=grid_graph(15,20)
an undirected unweighted graph with 300 vertices and 565 edges
> draw_graph(G,spring)

For example, connecting vertices in the opposite corners of the above grid yields a grid-like graph
with no corners.
> G:=add_edge(G,[["14:0","0:19"],["0:0","14:19"]])
an undirected unweighted graph with 300 vertices and 567 edges
> draw_graph(G,plot3d)

In the next example, the Möbius strip is constructed by connecting the vertices in the opposite
sides of a narrow grid graph.
> G:=grid_graph(20,3)
an undirected unweighted graph with 60 vertices and 97 edges
> G:=add_edge(G,[["0:0","19:2"],["0:1","19:1"],["0:2","19:0"]])
an undirected unweighted graph with 60 vertices and 100 edges
> draw_graph(G,plot3d,labels=false)

A triangular grid is created by passing the option triangle.
> G:=grid_graph(10,15,triangle)
an undirected unweighted graph with 150 vertices and 401 edges
> draw_graph(G,spring)

1.6 Special graphs

21

The next example demonstrates creating a torus grid graph with eight triangular levels.
> G:=torus_grid_graph(8,3)
an undirected unweighted graph with 24 vertices and 48 edges
> draw_graph(G,spring,labels=false)

1.6.8. Sierpi«ski graphs
The command sierpinski_graph is used for construction of Sierpi«ski-type graphs Skn and
STkn [30].

Syntax: sierpinski_graph(n,k)
sierpinski_graph(n,k,triangle)
sierpinski_graph accepts two positive integers n and k as its arguments and optionally the
symbol triangle as the third argument. It returns the Sierpi«ski (triangle) graph with parameters
n and k.
The Sierpi«ski triangle graph STkn is obtained by contracting all non-clique edges in Skn. To detect
such edges the variant of the algorithm by Bron and Kerbosch, developed by Tomita et al. in
[50], is used, which can be time consuming for n > 6.
> S:=sierpinski_graph(4,3)
an undirected unweighted graph with 81 vertices and 120 edges
> draw_graph(S,spring)

In particular, ST3n is the well-known Sierpi«ski sieve graph of order n.
> sierpinski_graph(4,3,triangle)
an undirected unweighted graph with 42 vertices and 81 edges
> sierpinski_graph(5,3,triangle)
an undirected unweighted graph with 123 vertices and 243 edges

22

Constructing graphs

A drawing of the graph produced by the last command line is shown in Figure 3.1.

1.6.9. Generalized Petersen graphs
The command petersen_graph is used for construction of generalized Petersen graphs P (n; k).
Syntax: petersen_graph(n)
petersen_graph(n,k)
petersen_graph accepts two positive integers n and k as its arguments. The second argument may
be omitted, in which case k = 2 is assumed. The graph P (n; k), which is returned, is a connected
cubic graph consisting ofin Schläi notationan inner star polygon fn; kg and an outer regular
polygon fng such that the n pairs of corresponding vertices in inner and outer polygons are
connected with edges. For k = 1 the prism graph of order n is obtained.
The well-known Petersen graph is equal to the generalized Petersen graph P (5; 2). It can also be
constructed by calling graph("petersen").
> draw_graph(graph("petersen"))

To obtain the dodecahedral graph P (10; 2), input:
> petersen_graph(10)
an undirected unweighted graph with 20 vertices and 30 edges
To obtain MöbiusKantor graph P (8; 3), input:
> G:=petersen_graph(8,3)
an undirected unweighted graph with 16 vertices and 24 edges
> draw_graph(G)
0

1
8 9

7
15
14
6

2
10
11
3

1312
5

4

Note that Desargues, Dürer and Nauru graphs are isomorphic to the generalized Petersen graphs
P (10; 3), P (6; 2) and P (12; 5), respectively.

1.6.10. LCF graphs
The command lcf_graph is used for construction of cubic Hamiltonian graphs from LCF notation.
Syntax: lcf_graph(L)
lcf_graph(L,n)
lcf_graph takes one or two arguments, a list L of nonzero integers, called jumps, and optionally
a positive integer n, called the exponent (by default, n = 1). The command returns the graph on
n jLj vertices obtained by iterating the sequence of jumps n times.

1.7 Isomorphic copies of graphs

23

For example, the following command line creates Frucht graph.
> F:=lcf_graph([-5,-2,-4,2,5,-2,2,5,-2,-5,4,2])
an undirected unweighted graph with 12 vertices and 18 edges
> draw_graph(F,planar)

In the next example, the truncated octahedral graph is constructed from LCF notation.
> G:=lcf_graph([3,-7,7,-3],6)
an undirected unweighted graph with 24 vertices and 36 edges
> draw_graph(G,planar,labels=false)

1.7. Isomorphic copies of graphs
1.7.1. Creating an isomorphic copy from a permutation
To create an isomorphic copy of a graph use the isomorphic_copy command.
Syntax: isomorphic_copy(G,sigma)
isomorphic_copy(G)
isomorphic_copy accepts one or two arguments, a graph G(V ; E) and optionally a permutation
 of order jV j. It returns a new graph where the adjacency lists are reordered according to  or a
random permutation if the second argument is omitted. The vertex labels are the same as in G.
This command discards all vertex and edge attributes present in G.
The complexity of the algorithm is O(jV j + jE j).
> G:=path_graph([1,2,3,4,5])
an undirected unweighted graph with 5 vertices and 4 edges
> vertices(G), neighbors(G)
[1; 2; 3; 4; 5]; f[2]; [1; 3]; [2; 4]; [3; 5]; [4]g
> H:=isomorphic_copy(G)
an undirected unweighted graph with 5 vertices and 4 edges
> vertices(H), neighbors(H)
[1; 2; 3; 4; 5]; f[2; 3]; [1; 5]; [1; 4]; [3]; [2]g
> H:=isomorphic_copy(G,[2,4,0,1,3])

24

Constructing graphs

an undirected unweighted graph with 5 vertices and 4 edges
> vertices(H), neighbors(H)
[1; 2; 3; 4; 5]; f[4; 5]; [5]; [4]; [1; 3]; [1; 2]g
> P:=prism_graph(3)
an undirected unweighted graph with 6 vertices and 9 edges
> draw_graph(P)
0

3

5

4

2

1

> H:=isomorphic_copy(P,[3,0,1,5,4,2])
an undirected unweighted graph with 6 vertices and 9 edges
> draw_graph(H,spring)
0

3

4

1

5

2

1.7.2. Permuting vertices
To create an isomorphic copy of a graph by providing the reordered list of vertex labels, use the
command permute_vertices.
Syntax: permute_vertices(G,L)
permute_vertices(G)
permute_vertices accepts one or two arguments, a graph G(V ; E) and optionally a list L of
length jV j containing all vertices from V , and returns a copy of G with vertices rearranged in
order they appear in L or at random if L is not given. All vertex and edge attributes are copied,
which includes vertex position information (if present). That means the resulting graph will look
the same as G when drawn.
The complexity of the algorithm is O(jV j + jE j).
> G:=path_graph([1,2,3,4,5])
an undirected unweighted graph with 5 vertices and 4 edges
> vertices(G), neighbors(G)
[1; 2; 3; 4; 5]; f[2]; [1; 3]; [2; 4]; [3; 5]; [4]g
> H:=permute_vertices(G,[3,5,1,2,4])
an undirected unweighted graph with 5 vertices and 4 edges
> vertices(H), neighbors(H)
[3; 5; 1; 2; 4]; f[2; 4]; [4]; [2]; [1; 3]; [3; 5]g

1.8 Subgraphs

25

1.7.3. Relabeling vertices
To relabel the vertices of a graph without changing their order, use the command relabel_vertices.

Syntax: relabel_vertices(G,L)
relabel_vertices accepts two arguments, a graph G(V ; E) and a list L of vertex labels of length
jV j. It returns a copy of G with L as the list of vertex labels.
The complexity of the algorithm is O(jV j).
> G:=path_graph([1,2,3,4])
an undirected unweighted graph with 4 vertices and 3 edges
> edges(G)
f[1; 2]; [2; 3]; [3; 4]g
> H:=relabel_vertices(G,[a,b,c,d])
an undirected unweighted graph with 4 vertices and 3 edges
> edges(H)
f[a; b]; [b; c]; [c; d]g

1.8. Subgraphs
1.8.1. Extracting subgraphs
To extract the subgraph of a graph formed by a subset of the set of its edges, use the command
subgraph.
Syntax: subgraph(G,L)
subgraph accepts two arguments, a graph G(V ; E) and a list of edges L. It returns the subgraph
G 0(V 0; L) of G, where V 0  V is a subset of vertices of G incident to at least one edge from L.
> K5:=complete_graph(5)
an undirected unweighted graph with 5 vertices and 10 edges
> S:=subgraph(K5,[[1,2],[2,3],[3,4],[4,1]])
an undirected unweighted graph with 4 vertices and 4 edges
> draw_graph(highlight_subgraph(K5,S))

1.8.2. Induced subgraphs
To obtain the subgraph of a graph induced by a subset of its vertices, use the command
induced_subgraph.
Syntax: induced_subgraph(G,L)

26

Constructing graphs

induced_subgraph accepts two arguments, a graph G(V ; E) and a list of vertices L. It returns the
subgraph G 0(L; E 0) of G, where E 0  E contains all edges which have both endpoints in L [23, pp. 3].
> G:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> S:=induced_subgraph(G,[5,6,7,8,9])
an undirected unweighted graph with 5 vertices and 5 edges
> draw_graph(highlight_subgraph(G,S))

1.8.3. Underlying graphs
For every graph G(V ; E) there is an undirected and unweighted graph U (V ; E 0), called the underlying graph of G, where E 0 is obtained from E by dropping edge directions. To construct U , use
the command underlying_graph.
Syntax: underlying_graph(G)
underlying_graph accepts a graph G(V ; E) as its only argument and returns an undirected
unweighted copy of G in which all vertex and edge attributes, together with edge directions, are
discarded.
The complexity of the algorithm is O(jV j + jE j).
> G:=digraph(%{[[1,2],6],[[2,3],4],[[3,1],5],[[3,2],7]%})
a directed weighted graph with 3 vertices and 4 arcs
> U:=underlying_graph(G)
an undirected unweighted graph with 3 vertices and 3 edges
> edges(U)
f[1; 2]; [1; 3]; [2; 3]g

1.8.4. Fundamental cycles
The command fundamental_cycle is used for extracting cycles from unicyclic graphs (also called
1-trees). To nd a fundamental cycle basis of an undirected graph, use the command cycle_basis.
Syntax: fundamental_cycle(G)
cycle_basis(G)
fundamental_cycle accepts one argument, an undirected connected graph G(V ; E) containing
exactly one cycle (i.e. a unicyclic graph), and returns that cycle as a graph. If G is not unicyclic,
an error is returned.
cycle_basis accepts an undirected graph G(V ; E) as its only argument and returns a basis
B of the cycle space of G as a list of fundamental cycles in G, with each cycle represented as
a list of vertices. Furthermore, jB j = jE j ¡ jV j + (G), where (G) is the number of connected
components of G. Every cycle C in G such that C 2
/ B can be obtained from cycles in B using
only symmetric dierences.

1.8 Subgraphs

27

The strategy is to construct a spanning tree T of G using depth-rst search and look for edges in
E which do not belong to the tree. For each non-tree edge e there is a unique fundamental cycle
Ce consisting of e together with the path in T connecting the endpoints of e. The vertices of Ce
are easily obtained from the search data. The complexity of this algorithm is O(jV j + jE j).
> G:=graph(trail(1,2,3,4,5,2,6))
an undirected unweighted graph with 6 vertices and 6 edges
> C:=fundamental_cycle(G)
an undirected unweighted graph with 4 vertices and 4 edges
> edges(C)
0

1
5
3 C
C
5 A
4

2
B 2
B
@ 4
3

Given a tree graph G and adding an edge from the complement Gc to G one obtains a 1-tree graph.
> G:=random_tree(25)
an undirected unweighted graph with 25 vertices and 24 edges
> ed:=choice(edges(graph_complement(G)))
[10; 20]
> G:=add_edge(G,ed)
an undirected unweighted graph with 25 vertices and 25 edges
> C:=fundamental_cycle(G)
an undirected unweighted graph with 8 vertices and 8 edges
> edges(C)
0
B
B
B
B
B
B
B
B
B
B
@

10
0
1
1
2
13
7
0

1

20
10
20
2
24
24
13
7

C
C
C
C
C
C
C
C
C
C
A

> draw_graph(highlight_subgraph(G,C),spring)
11
8

20
10

1

0
2
16
15

24

7
13

5
23

3

21

6
12
18

4
22

19

17
14

9

In the next example, a cycle basis of octahedral graph is computed.
> G:=graph("octahedron")
an undirected unweighted graph with 6 vertices and 12 edges

28

Constructing graphs

> draw_graph(G)
6

4

2
5

1

3

> cycle_basis(G)
f[6; 3; 1]; [5; 4; 6; 3; 1]; [4; 6; 3; 1]; [5; 4; 6; 3]; [2; 5; 4; 6; 3]; [2; 5; 4; 6]; [2; 5; 4]g
Given a tree graph T , one can create a graph with cycle basis cardinality equal to k by simply
adding k randomly selected edges from the complement T c to T .
> tree1:=random_tree(15)
an undirected unweighted graph with 15 vertices and 14 edges
> G1:=add_edge(tree1,rand(3,edges(graph_complement(tree1))))
an undirected unweighted graph with 15 vertices and 17 edges
> tree2:=random_tree(12)
an undirected unweighted graph with 12 vertices and 11 edges
> G2:=add_edge(tree2,rand(2,edges(graph_complement(tree2))))
an undirected unweighted graph with 12 vertices and 13 edges
> G:=disjoint_union(G1,G2)
an undirected unweighted graph with 27 vertices and 30 edges
> draw_graph(G,spring,labels=false)

> nops(cycle_basis(G))
5
> number_of_edges(G)-number_of_vertices(G)+nops(connected_components(G))
5

1.9. Operations on graphs
1.9.1. Graph complement
The command graph_complement is used for construction of complement graphs.
Syntax: graph_complement(G)
graph_complement accepts a graph G(V ; E) as its only argument and returns the complement
graph Gc(V ; E c) of G, where E c is the largest set containing only edges/arcs not present in G.
The complexity of the algorithm is O(jV j2).

1.9 Operations on graphs

29

> C5:=cycle_graph(5)
C5: an undirected unweighted graph with 5 vertices and 5 edges
> draw_graph(C5)
0

4

1

3

2

> G:=graph_complement(C5)
an undirected unweighted graph with 5 vertices and 5 edges
> draw_graph(G)
0

4

1

3

2

1.9.2. Seidel switching
The command seidel_switch is used for Seidel switching in graphs.
Syntax: seidel_switch(G,L)
seidel_switch accepts two arguments, an undirected and unweighted graph G(V ; E) and a list
of vertices L  V . The result is a copy of G in which, for each vertex v 2 L, its neighbors become
its non-neighbors and vice versa.
> S:=seidel_switch(cycle_graph(5),[1,2])
an undirected unweighted graph with 5 vertices and 7 edges
> draw_graph(S)
0

4

1

3

2

1.9.3. Transposing graphs
The command reverse_graph is used for reversing arc directions in digraphs.
Syntax: reverse_graph(G)
reverse_graph accepts a graph G(V ; E) as its only argument and returns the reverse graph GT (V ;
E 0) of G where E 0 = f(j ; i): (i; j) 2 E g, i.e. returns the copy of G with the directions of all edges
reversed.
Note that reverse_graph is dened for both directed and undirected graphs, but gives meaningful
results only for directed graphs.
GT is also called the transpose graph of G because adjacency matrices of G and GT are transposes of each other (hence the notation).

30

Constructing graphs

> G:=digraph(6, %{[1,2],[2,3],[2,4],[4,5]%})
a directed unweighted graph with 6 vertices and 4 arcs
> GT:=reverse_graph(G)
a directed unweighted graph with 6 vertices and 4 arcs
> edges(GT)
f[2; 1]; [3; 2]; [4; 2]; [5; 4]g

1.9.4. Union of graphs
The command graph_union is used for constructing unions of graphs.
Syntax: graph_union(G1,G2,..,Gn)
graph_union accepts a sequence of graphs Gk(Vk ; Ek) for k = 1; 2; :::; n as its argument and returns
the graph G(V ; E) where V = V1 [ V2 [  [ Vk and E = E1 [ E2 [  [ Ek.
> G1:=graph([1,2,3],%{[1,2],[2,3]%})
an undirected unweighted graph with 3 vertices and 2 edges
> G2:=graph([1,2,3],%{[3,1],[2,3]%})
an undirected unweighted graph with 3 vertices and 2 edges
> G:=graph_union(G1,G2)
an undirected unweighted graph with 3 vertices and 3 edges
> edges(G)
f[1; 2]; [1; 3]; [2; 3]g

1.9.5. Disjoint union of graphs
To construct disjoint union of graphs use the command disjoint_union.
Syntax: disjoint_union(G1,G2,..,Gn)
disjoint_union accepts a sequence of graphs Gk(Vk ; Ek) for k = 1; 2; :::; n as its only argument
and returns the graph obtained by labeling all vertices with strings k:v where v 2 Vk and all edges
with strings k:e where e 2 Ek and calling the graph_union
command subsequently.
As all vertices
Pn
Pn
and edges are labeled dierently, it follows jV j = k=1
jVk j and jE j = k=1
jEk j.6
> G:=disjoint_union(cycle_graph([1,2,3]),path_graph([1,2,3]))

an undirected unweighted graph with 6 vertices and 5 edges
> draw_graph(G)

1.9.6. Joining two graphs
The command graph_join is used for joining two graphs together.

1.9 Operations on graphs

31

Syntax: graph_join(G,H)
graph_join accepts two graphs G and H as its arguments and returns the graph G + H which is
obtained by connecting all the vertices of G to all vertices of H. The vertex labels in the resulting
graph are strings of the form 1:u and 2:v where u is a vertex in G and v is a vertex in H.
> G:=path_graph(2)
an undirected unweighted graph with 2 vertices and 1 edge
> H:=graph(3)
an undirected unweighted graph with 3 vertices and 0 edges
> GH:=graph_join(G,H)
an undirected unweighted graph with 5 vertices and 7 edges
> draw_graph(GH,spring)
2:0

1:1

1:0

2:1

2:2

1.9.7. Power graphs
The command graph_power is used for computing powers of graphs.
Syntax: graph_power(G,k)
graph_power accepts two arguments, a graph G(V ; E) and a positive integer k. It returns the k-th
power Gk of G with vertices V such that v; w 2 V are connected with an edge if and only if there
exists a path of length at most k in G.
The graph Gk is constructed from its adjacency matrix Ak which is obtained by adding powers of
the adjacency matrix A of G:
Ak =

k
X

Ak:

i=1

The above sum is obtained by assigning Ak A and repeating the instruction Ak
k ¡ 1 times, so exactly k matrix multiplications are required.
> G:=graph(trail(1,2,3,4,5))
an undirected unweighted graph with 5 vertices and 4 edges
> draw_graph(G,circle)

> P2:=graph_power(G,2)
an undirected unweighted graph with 5 vertices and 7 edges
> draw_graph(P2,circle)

(Ak + I) A for

32

Constructing graphs

> P3:=graph_power(G,3)
an undirected unweighted graph with 5 vertices and 9 edges
> draw_graph(P3,circle)

1.9.8. Graph products
There are two distinct operations for computing the product of two graphs: the Cartesian product
and the tensor product. These operations are available in Giac as the commands cartesian_product and tensor_product, respectively.
Syntax: cartesian_product(G1,G2,..,Gn)
tensor_product(G1,G2,..,Gn)
cartesian_product accepts a sequence of graphs Gk(Vk ; Ek) for k = 1; 2; :::; n as its argument
and returns the Cartesian product G1  G2    Gn of the input graphs. The Cartesian product
G(V ; E) = G1  G2 is the graph with list of vertices V = V1  V2, labeled with strings v1:v2 where
v1 2 V1 and v2 2 V2, such that (u1:v1,u2:v2)2E if and only if u1 is adjacent to u2 and v1 = v2 or
u1 = u2 and v1 is adjacent to v2.
> G1:=graph(trail(1,2,3,4,1,5))
an undirected unweighted graph with 5 vertices and 5 edges
> draw_graph(G1,circle)

> G2:=star_graph(3)
an undirected unweighted graph with 4 vertices and 3 edges
> draw_graph(G2,circle=[1,2,3])

> G:=cartesian_product(G1,G2)

1.9 Operations on graphs

33

an undirected unweighted graph with 20 vertices and 35 edges
> draw_graph(G)

tensor_product accepts a sequence of graphs Gk(Vk ; Ek) for k = 1; 2; :::; n as its argument and
returns the tensor product G1  G2    Gn of the input graphs. The tensor product G(V ;
E) = G1  G2 is the graph with list of vertices V = V1  V2, labeled with strings v1:v2 where v1 2 V1
and v2 2 V2, such that (u1:v1,u2:v2)2E if and only if u1 is adjacent to u2 and v1 is adjacent to v2.
> T:=tensor_product(G1,G2)
an undirected unweighted graph with 20 vertices and 30 edges
> draw_graph(T)

1.9.9. Transitive closure graph
The command transitive_closure is used for constructing transitive closure graphs.
Syntax: transitive_closure(G)
transitive_closure(G,weighted[=true or false])
transitive_closure accepts one or two arguments, a graph G(V ; E) and optionally the option
weighted=true (or simply weighted) or the option weighted=false (which is the default). The
command returns the transitive closure T (V ; E 0) of the input graph G by connecting u 2 V to
v 2 V in T if and only if there is a path from u to v in G. If G is directed, then T is also directed.
When weighted=true is specied, T is weighted such that the weight of edge v w 2 E 0 is equal to
the length (or cost, if G is weighted) of the shortest path from v to w in G.
The lengths/weights of the shortest paths are obtained by the command allpairs_distance if G
is weighted resp. the command vertex_distance if G is unweighted. Therefore T is constructed
in at most O(jV j3) time if weighted[=true] is given and in O(jV j jE j) time otherwise.
> G:=digraph([1,2,3,4,5,6],%{[1,2],[2,3],[2,4],[4,5],[3,5]%})
a directed unweighted graph with 6 vertices and 5 arcs
> draw_graph(G)

> T:=transitive_closure(G,weighted)
a directed weighted graph with 6 vertices and 9 arcs
> draw_graph(T)

34

Constructing graphs

> G:=assign_edge_weights(G,1,99)
a directed weighted graph with 6 vertices and 5 arcs
> draw_graph(G)

> draw_graph(transitive_closure(G,weighted=true))

1.9.10. Line graph
The command line_graph is used for construction of line graphs [23, pp. 10].
Syntax: line_graph(G)
line_graph accepts an undirected graph G as its only argument and returns the line graph L(G)
with jE j distinct vertices, one vertex for each edge in E. Furthermore, two vertices v1 and v2 in
L(G) are adjacent if and only if the corresponding edges e1; e2 2 E have a common endpoint. The
vertices in L(G) are labeled with strings in form v-w, where e = vw 2 E.
> K4:=complete_graph([1,2,3,4])
an undirected unweighted graph with 4 vertices and 6 edges
> L:=line_graph(K4)
an undirected unweighted graph with 6 vertices and 12 edges
> draw_graph(L,spring)

1.9.11. Plane dual graph
The command plane_dual is used for construction of dual graphs from undirected biconnected
planar graphs. To determine whether the given graph is planar [23, pp. 12] use the command
is_planar.

1.9 Operations on graphs

35

Syntax: plane_dual(G)
plane_dual(F)
is_planar(G)
is_planar(G,F)
plane_dual accepts a biconnected planar graph G(V ; E) or the list F of faces of a planar embedding of G as its only argument and returns the graph H with faces of G as its vertices. Two vertices
in H are adjacent if and only if the corresponding faces share an edge in G. The algorithm runs
in O(jV j2) time.
Note that the concept of dual graph is normally dened for multigraphs. By the strict denition,
every planar multigraph has the corresponding dual multigraph; moreover, the dual of the latter
is equal to the former. Since Giac generally does not support multigraphs, a simplied denition
suitable for simple graphs is used; hence the requirement that the input graph is biconnected.
In the example below, the dual graph of the cube graph is obtained.
> H:=hypercube_graph(3)
an undirected unweighted graph with 8 vertices and 12 edges
> draw_graph(H,spring)

The cube has six faces, hence its plane dual graph D has six vertices. Also, every face obviously
shares an edge with exactly four other faces, so the degree of each vertex in D is equal to 4.
> D:=plane_dual(H)
an undirected unweighted graph with 6 vertices and 12 edges
> draw_graph(D,spring)

is_planar accepts one or two arguments, the input graph G and optionally an unassigned identier F. It returns true if G is planar and false otherwise. If the second argument is given and G
is planar and biconnected, the list of faces of G is stored to F. Each face is represented as a cycle
(a list) of vertices. The strategy is to use the algorithm of Demoucron et al. [22, pp. 88], which
runs in O(jV j2) time.
> is_planar(graph("petersen"))
false
> is_planar(graph("durer"))
true
In the next example, a graph isomorphic to D is obtained when passing a list of faces of H to the
plane_dual command. The order of vertices is determined by the order of faces.
> is_planar(H,F); F

36

Constructing graphs

0

B
B
B
true;B
B
B
@

010
001
010
100
111
101

000
000
011
000
011
100

> is_isomorphic(plane_dual(F),D)

001
100
111
010
001
110

011
101
110
110
101
111

1
C
C
C
C
C
C
A

true

1.10. Random graphs
1.10.1. Random general graphs
The commands random_graph and random_digraph are used for generating general (di)graphs
uniformly at random according to Erd®sRényi model.
Syntax: random_graph(n|L,p)
random_graph(n|L,m)
random_digraph(n|L,p)
random_digraph(n|L,m)
random_graph and random_digraph both accept two arguments. The rst argument is a positive
integer n or a list of labels L of length n. The second argument is a positive real number p < 1
or a positive integer m. The return value is a (di)graph on n vertices (using the elements of L as
vertex labels) selected uniformly at random, i.e. a (di)graph in which each edge/arc is present with
probability p or which contains exactly m edges/arcs chosen uniformly at random.
The strategy is to use the algorithms of Bagatelj and Brandes [3, algorithms 1 and 2], which
operate in linear time.
> G:=random_graph(10,0.5)
an undirected unweighted graph with 10 vertices and 21 edges
> draw_graph(G,spring,labels=false)

> G:=random_graph(1000,0.05)
an undirected unweighted graph with 1000 vertices and 24870 edges
> is_connected(G)
true
> minimum_degree(G),maximum_degree(G)
20; 71
> G:=random_graph(15,20)

1.10 Random graphs

37

an undirected unweighted graph with 15 vertices and 20 edges
> draw_graph(G,spring)
13

6

8
3
14

5

7

0

11

12
4

10
9

2

1

> DG:=random_digraph(15,0.15)
a directed unweighted graph with 15 vertices and 33 arcs
> draw_graph(DG,labels=false,spring)

1.10.2. Random bipartite graphs
The command random_bipartite_graph is used for generating bipartite graphs at random.
Syntax: random_bipartite_graph(n,p|m)
random_bipartite_graph([a,b],p|m)
random_bipartite_graph accepts two arguments. The rst argument is either a positive integer
n or a list of two positive integers a and b. The second argument is either a positive real number
p < 1 or a positive integer m. The command returns a random bipartite graph on n vertices (or
with two partitions of sizes a and b) in which each possible edge is present with probability p (or
m edges are inserted at random).
> G:=random_bipartite_graph([3,4],0.5)
an undirected unweighted graph with 7 vertices and 8 edges
> draw_graph(G)

> G:=random_bipartite_graph(30,60)
an undirected unweighted graph with 30 vertices and 60 edges

1.10.3. Random trees
The command random_tree is used for generating tree graphs at random.

38

Constructing graphs

Syntax: random_tree(n|V)
random_tree(n|V,d)
random_tree(n|V,root)
random_tree(V,root=v)
random_tree accepts one or two arguments: a positive integer n or a list V = fv1; v2; :::; vng and
optionally an integer d > 2 or the option root[=v], where v 2 V . It returns a random tree T (V ; E)
on n vertices such that
¡

if the second argument is omitted, then T is uniformly selected among all unrooted unlabeled
trees on n vertices,

¡

if d is given as the second argument, then (T ) 6 d, where (T ) is the maximum vertex
degree in T ,

¡

if root[=v] is given as the second argument, then T is uniformly selected among all rooted
unlabeled trees on n vertices. If v is specied then the vertex labels in V (required) will be
assigned to vertices in T such that v is the rst vertex in the list returned by the command
vertices(T).

Rooted unlabeled trees are generated uniformly at random using RANRUT algorithm [38, pp. 274].
The root of a tree T generated this way, if not specied as v, is always the rst vertex in the list
returned by the command vertices(T). The average time complexity of RANRUT algorithm is
O(jV j log jV j) [2].
Unrooted unlabeled trees, also called free trees, are generated uniformly at random using Wilf's
algorithm1.1 [56], which is based on RANRUT algorithm and runs in about the same time as
RANRUT itself.
Trees with bounded maximum degree are generated using a simple algorithm which starts with an
empty tree and adds edges at random one at a time. It is much faster than RANRUT but selects
trees in a non-uniform manner. To force the use of this algorithm even without vertex degree limit
(for example, if n is very large), one can set d = +1.
For example, the command line below creates a forest containing 10 randomly selected free trees
on 10 vertices.
> G:=disjoint_union(apply(random_tree,[10$10]))
an undirected unweighted graph with 100 vertices and 90 edges
> draw_graph(G,tree,labels=false)

The following example demonstrates the uniformity of random generation of free trees. Letting
n = 6, there are exactly 6 distinct free trees on 6 vertices, created by the next command line.
> trees:=[star_graph(5),path_graph(6),graph(trail(1,2,3,4),trail(5,4,6)),
graph(%{[1,2],[2,3],[2,4],[4,5],[4,6]%}),graph(trail(1,2,3,4),trail(3,5,6)),
graph(trail(1,2,3,4),trail(5,3,6))]:;
1.1. The original Wilf's algorithm has an error in the procedure Free, page 207. The formula p =



1 + an/2
2



/an in

step (T1) is wrong; instead of the denominator an, which is the number of all rooted unlabeled trees on n vertices,
one should put the number tn of all unrooted unlabeled trees. tn can be obtained from a1; a2; :::; an by applying the
formula in [40, pp. 589]. The Giac implementation includes this correction.

1.10 Random graphs

39

> draw_graph(disjoint_union(trees),spring,labels=false)

Now, generating a random free tree on 6 nodes always produces one of the above six graphs, which
is determined by using is_isomorphic command. 1200 trees are generated in total and the number
of occurrences of trees[k] is stored in hits[k] for every k = 1; 2; :::; 6 (note that in Xcas mode it
is actually k = 0; :::; 5).
> hits:=[0$6]:;
> for k from 1 to 1200 do
T:=random_tree(6);
for j from 0 to 5 do
if is_isomorphic(T,trees[j]) then hits[j]++; fi;
od;
od:;
> hits
[198; 194; 192; 199; 211; 206]
To show that the algorithm also selects rooted trees on n vertices with equal probability, one can
reproduce the example in [38, pp. 281], in which n = 5. First, all distinct rooted trees on 5 vertices
are created and stored in trees; there are exactly nine of them. Their root vertices are highlighted
to be distinguishable. Then, 4500 rooted trees on 5 vertices are generated at random, highlighting
the root vertex in each of them. As in the previous example, the variable hits[k] records how
many of them are isomorphic to trees[k].
> trees:=[
highlight_vertex(graph(trail(1,2,3,4,5)),1),
highlight_vertex(graph(trail(1,2,3,4,5)),2),
highlight_vertex(graph(trail(1,2,3,4,5)),3),
highlight_vertex(graph(trail(1,2,3),trail(4,3,5)),1),
highlight_vertex(graph(trail(1,2,3),trail(4,3,5)),2),
highlight_vertex(graph(trail(1,2,3),trail(4,3,5)),3),
highlight_vertex(graph(trail(1,2,3),trail(4,3,5)),4),
highlight_vertex(graph(trail(1,2,3),trail(4,2,5)),1),
highlight_vertex(graph(trail(1,2,3),trail(4,2,5)),2)
]:;
> draw_graph(disjoint_union(trees),labels=false)

> hits:=[0$9]:;
> for k from 1 to 4500 do
T:=random_tree(5,root);
HT:=highlight_vertex(T,vertices(T)[0]);
for j from 0 to 8 do
if is_isomorphic(HT,trees[j]) then hits[j]++; fi;
od;
od:;
> hits

40

Constructing graphs

[534; 483; 486; 485; 496; 521; 498; 489; 508]
In the following example, a random tree on 100 vertices with maximum degree at most 3 is drawn.
> draw_graph(random_tree(100,3))

1.10.4. Random planar graphs
The command random_planar_graph is used for generating random planar graphs.
Syntax: random_planar_graph(n|L,p)
random_planar_graph(n|L,p,k)
random_planar_graph accepts two or three arguments, a positive integer n (or a list L of length
n), a positive real number p < 1 and optionally an integer k 2 f0; 1; 2; 3g (by default, k = 1). The
command returns a random k-connected planar graph on n vertices (using the elements of L as
vertex labels).
The result is obtained by rst generating a random maximal planar graph and then attempting
to remove each edge with probability p, maintaining the k-connectivity of the graph (if k = 0, the
graph may be disconnected). The running time is O(n) if k = 0, O(n2) if k 2 f1; 2g and O(n3) if
k = 3.
The following command line generates a biconnected planar graph.
> G:=random_planar_graph(20,0.8,2)
an undirected unweighted graph with 20 vertices and 25 edges
> draw_graph(G,planar,labels=false)

The command line below generates a triconnected planar graph.
> G:=random_planar_graph(15,0.9,3)
an undirected unweighted graph with 15 vertices and 25 edges
> draw_graph(G,planar,labels=false)

1.10 Random graphs

41

The next command line generates a disconnected planar graph with high probability.
> G:=random_planar_graph(30,0.9,0)
an undirected unweighted graph with 30 vertices and 23 edges
> is_forest(G)
true
> draw_graph(G,spring,labels=false)

By default, a connected planar graph is generated, like in the following example.
> G:=random_planar_graph(15,0.618)
an undirected unweighted graph with 15 vertices and 19 edges
> is_connected(G)
true
> is_biconnected(G)
false
> articulation_points(G)
[1; 2; 4; 10; 11]
> draw_graph(G,planar)

1.10.5. Random graphs from the given degree sequence
The command random_sequence_graph is used for generating a random undirected graph from
the given degree sequence.
Syntax: random_sequence_graph(L)
random_sequence_graph accepts the degree sequence L (a list of nonnegative integers) as its only
argument. It returns an asimptotically uniform random graph with the degree sequence equal to
L in almost linear time, using the algorithm developed by Bayati et al. [4].
> s:=[1,3,3,2,1,2,2,2,3,3]:; is_graphic_sequence(s)
Done; true
> G:=random_sequence_graph(s)
an undirected unweighted graph with 10 vertices and 11 edges

42

Constructing graphs

> draw_graph(G,spring)
0

6

8

1
7

9

3
2

5

4

> H:=random_sequence_graph(s)
an undirected unweighted graph with 10 vertices and 11 edges
> draw_graph(H,spring)
7

5

9

8

6

3
2

1

4

0

1.10.6. Random regular graphs
The command random_regular_graph is used for generating random regular graphs on the given
set of vertices.
Syntax: random_regular_graph(n or L,d)
random_regular_graph(n or L,d,connected)
random_regular_graph accepts two mandatory arguments, a positive integer n (or a list L of
length n) and a nonnegative integer d. Optionally, the option connected may be specied as a
third argument, indicating that the generated graph must be connected. The command creates n
vertices (using elements of L as vertex labels) and returns a random d-regular (connected) graph
on these vertices.
Note that a d-regular graph on n vertices exists if and only if n > d + 1 and n d is even. If these
conditions are not met, random_regular_graph returns an error.
The strategy is to use the algorithm developed by Steger and Wormald [44, algorithm 2]. The
runtime is negligible for n 6 100. However, for n > 200 the algorithm is considerably slower. Graphs
are generated with approximately uniform probability, which means that for n ! 1 and d not
growing so quickly with n the probability distribution converges to uniformity.
> G:=random_regular_graph(16,3)
an undirected unweighted graph with 16 vertices and 24 edges
> is_regular(G)
true
> degree_sequence(G)
[3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3]
> draw_graph(G,spring)
15

11
9
13

2

14 0

4
7

12
10

6

8

5
3

1

1.10 Random graphs

43

1.10.7. Random tournaments
The command random_tournament is used for generating random tournaments.
Syntax: random_tournament(n)
random_tournament(L)
random_tournament accepts a positive integer n or a list L of length n as its only argument and
returns a random tournament on n vertices. If L is specied, its elements are used to label the
vertices.
> G:=random_tournament([1,2,3,4])
a directed unweighted graph with 4 vertices and 6 arcs
> is_tournament(G)
true
> draw_graph(G)

1.10.8. Random network graphs
The command random_network is used for generation of random networks.
Syntax: random_network(a,b,[opts])
random_network(a,b,p,[opts])
random_network accepts two to four arguments: a positive integer a, a positive integer b, an
optional real number p such that 0 < p 6 1 (by default p = 0.5) and optionally a sequence of options
opts. The supported options are acyclic[=true|false] and weights=a..b.
The command returns a network graph with a2 b vertices which is composed as follows (the method
of generating the network skeleton is due to Goldfarb and Grigoriadis [24]).
Firstly, grid graphs F1; F2; :::; Fb (called frames), each of them with a  a vertices, are generated.
If the option acyclic[=true] is used (by default is acyclic=false), then an acyclic orientation
is computed for each frame using st-ordering (see Section 4.9.3) with two opposite corners of the
frame as source and sink, otherwise all vertices in the frame are connected to their neighbors (forth
and back). In addition, for each k < b the vertices of Fk are connected one to one with the vertices
of the next frame Fk+1 using a random permutation of those vertices. The rst vertex of the rst
frame is the source and the last vertex of the last frame is the sink of the network (some arcs may
have to be removed to achieve that). Finally, the removal of each arc is attempted with probability
1 ¡ p (unless its removal disconnects the network), making each arc present with probability p.
if the option weights=a..b is specied, arc weights in the network are randomized in the interval
[a; b]  R. If a; b are integers, the weights are also integers.
For example, the command line below creates a random network, consisting of 3 frames of size
2  2, in which each arc is present with the probability 0.9.
> N1:=random_network(2,3,0.9)
a directed unweighted graph with 12 vertices and 25 arcs
> draw_graph(N1,spring)

44

Constructing graphs

1

0

10

4

3

5

6

11

7

2

8

9

> is_network(N1)
[0]; [11]
In the next example, passing the option acyclic forces the output graph to be acyclic.
> N2:=random_network(3,2,0.618,acyclic)
a directed unweighted graph with 18 vertices and 22 arcs
> draw_graph(N2,spring)
7
16
4

6
3

13

15

14

12

11
10

2
1

9

5
8

0

17

> is_network(N2)


0 10
4 17



Arc weights can be randomized, as demonstrated below.
> N3:=random_network(2,2,0.75,weights=1..9)
a directed unweighted graph with 8 vertices and 12 arcs
> draw_graph(N3,spring)
1
3

5

0

4
4
3

4

3

6

2

5
6

8

6

5

8

7

1

7

1.10.9. Randomizing edge weights
The command assign_edge_weights is used for assigning weights to edges of graphs at random.
Syntax: assign_edge_weights(G,a..b)
assign_edge_weights(G,m,n)
assign_edge_weights accepts two or three arguments: a graph G(V ; E) and an interval a .. b of
real numbers or a sequence of two positive integers m and n. The command operates such that for,
each edge e 2 E, the weight of e is chosen uniformly from the real interval [a; b) or from the set of
integers lying between m and n, including both m and n. After assigning weights to all edges, a
modied copy of G is returned.
> G:=assign_edge_weights(grid_graph(5,3),1,99)

1.10 Random graphs

an undirected weighted graph with 15 vertices and 22 edges
> draw_graph(G,spring)

> G:=assign_edge_weights(graph_complement(complete_graph(2,3,4)),e..pi)
an undirected weighted graph with 9 vertices and 10 edges
> draw_graph(G)

45

Chapter 2
Modifying graphs
2.1. Promoting to directed and weighted graphs
2.1.1. Converting edges to arcs
To promote an existing undirected graph to a directed one, use the command make_directed.
Syntax: make_directed(G)
make_directed(G,A)
make_directed is called with one or two arguments, an undirected graph G(V ; E) and optionally a
numerical square matrix A = [aij] of order jV j. Every edge fi; j g 2 E is replaced with the pair of arcs
(i; j) and (j ; i) and, if matrix A is specied, its elements aij and aji are assigned as weights of these
arcs, respectively. Thus a directed (weighted) copy of G is constructed and subsequently returned.
> make_directed(cycle_graph(4))
C4: a directed unweighted graph with 4 vertices and 8 arcs
> make_directed(cycle_graph(4), [[0,0,0,1],[2,0,1,3],[0,1,0,4],[5,0,4,0]])
C4: a directed weighted graph with 4 vertices and 8 arcs

2.1.2. Assigning weight matrix to unweighted graphs
To promote an existing unweighted graph to a weighted one, use the command make_weighted.
Syntax: make_weighted(G)
make_weighted(G,A)
make_weighted accepts one or two arguments, an unweighted graph G(V ; E) and optionally a
square matrix A = [aij ] of order jV j. If the matrix specication is omitted, a square matrix of ones
is assumed. Then a copy of G is returned in which each edge/arc (i; j) 2 E gets the element aij in
A assigned as its weight. If G is undirected, it is assumed that A is a symmetric matrix.
> make_weighted(graph(%{[1,2],[2,3],[3,1]%}), [[0,2,3],[2,0,1],[3,1,0]])
an undirected weighted graph with 3 vertices and 3 edges

2.2. Modifying vertices of a graph
2.2.1. Adding and removing vertices
For adding and removing vertices to/from graphs use the commands add_vertex and
delete_vertex, respectively.
Syntax: add_vertex(G,v|L)
delete_vertex(G,v|L)
The command add_vertex accepts two arguments, a graph G(V ; E) and a single label v or a list
of labels L, and returns the graph G 0 (V [ fvg; E) or G 00 (V [ L; E) if a list L is given.
47

48

Modifying graphs

> K5:=complete_graph([1,2,3,4,5])
an undirected unweighted graph with 5 vertices and 10 edges
> add_vertex(K5,6)
an undirected unweighted graph with 6 vertices and 10 edges
> add_vertex(K5,[a,b,c])
an undirected unweighted graph with 8 vertices and 10 edges
Note that vertices already present in G will not be added. For example:
> add_vertex(K5,[4,5,6])
an undirected unweighted graph with 6 vertices and 10 edges
The command delete_vertex accepts two arguments, a graph G(V ; E) and a single label v or a
list of labels L, and returns the graph
G 0 (V n fv g; fe 2 E: e is not incident to v g)
or, if L is given,
G 00 (V n L; fe 2 E: e is not incident to any v 2 Lg):
If any of the specied vertices does not belong to G, an error is returned.
> delete_vertex(K5,2)
an undirected unweighted graph with 4 vertices and 6 edges
> delete_vertex(K5,[2,3])
an undirected unweighted graph with 3 vertices and 3 edges

2.3. Modifying edges of a graph
2.3.1. Adding and removing edges
For adding and removing edges or arcs to/from graphs use the commands add_edge or add_arc
and delete_edge or delete_arc, respectively.
Syntax: add_edge(G,e|E|T)
add_arc(G,e|E|T)
delete_edge(G,e|E|T)
delete_arc(G,e|E|T)
The command add_edge accepts two arguments, an undirected graph G and an edge e or a list
of edges E or a trail of edges T (entered as a list of vertices), and returns the copy of G with the
specied edges inserted. Edge insertion implies that its endpoints will be created if they are not
already present in G.
> C4:=cycle_graph(4)
C4: an undirected unweighted graph with 4 vertices and 4 edges
> add_edge(C4,[1,3])
C4: an undirected unweighted graph with 4 vertices and 5 edges
> add_edge(C4,[1,3,5,7])

2.3 Modifying edges of a graph

49

C4: an undirected unweighted graph with 6 vertices and 7 edges
The command add_arc works similarly to add_edge but applies only to directed graphs. Note that
the order of endpoints in an arc matters.
> add_arc(digraph(trail(a,b,c,d,a)),[[a,c],[b,d]])
a directed unweighted graph with 4 vertices and 6 arcs
When adding edge/arc to a weighted graph, its weight should be specied alongside its endpoints,
or it will be assumed that it equals to 1.
> add_edge(graph(%{[[1,2],5],[[3,4],6]%}),[[2,3],7])
an undirected weighted graph with 4 vertices and 3 edges
The commands delete_edge and delete_arc accept two arguments, the input graph G and an
edge/arc e or a list of edges/arcs E or a trail of edges T . It returns a copy of G in which the
specied edges/arcs are removed. Note that this operation does not change the set of vertices of G.
> K33:=relabel_vertices(complete_graph(3,3),[A,B,C,D,E,F])
an undirected unweighted graph with 6 vertices and 9 edges
> has_edge(K33,[A,D])
true
> delete_edge(K33,[A,D])
an undirected unweighted graph with 6 vertices and 8 edges
Note that G itself is not changed.
> has_edge(K33,[B,D])
true
> delete_edge(K33,[[A,D],[B,D]])
an undirected unweighted graph with 6 vertices and 7 edges
> DG:=digraph(trail(1,2,3,4,5,2,4))
a directed unweighted graph with 5 vertices and 6 arcs
> delete_arc(DG,[[2,3],[4,5],[5,2]])
a directed unweighted graph with 5 vertices and 3 arcs
> delete_arc(DG,[3,4,5,2])
a directed unweighted graph with 5 vertices and 3 arcs

2.3.2. Accessing and modifying edge weights
The commands get_edge_weight and set_edge_weight are used to access and modify the weight
of an edge/arc in a weighted graph, respectively.
Syntax: set_edge_weight(G,e,w)
set_edge_weight(G,e)
set_edge_weight accepts three arguments: a weighted graph G(V ; E), edge/arc e 2 E and the
new weight w, which may be any number. It returns the modied copy of G.
The command get_edge_weight accepts two arguments, a weighted graph G(V ; E) and an edge
or arc e 2 E. It returns the weight of e.

50

Modifying graphs

> G:=set_edge_weight(graph(%{[[1,2],4],[[2,3],5]%}),[1,2],6)
an undirected weighted graph with 3 vertices and 2 edges
> get_edge_weight(G,[1,2])
6

2.3.3. Contracting edges
The command contract_edge is used for contracting edges in undirected graphs.
Syntax: contract_edge(G,e)
contract_edge accepts two arguments, an undirected graph G(V ; E) and an edge e = (v; w) 2 E,
and merges v and w to a single vertex, deleting the edge e. The resulting vertex inherits the label
of v. The modied copy of G is returned.
> K5:=complete_graph(5)
an undirected unweighted graph with 5 vertices and 10 edges
> contract_edge(K5,[1,2])
an undirected unweighted graph with 4 vertices and 6 edges
To contract a set fe1; e2; :::; ek g  E of edges in G, none two of which are incident (i.e. when the
given set is a matching in G), one can use the foldl command. In the following example, the
complete graph K5 is obtained from Petersen graph by edge contraction.
> P:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> G:=foldl(contract_edge,P,[0,5],[1,6],[2,7],[3,8],[4,9])
an undirected unweighted graph with 5 vertices and 10 edges
> draw_graph(G)
0

4

1

3

2

2.3.4. Subdividing edges
The command subdivide_edges is used for graph subdivision.
Syntax: subdivide_edges(G,e|S)
subdivide_edges(G,e|S,r)
subdivide_edges accepts two or three arguments: a graph G(V ; E), a single edge/arc e 2 E or
a list of edges/arcs S  E and optionally a positive integer r (which defaults to 1). Each of the
specied edges/arcs will be subdivided with exactly r new vertices, labeled with the smallest
available nonnegative integers. The resulting graph, which is homeomorphic to G, is returned.
If the endpoints of the edge being subdivided have valid coordinates, the coordinates of the inserted
vertices will be computed accordingly.
> G:=graph("petersen")

2.4 Using attributes

51

an undirected unweighted graph with 10 vertices and 15 edges
> G:=subdivide_edges(G,[2,3])
an undirected unweighted graph with 11 vertices and 16 edges
> G:=subdivide_edges(G,[[1,2],[3,4]])
an undirected unweighted graph with 13 vertices and 18 edges
> G:=subdivide_edges(G,[0,1],2)
an undirected unweighted graph with 15 vertices and 20 edges
> draw_graph(G)
0
13
5
14
4

1
9

6
11

12
8
3

7
10

2

2.4. Using attributes
2.4.1. Graph attributes
The graph structure maintains a set of attributes as tag-value pairs which can be accessed
and/or modified by using the commands set_graph_attribute, get_graph_attribute,
list_graph_attributes and discard_graph_attribute.
Syntax: set_graph_attribute(G,tag1=value1,tag2=value2,...)
set_graph_attribute(G,[tag1=value1,tag2=value2,...])
set_graph_attribute(G,[tag1,tag2,...],[value1,value2,...])
get_graph_attribute(G,tag1,tag2,...)
get_graph_attribute(G,[tag1,tag2,...])
list_graph_attributes(G)
discard_graph_attribute(G,tag1,tag2,...)
discard_graph_attribute(G,[tag1,tag2,...])
The command set_graph_attribute is used for modifying the existing graph attributes or adding
new ones. It accepts two arguments, a graph G and a sequence or list of graph attributes in form
tag=value where tag is a string. Alternatively, attributes may be specied as a sequence of two
lists [tag1,tag2,...] and [value1,value2,...]. The command sets the specied values to the
indicated attribute slots, which are meant to represent some global properties of the graph G, and
returns the modied copy of G.
The previously set graph attribute values can be fetched with the command get_graph_attribute
which accepts two arguments: a graph G and a sequence or list of tags. The corresponding values
will be returned in a sequence or list, respectively. If some attribute is not set, undef is returned
as its value.
To list all graph attributes of G for which the values are set, use the list_graph_attributes
command which takes G as its only argument.
To discard a graph attribute, use the discard_graph_attribute command. It accepts two arguments: a graph G and a sequence or list of tags to be cleared, and returns the modied copy of G.
Two tags being used by the CAS commands are directed and weighted, so it is not advisable
to overwrite their values using this command; use the make_directed, make_weighted and
underlying_graph commands instead. Another attribute used internally is name, which holds
the name of the respective graph (as a string).

52

Modifying graphs

> G:=digraph(trail(1,2,3,1))
a directed unweighted graph with 3 vertices and 3 arcs
> G:=set_graph_attribute(G,"name"="C3","message"="this is some text")
C3: a directed unweighted graph with 3 vertices and 3 arcs
> get_graph_attribute(G,"message")
this is some text
> list_graph_attributes(G)
[directed = true; weighted = false; name = C3; message = this is some text]
> G:=discard_graph_attribute(G,"message")
C3: a directed unweighted graph with 3 vertices and 3 arcs
> list_graph_attributes(G)
[directed = true; weighted = false; name = C3]

2.4.2. Vertex attributes
For every vertex of a graph, the list of attributes in form of tag-value pairs is maintained, which can
be accessed/modied by using the commands set_vertex_attribute, get_vertex_attribute,
list_vertex_attributes and discard_vertex_attribute.
Syntax: set_vertex_attribute(G,v,tag1=value1,tag2=value2,...)
set_vertex_attribute(G,v,[tag1=value1,tag2=value2,...])
set_vertex_attribute(G,v,[tag1,tag2,...],[value1,value2,...])
get_vertex_attribute(G,v,tag1,tag2,...)
get_vertex_attribute(G,v,[tag1,tag2,...])
list_vertex_attributes(G,v)
discard_vertex_attribute(G,v,tag1,tag2,...)
discard_vertex_attribute(G,v,[tag1,tag2,...])
The command set_vertex_attribute is used for modifying the existing vertex attributes or
adding new ones. It accepts three arguments, a graph G(V ; E), a vertex v 2 V and a sequence or
list of attributes in form tag=value where tag is a string. Alternatively, attributes may be specied
as a sequence of two lists [tag1,tag2,...] and [value1,value2,...]. The command sets the
specied values to the indicated attributes of the vertex v and returns the modied copy of G.
The previously set attribute values for v can be fetched with the command get_vertex_attribute
which accepts three arguments: G, v and a sequence or list of tags. The corresponding values will
be returned in a sequence or list, respectively. If some attribute is not set, undef is returned as
its value.
To list all attributes of v for which the values are set, use the list_vertex_attributes command
which takes two arguments, G and v.
The discard_vertex_attribute command is used for discarding attribute(s) assigned to some
vertex v 2 V . It accepts three arguments: G, v and a sequence or list of tags to be cleared, and
returns the modied copy of G.
The attributes label, color, shape and pos are also used internally. These hold the vertex label, color,
shape and coordinates in a drawing, respectively. If the color is not set for a vertex, the latter is
drawn in yellow. The shape attribute may have one of the following values: square, triangle, diamond,
star or plus. If the shape attribute is not set or has a dierent value, the circled shape is applied
when drawing the vertex.
The following example shows how to change individual labels and colors.

2.4 Using attributes

53

> T:=complete_binary_tree(3)
an undirected unweighted graph with 15 vertices and 14 edges
> T:=set_vertex_attribute(T,5,"label"="root","color"=red)
an undirected unweighted graph with 15 vertices and 14 edges
> draw_graph(T,tree="root")
root
2

11

0
1
3
7

12

6
13

14
4

8

9

10

A vertex may also hold custom attributes.
> T:=set_vertex_attribute(T,"root","depth"=3,"shape"="square")
an undirected unweighted graph with 15 vertices and 14 edges
> list_vertex_attributes(T,"root")
[label = root; color = r e d; shape = square; depth = 3]
> T:=discard_vertex_attribute(T,"root","color")
an undirected unweighted graph with 15 vertices and 14 edges
> list_vertex_attributes(T,"root")
[label = root; shape = square; depth = 3]

2.4.3. Edge attributes
For every edge of a graph, the list of attributes in form of key-value pairs is maintained, which can
be accessed and/or modied by using the commands set_edge_attribute, get_edge_attribute,
list_edge_attributes and discard_edge_attribute.
Syntax: set_edge_attribute(G,e,tag1=value1,tag2=value2,...)
set_edge_attribute(G,e,[tag1=value1,tag2=value2,...])
set_edge_attribute(G,e,[tag1,tag2,...],[value1,value2,...])
get_edge_attribute(G,e,tag1,tag2,...)
get_edge_attribute(G,e,[tag1,tag2,...])
list_edge_attributes(G,e)
discard_edge_attribute(G,e,tag1,tag2,...)
discard_edge_attribute(G,e,[tag1,tag2,...])
The command set_edge_attribute is used for modifying the existing edge attributes or adding
new ones. It accepts three arguments, a graph G(V ; E), an edge/arc e 2 E and a sequence or list
of attributes in form tag=value where tag is a string. Alternatively, attributes may be specied
as a sequence of two lists [tag1,tag2,...] and [value1,value2,...]. The command sets the
specied values to the indicated attributes of the edge/arc e and returns the modied copy of G.
The previously set attribute values for e can be fetched with the command get_edge_attribute
which accepts three arguments: G, e and a sequence or list of tags. The corresponding values will
be returned in a sequence or list, respectively. If some attribute is not set, undef is returned as
its value.
To list all attributes of e for which the values are set, use the list_edge_attributes command
which takes two arguments, G and e.

54

Modifying graphs

To discard attribute(s) assigned to e call the discard_edge_attribute command, which accepts
three arguments: G, e and a sequence or list of tags to be cleared, and returns the modied copy
of G.
The attributes weight, color, style, pos and temp are also used internally. They hold the edge weight,
color, line style, the coordinates of the weight label anchor (and also the coordinates of the arrow)
and true if the edge is temporary. If the color attribute is not set for an edge, the latter is drawn
in blue, unless it is a temporary edge, in which case it is drawn in light gray. The style attribute
may have one of the following values: dashed, dotted or bold. If the style attribute is not set or has
a dierent value, the solid line style is applied when drawing the edge.
The following example illustrates the possibilities of using edge attributes.
> T:=complete_binary_tree(3)
an undirected unweighted graph with 15 vertices and 14 edges
> T:=set_edge_attribute(T,[1,4],"cost"=12.8,"message"="this is some text")
an undirected unweighted graph with 15 vertices and 14 edges
> list_edge_attributes(T,[1,4])
[cost = 12.8; message = this is some text]
> T:=discard_edge_attribute(T,[1,4],"message")
an undirected unweighted graph with 15 vertices and 14 edges
> T:=set_edge_attribute(T,[1,4],"style"="dotted","color"=magenta)
an undirected unweighted graph with 15 vertices and 14 edges
> list_edge_attributes(T,[1,4])
[color = m a g e n t a; style = dotted; cost = 12.8]
> T:=set_edge_attribute(T,[5,11],"temp"=true)
an undirected unweighted graph with 15 vertices and 14 edges
> draw_graph(T)
0
1

2

3

7

4

8

9

5

10 11

6

12 13

14

Chapter 3
Import and export
3.1. Importing graphs
3.1.1. Loading graphs from dot les
The command import_graph is used for importing a graph from text le in dot format.
Syntax: import_graph(filename)
import_graph accepts a string filename as its only argument and returns the graph constructed
from instructions written in the le filename or undef on failure. The passed string should contain
the path to a le in dot format. The le extension .dot may be omitted in the filename since dot
is the only supported format. The alternative extension is .gv3.1, which must be explicitly specied.
If a relative path to the le is specied, i.e. if it does not contain a leading forward slash, the
current working directory (which can be obtained by calling the pwd command) will be used as the
reference. The working directory can be changed by using the command cd.
For example, assume that the le example.dot is saved in the directory Documents/dot/ with the
following contents:
graph "Example graph" {
a [label="Foo"];
b [shape=diamond,color=red];
a -- b [style=bold];
b -- c [color=green];
b -- d [style=dotted];
}
To import the graph, input:
> G:=import_graph("Documents/dot/example.dot")
Example graph: an undirected unweighted graph with 4 vertices and 3 edges
> draw_graph(G)
Foo

b

c

d

3.1.2. The dot le format overview
Giac has some basic support for dot language. Each dot le is used to hold exactly one graph and
should consist of a single instance of the following environment:

strict? (graph | digraph) name? {
...
}
3.1. Although it is recommended to use .gv as the extension for dot les to avoid a certain confusion between dierent
le types, Giac uses the .dot extension because it coincides with the format name. This may change in the future.

55

56

Import and export

The keyword strict may be omitted, as well as the name of the graph, as indicated by the question
marks. The former is used to dierentiate between simple graphs (strict) and multigraphs (nonstrict). Since Giac supports only simple graphs, strict is redundant.
For specifying undirected graphs the keyword graph is used, while the digraph keyword is used
for undirected graphs.
The graph/digraph environment contains a series of instructions describing how the graph should
be built. Each instruction ends with the semicolon (;) and has one of the following forms.
syntax
creates
vertex_name [attributes]?
isolated vertices
V1  V2  :::  Vk [attributes]? edges and trails
graph [attributes]
graph attributes
Here, attributes is a comma-separated list of tag-value pairs in form tag=value,  is
-- for undirected and -> for directed graphs. Each of V1, V2 etc. is either a vertex name or a set
of vertex names in form {vertex_name1 vertex_name2 ...}. In the case a set is specied, each
vertex from that set is connected to the neighbor operands. Every specied vertex will be created
if it does not exist yet.
Any line beginning with # is ignored. C-like line and block comments are recognized and skipped
as well.
Using the dot syntax it is easy to specify a graph with adjacency lists. For example, the following
is the contents of a le which denes the octahedral graph with 6 vertices and 12 edges.
# octahedral graph
graph "octahedron" {
1 -- {3 6 5 4};
2 -- {3 4 5 6};
3 -- {5 6};
4 -- {5 6};
}

3.2. Exporting graphs
The command export_graph is used for saving graphs to disk in dot or LATEX format.
Syntax: export_graph(G,filename)
export_graph(G,filename,latex[=])

3.2.1. Saving graphs in dot format
export_graph accepts two mandatory arguments, a graph G and a string filename, and writes G
to the le specied by filename, which must be a path to the le, either relative or absolute; in
the former case the current working directory will be used as the reference. If only two arguments
are given the graph is saved in dot format. The le name may be entered with or without .dot
extension. The command returns 1 on success and 0 on failure.
> export_graph(G,"Documents/dot/copy_of_example")
1

3.2.2. Saving graph drawings in LATEX format
When calling the export_graph command, an optional third argument in form latex[=]
may be given. In that case the drawing of G (obtained by calling the draw_graph command) will
be saved to the LATEX le indicated by filename (the extension .tex may be omitted). Optionally,
one can specify a parameter or list of parameters params which will be passed to the draw_graph
command.

3.2 Exporting graphs

57

For example, let us create a picture of the Sierpi«ski sieve graph of order n = 5, i.e. the graph ST35.
> G:=sierpinski_graph(5,3,triangle)
an undirected unweighted graph with 123 vertices and 243 edges
> export_graph(G,"Documents/st53.tex",latex=[spring,labels=false])
1
The LATEX le obtained by exporting a graph is easily converted into an EPS le, which can
subsequently be inserted3.2 in a paper, report or some other document. A Linux user simply needs
to launch a terminal emulator, navigate to the directory in which the exported le, in this case
st53.tex, is stored and enter the following command:
latex st53.tex && dvips st53.dvi && ps2eps st53.ps
This will produce the (properly cropped) st53.eps le in the same directory. Afterwards, it is
recommended to enter
rm st53.tex st53.aux st53.log st53.dvi st53.ps
to delete the intermediate les. The above two commands can be combined in a simple shell script
which takes the name of the exported le (without the extension) as its input argument:
#!/bin/bash
# convert LaTeX to EPS
latex $1.tex
dvips $1.dvi
ps2eps $1.ps
rm $1.tex $1.aux $1.log $1.dvi $1.ps
Assuming that the script is stored under the name latex2eps in the same directory as st53.tex,
to do the conversion it is enough to input:
bash latex2eps st53
The drawing produced in our example is shown in Figure 3.1.
b
b

b
b
b

b

b
b
b

b

b
b

b

b
b

b
b

b
b

b
b

b
b

b

b

b
b

b

b

b

b
b
b

b
b

b
b

b
b
b

b
b

b

b
b

b

b
b

b

b
b

b

b
b

b
b

b

b
b

b
b

b
b

b

b
b

b
b
b
b

b
b

b
b

b
b

b

b
b

b
b

b
b

b
b

b
b

b
b

b

b
b

b

b

b

b
b

b
b

b

b
b
b

b

b
b

b

Fig. 3.1. drawing of the Sierpi«ski graph

b

b

b
b

b

b

ST35

b

b
b

b
b

b
b

b
b

b

using LATEX and PSTricks

3.2. Alternatively, a PSTricks picture from the body of the .tex le can be copied to some other LATEX document.

Chapter 4
Graph properties
4.1. Basic properties
4.1.1. Determining the type of a graph
The commands is_directed and is_weighted are used for determining the type of a graph:
whether is it directed or not resp. weighted or not.
Syntax: is_directed(G)
is_weighted(G)
Both commands accept a graph G as their only argument. is_directed resp. is_weighted returns
true if G is directed resp. weighted, else it returns false.
> G:=graph(trail(1,2,3,4,5,1,3))
an undirected unweighted graph with 5 vertices and 6 edges
> is_directed(G)
false
> is_directed(make_directed(G))
true
> is_weighted(G)
false
> is_weighted(make_weighted(G,randmatrix(5,5,99)))
true

4.1.2. Listing vertices and edges
The command vertices or graph_vertices resp. edges is used for extracting set of vertices
resp. set of edges from a graph. To obtain the number of vertices resp. the number of edges, use
the number_of_vertices resp. the number_of_edges command.
Syntax: vertices(G)
graph_vertices(G)
edges(G)
edges(G,weights)
number_of_vertices(G)
number_of_edges(G)
vertices or graph_vertices accepts a graph G(V ; E) as its only argument and returns the set
of vertices V in the same order in which they were created.
edges accepts one or two arguments, a graph G(V ; E) and optionally the identier weights. The
command returns the set of edges E (in a non-meaningful order). If weights is specied, each edge
is paired with the corresponding weight (in this case G must be a weighted graph).
number_of_vertices resp. number_of_edges accepts the input graph G(V ; E) as its only argument and returns jV j resp. jE j.
59

60

Graph properties

> G:=hypercube_graph(2)
an undirected unweighted graph with 4 vertices and 4 edges
> vertices(G)
[00; 01; 10; 11]
> C:=graph("coxeter")
an undirected unweighted graph with 28 vertices and 42 edges
> vertices(C)
[a1; a2; a7; z1; a3; z2; a4; z3; a5; z4; a6; z5; z6; z7; b1; b3; b6; b2; b4; b7; b5; c1; c4; c5; c2; c6; c3; c7]
> number_of_vertices(C), number_of_edges(C)
28; 42
> H:=digraph([[0,2.32,0,0.25],[0,0,0,1.32],[0,0.50,0,0],[0.75,0,3.34,0]])
a directed weighted graph with 4 vertices and 6 arcs
> edges(H)
f[0; 1]; [0; 3]; [1; 3]; [2; 1]; [3; 0]; [3; 2]g
> edges(H,weights)
f[[0; 1]; 2.32]; [[0; 3]; 0.25]; [[1; 3]; 1.32]; [[2; 1]; 0.5]; [[3; 0]; 0.75]; [[3; 2]; 3.34]g

4.1.3. Equality of graphs
Two graphs are considered equal if they are both (un)weighted and (un)directed and if the commands vertices and edges give the same results for both graphs. To determine whether two
graphs are equal use the command graph_equal.
Syntax: graph_equal(G1,G2)
graph_equal accepts two arguments, graphs G1 and G2, and returns true if G1 is equal to G2
with respect to the above denition. Else, it returns false.
> G1:=graph([1,2,3],%{[1,2],[2,3]%})
an undirected unweighted graph with 3 vertices and 2 edges
> G2:=graph([1,3,2],%{[1,2],[2,3]%})
an undirected unweighted graph with 3 vertices and 2 edges
> graph_equal(G1,G2)
false
> G3:=graph(trail(1,2,3))
an undirected unweighted graph with 3 vertices and 2 edges
> graph_equal(G1,G3)
true
> G4:=digraph(trail(1,2,3))
a directed unweighted graph with 3 vertices and 2 arcs
> graph_equal(G1,G4)
false

4.1 Basic properties

61

4.1.4. Vertex degrees
The command vertex_degree is used for computing the degree of a vertex, i.e. counting the vertices
adjacent to it. The related specialized commands are vertex_out_degree, vertex_in_degree,
degree_sequence, minimum_degree and maximum_degree.
Syntax: vertex_degree(G,v)
vertex_in_degree(G,v)
vertex_out_degree(G,v)
degree_sequence(G)
minimum_degree(G,v)
maximum_degree(G,v)
vertex_degree accepts two arguments, a graph G(V ; E) and a vertex v 2 V , and returns the
cardinality of the set fw 2 V : (v; w) 2 E g, i.e. the number of vertices in V which are adjacent to
v. Note that the edge directions are ignored in case G is a digraph.
When dealing with directed graphs, one can also use the specialized command vertex_out_degree
resp. vertex_in_degree which accepts the same arguments as vertex_degree but returns the
number of arcs (v; w) 2 E resp. the number of arcs (w; v) 2 E, where w 2 V .

To obtain the list of degrees of all vertices v 2 V , use the degree_sequence command which accepts
a graph G(V ; E) as its only argument and returns the list of degrees of vertices from V in the same
order as returned by the command vertices. If G is a digraph, arc directions are ignored.
To compute the minimum vertex degree (G) or the maximum vertex degree (G) in an undirected
graph G, use the command minimum_degree or maximum_degree, respectively. Both commands
accept G as the only argument and return (G) resp. (G).
> G:=graph(trail(1,2,3,4,1,5,6,7,1,8,9,4))
an undirected unweighted graph with 9 vertices and 11 edges
> draw_graph(G)

> vertex_degree(G,1)
5
> degree_sequence(G)
[5; 2; 2; 3; 2; 2; 2; 2; 2]
> T:=random_tournament([1,2,3,4,5])
a directed unweighted graph with 5 vertices and 10 arcs
> draw_graph(T)

> vertex_out_degree(T,1)

62

Graph properties

3
> vertex_in_degree(T,5)
2
The command line below shows that Petersen graph is cubic (3-regular).
> P:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> minimum_degree(P), maximum_degree(P)
3; 3
> is_regular(P,3)
true

4.1.5. Regular graphs
The command is_regular is used for determining whether the given graph is regular.
Syntax: is_regular(G)
is_regular(G,d)
is_regular accepts one or two arguments, a graph G(V ; E) and optionally a nonnegative integer
or an unassigned identier d. If G is undirected, the return value is true if G = G, i.e. if the
minimal vertex degree is equal to the maximal vertex degree in G, otherwise false is returned.
If G is a digraph, it is also required for each vertex v 2 V to have the same in- and out-degree. If
the second argument is given, G is tested for d-regularity in case d is an integer, otherwise G is
written to d in case the latter is an identier and G is regular.
The complexity of the algorithm is O(jV j).
> G:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> is_regular(G,d)
true
> d
3
> is_regular(G,2)
false
> is_regular(graph("grotzsch"))
false
> G:=digraph(%{[1,5],[1,6],[2,3],[2,4],[3,1],[3,4],[4,1],[4,5],[5,2],[5,6],[6,
2],[6,3]%})
a directed unweighted graph with 6 vertices and 12 arcs
> draw_graph(G,spring)
6

2

3

5

1

4

4.1 Basic properties

63

> is_regular(G,4)
true
> H:=add_arc(delete_arc(G,[5,6]),[6,5])
a directed unweighted graph with 6 vertices and 12 arcs
> is_regular(H,4)
false
> is_regular(underlying_graph(H))
true

4.1.6. Strongly regular graphs
The command is_strongly_regular is used for determining whether the given graph is
strongly regular.

Syntax: is_strongly_regular(G)
is_strongly_regular(G,srg)
is_strongly_regular accepts one or two arguments, a graph G(V ; E) and optionally an unassigned identier srg. It returns true if G is regular and there are integers  and  such that every
two adjacent vertices resp. non-adjacent vertices in V have exactly  resp.  common neighbors.
Else, it returns false. If the second argument is given, the list [k; ; ], where k is the degree of
G, is stored to srg.
The complexity of the algorithm is O(k jV j2).
> G:=graph("clebsch")
an undirected unweighted graph with 16 vertices and 40 edges
> is_regular(G)
true
> is_strongly_regular(G)
true
> H:=graph("shrikhande")
an undirected unweighted graph with 16 vertices and 48 edges
> is_strongly_regular(H,s)
true
> s
[6; 2; 2]
> is_strongly_regular(cycle_graph(5))
true
> is_strongly_regular(cycle_graph(6))
false

4.1.7. Vertex adjacency
The command has_edge is used for checking whether two vertices in an undirected graph are
adjacent. For digraphs, there is an analogous command has_arc.

64

Graph properties

The command neighbors is used for obtaining the list of vertices in a graph that are adjacent to
the particular vertex or the complete adjacency structure of the graph, in sparse form.
The command departures resp. arrivals is used for obtaining all neighbors of a vertex v in a
digraph which are the heads resp. the tails of the corresponding arcs.
Syntax: has_edge(G,[u,v])
has_arc(G,[u,v])
neighbors(G)
neighbors(G,v)
departures(G)
departures(G,v)
arrivals(G)
arrivals(G,v)
has_edge accepts two arguments, an undirected graph G(V ; E) and a list [u,v] where u; v 2 V .
The command returns true if uv 2 E and false otherwise. The syntax for has_arc is the same,
except now G is required to be directed. Note, however, that the order of vertices u and v matters
in digraphs. The complexity of both algorithms is O(log jV j).
neighbors accepts one or two arguments, a graph G(V ; E) and optionally a vertex v 2 V . The
command returns the list of neighbors of v in G if v is given. Otherwise, it returns the list of lists
of neighbors for all vertices in V , in order of vertices(G). Note that edge directions are ignored
in case G is a digraph.
departures resp. arrivals accepts one or two arguments, a digraph G(V ; E) and optionally a
vertex v 2 V , and returns the list Lv containing all vertices w 2 V for which vw 2 E resp. wv 2 E.
If v is omitted, the list of lists Lv for every v 2 V is returned.
> G:=graph(trail(1,2,3,4,5,2))
an undirected unweighted graph with 5 vertices and 5 edges
> has_edge(G,[1,2])
true
> has_edge(G,[2,1])
true
> has_edge(G,[1,3])
false
> D:=digraph(trail(1,2,3,4,5,2,1))
a directed unweighted graph with 5 vertices and 6 arcs
> has_arc(D,[1,2])
true
> has_arc(D,[2,1])
true
> has_arc(D,%{1,2%})
true
> has_arc(D,[4,5])
true
> has_arc(D,[5,4])
false
> has_arc(D,%{4,5%})

4.1 Basic properties

65

false
> neighbors(G,3)
[2; 4]
> neighbors(G)
f[2]; [1; 3; 5]; [2; 4]; [3; 5]; [2; 4]g
> G:=digraph(trail(1,2,3,4,2,5,1,6,7,8,4))
a directed unweighted graph with 8 vertices and 10 arcs
> draw_graph(G,spring)
7
8

6

4

1

2
3

5

> departures(G,2); arrivals(G,2); departures(G,1); arrivals(G,1)
[3; 5]; [1; 4]; [2; 6]; [5]

4.1.8. Tournament graphs
The command is_tournament is used for determining whether the given graph is a tournament.
Syntax: is_tournament(G)
is_tournament accepts a graph G(V ; E) as its only argument and returns true if G is directed and
for each pair of vertices u; v 2 V it is either uv 2 E or vu 2 E, i.e. there is exactly one arc between
u and v. Else, it returns false.
> T1:=digraph(%{[1,2],[2,3],[3,1]%})
a directed unweighted graph with 3 vertices and 3 arcs
> is_tournament(T1)
true
> T2:=digraph(%{[1,2],[2,3],[3,1],[1,3]%})
a directed unweighted graph with 3 vertices and 4 arcs
> is_tournament(T2)
false

4.1.9. Bipartite graphs
The command is_bipartite is used for determining if the given graph is bipartite.
Syntax: is_bipartite(G)
is_bipartite(G,P)
is_bipartite accepts one or two arguments, a graph G(V ; E) and optionally an unassigned
identier P. It returns true if there is a partition of V into two sets S and T such that every edge
from E connects a vertex in S to one in T . Else, it returns false. If the second argument is given
and G is bipartite, the partition of V is stored to P as a list of two lists of vertices, the rst one
containing the vertices from S and the second one containing vertices from T .

66

Graph properties

> K32:=complete_graph(3,2)
an undirected unweighted graph with 5 vertices and 6 edges
> is_bipartite(K32,bp)
true
> bp
[[0; 1; 2]; [3; 4]]
> draw_graph(K32,bipartite)
0

1

2

3

4

> adjacency_matrix(K32)
0
B
B
B
B
@

> G:=cycle_graph(5)

0
0
0
1
1

0
0
0
1
1

0
0
0
1
1

1
1
1
0
0

1
1
1
0
0

1
C
C
C
C
A

an undirected unweighted graph with 5 vertices and 5 edges
> is_bipartite(G)
false

4.1.10. Edge incidence
The command incident_edges is used for obtaining edges incident to the given vertex in a graph.
Syntax: indcident_edges(G,v)
indcident_edges(G,L)
incident_edges accepts two argument, a graph G(V ; E) and a vertex v 2 V or a list of vertices
L  V . The command returns the list of edges e1; e2; :::; ek 2 E which have v as one of its endpoints.
Note that edge directions are ignored when G is a digraph. To obtain only outgoing or incoming
edges, use the commands departures and arrivals, respectively.
> G:=cycle_graph([1,2,3,4,5])
C5: an undirected unweighted graph with 5 vertices and 5 edges
> incident_edges(G,1)
f[1; 2]; [1; 5]g
> incident_edges(G,[2,4,5])
f[1; 2]; [1; 5]; [2; 3]; [3; 4]; [4; 5]g
> G:=random_tournament([1,2,3,4,5])
a directed unweighted graph with 5 vertices and 10 arcs
> incident_edges(G,2)

4.2 Algebraic properties

67

f[2; 1]; [2; 3]; [2; 5]; [4; 2]g

4.2. Algebraic properties
4.2.1. Adjacency matrix
The command adjacency_matrix is used for obtaining the adjacency matrix of a graph.
Syntax: adjacency_matrix(G)
adjacency_matrix accepts a graph G(V ; E), where V = fv1; v2; :::; vng, as its only argument and
returns the square matrix A = [aij ] of order n such that, for i; j = 1; 2; :::; n,
aij =

(

1, if the set E contains edge/arc vi vj ,
0; otherwise:

Note that tr (A) = 0. Also, the adjacency matrix of an undirected graph is always symmetrical.
> G:=graph("octahedron")
an undirected unweighted graph with 6 vertices and 12 edges
> A:=adjacency_matrix(G)
0
B
B
B
B
B
B
@

> transpose(A)==A

0
1
1
1
1
0

1
0
1
1
0
1

1
1
0
0
1
1

1
1
0
0
1
1

1
0
1
1
0
1

0
1
1
1
1
0

1
C
C
C
C
C
C
A

true
> D:=digraph(trail(1,2,3,4,5,2,6,7,3,8,1))
a directed unweighted graph with 8 vertices and 10 arcs
> draw_graph(D)
1

3

5

6

2

4

7

8

> A:=adjacency_matrix(D)
0
B
B
B
B
B
B
B
B
B
B
@

0
0
0
0
0
0
0
1

1
0
0
0
1
0
0
0

0
1
0
0
0
0
1
0

0
0
1
0
0
0
0
0

0
0
0
1
0
0
0
0

0
1
0
0
0
0
0
0

0
0
0
0
0
1
0
0

0
0
1
0
0
0
0
0

1
C
C
C
C
C
C
C
C
C
C
A

68

Graph properties

> transpose(A)==A
false

4.2.2. Laplacian matrix
The command laplacian_matrix is used for computing the Laplacian matrix of a graph.
Syntax: laplacian_matrix(G)
laplacian_matrix(G,normal)
laplacian_matrix accepts an undirected graph G(V ; E), where V = fv1; v2; :::; vng, and returns
the symmetric matrix L = D ¡ A, where A is the adjacency matrix of G and
0

B
B
D =B
@

deg(v1)
0
0
deg(v2)




0
0

0
0


0


0

0




 deg(vn)

1

C
C
C:
A

The option normal may be passed as the second argument. In that case, the normalized Laplacian
Lsym := I ¡ D ¡1/2 A D ¡1/2 of G is returned.
> G:=path_graph(4)
an undirected unweighted graph with 4 vertices and 3 edges
> A:=adjacency_matrix(G)
0

0
B 1
B
@ 0
0

> L:=laplacian_matrix(G)

1
0
1
0

1
0
0 C
C
1 A
0

0
1
0
1

0

1
1 ¡1 0 0
B ¡1 2 ¡1 0 C
B
C
@ 0 ¡1 2 ¡1 A
0 0 ¡1 1

> diag(degree_sequence(G))-A==L

true
> laplacian_matrix(G,normal)
0
B
B
B
B
B
B
B
B
B
B
B
@

1

¡1
p
2

0

1

0 C
C
C
¡1
¡1
p
1
0 C
C
2
C
2
C
¡1
¡1 C
0
1 p C
2
2 C
C
¡1
A
0
0 p
1
2

The smallest eigenvalue of a Laplacian matrix of an undirected graph is always zero. Moreover,
its multiplicity is equal to the number of connected components in the corresponding graph [23,
pp. 280].

4.2 Algebraic properties

69

> sort(eigenvals(L))
p
p
0; ¡ 2 + 2; 2; 2 + 2
> H:=disjoint_union(complete_graph(4),cycle_graph(3),path_graph(2))
an undirected unweighted graph with 9 vertices and 10 edges
> draw_graph(H,labels=false)

> eigenvals(laplacian_matrix(H))
0; 0; 0; 4; 4; 4; 3; 3; 2
> nops(connected_components(H))
3

4.2.3. Incidence matrix
The command incidence_matrix is used for obtaining the incidence matrix of a graph.
Syntax: incidence_matrix(G)
incidence_matrix accepts a graph G(V ; E), where V = fv1; v2; :::; vng and E = fe1; e2; :::; emg, as
its only argument and returns the n  m matrix B = [bij ] such that, for all i = 1; 2; :::; n and j = 1;
2; :::; m,
(
1; if the vertex vi is incident to the edge ej ,
bij =
0; otherwise
if G is undirected resp.

bij =
if G is directed.

8
>
<

1; if the vertex vi is the head of the arc ej ,
¡1; if the vertex vi is the tail of the arc ej ,
>
: 0; otherwise

> K4:=complete_graph([1,2,3,4])
an undirected unweighted graph with 4 vertices and 6 edges
> edges(K4)
f[1; 2]; [1; 3]; [1; 4]; [2; 3]; [2; 4]; [3; 4]g
> incidence_matrix(K4)
0

1
B 1
B
@ 0
0

1
0
1
0

1
0
0
1

0
1
1
0

0
1
0
1

1
0
0 C
C
1 A
1

> DG:=digraph(trail(1,2,3,4,5,3),trail(1,5,2,4,1))
a directed unweighted graph with 5 vertices and 9 arcs

70

Graph properties

> draw_graph(DG)
1

5

2

4

3

> edges(DG)
f[1; 2]; [1; 5]; [2; 3]; [2; 4]; [3; 4]; [4; 1]; [4; 5]; [5; 2]; [5; 3]g
> incidence_matrix(DG)
0
B
B
B
B
@

¡1 ¡1 0 0 0 1 0 0 0
1 0 ¡1 ¡1 0 0 0 1 0
0 0 1 0 ¡1 0 0 0 1
0 0 0 1 1 ¡1 ¡1 0 0
0 1 0 0 0 0 1 ¡1 ¡1

1
C
C
C
C
A

4.2.4. Weight matrix
The command weight_matrix is used for obtaining the weight matrix of a weighted graph.
Syntax: weight_matrix(G)
weight_matrix accepts a graph G(V ; E), where V = fv1; v2; :::; vng, as its only argument and
returns the square matrix M = [mij ] of order n such that mij equals zero if vi and vj are not
adjacent and the weight of the edge/arc vi vj otherwise, for all i; j = 1; 2; :::; n (note that the weight
of an edge/arc may be any real number).
Note that tr (M ) = 0. Also, the weight matrix of an undirected graph is always symmetrical.
> G:=graph(%{[[1,2],1],[[2,3],2],[[4,5],3],[[5,2],4]%})
an undirected weighted graph with 5 vertices and 4 edges
> weight_matrix(G)
0
B
B
B
B
@

0
1
0
0
0

1
0
2
0
4

0
2
0
0
0

0
0
0
0
3

0
4
0
3
0

1
C
C
C
C
A

4.2.5. Characteristic polynomial
The command graph_charpoly or charpoly is used for obtaining the characteristic polynomial
of an undirected graph.
Syntax: graph_charpoly(G)
graph_charpoly(G,x)
charpoly(G)
charpoly(G,x)
graph_charpoly or charpoly accepts one or two arguments, an undirected graph G(V ; E) and
optionally a value or symbol x. The command returns p(x), where p is the characteristic polynomial
of the adjacency matrix of G.

4.2 Algebraic properties

71

> G:=graph(%{[1,2],[2,3]%})
an undirected unweighted graph with 3 vertices and 2 edges
> charpoly(G,x)
x3 ¡ 2 x

> charpoly(G,3)

21
> G:=graph("shrikhande")
an undirected unweighted graph with 16 vertices and 48 edges
> charpoly(G,x)

x16 ¡ 48 x14 ¡ 64 x13 + 768 x12 + 1536 x11 ¡ 5888 x10 ¡ 15360 x9 + 23040 x8 + 81920 x7 ¡
36864 x6 ¡ 245760 x5 ¡ 32768 x4 + 393216 x3 + 196608 x2 ¡ 262144 x ¡ 196608

4.2.6. Graph spectrum
The command graph_spectrum is used for computing graph spectra.
Syntax: graph_spectrum(G)
graph_spectrum accepts a graph G as its only argument and returns the list in which every element
is an eigenvalue of the adjacency matrix of G paired with its multiplicity.
> C5:=cycle_graph(5)
C5: an undirected unweighted graph with 5 vertices and 5 edges
> gs:=graph_spectrum(C5)
0

> p:=charpoly(C5,x)

> expand(roots(p))==expand(gs)

B
B
B
B
@

1
2
1
p
C
5 ¡1
C
2 C
C
p2
A
¡ 5¡1
2
2

x5 ¡ 5 x3 + 5 x ¡ 2
true

The above result indicates that gs and roots(p) are equal.

4.2.7. Seidel spectrum
The command seidel_spectrum is used for computing Seidel spectra.
Syntax: seidel_spectrum(G)
seidel_spectrum accepts a graph G(V ; E) as its only argument and returns the list in which every
element is an eigenvalue of the Seidel adjacency matrix S paired with its multiplicity. The matrix
S, which can be interpreted as the dierence of the adjacency matrices of G and its complement
Gc, is computed as J ¡ I ¡ 2 A, where J is all-one n  n matrix, I is the identity matrix of order
n, A is the adjacency matrix of G and n = jV j.

72

Graph properties

> seidel_spectrum(graph("clebsch"))


¡3 10
5 6



> seidel_spectrum(graph("levi"))
0
B
B
B
B
@

¡5
¡1
3
5
23

9
10
9
1
1

1
C
C
C
C
A

4.2.8. Integer graphs
The command is_integer_graph is used for determining whether the given graph is an
integral graph.

Syntax: is_integer_graph(G)
is_integer_graph accepts a graph G as its only argument and returns true if the spectrum of
G consists only of integers. Else it returns false.
> G:=graph("levi")
an undirected unweighted graph with 30 vertices and 45 edges
> is_integer_graph(G)
true
> factor(charpoly(G,x))
x10 (x ¡ 3) (x ¡ 2)9 (x + 2)9 (x + 3)
> graph_spectrum(G)
0
B
B
B
B
@

¡3
¡2
0
2
3

1
9
10
9
1

1
C
C
C
C
A

4.3. Graph isomorphism
4.3.1. Isomorphic graphs
The command is_isomorphic is used for determining whether two graphs are isomorphic.
Syntax: is_isomorphic(G1,G2)
is_isomorphic(G1,G2,m)
canonical_labeling(G)
is_isomorphic accepts two or three arguments: a graph G1(V1; E1), a graph G2(V2; E2) and optionally an unassigned identier m. The command returns true if G1 and G2 are isomorphic and
false otherwise. If the third argument is given and G1 and G2 are isomorphic, the list of pairwise
matching of vertices in G1 and G2, representing the isomorphism between the two graphs, is stored
to m.

4.3 Graph isomorphism

73

Note that the algorithm takes vertex colors into account. Namely, only vertices sharing the same
color can be mapped to each other. Vertex colors can be set by calling the highlight_vertex
command.
This command, as well as the commands canonical_labeling and graph_automorphisms described
later in this section, is using nauty library developed by Brendan McKay [35], which is one
of the fastest implementations for graph isomorphism.

For example, entering the command line below one shows that Petersen graph is isomorphic to
Kneser graph K(5; 2).
> is_isomorphic(graph("petersen"),kneser_graph(5,2))
true
In the following example, G1 and G3 are isomorphic while G1 and G2 are not isomorphic.
> G1:=graph(trail(1,2,3,4,5,6,1,3))
an undirected unweighted graph with 6 vertices and 7 edges
> G2:=graph(trail(1,2,3,4,5,6,1,4))
an undirected unweighted graph with 6 vertices and 7 edges
> G3:=graph(trail(1,2,3,4,5,6,1,5))
an undirected unweighted graph with 6 vertices and 7 edges
> draw_graph(G1,circle)
> draw_graph(G2,circle)
> draw_graph(G3,circle)
The drawings are ordered from left to right.
1

2

1

3

6

5

4

2

1

3

6

5

> is_isomorphic(G1,G2)
false
> is_isomorphic(G1,G3)
true
> is_isomorphic(G1,G3,mapping):; mapping
Done; [1 = 5; 2 = 6; 3 = 1; 4 = 2; 5 = 3; 6 = 4]
> H1:=highlight_vertex(G1,5):; H3:=highlight_vertex(G3,5):;
Done; Done
> is_isomorphic(H1,H3)
false
> H1:=highlight_vertex(H1,1):; H3:=highlight_vertex(H3,3):;

> is_isomorphic(H1,H3)
true

3

6

4

Done; Done

2

5

4

74

Graph properties

In the next example, D1 and D3 are isomorphic while D1 and D2 are not isomorphic.
> D1:=digraph(trail(1,2,3,1,4,5))
a directed unweighted graph with 5 vertices and 5 arcs
> D2:=digraph(trail(1,2,3,4,5,3))
a directed unweighted graph with 5 vertices and 5 arcs
> D3:=digraph([1,2,3,4,5],trail(3,4,5,3,1,2))
a directed unweighted graph with 5 vertices and 5 arcs
> draw_graph(D1,circle)
> draw_graph(D2,circle)
> draw_graph(D3,circle)
The drawings are ordered from left to right.
1

1

5

2

4

3

1

5

2

4

3

5

2

4

3

> is_isomorphic(D1,D2)
false
> is_isomorphic(D1,D3)
true
Isomorphism testing with nauty is very fast and can be used for large graphs, as in the example
below.
> G:=random_graph(10000,0.01)
an undirected unweighted graph with 10000 vertices and 499867 edges
> H:=isomorphic_copy(G,randperm(10000))
an undirected unweighted graph with 10000 vertices and 499867 edges
> is_isomorphic(G,H)
true
1.7 sec

To make the edge structures of G and H slightly dierent, a random edge from H is misplaced.
> ed:=edges(H)[rand(number_of_edges(H))]
[813; 3021]
> has_edge(H,[813,3022])
false
> H:=add_edge(delete_edge(H,ed),[813,3022])
an undirected unweighted graph with 10000 vertices and 499867 edges
> is_isomorphic(G,H)
false

4.3 Graph isomorphism

75

4.3.2. Canonical labeling
Graph isomorphism testing in nauty is based on computing the canonical labelings for the input
graphs. The canonical labeling of G is a particular ordering of the vertices of G. Rearranging
the vertices with respect to that ordering produces the canonical representation of G. Two
graphs are isomorphic if and only if their canonical representations share the same edge structure.
The command canonical_labeling is used for computing the canonical labeling as a permutation.
One can reorder the vertices by using this permutation with the isomorphic_copy command.
canonical_labeling accepts a graph G(V ; E) as its only argument and returns the permutation
representing the canonical labeling of G. Note that the colors of the vertices are taken into account.
In the next example it is demonstrated how to prove that G1 and G3 are isomorphic by comparing
their canonical representations C1 and C3 with the graph_equal command. Before testing C1 and
C3 for equality, their vertices have to be relabeled so that the command vertices gives the same
result for both graphs.
> L1:=canonical_labeling(G1)
[4; 3; 5; 1; 2; 0]
> L3:=canonical_labeling(G3)
[2; 1; 3; 5; 0; 4]
> C1:=relabel_vertices(isomorphic_copy(G1,L1),[1,2,3,4,5,6])
an undirected unweighted graph with 6 vertices and 7 edges
> C3:=relabel_vertices(isomorphic_copy(G3,L3),[1,2,3,4,5,6])
an undirected unweighted graph with 6 vertices and 7 edges
> graph_equal(C1,C3)
true

4.3.3. Graph automorphisms
The command graph_automorphisms is used for nding generators of the automorphism group of
a graph.
Syntax: graph_automorphisms(G)
graph_automorphisms accepts a graph G as its only argument and returns a list containing the
generators of Aut(G), the automorphism group of G (see [23, pp. 4] and [5, pp. 115]). Each generator is given as a list of cycles, which can be turned to a permutation by calling the cycles2permu
command.
Note that vertex colors are taken into account. Only vertices sharing the same color can be mapped
to each other. The color of a vertex can be set by calling the highlight_vertex command.
> g:=graph_automorphisms(graph("petersen"))
0
10
0
1 2 6
1
3 7 B
CB 2
3
8
CB
f@ 4 5 A;B
@ 4 5 A;@ 6
8 9
7 9
7
> cycles2permu(g[2])

10
4
0 1
B 2 4
3 C
C;B
9 A@ 5 6
8
7 9

[0; 4; 3; 2; 1; 5; 9; 8; 7; 6]
> G:=graph("petersen")

1

C
Cg
A

76

Graph properties

an undirected unweighted graph with 10 vertices and 15 edges
> G:=highlight_vertex(G,4)
an undirected unweighted graph with 10 vertices and 15 edges
> graph_automorphisms(G)
0

1

0

1
2 6 B
2
f@ 3 9 A;B
@ 3
7 8
6

10
5
0 3
B 1 2
7 C
C;B
9 A@ 5 8
8
6 7

1

C
Cg
A

In the above result, all permutations map the vertex 4 to itself, because it is the single greencolored vertex in G (it cannot be mapped to any other vertex because colors do not match).
Frucht graph (see the page 23) is an example of a graph with automorphism group containing only
the identity, so the set of its generators is empty:
> graph_automorphisms(lcf_graph([-5,-2,-4,2,5,-2,2,5,-2,-5,4,2]))
fg

4.4. Graph polynomials
4.4.1. Tutte polynomial
The command tutte_polynomial is used for computing Tutte polynomials.
Syntax: tutte_polynomial(G)
tutte_polynomial(G,x,y)
tutte_polynomial accepts one or three arguments, an undirected graph G(V ; E) and optionally
two variables or values x and y. It returns the the bivariate Tutte polynomial4.1 TG of G or the
value TG(x; y) if the optional arguments are given. If G is weighted, it is treated as a multigraph:
the weight w of an edge e, which must be a positive integer, is interpreted as the multiplicity of e,
for each e 2 E. Note, however, that loops are not supported.

The strategy is to apply the recursive denition of Tutte polynomial [25] together with the vorder
heuristic proposed by Haggard et al. [26] and improved by Monagan [36]. The subgraphs
appearing in the computation tree are cached and reused when possible, pruning the tree signicantly. Subgraphs are stored (and compared) in their canonical form, for which the nauty library
is used.
Note that nding Tutte polynomials is NP-hard in general, hence the problem becomes intractable
for larger and/or denser graphs.
> K4:=complete_graph(4)
an undirected unweighted graph with 4 vertices and 6 edges
> tutte_polynomial(K4,x,y)
x3 + 3 x2 + 4 x y + 2 x + y 3 + 3 y 2 + 2 y
> tutte_polynomial(K4,x,1)
x3 + 3 x2 + 6 x + 6
> G:=graph("petersen")
4.1. See [25], [5, pp. 97] and [7, pp. 335].

4.4 Graph polynomials

77

an undirected unweighted graph with 10 vertices and 15 edges
> f:=tutte_polynomial(G)
x9 + 6 x8 + 21 x7 + 56 x6 + 12 x5 y + 114 x5 + 70 x4 y + 170 x4 + 30 x3 y 2 + 170 x3 y + 180 x3 +
15 x2 y 3 + 105 x2 y 2 + 240 x2 y + 120 x2 + 10 x y4 + 65 x y 3 + 171 x y 2 + 168 x y + 36 x + y6 + 9 y 5 +
35 y 4 + 75 y 3 + 84 y 2 + 36 y
This result coincides with that in [5, pp. 103], which is supposed to be correct. Alternatively, it
can be veried by applying the recursive denition with an arbitrary edge e 2 E, as below.
> ed:=edges(G)[0]
[0; 1]
> Gdelete:=delete_edge(G,ed)
an undirected unweighted graph with 10 vertices and 14 edges
> Gcontract:=contract_edge(G,ed)
an undirected unweighted graph with 9 vertices and 14 edges
> expand(f-tutte_polynomial(Gdelete)-tutte_polynomial(Gcontract))
0
The value TG(1; 1) is equal to the number of spanning forests in G [7, pp. 345]in this case, the
number of spanning trees in Petersen graph. For verication, the same number is computed by
using the specialized command number_of_spanning_trees, which uses a dierent (much faster)
algorithm.
> tutte_polynomial(G,1,1)
2000
> number_of_spanning_trees(G)
2000
For a graph G and its dual G the following relation holds: TG(x; y) = TG(y; x). Therefore, if
TG(x; y) = TG(y; x) then G and G are isomorphic (since Tutte polynomial is a graph invariant).
A simple example of such graph is tetrahedral graph. Since it is planar and biconnected, its dual
can be determined by using the plane_dual command.


> G:=graph("tetrahedron")
an undirected unweighted graph with 4 vertices and 6 edges
> is_biconnected(G) and is_planar(G)
true
> H:=plane_dual(G)
an undirected unweighted graph with 4 vertices and 6 edges
> T:=tutte_polynomial(G)
x3 + 3 x2 + 4 x y + 2 x + y 3 + 3 y 2 + 2 y
> expand(T-subs(T,[x,y],[y,x]))
0
> is_isomorphic(G,H)
true
Multiple edges can be specied as edge weights.

78

Graph properties

> M:=make_weighted(G)
an undirected weighted graph with 4 vertices and 6 edges
> M:=set_edge_weight(set_edge_weight(M,[1,2],2),[3,4],3)
an undirected weighted graph with 4 vertices and 6 edges
> edges(M,weights)
f[[1; 2]; 2]; [[1; 3]; 1]; [[1; 4]; 1]; [[2; 3]; 1]; [[2; 4]; 1]; [[3; 4]; 3]g
> tutte_polynomial(M,x,y)
x3 + x2 y 2 + 2 x2 y + 3 x2 + 3 x y 3 + 6 x y 2 + 6 x y + 2 x + y 6 + 3 y5 + 6 y 4 + 7 y 3 + 5 y 2 + 2 y

4.4.2. Chromatic polynomial
The command chromatic_polynomial, is used for computing chromatic polynomials.
Syntax: chromatic_polynomial(G)
chromatic_polynomial(G,t)
chromatic_polynomial accepts one or two arguments, an undirected unweighted graph G(V ; E)
and optionally a variable or value t. It returns the chromatic polynomial PG of G or the value
PG(t) if the second argument is given.
PG and the Tutte polynomial TG satisfy the following relation (see [25] and [7, pp. 346]):
PG(t) = (¡1)jV j¡(G) t(G) TG(1 ¡ t; 0);

(4.1)

where (G) is the number of connected components of G. chromatic_polynomial uses (4.1) to
compute PG.
The value PG(k), where k > 0 is an integer, is equal to the number of all distinct k-colorings of
vertices in G. As shown in the example below, Petersen graph cannot be colored by using only two
colors, but is 3-colorable with 120 distinct colorings (all using the same three colors).
> P:=chromatic_polynomial(graph("petersen"),x)
x (x ¡ 2) (x ¡ 1) (x7 ¡ 12 x6 + 67 x5 ¡ 230 x4 + 529 x3 ¡ 814 x2 + 775 x ¡ 352)
> subs(P,x=2)
0
> subs(P,x=3)
120

4.4.3. Flow polynomial
The command flow_polynomial is used for computing ow polynomials.
Syntax: flow_polynomial(G)
flow_polynomial(G,x)
flow_polynomial accepts one or two arguments, an undirected unweighted graph G(V ; E) and
optionally a variable or value x. It returns the ow polynomial QG of G or the value QG(x) if the
second argument is given.
QG and the Tutte polynomial TG satisfy the following relation (see [25] and [5, pp. 110]):
QG(x) = (¡1)jE j¡jV j+(G) TG(0; 1 ¡ x);

(4.2)

4.4 Graph polynomials

79

where (G) is the number of connected components of G. flow_polynomial uses (4.2) to compute
QG.
The value QG(k), where k > 0 is an integer, is equal to the number of all nowhere-zero k-ows
in G. In such ows, the total ow fv entering and leaving vertex v is congruent modulo k, hence
fv 2 f1; 2; :::; k ¡ 1g for all v 2 V [7, pp. 347]. As shown in the example below, Petersen graph has
zero 4-ows and 240 5-ows.
> Q:=flow_polynomial(graph("petersen"))

> Q | x=4

x6 ¡ 15 x5 + 95 x4 ¡ 325 x3 + 624 x2 ¡ 620 x + 240
0

> Q | x=5
240

4.4.4. Reliability polynomial
The command reliability_polynomial is used for computing reliability polynomials.
Syntax: reliability_polynomial(G)
reliability_polynomial(G,p)
reliability_polynomial accepts one or two arguments, an undirected graph G(V ; E) and optionally a variable or value p. It returns the all-terminal reliability polynomial RG of G or the value
RG(p) if the second argument is given. If G is weighted, it is treated as a multigraph: the weight
w of an edge e, which must be a positive integer, is interpreted as the multiplicity of e, for each e 2 E.
RG and the Tutte polynomial TG satisfy the following relation [36]:

RG(p) = (1 ¡ p)jV j¡(G) pjE j¡jV j+(G) TG(1; p¡1);

(4.3)

where (G) is the number of connected components of G. reliability_polynomial uses (4.3) to
compute RG.
If G is a connected network, then the value RG(p), where p 2 [0; 1], is equal to the probability that
G does not fail (i.e. stays connected) after removing each edge with probability p [23, pp. 354355].
In the following example, it is clear that the graph G will stay connected with probability (1 ¡ p)2
if each of its two edges is removed with probability p.
> G:=graph(%{[1,2],[2,3]%})
an undirected unweighted graph with 3 vertices and 2 edges
> R:=reliability_polynomial(G,p)
p2 ¡ 2 p + 1
> factor(R)
(p ¡ 1)2
Adding a new edge should increase the reliability of G, since the latter is connected. Indeed, the
dierence S ¡ R below is positive for 0 < p < 1.
> S:=reliability_polynomial(add_edge(G,[1,3]),p)
2 p3 ¡ 3 p2 + 1
> factor(S-R)

80

Graph properties

2 p (p ¡ 1)2
Multiple edges can be specied as edge weights.
> M:=graph(%{[[1,2],2],[[2,3],1],[[3,1],1]%})
an undirected weighted graph with 3 vertices and 3 edges
> factor(reliability_polynomial(M))
(x ¡ 1)2 (2 x2 + 2 x + 1)
The following graph represents the Arpanet (early internet) in December 1970.
> V:=["MIT","LINCOLN","CASE","CMU","HARVARD","BBN","UCSB","UCLA","STANFORD",
"SRI","RAND","UTAH","SDC"]:;
> A:=graph(V,trail("BBN","HARVARD","CMU","CASE","LINCOLN","MIT","UTAH","SRI",
"STANFORD","UCLA","UCSB","SRI","UCLA","RAND","BBN","MIT"),trail("RAND","SDC",
"UTAH"))
an undirected unweighted graph with 13 vertices and 17 edges
> Arpanet:=set_vertex_positions(A,[[1.0,1.0],[0.9,1.2],[0.5,1.1],[0.6,0.8],[1.0,
0.6],[1.0,0.8],[-1.1,0.1],[-0.8,0.3],[-0.6,0.5],[-0.8,0.7],[-0.8,-0.1],[-0.3,
0.9],[-0.5,0.2]])
an undirected unweighted graph with 13 vertices and 17 edges
> draw_graph(Arpanet)
LINCOLN
CASE
MIT
UTAH
BBN

CMU

SRI

HARVARD

STANFORD
UCLA
SDC
UCSB
RAND

Which edge should be added to the Arpanet to improve the reliability the most? Below is an
analysis for the edge from Stanford to CMU.
> R:=reliability_polynomial(Arpanet,p)
(p ¡ 1)12 (280 p5 + 310 p4 + 186 p3 + 63 p2 + 12 p + 1)
> S:=reliability_polynomial(add_edge(Arpanet,["STANFORD","CMU"]),p)
(p ¡ 1)12 (976 p6 + 1118 p5 + 703 p4 + 276 p3 + 72 p2 + 12 p + 1)
> labels=["p","R,S"]; plot([R,S],p=0..1,color=[blue,red])
R,S
1
0.8
0.6
0.4
0.2
p0
0

0.2

0.4

0.6

0.8

1

4.5 Connectivity

81

The improvement is dened as the area enclosed by the above two curves, which can be computed
as an integral.
> improvement:=integrate(S-R,p=0..1)
443879
10581480
> evalf(improvement)
0.0419486688063

4.5. Connectivity
4.5.1. Connected, biconnected and triconnected graphs
The commands is_connected, is_biconnected and is_triconnected are used for determining
if a graph is connected, biconnected or triconnected (3-connected), respectively.
Syntax: is_connected(G)
is_biconnected(G)
is_triconnected(G)
Each of the above commands accepts a graph G(V ; E) as its only argument and returns true if
G possesses the required level of connectivity. Else, it returns false.
If G is directed, the edge directions are simply ignored (the commands operate on the underlying
graph of G).
The strategy for checking 1- and 2-connectivity is to use depth-rst search (see [22, pp. 20] and [45]).
Both algorithms run in O(jV j + jE j) time. The algorithm for checking 3-connectivity is quite
simple but less ecient: it works by choosing a vertex v 2 V and checking if the subgraph induced
by V n fv g is biconnected, moving on to the next vertex if so, and repeating the process until all
vertices are visited exactly once or a non-biconnected subgraph is found for some v. In the latter
case the input graph is not triconnected. The complexity of this algorithm is O(jV j jE j).
> G:=graph_complement(complete_graph(2,3,4))
an undirected unweighted graph with 9 vertices and 10 edges
> is_connected(G)
false
> C:=connected_components(G)
f[0; 1]; [2; 3; 4]; [5; 6; 7; 8]g
> H:=induced_subgraph(G,C[2])
an undirected unweighted graph with 4 vertices and 6 edges
> is_connected(H)
true
> is_biconnected(path_graph(5))
false
> is_biconnected(cycle_graph(5))
true
> is_triconnected(graph("petersen"))

82

Graph properties

true
> is_triconnected(cycle_graph(5))
false

4.5.2. Connected and biconnected components
The command connected_components resp. biconnected_components is used for decomposing
a graph into connected resp. biconnected components.
Syntax: connected_components(G)
biconnected_components(G)
connected_components resp. biconnected_components accepts a graph G(V ; E) as its only argument and returns the minimal partition fV1; V2; :::; Vk g of V such that the subgraph Gi  G induced
by Vi is connected resp. biconnected for each i = 1; 2; :::; k. The partition is returned as a list of
lists V1; V2; :::; Vk.
If G is directed, the edge directions are simply ignored (the commands operate on the underlying
graph of G).
The connected components of G are readily obtained by depth-rst search in O(jV j + jE j) time.
To nd the biconnected components of G, Tarjan's algorithm is used [45], which also runs in
linear time.
> G:=graph_complement(complete_graph(3,5,7))
an undirected unweighted graph with 15 vertices and 34 edges
> is_connected(G)
false
> C:=connected_components(G)
f[0; 1; 2]; [3; 4; 5; 6; 7]; [8; 9; 10; 11; 12; 13; 14]g
> G:=highlight_subgraph(G,induced_subgraph(G,C[1]))
an undirected unweighted graph with 15 vertices and 34 edges
> G:=highlight_subgraph(G,induced_subgraph(G,C[2]),magenta,cyan)
an undirected unweighted graph with 15 vertices and 34 edges
> draw_graph(G)
8
14

3

9
7

13

0

4

10

12

11

6

5

2

1

> H:=graph(trail(1,2,3,4,2),trail(4,5,6,7,5))
an undirected unweighted graph with 7 vertices and 8 edges
> draw_graph(H)
1
7

2

6

3

5

4

4.5 Connectivity

83

> is_biconnected(H)
false
> biconnected_components(H)
f[1; 2]; [2; 3; 4]; [4; 5]; [5; 6; 7]g

4.5.3. Vertex connectivity
The command vertex_connectivity is used for computing vertex connectivity in undirected
graphs.
Syntax: vertex_connectivity(G)
vertex_connectivity accepts an undirected connected graph G(V ; E) as its only argument and
returns the largest integer k for which G is k-vertex-connected, meaning that G remains connected
after removing fewer than k vertices from V .
The strategy is to use the algorithm by Esfahanian and Hakimi [18], which is based on the
maximum-ow computing approach by Even [19, Section 6.2]. The algorithm makes jV j ¡  ¡ 1 +
 ( ¡ 1)
calls to maxflow command, where  is the minimum vertex degree in G.
2
> vertex_connectivity(graph("petersen"))
3
> vertex_connectivity(graph("clebsch"))
5
> G:=random_planar_graph(1000,0.5,2)
an undirected unweighted graph with 1000 vertices and 1876 edges
> is_biconnected(G)
true
> vertex_connectivity(G)
2
3.28 sec

4.5.4. Graph rank
The command graph_rank is used for computing graph rank.
Syntax: graph_rank(G)
graph_rank(G,S)
graph_rank accepts one or two arguments, a graph G(V ; E) and optionally a set of edges S  E
(by default S = E), and returns jV j ¡ k where k is the number of connected components of the
spanning subgraph of G with edge set S.
> G:=graph(%{[1,2],[3,4],[4,5]%})
an undirected unweighted graph with 5 vertices and 3 edges
> graph_rank(G)
3
> graph_rank(G,[[1,2],[3,4]])
2

84

Graph properties

4.5.5. Articulation points
The command articulation_points is used for obtaining the set of articulation points (cutvertices) of a graph.
Syntax: articulation_points(G)
articulation_points accepts a graph G(V ; E) as its only argument and returns the list of
articulation points of G. A vertex v 2 V is an articulation point of G if the removal of v increases
the number of connected components of G.
The articulation points of G are found by depth-rst search in O(jV j + jE j) time [22].
> articulation_points(path_graph([1,2,3,4]))
[2; 3]
> length(articulation_points(cycle_graph(1,2,3,4)))
0

4.5.6. Strongly connected components
The command strongly_connected_components is used for decomposing digraphs into
strongly connected components. A digraph H is strongly connected if for each pair (v; w) of distinct vertices in H there is a directed path from v to w in H. The command is_strongly_connected
can be used to determine whether the given graph is strongly connected.
Syntax: strongly_connected_components(G)
is_strongly_connected(G)
strongly_connected_components accepts a digraph G(V ; E) as its only argument and returns
the minimal partition fV1; V2; :::; Vk g of V such that the subgraph Gi  G induced by Vi is strongly
connected for each i = 1; 2; :::; k. The result is returned as a list of lists V1; V2; :::; Vk.
is_strongly_connected accepts a digraph G as its only argument and returns true if G has
exactly one strongly connected component and false otherwise.
The strategy is to use Tarjan's algorithm for strongly connected components [45], which runs in
O(jV j + jE j) time.
> G:=digraph([1,2,3],%{[1,2],[1,3],[2,3],[3,2]%})
a directed unweighted graph with 3 vertices and 4 arcs
> draw_graph(G)
1

3

2

> is_connected(G)
true
> is_strongly_connected(G)
false
> strongly_connected_components(G)
f[1]; [2; 3]g

4.5 Connectivity

85

> G:=random_digraph(10,18)
a directed unweighted graph with 10 vertices and 18 arcs
> draw_graph(G)
0

1

9

2

8

3

7

4
6

5

> strongly_connected_components(G)
f[0; 2; 6]; [1]; [3]; [4]; [5; 7; 8]; [9]g

4.5.7. Edge connectivity
The command edge_connectivity is used for computing the edge connectivity of an undirected
graph.
Syntax: edge_connectivity(G)
edge_connectivity accepts an undirected connected graph G(V ; E) as its only argument and
returns the largest integer k for which G is k-edge connected, meaning that G remains connected
after fewer than k edges are removed from E.
The strategy is to apply Matula's algorithm [49, Section 13.3.1], which constructs a dominating
set D  V and calls maxflow command jDj ¡ 1 times.
> G:=cycle_graph([1,2,3,4,5])
an undirected unweighted graph with 5 vertices and 5 edges
> edge_connectivity(G)
2
> K5:=complete_graph(5)
an undirected unweighted graph with 5 vertices and 10 edges
> edge_connectivity(K5)
4
> edge_connectivity(graph("petersen"))
3
> edge_connectivity(graph("clebsch"))
5

4.5.8. Edge cuts
The command is_cut_set is used for determining whether a particular subset of edges of the
given graph is an edge cut.
Syntax: is_cut_set(G,L)
is_cut_set accepts two arguments, a graph G(V ; E) and a subset L  E of edges, and returns
true if the graph G 0(V ; E n L) has more connected components than G. Else it returns false.

86

Graph properties

> G:=graph(trail(1,2,3,4,5,6,4,1,3))
an undirected unweighted graph with 6 vertices and 8 edges
> draw_graph(G)
1

2

6

3

5

4

> E:=[[1,4],[3,4]]


1 4
3 4



> is_cut_set(G,E)
true
> is_connected(delete_edge(G,E))
false

4.5.9. Two-edge-connected graphs
The command is_two_edge_connected is used for determining whether an undirected graph is
two-edge-connected. The command two_edge_connected_components is used for splitting a graph
into components having this property.
Syntax: is_two_edge_connected(G)
two_edge_connected_components(G)
is_two_edge_connected accepts an undirected graph G(V ; E) as its only argument and returns
true if G has no bridges, i.e. edges which removal increases the number of connected components
of G.
two_edge_connected_components accepts an undirected graph G(V ; E) and returns the list of
two-edge-connected components of G, each of them represented by the list of its vertices. To obtain
a component as a graph, use the induced_subgraph command.
The strategy for nding bridges [46] is similar to nding articulation points. Once the bridges of
G are found, it is easy to split G into two-edge-connected components by removing the bridges
and returning the list of connected components of the resulting graph. Both algorithms run in
O(jV j + jE j) time.
> is_two_edge_connected(cycle_graph(4))
true
> is_two_edge_connected(path_graph(4))
false
> G:=graph(%{["a","b"],["b","c"],["a","c"],["d","e"],["e","f"],["d","f"],["c",
"d"],["a","h"],["a","i"],["h","i"]%})
an undirected unweighted graph with 8 vertices and 10 edges
> is_two_edge_connected(G)
false
> draw_graph(G)

4.6 Trees

87

a

b

i

c

h

d

f

e

> C:=two_edge_connected_components(G)
f[a; b; c; h; i]; [d; e; f ]g
To visualize the bridges of G, one can highlight the edges of each component. The remaining
(unhighlighted) edges are the bridges.
> for c in C do G:=highlight_edges(G,edges(induced_subgraph(G,c))); od:;
> draw_graph(G)
a

b

i

c

h

d

f

e

4.6. Trees
4.6.1. Tree graphs
The command is_tree is used for determining whether the given graph is a tree.
Syntax: is_tree(G)
is_tree accepts a graph G(V ; E) as its only argument and returns true if G is undirected,
connected and jV j = jE j + 1. Else it returns false.

The only expensive step in the algorithm is determining whether G is connected. The condition
jV j = jE j + 1 is checked rst, hence the algorithm runs in O(jV j) time.
> is_tree(complete_binary_tree(3))
true
> is_tree(cycle_graph(5))
false

4.6.2. Forest graphs
The command is_forest is used for determining whether the given graph is a forest.
Syntax: is_forest(G)
is_forest accepts the a G(V ; E) as its only argument and returns true if every connected
component of G is a tree and false otherwise.
The algorithm runs in O(jV j + jE j) time.
> F:=disjoint_union(apply(random_tree,[k$(k=10..30)]))
an undirected unweighted graph with 420 vertices and 399 edges

88

Graph properties

> is_connected(F)
false
> is_forest(F)
true
> draw_graph(F)

4.6.3. Height of a tree
The command tree_height is used for determining the height of a tree with respect to the specied
root node. The height of a tree T is the length of the longest path in T that has the root node
of T as one of its endpoints.
Syntax: tree_height(G,r)
tree_height accepts two arguments, a tree graph G(V ; E) and a vertex r 2 V , which is used as
the root node. The command returns the height of G with respect to r.
The strategy is to start a depth-rst search from the root node and look for the deepest node.
Therefore the algorithm runs in O(jV j) time.
> G:=random_tree(1000)
an undirected unweighted graph with 1000 vertices and 999 edges
> r:=rand(1000)
296
> tree_height(G,r)
20

4.6.4. Lowest common ancestor of a pair of nodes
The command lowest_common_ancestor is used for computing the lowest common ancestor (LCA)
of a pair of nodes in a tree or for each element of a list of such pairs.

Syntax: lowest_common_ancestor(G,r,u,v)
lowest_common_ancestor(G,r,[[u1,v1],[u2,v2],..,[uk,vk]])
lowest_common_ancestor accepts two mandatory arguments, a tree graph G(V ; E) and the root
node r 2 V . There are two possibilities for specifying the nodes to operate on: either the nodes
u; v 2 V are given as the third and the fourth argument, or a list of pairs of nodes in form [[u1,
v1],[u2,v2],...,[uk,vk]], where ui; vi 2 V and ui =
/ vi for i = 1; 2; :::; k, is given as the third
argument. The command returns the LCA of u and v or the list containing LCA of every pair of
nodes ui; vi for i = 1; 2; :::; k. Note that this is much faster than calling lowest_common_ancestor
k times with one pair ui; vi at a time.
The strategy is to use Tarjan's oine LCA algorithm [47], which runs in nearly linear time.
> G:=random_tree(25)

4.7 Networks

89

an undirected unweighted graph with 25 vertices and 24 edges
> draw_graph(G)
0

1

2

4

3

5

15

6

8

7

9

10

16

11

12

13

14

17

18

19

22

20

21 23

24

> lowest_common_ancestor(G,0,19,22)
16
> lowest_common_ancestor(G,0,[[5,13],[17,24],[9,16]])
[4; 16; 0]

4.6.5. Arborescence graphs
The command is_arborescence is used for determining whether the given directed unweighted
graph is an arborescence (which is the digraph form of a rotted tree).
Syntax: is_arborescence(G)
is_arborescence accepts a digraph G(V ; E) as its only argument and returns true if there is a
vertex u 2 V such that for any other v 2 V there is exactly one directed path from u to v. Else it
returns false.
> T:=digraph(%{[1,2],[1,3],[3,4],[3,5],[3,6],[5,7]%})
a directed unweighted graph with 7 vertices and 6 arcs
> is_arborescence(T)
true
> draw_graph(T)
1

3

2

5

4

6

7

4.7. Networks
4.7.1. Network graphs
The command is_network is used for determining whether the given graph is a ow network. In
this context, a ow network is directed, connected graph with at least one vertex with in-degree 0
(the source) and at least one vertex with out-degree 0 (the sink).
Syntax: is_network(G)
is_network(G,s,t)

90

Graph properties

is_network accepts one or three arguments, a digraph G(V ; E) and optionally the source vertex
s and the sink vertex t. If these vertices are given, the command returns true if G is a network
with respect to s, t and false otherwise. If the graph G is given as the only argument, the
command returns a sequence of two objects, the list of all sources in G and the list of all sinks in
G, respectively. If one of these lists is empty, then G is implicitly not a network (both lists are
empty if G is not connected).
> N:=digraph(%{[1,2],[1,3],[2,4],[3,4]%})
a directed unweighted graph with 4 vertices and 4 arcs
> draw_graph(N,spring)
4

3

2

1

> is_network(N,1,4)
true
> is_network(N,2,3)
false
> G:=digraph(%{[1,3],[2,3],[3,4],[3,5]%})
a directed unweighted graph with 5 vertices and 4 arcs
> draw_graph(G,circle)
1

5

3

4

2

> is_network(G)


1 2
4 5



4.7.2. Maximum ow
The command maxflow is used for computing the maximum ow in a network.
Syntax: maxflow(G,s,t)
maxflow(G,s,t,M)
maxflow accepts three or four arguments: a network graph G(V ; E), the source s 2 V , the sink
t 2 V and optionally an unassigned identier M. It returns the optimal value for the maximum ow
problem for the network (G; s; t). If the fourth argument is given, an optimal ow is written to M
in form of a matrix.
The strategy is to use the algorithm of Edmonds and Karp [17], which solves the maximum ow
problem in O(jV j jE j2) time.
> A:=[[0,1,0,4,0,0],[0,0,1,0,3,0],[0,1,0$3,1],[0,0,3,0,1,0],[0$3,1,0,4],[0$6]]

4.7 Networks

91

0
B
B
B
B
B
B
@

> N:=digraph([1,2,3,4,5,6],A)

0
0
0
0
0
0

1
0
1
0
0
0

0
1
0
3
0
0

4
0
0
0
1
0

0
3
0
1
0
0

0
0
1
0
4
0

1
C
C
C
C
C
C
A

a directed weighted graph with 6 vertices and 10 arcs
> is_network(N)




1
6

> draw_graph(N,spring)
4

3

3
1
1

4

1

1

1

1

6
1
4
3

2

5

> maxflow(N,1,6,M)
4
> M
0
B
B
B
B
B
B
@

0
0
0
0
0
0

1
0
1
0
0
0

0
0
0
2
0
0

3
0
0
0
0
0

0
2
0
1
0
0

0
0
1
0
3
0

1
C
C
C
C
C
C
A

> N:=random_network(2,3,0.9,acyclic,weights=5..15)
a directed weighted graph with 12 vertices and 19 arcs
> is_network(N)


0
11



> draw_graph(N,spring)
2
14

15

7

10
6

0

7
5

9

11

10
9

6
13

1

9
8

13

13
8

15
4

10
11

7

3

9

12

5
10

> maxflow(N,0,11,F)
17
To visualize the optimal ow F , one can use the highlight_subgraph command with the option
weights to display the actual ow in the highlighted edges. Non-highlighted edges have zero ow.

92

Graph properties

> draw_graph(highlight_subgraph(N,digraph(vertices(N),F),weights),spring)
2
10

9

0

1

6

7
7

7

3

5

9

9
2

9

3

6
3

1
8 9

3

12
8

5

4
10

5

5

11

10

4.7.3. Minimum cut
The command minimum_cut is used for obtaining minimum cuts in networks.
Syntax: minimum_cut(G,s,t)
minimum_cut accepts three arguments, a digraph G(V ; E) and two vertices s; t 2 V such that
(G; s; t) is a network with source s and sink t. The returned value is a list of edges in E representing
a minimum cut in the network.
The strategy is to apply the maxflow command, which nds a maximal ow, and to run depthrst search on the corresponding residual graph to nd a S ; T partition of V . The minimum cut
is then the set of all arcs vw 2 E such that v 2 S and w 2 T . The algorithm runs in O(jV j jE j2) time.
> G:=digraph(%{[[0,1],16],[[0,2],13],[[1,2],10],[[1,3],12],[[2,1],4],[[2,4],14],
[[3,2],9],[[3,5],20],[[4,3],7],[[4,5],4]%})
a directed weighted graph with 6 vertices and 10 arcs
> draw_graph(G,spring)
1
12
16

3

10
4

20
5

9

0

13
7
2

14

4
4

> cut:=minimum_cut(G,0,5)
0

1
1 3
@ 4 3 A
4 5

> draw_graph(highlight_edges(G,cut),spring)
1
12

3
16
0

10

4

20
9

5

13
7
2

14

4
4

By the max-ow min-cut theorem, the sum of edge weights in minimum cut is equal to the value
of maximum ow.
> w:=0:; for ed in cut do w:=w+get_edge_weight(G,ed); od:; w
Done; Done; 23
> maxflow(G,0,5)

4.8 Distance in graphs

93

23

4.8. Distance in graphs
4.8.1. Vertex distance
The command vertex_distance is used for computing the length of the shortest path(s) from the
source vertex to some other vertex/vertices of a graph.
Syntax: vertex_distance(G,v,w)
vertex_distance(G,v,L)
vertex_distance accepts three arguments, a graph G(V ; E), a vertex v 2 V called the source and
a vertex w 2 V called the target or a list L  V n fvg of target vertices. The command returns
the distance between v and w as the number of edges in a shortest path from v to w, or the list
of distances if a list of target vertices is given.
The strategy is to use breadth-rst search [22, pp. 35] starting from the source vertex. Therefore,
the algorithm runs in O(jV j + jE j) time.
> G:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> vertex_distance(G,1,3)
2
> vertex_distance(G,1,[3,6,9])
[2; 1; 2]

4.8.2. All-pairs vertex distance
The command allpairs_distance is used for computing the matrix of distances between all pairs
of vertices in the given (weighted) graph.
Syntax: allpairs_distance(G)
allpairs_distance accepts a graph G(V ; E) as its only argument and returns a square matrix
D = [dij ] with n = jV j rows and columns such that dij = distance(vi; vj ) for all i; j = 1; 2; :::; n,
where v1; v2; :::; vn are the elements of V . If vi vj 2
/ E, then dij = +1. The strategy is to apply the
algorithm of Floyd and Warshall [20], which runs in O(jV j3) time.

Note that, if G is weighted, it must not contain negative cycles. A cycle is negative if the sum of
weights of its edges is negative.
> G:=graph([1,2,3,4,5],%{[1,2],[1,3],[1,4],[1,5],[2,3],[3,4],[4,5],[5,2]%})
an undirected unweighted graph with 5 vertices and 8 edges
> allpairs_distance(G)
0
B
B
B
B
@

0
1
1
1
1

1
0
1
2
1

1
1
0
1
2

1
2
1
0
1

1
1
2
1
0

1
C
C
C
C
A

> H:=digraph(%{[1,2],[1,3],[1,4],[1,5],[2,3],[3,4],[4,5],[5,2]%})
a directed unweighted graph with 5 vertices and 8 arcs

94

Graph properties

> allpairs_distance(H)
0
B
B
B
B
@

> draw_graph(H)

0
+1
+1
+1
+1

1
0
3
2
1

1
1
0
3
2

1
2
1
0
3

1
3
2
1
0

1
C
C
C
C
A

1

5

2

4

3

> H:=assign_edge_weights(H,5,25)
a directed weighted graph with 5 vertices and 8 arcs
> draw_graph(H)
1
8
5

24

25

2

18

18
14

5

4

11

3

18
14
0
44
39

18
25
11
0
50

> allpairs_distance(H)
0
B
B
B
B
@

0
+1
+1
+1
+1

24
0
41
30
25

8
30
16
5
0

1
C
C
C
C
A

4.8.3. Diameter
The command graph_diameter is used for determining the maximum distance among all pairs of
vertices in a graph.
Syntax: graph_diameter(G)

graph_diameter accepts a graph G(V ; E) as its only argument and returns the number
max fdistance(u; v) : u; v 2 V g. If G is disconnected, +1 is returned.
This command calls allpairs_distance and picks the largest element in the output matrix. Hence
the complexity of the algorithm is O(jV j3).
> graph_diameter(graph("petersen"))
2
> graph_diameter(cycle_graph(19))
9
> graph_diameter(disjoint_union(graph("petersen"),cycle_graph(19)))
+1

4.9 Acyclic graphs

95

> G:=graph(%{[[1,2],0.2],[[2,3],0.3],[[3,4],0.4],[[4,1],1.1]%})
an undirected weighted graph with 4 vertices and 4 edges
> draw_graph(G)
1

3

1.1
0.2

0.4
0.3

2

4

> graph_diameter(G)
0.9
> dijkstra(G,1,4)
[[1; 2; 3; 4]; 0.9]

4.8.4. Girth
The commands girth and odd_girth are used for computing the (odd) girth of an undirected
unweighted graph.
Syntax: girth(G)
girth resp. odd_girth accepts a graph G(V ; E) as its only argument and returns the girth
resp. odd girth of G. The (odd) girth of G is dened to be the length of the shortest (odd)
cycle in G. If there is no (odd) cycle in G, the command returns +1.
The strategy is to apply breadth-rst search from each vertex of the input graph. The runtime is
therefore O(jV jjE j).
> girth(graph("petersen"))
5
> G:=hypercube_graph(3)
an undirected unweighted graph with 8 vertices and 12 edges
> G:=subdivide_edges(G,["000","001"])
an undirected unweighted graph with 9 vertices and 13 edges
> girth(G)
4
> odd_girth(G)
5
> girth(complete_binary_tree(2))
+1

4.9. Acyclic graphs
4.9.1. Acyclic graphs
The command is_acyclic is used for checking for absence of directed cycles in digraphs. A
directed graph with no directed cycle is said to be acyclic.

96

Graph properties

Syntax: is_acyclic(G)
is_acyclic accepts a digraph G(V ; E) as its only argument and returns true if G is acyclic and
false otherwise.
The algorithm attempts to nd topological order for its vertices. If that succeeds, the graph is
acyclic, otherwise not. The algorithm runs in O(jV j + jE j) time.
> is_acyclic(digraph(trail(1,2,3,4,5)))
true
> is_acyclic(digraph(trail(1,2,3,4,5,2)))
false

4.9.2. Topological sorting
The command topologic_sort or topological_sort is used for nding a linear ordering of
vertices of an acyclic digraph which is consistent with the arcs of the digraph. This procedure is
called topological sorting.
Syntax: topologic_sort(G)
topological_sort(G)
topologic_sort accepts a graph G(V ; E) as its only argument and returns the list of vertices of
G in a particular order: a vertex u precedes a vertex v if u v 2 E, i.e. if there is an arc from u to v.

Note that topological sorting is possible only if the input graph is acyclic. If this condition is not
met, topologic_sort returns an error. Otherwise, it nds the required ordering by applying
Kahn's algorithm [34], which runs in O(jV j + jE j) time.
> G:=digraph(%{[c,a],[c,b],[c,d],[a,d],[b,d],[a,b]%})
a directed unweighted graph with 4 vertices and 6 arcs
> is_acyclic(G)
true
> topologic_sort(G)
[c; a; b; d]

4.9.3. st ordering
The command st_ordering is used for nding st-orderings in undirected biconnected graphs.
Syntax: st_ordering(G,s,t)
st_ordering(G,s,t,D)
st_ordering accepts three or four arguments: an undirected biconnected graph G(V ; E), a vertex
s 2 V called the source, a vertex t 2 V called the sink such that st 2 E and optionally an unassigned
identier D. The command returns the permutation  of the vertex set V . Now, an orientation of
each e = uv 2 E can be determined by the ordinals n and m of its endpoints u and v, respectively,
which are assigned by the permutation : if n < m, then u is the head and v is the tail of the
corresponding arc, and vice versa otherwise. If the fourth argument is given, a copy of G, which
is made directed according to these orientations, is stored to D.
The strategy is to apply Tarjan's algorithm [48] which runs in O(jV j + jE j) time. Note that, since
the input graph is biconnected, st-ordering can be computed for any pair s; t 2 V such that st 2 E.
> G:=graph(%{[a,b],[a,c],[a,d],[b,c],[b,d],[c,d]%})

4.10 Matching in graphs

97

an undirected unweighted graph with 4 vertices and 6 edges
> vertices(G)
[a; b; c; d]
> st_ordering(G,a,d,D)
[0; 2; 1; 3]
> draw_graph(D)
a

b

d

c

4.10. Matching in graphs
4.10.1. Maximum matching
The command maximum_matching is used for nding maximum matchings [23, pp. 43] in undirected
unweighted graphs.
Syntax: maximum_matching(G)
maximum_matching accepts an undirected graph G(V ; E) as its only argument and returns a list of
edges e1; e2; :::; em 2 E such that ei and ej are not adjacent (i.e. have no common endpoints) for all
1 6 i < j 6 m and that m is maximal. The return value can be interpreted as the list of matched
pairs of vertices in G.
The strategy is to apply the blossom algorithm of Edmonds [16], which runs in O(jV j2 jE j) time.
> maximum_matching(graph("octahedron"))
0
1
1 6
@ 3 2 A
5 4
> G:=graph("soccerball")

an undirected unweighted graph with 60 vertices and 90 edges
> M:=maximum_matching(G):; length(M)
Done; 30
> draw_graph(highlight_edges(G,M),labels=false)

> G:=random_graph(100,1000)
an undirected unweighted graph with 100 vertices and 1000 edges

98

Graph properties

> length(maximum_matching(G))
50
> G:=graph("blanusa")
an undirected unweighted graph with 18 vertices and 27 edges
> draw_graph(highlight_edges(G,maximum_matching(G)),labels=false)

4.10.2. Maximum matching in bipartite graphs
The command bipartite_matching is used for finding maximum matchings in undirected,
unweighted bipartite graphs. It applies the algorithm of Hopcroft and Karp [31], which is
more ecient than the general algorithm used by the command maximum_matching.

Syntax: bipartite_matching(G)
bipartite_matching accepts an undirected bipartite graph G(V ; E) as its only argument and
returns a sequence containing two elements: the size ofp
the matching and the list of edges connecting
¡

matched pairs of vertices. The algorithm runs in O
jV j jE j time.
> G:=graph("desargues")

an undirected unweighted graph with 20 vertices and 30 edges
> is_bipartite(G)
true
> M:=bipartite_matching(G)
0

> draw_graph(highlight_edges(G,M))

B
B
B
B
B
B
B
B
B
B
B
B
B
B
@

0
2
4
6
8
10
11
12
14
16

1
3
5
7
9
13
18
15
17
19

1
C
C
C
C
C
C
C
C
C
C
C
C
C
C
A

4.11 Cliques

99

4.11. Cliques
4.11.1. Clique graphs
To check whether an undirected graph is complete, one can use the is_clique command.
Syntax: is_clique(G)
is_clique accepts an undirected graph G(V ; E) as its only argument and returns true if every
pair of distinct vertices is connected by a unique edge in E. Else, it returns false.
> K5:=complete_graph(5)
an undirected unweighted graph with 5 vertices and 10 edges
> is_clique(K5)
true
> G:=delete_edge(K5,[1,2])
an undirected unweighted graph with 5 vertices and 9 edges
> is_clique(G)
false

4.11.2. Maximal cliques
Given an undirected graph G(V ; E), a subset S  V is called a clique in G if any two distinct
vertices from S are adjacent in G, i.e. if the subgraph of G induced by the set S is complete. A
clique is maximal if it cannot be extended by adding more vertices from V to it. To count all
maximal cliques in a graph one can use the clique_stats command.
Syntax: clique_stats(G)
clique_stats(G,k)
clique_stats(G,m..n)
clique_stats accepts an undirected graph G(V ; E) as the mandatory rst argument. If no other
arguments are given, the command returns a list of pairs, each pair consisting of two integers: clique
cardinality k (rst) and the number nk > 0 of k-cliques in G (second). Therefore, the sum of second
members of all returned pairs is equal to the total count of all maximal cliques in G. Furthermore,
a second argument may be passed to clique_stats; if so, it must be a positive integer k or an
interval with integer bounds m .. n. In the rst case only the number of k-cliques for the given k is
returned; in the second case, only cliques with cardinality between m and n (inclusive) are counted.
The strategy used to nd all maximal cliques is a variant of the algorithm of Bron and Kerbosch
developed by Tomita et al. [50]. Its worst-case running time is O(3jV j/3). However, the performance usually takes only a moment for graphs with 100 vertices or less.
> G:=random_graph(50,0.5)
an undirected unweighted graph with 50 vertices and 588 edges
> clique_stats(G)
0

> G:=random_graph(100,0.5)

B
B
B
B
B
B
@

3
4
5
6
7
8

14
185
370
201
47
5

1
C
C
C
C
C
C
A

100

Graph properties

an undirected unweighted graph with 100 vertices and 2461 edges
> clique_stats(G,5)
3124
> G:=random_graph(500,0.25)
an undirected unweighted graph with 500 vertices and 30991 edges
> clique_stats(G,5..7)
0

1
5 144544
@ 6 16268 A
7 267

4.11.3. Maximum clique
Any largest maximal clique in an undirected graph is called maximum clique. The command
maximum_clique can be used to nd one in the given graph. If only the size of a maximum clique
is desired, one can use the command clique_number.
Syntax: maximum_clique(G)
clique_number(G)
maximum_clique accepts an undirected graph G as its only argument and returns a maximum
clique in G as a list of vertices. The clique may subsequently be extracted from G using the
command induced_subgraph.
The strategy used to nd maximum clique is an improved variant of the classical algorithm by
Carraghan and Pardalos developed by Östergård [39].
In the following examples the results were obtained almost instantly.
> G:=sierpinski_graph(5,5)
an undirected unweighted graph with 3125 vertices and 7810 edges
> maximum_clique(G)
[1560; 1561; 1562; 1563; 1564]
> G:=random_graph(300,0.3)
an undirected unweighted graph with 300 vertices and 13380 edges
> maximum_clique(G)
[46; 64; 144; 183; 208; 241; 244; 261]
> G:=graph_complement(complete_graph(4,3))
an undirected unweighted graph with 7 vertices and 9 edges
> cliq:=maximum_clique(G)
[0; 1; 2; 3]
> draw_graph(highlight_subgraph(G,induced_subgraph(G,cliq)))

clique_number accepts an undirected graph G as its only argument and returns the number of
vertices forming a maximum clique in G.

4.11 Cliques

101

> clique_number(G)
4

4.11.4. Minimum clique cover
A minimum clique cover for an undirected graph G is any minimal set S = fC1; C2; :::; Ck g of
cliques in G such that for every vertex v in G there exists i 6 k such that v 2 Ci. Such a cover can
be obtained by calling the clique_cover command.
Syntax: clique_cover(G)
clique_cover(G,k)
clique_cover accepts an undirected graph G(V ; E) as its mandatory argument and returns the
smallest possible cover. Optionally, a positive integer k may be passed as the second argument.
In that case the requirement that k is less or equal to the given integer is set. If no such cover is
found, clique_cover returns empty list.
The strategy is to nd a minimal vertex coloring in the complement Gc of G (note that these two
graphs share the same set of vertices). Each set of equally colored vertices in Gc corresponds to a
clique in G. Therefore, the color classes of Gc map to the elements C1; :::; Ck of a minimal clique
cover in G.
There is a special case in which G is triangle-free, which is computed separately in the algorithm.
In that case, G contains only 1- and 2-cliques. Therefore, every clique cover in G consists of a set
M  E of matched edges together with the singleton cliques (i.e. the isolated vertices in V which
remain unmatched). The total number of cliques in the cover is equal to jV j ¡ jM j, hence to nd a
minimal cover one just needs to nd a maximum matching in G, which can be done in polynomial
time.
> G:=random_graph(30,0.2)
an undirected unweighted graph with 30 vertices and 89 edges
> clique_cover(G)
f[0; 21]; [1; 17]; [2; 25; 28]; [3; 7; 10]; [4; 8]; [5; 11; 20]; [6; 13; 14]; [9; 16; 23]; [12; 15; 19]; [18; 22]; [24;
26]; [27; 29]g

> clique_cover(graph("octahedron"))


1 3 6
2 4 5



The vertices of Petersen graph can be covered with ve, but not with three cliques.
> clique_cover(graph("petersen"),3)
[]
> clique_cover(graph("petersen"),5)
0
B
B
B
B
@

0
2
4
5
6

1
3
9
7
8

1
C
C
C
C
A

4.11.5. Clique cover number
The command clique_cover_number is used for computing the clique cover number of a graph.

102

Graph properties

Syntax: clique_cover_number(G)
clique_cover_number accepts an undirected graph G(V ; E) as its only argument and returns the
minimum number of cliques in G needed to cover the vertex set V . (More precisely, it calls the
clique_cover command and returns the length of the output list.) This number, denoted by (G),
is equal to the chromatic number (Gc) of the complement graph Gc of G.
> clique_cover_number(graph("petersen"))
5
> clique_cover_number(graph("soccerball"))
30
> clique_cover_number(random_graph(40,0.618))
7

4.12. Clustering and transitivity in networks
4.12.1. Counting triangles in graphs
The command number_of_triangles is used for counting triangles in graphs.
Syntax: number_of_triangles(G)
number_of_triangles accepts a graph G as its only argument and returns the number n of 3cliques in G if G is undirected resp. the number m of directed paths of length 3 if G is directed.
The strategy is to compute the trace of A3, where A is the adjacency matrix of G (encoded as
a sparse matrix). This number is equal to 6 n if G is undirected resp. to 3 m if G is directed. If
tr (A3) = 0, then G is triangle-free (i.e. it contains no triangular subgraphs).
The matrix A is kept in sparse form and only the computation of A2 needs to be carried out
completely. To obtain tr (A3), one needs to compute only the elements of A3 lying on its diagonal.
Hence the algorithm requires O(jV j jE j) time and O(jE j) space.
> number_of_triangles(graph("tetrahedron"))
4
> G:=digraph([1,2,3,4],%{[1,2],[1,4],[2,3],[2,4],[3,1],[4,3]%})
a directed unweighted graph with 4 vertices and 6 arcs
> draw_graph(G,spring)
3

1

2

4

> number_of_triangles(G)
2
> G:=sierpinski_graph(7,3,triangle)
an undirected unweighted graph with 1095 vertices and 2187 edges
> number_of_triangles(G)

4.12 Clustering and transitivity in networks

103

972
The truncated icosahedral graph is triangle-free.
> number_of_triangles(graph("soccerball"))
0

4.12.2. Clustering coecient
The command clustering_coefficient is used for computing the average clustering coecient
of an undirected graph as well as the local clustering coecient of a particular vertex.
Syntax: clustering_coefficient(G)
clustering_coefficient(G,v)
clustering_coefficient accepts one or two arguments, an undirected graph G(V ; E) and optionally a vertex v 2 V . It returns the average clustering coecient c(G) [8, pp. 5] if v is not given and
the local clustering coecient cG(v) of v [8, pp. 4] otherwise. The returned value is, by denition,
a rational number in the range [0; 1] in both cases. The number c(G) can be computed from cG(v)
using the following relation:
1 X
c(G) =
cG(v):
jV j
v2V

In the context of social networks, c(G) can be interpreted as the probability that if v; w 2 V are
friends and w; z 2 V are friends then v and z are friends (note that friendship is a symmetric
relation). The number cG(v) has the same interpretation but in a local context: it measures how
probable the friendship transitivity is for a particular node v 2 V .
The complexity of computing c(G) is O(G jE j), where G is the maximum vertex degree in G.
> G:=graph(%{[1,2],[2,3],[2,4],[3,4],[4,1]%})
an undirected unweighted graph with 4 vertices and 5 edges
> draw_graph(G,spring)
4

3

1

2

The command lines below compute c(G), cG(1) and cG(2).
> clustering_coefficient(G)
5
6
> clustering_coefficient(G,1)
1
> clustering_coefficient(G,2)
2
3
The next example demonstrates the performance of clustering_coefficient on large graphs.
> G:=random_graph(5000,500000)

104

Graph properties

an undirected unweighted graph with 5000 vertices and 500000 edges
> cf:=clustering_coefficient(G):;
2.14 sec

> evalf(cf)
0.0400370165471
The probability that friendship is transitive in the network G above is therefore about 4%.

4.12.3. Network transitivity
The command network_transitivity is used for computing the transitivity (also called triangle
density or the global clustering coecient) of a network.
Syntax: network_transitivity(G)
network_transitivity accepts a graph G as its only argument and returns the transitivity T (G)
of G [8, pp. 5]. By denition, it is a rational number in the range [0; 1]:
T (G) =

3 Ntriangles
:
Ntriplets

If G is undirected, Ntriangles is the number of closed triplets (3-cliques) of vertices in V while Ntriplets
is the number of all triplets (two-edge paths). If G is directed, a triplet in G is any directed path
(v; w; z). For example, in a Twitter-like network this could mean that v following w and w following
z. The triplet (v; w; z) is closed if vz 2 E, i.e. if v also follows z [53, pp. 243]. Therefore, T (G) is
a measure of transitivity of a non-symmetric relation between the vertices of a network.
The complexity of computing T (G) is O(G jE j), where G is the maximum vertex degree in G.
> G:=graph(%{[1,2],[2,3],[2,4],[3,4],[4,1]%})
an undirected unweighted graph with 4 vertices and 5 edges
> network_transitivity(G)
3
4
Observe that the above result is dierent than c(G) obtained in Section 4.12.2. Hence c(G) =
/ T (G)
in general [8, pp. 5].
> G:=random_digraph(10,20)
a directed unweighted graph with 10 vertices and 20 arcs
> draw_graph(G)
0

1

9

2

8

3

7

4
6

5

In the above digraph, the triplet (5; 7; 6) is open while the triplet (7; 6; 4) is closed. Triangles (2; 5; 9)
and (6; 8; 7) are not closed by denition.
> network_transitivity(G)

4.13 Vertex coloring

105

5
33
The algorithm is usable on large networks, as shown in the example below.
> G:=random_digraph(1000,500000)
a directed unweighted graph with 1000 vertices and 500000 arcs
> nt:=network_transitivity(G):;
3.5 sec

> evalf(nt)
0.500492245999

4.13. Vertex coloring
To color vertices of a graph G(V ; E) means to assign to each vertex v 2 V a positive integer. Each
integer represents a distinct color. The key property of graph coloring is that the colors of a pair
of adjacent vertices must be mutually dierent. Two dierent colorings of G may use dierent
number of colors.

4.13.1. Greedy vertex coloring
The command greedy_color is used for coloring vertices of a graph in a greedy fashion.
Syntax: greedy_color(G)
greedy_color(G,p)
greedy_color accepts one mandatory argument, a graph G(V ; E). Optionally, a permutation p
of order jV j may be passed as the second argument. Vertices are colored one by one in the order
specied by p (or in the default order if p is not given) such that each vertex gets the smallest
available color. The list of vertex colors is returned in the order of vertices(G).
Generally, dierent choices of permutation p produce dierent colorings. The total number of
dierent colors may not be the same each time. The complexity of the algorithm is O(jV j + jE j).
> G:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> greedy_color(G)
[1; 2; 1; 2; 3; 2; 1; 3; 3; 2]
> L:=greedy_color(G,randperm(10))
[1; 2; 1; 4; 3; 4; 1; 3; 2; 2]
Observe that a dierent number of colors is obtained by executing the last command line. To
display the colored graph, input:
> draw_graph(highlight_vertex(G,vertices(G),L),labels=false)

106

Graph properties

The rst six positive integers are always mapped to the standard Xcas colors, as indicated in
Table 4.1. Note that the color 0 (black) and color 7 (white) are swapped; a vertex with color 0 is
white (uncolored) and vertex with color 7 is black. Also note that Xcas maps numbers greater than
7 to colors too, but the number of available colors is limited.

4.13.2. Minimal vertex coloring
The vertex coloring of G is minimal (or optimal) if the smallest possible number of colors is
used. To obtain such a coloring use the command minimal_vertex_coloring.
Syntax: minimal_coloring(G)
minimal_coloring(G,sto)
minimal_vertex_coloring accepts one mandatory argument, a graph G(V ; E) where V = fv1;
v2; :::; vng. Optionally, a symbol sto may be passed as the second argument. The command returns
the vertex colors c1; c2; :::; cn in order of vertices(G) or, if the second argument is given, stores
the colors as vertex attributes and returns the modied copy of G.
Giac requires the GLPK library to solve the minimal vertex coloring problem (MVCP), which is
converted to the equivalent integer linear programming problem and solved by using the branchand-bound method with specic branch/backtrack techniques [14]. Lower and upper bounds for the
number of colors n are obtained by nding a maximal clique (n cannot be lower than its cardinality)
and by using the heuristic proposed by Brélaz in [9] (which will use at least n colors), respectively.
Note that the algorithm performs some randomization when applying heuristics, so coloring a graph
several times will not take the same amount of computation time in each instance, generally.

In the following example, the Grötzsch graph is colored with the minimal number of colors by rst
nding the coloring and then assigning it to the graph by using the highlight_vertex command.
> G:=graph("grotzsch")
an undirected unweighted graph with 11 vertices and 20 edges
> coloring:=minimal_vertex_coloring(G)
[4; 2; 3; 1; 1; 4; 1; 3; 2; 1; 2]
> draw_graph(highlight_vertex(G,vertices(G),coloring),labels=false)

Solving MVCP for dierent graphs of exactly the same size (but which do not share the same edge
structure) may take quite dierent time in each instance. Also note that, since vertex coloring
problem is NP hard, the algorithm may take exponential time on some graphs.
value
1
2
3
4
5
6
7

color
red
green
yellow
blue
magenta
cyan
black

Table 4.1. interpretation of abstract vertex/edge colors in Xcas

4.13 Vertex coloring

107

4.13.3. Chromatic number
The command chromatic_number is used for exact computation or approximation of the
chromatic number of a graph.

Syntax: chromatic_number(G)
chromatic_number(G,c)
chromatic_number(G,approx or interval)
chromatic_number accepts one mandatory argument, a graph G(V ; E), and optionally a second
argument. To obtain only upper and lower bound for the chromatic number (which is much
faster than computing exactly) the option approx or interval should be passed as the second
argument. Alternatively, an unassigned identier c is passed as the second argument; in that case
the corresponding coloring will be stored to it in form of a list of colors of the individual vertices,
ordered as in vertices(G).
The command returns the chromatic number G of the graph G in the case of exact computation.
If the option approx or interval is given, an interval lb..ub is returned, where lb is the best
lower bound and ub the best upper bound for G found by the algorithm.
The strategy is call minimal_vertex_coloring in the case of exact computation. When approximating the chromatic number, the algorithm will establish the lower bound by nding a maximum
clique. The timeout for this operation is set to 5 seconds as it can be time consuming. If no
maximum clique is not found after that time, the largest clique found is used. Then, an upper
bound is established by by using the heuristic proposed by Brélaz in [9]. Obtaining the bounds
for G is usually very fast; however, their dierence grows with jV j.
Unless the input graph is sparse enough, the algorithm slows down considerably for, say, jV j > 40.
> chromatic_number(graph("grotzsch"),cols)
4
> cols
[4; 2; 3; 1; 1; 4; 1; 3; 2; 1; 2]
> G:=random_graph(30,0.75)
an undirected unweighted graph with 30 vertices and 313 edges
> chromatic_number(G)
10
> G:=random_graph(300,0.05)
an undirected unweighted graph with 300 vertices and 2196 edges
> chromatic_number(G,approx)
4..7

4.13.4. Mycielski graphs
The command mycielski is used for constructing Mycielski graphs.
Syntax: mycielski(G)
mycielski accepts an undirected graph G(V ; E) as its only argument and returns the corresponding Mycielski graph M (also called the Mycielskian of G) with 2 jV j + 1 vertices and
3 jE j + jV j edges. If G is triangle-free then M is also triangle-free and M = G + 1.
> P:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges

108

Graph properties

> M:=mycielski(P)
an undirected unweighted graph with 21 vertices and 55 edges
> apply(number_of_triangles,[P,M])
[0; 0]
> chromatic_number(P)
3
> chromatic_number(M)
4
mycielski can be applied iteratively, producing arbitrarily large graphs from the most simple ones.
For example, Grötzsch graph is obtained as the Mycielskian of a cycle graph on 5 vertices, which
is the Mycielskian of a path graph on two vertices.
> G1:=path_graph(2)
an undirected unweighted graph with 2 vertices and 1 edge
> G2:=mycielski(G1)
an undirected unweighted graph with 5 vertices and 5 edges
> is_isomorphic(G2,cycle_graph(5))
true
> G3:=mycielski(G2)
an undirected unweighted graph with 11 vertices and 20 edges
> is_isomorphic(G3,graph("grotzsch"))
true
All three graphs are triangle-free. Since it is obviously G1 = 2, it follows G2 = 3 and G3 = 4.
> apply(chromatic_number,[G1,G2,G3])
[2; 3; 4]

4.13.5. k-coloring
The command is_vertex_colorable is used for determining whether the vertices of a graph can
be colored with at most k colors.
Syntax: is_vertex_colorable(G,k)
is_vertex_colorable(G,k,c)
is_vertex_colorable accepts two or three arguments: a graph G(V ; E), a positive integer k and
optionally an unassigned identier c. The command returns true if G can be colored using at most
k colors and false otherwise. If the third argument is given, a coloring using at most k colors is
stored to c as a list of vertex colors, in the order of vertices(G).
The strategy is to rst apply a simple greedy coloring procedure which runs in linear time. If
the number of required colors is greater than k, the heuristic proposed by Brélaz in [9] is used,
which runs in quadratic time. If the number of required colors is still larger than k, the algorithm
attempts to nd the chromatic number G using k as the upper bound in the process.
> G:=graph("grotzsch")
an undirected unweighted graph with 11 vertices and 20 edges

4.14 Edge coloring

109

> is_vertex_colorable(G,3)
false
> is_vertex_colorable(G,4)
true
> G:=random_graph(70,0.2)
an undirected unweighted graph with 70 vertices and 469 edges
> chromatic_number(G,approx)
5..6
> is_vertex_colorable(G,5)
false
818 msec

From the results of the last two command lines it follows G = 6. Finding G by utilizing the next
command line is simpler, but requires much more time.
> chromatic_number(G)
6
92.7 sec

4.14. Edge coloring
4.14.1. Minimal edge coloring
The command minimal_edge_coloring is used for nding a minimal coloring of edges in a graph,
satisfying the following two conditions: any two mutually incident edges are colored dierently and
the total number n of colors is minimal. The theorem of Vizing [15, pp. 103] implies that every
simple undirected graph falls into one of two categories: 1 if n =  or 2 if n =  + 1, where  is
the maximum degree of the graph.
Syntax: minimal_edge_coloring(G)
minimal_edge_coloring(G,sto)
minimal_edge_coloring accepts one or two arguments, a graph G(V ; E) and optionally the
keyword sto. If the latter is given, a minimal coloring is stored to the input graph (each edge e 2 E
gets a color ce stored as an attribute) and a modied copy of G is returned. Else, the command
returns a sequence of two objects: integer 1 or 2, indicating the category, and the list of edge colors
ce1; ce2; :::; cem according the order of edges e1; e2; :::; em 2 E as returned by the command edges.
The strategy is to nd a minimal vertex coloring of the line graph of G by using the algorithm
described in Section 4.13.2.
> G:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> minimal_edge_coloring(G)
2; [1; 2; 3; 2; 3; 3; 4; 1; 2; 3; 1; 4; 1; 4; 2]
> H:=minimal_edge_coloring(graph("grotzsch"),sto)
an undirected unweighted graph with 11 vertices and 20 edges
> draw_graph(H,labels=false)

110

Graph properties

> G:=random_graph(100,0.1)
an undirected unweighted graph with 100 vertices and 499 edges
> minimal_edge_coloring(G):;
20.24 sec

4.14.2. Chromatic index
The command chromatic_index is used for computing the chromatic index of an undirected graph.
Syntax: chromatic_index(G)
chromatic_index(G,c)
chromatic_index accepts one or two arguments, an undirected graph G(E ; V ) and optionally an
unassigned identier c. The command returns the minimal number  0(G) of colors needed to color
each edge in G such that two incident edges never share the same color. If the second argument
is given, it species the destination for storing the coloring in form of a list of colors according to
the order of edges in E as returned by the command edges.
The example below demonstrates how to color the edges of a graph with colors obtained by passing
unassigned identier c to chromatic_index as the second argument.
> G:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> chromatic_index(G,c)
4
> draw_graph(highlight_edges(G,edges(G),c))

Blanu²a snarks, the two graphs with 18 vertices found in 1946 by Danilo Blanu²a, were the
second and third snarks discovered [6]. For almost fty years, Petersen graph was the only known
snark. The second Blanu²a snark is available in Giac by passing the string "blanusa" to the graph
command.
> G:=graph("blanusa")
an undirected unweighted graph with 18 vertices and 27 edges
> draw_graph(G,labels=false)

4.14 Edge coloring

111

> minimum_degree(G),maximum_degree(G)
3; 3
To prove that Blanu²a snark is bridgeless, it is enough to show that it is biconnected, since each
endpoint of a bridge is an articulation point (unless being of degree 1).
> is_biconnected(G)
true
> girth(G)
5
> chromatic_index(G)
4

Chapter 5
Traversing graphs
5.1. Walks and tours
5.1.1. Eulerian graphs
The command is_eulerian is used for determining whether an undirected graph contains an
Eulerian trail.
Syntax: is_eulerian(G)
is_eulerian(G,T)
is_eulerian accepts one or two arguments, an undirected graph G(V ; E) and optionally an
unassigned identier T, and returns true if G is Eulerian and false otherwise. If the second
argument is given, the corresponding Eulerian trail is stored to T.
A graph G is Eulerian if it has a trail covering all its edges. Such a trail is called Eulerian trail.
An Eulerian trail may be closed, in which case it is called Eulerian cycle. Note that every edge
e 2 E must be visited, i.e. strolled through, exactly once [23, pp. 395]. The edge endpoints (i.e. the
vertices in G) may, however, be visited more than once.
The strategy is to apply Hierholzer's algorithm for nding an Eulerian path [29]. It works by
covering one cycle at a time in the input graph. The required time is O(jE j).
> is_eulerian(complete_graph(4))
false
> is_eulerian(complete_graph([1,2,3,4,5]),T); T
true; [1; 2; 3; 4; 1; 5; 2; 4; 5; 3; 1]
> is_eulerian(graph("tetrahedron"))
false
> is_eulerian(graph("octahedron"))
true

5.1.2. Hamiltonian graphs
The command is_hamiltonian is used for checking hamiltonicity of an undirected graph. The
command can also construct a Hamiltonian cycle in the input graph if the latter is Hamiltonian.
Syntax: is_hamiltonian(G)
is_hamiltonian(G,hc)
is_hamiltonian accepts one or two arguments, an undirected graph G(V ; E) and optionally an
unassigned identier hc. The command returns true if G is Hamiltonian and false otherwise.
When failing to determine whether G is Hamiltonian or not, is_hamiltonian returns undef. If
the second argument is given, a Hamiltonian cycle is stored to hc.
113

114

Traversing graphs

The strategy is to apply some hamiltonicity criteria presented in DeLeon [13] before resorting
to the denitive but NP-hard algorithm. If G is not biconnected, it is not Hamiltonian. Else,
jV j
the criterion of Dirac is applied: if (G) > 2 , where (G) = min fdeg(v) : v 2 V g, then G is
Hamiltonian. Else, if G is bipartite with vertex partition V = V1 [ V2 and jV1j =
/ jV2j, then G is not
Hamiltonian. Else, the criterion of Ore is applied: if deg(u) + deg(v) > n holds for every pair u; v
of non-adjacent vertices from V , then G is Hamiltonian. Else, the theorem of Bondy and Chvátal
is applied: if the closure cl(G) of G (obtained by nding a pair u; v of non-adjacent vertices from
V such that deg(u) + deg(v) > n, adding a new edge u v to E and repeating the process until
exhaustion) is Hamiltonian, then G is Hamiltonian. (Note that in this case the previously tried
criteria are applied to cl(G); since the vertex degrees in cl(G) are generally higher than those in
G, the probability of success also rises.) Else, if the edge density of G is large enough, the criterion
n+2
of Nash and Williams is applied: if (G) > max
; , where is the independence number
3
of G, then G is Hamiltonian. If all of the above criteria fail, the command traveling_salesman
is called, either to nd a Hamiltonian cycle in G or to determine that none exist.
> is_hamiltonian(graph("soccerball"))
true
> is_hamiltonian(graph("octahedron"),hc)
true
> draw_graph(highlight_trail(graph("octahedron"),hc))
6

4

2
5

1

3

> is_hamiltonian(graph("herschel"))
false
> is_hamiltonian(graph("petersen"))
false
> is_hamiltonian(hypercube_graph(9))
true
6.04 sec

5.2. Optimal routing
5.2.1. Shortest unweighted paths
The command shortest_path is used for nding shortest paths in unweighted graphs.
Syntax: shortest_path(G,s,t)
shortest_path(G,s,T)
shortest_path accepts three arguments: an undirected unweighted graph G(V ; E), the source
vertex s 2 V and the target vertex t 2 V or a list T of target vertices. The shortest path from source
to target is returned. If more targets are specied, the list of shortest paths from the source to
each of these vertices is returned.

5.2 Optimal routing

115

The strategy is to run breadth-rst traversal on the graph G starting from the source vertex s.
The complexity of the algorithm is therefore O (jV j + jE j).
> G:=graph("dodecahedron")
an undirected unweighted graph with 20 vertices and 30 edges
> shortest_path(G,1,16)
[1; 6; 11; 16]
> paths:=shortest_path(G,1,[16,19])
f[1; 6; 11; 16]; [1; 5; 10; 14; 19]g
> H:=highlight_trail(G,paths,[red,green])
an undirected unweighted graph with 20 vertices and 30 edges
> draw_graph(H)
1
6
15

11

5

2

16
20

10

7
17

19
14

12
18
13
9

8

4

3

5.2.2. Cheapest weighted paths
The command dijkstra is used for nding cheapest paths in weighted graphs.
Syntax: dijkstra(G,s,t)
dijkstra(G,s,T)
dijkstra accepts two or three arguments: a weighted graph G(V ; E) with nonnegative weights, a
vertex s 2 V and optionally a vertex t 2 V or list T of vertices in V . It returns the cheapest path
from s to t or, if more target vertices are given, the list of such paths to each target vertex t 2 T ,
computed by Dijkstra's algorithm in O(jV j2) time. If no target vertex is specied, all vertices in
V n fsg are assumed to be targets.
A cheapest path from s to t is represented with a list [[v1,v2,...,vk],c] where the rst element
consists of path vertices with v1 = s and vk = t, while the second element c is the weight (cost) of
that path, equal to the sum of weights of its edges.
> G:=graph(%{[[1,2],1],[[1,6],3],[[2,3],3],[[3,4],7],[[4,5],3],[[5,6],3]%})
an undirected weighted graph with 6 vertices and 6 edges
> res:=dijkstra(G,1,4)
[[1; 6; 5; 4]; 9]
> draw_graph(highlight_trail(G,res[0]))
1

3

3

5

3

1

3
3

2

7

6

4

116

Traversing graphs

> dijkstra(G,1)
[[1]; 0]; [[1; 2]; 1]; [[1; 6]; 3]; [[1; 2; 3]; 4]; [[1; 6; 5; 4]; 9]; [[1; 6; 5]; 6]

5.2.3. Traveling salesman problem
The command traveling_salesman is used for solving traveling salesman problem (TSP)5.1.
Syntax: traveling_salesman(G,[opts])
traveling_salesman(G,M,[opts])
traveling_salesman accepts the following arguments: an undirected graph G(V ; E), a weight
matrix M (optional) and a sequence of options (optional). The supported options are approx and
vertex_distance.
If the input graph G is unweighted and M is not specied, a Hamiltonian cycle (tour) is returned
(the adjacency matrix of G is used for the edge weights). If G is weighted, two objects are returned:
the optimal value for the traveling salesman problem and a Hamiltonian cycle which achieves the
optimal value. If M is given and G is unweighted, M is used as the weight matrix for G.
If the option vertex_distance is passed and M is not specied, then for each edge e 2 E the
Euclidean distance between its endpoints is used as the weight of e. Therefore it is required for
each vertex in G to have a predened position.
If the option approx is passed, a near-optimal tour is returned. In this case it is required that G
is a complete weighted graph. For larger graphs, this is signicantly faster than nding optimal
tour. Results thus obtained are usually only a few percent larger than the corresponding optimal
values, despite the fact that the reported guarantee is generally much weaker (around 30%).
The strategy is to formulate TSP as a linear programming problem and to solve it by branch-andcut method, applying the hierarchical clustering method of Pferschy and Stan¥k [42] to generate
subtour elimination constraints. The branching rule is implemented according to Padberg and
Rinaldi [41]. In addition, the algorithm combines the method of Christofides [11], the method
of farthest insertion and a variant of the powerful tour improvement heuristic developed by Lin
and Kernighan [28] to generate near-optimal feasible solutions during the branch-and-cut process.
For Euclidean TSP instances, i.e. in cases when G is a complete graph with vertex distances as
the edge weights, the algorithm usually nishes in a few seconds for TSP with up to, say, 42 cities.
For problems with 100 or more cities, the option approx is recommended as nding the optimal
value takes a long time. Note that TSP is NP-hard, meaning that no polynomial time algorithm
is known. Hence the algorithm may take exponential time to nd the optimum in some instances.
The following example demonstrates nding a Hamiltonian cycle in the truncated icosahedral
(soccer ball) graph. The result is visualized by using the highlight_trail command.
> G:=graph("soccerball")
an undirected unweighted graph with 60 vertices and 90 edges
> draw_graph(highlight_trail(G,traveling_salesman(G)),labels=false)

5.1. For the details on traveling salesman problem and a historical overview see [12].

5.2 Optimal routing

117

A matrix may be passed alongside an undirected graph to specify the edge weights. The alternative
is to pass a weighted graph as the single argument.
> G:=graph("octahedron")
an undirected unweighted graph with 6 vertices and 12 edges
> M:=randmatrix(6,6,25)
0
B
B
B
B
B
B
@

13
7
24
16
20
8

7
17
15
3
9
17

15
23
19
10
9
19

10
3
15
18
2
20

17
17
20
1
19
15

6
5
24
3
15
15

> c,t:=traveling_salesman(G,M)

1
C
C
C
C
C
C
A

57.0; [4; 5; 2; 3; 1; 6; 4]
> draw_graph(highlight_trail(make_weighted(G,M),t))
6

20

24

15

23
4 15

2

13
17

1

5

5

10

3
13

3

In the next example, an instance of Euclidean TSP with 42 cities is solved to optimality. The
vertex positions are pairs of integers randomly chosen on the grid [0; 1000]  [0; 1000] 2 Z2.
> G:=set_vertex_positions(complete_graph(42),[randvector(2,1000)$(k=1..42)])
an undirected unweighted graph with 42 vertices and 861 edges
> c,t:=traveling_salesman(G,vertex_distance):;
10.01 sec

> draw_graph(subgraph(G,trail2edges(t)),labels=false)

For large instances of Euclidean TSP the approx option may be used, as in the following example
with 555 cities.
> H:=set_vertex_positions(complete_graph(555),[randvector(2,10000)$(k=1..555)])
an undirected unweighted graph with 555 vertices and 153735 edges
> ac,t:=traveling_salesman(H,vertex_distance,approx):;
49.34 sec

118

Traversing graphs

> draw_graph(subgraph(H,trail2edges(t)))

Near-optimal tours produced by the approx option are usually only slightly more expensive than
the optimal ones. For example, a sub-optimal tour for the previous instance G with 42 cities is
obtained by the following command.
> ac,st:=traveling_salesman(G,vertex_distance,approx):;
The tour cost is within 28% of the optimal value
Although it is guaranteed that the near-optimal cost ac is for at most 28% larger than c (the
optimum), the actual relative dierence is smaller than 3%, as computed below.
> 100*(ac-c)/c
2.7105821877

5.3. Spanning trees
5.3.1. Construction of spanning trees
The command spanning_tree is used for construction of spanning trees in graphs.
Syntax: spanning_tree(G)
spanning_tree(G,r)
spanning_tree accepts one or two arguments, an undirected graph G(V ; E) and optionally a
vertex r 2 V . It returns the spanning tree T (rooted in r) of G, obtained by depth-rst traversal
in O(jV j + jE j) time.
> P:=graph("petersen")
an undirected unweighted graph with 10 vertices and 15 edges
> T1:=spanning_tree(P)
an undirected unweighted graph with 10 vertices and 9 edges
> draw_graph(P)
0
5
4

1
9

6

8
3

7
2

By extracting T1 from P as a subgraph, it inherits vertex positions from P .
> draw_graph(subgraph(P,edges(T1)))

5.3 Spanning trees

119

0
5
4

1
6

9

8

7

3

2

> T2:=spanning_tree(P,4)
an undirected unweighted graph with 10 vertices and 9 edges
> edges(T1), edges(T2)
0

0
1
2
3
4
5
5
6
6

B
B
B
B
B
B
B
B
B
B
B
B
@

1
2
3
4
9
7
8
8
9

10
CB
CB
CB
CB
CB
CB
C;B
CB
CB
CB
CB
CB
A@

0
0
1
2
3
5
5
6
7

1
4
2
3
8
7
8
9
9

1
C
C
C
C
C
C
C
C
C
C
C
C
A

5.3.2. Minimal spanning tree
The command minimal_spanning_tree is used for obtaining minimal spanning trees in undirected
graphs.
Syntax: minimal_spanning_tree(G)
minimal_spanning_tree accepts an undirected graph G(V ; E) as its only argument and returns
its minimal spanning tree as a graph. If G is not weighted, it is assumed that the weight of each
edge in E is equal to 1.
The strategy is to apply Kruskal's algorithm which runs in O(jE j log jV j) time.
> A:=[[0,1,0,4,0,0],[1,0,1,0,4,0],[0,1,0,3,0,1],[4,0,3,0,1,0],[0,4,0,1,0,4],[0,
0,1,0,4,0]]:;
> G:=graph(A)
an undirected weighted graph with 6 vertices and 8 edges
> T:=minimal_spanning_tree(G)
an undirected weighted graph with 6 vertices and 5 edges
> edges(T,weights)
f[[0; 1]; 1]; [[1; 2]; 1]; [[2; 5]; 1]; [[2; 3]; 3]; [[3; 4]; 1]g
> draw_graph(highlight_subgraph(G,T))
0

2

4

1

3

4

4
1

1

4
1

1

3

5

5.3.3. Counting the spanning trees in a graph
The command number_of_spanning_trees is used for counting spanning trees in a graph.

120

Traversing graphs

Syntax: number_of_spanning_trees(G)
number_of_spanning_trees accepts an undirected graph G(V ; E) as its only argument and returns
the total number n of (labeled) spanning trees in G.
The strategy is to use Kirchhoff's Theorem [55, Theorem 2.2.12, pp. 86]. The number of spanning
trees is equal to the rst principal minor of the Laplacian matrix of G.
> number_of_spanning_trees(graph("octahedron"))
384
> number_of_spanning_trees(graph("dodecahedron"))
5184000
> number_of_spanning_trees(hypercube_graph(4))
42467328
> number_of_spanning_trees(graph("soccerball"))
375291866372898816000

Chapter 6
Visualizing graphs
6.1. Drawing graphs
The draw_graph command is used for visualizing graphs. It is capable to produce a drawing of
the given graph using one of the several built-in methods.
Syntax: draw_graph(G)
draw_graph(G,opts)

6.1.1. Overview
draw_graph accepts one or two arguments, the mandatory rst one being a graph G(V ; E). This
command assigns 2D or 3D coordinates to each vertex v 2 V and produces a visual representation
of G based on these coordinates. The second (optional) argument is a sequence of options. Each
option is one of the following:
¡

labels=true or false: controls the visibility of vertex labels and edge weights (by default
true, i.e. the labels and weights are displayed)

¡

spring: draw the graph G using a multilevel force-directed algorithm

¡

tree[=r or [r1,r2,...]]: draw the tree or forest G, optionally specifying root nodes for
each tree

¡

bipartite: draw the bipartite graph G keeping the vertex partitions separated

¡

circle[=L] or convexhull[=L]: draw the graph G by setting the hull vertices from list
L  V (assuming L = V by default) on the unit circle and all other vertices in origin,
subsequently applying a force-directed vertex placement algorithm to generate the layout
while keeping the hull vertices xed

¡

planar or plane: draw the planar graph G using a force-directed algorithm

¡

plot3d: draw the connected graph G as if the spring option was enabled, but with vertex
positions in 3D instead of 2D

¡

any unassigned identier P : when given, the vertex coordinates will be stored to it in form
of a list

The style options spring, tree, circle, planar and plot3d cannot be mixed, i.e. at most one can
be specied. The option labels may be combined with any of the style options. Note that edge
weights will not be displayed when using plot3d option when drawing a weighted graph.
When no style option is specied, the algorithm rst checks if the graph G is a tree or if it is
bipartite, in which cases it is drawn accordingly. Otherwise, the graph is drawn as if the option
circle was specied.
Tree, circle and bipartite drawings can be obtained in linear time with a very small overhead,
allowing graphs to be drawn quickly no matter the size. The force-directed algorithms are more
expensive and operating in the time which is quadratic in the number of vertices. Their performance
is, nevertheless, practically instantaneous for graphs with several hundreds of vertices (or less).

6.1.2. Drawing disconnected graphs
When the input graph has two or more connected components, each component is drawn separately
and the drawings are subsequently arranged such that the bounding box of the whole drawing has
the smallest perimeter under condition that as little space as possible is wasted inside the box.
121

122

Visualizing graphs

For example, the command lines below draw a sparse random planar graph.
> G:=random_planar_graph(100,0.9,0)
an undirected unweighted graph with 100 vertices and 74 edges
> draw_graph(G,planar)

6.1.3. Spring method
When the option spring is specied, the input graph is drawn using the force-directed algorithm
described in [32] (for an example of such a drawing see Figure 3.1). The idea, originally due to
Fruchterman and Reingold [21], is to simulate physical forces in a spring-electrical model
where the vertices and edges represent equally charged particles and springs connecting them,
respectively.
In a spring-electrical model, each vertex is being repulsed by every other vertex with a force
inversely proportional to the distance between them. At the same time, it is attracted to each of its
neighbors with a force proportional to the square of the distance. Assuming that xv is the vector
representing the position of the vertex v 2 V , the total force Fv applied to v is equal to
Fv =

X

w2V nfvg

¡

X
C K2
(xv ¡ xw) +
kxv ¡ xw k2

w2N (v)

kxv ¡ xw k
(xv ¡ xw);
K

where N (v) is the set of neighbors of v and C, K are certain positive real constants (actually, K
may be any positive number, it aects only the scaling of the entire layout). Applying the forces
iteratively and updating vertex positions in each iteration (starting from a random layout) leads the
system to the state of minimal energy. By applying a certain cooling scheme to the model which
cuts down the force magnitude in each iteration. the layout freezes after a number of iterations
large enough to achieve the minimal energy state.
The force-directed method is computationally expensive and for larger graphs the pleasing layout
cannot be obtained most of the time since the algorithm, starting with a random initial layout,
gets easily stuck in the local energy minimum (ideally, the vertex positions should settle in the
global minimal energy constellation). To avoid this a multilevel scheme is applied. The input graph
is iteratively coarsened, either by removing the vertices from a maximal independent vertex set
or contracting the edges of a maximal matching in each iteration. Each coarsening level is then
processed by the force-directed algorithm, starting from the deepest (coarsest) one and lifting the
obtained layout to the rst upper level, using it as the initial layout for that level. The lifting is
achieved by using the prolongation matrix technique described in [33]. To support drawing large
graphs (with 1000 vertices or more), the matrices used in the lifting process are stored as sparse
matrices. The multilevel algorithm is signicantly faster than the original, single-level one and
usually produces better results.
Graph layouts obtained by using force-directed method have a unique property of reecting symmetries in the design of the input graph, if any. Thus the drawings become more appealing and
illustrate the certain properties of the input graph better. To make the symmetry more prominent,
the drawing is rotated such that the axis, with respect to which the layout exhibits the largest
symmetry score, becomes vertical. As the symmetry detection is in general very computationally
expensiveup to O(jV j7) when using the symmetry measure of Purchase [54], for examplethe
algorithm deals only with the convex hull and the barycenter of the layout, which may not always
be enough to produce the optimal result. Nevertheless, this approach is very fast and seems to
work most of the time for graphs with a high level of symmetry.

6.1 Drawing graphs

123

For example, the following command lines produce a drawing of the tensor product of two graphs
using the force-directed algorithm.
> G1:=graph(trail(1,2,3,4,5,2))
an undirected unweighted graph with 5 vertices and 5 edges
> G2:=star_graph(3)
an undirected unweighted graph with 4 vertices and 3 edges
> G:=tensor_product(G1,G2)
an undirected unweighted graph with 20 vertices and 30 edges
> draw_graph(G,spring,labels=false)

The following example demonstrates drawing a much larger graph.
> S:=sierpinski_graph(5,4)
an undirected unweighted graph with 1024 vertices and 2046 edges
> draw_graph(S,spring)

Note that vertex labels are automatically suppressed because of the large number of vertices. On
our system, the algorithm took less than two seconds to produce the layout.
The spring method is also used for creating 3D graph layouts, which are obtained by passing the
option plot3d to the draw_graph command.
> draw_graph(graph("soccerball"),plot3d,labels=false)

> G1:=graph("icosahedron"):; G2:=graph("dodecahedron"):;
Done; Done
> G1:=highlight_edges(G1,edges(G1),red)

124

Visualizing graphs

an undirected unweighted graph with 12 vertices and 30 edges
> G2:=highlight_edges(G2,edges(G2),magenta)
an undirected unweighted graph with 20 vertices and 30 edges
> G:=disjoint_union(G1,G2)
an undirected unweighted graph with 32 vertices and 60 edges
> draw_graph(G,plot3d,labels=false)
z
x

y

6.1.4. Drawing trees
When the tree[=r] option is specied and the input graph G is a tree (and r 2 V ), it is drawn using
a fast but simple node positioning algorithm inspired by the well-known algorithm of Walker [52],
using the rst vertex (or the vertex r) as the root node. When drawing a rooted tree, one usually
requires the following aesthetic properties [10].
A1. The layout displays the hierarchical structure of the tree, i.e. the y-coordinate of a node is
given by its level.
A2. The edges do not cross each other.
A3. The drawing of a sub-tree does not depend on its position in the tree, i.e. isomorphic subtrees are drawn identically up to translation.
A4. The order of the children of a node is displayed in the drawing.
A5. The algorithm works symmetrically, i.e. the drawing of the reection of a tree is the reected
drawing of the original tree.
The algorithm implemented in Giac generally satises all the above properties but A3. Instead,
it tries to spread the inner sub-trees evenly across the available horizontal space. It works by
organizing the structure of the input tree into levels by using depth-rst search and laying out
each level subsequently, starting from the deepest one and climbing up to the root node. In the
end, another depth-rst traversal is made, shifting the sub-trees horizontally to avoid intersections
between their edges. The algorithm runs in O(jV j) time and uses the minimum of horizontal space
to draw the tree with respect to the specied root node r.
For example, the following command line produces the drawing of a random tree on 100 nodes.
> draw_graph(random_tree(100))

6.1 Drawing graphs

125

6.1.5. Drawing planar graphs
The algorithm implemented in Giac which draws planar graphs uses augmentation techniques to
extend the input graph G to a graph G 0, which is homeomorphic to some triconnected graph,
by adding temporary edges. The augmented graph G 0 is then drawn using Tutte's barycentric
method (see [51] and [23, pp. 293]) which puts each vertex in the barycenter of its neighbors. It
is guaranteed that a (non-strict) convex drawing will be produced, without edge crossings. In the
end, the duplicate of the outer face and the temporary edges inserted during the augmentation
stage are removed.
Tutte's algorithm requires that the vertices of the chosen outer face are initially xed somewhere
the boundary of a convex polygon. In addition, to produce a more exible layout, the outer face is
duplicated such that the subgraph induced by the vertices on both the outer face and its duplicate
is a prism graph. Then only the duplicates of the outer face vertices are xed, allowing the outer
face itself to take a more natural shape. The duplicate of the outer face is removed after a layout
is produced.
The augmentation process consists of two parts. Firstly, the input graph G is decomposed into
biconnected components (blocks) using the depth-rst search [22, pp. 25]. Each block is then
decomposed into faces (represented by cycles of vertices) using Demoucron's algorithm (see [22,
pp. 88] and [37]). Embeddings obtained for each blocks are then combined by adding one temporary
edge for each articulation point, joining the two corresponding blocks. Figure 6.1 shows the outer
faces of two blocks B1 and B2, connected by an articulation point (cut vertex). The temporary
temp. edge
B1

B2

Fig. 6.1. Joining two block by adding a temporary edge.

edge (shown in green) is added to join B1 and B2 into a single block. After folding up the tree
of blocks, the algorithm picks the largest face in the resulting biconnected graph to be the outer
face of the planar embedding.
The second part of the augmentation process consists of recursively decomposing each non-convex
inner face into several convex polygons by adding temporary edges. An inner face f = (v1; :::; vn)
is non-convex if there exist k and l such that 1 6 k < l ¡ 1 < n and either vk vl 2 E, in which case
the edge vk vl is a chord (see Figure 6.2 for an example) or there exists a face g = (w1; w2; :::; vk ; :::;
vl ; :::; wm¡1; wm) such that the vertices vk+1; :::; vl¡1 are not contained in g (see Figure 6.3 for an
example). In Figures 6.1, 6.2 and 6.3, the temporary edges added by the algorithm are drawn in
green.
This method of drawing planar graphs operates in O(jV j2) time. Nevertheless, it is quite fast
for graphs up to 1000 vertices, usually producing results in less than a second. The drawback of
this method is that it sometimes creates clusters of vertices which are very close to each other,
resulting in a very high ratio of the area of the largest inner face to the area of the smallest inner
face. However, if the result is not satisfactory, one should simply redraw the graph and repeat the
process until a better layout is found. The planar embedding will in general be dierent each time.
Another drawback of this method is that sparse planar graphs are sometimes drawn poorly.
The following example shows that the above described improvement of the barycentric method
handles non-triconnected graphs well.

126

Visualizing graphs

chord

f

Fig. 6.2. A chorded face.

f
vl
vk
g

Fig. 6.3. Two faces sharing a pair of vertices and no edges between them.

> G:=graph(trail(1,2,3,4,5,6,7,8,9,10,1),trail(11,12,6,11,1,12))
an undirected unweighted graph with 12 vertices and 15 edges
> draw_graph(G,planar)

Note that the inner diamond-like shape in the above drawing would end up attenedmaking the
two triangular faces invisibleif the input graph was not augmented. It is so because the vertices
with labels 11 and 12 are attracted to each other (namely, the two large faces are inating
themselves to become convex), causing them to merge eventually.
In the following example the input graph G is connected but not biconnected (it has two articulation points). It is obtained by removing a vertex from the Sierpi«ski triangle graph ST33. Note
that the syntax mode is set to Xcas in this example, so the rst vertex label is zero.
> G:=sierpinski_graph(3,3,triangle)
an undirected unweighted graph with 15 vertices and 27 edges
> G:=delete_vertex(G,3)
an undirected unweighted graph with 14 vertices and 23 edges
> draw_graph(G,planar,labels=false)

6.2 Vertex positions

127

In the above example, several redraws were required to obtain a good planar embedding.

6.1.6. Circular graph drawings
The drawing method selected by specifying the option circle=L or convexhull=L when calling
draw_graph on a triconnected graph G(V ; E), where L  V is a set of vertices in G, uses the
following strategy. First, positions of the vertices from L are xed so that they form a regular
polygon on the unit circle. Other vertices, i.e. all vertices from V n L, are placed in origin. Then
an iterative force-directed algorithm [43], similar to Tutte's barycentric method, is applied to
obtain the nal layout.
This approach gives best results for symmetrical graphs such as generalized Petersen graphs. In
addition, if the input graph is planar, the drawing will also be planar (there is a possibility, however,
that some very short edges may cross each other as the number of force update iterations is limited).
In the following example the Sierpi«ski graph S42 is drawn using the above method. Note that the
command lines below are executed in Xcas mode.
> G:=sierpinski_graph(2,4)
an undirected unweighted graph with 16 vertices and 30 edges
> draw_graph(G,circle=[0,1,4,5,7,13,15,14,11,10,8,2])

6.2. Vertex positions
6.2.1. Setting vertex positions
The command set_vertex_positions is used to assign custom coordinates to vertices of a graph
to be used when drawing the graph.
Syntax: set_vertex_positions(G,L)
set_vertex_positions accepts two arguments, a graph G(V ; E) and the list L of positions to be
assigned to vertices in order of vertices(G). The positions may be complex numbers, lists of coordinates or points (geometrical objects created with the command point). set_vertex_positions
returns the copy G 0 of G with the given layout stored in it.
Any subsequent call to draw_graph with G 0 as an argument and without specifying the drawing
style will result in displaying vertices at the stored coordinates. However, if a drawing style is
specied, the stored layout is ignored (although it stays stored in G 0).
> G:=digraph([1,2,3,4,5],%{[1,2],[2,3],[3,4],[2,5]%})
a directed unweighted graph with 5 vertices and 4 arcs
> draw_graph(G,circle)

128

Visualizing graphs

> H:=set_vertex_positions(G,[[0,0],[0.5,0],[1.0,0],[1.5,0],[0.5,1]])
a directed unweighted graph with 5 vertices and 4 arcs
> draw_graph(H)

6.2.2. Generating vertex positions
Vertex positions can be generated for a particular graph G by using the draw_graph command with
the additional argument P which should be an unassigned identier. After the layout is obtained,
it will be stored to P as a list of positions (complex numbers for 2D drawings or points for 3D
drawings) for each vertex in order of vertices(G).
This feature combines well with the set_vertex_positions command, as when one obtains the
desired drawing of the graph G by calling draw_graph, the layout coordinates can be easily stored
to the graph for future reference. In particular, each subsequent call of draw_graph with G as an
argument will display the stored layout. The example below illustrates this property by setting a
custom layout to the octahedral graph.
> G:=graph("octahedron")
an undirected unweighted graph with 6 vertices and 12 edges
> draw_graph(G)

> draw_graph(G,P,spring):;
Now P contains vertex coordinates, which can be permanently stored to G:
> G:=set_vertex_positions(G,P)
an undirected unweighted graph with 6 vertices and 12 edges
> draw_graph(G)

It should be noted that, after a particular layout is xed, it stays valid when some edges or vertices
are removed or when an edge is contracted. The stored layout becomes invalid only if a new vertex
is added to the graph (unless its position is specied by set_vertex_attribute upon the creation)
or if the position attribute of an existing vertex is discarded.

6.3 Highlighting parts of graphs

129

6.3. Highlighting parts of graphs
6.3.1. Highlighting vertices
The command highlight_vertex is used for changing color of one or more vertices in a graph.
Syntax: highlight_vertex(G,v)
highlight_vertex(G,v,c)
highlight_vertex(G,[v1,v2,..,vk])
highlight_vertex(G,[v1,v2,..,vk],c)
highlight_vertex(G,[v1,v2,..,vk],[c1,c2,..,ck])
highlight_vertex accepts two or three arguments: a graph G(V ; E), a vertex v 2 V or a list of
vertices v1; v2; :::; vk 2 V and optionally the new color c or a list of colors c1; c2; :::; ck for the selected
vertices (the default color is green). It returns a modied copy of G in which the specied vertices
are colored with the specied color.
> G:=graph("dodecahedron")
an undirected unweighted graph with 20 vertices and 30 edges
> L:=maximum_independent_set(G)
[2; 4; 6; 12; 13; 10; 16; 19]
> draw_graph(highlight_vertex(G,L))

6.3.2. Highlighting edges and trails
To highlight an edge or a set of edges in a graph, use the highlight_edges command. If the edges
form a trail, it is usually more convenient to use the highlight_trail command (see below).
Syntax: highlight_edges(G,e)
highlight_edges(G,e,c)
highlight_edges(G,[e1,e2,..,ek])
highlight_edges(G,[e1,e2,..,ek],c)
highlight_edges(G,[e1,e2,..,ek],[c1,c2,..,ck])
highlight_trail(G,T)
highlight_trail(G,T,c)
highlight_trail(G,[T1,T2,..,Tk])
highlight_trail(G,[T1,T2,..,Tk],c)
highlight_trail(G,[T1,T2,..,Tk],[c1,c2,..,ck])
highlight_edges accepts two or three arguments: a graph G(V ; E), an edge e 2 E or a list of
edges e1; e2; :::; ek 2 E and optionally the new color c or a list of colors c1; c2; :::; ck for the selected
edges (the default color is red). It returns a modied copy of G in which the specied edges are
colored with the specied color.
> M:=maximum_matching(G)
f[1; 2]; [5; 4]; [6; 11]; [3; 8]; [7; 12]; [9; 13]; [10; 15]; [14; 19]; [16; 17]g
> draw_graph(highlight_edges(G,M))

130

Visualizing graphs

> S:=spanning_tree(G)
an undirected unweighted graph with 20 vertices and 19 edges
> draw_graph(highlight_edges(G,edges(S),magenta))

highlight_trail accepts two or three arguments: a graph G(V ; E), a trail T or a list of trails T1;
T2; :::; Tk and optionally the new color c or a list of colors c1; c2; :::; ck. The command returns the
copy of G in which edges between consecutive vertices in each of the given trails are highlighted
with color c (by default red) or the trail Ti is highlighted with color ci for i = 1; 2; :::; k.
> draw_graph(highlight_trail(G,[6,15,20,19,18,17,16,11,7,2,3,8,13,9,14,10]))
1
6
15
5

11
2

20
16

10
19

7
17

14

12
18
13
9

8

4

3

> draw_graph(highlight_trail(G,shortest_path(G,1,[19,12]),[green,magenta]))
1
6
15
5

11
2

20
16

10
19

7
17

14

12
18
13
9

4

8
3

6.3.3. Highlighting subgraphs
The command highlight_subgraph is used for highlighting subgraph(s) of the given graph.
Syntax: highlight_subgraph(G,S,[weights])
highlight_subgraph(G,S,c1,c2,[weights])
highlight_subgraph(G,[S1,S2,..,Sk])
highlight_subgraph(G,[S1,S2,..,Sk],c1,c2)
highlight_subgraph accepts two or four arguments: a graph G(V ; E), a subgraph S(V 0; E 0) of
G or a list of subgraphs S1; S2; :::; Sk in G and optionally the new colors c1; c2 for the edges and
vertices of the selected subgraph(s), respectively. It returns a modied copy of G with the selected
subgraph(s) colored as specied. If colors are not given, red and green are used, respectively.
The option weights may be passed as an additional argument if G and S are weighted graphs.
In that case, the weights of edges in E 0  E in G are overwritten with those dened in S for the
same edges.

6.3 Highlighting parts of graphs

131

> G:=graph(%{[1,2],[2,3],[3,1],[3,4],[4,5],[5,6],[6,4]%})
an undirected unweighted graph with 6 vertices and 7 edges
> A:=articulation_points(G)
[3; 4]
> B:=biconnected_components(G)
[[4; 6; 5]; [3; 4]; [1; 3; 2]]
> H:=highlight_vertex(G,A,magenta)
an undirected unweighted graph with 6 vertices and 7 edges
> draw_graph(H)

> S:=induced_subgraph(G,B[0])
an undirected unweighted graph with 3 vertices and 3 edges
> H:=highlight_subgraph(G,S)
an undirected unweighted graph with 6 vertices and 7 edges
> draw_graph(H,spring)

Bibliography
[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]

Shehzad Afzal and Clemens Brand. Recognizing triangulated Cartesian graph products. Discrete Mathematics, 312:188193, 2012.
L. Alonso and R. Schott. Random Unlabelled Rooted Trees Revisited. In Proc. Int. Conf. on Computing and
Information 1994, pages 13521367.
Vladimir Bagatelj and Ulrik Brandes. Ecient generation of large random networks. Physical Review E,
71:036113, 2005.
Mohsen Bayati, Jeong Han Kim, and Amin Saberi. A Sequential Algorithm for Generating Random Graphs.
Algorithmica, 58:860910, 2010.
Norman Biggs. Algebraic graph theory. Cambridge University Press, Second edition, 1993.
Danilo Blanu²a. Problem £etiriju boja. Glasnik Mat.-Fiz. Astr. Ser. II , 1:3132, 1946.
Béla Bollobás. Modern Graph Theory. Graduate Texts in Mathematics. Springer, Corrected edition, 2002.
Coen Boot. Algorithms for Determining the Clustering Coecient in Large Graphs. Bachelor's thesis, Faculty
of Science, Utrecht University, 2016.
Daniel Brélaz. New Methods to Color the Vertices of a Graph. Communications of the ACM, 22:251256,
1979.
Cristoph Buchheim, Michael Jünger, and Sebastian Leipert. Improving Walker's Algorithm to Run in Linear
Time. In M. T. Goodrich and S. G. Kobourov, editors, Graph Drawing 2002, Lecture Notes in Computer
Science vol 2528, pages 344353. Springer-Verlag Berlin Heidelberg, 2002.
Nicos Christodes. Worst-case analysis of a new heuristic for the traveling salesman problem. Report 388,
Graduate School of Industrial Administration, 1976.
William J. Cook. In Pursuit of the Traveling Salesman: Mathematics at the Limits of Computation. Princeton
University Press, 2012.
Melissa DeLeon. A Study of Sucient Conditions for Hamiltonian Cycles. Rose-Hulman Undergraduate
Mathematics Journal, 1, Article 6, 2000. https://scholar.rose-hulman.edu/rhumj/vol1/iss1/6.
Isabel M. Díaz and Paula Zabala. A Branch-and-Cut Algorithm for Graph Coloring. Discrete Applied Mathematics, 154:826847, 2006.
Reinhard Diestel. Graph Theory. Springer-Verlag, New York, 1997.
Jack Edmonds. Paths, Trees, and Flowers. In Gessel I. and GC. Rota, editors, Classic Papers in Combinatorics, pages 361379. Birkhäuser Boston, 2009. Modern Birkhäuser Classics.
Jack Edmonds and Richard M. Karp. Theoretical improvements in algorithmic eciency for network ow
problems. Journal of the ACM, 19:248264, 1972.
Abdol H. Esfahanian and S. Louis Hakimi. On computing the connectivities of graphs and digraphs. Networks,
14:355366, 1984.
Shimon Even. Graph Algorithms. Computer software engineering series. Computer Science Press, 1979.
Robert W. Floyd. Algorithm 97: Shortest path. Communications of the ACM, 5:345, 1962.
T. M. J. Fruchterman and E. M. Reingold. Graph Drawing by Force-Directed Placement. Software: Practice
and Experience, 21:11291164, 1991.
Alan Gibbons. Algorithmic graph theory. Cambridge University Press, 1985.
Chris Godsil and Gordon F. Royle. Algebraic graph theory. Graduate Texts in Mathematics. Springer, First
edition, 2001.
Donald Goldfarb and Michael D. Grigoriadis. A computational comparison of the dinic and network simplex
methods for maximum ow. Annals of Operations Research, 13:81123, 1988.
Gary Haggard, David J. Pearce, and Gordon Royle. Computing Tutte Polynomials. ACM Transactions on
Mathematical Software, 37, 2010. Article No. 24.
Gary Haggard, David J. Pearce, and Gordon Royle. Edge-Selection Heuristics for Computing Tutte Polynomials. Chicago Journal of Theoretical Computer Science, 2010. Article 6.
S. L. Hakimi. On realizability of a set of integers as degrees of the vertices of a linear graph. I. Journal of
the Society for Industrial and Applied Mathematics, 10:496506, 1962.
Keld Helsgaun. General k-opt submoves for the LinKernighan TSP heuristic. Math. Prog. Comp., 1:119163,
2009.
Carl Hierholzer. Ueber die möglichkeit, einen Linienzug ohne Wiederholung und ohne Unterbrechung zu
umfahren. Mathematische Annalen, 6:3032, 1873.
Andreas M. Hinz, Sandi Klavºar, and Sara S. Zemlji£. A survey and classication of Sierpi«ski-type graphs.
Discrete Applied Mathematics, 217:565600, 2017.
John E. Hopcroft and Richard M. Karp. An n5/2 algorithm for maximum matchings in bipartite graphs.
SIAM Journal on Computing, 2:225231, 1973.
Yifan Hu. Ecient and High Quality Force-Directed Graph Drawing. Mathematica Journal, 10:3771, 2005.
Yifan Hu and Jennifer Scott. A Multilevel Algorithm for Wavefront Reduction. SIAM Journal on Scientic
Computing, 23:13521375, 2001.

133

134

Bibliography

[34]
[35]
[36]

Arthur B. Kahn. Topological sorting of large networks. Communications of the ACM, 5:558562, 1962.
B. D. McKay and A. Piperno. Practical Graph Isomorphism, II. J. Symbolic Computation, 60:94112, 2013.
Michael Monagan. A new edge selection heuristic for computing Tutte polynomials. In Proceedings of FPSAC
2012, pages 839850.
Wendy Myrwold and Willian Kocay. Errors in graph embedding algorithms. Journal of Computer and System
Sciences, 77:430438, 2011.
Albert Nijenhuis and Herbert S. Wilf. Combinatorial Algorithms. Computer Science and Applied Mathematics. Academic Press, Second edition, 1978.
Patric R. J. Östergård. A fast algorithm for the maximum clique problem. Discrete Applied Mathematics,
120:197207, 2002.
Richard Otter. The Number of Trees. The Annals of Mathematics, 2nd Ser., 49:583599, 1948.
Manfred Padberg and Giovanni Rinaldi. A Branch-and-Cut Algorithm for the Resolution of Large-Scale
Symmetric Traveling Salesman Problems. SIAM Review, 33:60100, 1991.
Ulrich Pferschy and Rostislav Stan¥k. Generating subtour elimination constraints for the TSP from pure
integer solutions. Central European Journal of Operations Research, 25:231260, 2017.
Bor Plestenjak. An Algorithm for Drawing Planar Graphs. Software: Practice and Experience, 29:973984,
1999.
Angelika Steger and Nicholas C. Wormald. Generating random regular graphs quickly. Combinatorics Probability and Computing, 8:377396, 1999.
R. E. Tarjan. Depth-First Search and Linear Graph Algorithms. SIAM Journal on Comp., 1:146160, 1972.
R. E. Tarjan. A note on nding the bridges of a graph. Information Processing Letters, 2:160161, 1974.
R. E. Tarjan. Applications of path compression on balanced trees. Journal of the ACM, 26:690715, 1979.
R. E. Tarjan. Two streamlined depth-rst search algorithms. Fundamenta Informaticae, 9:8594, 1986.
K. Thulasiraman, S. Arumugam, A. Brandstädt, and T. Nishizeki, editors. Handbook of Graph Theory,
Combinatorial Optimization, and Algorithms. CRC Press, 2016.
Etsuji Tomita, Akira Tanaka, and Haruhisa Takahashi. The worst-case time complexity for generating all
maximal cliques and computational experiments. Theoretical Computer Science, 363:2842, 2006.
W. T. Tutte. How to draw a graph. Proceedings of the London Mathematical Society, s3-13:743767, 1963.
John Q. Walker II. A nodepositioning algorithm for general trees. Software: Practice and Experience,
20:685705, 1990.
Stanley Wasserman and Katherine Faust. Social Network Analysis: Methods and Applications. Cambridge
University Press, 1994.
E. Welch and S. Kobourov. Measuring Symmetry in Drawings of Graphs. Computer Graphics Forum,
36:341351, 2017.
Douglas B. West. Introduction to Graph Theory. Pearson Education, 2002.
Herbert S. Wilf. The Uniform Selection of Free Trees. Journal of Algorithms, 2:204207, 1981.

[37]
[38]
[39]
[40]
[41]
[42]
[43]
[44]
[45]
[46]
[47]
[48]
[49]
[50]
[51]
[52]
[53]
[54]
[55]
[56]

Command Index

add_arc . . . . . . . . . . .
add_edge . . . . . . . . . .
add_vertex . . . . . . . . .
adjacency_matrix . . . . .
allpairs_distance . . . .
antiprism_graph . . . . . .
arrivals . . . . . . . . . .
articulation_points . . .
assign_edge_weights . . .
biconnected_components .
bipartite_matching . . . .
canonical_labeling . . . .
cartesian_product . . . .
chromatic_index . . . . . .
chromatic_number . . . . .
chromatic_polynomial . . .
clique_cover . . . . . . . .
clique_cover_number . . .
clique_number . . . . . . .
clique_stats . . . . . . . .
clustering_coefficient .
complete_binary_tree . . .
complete_graph . . . . . .
complete_kary_tree . . . .
connected_components . . .
contract_edge . . . . . . .
cycle_basis . . . . . . . .
cycle_graph . . . . . . . .
degree_sequence . . . . . .
delete_arc . . . . . . . . .
delete_edge . . . . . . . .
delete_vertex . . . . . . .
departures . . . . . . . . .
digraph . . . . . . . . . . .
dijkstra . . . . . . . . . .
discard_edge_attribute .
discard_graph_attribute .
discard_vertex_attribute
disjoint_union . . . . . .
draw_graph . . . . . . . . .
edge_connectivity . . . .
edges . . . . . . . . . . . .
export_graph . . . . . . . .
flow_polynomial . . . . . .
fundamental_cycle . . . .
get_edge_attribute . . . .
get_edge_weight . . . . . .
get_graph_attribute . . .
get_vertex_attribute . . .
girth . . . . . . . . . . . .
graph . . . . . . . . . . . .
graph_automorphisms . . .
graph_charpoly . . . . . .
graph_complement . . . . .
graph_equal . . . . . . . .
graph_join . . . . . . . . .
graph_power . . . . . . . .
graph_rank . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

graph_spectrum . . . .
graph_union . . . . . .
graph_vertices . . . .
greedy_color . . . . . .
grid_graph . . . . . . .
has_arc . . . . . . . . .
has_edge . . . . . . . .
highlight_edges . . . .
highlight_subgraph . .
highlight_trail . . . .
highlight_vertex . . .
hypercube_graph . . . .
import_graph . . . . . .
incidence_matrix . . .
incident_edges . . . .
induced_subgraph . . .
interval_graph . . . .
is_acyclic . . . . . . .
is_arborescence . . . .
is_biconnected . . . .
is_bipartite . . . . . .
is_clique . . . . . . .
is_connected . . . . . .
is_cut_set . . . . . . .
is_directed . . . . . .
is_eulerian . . . . . .
is_forest . . . . . . .
is_graphic_sequence .
is_hamiltonian . . . .
is_integer_graph . . .
is_isomorphic . . . . .
is_network . . . . . . .
is_planar . . . . . . .
is_regular . . . . . . .
is_strongly_connected
is_strongly_regular .
is_tournament . . . . .
is_tree . . . . . . . . .
is_triangle_free . . .
is_triconnected . . . .
is_two_edge_connected
is_vertex_colorable .
is_weighted . . . . . .
isomorphic_copy . . . .
kneser_graph . . . . . .
laplacian_matrix . . .
lcf_graph . . . . . . .
line_graph . . . . . . .
list_edge_attributes .
list_graph_attributes
list_vertex_attributes
lowest_common_ancestor
make_directed . . . . .
make_weighted . . . . .
maxflow . . . . . . . . .
maximum_clique . . . .
maximum_degree . . . .

48
48
47
67
93
19
64
84
44
82
98
75
32
110
107
78
101
101
100
99
103
15
14
15
82
50
26
13
61
48
48
47
64
10
115
53
51
52
30
121
85
59
56
78
26
53
49
51
52
95
. 9
75
70
28
60
30
31
83

135

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. 71
. 30
. 59
105

. 19
. 63
. 63

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

129
130
129
129
17
55
69
66
25
16
95
89
81
65
99
81
85
59
113
87
16
113
72
72
89
34
62
84
63
65
87
102
81
86
108
59
23
16
68
22
34
53
51
52
88
47
47
90
100
61

136

maximum_matching . . . . .
minimal_edge_coloring . .
minimal_spanning_tree . .
minimal_vertex_coloring .
minimum_cut . . . . . . . .
minimum_degree . . . . . .
mycielski . . . . . . . . .
neighbors . . . . . . . . .
network_transitivity . . .
number_of_edges . . . . . .
number_of_spanning_trees
number_of_vertices . . . .
odd_girth . . . . . . . . .
odd_graph . . . . . . . . .
path_graph . . . . . . . . .
permute_vertices . . . . .
petersen_graph . . . . . .
plane_dual . . . . . . . . .
prism_graph . . . . . . . .
random_bipartite_graph .
random_digraph . . . . . .
random_graph . . . . . . . .
random_network . . . . . .
random_planar_graph . . .
random_regular_graph . . .
random_sequence_graph . .
random_tournament . . . .
random_tree . . . . . . . .
relabel_vertices . . . . .
reliability_polynomial .
reverse_graph . . . . . . .
seidel_spectrum . . . . . .
seidel_switch . . . . . . .
sequence_graph . . . . . .

Command Index

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. 97

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

109
119
106
92
61
107
64
104
59
119
59
95
16
13
24
22
34
19
37
36
36
43
40
42
41
43
37
25
79
29
71
29
15

set_edge_attribute . . . . . . .
set_edge_weight . . . . . . . . .
set_graph_attribute . . . . . .
set_vertex_attribute . . . . . .
set_vertex_positions . . . . . .
shortest_path . . . . . . . . . .
sierpinski_graph . . . . . . . .
spanning_tree . . . . . . . . . .
st_ordering . . . . . . . . . . .
star_graph . . . . . . . . . . . .
strongly_connected_components
subdivide_edges . . . . . . . . .
subgraph . . . . . . . . . . . . .
tensor_product . . . . . . . . .
topologic_sort . . . . . . . . .
topological_sort . . . . . . . .
torus_grid_graph . . . . . . . .
trail . . . . . . . . . . . . . . .
trail2edges . . . . . . . . . . .
transitive_closure . . . . . . .
traveling_salesman . . . . . . .
tree_height . . . . . . . . . . .
tutte_polynomial . . . . . . . .
two_edge_connected_components
underlying_graph . . . . . . . .
vertex_connectivity . . . . . .
vertex_degree . . . . . . . . . .
vertex_distance . . . . . . . . .
vertex_in_degree . . . . . . . .
vertex_out_degree . . . . . . .
vertices . . . . . . . . . . . . .
web_graph . . . . . . . . . . . .
weight_matrix . . . . . . . . . .
wheel_graph . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

53
49
51
52
127
114
21
118
96
18
84
50
25
32
96
96
19
14
14
33
116
88
76
86
26
83
61
93
61
61
59
18
70
18



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.4
Linearized                      : No
Page Count                      : 136
Title                           : Graph theory package for Giac/Xcas
Creator                         : TeXmacs 1.99.7
Producer                        : TeXmacs 1.99.7 + Hummus 4.0
Create Date                     : 2018:09:13 11:56:39+02:00
EXIF Metadata provided by EXIF.tools

Navigation menu