Exemple #1
0
def followstrand(f, x0, x1, y0a):
    """
    Return a piecewise linear aproximation of the homotopy continuation of the root y0a
    from x0 to x1
    
    INPUT:
    
    - ``f`` -- a polynomial in two variables
    - ``x0`` -- a complex value, where the homotopy starts
    - ``x1`` -- a complex value, where the homotopy ends
    - ``y0a`` -- an approximate solution of the polynomial $F(y)=f(x_0,y)$
        
    OUTPUT:
    
    A list of values (t, ytr, yti) such that:
        - ``t`` is a real number between zero and one
        - $f(t\cdot x_1+(1-t)\cdot x_0, y_{tr} + I\cdot y_{ti})$ is zero (or a good enough aproximation)
        - the piecewise linear path determined by the points has a tubular
          neighborhood  where the actual homotopy continuation path lies, and
          no other root intersects it.
          
    EXAMPLES::
    
        sage: R.<x,y> = QQ[]
        sage: f = x^2 + y^3
        sage: x0 = CC(1, 0)
        sage: x1 = CC(1, 0.5)
        sage: followstrand(f, x0, x1, -1.0) # optional 
        [(0.0, -1.0, 0.0),
        (0.063125, -1.0001106593601545, -0.02104011456212618),
        (0.12230468750000001, -1.0004151100003031, -0.04075695242737829),
        (0.17778564453125, -1.0008762007617709, -0.059227299979315154),
        (0.28181243896484376, -1.0021948141328698, -0.09380038023464156),
        (0.3728358840942383, -1.0038270754728402, -0.123962953123039),
        (0.4524813985824585, -1.005613540368227, -0.15026634875747985),
        (0.5221712237596512, -1.0074443351354077, -0.17320066690539515),
        (0.5831498207896948, -1.009246118007067, -0.1931978258913501),
        (0.636506093190983, -1.0109719597443307, -0.21063630045261386),
        (0.6831928315421101, -1.0125937110987449, -0.2258465242053158),
        (0.7648946236565826, -1.0156754074572174, -0.2523480191006915),
        (0.8261709677424369, -1.0181837235093538, -0.2721208327884435),
        (0.8721282258068277, -1.0201720738092597, -0.2868892148703381),
        (0.9410641129034139, -1.0233210275568283, -0.3089391941950436),
        (1.0, -1.026166099551513, -0.3276894025360433)]
        
    """
    G = f.change_ring(QQbar).change_ring(CIF)
    (x, y) = G.variables()
    g = G.subs({x: (1 - x) * CIF(x0) + x * CIF(x1)})
    coefs = []
    deg = g.total_degree()
    for d in range(deg + 1):
        for i in range(d + 1):
            c = CIF(g.coefficient({x: d - i, y: i}))
            cr = c.real()
            ci = c.imag()
            coefs += list(cr.endpoints())
            coefs += list(ci.endpoints())
    yr = CC(y0a).real()
    yi = CC(y0a).imag()
    points = contpath(deg, coefs, yr, yi)
    return points
