Exemple #1
0
    def _eval_simplify(self, **kwargs):
        from .add import Add
        from sympy.core.expr import Expr
        r = self
        r = r.func(*[i.simplify(**kwargs) for i in r.args])
        if r.is_Relational:
            if not isinstance(r.lhs, Expr) or not isinstance(r.rhs, Expr):
                return r
            dif = r.lhs - r.rhs
            # replace dif with a valid Number that will
            # allow a definitive comparison with 0
            v = None
            if dif.is_comparable:
                v = dif.n(2)
            elif dif.equals(0):  # XXX this is expensive
                v = S.Zero
            if v is not None:
                r = r.func._eval_relation(v, S.Zero)
            r = r.canonical
            # If there is only one symbol in the expression,
            # try to write it on a simplified form
            free = list(
                filter(lambda x: x.is_real is not False, r.free_symbols))
            if len(free) == 1:
                try:
                    from sympy.solvers.solveset import linear_coeffs
                    x = free.pop()
                    dif = r.lhs - r.rhs
                    m, b = linear_coeffs(dif, x)
                    if m.is_zero is False:
                        if m.is_negative:
                            # Dividing with a negative number, so change order of arguments
                            # canonical will put the symbol back on the lhs later
                            r = r.func(-b / m, x)
                        else:
                            r = r.func(x, -b / m)
                    else:
                        r = r.func(b, S.zero)
                except ValueError:
                    # maybe not a linear function, try polynomial
                    from sympy.polys import Poly, poly, PolynomialError, gcd
                    try:
                        p = poly(dif, x)
                        c = p.all_coeffs()
                        constant = c[-1]
                        c[-1] = 0
                        scale = gcd(c)
                        c = [ctmp / scale for ctmp in c]
                        r = r.func(
                            Poly.from_list(c, x).as_expr(), -constant / scale)
                    except PolynomialError:
                        pass
            elif len(free) >= 2:
                try:
                    from sympy.solvers.solveset import linear_coeffs
                    from sympy.polys import gcd
                    free = list(ordered(free))
                    dif = r.lhs - r.rhs
                    m = linear_coeffs(dif, *free)
                    constant = m[-1]
                    del m[-1]
                    scale = gcd(m)
                    m = [mtmp / scale for mtmp in m]
                    nzm = list(filter(lambda f: f[0] != 0, list(zip(m, free))))
                    if scale.is_zero is False:
                        if constant != 0:
                            # lhs: expression, rhs: constant
                            newexpr = Add(*[i * j for i, j in nzm])
                            r = r.func(newexpr, -constant / scale)
                        else:
                            # keep first term on lhs
                            lhsterm = nzm[0][0] * nzm[0][1]
                            del nzm[0]
                            newexpr = Add(*[i * j for i, j in nzm])
                            r = r.func(lhsterm, -newexpr)

                    else:
                        r = r.func(constant, S.zero)
                except ValueError:
                    pass
        # Did we get a simplified result?
        r = r.canonical
        measure = kwargs['measure']
        if measure(r) < kwargs['ratio'] * measure(self):
            return r
        else:
            return self
