text:
using FrameFun.Platforms, FrameFun.FrameFunInterface, FrameFun.ExtensionFramePlatforms,
    FrameFun.FrameFunInterface, FrameFun.ExtensionFramePlatforms, FrameFun.ExtensionFrames,
    FrameFun.WeightedSumPlatforms, FrameFun.AugmentationPlatforms, FrameFun.FrameFunInterfaceExtension,
    BasisFunctions, FrameFun.ApproximationProblems, FrameFun.FrameFunPlatforms,
    DomainSets, StaticArrays, Test, LinearAlgebra

# TODO add AugmentationPlatforms tests
d1 = 0.0..0.5
    plat1 = platform(extensionframe(Fourier(10),0.0..0.5)), 10
    d2 = (0.0..0.5)^2
    plat2 = platform(extensionframe(Fourier(10)^2,d2)), (10,10)
    d3 = disk(.45,SVector(.5,.5))
    plat3 = platform(extensionframe(Fourier(10)^2,d3)), (10,10)
    plat4 = platform(extensionframe((Fourier(10)→(-1.0..1.0))^2,d3)), (10,10)

    wplat1 = WeightedSumPlatform(platform(Fourier(10)), x->1., sqrt), (10,10)
    wplat2 = WeightedSumPlatform(platform(Fourier(10)^2), (x,y)->1., (x,y)->sqrt(x^2+y^2)), ((10,10),(10,10))

    ap1 = approximationproblem(Fourier(10),d1)
    ap2 = approximationproblem(Fourier(10)^2,d2)
    ap3 = approximationproblem(Fourier(10)^2,d3)
    ap4 = approximationproblem((Fourier(10)→(-1.0..1.0))^2,d3)
    wap1 = approximationproblem(wplat1...)
    wap2 = approximationproblem(wplat2...)

    dict1 = dictionary(ap1)
    dict2 = dictionary(ap2)
    dict3 = dictionary(ap3)
    dict4 = dictionary(ap4)
    wdict1 = dictionary(wap1)
    wdict2 = dictionary(wap2)

@testset "dictionary" begin
    for plat in (plat1,plat2,plat3,plat4)
        @test dictionary(plat...) isa ExtensionFrameSuper
        @test dualdictionary(plat...,measure(plat[1])) isa ExtensionFrameSuper
    end

    for ap in (ap1,ap2,ap3,ap4)
        @test dictionary(ap) isa ExtensionFrameSuper
    end

    for (plat,ap) in zip((wplat1,wplat2),(wap1,wap2))
        @test dictionary(plat...) isa MultiDict
        @test dictionary(ap) isa MultiDict
        @test dualdictionary(plat...,measure(plat[1])) isa MultiDict
    end
end

@testset "samplingparameter" begin
    @test samplingparameter(ap1) == 38
    @test samplingparameter(ap2) == (27,27)
    @test samplingparameter(ap3) == (18,18)
    @test samplingparameter(ap4) == (36,36)

    @test samplingparameter(wap1) == (40)
    @test samplingparameter(wap2) == (21,21)

    @test samplingparameter(plat1...)  == samplingparameter(ap1)
    @test samplingparameter(plat2...)   == samplingparameter(ap2)
    @test samplingparameter(plat3...) == samplingparameter(ap3)
    @test samplingparameter(plat4...) == samplingparameter(ap4)
    @test samplingparameter(wplat1...) == samplingparameter(wap1)
    @test samplingparameter(wplat2...) == samplingparameter(wap2)
end

@testset "oversampling_grid" begin

    @test oversampling_grid(ap1) isa IndexSubGrid
    @test oversampling_grid(ap2) isa TensorSubGrid
    @test oversampling_grid(ap3) isa GridArrays.MaskedGrid
    @test oversampling_grid(ap4) isa GridArrays.MaskedGrid

    @test oversampling_grid(wap1) == FourierGrid(40)
    @test oversampling_grid(wap2) == FourierGrid(21)^2

    @test oversampling_grid(plat1...) isa IndexSubGrid
    @test oversampling_grid(plat2...) isa TensorSubGrid
    @test oversampling_grid(plat3...) isa GridArrays.MaskedGrid
    @test oversampling_grid(plat4...) isa GridArrays.MaskedGrid
    @test oversampling_grid(wplat1...) == FourierGrid(40)
    @test oversampling_grid(wplat2...) == FourierGrid(21)^2
end

@testset "samplingoperator" begin
    f1 = exp
    f2 = (x,y) -> exp(x*y)
    op1 = samplingoperator(ap1)
    op2 = samplingoperator(ap2)
    op3 = samplingoperator(ap3)
    op4 = samplingoperator(ap4)

    op5 = samplingoperator(wap1)
    op6 = samplingoperator(wap2)
    # Generic operators so hard to check their structure

    @test samplingoperator(ap1)*f1≈samplingoperator(plat1...)*f1
    @test samplingoperator(ap2)*f2≈samplingoperator(plat2...)*f2
    @test samplingoperator(ap3)*f2≈samplingoperator(plat3...)*f2
    @test samplingoperator(ap4)*f2≈samplingoperator(plat4...)*f2

    @test samplingoperator(wap1)*f1≈samplingoperator(wplat1...)*f1
    @test samplingoperator(wap2)*f2≈samplingoperator(wplat2...)*f2
end

@testset "sampling_grid" begin
    for ap in (ap1,ap2,ap3,ap4,wap1,wap2)
        @test sampling_grid(ap)≈oversampling_grid(ap)
    end
    for plat in (plat1,plat2,plat3,plat4,wplat1,wplat2)
        @test sampling_grid(plat...)≈oversampling_grid(plat...)
    end
    for dict in (dict1,dict2,dict3,dict4)
        @test sampling_grid(dict)≈oversampling_grid(dict)
    end
end

@testset "discretemeasure" begin
    for ap in (ap1,ap2,ap3,ap4,wap1,wap2)
        @test discretemeasure(ap)≈discretemeasure(sampling_grid(ap))
    end
    for plat in (plat1,plat2,plat3,plat4,wplat1,wplat2)
        @test discretemeasure(plat...)≈discretemeasure(sampling_grid(plat...))
    end
    for dict in (dict1,dict2,dict3,dict4)
        @test discretemeasure(dict)≈discretemeasure(sampling_grid(dict))
    end
end

@testset "measure" begin
    @test measure(ap1)==measure(dict1)
    @test measure(ap2)==measure(dict2)
    @test measure(ap3)==measure(dict3)
    @test measure(ap4)==measure(dict4)
    @test measure(wap1)==measure(wdict1)
    @test measure(wap2)==measure(wdict2)
    @test measure(plat1...)==measure(dict1)
    @test measure(plat2...)==measure(dict2)
    @test measure(plat3...)==measure(dict3)
    @test measure(plat4...)==measure(dict4)
    @test measure(wplat1...)==measure(wdict1)
    @test measure(wplat2...) ==measure(wdict2)
end

@testset "azdual_dict" begin
    @test azdual_dict(ap1) isa ExtensionFrame
    @test azdual_dict(ap2) isa ExtensionFrameTensor
    @test azdual_dict(ap3) isa ExtensionFrame
    @test azdual_dict(ap4) isa ExtensionFrame
    @test azdual_dict(wap1) isa MultiDict
    @test azdual_dict(wap2) isa MultiDict

    @test azdual_dict(plat1...) isa ExtensionFrame
    @test azdual_dict(plat2...) isa ExtensionFrameTensor
    @test azdual_dict(plat3...) isa ExtensionFrame
    @test azdual_dict(plat4...) isa ExtensionFrame
    @test azdual_dict(wplat1...) isa MultiDict
    @test azdual_dict(wplat2...) isa MultiDict

    @test azdual_dict(dict1) isa ExtensionFrame
    @test azdual_dict(dict2) isa ExtensionFrameTensor
    @test azdual_dict(dict3) isa ExtensionFrame
    @test azdual_dict(dict4) isa ExtensionFrame
end

@testset "discretization" begin
    op = discretization(ap1)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict1, r, sampling_grid(ap1))
    op = discretization(ap2)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict2, r, sampling_grid(ap2))
    op = discretization(ap3)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict3, r, sampling_grid(ap3))
    op = discretization(ap4)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict4, r, sampling_grid(ap4))
    op = discretization(wap1)
    r = rand(src(op))
    @test op*r≈eval_expansion(wdict1, r, sampling_grid(wap1))
    op = discretization(wap2)
    r = rand(src(op))
    @test op*r≈eval_expansion(wdict2, r, sampling_grid(wap2))

    op = discretization(plat1...)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict1, r, sampling_grid(ap1))
    op = discretization(plat2...)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict2, r, sampling_grid(ap2))
    op = discretization(plat3...)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict3, r, sampling_grid(ap3))
    op = discretization(plat4...)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict4, r, sampling_grid(ap4))
    op = discretization(wplat1...)
    r = rand(src(op))
    @test op*r≈eval_expansion(wdict1, r, sampling_grid(wap1))
    op = discretization(wplat2...)
    r = rand(src(op))
    @test op*r≈eval_expansion(wdict2, r, sampling_grid(wap2))

    op = discretization(dict1)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict1, r, sampling_grid(ap1))
    op = discretization(dict2)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict2, r, sampling_grid(ap2))
    op = discretization(dict3)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict3, r, sampling_grid(ap3))
    op = discretization(dict4)
    r = rand(src(op))
    @test op*r≈eval_expansion(dict4, r, sampling_grid(ap4))

end

@testset "dualdiscretization" begin
    op = dualdiscretization(ap1)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap1), r, sampling_grid(ap1))
    op = dualdiscretization(ap2)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap2), r, sampling_grid(ap2))
    op = dualdiscretization(ap3)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap3), r, sampling_grid(ap3))
    op = dualdiscretization(ap4)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap4), r, sampling_grid(ap4))
    op = dualdiscretization(wap1)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(wap1), r, sampling_grid(wap1))
    op = dualdiscretization(wap2)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(wap2), r, sampling_grid(wap2))

    op = dualdiscretization(plat1...)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap1), r, sampling_grid(ap1))
    op = dualdiscretization(plat2...)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap2), r, sampling_grid(ap2))
    op = dualdiscretization(plat3...)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap3), r, sampling_grid(ap3))
    op = dualdiscretization(plat4...)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap4), r, sampling_grid(ap4))
    op = dualdiscretization(wplat1...)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(wap1), r, sampling_grid(wap1))
    op = dualdiscretization(wplat2...)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(wap2), r, sampling_grid(wap2))

    op = dualdiscretization(dict1)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap1), r, sampling_grid(ap1))
    op = dualdiscretization(dict2)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap2), r, sampling_grid(ap2))
    op = dualdiscretization(dict3)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap3), r, sampling_grid(ap3))
    op = dualdiscretization(dict4)
    r = rand(src(op))
    @test op*r≈eval_expansion(azdual_dict(ap4), r, sampling_grid(ap4))
end

@testset "solvers" begin
    for dict in (dict1,)

        op1 = solver(dict;solverstyle=DirectStyle())
        r = rand(src(op1))
        # @show "11"
        op2 = solver(dict;solverstyle=IterativeStyle())
        @test norm(op1*r-op2*r) < 1e-4
        # @show "12"
        op3 = solver(dict;solverstyle=AZStyle())
        @test norm(op1*r-op3*r) < 1e-4
        # @show "13"
        op4 = solver(dict;solverstyle=AZSmoothStyle())
        @test norm(op1*r-op4*r) < 1e-4
        # @show "14"
        op4 = solver(dict;solverstyle=TridiagonalProlateStyle())
    end

    for dict in (dict1,dict3,dict4)
        op1 = solver(dict;solverstyle=DirectStyle())
        r = rand(src(op1))
        # @show "21"
        op2 = solver(dict;solverstyle=AZStyle())
        @test  norm(op1*r-op2*r) < 1e-1
        # @show "22"
    end

    P = FourierExtensionPlatform(0.0..0.5)
    f = exp
    A,b = discretization(f, P, 100)
    M = plungeoperator(P,100)*A
    # @show "31"
    S = rSVD_solver(M;threshold=1e-4)
    x1 = S*plungeoperator(P,100)*b
    # @show "32"
    x2 = AZ_Zt(P,100)*(b-A*x1)
    # @show "33"
    @test norm(A*(x1+x2)-b) <  1e-3
end
# @show "AZ_A, AZ_Z, AZ_Zt, plungeoperator, firstAZstepoperator, plungerank"
@testset "AZ_A, AZ_Z, AZ_Zt, plungeoperator, firstAZstepoperator, plungerank" begin

    for (ap, plat) in ((ap1,plat1),(ap2,plat2),(ap3,plat3),(ap4,plat4),(wap1,wplat1),(wap2,wplat2))
        @test AZ_A(ap) ≈ AZ_A(plat...)
        # @show "41"
        @test AZ_Zt(ap) ≈ AZ_Zt(plat...)
        # @show "42"
        @test plungeoperator(ap) ≈ plungeoperator(plat...)
        # @show "43"
        @test firstAZstepoperator(ap) ≈ firstAZstepoperator(plat...)
        # @show "44"
        @test abs(plungerank(ap) - plungerank(plat...)) < 3
        # @show "45"
    end

    for (ap, dict) in ((ap1,dict1),(ap2,dict2),(ap3,dict3),(ap4,dict4),)
        @test AZ_A(ap) ≈ AZ_A(dict)
        # @show "45"
        @test AZ_Zt(ap) ≈ AZ_Zt(dict)
        # @show "47"
        @test plungeoperator(ap) ≈ plungeoperator(dict)
        # @show "48"
        @test firstAZstepoperator(ap) ≈ firstAZstepoperator(dict)
        # @show "49"
        @test abs(plungerank(ap) - plungerank(dict)) < 3
        # @show "410"
    end

    for ap in (ap1,ap2,ap3,ap4,wap1,wap2)
        @test norm(plungeoperator(ap) - (I -AZ_A(ap)*AZ_Zt(ap))) < 1e-12
        # @show "51"
        @test norm(firstAZstepoperator(ap) - (AZ_A(ap) -AZ_A(ap)*AZ_Zt(ap)*AZ_A(ap) )) < 1e-12
        # @show "52"
    end

    @test plungerank(plat1[1],(100);threshold=1e-6,verbose=false) <= 30
    # @show "61"
    @test plungerank(plat2[1],(30,30);threshold=1e-6,verbose=false) <= 700
    # @show "62"
    @test plungerank(plat3[1],(30,30);threshold=1e-6,verbose=false) <= 600
    # @show "63"
    @test plungerank(plat4[1],(30,30);threshold=1e-6,verbose=false) <= 600
    # @show "64"
    @test plungerank(wplat1[1],(100,100);threshold=1e-6,verbose=false) <= 30
    # @show "65"
    @test plungerank(wplat2[1],((15,15),(15,15));threshold=1e-6,verbose=false)  <= 400
    # @show "66"

