coloring_nested_tire_graphs: define "cut tire" with multi-depth visualisation

Adds Definition (cut tire) to cut_depth_label.tex:

  Given the depth labelling on G'_i, for each d > 0 let H_d be the
  subgraph on depth-d edges (with inherited planar embedding).  For
  each face f of H_d, the cut tire at (d, f) is the subgraph of G'_i
  consisting of:
    - every edge on the boundary walk of f (all depth d), and
    - every edge of G'_i incident to the boundary walk of f with
      depth d-1 or d+1.

The depth-d edges form the "face boundary"; the d-1 edges are
"inner spokes" (toward the cut); the d+1 edges are "outer spokes."

This is the dual-side analogue of the tire annular face connector
T'_{f'} (paper.tex Def. 1.16):
  face boundary ↔ T'_ann (annular subgraph at depth d)
  cut tire     ↔ T'_{f'} (annular face connector)
  inner/outer spokes ↔ inner/outer spokes of T'_{f'}

Adds experiments/cut_tire.py producing fig_cut_tire.png:
5-panel visualisation of cut tires at depths d = 1, 2, 4, 5, 6 on
G'_1 (V\S half of Holton-McKay #0). Outermost tire at d=1 (face
length 12, 5+4 spokes); innermost at d=6 (face length 12, 7+1).

