text:
@testset "Fitness" begin
    @testset "hat_compare() Float64" begin
        @test hat_compare(1.0, 2.0) == -1
        @test hat_compare(-1.0, 1.0) == -1

        @test hat_compare(2.0, 1.0) == 1
        @test hat_compare(-2.0, -3.0) == 1

        @test hat_compare(1.0, 1.0) == 0
        @test hat_compare(0.0, 0.0) == 0
        @test hat_compare(-1.0, -1.0) == 0

        @test hat_compare(0.0, NaN) == -1
        @test hat_compare(NaN, 1.0) ==  1
        @test hat_compare(NaN, NaN) ==  0
    end

    @testset "ScalarFitnessScheme" begin
        @testset "is_minimizing()" begin
            mins = MinimizingFitnessScheme
            @test numobjectives(mins) == 1
            @test fitness_type(mins) === Float64
            @test fitness_eltype(mins) === Float64
            @test is_minimizing(mins)

            maxs = MaximizingFitnessScheme
            @test numobjectives(maxs) == 1
            @test fitness_type(maxs) === Float64
            @test fitness_eltype(maxs) === Float64
            @test is_minimizing(maxs) == false
        end

        @testset "hat_compare(..., MinimizingFitnessScheme)" begin
            scheme = MinimizingFitnessScheme

            @test hat_compare(1.0, 2.0, scheme) == -1
            @test hat_compare(2.0, 1.0, scheme) == 1
            @test hat_compare(1.0, 1.0, scheme) == 0
        end

        @testset "hat_compare(..., MaximizingFitnessScheme)" begin
            scheme = MaximizingFitnessScheme

            @test hat_compare(1.0, 2.0, scheme) == 1
            @test hat_compare(2.0, 1.0, scheme) == -1
            @test hat_compare(1.0, 1.0, scheme) == 0
        end

        # FIXME enable tests once v0.5 issue #14919 is fixed
        @testset "fitness_scheme(x, y)" begin
            mins = MinimizingFitnessScheme
            #@test !mins(5.0, 3.0)
            #@test mins(1.0, 2.0)

            maxs = MaximizingFitnessScheme
            #@test !maxs(3.0, 5.0)
            #@test maxs(2.0, 1.0)
        end
    end

    @testset "TupleFitnessScheme" begin
        @testset "general interface" begin
            @testset "ParetoFitnessScheme{1}" begin
                scheme = ParetoFitnessScheme{1}()
                @test numobjectives(scheme) == 1
                @test fitness_type(scheme) === Tuple{Float64}
                @test fitness_eltype(scheme) === Float64
                @test is_minimizing(scheme)
                @test isnafitness(nafitness(scheme), scheme)
                @test isequal(nafitness(scheme), (NaN,))
                @test isnafitness((NaN,), scheme)
                @test isnafitness((1.0,), scheme) == false
            end

            @testset "ParetoFitnessScheme{1}(is_minimizing=false)" begin
                scheme = ParetoFitnessScheme{1}(is_minimizing=false)
                @test fitness_type(scheme) == NTuple{1, Float64}
                @test fitness_eltype(scheme) === Float64
                @test numobjectives(scheme) == 1
                @test is_minimizing(scheme) == false
                @test isnafitness(nafitness(scheme), scheme)
                @test isequal(nafitness(scheme), (NaN,))
                @test isnafitness((NaN,), scheme)
                @test isnafitness((1.0,), scheme) == false
            end

            @testset "ParetoFitnessScheme{2}()" begin
                scheme = ParetoFitnessScheme{2}()
                @test fitness_type(scheme) == NTuple{2, Float64}
                @test fitness_eltype(scheme) === Float64
                @test isequal(nafitness(scheme), (NaN,NaN))
                @test numobjectives(scheme) == 2
                @test is_minimizing(scheme)
                @test isnafitness(nafitness(scheme), scheme)
                @test isnafitness((NaN, NaN), scheme)
                @test isnafitness((1.0, NaN), scheme)
                @test !isnafitness((1.0, 2.0), scheme)
            end

            @testset "ParetoFitnessScheme{3}()" begin
                scheme = ParetoFitnessScheme{3}()
                @test fitness_type(scheme) == NTuple{3, Float64}
                @test fitness_eltype(scheme) === Float64
                @test isequal(nafitness(scheme), (NaN,NaN,NaN))
                @test numobjectives(scheme) == 3
                @test is_minimizing(scheme)
                @test isnafitness(nafitness(scheme), scheme)
                @test isnafitness((NaN,NaN,NaN), scheme)
                @test isnafitness((1.0,NaN,2.0), scheme)
                @test isnafitness((1.0,2.0,2.0), scheme) == false
            end
        end

        @testset "hat_compare(..., ParetoFitnessScheme{1}())" begin
            scheme = ParetoFitnessScheme{1}()

            @test_throws MethodError hat_compare((-1.0,), (1.0, 2.0), scheme)

            @test hat_compare((-1.0,), (1.0,), scheme) == -1
            @test hat_compare((0.0,), (0.3,), scheme) == -1
            @test hat_compare((11.3,), (354.65,), scheme) == -1

            @test hat_compare((-1.0,), (-1.0,), scheme) == 0
            @test hat_compare((0.0,), (0.0,), scheme) == 0
            @test hat_compare((0.2,), (0.2,), scheme) == 0

            @test hat_compare((1.0,), (0.0,), scheme) == 1
            @test hat_compare((0.0,), (-0.4,), scheme) == 1
            @test hat_compare((-0.65,), (-34.2,), scheme) == 1
        end

        @testset "hat_compare(..., ParetoFitnessScheme{1}(is_minimizing=false))" begin
            scheme = ParetoFitnessScheme{1}(is_minimizing=false)
            @test hat_compare((-1.0,), (1.0,), scheme) == 1
            @test hat_compare((0.0,), (0.3,), scheme) == 1
            @test hat_compare((11.3,), (354.65,), scheme) == 1
            @test hat_compare((-1.0,), (-1.0,), scheme) == 0
            @test hat_compare((0.0,), (0.0,), scheme) == 0
            @test hat_compare((0.2,), (0.2,), scheme) == 0
            @test hat_compare((1.0,), (0.0,), scheme) == -1
            @test hat_compare((0.0,), (-0.4,), scheme) == -1
            @test hat_compare((-0.65,), (-34.2,), scheme) == -1
        end

        @testset "hat_compare(..., ParetoFitnessScheme{2}(is_minimizing=true))" begin
            scheme = ParetoFitnessScheme{2}(is_minimizing=true)
            @test is_minimizing(scheme)
            @test_throws MethodError hat_compare((-1.0,), (1.0, 2.0), scheme)
            @test_throws MethodError hat_compare((2.0, -1.0, 3.0), (1.0, 2.0), scheme)
            @test hat_compare((-1.0, 0.0), (1.0, 0.0), scheme) == -1
            @test hat_compare((0.0, -1.0), (0.3, 1.0), scheme) == -1
            @test hat_compare((-1.0, 2.0), (-1.0, 2.0), scheme) == 0
            @test hat_compare((0.0, 0.0), (0.0, 0.0), scheme) == 0
            @test hat_compare((0.2, -0.4), (0.2, -0.4), scheme) == 0
            @test hat_compare((0.4, -0.4), (0.2, -0.2), scheme) == 0
            @test hat_compare((-0.65, 1.0), (1.0, -34.2), scheme) == 0
            @test hat_compare((11.3, 100.0), (11.3, 10.0), scheme) == 1
            @test hat_compare((1.0, 0.0), (0.0, -1.0), scheme) == 1
            @test hat_compare((0.0, 34.0), (-0.4, 20.0), scheme) == 1
        end

        @testset "hat_compare(..., ParetoFitnessScheme{2}(is_minimizing=false))" begin
            scheme = ParetoFitnessScheme{2}(is_minimizing=false)
            @test is_minimizing(scheme) == false
            @test hat_compare((-1.0, 0.0), (1.0, 0.0), scheme) == 1
            @test hat_compare((0.0, -1.0), (0.3, 1.0), scheme) == 1
            @test hat_compare((-1.0, 2.0), (-1.0, 2.0), scheme) == 0
            @test hat_compare((0.0, 0.0), (0.0, 0.0), scheme) == 0
            @test hat_compare((0.2, -0.4), (0.2, -0.4), scheme) == 0
            @test hat_compare((0.4, -0.4), (0.2, -0.2), scheme) == 0
            @test hat_compare((-0.65, 1.0), (1.0, -34.2), scheme) == 0
            @test hat_compare((11.3, 100.0), (11.3, 10.0), scheme) == -1
            @test hat_compare((1.0, 0.0), (0.0, -1.0), scheme) == -1
            @test hat_compare((0.0, 34.0), (-0.4, 20.0), scheme) == -1
        end

        @testset "is_better/is_worse/same_fitness(..., ParetoFitnessScheme{2}(is_minimizing=true))" begin
            scheme = ParetoFitnessScheme{2}()

            @test is_better((-1.0, 0.0), (1.0, 0.0), scheme)
            @test is_better((0.0, 0.0), (1.0, 0.0), scheme)
            @test_throws MethodError is_better((0.0,), (1.0,), scheme)

            @test is_better((1.0, 0.0), (-1.0, 0.0), scheme) == false
            @test is_better((1.0, 0.0), (0.0, 0.0), scheme) == false

            @test is_worse((-1.0, 0.0), (1.0, 0.0), scheme) == false
            @test is_worse((0.0, 0.0), (1.0, 0.0), scheme) == false
            @test_throws MethodError is_worse((0.0, 1.0), (1.0,), scheme)

            @test is_worse((1.0, 0.0), (-1.0, 0.0), scheme)
            @test is_worse((1.0, 0.0), (0.0, 0.0), scheme)

            @test same_fitness((-1.0, 0.0), (1.0, 0.0), scheme) == false
            @test same_fitness((0.0, 0.0), (1.0, 0.0), scheme) == false
            @test_throws MethodError same_fitness((0.0,), (1.0,), scheme)

            @test same_fitness((-1.0, 0.0), (-1.0, 0.0), scheme)
            @test same_fitness((0.0, 0.0), (0.0, 0.0), scheme)
            @test_throws MethodError same_fitness((0.0,), (0.0,), scheme)
        end

        @testset "is_better/is_worse/same_fitness(..., ParetoFitnessScheme{2}(is_minimizing=false))" begin
            scheme = ParetoFitnessScheme{2}(is_minimizing=false)

            @test is_better((-1.0, 0.0), (1.0, 0.0), scheme) == false
            @test is_better((0.0, 0.0), (1.0, 0.0), scheme) == false

            @test is_better((1.0, 0.0), (-1.0, 0.0), scheme)
            @test is_better((1.0, 0.0), (0.0, 0.0), scheme)

            @test is_worse((-1.0, 0.0), (1.0, 0.0), scheme)
            @test is_worse((0.0, 0.0), (1.0, 0.0), scheme)

            @test is_worse((1.0, 0.0), (-1.0, 0.0), scheme) == false
            @test is_worse((1.0, 0.0), (0.0, 0.0), scheme) == false

            @test same_fitness((-1.0, 0.0), (1.0, 0.0), scheme) == false
            @test same_fitness((0.0, 0.0), (1.0, 0.0), scheme) == false

            @test same_fitness((-1.0, 0.0), (-1.0, 0.0), scheme)
            @test same_fitness((0.0, 0.0), (0.0, 0.0), scheme)
        end
    end

    @testset "ϵ-box FitnessScheme" begin
        @testset "ϵ-index()" begin
            for (u, ϵ, is_minim, u_ix, delta) in [
                    (2.3, 1.0, true, 2, 0.3),
                    (2.3, 0.1, true, 23, 0.0),
                    (2.3, 1.0, false, 3, 0.7),
                    (1.0, 1.0, true, 1.0, 0.0),
                    (2.0, 2.0, false, 1.0, 0.0),
                    (-1.1, 1.0, true, -2, 0.9),
                    (-5.4, 1.0, false, -5, 0.4)
                ]
                res = BlackBoxOptim.ϵ_index(u, ϵ, Val{is_minim})
                @test res[1] == u_ix
                @test isapprox(res[2], delta; atol=1E-12)
            end
        end

        @testset "IndexedTupleFitness" begin
            fit = (0.55, 0.3, -0.21)
            ifit1 = IndexedTupleFitness(fit, sum(fit), 0.1, Val{true})
            @test ifit1.orig == fit
            @test ifit1.agg == sum(fit)
            @test ifit1.index == (5, 3, -3)
            @test isapprox(ifit1.dist, norm([0.05, 0.09])/0.1)

            ifit2 = IndexedTupleFitness(fit, sum(fit), 0.1, Val{false})
            @test ifit2.orig == fit
            @test ifit2.agg == sum(fit)
            @test ifit2.index == (6, 3, -2)
            @test isapprox(ifit2.dist, norm([0.05, 0.01])/0.1)

            ifit3 = convert(IndexedTupleFitness, fit, EpsBoxDominanceFitnessScheme{3}(0.1))
            @test ifit3 == ifit1
            ifit4 = convert(IndexedTupleFitness, fit, EpsBoxDominanceFitnessScheme{3}(0.1, is_minimizing=false))
            @test ifit4 == ifit2
        end

        @testset "hat_compare(..., EpsBoxDominanceFitnessScheme{2}(...))" begin
            minscheme = EpsBoxDominanceFitnessScheme{2}(0.1, is_minimizing=true)
            maxscheme = EpsBoxDominanceFitnessScheme{2}(0.1, is_minimizing=false)

            @test numobjectives(minscheme) == numobjectives(maxscheme) == 2
            @test fitness_type(minscheme) === fitness_type(maxscheme) === IndexedTupleFitness{2, Float64}
            @test fitness_eltype(minscheme) === fitness_eltype(maxscheme) === Float64

            @test isnafitness(nafitness(minscheme), minscheme)
            @test isnafitness(nafitness(maxscheme), minscheme)
            @test isnafitness(nafitness(minscheme), maxscheme)
            @test isnafitness(nafitness(maxscheme), maxscheme)

            @test hat_compare((-1.0, 0.0), (-1.0, 0.0), minscheme) == (0, true)
            @test hat_compare((-1.0, 0.0), (-1.0, 0.0), maxscheme) == (0, true)
            @test hat_compare((-1.0, 0.0), (1.0, 0.0), minscheme) == (-1, false)
            @test hat_compare((-1.0, 0.0), (1.0, 0.0), maxscheme) == (1, false)
            @test hat_compare((-1.0, 0.0), (-0.99, 0.0), minscheme) == (-1, true)
            @test hat_compare((-1.0, 0.0), (-0.99, 0.0), maxscheme) == (1, false)
            @test hat_compare((-1.0, 0.0), (-1.01, 0.0), minscheme) == (1, false)
            @test hat_compare((-1.0, 0.0), (-1.01, 0.0), maxscheme) == (-1, true)

            @test hat_compare((-0.97, 0.44), (-0.96, 0.43), minscheme) == (0, true)
            @test hat_compare((-0.97, 0.44), (-0.96, 0.43), maxscheme) == (0, true)
            @test hat_compare((-1.0, 0.5), (-1.0, 0.51), minscheme) == (-1, true)
            @test hat_compare((-1.0, 0.5), (-1.0, 0.51), maxscheme) == (1, false)

            @test hat_compare((0.9, 0.0), (1.0, 0.0), minscheme) == (-1, false)
            @test hat_compare((0.9, 0.0), (1.0, 0.0), maxscheme) == (1, false)
            @test hat_compare((0.95, 0.0), (0.98, 0.0), minscheme) == (-1, true)
            @test hat_compare((0.95, 0.0), (0.98, 0.0), maxscheme) == (1, true)

            @test hat_compare((-1.0, 0.05), (1.0, 0.0), minscheme) == (-1, false)
            @test hat_compare((-1.0, 0.05), (1.0, 0.0), maxscheme) == (0, false)
            @test hat_compare((0.9, 0.05), (1.0, 0.0), minscheme) == (-1, false)
            @test hat_compare((0.9, 0.05), (1.0, 0.0), maxscheme) == (0, false)
            @test hat_compare((0.95, 0.05), (0.98, 0.0), minscheme) == (-1, true)
            @test hat_compare((0.95, 0.05), (0.98, 0.0), maxscheme) == (-1, false)
            @test hat_compare((0.95, 0.05), (0.98, 0.01), maxscheme) == (-1, true)
            @test hat_compare((0.95, 0.05), (0.96, 0.0), minscheme) == (1, true)
            @test hat_compare((0.95, 0.05), (0.96, 0.0), maxscheme) == (-1, false)
            @test hat_compare((0.95, 0.05), (0.96, 0.04), minscheme) == (-1, true)
            @test hat_compare((0.95, 0.05), (0.96, 0.04), maxscheme) == (-1, true)

            @test hat_compare((6.9928266604943286,0.03386770153536918),
                                (7.007808609410211,0.032833634435236035), minscheme, 0) == (-1, false)
            @test hat_compare((6.9928266604943286,0.03386770153536918),
                                (7.007808609410211,0.032833634435236035), minscheme, 1) == (-1, false)
            @test hat_compare((6.9928266604943286,0.03386770153536918),
                                (7.007808609410211,0.032833634435236035), minscheme, -1) == (-1, false)
        end
    end