end
# @show  "approximate"
@testset "approximate" begin
    P = FourierExtensionPlatform(0.0..0.5)
    f = exp
    A,b = discretization(f, P, 100)
    # @show "71"
    M = plungeoperator(P,100)*A
    # @show "72"
    S = rSVD_solver(M;threshold=1e-4)
    x1 = S*plungeoperator(P,100)*b
    # @show "73"
    x2 = AZ_Zt(P,100)*(b-A*x1)
    # @show "74"
    @test norm(A*(x1+x2)-b) <  1e-3

    F = approximate(f, P, 100;REG=rSVD_solver)[1]
    # @show "75"
    x = .2; @test abs(F(x)-f(x)) < 1e-3
# @show "8"
    P = FourierExtensionPlatform(0.0..0.5)
    f = exp
    A,b = discretization(f, P, 100)
    # @show "81"
    M = plungeoperator(P,100)*A
    # @show "82"
    S = pQR_solver(M;threshold=1e-4)
    x1 = S*plungeoperator(P,100)*b
    # @show "82"
    x2 = AZ_Zt(P,100)*(b-A*x1)
    # @show "83"
    @test norm(A*(x1+x2)-b) < 1e-3
# @show "9"
    F = approximate(f, P, 100;REG=pQR_solver)[1]
    x = .2; @test abs(F(x)-f(x)) < 1e-3
# @show "10"
    P = FourierExtensionPlatform(0.0..0.5)
    f = exp
    A,b = discretization(f, P, 100)
    M = plungeoperator(P,100)*A
    S = pSVD_solver(M;threshold=1e-4)
    x1 = S*plungeoperator(P,100)*b
    x2 = AZ_Zt(P,100)*(b-A*x1)
    @test norm(A*(x1+x2)-b) < 1e-3

    F = approximate(f, P, 100;REG=pSVD_solver)[1]
    x = .2; @test abs(F(x)-f(x)) < 1e-3
end


text:
type AttributeType
    name::Union{ASCIIString, Void}
    value::Union{ASCIIString, Void}

    AttributeType(; name=nothing, value=nothing) =
         new(name, value)
end
function AttributeType(pd::LightXML.XMLElement)
    o = AttributeType()
    o.name = LightXML.content(LightXML.find_element(pd, "Name"))
    o.value = LightXML.content(LightXML.find_element(pd, "Value"))
    o
end

export AttributeType

# Note: dataType="Binary" is not supported because HTTPC.urlencode_query_params is not presently capable of encoding binary data into a URL.
# Need to either enhance HTTPClient package, or place binary data into POST message instead of GET.
type MessageAttributeValueType
    dataType::Union{AbstractString, Void}
    binaryValue::Union{Vector{UInt8}, Void}
    stringValue::Union{AbstractString, Void}

    MessageAttributeValueType(; dataType=nothing, binaryValue=nothing, stringValue=nothing) =
         new(dataType, binaryValue, stringValue)
end
function MessageAttributeValueType(pd::LightXML.XMLElement)
    o = MessageAttributeValueType()
    o.dataType = LightXML.find_element(pd, "DataType") != nothing ? LightXML.content(LightXML.find_element(pd, "DataType")) : nothing
    o.binaryValue = LightXML.find_element(pd, "BinaryValue") != nothing ? AWS.safe_parseb64(LightXML.content(LightXML.find_element(pd, "BinaryValue"))) : nothing
    o.stringValue = LightXML.find_element(pd, "StringValue") != nothing ? LightXML.content(LightXML.find_element(pd, "StringValue")) : nothing
    o
end

export MessageAttributeValueType

type MessageAttributeType
    name::Union{ASCIIString, Void}
    value::Union{MessageAttributeValueType, Void}

    MessageAttributeType(; name=nothing, value=nothing) =
         new(name, value)
end
function MessageAttributeType(pd::LightXML.XMLElement)
    o = MessageAttributeType()
    o.name = LightXML.content(LightXML.find_element(pd, "Name"))
    o.value = MessageAttributeValueType(LightXML.find_element(pd, "Value"))
    o
end

export MessageAttributeType

type CreateQueueType
    queueName::Union{ASCIIString, Void}
    attributeSet::Union{Vector{AttributeType}, Void}

    CreateQueueType(; queueName=nothing, attributeSet=nothing) =
         new(queueName, attributeSet)
end
function CreateQueueType(pd::LightXML.XMLElement)
    o = CreateQueueType()
    o.queueName = LightXML.content(LightXML.find_element(pd, "QueueName"))
    o.attributeSet = AWS.@parse_vector(AWS.SQS.AttributeType, LightXML.get_elements_by_tagname(LightXML.find_element(pd, "Attribute")))
    o
end

export CreateQueueType

type CreateQueueResponseType
    queueUrl::Union{ASCIIString, Void}
    requestId::Union{ASCIIString, Void}

    CreateQueueResponseType(; queueUrl=nothing, requestId=nothing) =
         new(queueUrl, requestId)
end
function CreateQueueResponseType(pd::LightXML.XMLElement)
    o = CreateQueueResponseType()
    o.queueUrl = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "CreateQueueResult"), "QueueUrl"))
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export CreateQueueResponseType

type GetQueueUrlType
    queueName::Union{ASCIIString, Void}
    queueOwnerAWSAccountId::Union{ASCIIString, Void}

    GetQueueUrlType(; queueName=nothing, queueOwnerAWSAccountId=nothing) =
         new(queueName, queueOwnerAWSAccountId)
end
function GetQueueUrlType(pd::LightXML.XMLElement)
    o = GetQueueUrlType()
    o.queueName = LightXML.content(LightXML.find_element(pd, "QueueName"))
    o.queueOwnerAWSAccountId = LightXML.content(LightXML.find_element(pd, "QueueOwnerAWSAccountId"))
    o
end

export GetQueueUrlType

type GetQueueUrlResponseType
    queueUrl::Union{ASCIIString, Void}
    requestId::Union{ASCIIString, Void}

    GetQueueUrlResponseType(; queueUrl=nothing, requestId=nothing) =
         new(queueUrl, requestId)
end
function GetQueueUrlResponseType(pd::LightXML.XMLElement)
    o = GetQueueUrlResponseType()
    o.queueUrl = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "GetQueueUrlResult"), "QueueUrl"))
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export GetQueueUrlResponseType

type ListQueuesType
    queueNamePrefix::Union{ASCIIString, Void}

    ListQueuesType(; queueNamePrefix=nothing) =
         new(queueNamePrefix)
end
function ListQueuesType(pd::LightXML.XMLElement)
    o = ListQueuesType()
    o.queueName = LightXML.content(LightXML.find_element(pd, "QueueNamePrefix"))
    o
end

export ListQueuesType

type ListQueuesResponseType
    queueUrlSet::Union{Vector{ASCIIString}, Void}
    requestId::Union{ASCIIString, Void}

    ListQueuesResponseType(; queueUrlSet=nothing, requestId=nothing) =
         new(queueUrlSet, requestId)
end
function ListQueuesResponseType(pd::LightXML.XMLElement)
    o = ListQueuesResponseType()
    o.queueUrlSet = ASCIIString[LightXML.content(url) for url in LightXML.get_elements_by_tagname(LightXML.find_element(pd, "ListQueuesResult"), "QueueUrl")]
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export ListQueuesResponseType

# ChangeMessageVisibilityType
# ChangeMessageVisibilityResponseType

type DeleteMessageType
    queueUrl::Union{ASCIIString, Void}
    receiptHandle::Union{ASCIIString, Void}

    DeleteMessageType(; queueUrl=nothing, receiptHandle=nothing) =
         new(queueUrl, receiptHandle)
end
function DeleteMessageType(pd::LightXML.XMLElement)
    o = DeleteMessageType()
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
    o.receiptHandle = LightXML.content(LightXML.find_element(pd, "ReceiptHandle"))
    o
end

export DeleteMessageType

type DeleteMessageResponseType
    requestId::Union{ASCIIString, Void}

    DeleteMessageResponseType(; requestId=nothing) =
         new(requestId)
end
function DeleteMessageResponseType(pd::LightXML.XMLElement)
    o = DeleteMessageResponseType()
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export DeleteMessageResponseType

type DeleteQueueType
    queueUrl::Union{ASCIIString, Void}

    DeleteQueueType(; queueUrl=nothing) =
         new(queueUrl)
end
function DeleteQueueType(pd::LightXML.XMLElement)
    o = DeleteQueueType()
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
    o
end

export DeleteQueueType

type DeleteQueueResponseType
    requestId::Union{ASCIIString, Void}

    DeleteQueueResponseType(; requestId=nothing) =
         new(requestId)
end
function DeleteQueueResponseType(pd::LightXML.XMLElement)
    o = DeleteQueueResponseType()
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export DeleteQueueResponseType

type GetQueueAttributesType
    attributeNameSet::Union{Vector{ASCIIString}, Void}
    queueUrl::Union{ASCIIString, Void}

    GetQueueAttributesType(; attributeNameSet=nothing, queueUrl=nothing) =
         new(attributeNameSet, queueUrl)
end
function GetQueueAttributesType(pd::LightXML.XMLElement)
    o = GetQueueAttributesType()
    o.attributeNameSet = AWS.@parse_vector(ASCIIString, LightXML.get_elements_by_tagname(pd, "AttributeName"))
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
    o
end

export GetQueueAttributesType

type GetQueueAttributesResponseType
    attributeSet::Union{Vector{AttributeType}, Void}
    requestId::Union{ASCIIString, Void}

    GetQueueAttributesResponseType(; attributeSet=nothing, requestId=nothing) =
         new(attributeSet, requestId)
end
function GetQueueAttributesResponseType(pd::LightXML.XMLElement)
    o = GetQueueAttributesResponseType()
    o.attributeSet = AWS.@parse_vector(AWS.SQS.AttributeType, LightXML.get_elements_by_tagname(LightXML.find_element(pd, "GetQueueAttributesResult"), "Attribute"))
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export GetQueueAttributesResponseType

type ReceiveMessageType
    maxNumberOfMessages::Union{Int, Void}
    visibilityTimeout::Union{Int, Void}
    waitTimeSeconds::Union{Int, Void}
    attributeNameSet::Union{Vector{ASCIIString}, Void}
    messageAttributeNameSet::Union{Vector{ASCIIString}, Void}
    queueUrl::Union{ASCIIString, Void}

    ReceiveMessageType(; maxNumberOfMessages=nothing, visibilityTimeout=nothing, waitTimeSeconds=nothing, attributeNameSet=nothing, messageAttributeNameSet=nothing, queueUrl=nothing) =
         new(maxNumberOfMessages, visibilityTimeout, waitTimeSeconds, attributeNameSet, messageAttributeNameSet, queueUrl)
end
function ReceiveMessageType(pd::LightXML.XMLElement)
    o = ReceiveMessageType()
    o.maxNumberOfMessages = AWS.safe_parseint(LightXML.content(LightXML.find_element(pd, "MaxNumberOfMessages")))
    o.visibilityTimeout = AWS.safe_parseint(LightXML.content(LightXML.find_element(pd, "VisibilityTimeout")))
    o.waitTimeSeconds = AWS.safe_parseint(LightXML.content(LightXML.find_element(pd, "WaitTimeSeconds")))
    o.attributeNameSet = AWS.@parse_vector(ASCIIString, LightXML.content(LightXML.get_elements_by_tagname(pd, "AttributeName")))
    o.messageAttributeNameSet = AWS.@parse_vector(ASCIIString, LightXML.content(LightXML.get_elements_by_tagname(pd, "MessageAttributeName")))
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
    o
end

export ReceiveMessageType

type MessageType
    messageId::Union{ASCIIString, Void}
    receiptHandle::Union{ASCIIString, Void}
    MD5OfBody::Union{ASCIIString, Void}
    MD5OfMessageAttributes::Union{ASCIIString, Void}
    body::Union{AbstractString, Void}
    attributeSet::Union{Vector{AttributeType}, Void}
    messageAttributeSet::Union{Vector{MessageAttributeType}, Void}

    MessageType(; messageId=nothing, receiptHandle=nothing, MD5OfBody=nothing, MD5OfMessageAttributes=nothing, body=nothing, attributeSet=nothing, messageAttributeSet=nothing) =
        new(messageId, receiptHandle, MD5OfBody, MD5OfMessageAttributes, body, attributeSet, messageAttributeSet)
end
function MessageType(pd::LightXML.XMLElement)
    o = MessageType()
    o.messageId = LightXML.content(LightXML.find_element(pd, "MessageId"))
    o.receiptHandle = LightXML.content(LightXML.find_element(pd, "ReceiptHandle"))
    o.MD5OfBody = LightXML.content(LightXML.find_element(pd, "MD5OfBody"))
    ## MDP o.MD5OfMessageAttributes = LightXML.content(LightXML.find_element(pd, "MD5OfMessageAttributes"))
    o.body = LightXML.content(LightXML.find_element(pd, "Body"))
    o.attributeSet = AWS.@parse_vector(AWS.SQS.AttributeType, LightXML.get_elements_by_tagname(pd, "Attribute"))
    o.messageAttributeSet = AWS.@parse_vector(AWS.SQS.MessageAttributeType, LightXML.get_elements_by_tagname(pd, "MessageAttribute"))
    o
