text:
#
# Factors Reduce
#
# Dimension specific things, like broadcast, reduce, sum, etc.
# Functions (should) leave ϕ the same if dim ∉ ϕ

"""
    normalize!(ϕ, dims; p=1)
    normalize!(ϕ; p=1)

Return a normalized copy of the factor so all instances of dims have
(or the entire factors has) p-norm of 1
"""
LinearAlgebra.normalize(ϕ::Factor, x...; k...) = normalize!(deepcopy(ϕ), x...; k...)

"""
    normalize!(ϕ, dims; p=1)
    normalize!(ϕ; p=1)

Normalize the factor so all instances of dims have (or the entire factors has)
p-norm of 1
"""
function LinearAlgebra.normalize!(ϕ::Factor, dims::NodeNameUnion; p::Int=1)
    dims = unique(convert(NodeNames, dims))
    _check_dims_valid(dims, ϕ)

    inds = indexin(dims, ϕ)

    if !isempty(inds)
        if p == 1
            total = sum(abs, ϕ.potential, inds)
        elseif p == 2
            total = sum(abs2, ϕ.potential, inds)
        else
            throw(ArgumentError("p = $(p) is not supported"))
        end

        ϕ.potential ./= total
    end

    return ϕ
end

function LinearAlgebra.normalize!(ϕ::Factor; p::Int=1)
    if p == 1
        total = sum(abs, ϕ.potential)
    elseif p == 2
        total = sum(abs2, ϕ.potential)
    else
        throw(ArgumentError("p = $(p) is not supported"))
    end

    ϕ.potential ./= total

    return ϕ
end

# reduce the dimension and then squeeze them out
_reddim(op, ϕ::Factor, inds::Tuple, ::Nothing) =
            dropdims(reduce(op, ϕ.potential, dims=inds), dims=inds)
_reddim(op, ϕ::Factor, inds::Tuple, v0) =
            dropdims(reducedim(op, ϕ.potential, inds, v0), dims=inds)

"""
    reducedim(op, ϕ, dims, [v0])

Reduce dimensions `dims` in `ϕ` using function `op`.
"""
function reducedim(op, ϕ::Factor, dims::NodeNameUnion, v0=nothing)
    # a (possibly?) more efficient version than reducedim!(deepcopy(ϕ))
    dims = convert(NodeNames, dims)
    _check_dims_valid(dims, ϕ)

    # needs to be a tuple for squeeze
    inds = (indexin(dims, ϕ)...,)

    dims_new = deepcopy(ϕ.dimensions)
    deleteat!(dims_new, inds)

    v_new = _reddim(op, ϕ, inds, v0)
    ϕ = Factor(dims_new, v_new)

    return ϕ
end

function reducedim!(op, ϕ::Factor, dims::NodeNameUnion, v0=nothing)
    dims = convert(NodeNames, dims)
    _check_dims_valid(dims, ϕ)

    # needs to be a tuple for squeeze
    inds = (indexin(dims, ϕ)...,)

    deleteat!(ϕ.dimensions, inds)
    ϕ.potential = _reddim(op, ϕ, inds, v0)

    return ϕ
end

Base.sum(ϕ::Factor, dims::NodeNameUnion) = reducedim(+, ϕ, dims)
Base.sum!(ϕ::Factor, dims::NodeNameUnion) = reducedim!(+, ϕ, dims)
Base.prod(ϕ::Factor, dims::NodeNameUnion) = reducedim(*, ϕ, dims)
Base.prod!(ϕ::Factor, dims::NodeNameUnion) = reducedim!(*, ϕ, dims)
Base.maximum(ϕ::Factor, dims::NodeNameUnion) = reducedim(max, ϕ, dims)
Base.maximum!(ϕ::Factor, dims::NodeNameUnion) = reducedim!(max, ϕ, dims)
Base.minimum(ϕ::Factor, dims::NodeNameUnion) = reducedim(min, ϕ, dims)
Base.minimum!(ϕ::Factor, dims::NodeNameUnion) = reducedim!(min, ϕ, dims)

"""
    broadcast(f, ϕ, dims, values)

Broadcast a vector (or array of vectors) across the dimension(s) `dims`
Each vector in `values` will be broadcast acroos its respective dimension
in `dims`

See Base.broadcast for more info.
"""
Base.broadcast(f, ϕ::Factor, dims::NodeNameUnion, values) =
    broadcast!(f, deepcopy(ϕ), dims, values)

"""
    broadcast!(f, ϕ, dims, values)

Broadcast a vector (or array of vectors) across the dimension(s) `dims`
Each vector in `values` will be broadcast acroos its respective dimension
in `dims`

See Base.broadcast for more info.
"""
function Base.broadcast!(f, ϕ::Factor, dims::NodeNameUnion, values)
    if isa(dims, NodeName)
        dims = [dims]
        values = [values]
    end

    _ckeck_dims_unique(dims)
    _check_dims_valid(dims, ϕ)

    (length(dims) != length(values)) &&
        throw(ArgumentError("Number of dimensions does not " *
                    "match number of values to broadcast"))

    # broadcast will check if the dimensions of each value are valid

    inds = indexin(dims, ϕ)

    reshape_dims = ones(Int, ndims(ϕ))
    new_values = Vector{Array{Float64}}(undef, length(values))

    for (i, val) in enumerate(values)
        if isa(val, Vector{Float64})
            # reshape to the proper dimension
            dim_loc = inds[i]
            @inbounds reshape_dims[dim_loc] = length(val)
            new_values[i] = reshape(val, reshape_dims...)
            @inbounds reshape_dims[dim_loc] = 1
        elseif isa(val, Float64)
            new_values[i] = [val]
        else
            throw(TypeError(:broadcast!, "Invalid broadcast value",
                        Union{Float64, Vector{Float64}}, val))
        end
    end

    broadcast!(f, ϕ.potential, ϕ.potential, new_values...)

    return ϕ
end

"""
    join(op, ϕ1, ϕ2, :outer, [v0])
    join(op, ϕ1, ϕ2, :inner, [reducehow], [v0])

Performs either an inner or outer join,

An outer join returns a Factor with the union of the two dimensions
The two factors are combined with Base.broadcast(op, ...)

An inner join keeps the dimensions in common between the two Factors.
The extra dimensions are reduced with
    reducedim(reducehow, ...)
and then the two factors are combined with:
    op(ϕ1[common_dims].potential, ϕ2[common_dims].potential)
"""
function Base.join(op, ϕ1::Factor, ϕ2::Factor, kind::Symbol=:outer,
        reducehow=nothing, v0=nothing)
    # avoid all the broadcast overhead with a larger array (ideally)
    # more useful for edge cases where one (or both) is (are) singleton
    if length(ϕ1) < length(ϕ2)
        ϕ2, ϕ1 = ϕ1, ϕ2
    end

    common = intersect(ϕ1.dimensions, ϕ2.dimensions)
    index_common1 = indexin(common, ϕ1.dimensions)
    index_common2 = indexin(common, ϕ2.dimensions)

    if [size(ϕ1)[index_common1]...] != [size(ϕ2)[index_common2]...]
        throw(DimensionMismatch("Common dimensions must have same size"))
    end

    if kind == :outer
        # the first dimensions are all from ϕ1
        new_dims = union(ϕ1.dimensions, ϕ2.dimensions)

        if ndims(ϕ2) != 0
            # permute the common dimensions in ϕ2 to the beginning,
            #  in the order that they appear in ϕ1 (and therefore new_dims)
            unique1 = setdiff(ϕ1.dimensions, common)
            unique2 = setdiff(ϕ2.dimensions, common)
            # these will also be the same indices for new_dims
            index_unique1 = indexin(unique1, ϕ1.dimensions)
            index_unique2 = indexin(unique2, ϕ2.dimensions)
            perm = vcat(index_common2, index_unique2)
            temp = permutedims(ϕ2.potential, perm)

            # reshape by lining up the common dims in ϕ2 with those in ϕ1
            size_unique2 = size(ϕ2)[index_unique2]
            # set those dims to have dimension 1 for data in ϕ2
            reshape_lengths = vcat(size(ϕ1)..., size_unique2...)
            #new_v = duplicate(ϕ1.potential, size_unique2)
            new_v = Array{Float64}(undef, reshape_lengths...)
            reshape_lengths[index_unique1] .= 1
            temp = reshape(temp, (reshape_lengths...,))
        else
            new_v = similar(ϕ1.potential)
            temp = ϕ2.potential
        end

        # ndims(ϕ1) == 0 implies ndims(ϕ2) == 0
        if ndims(ϕ1) == 0
            new_v = dropdims([op(ϕ1.potential[1], temp[1])], dims=1)
        else
            broadcast!(op, new_v, ϕ1.potential, temp)
        end
    elseif kind == :inner
        error("Inner joins are (still) umimplemented")

        new_dims = getdim(ϕ1, common)

        if isempty(common)
            # weird magic for a zero-dimensional array
            v_new = squeeze(zero(eltype(ϕ1), 0), 1)
        else
            if reducehow == nothing
                throw(ArgumentError("`reducehow` is needed to reduce " *
                            "non-common dimensions"))
            end

            inds1 = (findin(ϕ1.dimensions, common)...,)
            inds2 = (findin(ϕ2.dimensions, common)...,)

            if v0 != nothing
                v1_new = squeeze(reducedim(op, ϕ1.potential, inds1, v0), inds)
                v2_new = squeeze(reducedim(op, ϕ2.potential, inds2, v0), inds)
            else
                v1_new = squeeze(reducedim(op, ϕ1.potential, inds1), inds)
                v2_new = squeeze(reducedim(op, ϕ2.potential, inds2), inds)
            end

            v_new = op(v1_new, v2_new)
        end
    else
        throw(ArgumentError("$(kind) is not a supported join type"))
    end

    return Factor(new_dims, new_v)
end

*(ϕ1::Factor, ϕ2::Factor) = join(*, ϕ1, ϕ2)
/(ϕ1::Factor, ϕ2::Factor) = join(/, ϕ1, ϕ2)
+(ϕ1::Factor, ϕ2::Factor) = join(+, ϕ1, ϕ2)
-(ϕ1::Factor, ϕ2::Factor) = join(-, ϕ1, ϕ2)


text:
export PureStateAnsatz, PureChain

struct PureStateAnsatz{A,IT,OT,Anal,S} <: KetNeuralNetwork
    __ansatz::A
    in_size::S
end

"""
    PureStateAnsatz(ansatz, input_size)

Wraps an arbitrary function into a structure that can be used as a variational
ansatz for a pure state, assuming that the width of the input is `input_size`
(corresponding to the number of lattice sites in the input hilbert space).

For this to work, ansatz must be a function respecting the following:
```
ansatz(rand(input_size)) --> scalar
trainable(ansatz) -> NamedTuple
```

To make `trainable` work with your functions, see the docs of [`functor`](@ref)
"""
function PureStateAnsatz(ansatz, in_size)
    if ansatz isa PureStateAnsatz
        throw("ansatz is already a network!")
    end

    if in_size isa AbstractHilbert
        in_size = nsites(in_size)
    end

    # input type
    in_t = real(eltype(trainable_first(ansatz)))
    # output_type
    out_t = Complex{real(eltype(trainable_first(ansatz)))}
    # is_analytic
    anal = true
    ansatz = (ansatz,)
    S=typeof(in_size)
    return PureStateAnsatz{typeof(ansatz), in_t, out_t, anal,S}(ansatz, in_size)
end

"""
    PureChain(N, args...)

Constructs a FeedForward network (a chain) encoding a pure-state. `N` must be
the number of input sites, while args... should be a series of layers.

Note: when you want to use sum, to output the total sum of states, don't use it
and use instead `sum_autobatch`, defined in this package. `sum_autobatch` behaves
as sum only for vectors, while for batches of data it sum along batches.

ex:
```
PureChain(5, Dense(5,3), Dense(3,2), sum_autobatch)
"""
function PureChain(N, args...)
    ch = Chain(args...)
    return PureStateAnsatz(N, ch)
end

@forward PureStateAnsatz.__m_ansatz Base.length, Base.first, Base.last,
         Base.iterate, Base.lastindex

ansatz(psa::PureStateAnsatz) = first(getfield(psa, :__ansatz))
functor(psa::PureStateAnsatz) = psa.__ansatz,
        a -> PureStateAnsatz(a, input_size(psa))

cache(psa::PureStateAnsatz) =
    cache(psa.__m_ansatz, trainable_first(psa), input_type(psa), input_size(psa))

cache(psa::PureStateAnsatz, batch_sz::Int) =
    cache(psa.__m_ansatz, trainable_first(psa), input_type(psa), input_size(psa), batch_sz)

(c::PureStateAnsatz)(x::Vararg{N,V}) where {N,V} = ansatz(c)(x...)
(c::PureStateAnsatz)(cache::NNCache, σ) = ansatz(c)(cache, σ)

logψ!(out::AbstractArray, net::PureStateAnsatz, c::NNBatchedCache, σ::AStateBatch) =
    logψ!(out, ansatz(net), c, σ)

logψ_and_∇logψ!(∇logψ, out::AbstractMatrix, net::PureStateAnsatz, c::NNBatchedCache, σ) =
    logψ_and_∇logψ!(∇logψ[1], out, ansatz(net), c, σ)

logψ_and_∇logψ!(∇logψ, net::PureStateAnsatz, c::NNCache, σ) =
    logψ_and_∇logψ!(∇logψ[1], ansatz(net), c, σ)

input_type(::PureStateAnsatz{A,IT,OT,AN}) where {A,IT,OT,AN} = IT
input_size(psa::PureStateAnsatz) = getfield(psa, :in_size)
out_type(::PureStateAnsatz{A,IT,OT,AN}) where {A,IT,OT,AN} = OT
is_analytic(::PureStateAnsatz{A,IT,OT,AN}) where {A,IT,OT,AN} = AN

Base.propertynames(psa::PureStateAnsatz) = propertynames(ansatz(psa))
Base.getproperty(psa::PureStateAnsatz, x::Symbol) = begin
    x === :__ansatz   && return getfield(psa, x)
    x === :__m_ansatz && return return ansatz(psa)
    getproperty(ansatz(psa), x)
end
Base.setproperty!(psa::PureStateAnsatz, name::Symbol, x) = begin
    name === :__ansatz   && return setfield!(psa, name, x)
    name === :__m_ansatz && return setfield!(psa, ansatz(psa), x)
    setproperty!(ansatz(psa), name, x)
end

Base.getindex(psa::PureStateAnsatz, x::Int) = begin
    @assert x==1
    return ansatz(psa)
end

ext: jl


text:
function compound_interest(amount, rate, years)
    new_amount = 0

    # Your code goes here!

    return new_mount
end

max_stars_repo_name: basimr/lovelace

max_issues_repo_name: basimr/project-lovelace

max_forks_repo_name: basimr/project-lovelace


text:
module Ellipticals

using OffsetArrays

using ..TypeSynonyms
using ..Input: FiberData, CellData

abstract type EllipticFunction end

include("Ellipticals-Theta.jl")
include("Ellipticals-Weierstrass.jl")
include("Ellipticals-QSpecial.jl")
include("Ellipticals-Series.jl")

struct Elliptical
    ℘ ::Weierstrass
    Q ::QSpecial
    ℘_series ::RComplex2OffsetMatrix
    Q_series ::RComplex2OffsetMatrix
end

