text:
module Terminals
    import Base.size, Base.write, Base.flush
    abstract TextTerminal <: Base.IO
    export TextTerminal, NCurses, writepos, cmove, pos, getX, getY, hascolor

    # Stuff that really should be in a Geometry package
    immutable Rect
        top
        left
        width
        height
    end

    immutable Size
        width
        height
    end

    # INTERFACE
    size(::TextTerminal) = error("Unimplemented")
    writepos(t::TextTerminal,x,y,s::Array{Uint8,1}) = error("Unimplemented")
    cmove(t::TextTerminal,x,y) = error("Unimplemented")
    getX(t::TextTerminal) = error("Unimplemented")
    getY(t::TextTerminal) = error("Unimplemented")
    pos(t::TextTerminal) = (getX(t),getY(t))

    # Relative moves (Absolute position fallbacks)
    export cmove_up, cmove_down, cmove_left, cmove_right, cmove_line_up, cmove_line_down, cmove_col

    cmove_up(t::TextTerminal,n) = cmove(getX(),max(1,getY()-n))
    cmove_up(t) = cmove_up(t,1)

    cmove_down(t::TextTerminal,n) = cmove(getX(),max(height(t),getY()+n))
    cmove_down(t) = cmove_down(t,1)

    cmove_left(t::TextTerminal,n) = cmove(max(1,getX()-n),getY())
    cmove_left(t) = cmove_left(t,1)

    cmove_right(t::TextTerminal,n) = cmove(max(width(t),getX()+n),getY())
    cmove_right(t) = cmove_right(t,1)

    cmove_line_up(t::TextTerminal,n) = cmove(1,max(1,getY()-n))
    cmove_line_up(t) = cmove_line_up(t,1)

    cmove_line_down(t::TextTerminal,n) = cmove(1,max(height(t),getY()+n))
    cmove_line_down(t) = cmove_line_down(t,1)

    cmove_col(t::TextTerminal,c) = comve(c,getY())

    # Defaults
    hascolor(::TextTerminal) = false

    # Utility Functions
    function writepos{T}(t::TextTerminal, x, y, b::Array{T})
        if isbits(T)
            writepos(t,x,y,reinterpret(Uint8,b))
        else
            cmove(t,x,y)
            invoke(write, (IO, Array), s, a)
        end
    end
    function writepos(t::TextTerminal,x,y,args...)
        cmove(t,x,y)
        write(t,args...)
    end
    width(t::TextTerminal) = size(t).width
    height(t::TextTerminal) = size(t).height

    # For terminals with buffers
    flush(t::TextTerminal) = nothing

    clear(t::TextTerminal) = error("Unimplemented")
    clear_line(t::TextTerminal,row) = error("Unimplemented")
    clear_line(t::TextTerminal) = error("Unimplemented")

    raw!(t::TextTerminal,raw::Bool) = error("Unimplemented")

    beep(t::TextTerminal) = nothing

    abstract TextAttribute

    module Attributes
        # This is just to get started and will have to be revised

        import Terminals.TextAttribute, Terminals.TextTerminal

        export Standout, Underline, Reverse, Blink, Dim, Bold, AltCharset, Invisible, Protect, Left, Right, Top,
                Vertical, Horizontal, Low

        macro flag_attribute(name)
            quote
                immutable $name <: TextAttribute
                end
            end
        end

        @flag_attribute Standout
        @flag_attribute Underline
        @flag_attribute Reverse
        @flag_attribute Blink
        @flag_attribute Dim
        @flag_attribute Bold
        @flag_attribute AltCharset
        @flag_attribute Invisible
        @flag_attribute Protect
        @flag_attribute Left
        @flag_attribute Right
        @flag_attribute Top
        @flag_attribute Vertical
        @flag_attribute Horizontal
        @flag_attribute Low

        attr_simplify(::TextTerminal, x::TextAttribute) = x
        attr_simplify{T<:TextAttribute}(::TextTerminal, ::Type{T}) = T()
        function attr_simplify(::TextTerminal, s::Symbol)
            if s == :standout
                return Standout()
            elseif s == :underline
                return Underline()
            elseif s == :reverse
                return Reverse()
            elseif s == :blink
                return Blink()
            end
        end

    end

    module Colors
        import Terminals.TextAttribute, Terminals.TextTerminal, Terminals.Attributes.attr_simplify
        using Color

        export TerminalColor, TextColor, BackgroundColor, ForegroundColor, approximate,
                lookup_color, terminal_color, maxcolors, maxcolorpairs, palette, numcolors

        # Represents a color actually displayable by the current terminal
        abstract TerminalColor

        immutable TextColor <: TextAttribute
            c::TerminalColor
        end
        immutable BackgroundColor <: TextAttribute
            c::TerminalColor
        end

        function approximate(t::TextTerminal, c::ColorValue)
            x = keys(palette(t))
            lookup_color(t,x[indmin(map(x->colordiff(c,x),x))])
        end

        attr_simplify(t::TextTerminal, c::ColorValue) = TextColor(lookup_color(t,c))

        # Terminals should implement this
        lookup_color(t::TextTerminal) = error("Unimplemented")
        maxcolors(t::TextTerminal) = error("Unimplemented")
        maxcolorpairs(t::TextTerminal) = error("Unimplemented")
        palette(t::TextTerminal) = error("Unimplemented")
        numcolors(t::TextTerminal) = error("Unimplemented")
    end

    module Unix
        importall Terminals

        import Terminals: width, height, cmove, Rect, Size, getX,
                          getY, raw!, clear, clear_line, beep, hascolor
        import Base: size, read, write, flush, TTY, writemime, readuntil, start_reading, stop_reading

        export UnixTerminal

        type UnixTerminal <: TextTerminal
            term_type
            in_stream::TTY
            out_stream::TTY
            err_stream::TTY
        end

        const CSI = "\x1b["

        cmove_up(t::UnixTerminal,n) = write(t.out_stream,"$(CSI)$(n)A")
        cmove_down(t::UnixTerminal,n) = write(t.out_stream,"$(CSI)$(n)B")
        cmove_right(t::UnixTerminal,n) = write(t.out_stream,"$(CSI)$(n)C")
        cmove_left(t::UnixTerminal,n) = write(t.out_stream,"$(CSI)$(n)D")
        cmove_line_up(t::UnixTerminal,n) = (cmove_up(t,n);cmove_col(t,0))
        cmove_line_down(t::UnixTerminal,n) = (cmove_down(t,n);cmove_col(t,0))
        cmove_col(t::UnixTerminal,n) = write(t.out_stream,"$(CSI)$(n)G")

        raw!(t::UnixTerminal,raw::Bool) = ccall(:uv_tty_set_mode,Int32,(Ptr{Void},Int32),t.in_stream.handle,raw?1:0)!=-1
        enable_bracketed_paste(t::UnixTerminal) = write(t.out_stream,"$(CSI)?2004h")
        disable_bracketed_paste(t::UnixTerminal) = write(t.out_stream,"$(CSI)?2004l")

        function size(t::UnixTerminal)
            s = Array(Int32,2)
            Base.uv_error("size (TTY)",ccall(:uv_tty_get_winsize,Int32,(Ptr{Void},Ptr{Int32},Ptr{Int32}),t.out_stream.handle,pointer(s,1),pointer(s,2))!=0)
            Size(s[1],s[2])
        end

        clear(t::UnixTerminal) = write(t.out_stream,"\x1b[H\x1b[2J")
        clear_line(t::UnixTerminal) = write(t.out_stream,"\x1b[0G\x1b[0K")
        beep(t::UnixTerminal) = write(t.err_stream,"\x7")

        write{T,N}(t::UnixTerminal,a::Array{T,N}) = write(t.out_stream,a)
        write(t::UnixTerminal,p::Ptr{Uint8}) = write(t.out_stream,p)
        write(t::UnixTerminal,p::Ptr{Uint8},x::Integer) = write(t.out_stream,p,x)
        write(t::UnixTerminal,x::Uint8) = write(t.out_stream,x)
        read{T,N}(t::UnixTerminal,x::Array{T,N}) = read(t.in_stream,x)
        readuntil(t::UnixTerminal,s::String) = readuntil(t.in_stream,s)
        readuntil(t::UnixTerminal,c::Char) = readuntil(t.in_stream,c)
        readuntil(t::UnixTerminal,s) = readuntil(t.in_stream,s)
        read(t::UnixTerminal,::Type{Uint8}) = read(t.in_stream,Uint8)
        start_reading(t::UnixTerminal) = start_reading(t.in_stream)
        stop_reading(t::UnixTerminal) = stop_reading(t.in_stream)

        hascolor(t::UnixTerminal) = (beginswith(t.term_type,"xterm") || success(`tput setaf 0`))
        #writemime(t::UnixTerminal, ::MIME"text/plain", x) = writemime(t.out_stream, MIME("text/plain"), x)
    end
    importall .Unix
    export UnixTerminal
end


text:
using Test
using FlightMechanics

@testset "atmosphere" begin include("atmosphere.jl") end
@testset "coordinates" begin include("coordinates.jl") end
@testset "anemometry" begin include("anemometry.jl") end
@testset "mechanics" begin include("mechanics.jl") end
@testset "flight mechanics" begin include("flight_mechanics.jl") end

@testset "pfm" begin include("simulator/models/point_forces_moments.jl") end
@testset "mass" begin include("simulator/models/mass.jl") end
@testset "attitude" begin include("simulator/models/attitude.jl") end
@testset "position" begin include("simulator/models/position.jl") end
@testset "aerodynamics" begin include("simulator/models/aerodynamics.jl") end
@testset "aerostate" begin include("simulator/models/aero_state.jl") end

@testset "ac: c310" begin include("simulator/aircrafts/c310.jl") end
@testset "ac: f16" begin include("simulator/aircrafts/f16.jl") end

ext: jl


text:
using QuantumESPRESSOHelpers
using Test

@testset "QuantumESPRESSOHelpers.jl" begin
    # Write your own tests here.
end


text:
#name: PCA
#description: Principal Component Analysis
#reference: https://en.wikipedia.org/wiki/Principal_component_analysis
#language: julia
#tags: demo, hide-suggestions
#sample: cars.csv
#input: dataframe table {columns:numerical} [Input data table]
#input: column_list features {type:numerical;allowNulls:false} [Features columns]
#input: int components = 2 [Number of components]
#output: dataframe result {action:join(table)} [PCA components]

using MultivariateStats

