def as_embedded_number_field_elements(algs): # number_field_elements_from_algebraics() now takes an embedded=... # argument, but doesn't yet support all cases we need nf, elts, emb = number_field_elements_from_algebraics(algs) if nf is not QQ: nf = NumberField(nf.polynomial(), nf.variable_name(), embedding=emb(nf.gen())) elts = [elt.polynomial()(nf.gen()) for elt in elts] nf, hom = good_number_field(nf) elts = [hom(elt) for elt in elts] # assert [QQbar.coerce(elt) == alg for alg, elt in zip(algs, elts)] return nf, elts
def as_embedded_number_field_elements(algs): try: nf, elts, _ = number_field_elements_from_algebraics(algs, embedded=True) except NotImplementedError: # compatibility with Sage <= 9.3 nf, elts, emb = number_field_elements_from_algebraics(algs) if nf is not QQ: nf = NumberField(nf.polynomial(), nf.variable_name(), embedding=emb(nf.gen())) elts = [elt.polynomial()(nf.gen()) for elt in elts] nf, hom = good_number_field(nf) elts = [hom(elt) for elt in elts] assert [QQbar.coerce(elt) == alg for alg, elt in zip(algs, elts)] return nf, elts
def platonic_icosahedron(): r"""Produce a triple consisting of a polyhedral version of the platonic icosahedron, the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface to the polyhedron. EXAMPLES:: sage: from flatsurf.geometry.polyhedra import platonic_icosahedron sage: polyhedron,surface,surface_to_polyhedron = platonic_icosahedron() sage: TestSuite(surface).run() r""" vertices=[] phi=AA(1+sqrt(5))/2 F=NumberField(phi.minpoly(),"phi",embedding=phi) phi=F.gen() for i in xrange(3): for s1 in xrange(-1,3,2): for s2 in xrange(-1,3,2): p=3*[None] p[i]=s1*phi p[(i+1)%3]=s2 p[(i+2)%3]=0 vertices.append(vector(F,p)) p=Polyhedron(vertices=vertices) s,m = polyhedron_to_cone_surface(p) return p,s,m
def platonic_dodecahedron(): r"""Produce a triple consisting of a polyhedral version of the platonic dodecahedron, the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface to the polyhedron. EXAMPLES:: sage: from flatsurf.geometry.polyhedra import platonic_dodecahedron sage: polyhedron,surface,surface_to_polyhedron = platonic_dodecahedron() sage: TestSuite(surface).run() r""" vertices=[] phi=AA(1+sqrt(5))/2 F=NumberField(phi.minpoly(),"phi",embedding=phi) phi=F.gen() for x in xrange(-1,3,2): for y in xrange(-1,3,2): for z in xrange(-1,3,2): vertices.append(vector(F,(x,y,z))) for x in xrange(-1,3,2): for y in xrange(-1,3,2): vertices.append(vector(F,(0,x*phi,y/phi))) vertices.append(vector(F,(y/phi,0,x*phi))) vertices.append(vector(F,(x*phi,y/phi,0))) scale=AA(2/sqrt(1+(phi-1)**2+(1/phi-1)**2)) p=Polyhedron(vertices=vertices) s,m = polyhedron_to_cone_surface(p,scaling_factor=scale) return p,s,m
def number_field_elements_from_algebraics(elts, name='a'): r""" The native Sage function ``number_field_elements_from_algebraics`` currently returns number field *without* embedding. This function return field with embedding! EXAMPLES:: sage: from flatsurf.geometry.polygon import number_field_elements_from_algebraics sage: z = QQbar.zeta(5) sage: c = z.real() sage: s = z.imag() sage: number_field_elements_from_algebraics((c,s)) (Number Field in a with defining polynomial y^4 - 5*y^2 + 5, [1/2*a^2 - 3/2, 1/2*a]) """ from sage.rings.qqbar import number_field_elements_from_algebraics from sage.rings.number_field.number_field import NumberField field,elts,phi = number_field_elements_from_algebraics(elts, minimal=True) polys = [x.polynomial() for x in elts] K = NumberField(field.polynomial(), name, embedding=AA(phi(field.gen()))) gen = K.gen() return K, [x.polynomial()(gen) for x in elts]
def platonic_icosahedron(): r"""Produce a triple consisting of a polyhedral version of the platonic icosahedron, the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface to the polyhedron. EXAMPLES:: sage: from flatsurf.geometry.polyhedra import platonic_icosahedron sage: polyhedron,surface,surface_to_polyhedron = platonic_icosahedron() sage: TestSuite(surface).run() r""" vertices = [] phi = AA(1 + sqrt(5)) / 2 F = NumberField(phi.minpoly(), "phi", embedding=phi) phi = F.gen() for i in range(3): for s1 in range(-1, 3, 2): for s2 in range(-1, 3, 2): p = 3 * [None] p[i] = s1 * phi p[(i + 1) % 3] = s2 p[(i + 2) % 3] = 0 vertices.append(vector(F, p)) p = Polyhedron(vertices=vertices) s, m = polyhedron_to_cone_surface(p) return p, s, m
def platonic_dodecahedron(): r"""Produce a triple consisting of a polyhedral version of the platonic dodecahedron, the associated cone surface, and a ConeSurfaceToPolyhedronMap from the surface to the polyhedron. EXAMPLES:: sage: from flatsurf.geometry.polyhedra import platonic_dodecahedron sage: polyhedron,surface,surface_to_polyhedron = platonic_dodecahedron() sage: TestSuite(surface).run() r""" vertices = [] phi = AA(1 + sqrt(5)) / 2 F = NumberField(phi.minpoly(), "phi", embedding=phi) phi = F.gen() for x in range(-1, 3, 2): for y in range(-1, 3, 2): for z in range(-1, 3, 2): vertices.append(vector(F, (x, y, z))) for x in range(-1, 3, 2): for y in range(-1, 3, 2): vertices.append(vector(F, (0, x * phi, y / phi))) vertices.append(vector(F, (y / phi, 0, x * phi))) vertices.append(vector(F, (x * phi, y / phi, 0))) scale = AA(2 / sqrt(1 + (phi - 1)**2 + (1 / phi - 1)**2)) p = Polyhedron(vertices=vertices) s, m = polyhedron_to_cone_surface(p, scaling_factor=scale) return p, s, m
def _number_field_from_algebraics(self): r""" Given a projective point defined over ``QQbar``, return the same point, but defined over a number field. This is only implemented for points of projective space. OUTPUT: scheme point EXAMPLES:: sage: R.<x> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(QQbar,1) sage: Q = P([-1/2*QQbar(sqrt(2)) + QQbar(I), 1]) sage: S = Q._number_field_from_algebraics(); S (1/2*a^3 + a^2 - 1/2*a : 1) sage: S.codomain() Projective Space of dimension 1 over Number Field in a with defining polynomial y^4 + 1 with a = 0.7071067811865475? + 0.7071067811865475?*I The following was fixed in :trac:`23808`:: sage: R.<x> = PolynomialRing(QQ) sage: P.<x,y> = ProjectiveSpace(QQbar,1) sage: Q = P([-1/2*QQbar(sqrt(2)) + QQbar(I), 1]);Q (-0.7071067811865475? + 1*I : 1) sage: S = Q._number_field_from_algebraics(); S (1/2*a^3 + a^2 - 1/2*a : 1) sage: T = S.change_ring(QQbar) # Used to fail sage: T (-0.7071067811865475? + 1.000000000000000?*I : 1) sage: Q[0] == T[0] True """ from sage.schemes.projective.projective_space import is_ProjectiveSpace if not is_ProjectiveSpace(self.codomain()): raise NotImplementedError("not implemented for subschemes") # Trac #23808: Keep the embedding info associated with the number field K # used below, instead of in the separate embedding map phi which is # forgotten. K_pre, P, phi = number_field_elements_from_algebraics(list(self)) if K_pre is QQ: K = QQ else: from sage.rings.number_field.number_field import NumberField K = NumberField(K_pre.polynomial(), embedding=phi(K_pre.gen()), name='a') psi = K_pre.hom([K.gen()], K) # Identification of K_pre with K P = [psi(p) for p in P] # The elements of P were elements of K_pre from sage.schemes.projective.projective_space import ProjectiveSpace PS = ProjectiveSpace(K, self.codomain().dimension_relative(), 'z') return PS(P)
def as_embedded_number_field_element(alg): from sage.rings.number_field.number_field import NumberField nf, elt, emb = alg.as_number_field_element() if nf is QQ: res = elt else: embnf = NumberField(nf.polynomial(), nf.variable_name(), embedding=emb(nf.gen())) res = elt.polynomial()(embnf.gen()) # assert QQbar.coerce(res) == alg return res
def __init__(self,lambda_squared=None, field=None): if lambda_squared==None: from sage.rings.number_field.number_field import NumberField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing R=PolynomialRing(ZZ,'x') x = R.gen() from sage.rings.qqbar import AA field=NumberField(x**3-ZZ(5)*x**2+ZZ(4)*x-ZZ(1), 'r', embedding=AA(ZZ(4))) self._l=field.gen() else: if field is None: self._l=lambda_squared field=lambda_squared.parent() else: self._l=field(lambda_squared) Surface.__init__(self,field, ZZ.zero(), finite=False)
def polyhedron_to_cone_surface(polyhedron, use_AA=False, scaling_factor=ZZ(1)): r"""Construct the Euclidean Cone Surface associated to the surface of a polyhedron and a map from the cone surface to the polyhedron. INPUT: - ``polyhedron`` -- A 3-dimensional polyhedron, which should be define over something that coerces into AA - ``use_AA`` -- If True, the surface returned will be defined over AA. If false, the algorithm will find the smallest NumberField and write the field there. - ``scaling_factor`` -- The surface returned will have a metric scaled by multiplication by this factor (compared with the original polyhendron). This can be used to produce a surface defined over a smaller NumberField. OUTPUT: A pair consisting of a ConeSurface and a ConeSurfaceToPolyhedronMap. EXAMPLES:: sage: from flatsurf.geometry.polyhedra import * sage: vertices=[] sage: for i in xrange(3): ....: temp=vector([1 if k==i else 0 for k in xrange(3)]) ....: for j in xrange(-1,3,2): ....: vertices.append(j*temp) sage: octahedron=Polyhedron(vertices=vertices) sage: surface,surface_to_octahedron = \ ....: polyhedron_to_cone_surface(octahedron,scaling_factor=AA(1/sqrt(2))) sage: TestSuite(surface).run() sage: TestSuite(surface_to_octahedron).run(skip="_test_pickling") sage: surface.num_polygons() 8 sage: surface.base_ring() Number Field in a with defining polynomial y^2 - 3 sage: sqrt3=surface.base_ring().gen() sage: tangent_bundle=surface.tangent_bundle() sage: v=tangent_bundle(0,(0,0),(sqrt3,2)) sage: traj=v.straight_line_trajectory() sage: traj.flow(10) sage: traj.is_saddle_connection() True sage: traj.combinatorial_length() 8 sage: surface_to_octahedron(traj) [(-1, 0, 0), (0.?e-18, -0.8000000000000000?, -0.2000000000000000?), (0.2500000000000000?, -0.750000000000000?, 0.?e-18), (0.4000000000000000?, 0.?e-19, 0.6000000000000000?), (0.?e-19, 0.500000000000000?, 0.500000000000000?), (-2/5, 3/5, 0), (-0.2500000000000000?, 0.?e-18, -0.750000000000000?), (0.?e-18, -0.2000000000000000?, -0.8000000000000000?), (1, 0, 0)] sage: surface_to_octahedron(traj.segment(0)) ((-1, 0, 0), (0.?e-18, -0.8000000000000000?, -0.2000000000000000?)) sage: surface_to_octahedron(traj.segment(0).start()) ((-1, 0, 0), (2.886751345948129?, -2.309401076758503?, -0.5773502691896258?)) sage: # octahedron.plot(wireframe=None,frame=False)+line3d(surface_to_octahedron(traj),radius=0.01) """ assert polyhedron.dim()==3 c=polyhedron.center() vertices=polyhedron.vertices() vertex_order={} for i,v in enumerate(vertices): vertex_order[v]=i faces=polyhedron.faces(2) face_order={} face_edges=[] face_vertices=[] face_map_data=[] for i,f in enumerate(faces): face_order[f]=i edges=f.as_polyhedron().faces(1) face_edges_temp = set() for edge in edges: edge_temp=set() for vertex in edge.vertices(): v=vertex.vector() v.set_immutable() edge_temp.add(v) face_edges_temp.add(frozenset(edge_temp)) last_edge = next(iter(face_edges_temp)) v = next(iter(last_edge)) face_vertices_temp=[v] for j in xrange(len(face_edges_temp)-1): for edge in face_edges_temp: if v in edge and edge!=last_edge: # bingo last_edge=edge for vv in edge: if vv!=v: v=vv face_vertices_temp.append(vv) break break v0=face_vertices_temp[0] v1=face_vertices_temp[1] v2=face_vertices_temp[2] n=(v1-v0).cross_product(v2-v0) if (v0-c).dot_product(n)<0: n=-n face_vertices_temp.reverse() v0=face_vertices_temp[0] v1=face_vertices_temp[1] v2=face_vertices_temp[2] face_vertices.append(face_vertices_temp) n=n/AA(n.norm()) w=v1-v0 w=w/AA(w.norm()) m=1/scaling_factor*matrix(AA,[w,n.cross_product(w),n]).transpose() mi=~m mis=mi.submatrix(0,0,2,3) face_map_data.append(( v0, # translation to bring origin in plane to v0 m.submatrix(0,0,3,2), -mis*v0, mis )) it=iter(face_vertices_temp) v_last=next(it) face_edge_dict={} j=0 for v in it: edge=frozenset([v_last,v]) face_edge_dict[edge]=j j+=1 v_last=v v=next(iter(face_vertices_temp)) edge=frozenset([v_last,v]) face_edge_dict[edge]=j face_edges.append(face_edge_dict) gluings={} for p1,face_edge_dict1 in enumerate(face_edges): for edge, e1 in face_edge_dict1.items(): found=False for p2, face_edge_dict2 in enumerate(face_edges): if p1!=p2 and edge in face_edge_dict2: e2=face_edge_dict2[edge] gluings[(p1,e1)]=(p2,e2) found=True break if not found: print(p1) print(e1) print(edge) raise RuntimeError("Failed to find glued edge") polygon_vertices_AA=[] for p,vs in enumerate(face_vertices): trans=face_map_data[p][2] m=face_map_data[p][3] polygon_vertices_AA.append([trans+m*v for v in vs]) if use_AA==True: Polys=Polygons(AA) polygons=[] for vs in polygon_vertices_AA: polygons.append(Polys(vertices=vs)) S=ConeSurface(surface_list_from_polygons_and_gluings(polygons,gluings)) return S, \ ConeSurfaceToPolyhedronMap(S,polyhedron,face_map_data) else: elts=[] for vs in polygon_vertices_AA: for v in vs: elts.append(v[0]) elts.append(v[1]) # Find the best number field: field,elts2,hom = number_field_elements_from_algebraics(elts,minimal=True) if field==QQ: # Defined over the rationals! polygon_vertices_field2=[] j=0 for vs in polygon_vertices_AA: vs2=[] for v in vs: vs2.append(vector(field,[elts2[j],elts2[j+1]])) j=j+2 polygon_vertices_field2.append(vs2) Polys=Polygons(field) polygons=[] for vs in polygon_vertices_field2: polygons.append(Polys(vertices=vs)) S=ConeSurface(surface_list_from_polygons_and_gluings(polygons,gluings)) return S, \ ConeSurfaceToPolyhedronMap(S,polyhedron,face_map_data) else: # Unfortunately field doesn't come with an real embedding (which is given by hom!) # So, we make a copy of the field, and add the embedding. field2=NumberField(field.polynomial(),name="a",embedding=hom(field.gen())) # The following converts from field to field2: hom2=field.hom(im_gens=[field2.gen()]) polygon_vertices_field2=[] j=0 for vs in polygon_vertices_AA: vs2=[] for v in vs: vs2.append(vector(field2,[hom2(elts2[j]),hom2(elts2[j+1])])) j=j+2 polygon_vertices_field2.append(vs2) Polys=Polygons(field2) polygons=[] for vs in polygon_vertices_field2: polygons.append(Polys(vertices=vs)) S=ConeSurface(surface_list_from_polygons_and_gluings(polygons,gluings)) return S, \ ConeSurfaceToPolyhedronMap(S,polyhedron,face_map_data)
class EInfinitySurface(Surface): r""" The surface based on the $E_\infinity$ graph. The biparite graph is shown below, with edges numbered: 0 1 2 -2 3 -3 4 -4 *---o---*---o---*---o---*---o---*... | |-1 o Here, black vertices are colored *, and white o. Black nodes represent vertical cylinders and white nodes represent horizontal cylinders. """ def __init__(self,lambda_squared=None, field=None): TranslationSurface_generic.__init__(self) if lambda_squared==None: from sage.rings.number_field.number_field import NumberField from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing R=PolynomialRing(ZZ,'x') x = R.gen() from sage.rings.qqbar import AA self._field=NumberField(x**3-ZZ(5)*x**2+ZZ(4)*x-ZZ(1), 'r', embedding=AA(ZZ(4))) self._l=self._field.gen() else: if field is None: self._l=lambda_squared self._field=lambda_squared.parent() else: self._field=field self._l=field(lambda_squared) Surface.__init__(self) def _repr_(self): r""" String representation. """ return "The E-infinity surface" def base_ring(self): r""" Return the rational field. """ return self._field def base_label(self): return ZZ.zero() @cached_method def get_white(self,n): r"""Get the weight of the white endpoint of edge n.""" l=self._l if n==0 or n==1: return l if n==-1: return l-1 if n==2: return 1-3*l+l**2 if n>2: x=self.get_white(n-1) y=self.get_black(n) return l*y-x return self.get_white(-n) @cached_method def get_black(self,n): r"""Get the weight of the black endpoint of edge n.""" l=self._l if n==0: return self._field(1) if n==1 or n==-1 or n==2: return l-1 if n>2: x=self.get_black(n-1) y=self.get_white(n-1) return y-x return self.get_black(1-n) def polygon(self, lab): r""" Return the polygon labeled by ``lab``. """ if lab not in self.polygon_labels(): raise ValueError("lab (=%s) not a valid label"%lab) from flatsurf.geometry.polygon import rectangle return rectangle(2*self.get_black(lab),self.get_white(lab)) def polygon_labels(self): r""" The set of labels used for the polygons. """ return ZZ def opposite_edge(self, p, e): r""" Return the pair ``(pp,ee)`` to which the edge ``(p,e)`` is glued to. """ if p==0: if e==0: return (0,2) if e==1: return (1,3) if e==2: return (0,0) if e==3: return (1,1) if p==1: if e==0: return (-1,2) if e==1: return (0,3) if e==2: return (2,0) if e==3: return (0,1) if p==-1: if e==0: return (2,2) if e==1: return (-1,3) if e==2: return (1,0) if e==3: return (-1,1) if p==2: if e==0: return (1,2) if e==1: return (-2,3) if e==2: return (-1,0) if e==3: return (-2,1) if p>2: if e%2: return -p,(e+2)%4 else: return 1-p,(e+2)%4 else: if e%2: return -p,(e+2)%4 else: return 1-p,(e+2)%4 def is_finite(self): return False
def polyhedron_to_cone_surface(polyhedron, use_AA=False, scaling_factor=ZZ(1)): r"""Construct the Euclidean Cone Surface associated to the surface of a polyhedron and a map from the cone surface to the polyhedron. INPUT: - ``polyhedron`` -- A 3-dimensional polyhedron, which should be define over something that coerces into AA - ``use_AA`` -- If True, the surface returned will be defined over AA. If false, the algorithm will find the smallest NumberField and write the field there. - ``scaling_factor`` -- The surface returned will have a metric scaled by multiplication by this factor (compared with the original polyhendron). This can be used to produce a surface defined over a smaller NumberField. OUTPUT: A pair consisting of a ConeSurface and a ConeSurfaceToPolyhedronMap. EXAMPLES:: sage: from flatsurf.geometry.polyhedra import * sage: vertices=[] sage: for i in range(3): ....: temp=vector([1 if k==i else 0 for k in range(3)]) ....: for j in range(-1,3,2): ....: vertices.append(j*temp) sage: octahedron=Polyhedron(vertices=vertices) sage: surface,surface_to_octahedron = \ ....: polyhedron_to_cone_surface(octahedron,scaling_factor=AA(1/sqrt(2))) sage: TestSuite(surface).run() sage: TestSuite(surface_to_octahedron).run(skip="_test_pickling") sage: surface.num_polygons() 8 sage: surface.base_ring() Number Field in a with defining polynomial y^2 - 3 with a = 1.732050807568878? sage: sqrt3=surface.base_ring().gen() sage: tangent_bundle=surface.tangent_bundle() sage: v=tangent_bundle(0,(0,0),(sqrt3,2)) sage: traj=v.straight_line_trajectory() sage: traj.flow(10) sage: traj.is_saddle_connection() True sage: traj.combinatorial_length() 8 sage: path3d = surface_to_octahedron(traj) sage: len(path3d) 9 sage: # We will show that the length of the path is sqrt(42): sage: total_length = 0 sage: for i in range(8): ....: start = path3d[i] ....: end = path3d[i+1] ....: total_length += (vector(end)-vector(start)).norm() sage: ZZ(total_length**2) 42 """ assert polyhedron.dim() == 3 c = polyhedron.center() vertices = polyhedron.vertices() vertex_order = {} for i, v in enumerate(vertices): vertex_order[v] = i faces = polyhedron.faces(2) face_order = {} face_edges = [] face_vertices = [] face_map_data = [] for i, f in enumerate(faces): face_order[f] = i edges = f.as_polyhedron().faces(1) face_edges_temp = set() for edge in edges: edge_temp = set() for vertex in edge.vertices(): v = vertex.vector() v.set_immutable() edge_temp.add(v) face_edges_temp.add(frozenset(edge_temp)) last_edge = next(iter(face_edges_temp)) v = next(iter(last_edge)) face_vertices_temp = [v] for j in range(len(face_edges_temp) - 1): for edge in face_edges_temp: if v in edge and edge != last_edge: # bingo last_edge = edge for vv in edge: if vv != v: v = vv face_vertices_temp.append(vv) break break v0 = face_vertices_temp[0] v1 = face_vertices_temp[1] v2 = face_vertices_temp[2] n = (v1 - v0).cross_product(v2 - v0) if (v0 - c).dot_product(n) < 0: n = -n face_vertices_temp.reverse() v0 = face_vertices_temp[0] v1 = face_vertices_temp[1] v2 = face_vertices_temp[2] face_vertices.append(face_vertices_temp) n = n / AA(n.norm()) w = v1 - v0 w = w / AA(w.norm()) m = 1 / scaling_factor * matrix( AA, [w, n.cross_product(w), n]).transpose() mi = ~m mis = mi.submatrix(0, 0, 2, 3) face_map_data.append(( v0, # translation to bring origin in plane to v0 m.submatrix(0, 0, 3, 2), -mis * v0, mis)) it = iter(face_vertices_temp) v_last = next(it) face_edge_dict = {} j = 0 for v in it: edge = frozenset([v_last, v]) face_edge_dict[edge] = j j += 1 v_last = v v = next(iter(face_vertices_temp)) edge = frozenset([v_last, v]) face_edge_dict[edge] = j face_edges.append(face_edge_dict) gluings = {} for p1, face_edge_dict1 in enumerate(face_edges): for edge, e1 in face_edge_dict1.items(): found = False for p2, face_edge_dict2 in enumerate(face_edges): if p1 != p2 and edge in face_edge_dict2: e2 = face_edge_dict2[edge] gluings[(p1, e1)] = (p2, e2) found = True break if not found: print(p1) print(e1) print(edge) raise RuntimeError("Failed to find glued edge") polygon_vertices_AA = [] for p, vs in enumerate(face_vertices): trans = face_map_data[p][2] m = face_map_data[p][3] polygon_vertices_AA.append([trans + m * v for v in vs]) if use_AA == True: Polys = ConvexPolygons(AA) polygons = [] for vs in polygon_vertices_AA: polygons.append(Polys(vertices=vs)) S = ConeSurface( surface_list_from_polygons_and_gluings(polygons, gluings)) return S, \ ConeSurfaceToPolyhedronMap(S,polyhedron,face_map_data) else: elts = [] for vs in polygon_vertices_AA: for v in vs: elts.append(v[0]) elts.append(v[1]) # Find the best number field: field, elts2, hom = number_field_elements_from_algebraics(elts, minimal=True) if field == QQ: # Defined over the rationals! polygon_vertices_field2 = [] j = 0 for vs in polygon_vertices_AA: vs2 = [] for v in vs: vs2.append(vector(field, [elts2[j], elts2[j + 1]])) j = j + 2 polygon_vertices_field2.append(vs2) Polys = ConvexPolygons(field) polygons = [] for vs in polygon_vertices_field2: polygons.append(Polys(vertices=vs)) S = ConeSurface( surface_list_from_polygons_and_gluings(polygons, gluings)) return S, \ ConeSurfaceToPolyhedronMap(S,polyhedron,face_map_data) else: # Unfortunately field doesn't come with an real embedding (which is given by hom!) # So, we make a copy of the field, and add the embedding. field2 = NumberField(field.polynomial(), name="a", embedding=hom(field.gen())) # The following converts from field to field2: hom2 = field.hom(im_gens=[field2.gen()]) polygon_vertices_field2 = [] j = 0 for vs in polygon_vertices_AA: vs2 = [] for v in vs: vs2.append( vector(field2, [hom2(elts2[j]), hom2(elts2[j + 1])])) j = j + 2 polygon_vertices_field2.append(vs2) Polys = ConvexPolygons(field2) polygons = [] for vs in polygon_vertices_field2: polygons.append(Polys(vertices=vs)) S = ConeSurface( surface_list_from_polygons_and_gluings(polygons, gluings)) return S, \ ConeSurfaceToPolyhedronMap(S,polyhedron,face_map_data)