### A Pluto.jl notebook ###
# v0.17.7

using Markdown
using InteractiveUtils

# ╔═╡ 64bba790-89ad-11ec-272d-af9bb791e63d
begin
	using Turing, MCMCChains
	using Distributions, StatsPlots, Random
end

# ╔═╡ dc1177eb-66ec-4b82-ad0d-5e76539faa24
md"""
### Gaussian Mixture Model

In this post we see an example of gaussian mixture model, which is a clustering model of unsupervised learning.
As stated, gaussian mixture model has several normal distributions. The aim of this model is to find optimal value of parameters(μ, Σ, π) that describe clusters.

Let's say we have n data and assumes K clusters.
- θ parameters
- Z latent variables(hidden variables)
- X data

What are the parameters here?
- θ = {μ(μ₁ . . . μₖ), Σ(Σ₁ . . . Σₖ), π(π₁ . . . πₖ)}
- μₖ is mean of kᵗʰ cluster
- Σₖ is covariance matrix of kᵗʰ cluster
- πₖ represent for probability of selecting kᵗʰ cluster

We assume that we have n data.
- {(X₁, Z₁) . . . (Xₙ, Zₙ)}
- Z can be interpreted as one-hot vector with only 1 in kᵗʰ position and 0 others.

"""

# ╔═╡ fc380f54-24c7-440a-9cfd-04d3a8ea3184
# Set a random seed.
Random.seed!(3)

# ╔═╡ 38643e87-ee2d-4aae-83f7-abc6199f54aa
# Construct 30 data points for each cluster.
N = 30

# ╔═╡ b7acb16e-b6d1-4e53-80c4-0819259a6130
# Parameters for each cluster, we assume that each cluster is Gaussian distributed in the example.
μs = [4.0, 1.0]

# ╔═╡ 24553bda-3ce4-4156-bf8a-0a1fe3df2afb
# Construct the data points.
x = mapreduce(c -> rand(MvNormal([μs[c], μs[c]], 1.), N), hcat, 1:2)

# ╔═╡ a0871b5d-02f4-4f16-9bcd-2e85264b0f41
gr()

# ╔═╡ b5f72bd8-97b7-435f-8940-950af86aed91
# Visualization.
scatter(x[1,:], x[2,:], legend = false, title = "Dataset", fmt="png")

# ╔═╡ 00f15e65-5133-4453-88af-c9479c8e3f9e
@model function GaussianMixtureModel(x)

    D, N = size(x)

    # Draw the parameters for cluster 1.
    μ1 ~ Normal()

    # Draw the parameters for cluster 2.
    μ2 ~ Normal()

    μ = [μ1, μ2]

    # draw the weights for the K clusters from a Dirichlet distribution.

    α = 1.0
	π ~ Dirichlet(D, α)

    # Draw assignments for each datum and generate it from a multivariate normal.
    k = Vector{Int}(undef, N)
    for i in 1:N
        k[i] ~ Categorical(π)
        x[:,i] ~ MvNormal([μ[k[i]], μ[k[i]]], 1.)
    end
    return k
end;

# ╔═╡ a45b70a7-acb0-48f1-8ae5-31c63992cbfa
gmm_model = GaussianMixtureModel(x);

# ╔═╡ 7fe105ae-7d5c-4dd8-8104-fdaa9a18ea25
gmm_sampler = Gibbs(PG(100, :k), HMC(0.05, 10, :μ1, :μ2))

# ╔═╡ c30df2ab-45c2-42c3-9e72-2c4759b9b640
tchain = sample(gmm_model, gmm_sampler, MCMCThreads(), 200, 3)

# ╔═╡ 9f18a980-5277-4419-912b-e261451427b0
summarystats(tchain)

# ╔═╡ c726de5c-e241-4fa5-984d-c4184a626e52
names(tchain)

# ╔═╡ 166d94ed-1e70-4ef6-8b78-f5b566216246
ids = findall(map(name -> occursin("μ", string(name)), names(tchain)))

# ╔═╡ 29c24b11-fad4-4a2f-afbe-9f6afaab82f1
p = plot(tchain[:, ids, :]; legend=true, labels=["Mu 1" "Mu 2"], colordim=:parameter)

# ╔═╡ 40214128-1ed7-4b37-b19e-78fafdebbb0b
tchain2 = tchain[:, :, 3];

# ╔═╡ 2c2ea945-795a-4e0a-bc16-c49fa15bee1c
# Helper function for plotting
function predict(x, y, π, μ)

    return Turing.logaddexp(
        log(π[1]) + logpdf(MvNormal([μ[1], μ[1]], 1.), [x, y]),
        log(π[2]) + logpdf(MvNormal([μ[2], μ[2]], 1.), [x, y])
    )
end

# ╔═╡ 60d2ae42-7e56-418e-88a9-2ad16e84555e
# plotting contour plot
begin
	contour(range(-2, stop = 8), range(-2, stop = 8),
	    (x, y) -> predict(x, y, [mean(tchain2[:"π[1]"]), mean(tchain2[:"π[2]"])], 	[mean(tchain2[:μ1]), mean(tchain2[:μ2])])
	)
	scatter!(x[1,:], x[2,:]; legend=false, title="Dataset")

end

# ╔═╡ 88c6f515-b4d9-4e85-9157-2fc1e81483a2
wireframe(range(-2, stop = 8), range(-2, stop = 8),
	    (x, y) -> predict(x, y, [mean(tchain2[:"π[1]"]), mean(tchain2[:"π[2]"])], 	[mean(tchain2[:μ1]), mean(tchain2[:μ2])]))

# ╔═╡ 63703e6a-7adb-43c3-82aa-34f5aa746017
mean(MCMCChains.group(tchain2, :k))

# ╔═╡ b81eb0e7-d3cd-49aa-ae14-b8436dc515a4
assignments = round.(mean(MCMCChains.group(tchain2, :k)).nt.mean)

# ╔═╡ 60b70f36-ffac-45c3-a3d4-78991ab57bab
scatter(x[1,:], x[2,:]; legend=false,
    title="Assignments on Dataset", zcolor=assignments)

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
Turing = "fce5fe82-541a-59a6-adf8-730c64b5f9a0"

