remove unused, rename goldberg.common to goldberg.display
This commit is contained in:
parent
bbf141785e
commit
77dfe62b06
@ -1,14 +1,12 @@
|
|||||||
import itertools
|
import itertools
|
||||||
from dataclasses import dataclass, field
|
|
||||||
from typing import Iterable, Literal
|
from typing import Iterable, Literal
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import sympy
|
from goldberg.operators import Polyhedron
|
||||||
|
|
||||||
from goldberg.operators import GoldbergOperator, Polyhedron
|
|
||||||
|
|
||||||
GoldbergClass = Literal["I", "II", "III"]
|
GoldbergClass = Literal["I", "II", "III"]
|
||||||
|
|
||||||
|
|
||||||
def group_dict(xs: Iterable, key=None):
|
def group_dict(xs: Iterable, key=None):
|
||||||
"""
|
"""
|
||||||
Group the items of `xs` into a dict using `sorted` and `itertools.groupby`.
|
Group the items of `xs` into a dict using `sorted` and `itertools.groupby`.
|
||||||
@ -17,7 +15,7 @@ def group_dict(xs: Iterable, key=None):
|
|||||||
return {i: list(j) for i, j in itertools.groupby(sorted(xs, key=key), key=key)}
|
return {i: list(j) for i, j in itertools.groupby(sorted(xs, key=key), key=key)}
|
||||||
|
|
||||||
|
|
||||||
def hexagons_to_polyhedron(hexagon_count: int): # | sympy.Expr):
|
def hexagons_to_polyhedron(hexagon_count: int):
|
||||||
"""General Goldberg solution"""
|
"""General Goldberg solution"""
|
||||||
return Polyhedron(
|
return Polyhedron(
|
||||||
face_count=hexagon_count + 12,
|
face_count=hexagon_count + 12,
|
||||||
@ -26,26 +24,8 @@ def hexagons_to_polyhedron(hexagon_count: int): # | sympy.Expr):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class GoldbergData:
|
|
||||||
parameter: tuple[int, int]
|
|
||||||
conway: str
|
|
||||||
|
|
||||||
parameter_link: str | None = None
|
|
||||||
conway_recipe: str | None = None
|
|
||||||
|
|
||||||
extra: list = field(default_factory=list)
|
|
||||||
|
|
||||||
|
|
||||||
def link_polyhedronisme(text: str, recipe: str) -> str:
|
def link_polyhedronisme(text: str, recipe: str) -> str:
|
||||||
return f"[{text}](https://levskaya.github.io/polyhedronisme/?recipe={recipe}){{target=\"_blank\"}}"
|
return f'[{text}](https://levskaya.github.io/polyhedronisme/?recipe={recipe}){{target="_blank"}}'
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class GCOperator:
|
|
||||||
name: GoldbergOperator
|
|
||||||
matrix: sympy.Matrix
|
|
||||||
parameter: int | sympy.Symbol
|
|
||||||
|
|
||||||
|
|
||||||
def parameter_to_class(parameter: tuple[int, int]) -> GoldbergClass:
|
def parameter_to_class(parameter: tuple[int, int]) -> GoldbergClass:
|
||||||
@ -57,11 +37,17 @@ def parameter_to_class(parameter: tuple[int, int]) -> GoldbergClass:
|
|||||||
|
|
||||||
|
|
||||||
def display_conway(conway_notation: str, seed: str | None = None):
|
def display_conway(conway_notation: str, seed: str | None = None):
|
||||||
|
"""
|
||||||
|
Display a Conway notation string in LaTeX.
|
||||||
|
Indexed operators (u, t, and k) have their indices placed in subscripts.
|
||||||
|
|
||||||
|
If `seed` is given, the notation is applied to it.
|
||||||
|
If the notation contains equals signs, these are interpreted as separate recipes to apply.
|
||||||
|
"""
|
||||||
# If a seed is given, split at the equals and apply to both sides
|
# If a seed is given, split at the equals and apply to both sides
|
||||||
if seed is not None:
|
if seed is not None:
|
||||||
conway_notation = " = ".join(
|
conway_notation = " = ".join(
|
||||||
operation + seed
|
operation + seed for operation in conway_notation.split(" = ")
|
||||||
for operation in conway_notation.split(" = ")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Latexify and subscript the numbers in u, t, and k
|
# Latexify and subscript the numbers in u, t, and k
|
||||||
@ -21,7 +21,9 @@ dodecahedral_goldberg_recipes: dict[tuple[int, int], str] = {
|
|||||||
# Assert all the above recipes are correct
|
# Assert all the above recipes are correct
|
||||||
verify_recipes(
|
verify_recipes(
|
||||||
{
|
{
|
||||||
param: " = ".join([op + "D" for op in goldberg_parameters_to_operations[param].split(" = ")])
|
param: " = ".join(
|
||||||
|
[op + "D" for op in goldberg_parameters_to_operations[param].split(" = ")]
|
||||||
|
)
|
||||||
for param in dodecahedral_goldberg_recipes.keys()
|
for param in dodecahedral_goldberg_recipes.keys()
|
||||||
},
|
},
|
||||||
dodecahedral_goldberg_recipes,
|
dodecahedral_goldberg_recipes,
|
||||||
|
|||||||
@ -106,7 +106,7 @@ def generalize_recipe(recipe: str | list[str], depth: int = 3) -> set[str]:
|
|||||||
"u(\\D)",
|
"u(\\D)",
|
||||||
"u2\\1",
|
"u2\\1",
|
||||||
re.sub("([KC]\\d*)", "", rec),
|
re.sub("([KC]\\d*)", "", rec),
|
||||||
)
|
),
|
||||||
).replace("dd", "")
|
).replace("dd", "")
|
||||||
for rec in recipe
|
for rec in recipe
|
||||||
]
|
]
|
||||||
@ -204,7 +204,9 @@ goldberg_operators: dict[GoldbergOperator, sympy.Matrix] = {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
goldberg_operators["tk"] = goldberg_operators["dk"] @ goldberg_operators["dk"]
|
goldberg_operators["tk"] = goldberg_operators["dk"] @ goldberg_operators["dk"]
|
||||||
goldberg_operators["g_T"] = from_same_eigenspace(goldberg_operators["dk"], [t_param % 3, 1, t_param])
|
goldberg_operators["g_T"] = from_same_eigenspace(
|
||||||
|
goldberg_operators["dk"], [t_param % 3, 1, t_param]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def apply_goldberg_operator(
|
def apply_goldberg_operator(
|
||||||
@ -215,18 +217,22 @@ def apply_goldberg_operator(
|
|||||||
# Naive combinatorial method
|
# Naive combinatorial method
|
||||||
if isinstance(operator, tuple):
|
if isinstance(operator, tuple):
|
||||||
return Polyhedron(
|
return Polyhedron(
|
||||||
*(goldberg_operators["g_T"] @ poly.as_matrix()).subs(t_param, loeschian_norm(*operator))
|
*(goldberg_operators["g_T"] @ poly.as_matrix()).subs(
|
||||||
|
t_param, loeschian_norm(*operator)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Try lookup parameter
|
# Try lookup parameter
|
||||||
if (parameter := goldberg_operators_to_parameters.get(operator)) is not None:
|
if (parameter := goldberg_operators_to_parameters.get(operator)) is not None:
|
||||||
return Polyhedron(
|
return Polyhedron(
|
||||||
*(goldberg_operators["g_T"] @ poly.as_matrix()).subs(t_param, loeschian_norm(*parameter))
|
*(goldberg_operators["g_T"] @ poly.as_matrix()).subs(
|
||||||
)
|
t_param, loeschian_norm(*parameter)
|
||||||
elif (matrix := goldberg_operators.get(operator)) is not None: # pyright: ignore[reportArgumentType]
|
)
|
||||||
return Polyhedron(
|
|
||||||
*(matrix @ poly.as_matrix())
|
|
||||||
)
|
)
|
||||||
|
elif (
|
||||||
|
matrix := goldberg_operators.get(operator) # pyright: ignore[reportArgumentType]
|
||||||
|
) is not None:
|
||||||
|
return Polyhedron(*(matrix @ poly.as_matrix()))
|
||||||
|
|
||||||
# Partition the recipe into operators for which we have the matrix
|
# Partition the recipe into operators for which we have the matrix
|
||||||
partitioned = []
|
partitioned = []
|
||||||
@ -237,7 +243,7 @@ def apply_goldberg_operator(
|
|||||||
for op in goldberg_operators.keys():
|
for op in goldberg_operators.keys():
|
||||||
if recipe.find(op) == 0:
|
if recipe.find(op) == 0:
|
||||||
partitioned.append(op)
|
partitioned.append(op)
|
||||||
recipe = recipe[len(op):]
|
recipe = recipe[len(op) :]
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
bad_recipe = True
|
bad_recipe = True
|
||||||
@ -249,8 +255,6 @@ def apply_goldberg_operator(
|
|||||||
if partitioned:
|
if partitioned:
|
||||||
# Technically you could just pointwise multiply the eigenvalues
|
# Technically you could just pointwise multiply the eigenvalues
|
||||||
matrix = reduce(matmul, (goldberg_operators[i] for i in partitioned))
|
matrix = reduce(matmul, (goldberg_operators[i] for i in partitioned))
|
||||||
return Polyhedron(
|
return Polyhedron(*(matrix @ poly.as_matrix()))
|
||||||
*(matrix @ poly.as_matrix())
|
|
||||||
)
|
|
||||||
|
|
||||||
raise ValueError("Could not partition operators!")
|
raise ValueError("Could not partition operators!")
|
||||||
|
|||||||
@ -171,6 +171,7 @@ def _apply_double(
|
|||||||
operation: GoldbergOperator,
|
operation: GoldbergOperator,
|
||||||
) -> dict[tuple[int, int], TetrahedralAntitruncation]:
|
) -> dict[tuple[int, int], TetrahedralAntitruncation]:
|
||||||
"""Build data for a double-Goldberg tetrahedral solution"""
|
"""Build data for a double-Goldberg tetrahedral solution"""
|
||||||
|
regularized_operation = "K300" + operation if operation == "w" else operation
|
||||||
return {
|
return {
|
||||||
entry: TetrahedralAntitruncation(
|
entry: TetrahedralAntitruncation(
|
||||||
conway=" = ".join(
|
conway=" = ".join(
|
||||||
@ -179,8 +180,8 @@ def _apply_double(
|
|||||||
conway_recipe=(
|
conway_recipe=(
|
||||||
"*"
|
"*"
|
||||||
if antitruncation.conway_recipe.find("*") == 0
|
if antitruncation.conway_recipe.find("*") == 0
|
||||||
else operation + antitruncation.conway_recipe
|
else regularized_operation + antitruncation.conway_recipe
|
||||||
), # TODO: might need to commute whirl with the last regularization operator
|
),
|
||||||
intercluster_paths=double_goldberg_paths[operation][
|
intercluster_paths=double_goldberg_paths[operation][
|
||||||
antitruncation.intercluster_paths[0]
|
antitruncation.intercluster_paths[0]
|
||||||
],
|
],
|
||||||
|
|||||||
@ -315,9 +315,11 @@ def recenter_axes(a: int, b: int):
|
|||||||
xspan = maxx - minx
|
xspan = maxx - minx
|
||||||
yspan = maxy - miny
|
yspan = maxy - miny
|
||||||
|
|
||||||
extent_x = a + 2*b + (a - b) * root3.real # rightward extent due to blue triangle
|
extent_x = a + 2 * b + (a - b) * root3.real # rightward extent due to blue triangle
|
||||||
if a > b and min(a, b) != 0:
|
if a > b and min(a, b) != 0:
|
||||||
extent_x += -(a-b) + (1 + a-b) * root3.real # leftward extent due to green parallelogram
|
extent_x += (
|
||||||
|
-(a - b) + (1 + a - b) * root3.real
|
||||||
|
) # leftward extent due to green parallelogram
|
||||||
|
|
||||||
extent_y = (2 * max(a, b) + min(a, b)) * root3.imag
|
extent_y = (2 * max(a, b) + min(a, b)) * root3.imag
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,12 @@ import sympy
|
|||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
import goldberg.triangles as goldberg_triangles
|
import goldberg.triangles as goldberg_triangles
|
||||||
from goldberg.common import link_polyhedronisme, parameter_to_class, display_conway, remove_repeats
|
from goldberg.display import (
|
||||||
|
display_conway,
|
||||||
|
link_polyhedronisme,
|
||||||
|
parameter_to_class,
|
||||||
|
remove_repeats,
|
||||||
|
)
|
||||||
from goldberg.operators import (
|
from goldberg.operators import (
|
||||||
Polyhedron,
|
Polyhedron,
|
||||||
goldberg_parameters_to_operations,
|
goldberg_parameters_to_operations,
|
||||||
@ -527,7 +532,7 @@ Though this list can be found
|
|||||||
#| classes: plain
|
#| classes: plain
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DodecahedralGoldbergSolution:
|
class DodecahedralSolution:
|
||||||
klass: str
|
klass: str
|
||||||
parameter: str
|
parameter: str
|
||||||
hexagon_count: str
|
hexagon_count: str
|
||||||
@ -543,9 +548,9 @@ special_names: dict[tuple[int, int], str] = {
|
|||||||
(1, 1): "https://en.wikipedia.org/wiki/Truncated_icosahedron",
|
(1, 1): "https://en.wikipedia.org/wiki/Truncated_icosahedron",
|
||||||
}
|
}
|
||||||
|
|
||||||
rows: list[DodecahedralGoldbergSolution] = [
|
rows: list[DodecahedralSolution] = [
|
||||||
# General solution
|
# General solution
|
||||||
DodecahedralGoldbergSolution(
|
DodecahedralSolution(
|
||||||
klass="",
|
klass="",
|
||||||
parameter="(a, b)",
|
parameter="(a, b)",
|
||||||
hexagon_count=f"${sympy.latex(polyhedron.face_count - 12)}$",
|
hexagon_count=f"${sympy.latex(polyhedron.face_count - 12)}$",
|
||||||
@ -562,7 +567,7 @@ rows: list[DodecahedralGoldbergSolution] = [
|
|||||||
] + sorted(
|
] + sorted(
|
||||||
[
|
[
|
||||||
# Particular solutions
|
# Particular solutions
|
||||||
DodecahedralGoldbergSolution(
|
DodecahedralSolution(
|
||||||
klass=parameter_to_class(parameter),
|
klass=parameter_to_class(parameter),
|
||||||
parameter=f"[{parameter}]({special_name})" if special_name is not None else str(parameter),
|
parameter=f"[{parameter}]({special_name})" if special_name is not None else str(parameter),
|
||||||
hexagon_count=str(polyhedron.face_count - 12),
|
hexagon_count=str(polyhedron.face_count - 12),
|
||||||
@ -589,7 +594,7 @@ rows: list[DodecahedralGoldbergSolution] = [
|
|||||||
key = lambda x: x.klass
|
key = lambda x: x.klass
|
||||||
)
|
)
|
||||||
|
|
||||||
headers = DodecahedralGoldbergSolution(
|
headers = DodecahedralSolution(
|
||||||
klass="Class",
|
klass="Class",
|
||||||
parameter="Parameter",
|
parameter="Parameter",
|
||||||
hexagon_count="$F_6$",
|
hexagon_count="$F_6$",
|
||||||
|
|||||||
@ -32,12 +32,12 @@ from IPython.display import Markdown
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
from goldberg.common import (
|
from goldberg.display import (
|
||||||
hexagons_to_polyhedron,
|
display_conway,
|
||||||
group_dict,
|
group_dict,
|
||||||
|
hexagons_to_polyhedron,
|
||||||
link_polyhedronisme,
|
link_polyhedronisme,
|
||||||
parameter_to_class,
|
parameter_to_class,
|
||||||
display_conway,
|
|
||||||
remove_repeats,
|
remove_repeats,
|
||||||
)
|
)
|
||||||
from goldberg.operators import (
|
from goldberg.operators import (
|
||||||
|
|||||||
@ -35,9 +35,9 @@ from IPython.display import Markdown
|
|||||||
import sympy
|
import sympy
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
from goldberg.common import (
|
from goldberg.display import (
|
||||||
hexagons_to_polyhedron,
|
|
||||||
group_dict,
|
group_dict,
|
||||||
|
hexagons_to_polyhedron,
|
||||||
link_polyhedronisme,
|
link_polyhedronisme,
|
||||||
)
|
)
|
||||||
from goldberg.operators import (
|
from goldberg.operators import (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user