text:
"""
    RelativeEntropyBridge{T}

The `RelativeEntropyCone` is representable with exponential cone and LP
constraints, since ``u \\ge \\sum_{i=1}^n w_i \\log (\\frac{w_i}{v_i})`` if and
only if there exists a vector ``y`` such that ``u \\ge \\sum_i y_i`` and
``y_i \\ge w_i \\log (\\frac{w_i}{v_i})`` or equivalently
``v_i \\ge w_i \\exp (\\frac{-y_i}{w_i})`` or equivalently
``(-y_i, w_i, v_i) \\in ExponentialCone``, for all ``i``.
"""
struct RelativeEntropyBridge{T,F,G,H} <: AbstractBridge
    y::Vector{MOI.VariableIndex}
    ge_index::MOI.ConstraintIndex{F,MOI.GreaterThan{T}}
    exp_indices::Vector{MOI.ConstraintIndex{G,MOI.ExponentialCone}}
end

function bridge_constraint(
    ::Type{RelativeEntropyBridge{T,F,G,H}},
    model::MOI.ModelLike,
    f::H,
    s::MOI.RelativeEntropyCone,
) where {T,F,G,H}
    f_scalars = MOI.Utilities.eachscalar(f)
    d = MOI.dimension(s)
    v_dim = div(d - 1, 2)
    y = MOI.add_variables(model, v_dim)
    rhs = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.(one(T), y), zero(T))
    ge_index = MOI.Utilities.normalize_and_add_constraint(
        model,
        MOI.Utilities.operate(-, T, f_scalars[1], rhs),
        MOI.GreaterThan(zero(T)),
        allow_modify_function = true,
    )
    w_start = 1 + v_dim
    exp_funcs = [
        MOI.Utilities.operate(
            vcat,
            T,
            MOI.Utilities.operate(-, T, y[i]),
            f_scalars[w_start+i],
            f_scalars[1+i],
        ) for i in 1:v_dim
    ]
    exp_indices = [
        MOI.add_constraint(model, exp_func_i, MOI.ExponentialCone()) for
        exp_func_i in exp_funcs
    ]
    return RelativeEntropyBridge{T,F,G,H}(y, ge_index, exp_indices)
end

function MOI.supports_constraint(
    ::Type{RelativeEntropyBridge{T}},
    ::Type{<:MOI.AbstractVectorFunction},
    ::Type{MOI.RelativeEntropyCone},
) where {T}
    return true
end

function MOI.Bridges.added_constrained_variable_types(
    ::Type{<:RelativeEntropyBridge},
)
    return Tuple{Type}[]
end

function MOI.Bridges.added_constraint_types(
    ::Type{RelativeEntropyBridge{T,F,G,H}},
) where {T,F,G,H}
    return Tuple{Type,Type}[(F, MOI.GreaterThan{T}), (G, MOI.ExponentialCone)]
end

function concrete_bridge_type(
    ::Type{<:RelativeEntropyBridge{T}},
    H::Type{<:MOI.AbstractVectorFunction},
    ::Type{MOI.RelativeEntropyCone},
) where {T}
    S = MOI.Utilities.scalar_type(H)
    F = MOI.Utilities.promote_operation(-, T, S, S)
    G = MOI.Utilities.promote_operation(
        vcat,
        T,
        MOI.Utilities.promote_operation(-, T, MOI.VariableIndex),
        S,
    )
    return RelativeEntropyBridge{T,F,G,H}
end

function MOI.get(bridge::RelativeEntropyBridge, ::MOI.NumberOfVariables)::Int64
    return length(bridge.y)
end

function MOI.get(bridge::RelativeEntropyBridge, ::MOI.ListOfVariableIndices)
    return copy(bridge.y)
end

function MOI.get(
    ::RelativeEntropyBridge{T,F},
    ::MOI.NumberOfConstraints{F,MOI.GreaterThan{T}},
)::Int64 where {T,F}
    return 1
end

function MOI.get(
    bridge::RelativeEntropyBridge{T,F,G},
    ::MOI.NumberOfConstraints{G,MOI.ExponentialCone},
)::Int64 where {T,F,G}
    return length(bridge.y)
end

function MOI.get(
    bridge::RelativeEntropyBridge{T,F},
    ::MOI.ListOfConstraintIndices{F,MOI.GreaterThan{T}},
) where {T,F}
    return [bridge.ge_index]
end

function MOI.get(
    bridge::RelativeEntropyBridge{T,F,G},
    ::MOI.ListOfConstraintIndices{G,MOI.ExponentialCone},
) where {T,F,G}
    return copy(bridge.exp_indices)
end

function MOI.delete(model::MOI.ModelLike, bridge::RelativeEntropyBridge)
    for exp_index_i in bridge.exp_indices
        MOI.delete(model, exp_index_i)
    end
    MOI.delete(model, bridge.ge_index)
    MOI.delete(model, bridge.y)
    return
end

function MOI.get(
    model::MOI.ModelLike,
    ::MOI.ConstraintFunction,
    bridge::RelativeEntropyBridge{T,F,G,H},
) where {T,F,G,H}
    func = MOI.Utilities.zero_with_output_dimension(G, 1 + 2 * length(bridge.y))
    MOI.Utilities.operate_output_index!(
        +,
        T,
        1,
        func,
        MOI.get(model, MOI.ConstraintFunction(), bridge.ge_index),
    )
    w_start = 1 + length(bridge.y)
    for i in eachindex(bridge.y)
        exp_func_i = MOI.Utilities.eachscalar(
            MOI.get(model, MOI.ConstraintFunction(), bridge.exp_indices[i]),
        )
        MOI.Utilities.operate_output_index!(-, T, 1, func, exp_func_i[1])
        MOI.Utilities.operate_output_index!(+, T, 1 + i, func, exp_func_i[3])
        MOI.Utilities.operate_output_index!(
            +,
            T,
            w_start + i,
            func,
            exp_func_i[2],
        )
    end
    return MOI.Utilities.convert_approx(
        H,
        MOI.Utilities.remove_variable(func, bridge.y),
    )
end

function MOI.get(
    ::MOI.ModelLike,
    ::MOI.ConstraintSet,
    bridge::RelativeEntropyBridge,
)
    return MOI.RelativeEntropyCone(1 + 2 * length(bridge.y))
end

function MOI.supports(
    model::MOI.ModelLike,
    attr::Union{MOI.ConstraintPrimalStart,MOI.ConstraintDualStart},
    ::Type{RelativeEntropyBridge{T,F,G,H}},
) where {T,F,G,H}
    ci_1 = MOI.ConstraintIndex{F,MOI.GreaterThan{T}}
    ci_2 = MOI.ConstraintIndex{G,MOI.ExponentialCone}
    return MOI.supports(model, attr, ci_1) && MOI.supports(model, attr, ci_2)
end

function MOI.get(
    model::MOI.ModelLike,
    attr::Union{MOI.ConstraintPrimal,MOI.ConstraintPrimalStart},
    bridge::RelativeEntropyBridge{T},
) where {T}
    primal = zeros(T, 1 + 2 * length(bridge.y))
    primal[1] = MOI.get(model, attr, bridge.ge_index)
    w_start = 1 + length(bridge.y)
    for i in eachindex(bridge.y)
        exp_primal_i = MOI.get(model, attr, bridge.exp_indices[i])
        primal[1] -= exp_primal_i[1]
        primal[1+i] = exp_primal_i[3]
        primal[w_start+i] = exp_primal_i[2]
    end
    return primal
end

function MOI.set(
    model::MOI.ModelLike,
    attr::MOI.ConstraintPrimalStart,
    bridge::RelativeEntropyBridge{T},
    value,
) where {T}
    v_dim = length(bridge.y)
    v_value = value[2:(v_dim+1)]
    w_value = value[(v_dim+2):end]
    y_value = [w_i * log(w_i / v_i) for (v_i, w_i) in zip(v_value, w_value)]
    MOI.set(
        model,
        attr,
        bridge.ge_index,
        value[1] - reduce(+, y_value, init = zero(T)),
    )
    for i in 1:v_dim
        MOI.set(
            model,
            attr,
            bridge.exp_indices[i],
            [-y_value[i], w_value[i], v_value[i]],
        )
        MOI.set(model, MOI.VariablePrimalStart(), bridge.y[i], y_value[i])
    end
    return
end

# Given a is dual on u - sum(y) >= 0 and (b_i, c_i, d_i) is dual on
# (-y_i, w_i, v_i) in ExponentialCone, the dual on
# (u, v, w) in RelativeEntropyCone is (a, d_i, c_i).
function MOI.get(
    model::MOI.ModelLike,
    attr::Union{MOI.ConstraintDual,MOI.ConstraintDualStart},
    bridge::RelativeEntropyBridge{T},
) where {T}
    dual = zeros(T, 1 + 2 * length(bridge.y))
    dual[1] = MOI.get(model, attr, bridge.ge_index)[1]
    w_start = 1 + length(bridge.y)
    for i in eachindex(bridge.y)
        exp_dual_i = MOI.get(model, attr, bridge.exp_indices[i])
        dual[1+i] = exp_dual_i[3]
        dual[w_start+i] = exp_dual_i[2]
    end
    return dual
end

