Exemple #1
0
def checkpdesol(pde, sol, func=None, solve_for_func=True):
    """
    Checks if the given solution satisfies the partial differential
    equation.

    pde is the partial differential equation which can be given in the
    form of an equation or an expression. sol is the solution for which
    the pde is to be checked. This can also be given in an equation or
    an expression form. If the function is not provided, the helper
    function _preprocess from deutils is used to identify the function.

    If a sequence of solutions is passed, the same sort of container will be
    used to return the result for each solution.

    The following methods are currently being implemented to check if the
    solution satisfies the PDE:

        1. Directly substitute the solution in the PDE and check. If the
           solution hasn't been solved for f, then it will solve for f
           provided solve_for_func hasn't been set to False.

    If the solution satisfies the PDE, then a tuple (True, 0) is returned.
    Otherwise a tuple (False, expr) where expr is the value obtained
    after substituting the solution in the PDE. However if a known solution
    returns False, it may be due to the inability of doit() to simplify it to zero.

    Examples
    ========
    >>> from sympy import Function, symbols, diff
    >>> from sympy.solvers.pde import checkpdesol, pdsolve
    >>> x, y = symbols('x y')
    >>> f = Function('f')
    >>> eq = 2*f(x,y) + 3*f(x,y).diff(x) + 4*f(x,y).diff(y)
    >>> sol = pdsolve(eq)
    >>> assert checkpdesol(eq, sol)[0]
    >>> eq = x*f(x,y) + f(x,y).diff(x)
    >>> checkpdesol(eq, sol)
    (False, (x*F(4*x - 3*y) - 6*F(4*x - 3*y)/25 + 4*Subs(Derivative(F(_xi_1), _xi_1), (_xi_1,), (4*x - 3*y,)))*exp(-6*x/25 - 8*y/25))
    """

    # Converting the pde into an equation
    if not isinstance(pde, Equality):
        pde = Eq(pde, 0)

    # If no function is given, try finding the function present.
    if func is None:
        try:
            _, func = _preprocess(pde.lhs)
        except ValueError:
            funcs = [s.atoms(AppliedUndef) for s in (
                sol if is_sequence(sol, set) else [sol])]
            funcs = reduce(set.union, funcs, set())
            if len(funcs) != 1:
                raise ValueError(
                    'must pass func arg to checkpdesol for this case.')
            func = funcs.pop()

    # If the given solution is in the form of a list or a set
    # then return a list or set of tuples.
    if is_sequence(sol, set):
        return type(sol)(map(lambda i: checkpdesol(pde, i,
            solve_for_func=solve_for_func), sol))

    # Convert solution into an equation
    if not isinstance(sol, Equality):
        sol = Eq(func, sol)

    # Try solving for the function
    if solve_for_func and not (sol.lhs == func and not sol.rhs.has(func)) and not \
            (sol.rhs == func and not sol.lhs.has(func)):
        try:
            solved = solve(sol, func)
            if not solved:
                raise NotImplementedError
        except NotImplementedError:
            pass
        else:
            if len(solved) == 1:
                result = checkpdesol(pde, Eq(func, solved[0]),
                    order=order, solve_for_func=False)
            else:
                result = checkpdesol(pde, [Eq(func, t) for t in solved],
                order=order, solve_for_func=False)

    # The first method includes direct substitution of the solution in
    # the PDE and simplifying.
    pde = pde.lhs - pde.rhs
    if sol.lhs == func:
        s = pde.subs(func, sol.rhs).doit()
    elif sol.rhs == func:
        s = pde.subs(func, sol.lhs).doit()
    if s:
        ss = simplify(s)
        if ss:
            return False, ss
        else:
            return True, 0
    else:
        return True, 0
