text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

export
# Modules
    Meta,
    StackTraces,
    Sys,
    Libc,
    Docs,
    Threads,
    Iterators,
    Broadcast,
    MathConstants,

# Types
    AbstractChannel,
    AbstractIrrational,
    AbstractMatrix,
    AbstractRange,
    AbstractSet,
    AbstractUnitRange,
    AbstractVector,
    AbstractVecOrMat,
    Array,
    AbstractDict,
    BigFloat,
    BigInt,
    BitArray,
    BitMatrix,
    BitVector,
    CartesianIndex,
    CartesianIndices,
    LinearIndices,
    Channel,
    Cmd,
    Colon,
    Complex,
    ComplexF64,
    ComplexF32,
    ComplexF16,
    DenseMatrix,
    DenseVecOrMat,
    DenseVector,
    Dict,
    Dims,
    Enum,
    ExponentialBackOff,
    IndexCartesian,
    IndexLinear,
    IndexStyle,
    InsertionSort,
    BitSet,
    IOBuffer,
    IOStream,
    LinRange,
    Irrational,
    Matrix,
    MergeSort,
    Missing,
    NTuple,
    IdDict,
    OrdinalRange,
    Pair,
    PartialQuickSort,
    PermutedDimsArray,
    QuickSort,
    Rational,
    Regex,
    RegexMatch,
    RoundFromZero,
    RoundDown,
    RoundingMode,
    RoundNearest,
    RoundNearestTiesAway,
    RoundNearestTiesUp,
    RoundToZero,
    RoundUp,
    Set,
    Some,
    StepRange,
    StepRangeLen,
    StridedArray,
    StridedMatrix,
    StridedVecOrMat,
    StridedVector,
    SubArray,
    SubString,
    SubstitutionString,
    Timer,
    UnitRange,
    Val,
    VecOrMat,
    Vector,
    VersionNumber,
    WeakKeyDict,

# Ccall types
    Cchar,
    Cdouble,
    Cfloat,
    Cint,
    Cintmax_t,
    Clong,
    Clonglong,
    Cptrdiff_t,
    Cshort,
    Csize_t,
    Cssize_t,
    Cuchar,
    Cuint,
    Cuintmax_t,
    Culong,
    Culonglong,
    Cushort,
    Cwchar_t,
    Cstring,
    Cwstring,

# Exceptions
    CapturedException,
    CompositeException,
    DimensionMismatch,
    EOFError,
    InvalidStateException,
    KeyError,
    MissingException,
    ProcessFailedException,
    TaskFailedException,
    SystemError,
    StringIndexError,

# Global constants and variables
    ARGS,
    C_NULL,
    DEPOT_PATH,
    ENDIAN_BOM,
    ENV,
    LOAD_PATH,
    PROGRAM_FILE,
    stderr,
    stdin,
    stdout,
    VERSION,
    devnull,

# Mathematical constants
    Inf,
    Inf16,
    Inf32,
    Inf64,
    NaN,
    NaN16,
    NaN32,
    NaN64,
    im,
    π, pi,
    ℯ,

# Operators
    !,
    !=,
    ≠,
    !==,
    ≡,
    ≢,
    xor,
    ⊻,
    %,
    ÷,
    &,
    *,
    +,
    -,
    /,
    //,
    <,
    <:,
    <<,
    <=,
    ≤,
    ==,
    >,
    >:,
    >=,
    ≥,
    >>,
    >>>,
    \,
    ^,
    |,
    |>,
    ~,
    :,
    =>,
    ∘,

# scalar math
    @evalpoly,
    evalpoly,
    abs,
    abs2,
    acos,
    acosd,
    acosh,
    acot,
    acotd,
    acoth,
    acsc,
    acscd,
    acsch,
    angle,
    asec,
    asecd,
    asech,
    asin,
    asind,
    asinh,
    atan,
    atand,
    atanh,
    big,
    binomial,
    bswap,
    cbrt,
    ceil,
    cis,
    clamp,
    cld,
    cmp,
    complex,
    conj,
    copysign,
    cos,
    cosc,
    cosd,
    cosh,
    cospi,
    cot,
    cotd,
    coth,
    count_ones,
    count_zeros,
    csc,
    cscd,
    csch,
    deg2rad,
    denominator,
    div,
    divrem,
    eps,
    exp,
    exp10,
    exp2,
    expm1,
    exponent,
    factorial,
    fld,
    fld1,
    fldmod,
    fldmod1,
    flipsign,
    float,
    tryparse,
    floor,
    fma,
    frexp,
    gcd,
    gcdx,
    hypot,
    imag,
    inv,
    invmod,
    isapprox,
    iseven,
    isfinite,
    isinf,
    isinteger,
    isnan,
    isodd,
    ispow2,
    isqrt,
    isreal,
    issubnormal,
    iszero,
    isone,
    lcm,
    ldexp,
    leading_ones,
    leading_zeros,
    log,
    log10,
    log1p,
    log2,
    maxintfloat,
    mod,
    mod1,
    modf,
    mod2pi,
    muladd,
    nextfloat,
    nextpow,
    nextprod,
    numerator,
    one,
    oneunit,
    powermod,
    prevfloat,
    prevpow,
    rad2deg,
    rationalize,
    real,
    floatmax,
    floatmin,
    reim,
    reinterpret,
    rem,
    rem2pi,
    round,
    sec,
    secd,
    sech,
    sign,
    signbit,
    signed,
    significand,
    sin,
    sinc,
    sincos,
    sincosd,
    sind,
    sinh,
    sinpi,
    sqrt,
    tan,
    tand,
    tanh,
    trailing_ones,
    trailing_zeros,
    trunc,
    unsafe_trunc,
    typemax,
    typemin,
    unsigned,
    widemul,
    zero,
    √,
    ∛,
    ≈,
    ≉,

# arrays
    axes,
    broadcast!,
    broadcast,
    cat,
    checkbounds,
    checkindex,
    circcopy!,
    circshift,
    circshift!,
    clamp!,
    conj!,
    copy!,
    copyto!,
    diff,
    cumprod,
    cumprod!,
    cumsum,
    cumsum!,
    accumulate,
    accumulate!,
    eachcol,
    eachindex,
    eachrow,
    eachslice,
    extrema,
    fill!,
    fill,
    first,
    hcat,
    hvcat,
    indexin,
    argmax,
    argmin,
    invperm,
    invpermute!,
    isassigned,
    isperm,
    issorted,
    last,
    mapslices,
    max,
    maximum!,
    maximum,
    min,
    minimum!,
    minimum,
    minmax,
    ndims,
    ones,
    parent,
    parentindices,
    partialsort,
    partialsort!,
    partialsortperm,
    partialsortperm!,
    permute!,
    permutedims,
    permutedims!,
    prod!,
    prod,
    promote_shape,
    range,
    reshape,
    reverse!,
    reverse,
    rot180,
    rotl90,
    rotr90,
    size,
    selectdim,
    sort!,
    sort,
    sortperm,
    sortperm!,
    sortslices,
    dropdims,
    step,
    stride,
    strides,
    sum!,
    sum,
    to_indices,
    vcat,
    vec,
    view,
    zeros,

# search, find, match and related functions
    eachmatch,
    endswith,
    findall,
    findfirst,
    findlast,
    findmax,
    findmin,
    findmin!,
    findmax!,
    findnext,
    findprev,
    match,
    occursin,
    searchsorted,
    searchsortedfirst,
    searchsortedlast,
    startswith,

# linear algebra
    adjoint,
    transpose,
    kron,

# bitarrays
    falses,
    trues,

# dequeues
    append!,
    insert!,
    pop!,
    prepend!,
    push!,
    resize!,
    popfirst!,
    pushfirst!,

# collections
    all!,
    all,
    allunique,
    any!,
    any,
    firstindex,
    collect,
    count,
    delete!,
    deleteat!,
    eltype,
    empty!,
    empty,
    lastindex,
    filter!,
    filter,
    foldl,
    foldr,
    foreach,
    get,
    get!,
    getindex,
    getkey,
    haskey,
    in,
    intersect!,
    intersect,
    isempty,
    issubset,
    issetequal,
    keys,
    keytype,
    length,
    map!,
    map,
    mapfoldl,
    mapfoldr,
    mapreduce,
    merge!,
    merge,
    pairs,
    reduce,
    setdiff!,
    setdiff,
    setindex!,
    similar,
    sizehint!,
    splice!,
    symdiff!,
    symdiff,
    union!,
    union,
    unique!,
    unique,
    values,
    valtype,
    ∈,
    ∉,
    ∋,
    ∌,
    ⊆,
    ⊈,
    ⊊,
    ⊇,
    ⊉,
    ⊋,
    ∩,
    ∪,

# strings
    ascii,
    bitstring,
    bytes2hex,
    chomp,
    chop,
    codepoint,
    codeunit,
    codeunits,
    digits,
    digits!,
    escape_string,
    hex2bytes,
    hex2bytes!,
    isascii,
    iscntrl,
    isdigit,
    isletter,
    islowercase,
    isnumeric,
    isprint,
    ispunct,
    isspace,
    isuppercase,
    isxdigit,
    lowercase,
    lowercasefirst,
    isvalid,
    join,
    lpad,
    lstrip,
    ncodeunits,
    ndigits,
    nextind,
    prevind,
    repeat,
    replace,
    replace!,
    repr,
    reverseind,
    rpad,
    rsplit,
    rstrip,
    split,
    string,
    strip,
    textwidth,
    thisind,
    titlecase,
    transcode,
    unescape_string,
    uppercase,
    uppercasefirst,

# text output
    IOContext,
    displaysize,
    dump,
    print,
    println,
    printstyled,
    show,
    showerror,
    sprint,
    summary,

# logging
    @debug,
    @info,
    @warn,
    @error,

# bigfloat & precision
    precision,
    rounding,
    setprecision,
    setrounding,
    get_zero_subnormals,
    set_zero_subnormals,

# iteration
    iterate,

    enumerate,  # re-exported from Iterators
    zip,
    only,

# object identity and equality
    copy,
    deepcopy,
    hash,
    identity,
    isbits,
    isequal,
    isimmutable,
    isless,
    ifelse,
    objectid,
    sizeof,

# tasks and conditions
    Condition,
    current_task,
    islocked,
    istaskdone,
    istaskstarted,
    istaskfailed,
    lock,
    notify,
    ReentrantLock,
    schedule,
    task_local_storage,
    trylock,
    unlock,
    yield,
    yieldto,
    wait,
    timedwait,
    asyncmap,
    asyncmap!,

# channels
    take!,
    put!,
    isready,
    fetch,
    bind,

# missing values
    coalesce,
    ismissing,
    missing,
    skipmissing,
    something,
    isnothing,
    nonmissingtype,

# time
    sleep,
    time,
    time_ns,

# errors
    backtrace,
    catch_backtrace,
    error,
    rethrow,
    retry,
    systemerror,

# stack traces
    stacktrace,

# types
    convert,
    getproperty,
    setproperty!,
    fieldoffset,
    fieldname,
    fieldnames,
    fieldcount,
    fieldtypes,
    hasfield,
    propertynames,
    hasproperty,
    isabstracttype,
    isbitstype,
    isprimitivetype,
    isstructtype,
    isconcretetype,
    isdispatchtuple,
    oftype,
    promote,
    promote_rule,
    promote_type,
    instances,
    supertype,
    typeintersect,
    typejoin,
    widen,

# syntax
    esc,
    gensym,
    macroexpand,
    @macroexpand1,
    @macroexpand,
    parse,

# help and reflection
    code_typed,
    code_lowered,
    fullname,
    functionloc,
    isconst,
    isinteractive,
    hasmethod,
    methods,
    nameof,
    parentmodule,
    pathof,
    pkgdir,
    names,
    which,
    @isdefined,

# loading source files
    __precompile__,
    evalfile,
    include_string,
    include_dependency,

# RTS internals
    GC,
    finalizer,
    finalize,
    precompile,

# misc
    atexit,
    atreplinit,
    exit,
    ntuple,

# I/O and events
    close,
    countlines,
    eachline,
    eof,
    fd,
    fdio,
    flush,
    gethostname,
    htol,
    hton,
    ismarked,
    isopen,
    isreadonly,
    ltoh,
    mark,
    bytesavailable,
    ntoh,
    open,
    pipeline,
    Pipe,
    PipeBuffer,
    position,
    RawFD,
    read,
    read!,
    readavailable,
    readbytes!,
    readchomp,
    readdir,
    readline,
    readlines,
    readuntil,
    redirect_stderr,
    redirect_stdin,
    redirect_stdout,
    reset,
    seek,
    seekend,
    seekstart,
    skip,
    skipchars,
    take!,
    truncate,
    unmark,
    unsafe_read,
    unsafe_write,
    write,

# multimedia I/O
    AbstractDisplay,
    display,
    displayable,
    TextDisplay,
    istextmime,
    MIME,
    @MIME_str,
    popdisplay,
    pushdisplay,
    redisplay,
    showable,
    HTML,
    Text,

