text:
"""
    AhoCorasickAutomaton{T}(keys::Vector{Pair{String, Ti}}; sort = false) where {T, Ti}
    AhoCorasickAutomaton{T}(keys::AbstractDict{String, Ti}; sort = false) where {T, Ti}
    AhoCorasickAutomaton{T}(keys::Vector{String}; sort = false) where T
    AhoCorasickAutomaton(keys::Vector{String}; sort = false) = AhoCorasickAutomaton{UInt32}(keys; sort = sort)
    AhoCorasickAutomaton(keys::Vector{Pair{String, Ti}}; sort = false) where Ti = AhoCorasickAutomaton{UInt32}(keys; sort = sort)

    T s.t. typemax(T) >= length(keys)

A 2-Array implementation of Aho–Corasick automaton(ACA)[^1], Most used as an engine to mine a long text string,
to get all occurences of substrings interested in the text. ACA is also adequate for unicode strings
as a `Set{String}` or `Dict{String, Unsigned}` (similar as Trie, but with a far more less space usage).

The ACA acts as a key data structrue in Aho–Corasick algorithm for multiple consecutive string
patterns finding[^2]. This particular implementation use no-decreasing `base`, i.e.,

    1. base[node] >= node
    2. children[node] > node

This choice make it suitable for large-size key set of not-very-long keys, with faster
insertion speed and moderate space usage.

# Notes
1. Maybe of slower speed than a oridinary tree-based ACA, specially for random generated keys.
2. When inserting duplicated keys, only the last one will make sense.
3. Inputing Sorted keys will be of (much) faster speed. Just turn the *sort* option on!

# Examples
```
julia> v = ["A", "B"]; obj1 = AhoCorasickAutomaton{UInt8}(v; sort = true) # constructor
type  AhoCorasickAutomaton{UInt8}
––––– –––––––––––––––––––––––––––
keys                            2
nodes                          67
nnz                             3
size                    623 bytes

julia> for key in v @assert key ∈ obj1 end

julia> @assert sort!(keys(obj1)) == v

julia> d = Dict("A" => 1, "B" => 2); obj2 = AhoCorasickAutomaton{UInt8}(d; sort = true); obj1 == obj2 # constructor
true

julia> obj3 = AhoCorasickAutomaton{UInt8}(collect(d); sort = true); obj2 == obj3 # constructor
true

julia> s = "AABDB"; matches = eachmatch(obj1, s) # eachmatch
4-element Array{ACMatch,1}:
 ACMatch(1, 1, 1)
 ACMatch(2, 2, 1)
 ACMatch(3, 3, 2)
 ACMatch(5, 5, 2)

julia> matches == eachmatch(obj1, codeunits(s)) # eachmatch
true

julia> map(x -> s[x], matches) # getindex
4-element Array{String,1}:
 "A"
 "A"
 "B"
 "B"

julia> ss = collect(codeunits(s)); foreach(x -> ss[x] = ss[x], matches); String(ss) == s # setindex!
true

julia> io = IOBuffer(); write(io, obj1); seek(io, 0); obj11 = read(io, AhoCorasickAutomaton); obj1 == obj11 # read & write
true
```
For more : `using Pkg; less(joinpath(Pkg.dir("AhoCorasickAutomatons"), "test", "runtests.jl"))`

# See also
*ACMatch*, *eachmatch*, *getindex*, *setindex!*,
*in*, *get*, *length*, *read*, *write*, *collect*, *keys*, *values*.

# References
[^1]: Jun‐Ichi Aoe, Katsushi Morimoto and Takashi Sato 'An Efficient Implementation of Trie Structures', September 1992.
[^2]:  Aho, Alfred V.; Corasick, Margaret J. (June 1975). "Efficient string matching: An aid to bibliographic search". Communications of the ACM. 18 (6): 333&ndash, 340. doi:10.1145/360825.360855. MR 0371172.

"""
struct AhoCorasickAutomaton{T <: Integer}
    base::Vector{T}
    from::Vector{T}
    ikey::Vector{T}
    deep::Vector{T}
    back::Vector{T}
    arcs::Vector{Vector{UInt8}}
end

function AhoCorasickAutomaton{T}() where T
    base = T[1]
    from = T[1]
    ikey = T[0]
    deep = T[0]
    back = T[0]
    arcs = [UInt8[]]
    return AhoCorasickAutomaton{T}(base, from, ikey, deep, back, arcs)
end

function AhoCorasickAutomaton{T}(keys::Vector{Pair{String, Ti}}; sort = false) where {T, Ti}
    nkeys = T(length(keys))
    obj = AhoCorasickAutomaton{T}()
    if !sort || issorted(keys)
        @showprogress 1 "Building ACA..." for i = T(1):nkeys
            addkey!(obj, codeunits(keys[i][1]), T(keys[i][2]))
        end
    else
        Base.sort!(keys)
        @showprogress 1 "Building ACA..." for i = T(1):nkeys
            addkey!(obj, codeunits(keys[i][1]), T(keys[i][2]))
        end
    end
    shrink!(obj)
    @inbounds fillback!(obj)
    validate(obj)
    resize!(obj.arcs, 0)
    obj
end

function AhoCorasickAutomaton{T}(keys::AbstractDict{String, Ti}; sort = false) where {T, Ti}
    nkeys = T(length(keys))
    if !sort || issorted(keys)
        obj = AhoCorasickAutomaton{T}()
        @showprogress 1 "Building ACA..." for (key, id) in keys
            addkey!(obj, codeunits(key), T(id))
        end
        return obj
    else
        return AhoCorasickAutomaton{T}(collect(keys); sort = sort)
    end
end

function AhoCorasickAutomaton{T}(keys::Vector{String}; sort = false) where T
    keys2 = Vector{Pair{String, T}}(undef, length(keys))
    for (i, key) in enumerate(keys) keys2[i] = key => T(i) end
    return AhoCorasickAutomaton{T}(keys2; sort = sort)
end

AhoCorasickAutomaton(keys::Vector{String}; sort = false) = AhoCorasickAutomaton{UInt32}(keys; sort = sort)
AhoCorasickAutomaton(keys::Vector{Pair{String, Ti}}; sort = false) where Ti = AhoCorasickAutomaton{UInt32}(keys; sort = sort)

function write(io::IO, obj::AhoCorasickAutomaton{T}) where T
    nbyte = 0
    if T isa Unsigned
        nbyte += write(io, +1)
    else
        nbyte += write(io, -1)
    end
    nbyte += write(io, sizeof(T))
    nbyte += write(io, length(obj.from))
    nbyte +=
    write(io, obj.base) +
    write(io, obj.from) +
    write(io, obj.ikey) +
    write(io, obj.deep) +
    write(io, obj.back)
    return nbyte;
end

function read(io::IO, ::Type{AhoCorasickAutomaton})
    signT = read(io, Int)
    byteT = read(io, Int)
    T = Int
    if signT > 0
        T = filter(x -> sizeof(x) == byteT, [UInt8, UInt16, UInt32, UInt64])[1]
    else
        T = filter(x -> sizeof(x) == byteT, [Int8, Int16, Int32, Int64])[1]
    end
    nnode = read(io, Int)
    base = reinterpret(T, read(io, nnode * sizeof(T)))
    from = reinterpret(T, read(io, nnode * sizeof(T)))
    ikey = reinterpret(T, read(io, nnode * sizeof(T)))
    deep = reinterpret(T, read(io, nnode * sizeof(T)))
    back = reinterpret(T, read(io, nnode * sizeof(T)))
    return AhoCorasickAutomaton{T}(base, from, ikey, deep, back, [UInt8[]])
end

function ==(x::AhoCorasickAutomaton, y::AhoCorasickAutomaton)
    return x.base == y.base && x.from == y.from && x.ikey == y.ikey && x.deep == y.deep && x.back == y.back
end

function in(key::AbstractString, obj::AhoCorasickAutomaton{T})::Bool where T
    return get(obj, key, T(0)) > 0
end

function in(key::DenseVector{UInt8}, obj::AhoCorasickAutomaton{T})::Bool where T
    return get(obj, key, T(0)) > 0
end

function get(obj::AhoCorasickAutomaton{T}, key::DenseVector{UInt8}, default::T)::T where T
    cur::T = 1
    n::T = length(obj.from)
    for c in key
        nxt = obj.base[cur] + c
        if (nxt <= n && obj.from[nxt] == cur)
            cur = nxt
        else
            return default
        end
    end
    return obj.ikey[cur]
end

function get(obj::AhoCorasickAutomaton{T}, key::AbstractString, default::T)::T where T
    return get(obj, codeunits(key), default)
end

function length(obj::AhoCorasickAutomaton{T}) where T
    return count(!iszero, obj.ikey)
end

function collect(obj::AhoCorasickAutomaton{T}) where T
    base = obj.base
    from = obj.from
    ikey = obj.ikey
    res = Pair{String, Int}[]
    for i = 1:length(ikey)
        if ikey[i] == 0 continue end
        codes = UInt8[]
        j = i
        while j > 1
            c = j - base[from[j]]
            push!(codes, c)
            j = from[j]
        end
        push!(res, String(reverse!(codes)) => ikey[i])
    end
    return res
end

function keys(obj::AhoCorasickAutomaton{T}) where T
    return map(first, collect(obj))
