Skip to content

Commit

Permalink
Fix doctests
Browse files Browse the repository at this point in the history
  • Loading branch information
saraedum committed Jun 21, 2024
1 parent 224c555 commit d6bafcf
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 145 deletions.
3 changes: 2 additions & 1 deletion flatsurvey/cache/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
# *********************************************************************

from flatsurvey.cache.cache import Cache
from flatsurvey.cache.pickles import Pickles

commands = [Cache.click]
commands = [Cache.click, Pickles.click]
4 changes: 2 additions & 2 deletions flatsurvey/jobs/flow_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ async def _consume(self, orientation, cost):
>>> surface = Ngon((1, 1, 1))
>>> decompositions = FlowDecompositions(surface=surface, report=Report([Log(surface)]), saddle_connection_orientations=SaddleConnectionOrientations(SaddleConnections(surface, report=None), report=None))
>>> produce = decompositions.produce() # indirect doctest
>>> asyncio.run(produce)
[Ngon([1, 1, 1])] [FlowDecompositions] ¯\_(ツ)_/¯ (orientation: (0, (-c ~ -1.7320508))) (cylinders: 1) (minimal: 0) (undetermined: 0)
>>> asyncio.run(produce) # doctest: +ELLIPSIS
[Ngon([1, 1, 1])] [FlowDecompositions] ¯\_(ツ)_/¯ (orientation: (0, ...)) (cylinders: 1) (minimal: 0) (undetermined: 0)
True
>>> decompositions._current
FlowDecomposition with 1 cylinders, 0 minimal components and 0 undetermined components
Expand Down
4 changes: 2 additions & 2 deletions flatsurvey/pipeline/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ async def produce(self):
>>> asyncio.run(produce) != Producer.EXHAUSTED
True
>>> orientations._current
(0, (-c ~ -1.7320508))
>>> orientations._current # doctest: +ELLIPSIS
(0, ...)
"""
self._current = None
Expand Down
123 changes: 32 additions & 91 deletions flatsurvey/surfaces/ngons.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class Ngon(Surface):
"""

def __init__(self, angles, length=None, lengths=None):
def __init__(self, angles, length=None, polygon=None):
super().__init__()

self.angles = list(angles)
Expand All @@ -97,22 +97,17 @@ def __init__(self, angles, length=None, lengths=None):
length = "exact-real"

self.length = length
if lengths is not None:
from flatsurf import EuclideanPolygonsWithAngles

# Support old pickles where polygon edge lengths are scaled by the
# length of the slopes.
# When we find such lengths, we set _lengths (and poison it with
# the wrong value.) However, we override the cache of polygon() so
# _lengths should never be accessed.
# TODO: Check that nobody else uses _lengths.
slopes = EuclideanPolygonsWithAngles(*self.angles).slopes()
edges = [l * r for (l, r) in zip(lengths, slopes)]
if sum(edges) == 0:
from flatsurf import Polygon
self.polygon.set_cache(Polygon(edges=edges))
if polygon is not None:
if isinstance(polygon, tuple):
# At some point we pickled the lengths of the sides instead of
# the actual polygon. We are too lazy to make these pickles
# work (because there are also two different flavors of those…)
import warnings
warnings.warn("ignoring legacy pickle of ngon; reported Ngon will have incorrect edge lengths")
polygon = self.polygon()

self._lengths.set_cache(tuple(lengths))
self.polygon.set_cache(polygon)

if any(a == sum(angles) / (len(angles) - 2) for a in angles):
import logging
Expand All @@ -129,9 +124,9 @@ def equivalents(self):
def ngon(angles):
angles = tuple(sorted(angles))
angles = tuple(a / gcd(angles) for a in angles)
if self._lengths.cache:
if self.polygon.cache:
raise NotImplementedError(
f"Cannot translate explicit lengths from {self} when constructing equivalent surface."
f"Cannot translate explicit polygon from {self} when constructing equivalent surface."
)
return Ngon(angles, length=self.length)