[compat]
Distributions = "~0.25.47"
MCMCChains = "~5.0.3"
StatsPlots = "~0.14.33"
Turing = "~0.20.1"
"""

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

[[AbstractFFTs]]
deps = ["ChainRulesCore", "LinearAlgebra"]
git-tree-sha1 = "6f1d9bc1c08f9f4a8fa92e3ea3cb50153a1b40d4"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.1.0"

[[AbstractMCMC]]
deps = ["BangBang", "ConsoleProgressMonitor", "Distributed", "Logging", "LoggingExtras", "ProgressLogging", "Random", "StatsBase", "TerminalLoggers", "Transducers"]
git-tree-sha1 = "db0a7ff3fbd987055c43b4e12d2fa30aaae8749c"
uuid = "80f14c24-f653-4e6a-9b94-39d6b0f70001"
version = "3.2.1"

[[AbstractPPL]]
deps = ["AbstractMCMC", "DensityInterface", "Setfield"]
git-tree-sha1 = "ca54027a17ca3133b36166191b5faa8a404e92d3"
uuid = "7a57a42e-76ec-4ea3-a279-07e840d6d9cf"
version = "0.4.0"

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

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

[[AdvancedHMC]]
deps = ["AbstractMCMC", "ArgCheck", "DocStringExtensions", "InplaceOps", "LinearAlgebra", "ProgressMeter", "Random", "Requires", "Setfield", "Statistics", "StatsBase", "StatsFuns", "UnPack"]
git-tree-sha1 = "189473a73d664fe2496675775b6c8a732b8dfe26"
uuid = "0bf59076-c3b1-5ca4-86bd-e02cd72cde3d"
version = "0.3.3"

[[AdvancedMH]]
deps = ["AbstractMCMC", "Distributions", "Random", "Requires"]
git-tree-sha1 = "8ad8bfddf8bb627d689ecb91599c349cbf15e971"
uuid = "5b7e9947-ddc0-4b3f-9b55-0d8042f74170"
version = "0.6.6"

[[AdvancedPS]]
deps = ["AbstractMCMC", "Distributions", "Libtask", "Random", "StatsFuns"]
git-tree-sha1 = "59c47e9525d5a807a950d8b79b5d6e60b2f6de82"
uuid = "576499cb-2369-40b2-a588-c64705576edc"
version = "0.3.3"

[[AdvancedVI]]
deps = ["Bijectors", "Distributions", "DistributionsAD", "DocStringExtensions", "ForwardDiff", "LinearAlgebra", "ProgressMeter", "Random", "Requires", "StatsBase", "StatsFuns", "Tracker"]
git-tree-sha1 = "130d6b17a3a9d420d9a6b37412cae03ffd6a64ff"
uuid = "b5ca4192-6429-45e5-a2d9-87aec30a685c"
version = "0.1.3"

[[ArgCheck]]
git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4"
uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197"
version = "2.3.0"

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

[[Arpack]]
deps = ["Arpack_jll", "Libdl", "LinearAlgebra", "Logging"]
git-tree-sha1 = "91ca22c4b8437da89b030f08d71db55a379ce958"
uuid = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97"
version = "0.5.3"

[[Arpack_jll]]
deps = ["Libdl", "OpenBLAS_jll", "Pkg"]
git-tree-sha1 = "e214a9b9bd1b4e1b4f15b22c0994862b66af7ff7"
uuid = "68821587-b530-5797-8361-c406ea357684"
version = "3.5.0+3"

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

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

[[AxisAlgorithms]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"]
git-tree-sha1 = "66771c8d21c8ff5e3a93379480a2307ac36863f7"
uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950"
version = "1.0.1"

[[AxisArrays]]
deps = ["Dates", "IntervalSets", "IterTools", "RangeArrays"]
git-tree-sha1 = "d127d5e4d86c7680b20c35d40b503c74b9a39b5e"
uuid = "39de3d68-74b9-583c-8d2d-e117c070f3a9"
version = "0.4.4"

[[BangBang]]
deps = ["Compat", "ConstructionBase", "Future", "InitialValues", "LinearAlgebra", "Requires", "Setfield", "Tables", "ZygoteRules"]
git-tree-sha1 = "d648adb5e01b77358511fb95ea2e4d384109fac9"
uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
version = "0.3.35"

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

[[Baselet]]
git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e"
uuid = "9718e550-a3fa-408a-8086-8db961cd8217"
version = "0.1.1"

[[Bijectors]]
deps = ["ArgCheck", "ChainRulesCore", "Compat", "Distributions", "Functors", "IrrationalConstants", "LinearAlgebra", "LogExpFunctions", "MappedArrays", "Random", "Reexport", "Requires", "Roots", "SparseArrays", "Statistics"]
git-tree-sha1 = "369af32fcb9be65d496dc43ad0bb713705d4e859"
uuid = "76274a88-744f-5084-9051-94815aaf08c4"
version = "0.9.11"

[[Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+0"

[[Cairo]]
deps = ["Cairo_jll", "Colors", "Glib_jll", "Graphics", "Libdl", "Pango_jll"]
git-tree-sha1 = "d0b3f8b4ad16cb0a2988c6788646a5e6a17b6b1b"
uuid = "159f3aea-2a34-519c-b102-8c37f9878175"
version = "1.0.5"

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

[[ChainRules]]
deps = ["ChainRulesCore", "Compat", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "Statistics"]
git-tree-sha1 = "849d4cb467ea3ecbbd3efe68dacd36f9429b543c"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "1.26.0"

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

[[ChangesOfVariables]]
deps = ["ChainRulesCore", "LinearAlgebra", "Test"]
git-tree-sha1 = "bf98fa45a0a4cee295de98d4c1462be26345b9a1"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.2"

[[Clustering]]
deps = ["Distances", "LinearAlgebra", "NearestNeighbors", "Printf", "SparseArrays", "Statistics", "StatsBase"]
git-tree-sha1 = "75479b7df4167267d75294d14b58244695beb2ac"
uuid = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5"
version = "0.14.2"

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

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

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

[[CompositionsBase]]
git-tree-sha1 = "455419f7e328a1a2493cabc6428d79e951349769"
uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b"
version = "0.1.1"

[[ConsoleProgressMonitor]]
deps = ["Logging", "ProgressMeter"]
git-tree-sha1 = "3ab7b2136722890b9af903859afcf457fa3059e8"
uuid = "88cd18e8-d9cc-4ea6-8889-5259c0d15c8b"
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 = "249fe38abf76d48563e2f4556bebd215aa317e15"
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
version = "4.1.1"

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

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

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

[[DataValues]]
deps = ["DataValueInterfaces", "Dates"]
git-tree-sha1 = "d88a19299eba280a6d062e135a43f00323ae70bf"
uuid = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5"
version = "0.4.13"

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

[[DefineSingletons]]
git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c"
uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52"
version = "0.1.2"

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

[[DensityInterface]]
deps = ["InverseFunctions", "Test"]
git-tree-sha1 = "80c3e8639e3353e5d2912fb3a1916b8455e2494b"
uuid = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
version = "0.4.0"

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

[[DiffRules]]
deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "84083a5136b6abf426174a58325ffd159dd6d94f"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.9.1"

[[Distances]]
deps = ["LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "3258d0659f812acde79e8a74b11f17ac06d0ca04"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.7"

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

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

[[DistributionsAD]]
deps = ["Adapt", "ChainRules", "ChainRulesCore", "Compat", "DiffRules", "Distributions", "FillArrays", "LinearAlgebra", "NaNMath", "PDMats", "Random", "Requires", "SpecialFunctions", "StaticArrays", "StatsBase", "StatsFuns", "ZygoteRules"]
git-tree-sha1 = "61805bf57113a52435a13ca0bb588daf8848784d"
uuid = "ced4e74d-a319-5a8a-b0ac-84af2272839c"
version = "0.6.37"

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

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

[[DynamicPPL]]
deps = ["AbstractMCMC", "AbstractPPL", "BangBang", "Bijectors", "ChainRulesCore", "Distributions", "LinearAlgebra", "MacroTools", "Random", "Setfield", "Test", "ZygoteRules"]
git-tree-sha1 = "d732ba45e3c22fba99957fba7f4de25735a57691"
uuid = "366bfd00-2699-11ea-058f-f148b4cae6d8"
version = "0.17.4"

[[EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+0"

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

[[EllipticalSliceSampling]]
deps = ["AbstractMCMC", "ArrayInterface", "Distributions", "Random", "Statistics"]
git-tree-sha1 = "c25a7254cf745720ddf9051cd0d2792b3baaca0e"
uuid = "cad2338a-1db2-11e9-3401-43bc07c9ede2"
version = "0.4.6"

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

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

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

[[FFTW]]
deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"]
git-tree-sha1 = "463cb335fa22c4ebacfd1faba5fde14edb80d96c"
uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
version = "1.4.5"

[[FFTW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c6033cc3892d0ef5bb9cd29b7f2f0331ea5184ea"
uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a"
version = "3.3.10+0"

[[FileIO]]
deps = ["Pkg", "Requires", "UUIDs"]
git-tree-sha1 = "80ced645013a5dbdc52cf70329399c35ce007fae"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.13.0"

[[FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "deed294cde3de20ae0b2e0355a6c4e1c6a5ceffc"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "0.12.8"

[[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 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

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

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

[[FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.4+0"

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

[[Functors]]
git-tree-sha1 = "e4768c3b7f597d5a352afa09874d16e3c3f6ead2"
uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
version = "0.2.7"

[[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 = "51d2dfe8e590fbd74e7a842cf6d13d8a2f45dc01"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.6+0"

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

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

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

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

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

[[Graphics]]
deps = ["Colors", "LinearAlgebra", "NaNMath"]
git-tree-sha1 = "1c5a84319923bea76fa145d49e93aa4394c73fc2"
uuid = "a2bd30eb-e257-5431-a919-1863eab51364"
version = "1.1.1"

[[Graphite2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011"
uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472"
version = "1.3.14+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 = "0fa77022fe4b511826b39c894c90daf5fce3334a"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.17"

[[HarfBuzz_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"]
git-tree-sha1 = "129acf094d168394e80ee1dc4bc06ec835e510a3"
uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566"
version = "2.8.1+1"

[[IRTools]]
deps = ["InteractiveUtils", "MacroTools", "Test"]
git-tree-sha1 = "006127162a51f0effbdfaab5ac0c83f8eb7ea8f3"
uuid = "7869d1d1-7146-5819-86e3-90919afe41df"
version = "0.4.4"

[[IfElse]]
git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1"
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
version = "0.1.1"

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

[[InitialValues]]
git-tree-sha1 = "4da0f88e9a39111c2fa3add390ab15f3a44f3ca3"
uuid = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
version = "0.3.1"

[[InplaceOps]]
deps = ["LinearAlgebra", "Test"]
git-tree-sha1 = "50b41d59e7164ab6fda65e71049fee9d890731ff"
uuid = "505f98c9-085e-5b2c-8e89-488be7bf1f34"
version = "0.3.0"

[[IntelOpenMP_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d979e54b71da82f3a65b62553da4fc3d18c9004c"
uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0"
version = "2018.0.3+2"

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

[[Interpolations]]
deps = ["AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "Requires", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"]
git-tree-sha1 = "b15fc0a95c564ca2e0a7ae12c1f095ca848ceb31"
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
version = "0.13.5"

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

[[InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.2"

[[InvertedIndices]]
git-tree-sha1 = "bee5f1ef5bf65df56bdd2e40447590b272a5471f"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.1.0"

[[IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

[[IterTools]]
git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.4.0"

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

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

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

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

[[Juno]]
deps = ["Base64", "Logging", "Media", "Profile"]
git-tree-sha1 = "07cb43290a840908a771552911a6274bc6c072c7"
uuid = "e5e0dc1b-0480-54bc-9374-aad01c23163d"
version = "0.8.4"

[[KernelDensity]]
deps = ["Distributions", "DocStringExtensions", "FFTW", "Interpolations", "StatsBase"]
git-tree-sha1 = "591e8dc09ad18386189610acafb970032c519707"
uuid = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b"
version = "0.6.3"

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

[[LRUCache]]
git-tree-sha1 = "d64a0aff6691612ab9fb0117b0995270871c5dfc"
uuid = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637"
version = "1.3.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 = "f2355693d6778a178ade15952b7ac47a4ff97996"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.3.0"

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

[[LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"

[[LeftChildRightSiblingTrees]]
deps = ["AbstractTrees"]
git-tree-sha1 = "b864cb409e8e445688bc478ef87c0afe4f6d1f8d"
uuid = "1d6d02ad-be62-4b6b-8a6d-2f90e265016e"
version = "0.1.3"

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

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

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

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

[[Librsvg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pango_jll", "Pkg", "gdk_pixbuf_jll"]
git-tree-sha1 = "25d5e6b4eb3558613ace1c67d6a871420bfca527"
uuid = "925c91fb-5dd6-59dd-8e8c-345e74382d89"
version = "2.52.4+0"

[[Libtask]]
deps = ["IRTools", "LRUCache", "LinearAlgebra", "MacroTools", "Statistics"]
git-tree-sha1 = "8c8d83112829dc54e7db2d209a1f0d13c1e044a3"
uuid = "6f1fad26-d15e-5dc8-ae53-837a1d7b8c9f"
version = "0.6.7"

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

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

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

[[LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "e5718a00af0ab9756305a0392832c8952c7426c1"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.6"

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

[[LoggingExtras]]
deps = ["Dates", "Logging"]
git-tree-sha1 = "dfeda1c1130990428720de0024d4516b1902ce98"
uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36"
version = "0.4.7"

[[Luxor]]
deps = ["Base64", "Cairo", "Colors", "Dates", "FFMPEG", "FileIO", "Juno", "LaTeXStrings", "Random", "Requires", "Rsvg"]
git-tree-sha1 = "81a4fd2c618ba952feec85e4236f36c7a5660393"
uuid = "ae8d54c2-7ccd-5906-9d76-62fc9837b5bc"
version = "3.0.0"

[[MCMCChains]]
deps = ["AbstractMCMC", "AxisArrays", "Compat", "Dates", "Distributions", "Formatting", "IteratorInterfaceExtensions", "KernelDensity", "LinearAlgebra", "MCMCDiagnosticTools", "MLJModelInterface", "NaturalSort", "OrderedCollections", "PrettyTables", "Random", "RecipesBase", "Serialization", "Statistics", "StatsBase", "StatsFuns", "TableTraits", "Tables"]
git-tree-sha1 = "ddafbd2a95114d13721f2b6ddeeaee9529d6bc2b"
uuid = "c7f686f2-ff18-58e9-bc7b-31028e88f75d"
version = "5.0.3"

[[MCMCDiagnosticTools]]
deps = ["AbstractFFTs", "DataAPI", "Distributions", "LinearAlgebra", "MLJModelInterface", "Random", "SpecialFunctions", "Statistics", "StatsBase", "Tables"]
git-tree-sha1 = "058d08594e91ba1d98dcc3669f9421a76824aa95"
uuid = "be115224-59cd-429b-ad48-344e309966f0"
version = "0.1.3"

[[MKL_jll]]
deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "5455aef09b40e5020e1520f551fa3135040d4ed0"
uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7"
version = "2021.1.1+2"

[[MLJModelInterface]]
deps = ["Random", "ScientificTypesBase", "StatisticalTraits"]
git-tree-sha1 = "8da86dcf5a9ea48413c7e920a990f0ea1869f9cb"
uuid = "e80e1ace-859a-464e-9ed9-23947d8ae3ea"
version = "1.3.6"

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

[[MappedArrays]]
git-tree-sha1 = "e8b359ef06ec72e8c030463fe02efe5527ee5142"
uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
version = "0.4.1"

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

[[Media]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "75a54abd10709c01f1b86b84ec225d26e840ed58"
uuid = "e89f7d12-3494-54d1-8411-f7d8b9ae1f27"
version = "0.5.0"

[[MicroCollections]]
deps = ["BangBang", "InitialValues", "Setfield"]
git-tree-sha1 = "6bb7786e4f24d44b4e29df03c69add1b63d88f01"
uuid = "128add7d-3638-4c79-886c-908ea0c25c34"
version = "0.1.2"

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

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

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

[[MultivariateStats]]
deps = ["Arpack", "LinearAlgebra", "SparseArrays", "Statistics", "StatsBase"]
git-tree-sha1 = "6d019f5a0465522bbfdd68ecfad7f86b535d6935"
uuid = "6f286f6a-111f-5878-ab1e-185364afe411"
version = "0.9.0"

[[NNlib]]
deps = ["Adapt", "ChainRulesCore", "Compat", "LinearAlgebra", "Pkg", "Requires", "Statistics"]
git-tree-sha1 = "c131644e2d7874361b5399a19e79387d90d28fea"
uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
version = "0.8.1"

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

[[NamedArrays]]
deps = ["Combinatorics", "DataStructures", "DelimitedFiles", "InvertedIndices", "LinearAlgebra", "Random", "Requires", "SparseArrays", "Statistics"]
git-tree-sha1 = "2fd5787125d1a93fbe30961bd841707b8a80d75b"
uuid = "86f7a689-2022-50b4-a561-43c23ac3c673"
version = "0.9.6"

[[NaturalSort]]
git-tree-sha1 = "eda490d06b9f7c00752ee81cfa451efe55521e21"
uuid = "c020b1a1-e9b0-503a-9c33-f039bfc54a85"
version = "1.0.0"

[[NearestNeighbors]]
deps = ["Distances", "StaticArrays"]
git-tree-sha1 = "16baacfdc8758bc374882566c9187e785e85c2f0"
uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce"
version = "0.4.9"

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

[[Observables]]
git-tree-sha1 = "fe29afdef3d0c4a8286128d4e45cc50621b1e43d"
uuid = "510215fc-4207-5dde-b226-833fc4488ee2"
version = "0.4.0"

[[OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "043017e0bdeff61cfbb7afeb558ab29536bbb5ed"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.8"

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

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

[[OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"

[[OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "648107615c15d4e09f7eca16307bc821c1f718d8"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.13+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"

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

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

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

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

[[Pango_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "FriBidi_jll", "Glib_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3a121dfbba67c94a5bec9dde613c3d0cbcf3a12b"
uuid = "36c8627f-9965-5494-a995-c6b170f724f3"
version = "1.50.3+0"

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

[[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 = "6f1b25e8ea06279b5689263cc538f51331d7ca17"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.1.3"

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

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

[[PrettyTables]]
deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"]
git-tree-sha1 = "dfb54c4e414caa595a1f2ed759b160f5a3ddcba5"
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
version = "1.3.1"

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

[[Profile]]
deps = ["Printf"]
uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79"

[[ProgressLogging]]
deps = ["Logging", "SHA", "UUIDs"]
git-tree-sha1 = "80d919dee55b9c50e8d9e2da5eeafff3fe58b539"
uuid = "33c8b6b6-d38a-422a-b730-caa89a2f386c"
version = "0.1.4"

[[ProgressMeter]]
deps = ["Distributed", "Printf"]
git-tree-sha1 = "afadeba63d90ff223a6a48d2009434ecee2ec9e8"
uuid = "92933f4c-e287-5a05-a399-4b506db050ca"
version = "1.7.1"

[[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 = "78aadffb3efd2155af139781b8a8df1ef279ea39"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.4.2"

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

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

[[RangeArrays]]
git-tree-sha1 = "b9039e93773ddcfc828f12aadf7115b4b4d225f5"
uuid = "b3c3ace0-ae52-54e7-9d0b-2c1406fd6b9d"
version = "0.3.2"

[[Ratios]]
deps = ["Requires"]
git-tree-sha1 = "01d341f502250e81f6fec0afe662aa861392a3aa"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.2"

[[RealDot]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9"
uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9"
version = "0.1.0"

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

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

[[RecursiveArrayTools]]
deps = ["Adapt", "ArrayInterface", "ChainRulesCore", "DocStringExtensions", "FillArrays", "LinearAlgebra", "RecipesBase", "Requires", "StaticArrays", "Statistics", "ZygoteRules"]
git-tree-sha1 = "5144e1eafb2ecc75765888a4bdcd3a30a6a08b14"
uuid = "731186ca-8d62-57ce-b412-fbd966d074cd"
version = "2.24.1"

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

[[RelocatableFolders]]
deps = ["SHA", "Scratch"]
git-tree-sha1 = "cdbd3b1338c72ce29d9584fdbe9e9b70eeb5adca"
uuid = "05181044-ff0b-4ac5-8273-598c1e38db00"
version = "0.1.3"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.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"

[[Roots]]
deps = ["CommonSolve", "Printf", "Setfield"]
git-tree-sha1 = "0abe7fc220977da88ad86d339335a4517944fea2"
uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
version = "1.3.14"

[[Rsvg]]
deps = ["Cairo", "Glib_jll", "Librsvg_jll"]
git-tree-sha1 = "3d3dc66eb46568fb3a5259034bfc752a0eb0c686"
uuid = "c4c386cf-5103-5370-be45-f3a111cca3b8"
version = "1.0.0"

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

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

[[ScientificTypesBase]]
git-tree-sha1 = "a8e18eb383b5ecf1b5e6fc237eb39255044fd92b"
uuid = "30f210dd-8aff-4c5f-94ba-8e64358c1161"
version = "3.0.0"

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

[[SentinelArrays]]
deps = ["Dates", "Random"]
git-tree-sha1 = "15dfe6b103c2a993be24404124b8791a09460983"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.3.11"

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

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

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

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

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

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

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

[[SpecialFunctions]]
deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "8d0c8e3d0ff211d9ff4a0c2307d876c99d10bdf1"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.1.2"

[[SplittablesBase]]
deps = ["Setfield", "Test"]
git-tree-sha1 = "39c9f91521de844bad65049efd4f9223e7ed43f9"
uuid = "171d559e-b47b-412a-8079-5efa626c420e"
version = "0.1.14"

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

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

[[StatisticalTraits]]
deps = ["ScientificTypesBase"]
git-tree-sha1 = "271a7fea12d319f23d55b785c51f6876aadb9ac0"
uuid = "64bff920-2084-43da-a3e6-9bb72801c0c9"
version = "3.0.0"

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

[[StatsAPI]]
git-tree-sha1 = "d88665adc9bcf45903013af0982e2fd05ae3d0a6"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.2.0"

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

[[StatsFuns]]
deps = ["ChainRulesCore", "InverseFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "f35e1879a71cca95f4826a14cdbf0b9e253ed918"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "0.9.15"

[[StatsPlots]]
deps = ["AbstractFFTs", "Clustering", "DataStructures", "DataValues", "Distributions", "Interpolations", "KernelDensity", "LinearAlgebra", "MultivariateStats", "Observables", "Plots", "RecipesBase", "RecipesPipeline", "Reexport", "StatsBase", "TableOperations", "Tables", "Widgets"]
git-tree-sha1 = "4d9c69d65f1b270ad092de0abe13e859b8c55cad"
uuid = "f3b207a7-027a-5e70-b257-86293d7955fd"
version = "0.14.33"

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

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

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

[[TableOperations]]
deps = ["SentinelArrays", "Tables", "Test"]
git-tree-sha1 = "e383c87cf2a1dc41fa30c093b2a19877c83e1bc1"
uuid = "ab02a1b2-a7df-11e8-156e-fb1833f50b87"
version = "1.2.0"

[[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 = "bb1064c9a84c52e277f1096cf41434b675cd368b"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.6.1"

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

[[TerminalLoggers]]
deps = ["LeftChildRightSiblingTrees", "Logging", "Markdown", "Printf", "ProgressLogging", "UUIDs"]
git-tree-sha1 = "62846a48a6cd70e63aa29944b8c4ef704360d72f"
uuid = "5d786b92-1e48-4d6f-9151-6b4477ca9bed"
version = "0.1.5"

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

[[Tracker]]
deps = ["Adapt", "DiffRules", "ForwardDiff", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NNlib", "NaNMath", "Printf", "Random", "Requires", "SpecialFunctions", "Statistics"]
git-tree-sha1 = "7b00adbe4216b919d487d82a852c48f378c6ed37"
uuid = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
version = "0.2.18"

[[Transducers]]
deps = ["Adapt", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "Setfield", "SplittablesBase", "Tables"]
git-tree-sha1 = "1cda71cc967e3ef78aa2593319f6c7379376f752"
uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999"
version = "0.4.72"

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

[[Turing]]
deps = ["AbstractMCMC", "AdvancedHMC", "AdvancedMH", "AdvancedPS", "AdvancedVI", "BangBang", "Bijectors", "DataStructures", "Distributions", "DistributionsAD", "DocStringExtensions", "DynamicPPL", "EllipticalSliceSampling", "ForwardDiff", "Libtask", "LinearAlgebra", "MCMCChains", "NamedArrays", "Printf", "Random", "Reexport", "Requires", "SciMLBase", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns", "Tracker", "ZygoteRules"]
git-tree-sha1 = "ce8198b3ac6bfa709f7c066ee0db13be52b2cbf8"
uuid = "fce5fe82-541a-59a6-adf8-730c64b5f9a0"
version = "0.20.1"

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

[[UnicodeFun]]
deps = ["REPL"]
git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf"
uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1"
version = "0.4.1"

[[Unzip]]
git-tree-sha1 = "34db80951901073501137bdbc3d5a8e7bbd06670"
uuid = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d"
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"]
git-tree-sha1 = "66d72dc6fcc86352f01676e8f0f698562e60510f"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.23.0+0"

[[Widgets]]
deps = ["Colors", "Dates", "Observables", "OrderedCollections"]
git-tree-sha1 = "505c31f585405fc375d99d02588f6ceaba791241"
uuid = "cc8bc4a8-27d6-5769-a93b-9d913e69aa62"
version = "0.6.5"

[[WoodburyMatrices]]
deps = ["LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "de67fa59e33ad156a590055375a30b23c40299d3"
uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6"
version = "0.5.5"

[[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 = "e45044cd873ded54b6a5bac0eb5c971392cf1927"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.2+0"

[[ZygoteRules]]
deps = ["MacroTools"]
git-tree-sha1 = "8c1a8e4dfacb1fd631745552c8db35d0deb09ea0"
uuid = "700de1a5-db45-46bc-99cf-38207098b444"
version = "0.2.2"

[[gdk_pixbuf_jll]]
deps = ["Artifacts", "Glib_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg", "Xorg_libX11_jll", "libpng_jll"]
git-tree-sha1 = "c23323cd30d60941f8c68419a70905d9bdd92808"
uuid = "da03df04-f53b-5353-a52f-6a8b0620ced0"
version = "2.42.6+1"

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

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

[[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 = "b910cb81ef3fe6e78bf6acee440bda86fd6ae00c"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+1"

[[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 = "4fea590b89e6ec504593146bf8b988b2c00922b2"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2021.5.5+0"

[[x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.5.0+0"

[[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:
# ╟─dc1177eb-66ec-4b82-ad0d-5e76539faa24
# ╟─64bba790-89ad-11ec-272d-af9bb791e63d
# ╠═fc380f54-24c7-440a-9cfd-04d3a8ea3184
# ╠═38643e87-ee2d-4aae-83f7-abc6199f54aa
# ╠═b7acb16e-b6d1-4e53-80c4-0819259a6130
# ╠═24553bda-3ce4-4156-bf8a-0a1fe3df2afb
# ╟─a0871b5d-02f4-4f16-9bcd-2e85264b0f41
# ╠═b5f72bd8-97b7-435f-8940-950af86aed91
# ╠═00f15e65-5133-4453-88af-c9479c8e3f9e
# ╠═a45b70a7-acb0-48f1-8ae5-31c63992cbfa
# ╠═7fe105ae-7d5c-4dd8-8104-fdaa9a18ea25
# ╠═c30df2ab-45c2-42c3-9e72-2c4759b9b640
# ╠═9f18a980-5277-4419-912b-e261451427b0
# ╠═c726de5c-e241-4fa5-984d-c4184a626e52
# ╠═166d94ed-1e70-4ef6-8b78-f5b566216246
# ╠═29c24b11-fad4-4a2f-afbe-9f6afaab82f1
# ╠═40214128-1ed7-4b37-b19e-78fafdebbb0b
# ╠═2c2ea945-795a-4e0a-bc16-c49fa15bee1c
# ╠═60d2ae42-7e56-418e-88a9-2ad16e84555e
# ╠═88c6f515-b4d9-4e85-9157-2fc1e81483a2
# ╠═63703e6a-7adb-43c3-82aa-34f5aa746017
# ╠═b81eb0e7-d3cd-49aa-ae14-b8436dc515a4
# ╠═60b70f36-ffac-45c3-a3d4-78991ab57bab
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


function triangular_solve_upper_rowwise(U, b)

    n_row = size(U, 1)
    x = zeros(eltype(b), n_row)

    @inbounds for ii = n_row:-1:1
        internal_sum = zero(eltype(b))
        @inbounds @simd for jj = n_row:-1:(ii+1)
            @fastmath internal_sum += U[ii, jj] * x[jj]
        end
        @fastmath x[ii] = (b[ii] - internal_sum) / U[ii, ii]
    end

    return x
end

function triangular_solve_upper_colwise(U, b)
# function triangular_solve_upper_colwise(U{T}, b::Array{T}) where {T}

    n_col = size(U, 2)
    x = copy(b)

    @inbounds for jj = n_col:-1:1
        @fastmath x[jj] = x[jj] / U[jj, jj]
        # @view( x[1:(jj-1)] ) = @view( x[1:(jj-1)] ) - @view( U[1:(jj-1), jj] ) .* x[jj]
        @inbounds @simd for ii = 1:(jj-1)
            @fastmath x[ii] -= U[ii, jj] .* x[jj]
        end
    end

    return x
end

function triangular_solve_upper_colwise_transposed(L, b)
    # the input matrix L is a lower triangular matrix
    # but it solved as it was U = L', L' * x = b

    #=
    n_row = size(L, 1)
    x = zeros(eltype(b), n_row)

    @inbounds for ii = n_row:-1:1
        internal_sum = zero(eltype(b))
        @inbounds @simd for jj = n_row:-1:(ii+1)
            @fastmath internal_sum += L[jj, ii] * x[jj]
        end
        @inbounds @fastmath x[ii] = (b[ii] - internal_sum) / L[ii, ii]
    end

    return x
    =#
    return triangular_solve_upper_colwise(L', b)
end

function triangular_solve_lower_rowwise(L, b)
# function triangular_solve_lower_rowwise(L{T}, b::Array{T}) where {T}

    n_row = size(L, 1)
    x = zeros(eltype(b), n_row)

    for ii = 1:n_row
        internal_sum = zero(eltype(b))
        @inbounds @simd for jj = 1:(ii-1)
            @fastmath internal_sum += L[ii, jj] * x[jj]
        end
        @fastmath x[ii] = (b[ii] - internal_sum) / L[ii, ii];
    end

    return x
end

function triangular_solve_lower_colwise(L, b)
# function triangular_solve_lower_colwise(L{T}, b::Array{T}) where {T}

    (n_row, n_col) = size(L)
    x = copy(b)

    # Single threaded
    @inbounds for jj = 1:n_col
        @fastmath x[jj] = x[jj] / L[jj, jj]
        @inbounds @simd for rr = (jj+1):n_row
            @fastmath x[rr] -= L[rr, jj] .* x[jj]
        end
    end

    return x
end

function triangular_solve_lower_sparse(spmat::SparseMatrixCSC, b)
    # forward substitution

    n_row = spmat.n_row
    n_col = spmat.n_col

    x = copy(b)
    L11 = spmat[1] # 1,1 location
    x[1] = x[1] / L11

    L::Int = length(spmat)
    idx_end::Int = 0

    for cc = 1:spmat.n_col

        idx_start = spmat.col_begins_index[cc]
        if idx_start == 0
            error("Singular matrix cannot be solved")
        end

        # find next nonzero index
        idx_end = find_next_nonempty_col_begin(spmat, cc)

        for rr = idx_start:(idx_end-1)
            a_ij = spmat.data[rr]
            ii = spmat.row_index[rr]
            x[ii] /= a_ij
        end

    end

    return x
end


export tukey
"""
    tukey(N::Int, r::AbstractArray) -> AbstractArray