end

function values(obj::AhoCorasickAutomaton{T}) where T
    return filter(!iszero, obj.ikey)
end

function shrink!(obj::AhoCorasickAutomaton{T})::T where T
    actlen = findlast(!iszero, obj.from)
    if (actlen < length(obj.from))
        resize!(obj.base, actlen)
        resize!(obj.from, actlen)
        resize!(obj.ikey, actlen)
        resize!(obj.deep, actlen)
        resize!(obj.back, actlen)
        resize!(obj.arcs, actlen)
    end
    return actlen
end

function enlarge!(obj::AhoCorasickAutomaton{T}, newlen::T)::T where T
    base = obj.base; from = obj.from; deep = obj.deep; back = obj.back; ikey = obj.ikey; arcs = obj.arcs;
    oldlen::T = length(obj.base)
    newlen2 = oldlen
    while newlen2 < newlen newlen2 *= 2 end
    if (oldlen < newlen2)
        resize!(base, newlen2)
        resize!(from, newlen2)
        resize!(ikey, newlen2)
        resize!(deep, newlen2)
        resize!(back, newlen2)
        resize!(arcs, newlen2)
        # for i = oldlen + 1:newlen2 base[i] = i end
        base[oldlen + 1:newlen2] .= 0
        from[oldlen + 1:newlen2] .= 0
        ikey[oldlen + 1:newlen2] .= 0
        deep[oldlen + 1:newlen2] .= 0
        back[oldlen + 1:newlen2] .= 0
        for i in oldlen + 1:newlen2
            arcs[i] = UInt8[]
        end
    end
    return newlen2
end

function addkey!(obj::AhoCorasickAutomaton{T}, code::Base.CodeUnits{UInt8,String}, icode::T)::Nothing where T
    base = obj.base; from = obj.from; deep = obj.deep; back = obj.back; ikey = obj.ikey; arcs = obj.arcs;
    cur::T = 1
    nxt::T = 0
    for c in code
        nxt = base[cur] + c
        enlarge!(obj, nxt)
        if (from[nxt] == 0)
            from[nxt] = cur
            push!(arcs[cur], c)
            deep[nxt] = deep[cur] + 1
            cur = nxt
        elseif (from[nxt] == cur)
            cur = nxt
        else # from[nxt] != cur
            push!(arcs[cur], c)
            if length(arcs[cur]) <= length(arcs[from[nxt]]) || from[nxt] == from[cur]
                rebase!(obj, cur)
                nxt = base[cur] + c
            else
                rebase!(obj, from[nxt])
            end
            from[nxt] = cur
            deep[nxt] = deep[cur] + 1
            cur = nxt
        end
    end
    ikey[cur] = icode
    return nothing
end

function rebase!(obj::AhoCorasickAutomaton{T}, cur::T)::Nothing where T
    base = obj.base; from = obj.from; deep = obj.deep; back = obj.back; ikey = obj.ikey; arcs = obj.arcs;
    oldbase = base[cur]
    @assert length(arcs[cur]) > 0 string(cur)
    newbase = findbase(obj, cur)
    enlarge!(obj, newbase + maximum(arcs[cur]))
    for i = eachindex(arcs[cur])
        # arc = arcs[cur][i]
        newson = newbase + arcs[cur][i]
        from[newson] = cur
        oldson = oldbase + arcs[cur][i]
        if (from[oldson] != cur) continue end
        base[newson] = base[oldson]
        ikey[newson] = ikey[oldson]
        deep[newson] = deep[oldson]
        z = arcs[newson]; arcs[newson] = arcs[oldson]; arcs[oldson] = z;
        # grandsons
        for arc in arcs[newson]
            from[base[newson] + arc] = newson
        end
        # oldson
        base[oldson] = from[oldson] = ikey[oldson] = deep[oldson] = 0
    end
    base[cur] = newbase
    return nothing
end

function findbase(obj::AhoCorasickAutomaton{T}, cur::T)::T where T
    base = obj.base; from = obj.from; deep = obj.deep; back = obj.back; ikey = obj.ikey; arcs = obj.arcs;
    n::T = length(from)
    for b = max(cur + 1, base[cur]):n
        ok = true
        for arc in arcs[cur]
            @inbounds ok &= arc + b > n || from[arc + b] == 0
        end
        if (ok)
            return b
        end
    end
    return T(n + 1)
end

function fillback!(obj::AhoCorasickAutomaton{T})::Nothing where T
    base = obj.base; from = obj.from; deep = obj.deep; back = obj.back; ikey = obj.ikey; arcs = obj.arcs;
    #println(arcs)
    n::T = length(arcs)
    root::T = 1
    que = similar(base); head::T = 1; tail::T = 2;
    que[1] = root; back[root] = root;
    while head < tail
        cur = que[head]; head += 1;
        for arc in arcs[cur]
            chd = base[cur] + arc
            chdback = root
            if (cur != root)
                chdback = back[cur]
                while chdback != root && (base[chdback] + arc > n || from[base[chdback] + arc] != chdback)
                    chdback = back[chdback]
                end
                if base[chdback] + arc <= n && from[base[chdback] + arc] == chdback
                    chdback = base[chdback] + arc
                end
            end
            back[chd] = chdback
            que[tail] = chd; tail += 1;
        end
    end
    return nothing
end

function validate(obj::AhoCorasickAutomaton{T})::Nothing where T
    base = obj.base; from = obj.from; deep = obj.deep; back = obj.back; ikey = obj.ikey; arcs = obj.arcs;
    root = 1
    que = similar(base); head = 1; tail = 2;
    que[1] = root;
    while head < tail
        cur = que[head]; head += 1;
        for arc in arcs[cur]
            chd = base[cur] + arc
            # @assert from[chd] == cur && back[chd] != chd && back[chd] != 0 string(chd, " fa=", cur, " from=", from[chd], " back=", back[chd])
            @assert from[chd] == cur string("cur=", cur, " chd=", chd, " from=", from[chd])
            que[tail] = chd; tail += 1;
        end
    end
    return nothing
end

function display(obj::AhoCorasickAutomaton{T}) where T
    rows = Any[["type", typeof(obj)],
                ["keys", length(obj)],
                ["nodes", length(obj.from)],
                ["nnz", count(!iszero, obj.from)],
                ["size", format_bytes(summarysize(obj))]
    ];
    return display(Markdown.MD(Markdown.Table(rows, Symbol[:l, :r])))
end

function print(io::IO, obj::AhoCorasickAutomaton{T}) where T
    print(io, (nodes = length(obj.from), nnz = count(!iszero, obj.from), size = format_bytes(summarysize(obj))))
end

"""
ACMatch has 3 fields:

    1. s : start of match
    2. t : stop of match, using text[s, t] to get matched patterns
    3. i : index of the key in *obj*, which is the original insertion order of keys to *obj*

The field *i* may be use as index of external property arrays, i.e., the AhoCorasickAutomaton
can act as a `Map{String, Any}`.

# See also
*eachmatch*, *getindex*, *setindex!*
"""
struct ACMatch
    s::Int
    t::Int
    i::Int
end

length(pos::ACMatch) = pos.t - pos.s + 1

function isless(x::ACMatch, y::ACMatch)::Bool
    return x.s < y.s || x.s == y.s && x.t < y.t || x.s == y.s && x.t == y.t && x.i < y.i
end

"""
    eachmatch(obj::AhoCorasickAutomaton{T}, text::AbstractString)::Vector{ACMatch} where T
    eachmatch(obj::AhoCorasickAutomaton{T}, text::DenseVector{T2})::Vector{ACMatch} where T where T2

Search for all matches of a AhoCorasickAutomaton *obj* in *text* and return a
vector of the matches. Each match is represented as a `ACMatch` type.

# See also
*ACMatch*
"""
function eachmatch(obj::AhoCorasickAutomaton{T}, text::AbstractString)::Vector{ACMatch} where T
    return eachmatch(obj, codeunits(text))
end

function eachmatch(obj::AhoCorasickAutomaton{T}, codes::DenseVector{UInt8})::Vector{ACMatch} where T
    base = obj.base; from = obj.from; deep = obj.deep; back = obj.back; ikey = obj.ikey; arcs = obj.arcs;
    n = length(base)
    root = cur = T(1)
    res = Vector{ACMatch}(undef, 0)
    for i = 1:length(codes)
        c = codes[i]
        while cur != root && (base[cur] + c > n || from[base[cur] + c ] != cur)
            cur = back[cur]
        end
        if (base[cur] + c <= n && from[base[cur] + c] == cur)
            cur = base[cur] + c
        end
        # if (ikey[cur] > 0)
            node = cur
            while node != root
                if (ikey[node] > 0) push!(res, ACMatch(i - deep[node] + 1, i, ikey[node])) end
                node = back[node]
            end
        # end
    end
    res
end

"""
    getindex(xs::AbstractString, pos::ACMatch)

Retrieve a substring of *xs* specified by *pos*.
# See also
*ACMatch*
"""
function getindex(xs::AbstractString, pos::ACMatch)
    return xs[pos.s:pos.t]
end

"""
    getindex(xs::DenseVector{UInt8}, pos::ACMatch)

Retrieve a sub-codeunits of *xs* specified by *pos*.
# See also
*ACMatch*
"""
function getindex(xs::DenseVector{UInt8}, pos::ACMatch)
    return xs[pos.s:pos.t]