Exemple #2
0
        def __getitem__(self, arg):
            """
            Extend this ring by one or several elements to create a polynomial
            ring, a power series ring, or an algebraic extension.

            This is a convenience method intended primarily for interactive
            use.

            .. SEEALSO::

                :func:`~sage.rings.polynomial.polynomial_ring_constructor.PolynomialRing`,
                :func:`~sage.rings.power_series_ring.PowerSeriesRing`,
                :meth:`~sage.rings.ring.Ring.extension`,
                :meth:`sage.rings.integer_ring.IntegerRing_class.__getitem__`,
                :meth:`sage.rings.matrix_space.MatrixSpace.__getitem__`,
                :meth:`sage.structure.parent.Parent.__getitem__`

            EXAMPLES:

            We create several polynomial rings::

                sage: ZZ['x']
                Univariate Polynomial Ring in x over Integer Ring
                sage: QQ['x']
                Univariate Polynomial Ring in x over Rational Field
                sage: GF(17)['abc']
                Univariate Polynomial Ring in abc over Finite Field of size 17
                sage: GF(17)['a,b,c']
                Multivariate Polynomial Ring in a, b, c over Finite Field of size 17
                sage: GF(17)['a']['b']
                Univariate Polynomial Ring in b over Univariate Polynomial Ring in a over Finite Field of size 17

            We can create skew polynomial rings::

                sage: k.<t> = GF(5^3)
                sage: Frob = k.frobenius_endomorphism()
                sage: k['x',Frob]
                Skew Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5

            We can also create power series rings by using double brackets::

                sage: QQ[['t']]
                Power Series Ring in t over Rational Field
                sage: ZZ[['W']]
                Power Series Ring in W over Integer Ring

                sage: ZZ[['x,y,z']]
                Multivariate Power Series Ring in x, y, z over Integer Ring
                sage: ZZ[['x','T']]
                Multivariate Power Series Ring in x, T over Integer Ring

            Use :func:`~sage.rings.fraction_field.Frac` or
            :meth:`~sage.rings.ring.CommutativeRing.fraction_field` to obtain
            the fields of rational functions and Laurent series::

                sage: Frac(QQ['t'])
                Fraction Field of Univariate Polynomial Ring in t over Rational Field
                sage: Frac(QQ[['t']])
                Laurent Series Ring in t over Rational Field
                sage: QQ[['t']].fraction_field()
                Laurent Series Ring in t over Rational Field

            Note that the same syntax can be used to create number fields::

                sage: QQ[I]
                Number Field in I with defining polynomial x^2 + 1
                sage: QQ[I].coerce_embedding()
                Generic morphism:
                 From: Number Field in I with defining polynomial x^2 + 1
                 To:   Complex Lazy Field
                 Defn: I -> 1*I

            ::

                sage: QQ[sqrt(2)]
                Number Field in sqrt2 with defining polynomial x^2 - 2
                sage: QQ[sqrt(2)].coerce_embedding()
                Generic morphism:
                 From: Number Field in sqrt2 with defining polynomial x^2 - 2
                 To:   Real Lazy Field
                 Defn: sqrt2 -> 1.414213562373095?

            ::

                sage: QQ[sqrt(2),sqrt(3)]
                Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field

            and orders in number fields::

                sage: ZZ[I]
                Order in Number Field in I with defining polynomial x^2 + 1
                sage: ZZ[sqrt(5)]
                Order in Number Field in sqrt5 with defining polynomial x^2 - 5
                sage: ZZ[sqrt(2)+sqrt(3)]
                Order in Number Field in a with defining polynomial x^4 - 10*x^2 + 1

            Embeddings are found for simple extensions (when that makes sense)::

                sage: QQi.<i> = QuadraticField(-1, 'i')
                sage: QQ[i].coerce_embedding()
                Generic morphism:
                  From: Number Field in i with defining polynomial x^2 + 1
                  To:   Complex Lazy Field
                  Defn: i -> 1*I

            TESTS:

            A few corner cases::

                sage: QQ[()]
                Multivariate Polynomial Ring in no variables over Rational Field

                sage: QQ[[]]
                Traceback (most recent call last):
                ...
                TypeError: power series rings must have at least one variable

            These kind of expressions do not work::

                sage: QQ['a,b','c']
                Traceback (most recent call last):
                ...
                ValueError: variable name 'a,b' is not alphanumeric
                sage: QQ[['a,b','c']]
                Traceback (most recent call last):
                ...
                ValueError: variable name 'a,b' is not alphanumeric

                sage: QQ[[['x']]]
                Traceback (most recent call last):
                ...
                TypeError: expected R[...] or R[[...]], not R[[[...]]]

            Extension towers are built as follows and use distinct generator names::

                sage: K = QQ[2^(1/3), 2^(1/2), 3^(1/3)]
                sage: K
                Number Field in a with defining polynomial x^3 - 2 over its base field
                sage: K.base_field()
                Number Field in sqrt2 with defining polynomial x^2 - 2 over its base field
                sage: K.base_field().base_field()
                Number Field in b with defining polynomial x^3 - 3

            Embeddings::

                sage: QQ[I](I.pyobject())
                I
                sage: a = 10^100; expr = (2*a + sqrt(2))/(2*a^2-1)
                sage: QQ[expr].coerce_embedding() is None
                False
                sage: QQ[sqrt(5)].gen() > 0
                True
                sage: expr = sqrt(2) + I*(cos(pi/4, hold=True) - sqrt(2)/2)
                sage: QQ[expr].coerce_embedding()
                Generic morphism:
                  From: Number Field in a with defining polynomial x^2 - 2
                  To:   Real Lazy Field
                  Defn: a -> 1.414213562373095?
            """
            def normalize_arg(arg):
                if isinstance(arg, (tuple, list)):
                    # Allowing arbitrary iterables would create confusion, but we
                    # may want to support a few more.
                    return tuple(arg)
                elif isinstance(arg, str):
                    return tuple(arg.split(','))
                else:
                    return (arg,)

            # 1. If arg is a list, try to return a power series ring.

            if isinstance(arg, list):
                if arg == []:
                    raise TypeError("power series rings must have at least one variable")
                elif len(arg) == 1:
                    # R[["a,b"]], R[[(a,b)]]...
                    if isinstance(arg[0], list):
                        raise TypeError("expected R[...] or R[[...]], not R[[[...]]]")
                    elts = normalize_arg(arg[0])
                else:
                    elts = normalize_arg(arg)
                from sage.rings.power_series_ring import PowerSeriesRing
                return PowerSeriesRing(self, elts)

            if isinstance(arg, tuple):
                from sage.categories.morphism import Morphism
                if len(arg) == 2 and isinstance(arg[1], Morphism):
                   from sage.rings.polynomial.skew_polynomial_ring_constructor import SkewPolynomialRing
                   return SkewPolynomialRing(self, arg[1], names=arg[0])

            # 2. Otherwise, if all specified elements are algebraic, try to
            #    return an algebraic extension

            elts = normalize_arg(arg)

            try:
                minpolys = [a.minpoly() for a in elts]
            except (AttributeError, NotImplementedError, ValueError, TypeError):
                minpolys = None

            if minpolys:
                # how to pass in names?
                names = tuple(_gen_names(elts))
                if len(elts) == 1:
                    from sage.rings.all import CIF, CLF, RIF, RLF
                    elt = elts[0]
                    try:
                        iv = CIF(elt)
                    except (TypeError, ValueError):
                        emb = None
                    else:
                        # First try creating an ANRoot manually, because
                        # extension(..., embedding=CLF(expr)) (or
                        # ...QQbar(expr)) would normalize the expression in
                        # QQbar, which currently is VERY slow in many cases.
                        # This may fail when minpoly has close roots or elt is
                        # a complicated symbolic expression.
                        # TODO: Rewrite using #19362 and/or #17886 and/or
                        # #15600 once those issues are solved.
                        from sage.rings.qqbar import AlgebraicNumber, ANRoot
                        try:
                            elt = AlgebraicNumber(ANRoot(minpolys[0], iv))
                        except ValueError:
                            pass
                        # Force a real embedding when possible, to get the
                        # right ordered ring structure.
                        if (iv.imag().is_zero() or iv.imag().contains_zero()
                                                   and elt.imag().is_zero()):
                            emb = RLF(elt)
                        else:
                            emb = CLF(elt)
                        return self.extension(minpolys[0], names[0], embedding=emb)
                try:
                    # Doing the extension all at once is best, if possible...
                    return self.extension(minpolys, names)
                except (TypeError, ValueError):
                    # ...but we can also construct it iteratively
                    return reduce(lambda R, ext: R.extension(*ext), zip(minpolys, names), self)

            # 2. Otherwise, try to return a polynomial ring

            from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
            return PolynomialRing(self, elts)
