From 306084908f73ec39b6cce21ef4189fdd5b343293 Mon Sep 17 00:00:00 2001 From: Amaras Date: Wed, 22 Jul 2020 23:04:59 +0200 Subject: [PATCH 1/4] Forward Euler method, version 1 --- .../code/coconut/euler.coco | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 contents/forward_euler_method/code/coconut/euler.coco diff --git a/contents/forward_euler_method/code/coconut/euler.coco b/contents/forward_euler_method/code/coconut/euler.coco new file mode 100644 index 000000000..89f82213a --- /dev/null +++ b/contents/forward_euler_method/code/coconut/euler.coco @@ -0,0 +1,23 @@ +import numpy as np + +def forward_euler(time_step, n): + y = 1 + for _ in range(n): + yield y + y *= (1 - 3 * time_step) + + +def check(result, threshold, time_step): + x = np.linspace(0, 1, 1 / time_step) + solution = np.exp(-3 * x) + return np.abs(solution - result) <= threshold).all() + + +if __name__ == '__main__': + time_step = 0.01 + n = 100 + threshold = 0.01 + + result = np.array(list(forward_euler(time_step, n))) + approx = check(result, threshold, time_step) + print("All values within threshold") if approx else print("Value(s) not in threshold") From 05a9720d9b5a9daf9c3776d52419c945f6295dc4 Mon Sep 17 00:00:00 2001 From: Amaras Date: Wed, 22 Jul 2020 23:08:32 +0200 Subject: [PATCH 2/4] Forward Euler method, version 2 --- .../forward_euler_method/code/coconut/euler.coco | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/contents/forward_euler_method/code/coconut/euler.coco b/contents/forward_euler_method/code/coconut/euler.coco index 89f82213a..24f83e8b1 100644 --- a/contents/forward_euler_method/code/coconut/euler.coco +++ b/contents/forward_euler_method/code/coconut/euler.coco @@ -1,4 +1,4 @@ -import numpy as np +import math def forward_euler(time_step, n): y = 1 @@ -8,9 +8,13 @@ def forward_euler(time_step, n): def check(result, threshold, time_step): - x = np.linspace(0, 1, 1 / time_step) - solution = np.exp(-3 * x) - return np.abs(solution - result) <= threshold).all() + approx = True + for i, y in enumerate(result): + solution = math.exp(-3 * i * time_step) + if not math.isclose(y, solution, abs_tol=threshold): + print(y, solution) + approx = False + return approx if __name__ == '__main__': @@ -18,6 +22,6 @@ if __name__ == '__main__': n = 100 threshold = 0.01 - result = np.array(list(forward_euler(time_step, n))) + result = list(forward_euler(time_step, n)) approx = check(result, threshold, time_step) print("All values within threshold") if approx else print("Value(s) not in threshold") From bf7923a6281e4dbf4afbbb5fe029e3e4fdf33dec Mon Sep 17 00:00:00 2001 From: Amaras Date: Wed, 22 Jul 2020 23:15:05 +0200 Subject: [PATCH 3/4] EUler method, version 2.1 --- contents/forward_euler_method/code/coconut/euler.coco | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contents/forward_euler_method/code/coconut/euler.coco b/contents/forward_euler_method/code/coconut/euler.coco index 24f83e8b1..2ffe29647 100644 --- a/contents/forward_euler_method/code/coconut/euler.coco +++ b/contents/forward_euler_method/code/coconut/euler.coco @@ -22,6 +22,6 @@ if __name__ == '__main__': n = 100 threshold = 0.01 - result = list(forward_euler(time_step, n)) + result = forward_euler(time_step, n) approx = check(result, threshold, time_step) print("All values within threshold") if approx else print("Value(s) not in threshold") From 62d0cebb97b1257aeada5f386e99c9e288acd82d Mon Sep 17 00:00:00 2001 From: Amaras Date: Fri, 13 Nov 2020 00:08:29 +0100 Subject: [PATCH 4/4] Forward Euler method, version 2.2: as functional as I could make it (for now) --- .../code/coconut/euler.coco | 17 +++++++++-------- .../forward_euler_method.md | 2 ++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/contents/forward_euler_method/code/coconut/euler.coco b/contents/forward_euler_method/code/coconut/euler.coco index 2ffe29647..7297e9c51 100644 --- a/contents/forward_euler_method/code/coconut/euler.coco +++ b/contents/forward_euler_method/code/coconut/euler.coco @@ -1,18 +1,19 @@ import math def forward_euler(time_step, n): - y = 1 - for _ in range(n): - yield y - y *= (1 - 3 * time_step) + factors = [1] + [1 - 3 * time_step] * (n-1) + # We want all the cumulative values, thus the use of scan + return scan((*), factors) + def check(result, threshold, time_step): approx = True - for i, y in enumerate(result): - solution = math.exp(-3 * i * time_step) - if not math.isclose(y, solution, abs_tol=threshold): - print(y, solution) + # A scan object has a len if the underlying iterable has a len + solution = range(len(result)) |> map$(i -> math.exp(-3*i*time_step)) + for y, sol in zip(result, solution): + if not math.isclose(y, sol, abs_tol=threshold): + print(y, sol) approx = False return approx diff --git a/contents/forward_euler_method/forward_euler_method.md b/contents/forward_euler_method/forward_euler_method.md index dfb185431..3547deb1c 100644 --- a/contents/forward_euler_method/forward_euler_method.md +++ b/contents/forward_euler_method/forward_euler_method.md @@ -146,6 +146,8 @@ Full code for the visualization follows: [import, lang:"nim"](code/nim/forwardeuler.nim) {% sample lang="lisp" %} [import, lang="lisp"](code/clisp/euler.lisp) +{%sample lang="coco" %} +[import, lang:"coconut"](code/coconut/euler.coco) {% endmethod %}