function max_power_per_delta(fibers::Vector{FiberData})
    delta_to_nterms = RComplex2IntDict()
    delta_to_nterms[0] = 0

    n_fibers = length(fibers)
    for i in 1 : n_fibers
        z1 = fibers[i].center
        n1 = fibers[i].n_terms

        for j in i+1 : n_fibers
            z2= fibers[j].center
            delta = z2 - z1
            if real(delta) < 0
                delta = -delta
            end

            n_terms = get(delta_to_nterms, delta, -1)
            n2 = fibers[j].n_terms
            n = max(n1, n2)
            if n_terms < n
                delta_to_nterms[delta] = n
            end
        end

        if delta_to_nterms[0] < n1
            delta_to_nterms[0] = n1
        end
    end

    return delta_to_nterms
end

function Elliptical(data::CellData)
    l1 = data.l1
    l2 = data.l2
    γ  = data.γ

    ω1 = complex(l1 / 2.0)
    ω3 = (l2 / 2.0) * exp(1.0im * γ)
    tolerance = eps(imag(ω3))
    θ = Theta(ω1, ω3, tolerance)
    ℘ = Weierstrass(ω1, ω3, θ)
    Q = QSpecial(℘)

    Δ_dict = max_power_per_delta(data.fibers)
    max_power = findmax(Δ_dict)[1]
    temp_container = OffsetArray{ComplexF64}(undef, -1 : 2*max_power)

    ℘_series = Dict{RationalComplex, ComplexOffsetMatrix}()
    Q_series = Dict{RationalComplex, ComplexOffsetMatrix}()

    for Δ in keys(Δ_dict)
        upper_term = Δ_dict[Δ]

        # Для вычисления разложений в ряд производных нужно разложить исходную
        # функцию с запасом членов.
        # Всего нужно n производных по n членов в каждой.
        diff_upper_term = 2 * upper_term

        if Δ != 0
            z = real(Δ)*ω1 + imag(Δ)*ω3
            norm_factor = abs(z)

            weierstrass_normalized!(z=z,
                                norm_factor=norm_factor,
                                w=℘,
                                upper_term=diff_upper_term,
                                output=temp_container)
        else
            expand_at_pole!(output=temp_container,
                            weierstrass_data=℘,
                            upper_term=diff_upper_term)
        end

        ℘_series_array = OffsetArray{ComplexF64}(undef, 0:upper_term, -1:upper_term-2)
        derivative_series_from_initial!(initial_series=temp_container,
                                        derivatives_series=℘_series_array)
        ℘_series[Δ] = ℘_series_array

        qspecial_normalized!(z=z,
                             norm_factor=norm_factor,
                             Q=Q,
                             upper_term=diff_upper_term,
                             ℘_derivs=temp_container)
        Q_series_array = OffsetArray{ComplexF64}(undef, 0:upper_term, 0:upper_term-2)
        derivative_series_from_initial!(initial_series=temp_container,
                                        derivatives_series=℘_series_array)
        ℘_series[Δ] = Q_series_array
    end
    # TODO
end

end # module Ellipticals


text:
module Joseki

using HTTP, JSON, Dates
import HTTP.IOExtras.bytes

include("utilities.jl")
include("responders.jl")
include("middleware.jl")

export stack
"""
    stack(fns::Array{Function, 1}, endpoint::Function; error_fn=(req, err)->rethrow(err))

Create a `HTTP.Handlers.HandlerFunction` from a set of middlware functions (of
the form `HTTP.Request` => `HTTP.Request`) and an endpoint (of the form
`HTTP.Request` => `HTTP.Response`).  If `error_fn` is not provided then any
requests that cause an unhandled error respond with the default HTTP.jl
rendering of that error (a plain text string).
"""
function stack(fns::Array{Function, 1}, endpoint::Function;
               error_fn=unhandled_error_responder)
    # First we form the function that represents our middleware + endpoint
    # wrapped in a try-catch block so that we can deal with errors that are not
    # explicitly handled.
    s = function(req::HTTP.Request)
        try
            for f! in fns
                f!(req)
            end
            return endpoint(req)
        catch err
            error_fn(req, err)
        end
    end
    # Once we have this function we wrap it in a HandlerFunction which is used
    # to register routes
    return HTTP.HandlerFunction(s)
end

# TODO: Named tuples might be good here...
"""
    Joseki.server(endpoints; middleware=default_middleware error_fn=error_responder)

Construct a `HTTP.Servers.Server` from an array of `Tuples` of the form (endpoint_function, http_method, endpoint_route).
"""
function server(endpoints::Array{Tuple{T, String, String}, 1};
        middleware=default_middleware,
        error_fn=unhandled_error_responder) where {T<:Function}

    router = HTTP.Router()
    for ep in endpoints
        HTTP.register!(router, ep[2], ep[3],
            stack(middleware, ep[1]; error_fn=error_responder))
    end
    return HTTP.Servers.Server(router)
end

end # End module


text:
# Setup server paths -
_PATH_TO_ROOT = pwd()
_PATH_TO_SRC = joinpath(_PATH_TO_ROOT,"src")
_PATH_TO_LOG = joinpath(_PATH_TO_ROOT,"log")
_PATH_TO_DATABASE = joinpath(_PATH_TO_ROOT,"database")
_PATH_TO_CONFIG = joinpath(_PATH_TO_ROOT,"config")

# load external packages required by the server -
using HTTP
using JSON
using TOML
using DataFrames
using CSV
using Sockets
using Logging
using Dates
using SQLite

# load my codes -
include(joinpath(_PATH_TO_SRC,"Endpoints.jl"))


text:
# parameters used for distance calculations and coordinate system transforms

#
# Ellipsoids
#
immutable Ellipsoid
    a::Float64                          # Semi-major axis
    b::Float64                          # Semi-minor axis
    e²::Float64                         # Eccentricity squared
    e′²::Float64                         # Second eccentricity squared
end

function Ellipsoid(; a::AbstractString="", b::AbstractString="", f_inv::AbstractString="")
    if isempty(a) || isempty(b) == isempty(f_inv)
        throw(ArgumentError("Specify parameter 'a' and either 'b' or 'f_inv'"))
    end
    if isempty(b)
        _ellipsoid_af(parse(BigFloat, a), parse(BigFloat, f_inv))
    else
        _ellipsoid_ab(parse(BigFloat, a), parse(BigFloat, b))
    end
end

function _ellipsoid_ab(a::BigFloat, b::BigFloat)
    e² = (a^2 - b^2) / a^2
    e′² = (a^2 - b^2) / b^2

    Ellipsoid(a, b, e², e′²)
end
function _ellipsoid_af(a::BigFloat, f_inv::BigFloat)
    b = a * (1 - inv(f_inv))
    _ellipsoid_ab(a, b)
end

#
# Predefined Ellipses
#

# A few common Ellipsoids (TODO: steal values from Proj4!)
const eWGS84      = Ellipsoid(a = "6378137.0", f_inv = "298.257223563")
const eGRS80      = Ellipsoid(a = "6378137.0", f_inv = "298.257222100882711243") # f_inv derived
const eHayford    = Ellipsoid(a = "6378388.0", f_inv = "297.0")
const eClarke1866 = Ellipsoid(a = "6378206.4",   b = "6356583.8")
const eAiry       = Ellipsoid(a = "6377563.396", b = "6356256.909")
const eNZGD2000   = Ellipsoid(a = "6378137.0", b = "6356752.3141")

#
# Generate Ellipse types
#

# build known ellipses
abstract Ellipse <: KnownDatum

# custom type
immutable CustomEllipse{T <: Ellipsoid} <: Ellipse end
ellipsoid{T <: Ellipsoid}(::Type{CustomEllipse{T}}) = T # grab the ellipse from the type

# A few common ellipses
immutable WGS84_ELLIPSE <: Ellipse end
ellipsoid(::Type{WGS84_ELLIPSE}) = eWGS84

immutable GRS80_ELLIPSE <: Ellipse end
ellipsoid(::Type{GRS80_ELLIPSE}) = eGRS80

immutable HAYFORD_ELLIPSE <: Ellipse end
ellipsoid(::Type{HAYFORD_ELLIPSE}) = eHayford

immutable AIRY_ELLIPSE <: Ellipse end
ellipsoid(::Type{AIRY_ELLIPSE}) = eAiry

immutable CLARKE66_ELLIPSE <: Ellipse end
ellipsoid(::Type{CLARKE66_ELLIPSE}) = eClarke1866

immutable NZGD2000_ELLIPSE <: Ellipse end
ellipsoid(::Type{NZGD2000_ELLIPSE}) = eNZGD2000


text:
function build_instance(M, d₁, d₂)
    output = init_output(M, d₁, d₂)
    for (i, (x, y, v)) in enumerate(make_index_iterator(M))
        output[i, 1:3] = [x y v]
    end
    output
end

function init_output(M, d₁, d₂)
    non_zero = count(>(0), M)
    output = zeros(non_zero, 5)
    p₁ = rand(d₁, non_zero)
    p₂ = rand(d₂, non_zero)
    output[:, 4] = p₁'
    output[:, 5] = p₂'
    output
end

function make_index_iterator(M)
    x, y = size(M)
    ((i, j, M[i, j]) for i ∈ 1:x, j ∈ 1:y if M[i, j] > 0)
end


text:
# EVs::Array{Lar.Cells,1} 	one for each 3-cell (relation Edges-Vertices)
# FVs::Array{Lar.Cells,1} 	one for each 3-cell (relation Faces-Vertices)