Exemple #2
0
def test_dispersion():
    x = Symbol("x")
    a = Symbol("a")

    fp = poly(S.Zero, x)
    assert sorted(dispersionset(fp)) == [0]

    fp = poly(S(2), x)
    assert sorted(dispersionset(fp)) == [0]

    fp = poly(x + 1, x)
    assert sorted(dispersionset(fp)) == [0]
    assert dispersion(fp) == 0

    fp = poly((x + 1) * (x + 2), x)
    assert sorted(dispersionset(fp)) == [0, 1]
    assert dispersion(fp) == 1

    fp = poly(x * (x + 3), x)
    assert sorted(dispersionset(fp)) == [0, 3]
    assert dispersion(fp) == 3

    fp = poly((x - 3) * (x + 3), x)
    assert sorted(dispersionset(fp)) == [0, 6]
    assert dispersion(fp) == 6

    fp = poly(x**4 - 3 * x**2 + 1, x)
    gp = fp.shift(-3)
    assert sorted(dispersionset(fp, gp)) == [2, 3, 4]
    assert dispersion(fp, gp) == 4
    assert sorted(dispersionset(gp, fp)) == []
    assert dispersion(gp, fp) is -oo

    fp = poly(x * (3 * x**2 + a) * (x - 2536) * (x**3 + a), x)
    gp = fp.as_expr().subs(x, x - 345).as_poly(x)
    assert sorted(dispersionset(fp, gp)) == [345, 2881]
    assert sorted(dispersionset(gp, fp)) == [2191]

    gp = poly((x - 2)**2 * (x - 3)**3 * (x - 5)**3, x)
    assert sorted(dispersionset(gp)) == [0, 1, 2, 3]
    assert sorted(dispersionset(gp, (gp + 4)**2)) == [1, 2]

    fp = poly(x * (x + 2) * (x - 1), x)
    assert sorted(dispersionset(fp)) == [0, 1, 2, 3]

    fp = poly(x**2 + sqrt(5) * x - 1, x, domain="QQ<sqrt(5)>")
    gp = poly(x**2 + (2 + sqrt(5)) * x + sqrt(5), x, domain="QQ<sqrt(5)>")
    assert sorted(dispersionset(fp, gp)) == [2]
    assert sorted(dispersionset(gp, fp)) == [1, 4]

    # There are some difficulties if we compute over Z[a]
    # and alpha happenes to lie in Z[a] instead of simply Z.
    # Hence we can not decide if alpha is indeed integral
    # in general.

    fp = poly(
        4 * x**4 + (4 * a + 8) * x**3 + (a**2 + 6 * a + 4) * x**2 +
        (a**2 + 2 * a) * x,
        x,
    )
    assert sorted(dispersionset(fp)) == [0, 1]

    # For any specific value of a, the dispersion is 3*a
    # but the algorithm can not find this in general.
    # This is the point where the resultant based Ansatz
    # is superior to the current one.
    fp = poly(a**2 * x**3 + (a**3 + a**2 + a + 1) * x, x)
    gp = fp.as_expr().subs(x, x - 3 * a).as_poly(x)
    assert sorted(dispersionset(fp, gp)) == []

    fpa = fp.as_expr().subs(a, 2).as_poly(x)
    gpa = gp.as_expr().subs(a, 2).as_poly(x)
    assert sorted(dispersionset(fpa, gpa)) == [6]

    # Work with Expr instead of Poly
    f = (x + 1) * (x + 2)
    assert sorted(dispersionset(f)) == [0, 1]
    assert dispersion(f) == 1

    f = x**4 - 3 * x**2 + 1
    g = x**4 - 12 * x**3 + 51 * x**2 - 90 * x + 55
    assert sorted(dispersionset(f, g)) == [2, 3, 4]
    assert dispersion(f, g) == 4

    # Work with Expr and specify a generator
    f = (x + 1) * (x + 2)
    assert sorted(dispersionset(f, None, x)) == [0, 1]
    assert dispersion(f, None, x) == 1

    f = x**4 - 3 * x**2 + 1
    g = x**4 - 12 * x**3 + 51 * x**2 - 90 * x + 55
    assert sorted(dispersionset(f, g, x)) == [2, 3, 4]
    assert dispersion(f, g, x) == 4
Exemple #3
0
def relsimp(func, args, **kwargs):
    lhs, rhs = args

    r = func(lhs.simplify(**kwargs), rhs.simplify(**kwargs))
    if not isinstance(r.lhs, Expr) or not isinstance(r.rhs, Expr):
        return r.canonical
    dif = r.lhs - r.rhs
    r = r.canonical
    # If there is only one symbol in the expression,
    # try to write it on a simplified form
    free = list(filter(lambda x: x.is_real is not False, r.free_symbols))
    if len(free) == 1:
        try:
            x = free.pop()
            dif = r.lhs - r.rhs
            m, b = linear_coeffs(dif, x)
            if m.is_zero is False:
                if m.is_negative:
                    # Dividing with a negative number, so change order of arguments
                    # canonical will put the symbol back on the lhs later
                    r = r.function(-b / m, x)
                else:
                    r = r.function(x, -b / m)
            else:
                r = r.function(b, S.Zero)
        except ValueError:
            # maybe not a linear function, try polynomial
            try:
                p = poly(dif, x)
                c = p.all_coeffs()
                constant = c[-1]
                c[-1] = 0
                scale = gcd(c)
                c = [ctmp / scale for ctmp in c]
                r = r.function(Poly.from_list(c, x).as_expr(), -constant / scale)
            except PolynomialError:
                pass
    elif len(free) >= 2:
        try:
            free = list(ordered(free))
            dif = r.lhs - r.rhs
            m = linear_coeffs(dif, *free)
            constant = m[-1]
            del m[-1]
            scale = gcd(m)
            m = [mtmp / scale for mtmp in m]
            nzm = list(filter(lambda f: f[0] != 0, list(zip(m, free))))
            if scale.is_zero is False:
                if constant != 0:
                    # lhs: expression, rhs: constant
                    newexpr = Add(*[i * j for i, j in nzm])
                    r = r.function(newexpr, -constant / scale)
                else:
                    # keep first term on lhs
                    lhsterm = nzm[0][0] * nzm[0][1]
                    del nzm[0]
                    newexpr = Add(*[i * j for i, j in nzm])
                    r = r.function(lhsterm, -newexpr)

            else:
                r = r.function(constant, S.Zero)
        except ValueError:
            pass
    # Did we get a simplified result?
    r = r.canonical
    rel = func(*args)
    measure = kwargs['measure']
    if measure(r) < kwargs['ratio'] * measure(rel):
        return r
    else:
        return rel
