def is_locally_solvable(self, p): r""" Returns True if and only if ``self`` has a solution over the `p`-adic numbers. Here `p` is a prime number or equals `-1`, infinity, or `\RR` to denote the infinite place. EXAMPLES:: sage: C = Conic(QQ, [1,2,3]) sage: C.is_locally_solvable(-1) False sage: C.is_locally_solvable(2) False sage: C.is_locally_solvable(3) True sage: C.is_locally_solvable(QQ.hom(RR)) False sage: D = Conic(QQ, [1, 2, -3]) sage: D.is_locally_solvable(infinity) True sage: D.is_locally_solvable(RR) True """ from sage.categories.map import Map from sage.categories.all import Rings D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] if abc[2] == 0: return True a = -abc[0]/abc[2] b = -abc[1]/abc[2] if is_RealField(p) or is_InfinityElement(p): p = -1 elif isinstance(p, Map) and p.category_for().is_subcategory(Rings()): # p is a morphism of Rings if p.domain() is QQ and is_RealField(p.codomain()): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " \ "B ( =`QQ`) in is_locally_solvable" % p) if hilbert_symbol(a, b, p) == -1: if self._local_obstruction is None: self._local_obstruction = p return False return True
def is_locally_solvable(self, p): r""" Returns True if and only if ``self`` has a solution over the `p`-adic numbers. Here `p` is a prime number or equals `-1`, infinity, or `\RR` to denote the infinite place. EXAMPLES:: sage: C = Conic(QQ, [1,2,3]) sage: C.is_locally_solvable(-1) False sage: C.is_locally_solvable(2) False sage: C.is_locally_solvable(3) True sage: C.is_locally_solvable(QQ.hom(RR)) False sage: D = Conic(QQ, [1, 2, -3]) sage: D.is_locally_solvable(infinity) True sage: D.is_locally_solvable(RR) True """ from sage.categories.map import Map from sage.categories.all import Rings D, T = self.diagonal_matrix() abc = [D[j, j] for j in range(3)] if abc[2] == 0: return True a = -abc[0] / abc[2] b = -abc[1] / abc[2] if is_RealField(p) or is_InfinityElement(p): p = -1 elif isinstance(p, Map) and p.category_for().is_subcategory(Rings()): # p is a morphism of Rings if p.domain() is QQ and is_RealField(p.codomain()): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " \ "B ( =`QQ`) in is_locally_solvable" % p) if hilbert_symbol(a, b, p) == -1: if self._local_obstruction is None: self._local_obstruction = p return False return True
def __init__(self, number_field, a, b=None, parent=None, lreps=None): """ Constructor of number field cusps. See ``NFCusp`` for full documentation. EXAMPLES:: sage: k.<a> = NumberField(x^2 + 1) sage: c = NFCusp(k, 3, a+1); c Cusp [3: a + 1] of Number Field in a with defining polynomial x^2 + 1 sage: c.parent() Set of all cusps of Number Field in a with defining polynomial x^2 + 1 sage: kCusps = NFCusps(k) sage: c.parent() is kCusps True """ if parent is None: parent = NFCusps(number_field) Element.__init__(self, parent) R = number_field.maximal_order() if b is None: if not a:#that is cusp "0" self.__a = R(0) self.__b = R(1) return if isinstance(a, NFCusp): if a.parent() == parent: self.__a = R(a.__a) self.__b = R(a.__b) else: raise ValueError("Cannot coerce cusps from one field to another") elif a in R: self.__a = R(a) self.__b = R(1) elif a in number_field: self.__b = R(a.denominator()) self.__a = R(a * self.__b) elif is_InfinityElement(a): self.__a = R(1) self.__b = R(0) elif isinstance(a, (int, long)): self.__a = R(a) self.__b = R(1) elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError("Unable to convert %s to a cusp \ of the number field"%a) if a[1].is_zero(): self.__a = R(1) self.__b = R(0) elif a[0] in R and a[1] in R: self.__a = R(a[0]) self.__b = R(a[1]) elif isinstance(a[0], NFCusp):#we know that a[1] is not zero if a[1] == 1: self.__a = a[0].__a self.__b = a[0].__b else: r = a[0].__a / (a[0].__b * a[1]) self.__b = R(r.denominator()) self.__a = R(r*self.__b) else: try: r = number_field(a[0]/a[1]) self.__b = R(r.denominator()) self.__a = R(r * self.__b) except (ValueError, TypeError): raise TypeError("Unable to convert %s to a cusp \ of the number field"%a) else: try: r = number_field(a) self.__b = R(r.denominator()) self.__a = R(r * self.__b) except (ValueError, TypeError): raise TypeError("Unable to convert %s to a cusp \ of the number field"%a) else:#'b' is given if is_InfinityElement(b): if is_InfinityElement(a) or (isinstance(a, NFCusp) and a.is_infinity()): raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field"%(a, b)) self.__a = R(0) self.__b = R(1) return elif not b: if not a: raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field"%(a, b)) self.__a = R(1) self.__b = R(0) return if not a: self.__a = R(0) self.__b = R(1) return if (b in R or isinstance(b, (int, long))) and (a in R or isinstance(a, (int, long))): self.__a = R(a) self.__b = R(b) else: if a in R or a in number_field: r = a / b elif is_InfinityElement(a): self.__a = R(1) self.__b = R(0) return elif isinstance(a, NFCusp): if a.is_infinity(): self.__a = R(1) self.__b = R(0) return r = a.__a / (a.__b * b) elif isinstance(a, (int, long)): r = R(a) / b elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field"%(a, b)) r = R(a[0]) / (R(a[1]) * b) else: try: r = number_field(a) / b except (ValueError, TypeError): raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field"%(a, b)) self.__b = R(r.denominator()) self.__a = R(r * self.__b) if not lreps is None: # Changes the representative of the cusp so the ideal associated # to the cusp is one of the ideals of the given list lreps. # Note: the trivial class is always represented by (1). I = self.ideal() for J in lreps: if (J/I).is_principal(): newI = J l = (newI/I).gens_reduced()[0] self.__a = R(l * self.__a) self.__b = R(l * self.__b)
def __init__(self, number_field, a, b=None, parent=None, lreps=None): """ Constructor of number field cusps. See ``NFCusp`` for full documentation. EXAMPLES:: sage: k.<a> = NumberField(x^2 + 1) sage: c = NFCusp(k, 3, a+1); c Cusp [3: a + 1] of Number Field in a with defining polynomial x^2 + 1 sage: c.parent() Set of all cusps of Number Field in a with defining polynomial x^2 + 1 sage: kCusps = NFCusps(k) sage: c.parent() is kCusps True """ if parent is None: parent = NFCusps(number_field) Element.__init__(self, parent) R = number_field.maximal_order() if b is None: if not a: #that is cusp "0" self.__a = R(0) self.__b = R(1) return if isinstance(a, NFCusp): if a.parent() == parent: self.__a = R(a.__a) self.__b = R(a.__b) else: raise ValueError( "Cannot coerce cusps from one field to another") elif a in R: self.__a = R(a) self.__b = R(1) elif a in number_field: self.__b = R(a.denominator()) self.__a = R(a * self.__b) elif is_InfinityElement(a): self.__a = R(1) self.__b = R(0) elif isinstance(a, (int, long)): self.__a = R(a) self.__b = R(1) elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError("Unable to convert %s to a cusp \ of the number field" % a) if a[1].is_zero(): self.__a = R(1) self.__b = R(0) elif a[0] in R and a[1] in R: self.__a = R(a[0]) self.__b = R(a[1]) elif isinstance(a[0], NFCusp): #we know that a[1] is not zero if a[1] == 1: self.__a = a[0].__a self.__b = a[0].__b else: r = a[0].__a / (a[0].__b * a[1]) self.__b = R(r.denominator()) self.__a = R(r * self.__b) else: try: r = number_field(a[0] / a[1]) self.__b = R(r.denominator()) self.__a = R(r * self.__b) except (ValueError, TypeError): raise TypeError("Unable to convert %s to a cusp \ of the number field" % a) else: try: r = number_field(a) self.__b = R(r.denominator()) self.__a = R(r * self.__b) except (ValueError, TypeError): raise TypeError("Unable to convert %s to a cusp \ of the number field" % a) else: #'b' is given if is_InfinityElement(b): if is_InfinityElement(a) or (isinstance(a, NFCusp) and a.is_infinity()): raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field" % (a, b)) self.__a = R(0) self.__b = R(1) return elif not b: if not a: raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field" % (a, b)) self.__a = R(1) self.__b = R(0) return if not a: self.__a = R(0) self.__b = R(1) return if (b in R or isinstance(b, (int, long))) and (a in R or isinstance( a, (int, long))): self.__a = R(a) self.__b = R(b) else: if a in R or a in number_field: r = a / b elif is_InfinityElement(a): self.__a = R(1) self.__b = R(0) return elif isinstance(a, NFCusp): if a.is_infinity(): self.__a = R(1) self.__b = R(0) return r = a.__a / (a.__b * b) elif isinstance(a, (int, long)): r = R(a) / b elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field" % (a, b)) r = R(a[0]) / (R(a[1]) * b) else: try: r = number_field(a) / b except (ValueError, TypeError): raise TypeError("Unable to convert (%s, %s) \ to a cusp of the number field" % (a, b)) self.__b = R(r.denominator()) self.__a = R(r * self.__b) if not lreps is None: # Changes the representative of the cusp so the ideal associated # to the cusp is one of the ideals of the given list lreps. # Note: the trivial class is always represented by (1). I = self.ideal() for J in lreps: if (J / I).is_principal(): newI = J l = (newI / I).gens_reduced()[0] self.__a = R(l * self.__a) self.__b = R(l * self.__b)
def _cmp_generators(self, other): """ Implement comparison We treat two matrix groups as equal if their generators are the same in the same order. Infinitely-generated groups are compared by identity. INPUT: - ``other`` -- anything. OUTPUT: ``-1``, ``0``, or ``+1``. EXAMPLES:: sage: G = GL(2,3) sage: H = MatrixGroup(G.gens()) sage: G._cmp_generators(H) 0 sage: cmp(G,H) 0 sage: cmp(H,G) 0 sage: G == H True """ if not is_MatrixGroup(other): return cmp(type(self), type(other)) c = cmp(self.matrix_space(), other.matrix_space()) if c != 0: return c def identity_cmp(): return cmp(id(self), id(other)) # compare number of generators try: n_self = self.ngens() n_other = other.ngens() except (AttributeError, NotImplementedError): return identity_cmp() c = cmp(n_self, n_other) if c != 0: return c from sage.structure.element import is_InfinityElement if is_InfinityElement(n_self) or is_InfinityElement(n_other): return identity_cmp() # compacte generator matrices try: self_gens = self.gens() other_gens = other.gens() except (AttributeError, NotImplementedError): return identity_cmp() assert(n_self == n_other) for g,h in zip(self_gens, other_gens): c = cmp(g.matrix(), h.matrix()) if c != 0: return c return c
def __init__(self, a, b=None, parent=None, check=True): r""" Create the cusp a/b in `\mathbb{P}^1(\QQ)`, where if b=0 this is the cusp at infinity. When present, b must either be Infinity or coercible to an Integer. EXAMPLES:: sage: Cusp(2,3) 2/3 sage: Cusp(3,6) 1/2 sage: Cusp(1,0) Infinity sage: Cusp(infinity) Infinity sage: Cusp(5) 5 sage: Cusp(1/2) 1/2 sage: Cusp(1.5) 3/2 sage: Cusp(int(7)) 7 sage: Cusp(1, 2, check=False) 1/2 sage: Cusp('sage', 2.5, check=False) # don't do this! sage/2.50000000000000 :: sage: I**2 -1 sage: Cusp(I) Traceback (most recent call last): ... TypeError: unable to convert I to a cusp :: sage: a = Cusp(2,3) sage: loads(a.dumps()) == a True :: sage: Cusp(1/3,0) Infinity sage: Cusp((1,0)) Infinity TESTS:: sage: Cusp("1/3", 5) 1/15 sage: Cusp(Cusp(3/5), 7) 3/35 sage: Cusp(5/3, 0) Infinity sage: Cusp(3,oo) 0 sage: Cusp((7,3), 5) 7/15 sage: Cusp(int(5), 7) 5/7 :: sage: Cusp(0,0) Traceback (most recent call last): ... TypeError: unable to convert (0, 0) to a cusp :: sage: Cusp(oo,oo) Traceback (most recent call last): ... TypeError: unable to convert (+Infinity, +Infinity) to a cusp :: sage: Cusp(Cusp(oo),oo) Traceback (most recent call last): ... TypeError: unable to convert (Infinity, +Infinity) to a cusp """ if parent is None: parent = Cusps Element.__init__(self, parent) if not check: self.__a = a self.__b = b return if b is None: if isinstance(a, Integer): self.__a = a self.__b = ZZ.one() elif isinstance(a, Rational): self.__a = a.numer() self.__b = a.denom() elif is_InfinityElement(a): self.__a = ZZ.one() self.__b = ZZ.zero() elif isinstance(a, Cusp): self.__a = a.__a self.__b = a.__b elif isinstance(a, integer_types): self.__a = ZZ(a) self.__b = ZZ.one() elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError("unable to convert %r to a cusp" % a) if ZZ(a[1]) == 0: self.__a = ZZ.one() self.__b = ZZ.zero() return try: r = QQ((a[0], a[1])) self.__a = r.numer() self.__b = r.denom() except (ValueError, TypeError): raise TypeError("unable to convert %r to a cusp" % a) else: try: r = QQ(a) self.__a = r.numer() self.__b = r.denom() except (ValueError, TypeError): raise TypeError("unable to convert %r to a cusp" % a) return if is_InfinityElement(b): if is_InfinityElement(a) or (isinstance(a, Cusp) and a.is_infinity()): raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b)) self.__a = ZZ.zero() self.__b = ZZ.one() return elif not b: if not a: raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b)) self.__a = ZZ.one() self.__b = ZZ.zero() return if isinstance(a, Integer) or isinstance(a, Rational): r = a / ZZ(b) elif is_InfinityElement(a): self.__a = ZZ.one() self.__b = ZZ.zero() return elif isinstance(a, Cusp): if a.__b: r = a.__a / (a.__b * b) else: self.__a = ZZ.one() self.__b = ZZ.zero() return elif isinstance(a, integer_types): r = ZZ(a) / b elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b)) r = ZZ(a[0]) / (ZZ(a[1]) * b) else: try: r = QQ(a) / b except (ValueError, TypeError): raise TypeError("unable to convert (%r, %r) to a cusp" % (a, b)) self.__a = r.numer() self.__b = r.denom()
def __init__(self, a, b=None, parent=None, check=True): r""" Create the cusp a/b in `\mathbb{P}^1(\QQ)`, where if b=0 this is the cusp at infinity. When present, b must either be Infinity or coercible to an Integer. EXAMPLES:: sage: Cusp(2,3) 2/3 sage: Cusp(3,6) 1/2 sage: Cusp(1,0) Infinity sage: Cusp(infinity) Infinity sage: Cusp(5) 5 sage: Cusp(1/2) 1/2 sage: Cusp(1.5) 3/2 sage: Cusp(int(7)) 7 sage: Cusp(1, 2, check=False) 1/2 sage: Cusp('sage', 2.5, check=False) # don't do this! sage/2.50000000000000 :: sage: I**2 -1 sage: Cusp(I) Traceback (most recent call last): ... TypeError: Unable to convert I to a Cusp :: sage: a = Cusp(2,3) sage: loads(a.dumps()) == a True :: sage: Cusp(1/3,0) Infinity sage: Cusp((1,0)) Infinity TESTS:: sage: Cusp("1/3", 5) 1/15 sage: Cusp(Cusp(3/5), 7) 3/35 sage: Cusp(5/3, 0) Infinity sage: Cusp(3,oo) 0 sage: Cusp((7,3), 5) 7/15 sage: Cusp(int(5), 7) 5/7 :: sage: Cusp(0,0) Traceback (most recent call last): ... TypeError: Unable to convert (0, 0) to a Cusp :: sage: Cusp(oo,oo) Traceback (most recent call last): ... TypeError: Unable to convert (+Infinity, +Infinity) to a Cusp :: sage: Cusp(Cusp(oo),oo) Traceback (most recent call last): ... TypeError: Unable to convert (Infinity, +Infinity) to a Cusp """ if parent is None: parent = Cusps Element.__init__(self, parent) if not check: self.__a = a; self.__b = b return if b is None: if isinstance(a, Integer): self.__a = a self.__b = ZZ(1) elif isinstance(a, Rational): self.__a = a.numer() self.__b = a.denom() elif is_InfinityElement(a): self.__a = ZZ(1) self.__b = ZZ(0) elif isinstance(a, Cusp): self.__a = a.__a self.__b = a.__b elif isinstance(a, (int, long)): self.__a = ZZ(a) self.__b = ZZ(1) elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError, "Unable to convert %s to a Cusp"%a if ZZ(a[1]) == 0: self.__a = ZZ(1) self.__b = ZZ(0) return try: r = QQ((a[0], a[1])) self.__a = r.numer() self.__b = r.denom() except (ValueError, TypeError): raise TypeError, "Unable to convert %s to a Cusp"%a else: try: r = QQ(a) self.__a = r.numer() self.__b = r.denom() except (ValueError, TypeError): raise TypeError, "Unable to convert %s to a Cusp"%a return if is_InfinityElement(b): if is_InfinityElement(a) or (isinstance(a, Cusp) and a.is_infinity()): raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b) self.__a = ZZ(0) self.__b = ZZ(1) return elif not b: if not a: raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b) self.__a = ZZ(1) self.__b = ZZ(0) return if isinstance(a, Integer) or isinstance(a, Rational): r = a / ZZ(b) elif is_InfinityElement(a): self.__a = ZZ(1) self.__b = ZZ(0) return elif isinstance(a, Cusp): if a.__b: r = a.__a / (a.__b * b) else: self.__a = ZZ(1) self.__b = ZZ(0) return elif isinstance(a, (int, long)): r = ZZ(a) / b elif isinstance(a, (tuple, list)): if len(a) != 2: raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b) r = ZZ(a[0]) / (ZZ(a[1]) * b) else: try: r = QQ(a) / b except (ValueError, TypeError): raise TypeError, "Unable to convert (%s, %s) to a Cusp"%(a, b) self.__a = r.numer() self.__b = r.denom()
def __richcmp__(self, other, op): """ Implement rich comparison. We treat two matrix groups as equal if their generators are the same in the same order. Infinitely-generated groups are compared by identity. INPUT: - ``other`` -- anything - ``op`` -- comparison operator OUTPUT: boolean EXAMPLES:: sage: G = GL(2,3) sage: H = MatrixGroup(G.gens()) sage: H == G True sage: G == H True sage: MS = MatrixSpace(QQ, 2, 2) sage: G = MatrixGroup([MS(1), MS([1,2,3,4])]) sage: G == G True sage: G == MatrixGroup(G.gens()) True TESTS:: sage: G = groups.matrix.GL(4,2) sage: H = MatrixGroup(G.gens()) sage: G == H True sage: G != H False """ if not is_MatrixGroup(other): return NotImplemented if self is other: return rich_to_bool(op, 0) lx = self.matrix_space() rx = other.matrix_space() if lx != rx: return richcmp_not_equal(lx, rx, op) # compare number of generators try: n_self = self.ngens() n_other = other.ngens() except (AttributeError, NotImplementedError): return richcmp(id(self), id(other), op) if n_self != n_other: return richcmp_not_equal(self, other, op) from sage.structure.element import is_InfinityElement if is_InfinityElement(n_self) or is_InfinityElement(n_other): return richcmp(id(self), id(other), op) # compact generator matrices try: self_gens = self.gens() other_gens = other.gens() except (AttributeError, NotImplementedError): return richcmp(id(self), id(other), op) assert (n_self == n_other) for g, h in zip(self_gens, other_gens): lx = g.matrix() rx = h.matrix() if lx != rx: return richcmp_not_equal(lx, rx, op) return rich_to_bool(op, 0)
def __richcmp__(self, other, op): """ Implement rich comparison. We treat two matrix groups as equal if their generators are the same in the same order. Infinitely-generated groups are compared by identity. INPUT: - ``other`` -- anything - ``op`` -- comparison operator OUTPUT: boolean EXAMPLES:: sage: G = GL(2,3) sage: H = MatrixGroup(G.gens()) sage: H == G True sage: G == H True sage: MS = MatrixSpace(QQ, 2, 2) sage: G = MatrixGroup([MS(1), MS([1,2,3,4])]) sage: G == G True sage: G == MatrixGroup(G.gens()) True TESTS:: sage: G = groups.matrix.GL(4,2) sage: H = MatrixGroup(G.gens()) sage: G == H True sage: G != H False """ if not is_MatrixGroup(other): return NotImplemented if self is other: return rich_to_bool(op, 0) lx = self.matrix_space() rx = other.matrix_space() if lx != rx: return richcmp_not_equal(lx, rx, op) # compare number of generators try: n_self = self.ngens() n_other = other.ngens() except (AttributeError, NotImplementedError): return richcmp(id(self), id(other), op) if n_self != n_other: return richcmp_not_equal(self, other, op) from sage.structure.element import is_InfinityElement if is_InfinityElement(n_self) or is_InfinityElement(n_other): return richcmp(id(self), id(other), op) # compact generator matrices try: self_gens = self.gens() other_gens = other.gens() except (AttributeError, NotImplementedError): return richcmp(id(self), id(other), op) assert(n_self == n_other) for g, h in zip(self_gens, other_gens): lx = g.matrix() rx = h.matrix() if lx != rx: return richcmp_not_equal(lx, rx, op) return rich_to_bool(op, 0)