# julia> @show V,EVs,FVs; # triangulation of 2-faces
(V, EVs, FVs) = ([1.01181 0.215639 0.516927 0.449016 0.91979 0.123616 0.147315 0.160136 0.213681 0.156419 0.699248 0.157422 0.242039 0.325549 0.591671 0.621329 0.628539 1.02252 0.226347 0.930498 0.134324 0.195738 0.992501 0.183203 0.208451 0.513984 0.566886 0.531412 0.511538 0.41632 0.223159 0.218365 0.221725 0.225755 0.81974 0.678562 0.530265 0.508469 0.514549 0.520034 0.294128 0.440629 0.305963 0.921653 0.129033 0.129737 0.131923 0.12989 0.319954 0.159637 0.940964 0.155899 0.150091 0.159038 0.178925 0.132213 0.133682 0.209488 0.212755 0.21717 0.045831 -0.301827 0.348275 0.000617 0.165572 -0.101237 -0.178503 -0.189822 0.579367 0.23171 0.881811 0.534154 0.662595 0.59629 0.344782 0.433038 0.753477 0.716324 0.740326 0.501848 0.568661 0.459863 0.222618 0.592366 0.594961 0.207386 0.394164 0.265922 0.522271 0.530034 0.293353 -0.180789 -0.052178 0.627953 -0.190635 0.489496 0.229234 0.579478 -0.060886 0.289468 -0.079901 -0.023388 0.656742 0.126044 -0.161846 0.518285 0.526925 0.635513 0.127723 0.603362 0.496221 0.064319 0.180298 0.576293 0.525604 0.27652 -0.087513 0.52527 0.161237 0.509324 0.145291 0.758074 0.394041 0.526972 0.355908 0.399061 0.238536 0.338359 0.238295 0.27631 0.564484 0.005828 0.294002 1.01221 1.30039 0.741732 1.02991; 0.160033 0.06801 0.102833 0.094984 0.956278 0.864255 0.659194 0.548263 0.084949 0.580426 0.316997 0.583871 0.542193 0.461307 0.305687 0.514086 0.549482 0.160649 0.068627 0.956895 0.864872 0.87197 0.420396 0.441934 0.223478 0.153821 0.413502 0.239372 0.231569 0.424659 0.068443 0.068167 0.06836 0.068593 0.137692 0.121256 0.104236 0.101329 0.10214 0.102872 0.076463 0.093529 0.078046 0.956385 0.864567 0.864608 0.864734 0.864616 0.886478 0.867939 0.780928 0.585196 0.677336 0.56981 0.393343 0.835666 0.82232 0.189753 0.173182 0.121583 -0.200245 0.102199 0.417839 0.720283 0.576781 0.512131 0.056734 0.066943 -0.35354 -0.051096 0.264543 0.566987 0.45525 0.512932 0.179982 0.360343 0.259028 0.186057 0.26983 0.038311 0.374082 0.280072 0.656498 0.383734 0.4692 0.63114 0.510617 -0.094786 0.326884 0.32346 -0.106882 0.152914 0.682359 0.543901 0.059204 -0.079254 -0.026271 0.32573 0.192415 0.485962 0.144527 0.956374 0.817917 0.925953 0.333219 0.194762 0.233648 0.615857 0.837779 0.614035 -0.015242 0.10294 0.139662 0.381916 0.218367 -0.102028 0.146722 0.324834 0.573584 -0.16916 0.07959 0.257702 0.506452 0.415618 0.441015 0.337141 0.551294 0.48303 0.550965 0.452356 0.181874 1.15396 0.883481 0.816151 0.545669 1.51776 1.24728; 0.196256 0.206964 0.202911 0.203825 0.196872 0.20758 0.207421 0.207335 0.206977 0.20736 0.200311 0.207344 0.206246 0.205192 0.201757 0.2012 0.201077 0.997729 1.00844 0.998346 1.00905 1.00823 0.99793 1.00873 1.00856 1.00453 1.00362 1.00423 1.0045 1.00562 0.76985 0.411 0.662501 0.964109 0.380467 0.534691 0.38142 0.882367 0.742631 0.616551 1.0042 0.83035 0.727092 0.33635 0.612986 0.665684 0.829368 0.67719 0.811536 0.82674 0.264299 0.209682 0.56973 0.310866 0.273055 0.601118 0.595637 0.795843 0.89635 0.781236 0.067745 0.601282 -0.08555 0.447986 0.194836 0.499611 0.433829 0.451328 0.502301 1.03584 0.349005 0.882542 0.685427 0.787184 0.978526 0.933793 0.504626 0.524499 0.524582 0.735709 0.772125 0.87254 0.628801 0.258519 0.608237 0.496507 0.379068 0.151378 0.079386 0.086386 0.176108 0.651402 0.1593 0.18809 0.433316 0.462105 0.451088 0.284025 0.370218 0.228267 0.391654 0.797002 0.825792 0.803328 1.07102 1.09981 1.08271 0.355548 0.603653 0.335159 0.611076 0.661604 0.803721 0.629483 1.04042 0.1446 0.377404 0.077468 0.310272 0.580364 0.813168 0.513232 0.746036 0.661025 0.756327 0.717271 0.454961 0.390781 0.454935 0.403805 1.13971 0.7676 1.5035 0.249344 0.985248 0.613139 1.34904], Array{Array{Int64,1},1}[[[1,11],[11,16],[1,16],[1,11],[1,3],[3,11],[13,16],[11,16],[11,13],[6,17],[7,17],[6,7],[5,17],[1,5],[1,17],[5,17],[6,17],[5,6],[1,17],[1,16],[16,17],[18,23],[18,28],[23,28],[18,28],[18,26],[26,28],[19,26],[19,25],[25,26],[19,26],[18,26],[18,19],[24,30],[22,24],[22,30],[21,22],[22,24],[21,24],[18,38],[38,41],[18,41],[41,42],[38,41],[38,42],[34,41],[19,34],[19,41],[19,41],[18,19],[18,41],[18,38],[1,18],[1,38],[1,35],[1,3],[3,35],[35,39],[38,39],[35,38],[35,38],[1,38],[1,35],[6,45],[44,45],[6,44],[5,44],[5,6],[6,44],[21,47],[22,47],[21,22],[22,50],[22,47],[47,50],[44,51],[5,51],[5,44],[5,51],[1,51],[1,5],[18,23],[1,18],[1,23],[1,23],[1,51],[23,51],[25,59],[19,59],[19,25],[19,34],[19,59],[34,59],[6,7],[7,56],[6,56],[45,56],[6,45],[6,56],[21,47],[21,24],[24,47],[61,63],[61,65],[63,65],[61,67],[65,67],[61,65],[67,68],[62,67],[62,68],[62,66],[66,68],[62,68],[61,67],[61,62],[62,67],[35,39],[39,69],[35,69],[39,69],[39,80],[69,80],[41,69],[42,69],[41,42],[69,70],[41,69],[41,70],[42,69],[69,80],[42,80],[69,70],[61,69],[61,70],[61,62],[62,70],[61,70],[11,63],[11,13],[13,63],[13,65],[63,65],[13,63],[35,69],[35,91],[69,91],[88,91],[61,88],[61,91],[90,91],[3,91],[3,90],[61,88],[88,89],[61,89],[61,91],[61,69],[69,91],[35,91],[3,35],[3,91],[3,11],[11,90],[3,90],[11,89],[89,90],[11,90],[11,89],[11,63],[63,89],[61,63],[61,89],[63,89],[62,92],[66,92],[62,66],[62,92],[62,70],[70,92],[34,70],[41,70],[34,41],[34,59],[59,92],[34,92],[34,92],[70,92],[34,70],[13,94],[13,16],[16,94],[13,94],[65,94],[13,65],[67,95],[67,93],[93,95],[65,93],[67,93],[65,67],[65,93],[65,94],[93,94],[30,105],[30,107],[105,107],[24,105],[24,30],[30,105],[106,107],[105,106],[105,107],[24,47],[24,105],[47,105],[47,102],[102,104],[47,104],[47,102],[47,105],[102,105],[47,104],[50,104],[47,50],[17,94],[93,94],[17,93],[7,93],[56,93],[7,56],[7,93],[7,17],[17,93],[56,109],[56,93],[93,109],[102,104],[104,109],[102,109],[93,109],[93,102],[102,109],[67,68],[67,95],[68,95],[38,42],[42,80],[38,80],[25,26],[26,106],[25,106],[92,105],[59,92],[59,105],[25,105],[25,106],[105,106],[59,105],[25,59],[25,105],[93,95],[68,95],[68,93],[66,93],[68,93],[66,68],[66,92],[92,105],[66,105],[102,105],[66,102],[66,105],[66,102],[93,102],[66,93],[16,17],[17,94],[16,94],[38,80],[38,39],[39,80],[26,106],[26,115],[106,115],[28,115],[26,115],[26,28],[107,115],[106,107],[106,115],[88,116],[88,118],[116,118],[89,118],[88,118],[88,89],[91,116],[88,116],[88,91],[89,118],[90,118],[89,90],[91,116],[116,118],[91,118],[90,118],[90,91],[91,118],[107,133],[30,133],[30,107],[22,133],[132,133],[22,132],[107,131],[107,115],[115,131],[107,131],[131,133],[107,133],[30,133],[22,133],[22,30],[104,132],[109,132],[104,109],[50,104],[22,50],[22,104],[22,132],[104,132],[22,104],[134,136],[134,137],[136,137],[135,137],[134,137],[134,135],[28,115],[28,131],[115,131],[28,131],[23,28],[23,131],[51,134],[134,135],[51,135],[23,135],[131,135],[23,131],[23,135],[23,51],[51,135],[132,136],[132,133],[133,136],[133,137],[136,137],[133,136],[51,134],[44,51],[44,134],[44,136],[134,136],[44,134],[56,109],[45,109],[45,56],[45,132],[132,136],[45,136],[45,132],[45,109],[109,132],[45,136],[44,136],[44,45],[133,137],[131,137],[131,133],[131,135],[131,137],[135,137]],[[3,4],[4,15],[3,15],[11,15],[14,15],[11,14],[11,15],[3,11],[3,15],[9,14],[9,13],[13,14],[8,13],[9,13],[8,9],[13,14],[11,13],[11,14],[4,36],[3,36],[3,4],[35,39],[35,36],[36,39],[35,36],[3,35],[3,36],[36,39],[36,40],[39,40],[42,43],[31,43],[31,42],[31,34],[34,41],[31,41],[31,41],[41,42],[31,42],[9,55],[8,55],[8,9],[31,34],[31,60],[34,60],[59,60],[34,59],[34,60],[61,63],[61,65],[63,65],[61,67],[65,67],[61,65],[67,68],[62,67],[62,68],[62,66],[66,68],[62,68],[61,67],[61,62],[62,67],[35,39],[39,69],[35,69],[39,69],[39,80],[69,80],[41,69],[42,69],[41,42],[69,70],[41,69],[41,70],[42,69],[69,80],[42,80],[69,70],[61,69],[61,70],[61,62],[62,70],[61,70],[11,63],[11,13],[13,63],[13,65],[63,65],[13,63],[35,69],[35,91],[69,91],[88,91],[61,88],[61,91],[90,91],[3,91],[3,90],[61,88],[88,89],[61,89],[61,91],[61,69],[69,91],[35,91],[3,35],[3,91],[3,11],[11,90],[3,90],[11,89],[89,90],[11,90],[11,89],[11,63],[63,89],[61,63],[61,89],[63,89],[62,92],[66,92],[62,66],[62,92],[62,70],[70,92],[34,70],[41,70],[34,41],[34,59],[59,92],[34,92],[34,92],[70,92],[34,70],[13,65],[8,13],[8,65],[8,55],[55,99],[8,99],[8,65],[8,99],[65,99],[67,101],[67,99],[99,101],[67,101],[97,101],[67,97],[67,99],[65,67],[65,99],[67,68],[68,97],[67,97],[92,112],[97,112],[92,97],[68,97],[68,92],[92,97],[92,113],[59,92],[59,113],[59,60],[60,113],[59,113],[112,113],[92,112],[92,113],[43,111],[42,43],[42,111],[42,80],[80,111],[42,111],[68,92],[66,92],[66,68],[39,80],[80,111],[39,111],[40,111],[39,40],[39,111],[9,88],[9,117],[88,117],[9,88],[88,89],[9,89],[9,117],[9,99],[99,117],[9,55],[55,99],[9,99],[9,89],[14,89],[9,14],[113,121],[31,113],[31,121],[31,60],[31,113],[60,113],[31,121],[31,120],[120,121],[40,120],[111,120],[40,111],[40,120],[36,40],[36,120],[111,120],[43,120],[43,111],[43,120],[31,120],[31,43],[112,121],[97,121],[97,112],[97,117],[101,117],[97,101],[97,120],[91,120],[91,97],[97,120],[97,121],[120,121],[88,91],[88,97],[91,97],[88,97],[88,117],[97,117],[14,89],[15,89],[14,15],[15,90],[15,89],[89,90],[4,90],[4,15],[15,90],[4,90],[90,91],[4,91],[36,120],[4,36],[4,120],[4,120],[4,91],[91,120],[99,101],[99,117],[101,117],[113,121],[112,121],[112,113]],[[8,13],[12,13],[8,12],[10,12],[8,10],[8,12],[8,55],[52,55],[8,52],[10,52],[8,10],[8,52],[54,55],[52,54],[52,55],[58,59],[53,59],[53,58],[58,59],[58,60],[59,60],[54,58],[53,58],[53,54],[53,54],[52,53],[52,54],[67,68],[66,67],[66,68],[10,64],[64,66],[10,66],[66,67],[65,67],[65,66],[10,65],[12,65],[10,12],[10,65],[10,66],[65,66],[10,52],[52,64],[10,64],[13,65],[12,65],[12,13],[53,64],[52,64],[52,53],[59,92],[66,92],[59,66],[64,66],[53,64],[53,66],[53,66],[53,59],[59,66],[13,65],[8,13],[8,65],[8,55],[55,99],[8,99],[8,65],[8,99],[65,99],[67,101],[67,99],[99,101],[67,101],[97,101],[67,97],[67,99],[65,67],[65,99],[67,68],[68,97],[67,97],[92,112],[97,112],[92,97],[68,97],[68,92],[92,97],[92,113],[59,92],[59,113],[59,60],[60,113],[59,113],[112,113],[92,112],[92,113],[68,92],[66,92],[66,68],[54,55],[55,99],[54,99],[58,60],[58,113],[60,113],[101,112],[97,112],[97,101],[58,99],[58,101],[99,101],[58,99],[54,99],[54,58],[58,112],[58,113],[112,113],[58,112],[101,112],[58,101]],[[4,15],[4,14],[14,15],[4,9],[9,14],[4,14],[4,9],[2,4],[2,9],[2,32],[2,37],[32,37],[2,37],[2,4],[4,37],[36,37],[36,40],[37,40],[36,37],[4,37],[4,36],[31,43],[31,33],[33,43],[2,9],[2,32],[9,32],[32,55],[9,55],[9,32],[31,33],[31,60],[33,60],[88,91],[90,91],[88,90],[89,90],[88,89],[88,90],[37,97],[37,96],[96,97],[32,97],[97,101],[32,101],[32,97],[32,37],[37,97],[99,101],[32,99],[32,101],[32,99],[55,99],[32,55],[96,111],[97,111],[96,97],[43,97],[33,43],[33,97],[43,97],[97,111],[43,111],[33,60],[60,113],[33,113],[112,113],[33,112],[33,113],[33,112],[97,112],[33,97],[37,96],[37,40],[40,96],[40,111],[96,111],[40,96],[9,88],[9,117],[88,117],[9,88],[88,89],[9,89],[9,117],[9,99],[99,117],[9,55],[55,99],[9,99],[9,89],[14,89],[9,14],[113,121],[31,113],[31,121],[31,60],[31,113],[60,113],[31,121],[31,120],[120,121],[40,120],[111,120],[40,111],[40,120],[36,40],[36,120],[111,120],[43,120],[43,111],[43,120],[31,120],[31,43],[112,121],[97,121],[97,112],[97,117],[101,117],[97,101],[97,120],[91,120],[91,97],[97,120],[97,121],[120,121],[88,91],[88,97],[91,97],[88,97],[88,117],[97,117],[14,89],[15,89],[14,15],[15,90],[15,89],[89,90],[4,90],[4,15],[15,90],[4,90],[90,91],[4,91],[36,120],[4,36],[4,120],[4,120],[4,91],[91,120],[99,101],[99,117],[101,117],[113,121],[112,121],[112,113]],[[7,12],[10,12],[7,10],[7,12],[7,13],[12,13],[13,17],[16,17],[13,16],[13,17],[7,13],[7,17],[26,28],[28,29],[26,29],[26,29],[25,29],[25,26],[25,30],[24,30],[24,25],[25,30],[25,29],[29,30],[47,50],[48,50],[47,48],[24,47],[24,48],[47,48],[57,59],[48,57],[48,59],[56,57],[7,57],[7,56],[25,48],[24,48],[24,25],[53,59],[53,57],[57,59],[48,59],[25,48],[25,59],[7,52],[10,52],[7,10],[7,53],[52,53],[7,52],[7,53],[7,57],[53,57],[67,68],[66,67],[66,68],[10,64],[64,66],[10,66],[66,67],[65,67],[65,66],[10,65],[12,65],[10,12],[10,65],[10,66],[65,66],[10,52],[52,64],[10,64],[13,65],[12,65],[12,13],[53,64],[52,64],[52,53],[59,92],[66,92],[59,66],[64,66],[53,64],[53,66],[53,66],[53,59],[59,66],[13,94],[13,16],[16,94],[13,94],[65,94],[13,65],[67,95],[67,93],[93,95],[65,93],[67,93],[65,67],[65,93],[65,94],[93,94],[30,105],[30,107],[105,107],[24,105],[24,30],[30,105],[106,107],[105,106],[105,107],[24,47],[24,105],[47,105],[47,102],[102,104],[47,104],[47,102],[47,105],[102,105],[47,104],[50,104],[47,50],[17,94],[93,94],[17,93],[7,93],[56,93],[7,56],[7,93],[7,17],[17,93],[56,109],[56,93],[93,109],[102,104],[104,109],[102,109],[93,109],[93,102],[102,109],[67,68],[67,95],[68,95],[25,26],[26,106],[25,106],[92,105],[59,92],[59,105],[25,105],[25,106],[105,106],[59,105],[25,59],[25,105],[93,95],[68,95],[68,93],[66,93],[68,93],[66,68],[66,92],[92,105],[66,105],[102,105],[66,102],[66,105],[66,102],[93,102],[66,93],[16,17],[17,94],[16,94],[26,106],[26,115],[106,115],[28,115],[26,115],[26,28],[107,115],[106,107],[106,115],[48,104],[104,109],[48,109],[48,104],[48,50],[50,104],[48,109],[57,109],[48,57],[29,30],[30,115],[29,115],[107,115],[30,115],[30,107],[28,29],[28,115],[29,115],[56,109],[56,57],[57,109]],[[28,29],[29,30],[28,30],[27,30],[27,28],[28,30],[49,50],[48,50],[48,49],[46,48],[46,49],[48,49],[46,48],[48,57],[46,57],[56,57],[46,56],[46,57],[81,82],[76,82],[76,81],[72,76],[72,74],[74,76],[74,76],[74,81],[76,81],[72,83],[74,83],[72,74],[74,83],[83,85],[74,85],[83,87],[85,87],[83,85],[83,87],[83,86],[86,87],[72,83],[72,76],[76,83],[49,50],[30,49],[30,50],[30,103],[27,103],[27,30],[30,103],[30,49],[49,103],[56,108],[56,110],[108,110],[49,108],[103,108],[49,103],[46,49],[46,56],[49,56],[49,56],[56,108],[49,108],[28,81],[27,81],[27,28],[27,81],[74,81],[27,74],[85,108],[74,108],[74,85],[74,103],[27,103],[27,74],[74,103],[74,108],[103,108],[30,76],[30,83],[76,83],[29,76],[76,82],[29,82],[29,76],[29,30],[30,76],[30,50],[50,83],[30,83],[48,57],[57,83],[48,83],[83,86],[57,83],[57,86],[50,83],[48,50],[48,83],[28,29],[29,82],[28,82],[81,82],[28,81],[28,82],[85,87],[85,110],[87,110],[108,110],[85,110],[85,108],[56,57],[57,110],[56,110],[86,87],[87,110],[86,110],[86,110],[57,110],[57,86]],[[20,23],[20,27],[23,27],[20,27],[20,22],[22,27],[23,27],[27,28],[23,28],[27,30],[22,27],[22,30],[44,45],[45,46],[44,46],[44,46],[46,49],[44,49],[49,50],[22,50],[22,49],[20,22],[20,49],[22,49],[20,49],[20,44],[44,49],[20,23],[23,51],[20,51],[44,51],[20,44],[20,51],[46,56],[45,46],[45,56],[74,81],[73,74],[73,81],[74,85],[73,74],[73,85],[49,50],[30,49],[30,50],[30,103],[27,103],[27,30],[30,103],[30,49],[49,103],[56,108],[56,110],[108,110],[49,108],[103,108],[49,103],[46,49],[46,56],[49,56],[49,56],[56,108],[49,108],[28,81],[27,81],[27,28],[27,81],[74,81],[27,74],[85,108],[74,108],[74,85],[74,103],[27,103],[27,74],[74,103],[74,108],[103,108],[22,50],[22,30],[30,50],[28,73],[28,51],[51,73],[73,81],[28,81],[28,73],[23,28],[23,51],[28,51],[51,85],[51,108],[85,108],[51,85],[73,85],[51,73],[108,110],[51,108],[51,110],[45,56],[56,110],[45,110],[51,110],[44,51],[44,110],[44,110],[44,45],[45,110]],[[7,12],[10,12],[7,10],[7,12],[7,13],[12,13],[13,17],[16,17],[13,16],[13,17],[7,13],[7,17],[26,28],[28,29],[26,29],[26,29],[25,29],[25,26],[25,30],[24,30],[24,25],[25,30],[25,29],[29,30],[38,42],[38,39],[39,42],[47,50],[48,50],[47,48],[24,47],[24,48],[47,48],[57,59],[48,57],[48,59],[56,57],[7,57],[7,56],[25,48],[24,48],[24,25],[53,59],[53,57],[57,59],[48,59],[25,48],[25,59],[7,52],[10,52],[7,10],[7,53],[52,53],[7,52],[7,53],[7,57],[53,57],[10,12],[12,52],[10,52],[75,76],[75,82],[76,82],[75,82],[42,75],[42,82],[39,82],[39,81],[81,82],[39,82],[42,82],[39,42],[13,84],[13,87],[84,87],[85,87],[84,85],[84,87],[13,87],[13,52],[52,87],[52,86],[86,87],[52,87],[53,86],[53,83],[83,86],[53,86],[52,86],[52,53],[13,52],[12,13],[12,52],[59,75],[75,76],[59,76],[53,83],[53,59],[59,83],[59,83],[59,76],[76,83],[13,16],[16,84],[13,84],[24,30],[24,50],[30,50],[47,50],[24,50],[24,47],[7,56],[7,110],[56,110],[17,110],[17,108],[108,110],[17,110],[7,110],[7,17],[26,38],[26,42],[38,42],[26,42],[26,75],[42,75],[25,75],[25,59],[59,75],[25,75],[26,75],[25,26],[84,85],[16,84],[16,85],[17,108],[85,108],[17,85],[17,85],[16,85],[16,17],[26,38],[28,38],[26,28],[28,39],[39,81],[28,81],[28,39],[28,38],[38,39],[30,76],[30,83],[76,83],[29,76],[76,82],[29,82],[29,76],[29,30],[30,76],[30,50],[50,83],[30,83],[48,57],[57,83],[48,83],[83,86],[57,83],[57,86],[50,83],[48,50],[48,83],[28,29],[29,82],[28,82],[81,82],[28,81],[28,82],[85,87],[85,110],[87,110],[108,110],[85,110],[85,108],[56,57],[57,110],[56,110],[86,87],[87,110],[86,110],[86,110],[57,110],[57,86]],[[33,43],[40,43],[33,40],[37,40],[32,37],[32,40],[32,40],[32,33],[33,40],[54,58],[55,58],[54,55],[55,58],[32,58],[32,55],[32,60],[33,60],[32,33],[32,60],[32,58],[58,60],[32,37],[37,98],[32,98],[55,100],[32,55],[32,100],[32,100],[32,98],[98,100],[43,60],[33,60],[33,43],[37,40],[37,114],[40,114],[98,114],[37,114],[37,98],[100,119],[54,119],[54,100],[54,55],[55,100],[54,100],[114,126],[40,114],[40,126],[124,126],[114,124],[114,126],[40,43],[43,126],[40,126],[58,126],[43,126],[43,58],[125,126],[58,126],[58,125],[43,58],[43,60],[58,60],[119,127],[100,127],[100,119],[100,127],[127,128],[100,128],[124,128],[98,124],[98,128],[98,114],[98,124],[114,124],[98,128],[98,100],[100,128],[127,129],[54,127],[54,129],[54,127],[119,127],[54,119],[58,125],[125,129],[58,129],[58,129],[54,129],[54,58],[125,129],[125,126],[126,129],[126,130],[129,130],[126,129],[128,130],[124,128],[124,130],[124,126],[126,130],[124,130],[127,128],[128,130],[127,130],[129,130],[127,129],[127,130]],[[8,13],[12,13],[8,12],[10,12],[8,10],[8,12],[40,43],[42,43],[40,42],[39,42],[39,40],[40,42],[8,55],[52,55],[8,52],[10,52],[8,10],[8,52],[54,55],[52,54],[52,55],[58,59],[53,59],[53,58],[58,59],[58,60],[59,60],[54,58],[53,58],[53,54],[53,54],[52,53],[52,54],[10,12],[12,52],[10,52],[75,76],[75,82],[76,82],[75,82],[42,75],[42,82],[39,82],[39,81],[81,82],[39,82],[42,82],[39,42],[13,84],[13,87],[84,87],[85,87],[84,85],[84,87],[13,87],[13,52],[52,87],[52,86],[86,87],[52,87],[53,86],[53,83],[83,86],[53,86],[52,86],[52,53],[13,52],[12,13],[12,52],[59,75],[75,76],[59,76],[53,83],[53,59],[59,83],[59,83],[59,76],[76,83],[13,84],[13,100],[84,100],[13,100],[8,13],[8,100],[84,98],[84,100],[98,100],[55,100],[8,100],[8,55],[43,60],[42,43],[42,60],[59,75],[59,60],[60,75],[60,75],[42,60],[42,75],[81,85],[81,114],[85,114],[81,114],[39,81],[39,114],[85,114],[84,114],[84,85],[84,114],[98,114],[84,98],[40,114],[39,114],[39,40],[100,119],[54,119],[54,100],[54,55],[55,100],[54,100],[114,126],[40,114],[40,126],[124,126],[114,124],[114,126],[40,43],[43,126],[40,126],[58,126],[43,126],[43,58],[125,126],[58,126],[58,125],[43,58],[43,60],[58,60],[119,127],[100,127],[100,119],[100,127],[127,128],[100,128],[124,128],[98,124],[98,128],[98,114],[98,124],[114,124],[98,128],[98,100],[100,128],[127,129],[54,127],[54,129],[54,127],[119,127],[54,119],[58,125],[125,129],[58,129],[58,129],[54,129],[54,58],[76,82],[76,126],[82,126],[76,125],[76,83],[83,125],[76,126],[76,125],[125,126],[83,86],[86,129],[83,129],[125,129],[83,125],[83,129],[85,87],[85,124],[87,124],[124,128],[87,128],[87,124],[124,126],[81,124],[81,126],[81,82],[82,126],[81,126],[85,124],[81,85],[81,124],[87,128],[127,128],[87,127],[86,129],[86,127],[127,129],[86,127],[86,87],[87,127]],[[3,4],[4,15],[3,15],[11,15],[14,15],[11,14],[11,15],[3,11],[3,15],[9,14],[9,13],[13,14],[8,13],[9,13],[8,9],[13,14],[11,13],[11,14],[4,36],[3,36],[3,4],[35,39],[35,36],[36,39],[35,36],[3,35],[3,36],[36,39],[36,40],[39,40],[9,55],[8,55],[8,9],[71,77],[35,77],[35,71],[77,79],[73,77],[73,79],[77,78],[35,78],[35,77],[71,77],[71,73],[73,77],[73,81],[78,81],[73,78],[39,78],[35,39],[35,78],[39,78],[78,81],[39,81],[73,78],[78,79],[73,79],[11,73],[73,84],[11,84],[11,73],[11,71],[71,73],[11,84],[13,84],[11,13],[73,85],[84,85],[73,84],[11,71],[35,71],[11,35],[3,35],[3,11],[11,35],[13,84],[13,100],[84,100],[13,100],[8,13],[8,100],[84,98],[84,100],[98,100],[55,100],[8,100],[8,55],[81,85],[81,114],[85,114],[81,114],[39,81],[39,114],[85,114],[84,114],[84,85],[84,114],[98,114],[84,98],[40,114],[39,114],[39,40],[9,55],[9,14],[14,55],[14,100],[55,100],[14,55],[78,79],[78,114],[79,114],[36,40],[40,114],[36,114],[36,114],[78,114],[36,78],[77,79],[77,98],[79,98],[77,98],[15,77],[15,98],[98,114],[79,114],[79,98],[14,98],[14,100],[98,100],[14,98],[15,98],[14,15],[4,15],[4,36],[15,36],[77,78],[15,77],[15,78],[15,78],[15,36],[36,78],[81,85],[73,81],[73,85]],[[42,43],[31,43],[31,42],[31,34],[34,41],[31,41],[31,41],[41,42],[31,42],[31,34],[31,60],[34,60],[59,60],[34,59],[34,60],[42,75],[41,42],[41,75],[41,75],[41,59],[59,75],[34,59],[41,59],[34,41],[43,60],[42,43],[42,60],[59,75],[59,60],[60,75],[60,75],[42,60],[42,75],[31,43],[31,60],[43,60]],[[40,43],[42,43],[40,42],[39,42],[39,40],[40,42],[42,80],[39,80],[39,42],[43,111],[42,43],[42,111],[42,80],[80,111],[42,111],[39,80],[80,111],[39,111],[40,111],[39,40],[39,111],[40,43],[40,111],[43,111]],[[4,15],[4,14],[14,15],[4,9],[9,14],[4,14],[4,9],[2,4],[2,9],[2,32],[2,37],[32,37],[2,37],[2,4],[4,37],[36,37],[36,40],[37,40],[36,37],[4,37],[4,36],[2,9],[2,32],[9,32],[32,55],[9,55],[9,32],[77,78],[77,79],[78,79],[32,37],[37,98],[32,98],[55,100],[32,55],[32,100],[32,100],[32,98],[98,100],[37,40],[37,114],[40,114],[98,114],[37,114],[37,98],[9,55],[9,14],[14,55],[14,100],[55,100],[14,55],[78,79],[78,114],[79,114],[36,40],[40,114],[36,114],[36,114],[78,114],[36,78],[77,79],[77,98],[79,98],[77,98],[15,77],[15,98],[98,114],[79,114],[79,98],[14,98],[14,100],[98,100],[14,98],[15,98],[14,15],[4,15],[4,36],[15,36],[77,78],[15,77],[15,78],[15,78],[15,36],[36,78]],[[49,50],[48,50],[48,49],[46,48],[46,49],[48,49],[46,48],[48,57],[46,57],[56,57],[46,56],[46,57],[49,50],[50,104],[49,104],[49,104],[46,104],[46,49],[46,109],[56,109],[46,56],[46,109],[46,104],[104,109],[48,104],[104,109],[48,109],[48,104],[48,50],[50,104],[48,109],[57,109],[48,57],[56,109],[56,57],[57,109]],[[28,29],[29,30],[28,30],[27,30],[27,28],[28,30],[27,107],[30,107],[27,30],[27,28],[28,107],[27,107],[107,115],[28,107],[28,115],[29,30],[30,115],[29,115],[107,115],[30,115],[30,107],[28,29],[28,115],[29,115]],[[81,82],[76,82],[76,81],[72,76],[72,74],[74,76],[74,76],[74,81],[76,81],[72,83],[74,83],[72,74],[74,83],[83,85],[74,85],[83,87],[85,87],[83,85],[83,87],[83,86],[86,87],[72,83],[72,76],[76,83],[74,81],[74,85],[81,85],[124,126],[123,126],[123,124],[123,125],[123,126],[125,126],[127,128],[124,128],[124,127],[123,124],[123,127],[124,127],[125,129],[123,125],[123,129],[123,127],[127,129],[123,129],[76,82],[76,126],[82,126],[76,125],[76,83],[83,125],[76,126],[76,125],[125,126],[83,86],[86,129],[83,129],[125,129],[83,125],[83,129],[85,87],[85,124],[87,124],[124,128],[87,128],[87,124],[124,126],[81,124],[81,126],[81,82],[82,126],[81,126],[85,124],[81,85],[81,124],[87,128],[127,128],[87,127],[86,129],[86,127],[127,129],[86,127],[86,87],[87,127]],[[77,78],[77,79],[78,79],[78,122],[79,122],[78,79],[77,122],[79,122],[77,79],[77,78],[77,122],[78,122]],[[1,11],[11,16],[1,16],[1,11],[1,3],[3,11],[13,16],[11,16],[11,13],[6,17],[7,17],[6,7],[5,17],[1,5],[1,17],[5,17],[6,17],[5,6],[1,17],[1,16],[16,17],[18,23],[18,28],[23,28],[18,28],[18,26],[26,28],[19,26],[19,25],[25,26],[19,26],[18,26],[18,19],[18,38],[38,41],[18,41],[41,42],[38,41],[38,42],[34,41],[19,34],[19,41],[19,41],[18,19],[18,41],[18,38],[1,18],[1,38],[1,35],[1,3],[3,35],[35,39],[38,39],[35,38],[35,38],[1,38],[1,35],[6,45],[44,45],[6,44],[5,44],[5,6],[6,44],[44,51],[5,51],[5,44],[5,51],[1,51],[1,5],[18,23],[1,18],[1,23],[1,23],[1,51],[23,51],[25,59],[19,59],[19,25],[19,34],[19,59],[34,59],[6,7],[7,56],[6,56],[45,56],[6,45],[6,56],[71,77],[35,77],[35,71],[77,79],[73,77],[73,79],[77,78],[35,78],[35,77],[71,77],[71,73],[73,77],[73,81],[78,81],[73,78],[39,78],[35,39],[35,78],[39,78],[78,81],[39,81],[73,78],[78,79],[73,79],[42,75],[41,42],[41,75],[11,73],[73,84],[11,84],[11,73],[11,71],[71,73],[11,84],[13,84],[11,13],[73,85],[84,85],[73,84],[11,71],[35,71],[11,35],[3,35],[3,11],[11,35],[41,75],[41,59],[59,75],[34,59],[41,59],[34,41],[13,16],[16,84],[13,84],[7,56],[7,110],[56,110],[17,110],[17,108],[108,110],[17,110],[7,110],[7,17],[26,38],[26,42],[38,42],[26,42],[26,75],[42,75],[25,75],[25,59],[59,75],[25,75],[26,75],[25,26],[84,85],[16,84],[16,85],[17,108],[85,108],[17,85],[17,85],[16,85],[16,17],[26,38],[28,38],[26,28],[28,39],[39,81],[28,81],[28,39],[28,38],[38,39],[78,122],[79,122],[78,79],[77,122],[79,122],[77,79],[77,78],[77,122],[78,122],[28,73],[28,51],[51,73],[73,81],[28,81],[28,73],[23,28],[23,51],[28,51],[51,85],[51,108],[85,108],[51,85],[73,85],[51,73],[108,110],[51,108],[51,110],[45,56],[56,110],[45,110],[51,110],[44,51],[44,110],[44,110],[44,45],[45,110]],[[24,30],[22,24],[22,30],[21,22],[22,24],[21,24],[21,47],[22,47],[21,22],[22,50],[22,47],[47,50],[21,47],[21,24],[24,47],[24,30],[24,50],[30,50],[47,50],[24,50],[24,47],[22,50],[22,30],[30,50]],[[20,23],[20,27],[23,27],[20,27],[20,22],[22,27],[23,27],[27,28],[23,28],[27,30],[22,27],[22,30],[44,45],[45,46],[44,46],[44,46],[46,49],[44,49],[49,50],[22,50],[22,49],[20,22],[20,49],[22,49],[20,49],[20,44],[44,49],[20,23],[23,51],[20,51],[44,51],[20,44],[20,51],[46,56],[45,46],[45,56],[49,50],[50,104],[49,104],[27,107],[30,107],[27,30],[49,104],[46,104],[46,49],[46,109],[56,109],[46,56],[46,109],[46,104],[104,109],[27,28],[28,107],[27,107],[107,115],[28,107],[28,115],[107,133],[30,133],[30,107],[22,133],[132,133],[22,132],[107,131],[107,115],[115,131],[107,131],[131,133],[107,133],[30,133],[22,133],[22,30],[104,132],[109,132],[104,109],[50,104],[22,50],[22,104],[22,132],[104,132],[22,104],[134,136],[134,137],[136,137],[135,137],[134,137],[134,135],[28,115],[28,131],[115,131],[28,131],[23,28],[23,131],[51,134],[134,135],[51,135],[23,135],[131,135],[23,131],[23,135],[23,51],[51,135],[132,136],[132,133],[133,136],[133,137],[136,137],[133,136],[51,134],[44,51],[44,134],[44,136],[134,136],[44,134],[56,109],[45,109],[45,56],[45,132],[132,136],[45,136],[45,132],[45,109],[109,132],[45,136],[44,136],[44,45],[133,137],[131,137],[131,133],[131,135],[131,137],[135,137]],[[38,42],[38,39],[39,42],[42,80],[39,80],[39,42],[38,42],[42,80],[38,80],[38,80],[38,39],[39,80]],[[33,43],[40,43],[33,40],[37,40],[32,37],[32,40],[32,40],[32,33],[33,40],[54,58],[55,58],[54,55],[55,58],[32,58],[32,55],[32,60],[33,60],[32,33],[32,60],[32,58],[58,60],[37,97],[37,96],[96,97],[32,97],[97,101],[32,101],[32,97],[32,37],[37,97],[99,101],[32,99],[32,101],[32,99],[55,99],[32,55],[96,111],[97,111],[96,97],[43,97],[33,43],[33,97],[43,97],[97,111],[43,111],[33,60],[60,113],[33,113],[112,113],[33,112],[33,113],[33,112],[97,112],[33,97],[37,96],[37,40],[40,96],[40,111],[96,111],[40,96],[54,55],[55,99],[54,99],[58,60],[58,113],[60,113],[40,43],[40,111],[43,111],[101,112],[97,112],[97,101],[58,99],[58,101],[99,101],[58,99],[54,99],[54,58],[58,112],[58,113],[112,113],[58,112],[101,112],[58,101]],[[31,43],[31,33],[33,43],[31,33],[31,60],[33,60],[43,60],[33,60],[33,43],[31,43],[31,60],[43,60]],[[74,81],[73,74],[73,81],[74,85],[73,74],[73,85],[74,81],[74,85],[81,85],[81,85],[73,81],[73,85]],[[88,91],[90,91],[88,90],[89,90],[88,89],[88,90],[88,116],[88,118],[116,118],[89,118],[88,118],[88,89],[91,116],[88,116],[88,91],[89,118],[90,118],[89,90],[91,116],[116,118],[91,118],[90,118],[90,91],[91,118]],[[124,126],[123,126],[123,124],[123,125],[123,126],[125,126],[127,128],[124,128],[124,127],[123,124],[123,127],[124,127],[125,129],[123,125],[123,129],[123,127],[127,129],[123,129],[125,129],[125,126],[126,129],[126,130],[129,130],[126,129],[128,130],[124,128],[124,130],[124,126],[126,130],[124,130],[127,128],[128,130],[127,130],[129,130],[127,129],[127,130]]],
Array{Array{Int64,1},1}[[[1,11,16],[1,3,11],[11,13,16],[6,7,17],[1,5,17],[5,6,17],[1,16,17],[18,23,28],[18,26,28],[19,25,26],[18,19,26],[22,24,30],[21,22,24],[18,38,41],[38,41,42],[19,34,41],[18,19,41],[1,18,38],[1,3,35],[35,38,39],[1,35,38],[6,44,45],[5,6,44],[21,22,47],[22,47,50],[5,44,51],[1,5,51],[1,18,23],[1,23,51],[19,25,59],[19,34,59],[6,7,56],[6,45,56],[21,24,47],[61,63,65],[61,65,67],[62,67,68],[62,66,68],[61,62,67],[35,39,69],[39,69,80],[41,42,69],[41,69,70],[42,69,80],[61,69,70],[61,62,70],[11,13,63],[13,63,65],[35,69,91],[61,88,91],[3,90,91],[61,88,89],[61,69,91],[3,35,91],[3,11,90],[11,89,90],[11,63,89],[61,63,89],[62,66,92],[62,70,92],[34,41,70],[34,59,92],[34,70,92],[13,16,94],[13,65,94],[67,93,95],[65,67,93],[65,93,94],[30,105,107],[24,30,105],[105,106,107],[24,47,105],[47,102,104],[47,102,105],[47,50,104],[17,93,94],[7,56,93],[7,17,93],[56,93,109],[102,104,109],[93,102,109],[67,68,95],[38,42,80],[25,26,106],[59,92,105],[25,105,106],[25,59,105],[68,93,95],[66,68,93],[66,92,105],[66,102,105],[66,93,102],[16,17,94],[38,39,80],[26,106,115],[26,28,115],[106,107,115],[88,116,118],[88,89,118],[88,91,116],[89,90,118],[91,116,118],[90,91,118],[30,107,133],[22,132,133],[107,115,131],[107,131,133],[22,30,133],[104,109,132],[22,50,104],[22,104,132],[134,136,137],[134,135,137],[28,115,131],[23,28,131],[51,134,135],[23,131,135],[23,51,135],[132,133,136],[133,136,137],[44,51,134],[44,134,136],[45,56,109],[45,132,136],[45,109,132],[44,45,136],[131,133,137],[131,135,137]],[[3,4,15],[11,14,15],[3,11,15],[9,13,14],[8,9,13],[11,13,14],[3,4,36],[35,36,39],[3,35,36],[36,39,40],[31,42,43],[31,34,41],[31,41,42],[8,9,55],[31,34,60],[34,59,60],[61,63,65],[61,65,67],[62,67,68],[62,66,68],[61,62,67],[35,39,69],[39,69,80],[41,42,69],[41,69,70],[42,69,80],[61,69,70],[61,62,70],[11,13,63],[13,63,65],[35,69,91],[61,88,91],[3,90,91],[61,88,89],[61,69,91],[3,35,91],[3,11,90],[11,89,90],[11,63,89],[61,63,89],[62,66,92],[62,70,92],[34,41,70],[34,59,92],[34,70,92],[8,13,65],[8,55,99],[8,65,99],[67,99,101],[67,97,101],[65,67,99],[67,68,97],[92,97,112],[68,92,97],[59,92,113],[59,60,113],[92,112,113],[42,43,111],[42,80,111],[66,68,92],[39,80,111],[39,40,111],[9,88,117],[9,88,89],[9,99,117],[9,55,99],[9,14,89],[31,113,121],[31,60,113],[31,120,121],[40,111,120],[36,40,120],[43,111,120],[31,43,120],[97,112,121],[97,101,117],[91,97,120],[97,120,121],[88,91,97],[88,97,117],[14,15,89],[15,89,90],[4,15,90],[4,90,91],[4,36,120],[4,91,120],[99,101,117],[112,113,121]],[[8,12,13],[8,10,12],[8,52,55],[8,10,52],[52,54,55],[53,58,59],[58,59,60],[53,54,58],[52,53,54],[66,67,68],[10,64,66],[65,66,67],[10,12,65],[10,65,66],[10,52,64],[12,13,65],[52,53,64],[59,66,92],[53,64,66],[53,59,66],[8,13,65],[8,55,99],[8,65,99],[67,99,101],[67,97,101],[65,67,99],[67,68,97],[92,97,112],[68,92,97],[59,92,113],[59,60,113],[92,112,113],[66,68,92],[54,55,99],[58,60,113],[97,101,112],[58,99,101],[54,58,99],[58,112,113],[58,101,112]],[[4,14,15],[4,9,14],[2,4,9],[2,32,37],[2,4,37],[36,37,40],[4,36,37],[31,33,43],[2,9,32],[9,32,55],[31,33,60],[88,90,91],[88,89,90],[37,96,97],[32,97,101],[32,37,97],[32,99,101],[32,55,99],[96,97,111],[33,43,97],[43,97,111],[33,60,113],[33,112,113],[33,97,112],[37,40,96],[40,96,111],[9,88,117],[9,88,89],[9,99,117],[9,55,99],[9,14,89],[31,113,121],[31,60,113],[31,120,121],[40,111,120],[36,40,120],[43,111,120],[31,43,120],[97,112,121],[97,101,117],[91,97,120],[97,120,121],[88,91,97],[88,97,117],[14,15,89],[15,89,90],[4,15,90],[4,90,91],[4,36,120],[4,91,120],[99,101,117],[112,113,121]],[[7,10,12],[7,12,13],[13,16,17],[7,13,17],[26,28,29],[25,26,29],[24,25,30],[25,29,30],[47,48,50],[24,47,48],[48,57,59],[7,56,57],[24,25,48],[53,57,59],[25,48,59],[7,10,52],[7,52,53],[7,53,57],[66,67,68],[10,64,66],[65,66,67],[10,12,65],[10,65,66],[10,52,64],[12,13,65],[52,53,64],[59,66,92],[53,64,66],[53,59,66],[13,16,94],[13,65,94],[67,93,95],[65,67,93],[65,93,94],[30,105,107],[24,30,105],[105,106,107],[24,47,105],[47,102,104],[47,102,105],[47,50,104],[17,93,94],[7,56,93],[7,17,93],[56,93,109],[102,104,109],[93,102,109],[67,68,95],[25,26,106],[59,92,105],[25,105,106],[25,59,105],[68,93,95],[66,68,93],[66,92,105],[66,102,105],[66,93,102],[16,17,94],[26,106,115],[26,28,115],[106,107,115],[48,104,109],[48,50,104],[48,57,109],[29,30,115],[30,107,115],[28,29,115],[56,57,109]],[[28,29,30],[27,28,30],[48,49,50],[46,48,49],[46,48,57],[46,56,57],[76,81,82],[72,74,76],[74,76,81],[72,74,83],[74,83,85],[83,85,87],[83,86,87],[72,76,83],[30,49,50],[27,30,103],[30,49,103],[56,108,110],[49,103,108],[46,49,56],[49,56,108],[27,28,81],[27,74,81],[74,85,108],[27,74,103],[74,103,108],[30,76,83],[29,76,82],[29,30,76],[30,50,83],[48,57,83],[57,83,86],[48,50,83],[28,29,82],[28,81,82],[85,87,110],[85,108,110],[56,57,110],[86,87,110],[57,86,110]],[[20,23,27],[20,22,27],[23,27,28],[22,27,30],[44,45,46],[44,46,49],[22,49,50],[20,22,49],[20,44,49],[20,23,51],[20,44,51],[45,46,56],[73,74,81],[73,74,85],[30,49,50],[27,30,103],[30,49,103],[56,108,110],[49,103,108],[46,49,56],[49,56,108],[27,28,81],[27,74,81],[74,85,108],[27,74,103],[74,103,108],[22,30,50],[28,51,73],[28,73,81],[23,28,51],[51,85,108],[51,73,85],[51,108,110],[45,56,110],[44,51,110],[44,45,110]],[[7,10,12],[7,12,13],[13,16,17],[7,13,17],[26,28,29],[25,26,29],[24,25,30],[25,29,30],[38,39,42],[47,48,50],[24,47,48],[48,57,59],[7,56,57],[24,25,48],[53,57,59],[25,48,59],[7,10,52],[7,52,53],[7,53,57],[10,12,52],[75,76,82],[42,75,82],[39,81,82],[39,42,82],[13,84,87],[84,85,87],[13,52,87],[52,86,87],[53,83,86],[52,53,86],[12,13,52],[59,75,76],[53,59,83],[59,76,83],[13,16,84],[24,30,50],[24,47,50],[7,56,110],[17,108,110],[7,17,110],[26,38,42],[26,42,75],[25,59,75],[25,26,75],[16,84,85],[17,85,108],[16,17,85],[26,28,38],[28,39,81],[28,38,39],[30,76,83],[29,76,82],[29,30,76],[30,50,83],[48,57,83],[57,83,86],[48,50,83],[28,29,82],[28,81,82],[85,87,110],[85,108,110],[56,57,110],[86,87,110],[57,86,110]],[[33,40,43],[32,37,40],[32,33,40],[54,55,58],[32,55,58],[32,33,60],[32,58,60],[32,37,98],[32,55,100],[32,98,100],[33,43,60],[37,40,114],[37,98,114],[54,100,119],[54,55,100],[40,114,126],[114,124,126],[40,43,126],[43,58,126],[58,125,126],[43,58,60],[100,119,127],[100,127,128],[98,124,128],[98,114,124],[98,100,128],[54,127,129],[54,119,127],[58,125,129],[54,58,129],[125,126,129],[126,129,130],[124,128,130],[124,126,130],[127,128,130],[127,129,130]],[[8,12,13],[8,10,12],[40,42,43],[39,40,42],[8,52,55],[8,10,52],[52,54,55],[53,58,59],[58,59,60],[53,54,58],[52,53,54],[10,12,52],[75,76,82],[42,75,82],[39,81,82],[39,42,82],[13,84,87],[84,85,87],[13,52,87],[52,86,87],[53,83,86],[52,53,86],[12,13,52],[59,75,76],[53,59,83],[59,76,83],[13,84,100],[8,13,100],[84,98,100],[8,55,100],[42,43,60],[59,60,75],[42,60,75],[81,85,114],[39,81,114],[84,85,114],[84,98,114],[39,40,114],[54,100,119],[54,55,100],[40,114,126],[114,124,126],[40,43,126],[43,58,126],[58,125,126],[43,58,60],[100,119,127],[100,127,128],[98,124,128],[98,114,124],[98,100,128],[54,127,129],[54,119,127],[58,125,129],[54,58,129],[76,82,126],[76,83,125],[76,125,126],[83,86,129],[83,125,129],[85,87,124],[87,124,128],[81,124,126],[81,82,126],[81,85,124],[87,127,128],[86,127,129],[86,87,127]],[[3,4,15],[11,14,15],[3,11,15],[9,13,14],[8,9,13],[11,13,14],[3,4,36],[35,36,39],[3,35,36],[36,39,40],[8,9,55],[35,71,77],[73,77,79],[35,77,78],[71,73,77],[73,78,81],[35,39,78],[39,78,81],[73,78,79],[11,73,84],[11,71,73],[11,13,84],[73,84,85],[11,35,71],[3,11,35],[13,84,100],[8,13,100],[84,98,100],[8,55,100],[81,85,114],[39,81,114],[84,85,114],[84,98,114],[39,40,114],[9,14,55],[14,55,100],[78,79,114],[36,40,114],[36,78,114],[77,79,98],[15,77,98],[79,98,114],[14,98,100],[14,15,98],[4,15,36],[15,77,78],[15,36,78],[73,81,85]],[[31,42,43],[31,34,41],[31,41,42],[31,34,60],[34,59,60],[41,42,75],[41,59,75],[34,41,59],[42,43,60],[59,60,75],[42,60,75],[31,43,60]],[[40,42,43],[39,40,42],[39,42,80],[42,43,111],[42,80,111],[39,80,111],[39,40,111],[40,43,111]],[[4,14,15],[4,9,14],[2,4,9],[2,32,37],[2,4,37],[36,37,40],[4,36,37],[2,9,32],[9,32,55],[77,78,79],[32,37,98],[32,55,100],[32,98,100],[37,40,114],[37,98,114],[9,14,55],[14,55,100],[78,79,114],[36,40,114],[36,78,114],[77,79,98],[15,77,98],[79,98,114],[14,98,100],[14,15,98],[4,15,36],[15,77,78],[15,36,78]],[[48,49,50],[46,48,49],[46,48,57],[46,56,57],[49,50,104],[46,49,104],[46,56,109],[46,104,109],[48,104,109],[48,50,104],[48,57,109],[56,57,109]],[[28,29,30],[27,28,30],[27,30,107],[27,28,107],[28,107,115],[29,30,115],[30,107,115],[28,29,115]],[[76,81,82],[72,74,76],[74,76,81],[72,74,83],[74,83,85],[83,85,87],[83,86,87],[72,76,83],[74,81,85],[123,124,126],[123,125,126],[124,127,128],[123,124,127],[123,125,129],[123,127,129],[76,82,126],[76,83,125],[76,125,126],[83,86,129],[83,125,129],[85,87,124],[87,124,128],[81,124,126],[81,82,126],[81,85,124],[87,127,128],[86,127,129],[86,87,127]],[[77,78,79],[78,79,122],[77,79,122],[77,78,122]],[[1,11,16],[1,3,11],[11,13,16],[6,7,17],[1,5,17],[5,6,17],[1,16,17],[18,23,28],[18,26,28],[19,25,26],[18,19,26],[18,38,41],[38,41,42],[19,34,41],[18,19,41],[1,18,38],[1,3,35],[35,38,39],[1,35,38],[6,44,45],[5,6,44],[5,44,51],[1,5,51],[1,18,23],[1,23,51],[19,25,59],[19,34,59],[6,7,56],[6,45,56],[35,71,77],[73,77,79],[35,77,78],[71,73,77],[73,78,81],[35,39,78],[39,78,81],[73,78,79],[41,42,75],[11,73,84],[11,71,73],[11,13,84],[73,84,85],[11,35,71],[3,11,35],[41,59,75],[34,41,59],[13,16,84],[7,56,110],[17,108,110],[7,17,110],[26,38,42],[26,42,75],[25,59,75],[25,26,75],[16,84,85],[17,85,108],[16,17,85],[26,28,38],[28,39,81],[28,38,39],[78,79,122],[77,79,122],[77,78,122],[28,51,73],[28,73,81],[23,28,51],[51,85,108],[51,73,85],[51,108,110],[45,56,110],[44,51,110],[44,45,110]],[[22,24,30],[21,22,24],[21,22,47],[22,47,50],[21,24,47],[24,30,50],[24,47,50],[22,30,50]],[[20,23,27],[20,22,27],[23,27,28],[22,27,30],[44,45,46],[44,46,49],[22,49,50],[20,22,49],[20,44,49],[20,23,51],[20,44,51],[45,46,56],[49,50,104],[27,30,107],[46,49,104],[46,56,109],[46,104,109],[27,28,107],[28,107,115],[30,107,133],[22,132,133],[107,115,131],[107,131,133],[22,30,133],[104,109,132],[22,50,104],[22,104,132],[134,136,137],[134,135,137],[28,115,131],[23,28,131],[51,134,135],[23,131,135],[23,51,135],[132,133,136],[133,136,137],[44,51,134],[44,134,136],[45,56,109],[45,132,136],[45,109,132],[44,45,136],[131,133,137],[131,135,137]],[[38,39,42],[39,42,80],[38,42,80],[38,39,80]],[[33,40,43],[32,37,40],[32,33,40],[54,55,58],[32,55,58],[32,33,60],[32,58,60],[37,96,97],[32,97,101],[32,37,97],[32,99,101],[32,55,99],[96,97,111],[33,43,97],[43,97,111],[33,60,113],[33,112,113],[33,97,112],[37,40,96],[40,96,111],[54,55,99],[58,60,113],[40,43,111],[97,101,112],[58,99,101],[54,58,99],[58,112,113],[58,101,112]],[[31,33,43],[31,33,60],[33,43,60],[31,43,60]],[[73,74,81],[73,74,85],[74,81,85],[73,81,85]],[[88,90,91],[88,89,90],[88,116,118],[88,89,118],[88,91,116],[89,90,118],[91,116,118],[90,91,118]],[[123,124,126],[123,125,126],[124,127,128],[123,124,127],[123,125,129],[123,127,129],[125,126,129],[126,129,130],[124,128,130],[124,126,130],[127,128,130],[127,129,130]]])


