def _make_CPRFanoToricVariety(self, name, coordinate_names, base_ring): """ Construct a (crepant partially resolved) Fano toric variety and cache the result. INPUT: - ``name`` -- string. One of the pre-defined names in the ``toric_varieties_rays_cones`` data structure. - ``coordinate_names`` -- A string describing the names of the homogeneous coordinates of the toric variety. - ``base_ring`` -- a ring (default: `\QQ`). The base ring for the toric variety. OUTPUT: A :class:`CPR-Fano toric variety <sage.schemes.toric.fano_variety.CPRFanoToricVariety_field>`. EXAMPLES:: sage: toric_varieties.P2() # indirect doctest 2-d CPR-Fano toric variety covered by 3 affine patches """ rays, cones = toric_varieties_rays_cones[name] if coordinate_names is None: dict_key = (name, base_ring) else: coordinate_names = normalize_names(coordinate_names, len(rays), DEFAULT_PREFIX) dict_key = (name, base_ring) + tuple(coordinate_names) if dict_key not in self.__dict__: polytope = LatticePolytope( matrix(rays).transpose() ) points = map(tuple, polytope.points().columns()) ray2point = [points.index(r) for r in rays] charts = [ [ray2point[i] for i in c] for c in cones ] self.__dict__[dict_key] = \ CPRFanoToricVariety(Delta_polar=polytope, coordinate_points=ray2point, charts=charts, coordinate_names=coordinate_names, base_ring=base_ring, check=self._check) return self.__dict__[dict_key]
def P(self, n, names='z+', base_ring=QQ): r""" Construct the ``n``-dimensional projective space `\mathbb{P}^n`. INPUT: - ``n`` -- positive integer. The dimension of the projective space. - ``names`` -- string. Names for the homogeneous coordinates. See :func:`~sage.schemes.toric.variety.normalize_names` for acceptable formats. - ``base_ring`` -- a ring (default: `\QQ`). The base ring for the toric variety. OUTPUT: A :class:`CPR-Fano toric variety <sage.schemes.toric.fano_variety.CPRFanoToricVariety_field>`. EXAMPLES:: sage: P3 = toric_varieties.P(3) sage: P3 3-d CPR-Fano toric variety covered by 4 affine patches sage: P3.fan().rays() N( 1, 0, 0), N( 0, 1, 0), N( 0, 0, 1), N(-1, -1, -1) in 3-d lattice N sage: P3.gens() (z0, z1, z2, z3) """ # We are going to eventually switch off consistency checks, so we need # to be sure that the input is acceptable. try: n = ZZ(n) # make sure that we got a "mathematical" integer except TypeError: raise TypeError("dimension of the projective space must be a " "positive integer!\nGot: %s" % n) if n <= 0: raise ValueError("only projective spaces of positive dimension " "can be constructed!\nGot: %s" % n) m = identity_matrix(n).augment(matrix(n, 1, [-1]*n)) charts = [ range(0,i)+range(i+1,n+1) for i in range(0,n+1) ] return CPRFanoToricVariety(Delta_polar=LatticePolytope(m), charts=charts, check=self._check, coordinate_names=names, base_ring=base_ring)
def integral_elements_in_box(K, C): r""" Return all integral elements of the totally real field `K` whose embeddings lie *numerically* within the bounds specified by the list `C`. The output is architecture dependent, and one may want to expand the bounds that define C by some epsilon. INPUT: - `K` -- a totally real number field - `C` -- a list [[lower, upper], ...] of lower and upper bounds, for each embedding EXAMPLES:: sage: x = polygen(QQ) sage: K.<alpha> = NumberField(x^2-2) sage: eps = 10e-6 sage: C = [[0-eps,5+eps],[0-eps,10+eps]] sage: ls = sage.rings.number_field.totallyreal_rel.integral_elements_in_box(K, C) sage: sorted([ a.trace() for a in ls ]) [0, 2, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 10, 10, 10, 10, 12, 12, 14] sage: len(ls) 19 sage: v = sage.rings.number_field.totallyreal_rel.integral_elements_in_box(K, C) sage: sorted(v) [0, -alpha + 2, 1, -alpha + 3, 2, 3, alpha + 2, 4, alpha + 3, 5, alpha + 4, 2*alpha + 3, alpha + 5, 2*alpha + 4, alpha + 6, 2*alpha + 5, 2*alpha + 6, 3*alpha + 5, 2*alpha + 7] A cubic field:: sage: x = polygen(QQ) sage: K.<a> = NumberField(x^3 - 16*x +16) sage: eps = 10e-6 sage: C = [[0-eps,5+eps]]*3 sage: v = sage.rings.number_field.totallyreal_rel.integral_elements_in_box(K, C) Note that the output is platform dependent (sometimes a 5 is listed below, and sometimes it isn't):: sage: sorted(v) [-1/2*a + 2, 1/4*a^2 + 1/2*a, 0, 1, 2, 3, 4,...-1/4*a^2 - 1/2*a + 5, 1/2*a + 3, -1/4*a^2 + 5] """ d = K.degree() Z_F = K.maximal_order() Foo = K.real_embeddings() B = K.reduced_basis() import numpy import numpy.linalg L = numpy.array([ [v(b) for b in B] for v in Foo]) Linv = numpy.linalg.inv(L) Vi = [[C[0][0]],[C[0][1]]] for i in range(1,d): Vi = sum([ [v + [C[i][0]], v + [C[i][1]]] for v in Vi], []) V = numpy.matrix(Linv)*(numpy.matrix(Vi).transpose()) j = 0 while j < 2**d: for i in range(d): if V[i,j] < V[i,j+1]: V[i,j] = math.floor(V[i,j]) V[i,j+1] = math.ceil(V[i,j+1]) else: V[i,j] = math.ceil(V[i,j]) V[i,j+1] = math.floor(V[i,j+1]) j += 2 W0 = (Linv*numpy.array([Vi[0]]*d)).transpose() W = (Linv*numpy.array([Vi[2**i] for i in range(d)])).transpose() for j in range(d): for i in range(d): if W[i,j] < W0[i,j]: W[i,j] = math.floor(W[i,j]) W0[i,j] = math.ceil(W0[i,j]) else: W[i,j] = math.ceil(W[i,j]) W0[i,j] = math.floor(W0[i,j]) M = [[int(V[i,j]) for i in range(V.shape[0])] for j in range(V.shape[1])] M += [[int(W0[i,j]) for j in range(W0.shape[0])] for i in range(W0.shape[0])] M += [[int(W[i,j]) for j in range(W.shape[1])] for i in range(W.shape[0])] from sage.matrix.constructor import matrix M = (matrix(IntegerRing(),len(M),len(M[0]), M).transpose()).columns() i = 0 while i < len(M): j = i+1 while j < len(M): if M[i] == M[j]: M.pop(j) else: j += 1 i += 1 from sage.geometry.lattice_polytope import LatticePolytope P = LatticePolytope(matrix(M).transpose()) S = [] try: pts = P.points().transpose() except ValueError: return [] for p in pts: theta = sum([ p.list()[i]*B[i] for i in range(d)]) inbounds = True for i in range(d): inbounds = inbounds and Foo[i](theta) >= C[i][0] and Foo[i](theta) <= C[i][1] if inbounds: S.append(theta) return S
def integral_elements_in_box(K, C): r""" Return all integral elements of the totally real field `K` whose embeddings lie *numerically* within the bounds specified by the list `C`. The output is architecture dependent, and one may want to expand the bounds that define C by some epsilon. INPUT: - `K` -- a totally real number field - `C` -- a list [[lower, upper], ...] of lower and upper bounds, for each embedding EXAMPLES:: sage: x = polygen(QQ) sage: K.<alpha> = NumberField(x^2-2) sage: eps = 10e-6 sage: C = [[0-eps,5+eps],[0-eps,10+eps]] sage: ls = sage.rings.number_field.totallyreal_rel.integral_elements_in_box(K, C) sage: sorted([ a.trace() for a in ls ]) [0, 2, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 10, 10, 10, 10, 12, 12, 14] sage: len(ls) 19 sage: v = sage.rings.number_field.totallyreal_rel.integral_elements_in_box(K, C) sage: sorted(v) [0, -alpha + 2, 1, -alpha + 3, 2, 3, alpha + 2, 4, alpha + 3, 5, alpha + 4, 2*alpha + 3, alpha + 5, 2*alpha + 4, alpha + 6, 2*alpha + 5, 2*alpha + 6, 3*alpha + 5, 2*alpha + 7] A cubic field:: sage: x = polygen(QQ) sage: K.<a> = NumberField(x^3 - 16*x +16) sage: eps = 10e-6 sage: C = [[0-eps,5+eps]]*3 sage: v = sage.rings.number_field.totallyreal_rel.integral_elements_in_box(K, C) Note that the output is platform dependent (sometimes a 5 is listed below, and sometimes it isn't):: sage: sorted(v) [-1/2*a + 2, 1/4*a^2 + 1/2*a, 0, 1, 2, 3, 4,...-1/4*a^2 - 1/2*a + 5, 1/2*a + 3, -1/4*a^2 + 5] """ d = K.degree() Z_F = K.maximal_order() Foo = K.real_embeddings() B = K.reduced_basis() import numpy import numpy.linalg L = numpy.array([ [v(b) for b in B] for v in Foo]) Linv = numpy.linalg.inv(L) Vi = [[C[0][0]],[C[0][1]]] for i in range(1,d): Vi = sum([ [v + [C[i][0]], v + [C[i][1]]] for v in Vi], []) V = numpy.matrix(Linv)*(numpy.matrix(Vi).transpose()) j = 0 while j < 2**d: for i in range(d): if V[i,j] < V[i,j+1]: V[i,j] = math.floor(V[i,j]) V[i,j+1] = math.ceil(V[i,j+1]) else: V[i,j] = math.ceil(V[i,j]) V[i,j+1] = math.floor(V[i,j+1]) j += 2 W0 = (Linv*numpy.array([Vi[0]]*d)).transpose() W = (Linv*numpy.array([Vi[2**i] for i in range(d)])).transpose() for j in range(d): for i in range(d): if W[i,j] < W0[i,j]: W[i,j] = math.floor(W[i,j]) W0[i,j] = math.ceil(W0[i,j]) else: W[i,j] = math.ceil(W[i,j]) W0[i,j] = math.floor(W0[i,j]) M = [[int(V[i,j]) for i in range(V.shape[0])] for j in range(V.shape[1])] M += [[int(W0[i,j]) for j in range(W0.shape[0])] for i in range(W0.shape[0])] M += [[int(W[i,j]) for j in range(W.shape[1])] for i in range(W.shape[0])] from sage.matrix.constructor import matrix M = (matrix(IntegerRing(),len(M),len(M[0]), M).transpose()).columns() i = 0 while i < len(M): j = i+1 while j < len(M): if M[i] == M[j]: M.pop(j) else: j += 1 i += 1 from sage.geometry.lattice_polytope import LatticePolytope P = LatticePolytope(M) S = [] try: pts = P.points() except ValueError: return [] for p in pts: theta = sum([ p.list()[i]*B[i] for i in range(d)]) inbounds = True for i in range(d): inbounds = inbounds and Foo[i](theta) >= C[i][0] and Foo[i](theta) <= C[i][1] if inbounds: S.append(theta) return S
def lattice_polytope(self, envelope=False): r""" Return an encompassing lattice polytope. INPUT: - ``envelope`` -- boolean (default: ``False``). If the polyhedron has non-integral vertices, this option decides whether to return a strictly larger lattice polytope or raise a ``ValueError``. This option has no effect if the polyhedron has already integral vertices. OUTPUT: A :class:`LatticePolytope <sage.geometry.lattice_polytope.LatticePolytopeClass>`. If the polyhedron is compact and has integral vertices, the lattice polytope equals the polyhedron. If the polyhedron is compact but has at least one non-integral vertex, a strictly larger lattice polytope is returned. If the polyhedron is not compact, a ``NotImplementedError`` is raised. If the polyhedron is not integral and ``envelope=False``, a ``ValueError`` is raised. ALGORITHM: For each non-integral vertex, a bounding box of integral points is added and the convex hull of these integral points is returned. EXAMPLES: First, a polyhedron with integral vertices:: sage: P = Polyhedron( vertices = [(1, 0), (0, 1), (-1, 0), (0, -1)]) sage: lp = P.lattice_polytope(); lp 2-d reflexive polytope #3 in 2-d lattice M sage: lp.vertices() M(-1, 0), M( 0, -1), M( 0, 1), M( 1, 0) in 2-d lattice M Here is a polyhedron with non-integral vertices:: sage: P = Polyhedron( vertices = [(1/2, 1/2), (0, 1), (-1, 0), (0, -1)]) sage: lp = P.lattice_polytope() Traceback (most recent call last): ... ValueError: Some vertices are not integral. You probably want to add the argument "envelope=True" to compute an enveloping lattice polytope. sage: lp = P.lattice_polytope(True); lp 2-d reflexive polytope #5 in 2-d lattice M sage: lp.vertices() M(-1, 0), M( 0, -1), M( 1, 1), M( 0, 1), M( 1, 0) in 2-d lattice M """ if not self.is_compact(): raise NotImplementedError('only compact lattice polytopes are allowed') try: vertices = self.vertices_matrix(ZZ).columns() except TypeError: if not envelope: raise ValueError('Some vertices are not integral. ' 'You probably want to add the argument ' '"envelope=True" to compute an enveloping lattice polytope.') from sage.arith.misc import integer_ceil as ceil from sage.arith.misc import integer_floor as floor vertices = [] for v in self.vertex_generator(): vbox = [ set([floor(x), ceil(x)]) for x in v ] vertices.extend( itertools.product(*vbox) ) # construct the (enveloping) lattice polytope from sage.geometry.lattice_polytope import LatticePolytope return LatticePolytope(vertices)