text:
### A Pluto.jl notebook ###
# v0.15.1

using Markdown
using InteractiveUtils

# ╔═╡ 449faf07-3214-47b6-bb02-824cf900bc07
begin
	#using Markdown
	using PlutoUI
	using Plots
end

# ╔═╡ 2dd2d4e3-14a0-43f1-b207-969b98ee5346
PlutoUI.TableOfContents(aside=true)

# ╔═╡ 89f1748e-593f-473f-907d-b3a64073e197
md"""
## Physics and math concepts

- Free fall
- Air friction
- Terminal speed
- Ordinary differential equations (ODEs)

"""

# ╔═╡ f878dcc5-06db-4dd4-8df8-c4666cf8f605
md"""
## Julia and numerical concepts

- Array comprehension
- Broadcasting
- Plotting, using `Plots` package
- Function arguments and keywords
- Euler and midpoint methods for ODEs
"""

# ╔═╡ f5e86f2a-076d-11ec-1080-c341c92d3fd1
md"""
# Free Fall
"""

# ╔═╡ 26f6893e-17ab-48e9-88d0-98a79ec0a1b0
md"""
## Assumption

Suppose we drop a ball from some height, and suppose we do it in a vacuum where air resistance is not an issue. Realistically, this would have to be a contrived experiment in a lab. It would not be case if we just went outside and dropped a ball off the roof.

And so let's be honest and say we will **neglect air resistance or friction** in our study. The statement **neglect _______** is used often, and can mean a couple of things:

1. The thing being neglected produces an effect so small you will not notice it, or

2. The effect may not be tiny and it may have a big effect on things, but it's difficult to add and we want to get an **approximate** picture of what's happening before we go ahead, do a bunch of work, and then add it.

The last option is the case here. It forms an important **assumption** in our work that follows.
"""

# ╔═╡ ecb886b8-cf77-4d82-865b-d2af63f22a2e
md"""
## Acceleration

**Free fall** refers to an object falling due to gravity, without air resistance. In this case, it **accelerates**, or gains a set amount of speed in a set amount of time, without bound in principle. Near the surface of Earth, it is about 9.8 m/s every second. This **gravitational acceleration** is denoted by the symbol ``g``. Hence,

```math
g = 9.8 \, \text{m}/\text{s}^2 .
```

We do not need to consider time increments of one second. They can be anything. If it is ``\Delta t``, then the speed at that increment later is ``g\, \Delta t``.

Expressed as an equation, if the speed of the ball at time ``t`` is ``v(t)``, then its speed at a later time ``t + \Delta t$ will be given by
```math
v(t+ \Delta t) = v(t) + g \, \Delta t .
```

Rounding ``g`` up to a convenient 10 m/s``^2`` and dropping the ball from rest,

|   time [s] | speed [m/s] |
|:----------:|:---------:|
|   0        |     0     |
|   0.5      |     5     |
|   1.0      |     10    |
|   2.0      |     20    |
|   4.0      |     40    |
|   ...      |  ...      |

"""

# ╔═╡ a3e1ba79-2f26-4ceb-b32d-457d9eef5ef9
md"""
Now, what about the **distance** fallen? The distance covered is speed times time. For a constant speed we have for any time increment
```math
z(t+ \Delta t) = z(t) + v \, \Delta t .
```
But now the speed is continually changing. How to deal with that?

A couple of options come to mind:
1. Take the speed to be constant and equal to that at the *start* of the time increment, or
2. Take the speed to be constant and equal to that in the *middle* of the time increment, or
3. what else?
"""

# ╔═╡ fe7c9f07-10c7-4aa3-b303-211da17ec695
md"""
## Computer experiments
"""

# ╔═╡ 6e215ec5-dafb-4eb0-a159-b9028d6de08d
md"""
Let's now apply some computational thinking to explore this physical situation.
"""

# ╔═╡ fcba2327-2306-4fc3-bb70-14e94e5d55c5
md"""
Finding the speed increment is not an issue. But the distance increment poses a problem, since the speed *changes* during the increment. We can think immediately of two approaches:
- use the average speed at the start of the increment
- use the initial speed
"""

# ╔═╡ 809e639a-8492-4b0a-bc98-2226c2404478
function Δv_grav(Δt, a=10.0)
	Δt*a
end

# ╔═╡ dd4a6136-75a7-460d-9bbc-97a374e23a4f
function Δz(v₀, Δt, Δv::Function)
	v_ave = ( v₀ + (v₀ + Δv(Δt)) )/2
	v_ave*Δt
end

# ╔═╡ c90cceb1-5f04-46e5-8879-da29516ea81f
function Δz(v₀, Δt)
	v_init = v₀
	v_init*Δt
end

# ╔═╡ 52671566-39e8-4849-b27d-669f6bdb49db
md"""
>Question: What magic is going on with the definition of Δz?
>
>Answer: This is an example of **multiple dispatch**, a centerpiece of Julia.
"""

# ╔═╡ 453ad11f-7bed-49f7-8255-6b4e7a86ae57
md"""
Our strategy will be **discretize** time. This means we will calculate quantities only at set time values. This is a common thing to do in computation, since we cannot find quantities at infinitely many points infinitely close together. And this is likely not useful even we could.

It's natural to start things at zero time. We can then find the **time grid** given the time interval ``\Delta t`` and the number of time points we want to consider.
"""

# ╔═╡ 0e324d7d-932a-41a5-b4e8-924286ed6878
begin
	Δt = 0.2
	t = [n*Δt for n in 0:10]
end

# ╔═╡ bf58c0d6-1c31-4fcc-b9e6-72058c79d79a
md"""
Speed and distance fallen will be determined at these time grid points, and they will thus fill arrays of the same size. Set the **speed and distance grids**. It doesn't matter what values we fill them with initially, since they'll be overwritten by those we calculate.
"""

# ╔═╡ cc9737b7-33ee-48c4-9cbd-dde3f9b28afc
begin
	v = similar(t)
	z = similar(t)
	v[1] = 0.0    # initial speed
	z[1] = 0.0    # initial location

	z_ave = similar(z)
	z_init = similar(z)
end

# ╔═╡ de13ad92-d15f-450a-9388-4e765c29ea66
md"""
Step through the time grid and get the speed and the distance fallen up to that time (using the two methods). We know what they are initially, so start at second grip point.
"""

# ╔═╡ e59e1646-d949-456d-8e28-a4f9e1f55a8a
for i in 2:length(v)
	v[i] = v[i-1] + Δv_grav(Δt)
	z_init[i] = z_init[i-1] + Δz(v[i-1], Δt)
	z_ave[i] = z_ave[i-1] + Δz(v[i-1], Δt, Δv_grav)
end

# ╔═╡ 421f19c1-38eb-4cff-b8d4-7a6ae4f438d0
md"""
"Sanity check" of the results... show the arrays.
"""

# ╔═╡ a87dd44d-89ca-41cc-b077-d444ea37c48d
v

# ╔═╡ becfff3a-b130-44e8-8f9b-f63d693fdc0d
z_init

# ╔═╡ 20e80196-d302-44ad-af58-c2c6211bcc95
z_ave

# ╔═╡ 202922e8-9d1a-4a23-afdc-f91deceb899e
md"""
>Question: Anything strange here?
>
>Answer:
"""

# ╔═╡ d98ad456-1f29-4047-8724-78a8cb35187a
md"""
Plot speed as a function of time.
"""

# ╔═╡ bafa445a-f3c8-4e83-bfa7-2b907bd33319
begin
	plot(t,v,label="v")
	plot!(title="speed vs time",xlabel="time [s]",ylabel="speed [m/s]")
end

# ╔═╡ 1d0dab51-947d-40f6-a38b-6bf54b1595cf
md"""
Now look at distance, and compare our two approaches. We also know the exact result

```math
z(t) = z_0 + v_0 t + \frac{1}{2} g t^2
```

and show that for comparison.
"""

# ╔═╡ 2f305768-1b2b-4939-926e-dee480da23f1
function z_exact(z₀, v₀, t, a=10.0)
		z₀ + v₀*t + a*t^2 / 2
end

# ╔═╡ 6afbfcf5-d0ed-484a-85df-9629f9d731f4
begin
	plot(t, z_init, label="init")
	plot!(t, z_ave, label="ave")
	plot!(t, z_exact.(z[1],v[1],t),label="exact")
	plot!(title="distance vs time",xlabel="time [s]",ylabel="distance [m]")
end

# ╔═╡ 2bfc8a93-4dc6-4c44-8df9-41866e52a681
md"""
>Question: What magic is happening in the plot command for the exact results?
>
>Answer: This is called **broadcasting**.
"""

# ╔═╡ 15bf0e04-9996-4c03-ae80-2e1df0151c85
z_exact.(z[1],v[1],t)

# ╔═╡ a9409040-77ea-442f-89c5-a5f7636b3e56
md"""
>Question: Which approach for calculating the distance is the best? Experiment with decreasing ``\Delta t`` (and increasing the number of grid points to keep the final time the same). What happens?
>
>Answer:
"""

# ╔═╡ 16b85f25-b033-47f0-a9a9-e92ae0ad97de
md"""
# Air friction
"""

# ╔═╡ 90e92459-1bfa-41b1-a0e1-e9499ef0d3b2
md"""
## A model
"""

# ╔═╡ b64d55a2-2272-4fb4-b71c-bc0e4ad0bfff
md"""
Air resistance or friction is complicated, and accurate approximate treatments require state-of-the-art computational fluid dynamics.

One model for the friction force that is generally decent is

```math
f = \frac{1}{2} C_d\, \rho\, A\, v^2 ,
```
where
- ``C_d`` is the **coefficient of dynamic friction**, and takes into account all the complicated effects of air moving around the object,
- ``\rho`` is the density of air,
- ``A`` is the cross-sectional area of the object,
- ``v`` is its speed, and
- ``m`` is its mass (used later).

The friction force is always directed *opposite* to the direction of motion.

It's effect is to decrease the object speed by
```math
\Delta v = -\frac{f}{m} \Delta t,
```
if ``\Delta t \rightarrow 0``.

Our time intervals are not **infinitesimally small**, so this becomes another approximation. And unfortunately, ``\Delta v`` depends on speed, so it is *not constant* over a time interval.
"""

# ╔═╡ c72fe0c7-c08a-4447-a727-612717c67e11
md"""
Learning from the distance study above, it looks reasonable to find the change in speed in an internal using the speed in the *middle* of the interval. So what we are doing is
1. **Stepping forward** a half interval, and then using that to
2. Step forward the whole interval.
"""

# ╔═╡ 930a4dff-f3ca-4817-9bd7-ef5c1d476431
md"""
## Computer experiments
"""