text:
Base.eltype(::AbstractGrid{N,T}) where {N,T} = T

Base.length(g::AbstractGrid) = length(getdomain(g))
Base.iterate(g::AbstractGrid, state...) = iterate(getdomain(g), state...)

Base.collect(g::AbstractGrid) = collect(getdomain(g))

Base.getproperty(g::AbstractGrid, k::Symbol) = getfield(getfield(g, :grid), k)
Base.propertynames(::AbstractGrid{N,T,Names}) where {N,T,Names} = Names
staticnames(::Type{<:AbstractGrid{N,T,Names}}) where {N,T,Names} = Names

Base.isempty(g::AbstractGrid) = all(map(isempty, getdomain(g)))

function Base.selectdim(f::T, dir::Symbol, slice_location; kwargs...) where T<: AbstractGrid
    @debug "Generic slice fallback for AbstractGrid"
    idx = location2idx(domain_discretization(T), f, dir, slice_location; kwargs...)
    selectdim(f, dir, idx)
end

function Base.dropdims(grid::AbstractGrid; dims)
    dims = dims isa Symbol ? (dims,) : dims
    selected_dims = (setdiff(propertynames(grid),dims)...,)
    @debug "Keeping grid dims: $selected_dims"

    selected = getproperty.((grid,), selected_dims)
    if(any(isempty.(selected)))
        empty(grid)
    end
    parameterless_type(grid)(selected...; names=selected_dims)
