text:
#=
This file is auto-generated. Do not edit.
=#
"""
    mutable struct ThermalStandard <: ThermalGen
        name::String
        available::Bool
        status::Bool
        bus::Bus
        activepower::Float64
        reactivepower::Float64
        rating::Float64
        primemover::PrimeMovers.PrimeMover
        fuel::ThermalFuels.ThermalFuel
        activepowerlimits::Min_Max
        reactivepowerlimits::Union{Nothing, Min_Max}
        ramplimits::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}
        timelimits::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}
        op_cost::ThreePartCost
        basepower::Float64
        services::Vector{Service}
        time_at_status::Float64
        dynamic_injector::Union{Nothing, DynamicInjection}
        ext::Dict{String, Any}
        forecasts::InfrastructureSystems.Forecasts
        internal::InfrastructureSystemsInternal
    end

Data Structure for thermal generation technologies.

# Arguments
- `name::String`
- `available::Bool`
- `status::Bool`
- `bus::Bus`
- `activepower::Float64`, validation range: activepowerlimits, action if invalid: warn
- `reactivepower::Float64`, validation range: reactivepowerlimits, action if invalid: warn
- `rating::Float64`: Thermal limited MVA Power Output of the unit. <= Capacity, validation range: (0, nothing), action if invalid: error
- `primemover::PrimeMovers.PrimeMover`: PrimeMover Technology according to EIA 923
- `fuel::ThermalFuels.ThermalFuel`: PrimeMover Fuel according to EIA 923
- `activepowerlimits::Min_Max`
- `reactivepowerlimits::Union{Nothing, Min_Max}`
- `ramplimits::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}`, validation range: (0, nothing), action if invalid: error
- `timelimits::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}`: Minimum up and Minimum down time limits in hours, validation range: (0, nothing), action if invalid: error
- `op_cost::ThreePartCost`
- `basepower::Float64`: Base power of the unit in system base per unit, validation range: (0, nothing), action if invalid: warn
- `services::Vector{Service}`: Services that this device contributes to
- `time_at_status::Float64`
- `dynamic_injector::Union{Nothing, DynamicInjection}`: corresponding dynamic injection device
- `ext::Dict{String, Any}`
- `forecasts::InfrastructureSystems.Forecasts`: internal forecast storage
- `internal::InfrastructureSystemsInternal`: power system internal reference, do not modify
"""
mutable struct ThermalStandard <: ThermalGen
    name::String
    available::Bool
    status::Bool
    bus::Bus
    activepower::Float64
    reactivepower::Float64
    "Thermal limited MVA Power Output of the unit. <= Capacity"
    rating::Float64
    "PrimeMover Technology according to EIA 923"
    primemover::PrimeMovers.PrimeMover
    "PrimeMover Fuel according to EIA 923"
    fuel::ThermalFuels.ThermalFuel
    activepowerlimits::Min_Max
    reactivepowerlimits::Union{Nothing, Min_Max}
    ramplimits::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}
    "Minimum up and Minimum down time limits in hours"
    timelimits::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}
    op_cost::ThreePartCost
    "Base power of the unit in system base per unit"
    basepower::Float64
    "Services that this device contributes to"
    services::Vector{Service}
    time_at_status::Float64
    "corresponding dynamic injection device"
    dynamic_injector::Union{Nothing, DynamicInjection}
    ext::Dict{String, Any}
    "internal forecast storage"
    forecasts::InfrastructureSystems.Forecasts
    "power system internal reference, do not modify"
    internal::InfrastructureSystemsInternal
end

function ThermalStandard(name, available, status, bus, activepower, reactivepower, rating, primemover, fuel, activepowerlimits, reactivepowerlimits, ramplimits, timelimits, op_cost, basepower, services=Device[], time_at_status=INFINITE_TIME, dynamic_injector=nothing, ext=Dict{String, Any}(), forecasts=InfrastructureSystems.Forecasts(), )
    ThermalStandard(name, available, status, bus, activepower, reactivepower, rating, primemover, fuel, activepowerlimits, reactivepowerlimits, ramplimits, timelimits, op_cost, basepower, services, time_at_status, dynamic_injector, ext, forecasts, InfrastructureSystemsInternal(), )
end

function ThermalStandard(; name, available, status, bus, activepower, reactivepower, rating, primemover, fuel, activepowerlimits, reactivepowerlimits, ramplimits, timelimits, op_cost, basepower, services=Device[], time_at_status=INFINITE_TIME, dynamic_injector=nothing, ext=Dict{String, Any}(), forecasts=InfrastructureSystems.Forecasts(), )
    ThermalStandard(name, available, status, bus, activepower, reactivepower, rating, primemover, fuel, activepowerlimits, reactivepowerlimits, ramplimits, timelimits, op_cost, basepower, services, time_at_status, dynamic_injector, ext, forecasts, )
end

# Constructor for demo purposes; non-functional.
function ThermalStandard(::Nothing)
    ThermalStandard(;
        name="init",
        available=false,
        status=false,
        bus=Bus(nothing),
        activepower=0.0,
        reactivepower=0.0,
        rating=0.0,
        primemover=PrimeMovers.OT,
        fuel=ThermalFuels.OTHER,
        activepowerlimits=(min=0.0, max=0.0),
        reactivepowerlimits=nothing,
        ramplimits=nothing,
        timelimits=nothing,
        op_cost=ThreePartCost(nothing),
        basepower=0.0,
        services=Device[],
        time_at_status=INFINITE_TIME,
        dynamic_injector=nothing,
        ext=Dict{String, Any}(),
        forecasts=InfrastructureSystems.Forecasts(),
    )
end

InfrastructureSystems.get_name(value::ThermalStandard) = value.name
"""Get ThermalStandard available."""
get_available(value::ThermalStandard) = value.available
"""Get ThermalStandard status."""
get_status(value::ThermalStandard) = value.status
"""Get ThermalStandard bus."""
get_bus(value::ThermalStandard) = value.bus
"""Get ThermalStandard activepower."""
get_activepower(value::ThermalStandard) = value.activepower
"""Get ThermalStandard reactivepower."""
get_reactivepower(value::ThermalStandard) = value.reactivepower
"""Get ThermalStandard rating."""
get_rating(value::ThermalStandard) = value.rating
"""Get ThermalStandard primemover."""
get_primemover(value::ThermalStandard) = value.primemover
"""Get ThermalStandard fuel."""
get_fuel(value::ThermalStandard) = value.fuel
"""Get ThermalStandard activepowerlimits."""
get_activepowerlimits(value::ThermalStandard) = value.activepowerlimits
"""Get ThermalStandard reactivepowerlimits."""
get_reactivepowerlimits(value::ThermalStandard) = value.reactivepowerlimits
"""Get ThermalStandard ramplimits."""
get_ramplimits(value::ThermalStandard) = value.ramplimits
"""Get ThermalStandard timelimits."""
get_timelimits(value::ThermalStandard) = value.timelimits
"""Get ThermalStandard op_cost."""
get_op_cost(value::ThermalStandard) = value.op_cost
"""Get ThermalStandard basepower."""
get_basepower(value::ThermalStandard) = value.basepower
"""Get ThermalStandard services."""
get_services(value::ThermalStandard) = value.services
"""Get ThermalStandard time_at_status."""
get_time_at_status(value::ThermalStandard) = value.time_at_status
"""Get ThermalStandard dynamic_injector."""
get_dynamic_injector(value::ThermalStandard) = value.dynamic_injector
"""Get ThermalStandard ext."""
get_ext(value::ThermalStandard) = value.ext

InfrastructureSystems.get_forecasts(value::ThermalStandard) = value.forecasts
"""Get ThermalStandard internal."""
get_internal(value::ThermalStandard) = value.internal

InfrastructureSystems.set_name!(value::ThermalStandard, val::String) = value.name = val
"""Set ThermalStandard available."""
set_available!(value::ThermalStandard, val::Bool) = value.available = val
"""Set ThermalStandard status."""
set_status!(value::ThermalStandard, val::Bool) = value.status = val
"""Set ThermalStandard bus."""
set_bus!(value::ThermalStandard, val::Bus) = value.bus = val
"""Set ThermalStandard activepower."""
set_activepower!(value::ThermalStandard, val::Float64) = value.activepower = val
"""Set ThermalStandard reactivepower."""
set_reactivepower!(value::ThermalStandard, val::Float64) = value.reactivepower = val
"""Set ThermalStandard rating."""
set_rating!(value::ThermalStandard, val::Float64) = value.rating = val
"""Set ThermalStandard primemover."""
set_primemover!(value::ThermalStandard, val::PrimeMovers.PrimeMover) = value.primemover = val
"""Set ThermalStandard fuel."""
set_fuel!(value::ThermalStandard, val::ThermalFuels.ThermalFuel) = value.fuel = val
"""Set ThermalStandard activepowerlimits."""
set_activepowerlimits!(value::ThermalStandard, val::Min_Max) = value.activepowerlimits = val
"""Set ThermalStandard reactivepowerlimits."""
set_reactivepowerlimits!(value::ThermalStandard, val::Union{Nothing, Min_Max}) = value.reactivepowerlimits = val
"""Set ThermalStandard ramplimits."""
set_ramplimits!(value::ThermalStandard, val::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}) = value.ramplimits = val
"""Set ThermalStandard timelimits."""
set_timelimits!(value::ThermalStandard, val::Union{Nothing, NamedTuple{(:up, :down), Tuple{Float64, Float64}}}) = value.timelimits = val
"""Set ThermalStandard op_cost."""
set_op_cost!(value::ThermalStandard, val::ThreePartCost) = value.op_cost = val
"""Set ThermalStandard basepower."""
set_basepower!(value::ThermalStandard, val::Float64) = value.basepower = val
"""Set ThermalStandard services."""
set_services!(value::ThermalStandard, val::Vector{Service}) = value.services = val
"""Set ThermalStandard time_at_status."""
set_time_at_status!(value::ThermalStandard, val::Float64) = value.time_at_status = val
"""Set ThermalStandard ext."""
set_ext!(value::ThermalStandard, val::Dict{String, Any}) = value.ext = val

InfrastructureSystems.set_forecasts!(value::ThermalStandard, val::InfrastructureSystems.Forecasts) = value.forecasts = val
"""Set ThermalStandard internal."""
set_internal!(value::ThermalStandard, val::InfrastructureSystemsInternal) = value.internal = val


text:
## Copied from Distributions.jl
## macro for argument checking
macro check_args(D, cond)
    quote
        if !($(esc(cond)))
            throw(ArgumentError(string(
                $(string(D)), ": the condition ", $(string(cond)), " is not satisfied.")))
        end
    end
end

# rowlogsumexps
rowlogsumexp(x) = logsumexp.(x[row,:] for row in 1:size(x)[1])

# replace nan by a number
function nan2num(x, g)
    for i in eachindex(x)
        @inbounds x[i] = ifelse(isnan(x[i]), g, x[i])
    end
end

# replace inf by a number
function inf2num(x, g)
    for i in eachindex(x)
        @inbounds x[i] = ifelse(isinf(x[i]), g, x[i])
    end
end

# matching functions for fast integration
function unique_bounds(l, u)
    return unique(hcat(vec(l), vec(u)), dims = 1)
end

matchrow(a, B) = findfirst( i -> all(j->a[j] == B[i,j], 1:size(B,2)), 1:size(B,1) )

function match_unique_bounds(all_bounds, unique_bounds)
    return [matchrow(all_bounds[i,:], unique_bounds) for i in 1:size(all_bounds)[1]]
end

# yl = vec([1 2 3 4 5 6 1 2 3 4 5 6])
# yu = vec([7 8 9 10 11 12 7 9 8 12 11 10])

# ab = hcat(vec(yl), vec(yu))
# ub = unique_bounds(yl, yu)
# match_unique_bounds(ab, ub)

# unique_bounds(yl, yu)
# match_unique_bounds(yl, yu)

# recursively solve for quantiles of discrete distributions
function _solve_discrete_quantile(d::DiscreteUnivariateDistribution, q::Real)
    l, u = 1, 2*1
    while cdf.(d, u) < q
        l = u+1
        u = 2*l
    end
    while u-l > 1
        tmp = ceil((u+l)/2)
        if cdf.(d, tmp) >= q
            l, u = l, tmp
        else
            l, u = tmp, u
        end
    end
    if cdf.(d, l) >= q
        return l
    else
        return u
    end
end

# Convert exact Y to full Y
function _exact_to_full(Y)
    result = fill(NaN, size(Y)[1], size(Y)[2]*4)
    for j in 1:size(Y)[2]
        result[:,4*(j-1)+1] .= 0.0
        result[:,4*(j-1)+2] .= Y[:,j]
        result[:,4*(j-1)+3] .= Y[:,j]
        result[:,4*(j-1)+4] .= Inf
    end
    return result
end

ext: jl

max_stars_repo_name: sparktseung/JuliaLRMoE

max_issues_repo_name: sparktseung/JuliaLRMoE

