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

using Markdown
using InteractiveUtils

# ╔═╡ a6e71018-ab69-42d0-9a15-ffb477b4bd64
begin
	using ModelingToolkit
	using DifferentialEquations
	using Plots
end

# ╔═╡ d4f1e3a9-d1c8-4e3e-8b88-f0a901a894f7
md"""
# Symbolic ODE Modeling

I recently stumbled upon the [DifferentialEquations.jl](https://github.com/SciML/DifferentialEquations.jl) and  [ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl)  which are pretty cool packages.

The idea is that we can represent ordinary differential equation models symbolically using the ModelingToolkit.jl and then use the DifferentialEquations.jl package to find our solutions.

Below will be a simple example in doing so.
"""

# ╔═╡ 656cae30-e450-11eb-266a-f7572588b91b
md"""
## An example in chemical kinetics
Determining the concentration of species involved in reaction kinetics is done by solving a set of ordinary differential equations goverened by [law of mass action](https://en.wikipedia.org/wiki/Law_of_mass_action) which can be expressed as:

```math
\begin{align}
\frac{dC_i}{dt} &= \sum_j N_{i,j} K_j \\
K_j &= k_j \prod_k C_k^{S_j}
\end{align}
```

where $N_{i,j}$ is the net stoichiometric value of species $i$ over reactions $j$, $K_j$ is the reaction coefficient, and $S_j$ the stoichiometry of species $k$ in reaction $j$. We  can solve the Robertson's 3-species reacting system:

$r_1 = k_1 [A]$
$r_2 = k_2 [B] [C]$
$r_3 = k_3 [B]$

This corresponds to the chemical processes:

$A \rightarrow B$
$B + C \rightarrow A + C$
$2B \rightarrow B + C$

One now needs to determine the concentrations of species A, B, and C as a function of time by solving the ODEs. When a species is consumed/reacted the sign is negative and when it is produced it is positive.

$\frac{d[A]}{dt} = r_2 - r_1$
$\frac{d[B]}{dt} = r_1 - r_2 - r_3$
$\frac{d[C]}{dt} = r_3$

The neat thing is we can solve this in a few lines of code using the [ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl) and [DifferentialEquations.jl](https://github.com/SciML/DifferentialEquations.jl) Julia packages.

This does the same thing that the [SymPy Code generation tutorial on youtube](https://www.youtube.com/watch?v=5jzIVp6bTy0).
"""

# ╔═╡ 53eaf1ae-6d16-4606-b5d2-97fd61ac7da6
function chemicalreaction_ode_solution()
	@parameters t k₁ k₂ k₃
	@variables  A(t) B(t) C(t)
	D = Differential(t);

	@named eq = ODESystem([D(A) ~ -A*k₁ + B*C*k₂,
			               D(B) ~ A*k₁ - B^2 * k₃ - B*C*k₂,
		                   D(C) ~ B^2 * k₃],
	                       t,[A,B,C],[k₁,k₂,k₃])

	k0 = [k₁ => 4.0e-2, k₂=>1.0e4, k₃=>3.0e7]
	c0 = [A => 1, B=>0, C=>0]
	τ = (1.0e-6,1.0e6)
	prob = ODEProblem(structural_simplify(eq),
		              c0,τ,k0,jac=true)

	#Use stiff numerical integration solver
	sol = solve(prob, TRBDF2())

	#Plotting solution with Plots.jl
	p1 = plot(sol,vars=[A,B,C],
		xaxis=:log,
		legend=(0.35,0.35),lw=3,size=(1100,400),
		title="semi-log scale")
	p2 = plot(sol,vars=[A,B,C],
		xaxis=:log,yaxis=(:log,[1.0e-12,:auto]),
		legend=(0.35,0.35),lw=3,size=(1100,400),
		title="log-log scale")
	timep = plot(p1,p2,layout=(1,2),margin=5Plots.mm,
		xlabel="time",ylabel="concentration")

	return eq,sol,timep
end;

# ╔═╡ 0267b2d1-f8da-48e8-991b-163497c0cd91
md"""
!!! note
	Created a function since the scope using Pluto.jl with these packages is a bit strange due to how Pluto.jl evaluates cells.
"""

# ╔═╡ 6da13129-b9f4-45c6-89fb-714200bce2d4
eqs,solution,timeplot = chemicalreaction_ode_solution();

# ╔═╡ 65cd1b1f-24df-4a48-bd26-0f394bc06c1f
md"""
Displaying the equation generated by the ModelingToolkit:
"""

# ╔═╡ 367a7c95-4655-4797-a62e-0f817d527dab
eqs

# ╔═╡ 56ba790d-0c78-46fb-b5b7-4711c77f4b54
md"""
and now displaying the plots from the solution.
"""

# ╔═╡ efe47a33-ea39-4f58-bc26-1517427f43f8
timeplot

# ╔═╡ 4f208f0a-7ff4-444d-b271-08f07ec31e72
md"""
So thats it! Pretty cool that we can solve this ODE so straightfowardly.

The thing to do is generalize the procedure to create a macro that returns an `ODESystem` for any arbitrary number of reactions and species. This would be similiar to the code below done for `SymPy.jl` but doing it using these packages.

```julia
using SymPy

struct RXN
	coeff::String
	reactants::Dict
	products::Dict
end

function getequations(species::Tuple,reactions::Array{RXN})
	symspecies = symbols(join(species," "),real=true,nonnegative=true)
	dicspecies = Dict(zip(species,symspecies))
	dequations = Dict(s=>Sym(0) for s in species)
	coeffs = Array{Sym}(undef,length(reactions))
	for (i,reaction) in enumerate(reactions)
		coeffs[i] = symbols(reaction.coeff)
		prodstoich = prod([dicspecies[s]^p for (s,p) in reaction.reactants])
		r = coeffs[i]*prodstoich
		for (name,stoich) in reaction.products
			dequations[name] += stoich*r
		end
	end
	#Generate array of equations rather than dictionary
	equations = [dequations[s] for s in species]
	return (equations,symspecies,coeffs)
end;
```
"""

# ╔═╡ 4d326031-3ec0-4faa-b6d2-531add859e06
html"""<style>
main {
    max-width: 1200px;
}
"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[compat]
DifferentialEquations = "~6.17.2"
ModelingToolkit = "~5.22.0"
Plots = "~1.18.2"
"""

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

[[AbstractTrees]]
git-tree-sha1 = "03e0550477d86222521d254b741d470ba17ea0b5"
uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
version = "0.3.4"

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

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

