def _split_hyperbolic(L) : cur_cor = 2 Lcor = L + cur_cor * identity_matrix(L.nrows()) while not is_positive_definite(Lcor) : cur_cor += 2 Lcor = L + cur_cor * identity_matrix(L.nrows()) a = FreeModule(ZZ, L.nrows()).gen(0) if a * L * a >= 0 : Lcor_length_inc = max(3, a * L * a) cur_Lcor_length = Lcor_length_inc while True : short_vectors = flatten(QuadraticForm(Lcor).short_vector_list_up_to_length( a * Lcor * a )[cur_Lcor_length - Lcor_length_inc: cur_Lcor_length], max_level = 1) for a in short_vectors : if a * L * a < 0 : break else : continue break n = -a * L * a // 2 short_vectors = E8.short_vector_list_up_to_length(n + 1)[-1] for v in short_vectors : for w in short_vectors : if v * E8_gram * w == 2 * n - 1 : LE8_mat = L.block_sum(E8_gram) v_form = vector( list(a) + list(v) ) * LE8_mat w_form = vector( list(a) + list(w) ) * LE8_mat Lred_basis = matrix(ZZ, [v_form, w_form]).right_kernel().basis_matrix().transpose() Lred_basis = matrix(ZZ, Lred_basis) return Lred_basis.transpose() * LE8_mat * Lred_basis
def identity(self): r""" Return identity morphism in an endomorphism ring. EXAMPLE:: sage: V=FreeModule(ZZ,5) sage: H=V.Hom(V) sage: H.identity() Free module morphism defined by the matrix [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] Domain: Ambient free module of rank 5 over the principal ideal domain ... Codomain: Ambient free module of rank 5 over the principal ideal domain ... """ if self.is_endomorphism_set(): return self( matrix.identity_matrix(self.base_ring(), self.domain().rank())) else: raise TypeError( "Identity map only defined for endomorphisms. Try natural_map() instead." )
def split_off_unimodular_lattice(self, L_basis_matrix, check = True) : r""" Split off a unimodular lattice that is an orthogonal summand of self. INPUT: - ``L_basis_matrix`` -- A matrix over `\ZZ` whose number of rows equals the size of the underlying lattice. - ``check`` -- A boolean (default: ``True``). If ``True`` it will be checked whether the given sublattice is a direct summand. OUTPUT: - A pair of a discriminant group and a homomorphism from self to this group. """ if check and L_basis_matrix.base_ring() is not ZZ : raise ValueError( "L_basis_matrix must define a sublattice" ) pre_bases = matrix(ZZ, [ [ l * self._L * b for l in L_basis_matrix.columns()] for b in FreeModule(ZZ, self._L.nrows()).gens() ]) \ .augment(identity_matrix(ZZ, self._L.nrows())).echelon_form() if check and pre_bases[:L_basis_matrix.ncols(),:L_basis_matrix.ncols()] != identity_matrix(ZZ, L_basis_matrix.ncols()) : raise ValueError( "The sublattice defined by L_basis_matrix must be unimodular" ) K_basis_matrix = pre_bases[L_basis_matrix.ncols():,L_basis_matrix.ncols():].transpose() if check and L_basis_matrix.column_module() + K_basis_matrix.column_module() != FreeModule(ZZ, self._L.nrows()) : raise ValueError( "The sublattice defined by L_basis_matrix must be an orthogonal summand" ) K = K_basis_matrix.transpose() * self._L * K_basis_matrix n_disc = DiscriminantForm(K) total_basis_matrix = L_basis_matrix.change_ring(QQ).augment(K_basis_matrix * n_disc._dual_basis) basis_images = [ sum(map(operator.mul, b.lift(), self._dual_basis.columns())) for b in self.smith_form_gens() ] basis_images = [ total_basis_matrix.solve_right(b)[-K_basis_matrix.ncols():] for b in basis_images ] coercion_hom = self.hom([ sum(map(operator.mul, map(ZZ, b), map(n_disc, FreeModule(ZZ, K.nrows()).gens()) )) for b in basis_images ]) return (n_disc, coercion_hom)
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 = [ list(range(i)) + list(range(i + 1, n + 1)) for i in range(n + 1) ] return CPRFanoToricVariety(Delta_polar=LatticePolytope( m.columns(), lattice=ToricLattice(n)), charts=charts, check=self._check, coordinate_names=names, base_ring=base_ring)
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 = [list(range(i)) + list(range(i + 1, n + 1)) for i in range(n + 1)] return CPRFanoToricVariety( Delta_polar=LatticePolytope(m.columns(), lattice=ToricLattice(n)), charts=charts, check=self._check, coordinate_names=names, base_ring=base_ring)
def _split_hyperbolic(L): cur_cor = 2 Lcor = L + cur_cor * identity_matrix(L.nrows()) while not is_positive_definite(Lcor): cur_cor += 2 Lcor = L + cur_cor * identity_matrix(L.nrows()) a = FreeModule(ZZ, L.nrows()).gen(0) if a * L * a >= 0: Lcor_length_inc = max(3, a * L * a) cur_Lcor_length = Lcor_length_inc while True: short_vectors = flatten( QuadraticForm(Lcor).short_vector_list_up_to_length( a * Lcor * a)[cur_Lcor_length - Lcor_length_inc:cur_Lcor_length], max_level=1) for a in short_vectors: if a * L * a < 0: break else: continue break n = -a * L * a // 2 short_vectors = E8.short_vector_list_up_to_length(n + 1)[-1] for v in short_vectors: for w in short_vectors: if v * E8_gram * w == 2 * n - 1: LE8_mat = L.block_sum(E8_gram) v_form = vector(list(a) + list(v)) * LE8_mat w_form = vector(list(a) + list(w)) * LE8_mat Lred_basis = matrix( ZZ, [v_form, w_form ]).right_kernel().basis_matrix().transpose() Lred_basis = matrix(ZZ, Lred_basis) return Lred_basis.transpose() * LE8_mat * Lred_basis
def A(self, n, names='z+', base_ring=QQ): r""" Construct the ``n``-dimensional affine space. INPUT: - ``n`` -- positive integer. The dimension of the affine 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:`toric variety <sage.schemes.toric.variety.ToricVariety_field>`. EXAMPLES:: sage: A3 = toric_varieties.A(3) sage: A3 3-d affine toric variety sage: A3.fan().rays() N(1, 0, 0), N(0, 1, 0), N(0, 0, 1) in 3-d lattice N sage: A3.gens() (z0, z1, z2) """ # 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 affine space must be a " "positive integer!\nGot: %s" % n) if n <= 0: raise ValueError("only affine spaces of positive dimension can " "be constructed!\nGot: %s" % n) rays = identity_matrix(n).columns() cones = [list(range(n))] fan = Fan(cones, rays, check=self._check) return ToricVariety(fan, coordinate_names=names)
def A(self, n, names='z+', base_ring=QQ): r""" Construct the ``n``-dimensional affine space. INPUT: - ``n`` -- positive integer. The dimension of the affine 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:`toric variety <sage.schemes.toric.variety.ToricVariety_field>`. EXAMPLES:: sage: A3 = toric_varieties.A(3) sage: A3 3-d affine toric variety sage: A3.fan().rays() N(1, 0, 0), N(0, 1, 0), N(0, 0, 1) in 3-d lattice N sage: A3.gens() (z0, z1, z2) """ # 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 affine space must be a " "positive integer!\nGot: %s" % n) if n <= 0: raise ValueError("only affine spaces of positive dimension can " "be constructed!\nGot: %s" % n) rays = identity_matrix(n).columns() cones = [ range(0,n) ] fan = Fan(cones, rays, check=self._check) return ToricVariety(fan, coordinate_names=names)
def P(self, n, names="z+"): 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.generic.toric_variety.normalize_names` for acceptable formats. OUTPUT: A :class:`CPR-Fano toric variety <sage.schemes.generic.fano_toric_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().ray_matrix() [ 1 0 0 -1] [ 0 1 0 -1] [ 0 0 1 -1] 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 )
def identity(self): r""" Return identity morphism in an endomorphism ring. EXAMPLE:: sage: V=FreeModule(ZZ,5) sage: H=V.Hom(V) sage: H.identity() Free module morphism defined by the matrix [1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1] Domain: Ambient free module of rank 5 over the principal ideal domain ... Codomain: Ambient free module of rank 5 over the principal ideal domain ... """ if self.is_endomorphism_set(): return self(matrix.identity_matrix(self.base_ring(),self.domain().rank())) else: raise TypeError, "Identity map only defined for endomorphisms. Try natural_map() instead."
def to_matrix(self, side="right", on_space="primal"): r""" Return ``self`` as a matrix acting on the underlying vector space. - ``side`` -- optional (default: ``"right"``) whether the action of ``self`` is on the ``"left"`` or on the ``"right"`` - ``on_space`` -- optional (default: ``"primal"``) whether to act as the reflection representation on the given basis, or to act on the dual reflection representation on the dual basis EXAMPLES:: sage: W = ReflectionGroup(['A',2]) # optional - gap3 sage: for w in W: # optional - gap3 ....: w.reduced_word() # optional - gap3 ....: [w.to_matrix(), w.to_matrix(on_space="dual")] # optional - gap3 [] [ [1 0] [1 0] [0 1], [0 1] ] [2] [ [ 1 1] [ 1 0] [ 0 -1], [ 1 -1] ] [1] [ [-1 0] [-1 1] [ 1 1], [ 0 1] ] [1, 2] [ [-1 -1] [ 0 -1] [ 1 0], [ 1 -1] ] [2, 1] [ [ 0 1] [-1 1] [-1 -1], [-1 0] ] [1, 2, 1] [ [ 0 -1] [ 0 -1] [-1 0], [-1 0] ] TESTS:: sage: W = ReflectionGroup(['F',4]) # optional - gap3 sage: all(w.to_matrix(side="left") == W.from_reduced_word(reversed(w.reduced_word())).to_matrix(side="right").transpose() for w in W) # optional - gap3 True sage: all(w.to_matrix(side="right") == W.from_reduced_word(reversed(w.reduced_word())).to_matrix(side="left").transpose() for w in W) # optional - gap3 True """ W = self.parent() if W._reflection_representation is None: if side == "left": w = ~self elif side == "right": w = self else: raise ValueError('side must be "left" or "right"') Delta = W.independent_roots() Phi = W.roots() M = Matrix([Phi[w(Phi.index(alpha) + 1) - 1] for alpha in Delta]) mat = W.base_change_matrix() * M else: refl_repr = W._reflection_representation id_mat = identity_matrix(QQ, refl_repr[W.index_set()[0]].nrows()) mat = prod([refl_repr[i] for i in self.reduced_word()], id_mat) if on_space == "primal": if side == "left": mat = mat.transpose() elif on_space == "dual": if side == "left": mat = mat.inverse() else: mat = mat.inverse().transpose() else: raise ValueError('on_space must be "primal" or "dual"') mat.set_immutable() return mat
def _compute_q_expansion_basis(self, prec=None): r""" Compute q-expansion basis using Schaeffer's algorithm. EXAMPLES:: sage: CuspForms(GammaH(31, [7]), 1).q_expansion_basis() # indirect doctest [ q - q^2 - q^5 + O(q^6) ] A more elaborate example (two Galois-conjugate characters each giving a 2-dimensional space):: sage: CuspForms(GammaH(124, [85]), 1).q_expansion_basis() [ q - q^4 - q^6 + O(q^7), q^2 + O(q^7), q^3 + O(q^7), q^5 - q^6 + O(q^7) ] """ if prec is None: prec = self.prec() else: prec = Integer(prec) chars=self.group().characters_mod_H(sign=-1, galois_orbits=True) B = [] dim = 0 for c in chars: chi = c.minimize_base_ring() Bchi = [weight1.modular_ratio_to_prec(chi, f, prec) for f in weight1.hecke_stable_subspace(chi) ] if Bchi == []: continue if chi.base_ring() == QQ: B += [f.padded_list(prec) for f in Bchi] dim += len(Bchi) else: d = chi.base_ring().degree() dim += d * len(Bchi) for f in Bchi: w = f.padded_list(prec) for i in range(d): B.append([x[i] for x in w]) basis_mat = Matrix(QQ, B) if basis_mat.is_zero(): return [] # Daft thing: "transformation=True" parameter to echelonize # is ignored for rational matrices! big_mat = basis_mat.augment(identity_matrix(dim)) big_mat.echelonize() c = big_mat.pivots()[-1] echelon_basis_mat = big_mat[:, :prec] R = self._q_expansion_ring() if c >= prec: verbose("Precision %s insufficient to determine basis" % prec, level=1) else: verbose("Minimal precision for basis: %s" % (c+1), level=1) t = big_mat[:, prec:] assert echelon_basis_mat == t * basis_mat self.__transformation_matrix = t self._char_basis = [R(f.list(), c+1) for f in basis_mat.rows()] return [R(f.list(), prec) for f in echelon_basis_mat.rows() if f != 0]
def to_matrix(self, side="right", on_space="primal"): r""" Return ``self`` as a matrix acting on the underlying vector space. - ``side`` -- optional (default: ``"right"``) whether the action of ``self`` is on the ``"left"`` or on the ``"right"`` - ``on_space`` -- optional (default: ``"primal"``) whether to act as the reflection representation on the given basis, or to act on the dual reflection representation on the dual basis EXAMPLES:: sage: W = ReflectionGroup(['A',2]) # optional - gap3 sage: for w in W: # optional - gap3 ....: w.reduced_word() # optional - gap3 ....: [w.to_matrix(), w.to_matrix(on_space="dual")] # optional - gap3 [] [ [1 0] [1 0] [0 1], [0 1] ] [2] [ [ 1 1] [ 1 0] [ 0 -1], [ 1 -1] ] [1] [ [-1 0] [-1 1] [ 1 1], [ 0 1] ] [1, 2] [ [-1 -1] [ 0 -1] [ 1 0], [ 1 -1] ] [2, 1] [ [ 0 1] [-1 1] [-1 -1], [-1 0] ] [1, 2, 1] [ [ 0 -1] [ 0 -1] [-1 0], [-1 0] ] TESTS:: sage: W = ReflectionGroup(['F',4]) # optional - gap3 sage: all(w.to_matrix(side="left") == W.from_reduced_word(reversed(w.reduced_word())).to_matrix(side="right").transpose() for w in W) # optional - gap3 True sage: all(w.to_matrix(side="right") == W.from_reduced_word(reversed(w.reduced_word())).to_matrix(side="left").transpose() for w in W) # optional - gap3 True """ W = self.parent() if W._reflection_representation is None: if side == "left": w = ~self elif side == "right": w = self else: raise ValueError('side must be "left" or "right"') Delta = W.independent_roots() Phi = W.roots() M = Matrix([Phi[w(Phi.index(alpha)+1)-1] for alpha in Delta]) mat = W.base_change_matrix() * M else: refl_repr = W._reflection_representation id_mat = identity_matrix(QQ, refl_repr[W.index_set()[0]].nrows()) mat = prod([refl_repr[i] for i in self.reduced_word()], id_mat) if on_space == "primal": if side == "left": mat = mat.transpose() elif on_space == "dual": if side == "left": mat = mat.inverse() else: mat = mat.inverse().transpose() else: raise ValueError('on_space must be "primal" or "dual"') mat.set_immutable() return mat
def eigenvalue_multiplicity(mat, ev) : mat = matrix(CC, mat - ev * identity_matrix(subspace_dimension)) return len(filter( lambda row: all( e.contains_zero() for e in row), _qr(mat).rows() ))
def eigenvalue_multiplicity(mat, ev): mat = matrix(CC, mat - ev * identity_matrix(subspace_dimension)) return len( filter(lambda row: all(e.contains_zero() for e in row), _qr(mat).rows()))
def split_off_unimodular_lattice(self, L_basis_matrix, check=True): r""" Split off a unimodular lattice that is an orthogonal summand of self. INPUT: - ``L_basis_matrix`` -- A matrix over `\ZZ` whose number of rows equals the size of the underlying lattice. - ``check`` -- A boolean (default: ``True``). If ``True`` it will be checked whether the given sublattice is a direct summand. OUTPUT: - A pair of a discriminant group and a homomorphism from self to this group. """ if check and L_basis_matrix.base_ring() is not ZZ: raise ValueError("L_basis_matrix must define a sublattice") pre_bases = matrix(ZZ, [ [ l * self._L * b for l in L_basis_matrix.columns()] for b in FreeModule(ZZ, self._L.nrows()).gens() ]) \ .augment(identity_matrix(ZZ, self._L.nrows())).echelon_form() if check and pre_bases[:L_basis_matrix.ncols(), :L_basis_matrix.ncols( )] != identity_matrix(ZZ, L_basis_matrix.ncols()): raise ValueError( "The sublattice defined by L_basis_matrix must be unimodular") K_basis_matrix = pre_bases[L_basis_matrix.ncols():, L_basis_matrix.ncols():].transpose() if check and L_basis_matrix.column_module( ) + K_basis_matrix.column_module() != FreeModule(ZZ, self._L.nrows()): raise ValueError( "The sublattice defined by L_basis_matrix must be an orthogonal summand" ) K = K_basis_matrix.transpose() * self._L * K_basis_matrix n_disc = DiscriminantForm(K) total_basis_matrix = L_basis_matrix.change_ring(QQ).augment( K_basis_matrix * n_disc._dual_basis) basis_images = [ sum(map(operator.mul, b.lift(), self._dual_basis.columns())) for b in self.smith_form_gens() ] basis_images = [ total_basis_matrix.solve_right(b)[-K_basis_matrix.ncols():] for b in basis_images ] coercion_hom = self.hom([ sum( map(operator.mul, map(ZZ, b), map(n_disc, FreeModule(ZZ, K.nrows()).gens()))) for b in basis_images ]) return (n_disc, coercion_hom)