table = Float64.(convert(Array, table))'
model = fit(PCA, table; maxoutdim=components, pratio=0.99999)
result = transform(model, table)
result = convert(DataFrame, result')

max_stars_repo_name: AndSviat/public

max_issues_repo_name: AndSviat/public

max_forks_repo_name: AndSviat/public


text:
using MLJTime, CategoricalArrays
using Test

@testset "datapath" begin
    _fpath = joinpath(dirname(@__FILE__), "..", "data/toy.csv")
    X1, y1 = load_dataset(_fpath)

    @test X1 == [-0.58291082 0.77026 0.59999317 0.96146749 0.37977839
    0.84154274 0.37243245 0.21868173 0.84613282 0.57537467
    0.93855293 0.25818638 0.29248046 0.42564401 0.5711786
    0.21304496 0.66891344 0.37140495 0.20650268 0.3307044
    0.71431759 0.8304377  0.1329058  0.36528646 0.91321754
    0.02603724 0.731184   -0.99851577 0.03834193 0.85909822
    0.93824209 0.96672667 0.71939988 0.13687903 0.88989899
    0.88613429 0.22027203 0.74891512 0.80662967 0.19656783
    0.25738735 -0.85849893 0.29519148 0.76403467 0.32104374
    0.17287711 0.34066372 0.29485052 0.3625377  0.80875406
    0.75821559 0.83328172 0.83108783 0.34411894 0.38067706
    -0.97173602 0.38711375 0.90523631 0.50105462 0.67240828
    0.49331099 0.47179102 0.68784676 0.81708483 0.22690731
    0.02193189 0.87135088 0.16605978 0.2785312  0.2463312
    0.2115269  0.97515003 0.83898221 0.44870931 0.32124904]

    @test y1 == CategoricalArray([-2, 2, 2, 1, 2, 2, -1, 2, 2, 0, 2, 2, -1, 2, 2])

    dataset = "BasicMotions"
    _fpath = joinpath(dirname(@__FILE__), "..", "data", dataset, string(dataset, "_", "TEST", ".ts" ))

    X2, y2 = load_from_tsfile_to_NDArray(_fpath)

    @test X2[1:20:end, 1:20:end, 1:2:end] == cat([-0.740653 -5.8e-5 -0.106508 -0.153654 -0.278119; -0.294498 0.575243 -0.494393 0.196209 -0.639463],
                                                 [-0.275809 0.134542 0.092941 -0.091092 0.095472; 0.218114 -0.648919 0.191443 -0.5032 0.308612],
                                                 [0.013317 -0.045277 -0.039951 0.005327 0.005327; -0.002663 -0.407496 0.127842 -0.447447 -0.103872], dims=3)

    @test y2[1:8:end] ==  CategoricalArray( ["Standing", "Standing", "Running", "Walking", "Badminton"])

    X3, y3 = load_NDdataset(dataset)

    @test X3[1:20:end, 1:20:end, 1:2:end] == cat([-0.740653 -5.8e-5 -0.106508 -0.153654 -0.278119; -0.294498 0.575243 -0.494393 0.196209 -0.639463; 0.079106 0.241339 -0.269544 -0.332913 -0.129874; -0.071819 1.245053 2.160997 3.774588 3.799607],
            [-0.275809 0.134542 0.092941 -0.091092 0.095472; 0.218114 -0.648919 0.191443 -0.5032 0.308612; 0.551444 0.385068 0.223995 -0.254828 0.207466; 0.275074 0.146363 -1.528987 0.446009 -1.56106],
            [0.013317 -0.045277 -0.039951 0.005327 0.005327; -0.002663 -0.407496 0.127842 -0.447447 -0.103872; 0.02397 -0.25302 0.00799 0.077238 -0.050604; 0.743081 0.098545 0.01598 0.194426 -0.964141], dims=3)

    @test y3[1:8:end] ==  CategoricalArray( ["Standing", "Standing", "Running", "Walking", "Badminton", "Standing", "Standing", "Running", "Walking", "Badminton"])
end

@testset "interval based forest" begin
    X, y = ts_dataset("Chinatown")
    rng = StableRNG(566) # seed to resproduce the results.

    Interval_features, Intervals = MLJTime.IntervalBasedForest.InvFeatureGen(matrix(X[1:5]), 1, 3, rng);

    #MLJTime.IntervalBasedForest.InvFeatureGen(matrix(X[1:5]), 1, 3, rng)[1]
    @test Interval_features[:, :, 1]  == ([[745.4444444444445 505.0103344571245 56.36945304437562 716.3157894736842 506.93973481750487 39.17543859649122 1057.6 311.9797714240104 -88.88484848484839 1197.5 66.31490531295862 13.4;
    643.6111111111111 413.3816266853738 45.493292053663545 619.578947368421 415.16761217468587 31.45964912280703 904.5 265.43057263414266 -75.93333333333331 1046.5 36.27211968808366 9.4;
    944.1666666666666 620.4238826138522 100.38906088751294 939.1052631578947 603.3471356374133 83.81228070175439 1421.2 164.37342310185736 -7.357575757575845 1406.75 169.44689433565904 119.1;
    1023.6666666666666 700.7234916603737 62.30340557275547 982.8421052631579 703.8473842750836 40.710526315789444 1366.3 455.57339937953157 -146.3454545454545 1541.5 139.28507936363224 -102.0;
    659.2222222222222 434.21268244349017 67.04643962848297 660.3157894736842 422.00579941138494 57.31754385964911 982.8 108.05327903914397 -15.757575757575758 922.25 88.08092869628476 7.5]])[1]

    #MLJTime.IntervalBasedForest.InvFeatureGen( matrix(X[6:10]), Intervals, 1)
    new_features = [937.6111111111111 627.4576281816954 100.41176470588233 927.8421052631579 611.2641966683922 82.419298245614 1419.6 160.05776734944445 -11.854545454545367 1383.5 133.4778383602811 71.4;
                    853.0 565.1491213934289 85.80804953560367 838.8947368421053 552.6569052954646 68.70526315789472 1276.1 203.59188479788565 -26.24848484848476 1345.25 139.28717337453102 105.3;
                    851.6111111111111 573.4303525983306 84.23839009287926 833.2105263157895 563.0164373905345 66.08245614035089 1277.6 223.29860426493192 -41.62424242424238 1351.0 121.72920767013971 89.6;
                    937.6666666666666 632.3074456958045 99.36016511867906 923.3157894736842 617.6681105066394 80.15087719298245 1419.9 203.8831092126619 -16.951515151515196 1444.75 149.92081243109644 108.5;
                    857.6666666666666 562.0918911687368 82.0 851.0 547.0275231751242 67.7 1258.6 214.72214603994624 -34.83636363636359 1344.5 117.53722814495839 79.2]

    new_features = reshape(new_features, 5, 12, 1)
    @test MLJTime.IntervalBasedForest.InvFeatureGen( matrix(X[6:10]), Intervals, 1)  ==  new_features

    train, test = partition(eachindex(y), 0.7)
    @test unique(y) == [1.0 , 2.0]

    model = TimeSeriesForestClassifier(n_trees=3, random_state=rng)
    mach = machine(model, matrix(X[train]), y[train])
    fit!(mach)
    y_pred = predict_mode(mach, matrix(X[test]))
    @test accuracy(y_pred, y[test]) >= 0.75
end

@testset "distances" begin
    rng = StableRNG(566)
    M = zeros(6, 6)
    FloatMax = maxintfloat(Float64)
    M[1, 2:end] .= FloatMax
    M[2:end, 1] .= FloatMax
    a = rand(rng, Int64, 5)
    b = rand(rng, Int64, 5)
    @test dtw_distance(a, b, -1, M) == -2.9402683278543684e19
end

@testset "KNN" begin
    X, y = ts_dataset("Chinatown")
    train, test = partition(eachindex(y), 0.7)

    A = rand(StableRNG(566), 5, 5)
    index = zeros(5, 3)
    index = MLJTime.select_sort(A, index, 3)
    @test index == [1.0 2.0 3.0; 1.0 3.0 4.0; 3.0 2.0 5.0; 1.0 5.0 4.0; 5.0 2.0 4.0]

    model = TimeSeriesKNNClassifier()
    mach = machine(model, matrix(X[train]), y[train])
    fit!(mach)
    y_pred = predict_mode(mach, matrix(X[test]))
    @test accuracy(y_pred, y[test]) >= 0.70

    k = 4
    rng = StableRNG(566)
    A = rand(rng, 20,30)
    index = zeros(20, k)

    @test MLJTime.select_sort(A, index, k) == [1.0  25.0  19.0   5.0
                             5.0  15.0  11.0  21.0
                            12.0  19.0  17.0  21.0
                            26.0  10.0  25.0   6.0
                            10.0   8.0  23.0   8.0
                            15.0  30.0  19.0  29.0
                            23.0   4.0   5.0  26.0
                             6.0  11.0  18.0  23.0
                            13.0   5.0  29.0  29.0
                            15.0  27.0  27.0  30.0
                            25.0  20.0  13.0  22.0
                            13.0   9.0  27.0  28.0
                            30.0  22.0  10.0   8.0
                            29.0   5.0   9.0  28.0
                            24.0   2.0   3.0   6.0
                            16.0  17.0  21.0  21.0
                            17.0  11.0  15.0  27.0
                            18.0  20.0  12.0  21.0
                            28.0  27.0   7.0  15.0
                            19.0  11.0  23.0  29.0]
end

@testset "Rocket" begin
    #=
    np.random.seed(5)
    kernel = generate_kernels(15, 15)
    XX = np.random.random((15,15))
    apply_kernels_ans = apply_kernels(XX, kernel)
    =#
    apply_kernels_ans = [0.466666667  1.86915069  0.714285714   1.56404946  0.466666667  0.644749239  0.2    0.81511455 0.333333333     0.182182149           0.2   0.391800731  0.266666667  0.260279791 0.666666667 1.40668578 1.0  2.6588065         0.6 1.16076305 0.0  -0.831747841 0.533333333 2.42694389 0.866666667 2.13242483 0.714285714  0.97215377 0.428571429  1.04198929
                         0.666666667   2.7605416  0.428571429   1.17048616          0.4    1.1636767  0.2     1.1492548 0.333333333  0.000722869176   0.266666667   0.965390512          0.2  0.473190683 0.777777778 1.18343075 1.0 1.61479977 0.666666667  2.3053302 0.0  -0.590403203 0.666666667  1.9228075         0.8 1.97877259 0.714285714  1.29059237 0.142857143 0.157695276
                         0.466666667  2.49380658  0.714285714  0.667454033  0.466666667   1.37855049  0.4   0.500730237 0.333333333     0.207603449   0.333333333   0.704937334  0.333333333  0.507972768         1.0 1.72705702 1.0 1.92037785 0.666666667 2.02551711 0.2   0.373990297 0.733333333 1.59525635 0.866666667  2.0680034 0.571428571  1.29283699 0.428571429 0.544295866
                         0.666666667  3.20101023  0.571428571   1.03278335  0.466666667   1.06228991  0.2   0.630871416 0.333333333     0.627532089   0.133333333    1.15763168  0.266666667  0.391364466 0.888888889  1.5503435 1.0 1.34876186 0.533333333 1.40246686 0.0 -0.0529354498 0.733333333 1.78481358         0.8 1.85289043 0.285714286  2.00849779 0.285714286 0.902233787
                         0.666666667  2.13769425  0.714285714   1.13289562  0.466666667    1.9158521  0.4   0.998864346         0.0   -0.0485586352   0.333333333   0.350269008  0.266666667  0.786788254 0.888888889 1.14198556 0.8 1.40468465 0.466666667  2.9189426 0.0  -0.109600439 0.666666667 1.78128214 0.733333333  2.6235522 0.428571429  2.18413789 0.571428571  1.29903864
                         0.533333333   2.9836892  0.428571429   1.45750256          0.4   1.43926618  0.4   0.516466306 0.666666667     0.960756044   0.333333333     1.1196118          0.2   0.76917819 0.888888889 1.05131567 1.0 2.47633094 0.666666667 2.43674043 0.0  -0.925993035         0.6 2.69302784         0.8 2.77034219 0.714285714  2.40433854 0.428571429 0.958647645
                         0.533333333  1.71039666  0.428571429   1.11807856  0.333333333   1.48710231  0.6    0.22319701         0.0    -0.358080617   0.266666667   0.403950255  0.133333333   0.36698616 0.888888889 1.33615988 1.0 1.57683181         0.4 1.91053745 0.2   0.272680734 0.533333333 2.83349575 0.866666667 1.64220126 0.571428571  2.04472092 0.428571429  0.68234057
                                 0.6  2.40716291  0.571428571  0.672292953          0.4  0.995636869  0.2    0.91441026 0.333333333      0.19570031   0.266666667   0.719213674          0.2   1.00029484         1.0 1.59276171 0.8 1.46403462 0.666666667 1.68903487 0.0  -0.257202796         0.8 2.15746543         0.8 2.33142911 0.285714286  1.58453787 0.285714286 0.276128956
                                 0.6   2.5495622  0.428571429   1.04375563  0.533333333  0.907804279  0.0  -0.426021734 0.333333333     0.106019564   0.266666667   0.284415817          0.2  0.458375633 0.777777778 1.16355143 1.0 1.78442748 0.466666667 1.35029968 0.0  -0.296840664 0.666666667 1.94336411 0.933333333 1.87213404 0.714285714 0.710278128 0.142857143 0.184764197
                         0.533333333  1.92622824  0.285714286   1.26193378  0.533333333   1.21053493  0.2   0.330809842 0.333333333     0.182135788   0.266666667    0.51782547  0.133333333  0.091649982 0.777777778 1.53573269 0.6 2.48635508 0.666666667 1.45231436 0.4   0.692076558 0.666666667 2.04981721 0.866666667 2.50377807 0.285714286 0.514873952 0.285714286 0.604855995
                         0.466666667   2.8742218  0.571428571   1.12958146  0.466666667  0.982245782  0.2   0.502296872 0.333333333     0.529597288           0.4   0.343820151          0.2   0.43421471 0.888888889 1.35043108 0.8 1.35316112 0.533333333 1.95035689 0.2   0.353456767         0.6 2.82308158 0.866666667 2.12306767 0.714285714  2.49379564 0.142857143 0.439333312
                         0.466666667  3.65026892  0.428571429   1.47874248  0.466666667   1.34404919  0.0  -0.140351928 0.333333333     0.859826084   0.333333333   0.803958376  0.333333333  0.569104927 0.777777778 1.57671415 1.0 2.60286486 0.533333333  2.0686166 0.0   -1.21365884 0.666666667 2.55552079         0.8 2.89945514 0.714285714  2.36488639 0.285714286  1.41428386
                         0.466666667  2.04937001  0.571428571   0.90878341  0.533333333   1.04658181  0.2   0.241451024 0.333333333     0.378097949           0.4   0.364750081  0.133333333  0.322329824 0.666666667 1.65218611 0.8 1.93793206 0.666666667 1.70518721 0.2 0.00126933835 0.666666667 2.20208141 0.933333333 2.08038651 0.571428571   1.4039941 0.285714286  0.57818107
                         0.666666667  2.27803077  0.571428571   1.43248392  0.666666667   1.01542443  0.2   0.989176771 0.333333333    0.0327688723   0.266666667   0.742917005  0.266666667  0.692247623 0.888888889 1.70813819 1.0 1.49204546 0.533333333 1.76710083 0.0  -0.247371683 0.933333333 1.63840312         0.8 2.21083423 0.285714286  2.72865965 0.428571429 0.938636132
                         0.666666667  1.99437795  0.714285714  0.847532833  0.533333333  0.831622384  0.4   0.712211698 0.333333333      0.60095948           0.4    0.60247533          0.2  0.437287443 0.777777778 1.32221869 0.8 1.69595313 0.533333333 1.72321886 0.0  -0.354538113 0.666666667 2.81551915 0.933333333 2.23133105 0.428571429  2.02749729 0.285714286 0.862765838]

    XX = [0.58291082 0.77026    0.59999317 0.96146749 0.37977839 0.49701035 0.33833865 0.74275074 0.30049587 0.79878627 0.08594978 0.23566364 0.43816889 0.12604585 0.20303198
          0.84154274 0.37243245 0.21868173 0.84613282 0.57537467 0.63371648 0.88892854 0.71395906 0.26511267 0.00970831 0.54946346 0.70752623 0.80569461 0.19065633 0.63421428
          0.93855293 0.25818638 0.29248046 0.42564401 0.5711786  0.99005555 0.58819961 0.8878994  0.65621128 0.47277887 0.30554853 0.35017958 0.77713429 0.17750905 0.13793536
          0.21304496 0.66891344 0.37140495 0.20650268 0.3307044  0.08162956 0.43653555 0.81121598 0.44579246 0.44731015 0.02752846 0.27897767 0.0751705  0.04773838 0.86358558
          0.71431759 0.8304377  0.1329058  0.36528646 0.91321754 0.43338789 0.92565181 0.96136808 0.00660811 0.43293059 0.58311263 0.34882757 0.37603202 0.35582158 0.23103288
          0.02603724 0.731184   0.99851577 0.03834193 0.85909822 0.54430493 0.01951996 0.06881641 0.52544948 0.10456021 0.29599743 0.2748344  0.97060571 0.46966648 0.28518106
          0.93824209 0.96672667 0.71939988 0.13687903 0.88989899 0.44126029 0.78612738 0.72148873 0.65316408 0.76697313 0.81183026 0.46166154 0.48462061 0.09738624 0.37086277
          0.88613429 0.22027203 0.74891512 0.80662967 0.19656783 0.76460265 0.65734626 0.97545921 0.38829315 0.75675    0.84395362 0.37907264 0.22368808 0.3682424  0.65282988
          0.25738735 0.85849893 0.29519148 0.76403467 0.32104374 0.50432241 0.87418372 0.48539667 0.62418851 0.34280804 0.4685735  0.06141402 0.51976649 0.44915414 0.29898286
          0.17287711 0.34066372 0.29485052 0.3625377  0.80875406 0.89559956 0.91503332 0.42155562 0.89844751 0.58707759 0.9966111  0.12426284 0.75683156 0.58826857 0.51456602
          0.75821559 0.83328172 0.83108783 0.34411894 0.38067706 0.59528513 0.04287195 0.81470528 0.5860231  0.44350472 0.63813487 0.95535158 0.80421115 0.65614969 0.20754234
          0.97173602 0.38711375 0.90523631 0.50105462 0.67240828 0.88740297 0.05838575 0.29474664 0.17769359 0.04656562 0.34180828 0.91540073 0.25271628 0.11303782 0.94184494
          0.49331099 0.47179102 0.68784676 0.81708483 0.22690731 0.20235285 0.42449878 0.84759295 0.9271214  0.19040336 0.68945921 0.44586868 0.87811028 0.2956111  0.27020385
          0.02193189 0.87135088 0.16605978 0.2785312  0.2463312  0.92205218 0.08162816 0.33665844 0.68043503 0.16556516 0.5776585  0.42465708 0.01314008 0.60660289 0.34691688
          0.2115269  0.97515003 0.83898221 0.44870931 0.32124904 0.01409788 0.72806984 0.26632355 0.51168995 0.62601907 0.75290599 0.15814617 0.09131661 0.77406715 0.05145793]

    weights   = [0.52762177, -0.0418873, 0.2471347, -1.31156877, -0.7247638, -0.78220244, -1.63412477, 2.7437687, -0.46801041, 0.01399379, 1.43003853, -0.68828345, 1.79152578, -0.19943179, -0.12082104, -0.18071698, -0.06975319, -0.47113781, 0.78166691, -0.84304843, 0.40557851, -1.27548192, 0.5544292, 0.44486959, -0.76179568, -0.84353163, -0.27708717, 0.05488085, 0.93928732, 0.81888716, -0.06003624, 1.42705634, -1.65799853, -1.03679063, -0.92473863, 0.80497937, -0.45438938, 1.91288138, 0.30939407, -0.22241857, -0.78292932, 0.62495391, -0.08524614, 0.18349484, -0.16950302, -0.60015582, -0.02692903, -0.56489894, 1.2632381, 0.74928421, 0.13981419, -0.25654669, 0.31853533, 0.04552576, -0.12017115, -1.26448862, -0.93308081, 1.32112779, -0.48612077, 0.68934027, -0.64064021, 0.42020047, 0.29536018, -0.919411, 0.64127106, -1.0641436, -0.31604487, -0.26644779, 1.58622318, -0.05704011, 0.36556408, -0.2481109, 0.60494258, 0.81612145, 0.83206467, -0.72643367, -0.13443512, -0.08208581, 0.09331525, -1.41730465, 1.06946835, -1.01957853, -0.03607454, 0.30114602, -2.20579273, 0.62166328, -0.1753795, 0.89379478, 1.76691169, -1.20234354, -1.28683233, -0.34219971, -1.06585416, -0.00949176, 0.89073309, 0.61441468, 0.35051293, 0.68524821, 0.13848917, 0.25151074, -0.22653086, -0.51363513, -1.01036993, -1.41547553, 0.32466544, 1.0371033, 1.47076476, 0.10694709, -0.75073608, 2.03104583, -0.51633515, 0.35914072, 0.74269627, -0.7995558, -1.0662558, 1.92427295, -0.67610275, -0.78531807, 0.48564705, -2.31143814, 0.02183875, 0.72847231, -0.58188375, 1.19451164, -0.85269623, 0.85391231, 0.82931092, -0.11102697, 1.39071293, -0.88898299, -0.52789062, 0.74821341, -1.44155276]
    lengths   = Int32[11, 9, 11, 11, 7, 9, 7, 7, 11, 7, 11, 7, 7, 9, 9]
    biases    = [0.68675053, 0.092913, 0.13270275, -0.79834545, -0.10765975, -0.28003361, -0.33196979, 0.62634105, 0.87208684, 0.05435767, -0.80174301, 0.45357874, 0.68722719, 0.28728044, -0.46194353]
    dilations = Int32[1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1]
    paddings  = Int32[5, 0, 5, 0, 0, 4, 3, 0, 0, 6, 0, 3, 3, 0, 0]
    kernel = (weights, lengths, biases, dilations, paddings)

    @test  apply_kernels_ans≈ MLJTime.apply_kernels(XX,  kernel)

    #First call to the apply_kernel from apply_kernels above
    _X = [0.58291082, 0.77026, 0.59999317, 0.96146749, 0.37977839, 0.49701035, 0.33833865, 0.74275074, 0.30049587, 0.79878627, 0.08594978, 0.23566364, 0.43816889, 0.12604585, 0.20303198]
    _W = [0.52762177, -0.0418873, 0.2471347, -1.31156877, -0.7247638, -0.78220244, -1.63412477, 2.7437687, -0.46801041, 0.01399379, 1.43003853]
    _b = 0.68675053
    _l = Int32(11)
    _d = Int32(1)
    _p = Int32(5)

    a1, b1 = MLJTime.apply_kernel(_X, _W, _l, _b, _d, _p)
    @test [a1, b1] ≈ [0.4666666666666667, 1.8691506816260883]
    weights, lengths, biases, dilations, paddings = MLJTime.generate_kernels(15, 15, 7)

    @test weights ≈ [0.20946987493470082, -0.021718758503254144, -0.35951714229923665, 0.17766188099745459, 0.40425359989114706, 0.9886081558231362, -0.7235728429911245, -0.7135888321389559, -1.2907160470203496, 0.8154160336360065, 0.5137040776704755, 0.26705111541213455, 0.47480026067660186, -0.197433071782658, 0.8514380635347026, -1.1617410473217324, -0.5431985964128231, 1.5337553835792397, -0.9629980600363045, -0.3973236396398957, -0.5189584581534508, 0.6546080501441861, 1.1208914028438155, -0.9332987829367986, -1.2557000343846472, 1.97997778832397, -0.8032049044041798, -1.4914342896826653, -1.105116662846912, 2.2640505338150367, 0.22383494927238068, -0.8229957681968434, 0.40361938080221244, -0.09327281427504056, -0.38282837155719585, -0.006372117026678892, 0.37582940303743456, -1.3496111434628901, 1.0940947490566022, 0.8910453473847659, 1.3020851484712181, -1.4115938142335838, -1.8726707563013845, -0.5848275170017244, 0.7431312211457688, 0.002465333213452936, -1.3981813569061972, 0.6561763106662478, 0.39852633887157674, 1.979348393298065, -0.9644818569568242, 0.9115730204189727, 0.12894086955204645, 1.718847157480878, 0.4955071820760768, 0.9188853578634907, -0.07067906593016868, 1.1847939270970322, -0.6229087888143605, -1.9185289193095396, -1.017424876293943, -0.6884919741694657, 0.652572062227571, -0.418483589977059, 1.1648263125150844, 0.12294055598670936, -0.22819443867015932, -1.0030830431507949, 0.4664791719419216, -0.341923305037045, -0.41513372583622815, -0.94524137793961, -1.2667442495182606, 1.6670739764664197, 0.11812368259705572, -0.22024569176706776, 0.8950805784363284, -0.7244193234267298, -0.7005788090737236, 0.6733433052776924, 0.6960649140820706, -0.19245700513417496, -2.348695501162304, 0.37730101924239223, 0.7052894414572141, -0.0931194561563581, 0.09121605364122187, -0.28375281929574153, -0.3388894308598973, 0.6268529843735299, 1.2637977087599426, 0.1965496693210121, 0.07924973428707299, -0.5010732418408879, -0.5736084100456836, -0.43274047658426484, 2.3133118468919385, -1.0816891220291873, 0.007095451682842702, -0.4368638452825783, -0.9533895065804225, 1.34448396464174, 0.7536292293935183, -0.5632524121470226, 0.18769651463338782, 0.24964568420867894, -0.5890450805501444, -1.5305063517644388, 0.848617318611738, -0.5771588150162538, -0.15434029777233785, -0.5069098623945345, 2.1842911895575816, -0.2639931812217544, 1.2668523211590947, -0.22196659877176117, 1.0512934657270945, -0.8346988959485406, -0.34305368115640067, -0.4339573550589728, -0.26061000823313407, -1.5832393795793775, 1.3593801318619982, -0.7638210991522643, 0.19341078852347915, 1.258420261976951, 1.2735382514792994, -0.8461291933410995, -1.4807043315046715, 0.3652853220183056, -1.234523036665802, 0.8729394696506795, 0.2788889225292732, -2.100613545364331, 0.2776841973243349, 1.047318794033346, 0.8583051984924995]
    @test lengths ≈ Int32[11, 11, 9, 11, 11, 9, 9, 11, 9, 7, 9, 7, 9, 7, 7]
    @test biases ≈ [-0.6035360765327771, 0.27249020484592235, 0.232263762639199, 0.417408084884888, -0.9926165669796312, 0.9531982209784409, 0.4176193131947299, 0.6251074449871927, -0.7788867556531662, 0.10914409688356663, 0.9935072895394153, 0.8385655813087447, -0.9835519116179752, 0.9193276717480652, -0.4225756505399385]
    @test dilations ≈ Int32[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2]
    @test paddings ≈ Int32[0, 5, 4, 0, 5, 4, 4, 5, 4, 0, 4, 0, 0, 3, 0]
end

#=

=#


text:
@enum Action UP=1 DOWN LEFT RIGHT

const actionspace = [UP, DOWN, LEFT, RIGHT]
const actions = ["↑", "↓", "←", "→"] # alias

const MOVEMENTS = Dict(
    UP    => State(0, 1),
    DOWN  => State(0, -1),
    LEFT  => State(-1, 0),
    RIGHT => State(1, 0)
)

# State Transition Function
@inline Base.:+(s1::State, s2::State)::State = State(s1.x + s2.x, s1.y + s2.y);

# Reward Function
function reward(g::Grid, s::State)::Real
    return inbounds(g, s) ? g[s.x, s.y] : 0;
end

# Transition Function
function transition(g::Grid, s::State, a::Action)
    if reward(g, s) != 0 # reached a terminal state
        return Deterministic(g.null_state);
    end

    N = length(actionspace)
    next_states = Vector{State}(undef, N+1)
    probabilities = zeros(N+1)
    p_transition = g.p_transition

    for (i, a′) in enumerate(actionspace)
        prob = (a′ == a) ? p_transition : (1 - p_transition) / (N - 1)
        destination = s + MOVEMENTS[a′]
        next_states[i+1] = destination
        if inbounds(g, destination)
            probabilities[i+1] += prob
        end
    end

    # handle out of bounds transitions
    next_states[1] = s
    probabilities[1] = 1 - sum(probabilities)

    return SparseCat(next_states, probabilities);
end

# Terminal State: Goal, Error, Out of Bounds
@inline terminal(g::Grid, s::State)::Bool = s == g.null_state;

max_stars_repo_name: Joshua-Robison/GridWorld

max_issues_repo_name: Joshua-Robison/GridWorld

max_forks_repo_name: Joshua-Robison/GridWorld


text:
# This file contains functions related to reading, writing and displaying a grid and experimental results

using JuMP
using Plots
using Printf
import GR

"""
Read an instance from an input file

- Argument:
inputFile: path of the input file
"""
function readInputFile(inputFile::String)

    # Open the input file
    datafile = open(inputFile)

    data = readlines(datafile)
    close(datafile)

    n=length(split(data[1],","))
    t=Array{Int64}(undef,n,n)

    lineNb=1
    # For each line of the input file
    for line in data
        lineSplit=split(line,",")
        if size(lineSplit,1)==n
            for colNb in 1:n
                if lineSplit[colNb] != " "
#                     println(lineSplit[colNb])
                    t[lineNb,colNb]=parse(Int64,lineSplit[colNb])
                else
                    t[lineNb,colNb]=0
                end
            end
        end
        lineNb+=1
    end
    return t
end

"""
Display a grid represented by a 2-dimensional array

Argument:
- t: array of size n*n with values in [0, n] (0 if the cell is empty)
"""
function displayGrid(t::Array{Int64, 2})

    n = size(t, 1)

    # Display the upper border of the grid
    println(" ", "-"^(3*n))

    # For each cell (l, c)
    for l in 1:n
        print("|")
        for c in 1:n

            if t[l, c] == 0
                print(" -")
            else
                if t[l, c] < 10
                    print(" ")
                end

                print(t[l, c])
            end
            print(" ")
        end
        println("|")
    end
    println(" ", "-"^(3*n))
end

"""
Display cplex solution

Argument
- x: 2-dimensional variables array such that x[i, j] = 1 if cell (i, j) is white
"""
function displaySolution(x::Array{VariableRef,2})

    n = size(x, 1)

    # Display the upper border of the grid
    println(" ", "-"^(3*n-2))

    # For each cell (l, c)
    for l in 1:n
        print("| ")
        for c in 1:n
            @printf("%d",JuMP.value(x[l, c]))

            print(" ")
        end
        println("|")
    end
    println(" ", "-"^(3*n-2))
end

"""
Create a pdf file which contains a performance diagram associated to the results of the ../res folder
Display one curve for each subfolder of the ../res folder.

Arguments
- outputFile: path of the output file

Prerequisites:
- Each subfolder must contain text files
- Each text file correspond to the resolution of one instance
- Each text file contains a variable "solveTime" and a variable "isOptimal"
"""
function performanceDiagram(outputFile::String)

    resultFolder = "../res/"

    # Maximal number of files in a subfolder
    maxSize = 0

    # Number of subfolders
    subfolderCount = 0

    folderName = Array{String, 1}()

    # For each file in the result folder
    for file in readdir(resultFolder)

        path = resultFolder * file

        # If it is a subfolder
        if isdir(path)

            folderName = vcat(folderName, file)

            subfolderCount += 1
            folderSize = size(readdir(path), 1)

            if maxSize < folderSize
                maxSize = folderSize
            end
        end
    end

    # Array that will contain the resolution times (one line for each subfolder)
    results = Array{Float64}(undef, subfolderCount, maxSize)

    for i in 1:subfolderCount
        for j in 1:maxSize
            results[i, j] = Inf
        end
    end

    folderCount = 0
    maxSolveTime = 0

    # For each subfolder
    for file in readdir(resultFolder)

        path = resultFolder * file

        if isdir(path)

            folderCount += 1
            fileCount = 0

            # For each text file in the subfolder
            for resultFile in filter(x->occursin(".txt", x), readdir(path))

                fileCount += 1
                include(path * "/" * resultFile)

                if isOptimal
                    results[folderCount, fileCount] = solveTime

                    if solveTime > maxSolveTime
                        maxSolveTime = solveTime
                    end
                end
            end
        end
    end

    # Sort each row increasingly
    results = sort(results, dims=2)

    println("Max solve time: ", maxSolveTime)
    # For each line to plot
    for dim in 1: size(results, 1)

        x = Array{Float64, 1}()
        y = Array{Float64, 1}()

        # x coordinate of the previous inflexion point
        previousX = 0
        previousY = 0

        append!(x, previousX)
        append!(y, previousY)

        # Current position in the line
        currentId = 1

       # While the end of the line is not reached
        while currentId < size(results, 2) && results[dim, currentId] != Inf

            # Number of elements which have the value previousX
            identicalValues = 1

             # While the value is the same
            while currentId <= size(results, 2) && results[dim, currentId] == previousX
                currentId += 1
                identicalValues += 1
            end
            println("id ",currentId)
            # Add the proper points
            append!(x, previousX)
            append!(y, currentId)
            if currentId <= size(results, 2)
                if results[dim, currentId] != Inf
                    append!(x, results[dim, currentId])
                    append!(y, currentId)
                end

                previousX = results[dim, currentId]
                previousY = currentId
            end
        end

        append!(x, maxSolveTime)
        append!(y, currentId)
        println(y)
        # If it is the first subfolder
        if dim == 1

            # Draw a new plot
            plot(x, y, label = folderName[dim], legend = :bottomright, xaxis = "Time (s)", yaxis = "Solved instances",linewidth=3)

        # Otherwise
        else
            # Add the new curve to the created plot
            savefig(plot!(x, y, label = folderName[dim], linewidth=3), outputFile)
        end
    end
end

"""
Create a latex file which contains an array with the results of the ../res folder.
Each subfolder of the ../res folder contains the results of a resolution method.

Arguments
- outputFile: path of the output file

Prerequisites:
- Each subfolder must contain text files
- Each text file correspond to the resolution of one instance
- Each text file contains a variable "solveTime" and a variable "isOptimal"
"""
function resultsArray(outputFile::String)

    resultFolder = "../res/"
    dataFolder = "../data/"

    # Maximal number of files in a subfolder
    maxSize = 0

    # Number of subfolders
    subfolderCount = 0

    # Open the latex output file
    fout = open(outputFile, "w")

    # Print the latex file output
    println(fout, raw"""\documentclass{article}

\usepackage[french]{babel}
\usepackage [utf8] {inputenc} % utf-8 / latin1
\usepackage{multicol}

\setlength{\hoffset}{-18pt}
\setlength{\oddsidemargin}{0pt} % Marge gauche sur pages impaires
\setlength{\evensidemargin}{9pt} % Marge gauche sur pages paires
\setlength{\marginparwidth}{54pt} % Largeur de note dans la marge
\setlength{\textwidth}{481pt} % Largeur de la zone de texte (17cm)
\setlength{\voffset}{-18pt} % Bon pour DOS
\setlength{\marginparsep}{7pt} % Séparation de la marge
\setlength{\topmargin}{0pt} % Pas de marge en haut
\setlength{\headheight}{13pt} % Haut de page
\setlength{\headsep}{10pt} % Entre le haut de page et le texte
\setlength{\footskip}{27pt} % Bas de page + séparation
\setlength{\textheight}{668pt} % Hauteur de la zone de texte (25cm)

\begin{document}""")

    header = raw"""
\begin{center}
\renewcommand{\arraystretch}{1.4}
 \begin{tabular}{l"""

    # Name of the subfolder of the result folder (i.e, the resolution methods used)
    folderName = Array{String, 1}()

    # List of all the instances solved by at least one resolution method
    solvedInstances = Array{String, 1}()

    # For each file in the result folder
    for file in readdir(resultFolder)

        path = resultFolder * file

        # If it is a subfolder
        if isdir(path)

            # Add its name to the folder list
            folderName = vcat(folderName, file)

            subfolderCount += 1
            folderSize = size(readdir(path), 1)

            # Add all its files in the solvedInstances array
            for file2 in filter(x->occursin(".txt", x), readdir(path))
                solvedInstances = vcat(solvedInstances, file2)
            end

            if maxSize < folderSize
                maxSize = folderSize
            end
        end
    end

    # Only keep one string for each instance solved
    unique(solvedInstances)

    # For each resolution method, add two columns in the array
    for folder in folderName
        header *= "rr"
    end

    header *= "}\n\t\\hline\n"

    # Create the header line which contains the methods name
    for folder in folderName
        header *= " & \\multicolumn{2}{c}{\\textbf{" * folder * "}}"
    end

    header *= "\\\\\n\\textbf{Instance} "

    # Create the second header line with the content of the result columns
    for folder in folderName
        header *= " & \\textbf{Temps (s)} & \\textbf{Optimal ?} "
    end

    header *= "\\\\\\hline\n"

    footer = raw"""\hline\end{tabular}
\end{center}

"""
    println(fout, header)

    # On each page an array will contain at most maxInstancePerPage lines with results
    maxInstancePerPage = 30
    id = 1

    # For each solved files
    for solvedInstance in solvedInstances

        # If we do not start a new array on a new page
        if rem(id, maxInstancePerPage) == 0
            println(fout, footer, "\\newpage")
            println(fout, header)
        end

        # Replace the potential underscores '_' in file names
        print(fout, replace(solvedInstance, "_" => "\\_"))

        # For each resolution method
        for method in folderName

            path = resultFolder * method * "/" * solvedInstance

            # If the instance has been solved by this method
            if isfile(path)

                include(path)

                println(fout, " & ", round(solveTime, digits=2), " & ")

                if isOptimal
                    println(fout, "\$\\times\$")
                end

            # If the instance has not been solved by this method
            else
                println(fout, " & - & - ")
            end
        end

        println(fout, "\\\\")

        id += 1
    end

    # Print the end of the latex file
    println(fout, footer)

    println(fout, "\\end{document}")

    close(fout)

end
"""
Save a grid in a text file

Argument
- t: 2-dimensional array of size n*n
- outputFile: path of the output file
"""
function saveInstance(t::Array{Int64, 2}, outputFile::String)

    n = size(t, 1)

    # Open the output file
    writer = open(outputFile, "w")

    # For each cell (l, c) of the grid
    for l in 1:n
        for c in 1:n

            # Write its value
            if t[l, c] == 0
                print(writer, " ")
            else
                print(writer, t[l, c])
            end

            if c != n
                print(writer, ",")
            else
                println(writer, "")
            end
        end
    end

    close(writer)

end

"""
Write a solution in an output stream

Arguments
- fout: the output stream (usually an output file)
- x: 2-dimensional variables array, x[i,j]==1 if the cell is white, otherwise x[i,j]=0
"""
function writeSolution(fout::IOStream, x::Array{VariableRef,2})

    # Convert the solution from x[i, j, k] variables into t[i, j] variables
    n = size(x, 1)
    t = Array{Int64}(undef, n, n)

    for l in 1:n
        for c in 1:n
            t[l, c] = Int(JuMP.value(x[l,c]))
        end
    end

    # Write the solution
    writeSolution(fout, t)

end

"""
Write a solution in an output stream

Arguments
- fout: the output stream (usually an output file)
- x: 2-dimensional variables array, x[i,j]==1 if the cell is white, otherwise x[i,j]=0
"""
function writeSolution(fout::IOStream, x::Array{Bool,2})

    # Convert the solution from x[i, j, k] variables into t[i, j] variables
    n = size(x, 1)
    t = Array{Int64}(undef, n, n)

    for l in 1:n
        for c in 1:n
            t[l, c] = x[l,c]
        end
    end

    # Write the solution
    writeSolution(fout, t)

end

"""
Write a solution in an output stream

Arguments
- fout: the output stream (usually an output file)
- t: 2-dimensional array of size n*n
"""
function writeSolution(fout::IOStream, t::Array{Int64, 2})

    println(fout, "t = [")
    n = size(t, 1)

    for l in 1:n

        print(fout, "[ ")

        for c in 1:n
            print(fout, string(t[l, c]) * " ")
        end

        endLine = "]"

        if l != n
            endLine *= ";"
        end

        println(fout, endLine)
    end

    println(fout, "]")
end


text:
using CUSPARSE
using CUDArt
using Base.Test

m = 25
n = 35
k = 10
blockdim = 5

###############
# test_bsrsv2 #
###############

function test_bsrsv2!(elty)
    A = rand(elty,m,m)
    A = triu(A)
    X = rand(elty,m)
    alpha = rand(elty)
    d_X = CudaArray(X)
    d_A = CudaSparseMatrixCSR(sparse(A))
    d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5))
    d_X = CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O')
    h_Y = to_host(d_X)
    Y = A\(alpha * X)
    @test_approx_eq(Y,h_Y)
    d_X = CudaArray(rand(elty,n))
    @test_throws(DimensionMismatch, CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O'))
    A = sparse(rand(elty,m,n))
    d_A = CudaSparseMatrixCSR(A)
    d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5))
    @test_throws(DimensionMismatch, CUSPARSE.sv2!('N','U',alpha,d_A,d_X,'O'))
