Exemplo n.º 1
0
Arquivo: jack.py Projeto: imark83/sage
def normalize_coefficients(self, c):
    r"""
    If our coefficient ring is the field of fractions over a univariate
    polynomial ring over the rationals, then we should clear both the
    numerator and denominator of the denominators of their
    coefficients.

    INPUT:

    - ``self`` -- a Jack basis of the symmetric functions
    - ``c`` -- a coefficient in the base ring of ``self``

    OUTPUT:

    - divide numerator and denominator by the greatest common divisor

    EXAMPLES::

        sage: JP = SymmetricFunctions(FractionField(QQ['t'])).jack().P()
        sage: t = JP.base_ring().gen()
        sage: a = 2/(1/2*t+1/2)
        sage: JP._normalize_coefficients(a)
        4/(t + 1)
        sage: a = 1/(1/3+1/6*t)
        sage: JP._normalize_coefficients(a)
        6/(t + 2)
        sage: a = 24/(4*t^2 + 12*t + 8)
        sage: JP._normalize_coefficients(a)
        6/(t^2 + 3*t + 2)
    """
    BR = self.base_ring()
    if is_FractionField(BR) and BR.base_ring() == QQ:
        denom = c.denominator()
        numer = c.numerator()

        # Clear the denominators
        a = lcm([i.denominator() for i in denom.coefficients(sparse=False)])
        b = lcm([i.denominator() for i in numer.coefficients(sparse=False)])
        l = Integer(a).lcm(Integer(b))
        denom *= l
        numer *= l

        # Divide through by the gcd of the numerators
        a = gcd([i.numerator() for i in denom.coefficients(sparse=False)])
        b = gcd([i.numerator() for i in numer.coefficients(sparse=False)])
        l = Integer(a).gcd(Integer(b))

        denom = denom // l
        numer = numer // l

        return c.parent()(numer, denom)
    else:
        return c
Exemplo n.º 2
0
    def __init__(self, domain, D):
        """
        Initialize the morphism with a domain and dictionary of specializations

        EXAMPLES::

            sage: R.<a,c> = QQ[]
            sage: S.<x,y> = R[]
            sage: from sage.rings.polynomial.flatten import FractionSpecializationMorphism
            sage: phi = FractionSpecializationMorphism(Frac(S), {c:3})
            sage: phi
            Fraction Specialization morphism:
                From: Fraction Field of Multivariate Polynomial Ring in x, y over Multivariate Polynomial Ring in a, c over Rational Field
                To:   Fraction Field of Multivariate Polynomial Ring in x, y over Univariate Polynomial Ring in a over Rational Field
        """
        if not is_FractionField(domain):
            raise TypeError("domain must be a fraction field")
        self._specialization = SpecializationMorphism(domain.base(), D)
        self._repr_type_str = 'Fraction Specialization'
        Morphism.__init__(self, domain,
                          self._specialization.codomain().fraction_field())
Exemplo n.º 3
0
def _coerce_map_from_patched(self, domain):
    r"""
    TESTS::

        sage: sys.path.append(os.getcwd()); from mac_lane import * # optional: standalone
        sage: R.<x> = ZZ[]
        sage: S.<x> = QQ[]
        sage: S.quo(x^2 + 1).coerce_map_from(R.quo(x^2 + 1)).is_injective() # indirect doctest
        True

    """
    from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing
    if is_PolynomialQuotientRing(domain) and domain.modulus() == self.modulus():
        if self.base().has_coerce_map_from(domain.base()):
            return DefaultConvertMap_unique_patched3(domain, self)
    from sage.rings.fraction_field import is_FractionField
    if is_FractionField(domain):
        # this should be implemented on a much higher level:
        # if there is a morphism R -> K then there is a morphism Frac(R) -> K
        if self.has_coerce_map_from(domain.base()):
            return True
    return self._coerce_map_from_original(domain)
Exemplo n.º 4
0
def field_format(field):
    """Print a nice representation of the given field object. This works
    correctly for number fields, but for fraction fields of polynomial
    rings we just pretend the base field are the complex numbers (for
    now)."""
    # print("debug field = {0}".format(field))
    if field == QQ:
        return ll("\\Q")
    elif is_NumberField(field):
        minpoly = field.defining_polynomial()
        g, = field.gens()
        # G, = minpoly.parent().gens()
        return (ll("K = \\Q(", g, ")") + ", where " +
                ll(g) + " has minimal polynomial " + ll(minpoly))
    elif is_FractionField(field):
        ring = field.ring_of_integers()
        if is_PolynomialRing(ring):
            return ll("\\C(", ring.gens()[0], ")")
        else:
            print("debug ring =  {0}".format(ring))
            raise UnknownField()
    else:
        raise UnknownField()