end


text:
function HDF5.hdf5_to_julia_eltype(objtype::HDF5Datatype)
    class_id = h5t_get_class(objtype.id)
    if class_id == H5T_STRING
        isvar = h5t_is_variable_str(objtype.id)
        n = Int(h5t_get_size(objtype.id))
        if !isvar && n < parse(Int, get(ENV, "HDF5_MAX_STRLEN", "256"))
            ENV["CSET"] = h5t_get_cset(objtype.id)
            return MaxLenString{n}
        end
    elseif class_id == H5T_COMPOUND
        n = Int(h5t_get_nmembers(objtype.id))
        field_names = Symbol[]
        field_types = DataType[]
        for i in 0:(n - 1)
            field_tid = h5t_get_member_type(objtype.id, i)
            field_type = hdf5_to_julia_eltype(HDF5Datatype(field_tid))
            field_name = h5t_get_member_name(objtype.id, i)
            push!(field_names, Symbol(field_name))
            push!(field_types, field_type)
        end
        T = NamedTuple{tuple(field_names...), Tuple{field_types...}}
        return T
    end
    invoke(hdf5_to_julia_eltype, Tuple{Any}, objtype)
end

macro h5bitslike(T)
    quote
        HDF5.datatype(::Type{T}) where T <: $T = HDF5Datatype(hdf5_type_id(T))

        HDF5.datatype(::T) where T <: $T = HDF5Datatype(hdf5_type_id(T))

        HDF5.datatype(A::AbstractArray{T}) where T <: $T = HDF5Datatype(hdf5_type_id(T))

        for H5T in (HDF5Dataset, HDF5Attribute)
            quote
                HDF5.read(obj::$H5T, ::Type{T}) where T <: $$T = read(obj, Array{T})[1]
                function HDF5.read(obj::$H5T, ::Type{Array{T}}) where T <: $$T
                    if isnull(obj)
                        return T[]
                    end
                    dims = size(obj)
                    data = Array{T}(undef, dims)
                    dtype = datatype(data)
                    readarray(obj, dtype.id, data)
                    close(dtype)
                    data
                end
            end |> eval
        end

        function HDF5.write(obj::DatasetOrAttribute, x::Union{T, Array{T}}) where T <: $T
            dtype = datatype(x)
            try
                writearray(obj, dtype.id, x)
            finally
            close(dtype)
            end
        end

        HDF5.write(parent::Union{HDF5File, HDF5Group}, name::String, data::Union{T, AbstractArray{T}}, plists...) where  T <: $T =
            d_write(parent, name, data, plists...)

        HDF5.d_write(parent::Union{HDF5File, HDF5Group}, name::String, data::Union{T, AbstractArray{T}}, plists...) where T <: $T =
            HDF5._d_write(parent, name, data, plists...)

        HDF5.d_create(parent::Union{HDF5File, HDF5Group}, name::String, data::Union{T, AbstractArray{T}}, plists...) where T <: $T =
            HDF5._d_create(parent, name, data, plists...)

        HDF5.dataspace(::T) where T <: $T = HDF5Dataspace(HDF5.h5s_create(H5S_SCALAR))

        function HDF5.h5d_write(dataset_id::Hid, memtype_id::Hid, x::T, xfer::Hid = H5P_DEFAULT) where T <: $T
            h5d_write(dataset_id, memtype_id, H5S_ALL, H5S_ALL, xfer, Ref{T}(x))
        end

        HDF5.ismmappable(::Type{Array{T}}) where T <: $T = true
    end |> esc
end

ext: jl


text:
#=
focus-chart.jl
=#

#using MIRTjim: jim
using ImagePhantoms: focus_chart, Object2d, Triangle, phantom
using Test: @test, @testset, @test_throws, @inferred

