text:
@test mysignif(SpecificG(0.1, 0.399_517_097E3), TestDigits) ≈ mysignif(SpecificG_Ps(0.1, 7.5), TestDigits)
@test mysignif(SpecificG(0.1u"MPa", 0.399_517_097E3u"K"), TestDigits) ≈ mysignif(SpecificG_Ps(0.1u"MPa", 7.5u"kJ/kg/K"), TestDigits)

@test mysignif(SpecificG(0.1, 0.514_127_081E3), TestDigits) ≈ mysignif(SpecificG_Ps(0.1, 8.0), TestDigits)
@test mysignif(SpecificG(0.1u"MPa", 0.514_127_081E3u"K"), TestDigits) ≈ mysignif(SpecificG_Ps(0.1u"MPa", 8.0u"kJ/kg/K"), TestDigits)

@test mysignif(SpecificG(2.5, 0.103_984_917E4), TestDigits) ≈ mysignif(SpecificG_Ps(2.5, 8.0), TestDigits)
@test mysignif(SpecificG(2.5u"MPa", 0.103_984_917E4u"K"), TestDigits) ≈ mysignif(SpecificG_Ps(2.5u"MPa", 8.0u"kJ/kg/K"), TestDigits)

@test mysignif(SpecificF(0.1, 0.399_517_097E3), TestDigits) ≈ mysignif(SpecificF_Ps(0.1, 7.5), TestDigits)
@test mysignif(SpecificF(0.1u"MPa", 0.399_517_097E3u"K"), TestDigits) ≈ mysignif(SpecificF_Ps(0.1u"MPa", 7.5u"kJ/kg/K"), TestDigits)

@test mysignif(SpecificF(0.1, 0.514_127_081E3), TestDigits) ≈ mysignif(SpecificF_Ps(0.1, 8.0), TestDigits)
@test mysignif(SpecificF(0.1u"MPa", 0.514_127_081E3u"K"), TestDigits) ≈ mysignif(SpecificF_Ps(0.1u"MPa", 8.0u"kJ/kg/K"), TestDigits)

@test mysignif(SpecificF(2.5, 0.103_984_917E4), TestDigits) ≈ mysignif(SpecificF_Ps(2.5, 8.0), TestDigits)
@test mysignif(SpecificF(2.5u"MPa", 0.103_984_917E4u"K"), TestDigits) ≈ mysignif(SpecificF_Ps(2.5u"MPa", 8.0u"kJ/kg/K"), TestDigits)

@test SpecificV(0.1, 0.399_517_097E3) ≈ SpecificV_Ps(0.1, 7.5)
@test SpecificV(0.1u"MPa", 0.399_517_097E3u"K") ≈ SpecificV_Ps(0.1u"MPa", 7.5u"kJ/kg/K")

@test SpecificV(0.1, 0.514_127_081E3) ≈ SpecificV_Ps(0.1, 8.0)
@test SpecificV(0.1u"MPa", 0.514_127_081E3u"K") ≈ SpecificV_Ps(0.1u"MPa", 8.0u"kJ/kg/K")

@test SpecificV(2.5, 0.103_984_917E4) ≈ SpecificV_Ps(2.5, 8.0)
@test SpecificV(2.5u"MPa", 0.103_984_917E4u"K") ≈ SpecificV_Ps(2.5u"MPa", 8.0u"kJ/kg/K")

@test SpecificU(0.1, 0.399_517_097E3) ≈ SpecificU_Ps(0.1, 7.5)
@test SpecificU(0.1u"MPa", 0.399_517_097E3u"K") ≈ SpecificU_Ps(0.1u"MPa", 7.5u"kJ/kg/K")

@test SpecificU(0.1, 0.514_127_081E3) ≈ SpecificU_Ps(0.1, 8.0)
@test SpecificU(0.1u"MPa", 0.514_127_081E3u"K") ≈ SpecificU_Ps(0.1u"MPa", 8.0u"kJ/kg/K")

@test SpecificU(2.5, 0.103_984_917E4) ≈ SpecificU_Ps(2.5, 8.0)
@test SpecificU(2.5u"MPa", 0.103_984_917E4u"K") ≈ SpecificU_Ps(2.5u"MPa", 8.0u"kJ/kg/K")

@test SpecificH(0.1, 0.399_517_097E3) ≈ SpecificH_Ps(0.1, 7.5)
@test SpecificH(0.1u"MPa", 0.399_517_097E3u"K") ≈ SpecificH_Ps(0.1u"MPa", 7.5u"kJ/kg/K")

@test SpecificH(0.1, 0.514_127_081E3) ≈ SpecificH_Ps(0.1, 8.0)
@test SpecificH(0.1u"MPa", 0.514_127_081E3u"K") ≈ SpecificH_Ps(0.1u"MPa", 8.0u"kJ/kg/K")

@test SpecificH(2.5, 0.103_984_917E4) ≈ SpecificH_Ps(2.5, 8.0)
@test SpecificH(2.5u"MPa", 0.103_984_917E4u"K") ≈ SpecificH_Ps(2.5u"MPa", 8.0u"kJ/kg/K")

@test SpecificCP(0.1, 0.399_517_097E3) ≈ SpecificCP_Ps(0.1, 7.5)
@test SpecificCP(0.1u"MPa", 0.399_517_097E3u"K") ≈ SpecificCP_Ps(0.1u"MPa", 7.5u"kJ/kg/K")

@test SpecificCP(0.1, 0.514_127_081E3) ≈ SpecificCP_Ps(0.1, 8.0)
@test SpecificCP(0.1u"MPa", 0.514_127_081E3u"K") ≈ SpecificCP_Ps(0.1u"MPa", 8.0u"kJ/kg/K")

@test SpecificCP(2.5, 0.103_984_917E4) ≈ SpecificCP_Ps(2.5, 8.0)
@test SpecificCP(2.5u"MPa", 0.103_984_917E4u"K") ≈ SpecificCP_Ps(2.5u"MPa", 8.0u"kJ/kg/K")

@test SpecificCV(0.1, 0.399_517_097E3) ≈ SpecificCV_Ps(0.1, 7.5)
@test SpecificCV(0.1u"MPa", 0.399_517_097E3u"K") ≈ SpecificCV_Ps(0.1u"MPa", 7.5u"kJ/kg/K")

@test SpecificCV(0.1, 0.514_127_081E3) ≈ SpecificCV_Ps(0.1, 8.0)
@test SpecificCV(0.1u"MPa", 0.514_127_081E3u"K") ≈ SpecificCV_Ps(0.1u"MPa", 8.0u"kJ/kg/K")

@test SpecificCV(2.5, 0.103_984_917E4) ≈ SpecificCV_Ps(2.5, 8.0)
@test SpecificCV(2.5u"MPa", 0.103_984_917E4u"K") ≈ SpecificCV_Ps(2.5u"MPa", 8.0u"kJ/kg/K")

@test SpeedOfSound(0.1, 0.399_517_097E3) ≈ SpeedOfSound_Ps(0.1, 7.5)
@test SpeedOfSound(0.1u"MPa", 0.399_517_097E3u"K") ≈ SpeedOfSound_Ps(0.1u"MPa", 7.5u"kJ/kg/K")

@test SpeedOfSound(0.1, 0.514_127_081E3) ≈ SpeedOfSound_Ps(0.1, 8.0)
@test SpeedOfSound(0.1u"MPa", 0.514_127_081E3u"K") ≈ SpeedOfSound_Ps(0.1u"MPa", 8.0u"kJ/kg/K")

@test SpeedOfSound(2.5, 0.103_984_917E4) ≈ SpeedOfSound_Ps(2.5, 8.0)
@test SpeedOfSound(2.5u"MPa", 0.103_984_917E4u"K") ≈ SpeedOfSound_Ps(2.5u"MPa", 8.0u"kJ/kg/K")


text:
module AnnotationFusion

using SHA
using Random
using Distances
using StatsBase
using DataFrames
using LinearAlgebra
using Statistics: mean, median
using TripletEmbeddings

import TripletEmbeddings: Triplets

export Triplets,
    dense, anonymize, anonymize!,
    Mean, Median, TE, Copeland,
    fuse, fuse!,
    name,
    fillmissing, fillmissing!

include("triplets.jl")
include("methods.jl")
include("utils.jl")

end

ext: jl


text:
# This file has methods to read font metrics for Base-14 fonts
#Currently only the width metric is used.
using ..Cos

using Rectangle

const ADOBE_STD_14 = Set(
["Times-Roman",      "Helvetica",             "Courier",         "Symbol",
 "Times-Bold",       "Helvetica-Bold",        "Courier-Bold",    "ZapfDingbats",
 "Times-Italic",     "Helvetica-Oblique",     "Courier-Oblique",
 "Times-BoldItalic", "Helvetica-BoldOblique", "Courier-BoldOblique"])

mutable struct AdobeFontMetrics
    cid_to_name::Dict{Int, CosName}
    name_to_wx::Dict{CosName, Float32}
    name_to_b::Dict{CosName, Vector{Int}}
    kern_pairs::Dict{Tuple{CosName, CosName}, Tuple{Float32, Float32}}
    has_kerning::Bool
    italicAngle::Float32
    isFixedPitch::Bool
    weight::Symbol
    fontname::CosName

    AdobeFontMetrics() = new(Dict{Int, CosName}(),
                             Dict{CosName, Int}(),
                             Dict{CosName, Vector{Int}}(),
                             Dict{Tuple{CosName, CosName},
                                  Tuple{Float32, Float32}}(),
                             false,
                             0,
                             false,
                             :Medium,
                             cn""
                             )
end

isBold(afm::AdobeFontMetrics)   = afm.weight === :Bold
isItalic(afm::AdobeFontMetrics) = afm.italicAngle != 0
isFixedW(afm::AdobeFontMetrics) = afm.isFixedPitch

get_font_name(afm::AdobeFontMetrics) = afm.fontname

function get_font_flags(afm::AdobeFontMetrics)
    res = 0x00000000
    isItalic(afm) && (res += 0x00000040)
    isFixedW(afm) && (res += 0x00000001)
    return res
end

function interpret_metric_line(line::AbstractString)
    tokens = split(line, ';'; keepempty=false)
    cid = -1; wx = 1000; n = "null"; bb = [0,0,0,0]
    for token in tokens
        v = split(strip(token), ' '; limit = 2)
        m = strip(v[1])
        val = strip(v[2])
        if m == "C"
            cid = parse(Int, val)
        elseif m == "CH"
            val = rstrip(replace(val, "<", "0x"), '>')
            cid = parse(Int, val)
        elseif m == "WX"
            wx = parse(Int, val)
        elseif m == "N"
            n = val
        elseif m == "B"
            rr = split(val)
            bb = parse.(Int, [rr[1], rr[2], rr[3], rr[4]])
        end
    end
    return (cid, wx, CosName(n), bb)
end

function populate_char_metrics(lines, state, afm, nLines)
    nLineRead = 0
    (line, state) = iterate(lines, state)
    while nLineRead < nLines
        cid, wx, n, b = interpret_metric_line(line)
        if cid > -1
            afm.cid_to_name[cid] = n
        end
        afm.name_to_wx[n] = Float32(wx)
        afm.name_to_b[n] = b
        nLineRead += 1
        (line, state) = iterate(lines, state)
    end
end

function interpret_kerpair_line(line::AbstractString)
    tokens = split(line)
    key = tokens[1]
    a = CosName(tokens[2])
    b = CosName(tokens[3])
    x = key in ("KP", "KPH", "KPX") ? parse(Float32, tokens[4]) : 0f0
    y = key in ("KP", "KPH", "KPY") ? parse(Float32, tokens[5]) : 0f0
    return a, b, x, y
end

function populate_kern_pairs(lines, state, afm, nLines)
    nLineRead = 0
    (line, state) = iterate(lines, state)
    while nLineRead < nLines
        n1, n2, x, y = interpret_kerpair_line(line)
        afm.kern_pairs[(n1, n2)] = (x, y)
        nLineRead += 1
        (line, state) = iterate(lines, state)
    end
    afm.has_kerning = true