# Given constraint dual start of (u, v, w), constraint dual on GreaterThan is u
# and on exponential cone constraint i is (r_i, w_i, v_i), but since y_i is
# free, its dual is 0, so we have -r_i + u == 0 hence r_i = u.
# Note: alternatively, we could use the Lambert W function to calculate
# r_i = exp(W(-w_i / (-v_i * e))) * (-v_i * e), but this is more complicated.
function MOI.set(
    model::MOI.ModelLike,
    ::MOI.ConstraintDualStart,
    bridge::RelativeEntropyBridge,
    value,
)
    u = value[1]
    MOI.set(model, MOI.ConstraintDualStart(), bridge.ge_index, u)
    w_start = 1 + length(bridge.y)
    for i in eachindex(bridge.y)
        MOI.set(
            model,
            MOI.ConstraintDualStart(),
            bridge.exp_indices[i],
            [u, value[w_start+i], value[1+i]],
        )
    end
    return
end


text:
# Each test here builds an ODEFunction including some user-registered
# Operations. The test simply checks that calling the ODEFunction
# appropriately calls the registered functions, whether the call is
# qualified (with a module name) or not.

# TEST: Function registration in a module.
# ------------------------------------------------
module MyModule
    using ModelingToolkit, DiffEqBase, LinearAlgebra, Test
    @parameters t x
    @variables u(t)
    Dt = Differential(t)

    function do_something(a)
        a + 10
    end
    @register_symbolic do_something(a)

    eq  = Dt(u) ~ do_something(x) + MyModule.do_something(x)
    @named sys = ODESystem([eq], t, [u], [x])
    fun = ODEFunction(sys)

    u0 = 5.0
    @test fun([0.5], [u0], 0.) == [do_something(u0) * 2]
end

# TEST: Function registration in a nested module.
# ------------------------------------------------
module MyModule2
    module MyNestedModule
        using ModelingToolkit, DiffEqBase, LinearAlgebra, Test
        @parameters t x
        @variables u(t)
        Dt = Differential(t)

        function do_something_2(a)
            a + 20
        end
        @register_symbolic do_something_2(a)

        eq  = Dt(u) ~ do_something_2(x) + MyNestedModule.do_something_2(x)
        @named sys = ODESystem([eq], t, [u], [x])
        fun = ODEFunction(sys)

        u0 = 3.0
        @test fun([0.5], [u0], 0.) == [do_something_2(u0) * 2]
    end
end

# TEST: Function registration outside any modules.
# ------------------------------------------------
using ModelingToolkit, DiffEqBase, LinearAlgebra, Test
@parameters t x
@variables u(t)
Dt = Differential(t)

function do_something_3(a)
    a + 30
end
@register_symbolic do_something_3(a)

eq  = Dt(u) ~ do_something_3(x) + (@__MODULE__).do_something_3(x)
@named sys = ODESystem([eq], t, [u], [x])
fun = ODEFunction(sys)

u0 = 7.0
@test fun([0.5], [u0], 0.) == [do_something_3(u0) * 2]

# TEST: Function registration works with derivatives.
# ---------------------------------------------------
foo(x, y) = sin(x) * cos(y)
@parameters t; @variables x(t) y(t) z(t); D = Differential(t)
@register_symbolic foo(x, y)

using ModelingToolkit: value, arguments, operation
expr = value(foo(x, y))
@test operation(expr) === foo
@test arguments(expr)[1] === value(x)
@test arguments(expr)[2] === value(y)
ModelingToolkit.derivative(::typeof(foo), (x, y), ::Val{1}) = cos(x) * cos(y) # derivative w.r.t. the first argument
ModelingToolkit.derivative(::typeof(foo), (x, y), ::Val{2}) = -sin(x) * sin(y) # derivative w.r.t. the second argument
@test isequal(expand_derivatives(D(foo(x, y))), expand_derivatives(D(sin(x) * cos(y))))

# TEST: Function registration run from inside a function.
# -------------------------------------------------------
# This tests that we can get around the world age issue by falling back to
# GeneralizedGenerated instead of function expressions.
# Might be useful in cases where someone wants to define functions that build
# up and use ODEFunctions given some parameters.
function do_something_4(a)
    a + 30
end
@register_symbolic do_something_4(a)
function build_ode()
    @parameters t x
    @variables u(t)
    Dt = Differential(t)
    eq  = Dt(u) ~ do_something_4(x) + (@__MODULE__).do_something_4(x)
    @named sys = ODESystem([eq], t, [u], [x])
    fun = ODEFunction(sys, eval_expression=false)
end
function run_test()
    fun = build_ode()
    u0 = 10.0
    @test fun([0.5], [u0], 0.) == [do_something_4(u0) * 2]
end
run_test()

using ModelingToolkit: arguments
@variables a
@register_symbolic foo(x,y,z)
@test 1 * foo(a,a,a) * Num(1) isa Num
@test !any(x->x isa Num, arguments(value(1 * foo(a,a,a) * Num(1))))

ext: jl


text:
# module for representing agent
# decide control order to robot
# this agent ignore puddle

mutable struct PuddleIgnoreAgent
  speed
  yaw_rate
  delta_time
  estimator
  prev_spd
  prev_yr
  puddle_coef
  puddle_depth
  total_reward
  in_goal
  final_value
  goal

  # init
  function PuddleIgnoreAgent(;delta_time::Float64=0.1,
                             estimator=nothing,
                             goal=nothing,
                             puddle_coef=100)
    self = new()
    self.speed = 0.0
    self.yaw_rate = 0.0
    self.delta_time = delta_time
    self.estimator = estimator
    self.prev_spd = 0.0
    self.prev_yr = 0.0
    self.puddle_coef = puddle_coef
    self.puddle_depth = 0.0
    self.total_reward = 0.0
    self.in_goal = false
    self.final_value = 0.0
    self.goal = goal
    return self
  end
end

function reward_per_sec(self::PuddleIgnoreAgent)
  return (-1.0 - self.puddle_depth*self.puddle_coef)
end

function policy(pose, goal)
  x, y, theta = pose[1], pose[2], pose[3]
  dx, dy = goal.pose[1]-x, goal.pose[2]-y
  direction = Int64(round((atan(dy, dx) - theta) * 180 / pi))
  direction = (direction + 360*1000 + 180)%360 - 180 # normalize -180 ~ 180 [deg]

  if direction > 10
    speed, yaw_rate = 0.0, 2.0
  elseif direction < -10
    speed, yaw_rate = 0.0, -2.0
  else
    speed, yaw_rate = 1.0, 0.0
  end

  return speed, yaw_rate
end

function draw_decision!(self::PuddleIgnoreAgent, observation)
  # reached goal
  if self.in_goal == true
    return 0.0, 0.0 # stop
  end

  if self.estimator !== nothing
    motion_update(self.estimator, self.prev_spd, self.prev_yr, self.delta_time)
    observation_update(self.estimator, observation)

    self.total_reward += self.delta_time * reward_per_sec(self)

    self.speed, self.yaw_rate = policy(self.estimator.estimated_pose, self.goal)
    self.prev_spd, self.prev_yr = self.speed, self.yaw_rate

    draw!(self.estimator)
    x = self.estimator.estimated_pose[1]
    y = self.estimator.estimated_pose[2]
    annotate!(x+1.0, y-0.5, text("reward/sec:$(reward_per_sec(self))", :left, 8))
    annotate!(x+1.0, y-1.0, text("total reward:$(round(self.total_reward, digits=1))", :left, 8))
  end

  return self.speed, self.yaw_rate
end

max_stars_repo_name: ShisatoYano/JuliaAutonomy

max_issues_repo_name: ShisatoYano/JuliaAutonomy

max_forks_repo_name: ShisatoYano/JuliaAutonomy


text:
features_df = DataFrames.DataFrame()
labels_df = DataFrames.DataFrame()
labels_df[:y] = [1,2,3]

Test.@test_throws(ErrorException, PredictMD.split_data(features_df,
                                                        labels_df,
                                                        2.0))

Test.@test_throws(ErrorException, PredictMD.split_data(features_df,
                                                        labels_df,
                                                        0.5))


text:
import Random: AbstractRNG, rand, rand!

abstract type VSLDistribution{T} <: AbstractRNG end

rand(d::VSLDistribution{T}, dims::Integer...) where T = rand(d, T, Dims(dims))

function rand(d::VSLDistribution{T}, ::Type{X}) where {T, X}
    error("Only $(T) type is supported for $d.")
end

function rand!(d::VSLDistribution{T}, A::AbstractArray{K}, ::Type{X}=T) where {T, K, X}
    # T !== K || T !== X
    error("Only $(T) type is supported for $d.")
end


text:
using DiffEqBase, OrdinaryDiffEq, DiffEqBiological, DiffEqJump, DiffEqProblemLibrary.JumpProblemLibrary, Plots, Statistics
gr()
fmt = :png
JumpProblemLibrary.importjumpproblems()

jprob = prob_jump_dnadimer_repressor
rn = jprob.network
rnpar = jprob.rates
varlabels = jprob.prob_data["specs_names"]
u0 = jprob.u0
tf = jprob.tstop

u0f = [1000., 0., 0., 0.,0.]
odeprob = ODEProblem(rn, u0f, (0.,tf),rnpar)
sol = solve(odeprob,Tsit5())
plot(sol, format=:png, label=varlabels)

