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

using Markdown
using InteractiveUtils

# ╔═╡ 1fbdb6c6-4bf4-11eb-3aeb-9548bde2b1a5
begin
	using DataFrames
	using Empirikos
	using Plots
	using PGFPlotsX
	using LaTeXStrings
	using MosekTools
	using JuMP
	using Setfield
	using Random
end

# ╔═╡ 3cf2bafa-4bf4-11eb-3482-ff09ca17af71
md"""
# Identifying genes associated with prostate cancer

## Load packages and dataset
"""

# ╔═╡ 473d8a28-4bf4-11eb-0151-8b3f3d286eda
begin
	pgfplotsx()
	empty!(PGFPlotsX.CUSTOM_PREAMBLE)
	push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\usepackage{amssymb}")
	push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\newcommand{\PP}[2][]{\mathbb{P}_{#1}\left[#2\right]}")
	push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\newcommand{\EE}[2][]{\mathbb{E}_{#1}\left[#2\right]}")
end;

# ╔═╡ 17be2c0c-4bf5-11eb-25ca-cfe4e5fb5485
theme(:default;
      background_color_legend = :transparent,
      foreground_color_legend = :transparent,
      grid=nothing,
      frame=:box,
      legendfonthalign = :left,
      thickness_scaling=1.3)

# ╔═╡ acfc4fc0-4bf4-11eb-32dc-dfe1652ac006
Zs = Prostate.ebayes_samples();

# ╔═╡ f4bd73b8-4bf4-11eb-3678-655227b0895b
md"""
## Marginal distribution of z-scores

### DKW-F-Localization
"""

# ╔═╡ 0731218a-4bf5-11eb-10f4-81241477b265
dkw_floc = DvoretzkyKieferWolfowitz(0.05)

# ╔═╡ 0d36dbee-4bf5-11eb-3036-7bcf68579a46
fitted_dkw = fit(dkw_floc, Zs)

# ╔═╡ 246264dc-4bf5-11eb-2f9d-b5c7d137a9b3
dkw_plot = plot(fitted_dkw, label="DKW band",
     xlab=L"z", ylab=L"\widehat{F}_n(z)",  size=(380,280))

# ╔═╡ 4dd1f99a-4bf5-11eb-3691-9db09ab324df
# savefig(dkw_plot, "prostate_dkw_band.tikz")

# ╔═╡ 362effcc-4bf5-11eb-1d84-3133de3f4825
md"### KDE-F-Localization"

# ╔═╡ 5ad6b662-4bf5-11eb-24fb-d141933957ca
infty_floc = Empirikos.InfinityNormDensityBand(;a_min=-3.0,a_max=3.0,α=0.05)

# ╔═╡ 605a545e-4bf5-11eb-3020-6d9c53e39a8e
fitted_infty_floc = fit(infty_floc, Zs)

# ╔═╡ 69e87366-4bf5-11eb-3fbb-8f7bf325d366
prostate_kde_plot = begin
	prostate_marginal_plot = histogram([response(Z) for Z in Zs],
		  bins=50, normalize=true,
          label="Histogram", fillalpha=0.4, linealpha=0.4, fillcolor=:lightgray,
          size=(380,280), xlims=(-4.5,4.5))
	plot!(prostate_marginal_plot, fitted_infty_floc,
       	  label="KDE band", xlims=(-4.5,4.5),
          yguide=L"\widehat{f}_n(z)", xguide=L"z")
	plot!(prostate_marginal_plot, [-3.0;3.0], seriestype=:vline,
		  linestyle=:dot, label=nothing, color=:lightgrey)
end

# ╔═╡ 750e2af0-4bf6-11eb-3374-1f224647d4e5
# savefig("prostate_kde_band.tikz")

# ╔═╡ aa99cc74-4bf6-11eb-2e3f-81de213db00d
 md"## Confidence intervals"

# ╔═╡ df1513be-4bf6-11eb-1b1c-fd650fd994fe
quiet_mosek = optimizer_with_attributes(Mosek.Optimizer, "QUIET" => true)

# ╔═╡ c4bc3468-4bf4-11eb-1710-f7638d026b91
gcal_locmix = MixturePriorClass(Normal.(-3:0.05:3, 0.25))

# ╔═╡ bd7a5362-4bf4-11eb-1f2c-79ff3e915f89
gcal_scalemix = Empirikos.set_defaults(GaussianScaleMixtureClass(), Zs; hints = Dict(:grid_scaling => 1.1))

# ╔═╡ 9b6b8f8a-4bf6-11eb-002d-7fa04ddde0d3
discr = interval_discretizer(-3.0:0.005:3.0)

# ╔═╡ 68f0af78-8165-11eb-2a88-efd9f9743eec
discr.sorted_intervals[1]

# ╔═╡ ce945cca-4bf6-11eb-29bc-4b2514ae395d
floc_method_dkw_locmix = FLocalizationInterval(flocalization = dkw_floc,
                               convexclass = gcal_locmix, solver = quiet_mosek)

# ╔═╡ e9e81b9c-4bf6-11eb-1c3c-d56076f6858b
floc_method_kde_locmix = FLocalizationInterval(flocalization = infty_floc,
                               convexclass = gcal_locmix, solver = quiet_mosek)

# ╔═╡ 04c72ec6-4bf7-11eb-3265-5f69502b9f0b

amari_kde_locmix = Empirikos.AMARI(
						convexclass = gcal_locmix,
						flocalization = (@set infty_floc.α=0.01),
                        discretizer=discr,
                        solver=quiet_mosek, )

# ╔═╡ 31bd322c-4bf7-11eb-007c-d7583730cd8e
floc_method_dkw_scalemix = FLocalizationInterval(flocalization = dkw_floc,
                               convexclass = gcal_scalemix, solver = quiet_mosek)

# ╔═╡ 3d5b459c-4bf7-11eb-3825-6b75cc4099f3
floc_method_kde_scalemix = FLocalizationInterval(flocalization = infty_floc,
                               convexclass = gcal_scalemix, solver = quiet_mosek)

# ╔═╡ 474bdc10-4bf7-11eb-0099-cdf3150001a2
amari_kde_scalemix = Empirikos.AMARI(
						convexclass = gcal_scalemix,
						flocalization = (@set infty_floc.α=0.01),
                        discretizer=discr,
                        solver=quiet_mosek, )

# ╔═╡ 5fe96288-4bf7-11eb-1805-1f7f7815e035
ts= -3:0.2:3

# ╔═╡ 65d3b2de-4bf7-11eb-3ab5-a13a5b5556ef
postmean_targets = Empirikos.PosteriorMean.(StandardNormalSample.(ts))

# ╔═╡ 6ade8f74-4bf7-11eb-2b46-51436f6bf297
lfsrs = Empirikos.PosteriorProbability.(StandardNormalSample.(ts),
										Interval(0,nothing))

# ╔═╡ 7c0fd708-4bf7-11eb-12e0-45ecc7f9af7a
postmean_ci_dkw_locmix = confint.(floc_method_dkw_locmix, postmean_targets, Zs)

# ╔═╡ 85c63cc4-4bf7-11eb-2688-2b63ea65b2e7
postmean_ci_kde_locmix = confint.(floc_method_kde_locmix, postmean_targets, Zs)

# ╔═╡ 89a047c2-4bf7-11eb-3c79-15fe2fcdcb1c
postmean_ci_amari_locmix = confint.(amari_kde_locmix, postmean_targets, Zs)

# ╔═╡ a262fe94-4bf7-11eb-1153-6f76128cbcd0
postmean_locmix_plot = begin
	postmean_locmix_plot = plot(ts, postmean_ci_kde_locmix, label="Gauss-F-Loc",
		fillcolor=:darkorange, fillalpha=0.5, ylim=(-2.55,2.55),
        xguide = L"z", yguide=L"\EE{\mu \mid Z=z}",
        size=(380,280))
	plot!(postmean_locmix_plot, ts, postmean_ci_dkw_locmix, label="DKW-F-Loc",
		show_ribbon=false, alpha=0.9, color=:black)
	plot!(postmean_locmix_plot, ts, postmean_ci_amari_locmix, label="AMARI",
		show_ribbon=true, fillcolor=:blue, fillalpha=0.4)
	plot!(postmean_locmix_plot, [-3.0;3.0], [-3.0; 3.0], seriestype=:line,
		linestyle=:dot, label=nothing, color=:lightgrey)
end

# ╔═╡ 622669fa-4bf8-11eb-08fd-a3bd67230729
# savefig(postmean_locmix_plot, "prostate_locmix_postmean.tikz")

# ╔═╡ 6930b1ae-4bf8-11eb-23c7-e5be40b7a283
postmean_ci_dkw_scalemix = confint.(floc_method_dkw_scalemix, postmean_targets, Zs)

# ╔═╡ 6fba4f94-4bf8-11eb-2177-87f38a9b73d2
postmean_ci_kde_scalemix = confint.(floc_method_kde_scalemix, postmean_targets, Zs)

# ╔═╡ 7c308bb4-4bf8-11eb-249a-0f6d933a530c
postmean_ci_amari_scalemix = confint.(amari_kde_scalemix, postmean_targets, Zs)

# ╔═╡ 8abdac16-4bf8-11eb-3b0d-a73d7b28bb7c
postmean_scalemix_plot = begin
	postmean_scalemix_plot = plot(ts, postmean_ci_kde_scalemix,
		label="Gauss-F-Loc", fillcolor=:darkorange, fillalpha=0.5, ylim=(-2.55,2.55),
        xguide = L"z",
		yguide=L"\EE{\mu \mid Z=z}",
        size=(380,280))
	plot!(postmean_scalemix_plot, ts, postmean_ci_dkw_scalemix,
		label="DKW-F-Loc",show_ribbon=false, alpha=0.9, color=:black)
	plot!(postmean_scalemix_plot, ts, postmean_ci_amari_scalemix,
		label="AMARI",show_ribbon=true, fillcolor=:blue, fillalpha=0.4)
	plot!(postmean_scalemix_plot, [-3.0;3.0], [-3.0; 3.0], seriestype=:line,
		linestyle=:dot, label=nothing, color=:lightgrey)
end

# ╔═╡ eb851e8a-4bf8-11eb-353a-e5c394ae5294
# savefig(postmean_scalemix_plot, "prostate_scalemix_postmean.tikz")

# ╔═╡ 1e0db04c-4bf9-11eb-1bde-9dfa4f81f279
lfsr_ci_dkw_locmix = confint.(floc_method_dkw_locmix, lfsrs, Zs)

# ╔═╡ 2700eeda-4bf9-11eb-27ba-c5c6fe33980d
lfsr_ci_kde_locmix = confint.(floc_method_kde_locmix, lfsrs, Zs)

# ╔═╡ 2eba35aa-4bf9-11eb-1bf0-0be32d4bff85
lfsr_ci_amari_locmix = confint.(amari_kde_locmix, lfsrs, Zs)

# ╔═╡ a30dce02-4bfa-11eb-1197-5b69f20af457
lfsr_locmix_plot = begin
	lfsr_locmix_plot = plot([-3;3], [0.5; 0.5], seriestype=:line,
		linestyle=:dot, label=nothing, color=:lightgrey,
        xguide = L"z",
		yguide=L"\PP{\mu \geq 0 \mid Z=z}", size=(380,280))
	plot!(lfsr_locmix_plot, ts, lfsr_ci_kde_locmix,
		label="Gauss-F-Loc", fillcolor=:darkorange, fillalpha=0.5, ylim=(0,1))
	plot!(lfsr_locmix_plot, ts, lfsr_ci_dkw_locmix,
		label="DKW-F-Loc",show_ribbon=false, alpha=0.9, color=:black)
	plot!(lfsr_locmix_plot, ts, lfsr_ci_amari_locmix,
		label="AMARI",show_ribbon=true, fillcolor=:blue, fillalpha=0.4)
end

# ╔═╡ 716b8220-4bf9-11eb-1a28-33dbf08e138c
# savefig(lfsr_locmix_plot, "prostate_locmix_lfsr.tikz")

# ╔═╡ 9afa4b4a-4bf9-11eb-2a16-531b86e6b9a9
lfsr_ci_dkw_scalemix = confint.(floc_method_dkw_scalemix, lfsrs, Zs)

# ╔═╡ 9e06f2b8-4bf9-11eb-1bad-b5a1d26339ee
lfsr_ci_kde_scalemix = confint.(floc_method_kde_scalemix, lfsrs, Zs)

# ╔═╡ a1ba1e12-4bf9-11eb-00c9-496602f4eb5c
lfsr_ci_amari_scalemix = confint.(amari_kde_scalemix, lfsrs, Zs)

# ╔═╡ f2414706-4bfa-11eb-1654-9bdcc7418db8
lfsr_scalemix_plot = begin
	lfsr_scalemix_plot = plot([-3;3], [0.5; 0.5], seriestype=:line,
		linestyle=:dot, label=nothing, color=:lightgrey,
        xguide = L"z",
		yguide=L"\PP{\mu \geq 0 \mid Z=z}", size=(380,280))
	plot!(lfsr_scalemix_plot, ts, lfsr_ci_kde_scalemix,
		label="Gauss-F-Loc", fillcolor=:darkorange, fillalpha=0.5, ylim=(0,1))
	plot!(lfsr_scalemix_plot, ts, lfsr_ci_dkw_scalemix,
		label="DKW-F-Loc",show_ribbon=false, alpha=0.9, color=:black)
	plot!(lfsr_scalemix_plot, ts, lfsr_ci_amari_scalemix,
		label="AMARI",show_ribbon=true, fillcolor=:blue, fillalpha=0.4)
end

# ╔═╡ f7a59c42-4bfa-11eb-27df-cf611213fefc
# savefig(lfsr_scalemix_plot, "prostate_scalemix_lfsr.tikz")

# ╔═╡ 3e986c36-79a1-4ffd-9d2b-4bc96f2a5fa8
md"## Sensitivity Analysis and goodness-of-fit"

# ╔═╡ c6758a61-c32f-4ec7-8336-085f6dadb96d
Random.seed!(1)

# ╔═╡ 3950ca34-f8eb-4450-985f-fdb47a1b6f8b
n_half = ceil(Int64, nobs(Zs)/2)

# ╔═╡ e61af6d2-e4df-4c9a-bb2e-40e8e706f36d
train_idx = sample(1:nobs(Zs), n_half, replace=false);

# ╔═╡ 8a936d80-c61f-4d22-a1f1-c891d0063ee2
test_idx = setdiff(1:nobs(Zs), train_idx);

# ╔═╡ d0c37eca-4c5e-42ba-970a-4d1fe27d33ea
Zs_train = Zs[train_idx]

# ╔═╡ 5ef18ef6-0d4a-4846-a1ec-8dfcc4168588
Zs_test = Zs[test_idx]

# ╔═╡ 506eb209-b761-48a2-8a31-0fe8c98a9802
τs = [0.02; 0.1; 0.25; 0.5; 0.55]

# ╔═╡ 80f5d5de-0d75-4a6e-8143-8e3f3b48af43
gcal_np = DiscretePriorClass(-4:0.005:4)

# ╔═╡ fb6464e6-3a4d-4609-9b96-37edc2a6021f
npmle_fit = fit(NPMLE(convexclass=gcal_np, solver=Mosek.Optimizer), Zs_train)

# ╔═╡ c09e057e-24b2-4486-a497-e4908dcf2881
res_list  = Vector{Any}(undef, 5);

# ╔═╡ c5ae00f4-c078-4ece-9ebf-90ea8e5b724a
postmean_target = Empirikos.PosteriorMean(StandardNormalSample(2.0))

# ╔═╡ 6501119c-338c-4931-a09e-38b5b3f8a81d
lfsr_target = Empirikos.PosteriorProbability(StandardNormalSample(2.0),
                          Interval(0,nothing))

# ╔═╡ a1b52f7a-4a53-485f-b246-fe008322c6a4
for (i, τ) in enumerate(τs)

    gcal_loc = MixturePriorClass(Normal.(-3:0.002:3, τ))

    npmle_loc_fit = fit(NPMLE(convexclass=gcal_loc, solver=Mosek.Optimizer),
						Zs_test)

    e_value = exp(loglikelihood(Zs_test, npmle_fit.prior) -
		          loglikelihood(Zs_test, npmle_loc_fit.prior))

    floc_tmp = FLocalizationInterval(flocalization = fitted_infty_floc,
                convexclass = gcal_loc;
                solver = quiet_mosek)

    local floc_fit_lfsr
    local ci_lfsr
    local floc_fit_postmean
    local ci_postmean
    try
        floc_fit_lfsr = fit(floc_tmp, lfsr_target, Zs)
        ci_lfsr = confint(floc_fit_lfsr)

        floc_fit_postmean = fit(floc_tmp, postmean_target, Zs)
        ci_postmean = confint(floc_fit_postmean)
    catch
        floc_fit_lfsr = "error"
        ci_lfsr = "error"
        floc_fit_postmean = "error"
        ci_postmean = "error"
    end
    res_list[i] = (floc_fit_lfsr = floc_fit_lfsr, ci_lfsr = ci_lfsr,
                   floc_fit_postmean = floc_fit_postmean, ci_postmean = ci_postmean,
                   e_value=e_value)
end

# ╔═╡ 24b4a3d6-2e7d-4f84-bf84-6fe97b24e93a
DataFrame(τ = τs,
	      SLR = getproperty.(res_list, :e_value),
          Lfsr_CI = getproperty.(res_list, :ci_lfsr),
		  Postmean_CI = getproperty.(res_list, :ci_postmean))

# ╔═╡ 4c812df1-fc00-4f42-a50c-4d08ca5b576b
us = -3:0.01:3

# ╔═╡ 8925c810-b292-4dc6-ba4d-3e040d8b8689
_plots = [plot(us,
   [pdf.(res_list[j].floc_fit_lfsr.g1, us) pdf.(res_list[j].floc_fit_lfsr.g2, us)],
   title=L"\tau = %$(τs[j])", color = [:darkblue :purple],
   linealpha = [0.6 0.8], xguide=L"\mu", yguide=L"g(\mu)")
   for j in 1:4];

# ╔═╡ fdb0fc1a-2b8b-4d6c-b848-47d145308875
worst_case_plots = plot(_plots..., layout=(1,4),size=(900,200), legend=false)

# ╔═╡ 40d68d1a-f93f-45e6-8f0e-3c25af40c411
# savefig(worst_case_plots, "worst_case_priors.tikz")

# ╔═╡ 7fe7a76b-fe38-4019-b068-d471123d1c9a
postmean_ci_kde_locmix[findfirst(ts.==2.0)] #sanity check 1

# ╔═╡ 81fd9a91-35dc-48dc-bb79-f01ea110d952
lfsr_ci_kde_locmix[findfirst(ts.==2.0)] #sanity check 2

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Empirikos = "cab608d6-c565-4ea1-96d6-ce5441ba21b0"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
MosekTools = "1ec41992-ff65-5c91-ac43-2df89e9693a4"
PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"

[compat]
DataFrames = "~1.2.2"
Empirikos = "~0.4.4"
JuMP = "~0.21.9"
LaTeXStrings = "~1.2.1"
MosekTools = "~0.9.4"
PGFPlotsX = "~1.3.2"
Plots = "~1.21.2"
Setfield = "~0.7.1"
"""

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

[[AbstractFFTs]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "485ee0867925449198280d4af84bdb46a2a404d0"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.0.1"

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

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

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

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

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

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

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

[[BenchmarkTools]]
deps = ["JSON", "Logging", "Printf", "Statistics", "UUIDs"]
git-tree-sha1 = "42ac5e523869a84eac9669eaceed9e4aa0e1587b"
uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
version = "1.1.4"

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

[[CSV]]
deps = ["Dates", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode"]
git-tree-sha1 = "b83aa3f513be680454437a0eee21001607e5d983"
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
version = "0.8.5"

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

[[Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"

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

[[CodecBzip2]]
deps = ["Bzip2_jll", "Libdl", "TranscodingStreams"]
git-tree-sha1 = "2e62a725210ce3c3c2e1a3080190e7ca491f18d7"
uuid = "523fee87-0ab8-5b00-afb7-3ecf72e48cfd"
version = "0.7.2"

[[CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "ded953804d019afa9a3f98981d99b33e3db7b6da"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.0"

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

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

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

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

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

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

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

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

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

[[DataFrames]]
deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
git-tree-sha1 = "d785f42445b63fc86caa08bb9a9351008be9b765"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.2.2"

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

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

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

[[DefaultApplication]]
deps = ["InteractiveUtils"]
git-tree-sha1 = "fc2b7122761b22c87fec8bf2ea4dc4563d9f8c24"
uuid = "3f0dd361-4fe0-5fc6-8523-80b14ec94d85"
version = "1.0.0"

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

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

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

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

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

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

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

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

[[Empirikos]]
deps = ["CSV", "DataStructures", "Distributions", "Intervals", "JuMP", "KernelDensity", "LinearAlgebra", "LinearFractional", "MathOptInterface", "Optim", "ParameterJuMP", "QuadGK", "Random", "RecipesBase", "Reexport", "Setfield", "Statistics", "StatsBase", "UnPack"]
git-tree-sha1 = "6f38a107e365b57d2a8f7561dd6b8aca46a5f421"
uuid = "cab608d6-c565-4ea1-96d6-ce5441ba21b0"
version = "0.4.4"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[IniFile]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.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 = "61aa005707ea2cebf47c8d780da8dc9bc4e0c512"
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
version = "0.13.4"

[[Intervals]]
deps = ["Dates", "Printf", "RecipesBase", "Serialization", "TimeZones"]
git-tree-sha1 = "323a38ed1952d30586d0fe03412cde9399d3618b"
uuid = "d8418881-c3e1-53bb-8760-2df7ec849ed5"
version = "1.5.0"

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

[[IrrationalConstants]]
git-tree-sha1 = "f76424439413893a832026ca355fe273e93bce94"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.0"

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

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

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

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

[[JSONSchema]]
deps = ["HTTP", "JSON", "ZipFile"]
git-tree-sha1 = "b84ab8139afde82c7c65ba2b792fe12e01dd7307"
uuid = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
version = "0.3.3"

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

[[JuMP]]
deps = ["Calculus", "DataStructures", "ForwardDiff", "JSON", "LinearAlgebra", "MathOptInterface", "MutableArithmetics", "NaNMath", "Printf", "Random", "SparseArrays", "SpecialFunctions", "Statistics"]
git-tree-sha1 = "4f0a771949bbe24bf70c89e8032c107ebe03f6ba"
uuid = "4076af6c-e467-56ae-b986-b466b2749572"
version = "0.21.9"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[LinearFractional]]
deps = ["JuMP", "MacroTools", "MathOptInterface"]
git-tree-sha1 = "d6f7fc5da94fbc9b68a999eb4da32ef832e1d766"
uuid = "31851ddc-f9b7-5097-a470-69ef907d7682"
version = "0.7.4"

[[LogExpFunctions]]
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "3d682c07e6dd250ed082f883dc88aee7996bf2cc"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.0"

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

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

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

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

[[MathOptInterface]]
deps = ["BenchmarkTools", "CodecBzip2", "CodecZlib", "JSON", "JSONSchema", "LinearAlgebra", "MutableArithmetics", "OrderedCollections", "SparseArrays", "Test", "Unicode"]
git-tree-sha1 = "575644e3c05b258250bb599e57cf73bbf1062901"
uuid = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
version = "0.9.22"

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

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

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

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

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

[[Mocking]]
deps = ["ExprTools"]
git-tree-sha1 = "748f6e1e4de814b101911e64cc12d83a6af66782"
uuid = "78c3b35d-d492-501b-9361-3d52fe80e533"
version = "0.7.2"

[[Mosek]]
deps = ["Libdl", "Pkg", "Printf", "SparseArrays", "WinReg"]
git-tree-sha1 = "883be630ab4a25991037c2a2079d7170a5a8908e"
uuid = "6405355b-0ac2-5fba-af84-adbd65488c0e"
version = "1.1.3"

[[MosekTools]]
deps = ["MathOptInterface", "Mosek", "Printf"]
git-tree-sha1 = "56f7c254a9d3769bda929e05f1db2d19d8aa3375"
uuid = "1ec41992-ff65-5c91-ac43-2df89e9693a4"
version = "0.9.4"

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

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

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

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

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

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

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

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

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

[[Optim]]
deps = ["Compat", "FillArrays", "LineSearches", "LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "PositiveFactorizations", "Printf", "SparseArrays", "StatsBase"]
git-tree-sha1 = "7863df65dbb2a0fa8f85fcaf0a41167640d2ebed"
uuid = "429524aa-4258-5aef-a3af-852621145aeb"
version = "1.4.1"

[[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 = "4dd403333bcf0909341cfe57ec115152f937d7d8"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.1"

[[PGFPlotsX]]
deps = ["ArgCheck", "DataStructures", "Dates", "DefaultApplication", "DocStringExtensions", "MacroTools", "Parameters", "Requires", "Tables"]
git-tree-sha1 = "9c70cfd9f33384c7e9560f2918c4ef716e4ce652"
uuid = "8314cec4-20b6-5062-9cdb-752b83310925"
version = "1.3.2"

[[ParameterJuMP]]
deps = ["JuMP", "MathOptInterface", "MutableArithmetics", "SparseArrays"]
git-tree-sha1 = "a73cb3215747dc6d42a71efd760933c9209c3d2b"
uuid = "774612a8-9878-5177-865a-ca53ae2495f9"
version = "0.3.0"

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

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

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

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

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

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

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

[[PooledArrays]]
deps = ["DataAPI", "Future"]
git-tree-sha1 = "a193d6ad9c45ada72c14b731a318bedd3c2f00cf"
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
version = "1.3.0"

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

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

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

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

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

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

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

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

[[Ratios]]
deps = ["Requires"]
git-tree-sha1 = "7dff99fbc740e2f8228c6878e2aad6d7c2678098"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.1"

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

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

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

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

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

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

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

[[SentinelArrays]]
deps = ["Dates", "Random"]
git-tree-sha1 = "54f37736d8934a12a200edea2f9206b03bdf3159"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.3.7"

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

[[Setfield]]
deps = ["ConstructionBase", "Future", "MacroTools", "Requires"]
git-tree-sha1 = "fca29e68c5062722b5b4435594c3d1ba557072a3"
uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
version = "0.7.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", "LogExpFunctions", "OpenSpecFun_jll"]
git-tree-sha1 = "a322a9493e49c5f3a10b50df3aedaf1cdb3244b7"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "1.6.1"

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

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

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

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

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

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

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

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

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

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

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

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

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

[[TimeZones]]
deps = ["Dates", "Future", "LazyArtifacts", "Mocking", "Pkg", "Printf", "RecipesBase", "Serialization", "Unicode"]
git-tree-sha1 = "6c9040665b2da00d30143261aea22c7427aada1c"
uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53"
version = "1.5.7"

[[TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "216b95ea110b5972db65aa90f88d8d89dcb8851c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.6"

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

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

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

[[WinReg]]
deps = ["Test"]
git-tree-sha1 = "808380e0a0483e134081cc54150be4177959b5f4"
uuid = "1b915085-20d7-51cf-bf83-8f477d6f5128"
version = "0.3.1"

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

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

[[ZipFile]]
deps = ["Libdl", "Printf", "Zlib_jll"]
git-tree-sha1 = "c3a5637e27e914a7a445b8d0ad063d701931e9f7"
uuid = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"
version = "0.9.3"

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

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

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

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

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

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

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

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

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

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

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

# ╔═╡ Cell order:
# ╟─3cf2bafa-4bf4-11eb-3482-ff09ca17af71
# ╠═1fbdb6c6-4bf4-11eb-3aeb-9548bde2b1a5
# ╠═473d8a28-4bf4-11eb-0151-8b3f3d286eda
# ╠═17be2c0c-4bf5-11eb-25ca-cfe4e5fb5485
# ╠═acfc4fc0-4bf4-11eb-32dc-dfe1652ac006
# ╟─f4bd73b8-4bf4-11eb-3678-655227b0895b
# ╠═0731218a-4bf5-11eb-10f4-81241477b265
# ╠═0d36dbee-4bf5-11eb-3036-7bcf68579a46
# ╠═246264dc-4bf5-11eb-2f9d-b5c7d137a9b3
# ╠═4dd1f99a-4bf5-11eb-3691-9db09ab324df
# ╟─362effcc-4bf5-11eb-1d84-3133de3f4825
# ╠═5ad6b662-4bf5-11eb-24fb-d141933957ca
# ╠═605a545e-4bf5-11eb-3020-6d9c53e39a8e
# ╠═69e87366-4bf5-11eb-3fbb-8f7bf325d366
# ╠═750e2af0-4bf6-11eb-3374-1f224647d4e5
# ╟─aa99cc74-4bf6-11eb-2e3f-81de213db00d
# ╠═df1513be-4bf6-11eb-1b1c-fd650fd994fe
# ╠═c4bc3468-4bf4-11eb-1710-f7638d026b91
# ╠═bd7a5362-4bf4-11eb-1f2c-79ff3e915f89
# ╠═9b6b8f8a-4bf6-11eb-002d-7fa04ddde0d3
# ╠═68f0af78-8165-11eb-2a88-efd9f9743eec
# ╠═ce945cca-4bf6-11eb-29bc-4b2514ae395d
# ╠═e9e81b9c-4bf6-11eb-1c3c-d56076f6858b
# ╠═04c72ec6-4bf7-11eb-3265-5f69502b9f0b
# ╠═31bd322c-4bf7-11eb-007c-d7583730cd8e
# ╠═3d5b459c-4bf7-11eb-3825-6b75cc4099f3
# ╠═474bdc10-4bf7-11eb-0099-cdf3150001a2
# ╠═5fe96288-4bf7-11eb-1805-1f7f7815e035
# ╠═65d3b2de-4bf7-11eb-3ab5-a13a5b5556ef
# ╠═6ade8f74-4bf7-11eb-2b46-51436f6bf297
# ╠═7c0fd708-4bf7-11eb-12e0-45ecc7f9af7a
# ╠═85c63cc4-4bf7-11eb-2688-2b63ea65b2e7
# ╠═89a047c2-4bf7-11eb-3c79-15fe2fcdcb1c
# ╠═a262fe94-4bf7-11eb-1153-6f76128cbcd0
# ╠═622669fa-4bf8-11eb-08fd-a3bd67230729
# ╠═6930b1ae-4bf8-11eb-23c7-e5be40b7a283
# ╠═6fba4f94-4bf8-11eb-2177-87f38a9b73d2
# ╠═7c308bb4-4bf8-11eb-249a-0f6d933a530c
# ╠═8abdac16-4bf8-11eb-3b0d-a73d7b28bb7c
# ╠═eb851e8a-4bf8-11eb-353a-e5c394ae5294
# ╠═1e0db04c-4bf9-11eb-1bde-9dfa4f81f279
# ╠═2700eeda-4bf9-11eb-27ba-c5c6fe33980d
# ╠═2eba35aa-4bf9-11eb-1bf0-0be32d4bff85
# ╠═a30dce02-4bfa-11eb-1197-5b69f20af457
# ╠═716b8220-4bf9-11eb-1a28-33dbf08e138c
# ╠═9afa4b4a-4bf9-11eb-2a16-531b86e6b9a9
# ╠═9e06f2b8-4bf9-11eb-1bad-b5a1d26339ee
# ╠═a1ba1e12-4bf9-11eb-00c9-496602f4eb5c
# ╠═f2414706-4bfa-11eb-1654-9bdcc7418db8
# ╠═f7a59c42-4bfa-11eb-27df-cf611213fefc
# ╟─3e986c36-79a1-4ffd-9d2b-4bc96f2a5fa8
# ╠═c6758a61-c32f-4ec7-8336-085f6dadb96d
# ╠═3950ca34-f8eb-4450-985f-fdb47a1b6f8b
# ╠═e61af6d2-e4df-4c9a-bb2e-40e8e706f36d
# ╠═8a936d80-c61f-4d22-a1f1-c891d0063ee2
# ╠═d0c37eca-4c5e-42ba-970a-4d1fe27d33ea
# ╠═5ef18ef6-0d4a-4846-a1ec-8dfcc4168588
# ╠═506eb209-b761-48a2-8a31-0fe8c98a9802
# ╠═80f5d5de-0d75-4a6e-8143-8e3f3b48af43
# ╠═fb6464e6-3a4d-4609-9b96-37edc2a6021f
# ╠═c09e057e-24b2-4486-a497-e4908dcf2881
# ╠═c5ae00f4-c078-4ece-9ebf-90ea8e5b724a
# ╠═6501119c-338c-4931-a09e-38b5b3f8a81d
# ╠═a1b52f7a-4a53-485f-b246-fe008322c6a4
# ╠═24b4a3d6-2e7d-4f84-bf84-6fe97b24e93a
# ╠═4c812df1-fc00-4f42-a50c-4d08ca5b576b
# ╠═8925c810-b292-4dc6-ba4d-3e040d8b8689
# ╠═fdb0fc1a-2b8b-4d6c-b848-47d145308875
# ╠═40d68d1a-f93f-45e6-8f0e-3c25af40c411
# ╠═7fe7a76b-fe38-4019-b068-d471123d1c9a
# ╠═81fd9a91-35dc-48dc-bb79-f01ea110d952
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


const BARS = collect("▁▂▃▄▅▆▇█")

function unicode_histogram(data, nbins = 12)
    # @show data
    f = fit(Histogram, data, nbins = nbins)  # nbins: more like a guideline than a rule, really
    # scale weights between 1 and 8 (length(BARS)) to fit the indices in BARS
    # eps is needed so indices are in the interval [0, 8) instead of [0, 8] which could
    # result in indices 0:8 which breaks things
    scaled = f.weights .* (length(BARS) / maximum(f.weights) - eps())
    indices = floor.(Int, scaled) .+ 1
    return join((BARS[i] for i in indices))
end

function precise(df::DataFrame; digits = 2, depth = Inf, alpha = 0.11)
    d = DataFrame()
    d.param = names(df)
    d.mean = mean.(eachcol(df))
    d.std = std.(eachcol(df))
    d[:, "5.5%"] = quantile.(eachcol(df), alpha/2)
    d[:, "50%"] = quantile.(eachcol(df), 0.5)
    d[:, "94.5%"] = quantile.(eachcol(df), 1 - alpha/2)
    u = unicode_histogram.(eachcol(df))
    d.histogram = unicode_histogram.(eachcol(df))

    for col in ["mean", "std", "5.5%", "50%", "94.5%"]
        d[:, col] .= round.(d[:, col], digits = digits)
    end

    pretty_table(d, nosubheader = true, vlines = [0, 1, 7])
end


abstract AbstractMixer

type LinearMixer <: AbstractMixer
    c::Float64  # mixing weight
end

LinearMixer(;c=0.25) = LinearMixer(c)

Base.call(mixer::LinearMixer, rho_in::AbstractArray, rho_out::AbstractArray) = (1 - mixer.c)*rho_in + mixer.c*rho_out

type PulayMixer <: AbstractMixer
    n::Int  # number of densities to mix
    beta::Float64  # damping coefficient
    grid  # integration grid
    rho_in::Array{AbstractArray}
    R::Array{AbstractArray}  # residuals
end

PulayMixer(;n=3, beta=0.25, grid=nothing) = PulayMixer(n,beta,grid,[],[])

function Base.call(mixer::PulayMixer, rho_in::AbstractArray, rho_out::AbstractArray)
    push!(mixer.rho_in, rho_in)
    push!(mixer.R, rho_out - rho_in)

    if length(mixer.rho_in) > mixer.n
        shift!(mixer.rho_in)
        shift!(mixer.R)
    end

    n = length(mixer.rho_in)

    B = Array{Float64}(n+1,n+1)
    for i in 1:n
        for j in i:n
            B[i,j] = integrate(mixer.grid, mixer.R[i].*mixer.R[j])
        end
    end

    B[:,end] = -1
    B[end,end] = 0
    B = Symmetric(B)

    c = zeros(1,n+1)
    c[end] = -1

    a = squeeze(c/B,1)  # solve

    rho = zeros(rho_in)
    for i in 1:n
        rho += a[i].*(mixer.rho_in[i] + mixer.beta.*mixer.R[i])
    end

    rho
end


"""
    sparsemax(x; dims = 1)

[Sparsemax](https://arxiv.org/abs/1602.02068) turns input array `x`
into sparse probability distributions that sum to 1 along the dimensions specified by `dims`.

Similar to softmax, each dimension is considered independent. For a matrix input `x` it will
by default (`dims = 1`) treat it as a batch of vectors, with each column independent. Keyword
`dims = 2` will instead treat rows independently.

# Examples

```jldoctest
julia> sparsemax(reshape(1:15, 5,3) ./ 2) # dims=1
5×3 Matrix{Float64}:
 0.0   0.0   0.0
 0.0   0.0   0.0
 0.0   0.0   0.0
 0.25  0.25  0.25
 0.75  0.75  0.75

julia> sparsemax(reshape(1:15, 5, 3) ./ 20) # Scale matters
5×3 Matrix{Float64}:
 0.1   0.1   0.1
 0.15  0.15  0.15
 0.2   0.2   0.2
 0.25  0.25  0.25
 0.3   0.3   0.3

 julia> sparsemax(reshape(1:15, 5, 3) ./ 20 .+ [-20 0 20])
 5×3 Matrix{Float64}:
  0.1   0.1   0.1
  0.15  0.15  0.15
  0.2   0.2   0.2
  0.25  0.25  0.25
  0.3   0.3   0.3
```
"""
function sparsemax(x::AbstractArray; dims::Integer=1)
    n_dims = length(size(x))
    if n_dims < dims
        error_msg = "Dims ($dims) is larger than the array dimensions ($n_dims)."
        throw(DimensionMismatch(error_msg))
    end

    if isa(x, AbstractVector)
        z = _sort_vector(x; dims=dims)
    else
        z = sort(float(x); dims=dims, rev=true)
    end
    mask = _sparsemax_mask(z, dims)
    tausum = sum(z .* mask; dims)
    kay = sum(mask; dims)
    z = _relu.(x  .- (tausum .- 1) ./ kay)
end

function _sort_vector(x::AbstractVector; dims::Integer=1, rev=true)
    if dims == 1
        z = sort(float(x); rev=rev)
    elseif dims == 2
        z = x
    end
    return z
end

function _sparsemax_mask(z::AbstractArray, dim::Integer)
    acc = cumsum(z; dims=dim)
    if dim == 1
        acc .= 1 .+ axes(z,1) .* z .> acc
    elseif dim == 2
        acc .= 1 .+ axes(z,2)' .* z .> acc
    else
        # This isn't type-stable. Writing into `acc` ensures the whole function still is:
        cnt = reshape(axes(x, dim), ntuple(_->1, dim-1)..., :)
        acc .= 1 .+ cnt .* z .> acc
    end
    acc
end

_ifelse(p, x, y) = ifelse(p, promote(x, y)...)
_relu(x) = _ifelse(x>0, x, false)  # different gradient at zero

function ∇sparsemax(Δ::AbstractArray, y::AbstractArray; dims = 1)
    nonzeros = Δ.!=0.0
    out = Δ .* y
    total = sum(out .* nonzeros; dims=dims) / sum(nonzeros; dims=dims)
    out = nonzeros .* (out .- total)
 end

function rrule(::typeof(sparsemax), xs; dims=1)
    y = sparsemax(xs; dims=dims)
    sparsemax_pullback(Δ) = (NoTangent(), ∇sparsemax(unthunk(Δ), y; dims = dims))
    return y, sparsemax_pullback
 end


# Very basic setup, useful for testing
using DFTK
using LinearAlgebra
using BenchmarkTools

a = 10.26  # Silicon lattice constant in Bohr
lattice = a / 2 * [[0 1 1.];
                   [1 0 1.];
                   [1 1 0.]]
Si = ElementPsp(:Si, psp=load_psp("hgh/lda/Si-q4"))
atoms = [Si => [ones(3)/8, -ones(3)/8]]

model = model_LDA(lattice, atoms)
kgrid = [1, 1, 1]  # k-point grid (Regular Monkhorst-Pack grid)
Ecut = 15          # kinetic energy cutoff in Hartree -- can increase to make G_vectors larger (larger solve time)
basis = PlaneWaveBasis(model, Ecut; kgrid=kgrid)

@time scfres = self_consistent_field(basis, tol=1e-8) # 75.068789 seconds (138.55 M allocations: 8.145 GiB, 4.59% gc time, 24.68% compilation time)

# TODO try to rewrite for Zygote
# e.g. translate loops to dense arrays or maps (?)

function kinetic_energy(lattice, basis, ψ, occ)
    recip_lattice = 2π * inv(lattice')
    E = zero(Float64)
    kinetic_energies = [[sum(abs2, recip_lattice * (G + kpt.coordinate)) / 2
                         for G in  G_vectors(kpt)]
                        for kpt in basis.kpoints]
    for (ik, k) in enumerate(basis.kpoints)
        for iband = 1:size(ψ[1], 2)
            ψnk = @views ψ[ik][:, iband]
            E += (basis.kweights[ik] * occ[ik][iband]
                  * real(dot(ψnk, kinetic_energies[ik] .* ψnk)))
        end
    end
    E
end
kinetic_energy(lattice) = kinetic_energy(lattice, basis, scfres.ψ, scfres.occupation)

@time E = kinetic_energy(lattice)
@btime kinetic_energy(lattice) # 648.802 μs (7590 allocations: 1.67 MiB)

# stress := diff E wrt lattice

#===#
# Check results and compile times on first call
stresses = Dict()

# works fine
using ForwardDiff
@time stresses[:ForwardDiff] = ForwardDiff.gradient(kinetic_energy, lattice) # 3.627630 seconds (5.99 M allocations: 363.981 MiB, 5.08% gc time, 98.69% compilation time)

# works but long compile time and gives ComplexF64 results
# hypothesis: slow compilation due to loop (and generator) unrolling
using Zygote
@time stresses[:Zygote] = Zygote.gradient(kinetic_energy, lattice) # 61.094425 seconds (63.31 M allocations: 3.715 GiB, 3.85% gc time, 67.43% compilation time)

# works fine
using ReverseDiff
@time stresses[:ReverseDiff] = ReverseDiff.gradient(kinetic_energy, lattice) # 5.409118 seconds (9.60 M allocations: 516.091 MiB, 14.61% gc time, 89.56% compilation time)

# sanity check
using FiniteDiff
@time stresses[:FiniteDiff] = FiniteDiff.finite_difference_gradient(kinetic_energy, lattice) # 2.606210 seconds (2.87 M allocations: 232.911 MiB, 19.92% gc time, 99.19% compilation time)

stresses
# Dict{Any, Any} with 4 entries:
#   :ForwardDiff => [0.206717 -0.207215 -0.207228; -0.198914 0.209309 -0.20982; -0.197421 -0.208313 0.207815]
#   :FiniteDiff  => [0.206717 -0.207215 -0.207228; -0.198914 0.209309 -0.20982; -0.197421 -0.208313 0.207815]
#   :Zygote      => (ComplexF64[0.206717+2.92541e-19im -0.207215-1.57175e-19im -0.207228-7.86273e-19im; -0.198914+1.08911e-19im 0.209309+4.47104e-20im -0.20982-5.38442e-19im; -0.197421-6.72652e-19im -0.2…
#   :ReverseDiff => [0.206717 -0.207215 -0.207228; -0.198914 0.209309 -0.20982; -0.197421 -0.208313 0.207815]

@btime ForwardDiff.gradient(kinetic_energy, lattice) #   3.152 ms (   7681 allocations:  11.00 MiB)
@btime Zygote.gradient(kinetic_energy, lattice)      #  99.395 ms ( 358600 allocations: 129.91 MiB)
@btime ReverseDiff.gradient(kinetic_energy, lattice) # 278.207 ms (4301696 allocations: 158.10 MiB)
@btime FiniteDiff.finite_difference_gradient(kinetic_energy, lattice) # 10.901 ms (136658 allocations: 30.14 MiB)


using Revise
using Latexify
using DifferentialEquations
using DataFrames
using LaTeXStrings

revise()

ex = :(min(1,2))
latexify(ex)

"x/y" |> latexify
l = latexify("x/y")

join(1, ",")

f = @ode_def feedback begin
    dx = y/c_1 - x
    dy = x^c_2 - y
    end c_1 c_2

latexalign(f.syms, f.funcs)
latexify(f.syms, f.funcs)


using ArgParse, MathProgComplex, OPFInstances

function parse_commandline()
  s = ArgParseSettings()
  s.description = "Load the *.sdp files at the given location and start Mosel solve."
  @add_arg_table s begin
    "instance_path"
        help=".dat instance path"
        arg_type = String
        required = true
    "d"
        help="relaxation order"
        arg_type = Int
        required = true
    "logpath"
        help = "folder storing all output"
        arg_type = String
        required = true
    "relaxation_type"
        help = "either 0 (SOSRelaxation) or 1 (MomentRelaxation)"
        arg_type = Int
        required = true
  end
  return parse_args(s)
end

function main(args)
    input_params = parse_commandline()

    # input_params = Dict("instance_path"=>getinstancepath("Matpower", "QCQP", "case9"),
    #                     "d"=>1,
    #                     "logpath"=>joinpath("tltu", "tita"),
    #                     "relaxation_type"=>0)

    instance_path = input_params["instance_path"]
    d = input_params["d"]
    hierarchykind = :Real
    symmetries = DataType[]
    logpath = input_params["logpath"]
    pbsolved = input_params["relaxation_type"]==0 ? (:MomentRelaxation) : (:SOSRelaxation)

    instance_name = splitdir(instance_path)[2][1:end-4]
    mkpath(logpath)

    @printf("->  Launching %30s  %2d  %s\n", instance_name, d, logpath)

    ## Run functions once for precompilation...
    WB2_path = getinstancepath("Matpower", "QCQP", "WB2")
    problem_C, point = import_from_dat(WB2_path)
    problem = pb_cplx2real(problem_C)
    relax_ctx = set_relaxation(problem; hierarchykind=hierarchykind,
                                        d=1,
                                        params = Dict(:opt_outlev=>0,
                                                      :opt_outmode=>0,
                                                      :opt_solver=>:None))
    run_hierarchy(problem, relax_ctx; save_pbs=false)

    ## Build real problem
    problem_C, point = import_from_dat(instance_path)
    problem = pb_cplx2real(problem_C)

    ## Build relaxation context
    relax_ctx = set_relaxation(problem; hierarchykind=hierarchykind,
                                        d=d,
                                        symmetries=symmetries,
                                        params = Dict(:opt_outlev=>1,
                                                      :opt_outmode=>1,
                                                      :opt_outcsv=>1,
                                                    #   :opt_msk_maxtime=>2*3600,
                                                      :opt_pbsolved=>pbsolved,
                                                      :opt_solver=>:None,
                                                      :opt_outname=>joinpath(logpath, "momentsos.log"),
                                                      :opt_outcsvname=>joinpath(logpath, "momentsos_solve.csv")))
    relax_ctx.relaxparams[:pb_name] = instance_name

    run_hierarchy(problem, relax_ctx; save_pbs=false)

    final_output(relax_ctx)

end

main(ARGS)


using AutoDiff
#=
x=Variable(2.0)
y=Variable(4.0)

z=(x-1)^2+(y-3)^2
println(z)
minimize(z)
println("x: $(val(x))")
println("y: $(val(y))")

#same computation as above, vectorized
z=sum((Lift([Variable(2.0), Variable(5.0)])-[1.0,3.0]).^2)
println(z)
minimize(z)
println("x: $(val(x))")
println("y: $(val(y))")
=#

using MNIST
using Images,ImageView

N=60000
data=traindata()[1][:,1:N]/256
raw_labels=traindata()[2][1:N]
labels=zeros(Float64,(10,N))
for i in 1:length(raw_labels)
	labels[raw_labels[i]+1,i]=1.0
end

currdigit=0
function getdigit()
	global currdigit=(currdigit+1)%N
	data[:,currdigit+1]
end
function getlabel(digit)
	labels[:,currdigit+1]
end

digit=Call(getdigit,())
label=Call(getlabel,(digit,))

weights1=Variable(0.01*randn((10,784)))
biases1=Variable(0.01*randn((10,)))
function prediction(digit)
	layer1=weights1*digit.+biases1
	tmp=exp(layer1)
	tmp./sum(tmp)
end

begin #viewing
	function f(x)
		a=x-minimum(x)
		a/=maximum(a)
		grayim(transpose(reshape(a,(28,28))))
	end
	c = canvasgrid(4,5)
	function updateview()
		for i in 1:10
			view(c[i],f(val(weights1)[i,:]))
		end
	end
end

error=sum((prediction(digit)-label).^2)
running_mean=0
using ProfileView
minimize(error,delta=0.0001,its=10)
Profile.clear_malloc_data()
minimize(error,delta=0.0001,its=10000000,f=(it->begin
	global running_mean
	running_mean=0.9999*running_mean+0.0001*val(error)
	if it%1000==0
		println("Mean error: $(running_mean)")
		updateview()
	end
end
))
ProfileView.view()


#############################################################################
# L_BFGS.jl
# Implement the L_BFGS method to solve convex optimization of the form:
# minimize f(x) + g(x), where f(x) is the Lovasz extension of a submodular funciton.
#############################################################################

export L_BFGS

function L_BFGS(p::Problem,                    # the convex problem
                f::LovaszExtAtom;              # the lovasz extension
                x₀::AbstractArray = collect(1:length(get_v(f)[1])),  # the starting point
                m::Int = length(get_v(f)[1]),  # the number of kept iterations
                c₁::Float64 = 0.7,             # linesearch parameter
                c₂::Float64 = 0.9,             # linesearch parameter
                μ::Float64 = 0.9,              # linesearch shrink rate
                epsilon::Float64 = 1e-3,       # the stopping criteria of the algorithm
                max_iters::Int = 100)          # the maximal iteration time

  if length(get_v(p.objective + f)) != 1
    error("Cannot optimize functions with multiple variables.")
  end

  x = x₀                                              # the candidate
  objective = p.objective + f
  var = get_v(f)[1]
  n = length(var)
  s = Array{AbstractArray}(m)                         # the differences between candidates of neighbouring iterations
  y = Array{AbstractArray}(m)                         # the differences between gradients candidates of neighbouring iterations
  α = Array{Number}(m)
  ρ = Array{Number}(m)
  r = AbstractArray                                   # quasi_gradient
  z = AbstractArray                                   # descent direction
  λ = 1.0                                             # step size
  λ̃ = 1.0                                             # the λ producing the largest gap satisfying the wolfe condition
  β = 0
  decr = 0.0                                          # the decrement
  gap = 0.0
  gap_upper = 0.0
  check = false
  grad_conv = grad(p.objective)
  obj(λ) = evaluate(objective, x + λ*z)[1]
  gra(λ) = evaluate(grad_conv, x + λ*z) + greedy(f.func, x + λ*z)
  q = evaluate(grad_conv, x) + greedy(f.func, x)

  for k = 0:max_iters
    # println("k = $k")
    # println("norm(q) = $(norm(q))")
    if k > 1
    end
    if norm(q) < epsilon
      return x
      break
    else
      # lev_tol = norm(q)/(n^0.5)*0.01                  # the tolerance for level sets
      if k == 0
        r = q
      elseif k < m
        H = (dot(s[k], y[k]) / dot(y[k], y[k])) * eye(n)
        for i = k:-1:1
          α[i] = ρ[i] * dot(s[i], q)
          q -= α[i] * y[i]
        end
        r = H * q
        for i = 1:k
          β = ρ[i] * dot(y[i], r)
          r += s[i] * (α[i] - β)
        end
      else
        k̃ = mod(k-1, m) + 1
        H = (dot(s[k̃], y[k̃]) / dot(y[k̃], y[k̃])) * eye(n)
        for i = k:-1:k-m+1
          ĩ = mod(i-1, m) + 1
          α[ĩ] = ρ[ĩ] * dot(s[ĩ], q)
          q -= α[ĩ] * y[ĩ]
        end
        r = H * q
        for i = (k-m+1):k
          ĩ = mod(i-1, m) + 1
          β = ρ[ĩ] * dot(y[ĩ], r)
          r += s[ĩ] * (α[ĩ] - β)
        end
      end
      z = -r
      λ = 1
      q = evaluate(grad_conv, x) + greedy(f.func, x)
      obj0 = obj(0)
      decr = dot(q, z)
      # println("x = $x")
      # println("q = $q")
      # println("z = $z")
      # println("decr = $decr")
      if abs(decr) < epsilon
        return x
        break
      end
      while obj(λ) > (obj0 + c₁ * λ * decr)
        if λ < 1e-2
          error("Line search fail to terminate")
          return x
        end
        # println("λ = $λ")
        # println("cond1 = $(obj(λ) - (obj0 + c₁ * λ * decr))")
  		  λ *= μ
  	  end
      while dot(gra(λ), z) < c₂ * decr
        if λ < 1e-2
          error("Line search fail to terminate")
          return x
        end
        # println("λ = $λ")
        # println("cond2 = $(dot(gra(λ), z) - c₂ * decr)")
  		  λ *= μ
      end
      # λ̃ = copy(λ)
      # check, gap = level_detector(x + λ*z, lev_tol)
      # gap_upper = gap
      # while check == true && dot(gra(λ), z) >= c₂ * decr
      #   if gap_upper < gap
      #     λ̃ = λ
      #     gap_upper = gap
      #   end
      #   λ *= μ
      #   # println(λ)
      #   check, gap = level_detector(x + λ*z, lev_tol)
      # end
      # if dot(gra(λ), z) < c₂ * decr                   # the wolfe condition is violated, pick the λ that produces the largest gap while satisfying the wolfe condition
      #   λ = λ̃
      # end
      # println()
      # println("λ = $λ")
      # println()
      x += λ * z
      k̃ = mod(k, m) + 1                              # update new entries
      s[k̃] = λ * z
      q_new = evaluate(grad_conv, x) + greedy(f.func, x)
      y[k̃] = q_new - q
      ρ[k̃] = 1 / dot(y[k̃], s[k̃])
      q = q_new
    end
  end
end

function level_detector(x::AbstractArray, lev_tol::Float64 = 1e-2)
  w = sort(x)
  gap = lev_tol                                       # the tightest gap
  check = false
  for i = 1:(length(x)-1)
    if w[i+1] - w[i] < gap
      gap = w[i+1] - w[i]
      check = true
    end
  end
  return check, gap
end


# SPDX-License-Identifier: X11
# 2020-12-09
# Day 5, Part 2

const TOTAL = 128 * 8

function main()
  passes = readlines()
  seats = falses(TOTAL)

  for p ∈ passes
    seats[seatid(p)] = true
  end

  for i ∈ 2:TOTAL - 1
    seats[i - 1] && !seats[i] && seats[i + 1] && (println(i); return)
  end
end

function seatid(str::AbstractString)
  row = -1
  s = 0
  e = 127
  for (i, c) ∈ enumerate(str[1:7])
    c == 'F' ? e -= 2^(7 - i) : s += 2^(7 - i)
  end
  @assert s == e
  row = s

  col = -1
  s = 0
  e = 7
  for (i, c) ∈ enumerate(str[8:10])
    c == 'L' ? e -= 2^(3 - i) : s += 2^(3 - i)
  end
  @assert s == e
  col = s

  return row * 8 + col
end

main()


immutable ExponentialSampler <: Sampleable{Univariate,Continuous}
    scale::Float64
end

rand(s::ExponentialSampler) = s.scale * randexp()

immutable ExponentialLogUSampler <: Sampleable{Univariate,Continuous}
    scale::Float64
end

rand(s::ExponentialLogUSampler) = -s.scale * log(rand())


"This module contains all inner parts."
module Internal

export Problem, Options, solve

using Roots
using UnPack

"""
```
Problem(
    α::Function,
    β::Function,
    γ::Function,
    δ::Function,
    p::Function
    q::Function
    a::Float64,
    b::Float64,
    A::Float64,
    y₀::Float64,
    z₀::Float64,
)
```

A Cauchy problem for a linear-stiff system of two ordinary differentials equations.

Expects the problem in the form:

```
[L]  y'(x) = α(A) y(x) + β(A) z(x) + p(x,z(x))
[NL] z'(x) = γ(A) y(x) + δ(A) z(x) + q(x,y(x),z(x))
y(a) = y₀, z(a) = z₀
```

where [L] is a linear equation, and [NL] is a nonlinear equation. The interval is [a, b].

You can call `y(x)` in `q` as `yᵢ₊₁(x, zᵢ₊₁)`.

"""
struct Problem
    α::Function
    β::Function
    γ::Function
    δ::Function

    p::Function
    q::Function

    a::Float64
    b::Float64
    A::Float64

    y₀::Float64
    z₀::Float64
end

"""
`Options(n::Integer)`

Options to provide to the solver. Includes the number of nodes in the grid `n`.
"""
struct Options
    n::Integer
end

"The default set of options. Sets `n` to 1000."
DefaultOptions = Options(1000)

include("Functions/solve.jl")

end


"""
    evaluate_error(eq::Equation, scenario::Scenario, grid::Grid, t::Float64)

Prints out the L1/L2/L∞ integral norms of the error for
equation `eq`, scenario (with analytical solution) `scenario`, grid
`grid` at time `t`.
Error is defined as difference between analytical solution and numerical
approximation.
"""
function evaluate_error(eq::Equation, scenario::Scenario, grid::Grid, t::Float64)
    @assert is_analytical_solution(eq, scenario)
    l1_error = similar(grid.dofs, get_ndofs(eq))
    l2_error = similar(l1_error)
    linf_error = similar(l1_error)
    l1_error .= 0
    l2_error .= 0
    linf_error .= 0

    # TODO "Project solution to basis" = comp. average
    # Compare cell average with exact average

    #dg_order = size(grid.basis,1)
    dg_order = 1
    quad_order = 3
    quadpoints, quadweights = get_quadpoints(quad_order)
    #quad_order = max(dg_order + 2, 6)
    #quad_basis = Basis(quad_order, grid.basis.dimensions)
    number_of_quadpoints = length(quadpoints)

    for cell in grid.cells
        # Constant cell averages -> only one value
        for var=1:get_ndofs(eq)
            @views value = grid.dofs[var, cell.dataidx]
            for i=1:number_of_quadpoints
                for j=1:number_of_quadpoints
                    x = quadpoints[i]
                    y = quadpoints[j]
                    quadweight = quadweights[i] * quadweights[j]
                    weight = volume(cell) * quadweight
                    pxg, pyg = globalposition(cell, (x,y))
                    analytical = get_initial_values(eq, scenario, (pxg,pyg), t=t)
                    error = abs(value - analytical[var])
                    l1_error[var] += weight * error
                    l2_error[var] += weight * error^2
                    linf_error[var] = max(linf_error[var], error)
                end
            end
        end
    end

    l2_error .= sqrt.(l2_error)
    println("Errors for each variable.")
    println("Var\tL1\tL2\tL∞")
    for i=1:get_ndofs(eq)
        var_name = string(get_variable_name(eq,i))
        @printf "%s\t%15.6e\t%15.6e\t%15.6e\n" var_name l1_error[i] l2_error[i] linf_error[i]
    end

end


"""
Linear Algebra related graph functions.
Especially, methods for handling incidence matrixes [`IncMat`](@ref).
"""
module LinA
import SparseArrays: SparseMatrixCSC, sparse

const IncMat = SparseMatrixCSC{Float64,Int64}
const Edges = Vector{Tuple{Int, Int}}

"""
    is_incmat(::IncMat)

Check whether a matrix is a graph (oriented) edge-vertex incidence matrix.
"""
function is_incmat(d::IncMat)::Bool
    dt = IncMat(d')
    any(diff(diff(dt.colptr)) .!= 0) && return false
    any(dt.nzval[1:2:end] + dt.nzval[2:2:end] .!= 0) && return false
    return true
end

function edges_from_incmat(d::IncMat)
    m, n = size(d)
    head = Vector{Int}(undef, m)
    tail = Vector{Int}(undef, m)
    lam = Vector{Float64}(undef, m)
    k = Int(1)
    for i = 1:n
        for ci = d.colptr[i]:d.colptr[i+1]-1
            ei = d.rowval[ci]
            v = d.nzval[ci]
            lam[ei] = abs(v)
            if v > 0
                head[ei] = i
            else
                tail[ei] = i
            end
        end
    end
    return head, tail, lam
end

"""
    IncMat(edges, λ, n [, T = Int])

Create an incidence matrix from a list of edges, weights `λ` having `n` nodes.
The resulting matrix index will have type `T`.
"""
function IncMat(E::Edges,
                lam::Vector{Float64},
                n::Int,
                T = Int)::IncMat
    m = length(E)
    I = Vector{T}(undef, 2m)
    J = Vector{T}(undef, 2m)
    V = Vector{eltype(lam)}(undef, 2m)
    for (i, (u, v)) in enumerate(E)
        I[2i-1] = i
        J[2i-1] = u
        V[2i-1] = lam[i]
        I[2i-0] = i
        J[2i-0] = v
        V[2i-0] = -lam[i]
    end
    sparse(I, J, V, m, n)
end

end


import Base: -, +, *, /, ^, abs, abs2, sqrt, exp, exp2, expm1, exp10, log, log2,
    log1p, log10, sin, sinpi, cos, cospi, tan, asin, acos, atan, sinh, cosh,
    asinh, acosh, tanh, atanh, inv, floor, ceil, min, max, round, trunc, eps
export -, +, *, /, ^, abs, abs2, sqrt, exp, exp2, expm1, exp10, log, log2,
    log1p, log10, sin, sinpi, cos, cospi, tan, asin, acos, atan, sinh, cosh,
    asinh, acosh, tanh, atanh, inv, floor, ceil, min, max, round, trunc, eps

for f in (:-, :abs, :abs2, :sqrt, :exp, :exp2, :expm1, :exp10, :log, :log2,
          :log1p, :log10, :sin, :sinpi, :cos, :cospi, :tan, :asin, :acos, :atan,
          :sinh, :cosh, :asinh, :acosh, :tanh, :atanh, :inv, :floor, :ceil,
          :round, :trunc)
    @eval $f(a::NumberInterval) = NumberInterval($f(Interval(a)))
end

for f in (:+, :-, :*, :/, :^, :atan, :min, :max)
    @eval $f(a::NumberInterval, b::NumberInterval) =
        NumberInterval($f(Interval(a), Interval(b)))
end

# specialization necessary to avoid ambiguity
for t in (:Integer, :AbstractFloat, :Rational)
    @eval ^(a::NumberInterval, n::$t) = NumberInterval(Interval(a)^n)
end

round(a::NumberInterval, mode) = NumberInterval(round(Interval(a), mode))

eps(::Type{NumberInterval{T}}) where T = eps(T)
function eps(a::NumberInterval)
    _a = abs(a)
    return NumberInterval(eps(_a.lo), eps(_a.hi))
end


function estConvRate(residuals)
    #set up and solve least squares problem to estimate slope of convergence line
    n=size(residuals,1)
    A=zeros(n,2)
    A[:,1]=ones(n)
    A[:,2]=collect(0:n-1)

    #solve least squares Ax=residuals
    x=\(A,log.(residuals)/log(10))
    return x[2]
end

function linquad(M,D,K)

    #A=[-D -K; eye(size(M,1)) zeros(size(M))]
    #B=[M zeros(size(M)); zeros(size(M)) eye(size(M,1))]

    A=[-D -K; -K zeros(size(M))]
    B=[M zeros(size(M)); zeros(size(M)) -K]

    #A=[-K zeros(size(M)); zeros(size(M)) M]
    #B=[D M; M zeros(size(M))]

    return (A,B)
end

#get left and right eigenvectors of generalized, nonsymmetric eigenvalue problem
function nseig(A,B)
    if(typeof(A)!=Array{ComplexF64,2})
        A=convert(Array{ComplexF64,2},A)
    end

    if(typeof(B)!=Array{ComplexF64,2})
        B=convert(Array{ComplexF64,2},B)
    end

    alpha,beta,vl,vr=LinearAlgebra.LAPACK.ggev!('V','V',A,B)

    return vl,alpha./beta,vr
end

#trapezoidal quadrature rule
function trapezoidal(nc)
    points=zeros(nc)
    weights=zeros(nc)

    a=-1.0
    b=1.0
    dx=(b-a)/(nc)
    for i in 1:nc
        points[i]=a+dx*(i-1)
        weights[i]=(b-a)/(nc+1)
    end

    return (points,weights)
end

function getRealSpurious(lest,resnorms,emid,ra,rb; inEps=1e-2)
#get distances of estimated eigenvalues from middle of contour:
	#have to rescale the approximate eigenvalues to adjust for the fact that we are using an ellipse and not a circle
	#more complicated contours will require a different approach
	lestdif=abs.(real(lest.-emid)/abs.(ra)+im*imag(lest.-emid)/abs.(rb))
	m0=size(lest,1)
	ninside=0

    p=sortperm(resnorms)

	s=Array{Int64,1}() #indices of eigenvalues inside contour
	spurious=Array{Int64,1}() #indices of spurious eigenvalues inside contour
	other=Array{Int64,1}() #stuff outside contour

	for k in 1:m0
	    if(lestdif[k]<=1.0 && resnorms[k]<inEps)
	        ninside=ninside+1
	        push!(s,k)
	    elseif(lestdif[k]<=1.0 && !(resnorms[k]<inEps))
	        push!(spurious,k)
	    elseif (!(lestdif[k]<=1.0))
	        push!(other,k)
	    end
	end

    return s,spurious,other
end

#find maximum residual inside contour
function getMaxResInside(lest,x,res,emid,ra,rb;inEps=1e-2, getIndices=false, getSpurious=false, set_nin=false)
#get distances of estimated eigenvalues from middle of contour:
	#have to rescale the approximate eigenvalues to adjust for the fact that we are using an ellipse and not a circle
	#more complicated contours will require a different approach
	lestdif=abs.(real(lest.-emid)/abs.(ra)+im*imag(lest.-emid)/abs.(rb))
	(n,m0)=size(x)
	ninside=0

	resnorms=zeros(m0)
    for i in 1:m0
        resnorms[i]=norm(res[:,i])/norm(x[:,i])
    end

    p=sortperm(resnorms)

	s=Array{Int64,1}() #indices of eigenvalues inside contour
	spurious=Array{Int64,1}() #indices of spurious eigenvalues inside contour

	for k in 1:m0
	    if(lestdif[k]<=1.0 && resnorms[k]<inEps)
	        ninside=ninside+1
	        push!(s,k)
	    end
	    if(lestdif[k]<=1.0 && !(resnorms[k]<inEps))
	        push!(spurious,k)
	    end
	end

    maxres=0.0
	if (set_nin!=false)
	    maxres=resnorms[set_nin]
    else
        if(ninside==0)
            maxres=maximum(resnorms)
        else
            for k in 1:m0
                if(lestdif[k]<=1.0 && resnorms[k]<inEps) #using 1.0 as the radius because we rescaled everything when forming lestdif
                   tmp=resnorms[k]#norm(res[:,k])/norm(x[:,k])
                   if(tmp>maxres)
                        maxres=tmp
                   end
                end
            end
        end
    end

    #println("50th residual=$(resnorms[p[50]])")

    if(getIndices & !(getSpurious))
        return maxres,ninside,s
    elseif (getIndices & (getSpurious))
        return maxres,ninside,s,spurious
    else
        return maxres,ninside
    end
end

function getInsideIndex(lest,emid,ra,rb)

    s=Array{Int64,1}()
    m0=size(lest,1)

    lestdif=abs.(real(lest.-emid)/abs.(ra)+im*imag(lest.-emid)/abs.(rb))

    for k in 1:m0
        if(lestdif[k]<=1.0) #using 1.0 as the radius because we rescaled everything when forming lestdif
           push!(s,k)
        end
    end

    return s
end

function getLock(lest,x,res,emid,ra,rb,eps)
#get distances of estimated eigenvalues from middle of contour:
	#have to rescale the approximate eigenvalues to adjust for the fact that we are using an ellipse and not a circle
	#more complicated contours will require a different approach
	lestdif=abs.(real(lest.-emid)/abs.(ra)+im*imag(lest.-emid)/abs.(rb))
	(n,m0)=size(x)
	ninside=0
	for k in 1:m0
	    if(lestdif[k]<=1.0)
	        ninside=ninside+1
	    end
	end

    resnorms=zeros(m0)
    for i in 1:m0
        resnorms[i]=norm(res[:,i])/norm(x[:,i])
    end

    p=sortperm(resnorms)

    locked=Array{Int64,1}()

    maxres=0.0
    for k in 1:m0
        if(lestdif[k]<=1.0 && resnorms[k]<=eps) #using 1.0 as the radius because we rescaled everything when forming lestdif
            push!(locked,k)
        end
    end

    #println("50th residual=$(resnorms[p[50]])")

    return locked
end

function getNotLock(lest,x,res,emid,ra,rb,eps)

    resnorms=zeros(m0)
    for i in 1:m0
        resnorms[i]=norm(res[:,i])/norm(x[:,i])
    end

    notlocked=Array{Int64,1}()

    maxres=0.0
    for k in 1:m0
        if(resnorms[k]>eps) #using 1.0 as the radius because we rescaled everything when forming lestdif
            push!(notlocked,k)
        end
    end

    #println("50th residual=$(resnorms[p[50]])")

    return notlocked
end

#solve reduced quadratic nonlinear problem with linearization
#select the m0 solutions that are closest to the center of the contour
function Quadrrsolve(Q,M,D,K,emid,ra,rb)
        (n,m0)=size(Q)
        #rayleigh ritz
        Mq=Matrix(Q'*(M*Q))
        Dq=Matrix(Q'*(D*Q))
        Kq=Matrix(Q'*(K*Q))

        #solve projected problem
        (Aq,Bq) = linquad(Mq,Dq,Kq)
        lest,xest=eigen(Matrix(Aq),Matrix(Bq))

        #get eigenvectors from linearization
        xall=Q*(xest[m0+1:2*m0,:])

	    #get distances of estimated eigenvalues from middle of contour:
	    #have to rescale the approximate eigenvalues to adjust for the fact that we are using an ellipse and not a circle
	    #more complicated contours will require a different approach
	    lestdif=abs.(real(lest.-emid)/abs.(ra)+im*imag(lest.-emid)/abs.(rb))

        #sort eigenpairs based on those distances:
        p=sortperm(lestdif)

        #take only the eigenpairs closest to the contour center:
        x=xall[:,p[1:m0]]
        lest=lest[p[1:m0]]
        return (lest,x)
end

#Beyn's method for nonlinear problems
#TinvApp = function for applying T^-1 to matrices
#Tapp=T(z)
function beynLoop(Tf,V,ncmax,emid,ra,rb,eps)
    (n,m0)=size(V)

    l=zeros(ComplexF64,m0)
    x=zeros(ComplexF64,n,m0)

    for nc in 1:ncmax
        (l,x)=beyn(Tf,V,nc,emid,ra,rb)
        R=zeros(ComplexF64,n,m0)
        for i in 1:m0
            R[:,i]=Tf(l[i])*x[:,i]
        end
        res,ninside=getMaxResInside(l,x,R,emid,ra,rb)
        println("---Beyn cp $nc  $res")
        if(res<=eps)
            return (l,x)
        end
    end

    return (l,x)
end

function beyn(Tf,V::Array{ComplexF64,2},nc,emid,ra,rb; verbose=false)
    (n,m0)=size(V)

    (gk,wk)=trapezoidal(nc) #contour integral quadrature rule
    offset=pi/nc #offset angle of first quadrature point; makes sure it isn't on real axis for hermitian problems

    A0=zero(V)
    A1=zero(V)
    for k in 1:nc
	#for k in 1:nc
	    if(verbose)
	        println("Beyn system $k of $nc")
	    end
	    theta=gk[k]*pi+pi+offset
	    z=emid+((ra+rb)/2)*exp(im*theta)+((ra-rb)/2)*exp(-1.0*im*theta)

        Qk=zeros(ComplexF64,n,m0)
        Tfz=Tf(z)

        Qk=\(Tfz,V)

	    A0=A0+wk[k]*(((ra+rb)/2)*exp(im*theta)-((ra-rb)/2)*exp(-1.0*im*theta))*Qk
	    A1=A1+wk[k]*(((ra+rb)/2)*exp(im*theta)-((ra-rb)/2)*exp(-1.0*im*theta))*z*Qk
    end

    (v0,s0,w0) = svd(A0)

    Av=v0'*A1*w0*diagm(0 => 1 ./ s0)

    l,xv=eigen(Av)

    return (l,v0*xv)
end

function ibeyn(Tf,V::Array{ComplexF64,2},alpha,isMaxit,nc,emid,ra,rb; verbose=false)
    (n,m0)=size(V)

    (gk,wk)=trapezoidal(nc) #contour integral quadrature rule
    offset=pi/nc #offset angle of first quadrature point; makes sure it isn't on real axis for hermitian problems

    A0=zeros(V)
    A1=zeros(V)
    for k in 1:nc
	    if(verbose)
	        println("Beyn system $k of $nc")
	    end
	    theta=gk[k]*pi+pi+offset
	    z=emid+((ra+rb)/2)*exp(im*theta)+((ra-rb)/2)*exp(-1.0*im*theta)

        Qk=zeros(ComplexF64,n,m0)
        Tfz=Tf(z)

        #if(typeof(Tfz)==SparseMatrixCSC{Complex{Float64},Int64})
        #    Qk=\(Tfz,V)
        #else
        #    Qk=\(Tfz,V)
        #end

        for i in 1:m0
            #Qk[:,i]=bicgstabl(Tfz,V[:,i],1,max_mv_products=isMaxit,tol=alpha,initial_zero=true,log=false)
            #Qk[:,i]=gmres(Tfz,V[:,i],restart=isMaxit,tol=alpha,initially_zero=true,maxiter=isMaxit,log=false)
            Qk[:,i]=minres(Tfz,V[:,i],tol=alpha,initially_zero=true,maxiter=isMaxit,log=false)
        end

	    A0=A0+wk[k]*(((ra+rb)/2)*exp(im*theta)-((ra-rb)/2)*exp(-1.0*im*theta))*Qk
	    A1=A1+wk[k]*(((ra+rb)/2)*exp(im*theta)-((ra-rb)/2)*exp(-1.0*im*theta))*z*Qk
    end

    (v0,s0,w0) = svd(A0)

    Av=v0'*A1*w0*diagm(1 ./ s0)

    (l,xv)=eigen(Av)

    return (l,v0*xv)
end

function beynscan(emin,emax,ndiv,Tf,nc,n,m0; verbose=false)

    eigs=Array{ComplexF64,1}()
    resvals=Array{ComplexF64,1}()

    edges=linspace(emin,emax,ndiv+1)
    x0=rand(ComplexF64,n,m0)

    for i in 1:ndiv
        if(verbose)
            println("Div $i of $ndiv")
        end
        emid=(edges[i]+edges[i+1])/2.0
        ra=(edges[i]-edges[i+1])/2.0
        rb=ra

        (lest,xest)=beyn(Tf,x0,nc,emid,ra,rb)

        res=zeros(x0)
        for j in 1:m0
            res[:,j]=Tf(lest[j])*xest[:,j]
        end
        (maxres,ninside,insideIndices)=getMaxResInside(lest,xest,res,emid,ra,rb;getIndices=true)

        for j in 1:ninside
            push!(eigs,lest[insideIndices[j]])
            tmp=norm(res[:,insideIndices[j]])/norm(xest[:,insideIndices[j]])
            push!(resvals,tmp)
            if(verbose)
                println("   $(lest[insideIndices[j]])   $tmp")
            end
        end
    end

    return eigs,resvals
end

function trapezoidalCont(nc)
    offset=pi/nc
    a=offset
    b=2*pi+offset

    dx=(b-a)/nc

    weights=zeros(nc)
    points=zeros(nc)

    weights[1]=dx
    points[1]=a
    for i in 2:nc
        points[i]=points[i-1]+dx
        weights[i]=dx
    end

    return (points,weights)
end


@inline function cos_kernel(::Union{NS,MV}, x::MCNoGrad, z::Interval{Float64},
                            cv_tp1::Float64, cv_tp2::Float64, cc_tp1::Float64, cc_tp2::Float64)
    xL = x.Intv.lo;    xU = x.Intv.hi;    zL = z.lo;    zU = z.hi
    eps_min, eps_max = cos_arg(xL, xU)
    mcc, cci = mid3(x.cc, x.cv, eps_max)
    mcv, cvi = mid3(x.cc, x.cv, eps_min)
    cc, dcc, cc_tp1, cc_tp2 = cc_cos(mcc, xL, xU, cc_tp1, cc_tp2)
    cv, dcv, cv_tp1, cv_tp2 = cv_cos(mcv, xL, xU, cv_tp1, cv_tp2)
    if zL > zcv
        cvi = 3
        dcv = 0.0
    end
    if zU < zcc
        cci = 3
        dcc = 0.0
    end
    return MCNoGrad(cv, cc, y, x.cnst), cvi, cci, dcv, dcc, cv_tp1, cc_tp1, cv_tp1, cc_tp2
end
@inline function cos(::ANYRELAX, x::MCNoGrad)
    y, _, _, _, _, _, _, _, _, = cos_kernel(x, cos(x.Intv), Inf, Inf, Inf, Inf)
    return y
end
function sin_kernel(::ANYRELAX, x::MCNoGrad, y::Interval{Float64},
                    cv_tp1::Float64, cv_tp2::Float64,
                    cc_tp1::Float64, cc_tp2::Float64)
    cos_kernel(x-pi/2.0, y, cv_tp1, cv_tp2, cc_tp1, cc_tp2)
end
function sin(::ANYRELAX, x::MCNoGrad)
    y, _, _, _, _ = sin_kernel(x, sin(x.Intv), Inf, Inf, Inf, Inf)
    return y
end


using Distributions, LinearAlgebra
using UnicodePlots

# Print out the thread count
@info "" Threads.nthreads()

# Utility function
u(X, γ, β) = (1 - exp(-γ * X'β)) / γ

# Single draw of X, gamma, beta, and u
function single_draw(n)
    X = rand(MvNormal(ones(n), 0.25*I))
    gamma = rand(Exponential(0.05))
    beta = rand(MvNormal(ones(n), 0.5*I))
    return u(X, gamma, beta)
end

# Serial simulation
function simulate(n, n_draws)
    draws = zeros(n_draws)

    for i in 1:n_draws
        draws[i] = single_draw(n)
    end

    return draws
end

# Simulation using a lock
function simulate_threads(n, n_draws)
    draws = zeros(n_draws)

    Threads.@threads for i in 1:n_draws
        draw = single_draw(n)
        draws[i] = draw
        # lock(drawlock) do
        #     draws[i] = draw
        # end
    end

    return draws
end

n = 1000
n_draws = 100_000
@time draws1 = simulate(n, n_draws)
@time draws2 = simulate_threads(n, n_draws)

println("Howdy")

histogram(draws1) |> display
histogram(draws2) |> display


using MAT
import sbp
datafile=ARGS[1]

vars = matread(datafile)

nx = vars["x"]
p = vars["p"]
v = vars["v"]
qp = vars["q_p"]
qv = vars["q_v"]
Fp = vars["Fp"]
Fv = vars["Fv"]
qFp = vars["q_Fp"]
qFv = vars["q_Fv"]

header = [ "Nx", "p", "v",
           "rate p", "rate v",
          "Fp", "rate Fp",
          "Fv", "rate Fv"]
variables = [
             nx,
             round.(log10.(p), sigdigits=4),
             round.(qp, sigdigits=4),
             round.(log10.(v), sigdigits=4),
             round.(qv, sigdigits=4),
             round.(log10.(Fp), sigdigits=4),
             round.(qFp, sigdigits=4),
             round.(log10.(Fv), sigdigits=4),
             round.(qFv, sigdigits=4),
             ]
print(join(sbp.Table.latex(header, variables)))


using FeynmanDiagram
using Lehmann
using Test, LinearAlgebra, Random, StaticArrays, Printf, Parameters, Documenter
using AbstractTrees

# @testset "doctest" begin
#     DocMeta.setdocmeta!(FeynmanDiagram, :DocTestSetup, :(using FeynmanDiagram); recursive = true)
#     doctest(FeynmanDiagram)
# end

include("common.jl")
include("diagram_tree.jl")
include("expression_tree.jl")
include("parquet_builder.jl")


# can we write a function adjusting the states so that process becomes monotone?
# resulting tree should be very close (in nested distance) to original process

#Example 1
trr1 = Tree([1,2,2,2]); trr2 = Tree([1,2,2,2]);
trr1.state = [0,0,0,0,0,0,0,1,3,20,40,2,4,21,41];
trr2.state = [0,0,0,0,0,0,0,1,21,3,41,2,20,4,40];

trr1.probability = [1.0,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5];
trr2.probability = trr1.probability;

nestedWasserstein(trr1,trr2,1.0)      # supposed to be 8.75

#Example 2
trr1 = Tree([1,2,4,1]); trr2 = Tree([1,2,4,1]);
trr1.state = [0,0,0,0,0,0,0,0,0,0,0,1,3,20,40,2,4,21,41];
trr2.state = [0,0,0,0,0,0,0,0,0,0,0,1,21,3,41,2,20,4,40];

trr1.probability = [1.0,0.5,0.5,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0];
trr2.probability = trr1.probability;

nestedWasserstein(trr1,trr2,1.0)

# Example 3

trr1 = Tree([1,1,2]); trr2 = Tree([1,2,1]);
trr1.state = [2,2,3,1];
trr2.state = [2,2,2,3,1];

trr1.probability = [1.0,1.0,0.3,0.7];
trr2.probability = [1.0,0.3,0.7,1.0,1.0];

nestedWasserstein(trr1,trr2,1.0)


using RipQP, LinearOperators, LLSModels, NLPModelsModifiers, QPSReader, QuadraticModels, Quadmath
using DelimitedFiles, LinearAlgebra, MatrixMarket, SparseArrays, Test

qps1 = readqps("QAFIRO.SIF") #lower bounds
qps2 = readqps("HS21.SIF") # low/upp bounds
qps3 = readqps("HS52.SIF") # free bounds
qps4 = readqps("AFIRO.SIF") # LP
qps5 = readqps("HS35MOD.SIF") # fixed variables

Q = [
  6.0 2.0 1.0
  2.0 5.0 2.0
  1.0 2.0 4.0
]
c = [-8.0; -3; -3]
A = [
  1.0 0.0 1.0
  0.0 2.0 1.0
]
b = [0.0; 3]
l = [0.0; 0; 0]
u = [Inf; Inf; Inf]

include("solvers/test_augmented.jl")
include("solvers/test_newton.jl")
include("solvers/test_normal.jl")

include("test_multi.jl")
include("test_alternative_methods.jl")
include("test_alternative_problems.jl")