refactor pentagons.3

This commit is contained in:
queue-miscreant 2025-03-23 22:05:24 -05:00
parent 6caf4640ac
commit bbf141785e
4 changed files with 286 additions and 326 deletions

View File

@ -33,8 +33,6 @@ import matplotlib.pyplot as plt
from tabulate import tabulate from tabulate import tabulate
from goldberg.common import ( from goldberg.common import (
GoldbergData,
GoldbergOperator,
hexagons_to_polyhedron, hexagons_to_polyhedron,
group_dict, group_dict,
link_polyhedronisme, link_polyhedronisme,

1
posts/pentagons/3/goldberg Symbolic link
View File

@ -0,0 +1 @@
../1/goldberg

View File

@ -12,27 +12,11 @@ categories:
- geometry - geometry
- combinatorics - combinatorics
- symmetry - symmetry
# Get rid of the figure label
crossref:
fig-title: ""
fig-labels: " "
tbl-title: ""
tbl-labels: " "
title-delim: ""
custom:
- key: fig
kind: float
reference-prefix: Figure
space-before-numbering: false
- key: tbl
kind: float
reference-prefix: Table
space-before-numbering: false
--- ---
<style> <style>
.image-wide { .image-wide {
width: 384px; width: 192px;
object-fit: contain; object-fit: contain;
} }
@ -43,8 +27,7 @@ crossref:
</style> </style>
```{python} ```{python}
#| echo: false from dataclasses import dataclass, asdict
from dataclasses import dataclass
import itertools import itertools
from typing import Callable, TypeAlias from typing import Callable, TypeAlias
@ -52,28 +35,91 @@ from IPython.display import Markdown
import sympy import sympy
from tabulate import tabulate from tabulate import tabulate
@dataclass from goldberg.common import (
class PolyData: hexagons_to_polyhedron,
hexagon_count: int group_dict,
vertex_count: int link_polyhedronisme,
edge_count: int )
from goldberg.operators import (
t_param,
GoldbergOperator,
goldberg_operators,
goldberg_operators_to_parameters,
loeschian_numbers,
loeschian_norm,
)
@classmethod n_param, aux_t_param, temp_param = sympy.symbols("n T' x")
def from_hexagons(cls, hexagon_count: int): from_base_case = lambda x: (t_param * (x + 10) - 10)
return cls(
hexagon_count=hexagon_count, @dataclass
vertex_count=2*hexagon_count + 20, class MiniConwayTable:
edge_count=3*hexagon_count + 30, conway: str
hexagon_count: str
vertex_count: str
edge_count: str
as_maybe_tex = lambda x: x if isinstance(x, int) or not x.has_free(t_param) else f"${sympy.latex(x)}$"
as_maybe_recipe_link = lambda x, recipe: x if recipe is None else link_polyhedronisme(x, recipe)
def display_mini_conway_table(
base_case_hexagons: int,
base_case_name: str,
recipes: dict[str, str] = {},
) -> Markdown:
headers = MiniConwayTable(
"Conway",
"$F_6$",
"V",
"E",
) )
rows = [
MiniConwayTable(
conway=recipe,
hexagon_count=str(as_maybe_tex(polyhedron.face_count - 12)),
vertex_count=str(as_maybe_tex(polyhedron.vertex_count)),
edge_count=str(as_maybe_tex(polyhedron.edge_count)),
)
# base row list
for operator in ["", "dk", "c", "w", "tk", "g_T"]
# try lookup (a, b) tuple in parameter dict
for maybe_parameter in (goldberg_operators_to_parameters.get(operator),)
# combinatorially construct polyhedron from the base case and (maybe) the parameter
for polyhedron in (
(
hexagons_to_polyhedron(base_case_hexagons)
if operator == ""
else hexagons_to_polyhedron(
from_base_case(base_case_hexagons).expand().subs(
# if the lookup failed, leave the T parameter free
t_param,
loeschian_norm(*maybe_parameter)
if maybe_parameter is not None
else t_param
)
)
),
)
# pull the recipe from the `recipes` dict
for recipe in (
as_maybe_recipe_link(
f"${operator + base_case_name.split(' ')[-1]}$"
if operator == ""
else f"${base_case_name}$",
recipes.get(operator),
),
)
]
@dataclass return Markdown(tabulate(
class GoldbergData: {
parameter: tuple[int, int] field: [name] + [getattr(item, field) for item in rows]
conway: str for field, name in asdict(headers).items()
},
parameter_link: str | None = None headers="firstrow",
conway_recipe: str | None = None numalign="left",
))
``` ```
@ -91,59 +137,79 @@ Yet more unconventional solutions are presented below.
Combinatorics of Goldberg-Coxeter Operators Combinatorics of Goldberg-Coxeter Operators
------------------------------------------- -------------------------------------------
In the last post, it was discovered that certain solutions cannot be created easily from seed polyhedra In the first post, we established that a solution figure *S* has feature counts
in a polyhedron viewer. which are parametrized entirely by $F_6$:
This prompts the question of how to calculate the vertex, edge, and face counts
without acquiring them from the output of such a program.
Each of the simple GC operators (*c*, *dk*, and *w*) has a combinatoric matrix form
which can be applied to a vector of the vertex, edge, and face counts of a figure *S*.
$$ $$
\begin{gather*} S = \begin{pmatrix} v \\ e \\ f \end{pmatrix}
S = \begin{pmatrix} v \\ e \\ f \end{pmatrix}
= \begin{pmatrix} = \begin{pmatrix}
2F_6 + 20 \\ 2F_6 + 20 \\
3F_6 + 30 \\ 3F_6 + 30 \\
F_6 + 12 F_6 + 12
\end{pmatrix} \end{pmatrix}
= \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6 = \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6
+ \begin{pmatrix} 20 \\ 30 \\ 12 \end{pmatrix} \\ + \begin{pmatrix} 20 \\ 30 \\ 12 \end{pmatrix}
\underset{ $$
In the last post, it was discovered that certain solutions cannot be created easily from seed polyhedra
in a polyhedron viewer.
This prompts the question of how to calculate the vertex, edge, and face counts
without acquiring them from the output of such a program.
Fortunatelly, each of the simple GC operators (*dk*, *c*, and *w*) has a combinatoric matrix form[^1].
$$
\underset{
\text{Class I} \text{Class I}
}{ }{
c = \begin{pmatrix} c = \begin{pmatrix}
1 & 2 & 0 \\ 1 & 2 & 0 \\
0 & 4 & 0 \\ 0 & 4 & 0 \\
0 & 1 & 1 0 & 1 & 1
\end{pmatrix} \end{pmatrix}
} \quad } \quad
\underset{ \underset{
\text{Class II} \text{Class II}
}{ }{
dk = \begin{pmatrix} dk = \begin{pmatrix}
0 & 2 & 0 \\ 0 & 2 & 0 \\
0 & 3 & 0 \\ 0 & 3 & 0 \\
1 & 0 & 1 1 & 0 & 1
\end{pmatrix} \end{pmatrix}
} \quad } \quad
\underset{ \underset{
\text{Class III} \text{Class III}
}{ }{
w = \begin{pmatrix} w = \begin{pmatrix}
1 & 4 & 0 \\ 1 & 4 & 0 \\
0 & 7 & 0 \\ 0 & 7 & 0 \\
0 & 2 & 1 0 & 2 & 1
\end{pmatrix} \end{pmatrix}
} }
\end{gather*}
$$ $$
[^1]:
These matrices can be derived by closely observing the vertex, edge, and face counts of a figure before
and after applying the operator.
Gather the feature counts of the tetrahedron, dodecahedron, and icosahedron into a matrix.
$$
\begin{gather*}
f \begin{pmatrix} | & | & | \\ T & D & I \\ | & | & | \end{pmatrix}
= f \begin{pmatrix} 4 & 20 & 12 \\ 6 & 30 & 30 \\ 4 & 12 & 20 \end{pmatrix}
= \begin{pmatrix} | & | & | \\ fT & fD & fI \\ | & | & | \end{pmatrix} \\
f = \begin{pmatrix} | & | & | \\ fT & fD & fI \\ | & | & | \end{pmatrix}
\begin{pmatrix} 4 & 20 & 12 \\ 6 & 30 & 30 \\ 4 & 12 & 20 \end{pmatrix}^{-1}
\end{gather*}
$$
This matrix is invertible, and the feature counts for *fT*, *fD*, and *fI* can be acquired from a viewer
implementing the operator *f*.
These operators are labelled with the classes of Goldberg polyhedra they construct These operators are labelled with the classes of Goldberg polyhedra they construct
when applied to the dodecahedron. when applied to the dodecahedron.
- *cD* = GC(2, 0)
- *dkD* = *tI* = GC(1, 1) - *dkD* = *tI* = GC(1, 1)
- *cD* = GC(2, 0)
- *wD* = GC(2, 1) - *wD* = GC(2, 1)
It's worth noting again that *dk* alternates between producing Class I and Class II solutions. It's worth noting again that *dk* alternates between producing Class I and Class II solutions.
@ -156,83 +222,41 @@ Unlike it, it preserves solution class.
Powers of a matrix are more readily expressed when the matrix is diagonalized. Powers of a matrix are more readily expressed when the matrix is diagonalized.
Diagonalizing each of these operators shows that they have something in common. Diagonalizing each of these operators shows that they have something in common.
$$ ```{python}
\begin{align*} # diagonalizing dk gives an eigenspace which shows the 3V = 2E condition
c &= \begin{pmatrix} # and Euler characteristic more clearly
1 & 2 & 0 \\ eigenspace, _ = goldberg_operators["dk"].diagonalize()
0 & 4 & 0 \\
0 & 1 & 1 def show_diagonalized(operator: GoldbergOperator):
\end{pmatrix} assert operator != "g_T"
= \textcolor{red}{ matrix = goldberg_operators[operator]
\begin{pmatrix} diag = eigenspace.inv() @ matrix @ eigenspace
-1 & 0 & 2 \\
0 & 0 & 3 \\ return f"""{
1 & 1 & 1 sympy.latex(matrix)
\end{pmatrix} } = \\textcolor{{red}}{{{
} sympy.latex(eigenspace)
\begin{pmatrix} }}}{
1 & 0 & 0 \\ sympy.latex(diag)
0 & 1 & 0 \\ }\\textcolor{{blue}}{{{
0 & 0 & 4 sympy.latex(eigenspace.inv(), fold_short_frac=True)
\end{pmatrix} }}}"""
\textcolor{blue}{
\begin{pmatrix} Markdown(f"""
1 & -2/3 & 0 \\ $$
1 & -1 & 1 \\ \\begin{{align*}}
0 & 1/3 & 0 dk &= {show_diagonalized("dk")} \\\\
\end{pmatrix} c &= {show_diagonalized("c")} \\\\
} \\ w &= {show_diagonalized("w")}
dk &= \begin{pmatrix} \\end{{align*}}
0 & 2 & 0 \\ $$
0 & 3 & 0 \\ """.replace(
1 & 0 & 1 "\\left[\\begin{matrix}", "\\begin{pmatrix}"
\end{pmatrix} ).replace(
= \textcolor{red}{ "\\end{matrix}\\right]", "\\end{pmatrix}"
\begin{pmatrix} )
-1 & 0 & 2 \\ )
0 & 0 & 3 \\ ```
1 & 1 & 1
\end{pmatrix}
}
\begin{pmatrix}
0 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 3
\end{pmatrix}
\textcolor{blue}{
\begin{pmatrix}
1 & -2/3 & 0 \\
1 & -1 & 1 \\
0 & 1/3 & 0
\end{pmatrix}
}
\\
w &= \begin{pmatrix}
1 & 4 & 0 \\
0 & 7 & 0 \\
0 & 2 & 1
\end{pmatrix}
= \textcolor{red}{
\begin{pmatrix}
-1 & 0 & 2 \\
0 & 0 & 3 \\
1 & 1 & 1
\end{pmatrix}
}
\begin{pmatrix}
1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 7
\end{pmatrix}
\textcolor{blue}{
\begin{pmatrix}
1 & -2/3 & 0 \\
1 & -1 & 1 \\
0 & 1/3 & 0
\end{pmatrix}
}
\end{align*}
$$
All of these operators share the same eigenvectors, which can be seen All of these operators share the same eigenvectors, which can be seen
in the columns of the left outer matrix and rows of the right outer one. in the columns of the left outer matrix and rows of the right outer one.
@ -243,7 +267,7 @@ Some of these eigenvectors have special interpretations:
- The left eigenvector (1, -1, 1) (right matrix, middle row) always has eigenvalue 1. - The left eigenvector (1, -1, 1) (right matrix, middle row) always has eigenvalue 1.
- This means that the operation does not change the Euler characteristic. - This means that the operation does not change the Euler characteristic.
- The left eigenvector (3, -2, 0) (right matrix, top row), when applied to general polyhedra - The left eigenvector (3, -2, 0) (right matrix, top row), when applied to general polyhedra,
corresponds to the edges and vertices added by the operation: corresponds to the edges and vertices added by the operation:
- In *dk*, this vector has eigenvalue 0, forcing $3V = 2E$, i.e., all vertices to have degree 3. - In *dk*, this vector has eigenvalue 0, forcing $3V = 2E$, i.e., all vertices to have degree 3.
- In *c* and *w*, this vector has eigenvalue 1. These operators only add degree-3 vertices. - In *c* and *w*, this vector has eigenvalue 1. These operators only add degree-3 vertices.
@ -265,10 +289,10 @@ $$
Call this number $T = \|a + bu\| = a^2 + ab + b^2$. Call this number $T = \|a + bu\| = a^2 + ab + b^2$.
We know that integers of this form are never congruent to 2 (mod 3). We know that integers of this form are never congruent to 2 (mod 3).
Conveniently, this matches with the upper-left eigenvalue. Conveniently, this matches with the upper-left eigenvalue.
Assuming for the sake of argument that this is true, it implies something interesting: Assuming for the sake of argument that this is true, it implies something interesting:
**the GC operators produced from *T* are (combinatorially) closed under composition**. **the GC operators produced from *T* are (combinatorially) closed under composition**.
This captures all powers of a given *T*, as well as products between it and other possible *T*s. This captures all powers of a given *T*, as well as products between it and other possible *T*s.
However, this combinatorial view misses some of the picture, since some feature counts However, this combinatorial view misses some of the picture, since some feature counts
can be shared between two different classes at once. can be shared between two different classes at once.
This comes down to the existence of chiral pairs. This comes down to the existence of chiral pairs.
@ -282,53 +306,21 @@ This doesn't affect hexagon counts, so it means we can characterize the possible
$$ $$
\begin{align*} \begin{align*}
g_T S &= \begin{pmatrix} g_T S &= g_T \left(
-1 & 0 & 2 \\ \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6
0 & 0 & 3 \\ + \begin{pmatrix} 20 \\ 30 \\ 10 \end{pmatrix}
1 & 1 & 1 + \begin{pmatrix} 0 \\ 0 \\ 2 \end{pmatrix}
\end{pmatrix} \right) \\
\begin{pmatrix} &= T \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix} F_6
x & 0 & 0 \\ + T \begin{pmatrix} 20 \\ 30 \\ 10 \end{pmatrix}
0 & 1 & 0 \\ + \begin{pmatrix} 0 \\ 0 \\ 2 \end{pmatrix} \\
0 & 0 & T &= \begin{pmatrix} T(2F_6 + 20) \\ T(3F_6 + 30) \\ T(F_6 + 10) + 2 \end{pmatrix} \\[8pt]
\end{pmatrix}
\begin{pmatrix}
1 & -{2 \over 3} & 0 \\
1 & -1 & 1 \\
0 & {1 \over 3} & 0
\end{pmatrix}
\begin{pmatrix} v \\ e \\ f \end{pmatrix} \\[8pt]
&=
\begin{pmatrix}
-1 & 0 & 2 \\
0 & 0 & 3 \\
1 & 1 & 1
\end{pmatrix}
\begin{pmatrix}
x & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & T
\end{pmatrix}
\begin{pmatrix}
v - {2 \over 3} e = 0 \\
v - e + f = 2 \\
{1 \over 3} e = F_6 + 10
\end{pmatrix} \\[8pt]
&=
\begin{pmatrix}
-1 & 0 & 2 \\
0 & 0 & 3 \\
1 & 1 & 1
\end{pmatrix}
\begin{pmatrix} 0 \\ 2 \\ T (F_6 + 10) \end{pmatrix} \\
&=
\begin{pmatrix} T(2F_6 + 20) \\ T(3F_6 + 30) \\ T(F_6 + 10) + 2 \end{pmatrix} \\[8pt]
F'_6 &= T(F_6 + 10) - 10 F'_6 &= T(F_6 + 10) - 10
\end{align*} \end{align*}
$$ $$
This demonstrates two things: the initial $F_6$ count from the choice of seed polygon *S* matters, This demonstrates two things: the initial $F_6$ count from the choice of seed polygon *S* matters,
and the possible values of *T* can be used to grow this sequence and we can use valid values of *T* to produce a sequence of solutions.
Searching for Other Seeds Searching for Other Seeds
@ -399,72 +391,13 @@ It inherits the dihedral symmetry of degree 3 from the vertices of the dodecahed
](./truncated gyroelongated bipyramid pole.png) ](./truncated gyroelongated bipyramid pole.png)
::: :::
::: {.column}
```{python} ```{python}
#| echo: false #| classes: plain
t_param = sympy.symbols("T")
norm = lambda a, b: a**2 + a*b + b**2
@dataclass
class GCOperator:
name: str
parameter: int | sympy.Symbol
gc_operators = [
GCOperator("dk", norm(1, 1)),
GCOperator("c", norm(2, 0)),
GCOperator("w", norm(2, 1)),
GCOperator("tk", norm(3, 0)),
GCOperator("g_T", t_param),
]
def polyhedronisme(recipe: str) -> str:
return f"https://levskaya.github.io/polyhedronisme/?recipe={recipe}"
as_maybe_tex = lambda x: x if isinstance(x, int) or not x.has_free(t_param) else f"${sympy.latex(x)}$"
as_maybe_recipe_link = lambda x, recipe: f"[{x}]({polyhedronisme(recipe)})" if recipe is not None else x
def mini_conway_table(
base_case_hexagons: int,
base_case_name: str,
recipes: dict[str, str] = {},
) -> list[tuple[str, PolyData]]:
return [
(
as_maybe_recipe_link(f"${base_case_name}$", recipes.get("")),
PolyData.from_hexagons(base_case_hexagons),
)
] + [
(
as_maybe_recipe_link(
f"${operator.name + base_case_name.split(' ')[-1]}$",
recipes.get(operator.name),
),
PolyData.from_hexagons((
t_param * (base_case_hexagons + 10) - 10
).expand().subs(t_param, operator.parameter)),
)
for operator in gc_operators
]
def display_mini_conway_table(
base_case_hexagons: int,
base_case_name: str,
recipes: dict[str, str] = {},
) -> Markdown:
return Markdown(tabulate(
[[
conway,
as_maybe_tex(polyhedron.hexagon_count),
as_maybe_tex(polyhedron.vertex_count),
as_maybe_tex(polyhedron.edge_count),
] for conway, polyhedron in mini_conway_table(base_case_hexagons, base_case_name, recipes)],
headers=["Conway", "$F_6$", "V", "E"],
numalign="left",
))
display_mini_conway_table(6, "F") display_mini_conway_table(6, "F")
``` ```
:::
:::: ::::
@ -497,7 +430,7 @@ The pentagons gather in groups of 4 and are separated by three bands of hexagons
The symmetry inherited by this figure is also dihedral of degree 3, but centered about a hexagon, The symmetry inherited by this figure is also dihedral of degree 3, but centered about a hexagon,
rather than (a complex of) pentagons. rather than (a complex of) pentagons.
:::: {layout-ncol="2" layout-valign="center"} ::: {layout-ncol="2" layout-valign="center"}
[ [
![ ![
One-third of the figure, showing a group of four pentagons.<br> One-third of the figure, showing a group of four pentagons.<br>
@ -506,11 +439,11 @@ The symmetry inherited by this figure is also dihedral of degree 3, but centered
](./frustum_third.png){target="_blank_"} ](./frustum_third.png){target="_blank_"}
```{python} ```{python}
#| echo: false #| classes: plain
display_mini_conway_table(8, "F") display_mini_conway_table(8, "F")
``` ```
:::: :::
#### Others #### Others
@ -567,7 +500,7 @@ This is a symmetry beyond that of the icosahedron, but exists due to the symmetr
](./polyhedronisme-K300t6dA6.png) ](./polyhedronisme-K300t6dA6.png)
```{python} ```{python}
#| echo: false #| classes: plain
display_mini_conway_table( display_mini_conway_table(
2, 2,
@ -577,8 +510,8 @@ display_mini_conway_table(
"dk": "dkK300t6dA6", "dk": "dkK300t6dA6",
"c": "K300cK30t6dA6", "c": "K300cK30t6dA6",
"w": "K300wK30t6dA6", "w": "K300wK30t6dA6",
"tk": "K300tkK30t6dA6" "tk": "K300tkK30t6dA6",
} },
) )
``` ```
:::: ::::
@ -608,11 +541,13 @@ The resultant figure has dihedral symmetry of degree 5.
](./petrial expanded dodecahedron.png) ](./petrial expanded dodecahedron.png)
::: :::
::: {.column}
```{python} ```{python}
#| echo: false #| classes: plain
display_mini_conway_table(5, "D_\\pi") display_mini_conway_table(5, "D_\\pi")
``` ```
:::
:::: ::::
Interestingly, this is also the first solution polyhedron with an odd number of faces. Interestingly, this is also the first solution polyhedron with an odd number of faces.
@ -632,12 +567,14 @@ Solution polyhedra can be found by examining the pentagonal ($t_5 g Y_5$) and he
The former has dihedral symmetry of degree 5 and the latter has that of degree 6. The former has dihedral symmetry of degree 5 and the latter has that of degree 6.
:::: {layout-ncol="2" layout-valign="center"} :::: {layout-ncol="2" layout-valign="center"}
::: {.column .slim-column}
![ ![
Base case 1: truncated pentagonal gyro-pyramid Base case 1: truncated pentagonal gyro-pyramid
](./polyhedronisme-K300t5K30gY5.png){.column .slim-column} ](./polyhedronisme-K300t5K30gY5.png){.column .slim-column}
:::
```{python} ```{python}
#| echo: false #| classes: plain
display_mini_conway_table( display_mini_conway_table(
10, 10,
@ -652,12 +589,14 @@ display_mini_conway_table(
) )
``` ```
::: {.column .slim-column}
![ ![
Base case 2: truncated hexagonal gyro-pyramid Base case 2: truncated hexagonal gyro-pyramid
](./polyhedronisme-K300t6K30gY6.png){.column .slim-column} ](./polyhedronisme-K300t6K30gY6.png)
:::
```{python} ```{python}
#| echo: false #| classes: plain
display_mini_conway_table( display_mini_conway_table(
14, 14,
@ -718,9 +657,13 @@ In fact, the graph of the whirl operation on the surface of a cube
:::: {#fig-tatami-polyhedron} :::: {#fig-tatami-polyhedron}
::: {layout="[[-1,2,-1,2,-1]]"} ::: {layout="[[-1,2,-1,2,-1]]"}
<a title="Tomruen, CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0>, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Conway_wC.png"><img width="384" alt="Conway wC" src="https://upload.wikimedia.org/wikipedia/commons/f/f4/Conway_wC.png"></a> <a title="Tomruen, CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0>, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Conway_wC.png">
<img width="384" alt="Conway wC" src="https://upload.wikimedia.org/wikipedia/commons/f/f4/Conway_wC.png">
</a>
<a title="See page for author, CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0>, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Tearoom_layout.svg"><img style="background-color: white !important; padding: 5px" width="384" alt="Tearoom layout" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Tearoom_layout.svg/256px-Tearoom_layout.svg.png"></a> <a title="See page for author, CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0>, via Wikimedia Commons" href="https://commons.wikimedia.org/wiki/File:Tearoom_layout.svg">
<img style="background-color: white !important; padding: 5px" width="384" alt="Tearoom layout" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Tearoom_layout.svg/256px-Tearoom_layout.svg.png">
</a>
::: :::
Images were retrieved from Wikimedia and belong to their respective owners. Images were retrieved from Wikimedia and belong to their respective owners.
@ -739,14 +682,14 @@ Next to it is an equivalent graph with a regular hexagon as an outer face.
As a 3D figure, it has only three hexagons and degree-3 dihedral symmetry, another odd number. As a 3D figure, it has only three hexagons and degree-3 dihedral symmetry, another odd number.
:::: {layout-ncol="2" layout-valign="center"} :::: {layout-ncol="2" layout-valign="center"}
::: {.column .slim-column} ::: {.column .slim-column .text-center}
![](./tatami_graph.png){.image-wide} ![](./tatami_graph.png){.image-wide}
![](./regularized_tatami_graph.png){.image-wide} ![](./regularized_tatami_graph.png){.image-wide}
::: :::
```{python} ```{python}
#| echo: false #| classes: plain
display_mini_conway_table(3, "M") display_mini_conway_table(3, "M")
``` ```
@ -791,10 +734,11 @@ Final Tabulation
The solutions examined have been collected in the table below. The solutions examined have been collected in the table below.
```{python} ```{python}
#| echo: false #| classes: plain
#| tbl-cap: "T, T' are members of the sequence 1, 3, 4, 7, 9, 12, 13, 16, 19, 21... ([OEIS A003136](http://oeis.org/A003136))\
#| <br>\\\\*: This is the result of a GC operator applied to $2T - 14$, which requires *T* > 7"
TFilter: TypeAlias = Callable[[int], bool] | None TFilter: TypeAlias = Callable[[int], bool] | None
n_param, t_param, aux_t_param, temp_param = sympy.symbols("n T T' x")
@dataclass @dataclass
class TotalHexagonRow: class TotalHexagonRow:
@ -803,8 +747,6 @@ class TotalHexagonRow:
f6_expression: sympy.Expr f6_expression: sympy.Expr
t_filter: TFilter = None t_filter: TFilter = None
from_base_case = lambda x: (t_param * (x + 10) - 10)
antitruncation = TotalHexagonRow( antitruncation = TotalHexagonRow(
symmetry_group="Tetrahedral", symmetry_group="Tetrahedral",
class_name="Tetrahedral Goldberg Antitruncations", class_name="Tetrahedral Goldberg Antitruncations",
@ -880,18 +822,10 @@ full_tabulation_rows = [
), ),
] ]
def loeschian():
"""
Loeschian numbers -- those of the form a^2 + ab + b^2
See https://oeis.org/A003136
"""
for a in itertools.count(1):
for b in range(a + 1):
yield a*a + a*b + b*b
def get_example_counts(expr: sympy.Expr, amount: int, t_filter: TFilter = None): def get_example_counts(expr: sympy.Expr, amount: int, t_filter: TFilter = None):
t_params = list(itertools.islice(loeschian(), 2*amount)) """Build values from the expression in terms of the number of hexagons"""
t_params = list(itertools.islice(loeschian_numbers(), 2*amount))
return [ return [
count count
@ -931,18 +865,20 @@ Markdown(tabulate(
)) ))
``` ```
T, T' are members of the sequence 1, 3, 4, 7, 9, 12, 13, 16, 19, 21... ([OEIS A003136](http://oeis.org/A003136)) Here are a few hexagon counts from the table, sorted in ascending order:
\*: This is the result of a GC operator applied to $2T - 14$, which requires *T* > 7
Sorting the entries in this table, we get the following possible hexagon counts:
```{python} ```{python}
#| echo: false Markdown(
", ".join([
Markdown(", ".join(list(map(str, sorted(itertools.chain(*[ str(i)
get_example_counts(row.f6_expression, 10, row.t_filter) for row in full_tabulation_rows for i in group_dict(
]))))[:15])) itertools.chain(*[
get_example_counts(row.f6_expression, 10, row.t_filter)
for row in full_tabulation_rows
])
).keys()
][:20]) + "..."
)
``` ```
However, keep in mind that this list is *not* exhaustive. However, keep in mind that this list is *not* exhaustive.

View File

@ -0,0 +1,25 @@
# freeze computational output
freeze: auto
# Enable banner style title blocks
title-block-banner: true
execute:
echo: false
# Get rid of the figure label
crossref:
fig-title: ""
fig-labels: "&#32;"
tbl-title: ""
tbl-labels: "&#32;"
title-delim: ""
custom:
- key: fig
kind: float
reference-prefix: Figure
space-before-numbering: false
- key: tbl
kind: float
reference-prefix: Table
space-before-numbering: false