Tukey window is a rectangular window with the first and
last r/2 percent of the samples equal to parts of a cosine.
"""
function tukey(N::Int, r::AbstractFloat=0.5)
    n = (0:N-1)/(N-1)
    w = zeros(N)
    for i = 1:N
        x = n[i]
        if 0 <= x <= r/2
            w[i] = 0.5 + 0.5*cos(2*pi/r*(x-r/2))
        elseif r/2 <= x <= 1-r/2
            w[i] = 1.0
        else
            w[i] = 0.5 + 0.5*cos(2*pi/r*(x-1+r/2))
        end
    end
    return w
end

export gauss
"""
    gauss(N::Int, a::AbstractFloat=0.5)

a is proportional to the standard deviation
"""
function gauss(N::Int, a::AbstractFloat=0.4)
    n = 0:N-1
    m = (N-1)/2
    return @. exp(-((n - m)/m/a)^2/2)
end


"""
	meanconfid(x;sigma)
Compute the mean with confidence interval assuming normal
distribution (or large sample size => central limit theorem)

**Input**
* x: vector of samples (NaNs will be removed)
* sigma: optional input in case sigma (standard deviation, not variance) is known
* alpha: (1-alpha) gives the conficende interval for x_mean

**Output**
* x_mean: estimated mean
* x_confid: tuple with (lower,upper) confidence bounds defined by alpha

