-
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
0 parents
commit 5d0bb9b
Showing
3 changed files
with
172 additions
and
0 deletions.
There are no files selected for viewing
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,28 @@ | ||
import numpy as np | ||
import pytest | ||
|
||
|
||
# add a commandline option to pytest | ||
def pytest_addoption(parser): | ||
"""Add random seed option to py.test. | ||
""" | ||
parser.addoption('--seed', dest='seed', type=int, action='store', | ||
help='set random seed') | ||
|
||
|
||
# configure pytest to automatically set the rnd seed if not passed on CLI | ||
def pytest_configure(config): | ||
seed = config.getvalue("seed") | ||
# if seed was not set by the user, we set one now | ||
if seed is None or seed == ('NO', 'DEFAULT'): | ||
config.option.seed = int(np.random.randint(2**31-1)) | ||
|
||
|
||
def pytest_report_header(config): | ||
return f'Using random seed: {config.option.seed}' | ||
|
||
|
||
@pytest.fixture | ||
def random_state(request): | ||
random_state = np.random.RandomState(request.config.option.seed) | ||
return random_state |
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,68 @@ | ||
import numpy as np | ||
from matplotlib import pyplot as plt | ||
|
||
from logistic import iterate_f | ||
|
||
def plot_trajectory(n, r, x0, fname="single_trajectory.png"): | ||
""" | ||
Saves a plot of a single trajectory of the logistic function | ||
inputs | ||
n: int (number of iterations) | ||
r: float (r value for the logistic function) | ||
x0: float (between 0 and 1, starting point for the iteration) | ||
fname: str (filename to which to save the image) | ||
returns | ||
fig, ax (matplotlib objects) | ||
""" | ||
l = iterate_f(n, x0, r) | ||
fig, ax = plt.subplots(figsize=(10,5)) | ||
ax.plot(list(range(n)), l) | ||
fig.suptitle('Logistic Function') | ||
|
||
fig.savefig(fname) | ||
return fig, ax | ||
|
||
|
||
def plot_bifurcation(start, end, step, fname="bifurcation.png", it=100000, | ||
last=300): | ||
""" | ||
Saves a plot of the bifurcation diagram of the logistic function. The | ||
`start`, `end`, and `step` parameters define for which r values to calculate | ||
the logistic function. If you space them too closely, it might take a very | ||
long time, if you dont plot enough, your bifurcation diagram won't be | ||
informative. Choose wisely! | ||
inputs | ||
start, end, step: float (which r values to calculate the logistic | ||
function for) | ||
fname: str (filename to which to save the image) | ||
it: int (how many iterations to run for each r value) | ||
last: int (how many of the last iterates to plot) | ||
returns | ||
fig, ax (matplotlib objects) | ||
""" | ||
r_range=np.arange(start, end, step) | ||
x=[] | ||
y=[] | ||
|
||
for r in r_range: | ||
l = iterate_f(it, 0.1, r) | ||
ll = l[len(l)-last::].copy() | ||
lll = np.unique(ll) | ||
y.extend(lll) | ||
x.extend(np.ones(len(lll))*r) | ||
|
||
fig, ax = plt.subplots(figsize=(20,10)) | ||
ax.scatter(x, y, s=0.1, color='k') | ||
ax.set_xlabel("r") | ||
fig.savefig(fname) | ||
return fig, ax | ||
|
||
|
||
if __name__=="__main__": | ||
plot_trajectory(100, 3.6, 0.1) | ||
plot_bifurcation(2.5, 4.2, 0.001) |
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,76 @@ | ||
# Testing Project for ASPP 2021 Bordeaux | ||
|
||
## Exercise 1 -- @parametrize and the logistic map | ||
|
||
Make a file `logistic.py` and `test_logistic.py`. Implement the code | ||
for the logistic map: | ||
|
||
a) Implement the logistic function f(π₯)=πβπ₯β(1βπ₯) . Use `@parametrize` | ||
to test the function for the following cases: | ||
``` | ||
x=0.1, r=2.2 => f(x, r)=0.198 | ||
x=0.2, r=3.4 => f(x, r)=0.544 | ||
x=0.75, r=1.7 => f(x, r)=0.31875 | ||
``` | ||
|
||
b) Implement the function `iterate_f` that runs `f` for `it` | ||
iterations, each time passing the result back into f. | ||
Use `@parametrize` to test the function for the following cases: | ||
``` | ||
x=0.1, r=2.2, it=1 => iterate_f(it, x, r)=[0.198] | ||
x=0.2, r=3.4, it=4 => f(x, r)=[0.544, 0.843418, 0.449019, 0.841163] | ||
x=0.75, r=1.7, it=2 => f(x, r)=[0.31875, 0.369152]] | ||
``` | ||
|
||
c) Use the `plot_trajectory` function from the `plot_logfun` module to look at | ||
the trajectories generated by your code. Try with values `r<3`, `r>4` and | ||
`3<r<4` to get a feeling for how the function behaves differently | ||
with different parameters. Note that your input x0 should be between 0 and 1. | ||
|
||
## Exercise 2 -- Check the convergence of an attractor using fuzzing | ||
a) Write a numerical fuzzing test that checks that, for `r=1.5`, all | ||
starting points converge to the attractor `f(x, r) = 1/3` . | ||
|
||
b) Use `pytest.mark` to mark the tests from the previous exercise with one mark | ||
(they relate to the correct implementation of the logistic function) and the | ||
test from this exercise with another (relates to the behavior of the logistic | ||
function). Try executing first the first set of tests and then the second set of | ||
tests separately. | ||
|
||
## Exercise 3 -- Chaotic behavior | ||
Some r values for `3<r<4` have some interesting properties. A chaotic | ||
trajectory doesn't diverge but also doesn't converge. | ||
|
||
## Visualize the bifurcation diagram | ||
a) Use the `plot_trajectory` function from the `plot_logfun` module using your | ||
implementation of `f` and `iterate_f` to look at the bifurcation diagram. | ||
|
||
The script generates an output image, `bifurcation_diagram.png`. | ||
|
||
b) Write a test that checks for chaotic behavior when r=3.8. Run the | ||
logistic map for 100000 iterations and verify the conditions for | ||
chaotic behavior: | ||
|
||
1) The function is deterministic: this does not need to be tested in | ||
this case | ||
2) Orbits must be bounded: check that all values are between 0 and 1 | ||
3) Orbits must be aperiodic: check that the last 1000 values are all | ||
different | ||
4) Sensitive dependence on initial conditions: this is the bonus | ||
exercise below | ||
|
||
The test should check conditions 2) and 3)! | ||
|
||
|
||
## Bonus Exercise 4 -- The Butterfly Effect | ||
For the same value of `r`, test the sensitive dependence on initial | ||
conditions, a.k.a. the butterfly effect. Use the following definition of SDIC. | ||
|
||
>`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 | ||