Expand Down Expand Up @@ -262,11 +257,11 @@ def unfolding_symmetries(self):
>>> S = Ngon((1, 1, 2))
>>> S.unfolding_symmetries
{[-1 0]
[ 0 -1], [1 0]
{[1 0]
[0 1], [ 0 1]
[-1 0], [ 0 -1]
[ 1 0]}
[ 1 0], [-1 0]
[ 0 -1]}
"""
S = self._surface()
Expand Down Expand Up @@ -485,68 +480,6 @@ def __repr__(self):
def _flatsurvey_characteristics(self):
return {"angles": [int(a) for a in self.angles]}

@cached_method
def _lengths(self):
r"""
Determine random lengths for the sides of the original n-gon.
EXAMPLES::
>>> Ngon((1, 2, 3))._lengths()
(8, 2/3*c, 2*c)
"""
from flatsurf import EuclideanPolygonsWithAngles

E = EuclideanPolygonsWithAngles(*self.angles)
if self.length == "exact-real":
from pyexactreal import ExactReals

R = ExactReals(E.base_ring())
elif self.length == "e-antic":
R = E.base_ring()
else:
raise NotImplementedError(self.length)

L = E.lengths_polytope()

def random_lengths():
# Do this properly in sage-flatsurf. See #11.
from random import shuffle

from sage.all import free_module_element, span

U = L.ambient_space().subspace([])

lengths = []
rays = list(L.rays())
shuffle(rays)
for ray in rays:
ray = ray.vector()
if ray not in U:
U += span([ray])
length = R.zero()
while length <= 0:
length = R.random_element() if lengths else R.one()
lengths.append(length)

return tuple(lengths)

for n in range(1024):
lengths = random_lengths()

from flatsurf import Polygon
try:
Polygon(angles=self.angles, lengths=lengths)
except ValueError:
continue

while min(lengths) < 1:
lengths = tuple(length * 2 for length in lengths)
return lengths

raise Exception(f"giving up on {E}")

def cache_predicate(self, exact, cache=None):
def surface_predicate(surface):
if surface.type != "Ngon":
Expand Down Expand Up @@ -586,12 +519,22 @@ def polygon(self):
EXAMPLES::
>>> Ngon((1, 1, 1)).polygon()
Polygon(vertices=[(0, 0), (4, 0), (2, 2*c)])
>>> Ngon((1, 1, 1)).polygon() # doctest: +ELLIPSIS
Polygon(vertices=[(0, 0), (..., 0), (..., ...)])
"""
from flatsurf import Polygon
return Polygon(angles=self.angles, lengths=self._lengths())
from flatsurf import EuclideanPolygonsWithAngles

E = EuclideanPolygonsWithAngles(*self.angles)
if self.length == "exact-real":
# sage-flatsurf does not support random_element() with exact-real lengths
raise NotImplementedError("exact-real ngons are currently not supported")
elif self.length == "e-antic":
pass
else:
raise NotImplementedError(self.length)

return E.random_element()

@cached_method
def _surface(self):
Expand Down Expand Up @@ -619,16 +562,16 @@ def to_yaml(cls, representer, self):
)

def __reduce__(self):
return (Ngon, (self.angles, self.length, self._lengths()))
return (Ngon, (self.angles, self.length, self.polygon()))

def __hash__(self):
return hash((tuple(self.angles), self._lengths()))
return hash((tuple(self.angles), self.polygon()))

def __eq__(self, other):
return (
isinstance(other, Ngon)
and self.angles == other.angles
and self._lengths() == other._lengths()
and self.polygon() == other.polygon()
)

def __ne__(self, other):
Expand Down Expand Up @@ -849,8 +792,6 @@ def partitions(total, n):