end

export MessageType

type ReceiveMessageResponseType
    messageSet::Union{Vector{MessageType}, Void}
    requestId::Union{ASCIIString, Void}

    ReceiveMessageResponseType(; messageSet=nothing, requestId=nothing) =
         new(messageSet, requestId)
end
function ReceiveMessageResponseType(pd::LightXML.XMLElement)
    o = ReceiveMessageResponseType()
    o.messageSet = AWS.@parse_vector(AWS.SQS.MessageType, LightXML.get_elements_by_tagname(LightXML.find_element(pd, "ReceiveMessageResult"), "Message"))
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export ReceiveMessageResponseType

type SendMessageType
    delaySeconds::Union{Int, Void}
    messageAttributeSet::Union{Vector{MessageAttributeType}, Void}
    messageBody::Union{AbstractString, Void}
    queueUrl::Union{ASCIIString, Void}

    SendMessageType(; delaySeconds=nothing, messageBody=nothing, queueUrl=nothing) =
         new(delaySeconds, messageBody, queueUrl)
end
function SendMessageType(pd::LightXML.XMLElement)
    o = SendMessageType()
    o.delaySeconds = AWS.safe_parseint(LightXML.content(LightXML.find_element(pd, "DelaySeconds")))
    o.messageAttributeSet = AWS.@parse_vector(AWS.SQS.MessageAttributeType, LightXML.get_elements_by_tagname(pd, "MessageAttribute"))
    o.messageBody = LightXML.content(LightXML.find_element(pd, "MessageBody"))
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
    o
end

export SendMessageType

type SendMessageResponseType
    MD5OfMessageBody::Union{ASCIIString, Void}
    MD5OfMessageAttributes::Union{ASCIIString, Void}
    messageId::Union{ASCIIString, Void}
    requestId::Union{ASCIIString, Void}

    SendMessageResponseType(; MD5OfMessageBody=nothing, MD5OfMessageAttributes=nothing, messageId=nothing, requestId=nothing) =
         new(MD5OfMessageBody, MD5OfMessageAttributes, messageId, requestId)
end
function SendMessageResponseType(pd::LightXML.XMLElement)
    o = SendMessageResponseType()
    o.MD5OfMessageBody = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "SendMessageResult"), "MD5OfMessageBody"))
    ## MDP TODO o.MD5OfMessageAttributes = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "SendMessageResult"), "MD5OfMessageAttributes"))
    o.messageId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "SendMessageResult"), "MessageId"))
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export SendMessageResponseType

type SetQueueAttributesType
    attributeSet::Union{Vector{AttributeType}, Void}
    queueUrl::Union{ASCIIString, Void}

    SetQueueAttributesType(; attributeSet=nothing, queueUrl=nothing) =
         new(attributeSet, queueUrl)
end
function SetQueueAttributesType(pd::LightXML.XMLElement)
    o = SetQueueAttributesType()
    o.attributeSet = AWS.@parse_vector(AWS.SQS.AttributeType, LightXML.get_elements_by_tagname(pd, "Attribute"))
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
    o
end

export SetQueueAttributesType

type SetQueueAttributesResponseType
    requestId::Union{ASCIIString, Void}

    SetQueueAttributesResponseType(; requestId=nothing) =
         new(requestId)
end
function SetQueueAttributesResponseType(pd::LightXML.XMLElement)
    o = SetQueueAttributesResponseType()
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export SetQueueAttributesResponseType

type SendMessageBatchRequestEntryType
    delaySeconds::Union{Int, Void}
    id::Union{ASCIIString, Void}
    messageAttributeSet::Union{Vector{MessageAttributeType}, Void}
    messageBody::Union{AbstractString, Void}

	SendMessageBatchRequestEntryType(; delaySeconds=nothing, id=nothing, messageAttributeSet=nothing, messageBody=nothing) =
		new(delaySeconds, id, messageAttributeSet, messageBody)
end

function SendMessageBatchRequestEntryType(pd::LightXML.XMLElement)
	o = SendMessageBatchRequestEntryType()
    o.delaySeconds = AWS.safe_parseint(LightXML.content(LightXML.find_element(pd, "DelaySeconds")))
    o.messageAttributeSet = AWS.@parse_vector(AWS.SQS.MessageAttributeType, LightXML.get_elements_by_tagname(pd, "MessageAttribute"))
    o.messageBody = LightXML.content(LightXML.find_element(pd, "MessageBody"))
end

export SendMessageBatchRequestEntryType

type SendMessageBatchType
    sendMessageBatchRequestEntrySet::Union{Vector{SendMessageBatchRequestEntryType}, Void}
    queueUrl::Union{ASCIIString, Void}

    SendMessageBatchType(; sendMessageBatchRequestEntrySet=nothing, queueUrl=nothing) =
         new(sendMessageBatchRequestEntrySet, queueUrl)
end

function SendMessageBatchType(pd::LightXML.XMLElement)
	o = SendMessageBatchType()
	o.sendMessageBatchRequestSet = AWS.@parse_vector(AWS.SQS.SendMessageBatchRequestEntryType, LightXML.get_elements_by_tagname(pd, "SendMessageBatchRequestEntry"))
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
end

export SendMessageBatchType

type SendMessageBatchResultEntryType
    id::Union{ASCIIString, Void}
    MD5OfMessageAttributes::Union{ASCIIString, Void}
    MD5OfBody::Union{ASCIIString, Void}
    messageId::Union{ASCIIString, Void}

	SendMessageBatchResultEntryType(; id=nothing, MD5OfMessageAttributes=nothing, MD5OfBody=nothing, messageId=nothing) =
		new(id, MD5OfMessageAttributes, MD5OfBody, messageId)
end

function SendMessageBatchResultEntryType(pd::LightXML.XMLElement)
	o = SendMessageBatchResultEntryType()
    o.id = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "Id"))
    ## MDP TODO o.MD5OfMessageAttributes = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "SendMessageResult"), "MD5OfMessageAttributes"))
    o.MD5OfBody = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "SendMessageResult"), "MD5OfBody"))
    o.messageId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "SendMessageResult"), "MessageId"))
end

export SendMessageBatchResultEntryType

type SendMessageBatchResultErrorEntryType
    code::Union{ASCIIString, Void}
    id::Union{ASCIIString, Void}
    message::Union{ASCIIString, Void}
    senderFault::Union{Bool, Void}

	SendMessageBatchResultErrorEntryType(; code=nothing, id=nothing, message=nothing, senderFault=nothing) =
		new(code, id, message, senderFault)
end

function SendMessageBatchResultErrorEntryType(pd::LightXML.XMLElement)
    o = SendMessageBatchResultErrorEntryType()
    o.code = LightXML.content(LightXML.find_element(pd, "Code"))
    o.id = LightXML.content(LightXML.find_element(pd, "Id"))
    o.message = LightXML.content(LightXML.find_element(pd, "Message"))
    o.senderFault = LightXML.content(LightXML.find_element(pd, "SenderFault"))
end

export SendMessageBatchResultErrorEntryType

type SendMessageBatchResponseType
    sendMessageBatchResultSet::Union{Vector{SendMessageBatchResultEntryType}, Void}
    sendMessageBatchErrorSet::Union{Vector{SendMessageBatchResultErrorEntryType}, Void}

	SendMessageBatchResponseType(; sendMessageBatchResultSet=nothing, sendMessageBatchErrorSet=nothing) =
		new(sendMessageBatchResultSet, sendMessageBatchErrorSet)
end

function SendMessageBatchResponseType(pd::LightXML.XMLElement)
	o = SendMessageBatchResponseType()
    o.sendMessageBatchResultSet = AWS.@parse_vector(AWS.SQS.SendMessageBatchResultEntryType, LightXML.get_elements_by_tagname(pd, "SendMessageBatchResultEntry"))
    o.sendMessageBatchErrorSet = AWS.@parse_vector(AWS.SQS.SendMessageBatchResultErrorEntryType, LightXML.get_elements_by_tagname(pd, "SendMessageBatchResultErrorEntry"))
end

export SendMessageBatchResponseType

type DeleteMessageBatchRequestEntryType
    id::Union{ASCIIString, Void}
    receiptHandle::Union{ASCIIString, Void}

	DeleteMessageBatchRequestEntryType(; id=nothing, receiptHandle=nothing) =
		new(id, receiptHandle)
end

function DeleteMessageBatchRequestEntryType(pd::LightXML.XMLElement)
	o = DeleteMessageBatchRequestEntryType()
    o.id = LightXML.content(LightXML.find_element(pd, "Id"))
    o.receiptHandle = LightXML.content(LightXML.find_element(pd, "ReceiptHandle"))
end

export DeleteMessageBatchRequestEntryType

type DeleteMessageBatchType
    deleteMessageBatchRequestEntrySet::Union{Vector{DeleteMessageBatchRequestEntryType}, Void}
    queueUrl::Union{ASCIIString, Void}

    DeleteMessageBatchType(; deleteMessageBatchRequestEntrySet=nothing, queueUrl=nothing) =
         new(deleteMessageBatchRequestEntrySet, queueUrl)
end

function DeleteMessageBatchType(pd::LightXML.XMLElement)
	o = DeleteMessageBatchType()
	o.deleteMessageBatchRequestSet = AWS.@parse_vector(AWS.SQS.DeleteMessageBatchRequestEntryType, LightXML.get_elements_by_tagname(pd, "DeleteMessageBatchRequestEntry"))
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
end

export DeleteMessageBatchType

type DeleteMessageBatchResultErrorEntryType
    code::Union{ASCIIString, Void}
    id::Union{ASCIIString, Void}
    message::Union{ASCIIString, Void}
    senderFault::Union{Bool, Void}

    DeleteMessageBatchResultErrorEntryType(; code=nothing, id=nothing, message=nothing, senderFault=nothing) =
        new(code, id, message, senderFault)
end

function DeleteMessageBatchResultErrorEntryType(pd::LightXML.XMLElement)
    o = DeleteMessageBatchResultErrorEntryType()
    o.code = LightXML.content(LightXML.find_element(pd, "Code"))
    o.id = LightXML.content(LightXML.find_element(pd, "Id"))
    o.message = LightXML.content(LightXML.find_element(pd, "Message"))
    o.senderFault = LightXML.content(LightXML.find_element(pd, "SenderFault"))
end

export DeleteMessageBatchResultErrorEntryType

type DeleteMessageBatchResultEntryType
    deleteMessageBatchResultEntrySet::Union{Vector{DeleteMessageBatchResultEntryType}, Void}
    queueUrl::Union{ASCIIString, Void}

    DeleteMessageBatchResultEntryType(; deleteMessageBatchResultEntrySet=nothing, queueUrl=nothing) =
         new(deleteMessageBatchResultEntrySet, queueUrl)
end

function DeleteMessageBatchResultEntryType(pd::LightXML.XMLElement)
	o = DeleteMessageBatchResultEntryType()
	o.deleteMessageBatchResultSet = AWS.@parse_vector(AWS.SQS.DeleteMessageBatchResultEntryType, LightXML.get_elements_by_tagname(pd, "DeleteMessageBatchResultEntry"))
    o.queueUrl = LightXML.content(LightXML.find_element(pd, "QueueUrl"))
end

export DeleteMessageBatchResultEntryType

type DeleteMessageBatchResponseType
    deleteMessageBatchResultSet::Union{Vector{DeleteMessageBatchResultEntryType}, Void}
    deleteMessageBatchErrorSet::Union{Vector{DeleteMessageBatchResultErrorEntryType}, Void}

	DeleteMessageBatchResponseType(; deleteMessageBatchResultSet=nothing, deleteMessageBatchErrorSet=nothing) =
		new(deleteMessageBatchResultSet, deleteMessageBatchErrorSet)
end

function DeleteMessageBatchResponseType(pd::LightXML.XMLElement)
	o = DeleteMessageBatchResponseType()
    o.deleteMessageBatchResultSet = AWS.@parse_vector(AWS.SQS.DeleteMessageBatchResultEntryType, LightXML.get_elements_by_tagname(pd, "DeleteMessageBatchResultEntry"))
    o.deleteMessageBatchErrorSet = AWS.@parse_vector(AWS.SQS.DeleteMessageBatchResultErrorEntryType, LightXML.get_elements_by_tagname(pd, "DeleteMessageBatchResultErrorEntry"))
end

export DeleteMessageBatchResponseType

type ChangeMessageVisibilityType
    queueUrl::Union{ASCIIString, Void}
    receiptHandle::Union{ASCIIString, Void}
    visibilityTimeout::Union{Int64, Void}

    ChangeMessageVisibilityType(; queueUrl=nothing, receiptHandle=nothing, visibilityTimeout=nothing) =
         new(queueUrl, receiptHandle, visibilityTimeout)
end

export ChangeMessageVisibilityType

type ChangeMessageVisibilityResponseType
    requestId::Union{ASCIIString, Void}

    ChangeMessageVisibilityResponseType(; requestId=nothing) =
         new(requestId)
end
function ChangeMessageVisibilityResponseType(pd::LightXML.XMLElement)
    o = ChangeMessageVisibilityResponseType()
    o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o
end

export ChangeMessageVisibilityResponseType

type ChangeMessageVisibilityBatchRequestEntryType
    id::Union{ASCIIString, Void}
    receiptHandle::Union{ASCIIString, Void}
    visibilityTimeout::Union{Int64, Void}

    ChangeMessageVisibilityBatchRequestEntryType(; id=nothing, receiptHandle=nothing, visibilityTimeout=nothing) =
         new(id, receiptHandle, visibilityTimeout)
end

export ChangeMessageVisibilityBatchRequestEntryType

type ChangeMessageVisibilityBatchType
    queueUrl::Union{ASCIIString, Void}
	changeMessageVisibilityBatchRequestEntrySet::Union{Vector{ChangeMessageVisibilityBatchRequestEntryType}, Void}

    ChangeMessageVisibilityBatchType(; queueUrl=nothing, changeMessageVisibilityBatchRequestEntrySet=nothing) =
         new(queueUrl, changeMessageVisibilityBatchRequestEntrySet)