end

function test_bsrsv2(elty)
    A = rand(elty,m,m)
    A = triu(A)
    X = rand(elty,m)
    alpha = rand(elty)
    d_X = CudaArray(X)
    d_A = CudaSparseMatrixCSR(sparse(A))
    d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5))
    d_Y = CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O')
    h_Y = to_host(d_Y)
    Y = A\(alpha * X)
    @test_approx_eq(Y,h_Y)
    d_Y = UpperTriangular(d_A)\d_X
    h_Y = to_host(d_Y)
    @test h_Y ≈ A\X
    A = sparse(rand(elty,m,n))
    d_A = CudaSparseMatrixCSR(A)
    d_A = CUSPARSE.switch2bsr(d_A, convert(Cint,5))
    @test_throws(DimensionMismatch, CUSPARSE.sv2('N','U',alpha,d_A,d_X,'O'))
end

types = [Float32,Float64,Complex64,Complex128]
for elty in types
    tic()
    test_bsrsv2!(elty)
    println("bsrsv2! took ", toq(), " for ", elty)
    tic()
    test_bsrsv2(elty)
    println("bsrsv2 took ", toq(), " for ", elty)
end


text:
"""
`SwitchEvidenceAccumulation_uncertainty(events, Prew, Psw, α; E1 = 0)`
events = Vector of Boolean indicating rewards or failures
Prew = P of reward
#Psw = P of switch
E1 = Evidence are calculated recursively, the first has to be given.
    After a reward the evidence of siwtch is 0
α = uncertainty,
"""