end

function Base.hash(g::AbstractGrid, h::UInt)
    data = getdomain(g)
    typename = Symbol(typeof(g))
    hash(data, hash(typename, h))
end

function Base.:(==)(a::AbstractGrid, b::AbstractGrid)
    typeof(a) == typeof(b) && getdomain(a) == getdomain(b) && true
end

function Base.isequal(a::AbstractGrid, b::AbstractGrid)
    d1 = getdomain(a)
    d2 = getdomain(b)
    t1 = typeof(a)
    t2 = typeof(b)
    isequal(t1, t2) && isequal(d1, d2) && true
end


text:
function parametric_sample(
    N::Int64,
    sample_fraction::Float64,
    bins::Vector{Int64},
    dist::Distributions.DiscreteNonParametric
    )
    W = dist.p
    K = size(W, 1)
    n_sample = rand(
        Distributions.DiscreteNonParametric(collect(1:K), W),
        Int(floor(sample_fraction * N)),
    )
    #check if each n_sample exists in bins, in case sample another one
    for n = 1:size(n_sample, 1)
        ns = copy(n_sample[n])
        while size(findall(bins .== ns), 1) == 0
            # if n_sample[n] > (K / 2)
            #     ns -= 1
            # else
            #     ns += 1
            # end
            ns = rand(Distributions.DiscreteNonParametric(collect(1:K), W),1)
        end
        n_sample[n] = copy(ns[1])
    end
    return n_sample::Vector{Int64}
