text:
export ComptonKleinNishina, sample
struct ComptonKleinNishina end

function cross_section_per_atom(::ComptonKleinNishina, Z, E)

end

function dσ_dθ(::ComptonKleinNishina, Z, E)

end

function differential_cross_section_per_atom(::ComptonKleinNishina,
                                         Z, E, energy_ratio)
end

"""
    compton_formula(E0::UF.Energy, theta)

Compute energy of scattered photon.

* `E0`: Energy of primary photon.
* `theta`: scattering angle
"""
function compton_formula(E0::UF.Energy, theta)
    mec2 = electron_rest_energy
    E0 * mec2 / (mec2 + E0 * (1-cos(theta)))
end

function rejection_function(eps, sintheta2)
    ret = 1 - (eps / (1 + eps^2))*sintheta2
end

function sample_buggy(rng::AbstractRNG, ::ComptonKleinNishina, E0::UF.Energy)
    # composition rejection with (alpha1*f1 + alpha2*f2) * g
    E_elec = electron_rest_energy
    eps0 = uconvert(NoUnits, E_elec / (E_elec + 2*E0)) # backward scattering energy_ratio

    alpha1 = log(1/eps0)
    alpha2 = (1-eps0^2) / 2

    while true
        r1 = rand(rng)
        r2 = rand(rng)
        if r1 < alpha1 / (alpha1 + alpha2)
            eps = exp(-r2*alpha1)
        else
            eps2 = eps0^2 + r2*(1 - eps0)^2
            eps = sqrt(eps2)
        end

        # t = 1 - cos(theta)
        t = uconvert(NoUnits, E_elec*(1-eps) / (E0*eps))
        sintheta2 = t*(2-t)

        if rejection_function(eps, sintheta2) > rand(rng)
            return (energy_ratio=eps, costheta = 1-t)
        end
    end
end

function sample(rng::AbstractRNG, ::ComptonKleinNishina, E0::UF.Energy)
    E0_m = E0/electron_rest_energy
    eps0       = 1/(1 + 2*E0_m)
    alpha1     = -log(eps0)
    alpha2     = alpha1 + (1- eps0^2)/2
    while true
        if alpha1 > alpha2*rand(rng)
            eps   = exp(-alpha1*rand(rng))
        else
            eps2  = eps0^2 + (1 - eps0^2)*rand(rng)
            eps   = sqrt(eps2)
        end

        one_costheta    = uconvert(NoUnits, (1 - eps)/(eps*E0_m))
        sintheta2   = one_costheta*(2-one_costheta)
        if rand(rng) < rejection_function(eps, sintheta2)
            costheta = 1-one_costheta
            ret = (energy_ratio=eps, costheta=costheta)
            return ret
        end
    end
end


text:
module pairwise

using LinearAlgebra
using Statistics: mean
using ..utils

include("metrics.jl"); export minkowski_distance, euclidian_distance, manhattan_distance, chebyshev_distance, braycurtis_distance, canberra_distance, cityblock_distance, mahalanobis_distance,
correlation, cosine_distance, cosine_similarity

end

ext: jl


text:
@testset "SortIndex" begin
    a = [3.0, 2.0, 8.0, 3.0]
    b = accelerate(a, SortIndex)

    @test 1.0 ∉ b
    @test 2.0 ∈ b
    @test 3.0 ∈ b
    @test 4.0 ∉ b
    @test 8.0 ∈ b
    @test 9.0 ∉ b

    @test count(isequal(1.0), b) == 0
    @test count(isequal(2.0), b) == 1
    @test count(isequal(3.0), b) == 2
    @test count(isequal(4.0), b) == 0
    @test count(isequal(8.0), b) == 1
    @test count(isequal(9.0), b) == 0

    @test count(isless(1.0), b) == 0
    @test count(isless(2.0), b) == 0
    @test count(isless(3.0), b) == 1
    @test count(isless(4.0), b) == 3
    @test count(isless(8.0), b) == 3
    @test count(isless(9.0), b) == 4

    @test count(islessequal(1.0), b) == 0
    @test count(islessequal(2.0), b) == 1
    @test count(islessequal(3.0), b) == 3
    @test count(islessequal(4.0), b) == 3
    @test count(islessequal(8.0), b) == 4
    @test count(islessequal(9.0), b) == 4

    @test count(isgreater(1.0), b) == 4
    @test count(isgreater(2.0), b) == 3
    @test count(isgreater(3.0), b) == 1
    @test count(isgreater(4.0), b) == 1
    @test count(isgreater(8.0), b) == 0
    @test count(isgreater(9.0), b) == 0

    @test count(isgreaterequal(1.0), b) == 4
    @test count(isgreaterequal(2.0), b) == 4
    @test count(isgreaterequal(3.0), b) == 3
    @test count(isgreaterequal(4.0), b) == 1
    @test count(isgreaterequal(8.0), b) == 1
    @test count(isgreaterequal(9.0), b) == 0

    @test count(in(1.1..1.9), b) == 0
    @test count(in(1.1..2.1), b) == 1
    @test count(in(1.1..3.1), b) == 3
    @test count(in(2.1..3.1), b) == 2

    @test issetequal(findall(isequal(1.0), b), [])
    @test issetequal(findall(isequal(2.0), b), [2])
    @test issetequal(findall(isequal(3.0), b), [1, 4])

    @test issetequal(findall(isless(1.1), b), [])
    @test issetequal(findall(isless(2.0), b), [])
    @test issetequal(findall(isless(2.1), b), [2])
    @test issetequal(findall(isless(3.1), b), [1, 2, 4])
    @test issetequal(findall(isless(8.1), b), [1, 2, 3, 4])

    @test issetequal(findall(islessequal(1.1), b), [])
    @test issetequal(findall(islessequal(2.0), b), [2])
    @test issetequal(findall(islessequal(2.1), b), [2])
    @test issetequal(findall(islessequal(3.1), b), [1, 2, 4])
    @test issetequal(findall(islessequal(8.1), b), [1, 2, 3, 4])

    @test issetequal(findall(isgreater(1.1), b), [1, 2, 3, 4])
    @test issetequal(findall(isgreater(2.0), b), [1, 3, 4])
    @test issetequal(findall(isgreater(2.1), b), [1, 3, 4])
    @test issetequal(findall(isgreater(3.1), b), [3])
    @test issetequal(findall(isgreater(8.1), b), [])

    @test issetequal(findall(isgreaterequal(1.1), b), [1, 2, 3, 4])
    @test issetequal(findall(isgreaterequal(2.0), b), [1, 2, 3, 4])
    @test issetequal(findall(isgreaterequal(2.1), b), [1, 3, 4])
    @test issetequal(findall(isgreaterequal(3.1), b), [3])
    @test issetequal(findall(isgreaterequal(8.1), b), [])

    @test issetequal(findall(in(1.1..1.9), b), [])
    @test issetequal(findall(in(1.1..2.1), b), [2])
    @test issetequal(findall(in(1.1..3.1), b), [1, 2, 4])
    @test issetequal(findall(in(2.1..3.1), b), [1, 4])

    @test filter(isequal(1.0), b) == []
    @test filter(isequal(2.0), b) == [2.0]
    @test filter(isequal(3.0), b) == [3.0, 3.0]

    @test issetequal(filter(isless(1.1), b), [])
    @test issetequal(filter(isless(2.0), b), [])
    @test issetequal(filter(isless(2.1), b), [2.0])
    @test issetequal(filter(isless(3.1), b), [2.0, 3.0, 3.0])
    @test issetequal(filter(isless(8.1), b), [2.0, 3.0, 3.0, 8.0])

    @test issetequal(filter(islessequal(1.1), b), [])
    @test issetequal(filter(islessequal(2.0), b), [2.0])
    @test issetequal(filter(islessequal(2.1), b), [2.0])
    @test issetequal(filter(islessequal(3.1), b), [2.0, 3.0, 3.0])
    @test issetequal(filter(islessequal(8.1), b), [2.0, 3.0, 3.0, 8.0])

    @test issetequal(filter(isgreater(1.1), b), [2.0, 3.0, 3.0, 8.0])
    @test issetequal(filter(isgreater(2.0), b), [3.0, 3.0, 8.0])
    @test issetequal(filter(isgreater(2.1), b), [3.0, 3.0, 8.0])
    @test issetequal(filter(isgreater(3.1), b), [8.0])
    @test issetequal(filter(isgreater(8.1), b), [])

    @test issetequal(filter(isgreaterequal(1.1), b), [2.0, 3.0, 3.0, 8.0])
    @test issetequal(filter(isgreaterequal(2.0), b), [2.0, 3.0, 3.0, 8.0])
    @test issetequal(filter(isgreaterequal(2.1), b), [3.0, 3.0, 8.0])
    @test issetequal(filter(isgreaterequal(3.1), b), [8.0])
    @test issetequal(filter(isgreaterequal(8.1), b), [])

    @test issetequal(filter(in(1.1..1.9), b), [])
    @test issetequal(filter(in(1.1..2.1), b), [2.0])
    @test issetequal(filter(in(1.1..3.1), b), [2.0, 3.0, 3.0])
    @test issetequal(filter(in(2.1..3.1), b), [3.0, 3.0])

    @test unique(b)::AcceleratedArray{<:Any,<:Any,<:Any,<:UniqueSortIndex{<:LinearIndices}} == [2.0, 3.0, 8.0]

    @test issetequal(innerjoin(identity, identity, tuple, isequal, b, [1.5, 3.0, 8.0]),
                     innerjoin(identity, identity, tuple, isequal, a, [1.5, 3.0, 8.0]))

    c = accelerate!(a, SortIndex) # a = [2.0, 3.0, 3.0, 8.0]

    @test 1.0 ∉ c
    @test 2.0 ∈ c
    @test 3.0 ∈ c
    @test 4.0 ∉ c
    @test 8.0 ∈ c
    @test 9.0 ∉ c

    @test count(isequal(1.0), c) == 0
    @test count(isequal(2.0), c) == 1
    @test count(isequal(3.0), c) == 2
    @test count(isequal(4.0), c) == 0
    @test count(isequal(8.0), c) == 1
    @test count(isequal(9.0), c) == 0

    @test count(isless(1.0), c) == 0
    @test count(isless(2.0), c) == 0
    @test count(isless(3.0), c) == 1
    @test count(isless(4.0), c) == 3
    @test count(isless(8.0), c) == 3
    @test count(isless(9.0), c) == 4

    @test count(islessequal(1.0), c) == 0
    @test count(islessequal(2.0), c) == 1
    @test count(islessequal(3.0), c) == 3
    @test count(islessequal(4.0), c) == 3
    @test count(islessequal(8.0), c) == 4
    @test count(islessequal(9.0), c) == 4

    @test count(isgreater(1.0), c) == 4
    @test count(isgreater(2.0), c) == 3
    @test count(isgreater(3.0), c) == 1
    @test count(isgreater(4.0), c) == 1
    @test count(isgreater(8.0), c) == 0
    @test count(isgreater(9.0), c) == 0

    @test count(isgreaterequal(1.0), c) == 4
    @test count(isgreaterequal(2.0), c) == 4
    @test count(isgreaterequal(3.0), c) == 3
    @test count(isgreaterequal(4.0), c) == 1
    @test count(isgreaterequal(8.0), c) == 1
    @test count(isgreaterequal(9.0), c) == 0

    @test count(in(1.1..1.9), c) == 0
    @test count(in(1.1..2.1), c) == 1
    @test count(in(1.1..3.1), c) == 3
    @test count(in(2.1..3.1), c) == 2

    @test issetequal(findall(isequal(1.0), c), [])
    @test issetequal(findall(isequal(2.0), c), [1])
    @test issetequal(findall(isequal(3.0), c), [2, 3])

    @test issetequal(findall(isless(1.1), c), [])
    @test issetequal(findall(isless(2.0), c), [])
    @test issetequal(findall(isless(2.1), c), [1])
    @test issetequal(findall(isless(3.1), c), [1, 2, 3])
    @test issetequal(findall(isless(8.1), c), [1, 2, 3, 4])

    @test issetequal(findall(islessequal(1.1), c), [])
    @test issetequal(findall(islessequal(2.0), c), [1])
    @test issetequal(findall(islessequal(2.1), c), [1])
    @test issetequal(findall(islessequal(3.1), c), [1, 2, 3])
    @test issetequal(findall(islessequal(8.1), c), [1, 2, 3, 4])

    @test issetequal(findall(isgreater(1.1), c), [1, 2, 3, 4])
    @test issetequal(findall(isgreater(2.0), c), [2, 3, 4])
    @test issetequal(findall(isgreater(2.1), c), [2, 3, 4])
    @test issetequal(findall(isgreater(3.1), c), [4])
    @test issetequal(findall(isgreater(8.1), c), [])

    @test issetequal(findall(isgreaterequal(1.1), c), [1, 2, 3, 4])
    @test issetequal(findall(isgreaterequal(2.0), c), [1, 2, 3, 4])
    @test issetequal(findall(isgreaterequal(2.1), c), [2, 3, 4])
    @test issetequal(findall(isgreaterequal(3.1), c), [4])
    @test issetequal(findall(isgreaterequal(8.1), c), [])

    @test issetequal(findall(in(1.1..1.9), c), [])
    @test issetequal(findall(in(1.1..2.1), c), [1])
    @test issetequal(findall(in(1.1..3.1), c), [1, 2, 3])
    @test issetequal(findall(in(2.1..3.1), c), [2, 3])

    @test filter(isequal(1.0), c) == []
    @test filter(isequal(2.0), c) == [2.0]
    @test filter(isequal(3.0), c) == [3.0, 3.0]

    @test issetequal(filter(isless(1.1), c), [])
    @test issetequal(filter(isless(2.0), c), [])
    @test issetequal(filter(isless(2.1), c), [2.0])
    @test issetequal(filter(isless(3.1), c), [2.0, 3.0, 3.0])
    @test issetequal(filter(isless(8.1), c), [2.0, 3.0, 3.0, 8.0])

    @test issetequal(filter(islessequal(1.1), c), [])
    @test issetequal(filter(islessequal(2.0), c), [2.0])
    @test issetequal(filter(islessequal(2.1), c), [2.0])
    @test issetequal(filter(islessequal(3.1), c), [2.0, 3.0, 3.0])
    @test issetequal(filter(islessequal(8.1), c), [2.0, 3.0, 3.0, 8.0])

    @test issetequal(filter(isgreater(1.1), c), [2.0, 3.0, 3.0, 8.0])
    @test issetequal(filter(isgreater(2.0), c), [3.0, 3.0, 8.0])
    @test issetequal(filter(isgreater(2.1), c), [3.0, 3.0, 8.0])
    @test issetequal(filter(isgreater(3.1), c), [8.0])
    @test issetequal(filter(isgreater(8.1), c), [])

    @test issetequal(filter(isgreaterequal(1.1), c), [2.0, 3.0, 3.0, 8.0])
    @test issetequal(filter(isgreaterequal(2.0), c), [2.0, 3.0, 3.0, 8.0])
    @test issetequal(filter(isgreaterequal(2.1), c), [3.0, 3.0, 8.0])
    @test issetequal(filter(isgreaterequal(3.1), c), [8.0])
    @test issetequal(filter(isgreaterequal(8.1), c), [])

    @test issetequal(filter(in(1.1..1.9), c), [])
    @test issetequal(filter(in(1.1..2.1), c), [2.0])
    @test issetequal(filter(in(1.1..3.1), c), [2.0, 3.0, 3.0])
    @test issetequal(filter(in(2.1..3.1), c), [3.0, 3.0])

    @test issetequal(innerjoin(identity, identity, tuple, isequal, c, [1.5, 3.0, 8.0]),
                     innerjoin(identity, identity, tuple, isequal, a, [1.5, 3.0, 8.0]))