@testset "focus-chart" begin
    ob = @inferred focus_chart( ; nspoke=20)
    @test ob isa Vector{<: Object2d{Triangle}}

    x = LinRange(-1,1,2^9) * 1.1
    image = phantom(ob).(x,x')
    @test image isa Matrix
#   jim(x, x, image)
end


text:
mutable struct Composite
    bodies
    constraints
    composites
end

Composite() = Composite([], [], [])

# TODO
function set_modified!(composite, is_modified::Bool, update_parent::Bool, update_children::Bool) end

function add!(composite::Composite, object)
    before_add!(composite, object)
    if object.type == "body"
        if object.parent != object
            @warn "Composite.add: skipped adding compound body part (you must add its parent instead)"
        end
        add_body!(composite, object)
    elseif object.type == "constraint"
        add_constraint!(composite, object)
    elseif object.type == "composite"
        add_composite!(composite, object)
    end
    after_add!(composite, object)
end

function remove!(composite, object)
    before_remove!(composite, object)
    if object.type == "body"
        remove_body!(composite, object)
    elseif object.type == "constraint"
        remove_constraint!(composite, object)
    elseif object.type == "composite"
        remove_composite!(composite, object)
    end
    after_remove!(composite, object)
end

function add_composite!(composite, new_composite)
    push!(composite.composites, new_composite)
    new_composite.parent = composite
    set_modified!(composite, true, true, false)
end

function remove_composite!(composite, old_composite)
    index = findall(c -> c.id == old_composite.id, composite.composites)
    deleteat!(composite.composites, index)
    set_modified(composite, true, true, false)
end

function add_body!(composite::Composite, body)
    push!(composite.bodies, body)
    set_modified!(composite, true, true, false)
end

function remove_body!(composite, body)
    index = findall(b -> b.id == body.id, composite.bodies)
    deleteat!(composite.bodies, index)
    set_modified!(composite, true, true, false)
end

function add_constraint!(composite::Composite, constraint)
    push!(composite.constraints, constraint)
    set_modified!(composite, true, true, false)
end

function remove_constraint!(composite, constraint)
    index = findall(c -> c.id == constraint.id, composite.constraints)
    deleteat!(composite.constraints, index)
    set_modified!(composite, true, true, false)
end

function translate!(composite::Composite, translation::Vector)
    for body in composite.bodies
        translate!(body, translation)
    end
    set_modified!(composite, true, true, false)
end

function rotate!(composite::Composite, rotation)
    for body in composite.bodies
        rotate!(body, rotation)
    end
end


text:
"""
    voss!(noise1::Vector, noise2::Vector, scale, N=length(noise1))

Generates pink noise using two random Gaussian noise vectors and the
Voss-McCartney algorithm. It is described in detaile at
[https://www.firstpr.com.au/dsp/pink-noise/#Voss-McCartney](https://www.firstpr.com.au/dsp/pink-noise/#Voss-McCartney).

Required Arguments:

- `noise1::Vector`: length `N` Gaussian noise vector
- `noise2::Vector`: length `N` Gaussian noise vector
- `scale`: the amplitude of the noise in rad

Optional Arguments:

- `N`: length of the noise vectors `(default = length(noise1))`

Modifies and Returns:

- `noise1`: length `N` pink noise vector
"""
function voss!(noise1::Vector, noise2::Vector, scale, N=length(noise1))
    # `n` is the starting period of the each noise vector, the number of samples
    # before the noise value changes for a given layer
    n = 2
    # For a given `N`, determine all the periods of the noise that are a
    # multiple of `n`. Each noise layer has a period that is twice the period
    # from the previous layer, until the period is equal to the longest, `N`.
    # `sampled_noise_T` stores all the periods that are that used in
    # constructing pink noise.
    sampled_noise_T = Array{Int}(undef, 0)
    while n <= N
        push!(sampled_noise_T, n)
        n = 2*n
    end
    # `noise1` vector is noise with a period of 1 sample. The second vector,
    # `noise2`, contains all noise layers. The first half of `noise2` is the
    # second layer of the pink noise, where the period is 2 samples. The rest
    # of `noise2` is used all other periods that are multiples of 2 until the
    # period is equal to `N`.
    M = length(sampled_noise_T)
    idx = 1
    T = 2
    for i in 1:N
        if idx > N
            idx = 1
            T = 2*T
        end
        if (idx+T-1) > N
            view(noise1, idx:N) .+= noise2[i]
        else
            view(noise1, idx:idx+T-1) .+= noise2[i]
        end
        idx += T
    end
    # Scale the amplitude of `noise1` by the number of layers and `scale`.
    scale_factor = scale/M
    view(noise1, 1:N) .*= scale_factor
    return noise1
end

"""
    generate_phase_noise(N::Int; scale=1/10)

Generates a pink noise vector of length `N` with noise σ of `scale` rad. Two
Gaussian noise vectors are generated and passed to `voss!`. Pink noise is
stored in `noise`.

Required Arguments:

- `N::Int`: the length of the noise vector

Optional Arguments:

- `scale`: the amplitude of the noise in rad `(default = 1/10)`

Returns:

- `noise::Vector`: contains pink noise with amplitude `scale` radians
"""
function generate_phase_noise(N::Int; scale=1/10)
    noise = randn(N)
    noise_temp = randn(N)
    return voss!(noise, noise_temp, scale, N)
end

"""
    generate_phase_noise!(noise::Vector, N::Int=length(noise); scale=1/10)

Generates pink noise and stores it in `noise`. A second noise vector of length
`N` is generated and both noise vectors are passed to `voss!`.

Required Arguments:

- `noise::Vector`: length `N` Gaussian noise vector

Optional Arguments:

- `N::Int`: the length of the noise vector `(default = length(noise))`
- `scale`: the amplitude of the noise in rad `(default = 1/10)`

Returns:

- `noise::Vector`: contains pink noise with amplitude `scale` radians
"""
function generate_phase_noise!(noise::Vector, N::Int=length(noise); scale=1/10)
    noise_temp = randn(N)
    return voss!(noise, noise_temp, scale, N)
end

"""
    generate_phase_noise!(noise::Vector, noise_temp::Vector; scale=1/10)

Generates pink noise using two Gaussian noise generated vectors which are passed
to `voss!`. Pink noise is generated and stored in the `noise` vector.

Required Arguments:

- `noise::Vector`: length `N` Gaussian noise vector
- `noise_temp::Vector`: length `N` Gaussian noise vector

Optional Arguments:

- `scale`: the amplitude of the noise in rad `(default = 1/10)`

Returns:

- `noise::Vector`: contains pink noise with amplitude `scale` radians
"""
function generate_phase_noise!(noise::Vector, noise_temp::Vector; scale=1/10)
    return voss!(noise, noise_temp, scale, length(noise))
end

"""
    generate_phase_noise(t_length::Number, f_s::Number, f_carrier::Number,
                         h_parms::Vector)

Generate phase noise using the h-paramters, stored in the vector `h_parms` where
the order is `[h₋₂, h₋₁, h₀, h₁, h₂]`.

Required Arguments:

- `t_length`: length of of the phase noise array to generate in seconds
- `f_s`: sampling rate of the data in Hz
- `f_carrier`: receiver center frequency in Hz (i.e. L1 C/A carrier frequency)
- `h_parms`: vector containing the oscillator h parameters in the from
             of `[h₋₂, h₋₁, h₀, h₁, h₂]`

Returns:

- `phase_noise`: vector of generated oscillator phase noise in radians
"""
function generate_phase_noise(t_length::Number, f_s::Number, f_carrier::Number,
                              h_parms::Vector)
    N = floor(Int, t_length*f_s)
    phase_noise = Array{Complex{Float64}}(undef, N)
    generate_phase_noise!(phase_noise, t_length,  f_carrier, h_parms)
    return phase_noise
end

"""
    generate_phase_noise!(phase_noise::Vector t_length::Number,
                          f_carrier::Number, h_parms::Vector)

Generate phase noise using the h-paramters, stored in the vector `h_parms` where
the order is `[h₋₂, h₋₁, h₀, h₁, h₂]`. Performs in-place operation on
pre-existing `phase_noise` vector.

Generates phase noise using methods from
[https://www.mathworks.com/matlabcentral/fileexchange/47342-timeseriesfrompsd-sxx-fs-t-plot_on](https://www.mathworks.com/matlabcentral/fileexchange/47342-timeseriesfrompsd-sxx-fs-t-plot_on)

Required Arguments:

- `phase_noise`: vector to store generated oscillator phase noise
- `t_length`: length of of the phase noise array to generate in seconds
- `f_carrier`: receiver center frequency in Hz (i.e. L1 C/A carrier frequency)
- `h_parms`: vector containing the oscillator h parameters in the from
             of `[h₋₂, h₋₁, h₀, h₁, h₂]`

Returns:

- `phase_noise`: vector of generated oscillator phase noise in radians
"""
function generate_phase_noise!(phase_noise::Vector, t_length::Number,
                               f_carrier::Number, h_parms::Vector;
                               phi_init=0.)
    h₋₂, h₋₁, h₀, h₁, h₂ = h_parms
    N = length(phase_noise)
    if iseven(N)
        N_over_2 = floor(Int, N/2)
    else
        N_over_2 = ceil(Int, N/2)
    end
    rand!(view(phase_noise, 1:N_over_2+1), Float64)
    # Square root of the spectral density
    Δf = 1/t_length
    # f = Δf
    # val = f_carrier^2 * (h₋₂*f^(-4) + h₋₁*f^(-3) + h₀*f^(-2) + h₁*f^(-1) + h₂*f^0)
    val = 0
    phase_noise[1] = val * cis(2π * phase_noise[1])
    for i in 2:(N_over_2+1)
        f = (i-1)*Δf
        val = f_carrier^2 * (h₋₂*f^(-4) + h₋₁*f^(-3) + h₀*f^(-2) + h₁*f^(-1) + h₂*f^0)
        if (i > 1) && (i < (N_over_2+1))
            val = val/2
        end
        val = sqrt(val * t_length) * cis(2π * phase_noise[i])
        phase_noise[i] = val
    end
    # Copy the positive frequency powers to the negative frequencies, except
    # the DC and Nyquist frequency
    if iseven(N)
    # println([length(phase_noise[N_over_2+2:end]), length(phase_noise[2:N_over_2])])
        phase_noise[N_over_2+2:end] .= reverse(conj.(phase_noise[2:N_over_2]))
    else
        phase_noise[N_over_2+1:end] .= reverse(conj.(phase_noise[2:N_over_2]))
    end
    ifft!(phase_noise)
    for i in 1:N
        phase_noise[i] = phase_noise[i] * N * Δf + phi_init
    end
    return phase_noise
end


text:
function simulate!(s::Simulator{T}; verbose=false) where T
    status = false

    p = s.policy
	w = s.dist
	traj = s.traj
	N = length(traj.u)

	# last_computed_control = p.ref_traj.u[1] / N_sample
	buffer_time = 0.0
    for t = 1:N
		# println("timestep $t / $N, time $time")
		traj.u[t] = policy(p, traj, t)

        # disturbances
        traj.w[t] .= disturbances(w, traj.q[t+1], t)

        # step
        status = RoboDojo.step!(s, t, verbose=verbose)
        !status && break
    end

    return status
end


text:
module XGBoost

using Printf
using Random: randperm, seed!
using SparseArrays: SparseMatrixCSC, nnz
using Statistics: mean, std

export DMatrix, Booster
export xgboost, predict, save, nfold_cv, slice, get_info, set_info, dump_model, importance
export rabit_init, rabit_finalize, rabit_is_distributed, rabit_get_rank, rabit_get_world_size, rabit_get_version_number

global const build_version = "0.82"
include("../deps/deps.jl")

function __init__()
    check_deps()
end
include("xgboost_wrapper_h.jl")
include("rabit_wrapper.jl")
include("xgboost_lib.jl")

end # module XGBoost


text:
using Test

@testset begin
    @test false
    return
end

max_stars_repo_name: TimoLarson/julia

max_issues_repo_name: TimoLarson/julia

max_forks_repo_name: TimoLarson/julia


text:
using Test

module test

using wgregseq

include("runtests_encoder.jl")

end


text:
Alias = Tuple{SparseVector{Int}, SparseVector{Float64}}

"""
    Computes node embeddings on graph `g`, as per [1]

Conducts biased random walks on the graph, then computes word embeddings
by treating those random walks like sentences.

# Arguments
- `walks_per_node::Int`: Number of walks starting on each node,
total number of walks is `nv(g) * walks_per_node`
- `len::Int`: Length of random walks
- `p::Float64`: Return parameter from [1]
- `q::Float64`: In-out parameter from [1]

[1] https://cs.stanford.edu/~jure/pubs/node2vec-kdd16.pdf
"""
function node2vec(g::AbstractGraph; walks_per_node::Int, len::Int, p::Float64, q::Float64)::Vector{Vector{Int}}
    walks = simulate_walks(g; walks_per_node=walks_per_node, len=len, p=p, q=q)
    model = walks2vec(walks)
    return copy(model.vectors)
end

"""
Modified version of Node2Vec.learn_embeddings[1]. Uses
a Julia interface[2] to the original word2vec C code[3].

Treats each random walk like a sentence, and computed word
embeddings using node ID as words.

[1] https://github.com/ollin18/Node2Vec.jl
[2] https://github.com/JuliaText/Word2Vec.jl
[3] https://code.google.com/archive/p/word2vec/
"""
function walks2vec(walks::Vector{Vector{Int}};size::Int=100)

    str_walks=map(x -> string.(x),walks)

    if Sys.iswindows()
        rpath = pwd()
    else
        rpath = "/tmp"
    end
    the_walks = joinpath(rpath,"str_walk.txt")
    the_vecs = joinpath(rpath,"str_walk-vec.txt")

    writedlm(the_walks,str_walks)
    word2vec(the_walks,the_vecs,verbose=true,size=size)
    model=wordvectors(the_vecs)
    rm(the_walks)
    rm(the_vecs)
    model
end

"""
    Conducts a random walk over `g` in O(l) time,
weighted by alias sampling probabilities `alias_nodes`
and `alias_edges`
"""
function node2vec_walk(
    g::AbstractGraph,
    alias_nodes::Dict{Int, Alias},
    alias_edges::Dict{Tuple{Int, Int}, Alias};
    start_node::Int,
    walk_length::Int)::Vector{Int}
    walk::Vector{Int} = [start_node]
    current::Int = start_node
    for _ in 2:walk_length
        curr = walk[end]
        cur_nbrs = sort(neighbors(g, curr))
        if length(walk) == 1
            push!(walk, cur_nbrs[alias_sample(alias_nodes[curr]...)])
        else
            prev = walk[end-1]
            next = cur_nbrs[alias_sample(alias_edges[(prev, curr)]...)]
            push!(walk, next)
        end
    end
    return walk
end

"Returns J and q for a given edge"
function get_alias_edge(g::AbstractGraph, src::Int, dst::Int, p::Float64, q::Float64)::Alias
    unnormalized_probs = spzeros(length(neighbors(g, dst)))
    for (i, dst_nbr) in enumerate(sort(neighbors(g, dst)))
        if dst_nbr == src
            unnormalized_probs[i] = 1/p
        elseif has_edge(g, dst_nbr, src)
            unnormalized_probs[i] = 1
        else
            unnormalized_probs[i] = 1/q
        end
    end
    normalized_probs = unnormalized_probs ./ sum(unnormalized_probs)
    return alias_setup(normalized_probs)
end

"""
    Computes weighted probability transition aliases J and q for nodes and edges
using return parameter `p` and In-out parameter `q`

Implementation as specified in the node2vec paper by Grover and Leskovec (2016)
https://cs.stanford.edu/~jure/pubs/node2vec-kdd16.pdf
"""
function preprocess_modified_weights(g::AbstractGraph, p::Float64, q::Float64)

    alias_nodes::Dict{Int, Alias} = Dict()
    alias_edges::Dict{Tuple{Int, Int}, Alias} = Dict()

    for node in vertices(g)
        probs = [1 / length(neighbors(g, node)) for _ in neighbors(g, node)]
        alias_nodes[node] =  alias_setup(probs)
    end
    for edge in edges(g)
        alias_edges[(edge.src, edge.dst)] = get_alias_edge(g, edge.src, edge.dst, p, q)
        if !is_directed(g)
            alias_edges[(edge.dst, edge.src)] = get_alias_edge(g, edge.dst, edge.src, p, q)
        end
    end
    return alias_nodes, alias_edges
end

"Given a graph, compute `walks_per_node` * nv(g) random walks."
function simulate_walks(g::AbstractGraph; walks_per_node::Int, len::Int, p::Float64, q::Float64)::Vector{Vector{Int}}
    alias_nodes, alias_edges = preprocess_modified_weights(g, p, q)
    walks::Vector{Vector{Int}} = []
    for _ in 1:walks_per_node
        for node in shuffle(vertices(g))
            walk::Vector{Int} = node2vec_walk(g, alias_nodes, alias_edges; start_node=node, walk_length=len)
            push!(walks, walk)
        end
    end
    return walks
end


text:
@testset "PerfLog.jl" begin
    my_log = PerfLog()
    startLog(my_log, "stuff")

    @test "stuff" in keys(my_log.root.sub_timing_entries)
    @test my_log.root.sub_timing_entries["stuff"].time == 0.
    @test length(my_log.timing_queue) == 2 # root and stuff

    startLog(my_log, "junk")

    @test length(my_log.timing_queue) == 3 # root, stuff and junk
    @test "junk" in keys(my_log.root.sub_timing_entries["stuff"].sub_timing_entries)

    stopLog(my_log, "junk")

    stopLog(my_log, "stuff")
    @test my_log.root.sub_timing_entries["stuff"].time > 0
end


text:
#=
    NLP
    many unsafe operations here, because we are using JuMP non exposed
    methods (the ones starting with "_")
    - TODO: PIN JUMP
=#

function _has_nlp_data(model)
    return  model.nlp_data !== nothing
end
function _load_nlp_data(model)
    # callen in JuMP.optimize!
    # The nlp_data is not kept in sync, so re-set it here.
    # TODO: Consider how to handle incremental solves.
    if model.nlp_data !== nothing
        MOI.set(model, MOI.NLPBlock(), JuMP._create_nlp_block_data(model))
        empty!(model.nlp_data.nlconstr_duals)
    end
end

function Base.getproperty(m::UpperModel, s::Symbol)
    if s === :nlp_data
        return mylevel_model(m).nlp_data
    else
        getfield(m, s)
    end
end
function Base.getproperty(m::LowerModel, s::Symbol)
    if s === :nlp_data
        return no_nlp_lower()
    else
        getfield(m, s)
    end
end

no_nlp() = error("Non-linear data must be passed to the Upper(.) model")
no_nlp_lower() = error("NLconstraint(s) are not allowed in the lower level")
no_nlp_lower_param() = error("NLparameter(s) are not allowed in the lower level")

JuMP._init_NLP(m::UpperModel) = JuMP._init_NLP(mylevel_model(m))
JuMP._init_NLP(m::LowerModel) = no_nlp_lower()

function JuMP._new_parameter(m::UpperModel, value::Number)
    JuMP._init_NLP(m)
    upper = m.m.upper
    nldata::JuMP._NLPData = upper.nlp_data
    push!(nldata.nlparamvalues, value)
    return JuMP.NonlinearParameter(upper, length(nldata.nlparamvalues))
end

function JuMP._new_parameter(::LowerModel, ::Number)
    no_nlp_lower_param()
end
function JuMP._new_parameter(::BilevelModel, ::Number)
    no_nlp()
end

# function JuMP.set_objective_function(m::UpperModel, func::JuMP._NonlinearExprData)
#     JuMP.set_objective_function(mylevel_model(m), func)
#     return nothing
# end
# function JuMP.set_objective_function(::LowerModel, ::JuMP._NonlinearExprData)
#     no_nlp_lower()
#     return nothing
# end
function JuMP.set_objective(
    m::UpperModel,
    sense::MOI.OptimizationSense,
    ex::JuMP._NonlinearExprData,
)
    JuMP._init_NLP(m)
    JuMP.set_objective_sense(m, sense)
    m.nlp_data.nlobj = ex
    return
end
function JuMP.set_objective(::LowerModel,
    ::MOI.OptimizationSense,
    ::JuMP._NonlinearExprData,
)
    no_nlp_lower()
    return
end

function JuMP._parse_NL_expr_runtime(m::UpperModel, x, tape, parent, values)
    JuMP._parse_NL_expr_runtime(mylevel_model(m), x, tape, parent, values)
    return nothing
end

function JuMP._parse_NL_expr_runtime(m::UpperModel, x::BilevelVariableRef, tape, parent, values)
    if !in_upper(x)
        error(
            "Variable in nonlinear expression does not belong to the " *
            "upper model, it is a LowerOnly variable",
        )
    end
    JuMP._parse_NL_expr_runtime(mylevel_model(m), upper_ref(x), tape, parent, values)
    return nothing
end

# function JuMP._parse_NL_expr_runtime(
#     m::Model,
#     x::NonlinearExpression,
#     tape,
#     parent,
#     values,
# )
#     push!(tape, NodeData(SUBEXPRESSION, x.index, parent))
#     return nothing
# end

# TODO: deal with param
# function JuMP._parse_NL_expr_runtime(
#     m::JuMP.Model,
#     x::JuMP.NonlinearParameter,
#     tape,
#     parent,
#     values,
# )
#     push!(tape, JuMP.NodeData(JuMP.PARAMETER, x.index, parent))
#     return nothing
# end

# function JuMP._parse_NL_expr_runtime(
#     m::Model,
#     x::AbstractArray,
#     tape,
#     parent,
#     values,
# )
#     return error(
#         "Unexpected array $x in nonlinear expression. Nonlinear expressions may contain only scalar expressions.",
#     )
# end

# function JuMP._parse_NL_expr_runtime(
#     m::Model,
#     x::GenericQuadExpr,
#     tape,
#     parent,
#     values,
# )
#     push!(tape, NodeData(CALL, operator_to_id[:+], parent))
#     sum_parent = length(tape)
#     _parse_NL_expr_runtime(m, x.aff, tape, sum_parent, values)
#     for (xy, c) in x.terms
#         push!(tape, NodeData(CALL, operator_to_id[:*], sum_parent))
#         mult_parent = length(tape)
#         _parse_NL_expr_runtime(m, xy.a, tape, mult_parent, values)
#         _parse_NL_expr_runtime(m, xy.b, tape, mult_parent, values)
#         if !isone(c)  # Optimization: no need for * node.
#             _parse_NL_expr_runtime(m, c, tape, mult_parent, values)
#         end
#     end
#     return
# end

# function JuMP._parse_NL_expr_runtime(
#     m::Model,
#     x::GenericAffExpr,
#     tape,
#     parent,
#     values,
# )
#     push!(tape, NodeData(CALL, operator_to_id[:+], parent))
#     sum_parent = length(tape)
#     if !iszero(x.constant)
#         _parse_NL_expr_runtime(m, x.constant, tape, sum_parent, values)
#     end
#     for (v, c) in x.terms
#         if isone(c)  # Optimization: no need for * node.
#             _parse_NL_expr_runtime(m, v, tape, sum_parent, values)
#         else
#             push!(tape, NodeData(CALL, operator_to_id[:*], sum_parent))
#             mult_parent = length(tape)
#             _parse_NL_expr_runtime(m, c, tape, mult_parent, values)
#             _parse_NL_expr_runtime(m, v, tape, mult_parent, values)
#         end
#     end
#     return
# end

# function JuMP._parse_NL_expr_runtime(m::Model, x, tape, parent, values)
#     return error(
#         "Unexpected object $x (of type $(typeof(x)) in nonlinear expression.",
#     )
# end

function JuMP._parse_NL_expr_runtime(m::LowerModel, x, tape, parent, values)
    return no_nlp_lower()
end

#=

function JuMP._Derivatives.expr_to_nodedata(
    ex::VariableRef,
    nd::Vector{NodeData},
    values::Vector{Float64},
    parentid,
    r::_Derivatives.UserOperatorRegistry,
)
    push!(nd, NodeData(MOIVARIABLE, ex.index.value, parentid))
    return nothing
end

function JuMP._Derivatives.expr_to_nodedata(
    ex::NonlinearExpression,
    nd::Vector{NodeData},
    values::Vector{Float64},
    parentid,
    r::_Derivatives.UserOperatorRegistry,
)
    push!(nd, NodeData(SUBEXPRESSION, ex.index, parentid))
    return nothing
end

function JuMP._Derivatives.expr_to_nodedata(
    ex::NonlinearParameter,
    nd::Vector{NodeData},
    values::Vector{Float64},
    parentid,
    r::_Derivatives.UserOperatorRegistry,
)
    push!(nd, NodeData(PARAMETER, ex.index, parentid))
    return nothing
end

=#

#=

# Construct a _NonlinearExprData from a Julia expression.
# VariableRef objects should be spliced into the expression.
function JuMP._NonlinearExprData(m::Model, ex::Expr)
    _init_NLP(m)
    _check_expr(m, ex)
    nd, values = _Derivatives.expr_to_nodedata(ex, m.nlp_data.user_operators)
    return _NonlinearExprData(nd, values)
end
_NonlinearExprData(m::Model, ex) = _NonlinearExprData(m, :($ex + 0))

# Error if:
# 1) Unexpected expression
# 2) VariableRef doesn't match the model
function JuMP._check_expr(m::Model, ex::Expr)
    if ex.head == :ref # if we have x[1] already in there, something is wrong
        error(
            "Unrecognized expression $ex. JuMP variable objects and input coefficients should be spliced directly into expressions.",
        )
    end
    for e in ex.args
        _check_expr(m, e)
    end
    return
end
function JuMP._check_expr(m::Model, v::VariableRef)
    owner_model(v) === m || error("Variable $v does not belong to this model.")
    return
end
_check_expr(m::Model, ex) = nothing

=#

# TODO - convert into bilevel constraint ref
# ConstraintRef(
#     $esc_m,
#     NonlinearConstraintIndex(length($esc_m.nlp_data.nlconstr)),
#     ScalarShape(),
# )


text:
using RvSpectMLBase
using Test

@testset "ChunkOfSpectrum" begin
        num_pixels = 100
        num_orders = 10
        @test_nowarn ChunkOfSpectrum(ones(num_pixels),ones(num_pixels),ones(num_pixels))

        lambda = reshape(range(5000.0, stop=6000, length=num_pixels*num_orders), num_pixels,num_orders)
        data = ones(100,10)
        order = 5
        pixels = 20:30
        @test_nowarn ChunkOfSpectrum(view(lambda,pixels,order), view(data,pixels,order), view(data,pixels,order))
        @test_nowarn ChunkOfSpectrum(lambda, data, data, order,pixels)
        @test_nowarn ChunkOfSpectrum(lambda, data, data, (pixels=pixels, order=order) )
end

max_stars_repo_name: RvSpectML/RvSpectMLTemplate

max_issues_repo_name: RvSpectML/RvSpectMLTemplate

max_forks_repo_name: RvSpectML/RvSpectMLTemplate


text:
module BulkAndTails

  using Distributions, ForwardDiff, Ipopt, Roots, Random
  export BulkAndTailsDist, fitbats

  include("BulkAndTailsDist_struct.jl")
  include("BulkAndTailsDist_functions.jl")
  include("fitting.jl")
  include("ipopt_interface.jl")

end # module


text:
"""
```
  genlasso(
      X    :: AbstractMatrix{T},
      y    :: AbstractVector{T};
      path :: Bool = true,
      ρ    :: Union{AbstractVector, Number} = zero(T),
      D    :: AbstractMatrix{T} = eye(size(X, 2)),
      solver = ECOSSolver(maxit=10e8, verbose=0)
    )
```
Solve generalized lasso problem by reformulating it as constrained lasso problem.
Note genralized lasso minimizes
    `0.5sumabs2(√obswt .* (y - X * β)) + ρ * sumabs(D * β)`.

### Arguments
- `X`       : predictor matrix.
- `y`       : response vector.

### Optional arguments
- `path`    : set `path=false` if user wishes to supply parameter value(s).
              Default is true.
- `ρ`       : tuning parameter value(s). Default is 0.
- `D`       : penalty matrix. Default is identity matrix.
- `solver`  : a solver Convex.jl supports. Default is ECOS.
              Note that Mosek and Gurobi are more robust than ECOS. Unlike ECOS or
              SCS, both Mosek and Gurobi require a license (free for academic
              use). <http://convexjl.readthedocs.io/en/latest/solvers.html>

### Returns
- `β`       : estimated coefficents.
- `objval`  : optimal objective value.
- `problem` : Convex.jl problem.
"""

function genlasso(
    X::AbstractMatrix{T},
    y::AbstractArray{T};
    path::Bool = true,
    ρ::Union{AbstractVector, Number} = zero(T),
    D::AbstractMatrix{T} = eye(size(X, 2)),
    solver = ECOSSolver(maxit=10e8, verbose=0)
    ) where T

  # singular value decomposition on D
  m = size(D, 1)
  F = svdfact!(D, thin = false)
  # extract singular values and submatrices
  singvals = F[:S]
  rankD = countnz(F[:S] .> abs(F[:S][1]) * eps(F[:S][1]) * maximum(size(D)))
  V1 = F[:V][:, 1:rankD]
  V2 = F[:V][:, rankD+1:end]
  U1 = F[:U][:, 1:rankD]
  U2 = F[:U][:, rankD+1:end]
  # calculate the MP-inverse of D
  Dplus = V1 * broadcast(*, U1', 1./F[:S])
  # transform the design matrix
  XDplus = X * Dplus
  XV2 = X * V2
  # projection matrix onto C(XV2)
  Pxv2 = (1 / dot(XV2, XV2)) * A_mul_Bt(XV2, XV2)
  # orthogonal projection matrix
  Mxv2 = eye(size(XV2, 1)) - Pxv2
  # obtain the new design matrix and response vector
  ỹ = vec(Mxv2 * y)
  X̃ = Mxv2 * XDplus
  # solve the constrained lasso problem
  if path
    α̂path, ρpath, = lsq_classopath(X̃, ỹ; solver=solver, Aeq = U2',
          beq = zeros(size(U2, 2)))
  else
    α̂path, = lsq_constrsparsereg(X̃, ỹ, ρ; solver=solver, Aeq = U2',
          beq = zeros(size(U, 2)))
    ρpath = ρ
  end
  # transform back to beta
  β̂path = Base.LinAlg.BLAS.ger!(1.0, vec(V2 * ((1 / dot(XV2, XV2)) *
    		At_mul_B(XV2, y))), ones(size(ρpath)), (eye(size(V2, 1)) -
    		V2 * ((1 / dot(XV2, XV2)) * At_mul_B(XV2, X))) * Dplus * α̂path)

  return β̂path, ρpath

end # end of function


text:
# updateGammaz does not recognize this as bad diamond II
# Claudia April 2015

if !isdefined(:individualtest) individualtest = false; end

if(individualtest)
    include("../src/types.jl")
    include("../src/functions.jl")
end

if isdefined(:PhyloNetworks)
    PhyloNetworks.CHECKNET || error("need CHECKNET==true in PhyloNetworks to test snaq in test_correctLik.jl")
else
    CHECKNET || error("need CHECKNET==true to test snaq in test_correctLik.jl")
end

tree = "(6,(5,#H7:0.0):9.970714072991349,(3,(((2,1):0.2950382234364404,4):0.036924483697671304)#H7:0.00926495670648208):1.1071489442240392);"
net = readTopologyLevel1(tree);
checkNet(net)
#printNodes(net)
#printEdges(net)
net.node[10].number == 3 || error("wrong hybrid")
net.node[10].hybrid || error("does not know it is hybrid")
net.node[10].isBadDiamondII || error("does not know it is bad diamond II")
##plot(net,showEdgeNumber=true)
[e.inCycle for e in net.edge] == [-1,-1,3,3,-1,-1,-1,-1,-1,-1,3,3] || error("error in incycle")
[e.containRoot for e in net.edge] == [true,true,false,true,true,false,false,false,false,false,false,true] || error("error in contain root")
[e.istIdentifiable for e in net.edge] == [false,false,true,true,false,false,false,true,false,false,true,true] || error("istIdentifiable not correct")
(net.edge[3].hybrid && net.edge[11].hybrid) || error("hybrid edges wrong")

df=DataFrame(t1=["1","1","2","2","1","2","2","2","2","2","1","2","2","3","2"],
             t2=["3","3","3","3","3","1","5","1","1","1","5","1","1","5","3"],
             t3=["5","5","5","5","6","5","6","3","6","5","6","3","3","6","6"],
             t4=["6","4","4","6","4","6","4","5","4","4","4","6","4","4","4"],
             CF1234=[0.565,0.0005,0.0005,0.565,0.00003,0.99986,0.0410167,1,0.99987,1,0.040167,0.998667,1,0.073167,0.00003],
             CF1324=[0.0903,0.8599,0.8599,0.0903,0.8885,0.00006,0.263,0,0.00006,0,0.2630,0.00006,0,0.0424667,0.8885])
df[:CF1423] = 1-df[:CF1234]-df[:CF1324]
d = readTableCF(df)

net2 = topologyMaxQPseudolik!(net,d, ftolRel=1e-5,ftolAbs=1e-6,xtolRel=1e-3,xtolAbs=1e-4)
340 < net2.loglik < 340.5 || error("wrong loglik")
net2.edge[3].istIdentifiable || error("wrong hybrid is t identifiable")
9.95 < net2.edge[3].length < 9.99 || error("wrong bl estimated")
net2.edge[11].istIdentifiable || error("wrong hybrid is t identifiable")
net2.edge[11].length < 0.01 || error("wrong bl estimated")
net2.edge[10].length == 0 || error("tree edge in bad diamond II not 0")
#printEdges(net2)

## testing readTopology----------------------------------------------------------------
## will remove this from the test because readTopology should not have to worry about istIdentifiable
## we move into updateGammaz
## tree = "(6,(5,#H7:0.0):9.970714072991349,(3,(((2,1):0.2950382234364404,4):0.036924483697671304)#H7:0.00926495670648208):1.1071489442240392);"
## net2 = readTopology(tree)
## printEdges(net2)

## for e in net2.edge
##     if(e.node[1].leaf || e.node[2].leaf)
##         !e.istIdentifiable || error("ext edge should not identifiable")
##     else
##         e.istIdentifiable || error("int edge should not identifiable")
##     end
## end

## ## this case works fine
## tree = "((((8,10))#H1,7),6,(4,#H1));" # Case I Bad diamond I
## net = readTopologyLevel1(tree)
## checkNet(net)
## net2 = readTopology(tree)
## printEdges(net2)

## for e in net2.edge
##     if(e.node[1].leaf || e.node[2].leaf)
##         !e.istIdentifiable || error("ext edge should not identifiable")
##     else
##         e.istIdentifiable || error("int edge should not identifiable")
##     end
## end


text:
with_tmp_repo_access() do test_repo, path
    context("test list all names") do
        @test [
            "master",
            "origin/HEAD",
            "origin/master",
            "origin/packed"
        ] == sort(branch_names(test_repo))
    end

    context("test list only local branches") do
        @test ["master"] == sort(branch_names(test_repo, :local))
    end

    context("test list only remote branches") do
       @test [
           "origin/HEAD",
           "origin/master",
           "origin/packed",
       ] == sort(branch_names(test_repo, :remote))
    end

    context("test get latest commit in branch") do
       t = lookup_branch(test_repo, "master") |> tip
       @test isa(t, GitCommit)
       @test Oid(t) == Oid("36060c58702ed4c2a40832c51758d5344201d89a")
    end

    context("test lookup local branch") do
       b = lookup_branch(test_repo, "master")
       @test b != nothing
       @test name(b) == "master"
       @test canonical_name(b) == "refs/heads/master"
       @test Oid(tip(b)) == Oid("36060c58702ed4c2a40832c51758d5344201d89a")
    end

    context("test lookup remote branches") do
       b = lookup_branch(test_repo, "origin/packed", :remote)
       @test b != nothing

       @test name(b) == "origin/packed"
       @test canonical_name(b) == "refs/remotes/origin/packed"
       @test Oid(tip(b)) == Oid("41bc8c69075bbdb46c5c6f0566cc8cc5b46e8bd9")
    end

    context("test branch equality") do
        b1 = lookup_branch(test_repo, "master")
        b2 = lookup_branch(test_repo, "master")
        @test b1 == b2

        b1 = lookup_branch(test_repo, "master")
        b2 = lookup_branch(test_repo, "origin/packed", :remote)
        @test b1 != b2
    end
end

with_tmp_repo_access("test lookup unicode branch name") do test_repo, path
    new_branch = create_branch(test_repo, "Ångström",
        Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))
    @test new_branch != nothing

    retrieved_branch = lookup_branch(test_repo, "Ångström")
    @test new_branch != nothing

    @test new_branch == retrieved_branch
end

with_tmp_repo_access("test delete branch") do test_repo, path
    b = create_branch(test_repo, "test_branch")
    delete!(b)
    @test lookup_branch(test_repo, "test_branch") == nothing
end

with_tmp_repo_access("test is head") do test_repo, path
    @test ishead(lookup_branch(test_repo, "master"))
    @test ishead(lookup_branch(test_repo, "origin/master", :remote)) == false
    @test ishead(lookup_branch(test_repo, "origin/packed", :remote)) == false
    @test ishead(create_branch(test_repo, "test_branch")) == false
end

with_tmp_repo_access("test rename branch") do test_repo, path
    b = create_branch(test_repo, "test_branch")
    rename(b, "other_branch")
    @test lookup_branch(test_repo, "test_branch") == nothing
    @test isa(lookup_branch(test_repo, "other_branch"), GitBranch)
end

with_tmp_repo_access("test create new branch") do test_repo, path
    new_branch = create_branch(test_repo, "test_branch",
        Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))

    @test new_branch != nothing
    @test name(new_branch) ==  "test_branch"
    @test canonical_name(new_branch) == "refs/heads/test_branch"

    @test tip(new_branch) != nothing
    @test Oid(tip(new_branch)) == Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644")
    @test any(b -> name(b) == "test_branch", foreach(GitBranch, test_repo))
