Esempio n. 1
0
def test_pow_gentle_simplify():
    # these simplify to 0 and 1
    weird0 = Add([x, -x])
    weird1 = Mul([x, 1 / x])
    assert weird0 != mathify(0)
    assert weird1 != mathify(1)
    assert weird0.gentle_simplify() == mathify(0)
    assert weird1.gentle_simplify() == mathify(1)

    assert Pow(x, Thing()).gentle_simplify() == Pow(x, Thing(True))
    assert Pow(Thing(), y).gentle_simplify() == Pow(Thing(True), y)
    assert Pow(Pow(x, y), z).gentle_simplify() == Pow(x, y * z)
    assert Pow(x * y, z).gentle_simplify() == Mul([Pow(x, z), Pow(y, z)])
    assert Pow(weird0, x).gentle_simplify() == mathify(0)
    assert Pow(weird1, x).gentle_simplify() == mathify(1)
    assert Pow(weird0, weird0).gentle_simplify() == mathify(0**0)
    assert Pow(x, weird0).gentle_simplify() == mathify(1)
    assert Pow(x, weird1).gentle_simplify() == x

    assert Pow(2, 3).gentle_simplify() == mathify(8)
    assert isinstance(Pow(2, -3).gentle_simplify(), Pow)

    for base in range(-10, 10):
        for exponent in range(-10, 10):
            try:
                value = base**exponent
            except ZeroDivisionError:
                continue  # TODO: derivater should also raise an error :(

            simplified = Pow(base, exponent).gentle_simplify()
            if abs(value - int(value)) > 1e-12:
                # not an integer
                assert isinstance(simplified, Pow)
            else:
                assert simplified == mathify(int(value))
Esempio n. 2
0
def test_mathify_pythonify():
    math2python = {
        Integer(1): 1,
        Integer(1) / 2: fractions.Fraction(1, 2),
        Integer(3) / (-5): fractions.Fraction(-3, 5),
        Pow(4, 2): fractions.Fraction(4)**2,
        Pow(5, 3): 5**3,
    }

    # keys() and values() are guaranteed to be in the same order, although a
    # different order shouldn't matter
    math_sum = Add(math2python.keys())  # not gentle_simplify()ied
    python_sum = sum(math2python.values())
    math2python[math_sum] = python_sum

    math_product = Mul(math2python.keys())
    python_product = functools.reduce(operator.mul, math2python.values())
    math2python[math_product] = python_product

    for math, python in math2python.items():
        assert mathify(math) == math  # returned as is
        assert mathify(python) == math.gentle_simplify()
        assert pythonify(math) == python
        assert pythonify(python) == python

    # make sure that fractions aren't returned when not needed
    assert type(mathify(fractions.Fraction(2, 1))) is Integer
    assert type(pythonify(Mul([4, half]))) is int

    with pytest.raises(TypeError, match="don't know how to pythonify <Toot>$"):
        pythonify(Toot())
    with pytest.raises(TypeError, match="don't know how to mathify 'lol'$"):
        mathify('lol')
Esempio n. 3
0
def test_with_fraction_coeff():
    assert Pow(3, 4).with_fraction_coeff() == (Pow(3, 4), mathify(1))
    assert Pow(3, -4).with_fraction_coeff() == (Pow(3, -4), mathify(1))
    assert Mul([2, Pow(3, -4)]).with_fraction_coeff() == (mathify(2) / 81,
                                                          mathify(1))
    assert Mul([half, x, 3]).with_fraction_coeff() == (half * 3, x)
    assert Add([2 * x / 3, 4 * y / 5
                ]).with_fraction_coeff() == (mathify(2) / 15, 5 * x + 6 * y)
    assert Add([]).with_fraction_coeff() == (mathify(1), Add([]))
Esempio n. 4
0
def test_mul_repr():
    assert repr(-x) == '-x'
    assert repr(2 * x) == '2*x'
    assert repr(-2 * x) == '-2*x'
    assert repr((x + y) * z) == '(x + y)*z'
    assert repr((x + y) / z) == '(x + y) / z'
    assert repr(Mul([1 / x, 1 / y])) == '1 / (x*y)'

    assert repr(Mul([])) == '1'
    assert repr(Mul([x])) == 'x'
    assert repr(Mul([1 / x])) == repr(1 / x) == '1 / x'
    assert repr(Mul([Pow(x / y, -2)])) == '1 / (x**2 / y**2)'