end


text:
function mse(m::M, z::AbstractVector{T}) where {T,M <: AbstractModel{T}}
    return mean(residuals(m, z).^2)
end

function rmse(m::M, z::AbstractVector{T}) where {T,M <: AbstractModel{T}}
    return sqrt.(mse(m, z))
end

function mae(m::M, z::AbstractVector{T}) where {T,M <: AbstractModel{T}}
    return mean(residuals(m, z))
end

function mape(m::M, z::AbstractVector{T}) where {T,M <: AbstractModel{T}}
    reduce(&, z .> 0) || throw(DomainError("mape requires strictly positive data"))
    return mean(abs.(residuals(m, z)) ./ z)
end

function aic(m::M, z::AbstractVector) where {M <: AbstractModel}
    return -2 * log(m.σ2) + 2 * k(m)
end

aic(m::M) where {T,M <: AbstractModel{T}} = aic(m, T[])

function aicc(m::M, z::AbstractVector) where {M <: AbstractModel}
    return aic(m, z) + 2 * k(m) * (k(m) + 1) / (length(z) - k(m) - 1)
end

function bic(m::M, z::AbstractVector) where {M <: AbstractModel}
    return -2 * log(m.σ2) + log(length(z)) * k(m)
end


text:
using Random, Pkg, VisualStringDistances

# Define our distance measure
d(s1, s2) = visual_distance(s1, s2; normalize=x -> 2 + sqrt(x))
d((s1,s2)) = d(s1, s2)

confusable_names = [
    ("DifferentialEquations", "DifferentIalEquations"),
    ("jellyfish", "jeIlyfish"), # example from python
    ("ANOVA", "AN0VA"),
    ("ODEInterfaceDiffEq", "0DEInterfaceDiffEq"),
    ("ValueOrientedRiskManagementInsurance", "ValueOrientedRiskManagementlnsurance"),
    ("IsoPkg", "lsoPkg"),
    ("DiffEqNoiseProcess", "DiffEgNoiseProcess"),
    ("Graph500", "Graph5O0")
]
@show d.(confusable_names)

function get_all_package_names(registry_dir::AbstractString)
    packages = [x["name"] for x in values(Pkg.TOML.parsefile(joinpath(registry_dir, "Registry.toml"))["packages"])]
    sort!(packages)
    unique!(packages)
    return packages
end

names = get_all_package_names(expanduser("~/.julia/registries/General"))
filter!(x -> !endswith(x, "_jll"), names)

confusable = ["O" => "0", "I" => "l", "I" => "1", "g" => "q"]
append!(confusable, reverse.(confusable))

function gen_list(names; N = 10)
    list = Tuple{String, String}[]
    while length(list) < N
        name = rand(names)
        swap = rand(confusable)
        if occursin(first(swap), name)
            new_name = replace(name, swap; count=1)
            push!(list, (name, new_name))
        end
    end
    return list
end

list = gen_list(names)
dists = d.(list)
dist, idx = findmax(dists)
@show dist, list[idx]


text:
function HDirProdPs(x,y)
#HDirProdFn    Calculates horizontal direct product of two matrices with equal number of rows.
#              z[i,:] is the Kronecker product of x[i:i,:] and y[i:i,:]
#
#
#  Usage:    z = HDirProdFn(x,y)
#
#  Input:    x      T x Kx matrix
#            y      T x Ky matrix
#
#  Output:   z      T x (Kx*Ky)
#
#
#  Example:   x = [ 1 2;
#                   3 4]
#             y = [5 6 1;
#                  7 8 1]
#
#             the z = HDirProdFn(x,y) gives
#
#             z = [ 5  6  1  10  12  2;
#                  21 24  3  28  32  4]
#
# Paul.Soderlind@unisg.ch, Oct 2015
#----------------------------------------------------------------------------

  #T = size(x,1)       #rows and columns in x
  Kx = size(x,2)       #columns in x
  Ky = size(y,2)       #columns in y

  z = repmat(y,1,Kx) .* kron(x,ones(1,Ky))

  return z

end
#----------------------------------------------------------------------------

max_stars_repo_name: PaulSoderlind/PaulSoderlindCode

max_issues_repo_name: PaulSoderlind/PaulSoderlindCode

max_forks_repo_name: PaulSoderlind/PaulSoderlindCode


text:
using Pkg
Pkg.activate(".")

using LPSjl.BayesianNetworks
using LPSjl.ParameterLearning
using SparseArrays
using DataFrames

"""
    Darwiche, A. 11a - Learning Parameters: Complete Data
"""

node_H = DiscreteNode("H", ["T", "F"])

node_S = DiscreteNode("S", ["T", "F"])
add_parent!(node_S, node_H)

node_E = DiscreteNode("E", ["T", "F"])
add_parent!(node_E, node_H)

df = DataFrame("H" => ["T", "T", "F", "F", "T", "T", "F", "T", "T", "F", "T", "T", "T", "T", "T", "T"],
               "S" => ["F", "F", "T", "F", "F", "F", "F", "F", "F", "F", "F", "T", "F", "T", "F", "F"],
               "E" => ["T", "T", "F", "T", "F", "T", "F", "T", "T", "T", "T", "T", "T", "T", "T", "T"])

estimator = MaximumLikelihoodEstimator(df, BayesianNetwork([node_H, node_S, node_E], [(node_H, node_S), (node_H, node_E)]))
estimate(estimator)


text:
#push!(LOAD_PATH, "/home/caseykneale/Desktop/ChemometricsTools/ChemometricsTools.jl/");
using ChemometricsTools
#View the data in the package space
ChemometricsToolsDatasets()
#Load the data from package-space
Iris = convert(Matrix, ChemometricsToolsDataset("iris.csv") ) ;
#Seperate data from labels
X = convert( Array{Float64,2}, Iris[:, 1 : ( end - 1 ) ] );
Y = Iris[:, end ];
#One hot encode the class vector
Encoding = LabelEncoding(Y);
YHot = ColdToHot(Y, Encoding);
#Shuffle the set, because the classes are ordered
Shuffle!( X, YHot );
#Split the data into a training and hold out set
( (TrainX, TrainY), (TestX, TestY) ) = SplitByProportion( X, YHot, 0.7);

#Let the shoot out begin!
@time knn = KNN(TrainX, TrainY, "euclidean")
@time lda = LDA(TrainX, TrainY; Factors = 2)
@time ldagd = GaussianDiscriminant( lda, TrainX, TrainY; Factors = 2 )
@time mnsr = MultinomialSoftmaxRegression(TrainX, TrainY; maxiters = 2000, LearnRate = 1e-3, L2 = 1e4)
@time gnb = GaussianNaiveBayes(TrainX, TrainY)
@time ct = ClassificationTree(TrainX, TrainY;gainfn = entropy, maxdepth = 8, minbranchsize = 5)
@time rf = RandomForest(TrainX, TrainY, :classification; gainfn = entropy, trees = 100,
                        maxdepth = 10,  minbranchsize = 5,
                        samples = 0.7, maxvars = nothing)
@time simca = SIMCA(TrainX, TrainY; VarianceExplained = 0.95, Quantile = 0.999)

#Let's evaluate them on the training set then the hold out - see how they do!
models = ( knn, ldagd, mnsr, gnb, ct, rf, simca );
modelnames = ( :knn, :ldagd, :mnsr, :gnb, :ct, :rf, :SIMCA );
TrainingF1s = Dict()
for ( name, model ) in zip(modelnames, models)
    Predicted = model(TrainX)
    TrainingF1s[name] = MulticlassStats( Predicted, TrainY, Encoding )[1][:Global]["FMeasure"]
end

TrainingF1s

HoldOutF1s = Dict()
for ( name, model ) in zip(modelnames, models)
    HoldOutF1s[name] = MulticlassStats( model(TestX), TestY, Encoding )[1][:Global]["FMeasure"]
end

HoldOutF1s

#Let's check specifically the random forest classification model for the virginica class
RFStats = MulticlassStats( rf(TestX), TestY, Encoding );
RFStats[2]["virginica"]

StatsToCSVs(RFStats, "/home/caseykneale/Desktop/", "RFStats")
StatsToLaTeX(RFStats, "/home/caseykneale/Desktop/", "RFStats"; maxcolumns = 3)


text:
@cache struct RichardsonEulerCache{uType,rateType,tabType, arrayType} <: OrdinaryDiffEqMutableCache
  u::uType
  uprev::uType
  tmp::uType
  k::rateType
  fsalfirst::rateType
  tab::tabType
  T::arrayType
end

struct RichardsonEulerConstantCache <: OrdinaryDiffEqConstantCache
  m::Int #Generalise type of m
  # Can add different order of n_{i} here
  function RichardsonEulerConstantCache()
    m = 4
    new(m)
  end
end

function alg_cache(alg::RichardsonEuler,u,rate_prototype,uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits,uprev,uprev2,f,t,dt,reltol,p,calck,::Type{Val{true}})
  tmp = similar(u)
  k = zero(rate_prototype)
  fsalfirst = zero(rate_prototype)
  tab = RichardsonEulerConstantCache()
  T = fill(zeros(eltype(u), size(u)), (tab.m, tab.m))
  RichardsonEulerCache(u,uprev,tmp,k,fsalfirst,tab,T)
end

function alg_cache(alg::RichardsonEuler,u,rate_prototype,uEltypeNoUnits,uBottomEltypeNoUnits,tTypeNoUnits,uprev,uprev2,f,t,dt,reltol,p,calck,::Type{Val{false}})
  RichardsonEulerConstantCache()
end


text:
## Julia program for Bivariate Gibbs sampler
## author: weiya <szcfweiya@gmail.com>
## date: 2018-08-22

function bigibbs(T, rho)
    x = ones(T+1)
    y = ones(T+1)
    for t = 1:T
        x[t+1] = randn() * sqrt(1-rho^2) + rho*y[t]
        y[t+1] = randn() * sqrt(1-rho^2) + rho*x[t+1]
    end
    return x, y
end

## example
bigibbs(100, 0.5)

max_stars_repo_name: szcf-weiya/MCMC

max_issues_repo_name: szcf-weiya/MCMC

max_forks_repo_name: szcf-weiya/MCMC


text:
@testset "Recruitment configuration tests" begin
    mpSim = MPsim()
    filePath = joinpath( "base", "baseConfig" )
    fileName = string( filePath, ".xlsx" )
    catFileName = joinpath( "base", "catalogue.xlsx" )

    XLSX.openxlsx( fileName ) do xf
        MPIO.readRetirement( mpSim, xf )
    end  # XLSX.openxlsx( fileName ) do xf

    @test ( mpSim.retirement.freq == 3 ) && ( mpSim.retirement.offset == 0 )
    @test ( mpSim.retirement.maxCareerLength == 120 ) &&
        ( mpSim.retirement.retirementAge == 360 )
    @test mpSim.retirement.isEither
end  # @testset "Recruitment configuration tests"


text:
using ADCME
do_it = load_op("./build/libDoItOp", "do_it_op")

function myfun(y, x)
    @. y = 2x
end

x = constant(rand(100))
y = 2x # or `y = Variable(rand(100))`
u = do_it(y)
config = tf.ConfigProto(inter_op_parallelism_threads=1)
sess = tf.Session()
init(sess)
ccall((:get_id, "./build/libDoItOp.so"), Cvoid, ())
run(sess, u, x=>rand(100))


text:
using Test, Printf

using CLIMA.TurbulenceConvection.Grids
using CLIMA.TurbulenceConvection.GridOperators

