text:
"""
struct BagModel{T <: AbstractMillModel, U <: AbstractMillModel} <: AbstractMillModel
im::T
a::Aggregation
bm::U
end

use a `im` model on data in `BagNode`, the uses function `a` to aggregate individual bags,
and finally it uses `bm` model on the output
"""
struct BagModel{T <: AbstractMillModel, A, U <: AbstractMillModel} <: AbstractMillModel
    im::T
    a::A
    bm::U
end

Flux.@functor BagModel

BagModel(im::MillFunction, a, bm::MillFunction) = BagModel(ArrayModel(im), a, ArrayModel(bm))
BagModel(im::AbstractMillModel, a, bm::MillFunction) = BagModel(im, a, ArrayModel(bm))
BagModel(im::MillFunction, a, bm::AbstractMillModel) = BagModel(ArrayModel(im), a, bm)
BagModel(im::MillFunction, a) = BagModel(im, a, identity)
BagModel(im::AbstractMillModel, a) = BagModel(im, a, ArrayModel(identity))

(m::BagModel)(x::WeightedBagNode{<: AbstractNode}) = m.bm(m.a(m.im(x.data), x.bags, x.weights))

function (m::BagModel)(x::BagNode)
    ismissing(x.data) ? m.bm(ArrayNode(m.a(x.data, x.bags))) : m.bm(m.a(m.im(x.data), x.bags))
end

function HiddenLayerModel(m::BagModel, x::BagNode, k::Int)
    im, o = HiddenLayerModel(m.im, x.data, k)
    a = SegmentedMax(k)
    b = m.a(o, x.bags)
    bm, o = HiddenLayerModel(m.bm, b, k)
    BagModel(im, a, bm), o
end

function mapactivations(hm::BagModel, x::BagNode{M, B,C}, m::BagModel) where {M<: AbstractNode,B,C}
    hmi, mi = mapactivations(hm.im, x.data, m.im)
    ai = m.a(mi, x.bags)
    hai = hm.a(hmi, x.bags)
    hbo, bo = mapactivations(hm.bm, ai, m.bm)
    (ArrayNode(hbo.data + hai.data), bo)
end

function mapactivations(hm::BagModel, x::BagNode{M, B,C}, m::BagModel) where {M<: Missing,B,C}
    ai = m.a(missing, x.bags)
    hai = hm.a(missing, x.bags)
    hbo, bo = mapactivations(hm.bm, ArrayNode(ai), m.bm)
    (ArrayNode(hbo.data + hai), bo)
end

function fold(f, m::BagModel, x)
    o₁ = fold(f, m.im, x.data)
    o₂ = f(m.a, o₁, x.bags)
    o₃ = fold(f, m.bm, o₂)
    o₃
end


text:
## Exercise 9-4
# Write a function named usesonly that takes a word and a string of letters, and that returns true if the word contains only letters in the list. Can you make a sentence using only the letters acefhlo? Other than "Hoe alfalfa?"

println("Ans:")

function usesonly(word, letters)
    letters *= " "

    for letter in lowercase(word)
        if letter ∉ letters
            return false
        end
    end

    return true
end

println(usesonly("Hoe alfalfa", "acefhlo"))

for word in eachline("words.txt")
    if usesonly(word, "acefhlo")
        println(word)
    end
end

println("End.")

ext: jl


text:
# NOTE: Need to make sure to load the following scripts before running this script:
# include("scripts/posterior_predictive_estimate.jl")
# include("scripts/post_hoc_plots.jl")
# include("scripts/radon_combined_post_hoc_plots.jl")

# Plots for posterior predictive model
function make_paper_plots()
    posterior_predictive_estimate_name = # Fill out
    posterior_predictive_baseline_name = # Fill out
    reprocess_pp_results(
        posterior_predictive_estimate_name;
        mcmc_baseline_name=posterior_predictive_baseline_name
    )

    # Plots for SIR model
    sir_estimate_name = # Fill out
    sir_baseline_name = # Fill out
    sir_data_file = # Fill out
    sir_ground_truth_calculation = # Fill out
    post_hoc_analysis(
        sir_data_file,
        sir_ground_truth_calculation,
        sir_estimate_name;
        mcmc_baseline_name=sir_baseline_name,
        make_joint_plot=false
    )

    # Plots for Radon model
    radon_estimate_name = # Fill out
    radon_combined_post_hoc_plots(radon_estimate_name)
end

make_paper_plots()


text:
@testset "SymSparseMatrixCSR" begin
    maxnz=5
    maxrows=5
    maxcols=5

    for T in (Int32,Int64,Float32,Float64)
        for Bi in (0,1)
            I = Vector{Int}()
            J = Vector{Int}()
            V = Vector{T}()
            for (ik, jk, vk) in zip(rand(1:maxrows, maxnz), rand(1:maxcols, maxnz), rand(1:T(maxnz), maxnz) )
                push_coo!(SymSparseMatrixCSR,I,J,V,ik,jk,vk)
            end
            finalize_coo!(SymSparseMatrixCSR,I,J,V,maxrows, maxcols)
            SYMCSC = Symmetric(sparse(I, J, V, maxrows, maxcols),:U)
            SYMCSR = symsparsecsr(SymSparseMatrixCSR{Bi},I, J, V, maxrows, maxcols)

            @test size(SYMCSC)==size(SYMCSR)
            @test SYMCSC == SYMCSR

            @test hasrowmajororder(SYMCSR) == true
            @test hascolmajororder(SYMCSR) == false
            @test getptr(SYMCSR)           == SYMCSR.uppertrian.rowptr
            @test getindices(SYMCSR)       == colvals(SYMCSR)

            @test nnz(SYMCSC.data) == nnz(SYMCSR.uppertrian) <= nnz(SYMCSR)
            @test count(!iszero, SYMCSC.data) == count(!iszero, SYMCSR.uppertrian)

            ICSC,JCSC,VCSC= findnz(SYMCSC.data)
            ICSR,JCSR,VCSR= findnz(SYMCSR)

            @test sort(ICSC)==sort(JCSR) && sort(JCSC)==sort(ICSR) && sort(VCSC)==sort(VCSR)

            v = rand(size(SYMCSC)[2])
            @test SYMCSC*v == SYMCSR*v
        end
    end

end


text:
module Utils
using LinearAlgebra

"""
affine_model!(y,A,x,b)

Simple affine model, ``y = Ax - b```, result stored in ``y```
"""
function affine_model!(y,A,x,b)
    mul!(y,A,x)
    y .= y .- b
    return nothing
end

end


text:
#=
Parse tokenized foam file to kind of AST with some unparsed token Content
ofmeshtypes over PreParsedDictonaryonary types

numbers and varaibles will not finally be parsed in this stage:
    preparse entities contain index of tokens or strings that are not completly
    parsed jet
=#

include("ofMeshDictTokenizer.jl")

const ParseEntitySymbols_Dict = Dict(
    :word => TokenTypeID_Dict[:word],
    :def_var_end => TokenTypeID_Dict[:semicolon],
    :dict_start => TokenTypeID_Dict[:curly_brace_open],
    :dict_end => TokenTypeID_Dict[:curly_brace_close],
    :arr_start => TokenTypeID_Dict[:bracket_open],
    :arr_end => TokenTypeID_Dict[:bracket_close],
)

const ParseSymbolsEntity_Dict = Dict(value => key for (key, value) in TokenTypeID_Dict)

abstract type PreParsedEntity end
abstract type PreParsedNum <: PreParsedEntity end

mutable struct PreParsedFNum <: PreParsedNum
    string::String
end

mutable struct PreParsedINum <: PreParsedNum
    string::String
end

mutable struct PreParsedVariable <: PreParsedEntity
    id_token_from::Int64
    id_token_to::Int64
end

mutable struct PreParsedDictonary <: PreParsedEntity
    id_token_from::Int64
    id_token_to::Int64
    name::String
    entries::Vector{PreParsedEntity}
end

# array list of same entities with length
mutable struct PreParsedArray <: PreParsedEntity
    id_token_from::Int64
    id_token_to::Int64
    length::Int64
    entries::Vector{PreParsedEntity}
end

# same as array but no defined length
mutable struct PreParsedList <: PreParsedEntity
    id_token_from::Int64
    id_token_to::Int64
    entries::Vector{PreParsedEntity}
end

"""
    parser(tokens::Vector{Token}, i_start::Int64=1, i_stop::Int64=-1)

pre parsing of tokens to array structure that represents file structure
"""
function parser(tokens::Vector{Token}, i_start::Int64=1,
                                    i_stop::Int64=-1)::Vector{PreParsedEntity}

    i = i_start

    if i_stop == -1
        i_stop = length(tokens)
    end

    parse_entities = Vector{PreParsedEntity}(undef,0)

    while i  <= i_stop
        t = tokens[i]

        if t.type_id == ParseEntitySymbols_Dict[:word]

            if tokens[i+1].type_id == ParseEntitySymbols_Dict[:dict_start]
                i_end = find_closing(tokens, i+1, tokens[i+1].type_id)
                dict_entities = parser(tokens, i+2, i_end-1)

                dict_name = tokens[i].string

                push!(parse_entities, PreParsedDictonary(i+1, i_end, dict_name, dict_entities))
                i_next = i_end + 1
            else
                i_end = get_end_of_ofvar(tokens, i+1)
                push!(parse_entities, PreParsedVariable(i, i_end))
                i_next  = i_end + 1
            end
        elseif t.type_id == ParseEntitySymbols_Dict[:arr_start]
            i_end = find_closing(tokens, i, t.type_id)

            if tokens[i-1].type_id == TokenTypeID_Dict[:int_number]
                arr_len = parse(Int64, tokens[i-1].string)

                arr_entities = parser(tokens, i+1, i_end-1)
                check_correct_arr_list!(arr_entities)
                push!(parse_entities, PreParsedArray(i, i_end, arr_len, arr_entities))
            else
                list_entities = parser(tokens, i+1, i_end-1)
                check_correct_arr_list!(list_entities)
                push!(parse_entities, PreParsedList(i, i_end, list_entities))
            end

            i_next = i_end + 1
        elseif t.type_id == TokenTypeID_Dict[:minus]

            if tokens[i+1].type_id == TokenTypeID_Dict[:float_number]
                push!(parse_entities, PreParsedFNum(tokens[i].string *
                                                  tokens[i+1].string))
                i_next = i+2

            elseif tokens[i+1].type_id == TokenTypeID_Dict[:int_number]
                push!(parse_entities, PreParsedINum(tokens[i].string *
                                                  tokens[i+1].string))
                i_next = i+2
            end

        elseif t.type_id == TokenTypeID_Dict[:float_number]
            push!(parse_entities, PreParsedFNum(tokens[i].string))
            i_next = i+1
        elseif  (t.type_id == TokenTypeID_Dict[:int_number]
                 && tokens[i+1].type_id != TokenTypeID_Dict[:bracket_open])
            push!(parse_entities, PreParsedINum(tokens[i].string))
            i_next = i+1
        else
            i_next = i + 1
        end

        i = i_next
    end

    return parse_entities
end

"""
    get_closing(tid_opening::Int64)::Int64

get matching closing bracket id
"""
function get_closing(tid_opening::Int64)::Int64

    if tid_opening == TokenTypeID_Dict[:bracket_open]
        tid_closing = TokenTypeID_Dict[:bracket_close]

    elseif tid_opening == TokenTypeID_Dict[:curly_brace_open]
        tid_closing = TokenTypeID_Dict[:curly_brace_close]

    else
        error("invalid charcter id to find matching closing bracket(char)")
    end

    return tid_closing
end

"""
    get_end_of_ofvar(tokens::Vector{Token}, i_start::Int64)

find end of variable entry
"""
function get_end_of_ofvar(tokens::Vector{Token}, i_start::Int64)

    i = i_start

    while i > 1
        t = tokens[i]
        if t.type_id == Int64(';')
            return i
        end

        i+=1
    end

    error("No end of var found")
end

"""
    find_closing(tokens::Vector{Token}, i_start::Int64,
                                        tid_opening::Int64)::Int64

find matching closing bracket position in list of tokens (tokens)
"""
function find_closing(tokens::Vector{Token}, i_start::Int64,
                                         tid_opening::Int64)::Int64

    i = i_start
    n_open = 1
    tid_closing = get_closing(tid_opening)

    while (n_open > 0 || i > length(tokens))

        i += 1
        t = tokens[i]

        if t.type_id == tid_opening
            n_open += 1
        elseif t.type_id == tid_closing
            n_open -= 1
        end
    end

    if (i > length(tokens))
        error("End of token not found")
    end

    return i
end

"""
    check_correct_arr_list!(arr_entries::Vector{PreParsedEntity}

checks if array and list pre parsed types contain same entity types, applies
    correction for floating and int point numbers ...
"""
function check_correct_arr_list!(arr_entries::Vector{PreParsedEntity})

    for i =1:length(arr_entries)
        arr_ent = arr_entries[i]
        if typeof(arr_ent) != typeof(arr_entries[1])

            if (typeof(arr_ent) == PreParsedINum
                 && typeof(arr_entries[1]) == PreParsedFNum)

                 arr_entries[i] = PreParsedFNum(arr_entries[i].string)

            elseif (typeof(arr_ent) == PreParsedFNum
                 && typeof(arr_entries[1]) == PreParsedINum)

                 arr_entries[1] = PreParsedFNum(arr_entries[1].string)
            else
                error("array/list entries musst be of same type")
            end

        end
    end

    return true
