示例#1
0
def is_torsion_same(p, K, chi, B=30, uniform=False):
    """Returns true if the minus part of J0(p) does not gain new torsion when
    base changing to K"""
    M = ModularSymbols(p)
    S = M.cuspidal_subspace()
    T = S.atkin_lehner_operator()
    S_min = (T + parent(T)(1)).kernel()
    J0_min = S_min.abelian_variety()

    d = K.degree()

    if uniform:
        frob_poly_data = [(q, d) for q in prime_range(d + 2, B) if q != p]
    else:
        frob_poly_data = [(q, 1) if chi(q) == 1 else (q, d)
                          for q in prime_range(d + 2, B) if gcd(q, p) == 1]

    point_counts = []

    for q, i in frob_poly_data:
        frob_pol_q = J0_min.frobenius_polynomial(q)
        frob_mat = companion_matrix(frob_pol_q)
        point_counts.append((frob_mat**i).charpoly()(1))

    # Recall that the rational torsion on J0(p) is entirely contained in
    # the minus part (theorem of Mazur), so checking no-growth of torsion
    # in minus part is done simply as follows

    return J0(p).rational_torsion_order(proof=False) == gcd(point_counts)
示例#2
0
    def ff(v, offset, start=0):
        """Fast-forward through vector `v` in ``offset`` sized steps starting at ``start``

        :param v: vector
        :param offset: increment in each step
        :param start: start offset

        """
        p = parent(v)
        return p(list(v)[start::offset])
示例#3
0
def balance(e, q=None):
    """
    Return a representation of `e` with elements balanced between `-q/2` and `q/2`

    :param e: a vector, polynomial or scalar
    :param q: optional modulus, if not present this function tries to recover it from `e`

    :returns: a vector, polynomial or scalar over/in the integers
    """
    try:
        p = parent(e).change_ring(ZZ)
        return p([balance(e_, q=q) for e_ in e])
    except (TypeError, AttributeError):
        if q is None:
            try:
                q = parent(e).order()
            except AttributeError:
                q = parent(e).base_ring().order()
        e = ZZ(e)
        e = e % q
        return ZZ(e-q) if e>q//2 else ZZ(e)
示例#4
0
    def _grid2motion(self, NAC_coloring, data, check):
        self._par_type = 'symbolic'
        alpha = var('alpha')
        self._field = parent(alpha)
        self._parameter = alpha
        self._active_NACs = [NAC_coloring]
        zigzag = data['zigzag']
        grid_coor = NAC_coloring.grid_coordinates(ordered_red=data['red'], ordered_blue=data['blue'])
        self._same_lengths = []
        for i, edges in enumerate([NAC_coloring.blue_edges(), NAC_coloring.red_edges()]):
            partition = [[list(edges[0])]]
            for u, v in edges[1:]:
                appended = False
                for part in partition:
                    u2, v2 = part[0]
                    if Set([grid_coor[u][i], grid_coor[v][i]]) == Set([grid_coor[u2][i], grid_coor[v2][i]]):
                        part.append([u, v])
                        appended = True
                        break
                if not appended:
                    partition.append([[u, v]])
            self._same_lengths += partition

        if check and len(Set(grid_coor.values())) != self._graph.num_verts():
            raise exceptions.ValueError('The NAC-coloring does not yield a proper flexible labeling.')
        if zigzag:
            if type(zigzag) == list and len(zigzag) == 2:
                a = [vector(c) for c in zigzag[0]]
                b = [vector(c) for c in zigzag[1]]
            else:
                m = max([k for _, k in grid_coor.values()])
                n = max([k for k, _ in grid_coor.values()])
                a = [vector([0.3*((-1)**i-1)+0.3*sin(i), i]) for i in range(0,m+1)]
                b = [vector([j, 0.3*((-1)**j-1)+0.3*sin(j)]) for j in range(0,n+1)]
        else:
            m = max([k for _, k in grid_coor.values()])
            n = max([k for k, _ in grid_coor.values()])
            a = [vector([0, i]) for i in range(0,m+1)]
            b = [vector([j, 0]) for j in range(0,n+1)]

        rotation = matrix([[cos(alpha), sin(alpha)], [-sin(alpha), cos(alpha)]])
        positions = {}
        for v in self._graph.vertices():
            positions[v] = rotation * a[grid_coor[v][1]] + b[grid_coor[v][0]]
        self._parametrization = positions
