
from hypothesis import given, assume, settings
from hypothesis.strategies import floats
from numpy import cos
from pytest import approx

from fastats.optimise.newton_raphson import newton_raphson


def func(x):
    return x**3 - x - 1


def less_or_equal(x, compared_to, rel=1e-6):
    return ((x < compared_to)
            or ((x - compared_to) == approx(0.0, rel=rel))
            or (x == approx(x, rel=rel)))


nr_func = newton_raphson(1, 1e-6, root=func, return_callable=True)


@given(floats(min_value=0.01, max_value=3.5))
def test_minimal(x):
    """
    Tests that the value output from the solver
    is less than or equal to the value of the
    objective.
    """
    eps = 1e-12
    value = nr_func(x, eps)

    assume(func(x) > 0.0)

    assert less_or_equal(value, compared_to=func(x))


def cos_func(x):
    return cos(x) - 2 * x


nr_cos = newton_raphson(0.5, 1e-6, root=cos_func, return_callable=True)


@given(floats(min_value=0.3, max_value=0.8))
@settings(deadline=None)
def test_cos_minus_2x(x):
    value = nr_cos(x, 1e-6)
    assert less_or_equal(value, compared_to=cos_func(x))


if __name__ == '__main__':
    import pytest
    pytest.main([__file__])

[(20, 'fastats.optimise.newton_raphson.newton_raphson', 'newton_raphson', (['(1)', '(1e-06)'], {'root': 'func', 'return_callable': '(True)'}), False, 'from fastats.optimise.newton_raphson import newton_raphson\n'), (42, 'fastats.optimise.newton_raphson.newton_raphson', 'newton_raphson', (['(0.5)', '(1e-06)'], {'root': 'cos_func', 'return_callable': '(True)'}), False, 'from fastats.optimise.newton_raphson import newton_raphson\n'), (46, 'hypothesis.settings', 'settings', ([], {'deadline': 'None'}), False, 'from hypothesis import given, assume, settings\n'), (23, 'hypothesis.strategies.floats', 'floats', ([], {'min_value': '(0.01)', 'max_value': '(3.5)'}), False, 'from hypothesis.strategies import floats\n'), (45, 'hypothesis.strategies.floats', 'floats', ([], {'min_value': '(0.3)', 'max_value': '(0.8)'}), False, 'from hypothesis.strategies import floats\n'), (54, 'pytest.main', 'pytest.main', (['[__file__]'], {}), False, 'import pytest\n'), (39, 'numpy.cos', 'cos', (['x'], {}), False, 'from numpy import cos\n'), (16, 'pytest.approx', 'approx', (['(0.0)'], {'rel': 'rel'}), False, 'from pytest import approx\n'), (17, 'pytest.approx', 'approx', (['x'], {'rel': 'rel'}), False, 'from pytest import approx\n')]