**Example**
```
# known standard deviation
x = [2.,3.,5.,6.,9.]
x_mean,x_confid = meanconfid(x,sigma=2.5)

# including NaN and Unknown sigma
push!(x,NaN);
x_mean,x_confid = meanconfid(x)
```
"""
function meanconfid(x::Vector{Float64};alpha::Float64=0.05,sigma::Float64=NaN)
	x_use = HypoTest.prepdata(x);
	x_mean = Distributions.mean(x_use);
	s = isnan(sigma) ? Distributions.std(x_use) : sigma;
	if isnan(sigma) && length(x_use) < 100
		d = Distributions.TDist(length(x_use)-1);
	else
		d =  Distributions.Normal();
	end
	q = Distributions.quantile(d,1-alpha/2);
	return x_mean,(x_mean-q*s/sqrt(length(x_use)),x_mean+q*s/sqrt(length(x_use)))
end

"""
	stdconfid(x;x_mean)
Compute the standard deviation with confidence interval assuming normal
distribution

**Input**
* x: vector of samples (NaNs will be removed)
* x_mean: optional input in case true mean is known (=>n instead n-1)
* alpha: (1-alpha) gives the conficende interval for sigma

**Output**
* sigma: estimated standard deviation (not variance)
* x_confid: tuple with (lower,upper) confidence bounds defined by alpha