tf      = 4000.
methods = (Direct(),DirectFW(),FRM(),FRMFW(),SortingDirect(),NRM(),DirectCR(),RSSA())
shortlabels = [string(leg)[12:end-2] for leg in methods]
prob    = prob = DiscreteProblem(u0, (0.0, tf), rnpar)
ploth   = plot(reuse=false)
p = []
for (i,method) in enumerate(methods)
    jump_prob = JumpProblem(prob, method, rn, save_positions=(false,false))
    sol = solve(jump_prob, SSAStepper(), saveat=tf/1000.)
    plot!(ploth,sol.t,sol[3,:],label=shortlabels[i], format=fmt)
    push!(p, plot(sol,title=shortlabels[i],leg=false,format=fmt))
end
plot(ploth, title="Protein level", xlabel="time",format=fmt)

plot(p[end],format=fmt,legend=true,labels=varlabels)

function run_benchmark!(t, jump_prob, stepper)
    sol = solve(jump_prob, stepper)
    @inbounds for i in 1:length(t)
        t[i] = @elapsed (sol = solve(jump_prob, stepper))
    end
end

nsims = 50
benchmarks = Vector{Vector{Float64}}()
for method in methods
    jump_prob = JumpProblem(prob, method, rn, save_positions=(false,false))
    stepper = SSAStepper()
    t = Vector{Float64}(undef, nsims)
    run_benchmark!(t, jump_prob, stepper)
    push!(benchmarks, t)
end

medtimes = Vector{Float64}(undef,length(methods))
stdtimes = Vector{Float64}(undef,length(methods))
avgtimes = Vector{Float64}(undef,length(methods))
for i in 1:length(methods)
    medtimes[i] = median(benchmarks[i])
    avgtimes[i] = mean(benchmarks[i])
    stdtimes[i] = std(benchmarks[i])
end

using DataFrames
df = DataFrame(names=shortlabels,medtimes=medtimes,relmedtimes=(medtimes/medtimes[1]),avgtimes=avgtimes, std=stdtimes, cv=stdtimes./avgtimes)
sa = [text(string(round(mt,digits=3),"s"),:center,12) for mt in df.medtimes]
bar(df.names,df.relmedtimes,legend=:false, fmt=fmt)
scatter!(df.names, .05 .+ df.relmedtimes, markeralpha=0, series_annotations=sa, fmt=fmt)
ylabel!("median relative to Direct")
title!("Marchetti Gene Expression Model")

using DiffEqBenchmarks
DiffEqBenchmarks.bench_footer(WEAVE_ARGS[:folder],WEAVE_ARGS[:file])


text:
# Copyright (c) 2021 Idiap Research Institute, http://www.idiap.ch/
#  Niccolò Antonello <nantonel@idiap.ch>

export RightStringWeight

"""
`RightStringWeight(x)`

| Set                     |        ``\\oplus``     |   ``\\otimes`` | ``\\bar{0}`` | ``\\bar{1}`` |
|:-----------------------:|:----------------------:|:--------------:|:------------:|:------------:|
|``L^*\\cup\\{\\infty\\}``|  longest common suffix |     ``\\cdot`` |``\\infty``   |``\\epsilon`` |

where ``L^*`` is Kleene closure of the set of characters ``L`` and ``\\epsilon`` the empty string.
"""
struct RightStringWeight <: Semiring
  x::String
  iszero::Bool
end
RightStringWeight(x::String) = RightStringWeight(x,false)
reversetype(::Type{S}) where {S <: RightStringWeight} = LeftStringWeight

zero(::Type{RightStringWeight}) = RightStringWeight("",true)
one(::Type{RightStringWeight})  = RightStringWeight("",false)

# longest common suffix
function lcs(a::RightStringWeight,b::RightStringWeight)
  if a.iszero
    return b
  elseif b.iszero
    return a
  else
    cnt = 0
    for x in zip(reverse(a.x),reverse(b.x))
      if x[1] == x[2]
        cnt +=1
      else
        break
      end
    end
    return RightStringWeight(a.x[end-cnt+1:end])
  end
end

*(a::T, b::T) where {T<:RightStringWeight}=
((a.iszero) | (b.iszero)) ? zero(T) : T(a.x * b.x)
+(a::RightStringWeight, b::RightStringWeight) = lcs(a,b)
function /(a::RightStringWeight, b::RightStringWeight)
  if b == zero(RightStringWeight)
    throw(ErrorException("Cannot divide by zero"))
  elseif a == zero(RightStringWeight)
    return a
  end
  return RightStringWeight(a.x[1:end-length(b.x)])
end
reverse(a::RightStringWeight) = LeftStringWeight(reverse(a.x),a.iszero)

#properties
isidempotent(::Type{W}) where {W <: RightStringWeight} = true
isright(::Type{W}) where {W <: RightStringWeight}= true
isweaklydivisible(::Type{W}) where {W <: RightStringWeight}= true


text:
function ft_symmetric_group(f::Function, n::Int)
    table = standard_tableaux(n)
    d_λ = Dict(λ => length(table[n][λ]) for λ in integer_partitions(n))
    f̂ = Dict(λ => zeros(Float64, d_λ[λ], d_λ[λ]) for λ in integer_partitions(n))

    for σ in permutations(1:n, n)
        g = SymmetricGroup(σ)
        for λ in integer_partitions(n)
            f̂[λ] .+= f(g) * irrep(g, λ)'
        end
    end

    for λ in integer_partitions(n)
        f̂[λ] *= d_λ[λ] / factorial(n)
    end

    return f̂
end

fft{N}(f::Function, ::Type{SymmetricGroup{N}}, L::Int) = ft_symmetric_group(f, N)


text:
taskheap() = lockedheap(Pair{PriorityInt,Task}, PriorityInt; by = first)
# Note: to avoid messing up the heap invariance, the priority is quenched by the
# time it is pushed to the heap

const TaskHeap = typeof(taskheap())

mutable struct PrioritizedScheduler <: AbstractScheduler
    @const unfairspins::Int
    @const yieldspins::Int
    @const workerindices::Vector{Int}
    @const threadids::Vector{Int}
    @const workers::Vector{Worker}
    @const multiq::MultiQueue{TaskHeap}
    @const externalqueue::ConcurrentQueue{Task}
    @atomic closed::Bool
end

function PrioritizedScheduler(
    threadids::Vector{Int};
    unfairspins::Integer = -1,
    yieldspins::Integer = default_yieldspins(),
    c::Real = 2,
)
    workerindices = workerindices_from_threadids(threadids)
    ref = Ref{PrioritizedScheduler}()
    workers = create_workers(threadids, ref)
    heaps = [taskheap() for _ in 1:ceil(Int, c * length(threadids))]
    if length(heaps) < length(threadids)
        error(
            "not enough number of heaps: length(heaps) = ",
            length(heaps),
            " ≥ length(threadids) = ",
            length(threadids),
            "; i.e., c = ",
            c,
            " is too small",
        )
    end
    scheduler = PrioritizedScheduler(
        unfairspins,
        yieldspins,
        workerindices,
        threadids,
        workers,
        MultiQueue(heaps),
        ConcurrentQueue{Task}(),
        false,
    )
    ref[] = scheduler
    return scheduler
end

function Base.push!(scheduler::PrioritizedScheduler, task::Task)
    priority = thunkof(task).priority
    push!(scheduler.multiq, -priority => task)
    return scheduler
end

function get_next_task!(scheduler::PrioritizedScheduler, _isretry::Bool)
    let y = maybepopfirst!(scheduler.externalqueue)
        if y isa Some
            return something(y)::Task
        end
    end
    while true

        y = trypop!(scheduler.multiq)
        if y isa Some
            return last(something(y))::Task
        else
            # TODO: do different things when `Contention` vs `LikelyEmpty`?
            return nothing
        end
    end
end

function Schedulers.setpriority(priority::Integer)
    priority = as_priority(priority)
    thunkof(Schedulers.current_task()).priority = priority
    return
end


text:
# # Model Updates
#
# When a pareto-optimal front in portfolio optimisation is computed for different risk-aversion parameters $\gamma$, we are repeatedly solving the same model with only a slight change in the cost function. This allows us to reuse the KKT factorisation from previous solves and recompute the solution very efficiently, see [Algorithm](@ref).
# For more information about solving portfolio optimsiation problems with COSMO see [Portfolio Optimisation](@ref).
# We are planning to solve the following QP for different values of $\gamma$:
# $$
# \begin{array}{ll} \text{minimize} &  x^\top D x + y^\top y - \gamma^{-1} \mu^\top x \\
# \text{subject to} &  y = F^\top x \\
#                   &  1^\top x = d + 1^\top x^0 \\
#                    &  x  \geq 0,
# \end{array}
# $$
# As you can see $\gamma$ enters only in the linear part of the cost function, i.e. our vector `q`. Let's generate some example data:
using LinearAlgebra, SparseArrays, Random, COSMO

rng = Random.MersenneTwister(1)
k = 5; # number of factors
n = k * 10; # number of assets
D = spdiagm(0 => rand(rng, n) .* sqrt(k))
F = sprandn(rng, n, k, 0.5); # factor loading matrix
μ = (3 .+ 9. * rand(rng, n)) / 100. # expected returns between 3% - 12%
d = 1 # we are starting from all cash
x0 = zeros(n);

# We want to solve this problem for the following risk-parameters:
gammas = [ 0.001, 0.01, 0.1,  0.5,  1., 3., 10, 100, 1000]

# Let's solve the problem for the first parameter:
## x = (x, y)
γ = gammas[1]
P = blockdiag(D, spdiagm(0 => ones(k)))
q = [-μ ./ (2 * γ); zeros(k)];