@testset "Grid interface" begin
  for n_ghost in (1, 2)
    n_elems = 12
    n_elems_real = n_elems-2*n_ghost
    elem_indexes = 1:n_elems
    elem_indexes_real = elem_indexes[1+n_ghost:end-n_ghost]
    Δz = 1/n_elems_real
    grid = Grids.Grid(0.0, 1.0, n_elems_real, n_ghost)
    @test all(over_elems(grid) .== elem_indexes)
    @test all(over_elems_real(grid) .== elem_indexes_real)
    @test length(over_elems(grid)) == n_elems
    @test length(over_elems_real(grid)) == n_elems_real
    @test first_elem_above_surface(grid) == 1+n_ghost
    @test get_z(grid, first_elem_above_surface(grid)) ≈ grid.zn_surf + Δz/2
    @test over_elems_ghost(grid) == [(1:n_ghost)..., (n_elems+1-n_ghost:n_elems)...]
    @test grid.zn_surf ≈ 0.0
    @test grid.zn_top  ≈ 1.0
    @test grid.zc_surf ≈ grid.zn_surf + Δz/2
    @test grid.zc_top  ≈ grid.zn_top  - Δz/2
    sprint(show, grid)
  end
end

@testset "Grid operators" begin
  n_elems_real = 10
  grid = Grids.Grid(0.0, 1.0, n_elems_real)
  f = [2, 2, 3]
  K = [1, 2, 1]
  @test ∇_z(f, grid) ≈ (f[1] + f[3] - 2*f[2])*grid.dzi
  @test Δ_z(f, grid) ≈ (f[3] - 2*f[2] + f[1])*grid.dzi2
  @test Δ_z(f, grid, K) ≈ 150.0
  u = [2, 3, 4]
  @test adv_upwind(f, u, grid) ≈ u[ 2 ]*(f[2] - f[1]) * grid.dzi
  u = [2, -2, 4]
  @test adv_upwind(f, u, grid) ≈ u[ 2 ]*(f[3] - f[2]) * grid.dzi
end

max_stars_repo_name: christophernhill-dev/CLIMA

max_issues_repo_name: christophernhill-dev/CLIMA

max_forks_repo_name: christophernhill-dev/CLIMA


text:
# Autogenerated wrapper script for ephemeralpg_jll for armv7l-linux-musleabihf
export ddl_compare, getsocket, pg_tmp