end

function non_parametric_sample(
    N::Int64,
    sample_fraction::Float64
)
    return Distributions.sample(
        collect(1:N),
        Int(ceil(sample_fraction * N)),
        replace = true
    )
end


text:
###############################################################
# Types
###############################################################

"""
Type representing a first-order tensor
"""
struct VectorValue{D,T} <: MultiValue{Tuple{D},T,1,D}
    data::NTuple{D,T}
    function VectorValue{D,T}(data::NTuple{D,T}) where {D,T}
        new{D,T}(data)
    end
end

###############################################################
# Constructors (VectorValue)
###############################################################

# Empty VectorValue constructor

VectorValue()                   = VectorValue{0,Int}(NTuple{0,Int}())
VectorValue{0}()                = VectorValue{0,Int}(NTuple{0,Int}())
VectorValue{0,T}() where {T}    = VectorValue{0,T}(NTuple{0,T}())
VectorValue(data::NTuple{0})    = VectorValue{0,Int}(data)
VectorValue{0}(data::NTuple{0}) = VectorValue{0,Int}(data)

# VectorValue single NTuple argument constructor

VectorValue(data::NTuple{D,T})        where {D,T}     = VectorValue{D,T}(data)
VectorValue{D}(data::NTuple{D,T})     where {D,T}     = VectorValue{D,T}(data)
VectorValue{D,T1}(data::NTuple{D,T2}) where {D,T1,T2} = VectorValue{D,T1}(NTuple{D,T1}(data))

VectorValue{D}(data::NTuple{D2,T2}) where {D,D2,T2} = @unreachable
VectorValue{D1,T1}(data::NTuple{D2,T2}) where {D1,T1,D2,T2} = @unreachable

# VectorValue single Tuple argument constructor

VectorValue(data::Tuple)                    = VectorValue(promote(data...))
VectorValue{D}(data::Tuple)    where {D}    = VectorValue{D}(promote(data...))
VectorValue{D,T1}(data::Tuple) where {D,T1} = VectorValue{D,T1}(NTuple{D,T1}(data))

# VectorValue Vararg constructor

VectorValue(data...)                    = VectorValue(data)
VectorValue{D}(data...)    where {D}    = VectorValue{D}(data)
VectorValue{D,T1}(data...) where {D,T1} = VectorValue{D,T1}(data)

# Fix for julia 1.0.4
VectorValue{D}(data::T...)    where {D,T}    = VectorValue{D,T}(data)

# VectorValue single AbstractVector argument constructor

VectorValue(data::AbstractArray{T}) where {T}              = (D=length(data);VectorValue(NTuple{D,T}(data)))
VectorValue{D}(data::AbstractArray{T}) where {D,T}         = VectorValue{D}(NTuple{D,T}(data))
VectorValue{D,T1}(data::AbstractArray{T2}) where {D,T1,T2} = VectorValue{D,T1}(NTuple{D,T1}(data))

###############################################################
# Conversions (VectorValue)
###############################################################

# Direct conversion
convert(::Type{<:VectorValue{D,T}}, arg:: AbstractArray) where {D,T} = VectorValue{D,T}(NTuple{D,T}(arg))
convert(::Type{<:VectorValue{D,T}}, arg:: Tuple) where {D,T} = VectorValue{D,T}(arg)

# Inverse conversion
convert(::Type{<:SVector{D,T}}, arg::VectorValue{D}) where {D,T} = SVector{D,T}(Tuple(arg))
convert(::Type{<:MVector{D,T}}, arg::VectorValue{D}) where {D,T} = MVector{D,T}(Tuple(arg))
convert(::Type{<:NTuple{D,T}},  arg::VectorValue{D}) where {D,T} = NTuple{D,T}(Tuple(arg))

# Internal conversion
convert(::Type{<:VectorValue{D,T}}, arg::VectorValue{D}) where {D,T} = VectorValue{D,T}(Tuple(arg))
convert(::Type{<:VectorValue{D,T}}, arg::VectorValue{D,T}) where {D,T} = arg

###############################################################
# Other constructors and conversions (VectorValue)
###############################################################

zero(::Type{<:VectorValue{D,T}}) where {D,T} = VectorValue{D,T}(tfill(zero(T),Val{D}()))
zero(::VectorValue{D,T}) where {D,T} = zero(VectorValue{D,T})

Mutable(::Type{VectorValue{D,T}}) where {D,T} = MVector{D,T}
Mutable(::VectorValue{D,T}) where {D,T} = Mutable(VectorValue{D,T})
mutable(a::VectorValue) = MVector(a.data)

change_eltype(::Type{VectorValue{D}},::Type{T}) where {D,T} = VectorValue{D,T}
change_eltype(::Type{VectorValue{D,T1}},::Type{T2}) where {D,T1,T2} = VectorValue{D,T2}
change_eltype(::VectorValue{D,T1},::Type{T2}) where {D,T1,T2} = change_eltype(VectorValue{D,T1},T2)

get_array(arg::VectorValue{D,T}) where {D,T} = convert(SVector{D,T}, arg)

###############################################################
# Introspection (VectorValue)
###############################################################

eltype(::Type{<:VectorValue{D,T}}) where {D,T} = T
eltype(arg::VectorValue{D,T}) where {D,T} = eltype(VectorValue{D,T})

size(::Type{<:VectorValue{D}}) where {D} = (D,)
size(::VectorValue{D}) where {D}  = size(VectorValue{D})

length(::Type{<:VectorValue{D}}) where {D} = D
length(::VectorValue{D}) where {D} = length(VectorValue{D})

num_components(::Type{<:VectorValue{D}}) where {D} = length(VectorValue{D})
num_components(::VectorValue{D}) where {D} = num_components(VectorValue{D})


text:
using PyPlot

ind(v::AbstractVector{T}, a::U) where {T<:Number,U<:Number} = argmin(abs.(v .- a))

function upsample(v::AbstractVector, fac::Int,
                  do_plot::Bool = false)
    dv = v[2]-v[1]
    all(abs.(diff(v) - dv)/abs(dv) .<= 1e-6) || error("Not equal spacing between all elements")
    ndv = dv/fac
    nv = v[1]:ndv:v[end]+0.9ndv

    if do_plot
        figure("upsample")
        clf()
        subplot(311)
        plot(v, v, "s-")
        plot(nv, nv, ".")
        axis([0.9v[1], 1.1v[10], 0.9v[1], 1.1v[10]])
        subplot(312)
        plot(v, v, "s-")
        plot(nv, nv, ".")
        axis([0.9v[end-10], 1.1v[end], 0.9v[end-10], 1.1v[end]])
        subplot(313)
        semilogy(abs(v-nv[1:fac:length(nv)]))
    end

    nsel = filter(eachindex(nv)) do i
        !(i in 1:fac:length(nv))
    end
    nv, nv[nsel]
end

function log_upsample(v::AbstractVector, fac::Int)
    nv,nvv = upsample(log.(v), fac)
    exp.(nv),exp.(nvv)
end