end

export ChangeMessageVisibilityBatchType

type ChangeMessageVisibilityBatchResultEntryType
	id::Union{Int64, Void}

	ChangeMessageVisibilityBatchResultEntryType(; id=nothing) =
		new(id)
end

function ChangeMessageVisibilityBatchResultEntryType(pd::LightXML.XMLElement)
    o = ChangeMessageVisibilityBatchResultEntryType()
    o.id = AWS.safe_parseint(LightXML.content(LightXML.find_element(pd, "Id")))
    o
end

export ChangeMessageVisibilityBatchResultEntryType

type ChangeMessageVisibilityBatchResultErrorEntryType
    code::Union{ASCIIString, Void}
    id::Union{ASCIIString, Void}
    message::Union{ASCIIString, Void}
    senderFault::Union{Bool, Void}

    ChangeMessageVisibilityBatchResultErrorEntryType(; code=nothing, id=nothing, message=nothing, senderFault=nothing) =
        new(code, id, message, senderFault)
end

function ChangeMessageVisibilityBatchResultErrorEntryType(pd::LightXML.XMLElement)
    o = ChangeMessageVisibilityBatchResultErrorEntryType()
    o.code = LightXML.content(LightXML.find_element(pd, "Code"))
    o.id = LightXML.content(LightXML.find_element(pd, "Id"))
    o.message = LightXML.content(LightXML.find_element(pd, "Message"))
    o.senderFault = LightXML.content(LightXML.find_element(pd, "SenderFault"))
end

export ChangeMessageVisibilityBatchResultErrorEntryType

type ChangeMessageVisibilityResponseBatchType
	changeMessageVisibilityBatchResultEntrySet::Union{Vector{ChangeMessageVisibilityBatchResultEntryType}, Void}
	changeMessageVisibilityBatchResultErrorEntrySet::Union{Vector{ChangeMessageVisibilityBatchResultErrorEntryType}, Void}

    ChangeMessageVisibilityResponseBatchType(; changeMessageVisibilityBatchResultEntrySet=nothing, changeMessageVisibilityBatchResultErrorEntrySet=nothing) =
         new(changeMessageVisibilityBatchResultEntrySet, changeMessageVisibilityBatchResultErrorEntrySet)
end

function ChangeMessageVisibilityResponseBatchType(pd::LightXML.XMLElement)
    o = ChangeMessageVisibilityResponseBatchType()
    o.changeMessageVisibilityBatchResultEntrySet = AWS.@parse_vector(AWS.SQS.ChangeMessageVisibilityBatchResultEntryType, LightXML.get_elements_by_tagname(pd, "ChangeMessageVisibilityBatchResultEntry"))
    o.changeMessageVisibilityBatchResultErrorEntrySet = AWS.@parse_vector(AWS.SQS.ChangeMessageVisibilityBatchResultErrorEntryType, LightXML.get_elements_by_tagname(pd, "ChangeMessageVisibilityBatchResultErrorEntry"))
    o
end

export ChangeMessageVisibilityResponseBatchType

type ListDeadLetterSourceQueuesType
	queueUrl::Union{ASCIIString, Void}

	ListDeadLetterSourceQueuesType(; queueUrl=nothing) =
		new(queueUrl)
end

export ListDeadLetterSourceQueuesType

type ListDeadLetterSourceQueuesResultType
	queueUrls::Union{Vector{ASCIIString}, Void}

	ListDeadLetterSourceQueuesResultType(; queueUrls=nothing) =
		new(queueUrls)
end

function ListDeadLetterSourceQueuesResultType(pd::LightXML.XMLElement)
    o = ListDeadLetterSourceQueuesResultType()
    o.queueUrlSet = ASCIIString[LightXML.content(url) for url in LightXML.get_elements_by_tagname(LightXML.find_element(pd, "ListDeadLetterSourceQueuesResult"), "QueueUrl")]
end

export ListDeadLetterSourceQueuesResultType

type ListDeadLetterSourceQueuesResponseType
	requestId::Union{ASCIIString, Void}
	listDeadLetterSourceQueuesResultType::Union{ListDeadLetterSourceQueuesResultType, Void}

	ListDeadLetterSourceQueuesResponseType(; requestId=nothing, listDeadLetterSourceQueuesResultType=nothing) =
		new(requestId, listDeadLetterSourceQueuesResultType)
end

function ListDeadLetterSourceQueuesResponseType(pd::LightXML.XMLElement)
    o = ListDeadLetterSourceQueuesResponseType()
	o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
    o.listDeadLetterSourceQueuesResultType = LightXML.find_element(LightXML.find_element(pd, "ListDeadLetterSourceQueuesResult"), "QueueUrl") != nothing ? ListDeadLetterSourceQueuesResultType(LightXML.find_element(LightXML.find_element(pd, "ListDeadLetterSourceQueuesResult"), "QueueUrl")) : nothing
end

export ListDeadLetterSourceQueuesResponseType

type PurgeQueueType
	queueUrl::Union{ASCIIString, Void}

	PurgeQueueType(; queueUrl=nothing) =
		new(queueUrl)
end

export PurgeQueueType

type PurgeQueueResponseType
	requestId::Union{ASCIIString, Void}

	PurgeQueueResponseType(; requestId=nothing) =
		new(requestId)
end

function PurgeQueueResponseType(pd::LightXML.XMLElement)
    o = PurgeQueueResponseType()
	o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
end

export PurgeQueueResponseType

#=
type ActionAccountType
	aWSAccountId::Union{ASCIIString, Void}
	actionName::Union{ASCIIString, Void}

	ActionAccountType(; aWSAccountId=nothing, actionName=nothing) =
		new(aWSAccountId, actionName)
end

export ActionAccountType
=#

type AddPermissionType
	queueUrl::Union{ASCIIString, Void}
	label::Union{ASCIIString, Void}
	aWSAccountIdSet::Union{Vector{ASCIIString}, Void}
	actionNameSet::Union{Vector{ASCIIString}, Void}
	## actionAccountSet::Union{Vector{ActionAccountType}, Void}

	AddPermissionType(; queueUrl=nothing, label=nothing, aWSAccountIdSet=nothing, actionNameSet=nothing) =
		new(queueUrl, label, aWSAccountIdSet, actionNameSet)
end

export AddPermissionType

type AddPermissionResponseType
	requestId::Union{ASCIIString, Void}

	AddPermissionResponseType(; requestId=nothing) =
		new(requestId)
end

function AddPermissionResponseType(pd::LightXML.XMLElement)
    o = AddPermissionResponseType()

	o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
end

export AddPermissionResponseType

type RemovePermissionType
	queueUrl::Union{ASCIIString, Void}
	label::Union{ASCIIString, Void}

	RemovePermissionType(; queueUrl=nothing, label=nothing) =
		new(queueUrl, label)
end

export RemovePermissionType

type RemovePermissionResponseType
	requestId::Union{ASCIIString, Void}

	RemovePermissionResponseType(; requestId=nothing) =
		new(requestId)
end

function RemovePermissionResponseType(pd::LightXML.XMLElement)
    o = RemovePermissionResponseType()

	o.requestId = LightXML.content(LightXML.find_element(LightXML.find_element(pd, "ResponseMetadata"), "RequestId"))
end

export RemovePermissionResponseType

ext: jl


text:
using ..Serde: GDPayloadSerde, GDStaticPayloadSerde

"""
    GDConfig{T <: Unsigned}(
        base::BaseConfig,
        chunksize::Int,
        fingerprint::Function,
        msbsize::T,
        store_host::String,
        store_port::Int,
        is_client::Bool
    ) <: Configuration

Compress the payload by using a `GD Store`, producing a generally deduplicated
`GDFile` which are exchanged between the clients and the server. This
configuration instanciates a [GDPayloadSerde](@ref) and is making use of the
[GD.jl](https://xiorcale.github.io/GD.jl/) library to handle the generalized
deduplication logic.
"""
struct GDConfig{T <: Unsigned} <: Configuration
    base::BaseConfig

    payload_serde::GDPayloadSerde

    chunksize::Int
    fingerprint::Function
    msbsize::T

    GDConfig{T}(
        base::BaseConfig,
        chunksize::Int,
        fingerprint::Function,
        msbsize::T,
        store_host::String,
        store_port::Int,
        is_client::Bool
    ) where T <: Unsigned = new(
        base,
        GDPayloadSerde{T}(chunksize, fingerprint, msbsize, store_host, store_port, is_client),
        chunksize,
        fingerprint,
        msbsize
    )
end

"""
    GDStaticConfig(base, chunksize, fingerprint, msbsize, host, port, is_client)

Compresses the payload by using a `GD Store`, producing a generally deduplicated
`GDFile` which are exchanged between the clients and the server. This
configuration is making use of the GD.jl library to handle the GD logic
(https://github.com/xiorcale/GD.jl).
"""
struct GDStaticConfig{T <: Unsigned} <: Configuration
    base::BaseConfig

    payload_serde::GDStaticPayloadSerde

    chunksize::Int
    fingerprint::Function
    msbsize::T

    GDStaticConfig{T}(
        base::BaseConfig,
        chunksize::Int,
        fingerprint::Function,
        msbsize::T,
        store_host::String,
        store_port::Int,
        is_client::Bool
    ) where T <: Unsigned = new(
        base,
        GDStaticPayloadSerde{T}(chunksize, fingerprint, msbsize, store_host, store_port, is_client),
        chunksize,
        fingerprint,
        msbsize
    )
end


text:
abstract type AbstractProblem end

include("problems/search_problem.jl")


text:
module MiniCheetahRobot

using RigidBodyDynamics
using RigidBodyDynamics.Contact

packagepath() = joinpath(@__DIR__, "..", "deps")
urdfpath() = joinpath(packagepath(), "cheetah_description", "mini_cheetah.urdf")

function default_contact_model()
    SoftContactModel(hunt_crossley_hertz(k = 500e3), ViscoelasticCoulombModel(0.8, 20e3, 100.))
end

function mechanism(::Type{T} = Float64;
                   floating = true,
                   contactmodel = default_contact_model(),
                   remove_fixed_tree_joints = false,
                   add_flat_ground = false) where {T}
    mechanism = RigidBodyDynamics.parse_urdf(urdfpath(); scalar_type = T,
                floating = floating, remove_fixed_tree_joints = remove_fixed_tree_joints)

    if contactmodel != nothing
        for leg in (:FR, :FL, :RR, :RL)
            foot = findbody(mechanism, "$(string(leg))_foot")
            frame = default_frame(foot)
            radius = 0.015

            # bottom of foot -- in foot frame, positive x
            add_contact_point!(foot, ContactPoint(Point3D(frame, radius, 0, 0), contactmodel))
        end
    end

    if add_flat_ground
        frame = root_frame(mechanism)
        ground = HalfSpace3D(Point3D(frame, 0., 0., 0.), FreeVector3D(frame, 0., 0., 1.))
        add_environment_primitive!(mechanism, ground)
    end

    remove_fixed_tree_joints && remove_fixed_tree_joints!(mechanism)

    return mechanism
end

function setnominal!(cheetah_state::MechanismState)
    mechanism = cheetah_state.mechanism
    zero!(cheetah_state)

    # Give the legs their natural bend
    hip_pitch = -0.8
    knee_pitch = -1.5
    for leg in (:FR, :FL, :RR, :RL)
        hip = findjoint(mechanism, "$(string(leg))_thigh_joint")
        knee = findjoint(mechanism, "$(string(leg))_calf_joint")
        set_configuration!(cheetah_state, hip, hip_pitch)
        set_configuration!(cheetah_state, knee, knee_pitch)
    end

    # Lift the floating base joint 0.30 off the ground
    floating_joint = first(out_joints(root_body(mechanism), mechanism))
    set_configuration!(cheetah_state, floating_joint, [1; 0; 0; 0; 0; 0; 0.30])
    return cheetah_state
end

function __init__()
    if !isfile(urdfpath())
        error("Could not find $(urdfpath()). Please run `import Pkg; Pkg.build(\"MiniCheetahRobot\")`.")
    end
end

end # module


text:
module TestPolyModule

using Test

using JuMP
using PolyJuMP

include("testpolymodule.jl")

function test_PolyModule()
    m = Model()
    # Triggers the creation of polydata
    @test PolyJuMP.getpolydata(m).nonnegpoly_default === nothing
    @test_throws ErrorException PolyJuMP.getdefault(m, PolyJuMP.NonNegPoly)
    @test PolyJuMP.getpolydata(m).posdefpolymatrix_default === nothing
    @test_throws ErrorException PolyJuMP.getdefault(m, PolyJuMP.PosDefPolyMatrix)
    setpolymodule!(m, DummyPolyModule)
    @test PolyJuMP.getdefault(m, PolyJuMP.NonNegPoly) == DummyPolyModule.DummyNonNeg
    @test PolyJuMP.getdefault(m, PolyJuMP.PosDefPolyMatrix) == DummyPolyModule.DummyPosDefMatrix
    PolyJuMP.setdefault!(m, PolyJuMP.PosDefPolyMatrix, DummyPolyModule.DummyNonNeg)
    @test PolyJuMP.getdefault(m, PolyJuMP.PosDefPolyMatrix) == DummyPolyModule.DummyNonNeg
end

function runtests()
    for name in names(@__MODULE__; all = true)
        if startswith("$name", "test_")
            @testset "$(name)" begin
                getfield(@__MODULE__, name)()
            end
        end
    end
end

end

TestPolyModule.runtests()


text:
AcousticCircleParticle{T} = Particle{T,2,Acoustic{T,2},Sphere{T,2}}

