text:
# *****************************************************************************
# Written by Ritchie Lee, ritchie.lee@sv.cmu.edu
# *****************************************************************************
# Copyright ã 2015, United States Government, as represented by the
# Administrator of the National Aeronautics and Space Administration. All
# rights reserved.  The Reinforcement Learning Encounter Simulator (RLES)
# platform is licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. You
# may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0. Unless @everywhered by applicable
# law or agreed to in writing, software distributed under the License is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the specific language
# governing permissions and limitations under the License.
# _____________________________________________________________________________
# Reinforcement Learning Encounter Simulator (RLES) includes the following
# third party software. The SISLES.jl package is licensed under the MIT Expat
# License: Copyright (c) 2014: Youngjun Kim.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED
# "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# *****************************************************************************

using Compat
import Compat: ASCIIString, UTF8String

using RLESCAS
using ConfParser
using RLESUtils, RunCases

function parseargs(args::Vector{UTF8String})
  #arg1 = config file
  if length(args) != 1
    error("wrong number of arguments.  \nCommand line usage: julia mcts.jl config.ini")
  end
  return configfile = convert(ASCIIString, args[1])
end

# the default one in the package isn't meant to return the whole block as a dict
#override
function retrieve_block(s::ConfParse, block::ASCIIString)
  haskey(s._data, block) ? s._data[block] : []
end

function check(condition::Bool, errormsg::ASCIIString="check failed")
  if !condition
    error(errormsg)
  end
end

function mcts_main()
  configfile = parseargs(ARGS)
  conf = ConfParse(configfile)
  parse_conf!(conf)

  search_method = "mcts" #or "mcbest"
  number_of_aircraft = -1
  encounter_ranges = nothing
  config = Dict{ASCIIString,Vector{Any}}()
  output_filters = ASCIIString[]
  outputs = ASCIIString[]
  output_dir = "./"
  quiet = false

  #Process default block
  for (k, v) in retrieve_block(conf, "default")
    #Obj2Dict doesn't work well with UTF8String and substring
    #work exclusively in ASCIIString
    v = convert(Array{ASCIIString}, v)
    if k == "search_method"
      check(length(v) == 1, "config: search_method: invalid number of parameters ($(length(v)))")
      search_method = v[1]
    elseif k == "number_of_aircraft"
      check(length(v) == 1, "config: number_of_aircraft: invalid number of parameters ($(length(v)))")
      config["sim_params.num_aircraft"] = [parse(Int,v[1])]
    elseif k == "encounter_equipage"
      check(length(v) == 1)
      config["sim_params.encounter_equipage"] = [Symbol(v[1])]
    elseif k == "encounter_model"
      check(length(v) == 1)
      config["sim_params.encounter_model"] = [Symbol(v[1])]
    elseif k == "command_method"
      check(length(v) == 1)
      config["sim_params.command_method"] = [Symbol(v[1])]
    elseif k == "response_model"
      check(length(v) == 1)
      config["sim_params.response_model"] = [Symbol(v[1])]
    elseif k == "cas_model"
      check(length(v) == 1)
      config["sim_params.cas_model"] = [Symbol(v[1])]
    elseif k == "dynamics_model"
      check(length(v) == 1)
      config["sim_params.dynamics_model"] = [Symbol(v[1])]
    elseif k == "encounters"
      check(length(v) >= 1, "config: encounters: invalid number of parameters ($(length(v)))")
      encounters = parse_ranges(v)
      config["sim_params.encounter_number"] = encounters
    elseif k == "encounter_file"
      check(length(v) == 1, "config: encounter_file: invalid number of parameters ($(length(v)))")
      encounter_file = abspath(v[1])
      config["sim_params.encounter_file"] = [encounter_file]
    elseif k == "initial"
      check(length(v) == 1, "config: initial: invalid number of parameters ($(length(v)))")
      initial = abspath(v[1])
      config["sim_params.initial_sample_file"] = [initial]
    elseif k == "transition"
      check(length(v) == 1, "config: transition: invalid number of parameters ($(length(v)))")
      transition = abspath(v[1])
      config["sim_params.transition_sample_file"] = [transition]
    elseif k == "mcts_iterations"
      check(length(v) == 1, "config: mcts_iterations: invalid number of parameters ($(length(v)))")
      mcts_iterations = parse(Int,v[1])
      config["mcts_params.n"] = [mcts_iterations]
    elseif k == "mcbest_samples"
      check(length(v) == 1, "config: mcbest_samples: invalid number of parameters ($(length(v)))")
      mcbest_samples = parse(Int,v[1])
      config["mcbest_params.n"] = [mcbest_samples]
    elseif k == "libcas"
      check(length(v) == 1, "config: libcas: invalid number of parameters ($(length(v)))")
      libcas = abspath(v[1])
      config["sim_params.libcas"] = [libcas]
    elseif k == "libcas_config"
      check(length(v) == 1, "config: libcas_config: invalid number of parameters ($(length(v)))")
      libcas_config = abspath(v[1])
      config["sim_params.libcas_config"] = [libcas_config]
    elseif k == "libcas2"
      check(length(v) == 1, "config: libcas2: invalid number of parameters ($(length(v)))")
      libcas2 = abspath(v[1])
      config["sim_params.libcas2"] = [libcas2]
    elseif k == "libcas2_config"
      check(length(v) == 1, "config: libcas2_config: invalid number of parameters ($(length(v)))")
      libcas2_config = abspath(v[1])
      config["sim_params.libcas2_config"] = [libcas2_config]
    elseif k == "output_dir"
      check(length(v) == 1, "config: output_dir: invalid number of parameters ($(length(v)))")
      output_dir = abspath(v[1])
    elseif k == "output_filters"
      filters = map(x -> convert(ASCIIString, x), v)
      output_filters = vcat(output_filters, filters)
    elseif k == "outputs"
      outs = map(x -> convert(ASCIIString, x), v)
      outputs = vcat(outputs, outs)
    elseif k == "quiet"
      check(length(v) == 1, "config: quiet: invalid number of parameters ($(length(v)))")
      quiet = bool(v[1]) #TODO(Ritchie): implement this
    else
      warn("invalid keyword skipped: $k")
    end
  end

  map_block!(config, conf, "simulation", "sim_params") # Process simulation block
  map_block!(config, conf, "ast", "ast_params") # Process ast block
  map_block!(config, conf, "mcts", "mcts_params") # Process mcts block
  map_block!(config, conf, "mcbest", "mcbest_params") # Process mcbest block
  map_block!(config, conf, "study", "study_params") # Process study block
  map_block!(config, conf, "manual", "", separator = "") #don't prefix, directly apply, # Process manual block

  if lowercase(search_method) == "mcts" #case insensitive
      #make sure no mcbest_params
      remove_by_key!(config, "mcbest_params.")
      study = MCTSStudy()
  elseif lowercase(search_method) == "mcbest"
      #make sure no mcts_params
      remove_by_key!(config, "mcts_params.")
      study = MCBestStudy()
  else
      error("No such search method: $(search_method)");
  end

  # Create the final config
  cases = generate_cases(collect(config)...)
  config_seeds!(cases) #seed each encounter with a different init_seed

  return rewards = trajSave(study, cases, postproc=StandardPostProc(outputs, output_filters),
                            outdir=output_dir)
end

function remove_by_key!(config::Dict{ASCIIString,Vector{Any}}, searchkey::AbstractString)
    for k in keys(config)
        if contains(k, searchkey)
            warn("config: ignoring incompatible key $k")
            delete!(config, k)
        end
    end
end

function parse_ranges(ranges::Vector{ASCIIString})
  #Only supports int ranges delimited by -, : or ,
  #e.g., 1-5,7-10,12
  out = Int[]
  for subexpr in ranges
    s = split(subexpr, ['-', ':'])
    if length(s) == 1
      push!(out, parse(Int,s[1]))
    elseif length(s) == 2
      r = parse(Int,s[1]):parse(Int,s[2])
      out = vcat(out, r)
    else
      error("parse_ranges: invalid range expression")
    end
  end
  return out
end

function map_block!(config::Dict{ASCIIString,Vector{Any}}, conf::ConfParse,
                    from_block::ASCIIString, to_param::ASCIIString; separator::ASCIIString=".")
  for (k, v) in retrieve_block(conf, from_block)
    composite_key = string(to_param, separator, k)
    config[composite_key] = v
  end
end

#vary the encounter seed and init seed with the encounter number
function config_seeds!(cases::Cases)
  add_field!(cases, "ast_params.init_seed", x -> Int64(x), ["sim_params.encounter_number"])
  add_field!(cases, "sim_params.encounter_seed", x -> UInt64(x), ["sim_params.encounter_number"])
  return cases
end

mcts_main()

max_stars_repo_name: sisl/RLESCAS

max_issues_repo_name: sisl/RLESCAS

max_forks_repo_name: sisl/RLESCAS


text:
######## Sampler for pure fBm and related processes ########