示例#5
0
    def _parametrization2motion(self, active_NACs, data,  check):
        self._parametrization = data['parametrization']
        element = (sum([self._parametrization[v][0]**Integer(2) for v in self._parametrization])
                    + sum([self._parametrization[v][1]**Integer(2) for v in self._parametrization]))
        self._field = parent(element)
        for v in self._parametrization:
            self._parametrization[v] = vector([self._field(x) for x in self._parametrization[v]])
        if data['par_type'] == 'symbolic':
            self._par_type = 'symbolic'
            if len(element.variables()) != 1:
                raise exceptions.ValueError('The parametrization has to have one parameter (' + str(len(element.variables())) + ' found).')
            self._parameter = element.variables()[0]
        if data['par_type'] == 'rational':
            self._par_type = 'rational'
            self._parameter = self._field.gen()
        if check:
            self._edges_with_same_length()

        self._active_NACs = active_NACs
示例#6
0
def is_rank_of_twist_zero(p, chi):
    """Returns true if the rank of the twist of the minus part of X_0(p)
    by the character chi is zero"""
    ML = ModularSymbols(p, base_ring=chi.base_ring())
    SL = ML.cuspidal_subspace()
    TL = SL.atkin_lehner_operator()
    S_min_L = (TL + parent(TL)(1)).kernel()

    for S in S_min_L.decomposition():
        my_map = S.rational_period_mapping()
        w = ML([0, oo])
        wmap = my_map(w)
        if wmap == 0:
            return False
        tw = ML.twisted_winding_element(0, chi)
        twmap = my_map(tw)
        if twmap == 0:
            return False

    return True
示例#7
0
def test_masur_veech_edge_weight():
    from surface_dynamics.topological_recursion import MasurVeechTR
    from sage.all import PolynomialRing

    R = PolynomialRing(QQ, 't')
    t = R.gen()
    MV = MasurVeechTR(edge_weight=t)
    for g, n, value in [
        (0, 3, R.one()), (0, 4, t), (0, 5, QQ((4, 9)) * t + QQ((5, 9)) * t**2),
        (0, 6, QQ((8, 27)) * t + QQ((4, 9)) * t**2 + QQ((7, 27)) * t**3),
        (1, 1, t), (1, 2, QQ((5, 9)) * t + QQ((4, 9)) * t**2),
        (1, 3, QQ((4, 9)) * t + QQ((13, 33)) * t**2 + QQ((16, 99)) * t**3),
        (2, 1, QQ((76, 261)) * t + QQ((125, 261)) * t**2 + QQ(
            (440, 2349)) * t**3 + QQ((100, 2349)) * t**4),
        (2, 2, QQ((296, 1011)) * t + QQ((19748, 45495)) * t**2 + QQ(
            (9127, 45495)) * t**3 + QQ((560, 9099)) * t**4 + QQ(
                (100, 9099)) * t**5)
    ]:
        p = MV.F(g, n, (0, ) * n)
        assert parent(p) is R
        p /= p(1)
        assert p == value, (g, n, p, value)
    def _element_constructor_(self, x, e=1):
        r"""Construct a Puiseux series from `x`.

        INPUT:

        - ``x`` -- an object that can be converted into a Puiseux series in (x-a)

        - ``a`` -- (default: 0) the series is in powers of (var - a)

        - ``e`` -- (default: 1) the ramification index of the series
        """
        P = parent(x)

        # 1. x is a Puiseux series belonging to this ring
        if isinstance(x, self.element_class) and P is self:
            return x
        # 2. x is a Puiseux series but not an element of this ring. the laurent
        #    part should be coercible to the laurent series ring of self
        elif isinstance(x, self.element_class):
            l = self.laurent_series_ring()(x.laurent_part)
            e = x.ramification_index
        # 3. x is a member of the base ring then convert x to a laurent series
        #    and set the ramificaiton index of the Puiseux series to 1.
        elif P is self.base_ring():
            l = self.laurent_series_ring()(x)
            e = 1
        # 4. x is a Laurent or power series with the same base ring
        elif ((is_LaurentSeries(x) or is_PowerSeries(x))
              and P is self.base_ring()):
            l = self.laurent_series_ring()(x)
        # 5. everything else: try to coerce to laurent series ring
        else:
            l = self.laurent_series_ring()(x)
            e = 1

        return self.element_class(self, l, e=e)
    def _element_constructor_(self, x, e=1):
        r"""Construct a Puiseux series from `x`.

        INPUT:

        - ``x`` -- an object that can be converted into a Puiseux series in (x-a)

        - ``a`` -- (default: 0) the series is in powers of (var - a)

        - ``e`` -- (default: 1) the ramification index of the series
        """
        P = parent(x)

        # 1. x is a Puiseux series belonging to this ring
        if isinstance(x, self.element_class) and P is self:
            return x
        # 2. x is a Puiseux series but not an element of this ring. the laurent
        #    part should be coercible to the laurent series ring of self
        elif isinstance(x, self.element_class):
            l = self.laurent_series_ring()(x.laurent_part)
            e = x.ramification_index
        # 3. x is a member of the base ring then convert x to a laurent series
        #    and set the ramificaiton index of the Puiseux series to 1.
        elif P is self.base_ring():
            l = self.laurent_series_ring()(x)
            e = 1
        # 4. x is a Laurent or power series with the same base ring
        elif ((is_LaurentSeries(x) or is_PowerSeries(x))
              and P is self.base_ring()):
            l = self.laurent_series_ring()(x)
        # 5. everything else: try to coerce to laurent series ring
        else:
            l = self.laurent_series_ring()(x)
            e = 1

        return self.element_class(self, l, e=e)
