def _UG(n, R, special, var='a', invariant_form=None): r""" This function is commonly used by the functions :func:`GU` and :func:`SU` to avoid duplicated code. For documentation and examples see the individual functions. TESTS:: sage: GU(3,25).order() # indirect doctest 3961191000000 """ prefix = 'General' latex_prefix = 'G' if special: prefix = 'Special' latex_prefix = 'S' degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q**2, name=var) if invariant_form is not None: raise NotImplementedError( "invariant_form for finite groups is fixed by GAP") if invariant_form is not None: invariant_form = normalize_args_invariant_form(ring, degree, invariant_form) if not invariant_form.is_hermitian(): raise ValueError("invariant_form must be hermitian") try: if invariant_form.is_positive_definite(): inserted_text = "with respect to positive definite hermitian form" else: inserted_text = "with respect to non positive definite hermitian form" except ValueError: inserted_text = "with respect to hermitian form" name = '{0} Unitary Group of degree {1} over {2} {3}\n{4}'.format( prefix, degree, ring, inserted_text, invariant_form) ltx = r'\text{{{0}U}}_{{{1}}}({2})\text{{ {3} }}{4}'.format( latex_prefix, degree, latex(ring), inserted_text, latex(invariant_form)) else: name = '{0} Unitary Group of degree {1} over {2}'.format( prefix, degree, ring) ltx = r'\text{{{0}U}}_{{{1}}}({2})'.format(latex_prefix, degree, latex(ring)) if is_FiniteField(ring): cmd = '{0}U({1}, {2})'.format(latex_prefix, degree, q) return UnitaryMatrixGroup_gap(degree, ring, special, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, special, name, ltx, invariant_form=invariant_form)
def _OG(n, R, special, e=0, var='a', invariant_form=None): r""" This function is commonly used by the functions GO and SO to avoid uneccessarily duplicated code. For documentation and examples see the individual functions. TESTS: Check that :trac:`26028` is fixed:: sage: GO(3,25).order() # indirect doctest 31200 """ prefix = 'General' ltx_prefix ='G' if special: prefix = 'Special' ltx_prefix ='S' degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: if invariant_form is not None: if is_FiniteField(ring): raise NotImplementedError("invariant_form for finite groups is fixed by GAP") invariant_form = normalize_args_invariant_form(ring, degree, invariant_form) if not invariant_form.is_symmetric(): raise ValueError("invariant_form must be symmetric") try: if invariant_form.is_positive_definite(): inserted_text = "with respect to positive definite symmetric form" else: inserted_text = "with respect to non positive definite symmetric form" except ValueError: inserted_text = "with respect to symmetric form" name = '{0} Orthogonal Group of degree {1} over {2} {3}\n{4}'.format( prefix, degree, ring, inserted_text,invariant_form) ltx = r'\text{{{0}O}}_{{{1}}}({2})\text{{ {3} }}{4}'.format( ltx_prefix, degree, latex(ring), inserted_text, latex(invariant_form)) else: name = '{0} Orthogonal Group of degree {1} over {2}'.format(prefix, degree, ring) ltx = r'\text{{{0}O}}_{{{1}}}({2})'.format(ltx_prefix, degree, latex(ring)) else: name = '{0} Orthogonal Group of degree {1} and form parameter {2} over {3}'.format(prefix, degree, e, ring) ltx = r'\text{{{0}O}}_{{{1}}}({2}, {3})'.format(ltx_prefix, degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = '{0}O({1}, {2}, {3})'.format(ltx_prefix, e, degree, ring.order()) return OrthogonalMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, False, name, ltx, invariant_form=invariant_form)
def SU(n, R, var='a'): """ The special unitary group `SU( d, R )` consists of all `d \times d` matrices that preserve a nondegenerate sequilinear form over the ring `R` and have determinant one. .. note:: For a finite field the matrices that preserve a sesquilinear form over `F_q` live over `F_{q^2}`. So ``SU(n,q)`` for integer ``q`` constructs the matrix group over the base ring ``GF(q^2)``. .. note:: This group is also available via ``groups.matrix.SU()``. INPUT: - ``n`` -- a positive integer. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``var`` -- variable used to represent generator of the finite field, if needed. OUTPUT: Return the special unitary group. EXAMPLES:: sage: SU(3,5) Special Unitary Group of degree 3 over Finite Field in a of size 5^2 sage: SU(3, GF(5)) Special Unitary Group of degree 3 over Finite Field in a of size 5^2 sage: SU(3,QQ) Special Unitary Group of degree 3 over Rational Field TESTS:: sage: groups.matrix.SU(2, 3) Special Unitary Group of degree 2 over Finite Field in a of size 3^2 """ degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q ** 2, name=var) name = 'Special Unitary Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{SU}}_{{{0}}}({1})'.format(degree, latex(ring)) if is_FiniteField(ring): cmd = 'SU({0}, {1})'.format(degree, q) return UnitaryMatrixGroup_gap(degree, ring, True, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, True, name, ltx)
def SU(n, R, var='a'): """ The special unitary group `SU( d, R )` consists of all `d \times d` matrices that preserve a nondegenerate sesquilinear form over the ring `R` and have determinant one. .. note:: For a finite field the matrices that preserve a sesquilinear form over `F_q` live over `F_{q^2}`. So ``SU(n,q)`` for integer ``q`` constructs the matrix group over the base ring ``GF(q^2)``. .. note:: This group is also available via ``groups.matrix.SU()``. INPUT: - ``n`` -- a positive integer. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``var`` -- variable used to represent generator of the finite field, if needed. OUTPUT: Return the special unitary group. EXAMPLES:: sage: SU(3,5) Special Unitary Group of degree 3 over Finite Field in a of size 5^2 sage: SU(3, GF(5)) Special Unitary Group of degree 3 over Finite Field in a of size 5^2 sage: SU(3,QQ) Special Unitary Group of degree 3 over Rational Field TESTS:: sage: groups.matrix.SU(2, 3) Special Unitary Group of degree 2 over Finite Field in a of size 3^2 """ degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q**2, name=var) name = 'Special Unitary Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{SU}}_{{{0}}}({1})'.format(degree, latex(ring)) if is_FiniteField(ring): cmd = 'SU({0}, {1})'.format(degree, q) return UnitaryMatrixGroup_gap(degree, ring, True, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, True, name, ltx)
def _UG(n, R, special, var='a', invariant_form=None): r""" This function is commonly used by the functions :func:`GU` and :func:`SU` to avoid duplicated code. For documentation and examples see the individual functions. TESTS:: sage: GU(3,25).order() # indirect doctest 3961191000000 """ prefix = 'General' latex_prefix ='G' if special: prefix = 'Special' latex_prefix ='S' degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q**2, name=var) if invariant_form is not None: raise NotImplementedError("invariant_form for finite groups is fixed by GAP") if invariant_form is not None: invariant_form = normalize_args_invariant_form(ring, degree, invariant_form) if not invariant_form.is_hermitian(): raise ValueError("invariant_form must be hermitian") try: if invariant_form.is_positive_definite(): inserted_text = "with respect to positive definite hermitian form" else: inserted_text = "with respect to non positive definite hermitian form" except ValueError: inserted_text = "with respect to hermitian form" name = '{0} Unitary Group of degree {1} over {2} {3}\n{4}'.format(prefix, degree, ring, inserted_text, invariant_form) ltx = r'\text{{{0}U}}_{{{1}}}({2})\text{{ {3} }}{4}'.format(latex_prefix, degree, latex(ring), inserted_text, latex(invariant_form)) else: name = '{0} Unitary Group of degree {1} over {2}'.format(prefix, degree, ring) ltx = r'\text{{{0}U}}_{{{1}}}({2})'.format(latex_prefix, degree, latex(ring)) if is_FiniteField(ring): cmd = '{0}U({1}, {2})'.format(latex_prefix, degree, q) return UnitaryMatrixGroup_gap(degree, ring, special, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, special, name, ltx, invariant_form=invariant_form)
def _coerce_map_from_(self, R): """ Returns True if this finite field has a coercion map from R. EXAMPLES:: sage: k.<a> = GF(3^8) sage: a + 1 # indirect doctest a + 1 sage: a + int(1) a + 1 sage: a + GF(3)(1) a + 1 """ from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.finite_field_base import is_FiniteField from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic if R is int or R is long or R is ZZ: return True if is_FiniteField(R): if R is self: return True from sage.rings.residue_field import ResidueField_generic if isinstance(R, ResidueField_generic): return False if R.characteristic() == self.characteristic(): if isinstance(R, IntegerModRing_generic): return True if R.degree() == 1: return True elif self.degree() % R.degree() == 0: # This is where we *would* do coercion from one nontrivial finite field to another... # We use this error message for backward compatibility until #8335 is finished raise TypeError, "unable to coerce from a finite field other than the prime subfield"
def _coerce_map_from_(self, R): """ Returns ``True`` if this finite field has a coercion map from ``R``. EXAMPLES:: sage: k.<a> = GF(3^8) sage: a + 1 # indirect doctest a + 1 sage: a + int(1) a + 1 sage: a + GF(3)(1) a + 1 """ from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.finite_field_base import is_FiniteField from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic if R is int or R is long or R is ZZ: return True if is_FiniteField(R): if R is self: return True from sage.rings.residue_field import ResidueField_generic if isinstance(R, ResidueField_generic): return False if R.characteristic() == self.characteristic(): if isinstance(R, IntegerModRing_generic): return True if R.degree() == 1: return True elif self.degree() % R.degree() == 0: # This is where we *would* do coercion from one nontrivial finite field to another... # We use this error message for backward compatibility until #8335 is finished raise TypeError, "unable to coerce from a finite field other than the prime subfield"
def can_convert_to_singular(R): """ Returns True if this ring's base field or ring can be represented in Singular, and the polynomial ring has at least one generator. If this is True then this polynomial ring can be represented in Singular. The following base rings are supported: finite fields, rationals, number fields, and real and complex fields. EXAMPLES:: sage: from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular sage: can_convert_to_singular(PolynomialRing(QQ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(ZZ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(QQ, names=[])) False TESTS: Avoid non absolute number fields (see :trac:`23535`):: sage: K.<a,b> = NumberField([x^2-2,x^2-5]) sage: can_convert_to_singular(K['s,t']) False """ if R.ngens() == 0: return False base_ring = R.base_ring() if (base_ring is ZZ or sage.rings.finite_rings.finite_field_constructor.is_FiniteField( base_ring) or is_RationalField(base_ring) or isinstance( base_ring, (sage.rings.abc.IntegerModRing, sage.rings.abc.RealField, sage.rings.abc.ComplexField, sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField))): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 elif number_field.number_field_base.is_NumberField(base_ring): return base_ring.is_absolute() elif sage.rings.fraction_field.is_FractionField(base_ring): B = base_ring.base_ring() return B.is_prime_field() or B is ZZ or is_FiniteField(B) elif isinstance(base_ring, RationalFunctionField): return base_ring.constant_field().is_prime_field() else: return False
def can_convert_to_singular(R): """ Returns True if this ring's base field or ring can be represented in Singular, and the polynomial ring has at least one generator. If this is True then this polynomial ring can be represented in Singular. The following base rings are supported: finite fields, rationals, number fields, and real and complex fields. EXAMPLES:: sage: from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular sage: can_convert_to_singular(PolynomialRing(QQ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(QQ, names=[])) False TESTS: Avoid non absolute number fields (see :trac:`23535`):: sage: K.<a,b> = NumberField([x^2-2,x^2-5]) sage: can_convert_to_singular(K['s,t']) False """ if R.ngens() == 0: return False; base_ring = R.base_ring() if (base_ring is ZZ or sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) or is_IntegerModRing(base_ring) or is_RealField(base_ring) or is_ComplexField(base_ring) or is_RealDoubleField(base_ring) or is_ComplexDoubleField(base_ring)): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 elif number_field.number_field_base.is_NumberField(base_ring): return base_ring.is_absolute() elif sage.rings.fraction_field.is_FractionField(base_ring): B = base_ring.base_ring() return B.is_prime_field() or B is ZZ or is_FiniteField(B) elif is_RationalFunctionField(base_ring): return base_ring.constant_field().is_prime_field() else: return False
def _coerce_map_from_(self, other): """ Return ``True`` if elements of ``other`` can be coerced into ``self``. EXAMPLES:: sage: F = GF(7).algebraic_closure() sage: F.has_coerce_map_from(Integers()) True """ if other is self: return True elif is_FiniteField(other) and self._subfield(other.degree()) is other: return True elif self._subfield(1).has_coerce_map_from(other): return True
def normalize_args_e(degree, ring, e): """ Normalize the arguments that relate the choice of quadratic form for special orthogonal groups over finite fields. INPUT: - ``degree`` -- integer. The degree of the affine group, that is, the dimension of the affine space the group is acting on. - ``ring`` -- a ring. The base ring of the affine space. - ``e`` -- integer, one of `+1`, `0`, `-1`. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The integer ``e`` with values required by GAP. TESTS:: sage: from sage.groups.matrix_gps.orthogonal import normalize_args_e sage: normalize_args_e(2, GF(3), +1) 1 sage: normalize_args_e(3, GF(3), 0) 0 sage: normalize_args_e(3, GF(3), +1) 0 sage: normalize_args_e(2, GF(3), 0) Traceback (most recent call last): ... ValueError: must have e=-1 or e=1 for even degree """ if is_FiniteField(ring) and degree%2 == 0: if e not in (-1, +1): raise ValueError('must have e=-1 or e=1 for even degree') else: e = 0 return ZZ(e)
def normalize_args_e(degree, ring, e): """ Normalize the arguments that relate the choice of quadratic form for special orthogonal groups over finite fields. INPUT: - ``degree`` -- integer. The degree of the affine group, that is, the dimension of the affine space the group is acting on. - ``ring`` -- a ring. The base ring of the affine space. - ``e`` -- integer, one of `+1`, `0`, `-1`. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The integer ``e`` with values required by GAP. TESTS:: sage: from sage.groups.matrix_gps.orthogonal import normalize_args_e sage: normalize_args_e(2, GF(3), +1) 1 sage: normalize_args_e(3, GF(3), 0) 0 sage: normalize_args_e(3, GF(3), +1) 0 sage: normalize_args_e(2, GF(3), 0) Traceback (most recent call last): ... ValueError: must have e=-1 or e=1 for even degree """ if is_FiniteField(ring) and degree % 2 == 0: if e not in (-1, +1): raise ValueError('must have e=-1 or e=1 for even degree') else: e = 0 return ZZ(e)
def can_convert_to_singular(R): """ Returns True if this ring's base field or ring can be represented in Singular, and the polynomial ring has at least one generator. If this is True then this polynomial ring can be represented in Singular. The following base rings are supported: finite fields, rationals, number fields, and real and complex fields. EXAMPLES:: sage: from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular sage: can_convert_to_singular(PolynomialRing(QQ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(QQ, names=[])) False """ if R.ngens() == 0: return False base_ring = R.base_ring() return ( sage.rings.finite_rings.constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) or (base_ring.is_prime_field() and base_ring.characteristic() <= 2147483647) or is_RealField(base_ring) or is_ComplexField(base_ring) or is_RealDoubleField(base_ring) or is_ComplexDoubleField(base_ring) or number_field.number_field_base.is_NumberField(base_ring) or (sage.rings.fraction_field.is_FractionField(base_ring) and (base_ring.base_ring().is_prime_field() or base_ring.base_ring() is ZZ or is_FiniteField(base_ring.base_ring()))) or base_ring is ZZ or is_IntegerModRing(base_ring) or (is_RationalFunctionField(base_ring) and base_ring.constant_field().is_prime_field()))
def finite_field_sqrt(ring): """ Helper function. INPUT: A ring. OUTPUT: Integer q such that ``ring`` is the finite field with `q^2` elements. EXAMPLES:: sage: from sage.groups.matrix_gps.unitary import finite_field_sqrt sage: finite_field_sqrt(GF(4, 'a')) 2 """ if not is_FiniteField(ring): raise ValueError('not a finite field') q, rem = ring.cardinality().sqrtrem() if rem: raise ValueError('cardinality not a square') return q
def __init__(self, base_ring, name, category=None, lattice=None, use_database=True): """ INPUT: - ``base_ring`` -- the finite field of which to construct an algebraic closure. Currently only prime fields are accepted. - ``name`` -- prefix to use for generators of the finite subfields. - ``category`` -- if provided, specifies the category in which this algebraic closure will be placed. - ``lattice`` -- :class:`~sage.rings.finite_rings.conway_polynomials.PseudoConwayPolynomialLattice` (default: None). If provided, use this pseudo-Conway polynonomial lattice to construct an algebraic closure. - ``use_database`` -- boolean. If True (default), use actual Conway polynomials whenever they are available in the database. If False, always compute pseudo-Conway polynomials from scratch. TESTS:: sage: F = GF(5).algebraic_closure(implementation='pseudo_conway') sage: print F.__class__.__name__ AlgebraicClosureFiniteField_pseudo_conway_with_category sage: TestSuite(F).run(skip=['_test_elements', '_test_pickling']) sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice sage: L = PseudoConwayLattice(11, use_database=False) sage: F = GF(7).algebraic_closure(lattice=L) Traceback (most recent call last): ... TypeError: lattice must be a pseudo-Conway lattice with characteristic 7 sage: F = GF(11).algebraic_closure(lattice=L) sage: F.gen(2).minimal_polynomial() x^2 + 4*x + 2 sage: F = GF(11).algebraic_closure(use_database=True) sage: F.gen(2).minimal_polynomial() x^2 + 7*x + 2 .. NOTE:: In the test suite, ``_test_pickling`` has to be skipped because ``F`` and ``loads(dumps(F))`` cannot consistently be made to compare equal, and ``_test_elements`` has to be skipped for the reason described in :meth:`AlgebraicClosureFiniteFieldElement.__init__`. """ if not (is_FiniteField(base_ring) and base_ring.is_prime_field()): raise NotImplementedError('algebraic closures of finite fields are only implemented for prime fields') from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice p = base_ring.characteristic() if lattice is None: lattice = PseudoConwayLattice(p, use_database) elif not isinstance(lattice, PseudoConwayLattice) or lattice.p != p: raise TypeError('lattice must be a pseudo-Conway lattice with characteristic %s' % p) self._pseudo_conway_lattice = lattice AlgebraicClosureFiniteField_generic.__init__(self, base_ring, name, category)
def GU(n, R, var='a'): r""" Return the general unitary group. The general unitary group `GU( d, R )` consists of all `d \times d` matrices that preserve a nondegenerate sequilinear form over the ring `R`. .. note:: For a finite field the matrices that preserve a sesquilinear form over `F_q` live over `F_{q^2}`. So ``GU(n,q)`` for integer ``q`` constructs the matrix group over the base ring ``GF(q^2)``. .. note:: This group is also available via ``groups.matrix.GU()``. INPUT: - ``n`` -- a positive integer. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``var`` -- variable used to represent generator of the finite field, if needed. OUTPUT: Return the general unitary group. EXAMPLES:: sage: G = GU(3, 7); G General Unitary Group of degree 3 over Finite Field in a of size 7^2 sage: G.gens() ( [ a 0 0] [6*a 6 1] [ 0 1 0] [ 6 6 0] [ 0 0 5*a], [ 1 0 0] ) sage: GU(2,QQ) General Unitary Group of degree 2 over Rational Field sage: G = GU(3, 5, var='beta') sage: G.base_ring() Finite Field in beta of size 5^2 sage: G.gens() ( [ beta 0 0] [4*beta 4 1] [ 0 1 0] [ 4 4 0] [ 0 0 3*beta], [ 1 0 0] ) TESTS:: sage: groups.matrix.GU(2, 3) General Unitary Group of degree 2 over Finite Field in a of size 3^2 """ degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q ** 2, name=var) name = 'General Unitary Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{GU}}_{{{0}}}({1})'.format(degree, latex(ring)) if is_FiniteField(ring): cmd = 'GU({0}, {1})'.format(degree, q) return UnitaryMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, False, name, ltx)
def _singular_init_(self, singular=singular): """ Return a newly created Singular ring matching this ring. EXAMPLES:: sage: PolynomialRing(QQ,'u_ba')._singular_init_() // characteristic : 0 // number of vars : 1 // block 1 : ordering lp // : names u_ba // block 2 : ordering C """ if not can_convert_to_singular(self): raise TypeError("no conversion of this ring to a Singular ring defined") if self.ngens()==1: _vars = '(%s)'%self.gen() if "*" in _vars: # 1.000...000*x _vars = _vars.split("*")[1] order = 'lp' else: _vars = str(self.gens()) order = self.term_order().singular_str() base_ring = self.base_ring() if is_RealField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order, check=False) elif is_ComplexField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order, check=False) elif is_RealDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(real,15,0)", _vars, order=order, check=False) elif is_ComplexDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(complex,15,0,I)", _vars, order=order, check=False) elif base_ring.is_prime_field(): self.__singular = singular.ring(self.characteristic(), _vars, order=order, check=False) elif sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring): # not the prime field! gen = str(base_ring.gen()) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (str(base_ring.modulus()).replace("x",gen)).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif number_field.number_field_base.is_NumberField(base_ring) and base_ring.is_absolute(): # not the rationals! gen = str(base_ring.gen()) poly=base_ring.polynomial() poly_gen=str(poly.parent().gen()) poly_str=str(poly).replace(poly_gen,gen) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (poly_str).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif sage.rings.fraction_field.is_FractionField(base_ring) and (base_ring.base_ring() is ZZ or base_ring.base_ring().is_prime_field() or is_FiniteField(base_ring.base_ring())): if base_ring.ngens()==1: gens = str(base_ring.gen()) else: gens = str(base_ring.gens()) if not (not base_ring.base_ring().is_prime_field() and is_FiniteField(base_ring.base_ring())) : self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) else: ext_gen = str(base_ring.base_ring().gen()) _vars = '(' + ext_gen + ', ' + _vars[1:]; R = self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) self.base_ring().__minpoly = (str(base_ring.base_ring().modulus()).replace("x",ext_gen)).replace(" ","") singular.eval('setring '+R._name); self.__singular = singular("std(ideal(%s))"%(self.base_ring().__minpoly),type='qring') elif sage.rings.function_field.function_field.is_RationalFunctionField(base_ring) and base_ring.constant_field().is_prime_field(): gen = str(base_ring.gen()) self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gen), _vars, order=order, check=False) elif is_IntegerModRing(base_ring): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 self.__singular = singular.ring("(integer,2,%d)"%(exp,), _vars, order=order, check=False) else: self.__singular = singular.ring("(integer,%d)"%(ch,), _vars, order=order, check=False) elif base_ring is ZZ: self.__singular = singular.ring("(integer)", _vars, order=order, check=False) else: raise TypeError("no conversion to a Singular ring defined") return self.__singular
def Sp(n, R, var='a', invariant_form=None): r""" Return the symplectic group. The special linear group `GL( d, R )` consists of all `d \times d` matrices that are invertible over the ring `R` with determinant one. .. NOTE:: This group is also available via ``groups.matrix.Sp()``. INPUT: - ``n`` -- a positive integer - ``R`` -- ring or an integer; if an integer is specified, the corresponding finite field is used - ``var`` -- (optional, default: ``'a'``) variable used to represent generator of the finite field, if needed - ``invariant_form`` -- (optional) instances being accepted by the matrix-constructor which define a `n \times n` square matrix over ``R`` describing the alternating form to be kept invariant by the symplectic group EXAMPLES:: sage: Sp(4, 5) Symplectic Group of degree 4 over Finite Field of size 5 sage: Sp(4, IntegerModRing(15)) Symplectic Group of degree 4 over Ring of integers modulo 15 sage: Sp(3, GF(7)) Traceback (most recent call last): ... ValueError: the degree must be even Using the ``invariant_form`` option:: sage: m = matrix(QQ, 4,4, [[0, 0, 1, 0], [0, 0, 0, 2], [-1, 0, 0, 0], [0, -2, 0, 0]]) sage: Sp4m = Sp(4, QQ, invariant_form=m) sage: Sp4 = Sp(4, QQ) sage: Sp4 == Sp4m False sage: Sp4.invariant_form() [ 0 0 0 1] [ 0 0 1 0] [ 0 -1 0 0] [-1 0 0 0] sage: Sp4m.invariant_form() [ 0 0 1 0] [ 0 0 0 2] [-1 0 0 0] [ 0 -2 0 0] sage: pm = Permutation([2,1,4,3]).to_matrix() sage: g = Sp4(pm); g in Sp4; g True [0 1 0 0] [1 0 0 0] [0 0 0 1] [0 0 1 0] sage: Sp4m(pm) Traceback (most recent call last): ... TypeError: matrix must be symplectic with respect to the alternating form [ 0 0 1 0] [ 0 0 0 2] [-1 0 0 0] [ 0 -2 0 0] sage: Sp(4,3, invariant_form=[[0,0,0,1],[0,0,1,0],[0,2,0,0], [2,0,0,0]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP TESTS:: sage: TestSuite(Sp4).run() sage: TestSuite(Sp4m).run() sage: groups.matrix.Sp(2, 3) Symplectic Group of degree 2 over Finite Field of size 3 sage: G = Sp(4,5) sage: TestSuite(G).run() """ degree, ring = normalize_args_vectorspace(n, R, var=var) if degree % 2 != 0: raise ValueError('the degree must be even') if invariant_form is not None: if is_FiniteField(ring): raise NotImplementedError( "invariant_form for finite groups is fixed by GAP") invariant_form = normalize_args_invariant_form(ring, degree, invariant_form) if not invariant_form.is_alternating(): raise ValueError("invariant_form must be alternating") name = 'Symplectic Group of degree {0} over {1} with respect to alternating bilinear form\n{2}'.format( degree, ring, invariant_form) ltx = r'\text{{Sp}}_{{{0}}}({1})\text{{ with respect to alternating bilinear form}}{2}'.format( degree, latex(ring), latex(invariant_form)) else: name = 'Symplectic Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{Sp}}_{{{0}}}({1})'.format(degree, latex(ring)) try: cmd = 'Sp({0}, {1})'.format(degree, ring._gap_init_()) return SymplecticMatrixGroup_gap(degree, ring, True, name, ltx, cmd) except ValueError: return SymplecticMatrixGroup_generic(degree, ring, True, name, ltx, invariant_form=invariant_form)
def __init__(self, base_ring, name, category=None, lattice=None, use_database=True): """ INPUT: - ``base_ring`` -- the finite field of which to construct an algebraic closure. Currently only prime fields are accepted. - ``name`` -- prefix to use for generators of the finite subfields. - ``category`` -- if provided, specifies the category in which this algebraic closure will be placed. - ``lattice`` -- :class:`~sage.rings.finite_rings.conway_polynomials.PseudoConwayPolynomialLattice` (default: None). If provided, use this pseudo-Conway polynomial lattice to construct an algebraic closure. - ``use_database`` -- boolean. If True (default), use actual Conway polynomials whenever they are available in the database. If False, always compute pseudo-Conway polynomials from scratch. TESTS:: sage: F = GF(5).algebraic_closure(implementation='pseudo_conway') sage: print(F.__class__.__name__) AlgebraicClosureFiniteField_pseudo_conway_with_category sage: TestSuite(F).run(skip=['_test_elements', '_test_pickling']) sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice sage: L = PseudoConwayLattice(11, use_database=False) sage: F = GF(7).algebraic_closure(lattice=L) Traceback (most recent call last): ... TypeError: lattice must be a pseudo-Conway lattice with characteristic 7 sage: F = GF(11).algebraic_closure(lattice=L) sage: F.gen(2).minimal_polynomial() x^2 + 4*x + 2 sage: F = GF(11).algebraic_closure(use_database=True) sage: F.gen(2).minimal_polynomial() x^2 + 7*x + 2 .. NOTE:: In the test suite, ``_test_pickling`` has to be skipped because ``F`` and ``loads(dumps(F))`` cannot consistently be made to compare equal, and ``_test_elements`` has to be skipped for the reason described in :meth:`AlgebraicClosureFiniteFieldElement.__init__`. """ if not (is_FiniteField(base_ring) and base_ring.is_prime_field()): raise NotImplementedError( 'algebraic closures of finite fields are only implemented for prime fields' ) from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice p = base_ring.characteristic() if lattice is None: lattice = PseudoConwayLattice(p, use_database) elif not isinstance(lattice, PseudoConwayLattice) or lattice.p != p: raise TypeError( 'lattice must be a pseudo-Conway lattice with characteristic %s' % p) self._pseudo_conway_lattice = lattice AlgebraicClosureFiniteField_generic.__init__(self, base_ring, name, category)
def GO(n, R, e=0, var='a'): """ Return the general orthogonal group. The general orthogonal group `GO(n,R)` consists of all `n \times n` matrices over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are multiple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. In the case of a finite field and if the degree `n` is even, then there are two inequivalent quadratic forms and a third parameter ``e`` must be specified to disambiguate these two possibilities. .. note:: This group is also available via ``groups.matrix.GO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The general orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES:: sage: GO( 3, GF(7)) General Orthogonal Group of degree 3 over Finite Field of size 7 sage: GO( 3, GF(7)).order() 672 sage: GO( 3, GF(7)).gens() ( [3 0 0] [0 1 0] [0 5 0] [1 6 6] [0 0 1], [0 2 1] ) TESTS:: sage: groups.matrix.GO(2, 3, e=-1) General Orthogonal Group of degree 2 and form parameter -1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'General Orthogonal Group of degree {0} over {1}'.format( degree, ring) ltx = r'\text{{GO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'General Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{GO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'GO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, False, name, ltx)
def SO(n, R, e=None, var='a'): """ Return the special orthogonal group. The special orthogonal group `GO(n,R)` consists of all `n \times n` matrices with determinant one over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are multiple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. .. note:: This group is also available via ``groups.matrix.SO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The special orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES:: sage: G = SO(3,GF(5)) sage: G Special Orthogonal Group of degree 3 over Finite Field of size 5 sage: G = SO(3,GF(5)) sage: G.gens() ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) sage: G = SO(3,GF(5)) sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) TESTS:: sage: groups.matrix.SO(2, 3, e=1) Special Orthogonal Group of degree 2 and form parameter 1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'Special Orthogonal Group of degree {0} over {1}'.format( degree, ring) ltx = r'\text{{SO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'Special Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{SO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'SO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, True, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, True, name, ltx)
def SO(n, R, e=None, var='a'): """ Return the special orthogonal group. The special orthogonal group `GO(n,R)` consists of all `n\times n` matrices with determint one over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are muliple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. .. note:: This group is also available via ``groups.matrix.SO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The special orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES:: sage: G = SO(3,GF(5)) sage: G Special Orthogonal Group of degree 3 over Finite Field of size 5 sage: G = SO(3,GF(5)) sage: G.gens() ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) sage: G = SO(3,GF(5)) sage: G.as_matrix_group() Matrix group over Finite Field of size 5 with 3 generators ( [2 0 0] [3 2 3] [1 4 4] [0 3 0] [0 2 0] [4 0 0] [0 0 1], [0 3 1], [2 0 4] ) TESTS:: sage: groups.matrix.SO(2, 3, e=1) Special Orthogonal Group of degree 2 and form parameter 1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'Special Orthogonal Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{SO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'Special Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{SO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'SO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, True, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, True, name, ltx)
def __call__(self, im_gens, base_map=None, check=True): """ Construct the homomorphism defined by ``im_gens``. EXAMPLES:: sage: R.<t> = ZZ[] sage: E.<a> = GF(25, modulus = t^2 - 2) sage: F.<b> = GF(625) sage: End(E) Automorphism group of Finite Field in a of size 5^2 sage: list(Hom(E, F)) [Ring morphism: From: Finite Field in a of size 5^2 To: Finite Field in b of size 5^4 Defn: a |--> 4*b^3 + 4*b^2 + 4*b, Ring morphism: From: Finite Field in a of size 5^2 To: Finite Field in b of size 5^4 Defn: a |--> b^3 + b^2 + b] sage: [phi(2*a)^2 for phi in Hom(E, F)] [3, 3] sage: End(GF(7))[0] Ring endomorphism of Finite Field of size 7 Defn: 1 |--> 1 sage: H = Hom(GF(7), GF(49, 'c')) sage: H[0](2) 2 sage: Hom(GF(49, 'c'), GF(7)).list() [] sage: Hom(GF(49, 'c'), GF(81, 'd')).list() [] sage: H = Hom(GF(9, 'a'), GF(81, 'b')) sage: H == loads(dumps(H)) True """ if isinstance(im_gens, FiniteFieldHomomorphism_generic): if base_map is not None: raise ValueError( "Cannot specify base map when providing morphism") return self._coerce_impl(im_gens) try: if self.domain().degree() == 1: from sage.rings.finite_rings.hom_prime_finite_field import FiniteFieldHomomorphism_prime return FiniteFieldHomomorphism_prime(self, im_gens, base_map=base_map, check=check) if is_FiniteField(self.codomain()): return FiniteFieldHomomorphism_generic(self, im_gens, base_map=base_map, check=check) # Currently, FiniteFieldHomomorphism_generic does not work if # the codomain is not derived from the finite field base class; # in that case, we have to fall back to the generic # implementation for rings else: return RingHomomorphism_im_gens(self, im_gens, base_map=base_map, check=check) except (NotImplementedError, ValueError): try: return self._coerce_impl(im_gens) except TypeError: raise TypeError("images do not define a valid homomorphism")
def GO(n, R, e=0, var='a'): """ Return the general orthogonal group. The general orthogonal group `GO(n,R)` consists of all `n\times n` matrices over the ring `R` preserving an `n`-ary positive definite quadratic form. In cases where there are muliple non-isomorphic quadratic forms, additional data needs to be specified to disambiguate. In the case of a finite field and if the degree `n` is even, then there are two inequivalent quadratic forms and a third parameter ``e`` must be specified to disambiguate these two possibilities. .. note:: This group is also available via ``groups.matrix.GO()``. INPUT: - ``n`` -- integer. The degree. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``e`` -- ``+1`` or ``-1``, and ignored by default. Only relevant for finite fields and if the degree is even. A parameter that distinguishes inequivalent invariant forms. OUTPUT: The general orthogonal group of given degree, base ring, and choice of invariant form. EXAMPLES: sage: GO( 3, GF(7)) General Orthogonal Group of degree 3 over Finite Field of size 7 sage: GO( 3, GF(7)).order() 672 sage: GO( 3, GF(7)).gens() ( [3 0 0] [0 1 0] [0 5 0] [1 6 6] [0 0 1], [0 2 1] ) TESTS:: sage: groups.matrix.GO(2, 3, e=-1) General Orthogonal Group of degree 2 and form parameter -1 over Finite Field of size 3 """ degree, ring = normalize_args_vectorspace(n, R, var=var) e = normalize_args_e(degree, ring, e) if e == 0: name = 'General Orthogonal Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{GO}}_{{{0}}}({1})'.format(degree, latex(ring)) else: name = 'General Orthogonal Group of degree' + \ ' {0} and form parameter {1} over {2}'.format(degree, e, ring) ltx = r'\text{{GO}}_{{{0}}}({1}, {2})'.format(degree, latex(ring), '+' if e == 1 else '-') if is_FiniteField(ring): cmd = 'GO({0}, {1}, {2})'.format(e, degree, ring.characteristic()) return OrthogonalMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return OrthogonalMatrixGroup_generic(degree, ring, False, name, ltx)
def Sp(n, R, var='a', invariant_form=None): r""" Return the symplectic group. The special linear group `GL( d, R )` consists of all `d \times d` matrices that are invertible over the ring `R` with determinant one. .. NOTE:: This group is also available via ``groups.matrix.Sp()``. INPUT: - ``n`` -- a positive integer - ``R`` -- ring or an integer; if an integer is specified, the corresponding finite field is used - ``var`` -- (optional, default: ``'a'``) variable used to represent generator of the finite field, if needed - ``invariant_form`` -- (optional) instances being accepted by the matrix-constructor which define a `n \times n` square matrix over ``R`` describing the alternating form to be kept invariant by the symplectic group EXAMPLES:: sage: Sp(4, 5) Symplectic Group of degree 4 over Finite Field of size 5 sage: Sp(4, IntegerModRing(15)) Symplectic Group of degree 4 over Ring of integers modulo 15 sage: Sp(3, GF(7)) Traceback (most recent call last): ... ValueError: the degree must be even Using the ``invariant_form`` option:: sage: m = matrix(QQ, 4,4, [[0, 0, 1, 0], [0, 0, 0, 2], [-1, 0, 0, 0], [0, -2, 0, 0]]) sage: Sp4m = Sp(4, QQ, invariant_form=m) sage: Sp4 = Sp(4, QQ) sage: Sp4 == Sp4m False sage: Sp4.invariant_form() [ 0 0 0 1] [ 0 0 1 0] [ 0 -1 0 0] [-1 0 0 0] sage: Sp4m.invariant_form() [ 0 0 1 0] [ 0 0 0 2] [-1 0 0 0] [ 0 -2 0 0] sage: pm = Permutation([2,1,4,3]).to_matrix() sage: g = Sp4(pm); g in Sp4; g True [0 1 0 0] [1 0 0 0] [0 0 0 1] [0 0 1 0] sage: Sp4m(pm) Traceback (most recent call last): ... TypeError: matrix must be symplectic with respect to the alternating form [ 0 0 1 0] [ 0 0 0 2] [-1 0 0 0] [ 0 -2 0 0] sage: Sp(4,3, invariant_form=[[0,0,0,1],[0,0,1,0],[0,2,0,0], [2,0,0,0]]) Traceback (most recent call last): ... NotImplementedError: invariant_form for finite groups is fixed by GAP TESTS:: sage: TestSuite(Sp4).run() sage: TestSuite(Sp4m).run() sage: groups.matrix.Sp(2, 3) Symplectic Group of degree 2 over Finite Field of size 3 sage: G = Sp(4,5) sage: TestSuite(G).run() """ degree, ring = normalize_args_vectorspace(n, R, var=var) if degree % 2 != 0: raise ValueError('the degree must be even') if invariant_form is not None: if is_FiniteField(ring): raise NotImplementedError("invariant_form for finite groups is fixed by GAP") invariant_form = normalize_args_invariant_form(ring, degree, invariant_form) if not invariant_form.is_alternating(): raise ValueError("invariant_form must be alternating") name = 'Symplectic Group of degree {0} over {1} with respect to alternating bilinear form\n{2}'.format( degree, ring, invariant_form) ltx = r'\text{{Sp}}_{{{0}}}({1})\text{{ with respect to alternating bilinear form}}{2}'.format( degree, latex(ring), latex(invariant_form)) else: name = 'Symplectic Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{Sp}}_{{{0}}}({1})'.format(degree, latex(ring)) try: cmd = 'Sp({0}, {1})'.format(degree, ring._gap_init_()) return SymplecticMatrixGroup_gap(degree, ring, True, name, ltx, cmd) except ValueError: return SymplecticMatrixGroup_generic(degree, ring, True, name, ltx, invariant_form=invariant_form)
def __init__(self, ogf, *args, **kwargs): """ Create a C-finite sequence given its ordinary generating function. INPUT: - ``ogf`` -- the ordinary generating function, a fraction of polynomials over the rationals OUTPUT: - A CFiniteSequence object EXAMPLES:: sage: R.<x> = QQ[] sage: CFiniteSequence((2-x)/(1-x-x^2)) # the Lucas sequence C-finite sequence, generated by (-x + 2)/(-x^2 - x + 1) sage: CFiniteSequence(x/(1-x)^3) # triangular numbers C-finite sequence, generated by x/(-x^3 + 3*x^2 - 3*x + 1) Polynomials are interpreted as finite sequences, or recurrences of degree 0:: sage: CFiniteSequence(x^2-4*x^5) Finite sequence [1, 0, 0, -4], offset = 2 sage: CFiniteSequence(1) Finite sequence [1], offset = 0 This implementation allows any polynomial fraction as o.g.f. by interpreting any power of `x` dividing the o.g.f. numerator or denominator as a right or left shift of the sequence offset:: sage: CFiniteSequence(x^2+3/x) Finite sequence [3, 0, 0, 1], offset = -1 sage: CFiniteSequence(1/x+4/x^3) Finite sequence [4, 0, 1], offset = -3 sage: P = LaurentPolynomialRing(QQ.fraction_field(), 'X') sage: X=P.gen() sage: CFiniteSequence(1/(1-X)) C-finite sequence, generated by 1/(-x + 1) The o.g.f. is always normalized to get a denominator constant coefficient of `+1`:: sage: CFiniteSequence(1/(x-2)) C-finite sequence, generated by -1/2/(-1/2*x + 1) TESTS:: sage: P.<x> = QQ[] sage: CFiniteSequence(0.1/(1-x)) Traceback (most recent call last): ... ValueError: O.g.f. base not rational. sage: P.<x,y> = QQ[] sage: CFiniteSequence(x*y) Traceback (most recent call last): ... NotImplementedError: Multidimensional o.g.f. not implemented. """ self._br = ogf.base_ring() if (self._br <> QQ) and (self._br <> ZZ) and not is_FiniteField(self._br): raise ValueError('O.g.f. base not proper.') P = PolynomialRing(self._br, 'x') if ogf in QQ: ogf = P(ogf) if hasattr(ogf,'numerator'): try: num = P(ogf.numerator()) den = P(ogf.denominator()) except TypeError: if ogf.numerator().parent().ngens() > 1: raise NotImplementedError('Multidimensional o.g.f. not implemented.') else: raise ValueError('Numerator and denominator must be polynomials.') else: num = P(ogf) den = 1 # Transform the ogf numerator and denominator to canonical form # to get the correct offset, degree, and recurrence coeffs and # start values. self._off = 0 self._deg = 0 if isinstance (ogf, FractionFieldElement) and den == 1: ogf = num # case p(x)/1: fall through if isinstance (ogf, (FractionFieldElement, FpTElement)): x = P.gen() if num.constant_coefficient() == 0: self._off = num.valuation() num = P(num / x**self._off) elif den.constant_coefficient() == 0: self._off = -den.valuation() den = P(den * x**self._off) f = den.constant_coefficient() num = P(num / f) den = P(den / f) f = gcd(num, den) num = P(num / f) den = P(den / f) self._deg = den.degree() self._c = [-den.list()[i] for i in range(1, self._deg + 1)] if self._off >= 0: num = x**self._off * num else: den = x**(-self._off) * den # determine start values (may be different from _get_item_ values) R = LaurentSeriesRing(self._br, 'x') rem = num % den alen = max(self._deg, num.degree() + 1) R.set_default_prec (alen) if den <> 1: self._a = R(num/(den+O(x**alen))).list() self._aa = R(rem/(den+O(x**alen))).list()[:self._deg] # needed for _get_item_ else: self._a = num.list() if len(self._a) < alen: self._a.extend([0] * (alen - len(self._a))) super(CFiniteSequence, self).__init__(P.fraction_field(), num, den, *args, **kwargs) elif ogf.parent().is_integral_domain(): super(CFiniteSequence, self).__init__(ogf.parent().fraction_field(), P(ogf), 1, *args, **kwargs) self._c = [] self._off = P(ogf).valuation() if ogf == 0: self._a = [0] else: self._a = ogf.parent()((ogf / (ogf.parent().gen())**self._off)).list() else: raise ValueError("Cannot convert a " + str(type(ogf)) + " to CFiniteSequence.")
def _single_variate(base_ring, name, sparse=None, implementation=None, order=None): # The "order" argument is unused, but we allow it (and ignore it) # for consistency with the multi-variate case. sparse = bool(sparse) # "implementation" must be last key = [base_ring, name, sparse, implementation] R = _get_from_cache(key) if R is not None: return R from . import polynomial_ring # Find the right constructor and **kwds for our polynomial ring constructor = None kwds = {} if sparse: kwds["sparse"] = True # Specialized implementations specialized = None if is_IntegerModRing(base_ring): n = base_ring.order() if n.is_prime(): specialized = polynomial_ring.PolynomialRing_dense_mod_p elif n > 1: # Specialized code breaks for n == 1 specialized = polynomial_ring.PolynomialRing_dense_mod_n elif is_FiniteField(base_ring): specialized = polynomial_ring.PolynomialRing_dense_finite_field elif isinstance(base_ring, padic_base_leaves.pAdicFieldCappedRelative): specialized = polynomial_ring.PolynomialRing_dense_padic_field_capped_relative elif isinstance(base_ring, padic_base_leaves.pAdicRingCappedRelative): specialized = polynomial_ring.PolynomialRing_dense_padic_ring_capped_relative elif isinstance(base_ring, padic_base_leaves.pAdicRingCappedAbsolute): specialized = polynomial_ring.PolynomialRing_dense_padic_ring_capped_absolute elif isinstance(base_ring, padic_base_leaves.pAdicRingFixedMod): specialized = polynomial_ring.PolynomialRing_dense_padic_ring_fixed_mod # If the implementation is supported, then we are done if specialized is not None: implementation_names = specialized._implementation_names_impl( implementation, base_ring, sparse) if implementation_names is not NotImplemented: implementation = implementation_names[0] constructor = specialized # Generic implementations if constructor is None: if not isinstance(base_ring, ring.CommutativeRing): constructor = polynomial_ring.PolynomialRing_general elif base_ring in _CompleteDiscreteValuationRings: constructor = polynomial_ring.PolynomialRing_cdvr elif base_ring in _CompleteDiscreteValuationFields: constructor = polynomial_ring.PolynomialRing_cdvf elif base_ring.is_field(proof=False): constructor = polynomial_ring.PolynomialRing_field elif base_ring.is_integral_domain(proof=False): constructor = polynomial_ring.PolynomialRing_integral_domain else: constructor = polynomial_ring.PolynomialRing_commutative implementation_names = constructor._implementation_names( implementation, base_ring, sparse) implementation = implementation_names[0] # Only use names which are not supported by the specialized class. if specialized is not None: implementation_names = [ n for n in implementation_names if specialized._implementation_names_impl( n, base_ring, sparse) is NotImplemented ] if implementation is not None: kwds["implementation"] = implementation R = constructor(base_ring, name, **kwds) for impl in implementation_names: key[-1] = impl _save_in_cache(key, R) return R
def can_convert_to_singular(R): """ Returns True if this ring's base field or ring can be represented in Singular, and the polynomial ring has at least one generator. If this is True then this polynomial ring can be represented in Singular. The following base rings are supported: finite fields, rationals, number fields, and real and complex fields. EXAMPLES:: sage: from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular sage: can_convert_to_singular(PolynomialRing(QQ, names=['x'])) True sage: can_convert_to_singular(PolynomialRing(QQ, names=[])) False """ if R.ngens() == 0: return False; base_ring = R.base_ring() return ( sage.rings.finite_rings.constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) or (base_ring.is_prime_field() and base_ring.characteristic() <= 2147483647) or is_RealField(base_ring) or is_ComplexField(base_ring) or is_RealDoubleField(base_ring) or is_ComplexDoubleField(base_ring) or number_field.number_field_base.is_NumberField(base_ring) or ( sage.rings.fraction_field.is_FractionField(base_ring) and ( base_ring.base_ring().is_prime_field() or base_ring.base_ring() is ZZ or is_FiniteField(base_ring.base_ring()) ) ) or base_ring is ZZ or is_IntegerModRing(base_ring) or (is_RationalFunctionField(base_ring) and base_ring.constant_field().is_prime_field()) )
def GU(n, R, var='a'): r""" Return the general unitary group. The general unitary group `GU( d, R )` consists of all `d \times d` matrices that preserve a nondegenerate sesquilinear form over the ring `R`. .. note:: For a finite field the matrices that preserve a sesquilinear form over `F_q` live over `F_{q^2}`. So ``GU(n,q)`` for integer ``q`` constructs the matrix group over the base ring ``GF(q^2)``. .. note:: This group is also available via ``groups.matrix.GU()``. INPUT: - ``n`` -- a positive integer. - ``R`` -- ring or an integer. If an integer is specified, the corresponding finite field is used. - ``var`` -- variable used to represent generator of the finite field, if needed. OUTPUT: Return the general unitary group. EXAMPLES:: sage: G = GU(3, 7); G General Unitary Group of degree 3 over Finite Field in a of size 7^2 sage: G.gens() ( [ a 0 0] [6*a 6 1] [ 0 1 0] [ 6 6 0] [ 0 0 5*a], [ 1 0 0] ) sage: GU(2,QQ) General Unitary Group of degree 2 over Rational Field sage: G = GU(3, 5, var='beta') sage: G.base_ring() Finite Field in beta of size 5^2 sage: G.gens() ( [ beta 0 0] [4*beta 4 1] [ 0 1 0] [ 4 4 0] [ 0 0 3*beta], [ 1 0 0] ) TESTS:: sage: groups.matrix.GU(2, 3) General Unitary Group of degree 2 over Finite Field in a of size 3^2 """ degree, ring = normalize_args_vectorspace(n, R, var=var) if is_FiniteField(ring): q = ring.cardinality() ring = GF(q**2, name=var) name = 'General Unitary Group of degree {0} over {1}'.format(degree, ring) ltx = r'\text{{GU}}_{{{0}}}({1})'.format(degree, latex(ring)) if is_FiniteField(ring): cmd = 'GU({0}, {1})'.format(degree, q) return UnitaryMatrixGroup_gap(degree, ring, False, name, ltx, cmd) else: return UnitaryMatrixGroup_generic(degree, ring, False, name, ltx)
def _singular_init_(self, singular=singular): """ Return a newly created Singular ring matching this ring. EXAMPLES:: sage: PolynomialRing(QQ,'u_ba')._singular_init_() // characteristic : 0 // number of vars : 1 // block 1 : ordering lp // : names u_ba // block 2 : ordering C """ if not can_convert_to_singular(self): raise TypeError("no conversion of this ring to a Singular ring defined") if self.ngens()==1: _vars = '(%s)'%self.gen() if "*" in _vars: # 1.000...000*x _vars = _vars.split("*")[1] order = 'lp' else: _vars = str(self.gens()) order = self.term_order().singular_str() base_ring = self.base_ring() if is_RealField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.rings.arith.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order, check=False) elif is_ComplexField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.rings.arith.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order, check=False) elif is_RealDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(real,15,0)", _vars, order=order, check=False) elif is_ComplexDoubleField(base_ring): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(complex,15,0,I)", _vars, order=order, check=False) elif base_ring.is_prime_field(): self.__singular = singular.ring(self.characteristic(), _vars, order=order, check=False) elif sage.rings.finite_rings.constructor.is_FiniteField(base_ring): # not the prime field! gen = str(base_ring.gen()) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (str(base_ring.modulus()).replace("x",gen)).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif number_field.number_field_base.is_NumberField(base_ring) and base_ring.is_absolute(): # not the rationals! gen = str(base_ring.gen()) poly=base_ring.polynomial() poly_gen=str(poly.parent().gen()) poly_str=str(poly).replace(poly_gen,gen) r = singular.ring( "(%s,%s)"%(self.characteristic(),gen), _vars, order=order, check=False) self.__minpoly = (poly_str).replace(" ","") if singular.eval('minpoly') != "(" + self.__minpoly + ")": singular.eval("minpoly=%s"%(self.__minpoly) ) self.__minpoly = singular.eval('minpoly')[1:-1] self.__singular = r elif sage.rings.fraction_field.is_FractionField(base_ring) and (base_ring.base_ring() is ZZ or base_ring.base_ring().is_prime_field() or is_FiniteField(base_ring.base_ring())): if base_ring.ngens()==1: gens = str(base_ring.gen()) else: gens = str(base_ring.gens()) if not (not base_ring.base_ring().is_prime_field() and is_FiniteField(base_ring.base_ring())) : self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) else: ext_gen = str(base_ring.base_ring().gen()) _vars = '(' + ext_gen + ', ' + _vars[1:]; R = self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gens), _vars, order=order, check=False) self.base_ring().__minpoly = (str(base_ring.base_ring().modulus()).replace("x",ext_gen)).replace(" ","") singular.eval('setring '+R._name); self.__singular = singular("std(ideal(%s))"%(self.base_ring().__minpoly),type='qring') elif sage.rings.function_field.function_field.is_RationalFunctionField(base_ring) and base_ring.constant_field().is_prime_field(): gen = str(base_ring.gen()) self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gen), _vars, order=order, check=False) elif is_IntegerModRing(base_ring): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 self.__singular = singular.ring("(integer,2,%d)"%(exp,), _vars, order=order, check=False) else: self.__singular = singular.ring("(integer,%d)"%(ch,), _vars, order=order, check=False) elif base_ring is ZZ: self.__singular = singular.ring("(integer)", _vars, order=order, check=False) else: raise TypeError("no conversion to a Singular ring defined") return self.__singular