end

"""
    setindex!(xs::DenseVector{UInt8}, sub::DenseVector{UInt8}, pos::ACMatch)

Set values of region specified by *pos* of *xs* to *sub*.
# Note
 @assert length(sub) == length(pos)
# See also
*ACMatch*
"""
function setindex!(xs::DenseVector{UInt8}, sub::DenseVector{UInt8}, pos::ACMatch)
    return xs[pos.s:pos.t] = sub
end


text:
using SmolyakInterpolation, Test, StaticArrays, LinearAlgebra

# internals to be tested
using SmolyakInterpolation:
    # utilities
    Counts, count_combinations, CappedCartesianIndices, largest_indices,
    # Chebyshev
    all_gridpoints,
    # basis
    _basis_block, _coordinate_block

include("test_utilities.jl")
include("test_chebyshev.jl")
include("test_basis.jl")

ext: jl


text:
module Multisession

using DocStringExtensions
using Combinatorics
using Caesar
using Neo4j, CloudGraphs

export
  getSessionsForEnvironment,
  getEnvironmentPrimeLandmarkNodes,
  getSessionLandmarks,
  getFederatedGraphElements,
  buildPrimeLandmarksAndFactors,
  getMultiSessionFg,
  updateLandmarkProducts

"""
    $(SIGNATURES)

Return all binary pair combinations of sessions and return a Vector::Tuple{String, String}.

Example
-------
```julia
str = ["a";"b";"c";"d"]
pstr = stringPairs(str)
@assert length(pstr) == 6
```
"""
function stringPairs(strs::Vector{<:AbstractString} )::Vector{Tuple{String, String}}
  ret = Tuple{String,String}[]
  for co in combinations( strs )
    if length(co) == 2
      push!(ret, (co[1], co[2]))
    end
  end
  return ret
end

"""
  $(SIGNATURES)

Gets a vector of session IDs that are related to an environment.
"""
function getSessionsForEnvironment(
    connection::Neo4j.Connection,
    environment::String)::Vector{String}
  query = "match (env:ENVIRONMENT:$environment)-[SESSION]->(s:SESSION) return s.id"
  cph, = Caesar.executeQuery(connection, query)
  return map(s -> s["row"][1], cph.results[1]["data"])
end

"""
  $(SIGNATURES)

Get a dictionary (label => Neo4j node) of all prime nodes for a given set of sessions and an environment.
"""
function getEnvironmentPrimeLandmarkNodes(cloudGraph::CloudGraph, sessions::Vector{String}, environment::String)::Dict{String, Neo4j.Node}
  # TODO - refactor prime labels as a special snowflake - m or something like `:m14` is better -- still need to test and upgrade IIF for this
  query = "match (node:MULTISESSION:LANDMARK) where ("*join("(node:".*sessions.*")", " or ")*") and node.environment = \"$environment\" return id(node)"
  cph, = Caesar.executeQuery(cloudGraph.neo4j.connection, query)
  existPrimeNodes = map(node -> getnode(cloudGraph.neo4j.graph, node["row"][1]), cph.results[1]["data"])
  labels = map(n -> getnodeproperty(n, "label"), existPrimeNodes)
  # Dictionary of all existing prime nodes...
  existPrimeNodes = Dict(labels .=> existPrimeNodes)
  return existPrimeNodes
end

"""
  $(SIGNATURES)

Gets all landmark IDs for a given session, excluding multisession.
"""
# TODO: This should be a generic function...
function getSessionLandmarks(
    conn::Neo4j.Connection,
    sessionId::String,
    robotId::String,
    userId::String)::Vector{String}
  query = "match (landmark:$sessionId:$robotId:$userId:LANDMARK) where NOT landmark:MULTISESSION return landmark.label"
  cph, = Caesar.executeQuery(conn, query)
  return map(s -> s["row"][1], cph.results[1]["data"])
end

"""
  $(SIGNATURES)

Very specific method to check if a prime factor exists between a session landmark and a prime node.
Prime node is identified by NeoNode ID.
"""
function _doesPrimeFactorExistByForSessionLandmark(
    conn::Neo4j.Connection,
    sessionId::String,
    robotId::String,
    userId::String,
    primeLandmarkNeoNodeId::Int)::Bool
  query = "match (node:LANDMARK:$sessionId:$robotId:$userId)-[:DEPENDENCE]-(f:FACTOR)-[:DEPENDENCE]-(m:MULTISESSION) where id(m)=$(primeLandmarkNeoNodeId) return id(node)"
  cph, = Caesar.executeQuery(conn, query)
  return length(cph.results[1]["data"]) > 0 # If it exists return true.
end

"""
  $(SIGNATURES)

Returns the tuples of the prime landmark -> prime factor -> session landmark for all existing prime factors.
Tuple elements: mid, mlabel, fid, flabel, lid, llabel
May contain duplicates elements (e.g. two prime factors for one prime landmark).
"""
function getFederatedGraphElements(
    connection::Neo4j.Connection,
    sessions::Vector{String},
    environment::String)::Vector{Tuple}
  query = "match (m:LANDMARK:MULTISESSION)--(f:FACTOR:MULTISESSION)--(l:LANDMARK) where "*(prod("m:".*sessions.*" or ")[1:(end-4)])*" and m.environment=\"$environment\" return id(m), m.label, id(f), f.label, id(l), l.label"
  cph, = Caesar.executeQuery(connection, query)

  elements = Vector{Tuple}()
  for data in cph.results[1]["data"]
    #Tuple elements: mid, mlabel, fid, flabel, lid, llabel
    push!(elements, (data["row"][1], Symbol(data["row"][2]), data["row"][3], Symbol(data["row"][4]), data["row"][5], Symbol(data["row"][6])))
  end
  return elements
end

"""
  $(SIGNATURES)

McFlurry step.
Builds the prime landmarks and prime factors for a given environment and sessions (if they don't exist).
Returns all prime landmarks.
"""
function buildPrimeLandmarksAndFactors(
    cloudGraph::CloudGraph,
    sessionLandmarks::Dict{String, Vector{String}},
    robotId::String,
    userId::String,
    environment::String)::Dict{String, Neo4j.Node}
  @debug "  - Checking and updating each combination of sessions for same landmarks..."
  sessions = collect(keys(sessionLandmarks))
  sessionPairs = stringPairs(sessions)
  primeLandmarkNodes = getEnvironmentPrimeLandmarkNodes(cloudGraph, sessions, environment)
  for (s1,s2) in sessionPairs
    @info "    - Creating landmark links between '$s1' and '$s2'"
    # TODO: Find a better way to for landmark equivalence check
    # TODO: Check that the landmarks are the same type
    commonLandmarks = intersect(sessionLandmarks[s1], sessionLandmarks[s2])
    @info "    - Common landmark set: $commonLandmarks"

    for commonLandmark in commonLandmarks
      @info "    - Checking common landmark $commonLandmark..."
      # Make the prime variable if it doesn't exist
      sym = Symbol("l"*string(parse(Int, commonLandmark[2:end])+100000))
      if !haskey(primeLandmarkNodes, String(sym))
        # TODO: be generic about which variables and factor types to use
        # Make a prime and add to db+list
        @info "    - Adding a prime landmark variable $sym..."
        fg = initfg(cloudgraph=cloudGraph, robotname=robotId, username=userId, sessionname=s1)

        # Check the softtypes to make sure they match.
        # TODO: FRACK GETTING AGAIN... YEESH
        land1 = Caesar.getCloudVert(cloudGraph, s1, robotId, userId, sym=Symbol(commonLandmark))
        land2 = Caesar.getCloudVert(cloudGraph, s2, robotId, userId, sym=Symbol(commonLandmark))
        if typeof(land1.packed.softtype) != typeof(land2.packed.softtype)
            @error "Softtypes don't match for $s1:$sym (got $(typeof(land1.packed.softtype))) and $s2:$sym (got $(typeof(land2.packed.softtype)))"
            continue
        end
        addVariable!(fg, sym, deepcopy(land1.packed.softtype), tags=[:MULTISESSION; :LANDMARK; Symbol(s1); Symbol(s2); Symbol(userId); Symbol(robotId)], uid=100000)
        # NOTE: Until DFG, all prime variables have exVertexId of 100000
        # Add the environment property
        setnodeproperty(getnode(cloudGraph.neo4j.graph, fg.cgIDs[100000]), "environment", environment)
        @debug "    - Added prime landmark!"
        # primeLandmarkNodes[string(sym)] = primeLandmarkNodes
        # Repull the existing prime nodes!
        primeLandmarkNodes = getEnvironmentPrimeLandmarkNodes(cloudGraph, sessions, environment)
      else
        @info "    - Prime landmark $sym already exists, making sure it has all the labels!"
        addnodelabels(primeLandmarkNodes[String(sym)], [s1, s2])
      end

      # check if factor already exists
      prime = primeLandmarkNodes[string(sym)]
      for s in [s1, s2]
        if !_doesPrimeFactorExistByForSessionLandmark(cloudGraph.neo4j.connection, s, robotId, userId, prime.id)
          @info "    - Adding a factor between session landmark '$commonLandmark' and prime landmark '$sym' for session $s..."
          # add new factor that between session landmark and prime landmark
          fg = initfg(cloudgraph=cloudGraph, robotname=robotId, username=userId, sessionname=s)
          syms = [Symbol(commonLandmark);sym]
          @debug "    - Copying local symbols $syms..."
          Caesar.subLocalGraphCopy!(fg, syms, neighbors=0, reqbackendset=false, reqSolvable=false, includeMultisession=true)

          # Note: this shouldn't be necessary because the check is done in the landmark creation, but doing just in case here too.
          @show sessionLandType = getData(getVert(fg, syms[1], api=localapi)).softtype
          @show primeLandType = getData(getVert(fg, syms[2], api=localapi)).softtype
          if typeof(sessionLandType) != typeof(primeLandType)
              @error "Softtypes don't match for $syms (got $(typeof(sessionLandType))) and (got $(typeof(primeLandType)))"
              continue
          end
          newFactorType = string(typeof(sessionLandType).name)*string(typeof(primeLandType).name)

          @debug "    - Trying to create a factor linking $syms of type $newFactorType ..."
          # How do i create a Point2Point2 or Pose2Pose2 generically.
          newPrimeFactor = Point2Point2(MvNormal(zeros(2), 1e-4*Matrix(LinearAlgebra.I, 2,2) ))
          @warn "Currently would like a factor of type $newFactorType, but hard-coded to create Point2Point2's. Please fix in FederatedSolving.jl!"
          addFactor!(fg, syms, newPrimeFactor, uid=100001, tags=[:FACTOR; :MULTISESSION; Symbol(userId); Symbol(robotId); Symbol(s)], autoinit=false)
          # NOTE: Until DFG, all prime variables have exVertexId of 100000
          # Add the environment property
          setnodeproperty(getnode(cloudGraph.neo4j.graph, fg.cgIDs[100001]), "environment", environment)
        else
          @debug "    - Factor link already exists, continuing..."
        end
      end
    end
  end
  return primeLandmarkNodes