max_forks_repo_name: sparktseung/JuliaLRMoE


text:
# Currently Julia gives false for isa([1,2,3], Vector{Real}), so doing manually.
typealias RealVector Union(Vector{Int}, Vector{Float64})
typealias RealMatrix Union(Matrix{Int}, Matrix{Float64})
typealias PlotInputs Union(Vector{Function}, (RealVector, RealMatrix))

SUPER = utf16("\u2070\u00b9\u00b2\u00b3\u2074\u2075\u2076\u2077\u2078\u2079")

# Find magnitude of difference between 2 nums, as digits before/after decimal.
function magnitude(num1::Real, num2::Real)
    -iround(log10(abs(num2 - num1)))
end

# See if this float happens to match common uses of constants like n*pi.
function findsymbolic(num::Real)
    num == 0 && return ""

    # Format strings for minus sign, superscript, multiples, and exponents.
    dash(x, super=false) = x >= 0 ? "" : super ? "⁻" : "-"
    sup(x) = dash(x, true) * join([SUPER[d + 1] for d in reverse(digits(iround(abs(x))))])
    multiple(x) = iround(x) == 0 ? "0" : iround(x) == 1 ? "" : "$(iround(x))"
    topower(n, x) = iround(x) == 0 ? "1" : iround(x) == 1 ? n : "$n$(sup(x))"

    # Split number between the absolute value and the minus sign, if any
    anum, sgn = abs(num), dash(num)

    isinteger(num/π)        && return "$(multiple(num/π))π"
    isinteger(num/e)        && return "$(multiple(num/e))e"
    isinteger(log(anum))    && return "$(sgn)$(topower("e", log(anum)))"
    isinteger(log10(anum))  && return "$(sgn)$(topower("10", log10(anum)))"

    return ""
end

# Julia somehow doesn't support the crucial "g" printf type.
# Don't feel like dealing with complex numbers yet.
function format(num::Real, width::Int, precision::Int=typemax(Int))
    str = findsymbolic(num)  # Check for a prettier format for num.
    if length(str) > 0
        str = lpad(str, width)  # Pretty format found, just fit in the space.
    else
        # Attempt multiple rounding levels to fit in available characters.
        precision < width && (num = round(num, precision + 1))
        isint = isinteger(num) || isinteger(round(num, width - 5))
        fmt = isint ? "%$(width)d" : "%$(width).$(width - 3)f"
        str = eval(:(@sprintf $(fmt) $(num)))
    end

    # Whatever the output was, number or symbol, truncate if too large.
    if length(str) > width
        str[end] == '.' && return " $(str[1:end - 1])"
        1 < search(str, '.') <= width && return str[1:width]
        width >= 4 && return str[1:width - 1] * "…"
    end
    str
end

# Attempt to produce a meaningful graph label automatically.
function funclabel(f::Function, names=["x"])
    if isa(f.env, MethodTable) && isdefined(f.env, :name)
        return "$(f.env.name)($(join(names, ", ")))"
    end

    # Julia uses different types for lambdas, named funcs, and inline funcs.
    fsrc = isdefined(f, :code) ? f.code : code_lowered(f, (Number,))[1]
    if isdefined(fsrc, :ast)
        if isa(fsrc.ast, Array)
            fsrc = ccall(:jl_uncompress_ast, Any, (Any,Any), fsrc, fsrc.ast)
        else
            fsrc = fsrc.ast
        end
    end
    codes = fsrc.args[end].args
    if length(codes) == 1 || (length(codes) == 2 && codes[1].head == :line)
        # Extract the return expression
        return string(codes[end].args[end])
    end

    return "(unlabeled)"
end

# Fancy terminal plotting for Julia using Braille characters.
function plot(data::PlotInputs, start::Real=-10, stop::Real=10;
                 border::Bool=true, labels::Bool=true, title::Bool=true,
                 cols::Int=60, rows::Int=16, margin::Int=9,
                 invert::Bool=false, gridlines::Bool=false,
                 scalefunc::Function=identity)

    # The unicode braille chars are conveniently structured to support bitwise
    # manipulation, so we can just OR specific bits to set that dot to filled.
    grid = fill(char(gridlines ? 0x2812 : 0x2800), cols, rows)
    left, right = sides = ((0, 1, 2, 6), (3, 4, 5, 7))
    function showdot(x, y)  # Assumes x & y are already scaled to the grid.
        invy = (rows - y)*0.9999
        col, col2 = ifloor(x), ifloor(x*2)
        row, row4 = ifloor(invy), ifloor(invy*4)
        # This does the bitwise OR to fill in a single dot out of the 8.
        grid[col + 1, row + 1] |= 1 << sides[1 + (col2 & 1)][1 + (row4 & 3)]
    end

    # If input is a function, sample it at each row & col to fill xvals & yvals.
    continuous = isa(data, Vector{Function})
    if continuous
        xframes, yframes = cols, rows
        xspread = stop - start
        xstep, xscale = (stop - start)/cols, xframes/xspread
        xvals = collect(start:xstep:stop)
        # Assumes f(x) is defined for all x in the given range.
        yvals = Float64[f(x) for x in xvals, f in data]
    else
        # Unfortunately much of this is redundant with the above code, but a few
        # things have to be done in a different order, making cleanup tricky.
        xframes, yframes = cols - 1, rows - 1
        xvals, yvals = data
        @assert length(yvals) >= length(xvals) "Different number of x/y points."
        start, stop = minimum(xvals), maximum(xvals)
        xspread = stop - start
        xstep, xscale = xspread/xframes, xframes/xspread
        isa(yvals, RealVector) && (yvals = reshape(yvals, length(yvals), 1))
    end

    # Rescaling and setting boundaries must happen after the sampling above.
    xscaled = xscale*(xvals .- start)
    ystart, ystop = minimum(yvals), maximum(yvals)
    yspread = ystop - ystart
    ystep, yscale = yspread/yframes, yframes/yspread

    # Finally, iterate through the grid, scaling & interpolating, to set dots.
    for row in 1:size(yvals, 2)
        rowvals = yvals[:, row]
        yscaled = yscale*(rowvals .- ystart)
        if scalefunc != identity
            yrescaled = [scalefunc(y) for y in rowvals]
            yrestart, yrestop = minimum(yrescaled), maximum(yrescaled)
            yrespread = yrestop - yrestart
            yrescale = rows/yrespread
            yscaled = yrescale*(yrescaled .- yrestart)
        end

        # Interpolate between steps to smooth plot & avoid frequent f(x) calls.
        for (col, x) in enumerate(xscaled[1:(continuous ? end - 1 : end)])
            if continuous
                yleftedge, yrightedge = yscaled[col:col + 1]
                ydelta = yrightedge - yleftedge
                showdot(x + eps(x), yleftedge + ydelta*0.25)
                showdot(x + 0.5 + eps(x), yrightedge - ydelta*0.25)
            else
                y = yscaled[col]
                showdot(x, y + 1)
            end
        end
    end

    # Exploit the bitwise nature of the braille chars to invert.
    invert && (grid = map(c -> char(c $ 0xFF), grid))

    # Build the plot decorations based on configuration params.
    lines = String[]
    padding = labels ? repeat(" ", margin) : ""
    prefix, suffix = border ? (padding * "⡇", "⢸") : (padding * "", "")
    border && push!(lines, padding * "⡤" * repeat("⠤", cols) * "⢤")
    append!(lines, [prefix * join(grid[:, row], "") * suffix for row in 1:rows])
    border && push!(lines, padding * "⠓" * repeat("⠒", cols) * "⠚")

    # Try pretty hard to fit rounded axis labels into available chars.
    if labels
        yprecision = magnitude(ystart, ystop)
        ystartlabel = format(ystart, margin - 1, yprecision)
        ystoplabel = format(ystop, margin - 1, yprecision)
        lines[1] = "$ystoplabel $(lines[1][margin + 1:end])"
        lines[end] = "$ystartlabel $(lines[end][margin + 1:end])"

        xprecision = magnitude(start, stop)
        xstartlabel = strip(format(start, margin - 1, xprecision))
        xstoplabel = strip(format(stop, margin - 1, xprecision))
        xstartlabel[1] != '-' && (xstartlabel = " $xstartlabel")
        lblrow = repeat(" ", margin - 1) * xstartlabel
        lblrow *= lpad(xstoplabel, length(prefix) + cols - length(lblrow) + 1)
        push!(lines, lblrow)
    end

    # The title is mostly useful when plotting repeatedly in a single session.
    if title
        if isa(data, Vector{Function})
            nametag = join([funclabel(f) for f in data], ", ")
        else
            nametag = "scatter plot"
        end
        println("$padding $nametag")
    end
    println(join(lines, '\n'))
end

# Overloads for a variety of different parameter specifications.
function plot(data::PlotInputs, rng::Range, etc...; args...)
    stop = isdefined(rng, :stop) ? rng.stop : rng.len
    plot(data, rng.start, stop, etc...; args...)
end
function plot(f::Function, etc...; args...)
    plot([f], etc...; args...)
end
function plot(xvals::RealVector, yvals::RealMatrix, etc...; args...)
    plot((xvals, yvals), etc...; args...)
end
function plot(xvals::RealVector, yvals::RealVector, etc...; args...)
    plot((xvals, reshape(yvals, length(yvals), 1)), etc...; args...)
end
function plot(data::RealVector, etc...; args...)
    plot(collect(1:length(data)), data, etc...; args...)
end
function plot(data::RealMatrix, etc...; args...)
    plot((collect(1:size(data, 1)), data), etc...; args...)
end
function plot(rng::Range, etc...; args...)
    plot(collect(rng))
end
# Shorthand for a logarithm plot scale.
function logplot(etc...; args...)
    plot(etc...; scalefunc=log10, args...)
end


