Face cycles: the base cycle, and the faces of a plane graph that grows by ears #
lem:face-cycles — every face of a finite 2-connected polygonal plane graph has a cycle as
its boundary and is one of the two complementary regions of that cycle — is proved by growing
the graph from a cycle by ears (Graph.IsTwoConnected.ear_decomposition) and applying
thm:polygonal-crosscut at each step. This file supplies everything in that proof that is not
the crosscut application itself. The lemma is not proved here; see "What is missing" below,
which says exactly what is in the way.
The base cycle #
The blueprint's first paragraph, in full. "First choose a cycle of length at least three.
Such a cycle exists: under our convention the graph has at least three vertices, and every
vertex has at least two distinct neighbors. Indeed, if a vertex v had only one distinct
neighbor w, then deleting w would isolate v from some third vertex, contrary to
2-connectivity. Now take a maximal simple path. An endpoint has a neighbor on the path other
than its predecessor, and the resulting closed subpath is a cycle of length at least three."
Graph.IsTwoConnected.exists_adj_ne is the two-neighbours sentence; "take a maximal simple
path" is Graph.exists_longest_path, already in Schoenflies/Graph/Tree.lean and not rebuilt
here; and Graph.IsTwoConnected.exists_long_cycle is the conclusion, packaged as
Graph.IsLongCycle, a cycle together with a named third vertex. Naming the third vertex
rather than counting is what both consumers want: the counting clause of
Graph.IsTwoConnected, and — later — the non-degeneracy of the polygon the cycle draws.
Graph.cycleGraph is that cycle as a subgraph, and Graph.IsLongCycle.isTwoConnected is
"the cycle C is 2-connected, so Lemma lem:relative-ear builds the graph from C". This
is the one place "length at least three" is used: a two-vertex cycle is a Graph.banana, and
Graph.not_isTwoConnected_banana says it is not 2-connected.
One step of the induction #
Adding an ear removes the ear's own point set from the exterior and changes nothing else:
Graph.pointSet_union, Graph.exterior_union and Graph.face_union_eq_of_disjoint are
"all other faces are unchanged".
Graph.IsDrawing.exists_face_of_ear is "its interior is connected and disjoint from the
current graph, so it lies in one current face F": the ear's realisation without its two ends
is the interior of an arc, hence connected
(Schoenflies.IsArcBetween.isConnected_diff), and it misses the drawing of the current
subgraph altogether (Graph.IsDrawing.edgesCover_inter_pointSet).
Graph.IsDrawing.ends_mem_frontier_face is the next sentence, "the ear's two endpoints are
limits of its interior, which lies in F, so they lie on ∂F" — which is what makes the ear
a crosscut of that face.
Graph.IsDrawing.mono — a subgraph of a plane graph is a plane graph, with the same drawing —
is what lets the induction talk about the faces of the current subgraph at all.
An interface repair #
Graph.IsTwoConnected.ear_decomposition hands its step the ear's path but not the clause
∀ g ∈ D, g ∉ E(B), which Graph.IsTwoConnected.relative_ear_exists proves and which
Graph.IsTwoConnected.relative_grows_by_ear drops on the way. A geometric consumer needs it:
without it the ear may be drawn right on top of the current subgraph, and
Graph.IsDrawing.edgesCover_inter_pointSet is false. Graph.ear_edges_notMem_or_union_eq
recovers it in the only form available from the outside — either every edge of the ear is new,
or the ear is a single edge the subgraph already had and the enlarged graph is the old graph,
so the step has nothing to prove. The better fix is for the integrator to add the clause to
relative_grows_by_ear and to ear_decomposition; that would make this lemma unnecessary.
What is missing #
The crosscut application, and therefore lem:face-cycles itself. thm:polygonal-crosscut is
available as Schoenflies.IsPolygonalCrosscut and Schoenflies.polygonal_crosscut, whose
hypotheses are stated for Schoenflies.ClosedPolygons: an explicit cyclic vertex list with
vertex_inj, edges_meet and corner (no two consecutive edges collinear). The realisation
of a graph cycle arrives here as a set — Graph.edgesCover drawing (e :: D) — which
Graph.IsDrawing.cycle_isJordanCurve knows to be a Jordan curve and Graph.polygonal_redrawing
knows to be polygonal. Turning such a set into a ClosedPolygon (enumerate its vertices
cyclically, delete the redundant collinear ones, and derive vertex_inj and edges_meet from
simplicity) is a construction main does not have, and the same construction is needed again
for the two curves Aᵢ ∪ P that the crosscut produces. Nothing below pretends to it, and no
statement below is weaker than its blueprint counterpart.
Namespace #
Root Graph, as fixed by Schoenflies/Graph/Walk.lean. The two arc lemmas are stated in
Schoenflies, where the rest of the arc theory lives.
Blueprint #
Graph.IsTwoConnected.exists_adj_ne— "every vertex has at least two distinct neighbors".Graph.IsLongCycle,Graph.IsTwoConnected.exists_long_cycle— "the resulting closed subpath is a cycle of length at least three".Graph.cycleGraph,Graph.IsLongCycle.isTwoConnected— "the cycleCis 2-connected, so Lemmalem:relative-earbuilds the graph fromC".Graph.ear_edges_notMem_or_union_eq— the ear's edges are new, or the ear is not an ear.Graph.pointSet_union,Graph.exterior_union,Graph.face_union_subset,Graph.face_union_eq_of_disjoint— "all other faces are unchanged".Graph.IsDrawing.mono— the current subgraph is itself a plane graph.Schoenflies.IsArcBetween.isConnected_diff,Schoenflies.IsArcBetween.left_mem_closure_diff,…right_mem_closure_diff,Graph.IsDrawing.edgesCover_inter_pointSet,Graph.IsDrawing.exists_face_of_ear,Graph.IsDrawing.ends_mem_frontier_face— "its interior is connected and disjoint from the current graph, so it lies in one current faceF… the ear's two endpoints are limits of its interior, which lies inF, so they lie on∂F; the ear is therefore a crosscut of that side".
Two distinct neighbours #
A vertex of a loopless 2-connected graph has a neighbour other than any prescribed vertex — in particular it has two distinct neighbours, and neither is itself.
The base cycle #
"Take a maximal simple path" is Graph.exists_longest_path, already in
Schoenflies/Graph/Tree.lean — it is what the three-leaf lemma runs on — so nothing here
rebuilds it.
A cycle with at least three vertices — the blueprint's "cycle of length at least three". The third vertex is named rather than counted, because that is what both consumers want.
- isCycle : G.IsCycleThrough e u v D
The edge and the detour form a cycle.
The detour visits a third vertex …
… distinct from the source of the edge …
… and from its target.
Instances For
The two ends of the edge are distinct: otherwise the detour would be a path from a vertex to itself, hence empty, and would visit no third vertex.
"The resulting closed subpath is a cycle of length at least three." A finite loopless 2-connected graph has a cycle with three distinct vertices.
Take a maximal path u —W→ v. Its source u has a neighbour x other than the vertex w₀
the path first steps to (Graph.IsTwoConnected.exists_adj_ne), and x lies on the path:
otherwise the edge to it could be prepended, contradicting maximality. Cutting the path at x
gives a path from u to x whose first step is still to w₀, and the chord closes it into a
cycle through u, w₀ and x. The chord is not an edge of that piece: an edge at u in the
tail is what the path's freshness clause forbids, and the first edge is not the chord because
their far ends differ.
The cycle as a subgraph, and its 2-connectivity #
Graph.IsTwoConnected.ear_decomposition starts from a 2-connected subgraph. The subgraph the
blueprint starts from is the base cycle, and this section builds it and proves it 2-connected.
This is the one place where "length at least three" is used: a two-vertex cycle is a
Graph.banana, and Graph.not_isTwoConnected_banana says it is not 2-connected.
A path graph grows with its edge list. General, and not in
Schoenflies/Graph/PathGraph.lean; the integrator may want to hoist it.
The subgraph of G drawn by a cycle: the detour followed by the edge, as a closed walk.
Exported as the object rather than hidden behind an existential — the consumer of
lem:face-cycles needs the graph itself, to feed it to the ear decomposition.
Equations
- G.cycleGraph u e D = G.pathGraphOf u (D ++ [e])
Instances For
The detour spans a path subgraph of the cycle.
Closing the cycle adds no vertex: both ends of the edge are already on the detour.
The edge of the cycle really is an edge of the cycle graph, joining the same two ends.
The cycle graph is connected: every vertex it has is visited by the detour, and the detour's own prefix runs there from the source.
A cycle with three vertices is 2-connected, which is what
Graph.IsTwoConnected.ear_decomposition asks of its starting subgraph.
Delete a vertex c. One of the two ends of the cycle's edge survives, and it is the hub:
every remaining vertex reaches an end of the detour inside the detour
(Graph.IsPathGraph.reaches_an_end), an end which — having been reached after the deletion —
survived it too, so the cycle's edge is still there to carry it the rest of the way.
An ear that is not new #
Graph.IsTwoConnected.ear_decomposition hands its step the ear's path but not the clause
∀ g ∈ D, g ∉ E(B) that Graph.IsTwoConnected.relative_ear_exists proves and that
Graph.IsTwoConnected.relative_grows_by_ear drops. A geometric consumer needs it: the ear's
drawing has to miss the drawing of the current subgraph, and an edge shared with B would sit
right on it.
It is recoverable, and this section recovers it. An edge of the ear that B already has must
join the ear's two ends; the ear is then that single edge, and the enlarged graph is the old
one, so the step has nothing to prove. The integrator may prefer to add the clause to
relative_grows_by_ear and to ear_decomposition instead — that is the better fix, and it
makes this section unnecessary.
An edge of a path incident to its source is the path's first edge, in the form that
decomposes the path — Graph.IsPath.eq_head_of_inc_source says the same about a list already
known to be a cons, and is what does the work here.
An edge of an ear that the subgraph already has is the whole ear. Both ends of such an edge lie in the subgraph, so the ear's freshness clause makes them the ear's own two ends; the edge is then the ear's first edge and its far end is the ear's target, so nothing follows it.
Either every edge of the ear is new, or the ear changes nothing. The disjunction the
step of Graph.IsTwoConnected.ear_decomposition has to open before it can do any geometry.
The faces of a graph that grows #
Adding an ear removes the ear's own point set from the exterior and changes nothing else. That
is the whole of "all other faces are unchanged", and the half of "its interior is connected and
disjoint from the current graph, so it lies in one current face F" that is pure topology.
What a union of two plane graphs occupies is what the two of them occupy.
Adding a graph removes exactly its own point set from the exterior.
A face of the enlarged graph lies inside a face of the old one.
"All other faces are unchanged." A face the ear does not touch survives the ear.
"Its interior is connected and disjoint from the current graph, so it lies in one current face." The topological half: a nonempty preconnected subset of the exterior lies in one face.
The ear lies in one face #
The blueprint's "its interior is connected and disjoint from the current graph, so it lies in
one current face F", in full.
The ear's realisation meets the drawing of the current subgraph only in the ear's two
ends. Two cases, and both come down to the ear's freshness clause: a point of the ear on a
vertex of B is an end of the edge of the ear it lies on
(Graph.IsDrawing.vertex_mem_edgeArc), and a point of the ear on an edge of B is a vertex
incident with both (Graph.IsDrawing.edge_inter) — the two edges being distinct because no
edge of the ear belongs to B. Either way the point is a vertex of B that the ear visits,
which the freshness clause makes one of the ear's two ends.
"Its interior is connected and disjoint from the current graph, so it lies in one current
face F." The ear's realisation without its two ends is an arc's interior, hence connected,
and it misses the drawing of B altogether, so it lies in a single face.
A subgraph of a plane graph is a plane graph #
The induction speaks of the faces of the current subgraph, so every step needs the current
subgraph to be a plane graph in its own right. Nothing has to be redrawn: the same drawing
serves. General, and not in Schoenflies/Graph/Drawing.lean; the integrator may want to hoist
it.
A subgraph of a plane graph is a plane graph, with the same drawing.
The ear's ends lie on the boundary of the face its interior lies in #
"The ear's two endpoints are limits of its interior, which lies in F, so they lie on
∂F." This is the hypothesis thm:polygonal-crosscut needs of a crosscut: its two ends are
on the boundary curve of the region it cuts.