JLLWrappers.@generate_wrapper_header("ephemeralpg")
JLLWrappers.@declare_executable_product(ddl_compare)
JLLWrappers.@declare_executable_product(getsocket)
JLLWrappers.@declare_executable_product(pg_tmp)
function __init__()
    JLLWrappers.@generate_init_header()
    JLLWrappers.@init_executable_product(
        ddl_compare,
        "bin/ddl_compare",
    )

    JLLWrappers.@init_executable_product(
        getsocket,
        "bin/getsocket",
    )

    JLLWrappers.@init_executable_product(
        pg_tmp,
        "bin/pg_tmp",
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
@testset "setup" begin
    x = collect(0:0.1:1)
    y = rand(11)
    m = Line(x,y)
    @test m.n == 11
    @test size(m) == (11,)
end

@testset "Interpolations" begin
    @testset "interpolate at log(1)" begin
        x = collect(0:0.1:1)
        y = log.(1.+x)
        m = Line(x,y)
        i = interp(m,[0.0])
        @test i[1] == 0.0
    end
end

@testset "getter and setters" begin
    x = [1,3,4,10]
    y = [6,0,8,1]
    l = Line(x,y)
    @test size(l) == (4,)

    @test l[1] == (1,6)
    @test isa(l[1:2],Line{Int64})
    @test l[1:2].x == [1,3]
    @test l[1:2].y == [6,0]

    setindex!(l,-1,-1,1)
    @test size(l) == (4,)
    @test l[1] == (-1,-1)

    setindex!(l,[10,11],[90,91],3:4)
    @test l[3:4].x == [10,11]
    @test l[3:4].y == [90,91]

end

@testset "Modifying Line methods" begin

    @testset "prepend" begin
        x = collect(0:0.1:1)
        y = log.(1.+x)
        L = Line(x,y)
        prepend!(L,18.0,-1.1)
        @test size(L)==(12,)
        @test L[1] == (18.0,-1.1)
        @test L[2] == (0.0,0.0)
    end

    @testset "append" begin
        x = collect(0:0.1:1)
        y = log.(1.+x)
        L = Line(x,y)
        append!(L,18.0,-1.1)
        @test size(L)==(12,)
        @test L[end] == (18.0,-1.1)
        @test L[1] == (0.0,0.0)
    end

    @testset "delete!" begin
        x = collect(0:0.1:1)
        y = rand(11)
        L = Line(x,y)
        delete!(L,9)
        @test size(L)==(10,)
        @test L[9] == (x[10],y[10])
    end
    @testset "insert!" begin
        x = collect(0:0.1:1)
        y = log.(1.+x)
        L = Line(x,y)
        insert!(L,1.1,3.3,9)
        @test size(L)==(12,)
        @test L[9] == (1.1,3.3)
        @test L[10] == (x[9],y[9])
        @test L[8] == (x[8],y[8])
    end
    @testset "splitat" begin
        x = collect(0:0.1:1)
        y = log.(1.+x)
        L = Line(x,y)
        n,o=splitat(L,1)
        @test size(n)==(1,)
        @test size(o)==(11,)

        n,o=splitat(L,2)
        @test size(n)==(2,)
        @test size(o)==(10,)
        @test n[2] == L[2]
        @test o[2] == L[3]
        @test o[1] == L[2]
        @test o[end] == L[end]

        n,o=splitat(L,2,false)
        @test size(n)==(2,)
        @test size(o)==(9,)
        @test n[2] == L[2]
        @test o[2] == L[4]
        @test o[1] == L[3]
    end
    @testset "sort!" begin
        x = collect(0:0.1:1)
        y = rand(11)
        L = Line(x,y)
        insert!(L,2.0,2.0,2)
        @test !(issorted(L.x))
        sort!(L)
        @test issorted(L.x)
    end
end

max_stars_repo_name: floswald/MultiLine

max_issues_repo_name: floswald/MultiLine

max_forks_repo_name: floswald/MultiLine


text:
import PortAudio, LibSndFile
using GR

function play(c::Channel)
  data = LibSndFile.load("Monty_Python.wav")
  stream = PortAudio.PortAudioStream(0, 1, blocksize=1024)
  spectrum = zeros(Int32, 300, 225)

  start = 1
  while start + 1024 < length(data)
    amplitudes = data[start:start+1024]
    start += 1024

    PortAudio.write(stream, amplitudes)

    power = log.(abs.(fft(float(amplitudes))) + 1) * 50
    spectrum[1, :] = round.(Int, power[1:225])
    spectrum = circshift(spectrum, [-1, 0])

    put!(c, spectrum)
  end
  put!(c, nothing)
end

c = Channel(play)
start = time_ns()

while isopen(c)
  spectrum = take!(c)
  if spectrum == nothing
    break
  end

  if time_ns() - start > 20 * 1000000   # 20ms
    imshow(spectrum, colormap=-13, yflip=true)

    start = time_ns()
  end
end


text:
"""
    istrait(x)

Return `true` if x is a trait type e.g. `FlyTrait` is a trait type when
it is defined by a statement like `@trait Fly`.
"""
istrait(x::DataType) = false

"""
    trait_type_name(t)

Return the name of trait type given a trait `t`.
For example, it would be `FlyTrait` for a `Fly` trait.
The trait is expected to be in TitleCase, but this
function automatically convert the first character to
upper case regardless.
"""
trait_type_name(t) = Symbol(uppercasefirst(string(t)) * "Trait")

"""
    trait_func_name(t)

Return the name of the trait instropectin function given a trait `t`.
For example, it would be `flytrait` for a `Fly` trait.
"""
trait_func_name(t) = Symbol(lowercase(string(t)) * "trait")

function trait_func_name(mod, t)
    sup = supertype(mod.eval(t))
    tn = Symbol(lowercase(string(nameof(sup))))
    modn = fullname(parentmodule(sup))
    foldl((a,b) -> Expr(:(.), a, QuoteNode(b)), (modn..., tn))
end

"""
Check if `x` is an expression of a tuple of symbols.
If `n` is specified then also check whether the tuple
has `n` elements. The `op` argument is used to customize
the check against `n`. Use `>=` or `<=` to check min/max
constraints.
"""
function is_tuple_of_symbols(x; n = nothing, op = isequal)
    x isa Expr &&
    x.head == :tuple &&
    all(x -> x isa Symbol, x.args) &&
    (n === nothing || op(length(x.args), n))
end

"""
    display_expanded_code(expr::Expr)

Display the expanded code from a macro for debugging purpose.
Only works when the verbose flag is set using `set_verbose`.
"""
function display_expanded_code(expr::Expr)
    if VERBOSE[]
        code = MacroTools.postwalk(rmlines, expr)
        @info "Generated code" code
    end
    return nothing
end

function define_const!(mod::Module, name::Symbol, val)
    if !isdefined(mod, name)
        mod.eval( :(const $name = $val) )
    else
        mod.eval(name)
    end
end
# -----------------------------------------------------------------------------------------
# Storage management
# -----------------------------------------------------------------------------------------

const LOCAL_STORAGE_NAME = :__binarytraits_storage
const TRAITS_STORAGE = TraitsStorage() # the singleton global storage
storage() = TRAITS_STORAGE

"""
    make_local_storage(module::Module)

Create a temporary variable with a `TraitsStorage` object in given module.
"""
function make_local_storage(mod::Module)
    define_const!(mod, LOCAL_STORAGE_NAME, TraitsStorage())
end

function get_local_storage(mod::Module)
    isdefined(mod, LOCAL_STORAGE_NAME) ? mod.__binarytraits_storage : nothing
end

"""
    getvalues(module::Module, sym::Symbol, key)

Get the set of values associated with the `key` in the dictionary
from the storage as identified by `sym` (e.g. `:interface_map`).
Try first local (module-) table, if key not found use global table.
"""
function getvalues(mod::Module, sym::Symbol, key)
    st = get_local_storage(mod)
    if st != nothing
        tab = getproperty(st, sym)
        haskey(tab, key) && return tab[key]
    end
    tab = getproperty(storage(), sym)
    return haskey(tab, key) ? tab[key] : valtype(tab)()
end
# get_traits_values(m::Module, key::Assignable) = getvalues(m, :traits_map, key)
get_interface_values(m::Module, key::DataType) = getvalues(m, :interface_map, key)
get_composite_values(m::Module, key::DataType) = getvalues(m, :composite_map, key)

function get_traits_map(mod::Module)
    lst = get_local_storage(mod)
    gst = storage()
    return lst === nothing ? gst.traits_map : merge(union, gst.traits_map, lst.traits_map)
end

"""
    pushdict!(module::Module, sym::Symbol, key, value)

Insert value into set associated with `key` in the dictionary as identified
by `sym` (e.g. `:interface_map`) from the local storage.
Create set if not pre-existent.
"""
function pushdict!(mod::Module, sym::Symbol, key, val)
    st = make_local_storage(mod)
    tab = getproperty(st, sym)
    s = get!(valtype(tab), tab, key)
    push_or_union!(s, val)
    return
end
push_traits_map!(m::Module, a::Assignable, val) = pushdict!(m, :traits_map, a, val)
push_interface_map!(m::Module, a::DataType, val) = pushdict!(m, :interface_map, a, val)
push_composite_map!(m::Module, a::DataType, val) = pushdict!(m, :composite_map, a, val)

push_or_union!(s::Set, val) = push!(s, val)
push_or_union!(s::Set, val::Set) = union!(s, val)

import Base.rehash!

"""
    move_to_global!(module::Module)

Move all sets collected in local storage to global storage.
Afterwareds, the local storage is empty.
"""
function move_to_global!(mod::Module)
    st = get_local_storage(mod)
    rehash!(st)
    if st !== nothing && !isempty(st)
        for sym in (:traits_map, :interface_map, :composite_map)
            dtab = getproperty(storage(), sym)
            stab = getproperty(st, sym)
            for (key, vset) in stab
                dset = get!(valtype(stab), dtab, key)
                union!(dset, vset)
            end
            empty!(stab)
        end
    end
    return
end

"""
    inittraits(module::Module)

This function should be called like `inittraits(@__MODULE__)` inside the
`__init__()' method of each module using `BinaryTraits`.

Alternatively it can be called outside the module this way:
`using Module; inittraits(Module)`, if `Module` missed to call it
within its `__init__` function.

This is required only if the traits/interfaces are expected to be shared
across modules.
"""
function inittraits(mod::Module)
    move_to_global!(mod)
end

function rehash!(st::TraitsStorage)
    rehash!(st.traits_map)
    rehash!(st.interface_map)
    rehash!(st.composite_map)
    return st
end
function Base.isempty(st::TraitsStorage)
    isempty(st.traits_map) &&
    isempty(st.interface_map) &&
    isempty(st.composite_map)
end


text:
# transform successes (Empty and Value)
# function must return a Value instance

@auto_hash_equals mutable struct Transform<:Delegate
    name::Symbol
    matcher::Matcher
    f::Function
    Transform(matcher, f) = new(:Transform, matcher, f)
end

@auto_hash_equals struct TransformState<:DelegateState
    state::State
end

always_print(::Transform) = false

# execute and failure come from Delegate

success(k::Config, m::Transform, s, t, i, r::Value) = Success(TransformState(t), i, m.f(r))

# as above, but function also takes iterator

@auto_hash_equals mutable struct ITransform<:Delegate
    name::Symbol
    matcher::Matcher
    f::Function
    ITransform(matcher, f) = new(:ITransform, matcher, f)
end

@auto_hash_equals struct ITransformState<:DelegateState
    state::State
end

always_print(::ITransform) = false

success(k::Config, m::ITransform, s, t, i, r::Value) = Success(ITransformState(t), i, m.f(i, r))

# simplified versions for transforming Success (remove and re-add the
# Success wrapper).

Appl(m::Matcher, f::Applicable) = Transform(m, x -> Any[f(x)])

function App(m::Matcher, f::Applicable)
    if f == vcat
        Transform(m, x -> Any[x])
    else
        Transform(m, x -> Any[f(x...)])
    end
end

IAppl(m::Matcher, f::Applicable) = ITransform(m, (i, x) -> Any[f(i, x)])

function IApp(m::Matcher, f::Applicable)
    ITransform(m, (i, x) -> Any[f(i, x...)])
end


text:
# Convolve with a Gaussian kernel with std s

function gaussian(s, N)
    a=convert(AbstractArray, Kernel.gaussian((s, s), (N+1,N+1)))
    as=circshift(parent(a)[1:N,1:N],(-N/2,-N/2))
    as=as./as[1,1]
    return as
end

function convfour(b, gf::Array{Complex{Float64},2})
    return real(ifft(gf.*fft(b)))
end

function convfour(bf::Array{Complex{Float64},2}, gf::Array{Complex{Float64},2})
    return real(ifft(gf.*bf))
end

function convfour!(bf::Array{Complex{Float64},2}, gf::Array{Complex{Float64},2})
    bf .*= gf
    ifft!(bf)
    bf.= real(bf)
end

function initsigma(smin, smax, Nsigma)
    σ = zeros(Nsigma)
    fact = (smax/smin) ^ (1. /(Nsigma-1))
    for i = 1:Nsigma
        σ[i]=smin*fact^(i-1)
    end
    return σ
end

function initfg(sigma, n, dx)
    fg = zeros(Complex{Float64}, n, n, length(sigma))
    for i = 1:length(sigma)
        g = gaussian(sigma[i]/dx, n)
        fg[:, :, i] .= fft(g)./(2π)*dx*dx
    end
    return fg
end

function alphal(φ::Array{Float64,2}, φi::Array{Float64,1})
   nl = length(φi)
   nx, ny = size(φ)
   α = Array{Float64,3}(undef, nx, ny, nl)
   φ2 = φ.^2
   φi2 = φi.^2
   aa = Array{Float64,2}(undef, nx, ny)
   for l = 1:nl
       aa .= 2 .* φ2 ./ (φ2 .+ φi2[l])
       for j in [collect(1:(l-1)); collect((l+1):nl)]
           aa .*= ((φ2 .- φi2[j]) ./ (φ2 .+ φi2[j])) .* ((φi2[l] + φi2[j]) / (φi2[l] - φi2[j]))
       end
       α[:, :, l] = aa
   end
   return α
end

# Eq2 in Gilad et al. 2006
# I2=\int K(r-r'; φ(r)) ψ(r') dr'
function approxintb(w, fg::Array{Complex{Float64},3}, α)
    nx, ny, ns = size(α)
    wf = fft(w)
    z = zeros(nx, ny)
    for l=1:ns
        cf=convfour(wf, fg[:, :, l])
        for j =1:ny
           for i =1:nx
               z[i, j] += α[i, j, l]*cf[i, j]
           end
        end
    end
    return z
end

# Eq1 in Gilad et al. 2006
# I1=\int K(r-r'; φ(r')) ψ(r') dr'
function approxintw(b, fg::Array{Complex{Float64},3}, α)
    nx, ny, ns = size(α)
    z = zeros(nx, ny)
    ab = similar(b)
    for l=1:ns
        ab .= α[:, :, l].*b
        z .+= convfour(ab, fg[:, :, l])
    end
    return z
end

function initapprox(b, η, sigma)
    φ = 1.0 .+ η.*b
    α = alphal(φ, sigma)
    return α
end

max_stars_repo_name: jhardenberg/bwh

max_issues_repo_name: jhardenberg/bwh

max_forks_repo_name: jhardenberg/bwh


text:
include(joinpath(@__DIR__, "pedagogy_graph.jl"))
using Random

dims = [5, 5]
g = LG.grid(dims)
roots = [8]
pp = PRS.RootedSpanningForest(g, roots)

rng = Random.MersenneTwister(7)
rooted_spanning_tree_padagogy(pp, dims, rng)


text:
sources = ["im2col.cpp", "pooling.cpp"]

compiler = "g++"
flags    = ["-fPIC", "-Wall", "-O3", "-shared"]
libname  = "libmochaext.so"
openmp   = "-fopenmp"

@osx? begin
  if !haskey(ENV, "MOCHA_FORCE_OMP")
    println("OpenMP is currently not officially supported by OS X Clang compiler yet.")
    println("(see http://clang-omp.github.io/ to install OpenMP clang extension, or")
    println("install gcc.")
    println("")
    println("Disabling OpenMP. To force enable OpenMP, set MOCHA_FORCE_OMP environment")
    println("variable.")
    println("")
    openmp = ""
  end
end : nothing

cmd = `$compiler $flags $openmp -o $libname $sources`
println("Running $cmd")
run(cmd)


text:
using EzXMLPatched
using Test
using Logging: SimpleLogger, with_logger

# Capture logging messages using a local logger.
function capture_logging_messages(proc)
    buf = IOBuffer()
    ret = with_logger(proc, SimpleLogger(buf))
    messages = String(take!(buf))
    return ret, messages
end

# Unit tests
# ----------

@testset "Error" begin
    for i in 1:21
        t = convert(EzXMLPatched.NodeType, i)
        @test t == i
        @test occursin(r"^[A-Z_]+_(NODE|DECL|START|END)$", repr(t))
        @test string(t) == string(i)
        @test convert(EzXMLPatched.NodeType, t) === t
    end
    @test_throws AssertionError repr(convert(EzXMLPatched.NodeType, 0))
    @test_throws AssertionError repr(convert(EzXMLPatched.NodeType, 100))

    err = EzXMLPatched.XMLError(1, 77, "some parser error", EzXMLPatched.XML_ERR_ERROR, 123)
    @test isa(err, EzXMLPatched.XMLError)
    buf = IOBuffer()
    showerror(buf, err)
    @test take!(buf) == b"XMLError: some parser error from XML parser (code: 77, line: 123)"
end

@testset "Reader" begin
    @testset "XML" begin
        valid_file = joinpath(dirname(@__FILE__), "sample1.xml")
        invalid_file = joinpath(dirname(@__FILE__), "sample1.invalid.xml")
        doc = readxml(valid_file)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE
        @test nodetype(readxml(valid_file).node) === EzXMLPatched.DOCUMENT_NODE
        @test_throws EzXMLPatched.XMLError readxml(invalid_file)
        @assert !isfile("not-exist.xml")
        @test_throws EzXMLPatched.XMLError readxml("not-exist.xml")

        # from compressed file
        compressed = joinpath(dirname(@__FILE__), "sample1.xml.gz")
        @test isa(readxml(compressed), EzXMLPatched.Document)

        # from stream
        doc = open(readxml, valid_file)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE
        @test_throws EzXMLPatched.XMLError open(readxml, invalid_file)

        # properties
        doc = readxml(joinpath(dirname(@__FILE__), "sample1.xml"))
        @test hasversion(doc)
        @test version(doc) == "1.0"
        @test !hasencoding(doc)
        @test_throws ArgumentError encoding(doc)
        doc = readxml(joinpath(dirname(@__FILE__), "sample2.xml"))
        @test hasversion(doc)
        @test version(doc) == "1.0"
        @test hasencoding(doc)
        @test encoding(doc) == "UTF-8"
    end

    @testset "HTML" begin
        valid_file = joinpath(dirname(@__FILE__), "sample1.html")
        doc = readhtml(valid_file)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE
        @test nodetype(readhtml(valid_file).node) === EzXMLPatched.HTML_DOCUMENT_NODE
        @assert !isfile("not-exist.html")
        @test_throws EzXMLPatched.XMLError readxml("not-exist.html")
        @test_throws EzXMLPatched.XMLError readhtml("not-exist.html")

        # from compressed file
        compressed = joinpath(dirname(@__FILE__), "sample1.html.gz")
        @test isa(readxml(compressed), EzXMLPatched.Document)
        @test isa(readhtml(compressed), EzXMLPatched.Document)

        # from stream (FIXME: this causes "Misplaced DOCTYPE declaration")
        #doc = open(readhtml, valid_file)
        #@test isa(doc, EzXMLPatched.Document)
        #@test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE
        buf = IOBuffer("""

            <title>hey</title>
            Hey

        """)
        doc = readhtml(buf)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE

        buf = IOBuffer("""
        MBGD
        &#124
        Ontology
        &#124
        To Previous Version (2015)
        """)
        doc, messages = capture_logging_messages() do
            readhtml(buf)
        end
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE
        @test occursin("Warning: XMLError: htmlParseCharRef: missing semicolon from HTML parser (code: 7, line: 2)", messages)
        @test occursin("Warning: XMLError: htmlParseCharRef: missing semicolon from HTML parser (code: 7, line: 4)", messages)
    end
end

@testset "Writer" begin
    docstr = """
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <foo>ok</foo>
    </root>
    """
    doc = parsexml(docstr)
    tmp = tempname()
    try
        @test write(tmp, doc) == sizeof(docstr)
        @test String(read(tmp)) == docstr
        @test string(readxml(tmp)) == docstr
    finally
        rm(tmp)
    end
end

@testset "Parser" begin
    @testset "XML" begin
        doc = parsexml("""
        <?xml version="1.0"?>
        <root>
            <child attr="value">content</child>
        </root>
        """)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE

        doc = parsexml("""
        <root>
            <child attr="value">content</child>
        </root>
        """)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE

        doc = parsexml(b"""
        <?xml version="1.0"?>
        <root>
            <child attr="value">content</child>
        </root>
        """)
        @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE

        @test nodetype(parsexml("<xml/>").node) === EzXMLPatched.DOCUMENT_NODE
        @test nodetype(parsexml("").node) === EzXMLPatched.DOCUMENT_NODE
        @test nodetype(parsexml(b"<xml/>").node) === EzXMLPatched.DOCUMENT_NODE
        @test nodetype(parsexml(b"").node) === EzXMLPatched.DOCUMENT_NODE

        # This includes multi-byte characters.
        doc = parsexml("""
        <?xml version="1.0" encoding="UTF-8" ?>
        <Link>
            <Name>pubmed_pubmed</Name>
            <Menu>Similar articles</Menu>
            <Description>... “linked from” ...</Description>
            <DbTo>pubmed</DbTo>
        </Link>
        """)
        @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE

        @test_throws ArgumentError parsexml("")
        @test_throws EzXMLPatched.XMLError parsexml(" ")
        @test_throws EzXMLPatched.XMLError parsexml("abracadabra")
        @test_throws EzXMLPatched.XMLError parsexml("""<?xml version="1.0"?>""")

        _, messages = capture_logging_messages() do
            @test_throws EzXMLPatched.XMLError parsexml("<gepa?>jgo<<<><<")
        end
        @test occursin("caught 4 errors; showing the first one", messages)
    end

    @testset "HTML" begin
        doc = parsehtml("""
        <!DOCTYPE html>

                <title>Title</title>

                Hello, world!

        """)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE
        @test hasdtd(doc)
        @test nodename(dtd(doc)) == "html"

        doc = parsehtml("""

                <title>Title</title>

                Hello, world!

        """)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE
        @test hasdtd(doc)

        doc = parsehtml(b"""
        <!DOCTYPE html>

                <title>Title</title>

                Hello, world!

        """)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE

        doc = parsehtml("""
        <!DOCTYPE html>

            <title>題名</title>
            こんにちは、世界！

        """)
        @test isa(doc, EzXMLPatched.Document)
        @test nodetype(doc.node) === EzXMLPatched.HTML_DOCUMENT_NODE

        @test nodetype(parsehtml("").node) === EzXMLPatched.HTML_DOCUMENT_NODE
        @test nodetype(parsehtml(b"").node) === EzXMLPatched.HTML_DOCUMENT_NODE

        @test_throws ArgumentError parsehtml("")
    end
end

@testset "Stream Reader" begin
    for i in 0:17
        t = convert(EzXMLPatched.ReaderType, i)
        @test t == i
        @test occursin(r"READER_[A-Z_]+$", repr(t))
        @test string(t) == string(i)
        @test convert(EzXMLPatched.ReaderType, t) === t
    end
    @test_throws AssertionError repr(convert(EzXMLPatched.ReaderType, -1))
    @test_throws AssertionError repr(convert(EzXMLPatched.ReaderType, 18))

    sample2 = joinpath(dirname(@__FILE__), "sample2.xml")
    reader = open(EzXMLPatched.StreamReader, sample2)
    @test isa(reader, EzXMLPatched.StreamReader)
    typs = []
    names = []
    depths = []
    contents = []
    attributes = []
    for typ in reader
        push!(typs, typ)
        push!(names, nodename(reader))
        push!(depths, nodedepth(reader))
        if typ == EzXMLPatched.READER_ELEMENT && nodename(reader) == "elm"
            push!(contents, nodecontent(reader))
            push!(attributes, reader["attr1"])
        end
        @test isa(expandtree(reader), EzXMLPatched.Node)
    end
    @test typs[1] === EzXMLPatched.READER_ELEMENT
    @test typs[2] === EzXMLPatched.READER_SIGNIFICANT_WHITESPACE
    @test names[1] == "root"
    @test names[3] == "elm"
    @test depths[1] === 0
    @test depths[end] === 0
    @test maximum(depths) === 2
    @test contents[1] == "some content 1"
    @test contents[2] == "some content 2"
    @test attributes[1] == "attr1 value 1"
    @test attributes[2] == "attr1 value 2"
    @test open(collect, EzXMLPatched.StreamReader, sample2) == typs

    simple_graphml = joinpath(dirname(@__FILE__), "simple.graphml")
    reader = open(EzXMLPatched.StreamReader, simple_graphml)
    @test isa(reader, EzXMLPatched.StreamReader)
    typs = []
    names = []
    namespaces = []
    for typ in reader
        push!(typs, typ)
        push!(names, nodename(reader))
        if typ == EzXMLPatched.READER_ELEMENT
            push!(namespaces, namespace(reader))
        end
        @test isa(expandtree(reader), EzXMLPatched.Node)
    end
    @test first(typs) === EzXMLPatched.READER_COMMENT
    @test first(names) == "#comment"
    @test last(typs) === EzXMLPatched.READER_END_ELEMENT
    @test last(names) == "graphml"
    @test first(namespaces) == "http://graphml.graphdrawing.org/xmlns"
    @test close(reader) === nothing

    reader = open(EzXMLPatched.StreamReader, simple_graphml)
    typs = []
    names = []
    for typ in reader
        push!(typs, typ)
        push!(names, nodename(reader))
    end
    @test first(typs) === EzXMLPatched.READER_COMMENT
    @test first(names) == "#comment"
    @test last(typs) === EzXMLPatched.READER_END_ELEMENT
    @test last(names) == "graphml"
    @test close(reader) === nothing

    input = open(simple_graphml)
    reader = EzXMLPatched.StreamReader(input)
    typs = []
    names = []
    for typ in reader
        push!(typs, typ)
        push!(names, nodename(reader))
    end
    @test first(typs) === EzXMLPatched.READER_COMMENT
    @test first(names) == "#comment"
    @test last(typs) === EzXMLPatched.READER_END_ELEMENT
    @test last(names) == "graphml"
    @test isopen(input)
    @test close(reader) === nothing
    @test !isopen(input)

    input = IOBuffer("""
    <root foo="FOO"/>
    """)
    reader = EzXMLPatched.StreamReader(input)
    for typ in reader
        if typ == EzXMLPatched.READER_ELEMENT
            @test haskey(reader, "foo")
            @test !haskey(reader, "bar")
            @test reader["foo"] == "FOO"
            @test_throws ArgumentError namespace(reader)
        end
    end

    input = IOBuffer("""

        <title>Hey</title>

    """)
    names = String[]
    reader = EzXMLPatched.StreamReader(input)
    for typ in reader
        @test reader.:type === typ
        push!(names, reader.name)
        if reader.name == "head" && reader.:type == EzXMLPatched.READER_ELEMENT
            @test reader.depth == 1
            @test reader.namespace == "http://www.w3.org/1999/xhtml"
        elseif reader.name == "title" && reader.:type == EzXMLPatched.READER_ELEMENT
            @test reader.depth == 2
            @test reader.content == "Hey"
            @test reader.namespace == "http://www.w3.org/1999/xhtml"
        elseif reader.:type == EzXMLPatched.READER_END_ELEMENT
            @test !hasnodecontent(reader)
            @test reader.content === nothing
        end
    end
    @test "head" ∈ names
    @test "title" ∈ names

    @test_throws EzXMLPatched.XMLError iterate(EzXMLPatched.StreamReader(IOBuffer("not xml")))

    # memory management test
    for _ in 1:10
        reader = EzXMLPatched.StreamReader(IOBuffer(""))
        for typ in reader
            if typ == EzXMLPatched.READER_ELEMENT && EzXMLPatched.nodename(reader) == "a"
                a = EzXMLPatched.expandtree(reader)
                b = EzXMLPatched.firstelement(a)
            end
        end
        close(reader)
    end
    @test true

    reader = EzXMLPatched.StreamReader(IOBuffer("""

    """))
    for typ in reader
        if typ == EzXMLPatched.READER_ELEMENT
            if nodename(reader) == "a"
                @test !hasnodevalue(reader)
                @test_throws ArgumentError nodevalue(reader)
                @test hasnodeattributes(reader)
                @test countattributes(reader) == 2
                @test nodeattributes(reader) == Dict{String,String}("attr1"=>"", "attr2"=>"This is cool")
                @test reader[1] == ""
                @test reader[2] == "This is cool"
                @test_throws KeyError reader[3]
                @test_throws KeyError reader["noattr"]
                for (i, attr) in enumerate(eachattribute(reader))
                    @test hasnodevalue(attr)
                    @test nodedepth(attr) == 1
                    if i == 1
                        @test nodename(attr) == "attr1"
                        @test nodevalue(attr) == ""
                    else
                        @test nodename(attr) == "attr2"
                        @test nodevalue(attr) == "This is cool"
                    end
                end
            elseif nodename(reader) == "b"
                @test !hasnodeattributes(reader)
                @test nodeattributes(reader) == Dict{String,String}()
                @test countattributes(reader) == 0
            end
        elseif typ == EzXMLPatched.READER_END_ELEMENT
            @test_throws ArgumentError eachattribute(reader)
        end
    end
    close(reader)

    # memory management test (XPath)
    # FIXME: support XPath
    #for _ in 1:10
    #    reader = EzXMLPatched.StreamReader(IOBuffer(""))
    #    for typ in reader
    #        if typ == EzXMLPatched.READER_ELEMENT && EzXMLPatched.nodename(reader) == "a"
    #            a = EzXMLPatched.expandtree(reader)
    #            b = findall("//b[1]", a)
    #        end
    #    end
    #    close(reader)
    #end
    #@test true
    reader = EzXMLPatched.StreamReader(IOBuffer(""))
    for typ in reader
        if typ == EzXMLPatched.READER_ELEMENT && EzXMLPatched.nodename(reader) == "a"
            a = EzXMLPatched.expandtree(reader)
            @test_throws ArgumentError findall("//b[1]", a, String[])
        end
    end
    close(reader)
    @test true

    # TODO: Activate this test.
    #@assert !isfile("not-exist.xml")
    #@test_throws EzXMLPatched.XMLError open(EzXMLPatched.StreamReader, "not-exist.xml")
end

@testset "Constructors" begin
    n = XMLDocumentNode("1.0")
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) === EzXMLPatched.DOCUMENT_NODE
    @test document(n) === EzXMLPatched.Document(n.ptr)

    n = HTMLDocumentNode(nothing, nothing)
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) === EzXMLPatched.HTML_DOCUMENT_NODE
    @test document(n) === EzXMLPatched.Document(n.ptr)

    n = HTMLDocumentNode("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
                         "-//W3C//DTD XHTML 1.0 Strict//EN")
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) === EzXMLPatched.HTML_DOCUMENT_NODE
    @test document(n) === EzXMLPatched.Document(n.ptr)

    n = ElementNode("node")
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) === EzXMLPatched.ELEMENT_NODE
    @test iselement(n)
    @test_throws ArgumentError document(n)

    n = TextNode("some text")
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) === EzXMLPatched.TEXT_NODE
    @test istext(n)
    @test_throws ArgumentError document(n)

    n = CommentNode("some comment")
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) === EzXMLPatched.COMMENT_NODE
    @test iscomment(n)
    @test_throws ArgumentError document(n)

    n = CDataNode("some CDATA")
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) === EzXMLPatched.CDATA_SECTION_NODE
    @test iscdata(n)
    @test_throws ArgumentError document(n)

    n = AttributeNode("attr", "value")
    @test isa(n, EzXMLPatched.Node)
    @test n.owner == n
    @test nodetype(n) == EzXMLPatched.ATTRIBUTE_NODE
    @test isattribute(n)
    @test_throws ArgumentError document(n)

    n = DTDNode("open-hatch")
    @test isa(n, EzXMLPatched.Node)
    @test isdtd(n)
    @test n.owner === n
    @test nodetype(n) === EzXMLPatched.DTD_NODE
    @test nodename(n) == "open-hatch"
    @test_throws ArgumentError systemID(n)
    @test_throws ArgumentError externalID(n)

    n = DTDNode("open-hatch",
                "http://www.textuality.com/boilerplate/OpenHatch.xml")
    @test isa(n, EzXMLPatched.Node)
    @test isdtd(n)
    @test n.owner === n
    @test nodetype(n) === EzXMLPatched.DTD_NODE
    @test systemID(n) == "http://www.textuality.com/boilerplate/OpenHatch.xml"
    @test_throws ArgumentError externalID(n)

    n = DTDNode("open-hatch",
                "http://www.textuality.com/boilerplate/OpenHatch.xml",
                "-//Textuality//TEXT Standard open-hatch boilerplate//EN")
    @test isa(n, EzXMLPatched.Node)
    @test isdtd(n)
    @test n.owner === n
    @test nodetype(n) === EzXMLPatched.DTD_NODE
    @test systemID(n) == "http://www.textuality.com/boilerplate/OpenHatch.xml"
    @test externalID(n) == "-//Textuality//TEXT Standard open-hatch boilerplate//EN"

    doc = XMLDocument()
    @test isa(doc, EzXMLPatched.Document)
    @test doc.node.owner === doc.node
    @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE
    @test !hasroot(doc)
    @test_throws ArgumentError root(doc)

    doc = HTMLDocument()
    @test isa(doc, EzXMLPatched.Document)
    @test doc.node.owner === doc.node
    @test nodetype(doc.node) == EzXMLPatched.HTML_DOCUMENT_NODE
    @test !hasroot(doc)
    @test_throws ArgumentError root(doc)

    doc = HTMLDocument("http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd",
                       "-//W3C//DTD XHTML 1.0 Strict//EN")
    @test isa(doc, EzXMLPatched.Document)
    @test doc.node.owner === doc.node
    @test nodetype(doc.node) == EzXMLPatched.HTML_DOCUMENT_NODE
    @test !hasroot(doc)
    @test_throws ArgumentError root(doc)