function SwitchEvidenceAccumulation_uncertainty(n_fail, Prew, Psw, α; E1 = 0)
    #n_fail = number of pokes
    #Prew = P of reward
    #Psw = P of switch
    #E1 = Evidence are calculated recursively, the first has to be given. After a reward the evidence of siwtch is 0
    #α = uncertainty
    Es = zeros(n_fail)
    Es[1] = E1
    for i = 2:n_fail
        Es[i] = (Es[i-1]+Psw)/((1-Prew)*(1-Psw))*α + (1-α)
    end
    return Es
end


text:
# This file is part of Kpax3. License is MIT.

function kpax3ga!(x::AminoAcidData,
                  population::AminoAcidStateList,
                  priorR::PriorRowPartition,
                  priorC::PriorColPartition,
                  settings::KSettings,
                  support::GASupport)
  if settings.verbose
    Printf.@printf("Initializing Genetic Algorithm... ")
  end

  # check if we can write to the backup file
  fp = open(settings.ofile, "w")
  close(fp)

  # elitism
  Nelite = max(1, ceil(Int, settings.popsize * 0.2))

  # randomization
  Nrand = Nelite + floor(Int, settings.popsize * 0.1)

  if ((settings.popsize - Nrand) % 2) != 0
    Nrand += 1
  end

  # initialize variables
  R = zeros(Int, support.n)

  i = 1
  maxk = 0
  idx = 0
  for i in 1:settings.popsize
    if population.state[i].k > maxk
      maxk = population.state[i].k
      idx = i
    end
  end

  beststate = copystate(population.state[population.rank[1]])

  newpopulation = AminoAcidStateList(settings.popsize, population.state[idx])

  if settings.verbose
    Printf.@printf("done\n")
    Printf.@printf("Current number of clusters: %d\n", beststate.k)
    Printf.@printf("Current log-posterior (plus a constant): %.4f\n",
                   beststate.logpp)
    Printf.@printf("Stochastic optimization is now running...\n")
  end

  iter = 0
  gap = 0
  keepgoing = true
  while keepgoing
    # copy the first Nelite best solutions without changing them
    i = 1
    while i <= Nelite
      copystate!(newpopulation.state[i], population.state[population.rank[i]])
      newpopulation.logpp[i] = population.logpp[population.rank[i]]
      i += 1
    end

    # now create Nrand random solutions starting from the best one
    while i <= Nrand
      copyto!(R, newpopulation.state[1].R)
      modifypartition!(R, newpopulation.state[1].k)

      newpopulation.state[i] = AminoAcidState(x.data, R, priorR, priorC,
                                              settings)
      newpopulation.logpp[i] = newpopulation.state[i].logpp

      i += 1
    end

    while i <= settings.popsize
      (i1, i2) = selection(population.logpp)

      if rand() <= settings.xrate
        crossover!(population.state[i1].R, population.state[i2].R, support)
      else
        copyto!(support.oi.R, population.state[i1].R)
        copyto!(support.oi.v, population.state[i1].v)

        copyto!(support.oj.R, population.state[i2].R)
        copyto!(support.oj.v, population.state[i2].v)
      end

      mutation!(support.oi, settings.mrate)
      mutation!(support.oj, settings.mrate)

      updatestate!(newpopulation.state[i], x.data, support.oi.R, priorR,
                   priorC, settings)
      updatestate!(newpopulation.state[i + 1], x.data, support.oj.R, priorR,
                   priorC, settings)

      newpopulation.logpp[i] = newpopulation.state[i].logpp
      newpopulation.logpp[i + 1] = newpopulation.state[i + 1].logpp

      i += 2
    end

    sortperm!(newpopulation.rank, newpopulation.logpp, rev=true,
              initialized=true)

    copystatelist!(population, newpopulation, settings.popsize)

    if population.logpp[population.rank[1]] >  beststate.logpp
      copystate!(beststate, population.state[population.rank[1]])
      gap = 0

      if settings.verbose
        Printf.@printf("Found a better solution! ")
        Printf.@printf("Log-posterior (plus a constant) for %d clusters: %.4f\n",
                       beststate.k, beststate.logpp)
      end
    else
      gap += 1
      keepgoing = (gap <= settings.maxgap)
    end

    iter += 1

    if iter < settings.maxiter
      if iter % settings.verbosestep == 0
        fp = open(settings.ofile, "w")
        for i in 1:support.n
          write(fp, "\"$(x.id[i])\",$(beststate.R[i])\n")
        end
        close(fp)

        if settings.verbose
          println("Step ", iter, " done")
        end
      end
    else
      keepgoing = false
    end
  end

  beststate