meshgrid(x::AbstractVector,y::AbstractVector) =
    repeat(x', outer=(length(y),1)),repeat(y, outer=(1,length(x)))

export ind, upsample, log_upsample, meshgrid


text:
module HaloMF
using Dierckx
export tinker08MF, tinker10MF
export bocquetMFhy, bocquetMFdm
export psMF, stMF, jenkinsMF
include("tinkerMF.jl")
include("bocquetMF.jl")
include("classicMF.jl")
end # module


text:
import Random: MersenneTwister

"""
    generate_porous_structure(outline,material,between_buffer;log=false)

Workhorse of CircGeometry.jl. This function takes in an outline,
a material, and a between buffer percentage, and launches the
algorithm to fill in the outline with filling circles.
"""
function generate_porous_structure(outline::O,material::MaterialParameters{T},between_buffer;log=false) where {O<:AbstractOutlineObject,T<:Real}
    check_vf(material.expected_volume_fraction)

    ideal_radius = compute_ideal_radius(outline,material)

    rng = MersenneTwister()
    radiiArr = create_radiiArr(ideal_radius,rng,material.n_objects,outline)
    ps = PorousStructure(material,radiiArr,between_buffer)

    placement = PlacementStatus()

    for ti=1:material.n_objects
        reset_placement!(placement)

        while !(placement.safe_placement)
            if log; print('\r',"attempting to place body #",ti,"/",ps.param.n_objects," ..."); end
            ps.xArr[ti],ps.yArr[ti] = choose_random_center(outline,rng)
            copyArraysToCenters!(ps,ti)

            is_safe_placement!(placement,ti,ps,outline)

            n_shuffles = 10
            if placement.marked_for_shuffling
                for i=1:n_shuffles
                    shuffle_object!(ti,ps.olist,outline.wlist)
                end
                copyCentersToArrays!(ps::PorousStructure)
            end

            is_safe_placement!(placement,ti,ps,outline)

            if placement.attempt_ind > material.n_objects*100
                error("reached attempt threshold while trying to place body #$(ti)")
            end

            update_attempt!(placement)
        end
    end

    if log
        computed_vf = compute_volume_fraction(ps,outline)
        println()
        println("entered volume fraction:  ",ps.param.expected_volume_fraction)
        println("computed volume fraction: ",round(computed_vf,digits=3))
    end

    return ps
end

"""
    compute_between_buffer(outline,material)

This is a 'smart' algorithm for choosing the between_buffer so that
the filling objects are more equally-spaced within the outline object.
"""
function compute_between_buffer(outline::O,material::MaterialParameters{T}) where {T<:Real,O<:AbstractOutlineObject}
    θstar = choose_θstar(material.expected_volume_fraction)
    ideal_radius = compute_ideal_radius(outline,material)
    area = compute_outline_area(outline)

    between_buffer = 100*(sqrt(area * θstar / (ideal_radius^2*pi*material.n_objects)) - one(T))

    return maximum([between_buffer,1])
end

"""
    compute_volume_fraction(ps,outline)

Computes the actual volume fraction from a completed PorousStructure object within
an outline object.
"""
function compute_volume_fraction(ps::PorousStructure,outline::O) where O<:AbstractOutlineObject
    true_area = compute_outline_area(outline)
    exp_area = 0.0
    for ti=1:ps.param.n_objects
        exp_area += 4*ps.olist[ti].radius^2
    end

    return exp_area/true_area
end

function is_safe_placement!(placement,ti,ps,outline)
    placement.inside = is_inside_outline(ps.olist[ti],outline)
    placement.intersection_others = is_intersecting_others(ti,ps)
    placement.intersection_walls = is_intersecting_walls(outline,ps.olist[ti])
    placement.safe_placement = placement.inside && !(placement.intersection_others) && !(placement.intersection_walls)
    placement.marked_for_shuffling = placement.inside && placement.intersection_others
    nothing
end

function choose_θstar(expected_volume_fraction::T) where T<:Real
    if expected_volume_fraction < 0.1
        return 3*expected_volume_fraction
    elseif expected_volume_fraction < 0.2
           return 2*expected_volume_fraction
    elseif expected_volume_fraction < 0.3
        return expected_volume_fraction + 0.1
    elseif expected_volume_fraction < 0.5
        return expected_volume_fraction + 0.05
    elseif expected_volume_fraction > 0.6
        return expected_volume_fraction
    else
        return maximum([0.4,expected_volume_fraction+0.05])
    end
end

function compute_ideal_radius(outline::O,material::MaterialParameters{T}) where {T<:Real,O<:AbstractOutlineObject}
    area = compute_outline_area(outline)
    return sqrt(area * material.expected_volume_fraction / (pi*material.n_objects))
end

function create_radiiArr(ideal_radius::T,rng,n_objects::Int,outline::OutlineCircle{T}) where T<:Real
    radiiArr = ideal_radius*(0.7*rand(rng,n_objects) .+ 0.505)
    return sort(radiiArr, rev=true)
end
function create_radiiArr(ideal_radius::T,rng,n_objects::Int,outline::OutlineRectangle{T}) where T<:Real
    radiiArr = ideal_radius*(0.7*rand(rng,n_objects) .+ 0.505)
    return sort(radiiArr, rev=true)
end
function create_radiiArr(ideal_radius::T,rng,n_objects::Int,outline::OutlinePolygon{T}) where T<:Real
    radiiArr = ideal_radius*(0.7*rand(rng,n_objects) .+ 0.519)
    return sort(radiiArr, rev=true)
end

function choose_random_center(outline::OutlineCircle{T},rng) where T<:Real
    x = outline.radius*(2*rand(rng) - one(T)) + outline.center.x
    y = outline.radius*(2*rand(rng) - one(T)) + outline.center.y
    return x,y
end
function choose_random_center(outline::OutlineRectangle{T},rng) where T<:Real
    length = outline.p2.x - outline.p1.x
    width  = outline.p2.y - outline.p1.y
    x = length*rand(rng) + outline.p1.x
    y = width*rand(rng) + outline.p1.y
    return x,y
end
function choose_random_center(outline::OutlinePolygon{T},rng) where T<:Real
    length = outline.p2_bound.x - outline.p1_bound.x
    width  = outline.p2_bound.y - outline.p1_bound.y
    x = length*rand(rng) + outline.p1_bound.x
    y = width*rand(rng) + outline.p1_bound.y
    return x,y
end

function is_intersecting_others(ind::Int,ps::PorousStructure)
    if ind > 1
        for ti = 1:(ind-1)
            is_intersecting = is_circle1_intersecting_circle2(ps.olist[ind],ps.olist[ti])
            if is_intersecting == true
                return true
            end
        end
    end

    return false
end

function is_circle1_intersecting_circle2(fo1::F,fo2::F) where F<:FillingCircle
    distance = sqrt((fo2.center.x - fo1.center.x)^2 + (fo2.center.y - fo1.center.y)^2)
    upper_limit = (1 + (fo1.buffer_percent + fo2.buffer_percent)/100)*(fo1.radius + fo2.radius)
    return (distance < upper_limit ? true : false)
end

function compute_outline_area(outline::OutlineCircle{T}) where T<:Real
    return pi*(outline.radius)^2
end
function compute_outline_area(outline::OutlineRectangle{T}) where T<:Real
    return (outline.p2.x - outline.p1.x)*(outline.p2.y - outline.p1.y)
end
function compute_outline_area(outline::OutlinePolygon{T}) where T<:Real
    n_points = length(outline.pList)
    area = zero(T)
    # first n_points segments (out of n_points + 1 total)
    for ti=1:(n_points-1)
        x0 = outline.pList[ti].x;   y0 = outline.pList[ti].y
        x1 = outline.pList[ti+1].x; y1 = outline.pList[ti+1].y

        area += x0*y1 - x1*y0
    end
    # last segment
    x0 = outline.pList[n_points].x;   y0 = outline.pList[n_points].y
    x1 = outline.pList[1].x; y1 = outline.pList[1].y
    area += x0*y1 - x1*y0

    return abs(area)/2
end

function check_vf(volume_fraction)
    if volume_fraction > 0.8
        error(
            "circle packing with volume_fraction = ",
            volume_fraction," is theoretically impossible")
    elseif volume_fraction > 0.7
        @warn string(
            "circle packing with volume_fraction = ",
            volume_fraction," is unlikely")
    end
end

function copyArraysToCenters!(ps::PorousStructure)
    for ti=1:ps.param.n_objects
        ps.olist[ti].center.x = ps.xArr[ti]
        ps.olist[ti].center.y = ps.yArr[ti]
    end
    nothing
end
function copyArraysToCenters!(ps::PorousStructure,ind::Int)
    ps.olist[ind].center.x = ps.xArr[ind]
    ps.olist[ind].center.y = ps.yArr[ind]
    nothing
end

function copyCentersToArrays!(ps::PorousStructure)
    for ti=1:ps.param.n_objects
        ps.xArr[ti] = ps.olist[ti].center.x
        ps.yArr[ti] = ps.olist[ti].center.y
    end
    nothing
end

max_stars_repo_name: pseastham/CircGeometry

max_issues_repo_name: pseastham/CircGeometry


text:
using DataFrames
using GLM
#using Plots
using RegressionDiscontinuity
using Test

Zs = randn(1000)

ZsR = RunningVariable(Zs, cutoff = 0.0)
Zsgeg0 = RunningVariable(Zs, cutoff = 1.0)
Zsless0 = RunningVariable(Zs, cutoff = 1.0, treated = :<)
@test all(xor.(Zsgeg0.Ws + Zsless0.Ws) .== 1)

tmp_df = DataFrame(Ws = ZsR.Ws, Zs = ZsR.Zs, ZsC = ZsR.ZsC)
@test Tables.schema(tmp_df) == Tables.schema(ZsR)

Ys = rand(1000)
rdd_data = RegressionDiscontinuity.RDData(Ys, ZsR)
myfit = fit(LinearModel, @formula(Ys ~ Zs + Ws), rdd_data)


text:
export plan_chebyshevtransform, plan_ichebyshevtransform, chebyshevtransform, ichebyshevtransform

## Transforms take values at Chebyshev points of the first and second kinds and produce Chebyshev coefficients

#TODO confirm that this can handle T=Complex{Float64} looks like this is a real-to-real transform

function plan_chebyshevtransform{T<:FFTW.fftwNumber}(x::Vector{T};kind::Integer=1)
    if kind == 1
        FFTW.plan_r2r(x, FFTW.REDFT10)
    elseif kind == 2
        FFTW.plan_r2r(x, FFTW.REDFT00)
    end
end

function chebyshevtransform{T<:FFTW.fftwNumber}(x::Vector{T},plan;kind::Integer=1)
    if kind == 1
        n = length(x)
        if n == 1
            x
        else
            ret=negateeven!(plan*x)
            ret[1]/=2
            ret/=n
        end
    elseif kind == 2
        n = length(x)
        if n == 1
            x
        else
            ret = plan*x
            ret[1] /= 2;ret[end] /= 2
            negateeven!(ret)./(n-1)
        end
    end
end
chebyshevtransform{T<:FFTW.fftwNumber}(x::Vector{T};kind::Integer=1)=chebyshevtransform(x,plan_chebyshevtransform(x;kind=kind);kind=kind)

## Inverse transforms take Chebyshev coefficients and produce values at Chebyshev points of the first and second kinds

function plan_ichebyshevtransform{T<:FFTW.fftwNumber}(x::Vector{T};kind::Integer=1)
    if kind == 1
        FFTW.plan_r2r(x, FFTW.REDFT01)
    elseif kind == 2
        FFTW.plan_r2r(x, FFTW.REDFT00)
    end
end

function ichebyshevtransform{T<:FFTW.fftwNumber}(x::Vector{T},plan;kind::Integer=1)
    if kind == 1
        x[1] *=2
        ret = plan*negateeven!(x)/2
        negateeven!(x)
        x[1]/=2
        ret
    elseif kind == 2
        n = length(x)
        if n == 1
            x
        else
            ##TODO: make thread safe
            x[1] *= 2;x[end] *= 2
            ret = chebyshevtransform(x,plan;kind=kind)
            x[1] /=2;x[end] /=2
            ret[1] *= 2;ret[end] *= 2
            negateeven!(ret)
            ret *= .5*(n-1)
            reverse!(ret)
        end
    end
end
ichebyshevtransform{T<:FFTW.fftwNumber}(x::Vector{T};kind::Integer=1)=ichebyshevtransform(x,plan_ichebyshevtransform(x;kind=kind);kind=kind)

## Code generation for integer inputs

for func in (:chebyshevtransform,:ichebyshevtransform)
    @eval $func{T<:Integer}(x::Vector{T};kind::Integer=1)=$func(float64(x);kind=kind)
end

# Matrix inputs

function chebyshevtransform{T<:FFTW.fftwNumber}(X::Matrix{T};kind::Integer=1)
    if kind == 1
        if size(X) == (1,1)
            X
        else
            R=negateeven!(FFTW.r2r(X,FFTW.REDFT10))
            R[:,1]/=2;R[1,:]/=2;
            R/=size(X,1)*size(X,2)
        end
    elseif kind == 2
        if size(X) == (1,1)
            X
        else
            R=FFTW.r2r(X,FFTW.REDFT00)/((size(X,1)-1)*(size(X,2)-1))
            R[:,1]/=2;R[:,end]/=2
            R[1,:]/=2;R[end,:]/=2
            negateeven!(R)
        end
    end
end

function ichebyshevtransform{T<:FFTW.fftwNumber}(X::Matrix{T};kind::Integer=1)
    if kind == 1
        if size(X) == (1,1)
            X
        else
            X[1,:]*=2;X[:,1]*=2
            R = FFTW.r2r(negateeven!(X),FFTW.REDFT01)/4
            negateeven!(X)
            X[1,:]/=2;X[:,1]/=2
            R
        end
    elseif kind == 2
        if size(X) == (1,1)
            X
        else
            X[1,:]*=2;X[end,:]*=2;X[:,1]*=2;X[:,end]*=2
            R=chebyshevtransform(X;kind=kind)
            X[1,:]/=2;X[end,:]/=2;X[:,1]/=2;X[:,end]/=2
            R[1,:]*=2;R[end,:]*=2;R[:,1]*=2;R[:,end]*=2
            negateeven!(R)
            R*=(size(X,1)-1)*(size(X,2)-1)/4
            flipud(fliplr(R))
        end
    end
end

# Helper routines

function negateeven!(x::Vector)
    for k =2:2:length(x)
        x[k] = -x[k]
    end
    x
end

#checkerboard, same as applying negativeeven! to all rows then all columns
function negateeven!(X::Matrix)
    for k =2:2:size(X,1),j=1:2:size(X,2)
        X[k,j] *= -1
    end
    for k =1:2:size(X,1),j=2:2:size(X,2)
        X[k,j] *= -1
    end
    X
end


text:
module EGraphs

# Write your package code here.
export EGraph, constant!, term!, rebuild!, find_root!, PatVar, PatTerm, ematch, Id, Rule, rewrite!, graphplot, in_same_set

include("types.jl")
include("ops.jl")
include("utils.jl")
include("matcher.jl")
end


text:
#=
Expanding the interval width until there is a sign change between the insterval.
=#

function bracket_sign_change(f′, a, b; k=2)
    if a > b; a, b = b, a; end
    center, half_width = (a+b)/2, (b-a)/2;
    while f′(a) * f′(b) > 0
        half_width *= k;
        a = center - half_width;
        b = center + half_width;
    end
    return (a, b);
end


text:
module JSON3

using Parsers, Mmap, UUIDs, Dates, StructTypes

"""An immutable (read only) struct which provides an efficient view of a JSON object. Supports the `AbstractDict` interface. See [built in types](#Builtin-types) for more detail on why we have an `Object` type."""
struct Object{S <: AbstractVector{UInt8}, TT <: AbstractVector{UInt64}} <: AbstractDict{Symbol, Any}
    buf::S
    tape::TT
    inds::Dict{Symbol, Int}
end

Object() = Object(codeunits(""), UInt64[object(Int64(2)), 0], Dict{Symbol, Int}())

"""An immutable (read only) struct which provides an efficient view of a JSON array. Supports the `AbstractArray` interface. See [built in types](#Builtin-types) for more detail on why we have an `Array` type."""
struct Array{T, S <: AbstractVector{UInt8}, TT <: AbstractVector{UInt64}} <: AbstractVector{T}
    buf::S
    tape::TT
    inds::Vector{Int}
end

Array{T}(buf::S, tape::TT, inds::Vector{Int}) where {T, S, TT} = Array{T, S, TT}(buf, tape, inds)

getbuf(j::Union{Object, Array}) = getfield(j, :buf)
gettape(j::Union{Object, Array}) = getfield(j, :tape)
getinds(j::Union{Object, Array}) = getfield(j, :inds)

include("utils.jl")

@noinline invalid(error, buf, pos, T) = throw(ArgumentError("""
invalid JSON at byte position $pos while parsing type $T: $error
$(String(buf[max(1, pos-25):min(end, pos+25)]))
"""))

@enum Error UnexpectedEOF ExpectedOpeningObjectChar ExpectedOpeningQuoteChar ExpectedOpeningArrayChar ExpectedClosingArrayChar ExpectedComma ExpectedSemiColon InvalidChar InvalidNumber

# AbstractDict interface
Base.length(obj::Object) = length(getinds(obj))

function populateinds!(x::Object)
    inds = getinds(x)
    buf = getbuf(x)
    tape = gettape(x)
    tapeidx = 3
    @inbounds len = getnontypemask(tape[2])
    i = 1
    while i <= len
        @inbounds t = tape[tapeidx]
        key = getvalue(Symbol, buf, tape, tapeidx, t)
        tapeidx += 2
        inds[key] = tapeidx
        @inbounds tapeidx += gettapelen(Any, tape[tapeidx])
        i += 1
    end
    return
end

function populateinds!(x::Array)
    inds = getinds(x)
    buf = getbuf(x)
    tape = gettape(x)
    tapeidx = 3
    @inbounds len = getnontypemask(tape[2])
    resize!(inds, len)
    i = 1
    while i <= len
        @inbounds inds[i] = tapeidx
        @inbounds tapeidx += gettapelen(Any, tape[tapeidx])
        i += 1
    end
    return
end

@inline function Base.iterate(obj::Object, (i, tapeidx)=(1, 3))
    i > length(obj) && return nothing
    tape = gettape(obj)
    @inbounds t = tape[tapeidx]
    key = getvalue(Symbol, getbuf(obj), tape, tapeidx, t)
    tapeidx += 2
    @inbounds t = tape[tapeidx]
    x = Pair{Symbol, Any}(key, getvalue(Any, getbuf(obj), tape, tapeidx, t))
    tapeidx += gettapelen(Any, t)
    return x, (i + 1, tapeidx)
end

function Base.get(obj::Object, key::Symbol)
    ind = getinds(obj)[key]
    tape = gettape(obj)
    @inbounds t = tape[ind]
    return getvalue(Any, getbuf(obj), tape, ind, t)
end

Base.get(obj::Object, key) = get(obj, Symbol(key))

function Base.get(obj::Object, ::Type{T}, key)::T where {T}
    return get(obj, key)
end

function Base.get(obj::Object, key::Symbol, default)
    ind = getinds(obj)
    if haskey(ind, key)
        return get(obj, key)
    else
        return default
    end
end

Base.get(obj::Object, key, default) = get(obj, Symbol(key), default)

function Base.get(obj::Object, ::Type{T}, key, default::T)::T where {T}
    return get(obj, key, default)
end

function Base.get(default::Base.Callable, obj::Object, key::Symbol)
    ind = getinds(obj)
    if haskey(ind, key)
        return get(obj, key)
    else
        return default()
    end
end

Base.get(default::Base.Callable, obj::Object, key) = get(default, obj, Symbol(key))

Base.propertynames(obj::Object) = collect(keys(obj))

Base.getproperty(obj::Object, prop::Symbol) = get(obj, prop)
Base.getindex(obj::Object, key) = get(obj, key)

"""
    copy(obj)

Recursively copy [`JSON3.Object`](@ref)s to `Dict`s and [`JSON3.Array`](@ref)s to `Vector`s.  This copy can then be mutated if needed.
"""
function Base.copy(obj::Object)
    dict = Dict{Symbol, Any}()
    for (k, v) in obj
        dict[k] = v isa Object || v isa Array ? copy(v) : v
    end
    return dict
end

# AbstractArray interface
Base.IndexStyle(::Type{<:Array}) = Base.IndexLinear()

Base.size(arr::Array) = (length(getinds(arr)),)

function Base.iterate(arr::Array{T}, (i, tapeidx)=(1, 3)) where {T}
    i > length(arr) && return nothing
    tape = gettape(arr)
    @inbounds t = tape[tapeidx]
    val = getvalue(T, getbuf(arr), tape, tapeidx, t)
    tapeidx += gettapelen(T, t)
    return val, (i + 1, tapeidx)
end

@inline Base.@propagate_inbounds function Base.getindex(arr::Array{T}, i::Int) where {T}
    @boundscheck checkbounds(arr, i)
    tape = gettape(arr)
    buf = getbuf(arr)
    @inbounds ind = getinds(arr)[i]
    @inbounds t = tape[ind]
    return getvalue(T, buf, tape, ind, t)
end

Base.copy(arr::Array) = map(x->x isa Object || x isa Array ? copy(x) : x, arr)

include("read.jl")
include("strings.jl")
include("show.jl")
include("structs.jl")
include("write.jl")
include("pretty.jl")
include("gentypes.jl")

end # module


text:
# This is the interface to the JPL ephemerides for use with eph_manager
# The origin of the source here is `solsys1.c`, as that is what is bundled with pyNOVAS

function planet_ephemeris(tjd::AbstractVector, target, center) end

"""
    solarsystem(tjd,body)

Provides an interface between the JPL direct-access solar system ephemerides and NOVAS

# Arguments
- `tjd::Real`:Julian date of the desired time, on the TDB time scale
- `body::Int`: Body identification number

# Optional Arguments
- `origin::Symbol=:barycenter`: The originof calculations, solar system `:barycenter`, the center of mass of the `:sun`, or the center of the `:earth`.

# Returns
`(pos,vel)` where
- `pos`: Position vector of `body` at `tjd` in AU
- `vel`: Velocity vector of `body` at `tdj` in AU/day
"""
function solarsystem(tjd::Real, body::Int; origin::Symbol=:barycenter)
    # Perform sanity checks
    @assert 1 <= body <= 11 "Illegal body id"
    @assert origin ∈ Set([:barycenter, :sun, :earth])
end


text:
using Mocha

############################################################
# This is an example script for training a fully connected
# network with dropout on mnist.
#
# The network size is 784-1200-1200-10 with ReLU units
# in the hidden layers and a softmax output layer.
# The parameters for training the network were chosen
# to reproduce the results from the original dropout paper:
# http://arxiv.org/abs/1207.0580
# and the corresponding newer JMLR paper:
# http://jmlr.org/papers/volume15/srivastava14a/srivastava14a.pdf
#
# Our parameters slightly differ. This is mainly due to the
# fact that in the original dropout paper the weights are scaled
# by 0.5 after training whereas we scale them by 2 during training.
#
# The settings in this script should currently produce a model that
# gets 94 errors (or 99.06 % accuracy) on the test set
# if you run it for the whole 2000 epochs (=600*2000 steps).
# This is slightly better than the results of the JMLR paper.
# This difference is likely due to slight differences in the
# learning parameters. Also note that our hyperparameters
# are not chosen using a validation set, as one would do
# for a paper. If your hardware and cuda versions differ
# from the setup we used for intial testing your results might
# also slightly vary due to floating point inaccuracies.
############################################################

# fix the random seed to make results reproducable
srand(12345678)

data_layer  = AsyncHDF5DataLayer(name="train-data", shuffle=true, source="data/train.txt", batch_size=100)
# each fully connected layer uses a ReLU activation and a constraint on the L2 norm of the weights
fc1_layer   = InnerProductLayer(name="fc1", output_dim=1200, neuron=Neurons.ReLU(),
                                weight_init = GaussianInitializer(std=0.01),
                                #weight_cons = L2Cons(4.5),
                                bottoms=[:data], tops=[:fc1])
fc2_layer   = InnerProductLayer(name="fc2", output_dim=1200, neuron=Neurons.ReLU(),
                                weight_init = GaussianInitializer(std=0.01),
                                weight_cons = L2Cons(4.5),
                                bottoms=[:fc1], tops=[:fc2])
fc3_layer   = InnerProductLayer(name="out", output_dim=10, bottoms=[:fc2],
                                weight_init = ConstantInitializer(0),
                                weight_cons = L2Cons(4.5),
                                tops=[:out])
loss_layer  = SoftmaxLossLayer(name="loss", bottoms=[:out,:label])

# setup dropout for the different layers
# we use 20% dropout on the inputs and 50% dropout in the hidden layers
# as these values were previously found to be good defaults
drop_input  = DropoutLayer(name="drop_in", bottoms=[:data], ratio=0.2)
drop_fc1 = DropoutLayer(name="drop_fc1", bottoms=[:fc1], ratio=0.5)
drop_fc2  = DropoutLayer(name="drop_fc2", bottoms=[:fc2], ratio=0.5)

backend = DefaultBackend()
init(backend)

common_layers = [fc1_layer, fc2_layer, fc3_layer]
drop_layers = [drop_input, drop_fc1, drop_fc2]
# put training net together, note that the correct ordering will automatically be established by the constructor
net = Net("MNIST-train", backend, [data_layer, common_layers..., drop_layers..., loss_layer])

base_dir = "snapshots_dropout_ft-$(Mocha.default_backend_type)"
# we let the learning rate decrease by 0.998 in each epoch (=600 batches of size 100)
# and let the momentum increase linearly from 0.5 to 0.9 over 500 epochs
# which is equivalent to an increase step of 0.0008
# training is done for 2000 epochs
method = SGD()
params = make_solver_parameters(method, max_iter=600*2000, regu_coef=0.0,
                          mom_policy=MomPolicy.Linear(0.5, 0.0008, 600, 0.9),
                          lr_policy=LRPolicy.Step(0.1, 0.998, 600),
                          load_from=base_dir)
solver = Solver(method, params)

setup_coffee_lounge(solver, save_into="$base_dir/statistics.jld", every_n_iter=5000)

# report training progress every 100 iterations
add_coffee_break(solver, TrainingSummary(), every_n_iter=100)

# save snapshots every 5000 iterations
add_coffee_break(solver, Snapshot(base_dir), every_n_iter=5000)

# show performance on test data every 600 iterations (one epoch)
data_layer_test = AsyncHDF5DataLayer(name="test-data", source="data/test.txt", batch_size=100)
acc_layer = AccuracyLayer(name="test-accuracy", bottoms=[:out, :label], report_error=true)
test_net = Net("MNIST-test", backend, [data_layer_test, common_layers..., acc_layer])
add_coffee_break(solver, ValidationPerformance(test_net), every_n_iter=600)

solve(solver, net)

#Profile.init(int(1e8), 0.001)
#@profile solve(solver, net)
#open("profile.txt", "w") do out
#  Profile.print(out)
#end

destroy(net)
destroy(test_net)
shutdown(backend)


text:
#=
Matrix Norms
------------

Many different matrix norms with different numerical values for the same matrix

3 main types of Matrix Norms
----------------------------

1) Frobenius norm aka Euclidian Norm