end

max_stars_repo_name: c-schubert/linearMeshIO

max_issues_repo_name: c-schubert/linearMeshIO

max_forks_repo_name: c-schubert/linearMeshIO


text:
# Automatically generated using Clang.jl wrap_c, version 0.0.0

using Compat

const TOX_VERSION_MAJOR = 0
const TOX_VERSION_MINOR = 0
const TOX_VERSION_PATCH = 0

# Skipping MacroDefinition: TOX_VERSION_IS_API_COMPATIBLE ( MAJOR , MINOR , PATCH ) ( TOX_VERSION_MAJOR == MAJOR && ( TOX_VERSION_MINOR > MINOR || ( TOX_VERSION_MINOR == MINOR && TOX_VERSION_PATCH >= PATCH ) ) )
# Skipping MacroDefinition: TOX_VERSION_REQUIRE ( MAJOR , MINOR , PATCH ) typedef char tox_required_version [ TOX_IS_COMPATIBLE ( MAJOR , MINOR , PATCH ) ? 1 : - 1 ]
# Skipping MacroDefinition: TOX_VERSION_IS_ABI_COMPATIBLE ( ) tox_version_is_compatible ( TOX_VERSION_MAJOR , TOX_VERSION_MINOR , TOX_VERSION_PATCH )

const TOX_PUBLIC_KEY_SIZE = 32
const TOX_SECRET_KEY_SIZE = 32

# Skipping MacroDefinition: TOX_ADDRESS_SIZE ( TOX_PUBLIC_KEY_SIZE + sizeof ( uint32_t ) + sizeof ( uint16_t ) )

const TOX_MAX_NAME_LENGTH = 128
const TOX_MAX_STATUS_MESSAGE_LENGTH = 1007
const TOX_MAX_FRIEND_REQUEST_LENGTH = 1016
const TOX_MAX_MESSAGE_LENGTH = 1372
const TOX_MAX_CUSTOM_PACKET_SIZE = 1373
const TOX_HASH_LENGTH = 32
const TOX_FILE_ID_LENGTH = 32
const TOX_MAX_FILENAME_LENGTH = 255

typealias Tox Void

# begin enum TOX_USER_STATUS
typealias TOX_USER_STATUS Uint32
const TOX_USER_STATUS_NONE = (UInt32)(0)
const TOX_USER_STATUS_AWAY = (UInt32)(1)
const TOX_USER_STATUS_BUSY = (UInt32)(2)
# end enum TOX_USER_STATUS

# begin enum TOX_MESSAGE_TYPE
typealias TOX_MESSAGE_TYPE Uint32
const TOX_MESSAGE_TYPE_NORMAL = (UInt32)(0)
const TOX_MESSAGE_TYPE_ACTION = (UInt32)(1)
# end enum TOX_MESSAGE_TYPE

# begin enum TOX_PROXY_TYPE
typealias TOX_PROXY_TYPE Uint32
const TOX_PROXY_TYPE_NONE = (UInt32)(0)
const TOX_PROXY_TYPE_HTTP = (UInt32)(1)
const TOX_PROXY_TYPE_SOCKS5 = (UInt32)(2)
# end enum TOX_PROXY_TYPE

# begin enum TOX_SAVEDATA_TYPE
typealias TOX_SAVEDATA_TYPE Uint32
const TOX_SAVEDATA_TYPE_NONE = (UInt32)(0)
const TOX_SAVEDATA_TYPE_TOX_SAVE = (UInt32)(1)
const TOX_SAVEDATA_TYPE_SECRET_KEY = (UInt32)(2)
# end enum TOX_SAVEDATA_TYPE

# begin enum TOX_ERR_OPTIONS_NEW
typealias TOX_ERR_OPTIONS_NEW Uint32
const TOX_ERR_OPTIONS_NEW_OK = (UInt32)(0)
const TOX_ERR_OPTIONS_NEW_MALLOC = (UInt32)(1)
# end enum TOX_ERR_OPTIONS_NEW

# begin enum TOX_ERR_NEW
typealias TOX_ERR_NEW Uint32
const TOX_ERR_NEW_OK = (UInt32)(0)
const TOX_ERR_NEW_NULL = (UInt32)(1)
const TOX_ERR_NEW_MALLOC = (UInt32)(2)
const TOX_ERR_NEW_PORT_ALLOC = (UInt32)(3)
const TOX_ERR_NEW_PROXY_BAD_TYPE = (UInt32)(4)
const TOX_ERR_NEW_PROXY_BAD_HOST = (UInt32)(5)
const TOX_ERR_NEW_PROXY_BAD_PORT = (UInt32)(6)
const TOX_ERR_NEW_PROXY_NOT_FOUND = (UInt32)(7)
const TOX_ERR_NEW_LOAD_ENCRYPTED = (UInt32)(8)
const TOX_ERR_NEW_LOAD_BAD_FORMAT = (UInt32)(9)
# end enum TOX_ERR_NEW

# begin enum TOX_ERR_BOOTSTRAP
typealias TOX_ERR_BOOTSTRAP Uint32
const TOX_ERR_BOOTSTRAP_OK = (UInt32)(0)
const TOX_ERR_BOOTSTRAP_NULL = (UInt32)(1)
const TOX_ERR_BOOTSTRAP_BAD_HOST = (UInt32)(2)
const TOX_ERR_BOOTSTRAP_BAD_PORT = (UInt32)(3)
# end enum TOX_ERR_BOOTSTRAP

# begin enum TOX_CONNECTION
typealias TOX_CONNECTION Uint32
const TOX_CONNECTION_NONE = (UInt32)(0)
const TOX_CONNECTION_TCP = (UInt32)(1)
const TOX_CONNECTION_UDP = (UInt32)(2)
# end enum TOX_CONNECTION

# begin enum TOX_ERR_SET_INFO
typealias TOX_ERR_SET_INFO Uint32
const TOX_ERR_SET_INFO_OK = (UInt32)(0)
const TOX_ERR_SET_INFO_NULL = (UInt32)(1)
const TOX_ERR_SET_INFO_TOO_LONG = (UInt32)(2)
# end enum TOX_ERR_SET_INFO

# begin enum TOX_ERR_FRIEND_ADD
typealias TOX_ERR_FRIEND_ADD Uint32
const TOX_ERR_FRIEND_ADD_OK = (UInt32)(0)
const TOX_ERR_FRIEND_ADD_NULL = (UInt32)(1)
const TOX_ERR_FRIEND_ADD_TOO_LONG = (UInt32)(2)
const TOX_ERR_FRIEND_ADD_NO_MESSAGE = (UInt32)(3)
const TOX_ERR_FRIEND_ADD_OWN_KEY = (UInt32)(4)
const TOX_ERR_FRIEND_ADD_ALREADY_SENT = (UInt32)(5)
const TOX_ERR_FRIEND_ADD_BAD_CHECKSUM = (UInt32)(6)
const TOX_ERR_FRIEND_ADD_SET_NEW_NOSPAM = (UInt32)(7)
const TOX_ERR_FRIEND_ADD_MALLOC = (UInt32)(8)
# end enum TOX_ERR_FRIEND_ADD

# begin enum TOX_ERR_FRIEND_DELETE
typealias TOX_ERR_FRIEND_DELETE Uint32
const TOX_ERR_FRIEND_DELETE_OK = (UInt32)(0)
const TOX_ERR_FRIEND_DELETE_FRIEND_NOT_FOUND = (UInt32)(1)
# end enum TOX_ERR_FRIEND_DELETE

# begin enum TOX_ERR_FRIEND_BY_PUBLIC_KEY
typealias TOX_ERR_FRIEND_BY_PUBLIC_KEY Uint32
const TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK = (UInt32)(0)
const TOX_ERR_FRIEND_BY_PUBLIC_KEY_NULL = (UInt32)(1)
const TOX_ERR_FRIEND_BY_PUBLIC_KEY_NOT_FOUND = (UInt32)(2)
# end enum TOX_ERR_FRIEND_BY_PUBLIC_KEY

# begin enum TOX_ERR_FRIEND_GET_PUBLIC_KEY
typealias TOX_ERR_FRIEND_GET_PUBLIC_KEY Uint32
const TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK = (UInt32)(0)
const TOX_ERR_FRIEND_GET_PUBLIC_KEY_FRIEND_NOT_FOUND = (UInt32)(1)
# end enum TOX_ERR_FRIEND_GET_PUBLIC_KEY

# begin enum TOX_ERR_FRIEND_GET_LAST_ONLINE
typealias TOX_ERR_FRIEND_GET_LAST_ONLINE Uint32
const TOX_ERR_FRIEND_GET_LAST_ONLINE_OK = (UInt32)(0)
const TOX_ERR_FRIEND_GET_LAST_ONLINE_FRIEND_NOT_FOUND = (UInt32)(1)
# end enum TOX_ERR_FRIEND_GET_LAST_ONLINE

# begin enum TOX_ERR_FRIEND_QUERY
typealias TOX_ERR_FRIEND_QUERY Uint32
const TOX_ERR_FRIEND_QUERY_OK = (UInt32)(0)
const TOX_ERR_FRIEND_QUERY_NULL = (UInt32)(1)
const TOX_ERR_FRIEND_QUERY_FRIEND_NOT_FOUND = (UInt32)(2)
# end enum TOX_ERR_FRIEND_QUERY

# begin enum TOX_ERR_SET_TYPING
typealias TOX_ERR_SET_TYPING Uint32
const TOX_ERR_SET_TYPING_OK = (UInt32)(0)
const TOX_ERR_SET_TYPING_FRIEND_NOT_FOUND = (UInt32)(1)
# end enum TOX_ERR_SET_TYPING

# begin enum TOX_ERR_FRIEND_SEND_MESSAGE
typealias TOX_ERR_FRIEND_SEND_MESSAGE Uint32
const TOX_ERR_FRIEND_SEND_MESSAGE_OK = (UInt32)(0)
const TOX_ERR_FRIEND_SEND_MESSAGE_NULL = (UInt32)(1)
const TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_FOUND = (UInt32)(2)
const TOX_ERR_FRIEND_SEND_MESSAGE_FRIEND_NOT_CONNECTED = (UInt32)(3)
const TOX_ERR_FRIEND_SEND_MESSAGE_SENDQ = (UInt32)(4)
const TOX_ERR_FRIEND_SEND_MESSAGE_TOO_LONG = (UInt32)(5)
const TOX_ERR_FRIEND_SEND_MESSAGE_EMPTY = (UInt32)(6)
# end enum TOX_ERR_FRIEND_SEND_MESSAGE

# begin enum TOX_FILE_KIND
typealias TOX_FILE_KIND Uint32
const TOX_FILE_KIND_DATA = (UInt32)(0)
const TOX_FILE_KIND_AVATAR = (UInt32)(1)
# end enum TOX_FILE_KIND

# begin enum TOX_FILE_CONTROL
typealias TOX_FILE_CONTROL Uint32
const TOX_FILE_CONTROL_RESUME = (UInt32)(0)
const TOX_FILE_CONTROL_PAUSE = (UInt32)(1)
const TOX_FILE_CONTROL_CANCEL = (UInt32)(2)
# end enum TOX_FILE_CONTROL

# begin enum TOX_ERR_FILE_CONTROL
typealias TOX_ERR_FILE_CONTROL Uint32
const TOX_ERR_FILE_CONTROL_OK = (UInt32)(0)
const TOX_ERR_FILE_CONTROL_FRIEND_NOT_FOUND = (UInt32)(1)
const TOX_ERR_FILE_CONTROL_FRIEND_NOT_CONNECTED = (UInt32)(2)
const TOX_ERR_FILE_CONTROL_NOT_FOUND = (UInt32)(3)
const TOX_ERR_FILE_CONTROL_NOT_PAUSED = (UInt32)(4)
const TOX_ERR_FILE_CONTROL_DENIED = (UInt32)(5)
const TOX_ERR_FILE_CONTROL_ALREADY_PAUSED = (UInt32)(6)
const TOX_ERR_FILE_CONTROL_SENDQ = (UInt32)(7)
# end enum TOX_ERR_FILE_CONTROL

# begin enum TOX_ERR_FILE_SEEK
typealias TOX_ERR_FILE_SEEK Uint32
const TOX_ERR_FILE_SEEK_OK = (UInt32)(0)
const TOX_ERR_FILE_SEEK_FRIEND_NOT_FOUND = (UInt32)(1)
const TOX_ERR_FILE_SEEK_FRIEND_NOT_CONNECTED = (UInt32)(2)
const TOX_ERR_FILE_SEEK_NOT_FOUND = (UInt32)(3)
const TOX_ERR_FILE_SEEK_DENIED = (UInt32)(4)
const TOX_ERR_FILE_SEEK_INVALID_POSITION = (UInt32)(5)
const TOX_ERR_FILE_SEEK_SENDQ = (UInt32)(6)
# end enum TOX_ERR_FILE_SEEK

# begin enum TOX_ERR_FILE_GET
typealias TOX_ERR_FILE_GET Uint32
const TOX_ERR_FILE_GET_OK = (UInt32)(0)
const TOX_ERR_FILE_GET_NULL = (UInt32)(1)
const TOX_ERR_FILE_GET_FRIEND_NOT_FOUND = (UInt32)(2)
const TOX_ERR_FILE_GET_NOT_FOUND = (UInt32)(3)
# end enum TOX_ERR_FILE_GET

