text:
using PyCall
using LinearAlgebra
using SparseArrays
using Combinatorics:permutations
#special testing
numpy = pyimport("numpy")
function numpy_kron(A,B)
    return numpy.kron(A,B)
end

ERROR_TOL = 1e-13

#Checks to see if under special parameters the marginalized tensors of HOFASM and HOM are equal.
function test_code()
    n = 10
    m = 10
    source = HOFASM.brute_force_triangles(rand(n,2))
    source[2] = (source[2][1],source[1][2]) #make a duplicate angle
    target = HOFASM.brute_force_triangles(rand(m,2))

    H_indices, H_vals,B_indices,B_vals =
        HOFASM.build_index_and_bases_tensors(source, target, 5.0,test_mode=true)
    HOFASM_perm_marg_ten = HOFASM_mode1_marg(H_indices,B_indices,B_vals,m,n)

    HOM_indices, HOM_vals = HOFASM.produce_HOM_tensor(source,target,m,tol=1e-16,test_mode=true)
    HOM_marg_ten = Matrix(HOFASM.sym_mode1_marginalization(HOM_indices,HOM_vals,n*m))

    #symmetry check
    @assert norm(HOM_marg_ten - HOM_marg_ten')/norm(HOM_marg_ten) < ERROR_TOL
    #println(norm(HOFASM_marg_ten - HOFASM_marg_ten')/norm(HOFASM_marg_ten))
    @assert norm(HOFASM_perm_marg_ten - HOFASM_perm_marg_ten')/norm(HOFASM_perm_marg_ten) < ERROR_TOL

    #equality check
    println(norm(HOM_marg_ten - HOFASM_perm_marg_ten) / norm(HOFASM_perm_marg_ten))
    @assert norm(HOM_marg_ten - HOFASM_perm_marg_ten)/norm(HOFASM_perm_marg_ten) < ERROR_TOL

end

#checks to see that all the different forms of HOFASM contractions yield the same values
function test_contraction(n::Int=30,m::Int=30,bin_size::Float64=5.0)

    source = HOFASM.brute_force_triangles(rand(n,2))
    target = HOFASM.brute_force_triangles(rand(m,2))

    H_indices, H_vals,B_indices,B_vals = HOFASM.build_index_and_bases_tensors(source, target, bin_size)
    pairs,pair_timing = @timed HOFASM.Make_HOFASM_tensor_pairs(H_indices,B_indices,B_vals,m,n)

    println("built $(length(pairs)) pairs")

    #--------------------------------unprocessed HXBᵀ------------------------------------------#
    x = ones(n*m)
    X = Matrix(reshape(x,m,n)') #julia defaults to col major formatting
    Y1 = rand(n,m)

    t1 = @timed HOFASM.HOFASM_contraction!(pairs,X,Y1)
    println("HOFASM_contraction runtimes;
            pre-processing: $(pair_timing[1])    contraction op:$(t1[2])")

    #--------------------------------pre-processed HXBᵀ----------------------------------------#
    Y2 = rand(n,m)
    preprocessed_pairs,processing_time = @timed [(findnz(H)...,B) for (H,B) in pairs]
    #preprocessed_pairs = [(findnz(H)...,B) for (H,B) in pairs]
    #return preprocessed_pairs,X,Y
    t2 = @timed HOFASM.HOFASM_contraction!(preprocessed_pairs,X,Y2)
    println("preprocessed HOFASM_contraction runtimes;
             pre-processing:$(processing_time[1]+pair_timing[1]) contraction op:$(t2[2])  ")

    #-----------------------------implicit marginalization-------------------------------------#
    implicit_marg_kron_y = rand(n*m)
    t3 = @timed HOFASM.implicit_kronecker_model_marginalization_contraction!(B_indices,B_vals,H_indices,
                                                                      x,implicit_marg_kron_y,n,m)
    println("explicit marg kron HOFASM_contraction runtimes;
             contraction op:$(t3[2])")

    #-----------------------------explicit marginalization-------------------------------------#

    kron_pairs, kron_times = @timed [HOFASM.perm_marginalize(Hn_ind,Bn_ind,Bn_val,n,m) for (Bn_ind,Bn_val,Hn_ind) in zip(B_indices,B_vals,H_indices)]
    explicit_marg_kron_y = rand(n*m)

    t4 = @timed HOFASM.HOFASM_contraction!(kron_pairs,x,explicit_marg_kron_y)
    println("explicit marg kron HOFASM_contraction runtimes;
             pre-processing:$(kron_times[1]) contraction op:$(t4[2])  ")

    #HOM_indices, HOM_vals = produce_HOM_tensor(source,target,m,tol=1e-5)
    #HOM_marg_ten = Matrix(sym_mode1_marginalization(HOM_indices,HOM_vals,n*m))
    #t3 = @timed HOM_marg_ten*x
    #t3 = t3[2]
    #println("HOM ran in time $t3")

  #  return Matrix(reshape(implicit_marg_kron_y,m,n)'), Y

    diff1 = norm(Y1 - Y2)/norm(Y2)
    println(diff1)
    @assert diff1 < ERROR_TOL

    diff2 = norm(Matrix(reshape(implicit_marg_kron_y,m,n)') - Y2)/norm(Y2)
    println(diff2)
    @assert diff2 < ERROR_TOL

    diff3 = norm(Matrix(reshape(explicit_marg_kron_y,m,n)') - Y2)/norm(Y2)
    println(diff3)
    @assert diff3 < ERROR_TOL
    println("performance ratio impli:new = $(t3[2]/t2[2])")

end

function brute_force_tensor(H_indices,B_indices,B_vals,n,m)

    e1 = size(H_indices,1)
    e2 = size(B_indices,1)

    final_indices = Array{Int,2}(undef,e1*e2,3)
    final_vals = Array{Float64,1}(undef,e1*e2)

    index = 1
    for (i1,i2,i3) in eachrow(H_indices)
        for ((j1,j2,j3),v) in zip(eachrow(B_indices),B_vals)
            final_indices[index,1] = (i1-1)*m + j1
            final_indices[index,2] = (i2-1)*m + j2
            final_indices[index,3] = (i3-1)*m + j3
            final_vals[index] = v
            index += 1
        end
    end

    return final_indices, final_vals
end

function HOFASM_mode1_marg(H_indices::Array{Array{Int64,2},1},B_indices::Array{Array{Int64,2},1},
                            B_vals::Array{Array{Float64,1},1},m::Int,n::Int)

        return sum([sum(
                [numpy_kron(HOFASM.perm_mode1_marginalization(H_idx,ones(size(H_idx,1)),p,n),
                            HOFASM.perm_mode1_marginalization(B_idx,v,p,m)
                            )
                            for p in permutations((1,2,3))
                ]) for (H_idx,B_idx,v) in zip(H_indices,B_indices,B_vals)])
end


text:
mutable struct MutualInfo{D,E} <: InfoDist
    joint::Matrix{Int}
    m1::Vector{Int}
    m2::Vector{Int}
    b1::NTuple{D,Int}
    b2::NTuple{E,Int}
    N::Int
    lag::Int
    function MutualInfo(b1::NTuple{D, <:Integer}, b2::NTuple{E, <:Integer}; lag::Int=0) where {D, E}
        if D == 0 || E == 0
            throw(MethodError(MutualInfo, (b1, b2)))
        end
        if any(b -> b < 2, b1) || any(b -> b < 2, b2)
            throw(ArgumentError("the support of each random variable must be at least 2"))
        end
        B1, B2 = prod(b1), prod(b2)
        new{D,E}(zeros(Int, B1, B2), zeros(Int, B1), zeros(Int, B2), b1, b2, 0, lag)
    end
end
MutualInfo(b1::Integer, b2::Integer; kwargs...) = MutualInfo((b1,), (b2,))
MutualInfo(b1::Integer, b2::NTuple; kwargs...) = MutualInfo((b1,), b2)
MutualInfo(b1::NTuple, b2::Integer; kwargs...) = MutualInfo(b1, (b2,))

function MutualInfo(xs::AbstractArray{Int,3}, ys::AbstractArray{Int,3}; kwargs...)
    if isempty(xs) || isempty(ys)
        throw(ArgumentError("arguments must not be empty"))
    end
    xmax = max.(2, maximum(xs; dims=(2,3)))
    ymax = max.(2, maximum(ys; dims=(2,3)))
    observe!(MutualInfo(tuple(xmax...), tuple(ymax...); kwargs...), xs, ys)
end

function MutualInfo(xs::AbstractArray{Int,2}, ys::AbstractArray{Int,2}; kwargs...)
    if isempty(xs) || isempty(ys)
        throw(ArgumentError("arguments must not be empty"))
    end
    xmax = max.(2, maximum(xs; dims=2))
    ymax = max.(2, maximum(ys; dims=2))
    observe!(MutualInfo(tuple(xmax...), tuple(ymax...); kwargs...), xs, ys)
end

function MutualInfo(xs::AbstractArray{Int,1}, ys::AbstractArray{Int,1}; kwargs...)
    if isempty(xs) || isempty(ys)
        throw(ArgumentError("arguments must not be empty"))
    end
    xmax = max(2, maximum(xs))
    ymax = max(2, maximum(ys))
    observe!(MutualInfo(tuple(xmax...), tuple(ymax...); kwargs...), xs, ys)
end

function estimate(dist::MutualInfo)
    entropy(dist.m1, dist.N) + entropy(dist.m2, dist.N) - entropy(dist.joint, dist.N)
end

function observe!(dist::MutualInfo, xs::AbstractArray{Int,3}, ys::AbstractArray{Int,3})
    if size(xs, 3) != size(ys, 3)
        throw(ArgumentError("time series should have the same number of replicates"))
    end

    @views for i in 1:size(xs, 3)
        observe!(dist, xs[:,:,i], ys[:,:,i])
    end

    dist
end

function observe!(dist::MutualInfo, xs::AbstractArray{Int,2}, ys::AbstractArray{Int,2})
    if size(xs, 2) != size(ys, 2)
        throw(ArgumentError("time series should have the same number of timesteps"))
    elseif any(b -> b < 1, xs) || any(b -> b < 1, ys)
        throw(ArgumentError("observations must be positive, nonzero"))
    end

    N = size(xs, 2) - abs(dist.lag)

    dist.N += N
    @views for t in 1:N
        x, y = if dist.lag < zero(dist.lag)
            index(xs[:,t-dist.lag], dist.b1), index(ys[:,t], dist.b2)
        else
            index(xs[:,t], dist.b1), index(ys[:,t+dist.lag], dist.b2)
        end
        dist.m1[x] += 1
        dist.m2[y] += 1
        dist.joint[x, y] += 1
    end
    dist
end

function observe!(dist::MutualInfo, xs::AbstractArray{Int,1}, ys::AbstractArray{Int,1})
    if length(xs) != length(ys)
        throw(ArgumentError("time series should have the same number of timesteps"))
    elseif any(b -> b < 1, xs) || any(b -> b < 1, ys)
        throw(ArgumentError("observations must be positive, nonzero"))
    end

    N = length(xs) - abs(dist.lag)

    dist.N += N
    @views for t in 1:N
        x, y = if dist.lag < zero(dist.lag)
            xs[t-dist.lag], ys[t]
        else
            xs[t], ys[t+dist.lag]
        end
        dist.m1[x] += 1
        dist.m2[y] += 1
        dist.joint[x, y] += 1
    end
    dist
end

@inline function clear!(dist::MutualInfo)
    dist.joint[:] .= 0
    dist.m1[:] .= 0
    dist.m2[:] .= 0
    dist.N = 0
    dist
end

function mutualinfo!(dist::MutualInfo, xs::AbstractArray{Int}, ys::AbstractArray{Int}; kwargs...)
    estimate(observe!(dist, xs, ys, kwargs...))
end

function mutualinfo(xs::AbstractArray{Int}, ys::AbstractArray{Int}; kwargs...)
    estimate(MutualInfo(xs, ys; kwargs...))
end

function mutualinfo(::Type{Kraskov1}, xs::AbstractMatrix{Float64}, ys::AbstractMatrix{Float64};
                    nn::Int=1, metric::Metric=Chebyshev())
    data = [xs; ys]
    joint = BallTree(data, metric)
    m1 = BallTree(xs, metric)
    m2 = BallTree(ys, metric)
    mi = zero(Float64)
    N = size(data, 2)

    δs = prevfloat.(last.(last(knn(joint, data, nn + 1, true))))
    for i in 1:N
        nx = length(inrange(m1, xs[:, i], δs[i]))
        ny = length(inrange(m2, ys[:, i], δs[i]))
        mi += digamma(nx) + digamma(ny)
    end
    digamma(nn) - (mi/N) + digamma(N)
end

function mutualinfo(::Type{Kraskov1}, xs::AbstractMatrix{Float64}, ys::AbstractMatrix{Float64},
                    cond::AbstractMatrix{Float64}, conds::AbstractMatrix{Float64}...;
                    nn::Int=1, metric::Metric=Chebyshev())
    data = [xs; ys; cond; conds...]
    var1 = [xs; cond; conds...]
    var2 = [ys; cond; conds...]
    varcond = [cond; conds...]

    joint = BallTree(data, metric)
    m1 = BallTree(var1, metric)
    m2 = BallTree(var2, metric)
    mcond = BallTree(varcond, metric)

    mi = zero(Float64)
    N = size(data, 2)

    δs = prevfloat.(last.(last(knn(joint, data, nn + 1, true))))
    for i in 1:N
        n1 = length(inrange(m1, var1[:, i], δs[i]))
        n2 = length(inrange(m2, var2[:, i], δs[i]))
        ncond = length(inrange(mcond, varcond[:, i], δs[i]))
        mi += digamma(ncond) - digamma(n1) - digamma(n2)
    end
    digamma(nn) + (mi/N)
end

function mutualinfo(::Type{Kraskov}, xs::AbstractMatrix{Float64}, ys::AbstractMatrix{Float64},
                    cond::AbstractMatrix{Float64}...; kwargs...)
    mutualinfo(Kraskov1, xs, ys, cond...; kwargs...)
end

function mutualinfo(xs::AbstractMatrix{Float64}, ys::AbstractMatrix{Float64},
                    cond::AbstractMatrix{Float64}...; kwargs...)
    mutualinfo(Kraskov1, xs, ys, cond...; kwargs...)
end

function mutualinfo(xs::AbstractVector{Float64}, ys::AbstractVector{Float64},
                    cond::AbstractVector{Float64}...; kwargs...)
    conds = map(c -> reshape(c, 1, length(c)), cond)
    mutualinfo(reshape(xs, 1, length(xs)), reshape(ys, 1, length(ys)), conds...; kwargs...)
end

ext: jl


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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el)
        el
    end
end

# ╔═╡ 866f4346-58fa-11ec-2d52-1fe8cc15ffbd
begin
    import Pkg
    # activate the shared project environment
    Pkg.activate(Base.current_project())
    # instantiate, i.e. make sure that all packages are downloaded
    Pkg.instantiate()

    using Plots, PlutoUI
	using Distributions, DataFrames
	using StanSample, StatisticalRethinking
end

# ╔═╡ f2224d36-7972-4e21-badc-3a401bf6f0bb
pwd()

# ╔═╡ 7d6d3864-3bff-414d-b077-ab59673f6d25
@__DIR__

# ╔═╡ 19f434b6-7f8c-40ff-a7ca-81dd0d6da884
md"##### Output will go to Terminal."

# ╔═╡ 19067711-ea26-47e7-901d-73df2640473b
Pkg.pkg"status"

# ╔═╡ 387e6736-a14f-46a9-accf-d21b046c0018
stan0_0 = "
data {
	int N;
	vector[N] D;
}
parameters {
	real a;
	real sigma;
}
model {
	a ~ normal(0, 2);
	sigma ~ exponential(1);
	D ~ normal(a, sigma);
}";

# ╔═╡ 6fe593b5-ac1e-484b-8ac5-779ff9499a1b
md"##### Slider variable `n` can go from 1:4"

# ╔═╡ bf6f4061-3ed4-4ab1-a315-38f2162ec74a
@bind k Slider(0:5, default=2)

# ╔═╡ 0b98128b-4826-4ac0-857e-a344be5218dc
data = (N=10^k, D=rand(Normal(0,1), 10^k));

# ╔═╡ 47d35d33-353c-443e-b24f-98eab9a0ca44
data.N

# ╔═╡ d943cc63-e0c1-4699-a4a1-ebf5320113a5
begin
	m0_0s = SampleModel("m0_0s", stan0_0)
	rc0_0s = stan_sample(m0_0s; data)
end;

# ╔═╡ 30e22695-bad8-4452-8f41-bd95e8792c87
if success(rc0_0s)
	df0_0s = read_samples(m0_0s, :dataframe)
	PRECIS(df0_0s)
end

# ╔═╡ Cell order:
# ╠═f2224d36-7972-4e21-badc-3a401bf6f0bb
# ╠═7d6d3864-3bff-414d-b077-ab59673f6d25
# ╠═866f4346-58fa-11ec-2d52-1fe8cc15ffbd
# ╟─19f434b6-7f8c-40ff-a7ca-81dd0d6da884
# ╠═19067711-ea26-47e7-901d-73df2640473b
# ╠═387e6736-a14f-46a9-accf-d21b046c0018
# ╟─6fe593b5-ac1e-484b-8ac5-779ff9499a1b
# ╠═bf6f4061-3ed4-4ab1-a315-38f2162ec74a
# ╠═0b98128b-4826-4ac0-857e-a344be5218dc
# ╠═47d35d33-353c-443e-b24f-98eab9a0ca44
# ╠═d943cc63-e0c1-4699-a4a1-ebf5320113a5
# ╠═30e22695-bad8-4452-8f41-bd95e8792c87


text:
#Simple Proof of concept
using WAV
minuet=[
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 96, 22, 141, 41, 105, 122, 11, 30, 70, 121, 26, 9, 112, 49, 109, 14],
        [0, 32, 6, 128, 63, 146, 46, 134, 81, 117, 39, 126, 56, 174, 18, 116, 83],
        [0, 69, 95, 158, 13, 153, 55, 110, 24, 66, 139, 15, 132, 73, 58, 145, 79],
        [0, 40, 17, 113, 85, 161, 2 ,159, 100, 90, 176, 7, 4, 67, 160, 52, 170],
        [0, 148, 74, 163, 45, 80, 97, 36, 107, 25, 143, 64, 125, 76, 136, 1, 93],
        [0, 104, 157, 27, 167, 154, 68, 118, 91, 138, 71, 150, 29, 101, 162, 23, 151],
        [0, 152, 60, 171, 53, 99, 133, 21, 127, 16, 155, 57, 175, 43, 168, 89, 172],
        [0, 119, 84, 114, 50, 140, 86, 169, 94, 120, 88, 48, 166, 51, 115, 72, 111],
        [0, 98, 142, 42, 156, 75, 129, 62, 123, 65, 77, 19, 82, 137, 38, 149, 8],
        [0, 3, 87, 165, 61, 135, 47, 147, 33, 102, 4, 31, 164, 44, 59, 173, 78],
        [0, 54, 130, 10, 103, 28, 37, 106, 5, 35, 20, 108, 92, 12, 124, 44, 131]];

trio=[
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 72, 6, 59, 25, 81, 41, 89, 13, 36, 5, 46, 79, 30, 95, 19, 66],
        [0, 56, 82, 42, 74, 14, 7, 26, 71, 76, 20, 64, 84, 8, 35, 47, 88],
        [0, 75, 39, 54, 1, 65, 43, 15, 80, 9, 34, 93, 48, 69, 58, 90, 21],
        [0, 40, 73, 16, 68, 29, 55, 2, 61, 22, 67, 49, 77, 57, 87, 33, 10],
        [0, 83, 3, 28, 53, 37, 17, 44, 70, 63, 85, 32, 96, 12, 23, 50, 91],
        [0, 18, 45, 62, 38, 4, 27, 52, 94, 11, 92, 24, 86, 51, 60, 78, 31]
    ];

println("Minuet:\n",minuet,"\n")
println("Trio:\n",trio,"\n")
val=minuet[1,1]
val2=string("")
for i in 2:16
	global val=minuet[1,1]
	global val2=string("")
	global val=minuet[rand(2:11)][i]
	global val2=string("mozart/M",val,".wav")
	global y, fs = wavread(val2)
	wavplay(y,fs)
end
#trio part
for i in 2:16
	global val=trio[1,1],val2=""
	global val=trio[rand(2:7)][i]
	global val2=string("mozart/T",val,".wav")
	global y, fs = wavread(val2)
	wavplay(y,fs)
end
#Minuet,Dacapo #Need to store the string from
#above case in list or something of similiar kind
for i in 2:16
	global val=minuet[1,1],val2=""
	global val=minuet[rand(2:11)][i]
	global val2=string("mozart/M",val,".wav")
	global y, fs = wavread(val2)
	wavplay(y,fs)
end
#val=minuet[rand(1:10)][rand(1:10)]
#val2=string("mozart/M",val,".wav")
#println(val2)
#y, fs = wavread(val2)
#wavplay(y,fs)


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

using Markdown
using InteractiveUtils

# ╔═╡ 2065e50f-1bba-4182-ae16-70feecaa1942
using PoreMatMod

# ╔═╡ 5e702404-3665-411e-a4d2-cb7fba303c91
using PoreMatMod.ExampleHelpers

# ╔═╡ 52318187-a575-4864-8185-416faeea27ab
begin
	rc[:paths][:crystals] = realpath(joinpath(pwd(), "..", "test", "data", "crystals"))
	rc[:paths][:moieties] = realpath(joinpath(pwd(), "..", "test", "data", "moieties"))
end

# ╔═╡ 6922e27b-b848-418b-bf1a-df17315baa80
begin
	parent = replicate(Crystal("diamond.cif", remove_duplicates=true), (2,2,1))
	strip_numbers_from_atom_labels!(parent)
	infer_bonds!(parent, true)
end

# ╔═╡ 418a7421-92ed-406f-9578-34187529c307
write_cif(parent, "diamond_cell.cif")

# ╔═╡ f7d3cb8c-9d12-4f78-94c6-30a308648e69
view_structure(parent)

# ╔═╡ 90f53a39-89b3-41c5-ad8b-c0683b96c9e4
query = moiety("adamantane_C5.xyz")

# ╔═╡ 58b79260-8a7a-4ca4-bdee-4c3c463334ba
replacement = moiety("nitrogen_vacancy.xyz")

# ╔═╡ b835a642-0a24-4796-8e01-e3c4041a6bff
child = replace(parent, query => replacement, loc=[8])

# ╔═╡ 3c003a65-3983-42ed-b445-5618ae21a4a3
write_cif(child, "child.cif")

# ╔═╡ caf947dc-11bd-455d-8fd6-434fa52edada
view_structure(child)

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Bio3DView = "99c8bb3a-9d13-5280-9740-b4880ed9c598"
PoreMatMod = "2de0d7f0-0963-4438-8bc8-7e7ffe3dc69a"

[compat]
Bio3DView = "~0.1.3"
PoreMatMod = "~0.2.7"
"""

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

[[ANSIColoredPrinters]]
git-tree-sha1 = "574baf8110975760d391c710b6341da1afa48d8c"
uuid = "a4c015fc-c6ff-483c-b24f-f7ea428134e9"
version = "0.0.1"

[[AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "abb72771fd8895a7ebd83d5632dc4b989b022b5b"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.1.2"

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

[[ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.2.0"

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

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

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

[[Bio3DView]]
deps = ["Requires"]
git-tree-sha1 = "7f472efd9b6af772307dd017f9deeff2a243754f"
uuid = "99c8bb3a-9d13-5280-9740-b4880ed9c598"
version = "0.1.3"

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

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

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

[[ChangesOfVariables]]
deps = ["LinearAlgebra", "Test"]
git-tree-sha1 = "9a1d594397670492219635b35a3d830b04730d62"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.1"

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

[[Conda]]
deps = ["Downloads", "JSON", "VersionParsing"]
git-tree-sha1 = "6cdc8832ba11c7695f494c9d9a1c31e90959ce0f"
uuid = "8f4d0f93-b110-5947-807f-2305c1781a2d"
version = "1.6.0"

[[Configurations]]
deps = ["ExproniconLite", "OrderedCollections", "TOML"]
git-tree-sha1 = "79e812c535bb9780ba00f3acba526bde5652eb13"
uuid = "5218b696-f38b-4ac9-8b61-a12ec717816d"
version = "0.16.6"

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

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

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

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

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

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

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

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

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

[[Documenter]]
deps = ["ANSIColoredPrinters", "Base64", "Dates", "DocStringExtensions", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "REPL", "Test", "Unicode"]
git-tree-sha1 = "f425293f7e0acaf9144de6d731772de156676233"
uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
version = "0.27.10"

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

[[ExproniconLite]]
git-tree-sha1 = "8b08cc88844e4d01db5a2405a08e9178e19e479e"
uuid = "55351af7-c7e9-48d6-89ff-24e801d99491"
version = "0.6.13"

[[FIGlet]]
deps = ["BinaryProvider", "Pkg"]
git-tree-sha1 = "bfc6b52f75b4720581e3e49ae786da6764e65b6a"
uuid = "3064a664-84fe-4d92-92c7-ed492f3d8fae"
version = "0.2.1"

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

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

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

[[FromFile]]
git-tree-sha1 = "81e918d0ed5978fcdacd06b7c64c0c5074c4d55a"
uuid = "ff7dd447-1dcb-4ce3-b8ac-22a812192de7"
version = "0.1.2"

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

[[FuzzyCompletions]]
deps = ["REPL"]
git-tree-sha1 = "2cc2791b324e8ed387a91d7226d17be754e9de61"
uuid = "fb4132e2-a121-4a70-b8a1-d5b831dcdcc2"
version = "0.4.3"

[[GitHubActions]]
deps = ["JSON", "Logging"]
git-tree-sha1 = "56e01ec63d13e1cf015d9ff586156eae3cc7cd6f"
uuid = "6b79fd1a-b13a-48ab-b6b0-aaee1fee41df"
version = "0.1.4"

[[Graphs]]
deps = ["ArnoldiMethod", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "92243c07e786ea3458532e199eb3feee0e7e08eb"
uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
version = "1.4.1"

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

[[Hyperscript]]
deps = ["Test"]
git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9"
uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
version = "0.0.4"

[[HypertextLiteral]]
git-tree-sha1 = "2b078b5a615c6c0396c77810d92ee8c6f470d238"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.3"

[[IOCapture]]
deps = ["Logging", "Random"]
git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a"
uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
version = "0.2.2"

[[Inflate]]
git-tree-sha1 = "f5fc07d4e706b84f72d54eedcc1c13d92fb0871c"
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
version = "0.1.2"

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

[[InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.2"

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

[[IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

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

[[JLD2]]
deps = ["DataStructures", "FileIO", "MacroTools", "Mmap", "Pkg", "Printf", "Reexport", "TranscodingStreams", "UUIDs"]
git-tree-sha1 = "46b7834ec8165c541b0b5d1c8ba63ec940723ffb"
uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
version = "0.4.15"

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

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

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

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

[[LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "be9eef9f9d78cecb6f262f3c10da151a6c5ab827"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.5"

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

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

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

[[MetaGraphs]]
deps = ["Graphs", "JLD2", "Random"]
git-tree-sha1 = "2af69ff3c024d13bde52b34a2a7d6887d4e7b438"
uuid = "626554b9-1ddb-594c-aa3c-2596fe9399a5"
version = "0.7.1"

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

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

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

[[MsgPack]]
deps = ["Serialization"]
git-tree-sha1 = "a8cbf066b54d793b9a48c5daa5d586cf2b5bd43d"
uuid = "99f44e22-a591-53d1-9472-aa23ef4bd671"
version = "1.1.0"

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

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

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

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

[[Pluto]]
deps = ["Base64", "Configurations", "Dates", "Distributed", "FileWatching", "FuzzyCompletions", "HTTP", "InteractiveUtils", "Logging", "Markdown", "MsgPack", "Pkg", "REPL", "Sockets", "TableIOInterface", "Tables", "UUIDs"]
git-tree-sha1 = "669c67f837da26719ff9102cd9b193e0d2114472"
uuid = "c3e4b0f8-55cb-11ea-2926-15256bba5781"
version = "0.17.3"

[[PlutoSliderServer]]
deps = ["Base64", "Configurations", "Distributed", "FromFile", "GitHubActions", "HTTP", "Logging", "Pkg", "Pluto", "SHA", "Sockets", "TOML", "UUIDs"]
git-tree-sha1 = "ed9660bb2c9eee9d389601bd80a10cee3dd64f0b"
uuid = "2fc8631c-6f24-4c5b-bca7-cbb509c42db4"
version = "0.2.7"

[[PlutoUI]]
deps = ["AbstractPlutoDingetjes", "Base64", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"]
git-tree-sha1 = "b68904528fd538f1cb6a3fbc44d2abdc498f9e8e"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.21"

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

[[PoreMatMod]]
deps = ["Bio3DView", "CSV", "DataFrames", "FIGlet", "Graphs", "LinearAlgebra", "MetaGraphs", "Pluto", "PlutoSliderServer", "PlutoUI", "Reexport", "StatsBase", "Xtals"]
git-tree-sha1 = "53bccf1b4a3c0b5e3c7d70cbc93a6bbda802edaa"
uuid = "2de0d7f0-0963-4438-8bc8-7e7ffe3dc69a"
version = "0.2.7"

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

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

[[PyCall]]
deps = ["Conda", "Dates", "Libdl", "LinearAlgebra", "MacroTools", "Serialization", "VersionParsing"]
git-tree-sha1 = "4ba3651d33ef76e24fef6a598b63ffd1c5e1cd17"
uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
version = "1.92.5"

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

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

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

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

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

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

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

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

[[SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"

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

[[SortingAlgorithms]]
deps = ["DataStructures", "Random", "Test"]
git-tree-sha1 = "03f5898c9959f8115e30bc7226ada7d0df554ddd"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "0.3.1"

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

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

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

[[StatsAPI]]
git-tree-sha1 = "0f2aa8e32d511f758a2ce49208181f7733a0936a"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.1.0"

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

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

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

[[TableIOInterface]]
git-tree-sha1 = "9a0d3ab8afd14f33a35af7391491ff3104401a35"
uuid = "d1efa939-5518-4425-949f-ab857e148477"
version = "0.1.6"

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

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

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

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

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

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

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

[[VersionParsing]]
git-tree-sha1 = "e575cf85535c7c3292b4d89d89cc29e8c3098e47"
uuid = "81def892-9a0e-5fdd-b105-ffc91e053289"
version = "1.2.1"

[[Xtals]]
deps = ["Bio3DView", "CSV", "DataFrames", "Documenter", "FIGlet", "Graphs", "JLD2", "LinearAlgebra", "Logging", "MetaGraphs", "Printf", "PyCall", "UUIDs"]
git-tree-sha1 = "3147503cd35c4f2b3744fe36301c7de3efee98c5"
uuid = "ede5f01d-793e-4c47-9885-c447d1f18d6d"
version = "0.3.9"

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

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

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

# ╔═╡ Cell order:
# ╠═2065e50f-1bba-4182-ae16-70feecaa1942
# ╠═5e702404-3665-411e-a4d2-cb7fba303c91
# ╠═52318187-a575-4864-8185-416faeea27ab
# ╠═6922e27b-b848-418b-bf1a-df17315baa80
# ╠═418a7421-92ed-406f-9578-34187529c307
# ╠═f7d3cb8c-9d12-4f78-94c6-30a308648e69
# ╠═90f53a39-89b3-41c5-ad8b-c0683b96c9e4
# ╠═58b79260-8a7a-4ca4-bdee-4c3c463334ba
# ╠═b835a642-0a24-4796-8e01-e3c4041a6bff
# ╠═3c003a65-3983-42ed-b445-5618ae21a4a3
# ╠═caf947dc-11bd-455d-8fd6-434fa52edada
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
gamma(x::Float64) = nan_dom_err(ccall((:tgamma,libm),  Float64, (Float64,), x), x)
gamma(x::Float32) = nan_dom_err(ccall((:tgammaf,libm),  Float32, (Float32,), x), x)
gamma(x::Real) = gamma(float(x))
@vectorize_1arg Number gamma

function lgamma_r(x::Float64)
    signp = Array(Int32, 1)
    y = ccall((:lgamma_r,libm),  Float64, (Float64, Ptr{Int32}), x, signp)
    return y, signp[1]
end
function lgamma_r(x::Float32)
    signp = Array(Int32, 1)
    y = ccall((:lgammaf_r,libm),  Float32, (Float32, Ptr{Int32}), x, signp)
    return y, signp[1]
end
lgamma_r(x::Real) = lgamma_r(float(x))

lfact(x::Real) = (x<=1 ? zero(float(x)) : lgamma(x+one(x)))
@vectorize_1arg Number lfact

const clg_coeff = [76.18009172947146,
                   -86.50532032941677,
                   24.01409824083091,
                   -1.231739572450155,
                   0.1208650973866179e-2,
                   -0.5395239384953e-5]

function clgamma_lanczos(z)
    const sqrt2pi = 2.5066282746310005

    y = x = z
    temp = x + 5.5
    zz = log(temp)
    zz = zz * (x+0.5)
    temp -= zz
    ser = complex(1.000000000190015, 0)
    for j=1:6
        y += 1.0
        zz = clg_coeff[j]/y
        ser += zz
    end
    zz = sqrt2pi*ser / x
    return log(zz) - temp
end

function lgamma(z::Complex)
    if real(z) <= 0.5
        a = clgamma_lanczos(1-z)
        b = log(sinpi(z))
        const logpi = 1.14472988584940017
        z = logpi - b - a
    else
        z = clgamma_lanczos(z)
    end
    complex(real(z), angle_restrict_symm(imag(z)))
end

gamma(z::Complex) = exp(lgamma(z))

# Derivatives of the digamma function
function psifn(x::Float64, n::Int, kode::Int, m::Int)
# Translated from http://www.netlib.org/slatec/src/dpsifn.f
# Note: Underflow handling at 380 in original is skipped
    const nmax = 100
    ans = Array(Float64, m)
#-----------------------------------------------------------------------
#             bernoulli numbers
#-----------------------------------------------------------------------
    const b =                         [1.00000000000000000e+00,
              -5.00000000000000000e-01,1.66666666666666667e-01,
              -3.33333333333333333e-02,2.38095238095238095e-02,
              -3.33333333333333333e-02,7.57575757575757576e-02,
              -2.53113553113553114e-01,1.16666666666666667e+00,
              -7.09215686274509804e+00,5.49711779448621554e+01,
              -5.29124242424242424e+02,6.19212318840579710e+03,
              -8.65802531135531136e+04,1.42551716666666667e+06,
              -2.72982310678160920e+07,6.01580873900642368e+08,
              -1.51163157670921569e+10,4.29614643061166667e+11,
              -1.37116552050883328e+13,4.88332318973593167e+14,
              -1.92965793419400681e+16]
    trm = Array(Float64, 22)
    trmr = Array(Float64, 100)
#***first executable statement  dpsifn
    if x <= 0.0 throw(DomainError()) end
    if n < 0 error("n must be non-negative") end
    if kode < 1 | kode > 2 error("kode must be one or two") end
    if m < 1 error("m must be larger than one") end
    mm = m
    const nx = min(-exponent(realmin(Float64)) + 1, exponent(realmax(Float64)))
    const r1m5 = log10(2)
    const r1m4 = Base.eps(Float64) * 0.5
    const wdtol = max(r1m4, 0.5e-18)
#-----------------------------------------------------------------------
#     elim = approximate exponential over and underflow limit
#-----------------------------------------------------------------------
    const elim = 2.302*(nx*r1m5 - 3.0)
    xln = log(x)
    nn = n + mm - 1
    fn = nn
    t = (fn + 1)*xln
#-----------------------------------------------------------------------
#     overflow and underflow test for small and large x
#-----------------------------------------------------------------------
    if abs(t) > elim
        if t <= 0.0 error("n too large") end
        error("overflow; x too small or n+m-1 too large or both")
    end
    if x < wdtol
        ans[1] = x^(-n - 1)
        if mm != 1
            k = 1
            for i = 2:mm
                ans[k + 1] = ans[k]/x
                k += 1
            end
        end
        if n != 0 return ans end
        if kode == 2 ans[1] = ans[1] + xln end
        return ans
    end
#-----------------------------------------------------------------------
#     compute xmin and the number of terms of the series, fln+1
#-----------------------------------------------------------------------
    rln = r1m5 * precision(x)
    rln = min(rln, 18.06)
    fln = max(rln, 3.0) - 3.0
    yint = 3.50 + 0.40*fln
    slope = 0.21 + fln*(0.0006038*fln + 0.008677)
    xm = yint + slope*fn
    mx = itrunc(xm) + 1
    xmin = mx
    if n != 0
        xm = -2.302*rln - min(0.0,xln)
        arg = xm/n
        arg = min(0.0,arg)
        eps = exp(arg)
        xm = 1.0 - eps
        if abs(arg) < 1.0e-3 xm = -arg end
        fln = x*xm/eps
        xm = xmin - x
        if (xm > 7.0) & (fln < 15.0)
            nn = itrunc(fln) + 1
            np = n + 1
            t1 = (n + 1)*xln
            t = exp(-t1)
            s = t
            den = x
            for i = 1:nn
                den += 1.0
                trm[i] = den^(-np)
                s += trm[i]
            end
            ans[1] = s
            if n == 0
                if kode == 2 ans[1] = s + xln end
            end
            if mm == 1 return ans end
#-----------------------------------------------------------------------
#     generate higher derivatives, j.gt.n
#-----------------------------------------------------------------------
            tol = wdtol/5.0
            for j = 2:mm
                t = t/x
                s = t
                tols = t*tol
                den = x
                for i = 1:nn
                    den += 1.0
                    trm[i] = trm[i]/den
                    s += trm[i]
                    if trm[i] < tols break end
                end
                ans[j] = s
            end
            return ans
        end
    end

    xdmy = x
    xdmln = xln
    xinc = 0.0
    if x < xmin
        nx = itrunc(x)
        xinc = xmin - nx
        xdmy = x + xinc
        xdmln = log(xdmy)
    end
#-----------------------------------------------------------------------
#     generate w(n+mm-1,x) by the asymptotic expansion
#-----------------------------------------------------------------------
    t = fn*xdmln
    t1 = xdmln + xdmln
    t2 = t + xdmln
    tk = max(abs(t), abs(t1), abs(t2))
    if tk > elim error("underflow") end
    tss = exp(-t)
    tt = 0.5/xdmy
    t1 = tt
    tst = wdtol*tt
    if nn != 0 t1 = tt + 1.0/fn end
    rxsq = 1.0/(xdmy*xdmy)
    ta = 0.5*rxsq
    t = (fn + 1)*ta
    s = t*b[3]
    if abs(s) >= tst
        tk = 2.0
        for k = 4:22
            t = t*((tk + fn + 1)/(tk + 1.0))*((tk + fn)/(tk + 2.0))*rxsq
            trm[k] = t*b[k]
            if abs(trm[k]) < tst break end
            s += trm[k]
            tk += 2.0
        end
    end
    s = (s + t1)*tss
    while true
        if xinc != 0.0
#-----------------------------------------------------------------------
#     backward recur from xdmy to x
#-----------------------------------------------------------------------
            nx = itrunc(xinc)
            np = nn + 1
            if nx > nmax error("n too large") end
            if nn == 0 break end
            xm = xinc - 1.0
            fx = x + xm
#-----------------------------------------------------------------------
#     this loop should not be changed. fx is accurate when x is small
#-----------------------------------------------------------------------
            for i = 1:nx
                trmr[i] = fx^(-np)
                s += trmr[i]
                xm -= 1.0
                fx = x + xm
            end
        end
        ans[mm] = s
        if fn == 0
            if kode != 2
                ans[1] = s - xdmln
                return ans
            end
            if xdmy == x return ans end
            xq = xdmy/x
            ans[1] = s - log(xq)
            return ans
        end
#-----------------------------------------------------------------------
#     generate lower derivatives, j.lt.n+mm-1
#-----------------------------------------------------------------------
        if mm == 1 return ans end
        for j = 2:mm
            fn -= 1
            tss *= xdmy
            t1 = tt
            if fn != 0 t1 = tt + 1.0/fn end
            t = (fn + 1)*ta
            s = t*b[3]
            if abs(s) >= tst
                tk = 4 + fn
                for k = 4:22 #110
                    trm[k] = trm[k]*(fn + 1)/tk
                    if abs(trm[k]) < tst break end
                    s += trm[k]
                    tk += 2.0
                end
            end
            s = (s + t1)*tss
            if xinc != 0.0
                if fn == 0 break end
                xm = xinc - 1.0
                fx = x + xm
                for i = 1:nx
                    trmr[i] = trmr[i]*fx
                    s += trmr[i]
                    xm -= 1.0
                    fx = x + xm
                end
            end
            mx = mm - j + 1
            ans[mx] = s
            if fn == 0
                if kode != 2
                    ans[1] = s - xdmln
                    return ans
                end
                if xdmy == x return ans end
                xq = xdmy/x
                ans[1] = s - log(xq)
                return ans
            end
        end
        if fn == 0 break end
        return ans
    end
#-----------------------------------------------------------------------
#     recursion for n = 0
#-----------------------------------------------------------------------
    for i = 1:nx
        s += 1.0/(x + nx - i)
    end
    if kode != 2
        ans[1] = s - xdmln
        return ans
    end
    if xdmy == x return ans end
    xq = xdmy/x
    ans[1] = s - log(xq)
    return ans
end
polygamma(k::Int, x::Float64) = (2rem(k,2) - 1)*psifn(x, k, 1, 1)[1]*gamma(k + 1)
polygamma(k::Int, x::Float32) = float32(polygamma(k, float64(x)))
polygamma(k::Int, x::Real) = polygamma(k, float64(x))

# Translation of psi.c from cephes
function digamma(x::Float64)
    negative = false
    nz = 0.0

    if x <= 0.0
        negative = true
        q = x
        p = floor(q)
        if p == q
            return NaN
        end

        nz = q - p
        if nz != 0.5
            if nz > 0.5
                p += 1.0
                nz = q - p
            end
            nz = pi / tan(pi * nz)
        else
            nz = 0.0
        end
        x = 1.0 - x
    end

    if x <= 10.0 && x == floor(x)
        y = 0.0
        for i = 1:x-1
            y += 1.0 / i
        end
        y -= γ  # γ == -digamma(1) == 0.5772156649015328606065121;

        if negative
            y -= nz
        end
        return y
    end

    w = 0.0
    while x < 10.0
        w += 1.0 / x
        x += 1.0
    end

    if x < 1.0e17
        z = 1.0 / (x*x)
        y = @horner(z, 8.33333333333333333333e-2, -8.33333333333333333333e-3, 3.96825396825396825397e-3,
                       -4.16666666666666666667e-3, 7.57575757575757575758e-3,-2.10927960927960927961e-2,
                       8.33333333333333333333e-2)
        y *= z
    else
        y = 0.0
    end

    y = log(x) - 0.5/x - y - w

    if negative
        y -= nz
    end

    return y
end
digamma(x::Float32) = float32(digamma(float64(x)))
digamma(x::Real) = digamma(float64(x))
@vectorize_1arg Real digamma

trigamma(x::Real) = polygamma(1, x)
@vectorize_1arg Real trigamma

# Inverse digamma function
#
# Implementation of fixed point algorithm described in
#  "Estimating a Dirichlet distribution" by Thomas P. Minka, 2000
function invdigamma(y::Float64)
    # Closed form initial estimates
    if y >= -2.22
        x_old = exp(y) + 0.5
        x_new = x_old
    else
        x_old = -1.0 / (y - digamma(1.0))
        x_new = x_old
    end

    # Fixed point algorithm
    delta = Inf
    iteration = 0
    while delta > 1e-12 && iteration < 25
        iteration += 1
        x_new = x_old - (digamma(x_old) - y) / trigamma(x_old)
        delta = abs(x_new - x_old)
        x_old = x_new
    end

    return x_new
end
invdigamma(x::Float32) = float32(invdigamma(float64(x)))
invdigamma(x::Real) = invdigamma(float64(x))
@vectorize_1arg Real invdigamma

function beta(x::Number, w::Number)
    yx, sx = lgamma_r(x)
    yw, sw = lgamma_r(w)
    yxw, sxw = lgamma_r(x+w)
    return copysign(exp(yx + yw - yxw), sx*sw*sxw)
end
lbeta(x::Number, w::Number) = lgamma(x)+lgamma(w)-lgamma(x+w)
@vectorize_2arg Number beta
@vectorize_2arg Number lbeta

const eta_coeffs =
    [.99999999999999999997,
     -.99999999999999999821,
     .99999999999999994183,
     -.99999999999999875788,
     .99999999999998040668,
     -.99999999999975652196,
     .99999999999751767484,
     -.99999999997864739190,
     .99999999984183784058,
     -.99999999897537734890,
     .99999999412319859549,
     -.99999996986230482845,
     .99999986068828287678,
     -.99999941559419338151,
     .99999776238757525623,
     -.99999214148507363026,
     .99997457616475604912,
     -.99992394671207596228,
     .99978893483826239739,
     -.99945495809777621055,
     .99868681159465798081,
     -.99704078337369034566,
     .99374872693175507536,
     -.98759401271422391785,
     .97682326283354439220,
     -.95915923302922997013,
     .93198380256105393618,
     -.89273040299591077603,
     .83945793215750220154,
     -.77148960729470505477,
     .68992761745934847866,
     -.59784149990330073143,
     .50000000000000000000,
     -.40215850009669926857,
     .31007238254065152134,
     -.22851039270529494523,
     .16054206784249779846,
     -.10726959700408922397,
     .68016197438946063823e-1,
     -.40840766970770029873e-1,
     .23176737166455607805e-1,
     -.12405987285776082154e-1,
     .62512730682449246388e-2,
     -.29592166263096543401e-2,
     .13131884053420191908e-2,
     -.54504190222378945440e-3,
     .21106516173760261250e-3,
     -.76053287924037718971e-4,
     .25423835243950883896e-4,
     -.78585149263697370338e-5,
     .22376124247437700378e-5,
     -.58440580661848562719e-6,
     .13931171712321674741e-6,
     -.30137695171547022183e-7,
     .58768014045093054654e-8,
     -.10246226511017621219e-8,
     .15816215942184366772e-9,
     -.21352608103961806529e-10,
     .24823251635643084345e-11,
     -.24347803504257137241e-12,
     .19593322190397666205e-13,
     -.12421162189080181548e-14,
     .58167446553847312884e-16,
     -.17889335846010823161e-17,
     .27105054312137610850e-19]

function eta(z::Union(Float64,Complex128))
    if z == 0
        return oftype(z, 0.5)
    end
    re, im = reim(z)
    if im==0 && re < 0 && re==round(re/2)*2
        return zero(z)
    end
    reflect = false
    if re < 0.5
        z = 1-z
        reflect = true
    end
    s = zero(z)
    for n = length(eta_coeffs):-1:1
        c = eta_coeffs[n]
        p = n^-z
        s += c * p
    end
    if reflect
        z2 = 2.0^z
        b = 2.0 - (2.0*z2)
        f = z2 - 2
        piz = pi^z

        b = b/f/piz

        return s * gamma(z) * b * cospi(z/2)
    end
    return s
end

eta(x::Integer) = eta(float64(x))
eta(x::Real)    = oftype(float(x),eta(float64(x)))
eta(z::Complex) = oftype(float(z),eta(complex128(z)))
@vectorize_1arg Number eta

function zeta(z::Number)
    zz = 2^z
    eta(z) * zz/(zz-2)
end
@vectorize_1arg Number zeta

max_stars_repo_name: vchuravy/julia

max_issues_repo_name: vchuravy/julia

max_forks_repo_name: vchuravy/julia


text:
PyType_CheckBuffer(t) = begin
    p = UnsafePtr{PyTypeObject}(t).as_buffer[]
    !isnull(p) && !isnull(p.get[!])
end

PyObject_CheckBuffer(o) = PyType_CheckBuffer(Py_Type(o))

PyObject_GetBuffer(o, b, flags) = begin
    p = UnsafePtr{PyTypeObject}(Py_Type(o)).as_buffer[]
    if isnull(p) || isnull(p.get[])
        PyErr_SetString(
            unsafe_load(Ptr{PyPtr}(pyglobal(:PyExc_TypeError))),
            "a bytes-like object is required, not '$(String(UnsafePtr{PyTypeObject}(Py_Type(o)).name[]))'",
        )
        return Cint(-1)
    end
    ccall(p.get[!], Cint, (PyPtr, Ptr{Py_buffer}, Cint), o, b, flags)
end

PyBuffer_Release(_b) = begin
    b = UnsafePtr(Base.unsafe_convert(Ptr{Py_buffer}, _b))
    o = b.obj[]
    isnull(o) && return
    p = UnsafePtr{PyTypeObject}(Py_Type(o)).as_buffer[]
    if (!isnull(p) && !isnull(p.release[]))
        ccall(p.release[!], Cvoid, (PyPtr, Ptr{Py_buffer}), o, b)
    end
    b.obj[] = C_NULL
    Py_DecRef(o)
    return
end


text:
using Plots, LaTeXStrings
pyplot()
# ..This just changes some defatuls for plots, everything works without also.. #
fontFamily = "Times"
default(size=(600,400), dpi=70, titlefont=(16, fontFamily),
    guidefont=(18, fontFamily), tickfont=(14, fontFamily),
    legendfont=(13, fontFamily), framestyle = :semi, grid = true)
# ...............................................................#
x= LinRange(0,2π,100)
plot(x, [sin.(x)], legend = :bottomleft, c = :black,
 label = L"sin(x)", xlab = L"x")
#save("pltSin.pdf")

max_stars_repo_name: lazarusA/helpfulJulia

max_issues_repo_name: lazarusA/helpfulJulia

max_forks_repo_name: lazarusA/helpfulJulia


text:
edges = (:DirectedEdge, :UndirectedEdge)
for e in edges
    @eval $e(src::VecOrMat, dst::VecOrMat) = vec([$e(l, r) for r in dst, l in src])
    @eval $e(src::Node, dst::VecOrMat) = vec(broadcast($e, (src,), dst))
    @eval $e(src::VecOrMat, dst::Node) = vec(broadcast($e, src, (dst, )))
end


text:
abstract IntersectionEvent
#####under developing
type AllWayStop <: IntersectionEvent
    connections::Array{Tuple{Int,Int}}
    entrances::Array{Int}
    exits::Array{Int}

    function AllWayStop()
        new(Tuple{Int,Int}[],Int[],Int[])
    end

    function AllWayStop(connections::Array{Tuple{Int,Int}})
        entrances = []
        exits = []
        for connection in connections
            if isempty(find(entrances .== connection[1]))
                push!(entrances,connection[1])
            end
            if isempty(find(exits .== connection[2]))
                push!(exits,connection[2])
            end
        end
        new(connections,entrances,exits)
    end
end

function updateAllWayStops!(driver::DriverModel,allwaystops::Array{AllWayStop})
    driver.allwaystops = allwaystops
    driver
end

function get_distance_to_stop(veh::Vehicle,allwaystop::AllWayStop,roadway::Roadway)
    vehSegid = veh.state.posF.roadind.tag.segment
    vehLaneid = veh.state.posF.roadind.tag.lane
    vehTag = veh.state.posF.roadind.tag
    distance_to_stop = -1.0
    if !isempty(find(allwaystop.entrances .== vehSegid))
        lane = roadway[vehTag]
        cindS = curveindex_end(lane.curve)
        endPoint = lane.curve[cindS]
        distance_to_stop = endPoint.s - veh.state.posF.s
    end
    return distance_to_stop
end

function stop_before(v::Float64,distance_to_stop::Float64,horizon::Float64=MAX_HORIZON,model::IDMDriver = IDMDriver())
    s_min = CAR_LENGTH/2

    s_gap = distance_to_stop
    acc = Inf
    if s_gap < horizon
        if s_gap > 0.0
            Δv = 0.0 - v
            s_des = s_min + v*model.T - v*Δv / (2*sqrt(model.a_max*model.d_cmf))
            v_ratio = model.v_des > 0.0 ? (v/model.v_des) : 1.0
            acc = model.a_max * (1.0 - v_ratio^model.δ - (s_des/s_gap)^2)
        elseif s_gap > -CAR_LENGTH
            acc = -model.d_max
        else
            Δv = model.v_des - v
            acc = Δv*model.k_spd
        end

        if isnan(acc)

            warn("IDM acceleration was NaN!")
            if s_gap > 0.0
                Δv = veh_target.state.v - v
                s_des = model.s_min + v*model.T - v*Δv / (2*sqrt(model.a_max*model.d_cmf))
                println("\tΔv: ", Δv)
                println("\ts_des: ", s_des)
                println("\tv_des: ", model.v_des)
                println("\tδ: ", model.δ)
                println("\ts_gap: ", s_gap)
            elseif s_gap > -veh_ego.def.length
                println("\td_max: ", model.d_max)
            end

            acc = 0.0
        end
    else
        # no lead vehicle, just drive to match desired speed
        Δv = model.v_des - v
        acc = Δv*model.k_spd # predicted accel to match target speed
    end
    acc = clamp(acc, -model.d_max, model.a_max)
    return acc
end

function update_waitlist!(driver, new::Bool,ego_distance::Float64,allwaystop::AllWayStop, scene::Scene, roadway::Roadway, egoid::Int)
    vehicle_index = findfirst(scene, egoid)
    ego_veh = scene[vehicle_index]
    if new #add veh
        empty!(driver.allwaystop_waitlist)
        for (i,veh) in enumerate(scene)
            dist = get_distance_to_stop(veh,allwaystop,roadway)
            if dist > 0.0 && dist < ego_distance
                push!(driver.allwaystop_waitlist,i)
            end
        end
    else #delete veh
        new_waitlist = []
        for veh_ind in driver.allwaystop_waitlist
            veh = scene.entities[veh_ind]
            vehSegid = veh.state.posF.roadind.tag.segment
            if isempty(find(allwaystop.exits .== vehSegid)) #this veh is still in waiting zone
                push!(new_waitlist,veh_ind)
            end
        end
        driver.allwaystop_waitlist = new_waitlist
    end
end

function reactAllWayStop!(driver, scene::Scene, roadway::Roadway, egoid::Int)
    vehicle_index = findfirst(scene, egoid)
    ego_veh = scene[vehicle_index]
    acc = Inf
    for i = 1:length(driver.allwaystops)
        distance_to_stop = get_distance_to_stop(ego_veh,driver.allwaystops[i],roadway)
        if distance_to_stop > 0.0 && distance_to_stop < driver.allwaystop_horizon
            allwaystop = driver.allwaystops[i]
            if distance_to_stop < CAR_LENGTH #in the waiting zone
                if i == driver.allwaystop_ind
                    update_waitlist!(driver, false,distance_to_stop,allwaystop, scene, roadway, egoid)
                    if isempty(driver.allwaystop_waitlist) && driver.allwaystop_stopcount > driver.allwaystop_waittime #time to go!
                        return acc
                    else #wait
                        if abs(ego_veh.state.v) < 0.1
                            driver.allwaystop_stopcount += 1
                        end
                        acc = stop_before(ego_veh.state.v,distance_to_stop,driver.allwaystop_horizon,driver.mlon)
                        return acc
                    end
                else # encounter new waiting zone
                    driver.allwaystop_stopcount = 0
                    acc = stop_before(ego_veh.state.v,distance_to_stop,driver.allwaystop_horizon,driver.mlon)
                    driver.allwaystop_ind = i
                    update_waitlist!(driver, true,distance_to_stop,allwaystop, scene, roadway, egoid)
                    return acc
                end
            else #outside the waiting zone
                acc = stop_before(ego_veh.state.v,distance_to_stop,driver.allwaystop_horizon,driver.mlon)
                break
            end
        end
    end
    #no allwaystop is encounterd
    driver.allwaystop_ind = 0
    empty!(driver.allwaystop_waitlist)
    return acc
end

##########################################################
type TrafficLight <: IntersectionEvent
    color::Int #0 green 1 red 2 yellow
    pos::VecSE2
end

function updateTrafficLights!(driver::DriverModel,trafficlights::Array{TrafficLight})
    driver.trafficlights = trafficlights
    driver
end

function get_yellowlight_decisison(distance)
    decision = 0
    if distance > MAX_HORIZON
        decision = 0
    else
        prob = distance*0.7/MAX_HORIZON
        #println("distance is : ",distance, " prob is : ",prob)
        if rand() < prob
            decision = -1
        end
    end
    return decision
end

function reac_yellowlight(driver,scene,roadway,foreResult)
    acc = Inf
    if driver.yellowlight_decision == -1
        acc = reac_redlight(driver,scene,roadway,foreResult)
    end
    return acc
end

function reac_redlight(driver,scene,roadway,foreResult)
    s_min_old = driver.mlon.s_min
    driver.mlon.s_min = 2.0
    AutomotiveDrivingModelsOld.track_longitudinal!(driver.mlon, scene, roadway, 1, foreResult.ind)
    driver.mlon.s_min = s_min_old
    acc = rand(driver.mlon)
    return acc
end

function reactTrafficLights(driver, scene::Scene, roadway::Roadway, egoid::Int)
    vehicle_index = findfirst(scene, egoid)
    ego_veh = scene[vehicle_index]
    scene= Scene(length(driver.trafficlights)+1)
    push!(scene,Vehicle(ego_veh.state,
                        VehicleDef(1, AgentClass.CAR, CAR_LENGTH, CAR_WIDTH)))
    for i=1:length(driver.trafficlights)
        push!(scene,Vehicle(VehicleState(driver.trafficlights[i].pos, roadway, 0.0),
            VehicleDef(AgentClass.CAR, 1.0, 3.0),i))
    end
    foreResult = get_neighbor_fore_along_lane(scene, 1, roadway)
    light_ind = 0
    distance = 0.0
    acc = Inf
    if foreResult.ind != 0 && foreResult.Δs < MAX_HORIZON
        light_ind = foreResult.ind - 1
        distance = foreResult.Δs
        if driver.trafficlights[light_ind].color == 2
            #println("light_id : ",light_ind," driver.yellowlight_id: ",driver.yellowlight_id)
            if light_ind == driver.yellowlight_id
                #println("continue previous decision ", driver.yellowlight_decision)
            else
                driver.yellowlight_id = light_ind
                driver.yellowlight_decision = get_yellowlight_decisison(distance)
            end
            acc = reac_yellowlight(driver,scene,roadway,foreResult)
        else
            driver.yellowlight_decision = 0
            driver.yellowlight_id = 0
        end
        if driver.trafficlights[light_ind].color == 1
            acc = reac_redlight(driver,scene,roadway,foreResult)
        end
    end
    return acc
end


text:
##############################################################################
#
# A macro for doing delegation
#
# This macro call
#
#     @delegate MyContainer.elems [:size, :length, :ndims, :endof]
#
# produces this block of expressions
#
#     size(a::MyContainer) = size(a.elems)
#     length(a::MyContainer) = length(a.elems)
#     ndims(a::MyContainer) = ndims(a.elems)
#     endof(a::MyContainer) = endof(a.elems)
#
##############################################################################

macro delegate(source, targets)
    typename = esc(source.args[1])
    fieldname = esc(Expr(:quote, source.args[2].args[1]))
    funcnames = targets.args
    n = length(funcnames)
    result = quote begin end end
    for i in 1:n
        funcname = esc(funcnames[i])
        f = quote
            ($funcname)(a::($typename), args...; kwargs...) = ($funcname)(getfield(a, $fieldname), args...; kwargs...)
        end
        push!(result.args[2].args, f)
    end
    return result
end

# Wrappers for DataFrameStatisticalModel and DataFrameRegressionModel
immutable DataFrameStatisticalModel{M,T} <: StatisticalModel
    model::M
    mf::ModelFrame
    mm::ModelMatrix{T}
end

immutable DataFrameRegressionModel{M,T} <: RegressionModel
    model::M
    mf::ModelFrame
    mm::ModelMatrix{T}
end

for (modeltype, dfmodeltype) in ((:StatisticalModel, DataFrameStatisticalModel),
                                 (:RegressionModel, DataFrameRegressionModel))
    @eval begin
        function StatsBase.fit{T<:$modeltype}(::Type{T}, f::Formula, df::AbstractDataFrame,
                                              args...; contrasts::Dict = Dict(), kwargs...)
            mf = ModelFrame(f, df, contrasts=contrasts)
            mm = ModelMatrix(mf)
            y = model_response(mf)
            $dfmodeltype(fit(T, mm.m, y, args...; kwargs...), mf, mm)
        end
    end
end

# Delegate functions from StatsBase that use our new types
typealias DataFrameModels @compat(Union{DataFrameStatisticalModel, DataFrameRegressionModel})
@delegate DataFrameModels.model [StatsBase.coef, StatsBase.confint,
                                 StatsBase.deviance, StatsBase.nulldeviance,
                                 StatsBase.loglikelihood, StatsBase.nullloglikelihood,
                                 StatsBase.dof, StatsBase.dof_residual, StatsBase.nobs,
                                 StatsBase.stderr, StatsBase.vcov]
@delegate DataFrameRegressionModel.model [StatsBase.residuals, StatsBase.model_response,
                                          StatsBase.predict, StatsBase.predict!]
# Need to define these manually because of ambiguity using @delegate
StatsBase.r2(mm::DataFrameRegressionModel) = r2(mm.model)
StatsBase.adjr2(mm::DataFrameRegressionModel) = adjr2(mm.model)
StatsBase.r2(mm::DataFrameRegressionModel, variant::Symbol) = r2(mm.model, variant)
StatsBase.adjr2(mm::DataFrameRegressionModel, variant::Symbol) = adjr2(mm.model, variant)

# Predict function that takes data frame as predictor instead of matrix
function StatsBase.predict(mm::DataFrameRegressionModel, df::AbstractDataFrame; kwargs...)
    # copy terms, removing outcome if present (ModelFrame will complain if a
    # term is not found in the DataFrame and we don't want to remove elements with missing y)
    newTerms = dropresponse!(mm.mf.terms)
    # create new model frame/matrix
    mf = ModelFrame(newTerms, df; contrasts = mm.mf.contrasts)
    newX = ModelMatrix(mf).m
    yp = predict(mm, newX; kwargs...)
    out = NullableArray(eltype(yp), size(df, 1))
    out[mf.msng] = yp
    return(out)
end

# coeftable implementation
function StatsBase.coeftable(model::DataFrameModels)
    ct = coeftable(model.model)
    cfnames = coefnames(model.mf)
    if length(ct.rownms) == length(cfnames)
        ct.rownms = cfnames
    end
    ct
end

# show function that delegates to coeftable
function Base.show(io::IO, model::DataFrameModels)
    try
        ct = coeftable(model)
        println(io, "$(typeof(model))")
        println(io)
        println(io, Formula(model.mf.terms))
        println(io)
        println(io,"Coefficients:")
        show(io, ct)
    catch e
        if isa(e, ErrorException) && contains(e.msg, "coeftable is not defined")
            show(io, model.model)
        else
            rethrow(e)
        end
    end
end


text:
#SafeTestsets makes every test run in a separate enviromment
#so error can be found independently
using SafeTestsets

@safetestset "Operator tests" begin include("operator_tests.jl") end
@safetestset "State tests" begin include("state_tests.jl") end
@safetestset "Logic gates tests" begin include("logic_gates_tests.jl") end
@safetestset "Correlations tests" begin include("correlations_tests.jl") end
@safetestset "Mixed tests" begin include("mixed_tests.jl") end


text:
module MyInterpolations

include("lin_interp.jl")

export MyLinInterp

end # module


text:
#=
    SOURCE: POMDPModelTools.jl
    --------------------------
    A deterministic distribution over only one value.
    This is for creating a distribution, but the outcome is deterministic.
    It is equivalent to the Kronecker Delta distribution.
=#
struct Deterministic{T}
    val::T
end

@inline Base.rand(d::Deterministic) = d.val;
@inline pdf(d::Deterministic, x) = convert(Float64, x == d.val);
@inline mode(d::Deterministic) = d.val;
@inline mean(d::Deterministic{N}) where N<:Number = d.val / 1;
@inline mean(d::Deterministic) = d.val;
@inline support(d::Deterministic) = (d.val,);
@inline weighted_iterator(d) = (x=>pdf(d, x) for x in support(d));

#=
    SOURCE: POMDPModelTools.jl
    --------------------------
    A sparse categorical distribution.
=#
struct SparseCat{V, P}
    vals::V
    probs::P
end

function Base.iterate(d::SparseCat)
    val, vstate = iterate(d.vals)
    prob, pstate = iterate(d.probs)
    return ((val=>prob), (vstate, pstate));
end

function Base.iterate(d::SparseCat, dstate::Tuple)
    vstate, pstate = dstate
    vnext = iterate(d.vals, vstate)
    pnext = iterate(d.probs, pstate)
    if vnext === nothing || pnext === nothing
        return nothing;
    end
    val, vstate_next = vnext
    prob, pstate_next = pnext
    return ((val=>prob), (vstate_next, pstate_next));
end

const Indexed = Union{AbstractArray, Tuple, NamedTuple}

@inline support(d::SparseCat) = d.vals;
@inline weighted_iterator(d::SparseCat) = d;

@inline Base.length(d::SparseCat) = min(length(d.vals), length(d.probs));

function Base.iterate(d::SparseCat{V,P}, state::Integer=1) where {V<:Indexed, P<:Indexed}
    if state > length(d)
        return nothing;
    end
    return (d.vals[state]=>d.probs[state], state+1);
end

function rand(d::SparseCat)
    r = sum(d.probs) * rand()
    tot = zero(eltype(d.probs))
    for (v, p) in d
        tot += p
        if r < tot
            return v;
        end
    end
    if sum(d.probs) <= 0.0
        error("""
              Tried to sample from a SparseCat distribution with probabilities that sum to $(sum(d.probs)).
              vals = $(d.vals)
              probs = $(d.probs)
              """)
    end
    error("Error sampling from SparseCat distribution with vals $(d.vals) and probs $(d.probs)")
end

function mean(d::SparseCat)
    vsum = zero(eltype(d.vals))
    for (v, p) in d
        vsum += v * p
    end
    return vsum / sum(d.probs);
end

function mode(d::SparseCat)
    bestp = zero(eltype(d.probs))
    bestv = first(d.vals)
    for (v, p) in d
        if p >= bestp
            bestp = p
            bestv = v
        end
    end
    return bestv;
end

max_stars_repo_name: Joshua-Robison/GridWorld

max_issues_repo_name: Joshua-Robison/GridWorld

max_forks_repo_name: Joshua-Robison/GridWorld


text:
# -------- MCTS Nodes -------------------------------------------------------- #

mutable struct Node
    action :: ActionIndex              # How did we get here?
    current_player :: Int              # Who is allowed an action in this situation?
    parent :: Union{Node, Nothing}     # Where did we get here from?
    children :: Vector{Node}           # Where can we walk?
    visit_counter :: Vector{Float32}   # How often were children visited?
    expected_reward :: Vector{Float32}
    model_policy :: Vector{Float32}
end

Node(action = 0, parent = nothing ) = Node(action, 0, parent, [], [], [], [])
Broadcast.broadcastable(node :: Node) = Ref(node)

is_leaf(node :: Node) :: Bool = isempty(node.children)

"""
Find all children for a node and assesses them through the model.
The state value predicted by the model is returned.
The value is from the perspective of the first player
"""
function expand!(node :: Node, game :: Game, model :: Model) :: Float32
  node.current_player = current_player(game)

  # We need to first check if the game is still active
  # and only evaluate the model on those games.
  is_over(game) && return status(game)

  actions = legal_actions(game)
  # This value variable is from the perspective of current_player(game)
  value, policy = apply(model, game)

  # Initialize the vectors that will be filled with info about the children
  node.children = Node.(actions, node)
  node.visit_counter = zeros(Float32, length(node.children))
  node.expected_reward = zeros(Float32, length(node.children))

  # Filter and normalize the policy vector returned by the network
  node.model_policy = policy[actions] / sum(policy[actions])
  value * current_player(game)
end

# -------- MCTS Algorithm --------------------------------------------------- #

# The confidence in a node
function confidence( node
                   ; dilution :: Float32 = 0.25
                   , exploration :: Float32 = 1.41
                   ) :: Array{Float32}

  weight = exploration * sqrt(sum(node.visit_counter))

  result = map(1:length(node.children)) do i
    explore = weight * node.model_policy[i] / (1 + node.visit_counter[i])
    node.expected_reward[i] + explore
  end

  # At the root, we blur the policy with a logit normal distribution
  # Note: In the original alpha zero implementation, dirichlet noise is used
  # instead.
  if isnothing(node.parent)
    result[:] = (1-dilution) * result + dilution * logit_normal(length(result))
  end

  result

end

"""
Traverse the tree from top to bottom and return a leaf.
While this is done, the game is mutated.
"""
function descend_to_leaf!( game :: Game
                         , node :: Node
                         ; kwargs...
                         ) :: Node

  while !is_leaf(node)
    best_i = findmax(confidence(node; kwargs...))[2]

    best_child = node.children[best_i]
    apply_action!(game, best_child.action)

    node = best_child
  end

  node

end

function backpropagate!(node, p1_value) :: Nothing

  if !isnothing(node.parent)
    # Since the parent keeps all child-information, we have to access it
    # indirectly
    parent = node.parent
    i = findfirst(x -> x === node, parent.children)

    # Update the reward and visit_counter
    counter = parent.visit_counter[i]
    parent_value = p1_value * parent.current_player
    reward = (parent.expected_reward[i] * counter + parent_value) / (counter + 1)
    parent.expected_reward[i] = reward
    parent.visit_counter[i] += 1

    # Continue the backpropagation
    backpropagate!(parent, p1_value)
  end

end

function expand_tree_by_one!(node, game, model; kwargs...)
  new_game = copy(game)
  # Decending to a leaf also changes the new_game value. This value then
  # corresponds to the game state at the leaf.
  new_node = descend_to_leaf!(new_game, node; kwargs...)
  p1_value = expand!(new_node, new_game, model)

  # Backpropagate the negative value, since the parent calculates its expected
  # reward from it.
  backpropagate!(new_node, p1_value)
end

# Runs the mcts algorithm, expanding the given root node.
function run_mcts( model
                 , game :: Game
                 ; root = Node()      # To track the expansion
                 , power = 100
                 , kwargs...
                 ) :: Node

  root.current_player = current_player(game)

  for i = 1:power
    expand_tree_by_one!(root, game, model; kwargs...)
  end

  root

end

function mctree_policy( model
                      , game :: Game
                      ; power = 100
                      , temperature = 1.
                      , kwargs...
                      ) :: Vector{Float32}

  root = run_mcts(model, game; power = power, kwargs... )

  # The paper states, that during self play we pick a move from the
  # improved stochastic policy root.visit_counter at random.
  # Note that visit_counter is generally prefered over expected_reward
  # when choosing the best move in a match, as it is less susceptible to
  # random fluctuations.
  # TODO: We now also draw from root.visit_counter in real playthroughts,
  # not only during learning. Think about this!

  if temperature == 0

    # One hot policy
    one_hot(length(root.visit_counter), findmax(root.visit_counter)[2])

  else

    # Weighted policy with temperature
    weights = (root.visit_counter/power).^(1/temperature)
    weights / sum(weights)

  end

end

function mctree_action(model, game :: Game; kwargs...) :: ActionIndex

  probs = mctree_policy(model, game; kwargs...)
  index = choose_index(probs)
  root.children[index].action

end

function mctree_turn!(model, game :: Game; kwargs...) :: Node

  root = Node()
  action = mctree_action(model, game; root = root, kwargs...)
  apply_action!(game, action)
  root

end

max_stars_repo_name: roSievers/jtac