end

"""
  $(SIGNATURES)

Create a Caesar FactorGraph that contains all landmarks and factors in a multisession
federated solve.
"""
function getMultiSessionFg(
    cloudGraph::CloudGraph,
    sessions::Vector{String},
    environment::String)
# #
  fg = initfg(cloudgraph=cloudGraph)

  # 1. Get all federated elements - Vector of tuples (mid,  mlabel, fid, flabel, lid, llabel)
  federatedGraphElements = getFederatedGraphElements(cloudGraph.neo4j.connection, sessions, environment)

  localIndex = 1
  for (mid, mlabel, fid, flabel, lid, llabel) in federatedGraphElements

    # make the local index unique
    origlabel = llabel
    llabel = Symbol(string(llabel, "_", localIndex))
    # If prime landmark not in FG, add it
    if !(mid in values(fg.IDs))
      mvert = CloudGraphs.get_vertex(fg.cg, mid, false)
      addVariable!(fg, mlabel, mvert.packed.softtype, api=IIF.localapi, uid=mid)
      getVert(fg, mlabel, api=localapi).attributes["origlabel"] = mlabel
      # Manually add the cloud node IDs
      push!(fg.cgIDs, mvert.neo4jNodeId => mvert.neo4jNodeId)
    end
    # If session landmark not in FG, add it
    if !(lid in values(fg.IDs))
      lvert = CloudGraphs.get_vertex(fg.cg, lid, false)
      addVariable!(fg, llabel, lvert.packed.softtype, api=IIF.localapi, uid=lid)
      getVert(fg, llabel, api=localapi).attributes["origlabel"] = origlabel
      Caesar.setValKDE!(fg, llabel, kde!(lvert.packed.val), api=IIF.localapi)
      # Manually add the cloud node IDs
      push!(fg.cgIDs, lvert.neo4jNodeId => lvert.neo4jNodeId)
      # Keep local label index unique
      localIndex += 1
    end
    # If prime factor (l1 prime -- l1 session) not in FG, add it
    if !(fid in values(fg.fIDs))
      vm = fg.g.vertices[mid]
      vl = fg.g.vertices[lid]
      fvert = CloudGraphs.get_vertex(fg.cg, fid, false)
      addFactor!(fg, [llabel; mlabel], fvert.packed.fnc.usrfnc!, api=IIF.localapi, uid=fid, autoinit=false)
    end
  end
  return fg
end

"""
$(SIGNATURES)

Updates the specified list of landmarks using local products.
Returns a symbol dictionary of the provided landmarks and a tuple of (new KDE, KDE propsals),
which is useful for plotting with plotKDE.
"""
function updateLandmarkProducts(
    fg::G,
    landmarkSymbols::Vector{Symbol},
    shouldFreeze::Bool)::Dict{Symbol, Tuple{BallTreeDensity, Vector{BallTreeDensity}}} where G <: AbstractDFG
  retDict = Dict{Symbol, Tuple{BallTreeDensity, Vector{BallTreeDensity}}}()
  for landmarkSymbol in landmarkSymbols
    @debug "Calculating local product for $landmarkSymbol..."

    # Update calculate the local product and persist it
    newkde, kdeproposals = IIF.localProduct(fg, landmarkSymbol, api=IIF.localapi)

    # SetValKDE does not do what we need here - do by hand...
    # Get local, update cloud.
    vert = getVert(fg, landmarkSymbol, api=IIF.localapi)
    data = getData(vert)
    data.val = getPoints(newkde)
    if shouldFreeze
      @debug "Freezing $landmarkSymbol..."
      # Freeze the landmark (TODO: May be overcooked, possibly refactore)
      data.ismargin = true
    end
    vert.attributes["label"] = vert.attributes["origlabel"]
    setData!(vert, data)

    @debug "Updating $landmarkSymbol on server..."
    # Fix the label before writing back
    dlapi.updatevertex!(fg, vert)
    #setValKde is not right call :/
    # setValKDE!(fg, landmarkSymbol, newkde, api=IIF.dlapi)

    push!(retDict, landmarkSymbol=>(newkde, kdeproposals))
  end
  return retDict
end

return nothing

end


text:
n = 9 # rand(1:10)
m = 8 # rand(1:10)
k = n-2 #rand(1:n)
alpha = 3.0
@test matrixdepot("triw", Float64, m, n, alpha, k) == matrixdepot("triw", m, n, alpha, k)
@test matrixdepot("triw", n) == matrixdepot("triw", Float64, n, n, -1, n-1)