Square all individual matrix elements,
add them together
take square root

=#
A = [1 2 3;4 5 6;7 8 9]
# naive implementation
frobnorm1(A) = sqrt(reduce(+, (map(x -> x^2, A))))

## (defn frobnorm [A]
##   (Math/sqrt (reduce + (map #(* % %) A))))

# more efficient ways using LinearAlgebra package

using LinearAlgebra

frobnorm2(A) = sqrt(tr(A' * A))

frobnorm3(A) = norm(A) # default in Julia
#=

2) Induced 2-norm - ascertains how much matrix A scales vector x

the magnitude of vector Ax (A matrix multiplied by vector x results in a vector),
divided by the magnitude of vector x

(where x is not a zero vector)

||Ax|| / ||x||
=#

twonorm(A,x) = norm(A * x) / norm(x)

normInd2(A) = sqrt(eigmax(A' * A))

# if A is a pure rotation matrix, then ||Ax|| would be equal to ||x||
# so the induced two-norm would be 1

#=
3) Schatten P-norm
Sum of the singluar values of a matrix

Singluar values is a set of scalar values associated with a matrix.

Singular Value Decomposition determines these values

=#

p = 1 # Schatten 1-norm
s = svdvals(A) # extracts singular values into a vector
normSchat = sum(s.^p)^(1/p)

p = 2 # same as Frobenius norm
normSchat = sum(s.^p)^(1/p)

#= Orthogonal Matrix
   -----------------

All the columns have a magnitude of 1, and each column is par-wise orthogonal to every other column

This can be a purely rotational matrix, so the induced 2-norm is 1

Can be extracted as the Q matrix of the pair from QR Decomposition
=#

Q, R = qr(randn(5,5))

# induced 2-norm = 1
ind2norm = sqrt(eigmax(Q' * Q))

max_stars_repo_path: linear-algebra-code-challenges/Lecture 60 - Matrix Norms.jl

max_stars_repo_name: jawuku/julia

max_issues_repo_name: jawuku/julia

max_forks_repo_name: jawuku/julia


text:
# Window partition.

mutable struct PartitionNode <: TabularNode
    over::Union{SQLNode, Nothing}
    by::Vector{SQLNode}
    order_by::Vector{SQLNode}
    frame::Union{PartitionFrame, Nothing}

    PartitionNode(; over = nothing, by = SQLNode[], order_by = SQLNode[], frame = nothing) =
        new(over, by, order_by, frame)
end

PartitionNode(by...; over = nothing, order_by = SQLNode[], frame = nothing) =
    PartitionNode(over = over, by = SQLNode[by...], order_by = order_by, frame = frame)

"""
    Partition(; over, by = [], order_by = [], frame = nothing)
    Partition(by...; over, order_by = [], frame = nothing)

The `Partition` node specifies how to relate each row to the adjacent rows
in the same dataset.  Aggregate functions applied to the output of `Partition`
summarize the values of the related rows.

```sql
SELECT ...
FROM \$over
WINDOW w AS (PARTITION BY \$by... ORDER BY \$order_by...)
```

# Examples

```jldoctest
julia> person = SQLTable(:person, columns = [:person_id, :year_of_birth]);

julia> q = From(person) |>
           Partition(Get.year_of_birth) |>
           Select(Get.year_of_birth, Agg.row_number());

julia> print(render(q))
SELECT
  "person_1"."year_of_birth",
  (ROW_NUMBER() OVER (PARTITION BY "person_1"."year_of_birth")) AS "row_number"
FROM "person" AS "person_1"
```

```jldoctest
julia> person = SQLTable(:person, columns = [:person_id, :year_of_birth]);

julia> q = From(person) |>
           Group(Get.year_of_birth) |>
           Partition(order_by = [Get.year_of_birth],
                     frame = (mode = :range, start = -1, finish = 1)) |>
           Select(Get.year_of_birth, Agg.avg(Agg.count()));

julia> print(render(q))
SELECT
  "person_1"."year_of_birth",
  (AVG(COUNT(*)) OVER (ORDER BY "person_1"."year_of_birth" RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING)) AS "avg"
FROM "person" AS "person_1"
GROUP BY "person_1"."year_of_birth"
```
"""
Partition(args...; kws...) =
    PartitionNode(args...; kws...) |> SQLNode

dissect(scr::Symbol, ::typeof(Partition), pats::Vector{Any}) =
    dissect(scr, PartitionNode, pats)

function PrettyPrinting.quoteof(n::PartitionNode, ctx::QuoteContext)
    ex = Expr(:call, nameof(Partition), quoteof(n.by, ctx)...)
    if !isempty(n.order_by)
        push!(ex.args, Expr(:kw, :order_by, Expr(:vect, quoteof(n.order_by, ctx)...)))
    end
    if n.frame !== nothing
        push!(ex.args, Expr(:kw, :frame, quoteof(n.frame)))
    end
    if n.over !== nothing
        ex = Expr(:call, :|>, quoteof(n.over, ctx), ex)
    end
    ex
end

label(n::PartitionNode) =
    label(n.over)

rebase(n::PartitionNode, n′) =
    PartitionNode(over = rebase(n.over, n′), by = n.by, order_by = n.order_by, frame = n.frame)


text:
using AxisArrays
using Dates
using Test
using Random
import IterTools

@testset "AxisArrays" begin
    VERSION >= v"1.1" && @test isempty(detect_ambiguities(AxisArrays, Base, Core))

    @testset "Core" begin
        include("core.jl")
    end

    @testset "Intervals" begin
        include("intervals.jl")
    end

    @testset "Indexing" begin
        include("indexing.jl")
    end

    @testset "SortedVector" begin
        include("sortedvector.jl")
    end

    @testset "CategoricalVector" begin
        include("categoricalvector.jl")
    end

    @testset "Search" begin
        include("search.jl")
    end

    @testset "Combine" begin
        include("combine.jl")
    end

    @testset "README" begin
        include("readme.jl")
    end
end


text: sort!(A, alg=QuickSort)

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
using Sole
using Documenter

DocMeta.setdocmeta!(Sole, :DocTestSetup, :(using Sole); recursive=true)

makedocs(;
    modules=[Sole],
    authors="Eduard I. STAN, Giovanni PAGLIARINI",
    repo="https://github.com/aclai-lab/Sole.jl/blob/{commit}{path}#{line}",
    sitename="Sole.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://aclai-lab.github.io/Sole.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
    ],
)

deploydocs(;
    repo="github.com/aclai-lab/Sole.jl",
)