**Example**
```
x = [1.95,1.96,1.98,1.99,2.00,2.00,2.01,2.01,2.01,2.01,
	2.02,2.02,2.03,2.03,2.04,2.04,2.05,2.06,2.08,2.10];
# unknown mean value
s,s_interval = stdconfid(x,alpha=0.05)

# known mean
x = [19.01,19.02,18.99,19.00,19.05,19.05,19.0,18.98,18.99,19.0];
s,s_interval = stdconfid(x,alpha=0.05,x_mean=19.)
```
"""
function stdconfid(x::Vector{Float64};alpha::Float64=0.05,x_mean::Float64=NaN)
	x_use = HypoTest.prepdata(x);
	sigma = Distributions.std(x_use, mean = isnan(x_mean) ? nothing : x_mean,
								corrected = isnan(x_mean) ? true : false);
	k = isnan(x_mean) ? length(x_use)-1 : length(x_use);
	d = Distributions.Chisq(k);
	qlow,qhigh = Distributions.quantile(d,1-alpha/2),Distributions.quantile(d,alpha/2);
	return sigma,(sqrt(k*sigma^2/qlow), sqrt(k*sigma^2/qhigh))
end


using FrankWolfe
using LinearAlgebra
using LaTeXStrings
using Plots

# # FrankWolfe for scaled, shifted ``\ell^1`` and ``\ell^{\infty}`` norm balls

# In this example, we run the vanilla FrankWolfe algorithm on a scaled and shifted ``\ell^1`` and ``\ell^{\infty}`` norm ball, using the `ScaledBoundL1NormBall`
# and `ScaledBoundLInfNormBall` LMOs. We shift both onto the point ``(1,0)`` and then scale them by a factor of ``2`` along the x-axis. We project the point ``(2,1)`` onto the polytopes.

n = 2

k = 1000

xp = [2.0,1.0]

f(x) = norm(x-xp)^2

function grad!(storage,x)
    @. storage = 2 * (x - xp)
    return nothing
end

lower = [-1.0,-1.0]
upper = [3.0,1.0]

l1 = FrankWolfe.ScaledBoundL1NormBall(lower, upper)

linf = FrankWolfe.ScaledBoundLInfNormBall(lower, upper)

x1 = FrankWolfe.compute_extreme_point(l1, zeros(n))
gradient = collect(x1)

x_l1, v_1, primal_1, dual_gap_1, trajectory_1 = FrankWolfe.frank_wolfe(
    f,
    grad!,
    l1,
    collect(copy(x1)),
    max_iteration=k,
    line_search=FrankWolfe.Shortstep(),
    L=2,
    print_iter=50,
    emphasis=FrankWolfe.memory,
    verbose=true,
    trajectory=true,
);

println("\nFinal solution: ", x_l1)

x2 = FrankWolfe.compute_extreme_point(linf, zeros(n))
gradient = collect(x2)

x_linf, v_2, primal_2, dual_gap_2, trajectory_2 = FrankWolfe.frank_wolfe(
    f,
    grad!,
    linf,
    collect(copy(x2)),
    max_iteration=k,
    line_search=FrankWolfe.Shortstep(),
    L=2,
    print_iter=50,
    emphasis=FrankWolfe.memory,
    verbose=true,
    trajectory=true,
);

println("\nFinal solution: ", x_linf)

# We plot the polytopes alongside the solutions from above:

xcoord1 = [1,3,1,-1,1]
ycoord1 = [-1,0,1,0,-1]

xcoord2 = [3,3,-1,-1,3]
ycoord2 = [-1,1,1,-1,-1]

plot(xcoord1, ycoord1, title = "Visualization of scaled shifted norm balls", lw = 2, label = L"\ell^1 \textrm{ norm}")
plot!(xcoord2, ycoord2, lw = 2, label = L"\ell^{\infty} \textrm{ norm}")
plot!([x_l1[1]], [x_l1[2]], seriestype = :scatter, lw = 5, color = "blue", label = L"\ell^1 \textrm{ solution}")
plot!([x_linf[1]], [x_linf[2]], seriestype = :scatter, lw = 5, color = "orange", label = L"\ell^{\infty} \textrm{ solution}", legend = :bottomleft)


# Word Problems Logical Reasoning Tests
# http://www.graduatewings.co.uk/word-problems-logical-tests
using AbstractLogic

# Question 1
# Sam is shorter than Hannah. William is shorter than Michael who is shorter than
# Hannah. Hannah and William are shorter than Fiona. Who is the tallest?
logicset = logicalparse(["Sam, Hannah, William, Michael, Fiona ∈ 1:5"])
logicset = logicalparse(["Sam < Hannah; William < Michael; Michael < Hannah"], logicset)
logicset = logicalparse(["Hannah < Fiona; William < Fiona"], logicset)

# A) Sam    B) Hannah    C) William    D) Fiona    E) Cannot Say
search("{{i}} > {{!i}}", logicset)
# :Fiona is a match with 13 feasible combinations out of 13.
# Therefore we choose D) Fiona

# Question 2
# Ben is taller than Sharon who is taller than Ralph. Ben is also taller than Mike.
logicset = logicalparse(["Ben, Sharon, Ralph, Mike ∈ 1:4"])
logicset = logicalparse(["Ben > Sharon; Sharon > Ralph; Ben > Mike"], logicset)

# Who is the shortest?
# A) Ben    B) Sharon    C) Ralph    D) Mike    E) Cannot Say
search("{{i}} < {{!i}}", logicset)
# :Ralph is a possible match with 6 feasible combinations out of 11.
# :Mike is a possible match with 1 feasible combinations out of 11.
# Therefore we choose E) Cannot Say


module problem116

description = """
Red, green or blue tiles
A row of five black square tiles is to have a number of its tiles replaced with coloured oblong tiles chosen from red (length two), green (length three), or blue (length four).
If red tiles are chosen there are exactly seven ways this can be done.
If green tiles are chosen there are three ways.
And if blue tiles are chosen there are two ways.
Assuming that colours cannot be mixed there are 7 + 3 + 2 = 12 ways of replacing the black tiles in a row measuring five units in length.