Exemplo n.º 5
0
    def _reduce_conic(self):
        r"""
        Return the reduced form of the conic, i.e. a conic with base field
        `K=F(t)` and coefficients `a,b,c` such that `a,b,c \in F[t]`,
        `\gcd(a,b)=\gcd(b,c)=\gcd(c,a)=1` and `abc` is square-free.
        
        Assumes `self` is in diagonal form.
        
        OUTPUT:
        
        A tuple (coefficients, multipliers), the coefficients of the conic
        in reduced form and multipliers `\lambda, \mu, \nu \in F(t)^*` such
        that `(x,y,z) \in F(t)` is a solution of the reduced conic if and only
        if `(\lambda x, \mu y, \nu z)` is a solution of `self`.
        
        ALGORITHM:
        
        The algorithm used is the algorithm ReduceConic in [HC2006]_.
        
        EXAMPLES::
        
            sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
            sage: C = Conic(K, [t^2-2, 2*t^3, -2*t^3-13*t^2-2*t+18])
            sage: C._reduce_conic()
            ([t^2 - 2, 2*t, -2*t^3 - 13*t^2 - 2*t + 18], [t, 1, t])
        """

        # start with removing fractions
        coeff = [
            self.coefficients()[0],
            self.coefficients()[3],
            self.coefficients()[5]
        ]
        coeff = lcm(lcm(coeff[0].denominator(), coeff[1].denominator()),
                    coeff[2].denominator()) * vector(coeff)
        # go to base ring of fraction field
        coeff = [self.base().base()(x) for x in coeff]
        coeff = vector(coeff) / gcd(coeff)
        # remove common divisors
        labda = mu = nu = 1
        g1 = g2 = g3 = 0
        ca, cb, cc = coeff
        while g1 != 1 or g2 != 1 or g3 != 1:
            g1 = gcd(ca, cb)
            ca = ca / g1
            cb = cb / g1
            cc = cc * g1
            nu = g1 * nu
            g2 = gcd(ca, cc)
            ca = ca / g2
            cc = cc / g2
            cb = cb * g2
            mu = g2 * mu
            g3 = gcd(cb, cc)
            cb = cb / g3
            cc = cc / g3
            ca = ca * g3
            labda = g3 * labda
        coeff = [ca, cb, cc]
        multipliers = [labda, mu, nu]

        # remove squares
        for i, x in enumerate(coeff):
            if is_FractionField(x.parent()):
                # go to base ring of fraction field
                x = self.base().base()(x)

            try:
                decom = x.squarefree_decomposition()
            except (NotImplementedError, AttributeError):
                decom = x.factor()
            x = decom.unit()
            x2 = 1
            for factor in decom:
                if factor[1] > 1:
                    if factor[1] % 2 == 0:
                        x2 *= factor[0]**(factor[1] // 2)
                    else:
                        x *= factor[0]
                        x2 *= factor[0]**((factor[1] - 1) // 2)
                else:
                    x *= factor[0]
            for j, y in enumerate(multipliers):
                if j != i:
                    multipliers[j] = y * x2
            coeff[i] = self.base_ring().base().coerce(x)

        return (coeff, multipliers)
Exemplo n.º 6
0
def Conic(base_field, F=None, names=None, unique=True):
    r"""
    Return the plane projective conic curve defined by ``F``
    over ``base_field``.

    The input form ``Conic(F, names=None)`` is also accepted,
    in which case the fraction field of the base ring of ``F``
    is used as base field.

    INPUT:

    - ``base_field`` -- The base field of the conic.

    - ``names`` -- a list, tuple, or comma separated string
      of three variable names specifying the names
      of the coordinate functions of the ambient
      space `\Bold{P}^3`. If not specified or read
      off from ``F``, then this defaults to ``'x,y,z'``.

    - ``F`` -- a polynomial, list, matrix, ternary quadratic form,
      or list or tuple of 5 points in the plane.

                   If ``F`` is a polynomial or quadratic form,
                   then the output is the curve in the projective plane
                   defined by ``F = 0``.

                   If ``F`` is a polynomial, then it must be a polynomial
                   of degree at most 2 in 2 variables, or a homogeneous
                   polynomial in of degree 2 in 3 variables.

                   If ``F`` is a matrix, then the output is the zero locus
                   of `(x,y,z) F (x,y,z)^t`.

                   If ``F`` is a list of coefficients, then it has
                   length 3 or 6 and gives the coefficients of
                   the monomials `x^2, y^2, z^2` or all 6 monomials
                   `x^2, xy, xz, y^2, yz, z^2` in lexicographic order.

                   If ``F`` is a list of 5 points in the plane, then the output
                   is a conic through those points.

    - ``unique`` -- Used only if ``F`` is a list of points in the plane.
      If the conic through the points is not unique, then
      raise ``ValueError`` if and only if ``unique`` is True

    OUTPUT:

    A plane projective conic curve defined by ``F`` over a field.

    EXAMPLES:

    Conic curves given by polynomials ::

        sage: X,Y,Z = QQ['X,Y,Z'].gens()
        sage: Conic(X^2 - X*Y + Y^2 - Z^2)
        Projective Conic Curve over Rational Field defined by X^2 - X*Y + Y^2 - Z^2
        sage: x,y = GF(7)['x,y'].gens()
        sage: Conic(x^2 - x + 2*y^2 - 3, 'U,V,W')
        Projective Conic Curve over Finite Field of size 7 defined by U^2 + 2*V^2 - U*W - 3*W^2

    Conic curves given by matrices ::

        sage: Conic(matrix(QQ, [[1, 2, 0], [4, 0, 0], [7, 0, 9]]), 'x,y,z')
        Projective Conic Curve over Rational Field defined by x^2 + 6*x*y + 7*x*z + 9*z^2

        sage: x,y,z = GF(11)['x,y,z'].gens()
        sage: C = Conic(x^2+y^2-2*z^2); C
        Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2
        sage: Conic(C.symmetric_matrix(), 'x,y,z')
        Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2

    Conics given by coefficients ::

        sage: Conic(QQ, [1,2,3])
        Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + 3*z^2
        sage: Conic(GF(7), [1,2,3,4,5,6], 'X')
        Projective Conic Curve over Finite Field of size 7 defined by X0^2 + 2*X0*X1 - 3*X1^2 + 3*X0*X2 - 2*X1*X2 - X2^2

    The conic through a set of points ::

        sage: C = Conic(QQ, [[10,2],[3,4],[-7,6],[7,8],[9,10]]); C
        Projective Conic Curve over Rational Field defined by x^2 + 13/4*x*y - 17/4*y^2 - 35/2*x*z + 91/4*y*z - 37/2*z^2
        sage: C.rational_point()
        (10 : 2 : 1)
        sage: C.point([3,4])
        (3 : 4 : 1)

        sage: a=AffineSpace(GF(13),2)
        sage: Conic([a([x,x^2]) for x in range(5)])
        Projective Conic Curve over Finite Field of size 13 defined by x^2 - y*z
    """
    if not (base_field is None or isinstance(base_field, IntegralDomain)):
        if names is None:
            names = F
        F = base_field
        base_field = None
    if isinstance(F, (list,tuple)):
        if len(F) == 1:
            return Conic(base_field, F[0], names)
        if names is None:
            names = 'x,y,z'
        if len(F) == 5:
            L=[]
            for f in F:
                if isinstance(f, SchemeMorphism_point_affine):
                    C = Sequence(f, universe = base_field)
                    if len(C) != 2:
                        raise TypeError("points in F (=%s) must be planar"%F)
                    C.append(1)
                elif isinstance(f, SchemeMorphism_point_projective_field):
                    C = Sequence(f, universe = base_field)
                elif isinstance(f, (list, tuple)):
                    C = Sequence(f, universe = base_field)
                    if len(C) == 2:
                        C.append(1)
                else:
                    raise TypeError("F (=%s) must be a sequence of planar " \
                                      "points" % F)
                if len(C) != 3:
                    raise TypeError("points in F (=%s) must be planar" % F)
                P = C.universe()
                if not isinstance(P, IntegralDomain):
                    raise TypeError("coordinates of points in F (=%s) must " \
                                     "be in an integral domain" % F)
                L.append(Sequence([C[0]**2, C[0]*C[1], C[0]*C[2], C[1]**2,
                                   C[1]*C[2], C[2]**2], P.fraction_field()))
            M=Matrix(L)
            if unique and M.rank() != 5:
                raise ValueError("points in F (=%s) do not define a unique " \
                                   "conic" % F)
            con = Conic(base_field, Sequence(M.right_kernel().gen()), names)
            con.point(F[0])
            return con
        F = Sequence(F, universe = base_field)
        base_field = F.universe().fraction_field()
        temp_ring = PolynomialRing(base_field, 3, names)
        (x,y,z) = temp_ring.gens()
        if len(F) == 3:
            return Conic(F[0]*x**2 + F[1]*y**2 + F[2]*z**2)
        if len(F) == 6:
            return Conic(F[0]*x**2 + F[1]*x*y + F[2]*x*z + F[3]*y**2 + \
                         F[4]*y*z + F[5]*z**2)
        raise TypeError("F (=%s) must be a sequence of 3 or 6" \
                         "coefficients" % F)
    if is_QuadraticForm(F):
        F = F.matrix()
    if is_Matrix(F) and F.is_square() and F.ncols() == 3:
        if names is None:
            names = 'x,y,z'
        temp_ring = PolynomialRing(F.base_ring(), 3, names)
        F = vector(temp_ring.gens()) * F * vector(temp_ring.gens())

    if not is_MPolynomial(F):
        raise TypeError("F (=%s) must be a three-variable polynomial or " \
                         "a sequence of points or coefficients" % F)

    if F.total_degree() != 2:
        raise TypeError("F (=%s) must have degree 2" % F)

    if base_field is None:
        base_field = F.base_ring()
    if not isinstance(base_field, IntegralDomain):
        raise ValueError("Base field (=%s) must be a field" % base_field)
    base_field = base_field.fraction_field()
    if names is None:
        names = F.parent().variable_names()
    pol_ring = PolynomialRing(base_field, 3, names)

    if F.parent().ngens() == 2:
        (x,y,z) = pol_ring.gens()
        F = pol_ring(F(x/z,y/z)*z**2)

    if F == 0:
        raise ValueError("F must be nonzero over base field %s" % base_field)

    if F.total_degree() != 2:
        raise TypeError("F (=%s) must have degree 2 over base field %s" % \
                          (F, base_field))

    if F.parent().ngens() == 3:
        P2 = ProjectiveSpace(2, base_field, names)
        if is_PrimeFiniteField(base_field):
            return ProjectiveConic_prime_finite_field(P2, F)
        if is_FiniteField(base_field):
            return ProjectiveConic_finite_field(P2, F)
        if is_RationalField(base_field):
            return ProjectiveConic_rational_field(P2, F)
        if is_NumberField(base_field):
            return ProjectiveConic_number_field(P2, F)
        if is_FractionField(base_field) and (is_PolynomialRing(base_field.ring()) or is_MPolynomialRing(base_field.ring())):
            return ProjectiveConic_rational_function_field(P2, F)
            
        return ProjectiveConic_field(P2, F)

    raise TypeError("Number of variables of F (=%s) must be 2 or 3" % F)
Exemplo n.º 7
0
    def __init__(self, domain, D):
        """
        The Python constructor

        EXAMPLES::

            sage: S.<x,y> = PolynomialRing(QQ)
            sage: D = dict({x:1})
            sage: from sage.rings.polynomial.flatten import SpecializationMorphism
            sage: phi = SpecializationMorphism(S, D); phi
            Specialization morphism:
              From: Multivariate Polynomial Ring in x, y over Rational Field
              To:   Univariate Polynomial Ring in y over Rational Field
            sage: phi(x^2 + y^2)
            y^2 + 1

        ::

            sage: R.<a,b,c> = PolynomialRing(ZZ)
            sage: S.<x,y,z> = PolynomialRing(R)
            sage: from sage.rings.polynomial.flatten import SpecializationMorphism
            sage: xi = SpecializationMorphism(S, {a:1/2})
            Traceback (most recent call last):
            ...
            TypeError: no conversion of this rational to integer

        The following was fixed in :trac:`23811`::

            sage: R.<c> = RR[]
            sage: P.<z> = AffineSpace(R, 1)
            sage: H = End(P)
            sage: f = H([z^2 + c])
            sage: f.specialization({c:1})
            Scheme endomorphism of Affine Space of dimension 1 over Real Field with 53 bits of precision
              Defn: Defined on coordinates by sending (z) to
                    (z^2 + 1.00000000000000)
        """
        if not is_PolynomialRing(domain) and not is_MPolynomialRing(domain):
            raise TypeError("domain should be a polynomial ring")

        # use only the generators that are in the stack somewhere,
        # and ignore the rest
        all_gens = domain.gens_dict_recursive()
        new_D = {}
        for gen in D:
            if str(gen) in all_gens:
                new_D[gen] = D[gen]
        D = new_D

        # _sub_specialization is a specialization morphism (recursive)
        # which is applied to the base Fraction field, or None if it's
        # any other base ring

        self._sub_specialization = None

        # We use this composition where "flat" is a flattened
        # polynomial ring.
        #
        #            phi       D       psi
        #     domain  →  flat  →  flat  →  R
        #        │         │               │
        #        └─────────┴───────────────┘
        # _flattening_morph     _eval_morph
        #             = phi       = psi ∘ D

        phi = FlatteningMorphism(domain)
        flat = phi.codomain()
        base = flat.base_ring()

        # Change domain of D to "flat" and ensure that the values lie
        # in the base ring.
        D = {phi(k): base(D[k]) for k in D}

        # Construct unflattened codomain R
        new_vars = []
        R = domain
        while is_PolynomialRing(R) or is_MPolynomialRing(
                R) or is_FractionField(R):
            if is_FractionField(R):
                # We've hit base_ring, so set _sub_specialization and exit the loop
                field_over = R.base()
                applicable_vars = {
                    key: val
                    for key, val in D.items() if key not in flat.gens()
                }
                # If there are any variables in D to set in _sub_specialization
                if applicable_vars:
                    # Coerce the generators to be in the right ring
                    # This un-does changing the domain of D to be in the flat base ring
                    tmp = {}
                    for var, val in applicable_vars.items():
                        for gstr, gen in field_over.gens_dict_recursive(
                        ).items():
                            if str(var) == gstr:
                                tmp[gen] = val
                                break
                        else:
                            # Should have been caught earlier
                            raise NameError(
                                "argument " + str(var) +
                                " is not a generator anywhere in the polynomial tower"
                            )
                    applicable_vars = tmp
                    self._sub_specialization = FractionSpecializationMorphism(
                        R, applicable_vars)
                break
            # We're still in the polynomials, so keep track of the tower
            old = R.gens()
            new = [t for t in old if t not in D]
            force_multivariate = ((len(old) == 1) and is_MPolynomialRing(R))
            new_vars.append((new, force_multivariate, old))
            R = R.base_ring()

        if self._sub_specialization:
            # The sub_specialization range will be different
            # if it applied some variables from D
            R = self._sub_specialization.codomain().fraction_field()

        # Construct unflattening map psi (only defined on the variables
        # of "flat" which are not involved in D)
        psi = dict()
        # Reconstruct the proper domain of this morphism
        # based on the sub_specialization domains
        new_domain = R
        for new, force_multivariate, old in reversed(new_vars):
            if self._sub_specialization:
                if force_multivariate:
                    new_domain = PolynomialRing(new_domain, old, len(old))
                else:
                    new_domain = PolynomialRing(new_domain, old)
            if not new:
                continue
            var_names = [str(var) for var in new]
            if force_multivariate:
                R = PolynomialRing(R, var_names, len(var_names))
            else:
                R = PolynomialRing(R, var_names)
            # Map variables in "new" to R
            psi.update(zip([phi(w) for w in new], R.gens()))

        # Fix domain of eval_morph
        # (note: phi's domain is correct)
        if self._sub_specialization:
            phi_prime = FlatteningMorphism(new_domain)
            flat_old = flat
            flat = phi_prime.codomain()
            base_prime = flat.base_ring()
            D = {phi(k): base_prime(D[k]) for k in D}
        else:
            # The bottom of our tower has not changed
            def flat_old(x):
                return x

        # Compose D with psi
        vals = []
        for t in flat.gens():
            if t in D:
                vals.append(R.coerce(D[t]))
            else:
                # Make sure keys are in the old domain
                # or else they won't match exactly
                vals.append(psi[flat_old(t)])

        self._flattening_morph = phi
        self._eval_morph = flat.hom(vals, R)
        self._repr_type_str = 'Specialization'
        Morphism.__init__(self, domain, R)
Exemplo n.º 8
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme

        ::

            sage: R.<x,y,z> = QQ[]
            sage: f = DynamicalSystem_affine([x+y+z, y*z])
            Traceback (most recent call last):
            ...
            ValueError: Number of polys does not match dimension of Affine Space of dimension 3 over Rational Field

        ::
            sage: A.<x,y> = AffineSpace(QQ,2)
            sage: f = DynamicalSystem_affine([CC.0*x^2, y^2], domain=A)
            Traceback (most recent call last):
            ...
            TypeError: coefficients of polynomial not in Rational Field
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(
                    domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys, (list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        PR = get_coercion_model().common_parent(*polys)
        fraction_field = any(is_FractionField(poly.parent()) for poly in polys)
        if fraction_field:
            K = PR.base_ring().fraction_field()
            # Replace base ring with its fraction field
            PR = PR.ring().change_ring(K).fraction_field()
            polys = [PR(poly) for poly in polys]
        else:
            quotient_ring = any(
                is_QuotientRing(poly.parent()) for poly in polys)
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            if quotient_ring:
                polys = [PR(poly).lift() for poly in polys]
            else:
                polys = [PR(poly) for poly in polys]
        if domain is None:
            if PR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                PR = PR.ring()
            domain = AffineSpace(PR)
        else:
            # Check if we can coerce the given polynomials over the given domain
            PR = domain.ambient_space().coordinate_ring()
            try:
                if fraction_field:
                    PR = PR.fraction_field()
                polys = [PR(poly) for poly in polys]
            except TypeError:
                raise TypeError('coefficients of polynomial not in {}'.format(
                    domain.base_ring()))
        if len(polys) != domain.ambient_space().coordinate_ring().ngens():
            raise ValueError(
                'Number of polys does not match dimension of {}'.format(
                    domain))
        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(
                domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
            return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
Exemplo n.º 9
0
def Conic(base_field, F=None, names=None, unique=True):
    r"""
    Return the plane projective conic curve defined by ``F``
    over ``base_field``.

    The input form ``Conic(F, names=None)`` is also accepted,
    in which case the fraction field of the base ring of ``F``
    is used as base field.

    INPUT:

    - ``base_field`` -- The base field of the conic.

    - ``names`` -- a list, tuple, or comma separated string
      of three variable names specifying the names
      of the coordinate functions of the ambient
      space `\Bold{P}^3`. If not specified or read
      off from ``F``, then this defaults to ``'x,y,z'``.

    - ``F`` -- a polynomial, list, matrix, ternary quadratic form,
      or list or tuple of 5 points in the plane.

                   If ``F`` is a polynomial or quadratic form,
                   then the output is the curve in the projective plane
                   defined by ``F = 0``.

                   If ``F`` is a polynomial, then it must be a polynomial
                   of degree at most 2 in 2 variables, or a homogeneous
                   polynomial in of degree 2 in 3 variables.

                   If ``F`` is a matrix, then the output is the zero locus
                   of `(x,y,z) F (x,y,z)^t`.

                   If ``F`` is a list of coefficients, then it has
                   length 3 or 6 and gives the coefficients of
                   the monomials `x^2, y^2, z^2` or all 6 monomials
                   `x^2, xy, xz, y^2, yz, z^2` in lexicographic order.

                   If ``F`` is a list of 5 points in the plane, then the output
                   is a conic through those points.

    - ``unique`` -- Used only if ``F`` is a list of points in the plane.
      If the conic through the points is not unique, then
      raise ``ValueError`` if and only if ``unique`` is True

    OUTPUT:

    A plane projective conic curve defined by ``F`` over a field.

    EXAMPLES:

    Conic curves given by polynomials ::

        sage: X,Y,Z = QQ['X,Y,Z'].gens()
        sage: Conic(X^2 - X*Y + Y^2 - Z^2)
        Projective Conic Curve over Rational Field defined by X^2 - X*Y + Y^2 - Z^2
        sage: x,y = GF(7)['x,y'].gens()
        sage: Conic(x^2 - x + 2*y^2 - 3, 'U,V,W')
        Projective Conic Curve over Finite Field of size 7 defined by U^2 + 2*V^2 - U*W - 3*W^2

    Conic curves given by matrices ::

        sage: Conic(matrix(QQ, [[1, 2, 0], [4, 0, 0], [7, 0, 9]]), 'x,y,z')
        Projective Conic Curve over Rational Field defined by x^2 + 6*x*y + 7*x*z + 9*z^2

        sage: x,y,z = GF(11)['x,y,z'].gens()
        sage: C = Conic(x^2+y^2-2*z^2); C
        Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2
        sage: Conic(C.symmetric_matrix(), 'x,y,z')
        Projective Conic Curve over Finite Field of size 11 defined by x^2 + y^2 - 2*z^2

    Conics given by coefficients ::

        sage: Conic(QQ, [1,2,3])
        Projective Conic Curve over Rational Field defined by x^2 + 2*y^2 + 3*z^2
        sage: Conic(GF(7), [1,2,3,4,5,6], 'X')
        Projective Conic Curve over Finite Field of size 7 defined by X0^2 + 2*X0*X1 - 3*X1^2 + 3*X0*X2 - 2*X1*X2 - X2^2

    The conic through a set of points ::

        sage: C = Conic(QQ, [[10,2],[3,4],[-7,6],[7,8],[9,10]]); C
        Projective Conic Curve over Rational Field defined by x^2 + 13/4*x*y - 17/4*y^2 - 35/2*x*z + 91/4*y*z - 37/2*z^2
        sage: C.rational_point()
        (10 : 2 : 1)
        sage: C.point([3,4])
        (3 : 4 : 1)

        sage: a=AffineSpace(GF(13),2)
        sage: Conic([a([x,x^2]) for x in range(5)])
        Projective Conic Curve over Finite Field of size 13 defined by x^2 - y*z
    """
    if not (base_field is None or isinstance(base_field, IntegralDomain)):
        if names is None:
            names = F
        F = base_field
        base_field = None
    if isinstance(F, (list, tuple)):
        if len(F) == 1:
            return Conic(base_field, F[0], names)
        if names is None:
            names = 'x,y,z'
        if len(F) == 5:
            L = []
            for f in F:
                if isinstance(f, SchemeMorphism_point_affine):
                    C = Sequence(f, universe=base_field)
                    if len(C) != 2:
                        raise TypeError("points in F (=%s) must be planar" % F)
                    C.append(1)
                elif isinstance(f, SchemeMorphism_point_projective_field):
                    C = Sequence(f, universe=base_field)
                elif isinstance(f, (list, tuple)):
                    C = Sequence(f, universe=base_field)
                    if len(C) == 2:
                        C.append(1)
                else:
                    raise TypeError("F (=%s) must be a sequence of planar " \
                                      "points" % F)
                if len(C) != 3:
                    raise TypeError("points in F (=%s) must be planar" % F)
                P = C.universe()
                if not isinstance(P, IntegralDomain):
                    raise TypeError("coordinates of points in F (=%s) must " \
                                     "be in an integral domain" % F)
                L.append(
                    Sequence([
                        C[0]**2, C[0] * C[1], C[0] * C[2], C[1]**2,
                        C[1] * C[2], C[2]**2
                    ], P.fraction_field()))
            M = Matrix(L)
            if unique and M.rank() != 5:
                raise ValueError("points in F (=%s) do not define a unique " \
                                   "conic" % F)
            con = Conic(base_field, Sequence(M.right_kernel().gen()), names)
            con.point(F[0])
            return con
        F = Sequence(F, universe=base_field)
        base_field = F.universe().fraction_field()
        temp_ring = PolynomialRing(base_field, 3, names)
        (x, y, z) = temp_ring.gens()
        if len(F) == 3:
            return Conic(F[0] * x**2 + F[1] * y**2 + F[2] * z**2)
        if len(F) == 6:
            return Conic(F[0]*x**2 + F[1]*x*y + F[2]*x*z + F[3]*y**2 + \
                         F[4]*y*z + F[5]*z**2)
        raise TypeError("F (=%s) must be a sequence of 3 or 6" \
                         "coefficients" % F)
    if is_QuadraticForm(F):
        F = F.matrix()
    if is_Matrix(F) and F.is_square() and F.ncols() == 3:
        if names is None:
            names = 'x,y,z'
        temp_ring = PolynomialRing(F.base_ring(), 3, names)
        F = vector(temp_ring.gens()) * F * vector(temp_ring.gens())

    if not is_MPolynomial(F):
        raise TypeError("F (=%s) must be a three-variable polynomial or " \
                         "a sequence of points or coefficients" % F)

    if F.total_degree() != 2:
        raise TypeError("F (=%s) must have degree 2" % F)

    if base_field is None:
        base_field = F.base_ring()
    if not isinstance(base_field, IntegralDomain):
        raise ValueError("Base field (=%s) must be a field" % base_field)
    base_field = base_field.fraction_field()
    if names is None:
        names = F.parent().variable_names()
    pol_ring = PolynomialRing(base_field, 3, names)

    if F.parent().ngens() == 2:
        (x, y, z) = pol_ring.gens()
        F = pol_ring(F(x / z, y / z) * z**2)

    if F == 0:
        raise ValueError("F must be nonzero over base field %s" % base_field)

    if F.total_degree() != 2:
        raise TypeError("F (=%s) must have degree 2 over base field %s" % \
                          (F, base_field))

    if F.parent().ngens() == 3:
        P2 = ProjectiveSpace(2, base_field, names)
        if is_PrimeFiniteField(base_field):
            return ProjectiveConic_prime_finite_field(P2, F)
        if is_FiniteField(base_field):
            return ProjectiveConic_finite_field(P2, F)
        if is_RationalField(base_field):
            return ProjectiveConic_rational_field(P2, F)
        if is_NumberField(base_field):
            return ProjectiveConic_number_field(P2, F)
        if is_FractionField(base_field) and (is_PolynomialRing(
                base_field.ring()) or is_MPolynomialRing(base_field.ring())):
            return ProjectiveConic_rational_function_field(P2, F)

        return ProjectiveConic_field(P2, F)

    raise TypeError("Number of variables of F (=%s) must be 2 or 3" % F)
Exemplo n.º 10
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys,(list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        # We now arrange for all of our list entries to lie in the same ring
        # Fraction field case first
        fraction_field = False
        for poly in polys:
            P = poly.parent()
            if is_FractionField(P):
                fraction_field = True
                break
        if fraction_field:
            K = P.base_ring().fraction_field()
            # Replace base ring with its fraction field
            P = P.ring().change_ring(K).fraction_field()
            polys = [P(poly) for poly in polys]
        else:
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            quotient_ring = False
            for poly in polys:
                P = poly.parent()
                if is_QuotientRing(P):
                    quotient_ring = True
                    break
            if quotient_ring:
                polys = [P(poly).lift() for poly in polys]
            else:
                poly_ring = False
                for poly in polys:
                    P = poly.parent()
                    if is_PolynomialRing(P) or is_MPolynomialRing(P):
                        poly_ring = True
                        break
                if poly_ring:
                    polys = [P(poly) for poly in polys]

        if domain is None:
            f = polys[0]
            CR = f.parent()
            if CR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                CR = CR.ring()
            domain = AffineSpace(CR)

        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
Exemplo n.º 11
0
def mandelbrot_plot(f=None, **kwds):
    r"""
    Plot of the Mandelbrot set for a one parameter family of polynomial maps.

    The family `f_c(z)` must have parent ``R`` of the
    form ``R.<z,c> = CC[]``.

    REFERENCE:

    [Dev2005]_

    INPUT:

    - ``f`` -- map (optional - default: ``z^2 + c``), polynomial family used to
      plot the Mandelbrot set.

    - ``parameter`` -- variable (optional - default: ``c``), parameter variable
      used to plot the Mandelbrot set.

    - ``x_center`` -- double (optional - default: ``-1.0``), Real part of center
      point.

    - ``y_center`` -- double (optional - default: ``0.0``), Imaginary part of
      center point.

    - ``image_width`` -- double (optional - default: ``4.0``), width of image
      in the complex plane.

    - ``max_iteration`` -- long (optional - default: ``500``), maximum number of
      iterations the map ``f_c(z)``.

    - ``pixel_count`` -- long (optional - default: ``500``), side length of
      image in number of pixels.

    - ``base_color`` -- RGB color (optional - default: ``[40, 40, 40]``) color
      used to determine the coloring of set.

    - ``level_sep`` -- long (optional - default: 1) number of iterations
      between each color level.

    - ``number_of_colors`` -- long (optional - default: 30) number of colors
      used to plot image.

    - ``interact`` -- boolean (optional - default: ``False``), controls whether
      plot will have interactive functionality.

    OUTPUT:

    24-bit RGB image of the Mandelbrot set in the complex plane.

    EXAMPLES:

    ::

        sage: mandelbrot_plot()
        500x500px 24-bit RGB image

    ::

        sage: mandelbrot_plot(pixel_count=1000)
        1000x1000px 24-bit RGB image

    ::

        sage: mandelbrot_plot(x_center=-1.11, y_center=0.2283, image_width=1/128, # long time
        ....: max_iteration=2000, number_of_colors=500, base_color=[40, 100, 100])
        500x500px 24-bit RGB image

    To display an interactive plot of the Mandelbrot in the Notebook, set
    ``interact`` to ``True``. (This is only implemented for ``z^2 + c``)::

        sage: mandelbrot_plot(interact=True)
        interactive(children=(FloatSlider(value=0.0, description=u'Real center', max=1.0, min=-1.0, step=1e-05),
        FloatSlider(value=0.0, description=u'Imag center', max=1.0, min=-1.0, step=1e-05),
        FloatSlider(value=4.0, description=u'Width', max=4.0, min=1e-05, step=1e-05),
        IntSlider(value=500, description=u'Iterations', max=1000),
        IntSlider(value=500, description=u'Pixels', max=1000, min=10),
        IntSlider(value=1, description=u'Color sep', max=20, min=1),
        IntSlider(value=30, description=u'# Colors', min=1),
        ColorPicker(value='#ff6347', description=u'Base color'), Output()),
        _dom_classes=(u'widget-interact',))

    ::

        sage: mandelbrot_plot(interact=True, x_center=-0.75, y_center=0.25,
        ....: image_width=1/2, number_of_colors=75)
        interactive(children=(FloatSlider(value=-0.75, description=u'Real center', max=1.0, min=-1.0, step=1e-05),
        FloatSlider(value=0.25, description=u'Imag center', max=1.0, min=-1.0, step=1e-05),
        FloatSlider(value=0.5, description=u'Width', max=4.0, min=1e-05, step=1e-05),
        IntSlider(value=500, description=u'Iterations', max=1000),
        IntSlider(value=500, description=u'Pixels', max=1000, min=10),
        IntSlider(value=1, description=u'Color sep', max=20, min=1),
        IntSlider(value=75, description=u'# Colors', min=1),
        ColorPicker(value='#ff6347', description=u'Base color'), Output()),
        _dom_classes=(u'widget-interact',))

    Polynomial maps can be defined over a multivariate polynomial ring or a
    univariate polynomial ring tower::

        sage: R.<z,c> = CC[]
        sage: f = z^2 + c
        sage: mandelbrot_plot(f)
        500x500px 24-bit RGB image

    ::

        sage: B.<c> = CC[]
        sage: R.<z> = B[]
        sage: f = z^5 + c
        sage: mandelbrot_plot(f)
        500x500px 24-bit RGB image

    When the polynomial is defined over a multivariate polynomial ring it is
    necessary to specify the parameter variable (default parameter is ``c``)::

        sage: R.<a,b> = CC[]
        sage: f = a^2 + b^3
        sage: mandelbrot_plot(f, parameter=b)
        500x500px 24-bit RGB image

    Interact functionality is not implemented for general polynomial maps::

        sage: R.<z,c> = CC[]
        sage: f = z^3 + c
        sage: mandelbrot_plot(f, interact=True)
        Traceback (most recent call last):
        ...
        NotImplementedError: Interact only implemented for z^2 + c
    """
    parameter = kwds.pop("parameter", None)
    x_center = kwds.pop("x_center", 0.0)
    y_center = kwds.pop("y_center", 0.0)
    image_width = kwds.pop("image_width", 4.0)
    max_iteration = kwds.pop("max_iteration", None)
    pixel_count = kwds.pop("pixel_count", 500)
    level_sep = kwds.pop("level_sep", 1)
    number_of_colors = kwds.pop("number_of_colors", 30)
    interacts = kwds.pop("interact", False)
    base_color = kwds.pop("base_color", Color('tomato'))
    # Check if user specified maximum number of iterations
    given_iterations = True
    if max_iteration is None:
        # Set default to 500 for z^2 + c map
        max_iteration = 500
        given_iterations = False

    from ipywidgets.widgets import FloatSlider, IntSlider, ColorPicker, interact
    widgets = dict(
        x_center=FloatSlider(min=-1.0,
                             max=1.0,
                             step=EPS,
                             value=x_center,
                             description="Real center"),
        y_center=FloatSlider(min=-1.0,
                             max=1.0,
                             step=EPS,
                             value=y_center,
                             description="Imag center"),
        image_width=FloatSlider(min=EPS,
                                max=4.0,
                                step=EPS,
                                value=image_width,
                                description="Width"),
        max_iteration=IntSlider(min=0,
                                max=1000,
                                value=max_iteration,
                                description="Iterations"),
        pixel_count=IntSlider(min=10,
                              max=1000,
                              value=pixel_count,
                              description="Pixels"),
        level_sep=IntSlider(min=1,
                            max=20,
                            value=level_sep,
                            description="Color sep"),
        color_num=IntSlider(min=1,
                            max=100,
                            value=number_of_colors,
                            description="# Colors"),
        base_color=ColorPicker(value=Color(base_color).html_color(),
                               description="Base color"),
    )

    if f is None:
        # Quadratic map f = z^2 + c

        if interacts:
            return interact(**widgets).widget(fast_mandelbrot_plot)

        else:
            return fast_mandelbrot_plot(x_center, y_center, image_width,
                                        max_iteration, pixel_count, level_sep,
                                        number_of_colors, base_color)

    else:
        if parameter is None:
            c = var('c')
            parameter = c

        P = f.parent()

        if P.base_ring() is CC or P.base_ring() is CDF:
            if is_FractionField(P):
                raise NotImplementedError(
                    "coefficients must be polynomials in the parameter")
            gen_list = list(P.gens())
            parameter = gen_list.pop(gen_list.index(parameter))
            variable = gen_list.pop()

        elif P.base_ring().base_ring() is CC or P.base_ring().base_ring(
        ) is CDF:
            if is_FractionField(P.base_ring()):
                raise NotImplementedError(
                    "coefficients must be polynomials in the parameter")
            phi = P.flattening_morphism()
            f = phi(f)
            gen_list = list(f.parent().gens())
            parameter = gen_list.pop(gen_list.index(parameter))
            variable = gen_list.pop()

        elif P.base_ring() in FunctionFields():
            raise NotImplementedError(
                "coefficients must be polynomials in the parameter")

        else:
            raise ValueError("base ring must be a complex field")

        if f == variable**2 + parameter:
            # Quadratic map f = z^2 + c
            if interacts:
                return interact(**widgets).widget(fast_mandelbrot_plot)

            else:
                return fast_mandelbrot_plot(x_center, y_center, image_width,
                                            max_iteration, pixel_count,
                                            level_sep, number_of_colors,
                                            base_color)
        else:
            if interacts:
                raise NotImplementedError(
                    "Interact only implemented for z^2 + c")
            else:
                # Set default of max_iteration to 50 for general polynomial maps
                # This prevents the function from being very slow by default
                if not given_iterations:
                    max_iteration = 50

                # Mandelbrot of General Polynomial Map
                return polynomial_mandelbrot(f, parameter, x_center, y_center, \
                 image_width, max_iteration, pixel_count, level_sep, \
                 number_of_colors, base_color)
Exemplo n.º 12
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(
                    domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys, (list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        # We now arrange for all of our list entries to lie in the same ring
        # Fraction field case first
        fraction_field = False
        for poly in polys:
            P = poly.parent()
            if is_FractionField(P):
                fraction_field = True
                break
        if fraction_field:
            K = P.base_ring().fraction_field()
            # Replace base ring with its fraction field
            P = P.ring().change_ring(K).fraction_field()
            polys = [P(poly) for poly in polys]
        else:
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            quotient_ring = False
            for poly in polys:
                P = poly.parent()
                if is_QuotientRing(P):
                    quotient_ring = True
                    break
            if quotient_ring:
                polys = [P(poly).lift() for poly in polys]
            else:
                poly_ring = False
                for poly in polys:
                    P = poly.parent()
                    if is_PolynomialRing(P) or is_MPolynomialRing(P):
                        poly_ring = True
                        break
                if poly_ring:
                    polys = [P(poly) for poly in polys]

        if domain is None:
            f = polys[0]
            CR = f.parent()
            if CR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                CR = CR.ring()
            domain = AffineSpace(CR)

        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(
                domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
            return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
Exemplo n.º 13
0
    def __classcall_private__(cls, morphism_or_polys, domain=None):
        r"""
        Return the appropriate dynamical system on an affine scheme.

        TESTS::

            sage: A.<x> = AffineSpace(ZZ,1)
            sage: A1.<z> = AffineSpace(CC,1)
            sage: H = End(A1)
            sage: f2 = H([z^2+1])
            sage: f = DynamicalSystem_affine(f2, A)
            sage: f.domain() is A
            False

        ::

            sage: P1.<x,y> = ProjectiveSpace(QQ,1)
            sage: DynamicalSystem_affine([y, 2*x], domain=P1)
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme
            sage: H = End(P1)
            sage: DynamicalSystem_affine(H([y, 2*x]))
            Traceback (most recent call last):
            ...
            ValueError: "domain" must be an affine scheme

        ::

            sage: R.<x,y,z> = QQ[]
            sage: f = DynamicalSystem_affine([x+y+z, y*z])
            Traceback (most recent call last):
            ...
            ValueError: Number of polys does not match dimension of Affine Space of dimension 3 over Rational Field

        ::
            sage: A.<x,y> = AffineSpace(QQ,2)
            sage: f = DynamicalSystem_affine([CC.0*x^2, y^2], domain=A)
            Traceback (most recent call last):
            ...
            TypeError: coefficients of polynomial not in Rational Field
        """
        if isinstance(morphism_or_polys, SchemeMorphism_polynomial):
            morphism = morphism_or_polys
            R = morphism.base_ring()
            polys = list(morphism)
            domain = morphism.domain()
            if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
                raise ValueError('"domain" must be an affine scheme')
            if domain != morphism_or_polys.codomain():
                raise ValueError('domain and codomain do not agree')
            if R not in Fields():
                return typecall(cls, polys, domain)
            if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
            return DynamicalSystem_affine_field(polys, domain)
        elif isinstance(morphism_or_polys,(list, tuple)):
            polys = list(morphism_or_polys)
        else:
            polys = [morphism_or_polys]

        PR = get_coercion_model().common_parent(*polys)         
        fraction_field = any(is_FractionField(poly.parent()) for poly in polys)
        if fraction_field:
            K = PR.base_ring().fraction_field()
            # Replace base ring with its fraction field
            PR = PR.ring().change_ring(K).fraction_field()
            polys = [PR(poly) for poly in polys]
        else:
            quotient_ring = any(is_QuotientRing(poly.parent()) for poly in polys)
            # If any of the list entries lies in a quotient ring, we try
            # to lift all entries to a common polynomial ring.
            if quotient_ring:
                polys = [PR(poly).lift() for poly in polys]
            else:
                polys = [PR(poly) for poly in polys]
        if domain is None:
            if PR is SR:
                raise TypeError("Symbolic Ring cannot be the base ring")
            if fraction_field:
                PR = PR.ring()
            domain = AffineSpace(PR)
        else:
            # Check if we can coerce the given polynomials over the given domain 
            PR = domain.ambient_space().coordinate_ring()
            try:
                if fraction_field:
                    PR = PR.fraction_field()
                polys = [PR(poly) for poly in polys]
            except TypeError:
                raise TypeError('coefficients of polynomial not in {}'.format(domain.base_ring()))
        if len(polys) != domain.ambient_space().coordinate_ring().ngens():
            raise ValueError('Number of polys does not match dimension of {}'.format(domain))
        R = domain.base_ring()
        if R is SR:
            raise TypeError("Symbolic Ring cannot be the base ring")
        if not is_AffineSpace(domain) and not isinstance(domain, AlgebraicScheme_subscheme_affine):
            raise ValueError('"domain" must be an affine scheme')

        if R not in Fields():
            return typecall(cls, polys, domain)
        if is_FiniteField(R):
                return DynamicalSystem_affine_finite_field(polys, domain)
        return DynamicalSystem_affine_field(polys, domain)
 def _reduce_conic(self):
     r"""
     Return the reduced form of the conic, i.e. a conic with base field
     `K=F(t)` and coefficients `a,b,c` such that `a,b,c \in F[t]`,
     `\gcd(a,b)=\gcd(b,c)=\gcd(c,a)=1` and `abc` is square-free.
     
     Assumes `self` is in diagonal form.
     
     OUTPUT:
     
     A tuple (coefficients, multipliers), the coefficients of the conic
     in reduced form and multipliers `\lambda, \mu, \nu \in F(t)^*` such
     that `(x,y,z) \in F(t)` is a solution of the reduced conic if and only
     if `(\lambda x, \mu y, \nu z)` is a solution of `self`.
     
     ALGORITMH:
     
     The algorithm used is the algorithm ReduceConic in [HC2006]_.
     
     EXAMPLES::
     
         sage: K.<t> = FractionField(PolynomialRing(QQ, 't'))
         sage: C = Conic(K, [t^2-2, 2*t^3, -2*t^3-13*t^2-2*t+18])
         sage: C._reduce_conic()
         ([t^2 - 2, 2*t, -2*t^3 - 13*t^2 - 2*t + 18], [t, 1, t])
     """
     
     # start with removing fractions
     coeff = [self.coefficients()[0], self.coefficients()[3],
             self.coefficients()[5]]
     coeff = lcm(lcm(coeff[0].denominator(), coeff[1].denominator()),
             coeff[2].denominator()) * vector(coeff)
     # go to base ring of fraction field
     coeff = [self.base().base()(x) for x in coeff]
     coeff = vector(coeff) / gcd(coeff)
     # remove common divisors
     labda = mu = nu = 1
     g1 = g2 = g3 = 0
     ca, cb, cc = coeff
     while g1 != 1 or g2 != 1 or g3 != 1:
         g1 = gcd(ca,cb); ca = ca/g1; cb = cb/g1; cc = cc*g1; nu = g1*nu
         g2 = gcd(ca,cc); ca = ca/g2; cc = cc/g2; cb = cb*g2; mu = g2*mu
         g3 = gcd(cb,cc); cb = cb/g3; cc = cc/g3; ca = ca*g3;
         labda = g3*labda
     coeff = [ca, cb, cc]
     multipliers = [labda, mu, nu]
     
     # remove squares
     for i, x in enumerate(coeff):
         if is_FractionField(x.parent()):
             # go to base ring of fraction field
             x = self.base().base()(x)
         
         try:
             decom = x.squarefree_decomposition()
         except (NotImplementedError, AttributeError):
             decom = x.factor()
         x = decom.unit(); x2 = 1
         for factor in decom:
             if factor[1] > 1:
                 if factor[1] % 2 == 0:
                     x2 = x2 * factor[0] ** (factor[1] / 2)
                 else:
                     x = x * factor[0]
                     x2 = x2 * factor[0] ** ((factor[1]-1) / 2)
             else:
                 x = x * factor[0]
         for j, y in enumerate(multipliers):
             if j != i:
                 multipliers[j] = y * x2
         coeff[i] = self.base_ring().base().coerce(x);
     
     return (coeff, multipliers)