text:
export maybe_static, @stat

"""
    maybe_static(f, args...)

Returns `static(f(args...))`, if all of `args` are `Static` and `f` returns a number.
If any of the args is not `Static`, then `f(args...)` is returned unchanged.

The `@stat` macro applies the `maybe_static` function to all function calls,
and this function can be overloaded to provide special behaviuor for certain
functions under the macro.
"""
@inline function maybe_static(f::F, args...; kwargs...) where {F}
    y = f(args...; kwargs...)
    if y isa Number && !(y isa Bool) && !(y isa Unsigned) &&
            all(map(a->a isa Static, args)) && all(map(a->a isa Static, values(kwargs)))
        static(y)
    else
        y
    end
end

@inline maybe_static(::typeof(nfields), t) = static(nfields(t))

@inline maybe_static(::typeof(firstindex), T::Tuple) = static(firstindex(T))
@inline maybe_static(::typeof(lastindex), T::Tuple) = static(lastindex(T))
@inline maybe_static(::typeof(length), T::Tuple) = static(length(T))

@inline maybe_static(::typeof(axes), T::Tuple) = StaticOneTo(length(T))

"""
Turn all constants in an expression into `static` and all
function calls into `trystatic`.
"""
statify(ex) = ex
statify(x::Number) = :( $static($x) )
statify(x::Unsigned) = x
function statify(ex::Expr)
    if ex.head == :call
        a1 = first(ex.args)::Union{Symbol, Expr}
        if first(string(a1)) == '.'  #for example: .+
            # TODO: We should handle breadcasted maybe_static.
            # Expr(:., maybe_static, Expr(:tuple, Symbol(string(ex.args[1])[2:end]), map(statify, ex.args[2:end])...))
            Expr(ex.head, map(statify, ex.args)...)
        elseif a1 ∈ (:oftype, :typeof)
            # Changing the type of the argument(s) makes no sense for these functions
            Expr(ex.head, maybe_static, ex.args...)
        else
            Expr(ex.head, maybe_static, map(statify, ex.args)...)
        end
    #elseif ex.head == :.
    #    Expr(:., maybe_static, Expr(:tuple, ex.args[1], map(statify, ex.args[2].args)...))
    elseif ex.head ∈ (:if, :&&, :||, :(=))
        Expr(ex.head, ex.args[1], map(statify, ex.args[2:end])...)
    elseif ex.head == :ref
        Expr(ex.head, :( $StaticNumbers.MaybeStatic($(statify(ex.args[1]))) ), map(statify, ex.args[2:end])...)
    else
        Expr(ex.head, map(statify, ex.args)...)
    end
end

# The name @static was taken!
macro stat(ex)
    esc(statify(ex))
end

"A wrapper type applied by the @stat macro"
struct MaybeStatic{T}
    parent::T
end

@inline Base.getindex(r::MaybeStatic, args...) = maybe_static(getindex, r.parent, args...)
@inline Base.step(r::MaybeStatic) = maybe_static(step, r.parent)
@inline Base.length(r::MaybeStatic) = maybe_static(length, r.parent)
@inline Base.unsafe_length(r::MaybeStatic) = maybe_static(Base.unsafe_length, r.parent)
@inline Base.firstindex(r::MaybeStatic) = maybe_static(firstindex, r.parent)
@inline Base.lastindex(r::MaybeStatic) = maybe_static(lastindex, r.parent)
@inline Base.first(r::MaybeStatic) = maybe_static(first, r.parent)
@inline Base.last(r::MaybeStatic) = maybe_static(last, r.parent)

maybe_static(::typeof(oftype), x, y) = oftype(x, y)
maybe_static(::typeof(oftype), x, y::Static) = static(oftype(x, y))
maybe_static(::typeof(oftype), ::Static{X}, ::Static{Y}) where {X,Y} = static(oftype(X, Y))


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

struct AvailabilitySetsApi <: SwaggerApi
    client::Swagger.Client
end