#### Cholesky ####
"""
Cholesky sampler for general Gaussian process.

# Notes
- This method generates a sample trajectory on any type of sampling grid (regular or arbitrary) adapted to the underlying process.
"""
struct CholeskySampler{T, P, G} <: Sampler{T, P, G}
    proc::P  # instance of the stochastic process
    grid::G  # grid in use for sampling
    cmat::AbstractMatrix  # covariance matrix
    lmat::AbstractMatrix  # lower-triangular matrix: lmat * lmat' = cmat

    function CholeskySampler{T, P, G}(p::P, g::G) where {T, P, G}
        # check the grid for fBM
        if (P<:FractionalBrownianMotion) && (0 in g)
            error("The sampling grid must not contain the origin.")
        end
        # construct the auto-covariance matrix
        cmat = covmat(p, g)
        # cholesky decomposition yields lower and upper triangular matrices L, U such that L*U = cmat, and L=U'
        # lmat = cholesky(cmat).U'
        lmat = cholesky(cmat).L
        return new(p, g, cmat, lmat)
    end
end

# outer constructor as a shortcut
# CholeskySampler(p::P, g::G) where {P, G} = CholeskySampler{typeof(p), typeof(g)}(p, g)
CholeskySampler(p::StochasticProcess{T}, g::AbstractVector{<:T}) where T<:TimeStyle = CholeskySampler{T, typeof(p), typeof(g)}(p, g)

function rand!(x::Vector{<:AbstractFloat}, s::CholeskySampler)
    return copyto!(x, s.lmat * randn(length(s)))
end

#### Circulant Embedding ####
"""
Circulant embedding sampler for stationary Gaussian process.

# Notes
- This method generates a sample trajectory on any sampling grid adapted to the underlying process.
"""
struct CircSampler{T, P<:StationaryProcess{T}, G<:AbstractVector{<:T}} <: Sampler{T, P, G}
    proc::P  # instance of the stochastic process
    grid::G  # grid in use for sampling
    cseq::AbstractVector  # covariance sequence
    fseq::AbstractVector  # square-root of the Fourier coefficients of cseq

    function CircSampler{T, P, G}(p::P, g::G) where {T, P, G}
        @assert isregulargrid(g)  # only works on regular (continuous or discrete) grid

        # Nf = 1 << ceil(Integer, log2(length(p)))  # length of FFT, equivalent to 2^()
        c = covseq(p, g)
        # minimal circulant embedding
        cm = vcat(c, c[end-1:-1:2])  # mirror vector
        M = length(cm)
        # fft() in Julia is not normalized
        # cf = real(fft(cm)/sqrt(M))  # the imaginary part is close to zero
        cf = real(fft(cm))  # the imaginary part is close to zero
        # check the non-negative constraint
        idx = cf .< 0.
        any(idx) && @warn("Negative eigenvalues encountered, using Wood-Chan approximation.")
        cf[idx] .= 0.
        new(p, g, c, sqrt.(cf))
    end
end

CircSampler(p::StationaryProcess{T}, g::AbstractVector{<:T}) where T = CircSampler{T, typeof(p), typeof(g)}(p, g)

# function rand!(x::Vector{Complex128}, s::CircSampler{P, G}) where {P, G}
function rand!(x::Vector{<:AbstractFloat}, s::CircSampler)
    # @assert length(x) <= length(s)
    M = length(s.fseq)
    z = randn(M) + im * randn(M)
    # y = real(ifft(s.fseq .* fft(z)))
    y = real(ifft(s.fseq .* z) * sqrt(M))
    return copyto!(x, y[1:length(x)])
end

"""
Functional implementation of the circulant embedding method. It takes the sequence of covariance and return a sample path of the same length.
"""
function circulant_embedding(c::Vector{<:AbstractFloat})
    cm = vcat(c, c[end-1:-1:2])  # mirror vector
    M = length(cm)
    # fft() in Julia is not normalized
    # cf = real(fft(cm)/sqrt(M))  # the imaginary part is close to zero
    cf = real(fft(cm))  # the imaginary part is close to zero
    # check the non-negative constraint
    idx = cf .< 0.
#     any(idx) && warn("Negative eigenvalues encountered, using Wood-Chan approximation.")
#         println("length(idx)=$(length(idx)), cf[idx]=$(cf[idx])")
    cf[idx] = 0.
    fseq = sqrt.(cf)
    z = randn(M) + im * randn(M)
    # y = real(ifft(s.fseq .* fft(z)))
    return real(ifft(fseq .* z) * sqrt(M))[1:length(c)]
end

#### Hosking ####
"""
Hosking (Levinson-Durbin) sampler for stationary Gaussian process.

# Notes
* This method draws the sample trajectory on any sampling grid adapted to the underlying process.
"""
struct HoskingSampler{T, P<:StationaryProcess{T}, G<:AbstractVector{<:T}} <: Sampler{T, P, G}
    proc::P  # instance of the stochastic process
    grid::G  # grid in use for sampling
    cseq::AbstractVector  # covariance sequence
    rseq::AbstractVector  # sequence of partial correlation
    pseq::AbstractVector{<:AbstractVector}  # the coefficients of consecutive projections
    sseq::AbstractVector  # sequence of variance of residual of projections
    # pmat::SparseMatrixCSC{AbstractFloat}  # upper triangular matrix diagonalizing the covariance matrix
    # cmat::Matrix{<:AbstractFloat}  # matrix of covariance

    function HoskingSampler{T, P, G}(p::P, g::G) where {T, P, G}
        @assert isregulargrid(g)  # only works on regular (continuous or discrete) grid

        cseq = covseq(p, g)
        pseq, sseq, rseq = LevinsonDurbin(cseq)

        # N = length(g)
        # pmat = 1 * speye(N,N)
        # for c = 2:N
        #     pmat[1:c-1, c] = -pseq[c-1][end:-1:1]
        # end
        # cmat = covmat(p, g)
        return new(p, g, cseq, rseq, pseq, sseq) #, pmat, cmat)
    end
end

HoskingSampler(p::StationaryProcess{T}, g::AbstractVector{<:T}) where T = HoskingSampler{T, typeof(p), typeof(g)}(p, g)

# function rand!(x::Vector{<:AbstractFloat}, s::HoskingSampler{P, G}) where {P,G}
function rand!(x::Vector{<:AbstractFloat}, s::HoskingSampler)
    # length(x) == length(s) || error()
    # generate the first sample
    x[1] = sqrt(s.sseq[1]) * randn()
    # recursive conditional sampling
    for n = 1:length(x)-1
        μ = s.pseq[n]' * x[n:-1:1]
        σ = sqrt(s.sseq[n+1])
        x[n+1] = μ + σ * randn()
    end
    return x
end

"""
    rand_otf!(x::Vector{<:AbstractFloat}, s::HoskingSampler{P, G}) where {P, G}

On-the-fly sampling using Levinson-Durbin algorithm. The partial auto-correlation function must be known for the process, for example, the FARIMA{0,d,0} process.
"""
function rand_otf!(x::Vector{<:AbstractFloat}, p::StationaryProcess{T}, g::AbstractVector{<:T}) where T
    # println("Stationary otf")
    # check dimension
    # @assert length(x) <= length(g)

    # generate the first sample
    γ0 = autocov(p, 0)
    x[1] = sqrt(γ0) * randn()

    σ = sqrt(γ0)
    ϕ = zeros(length(x)); ϕ[1] = partcorr(p, 1)

    # recursive conditional sampling
    for n = 1:length(x)-1
        μ = ϕ[1:n]' * x[n:-1:1]
        σ *= sqrt(1-ϕ[n]^2)
        x[n+1] = μ + σ * randn()
        ϕ[n+1] = partcorr(p, n+1)
        ϕ[1:n] -= ϕ[n+1] * ϕ[n:-1:1]
    end
    return x
end

# function rand_otf!(x::Vector{<:AbstractFloat}, s::HoskingSampler{P, G}) where {P,G}
#     # println("Stationary otf")
#     # length(x) == length(s) || error()

#     # generate the first sample
#     γ0 = autocov(s.proc, 0)
#     x[1] = sqrt(γ0) * randn()
#     # recursive conditional sampling
#     σ = sqrt(γ0)
#     ϕ = [partcorr(s.proc, 1)]
#     for n = 1:length(x)-1
#         μ = ϕ' * x[n:-1:1]
#         σ *= sqrt(1-ϕ[end]^2)
#         x[n+1] = μ + σ * randn()
#         r = partcorr(s.proc, n+1)
#         ϕ = [ϕ - r*ϕ[end:-1:1]; r]  # <- memory reallocation!
#     end
#     return x
# end