end

@testset "Traversal" begin
    doc = parsexml("<root/>")
    @test hasroot(doc)
    @test !hasdtd(doc)
    @test isa(root(doc), EzXMLPatched.Node)
    @test root(doc) == root(doc)
    @test root(doc) === root(doc)
    @test hash(root(doc)) === hash(root(doc))
    @test nodetype(root(doc)) === EzXMLPatched.ELEMENT_NODE
    @test nodepath(root(doc)) == "/root"
    @test nodename(root(doc)) == "root"
    @test nodecontent(root(doc)) == ""
    @test document(root(doc)) == doc
    @test document(root(doc)) === doc
    @test !hasparentnode(doc.node)
    @test_throws ArgumentError parentnode(doc.node)
    @test hasparentnode(root(doc))
    @test parentnode(root(doc)) === doc.node
    @test_throws ArgumentError nodename(parentnode(root(doc)))
    @test_throws ArgumentError dtd(doc)

    doc = parsexml("""
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

        <title>hello</title>
        Content

    """)
    @test hasroot(doc)
    @test hasdtd(doc)
    @test isa(dtd(doc), EzXMLPatched.Node)
    @test isdtd(dtd(doc))
    @test dtd(doc) === dtd(doc)
    @test nodename(dtd(doc)) == "html"
    @test systemID(dtd(doc)) == "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    @test externalID(dtd(doc)) == "-//W3C//DTD XHTML 1.0 Transitional//EN"
    @test parentnode(dtd(doc)) === doc.node
    @test_throws ArgumentError systemID(root(doc))
    @test_throws ArgumentError externalID(root(doc))

    doc = parsexml("""
    <?xml version="1.0"?>
    <r>
        <c1/>
        <c2/>
        <c3/>
    </r>
    """)
    r = root(doc)
    @test nodetype(firstnode(r)) === EzXMLPatched.TEXT_NODE
    @test nodetype(lastnode(r)) === EzXMLPatched.TEXT_NODE
    @test nodetype(firstelement(r)) === EzXMLPatched.ELEMENT_NODE
    @test nodename(firstelement(r)) == "c1"
    @test nodetype(lastelement(r)) === EzXMLPatched.ELEMENT_NODE
    @test nodename(lastelement(r)) == "c3"
    c1 = firstelement(r)
    @test hasnextnode(c1)
    @test hasprevnode(c1)
    @test nodetype(nextnode(c1)) === EzXMLPatched.TEXT_NODE
    @test nodetype(prevnode(c1)) === EzXMLPatched.TEXT_NODE
    @test hasnextelement(c1)
    @test !hasprevelement(c1)
    c2 = nextelement(c1)
    @test nodename(c2) == "c2"
    @test hasnextelement(c2)
    @test hasprevelement(c2)
    @test prevelement(c2) == c1
    c3 = nextelement(c2)
    @test nodename(c3) == "c3"
    @test !hasnextelement(c3)
    @test hasprevelement(c3)
    @test prevelement(c3) == c2
    @test_throws ArgumentError prevelement(c1)
    @test_throws ArgumentError nextelement(c3)

    doc = parsexml("""
    <?xml version="1.0"?>
    <root attr="some attribute value"><child>some content</child></root>
    """)
    @test nodecontent(root(doc)) == "some content"
    @test haskey(root(doc), "attr")
    @test !haskey(root(doc), "bah")
    @test root(doc)["attr"] == "some attribute value"
    @test_throws KeyError root(doc)["bah"]
    @test delete!(root(doc), "attr") == root(doc)
    @test !haskey(root(doc), "attr")
    @test_throws KeyError root(doc)["attr"]

    doc = parsexml("<root/>")
    x = root(doc)
    @test_throws ArgumentError firstnode(x)
    @test_throws ArgumentError lastnode(x)
    @test_throws ArgumentError firstelement(x)
    @test_throws ArgumentError lastelement(x)
    @test_throws ArgumentError nextnode(x)
    @test_throws ArgumentError prevnode(x)
    @test_throws ArgumentError nextelement(x)
    @test_throws ArgumentError prevelement(x)

    doc = parsexml("""
    <root xmlns:x="http://xxx.com" xmlns:y="http://yyy.com">
        <x:child x:attr="xxx" y:attr="yyy"/>
    </root>
    """)
    x = firstelement(root(doc))
    @test namespace(x) == "http://xxx.com"
    @test namespace(attributes(x)[1]) == "http://xxx.com"
    @test namespace(attributes(x)[2]) == "http://yyy.com"
    @test_throws ArgumentError namespace(parentnode(root(doc)))

    # http://www.xml.com/pub/a/1999/01/namespaces.html
    doc = parsexml("""
    <h:html xmlns:xdc="http://www.xml.com/books"
            xmlns:h="http://www.w3.org/HTML/1998/html4">
     <h:head><h:title>Book Review</h:title></h:head>
     <h:body>
      <xdc:bookreview>
       <xdc:title>XML: A Primer</xdc:title>
       <h:table>
        <h:tr align="center">
         <h:td>Author</h:td><h:td>Price</h:td>
         <h:td>Pages</h:td><h:td>Date</h:td></h:tr>
        <h:tr align="left">
         <h:td><xdc:author>Simon St. Laurent</xdc:author></h:td>
         <h:td><xdc:price>31.98</xdc:price></h:td>
         <h:td><xdc:pages>352</xdc:pages></h:td>
         <h:td><xdc:date>1998/01</xdc:date></h:td>
        </h:tr>
       </h:table>
      </xdc:bookreview>
     </h:body>
    </h:html>
    """)
    @test namespaces(root(doc)) ==
          namespaces(elements(root(doc))[1]) ==
          namespaces(elements(root(doc))[2]) == [
        "xdc" => "http://www.xml.com/books",
        "h"   => "http://www.w3.org/HTML/1998/html4"]
    @test nodename(root(doc)) == "html"
    @test namespace(root(doc)) == "http://www.w3.org/HTML/1998/html4"
    @test namespace(elements(elements(root(doc))[2])[1]) == "http://www.xml.com/books"

    # default namespace
    doc = parsexml("""

    """)
    @test namespaces(root(doc)) == [
        "" => "http://www.w3.org/HTML/1998/html4",
        "xdc" => "http://www.xml.com/books"]
    @test namespace(root(doc)) == "http://www.w3.org/HTML/1998/html4"

    doc = parsexml("""

    """)
    @test namespaces(root(doc)) == [
        "" => "",
        "xdc" => "http://www.xml.com/books"]

    doc = parsexml("""
    <root xmlns="http://xxx.com" xmlns:y="http://yyy.com">
        <child y:foo="Y"/>
    </root>
    """)
    child = firstelement(root(doc))
    @test haskey(child, "y:foo")
    @test !haskey(child, "foo")
    @test child["y:foo"] == "Y"
    @test_throws KeyError child["foo"]
    child["foo"] = "X"
    @test haskey(child, "foo")
    @test child["foo"] == "X"
    @test child["y:foo"] == "Y"

    doc = parsexml("""
    <root xmlns="http://xxx.com" xmlns:y="http://yyy.com">
        <child y:foo="Y" foo="X"/>
    </root>
    """)
    child = firstelement(root(doc))
    @test child["foo"] == "X"
    @test child["y:foo"] == "Y"
    delete!(child, "foo")
    @test !haskey(child, "foo")
    @test haskey(child, "y:foo")
    delete!(child, "y:foo")
    @test !haskey(child, "foo")
    @test !haskey(child, "y:foo")

    doc = parsexml("""
    <root xmlns="http://xxx.com" xmlns:y="http://yyy.com">
        <child foo="X" y:foo="Y"/>
    </root>
    """)
    child = firstelement(root(doc))
    @test child["foo"] == "X"
    @test child["y:foo"] == "Y"
    delete!(child, "foo")
    @test !haskey(child, "foo")
    @test haskey(child, "y:foo")
    delete!(child, "y:foo")
    @test !haskey(child, "foo")
    @test !haskey(child, "y:foo")

    # no namespace
    doc = parsexml("""
    <root></root>
    """)
    @test isempty(namespaces(root(doc)))
    @test_throws ArgumentError namespace(root(doc))

    @testset "Counters" begin
        doc = parsexml("<root/>")
        @test !hasnode(root(doc))
        @test countnodes(root(doc)) === 0
        @test countelements(root(doc)) === 0
        @test countattributes(root(doc)) === 0
        @test addelement!(root(doc), "c1") === lastelement(root(doc))
        root(doc)["attr1"] = "1"
        @test countnodes(root(doc)) === 1
        @test countelements(root(doc)) === 1
        @test countelements(root(doc)) === 1
        @test countattributes(root(doc)) === 1
        @test addelement!(root(doc), "c2", "some content") === lastelement(root(doc))
        @test countnodes(root(doc)) === 2
        @test countelements(root(doc)) === 2
        @test_throws ArgumentError countattributes(doc.node)
    end

    @testset "Iterators" begin
        doc = parsexml("<root/>")
        ns = EzXMLPatched.Node[]
        for (i, node) in enumerate(eachnode(root(doc)))
            @test isa(node, EzXMLPatched.Node)
            push!(ns, node)
        end
        @test length(ns) == 0
        @test nodes(root(doc)) == ns
        ns = EzXMLPatched.Node[]
        for (i, node) in enumerate(eachelement(root(doc)))
            @test isa(node, EzXMLPatched.Node)
            push!(ns, node)
        end
        @test length(ns) == 0
        @test elements(root(doc)) == ns

        doc = parsexml("""
        <root><c1></c1><c2></c2></root>
        """)
        ns = EzXMLPatched.Node[]
        for (i, node) in enumerate(eachnode(root(doc)))
            @test isa(node, EzXMLPatched.Node)
            push!(ns, node)
        end
        @test length(ns) == 2
        @test nodes(root(doc)) == ns
        ns = EzXMLPatched.Node[]
        for (i, node) in enumerate(eachelement(root(doc)))
            @test isa(node, EzXMLPatched.Node)
            push!(ns, node)
        end
        @test length(ns) == 2
        @test elements(root(doc)) == ns

        doc = parsexml("""
        <root>
            <c1></c1>
            <c2></c2>
        </root>
        """)
        ns = EzXMLPatched.Node[]
        for (i, node) in enumerate(eachnode(root(doc)))
            @test isa(node, EzXMLPatched.Node)
            push!(ns, node)
        end
        @test length(ns) == 5
        @test nodes(root(doc)) == ns
        ns = EzXMLPatched.Node[]
        for (i, node) in enumerate(eachelement(root(doc)))
            @test isa(node, EzXMLPatched.Node)
            push!(ns, node)
        end
        @test length(ns) == 2
        @test elements(root(doc)) == ns

        doc = parsexml("""
        <root>
            <c1/>
            <c2/>
            <c3/>
        </root>
        """)
        @test collect(eachnode(root(doc), true)) == reverse(collect(eachnode(root(doc))))
        @test collect(eachelement(root(doc), true)) == reverse(collect(eachelement(root(doc))))
        @test nodes(root(doc), true) == reverse(nodes(root(doc)))
        @test elements(root(doc), true) == reverse(elements(root(doc)))

        doc = parsexml("""
        <?xml version="1.0"?>
        <root attr1="foo" attr2="bar"></root>
        """)
        for node in eachattribute(root(doc))
            attr = nodename(node)
            val = nodecontent(node)
            @test val == (attr == "attr1" ? "foo" : "bar")
        end
        @test [(nodename(n), nodecontent(n)) for n in attributes(root(doc))] == [("attr1", "foo"), ("attr2", "bar")]
        @test_throws ArgumentError eachattribute(doc.node)
        @test_throws ArgumentError attributes(doc.node)
    end
