diff --git a/logistic.py b/logistic.py index e49d1c2..6983207 100644 --- a/logistic.py +++ b/logistic.py @@ -1 +1,17 @@ # Your code goes here +def f(x,r): + return r*x*(1-x) + +def iterate_f(x0,r,it): + iteration_timecourse = [] + + iteration_timecourse.append(x0) + + x = f(x0,r) + iteration_timecourse.append(x) + + for i in range(it-1): + x = f(x,r) + iteration_timecourse.append(x) + + return iteration_timecourse \ No newline at end of file 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/plot_logistic.py b/plot_logistic.py index 6227b5f..03bd185 100644 --- a/plot_logistic.py +++ b/plot_logistic.py @@ -10,7 +10,7 @@ from logistic import iterate_f -def plot_trajectory(n, r, x0, fname="single_trajectory.png"): +def plot_trajectory(x0,r,n, fname="single_trajectory.png"): """ Saves a plot of a single trajectory of the logistic function @@ -23,9 +23,9 @@ def plot_trajectory(n, r, x0, fname="single_trajectory.png"): returns fig, ax (matplotlib objects) """ - xs = iterate_f(n, x0, r) + xs = iterate_f(x0, r, n) fig, ax = plt.subplots(figsize=(10, 5)) - ax.plot(list(range(n)), xs) + ax.plot(list(range(n+1)), xs) fig.suptitle('Logistic Function') fig.savefig(fname) @@ -68,3 +68,14 @@ def plot_bifurcation(start, end, step, fname="bifurcation.png", it=100000, ax.set_xlabel("r") fig.savefig(fname) return fig, ax + + + + + +x0=0.1 +r=1.5 +n=20 + +plot_trajectory(x0, r, n) + \ No newline at end of file diff --git a/single_trajectory.png b/single_trajectory.png new file mode 100644 index 0000000..ae4a274 Binary files /dev/null and b/single_trajectory.png differ diff --git a/test_logistic.py b/test_logistic.py index 9391bee..1904ede 100644 --- a/test_logistic.py +++ b/test_logistic.py @@ -1,16 +1,60 @@ from numpy.testing import assert_allclose +from logistic import f, iterate_f +import pytest +from math import isclose +import numpy as np -from logistic import f - +SEED = np.random.randint(0, 2**31) # Add here your test for the logistic map +# def test_f_general(): +# 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) + + +# def test_f_corner_cases(): +# # Test cases are (x, r, expected) +# cases = [ +# (0, 1.1, 0), +# (1, 3.7, 0), +# ] +# for x, r, expected in cases: +# result = f(x, r) +# assert_allclose(result, expected) + + +# @pytest.mark.parametrize('x,r,expected',[(0.1,2.2,0.198),(0.2,3.4,0.544),(0.5,2,0.5),(0,1.1,0),(1,3.7,0)]) +# def test_f(x,r,expected): +# result = f(x,r) +# assert isclose(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,atol=0.001) + +@pytest.fixture +def random_state(): + print(f'\nUsing Seed: {SEED}') + random_state = np.random.RandomState(SEED) + return random_state -def test_f_corner_cases(): - # Test cases are (x, r, expected) - cases = [ - (0, 1.1, 0), - (1, 3.7, 0), - ] - for x, r, expected in cases: - result = f(x, r) - assert_allclose(result, expected) +def test_random_starting_point_convergence(random_state): + r = 1.5 + n = 100 + it = 30 + n_convergence_datapoints = 3 + for _ in range(n): + x0 = random_state.uniform(0.0001, 0.9999) + xs = iterate_f(x0,r,it) + for i in range(1, n_convergence_datapoints+1): + assert np.isclose(xs[-i], 1/3, atol=0.001) + \ No newline at end of file