import Images
import TestImages
import ImageMetadata
import ImageAxes
import ImageDraw
import ImageView
import ImageTransformations
import ImageFiltering

image2Filter = TestImages.testimage("lighthouse")
#add noise to image
noiseAddition = Images.channelview(image2Filter)
noiseAddition = eltype(noiseAddition).(clamp.(noiseAddition.+ randn.() .* 0.1, 0, 1))
noisyImage = Images.colorview(Images.RGB, noiseAddition)

image2Use = Images.Gray.(noisyImage)

ImageView.imshow(image2Use)
#sigma = 0.8
#gauss = ImageFiltering.KernelFactors.gaussian(sigma)
#gaussKernel = kernelfactors((gauss, gauss))

function bilateralFunction( imageWindow )
    std_spatial = 8.0
    std_pixelVal = 0.4

    normFactor_space = 1 / (2* pi * std_spatial)
    normFactor_pixelVal = 1 /(2 * pi * std_pixelVal)

    filteredValue = 0.0
    filteredNormFactor = 0.0
    centerRowIndex = ceil(Int, length(axes(imageWindow, 1)) / 2)
    centerColIndex = ceil(Int, length(axes(imageWindow, 2)) / 2)

    for rowIndex = axes(imageWindow, 1)
        for colIndex = axes(imageWindow, 2)
            spatialDistance = abs2(rowIndex - centerRowIndex ) + abs2(colIndex - centerColIndex)
            pixelDistance   = abs(imageWindow[rowIndex, colIndex] - imageWindow[centerRowIndex,centerColIndex] )

            gauss_spatial   = normFactor_space * exp(spatialDistance / (2 * abs2(std_spatial)))
            gauss_pixel     = normFactor_pixelVal * exp(pixelDistance / (2 * abs2(std_pixelVal)))

            filteredValue +=  gauss_spatial * gauss_pixel *  imageWindow[rowIndex,colIndex]
            filteredNormFactor += gauss_spatial * gauss_pixel
        end
    end

    filteredValue = filteredValue / (filteredNormFactor)
    return filteredValue
end

prova = [5,5]
filteredImage = ImageFiltering.MapWindow.mapwindow(bilateralFunction, image2Use,prova)

ImageView.imshow(filteredImage)


using Distributions, Random

@testset "test Gamma kde function" begin
    res = DualOptimalFiltering.create_gamma_kde_mixture_parameters_one_β([1,4,6])
    for i in eachindex(res[1])
        @test res[1][i] ≈ [1.46703, 2.86814, 3.80221][i] atol=10^(-5)
    end
    @test res[2] ≈ 0.4670348611479834 atol=10^(-10)
    res = DualOptimalFiltering.create_gamma_kde_mixture_parameters([1,4,6])
    @test length(res[1]) == length(res[2])
end;

@testset "test Dirichlet kde function" begin
    Random.seed!(0);
    xdata = rand(Dirichlet([0.3,5.,2.3]), 5)'
    @test_nowarn DualOptimalFiltering.create_Dirichlet_kde_mixture_parameters(xdata)
    xdata_list = [xdata[i,:] for i in 1:size(xdata,1)]
    @test_nowarn DualOptimalFiltering.create_Dirichlet_kde_mixture_parameters(xdata_list)
end;


module OptimizationAlgorithms
using LinearAlgebra

# principle of this package:
# reduce optimization problems to fixed point iterations
# to this end, design fixed point operator f! and stopping rule isfixed

######################## General Fixed Point Algorithm #########################
# IDEA: allocating (for immutable types), via 0D array?
# attempts to find a fixed point of f! by iterating f! on x
# in light of ode's, this could be a gradient flow
# general enough: iterate! - ?
# f! should be a fixed point operator, so ∃x s.t. x = f!(x)
function fixedpoint!(f!, x, isfixed)
    t = 1
    while true
        x = f!(x, t)
        t += 1
        isfixed(x, t) && break
    end
    x, t
end

# using default stopping criterion
fixedpoint!(f!, x) = fixedpoint!(f!, x, StoppingCriterion(x))

# # TODO:
# # f!(x, t) should return both x and y for generality with scalar case
# this is not a problem for Directions, but for Updates
# either rewrite update! to do this, thereby breaking it's use in fixedpoint!,
# or write new function update_evaluate!()
# function optimize!(f!, x, isfixed)
#     t = 0
#     while true
#         x, y = f!(x, t)
#         t += 1
#         isfixed(x, y, t) && break
#     end
#     x, y, t
# end
# optimize!(f!, x) = optimize!(f!, x, StoppingCriterion(x))

########################### Stopping Criterion ##################################
# IDEA: have input output be single argument as tuple?
# abstract type StoppingCriterion{T} end
mutable struct StoppingCriterion{T, S}
    x::T # holds last value of parameters
    dx::S # minimum absolute change in parameters x for termination
    rx::S # minimum relative change in parameters x for termination

    y::S # holds last function value
    dy::S
    ry::S

    maxiter::Int # maximum iterations
    verbose::Bool
    function StoppingCriterion(x, y::Real = Inf; dx::Real = 1e-6, rx::Real = 0.,
        dy::Real = 1e-6, ry::Real = 0., maxiter::Int = 1024, verbose::Bool = false)
        new{typeof(x), typeof(y)}(copy(x), dx, rx, y, dy, ry, maxiter, verbose)
    end
end

(T::StoppingCriterion)(x) = input_criterion!(T, x)
function (T::StoppingCriterion)(x, t::Integer)
    T.verbose && println("in iteration $t:")
    1 < t && (input_criterion!(T, x) || T.maxiter < t)
end
function (T::StoppingCriterion)(x, y::Real, t::Integer)
    T.verbose && println("in iteration $t:")
    1 < t && (input_criterion!(T, x) || output_criterion!(T, y) || T.maxiter < t)
end

function input_criterion!(T::StoppingCriterion, x::Union{Real, AbstractVector})
    any(isnan, x) && error("x contains NaN: x = $x")
    dx = norm(difference(x, T.x))
    rx = dx / norm(x)
    if T.verbose
        println("absolute change in x = $dx")
        println("relative change in x = $rx")
    end
    isfixed = dx < T.dx || rx < T.rx
    if x isa Real
        T.x = x
    else # AbstractVector
        T.x .= x
    end
    return isfixed
end
function output_criterion!(T::StoppingCriterion, y::Real)
    isnan(y) && error("y = NaN")
    dy = abs(y - T.y)
    ry = dy / abs(y)
    if T.verbose
        println("absolute change in y = $dy")
        println("relative change in y = $ry")
    end
    isfixed = dy < T.dy || ry < T.ry
    T.y = y
    return isfixed
end

######################## Canonical Descent Directions ##########################
# abstract type FixedPointIterator{T} end # makes sense as long as we stick to optimization
abstract type Update{T} end # <: FixedPointIterator{T} end
abstract type Direction{T} <: Update{T} end
# NOTE: all directions are decreasing unless a negative step size is chosen

# update functor
(D::Update)(x, t::Int) = update!(D, x, t)
(D::Update)(x) = update!(D, x)

# direction functor
(D::Direction)(x, t::Int) = direction(D, x) # since directions do not depend on time
(D::Direction)(x) = direction(D, x)

update!(D::Update, x, t::Int) = update!(D, x)
update!(D::Direction, x) = (x .+= D(x))
update!(D::Direction, x, t::Int) = (x .+= D(x, t))

# converting a direction to an update
update!(D::Direction) = (x, t::Int) -> (x .+= D(x, t))
fixedpoint!(D::Direction, x, isfixed) = fixedpoint!(update!(D), x, isfixed)

function objective end # returns objective function
objective(D::Direction, x) = D.f(x)
objective(D::Direction) = x->objective(D, x)

const value = objective

function direction end # returns direction
direction(D::Direction, x) = valdir(D, x)[2]
# direction(D::Direction, x, t::Int) = valdir(D, x)[2]

# calculates direction and value at the same time
# value_direction(D::Direction, x, t::Int) = valdir(D::Direction, x)
value_direction(D::Direction) = x -> valdir(D, x)
const valdir = value_direction

################################################################################
include("util.jl")
include("descentdirections.jl")
include("gaussnewton.jl")
include("descentupdates.jl")
include("stochastic.jl")
include("ode.jl")
include("stepsize.jl")
include("submodular.jl")

end # Optimization


@testset "minimal_intersection_test" begin

    @test intersect(interval(1.0,3.0), interval(2.1,4.0)) === Interval(2.1,3.0)

    @test intersect(interval(1.0,3.0), interval(3.0,4.0)) === Interval(3.0,3.0)

    @test intersect(interval(1.0,3.0), emptyinterval()) === emptyinterval()

    @test intersect(entireinterval(), emptyinterval()) === emptyinterval()

    @test intersect(interval(1.0,3.0), entireinterval()) === Interval(1.0,3.0)

end

@testset "minimal_intersection_dec_test" begin

    @test intersect(DecoratedInterval(interval(1.0,3.0), com), DecoratedInterval(interval(2.1,4.0), com)) === DecoratedInterval(Interval(2.1,3.0), trv)

    @test intersect(DecoratedInterval(interval(1.0,3.0), dac), DecoratedInterval(interval(3.0,4.0), def)) === DecoratedInterval(Interval(3.0,3.0), trv)

    @test intersect(DecoratedInterval(interval(1.0,3.0), def), DecoratedInterval(emptyinterval(), trv)) === DecoratedInterval(emptyinterval(), trv)

    @test intersect(DecoratedInterval(entireinterval(), dac), DecoratedInterval(emptyinterval(), trv)) === DecoratedInterval(emptyinterval(), trv)

    @test intersect(DecoratedInterval(interval(1.0,3.0), dac), DecoratedInterval(entireinterval(), dac)) === DecoratedInterval(Interval(1.0,3.0), trv)