end

function kpax3ga(partition::Vector{Int},
                 settings::KSettings)
  x = AminoAcidData(settings)
  (m, n) = size(x.data)

  R = normalizepartition(partition, n)
  k = maximum(R)

  maxclust = min(n, max(k, settings.maxclust))

  priorR = EwensPitman(settings.α, settings.θ)
  priorC = AminoAcidPriorCol(x.data, settings.γ, settings.r)

  population = AminoAcidStateList(x.data, R, priorR, priorC, settings)

  support = GASupport(m, n)

  kpax3ga!(x, population, priorR, priorC, settings, support)
end

function kpax3ga(x::AminoAcidData,
                 partition::Vector{Int},
                 settings::KSettings)
  (m, n) = size(x.data)

  R = normalizepartition(partition, n)
  k = maximum(R)

  maxclust = min(n, max(k, settings.maxclust))

  priorR = EwensPitman(settings.α, settings.θ)
  priorC = AminoAcidPriorCol(x.data, settings.γ, settings.r)

  population = AminoAcidStateList(x.data, R, priorR, priorC, settings)

  support = GASupport(m, n)

  kpax3ga!(x, population, priorR, priorC, settings, support)
end

function kpax3ga(partition::String,
                 settings::KSettings)
  x = AminoAcidData(settings)
  (m, n) = size(x.data)

  R = normalizepartition(partition, x.id)
  k = maximum(R)

  maxclust = min(n, max(k, settings.maxclust))

  priorR = EwensPitman(settings.α, settings.θ)
  priorC = AminoAcidPriorCol(x.data, settings.γ, settings.r)

  population = AminoAcidStateList(x.data, R, priorR, priorC, settings)

  support = GASupport(m, n)

  kpax3ga!(x, population, priorR, priorC, settings, support)
