diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb767ad..963a346 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,46 +13,37 @@ jobs: strategy: matrix: include: - - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,surface_dynamicsr" + - optionals: "sage" sagelib: "9.3" - python: "3.9.2" - - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,surface_dynamics" - sagelib: "9.4" - python: "3.9.5" - - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,pynormaliz,surface_dynamics" - sagelib: "9.5" - python: "3.9.9" - - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,pynormaliz,surface_dynamics" - sagelib: "9.6" - python: "3.10.5" - - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,pynormaliz,surface_dynamics" - sagelib: "9.7" - python: "3.10.5" - - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,pynormaliz,surface_dynamics" - sagelib: "9.8" - python: "3.10.5" - - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,pynormaliz,surface_dynamics" + python: "3.9.15" + - optionals: "sage" sagelib: "10.0" - python: "3.10.5" + python: "3.10.8" + - optionals: "sage,sage_flatsurf,pyeantic,pyintervalxt,pyflatsurf,pynormaliz,surface_dynamics" + sagelib: "10.4" + python: "3.12.15" # Test optional dependencies in isolation - optionals: "sage" - sagelib: "10.0" - python: "3.10.5" + sagelib: "10.4" + python: "3.12.15" - optionals: "sage,sage_flatsurf" - sagelib: "10.0" - python: "3.10.5" + sagelib: "10.4" + python: "3.12.15" - optionals: "sage,pyeantic" - sagelib: "10.0" - python: "3.10.5" + sagelib: "10.4" + python: "3.12.15" - optionals: "sage,pyintervalxt" - sagelib: "10.0" - python: "3.10.5" + sagelib: "10.4" + python: "3.12.15" - optionals: "sage,pynormaliz" - sagelib: "10.0" - python: "3.10.5" + sagelib: "10.4" + python: "3.12.15" - optionals: "sage,surface_dynamics" - sagelib: "10.0" - python: "3.10.5" + sagelib: "10.4" + python: "3.12.15" + - optionals: "sage,pyflatsurf" + sagelib: "10.4" + python: "3.12.15" steps: - uses: actions/checkout@v2 with: { submodules: recursive } diff --git a/doc/source/veerer_demo.rst b/doc/source/veerer_demo.rst index 18f284a..fb8f2d1 100644 --- a/doc/source/veerer_demo.rst +++ b/doc/source/veerer_demo.rst @@ -142,7 +142,7 @@ train-tracks. :: sage: # constructing veering triangulations from a component stratum - sage: Q = QuadraticStratum(3,3,3,3) # optional - surface_dynamics + sage: Q = Stratum([3,3,3,3], 2) # optional - surface_dynamics sage: Qreg = Q.regular_component() # optional - surface_dynamics sage: Qirr = Q.irregular_component() # optional - surface_dynamics @@ -343,7 +343,7 @@ filtering cylindrical (single test is cheap) ~2 sec for H(4)^hyp :: - sage: H = AbelianStratum(4).hyperelliptic_component() # optional - surface_dynamics + sage: H = Stratum([4], 1).hyperelliptic_component() # optional - surface_dynamics sage: V = VeeringTriangulation.from_stratum(H) # optional - surface_dynamics sage: AV = CoreAutomaton(V) # long time - ~21 secs # optional - surface_dynamics sage: print(AV.num_states()) # long time - ~150 µs # optional - surface_dynamics diff --git a/environment.yml b/environment.yml index 8570799..a2cfedb 100644 --- a/environment.yml +++ b/environment.yml @@ -21,8 +21,9 @@ dependencies: # Work around https://github.com/conda-forge/givaro-feedstock/issues/13 - givaro=4.1.1=h192cbe9_1 - sage-flatsurf # optional: sage_flatsurf - - pyeantic >=1.0.0,<2 # optional: pyeantic - - pyintervalxt >=3.1.0,<4 # optional: pyintervalxt + - pyeantic >=1,<2 # optional: pyeantic + - pyintervalxt >=3,<4 # optional: pyintervalxt + - pyflatsurf >=3.10.1,<4 # optional: pyflatsurf # Work around https://github.com/conda-forge/pynormaliz-feedstock/issues/10 by pinning normaliz and pynormaliz - pynormaliz 2.17 # optional: pynormaliz - normaliz 3.9.4 # optional: pynormaliz diff --git a/veerer/automaton.py b/veerer/automaton.py index ba061e3..05c8762 100644 --- a/veerer/automaton.py +++ b/veerer/automaton.py @@ -67,9 +67,9 @@ class Automaton(object): Exploring strata:: - sage: from surface_dynamics import * # optional - surface_dynamics - sage: strata = [AbelianStratum(2), QuadraticStratum(2,-1,-1), # optional - surface_dynamics - ....: QuadraticStratum(2,2), AbelianStratum(1,1)] + sage: from surface_dynamics import Stratum # optional - surface_dynamics + sage: strata = [Stratum([2], 1), Stratum([2,-1,-1], 2), # optional - surface_dynamics + ....: Stratum([2,2], 2), Stratum([1,1], 1)] sage: for stratum in strata: # optional - surface_dynamics ....: print(stratum) ....: vt = VeeringTriangulation.from_stratum(stratum) @@ -466,13 +466,13 @@ def from_stratum(self, stratum, **kwds): EXAMPLES:: sage: from veerer import * - sage: from surface_dynamics import * # optional - surface_dynamics - sage: CoreAutomaton.from_stratum(AbelianStratum(2)) # optional - surface_dynamics + sage: from surface_dynamics import Stratum # optional - surface_dynamics + sage: CoreAutomaton.from_stratum(Stratum([2], 1)) # optional - surface_dynamics Core veering automaton with 86 vertices - sage: GeometricAutomaton.from_stratum(AbelianStratum(2)) # optional - surface_dynamics + sage: GeometricAutomaton.from_stratum(Stratum([2], 1)) # optional - surface_dynamics Geometric veering automaton with 54 vertices - sage: Q = QuadraticStratum(8) # optional - surface_dynamics + sage: Q = Stratum([8], 2) # optional - surface_dynamics sage: A = CoreAutomaton.from_stratum(Q, max_size=100) # optional - surface_dynamics sage: A # optional - surface_dynamics Partial core veering automaton with 101 vertices @@ -956,11 +956,11 @@ def cylinder_diagrams(self, col=RED): EXAMPLES:: sage: from veerer import RED, BLUE, GeometricAutomaton - sage: from surface_dynamics import AbelianStratum # optional - surface_dynamics - sage: A = GeometricAutomaton.from_stratum(AbelianStratum(2)) # optional - surface_dynamics + sage: from surface_dynamics import Stratum # optional - surface_dynamics + sage: A = GeometricAutomaton.from_stratum(Stratum([2], 1)) # optional - surface_dynamics sage: len(A.cylinder_diagrams(RED)) # optional - surface_dynamics 2 - sage: A = GeometricAutomaton.from_stratum(AbelianStratum(1, 1)) # optional - surface_dynamics + sage: A = GeometricAutomaton.from_stratum(Stratum([1, 1], 1)) # optional - surface_dynamics sage: len(A.cylinder_diagrams(RED)) # optional - surface_dynamics 4 diff --git a/veerer/features.py b/veerer/features.py index 9e09410..11d3e51 100644 --- a/veerer/features.py +++ b/veerer/features.py @@ -4,7 +4,7 @@ from sage.features import PythonModule -flatsurf_feature = PythonModule( +sage_flatsurf_feature = PythonModule( "flatsurf", url="https://flatsurf.github.io/sage-flatsurf/#installation" ) surface_dynamics_feature = PythonModule( @@ -16,6 +16,9 @@ curver_feature = PythonModule( "curver", url="https://curver.readthedocs.io/en/master/user/install.html" ) +pyflatsurf_feature = PythonModule( + "pyflatsurf", url="https://github.com/flatsurf/flatsurf" +) pynormaliz_feature = PythonModule( "PyNormaliz", url="https://github.com/Normaliz/PyNormaliz" ) diff --git a/veerer/flatsurf_conversion.py b/veerer/flatsurf_conversion.py new file mode 100644 index 0000000..ca2267b --- /dev/null +++ b/veerer/flatsurf_conversion.py @@ -0,0 +1,208 @@ +r""" +Conversions from pyflatsurf and sage-flatsurf to veerer. +""" + +from array import array + +from sage.matrix.constructor import matrix + +from .features import sage_flatsurf_feature, pyflatsurf_feature +from .triangulation import Triangulation +from .veering_triangulation import VeeringTriangulation +from .linear_family import VeeringTriangulationLinearFamily + + +def oriented_slope(a, rotate=1): + r""" + Return either ``(1, 1)``, ``(1, -1)``, ``(-1, 1)`` or ``(-1, -1)``. + + If ``rotate`` is set to ``1`` then consider the edge as if it was rotated counterclockwise + infinitesimally (to make horizontal edges positive slopes and vertical edges negative + slopes). If it is set to ``-1`` then the rotation is in clockwise direction. If it is + set to ``0`` then return ``0`` on horizontal and vertical. + + EXAMPLES:: + + sage: from veerer.flatsurf_conversion import oriented_slope + sage: oriented_slope((1, 1)) + (1, 1) + sage: oriented_slope((-1, 1)) + (-1, 1) + sage: oriented_slope((-1, -1)) + (-1, -1) + sage: oriented_slope((1, -1)) + (1, -1) + + sage: oriented_slope((1, 0)) + (1, 1) + sage: oriented_slope((0, 1)) + (-1, 1) + sage: oriented_slope((-1, 0)) + (-1, -1) + sage: oriented_slope((0, -1)) + (1, -1) + + sage: oriented_slope((1, 0), rotate=-1) + (1, -1) + sage: oriented_slope((0, 1), rotate=-1) + (1, 1) + sage: oriented_slope((-1, 0), rotate=-1) + (-1, 1) + sage: oriented_slope((0, -1), rotate=-1) + (-1, -1) + + sage: oriented_slope((1, 0), rotate=0) + 0 + sage: oriented_slope((0, 1), rotate=0) + 0 + sage: oriented_slope((-1, 0), rotate=0) + 0 + sage: oriented_slope((0, -1), rotate=0) + 0 + + sage: oriented_slope((0, 0)) + Traceback (most recent call last): + ... + ValueError: zero vector + """ + x, y = a + if not x and not y: + raise ValueError("zero vector") + if (x > 0 and y > 0): + return (1, 1) + if (x < 0 and y < 0): + return (-1, -1) + if (x > 0 and y < 0): + return (1, -1) + if (x < 0 and y > 0): + return (-1, 1) + + if rotate == 0: + return 0 + if rotate == 1: + if x > 0: + return (1, 1) + if y > 0: + return (-1, 1) + if x < 0: + return (-1, -1) + if y < 0 : + return (1, -1) + if rotate == -1: + if x > 0: + return (1, -1) + if y > 0: + return (1, 1) + if x < 0: + return (-1, 1) + if y < 0: + return (-1, -1) + raise ValueError("invalid argument rotate={}".format(rotate)) + + +def pyflatsurf_surface_to_veerer_veering_triangulation(surface): + r""" + Convert a pyflatsurf surface in a veering triangulation. + + Note that the flatstructure is lost in the process. + + EXAMPLES:: + + sage: from veerer.flatsurf_conversion import pyflatsurf_surface_to_veerer_veering_triangulation + + sage: from flatsurf import Polygon, similarity_surfaces # optional - sage_flatsurf pyflatsurf + sage: P = Polygon(angles=(1,1,1,7), lengths=(3, 2)) # optional - sage_flatsurf pyflatsurf + sage: S1 = similarity_surfaces.billiard(P).minimal_cover("translation").erase_marked_points() # optional - sage_flatsurf pyflatsurf + sage: S2 = S1.l_infinity_delaunay_triangulation() # optional - sage_flatsurf pyflatsurf + sage: S2.is_veering_triangulated() # optional - sage_flatsurf pyflatsurf + True + sage: S3 = S2.pyflatsurf().codomain().flat_triangulation() # optional - sage_flatsurf pyflatsurf + sage: pyflatsurf_surface_to_veerer_veering_triangulation(S3) # optional - sage_flatsurf pyflatsurf + (VeeringTriangulation("(0,1,2)(3,4,~0)(5,6,~1)(7,8,~2)(9,~3,10)(11,~8,~4)(12,13,~5)(14,15,~6)(16,~11,~10)(17,18,~12)(19,20,~13)(~20,~15,~18)(~19,~16,~17)(~14,~7,~9)", "BRRRRRBRBBBRBRRRRRBBR"), [-1, -1, 1, 1, ..., -1, 1, 1]) + """ + pyflatsurf_feature.require() + + faces = surface.faces() + n = 3 * faces.size() + ep = array('i', [n - i - 1 for i in range(n)]) + fp = array('i', [-1] * n) + slopes = [None] * n + x_orientation = [None] * n + for face in faces: + a, b, c = face + va = surface.fromHalfEdge(a) + sa = oriented_slope((va.x(), va.y())) + vb = surface.fromHalfEdge(b) + sb = oriented_slope((vb.x(), vb.y())) + vc = surface.fromHalfEdge(c) + sc = oriented_slope((vc.x(), vc.y())) + a = a.id() + b = b.id() + c = c.id() + if a < 0 : + a = n + a + elif a > 0: + a = a - 1 + if b < 0: + b = n + b + elif b > 0: + b = b - 1 + if c < 0: + c = n + c + elif c > 0: + c = c - 1 + fp[a] = b + fp[b] = c + fp[c] = a + x_orientation[a] = sa[0] + slopes[a] = sa[0] * sa[1] + x_orientation[b] = sb[0] + slopes[b] = sb[0] * sb[1] + x_orientation[c] = sc[0] + slopes[c] = sc[0] * sc[1] + + colors = "".join("R" if x == 1 else "B" for x in slopes) + t = Triangulation.from_face_edge_perms(fp, ep) + return VeeringTriangulation(t, colors), x_orientation + + +def sage_flatsurf_orbit_closure_to_veerer_linear_family(orbit_closure): + r""" + Conversion of sage-flatsurf ``GL2ROrbitClosure`` to veerer ``VeeringTriangulationLinearFamily``. + + EXAMPLES:: + + sage: from veerer.flatsurf_conversion import sage_flatsurf_orbit_closure_to_veerer_linear_family + + sage: from flatsurf import Polygon, similarity_surfaces, GL2ROrbitClosure # optional - sage_flatsurf pyflatsurf + sage: P = Polygon(angles=(1,1,1,7), lengths=(3, 2)) # optional - sage_flatsurf pyflatsurf + sage: S1 = similarity_surfaces.billiard(P).minimal_cover("translation").erase_marked_points() # optional - sage_flatsurf pyflatsurf + sage: S2 = S1.l_infinity_delaunay_triangulation() # optional - sage_flatsurf pyflatsurf + sage: O = GL2ROrbitClosure(S2) # optional - sage_flatsurf pyflatsurf + sage: for d in O.decompositions(4): # optional - sage_flatsurf pyflatsurf + ....: O.update_tangent_space_from_flow_decomposition(d) + ....: if O.dimension() == 4: + ....: break + sage: F = sage_flatsurf_orbit_closure_to_veerer_linear_family(O) # optional - sage_flatsurf pyflatsurf + sage: F.base_ring() # optional - sage_flatsurf pyflatsurf + Number Field in c0 with defining polynomial x^2 - x - 1 with c0 = 1.618033988749895? + sage: F # optional - sage_flatsurf pyflatsurf + VeeringTriangulationLinearFamily("(0,1,2)(3,4,~0)(5,6,~1)(7,8,~2)(9,~3,10)(11,~8,~4)(12,13,~5)(14,15,~6)(16,~11,~10)(17,18,~12)(19,20,~13)(~20,~15,~18)(~19,~16,~17)(~14,~7,~9)", "BRRRRRBRBBBRBRRRRRBBR", [(1, 0, 1, 0, 1, c0, c0, 0, -1, -c0, -c0, 0, c0, 0, c0, 2*c0, c0, 0, c0, -c0, c0), (0, 1, 1, 0, 0, c0, c0 - 1, 0, -1, -1, -1, -1, 1, c0 - 1, 1, c0, 0, -c0 + 1, -c0 + 2, -c0 + 1, 2*c0 - 2), (0, 0, 0, 1, 1, 0, 0, 0, 0, -c0, -c0 + 1, 1, 0, 0, c0, c0, c0, c0 - 1, c0 - 1, -1, 1), (0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, c0 - 1, c0 - 1, c0 - 1, -c0 + 1)]) + """ + sage_flatsurf_feature.require() + + vt, x_orientation = pyflatsurf_surface_to_veerer_veering_triangulation(orbit_closure._surface) + + # build generators for the tangent space + phi = orbit_closure.V2.base_ring().coerce_embedding() + K = phi.codomain() + subspace = [] + for i in range(orbit_closure._U_rank): + v = orbit_closure.lift(orbit_closure._U[i]) + v = [x_orientation[j] * phi(v[j]) for j in range(len(v))] + subspace.append(v) + + R = orbit_closure.field_of_definition() + if orbit_closure.base_ring() != R: + subspace = matrix(orbit_closure.base_ring(), subspace).echelon_form().change_ring(R) + return VeeringTriangulationLinearFamily(vt, subspace) diff --git a/veerer/tatami_decomposition.py b/veerer/tatami_decomposition.py index dd8104b..97873c0 100644 --- a/veerer/tatami_decomposition.py +++ b/veerer/tatami_decomposition.py @@ -55,21 +55,21 @@ def tatami_decomposition(rectangles, base_ring=None): sage: from veerer.constants import LEFT, RIGHT sage: r0 = ((1, RIGHT, 1), (1, RIGHT, 0), (0, LEFT, 0), (0, LEFT, 1), (3, RIGHT, 2), (3, RIGHT, 1), (0, RIGHT, 2), (0, RIGHT, 1)) sage: r1 = ((3, LEFT, 0), (3, LEFT, 2), (0, LEFT, 1), (0, LEFT, 2), (3, RIGHT, 1), (1, LEFT, 1), (0, RIGHT, 1), (0, RIGHT, 0)) - sage: tatami_decomposition([r0, r1]) # optional: sage_flatsurf + sage: tatami_decomposition([r0, r1]) # optional - sage_flatsurf Translation Surface built from a square and a rectangle TESTS:: - sage: tatami_decomposition([r0, r1], ZZ) # optional: sage_flatsurf + sage: tatami_decomposition([r0, r1], ZZ) # optional - sage_flatsurf Translation Surface built from a square and a rectangle - sage: tatami_decomposition([r0, r1], QQ) # optional: sage_flatsurf + sage: tatami_decomposition([r0, r1], QQ) # optional - sage_flatsurf Translation Surface built from a square and a rectangle - sage: tatami_decomposition([r0, r1], AA) # optional: sage_flatsurf + sage: tatami_decomposition([r0, r1], AA) # optional - sage_flatsurf Translation Surface built from a square and a rectangle sage: r0 = ((1, RIGHT, AA(1)), (1, RIGHT, 0), (0, LEFT, 0), (0, LEFT, 1), (3, RIGHT, 2), (3, RIGHT, 1), (0, RIGHT, 2), (0, RIGHT, 1)) sage: r1 = ((3, LEFT, 0), (3, LEFT, 2), (0, LEFT, 1), (0, LEFT, 2), (3, RIGHT, 1), (1, LEFT, 1), (0, RIGHT, 1), (0, RIGHT, 0)) - sage: tatami_decomposition([r0, r1]) # optional: sage_flatsurf + sage: tatami_decomposition([r0, r1]) # optional - sage_flatsurf Translation Surface built from a square and a rectangle """ if base_ring is None: diff --git a/veerer/veering_quadrangulation.py b/veerer/veering_quadrangulation.py index 9aa2908..26ba1fc 100644 --- a/veerer/veering_quadrangulation.py +++ b/veerer/veering_quadrangulation.py @@ -2011,12 +2011,12 @@ def ferenczi_zamboni_class(k, labelled=False): sage: len(ferenczi_zamboni_class(4, labelled=False)) # optional - surface_dynamics 10 """ - from surface_dynamics import AbelianStratum + from surface_dynamics import Stratum o = one_quadrangulation(k).to_origami() if k % 2: - assert o.stratum_component() == AbelianStratum(k-1).hyperelliptic_component() + assert o.stratum_component() == Stratum([k-1], 1).hyperelliptic_component() elif k != 2: - assert o.stratum_component() == AbelianStratum((k-2)//2, (k-2)//2).hyperelliptic_component() + assert o.stratum_component() == Stratum([(k-2)//2, (k-2)//2], 1).hyperelliptic_component() if not labelled: ocan = o.relabel(inplace=False) diff --git a/veerer/veering_triangulation.py b/veerer/veering_triangulation.py index 694267b..7c55ea2 100644 --- a/veerer/veering_triangulation.py +++ b/veerer/veering_triangulation.py @@ -65,10 +65,10 @@ class VeeringTriangulation(Triangulation): sage: from surface_dynamics import * # optional - surface_dynamics - sage: VeeringTriangulation.from_stratum(AbelianStratum(2)) # optional - surface_dynamics + sage: VeeringTriangulation.from_stratum(Stratum([2], 1)) # optional - surface_dynamics VeeringTriangulation("(0,6,~5)(1,8,~7)(2,7,~6)(3,~1,~8)(4,~2,~3)(5,~0,~4)", "RRRBBBBBB") - sage: vt = VeeringTriangulation.from_stratum(QuadraticStratum({1:4})) # optional - surface_dynamics + sage: vt = VeeringTriangulation.from_stratum(Stratum({1:4}, 2)) # optional - surface_dynamics sage: vt.stratum() # optional - surface_dynamics Q_2(1^4) @@ -488,13 +488,13 @@ def from_stratum(cls, c, folded_edges=False, mutable=False, check=True): sage: from surface_dynamics import * # optional - surface_dynamics sage: from veerer import * - sage: T = VeeringTriangulation.from_stratum(AbelianStratum(2)) # optional - surface_dynamics + sage: T = VeeringTriangulation.from_stratum(Stratum([2], 1)) # optional - surface_dynamics sage: T # optional - surface_dynamics VeeringTriangulation("(0,6,~5)(1,8,~7)(2,7,~6)(3,~1,~8)(4,~2,~3)(5,~0,~4)", "RRRBBBBBB") sage: T.stratum() # optional - surface_dynamics H_2(2) - sage: Q = QuadraticStratum(9,-1) # optional - surface_dynamics + sage: Q = Stratum([9,-1], 2) # optional - surface_dynamics sage: CTreg = VeeringTriangulation.from_stratum(Q.regular_component()) # optional - surface_dynamics sage: CTreg.stratum() # optional - surface_dynamics @@ -1080,14 +1080,14 @@ def stratum(self): Some examples with purple edges:: - sage: from surface_dynamics import AbelianStratum, QuadraticStratum # optional - surface_dynamics - sage: C = AbelianStratum(2) # optional - surface_dynamics - sage: t = VeeringTriangulation.from_stratum(C, mutable=True) # optional - surface_dynamics - sage: t.forgot_forward_flippable_colour() # optional - surface_dynamics - sage: t.stratum() # optional - surface_dynamics + sage: from surface_dynamics import Stratum # optional - surface_dynamics + sage: C = Stratum([2], 1) # optional - surface_dynamics + sage: t = VeeringTriangulation.from_stratum(C, mutable=True) # optional - surface_dynamics + sage: t.forgot_forward_flippable_colour() # optional - surface_dynamics + sage: t.stratum() # optional - surface_dynamics H_2(2) - sage: C = QuadraticStratum(1,1,1,1) # optional - surface_dynamics + sage: C = Stratum([1,1,1,1], 2) # optional - surface_dynamics sage: t = VeeringTriangulation.from_stratum(C, mutable=True) # optional - surface_dynamics sage: t.forgot_forward_flippable_colour() # optional - surface_dynamics sage: t.stratum() # optional - surface_dynamics @@ -1095,14 +1095,13 @@ def stratum(self): """ from .features import surface_dynamics_feature surface_dynamics_feature.require() + from surface_dynamics import Stratum A = self.angles() if any(a%2 for a in A) or not self.is_abelian(): - from surface_dynamics import QuadraticStratum - return QuadraticStratum([(a-2) for a in A]) + return Stratum([(a - 2) for a in A], 2) else: - from surface_dynamics import AbelianStratum - return AbelianStratum([(a-2)/2 for a in A]) + return Stratum([(a - 2) // 2 for a in A], 1) def dimension(self): r""" @@ -1798,7 +1797,7 @@ def to_string(self): 'RRB_120_012' sage: from surface_dynamics import * # optional - surface_dynamics - sage: T = VeeringTriangulation.from_stratum(QuadraticStratum({1:20})) # optional - surface_dynamics + sage: T = VeeringTriangulation.from_stratum(Stratum({1:20}, 2)) # optional - surface_dynamics sage: s = T.to_string() # optional - surface_dynamics sage: TT = VeeringTriangulation.from_string(s) # optional - surface_dynamics sage: T == TT # optional - surface_dynamics @@ -3037,11 +3036,10 @@ def _flat_structure_from_train_track_lengths(self, VH, VV, base_ring=None, mutab Return a flat structure from two vectors ``VH`` and ``VV`` satisfying the train track equations. """ - from sage.modules.free_module import VectorSpace + from sage.modules.free_module import FreeModule if base_ring is None: - from sage.rings.rational_field import QQ - base_ring = QQ + base_ring = self.base_ring() assert len(VH) == len(VV) == self.num_edges() assert all(x >=0 for x in VH) @@ -3050,7 +3048,7 @@ def _flat_structure_from_train_track_lengths(self, VH, VV, base_ring=None, mutab self._set_train_track_constraints(self._tt_check, VH, HORIZONTAL, False, False) self._set_train_track_constraints(self._tt_check, VV, VERTICAL, False, False) - V = VectorSpace(base_ring, 2) + V = FreeModule(base_ring, 2) vectors = [V((x, y if self._colouring[i] == RED else -y)) for \ i,(x,y) in enumerate(zip(VV, VH))] m = self.num_edges() @@ -3091,8 +3089,20 @@ def flat_structure_middle(self, backend=None): sage: T.flat_structure_middle() FlatVeeringTriangulation(Triangulation("(0,1,2)"), [(1, 2), (-2, -1), (1, -1)]) + sage: x = polygen(QQ) + sage: K = NumberField(x^2 - x - 1, 'c0', embedding=(1+AA(5).sqrt())/2) + sage: c0 = K.gen() + sage: T = VeeringTriangulation("(0,1,2)(3,4,~0)(5,6,~1)(7,8,~2)(9,~3,10)(11,~8,~4)(12,13,~5)(14,15,~6)(16,~11,~10)(17,18,~12)(19,20,~13)(~20,~15,~18)(~19,~16,~17)(~14,~7,~9)", "BRRRRRBRBBBRBRRRRRBBR") + sage: deformations = [(1, 0, 1, 0, 1, c0, c0, 0, -1, -c0, -c0, 0, c0, 0, c0, 2*c0, c0, 0, c0, -c0, c0), + ....: (0, 1, 1, 0, 0, c0, c0 - 1, 0, -1, -1, -1, -1, 1, c0 - 1, 1, c0, 0, -c0 + 1, -c0 + 2, -c0 + 1, 2*c0 - 2), + ....: (0, 0, 0, 1, 1, 0, 0, 0, 0, -c0, -c0 + 1, 1, 0, 0, c0, c0, c0, c0 - 1, c0 - 1, -1, 1), + ....: (0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, c0 - 1, c0 - 1, c0 - 1, -c0 + 1)] + sage: F = VeeringTriangulationLinearFamily(T, deformations) + sage: F.flat_structure_middle() + FlatVeeringTriangulation(Triangulation("(0,1,2)(3,4,~0)(5,6,~1)(7,8,~2)(9,~3,10)(11,~8,~4)(12,13,~5)(14,15,~6)(16,~11,~10)(17,18,~12)(19,20,~13)(~20,~15,~18)(~19,~16,~17)(~14,~7,~9)"), ...) + sage: from surface_dynamics import * # optional - surface_dynamics - sage: Q = QuadraticStratum({1:4, -1:4}) # optional - surface_dynamics + sage: Q = Stratum({1:4, -1:4}, 2) # optional - surface_dynamics sage: CT = VeeringTriangulation.from_stratum(Q) # optional - surface_dynamics sage: CT.flat_structure_middle() # optional - surface_dynamics FlatVeeringTriangulation(Triangulation("(0,18,~17)(1,20,~19)...(19,~18,~0)"), [(3, 3), (1, 1), ..., (-3, -3)]) @@ -3127,7 +3137,7 @@ def flat_structure_min(self, allow_degenerations=False): sage: from veerer import * sage: from surface_dynamics import * # optional - surface_dynamics - sage: Q = QuadraticStratum({1:4, -1:4}) # optional - surface_dynamics + sage: Q = Stratum({1:4, -1:4}, 2) # optional - surface_dynamics sage: CT = VeeringTriangulation.from_stratum(Q) # optional - surface_dynamics sage: CT.flat_structure_min() # optional - surface_dynamics FlatVeeringTriangulation(Triangulation("(0,18,~17)(1,20,~19)...(19,~18,~0)"), [(3, 3), (1, 1), ..., (-3, -3)])