A = matrixdepot("triw", Float32, n)
@test istriu(A)
# B = A'*A has diagnoal B(i,i) = i
@test diag(A'*A) ≈ [1. : n;]
println("'triw' passed test...")


text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Test integer conversion routines from int.jl

using Random

@testset "flipsign/copysign" begin
    for y in (-4, Float32(-4), -4.0, big(-4.0))
        @test flipsign(3, y)  == -3
        @test flipsign(-3, y) == 3
        @test copysign(3, y)  == -3
        @test copysign(-3, y) == -3
    end

    for y in (4, Float32(4), 4.0, big(4.0))
        @test flipsign(3, y)  == 3
        @test flipsign(-3, y) == -3
        @test copysign(3, y)  == 3
        @test copysign(-3, y) == 3
    end

    # Result type must be type of first argument, except for Bool
    for U in (Base.BitInteger_types..., BigInt,
              Rational{Int}, Rational{BigInt},
              Float16, Float32, Float64)
        for T in (Base.BitInteger_types..., BigInt,
                  Rational{Int}, Rational{BigInt},
                  Float16, Float32, Float64)
            @test typeof(copysign(T(3), U(4))) === T
            @test typeof(flipsign(T(3), U(4))) === T
        end
        # Bool promotes to Int
        U <: Unsigned && continue
        for x in [true, false]
            @test flipsign(x, U(4)) === Int(x)
            @test flipsign(x, U(-1)) === -Int(x)
            @test copysign(x, U(4)) === Int(x)
            @test copysign(x, U(-1)) === -Int(x)
        end
    end

    @testset "flipsign/copysign(typemin($T), -1)" for T in Base.BitInteger_types
        for U in (Base.BitSigned_types..., BigInt, Float16, Float32, Float64)
            @test flipsign(typemin(T), U(-1)) == typemin(T)
            @test copysign(typemin(T), U(-1)) == typemin(T)
        end
    end

    @testset "flipsign with Float types" begin
        for s1 in (-1,+1), s2 in (-1,+1)
            @test flipsign(Int16(3s1), Float16(3s2)) === Int16(3s1*s2)
            @test flipsign(Int32(3s1), Float32(3s2)) === Int32(3s1*s2)
            @test flipsign(Int64(3s1), Float64(3s2)) === Int64(3s1*s2)
        end
    end
end
@testset "signed and unsigned" begin
    @test signed(3) === 3
    @test signed(UInt(3)) === 3
    @test isa(signed(UInt(3)), Int)
    @test signed(UInt(0) - 1) === -1
    @test_throws InexactError signed(UInt(-3))
    @test signed(true) === 1
    @test unsigned(true) isa Unsigned
    @test unsigned(true) === unsigned(1)

    @test signed(Bool) === Int
    @test signed(Bool) === typeof(signed(true))
    @test unsigned(Bool) === UInt
    @test unsigned(Bool) === typeof(unsigned(true))
end
@testset "bswap" begin
    @test bswap(true) == true
    @test bswap(Int8(3)) == 3
    @test bswap(UInt8(3)) === 0x3
    @test bswap(Int16(3)) == 256*3
    @test bswap(Int16(256)) == 1
    @test bswap(Int16(257)) == 257
    @test bswap(Int32(1)) == 2^(3*8)
    @test bswap(Int32(2)^(3*8)) == 1
    @test bswap(Int64(1)) === Int64(2)^(7*8)
    @test bswap(Int64(2)^(7*8)) == 1
    @test bswap(Int128(1)) === Int128(2)^(15*8)
    @test bswap(Int128(2)^(15*8)) === Int128(1)
    @test bswap(UInt128(2)^(15*8)) === UInt128(1)
end
@testset "count_zeros" begin
    @test count_zeros(10) === Sys.WORD_SIZE - 2
    @test count_zeros(UInt8(10)) === 6
end
@testset "Conversions" begin
    @test convert(Signed, UInt128(3)) === Int128(3)
    @test convert(Signed, false) === 0
    @test convert(Signed, true) === 1

    for (II, UU) in ((Int8,UInt8), (Int16,UInt16),
                     (Int32,UInt32), (Int64,UInt64),
                     (Int128,UInt128))
        @test convert(Unsigned, II(3)) === UU(3)
    end

    for T in (Float32, Float64)
        @test convert(Unsigned, T(3.0)) === UInt(3)
    end
end

@testset "trunc, floor, ceil" begin
    @test trunc(3) === 3
    @test trunc(Integer, 3) === 3

    @test floor(3) === 3
    @test ceil(3) === 3
end

@testset "big" begin
    @test big"2"^100 == BigInt(2)^100
    @test isa(big"2", BigInt)
    @test big"1.0" == BigFloat(1.0)
    @test_throws ArgumentError big"1.0.3"
    @test_throws ArgumentError big"pi"
end

@test round(UInt8, 123) == 123
@test mod(123, UInt8) === 0x7b

primitive type MyBitsType <: Signed 8 end
@test_throws MethodError ~reinterpret(MyBitsType, 0x7b)
@test signed(MyBitsType) === MyBitsType

UItypes = Base.BitUnsigned_types
SItypes = Base.BitSigned_types

@testset "promotions" begin
    for T in UItypes, S in UItypes
        @test promote(S(3), T(3)) === (sizeof(T) < sizeof(S) ? (S(3), S(3)) : (T(3), T(3)))
    end

    for T in SItypes, S in SItypes
        @test promote(S(3), T(3)) === (sizeof(T) < sizeof(S) ? (S(3), S(3)) : (T(3), T(3)))
    end

    for T in SItypes, S in UItypes
        R = sizeof(S) < sizeof(Int) ? Int : S
        @test promote(R(3), T(3)) === (sizeof(R) < sizeof(T) ? (T(3), T(3)) : (R(3), R(3)))
    end

    for i in 1:length(UItypes)
        @test promote(UItypes[i](3), SItypes[i](3)) === (UItypes[i](3), UItypes[i](3))
    end
end
@testset "limiting conversions" begin
    for T in (Int8, Int16, Int32, Int64)
        max_val = Int128(typemax(T))
        @test convert(T, max_val) == max_val
        @test_throws InexactError convert(T, max_val+1)

        min_val = Int128(typemin(T))
        @test convert(T, min_val) == min_val
        @test_throws InexactError convert(T, min_val-1)
    end

    for T in (UInt8, UInt16, UInt32, UInt64)
        max_val = Int128(typemax(T))
        @test convert(T, max_val) == max_val
        @test_throws InexactError convert(T, max_val+1)
        @test_throws InexactError convert(T, -1)
    end
end
@testset "bit shifts" begin
    for T in Base.BitInteger_types
        nbits = 8*sizeof(T)
        issigned = typemin(T) < 0
        highbit = T(2) ^ (nbits-1)
        val1 = 0x1234567890abcdef % T % highbit
        val2 = val1 + highbit
        for val in (val1, val2)
            for count in 0:nbits+1
                ucount, scount = unsigned(count), signed(count)
                # Note: We assume modulo semantics for the arithmetic operations
                # used here
                if count < nbits
                    @test val << ucount === val * T(2)^count
                    @test val >>> ucount ===
                        fld(unsigned(val), unsigned(T(2))^count) % T
                else
                    @test val << ucount === T(0)
                    @test val >>> ucount === T(0)
                end
                @test val << scount === val << ucount
                @test val << -scount === val >> ucount
                @test val >>> scount === val >>> ucount
                @test val >>> -scount === val << ucount
                if count < (issigned ? nbits-1 : nbits)
                    @test val >> ucount === fld(val, T(2)^count)
                else
                    @test val >> ucount === T(val<0 ? -1 : 0)
                end
                @test val >> scount === val >> ucount
                @test val >> -scount === val << ucount
            end
        end
    end
end

@testset "bit rotations" begin
    val1 = 0b01100011
    @test 0b00011011 === bitrotate(val1, 3)
    @test 0b01101100 === bitrotate(val1, -3)
    @test val1 === bitrotate(val1, 0)

    for T in Base.BitInteger_types
        @test val1 === bitrotate(val1, sizeof(T) * 8) === bitrotate(val1, sizeof(T) * -8)
    end

    val2 = 0xabcd
    @test 0x5e6d === bitrotate(val2, 3)
    @test 0xb579 === bitrotate(val2, -3)
end

@testset "widen/widemul" begin
    @test widen(UInt8(3)) === UInt16(3)
    @test widen(UInt16(3)) === UInt32(3)
    @test widen(UInt32(3)) === UInt64(3)
    @test widen(UInt64(3)) === UInt128(3)
    @test widen(UInt128(3)) == 3

    @test typeof(widen(UInt8(3))) == UInt16
    @test typeof(widen(UInt16(3))) == UInt32
    @test typeof(widen(UInt32(3))) == UInt64
    @test typeof(widen(UInt64(3))) == UInt128
    @test typeof(widen(UInt128(3))) == BigInt

    @test widen(Int8(-3)) === Int16(-3)
    @test widen(Int16(-3)) === Int32(-3)
    @test widen(Int32(-3)) === Int64(-3)
    @test widen(Int64(-3)) === Int128(-3)
    @test widen(Int128(-3)) == -3

    @test typeof(widen(Int8(-3))) == Int16
    @test typeof(widen(Int16(-3))) == Int32
    @test typeof(widen(Int32(-3))) == Int64
    @test typeof(widen(Int64(-3))) == Int128
    @test typeof(widen(Int128(-3))) == BigInt

    @test widemul(false, false) === false
    @test widemul(false, 3) === 0
    @test widemul(3, true) === widemul(true, 3) === 3

    let i=Int64(2)^63-1, k=widemul(i,i)
        @test widemul(i,i)===85070591730234615847396907784232501249
        j=div(k,2)
        @test div(k,j)==2
        j=div(k,5)
        @test rem(k,j)==4
    end
end
@testset "issue #3596" begin
    @test Int128(1)<<0 == 1
    @test repr(Int128(1)<<1) == "2"
end
# issue #16700
@test_throws MethodError 1.0 >> 8

@testset "PR #16988" begin
    @test true << 2 === 1 << 2
    @test true >> 2 === 1 >> 2
    @test true >>> 2 === 1 >>> 2
end
@testset "unsafe_trunc" begin
    @test @inferred(unsafe_trunc(Int8, 127)) === Int8(127)
    @test unsafe_trunc(Int8, 128) === Int8(-128)
    @test unsafe_trunc(Int8, -127) === Int8(-127)
    @test unsafe_trunc(Int8, -128) === Int8(-128)
    @test unsafe_trunc(Int8, -129) === Int8(127)
end
@testset "x % T returns a T, T = $T" for T in [Base.BitInteger_types..., BigInt],
    U in [Base.BitInteger_types..., BigInt]
    @test typeof(rand(U(0):U(127)) % T) === T
end

@testset "Signed, Unsigned, signed, unsigned for bitstypes" begin
    for (S,U) in zip(Base.BitSigned_types, Base.BitUnsigned_types)
        @test signed(U) === S
        @test unsigned(S) === U
        @test typemin(S) % Signed === typemin(S)
        @test typemax(U) % Unsigned === typemax(U)
        @test -one(S) % Unsigned % Signed === -one(S)
        @test ~one(U) % Signed % Unsigned === ~one(U)
    end
end

@testset "issue #15489" begin
    @test 0x00007ffea27edaa0 + (-40) === (-40) + 0x00007ffea27edaa0 === 0x00007ffea27eda78
    @test UInt64(1) * Int64(-1) === typemax(UInt64)
    @test UInt(1) - (-1) == 2
    @test UInt64(15) & -4 === UInt64(12)
    @test UInt64(15) | -4 === typemax(UInt64)
    @test UInt64(15) ⊻ -4 === 0xfffffffffffffff3
end

@testset "left shift with Vector{Int} on BigInt-scalar #13832" begin
    x = BigInt(1) .<< [1:70;]
    @test x[end] == 1180591620717411303424
    @test eltype(x) == BigInt
end

# issue #9292
@testset "mixed signedness arithmetic" begin
    for T in Base.BitInteger_types
        for S in Base.BitInteger_types
            a, b = one(T), one(S)
            for c in (a+b, a-b, a*b)
                if T === S
                    @test c isa T
                elseif sizeof(T) > sizeof(S)
                    # larger type wins
                    @test c isa T
                elseif sizeof(S) > sizeof(T)
                    @test c isa S
                else
                    # otherwise Unsigned wins
                    @test c isa (T <: Unsigned ? T : S)
                end
            end
        end
    end
end

@testset "Underscores in big_str" begin
    @test big"1_0_0_0" == BigInt(1000)
    @test_throws ArgumentError big"1_0_0_0_"
    @test_throws ArgumentError big"_1_0_0_0"

    @test big"1_0.2_5" == BigFloat(10.25)
    @test_throws ArgumentError big"_1_0.2_5"
    @test_throws ArgumentError big"1_0.2_5_"
    @test_throws ArgumentError big"1_0_.2_5"
    @test_throws ArgumentError big"1_0._2_5"
end

# issue #26779
struct MyInt26779 <: Integer
    x::Int
end
@test promote_type(MyInt26779, Int) == Integer
@test_throws ErrorException MyInt26779(1) + 1
let i = MyInt26779(1)
    @test_throws MethodError i >> 1
    @test_throws MethodError i << 1
    @test_throws MethodError i >>> 1
end

@testset "rounding division" begin
    for x = -100:100
        for y = 1:100
            for rnd in (RoundNearest, RoundNearestTiesAway, RoundNearestTiesUp, RoundFromZero)
                @test div(x,y,rnd) == round(x/y,rnd)
                @test div(x,-y,rnd) == round(x/-y,rnd)
            end
            @test divrem(x,y,RoundFromZero) == (div(x,y,RoundFromZero), rem(x,y,RoundFromZero))
            @test divrem(x,-y,RoundFromZero) == (div(x,-y,RoundFromZero), rem(x,-y,RoundFromZero))
        end
    end
    for (a, b, nearest, away, up, from_zero) in (
            (3, 2, 2, 2, 2, 2),
            (5, 3, 2, 2, 2, 2),
            (-3, 2, -2, -2, -1, -2),
            (5, 2, 2, 3, 3, 3),
            (-5, 2, -2, -3, -2, -3),
            (-5, 3, -2, -2, -2, -2),
            (5, -3, -2, -2, -2, -2))
        for sign in (+1, -1)
            (a, b) = (a*sign, b*sign)
            @test div(a, b, RoundNearest) === nearest
            @test div(a, b, RoundNearestTiesAway) === away
            @test div(a, b, RoundNearestTiesUp) === up
            @test div(a, b, RoundFromZero) === from_zero
        end
    end

    @test div(typemax(Int64), typemax(Int64)-1, RoundNearest) == 1
    @test div(-typemax(Int64), typemax(Int64)-1, RoundNearest) == -1
    @test div(typemax(Int64), 2, RoundNearest) == 4611686018427387904
    @test div(-typemax(Int64), 2, RoundNearestTiesUp) == -4611686018427387903
    @test div(typemax(Int)-2, typemax(Int), RoundNearest) === 1

    # Exhaustively test (U)Int8 to catch any overflow-style issues
    for r in (RoundNearest, RoundNearestTiesAway, RoundNearestTiesUp, RoundFromZero)
        for T in (UInt8, Int8)
            for x in typemin(T):typemax(T)
                for y in typemin(T):typemax(T)
                    if y == 0 || (T <: Signed && x == typemin(T) && y == -1)
                        @test_throws DivideError div(x, y, r)
                    else
                        @test div(x, y, r) == T(div(widen(T)(x), widen(T)(y), r))
                    end
                end
            end
        end
    end
end

@testset "bitreverse" begin
    for T in Base.BitInteger_types
        x = rand(T)::T
        @test bitreverse(x) isa T
        @test reverse(bitstring(x)) == bitstring(bitreverse(x))
    end
    @test bitreverse(0x80) === 0x01
    @test bitreverse(Int64(456618293)) === Int64(-6012608040035942400)
    @test bitreverse(Int32(456618293)) === Int32(-1399919400)
end

@testset "min/max of datatype" begin
    @test typemin(Int8) === Int8(-128)
    @test typemin(UInt8) === UInt8(0)
    @test typemin(Int16) === Int16(-32768)
    @test typemin(UInt16) === UInt16(0)
    @test typemin(Int32) === Int32(-2147483648)
    @test typemin(UInt32) === UInt32(0)
    @test typemin(Int64) === Int64(-9223372036854775808)
    @test typemin(UInt64) === UInt64(0)
    @test typemin(Int128) === Int128(-170141183460469231731687303715884105728)
    @test typemin(UInt128) === UInt128(0)

    @test typemax(Int8) === Int8(127)
    @test typemax(UInt8) === UInt8(255)
    @test typemax(Int16) === Int16(32767)
    @test typemax(UInt16) === UInt16(65535)
    @test typemax(Int32) === Int32(2147483647)
    @test typemax(UInt32) === UInt32(4294967295)
    @test typemax(Int64) === Int64(9223372036854775807)
    @test typemax(UInt64) === UInt64(0xffffffffffffffff)
    @test typemax(Int128) === Int128(170141183460469231731687303715884105727)
    @test typemax(UInt128) === UInt128(0xffffffffffffffffffffffffffffffff)
end

@testset "BitIntegerType" begin
    @test Int isa Base.BitIntegerType
    @test Base.BitIntegerType === Union{
        Type{ Int8}, Type{ Int16}, Type{ Int32}, Type{ Int64}, Type{ Int128},
        Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UInt64}, Type{UInt128}}