end

with_tmp_repo_access("test create unicode branch") do test_repo, path
    branch_name = "A\314\212ngstro\314\210m"
    new_branch = create_branch(test_repo, branch_name,
                        Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))

    @test new_branch != nothing
    @test normalize_string(branch_name, :NFC) == normalize_string(name(new_branch), :NFC)
    @test normalize_string(canonical_name(new_branch), :NFC) == normalize_string("refs/heads/$branch_name", :NFC)

    @test tip(new_branch) != nothing
    @test Oid(tip(new_branch)) == Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644")

    @test any(b -> normalize_string(name(b), :NFC) == normalize_string(branch_name, :NFC),
              foreach(GitBranch, test_repo))
end

with_tmp_repo_access("test create branch short sha") do test_repo, path
    new_branch = create_branch(test_repo, "test_branch", "5b5b025")

    @test new_branch != nothing
    @test name(new_branch) ==  "test_branch"
    @test canonical_name(new_branch) == "refs/heads/test_branch"

    @test tip(new_branch) != nothing
    @test Oid(tip(new_branch)) == Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644")

    @test any(b -> name(b) == "test_branch", foreach(GitBranch, test_repo))
end

with_tmp_repo_access("test create branch from tag") do test_repo, path
    new_branch = create_branch(test_repo, "test_branch", "refs/tags/v0.9")

    @test new_branch != nothing
    @test name(new_branch) ==  "test_branch"
    @test canonical_name(new_branch) == "refs/heads/test_branch"

    @test tip(new_branch) != nothing
    @test Oid(tip(new_branch)) == Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644")

    @test any(b -> name(b) == "test_branch", foreach(GitBranch, test_repo))
