text:
using POMDPs
using ContinuousPOMDPTreeSearchExperiments
using POMDPToolbox
using POMCP
using POMCPOW
using LightDarkPOMDPs
using ProgressMeter
using PmapProgressMeter
using ParticleFilters
using JLD
using CPUTime

N = 20

@everywhere begin
    using LightDarkPOMDPs
    using POMDPs
    using ContinuousPOMDPTreeSearchExperiments
    using POMDPToolbox
    using POMCP
    using POMCPOW
    using ParticleFilters

    pomdp = LightDark2DTarget(term_radius=0.1,
                              init_dist=SymmetricNormal2([2.0, 2.0], 5.0),
                              discount=0.95)
    p_rng = MersenneTwister(4)
    solvers = Dict{String, Union{Solver,Policy}}(
        #=
        "heuristic" => begin
            homing_policy = SimpleFeedback(gain=1.0, max_radius=10.0)
            exploring_up = ObsAdaptiveParticleFilter(pomdp, LowVarianceResampler(1000), 0.05, copy(p_rng))
            homing_up = ObsAdaptiveParticleFilter(pomdp, LowVarianceResampler(1000), 0.0, copy(p_rng))
            InfoGatherHeur(5.0, 0.03, homing_policy, exploring_up, homing_up)
        end,

        "pomcpdpw" => begin
            rng3 = copy(p_rng)
            action_gen = AdaptiveRadiusRandom(max_radius=6.0, to_zero_first=true, to_light_second=true, rng=rng3)
            rollout_policy = RadiusRandom(radius=10.0, rng=rng3)
            tree_queries = 1_000_000
            solver = POMCPDPWSolver(next_action=action_gen,
                                    tree_queries=tree_queries,
                                    c=5.0,
                                    max_depth=40,
                                    k_action=10.0,
                                    alpha_action=1/8,
                                    k_observation=4.0,
                                    alpha_observation=1/8,
                                    estimate_value=OneStepValue(),
                                    default_action=Vec2(0.1, 0.1),
                                    rng=rng3
                                   )
        end,

        "bt_100_osv_100k" => begin
            rng3 = copy(p_rng)
            action_gen = AdaptiveRadiusRandom(max_radius=6.0, to_zero_first=true, to_light_second=true, rng=rng3)
            rollout_policy = SimpleFeedback(max_radius=10.0)
            tree_queries = 100_000
            node_updater = ObsAdaptiveParticleFilter(pomdp, LowVarianceResampler(100), 0.05, rng3)
            solver = POMCPDPWSolver(next_action=action_gen,
                                    tree_queries=tree_queries,
                                    c=5.0,
                                    max_depth=40,
                                    k_action=10.0,
                                    alpha_action=1/8,
                                    k_observation=4.0,
                                    alpha_observation=1/8,
                                    estimate_value=OneStepValue(),
                                    node_belief_updater=node_updater,
                                    default_action=Vec2(0.1, 0.1),
                                    rng=rng3
                                   )
        end,
        =#

        "pomcpow" => begin
            rng3 = copy(p_rng)
            action_gen = AdaptiveRadiusRandom(max_radius=6.0, to_zero_first=true, to_light_second=true, rng=rng3)
            tree_queries = 1_000_000
            solver = POMCPOWSolver(next_action=action_gen,
                                    tree_queries=tree_queries,
                                    criterion=MaxUCB(5.0),
                                    final_criterion=MaxTries(),
                                    max_depth=40,
                                    k_action=10.0,
                                    alpha_action=1/8,
                                    k_observation=4.0,
                                    alpha_observation=1/8,
                                    estimate_value=OneStepValue(),
                                    rng=rng3
                                   )
        end,

        "pomcpow_10k" => begin
            rng3 = copy(p_rng)
            action_gen = AdaptiveRadiusRandom(max_radius=6.0, to_zero_first=true, to_light_second=true, rng=rng3)
            tree_queries = 10_000
            solver = POMCPOWSolver(next_action=action_gen,
                                    tree_queries=tree_queries,
                                    criterion=MaxUCB(5.0),
                                    final_criterion=MaxTries(),
                                    max_depth=40,
                                    k_action=10.0,
                                    alpha_action=1/8,
                                    k_observation=4.0,
                                    alpha_observation=1/8,
                                    estimate_value=OneStepValue(),
                                    rng=rng3
                                   )
        end,

        "bt_100_ro_100k" => begin
            rng3 = copy(p_rng)
            action_gen = AdaptiveRadiusRandom(max_radius=6.0, to_zero_first=true, to_light_second=true, rng=rng3)
            rollout_policy = SimpleFeedback(max_radius=10.0)
            tree_queries = 100_000
            node_updater = ObsAdaptiveParticleFilter(pomdp, LowVarianceResampler(100), 0.05, rng3)
            solver = POMCPDPWSolver(next_action=action_gen,
                                    tree_queries=tree_queries,
                                    c=5.0,
                                    max_depth=40,
                                    k_action=10.0,
                                    alpha_action=1/8,
                                    k_observation=4.0,
                                    alpha_observation=1/8,
                                    estimate_value=PORolloutEstimator(rollout_policy, node_updater),
                                    node_belief_updater=node_updater,
                                    default_action=Vec2(0.1, 0.1),
                                    rng=rng3
                                   )
        end,

        "bt_100_osv_100k" => begin
            rng3 = copy(p_rng)
            action_gen = AdaptiveRadiusRandom(max_radius=6.0, to_zero_first=true, to_light_second=true, rng=rng3)
            rollout_policy = SimpleFeedback(max_radius=10.0)
            tree_queries = 100_000
            node_updater = ObsAdaptiveParticleFilter(pomdp, LowVarianceResampler(100), 0.05, rng3)
            solver = POMCPDPWSolver(next_action=action_gen,
                                    tree_queries=tree_queries,
                                    c=5.0,
                                    max_depth=40,
                                    k_action=10.0,
                                    alpha_action=1/8,
                                    k_observation=4.0,
                                    alpha_observation=1/8,
                                    estimate_value=OneStepValue(),
                                    node_belief_updater=node_updater,
                                    default_action=Vec2(0.1, 0.1),
                                    rng=rng3
                                   )
        end,

        "greedy" => SimpleFeedback(gain=1.0, max_radius=10.0)

    )

    updaters = Dict{String, Any}(
        "heuristic" => :heuristic
    )
end

solver_keys = keys(solvers)
rewards = Dict{String, AbstractVector{Float64}}()
# state_hists = Dict{String, AbstractVector{AbstractVector{state_type(pomdp)}}}()
counts = Dict{String, AbstractVector{Int}}()
times = Dict{String, AbstractVector{Float64}}()
steps = Dict{String, AbstractVector{Int}}()

for (j, sk) in enumerate(solver_keys)
    s_rewards = SharedArray(Float64, N)
    s_counts = SharedArray(Int, N)
    # s_hists = SharedArray(AbstractVector{state_type(pomdp)}, N)
    s_times = SharedArray(Float64, N)
    s_steps = SharedArray(Float64, N)
    prog = Progress(N, desc="$sk ($j of $(length(solver_keys)))...")
    pmap(prog, 1:N) do i
        sim_rng = MersenneTwister(i)
        up_rng = MersenneTwister(i+100_000)
        if isa(solvers[sk], Policy)
            policy = deepcopy(solvers[sk])
        else
            policy = solve(solvers[sk], pomdp)
        end
        if get(updaters, sk, :standard) == :standard
            up = ObsAdaptiveParticleFilter(deepcopy(pomdp), LowVarianceResampler(100_000), 0.05, up_rng)
        elseif updaters[sk] == :heuristic
            up = updater(policy)
        end
        sim = HistoryRecorder(max_steps=40, rng=sim_rng)
        pomdp.count = 0
        s_times[i] = @CPUelapsed hist = simulate(sim, deepcopy(pomdp), policy, up)
        s_rewards[i] = discounted_reward(hist)
        s_counts[i] = pomdp.count
        s_steps[i] = n_steps(hist)
    end
    rewards[sk] = sdata(s_rewards)
    @show mean(rewards[sk])
    # state_hists[sk] = sdata(s_hists)
    counts[sk] = sdata(s_counts)
    times[sk] = sdata(s_times)
    steps[sk] = sdata(s_steps)
    @show sum(counts[sk])/sum(steps[sk])
end

for k in solver_keys
    println("$k mean: $(mean(rewards[k])) sem: $(std(rewards[k])/sqrt(N))")
    println("$k time: $(mean(times[k])) sim counts: $(mean(counts[k])) steps: $(mean(steps[k]))")
end

filename = Pkg.dir("ContinuousPOMDPTreeSearchExperiments", "data", "compare_$(Dates.format(now(), "E_d_u_HH_MM")).jld")
println("saving to $filename...")
@save(filename, pomdp, solver_keys, solvers, rewards, updaters, counts, steps, times)
println("done.")


text:
# Top level test script for Stan.jl
using CmdStan, StanDataFrames, Test, Statistics

println("\nRunning tests for StanDataFrames-j1.0-v4.0.1:\n")

# Run execution_tests only if cmdstan is installed and CMDSTAN_HOME is set correctly.
execution_tests = [
  "test_bernoulli.jl",
  "test_bernoulli_nodf.jl"
]

if CMDSTAN_HOME != ""
  println("CMDSTAN_HOME set. Try to run tests.")
  @testset "StanDataFrames.jl" begin

    for my_test in execution_tests
        println("\n\n  * $(my_test) *\n")
        include(my_test)
    end

    println("\n")
  end
else
  println("\n\nCMDSTAN_HOME not set or found.")
  println("Skipping all tests that depend on CmdStan!\n")
end

ext: jl


text:
function test_subspans(aligned, sample_rate, dur)
    subspans = collect(consecutive_subspans(aligned, dur))
    @test length(subspans) == cld(n_samples(aligned), n_samples(sample_rate, dur))
    for i in 1:(length(subspans) - 1)
        @test subspans[i + 1].first_index == subspans[i].last_index + 1 # consecutive indices
        @test n_samples(subspans[i]) == n_samples(sample_rate, dur) # each has as many samples as prescribed by the duration
    end
    r = rem(n_samples(aligned), n_samples(sample_rate, dur)) # last one has the remainder
    if r != 0
        @test n_samples(subspans[end]) == r
    else
        @test n_samples(subspans[end]) == n_samples(sample_rate, dur)
    end