end

max_stars_repo_name: SmiteWindows/julia

max_issues_repo_name: SmiteWindows/julia

max_forks_repo_name: SmiteWindows/julia


text:
using DrWatson
@quickactivate "StatReth"

# %%
using Distributions
using Plots

# %% 4.6
w = 6
n = 9
p_grid = range(0, 1, length = 100)
posterior = @. pdf(Binomial(n, p_grid), w) * pdf(Uniform(0, 1), p_grid)
posterior ./= sum(posterior)

plot(p_grid, posterior)


text:
# watch https://github.com/FluxML/Zygote.jl/pull/623

using Zygote

ignore(f) = f()
Zygote.@adjoint ignore(f) = ignore(f), _ -> nothing

using ReinforcementLearningCore

(app::NeuralNetworkApproximator)(args...; kwargs...) = app.model(args...; kwargs...)

using AbstractTrees
using TensorBoardLogger: TBLogger

AbstractTrees.children(t::StructTree{T}) where {T<:Union{TBLogger}} = ()


text:
using Test
using SimpleQuantum

q = Q0
@test measure!(q) == 0
q = Q1
@test measure!(q) == 1

total = 0
for k = 1:1000
    local q = Qubit(3, 4im)
    local v = measure!(q)
    global total += v
    if v == 0
        @test q == Q0
    else
        @test q == Q1
    end
end
println("total = $total which should be around 640")

total = 0
for k = 1:1000
    local q = RandomQubit()
    local v = measure!(q)
    global total += v
end
println("Generated 1000 random qubits and got $total ones")

q = Qubit(3, 4im)
w = q.vec[1]
z = q.vec[2]
@test w == 0.6
@test z == 0.8im


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

using Markdown
using InteractiveUtils

# ╔═╡ 60a31e42-95db-47b4-a173-9874425c0570
begin
	using Distributions
	using GaussianProcesses
	using Optim
	using Plots
	import PlotlyJS
	plotlyjs();
	#Global plotting options
	default(size=(675,325),foreground_color_legend = nothing)
end

# ╔═╡ 3d7989b6-74eb-4a41-8c0e-d8364b1e7ed1
md"""
## Talking myself through Gaussian processes and Bayesian inference[^1]
Stefan Bringuier[^a]
"""

# ╔═╡ 6eaf1750-31e1-479e-b9d5-8532c3619f80
md"""
[^1]: This is basically my notes as I work through thinking about Gaussian processes and Bayesian methods, so there are going to regular mistakes. No warrenty of correctness is given.
[^a]: Contact at stefanbringuier@gmail.com
"""

# ╔═╡ 33852240-0213-11ec-048e-353623cf3fad
md"""
Here i'm going to look at a simple test problem for Bayesian optimization. I will follow the tutorial located [here](https://machinelearningmastery.com/what-is-bayesian-optimization/).
"""

# ╔═╡ 8e0754e9-7396-4744-a626-0774013fb68f
md"""
As a first step lets define a "block-box" function that will generate some data for us. In an experimental setting this would be some event where data is being recorded based on controlled parameters. For computer simulation, this is data being generated from some program/code with known inputs.

For this example, the black box function is just going to be:

$f(x) = x^2 \sin\left(5\pi x\right)^6 + \scr{N}\left(0,σ\right)$

where the last term is some noise with a normal distributions. The goal of this little exersise is to work through Gaussian processes to model the data and then iteratively update where one should sample the black-box function next. That is, what $x$ should be choosen so that we can recover $f(x)$.

The benefit to using Gaussian processes, is that we model the function $f(x)$ with probability functions and therefore we inherently know our uncertaintly. Furthermore, in the framework of Bayesian inference we are able to take our prior knowledge (i.e. the variables for the model in the likelihood probability of the observations given the model) and update it in the posterior. More concisely in terms of Gaussian processes.

the data will be generated from a one-dimensional multimodal function that is augmented by a normally distributed noise.
"""