end

@testset "minimal_convex_hull_test" begin

    @test hull(interval(1.0,3.0), interval(2.1,4.0)) === Interval(1.0,4.0)

    @test hull(interval(1.0,1.0), interval(2.1,4.0)) === Interval(1.0,4.0)

    @test hull(interval(1.0,3.0), emptyinterval()) === Interval(1.0,3.0)

    @test hull(emptyinterval(), emptyinterval()) === emptyinterval()

    @test hull(interval(1.0,3.0), entireinterval()) === entireinterval()

end

@testset "minimal_convex_hull_dec_test" begin

    @test hull(DecoratedInterval(interval(1.0,3.0), trv), DecoratedInterval(interval(2.1,4.0), trv)) === DecoratedInterval(Interval(1.0,4.0), trv)

    @test hull(DecoratedInterval(interval(1.0,1.0), trv), DecoratedInterval(interval(2.1,4.0), trv)) === DecoratedInterval(Interval(1.0,4.0), trv)

    @test hull(DecoratedInterval(interval(1.0,3.0), trv), DecoratedInterval(emptyinterval(), trv)) === DecoratedInterval(Interval(1.0,3.0), trv)

    @test hull(DecoratedInterval(emptyinterval(), trv), DecoratedInterval(emptyinterval(), trv)) === DecoratedInterval(emptyinterval(), trv)

    @test hull(DecoratedInterval(interval(1.0,3.0), trv), DecoratedInterval(entireinterval(), dac)) === DecoratedInterval(entireinterval(), trv)

end


export Polygon

#= Polygon (for a base shape) =#

# Assume the followings for the polygon represented by Polygon:
# - The polygon is convex.
# - The vertices are listed in the counter-clockwise order around the origin.
mutable struct Polygon{K,K2} <: Shape{2,4}  # K2 = 2K
    v::SMatrix{2,K,Float64,K2}  # vertices
    n::SMatrix{2,K,Float64,K2}  # direction normals to edges
    Polygon{K,K2}(v,n) where {K,K2} = new(v,n)  # suppress default outer constructor
end

function Polygon(v::SMatrix{2,K,<:Real}) where {K}
    # Sort the vertices in the counter-clockwise direction
    w = v .- mean(v, dims=Val(2))  # v in center-of-mass coordinates
    ϕ = mod.(atan.(w[2,:], w[1,:]), 2π)  # SVector{K}: angle of vertices between 0 and 2π; `%` does not work for negative angle
    if !issorted(ϕ)
        # Do this only when ϕ is not sorted, because the following uses allocations.
        ind = MVector{K}(sortperm(ϕ))  # sortperm(::SVector) currently returns Vector, not MVector
        v = v[:,ind]  # SVector{K}: sorted v
    end

    # Calculate the increases in angle between neighboring edges.
    ∆v = hcat(diff(v, dims=Val(2)), SMatrix{2,1}(v[:,1]-v[:,end]))  # SMatrix{2,K}: edge directions
    ∆z = ∆v[1,:] + im * ∆v[2,:]  # SVector{K}: edge directions as complex numbers
    icurr = ntuple(identity, Val(K-1))
    inext = ntuple(x->x+1, Val(K-1))
    ∆ϕ = angle.(∆z[SVector(inext)] ./ ∆z[SVector(icurr)])  # angle returns value between -π and π

    # Check all the angle increases are positive.  If they aren't, the polygon is not convex.
    all(∆ϕ .> 0) || throw("v = $v should represent vertices of convex polygon.")

    n = [∆v[2,:] -∆v[1,:]]'  # SMatrix{2,K}; outward normal directions to edges
    n = n ./ hypot.(n[1,:], n[2,:])'  # normalize

    return Polygon{K,2K}(v,n)
end

Polygon(v::AbstractMatrix{<:Real}) = (K = size(v,2); Polygon(SMatrix{2,K}(v)))

# Regular polygon
function Polygon{K}(c::SVector{2,<:Real},
                    r::Real,  # distance between center and each vertex
                    θ::Real=0.0  # angle from +y-direction towards first vertex
                    ) where {K}
    ∆θ = 2π / K

    θs = π/2 + θ .+ ∆θ .* SVector(ntuple(k->k-1, Val(K)))  # SVector{K}: angles of vertices
    v = c .+ r .* [cos.(θs) sin.(θs)]'  # SMatrix{2,K}: locations of vertices

    return Polygon(v)
end

Polygon{K}(c::AbstractVector{<:Real},  # [x, y]: center of regular polygon
           r::Real,  # radius: distance from center to vertices
           θ::Real=0.0  # angle of first vertex
           ) where {K} =
   Polygon{K}(SVector{2}(c), r, θ)

Base.:(==)(s1::Polygon, s2::Polygon) = s1.v==s2.v && s1.n==s2.n  # assume sorted v
Base.isapprox(s1::Polygon, s2::Polygon) = s1.v≈s2.v && s1.n≈s2.n  # assume sorted v
Base.hash(s::Polygon, h::UInt) = hash(s.v, hash(s.n, hash(:Polygon, h)))

function level(x::SVector{2,<:Real}, s::Polygon)
    c = mean(s.v, dims=Val(2))  # center of mass

    d = sum(s.n .* (x .- c), dims=Val(1))
    r = sum(s.n .* (s.v .- c), dims=Val(1))
    @assert all(r .> 0)

    return maximum(d ./ r) - 1.0
end

function surfpt_nearby(x::SVector{2,<:Real}, s::Polygon{K}) where {K}
    # Calculate the signed distances from x to edge lines.
    ∆xe = sum(s.n .* (x .- s.v), dims=Val(1))[1,:]  # SVector{K}: values of equations of edge lines
    abs∆xe = abs.(∆xe)  # SVector{K}

    # Determine if x is outside of edges, inclusive.
    sz = abs.((-)(bounds(s)...))  # SVector{2}
    onbnd = abs∆xe .≤ Base.rtoldefault(Float64) * max(sz.data...)  # SVector{K}
    isout = (∆xe.>0) .| onbnd  # SVector{K}

    # For x inside the polygon, it is easy to find the closest surface point: we can simply
    # pick the closest edge and find its point closest to x.
    # For x outside the polygon, there are many cases depending on how many edges x lies
    # outside of.  However, x that is sufficiently close to the polygon should be outside of
    # at most two edges.  (Outside two edges near the vertices, and one edge elsewhere.)
    # Therefore, we will consider only cout ≤ 2 below.
    cout = count(isout)
    if cout == 2  # x is outside two edges
        # We could choose to find ind corresponding to the two nonnegative ∆xe, but such an
        # operation leads to allocations because it does not create an SVector.  Instead,
        # find the closest vertex directly, which is the surface point we are looking for
        # for cout = 2.
        ∆xv = x .- s.v
        l∆xv = hypot.(∆xv[1,:], ∆xv[2,:])
        imin = argmin(l∆xv)
        surf = s.v[:,imin]
        imin₋₁ = mod1(imin-1,K)

        if onbnd[imin] && onbnd[imin₋₁]  # x is very close to vertex imin
            nout = s.n[:,imin] + s.n[:,imin₋₁]
        else
            nout = x - s.v[:,imin]
        end
        nout = normalize(nout)
    else  # cout ≤ 1 or cout ≥ 3
        cout ≤ 1 || @warn "x = $x is outside $cout edges: too far from polygon with vertices $(s.v); " *
                            "result could be inaccurate."
        # Choose the closest edge to x.
        # If cout = 0, all ∆xe are negative, so the largest ∆xe is the smallest in magnitude
        # and corresponds to the closest edge.
        # If cout = 1, all but one ∆xe are negative, so again the largest ∆xe is the only
        # nonnegative one and corresponds to the edge outside which x lies.
        # Even for cout = 3, this seems to be a reasonable choice from a simple geometric
        # argument.
        imax = argmax(∆xe)
        vmax, nmax = s.v[:,imax], s.n[:,imax]

        ∆x = (nmax⋅(vmax-x)) .* nmax
        surf = x + ∆x
        nout = nmax
    end

    return surf, nout
end

translate(s::Polygon, ∆::SVector{2,<:Real}) = (s2 = deepcopy(s); s2.v = s2.v .+ ∆; s2)

function bounds(s::Polygon)
    l = minimum(s.v, dims=Val(2))[:,1]
    u = maximum(s.v, dims=Val(2))[:,1]

    return (l, u)
end


using OrdinaryDiffEq,DiffEqProblemLibrary, DiffEqDevTools, Test

using DiffEqProblemLibrary.ODEProblemLibrary: importodeproblems; importodeproblems()
import DiffEqProblemLibrary.ODEProblemLibrary: prob_ode_2Dlinear, prob_ode_linear

prob = prob_ode_2Dlinear
sol =solve(prob,Rosenbrock32(),dt=1/2^4)

sol =solve(prob,ExplicitRK(tableau = constructBogakiShampine3()),dt=1/2^4)
val1 = maximum(abs.(sol.u[end] - sol.u_analytic[end]))

sol2 =solve(prob,ExplicitRK(tableau = constructDormandPrince()),dt=1/2^4)
val2 = maximum(abs.(sol2.u[end] - sol2.u_analytic[end]))

sol3 =solve(prob,ExplicitRK(tableau = constructRKF8(Float64)),dt=1/2^4)
val3 = maximum(abs.(sol3.u[end] - sol3.u_analytic[end]))

@test length(sol.t)>length(sol2.t)>=length(sol3.t)
@test max(val1,val2,val3)<2e-3

function lorenz(u,p,t)
  [10.0(u[2]-u[1])
  u[1]*(28.0-u[3]) - u[2]
  u[1]*u[2] - (8/3)*u[3]]