"""
Sampling a general FARIMA process via a FARIMA{0,d,0} process.
"""
function rand(p::FARIMA, s::HoskingSampler{T, <:FractionalIntegrated, G}) where {T, G}
    p.d == s.proc.d || error("The order of fractional differential in FARIMA{P,Q} and FARIMA{0,0} must be identical.")
    ar_len, ma_len = length(p.ar), length(p.ma)
    x = zeros(length(s))

    # step 1: sample an FARIMA{0,d,0} process
    rand!(x, s)
    # or equivalently, invoke(rand!, Tuple{Vector{<:AbstractFloat}, HoskingSampler}, x, s)

    # step 2: generate an ARMA process
    # REVIEW 15/11/2018: NOT SURE about this implementation!!
    x = conv(x, [1; p.ma])[1:end-ma_len]
    if ar_len > 0
        for t = (ar_len+1):length(s)
            # singular case: Float64[]' * Float64[] = 0.0
            x[t] += p.ar' * x[(t-1):-1:(t-ar_len)]
        end
    end
    return x
end

#### CRMD ####
"""
Conditionalized random midpoint displacement (CRMD) sampler for the increment process of SSSI process, e.g. a fGn.

# Notes
- The step of increment process (e.g. a fGn) must be equal to 1, this is crucial since the Yule-Walker equations in our implementation is de-scaled.
- The original CRMD method draws the sample trajectory on the interval [0,1]. However in our implementation a scaling factor is applied at the end so that the final trajectory are samples of a discrete fGn process (i.e. of unit step).
- The sampling grid used in this method corresponds to the index of the sampling points but not their physical position in [0,1].
"""
struct CRMDSampler{P<:IncrementProcess} <: DiscreteTimeSampler{P}
    proc::P  # instance of the stochastic process
    grid::DiscreteTimeGrid  # grid in use for sampling
    jmin::Integer  # coarse scale index
    coarse_sampler::Sampler  # exact sampler for the coarse scale

    # sclrng::RegularGrid  # range of dyadic scales jmin..jmax
    wsize::Integer  # window size for the conditionalized sampling
    init_coef::AbstractMatrix  # coefficients of the initial sampler
    init_lmat::AbstractMatrix  # lower triangular matrix of the initial sampler
    rfn_coef::AbstractVector  # coefficients of the refinement sampler
    rfn_std::AbstractFloat  # square-root of variance of the refinement (scale independant)
    # cmat::AbstractMatrix  # system matrix of the refinement sampler
    # cvec::AbstractVector  # RHS vector of the refinement sampler
    # init_pos::Symbol  # window position of initial samples, :left, :right, :center

    """
    Constructor of CRMDSampler.

    # Args
    - p: object of `IncrementSSSIProcess`.
    - g: discrete-time regular sampling grid, the step can be >= 1.
    - w: moving window size.
    - jmin: index of the coarsest scale.

    # Notes
    - The step of increment process `p` (e.g. a fGn) must be equal to 1, this is crucial since the Yule-Walker equations in our implementation is de-scaled.
    - the grid `g` is used only at the end: the generated trajectory with unit step is restricted on `g` to obtain the (down-sampled) trajectory of desired length.
    """
    function CRMDSampler{P}(p::P, g::DiscreteTimeGrid, w::Integer, jmin::Integer) where {P}
        @assert isregulargrid(g)  # only works on regular (continuous or discrete) grid

        step(p) == 1 || error("Step of increment of the underlying process must be 1.")
        @assert 1 <= w <= 2^jmin
        # 2^(Int(round(log2(length(g))))) == length(g) || error("Length of the sampling grid must be power of 2.")
        # jmin = 10  # coarse scale length = 2^jmin
        # jmax = max(jmin, ceil(Int, log2(length(G))))

        H = ss_exponent(p)

        # full covariance matrix
        # Note: without explicite conversion RegularGrid(...) the autocov function
        # `autocov(X::IncrementProcess{T, P}, t::T, s::T) where {T, P}` will be called.
        Cf = covmat(p, 1:2*w)
        Ch = Cf[1:w, 1:w]  # half matrix
        Cd = Cf[1:2:end, 1:2:end]  # down-sampled
        Af = [autocov(p, 2*(l-m)) + autocov(p, 2*(l-m)+1) for l=0:2w-1, m=0:2w-1]

        # initial sampler
        Ah = Af[1:w, 1:w] # [autocov(p, 2*(l-m)) + autocov(p, 2*(l-m)+1) for l=0:w-1, m=0:w-1]
        ξ = (2^(2*H) * Ch) \ Ah
        M = Symmetric(Cd - ξ' * Ah)  # reinforce symmetry
        L = cholesky(M).U'

        # system matrix
        b11 = 2^(2*H) * Cf
        b12 = Af[:, 1:w]
        # b12 = [autocov(p, 2*(l-m)) + autocov(p, 2*(l-m)+1) for l=0:2*w-1, m=0:w-1]
        # b21 = [autocov(p, 2*(m-l)) + autocov(p, 2*(m-l)-1) for m=0:w-1, l=0:2*w-1]
        b22 = Cd
        Γ = [b11 b12; b12' b22]

        # RHS vector
        b1 = [autocov(p, 2*(l-w)) + autocov(p, 2*(l-w)+1) for l=0:2w-1]
        b2 = [autocov(p, 2*(m-w)) for m=0:w-1]
        γ = [b1; b2]

        φ = Γ \ γ  # coefficients of prediction
        σ = sqrt(autocov(p, 0) - φ' * γ)  # sqaure-root of variance

        coarse_sampler = CholeskySampler(p, 1:2^jmin)
        return new(p, g, jmin, coarse_sampler, w, ξ, L, φ, σ)
    end
end

CRMDSampler(p::P, g::DiscreteTimeGrid, w::Integer=10, jmin::Integer=10) where {P} = CRMDSampler{P}(p, g, w, jmin)

function rand!(x::Vector{<:AbstractFloat}, s::CRMDSampler)
    # @assert length(x) <= length(s)

    H = ss_exponent(s.proc)
    # sampling at the coarse scale using an exact sampler
    x0 = 2^(-s.jmin * H) * rand(s.coarse_sampler)

    # dyadic refinement, until the trajectory grows to the end of the sampling grid
    while length(x0) < s.grid[end]
        x0 = rand_rfn(x0, s)
    end
    # x0 is a sample trajectory of ${X^\delta_H(n)}_{n=0...N-1} $ with $\delta=1/N$ on the interval $[0,1]$. To obtain a sample trajectory of $X^1_H$, apply the scaling factor $N^H$.
    x0 .*= length(x0)^H

    return copyto!(x, x0[s.grid][1:length(x)])
end

function rand_rfn(x0::Vector{<:AbstractFloat}, s::CRMDSampler)
    j = ceil(Int, log2(length(x0)))  # scale index
    2^j == length(x0) || error("Length of the input vector must be a power of 2.")

    H = ss_exponent(s.proc)
    α = 2^(-j * H)  # scaling factor
    w = s.wsize

    x1 = zeros(2*length(x0))  # refined samples
    xo = view(x1, 1:2:length(x1))  # refined samples of odd positions
    xe = view(x1, 2:2:length(x1))  # refined samples of even positions
    xz = zeros(length(x0) + w); xz[1:length(x0)] = x0  # zero-padding to avoid boundary check
    wn = randn(length(x0))  # white noise vector

    # initialization: generate the w samples at the leftmost
    xo[1:w] = s.init_coef' * xz[1:w] + α * s.init_lmat * wn[1:w]

    # left to right (forward) propagation
    for t = (w+1):length(x0)
        xo[t] = s.rfn_coef' * [xz[t-w:t+(w-1)]; xo[t-w:t-1]] + α * s.rfn_std * wn[t]
    end
    xe[:] = x0 - xo  # [:] creates a reference, without [:] there will be re-allocation of memory.

    return x1
end

#### Wavelet ####
"""
Wavelet sampler for fractional integrated (fIt) process with d ∈ (-1/2, 1/2).

# Notes
- This method can generated FARIMA(0,H-1/2,0) as well as FARIMA(0, H+1/2,0) process for H in (0,1). The later corresponds to the partial sum of the former. The sampling grid corresponds to the index of the discrete samples. In the case of FARIMA(0, H+1/2, 0) the trajectory can approximate a fBm on the interval [0,1] by proper rescaling.
"""
struct WaveletSampler <: DiscreteTimeSampler{FractionalIntegrated}
    proc::FractionalIntegrated  # instance of the stochastic process
    grid::DiscreteTimeGrid  # grid in use for sampling
    coarse_sampler::Sampler  # exact sampler for the coarse scale
    psflag::Bool  # flag of partial sum
    jmin::Integer  # coarse scale index
    qmf_ori::Tuple{AbstractVector, AbstractVector}  # original qmf filter (lo, hi)
    # qmf_mod::Tuple{AbstractVector, AbstractVector}  # modified qmf filter (lo, hi)
    qmf_fra::Tuple{AbstractVector, AbstractVector}  # fractionnal qmf filter  (lo, hi)

    """
    Constructor of WaveletSampler.

    # Args
    - p: fractional integrated process, with the parameters d=H-1/2 and H the Hurst exponent
    - r: regularity of the wavelet function, must be strictly larger than s=H+1/2
    - psflag: if true generate a trajectory of FARIMA(0, H+1/2, 0), otherwise generate FARIMA(0, H-1/2, 0).
    """
    function WaveletSampler(p::FractionalIntegrated, g::DiscreteTimeGrid; r=5, jmin=10, psflag=true)
        @assert isregulargrid(g)  # only works on regular (continuous or discrete) grid

        # jmin = 10  # coarse scale index
        trunc_eps = 1e-8  # precision of truncation
        H = p.d + 1/2  # Hurst exponent

        r > H+1/2 || error("Regularity of the wavelet must be larger than H+1/2!")
        v = psflag ? H+1/2 : H-1/2  # fractional exponent for H+1/2 or H-1/2

        # s = H + 1/2; d = H - 1/2   #  or simply: s = p.d + 1; d = p.d
        # r > s || error("Regularity of the wavelet must be larger than H+1/2!")
        # v = psflag ? s : d  # fractional exponent for H+1/2 or H-1/2

        # original qmf filters
        lo_ori = Wavelets.WT.daubechies(2*r)
        hi_ori = qmf(lo_ori)  # or: hi_ori = reverse(mirror(lo_ori))

        # modified qmf filters
        lo_mod = copy(lo_ori)
        hi_mod = copy(hi_ori)
        knl = (-1).^(0:length(lo_mod)-1)
        for n=1:r
            lo_mod = conv(knl, lo_mod)[1:length(lo_mod)]
            hi_mod = cumsum(hi_mod)
        end

        lmax = 1000  # maximum length of truncation
        f0 = [binomial(v+r, k) for k in 0:lmax]
        g0 = [(-1)^k * binomial(r-v, k) for k in 0:lmax]
        lt = max(sum(abs.(f0).>trunc_eps), sum(abs.(g0).>trunc_eps))
        lo_fra = conv(f0[1:lt], lo_mod)
        hi_fra = conv(g0[1:lt], hi_mod)

        coarse_sampler = CholeskySampler(p, 1:2^jmin)
        return new(p, g, coarse_sampler, psflag, jmin, (lo_ori, hi_ori), (lo_fra, hi_fra))
    end
end

# binomial(n::Real, k::Real) = gamma(n+1)/gamma(n-k+1)/gamma(k+1)
binomial(n::Complex, k::Complex) = exp(lgamma(n+1)-lgamma(n-k+1)-lgamma(k+1))
# binomial(n::Complex, k::Complex) = exp(lgamma(k-n)-lgamma(-n)-lgamma(k+1))
binomial(n::Real, k::Real) = real(binomial(Complex(n), Complex(k)))
# binomial(n::Number, k::Number) = binomial(Complex(n), Complex(k))

"""
Dyadic refinement sampling.
"""
function rand_rfn(x0::Vector{<:AbstractFloat}, s::WaveletSampler)
    x = zeros(2*length(x0))  # up-sampled samples
    w = zeros(2*length(x0))  # white noise
    x[1:2:end] = x0
    w[1:2:end] = randn(length(x0))

    return conv(s.qmf_fra[1], x) + conv(s.qmf_fra[2], w)
end

# function rand_rfn_ori(x0::Vector{<:AbstractFloat}, s::WaveletSampler)
#     x = zeros(2*length(x0))  # up-sampled samples
#     w = zeros(2*length(x0))  # white noise
#     x[1:2:end] = x0
#     w[1:2:end] = randn(length(x0))
#     return conv(s.qmf_ori[1], x) + conv(s.qmf_ori[2], w)
# end

function rand!(x::Vector{<:AbstractFloat}, s::WaveletSampler)
    # @assert length(x) <= length(s)

    # sampling at the coarse scale using an exact sampler
    x0 = rand(s.coarse_sampler)
    if s.psflag
        x0 = cumsum(x0)
    end

    # dyadic refinement
    while length(x0) < 2 * s.grid[end]
        x0 = rand_rfn(x0, s)
    end

    Ng = s.grid[end]-s.grid[1]  # full range of grid
    # keep only the central part and force to start from 0
    n = max((length(x0)-Ng)÷2, 1)
    x1 = x0[n:(n+Ng)] .- x0[n]
    return copyto!(x, x1[s.grid][1:length(x)])
end

ext: jl

max_stars_repo_name: yanncalec/FracFin

max_issues_repo_name: yanncalec/FracFin

max_forks_repo_name: yanncalec/FracFin


text:
# Allocation of our arrays.
function _alloc(manager, totalsize, arraysize)
    num = div(totalsize, arraysize)

    #####
    ##### Allocate the large arrays
    #####

    numelements = div(arraysize, sizeof(Float32))
    return [LockedCachedArray{Float32}(undef, manager, numelements) for _ in 1:num]
end

function alloc_1d(manager, totalsize, arraysize)
    arrays = _alloc(manager, totalsize, arraysize)

    # Zero initialize the arrays.
    # Important to make sure the OS actually gives us the physical pages.
    for A in arrays
        _A = CachedArrays.unlock(A)
        Threads.@threads for i in eachindex(_A)
            _A[i] = zero(eltype(_A))
        end
    end
    return arrays
end

# Create `num` arrays of size `sz` bytes.
# Then, iterate through pairs in the array, copying each array to its neighbor.
function sequential_copy(arrays::Vector; iterations = 1)
    if !iszero(mod(length(arrays), 2))
        throw(ArgumentError("Argument `num` must be a multiple of 2!"))
    end

    for _ in 1:iterations
        @showprogress 1 for i in 1:2:length(arrays)
            CachedArrays.memcpy!(arrays[i+1], arrays[i])
        end
    end
    return nothing
end

# To element-wise accumulation.
function sequential_accumulation(arrays::Vector; iterations = 1)
    # Create a similar array to the input.
    s = CachedArrays.unlock(similar(first(arrays)))
    s .= zero(eltype(s))

    # Now, accumulate across all the arrays.
    for a in arrays
        Threads.@threads for i in eachindex(a)
            s[i] = s[i] + a[i]
        end
    end
    return s
end

function sequential_bump(arrays::Vector)
    for a in arrays
        CachedArrays.prefetch!(a)
        _a = CachedArrays.unlock(a)
        Threads.@threads for i in eachindex(_a)
            _a[i] += one(eltype(_a))
        end
    end
    return nothing
end

# This dirties the entire cache
function sequential_zero(arrays::Vector; iterations = 1)
    for A in arrays
        CachedArrays.shallow_fetch!(A)
        _A = CachedArrays.unlock(A)
        Threads.@threads for i in eachindex(_A)
            _A[i] = zero(eltype(A))
        end
    end
    return nothing
end

__set(A::LockedCachedArray, v) = __set(CachedArrays.unlock(A), v)
function __set(A::CachedArray, v)
    Threads.@threads for i in eachindex(A)
        @inbounds A[i] = v
    end
end

function __add!(A::AbstractArray{T}, B::AbstractArray{T}, C::AbstractArray{T}) where {T}
    @assert length(A) == length(B) == length(C)
    Threads.@threads for i in eachindex(A)
        @inbounds A[i] = B[i] + C[i]
    end
end

function alloc_and_dealloc(manager, totalsize, arraysize)
    numarrays = div(totalsize, arraysize)
    numelements = div(arraysize, sizeof(Float32))

    # Populate going forward.
    p = ProgressMeter.Progress(numarrays, 1, "Filling Arrays")
    count = zero(Float32)
    arrays = map(1:numarrays) do i
        A = LockedCachedArray{Float32}(undef, manager, numelements)

        # Set a function boundary here because otherwise, inference fails and makes the
        # threaded loop SUPER slow
        __set(A, count)

        ProgressMeter.next!(p)
        count += 1
        return A
    end

    # Now go the other direction.
    s = CachedArray{Float32}(undef, manager, numelements)
    p = ProgressMeter.Progress(numarrays, 1, "Popping Arrays")
    while !isempty(arrays)
        # Should touch previously freed arrays, resulting in a completely dirty cache,
        # but we can elide the writebacks if we set the manager to run GC before allocating.

        # Prefetch in case the random eviction policy decides to screw us.
        CachedArrays.prefetch!(s)

        # Try with both prefetching and without prefetching ... with all threads reading,
        # prefetching will probably be faster.
        a = pop!(arrays)
        u = CachedArray{Float32}(undef, manager, numelements)
        __add!(u, a, s)

        ProgressMeter.next!(p)

        # Rebind "s"
        s = u
    end
    return sum(s)
end


text:
function equals(obj::Object, arg0::Object)
    return jcall(obj, "equals", jboolean, (Object,), arg0)
end

function get_attitude(obj::AbstractGNSSAttitudeProvider, arg0::FieldPVCoordinatesProvider, arg1::FieldAbsoluteDate, arg2::Frame)
    return jcall(obj, "getAttitude", FieldAttitude, (FieldPVCoordinatesProvider, FieldAbsoluteDate, Frame), arg0, arg1, arg2)
end

function get_attitude(obj::AbstractGNSSAttitudeProvider, arg0::PVCoordinatesProvider, arg1::AbsoluteDate, arg2::Frame)
    return jcall(obj, "getAttitude", Attitude, (PVCoordinatesProvider, AbsoluteDate, Frame), arg0, arg1, arg2)
end

function get_class(obj::Object)
    return jcall(obj, "getClass", Class, ())
end

function hash_code(obj::Object)
    return jcall(obj, "hashCode", jint, ())
end

function notify(obj::Object)
    return jcall(obj, "notify", void, ())
end

function notify_all(obj::Object)
    return jcall(obj, "notifyAll", void, ())
end

function to_string(obj::Object)
    return jcall(obj, "toString", JString, ())
end

function validity_end(obj::AbstractGNSSAttitudeProvider)
    return jcall(obj, "validityEnd", AbsoluteDate, ())
end

function validity_start(obj::AbstractGNSSAttitudeProvider)
    return jcall(obj, "validityStart", AbsoluteDate, ())
end

function wait(obj::Object)
    return jcall(obj, "wait", void, ())
end

function wait(obj::Object, arg0::jlong)
    return jcall(obj, "wait", void, (jlong,), arg0)
end

function wait(obj::Object, arg0::jlong, arg1::jint)
    return jcall(obj, "wait", void, (jlong, jint), arg0, arg1)
end


text:
@testset "ProbVecMult roundtrip" begin
    for d in (2, 3, 5), T in (Float64, BigFloat)
        v = randprobvec(T, d)
        v2 = copy(v)
        result = collect(SortedProbVecMult(v))
        @test v2 == v # not modified
        @test issorted(result; rev = true) # sorted
        @test result ≈ sort(v2; rev = true) # roundtrip successfully
    end
end

@testset "ProbVecMult `majmin`" begin

    for d in (2, 3, 5), T in (Float64, BigFloat)
        v = randprobvec(T, d)
        spvm = SortedProbVecMult(v)
        for ϵ in 0.0:.01:1.0
            @test majmin(sort(v; rev = true), ϵ) ≈ collect(majmin(spvm, ϵ))
        end
    end

end


text:
module MelodyRepr

using MIDI
using ..NoteSequences

# Melody representation related constants
const NUM_SPECIAL_MELODY_EVENTS = 2
const MELODY_NOTE_OFF = -1
const MELODY_NO_EVENT = -2
const MIN_MELODY_EVENT = -2
const MAX_MELODY_EVENT = 127

include("melody.jl")
include("encoder_decoder.jl")

end


text:
export Reader

@Fun(Reader{InputDim, OutputDim}, DataEntry{InputDim, OutputDim}, row::Int)
#Written By Johnathan Bizzano
struct LazyDataSet{InputType, OutputType} <: AbstractDataSet{InputType, OutputType}
    reader::Reader{InputType, OutputType}
    length::Int

    LazyDataSet(reader::Reader{I, O}, length::Int) where {I, O} = new{I, O}(reader, length)

    Base.getindex(set::LazyDataSet, row::Int) = set.reader(row)

    Base.length(set::LazyDataSet) = set.length
end


text:
func(x) = sqrt.(x)
Inputs = Array{Float64,1}([2.0, 3.0, 4.0, 5.0, 7.0, 9.0, 25.6])
Outputs = func(Inputs)
Inputs = hcat(Inputs, Outputs[:,(2-1)])
result = func.(Inputs[:,2])
Outputs = hcat(Outputs, result)
Inputs = hcat(Inputs, Outputs[:,(3-1)])
result = func.(Inputs[:,3])
Outputs = hcat(Outputs, result)
Inputs = hcat(Inputs, Outputs[:,(4-1)])
result = func.(Inputs[:,4])
Outputs = hcat(Outputs, result)

Iterates = put_together_without_jumps(Inputs, Outputs)
Iterates == hcat(Inputs, Outputs[:,size(Outputs)[2]])

NewGuess = [5.4, 5.5, 2.3, 3.4, 1.2, 0.56, 9.0]
Inputs = hcat(Inputs, NewGuess)
result = func.(Inputs[:,5])
Outputs = hcat(Outputs, result)
Inputs = hcat(Inputs,  Outputs[:,(6-1)])
result = func.(Inputs[:,6])
Outputs = hcat(Outputs, result)

Iterates = put_together_without_jumps(Inputs, Outputs)
Iterates == hcat(NewGuess, func.(NewGuess), func.(func.(NewGuess)))


text:
# This code is originally written by Avik Pal
struct ResidualBlock
    conv_layers
    norm_layers
    shortcut
end

Flux.treelike(ResidualBlock)

# ResidualBlock Function allows us to define a Residual Block having any number of Convolution and Batch Normalization Layers
function ResidualBlock(filters, kernels::Array{Tuple{Int,Int}}, pads::Array{Tuple{Int,Int}}, strides::Array{Tuple{Int,Int}}, shortcut = identity)
    local conv_layers = []
    local norm_layers = []
    for i in 2:length(filters)
        push!(conv_layers, Conv(kernels[i-1], filters[i-1]=>filters[i], pad = pads[i-1], stride = strides[i-1])|>gpu)
        push!(norm_layers, BatchNorm(filters[i])|>gpu)
    end
    ResidualBlock(Tuple(conv_layers),Tuple(norm_layers),shortcut)
end

# Function converts the Array of scalar kernel, pad and stride values to tuples
function ResidualBlock(filters, kernels::Array{Int}, pads::Array{Int}, strides::Array{Int}, shortcut = identity)
    ResidualBlock(filters, [(i,i) for i in kernels], [(i,i) for i in pads], [(i,i) for i in strides], shortcut)
end

function (block::ResidualBlock)(input)
    local value = copy.(input)
    for i in 1:length(block.conv_layers)-1
        value = relu.((block.norm_layers[i])((block.conv_layers[i])(value)))
    end
    relu.(((block.norm_layers[end])((block.conv_layers[end])(value))) + block.shortcut(input))
end


text:
# Autogenerated wrapper script for snappy_jll for x86_64-apple-darwin
export libsnappy

using Zlib_jll
using LZO_jll
JLLWrappers.@generate_wrapper_header("snappy")
JLLWrappers.@declare_library_product(libsnappy, "@rpath/libsnappy.1.dylib")
function __init__()
    JLLWrappers.@generate_init_header(Zlib_jll, LZO_jll)
    JLLWrappers.@init_library_product(
        libsnappy,
        "lib/libsnappy.1.1.9.dylib",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
# ---
# title: 95. Unique Binary Search Trees II
# id: problem95
# author: Tian Jun
# date: 2020-10-31
# difficulty: Medium
# categories: Dynamic Programming, Tree
# link: <https://leetcode.com/problems/unique-binary-search-trees-ii/description/>
# hidden: true
# ---
#
# Given an integer `n`, generate all structurally unique **BST 's** (binary
# search trees) that store values 1 ...  _n_.
#
# **Example:**
#
#
#
#     Input: 3
#     Output:
#     [
#       [1,null,3,2],
#       [3,2,null,1],
#       [3,1,null,null,2],
#       [2,1,3],
#       [1,null,2,null,3]
#     ]
#     Explanation:
#     The above output corresponds to the 5 unique BST's shown below:
#
#        1         3     3      2      1
#         \       /     /      / \      \
#          3     2     1      1   3      2
#         /     /       \                 \
#        2     1         2                 3
#
#
#
#
# **Constraints:**
#
#   * `0 <= n <= 8`
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


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

using Markdown
using InteractiveUtils

# ╔═╡ 6eb805fc-08e2-11ec-26a6-f16f278813c4
using CSV,DataFrames,GLM, Plots, Statistics, StatsBase, RegressionTables, PlutoUI, OrdinalMultinomialModels

# ╔═╡ e02889cd-4aaf-431a-9514-35c2a73c0c1c
md"
# Some experiments modelling the Furlough Scheme using BoE data

See [Bank of England/NMG household survey data](https://www.bankofengland.co.uk/quarterly-bulletin/2011/q4/the-financial-position-of-british-households-evidence-from-the-2011-nmg-consulting-survey).

Data is 2020 sheet only, converted to CSV using Python Pandas, after way too much messing about (too wide for OO, all of the native Julia xlsx readers broke).

2020 was surveyed 25 August-15 September 2020.

"

# ╔═╡ bfa6c61f-ab0f-48d0-94cc-61bcc973d66e

# ╔═╡ a7f7c023-ad69-4483-8898-2520aea63250
begin

	bd = CSV.File( "/mnt/data/boe/boe.csv" ) |> DataFrame
	# 2020 xlsx sheet only converted to csv via Panda

end

# ╔═╡ 7531f5e5-0d00-46ea-b840-5abbce4f9cde
md"""

## Main BoE Variables

`cv101` - Are you currently furloughed from your job?

* Yes – on full pay (1)
* Yes – on 80-99% of my pay (2)
* Yes – on less than 80% of my pay (3)
* No (4)

`dsoc` - dsoc [Coded social grade]

* A (1)
* B (2)
* C1 (3)
* C2 (4)
* D (5)
* E (6)
* F (7)	[no obs for this in the dataset]
* None / not specified (99)

`fgenage_1` - age

`qregion` - qregion
Which part of the UK do you live in?

* North (1)
* North West (2)
* Yorks & Humberside (3)
* West Midlands (4)
* East Midlands (5)
* East Anglia (6)
* South West (7)
* South East (8)
* Greater London (9)
* Wales (10)
* Scotland (11)
* Northern Ireland (12)
* Not On Map (99)
* Non UK (13)

`fgen` - fgen

* Male (1)
* Female (2)

`qhousing` - qhousing

* Being bought on a mortgage (1)
* Owned outright by household (2)
* Rented from local authority (3)
* Rented from a private landlord (4)
* Belongs to housing association (5)
* Other (please specify) (98)____________
* Prefer not to state (96)

a20workingstatus - Which one of these currently applies to you? If you are currently taking sick leave or paid leave please state whether you usually work full time or part time.

* Have paid job - working full time (30+ hours per week) (1)
* Have paid job - working part time (up to 29 hours per week) (2)
* Furloughed (i.e. you remain employed but are absent from work at present and will continue receiving some or all of your wages) (3)
* Taking temporary unpaid leave (4)
* Self-employed (5)
* Full time student/still at school (6)
* Unemployed and seeking work (7)
* Retired (8)
* Not in paid work because of long term illness or disability (9)
* Not in paid work for other reason (10)
* Prefer not to state (11)

`industry` - What does the firm/organisation you work for in your main job mainly make or do (at the place where you work)?

* Agriculture, forestry and fishing (1)
* Mining and quarrying (2)
* Energy and water (3)
* Manufacturing (4)
* Construction (5)
* Transport and storage (6)
* Wholesale, retail, hotels and restaurants (7)
* Information, communication and IT (8)
* Banking, finance and insurance (9)
* Real estate activities (10)
* Professional, scientific and technical activities (11)
* Administrative and support service activities (12)
* Public administration, defence, education and health (13)
* Arts, entertainment and recreation (14)
* Other services (15)
* Don't know (16)
* Prefer not to state (17)

`bc1b` - Do you work within the public sector?

* Yes (1)
* No (2)
* Don't know (3)
* Prefer not to state (4)

"""

# ╔═╡ d9c08ca1-91fc-4a54-ab49-477d73abd709
# some new vars
begin
	# binary
	n = size(bd)[1]
	bd.furloughed = 0 .< bd.cv101 .< 4
	# stepped
	bd.furloughed_v = zeros(n)
	for i in 1:n
		r = bd[i,:]
		if r.cv101  == 4
			r.furloughed_v = 0
		elseif r.cv101  == 3
			r.furloughed_v = 1
		elseif r.cv101  == 2
			r.furloughed_v = 2
		elseif r.cv101  == 1
			r.furloughed_v = 3
		end
	end
	bd.public = bd.bc1b .== 1 # ? all missing?
	bd.agric = bd.industry .== 1 # missing
	bd.age = bd.fgenage_1
	bd.agesq = bd.age.^2 ./ 1_000
	bd.female = bd.fgen .== 2
	bd.scot = bd.qregion .== 11
	bd.renter = 3 .<= bd.qhousing .<= 5
	bd.privrent = bd.qhousing .== 4
	bd.mortaged = bd.qhousing .== 1
	bd.pubrent = (bd.qhousing .== 3) .| (bd.qhousing .== 5)
	# note these are highest earner
	bd.headprof = bd.dsocialgrade .== 1
	bd.headinter = bd.dsocialgrade .== 2
	bd.headclerical = bd.dsocialgrade .== 3
	bd.headmanual = 4 .<= bd.dsocialgrade .<= 5
	bd.work = bd.a20workingstatus .<= 3
	bd.se = bd.a20workingstatus .== 5
end

# ╔═╡ c1238987-ca73-4462-b83f-5c8cd6b747e9
md" A depressing number of possible good regressors are missing ..."

# ╔═╡ 8273704e-0476-4edf-b5e0-52eabf03392c
begin
	# Summary Stats
 (
		ind=countmap(bd.industry),
		work=countmap( bd.a20workingstatus ),
		hous=countmap( bd.qhousing  ),
		rent=countmap( bd.renter ),
		pubrent = countmap( bd.pubrent ),
		soc=countmap( bd.dsoc ),
		social=countmap( bd.dsocial ),
		fur=countmap( bd.cv101 ),
		furd=countmap( bd.furloughed ),
		furv=countmap( bd.furloughed_v ),
		age=countmap(bd.fgenage_1),
		sex=countmap(bd.fgen),
		scot=countmap(bd.scot),
		fsize=countmap(bd.firmsize),
		sgrade=countmap(bd.socialgrade),
		dsgrade=countmap(bd.dsocialgrade),
		marit=countmap(bd.qmarital)
 )

end

# ╔═╡ b515b283-84d9-4009-a291-53692f7ae8b7
begin
	wbd = bd[bd.work.==1,:]
m1 = glm( @formula( furloughed  ~ femalex + age + agesq + headprof + scot +  privrent + mortaged + pubrent ), wbd, Binomial(), ProbitLink())
	m2 = glm( @formula( furloughed  ~ female + age + agesq + scot +  privrent + mortaged ), wbd, Binomial(), ProbitLink())

	m3 = polr( @formula( furloughed_v  ~ female + age + agesq + scot +  privrent + mortaged ), wbd, ProbitLink())
	@eval regtable(m1,m2, renderSettings = latexOutput())
	[m1,m2,m3]
end

# ╔═╡ 09ca7083-23ae-47f0-a670-27acf564b36c
md"This seems the best I can do with what's there."

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
OrdinalMultinomialModels = "b51826c6-2bc1-4eb0-a3af-c080fd29f1d0"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
RegressionTables = "d519eb52-b820-54da-95a6-98e1306fdade"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"

[compat]
CSV = "~0.8.5"
DataFrames = "~1.2.2"
GLM = "~1.5.1"
OrdinalMultinomialModels = "~0.3.4"
Plots = "~1.21.1"
PlutoUI = "~0.7.9"
RegressionTables = "~0.5.1"
StatsBase = "~0.33.9"
"""

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

[[ASL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "370cafc70604b2522f2c7cf9915ebcd17b4cd38b"
uuid = "ae81ac8f-d209-56e5-92de-9978fef736f9"
version = "0.1.2+0"

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

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

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

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

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

[[BinaryProvider]]
deps = ["Libdl", "Logging", "SHA"]
git-tree-sha1 = "ecdec412a9abc8db54c0efc5548c64dfce072058"
uuid = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
version = "0.5.10"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[FixedEffectModels]]
deps = ["DataFrames", "FixedEffects", "LinearAlgebra", "Printf", "Reexport", "Statistics", "StatsBase", "StatsFuns", "StatsModels", "Tables", "Vcov"]
git-tree-sha1 = "a036618f39adeffb39d9be8dd54ba2d073256503"
uuid = "9d5cd8c9-2029-5cab-9928-427838db53e3"
version = "1.6.4"

[[FixedEffects]]
deps = ["GroupedArrays", "LinearAlgebra", "Printf", "Requires", "StatsBase"]
git-tree-sha1 = "91a0628a826002df975c8b22a39b79964e240376"
uuid = "c8885935-8500-56a7-9867-7708b20db0eb"
version = "2.0.8"

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

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

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

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

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

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

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

[[GLM]]
deps = ["Distributions", "LinearAlgebra", "Printf", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "StatsFuns", "StatsModels"]
git-tree-sha1 = "f564ce4af5e79bb88ff1f4488e64363487674278"
uuid = "38e38edf-8417-5370-95a0-9cbb8c7f171a"
version = "1.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 = "7bf67e9a481712b3dbe9cb3dac852dc4b1162e02"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+0"

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

[[GroupedArrays]]
deps = ["DataAPI", "Missings"]
git-tree-sha1 = "93e21548d0a4b8ac793fea1aa1d720f5c9eaf11a"
uuid = "6407cd72-fade-4a84-8a1e-56e431fc1533"
version = "0.3.1"

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

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

[[InvertedIndices]]
deps = ["Test"]
git-tree-sha1 = "15732c475062348b0165684ffe28e85ea8396afc"
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
version = "1.0.0"

[[Ipopt]]
deps = ["BinaryProvider", "Ipopt_jll", "Libdl", "LinearAlgebra", "MathOptInterface", "MathProgBase"]
git-tree-sha1 = "380786b4929b8d18d76e909c6b2eca355b7c3bd6"
uuid = "b6b21f68-93f8-5de0-b562-5493be1d77c9"
version = "0.7.0"

[[Ipopt_jll]]
deps = ["ASL_jll", "Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "MUMPS_seq_jll", "OpenBLAS32_jll", "Pkg"]
git-tree-sha1 = "82124f27743f2802c23fcb05febc517d0b15d86e"
uuid = "9cc047cb-c261-5740-88fc-0cf96f7bdcc7"
version = "3.13.4+2"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[METIS_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "2dc1a9fc87e57e32b1fc186db78811157b30c118"
uuid = "d00139f3-1899-568f-a2f0-47f597d42d70"
version = "5.1.0+5"

[[MUMPS_seq_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "METIS_jll", "OpenBLAS32_jll", "Pkg"]
git-tree-sha1 = "1a11a84b2af5feb5a62a820574804056cdc59c39"
uuid = "d7ed1dd3-d0ae-5e8e-bfb4-87a502085b8d"
version = "5.2.1+4"

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

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

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

[[MathProgBase]]
deps = ["LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "9abbe463a1e9fc507f12a69e7f29346c2cdc472c"
uuid = "fdba3010-5040-5b88-9595-932c9decdf73"
version = "0.7.8"

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

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

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

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

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

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

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

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

[[NLopt]]
deps = ["MathOptInterface", "MathProgBase", "NLopt_jll"]
git-tree-sha1 = "d80cb3327d1aeef0f59eacf225e000f86e4eee0a"
uuid = "76087f3c-5699-56af-9a33-bf431cd00edd"
version = "0.6.3"

[[NLopt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "2b597c46900f5f811bec31f0dcc88b45744a2a09"
uuid = "079eb43e-fd8e-5478-9966-2cf3e3edb778"
version = "2.7.0+0"

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

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

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

[[OpenBLAS32_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ba4a8f683303c9082e84afba96f25af3c7fb2436"
uuid = "656ef2d0-ae68-5445-9ca0-591084a874a2"
version = "0.3.12+1"

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

[[OrdinalMultinomialModels]]
deps = ["Distributions", "GLM", "Ipopt", "LinearAlgebra", "MathProgBase", "NLopt", "RDatasets", "Random", "Reexport", "StatsBase", "StatsModels"]
git-tree-sha1 = "3f9871242e79c662a21585709cd870106f5d656c"
uuid = "b51826c6-2bc1-4eb0-a3af-c080fd29f1d0"
version = "0.3.4"

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

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

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

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

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

[[Plots]]
deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"]
git-tree-sha1 = "0036d433cacff4767ff622be3cb2c281b773a2b4"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.21.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"

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

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

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

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

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

[[RData]]
deps = ["CategoricalArrays", "CodecZlib", "DataFrames", "Dates", "FileIO", "Requires", "TimeZones", "Unicode"]
git-tree-sha1 = "19e47a495dfb7240eb44dc6971d660f7e4244a72"
uuid = "df47a6cb-8c03-5eed-afd8-b6050d6c41da"
version = "0.8.3"

[[RDatasets]]
deps = ["CSV", "CodecZlib", "DataFrames", "FileIO", "Printf", "RData", "Reexport"]
git-tree-sha1 = "06d4da8e540edb0314e88235b2e8f0429404fdb7"
uuid = "ce6b1742-4840-55fa-b093-852dadbb1d8b"
version = "0.7.5"

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

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

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

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

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

[[RegressionTables]]
deps = ["Compat", "Distributions", "FixedEffectModels", "Formatting", "GLM", "Statistics", "StatsBase", "StatsModels", "UnPack"]
git-tree-sha1 = "db358ecc957106d8860e077893654683eca8b9ca"
uuid = "d519eb52-b820-54da-95a6-98e1306fdade"
version = "0.5.1"

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

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

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

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

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

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

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

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

[[ShiftedArrays]]
git-tree-sha1 = "22395afdcf37d6709a5a0766cc4a5ca52cb85ea0"
uuid = "1277b4bf-5013-50f5-be3d-901d8477a67a"
version = "1.0.0"

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

[[StatsModels]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Printf", "ShiftedArrays", "SparseArrays", "StatsBase", "StatsFuns", "Tables"]
git-tree-sha1 = "a209a68f72601f8aa0d3a7c4e50ba3f67e32e6f8"
uuid = "3eaba693-59b7-5ba5-a881-562e759f1c8d"
version = "0.6.24"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[Vcov]]
deps = ["Combinatorics", "GroupedArrays", "LinearAlgebra", "StatsBase", "Tables"]
git-tree-sha1 = "b382811c8beba117f70c07a42f3f18b3075a39db"
uuid = "ec2bfdc2-55df-4fc9-b9ae-4958c2cf2486"
version = "0.5.0"

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

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

[[XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

[[Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

[[Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[Xorg_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

[[Xorg_xcb_util_image_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97"
uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b"
version = "0.4.0+1"

[[Xorg_xcb_util_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"]
git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1"
uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5"
version = "0.4.0+1"

[[Xorg_xcb_util_keysyms_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00"
uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7"
version = "0.4.0+1"

[[Xorg_xcb_util_renderutil_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e"
uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e"
version = "0.3.9+1"

[[Xorg_xcb_util_wm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67"
uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361"
version = "0.4.1+1"

[[Xorg_xkbcomp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"]
git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b"
uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4"
version = "1.4.2+4"

[[Xorg_xkeyboard_config_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"]
git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d"
uuid = "33bec58e-1273-512f-9401-5d533626f822"
version = "2.27.0+4"

[[Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

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

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

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

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

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

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

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

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

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

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

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

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

# ╔═╡ Cell order:
# ╠═6eb805fc-08e2-11ec-26a6-f16f278813c4
# ╠═e02889cd-4aaf-431a-9514-35c2a73c0c1c
# ╠═bfa6c61f-ab0f-48d0-94cc-61bcc973d66e
# ╠═a7f7c023-ad69-4483-8898-2520aea63250
# ╟─7531f5e5-0d00-46ea-b840-5abbce4f9cde
# ╠═d9c08ca1-91fc-4a54-ab49-477d73abd709
# ╟─c1238987-ca73-4462-b83f-5c8cd6b747e9
# ╠═8273704e-0476-4edf-b5e0-52eabf03392c
# ╠═b515b283-84d9-4009-a291-53692f7ae8b7
# ╟─09ca7083-23ae-47f0-a670-27acf564b36c
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: grahamstark/ScottishTaxBenefitModel

max_issues_repo_name: grahamstark/ScottishTaxBenefitModel

max_forks_repo_name: grahamstark/ScottishTaxBenefitModel


text:
using HDF5

abstract Solution{T,N} <: AbstractArray{T,N}

"Create solution for ODE."
function Solution(equation::ODE, Δt, ntime::Int, nsave::Int=1)
    SolutionODE(equation, Δt, ntime, nsave)
end

"Create solution for partitioned ODE."
function Solution(equation::PODE, Δt, ntime::Int, nsave::Int=1)
    SolutionPODE(equation, Δt, ntime, nsave)
end

"Create solution for special ODE."
function Solution(equation::SODE, Δt, ntime::Int, nsave::Int=1)
    SolutionPODE(equation, Δt, ntime, nsave)
end

"Create solution for DAE."
function Solution(equation::DAE, Δt, ntime::Int, nsave::Int=1)
    SolutionDAE(equation, ntime, nsave)
end

"Create solution for partitioned DAE."
function Solution(equation::PDAE, Δt, ntime::Int, nsave::Int=1)
    SolutionPDAE(equation, ntime, nsave)
end

"Print error for solutions of equations not implemented, yet."
function Solution(equation::Equation, Δt, ntime::Int, nsave::Int=1)
    error("No solution found for equation ", equation)
end

# "createHDF5: Creates or opens HDF5 file."
# function createHDF5(file::AbstractString, overwrite=true)
#     if overwrite
#         flag = "w"
#     else
#         flag = "r+"
#     end
#
#     h5open(file, flag)
# end

"Creates HDF5 file, writes solution to file, and closes file."
function writeSolutionToHDF5(solution::Solution, file::AbstractString)
    h5 = createHDF5(solution, file, solution.nt+1)
    writeSolutionToHDF5(solution, h5)
    close(h5)
end

Base.eltype{T,N}(s::Solution{T,N}) = T
Base.ndims{T,N}(s::Solution{T,N}) = N
Base.size(s::Solution) = size(s.x)
# Base.length(s::Solution) = s.d * s.n
# Base.length(s::Solution) = length(s.x)
# Base.endof(s::Solution) = length(s)
Base.indices(s::Solution, d) = indices(s)[d]
Base.stride(s::Solution, d) = strides(s)[d]

# TODO Implement similar() and convert() to/from array functions.


text:
"""
    readsxmodel(file; raw_dict=false, ST=ConstrainedLinearControlContinuousSystem, kwargs...)

Read a SpaceExParser model file.

### Input

- `file`      -- the filename of the SpaceExParser file (in XML format)
- `raw_dict`  -- (optional, default: `false`) if `true`, return the raw dictionary with
                 the objects that define the model (see Output below), without
                 actually returning a `HybridSystem`; otherwise, instantiate a
                 `HybridSystem` with the given assumptions
- `ST`        -- (optional, default: `nothing`) assumption for the type of mathematical
                 system for each mode

### Output

Hybrid system that corresponds to the given SpaceExParser model and the given assumptions
on the system type if `raw_dict=true`; otherwise, a dictionary with the Julia
expression objects that define the model. The keys of this dictionary are:

- `automaton`
- `variables`
- `transitionlabels`
- `invariants`
- `flows`
- `assignments`
- `guards`
- `switchings`
- `nlocations`
- `ntransitions`

### Notes

Currently, this function makes the following assumptions:

1) The model contains only 1 component. If the model contains more than 1 component,
   an error is raised. In this case, recall that network components can be
   flattened using `sspaceex`.
2) The default and a custom `ST` parameter assume that all modes are of the same
   type. In general, you may pass a vector of system's types in `kwargs` (not implemented).

Moreover, let us note that:

1) The tags `<notes> ... <\notes>` are ignored.
2) Variable names are stored in the dictionary `variables`, together with other
   information such as if the variable is controlled or not. This dictionary is
   then stored in the extension field (`ext`) of the hybrid system.
3) The transition labels are stored in the extension field (`ext`) of the
   hybrid system.
