text:
module JuliaVariables

export Scope, Var
export solve_from_local, solve_from_local!, solve, solve!, simplify_ex

using NameResolution
using Base.Enums
using MLStyle

IdDict = Base.IdDict
Analyzer = NameResolution.Analyzer

include("SimplifyEx.jl")

# auxilliaries
find_line(ex::Expr) = begin
    for e in ex.args
        l = find_line(e)
        l !== nothing && return l
    end
end

find_line(e::LineNumberNode) = e
find_line(_) = nothing
error_ex(sym::Symbol, ex) =
    begin line = find_line(ex)
    locmsg = line === nothing ? "" : "$line: "
    error("$(locmsg)Malformed or non-canonicalized $sym expression")
end

@enum Ctx C_LOCAL C_GLOBAL C_LEXICAL
struct State
    ana::Union{Analyzer, Nothing}
    ctx::Ctx
    bound_inits::Set{Symbol}
end
State(ana::Analyzer, ctx::Ctx) = State(ana, ctx, Set{Symbol}())

mutable struct SymRef
    sym::Symbol
    ana::Union{Nothing, Analyzer}
    as_non_sym::Bool
    # as_non_sym = true : like for a key of namedtuples or argument keywords
end

function Base.show(io::IO, sym::SymRef)
    flag = ""
    if sym.ana === nothing
        flag *= "wild "
    end
    if sym.as_non_sym
        flag *= "nonsym "
    end
    print(io, "$(flag)$(sym.sym)")
end

SymRef(sym::Symbol, ana::Union{Nothing, Analyzer}) = SymRef(sym, ana, false)

struct Var
    name::Symbol
    is_mutable::Bool
    is_shared::Bool
    is_global::Bool
end

function Base.show(io::IO, var::Var)
    var.is_global && return print(io, "@global ", var.name)
    mut = var.is_mutable ? "mut " : ""
    var.is_shared && return print(io,  "$(mut)@shared ", var.name)
    print(io,  "$(mut)@local ", var.name)
end

macro _symref_func(N, n)
    quote
        $__source__
        function $N(symref::SymRef)
            $n(symref.ana, symref.sym)
        end
    end |> esc
end

@_symref_func ENTER! enter!
@_symref_func REQUIRE! require!
@_symref_func IS_LOCAL! is_local!
@_symref_func IS_GLOBAL! is_global!