__test__ = {
# Work around https://trac.sagemath.org/ticket/33951
"Ngon._lengths": Ngon._lengths.__doc__,
# Work around https://trac.sagemath.org/ticket/33951
"Ngon._polygon": Ngon.polygon.__doc__,
# Work around https://trac.sagemath.org/ticket/33951
Expand Down
14 changes: 7 additions & 7 deletions flatsurvey/surfaces/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Surface:
EXAMPLES::
>>> from flatsurvey.surfaces import Ngon
>>> isinstance(Ngon((1, 1, 1), 'exact-real'), Surface)
>>> isinstance(Ngon((1, 1, 1)), Surface)
True
"""
Expand All @@ -53,9 +53,9 @@ def reference(self):
EXAMPLES::
>>> from flatsurvey.surfaces import Ngon
>>> Ngon((1, 1, 3), 'exact-real').reference()
>>> Ngon((1, 1, 3)).reference()
'Veech 1989 via Ngon([2, 3, 5])'
>>> Ngon((10, 11, 82), 'exact-real').reference() is None
>>> Ngon((10, 11, 82)).reference() is None
True
"""
Expand All @@ -71,7 +71,7 @@ def orbit_closure(self):
EXAMPLES::
>>> from flatsurvey.surfaces import Ngon
>>> Ngon((1, 1, 1), 'exact-real').orbit_closure()
>>> Ngon((1, 1, 1)).orbit_closure()
GL(2,R)-orbit closure of dimension at least 2 in H_1(0) (ambient dimension 2)
"""
Expand Down Expand Up @@ -102,8 +102,8 @@ def flat_triangulation(self):
EXAMPLES::
>>> from flatsurvey.surfaces import Ngon
>>> Ngon((1, 1, 1)).flat_triangulation()
FlatTriangulationCombinatorial(vertices = (1, -3, 2, -1, 3, -2), faces = (1, 2, 3)(-1, -2, -3)) with vectors {1: (0, (-4*c ~ -6.9282032)), 2: (6, (2*c ~ 3.4641016)), 3: (-6, (2*c ~ 3.4641016))}
>>> Ngon((1, 1, 1)).flat_triangulation() # doctest: +ELLIPSIS
FlatTriangulationCombinatorial(vertices = (1, -3, 2, -1, 3, -2), faces = (1, 2, 3)(-1, -2, -3)) with vectors {1: (0, ...), 2: (..., ...), 3: (..., ...)}
"""
return self.orbit_closure()._surface
Expand Down Expand Up @@ -147,7 +147,7 @@ def command(self):
EXAMPLES::
>>> from flatsurvey.surfaces import Ngon
>>> Ngon((1, 1, 1), 'exact-real').command()
>>> Ngon((1, 1, 1)).command()
['pickle', '--base64', '...']
"""
Expand Down
31 changes: 10 additions & 21 deletions flatsurvey/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,18 @@
computations.
<BLANKLINE>
Goals:
boshernitzan-conjecture Determines whether Conjecture 2.2 in
Boshernitzan's *Billiards and Rational Periodic
Directions in Polygons* holds for this surface.
completely-cylinder-periodic Determines whether for all directions given by
saddle connections, the decomposition of the
surface is completely cylinder periodic, i.e.,
the decomposition consists only of cylinders.
cylinder-periodic-asymptotics Determines the maximum circumference of all
cylinders in each cylinder periodic direction.
cylinder-periodic-direction Determines whether there is a direction for
which the surface decomposes into cylinders.
orbit-closure Determines the GL₂(R) orbit closure of
``surface``.
undetermined-iet Tracks undetermined Interval Exchange
Transformations.
completely-cylinder-periodic Determines whether for all directions given by
saddle connections, the decomposition of the
surface is completely cylinder periodic, i.e.,
the decomposition consists only of cylinders.
cylinder-periodic-direction Determines whether there is a direction for
which the surface decomposes into cylinders.
orbit-closure Determines the GL₂(R) orbit closure of
``surface``.
undetermined-iet Tracks undetermined Interval Exchange
Transformations.
<BLANKLINE>
Intermediates:
boshernitzan-conjecture-orientations
Produces directions in $S^1(2d')$, i.e.,
corresponding to certain roots of unity, as
used in Conjecture 2.2 of Boshernitzan's
*Billiards and Rational Periodic Directions in
Polygons*.
flow-decompositions Turns directions coming from saddle
connections into flow decompositions.
saddle-connection-orientations Orientations of saddle connections on the
Expand Down
31 changes: 10 additions & 21 deletions flatsurvey/worker/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,17 @@
pickles Access a database of pickles storing parts of previous
computations.
Goals:
boshernitzan-conjecture Determines whether Conjecture 2.2 in
Boshernitzan's *Billiards and Rational Periodic
Directions in Polygons* holds for this surface.
completely-cylinder-periodic Determines whether for all directions given by
saddle connections, the decomposition of the
surface is completely cylinder periodic, i.e.,
the decomposition consists only of cylinders.
cylinder-periodic-asymptotics Determines the maximum circumference of all
cylinders in each cylinder periodic direction.
cylinder-periodic-direction Determines whether there is a direction for
which the surface decomposes into cylinders.
orbit-closure Determines the GL₂(R) orbit closure of
``surface``.
undetermined-iet Tracks undetermined Interval Exchange
Transformations.
completely-cylinder-periodic Determines whether for all directions given by
saddle connections, the decomposition of the
surface is completely cylinder periodic, i.e.,
the decomposition consists only of cylinders.
cylinder-periodic-direction Determines whether there is a direction for
which the surface decomposes into cylinders.
orbit-closure Determines the GL₂(R) orbit closure of
``surface``.
undetermined-iet Tracks undetermined Interval Exchange
Transformations.
Intermediates:
boshernitzan-conjecture-orientations
Produces directions in $S^1(2d')$, i.e.,
corresponding to certain roots of unity, as
used in Conjecture 2.2 of Boshernitzan's
*Billiards and Rational Periodic Directions in
Polygons*.
flow-decompositions Turns directions coming from saddle
connections into flow decompositions.
saddle-connection-orientations Orientations of saddle connections on the
Expand Down

0 comments on commit d6bafcf

Please sign in to comment.