How many different ways can the black tiles in a row measuring fifty units in length be replaced if colours cannot be mixed and at least one coloured tile must be used?
"""

# Fill function, based on problems 114, 115
function F(m::Integer, n :: Integer, memo = zeros(Int, n))
  # Base case: no space remaining in the row
  if n < m return 0 end

  # Recursive case, count 1 for each placement of block at positions 1:n-m+1, and all ways of
  # filling the remaining space at the end of the row after each placement, memoizing results.
  if memo[n] == 0
    total = 0
    for blockpos = 1:(n-m+1)
      total += 1 + F(m, n - blockpos - m + 1, memo)
    end
    memo[n] = total
  end
  return memo[n]
end

# total ways to fill a row with only red,blue or green tiles.
function homogenous_replacements(n :: Integer)
  return F(2, n) + F(3, n) + F(4, n)
end

using Base.Test

@test F(2, 5) == 7
@test F(3, 5) == 3
@test F(4, 5) == 2
@test homogenous_replacements(5) == (7+3+2)

end


#solve eq x=cos(x)
function main()
    x=0.0
    xnext = cos(x)
    iter=0
    eps=1e-7
    iteration=1000000
    is_convergence=false

    for n in 1:iteration
        xnext = cos(x)
        if(abs(xnext-x)<eps)
            is_convergence=true
            iter=n
            break
        end
        x=xnext
    end

    if is_convergence
        println("X=",xnext,", iter=",iter)
        println("X-cos(X)=",xnext-cos(xnext))
    else
        print("No Convergence")
    end
end

main()


using Plots;gr()

T = 1000
dt = 0.001
y_0 = 1

# オイラー法
function euler_method(y_0, T, dt)
    y = zeros(T)
    y[1] = y_0

    for t = 1:T-1
        y[t+1] = (1+5*dt)y[t] + 4*dt
    end

    return y
end

function exact_solution(t)
    (y_0+4//5)*exp.(5*t) - 4//5
end

t = 0:dt:(T-1)dt
y = euler_method(y_0, T, dt)

plot(t, exact_solution, color=:cornflowerblue, label="Exact",xlabel="t",ylabel="y")
plot!(t, y, color=:coral, linestyle=:dash, label="Numerical",xlabel="t",ylabel="y")
savefig("1st_order_euler.png")


function Diffusion!(array,width::Int64,boxwidth,Df,t)

	changelist = fill(0.0,width)

	changelist[1] = - Df*t*( array[1] - array[2] )/boxwidth

	for iterator in 2:width-1
		changelist[iterator] = Df * t * (array[iterator-1] - array[iterator]) / boxwidth - Df * t * (array[iterator] - array[iterator+1]) / boxwidth
	end

	changelist[width] = Df*t* ( array[width-1] - array[width] )/(boxwidth)/boxwidth

	for iterator in 1:width
		array[iterator] = array[iterator] + changelist[iterator]
	end

end

function mixing!(array,pos)
	temp = array[pos]
	array[pos] = array[pos+1]
	array[pos + 1] = temp
end

function diffusionin1d(heatspeed::Float64,cuttemp::Float64,width::Int64,boxwidth::Float64,Df::Float64,t::Float64,iteration::Int64,outputfilename; heatpos = [1], mixpos = 0, mixcountmax = 1, roomtemp::Float64 = 25.0 , tempdetectpos = 3, recordpos = [3])

	open(outputfilename,"w") do f

		write(f,"Initial condition:\n",
				"The speed of heating: $heatspeed \n",
				"Cut of temperature: $cuttemp \n",
				"width of the system: $width \n",
				"width of the box: $boxwidth \n",
				"Diffusion coefficient: $Df \n",
				"Δt: $t \n",
				"total iteration: $iteration \n",
				"mixing position: $mixpos \n",
				"max counter of mixing: $mixcountmax \n",
				"room temperature: $roomtemp \n",
				"The position of detecting temp: $tempdetectpos \n")

		array = fill(roomtemp,width)

		mixcount = 1

		for i in 1:iteration
			elapsedtime = i * t

			if(array[tempdetectpos] <= cuttemp)
				for h in heatpos
					array[h] = array[h] + heatspeed * t
				end
			end

			Diffusion!(array,width,boxwidth,Df,t)

			array[width] = roomtemp

				write(f,"t = $elapsedtime  : \n")

				for k in recordpos
					write(f,"$(array[k])    ")
				end

				write(f,"\n")

			if(mixpos != 0)
				if(mixcount >= mixcountmax)
					mixing!(array,mixpos)
					mixcount = 0
				end
				mixcount = mixcount + 1
			end

		end
	end
end

function executor(filename)
	open(filename) do f
		tempstring = readline(f)
		while tempstring != ""
			eval(Meta.parse(tempstring))
			tempstring = readline(f)
		end
	end
end

function indextable(q)
	temp = fill(0,q)
	for i in 1:q
		temp[i] = i
	end
end


using Distributions
using Plots

function calc_midpoints(edges::AbstractVector)::Vector{Float64}
    return Float64[0.5 * (edges[i] + edges[i+1]) for i ∈ 1:length(edges)-1]
end

function bin_data1d(data::AbstractVector, bins::Integer)
    low, high = extrema(data)
    edges = collect(range(low, stop = high, length = bins + 1))
    midpoints = calc_midpoints(edges)
    buckets = Int[max(2, min(searchsortedfirst(edges, x), length(edges))) - 1 for x ∈ data]
    counts = zeros(Int, length(midpoints))
    for b in buckets
        counts[b] += 1
    end
    return edges, midpoints, buckets, counts
end

function bin_data2d(data::AbstractMatrix, xbins::Integer, ybins::Integer)
    xmin, ymin = minimum(data, dims = 2)
    xmax, ymax = maximum(data, dims = 2)
    xedges = collect(range(xmin, stop = xmax, length = xbins + 1))
    yedges = collect(range(ymin, stop = ymax, length = ybins + 1))
    xmidpts = calc_midpoints(xedges)
    ymidpts = calc_midpoints(yedges)
    buckets = []
    d, c = size(data)
    for i = 1:c
        x = data[1, i]
        y = data[2, i]
        xb = max(2, min(searchsortedfirst(xedges, x), length(xedges))) - 1
        yb = max(2, min(searchsortedfirst(yedges, y), length(yedges))) - 1
        push!(buckets, (yb, xb))
    end
    counts = zeros(Int, length(ymidpts), length(xmidpts))
    for (yb, xb) in buckets
        counts[yb, xb] += 1
    end
    xedges, yedges, xmidpts, ymidpts, buckets, counts
end

μ = [
    -1
    -2
]

Σ = [
    1.0 -0.7
    -0.7 1.0
]

using Distributions
d = MvNormal(μ, Σ)
xydata = rand(d, 10000)

p1 = plot(xlabel = "x", ylabel = "y")
xedges, yedges, xmidpts, ymidpts, buckets, counts = bin_data2d(xydata, 30, 30)
r, c = size(counts)
scatter!(p1, xydata[1, :], xydata[2, :], alpha = 0.2)
heatmap!(p1, xmidpts, ymidpts, counts, alpha = 0.85)
xind = 18
plot!(
    p1,
    [xmidpts[xind], xmidpts[xind]],
    [minimum(ymidpts), maximum(ymidpts)],
    color = :red,
    legend = :false,
)
p2 = plot(
    ymidpts,
    counts[:, xind] / sum(counts[:, xind]),
    label = "p(y|x=$(xmidpts[xind])",
)
plot(p1, p2, layout = (2, 1))


using OrdinaryDiffEq
using DataDrivenDiffEq
using ModelingToolkit
using Distributions
using Random
using Plots

Random.seed!(123);

function sir_ode(u,p,t)
    (s,i,r) = u
    (β,γ) = p
    ds = -β*s*i
    di = β*s*i - γ*i
    dr = γ*i
    [ds,di,dr]
end;

p = [0.5,0.25]
u0 = [0.99, 0.01, 0.0]
tspan = (0.0, 40.0)
δt = 1;

solver = ExplicitRK();

sir_prob = ODEProblem(sir_ode, u0, tspan, p)
sir_sol = solve(sir_prob, solver, saveat = δt);

dd_prob = ContinuousDataDrivenProblem(sir_sol);

@parameters t
@variables u[1:3](t)
Ψ = Basis([u; u[1]*u[2]], u, independent_variable = t)

res_koopman = solve(dd_prob, Ψ, DMDPINV())
sys_koopman = result(res_koopman);

equations(sys_koopman)

parameter_map(res_koopman)

res_sindy = solve(dd_prob, Ψ, STLSQ(),digits=1)
sys_sindy = result(res_sindy);

equations(sys_sindy)

parameter_map(res_sindy)

sir_data = Array(sir_sol);

A = 500.0 # Smaller values of A = noisier data
noisy_data = sir_data
# Note that we can't draw from u0 as R(0)=0
for i in 2:size(sir_data)[2]
    noisy_data[1:3,i] = rand(Dirichlet(A*sir_data[1:3,i]))
end;

scatter(sir_sol.t,noisy_data',title="Noisy data",xlabel="Time",ylabel="Proportion",labels=["S+noise" "I+noise" "R+noise"])
plot!(sir_sol,labels=["S" "I" "R"],legend=:left)

noisy_dd_prob = ContinuousDataDrivenProblem(noisy_data,sir_sol.t,GaussianKernel());

noisy_res_koopman = solve(noisy_dd_prob, Ψ, DMDPINV())
noisy_sys_koopman = result(noisy_res_koopman)
equations(noisy_sys_koopman), parameter_map(noisy_res_koopman)

noisy_res_sindy = solve(noisy_dd_prob, Ψ, STLSQ())
noisy_sys_sindy = result(noisy_res_sindy)
equations(noisy_sys_sindy), parameter_map(noisy_res_sindy)

A = 50.0 # Smaller values of A = noisier data
v_noisy_data = sir_data
# Note that we can't draw from u0 as R(0)=0
for i in 2:size(sir_data)[2]
    v_noisy_data[1:3,i] = rand(Dirichlet(A*sir_data[1:3,i]))
end;

scatter(sir_sol.t,v_noisy_data',title="Very noisy data",xlabel="Time",ylabel="Proportion",labels=["S+noise" "I+noise" "R+noise"])
plot!(sir_sol,labels=["S" "I" "R"],legend=:left)

v_noisy_dd_prob = ContinuousDataDrivenProblem(v_noisy_data,sir_sol.t,GaussianKernel())
v_noisy_res_sindy = solve(v_noisy_dd_prob, Ψ, STLSQ())
v_noisy_sys_sindy = result(v_noisy_res_sindy)
equations(v_noisy_sys_sindy), parameter_map(v_noisy_res_sindy)


"""
    to_cartesian(lat::T, lon::T, r::T) where {T}
    to_cartesian(location::GeoLocation)
    to_cartesian(locations::Vector{GeoLocation})

Converts a vector of GeoLocations to (x, y, z) cartesian coordinates (based on radius of the Earth).
"""
function to_cartesian(lat::T, lon::T, r::T) where {T}
    x = r * cos(lat) * cos(lon)
    y = r * cos(lat) * sin(lon)
    z = r * sin(lat)
    return x, y, z
end
function to_cartesian(loc::GeoLocation)
    lat = deg2rad(loc.lat)
    lon = deg2rad(loc.lon)
    r = loc.alt + RADIUS_OF_EARTH_KM # approximate radius of earth + alt in km
    x, y, z = to_cartesian(lat, lon, r)
    return x, y, z
end
function to_cartesian(locs::Vector{GeoLocation})
    n_points = length(locs)
    results = Matrix{Float64}(undef, 3, n_points)
    @inbounds for i in 1:n_points
        x, y, z = to_cartesian(locs[i])
        results[1, i] = x
        results[2, i] = y
        results[3, i] = z
    end
    return results
end

"""
    haversine(a_lat::T, a_lon::T, b_lat::T, b_lon::T) where {T}
    haversine(GeoLocation, B::GeoLocation)
    haversine(Node, B::Node)
    haversine(A::Vector{GeoLocation}, B::Vector{GeoLocation})
    haversine(A::Vector{Node}, B::Vector{Node})
    haversine(a::Vector{U}, b::Vector{U})::U where {U <: AbstractFloat}

Calculates the haversine distance (km) between two points.
"""

function haversine(a_lat::T, a_lon::T, b_lat::T, b_lon::T) where {T}
    d = sin((a_lat - b_lat) / 2)^2 + cos(b_lat) * cos(a_lat) * sin((a_lon - b_lon) / 2)^2
    return 2 * RADIUS_OF_EARTH_KM * asin(sqrt(d))
end
function haversine(A::GeoLocation, B::GeoLocation)
    a_lat = deg2rad(A.lat)
    a_lon = deg2rad(A.lon)
    b_lat = deg2rad(B.lat)
    b_lon = deg2rad(B.lon)
    return haversine(a_lat, a_lon, b_lat, b_lon)
end
haversine(a::Node, b::Node) = haversine(a.location, b.location)
haversine(A::Vector{<:GeoLocation}, B::Vector{<:GeoLocation}) = haversine.(A, B)
haversine(A::Vector{<:Node}, B::Vector{<:Node}) = haversine.(A, B)
function haversine(a::Vector{U}, b::Vector{U})::U where {U <: AbstractFloat}
    a_lat = deg2rad(a[1])
    a_lon = deg2rad(a[2])
    b_lat = deg2rad(b[1])
    b_lon = deg2rad(b[2])
    return haversine(a_lat, a_lon, b_lat, b_lon)
end

"""
    euclidean(a_x::T, a_y::T, a_z::T, b_x::T, b_y::T, b_z::T) where {T}
    euclidean(A::GeoLocation, B::GeoLocation)
    euclidean(A::Node, B::Node)
    euclidean(A::Vector{GeoLocation}, B::Vector{GeoLocation})
    euclidean(A::Vector{<:Node}, B::Vector{<:Node})
    euclidean(a::Vector{U}, b::Vector{U})::U where {U <: AbstractFloat}

Calculates the euclidean distance (km) between two points.
"""
euclidean(a_x::T, a_y::T, a_z::T, b_x::T, b_y::T, b_z::T) where {T} = hypot(a_x-b_x, a_y-b_y, a_z-b_z)
euclidean(A::GeoLocation, B::GeoLocation) = euclidean(to_cartesian(A)...,to_cartesian(B)...)
euclidean(a::Node, b::Node) = euclidean(a.location, b.location)
euclidean(A::Vector{GeoLocation}, B::Vector{GeoLocation}) = euclidean.(A, B)
euclidean(A::Vector{<:Node}, B::Vector{<:Node}) = euclidean.(A, B)
function euclidean(a::Vector{U}, b::Vector{U})::U where {U <: AbstractFloat}
    a_lat = deg2rad(a[1])
    a_lon = deg2rad(a[2])
    b_lat = deg2rad(b[1])
    b_lon = deg2rad(b[2])
    return euclidean(
        to_cartesian(a_lat, a_lon, RADIUS_OF_EARTH_KM)...,
        to_cartesian(b_lat, b_lon, RADIUS_OF_EARTH_KM)...
    )
end

"""
    distance(A::Union{Vector{GeoLocation}, GeoLocation, Vector{<:Node}, Node, Vector{<:AbstractFloat}},
             B::Union{Vector{GeoLocation}, GeoLocation, Vector{<:Node}, Node, Vector{<:AbstractFloat}},
             type::Symbol=:haversine
             )