end

with_tmp_repo_access("test create branch from head") do test_repo, path
    new_branch = create_branch(test_repo, "test_branch")

    @test new_branch != nothing
    @test name(new_branch) ==  "test_branch"
    @test canonical_name(new_branch) == "refs/heads/test_branch"

    @test tip(new_branch) != nothing
    @test Oid(tip(new_branch)) == Oid("36060c58702ed4c2a40832c51758d5344201d89a")

    @test any(b -> name(b) == "test_branch", foreach(GitBranch, test_repo))
end

with_tmp_repo_access("test create branch explicit head") do test_repo, path
    new_branch = create_branch(test_repo, "test_branch", "HEAD")

    @test new_branch != nothing
    @test name(new_branch) ==  "test_branch"
    @test canonical_name(new_branch) == "refs/heads/test_branch"

    @test tip(new_branch) != nothing
    @test Oid(tip(new_branch)) == Oid("36060c58702ed4c2a40832c51758d5344201d89a")

    @test any(b -> name(b) == "test_branch", foreach(GitBranch, test_repo))
end

with_tmp_repo_access("test create branch from commit") do test_repo, path
    new_branch = create_branch(test_repo, "test_branch",
      lookup_commit(test_repo, Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644")))

    @test new_branch != nothing
    @test name(new_branch) ==  "test_branch"
    @test canonical_name(new_branch) == "refs/heads/test_branch"

    @test tip(new_branch) != nothing
    @test Oid(tip(new_branch)) == Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644")

    @test any(b -> name(b) == "test_branch", foreach(GitBranch, test_repo))
end

with_tmp_repo_access("test create branch from unknown ref fails") do test_repo, path
    @test_throws LibGitError{:Ref,:NotFound} create_branch(test_repo,
                                                    "test_branch", "i_do_not_exist")
end

with_tmp_repo_access("test create branch from unknown commit fails") do test_repo, path
 @test_throws LibGitError{:Odb,:NotFound} create_branch(test_repo, "test_branch",
        Oid("dd15de908706711b51b7acb24faab726d2b3cb16"))
end

with_tmp_repo_access("test create branch from non canonical fails") do test_repo, path
    @test_throws LibGitError{:Ref,:NotFound} create_branch(test_repo,
                                                           "test_branch", "packed")
end

with_tmp_repo_access("test remote branch") do test_repo, path
    @test "origin" == (lookup_branch(test_repo, "origin/master", :remote)
                       |> remote |> name)
end

with_tmp_repo_access("test branch remote local tracking remote") do test_repo, path
     @test "origin" == (lookup_branch(test_repo, "master", :local)
                        |> remote |> name)
end

with_tmp_repo_access("test branch remote local non-tracking") do test_repo, path
        b = create_branch(test_repo, "test_branch",
                Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))
        @test remote(b) == nothing
end

with_tmp_repo_access("test branch upstream") do test_repo, path
    upstream_branch = lookup_branch(test_repo, "master", :local) |> upstream
    @test "origin/master" == name(upstream_branch)
end

with_tmp_repo_access("test upstream remote branch") do test_repo, path
    @test nothing == (lookup_branch(test_repo, "origin/master", :remote)
                      |> upstream)
end

with_tmp_repo_access("test branch upstream no tracking branch") do test_repo, path
    branch = create_branch(test_repo, "test_branch",
                           Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))
    @test upstream(branch) == nothing