end

@testset "Properties" begin
    doc = readxml(joinpath(dirname(@__FILE__), "sample1.xml"))
    @test doc.version == "1.0"
    @test doc.encoding === nothing
    doc = readxml(joinpath(dirname(@__FILE__), "sample2.xml"))
    @test doc.version == "1.0"
    @test doc.encoding == "UTF-8"

    doc = parsexml("<root/>")
    @test doc.node isa EzXMLPatched.Node
    @test doc.node.type === EzXMLPatched.DOCUMENT_NODE
    @test doc.node.name === nothing
    @test doc.node.path == "/"
    @test doc.node.content == ""
    @test doc.node.namespace === nothing
    @test doc.root isa EzXMLPatched.Node
    @test doc.root.type === EzXMLPatched.ELEMENT_NODE
    @test doc.root.name == "root"
    @test doc.root.path == "/root"
    @test doc.root.content == ""
    @test doc.root.namespace === nothing
    @test doc.dtd === nothing

    doc = parsexml("""<root attr="100">some content</root>""")
    @test doc.root.content == "some content"
    attr = attributes(doc.root)[1]
    @test attr.type === EzXMLPatched.ATTRIBUTE_NODE
    @test attr.name == "attr"
    @test attr.path == "/root/@attr"
    @test attr.content == "100"
    @test attr.namespace === nothing

    doc = parsexml("""

        <title>Title</title>
        Body

    """)
    @test doc.root.namespace == "http://www.w3.org/1999/xhtml"
    head = firstelement(doc.root)
    body = lastelement(doc.root)
    @test head.namespace == body.namespace == "http://www.w3.org/1999/xhtml"

    # node traversal
    doc = parsexml("""
    <root>
        <c1/>
        <c2/>
        <c3/>
    </root>
    """)
    @test doc.root.document === doc
    @test doc.root.parentnode === doc.node
    @test doc.root.parentelement === nothing
    @test doc.root.firstnode.type === EzXMLPatched.TEXT_NODE
    @test doc.root.lastnode.type === EzXMLPatched.TEXT_NODE
    @test doc.root.firstelement.name == "c1"
    @test doc.root.lastelement.name  == "c3"
    @test doc.root.firstnode.nextnode === doc.root.firstelement
    @test doc.root.firstnode.prevnode === nothing
    @test doc.root.firstelement.nextelement === doc.root.lastelement.prevelement

    # setproperty!
    elm = ElementNode("foo")
    # name
    @test elm.name == "foo"
    elm.name = "bar"
    @test elm.name == "bar"
    elm.name = 100
    @test elm.name == "100"
    # content
    @test elm.content == ""
    elm.content = "hi there"
    @test elm.content == "hi there"
    elm.content = 3.14
    @test elm.content == "3.14"
end

@testset "Construction" begin
    doc = XMLDocument()
    @test isa(doc, EzXMLPatched.Document)
    @test nodetype(doc.node) === EzXMLPatched.DOCUMENT_NODE
    @test !hasroot(doc)
    @test_throws ArgumentError root(doc)
    r1 = ElementNode("r1")
    @test setroot!(doc, r1) === r1
    @test hasroot(doc)
    @test root(doc) === r1
    @test_throws ArgumentError setroot!(doc, TextNode("some text"))
    r2 = ElementNode("r2")
    setroot!(doc, r2)
    @test root(doc) == r2
    @test r1.owner === r1

    doc = XMLDocument()
    el = ElementNode("el")
    setroot!(doc, el)
    @test nodename(el) == "el"
    setnodename!(el, "EL")
    @test nodename(el) == "EL"
    @test nodecontent(el) == ""
    setnodecontent!(el, "some content")
    @test nodecontent(el) == "some content"

    doc = XMLDocument()
    @test countnodes(doc.node) === 0
    d1 = DTDNode("hello", "hello.dtd")
    @test setdtd!(doc, d1) === d1
    @test countnodes(doc.node) === 1
    @test dtd(doc) === d1
    setroot!(doc, ElementNode("root"))
    @test countnodes(doc.node) === 2
    @test nextnode(d1) === root(doc)
    d2 = DTDNode("hello", "hello2.dtd")
    @test setdtd!(doc, d2) === d2
    @test countnodes(doc.node) === 2
    @test dtd(doc) === d2
    @test_throws ArgumentError setdtd!(doc, ElementNode("foo"))

    # <e1>t1<e2>t2<e3 a1="val"/></e2></e1>
    doc = XMLDocument()
    e1 = ElementNode("e1")
    e2 = ElementNode("e2")
    e3 = ElementNode("e3")
    t1 = TextNode("t1")
    t2 = TextNode("t2")
    a1 = AttributeNode("a1", "val")
    setroot!(doc, e1)
    link!(e1, t1)
    link!(e1, e2)
    link!(e2, t2)
    link!(e2, e3)
    link!(e3, a1)
    @test root(doc) === e1
    @test document(e1) === doc
    @test document(e2) === doc
    @test document(e3) === doc
    @test document(t1) === doc
    @test document(t2) === doc
    @test document(a1) === doc
    @test e1.owner === doc.node
    @test e2.owner === doc.node
    @test e3.owner === doc.node
    @test t1.owner === doc.node
    @test t2.owner === doc.node
    @test a1.owner === doc.node
    @test e2 ∈ nodes(e1)
    unlink!(e2)
    @test e2 ∉ nodes(e1)
    @test root(doc) === e1
    @test document(e1) === doc
    @test document(t1) === doc
    @test !hasdocument(e2)
    @test !hasdocument(e3)
    @test !hasdocument(t2)
    @test !hasdocument(a1)
    @test e1.owner === doc.node
    @test t1.owner === doc.node
    @test e2.owner === e2
    @test e3.owner === e2
    @test t2.owner === e2
    @test a1.owner === e2

    doc = parsexml("<root/>")
    @test isempty(nodes(root(doc)))
    c1 = ElementNode("c1")
    link!(root(doc), c1)
    @test nodes(root(doc)) == [c1]
    c2 = ElementNode("c2")
    linknext!(c1, c2)
    @test nodes(root(doc)) == [c1, c2]
    c0 = ElementNode("c0")
    linkprev!(c1, c0)
    @test nodes(root(doc)) == [c0, c1, c2]

    doc = XMLDocument()
    @test !hasparentnode(doc.node)
    @test !hasparentelement(doc.node)
    @test_throws ArgumentError parentelement(doc.node)
    x = ElementNode("x")
    setroot!(doc, x)
    @test hasparentnode(x)
    @test !hasparentelement(x)
    @test_throws ArgumentError parentelement(x)
    y = ElementNode("y")
    link!(x, y)
    @test hasparentnode(y)
    @test hasparentelement(y)
    @test parentelement(y) == x

    el = ElementNode("el")
    el["attr1"] = "1"
    el["attr2"] = "2"
    doc = XMLDocument()
    setroot!(doc, el)
    @test root(doc) == el
    @test [(nodename(n), nodecontent(n)) for n in attributes(root(doc))] == [("attr1", "1"), ("attr2", "2")]

    doc = parsexml("""
    <root></root>
    """)
    @test string(doc.node) == """
    <?xml version="1.0" encoding="UTF-8"?>
    <root/>
    """
    @test !hasnode(root(doc))
    c1 = ElementNode("child1")
    link!(root(doc), c1)
    @test hasnode(root(doc))
    c2 = ElementNode("child2")
    link!(root(doc), c2)
    @test nodes(root(doc)) == [c1, c2]
    @test !hasnode(c1)
    link!(c1, TextNode("some text"))
    @test hasnode(c1)
    c3 = CommentNode("some comment")
    link!(root(doc), c3)
    c4 = CDataNode("<cdata>")
    link!(root(doc), c4)
    @test string(doc.node) == """
    <?xml version="1.0" encoding="UTF-8"?>
    <root><child1>some text</child1><child2/><![CDATA[<cdata>]]></root>
    """

    doc = parsexml("""
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <c1>
            <c2>
                <c3>ok</c3>
            </c2>
        </c1>
    </root>
    """)
    @test haselement(root(doc))
    c1 = firstelement(root(doc))
    c2 = firstelement(c1)
    @test unlink!(c1) == c1
    @test !haselement(root(doc))
    @test c1.owner == c1
    @test c2.owner == c1

    doc = parsexml("""
    <root xmlns:x="http://xxx.org/" xmlns:y="http://yyy.org/">
        <c x:attr="x-attr" y:attr="y-attr"/>
        <c y:attr="y-attr" x:attr="x-attr"/>
        <c x:attr=""/>
    </root>
    """)
    c = firstelement(root(doc))
    @test !haskey(c, "attr")
    @test haskey(c, "x:attr")
    @test haskey(c, "y:attr")
    @test !haskey(c, "z:attr")
    @test c["x:attr"] == "x-attr"
    @test c["y:attr"] == "y-attr"
    @test_throws KeyError c["attr"]
    @test_throws ArgumentError c["z:attr"]
    c = nextelement(c)
    @test !haskey(c, "attr")
    @test haskey(c, "x:attr")
    @test haskey(c, "y:attr")
    @test c["y:attr"] == "y-attr"
    @test c["x:attr"] == "x-attr"
    c = nextelement(c)
    c["x:attr"] = "x-attr"
    @test c["x:attr"] == "x-attr"
    c["y:attr"] = "y-attr"
    @test c["y:attr"] == "y-attr"
    delete!(c, "x:attr")
    @test !haskey(c, "x:attr")
    delete!(c, "y:attr")
    @test !haskey(c, "y:attr")
    delete!(c, "z:attr")

    # move <child/> of doc1 to doc2
    doc1 = parsexml("<root><child/></root>")
    doc2 = parsexml("<root/>")
    child = firstelement(root(doc1))
    @test_throws ArgumentError link!(root(doc2), child)
    unlink!(child)
    link!(root(doc2), child)
    @test child ∉ eachnode(root(doc1))
    @test child ∈ eachnode(root(doc2))

    doc1 = parsexml("<root><child/></root>")
    doc2 = parsexml("<root><target/></root>")
    child = firstelement(root(doc1))
    target = firstelement(root(doc2))
    @test_throws ArgumentError linknext!(target, child)
    @test_throws ArgumentError linkprev!(target, child)

    # Issue #28
    doc = readxml(joinpath(dirname(@__FILE__), "sample1.xml"))
    unlink!(firstelement(root(doc)))
    # No need to check the return value because this is a bug of memory
    # management. Regression will be detected as a SIGABRT.
    @test true