示例#10
0
def automatic_control(control, var=None):
    """
    Guesses the desired interact control from the syntax of the parameter.
    
    :arg control: Parameter value.
    
    :returns: An InteractControl object.
    :rtype: InteractControl
    
    
    """
    from numbers import Number
    from types import GeneratorType
    label = None
    default_value = 0

    # For backwards compatibility, we check to see if
    # auto_update=False as passed in. If so, we set up an
    # UpdateButton.  This should be deprecated.

    if var=="auto_update" and control is False:
        return UpdateButton()
    
    # Checks for interact controls that are verbosely defined
    if isinstance(control, InteractControl):
        return control
    
    # Checks for labels and control values
    for _ in range(2):
        if isinstance(control, tuple) and len(control) == 2 and isinstance(control[0], str):
            label, control = control
        if isinstance(control, tuple) and len(control) == 2 and isinstance(control[1], (tuple, list, GeneratorType)):
            default_value, control = control

    if isinstance(control, str):
        C = InputBox(default = control, label = label)
    elif isinstance(control, bool):
        C = Checkbox(default = control, label = label, raw = True)
    elif isinstance(control, Number):
        C = InputBox(default = control, label = label, raw = True)
    elif isinstance(control, list):
        if len(control)==1:
            if isinstance(control[0], (list,tuple)) and len(control[0])==2:
                buttonvalue, buttontext=control[0]
            else:
                buttonvalue, buttontext=control[0],str(control[0])
            C = Button(value=buttonvalue, text=buttontext, default=buttonvalue, label=label)
        else:
            if len(control) <= 5:
                selectortype = "button"
            else:
                selectortype = "list"
            C = Selector(selector_type = selectortype, default = control[default_value], label = label, values = control)
    elif isinstance(control, GeneratorType):
        values=take(10000,control)
        C = DiscreteSlider(default = values[default_value], values = values, label = label)
    elif isinstance (control, tuple):
        if len(control) == 2:
            C = ContinuousSlider(default = default_value, interval = (control[0], control[1]), label = label)
        elif len(control) == 3:
            C = ContinuousSlider(default = default_value, interval = (control[0], control[1]), stepsize = control[2], label = label)
        else:
            values=list(control)
            C = DiscreteSlider(default = values[default_value], values = values, label = label)
    else:
        C = InputBox(default = control, label=label, raw = True)

        if CONFIG.EMBEDDED_MODE["sage_mode"] and CONFIG.EMBEDDED_MODE["enable_sage"]:
            from sagenb.misc.misc import Color
            from sage.structure.all import is_Vector, is_Matrix
            from sage.all import parent
            if is_Matrix(control):
                nrows = control.nrows()
                ncols = control.ncols()
                default_value = control.list()
                default_value = [[default_value[j * ncols + i] for i in range(ncols)] for j in range(nrows)]
                C = InputGrid(nrows = nrows, ncols = ncols, label = label, 
                              default = default_value, adapter=lambda x, globs: parent(control)(x))
            elif is_Vector(control):
                default_value = [control.list()]
                nrows = 1
                ncols = len(control)
                C = InputGrid(nrows = nrows, ncols = ncols, label = label, 
                              default = default_value, adapter=lambda x, globs: parent(control)(x[0]))
            elif isinstance(control, Color):
                C = ColorSelector(default = control, label = label)
    
    return C