def test_dispersion():
    x = Symbol("x")
    a = Symbol("a")

    fp = poly(S(0), x)
    assert sorted(dispersionset(fp)) == [0]

    fp = poly(S(2), x)
    assert sorted(dispersionset(fp)) == [0]

    fp = poly(x + 1, x)
    assert sorted(dispersionset(fp)) == [0]
    assert dispersion(fp) == 0

    fp = poly((x + 1)*(x + 2), x)
    assert sorted(dispersionset(fp)) == [0, 1]
    assert dispersion(fp) == 1

    fp = poly(x*(x + 3), x)
    assert sorted(dispersionset(fp)) == [0, 3]
    assert dispersion(fp) == 3

    fp = poly((x - 3)*(x + 3), x)
    assert sorted(dispersionset(fp)) == [0, 6]
    assert dispersion(fp) == 6

    fp = poly(x**4 - 3*x**2 + 1, x)
    gp = fp.shift(-3)
    assert sorted(dispersionset(fp, gp)) == [2, 3, 4]
    assert dispersion(fp, gp) == 4
    assert sorted(dispersionset(gp, fp)) == []
    assert dispersion(gp, fp) == -oo

    fp = poly(x*(3*x**2+a)*(x-2536)*(x**3+a), x)
    gp = fp.as_expr().subs(x, x-345).as_poly(x)
    assert sorted(dispersionset(fp, gp)) == [345, 2881]
    assert sorted(dispersionset(gp, fp)) == [2191]

    gp = poly((x-2)**2*(x-3)**3*(x-5)**3, x)
    assert sorted(dispersionset(gp)) == [0, 1, 2, 3]
    assert sorted(dispersionset(gp, (gp+4)**2)) == [1, 2]

    fp = poly(x*(x+2)*(x-1), x)
    assert sorted(dispersionset(fp)) == [0, 1, 2, 3]

    fp = poly(x**2 + sqrt(5)*x - 1, x, domain='QQ<sqrt(5)>')
    gp = poly(x**2 + (2 + sqrt(5))*x + sqrt(5), x, domain='QQ<sqrt(5)>')
    assert sorted(dispersionset(fp, gp)) == [2]
    assert sorted(dispersionset(gp, fp)) == [1, 4]

    # There are some difficulties if we compute over Z[a]
    # and alpha happenes to lie in Z[a] instead of simply Z.
    # Hence we can not decide if alpha is indeed integral
    # in general.

    fp = poly(4*x**4 + (4*a + 8)*x**3 + (a**2 + 6*a + 4)*x**2 + (a**2 + 2*a)*x, x)
    assert sorted(dispersionset(fp)) == [0, 1]

    # For any specific value of a, the dispersion is 3*a
    # but the algorithm can not find this in general.
    # This is the point where the resultant based Ansatz
    # is superior to the current one.
    fp = poly(a**2*x**3 + (a**3 + a**2 + a + 1)*x, x)
    gp = fp.as_expr().subs(x, x - 3*a).as_poly(x)
    assert sorted(dispersionset(fp, gp)) == []

    fpa = fp.as_expr().subs(a, 2).as_poly(x)
    gpa = gp.as_expr().subs(a, 2).as_poly(x)
    assert sorted(dispersionset(fpa, gpa)) == [6]

    # Work with Expr instead of Poly
    f = (x + 1)*(x + 2)
    assert sorted(dispersionset(f)) == [0, 1]
    assert dispersion(f) == 1

    f = x**4 - 3*x**2 + 1
    g = x**4 - 12*x**3 + 51*x**2 - 90*x + 55
    assert sorted(dispersionset(f, g)) == [2, 3, 4]
    assert dispersion(f, g) == 4

    # Work with Expr and specify a generator
    f = (x + 1)*(x + 2)
    assert sorted(dispersionset(f, None, x)) == [0, 1]
    assert dispersion(f, None, x) == 1

    f = x**4 - 3*x**2 + 1
    g = x**4 - 12*x**3 + 51*x**2 - 90*x + 55
    assert sorted(dispersionset(f, g, x)) == [2, 3, 4]
    assert dispersion(f, g, x) == 4