Aeq = [ transpose(F) -diagm(0 => ones(k));
        ones(1, n) zeros(1, k)]
beq = [zeros(k); -1.0]
Aineq = [spdiagm(0 => ones(n)) spzeros(n, k)]

cs1 = COSMO.Constraint(Aeq, beq, COSMO.ZeroSet);
cs2 = COSMO.Constraint(Aineq, zeros(n), COSMO.Nonnegatives);
cosmo_settings = COSMO.Settings(verbose = false)

## solve the problem once
model = COSMO.Model();
assemble!(model, P, q, [cs1; cs2], settings = cosmo_settings);
result = COSMO.optimize!(model);
x_opt = view(result.x, 1:n);
y_opt = view(result.x, n+1:n+k);

## allocate some space for results
risks = zeros(length(gammas));
returns = zeros(length(gammas));
returns[1] = dot(μ, x_opt);
risks[1] = sqrt(dot(y_opt, y_opt));

# After a successful solve, we can use the `update!(model, q = nothing, b = nothing)` function to update our model and re-solve the problem efficiently:

## solve the problem efficiently for the remaining γ using model updates
function solve_repeatedly!(returns, risks, gammas, model, k, n, μ)
        for (i, γ) in enumerate(gammas[2:end])
                q_new = [-μ ./ (2 * γ); zeros(k)];

                ## here we use the update! function to change the model
                update!(model, q = q_new)
                result = COSMO.optimize!(model);

                x_opt = view(result.x, 1:n)
                y_opt = view(result.x, n+1:n+k)
                returns[i + 1] = dot(μ, x_opt)
                risks[i + 1] = sqrt(dot(y_opt, y_opt))
        end
end
solve_repeatedly!(returns, risks, gammas, model, k, n, μ);

# We can now plot the risk-return trade-off curve:
using Plots
Plots.plot(risks, returns, xlabel = "Standard deviation (risk)", ylabel = "Expected return", title = "Risk-return trade-off for efficient portfolios", legend = false)


text:
import Base:∩,<

##################################################
# Types for lines
##################################################

abstract type AbstractLine end

struct Line <: AbstractLine
    """
    Lines are described by the polar coordinates (θ, r)
    of the orthogonal projection of the origin.

    - θ is in [0, 2pi).
        - r is a nonnegative number.
    """
    θ::Float64
    r::Float64
end

mutable struct SweepLine <: AbstractLine
    """
    A vertical line, for the BO algorithm.
    """
    θ::Float64
    r::Float64
    SweepLine(r) = new(0, r)
end

struct RootedLine <: AbstractLine
    """
    It is a line, rooted at a certain x-position given by
    the sweep-line.
    """
    θ::Float64
    r::Float64
    ∅::SweepLine
    RootedLine(l::Line, sl::SweepLine) = new(l.θ, l.r, sl)
end

################################################
# Methods
################################################

function point_in_line(ℓ::AbstractLine, x::Float64)::Float64
    """
    Outputs the unique y such that (x, y) ∈ ℓ.
    """
    r = ℓ.r ; θ = ℓ.θ
    @assert θ!=0 throw(error("No vertical lines."))
    return r/sin(θ) - x/tan(θ)
end

function <(l1::RootedLine, l2::RootedLine)
    """
    A rooted line is smaller than another if the intersection with
    its sweepline is smaller than the other.
    """
    a = point_in_line(l1, l1.∅.r)
    b = point_in_line(l2, l2.∅.r)
    return a<b
end

function point_in_line(l::Line, x::Array{Float64})::Array{Float64}
    """
    Computes L(x) for any array x
    """
    r = l.r ; θ = l.θ
    return r/sin(θ) .- ( x ./ tan(θ) )
end

function intersection_with_circle(l::AbstractLine, R::Real)
    """
    Computes the two intersection of line l with the
    circle of radius R centered at zero.

    If there are no such intersections, returns nothing.
    Outputs the two points from left to right.
    """
    if R <= l.r
        return nothing
    else
        α = acos(l.r / R)
        x₁ = Array([R * cos(l.θ + α), R * sin(l.θ + α)])
        x₂ = Array([R * cos(l.θ - α), R * sin(l.θ - α)])
        return isless(x₁, x₂) ? (x₁, x₂) : (x₂, x₁)
    end

end

function get_endpoints(L::Array{Line, 1}, R::Real)
    """
    Given an array of n lines, computes the intersections of each
    line with a given circle of radius 1, then outputs the 2n intersection points.

    Input:
        an array of n Line

    Output:
        V, a 2×2n array of Floats. The vector V[:, 2i-1] is the leftpoint of
        line H[i] and V[:, 2i] is the right endpoint.
    """
    n = length(L) #number of lines
    output = zeros(2, 2 * n) #first line is x-coordinate of point

    for i in 1:n
        (a,b) = intersection_with_circle(L[i])
        output[:, 2*i-1] = a
        output[:, 2*i] = b
    end
    return output
end

normof(p) = p[1]^2 + p[2]^2

function ∩(l1::AbstractLine, l2::AbstractLine)::Array{Float64}
    """
    Input:
        two nonparallel line objects l1 and l2.

    Output:
        the cartesian coordinates of their intersection point.
    """
    #@assert l1.θ!=l2.θ "Lines must not be parallel. "
    u = (l2.r / sin(l2.θ)) - (l1.r / sin(l1.θ))
    d = (1/tan(l2.θ) - 1/tan(l1.θ))
    x = u/d
    return Array([x, point_in_line(l1, x)])
end

max_stars_repo_name: SimonCoste/LineIntersections

max_issues_repo_name: SimonCoste/LineIntersections

max_forks_repo_name: SimonCoste/LineIntersections


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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing
        el
    end
end

# ╔═╡ 6e070dde-de71-11eb-11e0-9161dfe3c5b6
# Import the packages and export their exported functions to the main namespace.
using StatsPlots, PlutoUI, Random

# ╔═╡ 0d9c0987-470d-4b2e-a446-b321a92e2b59
md"""
# Assignment 1 - Q4: Simulating Gaussian Distributions

Welcome to Pluto Notebooks! In this course you will be spending quite a bit of time working within these notebooks. These notebooks are an HTML/CSS/Javascript built interface for interacting with and working with Julia. They were inspiried by Jupyter, and you can learn more about the notebooks through [their github](https://github.com/fonsp/Pluto.jl). The notebooks are lightweight (with files that can be used by the normal julia interpretor), and track how notebook cells depend on eachother to re-run cells when their dependencies change.

The only code in this notebook which is not found in julia's base is the plotting code provided by [StatsPlots](https://github.com/JuliaPlots/StatsPlots.jl) and [Plots](http://docs.juliaplots.org/latest/). Please go read more about these packages, as they will be useful for you throught the course. Another package we use is [PlutoUI]() which contains a multitude of utilities for building interfaces in pluto notebooks (see below). For all the cells, some are hidden by default. To see hidden cells click on the eye to the top-left of the cell of interest.

To complete this assignment you shouldn't need to import any other packages.

In this assignment you will:
1. Learn about using Pluto Notebooks and Stats Plots for visualizing and analysing data.
2. Get experience with calculating the mean, variance, and other metrics of sample data.
3. Build intuition about how a gaussian distribution acts with various parameters.

"""

# ╔═╡ 6e95d732-b580-450a-85db-447444fea409
md"""
### !!!IMPORTANT!!!

Insert your details below. You should see a green checkmark.
"""

# ╔═╡ 8228b64b-96bf-422a-8e01-0e69594343f1
student = (name="Nasif", email="nhossain@ualberta.ca", ccid="nhossain", idnumber=1545143)

# ╔═╡ c4769b33-9ecb-4a1d-b927-d3b5b3351bf4
let
	def_student = (name="NAME as in eclass", email="UofA Email", ccid="CCID", idnumber=0)
	if length(keys(def_student) ∩ keys(student)) != length(keys(def_student))
		md"You don't have all the right entries! Make sure you have `name`, `email`, `ccid`, `idnumber`. ❌"
	elseif any(getfield(def_student, k) == getfield(student, k) for k in keys(def_student))
		md"You haven't filled in all your details! ❌"
	elseif !all(typeof(getfield(def_student, k)) === typeof(getfield(student, k)) for k in keys(def_student))
		md"Your types seem to be off: `name::String`, `email::String`, `ccid::String`, `idnumber::Int`"
	else
		md"Welcome $(student.name)! ✅"
	end
end

# ╔═╡ a29b97a4-ad2e-4888-97bc-6d129c7a19ba
with_terminal() do
	println("Hello worlds")
end

# ╔═╡ 859041a0-98b0-427d-8d92-f53f29176805
md"""
## Gaussian Distribution

A gaussian distribution with mean μ, standard deviation σ. Sample data from this distribution using sample(gd, n). You can also get the mean (mean), standard deviation (stddev), and variance (var) through their corresponding functions.
"""

# ╔═╡ 6c1fd792-91ac-4b3d-96b2-8e108b8caf55
# The block of text below add documentation to julia struct or function.
# Check out the live docs to the right when your cursor
# is in GaussianDistribution.
"""
	GaussianDistribution(μ::Float64, σ::Float64)

	A gaussian distribution with mean μ, standard deviation σ. Sample data from this distribution using `sample(gd, n)`. You can also get the mean (`mean(gd)`), standard deviation (`stddev(gd)`), and variance (`var(gd)`) through their corresponding functions.
	"""