end

function read_afm(fontname::AbstractString)
    d_name_w = Dict{CosName, Int}()
    d_cid_w = Dict{Int, Int}()
    filename = fontname * ".afm"
    path = joinpath(@__DIR__, "..", "data", "fonts", filename)
    lines = readlines(path)
    bStartCharMetrics = false
    bReadKernPairs = false
    nMetrics = 0
    nLineRead = 0
    afm = AdobeFontMetrics()
    next = iterate(lines)
    while next !== nothing
        (line, state) = next
        if startswith(line, "ItalicAngle")
            v = split(line)
            afm.italicAngle = parse(Float32, v[2])
        elseif startswith(line, "IsFixedPitch")
            v = split(line)
            afm.isFixedPitch = parse(Bool, v[2])
        elseif startswith(line, "FontName")
            v = split(line)
            afm.fontname = CosName(v[2])
        elseif startswith(line, "Weight")
            v = split(line)
            afm.weight = Symbol(v[2])
        else
            bStartCharMetrics = startswith(line, "StartCharMetrics")
            bReadKernPairs = startswith(line, "StartKernPairs")
            if bStartCharMetrics || bReadKernPairs
                v = split(line)
                n = parse(Int, v[2])
                if bStartCharMetrics
                    populate_char_metrics(lines, state, afm, n)
                    bStartCharMetrics = false
                end
                if bReadKernPairs
                    populate_kern_pairs(lines, state, afm, n)
                    bReadKernPairs = false
                end
            end
        end
        next = iterate(lines, state)
    end
    return afm
end

get_font_widths(cosdoc::CosDoc, font::CosNullType) = zeros(Float32, 256)

function get_font_widths(cosdoc::CosDoc, font::IDD{CosDict})
    d = zeros(Float32, 256)
    @assert cosDocGetObject(cosdoc, font, cn"Type") === cn"Font"
    subtype = cosDocGetObject(cosdoc, font, cn"Subtype")
    (subtype === cn"Type0") && return get_cid_font_widths(cosdoc, font)
    basefont = cosDocGetObject(cosdoc, font, cn"BaseFont")
    widths_obj = cosDocGetObject(cosdoc, font, cn"Widths")
    widths_obj === CosNull && return get_font_widths(basefont)
    firstchar = get(font, cn"FirstChar") |> get
    lastchar  = get(font, cn"LastChar")  |> get
    @assert lastchar < 256
    widths = get(widths_obj, true)
    for i = firstchar:lastchar
        ix = i - firstchar + 1
        d[i+1] = round(Int, widths[ix])
    end
    return d
end

get_font_widths(basefonts::CosName) = read_afm(convert(CDTextString, basefonts))

function get_cid_font_widths(cosDoc::CosDoc, font::IDDRef{CosDict})
    m = IntervalTree{UInt16, Float32}()
    encoding = cosDocGetObject(cosDoc, font, cn"Encoding")
    desc = cosDocGetObject(cosDoc, font, cn"DescendantFonts") |> get
    w = cosDocGetObject(cosDoc, desc[1], cn"W")
    dw = cosDocGetObject(cosDoc, desc[1], cn"DW")
    # If widths are not specified or the font encoding is not Identity-H
    # widths cannot be extracted.
    if w === CosNull || encoding != cn"Identity-H"
        return (dw === CosNull) ? CIDWidth() : CIDWidth(Float32(get(dw)))
    end
    w = get(w)
    next = iterate(w)
    while next !== nothing
        (i, state) = next
        bcid = get(i)
        next = iterate(w, state)
        (i, state) = next
        ecid = get(i)
        ccid = bcid
        if ecid isa Vector
            for wdo in ecid
                width = get(wdo)
                m[Interval(UInt16(ccid), UInt16(ccid))] = Float32(width)
                ccid += 1
            end
        else
            (width, state) = iterate(w, state)
            m[Interval(UInt16(bcid), UInt16(ecid))] = Float32(get(width))
        end
        next = iterate(w, state)
    end
    return (dw === CosNull) ? CIDWidth(m) : CIDWidth(m, Float32(get(dw)))
end

get_character_width(n::CosName, afm::AdobeFontMetrics) =
    get(afm.name_to_wx, n, 1000f0)
get_character_width(cid::UInt8, afm::AdobeFontMetrics) =
    get_character_width(get(afm.cid_to_name, cid, nothing), afm)
get_character_width(::Nothing, afm::AdobeFontMetrics) = 1000f0

get_kern_width(c1::Int, c2::Int, afm::AdobeFontMetrics) =
    get_kern_width(get(afm.cid_to_name, c1, nothing),
                   get(afm.cid_to_name, c2, nothing),
                   afm)
get_kern_width(n1::CosName, n2::CosName, afm::AdobeFontMetrics) =
    get(afm.kern_pairs, (n1, n2), (0f0, 0f0))[1]
get_kern_width(c1, ::Nothing, other) = 0f0
get_kern_width(::Nothing, c2, other) = 0f0
get_kern_width(::Nothing, ::Nothing, ::Any) = 0f0
get_kern_width(c1, c2, other) = 0f0

get_character_width(cid::UInt8, widths::Vector) =
    (widths[Int(cid+1)] == 0) ? 1000f0 : widths[Int(cid+1)]


text:
# Autogenerated wrapper script for Fontconfig_jll for x86_64-linux-gnu
export fc_match, fc_cat, fc_conflist, fonts_conf, libfontconfig, fc_validate, fc_list, fc_pattern, fc_cache, fc_scan, fc_query

using FreeType2_jll
using Bzip2_jll
using Zlib_jll
using Libuuid_jll
using Expat_jll
## Global variables
PATH = ""
LIBPATH = ""
LIBPATH_env = "LD_LIBRARY_PATH"