end

@testset "Validation" begin
    dtdfile = joinpath(dirname(@__FILE__), "note.dtd")
    system = relpath(dtdfile)
    if Sys.iswindows()
        system = replace(system, '\\' => '/')
    end

    doc = parsexml("""
    <?xml version="1.0"?>
    <!DOCTYPE note SYSTEM "$(system)">
    <note>
        <title>Note title</title>
        Note body
    </note>
    """)
    @test isempty(validate(doc))

    doc = parsexml("""
    <?xml version="1.0"?>
    <!DOCTYPE note SYSTEM "$(system)">
    <note>
        Note body
    </note>
    """)
    @test !isempty(validate(doc))

    doc = parsexml("""
    <?xml version="1.0"?>
    <note>
        <title>Note title</title>
        Note body
    </note>
    """)
    @test !isempty(validate(doc))

    doc = parsexml("""
    <?xml version="1.0"?>
    <note>
        <title>Note title</title>
        Note body
    </note>
    """)
    dtd = readdtd(dtdfile)
    @test isempty(validate(doc, dtd))
end

@testset "XPath" begin
    doc = parsexml("""
    <?xml version="1.0"?>
    <root>
        <foo>
            <bar>1</bar>
        </foo>
        <foo>
            <bar>2</bar>
            <bar>3</bar>
        </foo>
    </root>
    """)
    @test length(findall("/root", doc)) == 1
    @test findall("/root", doc)[1] === root(doc)
    @test length(findall("/root/foo", doc)) == 2
    @test findall("/root/foo", doc)[1] === elements(root(doc))[1]
    @test findall("/root/foo", doc)[2] === elements(root(doc))[2]
    for (i, node) in enumerate(findall("//bar", doc))
        @test nodename(node) == "bar"
        @test nodecontent(node) == string(i)
    end
    for (i, node) in enumerate(findall("//bar/text()", doc))
        @test nodename(node) == "text"
        @test nodecontent(node) == string(i)
    end
    @test findfirst("//bar", doc) === findall("//bar", doc)[1]
    @test findlast("//bar", doc) === findall("//bar", doc)[3]
    @test length(findall("/baz", doc)) == 0
    @test_throws EzXMLPatched.XMLError findall("//bar!", doc)
    @test findall("foo", root(doc)) == findall("//foo", doc)
    @test findfirst("foo", root(doc)) === findfirst("//foo", doc)
    @test findlast("foo", root(doc)) === findlast("//foo", doc)
    @test findall("root", doc) == findall("/root", root(doc))
    @test findall("foo", root(doc)) == findall("//foo", doc)
    @test findfirst("bambam", doc) === nothing
    @test findlast("bambam", doc) === nothing
    @test findfirst("bambam", root(doc)) === nothing
    @test findlast("bambam", root(doc)) === nothing

    go = readxml(joinpath(dirname(@__FILE__), "go.sample.xml"))
    go_uri =  "http://www.geneontology.org/dtds/go.dtd#"
    @test findall("/go:go", root(go)) == [root(go)]
    @test findfirst("/go:go", root(go)) === root(go)
    @test findlast("/go:go", root(go)) === root(go)
    @test findall("/g:go", root(go), ["g" => go_uri]) == [root(go)]
    @test findfirst("/g:go", root(go), ["g" => go_uri]) === root(go)
    @test findlast("/g:go", root(go), ["g" => go_uri]) === root(go)
    @test nodename.(findall("/go:go/rdf:RDF/go:term", root(go))) == ["term", "term"]
    @test findall("/go:go/rdf:RDF/go:term", root(go)) == findall("//go:term", root(go))

    # default namespace
    doc = parsexml("""
    <go xmlns="http://www.geneontology.org/dtds/go.dtd#">
        <term><accession>GO:0000001</accession></term>
    </go>
    """)
    warnmsg = "ignored the empty prefix for 'http://www.geneontology.org/dtds/go.dtd#'; expected to be non-empty"
    @test isempty(@test_logs (:warn, warnmsg) findall("term", root(doc)))
    @test isempty(@test_logs (:warn, warnmsg) findall("./term", root(doc)))
    @test findall("go:term", root(doc), ["go" => "http://www.geneontology.org/dtds/go.dtd#"]) == elements(root(doc))
    @test findall("./go:term", root(doc), ["go" => "http://www.geneontology.org/dtds/go.dtd#"]) == elements(root(doc))

    # pull/8
    doc = parsexml("""<root xmlns="urn:foo"/>""")
    @test isempty(findall("//foo:notexit/*", root(doc), [("foo", "urn:foo")]))
end

@testset "Misc" begin
    @testset "show" begin
        doc = parsexml("""<root attr="val"/>""")
        @test occursin(r"^Node\(<DOCUMENT_NODE>\)$", repr(doc.node))
        @test occursin(r"^Node\(<ELEMENT_NODE\[root\]>\)$", repr(root(doc)))
        @test occursin(r"^Node\(<ATTRIBUTE_NODE\[attr\]>\)$", repr(attributes(root(doc))[1]))
        @test occursin(r"^EzXMLPatched.Document\(Node\(<DOCUMENT_NODE>\)\)$", repr(doc))

        sample2 = joinpath(dirname(@__FILE__), "sample2.xml")
        reader = open(EzXMLPatched.StreamReader, sample2)
        @test occursin(r"^StreamReader\(<[A-Z_]+>\)$", repr(reader))
        close(reader)
    end

    @testset "print" begin
        elm = ElementNode("elm")
        @test string(elm) == "<elm/>"

        txt = TextNode("42 > 41")
        @test string(txt) == "42 > 41"

        cdata = CDataNode("42 > 41")
        @test string(cdata) == "<![CDATA[42 > 41]]>"

        comment = CommentNode("some comment")
        @test string(comment) == ""

        doc = parsexml("<e1><e2/></e1>")
        buf = IOBuffer()
        print(buf, doc)
        @test take!(buf) == b"""
        <?xml version="1.0" encoding="UTF-8"?>
        <e1><e2/></e1>
        """

        doc = parsexml("<e1><e2/></e1>")
        buf = IOBuffer()
        prettyprint(buf, doc)
        @test take!(buf) == b"""
        <?xml version="1.0" encoding="UTF-8"?>
        <e1>
          <e2/>
        </e1>
        """
    end
end

# Check no uncaught errors.
@test isempty(EzXMLPatched.XML_GLOBAL_ERROR_STACK)

if Sys.isunix()
    julia = joinpath(Sys.BINDIR, "julia")
    @testset "Examples" begin
        # Check examples work without error.
        cd(joinpath(dirname(@__FILE__), "..", "example")) do
            stdout = devnull

            @testset "primates.jl" begin
                try
                    run(pipeline(`$(julia) primates.jl`, stdout=stdout))
                    @test true
                catch
                    @test false
                end
            end

            @testset "julia2xml.jl" begin
                try
                    run(pipeline(pipeline(`echo "1 + sum([2,3])"`, `$(julia) julia2xml.jl`), stdout=stdout))
                    @test true
                catch
                    @test false
                end
            end

            @testset "listlinks.jl" begin
                try
                    links = joinpath(dirname(@__FILE__), "links.html")
                    run(pipeline(`$(julia) listlinks.jl $(links)`, stdout=stdout))
                    @test true
                catch
                    @test false
                end
            end
        end
    end
end

# Stress tests
# ------------
#
# Check the memory usage using the top command or something.

macro showprogress(name, loop)
    push!(loop.args[2].args, :(if n % 1000 == 0; print('\r', rpad($(name), 12), round(Int, n / N * 100), "%"); end))
    return :($loop; println())
end

if "stress" in ARGS
    const N = 1_000_000

    function parse_xml()
        @showprogress "parse_xml" for n in 1:N
            parsexml("""
            <?xml version="1.0" encoding="UTF-8"?>
            <root>
                <child>text</child>
                <child>text</child>
                <child>text</child>
            </root>
            """)
        end
    end

    function link_xml()
        @showprogress "link_xml" for n in 1:N
            doc = parsexml("""
            <?xml version="1.0" encoding="UTF-8"?>
            <root/>
            """)
            child = ElementNode("child")
            link!(root(doc), child)
            grandchild = ElementNode("grandchild")
            link!(child, grandchild)
        end
    end

    function unlink_xml()
        @showprogress "unlink_xml" for n in 1:N
            doc = parsexml("""
            <?xml version="1.0" encoding="UTF-8"?>
            <root>
                <child>
                    <grandchild attr="attribute value">text</grandchild>
                </child>
            </root>
            """)
            child = firstelement(root(doc))
            unlink!(child)
        end
    end

    function swap_xml()
        @showprogress "swap_xml" for n in 1:N
            doc1 = parsexml("<c/>")
            doc2 = parsexml("<c/>")
            b1 = firstelement(root(doc1))
            b2 = firstelement(root(doc2))
            unlink!(b1)
            link!(root(doc2), b1)
            unlink!(b2)
            link!(root(doc1), b2)
        end
    end

    parse_xml()
    link_xml()
    unlink_xml()
    swap_xml()
end


text:
using FrankWolfe
using LinearAlgebra
using SparseArrays