示例#11
0
def automatic_control(control, var=None):
    """
    Guesses the desired interact control from the syntax of the parameter.
    
    :arg control: Parameter value.
    
    :returns: An InteractControl object.
    :rtype: InteractControl
    
    
    """
    from numbers import Number
    from types import GeneratorType
    label = None
    default_value = 0

    # For backwards compatibility, we check to see if
    # auto_update=False as passed in. If so, we set up an
    # UpdateButton.  This should be deprecated.

    if var=="auto_update" and control is False:
        return UpdateButton()
    
    # Checks for interact controls that are verbosely defined
    if isinstance(control, InteractControl):
        return control
    
    # Checks for labels and control values
    for _ in range(2):
        if isinstance(control, tuple) and len(control) == 2 and isinstance(control[0], str):
            label, control = control
        if isinstance(control, tuple) and len(control) == 2 and isinstance(control[1], (tuple, list, GeneratorType)):
            default_value, control = control

    if isinstance(control, basestring):
        C = InputBox(default = control, label = label, evaluate=False)
    elif isinstance(control, bool):
        C = Checkbox(default = control, label = label, raw = True)
    elif isinstance(control, list):
        if len(control)==1:
            if isinstance(control[0], (list,tuple)) and len(control[0])==2:
                buttonvalue, buttontext=control[0]
            else:
                buttonvalue, buttontext=control[0],str(control[0])
            C = Button(value=buttonvalue, text=buttontext, default=buttonvalue, label=label)
        else:
            if len(control) <= 5:
                selectortype = "button"
            else:
                selectortype = "list"
            C = Selector(selector_type = selectortype, default = default_value, label = label, values = control)
    elif isinstance(control, GeneratorType):
        values=take(10000,control)
        C = DiscreteSlider(default = default_value, values = values, label = label)
    elif isinstance (control, tuple):
        if len(control) == 2:
            C = ContinuousSlider(default = default_value, interval = (control[0], control[1]), label = label)
        elif len(control) == 3:
            C = ContinuousSlider(default = default_value, interval = (control[0], control[1]), stepsize = control[2], label = label)
        else:
            values=list(control)
            C = DiscreteSlider(default = default_value, values = values, label = label)
    else:
        from sage.all import sage_eval
        C = InputBox(default = control, label=label, evaluate=True)

        if CONFIG.EMBEDDED_MODE["sage_mode"] and CONFIG.EMBEDDED_MODE["enable_sage"]:
            from sagenb.misc.misc import Color
            from sage.structure.all import is_Vector, is_Matrix
            from sage.all import parent
            if is_Matrix(control):
                nrows = control.nrows()
                ncols = control.ncols()
                default_value = control.list()
                default_value = [[default_value[j * ncols + i] for i in range(ncols)] for j in range(nrows)]
                C = InputGrid(nrows = nrows, ncols = ncols, label = label, 
                              default = default_value, adapter=lambda x, globs: parent(control)(x))
            elif is_Vector(control):
                default_value = [control.list()]
                nrows = 1
                ncols = len(control)
                C = InputGrid(nrows = nrows, ncols = ncols, label = label, 
                              default = default_value, adapter=lambda x, globs: parent(control)(x[0]))
            elif isinstance(control, Color):
                C = ColorSelector(default = control, label = label)
    
    return C
    def eval(self, element, *args, **kwds):
        r'''
            Method to evaluate elements in the ring of differential polynomials.

            Since the differential polynomials have an intrinsic meaning (namely, the 
            variables are related by derivation), evaluating a differential polynomial
            is a straight-forward computation once the objects for the ``*_0`` term is given.

            This method evaluates elements in ``self`` following that rule.

            INPUT:

            * ``element``: element (that must be in ``self``) to be evaluated
            * ``args``: list of arguments that will be linearly related with the generators
              of ``self`` (like they are given by ``self.gens()``)
            * ``kwds``: dictionary for providing values to the generators of ``self``. The 
              name of the keys must be the names of the generators (as they can be got using 
              the attribute ``_name``).

            We allow a mixed used of ``args`` and ``kwds`` but an error will be raised if

            * There are too many arguments in ``args``,
            * An input in ``kwds`` is not a valid name of a generator,
            * There are duplicate entries for a generator.

            OUTPUT:

            The resulting element after evaluating the variable `\alpha_n = \partial^n(\alpha)`,
            where `\alpha` is the name of the generator.

            EXAMPLES::

                sage: from dalgebra.differential_polynomial.differential_polynomial_ring import * 
                sage: R.<y> = DiffPolynomialRing(QQ['x']); x = R.base().gens()[0]
                sage: R.eval(y[1], 0)
                0
                sage: R.eval(y[0] + y[1], x)
                x + 1
                sage: R.eval(y[0] + y[1], y=x)
                x + 1

            This method commutes with the use of :func:`derivation`::

                sage: R.eval(R.derivation(x^2*y[1]^2 - y[2]*y[1]), y=x) == R.derivation(R.eval(x^2*y[1]^2 - y[2]*y[1], y=x))
                True

            This evaluation also works naturally with several infinite variables::

                sage: S = DiffPolynomialRing(R, 'a'); a,y = S.gens()
                sage: S.eval(a[1] + y[0]*a[0], a=x, y=x^2)
                x^3 + 1
                sage: in_eval = S.eval(a[1] + y[0]*a[0], y=x); in_eval
                a_1 + x*a_0
                sage: parent(in_eval)
                Ring of differential polynomials in (a) over [Univariate Polynomial Ring in x over Rational Field]
        '''
        if (not element in self):
            raise TypeError("Impossible to evaluate %s as an element of %s" %
                            (element, self))
        g = self.gens()
        final_input = {}
        names = [el._name for el in g]
        if (len(args) > self.ngens()):
            raise ValueError(
                "Too many argument for evaluation: given %d, expected (at most) %d"
                % (len(args), self.ngens()))
        for i in range(len(args)):
            final_input[g[i]] = args[i]
        for key in kwds:
            if (not key in names):
                raise TypeError("Invalid name for argument %s" % key)
            gen = g[names.index(key)]
            if (gen in final_input):
                raise TypeError("Duplicated value for generator %s" % gen)
            final_input[gen] = kwds[key]

        max_derivation = {gen: 0 for gen in final_input}
        for v in element.variables():
            for gen in max_derivation:
                if (gen.contains(v)):
                    max_derivation[gen] = max(max_derivation[gen],
                                              gen.index(v))
                    break

        to_evaluate = {}
        for gen in max_derivation:
            for i in range(max_derivation[gen] + 1):
                to_evaluate[str(gen[i])] = diff(final_input[gen], i)

        ## Computing the final ring
        values = list(final_input.values())
        R = parent(values[0])
        for i in range(1, len(values)):
            R = pushout(R, parent(values[i]))

        poly = element.polynomial()
        ## Adding all the non-appearing variables on element
        if (len(final_input) == len(g)):
            for v in poly.parent().gens():
                if (v not in poly.variables()) and (not str(v) in to_evaluate):
                    to_evaluate[str(v)] = 0
        else:
            left_gens = [gen for gen in g if gen not in final_input]
            R = DiffPolynomialRing(R, [el._name for el in left_gens])
            for v in poly.parent().gens():
                if (not any(gen.contains(v)
                            for gen in left_gens)) and (not str(v)
                                                        in to_evaluate):
                    to_evaluate[str(v)] = 0

        return R(poly(**to_evaluate))