# begin enum TOX_ERR_FILE_SEND
typealias TOX_ERR_FILE_SEND Uint32
const TOX_ERR_FILE_SEND_OK = (UInt32)(0)
const TOX_ERR_FILE_SEND_NULL = (UInt32)(1)
const TOX_ERR_FILE_SEND_FRIEND_NOT_FOUND = (UInt32)(2)
const TOX_ERR_FILE_SEND_FRIEND_NOT_CONNECTED = (UInt32)(3)
const TOX_ERR_FILE_SEND_NAME_TOO_LONG = (UInt32)(4)
const TOX_ERR_FILE_SEND_TOO_MANY = (UInt32)(5)
# end enum TOX_ERR_FILE_SEND

# begin enum TOX_ERR_FILE_SEND_CHUNK
typealias TOX_ERR_FILE_SEND_CHUNK Uint32
const TOX_ERR_FILE_SEND_CHUNK_OK = (UInt32)(0)
const TOX_ERR_FILE_SEND_CHUNK_NULL = (UInt32)(1)
const TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_FOUND = (UInt32)(2)
const TOX_ERR_FILE_SEND_CHUNK_FRIEND_NOT_CONNECTED = (UInt32)(3)
const TOX_ERR_FILE_SEND_CHUNK_NOT_FOUND = (UInt32)(4)
const TOX_ERR_FILE_SEND_CHUNK_NOT_TRANSFERRING = (UInt32)(5)
const TOX_ERR_FILE_SEND_CHUNK_INVALID_LENGTH = (UInt32)(6)
const TOX_ERR_FILE_SEND_CHUNK_SENDQ = (UInt32)(7)
const TOX_ERR_FILE_SEND_CHUNK_WRONG_POSITION = (UInt32)(8)
# end enum TOX_ERR_FILE_SEND_CHUNK

# begin enum TOX_ERR_FRIEND_CUSTOM_PACKET
typealias TOX_ERR_FRIEND_CUSTOM_PACKET Uint32
const TOX_ERR_FRIEND_CUSTOM_PACKET_OK = (UInt32)(0)
const TOX_ERR_FRIEND_CUSTOM_PACKET_NULL = (UInt32)(1)
const TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_FOUND = (UInt32)(2)
const TOX_ERR_FRIEND_CUSTOM_PACKET_FRIEND_NOT_CONNECTED = (UInt32)(3)
const TOX_ERR_FRIEND_CUSTOM_PACKET_INVALID = (UInt32)(4)
const TOX_ERR_FRIEND_CUSTOM_PACKET_EMPTY = (UInt32)(5)
const TOX_ERR_FRIEND_CUSTOM_PACKET_TOO_LONG = (UInt32)(6)
const TOX_ERR_FRIEND_CUSTOM_PACKET_SENDQ = (UInt32)(7)
# end enum TOX_ERR_FRIEND_CUSTOM_PACKET

# begin enum TOX_ERR_GET_PORT
typealias TOX_ERR_GET_PORT Uint32
const TOX_ERR_GET_PORT_OK = (UInt32)(0)
const TOX_ERR_GET_PORT_NOT_BOUND = (UInt32)(1)
# end enum TOX_ERR_GET_PORT

# begin enum ANONYMOUS_1
typealias ANONYMOUS_1 Uint32
const TOX_GROUPCHAT_TYPE_TEXT = (UInt32)(0)
const TOX_GROUPCHAT_TYPE_AV = (UInt32)(1)
# end enum ANONYMOUS_1

# begin enum ANONYMOUS_2
typealias ANONYMOUS_2 Uint32
const TOX_CHAT_CHANGE_PEER_ADD = (UInt32)(0)
const TOX_CHAT_CHANGE_PEER_DEL = (UInt32)(1)
const TOX_CHAT_CHANGE_PEER_NAME = (UInt32)(2)
# end enum ANONYMOUS_2

# begin enum TOX_CHAT_CHANGE
typealias TOX_CHAT_CHANGE Uint32
const TOX_CHAT_CHANGE_PEER_ADD = (UInt32)(0)
const TOX_CHAT_CHANGE_PEER_DEL = (UInt32)(1)
const TOX_CHAT_CHANGE_PEER_NAME = (UInt32)(2)
# end enum TOX_CHAT_CHANGE

immutable Array_128_Uint8
    d1::Uint8
    d2::Uint8
    d3::Uint8
    d4::Uint8
    d5::Uint8
    d6::Uint8
    d7::Uint8
    d8::Uint8
    d9::Uint8
    d10::Uint8
    d11::Uint8
    d12::Uint8
    d13::Uint8
    d14::Uint8
    d15::Uint8
    d16::Uint8
    d17::Uint8
    d18::Uint8
    d19::Uint8
    d20::Uint8
    d21::Uint8
    d22::Uint8
    d23::Uint8
    d24::Uint8
    d25::Uint8
    d26::Uint8
    d27::Uint8
    d28::Uint8
    d29::Uint8
    d30::Uint8
    d31::Uint8
    d32::Uint8
    d33::Uint8
    d34::Uint8
    d35::Uint8
    d36::Uint8
    d37::Uint8
    d38::Uint8
    d39::Uint8
    d40::Uint8
    d41::Uint8
    d42::Uint8
    d43::Uint8
    d44::Uint8
    d45::Uint8
    d46::Uint8
    d47::Uint8
    d48::Uint8
    d49::Uint8
    d50::Uint8
    d51::Uint8
    d52::Uint8
    d53::Uint8
    d54::Uint8
    d55::Uint8
    d56::Uint8
    d57::Uint8
    d58::Uint8
    d59::Uint8
    d60::Uint8
    d61::Uint8
    d62::Uint8
    d63::Uint8
    d64::Uint8
    d65::Uint8
    d66::Uint8
    d67::Uint8
    d68::Uint8
    d69::Uint8
    d70::Uint8
    d71::Uint8
    d72::Uint8
    d73::Uint8
    d74::Uint8
    d75::Uint8
    d76::Uint8
    d77::Uint8
    d78::Uint8
    d79::Uint8
    d80::Uint8
    d81::Uint8
    d82::Uint8
    d83::Uint8
    d84::Uint8
    d85::Uint8
    d86::Uint8
    d87::Uint8
    d88::Uint8
    d89::Uint8
    d90::Uint8
    d91::Uint8
    d92::Uint8
    d93::Uint8
    d94::Uint8
    d95::Uint8
    d96::Uint8
    d97::Uint8
    d98::Uint8
    d99::Uint8
    d100::Uint8
    d101::Uint8
    d102::Uint8
    d103::Uint8
    d104::Uint8
    d105::Uint8
    d106::Uint8
    d107::Uint8
    d108::Uint8
    d109::Uint8
    d110::Uint8
    d111::Uint8
    d112::Uint8
    d113::Uint8
    d114::Uint8
    d115::Uint8
    d116::Uint8
    d117::Uint8
    d118::Uint8
    d119::Uint8
    d120::Uint8
    d121::Uint8
    d122::Uint8
    d123::Uint8
    d124::Uint8
    d125::Uint8
    d126::Uint8
    d127::Uint8
    d128::Uint8
end

zero(::Type{Array_128_Uint8}) = begin  # /home/sbordt/.julia/v0.4/Clang/src/wrap_c.jl, line 264:
        Array_128_Uint8(fill(zero(Uint8),128)...)
    end

const RTP_PAYLOAD_SIZE = 65535

typealias ToxAv Void
typealias ToxAVCallback Ptr{Void}
typealias ToxAvAudioCallback Ptr{Void}
typealias ToxAvVideoCallback Ptr{Void}

# begin enum ANONYMOUS_3
typealias ANONYMOUS_3 Uint32
const av_OnInvite = (UInt32)(0)
const av_OnRinging = (UInt32)(1)
const av_OnStart = (UInt32)(2)
const av_OnCancel = (UInt32)(3)
const av_OnReject = (UInt32)(4)
const av_OnEnd = (UInt32)(5)
const av_OnRequestTimeout = (UInt32)(6)
const av_OnPeerTimeout = (UInt32)(7)
const av_OnPeerCSChange = (UInt32)(8)
const av_OnSelfCSChange = (UInt32)(9)
# end enum ANONYMOUS_3

# begin enum ToxAvCallbackID
typealias ToxAvCallbackID Uint32
const av_OnInvite = (UInt32)(0)
const av_OnRinging = (UInt32)(1)
const av_OnStart = (UInt32)(2)
const av_OnCancel = (UInt32)(3)
const av_OnReject = (UInt32)(4)
const av_OnEnd = (UInt32)(5)
const av_OnRequestTimeout = (UInt32)(6)
const av_OnPeerTimeout = (UInt32)(7)
const av_OnPeerCSChange = (UInt32)(8)
const av_OnSelfCSChange = (UInt32)(9)
# end enum ToxAvCallbackID

# begin enum ANONYMOUS_4
typealias ANONYMOUS_4 Uint32
const av_TypeAudio = (UInt32)(192)
const av_TypeVideo = (UInt32)(193)
# end enum ANONYMOUS_4

# begin enum ToxAvCallType
typealias ToxAvCallType Uint32
const av_TypeAudio = (UInt32)(192)
const av_TypeVideo = (UInt32)(193)
# end enum ToxAvCallType

# begin enum ANONYMOUS_5
typealias ANONYMOUS_5 Cint
const av_CallNonExistent = (Int32)(-1)
const av_CallInviting = (Int32)(0)
const av_CallStarting = (Int32)(1)
const av_CallActive = (Int32)(2)
const av_CallHold = (Int32)(3)
const av_CallHungUp = (Int32)(4)
# end enum ANONYMOUS_5

# begin enum ToxAvCallState
typealias ToxAvCallState Cint
const av_CallNonExistent = (Int32)(-1)
const av_CallInviting = (Int32)(0)
const av_CallStarting = (Int32)(1)
const av_CallActive = (Int32)(2)
const av_CallHold = (Int32)(3)
const av_CallHungUp = (Int32)(4)
# end enum ToxAvCallState

# begin enum ANONYMOUS_6
typealias ANONYMOUS_6 Cint
const av_ErrorNone = (Int32)(0)
const av_ErrorUnknown = (Int32)(-1)
const av_ErrorNoCall = (Int32)(-20)
const av_ErrorInvalidState = (Int32)(-21)
const av_ErrorAlreadyInCallWithPeer = (Int32)(-22)
const av_ErrorReachedCallLimit = (Int32)(-23)
const av_ErrorInitializingCodecs = (Int32)(-30)
const av_ErrorSettingVideoResolution = (Int32)(-31)
const av_ErrorSettingVideoBitrate = (Int32)(-32)
const av_ErrorSplittingVideoPayload = (Int32)(-33)
const av_ErrorEncodingVideo = (Int32)(-34)
const av_ErrorEncodingAudio = (Int32)(-35)
const av_ErrorSendingPayload = (Int32)(-40)
const av_ErrorCreatingRtpSessions = (Int32)(-41)
const av_ErrorNoRtpSession = (Int32)(-50)
const av_ErrorInvalidCodecState = (Int32)(-51)
const av_ErrorPacketTooLarge = (Int32)(-52)
# end enum ANONYMOUS_6

# begin enum ToxAvError
typealias ToxAvError Cint
const av_ErrorNone = (Int32)(0)
const av_ErrorUnknown = (Int32)(-1)
const av_ErrorNoCall = (Int32)(-20)
const av_ErrorInvalidState = (Int32)(-21)
const av_ErrorAlreadyInCallWithPeer = (Int32)(-22)
const av_ErrorReachedCallLimit = (Int32)(-23)
const av_ErrorInitializingCodecs = (Int32)(-30)
const av_ErrorSettingVideoResolution = (Int32)(-31)
const av_ErrorSettingVideoBitrate = (Int32)(-32)
const av_ErrorSplittingVideoPayload = (Int32)(-33)
const av_ErrorEncodingVideo = (Int32)(-34)
const av_ErrorEncodingAudio = (Int32)(-35)
const av_ErrorSendingPayload = (Int32)(-40)
const av_ErrorCreatingRtpSessions = (Int32)(-41)
const av_ErrorNoRtpSession = (Int32)(-50)
const av_ErrorInvalidCodecState = (Int32)(-51)
const av_ErrorPacketTooLarge = (Int32)(-52)
# end enum ToxAvError

# begin enum ANONYMOUS_7
typealias ANONYMOUS_7 Uint32
const av_AudioEncoding = (UInt32)(1)
const av_AudioDecoding = (UInt32)(2)
const av_VideoEncoding = (UInt32)(4)
const av_VideoDecoding = (UInt32)(8)
# end enum ANONYMOUS_7

# begin enum ToxAvCapabilities
typealias ToxAvCapabilities Uint32
const av_AudioEncoding = (UInt32)(1)
const av_AudioDecoding = (UInt32)(2)
const av_VideoEncoding = (UInt32)(4)
const av_VideoDecoding = (UInt32)(8)
# end enum ToxAvCapabilities

const TOXDNS_MAX_RECOMMENDED_NAME_LENGTH = 32


text:
using NiLang, NiLang.AD
using BenchmarkTools

include("../exmamples/besselj.jl")

# To test this function, we first define input parameters `a` and output `out!`
a = 1.0
out! = 0.0