end
u0 = [1.0;0.0;0.0]
tspan = (0.0,100.0)
prob = ODEProblem{false}(lorenz,u0,tspan)
sol = solve(prob,QNDF())
@test length(sol.t) < 5000

function lorenz(du,u,p,t)
  du[1] = 10.0(u[2]-u[1])
  du[2] = u[1]*(28.0-u[3]) - u[2]
  du[3] = u[1]*u[2] - (8/3)*u[3]
end
u0 = [1.0;0.0;0.0]
tspan = (0.0,100.0)
prob = ODEProblem{true}(lorenz,u0,tspan)
sol = solve(prob,QNDF())
@test length(sol.t) < 5000


type ThresholdModel <: DischargeModel
    M::Int
    k::Int
    f::Function
    β::Matrix{Float64}
    H::Matrix{Float64}
    Q::Vector{Float64}
end

ThresholdModel(M,N,f,k=1) = ThresholdModel(M,k,f,zeros(M,k),zeros(M,N),zeros(N))

function clusters(M::ThresholdModel,H::Matrix{Float64})
    cs = zeros(Int,size(H,2))
    for i in 1:size(H,2)
        cs[i] = M.f(H[:,i])
    end
    cs
end

function estimate_by_clusters(H,Q,cs,M,k)
    β = zeros(M,k)
    for i in 1:k
        Hi = H[:,cs.==i]
        Qi = Q[cs.==i]
        β[:,i] = (Hi*Hi')\(Hi*Qi)
    end
    β
end

function StatsBase.fit(M::ThresholdModel,H::Matrix{Float64},Q::Vector{Float64})
    cs = clusters(M,H)
    β = estimate_by_clusters(H,Q,cs,M.M,M.k)
    ThresholdModel(M.M,M.k,M.f,β,H,Q)
end

function StatsBase.fit!(M::ThresholdModel,H::Matrix{Float64},Q::Vector{Float64})
    cs = clusters(M,H)
    β = estimate_by_clusters(H,Q,cs,M.M,M.k)
    M.β = β
    M.H = H
    M.Q = Q
    M
end

StatsBase.coef(M::ThresholdModel) = M.β
StatsBase.nobs(M::ThresholdModel) = length(M.Q)
StatsBase.model_response(M::ThresholdModel) = M.Q

function StatsBase.predict(M::ThresholdModel,H)
    cs = clusters(M,H)
    Q = zeros(size(H,2))
    for i in 1:length(Q)
        Q[i] = (H[:,i]'M.β[:,cs[i]])[1]
    end
    Q
end

StatsBase.predict(M::ThresholdModel) = predict(M,M.H)

StatsBase.residuals(M::ThresholdModel) = M.Q-predict(M)
StatsBase.residuals(M::ThresholdModel,H,Q) = Q-predict(M,H)


using DataFrames
using CSV
using Plots
#%%
run(`./harmonic`)
data_v = open("harmonic_verlet.dat")
data_v4 = open("harmonic_verlet4.dat")
data_rk = open("harmonic_rk.dat")
data_rk4 = open("harmonic_rk4.dat")

df_v=CSV.read(data_v, header=false, delim=" ")
df_v4=CSV.read(data_v4, header=false, delim=" ")
df_rk=CSV.read(data_rk, header=false, delim=" ")
df_rk4=CSV.read(data_rk4, header=false, delim=" ")

t_v=df_v[1]
x_v=df_v[2]
v_v=df_v[3]

t_v4=df_v4[1]
x_v4=df_v4[2]
v_v4=df_v4[3]

t_rk=df_rk[1]
x_rk=df_rk[2]
v_rk=df_rk[3]

t_rk4=df_rk4[1]
x_rk4=df_rk4[2]
v_rk4=df_rk4[3]
#%%

K_v=1//2*v_v.^2
U_v=1//2*x_v.^2
En_v=K_v+U_v

K_v4=1//2*v_v4.^2
U_v4=1//2*x_v4.^2
En_v4=K_v4+U_v4

K_rk=1//2*v_rk.^2
U_rk=1//2*x_rk.^2
En_rk=K_rk+U_rk

K_rk4=1//2*v_rk4.^2
U_rk4=1//2*x_rk4.^2
En_rk4=K_rk4+U_rk4
#%%
plot(t_v, En_v, label="Energy Verlet", dpi=600)
plot!(t_v4, En_v4, label="Energy Verlet 4", dpi=600)
plot!(t_rk, En_rk, label="Energy Runge-Kutta", dpi=600)
plot!(t_rk4, En_rk4, label="Energy Runge-Kutta 4", dpi=600, line=:dash, color="black")
plot!(legend=:topleft)
xlabel!("step")
ylabel!("Energy")
savefig("harmonic4.png")

#%%
plot(t_v4, En_v4, label="Energy Verlet 4", dpi=600)
plot!(t_rk4, En_rk4, label="Energy Runge-Kutta 4", dpi=600, line=:dash)
plot!(legend=:bottomleft)
xlabel!("step")
ylabel!("Energy")
savefig("harmonic2.png")

pi/4


using Pkg
Pkg.activate(".")

using BenchmarkTools, LinearAlgebra

function dot1(x, y)
    s = 0.0
    for i in 1:length(x)
        s += x[i]*y[i]
    end
    s
end

function dot2(x, y)
    s = 0.0
    @simd for i in 1:length(x)
        @inbounds s += x[i]*y[i]
    end
    s
end

x = 1000*rand(10000);
y = 1000*rand(10000);

res1 = @btime dot1($x, $y)
res2 = @btime dot2($x, $y)
res3 = @btime dot($x, $y)

println([res2, res3] .- res1)


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

using Markdown
using InteractiveUtils

# ╔═╡ 8e250d30-e1c2-11eb-0360-7dc2bf254c24
using Plots, Distributions, Measurements, StatsPlots, DataFrames, Gadfly, PlutoUI, Statistics, StatsBase, LaTeXStrings, Latexify

# ╔═╡ 49244122-c0b3-47eb-a2a7-4a6fa61bf683
md"# Máquinas de Fluxo - Labs1
\
**Alunos:**
* Alessandro Cappellini Portugal
* Rodrigo Kenji Kuroda
* Jean Carlos Reisdorfer
* Laís Tussi
* Stella Colferai"

# ╔═╡ 0cabd498-4112-4de3-a3fe-7971d0cb566e
html"""

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License."""

# ╔═╡ 4225646f-c459-454e-b238-bd369d20ef9d
y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48]

# ╔═╡ 6789cfda-abe9-471f-86e2-209f3ccd7898
x = [-0.2, 1, 2, 3.1, 4, 5, 6.1, 7.3, 8.2, 9.25, 10.3, 11.3, 12.4, 13.45, 14.48, 15.1, 16.5, 17.5, 18.5, 19.6, 20.62, 21.7, 22.7, 23.7, 24.8, 25.9, 26.9, 28, 29.1, 30.1, 31.1, 32.1, 33.2, 34.2, 35.3, 36.3, 37.4, 38.5, 39.4, 40.5, 41.5, 42.5, 43.5, 44.5, 45.5, 46.6, 47.6, 48.7, 49.7]

# ╔═╡ 295a89c9-24e0-4be8-95b1-8bf60fa20c23
σx = [0.2, 0.1, 0.1, 0.1, 0.1, 0.05, 0.2, 0.1, 0.1, 0.05, 0.1, 0.1, 0.05, 0.05, 0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.05, 0.1, 0.1, 0.1, 0.1, 0.15, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]

# ╔═╡ abba40bf-a742-4033-8ba5-9c10af910e32
md"## Sem filtrar dados espúrios"

# ╔═╡ 0a6f1d35-5be7-4192-8ca9-2dbf476bb5af
md"### Equação 1° grau"

# ╔═╡ 8e400648-232d-405c-a9dd-e9bc6380802b
begin
	scatter(x,y,
		title = "Medições",
		label = "Medições",
		ylabel = "Valores verdadeiros",
		xlabel = "Valores medidos",
		markersize = 2,
		markerstrokewidth = 0,
		legend = :bottomright,
		xerror = σx)
	plot!(x,y,
		label = "",
		linealpha = 0,
		xerror = σx)
end

# ╔═╡ fb4da8a1-2ca9-4056-abdb-ba4f8da9950a
begin
	A = [x[i]^j for i in 1:49, j in 0:1]
	x̂ = A\y
	ŷ(x) = x̂' * [1,x]
end

# ╔═╡ d8673d86-8642-44b6-91cb-2e31e1df2a25
plot!(ŷ, label = "Regressão linear")

# ╔═╡ 45a828ec-a47b-4dd8-94bb-8620969b74c3
L"""
f(x) =  %$(round(x̂[1],digits=4))  + %$(round(x̂[2],digits=4))x
"""

# ╔═╡ 44f43f20-e258-4d16-aaf3-f0654ecae258
x̂

# ╔═╡ 3407bbda-c149-4bc3-ae63-d8e09940573d
begin
	c1 = x̂[1]
	c2 = x̂[2]
	eq1(x) = c1 + c2*x

	r1 = convert(Array{Float64},[])
	for i in 1:49
		append!(r1, eq1(x[i]))
	end
	d1 = y .- r1
	r1, d1
end

# ╔═╡ a34aeeea-00cf-42de-a8fc-d7270086a433
begin
	#Definição dos limites de aceitação para α = 95%

	limy = [2std(d1), 2*std(d1)]
	limx = [0, 50]
	limx, limy
end

# ╔═╡ 60a6e0d1-d222-44e7-9200-99742285adeb
begin
	histogram(d1,
		bins = 12,
		title = "Histograma das medições",
		label = "Histograma",
		ylabel = "Frequência normalizada",
		xlabel = "Desvio à média",
		normalize=true)
	plot!(Normal(mean(d1),std(d1)),
		lw=2,
		color=:orange,
		label = "Distribuição normal")
	plot!(limy,limx./7,
		label = "Limite superior",
		color=:red,
		ls=:dash,
		lw=1)
	plot!(-limy,limx./7,
		label = "Limite inferior",
		color=:red,
		ls=:dash,
		lw=1)
	plot!([mean(d1),mean(d1)],limx./7,
		label = "Média",
		color=:green,
		ls=:dash,
		lw=1)
end

# ╔═╡ 74e7d640-e932-4af4-be7d-d68c100e979f

# ╔═╡ 781e8b4a-a414-40f7-a25f-cee7410192bf
begin
	scatter(d1,
		title = "Desvio à média dos pontos (α = 95%)",
		label = "Desvios à média",
		ylabel = "Desvio à média",
		xlabel = "Valores verdadeiros",
		ylim = (-0.4,0.4),
		markersize = 2,
		markerstrokewidth = 0)
	plot!(d1,
		label = "",
		ylim = (-0.4,0.4),
		linealpha = 0,
		xerror = σx)
	plot!(limx,limy,
		label = "Limite superior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,-limy,
		label = "Limite inferior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,[mean(d1),mean(d1)],
		label = "Média",
		color = :green,
		ls = :dash,
		lw = 1)
end

# ╔═╡ 623a27b7-c768-42e4-963e-97658e81693a

# ╔═╡ 68300505-e792-4b68-a703-6e32de110964
md"### Equação 5° grau"

# ╔═╡ 5c5ebaa0-2092-4344-8c80-4b6b92d4dbb3
begin
	scatter(x,y,
		title = "Medições",
		label = "Medições",
		ylabel = "Valores verdadeiros",
		xlabel = "Valores medidos",
		markersize = 2,
		markerstrokewidth = 0,
		legend=:bottomright,
		xerror=σx)
	plot!(x,y,
		label = "",
		linealpha = 0,
		xerror=σx)
end

# ╔═╡ d53f1bc4-7572-4b49-9019-cec3b585c38b
begin
	C = [x[i]^j for i in 1:49, j in 0:5]
	ẋ = C\y
	ẏ(x) = ẋ' * [1,x,x^2,x^3,x^4,x^5]
end

# ╔═╡ 764ab490-bc21-4f77-a93a-897212d75016
plot!(ẏ, label = "Regressão linear")

# ╔═╡ db8dcdb4-3f6b-490d-97e0-b5aff6f9d4f4
L"""
f(x) =  %$(round(ẋ[1],digits=4)) + %$(round(ẋ[2],digits=4))x + %$(round(ẋ[3],digits=4))x^2 %$(round(ẋ[4],digits=4))x^3 + %$(round(ẋ[5],digits=4))x^4 %$(round(ẋ[6],digits=4))x^5
"""

# ╔═╡ b64dd1cc-076d-4edb-b1bc-30bbd8707a01
ẋ

# ╔═╡ cdbcb0e9-2286-4066-a453-b27a25f2c884
begin
	ṫ0 = ẋ[1]
	ṫ1 = ẋ[2]
	ṫ2 = ẋ[3]
	ṫ3 = ẋ[4]
	ṫ4 = ẋ[5]
	ṫ5 = ẋ[6]
	eq3(x) =ṫ0 + ṫ1*x + ṫ2*x^2 + ṫ3*x^3 + ṫ4*x^4 + ṫ5*x^5

	r3 = convert(Array{Float64},[])
	for i in 1:49
		append!(r3, eq3(x[i]))
	end
	d3 = y .- r3
	r3, d3
end

# ╔═╡ dcf76d4d-95e2-4acc-b5bd-55921968379c
begin
	histogram(d3,
		bins = 12,
		title = "Histograma das medições",
		label = "Histograma",
		ylabel = "Frequência normalizada",
		xlabel = "Desvio à média",
		normalize=true)
	plot!(Normal(mean(d3),std(d3)),
		lw=2,
		color=:orange,
		label = "Distribuição normal")
	plot!(limy,limx./7,
		label = "Limite superior",
		color=:red,
		ls=:dash,
		lw=1)
	plot!(-limy,limx./7,
		label = "Limite inferior",
		color=:red,
		ls=:dash,
		lw=1)
	plot!([mean(d3),mean(d3)],limx./7,
		label = "Média",
		color=:green,
		ls=:dash,
		lw=1)
end

# ╔═╡ 915b66f4-6c35-47c0-9847-f73457f39106

# ╔═╡ f5dbcdc1-5aeb-461a-9e15-4239b0e4379c
begin
	scatter(d3,
		title = "Desvio à média dos pontos (α = 95%)",
		label = "Desvios à média",
		ylabel = "Desvio à média",
		xlabel = "Valores verdadeiros",
		ylim = (-0.4,0.4),
		markersize = 2,
		markerstrokewidth = 0)
	plot!(d3,
		label = "",
		ylim = (-0.4,0.4),
		linealpha = 0,
		xerror = σx)
	plot!(limx,limy,
		label = "Limite superior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,-limy,
		label = "Limite inferior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,[mean(d3),mean(d3)],
		label = "Média",
		color = :green,
		ls = :dash,
		lw = 1)
end

# ╔═╡ 5b54a42f-8323-41ae-86b5-a7bda064d9b7
md"## Filtrando os dados espúrios"

# ╔═╡ b41a0cd0-7104-4520-9c3d-4069789b319d
md"### Encontrar Outliers"

# ╔═╡ 7e8643d2-1a95-4f98-addb-ef730cf77f12
md"""
A filtragem dos dados espúrios funciona pelo princípio de quartis
, onde se aplicam as seguintes equações e assim descobre-se os pontos a serem descartados:
\
\
``Lim_{mín} = Q_1 - 1.5(Q_3 - Q_1)``

``Lim_{máx} = Q_3 + 1.5(Q_3 - Q_1)``
"""

# ╔═╡ a909bac1-3c6c-4779-82a2-478a4eebb7d1
begin
	outliers = []
	valoresd1 = []
	indexd1 = []

	Q = quantile(d1)
	Q1 = Q[2]
	Q3 = Q[4]

	out_min = Q1-1.5*(Q3-Q1)
	out_max = Q3+1.5*(Q3 -Q1)

	for i in d1
		if i < out_min
			append!(valoresd1,i)
		elseif i > out_max
			append!(valoresd1,i)
		end
	end

	for i in 1:49
		for j in valoresd1
			if j == d1[i]
				append!(indexd1, i)
			end
		end
	end

	for i in indexd1
		append!(outliers,x[i])
	end

	outliers, indexd1
end

# ╔═╡ 7f29d513-03d1-4c64-90d9-61cc4fc94d29
md"### Filtrar Outliers"

# ╔═╡ 049c2a8d-e2de-4a95-b596-fc34acd48d9f
begin
	xx = convert(Array{Float64}, [])
	yy = convert(Array{Float64}, [])
	σxx = convert(Array{Float64}, [])
	for i in 1:49
		for j in outliers
			if x[i] != j
				append!(xx, x[i])
				append!(yy, y[i])
				append!(σxx, σx[i])
			end
		end
	end

	if size(outliers,1) == 0
		Print(size(outliers,1)," ponto foi removido!")
	elseif size(outliers,1) == 1
		Print(size(outliers,1)," ponto foi removido!")
	else
		Print(size(outliers,1)," pontos foram removidos!")
	end
end

# ╔═╡ 634c8ad1-bb47-450b-9143-2396810391f3
md"## Dados filtrados"

# ╔═╡ 18ab75fa-5a91-4817-b754-048bba299b59
md"### Equação 1° grau"

# ╔═╡ 595b3e0d-6e42-49c6-a479-85f32551bfff
yy

# ╔═╡ 5bf89139-715a-468d-a4ab-ce145d269175
xx

# ╔═╡ 95c8f96b-a35a-4b20-9c04-0f7e48aacada
σxx

# ╔═╡ 27ec07cb-f2fd-4a31-a3cf-c3bf82dd308d
begin
	scatter(xx,yy,
		title  =  "Medições",
		label  =  "Medições",
		ylabel  =  "Valores verdadeiros",
		xlabel  =  "Valores medidos",
		markersize = 2,
		markerstrokewidth = 0,
		legend = :bottomright)
	plot!(xx,yy,
		label  =  "",
		linealpha  =  0,
		xerror = σxx)
end

# ╔═╡ dd9463db-41f4-4c09-acac-9215d1c21229
begin
	B = [xx[i]^j for i in 1:48, j in 0:1]
	x̂f = B\yy
	ŷf(xx) = x̂f' * [1,xx]
end

# ╔═╡ c051daf8-d220-465d-9133-ec296a7cd48e
plot!(ŷf,label = "Regressão linear")

# ╔═╡ dc413f5f-e569-4458-9650-a6b064f6903d
L"""
f(x) =  %$(round(x̂f[1],digits=4))  + %$(round(x̂f[2],digits=4))x
"""

# ╔═╡ 072a675b-ef4c-47a0-8f26-64c84044a3bd
x̂f

# ╔═╡ ad1c1263-6967-4a28-bfc3-810c103382dd
begin
	c3 = x̂f[1]
	c4 = x̂f[2]
	eq2(xx) = c3 + c4*xx

	r2 = convert(Array{Float64},[])
	for i in 1:48
		append!(r2, eq2(xx[i]))
	end
	d2 = yy .- r2
	r2, d2
end

# ╔═╡ c0bd8c32-462e-405f-87c6-09303edc7a8e
begin
	histogram(d2,
		bins  =  12,
		title  =  "Histograma das medições",
		label  =  "Histograma",
		ylabel  =  "Frequência normalizada",
		xlabel  =  "Desvio à média",
		normalize = true)
	plot!(Normal(mean(d2),std(d2)),
		color = :orange,
		lw = 2,
		label  =  "Distribuição normal")
	plot!(limy,limx./6,
		label  =  "Limite superior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(-limy,limx./6,
		label  =  "Limite inferior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!([mean(d2),mean(d2)],limx./6,
		label  =  "Média",
		color = :green,
		ls = :dash,
		lw = 1)
end

# ╔═╡ 14ef3427-37ad-4dc3-86ec-eaf2f7e33cd7

# ╔═╡ 17f72af5-5adf-4903-acb4-b8e0fcbb6676
begin
	scatter(d2,
		title  =  "Desvio à média dos pontos (α = 95%)",
		label  =  "Desvios à média",
		ylabel  =  "Desvio à média",
		xlabel  =  "Valores verdadeiros",
		ylim = (-0.4,0.4),
		markersize = 2,
		markerstrokewidth  =  0)
	plot!(d2,
		label  =  "",
		ylim = (-0.4,0.4),
		linealpha  =  0,
		xerror = σx)
	plot!(limx,limy,
		label  =  "Limite superior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,-limy,
		label  =  "Limite inferior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,[mean(d2),mean(d2)],
		label  =  "Média",
		color = :green,
		ls = :dash,
		lw = 1)
end

# ╔═╡ aab0c032-f169-4ff6-9052-2f5190510cb2

# ╔═╡ a5069b22-8962-4c12-8e2b-ff0c8681185b
md"### Equação 5° grau"

# ╔═╡ b8ab84f4-33f1-4231-9744-413132c9e279
begin
	scatter(xx,yy,
		title  =  "Medições",
		label  =  "Medições",
		ylabel  =  "Valores verdadeiros",
		xlabel  =  "Valores medidos",
		markersize = 2,
		markerstrokewidth = 0,
		legend = :bottomright)
	plot!(xx,yy,
		label  =  "",
		linealpha  =  0,
		xerror = σxx)
end

# ╔═╡ 0a367bcb-5700-48ad-b1dd-7c66e8dc789e
begin
	D = [xx[i]^j for i in 1:48, j in 0:5]
	ẋf = D\yy
	ẏf(xx) = ẋf' * [1,xx,xx^2,xx^3,xx^4,xx^5]
end

# ╔═╡ 9c92c27a-f4cb-424b-893c-321309ee93a6
plot!(ẏf, label = "Regressão linear")

# ╔═╡ b6e2adff-52f9-4b61-bc22-08c46478a0a3
L"""
f(x) =  %$(round(ẋf[1],digits=4)) + %$(round(ẋf[2],digits=4))x + %$(round(ẋf[3],digits=4))x^2 %$(round(ẋf[4],digits=4))x^3 + %$(round(ẋf[5],digits=4))x^4 %$(round(ẋf[6],digits=4))x^5
"""

# ╔═╡ 90c7e5f8-03f8-46a1-a2a4-35c861f84dfe
ẋf

# ╔═╡ af9eba14-0f5f-4941-b56b-eab68107b15a
begin
	t0 = ẋf[1]
	t1 = ẋf[2]
	t2 = ẋf[3]
	t3 = ẋf[4]
	t4 = ẋf[5]
	t5 = ẋf[6]
	eq4(xx) =t0 + t1*xx + t2*xx^2 + t3*xx^3 + t4*xx^4 + t5*xx^5

	r4 = convert(Array{Float64},[])
	for i in 1:48
		append!(r4, eq4(xx[i]))
	end
	d4 = yy .- r4
	r4, d4
end

# ╔═╡ 693116ed-d66c-4938-8916-51a1825490fe
begin
	histogram(d4,
		bins = 12,
		title  =  "Histograma das medições",
		label  =  "Histograma",
		ylabel  =  "Frequência normalizada",
		xlabel  =  "Desvio à média",
		normalize = true)
	plot!(Normal(mean(d4),std(d4)),
		color = :orange,
		lw = 2,
		label  =  "Distribuição normal")
	plot!(limy,limx./5,
		label  =  "Limite superior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(-limy,limx./5,
		label  =  "Limite inferior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!([mean(d4),mean(d4)],limx./5,
		label  =  "Média",
		color = :green,
		ls = :dash,
		lw = 1)
end

# ╔═╡ e78f377e-0e61-40ed-995c-04e3197c0c09

# ╔═╡ 32ebe64e-703f-4f3c-a307-b0a43db5292a
begin
	scatter(d4,
		title  =  "Desvio à média dos pontos (α = 95%)",
		label  =  "Desvios à média",
		ylabel  =  "Desvio à média",
		xlabel  =  "Valores verdadeiros",
		ylim = (-0.4,0.4),
		markersize = 2,
		markerstrokewidth  =  0)
	plot!(d4,
		label  =  "",
		ylim = (-0.4,0.4),
		linealpha  =  0,
		xerror = σx)
	plot!(limx,limy,
		label  =  "Limite superior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,-limy,
		label  =  "Limite inferior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,[mean(d4),mean(d4)],
		label  =  "Média",
		color = :green,
		ls = :dash,
		lw = 1)
end

# ╔═╡ bd9c53be-072a-4efe-9bf9-0f77ec96879e

# ╔═╡ 70ab5271-6b97-46d7-9d16-00366bdfc23d
md"## Comparação de desvios à média entre 5° grau e 1° grau"

# ╔═╡ 510901ce-a7f2-48d0-a483-5144db931be9
begin
	d5 = r2 .- r4

	scatter(d5,
		title  =  "Diferença entre desvios de 1° e 5° grau (α = 95%)",
		label  =  "Desvios à média",
		ylabel  =  "Desvio à média",
		xlabel  =  "Valores verdadeiros",
		ylim = (-0.4,0.4),
		markersize = 2,
		markerstrokewidth  =  0)
	plot!(limx,limy,
		label  =  "Limite superior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,-limy,
		label  =  "Limite inferior",
		color = :red,
		ls = :dash,
		lw = 1)
	plot!(limx,[mean(d5),mean(d5)],
		label  =  "Média",
		color = :green,
		ls = :dash,
		lw = 1)
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"

[compat]
DataFrames = "~1.2.0"
Distributions = "~0.24.18"
Gadfly = "~1.3.3"
LaTeXStrings = "~1.2.1"
Latexify = "~0.15.6"
Measurements = "~2.6.0"
Plots = "~1.18.2"
PlutoUI = "~0.7.9"
StatsBase = "~0.33.8"
StatsPlots = "~0.14.25"
"""

# ╔═╡ 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"

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

[[Arpack]]
deps = ["Arpack_jll", "Libdl", "LinearAlgebra"]
git-tree-sha1 = "2ff92b71ba1747c5fdd541f8fc87736d82f40ec9"
uuid = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97"
version = "0.4.0"

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

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

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

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

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

[[CategoricalArrays]]
deps = ["DataAPI", "Future", "JSON", "Missings", "Printf", "RecipesBase", "Statistics", "StructTypes", "Unicode"]
git-tree-sha1 = "1562002780515d2573a4fb0c3715e4e57481075e"
uuid = "324d7699-5711-5eae-9e2f-1d82baa6b597"
version = "0.10.0"

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

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

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

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

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

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

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

[[Compose]]
deps = ["Base64", "Colors", "DataStructures", "Dates", "IterTools", "JSON", "LinearAlgebra", "Measures", "Printf", "Random", "Requires", "Statistics", "UUIDs"]
git-tree-sha1 = "c6461fc7c35a4bb8d00905df7adafcff1fe3a6bc"
uuid = "a81c6b42-2e10-5240-aca2-a61377ecd94b"
version = "0.9.2"

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

[[CoupledFields]]
deps = ["LinearAlgebra", "Statistics", "StatsBase"]
git-tree-sha1 = "6c9671364c68c1158ac2524ac881536195b7e7bc"
uuid = "7ad07ef1-bdf2-5661-9d2b-286fd4296dac"
version = "0.2.0"

[[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 = "1dadfca11c0e08e03ab15b63aaeda55266754bad"
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
version = "1.2.0"

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

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

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

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

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

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

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

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

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

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

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

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

[[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"]
git-tree-sha1 = "693210145367e7685d8604aee33d9bfb85db8b31"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "0.11.9"

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

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

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

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

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

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

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

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

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

[[Gadfly]]
deps = ["Base64", "CategoricalArrays", "Colors", "Compose", "Contour", "CoupledFields", "DataAPI", "DataStructures", "Dates", "Distributions", "DocStringExtensions", "Hexagons", "IndirectArrays", "IterTools", "JSON", "Juno", "KernelDensity", "LinearAlgebra", "Loess", "Measures", "Printf", "REPL", "Random", "Requires", "Showoff", "Statistics"]
git-tree-sha1 = "96da4818e4d481a29aa7d66aac1eb778432fb89a"
uuid = "c91e804a-d5a3-530f-b6f0-dfbca275c004"
version = "1.3.3"

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

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

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

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

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

[[Hexagons]]
deps = ["Test"]
git-tree-sha1 = "de4a6f9e7c4710ced6838ca906f81905f7385fd6"
uuid = "a1b4810d-1bce-5fbd-ac56-80944d57a21f"
version = "0.2.0"

[[IndirectArrays]]
git-tree-sha1 = "c2a145a145dc03a7620af1444e0264ef907bd44f"
uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959"
version = "0.5.1"

[[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 = "1470c80592cf1f0a35566ee5e93c5f8221ebc33a"
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
version = "0.13.3"

[[InvertedIndices]]
deps = ["Test"]
git-tree-sha1 = "15732c475062348b0165684ffe28e85ea8396afc"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.0.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 = "81690084b6198a2e1da36fcfda16eeca9f9f24e4"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.1"

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

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

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

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

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

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

[[Loess]]
deps = ["Distances", "LinearAlgebra", "Statistics"]
git-tree-sha1 = "b5254a86cf65944c68ed938e575f5c81d5dfe4cb"
uuid = "4345ca2d-374a-55d4-8d30-97f9976e7612"
version = "0.5.3"

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

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

[[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 = "6a8a2a625ab0dea913aba95c11370589e0239ff0"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.6"

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

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

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

[[Measurements]]
deps = ["Calculus", "LinearAlgebra", "Printf", "RecipesBase", "Requires"]
git-tree-sha1 = "31c8c0569b914111c94dd31149265ed47c238c5b"
uuid = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
version = "2.6.0"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[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]]
git-tree-sha1 = "37d210f612d70f3f7d57d488cb3b6eff56ad4e41"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.0"

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

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

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

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

[[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 = "ffae887d0f0222a19c406a11c3831776d1383e3d"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.3.3"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[StructTypes]]
deps = ["Dates", "UUIDs"]
git-tree-sha1 = "e36adc471280e8b346ea24c5c87ba0571204be7a"
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
version = "1.7.2"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[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:
# ╟─49244122-c0b3-47eb-a2a7-4a6fa61bf683
# ╟─0cabd498-4112-4de3-a3fe-7971d0cb566e
# ╠═8e250d30-e1c2-11eb-0360-7dc2bf254c24
# ╟─4225646f-c459-454e-b238-bd369d20ef9d
# ╟─6789cfda-abe9-471f-86e2-209f3ccd7898
# ╟─295a89c9-24e0-4be8-95b1-8bf60fa20c23
# ╠═a34aeeea-00cf-42de-a8fc-d7270086a433
# ╟─abba40bf-a742-4033-8ba5-9c10af910e32
# ╟─0a6f1d35-5be7-4192-8ca9-2dbf476bb5af
# ╟─8e400648-232d-405c-a9dd-e9bc6380802b
# ╠═fb4da8a1-2ca9-4056-abdb-ba4f8da9950a
# ╟─d8673d86-8642-44b6-91cb-2e31e1df2a25
# ╟─45a828ec-a47b-4dd8-94bb-8620969b74c3
# ╠═44f43f20-e258-4d16-aaf3-f0654ecae258
# ╠═3407bbda-c149-4bc3-ae63-d8e09940573d
# ╟─60a6e0d1-d222-44e7-9200-99742285adeb
# ╟─74e7d640-e932-4af4-be7d-d68c100e979f
# ╟─781e8b4a-a414-40f7-a25f-cee7410192bf
# ╟─623a27b7-c768-42e4-963e-97658e81693a
# ╟─68300505-e792-4b68-a703-6e32de110964
# ╟─5c5ebaa0-2092-4344-8c80-4b6b92d4dbb3
# ╠═d53f1bc4-7572-4b49-9019-cec3b585c38b
# ╟─764ab490-bc21-4f77-a93a-897212d75016
# ╟─db8dcdb4-3f6b-490d-97e0-b5aff6f9d4f4
# ╠═b64dd1cc-076d-4edb-b1bc-30bbd8707a01
# ╠═cdbcb0e9-2286-4066-a453-b27a25f2c884
# ╟─dcf76d4d-95e2-4acc-b5bd-55921968379c
# ╟─915b66f4-6c35-47c0-9847-f73457f39106
# ╟─f5dbcdc1-5aeb-461a-9e15-4239b0e4379c
# ╟─5b54a42f-8323-41ae-86b5-a7bda064d9b7
# ╟─b41a0cd0-7104-4520-9c3d-4069789b319d
# ╟─7e8643d2-1a95-4f98-addb-ef730cf77f12
# ╠═a909bac1-3c6c-4779-82a2-478a4eebb7d1
# ╟─7f29d513-03d1-4c64-90d9-61cc4fc94d29
# ╠═049c2a8d-e2de-4a95-b596-fc34acd48d9f
# ╟─634c8ad1-bb47-450b-9143-2396810391f3
# ╟─18ab75fa-5a91-4817-b754-048bba299b59
# ╠═595b3e0d-6e42-49c6-a479-85f32551bfff
# ╠═5bf89139-715a-468d-a4ab-ce145d269175
# ╠═95c8f96b-a35a-4b20-9c04-0f7e48aacada
# ╟─27ec07cb-f2fd-4a31-a3cf-c3bf82dd308d
# ╠═dd9463db-41f4-4c09-acac-9215d1c21229
# ╟─c051daf8-d220-465d-9133-ec296a7cd48e
# ╟─dc413f5f-e569-4458-9650-a6b064f6903d
# ╠═072a675b-ef4c-47a0-8f26-64c84044a3bd
# ╠═ad1c1263-6967-4a28-bfc3-810c103382dd
# ╟─c0bd8c32-462e-405f-87c6-09303edc7a8e
# ╟─14ef3427-37ad-4dc3-86ec-eaf2f7e33cd7
# ╟─17f72af5-5adf-4903-acb4-b8e0fcbb6676
# ╟─aab0c032-f169-4ff6-9052-2f5190510cb2
# ╟─a5069b22-8962-4c12-8e2b-ff0c8681185b
# ╟─b8ab84f4-33f1-4231-9744-413132c9e279
# ╠═0a367bcb-5700-48ad-b1dd-7c66e8dc789e
# ╟─9c92c27a-f4cb-424b-893c-321309ee93a6
# ╟─b6e2adff-52f9-4b61-bc22-08c46478a0a3
# ╠═90c7e5f8-03f8-46a1-a2a4-35c861f84dfe
# ╠═af9eba14-0f5f-4941-b56b-eab68107b15a
# ╟─693116ed-d66c-4938-8916-51a1825490fe
# ╟─e78f377e-0e61-40ed-995c-04e3197c0c09
# ╟─32ebe64e-703f-4f3c-a307-b0a43db5292a
# ╟─bd9c53be-072a-4efe-9bf9-0f77ec96879e
# ╟─70ab5271-6b97-46d7-9d16-00366bdfc23d
# ╟─510901ce-a7f2-48d0-a483-5144db931be9
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


mutable struct Box
    upper_left_x::Number
    upper_left_y::Number
    lower_right_x::Number
    lower_right_y::Number
end

"""
    Base.:(==)(a::Box, b::Box)::Bool

Tests for equivalence between two Box instances.
"""
function Base.:(==)(a::Box, b::Box)::Bool
    return  (a.upper_left_x == b.upper_left_x) &&
            (a.upper_left_y == b.upper_left_y) &&
            (a.lower_right_x == b.lower_right_x) &&
            (a.lower_right_y == b.lower_right_y)
end

"""
    barycenterbox( x::Number, y::Number, height::Number, width::Number)

Converts a detection box from x,y,h,w coordinates to upper left lower right
coordinates.
"""
function barycenterbox( x::Number, y::Number, height::Number, width::Number)
    wh, hh = width/2, height/2
    return Box( x - wh, y - hh, x + wh, y + hh )
end

"""
    LLURtoULLR( LL_x::Number, LL_y::Number, UR_x::Number, UR_y::Number)

Converts a detection box from lowerleft-upperright coordinates to upper left lower right
coordinates.

Untested...
"""
function LLURtoULLR( LL_x::Number, LL_y::Number, UR_x::Number, UR_y::Number)
    return Box( LL_x, UR_y, UR_x, LL_y )
end

"""
    area( a::Box )

Calculates the area of a Box instance.

"""
area( a::Box ) = ( a.lower_right_x - a.upper_left_x ) * ( a.lower_right_y - a.upper_left_y )

"""
    translate!(a::Box, x::Number,y::Number)::Box

Translates a box by the input x & y coordinates. This is an inplace operation.

"""
function translate!(a::Box, x::Number = 0, y::Number = 0)::Box
    a.upper_left_x  += x
    a.upper_left_y  += y
    a.lower_right_x += x
    a.lower_right_y += y
    return a
end

"""
    translate(a::Box, x::Number,y::Number)::Box

Translates a box by the input x & y coordinates.
"""
translate(a::Box, x::Number = 0, y::Number = 0)::Box = translate!( deepcopy( a ), x, y )

"""
    clamp!(a::Box, bound::Box)::Box

Clamps a `Box` instance `a` to be within a bounded `Box` region `bound`. This is an inplace operation.

"""
function clamp!(a::Box, bound::Box)::Box
    a.upper_left_x  = (a.upper_left_x < bound.upper_left_x) ? bound.upper_left_x : a.upper_left_x
    a.upper_left_y  = (a.upper_left_y < bound.upper_left_y) ? bound.upper_left_y : a.upper_left_y
    a.lower_right_x = (a.lower_right_x > bound.lower_right_x) ? bound.lower_right_x : a.lower_right_x
    a.lower_right_y = (a.lower_right_y > bound.lower_right_y) ? bound.lower_right_y : a.lower_right_y
    return a
end

"""
    clamp(a::Box, bound::Box)::Box

Clamps a `Box` instance `a` to be within a bounded `Box` region `bound`.

"""
clamp(a::Box, bound::Box)::Box = clamp!( deepcopy(a), bound )

"""
    intersection_area( a::Box, b::Box )::Number

Calculates the area of intersection between 2 Box instances.

"""
function intersection_area( a::Box, b::Box )::Number
	ul_x = max( a.upper_left_x,  b.upper_left_x )
	ul_y = max( a.upper_left_y,  b.upper_left_y )
	lr_x = min( a.lower_right_x, b.lower_right_x )
	lr_y = min( a.lower_right_y, b.lower_right_y )
	return max( 0, lr_x - ul_x ) * max( 0, lr_y - ul_y )
end

"""
    intersection_over_union( a::Box, b::Box )::Number

Calculates the intersection over union between 2 Box instances.

"""
function intersection_over_union( a::Box, b::Box )::Number
    intersection = intersection_area( a, b )
    return intersection / ( area( a ) + area( b ) - intersection)
end


@testset "ClosestVector.jl" begin
  #=
  The quadratic triple QT = [Q, L, c] is an n-dimensional ellipsoid with rational coefficients.
  Where,
  Q is an nxn symmetric matrix of the quadratic form ,
  L is a rational column vector of length n &
  c is a rational number
  =#
  Q = matrix(QQ,3,3,[1 0 0; 0 1 0; 0 0 1]);
  L = matrix(fmpq[1,0,0]);
  c = fmpq(2//5);
  Lat = Zlattice(gram = matrix(QQ,3,3,[1,0,0,0,1,0,0,0,1]));
  v = matrix(fmpq[-1,0,0]);
  u = fmpq(3//5);
  @test Hecke.closest_vectors(Q, L,c, sorting=true)[1] == Hecke.closest_vectors(Lat, v, u, sorting=true)[1]

  function compare_functions(Q::MatrixElem{T}, K::MatrixElem{T}, d::T) where T <: RingElem
    List1 = Hecke.closest_vectors(Q, K, d, sorting=true);
    L, v, c = Hecke.convert_type(Q, K, d)
    List2 = Hecke.closest_vectors(L, v, c, sorting=true);
    for i in 1:length(List1)
      if List1[i] == List2[i]
        return true
      else
        error("The entry at position $i in the two lists don't match.")
      end
    end
  end

  function compare_functions(L::ZLat, v::MatrixElem{T} , upperbound::T) where T <: RingElem
    List1 = Hecke.closest_vectors(L, v, upperbound, sorting=true);
    Q, K, d = Hecke.convert_type(L, v, upperbound);
    List2 = Hecke.closest_vectors(Q, K, d, sorting=true);
    for i in 1:length(List1)
      if List1[i] == List2[i]
        return true
      else
        error("The entry at position $i in the two lists don't match.")
      end
    end
  end

  #EXAMPLE 1a: 3-dimensional sphere
  Q1 = matrix(QQ,3,3,[1 0 0; 0 1 0; 0 0 1]);
  L1 = matrix(fmpq[1,1,1]);
  c1 = fmpq(1);

  #EXAMPLE 1b: 4-dimensional sphere
  Q2 = matrix(QQ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
  L2 = matrix(fmpq[1,1,1,1]);
  c2 = fmpq(3);

  #EXAMPLE 1c: 6-dimensional sphere
  Q3 = matrix(QQ,6,6,[1 0 0 0 0 0; 0 1 0 0 0 0; 0 0 1 0 0 0; 0 0 0 1 0 0; 0 0 0 0 1 0; 0 0 0 0 0 1]);
  L3 = matrix(fmpq[1,0,1,0,2,0]);
  c3 = fmpq(4//3);

  #-----------------------------------------------------------------------------

  #Examples for closest_vectors()
  #Example 1:
  Lat1 = Zlattice(gram = matrix(QQ,3,3,[1,0,0,0,1,0,0,0,1]));
  v1 = matrix(fmpq[-1,0,0]);
  u1 = fmpq(3//5);

  #Example 1:
  Lat2 = Zlattice(gram = matrix(QQ,4,4,[1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]));
  v2 = matrix(fmpq[-1,-1,-1,-1]);
  u2 = fmpq(41//11);

  #Example 1:
  Lat3 = Zlattice(gram = matrix(QQ,6,6,[1,0,0,0,0,0, 0,1,0,0,0,0, 0,0,1,0,0,0, 0,0,0,1,0,0, 0,0,0,0,1,0, 0,0,0,0,0,1]));
  v3 = matrix(fmpq[-1,0,-1,0,-2,0]);
  u3 = fmpq(14//3);

  @testset "Comparing closest_vectors(Q, K, d) to closest_vectors(Lat, vec, upperbound) list" begin
    @test compare_functions(Q1, L1, c1) == true
    @test compare_functions(Q2, L2, c2) == true
    @test compare_functions(Q3, L3, c3) == true
  end

  @testset "Comparing closest_vectors(Lat, vec, upperbound) list to closest_vectors(Q, K, d)" begin
    @test compare_functions(Lat1, v1, u1) == true
    @test compare_functions(Lat2, v2, u2) == true
    @test compare_functions(Lat3, v3, u3) == true
  end
  @testset "Comparing closest_vectors() computed with respect to type fmpz and fmpq" begin
    Q0 = matrix(ZZ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
    L0 = matrix(fmpz[1,1,1,1]);
    c0 = fmpz(3);
    @test compare_functions(Q0, L0, c0) == true

    Q01 = matrix(QQ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
    L01 = matrix(fmpq[1,1,1,1]);
    c01 = fmpq(3);
    @test compare_functions(Q01, L01, c01) == true

    List1 = Hecke.closest_vectors(Q0, L0, c0)
    List2 = Hecke.closest_vectors(Q01, L01, c01)
    for i in 1:length(List1)
      @test List1[i] == List2[i]
    end
  end

  @testset "Conversion from Quadratic Triple set to Closest Vector Enumeration input parameters" begin
    Q3 = matrix(QQ,6,6,[1 0 0 0 0 0; 0 1 0 0 0 0; 0 0 1 0 0 0; 0 0 0 1 0 0; 0 0 0 0 1 0; 0 0 0 0 0 1]);
    L3 = matrix(fmpq[1,0,1,0,2,0]);
    c3 = fmpq(4//3);
    cvp = Hecke.convert_type(Q3,L3,c3);
    @test  det(basis_matrix(cvp[1])) == 1
    @test cvp[2] == matrix(fmpq[-1, 0, -1, 0, -2, 0])
    @test cvp[3] == 14//3
  end

  @testset "Conversion from Closest Vector Enumeration to Quadratic Triple set input parameters" begin
    Lat = Zlattice(gram = matrix(QQ,3,3,[1,0,0,0,1,0,0,0,1]));
    vec = matrix(fmpq[-1,-1,-1]);
    upbound = fmpq(2);
    qt = Hecke.convert_type(Lat, vec, upbound);
    @test qt[1] == matrix(QQ,3,3,[1 0 0; 0 1 0; 0 0 1])
    @test qt[2] == matrix(fmpq[1,1,1])
    @test qt[3] == 1
  end

  @testset "Quadratic Triple Tests" begin
    @testset "Projective Quadratic Triple" begin
      Q = matrix(QQ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
      L = matrix(fmpq[1,1,1,1]);
      c = fmpq(3);
      @test Hecke.projective_quadratic_triple(Q, L, c, 1) == (Q[1, 1], L[1], 0)
      @test Hecke.projective_quadratic_triple(Q, L, c, 4) == (Q, L, c)
    end

    @testset "Finite set of integers for a 1-dimensional quadratic triple" begin
      Q = matrix(QQ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
      L = matrix(fmpq[1,1,1,1]);
      c = fmpq(3);
      Q1 = Hecke.projective_quadratic_triple(Q, L, c, 1)[1];
      L1 = Hecke.projective_quadratic_triple(Q, L, c, 1)[2];
      c1 = Hecke.projective_quadratic_triple(Q, L, c, 1)[3];
      @test Hecke.range_ellipsoid_dim1(Q1, L1, c1) == -2:0
    end

    @testset "Different Types of Extended Quadratic Triple" begin
      @testset "Quadratic triple extension from a 1-dimensional quadratic triple" begin
        Q = matrix(QQ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
        L = matrix(fmpq[1,1,1,1]);
        c = fmpq(3);
        @test Hecke.positive_quadratic_triple(fmpz(1), Q, L, c)[1] == Q[2:4, 2:4]
        @test Hecke.positive_quadratic_triple(fmpz(1), Q, L, c)[2] == L[2:4, 1:1]
        @test Hecke.positive_quadratic_triple(fmpz(1), Q, L, c)[3] == 6
      end

      @testset "Quadratic triple extension from a m-dimensional quadratic triple to m+n-1 quadratic triple" begin
        Q = matrix(QQ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
        L = matrix(fmpq[1,1,1,1]);
        c = fmpq(3);
        @test Hecke.positive_quadratic_triple2(fmpz[-2,0,1], Q,L,c)[1][1] == 1
        @test Hecke.positive_quadratic_triple2(fmpz[-2,0,1], Q,L,c)[2][1] == 1
        @test Hecke.positive_quadratic_triple2(fmpz[-2,0,1], Q,L,c)[3] == 6
      end
    end
  end

  @testset "Finite set tests" begin
    Q = matrix(QQ, 4,4,[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]);
    Q1 = -Q;
    L = matrix(fmpq[1,1,1,1]);
    c = fmpq(3);
    @test Hecke.closest_vectors(Q, L, c, sorting=true)[1] == [-2, -1, -1, -1]
    @test size(Hecke.closest_vectors(Q, L, c), 1) == 9
    @test Hecke.closest_vectors(Q, L, c, sorting=true)[1] == Hecke.closest_vectors(Q1,L,c, sorting=true)[1]

    @test Hecke.closest_vectors(Q, L, c, equal=true, sorting=true)[1] == [-2, -1, -1, -1]
    @test size(Hecke.closest_vectors(Q, L, c, equal=true), 1) == 8
    @test Hecke.closest_vectors(Q, L, c, equal=true, sorting=true)[1] == Hecke.closest_vectors(Q1,L,c, sorting=true)[1]

    L1, L2, L3 = Hecke.convert_type(Q,L,c)
    @test Hecke.closest_vectors(L1, L2, L3, sorting=true)[1] == Hecke.closest_vectors(Q, L, c, sorting=true)[1]
    @test size(Hecke.closest_vectors(L1, L2, L3), 1) == size(Hecke.closest_vectors(Q, L, c), 1)
    @test Hecke.closest_vectors(L1, L2, L3, equal=true, sorting=true)[1] == Hecke.closest_vectors(Q, L, c, equal=true, sorting=true)[1]
    @test size(Hecke.closest_vectors(L1, L2, L3, equal=true), 1) == size(Hecke.closest_vectors(Q, L, c, equal=true), 1)
    t = Hecke.closest_vectors(L1, L2, L3, equal=true)
    L21 = Vector{typeof(L2[1])}()
    for i1 in L2
      push!(L21, i1)
    end
    for i in 1:size(t)[1]
      @test inner_product(ambient_space(L1), L21-t[i], L21-t[i]) == L3
    end

    x = matrix(QQ, 4, 1, Hecke.closest_vectors(Q, L, c)[5]);
    xt = transpose(matrix(QQ, 4, 1, Hecke.closest_vectors(Q, L, c)[5]));
    R = (xt * Q * x)[1] + (2 * xt * L)[1] + c;
    @test  R <= 0

    y = matrix(QQ, 4, 1, Hecke.closest_vectors(Q1, L, c)[5]);
    yt = transpose(matrix(QQ, 4, 1, Hecke.closest_vectors(Q1, L, c)[5]));
    S = (yt * Q * y)[1] + (2 * yt * L)[1] + c;
    @test  S <= 0
  end
end


module NonlinearTestProblems

# export API
export domain_dimension, range_dimension, root, starting_point, lower_bounds, upper_bounds

# export problems
export F_NWp281, Rosenbrock, PowellSingular, PowellBadlyScaled, HelicalValley, Beale

using ArgCheck: @argcheck
using DocStringExtensions: FUNCTIONNAME, SIGNATURES

####
#### generic API
####
#### A *test problem* is a `ℝⁿ → ℝᵐ` mapping with some metadata (roots, starting point,
#### dimension).
####

"""
`$(FUNCTIONNAME)(problem)`

Dimension `n` of a the domain of a ``ℝⁿ → ℝᵐ`` test problem.
"""
function domain_dimension end

"""
$(SIGNATURES)

Dimension `m` of a the range of a ``ℝⁿ → ℝᵐ`` test problem.

!!! note
    Defaults to the domain dimension, only non-square implementations should need to define
    a method.
"""
range_dimension(problem) = domain_dimension(problem)

"""
`$(FUNCTIONNAME)(problem)`

Root (solution) of a test problem. Formally,

```julia
problem(root(problem)) ≈ zeros(range_dimension(problem))
```

Problems are guaranteed to have a unique root.
"""
function root end

"""
`$(FUNCTIONNAME)(problem)`

`$(FUNCTIONNAME)(problem, α)`

Recommended starting point of a test problem for methods that need one (eg quasi-Newton).
Usually taken from the literature that defines a problem, and should be “difficult”.

When used with a (positive real) argument `α`, the method should attempt to make it more
difficult (eg move away further from the root).

!!! note
    A default method is provided for the latter, problems just need to implement the
    single-argument version.
"""
function starting_point end

function starting_point(problem, α::Real)
    @argcheck α ≥ 0
    x0 = root(problem)
    x1 = starting_point(problem)
    @. x0 + (1 + α) * (x1 - x0)
end

"""
$(SIGNATURES)

Recommended lower bounds for box-constrained methods. Lower- and upper bounds are guaranteed
to contain the root. Coordinate-wise midpoints of bounds should not be near the root.

See also [`upper_bounds`](@ref).
"""
lower_bounds(problem) = fill(-100.0, domain_dimension(problem))

"""
$(SIGNATURES)

Recommended upper bounds for box-constrained methods. See [`lower_bounds`](@ref).
"""
upper_bounds(problem) = fill(50.0, domain_dimension(problem))

####
#### specific test problems
####

###
### Nocedal and Wright p 281
###

"Problem from Nocedal and Wright, p 281."
struct F_NWp281 end

domain_dimension(::F_NWp281) = 2

root(::F_NWp281) = [0, 1]

starting_point(::F_NWp281) = [-0.5, 1.4]

function (::F_NWp281)(x)
    x1, x2 = x
    [(x1 + 3) * (x2^3 - 7) + 18, sin(x2 * exp(x1) - 1)]
end

###
### Rosenbrock
###

"Rosenbrock function. (1) from Moré et al (1981)."
struct Rosenbrock end

domain_dimension(::Rosenbrock) = 2

root(::Rosenbrock) = [1, 1]

starting_point(::Rosenbrock) = [-1.2, 1]

function (::Rosenbrock)(x)
    x1, x2 = x
    [10 * (x2 - abs2(x1)), 1 - x1]
end

###
### Powell singular function
###

"Powell singular function. (13) from Moré et al (1981)."
struct PowellSingular end

domain_dimension(::PowellSingular) = 4

root(::PowellSingular) = zeros(4)

starting_point(::PowellSingular) = [3, -1, 0, 1]

function (::PowellSingular)(x)
    x1, x2, x3, x4 = x
    [x1 + 10 * x2, √5 * (x3 - x4), abs2(x2 - 2 * x3), √10 * abs2(x1 - x4)]
end

###
### Powell badly scaled function
###

"Powell's badly scaled function. (3) from Moré et al (1981)."
struct PowellBadlyScaled end

domain_dimension(::PowellBadlyScaled) = 2

root(::PowellBadlyScaled) = [1.0981593296999222e-5, 9.106146739865656]

starting_point(::PowellBadlyScaled) = [0, 1]

function (::PowellBadlyScaled)(x)
    x1, x2 = x
    [1e4 * x1 * x2 - 1, exp(-x1) + exp(-x2) - 1.0001]
end

###
### Helical valley function
###

"Helical valley function. (7) from Moré et al (1981)."
struct HelicalValley end

domain_dimension(::HelicalValley) = 3

root(::HelicalValley) = [1, 0, 0]

starting_point(::HelicalValley) = [-1, 0, 0]

function (::HelicalValley)(x)
    x1, x2, x3 = x
    θ = 1/(2π) * atan(x2 / x1) + ifelse(x1 < 0, 0.5, 0)
    [10*(x3 - 10 * θ), 10 * (hypot(x1, x2) - 1), x3]
end

###
### Beale function
###

"Beale function. (5) from Moré et al (1981)."
struct Beale end

domain_dimension(::Beale) = 2

range_dimension(::Beale) = 3

root(::Beale) = [3, 0.5]

starting_point(::Beale) = [1, 1]

function (::Beale)(x)
    [1.5, 2.25, 2.625] .- x[1] .* (1 .- x[2] .^ (1:3))
end

end # module


using DataStructure101
const DS = DataStructure101

export find_entrances, topological_sort

function calc_in_degree(g::DS.AbstractGraph)
    in_degrees = zeros(DS.nv(g))

    for v = 1:DS.nv(g)
        for n in DS.neighbor(g, v)
            in_degrees[n] += 1
        end # for
    end # for

    return in_degrees
end

function find_entrances(g::DS.AbstractGraph)
    entrances = Int[]

    in_degrees = calc_in_degree(g)
    for (v, in_degree) in enumerate(in_degrees)
        in_degree == 0 && push!(entrances, v)
    end # for

    return entrances
end # function

function topological_sort(g::DS.AbstractGraph)
    sorted = Int[]
    entrances = find_entrances(g)

    while length(entrances) > 0
        v = popfirst!(entrances)
        push!(sorted, v)

        ns = DS.neighbor(g, v)
        for n in ns
            if !(n in sorted || n in entrances) push!(entrances, n) end
        end
    end # while

    return sorted
end


using Catalyst
using DiffEqJump
using Random
using DataFrames
using StatsPlots
using BenchmarkTools

sir_model = @reaction_network begin
  β*c/(s+i+r), s + i --> 2i
  γ, i --> r
end β c γ;

tmax = 40.0
tspan = (0.0,tmax);

δt = 0.1
t = 0:δt:tmax;

u0 = [990,10,0]; # S,I,R

p = [0.05,10.0,0.25];

Random.seed!(1234);

prob_discrete = DiscreteProblem(sir_model,u0,tspan,p);

prob_jump = JumpProblem(sir_model,prob_discrete,Direct());

sol_jump = solve(prob_jump,SSAStepper());

out_jump = sol_jump(t);

df_jump = DataFrame(out_jump')
df_jump[!,:t] = out_jump.t;

@df df_jump plot(:t,
    [:x1 :x2 :x3],
    label=["S" "I" "R"],
    xlabel="Time",
    ylabel="Number")

@benchmark solve(prob_jump,SSAStepper())


module SimpleRecoTest

using FactorizationMachines
using Base.Test

# simple recommendation example

 #1 is User1
 #2 is User2
 #3 is Item1,
 #4 is Item2,
 #5 is Item3,
 #6 is Item4
 #7 is the category “18-25″,
 #8 is the category “26-40″,
 #9 is the category “40-60″
 #10 will represent the price feature

#rating     #user   #items     #category    #price

T = [
5           1 0     1 0 0 0    1 0 0        12.5;
5           1 0     0 1 0 0    1 0 0        20;
4           1 0     0 0 1 0    1 0 0        78;
1           0 1     1 0 0 0    0 0 1        12.5;
1           0 1     0 1 0 0    0 0 1        20;
]

info("Testing reading from libsvm format...")

(XFromFile, yFromFile) = read_libsvm("data/small_train.libfm")

println(XFromFile)
println(size(XFromFile))
@test size(XFromFile) == (10, 5)

X = sparse(T[:,2:end])
y = T[:,1]

fm = train(sparse(XFromFile),yFromFile)

(TFromFile, tFromFile) = read_libsvm("data/small_test.libfm")
p = predict(fm,sparse(TFromFile))

info("Predictions: $p")

end