Exemple #2
0
class EllipticCurve():
    """
    Create the following Elliptic Curve over domain.

    `y^{2} + a_{1} x y + a_{3} y = x^{3} + a_{2} x^{2} + a_{4} x + a_{6}`

    The default domain is ``QQ``. If no coefficient ``a1``, ``a2``, ``a3``,
    it create curve as following form.

    `y^{2} = x^{3} + a_{4} x + a_{6}`

    Examples
    ========

    References
    ==========

    [1] J. Silverman "A Friendly Introduction to Number Theory" Third Edition
    [2] http://mathworld.wolfram.com/EllipticDiscriminant.html
    [3] G. Hardy, E. Wright "An Introduction to the Theory of Numbers" Sixth Edition

    """
    def __init__(self, a1, a2, a3, a4, a6, domain=QQ):
        self._dom = domain
        # Calculate discriminant
        self._b2 = a1**2 + 4 * a2
        self._b4 = 2 * a4 + a1 * a3
        self._b6 = a3**2 + 4 * a6
        self._b8 = a1**2 * a6 + 4 * a2 * a6 - a1 * a3 * a4 + a2 * a3**2 - a4**2
        self._discrim = self._dom(-self._b2**2 * self._b8 - 8 * self._b4**3 -
                                  27 * self._b6**2 +
                                  9 * self._b2 * self._b4 * self._b6)
        self._a1 = self._dom(a1)
        self._a2 = self._dom(a2)
        self._a3 = self._dom(a3)
        self._a4 = self._dom(a4)
        self._a6 = self._dom(a6)
        self._eq = Eq(y**2 + self._a1 * x * y + self._a3 * y,
                      x**3 + self._a2 * x**2 + self._a4 * x + self._a6)
        if isinstance(self._dom, FiniteField):
            self._rank = 0
        elif isinstance(self._dom, RationalField):
            self._rank = None

    @classmethod
    def minimal(cls, a4, a6, domain=QQ):
        return cls(0, 0, 0, a4, a6, domain)

    def __call__(self, x, y, z=1):
        if z == 0:
            return InfinityPoint(self)
        return Point(x, y, z, self)

    def __contains__(self, point):
        if is_sequence(point):
            if len(point) == 2:
                z1 = 1
            else:
                z1 = point[2]
            x1, y1 = point[:2]
        elif isinstance(point, Point):
            x1, y1, z1 = point.x, point.y, point.z
        else:
            raise ValueError('Invalid point.')
        if self.characteristic == 0 and z1 == 0:
            return True
        return self._eq.subs({x: x1, y: y1})

    def __repr__(self):
        return 'E({}): {}'.format(self._dom, self._eq)

    def points(self):
        """
        Return points of curve over Finite Field.

        Examples
        ========

        >>> from sympy.polys.domains import FF
        >>> from ec import EllipticCurve
        >>> e2 = EllipticCurve.minimal(1, 0, domain=FF(2))
        >>> list(e2.points())
        [(0, 0), (1, 0)]

        """
        char = self.characteristic
        if char > 1:
            for i in range(char):
                y = sqrt_mod(i**3 + self._a2 * i**2 + self._a4 * i + self._a6,
                             char)
                if y is not None:
                    yield self(i, y)
                    if y != 0:
                        yield self(i, char - y)
        else:
            raise NotImplementedError("Still not implemented")

    def to_minimal(self):
        """
        Return minimal Weierstrass equation.

        Examples
        ========

        >>> from ec import EllipticCurve
        >>> e1 = EllipticCurve(0, -1, 1, -10, -20)
        >>> e1.to_minimal()
        E(QQ): y**2 == x**3 - 13392*x - 1080432

        """
        char = self.characteristic
        if char == 2:
            return self
        if char == 3:
            return EllipticCurve(0, self._b2 / 4, 0, self._b4 / 2,
                                 self._b6 / 4, self._dom)
        c4 = self._b2**2 - 24 * self._b4
        c6 = -self._b2**3 + 36 * self._b2 * self._b4 - 216 * self._b6
        return EllipticCurve.minimal(-27 * c4, -54 * c6, self._dom)

    def torsion_points(self):
        """
        Return torsion points of curve over Rational number.

        Return point objects those are finite order.
        According to Nagell-Lutz theorem, torsion point p(x, y)
        x and y are integers, either y = 0 or y**2 is divisor
        of discriminent. According to Mazur's theorem, there are
        at most 15 points in torsion collection.

        Examples
        ========

        >>> from ec import EllipticCurve
        >>> e2 = EllipticCurve.minimal(-43, 166)
        >>> [i for i in e2.torsion_points()]
        [O, (3, 8), (3, -8), (-5, 16), (-5, -16), (11, 32), (11, -32)]

        """
        if self.characteristic > 0:
            raise ValueError("No torsion point for Finite Field.")
        yield InfinityPoint(self)
        for x in solve(self._eq.subs(y, 0)):
            if x.is_rational:
                yield self(x, 0)
        for i in divisors(self.discriminant, generator=True):
            j = int(i**.5)
            if j**2 == i:
                for x in solve(self._eq.subs(y, j)):
                    p = self(x, j)
                    if x.is_rational and p.order() != oo:
                        yield p
                        yield -p

    @property
    def characteristic(self):
        """
        Return domain characteristic.

        Examples
        ========

        >>> from ec import EllipticCurve
        >>> e2 = EllipticCurve.minimal(-43, 166)
        >>> e2.characteristic
        0

        """
        return self._dom.characteristic()

    @property
    def discriminant(self):
        """
        Return curve discriminant.

        Examples
        ========

        >>> from ec import EllipticCurve
        >>> e2 = EllipticCurve.minimal(0, 17)
        >>> e2.discriminant
        -124848

        """
        return int(self._discrim)

    @property
    def is_singular(self):
        """
        Return True if curve discriminant is equal to zero.
        """
        return self.discriminant == 0

    @property
    def j_invariant(self):
        """
        Return curve j-invariant.

        Examples
        ========

        >>> from ec import EllipticCurve
        >>> e1 = EllipticCurve(0, 1, 1, -2, 0)
        >>> e1.j_invariant
        1404928/389

        """
        c4 = self._b2**2 - 24 * self._b4
        return self._dom.to_sympy(c4**3 / self._discrim)

    @property
    def order(self):
        """
        Number of points in Finite field.

        Examples
        ========

        >>> from sympy.polys.domains import FF
        >>> from ec import EllipticCurve
        >>> e2 = EllipticCurve.minimal(1, 0, domain=FF(19))
        >>> e2.order
        19

        """
        if self.characteristic == 0:
            raise NotImplementedError("Still not implemented")
        return len(list(self.points()))

    @property
    def rank(self):
        """
        Number of independent points of infinite order.

        For Finite field, it must be 0.
        """
        if self._rank is not None:
            return self._rank
        raise NotImplementedError("Still not implemented")