# ╔═╡ ea8c0bb9-c6bf-4be5-a582-f637de2bfa15
md"""
We need to consider a concrete example. Let's use a baseball.

Parameters:

- ``m = 0.145`` kg
- ``C_d = 0.346``
- ``\rho = 1.225`` kg/m``^3``
- ``A = 0.0043`` m``^2``
"""

# ╔═╡ 7a7b5329-582a-467b-a797-711e63e11966
function Δv_friction(v_i, Δt, a=10.0; mass=0.145, C_d=0.346, ρ=1.225, A=0.0043)
	f = C_d*ρ*A*v_i^2 / 2
	-(f/mass)*Δt
end

# ╔═╡ 4656fd48-7908-4c12-9117-4bf8a9e40a9a
function v_update!(v, Δt, Δv_grav::Function, Δv_friction::Function)
	for i in 2:length(v)
		v_halfstep = v[i-1] + ( Δv_grav(Δt/2) + Δv_friction(v[i-1], Δt/2) )
		v[i] = v[i-1] + ( Δv_grav(Δt) + Δv_friction(v_halfstep, Δt) )
	end
end

# ╔═╡ e60f5c16-f960-4c33-b966-4aa96b62ea84
begin
	v_update!(v, Δt, Δv_grav, Δv_friction0)
	v_friction = copy(v)
end

# ╔═╡ c356c512-565b-4da3-9d77-a12da63d349c
begin
	plot(t,v_friction,label="v")
	plot!(title="speed vs time",xlabel="time [s]",ylabel="speed [m/s]")
end

# ╔═╡ d8331098-d52c-4cd1-90d0-2756d6b6589e
md"""
Experiment with longer fall times, say out to 20 s. Notice that the speed behaves differently than with no friction. It approaches a limiting value, known as the **terminal speed**. This is different for every object.

Also, by updating according to the approach in `v_update!`, we have essentially solved a **differential equation** for the speed using a numerical technique called the **midpoint method** or **second-order Runge-Kutta**.

"""

# ╔═╡ 01d90dbf-b9ea-4daa-8141-022e974bdbed
md"""
>Question: Experiment with changing ``\Delta t`` (and increasing the number of grid points to keep the final time the same). What happens to the value of the terminal speed?
>
>Answer:
"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"

[compat]
Plots = "~1.21.2"
PlutoUI = "~0.7.9"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

[[Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "84918055d15b3114ede17ac6a7182f68870c16f7"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.1"

[[ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c3598e525718abcc440f69cc6d5f60dda0a1b61e"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.6+5"

[[Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "e2f47f6d8337369411569fd45ae5753ca10394c6"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.0+6"

[[ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "9995eb3977fbf67b86d0a0a0508e83017ded03f2"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.14.0"

[[ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.0"

[[Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "727e463cfebd0c7b999bbf3e9e7e16f254b94193"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.34.0"

[[CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[Contour]]
deps = ["StaticArrays"]
git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.5.7"

[[DataAPI]]
git-tree-sha1 = "ee400abb2298bd13bfc3df1c412ed228061a2385"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.7.0"

[[DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "7d9d316f04214f7efdbb6398d545446e246eff02"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.10"

[[DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "92d8f9f208637e8d2d28c664051a00569c01493d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.1.5+1"

[[Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b3bfd02e98aedfa5cf885665493c5598c350cd2f"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.2.10+0"

[[FFMPEG]]
deps = ["FFMPEG_jll"]
git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8"
uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
version = "0.4.1"

[[FFMPEG_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "LibVPX_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.3.1+4"

[[FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "35895cf184ceaab11fd778b4590144034a167a2f"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.1+14"

[[Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "cbd58c9deb1d304f5a245a0b7eb841a2560cfec6"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.1+5"

[[FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "dba1e8614e98949abfa60480b13653813d8f0157"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+0"

[[GR]]
deps = ["Base64", "DelimitedFiles", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Printf", "Random", "Serialization", "Sockets", "Test", "UUIDs"]
git-tree-sha1 = "182da592436e287758ded5be6e32c406de3a2e47"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.58.1"

[[GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "d59e8320c2747553788e4fc42231489cc602fa50"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.58.1+0"

[[GeometryBasics]]
deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "58bcdf5ebc057b085e58d95c138725628dd7453c"
uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
version = "0.4.1"

[[Gettext_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.21.0+0"

[[Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "7bf67e9a481712b3dbe9cb3dac852dc4b1162e02"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+0"

[[Grisu]]
git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2"
uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe"
version = "1.0.2"

[[HTTP]]
deps = ["Base64", "Dates", "IniFile", "Logging", "MbedTLS", "NetworkOptions", "Sockets", "URIs"]
git-tree-sha1 = "44e3b40da000eab4ccb1aecdc4801c040026aeb5"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.13"

[[IniFile]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.0"

[[InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[IterTools]]
git-tree-sha1 = "05110a2ab1fc5f932622ffea2a003221f4782c18"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.3.0"

[[IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.3.0"

[[JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

[[JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d735490ac75c5cb9f1b00d8b5509c11984dc6943"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.0+0"

[[LAME_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c"
uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d"
version = "3.100.1+0"

[[LZO_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6"
uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac"
version = "2.10.1+0"

[[LaTeXStrings]]
git-tree-sha1 = "c7f1c695e06c01b95a67f0cd1d34994f3e7db104"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.2.1"

[[Latexify]]
deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "Printf", "Requires"]
git-tree-sha1 = "a4b12a1bd2ebade87891ab7e36fdbce582301a92"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.6"

[[LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[LibVPX_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "12ee7e23fa4d18361e7c2cde8f8337d4c3101bc7"
uuid = "dd192d2f-8180-539f-9fb4-cc70b1dcf69a"
version = "1.10.0+0"

[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[Libffi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "761a393aeccd6aa92ec3515e428c26bf99575b3b"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+0"

[[Libgcrypt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"]
git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae"
uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4"
version = "1.8.7+0"

[[Libglvnd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"]
git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf"
uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29"
version = "1.3.0+3"

[[Libgpg_error_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9"
uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8"
version = "1.42.0+0"

[[Libiconv_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778"
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
version = "1.16.1+1"

[[Libmount_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73"
uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9"
version = "2.35.0+0"

[[Libtiff_jll]]
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.0+0"

[[Libuuid_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066"
uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700"
version = "2.36.0+0"

[[LinearAlgebra]]
deps = ["Libdl"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "0fb723cd8c45858c22169b2e42269e53271a6df7"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.7"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[MbedTLS]]
deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"]
git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "1.0.3"

[[MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[Measures]]
git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f"
uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
version = "0.3.1"

[[Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "2ca267b08821e86c5ef4376cffed98a46c2cb205"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.1"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[NaNMath]]
git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.5"

[[NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[Ogg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7937eda4681660b4d6aeeecc2f7e1c81c8ee4e2f"
uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051"
version = "1.3.5+0"

[[OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "15003dcb7d8db3c6c857fda14891a539a8f2705a"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.10+0"

[[Opus_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720"
uuid = "91d4177d-7536-5919-b921-800302f37372"
version = "1.3.2+0"

[[OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[PCRE_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488"
uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc"
version = "8.44.0+0"

[[Parsers]]
deps = ["Dates"]
git-tree-sha1 = "438d35d2d95ae2c5e8780b330592b6de8494e779"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.0.3"

[[Pixman_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29"
uuid = "30392449-352a-5448-841d-b1acce4e97dc"
version = "0.40.1+0"

[[Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[PlotThemes]]
deps = ["PlotUtils", "Requires", "Statistics"]
git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "2.0.1"

[[PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "9ff1c70190c1c30aebca35dc489f7411b256cd23"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.0.13"

[[Plots]]
deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"]
git-tree-sha1 = "9e1a400fb1f27b4146fe35dc1a22de6c793b8f20"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.21.2"

[[PlutoUI]]
deps = ["Base64", "Dates", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "Suppressor"]
git-tree-sha1 = "44e225d5837e2a2345e69a1d1e01ac2443ff9fcb"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.9"

[[Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.2"

[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[Qt5Base_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"]
git-tree-sha1 = "ad368663a5e20dbb8d6dc2fddeefe4dae0781ae8"
uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1"
version = "5.15.3+0"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[RecipesBase]]
git-tree-sha1 = "44a75aa7a527910ee3d1751d1f0e4148698add9e"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.1.2"

[[RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "d4491becdc53580c6dadb0f6249f90caae888554"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.4.0"

[[Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "4036a3bd08ac7e968e27c203d45f5fff15020621"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.1.3"

[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[Scratch]]
deps = ["Dates"]
git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.1.0"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[Showoff]]
deps = ["Dates", "Grisu"]
git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de"
uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
version = "1.0.3"

[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "3240808c6d463ac46f1c1cd7638375cd22abbccb"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.12"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[StatsAPI]]
git-tree-sha1 = "1958272568dc176a1d881acb797beb909c785510"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.0.0"

[[StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "8cbbc098554648c84f79a463c9ff0fd277144b6c"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.10"

[[StructArrays]]
deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"]
git-tree-sha1 = "1700b86ad59348c0f9f68ddc95117071f947072d"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.1"

[[Suppressor]]
git-tree-sha1 = "a819d77f31f83e5792a76081eee1ea6342ab8787"
uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
version = "0.2.0"

[[TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "d0c690d37c73aeb5ca063056283fde5585a41710"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.5.0"

[[Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[URIs]]
git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.3.0"

[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[Wayland_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "3e61f0b86f90dacb0bc0e73a0c5a83f6a8636e23"
uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89"
version = "1.19.0+0"

[[Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll"]
git-tree-sha1 = "2839f1c1296940218e35df0bbb220f2a79686670"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.18.0+4"

[[XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

[[Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

[[Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[Xorg_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

[[Xorg_xcb_util_image_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97"
uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b"
version = "0.4.0+1"

[[Xorg_xcb_util_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"]
git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1"
uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5"
version = "0.4.0+1"

[[Xorg_xcb_util_keysyms_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00"
uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7"
version = "0.4.0+1"

[[Xorg_xcb_util_renderutil_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e"
uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e"
version = "0.3.9+1"

[[Xorg_xcb_util_wm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67"
uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361"
version = "0.4.1+1"

[[Xorg_xkbcomp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"]
git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b"
uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4"
version = "1.4.2+4"

[[Xorg_xkeyboard_config_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"]
git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d"
uuid = "33bec58e-1273-512f-9401-5d533626f822"
version = "2.27.0+4"

[[Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

[[Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[Zstd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "cc4bf3fdde8b7e3e9fa0351bdeedba1cf3b7f6e6"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.0+0"

[[libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "acc685bcf777b2202a904cdcb49ad34c2fa1880c"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.14.0+4"

[[libfdk_aac_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7a5780a0d9c6864184b3a2eeeb833a0c871f00ab"
uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280"
version = "0.1.6+4"

[[libpng_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c"
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
version = "1.6.38+0"

[[libvorbis_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "c45f4e40e7aafe9d086379e5578947ec8b95a8fb"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+0"

[[nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"

[[x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d713c1ce4deac133e3334ee12f4adff07f81778f"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2020.7.14+2"

[[x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "487da2f8f2f0c8ee0e83f39d13037d6bbf0a45ab"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.0.0+3"

[[xkbcommon_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"]
git-tree-sha1 = "ece2350174195bb31de1a63bea3a41ae1aa593b6"
uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd"
version = "0.9.1+5"
"""