# ╔═╡ 90a03b2d-3101-4d2c-b85b-c7a41a94ae43
generate_data(x::Real;σ=0.0::Real) = begin
	ℵ = rand(Normal(0.0,σ));
	return x^2 * sin(5π*x)^6 + ℵ
end;

# ╔═╡ ab7dead8-305b-4c94-adff-6cc3e34b5416
generate_data(x::Array{T,1};σ=0.0::Real) where T<:Real = map(y -> generate_data(y,σ=σ),x);

# ╔═╡ f904beb4-3003-44c2-ba68-4277f576e8b7
begin
	x = collect(range(0,1,step=0.01))
	data = generate_data(x)
	noisydata = generate_data(x,σ=0.05)
	Plots.plot(x,data,label="known function",
			   size=(675,375))
	Plots.scatter!(x,noisydata,label="noisy data")
end

# ╔═╡ 20cc9df2-7229-45c8-b176-1f608554b4bb
md"""
Now the idea is to use a surrogate function to the observed data using probablistic methods, more specifically, a Bayesian approach. This means we need to select  proper prior, likelihood, and evidence distribution functions.

To begin lets address the likelihood probability, which is the likelihood of one of the possible models, or in other words what is the probability of that data given one o the models:

$p(x|M,\theta)$

here $x$ is the data, $M$ the model, and $\theta$ that model parameters. I think in Gaussian processing we marginalize over the models. Also called kriging if discrete I guess. So that what we get for our likelihood is:

$p(x|\theta) = \sum_i^N p(x|\theta,M_i) p(M_i)$

and our posterior reads:

$p(\theta|x) = p(x|\theta) p(\theta)$
"""

# ╔═╡ 0bdc6166-2a57-41eb-847a-7637ff33098c
md"""
## Create a Gaussian Process model

In this section I'll pretend that some of the data is available to us from the black-box function and that the data is noisy. With this in mind, below we have some selected indices from the data set and the corresponding values, as seen in the plot.

"""

# ╔═╡ 2539aefb-5655-431c-8718-37b83ea29ad4
begin
	xused = [ 2; 4; 12; 34; 65; 68; 92; 98];
	yused = generate_data(x[xused[:]]);
	scatter(x[xused[:]],yused)
end

# ╔═╡ c64c6e64-057d-400f-a31a-9a7bc654dffe
md"""
Here is the Gaussian process sept. First note is that I'm going to use [GaussianProcesses.jl](https://github.com/STOR-i/GaussianProcesses.jl) to create the model. In the future I would like to revisit this and do it from scratch but for now I'm just going to see how it works out.

For the GP model, we need to specificy our priors for parameters or hyperparameters for the normal distribution over model functions. Here I'm just going to use some standard values, a mean valued-function that evaluates to zero and a squared exponential kernel.
"""

# ╔═╡ 1325fe27-326b-4f2d-a8dd-78ef436c6155
begin
	μ = MeanZero()
	𝐾 = SEIso(0.0,0.0)
	gp = GP(x[xused[:]],noisydata[xused[:]],μ,𝐾)
end

# ╔═╡ ff012bba-7669-4937-8ee7-f941816910d4
md"""
Finally we want to obtain the optimal parameters/hyperparameters that would let us perform inference, in other words, obtain the posterior probability function. Since we are using the [GaussianProcesses.jl](https://github.com/STOR-i/GaussianProcesses.jl) package we can do this with the [Optim.jl](https://github.com/JuliaNLSolvers/Optim.jl) package straightforwardly. This works when the likelyhood probability function corresponds to data that is Gaussian in nature, but for other types of probability functions this approach won't work and one has to resort to other integration techniques like Markov-chain Monte Carlo.
"""

# ╔═╡ ba4c1965-1231-4a08-bc23-577a3ad290cf
optimize!(gp)

# ╔═╡ f487f7f2-c9be-4b7f-a1bf-e773ca28a970
plot(gp,label=["surrogate model" "sampled points"])

# ╔═╡ cdf15771-d575-445d-8e58-fbb58c209416
md"""
## Create improvement criteria

The idea here is to create a acquisition function for the next point to sample from the objective function. This is basically the Bayesian inference/optimization. What we do is take the Gaussian processes model with the priors and optimized hyperparameters and calculate mean and variance for known data points and randomly drawn points. Then we obtain the cumulative density function for a Normal distrubtion at points based on the difference between the best and sampled points and take the location of largest probability. I still need to review aquisition functions like expected improvement.
"""

# ╔═╡ fa9bb0f0-5917-4d20-b60d-5cbb719d1f3b
function acquisition(xsample,x,model::GPE)
	y,_ = predict_f(model,x)
	μ,σ² = predict_f(model,xsample)
	probs = cdf(Normal(), μ .- maximum(y) ./ sqrt.(σ²))
	return probs
end;

# ╔═╡ 33c21ed9-098c-42d2-a192-6c633c7f6f4f
function optimize_acquisition(x,model::GPE)
	xsample = rand(Uniform(0,1),100)
	scores = acquisition(xsample,x,model)
	ix = argmax(scores)
	wheretosample = xsample[ix]
	return wheretosample
end;

# ╔═╡ d0536f6c-4040-4f8f-a2b3-7740257679e1
md"""
## Sampling black-box to infer where to sample next using optimization.

Now we will wrap everything together. That is the Gaussian processes model with priors and optimized hyperparameters and Bayesian inference. Here we take the Gaussian processes and aquisition function and find out where to sample next, then optimize the likelihood function in the Gaussian processes. We keep doing this till we are content.
"""

# ╔═╡ 2d59c3a5-bb3d-4577-bf4b-0158a7a853d7
md"""
Click 👀 button to show plotting function below ⬇
"""

# ╔═╡ 44979d9e-1c78-4d0e-89a8-3cf14242aa2d
"""
routine for plotting results

## Inputs
	* x :: Vector{Real} : domain values for black-box function
	* y :: Vector{Real} : black-box function values for domain
	* i :: Vector{Integer}: actual observations for domain and black-box function
	* xu:: Vector{real} : x[i]
	* yu:: Vector{real} : y[i]
	* gpp:: GP model
""" function gifplot(s,x,y,i,xu,yu,gpp)
	p1 = plot(x,generate_data(x),label="known noise-free function",linewidth=3)
    scatter!(p1,x[i],y[i],markershape=:diamond,markersize=6, label= "initial noise-containing data")
	scatter!(p1,xu,yu,label="gaussian process probing black-box function")
	p2 = plot(gpp,label=["surrogate model" "points"],annotations = (0.01, 0.85, text("Surrogate model. Step $s", :left,9,:Arial)))
	return plot(p1,p2,layout=(2,1),size=(900,700),xlim=(0.0,1.0),ylim=(-0.25,1.0),legend=:topleft)
end;

# ╔═╡ 4db2b031-f408-463f-8e2f-8dcf055c374c
let
	xu,yu = x[xused[:]],noisydata[xused[:]]
	lxi = length(xu)
	gpi = GP(xu,yu,μ,𝐾)
	optimize!(gpi)
	anim = @animate for i=1:50
		xi = optimize_acquisition(xu,gpi)
		ycalc = generate_data(xi,σ=0.05) #Generate data on fly from "black box"
		ypred,varpred = predict_f(gpi,[xi])
		push!(xu,xi)
		push!(yu,ycalc)
		gpi = GP(xu,yu,μ,𝐾)
		optimize!(gpi)

		#Plotting
		gifplot(i,x,noisydata,xused[:],xu[lxi:end],yu[lxi:end],gpi)

	end
	gif(anim,fps=1)
end

# ╔═╡ 42ba19d9-4e65-4621-b713-ffc4d1051380
let
content = md"""
	```julia
	p1 = Plots.plot(x,generate_data(x),label="known noise-free function",linewidth=3)

	Plots.scatter(p1,x[xused[:]],noisydata[xused[:]],markershape=:diamond,markersize=6, label= "initial data")

	Plots.scatter!(p1,xu[lxi:end],yu[lxi:end],label="gaussian process probing black-box function")

	p2 = Plots.plot(gpi,label=false)

	Plots.plot(p1,p2,layout=(2,1),ylim=(-0.25,1.0))
	```
	"""
HTML("Show old plot code$(html(content))")

end

# ╔═╡ c945f7b9-c728-473c-8597-9c26522dbdfc
md"""
An interesting thing here is that the optimization using Gaussian processes looks like it captures the known function despite the noise. In other words, it samples ideally so that the orignial function is most clearly captured despite the noise. Interesting ❗
"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
GaussianProcesses = "891a1506-143c-57d2-908e-e1f8e92e6de9"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[compat]
Distributions = "~0.24.18"
GaussianProcesses = "~0.12.4"
Optim = "~1.4.1"
PlotlyJS = "~0.18.5"
Plots = "~1.20.1"
"""

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

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

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

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

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

[[AssetRegistry]]
deps = ["Distributed", "JSON", "Pidfile", "SHA", "Test"]
git-tree-sha1 = "b25e88db7944f98789130d7b503276bc34bc098e"
uuid = "bf4720bc-e11a-5d0c-854e-bdca1663c893"
version = "0.1.0"

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