end

function kpax3ga(x::AminoAcidData,
                 partition::String,
                 settings::KSettings)
  (m, n) = size(x.data)

  R = normalizepartition(partition, x.id)
  k = maximum(R)

  maxclust = min(n, max(k, settings.maxclust))

  priorR = EwensPitman(settings.α, settings.θ)
  priorC = AminoAcidPriorCol(x.data, settings.γ, settings.r)

  population = AminoAcidStateList(x.data, R, priorR, priorC, settings)

  support = GASupport(m, n)

  kpax3ga!(x, population, priorR, priorC, settings, support)
end


text:
const m = m_B + m_w + m_fs + 2m_f + 2m_s + 2m_t + m_k + m_RG + 2m_OA

function kinetic_energy(
    u,
    w,
    θ′,
    θ_t = θ_t,
    θ′_t = θ′_t,
    θ_k = θ_k,
    θ′_k = θ′_k,
    γ_OA = γ_OA,
    γ′_OA = γ′_OA,
)
    V_B0 = SA[u, w]

    V_RG = V_B0 + crossθ(θ′, r_RG)
    T_RG = 0.5 * dot(V_RG, V_RG) * m_RG

    V_w = V_B0 + r′_w(θ_t, θ′_t) + crossθ(θ′, r_w(θ_t))
    T_w = 0.5 * dot(V_w, V_w) * m_w

    V_f = V_B0 + crossθ(θ′, r_SB)
    T_fs = 0.5 * dot(V_f, V_f) * m_fs
    T_f = 0.5 * dot(V_f, V_f) * m_f

    V_s_const = V_B0 + crossθ(θ′, r_SB) + crossθ(θ′ - θ′_s(θ_t, θ′_t), r_s_const)
    V_s_∂l_s = crossθ(θ′ - θ′_s(θ_t, θ′_t), r_s_∂l_s(θ_t))
    T_s =
        0.5m_s * (
            dot(V_s_const, V_s_const) +
            2dot(V_s_const, V_s_∂l_s) * 0.5l_s +
            dot(V_s_∂l_s, V_s_∂l_s) * l_s^2 / 3
        )

    V_t_const =
        V_B0 + r′_w(θ_t, θ′_t) + crossθ(θ′, r_w(θ_t)) + crossθ(θ′, r_t_const(θ_t)) + crossθ(θ′_t, r_t_const(θ_t))
    V_t_∂l_t = crossθ(θ′ + θ′_t, r_t_∂l_t(θ_t))
    T_t =
        0.5m_t * (
            dot(V_t_const, V_t_const) +
            2dot(V_t_const, V_t_∂l_t) * 0.5l_t +
            dot(V_t_∂l_t, V_t_∂l_t) * l_t^2 / 3
        )

    V_k_const =
        V_B0 + r′_w(θ_t, θ′_t) + crossθ(θ′, r_w(θ_t)) + crossθ(θ′, r_k_const(θ_t)) + crossθ(θ′_k, r_k_const(θ_t))

    V_k_∂l_k = crossθ(θ′ + θ′_k, r_k_∂l_k(θ_k))
    T_k =
        0.5m_k * (
            dot(V_k_const, V_k_const) +
            2dot(V_k_const, V_k_∂l_k) * 0.5l_k +
            dot(V_k_∂l_k, V_k_∂l_k) * l_k^2 / 3
        )

    # V_OA = V_B0 +- γ′_OA x r_OA + θ′ x r_OA
    V_OA_XZ_const = V_B0 + SA[-γ′_OA*y_OA_const, 0]
    V_OA_XZ_∂l_OA = crossθ(θ′, SA[x_OA_∂l_OA(γ_OA), 0]) + SA[-γ′_OA*y_OA_∂l_OA(γ_OA), 0]
    V_OA_Y_∂l_OA = γ′_OA * x_OA_∂l_OA(γ_OA)
    V_OA_const = SA[V_OA_XZ_const[1], 0, V_OA_XZ_const[2]]
    V_OA_∂l_OA = SA[V_OA_XZ_∂l_OA[1], V_OA_Y_∂l_OA, V_OA_XZ_∂l_OA[2]]
    T_OA =
        0.5m_OA * (
            dot(V_OA_const, V_OA_const) +
            2dot(V_OA_const, V_OA_∂l_OA) * 0.5(l_OAMX + l_OAMN) +
            dot(V_OA_∂l_OA, V_OA_∂l_OA) * (l_OAMX^2 + l_OAMX * l_OAMN + l_OAMN^2) / 3
        )

    T_B = 0.5m_B * (u^2 + w^2) + 0.5J_By * θ′^2

    T_B + T_RG + T_w + T_fs + 2T_f + 2T_s + 2T_t + T_k + 2T_OA
end


text:
using LightXML

dialog = [("April", "Bubbly: I'm > Tam and <= Emily"),
          ("Tam O'Shanter", "Burns: \"When chapman billies leave the street ...\""),
          ("Emily", "Short & shrift")]

const xdoc = XMLDocument()
const xroot = create_root(xdoc, "CharacterRemarks")

for (name, remarks) in dialog
    xs1 = new_child(xroot, "Character")
    set_attribute(xs1, "name", name)
    add_text(xs1, remarks)
end

println(xdoc)

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
module Actors

using ..WalksBase: get_nsteps, get_time, get_position
using ..Points: get_x, norm_squared
using ..LatticeVars: get_num_sites_visited
import ..LatticeVars: init!
using EmpiricalCDFs
import EmpiricalCDFs: get_data
import Statistics
export AbstractActor, act!, ActorSet, NullActor, StepLimitActor, ErrorOnExitActor, FirstReturnActor,
    get_actor_value

export ActorExitException

export StoredValues, StoringActor, init!, storing_position_actor,
    storing_num_sites_visited_actor, get_times, get_ecdf_times, get_values,
    get_stored_values, storing_nsteps_actor, storing_nsteps_position_actor,
    storing_nsteps_num_sites_visited_actor, storing_msd_actor

export CountActor, get_count, CountLimitException, check_counter
export ECDFsActor, get_cdfs, ECDFActor, ECDFValueActor, get_cdf, unpack, prune
export SampleLoopActor, get_actor, ProgressIter

###
### AbstractActor
###

abstract type AbstractActor end

init!(_::AbstractActor) = nothing
finalize!(_::AbstractActor) = nothing
condition_satisfied(_::AbstractActor) = true
# Following makes detecting bugs harder. Leave here to avoid temptation.
# act!(_::AbstractActor, args...) = true

###
### NullActor
###

struct NullActor <: AbstractActor
end
act!(_::NullActor, args...) = true

###
### StepLimitActor
###

mutable struct StepLimitActor <: AbstractActor
    max_step_limit::Int
    hit_max_step_limit::Bool
    StepLimitActor(n=10) = new(n, false)
end

function act!(actor::StepLimitActor, latwalk)
    nsteps = get_nsteps(latwalk)
    if nsteps >= actor.max_step_limit
        actor.hit_max_step_limit = true
        return false
    end
    return true
end

init!(actor::StepLimitActor) = (actor.hit_max_step_limit = false; nothing)
condition_satisfied(actor::StepLimitActor) = actor.hit_max_step_limit

function Base.show(io::IO, actor::StepLimitActor)
    print(io, "StepLimitActor(n=", actor.max_step_limit,
          ", hit=", actor.hit_max_step_limit, ")")
end

###
### ErrorOnExitActor
###

struct ActorExitException{T} <: Exception
    actor::T
    msg::String
end

ActorExitException(actor::T) where {T} = ActorExitException(actor, "actor of type $T exited")
Base.showerror(io::IO, e::ActorExitException) = print(io, e.msg)

struct ErrorOnExitActor{T <: AbstractActor} <: AbstractActor
    child_actor::T
end

for f  in (:init!, :condition_satisfied)
    @eval ($f)(actor::ErrorOnExitActor, args...) = ($f)(actor.child_actor, args...)
end

function act!(actor::ErrorOnExitActor, arg)
    if ! act!(actor.child_actor, arg)
        throw(ActorExitException(actor.child_actor))
    end
    return true
end

###
### CountActor
###

mutable struct Counter
    c::Int
end
Counter() = Counter(0)
init!(counter::Counter) = counter.c = 0
increment(counter::Counter) = counter.c += 1
get_count(counter::Counter) = counter.c

struct CountActor{F} <: AbstractActor
    counter::Counter
    counting_func::F
end

function CountActor(child_actor::AbstractActor)
    CountActor(Counter(), () -> condition_satisfied(child_actor))
end

for f in (:increment, :get_count, :init!)
    @eval ($f)(actor::CountActor, args...) = ($f)(actor.counter, args...)
end
get_actor_value(actor::CountActor) = get_count(actor.counter)

function act!(actor::CountActor, _system)
    if actor.counting_func()
        increment(actor.counter)
    end
    return true
end

###
### CountLimitException
###

struct CountLimitException <: Exception
    msg::String
end

Base.showerror(io::IO, e::CountLimitException) = print(io, e.msg)

function check_counter(actor::CountActor, msg=""; max_count = 0)
    if get_actor_value(actor) > max_count
        throw(CountLimitException(string(msg, " CountActor made ", get_actor_value(actor), " counts. ",
                                         "Maximum allowed $max_count")))
    end
    return true
end

###
### FirstReturnActor
###

"""
    FirstReturnActor <: AbstractActor

Records and returns `true`, and the step number if the position is the origin.
"""
mutable struct FirstReturnActor <: AbstractActor
    return_step_num::Int
    has_walker_returned::Bool
end

FirstReturnActor() = FirstReturnActor(0, false)

init!(actor::FirstReturnActor) = (actor.has_walker_returned = false; actor.return_step_num = 0; nothing)

function act!(actor::FirstReturnActor, system)
    iszero(get_position(system)) || return true
    actor.has_walker_returned = true
    actor.return_step_num = get_nsteps(system)
    return false
end

condition_satisfied(actor::FirstReturnActor) = actor.has_walker_returned
get_actor_value(actor::FirstReturnActor) = actor.return_step_num

###
### ActorSet
###

"""
    struct ActorSet

A set of several `Actors` to be applied sequentially.
If one of the set returns `false`, then `ActorSet` immediately returns false.
"""
struct ActorSet{T <: Tuple} <: AbstractActor
    actors::T
end

ActorSet(child_actors::AbstractActor...) = ActorSet((child_actors...,))
ActorSet(child_actor::AbstractActor) = ActorSet((child_actor,))
init!(actor_set::ActorSet) = foreach(actor -> init!(actor), actor_set.actors)

function act!(actor_set::ActorSet, args...)
    for actor in actor_set.actors
        act!(actor, args...)::Bool || return false
    end
    return true
end

###
### StoredValues
###

"""
    mutable struct StoredValues{T, X}

Stores the data for `StoringActor`
"""
mutable struct StoredValues{T, X}
    times::T
    values::X
    current_index::Int
end

Base.getindex(sv::StoredValues, ind1, ind2) = sv.values[ind2][ind1]

# FIXME: used to work
# Base.show(io::IO, sv::StoredValues) = Base.show(io, MIME("text/plain"), sv)
# function Base.show(io::IO, m::typeof(MIME("text/plain")), sv::StoredValues{T}) where T
#                    println(io, "StoredValues{times_type=$T}(current_index=", sv.current_index, ")")
#                    maxind = length(sv.values[1])
#     show(io, m, [sv.times[1:maxind] (x[1:maxind] for x in sv.values)... ])
# end

get_target_time(sv::StoredValues) = sv.times[sv.current_index]
increment_current_index(sv::StoredValues) = sv.current_index += 1
Base.lastindex(sv::StoredValues) = lastindex(sv.times)
get_current_index(sv::StoredValues) = sv.current_index
reset_current_index!(sv::StoredValues) = sv.current_index = 1
get_values(sv::StoredValues) = sv.values
get_times(sv::StoredValues) = sv.times

Base.empty!(sv::StoredValues) = empty!(sv.values)

function Base.empty!(sv::StoredValues{<:Any, <:Tuple})
    for v in sv.values
        empty!(v)
    end
end

StoredValues(times; value_types = Float64) = _StoredValues(times, value_types)

function _StoredValues(times::T, value_types) where T
    initial_index = 1
    return StoredValues{T, Vector{value_types}}(times, zeros(value_types,0), initial_index)
end

function _StoredValues(times::T, value_types::Tuple) where T
    initial_index = 1
    tup = ((zeros(t,0) for t in value_types)...,)
    return StoredValues{T, typeof(tup)}(times, tup, initial_index)
end

###
### StoringActor
###

struct StoringActor{T, X, F} <: AbstractActor
    stored_values::StoredValues{T, X}
    storing_func::F
end

StoringActor(times, storing_func; value_types=Float64) = StoringActor(times, storing_func, value_types)
StoringActor(times, storing_func, value_types) = StoringActor(StoredValues(times; value_types=value_types), storing_func)
StoringActor(times, storing_func::Tuple, value_types::Tuple) = StoringActor(StoredValues(times; value_types=value_types), storing_func)

function act!(actor::StoringActor, system)
    stored_values = actor.stored_values
    get_current_index(stored_values) > lastindex(stored_values) && return false # terminate walk
    while get_time(system) >= get_target_time(stored_values)
        push!(stored_values.values, actor.storing_func(system))
        increment_current_index(stored_values)
        get_current_index(stored_values) > lastindex(stored_values) && return false # terminate walk
    end
    return true
end

function act!(actor::StoringActor{T, <:Tuple, <:Tuple}, system) where T
    get_current_index(actor.stored_values) > lastindex(actor.stored_values) && return false # terminate walk
    while get_time(system) >= get_target_time(actor.stored_values)
        for (array, func) in zip(actor.stored_values.values, actor.storing_func)
            push!(array, func(system))
        end
        increment_current_index(actor.stored_values)
        get_current_index(actor.stored_values) > lastindex(actor.stored_values) && return false # terminate walk
    end
    return true
end

function init!(actor::StoringActor)
    reset_current_index!(actor.stored_values)
    empty!(actor.stored_values)
    return nothing
end

for f in (:get_values, :get_times)
    @eval ($f)(sa::StoringActor) = ($f)(sa.stored_values)
end
get_stored_values(sa::StoringActor) = sa.stored_values

Base.getindex(sa::StoringActor, ind1::Integer, inds...) = _getindex(sa, Val(ind1), inds...)
Base.getindex(sa::StoringActor, ind1::Integer) = _getindex(sa, Val(ind1))
_getindex(sa::StoringActor, ::Val{1}, inds...) = get_times(sa)[inds...]
_getindex(sa::StoringActor, ::Val{n}, inds...) where {n} = get_values(sa)[n-1][inds...]
_getindex(sa::StoringActor, ::Val{1}) = get_times(sa)
_getindex(sa::StoringActor, ::Val{n}) where {n} = get_values(sa)[n-1]
Base.length(sa::StoringActor) = length(get_values(sa)) + 1
Base.size(sa::StoringActor) = (length(sa), ((length(sa[i]) for i in 1:length(sa))...,))
Base.show(io::IO, actor::StoringActor) = print(io, "StoringActor(", actor.stored_values, ")")

###
### Some instances of StoringActor
###

# FIXME: allowing single arrays rather than tuple of arrays (possibly of length 1) increases complexity
# and amount of code that must be maintained: Must support only tuples.
# hmmm. maybe convert single array and single type to tuples upon construction
storing_position_actor(times) = StoringActor(times, (system) -> get_x(get_position(system)))

function storing_num_sites_visited_actor(times)
    funcs = ((system) -> get_num_sites_visited(system),)
    value_types = (Int,)
    return StoringActor(times, funcs; value_types=value_types)
end

function storing_nsteps_actor(times)
    funcs = ((system) -> get_nsteps(system), )
    value_types = (Int, )
    return StoringActor(times, funcs; value_types=value_types)
end

function storing_nsteps_position_actor(times)
    funcs = ((system) -> get_nsteps(system), (system) -> get_x(get_position(system)))
    return StoringActor(times, funcs; value_types=(Int, Float64))
end

function storing_nsteps_num_sites_visited_actor(times)
    funcs = ((system) -> get_nsteps(system), (system) -> get_num_sites_visited(system))
    value_types = (Int, Int)
    return StoringActor(times, funcs; value_types=value_types)
end

function storing_msd_actor(times)
    funcs = ((system) -> norm_squared(get_position(system)), )
    return StoringActor(times, funcs; value_types = (Float64,))
end

###
### ECDFActor
###

struct ECDFActor{T <: AbstractEmpiricalCDF, F, FC} <: AbstractActor
    action_func::F
    ecdf::T
    condition_func::FC
end

ECDFActor(action_func, ecdf = EmpiricalCDF()) = ECDFActor(action_func, ecdf, _ -> true)
init!(actor::ECDFActor) = (empty!(actor.ecdf); nothing)
finalize!(actor::ECDFActor) = (sort!(actor.ecdf); nothing)

function act!(actor::ECDFActor, system)
    if actor.condition_func(system)
        push!(actor.ecdf, actor.action_func(system))
    end
    return true
end

get_cdf(ea::ECDFActor) = ea.ecdf

"""
    ECDFValueActor(child_actor::AbstractActor)

Builds a CDF for any `child_actor` that implements `condition_satisfied` and `get_actor_value`.
"""
function ECDFValueActor(child_actor::AbstractActor)
    ecdf = EmpiricalCDF{typeof(get_actor_value(child_actor))}()
    condition_func = _ -> condition_satisfied(child_actor)
    action_func = _ -> get_actor_value(child_actor)
    return ECDFActor(action_func, ecdf, condition_func)
end

###
### ECDFsActor
###

# In some cases, we may not need, or even have, a child_actor
struct ECDFsActor{CDFT, F} <: AbstractActor
    ecdfs_times::CDFT
    storing_func::F
end

get_ecdf_times(ea::ECDFsActor) = ea.ecdfs_times

struct ECDFsTimes{TimeT, CDFT}
    times::TimeT
    ecdfs::CDFT
end
get_times(et::ECDFsTimes) = et.times
get_cdfs(et::ECDFsTimes) = et.ecdfs
unpack(et::ECDFsTimes) = [get_times(et) get_cdfs(et)]

function prune(et::ECDFsTimes; f = x -> !isempty(x))
    good_inds = unique(getindex.(findall(f, et.ecdfs),1))
    new_times = et.times[good_inds]
    new_ecdfs = et.ecdfs[good_inds,:]
    return ECDFsTimes(new_times, new_ecdfs)
end

function Base.show(io::IO, actor::ECDFsActor)
    print(io, "ECDFsActor{", typeof(get_ecdf_times(actor)), ", Func, ")
    print(io, "}")
end

act!(actor::ECDFsActor, system) = (actor.storing_func(system); true)
get_cdfs(ea::ECDFsActor) = get_cdfs(get_ecdf_times(ea))

function init!(actor::ECDFsActor)
    empty!(actor)
    nothing
end

finalize!(actor::ECDFsActor) = (sort!(actor); nothing)

# TODO: Fix indexing. Time should not be in index value 1
function ECDFsActor(storing_actor::StoringActor)
    times = get_times(storing_actor)
    ecdfs = [EmpiricalCDF{eltype(storing_actor[j])}() for i in 1:length(times), j in 2:length(storing_actor)]
    ecdfs_times = ECDFsTimes(times, ecdfs)
    storing_func = function(_...)
        for j in 2:length(storing_actor)
            for i in 1:length(storing_actor[j])
                push!(ecdfs[i, j-1], storing_actor[j][i])
            end
        end
        return true
    end
    return ECDFsActor(ecdfs_times, storing_func)
end

get_times(a::ECDFsActor) = get_times(get_ecdf_times(a))
unpack(a::ECDFsActor) = unpack(get_ecdf_times(a))

for f in (:sort!, :empty!)
    @eval function Base.$(f)(actor::ECDFsActor)
        ecdfs = get_cdfs(get_ecdf_times(actor))
        for cdf in ecdfs
           ($f)(cdf)
        end
        return actor
    end
end

get_data(cdf::ECDFActor) = get_data(cdf.ecdf)

for f in (:length, :size, :minimum, :maximum, :extrema, :issorted, :iterate, :getindex,
          :lastindex, :firstindex, :eltype, :view)
    @eval begin
        Base.$(f)(cdf::ECDFActor, args...) = $(f)(cdf.ecdf, args...)
#        Base.$(f)(cdf::ECDFsActor, ind, args...) = $(f)(cdf.ecdfs[ind], args...)
    end
end

for f in (:mean, :median, :middle, :std, :stdm, :var, :varm, :quantile)
    @eval begin
        Statistics.$(f)(cdf::ECDFActor, args...; kws...) = Statistics.$(f)(cdf.ecdf, args...; kws...)
        Statistics.$(f)(cdf::ECDFsActor, ind, args...; kws...) = Statistics.$(f)(cdf.ecdfs[ind], args...; kws...)
    end
end

for f in (:sort!, :empty!)
    @eval begin
        Base.$(f)(cdf::ECDFActor, args...) = ($(f)(cdf.ecdf,args...); cdf)
    end
end

###
### SampleLoopActor
###

# abstract type AbstractSampleLoopActor <: AbstractActor
# end

struct ProgressIter{IterT}
    iter::IterT
end
ProgressIter(n::Integer) = ProgressIter(1:n)

struct SampleLoopActor{Iter, ActorT} <: AbstractActor
    iter::Iter
    actor::ActorT
end

"""
    SampleLoopActor(iter, actor::AbstractActor = NullActor())

Actor for use in `trial!`. The sample iterator is `iter`.
"""
SampleLoopActor(iter) = SampleLoopActor(iter, NullActor())

"""
    SampleLoopActor(n::Integer,  actor = NullActor())

Actor for use in `trial!` that performs `n` samples.
"""
SampleLoopActor(n::Integer, actor = NullActor()) = SampleLoopActor(1:n, actor)

get_actor(s::SampleLoopActor) = s.actor

end # module Actors


text:
using BenchmarkTools
using DelimitedFiles

function chechNeighbors(array, position)
    x,y = size(array)
    x,y
    neighbors = []
    if position[1] == 1 && position[2] == 1
        neighbors = [[1,2],[2,1]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...])*(array[position...]+1)
    end
    if position[1] == 1 && position[2] == y
        neighbors = [[1,y-1],[2,y]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...])*(array[position...]+1)
    end
    if position[1] == x && position[2] == 1
        neighbors = [[x,2],[x-1,1]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...])*(array[position...]+1)
    end
    if position[1] == x && position[2] == y
        neighbors = [[x-1,y],[x,y-1]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...])*(array[position...]+1)
    end
    if position[1] == 1
        neighbors = [[2,position[2]],[1,position[2]-1],[1,position[2]+1]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...] &&
        array[position...] < array[neighbors[3]...])*(array[position...]+1)
    end
    if position[1] == x
        neighbors = [[x-1,position[2]],[x,position[2]-1],[x,position[2]+1]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...] &&
        array[position...] < array[neighbors[3]...])*(array[position...]+1)
    end
    if position[2] == 1
        neighbors = [[position[1],2],[position[1]-1,1],[position[1]+1,1]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...] &&
        array[position...] < array[neighbors[3]...])*(array[position...]+1)
    end
    if position[2] == y
        neighbors = [[position[1],y-1],[position[1]-1,y],[position[1]+1,y]]
        return (array[position...] < array[neighbors[1]...] &&
        array[position...] < array[neighbors[2]...] &&
        array[position...] < array[neighbors[3]...])*(array[position...]+1)
    end
    neighbors = [[position[1]-1,position[2]],[position[1],position[2]-1],
                 [position[1]+1,position[2]],[position[1],position[2]+1]]
    return (array[position...] < array[neighbors[1]...] &&
    array[position...] < array[neighbors[2]...] &&
    array[position...] < array[neighbors[3]...] &&
    array[position...] < array[neighbors[4]...])*(array[position...]+1)
end

function answer1(input::String)
    elevations = vcat(map(x -> parse.(Int,x),split.(readlines(input),""))'...) #Easy way to read matrices without delimiters
    total = 0
    for i in 1:size(elevations,1)
        for j in 1:size(elevations,2)
        total += chechNeighbors(elevations,[i,j])
        end
    end
    total
end

@show answer1("input")

"Could have used circshift, but thought about it too late."
function calculateNeighbors(position, elevations)
    x,y = size(elevations)
    x,y
    neighbors = []
    if position[1] == 1 && position[2] == 1
        neighbors = [[1,2],[2,1]]
    elseif position[1] == 1 && position[2] == y
        neighbors = [[1,y-1],[2,y]]
    elseif position[1] == x && position[2] == 1
        neighbors = [[x,2],[x-1,1]]
    elseif position[1] == x && position[2] == y
        neighbors = [[x-1,y],[x,y-1]]
    elseif position[1] == 1
        neighbors = [[2,position[2]],[1,position[2]-1],[1,position[2]+1]]
    elseif position[1] == x
        neighbors = [[x-1,position[2]],[x,position[2]-1],[x,position[2]+1]]
    elseif position[2] == 1
        neighbors = [[position[1],2],[position[1]-1,1],[position[1]+1,1]]
    elseif position[2] == y
        neighbors = [[position[1],y-1],[position[1]-1,y],[position[1]+1,y]]
    else
        neighbors = [[position[1]-1,position[2]],[position[1],position[2]-1],
                    [position[1]+1,position[2]],[position[1],position[2]+1]]
    end
    neighbors
end

"Recursive patching of the basins, this one should work regardless of the number of
minima in each basin."
function whichBasinAmI!(history,toCheck,noBasins,elevations)
    total = 0
    if history[toCheck...] > 0
        return 0
    elseif elevations[toCheck...] == 9
        history[toCheck...] = 0
        return 0
    else
        history[toCheck...] = noBasins
        total += 1
        for neighbor in calculateNeighbors(toCheck,elevations)
            total += whichBasinAmI!(history,neighbor,noBasins,elevations)
        end
        return total
    end
end

"Since there is at least one minimum in each basin, this works fine."
function answer2(input::String,returnBasins=false)
    elevations = vcat(map(x -> parse.(Int,x),split.(readlines(input),""))'...) #Easy way to read matrices without delimiters
    lowest_points = []
    basins = zeros(size(elevations)) .-1
    #Finds the minimum of each basin.
    for i in 1:size(elevations,1)
        for j in 1:size(elevations,2)
            if chechNeighbors(elevations,[i,j]) > 0
                append!(lowest_points,[[i,j]])
            end
        end
    end
    basinSizes = zeros(size(lowest_points))
    #Uses the basins as starting points to do BFS with the 9 as walls.
    for (i,position) in enumerate(lowest_points)
        basinSizes[i] = whichBasinAmI!(basins,position,i,elevations)
    end
    answer = Int(prod(partialsort(basinSizes,1:3,rev=true)))
    if returnBasins
        return basins, answer
    end
    answer
end

@show answer2("input")

# Uncomment to plot the basins.
# using Plots
# gr()
# heatmap(answer2("input",true)[1], yflip = true)


text:
let
	# Test Optim.nelder_mead for all functions except Large Polynomials in Optim.UnconstrainedProblems.examples
	for (name, prob) in Optim.UnconstrainedProblems.examples
		f_prob = prob.f
		res = Optim.optimize(f_prob, prob.initial_x, NelderMead(), Optim.Options(iterations = 10000))
		if name == "Powell"
			res = Optim.optimize(f_prob, prob.initial_x, NelderMead(), Optim.Options(g_tol = 1e-12))
		elseif name == "Large Polynomial"
			# TODO do this only when a "run all" flag checked
			# res = Optim.optimize(f_prob, prob.initial_x, method=NelderMead(initial_simplex = Optim.AffineSimplexer(1.,1.)), iterations = 450_000)
		end
		!(name == "Large Polynomial") && @assert norm(Optim.minimizer(res) - prob.solutions) < 1e-2
	end

    # Test if the trace is correctly stored.
    prob = Optim.UnconstrainedProblems.examples["Rosenbrock"]
    res = Optim.optimize(prob.f, prob.initial_x, method = NelderMead(), store_trace = true)
    @assert ( length(unique(Optim.g_norm_trace(res))) != 1 || length(unique(Optim.f_trace(res))) != 1 ) && issorted(Optim.f_trace(res)[end:1])
end