Calculates the distance (km) between two points or two vectors of points.

# Arguments
- `A::Union{Vector{GeoLocation}, GeoLocation, Vector{<:Node}, Node, Vector{<:AbstractFloat}}`: Vector of origin points.
- `B::Union{Vector{GeoLocation}, GeoLocation, Vector{<:Node}, Node, Vector{<:AbstractFloat}}`: Vector of destination points.
- `method::Symbol=:haversine`: Either `:haversine` or `:euclidean`.

# Return
- Distance between origin and destination points in km.
"""
function distance(A::Union{Vector{GeoLocation},GeoLocation,Vector{<:Node},Node,Vector{<:AbstractFloat}},
                  B::Union{Vector{GeoLocation},GeoLocation,Vector{<:Node},Node,Vector{<:AbstractFloat}},
                  method::Symbol=:haversine
                  )
    if method == :haversine
        return haversine(A, B)
    elseif method == :euclidean
        return euclidean(A, B)
    else
        throw(ArgumentError("Distance method $method not implemented"))
    end
end

"""
    heading(a::GeoLocation, b::GeoLocation, return_units::Symbol=:degrees)
    heading(a::Node, b::Node, return_units::Symbol=:degrees)
    heading(A::Vector{GeoLocation}, B::Vector{GeoLocation}, return_units::Symbol=:degrees)
    heading(A::Vector{Node}, B::Vector{Node}, return_units::Symbol=:degrees)

Calculates heading(s) / bearing(s) between two points (`a` is origin, `b` is destination)
or two vectors of points (`A` is vector of origins, `B` is vector of destinations). Points
can be either `GeoLocation`s or `Node`s.

Depending on the `return_units` chosen, the return angle is in range of [-π, π] if `:radians`
or [-180, 180] if `:degrees`. Additionally, adjusts destination longitude in case the straight
line path between a and b crosses the International Date Line.
"""
function heading(a::GeoLocation, b::GeoLocation, return_units::Symbol=:degrees)
    a_lat = a.lat
    a_lon = a.lon
    b_lat = b.lat
    b_lon = b.lon

    # Adjust destination longitude in case straight line path between A and B crosses the International Date Line
    a_lon_left_idx = (b_lon <= a_lon) * ((b_lon + 180) + (180 - a_lon) > (a_lon - b_lon))
    a_lon_right_idx = (b_lon <= a_lon) * ((b_lon + 180) + (180 - a_lon) <= (a_lon - b_lon))

    b_lon_left_idx = (b_lon > a_lon) * ((a_lon + 180) + (180 - b_lon) .< (b_lon - a_lon))
    b_lon_right_idx = (b_lon > a_lon) * ((a_lon + 180) + (180 - b_lon) >= (b_lon - a_lon))

    b_lon_fixed = b_lon_left_idx * (-180 - (180 - b_lon)) +
                  b_lon_right_idx * b_lon +
                  a_lon_left_idx * b_lon +
                  a_lon_right_idx * (180 - abs(-180 - b_lon))

    a_lat = deg2rad(a_lat)
    a_lon = deg2rad(a_lon)
    b_lat = deg2rad(b_lat)
    b_lon_fixed = deg2rad(b_lon_fixed)

    y = sin(b_lon_fixed - a_lon) * cos(b_lat)
    x = cos(a_lat) * sin(b_lat) - sin(a_lat) * cos(b_lat) * cos(b_lon_fixed - a_lon)

    heading = atan.(y, x)

    if return_units == :radians
        return heading
    elseif return_units == :degrees
        return rad2deg(heading)
    else
        throw(ArgumentError("Incorrect input for argument `return_units`, choose either `:degrees` or `:radians`"))
    end
end
heading(A::Vector{GeoLocation}, B::Vector{GeoLocation}, return_units::Symbol=:degrees) = heading.(A, B, return_units)
heading(a::Node, b::Node, return_units::Symbol=:degrees)::AbstractFloat = heading(a.location, b.location, return_units)
heading(A::Vector{<:Node}, B::Vector{<:Node}, return_units::Symbol=:degrees) = heading.(A, B, return_units)

"""
    calculate_location(origin::GeoLocation, heading::Number, distance::Number)
    calculate_location(origin::Node, heading::Number, distance::Number)
    calculate_location(origin::Vector{GeoLocation}, heading::Vector{<:Number}, distance::Vector{<:Number})
    calculate_location(origin::Vector{Node}, heading::Vector{<:Number}, distance::Vector{<:Number})

Calculates next location(s) given origin `GeoLocation`(s) or `Node`(s), heading(s) (degrees)
and distance(s) (km).

Locations are returned as `GeoLocation`s.
"""
function calculate_location(origin::GeoLocation, heading::Number, distance::Number)
    lat = deg2rad(origin.lat)
    lon = deg2rad(origin.lon)
    heading = deg2rad(heading)

    lat_final = asin(sin(lat) * cos(distance / RADIUS_OF_EARTH_KM) + cos(lat) * sin(distance / RADIUS_OF_EARTH_KM) * cos(heading))
    lon_final = lon + atan(sin(heading) * sin(distance / RADIUS_OF_EARTH_KM) * cos(lat), cos(distance / RADIUS_OF_EARTH_KM) - sin(lat) * sin(lat_final))

    return GeoLocation(rad2deg(lat_final), rad2deg(lon_final))
end
calculate_location(origins::Vector{GeoLocation}, headings::Vector{<:Number}, distances::Vector{<:Number}) = calculate_location.(origins, headings, distances)
calculate_location(origin::Node, heading::Number, distance::Number)::GeoLocation = calculate_location(origin.location, heading, distance)
calculate_location(origins::Vector{<:Node}, headings::Vector{<:Number}, distances::Vector{<:Number}) = calculate_location.(origins, headings, distances)

"""
    bounding_box_from_point(point::GeoLocation, radius::Number)::NamedTuple

Calculates the coordinates of the bounding box given a centroid point and radius (km).

# Arguments
- `point::GeoLocation`: Centroid of the bounding box as an GeoLocation.
- `radius::Number`: Radius in km of the bounding box (to each corner).

# Return
- `NamedTuple`: Named tuple with attributes minlat, minlon, maxlat, right_lon.
"""
function bounding_box_from_point(point::GeoLocation, radius::Number)::NamedTuple
    bottom_left, top_right = calculate_location([point, point], [225, 45], [radius, radius])
    return (minlat = bottom_left.lat, minlon = bottom_left.lon, maxlat = top_right.lat, maxlon = top_right.lon)
end


module BarycentricLagrange
# Reference:
# Barycentric Lagrange Interpolation.
# Berrut, J.-P., & Trefethen, L. N. (2004).
# SIAM Review, 46(3), 501–517. doi:10.1137/S36144502417716

export bclag_interp_eval
export bclag_interp_matrix
export bclag_interp_weights

using Compat

function bclag_interp_weight(x, j, n)
    p = 1.0
    for k=1:j-1
        p *= x[j] - x[k]
    end
    for k=j+1:n
        p *= x[j] - x[k]
    end
    return 1/p
end

"""
    w = bclag_interp_weights(x)

Compute weights for Barycentric Lagrange interpolation.
"""
function bclag_interp_weights(x::Vector)
    n = length(x)
    w = zeros(n)
    for j=1:n
        w[j] = bclag_interp_weight(x, j, n)
    end
    return w
end

function bclag_interp_eval(x::Vector, f::Vector{T}, xx::Number,
                           w::Vector = bclag_interp_weights(x)) where T
    n = length(x)
    @assert length(f) == length(w) == n
    numer = zero(T)
    denom = 0.0
    for j=1:n
        xdiff = xx-x[j]
        if xdiff==0
            return f[j]
        end
        tmp = w[j] / xdiff
        numer += f[j]*tmp
        denom += tmp
    end
    ff = numer/denom
    return ff
end

"""
    ff = bclag_interp_eval(x, f, xx [, w])

Barycentric Lagrange interpolation of `f` from points `x` to points `xx`

`w` is vector of weights, `w = bclag_interp_weights(x)`
"""
function bclag_interp_eval(x::Vector, f::Vector{T}, xx::Vector,
                           w::Vector = bclag_interp_weights(x)) where T
    n = length(xx)
    ff = Array{T}(undef, n)
    for j=1:n
        ff[j] = bclag_interp_eval(x, f, xx[j], w)
    end
    return ff
end

"""
    M = bclag_interp_matrix(x, xx [, w])

Compute the matrix `M` such that `ff = M*f` gives the barycentric Lagrange interpolation of `f` from points `x` to points `xx`.