end

@testset "consecutive_subspans" begin
    sample_rate = 1
    span = TimeSpan(Second(0), Second(100))
    aligned = AlignedSpan(sample_rate, span, RoundSpanDown)
    @test n_samples(aligned) == 100

    # Special case: duration == inv(sampling rate)
    subspans = consecutive_subspans(aligned, Second(1))
    @test subspans isa Base.Generator
    v = collect(subspans)
    @test length(v) == 100
    for i in 1:100
        @test v[i] == AlignedSpan(sample_rate, i, i) # all one-sample wide
    end

    test_subspans(aligned, sample_rate, Second(1))

    # Other cases
    test_subspans(aligned, sample_rate, Second(9))
    test_subspans(aligned, sample_rate, Millisecond(2500))
    test_subspans(aligned, sample_rate, Millisecond(1111))

    @test_throws ArgumentError consecutive_subspans(aligned, Millisecond(1))
end


text:
using Base: OneTo

using Base.Threads: @spawn
using Base: @sync

function to_band!(A::AbstractMatrix{T}, block_size = 32) where {T}
    # iterate in blocks.

    m = size(A, 1)
    blocks = ÷(m, block_size, RoundUp)

    offset_col = 1
    offset_row = 1 + block_size

    τs = Vector{T}(undef, m)

    for block = OneTo(blocks)
        cols_to_band!(A, offset_row, offset_col, block_size, τs)
        offset_row += block_size
        offset_col += block_size
    end

    return A
end

function cols_to_band!(A, offset_row, offset_col, block_size, τs)
    # The part in which we do a tall and skinny QR
    A_qr = view(A, offset_row:size(A, 1), offset_col:min(size(A, 2), offset_col+block_size-1))

    # The part to which we apply the tall and skinny QR from the left
    A_left = view(A, offset_row:size(A, 1), offset_col+block_size:size(A, 2))

    # The part to which we apply the tall and skinny QR from the right.
    A_right = view(A, :, offset_row:size(A, 1))

    #=@sync=# for block_start = 1:block_size:size(A_qr, 1)
        let
            block_end = min(block_start + block_size - 1, size(A_qr, 1))
            range = block_start:block_end
            A_qr′ = view(A_qr, range, :)
            τs′ = view(τs, range)
            #=@spawn=# block_qr!(A_qr′, τs′)
        end
    end

    #=@sync=# for block_start = 1:block_size:size(A_qr, 1)
        let
            block_end = min(block_start + block_size - 1, size(A_qr, 1))
            range = block_start:block_end
            A_qr′ = view(A_qr, range, :)
            A_left′ = view(A_left, range, :)
            τs′ = view(τs, range)
            #=@spawn=# apply_left!(A_qr′, A_left′, τs′)
        end
    end

    #=@sync=# for block_start = 1:block_size:size(A_qr, 1)
        let
            block_end = min(block_start + block_size - 1, size(A_qr, 1))
            range = block_start:block_end
            A_qr′ = view(A_qr, range, :)
            A_right′ = view(A_right, :, range)
            τs′ = view(τs, range)
            #=@spawn=# apply_right!(A_qr′, A_right′, τs′)
        end
    end

    # Pair-wise reduce to single QR.
    merged_block_size = block_size
    while true
        # If there's only one block left, stop.
        nblocks = ÷(size(A_qr, 1), merged_block_size, RoundUp)
        nblocks ≤ 1 && break

        #=@sync=# for block_start = 1:2merged_block_size:size(A_qr, 1)
            let
                # If only a single block or less fits, stop.
                block_start + merged_block_size - 1 ≥ size(A_qr, 1) && break

                block_end = min(block_start + 2merged_block_size - 1, size(A_qr, 1))
                range = block_start:block_end
                A_qr′ = view(A_qr, range, :)
                τs′ = view(τs, range)
                #=@spawn=# merge_block_qr!(A_qr′, τs′, merged_block_size)
            end
        end

        #=@sync=# for block_start = 1:2merged_block_size:size(A_qr, 1)
            let
                # If only a single block or less fits, stop.
                block_start + merged_block_size - 1 ≥ size(A_qr, 1) && break

                block_end = min(block_start + 2merged_block_size - 1, size(A_qr, 1))
                range = block_start:block_end
                A_qr′ = view(A_qr, range, :)
                A_left′ = view(A_left, range, :)
                τs′ = view(τs, range)
                #=@spawn=# apply_left_with_gap!(A_qr′, A_left′, τs′, merged_block_size)
            end
        end

        #=@sync=# for block_start = 1:2merged_block_size:size(A_qr, 1)
            let
                # If only a single block or less fits, stop.
                block_start + merged_block_size - 1 ≥ size(A_qr, 1) && break

                block_end = min(block_start + 2merged_block_size - 1, size(A_qr, 1))
                range = block_start:block_end
                A_qr′ = view(A_qr, range, :)
                A_right′ = view(A_right, :, range)
                τs′ = view(τs, range)
                #=@spawn=# apply_right_with_gap!(A_qr′, A_right′, τs′, merged_block_size)
            end
        end

        merged_block_size *= 2
    end

    A
end

function block_qr!(A, τs)
    m, n = size(A)

    steps = min(m, n) - 1

    # Create a bunch of reflectors and save the norm value (τ)
    @inbounds for k = OneTo(steps)
        x = view(A, k:m, k)
        τs[k] = reflector!(x)
        reflectorApplyLeft!(view(A, k:m, k+1:n), τs[k], x)
    end

    return A
end

function apply_left!(qr, A, τs)
    m, n = size(qr)

    steps = min(m, n) - 1

    @inbounds for k = OneTo(steps)
        reflectorApplyLeft!(view(A, k:size(A, 1), :), τs[k], view(qr, k:m, k))
    end

    return A
end

function apply_right!(qr, A, τs)
    m, n = size(qr)

    steps = min(m, n) - 1

    @inbounds for k = OneTo(steps)
        reflectorApplyRight!(view(A, :, k:size(A, 2)), τs[k], view(qr, k:m, k))
    end

    return A
end

function merge_block_qr!(A, τs, v_block_size)
    m, n = size(A)

    B = copy(A)

    # Create a bunch of reflectors and save the norm value (τ)
    @inbounds for k = OneTo(n)
        gap = v_block_size - k + 1
        to = min(m, k + v_block_size)
        x = view(A, k:to, k)
        τs[k] = reflector!(x, gap)
        reflectorApplyLeft!(view(A, k:to, k+1:n), τs[k], x, gap)
    end

    return A
end

function apply_left_with_gap!(qr, A, τs, v_block_size)
    m, n = size(qr)

    # Create a bunch of reflectors and save the norm value (τ)
    @inbounds for k = OneTo(n)
        gap = v_block_size - k + 1
        to = min(m, k + v_block_size)
        x = view(qr, k:to, k)
        reflectorApplyLeft!(view(A, k:to, :), τs[k], x, gap)
    end

    return A
end

function apply_right_with_gap!(qr, A, τs, v_block_size)
    m, n = size(qr)

    # Create a bunch of reflectors and save the norm value (τ)
    @inbounds for k = OneTo(n)
        gap = v_block_size - k + 1
        to = min(m, k + v_block_size)
        x = view(qr, k:to, k)
        reflectorApplyRight!(view(A, :, k:to), τs[k], x, gap)
        qr[k+1:to, k] .= 0
    end

    return A
end

@inline function reflector!(x::AbstractVector, gap = 1)
    @inbounds begin
        n = length(x)
        n == 0 && return zero(eltype(x))
        ξ1 = x[1]
        normu = abs2(ξ1)
        for i = 1+gap:n
            normu += abs2(x[i])
        end
        iszero(normu) && return zero(eltype(x))
        normu = sqrt(normu)
        ν = copysign(normu, real(ξ1))
        ξ1 += ν
        x[1] = -ν
        for i = 1+gap:n
            x[i] /= ξ1
        end
        ξ1/ν
    end
end

@inline function reflectorApplyLeft!(A::AbstractMatrix, τ::Number, x::AbstractVector, gap = 1)
    m, n = size(A)
    m == 0 && return A

    @inbounds for j = 1:n
        # dot
        vAj = A[1, j]
        for i = 1+gap:m
            vAj += x[i]'*A[i, j]
        end

        vAj = conj(τ)*vAj

        # ger
        A[1, j] -= vAj
        for i = 1+gap:m
            A[i, j] -= x[i]*vAj
        end
    end
    return A
end

@inline function reflectorApplyRight!(A::AbstractMatrix, τ::Number, x::AbstractVector, gap = 1)
    m, n = size(A)
    n == 0 && return A
    @inbounds for j = 1:m
        # dot
        vAj = A[j, 1]
        for i = 1+gap:n
            vAj += x[i]*A[j, i]
        end

        vAj = τ*vAj

        # ger
        A[j, 1] -= vAj
        for i = 1+gap:n
            A[j, i] -= x[i]'*vAj
        end
    end
    return A
end


text:
using Thebes, Luxor

include(dirname(pathof(Thebes)) * "/../data/moreobjects.jl")

moreobjects = [boxcube, boxtorus, concave, cone, crossshape, cube,
cuboctahedron, dodecahedron , geodesic, # helix2, icosahedron,
icosidodecahedron, octahedron, octtorus, rhombicosidodecahedron,
rhombicuboctahedron, rhombitruncated_cubeoctahedron,
rhombitruncated_icosidodecahedron, snub_cube, snub_dodecahedron, sphere2, tet3d,
tetrahedron, triangle, truncated_cube, truncated_dodecahedron,
truncated_icosahedron, truncated_octahedron, truncated_tetrahedron]