text:
Base.show(io::IO, MP::JumpProcess) = println(io,
"Jump Process
-----------------------
  States: $(print_wo_type(MP.x))
  Propensities: $(print_wo_type(MP.a))
  Jumps: ["*prod(print_wo_type(MP.h[i])*(i < length(MP.h) ? ", " : "" ) for i in 1:length(MP.h))*"]
  State Space: $(MP.X)")

Base.show(io::IO, RP::ReactionProcess) = println(io,
"Reaction Process is analogous to following $(RP.JumpProcess)")

Base.show(io::IO, MP::DiffusionProcess) = println(io,
"Diffusion Process
-----------------------
  States: $(print_wo_type(MP.x))
  Drift: $(print_wo_type(MP.f))
  Diffusion: $(print_wo_type(MP.σ))
  State space: $(MP.X)")

Base.show(io::IO, LP::LangevinProcess) = println(io,
"Chemical Langevin Equation is analogous to following $(LP.DiffusionProcess)")

Base.show(io::IO, MP::JumpDiffusionProcess) = println(io,
"Jump-Diffusion Process
-----------------------
  States: $(print_wo_type(MP.x))
  Propensities: $(print_wo_type(MP.a))
  Jumps: ["*prod(print_wo_type(MP.h[i])*(i < length(MP.h) ? ", " : "" ) for i in 1:length(MP.h))*"]
  Drift: $(print_wo_type(MP.f))
  Diffusion: $(print_wo_type(MP.σ))
  State Space: $(MP.X)")

Base.show(io::IO, CP::ControlProcess) = println(io,
"Control Process
-----------------------
$(CP.MP)-----------------------
Admissible Controls: $(CP.U)
Control Horizon: [0, $(CP.T)]
Objective Function: $(CP.Objective)")

Base.show(io::IO, obj::LagrangeMayer) = println(io,
"𝔼[∫ $(obj.l) dt + $(obj.m)]")

Base.show(io::IO, bound::Bound) = println(io,
"$(bound.value) $(interpret_status(termination_status(bound.model), primal_status(bound.model)))")

Base.show(io::IO, S::Singleton) = println(io,"{ $(S.x) }")

function print_wo_type(A::AbstractArray)
  str = string(A)
  idx = findfirst('[', string(A))
  return str[idx:end]
end

function interpret_status(opt_status, feas_status)
  if feas_status == MOI.FEASIBLE_POINT
      status = "valid"
  elseif feas_status == MOI.NEARLY_FEASIBLE_POINT
      status = "likely valid"
  elseif feas_status == MOI.INFEASIBLE_POINT
      status = "invalid"
  else
      status = "unknown"
  end

  if opt_status == MOI.OPTIMAL
      status *= " (optimal)"
  elseif opt_status == MOI.ALMOST_OPTIMAL
      status *= " (near optimal)"
  elseif opt_status == MOI.INFEASIBLE
      status *= " (infeasible)"
  elseif opt_status == MOI.SLOW_PROGRESS
      status *= " (potentially suboptimal)"
  elseif opt_status == MOI.MEMORY_LIMIT
      status *= " (memory limit exceeded)"
  elseif opt_status == MOI.OBJECTIVE_LIMIT
      status *= " (objective limit exceeded)"
  else
      status *= " (unkown)"
  end
  return status
end


text:
mutable struct ZeroMean{T<:Real} <: MeanPrior{T}
end

"""
ZeroMean
```julia
ZeroMean()
```
Construct a mean prior set to 0 and cannot be changed.
"""
function ZeroMean()
    ZeroMean{Float64}()
end

function update!(μ::ZeroMean{T},grad::AbstractVector{T}) where {T<:Real}
end

Base.:+(x::Real,y::ZeroMean{<:Real}) = x
Base.:+(x::AbstractVector{<:Real},y::ZeroMean{<:Real}) = x
Base.:+(x::ZeroMean{<:Real},y::Real) = y
Base.:+(x::ZeroMean{<:Real},y::AbstractVector{<:Real}) = y
Base.:+(x::ZeroMean{<:Real},y::ConstantMean{<:Real}) = ConstantMean(y.C)
Base.:-(x::Real,y::ZeroMean{<:Real}) = x
Base.:-(x::AbstractVector{<:Real},y::ZeroMean) = x
Base.:-(x::ZeroMean{<:Real},y::Real) = -y
Base.:-(x::ZeroMean{<:Real},y::AbstractVector{<:Real}) = -y
Base.:-(x::ZeroMean{<:Real},y::ConstantMean{<:Real}) = ConstantMean(-y.C)
Base.:*(A::AbstractMatrix{<:Real},y::ZeroMean{T}) where {T<:Real} = zeros(T,size(A,2))
Base.:*(y::ZeroMean{T},A::AbstractMatrix{<:Real}) where {T<:Real} = zeros(T,1,size(A,1))
Base.:convert(::T1,x::ZeroMean{T2}) where {T1<:Real,T2<:Real} = T1(x.C)


text:
import Pkg
build_artifact = joinpath(@__DIR__, "artifact")
isfile(build_artifact) && rm(build_artifact)
@assert Pkg.installed()["JSON"] == v"0.19.0"
touch(build_artifact)


text: entangler_google53(nbits::Int, i::Int, j::Int) = put(nbits, (i,j)=>FSimGate(π/2, π/6))


text:
Base.minimum(solution::DESolution) = minimum(map(minimum, solution.u))
Base.maximum(solution::DESolution) = maximum(map(maximum, solution.u))

using DiffEqBase: AbstractTimeseriesSolution

struct MissingSolution <: AbstractTimeseriesSolution{Missing,Missing,Missing} end
function Base.show(io::IO, A::MissingSolution)
  print(io,"MissingSolution")
end
function Base.show(io::IO, m::MIME"text/plain", A::MissingSolution)
  print(io,"MissingSolution")
end

struct BareSolution{S,N,U<:Array{<:Array{<:S,N}},X,T} <: AbstractTimeseriesSolution{S,N,U}
    u::U
    x::X
    t::T
    tslocation::Int
end
BareSolution(; u, x, t) = BareSolution(u,x,t)
BareSolution(u::U, x::X, t::T) where {S,N,ELT<:Union{S,Array{<:S,N}},U<:Array{ELT},X,T} = BareSolution{S,N,U,X,T}(u,x,t,0)
BareSolution(u::Missing, x::Missing, t::Missing) = MissingSolution()
function Base.getproperty(bs::BareSolution, sym::Symbol)
    if sym ∈ [:dense, :prob]
        return false
    else
        return Base.getfield(bs, sym)
    end
end
timepoints(bs::BareSolution) = bs.t
coordinates(bs::BareSolution) = bs.x
function Base.show(io::IO, A::BareSolution)
  print(io,"t: ")
  show(io, A.t)
  println(io)
  print(io,"u: ")
  show(io, A.u)
end
function Base.show(io::IO, m::MIME"text/plain", A::BareSolution)
  print(io,"t: ")
  show(io,m,A.t)
  println(io)
  print(io,"u: ")
  show(io,m,A.u)
end
@generated function Simulation73.population_timepoint(solution::BareSolution{T,NP}, pop_dx::Int, time_dx::Int) where {T,NP}
    N = NP - 1 # N + pops
    colons = [:(:) for i in 1:N]
    :(solution[time_dx][$(colons...), pop_dx])
end


text:
include("../src/wgregseq.jl")

using .wgregseq

include("runtests_encoder.jl")


text: struct fixedIncome :> Income end

max_stars_repo_name: adamwillisXanax/accountingJulia

max_issues_repo_name: adamwillisXanax/accountingJulia

max_forks_repo_name: adamwillisXanax/accountingJulia


text:
module DATools

    mutable struct FixedSizeBinaryMaxHeap
        heap::Array{UInt16}
        ind::UInt16
        FixedSizeBinaryMaxHeap(m_max::Int) = new(Array{UInt16}(m_max), 0)
    end

    function Base.length(bmh::FixedSizeBinaryMaxHeap)
        return bmh.ind
    end

    function Base.push!{T <: Integer}(bmh::FixedSizeBinaryMaxHeap, value::T)
        bmh.ind += 1
        bmh.heap[bmh.ind] = value
        reshape_up!(bmh)
    end

    function top(bmh::FixedSizeBinaryMaxHeap)
        if bmh.ind == 0
            return 0
        else
            return bmh.heap[1]
        end
    end

    function Base.pop!(bmh::FixedSizeBinaryMaxHeap)
        ret_val = bmh.heap[1]
        bmh.heap[1] = bmh.heap[bmh.ind]
        bmh.ind -= 1
        reshape_down!(bmh)
        return ret_val
    end

    function Base.getindex(bmh::FixedSizeBinaryMaxHeap, ind::Int)
        return bmh.heap[ind]
    end

    function reshape_down!(bmh::FixedSizeBinaryMaxHeap)
        current_ind = 1
        while true
            c1, c2 = current_ind * 2, current_ind * 2 + 1
            if c1 > bmh.ind
                break
            elseif c2 > bmh.ind
                c = c1
            else
                c = bmh.heap[c1] < bmh.heap[c2] ? c2 : c1
            end
            if bmh.heap[current_ind] < bmh.heap[c]
                bmh.heap[c], bmh.heap[current_ind] = bmh.heap[current_ind], bmh.heap[c]
                current_ind = c
            else
                break
            end
        end
    end

    function reshape_up!(bmh::FixedSizeBinaryMaxHeap)
        current_ind = bmh.ind
        while true
            par = current_ind >> 1
            if par == 0 || bmh.heap[current_ind] <= bmh.heap[par]
                break
            else
                bmh.heap[current_ind], bmh.heap[par] = bmh.heap[par], bmh.heap[current_ind]
            end
            current_ind = par
        end
    end

end


text:
if VERSION < v"0.7-"
    # dummy type to be ignored in 0.6
    struct LineNumberNode end
end

"""
    @recon assignment_expr

A helper macro for reconstructing nested immutable struct.

For example,
    new = @recon old.a.b.c = 1
is converted into
    new = recon(old; a=recon(old.a; b=recon(old.a.b; c=1)))
"""
macro recon(ex)
    esc(recon_impl(ex))
end

recon_impl(ex::Expr) = recon_impl(Val{ex.head}, ex)
recon_impl(::Type{Val{:(=)}}, ex) = assign(ex.args...)

assign(ex::Expr, args...) = assign(Val{ex.head}, ex, args...)
function assign(::Type{Val{:.}}, lhs::Expr, rhs)
    # lhs = old.a.b.c
    # rhs = 1
    # inner = recon(old.a.b; c=1)
    inner = :($recon($(lhs.args[1]); $(assymbol(lhs.args[2])) = $rhs))
    return assign(lhs.args[1], inner)
end
assign(::Symbol, rhs) = rhs
assign(::Type{<: Val}, lhs::Expr, _) = error("Unsupported expression: $lhs")

assymbol(x::Symbol) = x
assymbol(x::QuoteNode) = x.value
assymbol(x::Expr) = assymbol(Val{x.head}, x)
function assymbol(::Type{Val{:quote}}, x::Expr)
    @assert length(x.args) == 1
    return assymbol(x.args[1])
end

statements(ex::Expr) = statements(Val{ex.head}, ex)
statements(::Type{Val{:block}}, ex) = vcat(map(statements, ex.args)...)
statements(::Type{Val{:line}}, _) = Expr[]
statements(::LineNumberNode) = Expr[]
statements(::Type{<: Val}, ex) = [ex]
statements(ex) = ex

function recon_impl(::Type{Val{:block}}, ex)
    args = statements(ex)
    if ! all(a.head == :(=) && length(a.args) == 2 for a in args)
        error("All statements in a block must be assignments. Given:\n",
              "$ex")
    end
    # ex = quote
    #     old.x.x.x = 10
    #     old.x.y.y = 20
    # end
    vlhs = [a.args[1] for a in args]
    vrhs = [a.args[2] for a in args]
    return vassign(vlhs, vrhs)
end

ndots(ex::Expr) = ndots(Val{ex.head}, ex)
ndots(::Type{Val{:.}}, ex) = 1 + ndots(ex.args[1])
ndots(::Symbol) = 0
ndots(::Type{<:Val}, ex) = error("Unsupported expression: $ex")

function vassign(vlhs::Vector, vrhs::Vector)
    maxdots = maximum(map(ndots, vlhs))
    if maxdots == 0
        if length(vlhs) > 1
            error("Trying to modify multiple structs: $vlhs")
        end
        @assert length(vlhs) == length(vrhs) == 1
        # vlhs = [:old]
        # vrhs = [:(recon(old; x=recon(old.x; ...)))]
        return vrhs[1]
    end

    # vlhs = [:(old.x.x.x), :(old.x.y.y)]
    # vrhs = [10, 20]
    # inner = recon(old.a.b; c=1)
    inners = Dict()
    next_vlhs = []
    next_vrhs = []
    for (lhs, rhs) in zip(vlhs, vrhs)
        if ndots(lhs) == maxdots
            kwargs = get!(inners, lhs.args[1]) do
                []
            end
            push!(kwargs, assymbol(lhs.args[2]) => rhs)
        else
            push!(next_vlhs, lhs)
            push!(next_vrhs, rhs)
        end
    end
    for (lhs, kwargs) in inners
        push!(next_vlhs, lhs)
        push!(next_vrhs, Expr(:call, recon, Expr(:parameters, (
            Expr(:kw, k, w) for (k, w) in kwargs
        )...), lhs))
        # next_vrhs[end] contains "recon(lhs; kwargs...)"
    end
    return vassign(next_vlhs, next_vrhs)
end


text:
import Pkg
Pkg.add("Documenter")
Pkg.add("Debugger")
Pkg.add("Parameters")
Pkg.add("ResumableFunctions")

max_stars_repo_name: timm/jut

max_issues_repo_name: timm/jut

max_forks_repo_name: timm/jut


text:
"""
    Harmonic(m=1.0, ω=1.0, r₀=0.0)

Adiabatic harmonic potential. ``V(x) = mω^2(x-r₀)^2 / 2``

```jldoctest
julia> using Symbolics;

julia> @variables x, m, ω, r₀;

julia> model = Harmonic(m=m, ω=ω, r₀=r₀);

julia> potential(model, hcat(x))
0.5m*(ω^2)*((x - r₀)^2)

julia> derivative(model, hcat(x))
1×1 Matrix{Num}:
 m*(x - r₀)*(ω^2)
```
"""
Parameters.@with_kw struct Harmonic{M,W,R} <: AdiabaticModel
    m::M = 1.0
    ω::W = 1.0
    r₀::R = 0.0
    dofs::Int = 1
end

NQCModels.ndofs(harmonic::Harmonic) = harmonic.dofs

function NQCModels.potential(model::Harmonic, R::AbstractMatrix)
    return sum(0.5 * model.m* model.ω^2 .* (R .- model.r₀) .^2)
end

function NQCModels.derivative!(model::Harmonic, D::AbstractMatrix, R::AbstractMatrix)
    D .= model.m* model.ω^2 .* (R .- model.r₀)
end


text:
using Flux
using Statistics
using CUDA
using Plots
using BSON
using Images
using FileIO
using LaTeXStrings
using DelimitedFiles
gr()

loadModelsGPU = (path;top="model-up.bson",down="model-down.bson") -> (
    filename = path*top;
    up = BSON.load(filename) ;
    model_up = up ;
    filename = path*down;
    down = BSON.load(filename) ;
    model_down = down;
    return model_up,model_down)

function calc_one(image)
    image = image
    y_up=CNN_C5_up(image)
    y_down=CNN_C5_down(image)
    y_up = y_up |> cpu
    y_down = y_down |> cpu
    return y_up,y_down
end

a = loadModelsGPU("/home/freshstart/DiplomaThesisData/NeuralNetSaves_050/")
CNN_C5_up = a[1][:md] |> gpu
CNN_C5_down = a[2][:md] |> gpu

data_pth = "/home/freshstart/DiplomaThesisData/r_-50_50/"
io = open(data_pth*"DIRS.dat","r")
dirs=readlines(io)
close(io)

#TRAINING IMAGES LOADING
N = size(dirs)[1] #training batch dynamically allocated to the training batch size
L = 49 #points of interest on the airfoil geometry per side

images = Array{Float32}(undef,(32,32,3,N));
Points_Cp_up = Array{Float32}(undef,(L,N));
Points_Cp_down = Array{Float32}(undef,(L,N));
pers = Array{Float16}(undef,(1,N));

n = 1
@time for airfoil in dirs
    #--- image loading-----
    image = load(airfoil*"RAE_var.png")
    image = channelview(image) #CWH not WHC ie. 3X32X32
    Channels,Width,Height=size(image[:,:,:])
    for C = 1:Channels-1,W = 1:Width,H = 1:Height
        images[W,H,C,n] = image[C,W,H] #Switching from CWH to WHCN
    end
    #-----------------------
    pers[1,n] = parse(Float16,replace(replace(replace(airfoil, data_pth=>""),"/"=>""),"%"=>""))
    #----- Cp data loading--

    file = open(airfoil*"Cp_RAE_up_var.dat")
    lines=readlines(file);
    num=[]
    for i in 1:length(lines)
        push!(num,parse(Float32, lines[i]))
    end
    Points_Cp_up[:,n]=num
    close(file)

    file = open(airfoil*"Cp_RAE_down_var.dat")
    lines=readlines(file);
    num=[]
    for i in 1:length(lines)
        push!(num,parse(Float32, lines[i]))
    end
    Points_Cp_down[:,n]=num
    close(file)

    n +=1
#     break
end

#-- Converting the data arrays to Cuda Arrays to be processed by the gpu
images = images |> gpu;

c = Array{Float32}(undef,(2,N))
x = [0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,0.65,0.7,0.75,0.8,0.85,0.9,0.95,0.96,0.97,0.98,0.99,1]

# UP =[]
# DOWN = []
for i in 1:N
    UP, DOWN = calc_one(reshape(images[:,:,:,i], (32,32,3,1)))
    c[1,i] = (1-sqrt(Flux.mse(UP,Points_Cp_up[:,i])))*100
    c[2,i] = (1-sqrt(Flux.mse(DOWN,Points_Cp_down[:,i])))*100
end

for i in 1:N
    if (i>1 & i<N)
        if ((pers[1,i-1] < 0) & (pers[1,i] > 0))
            c = hcat(c[:,1:i-1],[NaN;NaN],c[:,i:end])
            pers = hcat(pers[:,1:i-1],[0],pers[:,i:end])
            break
        end
    end
end
# test=plot()
# plot!(test,x,UP)
# plot!(test,x,Points_Cp_up[:,1])

pgfplotsx()
plot(   title = "Accuracy plot for airfoils deformed over the original range ",
        xlabel = "Deformation Percentage [%]",
        ylabel = "Accuracy Percentage [%]",
        minorgrid = true)
plot!(pers[1,:],c[1,:],label = "Top side")
plot!(pers[1,:],c[2,:],label = "Bottom side")

savefig(data_pth*"Acc_-50_50.pdf")

max_stars_repo_path: Neural Network/test_range.jl

max_issues_repo_path: Neural Network/test_range.jl

max_forks_repo_path: Neural Network/test_range.jl


text:
# function plot{T}(mnts::StatisticalMoments{T}; ribbon=false, X = mnts.x_arr, use_moments = [1,2,4]) #, kws...)
#     # if ribbon == true
#       # plot_ribbon(mnts)
#       plot_ribbon(mnts; X=X, use_moments=use_moments)
#     # else
#     #   plot_graph(mnts; kws...)
#     # end
#     # println("well hello mister put me nose in other peoples code")
# end

# # woud have liked a user series plot:
# """
#     plot(x, y, seriestype = :moments; kws...)
#
# A failed attempt a creating a user defined series plot for the moments `y` with x-axis `x`.
# """
@recipe function plot_ribbon(results::AbstractVector{SimRes};
        field_apply = real,
        num_moments = 2,
        use_moments = 1:min(num_moments,length(results)),
        Y = statistical_moments(results, num_moments; field_apply=field_apply)[use_moments],
        x = results[1].ω,
        labs = ["mean" "std" "skew" "kurt"]) where {T,SimRes<:SimulationResult{T}}

    # must include mean
    use_moments = sort(union([1; use_moments]))
    if labs == [] labs = repeat([""], inner = length(y)) end
    colors =[:black, :green, :orange, :red]

    m = Y[1]
    Ys = map(2:length(Y)) do i
        Y_down = if iseven(use_moments[i])
            Y[i]
            # Y[i]/T(2)
        else
            map(y-> (y< zero(T)) ? -y : zero(T), Y[i])
        end
        Y_up = if iseven(use_moments[i])
            Y[i]
            # Y[i]/T(2)
        else
            map(y-> (y> zero(T)) ? y : zero(T), Y[i])
        end
        (Y_down, Y_up)
    end
    for i = 1:(length(Ys)-1)
        Ys[i+1] = (Ys[i+1][1] + Ys[i][1], Ys[i+1][2] + Ys[i][2])
    end

    for i in reverse(1:length(Ys))
      @series begin
        seriestype := :line
        ribbon := Ys[i]
        lab --> labs[use_moments[i+1]]
        c --> colors[use_moments[i+1]]
        (x, m[:])
      end
    end

    for i in 1:min(6,length(results))
      @series begin
        linealpha --> 0.2
        lab --> ""
        c --> :grey
        results[i]
      end
    end

    @series begin
      seriestype := :line
      c --> :black
      linewidth --> 2
      lab --> labs[1]
      (x, m[:])
    end
end


text:
import Mongoc

import Base.UUID
using Test
using Dates
using DecFP
using Distributed

@testset "BSON" begin

    @testset "as_json" begin
        @test_throws ErrorException Mongoc.BSON(""" { ajskdla sdjsafd } """)
        bson = Mongoc.BSON("""{"hey" : 1}""")
        @test bson["hey"] == 1
        @test Mongoc.as_json(bson) == """{ "hey" : 1 }"""
        @test Mongoc.as_json(bson, canonical=true) == """{ "hey" : { "\$numberInt" : "1" } }"""
    end

    @testset "oid conversion" begin
        local oid::Mongoc.BSONObjectId = "5b9fb22b3192e3fa155693a1"
        local oid_str::String = oid
    end

    @testset "oid compare" begin
        x = Mongoc.BSONObjectId()
        y = Mongoc.BSONObjectId()
        @test x != y
        @test x == x
        @test y == y
        @test hash(x) == hash(x)
        @test hash(y) == hash(y)
        @test hash(x) != hash(y)
        @test Mongoc.bson_oid_compare(x, y) < 0
        @test Mongoc.bson_oid_compare(y, x) > 0
        @test Mongoc.bson_oid_compare(x, x) == 0
        @test Mongoc.bson_oid_compare(y, y) == 0
    end

    @testset "oid copy" begin
        x = Mongoc.BSONObjectId()
        y = copy(x)
        @test x == y
        @test hash(x) == hash(y)
        @test Mongoc.bson_oid_compare(x, y) == 0
    end

    @testset "oid string" begin
        x = Mongoc.BSONObjectId()
        y = Mongoc.BSONObjectId(string(x))
        @test x == y

        @test_throws ErrorException Mongoc.BSONObjectId("invalid_objectid")
    end

    @testset "oid time" begin
        Mongoc.get_time( Mongoc.BSONObjectId("5b9eaa2711c3dd0d6a46a5c4") ) == DateTime(2018, 9, 16, 19, 8, 23) # 2018-09-16T19:08:23
    end

    @testset "BSONObjectId segfault issue (#2)" begin
        io = IOBuffer()
        v = Vector{Mongoc.BSONObjectId}()

        for i in 1:5
            push!(v, Mongoc.BSONObjectId())
        end
        show(io, v)
    end

    @testset "oid sort" begin
        v = Vector{Mongoc.BSONObjectId}()
        for i in 1:10_000
            push!(v, Mongoc.BSONObjectId())
        end
        @test length(v) == length(unique(v))

        v_sorted = sort(v, lt = (a,b) -> Mongoc.bson_oid_compare(a,b) < 0)
        @test length(v_sorted) == length(v)
        for i in 1:length(v_sorted)
            @test v_sorted[i] == v[i]
        end
    end

    @testset "AbstractString support" begin
        keys_with_prefix = ["aKey1", "aKey2", "aKey3"]
        substring_keys = [ SubString(k, 2, length(k)) for k in keys_with_prefix ]
        vals = [ 1, "hey", nothing ]

        bson = Mongoc.BSON()
        for (i, k) in enumerate(substring_keys)
            bson[k] = vals[i]
        end

        for k in substring_keys
            @test haskey(bson, k)
        end

        for i in 1:3
            @test haskey(bson, "Key$i")
        end

        bson["ah"] = substring_keys[1]
        @test isa(bson["ah"], String)
        @test bson["ah"] == "Key1"
    end

    @testset "UUID support" begin
        uuid = UUID("a1f18b06-2210-499b-8313-28e69090511f")
        bson = Mongoc.BSON("uuid" => uuid)
        @test isa(bson["uuid"], UUID)
        @test bson["uuid"] == uuid
    end

    @testset "BSON key/values itr support" begin
        bson = Mongoc.BSON()
        bson["hey"] = 10
        bson["you"] = "aaa"
        bson["out"] = nothing

        for (k, v) in bson
            @test (k == "hey" && v == 10) || (k == "you" && v == "aaa") || (k == "out" && v == nothing)
        end

        for k in keys(bson)
            @test k == "hey" || k == "you" || k == "out"
        end

        for v in values(bson)
            @test v == 10 || v == "aaa" || v == nothing
        end
    end

    @testset "BSON Iterator" begin
        doc = Mongoc.BSON("""{ "a" : 1, "b" : 2.2, "str" : "my string", "bool_t" : true, "bool_f" : false, "array" : [1, 2, false, "inner_string"], "float_array" : [0.1, 0.2, 0.3, 0.4], "document" : { "a" : 1, "b" : "b_string"}, "null" : null  }""")

        new_id = Mongoc.BSONObjectId()
        doc["_id"] = new_id

        @test haskey(doc, "a")
        @test haskey(doc, "b")
        @test !haskey(doc, "c")
        @test haskey(doc, "str")
        @test haskey(doc, "_id")
        @test haskey(doc, "array")
        @test haskey(doc, "float_array")
        @test haskey(doc, "document")
        @test haskey(doc, "null")

        @test doc["a"] == 1
        @test doc["b"] == 2.2
        @test doc["str"] == "my string"
        @test doc["bool_t"]
        @test !doc["bool_f"]
        @test doc["_id"] == new_id
        @test doc["array"] == [1, 2, false, "inner_string"]
        @test doc["document"] == Dict("a"=>1, "b"=>"b_string")
        @test doc["null"] == nothing

        @test_throws ErrorException doc["invalid key"]

        doc_dict = Mongoc.as_dict(doc)
        @test doc_dict["a"] == 1
        @test doc_dict["b"] == 2.2
        @test doc_dict["str"] == "my string"
        @test doc_dict["bool_t"]
        @test !doc_dict["bool_f"]
        @test doc_dict["_id"] == new_id
        @test doc_dict["array"] == [1, 2, false, "inner_string"]
        @test doc_dict["document"] == Dict("a"=>1, "b"=>"b_string")
        @test doc_dict["null"] == nothing

        # Type-stable API
        @test @inferred(Mongoc.get_array(doc, "float_array", Float64)) == [0.1, 0.2, 0.3, 0.4]
        @test @inferred(Mongoc.get_array(doc, "float_array", Float32)) == Float32[0.1, 0.2, 0.3, 0.4]

        @test_throws MethodError Mongoc.get_array(doc, "float_array", String)
        @test_throws ErrorException Mongoc.get_array(doc, "document", Any)
    end

    @testset "BSON write" begin
        bson = Mongoc.BSON()
        new_oid = Mongoc.BSONObjectId()
        bson["_id"] = new_oid
        bson["int32"] = Int32(10)
        bson["int64"] = Int64(20)
        bson["string"] = "hey you"
        bson["bool_true"] = true
        bson["bool_false"] = false
        bson["double"] = 2.3
        bson["decimal128"] = d128"1.2"
        bson["datetime"] = DateTime(2018, 2, 1, 10, 20, 35, 10)
        bson["vector"] = collect(1:10)
        bson["source"] = Mongoc.BSONCode("function() = 1")
        bson["null"] = nothing
        @test_throws ErrorException bson["key"] = Date(2018, 9, 18)
        str = "the real string"
        sub = SubString(str, 4, 7)
        bson["substring"] = sub

        let
            sub_bson = Mongoc.BSON()
            sub_bson["hey"] = "you"
            sub_bson["num"] = 10
            bson["sub_document"] = sub_bson
        end

        @test bson["_id"] == new_oid
        @test bson["int32"] == Int32(10)
        @test bson["int64"] == Int64(20)
        @test bson["string"] == "hey you"
        @test bson["bool_true"]
        @test !bson["bool_false"]
        @test bson["double"] == 2.3
        @test bson["decimal128"] == d128"1.2"
        @test bson["datetime"] == DateTime(2018, 2, 1, 10, 20, 35, 10)
        @test bson["sub_document"]["hey"] == "you"
        @test bson["sub_document"]["num"] == 10
        @test bson["vector"] == collect(1:10)
        @test bson["source"] == Mongoc.BSONCode("function() = 1")
        @test bson["null"] == nothing
        @test bson["substring"] == sub

        let
            sub_bson = bson["sub_document"]
            @test sub_bson["hey"] == "you"
            @test sub_bson["num"] == 10
        end
    end

    @testset "BSON to Dict conversion" begin
        dict = Dict("a" => 1, "b" => false, "c" => "string", "d" => nothing)
        doc = Mongoc.BSON(dict)
        @test doc["a"] == 1
        @test doc["b"] == false
        @test doc["c"] == "string"
        @test doc["d"] == nothing
        @test dict == Mongoc.as_dict(doc)
    end

    @testset "BSON Dict API" begin
        doc = Mongoc.BSON("a" => 1, "b" => false, "c" => "string", "d" => nothing)

        @test doc["a"] == 1
        @test doc["b"] == false
        @test doc["c"] == "string"
        @test doc["d"] == nothing

        for (key, value) in doc
            if key == "a"
                @test value == 1
            elseif key == "b"
                @test value == false
            elseif key == "c"
                @test value == "string"
            elseif key == "d"
                @test value == nothing
            else
                # test fails
                @test false
            end
        end
    end

    @testset "BSON copy" begin
        @testset "exclude one key" begin
            src = Mongoc.BSON("hey" => "you", "out" => 1)
            dst = Mongoc.BSON()
            Mongoc.bson_copy_to_excluding_noinit(src.handle, dst.handle, "out")
            @test !haskey(dst, "out")
            @test dst["hey"] == "you"
        end

        @testset "no exclude keys" begin
            src = Mongoc.BSON("hey" => "you", "out" => 1)
            dst = Mongoc.BSON()
            Mongoc.bson_copy_to_excluding_noinit(src.handle, dst.handle)
            @test Mongoc.as_dict(src) == Mongoc.as_dict(dst)
        end
    end

    @testset "BSON Write to IO" begin

        @testset "write_bson closure" begin
            io = IOBuffer()

            Mongoc.bson_writer(io, initial_buffer_capacity=1) do writer
                Mongoc.write_bson(writer) do bson
                    bson["id"] = 10
                    bson["str"] = "aa"
                end
            end

            @test io.data == [0x1d,0x00,0x00,0x00,0x12,0x69,0x64,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x73,0x74,0x72,0x00,0x03,0x00,0x00,0x00,0x61,0x61,0x00,0x00,0x00,0x00,0x00]
        end

        @testset "BSON copy single doc" begin
            src = Mongoc.BSON("id" => 10, "str" => "aa")

            io = IOBuffer()
            Mongoc.write_bson(io, src)

            @test io.data == [0x1d,0x00,0x00,0x00,0x12,0x69,0x64,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x73,0x74,0x72,0x00,0x03,0x00,0x00,0x00,0x61,0x61,0x00,0x00,0x00,0x00,0x00]
        end

        @testset "BSON copy doc list" begin
            list = Vector{Mongoc.BSON}()

            let
                src = Mongoc.BSON("id" => 1, "name" => "1st")
                push!(list, src)
            end

            let
                src = Mongoc.BSON("id" => 2, "name" => "2nd")
                push!(list, src)
            end

            io = IOBuffer()
            Mongoc.write_bson(io, list)

            seekstart(io)
            vec_bson = Mongoc.read_bson(io)
            @test length(vec_bson) == 2

            let
                fst_bson = vec_bson[1]
                @test fst_bson["id"] == 1
                @test fst_bson["name"] == "1st"
            end

            let
                sec_bson = vec_bson[2]
                @test sec_bson["id"] == 2
                @test sec_bson["name"] == "2nd"
            end

            seekstart(io)
            reader = Mongoc.BSONReader(read(io))
            vec_bson_from_reader = collect(reader)

            let
                fst_bson = vec_bson_from_reader[1]
                @test fst_bson["id"] == 1
                @test fst_bson["name"] == "1st"
            end

            let
                sec_bson = vec_bson_from_reader[2]
                @test sec_bson["id"] == 2
                @test sec_bson["name"] == "2nd"
            end
        end

        @testset "read BSON from data" begin
            vec_bson = Mongoc.read_bson([0x1d,0x00,0x00,0x00,0x12,0x69,0x64,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x73,0x74,0x72,0x00,0x03,0x00,0x00,0x00,0x61,0x61,0x00,0x00,0x00,0x00,0x00])
            @test length(vec_bson) == 1
            bson = vec_bson[1]
            @test bson["id"] == 10
            @test bson["str"] == "aa"
        end

        @testset "read/write BSON to/from File" begin
            filepath = joinpath(@__DIR__, "data.bson")
            isfile(filepath) && rm(filepath)

            list = Vector{Mongoc.BSON}()

            let
                src = Mongoc.BSON("id" => 1, "name" => "1st")
                push!(list, src)
            end

            let
                src = Mongoc.BSON("id" => 2, "name" => "2nd")
                push!(list, src)
            end

            try
                open(filepath, "w") do io
                    Mongoc.write_bson(io, list)
                end

                @test isfile(filepath)

                reader = Mongoc.BSONReader(filepath)
                for (i, bson) in enumerate(reader)
                    if i == 1
                        @test bson["id"] == 1
                        @test bson["name"] == "1st"
                    elseif i == 2
                        @test bson["id"] == 2
                        @test bson["name"] == "2nd"
                    else
                        error("Got document $i.")
                    end
                end
                Mongoc.destroy!(reader)

            finally
                if isfile(filepath)
                    try
                        rm(filepath)
                    catch err
                        @warn("Failed to remove test file $filepath: $(err.msg)")
                        stacktrace(catch_backtrace())
                    end
                end
            end
        end
    end

    @testset "BSONJSONReader" begin

        @testset "Iterate Reader" begin
            fp = joinpath(@__DIR__, "docs.json")
            @assert isfile(fp)
            reader = Mongoc.BSONJSONReader(fp)

            for (i, bson) in enumerate(reader)
                if i == 1
                    @test bson["num"] == 1
                    @test bson["str"] == "two"
                elseif i == 2
                    @test bson["num"] == 2
                    @test bson["str"] == "three"
                else
                    error("Got bson $i.")
                end
            end

            Mongoc.destroy!(reader)
        end

        @testset "read_bson_from_json" begin
            fp = joinpath(@__DIR__, "docs.json")
            @assert isfile(fp)

            for (i, bson) in enumerate(Mongoc.read_bson_from_json(fp))
                if i == 1
                    @test bson["num"] == 1
                    @test bson["str"] == "two"
                elseif i == 2
                    @test bson["num"] == 2
                    @test bson["str"] == "three"
                else
                    error("Got bson $i.")
                end
            end
        end
    end

    @testset "BSONError" begin
        err = Mongoc.BSONError(0x00000005, 0x00000101, (0x54, 0x6f, 0x74, 0x61, 0x6c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6f,
            0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
            0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x31,
            0x36, 0x37, 0x39, 0x33, 0x36, 0x30, 0x30, 0x2e, 0x20, 0x41, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x69, 0x73, 0x20,
            0x31, 0x36, 0x37, 0x39, 0x34, 0x31, 0x37, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))

        str = sprint(show, err)
        @test str == "BSONError: domain=5, code=257, message=Total size of all transaction operations must be less than 16793600. Actual size is 16794174"
        @test sprint(showerror, err) == str
    end

    @testset "serialize" begin

        @testset "BufferedBSON" begin
            bson = Mongoc.BSON("a" => 1)
            x = Mongoc.BufferedBSON(bson)
            bson_copy = Mongoc.BSON(x)
            @test bson_copy["a"] == 1
        end

        addprocs(1)
        @everywhere using Mongoc

        @testset "serialize BufferedBSON" begin
            f = @spawn Mongoc.BufferedBSON(Mongoc.BSON("a" => 1))
            bson = Mongoc.BSON(fetch(f))
            @test bson["a"] == 1
        end

        @testset "read/write single BSON" begin
            doc = Mongoc.BSON("a" => 1)
            io = IOBuffer()
            write(io, doc)
            seekstart(io)
            doc2 = read(io, Mongoc.BSON)
            @test doc2["a"] == 1
        end

        @testset "Serialize BSON" begin
            f = @spawn Mongoc.BSON("a" => 1)
            bson = fetch(f)
            @test bson["a"] == 1
        end
    end
end


text:
# Abstract network definition

# Networks in agents.jl have nodes, and nodes have lists of AgentIDs

using Agents
using LightGraphs

function generateSpace(properties::Dict)

    if properties["type"] == "barabasi"
        n = properties["n"]
        k = properties["k"]
        n0 = properties["n0"]

        return GraphSpace(LightGraphs.barabasi_albert(n, n0, k))

    end

    if properties["type"] == "watts"
        n = properties["n"]
        k = properties["k"]
        β = properties["beta"]

        return GraphSpace(LightGraphs.watts_strogatz(n,k,β))

    end
end

# this is test, move to tests directory
props = Dict("type" => "barabasi",
             "n" => 100,
             "k" => 2,
             "n0" => 10
)
generateSpace(props)


text:
"""
Cache of expensive and potentially repeatedly-referenced computations.
"""
Base.@kwdef mutable struct Metrics
    d::Dict{String, Any} = Dict{String, Any}()
end

function initialize(m::Metrics, acs::Vector{Aircraft}, nmac::Tuple{R,R})
    m.d["d_min"] = Inf
    update(m, acs, nmac)
end

function update(m::Metrics, acs::Vector{Aircraft}, nmac::Tuple{R,R})
	pairs = subsets(acs, 2)
	m.d["d"] = minimum(norm(separation(pair...)) for pair in pairs) #TODO: was separation(pair...; scale=nmac)
    m.d["d_min"] = min(m.d["d_min"], m.d["d"])
	m.d["is_nmac"] = any(all(separation(pair...) .<= nmac) for pair in pairs)
end


text:
"""
Compiled templating language for Genie.
"""
module Flax

using Genie, Renderer, Gumbo, Logger, Genie.Configuration, Router, SHA, App, Reexport, JSON, DataStructures
@reexport using HttpCommon

if is_dev()
  @eval using Revise
end

if IS_IN_APP
  @eval parse("@dependencies")
end

export HTMLString, JSONString
export doctype, var_dump, include_template, @vars, @yield, el, foreachvar, @foreach

import Base.string

const NORMAL_ELEMENTS = [ :html, :head, :body, :title, :style, :address, :article, :aside, :footer,
                          :header, :h1, :h2, :h3, :h4, :h5, :h6, :hgroup, :nav, :section,
                          :dd, :div, :dl, :dt, :figcaption, :figure, :li, :main, :ol, :p, :pre, :ul, :span,
                          :a, :abbr, :b, :bdi, :bdo, :cite, :code, :data, :dfn, :em, :i, :kbd, :mark,
                          :q, :rp, :rt, :rtc, :ruby, :s, :samp, :small, :spam, :strong, :sub, :sup, :time,
                          :u, :var, :wrb, :audio, :map, :void, :embed, :object, :canvas, :noscript, :script,
                          :del, :ins, :caption, :col, :colgroup, :table, :tbody, :td, :tfoot, :th, :thead, :tr,
                          :button, :datalist, :fieldset, :form, :label, :legend, :meter, :optgroup, :option,
                          :output, :progress, :select, :textarea, :details, :dialog, :menu, :menuitem, :summary,
                          :slot, :template, :blockquote, :center]
const VOID_ELEMENTS   = [:base, :link, :meta, :hr, :br, :area, :img, :track, :param, :source, :input]
const BOOL_ATTRIBUTES = [:checked, :disabled, :selected]

const FILE_EXT      = ".flax.jl"
const TEMPLATE_EXT  = ".flax.html"
const JSON_FILE_EXT = ".json.jl"
const MARKDOWN_FILE_EXT = ".md"

const SUPPORTED_HTML_OUTPUT_FILE_FORMATS = [TEMPLATE_EXT, MARKDOWN_FILE_EXT]

const HTMLString = String
const JSONString = String

const BUILD_NAME    = "FlaxViews"
const MD_BUILD_NAME = "MarkdownViews"

task_local_storage(:__vars, Dict{Symbol,Any}())

"""
    prepare_template(s::String)
    prepare_template{T}(v::Vector{T})

Cleans up the template before rendering (ex by removing empty nodes).
"""
function prepare_template(s::String) :: String
  s
end
function prepare_template{T}(v::Vector{T}) :: String
  filter!(v) do (x)
    ! isa(x, Void)
  end
  join(v)
end

"""
    attributes(attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: Vector{String}

Parses HTML attributes.
"""
function attributes(attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: Vector{String}
  a = String[]
  for (k,v) in attrs
    push!(a, "$(k)=\"$(v)\"")
  end

  a
end

function normalize_element(elem::String)
  replace(string(lowercase(elem)), "_", "-")
end

"""
    normal_element(f::Function, elem::String, attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: HTMLString

Generates a regular HTML element in the form <...></...>
"""
function normal_element(f::Function, elem::String, attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: HTMLString
  a = attributes(attrs)
  elem = normalize_element(elem)

  "<$(elem * (! isempty(a) ? (" " * join(a, " ")) : ""))>$(prepare_template(f()))</$(elem)>"
end
function normal_element(elem::String, attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: HTMLString
  a = attributes(attrs)
  elem = normalize_element(elem)

  "<$(elem * (! isempty(a) ? (" " * join(a, " ")) : ""))></$(elem)>"
end

"""
    void_element(elem::String, attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: HTMLString

Generates a void HTML element in the form <...>
"""
function void_element(elem::String, attrs::Vector{Pair{Symbol,String}} = Vector{Pair{Symbol,String}}()) :: HTMLString
  a = attributes(attrs)
  elem = normalize_element(elem)

  "<$(elem * (! isempty(a) ? (" " * join(a, " ")) : ""))>"
end

"""
    skip_element(f::Function) :: HTMLString
    skip_element() :: HTMLString

Cleans up empty elements.
"""
function skip_element(f::Function) :: HTMLString
  "$(prepare_template(f()))"
end
function skip_element() :: HTMLString
  ""
end

"""
    include_template(path::String; partial = true, func_name = "") :: String

Includes a template inside another.
"""
function include_template(path::String; partial = true, func_name = "") :: String
  if App.config.log_views
    Logger.log("Including $path", :info)
    @time _include_template(path, partial = partial, func_name = func_name)
  else
    _include_template(path, partial = partial, func_name = func_name)
  end
end
function _include_template(path::String; partial = true, func_name = "") :: String
  _path, _extension = "", ""
  if isfile(abspath(path))
    _path, _extension = relpath(path), "." * split(path, ".")[end]
  else
    for file_extension in SUPPORTED_HTML_OUTPUT_FILE_FORMATS
      if isfile(relpath(path * file_extension))
        _path, _extension = relpath(path * file_extension), file_extension
        break
      end
    end
  end

  _path == "" ? error("File not found $path in $(@__FILE__):$(@__LINE__)") : path = _path

  if _extension == MARKDOWN_FILE_EXT # .md
    build_path = joinpath(Genie.BUILD_PATH, MD_BUILD_NAME, md_build_name(path))
    isfile(build_path) && ! build_is_stale(path, build_path) && return readstring(build_path)

    md_html = Markdown.parse(include_string(string('"', readstring(path), '"'))) |> Markdown.html
    open(joinpath(Genie.BUILD_PATH, MD_BUILD_NAME, md_build_name(path)), "w") do io
      write(io, md_html)
    end

    return md_html
  end

  f_name = func_name != "" ? Symbol(func_name) : Symbol(function_name(path))
  try
    build_path = joinpath(Genie.BUILD_PATH, BUILD_NAME, m_name(path) * ".jl")

    isdefined(Flax, f_name) &&
      (App.config.flax_compile_templates || ! build_is_stale(path, build_path)) &&
        return getfield(Flax, f_name) |> Base.invokelatest

    build_module(html_to_flax(path, partial = partial), path)
    sleep(0.1)

    isdefined(Flax, Symbol(m_name(path))) ? revise() : eval(Flax, parse("using $(m_name(path))"))

    return getfield(Flax, f_name) |> Base.invokelatest
  catch ex
    Logger.log("$(@__FILE__):$(@__LINE__)", :err)

    rethrow(ex)
  end
end

"""
"""
function md_build_name(path::String) :: String
  replace(path, "/", "_")
end

"""
"""
function build_is_stale(file_path::String, build_path::String) :: Bool
  file_mtime = stat(file_path).mtime
  build_mtime = stat(build_path).mtime
  status = file_mtime > build_mtime

  App.config.log_views && status && Logger.log("🚨  Flax view $file_path build $build_path is stale")

  status
end

"""
    html(resource::Symbol, action::Symbol, layout::Symbol; vars...) :: Dict{Symbol,String}

Renders a HTML view corresponding to a resource and a controller action.
"""
function html(resource::Union{Symbol,String}, action::Union{Symbol,String}, layout::Union{Symbol,String}; vars...) :: Dict{Symbol,String}
  try
    task_local_storage(:__vars, Dict{Symbol,Any}(vars))
    task_local_storage(:__yield, include_template(joinpath(Genie.RESOURCES_PATH, string(resource), Renderer.VIEWS_FOLDER, string(action))))

    Dict{Symbol,AbstractString}(:html => include_template(joinpath(Genie.APP_PATH, Renderer.LAYOUTS_FOLDER, string(layout)), partial = false) |> string |> doc)
  catch ex
    Logger.log(string(ex), :err)
    Logger.log("$(@__FILE__):$(@__LINE__)", :err)

    rethrow(ex)
  end
end
function html(view::String, layout::String = "<% @yield %>"; vars...) :: Dict{Symbol,String}
  try
    task_local_storage(:__vars, Dict{Symbol,Any}(vars))
    task_local_storage(:__yield, eval(parse(parse_string(view))))

    Dict{Symbol,AbstractString}(:html => eval(parse(parse_string(layout, partial = false))) |> string |> doc)
  catch ex
    Logger.log(string(ex), :err)
    Logger.log("$(@__FILE__):$(@__LINE__)", :err)

    rethrow(ex)
  end
end

"""
    flax(resource::Symbol, action::Symbol, layout::Symbol; vars...) :: Dict{Symbol,String}

Renders a Flax view corresponding to a resource and a controller action.
"""
function flax(resource::Union{Symbol,String}, action::Union{Symbol,String}, layout::Union{Symbol,String}; vars...) :: Dict{Symbol,String}
  err_msg = "The Flax view must return a function"
  try
    julia_action_template_func = joinpath(Genie.RESOURCES_PATH, string(resource), Renderer.VIEWS_FOLDER, string(action) * FILE_EXT) |> include
    julia_layout_template_func = joinpath(Genie.APP_PATH, Renderer.LAYOUTS_FOLDER, string(layout) * FILE_EXT) |> include

    task_local_storage(:__vars, Dict{Symbol,Any}(vars))

    if isa(julia_action_template_func, Function)
      task_local_storage(:__yield, julia_action_template_func())
    else
      Logger.log(err_msg, :err)
      Logger.log("$(@__FILE__):$(@__LINE__)")

      throw(err_msg)
    end

    return  if isa(julia_layout_template_func, Function)
              Dict{Symbol,AbstractString}(:html => julia_layout_template_func() |> string |> doc)
            else
              Logger.log(err_msg, :err)
              Logger.log("$(@__FILE__):$(@__LINE__)")

              throw(err_msg)
            end
  catch ex
    Logger.log(string(ex), :err)
    Logger.log("$(@__FILE__):$(@__LINE__)", :err)

    rethrow(ex)
  end
end

"""
    json(resource::Symbol, action::Symbol; vars...) :: Dict{Symbol,String}

Renders a JSON view corresponding to a resource and a controller action.
"""
function json(resource::Union{Symbol,String}, action::Union{Symbol,String}; vars...) :: Dict{Symbol,String}
  try
    task_local_storage(:__vars, Dict{Symbol,Any}(vars))

    return Dict{Symbol,AbstractString}(:json => (joinpath(Genie.RESOURCES_PATH, string(resource), Renderer.VIEWS_FOLDER, string(action) * JSON_FILE_EXT) |> include) |> JSON.json)
  catch ex
    Logger.log("Error generating JSON view", :err)
    Logger.log(string(ex), :err)
    Logger.log("$(@__FILE__):$(@__LINE__)", :err)

    rethrow(ex)
  end
end

"""
    function_name(file_path::String)

Generates function name for generated Flax views.
"""
function function_name(file_path::String) :: String
  file_path = relpath(file_path)
  "func_$(sha1(file_path) |> bytes2hex)"
end

"""
    m_name(file_path::String)

Generates module name for generated Flax views.
"""
function m_name(file_path::String) :: String
  file_path = relpath(file_path)
  "Module$(sha1(file_path) |> bytes2hex)"
end

"""
    html_to_flax(file_path::String; partial = true) :: String

Converts a HTML document to a Flax document.
"""
function html_to_flax(file_path::String; partial = true) :: String
  code =  """module $(m_name(file_path)) \n"""
  code *= """using Flax, Router\n"""
  code *= """export $(function_name(file_path)) \n"""
  code *= """function $(function_name(file_path))() \n"""
  code *= parse_template(file_path, partial = partial)
  code *= """\nend \n"""
  code *= """\nend"""

  code
end

"""
"""
function build_module(content::String, path::String) :: Bool
  module_path = joinpath(Genie.BUILD_PATH, BUILD_NAME, m_name(path) * ".jl")
  open(module_path, "w") do io
    write(io, content)
  end

  true
end

"""
    read_template_file(file_path::String) :: String

Reads `file_path` template from disk.
"""
function read_template_file(file_path::String) :: String
  html = String[]
  open(file_path) do f
    for line in enumerate(eachline(f))
      push!(html, parse_tags(line))
    end
  end

  join(html, "\n")
end

"""
    parse_template(file_path::String; partial = true) :: String

Parses a HTML file into a `string` of Flax code.
"""
function parse_template(file_path::String; partial = true) :: String
  htmldoc = read_template_file(file_path) |> Gumbo.parsehtml
  parse_tree(htmldoc.root, "", 0, partial = partial)
end

"""
"""
function parse_string(s::String; partial = true) :: String
  htmldoc = parse_tags(s) |> Gumbo.parsehtml
  parse_tree(htmldoc.root, "", 0, partial = partial)
end

"""
    parse_tree(elem, output, depth; partial = true) :: String

Parses a Gumbo tree structure into a `string` of Flax code.
"""
function parse_tree(elem::Union{HTMLElement,HTMLText}, output::String = "", depth::Int = 0; partial = true) :: String
  if isa(elem, HTMLElement)

    tag_name = replace(lowercase(string(tag(elem))), "-", "_")
    invalid_tag = partial && (tag_name == "html" || tag_name == "head" || tag_name == "body")

    if tag_name == "script" && in("type", collect(keys(attrs(elem))))
      if attrs(elem)["type"] == "julia/eval"
        if ! isempty(children(elem))
          output *= repeat("\t", depth) * string(children(elem)[1].text) * "\n"
        end
      end

    else
      # output *= (repeat("\t", depth) * (invalid_tag ? "" : "Flax.$(tag_name)("))
      output *= repeat("\t", depth) * ( ! invalid_tag ? "Flax.$(tag_name)(" : "Flax.skip_element(" )

      attributes = String[]
      for (k,v) in attrs(elem)
        x = v

        if startswith(v, "<\$") && endswith(v, "\$>")
          v = (replace(replace(replace(v, "<\$", ""), "\$>", ""), "'", "\"") |> strip)
          x = v
          v = "\$($v)"
        end

        if in(Symbol(lowercase(k)), BOOL_ATTRIBUTES)
          if x == true || x == "true" || x == :true || x == ":true" || x == ""
            push!(attributes, ":$(Symbol(k)) => \"$k\"") # boolean attributes can have the same value as the attribute -- or be empty
          end
        else
          push!(attributes, """Symbol("$k") => "$v" """)
        end
      end

      # output *= invalid_tag ? "" : join(attributes, ", ") * ") "
      output *= join(attributes, ", ") * ") "

      inner = ""
      if ! isempty(children(elem))
        children_count = size(children(elem))[1]

        # output *= invalid_tag ? "" : "do;[\n"
        output *= "do;[\n"

        idx = 0
        for child in children(elem)
          idx += 1
          inner *= parse_tree(child, "", depth + 1, partial = partial)
          if idx < children_count
            if isa(child, HTMLText) ||
                ( isa(child, HTMLElement) && ( ! in("type", collect(keys(attrs(child)))) || ( in("type", collect(keys(attrs(child)))) && (attrs(child)["type"] != "julia/eval") ) ) )
                ! isempty(inner) && (inner = repeat("\t", depth) * inner * "\n")
            end
          end
        end
        isempty(inner) || (output *= inner * "\n" * repeat("\t", depth))

        # output *= invalid_tag ? "" : "]end\n"
        output *= "]end\n"
      end
    end

  elseif isa(elem, HTMLText)
    # content = replace(elem.text, r"<:(.*):>", (x) -> replace(replace(x, "<:", ""), ":>", "") |> strip |> string)
    output *= repeat("\t", depth) * "\"$(elem.text |> strip |> string)\""
  end

  output
end

"""
    parse_tags(line::Tuple{Int64,String}, strip_close_tag = false) :: String

Parses special Flax tags.
"""
function parse_tags(line::Tuple{Int64,String}) :: String
  parse_tags(line[2])
end
function parse_tags(code::String) :: String
  # code = replace(code, "<%", """""")
  replace(code, "%>", ")")
end

"""
    doctype(doctype::Symbol = :html) :: String

Outputs document's doctype.
"""
function doctype(doctype::Symbol = :html) :: String
  "<!DOCTYPE $doctype>"
end

"""
    doc(html::String) :: String
    doc(doctype::Symbol, html::String) :: String

Outputs document's doctype.
"""
function doc(html::String) :: String
  doctype() * "\n" * html
end
function doc(doctype::Symbol, html::String) :: String
  doctype(doctype) * "\n" * html
end

"""
    register_elements() :: Void

Generated functions that represent Flax functions definitions corresponding to HTML elements.
"""
function register_elements() :: Void
  for elem in NORMAL_ELEMENTS
    register_normal_element(elem)
  end

  for elem in VOID_ELEMENTS
    register_void_element(elem)
  end

  nothing
end

function register_element(elem::Symbol, elem_type::Symbol = :normal)
  elem_type != :normal && elem_type != :void && error("elem_type must be one of :normal or :void")

  elem_type == :normal ? register_normal_element(elem) : register_void_element(elem)
end

"""
"""
function register_normal_element(elem::Symbol)
  """
    function $elem(f::Function = ()->"", attrs::Pair{Symbol,String}...) :: HTMLString
      \"\"\"\$(normal_element(f, "$(string(elem))", Pair{Symbol,String}[attrs...]))\"\"\"
    end
  """ |> parse |> eval

  """
    function $elem(attrs::Pair{Symbol,String}...) :: HTMLString
      \"\"\"\$(normal_element("$(string(elem))", Pair{Symbol,String}[attrs...]))\"\"\"
    end
  """ |> parse |> eval
end

"""
"""
function register_void_element(elem::Symbol)
  """
    function $elem(attrs::Pair{Symbol,String}...) :: HTMLString
      \"\"\"\$(void_element("$(string(elem))", Pair{Symbol,String}[attrs...]))\"\"\"
    end
  """ |> parse |> eval
end

push!(LOAD_PATH,  abspath(Genie.HELPERS_PATH))

"""
    include_helpers() :: Void

Loads helpers and makes them available in the view layer.
"""
function include_helpers() :: Void
  for h in readdir(Genie.HELPERS_PATH)
    if isfile(joinpath(Genie.HELPERS_PATH, h)) && endswith(h, "Helper.jl")
      eval("""@reexport using $(replace(h, r"\.jl$", ""))""" |> parse)
    end
  end

  nothing
end

"""
"""
macro foreach(f, arr)
  quote
    isempty($arr) && return ""
    mapreduce(*, $arr) do _s
      $f(_s)
    end
  end
end

"""
    foreachvar(f::Function, key::Symbol, v::Vector) :: String

Utility function for looping over a `vector` `v` in the view layer.
"""
function foreachvar(f::Function, key::Symbol, v::Vector) :: String
  isempty(v) && return ""

  output = mapreduce(*, v) do (value)
    vars = task_local_storage(:__vars)
    vars[key] = value
    task_local_storage(:__vars, vars)

    f(value)
  end

  vars = task_local_storage(:__vars)
  delete!(vars, key)
  task_local_storage(:__vars, vars)

  output
end

register_elements()
IS_IN_APP && include_helpers()

"""
    var_dump(var, html = true) :: String

Utility function for dumping a variable.
"""
function var_dump(var, html = true) :: String
  iobuffer = IOBuffer()
  show(iobuffer, var)
  content = takebuf_string(iobuffer)

  html ? replace(replace("$content", "\n", "
"), " ", " ") : content
end

macro vars()
  :(task_local_storage(:__vars))
end
macro vars(key)
  :(task_local_storage(:__vars)[$key])
end
macro vars(key, value)
  :(task_local_storage(:__vars)[$key] = $value)
end
macro yield()
  :(task_local_storage(:__yield))
end

function el(; vars...)
  OrderedDict(vars)
end

"""
    prepare_build() :: Bool

Sets up the build folder and the build module file for generating the compiled views.
"""
function prepare_build(subfolder) :: Bool
  rm(subfolder, force = true, recursive = true)

  build_path = joinpath(Genie.BUILD_PATH, subfolder)
  isdir(build_path) || mkpath(build_path)
  push!(LOAD_PATH, build_path)

  true
end
prepare_build(BUILD_NAME)
prepare_build(MD_BUILD_NAME)

end


text:
# MIT license
# Copyright (c) Microsoft Corporation. All rights reserved.
# See LICENSE in the project root for full license information.

abstract type ArrangementConvexShape{N, T<:Real} end

struct Shape{N, T} <: ArrangementConvexShape{N, T}
    _center::SVector{N, T}
    _points::Vector{SVector{N, T}}
    _coordinates::Tuple{Int,Int}

    function Shape(center::SVector{N, T}, points::AbstractVector{SVector{N, T}}, coordinates::Tuple{Int,Int}) where {N, T<:Real}
        return new{N, T}(center, points, coordinates)
    end

    """convenience function to make Shape constructor more compatible with functions in Repeat module, which use SMatrix{N1,N2} to represent vertices rather than Vector{SVector}"""
    function Shape(center::SVector{N, T}, points::SMatrix{N,N2,T}, coordinates::Tuple{Int,Int}) where {N, N2, T<:Real}
        return new{N,T}(center, Vector{SVector{N,T}}([points[:,i] for i in 1:N2]),coordinates)
    end
end

center(h::Shape) = h._center
points(h::Shape) = h._points
coordinates(h::Shape) = h._coordinates

function get_shapes(basis::Basis{2,T},cells::AbstractMatrix{Int}, radius::T) where{T}
    basic_tile = Repeat.tilevertices(basis) * radius
    cols = Base.size(cells)[2]
    res = Vector{Shape{2, T}}(undef, 0)

    for i in 1:cols
        cell = cells[:,i]
        center = SVector(basis[cell[1], cell[2]]) * radius
        points = [(SVector(p) + center) for p in eachcol(basic_tile)]
        center = center
        push!(res, Shape(center, points, (cell[1],cell[2])))
    end
    return res
end

get_shapes(type::Type{Any};) = @error "Unknown Type [$type] - available types are Hexagon, Rectangle"

function get_shapes(basis::HexBasis1{2,T};resolution::Tuple{Int,Int}=(2,2), size=1.5) where{T}
    println(typeof(Repeat.hexcellsinbox(resolution[1],resolution[2])))
    return get_shapes(basis,Repeat.hexcellsinbox(resolution[1],resolution[2]),size)
end

function get_shapes(basis::RectangularBasis{2,T};resolution::Tuple{Int,Int}=(2,2), size=1.5) where{T}
    temp = collect(Iterators.product(-resolution[1]:resolution[1], -resolution[2]:resolution[2]))
    cells = reshape(temp,length(temp))
    result = Matrix{Int64}(undef,2,length(temp))

    for i in 1:length(cells)
        result[1,i] = cells[i][1]
        result[2,i] = cells[i][2]
    end

    get_shapes(basis,result,size)
end

function project(shapes::Vector{Shape{2, T}}, csg::OpticSim.CSGTree{T})::Vector{Shape{3, T}} where {T<:Real}
    ray_origin_distance = -10.0
    projected_shapes = Vector{Shape{3, Float64}}(undef, 0)
    for shape in shapes
        ok = true               # will turn to false if one of the hexagon vertces is not hitting the CSGTree and we reject the hexagon
        projected_shape_points = Vector{SVector{3, Float64}}(undef, 0)
        for pt in points(shape)
            ray = Ray(Vec3(pt[1], pt[2], ray_origin_distance), Vec3(0.0, 0.0, 1.0))

            interval = surfaceintersection(csg, ray)

            if interval isa EmptyInterval || OpticSim.isinfiniteinterval(interval)
                ok = false;
                @warn "Hexagon Rejected - Coordinates $(coordinates(shape))"
                break;
            end

            p = point(OpticSim.lower(interval))
            push!(projected_shape_points, p)
        end
        if (ok)
            pt = center(shape)
            ray = Ray(Vec3(pt[1], pt[2], ray_origin_distance), Vec3(0.0, 0.0, 1.0))
            interval = surfaceintersection(csg, ray)
            p = point(OpticSim.lower(interval))
            projected_shape = Shape(p, projected_shape_points, coordinates(shape))
            push!(projected_shapes, projected_shape)
        end
    end
    return projected_shapes
end

function build_paraxial_lens(shape::Shape{3, T}; local_center_point = SVector(0.0, 0.0), parent_transform::Transform = identitytransform(), scale=1.0, focal_length=10.0)::ParaxialLens{T} where {T<:Real}
    pts = HeadEye.points(shape)
    cen = HeadEye.center(shape)

    # estimate a best fitting plane (least-squares wise)
    # switching to SMatrix format - should consider using SMatrix in the basic shapes instead of a vector of points
    pts_mat = reshape(SVector(reduce(vcat, pts)...), StaticArrays.Size(length(pts[1]),length(pts)))
    fitted_center, fitted_normal = HeadEye.plane_from_points2(pts_mat)

    # create a local frame for the fitted plane
    local_frame = Transform(fitted_center, fitted_normal)

    # project the center on the estimated plane
    local_center = world2local(local_frame) * cen
    projected_center = local2world(local_frame) * Vec3(local_center[1], local_center[2], 0.0)

    # convert the local frame so the origin will align with the projected center - not a must but more elegant
    local_frame = Transform(projected_center, fitted_normal)

    # project the rest of the points and get their local coordinates in order to create the convex polygon
    local_points = Vector{SVector{2, Float64}}(undef, 0)
    for p in pts
        local_p = world2local(local_frame) * p * scale
        push!(local_points, SVector(local_p[1], local_p[2]))
    end

    # polygon = ConvexPolygon(local_frame, local_points)
    # push!(planar_polygons, polygon)

    lens = ParaxialLensConvexPoly(focal_length, parent_transform * local_frame, local_points, local_center_point)
    return lens
end

function build_emitter(lens::ParaxialLens{T}; parent_transform::Transform = identitytransform(), distance=0.05, size=(0.01, 0.01))::Emitters.Sources.AbstractSource{T} where {T<:Real}
    local_frame = Transform(Vec3(OpticSim.centroid(lens)), Vec3(normal(lens)))
    S = Emitters.Spectrum.Uniform()
    P = Emitters.AngularPower.Lambertian()
    O = Emitters.Origins.RectGrid(size[1], size[2], 2, 2)
    D = Emitters.Directions.Constant()
    local Tr = parent_transform * Transform(local2world(local_frame) * (unitZ3() * -distance), forward(local_frame) )
    source = Emitters.Sources.Source(Tr, S, O, D, P)
    return source
end


text:
const TIMER_OUTPUTS = true
const being_timed = Ref{Bool}(false)

if TIMER_OUTPUTS
    using TimerOutputs

    macro timer(name, expr)
        :(if being_timed[]
              @timeit $(esc(name)) $(esc(expr))
          else
              $(esc(expr))
          end)
    end

    macro iftimer(expr)
        esc(expr)
    end

else
    macro timer(name, expr)
        esc(expr)
    end

    macro iftimer(expr)
    end
end

using Base: ImmutableDict

pow(x,y) = y==0 ? 1 : y<0 ? inv(x)^(-y) : x^y
pow(x::Symbolic,y) = y==0 ? 1 : Base.:^(x,y)
pow(x, y::Symbolic) = Base.:^(x,y)
pow(x::Symbolic,y::Symbolic) = Base.:^(x,y)

# Simplification utilities
function has_trig_exp(term)
    !istree(term) && return false
    fns = (sin, cos, tan, cot, sec, csc, exp)
    op = operation(term)

    if Base.@nany 7 i->fns[i] === op
        return true
    else
        return any(has_trig_exp, arguments(term))
    end
end

function fold(t)
    if istree(t)
        tt = map(fold, arguments(t))
        if !any(x->x isa Symbolic, tt)
            # evaluate it
            return operation(t)(tt...)
        else
            return similarterm(t, operation(t), tt)
        end
    else
        return t
    end
end

### Predicates

sym_isa(::Type{T}) where {T} = @nospecialize(x) -> x isa T || symtype(x) <: T

isliteral(::Type{T}) where {T} = x -> x isa T
is_literal_number(x) = isliteral(Number)(x)

# checking the type directly is faster than dynamic dispatch in type unstable code
_iszero(x) = x isa Number && iszero(x)
_isone(x) = x isa Number && isone(x)
_isinteger(x) = (x isa Number && isinteger(x)) || (x isa Symbolic && symtype(x) <: Integer)
_isreal(x) = (x isa Number && isreal(x)) || (x isa Symbolic && symtype(x) <: Real)

issortedₑ(args) = issorted(args, lt=<ₑ)
needs_sorting(f) = x -> is_operation(f)(x) && !issortedₑ(arguments(x))

# are there nested ⋆ terms?
function isnotflat(⋆)
    function (x)
        args = arguments(x)
        for t in args
            if istree(t) && operation(t) === (⋆)
                return true
            end
        end
        return false
    end
end

function hasrepeats(x)
    length(x) <= 1 && return false
    for i=1:length(x)-1
        if isequal(x[i], x[i+1])
            return true
        end
    end
    return false
end

function merge_repeats(merge, xs)
    length(xs) <= 1 && return false
    merged = Any[]
    i=1

    while i<=length(xs)
        l = 1
        for j=i+1:length(xs)
            if isequal(xs[i], xs[j])
                l += 1
            else
                break
            end
        end
        if l > 1
            push!(merged, merge(xs[i], l))
        else
            push!(merged, xs[i])
        end
        i+=l
    end
    return merged
end

"""
    flatten_term(⋆, x)

Return a flattened expression with the numbers at the back.

# Example
```jldoctest
julia> @syms x y;

julia> SymbolicUtils.flatten_term(+, y + y + x)
x + 2y
```
"""
function flatten_term(⋆, x)
    args = arguments(x)
    # flatten nested ⋆
    flattened_args = []
    for t in args
        if istree(t) && operation(t) === (⋆)
            append!(flattened_args, arguments(t))
        else
            push!(flattened_args, t)
        end
    end
    similarterm(x, ⋆, flattened_args)
end

function sort_args(f, t)
    args = arguments(t)
    if length(args) < 2
        return similarterm(t, f, args)
    elseif length(args) == 2
        x, y = args
        return similarterm(t, f, x <ₑ y ? [x,y] : [y,x])
    end
    args = args isa Tuple ? [args...] : args
    similarterm(t, f, sort(args, lt=<ₑ))
end


text:
""" Tests on the code """

include("main.jl")

function test(instance_path::String)

    println("-------------------------------------------")
    println("INSTANCE : ",instance_path)
    println(CONFIG)

    dichos = [JUMP, COMBO]
    methods = [EXACT_JUMP, EXACT_COMBO, RELAX_LIN_CLASSIC]
    tab = [false, true]

    last_cpt, last_lb = 0,0

    for dicho in dichos
        COMPONENTS.firstDicho = dicho
        for method in methods
            COMPONENTS.methodUB = method
            for vN in tab
                COMPONENTS.nadirsShift = vN
                for vH in tab
                    COMPONENTS.primal_heuristic = vH
                    cpt, lb = main(instance_path)
                    #cpt, lb = main()
                    if last_cpt != 0
                        @assert lb.sols == last_lb.sols "Different results"
                        println("   SUCCESS - ",COMPONENTS)
                    else
                        last_cpt = cpt
                        last_lb = lb
                        println("   FIRST   - ",COMPONENTS)
                    end
                end
            end
        end
    end
end

function test()
    for size in [10, 20, 30, 40, 50]
        for id in 1:5
            path = string("instances/Inst_",size,"_",id,".dat")
            test(path)
        end
    end
end


text:
####################################################################
#### An implementation of Adagrad: Adaptive Subgradient Methods ####
###########for Online Learning and Stochastic Optimization##########
########################### in Mocha.jl ############################
################### CREATED BY: ALEXANDER AMINI ####################
####################################################################

export Adagrad

immutable Adagrad <: SolverMethod
end

make_solver_parameters(method::Adagrad; kwargs...)=
 merge( make_solver_parameters(gamma=1.0, epsilon=1e-8), SolverParameters(kwargs))

validate_parameters(method::Adagrad, params::SolverParameters) = validate_parameters(params, :gamma, :epsilon)

type AdagradSolverState <: InternalSolverState
    param_states  :: Vector{LayerState}
    param_history :: Vector{Vector{Blob}}
end

type AdagradSolverSnapshot <: SolverStateSnapshot
    iteration     :: Int
    obj_val       :: Float64
end

function snapshot(state::SolverState{AdagradSolverState})
    AdagradSolverSnapshot(state.iter, state.obj_val)
end

solver_state(net::Net, snapshot::AdagradSolverSnapshot) = begin
    SolverState{AdagradSolverState}(snapshot.iteration, snapshot.obj_val,
                                Dict(),  AdagradSolverState(net))
end

solver_state(method::Adagrad, net::Net, params::SolverParameters) = begin
    SolverState(AdagradSolverState(net ))
end

AdagradSolverState(net::Net) = begin
  param_states = updatable_layer_states(net)

  param_history = Array{Vector{Blob}}(length(param_states))

  for i = 1:length(param_states)
    state = param_states[i]
    param_history[i] = [make_zero_blob(net.backend, eltype(x.blob),size(x.blob)...) for x in state.parameters]
  end
  return AdagradSolverState(param_states, param_history)
end

function shutdown(state::SolverState{AdagradSolverState})
  map(x -> map(destroy, x), state.internal.param_history)
end

function update(solver::Solver{Adagrad}, net::Net, state::SolverState{AdagradSolverState})
  for i = 1:length(state.internal.param_states)
    layer_state   = state.internal.param_states[i]
    history = state.internal.param_history[i]
    for j = 1:length(layer_state.parameters)
      hist_blob = history[j]
      gradient  = layer_state.parameters[j].gradient
      data_type = eltype(hist_blob)

      update_parameters!(net, solver.method, solver.params[:gamma], solver.params[:epsilon],
          layer_state.parameters[j].blob, hist_blob, gradient, data_type)
    end
  end
end

function update_parameters!(net::Net{CPUBackend}, method::Adagrad, gamma, epsilon,
    param_blob, hist_blob, gradient, data_type)

  g2 = gradient.data .^ 2;

  # hist_blob += 1* g2 (update with vt-1)
  BLAS.axpy!(length(hist_blob), convert(data_type, 1), pointer(g2), 1, pointer(hist_blob.data), 1)
  adj_learning_rate = gamma / (epsilon + sqrt(sum(hist_blob.data)))

  # param_blob += -adj_learning_rate * gradient
  BLAS.axpy!(length(hist_blob), convert(data_type, -adj_learning_rate), gradient.data, 1, param_blob.data, 1)
end


text:
const MatchesBuf = Vector{Tuple{Rule, Sub, Int64}}

import ..genrhsfun
import ..options
import ..@log

using .Schedulers

inst(var, egraph::EGraph, sub::Sub) =
    haskey(sub, var) ? first(sub[var]) : add!(egraph, var)
inst(p::Expr, egraph::EGraph, sub::Sub) = add!(egraph, p)

function instantiate(egraph::EGraph, p, sub::Sub; skip_assert=false)
    # remove type assertions
    if skip_assert
        p = df_walk( x -> (isexpr(x, :(::)) ? x.args[1] : x), p; skip_call=true )
    end

    df_walk(inst, p, egraph, sub; skip_call=true)
end

function eqsat_step!(egraph::EGraph, theory::Vector{Rule};
        scheduler=SimpleScheduler())
    matches=MatchesBuf()
    EMPTY_DICT = Sub()

    readstep!(scheduler)

    for rule ∈ theory
        # don't apply banned rules
        shouldskip(scheduler, rule) && continue

        if rule.mode == :rewrite || rule.mode == :dynamic
            for id ∈ keys(egraph.M)
                # println(rule.right)
                for sub in ematch(egraph, rule.left, id, EMPTY_DICT)
                    # display(sub); println()
                    !isempty(sub) && push!(matches, (rule, sub, id))
                end
                # for sub in ematch(egraph, rule.right, id, EMPTY_DICT)
                #     # display(sub); println()
                #     !isempty(sub) && push!(matches, (rule, sub, id))
                # end
            end
        else
            error("unsupported rule mode")
        end
    end

    for (rule, sub, id) ∈ matches
        writestep!(scheduler, rule)

        if rule.mode == :rewrite # symbolic replacement
            l = instantiate(egraph,rule.left,sub; skip_assert=true)
            r = instantiate(egraph,rule.right,sub)
            merge!(egraph,l.id,r.id)
        elseif rule.mode == :dynamic # execute the right hand!
            l = instantiate(egraph,rule.left,sub; skip_assert=true)
            (params, f) = rule.right_fun
            actual_params = map(params) do x
                (eclass, literal) = sub[x]
                literal != nothing ? literal : eclass
            end
            new = f(egraph, actual_params...)
            r = addexpr!(egraph, new)
            merge!(egraph,l.id,r.id)
        else
            error("unsupported rule mode")
        end
    end

    # display(egraph.parents); println()
    # display(egraph.M); println()
    saturated = isempty(egraph.dirty)
    rebuild!(egraph)
    return saturated, egraph
end

# TODO plot how egraph shrinks and grows during saturation
"""
Given an [`EGraph`](@ref) and a collection of rewrite rules,
execute the equality saturation algorithm.
"""
function saturate!(egraph::EGraph, theory::Vector{Rule};
    mod=@__MODULE__,
    timeout=0, stopwhen=(()->false), sizeout=2^12,
    scheduler::Type{<:AbstractScheduler}=BackoffScheduler)

    if timeout == 0
        timeout = length(theory)
    end

    curr_iter = 0

    # init the scheduler
    sched = scheduler(egraph, theory)
    saturated = false

    while true
        curr_iter+=1
        saturated, egraph = eqsat_step!(egraph, theory; scheduler=sched)

        cansaturate(sched) && saturated && (@log "E-GRAPH SATURATED"; break)
        curr_iter >= timeout && (@log "E-GRAPH TIMEOUT"; break)
        sizeout > 0 && length(egraph.U) > sizeout && (@log "E-GRAPH SIZEOUT"; break)
        stopwhen() && (@log "Halting requirement satisfied"; break)
    end
    return saturated, egraph
end


text:
import Base: Pair, Tuple, show, ==, hash
import LightGraphs: AbstractEdge, src, dst, reverse

abstract type AbstractSimpleEdge{T<:Integer} <: AbstractEdge{T} end

struct SimpleEdge{T<:Integer} <: AbstractSimpleEdge{T}
    src::T
    dst::T
end

SimpleEdge(t::Tuple) = SimpleEdge(t[1], t[2])
SimpleEdge(p::Pair) = SimpleEdge(p.first, p.second)
SimpleEdge{T}(p::Pair) where T<:Integer = SimpleEdge(T(p.first), T(p.second))
SimpleEdge{T}(t::Tuple) where T<:Integer = SimpleEdge(T(t[1]), T(t[2]))

eltype(::Type{<:ET}) where ET<:AbstractSimpleEdge{T} where T = T

# Accessors
src(e::AbstractSimpleEdge) = e.src
dst(e::AbstractSimpleEdge) = e.dst

# I/O
show(io::IO, e::AbstractSimpleEdge) = print(io, "Edge $(e.src) => $(e.dst)")

# Conversions
Pair(e::AbstractSimpleEdge) = Pair(src(e), dst(e))
Tuple(e::AbstractSimpleEdge) = (src(e), dst(e))

SimpleEdge{T}(e::AbstractSimpleEdge) where T <: Integer = SimpleEdge{T}(T(e.src), T(e.dst))

# Convenience functions
reverse(e::T) where T<:AbstractSimpleEdge = T(dst(e), src(e))
==(e1::AbstractSimpleEdge, e2::AbstractSimpleEdge) = (src(e1) == src(e2) && dst(e1) == dst(e2))
hash(e::AbstractSimpleEdge, h::UInt) = hash(src(e), hash(dst(e), h))


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule IVerilog_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("IVerilog")
JLLWrappers.@generate_main_file("IVerilog", UUID("985f9f6c-a11c-5717-b596-40558d7e7751"))
end  # module IVerilog_jll


text:
using Test
using CSV
using DataFrames
using Definitions
using Uprating
using Model_Household
using FRS_Household_Getter
include( "../src/data_mapping/hhld_from_frame.jl")
#
# Low-ish level tests of loading households from frames
#
@testset begin

    hhdata = CSV.File("$(MODEL_DATA_DIR)/model_households.tab", delim='\t') |> DataFrame
    nhhlds = size( hhdata )[1]
    hhpeople = CSV.File("$(MODEL_DATA_DIR)/model_people.tab", delim='\t') |> DataFrame
    some_pids = ((hhdata.hid.==1) .& (hhdata.data_year.==2017))
    npeople = size( hhpeople)[1]
    hhlds_a = Vector{Union{Missing,Household}}(missing,nhhlds)

    @time for h in 1:nhhlds
        hh1 = hhdata[h,:]
        mhh = map_hhld( hh1 )
        ## hhlds_a[h] = mhh
        if h % 10_000 == 0
            println( "$mhh")
        end
    end

    @time for p in 1:npeople
        p1 = hhpeople[p,:]
        mp = map_person( p1 )
        if p % 1_000 == 0
            println( "$mp")
        end
    end

    @time for h in 1:nhhlds
        hh1 = hhdata[h,:]
        mhh = load_hhld_from_frame( hh1, hhpeople )
        hhlds_a[h] = mhh
        if h % 10_000 == 0
            println( "$mhh")
        end
    end

    @time for h in 1:nhhlds
        uprate!( hhlds_a[h])
        if h % 10_000 == 0
            println( hhlds_a[h] )
        end
    end

    println(sizeof( hhlds_a ))

end