# We wrap the output with a randomly initialized gradient field, suppose we get the gradients from a virtual loss function.
# Also, we need to initialize an empty gradient field for elements in input cuda tensor `a`.
out! = ibesselj(out!, 2, a)[1]
out_g! = GVar(out!, 1.0)
a_g = GVar(a)

# Call the inverse program, the multiple dispatch will drive you to the goal.
println("Benchmarking NiLang")
display(@benchmark ibesselj($out!, 2, $a))
println("Benchmarking NiLang.AD")
display(@benchmark (~ibesselj)($out_g!, 2, $a_g))


text:
abstract type Topology <: Component end

function CheckBusParams(number, name, bustype, angle, voltage, voltagelimits, basevoltatge,
                        internal)
    if !isnothing(bustype)
        if bustype == SLACK::BusType
            bustype = REF::BusType
            @debug "Changed bus type from SLACK to" bustype
        elseif bustype == ISOLATED::BusType
            throw(DataFormatError("isolated buses are not supported; name=$name"))
        end
    end

    return number, name, bustype, angle, voltage, voltagelimits, basevoltatge, internal
end


text:
using DataFrames

export to_dataframe, from_dataframe

"""
Creates a `DataFrame` from a `PairwiseListMatrix`. The second positional argument `diag` is `true` by default
and the diagonal values are included in the `DataFrame`.
Labels are stored in the columns 1 (`i`) and 2 (`j`), and the values in the column 3 with `colname` as `:value` by default.

```
julia> using DataFrames, PairwiseListMatrices

julia> PLM  = PairwiseListMatrix([1,2,3,4,5,6], true)
3x3 PairwiseListMatrices.PairwiseListMatrix{Int64,true}:
 1  2  3
 2  4  5
 3  5  6

julia> to_dataframe(PLM, false, colname=:score)
3x3 DataFrames.DataFrame
| Row | i | j | score |
|-----|---|---|-------|
| 1   | 1 | 2 | 2     |
| 2   | 1 | 3 | 3     |
| 3   | 2 | 3 | 5     |

```
"""
function to_dataframe{T, diagonal}(plm::PairwiseListMatrix{T, diagonal}, diag::Bool=true; colname::Symbol=:value)
  N = plm.nelements
  labels = length(plm.labels) != 0 ? plm.labels : IndexedArray(collect(1:N))
  df = DataFrames.DataFrame([eltype(labels), eltype(labels), T], [:i, :j, colname], diag ? div(N*(N+1),2) : div(N*(N-1),2))
  t = 0
  @iterateupper plm diag begin
    t += 1
    df[t, :i] = labels[i]
    df[t, :j] = labels[j]
    df[t, colname] = list[k]
  end
  df
end

"""
Creation of a `PairwiseListMatrix` from a `DataFrame`.
By default the columns with the labels for i (slow) and j (fast) are 1 and 2. Values are taken from the column 3 by default.
The second argument `diagonal` should be true if the diagonal values are included in the `DataFrame`.
"""
function from_dataframe(df::DataFrames.DataFrame, diagonal::Bool, labelcols=[1,2], valuecol=3)
  labs = unique(vcat(df[labelcols[1]],df[labelcols[2]]))
  PairwiseListMatrix(df[:,valuecol], convert(Vector{eltype(labs)}, labs), diagonal)
end


text:
@testset "Mix matrix initialisation and manipulation functions" begin
    #test mix matrix init
    prior_mix_test=init_mix_matrix((trues(2,10),0.0),2, 20)
    @test all(prior_mix_test[:,1:10])
    @test !any(prior_mix_test[:,11:20])

    @test sum(init_mix_matrix((falses(0,0),1.0), O, S)) == O*S
    @test sum(init_mix_matrix((falses(0,0),0.0), O, S)) == 0
    @test 0 < sum(init_mix_matrix((falses(0,0),0.5), O, S)) < O*S

    #test mix matrix decorrelation
    empty_mixvec=falses(O)
    one_mix=mixvec_decorrelate(empty_mixvec,1)
    @test sum(one_mix)==1

    empty_mix = falses(O,S)
    new_mix,clean=mix_matrix_decorrelate(empty_mix, 500)
    @test 0 < sum(new_mix) <= 500
    @test !all(clean)

    full_mix = trues(O,S)
    less_full_mix,clean=mix_matrix_decorrelate(full_mix, 500)

    @test O*S-sum(less_full_mix) <= 500
    @test !all(clean)

    #test matrix similarity and dissimilarity functions
    test_mix=falses(O,S)
    test_mix[1:Int(floor(O/2)),:].=true
    test_idx=3
    compare_mix=deepcopy(test_mix)
    compare_mix[:,test_idx] .= .!compare_mix[:,test_idx]
    @test most_dissimilar(test_mix,compare_mix)==test_idx

    src_mixvec=falses(O)
    src_mixvec[Int(ceil(O/2)):end].=true
    @test most_similar(src_mixvec,compare_mix)==test_idx
end


text:
# Will be evaluated _inside_ the workspace.

module PlutoRunner

using Markdown
import Markdown: html, htmlinline, LaTeX, withtag, htmlesc
import Distributed
import Base64
import REPL.REPLCompletions: completions, complete_path, completion_text
import Base: show, istextmime
import UUIDs: UUID

export @bind

###
# WORKSPACE MANAGER
###

"Will be set to the latest workspace module"
current_module = Main

function set_current_module(newname)
    global current_module = getfield(Main, newname)
    global iocontext = IOContext(iocontext, :module => current_module)
end

cell_results = Dict{UUID, WeakRef}()

function fetch_formatted_result(id::UUID, ends_with_semicolon::Bool)::NamedTuple{(:output_formatted, :errored, :interrupted, :runtime),Tuple{Tuple{String,MIME},Bool,Bool,Union{UInt64, Missing}}}
    ans = cell_results[id].value
    errored = ans isa CapturedException
    output_formatted = (!ends_with_semicolon || errored) ? format_output(ans) : ("", MIME"text/plain"())
    (output_formatted = output_formatted, errored = errored, interrupted = false, runtime = Main.runtime)
end

function move_vars(old_workspace_name::Symbol, new_workspace_name::Symbol, vars_to_delete::Set{Symbol}, funcs_to_delete::Set{Vector{Symbol}}, module_imports_to_move::Set{Expr})
    old_workspace = getfield(Main, old_workspace_name)
    new_workspace = getfield(Main, new_workspace_name)

    for expr in module_imports_to_move
        try
            Core.eval(new_workspace, expr)
        catch; end # TODO catch specificallly
    end

    # TODO: delete
    Core.eval(new_workspace, :(import ..($(old_workspace_name))))

    old_names = names(old_workspace, all=true, imported=true)

    for symbol in old_names
        if symbol ∉ vars_to_delete
            # var will not be redefined in the new workspace, move it over
            if !(symbol == :eval || symbol == :include || string(symbol)[1] == '#' || startswith(string(symbol), "workspace"))
                try
                    val = getfield(old_workspace, symbol)

                    # Expose the variable in the scope of `new_workspace`
                    Core.eval(new_workspace, :(import ..($(old_workspace_name)).$(symbol)))
                catch ex
                    @warn "Failed to move variable $(symbol) to new workspace:"
                    showerror(stderr, ex, stacktrace(catch_backtrace()))
                end
            end
        else
            # var will be redefined - unreference the value so that GC can snoop it

            # free memory for other variables
            # & delete methods created in the old module:
            # for example, the old module might extend an imported function:
            # `import Base: show; show(io::IO, x::Flower) = print(io, "🌷")`
            # when you delete/change this cell, you want this extension to disappear.
            if isdefined(old_workspace, symbol)
                # try_delete_toplevel_methods(old_workspace, symbol)

                try
                    # it could be that `symbol ∈ vars_to_move`, but the _value_ has already been moved to the new reference in `new_module`.
                    # so clearing the value of this reference does not affect the reference in `new_workspace`.
                    Core.eval(old_workspace, :($(symbol) = nothing))
                catch; end # sometimes impossible, eg. when $symbol was constant
            end
        end
    end
    try_delete_toplevel_methods.([old_workspace], funcs_to_delete)
end

"Return whether the `method` was defined inside this notebook, and not in external code."
isfromtoplevel(method::Method) = startswith(nameof(method.module) |> string, "workspace")

function delete_toplevel_methods(f::Function)
    # we can delete methods of functions!
    # instead of deleting all methods, we only delete methods that were defined in this notebook. This is necessary when the notebook code extends a function from remote code
    methods_table = typeof(f).name.mt
    deleted_sigs = Set{Type}()
    Base.visit(methods_table) do method # iterates through all methods of `f`, including overridden ones
        if isfromtoplevel(method) && getfield(method, deleted_world) == alive_world_val
            Base.delete_method(method)
            push!(deleted_sigs, method.sig)
        end
    end

    # if `f` is an extension to an external function, and we defined a method that overrides a method, for example,
    # we define `Base.isodd(n::Integer) = rand(Bool)`, which overrides the existing method `Base.isodd(n::Integer)`
    # calling `Base.delete_method` on this method won't bring back the old method, because our new method still exists in the method table, and it has a world age which is newer than the original. (our method has a deleted_world value set, which disables it)
    #
    # To solve this, we iterate again, and _re-enable any methods that were hidden in this way_, by adding them again to the method table with an even newer `primary_world`.
    if !isempty(deleted_sigs)
        to_insert = Set{Method}()
        Base.visit(methods_table) do method
            if !isfromtoplevel(method) && method.sig ∈ deleted_sigs
                push!(to_insert, method)
            end
        end
        # separate loop to avoid visiting the recently added method
        for method in to_insert
            setfield!(method, primary_world, one(typeof(alive_world_val))) # `1` will tell Julia to increment the world counter and set it as this function's world
            ccall(:jl_method_table_insert, Cvoid, (Any, Any, Ptr{Cvoid}), methods_table, method, C_NULL) # i dont like doing this either!
        end
    end
end

function try_delete_toplevel_methods(workspace::Module, name::Symbol)
    try_delete_toplevel_methods(workspace, [name])
end

function try_delete_toplevel_methods(workspace::Module, name_parts::Vector{Symbol})
    try
        val = workspace
        for name in name_parts
            val = getfield(val, name)
        end
        try
            (val isa Function) && delete_toplevel_methods(val)
        catch ex
            @warn "Failed to delete methods for $(name_parts)"
            showerror(stderr, ex, stacktrace(catch_backtrace()))
        end
    catch; end
end

const primary_world = filter(in(fieldnames(Method)), [:primary_world, :min_world]) |> first # Julia v1.3 and v1.0 resp.
const deleted_world = filter(in(fieldnames(Method)), [:deleted_world, :max_world]) |> first # Julia v1.3 and v1.0 resp.
const alive_world_val = getfield(methods(Base.sqrt).ms[1], deleted_world) # typemax(UInt) in Julia v1.3, Int(-1) in Julia 1.0

###
# FORMATTING
###

function try_showerror(io::IO, e, args...)
    try
        showerror(io, e, args...)
    catch show_ex
        print(io, "\nFailed to show error:\n\n")
        try_showerror(io, show_ex, stacktrace(catch_backtrace()))
    end
end

# We add a method for the Markdown -> HTML conversion that takes a LaTeX chunk from the Markdown tree and adds our custom span
function htmlinline(io::IO, x::LaTeX)
    withtag(io, :span, :class => "tex") do
        print(io, '$')
        htmlesc(io, x.formula)
        print(io, '$')
    end
end

# this one for block equations: (double $$)
function html(io::IO, x::LaTeX)
    withtag(io, :p, :class => "tex") do
        print(io, '$', '$')
        htmlesc(io, x.formula)
        print(io, '$', '$')
    end
end

"The `IOContext` used for converting arbitrary objects to pretty strings."
iocontext = IOContext(stdout, :color => false, :compact => true, :limit => true, :displaysize => (18, 120))
const imagemimes = [MIME"image/svg+xml"(), MIME"image/png"(), MIME"image/jpg"(), MIME"image/bmp"(), MIME"image/gif"()]
# in order of coolness
# text/plain always matches
const allmimes = [MIME"application/vnd.pluto.tree+xml"(); MIME"text/html"(); imagemimes; MIME"text/plain"()]

"""Format `val` using the richest possible output, return formatted string and used MIME type.

See `PlutoRunner.allmimes` for the ordered list of supported MIME types."""
function format_output(val::Any)::Tuple{String, MIME}
    try
        sprint_withreturned(show_richest, val; context=iocontext)
    catch ex
        title = ErrorException("Failed to show value: \n" * sprint(try_showerror, ex))
        bt = stacktrace(catch_backtrace())
        format_output(CapturedException(title, bt))
    end
end

format_output(val::Nothing)::Tuple{String, MIME} = "", MIME"text/plain"()

function format_output(val::CapturedException)::Tuple{String, MIME}
    ## We hide the part of the stacktrace that belongs to Pluto's evalling of user code.
    stack = [s for (s,_) in val.processed_bt]

    for _ in 1:2
        until = findfirst(b -> b.func == :eval, reverse(stack))
        stack = until === nothing ? stack : stack[1:(length(stack) - until)]
    end

    pretty = map(stack[1:end]) do s
        Dict(
            :call => pretty_stackcall(s, s.linfo),
            :inlined => s.inlined,
            :file => basename(String(s.file)),
            :line => s.line,
        )
    end
    sprint(json, Dict(:msg => sprint(try_showerror, val.ex), :stacktrace => pretty)), MIME"application/vnd.pluto.stacktrace+json"()