end

with_tmp_repo_access("test branch set upstream with reference") do test_repo, path
    b = create_branch(test_repo, "test_branch",
                 Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))

    set_upstream!(b, lookup_ref(test_repo, "refs/heads/master"))
    @test name(upstream(b)) == "master"
end

with_tmp_repo_access("test branch set upstream with tag reference") do test_repo, path
    b = create_branch(test_repo, "test_branch",
            Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))
    r = lookup_ref(test_repo, "refs/tags/v1.0")
    @test_throws LibGitError{:Invalid,:Error} set_upstream!(b, r)
end

with_tmp_repo_access("test branch set upstream local") do test_repo, path
    b = create_branch(test_repo, "test_branch",
                Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))

    set_upstream!(b, lookup_branch(test_repo, "master", :local))
    @test (upstream(b) |> name) == "master"
end

with_tmp_repo_access("test branch set upstream remote") do test_repo, path
    b = create_branch(test_repo, "test_branch",
                Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))
    set_upstream!(b, lookup_branch(test_repo, "origin/master", :remote))
    @test name(upstream(b)) == "origin/master"
end

with_tmp_repo_access("test branch unset upstream") do test_repo, path
    b = lookup_branch(test_repo, "master", :local)
    @test upstream(b) != nothing
    set_upstream!(b, nothing)
    @test upstream(b) == nothing
end

with_tmp_repo_access("test branch set upstream on remote branch") do test_repo, path
    b1 = lookup_branch(test_repo, "origin/master", :remote)
    b2 = create_branch(test_repo, "test_branch",
                      Oid("5b5b025afb0b4c913b4c338a42934a3863bf3644"))
    @test_throws LibGitError{:Invalid,:Error} set_upstream!(b1, b2)
end


text:
__precompile__()

module ApproxFun
    using Base, Reexport, BlockArrays, BandedMatrices, BlockBandedMatrices, DomainSets, IntervalSets,
            SpecialFunctions, AbstractFFTs, FFTW, SpecialFunctions, DSP, DualNumbers, FastTransforms,
            LinearAlgebra, SparseArrays, LowRankApprox, FillArrays, InfiniteArrays, RecipesBase,
            FFTW, AbstractFFTs #, Arpack

import Calculus

@reexport using ApproxFunBase
@reexport using ApproxFunFourier
@reexport using ApproxFunOrthogonalPolynomials
@reexport using ApproxFunSingularities

import ApproxFunBase: normalize!, flipsign, FiniteRange, Fun, MatrixFun, UnsetSpace, VFun, RowVector,
                    UnivariateSpace, AmbiguousSpace, SumSpace, SubSpace, WeightSpace, NoSpace, Space,
                    HeavisideSpace, PointSpace,
                    IntervalOrSegment, RaggedMatrix, AlmostBandedMatrix,
                    AnyDomain, ZeroSpace, ArraySpace, TrivialInterlacer, BlockInterlacer,
                    AbstractTransformPlan, TransformPlan, ITransformPlan,
                    ConcreteConversion, ConcreteMultiplication, ConcreteDerivative, ConcreteIntegral, CalculusOperator,
                    ConcreteVolterra, Volterra, VolterraWrapper,
                    MultiplicationWrapper, ConversionWrapper, DerivativeWrapper, Evaluation, EvaluationWrapper,
                    Conversion, defaultConversion, defaultcoefficients, default_Fun, Multiplication, Derivative, Integral, bandwidths,
                    ConcreteEvaluation, ConcreteDefiniteLineIntegral, ConcreteDefiniteIntegral, ConcreteIntegral,
                    DefiniteLineIntegral, DefiniteIntegral, ConcreteDefiniteIntegral, ConcreteDefiniteLineIntegral, IntegralWrapper,
                    ReverseOrientation, ReverseOrientationWrapper, ReverseWrapper, Reverse, NegateEven,
                    Dirichlet, ConcreteDirichlet, DirichletWrapper,
                    TridiagonalOperator, SubOperator, Space, @containsconstants, spacescompatible,
                    hasfasttransform, canonicalspace, domain, setdomain, prectype, domainscompatible,
                    plan_transform, plan_itransform, plan_transform!, plan_itransform!, transform, itransform, hasfasttransform,
                    CanonicalTransformPlan, ICanonicalTransformPlan,
                    Integral,
                    domainspace, rangespace, boundary,
                    union_rule, conversion_rule, maxspace_rule, conversion_type, maxspace, hasconversion, points,
                    rdirichlet, ldirichlet, lneumann, rneumann, ivp, bvp,
                    linesum, differentiate, integrate, linebilinearform, bilinearform,
                    UnsetNumber, coefficienttimes, subspace_coefficients, sumspacecoefficients, specialfunctionnormalizationpoint,
                    Segment, IntervalOrSegmentDomain, PiecewiseSegment, isambiguous, Vec, eps, isperiodic,
                    arclength, complexlength,
                    invfromcanonicalD, fromcanonical, tocanonical, fromcanonicalD, tocanonicalD, canonicaldomain, setcanonicaldomain, mappoint,
                    reverseorientation, checkpoints, evaluate, mul_coefficients, coefficients, coefficientmatrix, isconvertible,
                    clenshaw, ClenshawPlan, sineshaw,
                    toeplitz_getindex, toeplitz_axpy!, sym_toeplitz_axpy!, hankel_axpy!, ToeplitzOperator, SymToeplitzOperator, hankel_getindex,
                    SpaceOperator, ZeroOperator, InterlaceOperator,
                    interlace!, reverseeven!, negateeven!, cfstype, pad!, alternatesign!, mobius,
                    extremal_args, hesseneigvals, chebyshev_clenshaw, recA, recB, recC, roots,splitatroots,
                    chebmult_getindex, intpow, alternatingsum,
                    domaintype, diagindshift, rangetype, weight, isapproxinteger, default_Dirichlet, scal!, dotu,
                    components, promoterangespace, promotedomainspace, choosedomainspace,
                    block, blockstart, blockstop, blocklengths, isblockbanded, pointscompatible,
                    AbstractProductSpace, MultivariateFun, BivariateSpace,
                    @wrapperstructure, @wrapperspaces, @wrapper, @calculus_operator, resizedata!, slnorm,
                    sample, chop!

import ApproxFunOrthogonalPolynomials: order

import DomainSets: Domain, indomain, UnionDomain, ProductDomain, FullSpace, Point, elements, DifferenceDomain,
            Interval, ChebyshevInterval, boundary, ∂, rightendpoint, leftendpoint,
            dimension, EuclideanDomain

import AbstractFFTs: Plan, fft, ifft
import FFTW: plan_r2r!, fftwNumber, REDFT10, REDFT01, REDFT00, RODFT00, R2HC, HC2R,
                r2r!, r2r,  plan_fft, plan_ifft, plan_ifft!, plan_fft!

import Base: values, convert, getindex, setindex!, *, +, -, ==, <, <=, >, |, !, !=, eltype, iterate,
                >=, /, ^, \, ∪, transpose, size, tail, broadcast, broadcast!, copyto!, copy, to_index, (:),
                similar, map, vcat, hcat, hvcat, show, summary, stride, sum, cumsum, sign, imag, conj, inv,
                complex, reverse, exp, sqrt, abs, abs2, sign, issubset, values, in, first, last, rand, intersect, setdiff,
                isless, union, angle, join, isnan, isapprox, isempty, sort, merge, promote_rule,
                minimum, maximum, extrema, argmax, argmin, findmax, findmin, isfinite,
                zeros, zero, one, promote_rule, repeat, length, resize!, isinf,
                getproperty, findfirst, unsafe_getindex, fld, cld, div, real, imag,
                @_inline_meta, eachindex, firstindex, lastindex, keys, isreal, OneTo,
                Array, Vector, Matrix, view, ones, @propagate_inbounds, print_array,
                split

import Base.Broadcast: BroadcastStyle, Broadcasted, AbstractArrayStyle, broadcastable,
                        DefaultArrayStyle, broadcasted

import LinearAlgebra: BlasInt, BlasFloat, norm, ldiv!, mul!, det, eigvals, dot, cross,
                        qr, qr!, rank, isdiag, istril, istriu, issymmetric, ishermitian,
                        Tridiagonal, diagm, diagm_container, factorize, nullspace,
                        Hermitian, Symmetric, adjoint, transpose, char_uplo

import SparseArrays: blockdiag

# import Arpack: eigs

# we need to import all special functions to use Calculus.symbolic_derivatives_1arg
# we can't do importall Base as we replace some Base definitions
import SpecialFunctions: sinpi, cospi, airy, besselh,
                    asinh, acosh,atanh, erfcx, dawson, erf, erfi,
                    sin, cos, sinh, cosh, airyai, airybi, airyaiprime, airybiprime,
                    hankelh1, hankelh2, besselj, besselj0, bessely, besseli, besselk,
                    besselkx, hankelh1x, hankelh2x, exp2, exp10, log2, log10,
                    tan, tanh, csc, asin, acsc, sec, acos, asec,
                    cot, atan, acot, sinh, csch, asinh, acsch,
                    sech, acosh, asech, tanh, coth, atanh, acoth,
                    expm1, log1p, lfact, sinc, cosc, erfinv, erfcinv, beta, lbeta,
                    eta, zeta, gamma,  lgamma, polygamma, invdigamma, digamma, trigamma,
                    abs, sign, log, expm1, tan, abs2, sqrt, angle, max, min, cbrt, log,
                    atan, acos, asin, erfc, inv

import StaticArrays: SVector

import BlockArrays: nblocks, blocksize, global2blockindex, globalrange, BlockSizes

import BandedMatrices: bandrange, bandshift,
                        inbands_getindex, inbands_setindex!, bandwidth, AbstractBandedMatrix,
                        colstart, colstop, colrange, rowstart, rowstop, rowrange,
                        bandwidths, _BandedMatrix, BandedMatrix

import BlockBandedMatrices: blockbandwidth, blockbandwidths, blockcolstop, blockcolrange,
                            blockcolstart, blockrowstop, blockrowstart, blockrowrange,
                            subblockbandwidth, subblockbandwidths, _BlockBandedMatrix,
                            _BandedBlockBandedMatrix, BandedBlockBandedMatrix, BlockBandedMatrix,
                            isblockbanded, isbandedblockbanded, bb_numentries, BlockBandedSizes,
                            BandedBlockBandedSizes

import FastTransforms: ChebyshevTransformPlan, IChebyshevTransformPlan, plan_chebyshevtransform,
                        plan_chebyshevtransform!, plan_ichebyshevtransform, plan_ichebyshevtransform!

import FillArrays: AbstractFill, getindex_value
import LazyArrays: cache
import InfiniteArrays: Infinity, InfRanges, AbstractInfUnitRange, OneToInf

"""
`Curve` Represents a domain defined by the image of a Fun.  Example
usage would be

```julia
x=Fun(1..2)
Curve(exp(im*x))  # represents an arc
```
"""
const Curve{S,T} = Union{IntervalCurve{S,T},PeriodicCurve{S,T}}
Curve(f::Fun{<:Space{<:PeriodicDomain}}) = PeriodicCurve(f)

#TODO: Make type stable
Curve(f::Fun{<:Space{<:ChebyshevInterval}}) = IntervalCurve(f)

export Curve

import Base: view

import StaticArrays: StaticArray, SVector

import IntervalSets: (..), endpoints

##Testing
export bisectioninv

## Further extra features

include("Extras/Extras.jl")
include("Plot/Plot.jl")
include("docs.jl")

#include("precompile.jl")
#_precompile_()