"""
    t_matrix(Particle{T,2,Acoustic{T,2},Sphere{T,2}}, Acoustic{T,2}, ω, order)

The T-matrix for a 2D circlular acoustic particle in a 2D acoustic medium.
"""
function t_matrix(p::Particle{T,2,Acoustic{T,2},Sphere{T,2}}, outer_medium::Acoustic{T,2}, ω::T, basis_order::Integer)::Diagonal{Complex{T}} where T <: AbstractFloat

    # Check for material properties that don't make sense or haven't been implemented
    check_material(p, outer_medium)

    "Returns a ratio used in multiple scattering which reflects the material properties of the particles"
    function Zn(m::Integer)::Complex{T}
        m = T(abs(m))
        ak = outer_radius(p)*ω/outer_medium.c

        # set the scattering strength and type
        if isinf(p.medium.c) || isinf(p.medium.ρ)
            numer = diffbesselj(m, ak)
            denom = diffhankelh1(m, ak)
        elseif iszero(outer_medium.ρ)
            numer = diffbesselj(m, ak)
            denom = diffhankelh1(m, ak)
        elseif iszero(p.medium.ρ) || iszero(p.medium.c)
            numer = besselj(m, ak)
            denom = hankelh1(m, ak)
        else
            q = impedance(p.medium)/impedance(outer_medium) # Impedance ratio
            γ = outer_medium.c/p.medium.c #speed ratio
            numer = q * diffbesselj(m, ak) * besselj(m, γ * ak) - besselj(m, ak)*diffbesselj(m, γ * ak)
            denom = q * diffhankelh1(m, ak) * besselj(m, γ * ak) - hankelh1(m, ak)*diffbesselj(m, γ * ak)
        end

        return numer / denom
    end

    # Get Zns for positive m
    Zns = map(Zn,0:basis_order)

    return - Diagonal(vcat(reverse(Zns), Zns[2:end]))
end


text:
#########
#File: c:\Users\digan\Dropbox\Dynamic_Networks\repos\ScoreDrivenExponentialRandomGraphs\_research\analysis_for_paper_revision\add_confidence_intervals\load_estimates_and_check_parametric_bootstrap_conf_intervals.jl
#Project: c:\Users\digan\Dropbox\Dynamic_Networks\repos\ScoreDrivenExponentialRandomGraphs\_research\analysis_for_paper_revision\add_confidence_intervals
#Created Date: Saturday April 24th 2021
#Author: Domenico Di Gangi,  <digangidomenico@gmail.com>
#-----
#Last Modified: Tuesday April 27th 2021 10:57:43 am
#Modified By:  Domenico Di Gangi
#-----
#Description:
#-----
########

#region import and models
#%%
using DrWatson
@quickactivate "ScoreDrivenExponentialRandomGraphs"

using ProjUtilities
using DataFrames
using ScoreDrivenERGM
import ScoreDrivenERGM:DynNets, Utilities, StaticNets, Scalings
using PyPlot
pygui(true)
#endregion

using Distributed

nWorkers = 5
addprocs(nWorkers - nprocs())
@everywhere begin
    import ScoreDrivenERGM:DynNets, Utilities, StaticNets, Scalings
end

## check coverage of confidence intervals in static ergm ~ edges + mutual
model = StaticNets.ErgmDirBin0Rec0()
@everywhere begin
N=500
Ldgp = Scalings.n_pox_dir_links(N)/4
Rdgp = Scalings.n_pox_pairs(N)/4-100
parDgp = StaticNets.estimate(model, Ldgp, Rdgp, N)
quantilesVals = [0.025, 0.975]
end

# coverFlags = StaticNets.get_coverage_conf_int_par_boot_ergm(model, N, parDgp, quantilesVals, nSampleDgp = 100, nSampleBands=500)

# @show mean(coverFlags, dims=2)

function get_coverage_conf_int_par_boot_ergm_parallel(model, N, parDgp, quantilesVals; nSampleDgp=100, nSampleBands = 100, estimates=nothing)

    # sample from dgp
    if isnothing(estimates)
        matsSample = StaticNets.sample_ergm(model, N, parDgp, nSampleDgp)
        estimates = reduce(hcat,[StaticNets.estimate(model, matsSample[:,:,n]) for n in 1:nSample])
    end

    coverFlags =falses(size(estimates))

    coverFlags = @sync @distributed  hcat for n in 1:nSampleDgp
        confInt = StaticNets.get_conf_int_ergm_par_boot(model, N, estimates[:, n], quantilesVals; nSample=nSampleBands)

        [StaticNets.is_between(parDgp[p], confInt[p,:]) for p in 1:model.nErgmPar]
    end

    return coverFlags
end

# coverFlags = get_coverage_conf_int_par_boot_ergm_parallel(model, N, parDgp, quantilesVals)

# @show mean(coverFlags, dims=2)

@elapsed df = collect_results( datadir("sims", "dgp&FIl_est"))
df["modelTag"] = string.(df["model"])

T = 300
N = 100
nSample = 50
indQuant = 1
modelTag = string(DynNets.SdErgmDirBin0Rec0_mle(scoreScalingType = "FISH_D"))

dgpSetting = DynNets.list_example_dgp_settings(DynNets.SdErgmDirBin0Rec0_mle()).dgpSetARlowlow

# # visual inspection of filter, dgp and conf bands
res = filter([:modelTag, :T, :N, :dgpSettings, :nSample, ] => (mTag,t,n, d, s) -> all((mTag==modelTag, t==T, n==N, d == dgpSetting, s == nSample)), df)[1,:]

model = res.model
using Statistics
n = 2

# coverFlags = @sync @distributed  hcat
nQuant = length(quantilesVals)
confBandsT = zeros(model.staticModel.nErgmPar, T, nSample, nQuant)
for t = 1:T
parDgp_t = res.allParDgpT[:,t,n]
parEst_t = res.allfVecT_filt[:,t,n]
confBandsT[:,t , n,:] = mapslices((x -> quantile(x, quantilesVals)), StaticNets.get_par_boot_ergm_distrib(model.staticModel, parEst_t, N; nSample = 100), dims=2)

end

mat_sample = StaticNets.sample_ergm(model, N, parEst, nSample)

p=2
plot(confBandsT[p,:,n,:])
plot(res.allParDgpT[p,:,n])
plot(res.allfVecT_filt[p,:,n])

#%%
## Sequence for rescaled Par Bootstrap confidence intervals for SDERGM

#Estimate SD on data and filter

# Obtain Distribution of observations from the filtered path, sampling each ergm_t using the filtered parameters nSample times

# filter each

max_stars_repo_name: domenicodigangi/SDERGM

max_issues_repo_name: domenicodigangi/SDERGM

max_forks_repo_name: domenicodigangi/SDERGM


text:
################################################# FILE DESCRIPTION #########################################################

# This file contains tests for the Mutation API

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

@testset "Mutation Addvertex" begin
   g = completegraph(10)

   # Set vertex properties
   setvprop!(g, :, 1:10, :p1)
   setvprop!(g, :, 1:10, :p2)

   # Set edge properties
   seteprop!(g, :, 1:90, :p1)
   seteprop!(g, :, 1:90, :p2)

   g1 = deepcopy(g)
   # Addvertex without labels
   # Check for NA row
   # Check for type of LabelMap
   @test addvertex!(g1) == 11
   @test isequal(getvprop(g1, 11, :p1), NA)
   @test isequal(getvprop(g1, 11, :p2), NA)
   @test isa(g1.lmap, IdentityLM)

   g2 = deepcopy(g)
   # Addvertex with label
   # Check for NA row
   # Check for type of LabelMap
   @test addvertex!(g2, 15) == 11
   @test isequal(getvprop(g2, 11, :p1), NA)
   @test isequal(getvprop(g2, 11, :p2), NA)
   @test isa(g2.lmap, DictLM)

   g3 = deepcopy(g)
   # Addvertex with existing label
   # Check for no new row
   # Check for type of LabelMap
   @test addvertex!(g3, 10) == 10
   @test size(g3.vdata) == (10,2)
   @test isa(g3.lmap, IdentityLM)

   g4 = deepcopy(g)
   g4 + 11
   @test g4 == g1

   g5 = deepcopy(g)
   g5 + 15
   @test g5 == g2
end

@testset "Mutation Addedge" begin
   g = completegraph(10)

   # Set vertex properties
   setvprop!(g, :, 1:10, :p1)
   setvprop!(g, :, 1:10, :p2)

   # Set edge properties
   seteprop!(g, :, 1:90, :p1)
   seteprop!(g, :, 1:90, :p2)

   g1 = deepcopy(g)
   # Addedge 1=>1
   # Check for NA row at the END.
   # Check for mapping
   @test addedge!(g1, 1=>1) == true
   @test g1.indxs[1=>1] == 91

   g2 = deepcopy(g)
   g2[1] = 1
   @test g2 == g1

   g3 = deepcopy(g)
   g3[1] = [1]
   g3[5] = [5]
   g3[10] = [10]
   @test g3.indxs[[1=>1, 5=>5, 10=>10]] == [91, 92, 93]
end

@testset "Mutation Rmvertex" begin
   g = completegraph(10)
   setlabel!(g, collect(1:10))

   # Set vertex properties
   setvprop!(g, :, 1:10, :p1)
   setvprop!(g, :, 1:10, :p2)

   # Set edge properties
   seteprop!(g, :, 1:90, :p1)
   seteprop!(g, :, 1:90, :p2)

   g1 = deepcopy(g)
   # Remove vertex 10
   # Check for size of vdata
   # Check for edata entries
   rmvertex!(g1, 10)
   @test size(g1.vdata) == (9, 2)
   @test size(g1.edata) == (72, 2)

   g2 = deepcopy(g)
   g2 - 10
   @test g2 == g1

   g3 = deepcopy(g)
   # Remove vertices 5, 8
   # Check for size of vdata
   # Check for edata entries
   rmvertex!(g3, [5,8])
   @test nv(g3) == 8
   @test size(vdata(g3)) == (8,2)
   @test size(edata(g3)) == (56,2)

   g4 = deepcopy(g)
   g4 - [5,8]
   @test g4 == g3
end

@testset "Mutation Rmedge" begin
   g = Graph(completeindxs(10))
   # Set edge properties
   seteprop!(g, :, 1:90, :p1)
   seteprop!(g, :, 1:90, :p2)

   g1 = deepcopy(g)
   # Remove edge 1=>2
   # Check for size of edata
   # Check indexing table
   rmedge!(g1, 1=>2)
   @test size(g1.edata) == (89, 2)
   @test g1.indxs.nzval == collect(1:89)
   @test hasedge(g1, 1=>2) == false

   g2 = deepcopy(g)
   # Remove edges 1=>2, 5=>4, 10=>9
   # Check for size of edata
   # Check indexing table
   rmedge!(g2, 1=>2)
   rmedge!(g2, 5=>4)
   rmedge!(g2, 10=>9)
   @test size(g2.edata) == (87,2)
   @test g2.indxs.nzval == collect(1:87)
   @test hasedge(g1, 1=>2) == false
   @test hasedge(g2, 5=>4) == false
   @test hasedge(g2, 10=>9) == false
end


text:
"""
    struct Filter
        name::String
        value::String
    end

Specify a filter to be applied to the query.

Examples :

    BioMart.Filter(ensembl_gene_id = "ENSG00000146648")
    BioMart.Filter("ensembl_gene_id", "ENSG00000146648")
"""
struct Filter
    name::String
    value::String
end

Filter(name::Symbol, value) = Filter(string(name), value)
Filter(name::String, value::Int) = Filter(name, string(value))
Filter(name::String, values::Vector) =  Filter(name, join(values,','))

function Filter(;args...)
    @assert length(args) == 1
    pair = first(args)
    Filter(pair.first, pair.second)
end

function Base.push!(query::Query, f::Filter)
    xf = new_child(query.dataset, "Filter")
    set_attributes(xf, name = f.name, value = f.value)
end

struct Filters
    filters::Vector{Filter}
end
"""
    BioMart.Filters(;args...)

Specify a list of filters to be applied to the query.

Example :

    BioMart.Filters(
        ensembl_gene_id = "ENSG00000146648",
        chromosome_name = "7"
    )
"""
function Filters(;args...)
    Filters([Filter(pair.first, pair.second) for pair in args])
end

Base.push!(query::Query, f::Filters)  = push!.(Ref(query), f.filters)

Base.push!(query::Query, i::Interval) = push!(query, convert(Filters, i))

Base.convert(::Type{Filters}, i::T)  where T <: Interval = Filters([
    Filter("start", i.first),
    Filter("end", i.last),
    Filter("chromosome_name", i.seqname),
])


text:
export AbstractTurnBuffer, buffers, RTSA, isfull, consecutive_view

"""
    AbstractTurnBuffer{names, types} <: AbstractArray{NamedTuple{names, types}, 1}

`AbstractTurnBuffer` is supertype of a collection of buffers to store the interactions
between agents and environments. It is a subtype of `AbstractArray{NamedTuple{names, types}, 1}` where `names` specifies which fields are to store and `types` is the coresponding types of the `names`.

| Required Methods| Brief Description |
|:----------------|:------------------|
| `Base.push!(b::AbstractTurnBuffer{names, types}, s[, a, r, d, s′, a′])` | Push a turn info into the buffer. According to different `names` and `types` of the buffer `b`, it may accept different number of arguments |
| `isfull(b)` | Check whether the buffer is full or not |
| `Base.length(b)` | Return the length of buffer |
| `Base.getindex(b::AbstractTurnBuffer{names, types})` | Return a turn of type `NamedTuple{names, types}` |
| `Base.empty!(b)` | Reset the buffer |
| **Optional Methods** | |
| `Base.size(b)` | Return `(length(b),)` by default |
| `Base.isempty(b)` | Check whether the buffer is empty or not. Return `length(b) == 0` by default |
| `Base.lastindex(b)` | Return `length(b)` by default |
"""
abstract type AbstractTurnBuffer{names,types} <: AbstractArray{NamedTuple{names,types},1} end

buffers(b::AbstractTurnBuffer) = getfield(b, :buffers)

