I am trying to learn the hypothesis testing library for python and I came up with the following example (taken from a math channel in youtube) which is a very simple arithmetic problem: find x, y, w, z
such that
x*y = 21 & x+w = 8 & y*z = 9 & w - z = 5
The solution is x = 2.1, y = 10, w = 5.9, z = 0.9
. Using hypothesis as a declarative programming library, I was expecting to find the solution rather quickly.
The code I used with hypothesis is:
from hypothesis import given
import hypothesis.strategies as st
from typing import Tuple
def f(a: float, b: float, c: float ,d: float) -> Tuple[float]:
return (a*b, a+c, b*d, c-d)
@given(
st.tuples(
st.floats(min_value=0),
st.floats(min_value=0),
st.floats(min_value=0),
st.floats(min_value=0)
)
)
def test_f(f32_tuple):
assert f(*f32_tuple) != (21, 8, 9, 5)
After launching it a few times with pytest, hypothesis is unable to find the solution. At first I thought it was a floating point comparison problem, or maybe the search space is just too enormous, so I decided to cut it back to integers (modifying the last number in the tuple), for example:
from hypothesis import given
import hypothesis.strategies as st
from typing import Tuple
def f(a: float, b: float, c: float ,d: float) -> Tuple[float]:
return (a*b, a+c, b*d, c-d)
@given(
st.tuples(
st.integers(min_value=0, max_value=10),
st.integers(min_value=0, max_value=10),
st.integers(min_value=0, max_value=10),
st.integers(min_value=0, max_value=10),
)
)
def test_f(f32_tuple):
assert f(*f32_tuple) != (21, 8, 9, -2)
Here, the solution would be the tuple (7, 3, 1, 3)
, the search space has "only" 10^4 elements so I expected it to find a solution after a few runs.
This behavior concerns me, since the usefulness of the library lies in its ability to detect cases one would not come up with normally.
Am I using the generators wrong? Or is hypothesis unable to deal with such cases? I need to know if I am going to use it in a day-to-day basis.