4) We use the location "id" field (an integer), such that each of the vectors `modes`,
   `resetmaps` and `switchings` corresponds to the location with the given "id". For
   example, `modes[1]` corresponds to the mode for the location with `id="1"`.
5) The `name` field of a location is ignored.
6) The nature of the switchings is autonomous. If there are guards, these define
   state-dependent switchings only. Switching control functions are not yet implemented.
7) The `resetmaps` field consists of the vector of tuples `(assignment, guard)`, for each
   location.

These comments apply whenever `raw_dict=false`:

1) The field `variables` is an ordered dictionary, where the order is given by the
   insertion order. This allows deterministic iteration over the dictionary,
   (notice that in a usual dictionary, the order in which the elements are returned
   does not correspond, in general, to the order in which the symbols were saved).
   The `variables` are stored in the coefficients matrix using this insertion order.
2) If `ST` is `nothing`, the modes are given as the vector of tuples `(flows, invariants)`,
   each component being a list of expressions, and similarly the reset maps are
   the vector of tuples `(assignments, guards)`.
"""
function readsxmodel(file; raw_dict=false,
                           ST=nothing,
                           kwargs...)

    # 1) Open XML and read number of components and locations
    # =======================================================
    sxmodel = readxml(file)
    root_sxmodel = root(sxmodel)

    nlocations_vector, ntransitions_vector = count_locations_and_transitions(root_sxmodel)
    ncomponents = length(nlocations_vector)
    if ncomponents > 1
        error("read $(ncomponents) components, but models with more than one component are not yet implemented; try flattening the model")
    elseif ncomponents < 1
        error("read $(ncomponents) components, but the model should have a positive number of components")
    end
    # keep the 1st component
    nlocations, ntransitions = nlocations_vector[1], ntransitions_vector[1]

    # 2) Parse SpaceExParser model and make the dictionary of Julia expressions
    # ==============================================================

    # hybrid automaton with the given number of locations
    automaton = LightAutomaton(nlocations)

    # ditionary with variables names and their properties
    variables = OrderedDict{Symbol, Dict{String, Any}}()

    # set of labels for the transitions
    transitionlabels = Set{String}()

    # vector with the invariants for each location
    invariants = Vector{Vector{Expr}}(undef, nlocations)

    # vector with the ODE flow for each location
    flows = Vector{Vector{Expr}}(undef, nlocations)

    # assignments for each transition
    assignments = Vector{Vector{Expr}}(undef, ntransitions)

    # guards for each transition; subsets of state space where the state needs
    # to be to make the transition
    guards = Vector{Vector{Expr}}(undef, ntransitions)

    switchings = Vector{AbstractSwitching}(undef, ntransitions)

    HDict = Dict("automaton"=>automaton,
                 "variables"=>variables,
                 "transitionlabels"=>transitionlabels,
                 "invariants"=>invariants,
                 "flows"=>flows,
                 "assignments"=>assignments,
                 "guards"=>guards,
                 "switchings"=>switchings,
                 "nlocations"=>nlocations,
                 "ntransitions"=>ntransitions)

    parse_sxmodel!(root_sxmodel, HDict)

    if raw_dict
        return HDict
    end

    if ST == nothing
        modes = Vector{Tuple{Vector{Expr}, Vector{Expr}}}()
        for i in eachindex(flows)
           push!(modes, (flows[i], invariants[i]))
        end

        resetmaps = Vector{Tuple{Vector{Expr}, Vector{Expr}}}()
        for i in eachindex(assignments)
           push!(resetmaps, (assignments[i], guards[i]))
        end

    elseif ST == ConstrainedLinearControlContinuousSystem
        # 2) Use a custom system type and symbolic representations
        (modes, resetmaps) = linearHS(HDict; kwargs...)
    else
        error("the system type $(ST) is not supported")
    end

    # extension field
    ext = Dict{Symbol, Any}()
    ext[:variables] = variables
    ext[:transitionlabels] = transitionlabels

    return HybridSystem(automaton, modes, resetmaps, switchings, ext)
end


text:
function create_cost_expr(jm, pf::Production)
    temp1 = :(
        +(
            $(
                (input.quantity for input in pf.inputs)...
            )
        )
    )

    return :(
        *(
            $(
                (:(
                    $(get_jump_variable_for_commodity(jm,input.commodity)) ^ ($(input.quantity)/$temp1)
                ) for input in pf.inputs)...
            )
        )
    )
end

function create_rev_expr(jm, pf::Production)
    temp1 = :(
        +(
            $(
                (output.quantity for output in pf.outputs)...
            )
        )
    )

    return :(
        sqrt(
            +(
                $(
                    (
                        :(
                            $(output.quantity) *
                            $(get_jump_variable_for_commodity(jm,output.commodity))^2 /
                            $temp1
                        ) for output in pf.outputs
                    )...
                )
            )
        )
    )
end

function build_implicitconstraints!(m, jm)
    # Add compensated demand (intermediate and factor)
    for s in m._productions
        for input in s.inputs
            ex = :(
                JuMP.@NLexpression(
                    $(jm),
                    $(input.quantity) *
                        $(create_cost_expr(jm, s)) /
                        $(get_jump_variable_for_commodity(jm, input.commodity)) -
                        $(jm[get_comp_demand_name(input)])
                )
            )

            exb = eval( swap_our_param_with_jump_param(jm, ex) )

            Complementarity.add_complementarity(jm, jm[get_comp_demand_name(input)], exb, string("F_", get_comp_demand_name(input)))
            push!(m._nlexpressions, exb)
        end
    end

    # Add compensated supply
    for s in m._productions
        for output in s.outputs
            ex = :(
                JuMP.@NLexpression(
                    $(jm),
                    $(output.quantity) *
                        $(get_jump_variable_for_commodity(jm, output.commodity)) /
                        $(create_rev_expr(jm, s)) -
                        $(jm[get_comp_supply_name(output)])
                )
            )

            exb = eval( swap_our_param_with_jump_param(jm, ex) )

            Complementarity.add_complementarity(jm, jm[get_comp_supply_name(output)], exb, string("F_", get_comp_supply_name(output)))
            push!(m._nlexpressions, exb)
        end
    end

    # Add final demand
    for demand_function in m._demands
        temp1 = :(
            +(
                $(
                    (demand.quantity for demand in demand_function.demands)...
                )
            )
        )
        for demand in demand_function.demands
            ex = :(
                JuMP.@NLexpression(
                    $(jm),
                        $(demand.quantity) /
                        $temp1 *
                        $(get_jump_variable_for_consumer(jm, demand_function.consumer)) /
                        $(get_jump_variable_for_commodity(jm, demand.commodity)) -
                        $(jm[get_final_demand_name(demand)])
                )
            )

            exb = eval( swap_our_param_with_jump_param(jm, ex) )

            Complementarity.add_complementarity(jm, jm[get_final_demand_name(demand)], exb, string("F_", get_final_demand_name(demand)))
            push!(m._nlexpressions, exb)
        end
    end
end


text:
module RollingFunctions

export rolling,
       rollmin,  rollmax,             # min, max
       rollmean, rollmedian,          # mean, median
       rollvar,  rollstd,             # variance, standard deviation
       rollskewness, rollkurtosis,    # skewness, kurtosis
       rollsem,                       # standard error of the mean
       rollmad,                       # mean absolute deviation
       rollmad_normalized,            # mean absolute deviation for normal data
       rollvariation,                 # coefficient of variation
       running,                       #      tapering versions
       runmin,  runmax,               # min, max
       runmean, runmedian,            # mean, median
       runvar,  runstd,               # variance, standard deviation
       runskewness, runkurtosis,      # skewness, kurtosis
       runsem,                        # standard error of the mean
       runmad,                        # mean absolute deviation
       runmad_normalized,             # mean absolute deviation for normal data
       runvariation,                  # coefficient of variation
                                      # with two data vectors
       rollcor, rollcov,
       runcor, runcov

using LinearAlgebra: normalize

using Statistics: mean, median, std, var, cor, cov
using StatsBase:  kurtosis, mad, sem, skewness, variation,
                  AbstractWeights, Weights,
                  FrequencyWeights, AnalyticWeights, ProbabilityWeights

include("roll/rolling.jl")
include("run/running.jl")
include("support.jl")
include("roll/rollstats.jl")
include("run/runstats.jl")
include("roll/rolling2.jl")
include("run/running2.jl")

end # RollingFunctions