end #module


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct DedicatedHostInstanceView <: SwaggerModel
    assetId::Any # spec type: Union{ Nothing, String } # spec name: assetId
    availableCapacity::Any # spec type: Union{ Nothing, DedicatedHostAvailableCapacity } # spec name: availableCapacity
    statuses::Any # spec type: Union{ Nothing, Vector{InstanceViewStatus} } # spec name: statuses

    function DedicatedHostInstanceView(;assetId=nothing, availableCapacity=nothing, statuses=nothing)
        o = new()
        validate_property(DedicatedHostInstanceView, Symbol("assetId"), assetId)
        setfield!(o, Symbol("assetId"), assetId)
        validate_property(DedicatedHostInstanceView, Symbol("availableCapacity"), availableCapacity)
        setfield!(o, Symbol("availableCapacity"), availableCapacity)
        validate_property(DedicatedHostInstanceView, Symbol("statuses"), statuses)
        setfield!(o, Symbol("statuses"), statuses)
        o
    end
end # type DedicatedHostInstanceView

const _property_map_DedicatedHostInstanceView = Dict{Symbol,Symbol}(Symbol("assetId")=>Symbol("assetId"), Symbol("availableCapacity")=>Symbol("availableCapacity"), Symbol("statuses")=>Symbol("statuses"))
const _property_types_DedicatedHostInstanceView = Dict{Symbol,String}(Symbol("assetId")=>"String", Symbol("availableCapacity")=>"DedicatedHostAvailableCapacity", Symbol("statuses")=>"Vector{InstanceViewStatus}")
Base.propertynames(::Type{ DedicatedHostInstanceView }) = collect(keys(_property_map_DedicatedHostInstanceView))
Swagger.property_type(::Type{ DedicatedHostInstanceView }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_DedicatedHostInstanceView[name]))}
Swagger.field_name(::Type{ DedicatedHostInstanceView }, property_name::Symbol) =  _property_map_DedicatedHostInstanceView[property_name]

function check_required(o::DedicatedHostInstanceView)
    true
end

function validate_property(::Type{ DedicatedHostInstanceView }, name::Symbol, val)
end


text:
# Computation of (logarithmic) moments of Chebyshev polynomials scaled to 0..1

"The integral of x^k*log(x) on [0,1]."
logmoment(k::Int, ::Type{T} = Float64) where {T} = -one(T)/(k+1)^2

"Modified Chebyshev moments on [0,1]"
function modified_moments(N, ::Type{T} = Float64) where {T}
    c = zeros(T, N+1)
    c[1] = 1
    for n in 2:(N>>1 + 1)
        c[2n-1] = -one(T) / ((2n-3)*(2n-1))
    end
    c
end

"Modified logarithmic Chebyshev moments on [0,1]"
function modified_log_moments(N, ::Type{T} = Float64) where {T}
    # recurrence coefficients of Chebyshev
    chebA =  [BasisFunctions.rec_An(ChebyshevT{T}(N), k) for k in 0:N]
    chebB =  [BasisFunctions.rec_Bn(ChebyshevT{T}(N), k) for k in 0:N]
    chebC =  [BasisFunctions.rec_Cn(ChebyshevT{T}(N), k) for k in 0:N]
    # recurrence coefficients of shifted Chebyshev to [0,1]
    modchebA = 2chebA
    modchebC = chebC
    modchebB = similar(chebB)
    for n in 1:length(chebB)
        modchebB[n] = chebB[n] - chebA[n]
    end
    # Moments L[n,k] = ∫_0^1 log(x) x^k p_n(x) dx
    L = zeros(T, N+1,N+1)
    L[1,:] = [logmoment(k,T) for k in 0:N]
    for n in 0:N-1
        for k in 0:N-1
            if n == 0
                L[n+2,k+1] = modchebA[n+1]*L[n+1,k+2] + modchebB[n+1]*L[n+1,k+1]
            else
                L[n+2,k+1] = modchebA[n+1]*L[n+1,k+2] + modchebB[n+1]*L[n+1,k+1] - modchebC[n+1]*L[n,k+1]
            end
        end
    end
    L[:,1]
end

# The rules below are generated with the following code:

# function pretty_print_quadrule(x, w, ::Type{BigFloat})
#     print("x = BigFloat.([")
#     for t in x
#         print("\"", string(t), "\", ")
#     end
#     println("])")
#     print("w = BigFloat.([")
#     for y in w
#         print("\"", string(y), "\", ")
#     end
#     println("])")
# end
# T = BigFloat
# for N = 1:20
#     cheb = ChebyshevT{T}(N) → 0..1
#     bmom = vcat(modified_moments(N-1, T), modified_log_moments(N-1, T))
#     b = cheb ⊕ log*cheb
#     w, x = compute_gauss_rule(b, bmom)
#     pretty_print_quadrule(x, w, T)
# end

const big_x1 = BigFloat.(["0.4999999999999999999999999999999999999999999999999999999999999999999999999999957", ])
const big_w1 = BigFloat.(["1.0", ])
const big_x2 = BigFloat.(["0.211324865405187117745425609749021272176199124364936561990698836758011163848551", "0.7886751345948128822545743902509787278238008756350634380093011632419888361514749", ])
const big_w2 = BigFloat.(["0.5000000000000000000000000000000000000000000000000000000000000000000000000000259", "0.4999999999999999999999999999999999999999999999999999999999999999999999999999741", ])
const big_x3 = BigFloat.(["0.1127016653792583114820734600217600389167078294708409173412426233886516908062983", "0.4999999999999999999999999999999999999999999999999999999999999999999999999999957", "0.8872983346207416885179265399782399610832921705291590826587573766113483091936996", ])
const big_w3 = BigFloat.(["0.2777777777777777777777777777777777777777777777777777777777777777777777777777783", "0.4444444444444444444444444444444444444444444444444444444444444444444444444444435", "0.2777777777777777777777777777777777777777777777777777777777777777777777777777783", ])
const big_x4 = BigFloat.(["0.0694318442029737123880267555535952474521373101851411811921390971150069362621467", "0.3300094782075718675986671204483776563997120651145428237035231072367364583996471", "0.6699905217924281324013328795516223436002879348854571762964769828255286829615636", "0.9305681557970262876119732444464047525478626898148588188078609457063963885589868", ])
const big_w4 = BigFloat.(["0.1739274225687269286865319746109997036176743479169467702462647873288657207063892", "0.3260725774312730713134680253890002963823256520830532297537352613642161665141882", "0.3260725774312730713134680253890002963823256520830532297537352588529504521363608", "0.1739274225687269286865319746109997036176743479169467702462646924539676606430575", ])
const big_x5 = BigFloat.(["0.04691007703066800360118656085030351743717404461873456856312774538495310585832495", "0.2307653449471584544818427896498955975163566965472200218989270432514549605914621", "0.5000000000000000000000000000000000000000000000000000000000797426589538788154181", "0.7692346550528415455181572103501044024836433034527799781012355866502245903569066", "0.9530899229693319963988134391496964825628259553812654314370407466671948296256858", ])
const big_w5 = BigFloat.(["0.1184634425280945437571320203599586813216300011062070077914363245751980472582409", "0.2393143352496832340206457574178190964561477766715707699864062992392239053715316", "0.2844444444444444444444444444444444444444444444444444444444573304920450434757956", "0.2393143352496832340206457574178190964561477766715707699864544060799612506070586", "0.1184634425280945437571320203599586813216300011062070077912456396135717532873701", ])
const big_x6 = BigFloat.(["0.03376524289842398609384922275300269543261713114385508756372519173669324957790098", "0.1693953067668677431693002024900473264967757178024149645927366470739082516964333", "0.3806904069584015456847491391596440322906946849299893249093024177128625328621882", "0.6193095930415984543152508608403559677093053150700106750906975822871374671378247", "0.8306046932331322568306997975099526735032242821975850354072633529260917483035732", "0.9662347571015760139061507772469973045673828688561449124362748082633067504220942", ])
const big_w6 = BigFloat.(["0.0856622461895851725201480710863664467634112507420219911993177198994728802711686", "0.1803807865240693037849167569188580558307609463733727411448696201185700189186321", "0.2339569672863455236949351719947754974058278028846052676558126599819571008101993", "0.233956967286345523694935171994775497405827802884605267655812659981957100810195", "0.1803807865240693037849167569188580558307609463733727411448696201185700189186256", "0.08566224618958517252014807108636644676341125074202199119931771989947288027117183", ])
const big_x7 = BigFloat.(["0.004929872133575382511273078541369005833050175678799509831107411346224851403894196", "0.05621464610426646944843588879386989279922531821579485139069338792689846975247951", "0.192287933937515541849713758599580029882154932092636671801817010573059843859954", "0.3984536481081884804663475670664267245733810143573168106648919508345540133232773", "0.6303829292704558125331985588105109567935632083246140000607245257050400884470481", "0.83556150914279693245080991327809828335238592867807829221382590113816878976327", "0.967225271993190330492166398923930257806838346389007730351566901746154753067759", ])
const big_w7 = BigFloat.(["0.01783956629577175664466161517779778330746762261739280193868888116464307618300876", "0.09200473466189314139337996394178583053265611188627297118565741860577372102041288", "0.1770039109583970541842419310398315314652008442538931692266384721379540913102143", "0.227630882575392394706842302518183045148130056062646081287058607732661591392765", "0.2272485914490278961711689421906388375849031602774791863163175474832987796256888", "0.1751216414188626855264193615824377275173037868653403184147776368054741810760185", "0.0831506726406550713732858835493252444443384180369754716308614360701945593918958", ])
const big_x8 = BigFloat.(["0.001731076483468685270312738321976022335247653348265799491291752676888324655463852", "0.02324239325675453541310616889139386853347071215419953798632062764425143212111116", "0.09674581137371957145465951844273824254653799833265552811149324227308844680975399", "0.2392034388083300373098325817761873300862438078606443203782515243905258660976843", "0.4377414076767430648608437870370205494748848997611776869673098571396591258307608", "0.6558058109441311212346397677935488371135950345845928481178266505564436739339613", "0.8471531551261965310775051873554285129614012469933877542714930228520273123505577", "0.9695608672869608660367505092846054315237604802943936622273926660421865678209417", ])
const big_w8 = BigFloat.(["0.00648051722632968580334106614227242117688991648717738051419594947334459502260248", "0.04249886199232947975876308636350701892667423974609345641479990672194805002887228", "0.1075793906538843862695869146830770045396978943792981645097158813680346763235746", "0.1750447315404564629273577322608578342561699810982462252671193876580950751308835", "0.2156888574332349972999088220266141505305931896033781190359618271951943097389702", "0.2125008990070870001049141617137792638781320237074018197374269892031613287174797", "0.1629674802715155610386405696905796745862955231428266578844571316431980172269869", "0.07723926187516242679748764711931263210554723183557817663632292673702394781061403", ])
const big_x9 = BigFloat.(["0.0008667056150679687310556652288569436907385437877138981057888864002168173244958056", "0.0122280227974677722385504897122547681746132158620974752074813304702917640058663", "0.05480618952483502181077931325849825384961877890619740899489187897956167653517274", "0.1479724698239139419056295126855349017672276520429764804253808066945167047226698", "0.2970327295923616776713877978535702864703987490795098148784984394014191846948765", "0.4876866420283321504345568480282204456865045811669770633300909323396820320457132", "0.6890765240440439634713012153821626128437843327643131136082765903924784802086815", "0.8626129599133903117371839678465821632020949373883030646894666014091469561601455", "0.9727063293384348507522097483930902940142000522105882750555178401920866287182623", ])
const big_w9 = BigFloat.(["0.003274998050208267294150508606138250683817401216433153311767094565563001679201521", "0.02313359082558968908460144360086466706488124569451662608076158761953109603160807", "0.06548060725856910278207153316883860438499930010336847275143993366561469729806786", "0.1218312674783635109299767023453009548358556338738575765857470968205141937769753", "0.173846779881900798110476532070518822473313843942857315313724461846196922415797", "0.2021610487996548918506456424823438545236363348536308756337183479670183496932752", "0.1940011564749999440632505455947670305529065622485673678531946231392676542355784", "0.1469746628249259371699540294690787861693361613628772591804787897776098200434126", "0.06929588840578785871487306266214902931125351670389135328916806459868426482607199", ])
const big_x10 = BigFloat.(["0.0005181961261082322472766705125340479900174875322281467529485321513894885979833173", "0.007465420091675458969500466087108891368802219689682897961139128243258364425744048", "0.03459491186740264883355418122867395454382629419333807279868225850754558414785065", "0.0975971115754346351913937631234074712307863612674323872325863975528816861786044", "0.206417705439011390678542948816149811668905321597780619366951240240363884154103", "0.3593223197305568860554706637412481214312776625092823039113159554783080462008666", "0.5409145569823813060562207909472447949677189410115970294850343468225381141652995", "0.7247101884173506583693766405048608650943421320009785899263353361616254227833195", "0.8792939364930664562292289635471936441225847549244316399022712337221415610078567", "0.9761172992753357690054548242993625400433499744882562766738928729785475675311865", ])
const big_w10 = BigFloat.(["0.001965567371635075131579256288544870059803127955115647264032642968078631060536703", "0.01432792816577584611857042476700654648649422540629984262180384241008794415186529", "0.04268191686661954873093685031206508271836823639234843167668804929665294052928837", "0.08508457499365887243509334455139864075115433485825750468759565514953919555209841", "0.1323019911493081912094714798178777091091080150778226083143129246153300131445892", "0.1708956795811918223417614118332969621708334291266240019249823757067261602912757", "0.1877671622133329938863531289790438941134765681225271869075098354721694488037552", "0.1744530516157494985126032352361095848091931713026742326752026513952084125816003", "0.1298293501440642503545269406245482685790299354859887555939751800285215578631445", "0.06069277789866390127910392759010844120253895627234178833389684295768569602184911", ])
const big_x11 = BigFloat.(["0.0003443027937109135938379257392787792195270698992816969762936160964556359137604324", "0.005013440864383067243350631424239433645064029252399323054292691041367933978740445", "0.02364331857940552032009849030947602840688383296539396136170458280031602132401195", "0.06832906693478315021724155223200949162548049943005956358316088710193697823676668", "0.1489678626315740314282860304118297803516562996303625981757521246031231427170625", "0.2688838656559724539423491761857709217537804019950614613561073810350146270995078", "0.4220897985161747732321112109047331469287654634290517346997682663343660208754401", "0.5930637127479588495458595939927986937605950267308572459511719743821404576187648", "0.7592028345589139171393141953611581168621813399181412693226876740966955975241855", "0.895370029154236793266330264734464498550020456534012095051569572437200644081219", "0.9794005414614251958306889531042697801706857543035411525475730358436694277191778", ])
const big_w11 = BigFloat.(["0.001308482060993663242256934335551828602557597584158319864496558916136475580582068", "0.00969288709408650133185273832612490903017063666717782862361318228555141531954964", "0.02966389152910070664026088218093860374186761085874794771767446706724502459211172", "0.06143343298637082474236249240006655872937604792306683029136169082125059831687015", "0.1004460191987578538388849340828766588722640884773582815408521130982985507869617", "0.1383922249121359956175747893411838985211421142619578716591922120708412482654264", "0.1653902823184988185876467092764404923048134540123907701310142247185824604911606", "0.1727117730020824070651803079243652850518442833088207015220610680720652237250866", "0.1552819614608011145886733180725256592817449838664247753879602818711437247875774", "0.1132688655746851899854851412461426927195457990615465803363035033863602674502828", "0.05241017986248692435982175281378341314467338397835009292547069769252501068438447", ])
const big_x12 = BigFloat.(["0.0002452842649772222144869997536432543470205814371170075690180054147088520992775438", "0.003593698020213691584953180824439056033669956241158510051647368882583871270772168", "0.01712292595159614370417434779200315632782276920007431158061911297835067104148647", "0.05020561232318819384573670192053134139721951029885763772161090595236481462236433", "0.1115235855573625644218104509890506301070703909739116102593900185940751708338317", "0.2060030029051239758752495933280674817971879824277011300806331528780271180801483", "0.3324626975136065400973675489452151731186473889850867214190447787726903983452818", "0.4826067009659319425485030369276700182993773813799224674012307668491958228063377", "0.6416794701239928589863342356411077314045630121734446869043875124123942657411672", "0.7907090871833554068663998980238029847238415941839073624406370514064356527864469", "0.9098838287655625921196627460245725561418481528176771869176662052248263188597252", "0.982347937715761951022141891215901227156130866563412648512060764471403968478102", ])
const big_w12 = BigFloat.(["0.0009331998830671428063097434802853682009550206244007777128833566469644722444453541", "0.006977495915143715985530451668181416880378092685376110400758040623857214633101594", "0.02169468902199853397715717399245055984405286952548586980559524949213660052353543", "0.04597069439559112469266362276166163303194960891828198574630707656287883134112197", "0.07752703869583178458842135271764051929635605596237314175811225613121850661805001", "0.1112525181837396068263131380719231904839616235119275896079063799871294167236009", "0.140273106008583333229227269735827131918570705030426981927389251409881630664525", "0.1575171300868296275541516487246811892573829874737442836958479223034436156494236", "0.1574083422236489759715520806009181432232319978495268878658371301577126086414867", "0.1372838327177858585860313720888032238952499990833424890457450322462456922961358", "0.09819669547418950067876642127280557873215905943121389372635589441374029408861288", "0.04496525739359079510387572488482204523575197990389998870726241002479111657595298", ])