Esempio n. 5
0
def test_automagic_gentle_simplify():
    assert (Thing() + x).objects[0].gentle
    assert (Thing() * x).objects[0].gentle
    assert (Thing()**x).base.gentle
    assert (x**Thing()).exponent.gentle

    assert not Add([Thing(), x]).objects[0].gentle
    assert not Mul([Thing(), x]).objects[0].gentle
    assert not Pow(Thing(), x).base.gentle
    assert not Pow(x, Thing()).exponent.gentle
Esempio n. 6
0
def test_operators():
    pairs = [
        (2 * x, y),
        (2 * ln(4), y),
        (x, x),
        (x, 2 * x),
        (y, -2 * x),
        # not all things are MathObjects, they must be mathified
        (1, -2 * x),
        (-10, -x),
    ]
    pairs.extend([(b, a) for (a, b) in pairs])

    for a, b in pairs:
        if not isinstance(b, int):
            assert 0 - b == -b
            assert 1 / b == pow(b, -1)

        assert a + b == Add([a, b]).gentle_simplify()
        assert a - b == Add([a, -b]).gentle_simplify()
        assert a * b == Mul([a, b]).gentle_simplify()
        assert a / b == Mul([a, Pow(b, -1)]).gentle_simplify()
        assert a**b == Pow(a, b).gentle_simplify()
Esempio n. 7
0
def test_add_partial_replaces():
    # this checks .objects to make sure the order is correct
    assert Add([x, y, z]).replace(Add([x, y]), a).objects == [a, z]
    assert Add([x, y, z]).replace(Add([y, x]), a).objects == [a, z]
    assert Add([x, y, z]).replace(Add([y, z]), a).objects == [x, a]
    assert Add([x, y, z]).replace(Add([z, y]), a).objects == [x, a]
    assert Add([x, y, z]).replace(Add([x, z]), a).objects == [y, a]
    assert Add([x, y, z]).replace(Add([z, x]), a).objects == [a, y]

    assert Mul([x, y, z]).replace(Mul([x, y]), a).objects == [a, z]
    assert Mul([x, y, z]).replace(Mul([y, x]), a).objects == [a, z]
    assert Mul([x, y, z]).replace(Mul([y, z]), a).objects == [x, a]
    assert Mul([x, y, z]).replace(Mul([z, y]), a).objects == [x, a]
    assert Mul([x, y, z]).replace(Mul([x, z]), a).objects == [y, a]
    assert Mul([x, y, z]).replace(Mul([z, x]), a).objects == [a, y]

    for klass, name, instead in [(Add, 'Add', 'zeros'), (Mul, 'Mul', 'ones')]:
        with pytest.raises(ValueError,
                           match=((r"cannot replace %s\(\[\]\) by something, "
                                   r"maybe use gentle_simplify\(\) to turn "
                                   r"%s\(\[\]\)'s into %s\?$") %
                                  (name, name, instead))):
            klass([x, y]).replace(klass([]), z)

    # make sure that gentle_simplify() is not called
    assert not Add([x, y, z]).replace(x + y, Thing()).objects[0].gentle
    assert not Mul([x, y, z]).replace(x * y, Thing()).objects[0].gentle

    # even -x which is Mul([-1, x]) doesn't turn into Integer(-1), instead it
    # turns into Mul([-1, 1]) which looks a lot like Integer(-1) ...  (lol)
    assert Add([x, -x]).replace(x, 1) == Add([1, Mul([-1, 1])])
    assert Mul([x, -x]).replace(x, 1) == Mul([1, Mul([-1, 1])])
Esempio n. 8
0
def test_mul_gentle_simplify():
    assert Mul([x, y, Thing()]).gentle_simplify() == Mul([x, y, Thing(True)])
    assert (Mul([x, y, Mul([z, Thing()])
                 ]).gentle_simplify() == Mul([x, y, z, Thing(True)]))
    assert Mul([1, x, 2, y, 3]).gentle_simplify() == Mul([6, x, y])
    assert Mul([1, x, 2, y, 3]).gentle_simplify().objects[0] == mathify(6)
    assert Mul([1, x, y]).gentle_simplify() == Mul([x, y])
    assert (Mul([x, y, x**a, y,
                 x**b]).gentle_simplify() == Mul([x**(a + b + 1), y**2]))
    assert Mul([x]).gentle_simplify() == x
    assert Mul([x, x]).gentle_simplify() == x**2
    assert Mul([]).gentle_simplify() == mathify(1)
    assert Mul([x, 1 / x]).gentle_simplify() == mathify(1)

    # these were broken in old derivater versions
    assert Mul([x, y, 1 / x]).gentle_simplify() == y
    assert Mul([x, 1 / x]).gentle_simplify() == mathify(1)