# ╔═╡ Cell order:
# ╠═449faf07-3214-47b6-bb02-824cf900bc07
# ╠═2dd2d4e3-14a0-43f1-b207-969b98ee5346
# ╟─89f1748e-593f-473f-907d-b3a64073e197
# ╟─f878dcc5-06db-4dd4-8df8-c4666cf8f605
# ╟─f5e86f2a-076d-11ec-1080-c341c92d3fd1
# ╟─26f6893e-17ab-48e9-88d0-98a79ec0a1b0
# ╟─ecb886b8-cf77-4d82-865b-d2af63f22a2e
# ╟─a3e1ba79-2f26-4ceb-b32d-457d9eef5ef9
# ╟─fe7c9f07-10c7-4aa3-b303-211da17ec695
# ╟─6e215ec5-dafb-4eb0-a159-b9028d6de08d
# ╟─fcba2327-2306-4fc3-bb70-14e94e5d55c5
# ╠═809e639a-8492-4b0a-bc98-2226c2404478
# ╠═dd4a6136-75a7-460d-9bbc-97a374e23a4f
# ╠═c90cceb1-5f04-46e5-8879-da29516ea81f
# ╟─52671566-39e8-4849-b27d-669f6bdb49db
# ╟─453ad11f-7bed-49f7-8255-6b4e7a86ae57
# ╠═0e324d7d-932a-41a5-b4e8-924286ed6878
# ╟─bf58c0d6-1c31-4fcc-b9e6-72058c79d79a
# ╠═cc9737b7-33ee-48c4-9cbd-dde3f9b28afc
# ╟─de13ad92-d15f-450a-9388-4e765c29ea66
# ╠═e59e1646-d949-456d-8e28-a4f9e1f55a8a
# ╟─421f19c1-38eb-4cff-b8d4-7a6ae4f438d0
# ╠═a87dd44d-89ca-41cc-b077-d444ea37c48d
# ╠═becfff3a-b130-44e8-8f9b-f63d693fdc0d
# ╠═20e80196-d302-44ad-af58-c2c6211bcc95
# ╟─202922e8-9d1a-4a23-afdc-f91deceb899e
# ╟─d98ad456-1f29-4047-8724-78a8cb35187a
# ╠═bafa445a-f3c8-4e83-bfa7-2b907bd33319
# ╟─1d0dab51-947d-40f6-a38b-6bf54b1595cf
# ╠═2f305768-1b2b-4939-926e-dee480da23f1
# ╠═6afbfcf5-d0ed-484a-85df-9629f9d731f4
# ╟─2bfc8a93-4dc6-4c44-8df9-41866e52a681
# ╠═15bf0e04-9996-4c03-ae80-2e1df0151c85
# ╟─a9409040-77ea-442f-89c5-a5f7636b3e56
# ╟─16b85f25-b033-47f0-a9a9-e92ae0ad97de
# ╟─90e92459-1bfa-41b1-a0e1-e9499ef0d3b2
# ╟─b64d55a2-2272-4fb4-b71c-bc0e4ad0bfff
# ╟─c72fe0c7-c08a-4447-a727-612717c67e11
# ╟─930a4dff-f3ca-4817-9bd7-ef5c1d476431
# ╟─ea8c0bb9-c6bf-4be5-a582-f637de2bfa15
# ╠═7a7b5329-582a-467b-a797-711e63e11966
# ╠═4656fd48-7908-4c12-9117-4bf8a9e40a9a
# ╠═e60f5c16-f960-4c33-b966-4aa96b62ea84
# ╠═c356c512-565b-4da3-9d77-a12da63d349c
# ╟─d8331098-d52c-4cd1-90d0-2756d6b6589e
# ╟─01d90dbf-b9ea-4daa-8141-022e974bdbed
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: jamesamiller/Computational-Thinking

max_issues_repo_name: jamesamiller/Computational-Thinking

max_forks_repo_name: jamesamiller/Computational-Thinking


text:
# Autogenerated wrapper script for FastHadamardStructuredTransforms_jll for x86_64-w64-mingw32
export libfasttransforms