@testset "Timing out" begin
    f(x) = norm(x)^2
    function grad!(storage, x)
        return storage .= 2x
    end
    lmo_prob = FrankWolfe.ProbabilitySimplexOracle(1)
    x0 = FrankWolfe.compute_extreme_point(lmo_prob, spzeros(5))
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Agnostic(),
            verbose=true,
        )[3] - 0.2,
    ) < 1.0e-5
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Agnostic(),
            verbose=false,
            gradient=collect(similar(x0)),
        )[3] - 0.2,
    ) < 1.0e-5
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Goldenratio(),
            verbose=true,
        )[3] - 0.2,
    ) < 1.0e-5
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Backtracking(),
            verbose=false,
        )[3] - 0.2,
    ) < 1.0e-5
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Nonconvex(),
            verbose=false,
        )[3] - 0.2,
    ) < 1.0e-2
    @test FrankWolfe.frank_wolfe(
        f,
        grad!,
        lmo_prob,
        x0,
        max_iteration=1000,
        line_search=FrankWolfe.Shortstep(),
        L=2,
        verbose=false,
    )[3] ≈ 0.2
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Nonconvex(),
            verbose=false,
        )[3] - 0.2,
    ) < 1.0e-2
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Agnostic(),
            verbose=false,
            momentum=0.9,
        )[3] - 0.2,
    ) < 1.0e-3
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Agnostic(),
            verbose=false,
            momentum=0.5,
        )[3] - 0.2,
    ) < 1.0e-3
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Agnostic(),
            verbose=false,
            momentum=0.9,
            emphasis=FrankWolfe.memory,
        )[3] - 0.2,
    ) < 1.0e-3
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Adaptive(),
            L=100,
            verbose=false,
            momentum=0.9,
        )[3] - 0.2,
    ) < 1.0e-3
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Adaptive(),
            L=100,
            verbose=false,
            momentum=0.5,
        )[3] - 0.2,
    ) < 1.0e-3
    @test abs(
        FrankWolfe.frank_wolfe(
            f,
            grad!,
            lmo_prob,
            x0,
            max_iteration=1000,
            line_search=FrankWolfe.Adaptive(),
            L=100,
            verbose=false,
            momentum=0.9,
            emphasis=FrankWolfe.memory,
        )[3] - 0.2,
    ) < 1.0e-3
end


text:
abstract type AbstractTimeIntegrationMethod end

"""
    RungeKuttaMethod(A, b, c=vec(sum(A, dims=2)))

Represent a Runge-Kutta method with Butcher coefficients `A`, `b`, and `c`.
If `c` is not provided, the usual "row sum" requirement of consistency with
autonomous problems is applied.
"""
struct RungeKuttaMethod{T, MatT<:AbstractMatrix{T}, VecT<:AbstractVector{T}} <: AbstractTimeIntegrationMethod
  A::MatT
  b::VecT
  c::VecT
end

function RungeKuttaMethod(A::AbstractMatrix, b::AbstractVector, c::AbstractVector=vec(sum(A, dims=2)))
  T = promote_type(eltype(A), eltype(b), eltype(c))
  _A = T.(A)
  _b = T.(b)
  _c = T.(c)
  return RungeKuttaMethod(_A, _b, _c)
end

Base.eltype(rk::RungeKuttaMethod{T}) where {T} = T

function Base.show(io::IO, rk::RungeKuttaMethod)
  print(io, "RungeKuttaMethod{", eltype(rk), "}")
  if get(io, :compact, false)
    print(io, "(")
    show(io, rk.A)
    print(io, ", ")
    show(io, rk.b)
    print(io, ", ")
    show(io, rk.c)
    print(io, ")")
  else
    print(io, " with\nA: ")
    show(io, MIME"text/plain"(), rk.A)
    print(io, "\nb: ")
    show(io, MIME"text/plain"(), rk.b)
    print(io, "\nc: ")
    show(io, MIME"text/plain"(), rk.c)
    print(io, "\n")
  end
end

"""
    elementary_weight(t::RootedTree, rk::RungeKuttaMethod)
    elementary_weight(t::RootedTree, A::AbstractMatrix, b::AbstractVector, c::AbstractVector)

Compute the elementary weight Φ(`t`) of the [`RungeKuttaMethod`](@ref) `rk`
with Butcher coefficients `A, b, c` for a rooted tree `t``.

Reference: Section 312 of
- Butcher, John Charles.
  Numerical methods for ordinary differential equations.
  John Wiley & Sons, 2008.
"""
function elementary_weight(t::RootedTree, rk::RungeKuttaMethod)
  dot(rk.b, derivative_weight(t, rk))
end

# TODO: Deprecate also this method?
function elementary_weight(t::RootedTree, A::AbstractMatrix, b::AbstractVector, c::AbstractVector)
  elementary_weight(t, RungeKuttaMethod(A, b, c))
end

"""
    derivative_weight(t::RootedTree, rk::RungeKuttaMethod)

Compute the derivative weight (ΦᵢD)(`t`) of the [`RungeKuttaMethod`](@ref) `rk`
with Butcher coefficients `A, b, c` for the rooted tree `t`.

Reference: Section 312 of
- Butcher, John Charles.
  Numerical methods for ordinary differential equations.
  John Wiley & Sons, 2008.
"""
function derivative_weight(t::RootedTree, rk::RungeKuttaMethod)
  A = rk.A
  c = rk.c

  # Initialize `result` with the identity element of pointwise multiplication `.*`
  result = zero(c) .+ one(eltype(c))

  # Iterate over all subtrees and update the `result` using recursion
  for subtree in SubtreeIterator(t)
    tmp = A * derivative_weight(subtree, rk)
    result = result .* tmp
  end

  return result
end

# TODO: Deprecations introduced in v2
@deprecate derivative_weight(t::RootedTree, A, b, c) derivative_weight(t, RungeKuttaMethod(A, b, c))

"""
    residual_order_condition(t::RootedTree, rk::RungeKuttaMethod)

The residual of the order condition
  `(Φ(t) - 1/γ(t)) / σ(t)`
with [`elementary_weight`](@ref) `Φ(t)`, [`density`](@ref) `γ(t)`, and
[`symmetry`](@ref) `σ(t)` of the [`RungeKuttaMethod`](@ref) `rk` with Butcher
coefficients `A, b, c` for the rooted tree `t`.

Reference: Section 315 of
- Butcher, John Charles.
  Numerical methods for ordinary differential equations.
  John Wiley & Sons, 2008.
"""
function residual_order_condition(t::RootedTree, rk::RungeKuttaMethod)
  ew = elementary_weight(t, rk)
  T = typeof(ew)

  (ew - one(T) / γ(t)) / σ(t)
end

# TODO: Deprecations introduced in v2
@deprecate residual_order_condition(t::RootedTree, A, b, c) residual_order_condition(t, RungeKuttaMethod(A, b, c))

"""
    AdditiveRungeKuttaMethod(rks)
    AdditiveRungeKuttaMethod(As, bs, cs=map(A -> vec(sum(A, dims=2)), As))

Represent an additive Runge-Kutta method with collections of Butcher
coefficients `As`, `bs`, and `cs`. Alternatively, you can pass a collection of
[`RungeKuttaMethod`](@ref)s to the constructor.
If the `cs` are not provided, the usual "row sum" requirement of consistency
with autonomous problems is applied.

An additive Runge-Kutta method applied to the ODE problem
```math
  u'(t) = \\sum_\\nu f^\\nu(t, u(t))
```
has the form
```math
\\begin{aligned}
  y^i &= u^n + \\Delta t \\sum_\\nu \\sum_j a^\\nu_{i,j} f^\\nu(y^i), \\\\
  u^{n+1} &= u^n + \\Delta t \\sum_\\nu \\sum_i b^\\nu_{i} f^\\nu(y^i).
\\end{aligned}
```

In particular, additive Runge-Kutta methods are a superset of partitioned RK
methods, which are applied to partitioned problems of the form
```math
  (u^1)'(t) = f^1(t, u^1, u^2),
  \\quad
  (u^2)'(t) = f^2(t, u^1, u^2).
```

# References

- A. L. Araujo, A. Murua, and J. M. Sanz-Serna.
  "Symplectic Methods Based on Decompositions".
  SIAM Journal on Numerical Analysis 34.5 (1997): 1926-1947.
  [DOI: 10.1137/S0036142995292128](https://doi.org/10.1137/S0036142995292128)
"""
struct AdditiveRungeKuttaMethod{T, RKs<:AbstractVector{<:RungeKuttaMethod{T}}} <: AbstractTimeIntegrationMethod
  rks::RKs
end

function AdditiveRungeKuttaMethod(rks) # if not all RK methods use the same eltype
  T = mapreduce(eltype, promote_type, rks)
  As = map(rk -> T.(rk.A), rks)
  bs = map(rk -> T.(rk.b), rks)
  cs = map(rk -> T.(rk.c), rks)
  AdditiveRungeKuttaMethod(As, bs, cs)
end

function AdditiveRungeKuttaMethod(As, bs, cs=map(A -> vec(sum(A, dims=2)), As))
  rks = map(RungeKuttaMethod, As, bs, cs)
  AdditiveRungeKuttaMethod(rks)
end

Base.eltype(ark::AdditiveRungeKuttaMethod{T}) where {T} = T

function Base.show(io::IO, ark::AdditiveRungeKuttaMethod)
  print(io, "AdditiveRungeKuttaMethod{", eltype(ark), "} with methods\n")
  for (idx, rk) in enumerate(ark.rks)
    print(io, idx, ". ")
    show(io, rk)
  end
end

# Colored trees are used for order conditions of additive Runge-Kutta methods.
# The function `color_to_index` maps a color to a one-based index of ARK
# coefficients.
# This is considered to be an internal interface but stable across minor/patch
# releases.
color_to_index(color::Integer) = Int(color)
color_to_index(color::Bool) = 1 + color

"""
    elementary_weight(t::ColoredRootedTree, ark::AdditiveRungeKuttaMethod)

Compute the elementary weight Φ(`t`) of the [`AdditiveRungeKuttaMethod`](@ref)
`ark` for a colored rooted tree `t``.

# References

- A. L. Araujo, A. Murua, and J. M. Sanz-Serna.
  "Symplectic Methods Based on Decompositions".
  SIAM Journal on Numerical Analysis 34.5 (1997): 1926–1947.
  [DOI: 10.1137/S0036142995292128](https://doi.org/10.1137/S0036142995292128)
- Butcher, John Charles.
  Numerical methods for ordinary differential equations.
  John Wiley & Sons, 2008.
  Section 312
"""
function elementary_weight(t::ColoredRootedTree, ark::AdditiveRungeKuttaMethod)
  # TODO: Check number of RK methods in `ark`?
  if isempty(t)
    return one(eltype(first(ark.rks).c))
  else
    color = first(t.color_sequence)
    dot(ark.rks[color_to_index(color)].b, derivative_weight(t, ark))
  end
end

"""
    derivative_weight(t::ColoredRootedTree, ark::AdditiveRungeKuttaMethod)

Compute the derivative weight (ΦᵢD)(`t`) of the [`AdditiveRungeKuttaMethod`](@ref)
`ark` for the colored rooted tree `t`.

# References

- A. L. Araujo, A. Murua, and J. M. Sanz-Serna.
  "Symplectic Methods Based on Decompositions".
  SIAM Journal on Numerical Analysis 34.5 (1997): 1926–1947.
  [DOI: 10.1137/S0036142995292128](https://doi.org/10.1137/S0036142995292128)
- Butcher, John Charles.
  Numerical methods for ordinary differential equations.
  John Wiley & Sons, 2008.
  Section 312
"""
function derivative_weight(t::ColoredRootedTree, ark::AdditiveRungeKuttaMethod)
  # Initialize `result` with the identity element of pointwise multiplication `.*`
  c = first(ark.rks).c
  result = zero(c) .+ one(eltype(c))

  # Iterate over all subtrees and update the `result` using recursion
  for subtree in SubtreeIterator(t)
    A = ark.rks[color_to_index(first(subtree.color_sequence))].A
    tmp = A * derivative_weight(subtree, ark)
    result = result .* tmp
  end

  return result
end

"""
    residual_order_condition(t::ColoredRootedTree, ark::AdditiveRungeKuttaMethod)

The residual of the order condition
  `(Φ(t) - 1/γ(t)) / σ(t)`
with [`elementary_weight`](@ref) `Φ(t)`, [`density`](@ref) `γ(t)`, and
[`symmetry`](@ref) `σ(t)` of the [`AdditiveRungeKuttaMethod`](@ref) `ark`
for the colored rooted tree `t`.

# References

- A. L. Araujo, A. Murua, and J. M. Sanz-Serna.
  "Symplectic Methods Based on Decompositions".
  SIAM Journal on Numerical Analysis 34.5 (1997): 1926–1947.
  [DOI: 10.1137/S0036142995292128](https://doi.org/10.1137/S0036142995292128)
- Butcher, John Charles.
  Numerical methods for ordinary differential equations.
  John Wiley & Sons, 2008.
  Section 312
"""
function residual_order_condition(t::ColoredRootedTree, ark::AdditiveRungeKuttaMethod)
  ew = elementary_weight(t, ark)
  T = typeof(ew)

  (ew - one(T) / γ(t)) / σ(t)
end


text:
using FastAI
using Documenter

makedocs(;
    modules=[FastAI],
    authors="Peter Wolf, Julia Community",
    repo="https://github.com/FluxML/FastAI.jl/blob/{commit}{path}#L{line}",
    sitename="FastAI.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://FluxML.github.io/FastAI.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
        "Getting Started" => "getting-started.md",
        "Training" => [
            "Overview" => "training/training.md",
            "Basic Train" => "training/basic-train.md",
        ],
        "Core" => [
            "Overview" => "core/core.md",
            "Torch Core" => "core/torch-core.md",
            "Basic Data" => "core/basic-data.md",
        ],
    ],
)

deploydocs(;
    repo="github.com/FluxML/FastAI.jl",
)


text:
"""
Exact and Tractable Algorithm for Solving the Two-stage Stochastic Unit Commitment Problem

Alvaro Gonzalez - alvaro.gonzalez@skolkovotech.ru
Moscow, July 2021
"""

## 0. SETUP
# 0.0. Setting working directory
cur_path, fileName = splitdir(Base.source_path())
  cd(cur_path[1:end-4])
  println()
  println("The current working directory is: "*pwd())

    # 0.1. Running setup file
    ENV["GRB_LICENSE_FILE"] = "C:\\Users\\ajcas\\gurobi.lic"
    using Revise
    includet("setup.jl")

max_stars_repo_name: gonzalez-alvaro/MultidimensionalGAPM

max_issues_repo_name: gonzalez-alvaro/MultidimensionalGAPM

max_forks_repo_name: gonzalez-alvaro/MultidimensionalGAPM