Base.size(b::AbstractTurnBuffer) = (length(b),)
Base.lastindex(b::AbstractTurnBuffer) = length(b)
Base.isempty(b::AbstractTurnBuffer) = all(isempty(x) for x in buffers(b))
Base.empty!(b::AbstractTurnBuffer) =
    for x in buffers(b)
        empty!(x)
    end
Base.getindex(b::AbstractTurnBuffer{names,types}, i::Int) where {names,types} =
    NamedTuple{names,types}(Tuple(x[i] for x in buffers(b)))
isfull(b::AbstractTurnBuffer) = all(isfull(x) for x in buffers(b))

function Base.push!(b::AbstractTurnBuffer; kw...)
    for (k, v) in kw
        hasproperty(buffers(b), k) && push!(getproperty(buffers(b), k), v)
    end
end

function Base.push!(b::AbstractTurnBuffer, experience::Pair{<:Observation})
    obs, a = experience
    push!(
        b;
        state = get_state(obs),
        reward = get_reward(obs),
        terminal = get_terminal(obs),
        action = a,
        obs.meta...,
    )
end

#####
# RTSA (Reward, Terminals, State, Action)
#####

state(b::AbstractTurnBuffer) = buffers(b).state
action(b::AbstractTurnBuffer) = buffers(b).action
reward(b::AbstractTurnBuffer) = buffers(b).reward
terminal(b::AbstractTurnBuffer) = buffers(b).terminal

const RTSA = (:reward, :terminal, :state, :action)

Base.getindex(b::AbstractTurnBuffer{RTSA,types}, i::Int) where {types} =
    (
     state = select_frame(state(b), i),
     action = select_frame(action(b), i),
     reward = select_frame(reward(b), i+1),
     terminal = select_frame(terminal(b), i+1),
     next_state = select_frame(state(b), i+1),
     next_action = select_frame(action(b), i+1),
    )

#####
# PRTSA (Prioritized, Reward, Terminal, State, Action)
#####

const PRTSA = (:priority, :reward, :terminal, :state, :action)

priority(b::AbstractTurnBuffer) = buffers(b).priority

Base.getindex(b::AbstractTurnBuffer{PRTSA,types}, i::Int) where {types} =
    (
     state = select_frame(state(b), i),
     action = select_frame(action(b), i),
     reward = select_frame(reward(b), i+1),
     terminal = select_frame(terminal(b), i+1),
     next_state = select_frame(state(b), i+1),
     next_action = select_frame(action(b), i+1),
     priority = select_frame(priority(b), i+1),
    )

function consecutive_view(b::AbstractTurnBuffer, inds, n, stack_size)
    next_inds = inds .+ 1

    (
     states = consecutive_view(state(b), inds, n, stack_size),
     actions = consecutive_view(action(b), inds, n),
     rewards = consecutive_view(reward(b), next_inds, n),
     terminals = consecutive_view(terminal(b), next_inds, n),
     next_states = consecutive_view(state(b), next_inds, n, stack_size),
     next_actions = consecutive_view(action(b), next_inds, n),
    )
end

function extract_SARTS(batch, γ)
    n_step, batch_size = size(batch.terminals)
    states = selectdim(batch.states, ndims(batch.states) - 1, 1)
    actions = selectdim(batch.actions, ndims(batch.actions) - 1, 1)
    next_states = selectdim(batch.next_states, ndims(batch.next_states) - 1, n_step)

    rewards, terminals = zeros(Float32, batch_size), fill(false, batch_size)

    # make sure that we only consider experiences in current episode
    for i = 1:batch_size
        t = findfirst(view(batch.terminals, :, i))

        if isnothing(t)
            terminals[i] = false
            rewards[i] = discount_rewards_reduced(view(batch.rewards, :, i), γ)
        else
            terminals[i] = true
            rewards[i] = discount_rewards_reduced(view(batch.rewards, 1:t, i), γ)
        end
    end

    (
        states=states,
        actions=actions,
        rewards=rewards,
        terminals=terminals,
        next_states=next_states
    )
end

Base.length(b::AbstractTurnBuffer) = max(0, length(terminal(b)) - 1)


text:
using Test

@testset "dummytest" begin

    @test 1.0+1.0 == 2.0
    @test 2.0+2.0 == 4.0
    @test 3.0+3.0 == 6.0
    # @test 4.0+4.0 == 8.0

end

max_stars_repo_name: sparktseung/JuliaLRMoE

max_issues_repo_name: sparktseung/JuliaLRMoE

max_forks_repo_name: sparktseung/JuliaLRMoE


text:
using CLSolvers
using DifferentialEquations, StochasticDiffEq
using Random
using Statistics
using LaTeXStrings

# In this file the true solutions used in the paper are stored as
# dictionares
include("Scro_Data.jl")

###############################################
###############################################
# SETTING UP THE CONTOUR                      #
###############################################
###############################################

## SELECT THE MODEL
p = AHO_Param(1,1,24)
#p = NonEquil_AHO_Param(1,1,1,1,1,1,0,1)

######################
## SELECT CONTOUR  ###
######################
#contour = EucledianContour(1.0)
#contour = NonEquilTiltedSchwingerKeldyshContour(1.0,0.0001)
#contour = NonEquilSchwingerKeldyshContour(0.5,0.0)
contour = SchwingerKeldyshContour(1.0,0.5,0.0,0.0)
#contour = SchwingerKeldyshContourRounded1(1.0,0.6,0.5,0.005,0.0025)
#contour = SchwingerKeldyshContourRounded2(1.0,0.6,0.25,0.1,0.025,0.05)
#contour = SchwingerKeldyshContourRounded3(1.0,0.6,0.25,0.4,0.1,0.15,0.02)

#########################
### DISCRETIZE CONTOUR ##
#########################
# Comment out the lines not used below if this file is used as
# a runnable script

# Set total number of points in contour
t_steps = 64

# Let the library choose how the contour should be distributed
# (Not optimal for non standard contours)
discContour = discretizeContour(contour,t_steps)

# script to distribute equally in a tilted contour
begin
    L1 = CLSolvers.L1(contour)/CLSolvers.T(contour)
    L2 = CLSolvers.L2(contour)/CLSolvers.T(contour)

    t_step1 = ceil(Int64,t_steps*L1)
    t_step2 = floor(Int64,t_steps*L2)
    discContour = discretizeContour(contour,t_step1,t_step2,0)
end

# Possible to specify number of points in each of the contour parts
# Some examples:
#       - Equal number of points in FW, BW and Eucl part.
discContour = discretizeContour(contour,t_steps/3,t_steps/3,t_steps/3)
#       - Twice as many points along the Eucl. part as the FW and BW parts.
discContour = discretizeContour(contour,t_steps/4,t_steps/4,2*t_steps/4)
#       - Twice as many points along the FW and BW parts as the Eucl. part.
discContour = discretizeContour(contour,2t_steps/5,2t_steps/5,t_steps/5)

# Get usefull parameters for simulation and plotting
begin
    a = getContourDistances(discContour, contour) # Points separation
    CC = getContour(discContour, contour)         # Contour points (Complex numbers)
    tp = CLSolvers.spread_timepoints(discContour,contour) # Parameterization points
end

# Plot contour to be safe
fig = CLSolvers.scatter(CC,legend=false)
#CLSolvers.scatter(a)

################################
## INITIAL CONDITION ###########
################################
begin
RANDOM_INIT = true

if RANDOM_INIT
    rng = MersenneTwister(12345);
    y0 = vcat(randn(rng, Float64, t_steps),zeros(Float64,t_steps))
else
    y0 = zeros(Float64,2*t_steps)
end
end

######################
# RUN THE SIMULATION #
######################
args = (N_Tr = 50, θ = 0.6, dt = 1e-4, tol = 5e-2, dtmax = 1e-3, tspan=(0.0,10.0), adaptive=true)
begin
params = getParamArray(p,a)
sde_a, sde_b, _ = CLSolvers.get_sde_funcs(p)

ff = SDEFunction(sde_a,sde_b)
prob_sde2 = SDEProblem(ff,sde_b,y0,args.tspan,params)

function prob_func(prob,i,repeat)
    println("Starting ensamble: ",i)
    remake(prob,u0=vcat(randn(rng, Float64, t_steps),zeros(Float64,t_steps)))
end

if RANDOM_INIT
    ensemble_prob = EnsembleProblem(prob_sde2,prob_func=prob_func)
else
    ensemble_prob = EnsembleProblem(prob_sde2)
end

@time sol = solve(ensemble_prob,ImplicitEM(theta=args.θ, symplectic=false),
            EnsembleThreads(), trajectories=args.N_Tr,
            progress = true, saveat = 0.01, save_start = false,
            dtmax=args.dtmax, dt=args.dt,
            adaptive=args.adaptive,
            abstol=args.tol,reltol=args.tol,maxiter=10^6)
end

#######  Check that simulation completed without errors
#######  removes warning trajectories if remove_warning_tr=true
check_errors(sol,remove_warning_tr=true)

##########################
## CALCULATE OBSERVABLES #
##########################
avg_Re, avg_Im, avg2_Re, avg2_Im, corr0t_Re, corr0t_Im, Gpm_Re, Gpm_Im, Gmp_Re, Gmp_Im = get_statistics(sol, thermal=32)
# (thermal argument should correspond to the last point in the real-time axes to use the Gpm and Gmp correlators)

#######################
## Plotting functions #
#######################
# The properties of the plot can be changed in the src/plot_observables.jl file
# ex. you can set the legend position here

####
# Thermal

# <ϕ(0)ϕ(t)> correlators
plot_realtime_corr0t(corr0t_Re, corr0t_Im, CC; true_solution=dfScroSolMinkBeta1)
plot_full_corr0t(corr0t_Re, corr0t_Im, CC; true_solution=dfScroSolMinkBeta1)

# <ϕ_+(0)ϕ_-(t)> and <ϕ_-(0)ϕ_+(t)> correlators
plot_Gpm_Gmp(Gpm_Re, Gpm_Im, Gmp_Re, Gmp_Im, CC; true_solution=dfScroSolMinkBeta1)

# Plot corr0t along the Eucledian part of the contour
plot_eucledian_corr0t(corr0t_Re, corr0t_Im, CC[1:end-1]; true_solution=dfScroSolEuclBeta1)

# plot <x> and <x^2>
plot_avg_avg2(avg_Re,avg_Im,avg2_Re,avg2_Im,tp[1:end-1]; true_solution=dfScroSolMinkBeta1)

#####
# Non-Equilibrium

# <ϕ(0)ϕ(t)>
plot_full_corr0t(corr0t_Re, corr0t_Im, CC; true_solution=dfScroSolMinkNonEquil)

# plot <x> and <x^2>
plot_avg_avg2_nonEquil(avg_Re,avg_Im,avg2_Re,avg2_Im,CC; true_solution=dfScroSolMinkNonEquil)

######################
## Corrections #######
######################
SS_Re, SS2_Re, SS_Im, SS2_Im = get_corrections(sol,params,args)
plot_corrections(SS_Re, SS2_Re, SS_Im, SS2_Im, avg2_Re, avg2_Im, tp; true_solution=dfScroSolMinkBeta1["avg2Re"])

#################################
### SAVE/LOAD CONFIGS AND SETUP #
#################################

filename = "filename1" # Set the filename to the file be saved/loaded

# Save solution + all information needed to continue simulating or plotting observables
begin
    CLSolvers.save_sol(string("results/",filename,".jld"),sol, p, contour, a, CC, tp)
end

# Load solution etc.
sol, p, contour, a, CC, tp = load_sol(string("results/",filename,".jld"))


text:
###############################################################################
# BUILD TMLE FROM .TOML

function buildmodels(config)
    models = Dict()
    for (modelname, hyperparams) in config
        if !(modelname in ("resampling", "measures"))
            modeltype = eval(Symbol(modelname))
            paramnames = Tuple(Symbol(x[1]) for x in hyperparams)
            counter = 1
            for paramvals in Base.Iterators.product(values(hyperparams)...)
                model = modeltype(;NamedTuple{paramnames}(paramvals)...)
                models[Symbol(modelname*"_$counter")] = model
                counter += 1
            end
        end
    end
    return models
end

function stack_from_config(config::Dict, metalearner; adaptive_cv=true)
    # Define the resampling strategy
    resampling = config["resampling"]
    resampling = eval(Symbol(resampling["type"]))(nfolds=resampling["nfolds"])
    if adaptive_cv
        resampling = AdaptiveCV(resampling)
    end

    # Define the internal cross validation measures to report
    measures = (haskey(config, "measures") && size(config["measures"], 1) > 0) ?
                    [getfield(MLJBase, Symbol(fn)) for fn in config["measures"]] :
                    nothing

    # Define the models library
    models = buildmodels(config)

    # Define the Stack
    Stack(;metalearner=metalearner, resampling=resampling, measures=measures, models...)
end

function estimator_from_toml(config::Dict, queries, target_type; adaptive_cv=true)
    # Parse estimator for the propensity score
    metalearner = LogisticClassifier(fit_intercept=false)
    if length(first(queries).case) > 1
        G = FullCategoricalJoint(stack_from_config(config["G"], metalearner, adaptive_cv=adaptive_cv))
    else
        G = stack_from_config(config["G"], metalearner, adaptive_cv=adaptive_cv)
    end

    # Parse estimator for the outcome regression
    if target_type == Real
        metalearner =  LinearRegressor(fit_intercept=false)
        Q̅ = stack_from_config(config["Qcont"], metalearner, adaptive_cv=adaptive_cv)
    elseif target_type == Bool
        metalearner = LogisticClassifier(fit_intercept=false)
        Q̅ = stack_from_config(config["Qcat"], metalearner, adaptive_cv=adaptive_cv)
    else
        throw(ArgumentError("The type of the outcomes: $target_type, should be either a Float or a Bool"))
    end

    threshold = haskey(config, "threshold") ? config["threshold"] : 0.005
    return TMLEstimator(Q̅, G, queries...; threshold=threshold)
end


text:
using Polyhedra
const polyhedra_test = joinpath(dirname(dirname(pathof(Polyhedra))), "test")

include(joinpath(polyhedra_test, "solvers.jl"))

