https://github.com/patmorin/lhp
An implementation of layered H-partitions
https://github.com/patmorin/lhp
layered-h-partition planar-graph product-structure-theorem tripod-partition
Last synced: about 2 months ago
JSON representation
An implementation of layered H-partitions
- Host: GitHub
- URL: https://github.com/patmorin/lhp
- Owner: patmorin
- Created: 2020-07-23T02:28:22.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2021-01-06T11:14:43.000Z (over 4 years ago)
- Last Synced: 2025-01-31T11:50:00.933Z (4 months ago)
- Topics: layered-h-partition, planar-graph, product-structure-theorem, tripod-partition
- Language: Python
- Homepage:
- Size: 1.1 MB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# An Implementation of the Product Structure Theorem for Planar Graphs
An implementation of layered H-partitions, a.k.a, the Product Structure Theorem for planar graphs. This implements the algorithm described in [arXiv:2004.02530](https://arxiv.org/abs/2004.02530).
# lhp.py
`lhp.py` is a module that includes the `tripod_partition` class and is also a standalone command-line program.
## The `tripod_partition` class
The useful thing for programmers is the `tripod_partition` class, whose constructor requires an embedding of a planar triangulation *G* with vertex set \{0,..,*n*-1\} and a list of three vertices `outer_face` that lists the vertices of some face in counterlockwise order.
The triangulation *G* must be described as a list `succ` of length *n*. The list entry `succ[i]` is a dictionary that maps each neighbour *j* of *i* onto the neighbour *k* of *i* that appears immediately after *j* when ordering the neighbours of *i* in counterclockwise order around *i*. Specifically, `(i,j,k)` is a triangular face of *G*. For any directed edge `ij`, `succ[i][j]` is the third vertex of the face to the left of `ij`.
If you have a standard adjacency list representation of *G* you can use the following function to convert it to the formatted needed by the `tripod_partition` constructor:
def al2succ(al):
succ = list()
for neighbours in al:
succ.append(dict())
for i in range(len(neighbours)):
succ[-1][neighbours[i]] = neighbours[(i+1)%len(neighbours)]
return succAfter constructing it, the tripod partition has several parts:
- `t`: This is a BFS tree rooted at `roots`, stored in an adjacency list representation. This tree is represented as a list of length *n*. For each `i` in \{0,...,`n`-1\}, `t[i]` is the list of nodes adjacent to `i` beginning with the parent node, so `t[i][0]` is the parent of `i` in the BFS tree. The parent of each outer face node is `-1`, so `t[j][0] = -1` for each j in `outer_face`.
- `tripods`: This is a list of *closed tripods*. Each tripod `tripods[t]` is a list of 3 vertical paths in the BFS tree T called the *legs* of `t`. Each leg `tripods[t][i]` of each tripod contains a *foot* `tripods[t][i][-1]`. For each `t>0` each each `i` in \{1,2,3\}, the foot `tripods[t][i][-1]` appears—not as a foot—in exactly one other tripod, so `tripods[t][i][-1]` is contained in `tripods[p][j][:-1]` for some `(p,j)`. When this happens, `p` is called the *parent tripod* of `t`. The only exception is the *root tripod* `tripods[0]`, for which `tripods[0][i][-1]=-1` for each `i` in \{0,1,2\}. The *open* tripod `t` consists of the tripod `t` minus its three feet. The open tripods form a partition of the vertices of *G*, as do the legs of the open tripods; each vertex of *G* appears in exactly one leg of one open tripod.
- `tripod_map`: This is a list of length *n* that maps each *v* vertex of *G* onto a triple `(ti,l,j)` where `ti` is the tripod that contains *v*, `l` is the leg that contains *v* and `j` is the location of *v* in this leg. So, if `(ti,l,j) = tripod_map[v]` then `tripods[ti][l][j]=v`.
- `tripod_tree`: This is a list of length `len(tripods)` that encodes a 3-ary tree whose nodes are tripods. This tree has the property that `tripods[i][j][:-1]` (a vertical path in `t`) has no vertex adjacent to any open tripod in the subtree `tripod_tree[i][j]`. (Leg *j* of the tripod is separated from all tripods contained in subtree *j*.) A useful property of these tripods is that they are ordered by a preorder traversal of the tripod tree. If tripod `a` is an ancestor of tripod `t`, then this makes it possible to know, in constant-time, which of the three subtrees of `a` contains `t`.## Tree decompositions of quotient graphs
A `tripod_partition` induces two quotient graphs: The graph h3 is the graph obtained by contracting each open tripod. The graph h8 is the graph obtained by contracting each leg of each open tripod. The data members `tripod_tree`, `tripods`, and `tripod_map` can be used to obtain a width-3 tree-decomposition of h3 and a width-8 tree decomposition of h8. The `tripod_partition` class includes members functions for doing this:
- `h3parents(t)`: returns a list of (at most 3) tripods that are the parents of t in a width-3 tree decomposition of h3.
- `h8parents(t, i)`: returns a lsit of (at most 8) tripods that are the parents of leg i of tripod t in a width-8 tree decomposition of h8.The numbering of tripods is such that `p
-h show this message
-c use collinear points
-y use random points in triangle
-r use random points in disk (default)
-w use O(n log n) time algorithm (default)
-b use O(n^2) time algorithm (usually faster)
-nv don't verify correctness of results
the number of points to use (default = 10)If *n* < 500 then this program will show the result in a matplotlib window, producing pictures that look like this:


Run `lhp_demo.py -h` for a list of options
# References
For more information on the Product Structure Theorem and the algorithm described here, see the following references:
- [arxiv:1904.04791](https://arxiv.org/abs/1904.04791) introduces the tripod decomposition and uses it to solve an old problem on planar graphs.
- [arxiv:1807.03683](https://arxiv.org/abs/1807.03683) introduces a slightly different tripod decomposition, on which the one described in the previous reference is based.
- [arxiv:2004.02530](https://arxiv.org/abs/2004.02530) describes the algorithm used in this implementationThe product structure theorem has been used to solve a number of problems on planar graphs, including [queue number](https://arxiv.org/abs/1904.04791), [nonrepetitive colouring](https://arxiv.org/abs/1904.05269), [adjacency labelling](https://arxiv.org/abs/2003.04280), [universal graphs](https://arxiv.org/abs/2010.05779), [vertex ranking](https://arxiv.org/abs/2007.06455) and [p-centered colouring](https://arxiv.org/abs/1907.04586). You can probably find more on [Google Scholar](https://scholar.google.com/scholar?cites=16964377059594834981).
There are product structure theorems for generalizations of planar graphs, including [bounded-genus and apex-minor-free graphs](https://arxiv.org/abs/1904.04791) and [k-planar graphs](https://arxiv.org/abs/1907.05168). Most of these ultimately rely on a subroutine computing the product structure of planar graphs like the one given in this implementation.