function main()

    Drawing(800, 800, "test-4.svg")
    background("ivory")
    origin()
    setopacity(0.5)
    setlinejoin("bevel")
    setline(0.3)

    tiles = Tiler(800, 800, 5, 5, margin=150)

    for (pos, n) in tiles
        @layer begin
            translate(pos)
            object = make(moreobjects[rand(1:length(moreobjects))])

            scaleby!(object, 30, 30, 30)
            moveby!(object, 1 * rand(), 1 * rand(), 10 * rand())
            rotateby!(object, #= object.vertices[1],=# 2pi * rand(), 2pi * rand(), 2pi * rand())
            sortfaces!(object)
            pin(object)
        end
    end
    finish()
end

main()


text:
using FFTA, Test
test_nums = [8]
@testset "backward" begin
    for N in test_nums
        x = ones(Float64, N, N)
        y = brfft(x, 2(N-1))
        y_ref = 0*y
        y_ref[1] = N*(2(N-1))
        @test y_ref ≈ y atol=1e-12
    end
end


text:
# legacy content to facilitate transition to AMP

function _reducePartialManifoldElements(el::Symbol)
  if el == :Euclid
    return TranslationGroup(1)
  elseif el == :Circular
    return Circle()
  end
  error("unknown manifold_symbol $el")
end

"""
    $SIGNATURES

Lots to do here, see RoME.jl #244 and standardized usage with Manifolds.jl.

Notes
- diffop( test, reference )   <===>   ΔX = inverse(test) * reference

DevNotes
- FIXME replace with Manifolds.jl #41, RoME.jl #244
"""
function buildHybridManifoldCallbacks(manif::Tuple)
  # TODO use multiple dispatch instead -- will be done for second version of system
  addopT = []
  diffopT = []
  getManiMu = []
  getManiLam = []

  for mn in manif
    if mn == :Euclid
      push!(addopT, +)
      push!(diffopT, -)
      push!(getManiMu, KDE.getEuclidMu)
      push!(getManiLam, KDE.getEuclidLambda)
    elseif mn == :Circular
      push!(addopT, addtheta)
      push!(diffopT, difftheta)
      push!(getManiMu, getCircMu)
      push!(getManiLam, getCircLambda)
    else
      error("Unrecognized manifold $(mn)")
    end
  end

  return (addopT...,), (diffopT...,), (getManiMu...,), (getManiLam...,)
end

# FIXME TO BE REMOVED
_MtoSymbol(::Euclidean{Tuple{1}}) = :Euclid
_MtoSymbol(::Circle) = :Circular
Base.convert(::Type{<:Tuple}, M::ProductManifold) = _MtoSymbol.(M.manifolds)
Base.convert(::Type{<:Tuple}, M::TranslationGroup) = tuple([:Euclid for i in 1:manifold_dimension(M)]...)

Base.convert(::Type{<:Tuple}, ::Type{<: typeof(Euclid)}) = (:Euclid,)
Base.convert(::Type{<:Tuple}, ::Type{<: typeof(Euclid2)}) = (:Euclid,:Euclid)
Base.convert(::Type{<:Tuple}, ::Type{<: typeof(Euclid3)}) = (:Euclid,:Euclid,:Euclid)
Base.convert(::Type{<:Tuple}, ::Type{<: typeof(Euclid4)}) = (:Euclid,:Euclid,:Euclid,:Euclid)
Base.convert(::Type{<:Tuple}, ::Type{<: typeof(SE2_Manifold)}) = (:Euclid,:Euclid,:Circular)
Base.convert(::Type{<:Tuple}, ::Type{<: typeof(SE3_Manifold)}) = (:Euclid,:Euclid,:Euclid,:Circular,:Circular,:Circular)

Base.convert(::Type{<:Tuple}, ::typeof(Euclid)) = (:Euclid,)
Base.convert(::Type{<:Tuple}, ::typeof(Euclid2)) = (:Euclid,:Euclid)
Base.convert(::Type{<:Tuple}, ::typeof(Euclid3)) = (:Euclid,:Euclid,:Euclid)
Base.convert(::Type{<:Tuple}, ::typeof(Euclid4)) = (:Euclid,:Euclid,:Euclid,:Euclid)
Base.convert(::Type{<:Tuple}, ::typeof(SE2_Manifold)) = (:Euclid,:Euclid,:Circular)
Base.convert(::Type{<:Tuple}, ::typeof(SE3_Manifold)) = (:Euclid,:Euclid,:Euclid,:Circular,:Circular,:Circular)

"""
    $(SIGNATURES)

Calculate the KDE bandwidths for each dimension independly, as per manifold of each.  Return vector of all dimension bandwidths.
"""
function getKDEManifoldBandwidths(pts::AbstractMatrix{<:Real},
                                  manif::T1 ) where {T1 <: Tuple}
  #
  ndims = size(pts, 1)
  bws = ones(ndims)

  for i in 1:ndims
    if manif[i] == :Euclid
      bws[i] = getBW( kde!(pts[i,:]) )[1,1]
    elseif manif[i] == :Circular
      bws[i] = getBW( kde!_CircularNaiveCV( pts[i,:] ) )[1,1]
    else
      error("Unrecognized manifold $(manif[i])")
    end
  end

  return bws
end

## ================================================================================================================================
# pass through API
## ================================================================================================================================

# not exported yet
# getManifold(x::ManifoldKernelDensity) = x.manifold

import KernelDensityEstimate: Ndim, Npts, getWeights, marginal
import KernelDensityEstimate: getKDERange, getKDEMax, getKDEMean, getKDEfit
import KernelDensityEstimate: sample, rand, resample, kld, minkld

Ndim(x::ManifoldKernelDensity, w...;kw...) = Ndim(x.belief,w...;kw...)
Npts(x::ManifoldKernelDensity, w...;kw...) = Npts(x.belief,w...;kw...)

getWeights(x::ManifoldKernelDensity, w...;kw...) = getWeights(x.belief, w...;kw...)

getKDERange(x::ManifoldKernelDensity, w...;kw...) = getKDERange(x.belief, w...;kw...)
getKDEMax(x::ManifoldKernelDensity, w...;kw...) = getKDEMax(x.belief, w...;kw...)
getKDEMean(x::ManifoldKernelDensity, w...;kw...) = getKDEMean(x.belief, w...;kw...)
getKDEfit(x::ManifoldKernelDensity, w...;kw...) = getKDEfit(x.belief, w...;kw...)

kld(x::ManifoldKernelDensity, w...;kw...) = kld(x.belief, w...;kw...)
minkld(x::ManifoldKernelDensity, w...;kw...) = minkld(x.belief, w...;kw...)

(x::ManifoldKernelDensity)(w...;kw...) = x.belief(w...;kw...)

#


text:
export TransferCoord, get_coupling, get_reorg_energy, get_activation_energy, get_transfer_rate, einstein_mobility

ħ = 6.582119514E-16 # eV⋅s
kB  = 8.6173303E-5 # eV⋅K⁻¹
ev_to_joule = 1.60218E-19
e_char = 1.60217662E-19 # C

"""
Stores three `Potential`s making up a transition between two diabatic states along an adiabatic potential energy surface.

## Fields

- `pot_d_i` and `pot_d_f` -- initial and final diabatic `Potential`s
- `pot_a` -- adiabatic `Potential`

## Constructor
    TransferCoord(pot_d_i::Potential, pot_d_i::Potential, pot_a::Potential)

"""
mutable struct TransferCoord
    # diabatic potentials
    pot_d_i::Potential; pot_d_f::Potential
    # adiabatic potential
    pot_a::Potential
end

"""
    get_coupling(tc::TransferCoord)

Calculate the electronic coupling between diabatic states

"""
function get_coupling(tc)
    crossing_Q, crossing_E = find_crossing(tc.pot_d_i, tc.pot_d_f)
    coupling = crossing_E - tc.pot_a.func(crossing_Q)

    return coupling
end

"""
    get_reorg_energy(tc::TransferCoord)

Calculate the reorganisation energy for the transfer

"""
function get_reorg_energy(tc::TransferCoord)
    Q_min_i = tc.pot_d_i.Q0
    E_min_f = tc.pot_d_f.E0
    # final diabatic potential evaulated at the initial minimum
    E_min_i_f = tc.pot_d_f.func(Q_min_i)

    reorg_energy = E_min_i_f - E_min_f
    return reorg_energy
end

"""
    get_activation_energy(tc::TransferCoord)

Calculate the activation energy for the transfer

"""
function get_activation_energy(tc::TransferCoord)
    crossing_Q, crossing_E = find_crossing(tc.pot_d_i, tc.pot_d_f)
    activation_energy = crossing_E - tc.pot_d_i.E0

    return activation_energy
end

"""
    transfer_rate(tc::TransferCoord)

Calculate the transfer rate

"""
function get_transfer_rate(tc::TransferCoord)
    λ = get_reorg_energy(tc)
    Hab = get_coupling(tc)
    ΔG = get_activation_energy(tc)
    kBT = kB * tc.pot_a.T

    rate = (2*pi/ħ) * 1/sqrt(4*pi*λ*kBT) * Hab^2 * exp(-ΔG/kBT)

    return rate
end

"""
    einstein_mobility(rate::Float64, n_neighbours::Int64, dist::Float64, temp::Float64)

## Fields

- `rate` -- Transfer rate
- `n_neighbours` -- Number of neighbours involved in the hopping
- `dist` -- Distance between sites in whichever unit
- `temp` -- Temperature in K

"""
function einstein_mobility(rate::Float64, n_neighbours::Int64, dist::Float64, temp::Float64)
    diffusion = dist^2 * n_neighbours * rate
    mob = e_char * diffusion / (kB * ev_to_joule * temp)
    return mob
end


text:
export TransformedSource

struct TransformedSource
  f::Any
  src::Any
  fs::Float32
  blksize::Int
  nchannels::Int
end

function TransformedSource(f, src)
  fs = inputframerate(src)
  blksize = inputblocksize(src)
  ch = inputchannels(src)
  x = f(zeros(blksize, ch))
  fs *= size(x, 1) / blksize
  if x isa AbstractMatrix
    blksize, ch = size(x)
  else
    ch = 1
    blksize = length(x)
  end
  TransformedSource(f, src, fs, blksize, ch)
end

connect(src::TransformedSource) = connect(src.src)
Base.close(src::TransformedSource) = close(src.src)
stopinputstream(src::TransformedSource) = stopinputstream(src.src)

inputframerate(src::TransformedSource) = src.fs
inputblocksize(src::TransformedSource) = src.blksize
inputchannels(src::TransformedSource) = src.nchannels

function startinputstream(src::TransformedSource, callback)
  startinputstream(src.src, (t, data) -> callback(t, src.f(data)))
end


text:
#==============================================================================#
# ES.jl
#
# This file is generated from:
# https://github.com/aws/aws-sdk-js/blob/master/apis/es-2015-01-01.normal.json
#==============================================================================#

__precompile__()

module ES

using AWSCore

"""
    using AWSSDK.ES.add_tags
    add_tags([::AWSConfig], arguments::Dict)
    add_tags([::AWSConfig]; ARN=, TagList=)

    using AWSCore.Services.es
    es([::AWSConfig], "POST", "/2015-01-01/tags", arguments::Dict)
    es([::AWSConfig], "POST", "/2015-01-01/tags", ARN=, TagList=)

# AddTags Operation

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.](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains.html#es-managedomains-awsresorcetagging)

# Arguments

## `ARN = ::String` -- *Required*
Specify the `ARN` for which you want to add the tags.

## `TagList = [[ ... ], ...]` -- *Required*
List of `Tag` that need to be added for the Elasticsearch domain.
```
 TagList = [[
        "Key" => <required> ::String,
        "Value" => <required> ::String
    ], ...]
```

# Exceptions

`BaseException`, `LimitExceededException`, `ValidationException` or `InternalException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/AddTags)
"""
@inline add_tags(aws::AWSConfig=default_aws_config(); args...) = add_tags(aws, args)

@inline add_tags(aws::AWSConfig, args) = AWSCore.Services.es(aws, "POST", "/2015-01-01/tags", args)

@inline add_tags(args) = add_tags(default_aws_config(), args)

"""
    using AWSSDK.ES.create_elasticsearch_domain
    create_elasticsearch_domain([::AWSConfig], arguments::Dict)
    create_elasticsearch_domain([::AWSConfig]; DomainName=, <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "POST", "/2015-01-01/es/domain", arguments::Dict)
    es([::AWSConfig], "POST", "/2015-01-01/es/domain", DomainName=, <keyword arguments>)

# CreateElasticsearchDomain Operation

Creates a new Elasticsearch domain. For more information, see [Creating Elasticsearch Domains](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-createupdatedomains.html#es-createdomains) in the *Amazon Elasticsearch Service Developer Guide*.

# Arguments

## `DomainName = ::String` -- *Required*
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 letter or number and can contain the following characters: a-z (lowercase), 0-9, and - (hyphen).

## `ElasticsearchVersion = ::String`
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](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-createupdatedomains.html#es-createdomains) in the *Amazon Elasticsearch Service Developer Guide*.

## `ElasticsearchClusterConfig = [ ... ]`
Configuration options for an Elasticsearch domain. Specifies the instance type and number of instances in the domain cluster.
```
 ElasticsearchClusterConfig = [
        "InstanceType" =>  "m3.medium.elasticsearch", "m3.large.elasticsearch", "m3.xlarge.elasticsearch", "m3.2xlarge.elasticsearch", "m4.large.elasticsearch", "m4.xlarge.elasticsearch", "m4.2xlarge.elasticsearch", "m4.4xlarge.elasticsearch", "m4.10xlarge.elasticsearch", "t2.micro.elasticsearch", "t2.small.elasticsearch", "t2.medium.elasticsearch", "r3.large.elasticsearch", "r3.xlarge.elasticsearch", "r3.2xlarge.elasticsearch", "r3.4xlarge.elasticsearch", "r3.8xlarge.elasticsearch", "i2.xlarge.elasticsearch", "i2.2xlarge.elasticsearch", "d2.xlarge.elasticsearch", "d2.2xlarge.elasticsearch", "d2.4xlarge.elasticsearch", "d2.8xlarge.elasticsearch", "c4.large.elasticsearch", "c4.xlarge.elasticsearch", "c4.2xlarge.elasticsearch", "c4.4xlarge.elasticsearch", "c4.8xlarge.elasticsearch", "r4.large.elasticsearch", "r4.xlarge.elasticsearch", "r4.2xlarge.elasticsearch", "r4.4xlarge.elasticsearch", "r4.8xlarge.elasticsearch", "r4.16xlarge.elasticsearch", "i3.large.elasticsearch", "i3.xlarge.elasticsearch", "i3.2xlarge.elasticsearch", "i3.4xlarge.elasticsearch", "i3.8xlarge.elasticsearch" or "i3.16xlarge.elasticsearch",
        "InstanceCount" =>  ::Int,
        "DedicatedMasterEnabled" =>  ::Bool,
        "ZoneAwarenessEnabled" =>  ::Bool,
        "DedicatedMasterType" =>  "m3.medium.elasticsearch", "m3.large.elasticsearch", "m3.xlarge.elasticsearch", "m3.2xlarge.elasticsearch", "m4.large.elasticsearch", "m4.xlarge.elasticsearch", "m4.2xlarge.elasticsearch", "m4.4xlarge.elasticsearch", "m4.10xlarge.elasticsearch", "t2.micro.elasticsearch", "t2.small.elasticsearch", "t2.medium.elasticsearch", "r3.large.elasticsearch", "r3.xlarge.elasticsearch", "r3.2xlarge.elasticsearch", "r3.4xlarge.elasticsearch", "r3.8xlarge.elasticsearch", "i2.xlarge.elasticsearch", "i2.2xlarge.elasticsearch", "d2.xlarge.elasticsearch", "d2.2xlarge.elasticsearch", "d2.4xlarge.elasticsearch", "d2.8xlarge.elasticsearch", "c4.large.elasticsearch", "c4.xlarge.elasticsearch", "c4.2xlarge.elasticsearch", "c4.4xlarge.elasticsearch", "c4.8xlarge.elasticsearch", "r4.large.elasticsearch", "r4.xlarge.elasticsearch", "r4.2xlarge.elasticsearch", "r4.4xlarge.elasticsearch", "r4.8xlarge.elasticsearch", "r4.16xlarge.elasticsearch", "i3.large.elasticsearch", "i3.xlarge.elasticsearch", "i3.2xlarge.elasticsearch", "i3.4xlarge.elasticsearch", "i3.8xlarge.elasticsearch" or "i3.16xlarge.elasticsearch",
        "DedicatedMasterCount" =>  ::Int
    ]
```

## `EBSOptions = [ ... ]`
Options to enable, disable and specify the type and size of EBS storage volumes.
```
 EBSOptions = [
        "EBSEnabled" =>  ::Bool,
        "VolumeType" =>  "standard", "gp2" or "io1",
        "VolumeSize" =>  ::Int,
        "Iops" =>  ::Int
    ]
```

## `AccessPolicies = ::String`
IAM access policy as a JSON-formatted string.

## `SnapshotOptions = ["AutomatedSnapshotStartHour" =>  ::Int]`
Option to set time, in UTC format, of 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](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html#es-creating-vpc) in *VPC Endpoints for Amazon Elasticsearch Service Domains*
```
 VPCOptions = [
        "SubnetIds" =>  [::String, ...],
        "SecurityGroupIds" =>  [::String, ...]
    ]
```

## `CognitoOptions = [ ... ]`
Options to specify the Cognito user and identity pools for Kibana authentication. For more information, see [Amazon Cognito Authentication for Kibana](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-cognito-auth.html).
```
 CognitoOptions = [
        "Enabled" =>  ::Bool,
        "UserPoolId" =>  ::String,
        "IdentityPoolId" =>  ::String,
        "RoleArn" =>  ::String
    ]
```

## `EncryptionAtRestOptions = [ ... ]`
Specifies the Encryption At Rest Options.
```
 EncryptionAtRestOptions = [
        "Enabled" =>  ::Bool,
        "KmsKeyId" =>  ::String
    ]
```

## `AdvancedOptions = ::Dict{String,String}`
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](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-createupdatedomains.html#es-createdomain-configure-advanced-options) for more information.

## `LogPublishingOptions = ::Dict{String,String}`
Map of `LogType` and `LogPublishingOption`, each containing options to publish a given type of Elasticsearch log.

# Returns

`CreateElasticsearchDomainResponse`

# Exceptions

`BaseException`, `DisabledOperationException`, `InternalException`, `InvalidTypeException`, `LimitExceededException`, `ResourceAlreadyExistsException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/CreateElasticsearchDomain)
"""
@inline create_elasticsearch_domain(aws::AWSConfig=default_aws_config(); args...) = create_elasticsearch_domain(aws, args)

@inline create_elasticsearch_domain(aws::AWSConfig, args) = AWSCore.Services.es(aws, "POST", "/2015-01-01/es/domain", args)

@inline create_elasticsearch_domain(args) = create_elasticsearch_domain(default_aws_config(), args)

"""
    using AWSSDK.ES.delete_elasticsearch_domain
    delete_elasticsearch_domain([::AWSConfig], arguments::Dict)
    delete_elasticsearch_domain([::AWSConfig]; DomainName=)

    using AWSCore.Services.es
    es([::AWSConfig], "DELETE", "/2015-01-01/es/domain/{DomainName}", arguments::Dict)
    es([::AWSConfig], "DELETE", "/2015-01-01/es/domain/{DomainName}", DomainName=)

# DeleteElasticsearchDomain Operation

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

# Arguments

## `DomainName = ::String` -- *Required*
The name of the Elasticsearch domain that you want to permanently delete.

# Returns

`DeleteElasticsearchDomainResponse`

# Exceptions

`BaseException`, `InternalException`, `ResourceNotFoundException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DeleteElasticsearchDomain)
"""
@inline delete_elasticsearch_domain(aws::AWSConfig=default_aws_config(); args...) = delete_elasticsearch_domain(aws, args)

@inline delete_elasticsearch_domain(aws::AWSConfig, args) = AWSCore.Services.es(aws, "DELETE", "/2015-01-01/es/domain/{DomainName}", args)

@inline delete_elasticsearch_domain(args) = delete_elasticsearch_domain(default_aws_config(), args)

"""
    using AWSSDK.ES.delete_elasticsearch_service_role
    delete_elasticsearch_service_role([::AWSConfig])

    using AWSCore.Services.es
    es([::AWSConfig], "DELETE", "/2015-01-01/es/role",)

# DeleteElasticsearchServiceRole Operation

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](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html#es-enabling-slr) in *VPC Endpoints for Amazon Elasticsearch Service Domains*.

# Exceptions

`BaseException`, `InternalException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DeleteElasticsearchServiceRole)
"""
@inline delete_elasticsearch_service_role(aws::AWSConfig=default_aws_config(); args...) = delete_elasticsearch_service_role(aws, args)

@inline delete_elasticsearch_service_role(aws::AWSConfig, args) = AWSCore.Services.es(aws, "DELETE", "/2015-01-01/es/role", args)

@inline delete_elasticsearch_service_role(args) = delete_elasticsearch_service_role(default_aws_config(), args)

"""
    using AWSSDK.ES.describe_elasticsearch_domain
    describe_elasticsearch_domain([::AWSConfig], arguments::Dict)
    describe_elasticsearch_domain([::AWSConfig]; DomainName=)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/es/domain/{DomainName}", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/es/domain/{DomainName}", DomainName=)

# DescribeElasticsearchDomain Operation

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

# Arguments

## `DomainName = ::String` -- *Required*
The name of the Elasticsearch domain for which you want information.

# Returns

`DescribeElasticsearchDomainResponse`

# Exceptions

`BaseException`, `InternalException`, `ResourceNotFoundException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DescribeElasticsearchDomain)
"""
@inline describe_elasticsearch_domain(aws::AWSConfig=default_aws_config(); args...) = describe_elasticsearch_domain(aws, args)

@inline describe_elasticsearch_domain(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/es/domain/{DomainName}", args)

@inline describe_elasticsearch_domain(args) = describe_elasticsearch_domain(default_aws_config(), args)

"""
    using AWSSDK.ES.describe_elasticsearch_domain_config
    describe_elasticsearch_domain_config([::AWSConfig], arguments::Dict)
    describe_elasticsearch_domain_config([::AWSConfig]; DomainName=)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/es/domain/{DomainName}/config", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/es/domain/{DomainName}/config", DomainName=)

# DescribeElasticsearchDomainConfig Operation

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

# Arguments

## `DomainName = ::String` -- *Required*
The Elasticsearch domain that you want to get information about.

# Returns

`DescribeElasticsearchDomainConfigResponse`

# Exceptions

`BaseException`, `InternalException`, `ResourceNotFoundException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DescribeElasticsearchDomainConfig)
"""
@inline describe_elasticsearch_domain_config(aws::AWSConfig=default_aws_config(); args...) = describe_elasticsearch_domain_config(aws, args)

@inline describe_elasticsearch_domain_config(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/es/domain/{DomainName}/config", args)

@inline describe_elasticsearch_domain_config(args) = describe_elasticsearch_domain_config(default_aws_config(), args)

"""
    using AWSSDK.ES.describe_elasticsearch_domains
    describe_elasticsearch_domains([::AWSConfig], arguments::Dict)
    describe_elasticsearch_domains([::AWSConfig]; DomainNames=)

    using AWSCore.Services.es
    es([::AWSConfig], "POST", "/2015-01-01/es/domain-info", arguments::Dict)
    es([::AWSConfig], "POST", "/2015-01-01/es/domain-info", DomainNames=)

# DescribeElasticsearchDomains Operation

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

# Arguments

## `DomainNames = [::String, ...]` -- *Required*
The Elasticsearch domains for which you want information.

# Returns

`DescribeElasticsearchDomainsResponse`

# Exceptions

`BaseException`, `InternalException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DescribeElasticsearchDomains)
"""
@inline describe_elasticsearch_domains(aws::AWSConfig=default_aws_config(); args...) = describe_elasticsearch_domains(aws, args)

@inline describe_elasticsearch_domains(aws::AWSConfig, args) = AWSCore.Services.es(aws, "POST", "/2015-01-01/es/domain-info", args)

@inline describe_elasticsearch_domains(args) = describe_elasticsearch_domains(default_aws_config(), args)

"""
    using AWSSDK.ES.describe_elasticsearch_instance_type_limits
    describe_elasticsearch_instance_type_limits([::AWSConfig], arguments::Dict)
    describe_elasticsearch_instance_type_limits([::AWSConfig]; InstanceType=, ElasticsearchVersion=, <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/es/instanceTypeLimits/{ElasticsearchVersion}/{InstanceType}", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/es/instanceTypeLimits/{ElasticsearchVersion}/{InstanceType}", InstanceType=, ElasticsearchVersion=, <keyword arguments>)

# DescribeElasticsearchInstanceTypeLimits Operation

Describe Elasticsearch Limits for a given InstanceType and ElasticsearchVersion. When modifying existing Domain, specify the `[DomainName](@ref)` to know what Limits are supported for modifying.

# Arguments

## `domainName = ::String`
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](@ref)` for existing domain.

## `InstanceType = "m3.medium.elasticsearch", "m3.large.elasticsearch", "m3.xlarge.elasticsearch", "m3.2xlarge.elasticsearch", "m4.large.elasticsearch", "m4.xlarge.elasticsearch", "m4.2xlarge.elasticsearch", "m4.4xlarge.elasticsearch", "m4.10xlarge.elasticsearch", "t2.micro.elasticsearch", "t2.small.elasticsearch", "t2.medium.elasticsearch", "r3.large.elasticsearch", "r3.xlarge.elasticsearch", "r3.2xlarge.elasticsearch", "r3.4xlarge.elasticsearch", "r3.8xlarge.elasticsearch", "i2.xlarge.elasticsearch", "i2.2xlarge.elasticsearch", "d2.xlarge.elasticsearch", "d2.2xlarge.elasticsearch", "d2.4xlarge.elasticsearch", "d2.8xlarge.elasticsearch", "c4.large.elasticsearch", "c4.xlarge.elasticsearch", "c4.2xlarge.elasticsearch", "c4.4xlarge.elasticsearch", "c4.8xlarge.elasticsearch", "r4.large.elasticsearch", "r4.xlarge.elasticsearch", "r4.2xlarge.elasticsearch", "r4.4xlarge.elasticsearch", "r4.8xlarge.elasticsearch", "r4.16xlarge.elasticsearch", "i3.large.elasticsearch", "i3.xlarge.elasticsearch", "i3.2xlarge.elasticsearch", "i3.4xlarge.elasticsearch", "i3.8xlarge.elasticsearch" or "i3.16xlarge.elasticsearch"` -- *Required*
The instance type for an Elasticsearch cluster for which Elasticsearch `[Limits](@ref)` are needed.

## `ElasticsearchVersion = ::String` -- *Required*
Version of Elasticsearch for which `[Limits](@ref)` are needed.

# Returns

`DescribeElasticsearchInstanceTypeLimitsResponse`

# Exceptions

`BaseException`, `InternalException`, `InvalidTypeException`, `LimitExceededException`, `ResourceNotFoundException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DescribeElasticsearchInstanceTypeLimits)
"""
@inline describe_elasticsearch_instance_type_limits(aws::AWSConfig=default_aws_config(); args...) = describe_elasticsearch_instance_type_limits(aws, args)

@inline describe_elasticsearch_instance_type_limits(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/es/instanceTypeLimits/{ElasticsearchVersion}/{InstanceType}", args)

@inline describe_elasticsearch_instance_type_limits(args) = describe_elasticsearch_instance_type_limits(default_aws_config(), args)

"""
    using AWSSDK.ES.describe_reserved_elasticsearch_instance_offerings
    describe_reserved_elasticsearch_instance_offerings([::AWSConfig], arguments::Dict)
    describe_reserved_elasticsearch_instance_offerings([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/es/reservedInstanceOfferings", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/es/reservedInstanceOfferings", <keyword arguments>)

# DescribeReservedElasticsearchInstanceOfferings Operation

Lists available reserved Elasticsearch instance offerings.

# Arguments

## `offeringId = ::String`
The offering identifier filter value. Use this parameter to show only the available offering that matches the specified reservation identifier.

## `maxResults = ::Int`
Set this value to limit the number of results returned. If not specified, defaults to 100.

## `nextToken = ::String`
NextToken should be sent in case if earlier API call produced result containing NextToken. It is used for pagination.

# Returns

`DescribeReservedElasticsearchInstanceOfferingsResponse`

# Exceptions

`ResourceNotFoundException`, `ValidationException`, `DisabledOperationException` or `InternalException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DescribeReservedElasticsearchInstanceOfferings)
"""
@inline describe_reserved_elasticsearch_instance_offerings(aws::AWSConfig=default_aws_config(); args...) = describe_reserved_elasticsearch_instance_offerings(aws, args)

@inline describe_reserved_elasticsearch_instance_offerings(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/es/reservedInstanceOfferings", args)

@inline describe_reserved_elasticsearch_instance_offerings(args) = describe_reserved_elasticsearch_instance_offerings(default_aws_config(), args)

"""
    using AWSSDK.ES.describe_reserved_elasticsearch_instances
    describe_reserved_elasticsearch_instances([::AWSConfig], arguments::Dict)
    describe_reserved_elasticsearch_instances([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/es/reservedInstances", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/es/reservedInstances", <keyword arguments>)

# DescribeReservedElasticsearchInstances Operation

Returns information about reserved Elasticsearch instances for this account.

# Arguments

## `reservationId = ::String`
The reserved instance identifier filter value. Use this parameter to show only the reservation that matches the specified reserved Elasticsearch instance ID.

## `maxResults = ::Int`
Set this value to limit the number of results returned. If not specified, defaults to 100.

## `nextToken = ::String`
NextToken should be sent in case if earlier API call produced result containing NextToken. It is used for pagination.

# Returns

`DescribeReservedElasticsearchInstancesResponse`

# Exceptions

`ResourceNotFoundException`, `InternalException`, `ValidationException` or `DisabledOperationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/DescribeReservedElasticsearchInstances)
"""
@inline describe_reserved_elasticsearch_instances(aws::AWSConfig=default_aws_config(); args...) = describe_reserved_elasticsearch_instances(aws, args)

@inline describe_reserved_elasticsearch_instances(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/es/reservedInstances", args)

@inline describe_reserved_elasticsearch_instances(args) = describe_reserved_elasticsearch_instances(default_aws_config(), args)

"""
    using AWSSDK.ES.list_domain_names
    list_domain_names([::AWSConfig])

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/domain",)

# ListDomainNames Operation

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

# Returns

`ListDomainNamesResponse`

# Exceptions

`BaseException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/ListDomainNames)
"""
@inline list_domain_names(aws::AWSConfig=default_aws_config(); args...) = list_domain_names(aws, args)

@inline list_domain_names(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/domain", args)

@inline list_domain_names(args) = list_domain_names(default_aws_config(), args)

"""
    using AWSSDK.ES.list_elasticsearch_instance_types
    list_elasticsearch_instance_types([::AWSConfig], arguments::Dict)
    list_elasticsearch_instance_types([::AWSConfig]; ElasticsearchVersion=, <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/es/instanceTypes/{ElasticsearchVersion}", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/es/instanceTypes/{ElasticsearchVersion}", ElasticsearchVersion=, <keyword arguments>)

# ListElasticsearchInstanceTypes Operation

List all Elasticsearch instance types that are supported for given ElasticsearchVersion

# Arguments

## `ElasticsearchVersion = ::String` -- *Required*
Version of Elasticsearch for which list of supported elasticsearch instance types are needed.

## `domainName = ::String`
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 = ::Int`
Set this value to limit the number of results returned. Value provided must be greater than 30 else it wont be honored.

## `nextToken = ::String`
NextToken should be sent in case if earlier API call produced result containing NextToken. It is used for pagination.

# Returns

`ListElasticsearchInstanceTypesResponse`

# Exceptions

`BaseException`, `InternalException`, `ResourceNotFoundException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/ListElasticsearchInstanceTypes)
"""
@inline list_elasticsearch_instance_types(aws::AWSConfig=default_aws_config(); args...) = list_elasticsearch_instance_types(aws, args)

@inline list_elasticsearch_instance_types(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/es/instanceTypes/{ElasticsearchVersion}", args)

@inline list_elasticsearch_instance_types(args) = list_elasticsearch_instance_types(default_aws_config(), args)

"""
    using AWSSDK.ES.list_elasticsearch_versions
    list_elasticsearch_versions([::AWSConfig], arguments::Dict)
    list_elasticsearch_versions([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/es/versions", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/es/versions", <keyword arguments>)

# ListElasticsearchVersions Operation

List all supported Elasticsearch versions

# Arguments

## `maxResults = ::Int`
Set this value to limit the number of results returned. Value provided must be greater than 10 else it wont be honored.

## `nextToken = ::String`

# Returns

`ListElasticsearchVersionsResponse`

# Exceptions

`BaseException`, `InternalException`, `ResourceNotFoundException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/ListElasticsearchVersions)
"""
@inline list_elasticsearch_versions(aws::AWSConfig=default_aws_config(); args...) = list_elasticsearch_versions(aws, args)

@inline list_elasticsearch_versions(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/es/versions", args)

@inline list_elasticsearch_versions(args) = list_elasticsearch_versions(default_aws_config(), args)

"""
    using AWSSDK.ES.list_tags
    list_tags([::AWSConfig], arguments::Dict)
    list_tags([::AWSConfig]; arn=)

    using AWSCore.Services.es
    es([::AWSConfig], "GET", "/2015-01-01/tags/", arguments::Dict)
    es([::AWSConfig], "GET", "/2015-01-01/tags/", arn=)

# ListTags Operation

Returns all tags for the given Elasticsearch domain.

# Arguments

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

# Returns

`ListTagsResponse`

# Exceptions

`BaseException`, `ResourceNotFoundException`, `ValidationException` or `InternalException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/ListTags)
"""
@inline list_tags(aws::AWSConfig=default_aws_config(); args...) = list_tags(aws, args)

@inline list_tags(aws::AWSConfig, args) = AWSCore.Services.es(aws, "GET", "/2015-01-01/tags/", args)

@inline list_tags(args) = list_tags(default_aws_config(), args)

"""
    using AWSSDK.ES.purchase_reserved_elasticsearch_instance_offering
    purchase_reserved_elasticsearch_instance_offering([::AWSConfig], arguments::Dict)
    purchase_reserved_elasticsearch_instance_offering([::AWSConfig]; ReservedElasticsearchInstanceOfferingId=, ReservationName=, <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "POST", "/2015-01-01/es/purchaseReservedInstanceOffering", arguments::Dict)
    es([::AWSConfig], "POST", "/2015-01-01/es/purchaseReservedInstanceOffering", ReservedElasticsearchInstanceOfferingId=, ReservationName=, <keyword arguments>)

# PurchaseReservedElasticsearchInstanceOffering Operation

Allows you to purchase reserved Elasticsearch instances.

# Arguments

## `ReservedElasticsearchInstanceOfferingId = ::String` -- *Required*
The ID of the reserved Elasticsearch instance offering to purchase.

## `ReservationName = ::String` -- *Required*
A customer-specified identifier to track this reservation.

## `InstanceCount = ::Int`
The number of Elasticsearch instances to reserve.

# Returns

`PurchaseReservedElasticsearchInstanceOfferingResponse`

# Exceptions

`ResourceNotFoundException`, `ResourceAlreadyExistsException`, `LimitExceededException`, `DisabledOperationException`, `ValidationException` or `InternalException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/PurchaseReservedElasticsearchInstanceOffering)
"""
@inline purchase_reserved_elasticsearch_instance_offering(aws::AWSConfig=default_aws_config(); args...) = purchase_reserved_elasticsearch_instance_offering(aws, args)

@inline purchase_reserved_elasticsearch_instance_offering(aws::AWSConfig, args) = AWSCore.Services.es(aws, "POST", "/2015-01-01/es/purchaseReservedInstanceOffering", args)

@inline purchase_reserved_elasticsearch_instance_offering(args) = purchase_reserved_elasticsearch_instance_offering(default_aws_config(), args)

"""
    using AWSSDK.ES.remove_tags
    remove_tags([::AWSConfig], arguments::Dict)
    remove_tags([::AWSConfig]; ARN=, TagKeys=)

    using AWSCore.Services.es
    es([::AWSConfig], "POST", "/2015-01-01/tags-removal", arguments::Dict)
    es([::AWSConfig], "POST", "/2015-01-01/tags-removal", ARN=, TagKeys=)

# RemoveTags Operation

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

# Arguments

## `ARN = ::String` -- *Required*
Specifies the `ARN` for the Elasticsearch domain from which you want to delete the specified tags.

## `TagKeys = [::String, ...]` -- *Required*
Specifies the `TagKey` list which you want to remove from the Elasticsearch domain.

# Exceptions

`BaseException`, `ValidationException` or `InternalException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/RemoveTags)
"""
@inline remove_tags(aws::AWSConfig=default_aws_config(); args...) = remove_tags(aws, args)

@inline remove_tags(aws::AWSConfig, args) = AWSCore.Services.es(aws, "POST", "/2015-01-01/tags-removal", args)

@inline remove_tags(args) = remove_tags(default_aws_config(), args)

"""
    using AWSSDK.ES.update_elasticsearch_domain_config
    update_elasticsearch_domain_config([::AWSConfig], arguments::Dict)
    update_elasticsearch_domain_config([::AWSConfig]; DomainName=, <keyword arguments>)

    using AWSCore.Services.es
    es([::AWSConfig], "POST", "/2015-01-01/es/domain/{DomainName}/config", arguments::Dict)
    es([::AWSConfig], "POST", "/2015-01-01/es/domain/{DomainName}/config", DomainName=, <keyword arguments>)

# UpdateElasticsearchDomainConfig Operation

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

# Arguments

## `DomainName = ::String` -- *Required*
The name of the Elasticsearch domain that you are updating.

## `ElasticsearchClusterConfig = [ ... ]`
The type and number of instances to instantiate for the domain cluster.
```
 ElasticsearchClusterConfig = [
        "InstanceType" =>  "m3.medium.elasticsearch", "m3.large.elasticsearch", "m3.xlarge.elasticsearch", "m3.2xlarge.elasticsearch", "m4.large.elasticsearch", "m4.xlarge.elasticsearch", "m4.2xlarge.elasticsearch", "m4.4xlarge.elasticsearch", "m4.10xlarge.elasticsearch", "t2.micro.elasticsearch", "t2.small.elasticsearch", "t2.medium.elasticsearch", "r3.large.elasticsearch", "r3.xlarge.elasticsearch", "r3.2xlarge.elasticsearch", "r3.4xlarge.elasticsearch", "r3.8xlarge.elasticsearch", "i2.xlarge.elasticsearch", "i2.2xlarge.elasticsearch", "d2.xlarge.elasticsearch", "d2.2xlarge.elasticsearch", "d2.4xlarge.elasticsearch", "d2.8xlarge.elasticsearch", "c4.large.elasticsearch", "c4.xlarge.elasticsearch", "c4.2xlarge.elasticsearch", "c4.4xlarge.elasticsearch", "c4.8xlarge.elasticsearch", "r4.large.elasticsearch", "r4.xlarge.elasticsearch", "r4.2xlarge.elasticsearch", "r4.4xlarge.elasticsearch", "r4.8xlarge.elasticsearch", "r4.16xlarge.elasticsearch", "i3.large.elasticsearch", "i3.xlarge.elasticsearch", "i3.2xlarge.elasticsearch", "i3.4xlarge.elasticsearch", "i3.8xlarge.elasticsearch" or "i3.16xlarge.elasticsearch",
        "InstanceCount" =>  ::Int,
        "DedicatedMasterEnabled" =>  ::Bool,
        "ZoneAwarenessEnabled" =>  ::Bool,
        "DedicatedMasterType" =>  "m3.medium.elasticsearch", "m3.large.elasticsearch", "m3.xlarge.elasticsearch", "m3.2xlarge.elasticsearch", "m4.large.elasticsearch", "m4.xlarge.elasticsearch", "m4.2xlarge.elasticsearch", "m4.4xlarge.elasticsearch", "m4.10xlarge.elasticsearch", "t2.micro.elasticsearch", "t2.small.elasticsearch", "t2.medium.elasticsearch", "r3.large.elasticsearch", "r3.xlarge.elasticsearch", "r3.2xlarge.elasticsearch", "r3.4xlarge.elasticsearch", "r3.8xlarge.elasticsearch", "i2.xlarge.elasticsearch", "i2.2xlarge.elasticsearch", "d2.xlarge.elasticsearch", "d2.2xlarge.elasticsearch", "d2.4xlarge.elasticsearch", "d2.8xlarge.elasticsearch", "c4.large.elasticsearch", "c4.xlarge.elasticsearch", "c4.2xlarge.elasticsearch", "c4.4xlarge.elasticsearch", "c4.8xlarge.elasticsearch", "r4.large.elasticsearch", "r4.xlarge.elasticsearch", "r4.2xlarge.elasticsearch", "r4.4xlarge.elasticsearch", "r4.8xlarge.elasticsearch", "r4.16xlarge.elasticsearch", "i3.large.elasticsearch", "i3.xlarge.elasticsearch", "i3.2xlarge.elasticsearch", "i3.4xlarge.elasticsearch", "i3.8xlarge.elasticsearch" or "i3.16xlarge.elasticsearch",
        "DedicatedMasterCount" =>  ::Int
    ]
```

## `EBSOptions = [ ... ]`
Specify the type and size of the EBS volume that you want to use.
```
 EBSOptions = [
        "EBSEnabled" =>  ::Bool,
        "VolumeType" =>  "standard", "gp2" or "io1",
        "VolumeSize" =>  ::Int,
        "Iops" =>  ::Int
    ]
```

## `SnapshotOptions = ["AutomatedSnapshotStartHour" =>  ::Int]`
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](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-vpc.html#es-creating-vpc) in *VPC Endpoints for Amazon Elasticsearch Service Domains*
```
 VPCOptions = [
        "SubnetIds" =>  [::String, ...],
        "SecurityGroupIds" =>  [::String, ...]
    ]
```

## `CognitoOptions = [ ... ]`
Options to specify the Cognito user and identity pools for Kibana authentication. For more information, see [Amazon Cognito Authentication for Kibana](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-cognito-auth.html).
```
 CognitoOptions = [
        "Enabled" =>  ::Bool,
        "UserPoolId" =>  ::String,
        "IdentityPoolId" =>  ::String,
        "RoleArn" =>  ::String
    ]
```

## `AdvancedOptions = ::Dict{String,String}`
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](http://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-createupdatedomains.html#es-createdomain-configure-advanced-options) for more information.

## `AccessPolicies = ::String`
IAM access policy as a JSON-formatted string.

## `LogPublishingOptions = ::Dict{String,String}`
Map of `LogType` and `LogPublishingOption`, each containing options to publish a given type of Elasticsearch log.

# Returns

`UpdateElasticsearchDomainConfigResponse`

# Exceptions

`BaseException`, `InternalException`, `InvalidTypeException`, `LimitExceededException`, `ResourceNotFoundException` or `ValidationException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/es-2015-01-01/UpdateElasticsearchDomainConfig)
"""
@inline update_elasticsearch_domain_config(aws::AWSConfig=default_aws_config(); args...) = update_elasticsearch_domain_config(aws, args)

@inline update_elasticsearch_domain_config(aws::AWSConfig, args) = AWSCore.Services.es(aws, "POST", "/2015-01-01/es/domain/{DomainName}/config", args)

@inline update_elasticsearch_domain_config(args) = update_elasticsearch_domain_config(default_aws_config(), args)

end # module ES

#==============================================================================#
# End of file
#==============================================================================#


text:
function build_description(res_dir::String, comment::String, sources::Vector{String})
    desc = "--- '$(basename(res_dir))' $(now()) ----------\nComment:\n\t$(comment)\nSources:\n";
    for s in sources
        desc *= " - $(s)\n";
    end
    return  desc;
end
# titi delicious de mi corazon

max_stars_repo_name: josePereiro/MyResultsManager

max_issues_repo_name: josePereiro/MyResultsManager

max_forks_repo_name: josePereiro/MyResultsManager


text:
tapFlowVecDict = Dict();
tapFlowDicDict = Dict();
arcsDict = Dict();
coeffs_dict = Dict();
jacobDict = Dict();
descDirecDict = Dict();
searchDirecDict = Dict();
demandsVecDict = Dict();
thetaMaxDict = Dict();
objFunDict = Dict();
norObjFunDict = Dict();
objInvVIDict = Dict();
demandsDiffDict = Dict();
odPairRouteDict = Dict();
jacobiSpiessDict = Dict();
linkCostDicDict = Dict();

max_stars_repo_name: jingzbu/InverseVITraffic

max_issues_repo_name: jingzbu/InverseVITraffic

max_forks_repo_name: jingzbu/InverseVITraffic


text:
function _precompile_()
    ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
    @assert precompile(
        Tuple{
            Core.kwftype(typeof(optimize_ticks)),
            NamedTuple{(:k_min, :k_max),Tuple{Int,Int}},
            typeof(optimize_ticks),
            Float64,
            Float64,
        },
    )
    for C in (RGB, RGBA), T in (Colors.FixedPointNumbers.N0f8, Float32, Float64)
        @assert precompile(cgrad, (ColorScheme{Vector{C{T}},String,String},))
        for V in (Vector{Float64}, typeof(get_range(3)))
            @assert precompile(cgrad, (ColorScheme{Vector{C{T}},String,String}, V))
            @assert precompile(
                CategoricalColorGradient,
                (ColorScheme{Vector{C{T}},String,String}, V),
            )
            @assert precompile(
                ContinuousColorGradient,
                (ColorScheme{Vector{C{T}},String,String}, V),
            )
        end
    end
    for T in (Float64, Int)
        @assert precompile(zscale, (Vector{T},))
    end
    @assert precompile(optimize_ticks, (Int, Int))
    @assert precompile(optimize_datetime_ticks, (Int, Int))
    @assert precompile(adapted_grid, (Function, Tuple{Int,Int}))
end


text:
using Test, DiracNotation, Random

include("array_test.jl")


text:
using DelayDiffEq, DiffEqProblemLibrary.DDEProblemLibrary
using Test

DDEProblemLibrary.importddeproblems()

const prob = DDEProblemLibrary.prob_dde_constant_1delay_long_ip
const alg = MethodOfSteps(Tsit5())

# reference integrator and solution
const dde_int = init(prob, alg)
const sol = solve!(dde_int)

@testset "reference" begin
  # solution equals solution of DDE integrator
  @test sol.t == dde_int.sol.t
  @test sol.u == dde_int.sol.u

  # solution equals solution of ODE integrator
  @test sol.t == dde_int.integrator.sol.t
  @test sol.u == dde_int.integrator.sol.u
end

# do not save every step
@testset "not every step (save_start=$save_start)" for save_start in (false, true)
  # for time(s) as scalar (implicitly adds end point as well!) and vectors
  for saveat in (25.0, [25.0, 50.0, 75.0])
    dde_int2 = init(prob, alg; saveat=saveat, save_start=save_start)

    # end point is saved if saveat is a scalar
    @test dde_int2.opts.save_end == (saveat isa Number)

    sol2 = solve!(dde_int2)

    # solution is equal to solution of DDE integrator
    @test sol2.t == dde_int2.sol.t
    @test sol2.u == dde_int2.sol.u

    # time point of solution
    if saveat isa Number
      @test sol2.t == (save_start ? [0.0, 25.0, 50.0, 75.0, 100.0] : [25.0, 50.0, 75.0, 100.0])
    else
      @test sol2.t == (save_start ? [0.0, 25.0, 50.0, 75.0] : [25.0, 50.0, 75.0])
    end

    # history is equal to solution above
    @test sol.t == dde_int2.integrator.sol.t
    @test sol.u == dde_int2.integrator.sol.u
  end
end

# do not save every step
@testset "not every step (save_end=$save_end)" for save_end in (false, true)
  # for time(s) as scalar (implicitly adds end point as well!) and vectors
  for saveat in (25.0, [25.0, 50.0, 75.0])
    dde_int2 = init(prob, alg; saveat=saveat, save_end=save_end)

    # start point is saved if saveat is a scalar
    @test dde_int2.opts.save_start == (saveat isa Number)

    sol2 = solve!(dde_int2)

    # solution is equal to solution of DDE integrator
    @test sol2.t == dde_int2.sol.t
    @test sol2.u == dde_int2.sol.u

    # time point of solution
    if saveat isa Number
      @test sol2.t == [0.0, 25.0, 50.0, 75.0, 100.0]
    else
      @test sol2.t == (save_end ? [25.0, 50.0, 75.0, 100.0] : [25.0, 50.0, 75.0])
    end

    # history is equal to solution above
    @test sol.t == dde_int2.integrator.sol.t
    @test sol.u == dde_int2.integrator.sol.u
  end
end

# save every step
@testset "every step (save_start=$save_start)" for save_start in (false, true)
  for saveat in (25.0, [25.0, 50.0, 75.0])
    dde_int2 = init(prob, alg; saveat=saveat, save_everystep=true,
                    save_start=save_start)

    # end point is saved implicitly
    @test dde_int2.opts.save_end

    sol2 = solve!(dde_int2)

    # solution is equal to solution of DDE integrator
    @test sol2.t == dde_int2.sol.t
    @test sol2.u == dde_int2.sol.u

    # time points of solution
    if saveat isa Number
      @test symdiff(sol.t, sol2.t) == (save_start ? [100.0, 25.0, 50.0, 75.0] :
                                       [0.0, 100.0, 25.0, 50.0, 75.0])
    else
      @test symdiff(sol.t, sol2.t) == (save_start ? [25.0, 50.0, 75.0] :
                                       [0.0, 25.0, 50.0, 75.0])
    end

    # history is equal to solution above
    @test sol.t == dde_int2.integrator.sol.t
    @test sol.u == dde_int2.integrator.sol.u
  end
end

# save every step
@testset "every step (save_end=$save_end)" for save_end in (false, true)
  for saveat in (25.0, [25.0, 50.0, 75.0])
    dde_int2 = init(prob, alg; saveat=saveat, save_everystep=true,
                    save_end=save_end)

    # start point is saved implicitly
    @test dde_int2.opts.save_start

    sol2 = solve!(dde_int2)

    # solution is equal to solution of DDE integrator
    @test sol2.t == dde_int2.sol.t
    @test sol2.u == dde_int2.sol.u

    # time points of solution
    if saveat isa Number
      @test symdiff(sol.t, sol2.t) == (save_end ? [100.0, 25.0, 50.0, 75.0] :
                                       [100.0, 25.0, 50.0, 75.0])
    else
      @test symdiff(sol.t, sol2.t) == (save_end ? [25.0, 50.0, 75.0] :
                                       [25.0, 50.0, 75.0])
    end

    # history is equal to solution above
    @test sol.t == dde_int2.integrator.sol.t
    @test sol.u == dde_int2.integrator.sol.u
  end
end


text:
using OpenQuantumBase, Test
import SparseArrays:spzeros

A = (s)->(1 - s)
B = (s)->s
u = [1.0 + 0.0im, 1] / sqrt(2)
ρ = u * u'

H_sparse = SparseHamiltonian([A, B], [spσx, spσz])

H_real = convert(Real, H_sparse)
@test eltype(H_real) <: Real
@test H_sparse(0.0) ≈ H_real(0.0)

@test size(H_sparse) == (2,2)
@test issparse(H_sparse)
@test H_sparse(0) ≈ 2π * spσx
@test evaluate(H_sparse, 0) == spσx
@test H_sparse(0.5) ≈ π * (spσx + spσz)
@test evaluate(H_sparse, 0.5) == (spσx + spσz)/2
@test get_cache(H_sparse) ≈ π*(spσx + spσz)

du = [1.0 + 0.0im 0; 0 0]
H_sparse(du, ρ, 1.0, 0.5)
@test du ≈ -1.0im * π * ((σx + σz) * ρ - ρ * (σx + σz))

# update_cache method
C = similar(spσz)
update_cache!(C, H_sparse, 10, 0.5)
@test C == -1im * π * (spσx + spσz)

# update_vectorized_cache method
C = C⊗C
update_vectorized_cache!(C, H_sparse, 10, 0.5)
temp = -1im * π * (spσx + spσz)
@test C == spσi⊗temp - transpose(temp)⊗spσi

H_sparse = SparseHamiltonian([A, B], real.([spσx ⊗ spσi + spσi ⊗ spσx, 0.1spσz ⊗ spσi - spσz ⊗ spσz]))
w, v = eigen_decomp(H_sparse, 1.0)
vf = [0, 0, 0, 1.0]

@test w ≈ [-1.1, -0.9]
@test abs(v[end, 1]) ≈ 1
@test abs(v[1, 2]) ≈ 1


text:
module CLBLAS

export axpy!, scal!, gemm!

# why there is a type assertion at context.jl line 38
import OpenCL.cl

@unix_only const libCLBLAS = "libclBLAS"
@windows_only const libCLBLAS = "clBLAS"

include("constants.jl")
include("macros.jl")

include("L1/L1.jl")
include("L2/L2.jl")
include("L3/L3.jl")

include("highlevel.jl")

LocalMem{T}(::Type{T}, len::Integer) = begin
    @assert len > 0
    nbytes = sizeof(T) * len
    return LocalMem{T}(convert(Csize_t, nbytes))
end

# setup function
@blasfun clblasSetup()

#destroy
@blasfun clblasTeardown()

global compute_context_holder = Array(Tuple, 0)
global next_compute_context = -1
global setup_called = false

function get_next_compute_context()
    global next_compute_context = next_compute_context + 1
    return get_next_compute_context(next_compute_context)
end

function get_next_compute_context(next_compute_context)
    return compute_context_holder[( next_compute_context % length(compute_context_holder)) + 1]
end

function supress_context_error(error_info, private_info)
    warn(error_info)
    return C_NULL
end

function setup(profile=false)
    if isempty(cl.platforms())
        throw(cl.OpenCLException("No OpenCL.Platform available"))
    end
    #TODO: osx only due to https://github.com/clMathLibraries/clBLAS/issues/25
    available_devices = @osx ? cl.devices(:gpu) : cl.devices()
    if isempty(available_devices)
        throw(cl.OpenCLException("Unable to create any OpenCL.Context, no available devices"))
    end
    if !isempty(available_devices)
        for dev in available_devices
            local ctx::cl.Context
            local queue::cl.CmdQueue
            try
                ctx = cl.Context(dev, properties=nothing, callback=supress_context_error)
                queue  = profile ? cl.CmdQueue(ctx, :profile) : cl.CmdQueue(ctx);
                push!(compute_context_holder, (dev, ctx, queue))
            catch err
                error(err)
            end
        end
    end
    if isempty(compute_context_holder)
        throw(cl.OpenCLException("Unable to create any OpenCL.Context, not worked..."))
    end
    #initializing clblas
    clblasSetup()
end

function teardown()
    clblasTeardown()
    release!(compute_context_holder)
    global compute_context_holder = Array(Tuple, 0)
    global next_compute_context = -1
    global setup_called = false
    return nothing
end

function release!(compute_context_holder::Vector{Tuple})
    for (dev, ctx, queue) in compute_context_holder
        try
            finalize(queue)
            finalize(ctx)
        catch err
            println(err)
            continue
        end
    end
end

end # module


text:
include("linmin1.jl")
include("linmin2.jl")

function Sch_solve_Emin_cg( pw::PWGrid, Vpot, psi::Array{ComplexF64,2};
                            NiterMax=1000 )
    #
    Npoints = size(psi)[1]
    Nstates = size(psi)[2]
    d = zeros(ComplexF64, Npoints, Nstates)
    g_old  = zeros(ComplexF64, Npoints, Nstates)
    d_old  = zeros(ComplexF64, Npoints, Nstates)
    Kg     = zeros(ComplexF64, Npoints, Nstates)
    Kg_old = zeros(ComplexF64, Npoints, Nstates)
    #
    α_t = 3e-5
    β = 0.0

    Etot = calc_Etot( pw, Vpot, psi )
    Etot_old = Etot

    #
    for iter = 1:NiterMax
        g = calc_grad( pw, Vpot,  psi)
        nrm = 0.0
        for is = 1:Nstates
          nrm = nrm + real( dot( g[:,is], g[:,is] ) )
        end

        Kg = Kprec(pw,g)
        #Kg = copy(g)  # test for no preconditioner

        if iter != 1
          #β = real(sum(conj(g).*Kg))/real(sum(conj(g_old).*Kg_old))
          #β = real(sum(conj(g-g_old).*Kg))/real(sum(conj(g_old).*Kg_old))
          #β = real(sum(conj(g-g_old).*Kg))/real(sum(conj(g-g_old).*d_old))
          β = real(sum(conj(g).*Kg))/real(sum((g-g_old).*conj(d_old)))
        end

        if β < 0.0
            println("β is negative: set to zero")
            β = 0.0
        end

        d = -Kg + β * d_old

        #α = linmin2( pw, Vpot, α_t, psi, d, g )

        α = linmin1( pw, Vpot, α_t, psi, d, Etot_old, g )

        # Update wavefunction
        psi = psi[:,:] + α*d[:,:]

        psi = ortho_gram_schmidt(psi)
        Etot = calc_Etot( pw, Vpot, psi )

        diff = abs(Etot-Etot_old)
        @printf("E step %8d = %18.10f %18.10f %18.10f\n", iter, Etot, diff, nrm/Nstates)
        if diff < 1e-6
            @printf("CONVERGENCE ACHIEVED\n")
            break
        end
        g_old = copy(g)
        d_old = copy(d)
        Kg_old = copy(Kg)
        Etot_old = Etot
    end
    return psi, Etot
    #
end


text:
import Base:show
export AbstractPropMethod, AdiabaticProcessing, QuExpmV, QuExpokit, timer, hamiltonian

abstract AbstractPropMethod

immutable QuExpokit <: AbstractPropMethod
    options::Dict{Symbol, Any}
end

QuExpokit() = QuExpokit(Dict())

function (prob::QuExpokit)(scalar::Real, A::AbstractMatrix, v::Vector)
    return Expokit.expmv(scalar,A,v,m=get(prob.options, :m, 30), tol=get(prob.options, :tol, 1e-7))
end

type QuExpmV <: AbstractPropMethod
    options::Dict{Symbol, Any}
end

QuExpmV() = QuExpmV(Dict())

function (prob::QuExpmV)(scalar::Real, A::AbstractMatrix, v::Vector)
    return ExpmV.expmv(scalar,A,v,M = get(prob.options, :M, []), prec = get(prob.options, :prec, "double"), shift = get(prob.options, :shift, false), full_term = get(prob.options, :full_term, false))
end

immutable AdiabaticProcessing{H<:AbstractMatrix, S<:AbstractPropMethod, N}<:AQCprocessor{N}
    HB::H
    HP::H
    T::AbstractFloat
    prop::S
    dt::Real
    tlist::Tuple

    function AdiabaticProcessing(
        HP::H,
        method::S,
        maxtime::Real,
        dt::Real,
        tlist::Tuple
        )
        HB = bHamiltonian(N)

        # Similar Matrix
        P = eigenvector(0,N)
        for i=1:2^N-1
            P = [P eigenvector(i,N)]
        end
        invP = inv(P)
        HB = P*HB*invP
        new(HB,HP,maxtime,method,dt,tlist)
    end
end

AdiabaticProcessing{H<:AbstractMatrix,S<:AbstractPropMethod}(HP::H,method::S;dt=1e-2,tlist=(0.0,1.0),maxtime=1)=AdiabaticProcessing{H,S,Int(log2(size(HP)[1]))}(HP,method,maxtime,dt,tlist)

AdiabaticProcessing(HP::AbstractMatrix) = AdiabaticProcessing(HP,QuExpmV())

function show{H,S,N}(io::IO,ap::AdiabaticProcessing{H,S,N})
    println(io,"------------------------------")
    println(io,"$N qubits Adiabatic Processing")
end

# function print{H,S,N}(ap::AdiabaticProcessing{H,S,N})
#     println("------------------------------")
#     println("$N qubits Adiabatic Processing")
# end

function hamiltonian(ap::AdiabaticProcessing, s::Real)
    return (1-s)*ap.HB+s*ap.HP
end

# return processor output states and time cost
function run!(ap::AdiabaticProcessing, aqc::AQC)
    for t in ap.tlist[1]*ap.T:ap.dt:ap.tlist[2]*ap.T
        s = t/ap.T
        H = hamiltonian(ap, s)
        aqc.state.coeffs = ap.prop(ap.dt, -im*H, coeff(aqc.state))
    end
    aqc.sys_h = hamiltonian(ap, ap.tlist[2])
    return (ap.tlist[2]-ap.tlist[1])*ap.T
end

function timer(ap::AdiabaticProcessing)
    return ap.T
end

max_stars_repo_name: Roger-luo/openQC

max_issues_repo_name: Roger-luo/openQC

max_forks_repo_name: Roger-luo/openQC