refactor pentagons.3
This commit is contained in:
parent
6caf4640ac
commit
bbf141785e
@ -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
1
posts/pentagons/3/goldberg
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../1/goldberg
|
||||||
@ -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 (
|
||||||
@classmethod
|
t_param,
|
||||||
def from_hexagons(cls, hexagon_count: int):
|
GoldbergOperator,
|
||||||
return cls(
|
goldberg_operators,
|
||||||
hexagon_count=hexagon_count,
|
goldberg_operators_to_parameters,
|
||||||
vertex_count=2*hexagon_count + 20,
|
loeschian_numbers,
|
||||||
edge_count=3*hexagon_count + 30,
|
loeschian_norm,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
n_param, aux_t_param, temp_param = sympy.symbols("n T' x")
|
||||||
|
from_base_case = lambda x: (t_param * (x + 10) - 10)
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class GoldbergData:
|
class MiniConwayTable:
|
||||||
parameter: tuple[int, int]
|
|
||||||
conway: str
|
conway: str
|
||||||
|
hexagon_count: str
|
||||||
|
vertex_count: str
|
||||||
|
edge_count: str
|
||||||
|
|
||||||
parameter_link: str | None = None
|
as_maybe_tex = lambda x: x if isinstance(x, int) or not x.has_free(t_param) else f"${sympy.latex(x)}$"
|
||||||
conway_recipe: str | None = None
|
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),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
return Markdown(tabulate(
|
||||||
|
{
|
||||||
|
field: [name] + [getattr(item, field) for item in rows]
|
||||||
|
for field, name in asdict(headers).items()
|
||||||
|
},
|
||||||
|
headers="firstrow",
|
||||||
|
numalign="left",
|
||||||
|
))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -91,16 +137,10 @@ 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 \\
|
||||||
@ -108,7 +148,16 @@ $$
|
|||||||
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}
|
||||||
|
$$
|
||||||
|
|
||||||
|
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{
|
\underset{
|
||||||
\text{Class I}
|
\text{Class I}
|
||||||
}{
|
}{
|
||||||
@ -136,14 +185,31 @@ $$
|
|||||||
0 & 2 & 1
|
0 & 2 & 1
|
||||||
\end{pmatrix}
|
\end{pmatrix}
|
||||||
}
|
}
|
||||||
|
$$
|
||||||
|
|
||||||
|
[^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*}
|
\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}
|
||||||
|
# diagonalizing dk gives an eigenspace which shows the 3V = 2E condition
|
||||||
|
# and Euler characteristic more clearly
|
||||||
|
eigenspace, _ = goldberg_operators["dk"].diagonalize()
|
||||||
|
|
||||||
|
def show_diagonalized(operator: GoldbergOperator):
|
||||||
|
assert operator != "g_T"
|
||||||
|
matrix = goldberg_operators[operator]
|
||||||
|
diag = eigenspace.inv() @ matrix @ eigenspace
|
||||||
|
|
||||||
|
return f"""{
|
||||||
|
sympy.latex(matrix)
|
||||||
|
} = \\textcolor{{red}}{{{
|
||||||
|
sympy.latex(eigenspace)
|
||||||
|
}}}{
|
||||||
|
sympy.latex(diag)
|
||||||
|
}\\textcolor{{blue}}{{{
|
||||||
|
sympy.latex(eigenspace.inv(), fold_short_frac=True)
|
||||||
|
}}}"""
|
||||||
|
|
||||||
|
Markdown(f"""
|
||||||
$$
|
$$
|
||||||
\begin{align*}
|
\\begin{{align*}}
|
||||||
c &= \begin{pmatrix}
|
dk &= {show_diagonalized("dk")} \\\\
|
||||||
1 & 2 & 0 \\
|
c &= {show_diagonalized("c")} \\\\
|
||||||
0 & 4 & 0 \\
|
w &= {show_diagonalized("w")}
|
||||||
0 & 1 & 1
|
\\end{{align*}}
|
||||||
\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 & 4
|
|
||||||
\end{pmatrix}
|
|
||||||
\textcolor{blue}{
|
|
||||||
\begin{pmatrix}
|
|
||||||
1 & -2/3 & 0 \\
|
|
||||||
1 & -1 & 1 \\
|
|
||||||
0 & 1/3 & 0
|
|
||||||
\end{pmatrix}
|
|
||||||
} \\
|
|
||||||
dk &= \begin{pmatrix}
|
|
||||||
0 & 2 & 0 \\
|
|
||||||
0 & 3 & 0 \\
|
|
||||||
1 & 0 & 1
|
|
||||||
\end{pmatrix}
|
|
||||||
= \textcolor{red}{
|
|
||||||
\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*}
|
|
||||||
$$
|
$$
|
||||||
|
""".replace(
|
||||||
|
"\\left[\\begin{matrix}", "\\begin{pmatrix}"
|
||||||
|
).replace(
|
||||||
|
"\\end{matrix}\\right]", "\\end{pmatrix}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
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"}
|
||||||
[
|
[
|
||||||
{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}
|
||||||
{.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}
|
||||||
{.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}
|
||||||
{.image-wide}
|
{.image-wide}
|
||||||
|
|
||||||
{.image-wide}
|
{.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.
|
||||||
|
|||||||
25
posts/pentagons/_metadata.yml
Normal file
25
posts/pentagons/_metadata.yml
Normal 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: " "
|
||||||
|
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
|
||||||
Loading…
x
Reference in New Issue
Block a user