Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
implement edge polytope and symmetric edge polytope
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Kliem committed Sep 10, 2021
1 parent a3bd572 commit fe16d78
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/sage/geometry/polyhedron/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
from .constructor import Polyhedron
from .parent import Polyhedra
from sage.graphs.digraph import DiGraph
from sage.graphs.graph import Graph
from sage.combinat.root_system.associahedron import Associahedron

def zero_sum_projection(d, base_ring=RDF):
Expand Down Expand Up @@ -3412,6 +3413,8 @@ def parallelotope(self, generators, backend=None):
associahedron = staticmethod(Associahedron)

flow_polytope = staticmethod(DiGraph.flow_polytope)
edge_polytope = staticmethod(Graph.edge_polytope)
symmetric_edge_polytope = staticmethod(Graph.symmetric_edge_polytope)


polytopes = Polytopes()
205 changes: 205 additions & 0 deletions src/sage/graphs/generic_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -23475,6 +23475,211 @@ def katz_centrality(self, alpha , u=None):
K.update({u: sum(M[i]) for i, u in enumerate(verts)})
return K

def edge_polytope(self, backend=None):
r"""
Return the edge polytope of ``self``.

The edge polytope (EP) of a Graph on `n` vertices
is a polytope in `\RR^{n}` defined as the convex hull of
`e_i + e_j` for each edge `(i, j)`.
Here `e_1, \dots, e_n` denotes the standard basis.

INPUT:

- ``backend`` -- string or ``None`` (default); the backend to use;
see :meth:`sage.geometry.polyhedron.constructor.Polyhedron`

EXAMPLES:

The EP of a `4`-cycle is a square::

sage: G = graphs.CycleGraph(4)
sage: P = G.edge_polytope(); P
A 2-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices

The EP of a complete graph on `4` vertices is cross polytope::

sage: G = graphs.CompleteGraph(4)
sage: P = G.edge_polytope(); P
A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices
sage: P.is_combinatorially_isomorphic(polytopes.cross_polytope(3))
True

The EP of a graph with edges is isomorphic
to the product of it's connected components with edges::

sage: n = randint(5, 12)
sage: G = Graph()
sage: while not G.num_edges():
....: G = graphs.RandomGNP(n, 0.2)
sage: P = G.edge_polytope()
sage: components = [G.subgraph(c).edge_polytope()
....: for c in G.connected_components()
....: if G.subgraph(c).num_edges()]
sage: P.is_combinatorially_isomorphic(product(components))
True

All trees on `n` vertices have isomorphic EP::

sage: n = randint(4, 10)
sage: G1 = graphs.RandomTree(n)
sage: G2 = graphs.RandomTree(n)
sage: P1 = G1.edge_polytope()
sage: P2 = G2.edge_polytope()
sage: P1.is_combinatorially_isomorphic(P2)
True

However, there are still many different EPs:

sage: len(list(graphs(5)))
34
sage: polys = []
sage: for G in graphs(5):
....: P = G.edge_polytope()
....: for P1 in polys:
....: if P.is_combinatorially_isomorphic(P1):
....: break
....: else:
....: polys.append(P)
....:
sage: len(polys)
19
"""
from sage.matrix.special import identity_matrix
from sage.geometry.polyhedron.parent import Polyhedra
dim = self.num_verts()
e = identity_matrix(dim).rows()
dic = {v: e[i] for i, v in enumerate(self.vertices())}
vertices = ((dic[i] + dic[j]) for i,j in self.edge_iterator(sort_vertices=False, labels=False))
parent = Polyhedra(ZZ, dim, backend=backend)
return parent([vertices, [], []], None)