"""

Create or update an availability set.
Param: resourceGroupName::String (required)
Param: availabilitySetName::String (required)
Param: parameters::AvailabilitySet (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: AvailabilitySet
"""
function _swaggerinternal_availabilitySetsCreateOrUpdate(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", AvailabilitySet, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "availabilitySetName", availabilitySetName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function availabilitySetsCreateOrUpdate(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsCreateOrUpdate(_api, resourceGroupName, availabilitySetName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function availabilitySetsCreateOrUpdate(_api::AvailabilitySetsApi, response_stream::Channel, resourceGroupName::String, availabilitySetName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsCreateOrUpdate(_api, resourceGroupName, availabilitySetName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Delete an availability set.
Param: resourceGroupName::String (required)
Param: availabilitySetName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_availabilitySetsDelete(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "availabilitySetName", availabilitySetName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function availabilitySetsDelete(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsDelete(_api, resourceGroupName, availabilitySetName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function availabilitySetsDelete(_api::AvailabilitySetsApi, response_stream::Channel, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsDelete(_api, resourceGroupName, availabilitySetName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Retrieves information about an availability set.
Param: resourceGroupName::String (required)
Param: availabilitySetName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: AvailabilitySet
"""
function _swaggerinternal_availabilitySetsGet(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", AvailabilitySet, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "availabilitySetName", availabilitySetName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function availabilitySetsGet(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsGet(_api, resourceGroupName, availabilitySetName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function availabilitySetsGet(_api::AvailabilitySetsApi, response_stream::Channel, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsGet(_api, resourceGroupName, availabilitySetName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Lists all availability sets in a resource group.
Param: resourceGroupName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: AvailabilitySetListResult
"""
function _swaggerinternal_availabilitySetsList(_api::AvailabilitySetsApi, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", AvailabilitySetListResult, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function availabilitySetsList(_api::AvailabilitySetsApi, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsList(_api, resourceGroupName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function availabilitySetsList(_api::AvailabilitySetsApi, response_stream::Channel, resourceGroupName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsList(_api, resourceGroupName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Lists all available virtual machine sizes that can be used to create a new virtual machine in an existing availability set.
Param: resourceGroupName::String (required)
Param: availabilitySetName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: VirtualMachineSizeListResult
"""
function _swaggerinternal_availabilitySetsListAvailableSizes(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", VirtualMachineSizeListResult, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}/vmSizes", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "availabilitySetName", availabilitySetName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function availabilitySetsListAvailableSizes(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsListAvailableSizes(_api, resourceGroupName, availabilitySetName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function availabilitySetsListAvailableSizes(_api::AvailabilitySetsApi, response_stream::Channel, resourceGroupName::String, availabilitySetName::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsListAvailableSizes(_api, resourceGroupName, availabilitySetName, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Lists all availability sets in a subscription.
Param: api_version::String (required)
Param: subscriptionId::String (required)
Param: expand::String
Return: AvailabilitySetListResult
"""
function _swaggerinternal_availabilitySetsListBySubscription(_api::AvailabilitySetsApi, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", AvailabilitySetListResult, "/subscriptions/{subscriptionId}/providers/Microsoft.Compute/availabilitySets", ["azure_auth"])
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_param(_ctx.query, "\$expand", expand)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function availabilitySetsListBySubscription(_api::AvailabilitySetsApi, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsListBySubscription(_api, api_version, subscriptionId; expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function availabilitySetsListBySubscription(_api::AvailabilitySetsApi, response_stream::Channel, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsListBySubscription(_api, api_version, subscriptionId; expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Update an availability set.
Param: resourceGroupName::String (required)
Param: availabilitySetName::String (required)
Param: parameters::AvailabilitySetUpdate (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: AvailabilitySet
"""
function _swaggerinternal_availabilitySetsUpdate(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", AvailabilitySet, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/availabilitySets/{availabilitySetName}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "availabilitySetName", availabilitySetName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function availabilitySetsUpdate(_api::AvailabilitySetsApi, resourceGroupName::String, availabilitySetName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsUpdate(_api, resourceGroupName, availabilitySetName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function availabilitySetsUpdate(_api::AvailabilitySetsApi, response_stream::Channel, resourceGroupName::String, availabilitySetName::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_availabilitySetsUpdate(_api, resourceGroupName, availabilitySetName, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export availabilitySetsCreateOrUpdate, availabilitySetsDelete, availabilitySetsGet, availabilitySetsList, availabilitySetsListAvailableSizes, availabilitySetsListBySubscription, availabilitySetsUpdate

ext: jl


text:
module TestUnion

include("preamble.jl")
using BangBang: SingletonVector
using InitialValues: Init, asmonoid

@testset begin
    @test union!!([0.0], [1.0]) ==ₜ [0.0, 1.0]
    @test union!!([0], [0.5]) ==ₜ [0.0, 0.5]
    @test union!!(Set([0.0]), [1.0]) ==ₜ Set([0.0, 1.0])
    @test union!!(Set([0]), [0.5]) ==ₜ Set([0.0, 0.5])
    @test union!!(Empty(Set), [0]) ==ₜ Set([0])
    @test union!!(Empty(Set), SingletonVector(0)) ==ₜ Set([0])
end

@testset "Empty" begin
    @testset "union!!(::Empty, ::Empty) :: Empty" begin
        @test union!!(Empty(Set), Empty(Set)) === Empty(Set)
        @test union!!(Empty(Set), Empty(Vector)) === Empty(Set)
    end
end

@testset "mutation" begin
    @testset "Vector" begin
        x = [0.0]
        @test union!!(x, [1]) === x
        @test x ==ₜ [0.0, 1.0]
    end
    @testset "Set" begin
        x = Set([0.0])
        @test union!!(x, [1]) === x
        @test x ==ₜ Set([0.0, 1.0])
    end
end

@testset "Init" begin
    xs = Set([0])
    @test union!!(xs, Init(union!!)) === xs
    @test union!!(Init(union!!), xs) !== xs
    @test union!!(Init(union!!), xs) ==ₜ xs
    @test union!!(Init(union!!), (x for x in xs if true)) ==ₜ xs
    @test union!!(Init(union!!), Init(union!!)) === Init(union!!)
    @test asmonoid(union!!) === union!!
end

end  # module


text:
module TestRequest

using HTTP

function testrequestlayer(handler)
    return function(req; httptestlayer=Ref(false), kw...)
        httptestlayer[] = true
        return handler(req; kw...)
    end
end

function teststreamlayer(handler)
    return function(stream; httptestlayer=Ref(false), kw...)
        httptestlayer[] = true
        return handler(stream; kw...)
    end
end

HTTP.@client (testrequestlayer,) (teststreamlayer,)

end


text:
module BiApprox

import LinearAlgebra: norm, dot
import MLKernels: Kernel, kernel, GaussianKernel, PeriodicKernel
import Random: randperm
import Statistics: mean, std, var

export kernel_approx_ul, approx_values, train_model, F̂
export train, train!, evaluate, KernelInterpolation, Data
export approximate

export LL_approx, bruteforce!, Ψ_approx, update_approximation_errors!, fit!

include("structures.jl")
include("kernelInterpolation.jl")
include("approximate.jl")
include("psi_approx.jl")
include("deprecated.jl")

end # module


text:
module DocumentDistances
using Distances, JSON, SinkhornDistance, DataDeps, TextAnalysis, SparseArrays

println("Loading the Embeddings package. This takes some time...")
using Embeddings

export SinkhornDocumentDistance, evaluate
export WordDistanceCache, embedding, worddistance, save
export WordMoversDistance
export find_k_nearest_neighbours
export FilteredNGramDocument

abstract type AbstractDocumentDistance <: SemiMetric end

include("word_distance_cache.jl")
include("sinkhorn_document_distance.jl")
include("pdf2text.jl")
include("word_movers_distance.jl")
include("k_nearest_neighbours.jl")
include("textanalysis_interface.jl")

function __init__()
    register_tika_app_jar_dependency()
end

end  # module


text:
# Utilities for Gibbs sampling with geometric inter-arrivals

function update_geometric_interarrival_param!(p::Vector{Float64},PP::Vector{Int},T::Vector{Int},n::Int,params::Vector{Float64})
    """
    - `p`: current geometric parameter for the interarrival time distribution (will be updated in place)
    - `PP`: partition/degree vector
    - `T`: arrival times vector
    - `n`: number of observations
    - `params`: parameters of prior Beta distribution
    """
    K = size(T,1)
    update_geometric_interarrival_param!(p,K,n,params)

end

function update_geometric_interarrival_param!(p::Vector{Float64},K::Int,n::Int,params::Vector{Float64})
    """
    - `p`: current geometric parameter for the interarrival time distribution (will be updated in place)
    - `K`: number of blocks in partition (=# of arrivals)
    - `n`: number of observations
    - `params`: parameters of prior Beta distribution
    """
    # sample conjugate p
    p[1] = rand(Beta(K-1+params[1],n-K+params[2]))

end


text:
using LightGraphs
using DataStructures

struct SpanningTreeInstance{T}
  graph::AbstractGraph{T}
  rewards::Dict{Edge{T}, Float64}
end

graph(i::SpanningTreeInstance{T}) where T = i.graph
# rewards(i::SpanningTreeInstance{T}) where T = i.rewards
function reward(i::SpanningTreeInstance{T}, e::Edge{T}) where T
  if e in keys(i.rewards)
    return i.rewards[e]
  end
  return i.rewards[reverse(e)]
end

struct SpanningTreeSolution{T}
  instance::SpanningTreeInstance{T}
  tree::Vector{Edge{T}}
end

function st_prim(i::SpanningTreeInstance{T}) where T
  remaining_edges = PriorityQueue{Edge{T}, Float64}(Base.Reverse) # Easy retrieval of highest-reward edge.
  node_done = falses(nv(graph(i)))

  # Helper methods.
  edges_around(g, v) = ((v < x) ? edgetype(g)(v, x) : edgetype(g)(x, v) for x in neighbors(g, v))

  # Initialise with the source node (arbitrarily, the first one).
  first_node = first(vertices(graph(i)))
  node_done[first_node] = true
  for e in edges_around(graph(i), first_node)
    enqueue!(remaining_edges, e => reward(i, e))
  end

  # Build the spanning tree.
  solution = Edge{T}[]
  while length(solution) < nv(graph(i)) - 1 # While there is still an edge to add...
    # Find an admissible edge, starting with those of minimum reward.
    e = nothing
    new_node = nothing
    while isnothing(new_node)
      e = dequeue!(remaining_edges)

      if node_done[src(e)] && ! node_done[dst(e)]
        new_node = dst(e)
      end
      if ! node_done[src(e)] && node_done[dst(e)]
        new_node = src(e)
      end
    end

    @assert ! node_done[new_node]

    # Use this edge in the solution.
    push!(solution, e)
    node_done[new_node] = true

    # Prepare to use the neighbours of this new node, but skip nodes already done.
    for ϵ in edges_around(graph(i), new_node)
      if haskey(remaining_edges, ϵ)
        # No need to update the priority, the edge still has the same reward.
        continue
      end

      # Ensure the edge links a node already in the tree and another one outside.
      if (node_done[src(ϵ)] && ! node_done[dst(ϵ)]) || (! node_done[src(ϵ)] && node_done[dst(ϵ)])
        enqueue!(remaining_edges, ϵ => reward(i, ϵ))
      end
    end
  end

  return SpanningTreeSolution(i, solution)
end


text:
import Base:  ==, hash
"""
    Patch()
"""
mutable struct Patch{T}
    state::T
    id::UUID
    Patch(data::T, rng::AbstractRNG=Random.GLOBAL_RNG) where T = new{T}(data,UUIDs.uuid4(rng))
end

function ==(patch1::Patch, patch2::Patch)
    patch1.id==patch2.id
end

function hash(patch::Patch, h::UInt)
    hash(patch.id, h)
end


text:
# Function for Synthetic Control
function normalz(xₒ, x₁, idx_control, idx_treat)
    x = hcat(xₒ, x₁);
    k, n = size(x);
    kₒ = size(xₒ, 1);
    k₁ = size(x₁, 1);

    xscale = 1 ./ std(x, dims = 2);

    xmat = ((x') * (eye(k) .* xscale))';
    xₒscale = xmat[1:kₒ, idx_control];
    x₁scale = xmat[1:k₁, idx_treat];

    return xₒscale, x₁scale;
end

# Create diagonal identiy matrix
eye(n) = Matrix{Float64}(I, n, n);

# Standardize matrix
function func_std(mat)
    # Function to standardize data
    T, k = size(mat);
    μ = mean(mat; dims = 1);
    σ = std(mat; dims = 1);
    return (mat .- μ) ./ σ;
end

# Loss function
function loss_ssr(ν)
    l = size(yₒpre, 2);

    ν = [1; ν];
    D = (eye(length(ν)) .* ν);

    H = xₒ' * D * xₒ;
    f = -1 .* (x₁' * D * xₒ);

    ω = abs.(solveQadProg(H, f));

    e = y₁pre - yₒpre*ω;
    ln_ssr = log(sum(e.^2));
    return ln_ssr
end
# More on the solver type:
# https://jump.dev/JuMP.jl/v0.21.1/installation/;
# Useful website on vectorization
# https://www.softcover.io/read/7b8eb7d0/juliabook/optimization
function solveQadProg(H, f)#, ceq, beq)
    #model = Model(with_optimizer(GLPK.Optimizer))
    optimizer = Juniper.Optimizer
    nl_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level"=>0)

    model = Model(optimizer_with_attributes(optimizer, "nl_solver"=>nl_solver))

    k = size(H, 1);

    @variable(model, x[1:k])
    @constraint(model, [i = 1:k], 0 <= x[i] <= 1)

    @objective(model, Min,
                    (
                        sum(0.5 * H[i,j] * x[i] * x[j] for i = 1:length(x), j = 1:length(x)) +
                        sum( f[i] * x[i] for i = 1:length(x))
                    )
                );
    @constraint(model, sum( x[i] for i = 1:length(x) ) == 1)

    optimize!(model)

    res = JuMP.value.(x);
    return res
end


text:
module Parameters

export Param, setParameters

const BCDirichlet,BCRiemann = 1,2 # Constants for different boundary types

using TOML

# Parameters
struct Param
   nD::Int             # Dimension of the system
   LatticeType::Int    # DmQn lattice model
   Δx::Float64         # Discretized space interval
   Δt::Float64         # Discretized time interval
   α ::Float64         # Thermal diffusivity
   ω ::Float64         # Relaxation coefficient
   TotalTime::Float64  # Total simulation time
   nT::Int             # Total timesteps
   nI::Int             # Number of space intervals in x
   nJ::Int             # Number of space intervals in y

   Tᴸ::Float64     # Left boundary temperature
   Tᴿ::Float64     # Right boundary temperature
   Tᵀ::Float64     # Top boundary temperature
   Tᴮ::Float64     # Bottom boundary temperature

   BCtype::Int         # Type of boundary conditions

   function Param(nD::Int=2,LatticeType::Int=3,dx::Float64=1.0,dt::Float64=1.0,
      α::Float64=0.25,TotalTime::Float64=400.0,nI::Int=100,nJ::Int=100,
      Tleft::Float64=1.0,Tright::Float64=0.0,
      Ttop::Float64=0.0,Tbot::Float64=0.0,
      BCtype::Int=1)
      @assert(0 ≤ TotalTime, "Simulation time must be positive!")

      new(nD,LatticeType,dx,dt,α,inv(nD*dt*α/dx^2 + 0.5),TotalTime,
         Int(TotalTime/dt),nI,nJ,Tleft,Tright,Ttop,Tbot,BCtype)
   end
end

function setParameters()
   paramIn = TOML.parsefile("PARAM.toml")
   nD = paramIn["Parameters"]["nD"]
   LatticeType = paramIn["Parameters"]["LatticeType"]
   dx = paramIn["Parameters"]["dx"]
   dt = paramIn["Parameters"]["dt"]
   α = paramIn["Parameters"]["α"]
   TotalTime = paramIn["Parameters"]["TotalTime"]
   nI = paramIn["Parameters"]["nI"]
   nJ = paramIn["Parameters"]["nJ"]
   Tleft = paramIn["Parameters"]["Tleft"]
   Tright = paramIn["Parameters"]["Tright"]
   Ttop = paramIn["Parameters"]["Ttop"]
   Tbot = paramIn["Parameters"]["Tbot"]
   BCtype = paramIn["Parameters"]["BCtype"]

   if LatticeType == "D2Q4"
      LT = 1
   elseif LatticeType == "D2Q5"
      LT = 2
   elseif LatticeType == "D2Q9"
      LT = 3
   end

   if BCtype == "Dirichlet"
      BC = 1
   elseif BCtype == "Riemann"
      BC = 2
   end

   param = Param(nD,LT,dx,dt,α,TotalTime,nI,nJ,Tleft,Tright,Ttop,Tbot,BC)

end

end


text:
import GLPK
const lp_solver = GLPK.Optimizer
import Polyhedra
const lib = Polyhedra.DefaultLibrary{Float64}(lp_solver)

include("Sets.jl")
include("apply.jl")
include("variables.jl")
include("L1_heuristic.jl")
include("recipes.jl")
include("mock_tests.jl")


text:
struct StateValue
  state :: EVENT_STATE
  value :: Any
  function StateValue(state::EVENT_STATE, value::Any=nothing)
    new(state, value)
  end
end

struct Operator <: AbstractEvent
  bev :: BaseEvent
  eval :: Function
  function Operator(eval::Function, fev::AbstractEvent, events::AbstractEvent...)
    env = environment(fev)
    op = new(BaseEvent(env), eval)
    event_state_values = Dict{AbstractEvent, StateValue}()
    for ev in tuple(fev, events...)
      event_state_values[ev] = StateValue(state(ev))
      @callback check(ev, op, event_state_values)
    end
    op
  end
end

function check(ev::AbstractEvent, op::Operator, event_state_values::Dict{AbstractEvent, StateValue})
  val = value(ev)
  if state(op) == idle
    if isa(val, Exception)
      schedule(op; value=val)
    else
      event_state_values[ev] = StateValue(state(ev), val)
      op.eval(collect(values(event_state_values))) && schedule(op; value=event_state_values)
    end
  elseif state(op) == scheduled
    if isa(val, Exception)
      schedule(op; priority=typemax(Int), value=val)
    else
      event_state_values[ev] = StateValue(state(ev), val)
    end
  end
end

function eval_and(state_values::Vector{StateValue})
  all(map((sv)->sv.state == processed, state_values))
end

function eval_or(state_values::Vector{StateValue})
  any(map((sv)->sv.state == processed, state_values))
end

function (&)(ev1::AbstractEvent, ev2::AbstractEvent)
  Operator(eval_and, ev1, ev2)
end

function (|)(ev1::AbstractEvent, ev2::AbstractEvent)
  Operator(eval_or, ev1, ev2)
end


text:
function buildptdf(branches::Array{T}, nodes::Array{Bus}, dist_slack::Array{Float64}=[0.1] ) where {T<:Branch}

    buscount = length(nodes)
    linecount = length(branches)
    line_axis = [branch.name for branch in branches]
    num_bus = Dict{Int,Int}()

    for (ix,b) in enumerate(nodes)
        if b.number < -1
            @error "buses must be numbered consecutively in the bus/node matrix" # TODO: raise error here?
        end
        num_bus[b.number] = ix
    end

    A = zeros(Float64,buscount,linecount);
    inv_X = zeros(Float64,linecount,linecount);

   #build incidence matrix
   #incidence_matrix = A

    for (ix,b) in enumerate(branches)

        isa(b,DCLine) ? continue : true

        A[num_bus[b.connectionpoints.from.number], ix] =  1;

        A[num_bus[b.connectionpoints.to.number], ix] = -1;

        if isa(b,Transformer2W)
            inv_X[ix,ix] = 1/b.x;

        elseif isa(b,TapTransformer)
            inv_X[ix,ix] = 1/(b.x*b.tap);

        elseif isa(b, Line)
            inv_X[ix,ix] = 1/b.x;

        elseif isa(b,PhaseShiftingTransformer)
            y = 1 / (b.r + b.x * 1im)
            y_a = y / (b.tap * exp(b.α * 1im * (π / 180)))
            inv_X[ix,ix] = 1/imag(y_a)
        end
    end
    slacks = [num_bus[n.number] for n in nodes if n.bustype == "SF"]
    slack_position = slacks[1]
    bus_axis = [bus.name for bus in nodes]

    B = gemm('N','T', gemm('N','N',A[setdiff(1:end, slack_position),1:end] ,inv_X), A[setdiff(1:end, slack_position),1:end])

    if dist_slack[1] == 0.1 && length(dist_slack) ==1
        (B, bipiv, binfo) = getrf!(B)
        S_ = gemm('N','N', gemm('N','T', inv_X, A[setdiff(1:end, slack_position), :]), getri!(B, bipiv) )
        S = hcat(S_[:,1:slack_position-1],zeros(linecount,),S_[:,slack_position:end])

    elseif dist_slack[1] != 0.1 && length(dist_slack)  == buscount
        @info "Distributed bus"
        (B, bipiv, binfo) = getrf!(B)
        S_ = gemm('N','N', gemm('N','T', inv_X, A[setdiff(1:end, slack_position), :]), getri!(B, bipiv) )
        S = hcat(S_[:,1:slack_position-1],zeros(linecount,),S_[:,slack_position:end])
        slack_array =dist_slack/sum(dist_slack)
        slack_array = reshape(slack_array,buscount,1)
        S = S - gemm('N','N',gemm('N','N',S,slack_array),ones(1,buscount))

    elseif length(slack_position) == 0
        @warn "Slack bus not identified in the Bus/Nodes list, can't build PTDF"
        S = Array{Float64,2}(undef,linecount,buscount)
    end

    S_ax = AxisArrays.AxisArray(S, AxisArrays.Axis{:branches}(line_axis), AxisArrays.Axis{:buses}(bus_axis))
    A_ax = AxisArrays.AxisArray(A, AxisArrays.Axis{:buses}(bus_axis), AxisArrays.Axis{:lines}(line_axis))

    return  S_ax , A_ax

end


text:
using Compat: @warn, @info
using Tokenize
using Tokenize.Lexers
using Missings
const T = Tokenize.Tokens

noname(name::String) = name == ""

tokenerror(token, str) = error("Unexpected $(token.kind) token " *
                               "'$(untokenize(token))' instead of '$str'")

isWHITESPACE(token) = token.kind == T.WHITESPACE
isEQ(token) = token.kind == T.EQ
isEQorRSQUARE(token) = token.kind ∈ [T.EQ, T.RSQUARE]
isIDENTIFIER(token, text) =
    (token.kind == T.IDENTIFIER) & (lowercase(untokenize(token)) == text)
    isBEGIN(token) = (token.kind == T.BEGIN) | isIDENTIFIER(token, "begin")
isTAXA(token) = isIDENTIFIER(token, "taxa")
isTREE(token) = isIDENTIFIER(token, "tree")
isTREES(token) = isIDENTIFIER(token, "trees")
isDIMENSIONS(token) = isIDENTIFIER(token, "dimensions")
isTAXLABELS(token) = isIDENTIFIER(token, "taxlabels")
isTRANSLATE(token) = isIDENTIFIER(token, "translate")
isEND(token) = (token.kind == T.END) | isIDENTIFIER(token, "end")

function iterateskip(tokens, state = nothing)
    if VERSION < v"0.7.0-"
    if state !== nothing && done(tokens, state)
        return nothing
    end
    token, state = (state === nothing) ?
        next(tokens, start(tokens)) : next(tokens, state)
    while isWHITESPACE(token)
        token, state = next(tokens, state)
    end
    return token, state
    else
    result = (state === nothing) ? iterate(tokens) : iterate(tokens, state)
    result === nothing && return nothing
    token, state = result
    while isWHITESPACE(token)
        result = iterate(tokens, state)
        result === nothing && return nothing
        token, state = result
    end
    return token, state
    end
end

function tokensgetkey(token, state, tokens, finished::Function = isEQ)
    sofar = String[]
    while !finished(token) && token.kind != T.ENDMARKER
        if token.kind ∈ [T.STRING, T.CHAR]
            push!(sofar, untokenize(token)[2:end-1])
        else
            push!(sofar, untokenize(token))
        end
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    end
    return token, state, join(sofar)
end

function checktosemi(test::Function, token, state, tokens)
    if !test(token)
        return false
    end
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    if token.kind != T.SEMICOLON
        tokenerror(token, ";")
    end
    return true
end

function parsevector(token, state, tokens, ::Type{TY}, sgn) where TY <: Real
    vec = TY[]
    while token.kind != T.RBRACE && token.kind != T.ENDMARKER
        if token.kind == T.PLUS
            sgn = +;
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        elseif token.kind == T.MINUS
            sgn = -;
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        end
        push!(vec, sgn(parse(TY, untokenize(token))))
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
        if token.kind != T.COMMA && token.kind != T.RBRACE
            tokenerror(token, ",")
        elseif token.kind == T.COMMA
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        end
    end

    return token, state, vec
end

function parsevector(token, state, tokens)
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result

    sgn = +;
    if token.kind == T.MINUS
        sgn = -;
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    elseif token.kind == T.PLUS
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    end

    if token.kind == T.INTEGER
        return parsevector(token, state, tokens, Int, sgn)
    elseif token.kind == T.FLOAT
        return parsevector(token, state, tokens, Float64, sgn)
    end

    vec = String[]
    while token.kind != T.RBRACE && token.kind != T.ENDMARKER
        if token.kind ∈ [T.STRING, T.CHAR]
            push!(vec, untokenize(token)[2:end-1])
        else
            push!(vec, untokenize(token))
        end
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
        if token.kind != T.COMMA && token.kind != T.RBRACE
            tokenerror(token, ",")
        elseif token.kind == T.COMMA
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        end
    end

    return token, state, vec
end

function parsedict(token, state, tokens)
    dict = Dict{String, Any}()
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    if token.kind != T.AND
        tokenerror(token, "&")
    else
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    end

    while token.kind != T.RSQUARE && token.kind != T.ENDMARKER
        token, state, key = tokensgetkey(token, state, tokens, isEQorRSQUARE)
        if token.kind != T.RSQUARE # Allow [&R] as a valid (empty) dict
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            if token.kind == T.LBRACE
                token, state, value = parsevector(token, state, tokens)
            else
                sgn = +;
                if token.kind == T.PLUS
                    sgn = +;
                    result = iterateskip(tokens, state)
                    result === nothing && return nothing
                    token, state = result
                elseif token.kind == T.MINUS
                    sgn = -;
                    result = iterateskip(tokens, state)
                    result === nothing && return nothing
                    token, state = result
                end

                if token.kind == T.INTEGER
                    value = sgn(parse(Int, untokenize(token)))
                elseif token.kind == T.FLOAT
                    value = sgn(parse(Float64, untokenize(token)))
                elseif token.kind ∈ [T.STRING, T.CHAR]
                    value = untokenize(token)[2:end-1]
                else
                    value = untokenize(token)
                end
            end
            dict[key] = value

            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            if token.kind != T.COMMA && token.kind != T.RSQUARE
                tokenerror(token, ", or ]")
            elseif token.kind == T.COMMA
                result = iterateskip(tokens, state)
                result === nothing && return nothing
                token, state = result
            end
        end
    end

    if token.kind == T.RSQUARE
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    end

    return token, state, dict
end

function parsenode(token, state, tokens, tree::TREE,
                   lookup, siblings, istip) where {NL, BL,
                                                   TREE <: AbstractBranchTree{NL, BL}}
    myname = ""
    endkinds = [T.SEMICOLON, T.COLON, T.COMMA, T.RPAREN, T.LSQUARE]
    if token.kind ∉ endkinds # We got a nodename
        token, state, name = tokensgetkey(token, state, tokens,
                                          t -> t.kind ∈ endkinds)
        if isempty(lookup)
            myname = addnode!(tree, name)
        else
            if istip
                if haskey(lookup, name)
                    myname = lookup[name]
                else
                    @warn "Wrongly named tip '$name' found in tree " *
                        "with named tips, adding"
                    myname = addnode!(tree, name)
                end
            else
                if haskey(lookup, name)
                    myname = lookup[name]
                else
                    myname = addnode!(tree, name)
                end
            end
        end
    else
        if istip && !isempty(lookup)
            @warn "Anonymous tip found in tree with named tips"
        end
        myname = addnode!(tree)
    end

    foundcolon = false
    if token.kind == T.COLON
        foundcolon = true
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    end

    siblings[myname] = Dict{String, Any}()
    if token.kind == T.LSQUARE
        token, state, dict = parsedict(token, state, tokens)
        siblings[myname]["dict"] = dict
        setnoderecord!(tree, myname, dict)
    end

    if token.kind == T.COLON || foundcolon
        if token.kind == T.COLON
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        end
        sgn = +;
        if token.kind == T.PLUS
            sgn = +;
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        elseif token.kind == T.MINUS
            sgn = -;
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        end
        if token.kind ∈ [T.INTEGER, T.FLOAT]
            siblings[myname]["length"] = sgn(parse(Float64, untokenize(token)))
        else
            tokenerror(token, "a length")
        end
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    end

    return token, state, myname
end

function parsenewick!(token, state, tokens, tree::TREE,
                     lookup = Dict(), depth = 0,
                     children = Dict{NL, Dict{String, Any}}()) where
    {NL, BL, TREE <: AbstractBranchTree{NL, BL}}
    mychildren = Dict{NL, Dict{String, Any}}()
    while (token.kind != T.RPAREN) & (token.kind != T.ENDMARKER)
        result = iterateskip(tokens, state)
        result === nothing &&
            error("Tree ended at depth $depth before right bracket")
        token, state = result
        if token.kind == T.LPAREN
            token, state = parsenewick!(token, state, tokens, tree,
                                        lookup, depth + 1, mychildren)
        else
            token, state, nodename = parsenode(token, state, tokens, tree,
                                               lookup, mychildren, true)
        end
    end
    result = iterateskip(tokens, state)
    result === nothing &&
        error("Tree ended at depth $depth before" *
              (depth > 0 ? "right bracket" : "semicolon"))
    token, state = result
    token, state, nodename = parsenode(token, state, tokens, tree,
                                       lookup, children, false)
    for child in keys(mychildren)
        dict = mychildren[child]
        haskey(dict, "length") ?
            addbranch!(tree, nodename, child, dict["length"]) :
            addbranch!(tree, nodename, child)
    end

    if depth == 0
        # Should be at end of tree
        if token.kind == T.SEMICOLON
            # Am at end of tree
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        else
            error("At end of tree, but not ';'")
        end
        tree = resetleaves!(tree)
    end

    return token, state
end

function parsenewick(tokens::Tokenize.Lexers.Lexer,
                     ::Type{TREE}) where TREE <: AbstractBranchTree{String, Int}
    result = iterateskip(tokens)
    if result === nothing
        error("Unexpected end of file at start of newick file")
    end
    token, state = result
    if token.kind == T.LPAREN
        tree = TREE()
        result = parsenewick!(token, state, tokens, tree)
        (result !== nothing) && (result[1].kind != T.ENDMARKER) &&
            @warn "Tree ended but not finished - " *
                  "got $(result[1].kind) $(untokenize(result[1]))"
        return tree
    else
        error("Unexpected $(token.kind) token '$(untokenize(token))' " *
              "at start of newick file")
    end
end

parsenewick(io::IOBuffer, ::Type{TREE}) where TREE <: AbstractBranchTree =
    parsenewick(tokenize(io), TREE)

parsenewick(s::String, ::Type{TREE}) where TREE <: AbstractBranchTree =
    parsenewick(IOBuffer(s), TREE)

function parsenewick(ios::IOStream, ::Type{TREE}) where TREE <: AbstractBranchTree
    buf = IOBuffer()
    print(buf, read(ios, String))
    seek(buf, 0)
    return parsenewick(buf, TREE)
end

parsenewick(inp) = parsenewick(inp, NamedTree)

function parsetaxa(token, state, tokens, taxa)
    if !isDIMENSIONS(token)
        tokenerror(token, "Dimensions")
    end
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    token, state, ntaxstr = tokensgetkey(token, state, tokens)
    if lowercase(ntaxstr) != "ntax"
        error("Unexpected label '$ntaxstr=' not 'ntax='")
    end
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    ntax = parse(Int64, untokenize(token))
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    if token.kind != T.SEMICOLON
        tokenerror(token, ";")
    end
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    if !isTAXLABELS(token)
        tokenerror(token, "Taxlabels")
    end
    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    while token.kind != T.SEMICOLON && token.kind != T.ENDMARKER
        name = untokenize(token)
        if token.kind ∈ [T.STRING, T.CHAR]
            name = name[2:end-1]
        end
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
        taxa[name] = name
        if token.kind == T.LSQUARE
            while token.kind != T.RSQUARE
                result = iterateskip(tokens, state)
                result === nothing && return nothing
                token, state = result
            end
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
        end
    end
    if length(taxa) != ntax
        @warn "Taxa list length ($(length(taxa))) and ntax ($ntax) do not match"
    end

    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    if !checktosemi(isEND, token, state, tokens)
        tokenerror(token, "End;")
    end
    return iterateskip(tokens, state)
end

function parsetrees(token, state, tokens,
                    ::Type{TREE}, taxa) where TREE <: AbstractBranchTree{String, Int}
    notaxa = isempty(taxa)
    if isTRANSLATE(token)
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
        while token.kind != T.SEMICOLON && token.kind != T.ENDMARKER
            short = untokenize(token)
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            proper = untokenize(token)
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            if haskey(taxa, proper)
                delete!(taxa, proper)
                taxa[short] = proper
            elseif notaxa
                @warn "Found a '$short' => '$proper' link without a taxa entry first"
                taxa[short] = proper
            else
                @warn "Missing '$proper' in taxa block, but in 'trees -> translate' block"
            end
            if token.kind == T.COMMA
                result = iterateskip(tokens, state)
                result === nothing && return nothing
                token, state = result
            end
        end
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
    end

    trees = Dict{String, TREE}()
    treedata = Dict{String, Dict{String, Any}}()
    while isTREE(token)
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
        token, state, treename = tokensgetkey(token, state, tokens,
                                              t -> t.kind ∈ [T.LSQUARE, T.EQ])
        @info "Created a tree called '$treename'"
        trees[treename] = TREE()
        addnodes!(trees[treename], collect(values(taxa)))
        if token.kind == T.LSQUARE
            token, state, treedata[treename] = parsedict(token, state, tokens)
        end
        if !isEQ(token)
            tokenerror(token, "=")
        else
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            if token.kind == T.LSQUARE
                token, state, _ = parsedict(token, state, tokens)
            end
        end
        if token.kind != T.LPAREN
            tokenerror(token, "(")
        else
            result = parsenewick!(token, state, tokens, trees[treename], taxa)
            result === nothing && return nothing
            token, state = result
        end
    end
    if !checktosemi(isEND, token, state, tokens)
        tokenerror(token, "End;")
    end

    result = iterateskip(tokens, state)
    result === nothing && return nothing
    token, state = result
    return token, state, trees, treedata
end

function parsenexus(token, state, tokens,
                    ::Type{TREE}) where {NL, BL,
                                         TREE <: AbstractBranchTree{NL, BL}}
    trees = missing
    treedata = missing
    taxa = Dict{NL, NL}()
    while isBEGIN(token)
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
        if checktosemi(isTAXA, token, state, tokens)
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            token, state = parsetaxa(token, state, tokens, taxa)
        elseif checktosemi(isTREES, token, state, tokens)
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            token, state, trees, treedata = parsetrees(token, state, tokens, TREE, taxa)
        else
            @warn "Unexpected nexus block '$(untokenize(token))', skipping..."
            result = iterateskip(tokens, state)
            result === nothing && return nothing
            token, state = result
            while !checktosemi(isEND, token, state, tokens) && token.kind != T.ENDMARKER
                result = iterateskip(tokens, state)
                result === nothing && return nothing
                token, state = result
            end
        end
    end

    if token.kind != T.ENDMARKER
        tokenerror(token, "end of file")
    end
    return TreeSet(trees, treedata)
end

function parsenexus(tokens::Tokenize.Lexers.Lexer,
                    ::Type{TREE}) where TREE <: AbstractBranchTree{String, Int}
    result = iterateskip(tokens)
    result === nothing && return nothing
    token, state = result
    if token.kind == T.COMMENT && lowercase(untokenize(token)) == "#nexus"
        result = iterateskip(tokens, state)
        result === nothing && return nothing
        token, state = result
        return parsenexus(token, state, tokens, TREE)
    else
        error("Unexpected $(token.kind) token '$(untokenize(token))' " *
              "at start of nexus file")
    end
end

parsenexus(io::IOBuffer, ::Type{TREE}) where TREE <: AbstractBranchTree =
    parsenexus(tokenize(io), TREE)

function parsenexus(ios::IOStream, ::Type{TREE}) where TREE <: AbstractBranchTree
    buf = IOBuffer()
    print(buf, read(ios, String))
    seek(buf, 0)
    return parsenexus(buf, TREE)
end

parsenexus(inp) = parsenexus(inp, NamedTree)


text:
import Dates
using AutoHashEquals

struct MonthIncrementPDOM <: MonthIncrementConvention end
adjust(::MonthIncrementPDOM, date::Dates.Date, new_month, new_year, cal_mgr::CalendarManager) = (new_year, new_month, Dates.day(date))
Base.show(io::IO, ::MonthIncrementPDOM) = print(io, "PDOM")

@auto_hash_equals struct MonthIncrementPDOMEOM <: MonthIncrementConvention
    calendars::Union{Vector{String}, Nothing}

    MonthIncrementPDOMEOM() = new(nothing)
    MonthIncrementPDOMEOM(calendars) = new(calendars)
end

function adjust(mic::MonthIncrementPDOMEOM, date::Dates.Date, new_month, new_year, cal_mgr::CalendarManager)
    ldom = Dates.lastdayofmonth(date)
    cal = mic.calendars === nothing ? nothing : calendar(cal_mgr, mic.calendars)
    if cal !== nothing
        ldom = apply(HolidayRoundingPBD(), ldom, cal)
    end

    if ldom == date
        new_ldom = Dates.lastdayofmonth(Dates.Date(new_year, new_month))
        if cal !== nothing
            new_ldom = apply(HolidayRoundingPBD(), new_ldom, cal)
        end

        return Dates.yearmonthday(new_ldom)
    else
        return (new_year, new_month, Dates.day(date))
    end
end

Base.show(io::IO, mic::MonthIncrementPDOMEOM) = mic.calendars === nothing ? print(io, "PDOMEOM") : print(io, "PDOMEOM@$(join(mic.calendars, "|"))")

const MONTH_INCREMENT_MAPPINGS = Dict("PDOM" => MonthIncrementPDOM(), "PDOMEOM" => MonthIncrementPDOMEOM())


text:
@testset "SimpleEdgeIter" begin
    ga = @inferred(SimpleGraph(10, 20; seed=1))
    gb = @inferred(SimpleGraph(10, 20; seed=1))
    dga = @inferred(SimpleDiGraph(10, 20; seed=1))
    dgb = @inferred(SimpleDiGraph(10, 20; seed=1))
    @testset "string representation" begin
        @test sprint(show, edges(ga)) == "SimpleEdgeIter 20"
    end

    @test length(collect(edges(Graph(0, 0)))) == 0

    @testset "collection operations" begin
        @test @inferred(edges(ga)) == edges(gb)
        @test @inferred(edges(ga)) == collect(Edge, edges(gb))
        @test edges(ga) != collect(Edge, Base.Iterators.take(edges(gb), 5))
        @test collect(Edge, edges(gb)) == edges(ga)
        @test Set{Edge}(collect(Edge, edges(gb))) == edges(ga)
        @test @inferred(edges(ga)) == Set{Edge}(collect(Edge, edges(gb)))

        @test @inferred(edges(dga)) == edges(dgb)
        @test @inferred(edges(dga)) == collect(SimpleEdge, edges(dgb))
        @test edges(dga) != collect(Edge, Base.Iterators.take(edges(dgb), 5))
        @test collect(SimpleEdge, edges(dgb)) == edges(dga)
        @test Set{Edge}(collect(SimpleEdge, edges(dgb))) == edges(dga)
        @test @inferred(edges(dga)) == Set{SimpleEdge}(collect(SimpleEdge, edges(dgb)))
    end
    @testset "eltype" begin
        @test @inferred(eltype(edges(ga))) == eltype(typeof(edges(ga))) == edgetype(ga)
        @test eltype(collect(edges(ga))) == edgetype(ga)
        @test eltype(collect(edges(dga))) == edgetype(dga)
        #
        # codecov for eltype(::Type{SimpleEdgeIter{SimpleDiGraph{T}}}) where {T} = SimpleDiGraphEdge{T}
        gd = SimpleDiGraph{UInt8}(10, 20)
        @test @inferred(eltype(edges(gd))) == eltype(typeof(edges(gd))) == edgetype(gd) == SimpleDiGraphEdge{UInt8}
    end

    ga = SimpleGraph(10)
    add_edge!(ga, 3, 2)
    add_edge!(ga, 3, 10)
    add_edge!(ga, 5, 10)
    add_edge!(ga, 10, 3)

    dga = SimpleDiGraph(10)
    add_edge!(dga, 3, 2)
    add_edge!(dga, 3, 10)
    add_edge!(dga, 5, 10)
    add_edge!(dga, 10, 3)

    e1 = Edge(3, 10)
    e2 = (3, 10)
    @testset "membership operations" begin
        @test e1 ∈ edges(ga)
        @test e2 ∈ edges(ga)
        @test (3, 9) ∉ edges(ga)

        for u in 1:12, v in 1:12
            b = has_edge(ga, u, v)
            @test b == @inferred (u, v) ∈ edges(ga)
            @test b == @inferred (u => v) ∈ edges(ga)
            @test b == @inferred Edge(u, v) ∈ edges(ga)

            db = has_edge(dga, u, v)
            @test db == @inferred (u, v) ∈ edges(dga)
            @test db == @inferred (u => v) ∈ edges(dga)
            @test db == @inferred Edge(u, v) ∈ edges(dga)
        end
    end

    @testset "iterator protocol" begin
        eit = edges(ga)
        # @inferred not valid for new interface anymore (return type is a Union)
        @test collect(eit) == [Edge(2, 3), Edge(3, 10), Edge(5, 10)]

        eit = @inferred(edges(dga))
        @test collect(eit) == [
            SimpleEdge(3, 2), SimpleEdge(3, 10),
            SimpleEdge(5, 10), SimpleEdge(10, 3)
        ]
    end

    @testset "graph modifications" begin
        gb = copy(ga)
        add_vertex!(gb)
        @test edges(ga) == edges(gb)
        @test edges(gb) == edges(ga)

        dgb = copy(dga)
        add_vertex!(dgb)
        @test edges(dga) == edges(dgb)
        @test edges(dgb) == edges(dga)
    end
end


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

mutable struct Alias <: SwaggerModel
    name::Any # spec type: Union{ Nothing, String } # spec name: name
    paths::Any # spec type: Union{ Nothing, Vector{AliasPath} } # spec name: paths
    type::Any # spec type: Union{ Nothing, String } # spec name: type
    defaultPath::Any # spec type: Union{ Nothing, String } # spec name: defaultPath
    defaultPattern::Any # spec type: Union{ Nothing, AliasPattern } # spec name: defaultPattern

    function Alias(;name=nothing, paths=nothing, type=nothing, defaultPath=nothing, defaultPattern=nothing)
        o = new()
        validate_property(Alias, Symbol("name"), name)
        setfield!(o, Symbol("name"), name)
        validate_property(Alias, Symbol("paths"), paths)
        setfield!(o, Symbol("paths"), paths)
        validate_property(Alias, Symbol("type"), type)
        setfield!(o, Symbol("type"), type)
        validate_property(Alias, Symbol("defaultPath"), defaultPath)
        setfield!(o, Symbol("defaultPath"), defaultPath)
        validate_property(Alias, Symbol("defaultPattern"), defaultPattern)
        setfield!(o, Symbol("defaultPattern"), defaultPattern)
        o
    end
end # type Alias

const _property_map_Alias = Dict{Symbol,Symbol}(Symbol("name")=>Symbol("name"), Symbol("paths")=>Symbol("paths"), Symbol("type")=>Symbol("type"), Symbol("defaultPath")=>Symbol("defaultPath"), Symbol("defaultPattern")=>Symbol("defaultPattern"))
const _property_types_Alias = Dict{Symbol,String}(Symbol("name")=>"String", Symbol("paths")=>"Vector{AliasPath}", Symbol("type")=>"String", Symbol("defaultPath")=>"String", Symbol("defaultPattern")=>"AliasPattern")
Base.propertynames(::Type{ Alias }) = collect(keys(_property_map_Alias))
Swagger.property_type(::Type{ Alias }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_Alias[name]))}
Swagger.field_name(::Type{ Alias }, property_name::Symbol) =  _property_map_Alias[property_name]

const _allowed_Alias_type = ["NotSpecified", "PlainText", "Mask"]

function check_required(o::Alias)
    true
end

function validate_property(::Type{ Alias }, name::Symbol, val)
    if name === Symbol("type")
        Swagger.validate_param(name, "Alias", :enum, val, _allowed_Alias_type)
    end
end


text:
"""
    GapRange{T,F,L}

Represents a range that is broken up by gaps making it noncontinuous. This allows
more compact storage of numbers where the majority are known to be continuous.

## Examples
```jldoctest
julia> using StaticRanges

julia> findall(and(>(4), <(10)), 1:10)
5-element Vector{Int64}:
 5
 6
 7
 8
 9

julia> find_all(or(<(4), >(6)), 1:10)
7-element GapRange{Int64, UnitRange{Int64}, UnitRange{Int64}}:
  1
  2
  3
  7
  8
  9
 10
```
"""
struct GapRange{T,F,L} <: AbstractVector{T}
    first_range::F
    last_range::L

   function GapRange{T,F,L}(fr::F, lr::L) where {T,F,L}
       if (eltype(fr) <: T) & (eltype(lr) <: T)
           if F <: AbstractRange || F <: GapRange || F <: T
               if L <: AbstractRange || L <: GapRange || L <: T
                   return new{T,F,L}(fr, lr)
               else
                   error("A GapRange can only be composed of ranges or othe GapRanges, got $L.")
               end
           else
               error("A GapRange can only be composed of ranges or othe GapRanges, got $F.")
           end
       else
           error("element type of first and last range must be the same, got $(eltype(fr)) and $(eltype(lr)).")
       end
    end
end

GapRange(f::T, l::T) where {T} = GapRange{T,T,T}(f, l)
function GapRange(f::T, l::AbstractVector{T}) where {T<:Real}
    if step(l) > 0
        if f < first(l)
            return GapRange{T,T,typeof(l)}(f, l)
        elseif f > last(l)
            return GapRange{T,typeof(l),T}(l, f)
        else
            error("The two ranges composing a GapRange can't overlap.")
        end
    else
        if f > first(l)
            return GapRange{T,T,typeof(l)}(f, l)
        elseif f < last(l)
            return GapRange{T,typeof(l),T}(l, f)
        else
            error("The two ranges composing a GapRange can't overlap.")
        end
    end
end

function GapRange(f::AbstractVector{T}, l::T) where {T<:Real}
    if step(f) > 0
        if last(f) < l
            return GapRange{T,typeof(f),T}(f, l)
        elseif l < first(f)
            return GapRange{T,T,typeof(f)}(l, f)
        else
            error("The two ranges composing a GapRange can't overlap.")
        end
    else
        if l > first(f)
            return GapRange{T,typeof(f),T}(f, l)
        elseif l < last(f)
            return GapRange{T,T,typeof(f)}(l, f)
        else
            error("The two ranges composing a GapRange can't overlap.")
        end
    end
end

function GapRange(f::AbstractVector{T}, l::AbstractVector{T}) where {T}
    if step(f) > 0
        if step(l) > 0
            if last(f) < first(l)
                return GapRange{T,typeof(f),typeof(l)}(f, l)
            elseif last(l) < first(f)
                return GapRange{T,typeof(l),typeof(f)}(l, f)
            else
                error("The two ranges composing a GapRange can't overlap.")
            end
        else
            error("Both arguments to GapRange must have the same sorting, got forward and reverse ordered ranges.")
        end
    else
        if step(l) > 0
            error("Both arguments to GapRange must have the same sorting, got reverse and forward ordered ranges.")
        else
            if last(f) > first(l)
                return GapRange{T,typeof(f),typeof(l)}(f, l)
            elseif last(l) > first(f)
                return GapRange{T,typeof(l),typeof(f)}(l, f)
            else
                error("The two ranges composing a GapRange can't overlap.")
            end
        end
    end
end

first_range(gr::GapRange) = getfield(gr, :first_range)
last_range(gr::GapRange) = getfield(gr, :last_range)

first_length(gr::GapRange) = length(first_range(gr))
first_length(gr::GapRange{T,T}) where {T} = 1

last_length(gr::GapRange) = length(last_range(gr))
last_length(gr::GapRange{T,F,T}) where {T,F} = 1

Base.length(gr::GapRange) = length(first_range(gr)) + length(last_range(gr))

Base.first(gr::GapRange) = first(first_range(gr))

Base.last(gr::GapRange) = last(last_range(gr))
Base.length(gr::GapRange{T,T,T}) where {T} = 2

# bypasses order checking
_unsafe_gaprange(f, l) = GapRange{eltype(f),typeof(f),typeof(l)}(f, l)

#Base.:(==)(x::GapRange, y::GapRange) = _isequal(x, y)
Base.:(==)(x::AbstractArray, y::GapRange) = _isequal(x, y)
Base.:(==)(x::GapRange, y::AbstractArray) = _isequal(x, y)
Base.:(==)(x::GapRange, y::GapRange) = _isequal(x, y)

function _isequal(x, y)
    out = true
    for (x_i,y_i) in zip(x,y)
        if x_i != y_i
            out = false
            break
        end
    end
    return out
end

Base.size(gr::GapRange) = (length(gr),)

Base.firstindex(gr::GapRange) = firstindex(first_range(gr))

first_lastindex(gr) = lastindex(first_range(gr))

Base.lastindex(gr::GapRange) = length(gr)

last_firstindex(gr::GapRange) = lastindex(first_range(gr)) + 1

function Base.AbstractArray{T}(gr::GapRange) where {T}
    fr = AbstractRange{T}(gr.first_range)
    lr = AbstractRange{T}(gr.last_range)
    return GapRange{T,typeof(fr),typeof(lr)}(fr, lr)
end
# GapRange
unsafe_index_first(gr::GapRange, i) = @inbounds(getindex(first_range(gr), i))
function unsafe_index_last(gr::GapRange, i)
    return @inbounds(getindex(last_range(gr), i .- first_length(gr)))
end

function Base.getindex(gr::GapRange, i::Integer)
    @boundscheck checkbounds(gr, i)
    return i <= first_length(gr) ? unsafe_index_first(gr, i) : unsafe_index_last(gr, i)
end

@propagate_inbounds function Base.getindex(r::AbstractRange, gr::GapRange)
    fr = r[gr.first_range]
    lr = r[gr.last_range]
    return GapRange{eltype(r),typeof(fr),typeof(lr)}(fr, lr)
end

@propagate_inbounds function Base.getindex(gr::GapRange, v::AbstractRange)
    @boundscheck checkbounds(gr, v)
    fr = first_range(gr)
    lr = last_range(gr)
    if checkindexhi(fr, minimum(v))
        if checkindexlo(lr, maximum(v))
            return unsafe_spanning_getindex(gr, v)
        else
            # largest value of `v` is not found in last segment so only index first segment
            return unsafe_index_first(gr, v)
        end
    else
        # smallest value of `v` is not found in first segment so only index last segment
        return unsafe_index_last(gr, v)
    end
end

function unsafe_spanning_getindex(gr, v)
    ltfli = find_all(<=(first_lastindex(gr)), v)
    gtlfi = find_all(>=(last_firstindex(gr)), v)
    if step(v) > 0
        return _unsafe_gaprange(
            unsafe_index_first(gr, @inbounds(v[ltfli])),
            unsafe_index_last(gr, @inbounds(v[gtlfi]))
           )
    else
        return _unsafe_gaprange(
            unsafe_index_last(gr, @inbounds(v[gtlfi])),
            unsafe_index_first(gr, @inbounds(v[ltfli]))
        )
    end
end

Base.checkbounds(::Type{Bool}, gr::GapRange, i::Integer) = checkindex(Bool, gr, i)

function Base.checkindex(::Type{Bool}, gr::GapRange, i::Integer)
    return checkindexlo(gr, i) & checkindexhi(gr, i)
end