# paths and file names
    abspath,
    basename,
    dirname,
    expanduser,
    homedir,
    isabspath,
    isdirpath,
    joinpath,
    normpath,
    realpath,
    relpath,
    splitdir,
    splitdrive,
    splitext,
    splitpath,

# filesystem operations
    cd,
    chmod,
    chown,
    cp,
    ctime,
    download,
    filemode,
    filesize,
    gperm,
    isblockdev,
    ischardev,
    isdir,
    isfifo,
    isfile,
    islink,
    ismount,
    ispath,
    isreadable,
    issetgid,
    issetuid,
    issocket,
    issticky,
    iswritable,
    lstat,
    mkdir,
    mkpath,
    mktemp,
    mktempdir,
    mtime,
    mv,
    operm,
    pwd,
    readlink,
    rm,
    stat,
    symlink,
    tempdir,
    tempname,
    touch,
    uperm,
    walkdir,

# external processes ## TODO: whittle down these exports.
    detach,
    getpid,
    ignorestatus,
    kill,
    process_exited,
    process_running,
    run,
    setenv,
    success,
    withenv,

# C interface
    @cfunction,
    cglobal,
    disable_sigint,
    pointer,
    pointer_from_objref,
    unsafe_wrap,
    unsafe_string,
    reenable_sigint,
    unsafe_copyto!,
    unsafe_load,
    unsafe_pointer_to_objref,
    unsafe_store!,

# implemented in Random module
    rand,
    randn,

# Macros
    # parser internal
    @__FILE__,
    @__DIR__,
    @__LINE__,
    @__MODULE__,
    @int128_str,
    @uint128_str,
    @big_str,
    @cmd,    # `commands`

    # notation for certain types
    @b_str,    # byte vector
    @r_str,    # regex
    @s_str,    # regex substitution string
    @v_str,    # version number
    @raw_str,  # raw string with no interpolation/unescaping

    # documentation
    @text_str,
    @html_str,
    @doc,

    # output
    @show,

    # profiling
    @time,
    @timed,
    @timev,
    @elapsed,
    @allocated,

    # tasks
    @sync,
    @async,
    @task,
    @threadcall,

    # metaprogramming utilities
    @generated,
    @gensym,
    @eval,
    @deprecate,

    # performance annotations
    @boundscheck,
    @inbounds,
    @fastmath,
    @simd,
    @inline,
    @noinline,
    @nospecialize,
    @specialize,
    @polly,

    @assert,
    @__dot__,
    @enum,
    @label,
    @goto,
    @view,
    @views,
    @static


text:
module AdventOfCode2020

include("day01/day01.jl")

end

ext: jl


text:
A = AxisArray(reshape(1:24, 2,3,4), .1:.1:.2, .1:.1:.3, .1:.1:.4)
D = similar(A)
D[1,1,1,1,1] = 10
@test @inferred(D[1,1,1,1,1]) == @inferred(D[1]) == D.data[1] == 10
@test @inferred(D[1,1,1,:]) == @inferred(D[1,1,1,1:1]) == @inferred(D[1,1,1,[1]]) == AxisArray([10], Axis{:dim_4}(Base.OneTo(1)))

# Test slices

@test A == A.data
@test A[:,:,:] == A[Axis{:row}(:)] == A[Axis{:col}(:)] == A[Axis{:page}(:)] == A.data[:,:,:]
# Test UnitRange slices
@test @inferred(A[1:2,:,:]) == A.data[1:2,:,:] == @inferred(A[Axis{:row}(1:2)])  == @inferred(A[Axis{1}(1:2)]) == @inferred(A[Axis{:row}(ClosedInterval(-Inf,Inf))]) == @inferred(A[[true,true],:,:])
@test @inferred(view(A,1:2,:,:)) == A.data[1:2,:,:] == @inferred(view(A,Axis{:row}(1:2))) == @inferred(view(A,Axis{1}(1:2))) == @inferred(view(A,Axis{:row}(ClosedInterval(-Inf,Inf)))) == @inferred(view(A,[true,true],:,:))
@test @inferred(A[:,1:2,:]) == A.data[:,1:2,:] == @inferred(A[Axis{:col}(1:2)])  == @inferred(A[Axis{2}(1:2)]) == @inferred(A[Axis{:col}(ClosedInterval(0.0, .25))]) == @inferred(A[:,[true,true,false],:])
@test @view(A[:,1:2,:]) == A.data[:,1:2,:] == @view(A[Axis{:col}(1:2)])  == @view(A[Axis{2}(1:2)]) == @view(A[Axis{:col}(ClosedInterval(0.0, .25))]) == @view(A[:,[true,true,false],:])
@test A[:,:,1:2] == A.data[:,:,1:2] == A[Axis{:page}(1:2)] == A[Axis{3}(1:2)] == A[Axis{:page}(ClosedInterval(-1., .22))] == A[:,:,[true,true,false,false]]
@test @view(A[:,:,1:2]) == @view(A.data[:,:,1:2]) == @view(A[Axis{:page}(1:2)]) == @view(A[Axis{3}(1:2)]) == @view(A[Axis{:page}(ClosedInterval(-1., .22))]) == @view(A[:,:,[true,true,false,false]])
# Test scalar slices
@test A[2,:,:] == A.data[2,:,:] == A[Axis{:row}(2)]
@test A[:,2,:] == A.data[:,2,:] == A[Axis{:col}(2)]
@test A[:,:,2] == A.data[:,:,2] == A[Axis{:page}(2)]

# Test fallback methods
@test A[[1 2; 3 4]] == @view(A[[1 2; 3 4]]) == A.data[[1 2; 3 4]]
@test A[] == A.data[]

# Test axis restrictions
@test A[:,:,:].axes == A.axes

@test A[Axis{:row}(1:2)].axes[1].val == A.axes[1].val[1:2]
@test A[Axis{:row}(1:2)].axes[2:3] == A.axes[2:3]

@test A[Axis{:col}(1:2)].axes[2].val == A.axes[2].val[1:2]
@test A[Axis{:col}(1:2)].axes[[1,3]] == A.axes[[1,3]]

@test A[Axis{:page}(1:2)].axes[3].val == A.axes[3].val[1:2]
@test A[Axis{:page}(1:2)].axes[1:2] == A.axes[1:2]

# Linear indexing across multiple dimensions drops tracking of those dims
@test A[:].axes[1].val == 1:length(A)
# TODO: remove the next 4 lines when we no longer feel we need to test for this
VERSION >= v"0.6.0-dev" && info("partial linear indexing deprecation warning is expected")
B = A[1:2,:]
@test B.axes[1].val == A.axes[1].val[1:2]
@test B.axes[2].val == 1:Base.trailingsize(A,2)
B2 = reshape(A, Val{2})
B = B2[1:2,:]
@test B.axes[1].val == A.axes[1].val[1:2]
@test B.axes[2].val == 1:Base.trailingsize(A,2)

B = AxisArray(reshape(1:15, 5,3), .1:.1:0.5, [:a, :b, :c])

# Test indexing by Intervals
@test B[ClosedInterval(0.0,  0.5), :] == B[ClosedInterval(0.0,  0.5)] == B[:,:]
@test B[ClosedInterval(0.0,  0.3), :] == B[ClosedInterval(0.0,  0.3)] == B[1:3,:]
@test B[ClosedInterval(0.15, 0.3), :] == B[ClosedInterval(0.15, 0.3)] == B[2:3,:]
@test B[ClosedInterval(0.2,  0.5), :] == B[ClosedInterval(0.2,  0.5)] == B[2:end,:]
@test B[ClosedInterval(0.2,  0.6), :] == B[ClosedInterval(0.2,  0.6)] == B[2:end,:]
@test @view(B[ClosedInterval(0.0,  0.5), :]) == @view(B[ClosedInterval(0.0,  0.5)]) == B[:,:]
@test @view(B[ClosedInterval(0.0,  0.3), :]) == @view(B[ClosedInterval(0.0,  0.3)]) == B[1:3,:]
@test @view(B[ClosedInterval(0.15, 0.3), :]) == @view(B[ClosedInterval(0.15, 0.3)]) == B[2:3,:]
@test @view(B[ClosedInterval(0.2,  0.5), :]) == @view(B[ClosedInterval(0.2,  0.5)]) == B[2:end,:]
@test @view(B[ClosedInterval(0.2,  0.6), :]) == @view(B[ClosedInterval(0.2,  0.6)]) == B[2:end,:]

# Test Categorical indexing
@test B[:, :a] == @view(B[:, :a]) == B[:,1]
@test B[:, :c] == @view(B[:, :c]) == B[:,3]
@test B[:, [:a]] == @view(B[:, [:a]]) == B[:,[1]]
@test B[:, [:a,:c]] == @view(B[:, [:a,:c]]) == B[:,[1,3]]

@test B[Axis{:row}(ClosedInterval(0.15, 0.3))] == @view(B[Axis{:row}(ClosedInterval(0.15, 0.3))]) == B[2:3,:]