JLLWrappers.@generate_wrapper_header("FastHadamardStructuredTransforms")
JLLWrappers.@declare_library_product(libfasttransforms, "libfasttransforms.dll")
function __init__()
    JLLWrappers.@generate_init_header()
    JLLWrappers.@init_library_product(
        libfasttransforms,
        "bin\\libfasttransforms.dll",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()

ext: jl


text:
#=
    Figure 1
=#

using Model # To get colours

using CSV
using ColorSchemes
using DataFrames
using DataFramesMeta
using Plots
using StatsPlots

include("../figure_defaults.jl")

##############################################################
## Data (at t = 10 min)
##############################################################

data = @subset(CSV.read("Data/CSV/DualMarker.csv",DataFrame), :Temp .== 37.0, :Time .== 10.0)

##############################################################
## Univariate
##############################################################

p1 = @df @subset(data,(!).(:Quenched)) density(:Signal_Cy5  / 1e4,c=col_Q,lw=2.0,frange=0.0,fα=0.4,label="Not quenched")
@df @subset(data,:Quenched) density!(p1,:Signal_Cy5 / 1e4,c=col_Q̄,lw=2.0,frange=0.0,fα=0.4,ls=:dash,label="Quenched")
plot!(p1,xlim=(0.0,1.5),widen=:false,yticks=[],xlabel="Cy5 (10⁴)")

p2 = @df @subset(data,(!).(:Quenched)) density(:Signal_BDP,c=col_U,lw=2.0,frange=0.0,fα=0.4,label="Not quenched")
@df @subset(data,:Quenched) density!(p2,:Signal_BDP,c=col_Ū,lw=2.0,frange=0.0,fα=0.4,ls=:dash,label="Quenched")
plot!(p2,xlim=(0.0,100.0),widen=:false,yticks=[],xlabel="BDP")

fig1di = plot(p1,p2,layout=grid(2,1),axis=:x,grid=:x)

##############################################################
## Bivariate plots
##############################################################

cs1 = ColorScheme(range(colorant"white",parse(Colorant,col_QU),length=200))
cs2 = ColorScheme(range(colorant"white",parse(Colorant,col_Q̄Ū),length=200))

p3 = @df @subset(data,:Quenched) density2d(:Signal_Cy5,:Signal_BDP,c=palette(cs2),lc=col_Q̄Ū,lw=1.0,fill=true)

p4 = @df @subset(data,(!).(:Quenched)) density2d(:Signal_Cy5,:Signal_BDP,c=palette(cs1),lc=col_QU,lw=1.0,fill=true)

fig1dii = plot(p3,p4,layout=grid(2,1),
    box=:on,xlim=(0.0,1e4),ylim=(0.0,100),
    xformatter=x->x / 1e4,
    xlabel="Cy5 (10⁴)",
    ylabel="BDP",grid=:all)

##############################################################
## Save
##############################################################

plot(fig1di,fig1dii,layout=grid(1,2),size=(500,500))
savefig("$(@__DIR__)/Fig1.svg")

max_stars_repo_name: ap-browning/internalisation

max_issues_repo_name: ap-browning/internalisation

max_forks_repo_name: ap-browning/internalisation


text:
# Run conventional GA (or infinite alleles) algorithm to optimize digital circuits.
export run_inf_alleles, inf_alleles, inf_alleles_to_tuple

using DataFrames
using CSV

mutable struct inf_alleles_result_type
  numinputs::Int64
  numoutputs::Int64
  numints::Int64
  levsback::Int64
  gl::Vector{Goal}
  popsize::Int64
  max_pop_gens::Int64
  tourn_size::Int64
  func_evals::Int64
  fitness::Float64
  gen_finished::Int64
end

# This is the top-level function to run multiple simulations in parallel using pmap.
# Parameters of type IntRange can be Int64s or Bools or AbstractRanges{Int64} or AbstractRanges{Bool}.
function run_inf_alleles( nreps::Int64,
    numinputs::IntRange, numoutputs::IntRange, numinteriors::IntRange, ngoals_rng::IntRange, levelsback::IntRange,
    popsize_rng::IntRange, max_pop_gens_rng::IntRange, tournsize::Int64, csvfile::String )
  nodearity = 2
  inf_alleles_param_list = inf_alleles_result_type[]
  df = DataFrame()
  df.numinputs = Int64[]
  df.numoutputs = Int64[]
  df.numints = Int64[]
  df.levsback = Int64[]
  #df.gl = Vector{Goal}[]
  df.ngoals = Int64[]
  df.popsize = Int64[]
  df.max_pop_gens = Int64[]
  df.tournsize = Int64[]
  df.func_evals=Int64[]
  df.fitness = Float64[]
  df.gen_finished = Int64[]
  iter = 1   # iteration
  for num_inputs = numinputs
    for num_outputs = numoutputs
      funcs = default_funcs(num_inputs)
      for ngoals = ngoals_rng
        gl = randgoallist(ngoals,num_inputs,num_outputs)
        for num_interiors = numinteriors
          for levsback = levelsback
            for max_pop_gens = max_pop_gens_rng
              for popsize = popsize_rng
                for i = 1:nreps
                  p = Parameters( num_inputs, num_outputs, num_interiors, levsback )
                  #println("run inf_alleles: iter: ",iter)
                  ia = inf_alleles_result( p, gl, popsize=popsize,  max_pop_gens=max_pop_gens, tourn_size=tournsize )
                  push!(inf_alleles_param_list,ia)
                  iter += 1
                end
              end
            end
          end
        end
      end
    end
  end
  inf_alleles_result_list = pmap( x->inf_alleles(x), inf_alleles_param_list )
  #inf_alleles_result_list = map( x->inf_alleles(x), inf_alleles_param_list )
  for ia in inf_alleles_result_list
    new_row = inf_alleles_to_tuple(ia)
    Base.push!( df, new_row )
  end
  println()
  open( csvfile, "w" ) do f
    println(f,"MyInt: ",Main.CGP.MyInt)
    println(f,"funcs: ", Main.CGP.default_funcs(numinputs[end]))
    println(f,"nodearity: ",nodearity)
    CSV.write( f, df, append=true, writeheader=true )
  end
  df
end

function inf_alleles( ia::inf_alleles_result_type )
  funcs = default_funcs( ia.numinputs )
  context = construct_context(ia.numinputs)
  p = Parameters( numinputs=ia.numinputs, numoutputs=ia.numoutputs, numinteriors=ia.numints, numlevelsback=ia.levsback )
  pop = [ random_chromosome(p,funcs) for _ = 1:ia.popsize ]
  @assert ia.numinputs == p.numinputs
  for g = 1:ia.max_pop_gens
    fit_vector = zeros(Float64,ia.popsize)
    for i = 1:ia.popsize
      new_c = deepcopy(pop[i])
      mutate_chromosome!( new_c, funcs )
      output = execute_chromosome(new_c,context)
      ( new_c.fitness, matched_goals, matched_goals_list ) = goals_matched_hamming( output, ia.gl, p.numinputs)
      pop[i] = new_c
      fit_vector[i] = pop[i].fitness
    end
    #println("g:",g,"  fitv: ",fit_vector)
    maxfit = findmax( fit_vector )
    if Int(trunc(maxfit[1])) == p.numoutputs
      #println("optimum at generation ",g," = ",pop[maxfit[2]].fitness)
      ia.fitness = maxfit[1]
      ia.gen_finished = g
      ia.func_evals = g*ia.popsize
      print(".")
      #return (maxfit[1], g)
      return ia
    elseif g == ia.max_pop_gens  # return best fitness chromosome
      #println("Best fitness found: ",maxfit," after ",max_pop_gens," generations" )
      ia.fitness = maxfit[1]
      ia.gen_finished = ia.max_pop_gens
      ia.func_evals = ia.max_pop_gens*ia.popsize
      print(".")
      #return (maxfit[1], max_pop_gens)
      return ia
    end
    if ia.tourn_size == 0
      propsel!( pop, fit_vector )
    else
      tournsel!( pop, fit_vector, ia.tourn_size )
    end
  end
end

function inf_alleles_result( p::Parameters, gl::Vector{Goal} ;
    popsize::Int64=3, max_pop_gens::Int64=10, tourn_size::Int64=0 )
  inf_alleles_result_type( p.numinputs, p.numoutputs, p.numinteriors, p.numlevelsback, gl, popsize, max_pop_gens,
        tourn_size, 0, 0.0, 0 )
end

function inf_alleles_to_tuple( ia::inf_alleles_result_type )
  (
    ia.numinputs,
    ia.numoutputs,
    ia.numints,
    ia.levsback,
    length(ia.gl),
    ia.popsize,
    ia.max_pop_gens,
    ia.tourn_size,
    ia.func_evals,
    ia.fitness,
    ia.gen_finished
  )
end


text:
abstract type AbstractCallback end
abstract type SafeCallback <: AbstractCallback end
"""
    abstract type Callback

Callbacks can add custom functionality to the training loop.
See [custom callbacks](../docs/callbacks/custom.md) for more info.
"""
const Callback = SafeCallback
abstract type UnsafeCallback <: AbstractCallback end

# TODO: implement proper merging of permissions

"""
    stateaccess(callback)

Return a named tuple determining what learner state `callback`
can access. The default is `(;)`, the empty named tuple, meaning
no state can be accessed. Implementations of `stateaccess` should
always return the least permissions possible.

For example, the [`ToGPU`](#) callback needs to write both the model and
the batch data, so its `stateaccess` implementation is:

```julia
stateaccess(::ToGPU) = (
    model = Write(),
    params = Write(),
    step = (xs = Write(), ys = Write()),
)
```

When defining `stateaccess`, be careful that you do return a `NamedTuple`.
`(x = Read(),)` is one but `(x = Read())` (without the comma) is parsed as
an assignment with value `Read()`.
"""
stateaccess(::Callback) = (;)
runafter(::AbstractCallback) = ()

"""
    abstract type ConflictResolution

A conflict resolution strategy for resolving write/write conflicts
of two callbacks.

See [`resolveconflict`](#).
"""
abstract type ConflictResolution end
struct NotDefined <: ConflictResolution end
struct Unresolvable <: ConflictResolution end
struct RunFirst <: ConflictResolution cb end
struct NoConflict <: ConflictResolution end

function _resolveconflict(cb1, cb2)
    r = resolveconflict(cb1, cb2)
    if r === NotDefined()
        return resolveconflict(cb2, cb1)
    else
        return r
    end
end

"""
    resolveconflict(cb1, cb2)

Define a conflict resolution strategy for resolving a write/write conflict
between two callbacks.

The default is [`NotDefined()`], which will result in an error and a message
to implement this method.

To implement, dispatch on the callback types that you which to resolve (in any
order) and return one of the following:

- [`Unresolvable`](#)`()` if the callbacks must not be used together
- [`RunFirst`](#)`(cb)` if one of the callbacks needs to run first; or
- [`NoConflict`](#)`()` if the callbacks may run together in any order
"""
resolveconflict(::AbstractCallback, ::AbstractCallback) = NotDefined()

"""
    abstract type FitException

Abstract types for exceptions that can be thrown during fitting,
to change its control flow.

See [`CancelStepException`](#), [`CancelEpochException`](#), [`CancelFittingException`](#).
"""
abstract type FitException <: Exception end
"""
    CancelStepException(msg)

Throw during fitting to cancel the currently running batch.
"""
struct CancelStepException <: FitException
    msg::String
end

"""
    CancelEpochException(msg)

Throw during fitting to cancel the currently running epoch.
"""

struct CancelEpochException <: FitException
    msg::String
end

"""
    CancelFittingException(msg)

Throw during fitting to cancel it.
"""
struct CancelFittingException <: FitException
    msg::String
end

# Callback hook

"""
    on(event::Event, phase::Phase, callback::AbstractCallback, learner)

Handle `event` with `callback`. Can dispatch on an `Phase` and
receives `learner` as an additional argument.

If not overwritten with a more specific method, does nothing.

To see events which an `AbstractCallback` handles, use

```julia
methods(Training.on, (Any, Any, MyCallbackType, Any)
```
"""
on(::Event, phase, ::Callback, learner) = return

_on(e, p, cb, learner) = on(e, p, cb, learner)
function _on(e, p, cb::SafeCallback, learner)
    perms = Zygote.ignore() do
        stateaccess(cb)
    end
    on(e, p, cb, protect(learner, perms))
end

"""
    init!(callback, learner)

Initialization method that can be extended for a `callback`. Default does nothing.
Can be used to create fields in `learner.cbstate` that need to be accessed when
events occur.
"""
init!(cb::Callback, learner) = return


text:
"""
`histogram(v; nargs...)` → `Plot`

Description
============

Draws a horizontal histogram of the given vector `v`.
If the parameter `bins` is not specified,
then it will be chosen based on *sturges rule*.
Note that `histogram` is a simply wrapper for `barplot`,
which means that it supports the same parameter arguments.

Usage
======

    histogram(v; bins = sturges(length(v)), symb = "▇", border = :solid, title = "", margin = 3, padding = 1, color = :blue, width = 40, labels = true)

Arguments
==========

- **`v`** : Vector or range for which the histogram should be computed.

- **`bins`** : The approximate number of bins that should be used.

- **`border`** : The style of the bounding box of the plot.
Supports `:solid`, `:bold`, `:dashed`, `:dotted`, `:ascii`, and `:none`.

- **`title`** : Text to display on the top of the plot.

- **`margin`** : Number of empty characters to the left of the whole plot.

- **`padding`** : Space of the left and right of the plot between the labels and the canvas.

- **`color`** : Color of the drawing. Can be any of `:blue`, `:red`, `:yellow`

- **`width`** : Number of characters per row that should be used for plotting.

- **`labels`** : Can be used to hide the labels by setting `labels=false`.

- **`symb`** : Specifies the character that should be used to render the bars

Returns
========

A plot object of type `Plot{BarplotGraphics}`

Author(s)
==========

- Iain Dunning (Github: https://github.com/IainNZ)
- Christof Stocker (Github: https://github.com/Evizero)
- Kenta Sato (Github: https://github.com/bicycle1885)

Examples
=========

    julia> histogram(randn(1000), bins = 15, title = "Histogram")

                                 Histogram
                  ┌────────────────────────────────────────┐
      (-3.5,-3.0] │ 1                                      │
      (-3.0,-2.5] │ 2                                      │
      (-2.5,-2.0] │▇▇▇▇ 22                                 │
      (-2.0,-1.5] │▇▇▇▇▇▇▇▇▇▇ 53                           │
      (-1.5,-1.0] │▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 78                       │
      (-1.0,-0.5] │▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 141          │
       (-0.5,0.0] │▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 191 │
        (0.0,0.5] │▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 193 │
        (0.5,1.0] │▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 150         │
        (1.0,1.5] │▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 101                  │
        (1.5,2.0] │▇▇▇▇▇▇▇▇ 42                             │
        (2.0,2.5] │▇▇▇ 17                                  │
        (2.5,3.0] │▇ 4                                     │
        (3.0,3.5] │▇ 5                                     │
                  └────────────────────────────────────────┘

See also
=========

`hist`, `Plot`, `barplot`, `BarplotGraphics`
"""
function histogram(v, bins::Int; symb = "▇", args...)
    edges, counts = hist(v, bins)
    labels = Array(UTF8String, length(counts))
    binwidth = edges.step / edges.divisor
    @inbounds for i in 1:length(counts)
        val = float_round_log10(edges[i], binwidth)
        labels[i] = string("(", val, ",", float_round_log10(val+binwidth, binwidth), "]")
    end
    barplot(labels, counts; symb = symb, args...)
end

function histogram(v; bins::Int = sturges(length(v)), args...)
    histogram(v, bins; args...)
end

# Sturges' rule
sturges(n) = n == 0 ? 1 : ceil(Int, log2(n) + 1)


text:
using DelimitedFiles

function read_data(filename)
    open(filename, "r") do f
        data = split(replace(read(f, String), "->" => "", "\n" => " "), " ", keepempty = false)
        dat_list = reshape(data, 2, :)
    end
end

function main()

    filename = "data_5.dat"
    dat_list = read_data(filename)
    mines = zeros(Int32, 1000, 1000)

    x_start = zeros(Int32, length(dat_list[1, :]))
    y_start = zeros(Int32, length(dat_list[1, :]))

    x_end = zeros(Int32, length(dat_list[1, :]))
    y_end = zeros(Int32, length(dat_list[1, :]))

    ii = 1
    for d in dat_list[1,:]
        (startx, starty) = parse.(Int, split(d, ","))
        x_start[ii] = startx + 1
        y_start[ii] = starty + 1
        ii += 1
    end

    ii = 1
    for d in dat_list[2,:]
        (endx, endy) = parse.(Int, split(d, ","))
        x_end[ii] = endx + 1
        y_end[ii] = endy + 1
        ii += 1
    end

    for ii in 1:length(x_end)

        if x_start[ii] == x_end[ii]
            if y_start[ii] < y_end[ii]
                mines[y_start[ii] : y_end[ii], x_start[ii]] .+= 1
            else
                mines[y_end[ii] : y_start[ii], x_start[ii]] .+= 1
            end
        elseif y_start[ii] == y_end[ii]
            if x_start[ii] < x_end[ii]
                mines[y_start[ii], x_start[ii] : x_end[ii]] .+= 1
            else
                mines[y_start[ii], x_end[ii] : x_start[ii]] .+= 1
            end

        end
    end
    int_avoid = findall(x -> x>=2, mines)
    println(length(int_avoid))
end

@time main()


text:
# `Dimensions` is a collection of named dimensions
# each dimension has a name and a size (possibly unlimited)

"""
    keys(d::Dimensions)

Return a list of all dimension names in NCDataset `ds`.

# Examples

```julia-repl
julia> ds = NCDataset("results.nc", "r");
julia> dimnames = keys(ds.dim)
```
"""
function Base.keys(d::Dimensions)
    return String[nc_inq_dimname(d.ds.ncid,dimid)
                  for dimid in nc_inq_dimids(d.ds.ncid,false)]
end

function Base.show(io::IO, d::AbstractDimensions; indent = "")
    printstyled(io, indent, "Dimensions\n",color=section_color())
    try
        for (dimname,dimlen) in d
            print(io,indent,"   $(dimname) = $(dimlen)\n")
        end
    catch err
        if isa(err, NetCDFError)
            if err.code == NC_EBADID
                print(io, "NetCDF dimensions (file closed)")
                return
            end
        end
        rethrow()
    end
end

function Base.getindex(d::Dimensions,name::AbstractString)
    dimid = nc_inq_dimid(d.ds.ncid,name)
    return nc_inq_dimlen(d.ds.ncid,dimid)
end

"""
    unlimited(d::Dimensions)

Return the names of all unlimited dimensions.
"""
function unlimited(d::Dimensions)
    return String[nc_inq_dimname(d.ds.ncid,dimid)
                  for dimid in nc_inq_unlimdims(d.ds.ncid)]
end

export unlimited

"""
    Base.setindex!(d::Dimensions,len,name::AbstractString)

Defines the dimension called `name` to the length `len`.
Generally dimension are defined by indexing, for example:

```julia
ds = NCDataset("file.nc","c")
ds.dim["longitude"] = 100
```

If `len` is the special value `Inf`, then the dimension is considered as
`unlimited`, i.e. it will grow as data is added to the NetCDF file.
"""
function Base.setindex!(d::Dimensions,len,name::AbstractString)
    defmode(d.ds) # make sure that the file is in define mode
    dimid = nc_def_dim(d.ds.ncid,name,(isinf(len) ? NC_UNLIMITED : len))
    return len
end

"""
    defDim(ds::NCDataset,name,len)

Define a dimension in the data set `ds` with the given `name` and length `len`.
If `len` is the special value `Inf`, then the dimension is considered as
`unlimited`, i.e. it will grow as data is added to the NetCDF file.

For example:

```julia
using NCDatasets
ds = NCDataset("/tmp/test.nc","c")
defDim(ds,"lon",100)
# [...]
close(ds)
```

This defines the dimension `lon` with the size 100.

To create a variable with an unlimited dimensions use for example:

```julia
using NCDatasets
ds = NCDataset("/tmp/test2.nc","c")
defDim(ds,"lon",10)
defDim(ds,"lat",10)
defDim(ds,"time",Inf)
defVar(ds,"unlimited_variable",Float64,("lon","lat","time"))
@show ds.dim["time"]
# returns 0 as no data is added
ds["unlimited_variable"][:,:,:] = randn(10,10,4)
@show ds.dim["time"]
# returns now 4 as 4 time slice have been added
close(ds)
```
"""
function defDim(ds::NCDataset,name,len)
    defmode(ds) # make sure that the file is in define mode
    dimid = nc_def_dim(ds.ncid,name,(isinf(len) ? NC_UNLIMITED : len))
    return nothing
end
export defDim

function renameDim(ds::NCDataset,oldname,newname)
    defmode(ds) # make sure that the file is in define mode
    dimid = nc_inq_dimid(ds.ncid,oldname)
    nc_rename_dim(ds.ncid,dimid,newname)
    return nothing
end
export renameDim


text:
### A Pluto.jl notebook ###
# v0.15.1

using Markdown
using InteractiveUtils

# ╔═╡ e6d02bc0-103b-11ec-17ab-652d07c170a7
md"""
# Julia简要介绍

## 启动julia

双击Julia.exe，或者我们在命令行模式下输入julia后回车（前提是之前已经设置好PATH环境变量），就能打开Julia的REPL界面。

## Julia的四种模式
四种模式分别是REPL模式、Help模式、shell模式、包管理模式。

打开julia之后的模式直接就是REPL模式。

在REPL下输入?就会进入Help模式。退格键退回REPL模式。

输入;则进入shell模式，如果不清楚shell是什么，可以通俗的理解，就当时windows下的命令提示符，可以输入并执行命令。同样的退格退出该模式。

在REPL模式下输入]就进入Pkg模式，可以执行包管理的操作。我们这里暂时不展开。同样的退格退出该模式。

**因为我们现在不是在Julia的REPL下，所以此段不在这里做演示。**
"""

# ╔═╡ 66fcd604-aa15-4215-85a7-bbcb8dda34c7
md"""## 让我们来熟悉一下Julia的一些基本操作

在Julia的REPL界面，输入 pwd() ，就可以输出当前工作目录
"""

# ╔═╡ 3bc9cddb-2d83-47e5-be1a-fe664ff5ceb4
pwd()

# ╔═╡ Cell order:
# ╠═e6d02bc0-103b-11ec-17ab-652d07c170a7
# ╟─66fcd604-aa15-4215-85a7-bbcb8dda34c7
# ╠═3bc9cddb-2d83-47e5-be1a-fe664ff5ceb4


text:
# complex number utils

function cis!{T<:Number}(dest::AbstractVector{Complex{T}}, v::AbstractVector{T})
    @inbounds for i in 1:length(v)
        dest[i] = cis(v[i])
    end
end

function multiply!{T<:Number}(dest::AbstractVector{Complex{T}}, left::AbstractVector{Complex{T}}, right::AbstractVector{T})
    @inbounds for i in 1:length(dest)
        dest[i] = left[i] * right[i]
    end
end

typealias ArrayLike{T} Union{Vector{T}, Ptr{T}}

function plan_dft_c2r_1d!(dest::ArrayLike{Float32}, src::ArrayLike{Complex{Float32}}, nfft::Int)
    ccall((:fftwf_plan_dft_c2r_1d, "libfftw3f"), FFTW.PlanPtr, (Cint, Ptr{Complex{Float32}}, Ptr{Float32}, Cuint), nfft, src, dest, 0)
end

function plan_dft_c2r_1d!(dest::ArrayLike{Float64}, src::ArrayLike{Complex{Float64}}, nfft::Int)
    ccall((:fftw_plan_dft_c2r_1d, "libfftw3"), FFTW.PlanPtr, (Cint, Ptr{Complex{Float64}}, Ptr{Float64}, Cuint), nfft, src, dest, 0)
end

function execute_dft_c2r!(dest::ArrayLike{Float32}, src::ArrayLike{Complex{Float32}}, plan::FFTW.PlanPtr)
    ccall((:fftwf_execute_dft_c2r, "libfftw3f"), Void, (FFTW.PlanPtr, Ptr{Complex{Float32}}, Ptr{Float32}), plan, src, dest)
end

function execute_dft_c2r!(dest::ArrayLike{Float64}, src::ArrayLike{Complex{Float64}}, plan::FFTW.PlanPtr)
    ccall((:fftw_execute_dft_c2r, "libfftw3"), Void, (FFTW.PlanPtr, Ptr{Complex{Float64}}, Ptr{Float64}), plan, src, dest)
end

"""Performs inverse real-data FFT without allocating the result array"""
function irfft!{T<:Number}(dest::Array{T}, src::ArrayLike{Complex{T}}, nfft::Int)
    plan = plan_dft_c2r_1d!(dest, src, nfft)
    execute_dft_c2r!(dest, src, plan)
    for i = 1:nfft
        dest[i] /= nfft
    end
end


text:
# Command: Element Clear
"""
    clear!(element::Element)::Nothing

Element Clear
"""
function clear!(element::Element)::Nothing
    @unpack addr, id = element.session
    element_id = element.id
    response = HTTP.post(
        "$addr/session/$id/element/$element_id/clear",
        [("Content-Type" => "application/json")],
    )
    @assert response.status == 200
end


text:
import Pkg; Pkg.add("Distributions"); Pkg.add("Plots"); Pkg.add("MLDatasets"); Pkg.add("CSV")

using CSV
using Plots
using Random, Distributions
using MLDatasets

# the implementation is based on http://www.jmlr.org/papers/volume9/vandermaaten08a/vandermaaten08a.pdf
# and uses https://raw.githubusercontent.com/danaugrs/go-tsne/master/tsne/tsne.go as a basis
# with input params borrowed from https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html

# setting up constants that we'll need
epsilon = 10^-7 # minimum gradient norm (if smaller optimization is stopped)
fake_zero = 10^-12 # can't really have 0 for some of the calculations - making a mumber really close to it
tol = 10^-5 # enthropy tolerance
max_binary = 50 # max number of steps that the binary search gets to do
init_stdev = 10^-4 # the stdev that we're initialising Y with

# and init parameters that we'll be working with
m_out = 2 # the number of dimensions we want to get as an output
T = 1000 # the number of iterations

perp = 50 # in a sense, a guess about the number of close neighbors each point has
l_rate = 300 # the learning rate

# loading our dataset
csv_data = CSV.read("tsne-julia/abalone.csv", header=false)
X = convert(Matrix, csv_data[:, 2:9])
n, m = size(X)
cols = convert(Matrix, csv_data[:, 1:1])
unique_cols = unique(cols)
colmap = ["#e6194b", "#3cb44b", "#ffe119", "#4363d8", "#f58231", "#911eb4", "#46f0f0", "#f032e6", "#bcf60c", "#fabebe", "#008080", "#e6beff", "#9a6324", "#fffac8", "#800000", "#aaffc3", "#808000", "#ffd8b1", "#000075", "#808080", "#ffffff", "#000000"]

# calculates the squared euclidean distance between two lists of the same length
function squared_euclidean(p, q, m)
  # remember that the lists in julia are 1 based
  # sicne the distance is a square root of the sum of squares we can just omit the sqrt
  # (since we're interested in the squared distance)
  return sum([(p[i]-q[i])^2 for i in 1:m])
end

# calculates a squared distance matrix for row vectors in X
function squared_distances(X, n, m)
  dists = zeros(n, n)
  for i in 1:n
    for j in (i+1):n # skip the diagonal as well
      tmp_dist = squared_euclidean(X[i,:], X[j,:], m) # and reuse the value for the pair
      dists[i, j] = tmp_dist
      dists[j, i] = tmp_dist
    end
  end
  return dists
end

function similarities(D, m, n, tol, perp, epsilon)
  # the target entropy of the gaussian kernels is the log of the target perplexity
  h_target = log(perp)

  # the similarity matrix that we're going to populate
  P = zeros(n, n)

  # work through all of the rows
  for i in 1:n
    # perform a binary search for the Gaussian kernel precision (beta)
    # such that the entropy (and thus the perplexity) of the distribution
    # given the data is the same for all data points
    beta_min = -Inf
    beta_max = Inf
    beta = 1 # initial value of precision

    for j in 1:max_binary
      # compute raw probabilities with beta precision (along with sum of all raw probabilities)
      p_sum = Float64(0)
      for k in 1:m
        p = 0
        if i != k
          p = exp(-D[i, k]*beta)
        end

        P[i, k] = p # note that we're not updating the whole thing (can't really do shorthand as a result)
        p_sum += p
      end

      # normalize probabilities and compute entropy H
      h = Float64(0) # distribution entropy
      for k in 1:m
        p = 0
        if p_sum != 0
          p = P[i, k]/p_sum
        end

        P[i, k] = p
        if p > epsilon
          h -= p*log(p)
        end
      end

      # adjust beta to move H closer to Htarget
      h_diff = h-h_target
      if h_diff > 0
        # entropy is too high (distribution too spread-out)
        # so we need to increase the precision
        beta_min = beta # move up the bounds
        if beta_max == Inf
          beta *= 2
        else
          beta = (beta+beta_max)/2
        end
      else
        # entropy is too low - need to decrease precision
        beta_max = beta # move down the bounds
        if beta_min == -Inf
          beta /= 2
        else
          beta = (beta+beta_min)/2
        end
      end

      # if current entropy is within specified tolerance - we are done with this data point
      if abs(h_diff) < tol
        break
      end
    end
  end

  return P
end

function cost_gradient(P, Y, dCdY, n, m_out, P_log_P, fake_zero)
  # q i|j (1+dist^2)^-1 / sum(i≠j, (1+dist^2)^-1)
  Y_dist = squared_distances(Y, n, m_out)
  # set up the top part of that calculation
  Q_top = zeros(n, n)
  for i in 1:n
    for j in 1:n
      if i!=j
        Q_top[i, j] = 1/(1+Y_dist[i, j])
      end
    end
  end
  # get the bottom bit of that function
  sum_q = sum(sum(Q_top))
  # build up the q i|j set
  Q = zeros(n, n)
  for i in 1:n
    for j in 1:n
      Q[i, j] = max(Q_top[i, j]/sum_q, fake_zero)
    end
  end
  # the non-constant portion of the divergence
  Q_log = zeros(n, n)
  for i in 1:n
    for j in 1:n
      Q_log[i, j] = log(Q[i, j])
    end
  end
  # compute the Kullback-Leiber divergence
  P_log_Q = sum(sum(P*Q_log))
  # work out the gradient of the Kullback-Leibler divergence between P and the Student-t based joint probability distribution Q
  mult = P-Q
  mult = mult.*4
  mult = mult*Y_dist
  for r in 1:n
    for c in 1:n
      m = mult[r, c]
      for k in 1:m_out
        y_diff = Y[r, k] - Y[c, k]
        dCdY[r, k] += m*y_diff
      end
    end
  end
  return dCdY
  #return [4*sum([(P[i][j]-Q[i][j])*(Y[i]-Y[j])/(1+Y_dist[i][j]) for j in 1:n]) for i in 1:n]
end

println("Prepping")
# compute pairwise affinities p i|j with perplexity Perp (using Equation 1)
D = squared_distances(X, n, m)
println("Distances calculated")
P = similarities(D, m, n, tol, perp, epsilon)
println("Similarities calculated")
# set p ij = (p j|i + p i|j)/2n
P = zeros(n, n)
for i in 1:n
  for j in 1:m_out
    P[i, j] = max((P[j, i]+P[i, j])/(2*n), fake_zero)
  end
end
println("Similarities adjusted")
# sample initial solution Y(0)={y1, y2, ..., yn} for N(0,10^-4*I)
init_vals = rand(Normal(0, init_stdev), m_out*n)
Y = zeros(n, m_out)
for i in 1:n
  for j in 1:m_out
    Y[i, j] = init_vals[m_out*i-j+1]
  end
end
dCdY = zeros(n, m_out)
println("Y initialised")
# compute and store the constant portion of the KL divergence
P_log_P = zeros(n, n)
for i in 1:n
  for j in 1:n
    P_log_P[i, j] = log(P[i, j])*P[i, j]
  end
end
P_log_P = sum(sum(P_log_P))
# for t=1 to T do
#
#   where T is the number of epochs that we're looking to work through
println("Training")
for t in 1:T
  global P, Y, n, m_out, P_log_P, fake_zero, cols, momentum, dCdY
  # compute the gradient matrix
  dCdY = cost_gradient(P, Y, dCdY, n, m_out, P_log_P, fake_zero)
  # apply scaled gradient
  println(Y[1:5, :])
  Y -= dCdY.*l_rate
  # reproject Y to have zero mean
  Y_mean = zeros(m_out)
  for i in 1:n
    for j in 1:m_out
      Y_mean[j] += Y[i, j]
    end
  end

  for i in 1:n
    for j in 1:m_out
      Y[i, j] -= (Y_mean[j]/n)
    end
  end
  println(Y[1:5, :])
  println(t)
  if t%10 == 0 # keeping myself from getting swamped in charts
    indices = [i for i in 1:n if cols[i]==unique_cols[1]]
    p = scatter(Y[:, 1][indices], Y[:, 2][indices], markercolor=colmap[1])
    for k = 2:length(unique_cols)
      indices = [i for i in 1:n if cols[i]==unique_cols[k]]
      scatter!(Y[:, 1][indices], Y[:, 2][indices], markercolor=colmap[k])
    end
    display(p)
  end
end

max_stars_repo_name: lucren/tsne-julia

max_issues_repo_name: lucren/tsne-julia

max_forks_repo_name: lucren/tsne-julia


text:
function histogram(param,nbin)
  p1 = minimum(param)-1e-15; p2 = maximum(param)+1e-15
  pbin_square = [p1]
  hist_square = [0.0]
  pbin = zeros(nbin)
  hist = zeros(nbin)
  psort = sort(param)
  i1 = 1; np = size(param)[1]
  println(p1," ",psort[i1]," ",p2," ",psort[np])
  dp = (p2-p1)/nbin
  for i=1:nbin
    while psort[i1] <= p1+dp*i
      hist[i] += 1.0
      i1 += 1
      if i1 == np+1
        break
      end
    end
    push!(hist_square,hist[i]); push!(hist_square,hist[i])
    pbin[i] = p1+dp*(i-0.5)
    push!(pbin_square,p1+dp*(i-1))
    push!(pbin_square,p1+dp*i)
    if i1 == np+1
      break
    end
  end
  push!(hist_square,0.0)
  push!(pbin_square,p2)
  return pbin,hist,pbin_square,hist_square
end


text:
# %% Interactive bifurcations for 1D energy balance
using DrWatson
@quickactivate "NonlinearDynamicsTextbook"
include(srcdir("colorscheme.jl"))
using DynamicalSystems, InteractiveDynamics
using Roots
import GLMakie

αtan(T) = 0.5 - (0.4/π)*atan((T-263)/2)
dTdt(T, ε = 0.65, α=αtan, s= 1.0) = s*(1 - α(T)) - 1.6e-10 * ε * T^4

Ts = 200:0.5:320.0
εs = 0.2:0.01:1.0

function roots(ε)
    f = T -> dTdt(T, ε)
    r = Roots.find_zeros(f, Ts[1], Ts[end])
    s = [GLMakie.to_color(COLORS[isodd(i) ? 4 : 3]) for i in 1:length(r)]
    return [Point2f0(x, 0) for x in r], s # roots, stability
end

fig = GLMakie.Figure(resolution = (800, 500))

ax = fig[1, 1] = GLMakie.Axis(fig;
    xlabel = GLMakie.L"T", ylabel = GLMakie.L"f(T)",
    ylabelsize = 24, xlabelsize = 24
)
ax.limits = ((Ts[1], Ts[end]), (-0.3, 0.3))
axb = fig[1, 2] = GLMakie.Axis(fig;
    xlabel = GLMakie.L"\epsilon", ylabel = GLMakie.L"T^*",
    ylabelsize = 24, xlabelsize = 24
)
sll = GLMakie.labelslider!(fig, "ϵ =", εs; sliderkw = Dict(:startvalue => 0.65))
fig[2, :] = sll.layout
ε_observable = sll.slider.value
axb.limits = ((εs[1], εs[end]), (220, 300))

# initialize plot
fs = GLMakie.Observable(dTdt.(Ts))
GLMakie.lines!(ax, Ts, fs; color = COLORS[2], linewidth = 4)
GLMakie.hlines!(ax, 0; color = COLORS[1])
r, s = roots(0.65)
rootvals = GLMakie.Observable(r)
rootcols = GLMakie.Observable(s)
GLMakie.scatter!(ax, rootvals; color = rootcols, markersize = 10)

stablefp = GLMakie.Observable(GLMakie.Point2f0[])
unstablefp = GLMakie.Observable(GLMakie.Point2f0[])

GLMakie.scatter!(axb, stablefp; color = COLORS[4])
GLMakie.scatter!(axb, unstablefp; color = COLORS[3])

display(fig)

GLMakie.on(ε_observable) do ε
    fs[] = dTdt.(Ts, ε)
    r, s = roots(ε)
    rootvals[] = r
    rootcols[] = s

    for (i, ρ) in enumerate(r)
        p = GLMakie.Point2f0(ε, ρ[1])
        if isodd(i)
            push!(stablefp[], p)
        else
            push!(unstablefp[], p)
        end
    end
    stablefp[] = stablefp[]
    unstablefp[] = unstablefp[]
end

ε_observable[] = 0.65

# %%
record_interaction(fig, string(@__FILE__)[1:end-2]*"mp4"; total_time = 15, sleep_time = 2)

max_stars_repo_name: JuliaDynamics/NonlinearDynamicsTextbook

max_issues_repo_name: JuliaDynamics/NonlinearDynamicsTextbook

max_forks_repo_name: JuliaDynamics/NonlinearDynamicsTextbook


text:
module NumberIntervals

using IntervalArithmetic

# three-value logic
include("indeterminate.jl")
# basic type definitions, conversion rules, etc
include("types.jl")

# import set-like (IEEE conform) behaviors from IntervalArithmetic
include("set_operations.jl")
include("numeric.jl")
include("boolean.jl")
include("basic.jl")

# define strict number-like arithmetic
include("nonstandard.jl")

end # module


text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

module TypesTest

import Dates
using Test
using ExtendedDates

# Create "test" check manually
y = Year(1)
s = SemesterDate
q = Quarter(1)
m = Month(1)
w = Week(1)
d = Day(1)
h = Hour(1)
mi = Minute(1)
s = Second(1)
ms = Millisecond(1)
@testset "SimpleDate construction by parts" begin
    test = YearDate(ExtendedDates.UTY(2012))
    @test YearDate(2013) == test

    test = DayDate(ExtendedDates.UTD(Dates.value(Dates.Date(2013))))
    @test DayDate(2013) == test
    @test DayDate(2013, 1) == test
    @test DayDate(2013, 1, 1) == test

    @test DayDate(y) == DayDate(1)
    @test DayDate(y, m) == DayDate(1, 1)
    @test DayDate(y, m, d) == DayDate(1, 1, 1)
    @test DayDate(Day(10), Month(2), y) == DayDate(1, 2, 10)

    test = WeekDate(ExtendedDates.UTW(ExtendedDates.WEEKTABLE[2012]["cum_weeks"] + 1))
    @test WeekDate(2013) == test
    @test WeekDate(2013, 1) == test

    @test WeekDate(y) == WeekDate(1)
    @test WeekDate(y, w) == WeekDate(1, 1)
    @test WeekDate(Week(10), y) == WeekDate(1, 10)

    test = MonthDate(ExtendedDates.UTM(2012 * 12 + 1))
    @test MonthDate(2013) == test
    @test MonthDate(2013, 1) == test

    @test MonthDate(y) == MonthDate(1)
    @test MonthDate(y, m) == MonthDate(1, 1)
    @test MonthDate(Month(10), y) == MonthDate(1, 10)

    test = QuarterDate(ExtendedDates.UTQ(2012 * 4 + 1))
    @test QuarterDate(2013) == test
    @test QuarterDate(2013, 1) == test

    @test QuarterDate(y) == QuarterDate(1)
    @test QuarterDate(y, q) == QuarterDate(1, 1)
    @test QuarterDate(Quarter(3), y) == QuarterDate(1, 3)

    test = SemesterDate(ExtendedDates.UTS(2012 * 2 + 1))
    @test SemesterDate(2013) == test
    @test SemesterDate(2013, 1) == test

    @test SemesterDate(y) == SemesterDate(1)
    @test SemesterDate(y, s) == SemesterDate(1, 1)
    @test SemesterDate(Semester(2), y) == SemesterDate(1, 2)
end

@testset "various input types for Date/DateTime" begin
    test = DayDate(1, 1, 1)
    @test DayDate(Int8(1), Int8(1), Int8(1)) == test
    @test DayDate(UInt8(1), UInt8(1), UInt8(1)) == test
    @test DayDate(Int16(1), Int16(1), Int16(1)) == test
    @test DayDate(UInt8(1), UInt8(1), UInt8(1)) == test
    @test DayDate(Int32(1), Int32(1), Int32(1)) == test
    @test DayDate(UInt32(1), UInt32(1), UInt32(1)) == test
    @test DayDate(Int64(1), Int64(1), Int64(1)) == test
    @test DayDate('\x01', '\x01', '\x01') == test
    @test DayDate(true, true, true) == test
    @test_throws ArgumentError DayDate(false, true, false)
    @test DayDate(false, true, true) == test - Day(366)
    @test_throws ArgumentError DayDate(true, true, false)
    @test DayDate(UInt64(1), UInt64(1), UInt64(1)) == test
    @test DayDate(0, UInt64(12), UInt64(30)) == test - Day(2)
    @test DayDate(Int128(1), Int128(1), Int128(1)) == test
    @test_throws InexactError DayDate(
        170141183460469231731687303715884105727,
        Int128(1),
        Int128(1),
    )
    @test DayDate(UInt128(1), UInt128(1), UInt128(1)) == test
    @test DayDate(big(1), big(1), big(1)) == test
    @test DayDate(big(1), big(1), big(1)) == test
    # Potentially won't work if can't losslessly convert to Int64
    @test DayDate(BigFloat(1), BigFloat(1), BigFloat(1)) == test
    @test DayDate(complex(1), complex(1), complex(1)) == test
    @test DayDate(Float64(1), Float64(1), Float64(1)) == test
    @test DayDate(Float32(1), Float32(1), Float32(1)) == test
    @test DayDate(Float16(1), Float16(1), Float16(1)) == test
    @test DayDate(Rational(1), Rational(1), Rational(1)) == test
    @test_throws InexactError DayDate(BigFloat(1.2), BigFloat(1), BigFloat(1))
    @test_throws InexactError DayDate(1 + im, complex(1), complex(1))
    @test_throws InexactError DayDate(1.2, 1.0, 1.0)
    @test_throws InexactError DayDate(1.2f0, 1.0f0, 1.0f0)
    @test_throws InexactError DayDate(3 // 4, Rational(1), Rational(1)) == test

    test = WeekDate(1, 1)
    @test WeekDate(Int8(1), Int8(1)) == test
    @test WeekDate(UInt8(1), UInt8(1)) == test
    @test WeekDate(Int16(1), Int16(1)) == test
    @test WeekDate(UInt8(1), UInt8(1)) == test
    @test WeekDate(Int32(1), Int32(1)) == test
    @test WeekDate(UInt32(1), UInt32(1)) == test
    @test WeekDate(Int64(1), Int64(1)) == test
    @test WeekDate('\x01', '\x01') == test
    @test WeekDate(true, true) == test
    @test_throws ArgumentError WeekDate(0)
    @test_throws ArgumentError WeekDate(false, false)
    @test_throws ArgumentError WeekDate(true, false)
    @test WeekDate(UInt64(1), UInt64(1)) == test
    @test WeekDate(Int128(1), Int128(1)) == test
    @test_throws InexactError WeekDate(170141183460469231731687303715884105727, Int128(1))
    @test WeekDate(UInt128(1), UInt128(1)) == test
    @test WeekDate(big(1), big(1)) == test
    @test WeekDate(big(1), big(1)) == test
    # Potentially won't work if can't losslessly convert to Int64
    @test WeekDate(BigFloat(1), BigFloat(1)) == test
    @test WeekDate(complex(1), complex(1)) == test
    @test WeekDate(Float64(1), Float64(1)) == test
    @test WeekDate(Float32(1), Float32(1)) == test
    @test WeekDate(Float16(1), Float16(1)) == test
    @test WeekDate(Rational(1), Rational(1)) == test
    @test_throws InexactError WeekDate(BigFloat(1.2), BigFloat(1))
    @test_throws InexactError WeekDate(1 + im, complex(1))
    @test_throws InexactError WeekDate(1.2, 1.0)
    @test_throws InexactError WeekDate(1.2f0, 1.0f0)
    @test_throws InexactError WeekDate(3 // 4, Rational(1)) == test

    test = MonthDate(1, 1)
    @test MonthDate(Int8(1), Int8(1)) == test
    @test MonthDate(UInt8(1), UInt8(1)) == test
    @test MonthDate(Int16(1), Int16(1)) == test
    @test MonthDate(UInt8(1), UInt8(1)) == test
    @test MonthDate(Int32(1), Int32(1)) == test
    @test MonthDate(UInt32(1), UInt32(1)) == test
    @test MonthDate(Int64(1), Int64(1)) == test
    @test MonthDate('\x01', '\x01') == test
    @test MonthDate(true, true) == test
    @test_throws ArgumentError MonthDate(false, false)
    @test MonthDate(false, true) == test - Dates.Month(12)
    @test_throws ArgumentError MonthDate(true, false)
    @test MonthDate(UInt64(1), UInt64(1)) == test
    @test MonthDate(0, UInt64(12)) == test - Dates.Month(1)
    @test MonthDate(Int128(1), Int128(1)) == test
    @test_throws InexactError MonthDate(170141183460469231731687303715884105727, Int128(1))
    @test MonthDate(UInt128(1), UInt128(1)) == test
    @test MonthDate(big(1), big(1)) == test
    @test MonthDate(big(1), big(1)) == test
    # Potentially won't work if can't losslessly convert to Int64
    @test MonthDate(BigFloat(1), BigFloat(1)) == test
    @test MonthDate(complex(1), complex(1)) == test
    @test MonthDate(Float64(1), Float64(1)) == test
    @test MonthDate(Float32(1), Float32(1)) == test
    @test MonthDate(Float16(1), Float16(1)) == test
    @test MonthDate(Rational(1), Rational(1)) == test
    @test_throws InexactError MonthDate(BigFloat(1.2), BigFloat(1))
    @test_throws InexactError MonthDate(1 + im, complex(1))
    @test_throws InexactError MonthDate(1.2, 1.0)
    @test_throws InexactError MonthDate(1.2f0, 1.0f0)
    @test_throws InexactError MonthDate(3 // 4, Rational(1)) == test

    test = QuarterDate(1, 1)
    @test QuarterDate(Int8(1), Int8(1)) == test
    @test QuarterDate(UInt8(1), UInt8(1)) == test
    @test QuarterDate(Int16(1), Int16(1)) == test
    @test QuarterDate(UInt8(1), UInt8(1)) == test
    @test QuarterDate(Int32(1), Int32(1)) == test
    @test QuarterDate(UInt32(1), UInt32(1)) == test
    @test QuarterDate(Int64(1), Int64(1)) == test
    @test QuarterDate('\x01', '\x01') == test
    @test QuarterDate(true, true) == test
    @test_throws ArgumentError QuarterDate(false, false)
    @test QuarterDate(false, true) == test - Dates.Quarter(4)
    @test_throws ArgumentError QuarterDate(true, false)
    @test QuarterDate(UInt64(1), UInt64(1)) == test
    @test QuarterDate(0, UInt64(4)) == test - Dates.Quarter(1)
    @test QuarterDate(Int128(1), Int128(1)) == test
    @test_throws InexactError QuarterDate(
        170141183460469231731687303715884105727,
        Int128(1),
    )
    @test QuarterDate(UInt128(1), UInt128(1)) == test
    @test QuarterDate(big(1), big(1)) == test
    @test QuarterDate(big(1), big(1)) == test
    # Potentially won't work if can't losslessly convert to Int64
    @test QuarterDate(BigFloat(1), BigFloat(1)) == test
    @test QuarterDate(complex(1), complex(1)) == test
    @test QuarterDate(Float64(1), Float64(1)) == test
    @test QuarterDate(Float32(1), Float32(1)) == test
    @test QuarterDate(Float16(1), Float16(1)) == test
    @test QuarterDate(Rational(1), Rational(1)) == test
    @test_throws InexactError QuarterDate(BigFloat(1.2), BigFloat(1))
    @test_throws InexactError QuarterDate(1 + im, complex(1))
    @test_throws InexactError QuarterDate(1.2, 1.0)
    @test_throws InexactError QuarterDate(1.2f0, 1.0f0)
    @test_throws InexactError QuarterDate(3 // 4, Rational(1)) == test

    test = SemesterDate(1, 1)
    @test SemesterDate(Int8(1), Int8(1)) == test
    @test SemesterDate(UInt8(1), UInt8(1)) == test
    @test SemesterDate(Int16(1), Int16(1)) == test
    @test SemesterDate(UInt8(1), UInt8(1)) == test
    @test SemesterDate(Int32(1), Int32(1)) == test
    @test SemesterDate(UInt32(1), UInt32(1)) == test
    @test SemesterDate(Int64(1), Int64(1)) == test
    @test SemesterDate('\x01', '\x01') == test
    @test SemesterDate(true, true) == test
    @test_throws ArgumentError SemesterDate(false, false)
    @test SemesterDate(false, true) == test - Semester(2)
    @test_throws ArgumentError SemesterDate(true, false)
    @test SemesterDate(UInt64(1), UInt64(1)) == test
    @test SemesterDate(0, UInt64(2)) == test - Semester(1)
    @test SemesterDate(Int128(1), Int128(1)) == test
    @test_throws InexactError SemesterDate(
        170141183460469231731687303715884105727,
        Int128(1),
    )
    @test SemesterDate(UInt128(1), UInt128(1)) == test
    @test SemesterDate(big(1), big(1)) == test
    @test SemesterDate(big(1), big(1)) == test
    # Potentially won't work if can't losslessly convert to Int64
    @test SemesterDate(BigFloat(1), BigFloat(1)) == test
    @test SemesterDate(complex(1), complex(1)) == test
    @test SemesterDate(Float64(1), Float64(1)) == test
    @test SemesterDate(Float32(1), Float32(1)) == test
    @test SemesterDate(Float16(1), Float16(1)) == test
    @test SemesterDate(Rational(1), Rational(1)) == test
    @test_throws InexactError SemesterDate(BigFloat(1.2), BigFloat(1))
    @test_throws InexactError SemesterDate(1 + im, complex(1))
    @test_throws InexactError SemesterDate(1.2, 1.0)
    @test_throws InexactError SemesterDate(1.2f0, 1.0f0)
    @test_throws InexactError SemesterDate(3 // 4, Rational(1)) == test

    test = YearDate(1)
    @test YearDate(Int8(1)) == test
    @test YearDate(UInt8(1)) == test
    @test YearDate(Int16(1)) == test
    @test YearDate(UInt8(1)) == test
    @test YearDate(Int32(1)) == test
    @test YearDate(UInt32(1)) == test
    @test YearDate(Int64(1)) == test
    @test YearDate('\x01') == test
    @test YearDate(true) == test
    @test YearDate(false) == test - Year(1)
    @test YearDate(UInt64(1)) == test
    @test YearDate(0) == test - Year(1)
    @test YearDate(Int128(1)) == test
    @test_throws InexactError YearDate(170141183460469231731687303715884105727)
    @test YearDate(UInt128(1)) == test
    @test YearDate(big(1)) == test
    @test YearDate(big(1)) == test
    # Potentially won't work if can't losslessly convert to Int64
    @test YearDate(BigFloat(1)) == test
    @test YearDate(complex(1)) == test
    @test YearDate(Float64(1)) == test
    @test YearDate(Float32(1)) == test
    @test YearDate(Float16(1)) == test
    @test YearDate(Rational(1)) == test
    @test_throws InexactError YearDate(BigFloat(1.2))
    @test_throws InexactError YearDate(1 + im)
    @test_throws InexactError YearDate(1.2)
    @test_throws InexactError YearDate(1.2f0)
    @test_throws InexactError YearDate(3 // 4) == test

    test = UndatedDate(1)
    @test UndatedDate(Int8(1)) == test
    @test UndatedDate(UInt8(1)) == test
    @test UndatedDate(Int16(1)) == test
    @test UndatedDate(UInt8(1)) == test
    @test UndatedDate(Int32(1)) == test
    @test UndatedDate(UInt32(1)) == test
    @test UndatedDate(Int64(1)) == test
    @test UndatedDate('\x01') == test
    @test UndatedDate(true) == test
    @test UndatedDate(false) == test - Undated(1)
    @test UndatedDate(UInt64(1)) == test
    @test UndatedDate(0) == test - Undated(1)
    @test UndatedDate(Int128(1)) == test
    @test_throws InexactError UndatedDate(170141183460469231731687303715884105727)
    @test UndatedDate(UInt128(1)) == test
    @test UndatedDate(big(1)) == test
    @test UndatedDate(big(1)) == test
    # Potentially won't work if can't losslessly convert to Int64
    @test UndatedDate(BigFloat(1)) == test
    @test UndatedDate(complex(1)) == test
    @test UndatedDate(Float64(1)) == test
    @test UndatedDate(Float32(1)) == test
    @test UndatedDate(Float16(1)) == test
    @test UndatedDate(Rational(1)) == test
    @test_throws InexactError UndatedDate(BigFloat(1.2))
    @test_throws InexactError UndatedDate(1 + im)
    @test_throws InexactError UndatedDate(1.2)
    @test_throws InexactError UndatedDate(1.2f0)
    @test_throws InexactError UndatedDate(3 // 4) == test

    # Semesters, Quarters, Months, Weeks Days must be in range
    @test_throws ArgumentError DayDate(2013, 0, 1)
    @test_throws ArgumentError DayDate(2013, 13, 1)
    @test_throws ArgumentError DayDate(2013, 1, 0)
    @test_throws ArgumentError DayDate(2013, 1, 32)

    @test_throws ArgumentError WeekDate(2013, 0)
    @test_throws ArgumentError WeekDate(2013, 54)

    @test_throws ArgumentError MonthDate(2013, 0)
    @test_throws ArgumentError MonthDate(2013, 13)

    @test_throws ArgumentError QuarterDate(2013, 0)
    @test_throws ArgumentError QuarterDate(2013, 5)

    @test_throws ArgumentError SemesterDate(2013, 0)
    @test_throws ArgumentError SemesterDate(2013, 3)

end
a = Dates.DateTime(2000)
b = Dates.Date(2000)
c = Dates.Time(0)
@testset "DateTime traits" begin
    for (T1, T2) in zip(
        (:DayDate, :WeekDate, :MonthDate, :QuarterDate, :YearDate),
        (:Day, :Week, :Month, :Quarter, :Year),
    )
        @eval begin
            @test ExtendedDates.calendar($T1(2000)) == Dates.ISOCalendar
            @test eps($T1) == Dates.$T2(1)
            @test zero($T1) == Dates.$T2(0)
            @test isfinite($T1)
        end
    end
end
@testset "Date-DateTime conversion/promotion" begin
    for T in (
        :DayDate,
        :WeekDate,
        :MonthDate,
        :QuarterDate,
        :SemesterDate,
        :YearDate,
        :UndatedDate,
    )
        @eval begin
            a = $T(2000)
            b = $T(2000)
            @test $T(a) == a
            @test $T(a) == b
            @test $T(b) == b
            @test a == b
            @test a == a
            @test b == a
            @test b == b
            @test !(a < b)
            @test !(b < a)
            b = $T(2001)
            @test b > a
            @test a < b
            @test a != b
        end
    end
end

@testset "min and max" begin
    for T in (
        :DayDate,
        :WeekDate,
        :MonthDate,
        :QuarterDate,
        :SemesterDate,
        :YearDate,
        :UndatedDate,
    )
        @eval begin
            a = $T(2000)
            b = $T(2001)
            @test min(a, b) == a
            @test min(b, a) == a
            @test min(a) == a
            @test max(a, b) == b
            @test max(b, a) == b
            @test max(b) == b
            @test minmax(a, b) == (a, b)
            @test minmax(b, a) == (a, b)
            @test minmax(a) == (a, a)
        end
    end

    for T in (:DayDate, :WeekDate, :MonthDate, :QuarterDate, :SemesterDate)
        @eval begin
            a = $T(2000, 1)
            b = $T(2000, 2)
            @test min(a, b) == a
            @test min(b, a) == a
            @test min(a) == a
            @test max(a, b) == b
            @test max(b, a) == b
            @test max(b) == b
            @test minmax(a, b) == (a, b)
            @test minmax(b, a) == (a, b)
            @test minmax(a) == (a, a)
        end
    end

    @test DayDate(2000, 1, 1) < DayDate(2000, 1, 2)

end

@testset "simpleperiod" begin
    @test ExtendedDates.simpleperiod(FYear, 2000) == YearDate(2000)
    @test ExtendedDates.simpleperiod(FSemester, 2000, 2) == SemesterDate(2000, 2)
    @test ExtendedDates.simpleperiod(FQuarter, 2000, 4) == QuarterDate(2000, 4)
    @test ExtendedDates.simpleperiod(FMonth, 2000, 11) == MonthDate(2000, 11)
    @test ExtendedDates.simpleperiod(FWeek, 2000, 52) == WeekDate(2000, 52)
    @test ExtendedDates.simpleperiod(FDay, 2004, 2, 29) == DayDate(2004, 2, 29)
    @test ExtendedDates.simpleperiod(FUndated, 2000) == UndatedDate(2000)
end

end