[[ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "f87e559f87a45bece9c9ed97458d3afe98b1ebb9"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.1.0"

[[ArrayInterface]]
deps = ["IfElse", "LinearAlgebra", "Requires", "SparseArrays", "Static"]
git-tree-sha1 = "045ff5e1bc8c6fb1ecb28694abba0a0d55b5f4f5"
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
version = "3.1.17"

[[ArrayLayouts]]
deps = ["FillArrays", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "0f7998147ff3d112fad027c894b6b6bebf867154"
uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
version = "0.7.3"

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

[[BandedMatrices]]
deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"]
git-tree-sha1 = "6facee700024bdc7bc870657d235848043f5564c"
uuid = "aae01518-5342-5314-be14-df237901396f"
version = "0.16.9"

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

[[BoundaryValueDiffEq]]
deps = ["BandedMatrices", "DiffEqBase", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "NLsolve", "Reexport", "SparseArrays"]
git-tree-sha1 = "fe34902ac0c3a35d016617ab7032742865756d7d"
uuid = "764a87c0-6b3e-53db-9096-fe964310641d"
version = "2.7.1"

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

[[CEnum]]
git-tree-sha1 = "215a9aa4a1f23fbd05b92769fdd62559488d70e9"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.1"

[[CSTParser]]
deps = ["Tokenize"]
git-tree-sha1 = "9723e1c07c1727082e169ca50789644a552fb023"
uuid = "00ebfdb7-1f24-5e51-bd34-a7502290713f"
version = "3.2.3"

[[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"

[[ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "dcc25ff085cf548bc8befad5ce048391a7c07d40"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "0.10.11"

[[ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random", "StaticArrays"]
git-tree-sha1 = "ed268efe58512df8c7e224d2e170afd76dd6a417"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.13.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"

[[Combinatorics]]
git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860"
uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
version = "1.0.2"

[[CommonMark]]
deps = ["Crayons", "JSON", "URIs"]
git-tree-sha1 = "7632afc57f92720a01d9aedf23f413f4e5e21015"
uuid = "a80b9123-70ca-4bc0-993e-6e3bcb318db6"
version = "0.8.1"

[[CommonSolve]]
git-tree-sha1 = "68a0743f578349ada8bc911a5cbd5a2ef6ed6d1f"
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
version = "0.2.0"

[[CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"

[[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 = "dc7dedc2c2aa9faf59a55c622760a25cbefbe941"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.31.0"

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

[[CompositeTypes]]
git-tree-sha1 = "d5b014b216dc891e81fea299638e4c10c657b582"
uuid = "b152e2b5-7a66-4b01-a709-34e65c35f657"
version = "0.1.2"

[[ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f74e9d5388b8620b4cee35d4c5a618dd4dc547f4"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.3.0"

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

[[Crayons]]
git-tree-sha1 = "3f71217b538d7aaee0b69ab47d9b7724ca8afa0d"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.0.4"

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

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

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

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

[[DelayDiffEq]]
deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "LinearAlgebra", "Logging", "NonlinearSolve", "OrdinaryDiffEq", "Printf", "RecursiveArrayTools", "Reexport", "UnPack"]
git-tree-sha1 = "6eba402e968317b834c28cd47499dd1b572dd093"
uuid = "bcd4f6db-9728-5f36-b5f7-82caef46ccdb"
version = "5.31.1"

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

[[DiffEqBase]]
deps = ["ArrayInterface", "ChainRulesCore", "DataStructures", "DocStringExtensions", "FastBroadcast", "FunctionWrappers", "IterativeSolvers", "LabelledArrays", "LinearAlgebra", "Logging", "MuladdMacro", "NonlinearSolve", "Parameters", "Printf", "RecursiveArrayTools", "RecursiveFactorization", "Reexport", "Requires", "SciMLBase", "Setfield", "SparseArrays", "StaticArrays", "Statistics", "SuiteSparse", "ZygoteRules"]
git-tree-sha1 = "932153f62d0508e59733e0fc33361470d293a889"
uuid = "2b5f629d-d688-5b77-993f-72d75c75574e"
version = "6.68.1"

[[DiffEqCallbacks]]
deps = ["DataStructures", "DiffEqBase", "ForwardDiff", "LinearAlgebra", "NLsolve", "OrdinaryDiffEq", "RecipesBase", "RecursiveArrayTools", "StaticArrays"]
git-tree-sha1 = "0972ca167952dc426b5438fc188b846b7a66a1f3"
uuid = "459566f4-90b8-5000-8ac3-15dfb0a30def"
version = "2.16.1"

[[DiffEqFinancial]]
deps = ["DiffEqBase", "DiffEqNoiseProcess", "LinearAlgebra", "Markdown", "RandomNumbers"]
git-tree-sha1 = "db08e0def560f204167c58fd0637298e13f58f73"
uuid = "5a0ffddc-d203-54b0-88ba-2c03c0fc2e67"
version = "2.4.0"

[[DiffEqJump]]
deps = ["ArrayInterface", "Compat", "DataStructures", "DiffEqBase", "FunctionWrappers", "LightGraphs", "LinearAlgebra", "PoissonRandom", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "StaticArrays", "TreeViews", "UnPack"]
git-tree-sha1 = "d2d9a628b9659a3107c95b0a61ca93865794245a"
uuid = "c894b116-72e5-5b58-be3c-e6d8d4ac2b12"
version = "6.15.1"

[[DiffEqNoiseProcess]]
deps = ["DiffEqBase", "Distributions", "LinearAlgebra", "Optim", "PoissonRandom", "QuadGK", "Random", "Random123", "RandomNumbers", "RecipesBase", "RecursiveArrayTools", "Requires", "ResettableStacks", "SciMLBase", "StaticArrays", "Statistics"]
git-tree-sha1 = "d6839a44a268c69ef0ed927b22a6f43c8a4c2e73"
uuid = "77a26b50-5914-5dd7-bc55-306e6241c503"
version = "5.9.0"

[[DiffEqPhysics]]
deps = ["DiffEqBase", "DiffEqCallbacks", "ForwardDiff", "LinearAlgebra", "Printf", "Random", "RecipesBase", "RecursiveArrayTools", "Reexport", "StaticArrays"]
git-tree-sha1 = "8f23c6f36f6a6eb2cbd6950e28ec7c4b99d0e4c9"
uuid = "055956cb-9e8b-5191-98cc-73ae4a59e68a"
version = "3.9.0"

[[DiffResults]]
deps = ["StaticArrays"]
git-tree-sha1 = "c18e98cba888c6c25d1c3b048e4b3380ca956805"
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
version = "1.0.3"

[[DiffRules]]
deps = ["NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "214c3fcac57755cfda163d91c58893a8723f93e9"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.0.2"

[[DifferentialEquations]]
deps = ["BoundaryValueDiffEq", "DelayDiffEq", "DiffEqBase", "DiffEqCallbacks", "DiffEqFinancial", "DiffEqJump", "DiffEqNoiseProcess", "DiffEqPhysics", "DimensionalPlotRecipes", "LinearAlgebra", "MultiScaleArrays", "OrdinaryDiffEq", "ParameterizedFunctions", "Random", "RecursiveArrayTools", "Reexport", "SteadyStateDiffEq", "StochasticDiffEq", "Sundials"]
git-tree-sha1 = "3a72107d0ce1594a2ebbd3d46c7d0832802e215a"
uuid = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
version = "6.17.2"

[[DimensionalPlotRecipes]]
deps = ["LinearAlgebra", "RecipesBase"]
git-tree-sha1 = "af883a26bbe6e3f5f778cb4e1b81578b534c32a6"
uuid = "c619ae07-58cd-5f6d-b883-8f17bd6a98f9"
version = "1.2.0"

[[Distances]]
deps = ["LinearAlgebra", "Statistics", "StatsAPI"]
git-tree-sha1 = "abe4ad222b26af3337262b8afb28fab8d215e9f8"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.3"

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

[[Distributions]]
deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns"]
git-tree-sha1 = "d5fa76fdab7bf54615262bd639e8c2e9bf295444"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.10"

[[DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "a32185f5428d3986f47c2ab78b1f216d5e6cc96f"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.5"

[[DomainSets]]
deps = ["CompositeTypes", "IntervalSets", "LinearAlgebra", "StaticArrays", "Statistics", "Test"]
git-tree-sha1 = "6cdd99d0b7b555f96f7cb05aa82067ee79e7aef4"
uuid = "5b8099bc-c8ec-5219-889f-1d9e522a28bf"
version = "0.5.2"

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

[[DynamicPolynomials]]
deps = ["DataStructures", "Future", "LinearAlgebra", "MultivariatePolynomials", "MutableArithmetics", "Pkg", "Reexport", "Test"]
git-tree-sha1 = "5e47c4d652ea67652b7c5945c79c46472397d47f"
uuid = "7c1d4256-1411-5781-91ec-d7bc3513ac07"
version = "0.3.18"

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

[[EllipsisNotation]]
deps = ["ArrayInterface"]
git-tree-sha1 = "8041575f021cba5a099a456b4163c9a08b566a02"
uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
version = "1.1.0"

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

[[ExponentialUtilities]]
deps = ["ArrayInterface", "LinearAlgebra", "Printf", "Requires", "SparseArrays"]
git-tree-sha1 = "ad435656c49da7615152b856c0f9abe75b0b5dc9"
uuid = "d4d017d3-3776-5f7e-afef-a10c40355c18"
version = "1.8.4"

[[ExprTools]]
git-tree-sha1 = "b7e3d17636b348f005f11040025ae8c6f645fe92"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.6"

[[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"

[[FastBroadcast]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "26be48918640ce002f5833e8fc537b2ba7ed0234"
uuid = "7034ab61-46d4-4ed7-9d0f-46aef9175898"
version = "0.1.8"

[[FastClosures]]
git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef"
uuid = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a"
version = "0.3.2"

[[FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays"]
git-tree-sha1 = "693210145367e7685d8604aee33d9bfb85db8b31"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "0.11.9"

[[FiniteDiff]]
deps = ["ArrayInterface", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays"]
git-tree-sha1 = "f6f80c8f934efd49a286bb5315360be66956dfc4"
uuid = "6a86dc24-6348-571c-b903-95158fe2bd41"
version = "2.8.0"

[[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"

[[ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "NaNMath", "Printf", "Random", "SpecialFunctions", "StaticArrays"]
git-tree-sha1 = "e2af66012e08966366a43251e1fd421522908be6"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.18"

[[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"

[[FunctionWrappers]]
git-tree-sha1 = "241552bc2209f0fa068b6415b1942cc0aa486bcc"
uuid = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e"
version = "1.1.2"

[[Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"

[[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 = "b83e3125048a9c3158cbb7ca423790c7b1b57bea"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.57.5"

[[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 = "e14907859a1d3aee73a019e7b3c98e9e7b8b5b3e"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.57.3+0"

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

[[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 = "47ce50b742921377301e15005c96e979574e130b"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.1+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 = "c6a1fff2fd4b1da29d3dccaffb1e1001244d844e"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.12"

[[Hwloc]]
deps = ["Hwloc_jll"]
git-tree-sha1 = "92d99146066c5c6888d5a3abc871e6a214388b91"
uuid = "0e44f5e4-bd66-52a0-8798-143a42290a1d"
version = "2.0.0"

[[Hwloc_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3395d4d4aeb3c9d31f5929d32760d8baeee88aaf"
uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8"
version = "2.5.0+0"

[[IfElse]]
git-tree-sha1 = "28e837ff3e7a6c3cdb252ce49fb412c8eb3caeef"
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
version = "0.1.0"

[[Inflate]]
git-tree-sha1 = "f5fc07d4e706b84f72d54eedcc1c13d92fb0871c"
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
version = "0.1.2"

[[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"

[[IntervalSets]]
deps = ["Dates", "EllipsisNotation", "Statistics"]
git-tree-sha1 = "3cc368af3f110a767ac786560045dceddfc16758"
uuid = "8197267c-284f-5f27-9208-e0e47529a953"
version = "0.5.3"

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

[[IterativeSolvers]]
deps = ["LinearAlgebra", "Printf", "Random", "RecipesBase", "SparseArrays"]
git-tree-sha1 = "1a8c6237e78b714e901e406c096fc8a65528af7d"
uuid = "42fd0dbc-a981-5370-80f2-aaf504508153"
version = "0.9.1"

[[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 = "81690084b6198a2e1da36fcfda16eeca9f9f24e4"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.1"

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

[[JuliaFormatter]]
deps = ["CSTParser", "CommonMark", "DataStructures", "Pkg", "Tokenize"]
git-tree-sha1 = "9e7476b5e1dc749e525497eef53809893cb6c898"
uuid = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
version = "0.14.8"

[[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"

[[LabelledArrays]]
deps = ["ArrayInterface", "LinearAlgebra", "MacroTools", "StaticArrays"]
git-tree-sha1 = "5e38cfdd771c34821ade5515f782fe00865d60b3"
uuid = "2ee39098-c373-598a-b85f-a56591580800"
version = "1.6.2"

[[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"

[[LightGraphs]]
deps = ["ArnoldiMethod", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "432428df5f360964040ed60418dd5601ecd240b6"
uuid = "093fc24a-ae57-5d10-9952-331d41423f4d"
version = "1.3.5"

[[LineSearches]]
deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"]
git-tree-sha1 = "f27132e551e959b3667d8c93eae90973225032dd"
uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
version = "7.1.1"

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

[[LogExpFunctions]]
deps = ["DocStringExtensions", "LinearAlgebra"]
git-tree-sha1 = "7bd5f6565d80b6bf753738d2bc40a5dfea072070"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.2.5"

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

[[LoopVectorization]]
deps = ["ArrayInterface", "DocStringExtensions", "IfElse", "LinearAlgebra", "OffsetArrays", "Polyester", "Requires", "SLEEFPirates", "Static", "StrideArraysCore", "ThreadingUtilities", "UnPack", "VectorizationBase"]
git-tree-sha1 = "652a17092a160bb9677eefb18db31d717e7a4078"
uuid = "bdcacae8-1622-11e9-2a5c-532679323890"
version = "0.12.50"

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

[[ManualMemory]]
git-tree-sha1 = "80ccdd8143934c40a170ef3178af64b7905230bd"
uuid = "d125e4d3-2237-4719-b19c-fa641b8a4667"
version = "0.1.3"

[[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 = "4ea90bd5d3985ae1f9a908bd4500ae88921c5ce7"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.0"

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

[[ModelingToolkit]]
deps = ["AbstractTrees", "ArrayInterface", "ConstructionBase", "DataStructures", "DiffEqBase", "DiffEqJump", "DiffRules", "Distributed", "Distributions", "DocStringExtensions", "DomainSets", "IfElse", "InteractiveUtils", "JuliaFormatter", "LabelledArrays", "Latexify", "Libdl", "LightGraphs", "LinearAlgebra", "MacroTools", "NaNMath", "NonlinearSolve", "RecursiveArrayTools", "Reexport", "Requires", "RuntimeGeneratedFunctions", "SafeTestsets", "SciMLBase", "Serialization", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "SymbolicUtils", "Symbolics", "UnPack", "Unitful"]
git-tree-sha1 = "9cc6e4543374e89b4a33c4b787b3ab6298a4cf78"
uuid = "961ee093-0014-501f-94e3-6117800e7a78"
version = "5.22.0"

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

[[MuladdMacro]]
git-tree-sha1 = "c6190f9a7fc5d9d5915ab29f2134421b12d24a68"
uuid = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221"
version = "0.2.2"

[[MultiScaleArrays]]
deps = ["DiffEqBase", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "OrdinaryDiffEq", "Random", "RecursiveArrayTools", "SparseDiffTools", "Statistics", "StochasticDiffEq", "TreeViews"]
git-tree-sha1 = "258f3be6770fe77be8870727ba9803e236c685b8"
uuid = "f9640e96-87f6-5992-9c3b-0743c6a49ffa"
version = "1.8.1"

[[MultivariatePolynomials]]
deps = ["DataStructures", "LinearAlgebra", "MutableArithmetics"]
git-tree-sha1 = "45c9940cec79dedcdccc73cc6dd09ea8b8ab142c"
uuid = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3"
version = "0.3.18"

[[MutableArithmetics]]
deps = ["LinearAlgebra", "SparseArrays", "Test"]
git-tree-sha1 = "3927848ccebcc165952dc0d9ac9aa274a87bfe01"
uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
version = "0.2.20"

[[NLSolversBase]]
deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"]
git-tree-sha1 = "50608f411a1e178e0129eab4110bd56efd08816f"
uuid = "d41bc354-129a-5804-8e4c-c37616107c6c"
version = "7.8.0"

[[NLsolve]]
deps = ["Distances", "LineSearches", "LinearAlgebra", "NLSolversBase", "Printf", "Reexport"]
git-tree-sha1 = "019f12e9a1a7880459d0173c182e6a99365d7ac1"
uuid = "2774e3e8-f4cf-5e23-947b-6d7e65073b56"
version = "4.5.1"

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

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

[[NonlinearSolve]]
deps = ["ArrayInterface", "FiniteDiff", "ForwardDiff", "IterativeSolvers", "LinearAlgebra", "RecursiveArrayTools", "RecursiveFactorization", "Reexport", "SciMLBase", "Setfield", "StaticArrays", "UnPack"]
git-tree-sha1 = "ef18e47df4f3917af35be5e5d7f5d97e8a83b0ec"
uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
version = "0.3.8"

[[OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "2bf78c5fd7fa56d2bbf1efbadd45c1b8789e6f57"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.2"

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

[[OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

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

[[OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"

[[Optim]]
deps = ["Compat", "FillArrays", "LineSearches", "LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "PositiveFactorizations", "Printf", "SparseArrays", "StatsBase"]
git-tree-sha1 = "d34366a3abc25c41f88820762ef7dfdfe9306711"
uuid = "429524aa-4258-5aef-a3af-852621145aeb"
version = "1.3.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"

[[OrdinaryDiffEq]]
deps = ["Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "ExponentialUtilities", "FastClosures", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "Logging", "MacroTools", "MuladdMacro", "NLsolve", "Polyester", "RecursiveArrayTools", "Reexport", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"]
git-tree-sha1 = "c976f6257f59db6ab0ae458fa168aa24ed543652"
uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
version = "5.60.0"

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

[[PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "4dd403333bcf0909341cfe57ec115152f937d7d8"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.1"

[[ParameterizedFunctions]]
deps = ["DataStructures", "DiffEqBase", "DocStringExtensions", "Latexify", "LinearAlgebra", "ModelingToolkit", "Reexport", "SciMLBase"]
git-tree-sha1 = "d290c172dae21d73ae6a19a8381abbb69ef0a624"
uuid = "65888b18-ceab-5e60-b2b9-181511a3b968"
version = "5.10.0"

[[Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "2276ac65f1e236e0a6ea70baff3f62ad4c625345"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.2"

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

[[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 = "501c20a63a34ac1d015d5304da0e645f42d91c9f"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.0.11"

[[Plots]]
deps = ["Base64", "Contour", "Dates", "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 = "f32cd6fcd2909c2d1cdd47ce55e1394b04a66fe2"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.18.2"

[[PoissonRandom]]
deps = ["Random", "Statistics", "Test"]
git-tree-sha1 = "44d018211a56626288b5d3f8c6497d28c26dc850"
uuid = "e409e4f3-bfea-5376-8464-e040bb5c01ab"
version = "0.4.0"

[[Polyester]]
deps = ["ArrayInterface", "IfElse", "ManualMemory", "Requires", "Static", "StrideArraysCore", "ThreadingUtilities", "VectorizationBase"]
git-tree-sha1 = "f5a74523ebc205723baefb95874f708741199d70"
uuid = "f517fe37-dbe3-4b94-8317-1923a5111588"
version = "0.3.4"

[[PositiveFactorizations]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "17275485f373e6673f7e7f97051f703ed5b15b20"
uuid = "85a6dd25-e78a-55b7-8502-1745935b8125"
version = "0.2.4"

[[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"

[[QuadGK]]
deps = ["DataStructures", "LinearAlgebra"]
git-tree-sha1 = "12fbe86da16df6679be7521dfb39fbc861e1dc7b"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.4.1"

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

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

[[Random123]]
deps = ["Libdl", "Random", "RandomNumbers"]
git-tree-sha1 = "0e8b146557ad1c6deb1367655e052276690e71a3"
uuid = "74087812-796a-5b5d-8853-05524746bad3"
version = "1.4.2"

[[RandomNumbers]]
deps = ["Random", "Requires"]
git-tree-sha1 = "441e6fc35597524ada7f85e13df1f4e10137d16f"
uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143"
version = "1.4.0"

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

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

[[RecursiveArrayTools]]
deps = ["ArrayInterface", "ChainRulesCore", "DocStringExtensions", "LinearAlgebra", "RecipesBase", "Requires", "StaticArrays", "Statistics", "ZygoteRules"]
git-tree-sha1 = "8755b407ac7de9256b21b5da1c7304aa3e398847"
uuid = "731186ca-8d62-57ce-b412-fbd966d074cd"
version = "2.14.8"

[[RecursiveFactorization]]
deps = ["LinearAlgebra", "LoopVectorization"]
git-tree-sha1 = "2e1a88c083ebe8ba69bc0b0084d4b4ba4aa35ae0"
uuid = "f2c3362d-daeb-58d1-803e-2bc74f2840b4"
version = "0.1.13"

[[Reexport]]
git-tree-sha1 = "5f6c21241f0f655da3952fd60aa18477cf96c220"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.1.0"

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

[[ResettableStacks]]
deps = ["StaticArrays"]
git-tree-sha1 = "622b3e491fb0a85fbfeed6f17dc320a9f46d8929"
uuid = "ae5879a3-cd67-5da8-be7f-38c6eb64a37b"
version = "1.1.0"

[[Rmath]]
deps = ["Random", "Rmath_jll"]
git-tree-sha1 = "bf3188feca147ce108c76ad82c2792c57abe7b1f"
uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa"
version = "0.7.0"

[[Rmath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "68db32dff12bb6127bac73c209881191bf0efbb7"
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
version = "0.3.0+0"

[[RuntimeGeneratedFunctions]]
deps = ["ExprTools", "SHA", "Serialization"]
git-tree-sha1 = "5975a4f824533fa4240f40d86f1060b9fc80d7cc"
uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47"
version = "0.5.2"

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

[[SLEEFPirates]]
deps = ["IfElse", "Static", "VectorizationBase"]
git-tree-sha1 = "da6d214ffc85b1292f300649ef86d3c4f9aaf25d"
uuid = "476501e8-09a2-5ece-8869-fb82de89a1fa"
version = "0.6.22"

[[SafeTestsets]]
deps = ["Test"]
git-tree-sha1 = "36ebc5622c82eb9324005cc75e7e2cc51181d181"
uuid = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
version = "0.0.1"

[[SciMLBase]]
deps = ["ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "RecipesBase", "RecursiveArrayTools", "StaticArrays", "Statistics", "Tables", "TreeViews"]
git-tree-sha1 = "932aaae93e81686e6473f27b5a11c403576a2183"
uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
version = "1.18.0"

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

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

[[Setfield]]
deps = ["ConstructionBase", "Future", "MacroTools", "Requires"]
git-tree-sha1 = "d5640fc570fb1b6c54512f0bd3853866bd298b3e"
uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
version = "0.7.0"

[[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"

[[SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"

[[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"

[[SparseDiffTools]]
deps = ["Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "LightGraphs", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays", "VertexSafeGraphs"]
git-tree-sha1 = "0b80aeffdc8a7bae5b6f7a9d43c600215775788b"
uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804"
version = "1.14.0"

[[SpecialFunctions]]
deps = ["ChainRulesCore", "LogExpFunctions", "OpenSpecFun_jll"]
git-tree-sha1 = "a50550fa3164a8c46747e62063b4d774ac1bcf49"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "1.5.1"

[[Static]]
deps = ["IfElse"]
git-tree-sha1 = "2740ea27b66a41f9d213561a04573da5d3823d4b"
uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
version = "0.2.5"

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

[[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 = "2f6792d523d7448bbe2fec99eca9218f06cc746d"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.8"

[[StatsFuns]]
deps = ["LogExpFunctions", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "30cd8c360c54081f806b1ee14d2eecbef3c04c49"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "0.9.8"

[[SteadyStateDiffEq]]
deps = ["DiffEqBase", "DiffEqCallbacks", "LinearAlgebra", "NLsolve", "Reexport", "SciMLBase"]
git-tree-sha1 = "3df66a4a9ba477bea5cb10a3ec732bb48a2fc27d"
uuid = "9672c7b4-1e72-59bd-8a11-6ac3964bc41f"
version = "1.6.4"

[[StochasticDiffEq]]
deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "DiffEqJump", "DiffEqNoiseProcess", "DocStringExtensions", "FillArrays", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "Logging", "MuladdMacro", "NLsolve", "OrdinaryDiffEq", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"]
git-tree-sha1 = "aee830c3b2c96d0e2e9fa40c5cae30d281db0dbd"
uuid = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0"
version = "6.35.0"

[[StrideArraysCore]]
deps = ["ArrayInterface", "ManualMemory", "Requires", "ThreadingUtilities", "VectorizationBase"]
git-tree-sha1 = "f25b9b62645d97ca5770015ad5d144c3e220fb47"
uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da"
version = "0.1.15"

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

[[SuiteSparse]]
deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"]
uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"

[[SuiteSparse_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"

[[Sundials]]
deps = ["CEnum", "DataStructures", "DiffEqBase", "Libdl", "LinearAlgebra", "Logging", "Reexport", "SparseArrays", "Sundials_jll"]
git-tree-sha1 = "4acae01957a38544ee0d00bc10c53d137c1e4439"
uuid = "c3572dad-4567-51f8-b174-8c6c989267f4"
version = "4.5.1"

[[Sundials_jll]]
deps = ["CompilerSupportLibraries_jll", "Libdl", "OpenBLAS_jll", "Pkg", "SuiteSparse_jll"]
git-tree-sha1 = "013ff4504fc1d475aa80c63b455b6b3a58767db2"
uuid = "fb77eaff-e24c-56d4-86b1-d163f2edb164"
version = "5.2.0+1"

[[SymbolicUtils]]
deps = ["AbstractTrees", "ChainRulesCore", "Combinatorics", "ConstructionBase", "DataStructures", "DynamicPolynomials", "IfElse", "LabelledArrays", "LinearAlgebra", "MultivariatePolynomials", "NaNMath", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "TimerOutputs"]
git-tree-sha1 = "17fecd52e9a82ca52bfc9d28a2d31b33458a6ce0"
uuid = "d1185830-fcd6-423d-90d6-eec64667417b"
version = "0.13.1"

[[Symbolics]]
deps = ["ConstructionBase", "DiffRules", "Distributions", "DocStringExtensions", "DomainSets", "IfElse", "Latexify", "Libdl", "LinearAlgebra", "MacroTools", "NaNMath", "RecipesBase", "Reexport", "Requires", "RuntimeGeneratedFunctions", "SciMLBase", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "SymbolicUtils", "TreeViews"]
git-tree-sha1 = "24fbb434af5bc33ab8df86857f0297fe8e4a1e90"
uuid = "0c5d862f-8b57-4792-8d23-62f2024744c7"
version = "1.3.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 = "8ed4a3ea724dac32670b062be3ef1c1de6773ae8"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.4.4"

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

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

[[ThreadingUtilities]]
deps = ["ManualMemory"]
git-tree-sha1 = "593009385e6536dc50baedc2c8bc1a3717ef358f"
uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5"
version = "0.4.5"

[[TimerOutputs]]
deps = ["ExprTools", "Printf"]
git-tree-sha1 = "209a8326c4f955e2442c07b56029e88bb48299c7"
uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
version = "0.5.12"

[[Tokenize]]
git-tree-sha1 = "eee92eda3cc8e104b7e56ff4c1fcf0d78ca37c89"
uuid = "0796e94c-ce3b-5d07-9a54-7f471281c624"
version = "0.5.18"

[[TreeViews]]
deps = ["Test"]
git-tree-sha1 = "8d0d7a3fe2f30d6a7f833a5f19f7c7a5b396eae6"
uuid = "a2a6695c-b41b-5b7d-aed9-dbfdeacea5d7"
version = "0.3.0"

[[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"

[[UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

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

[[Unitful]]
deps = ["ConstructionBase", "Dates", "LinearAlgebra", "Random"]
git-tree-sha1 = "b3682a0559219355f1e3c8024e9f97adce2d4623"
uuid = "1986cc42-f94f-5a68-af5c-568840ba703d"
version = "1.8.0"

[[VectorizationBase]]
deps = ["ArrayInterface", "Hwloc", "IfElse", "Libdl", "LinearAlgebra", "Static"]
git-tree-sha1 = "0ba060e248edfacacafd764926cdd6de51af1343"
uuid = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f"
version = "0.20.19"

[[VertexSafeGraphs]]
deps = ["LightGraphs"]
git-tree-sha1 = "b9b450c99a3ca1cc1c6836f560d8d887bcbe356e"
uuid = "19fa3120-7c27-5ec5-8db8-b0b0aa330d6f"
version = "0.1.2"

[[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"

[[ZygoteRules]]
deps = ["MacroTools"]
git-tree-sha1 = "9e7a1e8ca60b742e508a315c17eef5211e7fbfd7"
uuid = "700de1a5-db45-46bc-99cf-38207098b444"
version = "0.2.1"

[[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:
# ╟─d4f1e3a9-d1c8-4e3e-8b88-f0a901a894f7
# ╟─656cae30-e450-11eb-266a-f7572588b91b
# ╠═a6e71018-ab69-42d0-9a15-ffb477b4bd64
# ╠═53eaf1ae-6d16-4606-b5d2-97fd61ac7da6
# ╟─0267b2d1-f8da-48e8-991b-163497c0cd91
# ╠═6da13129-b9f4-45c6-89fb-714200bce2d4
# ╟─65cd1b1f-24df-4a48-bd26-0f394bc06c1f
# ╟─367a7c95-4655-4797-a62e-0f817d527dab
# ╟─56ba790d-0c78-46fb-b5b7-4711c77f4b54
# ╟─efe47a33-ea39-4f58-bc26-1517427f43f8
# ╟─4f208f0a-7ff4-444d-b271-08f07ec31e72
# ╟─4d326031-3ec0-4faa-b6d2-531add859e06
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


#-----------------------------------------------------------------------
#       BEGIN   Minkowski.jl
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
#   THE MINKOWSKI PRODUCT (RECTANGULAR COORDINATES)
#-----------------------------------------------------------------------
"""
    ηdot( V1::RealVec , V2::RealVec )

The function `ηdot` takes two vectors ``V_1`` and ``V_2`` of equal
dimension, and computes their Minkowski product ``η(V_1,V_2)``, with the
assumption that the first element of the vectors corresponds to the time
component.

"""
function ηdot( V1::RealVec , V2::RealVec )  # Computes Minkowski product
    nv1 = length(V1)
    nv2 = length(V2)

    met = -V1[1]*V2[1]

    if nv1==nv2
        for i=2:nv1
            met += V1[i]*V2[i]
        end
        return met
    else
        print("Vectors are of a different dimension.")
        return 0*V[1]
    end
end     #---------------------------------------------------------------

#-----------------------------------------------------------------------
#   THE MINKOWSKI NORM
#-----------------------------------------------------------------------
"""
    mnorm( V )

The function `mnorm` computes the Minkowski norm, which is
mathematically equivalent to the absolute value of the square root of
the Minkowski product ``√|η(V_1,V_2)|``. However, this function computes
the result according to the formula used in the hypot function.

"""
function mnorm( V )
    l = length(V)

    t = abs(V[1])
    x = norm(V[2:l])

    if t > x
        return abs(t - ( x/t )*( x / ( 1 + √( 1 - (x/t)^2 ) ) ))
    elseif x > t
        return abs(x - ( t/x )*( t / ( 1 + √( 1 - (t/x)^2 ) ) ))
    else
        return zero( typeof(V[1]) )
    end
end     #---------------------------------------------------------------

#-----------------------------------------------------------------------
#   THE MINKOWSKI METRIC (RECTANGULAR COORDINATES)
#-----------------------------------------------------------------------
"""
    ημν( tpfl::DataType=Float64 , dim::Int=4 )

The function `ημν` constructs the components of the Minkowski metric.
The first argument `tpfl` specifies the floating point datatype
(typically Float64 or Double64 if one uses the DoubleFloats package) and
the second argument `dim` specifies the dimension. The default values
are `tpfl=Float64` and `dim=4`:

    julia> ημν() == ημν( Float64 , 4 )
        true

"""
function ημν( tpfl::DataType=Float64 , dim::Int=4 )
    gη = one(tpfl)*(I(dim))

    gη[1,1] = -gη[1,1]

    return Matrix(gη)
end     #---------------------------------------------------------------

#-----------------------------------------------------------------------
#   KRONECKER DELTA
#-----------------------------------------------------------------------
"""
    δμν( tpfl::DataType=Float64 , dim::Int=4 )

The function `δμν` returns the components of an identity matrix of
dimension `dim` using the floating-point datatype `tpfl`

"""
function δμν( tpfl::DataType=Float64 , dim::Int=4 )
    return one(tpfl)*(I(dim))
end     #---------------------------------------------------------------

#-----------------------------------------------------------------------
#       END     Minkowski.jl
#-----------------------------------------------------------------------


#=
Problem 1
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
=#
sum = 0
for i = 1:999
  if (i % 3 == 0 || i % 5 == 0)
    sum += i
  end
end

println("The sum is: $(sum)")


x = [ x^2 for x = 1:5 ]                # Square of the numbers 1 to 5

A = [ x+y for x = 1:3, y = 1:5 ]       # 3x5 matrix with entries A_ij = i + j

B = [ x^y for x = 1:3, y = 1:5 ]       # 3x5 matrix with entries A_ij = i^j

x = [ x^2 for x = 1:10 if x%3 == 0]    # Only for x that are multiples of 3

y = Float64[ rand(-5:5) for i = 1:2, j = 1:10 ]

gen = (i*(i-1) for i = 1:10)        # A generator expression

for x in gen                        # Loop over all the values in the generator expression
    print(x, " ")
end

reshape(1:15, 3, 5)

permutedims(reshape(1:15, 5, 3))

repeat(1:2, 3)

repeat(1:2, 3, 4)

repeat([1 2; 3 4], 1, 2)


# Compute Eccentric Anomally from Mean Anomally
# WARNING: Only valid for small e.  Not convergent for e>~0.66
# Therefore, this should only be used for testing purposes, not general science applications
function ecc_anom_bessel_series_approx{T}(mean_anom::T, ecc::T; tol::Real = 1.e-12)
  sinM = sin(mean_anom)
  sin2M = sin(2*mean_anom)
  sin3M = sin(3*mean_anom)
  sin4M = sin(4*mean_anom)
  E = mean_anom+ecc*(sinM+ecc*(0.5*sin2M+ecc*((3*sin3M-sinM)/8+ecc*((sin4M-0.5*sin2M)/3))))
end

#=  Compute Eccentric Anomally from Mean Anomally robustly
    Initial guess for eccentric anomaly for use by itterative solvers of Kepler's equation
    Based on "The Solution of Kepler's Equations - Part Three"
            Danby, J. M. A. (1987) Journal: Celestial Mechanics, Volume 40, Issue 3-4, pp. 303-312
            1987CeMec..40..303D
=#
function ecc_anom_init_guess_danby{T}(M::T, ecc::T)
    local k, E
    const k = convert(T,0.85)
    if(M<zero(T)) M += 2pi end
    E = (M<pi) ? M + k*ecc : M - k*ecc;
end

#= Update the current guess for solution to Kepler's equation
   Based on "An Improved Algorithm due to Laguerre for the Solution of Kepler's Equation"
   Conway, B. A.  (1986) Celestial Mechanics, Volume 39, Issue 2, pp.199-211
  1986CeMec..39..199C
=#
function update_ecc_anom_laguerre{T}(E::T, M::T, ecc::T)
  es = ecc*sin(E)
  ec = ecc*cos(E)
  F = (E-es)-M
  Fp = one(T)-ec
  Fpp = es
  const n = 5
  root = sqrt(abs((n-1)*((n-1)*Fp*Fp-n*F*Fpp)))
  denom = Fp>zero(T) ? Fp+root : Fp-root
  return E-n*F/denom
end

# Loop to update the current estimate of the solution to Kepler's equation
function calc_ecc_anom_itterative_laguerre{T}(mean_anom::T, ecc::T; tol::Real = 1.e-8)
    local M, E, E_old
    #M = atan2(sin(mean_anom),cos(mean_anom))  # WARNING: Kludge since missing autodif for mod2pi  # [-pi,pi]
    M = mod2pi(mean_anom)
    E = ecc_anom_init_guess_danby(M,ecc)
    const max_its_laguerre = 200
    for i in 1:max_its_laguerre
       E_old = E
       E = update_ecc_anom_laguerre(E_old, M, ecc)
       if abs(E-E_old)<tol break end
    end
    @assert abs(E-E_old)<tol
    return E
end

# Set the default Kepler solver
calc_ecc_anom = calc_ecc_anom_itterative_laguerre
#=
 function calc_ecc_anom{T}(mean_anom::T, ecc::T; tol::Real = 1.e-8)
  return calc_ecc_anom_itterative_laguerre(mean_anom, ecc, tol=tol)
end
=#

# export calc_ecc_anom


#!/usr/bin/env julia
using Plots

# sigmoid function
s(a,x)   = 1/(1+exp(-a*x))

# first derivative of sigmoid function
d1s(a,x) = a*exp(-a*x)/((1+exp(-a*x))^2)

# second derivative of sigmoid function
d2s(a,x) = a * (2*d1s(a,x)*exp(-a*x)/(1+exp(-a*x))  - d1s(a,x))

x  =  range(-5.0,5.0,step=0.01)
s1   =  s.(5,x)
d1s1 =  d1s.(5,x)
#d2s1 =  d2s.(5,x)

plot(x,[s1,d1s1],yscale = :log10)
# ,d2s1]
#label = ["sigmoid", "dsigmoid/dx", "d^2sigmoid/dx^2"])


module FindingPi

export Point, is_inside, find_pi, random_point, generate_points

type Point
    x::Real
    y::Real
end

# r^2 = x^2 + y^2
is_inside(x, y, radius) = x^2 + y^2 <= radius^2
is_inside(point, radius) = is_inside(point.x, point.y, radius)
is_inside(point) = is_inside(point, 1)

# area_circle = pi*r^2
# area_square = (2r)^2
#  => c / s = pi / 4
find_pi(inside, total) = 4 * inside / total

function random_point()
    x = (rand() * 2) - 1
    y = (rand() * 2) - 1
    Point(x, y)
end

generate_points(n) = [random_point() for i=1:n]

end

module TestingPi

using FindingPi
using Base.Test

# is_inside
@test is_inside(0, 0, 1)
@test !is_inside(1, 1, 1)
@test is_inside(1/sqrt(2), 1/sqrt(2), 1)
@test is_inside(Point(0,0))

# find_pi
@test find_pi(100, 100) == 4

# generate_points
@test typeof(random_point()) == Point
@test length(generate_points(4)) == 4

end

module FindingPiSim

using FindingPi

function trial(n)
    points = generate_points(n)
    points_inside = map(is_inside, points)
    inside_count = sum(points_inside)
    pi_estimate = find_pi(inside_count, n)
end

function batch(range, iterations)
    results = Array(Real, (length(range) * iterations, 2))
    i = 1
    for n = range
        for j = 1:iterations
            results[i, :] = [n, trial(n)]
            i += 1
        end
    end
    results
end

end

# Analysis with Gadfly and DataFrames
# -----------------------------------

FindingPiSim.trial(1000000)

Pkg.add("Gadfly")
Pkg.add("DataFrames")

using Gadfly
using DataFrames

range = 100:10:1000
iterations = 5

total_points = sum(range) * iterations
println("$total_points points")
t1 = time()

res = FindingPiSim.batch(range, iterations)

t2 = time()
println("total time: $(t2 - t1)")
println("time per point: $((t2 - t1) / total_points)")

df = DataFrame(n=res[:, 1], pi_est=res[:, 2])
df[:error] = pi - df[:pi_est]

# A simple plot:
plot(df, x="n", y="pi_est", color="error", Geom.point)

# A more complex plot, with a theme for point size,
# and a layer to mark the true value of pi with a line:
#
# t = Theme(
#     default_point_size=Compose.Measure(0.7),
#     highlight_width=Compose.Measure(0.1)
# )
#
# plot(
#     layer(x->3.1415, range[1], range[end]),
#     layer(df, x="n", y="pi_est", color="error", Geom.point, t)
# )


# This file illustrates calculation of power spectral density and total average power of an white Gaussian noise.

using FFTW
using Plots
using DSP
using Statistics

# Construct noise signal
N0 = 50.
fs = 100
ts = 1 / fs
ln = 2^10
tn = (0 : ln - 1) * ts
n = sqrt(N0 / 2 * fs) * randn(ln)

# Compute autocorrelation function.
Rn = xcorr(n, n) / (ln - 1)
τ = (-ln + 1 : ln - 1) * ts
lr = length(Rn)

# Fourier tranform of autocorrelation function
xrf = fft(Rn) * ts
psdr = abs.(xrf)
ffr = (0 : 1 / (lr - 1) : 1) * fs
Δfr = fs / (lr - 1)
Pfr = sum(psdr[1 : end - 1]) * Δfr

# Compute power spectral density
xfn = fft(n) * ts
psdn = abs.(xfn).^2 / (ln - 1) / ts
ffn = (0 : 1 / (ln - 1) : 1) * fs

# Compute powers
Pt = sum(n[1 : ln - 1].^2) / (ln - 1)
Δf = fs / (ln - 1)
Pfn = sum(psdn[1 : end - 1]) * Δf

# Compare all the powers and variance
@show  Pfr, Pt, Pfn, var(n)

# Plots
plt = plot(layout=4)
plot!(tn, n, subplot=1)
plot!(τ, Rn, subplot=2)
plot!(ffn, psdn, subplot=3)
plot!(ffr, psdr, subplot=4)
display(plt)


# [69](https://projecteuler.net/problem=69)

#Euler totient function looks like
#```math
#\varphi(n) = n \prod_{p|n} ( 1 - \frac{1}{p} )
#```
#
#To find the solution n* which maximizes our object function
#```math
#\text{max} \frac{n}{\varphi(n)} = \frac{1}{ \prod\limits_{p|n} (1-\frac{1}{p}) }, n \leq 1000000
#```
#
#is equivalent to
#```math
#\text{min} \prod_{p|n} (1-\frac{1}{p}), n \leq 1000000
#```
#
#Distinct prime factors $`p_i \in \{p|n\}`$ are always positive integers that are larger than 1,
#hence $`0 < 1-\frac{1}{p} < 1`$ always holds. To minimize the above object function, we need
#as many distince prime factors as possible from the number n*. Now we comprehend this problem
#as to figure out a integer n* where n* <= 1000000 and has the most distinct prime factors
#among the ingeters less or equal to itself.
#
#Let's think about this problem in the reverse direction. The most ideal integer for this problem
#should ship all possible primes, e.g. $`n^* =\prod([2,3,5,7,11,\ldots])`$. Moreover, there are infinite
#number of primes, and the constraint $`n\leq 1000000`$ is exactly telling us when we should stop
#the infinite production.
#
for i in 1:20
    @printf "%d\t%8d\t%s\n" i prod(primes(i)) "$(prod(primes(i))<1_000_000)"
end

#Output
#```
#1	       1	true
#2	       2	true
#3	       6	true
#4	       6	true
#5	      30	true
#6	      30	true
#7	     210	true
#8	     210	true
#9	     210	true
#10	     210	true
#11	    2310	true
#12	    2310	true
#13	   30030	true
#14	   30030	true
#15	   30030	true
#16	   30030	true
#17	  510510	true
#18	  510510	true    *
#19	 9699690	false
#20	 9699690	false
#```


function pagerank(
    g::AbstractGraph{U},
    α=0.85,
    n=100::Integer,
    ϵ=1.0e-6
    ) where U <: Integer

    # indegree(g, v) is estimated run-time to iterate over inneighbors(g, v)
    partitions = LightGraphs.optimal_contiguous_partition(indegree(g), nthreads(), nv(g))

    # collect dangling nodes
    dangling_nodes = [v for v in vertices(g) if outdegree(g, v) == 0]
    N = Int(nv(g))
    # solution vector and temporary vector
    x = fill(1.0 / N, N)
    xlast = copy(x)
    # personalization vector
    p = fill(1.0 / N, N)
    # adjustment for leaf nodes in digraph
    dangling_weights = p
    for _ in 1:n
        dangling_sum = 0.0
        for v in dangling_nodes
            dangling_sum += x[v]
        end
        # flow from teleprotation
        for v in vertices(g)
            xlast[v] = (1 - α + α * dangling_sum) * p[v]
        end
        # flow from edges
        @threads for v_set in partitions
            for v in v_set
                for u in inneighbors(g, v)
                    xlast[v] += α * x[u] / outdegree(g, u)
                end
            end
        end

        # l1 change in solution convergence criterion
        err = 0.0
        for v in vertices(g)
            err += abs(xlast[v] - x[v])
            x[v] = xlast[v]
        end
        if (err < N * ϵ)
            return x
        end
    end
    error("Pagerank did not converge after $n iterations.") # TODO 0.7: change to InexactError with appropriate msg.
end


module problem120

description = """
Square remainders
Let r be the remainder when (a−1)^n + (a+1)^n is divided by a^2.
For example, if a = 7 and n = 3, then r = 42: 63 + 83 = 728 ≡ 42 mod 49. And as n varies, so too will r, but for a = 7 it turns out that rmax = 42.

For 3 ≤ a ≤ 1000, find ∑ rmax.
"""

# compute the maximum value for r = ((a-1)^n + (a+1)^n) % (a^2)
# For increasing values of n, this is a repeating sequence.
# Stop searching for max r when the first value is repeated.
# Perform the power operations using modulo arithmetic to prevent overflow, reusing the results of the previous iterations.
function rmax(a :: Int)
  as1 = a - 1
  ap1 = a + 1
  asq = a * a
  r1 = (as1 + ap1) % asq
  result = r1
  while true
    as1 = (as1 * (a-1)) % asq
    ap1 = (ap1 * (a+1)) % asq
    r = (as1 + ap1) % asq
    if r == r1
      return result
    end
    result = max(result, r)
  end
end

function sumrmax(low=3, high=1000)
  return sum(map(rmax, low:high))
end

using Base.Test
@test rmax(7) == 42

end


"""
Created on Thu Apr 09 2020

@author: Yoann Pradat

α and β divergences.
"""

"""
β_divergence(X, Y, β[, ϵ])

Compute the the β-divergence of X and Y, d_β(X||Y).

# Arguments
- `X::Matrix{<:Real}`: array
- `Y::Matrix{<:Real}`: array
- `β::Real`: real, parameter of the β-divergence.
    If β == 2, this is half the Frobenius *squared* norm.
    If β == 1, this is the Kullback-Leibler divergence.
    If β == 0, this is the Itakura-Saito divergence.
    Else, this is the general β-divergence.
"""
function β_divergence(X::Matrix{T}, Y::Matrix{T}, β::Real; ϵ::Float64=eps(T)) where T <: Real
    if β == 2
        #### Frobenius norm
        res = norm(X - Y, 2) ^ 2 / 2.
    else
        # vec() flattens the array column-wise
        Y_vec = vec(Y)
        X_vec = vec(X)

        if β == 1
            # drop 0 coordinates in X that contribute 0 to the divergence as (x -> xlog(x) continuous in 0)
            indices = X_vec .> ϵ
            Y_vec = Y_vec[indices]
            X_vec = X_vec[indices]

            #### Kullback-Leibler divergence
            sum_X_log_X_Y = sum(X_vec .* log.(X_vec ./ Y_vec))
            sum_X         = sum(X_vec)
            sum_Y         = sum(Y_vec)
            res           = abs(sum_X_log_X_Y - sum_X + sum_Y)

        elseif β == 0
            sum(X_vec .== 0) == 0 || throw(ArgumentError("for β=0, β-divergence is undefined if X has null entries"))
            sum(Y_vec .== 0) == 0 || throw(ArgumentError("for β=0, β-divergence is undefined if Y has null entries"))

            #### Itakura-Saito divergence
            X_Y         = X_vec ./ Y_vec
            sum_log_X_Y = sum(log.(X_Y))
            sum_X_Y_m1  = sum(X_Y .- 1)
            res         = abs(-sum_log_X_Y + sum_X_Y_m1)

        else
            if β > 0 && β < 1
                sum(Y_vec .== 0) == 0 || throw(ArgumentError("for 0<β<1, β-divergence is undefined if Y has null entries"))
                # drop 0 coordinates in X that contribute 0 to the divergence as (x -> xlog(x) continuous in 0)
                indices = X_vec .> ϵ
                Y_vec = Y_vec[indices]
                X_vec = X_vec[indices]
            elseif β < 0
                sum(X_vec .== 0) == 0 || throw(ArgumentError("for β<0, β-divergence is undefined if X has null entries"))
                sum(Y_vec .== 0) == 0 || throw(ArgumentError("for β<0, β-divergence is undefined if Y has null entries"))
            end

            #### General β-divergence for β not in (0, 1, 2)
            sum_X_β      = sum(X_vec .^ β)
            sum_Y_β      = sum(Y_vec .^ β)
            sum_X_Y_β_m1 = sum(X_vec .* Y_vec .^ (β-1))
            res          = abs((sum_X_β + (β-1) * sum_Y_β - β * sum_X_Y_β_m1)/(β*(β-1)))
        end
    end
    res
end

"""
α_divergence(X, Y, α[, ϵ])

Compute the the α-divergence of X and Y, d_α(X||Y).

# Arguments
- `X::Matrix{<:Real}`: array
- `Y::Matrix{<:Real}`: array
- `α::Real`: float, parameter of the α-divergence.
    If α == 2, this is Pearsoni's Chi-squared distance
    If α == 1, this is (at the limit) the Kullback-Leibler divergence
    If α == 0, this is (at the limit) the dual Kullback-Leibler divergence
    If α == 0.5, this is the squared Hellinger distance
    If α == -1, this is the Neyman's Chi-squared distance
    Else, this is the general α-divergence.
"""
function α_divergence(X::Matrix{T}, Y::Matrix{T}, α::Real; ϵ::Float64=eps(T)) where T <: Real
    # vec() flattens the array column-wise
    Y_vec = vec(Y)
    X_vec = vec(X)

    if α == 1
        # avoid division by zero
        Y_vec[Y_vec .== 0] .= ϵ

        #### Kullback-Leibler divergence
        sum_X_log_X_Y = sum(X_vec .* log.(X_vec ./ Y_vec))
        sum_X         = sum(X_vec)
        sum_Y         = sum(Y_vec)
        res           = abs(sum_X_log_X_Y - sum_X + sum_Y)
    elseif α == 0
        # avoid division by zero
        X_vec[X_vec .== 0] .= ϵ

        #### dual Kullback-Leibler divergence
        sum_Y_log_Y_X = sum(Y_vec .* log.(Y_vec ./ X_vec))
        sum_Y         = sum(Y_vec)
        sum_X         = sum(X_vec)
        res           = abs(sum_Y_log_Y_X - sum_Y + sum_X)
    else
        if α < 1
            # avoid division by zero
            Y_vec[Y_vec .== 0] .= ϵ
        end

        if α < 0
            # avoid division by zero
            X_vec[X_vec .== 0] .= ϵ
        end

        #### general α-divergence for α not in {0,1}
        sum_X_α_Y_α_m1 = sum(X_vec .^ α .* Y_vec .^ (1-α))
        sum_X          = sum(X_vec)
        sum_Y          = sum(Y_vec)
        res            = abs((sum_X_α_Y_α_m1 - α * sum_X + (α-1) * sum_Y)/(α*(α-1)))
    end
    res
end


function newton(f, fp, x::Float64,tol=1e-14::Float64,maxsteps=100::Int64)
         ##f: the function of x
         ##fp: the derivative of f

	 local xnew, xold = x, Inf
	 local fn, fo = f(xnew), Inf
	 local counter = 1

	 while (counter < maxsteps) && (abs(xnew - xold) > tol) && ( abs(fn - fo) > tol )
	   x = xnew - f(xnew)/fp(xnew) ## update x
	   xnew, xold = x, xnew
           fn, fo = f(xnew), fn
	   counter += 1
	 end

	 if counter >= maxsteps
	    error("Did not converge in ", string(maxsteps), " steps")
         else
	   xnew, counter
         end
end


n = 8 # rand(2: 10)

# test Hessenberg

A = matrixdepot("rohess", n)

B = tril(A) - diagm(0 => diag(A)) - diagm(-1 => diag(A, -1))

@test B ≈ zeros(n,n) atol=1.0e-7

# test orithogonality

@test A'*A ≈ Matrix(1.0I, n, n) atol=1.0e-7

println("'rohess' passed test...")


#****************************************************************#
# VeysiADN 12 May 2021
# Advanced Robotics Homework 5 Codes
#****************************************************************#
using LinearAlgebra
const lAlgebra = LinearAlgebra
#****************************************************************#
#Computes exponential coordinate ‘so3mat’
#(skew symmetric matrix) of the rotation matrix R

function MatrixLog3(R)
    acosinput = (lAlgebra.tr(R) - 1) / 2
    if acosinput >= 1
        return zeros(3, 3)
    else
        theta = acos(acosinput)
        return 1 / 2 / sin(theta) * (R - R')
    end
end
#****************************************************************#
# Computes exponential coordinate ‘se3mat’
# (twist matrix) of the rigid body transformation matrix T
function MatrixLog6(T)
    if( size(T)!=(4,4) )
        println("!Warning! : Transformation matrix should be 4x4.")
        return
    end
    R = T[1:3,1:3]
    t = T[1:3,4]
    omg_h = MatrixLog3(R)
    w = [omg_h[3,2];omg_h[1,3];omg_h[2,1]]
    if omg_h == zeros(3, 3)
        return vcat(hcat(zeros(3, 3), T[1:3, 4]), [0 0 0 0])
    else
        theta = acos((lAlgebra.tr(R) - 1) / 2)
        return vcat(hcat(omg_h,inv((I-R)*omg_h + w*w'*theta)*t),
                          [0 0 0 0])
    end
end
#****************************************************************#


using NPZ
using Distributions
using LinearAlgebra

"""
    generate_gaussian_data(N::Int64, D::Int64, K::Int64,MixtureVar::Number)

Generate `N` observations, generated from `K` `D` dimensions Gaussians, with the Gaussian means sampled from a `Normal` distribution with mean `0` and `MixtureVar` variance.

Returns `(Samples, Labels, Clusters_means, Clusters_cov)`

# Example
```julia
julia> x,y,clusters = generate_gaussian_data(10000,2,6,100.0)
[3644, 2880, 119, 154, 33, 3170]
...
```
"""
function generate_gaussian_data(N::Int64, D::Int64, K::Int64, MixtureVar::Int64)
    x = randn(Float32, D, N)
    tpi = rand(Dirichlet(ones(K)*0.01))
    tzn = rand(Multinomial(N, tpi))
    tz = zeros(Float32, N)

    tmean = zeros(Float32, D, K)
    tcov = zeros(Float32, D, D, K)

    ind = 1
    println(tzn)
    for i = 1:length(tzn)
        indices = ind:ind+tzn[i]-1
        tz[indices] .= i
        tmean[:, i] .=
            rand(MvNormal(zeros(Float32, D), MixtureVar * Matrix{Float32}(I, D, D)))
        tcov[:, :, i] .= rand(InverseWishart(D + 2, Matrix{Float32}(I, D, D)))
        d = MvNormal(tmean[:, i], tcov[:, :, i])
        for j in indices
            x[:, j] = rand(d)
        end
        ind += tzn[i]
    end
    x, tz, tmean, tcov
end

"""
     generate_mnmm_data(N::Int64, D::Int64, K::Int64, trials::Int64)

Generate `N` observations, generated from `K` `D` features Multinomial vectors, with `trials` draws from each vector.

Returns `(Samples, Labels, Vectors)`

# Example
```julia
julia> generate_mnmm_data(10000, 10, 5, 100)
...
```
"""
function generate_mnmm_data(N::Int64, D::Int64, K::Int64, trials::Int64)
    clusters = zeros(Float64, D, K)
    x = zeros(Float32, D, N)
    labels = rand(1:K, (N,))
    for i = 1:K
        alphas = rand(1:20, (D,))
        alphas[i] = rand(30:100)
        clusters[:, i] = rand(Dirichlet(alphas))
    end
    for i = 1:N
        x[:, i] = rand(Multinomial(trials, clusters[:, labels[i]]))
    end
    return x, labels, clusters
end


export jacobi, jacobi_weight

"""
    jacobi_weight(α, β, x)

Compute the weighting function (1-x)^α * (1-x)^β .
"""
function jacobi_weight(α, β, x)
	return (1-x)^α * (1-x )^β
end

"""
    abc(n, α, β, x)

Compute the three coefficients in the recurrence relation for the Jacobi polynomial.

n is the order of the polynomial.

α,β are the two weighting parameters.

x is the argument or point at which the polynomial will be evaluated.
"""
function abc(n, α, β, x)
	# the parens emphasize the terms, not PEMDAS
	a = (2n) * (n + α + β) * (2n + α + β - 2)
	b1 = (2n + α + β -1)
	b2 = (2n + α + β)
	b2 = b2 * (b2 - 2)
	b = b1 * (b2 * x + α^2 - β^2)
	c = 2 * (n + α - 1) * (n + β - 1) * (2n + α + β)
	return a, b, c
end

"""
    jacobi(n, α, β, x)

Compute the Jacobi polynomial of order n and weights α,β at point x.

This function uses a recurrence relation and is numerical stable to very high
order.  The computation time is linear w.r.t. the order n.  jacobi.(n, a, b, x)
is also linear w.r.t. the size of argument x.
"""
function jacobi(n, α, β, x)
	if n == 0
		return 1.0
	elseif n == 1
		return (α + 1) + (α + β + 2) * ((x-1)/2)
	end
	# this uses a loop to avoid recursion
	# we init P of n-2, n-1, and n=2.
	# the latter is the first recursive term.
	# then loop from 3 up to n, updating
	# Pnm2, Pnm1, a, b, c, Pn
	Pnm2 = jacobi(0, α, β, x)
	Pnm1 = jacobi(1, α, β, x)
	a, b, c = abc(2, α, β, x)
	Pn = ((b * Pnm1) - (c * Pnm2)) / a
	if n == 2
		return Pn
	end
	for i = 3:n
		Pnm2 = Pnm1
		Pnm1 = Pn
		a, b, c = abc(n, α, β, x)
		Pn = ((b * Pnm1) - (c * Pnm2)) / a
	end
	return Pn
end


##
##  m i s c . j l
##

#-- Algebraic-geometric mean
function agm(a::Number, b::Number)
    local a0 = a, b0 = b
    local c  = max(abs(a), abs(b))
    if typeof(a) <: Real && a < 0; a0 = complex(a, 0); end
    if typeof(b) <: Real && b < 0; b0 = complex(b, 0); end

    while abs(b0-a0) >= eps(c)
        a0, b0 = (a0 + b0)/2.0, sqrt(a0 * b0)
    end
    return (a0 + b0) / 2.0
end

#-- Arc length of a curve defined through f:R --> R
function arc_length(f::Function, a::Real, b::Real;
                        nmax::Int=25, tol::Real=2.5e-15)
    local k::Int
    h = b - a;
    fa = f(a); fb = f(b)
    A = zeros(nmax, nmax)
    A[1, 1] = sqrt(sum((fb - fa)^2))
    for k = 1:(nmax-1)
        h /= 2
        x = linspace(a, b, 2^k + 1)
        y = map(f, x)
        X = [x y]
        dX = diff(X)
        A[k+1, 1] = sum(sqrt(sum(dX.^2, 2)))
        for l in 1:k
            A[k+1, l+1] = (4^l * A[k+1, l] - A[k, l]) / (4^l - 1)
        end
        if abs(A[k+1, k+1] - A[k, k]) < tol && k > 3
            break
        end
    end
    err = abs(A[k+1, k+1] - A[k, k])
    return A[k+1, k+1], k+1, err
end


"""
    w = ds_hann(n)

A Hann window of length `n`. Does not smear tones located exactly in a bin.
"""
function ds_hann(n)
    return 0.5 * (1 .- cos.(2*pi*(0:n-1)/n))
end


using DataFrames, Distributions, Random, LinearAlgebra, CSV, Plots; pyplot()
Random.seed!(0)

data = CSV.read("../data/L1L2data.csv")
xVals, yVals, n = data.X, data.Y, size(data)[1]

N = 10^6
alphaMin, alphaMax, betaMin, betaMax = 0, 5, 0, 5

alpha1, beta1, alpha2, beta2, bestL1Cost, bestL2Cost = 0.0,0.0,0.0,0.0,Inf,Inf
for _ in 1:N
    rAlpha,rBeta=rand(Uniform(alphaMin,alphaMax)),rand(Uniform(betaMin,betaMax))
    L1Cost = norm(rAlpha .+ rBeta*xVals - yVals,1)
    if L1Cost < bestL1Cost
        global alpha1 = rAlpha
        global beta1 = rBeta
        global bestL1Cost = L1Cost
    end
    L2Cost = norm(rAlpha .+ rBeta*xVals  - yVals)
    if L2Cost < bestL2Cost
        global alpha2 = rAlpha
        global beta2 = rBeta
        global bestL2Cost = L2Cost
    end
end

println("L1 line: $(round(alpha1,digits = 2)) + $(round(beta1,digits = 2))x")
println("L2 line: $(round(alpha2,digits = 2)) + $(round(beta2,digits = 2))x")

d = yVals - (alpha2 .+ beta2*xVals)
rectangle(x, y, d) = Shape(x .- [0,d,d,0,0], y .- [0,0,d,d,0])

p1 = scatter(xVals,yVals, c=:black, ms=5, label="")
p1 = plot!([0,10],[alpha1, alpha1 .+ beta1*10], c=:blue,label="L1 minimized")
for i in 1:n
    x,y = xVals[i],yVals[i]
    p1 = plot!([x, x], [y, alpha1 .+ beta1*x],color="black", label="")
end

p2 = scatter(xVals,yVals, c=:black, ms=5, label="")
p2 = plot!([0,10],[alpha2, alpha2 .+ beta2*10],c=:red,label="L2 minimized")
for i in 1:n
    x,y = xVals[i],yVals[i]
	p2 = plot!(rectangle(x,y,d[i]), fc=:gray, fa=0.5, label="")
end

p3 = scatter(xVals,yVals, c=:black, ms=5, label="")
p3 = plot!([0,10],[alpha1, alpha1 .+ beta1*10], c=:blue, label="L1 minimized")
p3 = plot!([0,10],[alpha2, alpha2 .+ beta2*10], c=:red, label="L2 minimized")

plot(p1, p2, p3, layout = (1,3),
	ratio=:equal, xlims=(0,10), ylims=(0,10),
	legend=:topleft, size=(1200, 400),
    	xlabel = "x", ylabel = "y")


using Plots; pyplot()
using DeSolver
using LaTeXStrings

function test(u,t)
    du=sin(t)^2*u
    return du
end

function testexact(x)
    # exact solution of test with the initial condition u=1
    return exp(1/2*(x - sin(x)*cos(x)))
end

function wave(u,t)
    du= u[2]
    ddu = -u[1]
    return [du, ddu]
end

soltest4=odesolve(test, 1., (0.,10.), 1, method="RK4")
soltest2=odesolve(test, 1., (0.,10.), 1, method="RK2")
soltest5=odesolve(test, 1., (0.,10.), 0.25, method="RK4")

solwave4=odesolve(wave, [1., 0.], (0.,10.), 1, method="RK4")
solwave2=odesolve(wave, [1., 0.], (0.,10.), 1, method="RK2")
solwave5=odesolve(wave, [1., 0.], (0.,10.), 0.25, method="RK4")

display(plot(map(x->x[1],soltest4.t),map(x->x[1],soltest4.u), label=L"u'=sin(t)^2u"*"  with RK4 stepsize 1"))
display(plot!(map(x->x[1],soltest2.t),map(x->x[1],soltest2.u), label=L"u'=sin(t)^2u"*"  with RK2 stepsize 1"))
display(plot!(map(x->x[1],soltest5.t),map(x->x[1],soltest5.u), label=L"u'=sin(t)^2u"*"  with RK4 stepsize .25"))
display(plot!(testexact, label="Exact Solution of  "*L"u'=sin(t)^2u"))

display(plot(map(x->x[1],solwave4.t),map(x->x[1],solwave4.u), label=L"u''=-u"*"  with RK4 stepsize 1"))
display(plot!(map(x->x[1],solwave2.t),map(x->x[1],solwave2.u), label=L"u''=-u"*"  with RK2 stepsize 1"))
display(plot!(map(x->x[1],solwave5.t),map(x->x[1],solwave5.u), label=L"u''=-u"*"  with RK4 stepsize .25"))
display(plot!(cos, label = "Exact solution of  "*L"u''=-u"))

# gui()
# plot(p1)
# plot!(p4)


using Distributions
using SpecialFunctions
using StatsBase
using DelimitedFiles

function higibbs(Y, T, nu0 = 1, s20 = 100.0, eta0 = 1.0, t20 = 100.0, mu0 = 50.0, g20 = 25.0)
    m = size(unique(Y[:,1]), 1)
    # starting value
    ybar = ones(m)
    sv = ones(m)
    n = ones(Int, m)
    for j = 1:m
        yj = Y[ [Y[i,1] == j for i = 1:end], 2]
        ybar[j] = mean(yj)
        sv[j] = var(yj)
        n[j] = size(yj, 1)
    end
    theta = copy(ybar)
    sigma2 = mean(sv)
    mu = mean(theta)
    tau2 = var(theta)

    THETA = ones(T, m)
    # sigma2 mu tau2
    SMT = ones(T, 3)

    for t = 1:T
        # sample theta
        for j = 1:m
            vartheta = 1 / (n[j] / sigma2 + 1 / tau2)
            meantheta = vartheta * ( n[j] * ybar[j] / sigma2 + mu / tau2)
            rnorm = Normal(meantheta, sqrt(vartheta))
            theta[j] = rand(rnorm, 1)[1]
        end

        # sample new sigma2
        nun = nu0 + sum(n)
        ss = nu0 * s20
        for j = 1:m
            ss += sum((Y[ [Y[i, 1] == j for i = 1:end], 2] .- theta[j]).^2)
        end
        rgamma = Gamma(nun/2, 2/ss)
        sigma2 = 1 / rand(rgamma, 1)[1]

        # sample mu
        varmu = 1 / (m / tau2 + 1 / g20)
        meanmu = varmu * (m * mean(theta) / tau2 + mu0 / g20)
        rnorm = Normal(meanmu, sqrt(varmu))
        mu = rand(rnorm, 1)[1]

        # sample 1/tau2
        shapetau = (eta0 + m) / 2
        ratetau = ( eta0 * t20 + sum((theta .- mu).^2) ) / 2
        rgamma = Gamma(shapetau, 1/ratetau)
        tau2 = 1 / rand(rgamma, 1)[1]

        # store results
        THETA[t, :] .= theta
        SMT[t, :] .= [sigma2, mu, tau2]
    end
    return THETA, SMT
end

# run
Y = readdlm("math-score-Y.csv")
THETA, SMT = higibbs(Y, 50);
#using PyPlot
#plt[:hist](SMT[:,2])
#show()


"""
    modular_exponentiation(base::Int64, exponent::Int64, modulus::Int64)

Compute the `residuum` of the base raised to the `exponent`, which is divided by the
`modulus`.

# Arguments
- `base::Int64`: base
- `exponent::Int64`: exponent
- `modulus ::Int64`: modulus

# Examples
```julia-repl
julia> import ClassicAlgorithmsCollections
julia> ClassicAlgorithmsCollections.modular_exponentiation(2, 3, 15)
8
```
"""
function modular_exponentiation(base::Int64, exponent::Int64, modulus::Int64)
    residuum = 1     # Initialize result

    # Update base if it is more
    # than or equal to modulus
    base = base % modulus

    if (base == 0)
        return 0
    end

    while (exponent > 0)

        # If exponent is odd, multiplexponent
        # base with result
        if ((exponent & 1) == 1)
            residuum = (residuum * base) % modulus
        end
        # exponent must be even now
        exponent = exponent >> 1      # exponent = exponent/2
        base = (base * base) % modulus
    end

    return residuum
end


module PiAnalysis

using Plots

# Function to compute pi using the Chudnovsky algorithm
#
# chud() takes the desired precision of BigFloat as input

export chud
function chud(prcsn::Int)

  # Set the precision of BigFloat using the input

  setprecision(BigFloat,prcsn)

  # Begin the summation in the algorithm

  pInvTemp = 0

  for i in 0:ceil(28*prcsn/1024)

    pInvTemp = pInvTemp + (-1)^(i)*factorial(BigInt(6*i))*BigInt(545140134*i+13591409)/((factorial(BigInt(3*i))*((factorial(BigInt(i)))^3)*(BigInt(640320)^BigFloat(3*i+(3/2)))))

  end

  # End the summation and multiply the result by 12

  pInv = BigFloat(pInvTemp*12)

  # Invert pInv to obtain pi

  p = BigFloat(1/pInv)

  return BigFloat(p)

end

# Function to test the accuracy of Julia's pi by comparing it to
# the result of the Chudnovsky algorithm
#
# piAccurate() takes the desired precision of BigFloat as input

export piAccurate
function piAccurate(prcsn::Int)

  # Set the precision of BigFloat using the input

  setprecision(BigFloat,prcsn)

  # Compute pi using Julia's value and chud() and return
  # the absolute value of the difference

  p1 = BigFloat(pi)
  p2 = chud(prcsn)
  diff = abs(p1-p2)

  return diff

end

# Function to find the number of recurrences of each digit of pi
#
# numDig() takes the number of the first and last digit in the
# desired interval, as well as the desired precision of BigFloat,
# as input

export numDig
function numDig(a::Int,b::Int,prcsn::Int)

  # Return errors if the input interval doesn't make any sense,
  # or if the precision of the desired interval is too small.

  if a>=b
    return error("The first input cannot be greater than or equal to the second input")
  end

  if b > prcsn/3.5
    return error("The precision must be higher for this interval (Try a precision that is at least 3.5 times the end bound)")
  end

  # Set the precision of BigFloat using the third input

  setprecision(BigFloat,prcsn)

  # Compute pi

  p = BigFloat(pi)

  # Convert pi into an array of digits

  temp = p*(10^BigFloat(b))
  dig = Base.digits(trunc(BigInt,temp))

  # Create an array to hold the numbers of recurrences the
  # first column contains the digit, and the second contains
  # the number of recurrences

  numDgts = zeros(Float64, 10, 2)

  for i in 1:10
    d = i-1
    numDgts[i,1] = d
  end

  # Count the recurrences

  for i in a:b

    num = dig[b+1-i]

    if num == 0
      numDgts[1,2] = numDgts[1,2] + 1
    elseif num == 1
      numDgts[2,2] = numDgts[2,2] + 1
    elseif num == 2
      numDgts[3,2] = numDgts[3,2] + 1
    elseif num == 3
      numDgts[4,2] = numDgts[4,2] + 1
    elseif num == 4
      numDgts[5,2] = numDgts[5,2] + 1
    elseif num == 5
      numDgts[6,2] = numDgts[6,2] + 1
    elseif num == 6
      numDgts[7,2] = numDgts[7,2] + 1
    elseif num == 7
      numDgts[8,2] = numDgts[8,2] + 1
    elseif num == 8
      numDgts[9,2] = numDgts[9,2] + 1
    elseif num == 9
      numDgts[10,2] = numDgts[10,2] + 1
    end
  end

# return the array of digits

  return(numDgts)

end

# Function to compare the number of recurrences in two different
# intervals
#
# Takes the takes the number of the first and last digit in both
# desired intervals, as well as the desired precision of BigFloat,
# as input. Returns an array with the digits in the first column
# and the number of recurrences in the second column.

export digCompare
function digCompare(a::Int,b::Int,c::Int,d::Int,prcsn::Int)

  # Return errors if the intervals are not equal or overlap

  if (b-a) != (d-c)
    return error("The intervals are not equal")
  end

  if c<=a
    return error("The intervals cannot overlap")
  end

  # Use numDig() to compute the recurrences in each interval

  dig1 = numDig(a,b,prcsn)
  dig2_temp = numDig(c,d,prcsn)

  # Subtract out the first column of the second array so
  # that the first column will remain when the arrays are
  # subtracted

  dig2 = dig2_temp-[0 0;1 0;2 0;3 0;4 0;5 0;6 0;7 0;8 0;9 0]

  # Return the result of subtracting the arrays

  return dig1-dig2

end

# Function to plot the recurrences as a pie chart
#
# Takes the number of the first and last digit in the
# desired interval, as well as the desired precision of BigFloat
# as input
#
# Uses Plots and pyplot()

export piPlot
function piPlot(a::Int,b::Int,prcsn::Int)

  pyplot()

  values = numDig(a,b,prcsn) # Compute the recurrences

  # Put the values and the labels into two arrays and plot

  x = ["0","1","2","3","4","5","6","7","8","9"]

  y = values[:,2]

  pie(x,y,title="Digits in pi from $a to $b",l=0.5)

end

end # module