const INPLACE_BIN_OP = (
    :(+=), :(-=), :(*=), :(/=), :(//=), :(%=), :(&=), :(|=), :(\=), :(^=))

is_broadcast_sym(sym) = begin
    s = string(sym)
    startswith(s, ".") && Base.isoperator(Symbol(s[1:end]))
end

is_broadcast_fusing(sym) = begin
    s = string(sym)
    endswith(s, "=") && startswith(s, ".")
end

function no_ana(ex)
    @match ex begin
        # inline
        Expr(:meta, _...)          ||
        # @label, @goto
        Expr(:symboliclabel, _...) ||
        Expr(:symbolicgoto, _...)  ||
        # @inbounds
        Expr(:inbounds, _...)      ||
        # @generated
        Expr(:generated, _...)     ||
        # @boundscheck
        Expr(:boundscheck, _...)   ||
        # @isdefined
        Expr(:isdefined, _...)     ||
        # @locals
        Expr(:locals) => true
        _ => false
    end
end

"""Process expressions with returning their scope.
The `solve!` function can only accept ASTs that
satifies following conditions:
- It's a *simplified* expression, which means `JuliaVariables.simplify_ex`
  will have no effects on the expression. You can check the very concise code
  of `JuliaVariables.simplify_ex` to understand the simplification rules.
- No macros included in the expression, as we don't know how much a macro
  could change the code.
"""
function solve!(ast; toplevel=true)
    S = Ref(State(top_analyzer(), C_LEXICAL, Set{Symbol}()))
    ScopeInfo = IdDict{Expr,Any}()
    PHYSICAL = true
    PSEUDO = false
    IS_BOUND_INIT = Ref(false)

    @nospecialize
    function LHS(ex)
        syms = rule(ex)
        st = S[]
        st.ctx ===
            C_LOCAL ?
            IS_LOCAL!.(syms) :
        st.ctx ===
            C_GLOBAL ?
            IS_GLOBAL!.(syms) :
            nothing
        ENTER!.(syms)
        REQUIRE!.(syms)
        IS_BOUND_INIT[] && return for sym in syms
            sym.as_non_sym = true
            push!(st.bound_inits, sym.sym)
        end
    end

    function RHS(ex)
        syms = rule(ex)
        REQUIRE!.(syms)
    end

    function LOCAL()
        s = S[]
        S[] = State(s.ana, C_LOCAL, s.bound_inits)
        nothing
    end

    function LOCAL(ex)
        syms = rule(ex)
        IS_LOCAL!.(syms)
        REQUIRE!.(syms)
    end

    function GLOBAL()
        s = S[]
        S[] = State(s.ana, C_GLOBAL, s.bound_inits)
        nothing
    end

    function GLOBAL(ex)
        syms = rule(ex)
        IS_GLOBAL!.(syms)
        REQUIRE!.(syms)
    end

    function CHILD(st::State, p::Bool)
        ana = st.ana
        new_ana = child_analyzer!(ana, p)
        State(new_ana, C_LEXICAL)
    end

    function WITH_STATE(f::Function)
        S_ = S[]
        try
            f()
        finally
            S[] = S_
        end
    end

    function WITH_STATE(f::Function, st::State)
        S_ = S[]
        S[] = st
        try
            f()
        finally
            S[] = S_
        end
    end

    function LOCAL_LHS(st, ex)
        WITH_STATE(st) do
            LOCAL()
            ns = IS_BOUND_INIT[]
            try
                IS_BOUND_INIT[] = true
                LHS(ex)
            finally
                IS_BOUND_INIT[] = ns
            end
        end
    end

    LHS(st, ex) = WITH_STATE(st) do; LHS(ex) end
    RHS(st, ex) = WITH_STATE(st) do; RHS(ex) end
    LOCAL(st, ex) = WITH_STATE(st) do; LOCAL(ex) end
    GLOBAL(st, ex) = WITH_STATE(st) do; GLOBAL(ex) end
    LOCAL_LHS(ex) = LOCAL_LHS(S[], ex)

    @specialize

    function IS_SCOPED(st::State, ex::Expr)
        ScopeInfo[ex] =(st.ana.solved.bounds, st.ana.solved.freevars, st.bound_inits)
    end

    rule(_) = SymRef[]
    rule(sym::Symbol) =
        error("An immutable Symbol cannot be analyzed. Transform them to SymRefs.")
    rule(sym::SymRef) = begin
        sym.ana = S[].ana; SymRef[sym]
    end
    rule(ex::Expr)::Vector{SymRef} =
        @when (_ && if no_ana(ex) end) = nothing begin
            SymRef[]
        @when Expr(:let, :($a = $b), body) = ex
            S₀ = S[]
            S₁ = CHILD(S₀, PSEUDO)
            RHS(S₀, b)
            LOCAL_LHS(S₁, a)
            RHS(S₁, body)
            S[] = S₀
            IS_SCOPED(S₁, body)
            SymRef[]

        @when Expr(:let, a::SymRef, body) = ex
            S₀ = S[]
            S₁ = CHILD(S₀, PSEUDO)
            LOCAL(S₁, a)
            RHS(S₁, body)
            IS_SCOPED(S₁, body)
            S[] = S₀
            SymRef[]

        @when Expr(:let, Expr(:block), body) = ex
            S₀ = S[]
            S₁ = CHILD(S₀, PSEUDO)
            RHS(S₁, body)
            IS_SCOPED(S₁, body)
            S[] = S₀
            SymRef[]

        @when Expr(:let, seq, body) = ex
            error_ex(:let, seq)

# assign is canonicalized, thus cannot be a function
        @when Expr(:(=), lhs, rhs) = ex
            @when Expr(:call, _...) = lhs begin error_ex(:(=), ex) end
            LHS(lhs)
            RHS(rhs)
            SymRef[]

# broadcast fusing
        @when Expr(hd && if is_broadcast_fusing(hd) end, lhs, rhs) = ex
            RHS(lhs)
            RHS(rhs)
            SymRef[]

# addition assignment, https://github.com/thautwarm/JuliaVariables.jl/issues/6
        @when Expr(hd && if hd in INPLACE_BIN_OP end, lhs, rhs) = ex
            LHS(lhs)
            RHS(rhs)
            SymRef[]

# broadcasting symbols
        @when (
            Expr(:call, f :: SymRef, args...) &&
                if length(args) in (1, 2) && is_broadcast_sym(f.sym)
                end
            ) = ex
            f.as_non_sym = true
            RHS.(args)
            Symbol[]
# namedtuple
# https://github.com/thautwarm/GG.jl/issues/8
        @when Expr(:tuple, elts...) = ex
            syms = SymRef[]
            for elt in elts
                sym_ex = @when :($a = $b) = elt begin
                    a isa SymRef || error("invalid namedtuple")
                    a.as_non_sym = true
                    b
                @otherwise
                    elt
                end
                append!(syms, rule(sym_ex))
            end
            syms

        @when Expr(:where, t, tps...) = ex
            S₁ = CHILD(S[], PSEUDO)
            for tp in tps
                @match tp begin
                :($a >: $b) || :($a <: $b) => begin LOCAL_LHS(S₁, a); RHS(S₁, b) end
                :($a >: $b >: $c) ||
                :($a <: $b <: $c) => begin RHS(S₁, a); LOCAL_LHS(S₁, b); RHS(S₁, c) end
                ::SymRef => begin LOCAL_LHS(S₁, tp) end
                _ => error_ex(:where, ex)
                end
            end
            RHS(S[], t)
            SymRef[]

        @when Expr(:kw, k, v) = ex
            k isa SymRef || error("invalid keyword argument")
            k.as_non_sym = true
            rule(v)

        @when Expr(:for, :($i = $I), body) = ex
            S₀ = S[]
            S₁ = CHILD(S₀, PSEUDO)
            IS_SCOPED(S₁, body)
            RHS(S₀, I)
            LOCAL_LHS(S₁, i)
            RHS(S₁, body)
            SymRef[]

        @when Expr(:while, cond, body) = ex
            S₀ = S[]
            S₁ = CHILD(S₀, PSEUDO)
            IS_SCOPED(S₁, body)
            RHS(S₀, cond)
            RHS(S₁, body)
            SymRef[]

        @when Expr(:local, args...) = ex
            WITH_STATE() do
                LOCAL()
                for arg in args
                    LOCAL(arg)
                end
            end
            SymRef[]

        @when Expr(:global, args...) = ex
            WITH_STATE() do
                GLOBAL()
                for arg in args
                    GLOBAL(arg)
                end
            end
            SymRef[]

        @when Expr(:function, header, body) = ex
            left = header
            S₀ = S[]
            S₁ = CHILD(S₀, PSEUDO)
            S₂ = CHILD(S₁, PHYSICAL)
            IS_SCOPED(S₂, body)

            # check type parameters
            @when :($left_ where {$(freshes...)}) = left begin
                S[] = S₁
                for decl in freshes
                        @match decl begin
                        :($a >: $b) || :($a <: $b) => begin LOCAL_LHS(a); LOCAL_LHS(S₂, a); RHS(b) end
                        :($a >: $b >: $c) ||
                        :($a <: $b <: $c) => begin RHS(a); LOCAL_LHS(b); LOCAL_LHS(S₂, b); RHS(c) end
                        ::SymRef => begin LOCAL_LHS(decl); LOCAL_LHS(S₂, decl) end
                        _ => error_ex(:where, ex)
                    end
                end
                left = left_;nothing
            end

            # check return type
            @when :($left_::$t) = left begin
                RHS(S₁, t)
                left = left_;nothing
            end

            # check function name
            args = @match left begin
                Expr(:call, f, args...) => begin LHS(S₀, f); args end
                Expr(:tuple, args...)   => args
                # declaration
                ::Symbol => []
                _ => error_ex(:function, ex)
            end

            # check args
            function visit_arg(arg)
                @nospecialize arg
                @when (:($arg_ = $default) || Expr(:kw, arg_, default)) = arg begin
                    RHS(S₂, default)
                    arg = arg_
                end
                @when :($arg_::$t) = arg begin
                    RHS(S₁, t)
                    arg = arg_
                end
                LOCAL_LHS(S₂, arg)
            end
            for arg in args
                @when Expr(:parameters, kwargs...) = arg begin
                    foreach(visit_arg, kwargs)
                @otherwise
                    visit_arg(arg)
                end
            end
            RHS(S₂, body)
            S[] = S₀
            SymRef[]

        @when Expr(_, args...) = ex
            syms = SymRef[]
            for each in args
                append!(syms, rule(each))
            end
            syms
        end

    function local_var_to_var(var::LocalVar)::Var
        Var(var.sym, var.is_mutable[], var.is_shared[], false)
    end

    function to_symref(ex::Expr)
        args = ex.args
        for i = 1:length(args)
            args[i] = to_symref(args[i])
        end
        ex
    end

    function to_symref(s::Symbol)
        SymRef(s, nothing)
    end

    to_symref(@nospecialize(l)) = l

    function from_symref(ex::Expr)
        args = ex.args
        for i = 1:length(args)
            args[i] = from_symref(args[i])
        end
        haskey(ScopeInfo, ex) && return begin
            triple = ScopeInfo[ex]
            scope_info = (
                bounds = Var[local_var_to_var(v) for (_, v) = triple[1]],
                freevars = Var[local_var_to_var(v) for (_, v) = triple[2]],
                bound_inits = Symbol[triple[3]...]
            )
            Expr(:scoped, scope_info, ex)
        end
        ex
    end

    function from_symref(s::SymRef)
        s.as_non_sym && return s.sym
        s.ana === nothing && return Var(s.sym, true, true, true)
        var = s.ana.solved[s.sym]
        var isa Symbol && return Var(var, true, true, true)
        local_var_to_var(var)
    end

    from_symref(s::Symbol) =
        error("An immutable Symbol cannot be analyzed. Transform them to SymRefs.")

    from_symref(l) = l

    function transform(@nospecialize(ex))
        ex = to_symref(ex)
        if toplevel
            GLOBAL()
        end
        IS_SCOPED(S[], ex)
        rule(ex)
        ana = S[].ana
        run_analyzer(ana)
        from_symref(ex)
    end

    transform(ast)
end # module struct

solve_from_local!(@nospecialize(ex)) = solve!(ex; toplevel=false)

_depwarn(sym) = Base.depwarn(
    "`$sym(ex)` is deprecated in JuliaVariables 0.2.x. " *
    "Please use `$(sym)!(ex)` instead.  `$sym(ex)`, which currently mutates `ex` " *
    "in-place, will be re-introduced in 0.3 as a non-mutating variant.",
    sym,
)

function solve(@nospecialize(ex))
    _depwarn(:solve)
    solve!(ex)
end

function solve_from_local(@nospecialize(ex))
    _depwarn(:solve_from_local)
    solve_from_local!(ex)
end

end # module


text:
# This file is part of the StateMachines.jl Julia package
#
# Paul Bayer
# MIT License
# Github: https://github.com/pbayer/StateMachines.jl
#

ext: jl


text:
export doAdd
"""
    doAdd(a, b)

Compute the sum of two numbers a,b and return the result

# Examples
```julia-repl
julia> doAdd(1.0, 2.0)
3.0
```
"""
doAdd(a, b) = nothing

max_stars_repo_name: sonolac/JuliaInterface

max_issues_repo_name: sonolac/JuliaInterface

max_forks_repo_name: sonolac/JuliaInterface


text:
using Test
using YaoBlocks.AD
using YaoBlocks, YaoArrayRegister
using Random

@testset "apply put" begin
    Random.seed!(5)
    for reg0 in [rand_state(3), rand_state(3, nbatch = 10)]
        # put block, diagonal
        @test test_apply_back(reg0, put(3, 1 => shift(0.5)), 0.5; δ = 1e-5)
        @test test_apply_back(reg0, control(3, (2, 3), 1 => Rz(0.5)), 0.5; δ = 1e-5)
        @test test_apply_back(reg0, control(3, 2, 1 => shift(0.5)), 0.5; δ = 1e-5)
        # dense matrix
        @test test_apply_back(reg0, put(3, 1 => cache(Rx(0.5))), 0.5; δ = 1e-5)
        @test test_apply_back(reg0, put(3, 1 => chain(Rz(0.5), Rx(0.8))), [0.5, 0.8]; δ = 1e-5)
        @test test_apply_back(reg0, control(3, (2, 3), 1 => Rx(0.5)), 0.5; δ = 1e-5)
        # sparse matrix csc
        @test test_apply_back(reg0, put(3, (1, 2) => rot(SWAP, 0.5)), 0.5; δ = 1e-5)
        @test test_apply_back(reg0, control(3, (3,), (1, 2) => rot(SWAP, 0.5)), 0.5; δ = 1e-5)

        # special cases: DiffBlock
        @test test_apply_back(reg0, put(3, 1 => Rz(0.5)), 0.5; δ = 1e-5)
        @test test_apply_back(reg0, put(3, 1 => Rx(0.5)), 0.5; δ = 1e-5)
        @test test_apply_back(rand_state(1), Rx(0.0), 0.5; δ = 1e-5)

        # TimeEvolution
        @test test_apply_back(reg0, TimeEvolution(put(3, 1 => X), 0.5), 0.5; δ = 1e-5)
    end
end

@testset "apply chain" begin
    Random.seed!(5)
    for reg0 in [rand_state(3), rand_state(3, nbatch = 10)]
        @test test_apply_back(
            reg0,
            chain(3, put(3, 1 => shift(0.0)), control(3, (2, 3), 1 => Rz(0.0))),
            [0.5, 0.5];
            δ = 1e-5,
        )
        c = chain(3, put(3, 1 => shift(0.0)), NoParams(control(3, (2, 3), 1 => Rz(0.0))))
        @test nparameters(c) == 1
        @test test_apply_back(reg0, c, 0.5; δ = 1e-5)
    end
end

@testset "apply dagger, scale" begin
    Random.seed!(5)
    for reg0 in [rand_state(3), rand_state(3, nbatch = 10)]
        @test test_apply_back(
            reg0,
            chain(put(3, 1 => Rx(0.0)), (3 + 2im) * control(3, (2, 3), 1 => Rz(0.0))),
            [0.5, 0.5];
            δ = 1e-5,
        )
        @test test_apply_back(reg0, Daggered(put(3, 1 => Rx(0.0))), 0.5; δ = 1e-5)
        @test test_apply_back(reg0, control(3, (2, 3), 1 => Daggered(Rz(0.0))), 0.5; δ = 1e-5)
        @test test_apply_back(
            reg0,
            chain(3, Daggered(put(3, 1 => Rx(0.0))), control(3, (2, 3), 1 => Daggered(Rz(0.0)))),
            [0.5, 0.5];
            δ = 1e-5,
        )
    end
end

@testset "apply concentrate" begin
    Random.seed!(5)
    for reg0 in [rand_state(3), rand_state(3, nbatch = 10)]
        @test test_apply_back(
            reg0,
            chain(3, put(3, 1 => Rx(0.0)), concentrate(3, control(2, 2, 1 => shift(0.0)), (3, 1))),
            [0.5, 0.5];
            δ = 1e-5,
        )
    end
end

@testset "apply kron repeated" begin
    Random.seed!(5)
    for reg0 in [rand_state(3), rand_state(3, nbatch = 10)]
        @test test_apply_back(
            reg0,
            chain(3, put(3, 1 => Rx(0.0)), kron(Rx(0.4), Y, Rz(0.5))),
            [0.5, 0.3, 0.8];
            δ = 1e-5,
        )
        @test test_apply_back(
            reg0,
            chain(repeat(3, Rx(0.5), 1:2), repeat(3, Ry(0.6), 2:3)),
            [0.5, 0.8];
            δ = 1e-5,
        )
        @test test_apply_back(
            reg0,
            chain(repeat(3, H, 1:2), repeat(3, Ry(0.6), 2:3)),
            [0.8];
            δ = 1e-5,
        )
    end
end

@testset "apply Add" begin
    # + is not reversible
    for reg0 in [rand_state(3), rand_state(3, nbatch = 10)]
        @test_broken test_apply_back(
            reg0,
            (3 * control(3, (2, 3), 1 => Rz(0.0)) + put(3, 2 => Rx(0.0))) / 5,
            [0.5, 0.5];
            δ = 1e-5,
            in = copy(reg0),
        )
    end
end

AA(i, j) = control(i, j => shift(2π / (1 << (i - j + 1))))
B(n, i) = chain(n, i == j ? put(i => H) : AA(j, i) for j in i:n)
qft(n) = chain(B(n, i) for i in 1:n)

@testset "system test" begin
    nbit = 4
    c = qft(nbit)
    H = repeat(nbit, X, 1:nbit)
    adjin, adjparams = expect'(H, zero_state(nbit) => c)
    numgrad = YaoBlocks.AD.ng(x -> expect(H, zero_state(nbit) |> dispatch!(c, x)), parameters(c))
    @test adjparams ≈ vec(numgrad)
end


text:
function fft_axis(fxn::Function, axis::AbstractAxis, inds::AbstractUnitRange)
    return assign_indices(axis, inds)  # default
end

@inline function fft_axes(fxn::Function, axs::Tuple, inds::Tuple, dims::Tuple, cnt::Int=1)
    if first(dims) === cnt
        return (fft_axis(fxn, first(axs), first(inds)),
                fft_axes(fxn, tail(axs), tail(inds), tail(dims), cnt + 1)...)
    else
        return (assign_indices(first(axs), first(inds)),
                fft_axes(fxn, tail(axs), tail(inds), dims, cnt + 1)...)
    end
end
fft_axes(fxn::Function, axs::Tuple, inds::Tuple, dims::Tuple{}, cnt::Int=1) = map(assign_indices, axs, inds)
fft_axes(fxn::Function, axs::Tuple{}, inds::Tuple{}, dims::Tuple{}, cnt::Int=1) = ()

_try_tuple(dim::Integer) = (dim,)
_try_tuple(dim::Tuple) = dim

for f in (:fft, :ifft, :bfft)
    @eval begin
        function AbstractFFTs.$f(A::AxisArray, dims)
            p = AbstractFFTs.$f(parent(A), dims)
            axs = fft_axes(AbstractFFTs.$f, axes(A), axes(p), _try_tuple(dims))
            return unsafe_reconstruct(A, p; axes=axs)
        end
    end
end


text:
using NoisyNeuron, Test

println("Let's test things")

@testset "point" begin
  @test length(point_white_steady_test()) == 2
  @test length(point_white_cmod_test()) == 2
  @test length(point_white_vmod_test()) == 2
end

@testset "cable" begin
  @test length(sealed_white_steady_var_test()) == 3
  @test length(sealed_colour_steady_var_test()) == 5
end

max_stars_repo_name: rpgowers/NoisyNeuron

max_issues_repo_name: rpgowers/NoisyNeuron

max_forks_repo_name: rpgowers/NoisyNeuron


text:
# test_table_function.jl

struct MyBindStruct
    count::Int64

    function MyBindStruct(count::Int64)
        return new(count)
    end
end

function my_bind_function(info::DuckDB.BindInfo)
    DuckDB.add_result_column(info, "forty_two", Int64)

    parameter = DuckDB.get_parameter(info, 0)
    number = DuckDB.getvalue(parameter, Int64)
    return MyBindStruct(number)
end

mutable struct MyInitStruct
    pos::Int64

    function MyInitStruct()
        return new(0)
    end
end

function my_init_function(info::DuckDB.InitInfo)
    return MyInitStruct()
end

function my_main_function(info::DuckDB.FunctionInfo, output::DuckDB.DataChunk)
    bind_info = DuckDB.get_bind_info(info, MyBindStruct)
    init_info = DuckDB.get_init_info(info, MyInitStruct)

    result_array = DuckDB.get_array(output, 1, Int64)
    count = 0
    for i in 1:(DuckDB.VECTOR_SIZE)
        if init_info.pos >= bind_info.count
            break
        end
        result_array[count + 1] = init_info.pos % 2 == 0 ? 42 : 84
        count += 1
        init_info.pos += 1
    end

    DuckDB.set_size(output, count)
    return
end

function my_main_function_nulls(info::DuckDB.FunctionInfo, output::DuckDB.DataChunk)
    bind_info = DuckDB.get_bind_info(info, MyBindStruct)
    init_info = DuckDB.get_init_info(info, MyInitStruct)

    result_array = DuckDB.get_array(output, 1, Int64)
    validity = DuckDB.get_validity(output, 1)
    count = 0
    for i in 1:(DuckDB.VECTOR_SIZE)
        if init_info.pos >= bind_info.count
            break
        end
        if init_info.pos % 2 == 0
            result_array[count + 1] = 42
        else
            DuckDB.setinvalid(validity, count + 1)
        end
        count += 1
        init_info.pos += 1
    end

    DuckDB.set_size(output, count)
    return
end

@testset "Test custom table functions" begin
    con = DBInterface.connect(DuckDB.DB)

    DuckDB.create_table_function(con, "forty_two", [Int64], my_bind_function, my_init_function, my_main_function)
    GC.gc()

    # 3 elements
    results = DBInterface.execute(con, "SELECT * FROM forty_two(3)")
    GC.gc()

    df = DataFrame(results)
    @test names(df) == ["forty_two"]
    @test size(df, 1) == 3
    @test df.forty_two == [42, 84, 42]

    # > vsize elements
    results = DBInterface.execute(con, "SELECT COUNT(*) cnt FROM forty_two(10000)")
    GC.gc()

    df = DataFrame(results)
    @test df.cnt == [10000]

    # 	@time begin
    # 		results = DBInterface.execute(con, "SELECT SUM(forty_two) cnt FROM forty_two(10000000)")
    # 	end
    # 	df = DataFrame(results)
    # 	println(df)

    # return null values from a table function
    DuckDB.create_table_function(
        con,
        "forty_two_nulls",
        [Int64],
        my_bind_function,
        my_init_function,
        my_main_function_nulls
    )
    results = DBInterface.execute(con, "SELECT COUNT(*) total_cnt, COUNT(forty_two) cnt FROM forty_two_nulls(10000)")
    df = DataFrame(results)
    @test df.total_cnt == [10000]
    @test df.cnt == [5000]

    # 	@time begin
    # 		results = DBInterface.execute(con, "SELECT SUM(forty_two) cnt FROM forty_two_nulls(10000000)")
    # 	end
    # 	df = DataFrame(results)
    # 	println(df)
end

function my_bind_error_function(info::DuckDB.BindInfo)
    throw("bind error")
end

function my_init_error_function(info::DuckDB.InitInfo)
    throw("init error")
end

function my_main_error_function(info::DuckDB.FunctionInfo, output::DuckDB.DataChunk)
    throw("runtime error")
end

@testset "Test table function errors" begin
    con = DBInterface.connect(DuckDB.DB)

    DuckDB.create_table_function(
        con,
        "bind_error_function",
        [Int64],
        my_bind_error_function,
        my_init_function,
        my_main_function
    )
    DuckDB.create_table_function(
        con,
        "init_error_function",
        [Int64],
        my_bind_function,
        my_init_error_function,
        my_main_function
    )
    DuckDB.create_table_function(
        con,
        "main_error_function",
        [Int64],
        my_bind_function,
        my_init_function,
        my_main_error_function
    )

    @test_throws DuckDB.QueryException DBInterface.execute(con, "SELECT * FROM bind_error_function(3)")
    @test_throws DuckDB.QueryException DBInterface.execute(con, "SELECT * FROM init_error_function(3)")
    @test_throws DuckDB.QueryException DBInterface.execute(con, "SELECT * FROM main_error_function(3)")
end

max_stars_repo_name: lokax/duckdb

max_issues_repo_name: lokax/duckdb

max_forks_repo_name: lokax/duckdb


text:
################################################################################
#  Copyright 2021, Marta Vanin                                                 #
################################################################################
function add_some_noise!(data::Dict)
    Random.seed!(1)
    err_array = 1e-6:1e-6:2e-6
    for (_, meas) in data["meas"]
        σ = _DST.std.(meas["dst"])
        μ = _DST.mean.(meas["dst"])
        new_μ = [μ[i]*(1+rand(err_array)) for i in 1:length(meas["dst"])]
        meas["dst"] = [_DST.Normal(new_μ[i], σ[i]) for i in 1:length(meas["dst"])]
    end
end

function add_errors!(data::Dict; seed::Int64=1)
    for (m, meas) in data["meas"]
        σ = [_DST.std(meas["dst"][i]) for i in 1:length(meas["dst"])]
        new_μ = [_RAN.rand(_RAN.seed!(seed+parse(Int64,m)+i), _DST.Normal(_DST.mean(meas["dst"][i]), _DST.std(meas["dst"][i]))) for i in 1:length(meas["dst"])]
        meas["dst"] = [_DST.Normal(new_μ[i], σ[i]) for i in 1:length(σ)]
    end
end


text:
function constant_contractor(X, y_val)
    x, y = X
    y = y ∩ Interval(y_val)
    return IntervalBox(x, y)
end

"Contractor for y = x^2, x >= 0"
function square_pos(X::IntervalBox)

    x, y = X

    x = x ∩ (0..∞)

    y = y ∩ (x^2)
    x = x ∩ √y

    return IntervalBox(x, y)
end

square_neg = symmetrise(square_pos, reflect_x(0.0))
square!(X::IntervalBox) = square_pos(X) ∪ square_neg(X)

function cube_pos(X::IntervalBox)  # contractor for y=x^3, x>=0

    x, y = X

    x = x ∩ (0..∞)

    y = y ∩ (x ^ 3)
    x = x ∩ Interval(y.lo ^ (1/3), y.hi^(1/3))   # not rigorous!

    return x × y
end

cube_neg = symmetrise(cube_pos, odd)
cube!(X::IntervalBox) = cube_pos(X) ∪ cube_neg(X)


text:
module TestGtkMegaJLL

using Pkg, Pkg.BinaryPlatforms, Pkg.Artifacts, Libdl
import Base: UUID

# We put these inter-JLL-package API values here so that they are always defined, even if there
# is no underlying wrapper held within this JLL package.
const PATH_list = String[]
const LIBPATH_list = String[]

# # Load Artifacts.toml file
artifacts_toml = joinpath(@__DIR__, "..", "Artifacts.toml")

# Extract all platforms
artifacts = Pkg.Artifacts.load_artifacts_toml(artifacts_toml; pkg_uuid=UUID("05f542c5-fd2e-4f6f-a354-1fd7cae9a8d6"))
platforms = [Pkg.Artifacts.unpack_platform(e, "ATK", artifacts_toml) for e in artifacts["ATK"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Bzip2", artifacts_toml) for e in artifacts["Bzip2"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Cairo", artifacts_toml) for e in artifacts["Cairo"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Dbus", artifacts_toml) for e in artifacts["Dbus"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Expat", artifacts_toml) for e in artifacts["Expat"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Fontconfig", artifacts_toml) for e in artifacts["Fontconfig"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "FreeType2", artifacts_toml) for e in artifacts["FreeType2"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "FriBidi", artifacts_toml) for e in artifacts["FriBidi"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "GTK3", artifacts_toml) for e in artifacts["GTK3"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Gettext", artifacts_toml) for e in artifacts["Gettext"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Glib", artifacts_toml) for e in artifacts["Glib"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Graphene", artifacts_toml) for e in artifacts["Graphene"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Graphite2", artifacts_toml) for e in artifacts["Graphite2"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "HarfBuzz", artifacts_toml) for e in artifacts["HarfBuzz"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "JpegTurbo", artifacts_toml) for e in artifacts["JpegTurbo"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "LZO", artifacts_toml) for e in artifacts["LZO"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libepoxy", artifacts_toml) for e in artifacts["Libepoxy"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libffi", artifacts_toml) for e in artifacts["Libffi"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libgcrypt", artifacts_toml) for e in artifacts["Libgcrypt"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libglvnd", artifacts_toml) for e in artifacts["Libglvnd"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libgpg_error", artifacts_toml) for e in artifacts["Libgpg_error"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libiconv", artifacts_toml) for e in artifacts["Libiconv"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libtiff", artifacts_toml) for e in artifacts["Libtiff"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Libuuid", artifacts_toml) for e in artifacts["Libuuid"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "PCRE", artifacts_toml) for e in artifacts["PCRE"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Pango", artifacts_toml) for e in artifacts["Pango"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Pixman", artifacts_toml) for e in artifacts["Pixman"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Wayland", artifacts_toml) for e in artifacts["Wayland"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Wayland_protocols", artifacts_toml) for e in artifacts["Wayland_protocols"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "X11", artifacts_toml) for e in artifacts["X11"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "XML2", artifacts_toml) for e in artifacts["XML2"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "XSLT", artifacts_toml) for e in artifacts["XSLT"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_compositeproto", artifacts_toml) for e in artifacts["Xorg_compositeproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_damageproto", artifacts_toml) for e in artifacts["Xorg_damageproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_fixesproto", artifacts_toml) for e in artifacts["Xorg_fixesproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_glproto", artifacts_toml) for e in artifacts["Xorg_glproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_inputproto", artifacts_toml) for e in artifacts["Xorg_inputproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_kbproto", artifacts_toml) for e in artifacts["Xorg_kbproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libX11", artifacts_toml) for e in artifacts["Xorg_libX11"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXau", artifacts_toml) for e in artifacts["Xorg_libXau"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXcomposite", artifacts_toml) for e in artifacts["Xorg_libXcomposite"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXcursor", artifacts_toml) for e in artifacts["Xorg_libXcursor"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXdamage", artifacts_toml) for e in artifacts["Xorg_libXdamage"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXdmcp", artifacts_toml) for e in artifacts["Xorg_libXdmcp"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXext", artifacts_toml) for e in artifacts["Xorg_libXext"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXfixes", artifacts_toml) for e in artifacts["Xorg_libXfixes"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXi", artifacts_toml) for e in artifacts["Xorg_libXi"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXinerama", artifacts_toml) for e in artifacts["Xorg_libXinerama"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXrandr", artifacts_toml) for e in artifacts["Xorg_libXrandr"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXrender", artifacts_toml) for e in artifacts["Xorg_libXrender"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libXtst", artifacts_toml) for e in artifacts["Xorg_libXtst"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libpthread_stubs", artifacts_toml) for e in artifacts["Xorg_libpthread_stubs"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libxcb", artifacts_toml) for e in artifacts["Xorg_libxcb"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_libxkbfile", artifacts_toml) for e in artifacts["Xorg_libxkbfile"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_randrproto", artifacts_toml) for e in artifacts["Xorg_randrproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_recordproto", artifacts_toml) for e in artifacts["Xorg_recordproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_renderproto", artifacts_toml) for e in artifacts["Xorg_renderproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_util_macros", artifacts_toml) for e in artifacts["Xorg_util_macros"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_xcb_proto", artifacts_toml) for e in artifacts["Xorg_xcb_proto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_xextproto", artifacts_toml) for e in artifacts["Xorg_xextproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_xineramaproto", artifacts_toml) for e in artifacts["Xorg_xineramaproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_xkbcomp", artifacts_toml) for e in artifacts["Xorg_xkbcomp"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_xkeyboard_config", artifacts_toml) for e in artifacts["Xorg_xkeyboard_config"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_xproto", artifacts_toml) for e in artifacts["Xorg_xproto"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Xorg_xtrans", artifacts_toml) for e in artifacts["Xorg_xtrans"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Zlib", artifacts_toml) for e in artifacts["Zlib"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "Zstd", artifacts_toml) for e in artifacts["Zstd"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "adwaita_icon_theme", artifacts_toml) for e in artifacts["adwaita_icon_theme"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "at_spi2_atk", artifacts_toml) for e in artifacts["at_spi2_atk"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "at_spi2_core", artifacts_toml) for e in artifacts["at_spi2_core"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "gdk_pixbuf", artifacts_toml) for e in artifacts["gdk_pixbuf"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "hicolor_icon_theme", artifacts_toml) for e in artifacts["hicolor_icon_theme"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "iso_codes", artifacts_toml) for e in artifacts["iso_codes"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "libpng", artifacts_toml) for e in artifacts["libpng"]]
platforms = [Pkg.Artifacts.unpack_platform(e, "xkbcommon", artifacts_toml) for e in artifacts["xkbcommon"]]

# Filter platforms based on what wrappers we've generated on-disk
platforms = filter(p -> isfile(joinpath(@__DIR__, "wrappers", triplet(p) * ".jl")), platforms)

# From the available options, choose the best platform
best_platform = select_platform(Dict(p => triplet(p) for p in platforms))

# Silently fail if there's no binaries for this platform
if best_platform === nothing
    @debug("Unable to load TestGtkMegaJLL; unsupported platform $(triplet(platform_key_abi()))")
else
    # Load the appropriate wrapper
    include(joinpath(@__DIR__, "wrappers", "x86_64-linux-gnu.jl"))
end

end # module


text:
const _get_bert_config = Dict(
    "uncased_L-12_H-768_A-12" => Dict(
        :host => :google,
        :case => :uncased,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "uncased_L-12_H-768_A-12",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "uncased_L-24_H-1024_A-16" => Dict(
        :host => :google,
        :case => :uncased,
        :layer => 24,
        :hidden => 1024,
        :head => 16,
        :wwm => false,
        :name => "uncased_L-24_H-1024_A-16",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "wwm_cased_L-24_H-1024_A-16" => Dict(
        :host => :google,
        :case => :cased,
        :layer => 24,
        :hidden => 1024,
        :head => 16,
        :wwm => true,
        :name => "wwm_cased_L-24_H-1024_A-16",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "wwm_uncased_L-24_H-1024_A-16" => Dict(
        :host => :google,
        :case => :cased,
        :layer => 24,
        :hidden => 1024,
        :head => 16,
        :wwm => true,
        :name => "wwm_uncased_L-24_H-1024_A-16",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "multilingual_L-12_H-768_A-12" => Dict(
        :host => :google,
        :case => :multilingual,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "multilingual_L-12_H-768_A-12",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "multi_cased_L-12_H-768_A-12" => Dict(
        :host => :google,
        :case => :multi_cased,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "multi_cased_L-12_H-768_A-12",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "chinese_L-12_H-768_A-12" => Dict(
        :host => :google,
        :case => :chinese,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "chinese_L-12_H-768_A-12",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "cased_L-24_H-1024_A-16" => Dict(
        :host => :google,
        :case => :cased,
        :layer => 24,
        :hidden => 1024,
        :head => 16,
        :wwm => false,
        :name => "cased_L-24_H-1024_A-16",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "cased_L-12_H-768_A-12" => Dict(
        :host => :google,
        :case => :cased,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "cased_L-12_H-768_A-12",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "scibert_scivocab_uncased" => Dict(
        :host => :allenai,
        :case => :cased,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "scibert_scivocab_uncased",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "scibert_scivocab_cased" => Dict(
        :host => :allenai,
        :case => :cased,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "scibert_scivocab_cased",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "scibert_basevocab_uncased" => Dict(
        :host => :allenai,
        :case => :cased,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "scibert_basevocab_uncased",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
    "scibert_basevocab_cased" => Dict(
        :host => :allenai,
        :case => :cased,
        :layer => 12,
        :hidden => 768,
        :head => 12,
        :wwm => false,
        :name => "scibert_basevocab_cased",
        :items => (:bert_model, :wordpiece, :tokenizer)
    ),
)

function bert_init()
    for (model, url, cksum) ∈ zip(
        ("uncased_L-12_H-768_A-12",
         "uncased_L-24_H-1024_A-16",
         "wwm_cased_L-24_H-1024_A-16",
         "wwm_uncased_L-24_H-1024_A-16",
         "multilingual_L-12_H-768_A-12",
         "multi_cased_L-12_H-768_A-12",
         "chinese_L-12_H-768_A-12",
         "cased_L-24_H-1024_A-16",
         "cased_L-12_H-768_A-12",
         "scibert_scivocab_uncased",
         "scibert_scivocab_cased",
         "scibert_basevocab_uncased",
         "scibert_basevocab_cased",
         ),
        ("https://drive.google.com/uc?export=download&id=1X-p84u7LDEJlhAnDXnyrXbbFo9Y0UBzu",
         "https://drive.google.com/uc?export=download&id=1IR7RWI2ZORzR7JmPSPrUtZk9jdcOm0Na",
         "https://drive.google.com/uc?export=download&id=1sqVrc_PdhYQzdt903yvx7OROtmpjRLUi",
         "https://drive.google.com/uc?export=download&id=1FrpWNCIgVCNGTF-rlU8_3oj1Xp4S94e9",
         "https://drive.google.com/uc?export=download&id=1BJUHaVkpnDL71VlVJS2yRjNF72l1LmWD",
         "https://drive.google.com/uc?export=download&id=1teAmrvOqJfyEa2yYFyNLW7M8JOmg-4sn",
         "https://drive.google.com/uc?export=download&id=14OaijyaNjpK69-Oh7NddIXFlLrgfkf35",
         "https://drive.google.com/uc?export=download&id=1TsaVQHlhOVG905elbHXeXK2qzp-vFe68",
         "https://drive.google.com/uc?export=download&id=1p4mej6xhfpqzLfRuMNkKHJb9ScjXU193",
         "https://drive.google.com/uc?export=download&id=1L0woI2DeNES5OCzgLNBOCRrj5ikOzN7c",
         "https://drive.google.com/uc?export=download&id=1YYy6cH_gQf9rXmnPW9861N0Chlf_ZmTF",
         "https://drive.google.com/uc?export=download&id=16EgAh0uo7pB7aQKCMeI5dfMkCJ1y-RvB",
         "https://drive.google.com/uc?export=download&id=1Htg-qTj03YRQqBgbHxz8KOULBYQGQieP",
         ),
        ("631de5b205c8cb535818ab3a0a2c25c8ac66d841197225496bc26d0ae9fa5702",
         "c696f7fa9c9a774e61d5bff83bd2a0f2263698591be3344400a58c3c88af8e8f",
         "1d77c9128d4262f58aea8d2aa6d21becba241f607168c24e2fc76163d0db7b0a",
         "391b8721471dae54780ea61f1edd286ce2fa67aa9ff47a28807e96b006ef21df",
         "cb2a1b24b4b99434932c647c21baab4ae7867b45053b2a804d8213e9bdc2e04e",
         "ee239ec5fc30ce0c817626dbbf4b8f25119a1b202930f7f1b50ee88b98f26647",
         "94cf78daa24cc3652deec24c786cbe8067fe8dec824d34d7280a0ca9069dc8a1",
         "d08bd9011df02afcf324fc8888304e4868f5bbfca061b4396262903c7d7a7fe0",
         "a02aadcc30c4e49355ebe350b3933dcdcecf7e50af3ea442b71e3c728423ac3a",
         "aa87890fe7c56a30ec4df79cdfabc575448efb6f31e119e6dc0d53150940b1ea",
         "2d6b0e839d5485dc9e5eedcc967671f134308316fe3ee3e9e249cc2aa502f1c4",
         "216afe3542536ac32579f8b81c2b3564c2a8a0033a214274ddacecf215b97100",
         "e5a3b2a692e3971185979c0d8c6882f092380bd580db79a32e72e1b4ec77537f",
         )
    )
        config = _get_bert_config[model]
        case = config[:case]
        head = config[:head]
        hidden = config[:hidden]
        layer = config[:layer]
        wwm = config[:wwm] ? ", whole word masked" : ""
        band = "$(Base.Unicode.titlecase(string(config[:host]))) released "
        register(DataDep(
            "BERT-$model",
            """
            $(band)bert model with $(layer)-layer, $(head)-head, $(hidden)-hidden, $(case)$(wwm)
            """,
            url,
            cksum;
            fetch_method = download_gdrive
        ))
    end
end


text:
# Enable mocking
using Mocking
Mocking.enable()

# Standard imports
using Test
using HTTP

# Integration test!
# include("EndToEnd.jl")


text:
time_to_hours(t::TimeOfDay) = float(t)*1e-12/3.6

# # we can add methods dynamically
# Base.push!(plt::Plot, i::Integer, p::Price) = push!(plt, i, float(p))
# Base.push!(plt::Plot, i::Integer, t::TimeOfDay, p) = push!(plt, i, time_to_hours(t), float(p))

# TODO: generalize this better, so we can just pass a conversion function?

@recipe f{T<:AbstractArray{TimeOfDay}}(::Type{T}, ts::T) = map(time_to_hours, ts)
@recipe f{T<:AbstractArray{Price}}(::Type{T}, ts::T) = map(float, ts)

# function Plots.convertToAnyVector(ts::AbstractVector{TimeOfDay}; kw...)
#     Any[map(time_to_hours, ts)], nothing
# end

# function Plots.convertToAnyVector(tmat::AbstractMatrix{TimeOfDay}; kw...)
#     Any[map(time_to_hours, vec(tmat[:,i])) for i in size(tmat,2)], nothing
# end

# function Plots.convertToAnyVector(ps::AbstractVector{Price}; kw...)
#     Any[map(float, ps)], nothing
# end

# function Plots.convertToAnyVector(pmat::AbstractMatrix{Price}; kw...)
#     Any[map(float, vec(pmat[:,i])) for i in size(pmat,2)], nothing
# end


text:
"""
    abstract type AbstractIntDomain end

Abstract domain type. Every integer domain must inherit from this type.
"""
abstract type AbstractIntDomain <: AbstractDomain end

"""
    struct IntDomain <: AbstractIntDomain

Sparse integer domain. Can contain any set of integer.

You must note that this implementation takes as much space as the size of the initial domain.
However, it can be pretty efficient in accessing and editing. Operation costs are detailed for each method.
"""
struct IntDomain <: AbstractIntDomain
    values          ::Array{Int}
    indexes         ::Array{Int}
    offset          ::Int
    initSize        ::Int
    size            ::SeaPearl.StateObject{Int}
    min             ::SeaPearl.StateObject{Int}
    max             ::SeaPearl.StateObject{Int}
    trailer         ::SeaPearl.Trailer
end

"""
    IntDomain(trailer::Trailer, n::Int, offset::Int)

Create an integer domain going from `ofs + 1` to `ofs + n`.
Will be backtracked by the given `trailer`.
"""
function IntDomain(trailer::Trailer, n::Int, offset::Int)

    size = SeaPearl.StateObject{Int}(n, trailer)
    min = SeaPearl.StateObject{Int}(offset + 1, trailer)
    max = SeaPearl.StateObject{Int}(offset + n, trailer)
    values = zeros(n)
    indexes = zeros(n)
    for i in 1:n
        values[i] = i
        indexes[i] = i
    end
    return IntDomain(values, indexes, offset, n, size, min, max, trailer)
end

"""
    reset_domain!(dom::IntDomain)

Used in `reset_model!`.
"""
function reset_domain!(dom::IntDomain)
    setValue!(dom.size, dom.initSize)
    setValue!(dom.min, dom.offset + 1)
    setValue!(dom.max, dom.offset + dom.initSize)
    sort!(dom.values)
    sort!(dom.indexes)
    dom
end

function Base.show(io::IO, dom::IntDomain)
    print(io, "[", join(dom, " "), "]")
end

function Base.show(io::IO, ::MIME"text/plain", dom::IntDomain)
    print(io, typeof(dom), ": [", join(dom, " "), "]")
end

"""
    isempty(dom::IntDomain)

Return `true` iff `dom` is an empty set. Done in constant time.
"""
Base.isempty(dom::SeaPearl.IntDomain) = dom.size.value == 0

"""
    length(dom::IntDomain)

Return the size of `dom`. Done in constant time.
"""
Base.length(dom::SeaPearl.IntDomain) = dom.size.value

"""
    Base.in(value::Int, dom::IntDomain)

Check if an integer is in the domain. Done in constant time.
"""
function Base.in(value::Int, dom::IntDomain)
    value -= dom.offset
    if value < 1 || value > dom.initSize
        return false
    end
    return dom.indexes[value] <= length(dom)
end

"""
    remove!(dom::IntDomain, value::Int)

Remove `value` from `dom`. Done in constant time.
"""
function remove!(dom::IntDomain, value::Int)
    if !(value in dom)
        return Int[]
    end

    value -= dom.offset

    exchangePositions!(dom, value, dom.values[dom.size.value])
    setValue!(dom.size, dom.size.value - 1)

    updateBoundsFromRemovedVal!(dom, value+dom.offset)

    return [value+dom.offset]
end

"""
    removeAll!(dom::IntDomain)

Remove every value from `dom`. Return the removed values. Done in constant time.
"""
function removeAll!(dom::IntDomain)
    removed = Array{Int}(undef, dom.size.value)
    for i in 1:dom.size.value
        removed[i] = dom.values[i] + dom.offset
    end

    setValue!(dom.size, 0)
    return removed
end

"""
    removeAbove!(dom::IntDomain, value::Int)

Remove every integer of `dom` that is *strictly* above `value`. Done in *linear* time.
"""
function removeAbove!(dom::IntDomain, value::Int)
    if dom.min.value > value
        return removeAll!(dom)
    end

    pruned = Int[]
    for i in (value+1):dom.max.value
        if i in dom
            remove!(dom, i)
            push!(pruned, i)
        end
    end
    return pruned
end

"""
    removeBelow!(dom::IntDomain, value::Int)

Remove every integer of `dom` that is *strictly* below `value`. Return the pruned values.
Done in *linear* time.
"""
function removeBelow!(dom::IntDomain, value::Int)
    if dom.max.value < value
        return removeAll!(dom)
    end

    pruned = Int[]
    for i in dom.min.value:(value-1)
        if i in dom
            remove!(dom, i)
            push!(pruned, i)
        end
    end
    return pruned
end

"""
    assign!(dom::IntDomain, value::Int)

Remove everything from the domain but `value`. Return the removed values. Return the pruned values.
Done in *constant* time.
"""
function assign!(dom::IntDomain, value::Int)
    @assert value in dom

    value -= dom.offset

    exchangePositions!(dom, value, dom.values[1])

    removed = Array{Int}(undef, dom.size.value - 1)
    for i in 2:dom.size.value
        removed[i-1] = dom.values[i] + dom.offset
    end

    setValue!(dom.size, 1)
    setValue!(dom.max, value + dom.offset)
    setValue!(dom.min, value + dom.offset)

    return removed
end

"""
    Base.iterate(dom::IntDomain, state=1)

Iterate over the domain in an efficient way. The order may not be consistent.
WARNING: Do **NOT** update the domain you are iterating on.
"""
function Base.iterate(dom::IntDomain, state=1)
    @assert state >= 1
    if state > dom.size.value
        return nothing
    end

    return dom.values[state] + dom.offset, state+1
end

"""
    exchangePositions!(dom::IntDomain, v1::Int, v2::Int)

Intended for internal use only, exchange the position of `v1` and `v2` in the array of the domain.
"""
function exchangePositions!(dom::IntDomain, v1::Int, v2::Int)
    @assert(v1 <= length(dom.values) && v2 <= length(dom.values))

    i1, i2 = dom.indexes[v1], dom.indexes[v2]

    dom.values[i1] = v2
    dom.values[i2] = v1
    dom.indexes[v1] = i2
    dom.indexes[v2] = i1

    return dom
end

"""
    updateMaxFromRemovedVal!(dom::IntDomain, v::Int)

Knowing that `v` just got removed from `dom`, update `dom`'s maximum value.
Done in *constant* time.
"""
function updateMaxFromRemovedVal!(dom::IntDomain, v::Int)
    if !isempty(dom) && maximum(dom) == v
        @assert !(v in dom)
        currentVal = v - 1
        while currentVal >= minimum(dom)
            if currentVal in dom
                break
            end
            currentVal -= 1
        end
        setValue!(dom.max, currentVal)
    end
end

"""
    updateMinFromRemovedVal!(dom::IntDomain, v::Int)

Knowing that `v` just got removed from `dom`, update `dom`'s minimum value.
Done in *constant* time.
"""
function updateMinFromRemovedVal!(dom::IntDomain, v::Int)
    if !isempty(dom) && minimum(dom) == v
        @assert !(v in dom)
        currentVal = v + 1
        while currentVal <= maximum(dom)
            if currentVal in dom
                break
            end
            currentVal += 1
        end
        setValue!(dom.min, currentVal)
    end
end

"""
    updateBoundsFromRemovedVal!(dom::AbstractIntDomain, v::Int)

Knowing that `v` just got removed from `dom`, update `dom`'s minimum and maximum value.
Done in *constant* time.
"""
function updateBoundsFromRemovedVal!(dom::AbstractIntDomain, v::Int)
    updateMaxFromRemovedVal!(dom, v)
    updateMinFromRemovedVal!(dom, v)
end

"""
    minimum(dom::IntDomain)

Return the minimum value of `dom`.
Done in *constant* time.
"""
minimum(dom::IntDomain) = dom.min.value

"""
    maximum(dom::IntDomain)

Return the maximum value of `dom`.
Done in *constant* time.
"""
maximum(dom::IntDomain) = dom.max.value


text:
##########################################################################
# Copyright 2017 Samuel Ridler.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##########################################################################

@testset "binary search" begin
	n = 10
	x = cumsum(rand(n).+0.1)
	@assert(issorted(x, lt=<=)) # values should be strictly increasing
	for i = 1:n
		@assert(binarySearch(x, x[i]*(1-eps())) == (i-1,i))
		@assert(binarySearch(x, x[i]) == (i,i))
		@assert(binarySearch(x, x[i]*(1+eps())) == (i,i+1))
	end
	@test true
end


text:
"""
DataFS object for FAM with feature selection.
Augments Data object with covariates X.
X can be indicators, or continuous predictors.
"""
struct DataFS
  X::Matrix{Float64}  # dim: I x P
  P::Int  # P is number of covariates, aka ncol(X)
  data::Data
end

function DataFS(data::Data, X::Matrix{Float64})
  P = ncol(X)
  return DataFS(X, P, data)
end


text:
struct InnerProductVec{F,T}
    vec::T
    dotf::F
end
Base.eltype(v::InnerProductVec) = eltype(typeof(v))
Base.eltype(::Type{InnerProductVec{F,T}}) where {F,T} = eltype(T)

Base.:-(v::InnerProductVec) = InnerProductVec(-v.vec, v.dotf)
Base.:+(v::InnerProductVec{F}, w::InnerProductVec{F}) where F = InnerProductVec(v.vec+w.vec, v.dotf)
Base.:-(v::InnerProductVec{F}, w::InnerProductVec{F}) where F = InnerProductVec(v.vec-w.vec, v.dotf)
Base.:*(v::InnerProductVec, a) = InnerProductVec(v.vec*a, v.dotf)
Base.:*(a, v::InnerProductVec) = InnerProductVec(a*v.vec, v.dotf)
Base.:/(v::InnerProductVec, a) = InnerProductVec(v.vec/a, v.dotf)
Base.:\(a, v::InnerProductVec) = InnerProductVec(a\v.vec, v.dotf)

Base.similar(v::InnerProductVec, ::Type{T} = eltype(v)) where {T} = InnerProductVec(similar(v.vec), v.dotf)

Base.getindex(v::InnerProductVec) = v.vec

function Base.fill!(v::InnerProductVec, a)
    fill!(v.vec, a)
    return v
end

function Base.copyto!(w::InnerProductVec{F}, v::InnerProductVec{F}) where F
    copyto!(w.vec, v.vec)
    return w
end

function LinearAlgebra.mul!(w::InnerProductVec{F}, a, v::InnerProductVec{F}) where F
    mul!(w.vec, a, v.vec)
    return w
end

function LinearAlgebra.mul!(w::InnerProductVec{F}, v::InnerProductVec{F}, a) where F
    mul!(w.vec, v.vec, a)
    return w
end

function LinearAlgebra.rmul!(v::InnerProductVec, a)
    rmul!(v.vec, a)
    return v
end

function LinearAlgebra.axpy!(a, v::InnerProductVec{F}, w::InnerProductVec{F}) where F
    axpy!(a, v.vec, w.vec)
    return w
end
function LinearAlgebra.axpby!(a, v::InnerProductVec{F}, b, w::InnerProductVec{F}) where F
    axpby!(a, v.vec, b, w.vec)
    return w
end

LinearAlgebra.dot(v::InnerProductVec{F}, w::InnerProductVec{F}) where {F} = v.dotf(v.vec, w.vec)
LinearAlgebra.norm(v::InnerProductVec) = sqrt(real(dot(v,v)))


text:
module DuffyQuadraturesTests

using Test
using Gridap.ReferenceFEs

degree = 1
quad = Quadrature(TRI,duffy,degree)
@test sum(get_weights(quad)) ≈ 0.5

degree = 4
quad = Quadrature(TET,duffy,degree)
@test sum(get_weights(quad)) ≈ 0.5*1/3

end # module


text:
export logsumexp3!, logsumexp_and_softmax3!, softmax3!, logsumexp_and_softmax!, logsumexp_and_softmax

add_1_dim(x::AbstractArray) = reshape(x, size(x)..., 1)

"""
    logsumexp_and_softmax!(r, x)

Set `r` = softmax(x) and return `logsumexp(x)`.
"""
function logsumexp_and_softmax!(r::AbstractArray{T}, x::AbstractArray{T}) where {T}
    n = length(x)
    length(r) == n || throw(DimensionMismatch("Inconsistent array lengths."))
    isempty(x) && return -T(Inf)

    u = maximum(x)                                       # max value used to re-center
    abs(u) == Inf && return any(isnan, x) ? T(NaN) : u   # check for non-finite values

    s = zero(T)
    @inbounds @simd for i in 1:n
        s += ( r[i] = exp(x[i] - u) )
    end
    invs = one(T)/s
    r .*= invs
    return log(s) + u
end

logsumexp_and_softmax!(x::AbstractArray) = logsumexp_and_softmax!(x, x)

function logsumexp3!(lse::AbstractMatrix, tmp::AbstractMatrix, x::AbstractArray3)
    nz, nψ, nd = size(x)
    (nz, nψ) ==  size(lse) == size(tmp) || throw(DimensionMismatch())

    maximum!(add_1_dim(tmp), x)
    fill!(lse, zero(eltype(lse)))
    @inbounds for k in 1:nd
        @views lse .+= exp.(x[:,:,k] .- tmp)
    end
    lse .= log.(lse) .+ tmp
end

function softmax3!(q::AbstractArray3, lse::AbstractMatrix, tmp::AbstractMatrix, x::AbstractArray3)
    nz, nψ, nd = size(x)
    (nz, nψ, nd) == size(q) || throw(DimensionMismatch())
    (nz, nψ) ==  size(lse) == size(tmp) || throw(DimensionMismatch())

    maximum!(add_1_dim(tmp), x)
    fill!(lse, zero(eltype(lse)))
    @inbounds for k in 1:size(x,3)
        @views lse .+= (q[:,:,k] .= exp.(x[:,:,k] .- tmp))
    end
    q ./= lse
end

# update q as Pr(x[:,:,1])
function softmax3!(q::AbstractMatrix, lse::AbstractMatrix, tmp::AbstractMatrix, x::AbstractArray3)
    nz, nψ, nd = size(x)
    (nz, nψ) ==  size(lse) == size(tmp) == size(q) || throw(DimensionMismatch())

    maximum!(add_1_dim(tmp), x)
    @views lse .= (q .= exp.(x[:,:,1] .- tmp))
    @inbounds for k in 2:nd
        @views lse .+= exp.(x[:,:,k] .- tmp)
    end
    q ./= lse
end

# updates updates x to Pr(x)
softmax3!(x::AbstractArray3, lse::AbstractMatrix, tmp::AbstractMatrix) = softmax3!(x, lse, tmp, x)

# does not change x
function logsumexp_and_softmax3!(lse::AbstractMatrix, q::AbstractArray, tmp::AbstractMatrix, x::AbstractArray3)
    softmax3!(q, lse, tmp, x)
    lse .= log.(lse) .+ tmp
end

# updates x to Pr(x)
function logsumexp_and_softmax3!(lse::AbstractMatrix, x::AbstractArray3, tmp::AbstractMatrix)
    logsumexp_and_softmax3!(lse, x, tmp, x)
end


text:
"""
transforms a contigency list into explicit multinetwork data with network 0
being the base case
"""
function build_scopf_multinetwork(network)
    if InfrastructureModels.ismultinetwork(network)
        error(_LOGGER, "build scopf can only be used on single networks")
    end

    contingencies = length(network["gen_contingencies"]) + length(network["branch_contingencies"])

    info(_LOGGER, "building scopf multi-network with $(contingencies) networks")

    mn_data = PowerModels.replicate(network, contingencies)
    base_network = mn_data["nw"]["0"] = deepcopy(mn_data["nw"]["1"])

    for (n, network) in mn_data["nw"]
        if n == "0"
            continue
        end
        for (i,bus) in network["bus"]
            if haskey(bus, "evhi")
                bus["vmax"] = bus["evhi"]
            end
            if haskey(bus, "evlo")
                bus["vmin"] = bus["evlo"]
            end
        end

        for (i,branch) in network["branch"]
            if haskey(branch, "rate_c")
                branch["rate_a"] = branch["rate_c"]
            end
        end
    end

    network_id = 1
    for cont in base_network["gen_contingencies"]
        cont_nw = mn_data["nw"]["$(network_id)"]
        cont_nw["name"] = cont.label
        cont_nw["gen"]["$(cont.idx)"]["gen_status"] = 0
        network_id += 1
    end
    for cont in base_network["branch_contingencies"]
        cont_nw = mn_data["nw"]["$(network_id)"]
        cont_nw["name"] = cont.label
        cont_nw["branch"]["$(cont.idx)"]["br_status"] = 0
        network_id += 1
    end

    return mn_data
end

# note this is simialr to bus_gen_lookup in PowerModels
# core differences are taking network as an arg and filtering by gen_status
function gens_by_bus(network)
    bus_gens = Dict(i => Any[] for (i,bus) in network["bus"])
    for (i,gen) in network["gen"]
        if gen["gen_status"] != 0
            push!(bus_gens["$(gen["gen_bus"])"], gen)
        end
    end
    return bus_gens
end

function tighten_constraints!(network)
    for (i,bus) in network["bus"]
        if isapprox(bus["vmax"], bus["evhi"])
            bus["vmax_target"] = bus["vmax"] - 0.03
        else
            bus["vmax_target"] = bus["vmax"]
        end
        if isapprox(bus["vmin"], bus["evlo"])
            bus["vmin_target"] = bus["vmin"] + 0.03
        else
            bus["vmin_target"] = bus["vmin"]
        end
    end

    for (i,gen) in network["gen"]
        if gen["pmax"] > 0 && gen["pmax"]*0.9 > gen["pmin"]
            gen["pmax_target"] = gen["pmax"]*0.9
        else
            gen["pmax_target"] = gen["pmax"]
        end
    end

    for (i,branch) in network["branch"]
        # TODO restore this
        #if isapprox(branch["rate_a"], branch["rate_c"])
            branch["rate_a"] = branch["rate_a"]*0.80
        #end
    end
end

function deactivate_rate_a!(network)
    network["active_rates"] = Int[]
    for (i,branch) in network["branch"]
        branch["rate_a_inactive"] = branch["rate_a"]
        delete!(branch, "rate_a")
    end
end

function activate_rate_a!(network)
    if haskey(network, "active_rates")
        delete!(network, "active_rates")
    end

    for (i,branch) in network["branch"]
        if haskey(branch, "rate_a_inactive")
            branch["rate_a"] = branch["rate_a_inactive"]
            delete!(branch, "rate_a_inactive")
        end
    end
end

function activate_rate_a_violations!(network)
    ac_flows = PowerModels.calc_branch_flow_ac(network)
    for (i,branch) in network["branch"]
        branch["pf_start"] = ac_flows["branch"][i]["pf"]
        branch["qf_start"] = ac_flows["branch"][i]["qf"]

        branch["pt_start"] = ac_flows["branch"][i]["pt"]
        branch["qt_start"] = ac_flows["branch"][i]["qt"]
    end

    line_flow_vio = false
    for (i,branch) in network["branch"]
        if !haskey(branch, "rate_a")
            if (ac_flows["branch"][i]["pf"]^2 + ac_flows["branch"][i]["qf"]^2 > branch["rate_a_inactive"]^2 ||
                ac_flows["branch"][i]["pt"]^2 + ac_flows["branch"][i]["qt"]^2 > branch["rate_a_inactive"]^2)
                info(_LOGGER, "add rate_a flow limit on branch $(i) $(branch["source_id"])")
                #branch["rate_a"] = branch["rate_a_inactive"] - max(abs(ac_flows["branch"][i]["qf"]), abs(ac_flows["branch"][i]["qt"]))
                branch["rate_a"] = branch["rate_a_inactive"]
                push!(network["active_rates"], branch["index"])
                line_flow_vio = true
            end
        else
            sm_fr = sqrt(ac_flows["branch"][i]["pf"]^2 + ac_flows["branch"][i]["qf"]^2)
            sm_to = sqrt(ac_flows["branch"][i]["pf"]^2 + ac_flows["branch"][i]["qf"]^2)
            vio = max(0.0, sm_fr - branch["rate_a"], sm_to - branch["rate_a"])
            if vio > 0.01
                warn(_LOGGER, "add rate_a flow limit violations $(vio) on branch $(i) $(branch["source_id"])")
            end
        end
    end

    return line_flow_vio
end

"""
assumes there is one reference bus and one connected component and adjusts voltage
angles to be centered around zero at the reference bus.
"""
function correct_voltage_angles!(network)
    ref_bus = -1
    for (i,bus) in network["bus"]
        if bus["bus_type"] == 3
            @assert ref_bus == -1
            ref_bus = bus
        end
    end

    if !isapprox(ref_bus["va"], 0.0, atol=1e-8)
        warn(_LOGGER, "shifting voltage angles by $(-ref_bus["va"]) to set reference bus to 0.0")
        shift_voltage_anlges!(network, -ref_bus["va"])
    end
end

"shift networks voltage angles by a specified amount"
function shift_voltage_anlges!(network, shift::Number)
    for (i,bus) in network["bus"]
        bus["va"] = bus["va"] + shift
    end
end

"add start values to a data model"
function set_start_values!(network::Dict{String,<:Any}; branch_flow=false)
    for (i,bus) in network["bus"]
        bus["va_start"] = bus["va"]
        bus["vm_start"] = bus["vm"]

        bus["vr_start"] = bus["vm"]*cos(bus["va"])
        bus["vi_start"] = bus["vm"]*sin(bus["va"])

        if haskey(bus, "vm_offset") && !isnan(bus["vm_offset"])
            bus["vm_offset_start"] = bus["vm_offset"]
        end
    end

    for (i,gen) in network["gen"]
        gen["pg_start"] = gen["pg"]
        gen["qg_start"] = gen["qg"]
    end

    for (i,shunt) in network["shunt"]
        shunt["bs_start"] = shunt["bs"]
    end

    if branch_flow
        for (i,branch) in network["branch"]
            branch["pf_start"] = branch["pf"]
            branch["qf_start"] = branch["qf"]

            branch["pt_start"] = branch["pt"]
            branch["qt_start"] = branch["qt"]
        end
    end
end

function update_active_power_data!(network, data; branch_flow=false)
    for (i,bus) in data["bus"]
        nw_bus = network["bus"][i]
        nw_bus["va"] = bus["va"]
    end

    for (i,gen) in data["gen"]
        nw_gen = network["gen"][i]
        nw_gen["pg"] = gen["pg"]
    end

    if branch_flow
        for (i,branch) in data["branch"]
            nw_branch = network["branch"][i]
            nw_branch["pf"] = branch["pf"]
            nw_branch["pt"] = branch["pt"]
        end
    end
end

function extract_solution(network; branch_flow=false)
    sol = Dict{String,Any}()

    sol["bus"] = Dict{String,Any}()
    for (i,bus) in network["bus"]
        bus_dict = Dict{String,Any}()
        bus_dict["va"] = get(bus, "va", 0.0)
        bus_dict["vm"] = get(bus, "vm", 1.0)
        sol["bus"][i] = bus_dict
    end

    sol["shunt"] = Dict{String,Any}()
    for (i,shunt) in network["shunt"]
        shunt_dict = Dict{String,Any}()
        shunt_dict["gs"] = get(shunt, "gs", 0.0)
        shunt_dict["bs"] = get(shunt, "bs", 0.0)
        sol["shunt"][i] = shunt_dict
    end

    sol["gen"] = Dict{String,Any}()
    for (i,gen) in network["gen"]
        gen_dict = Dict{String,Any}()
        gen_dict["pg"] = get(gen, "pg", 0.0)
        gen_dict["qg"] = get(gen, "qg", 0.0)
        sol["gen"][i] = gen_dict
    end

    if branch_flow
        sol["branch"] = Dict{String,Any}()
        for (i,branch) in network["branch"]
            branch_dict = Dict{String,Any}()
            branch_dict["pf"] = get(branch, "pf", 0.0)
            branch_dict["qf"] = get(branch, "qf", 0.0)
            branch_dict["pt"] = get(branch, "pt", 0.0)
            branch_dict["qt"] = get(branch, "qt", 0.0)
            sol["branch"][i] = branch_dict
        end
    end

    return sol
end

##### Solution Analysis #####

"assumes a vaild ac solution is included in the data and computes the branch flow values"
function calc_branch_flow_ac_goc(data::Dict{String,<:Any})
    @assert("per_unit" in keys(data) && data["per_unit"])
    @assert(!haskey(data, "conductors"))

    if InfrastructureModels.ismultinetwork(data)
        nws = Dict{String,Any}()
        for (i,nw_data) in data["nw"]
            nws[i] = _calc_branch_flow_ac_goc(nw_data)
        end
        return Dict{String,Any}(
            "nw" => nws,
            "per_unit" => data["per_unit"],
            "baseMVA" => data["baseMVA"]
        )
    else
        flows = _calc_branch_flow_ac_goc(data)
        flows["per_unit"] = data["per_unit"]
        flows["baseMVA"] = data["baseMVA"]
        return flows
    end
end

"helper function for calc_branch_flow_ac"
function _calc_branch_flow_ac_goc(data::Dict{String,<:Any})
    vm = Dict(bus["index"] => bus["vm"] for (i,bus) in data["bus"])
    va = Dict(bus["index"] => bus["va"] for (i,bus) in data["bus"])

    flows = Dict{String,Any}()
    for (i,branch) in data["branch"]
        if branch["br_status"] != 0
            f_bus = branch["f_bus"]
            t_bus = branch["t_bus"]

            g, b = calc_branch_y(branch)
            tr, ti = calc_branch_t(branch)
            g_fr = branch["g_fr"]
            b_fr = branch["b_fr"]
            g_to = branch["g_to"]
            b_to = branch["b_to"]

            tm = branch["tap"]

            vm_fr = vm[f_bus]
            vm_to = vm[t_bus]
            va_fr = va[f_bus]
            va_to = va[t_bus]

            if branch["transformer"]
                p_fr =  (g/tm^2+g_fr)*vm_fr^2 + (-g*tr+b*ti)/tm^2*(vm_fr*vm_to*cos(va_fr-va_to)) + (-b*tr-g*ti)/tm^2*(vm_fr*vm_to*sin(va_fr-va_to))
                q_fr = -(b/tm^2+b_fr)*vm_fr^2 - (-b*tr-g*ti)/tm^2*(vm_fr*vm_to*cos(va_fr-va_to)) + (-g*tr+b*ti)/tm^2*(vm_fr*vm_to*sin(va_fr-va_to))
            else
                p_fr =  (g+g_fr)/tm^2*vm_fr^2 + (-g*tr+b*ti)/tm^2*(vm_fr*vm_to*cos(va_fr-va_to)) + (-b*tr-g*ti)/tm^2*(vm_fr*vm_to*sin(va_fr-va_to))
                q_fr = -(b+b_fr)/tm^2*vm_fr^2 - (-b*tr-g*ti)/tm^2*(vm_fr*vm_to*cos(va_fr-va_to)) + (-g*tr+b*ti)/tm^2*(vm_fr*vm_to*sin(va_fr-va_to))
            end

            p_to =  (g+g_to)*vm_to^2 + (-g*tr-b*ti)/tm^2*(vm_to*vm_fr*cos(va_to-va_fr)) + (-b*tr+g*ti)/tm^2*(vm_to*vm_fr*sin(va_to-va_fr))
            q_to = -(b+b_to)*vm_to^2 - (-b*tr+g*ti)/tm^2*(vm_to*vm_fr*cos(va_to-va_fr)) + (-g*tr-b*ti)/tm^2*(vm_to*vm_fr*sin(va_to-va_fr))
        else
            p_fr = NaN
            q_fr = NaN

            p_to = NaN
            q_to = NaN
        end

        flows[i] = Dict(
            "pf" => p_fr,
            "qf" => q_fr,
            "pt" => p_to,
            "qt" => q_to
        )
    end

    return Dict{String,Any}("branch" => flows)
end

function compute_power_balance_deltas!(network)
    flows = calc_branch_flow_ac_goc(network)
    PowerModels.update_data!(network, flows)

    balance = PowerModels.calc_power_balance(network)
    PowerModels.update_data!(network, balance)

    p_delta_abs = [abs(bus["p_delta"]) for (i,bus) in network["bus"] if bus["bus_type"] != 4]
    q_delta_abs = [abs(bus["q_delta"]) for (i,bus) in network["bus"] if bus["bus_type"] != 4]

    return (
        p_delta_abs_max = maximum(p_delta_abs),
        p_delta_abs_mean = mean(p_delta_abs),
        q_delta_abs_max = maximum(q_delta_abs),
        q_delta_abs_mean = mean(q_delta_abs),
    )
end

function compute_violations(network, solution; vm_digits=3)

    vm_vio = 0.0
    for (i,bus) in network["bus"]
        if bus["bus_type"] != 4
            bus_sol = solution["bus"][i]

            # helps to account for minor errors in equality constraints
            sol_val = round(bus_sol["vm"], digits=vm_digits)

            #vio_flag = false
            if sol_val < bus["vmin"]
                vm_vio += bus["vmin"] - sol_val
                #vio_flag = true
            end
            if sol_val > bus["vmax"]
                vm_vio += sol_val - bus["vmax"]
                #vio_flag = true
            end
            #if vio_flag
            #    info(_LOGGER, "$(i): $(bus["vmin"]) - $(sol_val) - $(bus["vmax"])")
            #end
        end
    end

    pg_vio = 0.0
    qg_vio = 0.0
    for (i,gen) in network["gen"]
        if gen["gen_status"] != 0
            gen_sol = solution["gen"][i]

            if gen_sol["pg"] < gen["pmin"]
                pg_vio += gen["pmin"] - gen_sol["pg"]
            end
            if gen_sol["pg"] > gen["pmax"]
                pg_vio += gen_sol["pg"] - gen["pmax"]
            end

            if gen_sol["qg"] < gen["qmin"]
                qg_vio += gen["qmin"] - gen_sol["qg"]
            end
            if gen_sol["qg"] > gen["qmax"]
                qg_vio += gen_sol["qg"] - gen["qmax"]
            end
        end
    end

    sm_vio = NaN
    if haskey(solution, "branch")
        sm_vio = 0.0
        for (i,branch) in network["branch"]
            if branch["br_status"] != 0
                branch_sol = solution["branch"][i]
                s_fr = sqrt(branch_sol["pf"]^2 + branch_sol["qf"]^2)
                s_to = sqrt(branch_sol["pt"]^2 + branch_sol["qt"]^2)

                # note true model is rate_c
                #vio_flag = false
                if s_fr > branch["rate_a"]
                    sm_vio += s_fr - branch["rate_a"]
                    #vio_flag = true
                end
                if s_to > branch["rate_a"]
                    sm_vio += s_to - branch["rate_a"]
                    #vio_flag = true
                end

                #=
                if s_fr > branch["rate_c"]
                    sm_vio += s_fr - branch["rate_c"]
                    #vio_flag = true
                end
                if s_to > branch["rate_c"]
                    sm_vio += s_to - branch["rate_c"]
                    #vio_flag = true
                end
                =#
                #if vio_flag
                #    info(_LOGGER, "$(i), $(branch["f_bus"]), $(branch["t_bus"]): $(s_fr) / $(s_to) <= $(branch["rate_c"])")
                #end
            end
        end
    end

    return (vm=vm_vio, pg=pg_vio, qg=qg_vio, sm=sm_vio)
end

function compute_violations_ratec(network, solution; vm_digits=3)
    vm_vio = 0.0
    for (i,bus) in network["bus"]
        if bus["bus_type"] != 4
            bus_sol = solution["bus"][i]

            # helps to account for minor errors in equality constraints
            sol_val = round(bus_sol["vm"], digits=vm_digits)

            #vio_flag = false
            if sol_val < bus["vmin"]
                vm_vio += bus["vmin"] - sol_val
                #vio_flag = true
            end
            if sol_val > bus["vmax"]
                vm_vio += sol_val - bus["vmax"]
                #vio_flag = true
            end
            #if vio_flag
            #    info(_LOGGER, "$(i): $(bus["vmin"]) - $(sol_val) - $(bus["vmax"])")
            #end
        end
    end

    pg_vio = 0.0
    qg_vio = 0.0
    for (i,gen) in network["gen"]
        if gen["gen_status"] != 0
            gen_sol = solution["gen"][i]

            if gen_sol["pg"] < gen["pmin"]
                pg_vio += gen["pmin"] - gen_sol["pg"]
            end
            if gen_sol["pg"] > gen["pmax"]
                pg_vio += gen_sol["pg"] - gen["pmax"]
            end

            if gen_sol["qg"] < gen["qmin"]
                qg_vio += gen["qmin"] - gen_sol["qg"]
            end
            if gen_sol["qg"] > gen["qmax"]
                qg_vio += gen_sol["qg"] - gen["qmax"]
            end
        end
    end

    sm_vio = NaN
    if haskey(solution, "branch")
        sm_vio = 0.0
        for (i,branch) in network["branch"]
            if branch["br_status"] != 0
                branch_sol = solution["branch"][i]
                s_fr = sqrt(branch_sol["pf"]^2 + branch_sol["qf"]^2)
                s_to = sqrt(branch_sol["pt"]^2 + branch_sol["qt"]^2)

                # note true model is rate_c
                #vio_flag = false
                if s_fr > branch["rate_c"]
                    sm_vio += s_fr - branch["rate_c"]
                    #vio_flag = true
                end
                if s_to > branch["rate_c"]
                    sm_vio += s_to - branch["rate_c"]
                    #vio_flag = true
                end
                #if vio_flag
                #    info(_LOGGER, "$(i), $(branch["f_bus"]), $(branch["t_bus"]): $(s_fr) / $(s_to) <= $(branch["rate_c"])")
                #end
            end
        end
    end

    return (vm=vm_vio, pg=pg_vio, qg=qg_vio, sm=sm_vio)
end

"returns a sorted list of branch flow violations"
function branch_violations_sorted(network, solution)
    branch_violations = []

    if haskey(solution, "branch")
        for (i,branch) in network["branch"]
            if branch["br_status"] != 0
                branch_sol = solution["branch"][i]
                s_fr = sqrt(branch_sol["pf"]^2 + branch_sol["qf"]^2)
                s_to = sqrt(branch_sol["pt"]^2 + branch_sol["qt"]^2)

                sm_vio = 0.0
                # TODO update to rate_c
                if s_fr > branch["rate_a"]
                    sm_vio = s_fr - branch["rate_a"]
                end
                if s_to > branch["rate_a"] && s_to - branch["rate_a"] > sm_vio
                    sm_vio = s_to - branch["rate_a"]
                end

                if sm_vio > 0.0
                    push!(branch_violations, (branch_id=branch["index"], sm_vio=sm_vio))
                end
            end
        end
    end

    sort!(branch_violations, by=(x) -> -x.sm_vio)

    return branch_violations
end

"returns a sorted list of branch flow violations"
function branch_violations_sorted_ratec(network, solution)
    branch_violations = []

    if haskey(solution, "branch")
        for (i,branch) in network["branch"]
            if branch["br_status"] != 0
                branch_sol = solution["branch"][i]
                s_fr = sqrt(branch_sol["pf"]^2 + branch_sol["qf"]^2)
                s_to = sqrt(branch_sol["pt"]^2 + branch_sol["qt"]^2)

                sm_vio = 0.0
                # TODO update to rate_c
                if s_fr > branch["rate_c"]
                    sm_vio = s_fr - branch["rate_c"]
                end
                if s_to > branch["rate_c"] && s_to - branch["rate_c"] > sm_vio
                    sm_vio = s_to - branch["rate_c"]
                end

                if sm_vio > 0.0
                    push!(branch_violations, (branch_id=branch["index"], sm_vio=sm_vio))
                end
            end
        end
    end

    sort!(branch_violations, by=(x) -> -x.sm_vio)

    return branch_violations
end


text:
phasefile = joinpath("data", "small", "Phase.nii")
magfile = joinpath("data", "small", "Mag.nii")
phase = Float32.(readphase(phasefile))
magni = readmag(magfile)

iswrap(x, y) = abs(rem2pi(x - y, RoundNearest)) < 1e-6

function test(f)
    unwrapped = f(phase; mag=magni, TEs=[4,8,12])
    @test !all(unwrapped .== phase)
    @test all(iswrap.(unwrapped, phase))
    return unwrapped
end

test(romeo)
test(unwrap)
test(unwrap_individual)
@test !all(laplacianunwrap(phase) .== phase)


text:
# 対象とする関数
f(x) = sqrt(x+1) - sqrt(x)
# 有理化した関数
rf(x) = 1 / (sqrt(x+1) + sqrt(x))

println("x=1e+15       : ", f(1e+15))
println("x=1e+15(有理化): ", rf(1e+15))
println("x=1e+16       : ", f(1e+16))
println("x=1e+16(有理化): ", rf(1e+16))


text:
include("../../testcases.jl")
using PyCall
using DFTK

atoms = [ElementPsp(:Mg, psp=load_psp("hgh/lda/mg-q2")) => magnesium.positions]
model = model_DFT(magnesium.lattice, atoms, [:gga_x_pbe, :gga_c_pbe],
                  temperature=0.01, smearing=Smearing.MethfesselPaxton2())

abinitpseudos = [joinpath(pyimport("abipy.data").__path__[end], "hgh_pseudos/12mg.2.hgh")]
DFTK.run_abinit_scf(model, @__DIR__; abinitpseudos=abinitpseudos,
                    Ecut=25, kgrid=[5, 5, 5], n_bands=10, tol=1e-10,
                    iscf=3)  # Use Anderson mixing instead of minimization


text:
module ParallelTrainingNN

import Distributions
import Optim
import Plots

export
    # Static Models
    StaticModel,
    ParametricModel,
    AparametricModel,
    ElementwiseOperator,
    Linear,
    LinearSparse,
    LogisticFunction,
    HyperbolicTangent,
    AffineMap,
    Identity,
    Bias,
    SeriesModel,
    FeedforwardNetwork,

    # Initializers
    Initializer,
    DefaultInitializer,
    ZeroInitializer,
    CustomRandomInitializer,
    ScaledGaussianInitializer,
    ComposedInitializer,

    # Static Models Methods
    evaluate!,
    z_buffer,
    dx_buffer,
    dΘ_buffer,
    initial_guess,
    isparametric,
    length_input,
    length_output,
    length_params,

    # Difference Equation Methods
    DifferenceEquation,
    simulate!,
    simulate,

    # Identification Data
    IdData,
    get_time_vector,
    get_input,
    get_output,

    # Predictor
    Predictor,
    one_step_ahead,
    free_run_simulation,
    predict!,
    predict,
    y_buffer,
    dy0_buffer,
    get_slice,

    # Predictor Error
    PredictorError,
    SimpleError,
    ExtendedParamsError,
    error_function!,
    estimate_parameters,
    narx,
    noe,

    # Preprocess Data
    learn_offset,
    learn_normalization,

    # Plots
    plot_input,
    plot_output

# Static Models
include("static_models/static_model.jl")
include("static_models/initializers.jl")
include("static_models/linear.jl")
include("static_models/linear_sparse.jl")
include("static_models/elementwise_operator.jl")
include("static_models/bias.jl")
include("static_models/series_model.jl")
include("static_models/feedforward_network.jl")

# Difference Equation
include("difference_equation.jl")

# IdData
include("iddata.jl")

# Include Levenberg-Marquadt algorithm
include("optimization/levenberg_marquardt.jl")

# Predictor
include("predictor.jl")
include("predictor_error.jl")

# Preprocessing data
include("preprocess_data.jl")

# Plots
include("plots.jl")

end # module


text:
version = "3.16.08"
os_string = @static is_apple() ? "darwin" : "linux"
extension = @static is_apple() ? "darwin" : "tar.gz"

file_name = "dReal-$version-$os_string-shared-libs.$extension"
file_url = "https://github.com/dreal/dreal3/releases/download/v$version/$file_name"
deps_dir = dirname(@__FILE__)
prefix = joinpath(deps_dir,"usr")

println("Cleanup old build files")

try
  run(`rm  -r $(joinpath(deps_dir,"dReal*"))`)
catch end
try
  run(`rm -r $(joinpath(deps_dir,"usr"))`)
catch end

download(file_url,joinpath(deps_dir,file_name))
@static is_apple() ? begin
  run(`unzip $file_name`)
end : begin
  run(`tar -xvf $file_name`)
end
run(`mv $(joinpath(deps_dir, "dReal-$version-$os_string-shared-libs")) usr`)


text:
using NgSpice
using Test

rootdir = joinpath(@__DIR__, "..")
netpath = joinpath(rootdir, "inputs", "mosfet.cir")

@testset "initialize" begin
    init()
    @test source(netpath) == 0
    @test NgSpice.run() == 0
end

@testset "getvectors" begin
    # as this simulation runs after the one in `ngspice_api.jl`,
    # `tran2` is the current plot
    @test curplot() == "tran2"
    @test listallplots() == ["tran2", "tran1", "const"]
    @test collect(keys(listallvecs())) == collect(sort(listallplots()))
    @test listallvecs()[curplot()] == listcurvecs()
    @test getvec.(listcurvecs()) == get_vector_info.(listcurvecs())
    #listcurvecs()
    for node in split("V(1) emit coll base vcc")
        @test getvec(node)[2] == "voltage"
    end
    for branch in split("vcc#branch vin#branch")
        @test getvec(branch)[2] == "current"
    end
    @test getvec("time")[2] == "time"
end

@testset "passing circuit as an array" begin
    netlist = readlines(netpath)
    @test load_netlist(netlist) == 0
end

max_stars_repo_name: JuliaComputing/Ngspice

max_issues_repo_name: JuliaComputing/Ngspice

max_forks_repo_name: JuliaComputing/Ngspice


text:
#=

  Traffic lights problem in Julia ConstraintSolver.jl

  CSPLib problem 16
  http://www.cs.st-andrews.ac.uk/~ianm/CSPLib/prob/prob016/index.html
  """
  Specification:
  Consider a four way traffic junction with eight traffic lights. Four of the traffic
  lights are for the vehicles and can be represented by the variables V1 to V4 with domains
  {r,ry,g,y} (for red, red-yellow, green and yellow). The other four traffic lights are
  for the pedestrians and can be represented by the variables P1 to P4 with domains {r,g}.

  The constraints on these variables can be modelled by quaternary constraints on
  (Vi, Pi, Vj, Pj ) for 1<=i<=4, j=(1+i)mod 4 which allow just the tuples
  {(r,r,g,g), (ry,r,y,r), (g,g,r,r), (y,r,ry,r)}.

  It would be interesting to consider other types of junction (e.g. five roads
  intersecting) as well as modelling the evolution over time of the traffic light sequence.
  ...

  Results
  Only 2^2 out of the 2^12 possible assignments are solutions.

  (V1,P1,V2,P2,V3,P3,V4,P4) =
     {(r,r,g,g,r,r,g,g), (ry,r,y,r,ry,r,y,r), (g,g,r,r,g,g,r,r), (y,r,ry,r,y,r,ry,r)}
     [(1,1,3,3,1,1,3,3), ( 2,1,4,1, 2,1,4,1), (3,3,1,1,3,3,1,1), (4,1, 2,1,4,1, 2,1)}

  The problem has relative few constraints, but each is very tight. Local propagation
  appears to be rather ineffective on this problem.
  """

  Model created by Hakan Kjellerstrand, hakank@gmail.com
  See also my Julia page: http://www.hakank.org/julia/

=#
using ConstraintSolver, JuMP
using Cbc, GLPK
const CS = ConstraintSolver
include("constraints_utils.jl")

function traffic_lights(print_solutions=true,all_solutions=true)

    cbc_optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0)
    glpk_optimizer = optimizer_with_attributes(GLPK.Optimizer)

    model = Model(optimizer_with_attributes(CS.Optimizer,   "all_solutions"=> all_solutions,
                                                            # "all_optimal_solutions"=>true,
                                                            "logging"=>[],

                                                            "traverse_strategy"=>:BFS,
                                                            # "traverse_strategy"=>:DFS, # <-
                                                            # "traverse_strategy"=>:DBFS,

                                                            "branch_split"=>:Smallest,
                                                            # "branch_split"=>:Biggest,
                                                            # "branch_split"=>:InHalf, # <-

                                                            # "simplify"=>false,
                                                            # "simplify"=>true, # default

                                                            "time_limit"=>16,

                                                            # "lp_optimizer" => cbc_optimizer,
                                                            # "lp_optimizer" => glpk_optimizer,
                                        ))

    n=4
    r,ry,g,y = 1:n
    d = Dict(1=>"r",2=>"ry",3=>"g",4=>"y")
    # allowed light combinations
    allowed = [r r g g;
               ry r y r;
               g g r r;
               y r ry r
              ]

    @variable(model, v[1:n],  CS.Integers([r,ry,g,y]))
    @variable(model, p[1:n],  CS.Integers([r,ry,g,y]))

    for i in 1:n, j in 1:n
        if j == (1+i) % n
            @constraint(model, [v[i], p[i], v[j], p[j]] in CS.TableSet(allowed))
        end
    end

    # Solve the problem
    optimize!(model)

    status = JuMP.termination_status(model)
    # println("status:$status")
    if status == MOI.OPTIMAL
        num_sols = MOI.get(model, MOI.ResultCount())
        println("num_sols:$num_sols\n")
        if print_solutions
            for sol in 1:num_sols
                # println("solution #$sol")
                vv = convert.(Integer,JuMP.value.(v; result=sol))
                pp = convert.(Integer,JuMP.value.(p; result=sol))
                # println("v:$vv  p:$pp")
                for i in 1:n
                print(d[vv[i]]," ", d[pp[i]], " ")
                end
                println()
            end
            println()
        end
    else
        println("status:$status")
    end

    return status
end

@time traffic_lights()

max_stars_repo_name: Wikunia/hakank

max_issues_repo_name: Wikunia/hakank

max_forks_repo_name: Wikunia/hakank


text:
using Turing
using Memoization
using ReverseDiff
Turing.setrdcache(true)
setadbackend(:reversediff)

n  = 100
x  = 1:n
λs = sin.(2π/100 * x)*10 .+ 10
p  = .8
m  = 100
is = repeat(x, inner=m)
dist(x...) = ZeroInflatedDistribution(
    Bernoulli( first(x) ),
    Poisson( last(x) )
)
ys = [rand(dist(p, λs[i])) for i in is]

##
function lnk!(ys, y0, xs, lnk)
    ys[1] = y0
    for (i, x) in enumerate(xs)
        ys[i+1] = lnk(x)
    end
    return nothing
end

##
@model function test(y, n, i, lnk, invlnk, ::Type{V}  = Float64) where V
    p  ~ Beta()
    λ0 ~ truncated(Normal(10,1.), 0, 20.)
    σ  ~ truncated(Normal(0.1, .05), 0, Inf)
    latent_λ  ~ CovidSurvey.RandomWalk(n-1, σ, invlnk(λ0))

    λ = Vector{V}(undef, n)
    lnk!(λ, λ0, latent_λ, lnk)

    d = ZeroInflatedDistribution.(
        Ref(Bernoulli(p)),
        Poisson.(λ)
    )

    y ~ arraydist(d[i])
    return λ
end
lnk = KLogistic(20.)
invlnk = KLogit(20.)
m = test(ys, n, is, lnk, invlnk)
c = sample(m, NUTS(10, 0.8), 20; progress=true)
λs = generated_quantities(m, c)
##
plot(c[[:p, :λ0, :σ]])
CovidSurvey.plot_confidence_timeseries(λs[:,1])
## ADVI
using Turing: Variational
include(projectdir("scripts/utils.jl"))

advi = ADVI(10, 1000)
q0 = Variational.meanfield(m)
q = vi(m, advi, q0)
c = Chains(q, m; ignorekeys=[])
mixeddensity(c)
λs = generated_quantities(m, c)
CovidSurvey.plot_confidence_timeseries(λs[:,1])
## Optim
# using Optim
# mle = optimize(m, MLE(), LBFGS(), Optim.Options(iterations = 1000, allow_f_increases = true))
# opt = optimize(m, MAP(), Optim.Options(show_trace=true))
##
using TransformVariables, LogDensityProblems
include(projectdir("scripts/rawsurvey_utils.jl"))

df = let
    n  = 100
    x  = 1:n
    μ = sin.(2π/100 * x)*10 .+ 20
    p  = .8
    m  = 100
    ϕ  = 10.
    is = repeat(x, inner=m)
    d  = Date("2020-12-31") .+ Day.(is)
    ys = [rand(likelihood_dist(p, μ[i], ϕ)) for i in is]
    DataFrame(:date=>d, :y=>ys)
end

problem = ZeroInflatedProblem(df, :y)
t  = problem_transformation(problem)
P  = TransformedLogDensity(t, problem)
∇P = ADgradient(Val(:ReverseDiff), P)
getlossf(P) = f(x) = -LogDensityProblems.logdensity(P, x)
getgradf(∇P) = g(x) = -LogDensityProblems.logdensity_and_gradient(∇P, x)[2]
f = getlossf(P)
g = getgradf(∇P)

θ  = rand(problem.prior)
x  = TransformVariables.inverse(t, θ)
##
res = optimize(f, g, x,
    LBFGS(),
    Optim.Options(show_trace=true, iterations=4000);
    inplace = false
)
##
θ = TransformVariables.transform(t, res.minimizer)
μ = generate_quantities(problem, θ)
let
    dates = first(df.date) : Day(1) : last(df.date)
    p = plot(dates, μ, xticks=:native)
end
##
let
    y = predict(problem, θ)
    df = DataFrame(:posterior=>y, :data=>problem.y, :date=>df.date)
    p = CovidSurvey.plot_confidence_timeseries(df, :data; cols=[:posterior, :data])
    firefox(p)
end

## ============================================================================
# DynamicHMC
using DynamicHMC

results = mcmc_with_warmup(Random.GLOBAL_RNG, ∇P, 1000;
    initialization = (
        q = x,
        κ = GaussianKineticEnergy(length(x), 0.1)
    ),
)

plot( mean( getindex.(θs, :rw) ) )

posterior = TransformVariables.transform.(t, results.chain)

using NamedTupleTools
df = delete.(posterior, Ref(:latent_λ)) |> DataFrame
c = Chains(Array(df), names(df))
plot(c)

generate_quantities(problem, θs::Vector{<:NamedTuple}) =
    generate_quantities.(Ref(problem), θs)
λs = generate_quantities(problem, posterior)
plot_confidence_timeseries(λs)
## ==========================================================================

max_stars_repo_name: andreaskoher/CovidSurvey

max_issues_repo_name: andreaskoher/CovidSurvey

max_forks_repo_name: andreaskoher/CovidSurvey


text:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Description
# ==============================================================================
#
#   Definition of types and structures.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

const SearchMatch = NTuple{3, Int}
const SearchMatches = Vector{SearchMatch}

# Structure that holds all the information about the pager.
Base.@kwdef mutable struct Pager
    term::REPL.Terminals.TTYTerminal
    buf::IOContext{IOBuffer}
    display_size::NTuple{2, Int} = (0, 0)
    start_row::Int = 1
    start_col::Int = 1
    lines::Vector{String} = String[]
    num_lines::Int = 0
    lines_cropped::Int = 0
    columns_cropped::Int = 0
    search_matches::SearchMatches = SearchMatch[]
    active_search_match_id::Int = 0
    redraw::Bool = true
    mode::Symbol = :view
    event::Union{Nothing, Symbol} = nothing
    features::Vector{Symbol} = Symbol[]
    freeze_columns::Int = 0
    freeze_rows::Int = 0
    title_rows::Int = 0
    draw_ruler::Bool = false
end

# This struct describe the decoration of a string.
Base.@kwdef struct Decoration
    foreground::String = ""
    background::String = ""
    bold::Bool         = false
    underline::Bool    = false
    reset::Bool        = false
    reversed::Bool     = false

    # This variable is used to force a formatting. This is necessary because we
    # do not add escape sequences if the decoration is the default, avoiding
    # unnecessary writing. However, we need to differentiate the decoration
    # that is forcing to go back to the default.
    force::Bool = false
end

"""
    struct Keystorke

Structure that defines a keystroke.

# Fields

* `raw`: Raw keystroke code converted to string.
* `value`: String representing the keystroke.
* `alt`: `true` if ALT key was pressed (only valid if `value != :char`).
* `ctrl`: `true` if CTRL key was pressed (only valid if `value != :char`).
* `shift`: `true` if SHIFT key was pressed (only valid if `value != :char`).

"""
Base.@kwdef struct Keystroke
    raw::String = ""
    value::Union{Symbol, String}
    alt::Bool   = false
    ctrl::Bool  = false
    shift::Bool = false
end