struct GaussianDistribution
	μ::Float64 # mean
	σ::Float64 # standard deviation
end

# ╔═╡ 29d1cde5-a0e5-4539-9490-bff81109bd07
mean(gd::GaussianDistribution) = gd.μ

# ╔═╡ d0d7c379-f03a-4dd9-a3f2-88835e2ecebb
stddev(gd::GaussianDistribution) = gd.σ

# ╔═╡ d281372b-1473-4e6c-8f9f-cb8f280d8f07
var(gd::GaussianDistribution) = gd.σ^2

# ╔═╡ 131f1dbd-c128-4d12-8163-250361c13337
function sample(gd::GaussianDistribution, n = 1)
	gd.σ*randn(n) .+ gd.μ
end

# ╔═╡ 07fba25d-ffc3-4eb5-aebf-742e31267aa1
md"""
## Implementing basic statistcs from data

Below you will be implementing the sample mean, variance, and standard deviation of a dataset X. This dataset is guaranteed to be a vector of floating point numbers. We want the estimates of the variance and standard deviation to be unbiased.

"""

# ╔═╡ e8437a34-c89b-4da6-ad49-56ea445bacd9

# ╔═╡ b950704c-4276-4e06-bad0-944aab0b767b

# ╔═╡ 6fcf8a25-07a9-4d5a-8aa4-af4c4d38c96c
function mean(X::Vector{Float64})
	s = 0
	for x in X
		s += x
	end
	return s / length(X)
end

# ╔═╡ 10a62eea-efc1-416c-a789-21245a2c3470
function var(X::Vector{Float64})
	m = mean(X)
	v = 0
	n = length(X) - 1
	for x in X
	    v += (x - m)^2 / n
	end
    return v
end

# ╔═╡ eb442864-b44d-4980-bb8f-912bc802d4d2
function stddev(X::Vector{Float64})
	sqrt(var(X))
end

# ╔═╡ 5a89a61f-fb50-4843-97da-a1c526aa6a64
let
	# Testing cell
	X = [1.0, 2.0, 3.0, 4.0, 5.0]
	μ̂ = mean(X)
	σ̂ = stddev(X)
	v = var(X)
	μ̂, σ̂, v
	if μ̂ == 3.0 && σ̂ == sqrt(2.0) && v == 2.0
		md"**Ok, but something is slightly wrong!** 🤔"
	elseif μ̂ == 3.0 && σ̂ == sqrt(2.5) && v == 2.5
		md"**Great job!** ✅🎉"
	else
		md"**Keep at it** ❌"
	end
end

# ╔═╡ ff54abab-068a-442f-8572-2da4d90f1fdd
md"""
### Simulating sample variance

Use the below let blocks to complete question 4(bcde). You will be graded on your written work, not on the code in these cells.
"""

# ╔═╡ dfe61219-4c26-4cf1-a9ba-3a6abddfdaa8
md"
Run the code for 10 samples with µ = 0 and σ 2 = 1.0. Write down the sample average that you obtain. Now do this another 4 times, giving you 5 estimates of the sample average M1, M2, M3, M4 and M5. What is the sample variance of these 5 estimates? Use the unbiased sample variance formula. Note that here we want to understand the
variability of the mean estimator itself, if it had been run on different datasets; beautifully we can actually simulate this using synthetic data.
"

# ╔═╡ 9406e2bf-c6c6-4cc2-a79e-376fdb554df5
let # 4b
	# using the means from the 10 samples
	X = [0.09177, 0.1362, 0.553, 0.3527, -0.1012]
	μ̂ = mean(X)
	σ̂ = stddev(X)
	v = var(X)
	with_terminal() do
		println("Sample average ", μ̂)
		println("Variance " , v)
	end
end

# ╔═╡ 1513064c-438e-44e3-9e95-6500219eac00
md"Now run the same experiment, but use 100 samples for each sample average
estimate. What is the sample variance of these 5 estimates? How is it different from the variance when you used 10 samples to compute the estimates?"

# ╔═╡ 42b5216b-1127-4733-953f-652e4afbc105
let # 4c
	# using the means from the 100 samples
	X = [-0.05904, 0.1058, 0.0677, -0.1398, 0.08169]
	μ̂ = mean(X)
	σ̂ = stddev(X)
	v = var(X)
	with_terminal() do
		println("Sample average ", μ̂)
		println("Variance " , v)
	end
end

# ╔═╡ 26839ac2-9e84-42e4-9936-7132711a3b8c
md"
(d) Now let us consider a higher variance situation, where σ
2 = 10.0. Imagine you
know this variance, and that the data comes from a Gaussian, but that you do not know the true
mean. Run the code to get 30 samples, and compute one sample average M. What is the 95%
confidence interval around this M? Give actual numbers.

(e) [8 marks] Now assume you know less: you do not know the data is Gaussian, though you
still know the variance is σ
2 = 10.0. Use the same 30 samples from (d) and resulting sample average
M. Give a 95% confidence interval around M, now without assuming the samples are Gaussian."

# ╔═╡ 34fe4272-f9e8-4a3d-acac-47e7b9c23797
let # 4d, 4e
	# using the means from the 30 samples with variance 10
	μ̂ = 0.1138
	v = 10
	with_terminal() do
		println("Variance " , v)
	end
end

# ╔═╡ 4ed5ce0f-8aa2-4a82-97a6-cdde9220f19f
md"""

## Plotting

Below you will see some example plotting code `plot_density` and `plot_box_and_violin`.

`plot_density` plots a histogram of the data passed through X and a density estimated through a kernel density algorithm (see implementation on [github](https://github.com/JuliaPlots/StatsPlots.jl) for more details).

`plot_box_and_violin` plots a box plot over a violin plot. A violin plot shows the density of the sampled data (same as the `density` function), while the overlayed box plot shows the first quartile, median, and third quartile. More information can be found on [github](https://github.com/JuliaPlots/StatsPlots.jl) about these plotting utilites.

"""

# ╔═╡ 1e613f8c-4639-449e-8c40-f0be93c1ca46
function plot_density(X)
	histogram(
		# data/transform paramters
		X, norm=true,
		# make plot pretty parameters
		grid=false, # removes background grid
		tickdir=:out, # changes tick direction to be out
		lw=1, # makes line width thicker
		color=RGB(87/255, 123/255, 181/255), # Changes fill color of histogram
		legend=nothing, # removes legend
		fillalpha=0.6) # makes the histogram transparent

	density!(X, color=:black, lw=2)
end

# ╔═╡ b62fa4e7-7ff6-46a0-8232-b106e8adbc20
function plot_box_and_violin(X)
	plt = violin(
		["data"], #The label for the data on the x-axis
		X, # the data
		grid=false, # remove the background grid
		tickdir=:out, # set the ticks to be out
		lw=0, # set the line width to be zero
		color=RGB(87/255, 123/255, 181/255), # set color
		legend=nothing)
	boxplot!(
		plt, # explicitly pass in plt object
		["data"], #The label for the data on the x-axis
		X, # the data
		fillalpha=0.5, # make transparent
		lw=3) # emphasize the lines

end

# ╔═╡ 8bbbfb8c-6582-4fe8-928d-714eb56a0ad1
# This is a markdown block.
md"""
## Visualizing the distribution from samples

Below are some sliders you can use to visualize different normal distribtuions interactively. The data is then plotted using the above plotting functions.

Mean: $(@bind mu Slider(-100.0 : 0.1 : 100.0; default=0.0, show_value=true))

Std Dev: $(@bind sigma Slider(0.1 : 0.1: 100.0; default=1.0, show_value=true))

number of samples: $(@bind n Slider(10 : 10 : 10000; default=100, show_value=true))

$(@bind resample_btn Button("Resample"))
"""

# ╔═╡ 6c23eb8c-bf97-462e-a0b0-5a72ff2ce1b7
gd = GaussianDistribution(mu, sigma)

# ╔═╡ cc2729ed-6e19-4596-8daf-6a87fb7763df
begin
	resample_btn
	X = sample(gd, n)
end;

# ╔═╡ eb13fb20-d27a-4cb2-b42c-2aba098a6a48
let
	x̄ = mean(X)
	σ̄ = stddev(X)
	"Sample mean: $(x̄), Sample Standard Deviation: $(σ̄)"
end

# ╔═╡ e94d17ab-862e-4c13-9b65-a4df009c59a0
let
	plt_1 = plot_density(X)
	plt_2 = plot_box_and_violin(X)
	plot(plt_1, plt_2)
end

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"