const x1 = [0.5, ]
const w1 = ["1.0", ])
const x2 = [0.2113248654051871, 0.7886751345948129, ]
const w2 = ["0.5", "0.5", ])
const x3 = [0.11270166537925831, 0.5, 0.8872983346207417, ]
const w3 = ["0.2777777777777778", "0.4444444444444444", "0.2777777777777778", ])
const x4 = [0.06943184420297371, 0.33000947820757187, 0.6699905217924281, 0.9305681557970263, ]
const w4 = ["0.17392742256872692", "0.32607257743127305", "0.32607257743127305", "0.17392742256872692", ])
const x5 = [0.046910077030668004, 0.23076534494715845, 0.5, 0.7692346550528415, 0.953089922969332, ]
const w5 = ["0.11846344252809454", "0.23931433524968324", "0.28444444444444444", "0.23931433524968324", "0.11846344252809454", ])
const x6 = [0.03376524289842399, 0.16939530676686773, 0.38069040695840156, 0.6193095930415985, 0.8306046932331322, 0.966234757101576, ]
const w6 = ["0.08566224618958518", "0.1803807865240693", "0.23395696728634552", "0.23395696728634552", "0.1803807865240693", "0.08566224618958518", ])
const x7 = [0.004929872133575383, 0.05621464610426647, 0.19228793393751553, 0.3984536481081885, 0.6303829292704558, 0.8355615091427969, 0.9672252719931903, ]
const w7 = ["0.017839566295771755", "0.09200473466189314", "0.17700391095839704", "0.2276308825753924", "0.2272485914490279", "0.1751216414188627", "0.08315067264065507", ])
const x8 = [0.0017310764834686852, 0.023242393256754534, 0.09674581137371957, 0.23920343880833003, 0.4377414076767431, 0.6558058109441312, 0.8471531551261965, 0.9695608672869609, ]
const w8 = ["0.006480517226329686", "0.04249886199232948", "0.10757939065388439", "0.17504473154045647", "0.215688857433235", "0.212500899007087", "0.16296748027151556", "0.07723926187516243", ])
const x9 = [0.0008667056150679687, 0.012228022797467772, 0.05480618952483502, 0.14797246982391393, 0.29703272959236166, 0.4876866420283322, 0.689076524044044, 0.8626129599133903, 0.9727063293384348, ]
const w9 = ["0.003274998050208267", "0.02313359082558969", "0.0654806072585691", "0.12183126747836351", "0.1738467798819008", "0.20216104879965488", "0.19400115647499994", "0.14697466282492594", "0.06929588840578786", ])
const x10 = [0.0005181961261082322, 0.007465420091675459, 0.03459491186740265, 0.09759711157543463, 0.2064177054390114, 0.3593223197305569, 0.5409145569823813, 0.7247101884173507, 0.8792939364930664, 0.9761172992753357, ]
const w10 = ["0.0019655673716350752", "0.014327928165775846", "0.04268191686661955", "0.08508457499365887", "0.13230199114930818", "0.1708956795811918", "0.187767162213333", "0.1744530516157495", "0.12982935014406424", "0.060692777898663904", ])
const x11 = [0.0003443027937109136, 0.005013440864383067, 0.02364331857940552, 0.06832906693478315, 0.14896786263157402, 0.26888386565597244, 0.4220897985161748, 0.5930637127479589, 0.7592028345589139, 0.8953700291542368, 0.9794005414614252, ]
const w11 = ["0.0013084820609936632", "0.009692887094086501", "0.029663891529100705", "0.06143343298637082", "0.10044601919875785", "0.13839222491213599", "0.1653902823184988", "0.1727117730020824", "0.15528196146080112", "0.11326886557468518", "0.05241017986248692", ])
const x12 = [0.0002452842649772222, 0.0035936980202136916, 0.017122925951596143, 0.050205612323188195, 0.11152358555736257, 0.20600300290512397, 0.3324626975136065, 0.48260670096593195, 0.6416794701239928, 0.7907090871833554, 0.9098838287655626, 0.9823479377157619, ]
const w12 = ["0.0009331998830671429", "0.006977495915143716", "0.021694689021998535", "0.04597069439559112", "0.07752703869583179", "0.1112525181837396", "0.14027310600858334", "0.15751713008682963", "0.15740834222364897", "0.13728383271778585", "0.09819669547418951", "0.04496525739359079", ])


text:
using Test
using StatsBase
using LearnBase
using MLLabelUtils
using MLDataPattern
using ReferenceTests
using Random
using SparseArrays

# --------------------------------------------------------------------
# create some test data

showcompact(io, x) = show(IOContext(io, :compact => true), x)

Random.seed!(1335)
X = rand(4, 150)
y = repeat(["setosa","versicolor","virginica"], inner = 50)
Y = permutedims(hcat(y,y), [2,1])
Yt = hcat(y,y)
yt = Y[1:1,:]
Xv = view(X,:,:)
yv = view(y,:)
XX = rand(20,30,150)
XXX = rand(3,20,30,150)
vars = (X, Xv, yv, XX, XXX, y)
tuples = ((X,y), (X,Y), (XX,X,y), (XXX,XX,X,y))
Xs = sprand(10,150,.5)
ys = sprand(150,.5)
# to compare if obs match
X1 = hcat((1:150 for i = 1:10)...)'
Y1 = collect(1:150)

struct EmptyType end

struct CustomType end
LearnBase.nobs(::CustomType) = 100
LearnBase.getobs(::CustomType, i::Int) = i
LearnBase.getobs(::CustomType, i::AbstractVector) = collect(i)
LearnBase.gettargets(::CustomType, i::Int) = "obs $i"
LearnBase.gettargets(::CustomType, i::AbstractVector) = "batch $i"

struct CustomStorage end
struct CustomObs{T}; data::T end
LearnBase.nobs(::CustomStorage) = 2
LearnBase.getobs(::CustomStorage, i) = CustomObs(i)
LearnBase.gettarget(str::String, obs::CustomObs) = "$str - obs $(obs.data)"
LearnBase.gettarget(obs::CustomObs) = "obs $(obs.data)"

struct ObsDimTriggeredException <: Exception end
struct MetaDataStorage end
LearnBase.nobs(::MetaDataStorage) = 3
LearnBase.getobs(::MetaDataStorage, i) = throw(ObsDimTriggeredException())
LearnBase.gettargets(::MetaDataStorage) = "full"
LearnBase.gettargets(::MetaDataStorage, i::Int) = "obs $i"
LearnBase.gettargets(::MetaDataStorage, i::AbstractVector) = "batch $i"

# --------------------------------------------------------------------

tests = [
    "tst_container.jl"
    "tst_datasubset.jl"
    "tst_randobs.jl"
    "tst_shuffleobs.jl"
    "tst_splitobs.jl"
    "tst_dataview.jl"
    "tst_slidingwindow.jl"
    "tst_targets.jl"
    "tst_stratifiedobs.jl"
    "tst_resample.jl"
    "tst_folds.jl"
    "tst_dataiterator.jl"
]

for t in tests
    @testset "$t" begin
        include(t)
    end
end


text:
include("cholesky.jl")
include("elimination_game.jl")
include("lex_m.jl")
include("mcs_m.jl")
include("minimum_degree.jl")

const chordal_extension_functions = Dict(
    "cholesky" => choleskydec,
    "minimum_degree" => minimum_degree,
    "mcs_m" => mcs_m,
    "lex_m" => lex_m,
    "elimination_game" => elimination_game
)

function chordal_extension(g::AbstractGraph, extension_alg::AbstractString; kwargs...)
    chordal_g, data = chordal_extension_functions[extension_alg](g; kwargs...)
    for v in vertices(chordal_g)
        rem_edge!(chordal_g, v, v)
    end
    return chordal_g, data
end

max_stars_repo_name: charlyalizadeh/PowerFlowNetworks

max_issues_repo_name: charlyalizadeh/PowerFlowNetworks

max_forks_repo_name: charlyalizadeh/PowerFlowNetworks