Exemple #3
0
def test_equality_subs2():
    f = Function('f')
    eq = Eq(f(x)**2, 16)
    assert bool(eq.subs(f(x), 3)) is False
    assert bool(eq.subs(f(x), 4)) is True
class EllipticCurve:
    """
    Create the following Elliptic Curve over domain.

    `y^{2} + a_{1} x y + a_{3} y = x^{3} + a_{2} x^{2} + a_{4} x + a_{6}`

    The default domain is ``QQ``. If no coefficient ``a1``, ``a2``, ``a3``,
    it create curve as following form.

    `y^{2} = x^{3} + a_{4} x + a_{6}`

    Examples
    ========

    References
    ==========

    .. [1] J. Silverman "A Friendly Introduction to Number Theory" Third Edition
    .. [2] http://mathworld.wolfram.com/EllipticDiscriminant.html
    .. [3] G. Hardy, E. Wright "An Introduction to the Theory of Numbers" Sixth Edition

    """
    def __init__(self, a4, a6, a1=0, a2=0, a3=0, modulus=0):
        if modulus == 0:
            domain = QQ
        else:
            domain = FF(modulus)
        a1, a2, a3, a4, a6 = map(domain.convert, (a1, a2, a3, a4, a6))
        self._domain = domain
        self.modulus = modulus
        # Calculate discriminant
        b2 = a1**2 + 4 * a2
        b4 = 2 * a4 + a1 * a3
        b6 = a3**2 + 4 * a6
        b8 = a1**2 * a6 + 4 * a2 * a6 - a1 * a3 * a4 + a2 * a3**2 - a4**2
        self._b2, self._b4, self._b6, self._b8 = b2, b4, b6, b8
        self._discrim = -b2**2 * b8 - 8 * b4**3 - 27 * b6**2 + 9 * b2 * b4 * b6
        self._a1 = a1
        self._a2 = a2
        self._a3 = a3
        self._a4 = a4
        self._a6 = a6
        x, y, z = symbols('x y z')
        self.x, self.y, self.z = x, y, z
        self._eq = Eq(y**2 * z + a1 * x * y * z + a3 * y * z**2,
                      x**3 + a2 * x**2 * z + a4 * x * z**2 + a6 * z**3)
        if isinstance(self._domain, FiniteField):
            self._rank = 0
        elif isinstance(self._domain, RationalField):
            self._rank = None

    def __call__(self, x, y, z=1):
        return EllipticCurvePoint(x, y, z, self)

    def __contains__(self, point):
        if is_sequence(point):
            if len(point) == 2:
                z1 = 1
            else:
                z1 = point[2]
            x1, y1 = point[:2]
        elif isinstance(point, EllipticCurvePoint):
            x1, y1, z1 = point.x, point.y, point.z
        else:
            raise ValueError('Invalid point.')
        if self.characteristic == 0 and z1 == 0:
            return True
        return self._eq.subs({self.x: x1, self.y: y1, self.z: z1})

    def __repr__(self):
        return 'E({}): {}'.format(self._domain, self._eq)

    def minimal(self):
        """
        Return minimal Weierstrass equation.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve

        >>> e1 = EllipticCurve(-10, -20, 0, -1, 1)
        >>> e1.minimal()
        E(QQ): Eq(y**2*z, x**3 - 13392*x*z**2 - 1080432*z**3)

        """
        char = self.characteristic
        if char == 2:
            return self
        if char == 3:
            return EllipticCurve(self._b4 / 2,
                                 self._b6 / 4,
                                 a2=self._b2 / 4,
                                 modulus=self.modulus)
        c4 = self._b2**2 - 24 * self._b4
        c6 = -self._b2**3 + 36 * self._b2 * self._b4 - 216 * self._b6
        return EllipticCurve(-27 * c4, -54 * c6, modulus=self.modulus)

    def points(self):
        """
        Return points of curve over Finite Field.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(1, 1, 1, 1, 1, modulus=5)
        >>> e2.points()
        {(0, 2), (1, 4), (2, 0), (2, 2), (3, 0), (3, 1), (4, 0)}

        """

        char = self.characteristic
        all_pt = set()
        if char >= 1:
            for i in range(char):
                congruence_eq = ((self._eq.lhs - self._eq.rhs).subs({
                    self.x: i,
                    self.z: 1
                }))
                sol = polynomial_congruence(congruence_eq, char)
                for num in sol:
                    all_pt.add((i, num))
            return all_pt
        else:
            raise ValueError("Infinitely many points")

    def points_x(self, x):
        "Returns points on with curve where xcoordinate = x"
        pt = []
        if self._domain == QQ:
            for y in solve(self._eq.subs(self.x, x)):
                pt.append((x, y))
        congruence_eq = ((self._eq.lhs - self._eq.rhs).subs({
            self.x: x,
            self.z: 1
        }))
        for y in polynomial_congruence(congruence_eq, self.characteristic):
            pt.append((x, y))
        return pt

    def torsion_points(self):
        """
        Return torsion points of curve over Rational number.

        Return point objects those are finite order.
        According to Nagell-Lutz theorem, torsion point p(x, y)
        x and y are integers, either y = 0 or y**2 is divisor
        of discriminent. According to Mazur's theorem, there are
        at most 15 points in torsion collection.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(-43, 166)
        >>> sorted(e2.torsion_points())
        [(-5, -16), (-5, 16), O, (3, -8), (3, 8), (11, -32), (11, 32)]

        """
        if self.characteristic > 0:
            raise ValueError("No torsion point for Finite Field.")
        l = [EllipticCurvePoint.point_at_infinity(self)]
        for xx in solve(self._eq.subs({self.y: 0, self.z: 1})):
            if xx.is_rational:
                l.append(self(xx, 0))
        for i in divisors(self.discriminant, generator=True):
            j = int(i**.5)
            if j**2 == i:
                for xx in solve(self._eq.subs({self.y: j, self.z: 1})):
                    if not xx.is_rational:
                        continue
                    p = self(xx, j)
                    if p.order() != oo:
                        l.extend([p, -p])
        return l

    @property
    def characteristic(self):
        """
        Return domain characteristic.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(-43, 166)
        >>> e2.characteristic
        0

        """
        return self._domain.characteristic()

    @property
    def discriminant(self):
        """
        Return curve discriminant.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(0, 17)
        >>> e2.discriminant
        -124848

        """
        return int(self._discrim)

    @property
    def is_singular(self):
        """
        Return True if curve discriminant is equal to zero.
        """
        return self.discriminant == 0

    @property
    def j_invariant(self):
        """
        Return curve j-invariant.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e1 = EllipticCurve(-2, 0, 0, 1, 1)
        >>> e1.j_invariant
        1404928/389

        """
        c4 = self._b2**2 - 24 * self._b4
        return self._domain.to_sympy(c4**3 / self._discrim)

    @property
    def order(self):
        """
        Number of points in Finite field.

        Examples
        ========

        >>> from sympy.ntheory.elliptic_curve import EllipticCurve
        >>> e2 = EllipticCurve(1, 0, modulus=19)
        >>> e2.order
        19

        """
        if self.characteristic == 0:
            raise NotImplementedError("Still not implemented")
        return len(list(self.points()))

    @property
    def rank(self):
        """
        Number of independent points of infinite order.

        For Finite field, it must be 0.
        """
        if self._rank is not None:
            return self._rank
        raise NotImplementedError("Still not implemented")
Exemple #5
0
def test_equality_subs1():
    f = Function('f')
    eq = Eq(f(x)**2, x)
    res = Eq(Integer(16), x)
    assert eq.subs(f(x), 4) == res