-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9fa911b
commit 19c23c2
Showing
4 changed files
with
153 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: Run all the tests for PRs | ||
on: | ||
[push, pull_request] | ||
|
||
jobs: | ||
run-tests: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up Python | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: 3.9 | ||
- name: Install dependencies | ||
run: | ||
python -m pip install pytest numpy | ||
- name: Test with pytest | ||
run: | ||
pytest -sv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import numpy as np | ||
|
||
|
||
def f(x, r): | ||
""" | ||
takes r and x as input and returns r*x*(1-x) | ||
""" | ||
return r * x * (1 - x) | ||
|
||
|
||
def iterate_f(it, xi, r): | ||
""" | ||
takes a number of iterations `it`, a starting value, | ||
and a parameter value for r. It should execute f repeatedly (it times), | ||
each time using the last result of f as the new input to f. Append each | ||
iteration's result to a list l. Finally, convert the list into a numpy | ||
array and return it. | ||
""" | ||
x = xi | ||
xs = [] | ||
for _ in range(it): | ||
x = f(x, r) | ||
xs.append(x) | ||
|
||
return np.array(xs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import numpy as np | ||
from numpy.testing import assert_allclose | ||
import pytest | ||
|
||
from logistic import f, iterate_f | ||
|
||
# set the random seed for once here | ||
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('a', [1, 2, 3]) | ||
@pytest.mark.parametrize('b', [5, 6, 7]) | ||
def test_addition_increases(a, b): | ||
print(a, b) | ||
assert b + a > a | ||
|
||
|
||
|
||
@pytest.mark.parametrize( | ||
'x, r, expected', | ||
[ | ||
(0.1, 2.2, 0.198), | ||
(0.2, 3.4, 0.544), | ||
(0.75, 1.7, 0.31875), | ||
] | ||
) | ||
def test_f(x, r, expected): | ||
result = f(x, r) | ||
assert_allclose(result, expected) | ||
|
||
|
||
@pytest.mark.parametrize( | ||
'x, r, it, expected', | ||
[ | ||
(0.1, 2.2, 1, [0.198]), | ||
(0.2, 3.4, 4, [0.544, 0.843418, 0.449019, 0.841163]), | ||
(0.75, 1.7, 2, [0.31875, 0.369152]), | ||
] | ||
) | ||
def test_iterate_f(x, r, it, expected): | ||
result = iterate_f(it, x, r) | ||
assert_allclose(result, expected, rtol=1e-5) | ||
|
||
|
||
def test_attractor_converges(): | ||
SEED = 42 | ||
random_state = np.random.RandomState(SEED) | ||
|
||
for _ in range(100): | ||
x = random_state.uniform(0, 1) | ||
result = iterate_f(100, x, 1.5) | ||
assert_allclose(result[-1], 1 / 3) | ||
|
||
#################################################################### | ||
# These only work after adding the fixture | ||
#################################################################### | ||
|
||
|
||
@pytest.mark.xfail | ||
def test_attractor_converges2(random_state): | ||
for _ in range(100): | ||
x = random_state.uniform(0, 1) | ||
result = iterate_f(100, x, 1.5) | ||
assert_allclose(result[-1], 1 / 3) | ||
|
||
|
||
@pytest.mark.xfail | ||
def test_chaotic_behavior(random_state): | ||
r = 3.8 | ||
for _ in range(10): | ||
x = random_state.uniform(0, 1) | ||
result = iterate_f(100000, x, r) | ||
assert np.all(result >= 0.0) | ||
assert np.all(result <= 1.0) | ||
assert min(np.abs(np.diff(result[-1000:]))) > 1e-6 | ||
|
||
|
||
@pytest.mark.xfail | ||
def test_sensitivity_to_initial_conditions(random_state): | ||
""" | ||
`f` is a function and `x0` and `y0` are two possible seeds. | ||
If `f` has SDIC then: | ||
there is a number `delta` such that for any `x0` there is a `y0` that is | ||
not more than `init_error` away from `x0`, where the initial condition `y0` | ||
has the property that there is some integer n such that after n iterations, | ||
the orbit is more than `delta` away from the orbit of `x0`. That is | ||
|xn-yn| > delta | ||
""" | ||
delta = 0.1 | ||
n = 10000 | ||
x0 = random_state.rand() | ||
x0_diffs = random_state.rand(100) * 0.001 - 0.0005 | ||
|
||
result_list = [] | ||
for x0_diff in x0_diffs: | ||
x1 = x0 + x0_diff | ||
l_x = iterate_f(n, x0, 3.8) | ||
l_y = iterate_f(n, x1, 3.8) | ||
result_list.append(any(abs(l_x - l_y) > delta)) | ||
assert any(result_list) |