A = AxisArray(reshape(1:256, 4,4,4,4), Axis{:d1}(.1:.1:.4), Axis{:d2}(1//10:1//10:4//10), Axis{:d3}(["1","2","3","4"]), Axis{:d4}([:a, :b, :c, :d]))
ax1 = axes(A)[1]
@test A[Axis{:d1}(2)] == A[ax1(2)]
@test A.data[1:2,:,:,:] == A[Axis{:d1}(ClosedInterval(.1,.2))]       == A[ClosedInterval(.1,.2),:,:,:]       == A[ClosedInterval(.1,.2),:,:,:,1]       == A[ClosedInterval(.1,.2)]
@test A.data[:,1:2,:,:] == A[Axis{:d2}(ClosedInterval(1//10,2//10))] == A[:,ClosedInterval(1//10,2//10),:,:] == A[:,ClosedInterval(1//10,2//10),:,:,1] == A[:,ClosedInterval(1//10,2//10)]
@test A.data[:,:,1:2,:] == A[Axis{:d3}(["1","2"])]             == A[:,:,["1","2"],:]             == A[:,:,["1","2"],:,1]             == A[:,:,["1","2"]]
@test A.data[:,:,:,1:2] == A[Axis{:d4}([:a,:b])]               == A[:,:,:,[:a,:b]]               == A[:,:,:,[:a,:b],1]

A = AxisArray(reshape(1:32, 2, 2, 2, 2, 2), .1:.1:.2, .1:.1:.2, .1:.1:.2, [:a, :b], [:c, :d])
@test A[ClosedInterval(.15, .25), ClosedInterval(.05, .15), ClosedInterval(.15, .25), :a] == A.data[2:2, 1:1, 2:2, 1, :]
@test A[Axis{:dim_5}(2)] == A.data[:, :, :, :, 2]

# Test vectors
v = AxisArray(collect(.1:.1:10.0), .1:.1:10.0)
@test v[Colon()] == v
@test v[:] == v.data[:] == v[Axis{:row}(:)]
@test v[3:8] == v.data[3:8] == v[ClosedInterval(.25,.85)] == v[Axis{:row}(3:8)] == v[Axis{:row}(ClosedInterval(.22,.88))]

# Test repeated intervals, for different range types

# First, since integers mean "location" rather than value, we have to
# create a number type from which we build a StepRange but which is
# not an Int.
module IL  # put in a module so this file can be re-run
immutable IntLike <: Number
    val::Int
end
Base.one(x::IntLike) = IntLike(0)
Base.zero(x::IntLike) = IntLike(0)
Base.isless(x::IntLike, y::IntLike) = isless(x.val, y.val)
Base.:+(x::IntLike, y::IntLike) = IntLike(x.val+y.val)
Base.:-(x::IntLike, y::IntLike) = IntLike(x.val-y.val)
Base.:/(x::IntLike, y::IntLike) = x.val / y.val
Base.rem(x::IntLike, y::IntLike) = IntLike(rem(x.val, y.val))
Base.div(x::IntLike, y::IntLike) = div(x.val, y.val)
Base.:*(x::IntLike, y::Int) = IntLike(x.val * y)
Base.:*(x::Int, y::IntLike) = y*x
Base.:/(x::IntLike, y::Int) = IntLike(x.val / y)
Base.promote_rule(::Type{IntLike}, ::Type{Int}) = Int
Base.convert(::Type{Int}, x::IntLike) = x.val
using AxisArrays
AxisArrays.axistrait(::AbstractVector{IntLike}) = AxisArrays.Dimensional
end

for (r, Irel) in ((0.1:0.1:10.0, -0.5..0.5),  # FloatRange
                  (linspace(0.1, 10.0, 100), -0.51..0.51),  # LinSpace
                  (IL.IntLike(1):IL.IntLike(1):IL.IntLike(100),
                   IL.IntLike(-5)..IL.IntLike(5))) # StepRange
    Iabs = r[20]..r[30]
    A = AxisArray([1:100 -1:-1:-100], r, [:c1, :c2])
    @test A[Iabs, :] == A[atindex(Irel, 25), :] == [20:30 -20:-1:-30]
    @test A[Iabs, :] == A[r[25]+Irel, :] == [20:30 -20:-1:-30]
    @test A[Iabs, [:c1,:c2]] == A[atindex(Irel, 25), [:c1, :c2]] == [20:30 -20:-1:-30]
    @test A[Iabs, :c1] == A[atindex(Irel, 25), :c1] == collect(20:30)
    @test A[atindex(Irel, 25), :c1] == collect(20:30)
    @test A[atindex(Irel, [25, 35]), :c1] == [20:30 30:40]
    @test A[r[[25, 35]] + Irel,  :c1] == [20:30 30:40]
    @test_throws BoundsError A[atindex(Irel, 5), :c1]
    @test_throws BoundsError A[atindex(Irel, [5, 15, 25]), :]

    B = A[r[[25, 35]] + Irel,  :c1]
    @test B[:,:] == B[Irel, :] == [20:30 30:40]
end

# Indexing with CartesianIndex
A = AxisArray(reshape(1:15, 3, 5), :x, :y)
@test A[2,2,CartesianIndex(())] == 5
@test A[2,CartesianIndex(()),2] == 5
@test A[CartesianIndex(()),2,2] == 5
A3 = AxisArray(reshape(1:24, 4, 3, 2), :x, :y, :z)
@test A3[2,CartesianIndex(2,2)] == 18
@test A3[CartesianIndex(2,2),2] == 18
@test A3[CartesianIndex(2,2,2)] == 18

# Extracting the full axis
axx = @inferred(A[Axis{:x}])
@test isa(axx, Axis{:x})
@test axx.val == 1:3
axy = @inferred(A[Axis{:y}])
@test isa(axy, Axis{:y})
@test axy.val == 1:5
@test_throws ArgumentError A[Axis{:z}]

# Test for the expected exception type given repeated axes
A = AxisArray(rand(2,2), :x, :y)
@test_throws ArgumentError A[Axis{:x}(1), Axis{:x}(1)]
@test_throws ArgumentError A[Axis{:y}(1), Axis{:y}(1)]

# Reductions (issues #66, #62)
@test maximum(A3, 1) == reshape([4 16; 8 20; 12 24], 1, 3, 2)
@test maximum(A3, 2) == reshape([9 21; 10 22; 11 23; 12 24], 4, 1, 2)
@test maximum(A3, 3) == reshape(A3[:,:,2], 4, 3, 1)
acc = zeros(Int, 4, 1, 2)
Base.mapreducedim!(x->x>5, +, acc, A3)
@test acc == reshape([1 3; 2 3; 2 3; 2 3], 4, 1, 2)


text:
export
       Creation,
       Matrices,
       Graph,
       connect!,
       disconnect,
       remove_vertex!,
       reindex!,
       random_graph,
       target_vertex,
       cycles,
    number_of_neighbors

using LightGraphs

import LightGraphs: nv, ne, has_edge, is_directed

import Base.length
import Base.empty!
import Base.iterate
"""
```julia
type Edge
```

"""
mutable struct Edge{T}
  next_v1::Union{Nothing,Edge{T}}
  prev_v1::Union{Nothing,Edge{T}}
  next_v2::Union{Nothing,Edge{T}}
  prev_v2::Union{Nothing,Edge{T}}
  v1
  v2
  weight::T
end
function weight_type(edge::Edge{T}) where T
    return T
end
mutable struct Vertex{T, EdgeType}
   id::Integer
   data::T
   edges::Union{Nothing,Edge{EdgeType}}
   number_of_edges::Integer
   degree::Float64
   connections::Set{Integer}
   lock::Threads.SpinLock
end
function weight_type(v::Vertex{V,E}) where V where E
    return E
end
function Vertex(id::Integer,d::DataType = Any, val=nothing, weight_type::DataType=Float64)
    return Vertex{d, weight_type}(id,val,nothing,0,0, Set{Integer}(),Threads.SpinLock())
end
function Edge(v1::Vertex,v2::Vertex,w::Number)
    return Edge{weight_type(v1)}(nothing,nothing,nothing,nothing,v1,v2,convert(weight_type(v1),w))
end
struct Graph
  vertices::Vector{Vertex}
  is_dirty::Bool
end
struct EdgeIterator
   e::Union{Nothing,Edge}
   i::Integer
end
function empty!(g::Graph)
  for i=1:length(g.vertices)
    g.vertices[i].edges = nothing
    g.vertices[i].number_of_edges = 0
    g.vertices[i].degree = 0
  end
end
"""
```julia
Graph(n_vertices::Integer=0; vertex_type::DataType  = Any ,initial_value=nothing, weight_type::DataType = Float64)
```
Construct an undirected weighted grpah of `n_vertices` vertices.
"""
function Graph(n_vertices::Integer=0; vertex_type::DataType  = Any ,initial_value=nothing, weight_type::DataType = Float64)
   vertices = Vector{Vertex{vertex_type, weight_type}}(undef, n_vertices)
   for i=1:n_vertices
       vertices[i] = Vertex(i,vertex_type,initial_value, weight_type)
   end
   return Graph(vertices,false)
end

function is_directed(g::Graph)
    return false
end
"""
```julia
nv(g::Graph)
```
Return the number of vertices of `g`.
"""
function nv(g::Graph)
    return length(g.vertices)
end
function ne(g::Graph)
    return sum([v.number_of_edges for v in g.vertices])
end
function has_edge(gr::Graph, i::Integer, k::Integer)
    return (k in gr.vertices[i].connections)
end
function insert!(v::Vertex,e::Edge)
    if (e.v1 == v)
        #El siguiente del nuevo es el primero de la lista original
        e.next_v1 = v.edges
        #El anterior del primero de la lista original es ahora el nuevo
        if (v.edges != nothing)
          if (v.edges.v1 == v)
              v.edges.prev_v1 = e
         else
              v.edges.prev_v2 = e
          end
        end
        v.edges = e
    else
        e.next_v2 = v.edges
        if (v.edges != nothing)
          if (v.edges.v1 == v)
              v.edges.prev_v1 = e
          else
            v.edges.prev_v2 = e
          end
        end
        v.edges = e
    end
end

function set_previous(v::Vertex,e::Edge,prev::Union{Nothing,Edge})
    if (e.v1 == v)
        e.prev_v1=prev
    else
        e.prev_v2=prev
    end
end

function set_next(v::Vertex,e::Edge,next::Union{Nothing,Edge})
    if (e.v1 == v)
        e.next_v1=next
    else
        e.next_v2=next
    end
end
function linked_list_connect(v::Vertex,e::Edge,next::Union{Nothing,Edge})
    set_next(v,e,next)
    if (next != nothing)
        set_previous(v,next,e)
    end
end
function remove!(v::Vertex,e::Edge)
    if (e.v1 == v)
        prev = e.prev_v1
        if (prev == nothing)
           v.edges = e.next_v1
           if e.next_v1 != nothing
               set_previous(v,e.next_v1,nothing)
            end
           return
        else
           linked_list_connect(v,prev,e.next_v1)
        end
    else
        prev = e.prev_v2
        if (prev == nothing)
           v.edges = e.next_v2
           if e.next_v2 != nothing
              set_previous(v,e.next_v2,nothing)
           end
           return
        else
           linked_list_connect(v,prev,e.next_v2)
        end
    end
end
"""
```julia
function connect!(g::Graph, i::Integer, neighbors::Vector, weigths::Vector)
```
"""
function connect!(g::Graph, i::Integer, neighbors::Vector, w::Vector)
    for j=1:length(neighbors)
        connect!(g,i,neighbors[j],w[j])
    end
end

"""
```julia
connect!(g::Graph,i::Integer,j::Integer,w::Number)
```
Connect the vertex `i` with the vertex `j` with weight `w`.
"""
function connect!(g::Graph,i::Integer,j::Integer,w::Number)
    if (i==j)
        return
    end
    if i>nv(g) || j>nv(g)
      throw("Invalid vertex")
    end
    if (w<=0)
        return
    end
    vertex_j = g.vertices[j]
    vertex_i = g.vertices[i]

     if !(vertex_j.id in vertex_i.connections)
      edge = Edge(g.vertices[i],g.vertices[j],w)
      lock(vertex_i.lock)
      lock(vertex_j.lock)
      insert!(g.vertices[i],edge)
      insert!(g.vertices[j],edge)
      push!(vertex_i.connections, vertex_j.id)
      push!(vertex_j.connections, vertex_i.id)
      unlock(vertex_j.lock)
      unlock(vertex_i.lock)
      g.vertices[i].number_of_edges=g.vertices[i].number_of_edges+1
      g.vertices[j].number_of_edges=g.vertices[j].number_of_edges+1
      g.vertices[i].degree = g.vertices[i].degree + w
      g.vertices[j].degree = g.vertices[j].degree + w
    end

end

"""
```julia
target_vertex(e::Edge,v::Vertex)
```
Given an edge `e` and a vertex `v` returns the other vertex different from `v`
"""
function target_vertex(e::Edge,v::Vertex)
    if (e.v1 == v)
        return e.v2
    elseif (e.v2 == v)
        return e.v1
    else
        return Nothing
    end
end
"""
```julia
length(v::Vertex)
```
Return the number of edges connected to a given vertex.
"""
function length(v::Vertex)
    return v.number_of_edges
end
function iterate(v::Vertex)
    if v.edges == nothing
        return nothing
    else
        edge = v.edges
        next_edge = edge.v1 == v ? edge.next_v1 : edge.next_v2
        return (edge, next_edge)
    end
end

function iterate(v::Vertex, state)
    edge = state
    if edge == nothing
        return nothing
    else
        next_edge = edge.v1 == v ? edge.next_v1 : edge.next_v2
        return (edge, next_edge)
    end
end

import Base.show
function show(io::IO, e::Edge)
  println(string(e.v1.id," -(",e.weight, ")-> ",e.v2.id))
end
function show(io::IO, g::Graph)
  for vertex in g.vertices
         println(vertex)
         for e in vertex
           println(e)
       end
   end
end

function show(io::IO, v::Vertex)
    repr = "Vertex $(v.id) ("
    if v.data != nothing
      repr *= "data=$(v.data), "
    end
    repr *= "n_edges=$(v.number_of_edges), "
    repr *= "degree=$(v.degree))"
    println(repr)
end
function find_edge(p, v::Vertex)
     for e in v
         if (p(e))
           return e
         end
      end
      return nothing
end
"""
```julia
disconnect(g::Graph,i::Integer,j::Integer)
```
Removes the edge that connects the `i`-th vertex to the `j`-th vertex.
"""
function disconnect(g::Graph,i::Integer,j::Integer)
   vertex_i = g.vertices[i]
   vertex_j = g.vertices[j]
   edge = find_edge(e->(e.v1 == vertex_j || e.v2==vertex_j),g.vertices[i])
   remove!(vertex_i,edge)
   remove!(vertex_j,edge)
   delete!(vertex_i.connections, vertex_j.id)
   delete!(vertex_j.connections, vertex_i.id)
   vertex_i.degree = vertex_i.degree - edge.weight
   vertex_j.degree = vertex_j.degree - edge.weight
   g.is_dirty = true
end
function update_connections!(g::Graph)

   for i=1:nv(g)
       empty!(g.vertices[i].connections)
       for e in g.vertices[i]
            v_j = target_vertex(e, g.vertices[i])
            push!(g.vertices[i].connections, v_j.id)
       end
   end
end

function reindex!(g::Graph)
   for i=1:nv(g)
       g.vertices[i].id = i
   end
   update_connections!(g)
   g.is_dirty = false
end
"""
```julia
remove_vertex!(g::Graph,i::Integer)
```
Remove the `i`-th vertex.
"""
function remove_vertex!(g::Graph,i::Integer)
    if i>nv(g)
      throw("No se puede eliminar")
    end
    if (g.is_dirty)
      reindex!(g)
    end
    vertex_i = g.vertices[i]
    for e in vertex_i
      if e.v1 == vertex_i
            remove!(e.v2,e)
            e.v2.degree = e.v2.degree - e.weight
            e.v2.number_of_edges = e.v2.number_of_edges-1
        else
            remove!(e.v1,e)
            e.v1.number_of_edges = e.v1.number_of_edges-1
            e.v1.degree = e.v1.degree - e.weight
        end
    end
    deleteat!(g.vertices,i)
    g.is_dirty=true
end
function add_vertex!(g::Graph, datatype = Any, data=nothing)
   if g.is_dirty
      reindex!(g)
   end
   new_id = nv(g) +1
   vertex = Vertex(new_id,datatype, data)
   push!(g.vertices,vertex)
   return vertex
end
function connect(e::Edge, v::Vertex)
   return e.v1 == v || e.v2 == v
end
function number_of_neighbors(g::Graph)
    number = zeros(Int,nv(g))
    for i=1:length(g.vertices)
        n=0
        for e in g.vertices[i]
            n= n +1
        end
        number[i] = n
    end
    return number

end
"""
```
function random_graph(iterations::Integer; probs=[0.4,0.4,0.2], weight=()->5, debug=false)
```
Create a random graphs. `probs` is an array of probabilities. The function create a vertex with probability `probs[1]`, connect two vertices with probability `probs[2]` and delete a vertex with probability `probs[2]`. The weight of the edges is given by `weight`
"""
function random_graph(iterations::Integer; probs=[0.4,0.4,0.2], weight=()->5, debug=false)
  g= Graph()
  for i=1:iterations
    action = sum(rand() .>= cumsum(probs)) +1
    nog = nv(g)
    if action==1
        add_vertex!(g)
        if debug
           println("add_vertex!(g)")
        end
    elseif action == 2
        if (nog >= 2)
           v1 = rand(1:nog)
           v2 = rand(1:nog)
           if (v1!=v2)
             if (debug)
               println("connect!(g,$(v1),$(v2),5)")
             end
             connect!(g,v1,v2,weight())
           end
        end
     elseif action == 3
       if (nog > 0)
          v1 = rand(1:nog)
          if (debug)
            println("remove_vertex!(g,$(v1))")
          end
          remove_vertex!(g,v1)
        end
     end
  end
  return g
end
struct TargetVertexAndWeight
    vertex_id::Integer
    edge_weight::Float64
end
struct Triangle
    edge_1::TargetVertexAndWeight
    edge_2::TargetVertexAndWeight
end
function Triangle()
    return Triangle((-1,-1.0),(-1,-1.0))
end
import Base.hash
import Base.isequal

function hash(a::Triangle, h::UInt)
    if a.edge_1.vertex_id < a.edge_2.vertex_id
        hash(a.edge_1.vertex_id, hash(a.edge_2.vertex_id, hash(:Triangle, h)))
    else
        hash(a.edge_2.vertex_id, hash(a.edge_1.vertex_id, hash(:Triangle, h)))
    end

end
isequal(a::Triangle, b::Triangle) = Base.isequal(hash(a), hash(b))
function compute_cycles(vertice_inicio::Vertex, vertice::Vertex,
                                        visitados::Vector{Bool}, ciclos::Set{Triangle},
                                        cant_aristas::Integer, peso_aristas::TargetVertexAndWeight)
   if  !visitados[vertice.id]
     visitados[vertice.id] = true
     cant_aristas = cant_aristas+1
     for edge in vertice
          vertice_destino = target_vertex(edge, vertice)
          if cant_aristas == 1
               peso_aristas.vertex_id  = vertice_destino.id
               peso_aristas.edge_weight  = edge.weight
          end
          if vertice_destino == vertice_inicio && cant_aristas == 3

               push!(ciclos, Triangle( deepcopy(peso_aristas), TargetVertexAndWeight(vertice.id, edge.weight)))
               visitados[vertice.id]=false
               return  #Si encontre un ciclo, no voy a encontrar otro
          else
               if !visitados[vertice_destino.id]
                    if cant_aristas < 3
                         compute_cycles(vertice_inicio, vertice_destino, visitados, ciclos,
                                        cant_aristas,peso_aristas)

                    end
               end
          end
     end
     visitados[vertice.id]=false
   end

end

function cycles(g::Graph)
    visitados = fill(false,length(g.vertices))
    ciclos_vertices = []
    for i=1:length(g.vertices)
        v = g.vertices[i]
        peso_aristas = TargetVertexAndWeight(-1,-1.0)
        ciclos = Set{Triangle}()
        compute_cycles(v,v, visitados,ciclos,0,peso_aristas)
        push!(ciclos_vertices,ciclos)
    end
    return ciclos_vertices
end

import LinearAlgebra.issymmetric
import LinearAlgebra.diag
issymmetric(::SpectralClustering.Graph) = true
diag(g::SpectralClustering.Graph) = [g.vertices[i].degree for i=1:length(g.vertices)]

include("Creation.jl")
include("Matrices.jl")
include("Plot.jl")


text:
# 1. Import Dash
using Dash, DashBootstrapComponents

# 2. Create a Dash app instance
app = dash(external_stylesheets = [dbc_themes.BOOTSTRAP])

# 3. Add the example to the app's layout
# First we copy the snippet from the docs
badge = dbc_button(
    [
        "Notifications",
        dbc_badge("4", color = "light", text_color = "primary", className = "ms-1"),
    ],
    color = "primary",
)

# Then we incorporate the snippet into our layout.
# This example keeps it simple and just wraps it in a Container
app.layout = dbc_container(badge, fluid = true)

# 5. Start the Dash server
run_server(app, "0.0.0.0", 8050)

max_stars_repo_name: glsdown/dash-bootstrap-components

max_issues_repo_name: glsdown/dash-bootstrap-components

max_forks_repo_name: glsdown/dash-bootstrap-components


text:
using Literate, JuliaForBioinformatics

REPO = abspath(@__DIR__, "..")
MD_OUTPUT = joinpath(@__DIR__, "src")
NB_OUTPUT = joinpath(@__DIR__, "src", "notebooks")

for file in [ "01_Introduction.jl",
              "02_DataStructures.jl",
              "03_Files_Homework.jl" ]
    Literate.markdown(joinpath(REPO, "src", "Introduction", file),
        MD_OUTPUT, execute=false, documenter=true)
    Literate.notebook(joinpath(REPO, "src", "Introduction", file),
        NB_OUTPUT, execute=false, documenter=true)
end

for file in [ "04_HowJuliaWorks.jl",
              "05_DefiningTypes.jl",
              "06_Strings.jl",
              "07_Stats.jl",
              "08_Packages_Homework.jl" ]
    Literate.markdown(joinpath(REPO, "src", "Advance", file),
        MD_OUTPUT, execute=false, documenter=true)
    Literate.notebook(joinpath(REPO, "src", "Advance", file),
        NB_OUTPUT, execute=false, documenter=true)
end

for file in [ "09_MSA.jl",
              "10_Information.jl",
              "11_PDB.jl" ]
    Literate.markdown(joinpath(REPO, "src", "Bioinformatics", file),
        MD_OUTPUT, execute=false, documenter=true)
    Literate.notebook(joinpath(REPO, "src", "Bioinformatics", file),
        NB_OUTPUT, execute=false, documenter=true)
end

# copy some figures to the build directory
cp(joinpath(REPO, "src", "Advance", "figures", "JuliaCompiler.png"),
    joinpath(MD_OUTPUT, "JuliaCompiler.png"); force = true)
cp(joinpath(REPO, "src", "Advance", "figures", "JuliaCompiler.png"),
    joinpath(NB_OUTPUT, "JuliaCompiler.png"); force = true)

max_stars_repo_name: diegozea/JuliaForBioinformatics

max_issues_repo_name: diegozea/JuliaForBioinformatics

max_forks_repo_name: diegozea/JuliaForBioinformatics


text:
# Example adapted from Luxor.jl documentation
# https://juliagraphics.github.io/Luxor.jl/stable/polygons/#Offsetting-polygons

using Alexya

@init "Basic example" 800 600 # create a window and canvas
@layout aside(:v, 100)

t = 0

# @create macro creates and adds the widget to the window
velocity = @create Slider(1/10:1/100:1, @margin(10))

# update function is called every frame
@use function update()
    w, h = @width, @height
    background("#e1e1e1")
    origin()

    spine = [Point(20x, 15sin(x + t)) for x in -4π:pi/24:4pi]

    f(t, b, c, d) = 2sin(t * π)

    pg = offsetpoly(spine, startoffset=1, endoffset=10, easingfunction=f)
    sethue("black")
    poly(pg, :fill)

    sethue("#e1e1e1")
    poly(spine, :stroke)

    global t += value(velocity)

    if t >= 6π
        global t = 0
    end
end

start()


text:
# install PkgFix if not present
if !isdir(joinpath(Pkg.dir(), "PkgFix"))
  Pkg.clone("https://github.com/OptimalDesignLab/PkgFix.jl.git")
end
start_dir=pwd()
cd(Pkg.dir("PkgFix"))
run(`git checkout upgrade_0.6`)
cd(start_dir)

using PkgFix

#=
pkg_dict = Pkg.installed()  # get dictionary of installed package names to version numbers

if !haskey(pkg_dict, "MPI")
  Pkg.clone("https://github.com/JaredCrean2/MPI.jl.git")
  Pkg.build("MPI")
end

if !haskey(pkg_dict, "ArrayViews")
  Pkg.clone("https://github.com/JuliaLang/ArrayViews.jl.git")
  start_dir = pwd()
  cd(Pkg.dir("ArrayViews"))
  run(`git checkout 93e80390aeedb1dbcd90281b6dff7f760f430bc8`)
  cd(start_dir)
end

if !(haskey(pkg_dict, "FactCheck"))
  Pkg.clone("FactCheck")
  start_dir = pwd()
  cd(Pkg.dir("FactCheck"))
  run(`git checkout e3739d5fdf0e54bc1e74957c060c693cd8ce9cd6`)
  cd(start_dir)
  Pkg.build("FactCheck")
end
=#

global const ARRAYVIEWS_URL = "https://github.com/JaredCrean2/ArrayViews.jl.git"
global const ARRAYVIEWS_VER = "work"

pkg_dict = PkgFix.installed()

if !haskey(pkg_dict, "ArrayViews")
  PkgFix.add(ARRAYVIEWS_URL, branch_ish=ARRAYVIEWS_VER)
else
  PkgFix.checkout("ArrayViews", ARRAYVIEWS_VER)
end

if !haskey(ENV, "PETSC_DIR")  && !haskey(ENV, "PETSC_ARCH")
 run(`./install_petsc.sh`)
end


text:
using JuMP
using GLPK,GLPKMathProgInterface

using Cbc
using CPLEX

include("parser.jl")

# model = Model(solver=GLPKSolverMIP())
# model = Model(solver=CbcSolver())
model = Model(solver=CplexSolver())

sommeL = sum(inst.rect[i][1] for i in 1:inst.nb)*2
sommeH = sum(inst.rect[i][2] for i in 1:inst.nb)*2

##############################################################
####################### Variables ############################
##############################################################

# x[i,j] = rectangle i, coordonnée j (1 ou 2)

@variable(model, x[i in 1:inst.nb, j in 1:2] >= 0)

# ox : à gauche ou à droite d'un autre rectangle
# ox = 0 : à gauche
# oy : en haut ou en bas d'un autre rectangle
# oy = 0 : en haut
@variable(model, ox[i in 1:inst.nb, j in (i+1):inst.nb], Bin)
@variable(model, oy[i in 1:inst.nb, j in (i+1):inst.nb], Bin)

# largeur et hauteur max
@variable(model, lmax >= 0)
@variable(model, hmax >= 0)

##############################################################
####################### Contraintes ##########################
##############################################################

# les rectangles ne se chevauchent pas

for i in 1:inst.nb
    for j in i+1:inst.nb

        # en abscisse
        @constraint(model, x[i,1] <= x[j,1] - inst.rect[i][1] + (1-ox[i,j])*sommeL)
        @constraint(model, x[i,1] >= x[j,1] + inst.rect[j][1] - ox[i,j]*sommeL)

        # en ordonnée
        @constraint(model, x[i,2] <= x[j,2] - inst.rect[i][2] + (1-oy[i,j])*sommeH)
        @constraint(model, x[i,2] >= x[j,2] + inst.rect[j][2] - oy[i,j]*sommeH)

    end
end

# cadre à minimiser

@constraint(model, [i in 1:inst.nb], lmax >= x[i,1]+inst.rect[i][1])
@constraint(model, [i in 1:inst.nb], hmax >= x[i,2]+inst.rect[i][2])

##############################################################
##################### Fonction objectif ######################
##############################################################

@objective(model, Min, hmax+lmax)

@time solve(model)

X = getvalue(x)


text:
abstract type DelayDiffEqAlgorithm <: AbstractDDEAlgorithm end
abstract type AbstractMethodOfStepsAlgorithm{constrained} <: DelayDiffEqAlgorithm end

struct MethodOfSteps{algType,F,constrained} <: AbstractMethodOfStepsAlgorithm{constrained}
  alg::algType
  fpsolve::F
end

"""
    MethodOfSteps(alg; constrained = false, fpsolve = NLFunctional())

Construct an algorithm that solves delay differential equations by the method of steps,
where `alg` is an ODE algorithm from OrdinaryDiffEq.jl upon which the calculation of
steps is based.

If the algorithm is `constrained` only steps of size at most the minimal delay will be
taken. If it is unconstrained, fixed-point iteration `fpsolve` is applied for step sizes
that exceed the minimal delay.
"""
MethodOfSteps(alg; constrained = false, fpsolve = NLFunctional()) =
  MethodOfSteps{typeof(alg),typeof(fpsolve),constrained}(alg, fpsolve)


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

mutable struct EffectiveRoute <: SwaggerModel
    name::Any # spec type: Union{ Nothing, String } # spec name: name
    disableBgpRoutePropagation::Any # spec type: Union{ Nothing, Bool } # spec name: disableBgpRoutePropagation
    source::Any # spec type: Union{ Nothing, String } # spec name: source
    state::Any # spec type: Union{ Nothing, String } # spec name: state
    addressPrefix::Any # spec type: Union{ Nothing, Vector{String} } # spec name: addressPrefix
    nextHopIpAddress::Any # spec type: Union{ Nothing, Vector{String} } # spec name: nextHopIpAddress
    nextHopType::Any # spec type: Union{ Nothing, RouteNextHopType } # spec name: nextHopType

    function EffectiveRoute(;name=nothing, disableBgpRoutePropagation=nothing, source=nothing, state=nothing, addressPrefix=nothing, nextHopIpAddress=nothing, nextHopType=nothing)
        o = new()
        validate_property(EffectiveRoute, Symbol("name"), name)
        setfield!(o, Symbol("name"), name)
        validate_property(EffectiveRoute, Symbol("disableBgpRoutePropagation"), disableBgpRoutePropagation)
        setfield!(o, Symbol("disableBgpRoutePropagation"), disableBgpRoutePropagation)
        validate_property(EffectiveRoute, Symbol("source"), source)
        setfield!(o, Symbol("source"), source)
        validate_property(EffectiveRoute, Symbol("state"), state)
        setfield!(o, Symbol("state"), state)
        validate_property(EffectiveRoute, Symbol("addressPrefix"), addressPrefix)
        setfield!(o, Symbol("addressPrefix"), addressPrefix)
        validate_property(EffectiveRoute, Symbol("nextHopIpAddress"), nextHopIpAddress)
        setfield!(o, Symbol("nextHopIpAddress"), nextHopIpAddress)
        validate_property(EffectiveRoute, Symbol("nextHopType"), nextHopType)
        setfield!(o, Symbol("nextHopType"), nextHopType)
        o
    end
end # type EffectiveRoute

const _property_map_EffectiveRoute = Dict{Symbol,Symbol}(Symbol("name")=>Symbol("name"), Symbol("disableBgpRoutePropagation")=>Symbol("disableBgpRoutePropagation"), Symbol("source")=>Symbol("source"), Symbol("state")=>Symbol("state"), Symbol("addressPrefix")=>Symbol("addressPrefix"), Symbol("nextHopIpAddress")=>Symbol("nextHopIpAddress"), Symbol("nextHopType")=>Symbol("nextHopType"))
const _property_types_EffectiveRoute = Dict{Symbol,String}(Symbol("name")=>"String", Symbol("disableBgpRoutePropagation")=>"Bool", Symbol("source")=>"String", Symbol("state")=>"String", Symbol("addressPrefix")=>"Vector{String}", Symbol("nextHopIpAddress")=>"Vector{String}", Symbol("nextHopType")=>"RouteNextHopType")
Base.propertynames(::Type{ EffectiveRoute }) = collect(keys(_property_map_EffectiveRoute))
Swagger.property_type(::Type{ EffectiveRoute }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_EffectiveRoute[name]))}
Swagger.field_name(::Type{ EffectiveRoute }, property_name::Symbol) =  _property_map_EffectiveRoute[property_name]

const _allowed_EffectiveRoute_source = ["Unknown", "User", "VirtualNetworkGateway", "Default"]

const _allowed_EffectiveRoute_state = ["Active", "Invalid"]

function check_required(o::EffectiveRoute)
    true
end

function validate_property(::Type{ EffectiveRoute }, name::Symbol, val)
    if name === Symbol("source")
        Swagger.validate_param(name, "EffectiveRoute", :enum, val, _allowed_EffectiveRoute_source)
    end
    if name === Symbol("state")
        Swagger.validate_param(name, "EffectiveRoute", :enum, val, _allowed_EffectiveRoute_state)
    end
end


text:
module ForexUnits
using HTTP, JSON
using Unitful

function request(url)
    try
        response = HTTP.get(url)
        return String(response.body)
    catch e
        return "E: $e"
    end
end

@dimension ¤ "¤" Currency
@refunit EUR "EUR" Euro ¤ true

rates = (JSON.parse ∘ request)("https://api.exchangeratesapi.io/latest")["rates"]

for rate ∈ rates
    curr = :(@unit $(rate[1]) $(rate[1]) $(rate[1]) (1/$(rate[2]))*EUR false)
    eval(curr)
end

end

using Unitful

Unitful.register(ForexUnits)


text:
# Make sure we're running from the examples directory.
cd(joinpath(@__DIR__(), ".."))

using Eratosthenes # Bring in the top-level sim environment.
using Plots # For plotting (Pkg.add("Plots"); Pkg.add("PyPlot");)
import HDF5 # For loading the log file (Pkg.add("HDF5");)
import Juno # For the progress bar

# Create a Juno waitbar. This do-block syntax makes sure it gets "closed" even
# if there's an error.
scenario = Juno.progress(name="Simulating...") do progress_bar

    # Run the simulation. Anything inside this do-block will be run at the
    # beginning of every major time step. This is useful for updating a progress
    # bar or a plot.
    scenario = simulate("scenarios/min-scenario.yaml") do fraction
        Juno.progress(progress_bar, fraction) # Update Juno's progress bar.
        return true # Return false to end the sim.
    end

end

# Open the logs and plot some things.
if !isempty(scenario.sim.log_file)

    # Read some data from the logs. This do block takes care of
    # error-handling, so we can just read whatever we want and return it.
    t, q_BI, ω_BI_B = HDF5.h5open(scenario.sim.log_file, "r") do logs
        (read(logs, "/cube1/truth/time"),
         read(logs, "/cube1/truth/data/q_BI"),
         read(logs, "/cube1/truth/data/ω_BI_B"))
    end

    # Scalars are logged as 1-by-n (don't know why). Convert to just n for
    # the sake of plotting.
    t = dropdims(t, dims=1)

    # Choose a friendly plotting package. PyPlot behaves nicely.
    pyplot()

    # Define each plot that we'll need.
    p1 = plot(t, transpose(q_BI),
              label  = ["q1" "q2" "q3" "q4"],
              ylabel = "Attitude Quaternion")
    p2 = plot(t, 180/π * transpose(ω_BI_B),
              label  = ["ω1" "ω2" "ω3"],
              ylabel = "Rotation Rate (deg/s)")

    # Save the individual plots before showing them together.
    savefig(p1, "out/sim-results-q.png")
    savefig(p2, "out/sim-results-ω.png")

    # Display those plots as subplots using the default "2" layout. Put any
    # common descriptors here.
    display(plot(p1, p2,
                 layout = 2,
                 xlabel = "Time (s)"))

end # plotting


text:
################################################################################
#
#  Top level functions
#
################################################################################

@doc Markdown.doc"""
    multiplicative_group(Q::AlgAssAbsOrdQuoRing)
      -> GrpAbFinGen, GrpAbFinGenToAbsOrdMap
    unit_group(Q::AlgAssAbsOrdQuoRing) -> GrpAbFinGen, GrpAbFinGenToAbsOrdMap

Returns the group $Q^\times$ and the injection $Q^\times -> Q$.
"""
function multiplicative_group(Q::AlgAssAbsOrdQuoRing{S, T}) where {S, T}
  if !isdefined(Q, :multiplicative_group)
    O = base_ring(Q)
    OO = maximal_order(algebra(O))
    if O == OO
      G, GtoQ = _multgrp(Q)
    else
      G, GtoQ = _multgrp_non_maximal(Q)
    end
    Q.multiplicative_group = GtoQ
  end
  mQ = Q.multiplicative_group::GrpAbFinGenToAbsOrdQuoRingMultMap{typeof(base_ring(Q)), ideal_type(base_ring(Q)), elem_type(base_ring(Q))}
  return domain(mQ), mQ
end

unit_group(Q::AlgAssAbsOrdQuoRing) = multiplicative_group(Q)

function _multgrp_non_maximal(Q::AbsOrdQuoRing{U, T}) where {U, T}
  O = base_ring(Q)
  a = ideal(Q)
  A = algebra(O)
  OO = maximal_order(A)

  aOO = a*OO

  fac_of_aOO = factor(aOO)
  prime_ideals = Dict{ideal_type(O), Vector{ideal_type(OO)}}()
  for (p, e) in fac_of_aOO
    q = contract(p, O)
    if haskey(prime_ideals, q)
      push!(prime_ideals[q], p)
    else
      prime_ideals[q] = ideal_type(OO)[ p ]
    end
  end

  # keys are the same as in prime_ideals
  primary_ideals = Dict{ideal_type(O), ideal_type(O)}()
  for p in keys(prime_ideals)
    primes_above = prime_ideals[p]
    q = primes_above[1]^fac_of_aOO[primes_above[1]]
    for i = 2:length(primes_above)
      q = intersect(q, primes_above[i]^fac_of_aOO[primes_above[i]])
    end
    primary_ideals[p] = contract(q, O)
  end

  groups = Vector{GrpAbFinGen}()
  maps = Vector{GrpAbFinGenToAbsOrdQuoRingMultMap{U, T, elem_type(OO)}}()
  ideals = Vector{ideal_type(O)}() # values of primary_ideals, but in the "right" order
  for (p, q) in primary_ideals
    G, GtoQ = _multgrp_mod_q(p, q, prime_ideals[p][1])
    push!(groups, G)
    push!(maps, GtoQ)
    push!(ideals, q)
  end

  G, GtoQ = _direct_product(groups, maps, ideals, Q)
  S, StoG, StoQ = snf(G, GtoQ)
  return S, StoQ
end

function _multgrp(Q::AbsOrdQuoRing{U, T}) where {U, T}
  O = base_ring(Q)
  OtoQ = AbsOrdQuoMap(O, Q)
  a = ideal(Q)
  A = algebra(O)
  fields_and_maps = as_number_fields(A)
  groups = Vector{Tuple{GrpAbFinGen, GrpAbFinGenToAbsOrdQuoRingMultMap{NfOrd, NfOrdIdl, NfOrdElem}}}()
  for i = 1:length(fields_and_maps)
    K, AtoK = fields_and_maps[i]
    ai = _as_ideal_of_number_field(a, AtoK)
    push!(groups, multiplicative_group(quo(maximal_order(K), ai)[1]))
  end

  G = groups[1][1]
  for i = 2:length(groups)
    G = direct_product(G, groups[i][1]; task = :none)::GrpAbFinGen
  end
  S, StoG = snf(G)

  generators = Vector{elem_type(Q)}()
  for i = 1:ngens(S)
    x = StoG(S[i])
    y = zero(Q)
    offset = 1
    for j = 1:length(groups)
      H, HtoQK = groups[j]
      n = ngens(H)
      if iszero(n)
        continue
      end

      s = H([ x.coeff[1, k] for k = offset:(offset + n - 1) ])
      K, AtoK = fields_and_maps[j]
      QK = codomain(HtoQK)
      OK = base_ring(QK)
      OKtoQK = NfOrdQuoMap(OK, QK)
      t = K(OKtoQK\(HtoQK(s)))
      y += OtoQ(O(AtoK\t))
      offset += n
    end
    push!(generators, y)
  end

  local disc_log
  let fields_and_maps = fields_and_maps, groups = groups, OtoQ = OtoQ, StoG = StoG, G = G, S = S
    function disc_log(x::AbsOrdQuoRingElem)
      y = zero_matrix(FlintZZ, 1, 0)
      for i = 1:length(groups)
        K, AtoK = fields_and_maps[i]
        H, HtoQK = groups[i]
        QK = codomain(HtoQK)
        OK = base_ring(QK)
        h = HtoQK\(QK(OK(AtoK(elem_in_algebra(OtoQ\x, copy = false)))))
        y = hcat(y, h.coeff)
      end
      s = StoG\G(y)
      return fmpz[ s.coeff[1, i] for i = 1:ngens(S) ]
    end
  end

  return S, GrpAbFinGenToAbsOrdQuoRingMultMap(S, Q, generators, disc_log)
end

################################################################################
#
#  Order modulo primary ideal
#
################################################################################

# p should be a prime ideal in a non-maximal order, q a p-primary ideal and
# P a prime ideal above p in the maximal order
function _multgrp_mod_q(p::AlgAssAbsOrdIdl, q::AlgAssAbsOrdIdl, P::AlgAssAbsOrdIdl)

  Q, OtoQ = quo(order(q), q)
  G1, G1toO = _multgrp_mod_p(p, P)

  if p == q
    function disc_log1(x::AbsOrdQuoRingElem)
      return G1toO.discrete_logarithm(OtoQ\x)
    end
    GtoQ = GrpAbFinGenToAbsOrdQuoRingMultMap(G1, Q, map(OtoQ, G1toO.generators), disc_log1)
    return G1, GtoQ
  end

  G2, G2toO = _1_plus_p_mod_1_plus_q(p, q)

  if ngens(G1) == 0
    function disc_log2(x::AbsOrdQuoRingElem)
      return G2toO.discrete_logarithm(OtoQ\x)
    end
    GtoQ = GrpAbFinGenToAbsOrdQuoRingMultMap(G2, Q, map(OtoQ, G2toO.generators), disc_log2)
    return G2, GtoQ
  end

  gen1 = G1toO(G1[1])
  @assert is_snf(G1) && is_snf(G2)
  rel1 = G1.snf[1]
  gen1_obcs = powermod(gen1, G2.snf[end], q)
  gens = map(OtoQ, [ gen1_obcs ; G2toO.generators ])
  G1toO.generators[1] = gen1_obcs

  G = direct_product(G1, G2)[1]

  obcs_inv = gcdx(G2.snf[end], rel1)[2]
  function disc_log(x::AbsOrdQuoRingElem)
    y = OtoQ\x
    r = mod((G1toO.discrete_logarithm(y))[1]*obcs_inv, rel1)
    y *= gen1_obcs^mod(-r, rel1)
    return append!([ r ], G2toO.discrete_logarithm(y))
  end

  GtoQ = GrpAbFinGenToAbsOrdQuoRingMultMap(G, Q, gens, disc_log)
  S, StoG, StoQ = snf(G, GtoQ)
  return S, StoQ
end

################################################################################
#
#  Order modulo prime ideal
#
################################################################################

# p should be a prime ideal in a non-maximal order and P a prime ideal above
# p in the maximal order
function _multgrp_mod_p(p::AlgAssAbsOrdIdl, P::AlgAssAbsOrdIdl)
  O = order(p)
  OA = order(P) # the maximal order

  q = norm(p, O)
  @assert isone(denominator(q))
  q = numerator(q)
  q = q - 1 # the cardinality of (O/p)^\times
  if isone(q)
    G = GrpAbFinGen(fmpz[])
    function disc_log2(x::AlgAssAbsOrdElem)
      return fmpz[]
    end
    GtoO = GrpAbFinGenToAbsOrdMap(G, O, elem_type(O)[], disc_log2, p)
    return G, GtoO
  end

  OAP, OAtoOAP = quo(OA, P)
  G, GtoOAP = _multgrp(OAP)
  qq = order(G)
  @assert ngens(G) <= 1

  a = O()
  g = G[1]
  if qq == q
    # Maybe we are lucky and don't need to search for another generator
    aa = OAtoOAP\GtoOAP(G[1])
    x = _check_elem_in_order(elem_in_algebra(aa, copy = false), O, Val{true})
    if x
      a = O(aa, false)
    end
  end

  # Search for a generator of (O/p)^times.
  # See Bley, Endres "Picard Groups and Refined Discrete Logarithms".
  if iszero(a)
    b, r = divides(qq, q)
    @assert b

    while true
      a = rand(O, q)
      if a in p
        continue
      end

      aa = OAtoOAP(OA(a))
      g = GtoOAP\aa
      n = g.coeff[1]
      if gcd(n, qq) == r
        break
      end
    end
  end

  if qq == q
    function disc_log3(x::AlgAssAbsOrdElem)
      xx = OAtoOAP(OA(x))
      return GtoOAP.discrete_logarithm(xx)
    end
    return G, GrpAbFinGenToAbsOrdMap(G, O, [ a ], disc_log3, p)
  end

  H, HtoG = sub(G, [ g ])
  S, StoH = snf(H)

  function disc_log(x::AlgAssAbsOrdElem)
    xx = OAtoOAP(OA(x))
    g = GtoOAP\xx
    b, h = haspreimage(HtoG, g)
    @assert b
    b, s = haspreimage(StoH, h)
    @assert b
    return [ s.coeff[1, i] for i = 1:ngens(S) ]
  end

  return S, GrpAbFinGenToAbsOrdMap(S, O, [ a ], disc_log, p)
end

################################################################################
#
#  Computation of (1 + p)/(1 + q)
#
################################################################################

# Much of this is taken from the implementation in NfOrd/ResidueRingMultGrp.jl

# Computes (1 + p)/(1 + q) where q is a p-primary ideal (in a non-maximal order)
function _1_plus_p_mod_1_plus_q(p::AlgAssAbsOrdIdl, q::AlgAssAbsOrdIdl)
  @assert q != p

  O = order(p)
  g = Vector{elem_type(O)}()
  M = zero_matrix(FlintZZ, 0, 0)
  dlogs = Vector{Function}()

  l = 1
  pl = p
  plq = pl + q
  while plq != q
    k = l
    pk, pkq = pl, plq
    l = 2*k
    pl = pl^2
    plq = pl + q

    h, N, disc_log = _1_plus_pu_plus_q_mod_1_plus_pv_plus_q(pkq, plq)
    g, M = _expand(g, M, h, N, disc_log, q)
    push!(dlogs, disc_log)
  end

  Q, OtoQ = quo(order(q), q)
  # Cohen "Advanced Topics in Computational Number Theory" Algorithm 4.2.16
  function disc_log(b::AlgAssAbsOrdElem)
    b = OtoQ(b)
    a = fmpz[]
    gQ = map(OtoQ, g)
    k = 1
    for i in 1:length(dlogs)
      aa = dlogs[i](OtoQ\b)
      prod = one(Q)
      for j in 1:length(aa)
        prod = prod*gQ[k]^aa[j]
        k += 1
      end
      a = fmpz[ a ; aa ]
      b = divexact(b, prod)
    end
    return a
  end

  toO = GrpAbFinGenToAbsOrdMap(O, g, M, disc_log, q)
  S, mS, StoO = snf(toO, OtoQ)
  return S, StoO
end

function _1_plus_p_mod_1_plus_q_generators(p::AlgAssAbsOrdIdl, q::AlgAssAbsOrdIdl)
  @assert p != q

  O = order(p)
  g = Vector{elem_type(O)}()

  l = 1
  pl = p
  plq = pl + q
  while plq != q
    k = l
    pk, pkq = pl, plq
    l = 2*k
    pl = pl^2
    plq = pl + q
    append!(g, _1_plus_pu_plus_q_mod_1_plus_pv_plus_q(pkq, plq, Val{true}))
  end

  return g
end

# Given the groups (1 + p)/(1 + p^k + q) (via g and M) and
# (1 + p^k + q)/(1 + p^(2*k) + q) (via h and N) and a discrete logarithm in the
# second group this function computes the group (1 + p)/(1 + p^(2*k) + q).
function _expand(g::Vector{T}, M::fmpz_mat, h::Vector{T}, N::fmpz_mat, disc_log::Function, q::AlgAssAbsOrdIdl) where { T <: AlgAssAbsOrdElem }
  isempty(g) && return h, N
  isempty(h) && return g, M

  @assert is_snf(N)
  O = order(q)
  Z = zero_matrix(FlintZZ, nrows(M) + nrows(N), ncols(M) + ncols(N))
  for i = 1:nrows(M)
    for j = 1:ncols(M)
      Z[i, j] = M[i, j]
    end
  end
  for i = 1:nrows(N)
    Z[i + nrows(M), i + nrows(M)] = N[i, i]
  end
  for i = 1:nrows(M)
    el = one(O)
    for j = 1:ncols(M)
      el = mod(el*powermod(g[j], M[i, j], q), q)
    end
    alpha = disc_log(el)
    for j in 1:ncols(N)
      Z[i, j + ncols(M)] = -alpha[j]
    end
  end

  append!(g, h)
  return g, Z
end

# Compute the group (1 + puq)/(1 + pvq), where it should hold puq = p^u + q and
# pvq = p^v + q with v <= 2*u.
# Cohen "Advanced Topics in Computational Number Theory" Algorithm 4.2.15.
function _1_plus_pu_plus_q_mod_1_plus_pv_plus_q(puq::AlgAssAbsOrdIdl, pvq::AlgAssAbsOrdIdl, only_generators::Type{Val{T}} = Val{false}) where T
  O = order(puq)
  b = [ O(x) for x in basis(puq, copy = false) ]

  # Compute (p^u + q)/(p^v + q)
  N = basis_matrix(pvq, copy = false)*basis_mat_inv(puq, copy = false)
  @assert denominator(N, copy = false) == 1
  G = abelian_group(numerator(N, copy = false))
  S, StoG = snf(G)

  gens = Vector{elem_type(O)}(undef, ngens(S))
  for i = 1:ngens(S)
    x = StoG(S[i])
    gens[i] = O()
    for j = 1:ngens(G)
      gens[i] += mod(x[j], S.snf[end])*b[j]
    end
  end

  # We want generators of (1 + p^u + q)/(1 + p^v + q)
  map!(x -> x + one(O), gens, gens)

  if only_generators == Val{true}
    return gens
  end

  # The first part of Algorithm 4.2.16 in Cohen "Advanced Topics..."
  M = basis_matrix(O, copy = false)*basis_mat_inv(puq, copy = false)*StoG.imap
  y_fakemat2 = FakeFmpqMat(zero_matrix(FlintZZ, 1, ncols(M)), fmpz(1))
  function disc_log(x::AlgAssAbsOrdElem)
    y = mod(x - one(O), pvq)
    y_fakemat = FakeFmpqMat(matrix(FlintZZ, 1, degree(O), coordinates(y)), fmpz(1))
    mul!(y_fakemat2, y_fakemat, M)
    #@assert y_fakemat2 == y_fakemat * M
    denominator(y_fakemat2) != 1 && error("Element is in the ideal")
    return vec(Array(numerator(y_fakemat2)))
  end

  return gens, rels(S), disc_log
end


text:
if VERSION ≥ v"1.4"
    function frule((_, ẋ, ṗ), ::typeof(evalpoly), x, p)
        Δx, Δp = ẋ, unthunk(ṗ)
        N = length(p)
        @inbounds y = p[N]
        Δy = Δp[N]
        @inbounds for i in (N - 1):-1:1
            Δy = muladd(Δx, y, muladd(x, Δy, Δp[i]))
            y = muladd(x, y, p[i])
        end
        return y, Δy
    end

    function rrule(::typeof(evalpoly), x, p)
        y, ys = _evalpoly_intermediates(x, p)
        project_x = ProjectTo(x)
        project_p = p isa Tuple ? identity : ProjectTo(p)
        function evalpoly_pullback(Δy)
            ∂x, ∂p = _evalpoly_back(x, p, ys, Δy)
            return NoTangent(), project_x(∂x), project_p(∂p)
        end
        return y, evalpoly_pullback
    end

    function rrule(::typeof(evalpoly), x, p::Vector{<:Matrix}) # does not type infer with ProjectTo
        y, ys = _evalpoly_intermediates(x, p)
        function evalpoly_pullback(Δy)
            ∂x, ∂p = _evalpoly_back(x, p, ys, Δy)
            return NoTangent(), ∂x, ∂p
        end
        return y, evalpoly_pullback
    end

    # evalpoly but storing intermediates
    function _evalpoly_intermediates(x, p::Tuple)
        return if @generated
            N = length(p.parameters)
            exs = []
            vars = []
            ex = :(p[$N])
            for i in 1:(N - 1)
                yi = Symbol("y", i)
                push!(vars, yi)
                push!(exs, :($yi = $ex))
                ex = :(muladd(x, $yi, p[$(N - i)]))
            end
            push!(exs, :(y = $ex))
            Expr(:block, exs..., :(y, ($(vars...),)))
        else
            _evalpoly_intermediates_fallback(x, p)
        end
    end
    function _evalpoly_intermediates_fallback(x, p::Tuple)
        N = length(p)
        y = p[N]
        ys = (y, ntuple(N - 2) do i
            return y = muladd(x, y, p[N - i])
        end...)
        y = muladd(x, y, p[1])
        return y, ys
    end
    function _evalpoly_intermediates(x, p)
        N = length(p)
        @inbounds yn = one(x) * p[N]
        ys = similar(p, typeof(yn), N - 1)
        @inbounds ys[1] = yn
        @inbounds for i in 2:(N - 1)
            ys[i] = muladd(x, ys[i - 1], p[N - i + 1])
        end
        @inbounds y = muladd(x, ys[N - 1], p[1])
        return y, ys
    end

    # TODO: Handle following cases
    #     1) x is a UniformScaling, pᵢ is a matrix
    #     2) x is a matrix, pᵢ is a UniformScaling
    @inline _evalpoly_backx(x, yi, ∂yi) = ∂yi * yi'
    @inline _evalpoly_backx(x, yi, ∂x, ∂yi) = muladd(∂yi, yi', ∂x)
    @inline _evalpoly_backx(x::Number, yi, ∂yi) = conj(dot(∂yi, yi))
    @inline _evalpoly_backx(x::Number, yi, ∂x, ∂yi) = _evalpoly_backx(x, yi, ∂yi) + ∂x

    @inline _evalpoly_backp(pi, ∂yi) = ∂yi

    function _evalpoly_back(x, p::Tuple, ys, Δy)
        return if @generated
            exs = []
            vars = []
            N = length(p.parameters)
            for i in 2:(N - 1)
                ∂pi = Symbol("∂p", i)
                push!(vars, ∂pi)
                push!(exs, :(∂x = _evalpoly_backx(x, ys[$(N - i)], ∂x, ∂yi)))
                push!(exs, :($∂pi = _evalpoly_backp(p[$i], ∂yi)))
                push!(exs, :(∂yi = x′ * ∂yi))
            end
            push!(vars, :(_evalpoly_backp(p[$N], ∂yi))) # ∂pN
            Expr(
                :block,
                :(x′ = x'),
                :(∂yi = Δy),
                :(∂p1 = _evalpoly_backp(p[1], ∂yi)),
                :(∂x = _evalpoly_backx(x, ys[$(N - 1)], ∂yi)),
                :(∂yi = x′ * ∂yi),
                exs...,
                :(∂p = (∂p1, $(vars...))),
                :(∂x, Tangent{typeof(p),typeof(∂p)}(∂p)),
            )
        else
            _evalpoly_back_fallback(x, p, ys, Δy)
        end
    end
    function _evalpoly_back_fallback(x, p::Tuple, ys, Δy)
        x′ = x'
        ∂yi = unthunk(Δy)
        N = length(p)
        ∂p1 = _evalpoly_backp(p[1], ∂yi)
        ∂x = _evalpoly_backx(x, ys[N - 1], ∂yi)
        ∂yi = x′ * ∂yi
        ∂p = (
            ∂p1,
            ntuple(N - 2) do i
                ∂x = _evalpoly_backx(x, ys[N - i - 1], ∂x, ∂yi)
                ∂pi = _evalpoly_backp(p[i + 1], ∂yi)
                ∂yi = x′ * ∂yi
                return ∂pi
            end...,
            _evalpoly_backp(p[N], ∂yi), # ∂pN
        )
        return ∂x, Tangent{typeof(p),typeof(∂p)}(∂p)
    end
    function _evalpoly_back(x, p, ys, Δy)
        x′ = x'
        ∂yi = one(x′) * Δy
        N = length(p)
        @inbounds ∂p1 = _evalpoly_backp(p[1], ∂yi)
        ∂p = similar(p, typeof(∂p1))
        @inbounds begin
            ∂x = _evalpoly_backx(x, ys[N - 1], ∂yi)
            ∂yi = x′ * ∂yi
            ∂p[1] = ∂p1
            for i in 2:(N - 1)
                ∂x = _evalpoly_backx(x, ys[N - i], ∂x, ∂yi)
                ∂p[i] = _evalpoly_backp(p[i], ∂yi)
                ∂yi = x′ * ∂yi
            end
            ∂p[N] = _evalpoly_backp(p[N], ∂yi)
        end
        return ∂x, ∂p
    end
end


text:
## PART 4
#  Find the integrated autocorrelation times

include("autocorrelation.jl");

println("\nPart 4");
println("\n\tPick ncut = 200 and calculate autocorrelation times");

# Based on result of part 3
ncut = 150;

tau = τ(M, v, ncut);

println("\n\tAutocorrelation times:\n");
for i in [1:5]
  println("\t\tτ̂v$i:\t$(tau[i])");
end


text:
module EGraphs

include("../docstrings.jl")

using RuntimeGeneratedFunctions
RuntimeGeneratedFunctions.init(@__MODULE__)

# import ..Rule
# import ..getrhsfun

using ..TermInterface
using ..Util
using ..Rules
import ..@log

include("enode.jl")
export ENode

include("abstractanalysis.jl")
export AbstractAnalysis

include("eclass.jl")
export EClass
export hasdata
export getdata
export setdata!

include("intdisjointmap.jl")
export IntDisjointSet
export in_same_set

include("egraph.jl")
export find
export geteclass
export arity
export EGraph
export merge!
export in_same_class
export addexpr!
export rebuild!

include("analysis.jl")
export analyze!

# include("substitution.jl")
# export instantiate
# export instantiateterm

include("subst.jl")
export Sub

# include("ematch.jl")
include("ematch.jl")
include("Schedulers/Schedulers.jl")
export Schedulers
using .Schedulers

include("saturation/goal.jl")
export SaturationGoal
export EqualityGoal
export reached
include("saturation/reason.jl")
export ReportReasons
include("saturation/report.jl")
include("saturation/params.jl")
export SaturationParams
include("saturation/search.jl")
include("saturation/apply.jl")
include("saturation/saturation.jl")
export saturate!

include("equality.jl")
export areequal
export @areequal
export @areequalg

include("extraction.jl")
export extract!
export ExtractionAnalysis
export astsize
export astsize_inv
export @extract

end


text:
```Write a function that rotates a list by k elements. For example [1,2,3,4,5,6]
rotated by two becomes [3,4,5,6,1,2]. Try solving this without creating a copy of
 the list. How many swap or move operations do you need?```

using BenchmarkTools

list = 1:10

function rotate_list(x::Vector{Int64},y::Int64)
    x[[y:end; 1:y]]
end

@benchmark circshift(list, 3)
@benchmark rotate_list(list, 3)

max_stars_repo_name: atott/Simple-Programming-Problems-Julia

max_issues_repo_name: atott/Simple-Programming-Problems-Julia

max_forks_repo_name: atott/Simple-Programming-Problems-Julia


text:
using RedPitayaDAQServer
using PyPlot

# obtain the URL of the RedPitaya
include("config.jl")

rp = RedPitayaCluster([URLs[1]])

dec = 32
modulus = 12500
base_frequency = 125000000
samples_per_period = div(modulus, dec)
periods_per_frame = 10
N = samples_per_period * periods_per_frame

decimation(rp, dec)
samplesPerPeriod(rp, samples_per_period)
periodsPerFrame(rp, periods_per_frame)

modeDAC(rp, "STANDARD")

frequencyDAC(rp,1,1, base_frequency / modulus)

amplitudeDAC(rp, 1, 1, 0.5)
offsetDAC(master(rp), 1, 0.1)

phaseDAC(rp, 1, 1, 0.0 )

ramWriterMode(rp, "TRIGGERED")
triggerMode(rp, "INTERNAL")

signals = zeros(4*N)

jumpSharpnessDAC(rp, 1, 0.01) # controls the sharpness of the jump for the square

figure(1)
clf()

color = ["g", "b", "orange", "k"]
for (i,name) in enumerate(["SINE", "SQUARE", "TRIANGLE", "SAWTOOTH"])
  signalTypeDAC(rp, 1 , name)
  masterTrigger(rp, false)
  startADC(rp)
  masterTrigger(rp, true)
  fr = 1
  uFirstPeriod = readData(rp, fr, 1) # read 2nd frame
  subplot(2,2,i)

  plot(vec(uFirstPeriod[:,1,:,:]),color[i])
  title(name)
end
subplots_adjust(left=0.08, bottom=0.05, right=0.98, top=0.95, wspace=0.3, hspace=0.35)
savefig("images/waveforms.png")

max_stars_repo_name: tknopp/RedPitayaDAQServer

max_issues_repo_name: Fypsilonn/RedPitayaDAQServer

max_forks_repo_name: Fypsilonn/RedPitayaDAQServer


text:
compiler_env, script, output = ARGS

if VERSION < v"0.7-"
    error("Unsupported Julia version $VERSION")
end

using Pkg

Pkg.activate(compiler_env)
@info "Loading PackageCompiler..."
using PackageCompiler

@info "Installing PyCall..."
Pkg.activate(".")
Pkg.add([
    PackageSpec(
        name = "PyCall",
        uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0",
    )
    PackageSpec(
        name = "MacroTools",
        uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09",
    )
])

@info "Compiling system image..."
sysout, _curr_syso = compile_incremental("Project.toml", script)

@info "System image is created at $output"
cp(sysout, output, force=true)

max_stars_repo_name: darrencl/pyjulia

max_issues_repo_name: darrencl/pyjulia

max_forks_repo_name: darrencl/pyjulia


text:
using DataDeps
using DataFrames
using GHCNData
using Test

@testset "GHCNData.jl" begin
    include("dataset_loading.jl")
end


text:
import Nemo.characteristic, Nemo.gen, Nemo.size
export gen, characteristic, size, elem_to_mat_row!, rand

function gen{T<:PolyElem}(R::GenResRing{T})
  return R(gen(base_ring(R)))
end

function gen(R::GenResRing{fq_nmod_poly}) ## this is not covered by above
  return R(gen(base_ring(R)))              ## and I don't know why
end

function gen(R::GenResRing{nmod_poly})
  return R(gen(base_ring(R)))
end

function characteristic(R::GenResRing{Nemo.fmpz})
  return modulus(R)
end

function characteristic(R::GenResRing{nmod_poly})
  return characteristic(base_ring(base_ring(R)))
end

function characteristic{T<:PolyElem}(R::GenResRing{T})
  return characteristic(base_ring(base_ring(R)))
end

# discuss: size = order? order = size?
function size(R::Nemo.GenResRing{Nemo.nmod_poly})
  return characteristic(R)^degree(modulus(R))
end

function size{T <: ResElem}(R::Nemo.GenResRing{T})
  return size(base_ring(base_ring(R)))^degree(modulus(R))
end

function size(R::Nemo.GenResRing{fmpz})
  return modulus(R)
end

function size{T<:PolyElem}(R::Nemo.GenResRing{T})
  return size(base_ring(base_ring(R)))^degree(R.modulus)
end

function size(R::Nemo.GenResRing{fq_nmod_poly})
  return size(base_ring(base_ring(R)))^degree(R.modulus)
end

function size(R::FqFiniteField)
  return order(R)
end

function size(R::FqNmodFiniteField)
  return order(R)
end

#################################################
# in triplicate.... and probably cases missing...
function elem_to_mat_row!{T <: PolyElem}(M::MatElem, i::Int, a::ResElem{T})
  z = zero(parent(M[1,1]))
  for j=0:degree(a.data)
    M[i,j+1] = coeff(a.data, j)
  end
  for j=degree(a.data)+2:cols(M)
    M[i,j] = z
  end
end
function elem_to_mat_row!(M::MatElem, i::Int, a::ResElem{fq_poly})
  z = zero(parent(M[1,1]))
  for j=0:degree(a.data)
    M[i,j+1] = coeff(a.data, j)
  end
  for j=degree(a.data)+2:cols(M)
    M[i,j] = z
  end
end
function elem_to_mat_row!(M::MatElem, i::Int, a::ResElem{fq_nmod_poly})
  z = zero(parent(M[1,1]))
  for j=0:degree(a.data)
    M[i,j+1] = coeff(a.data, j)
  end
  for j=degree(a.data)+2:cols(M)
    M[i,j] = z
  end
end

function rand(R::GenResRing{fmpz})
  return R(rand(fmpz(0):(size(R)-1)))
end

function rand{T<:PolyElem}(R::GenResRing{T})
  r = rand(base_ring(base_ring(R)))
  g = gen(R)
  for i=1:degree(R.modulus)
    r = r*g + rand(base_ring(base_ring(R)))
  end
  return r
end

function rand(R::GenResRing{fq_nmod_poly})
  r = rand(base_ring(base_ring(R)))
  g = gen(R)
  for i=1:degree(R.modulus)
    r = r*g + rand(base_ring(base_ring(R)))
  end
  return r
end

function rand(R::GenResRing{fq_poly})
  r = rand(base_ring(base_ring(R)))
  g = gen(R)
  for i=1:degree(R.modulus)
    r = r*g + rand(base_ring(base_ring(R)))
  end
  return r
end

function rand(R::GenResRing{nmod_poly})
  r = rand(base_ring(base_ring(R)))
  g = gen(R)
  for i=1:degree(R.modulus)
    r = r*g + rand(base_ring(base_ring(R)))
  end
  return r
end

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

function gens{T<:PolyElem}(R::GenResRing{T}) ## probably needs more cases
                                          ## as the other residue functions
  g = gen(R)
  r = Array{typeof(g), 1}()
  push!(r, one(R))
  if degree(R.modulus)==1
    return r
  end
  push!(r, g)
  for i=2:degree(R.modulus)-1
    push!(r, r[end]*g)
  end
  return r
end

function gens(R::GenResRing{nmod_poly})
  g = gen(R)
  r = Array{typeof(g), 1}()
  push!(r, one(R))
  if degree(R.modulus)==1
    return r
  end
  push!(r, g)
  for i=2:degree(R.modulus)-1
    push!(r, r[end]*g)
  end
  return r
end

function rem!(f::Nemo.nmod_poly, g::Nemo.nmod_poly, h::Nemo.nmod_poly)
  ccall((:nmod_poly_rem, :libflint), Void, (Ptr{Nemo.nmod_poly}, Ptr{Nemo.nmod_poly}, Ptr{Nemo.nmod_poly}), &f, &g, &h)
  return f
end

function gcd!(f::Nemo.nmod_poly, g::Nemo.nmod_poly, h::Nemo.nmod_poly)
  ccall((:nmod_poly_gcd, :libflint), Void, (Ptr{Nemo.nmod_poly}, Ptr{Nemo.nmod_poly}, Ptr{Nemo.nmod_poly}), &f, &g, &h)
  return f
end

function Base.call(R::Nemo.NmodPolyRing, g::fmpq_poly)
  return fmpq_poly_to_nmod_poly(R, g)
end


text:
@testset "Autodiff propagation" begin
  f = ToCartesian(r->[r[1] * cos(r[2]), r[1]*sin(r[2])], 2)
  f⁻¹ = FromCartesian(x->[sqrt(x[1]^2 + x[2]^2), atan(x[2], x[1])], 2)

  X = rand(2) .- 0.5
  R = f⁻¹(X)

  @test ForwardDiff.jacobian(f, R) ≈ inv(ForwardDiff.jacobian(f⁻¹, X))
  @test inv(ForwardDiff.jacobian(f, R)) ≈ ForwardDiff.jacobian(f⁻¹, X)
  @test X ≈ f⁻¹ \ R
  @test inv(ForwardDiff.jacobian(f, R)) ≈ ForwardDiff.jacobian(r-> f⁻¹(f⁻¹ \ r), R)
end

max_stars_repo_name: jwscook/DifferentialGeometries

max_issues_repo_name: jwscook/DifferentialGeometries

max_forks_repo_name: jwscook/DifferentialGeometries


text:
struct BootstrapEstimates
  Δhat::Vector{Float64}
  Δb::Matrix{Float64}     # each column represents a bootstrap estimate
end

function bootstrap(X, Y; bootSamples::Int64=300, estimSupport::Union{Vector{Vector{Int64}},Nothing}=nothing)
  nx, p = size(X)
  ny    = size(Y, 1)

  Sx = Symmetric( cov(X) )
  Sy = Symmetric( cov(Y) )

  eS = estimSupport === nothing ? __initSupport(Sx, Sy, X, Y) : estimSupport

  rp = div((p+1)*p, 2)
  # indS = Vector{Vector{Int64}}(undef, rp)

  Δhat = Vector{Float64}(undef, rp)
  Δb = Matrix{Float64}(undef, rp, bootSamples)

  bX = similar(X)
  bY = similar(Y)
  x_ind = Vector{Int64}(undef, nx)
  y_ind = Vector{Int64}(undef, ny)

  # obtain initial estimate
  it = 0
  for col=1:p
    for row=col:p
      it = it + 1
      indElem = sub2indLowerTriangular(p, row, col)
      # tmp = estimate(ReducedOracleNormal(), Sx, Sy, X, Y, indElem, eS[it])

      indS = eS[it]
      makeFirst!(indS, indElem)
      C = skron(Sx, Sy, indS)
      b = svec(Sy, indS) - svec(Sx, indS)
      Δ = C \ b

      Δhat[it] = Δ[1]
    end
  end

  for _b=1:bootSamples
    sample!(1:nx, x_ind)
    sample!(1:ny, y_ind)

    _fill_boot!(bX, X, x_ind)
    _fill_boot!(bY, Y, y_ind)

    bSx = Symmetric( cov(bX) )
    bSy = Symmetric( cov(bY) )

    it = 0
    for col=1:p
      for row=col:p
        it = it + 1
        indElem = sub2indLowerTriangular(p, row, col)
        # tmp = estimate(ReducedOracleNormal(), bSx, bSy, bX, bY, indexElementLinear, eS[it])

        indS = eS[it]
        makeFirst!(indS, indElem)
        C = skron(bSx, bSy, indS)
        b = svec(bSy, indS) - svec(bSx, indS)
        Δ = C \ b

        Δb[it, _b] = Δ[1]
        end
      end
    end

    BootstrapEstimates(Δhat, Δb), eS
end

function simulCI(straps::BootstrapEstimates, α::Float64=0.95)
    m, bootSamples = size(straps.Δb)

    infNormDist = Vector{Float64}(undef, bootSamples)
    CI = Matrix{Float64}(undef, m, 2)

    for b=1:bootSamples
        infNormDist[b] = norm_diff(straps.Δhat, view(straps.Δb, :, b), Inf)
    end
    x = quantile!(infNormDist, α)
    CI[:, 1] .= straps.Δhat .- x
    CI[:, 2] .= straps.Δhat .+ x

    CI
end

function simulCIstudentized(straps::BootstrapEstimates, α::Float64=0.95)
    m, bootSamples = size(straps.Δb)

    infNormDist = Vector{Float64}(undef, bootSamples)
    w = reshape(std(straps.Δb; dims = 2, corrected = false), :)

    CI = Matrix{Float64}(undef, m, 2)
    tmp = Vector{Float64}(undef, m)

    for b=1:bootSamples
        tmp .= (straps.Δhat .- straps.Δb[:, b]) ./ w
        infNormDist[b] = norm(tmp, Inf)
    end
    x = quantile!(infNormDist, α)
    @. CI[:, 1] = straps.Δhat - x * w
    @. CI[:, 2] = straps.Δhat + x * w

    CI
end

function _fill_boot!(bX, X, b_ind)
  n, p = size(X)
  for col=1:p
      for row=1:n
          bX[row, col] = X[b_ind[row], col]
      end
  end
end


text:
# SPDX-License-Identifier: MIT

using ArgParse
using JLD2
using MarkovModels

function parse_commandline()
    s = ArgParseSettings()
    @add_arg_table s begin
        "out"
            help = "output JLD2 archive"
            required = true
        "archives"
            nargs = '+'
            help = "archives to concatenate"
            required = true
    end
    parse_args(s)
end

function main(args)
    archives = args["archives"]
    jldopen(args["out"], "w") do f

        # Copy the data of each archive in the new one.
        for arch in archives
            jldopen(arch, "r") do farchive
                for uttid in keys(farchive)
                    f["$uttid"] = farchive["$uttid"]
                end
            end
        end
    end

end

args = parse_commandline()
main(args)

max_stars_repo_name: MartinKocour/SpeechLab

max_issues_repo_name: MartinKocour/SpeechLab

max_forks_repo_name: MartinKocour/SpeechLab


text:
function thingo(n)
    x = []
    for i =1 : n
        push!(x, i)
    end
    return x
end


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

include("model_AddressSpace.jl")
include("model_BgpPeerStatus.jl")
include("model_BgpPeerStatusListResult.jl")
include("model_BgpSettings.jl")
include("model_ConnectionResetSharedKey.jl")
include("model_ConnectionSharedKey.jl")
include("model_GatewayRoute.jl")
include("model_GatewayRouteListResult.jl")
include("model_IpsecPolicy.jl")
include("model_LocalNetworkGatewayListResult.jl")
include("model_LocalNetworkGatewayPropertiesFormat.jl")
include("model_Resource.jl")
include("model_SubResource.jl")
include("model_TunnelConnectionHealth.jl")
include("model_VirtualNetworkGatewayConnectionListResult.jl")
include("model_VirtualNetworkGatewayConnectionPropertiesFormat.jl")
include("model_VirtualNetworkGatewayIPConfigurationPropertiesFormat.jl")
include("model_VirtualNetworkGatewayListResult.jl")
include("model_VirtualNetworkGatewayPropertiesFormat.jl")
include("model_VirtualNetworkGatewaySku.jl")
include("model_VpnClientConfiguration.jl")
include("model_VpnClientParameters.jl")
include("model_VpnClientRevokedCertificatePropertiesFormat.jl")
include("model_VpnClientRootCertificatePropertiesFormat.jl")
include("model_LocalNetworkGateway.jl")
include("model_VirtualNetworkGateway.jl")
include("model_VirtualNetworkGatewayConnection.jl")
include("model_VirtualNetworkGatewayIPConfiguration.jl")
include("model_VpnClientRevokedCertificate.jl")
include("model_VpnClientRootCertificate.jl")


text:
using Test
using Verificatum: encode, decode, marshal_publickey, marshal_privatekey, unmarshal, unmarshal_publickey, unmarshal_privatekey

PUBLIC_KEY = "$(@__DIR__)/publicKey"
PRIVATE_KEY = "$(@__DIR__)/privateKey"

group_spec = "00000000020100000020636f6d2e766572696669636174756d2e61726974686d2e4d6f645047726f757000000000040100000041009a91c3b704e382e0c772fa7cf0e5d6363edc53d156e841555702c5b6f906574204bf49a551b695bed292e0218337c0861ee649d2fe4039174514fe2c23c10f6701000000404d48e1db8271c17063b97d3e7872eb1b1f6e29e8ab7420aaab8162db7c832ba1025fa4d2a8db4adf69497010c19be0430f7324e97f201c8ba28a7f1611e087b3010000004100300763b0150525252e4989f51e33c4e6462091152ef2291e45699374a3aa8acea714ff30260338bddbb48fc7446b273aaada90e3ee8326f388b582ea8a073502010000000400000001"

tree = decode(group_spec)

g = unmarshal(BigInt, tree)

sk = BigInt(11112)

y = g^sk

pubkey_tree = marshal_publickey(g, y)
write(PUBLIC_KEY, pubkey_tree)

privkey_tree = marshal_privatekey(g, sk)
write(PRIVATE_KEY, privkey_tree)

### Let's test that writing was succesful

y′, g′ =  unmarshal_publickey(decode(read(PUBLIC_KEY)))

@test y′ == y
@test g′ == g

sk′, g′′ =  unmarshal_privatekey(decode(read(PRIVATE_KEY)))

@test g′′ == g
@test sk′ == sk


text:
module BoltzmannMachines

using Distributed
using LinearAlgebra
using Random
using Statistics

const BMs = BoltzmannMachines

export
   AbstractBM,
      aislogimpweights, aisprecision, aisstandarddeviation,
      empiricalloglikelihood, energy, exactloglikelihood,
      exactlogpartitionfunction, loglikelihood,
      logpartitionfunction, logpartitionfunctionzeroweights,
      logproblowerbound, reconstructionerror,
      sampleparticles, samples,
      AbstractRBM,
         BernoulliRBM,
         BernoulliGaussianRBM,
         Binomial2BernoulliRBM,
         GaussianBernoulliRBM,
         GaussianBernoulliRBM2,
         Softmax0BernoulliRBM,
         PartitionedRBM,
         fitrbm, freeenergy, initrbm,
         joinrbms, joindbms,
         trainrbm!,
         samplehidden, samplehidden!,
         samplevisible, samplevisible!,
         hiddenpotential, hiddenpotential!,
         hiddeninput, hiddeninput!,
         visiblepotential, visiblepotential!,
         visibleinput, visibleinput!,
      MultimodalDBM,
         BasicDBM,
         AbstractTrainLayer, AbstractTrainLayers,
         TrainLayer, TrainPartitionedLayer,
         stackrbms,
         initparticles, gibbssample!, gibbssamplecond!,
         meanfield, fitdbm, traindbm!,
   Particle, Particles,
   AbstractOptimizer,
      LoglikelihoodOptimizer,
      initialized, computegradient!, updateparameters!,
      loglikelihoodoptimizer,
      beamoptimizer,
   Monitor, MonitoringItem, DataDict,
      monitored_fitrbm, monitored_stackrbms,
      monitored_traindbm!, monitored_fitdbm,
      monitorexactloglikelihood, monitorexactloglikelihood!,
      monitorfreeenergy, monitorfreeenergy!,
      monitorlogproblowerbound, monitorlogproblowerbound!,
      monitorloglikelihood, monitorloglikelihood!,
      monitorreconstructionerror, monitorreconstructionerror!,
      monitorsd, monitorsd!,
      monitorweightsnorm, monitorweightsnorm!,
      propagateforward,
   crossvalidation,
   intensities, intensities_encode, intensities_decode,
   oneornone_encode, oneornone_decode,
   splitdata,
   barsandstripes, blocksinnoise, logit,
   top2latentdims

include("bmtypes.jl")
include("gibbssampling.jl")
include("samplers.jl")
include("optimizers.jl")
include("rbmtraining.jl")
include("rbmstacking.jl")
include("dbmtraining.jl")
include("weightsjoining.jl")
include("evaluating.jl")
include("monitoring.jl")
include("monitoredfitting.jl")
include("beam.jl")
include("misc.jl")
include("datapreprocessing.jl")

end # of module BoltzmannMachines


text:
using AutomatonEdification

@testset "sigmoid" begin
    @test AutomatonEdification.ActivationFunctions.sigmoid(0) == 0.5
    @test AutomatonEdification.ActivationFunctions.sigmoid(1) == 1/(1 + exp(-1))
    @test AutomatonEdification.ActivationFunctions.sigmoid(2) == 1/(1 + exp(-2))
    @test AutomatonEdification.ActivationFunctions.sigmoid(-1) == 1/(1 + exp(1))

    @test AutomatonEdification.ActivationFunctions.sigmoid([0, 0, 0]) == [0.5, 0.5, 0.5]
    @test AutomatonEdification.ActivationFunctions.sigmoid([0, 1, 2, -1]) ==
        [0.5, 1/(1 + exp(-1)), 1/(1 + exp(-2)), 1/(1 + exp(1))]
end

@testset "relu" begin
    @test AutomatonEdification.ActivationFunctions.relu(0) == 0
    @test AutomatonEdification.ActivationFunctions.relu(1) == 1
    @test AutomatonEdification.ActivationFunctions.relu(-10) == 0

    @test AutomatonEdification.ActivationFunctions.relu([0, 1, -10]) ==
        [0, 1, 0]
end

@testset "softmax" begin
    @test AutomatonEdification.ActivationFunctions.softmax([0]) == [1]
    @test AutomatonEdification.ActivationFunctions.softmax([-2]) == [1]
    @test AutomatonEdification.ActivationFunctions.softmax([1000]) == [1]

    @test AutomatonEdification.ActivationFunctions.softmax([0, 0]) == [0.5, 0.5]
    @test AutomatonEdification.ActivationFunctions.softmax([0, 0, 0, 0]) ==
        [0.25, 0.25, 0.25, 0.25]

    @test isapprox(
        AutomatonEdification.ActivationFunctions.softmax([0, -1, 3, 3, -4]),
        [exp(0), exp(-1), exp(3), exp(3), exp(-4)] ./
        (exp(0) + exp(-1) + exp(3) + exp(3) + exp(-4)))
end

max_stars_repo_name: brianxie/automaton-edification

max_issues_repo_name: brianxie/automaton-edification

max_forks_repo_name: brianxie/automaton-edification