graph TD; 0[4]; 1[5]; 0 --- 1; 1 -->|x^2+5| 0;
Graphs
Graphs with parallel edges, self-edges, edge directions, vertex and edge colors can easily be constructed. For example:
g = Graph()
n1 = g.add_node(4)
n2 = g.add_node(5)
g.add_edge(n1, n2)
g.add_edge(n2, n1, True, E("x^2+5"))yields the following graph:
The data of the nodes an edges can be any data in Rust and in Python it is a Symbolica Expression.
Export
Graphs can be written in Graphviz “dot” notation or in mermaid notation. For example:
print(g.to_dot())yields:
digraph G {
  0 [label="4"];
  1 [label="5"];
  0 -> 1 [dir=none,label="0"];
  1 -> 0 [label="5"];
}
Isomorphisms
You can check if two graphs are isomorphic using is_isomorphic.
Canonization
A graph can be written into its canonical form: a specific representation that any isomorphic version of the graph will map to.
For example:
g = Graph()
n0 = g.add_node(1)
n1 = g.add_node(0)
n2 = g.add_node(1)
n3 = g.add_node(0)
n4 = g.add_node(2)
n5 = g.add_node(0)
n6 = g.add_node(1)
n7 = g.add_node(0)
n8 = g.add_node(1)
g.add_edge(n0, n1)
g.add_edge(n0, n3)
g.add_edge(n1, n2)
g.add_edge(n1, n3)
g.add_edge(n1, n4)
g.add_edge(n1, n5)
g.add_edge(n2, n5)
g.add_edge(n3, n4)
g.add_edge(n3, n6)
g.add_edge(n3, n7)
g.add_edge(n4, n5)
g.add_edge(n4, n7)
g.add_edge(n5, n7)
g.add_edge(n5, n8)
g.add_edge(n6, n7)
g.add_edge(n7, n8)
g.canonize()graph TD; 0[0]; 1[1]; 2[2]; 3[3]; 4[4]; 5[5]; 6[6]; 7[7]; 8[8]; 0 --- 2; 0 --- 3; 0 --- 6; 0 --- 7; 0 --- 8; 1 --- 2; 1 --- 3; 1 --- 4; 1 --- 5; 1 --- 8; 2 --- 5; 2 --- 7; 2 --- 8; 3 --- 4; 3 --- 6; 3 --- 8;
Returns the canonized graph, the vertex map ([7, 0, 6, 2, 8, 3, 5, 1, 4]), the automorphism group size (8), and the orbit ((0 1 2 3)(4 5 6 7)(8)).
Graph generation
Symbolica can generate all connected graphs with external_edges half-edges and the given allowed list of vertex connections. The generator returns the canonical form of the graph and the size of its automorphism group (including edge permutations).
For example:
g, q, qb, gh, ghb = S('g', 'q', 'qb', 'gh', 'ghb')
graphs = Graph.generate([(1, g), (2, g)],
                        [[g, g, g], [g, g, g, g],
                         [q, qb, g], [gh, ghb, g]], max_loops=2)
for (g, sym) in graphs.items():
    print(f'Symmetry factor = 1/{sym}:')
    print(g.to_dot())generates all connected Feynman graphs for QCD up to 2 loops with the specified vertices and the correct symmetry factor.