Exemple #3
0
def followstrand(f, x0, x1, y0a):
    """
    Return a piecewise linear aproximation of the homotopy continuation of the root y0a
    from x0 to x1
    
    INPUT:
    
    - ``f`` -- a polynomial in two variables
    - ``x0`` -- a complex value, where the homotopy starts
    - ``x1`` -- a complex value, where the homotopy ends
    - ``y0a`` -- an approximate solution of the polynomial $F(y)=f(x_0,y)$
        
    OUTPUT:
    
    A list of values (t, ytr, yti) such that:
        - ``t`` is a real number between zero and one
        - $f(t\cdot x_1+(1-t)\cdot x_0, y_{tr} + I\cdot y_{ti})$ is zero (or a good enough aproximation)
        - the piecewise linear path determined by the points has a tubular
          neighborhood  where the actual homotopy continuation path lies, and
          no other root intersects it.
          
    EXAMPLES::
    
        sage: R.<x,y> = QQ[]
        sage: f = x^2 + y^3
        sage: x0 = CC(1, 0)
        sage: x1 = CC(1, 0.5)
        sage: followstrand(f, x0, x1, -1.0) # optional 
        [(0.0, -1.0, 0.0),
        (0.063125, -1.0001106593601545, -0.02104011456212618),
        (0.12230468750000001, -1.0004151100003031, -0.04075695242737829),
        (0.17778564453125, -1.0008762007617709, -0.059227299979315154),
        (0.28181243896484376, -1.0021948141328698, -0.09380038023464156),
        (0.3728358840942383, -1.0038270754728402, -0.123962953123039),
        (0.4524813985824585, -1.005613540368227, -0.15026634875747985),
        (0.5221712237596512, -1.0074443351354077, -0.17320066690539515),
        (0.5831498207896948, -1.009246118007067, -0.1931978258913501),
        (0.636506093190983, -1.0109719597443307, -0.21063630045261386),
        (0.6831928315421101, -1.0125937110987449, -0.2258465242053158),
        (0.7648946236565826, -1.0156754074572174, -0.2523480191006915),
        (0.8261709677424369, -1.0181837235093538, -0.2721208327884435),
        (0.8721282258068277, -1.0201720738092597, -0.2868892148703381),
        (0.9410641129034139, -1.0233210275568283, -0.3089391941950436),
        (1.0, -1.026166099551513, -0.3276894025360433)]
        
    """
    G = f.change_ring(QQbar).change_ring(CIF)
    (x, y) = G.variables()
    g = G.subs({x: (1-x)*CIF(x0) + x*CIF(x1)})
    coefs = []
    deg = g.total_degree()
    for d in range(deg + 1):
        for i in range(d + 1):
            c = CIF(g.coefficient({x: d-i, y: i}))
            cr = c.real()
            ci = c.imag()
            coefs += list(cr.endpoints())
            coefs += list(ci.endpoints())
    yr = CC(y0a).real()
    yi = CC(y0a).imag()
    points = contpath(deg, coefs, yr, yi)
    return points