def test_gothic_generic(): x = polygen(QQ) K = NumberField(x**3 - 2, 'a', embedding=AA(2)**QQ((1, 3))) a = K.gen() S = translation_surfaces.cathedral(a, a**2) O = GL2ROrbitClosure(S) assert O.ambient_stratum() == AbelianStratum(2, 2, 2) for d in O.decompositions(4, 50): O.update_tangent_space_from_flow_decomposition(d) assert O.dimension() == O.absolute_dimension() == 4 assert O.field_of_definition() == QQ
def test_D9_number_field(): x = polygen(QQ) K = NumberField(x**3 - 2, 'a', embedding=AA(2)**QQ((1,3))) a = K.gen() S = translation_surfaces.mcmullen_genus2_prototype(2,1,0,-1,a/4) O = GL2ROrbitClosure(S) for d in O.decompositions(5): ncyl, nmin, nund = d.num_cylinders_minimals_undetermined() assert (nund == 0) assert ((nmin == 0) or (ncyl == 0 and 1 <= nmin <= 2)) O.update_tangent_space_from_flow_decomposition(d) assert O.dimension() == 3 assert O.field_of_definition() == QQ
def test_gothic_exact_reals(): pytest.importorskip('pyexactreal') from pyexactreal import ExactReals x = polygen(QQ) K = NumberField(x**3 - 2, 'a', embedding=AA(2)**QQ((1, 3))) R = ExactReals(K) S = translation_surfaces.cathedral(K.gen(), R.random_element([0.1, 0.2])) O = GL2ROrbitClosure(S) assert O.ambient_stratum() == AbelianStratum(2, 2, 2) for d in O.decompositions(4, 50): O.update_tangent_space_from_flow_decomposition(d) assert O.dimension() == O.absolute_dimension() == 4
def test_back_and_forth_nf(): p = iet.Permutation("a b c", "c b a") x = polygen(QQ) K = NumberField(x**2 - 2, 'sqrt2', embedding=AA(2).sqrt()) sqrt2 = K.gen() T = iet.IntervalExchangeTransformation(p, [1, sqrt2, sqrt2 - 1]) T2 = iet_to_pyintervalxt(T) T3 = iet_from_pyintervalxt(T2) assert T == T3 r1 = vector(ZZ, (0, 0, 0, 1, 1, 0)) r2 = vector(ZZ, (3, 1, 0, 1, 0, 2)) r3 = vector(ZZ, (5, 0, 1, 2, 0, 3)) K = NumberField(x**3 - 3, 'cbrt3', embedding=AA(3)**QQ((1, 3))) cbrt3 = K.gen() p = iet.Permutation(["a", "b", "c", "d", "e", "f"], ["f", "d", "c", "b", "a", "e"]) l = r1 + (cbrt3 - 1) * r2 + cbrt3**2 * r3 T = iet.IntervalExchangeTransformation(p, l) assert T.sah_arnoux_fathi_invariant().is_zero() T2 = iet_to_pyintervalxt(T) assert list(T2.safInvariant()) == [0, 0, 0] T3 = iet_from_pyintervalxt(T2) assert T == T3
def test_D9_exact_real(): pytest.importorskip('pyexactreal') from pyexactreal import ExactReals R = ExactReals(QQ) x = polygen(QQ) K = NumberField(x**3 - 2, 'a', embedding=AA(2)**QQ((1,3))) a = K.gen() S = translation_surfaces.mcmullen_genus2_prototype(2,1,0,-1,R.random_element([0.1, 0.2])) O = GL2ROrbitClosure(S) for d in O.decompositions(5): ncyl, nmin, nund = d.num_cylinders_minimals_undetermined() assert (nund == 0) assert ((nmin == 0) or (ncyl == 0 and 1 <= nmin <= 2)) O.update_tangent_space_from_flow_decomposition(d) assert O.dimension() == 3
def test_gothic_veech(): x = polygen(QQ) K = NumberField(x**2 - 2, 'sqrt2', embedding=AA(2)**QQ((1, 2))) sqrt2 = K.gen() x = QQ((1, 2)) y = 1 a = x + y * sqrt2 b = -3 * x - QQ((3, 2)) + 3 * y * sqrt2 S = translation_surfaces.cathedral(a, b) O = GL2ROrbitClosure(S) assert O.ambient_stratum() == AbelianStratum(2, 2, 2) for d in O.decompositions(4, 50): assert d.parabolic() O.update_tangent_space_from_flow_decomposition(d) assert O.dimension() == O.absolute_dimension() == 2 assert O.field_of_definition() == O.V2._isomorphic_vector_space.base_ring()
def test_nf(): from sage.all import NumberField, QQ, AA, Rational, polygen from pyeantic.sage_conversion import sage_nf_to_eantic x = polygen(QQ) # linear K = NumberField(x - 3, 'x', embedding=QQ(3)) L = sage_nf_to_eantic(K) # quadratic K = NumberField(2*x**2 - 3, 'A', embedding=AA(Rational((3,2)))**Rational((1,2))) L = sage_nf_to_eantic(K) # cubic p = x**3 - x**2 - x - 1 s = p.roots(AA, False)[0] K = NumberField(x**3 - x**2 - x - 1, 's', embedding=s) L = sage_nf_to_eantic(K)
def __classcall__(cls, embed, category=None): r""" Normalize parameters so embedded real number fields are unique:: sage: from pyeantic import eantic, RealEmbeddedNumberField sage: K = NumberField(x**2 - 2, 'a', embedding=sqrt(AA(2))) sage: K = RealEmbeddedNumberField(K) sage: L = NumberField(x**2 - 2, 'a') sage: L = RealEmbeddedNumberField(L.embeddings(AA)[1]) sage: M = eantic.renf_class.make("a^2 - 2", "a", "1.4 +/- .1") sage: M = RealEmbeddedNumberField(M) sage: K is L True sage: K is M True """ if isinstance(embed, eantic.renf_class): # Since it is quite annoying to convert an fmpz polynomial, we parse # the printed representation of the renf_class. This is of course # not very robust… import re match = re.match("^NumberField\\(([^,]+), (\\[[^\\]]+\\])\\)$", repr(embed)) assert match, "renf_class printed in an unexpected way" minpoly = match.group(1) root_str = match.group(2) match = re.match("^\\d*\\*?([^\\^ *]+)[\\^ ]", minpoly) assert match, "renf_class printed leading coefficient in an unexpected way" minpoly = QQ[match.group(1)](minpoly) roots = [] AA_roots = minpoly.roots(AA, multiplicities=False) for prec in [53, 64, 128, 256]: R = RealBallField(prec) root = R(root_str) roots = [aa for aa in AA_roots if R(aa).overlaps(root)] if len(roots) == 1: break if len(roots) != 1: raise RuntimeError( "cannot distinguish roots with limited ball field precision" ) embed = NumberField(minpoly, minpoly.variable_name(), embedding=roots[0]) if embed in NumberFields(): if not RR.has_coerce_map_from(embed): raise ValueError( "number field must be endowed with an embedding into the reals" ) if not embed.is_absolute(): raise NotImplementedError("number field must be absolute") # We recreate our NumberField from the embedding since number # fields with the same embedding might differ by other parameters # and therefore do not serve immediately as unique keys. embed = AA.coerce_map_from(embed) if isinstance(embed, Map): K = embed.domain() if K not in NumberFields(): raise ValueError("domain must be a number field") if not AA.has_coerce_map_from(embed.codomain()): raise ValueError("codomain must coerce into RR") if not K.is_absolute(): raise NotImplementedError("number field must be absolute") # We explicitly construct an embedding from the given embedding to # make sure that we get a useable key. minpoly = (QQ['x'].gen() - 1) if K is QQ else K.polynomial() minpoly = minpoly.change_variable_name('x') embedding = AA.one() if K is QQ else embed(K.gen()) embed = NumberField(minpoly, K.variable_name(), embedding=embedding) else: raise TypeError( "cannot build RealEmbeddedNumberField from embedding %s" % (type(embed))) category = category or Fields() return super(RealEmbeddedNumberField, cls).__classcall__(cls, embed, category)
import sys import pytest import itertools pytest.importorskip('pyflatsurf') from sage.all import AA, QQ from flatsurf import EquiangularPolygons, similarity_surfaces, GL2ROrbitClosure # TODO: the test for field of definition with is_isomorphic() does not check # for embeddings... though for quadratic fields it does not matter much. @pytest.mark.parametrize("a,b,c,d,l1,l2,veech,discriminant", [(1, 1, 1, 7, 1, 1, True, 5), (1, 1, 1, 7, AA(2).sqrt(), 1, False, 5), (1, 1, 1, 9, 1, 1, True, 3), (1, 1, 1, 9, AA(2).sqrt(), 1, False, 1), (2, 2, 3, 13, 1, 1, False, 5), (1, 1, 2, 8, 1, 1, False, 1), (1, 1, 2, 12, 1, 1, False, 2), (1, 2, 2, 11, 1, 1, False, 2), (1, 2, 2, 15, 1, 1, False, 5)]) def test_rank2_quadrilateral(a, b, c, d, l1, l2, veech, discriminant): E = EquiangularPolygons(a, b, c, d) P = E([l1, l2], normalized=True) B = similarity_surfaces.billiard(P, rational=True) S = B.minimal_cover(cover_type="translation") S = S.erase_marked_points() S, _ = S.normalized_coordinates() O = GL2ROrbitClosure(S)