# Relative path to `fc_match`
const fc_match_splitpath = ["bin", "fc-match"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_match_path = ""

# fc_match-specific global declaration
function fc_match(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_match_path)
    end
end

# Relative path to `fc_cat`
const fc_cat_splitpath = ["bin", "fc-cat"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_cat_path = ""

# fc_cat-specific global declaration
function fc_cat(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_cat_path)
    end
end

# Relative path to `fc_conflist`
const fc_conflist_splitpath = ["bin", "fc-conflist"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_conflist_path = ""

# fc_conflist-specific global declaration
function fc_conflist(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_conflist_path)
    end
end

# Relative path to `fonts_conf`
const fonts_conf_splitpath = ["etc", "fonts", "fonts.conf"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fonts_conf_path = ""

# fonts_conf-specific global declaration
# This will be filled out by __init__()
fonts_conf = ""

# Relative path to `libfontconfig`
const libfontconfig_splitpath = ["lib", "libfontconfig.so"]

# This will be filled out by __init__() for all products, as it must be done at runtime
libfontconfig_path = ""

# libfontconfig-specific global declaration
# This will be filled out by __init__()
libfontconfig_handle = C_NULL

# This must be `const` so that we can use it with `ccall()`
const libfontconfig = "libfontconfig.so.1"

# Relative path to `fc_validate`
const fc_validate_splitpath = ["bin", "fc-validate"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_validate_path = ""

# fc_validate-specific global declaration
function fc_validate(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_validate_path)
    end
end

# Relative path to `fc_list`
const fc_list_splitpath = ["bin", "fc-list"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_list_path = ""

# fc_list-specific global declaration
function fc_list(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_list_path)
    end
end

# Relative path to `fc_pattern`
const fc_pattern_splitpath = ["bin", "fc-pattern"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_pattern_path = ""

# fc_pattern-specific global declaration
function fc_pattern(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_pattern_path)
    end
end

# Relative path to `fc_cache`
const fc_cache_splitpath = ["bin", "fc-cache"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_cache_path = ""

# fc_cache-specific global declaration
function fc_cache(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_cache_path)
    end
end

# Relative path to `fc_scan`
const fc_scan_splitpath = ["bin", "fc-scan"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_scan_path = ""

# fc_scan-specific global declaration
function fc_scan(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_scan_path)
    end
end

# Relative path to `fc_query`
const fc_query_splitpath = ["bin", "fc-query"]

# This will be filled out by __init__() for all products, as it must be done at runtime
fc_query_path = ""

# fc_query-specific global declaration
function fc_query(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    global PATH, LIBPATH
    env_mapping = Dict{String,String}()
    if adjust_PATH
        if !isempty(get(ENV, "PATH", ""))
            env_mapping["PATH"] = string(PATH, ':', ENV["PATH"])
        else
            env_mapping["PATH"] = PATH
        end
    end
    if adjust_LIBPATH
        if !isempty(get(ENV, LIBPATH_env, ""))
            env_mapping[LIBPATH_env] = string(LIBPATH, ':', ENV[LIBPATH_env])
        else
            env_mapping[LIBPATH_env] = LIBPATH
        end
    end
    withenv(env_mapping...) do
        f(fc_query_path)
    end
end

"""
Open all libraries
"""
function __init__()
    global artifact_dir = abspath(artifact"Fontconfig")

    # Initialize PATH and LIBPATH environment variable listings
    global PATH_list, LIBPATH_list
    # We first need to add to LIBPATH_list the libraries provided by Julia
    append!(LIBPATH_list, [joinpath(Sys.BINDIR, Base.LIBDIR, "julia"), joinpath(Sys.BINDIR, Base.LIBDIR)])
    # From the list of our dependencies, generate a tuple of all the PATH and LIBPATH lists,
    # then append them to our own.
    foreach(p -> append!(PATH_list, p), (FreeType2_jll.PATH_list, Bzip2_jll.PATH_list, Zlib_jll.PATH_list, Libuuid_jll.PATH_list, Expat_jll.PATH_list,))
    foreach(p -> append!(LIBPATH_list, p), (FreeType2_jll.LIBPATH_list, Bzip2_jll.LIBPATH_list, Zlib_jll.LIBPATH_list, Libuuid_jll.LIBPATH_list, Expat_jll.LIBPATH_list,))

    global fc_match_path = normpath(joinpath(artifact_dir, fc_match_splitpath...))

    push!(PATH_list, dirname(fc_match_path))
    global fc_cat_path = normpath(joinpath(artifact_dir, fc_cat_splitpath...))

    push!(PATH_list, dirname(fc_cat_path))
    global fc_conflist_path = normpath(joinpath(artifact_dir, fc_conflist_splitpath...))

    push!(PATH_list, dirname(fc_conflist_path))
    global fonts_conf_path = normpath(joinpath(artifact_dir, fonts_conf_splitpath...))

    global fonts_conf = fonts_conf_path
    global libfontconfig_path = normpath(joinpath(artifact_dir, libfontconfig_splitpath...))

    # Manually `dlopen()` this right now so that future invocations
    # of `ccall` with its `SONAME` will find this path immediately.
    global libfontconfig_handle = dlopen(libfontconfig_path)
    push!(LIBPATH_list, dirname(libfontconfig_path))

    global fc_validate_path = normpath(joinpath(artifact_dir, fc_validate_splitpath...))

    push!(PATH_list, dirname(fc_validate_path))
    global fc_list_path = normpath(joinpath(artifact_dir, fc_list_splitpath...))

    push!(PATH_list, dirname(fc_list_path))
    global fc_pattern_path = normpath(joinpath(artifact_dir, fc_pattern_splitpath...))

    push!(PATH_list, dirname(fc_pattern_path))
    global fc_cache_path = normpath(joinpath(artifact_dir, fc_cache_splitpath...))

    push!(PATH_list, dirname(fc_cache_path))
    global fc_scan_path = normpath(joinpath(artifact_dir, fc_scan_splitpath...))

    push!(PATH_list, dirname(fc_scan_path))
    global fc_query_path = normpath(joinpath(artifact_dir, fc_query_splitpath...))

    push!(PATH_list, dirname(fc_query_path))
    # Filter out duplicate and empty entries in our PATH and LIBPATH entries
    filter!(!isempty, unique!(PATH_list))
    filter!(!isempty, unique!(LIBPATH_list))
    global PATH = join(PATH_list, ':')
    global LIBPATH = join(LIBPATH_list, ':')

    # Add each element of LIBPATH to our DL_LOAD_PATH (necessary on platforms
    # that don't honor our "already opened" trick)
    #for lp in LIBPATH_list
    #    push!(DL_LOAD_PATH, lp)
    #end
end  # __init__()

max_stars_repo_name: giordano/Fontconfig

max_issues_repo_name: giordano/Fontconfig

max_forks_repo_name: giordano/Fontconfig


text:
"(x1(ω), x2(ω), ... xn(ω))"
applymany(ω::Ω, xs) = map(xi->xi(ω), xs)

"RandVar{Vector} from Vector{<:RandVar}"
randarray(x::Array{<:RandVar, N}) where N = URandVar(applymany, (x,))
# zt: FIXME AbstractArray?

randtuple(x::UTuple{RandVar}) = URandVar(applymany, (x,))

# Lift GetIndex
Base.getindex(x::RandVar, i) = lift(getindex)(x, i)
Base.getindex(x::RandVar, i, is...) = lift(getindex)(x, i, is...)

Base.:*(tpl::Tuple, ::Type{ᵣ}) = randtuple(tpl)
Base.:*(tpl::AbstractArray, ::Type{ᵣ}) = randarray(tpl)


text:
module MeasureTheory

using MLStyle

import Distributions
const Dists = Distributions

const EmptyNamedTuple = NamedTuple{(),Tuple{}}

export ≪

abstract type AbstractMeasure{X} end

"""
    logdensity(μ::Measure{X}, x::X)

Compute the logdensity of the measure μ at the point x. This is the standard way
to define `logdensity` for a new measure. the base measure is implicit here, and
is understood to be `baseMeasure(μ)`.

Methods for computing density relative to other measures will be
"""
function logdensity end

Base.eltype(μ::AbstractMeasure{X}) where {X} = X

logdensity(μ::Dists.Distribution, x) = Dists.logpdf(μ,x)

density(μ::Dists.Distribution, x) = Dists.pdf(μ,x)

include("absolutecontinuity.jl")
include("basemeasures/lebesgue.jl")
include("macros.jl")
include("combinators/scale.jl")
include("combinators/superpose.jl")
include("combinators/product.jl")
include("distributions.jl")
# include("probability/normal.jl")
include("density.jl")

end # module


text:
"""
## beam_mm

This subroutine forms the stiffness matrix of a beam element (bending only).

### Method
```julia
beam_mm(ei, ell)
```

### Arguments
```julia
* fs::Float64               : Element density
* ell::Float64              : Element length
```

### Return value
```julia
* mm::::Matrix{Float64}     : Mass matrix for beam elembeam_mmated)
```
"""
function beam_mm(fs::Float64, ell::Float64)
  #
  # This subroutine forms the consistent mass matrix of a beam fin_el.
  #
  fac = (fs*ell)/420.0
  mm = zeros(4,4)
  mm[1,1] = 156.0*fac
  mm[3,3] = mm[1,1]
  mm[1,2] = 22.0*ell*fac
  mm[2,1] = mm[1,2]
  mm[3,4] = -mm[1,2]
  mm[4,3] = mm[3,4]
  mm[1,3] = 54.0*fac
  mm[3,1] = mm[1,3]
  mm[1,4] = -13.0*ell*fac
  mm[4,1] = mm[1,4]
  mm[2,3] = -mm[1,4]
  mm[3,2] = mm[2,3]
  mm[2,2] = 4.0*(ell*ell)*fac
  mm[4,4] = mm[2,2]
  mm[2,4] = -3.0*(ell*ell)*fac
  mm[4,2] = mm[2,4]
  mm
end


text:
@testset "1D Test Propagations with single slit example" begin

    function test_prop_1D(M, d, z, λ, L_slit)
	    slit = zeros(Float64, (1, M))
	    xs = LinRange(-L_slit / 2, L_slit / 2, M)
	    slit[1, (abs.(xs) .< d / 2)] .= 1

        slit_prop = abs2.(propagate(slit, L_slit, z, kernel=fresnel_kernel, λ=λ))
        slit_proprs = abs2.(propagate(slit, L_slit, z, kernel=rs_kernel, λ=λ))
	    # normalize for a better plot
	    slit_prop ./= maximum(slit_prop)
	    slit_proprs ./= maximum(slit_proprs)

	    analytical(x) = begin
	    	x_0 = π .* d .* x ./ λ ./ z
	    	return (sin.(x_0) ./ x_0).^2
	    end

        @test   ≈(analytical.(xs)[200:800], slit_prop[200:800], rtol=0.01)
        @test   ≈(analytical.(xs)[200:800], slit_proprs[200:800], rtol=0.01)

        return slit_prop
    end

    x_1 = test_prop_1D(1000, 100e-6, 0.2, 550e-9, 10e-3)
    x_2 = test_prop_1D(1000, 100e-6, 0.2, 450e-9, 10e-3)
    test_prop_1D(1000, 120e-6, 0.2, 450e-9, 10e-3)

    @test ~ ≈(x_1, x_2, rtol=0.01)
end

@testset "Confirm that lens_propagate, four_f_propagate, Debye integral match analytical solution and are consistent to each other" begin
    function lens_test(L, N, f, radius, shift)

        NA = radius/f

	    E0 = zeros((N, N))
        # place point source at center
	    E0[center_pos(N), center_pos(N)] = 1
	    E1, L1 = lens_propagate(E0, L, f)
	    E1_ = circ(E1, L1, radius)
	    E2, L2 = lens_propagate(E1_, L1, f)
	    psf_ = abs2.(E2)
	    psf = psf_ ./ sum(psf_)
	    psf1 = psf ./ maximum(psf)

        psf_analytical = jinc_psf((N, N), L, radius, f; shift=shift)
	    psf2 = psf_analytical ./ maximum(psf_analytical)

        E_deb = debye_focus(L, N, NA, 0.0)
        psf_deb = abs2.(E_deb)
        psf_deb ./= sum(psf_deb)
        psf_deb ./= maximum(psf_deb)

        psf_4f, L2_4f = four_f_propagate(E0, L, f, f, NA)
	    psf_4f = normabs2(psf_4f)
        if ~ shift
            psf_deb = ifftshift(psf_deb)
            psf1 = ifftshift(psf1)
            psf_4f = ifftshift(psf_4f)
            # exlude borders of the fields because they can differ
            slice = 1 : round(Int, 0.5 * N)
        else
            slice = round(Int, 0.25 * N) : round(Int, 0.75 * N)
        end

        @test L2 == L2_4f
	    @test ≈(psf1[slice, slice], psf2[slice, slice], rtol=0.005)
	    @test ≈(psf_4f[slice, slice], psf2[slice, slice], rtol=0.005)
        @test ≈(psf_deb[slice, slice], psf_4f[slice, slice], rtol=0.01)

    end

    lens_test(10e-3, 2048, 100e-3, 1e-3, true)
    lens_test(1e-3, 2049, 100e-3, 10e-3, true)
    lens_test(100e-6, 513, 1e-3, 0.2e-3, false)
end

@testset "Point source propagation tests" begin
    N = 100
    L = 100e-6
    ps = point_source_propagate(L, (N, N), Point(0.0, 0.0, 0.0))
    ref = zeros(ComplexF32, (N, N))
    ref[center_pos(N), center_pos(N)] = 1

    @test ps == ref

    ps = point_source_propagate(L, (N, N), Point(10e-6, 0.0, 10.0e-6))
    ref = zeros(ComplexF32, (N, N))

    k = 2π/550f-9
    for (j, x) in enumerate(fftpos(L, N))
        for (i, y) in enumerate(fftpos(L, N))
            r = sqrt((x-10e-6)^2 + (y)^2 + (10.0e-6)^2)
            ref[i, j] = 1/r .* exp(-1im * k * r);
        end
    end
    ref ./= ref[argmax(abs2.(ref))]
    @test ≈(ComplexF32.(ps), ComplexF32.(ref), rtol=1e-4)

    ps = point_source_propagate(L, (N, N), Point(-50.0e-6, -50.0e-6, 0.0))
    @test ps[1, 1] == 1

end

@testset "Compare Debye with 4F for different NAs" begin

    function compare(N, L, NA)
	    out_s = (N, N)
	    #f = 50-3
	    out = debye_focus(L, N, NA, 0e-6)
	    h1 = abs2.(out)
	    h1 ./= sum(h1)

        E0 = zeros(ComplexF32, (N, N))
	    E0[center_pos(N), center_pos(N)] = 1
	    E1, L2 = four_f_propagate(E0, L, 100e-3, 100e-3, NA)
	    h2 = abs2.(E1)
	    h2 ./= sum(h2)

        slice = round(Int, 0.3*N):round(Int, 0.7 * N)
        @test ≈(h1[slice, slice], h2[slice, slice], rtol=0.05)
    end

    compare(256, 20e-6, 0.2)
    compare(256, 50e-6, 0.1)
    compare(256, 10e-6, 0.7)
    compare(512, 10e-6, 0.4)
end

@testset "Compare Point source propagate with different lens_prop" begin
    L = 50e-6

    f = 20e-3
    z = 50e-6
    N = 256
    E1 = point_source_propagate(L, (N, N), Point(0.0e-3, 0.0, z), dtype=ComplexF32)
    E1, L1 = lens_propagate(E1, L, f, d=f)
    quadratic!(E1, L1, L1/9)
    E1, L1 = lens_propagate(E1, L1, f)
    I1 = abs2.(E1)
    I1 ./= sum(I1)

    E2 = point_source_propagate(L, (N, N), Point(0.0e-3, 0.0, 0.0), dtype=ComplexF32)
    E2, L2 = lens_propagate(E2, L, f, d=f-z)
    quadratic!(E2, L2, L2/9)
    E2, L2 = lens_propagate(E2, L2, f)
    I2 = abs2.(E2)
    I2 ./= sum(I2)
    @test .≈(I1 .+ 1, I2 .+ 1, rtol=1e-5)  |> all
end

max_stars_repo_name: JuliaPhysics/PhysicalOptics

max_issues_repo_name: JuliaPhysics/PhysicalOptics

max_forks_repo_name: JuliaPhysics/PhysicalOptics


text:
# Tracing multiple charged particles in a static EM field.
# This example takes advantage of the multithreading support in the ODE solver.
# A multiproc version is also available. Check the official documentation of
# DifferentialEquations.jl for details.
#
# Hongyang Zhou, hyzhou@umich.edu

using TestParticle
using Meshes
using OrdinaryDiffEq
using Plots

"Initial state perturbation for EnsembleProblem."
function prob_func(prob, i, repeat)
   remake(prob, u0=rand()*prob.u0)
end

## Initialize grid and field

x = range(-10, 10, length=15)
y = range(-10, 10, length=20)
z = range(-10, 10, length=25)
B = fill(0.0, 3, length(x), length(y), length(z)) # [T]
E = fill(0.0, 3, length(x), length(y), length(z)) # [V/m]

B[3,:,:,:] .= 1e-11
E[3,:,:,:] .= 5e-13

Δx = x[2] - x[1]
Δy = y[2] - y[1]
Δz = z[2] - z[1]

mesh = CartesianGrid((length(x)-1, length(y)-1, length(z)-1),
   (x[1], y[1], z[1]),
   (Δx, Δy, Δz))

## Initialize particles

x0 = [0.0, 0.0, 0.0] # initial position, [m]
u0 = [1.0, 0.0, 0.0] # initial velocity, [m/s]
stateinit = [x0..., u0...]

param = prepare(mesh, E, B, species=Electron)
tspan = (0.0, 15.0)

trajectories = 10

## Solve for the trajectories

prob = ODEProblem(trace_numeric!, stateinit, tspan, param)
ensemble_prob = EnsembleProblem(prob, prob_func=prob_func)
sol = solve(ensemble_prob, Tsit5(), EnsembleThreads();
   trajectories=trajectories, save_idxs=[1,2,3])

## Visualization

xyz = plot(sol, vars=(1,2,3), xlabel="x", ylabel="y", zlabel="z",
   aspect_ratio=:equal, label="electron", lw=2)


text:
# BAM File Format
# ===============

module BAM

using BioGenerics
using GenomicFeatures
using XAM.SAM
import ..XAM: flag

import BGZFStreams
import BioAlignments
import Indexes
import BioSequences
import BioGenerics: isfilled, header

import GenomicFeatures: eachoverlap

include("bai.jl")
include("auxdata.jl")
include("reader.jl")
include("record.jl")
include("writer.jl")
include("overlap.jl")

end


text:
################################################################################

"""
    euclDist(arr::Array{T, 1}, h::Array{T, 1}) where {T <: Number}

# Description
Euclidean distance.

# Examples
```
julia> euclDist(collect(1:10), fill(5, 10))
9.219544457292887
```

See also: [`bhattDist`](@ref), [`amplitude`](@ref)
"""
function euclDist(arr::Array{T,1}, h::Array{T,1}) where {T <: Number}
  return (arr .- h) .^ 2 |> sum |> sqrt
end

"""
    bhattDist(arr::Array{T, 1}, h::Array{T, 1}) where {T <: Number}

# Description
Bhattacharyya distance.

# Examples
```
julia> bhattDist(collect(1:10), fill(5, 10))
-3.936532135073928
```

See also: [`euclDist`](@ref), [`amplitude`](@ref)
"""
function bhattDist(arr::Array{T,1}, h::Array{T,1}) where {T <: Number}
  return -log((arr .* h .|> sqrt |> sum) + 1)
end

"""
    amplitude(arr::Array{T, 1}) where {T <: Number}

# Description
Amplitude.

# Examples
```
julia> amplitude(collect(1:10))
19.621416870348583
```

See also: [`euclDist`](@ref), [`bhattDist`](@ref)
"""
function amplitude(arr::Array{T,1}) where {T <: Number}
  return arr .^ 2 |> sum |> sqrt
end

################################################################################


text:
module Knet

# To see debug output, start julia with `JULIA_DEBUG=Knet julia`
# To perform profiling, set ENV["KNET_TIMER"] to "true" and rebuild Knet. (moved this to gpu.jl)
# The @dbg macro below evaluates `ex` only when debugging. The @debug macro prints stuff as documented in Julia.
macro dbg(ex); :(if Base.CoreLogging.current_logger_for_env(Base.CoreLogging.Debug,:none,Knet)!==nothing; $(esc(ex)); end); end

export		# ref:reference.md tut:tutorial
    accuracy,	# ref, tut
    adadelta!,	# ref
    Adadelta,	# ref
    adadelta,	# ref
    adagrad!,	# ref
    Adagrad,	# ref
    adagrad,	# ref
    adam!,	# ref
    Adam,	# ref
    adam,	# ref, tut
    AutoGrad,	# ref, tut
    batchnorm,	# ref
    bce,	# ref
    bilinear,	# ref
    bmm,	# ref
    bnmoments,	# ref
    bnparams,	# ref
    cat1d,	# ref
    conv4,	# ref, tut
    converge!,	# ref
    converge,	# ref, tut
    cpucopy,	# ref
    #Data,	# tut, use Knet.Data
    deconv4,	# ref
    @diff,	# ref, tut
    #dir,	# ref, tut, use Knet.dir
    dropout,	# ref, tut
    elu,	# ref
    #epochs,	# deprecated, use repeat(data,n)
    gaussian,	# ref
    #gc,  	# ref, tut, use Knet.gc
    #@gheck,	# ref, use AutoGrad.@gcheck
    goldensection, # ref
    gpu,	# ref, tut
    gpucopy,	# ref
    grad,	# ref, tut
    gradloss,	# ref
    hyperband,	# ref
    invx,	# ref
    KnetArray,	# ref, tut
    knetgc,     # deprecated, use Knet.gc
    #load,	# ref, tut
    #@load,	# ref
    logistic,	# ref
    logp,	# ref
    logsoftmax,	# ref
    logsumexp,	# ref
    mat,	# ref, tut
    minibatch,	# ref, tut
    #minimize!,	# use sgd!, adam! etc.
    #minimize,	# use sgd, adam etc.
    momentum!,	# ref
    Momentum,	# ref
    momentum,	# ref
    nesterov!,	# ref
    Nesterov,	# ref
    nesterov,	# ref
    nll,	# ref, tut
    optimizers,	# deprecated, use sgd etc.
    Param,	# ref, tut
    param,	# ref, tut
    param0,	# ref, tut
    params,	# ref, tut
    pool,	# ref, tut
    #@primitive, # ref, use AutoGrad.@primitive
    progress!,	# ref, tut
    progress,	# ref, tut
    relu,	# ref, tut
    rmsprop!,	# ref
    Rmsprop,	# ref
    rmsprop,	# ref
    RNN,	# ref, tut
    rnninit,    # deprecated, use RNN
    rnnparam,	# ref, rnnparam(r,w,l,i,d) deprecated, use rnnparam(r,l,i,d)
    rnnparams,	# ref, rnnparams(r,w) deprecated, use rnnparams(r)
    #save,	# ref, tut, use Knet.save
    #@save,	# ref, use Knet.@save
    #seed!,	# ref, use Knet.seed!
    selu,	# ref
    setseed,	# deprecated, use Knet.seed!
    sgd!,	# ref
    SGD,	# ref
    Sgd,	# deprecated, use SGD
    sgd,	# ref, tut
    sigm,	# ref
    softmax,	# ref
    train!,	# deprecated, use sgd, adam etc.
    #train,	# deprecated, use sgd, adam etc.
    training,	# ref, tut
    unpool,	# ref
    update!,	# ref
    #updates,	# deprecated, use take(cycle(data),n)
    value,	# ref, tut
    xavier,	# ref, tut
    xavier_uniform,	# ref
    xavier_normal,	# ref
    #@zerograd, # ref, use AutoGrad.@zerograd
    zeroone	# ref, tut

using AutoGrad

# using Pkg; const AUTOGRAD_VERSION = (isdefined(Pkg.API,:__installed) ? Pkg.API.__installed()["AutoGrad"] : Pkg.dependencies()[Base.UUID("6710c13c-97f1-543f-91c5-74e8f7d95b35")].version)

include("gpu.jl");              # gpu
# include("uva.jl")
include("kptr.jl");
include("karray.jl");           # KnetArray
include("cuarrays/knetarray.jl");
include("cuarrays/autograd.jl");
include("cuarrays/getindex.jl");
include("gcnode.jl");
include("ops.jl");
include("unary.jl");            # relu, sigm, invx, elu, selu
include("binary.jl");           # elementwise broadcasting operations
include("reduction.jl");        # sum, max, etc.
include("cuarrays/reduction.jl");
include("statistics.jl");       # mean, std, var, stdm, varm
include("linalg.jl");           # mat # matmul, axpy!, transpose, (i)permutedims
include("bmm.jl");              # bmm # matmul, axpy!, transpose, (i)permutedims
include("conv.jl");             # conv4, pool, deconv4, unpool
include("batchnorm.jl");        # batchnorm, bnmoments, bnparams
include("rnn.jl");              # RNN, rnnparam, rnnparams
include("data.jl");             # Data, minibatch
include("progress.jl");         # progress, progress!
include("train.jl");		# train, train!, minimize, minimize!, converge, converge!, param, param0
include("loss.jl");             # logp, logsoftmax, logsumexp, softmax, nll, logistic, bce, accuracy, zeroone # TODO: PR
include("dropout.jl");          # dropout
include("cuarrays/dropout.jl");
include("update.jl"); 		# SGD, Sgd, sgd, sgd!, Momentum, momentum, momentum!, Nesterov, nesterov, nesterov!, Adam, adam, adam!, Adagrad, adagrad, adagrad!, Adadelta, adadelta, adadelta!, Rmsprop, rmsprop, rmsprop!, update!, optimizers
include("distributions.jl"); 	# gaussian, xavier, bilinear, xavier_uniform, xavier_normal
# include("random.jl");           # setseed  # TODO: deprecate setseed
include("hyperopt.jl");         # hyperband, goldensection
include("serialize.jl");        # gpucopy,cpucopy
include("jld.jl");              # load, save, @load, @save; not exported use with Knet. prefix.

"""
    Knet.dir(path...)

Construct a path relative to Knet root.

# Example
```julia
julia> Knet.dir("examples","mnist.jl")
"/home/dyuret/.julia/dev/Knet/examples/mnist.jl"
```
"""
dir(path...) = joinpath(dirname(@__DIR__),path...)

# See if we have a gpu at initialization:
function __init__()
    if !CUDA.functional()
        @warn "Knet cannot use the GPU: CUDA.jl is not functional"
    else; try
        dev = gpu(true)
        if dev >= 0
            AutoGrad.set_gc_function(Knet.knetgcnode)
            @debug "Knet using GPU $dev"
        else
            @debug "No GPU found, Knet using the CPU"
        end
    catch e
        gpu(false)
        @warn "Knet cannot use the GPU: $e"
    end; end
end

# @use X,Y,Z calls using on packages installing them if necessary. (WIP)
# 1. still need "using Knet"
# 2. Pkg.insalled gives false for stdlib packages.
# macro use(ps)
#     if isa(ps, Symbol); ps = Expr(:tuple,ps); end
#     a = map(ps.args) do p
#         s=string(p)
#         esc(:(haskey(Pkg.installed(),$s)||Pkg.add($s); using $p))
#     end
#     Expr(:block,:(using Pkg),a...)
# end
# export @use

#using  AutoGrad: @diff, Param, params, grad, gradloss, value, cat1d, @primitive, @zerograd, @primitive1, @zerograd1, forw, back, Value, AutoGrad
#export AutoGrad, @diff, Param, params, grad, gradloss, value, cat1d #@primitive, @zerograd, @primitive1, @zerograd1, forw, back, Value, getval

end # module


text:
using Rheologies;
const R = Rheologies;

include(joinpath(@__DIR__, "seeded_crust_gmsh.jl"))

output_path = @__DIR__
## SPATIAL DOMAIN ##
dim = 2 # spatial dimensions

Lx = 1.0
Ly = 0.1
H_bdt = 1e3
n_seeds = 0
radius_bounds = (300, 400)
#el_geom = Triangle # Quadrilateral or Triangle, equivalent to Cell{dim,nnodes,nfaces}

nx = 100
ny = 10

corner1 = Vec(0.0, 0.0)
corner2 = Vec(Lx, Ly)
el_geom = Quadrilateral # Quadrilateral or Triangle, equivalent to Cell{dim,nnodes,nfaces}

# generate the grid and sets:
grid = JuAFEM.generate_grid(el_geom, (nx, ny), corner1, corner2)
# Add facesets / nodesets / cellsets on which bc will be applied (except for the top, bottom, left and right boundary that are implemented by default)

## VARIABLES AND INTERPOLATIONS
variables = PrimitiveVariables{1}((:u,), (2,), el_geom)
#variables = PrimitiveVariables{2}((:u,:p), (2,1), el_geom) # not good !!!!

quad_order = 2
quad_type = :legendre # or :lobatto

## BOUNDARY CONDITIONS ##
# DIRICHLET :
# KEY : set on which to apply bc
# VALUES :
# 1) constrained variable
# 2) constraint function of (x,t)
# 3) constrained components
# NEUMANN :
# KEY : set on which to apply bc
# VALUES : traction as a function of (x,t)
gaussian_shape(x,A,xm,std) = A*exp(-0.5*(x[1]-xm)^2/std^2)
load_rate = -1e6
gaussian_trac(x) = gaussian_shape(x,load_rate,Lx,0.05)
bc = BoundaryConditions(
    dirichlet = Dict("left" => [:u, (x,t)-> Vec(0.0,0.0), [1,2]]),
    neumann = Dict("right" => (x,t)-> Vec(0.0,gaussian_trac(x)*t))
    )
#Dict("top" => (x,t)->Vec(0.0,-1e5),
#"bottom" => (x,t)->Vec(0.0,1e5)) )

bf = BodyForces([0.0, 0.0])#-9.81*2700])

## MATERIAL RHEOLOGY :

# define a rheology distribution function ...
# function multi_seeds(x,x0,radius,val_in,val_out)
#     for i in eachindex(radius)
#         (sqrt((x[1]-x0[i][1])^2 + (x[2]-x0[i][2])^2) <= radius[i]) && return val_in
#     end
#     return val_out
# end
# multi_seeds(x,val_in,val_out) = multi_seeds(x,x0,radius,val_in,val_out)
# and use it ...
seed(x,x0,r,val_in::T,val_out::T) where {T<:Real} = (sqrt((x[1]-x0[1])^2 + (x[2]-x0[2])^2) <= r ?
                                   val_in : val_out)

elas = Elasticity(E = 70e9, ν = 0.3)

visco = Viscosity(η = x -> (x[2] >= Ly - H_bdt) ? 1e24 : 1e17)

Δσ = 1e3
plas = DruckerPrager(
    ϕ = 30.0,
    C = 1e6,#x -> seed(x,[0.1Lx,0.9Ly],0.1*Ly,1e4,1e6),
    H = -1,
    ηᵛᵖ = 1e5,
)

VEP_rheology = Rheology(elasticity = elas, plasticity = plas)

### CLOCK ###
clock = Clock(tspan = (0.0, 40), Δt = 1, Δt_max = 20)

### SOLVER ###
linsolver = BackslashSolver()
nlsolver = NewtonRaphson(max_iter_number = 10, atol = 1e-3, linear_solver = linsolver)

### MODEL ###
VEP_model = Model(
    grid = grid,
    variables = variables,
    quad_order = quad_order,
    quad_type = quad_type,
    bc = bc,
    body_forces = bf,
    rheology = VEP_rheology,
    initial_state = nothing,
    clock = clock,
    solver = nlsolver,
)

### OUTPUT ###
output_name = "point_load_plate"
VEP_outputs = Dict(
    :σxx => (r, s) -> s.σ[1, 1],
    :σyy => (r, s) -> s.σ[2, 2],
    :σzz => (r, s) -> s.σ[3, 3],
    :acum_ep => (r,s)-> s.ϵ̅ᵖ,
    #:η => (r, s) -> r.viscosity.η,
    :C => (r,s)-> r.plasticity.C,
    #:E => (r,s)-> r.elasticity.E,
    :τ => (r,s) -> R.get_τ(dev(s.σ),r.plasticity),
    :F => (r,s) -> R.get_τ(dev(s.σ),r.plasticity) - (1/3 * tr(s.σ) + r.plasticity.ξ*(r.plasticity.C + r.plasticity.H*s.ϵ̅ᵖ)),
    :p => (r,s) -> -1 / 3 * tr(s.σ),
)#,
#:τoverp  => (r,s)-> R.get_τ(dev(s.σ),r.plasticity)/(-1/3 * tr(s.σ)) )

# C = r.plasticity.C
# H = r.plasticity.H
# η = r.plasticity.η
# ξ = r.plasticity.ξ

VEP_ow = VTKOutputWriter(
    VEP_model,
    joinpath(output_path, output_name),
    VEP_outputs,
    interval = 1,
    force_path = true,
)

### SOLVE ###
@time modelsol, u = solve(VEP_model, output_writer = VEP_ow, log = true);


text:
using EvolvingGraphs
using Base.Test

tests = [
         "base",
         "evolving_graph",
         "adjacency_list",
         "centrality",
         "random_graph",
         "static_graph",
         #"io",
         "matrix_list",
         "incidence_matrix",
         "bfs",
         "dfs",
         "sort_slice",
         # "shortest_distance",
         # "shortest_temporal_distance",
         # "temporal_efficiency",
         # "components"
         ]

t_passed = falses(length(tests))
for (i,t) in enumerate(tests)
    tp = joinpath(Pkg.dir("EvolvingGraphs"), "test", "$(t).jl")
    println("Testing $t ...")
    try
        include(tp)
        println("$t tests passed.\n")
        t_passed[i] = true
    catch
        println("$t tests failed!\n")
    end
end

println("##### Test Summary: #####")
for (i,t) in enumerate(tests)
    println(t_passed[i] ? "$t ✓" : "$t ✗")
end

@test all(t_passed)


text:
abstract type Dependency end

_ni(f, dep) = error("$f not implemented for type $(typeof(dep))!")

# Dependency API:
dep(node::Dependency, args...; head=0, kwargs...) = _ni(dep, node)
deprel(node::Dependency) = _ni(deprel, node)
form(node::Dependency) = _ni(form, node)
hashead(node::Dependency) = _ni(hashead, node)
head(node::Dependency) = _ni(head, node)
isroot(node::Dependency) = _ni(isroot, node)
noval(node::Dependency) = _ni(noval, node)
root(t::Type{<:Dependency}) = _ni(root, t)
unk(t::Type{<:Dependency}) = _ni(unk, t)

const ROOT = "ROOT"
const NOVAL = "NOVAL"

leftdeps(tokens::AbstractVector, i::Int) =
    id.(filter(t -> id(t) < i && head(t) == i, tokens))

leftdeps(tokens::AbstractVector, dep::Dependency) =
    filter(t -> id(t) < id(dep) && head(t) == id(dep), tokens)

rightdeps(tokens::AbstractVector, i::Int) =
    id.(filter(t -> id(t) > i && head(t) == i, tokens))

rightdeps(tokens::AbstractVector, dep::Dependency) =
    filter(t -> id(t) > id(dep) && head(t) == id(dep), tokens)

function leftmostdep(tokens::AbstractVector, i::Int, n::Int=1, notfound::Int=-1)
    deps = filter(a -> i > id(a) && hashead(a) && head(a) == i, tokens)
    return length(deps) < n ? notfound : id(deps[n])
end
function leftmostdep(tokens::AbstractVector, dep::Dependency, n::Int=1)
    ldep = leftmostdep(tokens, id(dep), n)
    return ldep == -1 ? noval(eltype(tokens)) : tokens[ldep]
end

function rightmostdep(tokens::AbstractVector, i::Int, n::Int=1, notfound::Int=-1)
    deps = filter(a -> i < id(a) && hashead(a) && head(a) == i, tokens)
    return length(deps) < n ? notfound : id(deps[end-n+1])
end
function rightmostdep(tokens::AbstractVector, dep::Dependency, n::Int=1)
    rdep = rightmostdep(tokens, id(dep), n)
    return rdep == -1 ? noval(eltype(tokens)) : tokens[rdep]
end

struct MultiWordToken
    i::Int
    j::Int
    word::String
end

function MultiWordToken(line::String)
    fields = split(line, "\t")
    i, j = match(r"([0-9]+)-([0-9]+)", fields[1]).captures
    MultiWordToken(parse(Int, i), parse(Int, j), String(fields[2]))
end

struct EmptyToken
    id::Float32
    word::String
end

function EmptyToken(line::String)
    fields = split(line, "\t")
    EmptyToken(parse(Float32, fields[1]), String(fields[2]))
end

"""
    UntypedDependency(id, form, head)

Represents a simple untyped (head --> dependent) relation between two
words in a sentence.
"""
struct UntypedDependency <: Dependency
    id::Int
    form::String
    head::Int
end

function UntypedDependency(line::String)
    xs = split(strip(line))
    UntypedDependency(parse(Int, xs[1]), String(xs[2]), parse(Int, xs[3]))
end

function UntypedDependency(id::Int, line::String)
    form, head = split(strip(line))
    UntypedDependency(id, String(form), parse(Int, head))
end

dep(d::UntypedDependency, _args...; head=head(d)) =
    UntypedDependency(d.id, d.form, head)

typed(d::UntypedDependency) = ()

id(d::UntypedDependency) = d.id
deprel(d::UntypedDependency) = ()
form(d::UntypedDependency) = d.form
hashead(d::UntypedDependency) = (d.head >= 0)
head(d::UntypedDependency) = d.head

isroot(d::UntypedDependency) = (d.form == ROOT && d.id == 0)
noval(::Type{UntypedDependency}) = UntypedDependency(-1, NOVAL, -1)
root(::Type{UntypedDependency}) = UntypedDependency(0, ROOT, 0)

toconllu(d::UntypedDependency) =
    join([d.id,d.form,"_","_","_","_",d.head,"_","_","_"],"\t")*"\n"

unk(::Type{UntypedDependency}, id, word) = UntypedDependency(id, word, -1)

==(d1::UntypedDependency, d2::UntypedDependency) =
    d1.id == d2.id && d1.form == d2.form && d1.head == d2.head

"""
    TypedDependency(id, form, deprel, head)

Represents a typed (head -[deprel]-> dependent) relation between two
words in a sentence. `id` is the index of the word `form` in the
sentence (starting at 1, with 0 meaning the root node). `deprel` is
the dependency relation between this word and its `head`).
"""
struct TypedDependency{T} <: Dependency
    id::Int
    form::String
    deprel::T
    head::Int
end

function TypedDependency(line::AbstractString; read_deprel=String)
    xs = String.(split(strip(line)))
    id = parse(Int, xs[1])
    form = xs[2]
    deprel = read_deprel(xs[3])
    head = parse(Int, xs[4])
    TypedDependency(id, form, deprel, head)
end

function TypedDependency(id::Int, line::AbstractString; read_deprel=String)
    xs = String.(split(strip(line)))
    form = xs[1]
    deprel = read_deprel(xs[2])
    head = parse(Int, xs[3])
    TypedDependency(id, form, deprel, head)
end

dep(d::TypedDependency, deprel=deprel(d); head=head(d)) =
    TypedDependency(d.id, d.form, deprel, head)

id(d::TypedDependency) = d.id
deprel(d::TypedDependency) = d.deprel
form(d::TypedDependency) = d.form
hashead(d::TypedDependency) = (d.head >= 0)
head(d::TypedDependency) = d.head
isroot(d::TypedDependency) = (d.form == ROOT && d.id == 0)
root(::Type{<:TypedDependency}) = TypedDependency(0, ROOT, ROOT, 0)
noval(::Type{<:TypedDependency}) = TypedDependency(-1, NOVAL, NOVAL, -1)

toconllu(d::TypedDependency) =
    join([d.id,d.form,"_","_","_","_",d.head,d.deprel,"_","_"],"\t")*"\n"

unk(::Type{TypedDependency}, id, word) = TypedDependency(id, word, undef, -1)

==(d1::TypedDependency, d2::TypedDependency) =
    all([d1.id == d2.id, d1.form == d2.form,
         d1.deprel == d2.deprel, d1.head == d2.head])


text:
syms lon lat r
syms x1 y1 z1
syms xx1 yy1 zz1
syms lam1 theta1 r1

% xx1=x1/sqrt(x1^2+y1^2+z1^2);
% yy1=y1/sqrt(x1^2+y1^2+z1^2);
% zz1=z1/sqrt(x1^2+y1^2+z1^2);

% xx1=r*cos(lam)*cos(theta)
% yy1=r*sin(lam)*cos(theta)
% zz1=r*sin(theta);
% yy1/xx1=sin(lam)/cos(lam)
% lam=atan(yy1/xx1)
% theta=asin(zz1/sqrt(xx1^2+yy1^2+zz1^2))
% r=sqrt(xx1^2+yy1^2+zz1^2);
%
% d atan(s) / ds = 1/(1+s^2)
% d asin(s) / ds = 1/sqrt(1-s^2)

lam=atan(yy1/xx1);
theta=asin(zz1);

D1=[diff(lam,xx1) diff(lam,yy1) diff(lam,zz1)
    diff(theta,xx1) diff(theta,yy1) diff(theta,zz1)];
D11=subs(D1,{xx1,yy1,zz1},{cos(lam1)*cos(theta1),sin(lam1)*cos(theta1),sin(theta1)});
D111=simplify(D11);

C=[cos(theta1) 0
   0           1 ];
D1111=C*D111;

lam=atan(yy1/xx1);
theta=asin(zz1/sqrt(xx1^2+yy1^2+zz1^2));
r=sqrt(xx1^2+yy1^2+zz1^2);
E1=[diff(lam,xx1) diff(lam,yy1) diff(lam,zz1)
    diff(theta,xx1) diff(theta,yy1) diff(theta,zz1)
    diff(r,xx1) diff(r,yy1) diff(r,zz1)];
E11=subs(E1,{xx1,yy1,zz1},{r1*cos(lam1)*cos(theta1),r1*sin(lam1)*cos(theta1),r1*sin(theta1)});
E111=simplify(E11);

C=[r1*cos(theta1) 0  0
   0              r1 0
   0              0  1];

E1111=C*E111;

% [-sin(lam1)                cos(lam1)                     0
%  -cos(lam1)*sin(theta1)   -sin(lam1)*sin(theta1)    cos(theta1)
%   cos(lam1)*cos(theta1)    sin(lam1)*cos(theta1)    sin(theta1)]

A(1,1)=diff(xx1,x1);
A(1,2)=diff(xx1,y1);
A(1,3)=diff(xx1,z1);
A(2,1)=diff(yy1,x1);
A(2,2)=diff(yy1,y1);
A(2,3)=diff(yy1,z1);
A(3,1)=diff(zz1,x1);
A(3,2)=diff(zz1,y1);
A(3,3)=diff(zz1,z1);

AA=simplify(subs(A,{x1,y1,z1},{r*cos(lon)*cos(lat),r*sin(lon)*cos(lat),r*sin(lat)}));
B=[r*cos(lat) 0 0
  0         r 0
  0         0 r];
C=simplify(B*AA);
bb=77;


text:
using BenchmarkTools
using CuArrays
using Flux

f(m, x) = m(x)

in, out, batchsize = 1536, 1024, 64
σ = Flux.leakyrelu
m = CachedDense(in, out, σ; batchsize=batchsize) |> Flux.gpu
mf = Flux.Dense(in, out, σ) |> Flux.gpu

x = rand(Float32, in) |> Flux.gpu;
@benchmark CuArrays.@sync f($m, $x)
@benchmark CuArrays.@sync f($mf, $x)
x = rand(Float32, in, batchsize÷2) |> Flux.gpu;
@benchmark CuArrays.@sync f($m, $x)
@benchmark CuArrays.@sync f($mf, $x)
x = rand(Float32, in, batchsize) |> Flux.gpu;
@benchmark CuArrays.@sync f($m, $x)
@benchmark CuArrays.@sync f($mf, $x)

x = rand(Float32, in) |> Flux.gpu;
CuArrays.@time f(m, x);
CuArrays.@time f(mf, x);
x = rand(Float32, in, batchsize÷2) |> Flux.gpu;
CuArrays.@time f(m, x);
CuArrays.@time f(mf, x);
x = rand(Float32, in, batchsize) |> Flux.gpu;
CuArrays.@time f(m, x);
CuArrays.@time f(mf, x);

cdims = Flux.NNlib.DenseConvDims(x,x)
@edit Flux.conv!(x, m.W, x,cdims)

###
x = rand(Float32, in, batchsize) |> gpu
m = CachedDense(in, out; batchsize=batchsize)  |> gpu
θ = Flux.params(m)
mf = Dense(copy(m.W), copy(m.b)) |> gpu
θf = Flux.params(mf)

mf(x) == m(x)

Juno.@profiler gs = gradient(θ) do
   sum(m(x))
end
@time gsf = gradient(θf) do
   sum(mf(x))
end

gsf[mf.W] == gs[m.W]
gsf[mf.b] == gs[m.b]

###
function reorder(x::AbstractMatrix)
   o = size(x,1) ÷ 4
   [x[1:(2o),:];
    x[(3o+1):end,:];
    x[(2o+1):(3o),:]]
end
function reorder(x::AbstractVector)
   o = size(x,1) ÷ 4
   [x[1:(2o)];
    x[(3o+1):end];
    x[(2o+1):(3o)]]
end

in, out, batchsize = 3, 5, 7
x = rand(Float32, in, batchsize) |> gpu
mf = Flux.LSTM(in, out) |> gpu; mf(x)
(h, c) = mf.state
(h1, c1), h1 = mf.cell((h, c), x)

m = CachedLSTMCell(in, out; batchsize=3batchsize) |> gpu
m = CachedLSTMCell(reorder(mf.cell.Wi), reorder(mf.cell.Wh), reorder(mf.cell.b), m.cache) |> gpu

(h2, c2), h2 = m((copy(h), copy(c)), x)
h1 == h2
c1 == c2

h1 - h2
c1 - c2

h1 ≈ h2
c1 ≈ c2

max_stars_repo_name: AzamatB/CachedFluxLayers

max_issues_repo_name: AzamatB/CachedFluxLayers

max_forks_repo_name: AzamatB/CachedFluxLayers


text:
using GeoInterface
using Test

@testset "Developer" begin
    # Implement interface
    struct MyPoint end
    struct MyEmptyPoint end
    struct MyCurve end
    struct MyPolygon end
    struct MyTriangle end
    struct MyMultiPoint end
    struct MyMultiCurve end
    struct MyMultiPolygon end
    struct MyTIN end
    struct MyCollection end
    struct MyFeature{G,P}
        geometry::G
        properties::P
    end
    struct MyFeatureCollection{G}
        geoms::G
    end

    GeoInterface.isgeometry(::MyPoint) = true
    GeoInterface.geomtrait(::MyPoint) = PointTrait()
    GeoInterface.ncoord(::PointTrait, geom::MyPoint) = 2
    GeoInterface.getcoord(::PointTrait, geom::MyPoint, i) = [1, 2][i]

    GeoInterface.isgeometry(::MyEmptyPoint) = true
    GeoInterface.geomtrait(::MyEmptyPoint) = PointTrait()
    GeoInterface.ncoord(::PointTrait, geom::MyEmptyPoint) = 0
    GeoInterface.isempty(::PointTrait, geom::MyEmptyPoint) = true

    GeoInterface.isgeometry(::MyCurve) = true
    GeoInterface.geomtrait(::MyCurve) = LineStringTrait()
    GeoInterface.ngeom(::LineStringTrait, geom::MyCurve) = 2
    GeoInterface.getgeom(::LineStringTrait, geom::MyCurve, i) = MyPoint()
    Base.convert(T::Type{MyCurve}, geom::X) where {X} = Base.convert(T, geomtrait(geom), geom)
    Base.convert(::Type{MyCurve}, ::LineStringTrait, geom::MyCurve) = geom

    GeoInterface.isgeometry(::MyPolygon) = true
    GeoInterface.geomtrait(::MyPolygon) = PolygonTrait()
    GeoInterface.ngeom(::PolygonTrait, geom::MyPolygon) = 2
    GeoInterface.getgeom(::PolygonTrait, geom::MyPolygon, i) = MyCurve()

    GeoInterface.isgeometry(::MyTriangle) = true
    GeoInterface.geomtrait(::MyTriangle) = TriangleTrait()
    GeoInterface.ngeom(::TriangleTrait, geom::MyTriangle) = 3
    GeoInterface.getgeom(::TriangleTrait, geom::MyTriangle, i) = MyCurve()

    GeoInterface.isgeometry(::MyMultiPoint) = true
    GeoInterface.geomtrait(::MyMultiPoint) = MultiPointTrait()
    GeoInterface.ngeom(::MultiPointTrait, geom::MyMultiPoint) = 2
    GeoInterface.getgeom(::MultiPointTrait, geom::MyMultiPoint, i) = MyPoint()

    GeoInterface.isgeometry(::MyMultiCurve) = true
    GeoInterface.geomtrait(::MyMultiCurve) = MultiCurveTrait()
    GeoInterface.ngeom(::MultiCurveTrait, geom::MyMultiCurve) = 2
    GeoInterface.getgeom(::MultiCurveTrait, geom::MyMultiCurve, i) = MyCurve()

    GeoInterface.isgeometry(::MyMultiPolygon) = true
    GeoInterface.geomtrait(::MyMultiPolygon) = MultiPolygonTrait()
    GeoInterface.ngeom(::MultiPolygonTrait, geom::MyMultiPolygon) = 2
    GeoInterface.getgeom(::MultiPolygonTrait, geom::MyMultiPolygon, i) = MyPolygon()

    GeoInterface.isgeometry(::MyTIN) = true
    GeoInterface.geomtrait(::MyTIN) = PolyhedralSurfaceTrait()
    GeoInterface.ngeom(::PolyhedralSurfaceTrait, geom::MyTIN) = 2
    GeoInterface.getgeom(::PolyhedralSurfaceTrait, geom::MyTIN, i) = MyTriangle()

    GeoInterface.isgeometry(::MyCollection) = true
    GeoInterface.geomtrait(::MyCollection) = GeometryCollectionTrait()
    GeoInterface.ngeom(::GeometryCollectionTrait, geom::MyCollection) = 2
    GeoInterface.getgeom(::GeometryCollectionTrait, geom::MyCollection, i) = MyCurve()

    GeoInterface.isfeature(::Type{<:MyFeature}) = true
    GeoInterface.trait(feature::MyFeature) = FeatureTrait()
    GeoInterface.geometry(f::MyFeature) = f.geometry
    GeoInterface.properties(f::MyFeature) = f.properties
    GeoInterface.extent(f::MyFeature) = nothing

    GeoInterface.isfeaturecollection(fc::Type{<:MyFeatureCollection}) = true
    GeoInterface.trait(fc::MyFeatureCollection) = FeatureCollectionTrait()
    GeoInterface.nfeature(::FeatureCollectionTrait, fc::MyFeatureCollection) = length(fc.geoms)
    GeoInterface.getfeature(::FeatureCollectionTrait, fc::MyFeatureCollection) = fc.geoms
    GeoInterface.getfeature(::FeatureCollectionTrait, fc::MyFeatureCollection, i::Integer) = fc.geoms[i]

    @testset "Point" begin
        geom = MyPoint()
        @test testgeometry(geom)
        @test GeoInterface.x(geom) === 1
        @test GeoInterface.y(geom) === 2
        @test_throws ArgumentError GeoInterface.z(geom)
        @test_throws ArgumentError GeoInterface.m(geom)
        @test ncoord(geom) === 2
        @test collect(getcoord(geom)) == [1, 2]
        @test getcoord(geom, 1) === 1
        @test GeoInterface.coordnames(geom) == (:X, :Y)
        @test !GeoInterface.isempty(geom)
        @test !GeoInterface.is3d(geom)
        @test !GeoInterface.ismeasured(geom)

        geom = MyEmptyPoint()
        @test GeoInterface.coordnames(geom) == ()
        @test GeoInterface.isempty(geom)

        @test isnothing(GeoInterface.crs(geom))
        @test isnothing(GeoInterface.extent(geom))
        @test isnothing(GeoInterface.bbox(geom))
    end

    @testset "LineString" begin
        geom = MyCurve()
        @test testgeometry(geom)

        @test GeoInterface.npoint(geom) == 2  # defaults to ngeom
        @test GeoInterface.coordinates(geom) == [[1, 2], [1, 2]]
        points = GeoInterface.getpoint(geom)
        point = GeoInterface.getpoint(geom, 1)
        pointa = GeoInterface.startpoint(geom)
        pointb = GeoInterface.endpoint(geom)
        @test GeoInterface.y(point) == 2

        @test_throws MethodError GeoInterface.length(geom)

        @test GeoInterface.issimple(geom)
        @test GeoInterface.isclosed(geom)
        @test GeoInterface.isring(geom)

    end

    @testset "Polygon" begin
        geom = MyPolygon()
        @test testgeometry(geom)
        # Test that half a implementation yields an error

        @test GeoInterface.nring(geom) == 2
        @test GeoInterface.nhole(geom) == 1
        @test GeoInterface.coordinates(geom) == [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]
        lines = GeoInterface.getring(geom)
        line = GeoInterface.getring(geom, 1)
        lines = GeoInterface.gethole(geom)
        line = GeoInterface.gethole(geom, 1)
        line = GeoInterface.getexterior(geom)
        @test GeoInterface.npoint(geom) == 4
        @test collect(GeoInterface.getpoint(geom)) == [MyPoint(), MyPoint(), MyPoint(), MyPoint()]

        @test_throws MethodError GeoInterface.area(geom)

        geom = MyTriangle()
        @test testgeometry(geom)
        @test GeoInterface.nring(geom) == 1
        @test GeoInterface.nhole(geom) == 0
        @test GeoInterface.npoint(geom) == 3
    end

    @testset "MultiPoint" begin
        geom = MyMultiPoint()
        @test testgeometry(geom)

        @test GeoInterface.npoint(geom) == 2
        points = GeoInterface.getpoint(geom)
        point = GeoInterface.getpoint(geom, 1)
        @test GeoInterface.coordinates(geom) == [[1, 2], [1, 2]]
        @test collect(points) == [MyPoint(), MyPoint()]

        @test !GeoInterface.issimple(geom)
    end

    @testset "MultiLineString" begin
        geom = MyMultiCurve()
        @test testgeometry(geom)

        @test GeoInterface.nlinestring(geom) == 2
        lines = GeoInterface.getlinestring(geom)
        line = GeoInterface.getlinestring(geom, 1)
        @test GeoInterface.coordinates(geom) == [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]
        @test collect(lines) == [MyCurve(), MyCurve()]
    end

    @testset "MultiPolygon" begin
        geom = MyMultiPolygon()
        @test testgeometry(geom)

        @test GeoInterface.npolygon(geom) == 2
        polygons = GeoInterface.getpolygon(geom)
        polygon = GeoInterface.getpolygon(geom, 1)
        @test GeoInterface.coordinates(geom) == [[[[1, 2], [1, 2]], [[1, 2], [1, 2]]], [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]]
        @test collect(polygons) == [MyPolygon(), MyPolygon()]
    end

    @testset "Surface" begin
        geom = MyTIN()
        @test testgeometry(geom)

        @test GeoInterface.npatch(geom) == 2
        polygons = GeoInterface.getpatch(geom)
        polygon = GeoInterface.getpatch(geom, 1)
        @test GeoInterface.coordinates(geom) == [[[[1, 2], [1, 2]], [[1, 2], [1, 2]], [[1, 2], [1, 2]]], [[[1, 2], [1, 2]], [[1, 2], [1, 2]], [[1, 2], [1, 2]]]]
        @test collect(polygons) == [MyTriangle(), MyTriangle()]
    end

    @testset "GeometryCollection" begin
        geom = MyCollection()
        @test testgeometry(geom)

        @test GeoInterface.ngeom(geom) == 2
        geoms = GeoInterface.getgeom(geom)
        thing = GeoInterface.getgeom(geom, 1)
        @test GeoInterface.coordinates(geom) == [[[1, 2], [1, 2]], [[1, 2], [1, 2]]]
        @test collect(geoms) == [MyCurve(), MyCurve()]
    end

end

@testset "Defaults" begin
    @test GeoInterface.subtrait(TINTrait()) == TriangleTrait
    @test GeoInterface.nring(QuadTrait(), ()) == 1
    @test GeoInterface.npoint(QuadTrait(), ()) == 4
end

@testset "Feature" begin
    feature = MyFeature((1, 2), (a=10, b=20))
    @test GeoInterface.testfeature(feature)
end

@testset "FeatureCollection" begin
    features = MyFeatureCollection(
        [MyFeature(MyPoint(), (a="1", b="2")), MyFeature(MyPolygon(), (a="3", b="4"))]
    )
    @test GeoInterface.testfeaturecollection(features)
end

@testset "Conversion" begin
    struct XCurve end
    struct XPolygon end

    Base.convert(T::Type{XCurve}, geom::X) where {X} = Base.convert(T, geomtrait(geom), geom)
    Base.convert(::Type{XCurve}, ::LineStringTrait, geom::XCurve) = geom  # fast fallthrough
    Base.convert(::Type{XCurve}, ::LineStringTrait, geom) = geom

    geom = MyCurve()
    @test !isnothing(convert(MyCurve, geom))

    Base.convert(T::Type{XPolygon}, geom::X) where {X} = Base.convert(T, geomtrait(geom), geom)
    @test_throws Exception convert(MyPolygon, geom)
end

@testset "Operations" begin
    struct XGeom end

    GeoInterface.isgeometry(::XGeom) = true
    GeoInterface.geomtrait(::XGeom) = PointTrait()
    GeoInterface.ncoord(::PointTrait, geom::XGeom) = 2
    GeoInterface.getcoord(::PointTrait, geom::XGeom, i) = [1, 2][i]

    GeoInterface.equals(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
    GeoInterface.disjoint(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
    GeoInterface.intersects(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
    GeoInterface.touches(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
    GeoInterface.within(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
    GeoInterface.contains(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
    GeoInterface.overlaps(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true
    GeoInterface.crosses(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = true

    GeoInterface.relate(::PointTrait, ::PointTrait, ::XGeom, ::XGeom, matrix) = true

    GeoInterface.symdifference(::PointTrait, ::PointTrait, a::XGeom, ::XGeom) = a
    GeoInterface.difference(::PointTrait, ::PointTrait, a::XGeom, ::XGeom) = a
    GeoInterface.intersection(::PointTrait, ::PointTrait, a::XGeom, ::XGeom) = a
    GeoInterface.union(::PointTrait, ::PointTrait, ::XGeom, a::XGeom) = a

    GeoInterface.distance(::PointTrait, ::PointTrait, ::XGeom, ::XGeom) = rand()

    GeoInterface.buffer(::PointTrait, a::XGeom, distance) = a
    GeoInterface.convexhull(::PointTrait, a::XGeom) = a

    GeoInterface.astext(::PointTrait, ::XGeom) = "POINT (1 2)"
    GeoInterface.asbinary(::PointTrait, ::XGeom) = [0x0, 0x0]

    geom = XGeom()

    @test GeoInterface.equals(geom, geom)
    @test GeoInterface.disjoint(geom, geom)
    @test GeoInterface.intersects(geom, geom)
    @test GeoInterface.touches(geom, geom)
    @test GeoInterface.within(geom, geom)
    @test GeoInterface.contains(geom, geom)
    @test GeoInterface.overlaps(geom, geom)
    @test GeoInterface.crosses(geom, geom)

    @test GeoInterface.relate(geom, geom, ["a"])

    @test GeoInterface.isgeometry(GeoInterface.symdifference(geom, geom))
    @test GeoInterface.isgeometry(GeoInterface.difference(geom, geom))
    @test GeoInterface.isgeometry(GeoInterface.intersection(geom, geom))
    @test GeoInterface.isgeometry(GeoInterface.union(geom, geom))

    @test GeoInterface.distance(geom, geom) isa Number

    @test GeoInterface.isgeometry(GeoInterface.buffer(geom, 1.0))
    @test GeoInterface.isgeometry(GeoInterface.convexhull(geom))

    @test GeoInterface.astext(geom) isa String
    @test GeoInterface.asbinary(geom) isa Vector{UInt8}
end

@testset "Base Implementations" begin

    @testset "Vector" begin
        geom = [1, 2]
        @test testgeometry(geom)
        @test GeoInterface.x(geom) == 1
        @test GeoInterface.ncoord(geom) == 2
        @test collect(GeoInterface.getcoord(geom)) == geom
    end

    @testset "Tuple" begin
        geom = (1, 2)
        @test testgeometry(geom)
        @test GeoInterface.x(geom) == 1
        @test GeoInterface.ncoord(geom) == 2
        @test collect(GeoInterface.getcoord(geom)) == [1, 2]
    end

    @testset "NamedTuple" begin
        geom = (; X=1, Y=2)
        @test testgeometry(geom)
        @test GeoInterface.x(geom) == 1
        @test collect(GeoInterface.getcoord(geom)) == [1, 2]

        geom = (; X=1, Y=2, Z=3)
        @test testgeometry(geom)
        geom = (; X=1, Y=2, Z=3, M=4)
        @test testgeometry(geom)
        geom = (; Z=3, X=1, Y=2, M=4)
        @test testgeometry(geom)

        @test GeoInterface.x(geom) == 1
        @test GeoInterface.m(geom) == 4
        @test GeoInterface.ncoord(geom) == 4
        @test collect(GeoInterface.getcoord(geom)) == [3, 1, 2, 4]

    end

    @testset "NamedTupleFeature" begin
        feature = (; geometry=(1, 2), properties=(a="x", b="y"))
        @test GeoInterface.testfeature(feature)
        @test GeoInterface.testfeaturecollection([feature, feature])
    end
end


text:
# Autogenerated wrapper script for ssht_jll for aarch64-apple-darwin
export libssht

using FFTW_jll
JLLWrappers.@generate_wrapper_header("ssht")
JLLWrappers.@declare_library_product(libssht, "@rpath/libssht.dylib")
function __init__()
    JLLWrappers.@generate_init_header(FFTW_jll)
    JLLWrappers.@init_library_product(
        libssht,
        "lib/libssht.dylib",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

max_stars_repo_name: UCLA-SEAL/JShrink

max_issues_repo_name: UCLA-SEAL/JShrink

max_forks_repo_name: UCLA-SEAL/JShrink


text:
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

Base.show(io::IO, sym::SymbolicNode) =
  print(io, "$(typeof(sym)) $(get_name(sym))")

"""
    print([io::IO], sym::SymbolicNode)

Print the content of symbol, used for debug.

```julia
julia> layer = @mx.chain mx.Variable(:data)           =>
         mx.FullyConnected(name=:fc1, num_hidden=128) =>
         mx.Activation(name=:relu1, act_type=:relu)
MXNet.mx.SymbolicNode(MXNet.mx.MX_SymbolHandle(Ptr{Nothing} @0x000055b29b9c3520))

julia> print(layer)
Symbol Outputs:
        output[0]=relu1(0)
Variable:data
Variable:fc1_weight
Variable:fc1_bias
--------------------
Op:FullyConnected, Name=fc1
Inputs:
        arg[0]=data(0) version=0
        arg[1]=fc1_weight(0) version=0
        arg[2]=fc1_bias(0) version=0
Attrs:
        num_hidden=128
--------------------
Op:Activation, Name=relu1
Inputs:
        arg[0]=fc1(0)
Attrs:
        act_type=relu
```
"""
function Base.print(io::IO, sym::SymbolicNode)
  out = Ref{mx.char_p}(C_NULL)
  @mx.mxcall(:MXSymbolPrint, (mx.MX_SymbolHandle, Ref{mx.char_p}), sym.handle, out)
  print(io, unsafe_string(out[]))
end

Base.print(sym::SymbolicNode) = print(stdout, sym)


text:
"""
    plot(data::InferenceData; groupname=:posterior, kwargs...)
    plot!(data::InferenceData; groupname=:posterior, kwargs...)

Plot the specified group of `data` using `kwargs` attributes recognized by Plots.
"""
RecipesBase.plot(::ArviZ.InferenceData; kwargs...)

RecipesBase.@recipe function f(
    ::Type{T}, data::T; groupname=:posterior
) where {T<:InferenceData}
    return tuple(ArviZ.convert_to_dataset(data; group=groupname))
end

"""
    plot(data::ArviZ.Dataset; kwargs...)
    plot!(data::ArviZ.Dataset; kwargs...)

Plot the specified group of `data` using `kwargs` attributes recognized by Plots.

`data` is split into individual subplots based on the provided keyword arguments.
Chain number for each draw is stored in the plot attribute `chain` and can be used by series
recipes.

# Positional Arguments
- `data`: an `ArviZ.Dataset` object.

# Keyword Arguments
- `var_names=nothing`: Variables to be plotted. Prefix the variables by `~`
    to exclude them from the plot. Behavior modified by `filter_vars`.
- `filter_vars=nothing`: interpret `var_names` as
    + `filter_vars=nothing`: real variables names
    + `filter_vars="like"`: substrings of the real variables names
    + `filter_vars="regex"`: regular expressions on the real variables names
- `coords=Dict()`: Specific coordinates of `var_names` to be plotted
- `kwargs`: Additional attributes understood by Plots.jl
"""
RecipesBase.plot(::ArviZ.Dataset; kwargs...)

RecipesBase.@recipe function f(
    ::Type{T}, data::T; var_names=nothing, coords=Dict(), filter_vars=nothing
) where {T<:ArviZ.Dataset}
    var_names = ArviZ.arviz.utils._var_names(var_names, data, filter_vars)
    plotters = collect(
        ArviZ.arviz.plots.plot_utils.xarray_var_iter(
            ArviZ.arviz.utils.get_coords(data, coords); var_names=var_names, combined=true
        ),
    )
    titles = String[]
    series_values = Vector{<:Real}[]
    chains = Vector{Int}[]
    for (var_name, selection, values) in plotters
        label = make_label(var_name, selection)
        push!(titles, label)
        push!(series_values, vec(values))
        sz = size(values)
        push!(chains, repeat(1:sz[1], prod(sz[2:end])))
    end
    layout := length(plotters)
    title --> permutedims(titles)
    # TODO: find a way to split chains across subplots.
    chain := permutedims(chains)
    return tuple(series_values)
end


text:
opts = [STRRidge(), ADMM(), SR3()]
iters = Int64[3000, 30000, 30000]
atols = Float64[1e-10, 1e-4, 1e-7]

@testset "Equal Sizes" begin

    x = 10.0*[1 -2 3; 5 0.5 8; 1.1 2.7 5]
    A = [0.6 0 -0.1; 0.1 -8.0 0; 0.9 0 -0.8]
    y = A*x

    threshold = 1e-3

    @testset for (opt, maxiter, a_tol) in zip(opts, iters, atols)
        set_threshold!(opt, threshold)
        Ξ = DataDrivenDiffEq.Optimize.init(opt, x', y')
        _iters = fit!(Ξ, x', y', opt, maxiter = maxiter)
        @debug println("$opt $_iters $(norm(A-Ξ', 2))")
        @test _iters <= maxiter
        @test norm(A - Ξ', 2) < a_tol
    end
end

@testset "Single Signal" begin
    x = 10.0*randn(3, 100)
    A = [1.0 0 -0.1]
    y = A*x
    threshold = 1e-2
    @testset for (opt, maxiter, a_tol) in zip(opts, iters, atols)
        set_threshold!(opt, threshold)
        Ξ = DataDrivenDiffEq.Optimize.init(opt, x', y')
        _iters = fit!(Ξ, x', y', opt, maxiter = maxiter)
        @debug println("$opt $_iters $(norm(A-Ξ', 2))")
        @test _iters <= maxiter
        @test norm(A - Ξ', 2) < a_tol
    end
end

@testset "Multiple Signals" begin
    x = 10.0*randn(100, 1000)
    A = zeros(5,100)
    A[1,1] = 1.0
    A[1, 50] = 3.0
    A[2, 75] = 10.0
    A[3, 5] = -2.0
    A[4,80] = 0.2
    A[5,5] = 0.1
    y = A*x
    threshold =1e-2
    @testset for (opt, maxiter, a_tol) in zip(opts, iters, atols)
        set_threshold!(opt, threshold)
        Ξ = DataDrivenDiffEq.Optimize.init(opt, x', y')
        _iters = fit!(Ξ, x', y', opt, maxiter = maxiter)
        @debug println("$opt $_iters $(norm(A-Ξ', 2))")
        @test _iters <= maxiter
        @test norm(A - Ξ', 2) < a_tol
    end
end

@testset "ADM" begin
    x = 10.0*randn(3, 100)
    A = Float64[1 0 3; 0 1 0; 0 2 1]
    @testset "Linear" begin
        Z = A*x # Measurements
        Z[1, :] = Z[1,:] ./ (1 .+ x[2,:])
        θ = [Z[1,:]'; Z[1,:]' .* x[1,:]';Z[1,:]' .* x[2,:]';Z[1,:]' .* x[3,:]'; x[1,:]'; x[2,:]'; x[3,:]']
        M = nullspace(θ', rtol = 0.99)
        L = deepcopy(M)
        opt = ADM(1e-2)
        fit!(M, L', opt, maxiter = 10000)
        @test all(norm.(eachcol(M)) .≈ 1)
        pareto = map(q->norm([norm(q, 0) ;norm(θ'*q, 2)], 2), eachcol(M))
        score, posmin = findmin(pareto)
        # Get the corresponding eqs
        q_best = M[:, posmin] ./ M[1, posmin]
        @test q_best ≈ [1.0 0 1.0 0 -1 0 -3]'
    end

    @testset "Quadratic" begin
        Z = A*x # Measurements
        Z[1, :] = Z[1,:] ./ (1 .+ x[2,:].*x[1,:])
        θ = [Z[1,:]'; Z[1,:]' .* x[1,:]';Z[1,:]' .* x[2,:]';Z[1,:]' .* x[3,:]'; Z[1,:]' .* (x[1,:].*x[2,:])'; x[1,:]'; x[2,:]'; x[3,:]']
        M = nullspace(θ', rtol = 0.99)
        L = deepcopy(M)
        opt = ADM(1e-2)
        fit!(M, L', opt, maxiter = 10000)
        @test all(norm.(eachcol(M)) .≈ 1)
        pareto = map(q->norm([norm(q, 0) ;norm(θ'*q, 2)], 2), eachcol(M))
        score, posmin = findmin(pareto)
        # Get the corresponding eqs
        q_best = M[:, posmin] ./ M[1, posmin]
        @test q_best ≈ [1.0 0 0.0 0.0 1.0 -1 0 -3]'
    end

    @testset "Nonlinear" begin
        Z = A*x # Measurements
        Z[1, :] = Z[1,:] ./ (2 .+ sin.(x[1,:]))
        θ = [Z[1,:]'; Z[1,:]' .* x[1,:]';Z[1,:]' .* x[2,:]';Z[1,:]' .* x[3,:]'; Z[1,:]' .* (x[1,:].*x[2,:])';Z[1,:]' .* sin.(x[1,:])' ;x[1,:]'; x[2,:]'; x[3,:]']
        M = nullspace(θ', rtol = 0.99)
        L = deepcopy(M)
        opt = ADM(1e-2)
        fit!(M, L', opt, maxiter = 10000)
        @test all(norm.(eachcol(M)) .≈ 1)
        pareto = map(q->norm([norm(q, 0) ;norm(θ'*q, 2)], 2), eachcol(M))
        score, posmin = findmin(pareto)
        # Get the corresponding eqs
        q_best = M[:, posmin] ./ M[1, posmin]
        @test q_best ≈ [1.0 0 0.0 0.0 0.0 0.5 -0.5 0 -1.5]'
    end
end


text:
# TODO: replace with Mjolnir version.

abstract type Diff end
struct UndefinedChange <: Diff end
struct NoChange <: Diff end
struct SetDiff{V} <: Diff
    added::Set{V}
    deleted::Set{V}
end
struct DictDiff{K, V} <: Diff
    added::AbstractDict{K, V}
    deleted::AbstractSet{K}
    updated::AbstractDict{K, Diff}
end
struct VectorDiff <: Diff
    new_length::Int
    prev_length::Int
    updated::Dict{Int,Diff}
    VectorDiff(nl::Int, pl::Int, updated::Dict{Int, Diff}) = new(nl, pl, updated)
end
struct IntDiff <: Diff
    difference::Int # new - old
end

struct Diffed{V, DV}
    val::V
    diff::DV
end

# Register diff propagation with Mjolnir
#struct DiffPrimitives end
#
#@abstract DiffPrimitives function *(d1::Partial{<:Diffed{V, NoChange}}, d2::Partial{<:Diffed{V, NoChange}}) where V
#    Diffed(d1.value.val * d2.value.val, NoChange())
#end
#@abstract DiffPrimitives function +(d1::Partial{<:Diffed{V, NoChange}}, d2::Partial{<:Diffed{V, NoChange}}) where V
#    Diffed(d1.value.val + d2.value.val, NoChange())
#end
#@abstract DiffPrimitives function -(d1::Partial{<:Diffed{V, NoChange}}, d2::Partial{<:Diffed{V, NoChange}}) where V
#    Diffed(d1.value.val - d2.value.val, NoChange())
#end
#@abstract DiffPrimitives function /(d1::Partial{<:Diffed{V, NoChange}}, d2::Partial{<:Diffed{V, NoChange}}) where V
#    Diffed(d1.value.val / d2.value.val, NoChange())
#end


text:
@testset "basicheuristic.jl" begin

    @testset "BasicHeuristic default function" begin
        trailer = SeaPearl.Trailer()
        model = SeaPearl.CPModel(trailer)

        x = SeaPearl.IntVar(2, 6, "x", trailer)
        heuristic = SeaPearl.BasicHeuristic()
        @test heuristic.selectValue(x) == 6
    end

    @testset "BasicHeuristic" begin
        valueselection = SeaPearl.BasicHeuristic()
        my_heuristic(x::SeaPearl.IntVar; cpmodel=nothing) = minimum(x.domain)
        new_valueselection = SeaPearl.BasicHeuristic(my_heuristic)

        @test new_valueselection.selectValue == my_heuristic

        trailer = SeaPearl.Trailer()
        model = SeaPearl.CPModel(trailer)

        x = SeaPearl.IntVar(2, 6, "x", trailer)

        @test valueselection.selectValue(x) == 6
        @test new_valueselection.selectValue(x) == 2
    end

end


text:
using MAT

function load_data(N::Int64)
  #=
  This function loads the training, validation and test sets.
  Further, it divides the training set into mini-batches.
  Finally, it returns the needed data for every case.
  --------------
  Input N : Size of mini-batch
  --------------
  Outputs:
  train_input: An array of size D X N X M, where
              D: number of words in the input(in this dataset it is 3)
              N: size of each mini-batch
              M: number of mini-batches
  train_target: Ab array of size 1 X N X M.
  valid_input: An array of size D X number of points in the validation set.
  test: An array of size D X number of points in the test set.
  vocab: Vocabulary of containing index to word mapping.

  =#

  file = matopen("data.mat")
  data = read(file, "data")
  numdims = size(data["trainData"], 1)
  D = numdims - 1
  M = convert(Int64, floor(size(data["trainData"], 2) / N))
  train_input = reshape(data["trainData"][1:D, 1:N * M], D, N, M)
  train_target = reshape(data["trainData"][D + 1, 1:N * M], 1, N, M)
  valid_input = data["validData"][1:D, :]
  valid_target = data["validData"][D+1, :]
  test_input = data["testData"][1:D, :]
  test_target = data["testData"][D + 1, :]
  vocab = data["vocab"]

  return (train_input,
          train_target,
          valid_input,
          valid_target,
          test_input,
          test_target,
          vocab)
end

max_stars_repo_name: kirnap/Machine-Learning-in-Julia

max_issues_repo_name: kirnap/Machine-Learning-in-Julia

max_forks_repo_name: kirnap/Machine-Learning-in-Julia