const LIB = QHull.Library(lp_solver)

@testset "Volume" begin
    h = HalfSpace([1, 0, 0], 1) ∩ HalfSpace([0, 1, 0], 1) ∩ HalfSpace([0, 0, 1], 1) ∩
        HalfSpace([-1, 0, 1], 1) ∩ HalfSpace([0, -1, 0], 1) ∩ HalfSpace([0, 0, -1], 1)
    p = polyhedron(h, LIB)
    @test volume(p) ≈ 8
end

include(joinpath(polyhedra_test, "utils.jl"))
include(joinpath(polyhedra_test, "polyhedra.jl"))

exclude = [
    "jumpsimplex", "ex1", "infeasible", "nonfulldimensional",
    "simplex", "permutahedron", "board", "issue48", "empty",
    "orthantdecompose", "largedecompose", "recipe",
    # 1D not supported:
    "vhypercubetest1c", "vhypercubetest1u"
]

polyhedratest(LIB, exclude)


text:
"""
    TabularRL

This module was ported from an old version of this code base. This is only used for the variance experiments in the markov chaing `experiment/markov_chain_var.jl` and `parallel/markov_chain_variance.jl

"""

module TabularRL

using Lazy
import Base.getindex, Base.setindex!
# using ..GeneralValueFunction

export ValueFunction, Optimizer, update!, BatchTD, WISBatchTD, VTrace

abstract type ValueFunction end

"""
StateValueFunction(size)

# Arguments:
`size`: Integer, many integers, or tuple of integers determining the size of the Value table.
"""
mutable struct StateValueFunction <: ValueFunction
    values::Array{Float64}
    StateValueFunction(size) = new(zeros(size))
    StateValueFunction(size...) = new(zeros(size...))
end

@forward ValueFunction.values Base.getindex
@forward ValueFunction.values Base.setindex!

abstract type Optimizer end

"""
update!(value::ValueFunction, opt::Optimizer, ρ, s_t, s_tp1, reward, γ, terminal)

# Arguments:
`value::ValueFunction`:
`opt::Optimizer`:
`ρ`: Importance sampling ratios (Array of Floats)
`s_t`: States at time t
`s_tp1`: States at time t + 1
`reward`: cumulant or reward for value function
`γ`: discount factor
`terminal`: Determining termination of the episode (if applicable).
"""
function update!(value::ValueFunction, opt::Optimizer, ρ, s_t, s_tp1, reward, γ, terminal)
    throw(ErrorException("Implement update for $(typeof(opt))"))
end

function update!(value::ValueFunction, opt::Optimizer, ρ, s_t, s_tp1, reward, γ, terminal, a_t, a_tp1, policy)
    return update!(value, opt, ρ, s_t, s_tp1, reward, γ, terminal)
end

############
#
# WISTD - Batch
#
############
"""
WISBatchTD(α, batch_size)

# Arguments:
`α::Float64`: The step size used for learning
`batch_size::Integer`: The size of the batch for learning

Parameter struct for WISBatchTD

"""
mutable struct WISBatchTD <: Optimizer
    α::Float64
    batch_size::Integer
    α_mod::Float64
    WISBatchTD(α, batch_size) = new(α, batch_size, 1.0)
    WISBatchTD(α, batch_size, α_mod) = new(α, batch_size, α_mod)
end

function update!(value::StateValueFunction, opt::WISBatchTD, ρ, s_t, s_tp1, r, γ, terminal)
    batch_size = opt.batch_size
    α = opt.α*opt.α_mod
    δ = zeros(batch_size)
    γ_eff = γ .* (terminal.==false)
    δ = ρ.*(r + γ_eff.*value[s_tp1] - value[s_t])
    ρ_wis = sum(ρ)
    if ρ_wis != 0
        ρ_wis_inv = 1.0/ρ_wis
        for i = 1:batch_size
            value[s_t[i]] += α*ρ_wis_inv*δ[i]
        end
    end
end

"""
BatchTD(α, batch_size)

# Arguments:
`α::Float64`: The step size used for learning
`batch_size::Integer`: The size of the batch for learning
`α_mod::Float64`: The modifier to the step size (for WIS!)

Parameter struct for BatchTD
"""
mutable struct BatchTD <: Optimizer
    α::Float64
    batch_size::Integer
    α_mod::Float64
    avg::Bool
    BatchTD(α::Float64, batch_size::Integer) = new(α, batch_size, 1.0, false)
    BatchTD(α::Float64, batch_size::Integer, α_mod) = new(α, batch_size, α_mod, false)
    BatchTD(α::Float64, batch_size::Integer, α_mod, avg) = new(α, batch_size, α_mod, avg)
end

# mutable struct BatchTD <: Optimizer
#     α::Float64
#     batch_size::Integer
#     α_mod::Float64
#     BatchTD(α::Float64, batch_size::Integer) = new(α, batch_size, 1.0)
# end

function update!(value::StateValueFunction, opt::BatchTD, ρ, s_t, s_tp1, r, γ, terminal)
    batch_size = opt.batch_size
    α = opt.α*opt.α_mod
    if opt.avg
        α = α/length(ρ)
    end
    δ = zeros(batch_size)
    γ_eff = γ .* (terminal.==false)
    δ = ρ.*(r + γ_eff.*value[s_tp1] - value[s_t])
    for i = 1:batch_size
        value[s_t[i]] += (α)*δ[i]
    end
end

"""
VTrace(α, ρ_bar, batch_size)

# Arguments:
`α::Float64`: The step size used for learning
`ρ_bar::Float64`: The clipping parameter for importance sampling.
`batch_size::Integer`: The size of the batch for learning

Parameter struct for WISBatchTD
"""
mutable struct VTrace <: Optimizer
    α::Float64
    ρ_bar::Float64
    batch_size::Integer
    α_mod::Float64
    avg::Bool
    VTrace(α, ρ_bar, batch_size) = new(α, ρ_bar, batch_size, 1.0, false)
    VTrace(α, ρ_bar, batch_size, α_mod) = new(α, ρ_bar, batch_size, α_mod, false)
    VTrace(α, ρ_bar, batch_size, α_mod, avg) = new(α, ρ_bar, batch_size, α_mod, avg)
end

function update!(value::StateValueFunction, opt::VTrace, ρ, s_t, s_tp1, r, γ, terminal)
    # batch_size = length(terminal)
    batch_size = opt.batch_size
    α = opt.α*opt.α_mod
    if opt.avg
        α = α/length(ρ)
    end
    ρ_bar = opt.ρ_bar
    γ_eff = γ .* (terminal.==false)
    δ = zeros(batch_size)
    δ .= clamp.(ρ, 0, ρ_bar).*(r +γ_eff.*value[s_tp1] - value[s_t])
    for i = 1:batch_size
        value[s_t[i]] += (α)*δ[i]
    end
end

export QValueFunction, get_q_values, QOptimizer, Sarsa, ExpectedSarsa

mutable struct QValueFunction <: ValueFunction
    values::Array{Float64}
    QValueFunction(num_actions::Integer, size...) = new(zeros(num_actions, size...))
end

@forward QValueFunction.values getindex
@forward QValueFunction.values setindex!

get_q_values(q_value::QValueFunction, a::Integer, s...) = q_value[a, s...]
get_q_values(q_value::QValueFunction, a::Integer, s::Int64...) = q_value[a, s...]
get_q_values(q_value::QValueFunction, a::Integer, s::Array{Int64, 1}) = q_value[a, s...]
get_q_values(q_value::QValueFunction, a_vec::Array{Int64,1}, s_vec::Array{Int64, 1}) = [q_value[a_vec[i], s_vec[i]] for i in 1:length(s_vec)]
get_q_values(q_value::QValueFunction, a_vec::Array{Int64,1}, s_vec::Array{Array{Int64, 1}, 1}) = [q_value[a_vec[i], s_vec[i]...] for i in 1:length(s_vec)]
get_q_values(q_value::QValueFunction, a_vec::Array{Int64,1}, s_vec::Array{CartesianIndex, 1}) = [q_value[a_vec[i], s_vec[i]] for i in 1:length(s_vec)]
get_q_values(q_value::QValueFunction, a_vec::Array{Int64,1}, s_vec::Array{CartesianIndex{2}, 1}) = [q_value[a_vec[i], s_vec[i]] for i in 1:length(s_vec)]
get_q_values(q_value::QValueFunction, a, s) = q_value[a, s]

abstract type QOptimizer <: Optimizer end

function update!(q_value::QValueFunction, opt::QOptimizer, ρ, s_t, s_tp1, r, γ, terminal, a_t, a_tp1, policy)
    throw(ErrorException("Implement update for $(typeof(opt))"))
end

mutable struct Sarsa <: QOptimizer
    α::Float64
    batch_size::Integer
    α_mod::Float64
    avg::Bool
    Sarsa(α, batch_size) = new(α, batch_size, 1.0, false)
    Sarsa(α, batch_size, α_mod) = new(α, batch_size, α_mod, false)
    Sarsa(α, batch_size, α_mod, avg) = new(α, batch_size, α_mod, avg)
end

function update!(q_value::QValueFunction, opt::Sarsa, ρ, s_t, s_tp1, r, γ, terminal, a_t, a_tp1, policy)
    batch_size = opt.batch_size
    α = opt.α*opt.α_mod
    if opt.avg
        α = α/length(ρ)
    end
    γ_eff = γ .* (terminal.==false)
    δ = zeros(batch_size)
    q_t = get_q_values(q_value, a_t, s_t)
    q_tp1 = get_q_values(q_value, a_tp1, s_tp1)
    δ .= (r + γ_eff.*q_tp1 - q_t)
    for i = 1:batch_size
        q_value[a_t[i], s_t[i]] += α*δ[i]
    end
end

"""
Various functions for getting the expected value of a QFunction. (expected over actions).
"""

get_expected_q_value(q_value::QValueFunction, policy::Array{Float64, 1}, s) =
    sum(policy[a]*get_q_values(q_value, a, s) for a in 1:length(policy))
get_expected_q_value(q_value::QValueFunction, policy::Array{Float64, 1}, s::Int64...) =
    sum(policy[a]*get_q_values(q_value, a, s...) for a in 1:length(policy))
get_expected_q_value(q_value::QValueFunction, policy::Array{Float64, 1}, s::Array{Int64, 1}) =
    [sum(policy[a]*get_q_values(q_value, a, s_ex) for a in 1:length(policy)) for s_ex in s]
get_expected_q_value(q_value::QValueFunction, policy::Array{Float64, 1}, s::Array{Array{Int64, 1}, 1}) =
    [get_expectex_q_value(q_value, policy, s_ex...) for s_ex in s]
get_expected_q_value(q_value::QValueFunction, policy::Array{Float64, 1}, s::Array{CartesianIndex, 1}) =
    [get_expected_q_value(q_value, policy, s_ex) for s_ex in s]
get_expected_q_value(q_value::QValueFunction, policy::Array{Array{Float64, 1}, 1}, s::Array{CartesianIndex, 1}) =
    [get_expected_q_value(q_value, policy[s_idx], s_ex) for (s_idx, s_ex) in enumerate(s)]

mutable struct ExpectedSarsa <: QOptimizer
    α::Float64
    batch_size::Integer
    num_actions::Integer
    α_mod::Float64
    avg::Bool
end

function update!(q_value::QValueFunction, opt::ExpectedSarsa,
                 ρ, s_t, s_tp1, r, γ, terminal, a_t, a_tp1,
                 policy::Array{Float64, 1})
    batch_size = opt.batch_size
    α = opt.α*opt.α_mod
    if opt.avg
        α = α/length(ρ)
    end
    num_actions = opt.num_actions
    γ_eff = γ .* (terminal.==false)
    δ = zeros(batch_size)

    q_t = get_q_values(q_value, a_t, s_t)
    q_expected_tp1 = get_expected_q_value(q_value, policy, s_tp1)
    δ .= (r + γ_eff.*q_expected_tp1 .- q_t)
    for i = 1:batch_size
        q_value[a_t[i], s_t[i]] += α*δ[i]
    end
end

# function update!(q_value::QValueFunction, opt::ExpectedSarsa,
#                  ρ, s_t, s_tp1, r, γ, terminal, a_t, a_tp1,
#                  policy::Array{Array{Float64, 1}, 1})
#     batch_size = opt.batch_size
#     α = opt.α*opt.α_mod
#     num_actions = opt.num_actions
#     γ_eff = γ .* (terminal.==false)
#     δ = zeros(batch_size)

#     q_t = get_q_values(q_value, a_t, s_t)
#     q_expected_tp1 = get_expected_q_value(q_value, policy, s_tp1)
#     # q_tp1 = get_q_values(q_value, a_tp1, s_tp1)

#     δ .= (r + γ_eff.*q_expected_tp1 .- q_t)
#     for i = 1:batch_size
#         q_value[a_t[i], s_t[i]] += α*δ[i]
#     end
# end

end # module TabularRL


text:
using LinearAlgebra
using Images
using FFTW

# load data
xs = load("./examples/StarGalaxy/star.png")
xd = load("./examples/StarGalaxy/galaxy.png")

# size
m, n = size(xs)

# preprocessing on xs
xs = Gray.(xs); xs = convert(Array{Float64}, xs)
γ = xs[3,1]; xs = xs .- γ # normalize
idx = findall(x->abs(x)<=7e-2, xs); xs[idx] .= 0
ks = count(x->x!=0, xs)
xs = vec(xs)

# preprocessing on xd
xd = Gray.(xd); xd = convert(Array{Float64}, xd);
zd = dct(xd); idx = findall(x->abs(x)<=0.02, zd); zd[idx] .= 0
kd = count(x->x!=0, zd)
xd = idct(zd)
xd = vec(xd)

# observation
b = xs + xd

# write to file
f = open("/home/zhenan/Github/AtomicOpt.jl/examples/StarGalaxy/StarGalaxyData.txt", "w")
l = length(b)
@printf(f, "xs = ")
for i in 1:l
    @printf(f, "%.3f ", xs[i])