[compat]
PlutoUI = "~0.7.9"
StatsPlots = "~0.14.26"
"""

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

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

[[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"]
git-tree-sha1 = "9995eb3977fbf67b86d0a0a0508e83017ded03f2"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.14.0"

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

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

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

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

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

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

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

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

[[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 = "3889f646423ce91dd1055a76317e9a1d3a23fff1"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.11"

[[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", "Statistics"]
git-tree-sha1 = "8c8eac2af06ce35973c3eadb4ab3243076a408e7"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "0.12.1"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[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 = "0b4a5d71f3e5200a7dff793393e09dfc2d874290"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+1"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "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 = "c0f4a4836e5f3e0763243b8324200af6d0e0f90c"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.5"

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

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

[[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 = "477bf42b4d1496b454c10cce46645bb5b8a0cf2c"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.0.2"

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

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

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

[[PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "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 = "8365fa7758e2e8e4443ce866d6106d8ecbb4474e"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.20.1"

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

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

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

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

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

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

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

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

[[RecipesBase]]
git-tree-sha1 = "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 = "a3a337914a035b2d59c9cbe7f1a38aaba1265b02"
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
version = "1.3.6"

[[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 = "a322a9493e49c5f3a10b50df3aedaf1cdb3244b7"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "1.6.1"

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

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

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

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

[[StatsFuns]]
deps = ["IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "20d1bb720b9b27636280f751746ba4abb465f19d"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "0.9.9"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "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:
# ╟─0d9c0987-470d-4b2e-a446-b321a92e2b59
# ╠═6e070dde-de71-11eb-11e0-9161dfe3c5b6
# ╠═6e95d732-b580-450a-85db-447444fea409
# ╠═8228b64b-96bf-422a-8e01-0e69594343f1
# ╠═c4769b33-9ecb-4a1d-b927-d3b5b3351bf4
# ╠═a29b97a4-ad2e-4888-97bc-6d129c7a19ba
# ╟─859041a0-98b0-427d-8d92-f53f29176805
# ╠═6c1fd792-91ac-4b3d-96b2-8e108b8caf55
# ╠═29d1cde5-a0e5-4539-9490-bff81109bd07
# ╠═d0d7c379-f03a-4dd9-a3f2-88835e2ecebb
# ╠═d281372b-1473-4e6c-8f9f-cb8f280d8f07
# ╠═131f1dbd-c128-4d12-8163-250361c13337
# ╟─07fba25d-ffc3-4eb5-aebf-742e31267aa1
# ╠═e8437a34-c89b-4da6-ad49-56ea445bacd9
# ╟─b950704c-4276-4e06-bad0-944aab0b767b
# ╠═5a89a61f-fb50-4843-97da-a1c526aa6a64
# ╠═6fcf8a25-07a9-4d5a-8aa4-af4c4d38c96c
# ╠═10a62eea-efc1-416c-a789-21245a2c3470
# ╠═eb442864-b44d-4980-bb8f-912bc802d4d2
# ╟─ff54abab-068a-442f-8572-2da4d90f1fdd
# ╟─dfe61219-4c26-4cf1-a9ba-3a6abddfdaa8
# ╠═9406e2bf-c6c6-4cc2-a79e-376fdb554df5
# ╟─1513064c-438e-44e3-9e95-6500219eac00
# ╠═42b5216b-1127-4733-953f-652e4afbc105
# ╟─26839ac2-9e84-42e4-9936-7132711a3b8c
# ╠═34fe4272-f9e8-4a3d-acac-47e7b9c23797
# ╟─4ed5ce0f-8aa2-4a82-97a6-cdde9220f19f
# ╟─1e613f8c-4639-449e-8c40-f0be93c1ca46
# ╟─b62fa4e7-7ff6-46a0-8232-b106e8adbc20
# ╟─8bbbfb8c-6582-4fe8-928d-714eb56a0ad1
# ╠═6c23eb8c-bf97-462e-a0b0-5a72ff2ce1b7
# ╠═cc2729ed-6e19-4596-8daf-6a87fb7763df
# ╠═eb13fb20-d27a-4cb2-b42c-2aba098a6a48
# ╠═e94d17ab-862e-4c13-9b65-a4df009c59a0
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_path: Assignment 1/A1.jl

max_issues_repo_path: Assignment 1/A1.jl

max_forks_repo_path: Assignment 1/A1.jl


text:
export matern1, matern3, matern5, sq_exp

"""
    matern1(x1, x2; σ=1)

The matern1 kernel function. (Also called covariance function.)

Use this function as a parameter for the `gaussian_process` function.

See also [`gaussian_process`](@ref), [`matern3`](@ref), [`matern5`](@ref), [`sq_exp`](@ref).
"""
function matern1(x1, x2; σ=1)
    r = radius(x1, x2)
    return σ^2 * exp(- r)
end

"""
    matern3(x1, x2; σ=1)

The matern3 kernel function. (Also called covariance function.)

Use this function as a parameter for the `gaussian_process` function.

See also [`gaussian_process`](@ref), [`matern1`](@ref), [`matern5`](@ref), [`sq_exp`](@ref).
"""
function matern3(x1, x2; σ=1)
    r = radius(x1, x2)
    return σ^2 * exp(- sqrt(3) * r) * (1 + sqrt(3) * r)
end

"""
    matern5(x1, x2; σ=1)

The matern5 kernel function. (Also called covariance function.)

Use this function as a parameter for the `gaussian_process` function.

See also [`gaussian_process`](@ref), [`matern1`](@ref), [`matern3`](@ref), [`sq_exp`](@ref).
"""
function matern5(x1, x2; σ=1)
    r = radius(x1, x2)
    return σ^2 * exp(- sqrt(5) * r) * (1 + sqrt(5) * r + (5/3) * r^2)
end

"""
    matern1(x1, x2; σ=1)

The "squared exponential" kernel function. (Also called covariance function.)

Use this function as a parameter for the `gaussian_process` function.

See also [`gaussian_process`](@ref), [`matern1`](@ref), [`matern3`](@ref), [`matern5`](@ref).
"""
function sq_exp(x1, x2; σ=1)
    r = radius(x1, x2)
    return σ^2 * exp(- (1/2) * r^2)
end

# return r::Real
radius(x1, x2) = abs(x1 - x2)


text:
function ispalindrome(a)
  s = string(a)
  mid = Int(floor(length(s)/ 2))
  r = true
  for j = 1:mid
    if s[j] != s[end-(j-1)]
      r = false
      break
    end
  end
  return r
end

function istwo3digitprod(a)
  r = false
  for i = 100:999
    if a%i == 0 && 100 <= a/i <= 999
      r = true
      break
    end
  end
  return r
end

for i = 999*999:-1:100*100
  if ispalindrome(i) && istwo3digitprod(i)
    println(i)
    break
  end
end

max_stars_repo_name: sujimodern/project-euler-jl

max_issues_repo_name: sujimodern/project-euler-jl

max_forks_repo_name: sujimodern/project-euler-jl


text:
"""
```
abstract type AbstractIntegrator end
struct AdaptiveEulerTrapezoid <: AbstractIntegrator end
```
Integrator types for dispatch.
"""
abstract type AbstractIntegrator end
struct AdaptiveEulerTrapezoid <: AbstractIntegrator end

"""
```
struct IntegrationParameters{T1,T2,T3,T4,T5,T6,T7,T8,T9,T10}
    method::T1
    tmin::T2
    tmax::T3
    dtmin::T4
    dtmax::T5
    abstol::T6
    reltol::T7
    maxchange::T8
    exponent::T9
    maxiter::T10
end
```
Stores integration parameters.
"""
struct IntegrationParameters{T1, T2, T3, T4, T5, T6, T7, T8, T9, T10}
    method::T1
    tmin::T2
    tmax::T3
    dtmin::T4
    dtmax::T5
    abstol::T6
    reltol::T7
    maxchange::T8
    exponent::T9
    maxiter::T10
end

"""
```
struct IntegrationTime{T1,T2,T3}
    dt::T1      # Current time step.
    time::T2    # Current simulation time.
    step::T3    # Current simulation step.
end
```
Store integration time and steps.
"""
struct IntegrationTime{T1, T2, T3}
    dt::T1
    time::T2
    step::T3
end

max_stars_repo_name: dcelisgarza/DDD

max_forks_repo_name: dcelisgarza/DDD


text:
using LabelledArrays

export lorenz_lorenz_lorenz_transitive

@inline @inbounds function eom_lorenz_lorenz_lorenz_transitive(u, p, t)
    x₁, y₁, z₁, x₂, y₂, z₂, x₃, y₃, z₃ = (u...,)
    σ₁, σ₂, σ₃, ρ₁, ρ₂, ρ₃, β₁, β₂, β₃, c₁₂, c₂₃ = (p...,)

    # Subsystem 1
    dx₁ = σ₁*(y₁-x₁)
    dy₁ = ρ₁*x₁ - y₁ - x₁*z₁
    dz₁ = x₁*y₁ - β₁*z₁

    # Subsystem 2
    dx₂ = σ₂*(y₂-x₂) + c₁₂*(x₁ - x₂)
    dy₂ = ρ₂*x₂ - y₂ - x₂*z₂
    dz₂ = x₂*y₂ - β₂*z₂

    # Subsystem 3
    dx₃ = σ₃*(y₃-x₃) + c₂₃*(x₂ - x₃)
    dy₃ = ρ₃*x₃ - y₃ - x₃*z₃
    dz₃ = x₃*y₃ - β₃*z₃
    return SVector{9}(dx₁, dy₁, dz₁, dx₂, dy₂,dz₂, dx₃, dy₃, dz₃)
end

function lorenz_lorenz_lorenz_transitive(u₀, σ₁, σ₂, σ₃, ρ₁, ρ₂, ρ₃, β₁, β₂, β₃, c₁₂, c₂₃)
    p = @LArray [σ₁, σ₂, σ₃, ρ₁, ρ₂, ρ₃, β₁, β₂, β₃, c₁₂, c₂₃] (:σ₁, :σ₂, :σ₃, :ρ₁, :ρ₂, :ρ₃, :β₁, :β₂, :β₃, :c₁₂, :c₂₃)
    ContinuousDynamicalSystem(eom_lorenz_lorenz_lorenz_transitive, u₀, p)
end

"""
    lorenz_lorenz_lorenz_transitive(;u₀=rand(9),
                σ₁ = 10.0, σ₂ = 10.0, σ₃ = 10.0,
                ρ₁ = 28.0, ρ₂ = 28.0, ρ₃ = 28.0,
                β₁ = 8/3,  β₂ = 8/3,  β₃ = 8.3,
                c₁₂ = 1.0, c₂₃ = 1.0) → ContinuousDynamicalSystem