`w` is vector of weights, `w = bclag_interp_weights(x)`
"""
function bclag_interp_matrix(x::Vector, xx::Vector,
                             w::Vector = bclag_interp_weights(x))
    n = length(x)
    N = length(xx)
    @assert length(w)==n
    B, denom, exact = matrix_alloc(n, N)
    compute_matrix!(B, denom, exact, x, xx, w)
    return B
end

function matrix_alloc(n, N)
    B = Array{Float64}(undef, N, n)
    denom = Array{Float64}(undef, N)
    exact = Array{Int64}(undef, N)
    return B, denom, exact
end

function compute_matrix!(B, denom, exact, x, xx, w)
    # No allocations or size checks done here
    N, n = size(B)
    fill!(denom, 0.0)
    fill!(exact, 0)
    for j=1:n
        for k=1:N
            xdiff = xx[k]-x[j]
            if xdiff != 0
                temp = w[j]/xdiff
                B[k,j] = temp
                denom[k] += temp
            else
                exact[k] = j
            end
        end
    end
    B ./= denom
    for jj=1:N
        if exact[jj] != 0
            @. B[jj,:] = 0.0
            B[jj + N*(exact[jj]-1)] = 1.0
        end
    end
end

end # module


#Import Turing, Distributions and DataFrames
using Turing, Distributions, DataFrames, Distributed

# Import MCMCChain, Plots, and StatsPlots for visualizations and diagnostics.
using MCMCChains, Plots, StatsPlots

# Set a seed for reproducibility.
using Random
Random.seed!(12);

# Turn off progress monitor.
Turing.setprogress!(false)

theta_noalcohol_meds = 1    # no alcohol, took medicine
theta_alcohol_meds = 3      # alcohol, took medicine
theta_noalcohol_nomeds = 6  # no alcohol, no medicine
theta_alcohol_nomeds = 36   # alcohol, no medicine

# no of samples for each of the above cases
q = 100

#Generate data from different Poisson distributions
noalcohol_meds = Poisson(theta_noalcohol_meds)
alcohol_meds = Poisson(theta_alcohol_meds)
noalcohol_nomeds = Poisson(theta_noalcohol_nomeds)
alcohol_nomeds = Poisson(theta_alcohol_nomeds)

nsneeze_data = vcat(rand(noalcohol_meds, q), rand(alcohol_meds, q), rand(noalcohol_nomeds, q), rand(alcohol_nomeds, q) )
alcohol_data = vcat(zeros(q), ones(q), zeros(q), ones(q) )
meds_data = vcat(zeros(q), zeros(q), ones(q), ones(q) )

df = DataFrame(nsneeze = nsneeze_data, alcohol_taken = alcohol_data, nomeds_taken = meds_data, product_alcohol_meds = meds_data.*alcohol_data)
df[sample(1:nrow(df), 5, replace = false), :]

#Data Plotting

p1 = Plots.histogram(df[(df[:,:alcohol_taken] .== 0) .& (df[:,:nomeds_taken] .== 0), 1], title = "no_alcohol+meds")
p2 = Plots.histogram((df[(df[:,:alcohol_taken] .== 1) .& (df[:,:nomeds_taken] .== 0), 1]), title = "alcohol+meds")
p3 = Plots.histogram((df[(df[:,:alcohol_taken] .== 0) .& (df[:,:nomeds_taken] .== 1), 1]), title = "no_alcohol+no_meds")
p4 = Plots.histogram((df[(df[:,:alcohol_taken] .== 1) .& (df[:,:nomeds_taken] .== 1), 1]), title = "alcohol+no_meds")
plot(p1, p2, p3, p4, layout = (2, 2), legend = false)

# Convert the DataFrame object to matrices.
data = Matrix(df[:,[:alcohol_taken, :nomeds_taken, :product_alcohol_meds]])
data_labels = df[:,:nsneeze]
data

# # Rescale our matrices.
data = (data .- mean(data, dims=1)) ./ std(data, dims=1)

# Bayesian poisson regression (LR)
@model poisson_regression(x, y, n, σ²) = begin
    b0 ~ Normal(0, σ²)
    b1 ~ Normal(0, σ²)
    b2 ~ Normal(0, σ²)
    b3  ~ Normal(0, σ²)
    for i = 1:n
        theta = b0 + b1*x[i, 1] + b2*x[i,2] + b3*x[i,3]
        y[i] ~ Poisson(exp(theta))
    end
end;

# Retrieve the number of observations.
n, _ = size(data)

# Sample using NUTS.

num_chains = 4
chain = mapreduce(
    c -> sample(poisson_regression(data, data_labels, n, 10), NUTS(200, 0.65), 2500, discard_adapt=false),
    chainscat,
    1:num_chains);

gelmandiag(chain)

# Taking the first chain
c1 = chain[:,:,1]

# Calculating the exponentiated means
b0_exp = exp(mean(c1[:b0]))
b1_exp = exp(mean(c1[:b1]))
b2_exp = exp(mean(c1[:b2]))
b3_exp = exp(mean(c1[:b3]))

print("The exponent of the meaned values of the weights (or coefficients are): \n")
print("b0: ", b0_exp, " \n", "b1: ", b1_exp, " \n", "b2: ", b2_exp, " \n", "b3: ", b3_exp, " \n")
print("The posterior distributions obtained after sampling can be visualised as :\n")

plot(chain)

# Note the standard deviation before removing the warmup samples
describe(chain)

# Removing the first 200 values of the chains.
chains_new = chain[201:2500,:,:]
describe(chains_new)

plot(chains_new)

if isdefined(Main, :TuringTutorials)
    Main.TuringTutorials.tutorial_footer(WEAVE_ARGS[:folder], WEAVE_ARGS[:file])
end


@doc raw"""
    general_form(xi::Point2D, xo::Point2D)

Returns the general form equation of a line that passes through points `xi` and `xo` as a
[`SVector`](@ref) which holds A, B and C such that:
```math
A \cdot x + B \cdot y +  C = 0.
```
"""
function general_form(xi::Point2D, xo::Point2D)
    A = xi[2] - xo[2]
    B = xo[1] - xi[1]
    C = xi[1] * xo[2] - xo[1] * xi[2]
    ABC = SVector(A, B, C)
    ABC /= norm(ABC) # for numerical reasons (?)
    return ABC
end
# the function above is faster than using linear algebra:
# [x1 y1; x2 y2] ⋅ [Â, B̂] = [-1, -1] yields to solution for Â and B̂ such that
# Â ⋅ x + B̂ ⋅ y + 1 = 0. Here we make it faster.
# F = transpose(hcat(xi, xo))
# b = SVector(-1, -1)
# x = F \ b
# ABC = vcat(b, 1) # and then we can normalize

# We could use LazySets.jl for some part of this particular function but it seems slow!
"""
    intersections(mesh::Mesh, cell_id::Int, track::Track)

Computes the entry and exit points of a given `track` that is known to cross element with id
`cell_id`.
"""
function intersections(
    mesh::Mesh, cell_id::Int32, track::Track{BIn,BOut,DFwd,DBwd,T}
) where {BIn,BOut,DFwd,DBwd,T}
    @unpack model, cell_nodes = mesh

    node_coordinates = get_node_coordinates(get_grid(model))
    node_ids = cell_nodes[cell_id]

    int_points = MVector{4,Point2D{T}}(
        Point2D(0, 0), Point2D(0, 0), Point2D(0, 0), Point2D(0, 0)
    )

    n_int = 0
    parallel_found = false
    for i in eachindex(node_ids)

        j = i == lastindex(node_ids) ? 1 : i + 1

        # get node coordinates and cast them to Point2D
        p1 = convert(Point2D{T}, node_coordinates[node_ids[i]])
        p2 = convert(Point2D{T}, node_coordinates[node_ids[j]])

        # compute general form equation for the selected element face
        ABC = general_form(p1, p2)

        # compute intersections between track and element face
        are_parallel, x_int = intersection(track.ABC, ABC)

        # if the track is parallel to the element face, it can be on top of it or do not
        # cross at all. Either way, we just ignore this case because we can compute the
        # intersections using the other faces.
        if are_parallel
            parallel_found = true
            continue

        # if the intersection is outside the face, avoid it
        elseif !point_in_segment(p1, p2, x_int)
            continue

        # this is a valid intersection, store it
        else
            n_int += 1
            int_points[n_int] = x_int
        end
    end

    # now let's check all the possible situations and handle extreme cases
    if n_int in (3, 4)
        ℓ = zero(T)
        # get the points that have the maximun distance between
        for i in 2:n_int, j in i:n_int
            x1 = int_points[i-1]
            x2 = int_points[j]
            ℓi = norm(x1 - x2)
            if ℓi > ℓ
                x_int1 = x1
                x_int2 = x2
                ℓ = ℓi
            end
        end
        return order_intersection_points(track, x_int1, x_int2)

    elseif n_int == 2 && parallel_found

        x_int1 = int_points[1]
        x_int2 = int_points[2]
        return order_intersection_points(track, x_int1, x_int2)

    elseif n_int == 2 && !parallel_found

        x_int1 = int_points[1]
        x_int2 = int_points[2]

        if isapprox(x_int1, x_int2)
            # do nothing and move a tiny step forward in the parent function, we are on a
            # vertex
            return x_int1, x_int2
        else
            return order_intersection_points(track, x_int1, x_int2)
        end
    elseif iszero(n_int) || isone(n_int)
        # the parent function will move a tiny step further
        return Point2D{T}(0, 0), Point2D{T}(0, 0)
        # error("This is an unexpected case. Please, submit an issue.")
    end
end

"""
    intersection(ABC1, ABC2)

Computes the intersection between two lines with general form equations given by `ABC1` and
`ABC2`. It also indicates if the lines are parallel.
"""
function intersection(ABC1::AbstractVector, ABC2::AbstractVector)
    a = ABC1[2] * ABC2[1]
    b = ABC2[2] * ABC1[1]
    x = y = zero(a)
    are_parallel = isapprox(a, b)
    if !are_parallel
        det = a - b
        x = (ABC1[3] * ABC2[2] - ABC2[3] * ABC1[2]) / det
        y = (ABC1[1] * ABC2[3] - ABC2[1] * ABC1[3]) / det
    end
    return are_parallel, Point2D(x, y)
end

# this one returns a matrix even if F is not invertible (have the same speed as the above)
# function intersection(ABC1, ABC2)
#     F = @SMatrix [ABC1[1] ABC1[2]
#                   ABC2[1] ABC2[2]]
#     b = @SVector [ABC1[3], ABC2[3]]

#     x = F \ (-b)

#     return Point2D(x[1], x[2])
# end

function order_intersection_points(track::Track, x1::Point2D, x2::Point2D)
    @unpack ϕ = track

    if isless(ϕ, π/2)
        if x1[1] < x2[1]
            xi = x1
            xo = x2
        else
            xi = x2
            xo = x1
        end
    else
        if x1[1] > x2[1]
            xi = x1
            xo = x2
        else
            xi = x2
            xo = x1
        end
    end
    return xi, xo
end


#=
Compute the running median of a sequence of numbers. That is, given a stream of numbers, print out the median of the list so far on each new element.

Recall that the median of an even-numbered list is the average of the two middle numbers.

For example, given the sequence [2, 1, 5, 7, 2, 0, 5], your algorithm should print out:

2
1.5
2
3.5
2
2
2
=#

function print_running_median(arr::Array; store = false)
    if store
        median_arr = []
    end
    for index in 1:length(arr)
        current_arr = sort(arr[1:index])
        if length(current_arr) % 2 == 0
            median = (current_arr[Int8(length(current_arr)/2)] + current_arr[Int8(length(current_arr)/2 + 1)]) / 2
            println(median)
            if store
                push!(median_arr, median)
            end
        else
            median = current_arr[ceil(Int8, length(current_arr)/2)]
            println(median)
            if store
                push!(median_arr, median)
            end
        end
    end
    if store
        return median_arr
    end
end


using Statistics

"""
    mse(y, t; back = false)
Return the mean square error:
    mean((y .- t) .^ 2)
# Example
```
julia> loss = mse
mse (generic function with 1 method)

julia> y, t = [1, 3, 2, 5], [1, 2, 3, 4]
([1, 3, 2, 5], [1, 2, 3, 4])

julia> loss(y, t)
0.75
```
"""
function mse(y, t; back = false)
    if back == true
        return 2(y .- t)
    end
    return mean((y .- t) .^ 2)
end