end

# from the Julia source code:
function pretty_stackcall(frame::Base.StackFrame, linfo::Nothing)
    if frame.func isa Symbol
        String(frame.func)
    else
        repr(frame.func)
    end
end

function pretty_stackcall(frame::Base.StackFrame, linfo::Core.CodeInfo)
    "top-level scope"
end

function pretty_stackcall(frame::Base.StackFrame, linfo::Core.MethodInstance)
    if linfo.def isa Method
        sprint(Base.show_tuple_as_call, linfo.def.name, linfo.specTypes)
    else
        sprint(Base.show, linfo)
    end
end

"Like `Base.sprint`, but return `(String, Any)` tuple containing function output as second entry."
function sprint_withreturned(f::Function, args...; context=nothing, sizehint::Integer=0)
    s = IOBuffer(sizehint=sizehint)
    val = if context !== nothing
        f(IOContext(s, context), args...)
    else
        f(s, args...)
    end
    String(resize!(s.data, s.size)), val
end

struct 🥔 end
const struct_showmethod = which(show, (IO, 🥔))
const struct_showmethod_mime = which(show, (IO, MIME"text/plain", 🥔))

function show_richest(io::IO, @nospecialize(x); onlyhtml::Bool=false)::MIME
    mime = Iterators.filter(m -> Base.invokelatest(showable, m, x), allmimes) |> first
    t = typeof(x)

    isstruct =
        mime isa MIME"text/plain" &&
        t isa DataType &&
        which(show, (IO, MIME"text/plain", t)) === struct_showmethod_mime &&
        which(show, (IO, t)) === struct_showmethod

    if isstruct
        # we have a struct with no specialised show function
        # we display it as an interactive tree
        show_struct(io, x)
        return MIME"application/vnd.pluto.tree+xml"()
    end

    if istextmime(mime)
        onlyhtml && (mime isa MIME"text/plain") && print(io, "
")
        show(io, mime, x)
        onlyhtml && (mime isa MIME"text/plain") && print(io, "
")
        return mime
    else
        enc_pipe = Base64.Base64EncodePipe(io)
        io_64 = IOContext(enc_pipe, iocontext)
        if onlyhtml
            print(io, "")
            return MIME"text/html"()
        else
            print(io, "data:", mime, ";base64,")
            show(io_64, mime, x)
            close(enc_pipe)
            return mime
        end
    end
end

###
# TREE VIEWER
###

tree_display_limit = 50

function show_array_row(io::IO, pair::Tuple)
    i, el = pair
    print(io, "<r><k>", i, "</k><v>")
    show_richest(io, el; onlyhtml=true)
    print(io, "</v></r>")
end

function show_dict_row(io::IO, pair::Pair)
    k, el = pair
    print(io, "<r><k>")
    show_richest(io, k; onlyhtml=true)
    print(io, "</k><v>")
    show_richest(io, el; onlyhtml=true)
    print(io, "</v></r>")
end

istextmime(::MIME"application/vnd.pluto.tree+xml") = true

function show(io::IO, ::MIME"application/vnd.pluto.tree+xml", x::AbstractArray{<:Any, 1})
    print(io, """<jltree class="collapsed" onclick="onjltreeclick(this, event)">""")
    print(io, eltype(x))
    print(io, "<jlarray>")
    if length(x) <= tree_display_limit
        show_array_row.([io], enumerate(x))
    else
        from_end = tree_display_limit > 20 ? 10 : 1
        show_array_row.([io], enumerate(x[1:tree_display_limit-from_end]))

        print(io, "<r><more></more></r>")

        indices = 1+length(x)-from_end:length(x)
        show_array_row.([io], zip(indices, x[indices]))
    end

    print(io, "</jlarray>")
    print(io, "</jltree>")
end

function show(io::IO, ::MIME"application/vnd.pluto.tree+xml", x::AbstractDict{<:Any, <:Any})
    print(io, """<jltree class="collapsed" onclick="onjltreeclick(this, event)">""")
    print(io, "Dict")
    print(io, "<jldict>")
    row_index = 1
    for pair in x
        show_dict_row(io, pair)
        if row_index == tree_display_limit
            print(io, "<r><more></more></r>")
            break
        end
        row_index += 1
    end

    print(io, "</jldict>")
    print(io, "</jltree>")
end

# Based on Julia source code, but HTML-ified
function show_struct(io::IO, @nospecialize(x))
    t = typeof(x)
    nf = nfields(x)
    nb = sizeof(x)
    if nf != 0 || nb == 0
        print(io, """<jltree class="collapsed" onclick="onjltreeclick(this, event)">""")
        show(io, t)
        print(io, "<jlstruct>")

        if !Base.show_circular(io, x)
            recur_io = IOContext(io, Pair{Symbol,Any}(:SHOWN_SET, x),
                                 Pair{Symbol,Any}(:typeinfo, Any))
            for i in 1:nf
                f = fieldname(t, i)
                if !isdefined(x, f)
                    print(io, "<r>", Base.undef_ref_str, "</r>")
                else
                    show_array_row(recur_io, (f, getfield(x, i)))
                end
            end
        end

        print(io, "</jlstruct>")
        print(io, "</jltree>")
    else
        Base.show_default(io, x)
    end
end

###
# JSON SERIALIZER
###

# We define a minimal JSON serializer here so that the notebook process does not need to depend on JSON.jl
# Performance is about 0.5-1.0x JSON.jl, but that's okay since it is only used for special output types like stack traces
# Not designed/tested for use outside of Pluto

struct ReplacePipe <: IO
	outstream::IO
end

# to get these character codes:
# [c => UInt8(c) for c in "\"\\/\b\f\n\r\t"]
# we can do this escaping per-byte because UTF-8 is backwards compatible with ASCII, i.e. these special characters are never part of a UTF-8 encoded character other than the ASCII characters they represent. Cool!
function Base.write(rp::ReplacePipe, x::UInt8)
	if x == 0x22 || x== 0x5c || x== 0x2f # https://www.json.org/json-en.html
        write(rp.outstream, '\\')
        write(rp.outstream, x)
    elseif x < 0x10 # ish
        write(rp.outstream, escape_string(String([Char(x)]))) # the Julia escaping 'happens' to coincide with what we want
    else
        write(rp.outstream, x)
    end
end
function sanitize_pipe(func::Function, outstream::IO, args...)
	func(ReplacePipe(outstream), args...)
end

function json(io, arr::AbstractArray)
    write(io, '[')
    len = length(arr)
    for (i, val) in enumerate(arr)
        json(io, val)
        (i != len) && write(io, ',')
    end
    write(io, ']')
end

function json(io, d::Dict{Symbol, T}) where T
    write(io, '{')
    len = length(d)
    for (i, val) in enumerate(d)
        write(io, '"', val.first, '"', ':')
        json(io, val.second)
        (i != len) && write(io, ',')
    end
    write(io, '}')
end

function json(io, str::T) where T<:AbstractString
    write(io, '"')
    sanitize_pipe(write, io, str)
    write(io, '"')
end

function json(io, val::Any)
    show(io, val)
end

###
# REPL THINGS
###

function completion_fetcher(query, pos, workspace::Module=current_module)
    results, loc, found = completions(query, pos, workspace)
    (completion_text.(results), loc, found)
end

function doc_fetcher(query, workspace::Module=current_module)
    try
        obj = Core.eval(workspace, Meta.parse(query))
        if obj isa Expr
            (nothing, :👎)
        else
            (repr(MIME"text/html"(), Docs.doc(obj)), :👍)
        end
    catch ex
        (nothing, :👎)
    end
end

###
# BONDS
###

struct Bond
    element::Any
    defines::Symbol
    Bond(element, defines::Symbol) = showable(MIME"text/html"(), element) ? new(element, defines) : error("""Can only bind to html-showable objects, ie types T for which show(io, ::MIME"text/html", x::T) is defined.""")
end

import Base: show
function show(io::IO, ::MIME"text/html", bond::Bond)
    print(io, "<bond def=\"$(bond.defines)\">")
    show(io, MIME"text/html"(), bond.element)
    print(io, "</bond>")
end

"""`@bind symbol element`

Returns the HTML `element`, and uses its latest JavaScript value as the definition of `symbol`.

# Example

```julia
@bind x html"<input type='range'>"
```
and in another cell:
```julia
x^2
```

The first cell will show a slider as the cell's output, ranging from 0 until 100.
The second cell will show the square of `x`, and is updated in real-time as the slider is moved.
"""
macro bind(def, element)
	if def isa Symbol
		quote
			local el = $(esc(element))
            global $(esc(def)) = Core.applicable(Base.peek, el) ? Base.peek(el) : missing
			PlutoRunner.Bond(el, $(Meta.quot(def)))
		end
	else
		:(throw(ArgumentError("""\nMacro example usage: \n\n\t@bind my_number html"<input type='range'>"\n\n""")))
	end
end

"Will be inserted in saved notebooks that use the @bind macro, make sure that they still contain legal syntax when executed as a vanilla Julia script. Overloading `Base.peek` for custom UI objects gives bound variables a sensible value."
const fake_bind = """macro bind(def, element)
    quote
        local el = \$(esc(element))
        global \$(esc(def)) = Core.applicable(Base.peek, el) ? Base.peek(el) : missing
        el
    end
end"""

end


text:
"""
    WarpedView(img, tform, [indices]) -> wv

Create a view of `img` that lazily transforms any given index `I`
passed to `wv[I]` to correspond to `img[tform(I)]`. This approach
is known as backward mode warping.

The optional parameter `indices` can be used to specify the
domain of the resulting `wv`. By default the indices are computed
in such a way that `wv` contains all the original pixels in
`img`. To do this `inv(tform)` has to be computed. If the given
transformation `tform` does not support `inv`, then the parameter
`indices` has to be specified manually.

see [`warpedview`](@ref) for more information.
"""
struct WarpedView{T,N,A<:AbstractArray,F<:Transformation,I<:Tuple,E<:AbstractExtrapolation} <: AbstractArray{T,N}
    parent::A
    transform::F
    indices::I
    extrapolation::E

    function WarpedView{T,N,TA,F,I}(
            parent::TA,
            tform::F,
            indices::I) where {T,N,TA<:AbstractArray,F<:Transformation,I<:Tuple}
        @assert eltype(parent) == T
        etp = box_extrapolation(parent)
        new{T,N,TA,F,I,typeof(etp)}(parent, tform, indices, etp)
    end
end

function WarpedView(
        A::AbstractArray{T,N},
        tform::F,
        inds::I = autorange(A, inv(tform))) where {T,N,F<:Transformation,I<:Tuple}
    WarpedView{T,N,typeof(A),F,I}(A, tform, inds)
end

Base.parent(A::WarpedView) = A.parent
@inline Base.axes(A::WarpedView) = A.indices

IndexStyle(::Type{T}) where {T<:WarpedView} = IndexCartesian()
@inline Base.getindex(A::WarpedView{T,N}, I::Vararg{Int,N}) where {T,N} =
    T(_getindex(A.extrapolation, A.transform(SVector(I))))
Base.size(A::WarpedView{T,N,TA,F}) where {T,N,TA,F}    = map(length,axes(A))
Base.size(A::WarpedView{T,N,TA,F}, d) where {T,N,TA,F} = length(axes(A,d))

Base.size(A::WarpedView{T,N,TA,F,NTuple{N,Base.OneTo{Int}}}) where {T,N,TA,F}    = map(length, A.indices)
Base.size(A::WarpedView{T,N,TA,F,NTuple{N,Base.OneTo{Int}}}, d) where {T,N,TA,F} = d <= N ? length(A.indices[d]) : 1

function Base.showarg(io::IO, A::WarpedView, toplevel)
    print(io, "WarpedView(")
    Base.showarg(io, parent(A), false)
    print(io, ", ")
    print(io, A.transform)
    if toplevel
        print(io, ") with eltype ", eltype(parent(A)))
    else
        print(io, ')')
    end
end

"""
    warpedview(img, tform, [indices], [degree = Linear()], [fill = NaN]) -> wv

Create a view of `img` that lazily transforms any given index `I`
passed to `wv[I]` to correspond to `img[tform(I)]`. This approach
is known as backward mode warping. The given transformation
`tform` must accept a `SVector` as input. A useful package to
create a wide variety of such transformations is
[CoordinateTransformations.jl](https://github.com/FugroRoames/CoordinateTransformations.jl).

When invoking `wv[I]`, values for `img` must be reconstructed at
arbitrary locations `tform(I)` which do not lie on to the lattice
of pixels. How this reconstruction is done depends on the type of
`img` and the optional parameter `degree`. When `img` is a plain
array, then on-grid b-spline interpolation will be used, where
the pixel of `img` will serve as the coeficients. It is possible
to configure what degree of b-spline to use with the parameter
`degree`. The two possible values are `degree = Linear()` for
linear interpolation, or `degree = Constant()` for nearest
neighbor interpolation.

In the case `tform(I)` maps to indices outside the domain of
`img`, those locations are set to a value `fill` (which defaults
to `NaN` if the element type supports it, and `0` otherwise).
Additionally, the parameter `fill` also accepts extrapolation
schemes, such as `Flat()`, `Periodic()` or `Reflect()`.

The optional parameter `indices` can be used to specify the
domain of the resulting `WarpedView`. By default the indices are
computed in such a way that the resulting `WarpedView` contains
all the original pixels in `img`. To do this `inv(tform)` has to
be computed. If the given transformation `tform` does not support
`inv`, then the parameter `indices` has to be specified manually.

`warpedview` is essentially a non-coping, lazy version of
[`warp`](@ref). As such, the two functions share the same
interface, with one important difference. `warpedview` will
insist that the resulting `WarpedView` will be a view of `img`
(i.e. `parent(warpedview(img, ...)) === img`). Consequently,
`warpedview` restricts the parameter `degree` to be either
`Linear()` or `Constant()`.
"""
@inline warpedview(A::AbstractArray, tform::Transformation, args...) =
    WarpedView(A, tform, args...)

function warpedview(
        A::AbstractArray{T},
        tform::Transformation,
        degree::Union{Linear,Constant},
        fill::FillType = _default_fill(T)) where T
    warpedview(box_extrapolation(A, degree, fill), tform)
end

function warpedview(
        A::AbstractArray{T},
        tform::Transformation,
        indices::Tuple,
        degree::Union{Linear,Constant},
        fill::FillType = _default_fill(T)) where T
    warpedview(box_extrapolation(A, degree, fill), tform, indices)
end

function warpedview(
        A::AbstractArray,
        tform::Transformation,
        fill::FillType)
    warpedview(A, tform, Linear(), fill)
end

function warpedview(
        A::AbstractArray,
        tform::Transformation,
        indices::Tuple,
        fill::FillType)
    warpedview(A, tform, indices, Linear(), fill)
end


text:
#=
Author : Ng Yeesian
Modified : Guy Farmer / Zander Tedjo / Will Worthington / Michael Hilborn
generates the closest dispatch model
=#
mutable struct ClosestDispatch <: DispatchModel
    drivetime::DataFrame
    candidates::Vector{Vector{Int}}
    available::Vector{Int}
    assignment::Vector{Int} # which location the ambulance is assigned to
    ambulances::Vector{Vector{Int}} # list of ambulances assigned to each location
    status::Vector{Symbol} # the current status of the ambulance
        # possible statuses: :available, :responding, :atscene, :conveying, :returning
    fromtime::Vector{Int} # the time it started the new status
    hospital::Vector{Int}
end

function ClosestDispatch(p::DeploymentProblem, drivetime::DataFrame,distribution::Vector{Int})
    candidates = Any[]
    I = 1:p.nlocations
    for region in 1:p.nregions
        push!(candidates, I[vec(p.coverage[region,:])])
    end

    assignment = zeros(Int, p.nambulances)
    ambulances = [Int[] for i in 1:p.nlocations]
    k = 1
    for i in eachindex(distribution), j in 1:distribution[i]
        assignment[k] = i
        push!(ambulances[i], k)
        k += 1
    end
    status = fill(:available, p.nambulances)
    fromtime = zeros(Int, p.nambulances)
    hospital = zeros(Int, p.nambulances)

    ClosestDispatch(drivetime, candidates, distribution, assignment, ambulances, status, fromtime, hospital)

end

function ClosestDispatch(p::DeploymentProblem, problem::DispatchProblem)
    stn_names = [Symbol("stn$(i)_min") for i in 1:size(p.coverage,2)]
    ClosestDispatch(p, problem.emergency_calls[:, stn_names], problem.available)
end

function update_ambulances!(model::ClosestDispatch, i::Int, delta::Int)
    model.available[i] += delta
    @assert model.available[i] >= 0
end

function closest_available(dispatch::ClosestDispatch, id::Int, problem::DispatchProblem)
    location = 0
    min_time = Inf
    for i in dispatch.candidates[problem.emergency_calls[id, :neighborhood]]
        if problem.available[i] > 0 && dispatch.drivetime[id, i] < min_time
            location = i
            min_time = dispatch.drivetime[id, i]
        end
    end
    location
end

function respond_to!(dispatch::ClosestDispatch, i::Int, t::Int)
    @assert length(dispatch.ambulances[i]) > 0 "$i: $(dispatch.ambulances[i])"
    amb = popfirst!(dispatch.ambulances[i])
    @assert amb != 0
    @assert dispatch.status[amb] == :available "$amb: $(dispatch.status[amb])"
    dispatch.status[amb] = :responding
    amb
end

function arriveatscene!(dispatch::ClosestDispatch, amb::Int, t::Int)
    @assert dispatch.status[amb] == :responding "$amb: $(dispatch.status[amb])"
    @assert dispatch.hospital[amb] == 0
    dispatch.status[amb] = :atscene
    dispatch.fromtime[amb] = t
end

function arriveathospital!(dispatch::DispatchModel, amb::Int, hosp::Int, t::Int)
    @assert dispatch.status[amb] == :atscene "$amb: $(dispatch.status[amb])"
    @assert dispatch.hospital[amb] != 0
    dispatch.status[amb] = :atHospital
    dispatch.fromtime[amb] = t
    dispatch.hospital[amb] = hosp
end

function returning_to!(dispatch::DispatchModel, amb::Int, t::Int)
    @assert dispatch.status[amb] == :atHospital "$amb: $(dispatch.status[amb])"
    @assert dispatch.hospital[amb] != 0
    dispatch.status[amb] = :returning
    dispatch.fromtime[amb] = t
    dispatch.assignment[amb]
end

max_stars_repo_name: michaelhilborn/AmbulanceDeployement

max_issues_repo_name: joshua-ong/AmbulanceDeployment

max_forks_repo_name: joshua-ong/AmbulanceDeployment


text:
using ForneyLab
using LinearAlgebra
import ForneyLab: SoftFactor, @ensureVariables, generateId, addNode!, associate!,
                  averageEnergy, Interface, Variable, slug, ProbabilityDistribution,
                  differentialEntropy, unsafeLogMean, unsafeMean, unsafeCov, unsafePrecision, unsafeMeanCov
export AutoRegressiveMovingAverage, ARMA

"""
Description:

    An AutoRegressive model with Moving Average (ARMA)

    y_k = θ'⋅[y_k-1, …, y_k-M1, e_k-1, … e_k-M2] + e_k

    where M1 is the number of previous observations and M2 the number of previous residuals.
    These histories are stored as the following vectors:
    - z_k-1 = [y_k-1, …, y_k-M1]'
    - r_k-1 = [e_k-1, …, e_k-M2]'.

    Assume y_k, z_k-1 and r_k-1 are observed and e_k ~ N(0, τ^-1).

Interfaces:

    1. y (output)
    2. θ (function coefficients)
    3. z (previous observations vector)
    6. r (previous residuals)
    7. τ (precision)

Construction:

    AutoRegressiveMovingAverage(y, θ, z, r, τ, id=:some_id)
"""

mutable struct AutoRegressiveMovingAverage <: SoftFactor
    id::Symbol
    interfaces::Vector{Interface}
    i::Dict{Symbol,Interface}

    function AutoRegressiveMovingAverage(y, θ, z, r, τ; id=generateId(AutoRegressiveMovingAverage))
        @ensureVariables(y, θ, z, r, τ)
        self = new(id, Array{Interface}(undef, 5), Dict{Symbol,Interface}())
        addNode!(currentGraph(), self)
        self.i[:y] = self.interfaces[1] = associate!(Interface(self), y)
        self.i[:θ] = self.interfaces[2] = associate!(Interface(self), θ)
        self.i[:z] = self.interfaces[3] = associate!(Interface(self), z)
        self.i[:r] = self.interfaces[4] = associate!(Interface(self), r)
        self.i[:τ] = self.interfaces[5] = associate!(Interface(self), τ)
        return self
    end
end

slug(::Type{AutoRegressiveMovingAverage}) = "ARMA"

function averageEnergy(::Type{AutoRegressiveMovingAverage},
                       marg_y::ProbabilityDistribution{Univariate},
                       marg_θ::ProbabilityDistribution{Multivariate},
                       marg_z::ProbabilityDistribution{Multivariate},
                       marg_r::ProbabilityDistribution{Multivariate},
                       marg_τ::ProbabilityDistribution{Univariate})

        my = unsafeMean(marg_y)
        mz = unsafeMean(marg_z)
        mr = unsafeMean(marg_r)
        x = [mz; mr]

        mθ = unsafeMean(marg_θ)
        Vθ = unsafeCov(marg_θ)
        mτ = unsafeMean(marg_τ)

        aτ = marg_τ.params[:a]
        bτ = marg_τ.params[:b]

        temp1 = -(1. / 2.)*digamma(aτ).-(1. / 2.)*log(bτ).+(1. / 2.)*log(2*pi) # 0.5 log(2 pi) ~= 0.4
        temp2 = (1. / 2.).* mτ.*(my.^2 .-2 .*my.*mθ'*x.+x'*(Vθ.+mθ*mθ')*x)
        return (temp1.+temp2)[1]
end

max_stars_repo_name: wmkouw/ARMA

max_issues_repo_name: wmkouw/ARMA

max_forks_repo_name: wmkouw/ARMA


text:
export Add

"""
    Add{D} <: CompositeBlock{D}
    Add(blocks::AbstractBlock...) -> Add
"""
struct Add{D} <: CompositeBlock{D}
    n::Int
    list::Vector{AbstractBlock{D}}
    Add(n::Int, blocks::Vector{AbstractBlock{D}}) where {D} = new{D}(_check_block_sizes(blocks, n), blocks)
    Add(blocks::Vector{AbstractBlock{D}}) where {D} = new{D}(_check_block_sizes(blocks), blocks)
    Add(n::Int; nlevel=2) = new{nlevel}(n, AbstractBlock{nlevel}[])
end

Add(blocks::NTuple{M,AbstractBlock{D}}) where {M,D} = Add(collect(AbstractBlock{D}, blocks))
Add(n::Int, blocks::AbstractVector{<:AbstractBlock{D}}) where {D} = Add(n, collect(AbstractBlock{D}, blocks))
Add(blocks::AbstractVector{<:AbstractBlock{D}}) where {D} = Add(collect(AbstractBlock{D}, blocks))
Add(blocks::AbstractBlock{D}...) where {D} = Add(collect(AbstractBlock{D}, blocks))
nqudits(add::Add) = add.n

function mat(::Type{T}, x::Add{D}) where {D,T}
    length(x.list) == 0 && return Diagonal(zeros(T, D^x.n))
    mapreduce(x -> mat(T, x), +, x.list)
end

chsubblocks(x::Add, it) = Add(it)

function _apply!(r::AbstractRegister, x::Add)
    isempty(x.list) && return r
    length(x.list) == 1 && return _apply!(r, x.list[])

    res = mapreduce(blk -> _apply!(copy(r), blk), regadd!, x.list[1:end-1])
    _apply!(r, x.list[end])
    regadd!(r, res)
    r
end

export Add

subblocks(x::Add) = x.list
cache_key(x::Add) = map(cache_key, x.list)
Base.copy(x::Add) = Add(x.n, copy(x.list))
Base.similar(c::Add) = Add(c.n, empty!(similar(c.list)))

function Base.:(==)(lhs::Add{D}, rhs::Add{D}) where {D}
    nqudits(lhs) == nqudits(rhs) && (length(lhs.list) == length(rhs.list)) && all(lhs.list .== rhs.list)
end

for FUNC in [:length, :iterate, :getindex, :eltype, :eachindex, :popfirst!, :lastindex]
    @eval Base.$FUNC(x::Add, args...) = $FUNC(subblocks(x), args...)
end

Base.getindex(c::Add{D}, index::Union{UnitRange,Vector}) where {D} =
    Add(c.n, getindex(c.list, index))
Base.setindex!(c::Add{D}, val::AbstractBlock{D}, index::Integer) where {D} =
    (setindex!(c.list, val, index); c)
Base.insert!(c::Add{D}, index::Integer, val::AbstractBlock{D}) where {D} =
    (insert!(c.list, index, val); c)
Base.adjoint(blk::Add{D}) where {D} = Add(blk.n, map(adjoint, subblocks(blk)))

## Iterate contained blocks
occupied_locs(c::Add) =
    (unique(Iterators.flatten(occupied_locs(b) for b in subblocks(c)))...,)

# Additional Methods for Add
Base.push!(c::Add{D}, val::AbstractBlock{D}) where {D} = (_check_block_sizes(c, val); push!(c.list, val); c)

function Base.push!(c::Add{D}, val::Function) where {D}
    push!(c, val(c.n))
end

function Base.append!(c::Add, list)
    for blk in list
        push!(c, blk)
    end
    c
end

function Base.prepend!(c::Add, list)
    for blk in list[end:-1:1]
        insert!(c, 1, blk)
    end
    c
end

YaoBase.ishermitian(ad::Add) = all(ishermitian, ad.list) || ishermitian(mat(ad))


text:
using Contour

### /HJI_values
function initialize_HJI_values_marker!(m, cache=X1CMPC.HJI_cache)
    m.header.frame_id = "x1"
    m.type = Marker[:TRIANGLE_LIST]
    m.pose.orientation.w = 1.0
    m.scale.x = 1.0
    m.scale.y = 1.0
    m.scale.z = 1.0
    m.frame_locked = true
    X = cache.grid_knots[1]
    Y = cache.grid_knots[2]
    for i in 1:length(X)-1, j in 1:length(Y)-1
        push!(m.points, Point(X[i]  , Y[j]  , -0.1)); push!(m.colors, ColorRGBA(1.0, 1.0, 1.0, 1.0))
        push!(m.points, Point(X[i+1], Y[j]  , -0.1)); push!(m.colors, ColorRGBA(1.0, 1.0, 1.0, 1.0))
        push!(m.points, Point(X[i+1], Y[j+1], -0.1)); push!(m.colors, ColorRGBA(1.0, 1.0, 1.0, 1.0))
        push!(m.points, Point(X[i]  , Y[j]  , -0.1)); push!(m.colors, ColorRGBA(1.0, 1.0, 1.0, 1.0))
        push!(m.points, Point(X[i]  , Y[j+1], -0.1)); push!(m.colors, ColorRGBA(1.0, 1.0, 1.0, 1.0))
        push!(m.points, Point(X[i+1], Y[j+1], -0.1)); push!(m.colors, ColorRGBA(1.0, 1.0, 1.0, 1.0))
    end
end
function update_HJI_values_marker!(m, q, cache=X1CMPC.HJI_cache)
    X = cache.grid_knots[1]
    Y = cache.grid_knots[2]
    ct = 1
    for i in 1:length(X)-1, j in 1:length(Y)-1
        for (x,y) in ((X[i]  , Y[j]  ),
                      (X[i+1], Y[j]  ),
                      (X[i+1], Y[j+1]),
                      (X[i]  , Y[j]  ),
                      (X[i]  , Y[j+1]),
                      (X[i+1], Y[j+1]))
            q = HJIRelativeState{Float32}(x, y, q[3], q[4], q[5], q[6], q[7])
            color = m.colors[ct]
            color.r, color.g, color.b = value_to_RGB(cache[q].V)
            ct += 1
        end
    end
end
function value_to_RGB(V, V_lo=-3.0, V_hi=20.0, C_lo = SVector(1.0, 0.5, 0.0), C_hi = SVector(0.0, 0.5, 1.0))
    x = clamp(ifelse(V < 0, 0.5*(V_lo - V)/V_lo, 0.5 + 0.5*V/V_hi), 0.0, 1.0)
    (1 - x)*C_lo + x*C_hi
end

const HJI_values_marker = Marker()
initialize_HJI_values_marker!(HJI_values_marker)

### /HJI_contour
function initialize_HJI_contour_marker!(m, cache=X1CMPC.HJI_cache)
    m.header.frame_id = "x1"
    m.type = Marker[:LINE_STRIP]
    m.pose.orientation.w = 1.0
    m.scale.x = 0.1
    m.scale.y = 0.1
    m.scale.z = 0.1
    m.frame_locked = true
    m.color = ColorRGBA(1.0, 1.0, 1.0, 1.0)
end
function update_HJI_contour_marker!(m, q, cache=X1CMPC.HJI_cache)
    X = cache.grid_knots[1]
    Y = cache.grid_knots[2]
    c = contour(X, Y, [cache[HJIRelativeState{Float32}(x, y, q[3], q[4], q[5], q[6], q[7])].V for x in X, y in Y], Float32(0))
    if isempty(c.lines) || isempty(c.lines[1].vertices)
        resize!(m.points, 0)
    else
        m.points = [Point(x, y, -0.05) for (x,y) in c.lines[1].vertices]
    end
end

const HJI_contour_marker = Marker()
initialize_HJI_contour_marker!(HJI_contour_marker)

max_stars_repo_name: Michelle-NYX/CollisionAvoidance

max_issues_repo_name: Michelle-NYX/CollisionAvoidance

max_forks_repo_name: Michelle-NYX/CollisionAvoidance


text:
#
#using Debug
function rand_pert(x,randmag=10.0)
a = 1.0/randmag
b = randmag

r = a + (b-a).*rand(size(x)[1],1)

return r.*x
end

function generate_random_set(objective_function,parameter_array_original,write_out,randmag=10.0,popsize=1000)

EC_array = []
for i in 1:popsize
parameter_array_active = rand_pert(original_parameter_array)
EC=objective_function(parameter_array_active)
@show i
open(write_out,"a") do f
    writecsv(f,EC)
end
push!(EC_array,EC)
end

return EC_array
end


text:
##
# Represent an m x n rank-r matrix
# A = U*Vᵗ
##
function _LowRankMatrix end

mutable struct LowRankMatrix{T} <: AbstractMatrix{T}
    U::Matrix{T} # m x r Matrix
    V::Matrix{T} # n x r Matrix

    global function _LowRankMatrix(U::AbstractMatrix{T}, V::AbstractMatrix{T}) where T
        m,r = size(U)
        n,rv = size(V)
        if r ≠ rv throw(ArgumentError("U and V must have same number of columns")) end
        new{T}(Matrix{T}(U), Matrix{T}(V))
    end
end

_LowRankMatrix(U::AbstractMatrix, V::AbstractMatrix) = _LowRankMatrix(promote(U,V)...)
_LowRankMatrix(U::AbstractVector, V::AbstractMatrix) = _LowRankMatrix(reshape(U,length(U),1),V)
_LowRankMatrix(U::AbstractMatrix, V::AbstractVector) = _LowRankMatrix(U,reshape(V,length(V),1))
_LowRankMatrix(U::AbstractVector, V::AbstractVector) =
    _LowRankMatrix(reshape(U,length(U),1), reshape(V,length(V),1))

LowRankMatrix{T}(::UndefInitializer, mn::NTuple{2,Int}, r::Int) where {T} =
    _LowRankMatrix(Matrix{T}(undef,mn[1],r),Matrix{T}(undef,mn[2],r))
LowRankMatrix{T}(Z::Zeros, r::Int=0) where {T<:Number} =
    _LowRankMatrix(zeros(T,size(Z,1),r), zeros(T,size(Z,2),r))
LowRankMatrix{T}(Z::Zeros, r::Int=0) where {T} =
    _LowRankMatrix(zeros(T,size(Z,1),r), zeros(T,size(Z,2),r))

LowRankMatrix(Z::Zeros, r::Int=0) = LowRankMatrix{eltype(Z)}(Z, r)
function LowRankMatrix{T}(F::AbstractFill) where T
    v = T(FillArrays.getindex_value(F))
    m,n = size(F)
    _LowRankMatrix(fill(v,m,1), fill(one(T),n,1))
end
LowRankMatrix(F::AbstractFill{T}) where T = LowRankMatrix{T}(F)

similar(L::LowRankMatrix, ::Type{T}, dims::Dims{2}) where {T} = LowRankMatrix{T}(undef, dims, rank(L))
similar(L::LowRankMatrix{T}) where {T} = LowRankMatrix{T}(undef, size(L), rank(L))
similar(L::LowRankMatrix{T}, dims::Dims{2}) where {T} = LowRankMatrix(undef, dims, rank(L))
similar(L::LowRankMatrix{T}, m::Int) where {T} = Vector{T}(undef, m)
similar(L::LowRankMatrix{T}, ::Type{S}) where {S,T} = LowRankMatrix{S}(undef, size(L), rank(L))

function LowRankMatrix{T}(A::AbstractMatrix{T}) where T
    U,Σ,V = svd(A)
    r = refactorsvd!(U,Σ,V)
    _LowRankMatrix(U[:,1:r], V[:,1:r])
end

LowRankMatrix{T}(A::AbstractMatrix) where T = LowRankMatrix{T}(AbstractMatrix{T}(A))
LowRankMatrix(A::AbstractMatrix{T}) where T = LowRankMatrix{T}(A)

balance!(U::Matrix{T}, V::Matrix{T}, m::Int, n::Int, r::Int) where {T<:Union{Integer,Rational}} = U,V
function balance!(U::Matrix{T}, V::Matrix{T}, m::Int, n::Int, r::Int) where T
    for k=1:r
        uk = zero(T)
        for i=1:m
            @inbounds uk += abs2(U[i,k])
        end
        vk = zero(T)
        for j=1:n
            @inbounds vk += abs2(V[j,k])
        end
        uk,vk = sqrt(uk),sqrt(vk)
        σk = sqrt(uk*vk)
        if abs2(uk) ≥ eps(T)^2 && abs2(vk) ≥ eps(T)^2
            uk,vk = σk/uk,σk/vk
            for i=1:m
                @inbounds U[i,k] *= uk
            end
            for j=1:n
                @inbounds V[j,k] *= vk
            end
        end
    end
    U,V
end

# Moves Σ into U and V
function refactorsvd!(U::AbstractMatrix{S}, Σ::AbstractVector{T}, V::AbstractMatrix{S}) where {S,T}
    conj!(V)
    σmax = Σ[1]
    r = count(s->s>10σmax*eps(T),Σ)
    m,n = size(U,1),size(V,1)
    for k=1:r
        σk = sqrt(Σ[k])
        for i=1:m
            @inbounds U[i,k] *= σk
        end
        for j=1:n
            @inbounds V[j,k] *= σk
        end
    end
    r
end

for MAT in (:LowRankMatrix, :AbstractMatrix, :AbstractArray)
    @eval convert(::Type{$MAT{T}}, L::LowRankMatrix) where {T} =
        _LowRankMatrix(convert(Matrix{T}, L.U), convert(Matrix{T}, L.V))
end
convert(::Type{Matrix{T}}, L::LowRankMatrix) where {T} = convert(Matrix{T}, Matrix(L))
promote_rule(::Type{LowRankMatrix{T}}, ::Type{LowRankMatrix{V}}) where {T,V} = LowRankMatrix{promote_type(T,V)}
promote_rule(::Type{LowRankMatrix{T}}, ::Type{Matrix{V}}) where {T,V} = Matrix{promote_type(T,V)}

size(L::LowRankMatrix) = size(L.U,1),size(L.V,1)
rank(L::LowRankMatrix) = size(L.U,2)
transpose(L::LowRankMatrix) = LowRankMatrix(L.V,L.U) # TODO: change for 0.7
adjoint(L::LowRankMatrix{T}) where {T<:Real} = LowRankMatrix(L.V,L.U)
adjoint(L::LowRankMatrix) = LowRankMatrix(conj(L.V),conj(L.U))
fill!(L::LowRankMatrix{T}, x::T) where {T} = (fill!(L.U, sqrt(abs(x)/rank(L))); fill!(L.V,sqrt(abs(x)/rank(L))/sign(x)); L)

function unsafe_getindex(L::LowRankMatrix, i::Int, j::Int)
    ret = zero(eltype(L))
    @inbounds for k=1:rank(L)
        ret = muladd(L.U[i,k],L.V[j,k],ret)
    end
    return ret
end

function getindex(L::LowRankMatrix, i::Int, j::Int)
    m,n = size(L)
    if 1 ≤ i ≤ m && 1 ≤ j ≤ n
        unsafe_getindex(L,i,j)
    else
        throw(BoundsError())
    end
end
getindex(L::LowRankMatrix, i::Int, jr::AbstractRange) = transpose(eltype(L)[L[i,j] for j=jr])
getindex(L::LowRankMatrix, ir::AbstractRange, j::Int) = eltype(L)[L[i,j] for i=ir]
getindex(L::LowRankMatrix, ir::AbstractRange, jr::AbstractRange) = eltype(L)[L[i,j] for i=ir,j=jr]
Matrix(L::LowRankMatrix) = L[1:size(L,1),1:size(L,2)]

# constructors

copy(L::LowRankMatrix) = _LowRankMatrix(copy(L.U),copy(L.V))
copyto!(L::LowRankMatrix, N::LowRankMatrix) = (copyto!(L.U,N.U); copyto!(L.V,N.V);L)

# algebra

for op in (:+,:-)
    @eval begin
        $op(L::LowRankMatrix) = LowRankMatrix($op(L.U),L.V)

        $op(a::Bool, L::LowRankMatrix{Bool}) = error("Not callable")
        $op(L::LowRankMatrix{Bool}, a::Bool) = error("Not callable")
        $op(a::Number,L::LowRankMatrix) = $op(LowRankMatrix(Fill(a,size(L))), L)
        $op(L::LowRankMatrix,a::Number) = $op(L, LowRankMatrix(Fill(a,size(L))))

        function $op(L::LowRankMatrix, M::LowRankMatrix)
            size(L) == size(M) || throw(DimensionMismatch("A has dimensions $(size(L)) but B has dimensions $(size(M))"))
            _LowRankMatrix(hcat(L.U,$op(M.U)), hcat(L.V,M.V))
        end
        $op(L::LowRankMatrix,A::Matrix) = $op(promote(L,A)...)
        $op(A::Matrix,L::LowRankMatrix) = $op(promote(A,L)...)
    end
end

*(a::Number, L::LowRankMatrix) = _LowRankMatrix(a*L.U,L.V)
*(L::LowRankMatrix, a::Number) = _LowRankMatrix(L.U,L.V*a)

# override default:

    *(A::LowRankMatrix, B::Adjoint{T,LowRankMatrix{T}}) where T = A*adjoint(B)

    function mul!(b::AbstractVector, L::LowRankMatrix, x::AbstractVector)
        temp = zeros(promote_type(eltype(L),eltype(x)), rank(L))
        mul!(temp, transpose(L.V), x)
        mul!(b, L.U, temp)
        b
    end
    function *(L::LowRankMatrix, M::LowRankMatrix)
        T = promote_type(eltype(L),eltype(M))
        temp = zeros(T,rank(L),rank(M))
        mul!(temp, transpose(L.V), M.U)
        V = zeros(T,size(M,2),rank(L))
        mul!(V, M.V, transpose(temp))
        _LowRankMatrix(copy(L.U),V)
    end

    function *(L::LowRankMatrix, A::Matrix)
        V = zeros(promote_type(eltype(L),eltype(A)),size(A,2),rank(L))
        mul!(V, transpose(A), L.V)
        _LowRankMatrix(copy(L.U),V)
    end

function *(A::Matrix, L::LowRankMatrix)
    U = zeros(promote_type(eltype(A),eltype(L)),size(A,1),rank(L))
    mul!(U,A,L.U)
    _LowRankMatrix(U,copy(L.V))
end

\(L::LowRankMatrix, b::AbstractVecOrMat) = transpose(L.V) \ (L.U \ b)


text:
# Time units

## --------------  Endowments
# One model time unit is `hoursPerWeek = 112` data hours per week.
# This is also the time endowment.

# 7 * 16 hours per week
const weeksPerYear = 52
const daysPerYear = 365
const hoursPerWeek = 112
const hoursPerYear = hoursPerWeek * weeksPerYear;

## ------------  Convert data to model time units

# Convert model time units into hours per week
function mtu_to_hours_per_week(mtu)
    hoursPerWeek .* mtu;
end

function hours_per_week_to_mtu(hours)
    return hours ./ hoursPerWeek;
end

function time_factor(timeUnit :: Symbol)
    if timeUnit == :weeksPerYear
        tf = weeksPerYear;
    elseif timeUnit == :daysPerYear
        tf = daysPerYear;
    elseif timeUnit == :hoursPerYear
        tf = hoursPerYear;
    elseif timeUnit == :hoursPerWeek
        tf = hoursPerWeek;
    else
        error("Invalid timeUnit: $timeUnit")
    end
    return tf
end

"""
	$(SIGNATURES)

Convert arbitrary data hours into model time units.
"""
function hours_data_to_mtu(hours, timeUnit :: Symbol)
    tf = time_factor(timeUnit);
    return hours ./ tf
end

function hours_mtu_to_data(hours, timeUnit :: Symbol)
    tf = time_factor(timeUnit);
    return hours .* tf
end

"""
	$(SIGNATURES)

Convert hours per year to hours per week.
"""
per_year_to_per_week(hours) =
    hours ./ time_factor(:weeksPerYear);

## -------------  Validate model time units

"""
	$(SIGNATURES)

Validate model time units
"""
function validate_mtu(mtu)
    if any(mtu .< 0.0)  ||  any(mtu .> 1.0)
        error("""
            Invalid time input:
            $mtu
        """);
    end
    return nothing
end

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


text:
using MyUtils
using Documenter

DocMeta.setdocmeta!(MyUtils, :DocTestSetup, :(using MyUtils); recursive=true)

makedocs(;
    modules=[MyUtils],
    authors="genkuroki <genkuroki@gmail.com> and contributors",
    repo="https://github.com/genkuroki/MyUtils.jl/blob/{commit}{path}#{line}",
    sitename="MyUtils.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://genkuroki.github.io/MyUtils.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
    ],
)

deploydocs(;
    repo="github.com/genkuroki/MyUtils.jl",
)


text:
using Test
using CryptoGroups: @bin_str, @hex_str, ECP, specialize, ECPoint, <|, generator, octet, Hash, gx, gy, order, modinv
using CryptoGroups.Specs: octet2int

curve_spec = ECP(;
                 p = 6277101735386680763835789423207666416083908700390324961279,
                 n = 6277101735386680763835789423176059013767194773182842284081,
                 h = 1,
                 a = hex"FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFFFF FFFFFFFC",
                 b = hex"64210519 E59C80E7 0FA7E9AB 72243049 FEB8DEEC C146B9B1",
                 G = hex"03 188DA80E B03090F6 7CBF20EB 43A18800 F4FF0AFD 82FF1012",
)

P = specialize(ECPoint, curve_spec)
G = P <| generator(curve_spec)

# Key Generation

d = 651056770906015076056810763456358567190100156695615665659
Q = d*G

@test octet(Q; mode=:compressed) == hex"02 62B12D60 690CDCF3 30BABAB6 E69763B4 71F994DD 702D16A5"

# Signature Generation

M = "abc"
#H = Hash("sha256")
H = Hash("SHA1")
e = octet2int(H(M))

@test e == 968236873715988614170569073515315707566766479517

k = 6140507067065001063065065565667405560006161556565665656654

R = k*G

x₁ = octet(gx(R))
y₁ = octet(gy(R))

@test x₁ == hex"88505238 0FF147B7 34C330C4 3D39B2C4 A89F29B0 F749FEAD"
@test y₁ == hex"9CF9FA1C BEFEFB91 7747A3BB 29C072B9 289C2547 884FD835"

x̄₁ = octet2int(x₁)

@test x̄₁ == 3342403536405981729393488334694600415596881826869351677613

n = order(P)

r = x̄₁ % n

@test r == 3342403536405981729393488334694600415596881826869351677613

s = modinv(k, n) * (e + d*r) % n

@test s == 5735822328888155254683894997897571951568553642892029982342

println("""The signature is:
    r = $r
    s = $s
""")

# Signature verification

(r′, s′) = r, s

M′ = "abc"
H′ = Hash("sha256")
e′ = octet2int(H(M′))

@test 1 < r′ < n - 1
@test 1 < s′ < n - 1

c = modinv(s′, n)

@test c == 3250964404472526825130516490452346217749189704049629042861

u₁ = e′*c % n
u₂ = r′*c % n

@test u₁ == 2563697409189434185194736134579731015366492496392189760599
@test u₂ == 6266643813348617967186477710235785849136406323338782220568

W = u₁*G + u₂*Q
x₁ = octet(gx(W))
y₁ = octet(gy(W))

@test x₁ == hex"88505238 0FF147B7 34C330C4 3D39B2C4 A89F29B0 F749FEAD"
@test y₁ == hex"9CF9FA1C BEFEFB91 7747A3BB 29C072B9 289C2547 884FD835"

x̄₁ = octet2int(x₁)

ν = x̄₁ % n

@test ν == r′


text:
if VERSION >= v"0.7.0-DEV.3382"
    import Libdl
end

# Load in `deps.jl`, complaining if it does not exist
const depsjl_path = joinpath(dirname(@__FILE__), "..", "deps", "deps.jl")
if !isfile(depsjl_path)
    error("BKMaxflow was not build properly. Please run Pkg.build(\"BKMaxflow\")")
end
include(depsjl_path)

# Module initialization function
function __init__()
    # Always check your dependencies from `deps.jl`
    check_deps()
end

include(joinpath(@__DIR__, "..", "gen", "api", "bk_common.jl"))
include(joinpath(@__DIR__, "..", "gen", "api", "bk_api.jl"))
# high-level
export create_graph, delete_graph, check_error
export add_node, add_tweights, add_edge
export maxflow, what_segment
# low-level
export bk_error, bk_error_message, bk_error_release
export bk_create_graph_int, bk_create_graph_short, bk_create_graph_float, bk_create_graph_double
export bk_delete_graph_int, bk_delete_graph_short, bk_delete_graph_float, bk_delete_graph_double
export bk_add_node_int, bk_add_node_short, bk_add_node_float, bk_add_node_double
export bk_add_tweights_int, bk_add_tweights_short, bk_add_tweights_float, bk_add_tweights_double
export bk_add_edge_int, bk_add_edge_short, bk_add_edge_float, bk_add_edge_double
export bk_maxflow_int, bk_maxflow_short, bk_maxflow_float, bk_maxflow_double
export bk_what_segment_int, bk_what_segment_short, bk_what_segment_float, bk_what_segment_double

function check_error(err)
    if err[] != C_NULL
        message = unsafe_string(bk_error_message(err[]))
        error("$message")
    end
    bk_error_release(err[])
end

@generated function create_graph(::Type{CImpl{Tv}}, node_num_max::Integer, edge_num_max::Integer) where {Tv<:Real}
    if Tv == Cint
        return quote
            err = Ref{bk_error}(C_NULL)
            graph = bk_create_graph_int(node_num_max, edge_num_max, err[])
            check_error(err)
            graph
        end
    elseif Tv == Cshort
        return quote
            err = Ref{bk_error}(C_NULL)
            graph = bk_create_graph_short(node_num_max, edge_num_max, err[])
            check_error(err)
            graph
        end
    elseif Tv == Cfloat
        return quote
            err = Ref{bk_error}(C_NULL)
            graph = bk_create_graph_float(node_num_max, edge_num_max, err[])
            check_error(err)
            graph
        end
    elseif Tv == Cdouble
        return quote
            err = Ref{bk_error}(C_NULL)
            graph = bk_create_graph_double(node_num_max, edge_num_max, err[])
            check_error(err)
            graph
        end
    end
end

@generated function delete_graph(::Type{CImpl{Tv}}, graph::Ptr{Cvoid}) where {Tv<:Real}
    if Tv == Cint
        return :(bk_delete_graph_int(graph))
    elseif Tv == Cshort
        return :(bk_delete_graph_short(graph))
    elseif Tv == Cfloat
        return :(bk_delete_graph_float(graph))
    elseif Tv == Cdouble
        return :(bk_delete_graph_double(graph))
    end
end

@generated function add_node(::Type{CImpl{Tv}}, graph::Ptr{Cvoid}, num::Integer=1) where {Tv<:Real}
    if Tv == Cint
        return quote
            err = Ref{bk_error}(C_NULL)
            n = bk_add_node_int(graph, num, err[])
            check_error(err)
            n
        end
    elseif Tv == Cshort
        return quote
            err = Ref{bk_error}(C_NULL)
            n = bk_add_node_short(graph, num, err[])
            check_error(err)
            n
        end
    elseif Tv == Cfloat
        return quote
            err = Ref{bk_error}(C_NULL)
            n = bk_add_node_float(graph, num, err[])
            check_error(err)
            n
        end
    elseif Tv == Cdouble
        return quote
            err = Ref{bk_error}(C_NULL)
            n = bk_add_node_double(graph, num, err[])
            check_error(err)
            n
        end
    end
end

@generated function add_tweights(::Type{CImpl}, graph::Ptr{Cvoid}, id::Integer, cap_source::Tv, cap_sink::Tv) where {Tv<:Real}
    if Tv == Cint
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_tweights_int(graph, id, cap_source, cap_sink, err[])
            check_error(err)
        end
    elseif Tv == Cshort
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_tweights_short(graph, id, cap_source, cap_sink, err[])
            check_error(err)
        end
    elseif Tv == Cfloat
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_tweights_float(graph, id, cap_source, cap_sink, err[])
            check_error(err)
        end
    elseif Tv == Cdouble
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_tweights_double(graph, id, cap_source, cap_sink, err[])
            check_error(err)
        end
    end
end

@generated function add_edge(::Type{CImpl}, graph::Ptr{Cvoid}, i::Integer, j::Integer, cap::Tv, rev_cap::Tv) where {Tv<:Real}
    if Tv == Cint
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_edge_int(graph, i, j, cap, rev_cap, err[])
            check_error(err)
        end
    elseif Tv == Cshort
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_edge_short(graph, i, j, cap, rev_cap, err[])
            check_error(err)
        end
    elseif Tv == Cfloat
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_edge_float(graph, i, j, cap, rev_cap, err[])
            check_error(err)
        end
    elseif Tv == Cdouble
        return quote
            err = Ref{bk_error}(C_NULL)
            bk_add_edge_double(graph, i, j, cap, rev_cap, err[])
            check_error(err)
        end
    end
end

@generated function maxflow(::Type{CImpl{Tv}}, graph::Ptr{Cvoid}, reuse_trees::Bool=false) where {Tv<:Real}
    if Tv == Cint
        return quote
            err = Ref{bk_error}(C_NULL)
            flow = bk_maxflow_int(graph, reuse_trees, err[])
            check_error(err)
            flow
        end
    elseif Tv == Cshort
        return quote
            err = Ref{bk_error}(C_NULL)
            flow = bk_maxflow_short(graph, reuse_trees, err[])
            check_error(err)
            flow
        end
    elseif Tv == Cfloat
        return quote
            err = Ref{bk_error}(C_NULL)
            flow = bk_maxflow_float(graph, reuse_trees, err[])
            check_error(err)
            flow
        end
    elseif Tv == Cdouble
        return quote
            err = Ref{bk_error}(C_NULL)
            flow = bk_maxflow_double(graph, reuse_trees, err[])
            check_error(err)
            flow
        end
    end
end

@generated function what_segment(::Type{CImpl{Tv}}, graph::Ptr{Cvoid}, i::Integer) where {Tv<:Real}
    if Tv == Cint
        return quote
            err = Ref{bk_error}(C_NULL)
            label = bk_what_segment_int(graph, i, err[])
            check_error(err)
            label
        end
    elseif Tv == Cshort
        return quote
            err = Ref{bk_error}(C_NULL)
            label = bk_what_segment_short(graph, i, err[])
            check_error(err)
            label
        end
    elseif Tv == Cfloat
        return quote
            err = Ref{bk_error}(C_NULL)
            label = bk_what_segment_float(graph, i, err[])
            check_error(err)
            label
        end
    elseif Tv == Cdouble
        return quote
            err = Ref{bk_error}(C_NULL)
            label = bk_what_segment_double(graph, i, err[])
            check_error(err)
            label
        end
    end
end

max_stars_repo_name: Gnimuc/BKmaxflow

max_issues_repo_name: Gnimuc/BKmaxflow

max_forks_repo_name: Gnimuc/BKmaxflow