From 1f6cf681a71a5aab0116caa69cffe639512964ee Mon Sep 17 00:00:00 2001 From: ASPP Student Date: Tue, 29 Aug 2023 12:07:12 +0300 Subject: [PATCH 1/6] Add logistic function and generic cases test --- logistic.py | 6 +++++- test_logistic.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/logistic.py b/logistic.py index e49d1c2..4c26603 100644 --- a/logistic.py +++ b/logistic.py @@ -1 +1,5 @@ -# Your code goes here +def f(x, r): + """ + Implements the logistic function. + """ + return r * x * (1 - x) diff --git a/test_logistic.py b/test_logistic.py index 9391bee..cb5d457 100644 --- a/test_logistic.py +++ b/test_logistic.py @@ -14,3 +14,13 @@ def test_f_corner_cases(): for x, r, expected in cases: result = f(x, r) assert_allclose(result, expected) + +def test_f_generic_cases(): + cases = [ + (0.1, 2.2, 0.198), + (0.2, 3.4, 0.544), + (0.5, 2, 0.5), + ] + for x, r, expected in cases: + result = f(x, r) + assert_allclose(result, expected) \ No newline at end of file From 01da9260130aa2dc6b04d9f8660b2bbe80fcf5a0 Mon Sep 17 00:00:00 2001 From: ASPP Student Date: Tue, 29 Aug 2023 12:27:01 +0300 Subject: [PATCH 2/6] Use parametrize --- test_logistic.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/test_logistic.py b/test_logistic.py index cb5d457..5ebd5f4 100644 --- a/test_logistic.py +++ b/test_logistic.py @@ -1,26 +1,22 @@ +import pytest from numpy.testing import assert_allclose - from logistic import f -# Add here your test for the logistic map - - -def test_f_corner_cases(): - # Test cases are (x, r, expected) - cases = [ +@pytest.mark.parametrize('x, r, expected', [ (0, 1.1, 0), (1, 3.7, 0), ] - for x, r, expected in cases: - result = f(x, r) - assert_allclose(result, expected) +) +def test_f_corner_cases(x, r, expected): + result = f(x, r) + assert_allclose(result, expected) -def test_f_generic_cases(): - cases = [ +@pytest.mark.parametrize('x, r, expected', [ (0.1, 2.2, 0.198), (0.2, 3.4, 0.544), (0.5, 2, 0.5), ] - for x, r, expected in cases: - result = f(x, r) - assert_allclose(result, expected) \ No newline at end of file +) +def test_f_generic_cases(x, r, expected): + result = f(x, r) + assert_allclose(result, expected) \ No newline at end of file From 2dbbd40b3f3e7f2129eecab5c6ddb9eb599dae2b Mon Sep 17 00:00:00 2001 From: ASPP Student Date: Tue, 29 Aug 2023 12:54:14 +0300 Subject: [PATCH 3/6] Add iterate_f and corresponding test --- logistic.py | 9 +++++++++ test_logistic.py | 15 +++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/logistic.py b/logistic.py index 4c26603..470f560 100644 --- a/logistic.py +++ b/logistic.py @@ -1,5 +1,14 @@ +from plot_logistic import plot_trajectory + def f(x, r): """ Implements the logistic function. """ return r * x * (1 - x) + +def iterate_f(x, r, it): + traj = [x] + for _ in range(it): + x = f(x, r) + traj.append(x) + return traj diff --git a/test_logistic.py b/test_logistic.py index 5ebd5f4..46af459 100644 --- a/test_logistic.py +++ b/test_logistic.py @@ -1,6 +1,6 @@ import pytest from numpy.testing import assert_allclose -from logistic import f +from logistic import f, iterate_f @pytest.mark.parametrize('x, r, expected', [ (0, 1.1, 0), @@ -19,4 +19,15 @@ def test_f_corner_cases(x, r, expected): ) def test_f_generic_cases(x, r, expected): result = f(x, r) - assert_allclose(result, expected) \ No newline at end of file + assert_allclose(result, expected) + + +@pytest.mark.parametrize('x, r, it, expected', [ + (0.1, 2.2, 1, [0.1, 0.198]), + (0.2, 3.4, 4, [0.2, 0.544, 0.843418, 0.449019, 0.841163]), + (0.5, 2, 3, [0.5, 0.5, 0.5, 0.5]), + ] +) +def test_iterate_f(x, r, it, expected): + result = iterate_f(x, r, it) + assert_allclose(result, expected, rtol=5e-07) \ No newline at end of file From 07b8441b6d80de37976e38af131412e449276fd6 Mon Sep 17 00:00:00 2001 From: ASPP Student Date: Tue, 29 Aug 2023 14:53:14 +0300 Subject: [PATCH 4/6] Add test fit_r --- logistic.py | 2 -- logistic_fit.py | 2 +- test_logistic.py | 33 ++++++++++++++++++++++++++------- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/logistic.py b/logistic.py index 470f560..7f62337 100644 --- a/logistic.py +++ b/logistic.py @@ -1,5 +1,3 @@ -from plot_logistic import plot_trajectory - def f(x, r): """ Implements the logistic function. diff --git a/logistic_fit.py b/logistic_fit.py index 1d38ac7..55ee1f0 100644 --- a/logistic_fit.py +++ b/logistic_fit.py @@ -24,7 +24,7 @@ def fit_r(xs): it = len(xs) - 1 def error(r): - return np.linalg.norm(xs - iterate_f(it, x0, r)) + return np.linalg.norm(xs - iterate_f(x0, r, it)) errors = [] for r in np.linspace(0, 4, 4001): diff --git a/test_logistic.py b/test_logistic.py index 46af459..8ef0045 100644 --- a/test_logistic.py +++ b/test_logistic.py @@ -1,6 +1,10 @@ import pytest +import numpy as np from numpy.testing import assert_allclose -from logistic import f, iterate_f +from logistic import f +# from logistic import f, iterate_f +from logistic_fit import fit_r +from logistic import iterate_f @pytest.mark.parametrize('x, r, expected', [ (0, 1.1, 0), @@ -11,7 +15,9 @@ def test_f_corner_cases(x, r, expected): result = f(x, r) assert_allclose(result, expected) -@pytest.mark.parametrize('x, r, expected', [ +@pytest.mark.parametrize( + 'x, r, expected', + [ (0.1, 2.2, 0.198), (0.2, 3.4, 0.544), (0.5, 2, 0.5), @@ -22,12 +28,25 @@ def test_f_generic_cases(x, r, expected): assert_allclose(result, expected) -@pytest.mark.parametrize('x, r, it, expected', [ - (0.1, 2.2, 1, [0.1, 0.198]), - (0.2, 3.4, 4, [0.2, 0.544, 0.843418, 0.449019, 0.841163]), - (0.5, 2, 3, [0.5, 0.5, 0.5, 0.5]), +@pytest.mark.parametrize( + 'x, r, it, expected', + [ + (0.1, 2.2, 1, [0.1, 0.198]), + (0.2, 3.4, 4, [0.2, 0.544, 0.843418, 0.449019, 0.841163]), + (0.5, 2, 3, [0.5, 0.5, 0.5, 0.5]), ] ) def test_iterate_f(x, r, it, expected): result = iterate_f(x, r, it) - assert_allclose(result, expected, rtol=5e-07) \ No newline at end of file + assert_allclose(result, expected, rtol=5e-07) + +@pytest.mark.parametrize( + 'x, r, it', + [ + (0.3, 3.421, 23) + ] +) +def test_fit_r(x, r, it): + traj = iterate_f(x, r, it) + r_fitted = fit_r(traj) + assert_allclose(r, r_fitted) From 891ed45453455a739ca22337e1f6e13281aaf02b Mon Sep 17 00:00:00 2001 From: ASPP Student Date: Tue, 29 Aug 2023 15:23:16 +0300 Subject: [PATCH 5/6] Add convergence test --- test_logistic.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test_logistic.py b/test_logistic.py index 8ef0045..104a0ff 100644 --- a/test_logistic.py +++ b/test_logistic.py @@ -27,7 +27,6 @@ def test_f_generic_cases(x, r, expected): result = f(x, r) assert_allclose(result, expected) - @pytest.mark.parametrize( 'x, r, it, expected', [ @@ -50,3 +49,10 @@ def test_fit_r(x, r, it): traj = iterate_f(x, r, it) r_fitted = fit_r(traj) assert_allclose(r, r_fitted) + +def test_random_converge(r=1.5, it=100, expected=1/3, low=0.0001, high=0.9999, seed=42): + random_state = np.random.RandomState(seed) + for _ in range(100): + x0 = random_state.uniform(low, high) + traj = iterate_f(x0, r, it) + assert_allclose(traj[-1], expected, atol=1e-3) \ No newline at end of file From 16911ea919f637d236a78574a616a44f55ace9a9 Mon Sep 17 00:00:00 2001 From: ASPP Student Date: Tue, 29 Aug 2023 15:33:03 +0300 Subject: [PATCH 6/6] Add fixture for random seed --- test_logistic.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test_logistic.py b/test_logistic.py index 104a0ff..e6a4c41 100644 --- a/test_logistic.py +++ b/test_logistic.py @@ -6,6 +6,14 @@ from logistic_fit import fit_r from logistic import iterate_f +SEED = np.random.randint(0, 2**31) + +@pytest.fixture +def random_state(): + print(f'Using seed {SEED}') + random_state = np.random.RandomState(SEED) + return random_state + @pytest.mark.parametrize('x, r, expected', [ (0, 1.1, 0), (1, 3.7, 0), @@ -50,8 +58,7 @@ def test_fit_r(x, r, it): r_fitted = fit_r(traj) assert_allclose(r, r_fitted) -def test_random_converge(r=1.5, it=100, expected=1/3, low=0.0001, high=0.9999, seed=42): - random_state = np.random.RandomState(seed) +def test_random_converge(random_state, r=1.5, it=100, expected=1/3, low=0.0001, high=0.9999): for _ in range(100): x0 = random_state.uniform(low, high) traj = iterate_f(x0, r, it)