Note grows from 3 → 5 pages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 15:32:47 -04:00
parent d065c5c31b
commit 53a676971c
6 changed files with 398 additions and 31 deletions
@@ -0,0 +1,247 @@
"""Define and visualise a cut tire: a structure built from a face of
the depth-d subgraph of a cut half G'_i, together with adjacent edges
at depths d-1 and d+1.
Procedure for a chosen d > 0:
1. Build H_d := subgraph of G'_i on edges of depth d.
2. Find the faces of H_d in the inherited planar embedding.
3. Pick one face f.
4. The cut tire at (d, f) is the subgraph of G'_i consisting of:
- The boundary edges of f (all depth d in H_d), AND
- All edges of G'_i with at least one endpoint on the boundary
walk of f whose depth is d-1 or d+1.
"""
import os
import sys
import math
from collections import deque, defaultdict
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from sage.all import Graph
# Reuse the cut-and-depth-label infrastructure.
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from cut_depth_label import (
parse_planar_code, HM_FILE, find_six_edge_cut,
apply_procedure, compute_nice_layout,
)
def faces_of_subgraph(H, pos):
"""Find faces of H using its planar embedding inherited from pos.
Uses Sage's planar embedding facility. Returns list of faces, each
a list of vertices in cyclic order on the face boundary."""
if not H.is_planar(set_embedding=True):
return []
return H.faces()
def cut_tire_at(G_i, edge_depth, d):
"""Build cut tires at depth d for each face of the depth-d subgraph.
Returns list of (face_vertices, tire_subgraph_edges_by_role) where:
tire_subgraph_edges_by_role is a dict with keys
'face' (boundary at depth d), 'inner' (adjacent at d-1),
'outer' (adjacent at d+1).
"""
# Build H_d
H_d_edges = [e for e, ed in edge_depth.items() if ed == d]
H_d = Graph([(u, v) for (u, v) in H_d_edges],
multiedges=False, loops=False)
if H_d.size() == 0:
return []
if not H_d.is_planar(set_embedding=True):
return []
faces_h_d = H_d.faces()
results = []
for face in faces_h_d:
# face is a list of (u, v) edge-pairs going around the boundary
# in Sage; convert to vertex sequence
vertices_on_face = []
for (u, v) in face:
vertices_on_face.append(u)
face_vertex_set = set(vertices_on_face)
# Boundary edges of the face (in H_d): they're the face edges
face_edges = [(min(u, v), max(u, v)) for (u, v) in face]
# Find adjacent edges at d-1 and d+1 from G'_i
inner_edges = [] # depth d-1
outer_edges = [] # depth d+1
for e_full, ed in edge_depth.items():
if ed not in (d - 1, d + 1):
continue
u, v = e_full
if u in face_vertex_set or v in face_vertex_set:
if ed == d - 1:
inner_edges.append(e_full)
else:
outer_edges.append(e_full)
results.append({
'face_vertices': vertices_on_face,
'face_edges': face_edges,
'inner_edges': inner_edges,
'outer_edges': outer_edges,
'face_length': len(face),
})
return results
def draw_cut_tire(ax, G_i, pos, edge_depth, tire, d, title):
"""Draw G_i faded with a single cut tire highlighted."""
face_set = set(tire['face_edges'])
inner_set = set(tire['inner_edges'])
outer_set = set(tire['outer_edges'])
face_vertex_set = set(tire['face_vertices'])
# Fade all G_i edges
for e in G_i.edges(labels=False):
u, v = e
e_norm = (min(u, v), max(u, v))
if e_norm in face_set or e_norm in inner_set or e_norm in outer_set:
continue
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='#dddddd', linewidth=0.9,
zorder=1)
# Highlight the tire
for e in face_set:
u, v = e
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='#1f77b4', linewidth=3.0,
zorder=3, label=None)
for e in inner_set:
u, v = e
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='#d62728', linewidth=2.4,
linestyle='--', zorder=2)
for e in outer_set:
u, v = e
x1, y1 = pos[u]; x2, y2 = pos[v]
ax.plot([x1, x2], [y1, y2], color='#2ca02c', linewidth=2.4,
linestyle='--', zorder=2)
# Draw vertices: face vertices highlighted, others faded
for v in G_i.vertices():
x, y = pos[v]
if v in face_vertex_set:
ax.plot(x, y, 'o', color='#1f77b4', markersize=10,
zorder=4, markeredgecolor='#0a3b5f',
markeredgewidth=1.0)
else:
ax.plot(x, y, 'o', color='#bbbbbb', markersize=5, zorder=2)
legend = [
plt.Line2D([], [], color='#1f77b4', linewidth=3,
label=f'face boundary (depth {d})'),
plt.Line2D([], [], color='#d62728', linewidth=2.4,
linestyle='--', label=f'inner spokes (depth {d - 1})'),
plt.Line2D([], [], color='#2ca02c', linewidth=2.4,
linestyle='--', label=f'outer spokes (depth {d + 1})'),
]
ax.legend(handles=legend, loc='upper left',
bbox_to_anchor=(1.02, 1.0), fontsize=9, frameon=False)
ax.set_aspect('equal'); ax.axis('off')
ax.set_title(title, fontsize=10)
def main():
out_fig = os.path.normpath(os.path.join(HERE, '..', 'notes',
'fig_cut_tire.png'))
gs = parse_planar_code(HM_FILE)
G = gs[0]
S, cut = find_six_edge_cut(G)
base_pos = compute_nice_layout(G)
S0 = frozenset(S)
S1 = frozenset(G.vertices()) - S0
H0, pos0, ed0, _, _, _ = apply_procedure(
G, S0, cut, base_pos, '0',
pendant_start_id=max(G.vertices()) + 1)
H1, pos1, ed1, _, _, _ = apply_procedure(
G, S1, cut, base_pos, '1',
pendant_start_id=max(G.vertices()) + 1 + 6)
# Try several depths in G'_1 (which has depths 0-7) and pick a
# decent example.
print(f"G'_1 depths range: 0 to {max(ed1.values())}")
chosen_d = None
chosen_tire = None
for d in range(1, max(ed1.values())):
tires = cut_tire_at(H1, ed1, d)
print(f' depth {d}: {len(tires)} faces in depth-{d} subgraph')
for tire in tires:
print(f' face length {tire["face_length"]}, '
f'inner spokes: {len(tire["inner_edges"])}, '
f'outer spokes: {len(tire["outer_edges"])}')
# Pick the largest "interesting" face: try to find one with
# > 3 face edges AND inner/outer spokes both > 0.
candidates = [t for t in tires
if t['face_length'] >= 4
and t['inner_edges'] and t['outer_edges']]
if candidates and chosen_tire is None:
chosen_d = d
# Pick the face with the most spokes total (most "informative")
candidates.sort(key=lambda t: -(len(t['inner_edges']) +
len(t['outer_edges'])))
chosen_tire = candidates[0]
if chosen_tire is None:
print('No suitable cut tire found.')
return
print(f"\nChosen cut tire at depth d = {chosen_d}")
print(f" face length: {chosen_tire['face_length']}")
print(f" inner spokes (depth {chosen_d - 1}): "
f"{len(chosen_tire['inner_edges'])}")
print(f" outer spokes (depth {chosen_d + 1}): "
f"{len(chosen_tire['outer_edges'])}")
# Collect "best" cut tires at multiple depths
selected = []
for d in range(1, max(ed1.values())):
tires = cut_tire_at(H1, ed1, d)
candidates = [t for t in tires
if t['face_length'] >= 4
and t['inner_edges'] and t['outer_edges']]
if candidates:
candidates.sort(key=lambda t: -(len(t['inner_edges']) +
len(t['outer_edges'])))
selected.append((d, candidates[0]))
print(f"\nCut tires selected for visualization at depths: "
f"{[d for d, _ in selected]}")
# Multi-panel figure
n = len(selected)
cols = 2
rows = (n + cols - 1) // cols
xs = [p[0] for p in base_pos.values()]
ys = [p[1] for p in base_pos.values()]
fig, axes = plt.subplots(rows, cols, figsize=(13, 5 * rows))
if rows == 1:
axes = [axes]
axes_flat = [ax for row in axes for ax in (row if hasattr(row, '__iter__') else [row])]
for idx, (d, tire) in enumerate(selected):
ax = axes_flat[idx]
draw_cut_tire(ax, H1, pos1, ed1, tire, d,
title=(f"$d = {d}$: face length "
f"{tire['face_length']}, "
f"{len(tire['inner_edges'])} inner + "
f"{len(tire['outer_edges'])} outer spokes"))
ax.set_xlim(min(xs) - 0.5, max(xs) + 0.5)
ax.set_ylim(min(ys) - 0.5, max(ys) + 0.5)
for idx in range(n, len(axes_flat)):
axes_flat[idx].axis('off')
fig.suptitle(r"Cut tires on $G'_1$ (Holton-McKay #0, V\S half) at "
r"several depths $d$" + "\n"
r"Each panel: blue face boundary at depth $d$ "
r"+ inner spokes (depth $d-1$, red dashed) "
r"+ outer spokes (depth $d+1$, green dashed)",
fontsize=11, y=1.00)
plt.tight_layout()
plt.savefig(out_fig, dpi=160, bbox_inches='tight')
plt.close()
print(f'Wrote {out_fig}')
if __name__ == '__main__':
main()
@@ -1,8 +1,12 @@
\relax
\@writefile{toc}{\contentsline {paragraph}{The chosen 6-edge cut.}{1}{}\protected@file@percent }
\@writefile{toc}{\contentsline {paragraph}{Resulting half-graphs.}{2}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Cut-and-depth-label procedure on Holton-McKay graph \#0 ($38$ vertices, $57$ edges, cubic planar non-Hamiltonian). The $6$-edge matching cut splits $G'$ into a $10$-vertex piece $G'_0$ (left) and a $28$-vertex piece $G'_1$ (right). Pendant edges (dashed, dark purple) are at depth $0$; the colour gradient encodes depth $0$ through max depth via BFS in the line-graph sense. Orange squares are the new pendant vertices; red circles are the boundary vertices in $V_i$; gray circles are interior vertices.\relax }}{2}{}\protected@file@percent }
\providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
\newlabel{fig:cut-depth-label}{{1}{2}}
\@writefile{toc}{\contentsline {paragraph}{Visualization.}{2}{}\protected@file@percent }
\gdef \@abspage@last{3}
\@writefile{toc}{\contentsline {paragraph}{Relation to the existing tire framework.}{2}{}\protected@file@percent }
\@writefile{toc}{\contentsline {paragraph}{Example on $G'_1$ (Holton-McKay \#0, $V \setminus S$ half).}{3}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Cut-and-depth-label procedure on Holton-McKay graph \#0 ($38$ vertices, $57$ edges, cubic planar non-Hamiltonian). The $6$-edge matching cut splits $G'$ into a $10$-vertex piece $G'_0$ (left) and a $28$-vertex piece $G'_1$ (right). Pendant edges (dashed, dark purple) are at depth $0$; the colour gradient encodes depth $0$ through max depth via BFS in the line-graph sense. Orange squares are the new pendant vertices; red circles are the boundary vertices in $V_i$; gray circles are interior vertices.\relax }}{4}{}\protected@file@percent }
\providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
\newlabel{fig:cut-depth-label}{{1}{4}}
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Cut tires on $G'_1$ at depths $d = 1, 2, 4, 5, 6$. In each panel, blue solid edges form the face boundary at depth $d$; red dashed edges are inner spokes (depth $d - 1$); green dashed edges are outer spokes (depth $d + 1$). Vertices on the face boundary are highlighted; the rest of $G'_1$ is faded.\relax }}{5}{}\protected@file@percent }
\newlabel{fig:cut-tire}{{2}{5}}
\gdef \@abspage@last{5}
@@ -1,4 +1,4 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 26 MAY 2026 15:00
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 26 MAY 2026 15:32
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
@@ -288,45 +288,89 @@ n[]level[]graph[]generators/experiments/nonham38m4.pc\OT1/cmr/m/n/10.95 ).
[1
{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]
<fig_cut_depth_label.png, id=17, 1150.44806pt x 565.06107pt>
<fig_cut_depth_label.png, id=17, 525.31256pt x 1377.19519pt>
File: fig_cut_depth_label.png Graphic file (type png)
<use fig_cut_depth_label.png>
Package pdftex.def Info: fig_cut_depth_label.png used on input line 108.
(pdftex.def) Requested size: 469.75502pt x 230.7281pt.
(pdftex.def) Requested size: 469.75502pt x 1231.6049pt.
Overfull \hbox (46.78696pt too wide) in paragraph at lines 123--130
LaTeX Warning: Float too large for page by 659.17491pt on input line 119.
LaTeX Warning: `h' float specifier changed to `ht'.
! LaTeX Error: Environment definition undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.129 \begin{definition}
[Cut tire]
Your command was ignored.
Type I <command> <return> to replace it with another command,
or <return> to continue without it.
! LaTeX Error: \begin{document} ended by \end{definition}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.149 \end{definition}
Your command was ignored.
Type I <command> <return> to replace it with another command,
or <return> to continue without it.
<fig_cut_tire.png, id=19, 864.98157pt x 1087.6635pt>
File: fig_cut_tire.png Graphic file (type png)
<use fig_cut_tire.png>
Package pdftex.def Info: fig_cut_tire.png used on input line 171.
(pdftex.def) Requested size: 469.75502pt x 590.68202pt.
LaTeX Warning: `h' float specifier changed to `ht'.
[2]
Overfull \hbox (46.78696pt too wide) in paragraph at lines 195--202
\OT1/cmr/m/n/10.95 The pro-ce-dure mir-rors the $4$CT cut-and-reglue scheme (\O
T1/cmtt/m/n/10.95 rainbow[]proof.tex\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 wo
rst[]case[]proof[]sketch.tex\OT1/cmr/m/n/10.95 ,
[]
[2 <./fig_cut_depth_label.png>] [3] (./cut_depth_label.aux) )
[3] [4 <./fig_cut_depth_label.png>] [5 <./fig_cut_tire.png>]
(./cut_depth_label.aux) )
Here is how much of TeX's memory you used:
4579 strings out of 478268
74295 string characters out of 5846347
370409 words of memory out of 5000000
22760 multiletter control sequences out of 15000+600000
4588 strings out of 478268
74465 string characters out of 5846347
375417 words of memory out of 5000000
22768 multiletter control sequences out of 15000+600000
479174 words of font info for 66 fonts, out of 8000000 for 9000
1141 hyphenation exceptions out of 8191
55i,8n,63p,656b,312s stack positions out of 10000i,1000n,20000p,200000b,200000s
{/usr/local/texliv
e/2022/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc}</usr/local/texlive
/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/local/texlive/
2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb></usr/local/texlive/2
022/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/local/texlive/20
22/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi8.pfb></usr/local/texlive/2022
/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/local/texlive/2022/t
exmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb></usr/local/texlive/2022/tex
mf-dist/fonts/type1/public/amsfonts/cm/cmr8.pfb></usr/local/texlive/2022/texmf-
dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb></usr/local/texlive/2022/texmf-d
ist/fonts/type1/public/amsfonts/cm/cmsy8.pfb></usr/local/texlive/2022/texmf-dis
t/fonts/type1/public/amsfonts/cm/cmti10.pfb></usr/local/texlive/2022/texmf-dist
/fonts/type1/public/amsfonts/cm/cmtt10.pfb></usr/local/texlive/2022/texmf-dist/
fonts/type1/public/cm-super/sfrm1095.pfb>
Output written on cut_depth_label.pdf (3 pages, 357384 bytes).
{/usr/local/texlive/2022/texmf-dist/fonts/enc/dvips/cm
-super/cm-super-ts1.enc}</usr/local/texlive/2022/texmf-dist/fonts/type1/public/
amsfonts/cm/cmbx10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/a
msfonts/cm/cmbx12.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/am
sfonts/cm/cmmi10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/ams
fonts/cm/cmmi8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfo
nts/cm/cmr10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfont
s/cm/cmr17.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/
cm/cmr8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/
cmsy10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/c
msy6.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cms
y8.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmti1
0.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt10
.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/amsfonts/symbols/ms
bm10.pfb></usr/local/texlive/2022/texmf-dist/fonts/type1/public/cm-super/sfrm10
95.pfb>
Output written on cut_depth_label.pdf (5 pages, 500070 bytes).
PDF statistics:
78 PDF objects out of 1000 (max. 8388607)
46 compressed objects within 1 object stream
96 PDF objects out of 1000 (max. 8388607)
56 compressed objects within 1 object stream
0 named destinations out of 1000 (max. 500000)
6 words of extra memory for PDF output out of 10000 (max. 10000000)
11 words of extra memory for PDF output out of 10000 (max. 10000000)
@@ -118,6 +118,78 @@ vertices.}
\label{fig:cut-depth-label}
\end{figure}
\section*{Cut tires}
The depth labelling on $G'_i$ organises its edges into layers indexed
by distance to the cut. Each layer gives rise to a family of
``cut tires'' that play the same structural role as the tires of
\texttt{paper.tex} but are derived from the cut rather than from a
level source in the primal $G$.
\begin{definition}[Cut tire]
Let $G'_i$ be a cut half (Step~3 above) with edge depth labelling
$\mathrm{depth} : E(G'_i) \to \mathbb{Z}_{\ge 0}$. Fix $d > 0$ and
let $H_d \subseteq G'_i$ be the subgraph induced on the edges of
depth $d$ (vertex set $=$ endpoints of depth-$d$ edges, edges $=$
depth-$d$ edges). Equip $H_d$ with the planar embedding inherited
from $G'_i$.
For each face $f$ of $H_d$, the \emph{cut tire at $(d, f)$} is the
subgraph of $G'_i$ consisting of:
\begin{itemize}
\item every edge on the boundary walk of $f$ (all of depth $d$ in
$H_d$), and
\item every edge of $G'_i$ with at least one endpoint on the
boundary walk of $f$ whose depth is $d - 1$ or $d + 1$.
\end{itemize}
The first set forms the \emph{face boundary at depth $d$}; the second
splits into \emph{inner spokes} (depth $d - 1$, pointing toward the
cut) and \emph{outer spokes} (depth $d + 1$, pointing away from the
cut).
\end{definition}
\paragraph{Relation to the existing tire framework.} Under the
correspondence between primal level structure (paper.tex) and dual
depth labelling, a cut tire on $G'_i$ at $(d, f)$ corresponds to:
\begin{itemize}
\item face boundary at depth $d$ $\longleftrightarrow$ the tire
annular subgraph $T'_{\mathrm{ann}}$ at depth $d$ from the
cut (cf.\ Def.~1.15 of paper.tex);
\item the cut tire itself $\longleftrightarrow$ the tire annular
face connector $T'_{f'}$ (cf.\ Def.~1.16);
\item inner / outer spokes $\longleftrightarrow$ the inner and
outer spokes of $T'_{f'}$ (cf.\ Def.~1.17).
\end{itemize}
So the cut tire is the dual-side analogue of the
``tire annular face connector,'' parametrised by depth from the cut
rather than depth from a primal level source.
\paragraph{Example on $G'_1$ (Holton-McKay \#0, $V \setminus S$ half).}
\begin{figure}[h]
\centering
\includegraphics[width=\textwidth]{fig_cut_tire.png}
\caption{Cut tires on $G'_1$ at depths $d = 1, 2, 4, 5, 6$. In each
panel, blue solid edges form the face boundary at depth $d$; red
dashed edges are inner spokes (depth $d - 1$); green dashed edges
are outer spokes (depth $d + 1$). Vertices on the face boundary are
highlighted; the rest of $G'_1$ is faded.}
\label{fig:cut-tire}
\end{figure}
In this example:
\begin{itemize}
\item $d = 1$: face length $12$, $5$ inner spokes (to depth-$0$
pendants) $+$ $4$ outer spokes. This is the outermost cut
tire, immediately adjacent to the cut.
\item $d = 2$: face length $7$ (one of two symmetric faces in
$H_2$), $4 + 3$ spokes.
\item $d = 4$: face length $8$, $2 + 5$ spokes.
\item $d = 5$: face length $14$, $4 + 6$ spokes.
\item $d = 6$: face length $12$, $7 + 1$ spokes. This is the
innermost cut tire (one face left, almost no outer spokes).
\end{itemize}
\section*{Connection to chain pigeonhole / 4CT reducibility}
The procedure mirrors the $4$CT cut-and-reglue scheme
Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB