text:
"""
    convert2features(array)

Convert the given SVHN tensor to a feature matrix (or feature
vector in the case of a single image). The purpose of this
function is to drop the spatial dimensions such that traditional
ML algorithms can process the dataset.

```julia
julia> SVHN2.convert2features(SVHN2.traindata(Float32)[1]) # full training data
3072×50000 Array{Float32,2}:
[...]

julia> SVHN2.convert2features(SVHN2.traindata(Float32,1)[1]) # first observation
3072-element Array{Float32,1}:
[...]
```
"""
function convert2features(array::AbstractArray{<:Number,3})
    nrows, ncols, nchan = size(array)
    @assert nchan == 3 "the given array should have the RGB channel in the third dimension"
    vec(array)
end

function convert2features(array::AbstractArray{<:Number,4})
    nrows, ncols, nchan, nimages = size(array)
    @assert nchan == 3 "the given array should have the RGB channel in the third dimension"
    reshape(array, (nrows * ncols * nchan, nimages))
end

convert2features(array::AbstractArray{<:RGB,2}) =
    convert2features(permutedims(_channelview(array), (2,3,1)))

convert2features(array::AbstractArray{<:RGB,3}) =
    convert2features(permutedims(_channelview(array), (2,3,1,4)))

"""
    convert2image(array) -> Array{RGB}

Convert the given SVHN tensor (or feature vector/matrix) to a
`RGB` array.

```julia
julia> SVHN2.convert2image(SVHN2.traindata()[1]) # full training dataset
32×32×50000 Array{RGB{N0f8},3}:
[...]

julia> SVHN2.convert2image(SVHN2.traindata(1)[1]) # first training image
32×32 Array{RGB{N0f8},2}:
[...]
```
"""
function convert2image(array::AbstractVector{<:Number})
    @assert length(array) % 3072 == 0
    if length(array) == 3072
        convert2image(reshape(array, 32, 32, 3))
    else
        n = Int(length(array) / 3072)
        convert2image(reshape(array, 32, 32, 3, n))
    end
end

function convert2image(array::AbstractMatrix{<:Number})
    @assert size(array, 1) == 3072
    convert2image(reshape(array, 32, 32, 3, size(array, 2)))
end

function convert2image(array::AbstractArray{<:Number,3})
    nrows, ncols, nchan = size(array)
    @assert nchan == 3 "the given array should have the RGB channel in the third dimension"
    _colorview(RGB, permutedims(_norm_array(array), (3,1,2)))
end

function convert2image(array::AbstractArray{<:Number,4})
    nrows, ncols, nchan, nimages = size(array)
    @assert nchan == 3 "the given array should have the RGB channel in the third dimension"
    _colorview(RGB, permutedims(_norm_array(array), (3,1,2,4)))
end

_norm_array(array::AbstractArray) = array
_norm_array(array::AbstractArray{<:Integer}) = reinterpret(N0f8, convert(Array{UInt8}, array))


text:
"""
    jacobi(A, B, Xawal)
adalah fungsi yang digunakan untuk mencari solusi SPL `Ax=B` secara iteratif dengan
nilai tebakan awal `Xawal` menggunakan metode jacobi.

# Example
```jl
julia> A = [4 -1 1
            4 -8 1
           -2 1 5];

julia> B = [7;-21;15];

julia> Xa = [1,2,2];

julia> X,flag,err,M = jacobi(A,B,Xa);

julia> X
3-element Array{Float64,1}:
 1.9999999884128572
 3.9999999907302857
 3.0000000018539428

julia> flag
0

julia> err
3.777053140308286e-8

julia> M
18×5 Array{Float64,2}:
  0.0  1.0      2.0    2.0     NaN
  1.0  1.75     3.375  3.0       1.85826
  2.0  1.84375  3.875  3.025     0.509327
  3.0  1.9625   3.925  2.9625    0.143205
  ⋮
 14.0  2.0      4.0    3.0       1.00721e-6
 15.0  2.0      4.0    3.0       2.83194e-7
 16.0  2.0      4.0    3.0       1.37804e-7
 17.0  2.0      4.0    3.0       3.77705e-8
```
return solusi `X` dengan `flag` bernilai 0 jika metode jacobi berhasil menemukan
solusi dan gagal jika tidak 0. Serta, matriks `M` yang berisi catatan proses tiap
iterasi `[k, X', error]`
"""
function jacobi(A, B, Xawal)
    delta = 10^-7;
    maxi = 100;
    flag = 1;
    D = Diagonal(diag(A))
    R = A - D;
    X = Xawal[:];
    M = [0 X' NaN];
    for k = 1:maxi
        Xlama = X;
        X = inv(D)*(B - R*Xlama);
        err = norm(X-Xlama);
        M = [M; [k X' err] ];
        if err<delta || norm(B-A*X)<delta
            flag = 0;
            break
        end
    end
    err = M[end,end]
    return X, flag, err, M
end

ext: jl


text:
using Parameters

abstract type AbstractSolvent end
export AbstractSolvent

struct EmptySolvent <: AbstractSolvent end
export EmptySolvent

@with_kw struct Solvent <: AbstractSolvent
    name::String
    mu::AbstractViscosity
end
export Solvent


text:
function sqlite3_data_count(stmtptr::Ptr{Void})
    @windows_only return ccall(
        (:sqlite3_data_count, sqlite3_lib),
        stdcall,
        Cint,
        (Ptr{Void}, ),
        stmtptr
    )
    @unix_only return ccall(
        (:sqlite3_data_count, sqlite3_lib),
        Cint,
        (Ptr{Void}, ),
        stmtptr
    )
end

function sqlite3_column_count(stmtptr::Ptr{Void})
    @windows_only return ccall(
        (:sqlite3_column_count, sqlite3_lib),
        stdcall,
        Cint,
        (Ptr{Void}, ),
        stmtptr
    )
    @unix_only return ccall(
        (:sqlite3_column_count, sqlite3_lib),
        Cint,
        (Ptr{Void}, ),
        stmtptr
    )
end

function sqlite3_column_blob(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_blob, sqlite3_lib),
        stdcall,
        Ptr{Void},
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_blob, sqlite3_lib),
        Ptr{Void},
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_bytes(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_bytes, sqlite3_lib),
        stdcall,
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_bytes, sqlite3_lib),
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_bytes16(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_bytes16, sqlite3_lib),
        stdcall,
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_bytes16, sqlite3_lib),
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_double(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_double, sqlite3_lib),
        stdcall,
        Cdouble,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_double, sqlite3_lib),
        Cdouble,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_int(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_int, sqlite3_lib),
        stdcall,
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_int, sqlite3_lib),
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_int64(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_int64, sqlite3_lib),
        stdcall,
        Clonglong,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_int64, sqlite3_lib),
        Clonglong,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_text(stmtptr::Ptr{Void},colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_text, sqlite3_lib),
        stdcall,
        Ptr{Uint8},
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_text, sqlite3_lib),
        Ptr{Uint8},
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_text16(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_text16, sqlite3_lib),
        stdcall,
        Ptr{Void},
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_text16, sqlite3_lib),
        Ptr{Void},
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_type(stmtptr::Ptr{Void}, colindex::Int)
    @windows_only return ccall(
        (:sqlite3_column_type, sqlite3_lib),
        stdcall,
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
    @unix_only return ccall(
        (:sqlite3_column_type, sqlite3_lib),
        Cint,
        (Ptr{Void}, Cint),
        stmtptr,
        colindex
    )
end

function sqlite3_column_name(stmtptr::Ptr{Void}, n::Int)
    @windows_only return ccall(
        (:sqlite3_column_name, sqlite3_lib),
        stdcall,
        Ptr{Uint8},
        (Ptr{Void}, Cint),
        stmtptr,
        n
    )
    @unix_only return ccall(
        (:sqlite3_column_name, sqlite3_lib),
        Ptr{Uint8},
        (Ptr{Void}, Cint),
        stmtptr,
        n
    )
end


text:
function get_date(obj::FieldTimeStamped)
    return jcall(obj, "getDate", FieldAbsoluteDate, ())
end


text:
using PyPlot
include("../../../src/extract_planet.jl")

function plot_ttv(data,elements,tt1,count1,nplanet)

# Now make some plots:
fig,axes = subplots(4,1,sharex="col",figsize=(6,8))
plabel = ["T1b","T1c","T1d","T1e","T1f","T1g","T1h"]
range = [1.0,1.0,1.0,2.0,12.0,8.0,3.0]

# Now make some plots:
eoffset = [43,10,75,9,7,3,22]
ord = [5,5,18,24,18,18,18]
i1 = 1
i2 = 0
for ip=1:nplanet
  if ip == 1 || ip == 2
    ax = axes[1]
  elseif ip == 3
    ax = axes[2]
  elseif ip == 4 || ip == 5
    ax = axes[3]
  else
    ax = axes[4]
  end
  coeff = zeros(Float64,2)
  # Plot each "Mode"
  eobs,tobs,sobs,nobs = extract_planet(data,ip)
  println("ip: ",ip," nobs: ",nobs)
  fn = zeros(2,nobs)
  fn[1,:] .= 1.0
  fn[2,:] .= eobs
  coeff,cov = regress(fn,tobs,sobs)
  println(ip," obs: ",coeff[1]," ",coeff[2])
  # Now plot TTVFast:
  fn = zeros(Float64,2,count1[ip+1])
  sig = ones(count1[ip+1])
  tti1 = tt1[ip+1,1:count1[ip+1]]
  tt_ref1 = zeros(count1[ip+1])
  epoch = zeros(count1[ip+1])
  for j=1:count1[ip+1]
    fn[1,j] = 1.0
    fn[2,j] = round(Int64,(tti1[j]-elements[ip+1,3])/elements[ip+1,2])
    epoch[j] = round((tti1[j]-coeff[1])/coeff[2])
    tt_ref1[j] = coeff[1]+coeff[2]*epoch[j]
  end
  coeff,cov = regress(fn,tti1,sig)
  println(ip," model: ",coeff[1]," ",coeff[2])
  tt_ref1 = coeff[1] .+coeff[2] .*fn[2,:]
  ttv1 = (tti1 .-tt_ref1) .*(24*60)
  ax.plot(tti1,ttv1,label=plabel[ip],linewidth=1.5,zorder=-32)
  ttv_obs = (tobs .- coeff[1] .- coeff[2] .*(eobs .+eoffset[ip]))*(24*60)
  ax.errorbar(tobs, ttv_obs, sobs*(24*60),fmt=".",linewidth=1.5,markersize=4.0)
  i2 = i1 + count1[ip+1] - 1
  resid = (tobs .- tt1[ip+1,indx[iplanet .== (ip+1)]])./sobs
  i1 = i2 + 1
  iout = abs.(resid) .> 3.0
  ax.errorbar(tobs[iout], ttv_obs[iout], sobs[iout]*(24*60),fmt=".",linewidth=1.5,markersize=4.0,color="C5")
  if ip == 7
    ax.set_xlabel(L"BJD$_\mathrm{TDB}$-2,450,000 [d]")
  end
  ax.grid(linestyle=":")
  ax.set_ylabel("TTV [min]")
  ax.legend()
  # Now, fit a high-order polynomial to TTVs, and overplot it:
  fn = zeros(ord[ip]+1,count1[ip+1])
  fn[1,:] .= 1.0
  for j=1:ord[ip]
    fn[j+1,:] .= epoch.^j
  end
  coeff,cov = regress(fn,tti1,sig)
  mod_poly = ones(count1[ip+1])*coeff[1]
  for j=1:ord[ip]
     mod_poly .+= fn[j+1,:] .*coeff[j+1]
  end
#  ax.plot(tti1,(mod_poly .-tt_ref1) .*(24*60),linewidth=1.5,alpha=0.5)
end
#ax = axes[8]
#ax.axis("off")
tight_layout()
subplots_adjust(hspace=0)
savefig("../T1_ttvs_4panel_stacked.pdf",bbox_inches="tight")
return
end


text:
module Snappy

using Compat

if isfile(joinpath(dirname(dirname(@__FILE__)),"deps","deps.jl"))
    include("../deps/deps.jl")
else
    error("Snappy not properly installed. Please run Pkg.build(\"Snappy\")")
end

export compress, uncompress

# snappy status
const SnappyOK = 0
const SnappyInvalidInput = 1
const SnappyBufferTooSmall = 2

# High-level Interfaces

function compress(input::Vector{UInt8})
    ilen = length(input)
    maxlen = snappy_max_compressed_length(@compat(UInt(ilen)))
    compressed = Array(UInt8, maxlen)
    olen, st = snappy_compress(input, compressed)
    if st != SnappyOK
        error("failed to compress the data")
    end
    resize!(compressed, olen)
    compressed
end

function uncompress(input::Array{UInt8})
    ilen = length(input)
    explen, st = snappy_uncompressed_length(input)
    if st != SnappyOK
        error("faield to guess the length of the uncompressed data (the compressed data may be broken?)")
    end
    uncompressed = Array(UInt8, explen)
    olen, st = snappy_uncompress(input, uncompressed)
    if st != SnappyOK
        error("failed to uncompress the data")
    end
    @assert explen == olen
    resize!(uncompressed, olen)
    uncompressed
end

# Low-level Interfaces

function snappy_compress(input::Vector{UInt8}, compressed::Vector{UInt8})
    ilen = length(input)
    olen = Csize_t[length(compressed)]
    status = ccall(
        (:snappy_compress, libsnappy),
        Int,
        (Ptr{UInt8}, Csize_t, Ptr{UInt8}, Ptr{Csize_t}),
        input, ilen, compressed, olen
    )
    olen[1], status
end

function snappy_uncompress(compressed::Vector{UInt8}, uncompressed::Vector{UInt8})
    ilen = length(compressed)
    olen = Csize_t[length(uncompressed)]
    status = ccall(
        (:snappy_uncompress, libsnappy),
        Int,
        (Ptr{UInt8}, Csize_t, Ptr{UInt8}, Ptr{Csize_t}),
        compressed, ilen, uncompressed, olen
    )
    olen[1], status
end

function snappy_max_compressed_length(source_length::UInt)
    ccall((:snappy_max_compressed_length, libsnappy), Csize_t, (Csize_t,), source_length)
end

function snappy_uncompressed_length(compressed::Vector{UInt8})
    len = length(compressed)
    result = Csize_t[0]
    status = ccall((:snappy_uncompressed_length, libsnappy), Int, (Ptr{UInt8}, Csize_t, Ptr{Csize_t}), compressed, len, result)
    result[1], status
end

function snappy_validate_compressed_buffer(compressed::Vector{UInt8})
    ilen = length(compressed)
    ccall((:snappy_validate_compressed_buffer, libsnappy), Int, (Ptr{UInt8}, Csize_t), compressed, ilen)
end

end # module


text:
using Pkg
Pkg.activate(".")

using DataFrames
using CSV
using GLPKMathProgInterface
using GLPK
using JuMP

distance_data = CSV.read("distance_data.csv",header=[:i, :j, :dist])

N = length(unique(distance_data.i))
const distance_mx = zeros(Float64,(N,N))
for r in 1:nrow(distance_data)
   distance_mx[distance_data.i[r],distance_data.j[r]] = distance_data.dist[r]
end

#http://opensourc.es/blog/mip-tsp
N = 30 #this is an NP hard problem - we do only 30 cites
m = Model(with_optimizer(GLPK.Optimizer))
@variable(m, x[f=1:N, t=1:N], Bin)
@objective(m, Min, sum( x[i, j]*distance_mx[i,j] for i=1:N,j=1:N))
@constraint(m, notself[i=1:N], x[i, i] == 0)
@constraint(m, oneout[i=1:N], sum(x[i, 1:N]) == 1)
@constraint(m, onein[j=1:N], sum(x[1:N, j]) == 1)
for f=1:N, t=1:N
    @constraint(m, x[f, t]+x[t, f] <= 1)
end

function getcycle(m, N)
    x_val = value.(x)
    cycle_idx = Vector{Int}()
    push!(cycle_idx, 1)
    while true
        v, idx = findmax(x_val[cycle_idx[end], 1:N])
        if idx == cycle_idx[1]
            break
        else
            push!(cycle_idx, idx)
        end
    end
    cycle_idx
end

optimize!(m)
getcycle(m,N)

function solved(m, cycle_idx, N)
    println("cycle_idx: ", cycle_idx)
    println("Length: ", length(cycle_idx))
    if length(cycle_idx) < N
        cc = @constraint(m, sum(x[cycle_idx,cycle_idx]) <= length(cycle_idx)-1)
        println("added a constraint")
        return false
    end
    return true
end

while true
    optimize!(m)
    println(termination_status(m))
    cycle_idx = getcycle(m, N)
    if solved(m, cycle_idx,N)
        break;
    end
end

sbws_la = CSV.read("Subway_LV.csv")

using PyPlot
cycle_idx = getcycle(m, N)
ids = vcat(cycle_idx, cycle_idx[1])
PyPlot.cla()
PyPlot.ioff()
p = PyPlot.plot(sbws_la.long[ids], sbws_la.latt[ids])
PyPlot.display_figs()
PyPlot.show()


text:
using Base.Test
using PGM

@testset "JointPMF" begin

@testset "Basics" begin
    p1 = rand(3, 4)
    g1 = JointPMF(["x", "y"], p1)
    @test isa(g1, JointPMF{Float64})
    @test nvars(g1) == 2
    @test vars(g1)[1] == dvar("x", 3)
    @test vars(g1)[2] == dvar("y", 4)
    @test probs(g1) == p1

    p2 = rand(3, 4, 5)
    g2 = JointPMF(("x", "y", "z"), p2)
    @test isa(g2, JointPMF{Float64})
    @test nvars(g2) == 3
    @test vars(g2)[1] == dvar("x", 3)
    @test vars(g2)[2] == dvar("y", 4)
    @test vars(g2)[3] == dvar("z", 5)
    @test probs(g2) == p2
end

@testset "Marginal" begin
    p = rand(3, 4, 5, 2)  # for x, y, z, w
    p ./= sum(p)
    px = reshape(sum(p, (2, 3, 4)), 3)
    py = reshape(sum(p, (1, 3, 4)), 4)
    pz = reshape(sum(p, (1, 2, 4)), 5)
    pw = reshape(sum(p, (1, 2, 3)), 2)

    pxy = reshape(sum(p, (3, 4)), (3, 4))
    pxz = reshape(sum(p, (2, 4)), (3, 5))
    pxw = reshape(sum(p, (2, 3)), (3, 2))
    pyx = pxy.'
    pyz = reshape(sum(p, (1, 4)), (4, 5))
    pyw = reshape(sum(p, (1, 3)), (4, 2))
    pzx = pxz.'
    pzy = pyz.'
    pzw = reshape(sum(p, (1, 2)), (5, 2))
    pwx = pxw.'
    pwy = pyw.'
    pwz = pzw.'

    pxyz = reshape(sum(p, 4), (3, 4, 5))
    pxzy = permutedims(pxyz, (1, 3, 2)); @assert size(pxzy) == (3, 5, 4)
    pyxz = permutedims(pxyz, (2, 1, 3)); @assert size(pyxz) == (4, 3, 5)
    pyzx = permutedims(pxyz, (2, 3, 1)); @assert size(pyzx) == (4, 5, 3)
    pzxy = permutedims(pxyz, (3, 1, 2)); @assert size(pzxy) == (5, 3, 4)
    pzyx = permutedims(pxyz, (3, 2, 1)); @assert size(pzyx) == (5, 4, 3)

    jp1 = JointPMF(("x",), px)
    jp2 = JointPMF(("x", "y"), pxy)
    jp3 = JointPMF(("x", "y", "z"), pxyz)
    jp4 = JointPMF(("x", "y", "z", "w"), p)

    # 1 -> 1
    @test marginal(jp1, "x") == px

    # 2 -> 1
    @test marginal(jp2, "x") ≈ px
    @test marginal(jp2, "y") ≈ py

    # 2 -> 2
    @test marginal(jp2, ("x", "y")) == pxy
    @test marginal(jp2, ("y", "x")) == pyx

    # 3 -> 1
    @test marginal(jp3, "x") ≈ px
    @test marginal(jp3, "y") ≈ py
    @test marginal(jp3, "z") ≈ pz

    # 3 -> 2
    @test marginal(jp3, ("x", "y")) ≈ pxy
    @test marginal(jp3, ("x", "z")) ≈ pxz
    @test marginal(jp3, ("y", "x")) ≈ pyx
    @test marginal(jp3, ("y", "z")) ≈ pyz
    @test marginal(jp3, ("z", "x")) ≈ pzx
    @test marginal(jp3, ("z", "y")) ≈ pzy

    # 3 -> 3
    @test marginal(jp3, ("x", "y", "z")) == pxyz
    @test marginal(jp3, ("x", "z", "y")) == pxzy
    @test marginal(jp3, ("y", "x", "z")) == pyxz
    @test marginal(jp3, ("y", "z", "x")) == pyzx
    @test marginal(jp3, ("z", "x", "y")) == pzxy
    @test marginal(jp3, ("z", "y", "x")) == pzyx

    # 4 -> 1
    @test marginal(jp4, ("x",)) ≈ px
    @test marginal(jp4, ("y",)) ≈ py
    @test marginal(jp4, ("z",)) ≈ pz
    @test marginal(jp4, ("w",)) ≈ pw

    # 4 -> 2
    @test marginal(jp4, ("x", "y")) ≈ pxy
    @test marginal(jp4, ("x", "z")) ≈ pxz
    @test marginal(jp4, ("x", "w")) ≈ pxw
    @test marginal(jp4, ("y", "x")) ≈ pyx
    @test marginal(jp4, ("y", "z")) ≈ pyz
    @test marginal(jp4, ("y", "w")) ≈ pyw
    @test marginal(jp4, ("z", "x")) ≈ pzx
    @test marginal(jp4, ("z", "y")) ≈ pzy
    @test marginal(jp4, ("z", "w")) ≈ pzw
    @test marginal(jp4, ("w", "x")) ≈ pwx
    @test marginal(jp4, ("w", "y")) ≈ pwy
    @test marginal(jp4, ("w", "z")) ≈ pwz

    # 4 -> 3
    @test marginal(jp4, ("x", "y", "z")) ≈ pxyz

    pxwy = sum(p, 3) |>
        r->reshape(r, (3, 4, 2)) |>
        r->permutedims(r, (1, 3, 2))
    @assert size(pxwy) == (3, 2, 4)
    @test marginal(jp4, ("x", "w", "y")) ≈ pxwy

    pwzx = sum(p, 2) |>
        r->reshape(r, (3, 5, 2)) |>
        r->permutedims(r, (3, 2, 1))
    @assert size(pwzx) == (2, 5, 3)
    @test marginal(jp4, ("w", "z", "x")) ≈ pwzx

    pywz = sum(p, 1) |>
        r->reshape(r, (4, 5, 2)) |>
        r->permutedims(r, (1, 3, 2))
    @assert size(pywz) == (4, 2, 5)
    @test marginal(jp4, ("y", "w", "z")) ≈ pywz
end

@testset "Conditional" begin
    p = rand(3, 4, 5)
    p ./= sum(p)
    jp = JointPMF(("x", "y", "z"), p)

    p_x = sum(p, (2, 3))
    p_y = sum(p, (1, 3))
    p_z = sum(p, (1, 2))
    p_xy = sum(p, 3)
    p_xz = sum(p, 2)
    p_yz = sum(p, 1)

    # 1 | 0
    @test conditional(jp, "x", ()) ≈ reshape(p_x, 3)
    @test conditional(jp, "y", ()) ≈ reshape(p_y, 4)
    @test conditional(jp, "z", ()) ≈ reshape(p_z, 5)

    # 2 | 0
    @test conditional(jp, ("x", "y"), ()) ≈ reshape(p_xy, (3, 4))
    @test conditional(jp, ("x", "z"), ()) ≈ reshape(p_xz, (3, 5))
    @test conditional(jp, ("y", "z"), ()) ≈ reshape(p_yz, (4, 5))
    @test conditional(jp, ("z", "x"), ()) ≈ reshape(p_xz, (3, 5)).'

    # 3 | 0
    @test conditional(jp, ("x", "y", "z"), ()) == p
    @test conditional(jp, ("y", "z", "x"), ()) == permutedims(p, (2, 3, 1))

    # 1 | 1
    @test conditional(jp, "x", "y") ≈ reshape(p_xy ./ p_y, (3, 4))
    @test conditional(jp, "x", "z") ≈ reshape(p_xz ./ p_z, (3, 5))
    @test conditional(jp, "y", "x") ≈ reshape(p_xy ./ p_x, (3, 4)).'
    @test conditional(jp, "y", "z") ≈ reshape(p_yz ./ p_z, (4, 5))
    @test conditional(jp, "z", "x") ≈ reshape(p_xz ./ p_x, (3, 5)).'
    @test conditional(jp, "z", "y") ≈ reshape(p_yz ./ p_y, (4, 5)).'

    # 2 | 1
    @test conditional(jp, ("x", "y"), "z") ≈ p ./ p_z
    @test conditional(jp, ("y", "x"), "z") ≈ permutedims(p ./ p_z, (2, 1, 3))
    @test conditional(jp, ("x", "z"), "y") ≈ permutedims(p ./ p_y, (1, 3, 2))
    @test conditional(jp, ("z", "x"), "y") ≈ permutedims(p ./ p_y, (3, 1, 2))
    @test conditional(jp, ("y", "z"), "x") ≈ permutedims(p ./ p_x, (2, 3, 1))
    @test conditional(jp, ("z", "y"), "x") ≈ permutedims(p ./ p_x, (3, 2, 1))

    # 1 | 2
    @test conditional(jp, "x", ("y", "z")) ≈ p ./ p_yz
    @test conditional(jp, "x", ("z", "y")) ≈ permutedims(p ./ p_yz, (1, 3, 2))
    @test conditional(jp, "y", ("x", "z")) ≈ permutedims(p ./ p_xz, (2, 1, 3))
    @test conditional(jp, "y", ("z", "x")) ≈ permutedims(p ./ p_xz, (2, 3, 1))
    @test conditional(jp, "z", ("x", "y")) ≈ permutedims(p ./ p_xy, (3, 1, 2))
    @test conditional(jp, "z", ("y", "x")) ≈ permutedims(p ./ p_xy, (3, 2, 1))
end

end # JointPMF


text:
using Documenter, Fourier

makedocs(modules = [Fourier], doctest = false, sitename = "Fourier")
deploydocs(repo = "github.com/JuliaOptics/Fourier.jl.git")

max_stars_repo_name: JuliaOptics/Fourier

max_issues_repo_name: JuliaOptics/Fourier

max_forks_repo_name: JuliaOptics/Fourier


text:
"""
    module Interfaces

This module contains interfaces that can be used to extend and modify the algorithms and behaviours of `Rimu`.

# Interfaces
Follow the links for the definitions of the interfaces!
* [`AbstractHamiltonian`](@ref) for defining [`Hamiltonians`](@ref)
* [`AbstractDVec`](@ref) for defining data structures for `Rimu` as in [`DictVectors`](@ref)
* [`StochasticStyle`](@ref) for controlling the stochastic algorithms used by [`lomc!`](@ref)
  as implemented in [`StochasticStyles`](@ref)

# Additonal exports

## Interface functions for[`AbstractHamiltonian`](@ref)s:
* [`diagonal_element`](@ref)
* [`num_offdiagonals`](@ref)
* [`get_offdiagonal`](@ref)
* [`offdiagonals`](@ref).
* [`random_offdiagonal`](@ref)
* [`starting_address`](@ref)
* [`LOStructure`](@ref)

## working with  [`AbstractDVec`](@ref)s and [`StochasticStyle`](@ref)
* [`deposit!`](@ref)
* [`default_style`](@ref)
* [`CompressionStrategy`](@ref)

## Functions Rimu.jl uses to do FCIQMC:

* [`fciqmc_col!`](@ref)
* [`step_stats`](@ref)
* [`update_dvec!`](@ref)
"""
module Interfaces

using LinearAlgebra
using StaticArrays

using ..ConsistentRNG
import OrderedCollections: freeze

export
    StochasticStyle, default_style, StyleUnknown, fciqmc_col!, step_stats, update_dvec!,
    CompressionStrategy, NoCompression, compress!
export
    AbstractDVec, deposit!, storage, localpart, freeze
export
    AbstractHamiltonian, diagonal_element, num_offdiagonals, get_offdiagonal, offdiagonals,
    random_offdiagonal, starting_address,
    LOStructure, IsHermitian, AdjointKnown, AdjointUnknown, has_adjoint

include("stochasticstyles.jl")
include("dictvectors.jl")
include("hamiltonians.jl")

end


text:
# generates array of arrays for a mesh, useful when interpolating the FEM solution
# L is the length of a single cell
#
# index of femCLmap corresponds to cell index
# values of femCLmap[jj] correspond to index of elements inside cell jj
function generate_femap(mesh::M,totalBounds::Vector{Float64},L::Float64) where M<:eFEM.AbstractMesh
    Nnodes = length(mesh.xy)
    numNodesPerElm = (mesh.order == :Linear ? 4 : 9)

    # generate particle List for FEM nodes
    particleList = [Particle2D(Point2D(mesh.xy[i].x,mesh.xy[i].y),0.0,0) for i=1:Nnodes]

    tempCL = StokesParticles.generate_cell_list(particleList,totalBounds,L)
    femap = Array{Array{Int}}(undef,length(tempCL.cells))

    # initialize element array
    elementArray = Array{Int}(undef,numNodesPerElm)

    # convert all point indices to corresponding element indices
    for cellInd = 1:length(tempCL.cells)
        tempArr = Array{Int}(undef,0)

        #for each node in that cell
        for nodeInd in tempCL.cells[cellInd].particleIDList
            fill!(elementArray,zero(Int))

            # map node index to element
            getElementFromNode!(elementArray,mesh,nodeInd)

            for ti=1:numNodesPerElm
                if elementArray[ti] != 0
                    push!(tempArr,elementArray[ti])
                end
            end
        end

        # assign elements to femCL as 'nodes'
        femap[cellInd] = unique(tempArr)
    end

    return femap
end

"""
    interpFGT!(v,pList,mesh,h,ε,x,y,q)

Takes in particle position and FEM mesh to interpolate values.
Also updates particle possitoin arrays in-place to reduce memory consumption

POSSIBLE IMPROVEMENTS:
1. add another function that updates the target array only once the first time
       this code is run. Maybe some sort of interp object that does this for me

INPUTS:
v:     [Vector{Float64}, M] interpolated values at targets
pList: [ParticleList] Array of particles, acts as sources
mesh:  [Mesh] Finite Element mesh, acts as targets
h:     [Float64] bandwidth, h=sqrt(2)*stddev if standard deviation is known
ε:     [Float64] maximum absolute error
x:     [Vector{Float64}, d*N] list of sources -- updated in-place within function
y:     [Vector{Float64}, d*M] list of targets -- updated in-place within function
q:     [Vector{Float64}, N] weights on sources -- updated in-place within function
W:     [Int] number of weight functions (e.g. if W=2, then length(q) = 2N)
"""
function interpFGT!(v::Array{Float64},pList,mesh,h::Float64,ε::Float64,
                    x::Array{Float64},y::Array{Float64},q::Array{Float64})
    N = length(pList)       # sources -- needed for fgt function
    M = length(mesh.xy)     # targets -- needed for fgt function
    d = 2                   # dimension of data -- needed for fgt function
    W = 1                   # number of different weights -- needed for fgt function

    # update source array
    for ti=1:N
        x[2*ti-1] = pList[ti].pos.x
        x[2*ti]   = pList[ti].pos.y
    end

    # update target array -- really should only have to do this once! room for improvement
    for ti=1:M
        y[2*ti-1] = mesh.xy[ti].x       # xval of source
        y[2*ti]   = mesh.xy[ti].y
    end

    # run interpolation routine
    StokesParticles.fgt!(v,d,M,N,h,ε,x,y,q,W)

    # return nothing -- updates in-place
    nothing
end

function getElementFromNode!(elementArray::Vector{Int},mesh::M,nodeInd::Int) where M<:eFEM.AbstractMesh
    nElm = length(mesh.cm)

    tk = 1
    for elmInd=1:nElm
      if nodeInd in mesh.cm[elmInd].NodeList
        elementArray[tk] = elmInd
        tk += 1
      end
    end

    nothing
  end

max_stars_repo_name: pseastham/eFEMpart


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: elasticsearch_service
using AWS.Compat
using AWS.UUIDs

"""
    accept_inbound_cross_cluster_search_connection(connection_id)
    accept_inbound_cross_cluster_search_connection(connection_id, params::Dict{String,<:Any})

Allows the destination domain owner to accept an inbound cross-cluster search connection
request.

# Arguments
- `connection_id`: The id of the inbound connection that you want to accept.

"""
function accept_inbound_cross_cluster_search_connection(
    ConnectionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "PUT",
        "/2015-01-01/es/ccs/inboundConnection/$(ConnectionId)/accept";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function accept_inbound_cross_cluster_search_connection(
    ConnectionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "PUT",
        "/2015-01-01/es/ccs/inboundConnection/$(ConnectionId)/accept",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    add_tags(arn, tag_list)
    add_tags(arn, tag_list, params::Dict{String,<:Any})

Attaches tags to an existing Elasticsearch domain. Tags are a set of case-sensitive key
value pairs. An Elasticsearch domain may have up to 10 tags. See  Tagging Amazon
Elasticsearch Service Domains for more information.

# Arguments
- `arn`:  Specify the ARN for which you want to add the tags.
- `tag_list`:  List of Tag that need to be added for the Elasticsearch domain.

"""
function add_tags(ARN, TagList; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "POST",
        "/2015-01-01/tags",
        Dict{String,Any}("ARN" => ARN, "TagList" => TagList);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function add_tags(
    ARN,
    TagList,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/tags",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("ARN" => ARN, "TagList" => TagList), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    associate_package(domain_name, package_id)
    associate_package(domain_name, package_id, params::Dict{String,<:Any})

Associates a package with an Amazon ES domain.

# Arguments
- `domain_name`: Name of the domain that you want to associate the package with.
- `package_id`: Internal ID of the package that you want to associate with a domain. Use
  DescribePackages to find this value.

"""
function associate_package(
    DomainName, PackageID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/associate/$(PackageID)/$(DomainName)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function associate_package(
    DomainName,
    PackageID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/associate/$(PackageID)/$(DomainName)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    cancel_elasticsearch_service_software_update(domain_name)
    cancel_elasticsearch_service_software_update(domain_name, params::Dict{String,<:Any})

Cancels a scheduled service software update for an Amazon ES domain. You can only perform
this operation before the AutomatedUpdateDate and when the UpdateStatus is in the
PENDING_UPDATE state.

# Arguments
- `domain_name`: The name of the domain that you want to stop the latest service software
  update on.

"""
function cancel_elasticsearch_service_software_update(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/serviceSoftwareUpdate/cancel",
        Dict{String,Any}("DomainName" => DomainName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function cancel_elasticsearch_service_software_update(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/serviceSoftwareUpdate/cancel",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("DomainName" => DomainName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_elasticsearch_domain(domain_name)
    create_elasticsearch_domain(domain_name, params::Dict{String,<:Any})

Creates a new Elasticsearch domain. For more information, see Creating Elasticsearch
Domains in the Amazon Elasticsearch Service Developer Guide.

# Arguments
- `domain_name`: The name of the Elasticsearch domain that you are creating. Domain names
  are unique across the domains owned by an account within an AWS region. Domain names must
  start with a lowercase letter and can contain the following characters: a-z (lowercase),
  0-9, and - (hyphen).

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"AccessPolicies"`:  IAM access policy as a JSON-formatted string.
- `"AdvancedOptions"`:  Option to allow references to indices in an HTTP request body. Must
  be false when configuring access to individual sub-resources. By default, the value is
  true. See Configuration Advanced Options for more information.
- `"AdvancedSecurityOptions"`: Specifies advanced security options.
- `"AutoTuneOptions"`: Specifies Auto-Tune options.
- `"CognitoOptions"`: Options to specify the Cognito user and identity pools for Kibana
  authentication. For more information, see Amazon Cognito Authentication for Kibana.
- `"DomainEndpointOptions"`: Options to specify configuration that will be applied to the
  domain endpoint.
- `"EBSOptions"`: Options to enable, disable and specify the type and size of EBS storage
  volumes.
- `"ElasticsearchClusterConfig"`: Configuration options for an Elasticsearch domain.
  Specifies the instance type and number of instances in the domain cluster.
- `"ElasticsearchVersion"`: String of format X.Y to specify version for the Elasticsearch
  domain eg. \"1.5\" or \"2.3\". For more information, see Creating Elasticsearch Domains in
  the Amazon Elasticsearch Service Developer Guide.
- `"EncryptionAtRestOptions"`: Specifies the Encryption At Rest Options.
- `"LogPublishingOptions"`: Map of LogType and LogPublishingOption, each containing options
  to publish a given type of Elasticsearch log.
- `"NodeToNodeEncryptionOptions"`: Specifies the NodeToNodeEncryptionOptions.
- `"SnapshotOptions"`: Option to set time, in UTC format, of the daily automated snapshot.
  Default value is 0 hours.
- `"TagList"`: A list of Tag added during domain creation.
- `"VPCOptions"`: Options to specify the subnets and security groups for VPC endpoint. For
  more information, see Creating a VPC in VPC Endpoints for Amazon Elasticsearch Service
  Domains
"""
function create_elasticsearch_domain(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/domain",
        Dict{String,Any}("DomainName" => DomainName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_elasticsearch_domain(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/domain",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("DomainName" => DomainName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_outbound_cross_cluster_search_connection(connection_alias, destination_domain_info, source_domain_info)
    create_outbound_cross_cluster_search_connection(connection_alias, destination_domain_info, source_domain_info, params::Dict{String,<:Any})

Creates a new cross-cluster search connection from a source domain to a destination domain.

# Arguments
- `connection_alias`: Specifies the connection alias that will be used by the customer for
  this connection.
- `destination_domain_info`: Specifies the DomainInformation for the destination
  Elasticsearch domain.
- `source_domain_info`: Specifies the DomainInformation for the source Elasticsearch domain.

"""
function create_outbound_cross_cluster_search_connection(
    ConnectionAlias,
    DestinationDomainInfo,
    SourceDomainInfo;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/ccs/outboundConnection",
        Dict{String,Any}(
            "ConnectionAlias" => ConnectionAlias,
            "DestinationDomainInfo" => DestinationDomainInfo,
            "SourceDomainInfo" => SourceDomainInfo,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_outbound_cross_cluster_search_connection(
    ConnectionAlias,
    DestinationDomainInfo,
    SourceDomainInfo,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/ccs/outboundConnection",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "ConnectionAlias" => ConnectionAlias,
                    "DestinationDomainInfo" => DestinationDomainInfo,
                    "SourceDomainInfo" => SourceDomainInfo,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_package(package_name, package_source, package_type)
    create_package(package_name, package_source, package_type, params::Dict{String,<:Any})

Create a package for use with Amazon ES domains.

# Arguments
- `package_name`: Unique identifier for the package.
- `package_source`: The customer S3 location PackageSource for importing the package.
- `package_type`: Type of package. Currently supports only TXT-DICTIONARY.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"PackageDescription"`: Description of the package.
"""
function create_package(
    PackageName,
    PackageSource,
    PackageType;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages",
        Dict{String,Any}(
            "PackageName" => PackageName,
            "PackageSource" => PackageSource,
            "PackageType" => PackageType,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_package(
    PackageName,
    PackageSource,
    PackageType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "PackageName" => PackageName,
                    "PackageSource" => PackageSource,
                    "PackageType" => PackageType,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_elasticsearch_domain(domain_name)
    delete_elasticsearch_domain(domain_name, params::Dict{String,<:Any})

Permanently deletes the specified Elasticsearch domain and all of its data. Once a domain
is deleted, it cannot be recovered.

# Arguments
- `domain_name`: The name of the Elasticsearch domain that you want to permanently delete.

"""
function delete_elasticsearch_domain(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/domain/$(DomainName)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_elasticsearch_domain(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/domain/$(DomainName)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_elasticsearch_service_role()
    delete_elasticsearch_service_role(params::Dict{String,<:Any})

Deletes the service-linked role that Elasticsearch Service uses to manage and maintain VPC
domains. Role deletion will fail if any existing VPC domains use the role. You must delete
any such Elasticsearch domains before deleting the role. See Deleting Elasticsearch Service
Role in VPC Endpoints for Amazon Elasticsearch Service Domains.

"""
function delete_elasticsearch_service_role(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/role";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_elasticsearch_service_role(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/role",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_inbound_cross_cluster_search_connection(connection_id)
    delete_inbound_cross_cluster_search_connection(connection_id, params::Dict{String,<:Any})

Allows the destination domain owner to delete an existing inbound cross-cluster search
connection.

# Arguments
- `connection_id`: The id of the inbound connection that you want to permanently delete.

"""
function delete_inbound_cross_cluster_search_connection(
    ConnectionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/ccs/inboundConnection/$(ConnectionId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_inbound_cross_cluster_search_connection(
    ConnectionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/ccs/inboundConnection/$(ConnectionId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_outbound_cross_cluster_search_connection(connection_id)
    delete_outbound_cross_cluster_search_connection(connection_id, params::Dict{String,<:Any})

Allows the source domain owner to delete an existing outbound cross-cluster search
connection.

# Arguments
- `connection_id`: The id of the outbound connection that you want to permanently delete.

"""
function delete_outbound_cross_cluster_search_connection(
    ConnectionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/ccs/outboundConnection/$(ConnectionId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_outbound_cross_cluster_search_connection(
    ConnectionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/es/ccs/outboundConnection/$(ConnectionId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_package(package_id)
    delete_package(package_id, params::Dict{String,<:Any})

Delete the package.

# Arguments
- `package_id`: Internal ID of the package that you want to delete. Use DescribePackages to
  find this value.

"""
function delete_package(PackageID; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/packages/$(PackageID)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_package(
    PackageID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "DELETE",
        "/2015-01-01/packages/$(PackageID)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_domain_auto_tunes(domain_name)
    describe_domain_auto_tunes(domain_name, params::Dict{String,<:Any})

Provides scheduled Auto-Tune action details for the Elasticsearch domain, such as Auto-Tune
action type, description, severity, and scheduled date.

# Arguments
- `domain_name`: Specifies the domain name for which you want Auto-Tune action details.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: Set this value to limit the number of results returned. If not specified,
  defaults to 100.
- `"NextToken"`: NextToken is sent in case the earlier API call results contain the
  NextToken. It is used for pagination.
"""
function describe_domain_auto_tunes(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/domain/$(DomainName)/autoTunes";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_domain_auto_tunes(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/domain/$(DomainName)/autoTunes",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_elasticsearch_domain(domain_name)
    describe_elasticsearch_domain(domain_name, params::Dict{String,<:Any})

Returns domain configuration information about the specified Elasticsearch domain,
including the domain ID, domain endpoint, and domain ARN.

# Arguments
- `domain_name`: The name of the Elasticsearch domain for which you want information.

"""
function describe_elasticsearch_domain(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/domain/$(DomainName)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_elasticsearch_domain(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/domain/$(DomainName)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_elasticsearch_domain_config(domain_name)
    describe_elasticsearch_domain_config(domain_name, params::Dict{String,<:Any})

Provides cluster configuration information about the specified Elasticsearch domain, such
as the state, creation date, update version, and update date for cluster options.

# Arguments
- `domain_name`: The Elasticsearch domain that you want to get information about.

"""
function describe_elasticsearch_domain_config(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/domain/$(DomainName)/config";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_elasticsearch_domain_config(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/domain/$(DomainName)/config",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_elasticsearch_domains(domain_names)
    describe_elasticsearch_domains(domain_names, params::Dict{String,<:Any})

Returns domain configuration information about the specified Elasticsearch domains,
including the domain ID, domain endpoint, and domain ARN.

# Arguments
- `domain_names`: The Elasticsearch domains for which you want information.

"""
function describe_elasticsearch_domains(
    DomainNames; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/domain-info",
        Dict{String,Any}("DomainNames" => DomainNames);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_elasticsearch_domains(
    DomainNames,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/domain-info",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("DomainNames" => DomainNames), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_elasticsearch_instance_type_limits(elasticsearch_version, instance_type)
    describe_elasticsearch_instance_type_limits(elasticsearch_version, instance_type, params::Dict{String,<:Any})

 Describe Elasticsearch Limits for a given InstanceType and ElasticsearchVersion. When
modifying existing Domain, specify the  DomainName  to know what Limits are supported for
modifying.

# Arguments
- `elasticsearch_version`:  Version of Elasticsearch for which  Limits  are needed.
- `instance_type`:  The instance type for an Elasticsearch cluster for which Elasticsearch
  Limits  are needed.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"domainName"`:  DomainName represents the name of the Domain that we are trying to
  modify. This should be present only if we are querying for Elasticsearch  Limits  for
  existing domain.
"""
function describe_elasticsearch_instance_type_limits(
    ElasticsearchVersion, InstanceType; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/instanceTypeLimits/$(ElasticsearchVersion)/$(InstanceType)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_elasticsearch_instance_type_limits(
    ElasticsearchVersion,
    InstanceType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/instanceTypeLimits/$(ElasticsearchVersion)/$(InstanceType)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_inbound_cross_cluster_search_connections()
    describe_inbound_cross_cluster_search_connections(params::Dict{String,<:Any})

Lists all the inbound cross-cluster search connections for a destination domain.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filters"`:  A list of filters used to match properties for inbound cross-cluster search
  connection. Available Filter names for this operation are:
  cross-cluster-search-connection-id source-domain-info.domain-name
  source-domain-info.owner-id source-domain-info.region destination-domain-info.domain-name
- `"MaxResults"`: Set this value to limit the number of results returned. If not specified,
  defaults to 100.
- `"NextToken"`:  NextToken is sent in case the earlier API call results contain the
  NextToken. It is used for pagination.
"""
function describe_inbound_cross_cluster_search_connections(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/ccs/inboundConnection/search";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_inbound_cross_cluster_search_connections(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/ccs/inboundConnection/search",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_outbound_cross_cluster_search_connections()
    describe_outbound_cross_cluster_search_connections(params::Dict{String,<:Any})

Lists all the outbound cross-cluster search connections for a source domain.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filters"`:  A list of filters used to match properties for outbound cross-cluster
  search connection. Available Filter names for this operation are:
  cross-cluster-search-connection-id destination-domain-info.domain-name
  destination-domain-info.owner-id destination-domain-info.region
  source-domain-info.domain-name
- `"MaxResults"`: Set this value to limit the number of results returned. If not specified,
  defaults to 100.
- `"NextToken"`:  NextToken is sent in case the earlier API call results contain the
  NextToken. It is used for pagination.
"""
function describe_outbound_cross_cluster_search_connections(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/ccs/outboundConnection/search";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_outbound_cross_cluster_search_connections(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/ccs/outboundConnection/search",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_packages()
    describe_packages(params::Dict{String,<:Any})

Describes all packages available to Amazon ES. Includes options for filtering, limiting the
number of results, and pagination.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filters"`: Only returns packages that match the DescribePackagesFilterList values.
- `"MaxResults"`: Limits results to a maximum number of packages.
- `"NextToken"`: Used for pagination. Only necessary if a previous API call includes a
  non-null NextToken value. If provided, returns results for the next page.
"""
function describe_packages(; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/describe";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_packages(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/describe",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_reserved_elasticsearch_instance_offerings()
    describe_reserved_elasticsearch_instance_offerings(params::Dict{String,<:Any})

Lists available reserved Elasticsearch instance offerings.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Set this value to limit the number of results returned. If not specified,
  defaults to 100.
- `"nextToken"`: NextToken should be sent in case if earlier API call produced result
  containing NextToken. It is used for pagination.
- `"offeringId"`: The offering identifier filter value. Use this parameter to show only the
  available offering that matches the specified reservation identifier.
"""
function describe_reserved_elasticsearch_instance_offerings(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/reservedInstanceOfferings";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_reserved_elasticsearch_instance_offerings(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/reservedInstanceOfferings",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_reserved_elasticsearch_instances()
    describe_reserved_elasticsearch_instances(params::Dict{String,<:Any})

Returns information about reserved Elasticsearch instances for this account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Set this value to limit the number of results returned. If not specified,
  defaults to 100.
- `"nextToken"`: NextToken should be sent in case if earlier API call produced result
  containing NextToken. It is used for pagination.
- `"reservationId"`: The reserved instance identifier filter value. Use this parameter to
  show only the reservation that matches the specified reserved Elasticsearch instance ID.
"""
function describe_reserved_elasticsearch_instances(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/reservedInstances";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_reserved_elasticsearch_instances(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/reservedInstances",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    dissociate_package(domain_name, package_id)
    dissociate_package(domain_name, package_id, params::Dict{String,<:Any})

Dissociates a package from the Amazon ES domain.

# Arguments
- `domain_name`: Name of the domain that you want to associate the package with.
- `package_id`: Internal ID of the package that you want to associate with a domain. Use
  DescribePackages to find this value.

"""
function dissociate_package(
    DomainName, PackageID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/dissociate/$(PackageID)/$(DomainName)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function dissociate_package(
    DomainName,
    PackageID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/dissociate/$(PackageID)/$(DomainName)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_compatible_elasticsearch_versions()
    get_compatible_elasticsearch_versions(params::Dict{String,<:Any})

 Returns a list of upgrade compatible Elastisearch versions. You can optionally pass a
DomainName  to get all upgrade compatible Elasticsearch versions for that specific domain.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"domainName"`:
"""
function get_compatible_elasticsearch_versions(;
    aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/compatibleVersions";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_compatible_elasticsearch_versions(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/compatibleVersions",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_package_version_history(package_id)
    get_package_version_history(package_id, params::Dict{String,<:Any})

Returns a list of versions of the package, along with their creation time and commit
message.

# Arguments
- `package_id`: Returns an audit history of versions of the package.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Limits results to a maximum number of versions.
- `"nextToken"`: Used for pagination. Only necessary if a previous API call includes a
  non-null NextToken value. If provided, returns results for the next page.
"""
function get_package_version_history(
    PackageID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/packages/$(PackageID)/history";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_package_version_history(
    PackageID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/packages/$(PackageID)/history",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_upgrade_history(domain_name)
    get_upgrade_history(domain_name, params::Dict{String,<:Any})

Retrieves the complete history of the last 10 upgrades that were performed on the domain.

# Arguments
- `domain_name`:

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`:
- `"nextToken"`:
"""
function get_upgrade_history(DomainName; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/upgradeDomain/$(DomainName)/history";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_upgrade_history(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/upgradeDomain/$(DomainName)/history",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_upgrade_status(domain_name)
    get_upgrade_status(domain_name, params::Dict{String,<:Any})

Retrieves the latest status of the last upgrade or upgrade eligibility check that was
performed on the domain.

# Arguments
- `domain_name`:

"""
function get_upgrade_status(DomainName; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/upgradeDomain/$(DomainName)/status";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_upgrade_status(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/upgradeDomain/$(DomainName)/status",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_domain_names()
    list_domain_names(params::Dict{String,<:Any})

Returns the name of all Elasticsearch domains owned by the current user's account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"engineType"`:  Optional parameter to filter the output by domain engine type.
  Acceptable values are 'Elasticsearch' and 'OpenSearch'.
"""
function list_domain_names(; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "GET", "/2015-01-01/domain"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_domain_names(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/domain",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_domains_for_package(package_id)
    list_domains_for_package(package_id, params::Dict{String,<:Any})

Lists all Amazon ES domains associated with the package.

# Arguments
- `package_id`: The package for which to list domains.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Limits results to a maximum number of domains.
- `"nextToken"`: Used for pagination. Only necessary if a previous API call includes a
  non-null NextToken value. If provided, returns results for the next page.
"""
function list_domains_for_package(
    PackageID; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/packages/$(PackageID)/domains";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_domains_for_package(
    PackageID,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/packages/$(PackageID)/domains",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_elasticsearch_instance_types(elasticsearch_version)
    list_elasticsearch_instance_types(elasticsearch_version, params::Dict{String,<:Any})

List all Elasticsearch instance types that are supported for given ElasticsearchVersion

# Arguments
- `elasticsearch_version`: Version of Elasticsearch for which list of supported
  elasticsearch instance types are needed.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"domainName"`: DomainName represents the name of the Domain that we are trying to
  modify. This should be present only if we are querying for list of available Elasticsearch
  instance types when modifying existing domain.
- `"maxResults"`:  Set this value to limit the number of results returned. Value provided
  must be greater than 30 else it wont be honored.
- `"nextToken"`: NextToken should be sent in case if earlier API call produced result
  containing NextToken. It is used for pagination.
"""
function list_elasticsearch_instance_types(
    ElasticsearchVersion; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/instanceTypes/$(ElasticsearchVersion)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_elasticsearch_instance_types(
    ElasticsearchVersion,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/instanceTypes/$(ElasticsearchVersion)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_elasticsearch_versions()
    list_elasticsearch_versions(params::Dict{String,<:Any})

List all supported Elasticsearch versions

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`:  Set this value to limit the number of results returned. Value provided
  must be greater than 10 else it wont be honored.
- `"nextToken"`:
"""
function list_elasticsearch_versions(; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/versions";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_elasticsearch_versions(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/es/versions",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_packages_for_domain(domain_name)
    list_packages_for_domain(domain_name, params::Dict{String,<:Any})

Lists all packages associated with the Amazon ES domain.

# Arguments
- `domain_name`: The name of the domain for which you want to list associated packages.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Limits results to a maximum number of packages.
- `"nextToken"`: Used for pagination. Only necessary if a previous API call includes a
  non-null NextToken value. If provided, returns results for the next page.
"""
function list_packages_for_domain(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/domain/$(DomainName)/packages";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_packages_for_domain(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/domain/$(DomainName)/packages",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_tags(arn)
    list_tags(arn, params::Dict{String,<:Any})

Returns all tags for the given Elasticsearch domain.

# Arguments
- `arn`:  Specify the ARN for the Elasticsearch domain to which the tags are attached that
  you want to view.

"""
function list_tags(arn; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "GET",
        "/2015-01-01/tags/",
        Dict{String,Any}("arn" => arn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags(
    arn, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "GET",
        "/2015-01-01/tags/",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("arn" => arn), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    purchase_reserved_elasticsearch_instance_offering(reservation_name, reserved_elasticsearch_instance_offering_id)
    purchase_reserved_elasticsearch_instance_offering(reservation_name, reserved_elasticsearch_instance_offering_id, params::Dict{String,<:Any})

Allows you to purchase reserved Elasticsearch instances.

# Arguments
- `reservation_name`: A customer-specified identifier to track this reservation.
- `reserved_elasticsearch_instance_offering_id`: The ID of the reserved Elasticsearch
  instance offering to purchase.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"InstanceCount"`: The number of Elasticsearch instances to reserve.
"""
function purchase_reserved_elasticsearch_instance_offering(
    ReservationName,
    ReservedElasticsearchInstanceOfferingId;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/purchaseReservedInstanceOffering",
        Dict{String,Any}(
            "ReservationName" => ReservationName,
            "ReservedElasticsearchInstanceOfferingId" =>
                ReservedElasticsearchInstanceOfferingId,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function purchase_reserved_elasticsearch_instance_offering(
    ReservationName,
    ReservedElasticsearchInstanceOfferingId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/purchaseReservedInstanceOffering",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "ReservationName" => ReservationName,
                    "ReservedElasticsearchInstanceOfferingId" =>
                        ReservedElasticsearchInstanceOfferingId,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    reject_inbound_cross_cluster_search_connection(connection_id)
    reject_inbound_cross_cluster_search_connection(connection_id, params::Dict{String,<:Any})

Allows the destination domain owner to reject an inbound cross-cluster search connection
request.

# Arguments
- `connection_id`: The id of the inbound connection that you want to reject.

"""
function reject_inbound_cross_cluster_search_connection(
    ConnectionId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "PUT",
        "/2015-01-01/es/ccs/inboundConnection/$(ConnectionId)/reject";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function reject_inbound_cross_cluster_search_connection(
    ConnectionId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "PUT",
        "/2015-01-01/es/ccs/inboundConnection/$(ConnectionId)/reject",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    remove_tags(arn, tag_keys)
    remove_tags(arn, tag_keys, params::Dict{String,<:Any})

Removes the specified set of tags from the specified Elasticsearch domain.

# Arguments
- `arn`: Specifies the ARN for the Elasticsearch domain from which you want to delete the
  specified tags.
- `tag_keys`: Specifies the TagKey list which you want to remove from the Elasticsearch
  domain.

"""
function remove_tags(ARN, TagKeys; aws_config::AbstractAWSConfig=global_aws_config())
    return elasticsearch_service(
        "POST",
        "/2015-01-01/tags-removal",
        Dict{String,Any}("ARN" => ARN, "TagKeys" => TagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function remove_tags(
    ARN,
    TagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/tags-removal",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("ARN" => ARN, "TagKeys" => TagKeys), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    start_elasticsearch_service_software_update(domain_name)
    start_elasticsearch_service_software_update(domain_name, params::Dict{String,<:Any})

Schedules a service software update for an Amazon ES domain.

# Arguments
- `domain_name`: The name of the domain that you want to update to the latest service
  software.

"""
function start_elasticsearch_service_software_update(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/serviceSoftwareUpdate/start",
        Dict{String,Any}("DomainName" => DomainName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function start_elasticsearch_service_software_update(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/serviceSoftwareUpdate/start",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("DomainName" => DomainName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_elasticsearch_domain_config(domain_name)
    update_elasticsearch_domain_config(domain_name, params::Dict{String,<:Any})

Modifies the cluster configuration of the specified Elasticsearch domain, setting as
setting the instance type and the number of instances.

# Arguments
- `domain_name`: The name of the Elasticsearch domain that you are updating.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"AccessPolicies"`: IAM access policy as a JSON-formatted string.
- `"AdvancedOptions"`: Modifies the advanced option to allow references to indices in an
  HTTP request body. Must be false when configuring access to individual sub-resources. By
  default, the value is true. See Configuration Advanced Options for more information.
- `"AdvancedSecurityOptions"`: Specifies advanced security options.
- `"AutoTuneOptions"`: Specifies Auto-Tune options.
- `"CognitoOptions"`: Options to specify the Cognito user and identity pools for Kibana
  authentication. For more information, see Amazon Cognito Authentication for Kibana.
- `"DomainEndpointOptions"`: Options to specify configuration that will be applied to the
  domain endpoint.
- `"DryRun"`:  This flag, when set to True, specifies whether the UpdateElasticsearchDomain
  request should return the results of validation checks without actually applying the
  change. This flag, when set to True, specifies the deployment mechanism through which the
  update shall be applied on the domain. This will not actually perform the Update.
- `"EBSOptions"`: Specify the type and size of the EBS volume that you want to use.
- `"ElasticsearchClusterConfig"`: The type and number of instances to instantiate for the
  domain cluster.
- `"EncryptionAtRestOptions"`: Specifies the Encryption At Rest Options.
- `"LogPublishingOptions"`: Map of LogType and LogPublishingOption, each containing options
  to publish a given type of Elasticsearch log.
- `"NodeToNodeEncryptionOptions"`: Specifies the NodeToNodeEncryptionOptions.
- `"SnapshotOptions"`: Option to set the time, in UTC format, for the daily automated
  snapshot. Default value is 0 hours.
- `"VPCOptions"`: Options to specify the subnets and security groups for VPC endpoint. For
  more information, see Creating a VPC in VPC Endpoints for Amazon Elasticsearch Service
  Domains
"""
function update_elasticsearch_domain_config(
    DomainName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/domain/$(DomainName)/config";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_elasticsearch_domain_config(
    DomainName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/domain/$(DomainName)/config",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_package(package_id, package_source)
    update_package(package_id, package_source, params::Dict{String,<:Any})

Updates a package for use with Amazon ES domains.

# Arguments
- `package_id`: Unique identifier for the package.
- `package_source`:

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"CommitMessage"`: An info message for the new version which will be shown as part of
  GetPackageVersionHistoryResponse.
- `"PackageDescription"`: New description of the package.
"""
function update_package(
    PackageID, PackageSource; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/update",
        Dict{String,Any}("PackageID" => PackageID, "PackageSource" => PackageSource);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_package(
    PackageID,
    PackageSource,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/packages/update",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "PackageID" => PackageID, "PackageSource" => PackageSource
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    upgrade_elasticsearch_domain(domain_name, target_version)
    upgrade_elasticsearch_domain(domain_name, target_version, params::Dict{String,<:Any})

Allows you to either upgrade your domain or perform an Upgrade eligibility check to a
compatible Elasticsearch version.

# Arguments
- `domain_name`:
- `target_version`: The version of Elasticsearch that you intend to upgrade the domain to.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"PerformCheckOnly"`:  This flag, when set to True, indicates that an Upgrade Eligibility
  Check needs to be performed. This will not actually perform the Upgrade.
"""
function upgrade_elasticsearch_domain(
    DomainName, TargetVersion; aws_config::AbstractAWSConfig=global_aws_config()
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/upgradeDomain",
        Dict{String,Any}("DomainName" => DomainName, "TargetVersion" => TargetVersion);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function upgrade_elasticsearch_domain(
    DomainName,
    TargetVersion,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return elasticsearch_service(
        "POST",
        "/2015-01-01/es/upgradeDomain",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "DomainName" => DomainName, "TargetVersion" => TargetVersion
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
#using Distributed
#addprocs(1)
#@everywhere
include("local_hh_neuron.jl")
using NSGAII
#@everywhere
include("../src/units.jl")
#@everywhere
using .HHNSGA
#=
seed = pop[1]
bincoded = NSGAII.encode(seed, HHNSGA.bc)
decoded = NSGAII.decode(bincoded, HHNSGA.bc)
scores = map(HHNSGA.z,pop)
@show(scores)

pop = []
for i in 1:3
   append!(pop,[HHNSGA.init_function()])
end
=#

function fdecode(x)
   decoded = NSGAII.decode(x, HHNSGA.bc)

   #y = [ convert(Int64,i) for i in Int(x) ]
   return decoded
end
#@test
#@show decoded
#@show seed
#assert decoded .≈ seed

#lower_list = [v[0] for k,v in ranges.items()]
#upper_list = [v[1] for k,v in ranges.items()]

#NSGAII.create_indiv(pop[1], fdecode, HHNSGA.z, HHNSGA.init_function2)

#@show(pop)
#pop = map(HHNSGA.init_function,1:3)
#NSGAII.create_indiv(pop[1],HHNSGA.z)
#=
println(pop)

export SNN

include("../src/SpikingNeuralNetworks.jl")
include("../src/units.jl")
include("../src/plot.jl")
#SNN = SpikingNeuralNetworks.SNN

=#

#repop = NSGAII.nsga(2,2,HHNSGA.z,HHNSGA.init_function())
#append!(pop,
using Plots
unicodeplots()

function plot_pop(P)
    P = filter(x -> x.rank == 1, P)
    plot(map(x -> x.y[1], P), map(x -> x.y[2], P))#, "bo", markersize = 1)
    #show()
    #sleep(0.1)
end

repop = NSGAII.nsga(10,10,HHNSGA.z,HHNSGA.init_function, fplot = plot_pop)
x1 = sort(repop, by = ind -> ind.y[1])[end];
decoded = fdecode(x1.pheno)
println("z = $(x1.y)")
#=
NSGAII.indiv(copy(pop[1]),HHNSGA.z)

println(scores)
non_dom = NSGAIII.fast_non_dominated_sort!(scores)[1]
pop = setdiff(pop, non_dom)
HHNSGA.plot_pop(scores)
@show(pop)
@show(scores)
try
   pop2 = Any[]
   for x in pop
      append!(pop,NSGAII.create_indiv(x, HHNSGA.init_function2, HHNSGA.z))
   end
catch
   @show(pop)
   @show(scores)
end
=#

max_stars_repo_name: russelljjarvis/juliaSNN

max_issues_repo_name: russelljjarvis/juliaSNN

max_forks_repo_name: russelljjarvis/juliaSNN


text:
module GrammianAngularFields

# 1. pkg > generate Blabba
# 2. shell > cd Blabba
# 3. pkg > activate .
# 4. import Blabba
# 5. test the different functions
# 6. write more code
# 7. quit julia
# 8. go to 3.

import StatsBase
import PlotlyJS

export grammify

include("transformations.jl")
include("grammians.jl")

greet() = print("This is Grammian Angular Fields!")

end # module


text:
#ДАНО: Робот - в произвольной клетке ограниченного прямоугольной рамкой поля без внутренних перегородок и маркеров.
#РЕЗУЛЬТАТ: Робот - в исходном положении в центре косого креста (в форме X) из маркеров.
function kosoykrest(r::Robot)
    for i in 0:3

        while !isborder(r, HorizonSide(i)) && !isborder(r, HorizonSide((i+1)%4))
            move!(r, HorizonSide(i))
            move!(r, HorizonSide((i+1)%4))
            putmarker!(r)
        end

        while ismarker(r)
            move!(r, HorizonSide((i+2)%4))
            move!(r, HorizonSide((i+2+1)%4))
        end

        if i == 3
            putmarker!(r)
            break
        end
    end
end

max_stars_repo_name: listova-nastya/mirea-progs

max_issues_repo_name: listova-nastya/mirea-progs

max_forks_repo_name: listova-nastya/mirea-progs


text:
using DrWatson
@quickactivate
using Test
using GenerativeAD

@testset "Models" begin
    include("knn.jl")
    include("vae.jl")
    include("aae.jl")
    include("gan.jl")
end


text: # TODO (max): do we need a unified API for io?


text:
function lgd24()
#
#  test polynomial suggested by Goedecker
#   Legendre polynomial of degree 24
#
    p = lgd(24);
    z = [-.9951872199970214; -.9747285559713095; -.9382745520027328; -.8864155270044010;
         -.8200019859739029; -.7401241915785544; -.6480936519369756; -.5454214713888395;
         -.4337935076260451; -.3150426796961634; -.1911188674736163; -.6405689286260563e-1;
         .6405689286260563e-1; .1911188674736163; .3150426796961634; .4337935076260451;
         .5454214713888395; .6480936519369756; .7401241915785544; .8200019859739029;
         .8864155270044010; .9382745520027328; .9747285559713095; .9951872199970214]
    z = [z ones(24)]
    p, PolyZeros(z)
end


text:
export SVDLikeRepresentation
"""
    X = U*S*V'

    SVD like factorization of a low rank matrix into factors U ∈ ℝⁿˣʳ, S ∈ ℝʳˣʳ, V ∈ ℝᵐˣʳ.
    The columns of U span the range of X, the colomuns of V span the co-range of X and S describes the map between
    co-range and range. The factorization is non-unique and U and V need not be orthogonal!
    However, often U and V are chosen orthogonal to allow for cheap (pseudo)inversion. In that case, note that
    orthogonality of U and V is not guaranteed to and in fact will rarely be preserved under the operations that
    are supported (multiplication, addition, etc.). In order to reorthonormalize U and V, simply call `orthonormalize!(X, alg)`
    where alg refers to the algorithm used to compute the orthonormalization:
        * QRFact()
        * SVDFact()
        * GradientDescent()
"""
mutable struct SVDLikeRepresentation{uType, sType, vType} <: AbstractLowRankRepresentation
    U::uType
    S::sType
    V::vType
end

rank(LRA::SVDLikeRepresentation) = size(LRA.S,1)
size(LRA::SVDLikeRepresentation) = (size(LRA.U,1), size(LRA.V,1))
size(LRA::SVDLikeRepresentation, ::Val{1}) = size(LRA.U,1)
size(LRA::SVDLikeRepresentation, ::Val{2}) = size(LRA.V,1)
size(LRA::SVDLikeRepresentation, i::Int) = size(LRA, Val(i))
Matrix(LRA::SVDLikeRepresentation) = LRA.U*LRA.S*LRA.V'
getindex(LRA::SVDLikeRepresentation, i::Int, j::Int) = sum(LRA.U[i,k]*sum(LRA.S[k,s]*LRA.V[j,s] for s in 1:rank(LRA)) for k in 1:rank(LRA))
getindex(LRA::SVDLikeRepresentation, i, j::Int) = SVDLikeRepresentation(LRA.U[i,:], LRA.S, LRA.V[[j],:])
getindex(LRA::SVDLikeRepresentation, i::Int, j) = SVDLikeRepresentation(LRA.U[[i],:], LRA.S, LRA.V[j,:])
getindex(LRA::SVDLikeRepresentation, i, j) = SVDLikeRepresentation(LRA.U[i,:], LRA.S, LRA.V[j,:])
getindex(LRA::SVDLikeRepresentation, ::Colon, j::AbstractVector) = SVDLikeRepresentation(LRA.U, LRA.S, LRA.V[j,:])
getindex(LRA::SVDLikeRepresentation, ::Colon, j::Int) = SVDLikeRepresentation(LRA.U, LRA.S, LRA.V[[j],:])
getindex(LRA::SVDLikeRepresentation, i::AbstractVector, ::Colon) = SVDLikeRepresentation(LRA.U[i,:], LRA.S, LRA.V)
getindex(LRA::SVDLikeRepresentation, i::Int, ::Colon) = SVDLikeRepresentation(LRA.U[[i],:], LRA.S, LRA.V)
hcat(A::SVDLikeRepresentation, B::SVDLikeRepresentation) = SVDLikeRepresentation(hcat(A.U, B.U), blockdiagonal(A.S, B.S), blockdiagonal(A.V, B.V))
vcat(A::SVDLikeRepresentation, B::SVDLikeRepresentation) = SVDLikeRepresentation(blockdiagonal(A.U, B.U), blockdiagonal(A.S, B.S), hcat(A.V, B.V))

# simple support of adjoints, probably not ideal though
adjoint(LRA::SVDLikeRepresentation) = TwoFactorRepresentation(conj(LRA.V),LRA.S',conj(LRA.U))

# converting between representations
TwoFactorRepresentation(A::SVDLikeRepresentation) = TwoFactorRepresentation(A.U, A.V*A.S')
function SVDLikeRepresentation(A::TwoFactorRepresentation)
    U, S, V = svd(A.Z)
    return SVDLikeRepresentation(A.U*V, S', U)
end

## *
*(A::AbstractMatrix, B::SVDLikeRepresentation) = SVDLikeRepresentation(A*B.U, B.S, B.V)
*(A::SVDLikeRepresentation, B::AbstractMatrix) = SVDLikeRepresentation(A.U, A.S, B'*A.V)
*(A::SVDLikeRepresentation, ::UniformScaling) = A
*(::UniformScaling, A::SVDLikeRepresentation) = A
function *(A::SVDLikeRepresentation, B::SVDLikeRepresentation)
    if rank(A) ≤ rank(B)
        return SVDLikeRepresentation(A.U, A.S, B.V*B.S'*(B.U'*A.V))
    else
        return SVDLikeRepresentation(A.U*A.S*(A.V'*B.U), B.S, B.V)
    end
end
*(A::SVDLikeRepresentation, α::Number) = SVDLikeRepresentation(A.U, α*A.S, A.V)
*(α::Number, A::SVDLikeRepresentation) = SVDLikeRepresentation(A.U, α*A.S, A.V)
*(A::SVDLikeRepresentation, v::AbstractVector) = A.U*(A.S*(A.V'*v))
*(v::AbstractVector, A::SVDLikeRepresentation) = ((v*A.U)*A.S)*A.V'

# default to TwoFactorRepresentation
*(A::TwoFactorRepresentation, B::SVDLikeRepresentation) = A*TwoFactorRepresentation(B)
*(A::SVDLikeRepresentation, B::TwoFactorRepresentation) = TwoFactorRepresentation(B)*A

## +
+(A::SVDLikeRepresentation, B::SVDLikeRepresentation) = SVDLikeRepresentation(hcat(A.U, B.U), blockdiagonal(A.S, B.S),hcat(A.V, B.V))
+(A::AbstractMatrix, B::SVDLikeRepresentation) = A + Matrix(B)
+(A::SVDLikeRepresentation, B::AbstractMatrix) = Matrix(A) + B
-(A::SVDLikeRepresentation, B::SVDLikeRepresentation) = SVDLikeRepresentation(hcat(A.U, B.U), blockdiagonal(A.S, -B.S), hcat(A.V, B.V))
-(A::AbstractMatrix, B::SVDLikeRepresentation) = A - Matrix(B)
-(A::SVDLikeRepresentation, B::AbstractMatrix) = Matrix(A) - B

# default to TwoFactorRepresentation
+(A::TwoFactorRepresentation, B::SVDLikeRepresentation) = A+TwoFactorRepresentation(B)
+(A::SVDLikeRepresentation, B::TwoFactorRepresentation) = B+A
-(A::TwoFactorRepresentation, B::SVDLikeRepresentation) = A-TwoFactorRepresentation(B)
-(A::SVDLikeRepresentation, B::TwoFactorRepresentation) = TwoFactorRepresentation(A)-B

## .*
function hadamard(A::SVDLikeRepresentation, B::SVDLikeRepresentation)
    @assert size(A) == size(B) "elementwise product is only defined between matrices of equal dimension"
    rA, rB = rank(A), rank(B)
    r_new = rA*rB
    U = ones(eltype(A.U), size(A,1), r_new)
    V = ones(eltype(A.V), size(A,2), r_new)
    S = ones(eltype(A.S), r_new, r_new)
    AUcols = [@view A.U[:,i] for i in 1:rA]
    AVcols = [@view A.V[:,i] for i in 1:rA]
    BUcols = [@view B.U[:,i] for i in 1:rB]
    BVcols = [@view B.V[:,i] for i in 1:rB]
    k = 0
    for r1 in 1:rA, r2 in 1:rB
        k += 1
        U[:,k] = AUcols[r1] .* BUcols[r2]
        V[:,k] = AVcols[r1] .* BVcols[r2]
        l = 0
        for k1 in 1:rA, k2 in 1:rB
            l += 1
            S[k,l] = A.S[r1,k1]*B.S[r2,k2]
        end
    end
    return SVDLikeRepresentation(U,S,V)
end

# default to TwoFactorRepresentation
hadamard(A::TwoFactorRepresentation, B::SVDLikeRepresentation) = hadamard(A, TwoFactorRepresentation(B))
hadamard(A::SVDLikeRepresentation, B::TwoFactorRepresentation) = hadamard(TwoFactorRepresentation(A), B)

## .^d
# very suboptimal
function elpow(A::SVDLikeRepresentation, d::Int)
    @assert d >= 1 "elementwise power operation 'elpow' only defined for positive powers"
    r = rank(A)
    r_new = binomial(r+d-1, d)

    # the following sequence is not ideal but cheap under the premise of low rank, need to be improved though
    U, S, V = svd(A.S)
    A.U .= A.U*U
    A.V .= A.V*V
    A.S .= diagm(S)

    Ucols = [@view A.U[:,i] for i in 1:r]
    Vcols = [@view A.V[:,i] for i in 1:r]
    U = ones(eltype(A.U), size(A,1), r_new)
    V = ones(eltype(A.V), size(A,2), r_new)
    S = zeros(eltype(A.S), r_new, r_new)
    k = 0
    multi_exps = multiexponents(r,d)
    for exps in multi_exps
        k += 1
        S[k,k] += multinomial(exps...)
        for j in 1:r
            if exps[j] != 0
                U[:, k] .*= Ucols[j].^exps[j]
                V[:, k] .*= Vcols[j].^exps[j]
                S[k,k] *= A.S[j,j]^exps[j]
            end
        end
    end
    return SVDLikeRepresentation(U,S,V)
end

## special cases
function add_to_cols(LRA::SVDLikeRepresentation, v::AbstractVector)
    return LRA + SVDLikeRepresentation(v, ones(eltype(v), 1, 1), ones(eltype(v), size(LRA, 2)))
end

function multiply_cols(LRA::SVDLikeRepresentation, v::AbstractVector)
    return hadamard(LRA, SVDLikeRepresentation(v, ones(eltype(v), 1, 1), ones(eltype(v), size(LRA, 2))))
end

function add_to_rows(LRA::SVDLikeRepresentation, v::AbstractVector)
    return LRA + SVDLikeRepresentation(ones(eltype(v), size(LRA, 1)), ones(eltype(v), 1, 1), v)
end

function multiply_rows(LRA::SVDLikeRepresentation, v::AbstractVector)
    return hadamard(LRA, SVDLikeRepresentation(ones(eltype(v), size(LRA, 1)), ones(eltype(v), 1, 1), v))
end

function add_scalar(LRA::SVDLikeRepresentation, α::Number)
    return LRA + SVDLikeRepresentation(ones(eltype(α), size(LRA, 1)), [α], ones(eltype(α), size(LRA,2)))
end

## rounding
function svd(A::SVDLikeRepresentation, alg=QRFact())
    orthonormalize!(A, alg)
    U_, S_, V_ = svd(A.S)
    return SVDLikeRepresentation(A.U*U_, S_, A.V*V_)
end

function qr(A::SVDLikeRepresentation, alg=QRFact())
    orthonormalize!(A.U, A.S, alg)
    U_, R_ = qr(A.S*A.V')
    return TwoFactorRepresentation(A.U*U_, R_')
end

function round(A::SVDLikeRepresentation, alg = SVDFact(); tol = sqrt(eps(eltype(A.U))), rmin::Int = 1, rmax::Int = rank(A), alg_orthonormalize = QRFact())
    orthonormalize!(A, alg_orthonormalize)
    S_lr = truncated_svd(A.S, alg, tol = tol, rmin = rmin, rmax = rmax)
    return SVDLikeRepresentation(A.U*S_lr.U, S_lr.S, A.V*S_lr.V)
end

function round(A::SVDLikeRepresentation, rank::Int, alg = SVDFact(); alg_orthonormalize=QRFact())
    orthonormalize!(A, alg_orthonormalize)
    S_lr = truncated_svd(A.S, rank, alg)
    return SVDLikeRepresentation(A.U*S_lr.U, S_lr.S, A.V*S_lr.V)
end

## orthonormalization
function orthonormalize!(LRA::SVDLikeRepresentation, alg)
    orthonormalize!(LRA.U, LRA.S', alg)
    orthonormalize!(LRA.V, LRA.S, alg)
end


text:
@noinline function dostuff(A; B = I)
  StrideArrays.@avx for i in eachindex(A)
    A[i] += 1
  end
  C = A * B
  s = zero(eltype(C))
  StrideArrays.@avx for i in eachindex(C)
    s += C[i]
  end
  s
end
function gc_preserve_test()
  A = @StrideArray rand(8, $(2 << 2))
  B = @StrideArray rand($(1 << 3), 8)
  @gc_preserve dostuff(A, B = B)
end

@testset "Miscellaneous" begin
  x = @StrideArray rand(127)
  @test maximum(abs, x) == maximum(abs, Array(x))
  y = @StrideArray rand(3)
  @test maximum(abs, y) == maximum(abs, Array(y))
  @test iszero(@allocated gc_preserve_test())

  A = @StrideArray rand($(5 << 1), $(1 << 3))
  @test StrideArrays.size(A) === (StaticInt(10), StaticInt(8))
  A_u = view(A, StaticInt(1):StaticInt(6), :)
  A_l = view(A, StaticInt(7):StaticInt(10), :)
  @test A == @inferred(vcat(A_u, A_l))
  @test StrideArrays.size(A) === StrideArrays.size(vcat(A_u, A_l))

  # On 1.5 tests fail if you don't do this first.
  @test pointer(view(A, 1:StaticInt(6), :)) == pointer(A)
  A_u = view(A, 1:StaticInt(6), :)
  A_l = view(A, StaticInt(7):StaticInt(10), :)
  @test A == @inferred(vcat(A_u, A_l))
  @test StrideArrays.size(A) == StrideArrays.size(vcat(A_u, A_l))
  @test StrideArrays.size(A) !== StrideArrays.size(vcat(A_u, A_l))

  Aa = Array(A)
  @test sum(A) ≈ sum(Aa)
  @test maximum(A) == maximum(Aa) == maximum(abs, @. -A)
  @test mapreduce(abs2, +, A) ≈ mapreduce(abs2, +, Aa)

  @test A[1, 1] == A[1] == vec(A)[1]
  A[1, 1] = 3
  @test A[1, 1] == A[1] == vec(A)[1] == 3
  A[2] = 4
  @test A[2, 1] == A[2] == vec(A)[2] == 4
  vec(A)[3] = 5
  @test A[3, 1] == A[3] == vec(A)[3] == 5

  @test ArrayInterface.stride_rank(StrideArrays.similar_layout(A')) ===
        ArrayInterface.stride_rank(StrideArrays.similar_layout(Aa')) ===
        (StaticInt(2), StaticInt(1))
  @test ArrayInterface.contiguous_axis(StrideArrays.similar_layout(A')) ===
        ArrayInterface.contiguous_axis(StrideArrays.similar_layout(Aa')) ===
        StrideArrays.StaticInt{2}()

  let B = @StrideArray rand(10, 10)
    @test exp(B) ≈ exp(Array(B))
  end
end


text:
using BinaryBuilder, Pkg

name = "FastANI"
version = v"1.33.0"
sources = [
    GitSource("https://github.com/ParBLiSS/FastANI.git", "6531da0957344d2a56e3eeb9bb83fea02cc4abe0"),
]

script = raw"""
cd ${WORKSPACE}/srcdir/FastANI
mkdir -p "${bindir}"
c++ -O3 -DNDEBUG -std=c++11 -Isrc -fopenmp   src/cgi/core_genome_identity.cpp -o "${bindir}/fastANI${exeext}" -lgsl -lgslcblas -lz -lm
"""

platforms = supported_platforms()
platforms = filter(!Sys.iswindows, platforms)
platforms = expand_cxxstring_abis(platforms)

products = [
    ExecutableProduct("fastANI", :fastANI),
]

dependencies = [
    # Dependency(PackageSpec(name="Boost_jll", uuid="28df3c45-c428-5900-9ff8-a3135698ca75")),
    Dependency(PackageSpec(name="GSL_jll", uuid="1b77fbbe-d8ee-58f0-85f9-836ddc23a7a4")),
    Dependency(PackageSpec(name="Zlib_jll", uuid="83775a58-1f1d-513f-b197-d71354ab007a")),
    Dependency(PackageSpec(name="CompilerSupportLibraries_jll", uuid="e66e0078-7015-5450-92f7-15fbd957f2ae"); platforms=filter(!Sys.isbsd, platforms)),
    Dependency(PackageSpec(name="LLVMOpenMP_jll", uuid="1d63c593-3942-5779-bab2-d838dc0a180e"); platforms=filter(Sys.isbsd, platforms)),
]

build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies, julia_compat="1.6")