Initalise a dynamical system consisting of three coupled Lorenz attractors with
a transitive causality chain where X₁ → X₂ and X₂ → X₃. In total, the three
3D-subsystems create a 9-dimensional dynamical system.

The strength of the forcing X₁ → X₂ is controlled by the parameter `c₁`, and
the forcing from X₂ → X₃ by `c₂`. The remaining parameters are the usual
parameters for the Lorenz system, where the subscript `i` refers to the
subsystem Xᵢ.

## Equations of motion

The dynamics is generated by the following vector field

```math
\\begin{aligned}
\\dot{x_1} &= \\sigma_1(y_1 - x_1) \\\\
\\dot{y_1} &= \\rho_1 x_1 - y_1 - x_1 z_1 \\\\
\\dot{z_1} &= x_1 y_1 - \\beta_1 z_1 \\\\
\\dot{x_2} &=  \\sigma_2 (y_2 - x_2) + c_{12}(x_1 - x_2) \\\\
\\dot{y_2} &= \\rho_2 x_2 - y_2 - x_2 z_2 \\\\
\\dot{z_2} &= x_2 y_2 - \\beta_2 z_2 \\\\
\\dot{x_3} &= \\sigma_3 (y_3 - x_3) + c_{23} (x_2 - x_3) \\\\
\\dot{y_3} &= \\rho_3 x_3 - y_3 - x_3 z_3 \\\\
\\dot{z_3} &= x_3 y_3 - \\beta_3 z_3
\\end{aligned}
```

## Usage in literature

This system was studied by Papana et al. (2013) for coupling strengths
``c_{12} = 0, 1, 3, 5`` and ``c_{23} = 0, 1, 3, 5``.

## References

1. Papana et al., Simulation Study of Direct Causality Measures in Multivariate
    Time Series. Entropy 2013, 15(7), 2635-2661; doi:10.3390/e15072635