[[BinDeps]]
deps = ["Libdl", "Pkg", "SHA", "URIParser", "Unicode"]
git-tree-sha1 = "1289b57e8cf019aede076edab0587eb9644175bd"
uuid = "9e28174c-4ba2-5203-b857-d8d62c4213ee"
version = "1.0.2"

[[Blink]]
deps = ["Base64", "BinDeps", "Distributed", "JSExpr", "JSON", "Lazy", "Logging", "MacroTools", "Mustache", "Mux", "Reexport", "Sockets", "WebIO", "WebSockets"]
git-tree-sha1 = "08d0b679fd7caa49e2bca9214b131289e19808c0"
uuid = "ad839575-38b3-5650-b840-f874b8c74a25"
version = "0.12.5"

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

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

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

[[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 = "32a2b8af383f11cbb65803883837a149d10dfe8a"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.10.12"

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

[[CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[ElasticArrays]]
deps = ["Adapt"]
git-tree-sha1 = "a0fcc1bb3c9ceaf07e1d0529c9806ce94be6adf9"
uuid = "fdbdab4c-e67f-52f5-8c3f-e7b388dad3d4"
version = "1.2.9"

[[ElasticPDMats]]
deps = ["LinearAlgebra", "MacroTools", "PDMats"]
git-tree-sha1 = "5157c93fe9431a041e4cd84265dfce3d53a52323"
uuid = "2904ab23-551e-5aed-883f-487f97af5226"
version = "0.2.2"

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

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

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

[[FastGaussQuadrature]]
deps = ["LinearAlgebra", "SpecialFunctions", "StaticArrays"]
git-tree-sha1 = "5829b25887e53fb6730a9df2ff89ed24baa6abf6"
uuid = "442a2c76-b920-505d-bb47-c5924d526838"
version = "0.4.7"

[[FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"

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

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

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

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

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

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

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

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

[[FunctionalCollections]]
deps = ["Test"]
git-tree-sha1 = "04cb9cfaa6ba5311973994fe3496ddec19b6292a"
uuid = "de31a74c-ac4f-5751-b3fd-e18cd04993ca"
version = "0.5.0"

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

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

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

[[GaussianProcesses]]
deps = ["Distances", "Distributions", "ElasticArrays", "ElasticPDMats", "FastGaussQuadrature", "ForwardDiff", "LinearAlgebra", "Optim", "PDMats", "Printf", "ProgressMeter", "Random", "RecipesBase", "ScikitLearnBase", "SpecialFunctions", "StaticArrays", "Statistics", "StatsFuns"]
git-tree-sha1 = "9cf8ba8037e332b1be14c71e549143e68c42a22d"
uuid = "891a1506-143c-57d2-908e-e1f8e92e6de9"
version = "0.12.4"

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

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

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

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

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

[[Hiccup]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "6187bb2d5fcbb2007c39e7ac53308b0d371124bd"
uuid = "9fb69e20-1954-56bb-a84f-559cc56a8ff7"
version = "0.2.2"

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

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

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

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

[[JSExpr]]
deps = ["JSON", "MacroTools", "Observables", "WebIO"]
git-tree-sha1 = "bd6c034156b1e7295450a219c4340e32e50b08b1"
uuid = "97c1335a-c9c5-57fe-bc5d-ec35cebe8660"
version = "0.5.3"

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

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

[[Kaleido_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "2ef87eeaa28713cb010f9fb0be288b6c1a4ecd53"
uuid = "f7e6163d-2fa5-5f23-b69c-1db539e41963"
version = "0.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"

[[Lazy]]
deps = ["MacroTools"]
git-tree-sha1 = "1370f8202dac30758f3c345f9909b97f53d87d3f"
uuid = "50d2b5c4-7a5e-59d5-8109-a42b560f39c0"
version = "0.15.1"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[Mustache]]
deps = ["Printf", "Tables"]
git-tree-sha1 = "36995ef0d532fe08119d70b2365b7b03d4e00f48"
uuid = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
version = "1.0.10"

[[Mux]]
deps = ["AssetRegistry", "Base64", "HTTP", "Hiccup", "Pkg", "Sockets", "WebSockets"]
git-tree-sha1 = "82dfb2cead9895e10ee1b0ca37a01088456c4364"
uuid = "a975b10e-0019-58db-a62f-e48ff68538c9"
version = "0.7.6"

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

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

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

[[Observables]]
git-tree-sha1 = "3469ef96607a6b9a1e89e54e6f23401073ed3126"
uuid = "510215fc-4207-5dde-b226-833fc4488ee2"
version = "0.3.3"

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

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

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

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

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

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

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

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

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

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

[[Pidfile]]
deps = ["FileWatching", "Test"]
git-tree-sha1 = "1be8660b2064893cd2dae4bd004b589278e4440d"
uuid = "fa939f87-e72e-5be4-a000-7fc836dbe307"
version = "1.2.0"

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

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

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

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

[[PlotlyBase]]
deps = ["ColorSchemes", "Dates", "DelimitedFiles", "DocStringExtensions", "JSON", "LaTeXStrings", "Logging", "Parameters", "Pkg", "REPL", "Requires", "Statistics", "UUIDs"]
git-tree-sha1 = "3984b84a295d1bcf0d0f7902f9fb1eeed54f97db"
uuid = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
version = "0.8.13"

[[PlotlyJS]]
deps = ["Base64", "Blink", "DelimitedFiles", "JSExpr", "JSON", "Kaleido_jll", "Markdown", "Pkg", "PlotlyBase", "REPL", "Reexport", "Requires", "WebIO"]
git-tree-sha1 = "2e001b91e953f214191314c397c389d8743c8d5f"
uuid = "f0f68f2c-4968-5e81-91da-67840de0976a"
version = "0.18.5"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[ScikitLearnBase]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "7877e55c1523a4b336b433da39c8e8c08d2f221f"
uuid = "6e75b9c4-186b-50bd-896f-2d2496a4843e"
version = "0.5.0"

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

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

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

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

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

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

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

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

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

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

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

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

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

[[URIParser]]
deps = ["Unicode"]
git-tree-sha1 = "53a9f49546b8d2dd2e688d216421d050c9a31d0d"
uuid = "30578b45-9adc-5946-b283-645ec420af67"
version = "0.4.1"

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

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

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

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

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

[[WebIO]]
deps = ["AssetRegistry", "Base64", "Distributed", "FunctionalCollections", "JSON", "Logging", "Observables", "Pkg", "Random", "Requires", "Sockets", "UUIDs", "WebSockets", "Widgets"]
git-tree-sha1 = "adc25e225bc334c7df6eec3b39496edfc451cc38"
uuid = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29"
version = "0.8.15"

[[WebSockets]]
deps = ["Base64", "Dates", "HTTP", "Logging", "Sockets"]
git-tree-sha1 = "f91a602e25fe6b89afc93cf02a4ae18ee9384ce3"
uuid = "104b5d7c-a370-577a-8038-80a2059c5097"
version = "1.5.9"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# ╔═╡ Cell order:
# ╟─3d7989b6-74eb-4a41-8c0e-d8364b1e7ed1
# ╟─6eaf1750-31e1-479e-b9d5-8532c3619f80
# ╟─33852240-0213-11ec-048e-353623cf3fad
# ╟─8e0754e9-7396-4744-a626-0774013fb68f
# ╠═90a03b2d-3101-4d2c-b85b-c7a41a94ae43
# ╠═ab7dead8-305b-4c94-adff-6cc3e34b5416
# ╠═f904beb4-3003-44c2-ba68-4277f576e8b7
# ╟─20cc9df2-7229-45c8-b176-1f608554b4bb
# ╟─0bdc6166-2a57-41eb-847a-7637ff33098c
# ╠═2539aefb-5655-431c-8718-37b83ea29ad4
# ╟─c64c6e64-057d-400f-a31a-9a7bc654dffe
# ╠═1325fe27-326b-4f2d-a8dd-78ef436c6155
# ╟─ff012bba-7669-4937-8ee7-f941816910d4
# ╠═ba4c1965-1231-4a08-bc23-577a3ad290cf
# ╠═f487f7f2-c9be-4b7f-a1bf-e773ca28a970
# ╟─cdf15771-d575-445d-8e58-fbb58c209416
# ╠═fa9bb0f0-5917-4d20-b60d-5cbb719d1f3b
# ╠═33c21ed9-098c-42d2-a192-6c633c7f6f4f
# ╟─d0536f6c-4040-4f8f-a2b3-7740257679e1
# ╟─2d59c3a5-bb3d-4577-bf4b-0158a7a853d7
# ╟─44979d9e-1c78-4d0e-89a8-3cf14242aa2d
# ╠═4db2b031-f408-463f-8e2f-8dcf055c374c
# ╟─42ba19d9-4e65-4621-b713-ffc4d1051380
# ╟─c945f7b9-c728-473c-8597-9c26522dbdfc
# ╠═60a31e42-95db-47b4-a173-9874425c0570
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: stefanbringuier/PlutoNotebookBlogging

max_issues_repo_name: stefanbringuier/PlutoNotebookBlogging

max_forks_repo_name: stefanbringuier/PlutoNotebookBlogging