end
println(f, "\n")
@printf(f, "xd = ")
for i in 1:l
    @printf(f, "%.3f ", xd[i])
end
println(f, "\n")
@printf(f, "b = ")
for i in 1:l
    @printf(f, "%.3f ", b[i])
end
println(f, "\n")
@printf(f, "ks = %d\n", ks)
@printf(f, "kd = %d\n", kd)
@printf(f, "m = %d\n", m)
@printf(f, "n = %d\n", n)
close(f)


text:
#xor-ml.jl - set up to test the xor function in julia.

using SigmoidNumbers
using GenML

import SigmoidNumbers.Sigmoid

#assign sigmoid to the pseudologistic
GenML.TF.sigmoid(x::Posit) = SigmoidNumbers.pseudologistic(x)
GenML.TF.dasysigmoid(x::Posit) = SigmoidNumbers.delta_psl(x)
GenML.CF.logloss(x::Posit) = SigmoidNumbers.pseudologcost(x)

function xortrain(PType)

  println("working on unreliable xor data set with backpropagation")

  input_matrix = rand(Bool, 10, 500)
  training_results = Array{Bool,2}(1,500)
  training_results[:] = [input_matrix[1, col] $ input_matrix[2, col] $ (rand() < 0.05) for col in 1:size(input_matrix,2)]

  xornet = GenML.MLP.MultilayerPerceptron{PType,(10,2,1)}(randn)

  for rounds = 1:25
  for idx = 1:500
    input_column = input_matrix[:, idx]
    training_column = training_results[:, idx]

    GenML.MLP.backpropagationoptimize(xornet, input_column, training_column, GenML.CF.crossentropy)
  end
  end

  #verify that the optimization has resulted in a good data set.
  wrongcount = 0
  for x = 1:50
    input_vector = rand(Bool, 10)
    wrongcount += (xornet(input_vector)[1] > PType(0.5)) != (input_vector[1] $ input_vector[2])
  end
  println("incorrect responses for noisy xor: $wrongcount / 50 => $(2 * (50 - wrongcount)) % correct")

  return wrongcount
end

Base.randn{PType <: Sigmoid}(::Type{PType}, dims::Integer...) = map(PType, randn(dims...))

const trials = 1000

for nindex = 16:-1:6
  results = zeros(Int, trials)

  PType = Posit{nindex}

  for idx = 1:trials
    println("posit $(PType): round $idx")
    results[idx] = xortrain(PType)
  end

  writedlm(string("./results/posit-widened-$nindex.csv"), results, ',')
end

max_stars_repo_name: ityonemo/SigmoidNumbers

max_issues_repo_name: ityonemo/SigmoidNumbers

max_forks_repo_name: ityonemo/SigmoidNumbers


text:
function generate_compat_entry(ver::VersionNumber)
    (ver.major > 0) && return "$(ver.major)"
    (ver.minor > 0) && return "0.$(ver.minor)"
    return "0.0.$(ver.patch)"
end


text:
# # Machine Learning in Julia (continued)

# An introduction to the
# [MLJ](https://alan-turing-institute.github.io/MLJ.jl/stable/)
# toolbox.

# ### Set-up

# Inspect Julia version:

VERSION

# The following instantiates a package environment.

# The package environment has been created using **Julia 1.6** and may not
# instantiate properly for other Julia versions.

using Pkg
Pkg.activate("env")
Pkg.instantiate()

# ## General resources

# - [MLJ Cheatsheet](https://alan-turing-institute.github.io/MLJ.jl/dev/mlj_cheatsheet/)
# - [Common MLJ Workflows](https://alan-turing-institute.github.io/MLJ.jl/dev/common_mlj_workflows/)
# - [MLJ manual](https://alan-turing-institute.github.io/MLJ.jl/dev/)
# - [Data Science Tutorials in Julia](https://juliaai.github.io/DataScienceTutorials.jl/)

# ## Part 4 - Tuning Hyper-parameters

# ### Naive tuning of a single parameter

# The most naive way to tune a single hyper-parameter is to use
# `learning_curve`, which we already saw in Part 2. Let's see this in
# the Horse Colic classification problem, a case where the parameter
# to be tuned is *nested* (because the model is a pipeline).

# Here is the Horse Colic data again, with the type coercions we
# already discussed in Part 1:

using MLJ
using UrlDownload, CSV, DataFrames
csv_file = urldownload("https://raw.githubusercontent.com/ablaom/"*
                   "MachineLearningInJulia2020/"*
                   "for-MLJ-version-0.16/data/horse.csv");
horse = DataFrames.DataFrame(csv_file); # convert to data frame
coerce!(horse, autotype(horse));
coerce!(horse, Count => Continuous);
coerce!(horse,
        :surgery               => Multiclass,
        :age                   => Multiclass,
        :mucous_membranes      => Multiclass,
        :capillary_refill_time => Multiclass,
        :outcome               => Multiclass,
        :cp_data               => Multiclass);

y, X = unpack(horse, ==(:outcome));
schema(X)

# Now for a pipeline model:

LogisticClassifier = @load LogisticClassifier pkg=MLJLinearModels
model = Standardizer |> ContinuousEncoder |> LogisticClassifier
mach = machine(model, X, y)

#-

r = range(model, :(logistic_classifier.lambda), lower = 1e-2, upper=100, scale=:log10)

# If you're curious, you can see what `lambda` values this range will
# generate for a given resolution:

iterator(r, 5)

#-

using Plots
gr(size=(490,300))
_, _, lambdas, losses = learning_curve(mach,
                                       range=r,
                                       resampling=CV(nfolds=6),
                                       resolution=30, # default
                                       measure=cross_entropy)
plt=plot(lambdas, losses, xscale=:log10)
xlabel!(plt, "lambda")
ylabel!(plt, "cross entropy using 6-fold CV")
savefig("learning_curve2.png")
plt #!md

# ![](learning_curve2.png) #md

best_lambda = lambdas[argmin(losses)]

# ### Self tuning models

# A more sophisticated way to view hyper-parameter tuning (inspired by
# MLR) is as a model *wrapper*. The wrapped model is a new model in
# its own right and when you fit it, it tunes specified
# hyper-parameters of the model being wrapped, before training on all
# supplied data. Calling `predict` on the wrapped model is like
# calling `predict` on the original model, but with the
# hyper-parameters already optimized.

# In other words, we can think of the wrapped model as a "self-tuning"
# version of the original.

# We now create a self-tuning version of the pipeline above, adding a
# parameter from the `ContinuousEncoder` to the parameters we want
# optimized.

# First, let's choose a tuning strategy (from [these
# options](https://github.com/juliaai/MLJTuning.jl#what-is-provided-here)). MLJ
# supports ordinary `Grid` search (query `?Grid` for
# details). However, as the utility of `Grid` search is limited to a
# small number of parameters, and as `Grid` searches are demonstrated
# elsewhere (see the [resources below](#resources-for-part-4)) we'll
# demonstrate `RandomSearch` here:

tuning = RandomSearch(rng=123)

# In this strategy each parameter is sampled according to a
# pre-specified prior distribution that is fit to the one-dimensional
# range object constructed using `range` as before. While one has a
# lot of control over the specification of the priors (run
# `?RandomSearch` for details) we'll let the algorithm generate these
# priors automatically.

# #### Unbounded ranges and sampling

# In MLJ a range does not have to be bounded. In a `RandomSearch` a
# positive unbounded range is sampled using a `Gamma` distribution, by
# default:

r = range(model,
          :(logistic_classifier.lambda),
          lower=0,
          origin=6,
          unit=5,
          scale=:log10)

# The `scale` in a range is ignored in a `RandomSearch`, unless it is a
# function. (It *is* relevant in a `Grid` search, not demonstrated
# here.) Note however, the choice of scale *does* effect how later plots
# will look.

# Let's see what sampling using a Gamma distribution is going to mean
# for this range:

import Distributions
sampler_r = sampler(r, Distributions.Gamma)
plt = histogram(rand(sampler_r, 10000), nbins=50)
savefig("gamma_sampler.png")
plt #!md

# ![](gamma_sampler.png) #md

# The second parameter that we'll add to this is *nominal* (finite) and, by
# default, will be sampled uniformly. Since it is nominal, we specify
# `values` instead of `upper` and `lower` bounds:

s  = range(model, :(continuous_encoder.one_hot_ordered_factors),
           values = [true, false])

# #### The tuning wrapper

# Now for the wrapper, which is an instance of `TunedModel`:

tuned_model = TunedModel(model=model,
                         ranges=[r, s],
                         resampling=CV(nfolds=6),
                         measures=cross_entropy,
                         tuning=tuning,
                         n=15)

# We can apply the `fit!/predict` work-flow to `tuned_model` just as
# for any other model:

tuned_mach = machine(tuned_model, X, y);
fit!(tuned_mach);
predict(tuned_mach, rows=1:3)

# The outcomes of the tuning can be inspected from a detailed
# report. For example, we have:

rep = report(tuned_mach);
rep.best_model

# In the special case of two-parameters, you can also plot the results:

plt = plot(tuned_mach)
savefig("tuning.png")
plt #!md

# ![](tuning.png) #md

# Finally, let's compare cross-validation estimate of the performance
# of the self-tuning model with that of the original model (an example
# of [*nested
# resampling*]((https://mlr.mlr-org.com/articles/tutorial/nested_resampling.html)
# here):

err = evaluate!(mach, resampling=CV(nfolds=3), measure=cross_entropy)

#-

tuned_err = evaluate!(tuned_mach, resampling=CV(nfolds=3), measure=cross_entropy)

#

# ### Resources for Part 4
#
# - From the MLJ manual:
#    - [Learning Curves](https://alan-turing-institute.github.io/MLJ.jl/dev/learning_curves/)
#    - [Tuning Models](https://alan-turing-institute.github.io/MLJ.jl/dev/tuning_models/)
# - The [MLJTuning repo](https://github.com/juliaai/MLJTuning.jl#who-is-this-repo-for) - mostly for developers
#
# - From Data Science Tutorials:
#     - [Tuning a model](https://juliaai.github.io/DataScienceTutorials.jl/getting-started/model-tuning/)
#     - [Crabs with XGBoost](https://juliaai.github.io/DataScienceTutorials.jl/end-to-end/crabs-xgb/) `Grid` tuning in stages for a tree-boosting model with many parameters
#     - [Boston with LightGBM](https://juliaai.github.io/DataScienceTutorials.jl/end-to-end/boston-lgbm/) -  `Grid` tuning for another popular tree-booster
#     - [Boston with Flux](https://juliaai.github.io/DataScienceTutorials.jl/end-to-end/boston-flux/) - optimizing batch size in a simple neural network regressor
# - [UCI Horse Colic Data Set](http://archive.ics.uci.edu/ml/datasets/Horse+Colic)

# ### Exercises for Part 4

# #### Exercise 8

# This exercise continues our analysis of the King County House price
# prediction problem (Part 1, Exercise 3 and Part 2):

house_csv = urldownload("https://raw.githubusercontent.com/ablaom/"*
                        "MachineLearningInJulia2020/for-MLJ-version-0.16/"*
                        "data/house.csv");
house = DataFrames.DataFrame(house_csv)
coerce!(house, autotype(house_csv));
coerce!(house, Count => Continuous, :zipcode => Multiclass);
y, X = unpack(house, ==(:price), rng=123);
schema(X)

# Your task will be to tune the following pipeline regression model,
# which includes a gradient tree boosting component:

EvoTreeRegressor = @load EvoTreeRegressor
tree_booster = EvoTreeRegressor(nrounds = 70)
model = ContinuousEncoder |> tree_booster

# (a) Construct a bounded range `r1` for the `evo_tree_booster`
# parameter `max_depth`, varying between 1 and 12.

# \star&(b) For the `nbins` parameter of the `EvoTreeRegressor`, define the range

r2 = range(model,
           :(evo_tree_regressor.nbins),
           lower = 2.5,
           upper= 7.5, scale=x->2^round(Int, x))

# Notice that in this case we've specified a *function* instead of a
# canned scale, like `:log10`. In this case the `scale` function is
# applied after sampling (uniformly) between the limits of `lower` and
# `upper`. Perhaps you can guess the outputs of the following lines of
# code?

r2_sampler = sampler(r2, Distributions.Uniform)
samples = rand(r2_sampler, 1000);
plt = histogram(samples, nbins=50)
savefig("uniform_sampler.png")

plt #!md

# ![](uniform_sampler.png)

sort(unique(samples))

# (c) Optimize `model` over these the parameter ranges `r1` and `r2`
# using a random search with uniform priors (the default). Use
# `Holdout()` resampling, and implement your search by first
# constructing a "self-tuning" wrap of `model`, as described
# above. Make `mae` (mean absolute error) the loss function that you
# optimize, and search over a total of 40 combinations of
# hyper-parameters.  If you have time, plot the results of your
# search. Feel free to use all available data.

# (d) Evaluate the best model found in the search using 3-fold
# cross-validation and compare with that of the self-tuning model
# (which is different!). Setting data hygiene concerns aside, feel
# free to use all available data.

#


text:
# Example use of the Wolff sampler

using Random
using Printf
using Statistics

using Ising2D

# Set lattice size, temperature, and number of iterations
N = 10;
β = 0.5;
J = 1.0; # lattice coupling
niters = 10^6;

# Generate an initial random lattice
Random.seed!(100);
x₀ = RandomLattice(L);
# Define the sampler
sampler = Wolff(β, J, L);
# Set sampler options
opts = IsingOptions(n_iters=niters,n_save_iters=1);

# Sample
x_trajectory = sample_trajectory(x₀, sampler, options=opts);

# Compute statistics
e_trajectory = Energy.(x_trajectory)/L^2;
m_trajectory = Magnetization.(x_trajectory)/L^2;
@printf("β = %g, %d iterations\n\n", β, niters)
@printf("Mean Energy (per spin): %g, Std. Dev %g\n", mean(e_trajectory), std(e_trajectory))
@printf("Mean Magnetization (per spin): %g, Std. Dev %g\n", mean(m_trajectory), std(m_trajectory))