"""
lorenz_lorenz_lorenz_transitive(;u₀=rand(9),
            σ₁ = 10.0, σ₂ = 10.0, σ₃ = 10.0,
            ρ₁ = 28.0, ρ₂ = 28.0, ρ₃ = 28.0,
            β₁ = 8/3,  β₂ = 8/3,  β₃ = 8.3,
            c₁₂ = 1.0, c₂₃ = 1.0) =
    lorenz_lorenz_lorenz_transitive(u₀, σ₁, σ₂, σ₃, ρ₁, ρ₂, ρ₃, β₁, β₂, β₃, c₁₂, c₂₃)


text:
#This file contains a wrapper object and some helper functions
#relating to endowment files

struct NCCSFile
    df::DataFrame
    meta::MetaDictionary

    fileType::Symbol
    fileYear::Int
    fullFile::Bool
end

const NNCCSFile = Union{NCCSFile, Nothing}

#constructs the objects from the metaDictionary
function NCCSFile(meta::MetaDictionary; preProcess::Bool = true,
nccsPath::String = NCCS_PATH, iStreamer::Function = I_CSV_STREAMER)

  inPath::String = "$nccsPath\\$(meta.fileName).csv.gz"

  df::DataFrame = readSingleTypeCSV(inPath)

  #now get the other info we need
  yearMatch::RegexMatch = match(r"\d{4}", meta.fileName)
  fileType::Symbol = Symbol(meta.fileName[(yearMatch.offset+5):(yearMatch.offset+6)])
  fileYear::Int = parse(Int, yearMatch.match)
  fullFile::Bool = contains(meta.fileName, "full")

  data = NCCSFile(df, meta, fileType, fileYear, fullFile)

  preProcess?preProcessNCCSFile!(data):data

  return data
end

  #serializes and compresses an already downloaded NCCS file
function willFail(meta::MetaDictionary; nccsPath::String = NCCS_PATH,
  iStreamer::Function = I_CSV_STREAMER, oStreamer::Function = O_JLS_STREAMER,
  serializeOnly::Bool = true, verbose::Bool = true)::DataFrame

  #these are the column names that we expect
  expectedCols::Vector{Symbol} = collect(keys(meta.dictionary))

  inPath::String = "$nccsPath\\$(meta.fileName).csv.gz"
  outPath::String = "$nccsPath\\$(meta.fileName).jls.gz"

  if verbose
    println("Serializing $(meta.fileName)...")
  end

  iStream = iStreamer(inPath)
  df::DataFrame = CSV.read(iStream, strings=:raw, categorical=false, rows=2)
  close(iStream)

  #get the column names and make sure each one is in the list of columns we want
  actualCols::Vector{String} = (s::Symbol->lowercase(string(s))).(names(df))

  #form the lookup dictionary for the type. Takes a column name and gets the type, with a default of String
  typeDict::Dict = Dict(
    actualCols[i] => (
    haskey(meta.dictionary, Symbol(actualCols[i])) ? meta.dictionary[Symbol(actualCols[i])]: Union{String, Missing})
    for i::Int ∈ 1:(length(actualCols)))

  #now read in the file
  iStream = iStreamer(inPath)
  #CSV.validate(iStream, header=actualCols, datarow=2, types=typeDict)
  try
    df = CSV.read(iStream, header=actualCols, datarow=2, types=typeDict)
  catch
    error("Try Block worked.")
  end
  close(iStream)

  #remove columns we don't expect or want
  try
    df = df[:,expectedCols]
  catch err
    error("$err\nmeta: $(meta)")
  end

  oStream = oStreamer(outPath)
  serialize(oStream, df)
  close(oStream)

  if verbose
    println("Serialization of $(meta.fileName) complete.")
  end

  if serializeOnly
    df = DataFrame([[nothing]]) #free the memory with an empty dataframe
  end

  return df

end

function changeNCCSColumnType!(data::NCCSFile, col::Symbol, T::Type)::NCCSFile

  if T <: MString #case 1: String or StringUMissing
    return data #do nothing
  end

  rename!(data.df, [col=>:oldCol])
  oldCol::Vector{R where R <: MString} = data.df[:oldCol]
  NValues::Int = length(oldCol)

  if (T <: CategoricalValue{Union{Symbol, Missing}}) #case 3: pool the categorical data
    data.df[:,col] = Vector{Union{Symbol, Missing}}(NValues)
    data.df[:,col] .= ((s::MString->ismissing(s)?missing:Symbol(s)).(oldCol))
    #println("Before: $(typeof(data.df[col]))")
    categorical!(data.df, col)
    #println("After: $(typeof(data.df[col]))")
    data.df[col] = compress(data.df[col])

  elseif T <: Union{MFloat64, MInt, Int, Float64, Bool, MBool} #case 2: concrete numerical type
    #need to parse each entry
    concreteCol::Vector{T} = Vector{T}(NValues)
    if T == Missing #special case where the column is entirely missing
      concreteCol = missings(NValues)
    else
      TSub::Type = typeintersect(T, Union{Float64, Bool, Int}) #get the nonmissable type

      #=@inbounds @simd for i ∈ 1:NValues #parse the column text
        concreteCol[i] = ifelse(ismissing(oldCol[i]),missing, parse("$(oldCol[i])"))
      end=#
      @inbounds @simd for i ∈ 1:NValues
        concreteCol[i] = ismissing(oldCol[i]) ? missing : parse(TSub, oldCol[i])
      end

    end

    data.df[:,col] = concreteCol

  else #Write explicit code for each type of column
    error("Col $col from file $(data.meta.fileName) is of type $T which is not recognized.")
  end

  #delete the old column
  delete!(data.df, :oldCol)

  return data
end

#fixes the type information
function preProcessNCCSFile!(data::NCCSFile)::NCCSFile

  meta::MetaDictionary = data.meta
  expectedCols::Vector{Symbol} = collect(keys(meta.dictionary))
  actualCols::Vector{Symbol} = (s::Symbol->Symbol(lowercase(string(s)))).(names(data.df))
  names!(data.df, actualCols) #make the names lower case

  #form the lookup dictionary for the type. Takes a column name and gets the type, with a default of String
  typeDict::Dict = Dict(
    actualCols[i] => (
    haskey(meta.dictionary, actualCols[i]) ? meta.dictionary[actualCols[i]]: MString)
    for i::Int ∈ 1:(length(actualCols)))

  #remove columns we don't expect or want
  diff::Vector{Symbol} = setdiff(actualCols, expectedCols)
  if length(diff) > 0
    try
      delete!(data.df, setdiff(actualCols, expectedCols))
    catch err
      error("$err\nmeta: $(meta.fileName)")
    end
  end

  #set the column types. Would have preferred to do this on the read, but got a weird error.
  for col::Symbol ∈ actualCols
    changeNCCSColumnType!(data, col, typeDict[col])
  end

  return data
end

#serializes a NCCSFile object
function serializeNCCSFile(data::NCCSFile; nccsPath::String = NCCS_PATH,
    oStreamer::Function = O_JLS_STREAMER,verbose=true)::NNCCSFile

    outPath::String = "$nccsPath\\$(data.meta.fileName).jls.gz"

    oStream = oStreamer(outPath)
    serialize(oStream, data)
    close(oStream)

    return nothing
end

#wrapper object to serialize a data file object
#For convenience, can return the object if requested
function serializeNCCSFile(meta::MetaDictionary;
  verbose::Bool = true, returnNCCSFile::Bool=true)::NNCCSFile

  #these are the column names that we expect

  if verbose
    println("Serializing $(meta.fileName)...")
  end

  data::NCCSFile = NCCSFile(meta) #make the object
  serializeNCCSFile(data) #serialize the object

  if verbose
    println("Serialization of $(meta.fileName) complete.")
  end

  return returnNCCSFile?data:nothing
end

#deserializes a NCCSFile object
function deserializeNCCSFile(fileName::String; nccsPath::String = NCCS_PATH,
    iStreamer::Function = I_JLS_STREAMER)::NCCSFile

    outPath::String = "$nccsPath\\$(fileName).jls.gz"

    iStream = iStreamer(outPath)
    data::NCCSFile = deserialize(iStream)
    close(iStream)

    return data
end

deserializeNCCSFile(meta::MetaDictionary)::NCCSFile = deserializeNCCSFile(meta.fileName)

#loads an already downloaded NCCS file
function loadNCCSFile(meta::MetaDictionary; nccsPath::String = NCCS_PATH,
  reserializeData::Bool = true, returnNCCSFile::Bool = true)::NNCCSFile

  filePath::String = "$nccsPath\\$(meta.fileName).jls.gz"

  #only re-process the file if necessesary
  if reserializeData || !isfile(filePath)
    data::NNCCSFile = serializeNCCSFile(meta, returnNCCSFile=returnNCCSFile)
  elseif returnNCCSFile
    data = deserializeNCCSFile(meta)
  else #do nothing
    data = nothing #an empty dataframe
  end

  return data
end

#loads and/or serializes a vector of corresponding files
function loadNCCSFiles(metadata::Vector{MetaDictionary}; mode::Symbol = :serial,
  reserializeData::Bool = true,  serializeOnly::Bool = true)::Union{Nothing,Vector{NCCSFile}}

  if mode == :parallel #relaunch the dedicated parallel function
    return loadNCCSFilesPar(metadata::Vector{MetaDictionary}, reserializeData=reserializeData,
      serializeOnly=serializeOnly)
  end

  if serializeOnly
    for meta::MetaDictionary ∈ metadata #do this in a loop format for space conservation
      loadNCCSFile(meta,reserializeData=reserializeData, returnNCCSFile=false)
    end
    return nothing
  else
    return (meta::MetaDictionary->loadNCCSFile(meta,returnNCCSFile=true)).(metadata)
  end
end

#loads many NCCS serial files in parallel
function loadNCCSFilesPar(metadata::Vector{MetaDictionary}; reserializeData::Bool = true,
  serializeOnly::Bool=true)::Union{Nothing, Vector{DataFrame}}

  numFiles::Int = length(metadata)
  pids = workers()
  np::Int = length(pids)

  #divide up the work
  assignments::Vector{Vector{Int}} = ((i::Int)->Vector{Int}()).(1:np)
  for i::Int ∈ 1:numFiles
    push!(assignments[i%np+1], i) #assigns a file to a pid
  end

  #set up a vector for pushing and receiving assignments
  futures::Vector{Future} = Vector{Future}()
  sizehint!(futures, np)

  for i::Int ∈ 1:np
    if length(assignments[i]) > 0
      push!(futures,
        (@spawnat pids[i] loadNCCSFiles(metadata[assignments[i]], reserializeData=reserializeData,
          serializeOnly=serializeOnly)))
    end
  end

  #get the work and return it if desired
  if serializeOnly
    (fetch).(futures)
    return nothing
  else
    return vcat((fetch).(futures)...)
  end
end

#creates a table of summary values
function summarizeNCCSFile(data::NCCSFile)::String
  df::DataFrame = data.df #for convenience since we are just reading, not writing

  fields::Vector{Symbol} = names(df)
  N::Int = size(df,1)
  NFields::Int = length(fields)

  #the names of the columns
  headers::Vector{Symbol} = [:N, :pMissing, :Unique, :Mean, :StdDev, :Skew, :Kurtosis,
    :Min, :p05, :p25, :p50, :p75, :p95, :Max]

  #set up our columns as a dictionary
  columns::OrderedDict = OrderedDict(headers[i] => OrderedDict{String, String}() for i::Int ∈ 1:length(headers))
  (s::Symbol->sizehint!(columns[s], NFields)).(headers)

  fieldStrings::Vector{String} = (s::Symbol->join(split(string(s),"_"),"\\_")).(fields)

  f(x::T where T<:Real) = num2Str(x,2,Ints=true, scaleHurdle = 1000.)

  for i ∈ 1:length(fields)
    #fieldString::String = string(fields[i])

    #first get some type info
    T::Type = data.meta.dictionary[fields[i]]
    TSub::Type = typeintersect(T, Union{Float64, Bool, Int, String, CategoricalValue}) #get the nonmissable type
    TSub = CategoricalValue <: TSub || TSub <: CategoricalValue? Symbol : TSub

    #compute if the type is numeric, then get the column type
    numeric::Bool = (T <: MFloat64) || (T <: MInt)
    VecT = (T <: CategoricalValue) || (CategoricalValue <: T) ? Vector{Union{Symbol,Missing}} : Vector{T}

    #form the rows
    col::VecT = VecT(N)
    col .= VecT(df[fields[i]])
    sansMissing::Vector{TSub} = collect(skipmissing(col))
    if numeric
      push!(columns[:N], fieldStrings[i] => f(length(sansMissing)))
      push!(columns[:pMissing], fieldStrings[i] => f(1.-length(sansMissing)/length(col)))
      push!(columns[:Unique], fieldStrings[i] => f(length(unique(col))))
      push!(columns[:Mean], fieldStrings[i] => f(mean(sansMissing)))
      push!(columns[:StdDev], fieldStrings[i] => f(std(sansMissing)))
      push!(columns[:Skew], fieldStrings[i] => f(skewness(sansMissing)))
      push!(columns[:Kurtosis], fieldStrings[i] => f(kurtosis(sansMissing)))
      push!(columns[:Min], fieldStrings[i] => f(minimum(sansMissing)))
      push!(columns[:p05], fieldStrings[i] => f(percentile(sansMissing,.05)))
      push!(columns[:p25], fieldStrings[i] => f(percentile(sansMissing,.25)))
      push!(columns[:p50], fieldStrings[i] => f(percentile(sansMissing,.50)))
      push!(columns[:p75], fieldStrings[i] => f(percentile(sansMissing,.75)))
      push!(columns[:p95], fieldStrings[i] => f(percentile(sansMissing,.95)))
      push!(columns[:Max], fieldStrings[i] => f(maximum(sansMissing)))
    else
      push!(columns[:N], fieldStrings[i] => f(length(sansMissing)))
      push!(columns[:pMissing], fieldStrings[i] => f(1.-length(sansMissing)/length(col)))
      push!(columns[:Unique], fieldStrings[i] => f(length(unique(col))))
    end
  end

  #convert the dictionaries to table columns
  tableColumns::Vector{TableCol} = (s::Symbol -> TableCol(string(s), columns[s])).(headers)

  table::String = texTable(hcat(tableColumns...), title=data.meta.fileName, titleDescription="Summary Table")

  return table
end

#convenience method since loading many files is memory intensive
summarizeNCCSFile(meta::MetaDictionary) =
  summarizeNCCSFile(loadNCCSFile(meta, reserializeData=false, returnNCCSFile=true))::String

#vectorized method for creating summary tables
function summarizeNCCSFiles(metadata::Vector{MetaDictionary}; mode=:serial)::Vector{String}

  if mode == :parallel #relaunch the dedicated parallel function
    return summarizeNCCSFilesPar(metadata::Vector{MetaDictionary})
  end

  #get the summary tables
  NData::Int = length(metadata)
  summaryTables::Vector{String} = (summarizeNCCSFile).(metadata)

  return summaryTables
end

#helper function to parallelize the formation of the metadata
function summarizeNCCSFilesPar(metadata::Vector{MetaDictionary})::Vector{String}

  numFiles::Int = length(metadata)
  pids = workers()
  np::Int = length(pids)

  #divide up the work
  assignments::Vector{Vector{Int}} = ((i::Int)->Vector{Int}()).(1:np)
  for i::Int ∈ 1:numFiles
    push!(assignments[i%np+1], i) #assigns a file to a pid
  end

  #set up a vector for pushing and receiving assignments
  futures::Vector{Future} = Vector{Future}()
  sizehint!(futures, np)

  for i::Int ∈ 1:np
    if length(assignments[i]) > 0
      push!(futures,
        (@spawnat pids[i] summarizeNCCSFiles(metadata[assignments[i]], mode=:serial)))
    end
  end

  return vcat((fetch).(futures)...) #concatenate the reulsts
end

function writeSummaryNCCSTables(metadata::Vector{MetaDictionary};
  outputPath::String = OUTPUT_PATH, headerName::String = HEADER_NAME, footerName::String = FOOTER_NAME)::Nothing

  tables::Vector{String} = summarizeNCCSFiles(metadata, mode=:parallel)
  writeTables2File(tables, "header.tex", "footer.tex", path=outputPath, outName = "summaryTables.tex")

  return nothing

end

max_stars_repo_name: clintonTE/CCA

max_issues_repo_name: clintonTE/CCA

max_forks_repo_name: clintonTE/CCA