def symmetric_edge_polytope(self, backend=None):
r"""
Return the symmetric edge polytope of ``self``.

The symmetric edge polytope (SEP) of a Graph on `n` vertices
is a polytope in `\RR^{n}` defined as the convex hull of
`e_i - e_j` and `e_j - e_i` for each edge `(i, j)`.
Here `e_1, \dots, e_n` denotes the standard basis.

INPUT:

- ``backend`` -- string or ``None`` (default); the backend to use;
see :meth:`sage.geometry.polyhedron.constructor.Polyhedron`

EXAMPLES:

The SEP of a `4`-cycle is a cube::

sage: G = graphs.CycleGraph(4)
sage: P = G.symmetric_edge_polytope(); P
A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 8 vertices
sage: P.is_combinatorially_isomorphic(polytopes.cube())
True

The SEP of a complete graph on `4` vertices is a cuboctahedron::

sage: G = graphs.CompleteGraph(4)
sage: P = G.symmetric_edge_polytope(); P
A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 12 vertices
sage: P.is_combinatorially_isomorphic(polytopes.cuboctahedron())
True

The SEP of a graph with edges on `n` vertices has dimension `n`
minus the number of connected components::

sage: n = randint(5, 12)
sage: G = Graph()
sage: while not G.num_edges():
....: G = graphs.RandomGNP(n, 0.2)
sage: P = G.symmetric_edge_polytope()
sage: P.ambient_dim() == n
True
sage: P.dim() == n - G.connected_components_number()
True

The SEP of a graph with edges is isomorphic
to the product of it's connected components with edges::

sage: n = randint(5, 12)
sage: G = Graph()
sage: while not G.num_edges():
....: G = graphs.RandomGNP(n, 0.2)
sage: P = G.symmetric_edge_polytope()
sage: components = [G.subgraph(c).symmetric_edge_polytope()
....: for c in G.connected_components()
....: if G.subgraph(c).num_edges()]
sage: P.is_combinatorially_isomorphic(product(components))
True

All trees on `n` vertices have isomorphic SEP::

sage: n = randint(4, 10)
sage: G1 = graphs.RandomTree(n)
sage: G2 = graphs.RandomTree(n)
sage: P1 = G1.symmetric_edge_polytope()
sage: P2 = G2.symmetric_edge_polytope()
sage: P1.is_combinatorially_isomorphic(P2)
True

However, there are still many different SEPs:

sage: len(list(graphs(5)))
34
sage: polys = []
sage: for G in graphs(5):
....: P = G.symmetric_edge_polytope()
....: for P1 in polys:
....: if P.is_combinatorially_isomorphic(P1):
....: break
....: else:
....: polys.append(P)
....:
sage: len(polys)
25

A non-trivial example of two graphs with isomorphic SEP::

sage: G1 = graphs.CycleGraph(4)
sage: G1.add_edges([[0, 5], [5, 2], [1, 6], [6, 2]])
sage: G2 = copy(G1)
sage: G1.add_edges([[2, 7], [7, 3]])
sage: G2.add_edges([[0, 7], [7, 3]])
sage: G1.is_isomorphic(G2)
False
sage: P1 = G1.symmetric_edge_polytope()
sage: P2 = G2.symmetric_edge_polytope()
sage: P1.is_combinatorially_isomorphic(P2)
True

Apparently, glueing two graphs together on a vertex
gives isomorphic SEPs::

sage: n = randint(3, 7)
sage: g1 = graphs.RandomGNP(n, 0.2)
sage: g2 = graphs.RandomGNP(n, 0.2)
sage: G = g1.disjoint_union(g2)
sage: H = copy(G)
sage: G.merge_vertices(((0, randrange(n)), (1, randrange(n))))
sage: H.merge_vertices(((0, randrange(n)), (1, randrange(n))))
sage: PG = G.symmetric_edge_polytope()
sage: PH = H.symmetric_edge_polytope()
sage: PG.is_combinatorially_isomorphic(PH)
True
"""
from itertools import chain
from sage.matrix.special import identity_matrix
from sage.geometry.polyhedron.parent import Polyhedra
dim = self.num_verts()
e = identity_matrix(dim).rows()
dic = {v: e[i] for i, v in enumerate(self.vertices())}
vertices = chain(((dic[i] - dic[j]) for i,j in self.edge_iterator(sort_vertices=False, labels=False)),
((dic[j] - dic[i]) for i,j in self.edge_iterator(sort_vertices=False, labels=False)))
parent = Polyhedra(ZZ, dim, backend=backend)
return parent([vertices, [], []], None)


def tachyon_vertex_plot(g, bgcolor=(1,1,1),
vertex_colors=None,
vertex_size=0.06,
Expand Down

0 comments on commit fe16d78

Please sign in to comment.