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

const Bits = Vector{UInt64}
const CHK0 = zero(UInt64)
const NO_OFFSET = Int === Int64 ? -one(Int) << 60 : -one(Int) << 29
# + NO_OFFSET must be small enough to stay < 0 when added with any offset.
#   An offset is in the range -2^57:2^57 (64-bits architectures)
#   or -2^26:2^26 (32-bits architectures)
# + when the offset is NO_OFFSET, the bits field *must* be empty
# + NO_OFFSET could be made to be > 0, but a negative one allows
#   a small optimization in the in(x, ::BitSet)

mutable struct BitSet <: AbstractSet{Int}
    bits::Vector{UInt64}
    # 1st stored Int equals 64*offset
    offset::Int

    BitSet() = new(sizehint!(zeros(UInt64, 0), 4), NO_OFFSET)
end

"""
    BitSet([itr])

Construct a sorted set of `Int`s generated by the given iterable object, or an
empty set. Implemented as a bit string, and therefore designed for dense integer sets.
If the set will be sparse (for example, holding a few
very large integers), use [`Set`](@ref) instead.
"""
BitSet(itr) = union!(BitSet(), itr)

@inline intoffset(s::BitSet) = s.offset << 6

eltype(::Type{BitSet}) = Int

empty(s::BitSet, ::Type{Int}=Int) = BitSet()
emptymutable(s::BitSet, ::Type{Int}=Int) = BitSet()

copy(s1::BitSet) = copy!(BitSet(), s1)
copymutable(s::BitSet) = copy(s)

"""
    copy!(dst, src)

In-place [`copy`](@ref) of `src` into `dst`. After the call to `copy!`,
`dst` must be left equal to `src`, otherwise an error is thrown; this
function appropriately resizes `dst` if necessary.
See also [`copyto!`](@ref).
"""
function copy!(dest::BitSet, src::BitSet)
    resize!(dest.bits, length(src.bits))
    copyto!(dest.bits, src.bits)
    dest.offset = src.offset
    dest
end

sizehint!(s::BitSet, n::Integer) = (sizehint!(s.bits, (n+63) >> 6); s)

function _bits_getindex(b::Bits, n::Int, offset::Int)
    ci = _div64(n) - offset + 1
    1 <= ci <= length(b) || return false
    @inbounds r = (b[ci] & (one(UInt64) << _mod64(n))) != 0
    r
end

function _bits_findnext(b::Bits, start::Int)
    # start is 0-based
    # @assert start >= 0
    _div64(start) + 1 > length(b) && return -1
    ind = unsafe_bitfindnext(b, start+1)
    ind === nothing ? -1 : ind - 1
end

function _bits_findprev(b::Bits, start::Int)
    # start is 0-based
    # @assert start <= 64 * length(b) - 1
    start >= 0 || return -1
    ind = unsafe_bitfindprev(b, start+1)
    ind === nothing ? -1 : ind - 1
end

# An internal function for setting the inclusion bit for a given integer
@inline function _setint!(s::BitSet, idx::Int, b::Bool)
    cidx = _div64(idx)
    len = length(s.bits)
    diff = cidx - s.offset
    if diff >= len
        b || return s # setting a bit to zero outside the set's bits is a no-op

        # we put the following test within one of the two branches,
        # with the NO_OFFSET trick, to avoid having to perform it at
        # each and every call to _setint!
        if s.offset == NO_OFFSET # initialize the offset
            # we assume isempty(s.bits)
            s.offset = cidx
            diff = 0
        end
        _growend0!(s.bits, diff - len + 1)
    elseif diff < 0
        b || return s
        _growbeg0!(s.bits, -diff)
        s.offset += diff
        diff = 0
    end
    _unsafe_bitsetindex!(s.bits, b, diff+1, _mod64(idx))
    s
end

# An internal function to resize a Bits object and ensure the newly allocated
# elements are zeroed (will become unnecessary if this behavior changes)
@inline function _growend0!(b::Bits, nchunks::Int)
    len = length(b)
    _growend!(b, nchunks)
    @inbounds b[len+1:end] = CHK0 # resize! gives dirty memory
end

@inline function _growbeg0!(b::Bits, nchunks::Int)
    _growbeg!(b, nchunks)
    @inbounds b[1:nchunks] = CHK0
end

function _matched_map!(f, s1::BitSet, s2::BitSet)
    left_false_is_false = f(false, false) == f(false, true) == false
    right_false_is_false = f(false, false) == f(true, false) == false

    # we must first handle the NO_OFFSET case; we could test for
    # isempty(s1) but it can be costly, so the user has to call
    # empty!(s1) herself before-hand to re-initialize to NO_OFFSET
    if s1.offset == NO_OFFSET
        return left_false_is_false ? s1 : copy!(s1, s2)
    elseif s2.offset == NO_OFFSET
        return right_false_is_false ? empty!(s1) : s1
    end
    s1.offset = _matched_map!(f, s1.bits, s1.offset, s2.bits, s2.offset,
                              left_false_is_false, right_false_is_false)
    s1
end

# An internal function that takes a pure function `f` and maps across two BitArrays
# allowing the lengths and offsets to be different and altering b1 with the result
# WARNING: the assumptions written in the else clauses must hold
function _matched_map!(f, a1::Bits, b1::Int, a2::Bits, b2::Int,
                       left_false_is_false::Bool, right_false_is_false::Bool)
    l1, l2 = length(a1), length(a2)
    bdiff = b2 - b1
    e1, e2 = l1+b1, l2+b2
    ediff = e2 - e1

    # map! over the common indices
    @inbounds for i = max(1, 1+bdiff):min(l1, l2+bdiff)
        a1[i] = f(a1[i], a2[i-bdiff])
    end

    if ediff > 0
        if left_false_is_false
            # We don't need to worry about the trailing bits — they're all false
        else # @assert f(false, x) == x
            _growend!(a1, ediff)
            # if a1 and a2 are not overlapping, we infer implied "false" values from a2
            for outer l1 = l1+1:bdiff
                @inbounds a1[l1] = CHK0
            end
            # update ediff in case l1 was updated
            ediff = e2 - l1 - b1
            # copy actual chunks from a2
            unsafe_copyto!(a1, l1+1, a2, l2+1-ediff, ediff)
            l1 = length(a1)
        end
    elseif ediff < 0
        if right_false_is_false
            # We don't need to worry about the trailing bits — they're all false
            _deleteend!(a1, min(l1, -ediff))
            # no need to update l1, as if bdiff > 0 (case below), then bdiff will
            # be smaller anyway than an updated l1
        else # @assert f(x, false) == x
            # We don't need to worry about the trailing bits — they already have the
            # correct value
        end
    end

    if bdiff < 0
        if left_false_is_false
            # We don't need to worry about the leading bits — they're all false
        else # @assert f(false, x) == x
            _growbeg!(a1, -bdiff)
            # if a1 and a2 are not overlapping, we infer implied "false" values from a2
            for i = l2+1:-bdiff
                @inbounds a1[i] = CHK0
            end
            b1 += bdiff # updated return value

            # copy actual chunks from a2
            unsafe_copyto!(a1, 1, a2, 1, min(-bdiff, l2))
        end
    elseif bdiff > 0
        if right_false_is_false
            # We don't need to worry about the trailing bits — they're all false
            _deletebeg!(a1, min(l1, bdiff))
            b1 += bdiff
        else # @assert f(x, false) == x
            # We don't need to worry about the trailing bits — they already have the
            # correct value
        end
    end
    b1 # the new offset
end

@noinline _throw_bitset_bounds_err() =
    throw(ArgumentError("elements of BitSet must be between typemin(Int) and typemax(Int)"))

@inline _is_convertible_Int(n) = typemin(Int) <= n <= typemax(Int)

@inline _check_bitset_bounds(n) =
    _is_convertible_Int(n) ? Int(n) : _throw_bitset_bounds_err()

@inline _check_bitset_bounds(n::Int) = n

@noinline _throw_keyerror(n) = throw(KeyError(n))

@inline push!(s::BitSet, n::Integer) = _setint!(s, _check_bitset_bounds(n), true)

push!(s::BitSet, ns::Integer...) = (for n in ns; push!(s, n); end; s)

@inline pop!(s::BitSet) = pop!(s, last(s))

@inline function pop!(s::BitSet, n::Integer)
    if n in s
        delete!(s, n)
        n
    else
        _throw_keyerror(n)
    end
end

@inline function pop!(s::BitSet, n::Integer, default)
    if n in s
        delete!(s, n)
        n
    else
        default
    end
end

@inline delete!(s::BitSet, n::Int) = _setint!(s, n, false)
@inline delete!(s::BitSet, n::Integer) = _is_convertible_Int(n) ? delete!(s, Int(n)) : s

popfirst!(s::BitSet) = pop!(s, first(s))

function empty!(s::BitSet)
    empty!(s.bits)
    s.offset = NO_OFFSET
    s
end

isempty(s::BitSet) = _check0(s.bits, 1, length(s.bits))

# Mathematical set functions: union!, intersect!, setdiff!, symdiff!

union(s::BitSet, sets...) = union!(copy(s), sets...)
union!(s1::BitSet, s2::BitSet) = _matched_map!(|, s1, s2)

intersect(s1::BitSet, s2::BitSet) =
    length(s1.bits) < length(s2.bits) ? intersect!(copy(s1), s2) : intersect!(copy(s2), s1)

intersect!(s1::BitSet, s2::BitSet) = _matched_map!(&, s1, s2)

setdiff!(s1::BitSet, s2::BitSet) = _matched_map!((p, q) -> p & ~q, s1, s2)

symdiff!(s::BitSet, ns) = foldl(int_symdiff!, s, ns)

function int_symdiff!(s::BitSet, n::Integer)
    n0 = _check_bitset_bounds(n)
    val = !(n0 in s)
    _setint!(s, n0, val)
    s
end

symdiff!(s1::BitSet, s2::BitSet) = _matched_map!(xor, s1, s2)

filter!(f, s::BitSet) = unsafe_filter!(f, s)

@inline in(n::Int, s::BitSet) = _bits_getindex(s.bits, n, s.offset)
@inline in(n::Integer, s::BitSet) = _is_convertible_Int(n) ? in(Int(n), s) : false

# Use the next-set index as the state to prevent looking it up again in done
start(s::BitSet) = _bits_findnext(s.bits, 0)

function next(s::BitSet, i::Int)
    nextidx = _bits_findnext(s.bits, i+1)
    (i+intoffset(s), nextidx)
end

done(s::BitSet, i) = i == -1

@noinline _throw_bitset_notempty_error() =
    throw(ArgumentError("collection must be non-empty"))

function first(s::BitSet)
    idx = _bits_findnext(s.bits, 0)
    idx == -1 ? _throw_bitset_notempty_error() : idx + intoffset(s)
end

function last(s::BitSet)
    idx = _bits_findprev(s.bits, (length(s.bits) << 6) - 1)
    idx == -1 ? _throw_bitset_notempty_error() : idx + intoffset(s)
end

length(s::BitSet) = bitcount(s.bits) # = mapreduce(count_ones, +, 0, s.bits)

function show(io::IO, s::BitSet)
    print(io, "BitSet([")
    first = true
    for n in s
        !first && print(io, ", ")
        print(io, n)
        first = false
    end
    print(io, "])")
end

function _check0(a::Vector{UInt64}, b::Int, e::Int)
    @inbounds for i in b:e
        a[i] == CHK0 || return false
    end
    true
end

function ==(s1::BitSet, s2::BitSet)
    # Swap so s1 has always the smallest offset
    if s1.offset > s2.offset
        s1, s2 = s2, s1
    end
    a1 = s1.bits
    a2 = s2.bits
    b1, b2 = s1.offset, s2.offset
    l1, l2 = length(a1), length(a2)
    e1 = l1+b1
    overlap0 = max(0, e1 - b2)
    included = overlap0 >= l2  # whether a2's indices are included in a1's
    overlap  = included ? l2 : overlap0

    # Ensure non-overlap chunks are zero (unlikely)
    _check0(a1, 1, l1-overlap0) || return false
    if included
        _check0(a1, b2-b1+l2+1, l1) || return false
    else
        _check0(a2, 1+overlap, l2) || return false
    end

    # compare overlap values
    if overlap > 0
        _memcmp(pointer(a1, b2-b1+1), pointer(a2), overlap<<3) == 0 || return false
    end

    return true
end

issubset(a::BitSet, b::BitSet) = a == intersect(a,b)
⊊(a::BitSet, b::BitSet) = a <= b && a != b

minimum(s::BitSet) = first(s)
maximum(s::BitSet) = last(s)
extrema(s::BitSet) = (first(s), last(s))
issorted(s::BitSet) = true

max_stars_repo_name: nreigl/julia

max_issues_repo_name: BenChung/Julia-BTI

max_forks_repo_name: BenChung/Julia-BTI


text:
using TopOpt, TopOptProblems, CuArrays, LinearAlgebra

E = 1.0 # Young’s modulus
v = 0.3 # Poisson’s ratio
f = 1.0 # downward force

problem = PointLoadCantilever(Val{:Linear}, (160, 40), (1.0, 1.0), E, v, f)
V = 0.5 # volume fraction
xmin = 0.001 # minimum density
maxtol = 0.01 # maximum tolerance
mintol = 0.0001 # minimum tolerance
steps = 40 # maximum number of penalty steps, delta_p0 = 0.1
reuse = true # adaptive penalty flag
filtering = true
solver = FEASolver(Displacement, CG, MatrixFree, problem, xmin = xmin,
	penalty = TopOpt.PowerPenalty(1.0))
cusolver = cu(solver)
cuobj = ComplianceFunction(problem, cusolver, filtering = filtering,
rmin = 3.0, tracing = true, logarithm = false)

operator = TopOpt.buildoperator(cusolver)
x = CuArray(ones(length(cusolver.f)))
mul!(x, operator, cusolver.f)

ext: jl


text:
## FUNCTIONS TO INSPECT METADATA OF REGISTERED MODELS AND TO
## FACILITATE MODEL SEARCH

is_supervised(::Type{<:MLJBase.Supervised}) = true
is_supervised(::Type{<:MLJBase.Unsupervised}) = false

supervised_propertynames = sort(SUPERVISED_TRAITS)
alpha = [:name, :package_name, :is_supervised]
omega = [:input_scitype, :target_scitype]
both = vcat(alpha, omega)
filter!(!in(both), supervised_propertynames)
prepend!(supervised_propertynames, alpha)
append!(supervised_propertynames, omega)
const SUPERVISED_PROPERTYNAMES = Tuple(supervised_propertynames)

unsupervised_propertynames = sort(UNSUPERVISED_TRAITS)
alpha = [:name, :package_name, :is_supervised]
omega = [:input_scitype, :output_scitype]
both = vcat(alpha, omega)
filter!(!in(both), unsupervised_propertynames)
prepend!(unsupervised_propertynames, alpha)
append!(unsupervised_propertynames, omega)
const UNSUPERVISED_PROPERTYNAMES = Tuple(unsupervised_propertynames)

ModelProxy = Union{NamedTuple{SUPERVISED_PROPERTYNAMES},
                   NamedTuple{UNSUPERVISED_PROPERTYNAMES}}

function Base.isless(p1::ModelProxy, p2::ModelProxy)
    if isless(p1.name, p2.name)
        return true
    elseif p1.name == p2.name
        return isless(p1.package_name, p2.package_name)
    else
        return false
    end
end

import MLJBase.==
function ==(m1::ModelProxy, m2::ModelProxy)
    m1.name == m2.name && m1.package_name == m2.package_name
    # tests = map(keys(m1)) do k
    #     v1 = getproperty(m1, k)
    #     v2 = getproperty(m2, k)
    #     if k isa AbstractVector
    #         Set(v1) == Set(v2)
    #     else
    #         v1 == v2
    #     end
    # end
    # return all(tests)
end

Base.show(stream::IO, p::ModelProxy) =
    print(stream, "(name = $(p.name), package_name = $(p.package_name), "*
          "... )")

function Base.show(stream::IO, ::MIME"text/plain", p::ModelProxy)
    printstyled(IOContext(stream, :color=> MLJBase.SHOW_COLOR),
                    p.docstring, bold=false, color=:magenta)
    println(stream)
    MLJBase.fancy_nt(stream, p)
end

# returns named tuple version of the dictionary i=info_dict(SomeModelType):
function info_as_named_tuple(i)
    propertynames = ifelse(i[:is_supervised], SUPERVISED_PROPERTYNAMES,
                           UNSUPERVISED_PROPERTYNAMES)
    propertyvalues = Tuple(i[property] for property in propertynames)
    return NamedTuple{propertynames}(propertyvalues)
end

MLJBase.info(handle::Handle) =
    info_as_named_tuple(INFO_GIVEN_HANDLE[handle])

"""
    info(name::String; pkg=nothing)

Returns the metadata for the registered model type with specified
`name`. The key-word argument `pkg` is required in the case of
duplicate names.

"""
function MLJBase.info(name::String; pkg=nothing)
    name in NAMES ||
        throw(ArgumentError("There is no model named \"$name\" in "*
                            "the registry. \n Run `models()` to view all "*
                            "registered models."))
    # get the handle:
    if pkg == nothing
        handle  = Handle(name)
        if ismissing(handle.pkg)
            pkgs = PKGS_GIVEN_NAME[name]
            message = "Ambiguous model name. Use pkg=... .\n"*
            "The model $name is provided by these packages:\n $pkgs.\n"
            throw(ArgumentError(message))
        end
    else
        handle = Handle(name, pkg)
        haskey(INFO_GIVEN_HANDLE, handle) ||
            throw(ArgumentError("The package \"$pkg\" does not appear to "*
                                "provide the model \"$name\". \n"*
                                "Use models() to list all models. "))
    end
    return info(handle)

end

"""
   info(model::Model)

Return the traits associated with the specified `model`. Equivalent to
`info(name; pkg=pkg)` where `name::String` is the name of the model type, and
`pkg::String` the name of the package containing it.

"""
MLJBase.info(M::Type{<:MLJBase.Model}) =
    info_as_named_tuple(MLJBase.info_dict(M))
MLJBase.info(model::MLJBase.Model) = info(typeof(model))

"""
    models()

List all models in the MLJ registry. Here and below *model* means the
registry metadata entry for a genuine model type (a proxy for types
whose defining code may not be loaded).

    models(conditions...)

List all models satisifying the specified `conditions`. A *condition*
is any `Bool`-valued function on models.

Excluded in the listings are the built-in model-wraps `EnsembleModel`,
`TunedModel`, and `IteratedModel`.

### Example

If

    task(model) = model.is_supervised && model.is_probabilistic

then `models(task)` lists all supervised models making probabilistic
predictions.

See also: [`localmodels`](@ref).

"""
function MLJBase.models(conditions...)
    unsorted = filter(info.(keys(INFO_GIVEN_HANDLE))) do model
        all(c(model) for c in conditions)
    end
    return sort!(unsorted)
end

MLJBase.models() = models(x->true)

# function models(task::MLJBase.SupervisedTask)
#     ret = Dict{String, Any}()
#     function condition(t)
#         return t.is_supervised &&
#             task.target_scitype <: t.target_scitype &&
#             task.input_scitype <: t.input_scitype &&
#             task.is_probabilistic == t.is_probabilistic
#     end
#     return models(condition)
# end

# function models(task::UnsupervisedTask)
#     ret = Dict{String, Any}()
#     function condition(handle)
#         t = info(handle)
#         return task.input_scitype <: t.input_scitype
#     end
#     return models(condition)
# end

"""
    localmodels(; modl=Main)
    localmodels(conditions...; modl=Main)

List all models whose names are in the namespace of the specified
module `modl`, or meeting the `conditions`, if specified. Here a
*condition* is a `Bool`-valued function on models.

See also [`models`](@ref)

"""
function localmodels(args...; modl=Main)
    modeltypes = localmodeltypes(modl)
    names = map(modeltypes) do M
        MLJBase.name(M)
    end
    return filter(models(args...)) do handle
        handle.name in names
    end
end


text:
using BEAST
using CompScienceMeshes

Γ = readmesh(Pkg.dir("BEAST", "test","assets","flatplate.in"))
#Γ = readmesh(Pkg.dir("BEAST", "test","assets","smallflatplate.in"))
RT = raviartthomas(Γ)

X = RT
Y = RT

κ = 1.0
t = BEAST.MWDoubleLayer3D(κ*im)

BEAST.quadrule(op::BEAST.MaxwellOperator3D, g::BEAST.RTRefSpace, f::BEAST.RTRefSpace, i, τ, j, σ, qd) = BEAST.q(op, g, f, i, τ, j, σ, qd)
Zss = assemble(t,X,Y)

BEAST.quadrule(op::BEAST.MaxwellOperator3D, g::BEAST.RTRefSpace, f::BEAST.RTRefSpace, i, τ, j, σ, qd) = BEAST.qrdf(op, g, f, i, τ, j, σ, qd)
Zqrdf = assemble(t,X,Y)

BEAST.quadrule(op::BEAST.MaxwellOperator3D, g::BEAST.RTRefSpace, f::BEAST.RTRefSpace, i, τ, j, σ, qd) = BEAST.qrib(op, g, f, i, τ, j, σ, qd)
Zbogaert = assemble(t,X,Y)

println(abs(Zss)./abs(Zbogaert))


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: budgets
using AWS.Compat
using AWS.UUIDs
"""
    CreateBudget()

Creates a budget and, if included, notifications and subscribers.   Only one of BudgetLimit or PlannedBudgetLimits can be present in the syntax at one time. Use the syntax that matches your case. The Request Syntax section shows the BudgetLimit syntax. For PlannedBudgetLimits, see the Examples section.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget.
- `Budget`: The budget object that you want to create.

# Optional Parameters
- `NotificationsWithSubscribers`: A notification that you want to associate with a budget. A budget can have up to five notifications, and each notification can have one SNS subscriber and up to 10 email subscribers. If you include notifications and subscribers in your CreateBudget call, AWS creates the notifications and subscribers for you.
"""

create_budget(AccountId, Budget; aws_config::AWSConfig=global_aws_config()) = budgets("CreateBudget", Dict{String, Any}("AccountId"=>AccountId, "Budget"=>Budget); aws_config=aws_config)
create_budget(AccountId, Budget, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("CreateBudget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "Budget"=>Budget), args)); aws_config=aws_config)

"""
    CreateBudgetAction()

 Creates a budget action.

# Required Parameters
- `AccountId`:
- `ActionThreshold`:
- `ActionType`:  The type of action. This defines the type of tasks that can be carried out by this action. This field also determines the format for definition.
- `ApprovalModel`:  This specifies if the action needs manual or automatic approval.
- `BudgetName`:
- `Definition`:
- `ExecutionRoleArn`:  The role passed for action execution and reversion. Roles and actions must be in the same account.
- `NotificationType`:
- `Subscribers`:

"""

create_budget_action(AccountId, ActionThreshold, ActionType, ApprovalModel, BudgetName, Definition, ExecutionRoleArn, NotificationType, Subscribers; aws_config::AWSConfig=global_aws_config()) = budgets("CreateBudgetAction", Dict{String, Any}("AccountId"=>AccountId, "ActionThreshold"=>ActionThreshold, "ActionType"=>ActionType, "ApprovalModel"=>ApprovalModel, "BudgetName"=>BudgetName, "Definition"=>Definition, "ExecutionRoleArn"=>ExecutionRoleArn, "NotificationType"=>NotificationType, "Subscribers"=>Subscribers); aws_config=aws_config)
create_budget_action(AccountId, ActionThreshold, ActionType, ApprovalModel, BudgetName, Definition, ExecutionRoleArn, NotificationType, Subscribers, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("CreateBudgetAction", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "ActionThreshold"=>ActionThreshold, "ActionType"=>ActionType, "ApprovalModel"=>ApprovalModel, "BudgetName"=>BudgetName, "Definition"=>Definition, "ExecutionRoleArn"=>ExecutionRoleArn, "NotificationType"=>NotificationType, "Subscribers"=>Subscribers), args)); aws_config=aws_config)

"""
    CreateNotification()

Creates a notification. You must create the budget before you create the associated notification.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget that you want to create a notification for.
- `BudgetName`: The name of the budget that you want AWS to notify you about. Budget names must be unique within an account.
- `Notification`: The notification that you want to create.
- `Subscribers`: A list of subscribers that you want to associate with the notification. Each notification can have one SNS subscriber and up to 10 email subscribers.

"""

create_notification(AccountId, BudgetName, Notification, Subscribers; aws_config::AWSConfig=global_aws_config()) = budgets("CreateNotification", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification, "Subscribers"=>Subscribers); aws_config=aws_config)
create_notification(AccountId, BudgetName, Notification, Subscribers, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("CreateNotification", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification, "Subscribers"=>Subscribers), args)); aws_config=aws_config)

"""
    CreateSubscriber()

Creates a subscriber. You must create the associated budget and notification before you create the subscriber.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget that you want to create a subscriber for.
- `BudgetName`: The name of the budget that you want to subscribe to. Budget names must be unique within an account.
- `Notification`: The notification that you want to create a subscriber for.
- `Subscriber`: The subscriber that you want to associate with a budget notification.

"""

create_subscriber(AccountId, BudgetName, Notification, Subscriber; aws_config::AWSConfig=global_aws_config()) = budgets("CreateSubscriber", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification, "Subscriber"=>Subscriber); aws_config=aws_config)
create_subscriber(AccountId, BudgetName, Notification, Subscriber, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("CreateSubscriber", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification, "Subscriber"=>Subscriber), args)); aws_config=aws_config)

"""
    DeleteBudget()

Deletes a budget. You can delete your budget at any time.  Deleting a budget also deletes the notifications and subscribers that are associated with that budget.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget that you want to delete.
- `BudgetName`: The name of the budget that you want to delete.

"""

delete_budget(AccountId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteBudget", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName); aws_config=aws_config)
delete_budget(AccountId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteBudget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DeleteBudgetAction()

 Deletes a budget action.

# Required Parameters
- `AccountId`:
- `ActionId`:  A system-generated universally unique identifier (UUID) for the action.
- `BudgetName`:

"""

delete_budget_action(AccountId, ActionId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteBudgetAction", Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName); aws_config=aws_config)
delete_budget_action(AccountId, ActionId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteBudgetAction", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DeleteNotification()

Deletes a notification.  Deleting a notification also deletes the subscribers that are associated with the notification.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget whose notification you want to delete.
- `BudgetName`: The name of the budget whose notification you want to delete.
- `Notification`: The notification that you want to delete.

"""

delete_notification(AccountId, BudgetName, Notification; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteNotification", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification); aws_config=aws_config)
delete_notification(AccountId, BudgetName, Notification, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteNotification", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification), args)); aws_config=aws_config)

"""
    DeleteSubscriber()

Deletes a subscriber.  Deleting the last subscriber to a notification also deletes the notification.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget whose subscriber you want to delete.
- `BudgetName`: The name of the budget whose subscriber you want to delete.
- `Notification`: The notification whose subscriber you want to delete.
- `Subscriber`: The subscriber that you want to delete.

"""

delete_subscriber(AccountId, BudgetName, Notification, Subscriber; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteSubscriber", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification, "Subscriber"=>Subscriber); aws_config=aws_config)
delete_subscriber(AccountId, BudgetName, Notification, Subscriber, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DeleteSubscriber", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification, "Subscriber"=>Subscriber), args)); aws_config=aws_config)

"""
    DescribeBudget()

Describes a budget.  The Request Syntax section shows the BudgetLimit syntax. For PlannedBudgetLimits, see the Examples section.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget that you want a description of.
- `BudgetName`: The name of the budget that you want a description of.

"""

describe_budget(AccountId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudget", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName); aws_config=aws_config)
describe_budget(AccountId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DescribeBudgetAction()

 Describes a budget action detail.

# Required Parameters
- `AccountId`:
- `ActionId`:  A system-generated universally unique identifier (UUID) for the action.
- `BudgetName`:

"""

describe_budget_action(AccountId, ActionId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetAction", Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName); aws_config=aws_config)
describe_budget_action(AccountId, ActionId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetAction", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DescribeBudgetActionHistories()

 Describes a budget action history detail.

# Required Parameters
- `AccountId`:
- `ActionId`:  A system-generated universally unique identifier (UUID) for the action.
- `BudgetName`:

# Optional Parameters
- `MaxResults`:
- `NextToken`:
- `TimePeriod`:
"""

describe_budget_action_histories(AccountId, ActionId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetActionHistories", Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName); aws_config=aws_config)
describe_budget_action_histories(AccountId, ActionId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetActionHistories", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DescribeBudgetActionsForAccount()

 Describes all of the budget actions for an account.

# Required Parameters
- `AccountId`:

# Optional Parameters
- `MaxResults`:
- `NextToken`:
"""

describe_budget_actions_for_account(AccountId; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetActionsForAccount", Dict{String, Any}("AccountId"=>AccountId); aws_config=aws_config)
describe_budget_actions_for_account(AccountId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetActionsForAccount", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId), args)); aws_config=aws_config)

"""
    DescribeBudgetActionsForBudget()

 Describes all of the budget actions for a budget.

# Required Parameters
- `AccountId`:
- `BudgetName`:

# Optional Parameters
- `MaxResults`:
- `NextToken`:
"""

describe_budget_actions_for_budget(AccountId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetActionsForBudget", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName); aws_config=aws_config)
describe_budget_actions_for_budget(AccountId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetActionsForBudget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DescribeBudgetPerformanceHistory()

Describes the history for DAILY, MONTHLY, and QUARTERLY budgets. Budget history isn't available for ANNUAL budgets.

# Required Parameters
- `AccountId`:
- `BudgetName`:

# Optional Parameters
- `MaxResults`:
- `NextToken`:
- `TimePeriod`: Retrieves how often the budget went into an ALARM state for the specified time period.
"""

describe_budget_performance_history(AccountId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetPerformanceHistory", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName); aws_config=aws_config)
describe_budget_performance_history(AccountId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgetPerformanceHistory", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DescribeBudgets()

Lists the budgets that are associated with an account.  The Request Syntax section shows the BudgetLimit syntax. For PlannedBudgetLimits, see the Examples section.

# Required Parameters
- `AccountId`: The accountId that is associated with the budgets that you want descriptions of.

# Optional Parameters
- `MaxResults`: An optional integer that represents how many entries a paginated response contains. The maximum is 100.
- `NextToken`: The pagination token that you include in your request to indicate the next set of results that you want to retrieve.
"""

describe_budgets(AccountId; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgets", Dict{String, Any}("AccountId"=>AccountId); aws_config=aws_config)
describe_budgets(AccountId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeBudgets", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId), args)); aws_config=aws_config)

"""
    DescribeNotificationsForBudget()

Lists the notifications that are associated with a budget.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget whose notifications you want descriptions of.
- `BudgetName`: The name of the budget whose notifications you want descriptions of.

# Optional Parameters
- `MaxResults`: An optional integer that represents how many entries a paginated response contains. The maximum is 100.
- `NextToken`: The pagination token that you include in your request to indicate the next set of results that you want to retrieve.
"""

describe_notifications_for_budget(AccountId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeNotificationsForBudget", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName); aws_config=aws_config)
describe_notifications_for_budget(AccountId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeNotificationsForBudget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    DescribeSubscribersForNotification()

Lists the subscribers that are associated with a notification.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget whose subscribers you want descriptions of.
- `BudgetName`: The name of the budget whose subscribers you want descriptions of.
- `Notification`: The notification whose subscribers you want to list.

# Optional Parameters
- `MaxResults`: An optional integer that represents how many entries a paginated response contains. The maximum is 100.
- `NextToken`: The pagination token that you include in your request to indicate the next set of results that you want to retrieve.
"""

describe_subscribers_for_notification(AccountId, BudgetName, Notification; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeSubscribersForNotification", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification); aws_config=aws_config)
describe_subscribers_for_notification(AccountId, BudgetName, Notification, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("DescribeSubscribersForNotification", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "Notification"=>Notification), args)); aws_config=aws_config)

"""
    ExecuteBudgetAction()

 Executes a budget action.

# Required Parameters
- `AccountId`:
- `ActionId`:  A system-generated universally unique identifier (UUID) for the action.
- `BudgetName`:
- `ExecutionType`:  The type of execution.

"""

execute_budget_action(AccountId, ActionId, BudgetName, ExecutionType; aws_config::AWSConfig=global_aws_config()) = budgets("ExecuteBudgetAction", Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName, "ExecutionType"=>ExecutionType); aws_config=aws_config)
execute_budget_action(AccountId, ActionId, BudgetName, ExecutionType, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("ExecuteBudgetAction", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName, "ExecutionType"=>ExecutionType), args)); aws_config=aws_config)

"""
    UpdateBudget()

Updates a budget. You can change every part of a budget except for the budgetName and the calculatedSpend. When you modify a budget, the calculatedSpend drops to zero until AWS has new usage data to use for forecasting.  Only one of BudgetLimit or PlannedBudgetLimits can be present in the syntax at one time. Use the syntax that matches your case. The Request Syntax section shows the BudgetLimit syntax. For PlannedBudgetLimits, see the Examples section.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget that you want to update.
- `NewBudget`: The budget that you want to update your budget to.

"""

update_budget(AccountId, NewBudget; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateBudget", Dict{String, Any}("AccountId"=>AccountId, "NewBudget"=>NewBudget); aws_config=aws_config)
update_budget(AccountId, NewBudget, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateBudget", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "NewBudget"=>NewBudget), args)); aws_config=aws_config)

"""
    UpdateBudgetAction()

 Updates a budget action.

# Required Parameters
- `AccountId`:
- `ActionId`:  A system-generated universally unique identifier (UUID) for the action.
- `BudgetName`:

# Optional Parameters
- `ActionThreshold`:
- `ApprovalModel`:  This specifies if the action needs manual or automatic approval.
- `Definition`:
- `ExecutionRoleArn`:  The role passed for action execution and reversion. Roles and actions must be in the same account.
- `NotificationType`:
- `Subscribers`:
"""

update_budget_action(AccountId, ActionId, BudgetName; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateBudgetAction", Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName); aws_config=aws_config)
update_budget_action(AccountId, ActionId, BudgetName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateBudgetAction", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "ActionId"=>ActionId, "BudgetName"=>BudgetName), args)); aws_config=aws_config)

"""
    UpdateNotification()

Updates a notification.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget whose notification you want to update.
- `BudgetName`: The name of the budget whose notification you want to update.
- `NewNotification`: The updated notification to be associated with a budget.
- `OldNotification`: The previous notification that is associated with a budget.

"""

update_notification(AccountId, BudgetName, NewNotification, OldNotification; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateNotification", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "NewNotification"=>NewNotification, "OldNotification"=>OldNotification); aws_config=aws_config)
update_notification(AccountId, BudgetName, NewNotification, OldNotification, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateNotification", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "NewNotification"=>NewNotification, "OldNotification"=>OldNotification), args)); aws_config=aws_config)

"""
    UpdateSubscriber()

Updates a subscriber.

# Required Parameters
- `AccountId`: The accountId that is associated with the budget whose subscriber you want to update.
- `BudgetName`: The name of the budget whose subscriber you want to update.
- `NewSubscriber`: The updated subscriber that is associated with a budget notification.
- `Notification`: The notification whose subscriber you want to update.
- `OldSubscriber`: The previous subscriber that is associated with a budget notification.

"""

update_subscriber(AccountId, BudgetName, NewSubscriber, Notification, OldSubscriber; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateSubscriber", Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "NewSubscriber"=>NewSubscriber, "Notification"=>Notification, "OldSubscriber"=>OldSubscriber); aws_config=aws_config)
update_subscriber(AccountId, BudgetName, NewSubscriber, Notification, OldSubscriber, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = budgets("UpdateSubscriber", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("AccountId"=>AccountId, "BudgetName"=>BudgetName, "NewSubscriber"=>NewSubscriber, "Notification"=>Notification, "OldSubscriber"=>OldSubscriber), args)); aws_config=aws_config)


text:
import LowLevelJPEG: @code_str, getcodeindex

@testset "HuffmanTreeNode" begin
    @testset "Constructors" begin
        snode1 = HuffmanTreeNode((ACSymbol(0x1), 0.5))
        @test snode1 === HuffmanSymbolNode(ACSymbol(0x1), 0.5)

        snode2 = ACSymbolNode(0x02, 0.25)
        @test snode2 === ACSymbolNode(ACSymbol(0x02), 0.25)

        bnode = HuffmanTreeNode((snode1, snode2))
        @test bnode === HuffmanBranchNode(snode1, snode2)
        @test bnode.probability === 0.75

        @test HuffmanTreeNode((DCSymbol(0x1), 0.5)) ===
                HuffmanSymbolNode(DCSymbol(0x1), 0.5)
    end
end

@testset "HuffmanTree" begin
    s2 = HuffmanTreeNode{ACSymbol}[
        (ACSymbol(0x01), 0.6),
        (ACSymbol(0x02), 0.4)
    ]
    s6 = HuffmanTreeNode{ACSymbol}[
        (0x01, 0.5),
        (0x02, 0.2),
        (0x03, 0.1),
        (0x04, 0.09),
        (0x05, 0.08),
        (0x06, 0.03)
    ]

    @testset "Constructors" begin
        h2 = HuffmanTree(s2)
        @test h2 isa ACHuffmanTree

        h1 = HuffmanTree([HuffmanSymbolNode(DCSymbol(0x1), 1.0)])
        @test h1 isa DCHuffmanTree

        @test_throws MethodError HuffmanTree([])
        @test_throws ErrorException HuffmanTree(HuffmanSymbolNode{ACSymbol}[])
    end

    @testset "Traits" begin
        h2 = HuffmanTree(s2)
        @test LowLevelJPEG.height(h2) == 1
        h6 = HuffmanTree(s6)
        @test LowLevelJPEG.height(h6) == 4
    end

    @testset "Display" begin
        h6 = HuffmanTree(s6)
        @test shown_string(h6) ==   "HuffmanTree{ACSymbol}(" *
                                        "("*"(0x01, 0.5), " *
                                            "("*"("*"("*"(0x03, 0.1), " *
                                                        "(0x04, 0.09)), " *
                                                    "("*"(0x05, 0.08), " *
                                                        "(0x06, 0.03))), " *
                                                "(0x02, 0.2))))"

        @test shown_plaintext(h6) ==    """
                                        HuffmanTree{ACSymbol}
                                        ├─ ACSymbolNode(0x01, 0.5)
                                        └─ ・
                                           ├─ ・
                                           │  ├─ ・
                                           │  │  ├─ ACSymbolNode(0x03, 0.1)
                                           │  │  └─ ACSymbolNode(0x04, 0.09)
                                           │  └─ ・
                                           │     ├─ ACSymbolNode(0x05, 0.08)
                                           │     └─ ACSymbolNode(0x06, 0.03)
                                           └─ ACSymbolNode(0x02, 0.2)"""
    end

    @testset "Conversions" begin
        h6 = HuffmanTree(s6)
        htable = HuffmanTable(h6)
        @test htable isa ACHuffmanTable
        h6r = HuffmanTree(htable)
        @test shown_plaintext(h6r) ==  """
                                    HuffmanTree{ACSymbol}
                                    ├─ ACSymbolNode(0x01, 0.5)
                                    └─ ・
                                       ├─ ACSymbolNode(0x02, 0.25)
                                       └─ ・
                                          ├─ ・
                                          │  ├─ ACSymbolNode(0x03, 0.0625)
                                          │  └─ ACSymbolNode(0x04, 0.0625)
                                          └─ ・
                                             ├─ ACSymbolNode(0x05, 0.0625)
                                             └─ ACSymbolNode(0x06, 0.0625)"""

    end
end

@testset "HuffmanTable" begin

    @testset "Constructors" begin
        li = fill(0x0, 16)
        li[2] = 1
        li[4] = 2
        dcsymbols = DCSymbol.(0x1:0x3)
        acsymbols = ACSymbol.(0x2:0x4)

        dcht = DCHuffmanTable(li, dcsymbols)
        @test dcht isa DCHuffmanTable
        @test dcht.id === 0x0

        acht = ACHuffmanTable(li, acsymbols, id=0x1)
        @test acht isa ACHuffmanTable
        @test acht.id === 0x1
    end

    @testset "Traits" begin
        dcht = readtest(HuffmanTable, 0xB1)
        @test sizeof(dcht) == 21
        @test length(dcht) == 4
        @test LowLevelJPEG.codelist(dcht) == [code"00", code"01", code"10", code"110"]
    end

    @testset "Display" begin
        dcht = readtest(HuffmanTable, 0xB1)
        @test shown_string(dcht) ==
            "HuffmanTable{DCSymbol}(" *
            "[0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], " *
            "DCSymbol[0x00, 0x05, 0x07, 0x08], id=0)"
        @test shown_plaintext(dcht) == """
                                    4-symbol HuffmanTable{DCSymbol}(id=0):
                                     DCSymbol(0x00)  code"00"
                                     DCSymbol(0x05)  code"01"
                                     DCSymbol(0x07)  code"10"
                                     DCSymbol(0x08)  code"110\""""
    end
end

@testset "HuffmanDecoder" begin

    ht = ACHuffmanTable(UInt8[0, 1, 2, 3, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1],
                        ACSymbol.(0x01:0x0C), id=0x0)
    @test shown_plaintext(ht) ==   """
                                12-symbol HuffmanTable{ACSymbol}(id=0):
                                 ACSymbol(0x01)  code"00"
                                 ACSymbol(0x02)  code"010"
                                 ACSymbol(0x03)  code"011"
                                 ACSymbol(0x04)  code"1000"
                                 ACSymbol(0x05)  code"1001"
                                 ACSymbol(0x06)  code"1010"
                                 ACSymbol(0x07)  code"101100000"
                                 ACSymbol(0x08)  code"1011000010"
                                 ACSymbol(0x09)  code"10110000110"
                                 ACSymbol(0x0a)  code"101100001110"
                                 ACSymbol(0x0b)  code"1011000011110"
                                 ACSymbol(0x0c)  code"1011000011111000\""""

    @testset "Constructors" begin
        @test LowLevelJPEG.HuffmanDecoder(ht) isa LowLevelJPEG.HuffmanDecoder
    end

    @testset "Functions" begin
        d = LowLevelJPEG.HuffmanDecoder(ht)
        @test getcodeindex(d, UInt32(0b0101010101010101) << 16, 2) == 0
        @test getcodeindex(d, UInt32(0b0101010101010101) << 16, 3) == 2
        @test getcodeindex(d, UInt32(0b0101010101010101) << 16, 4) == 2
        @test_throws LowLevelJPEG.BitSequenceError getcodeindex(
            d, UInt32(0b1111111100000000) << 16, 8)
        @test getcodeindex(d, UInt32(0b1011000011111000) << 16, 15) == 0
        @test getcodeindex(d, UInt32(0b1011000011111000) << 16, 16) == 12
        @test getcodeindex(d, UInt32(0b1011000011111000) << 16, 17) == 12
        @test_throws LowLevelJPEG.BitSequenceError getcodeindex(
            d, UInt32(0b1011000011111001) << 16, 16)
    end
end


text:
include("../benchmark/bench_van_der_pol.jl")

@time lc_solver = pre_solve!(make_van_der_pol_lc_solver())
@time sweep!(lc_solver)

@time lc_solver = pre_solve!(make_van_der_pol_lc_solver())
Profile.clear()
@profile sweep!(lc_solver)


text:
using Documenter, MassCommits

makedocs(;
    modules=[MassCommits],
    format=Documenter.HTML(),
    pages=[
        "Home" => "index.md",
    ],
    repo="https://github.com/asinghvi17/MassCommits.jl/blob/{commit}{path}#L{line}",
    sitename="MassCommits.jl",
    authors="Anshul Singhvi",
    assets=String[],
)

deploydocs(;
    repo="github.com/asinghvi17/MassCommits.jl",
)


text:
include("./helpers.jl")

include("./ExploreExpression.jl")
include("./React.jl")
include("./WorkspaceManager.jl")
include("./Notebook.jl")


text:
using AdFem

mmesh = Mesh3(20, 20, 20, 1/20)
xy = gauss_nodes(mmesh)
a = Variable(0.1)
κ = 1/(a+xy[:,1].^2 + xy[:,2].^2 + xy[:,3].^2)
K = compute_fem_laplace_matrix1(κ, mmesh)
rhs = compute_fem_source_term1(ones(get_ngauss(mmesh)), mmesh)
bd = bcnode(mmesh)
K, rhs = impose_Dirichlet_boundary_conditions(K, rhs, bd, zeros(length(bd)))
sol = K\rhs
sess = Session(); init(sess)
SOL = run(sess, sol)

############## Visualization 1
using PyPlot
using DelimitedFiles
idx = falses(mmesh.ndof)
s = 1
for k = 1:21
    for j = 1:21
        for i = 1:21
            if k==11 && j==11
                idx[s] = true
            end
            global s = s + 1
        end
    end
end
close("all")
x0 = LinRange(0,1,21)
plot(x0, readdlm("val.txt")[:], label = "FEniCS")
plot(x0, SOL[idx], "o", label = "AdFem")

legend()
xlabel("x")
ylabel("\$u(x, 0.5, 0.5)\$")
savefig("section_plot_mfem3d.png")

############## Visualization 2
visualize_scalar_on_fem_points(SOL, mmesh)
visualize_mesh(mmesh)


text:
"""
    conceptnet2wv(cptnet, language)

Converts a `ConceptNet` object, `cptnet` to a `WordVectors` object.
The `language` of the word embeddings has to be specified explicitly
as a `Symbol` or `Languages.Language` (Conceptnet embeddings can be
multilingual).
"""
function conceptnet2wv(cptnet::ConceptNet{L,K,E},
                       language::Languages.Language;
                      ) where {L<:Language, K<:AbstractString, E<:AbstractFloat}
    embeddings = cptnet.embeddings[language]
    vector_size = cptnet.width
    vocab_size = length(embeddings)
    vocab = Vector{String}(undef, vocab_size)
    vectors = zeros(E, vector_size, vocab_size)
    for (i, (word, wordvector)) in enumerate(embeddings)
        vocab[i] = word
        vectors[:,i] = wordvector
    end
    wv = WordVectors(vocab, vectors)
end

function conceptnet2wv(cptnet::ConceptNet{L,K,E},
                       language::Symbol;
                      ) where {L<:Language, K<:AbstractString, E<:AbstractFloat}
    conceptnet2wv(cptnet, ConceptnetNumberbatch.LANGUAGES[language])
end

max_stars_repo_name: zgornel/EmbeddingsAnalysis

max_issues_repo_name: zgornel/EmbeddingsAnalysis

max_forks_repo_name: zgornel/EmbeddingsAnalysis


text:
using Keldysh, Test

@testset "branch" begin
  let tmax = 2.0, β = 3.0
    fwd = Branch(forward_branch, tmax)
    back = Branch(backward_branch, tmax)
    imag = Branch(imaginary_branch, β)

    @test fwd.domain == forward_branch
    @test back.domain == backward_branch
    @test imag.domain == imaginary_branch

    @test length(fwd) == tmax
    @test length(back) == tmax
    @test length(imag) == β

    @test fwd(0.0).val == 0.0
    @test fwd(1.0).val == tmax

    @test back(0.0).val == tmax
    @test back(1.0).val == 0.0

    @test imag(0.0).val == 0.0
    @test imag(1.0).val == -1.0im * β
  end
end


text:
using JSON

struct ObservableNode
    id::AbstractString
    name::AbstractString
end


text:
struct Point
    x::Float64
    y::Float64
end
function isLeft(a::Point, b::Point, c::Point)
     return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0
end
function left_points(angle::Float64, shift::Float64, X::Matrix{Float64})
    dydx=tand(angle)
    perp=tand(angle+90)
    meanx = mean(X[1,:])
    meany = mean(X[2,:])
    direction=sign(cosd(angle+90))
    if direction==0.0
        direction=1.0
    end
    shift_x = shift*cosd(angle+90)*direction
    shift_y = shift*sind(angle+90)*direction
    a = Point(meanx+shift_x,meany+shift_y)
    if abs(dydx)<1.0
        dx=1.0
        dy=dydx
    else
        dx=1.0/dydx
        dy=1.0
    end
    b = Point(meanx+shift_x+dx,meany+dy+shift_y)

    n = size(X,2)
    points = [Point(X[1,i],X[2,i]) for i in 1:n]
    are_left = [isLeft(a,b,p) for p in points]
end

function plot_line(angle::Float64, shift::Float64, X::Matrix; kwargs...)
    meanx=mean(X[1,:])
    meany=mean(X[2,:])
    dydx=tand(angle)
    direction=sign(cosd(angle+90))
    if direction==0.0
        direction=1.0
    end
    shift_x = shift*cosd(angle+90)*direction
    shift_y = shift*sind(angle+90)*direction

    xlim=plt.xlim()
    ylim=plt.ylim()
    xlim_arr = Float64[xlim[1],xlim[2]]
    ylim_arr = Float64[ylim[1],ylim[2]]
    if dydx > 1e3
        plt.axvline(meanx+shift_x, color="red"; kwargs...)
    elseif dydx > 10
        plt.plot(meanx+(ylim_arr.-meany.-shift_y)./dydx+shift_x,ylim_arr; color="red", kwargs...)
    else
        plt.plot(xlim_arr,meany+(xlim_arr.-shift_x.-meanx).*dydx+shift_y; color="red", kwargs...)
    end
    plt.xlim(xlim)
    plt.ylim(ylim)
end

function placebo_sentinels(angle::Float64, shift::Float64, X::AbstractMatrix, npoints::Int)
    meanx=mean(X[1,:])
    meany=mean(X[2,:])
    minx,maxx = extrema(X[1,:])
    miny,maxy = extrema(X[2,:])

    dydx=tand(angle)
    direction=sign(cosd(angle+90))
    if direction==0.0
        direction=1.0
    end
    shift_x = shift*cosd(angle+90)*direction
    shift_y = shift*sind(angle+90)*direction

    center_x = meanx + shift_x
    center_y = meany + shift_y

    y_from_minx = center_y + dydx*(minx-center_x)
    y_from_maxx = center_y + dydx*(maxx-center_x)
    x_from_miny = center_x + (miny-center_y)/dydx
    x_from_maxy = center_x + (maxy-center_y)/dydx

    extremes = []
    if miny < y_from_minx < maxy
        push!(extremes, (minx, y_from_minx))
    end
    if miny < y_from_maxx < maxy
        push!(extremes, (maxx, y_from_maxx))
    end
    if minx < x_from_miny < maxx
        push!(extremes, (x_from_miny, miny))
    end
    if minx < x_from_maxy < maxx
        push!(extremes, (x_from_maxy, maxy))
    end
    @assert length(extremes)==2
    x∂ = range(extremes[1][1], stop=extremes[2][1], length=npoints)
    y∂ = range(extremes[1][2], stop=extremes[2][2], length=npoints)
    X∂ = Float64[x∂'; y∂']
    return X∂
end

function prop_left(angle::Float64, shift::Float64, X::Matrix{Float64})
    are_left = left_points(angle, shift, X)
    return mean(are_left)
end

#copy-pasted from http://blog.mmast.net/bisection-method-julia
function bisection(f::Function, a::Number, b::Number;
                   tol::AbstractFloat=1e-5, maxiter::Integer=100)
    fa = f(a)
    fa*f(b) <= 0 || error("No real root in [a,b]")
    i = 0
    local c
    while b-a > tol
        i += 1
        i != maxiter || error("Max iteration exceeded")
        c = (a+b)/2
        fc = f(c)
        if fc == 0
            break
        elseif fa*fc > 0
            a = c  # Root is in the right half of [a,b].
            fa = fc
        else
            b = c  # Root is in the left half of [a,b].
        end
    end
    return c
end

function shift_for_even_split(angle::Float64, X::Matrix)
    minx,maxx = extrema(X[1,:])
    miny,maxy = extrema(X[2,:])
    maxdistance = sqrt( (maxy-miny)^2 + (maxx-minx)^2)
    return bisection(shift -> prop_left(angle,shift,X)-0.5, -maxdistance, maxdistance)
end


text:
export get_symbol_price, get_multisymbol_price, get_multisymbol_data, get_custom_average
"""
    get_symbol_price()

Get the current price of any cryptocurrency in any other currency that you need. If the crypto does not trade directly into the toSymbol requested, BTC will be used for conversion. If the opposite pair trades we invert it (eg.: BTC-XMR)

1. tryConversion: If set to false, it will try to get only direct trading values. This parameter is only valid for e=CCCAGG value [ Default - true]
2. fsym [Required]: The cryptocurrency symbol of interest [ Min length - 1] [ Max length - 30]
3. tsyms [Required]: Comma separated cryptocurrency symbols list to convert into [ Min length - 1] [ Max length - 500]
4. relaxedValidation: Setting this to true will make sure you don't get an error on non trading pairs, they will just be filtered out of the response. [ Default - true]
5. e: The exchange to obtain data from [ Min length - 2] [ Max length - 30] [ Default - cccagg_or_exchange]
6. extraParams: The name of your application (we recommend you send it) [ Min length - 1] [ Max length - 2000] [ Default - NotAvailable]
7. sign: If set to true, the server will sign the requests (by default we don't sign them), this is useful for usage in smart contracts [ Default - false]
"""
function get_symbol_price(fsym::String, tsyms::Array{String,1}; tryConversion::Bool=true, relaxedValidation::Bool=true, e::String="cccagg_or_exchange", extraParams::String="", sign::Bool=false)
    url = build_price_url("single_symbol_price", fsym=fsym, tsyms=tsyms, e=e, tryConversion=tryConversion,
                          relaxedValidation=relaxedValidation, extraParams=extraParams, sign=sign)
    try
        str = make_API_call(url)
        jobj = JSON.Parser.parse(str)
        datadict = jobj
        return datadict
    catch e
        return e
    end
end

"""
    get_multisymbol_price(fsyms::Array{String,1}, tsyms::Array{String,1}; tryConversion::Bool=true, relaxedValidation::Bool=true, e::String="cccagg_or_exchange", extraParams::String="", sign::Bool=false)

Same as single API path but with multiple from symbols.

1. tryConversion: If set to false, it will try to get only direct trading values. This parameter is only valid for e=CCCAGG value [ Default - true]
2. fsyms [Required]: Comma separated cryptocurrency symbols list [ Min length - 1] [ Max length - 300]
3. tsyms [Required]: Comma separated cryptocurrency symbols list to convert into [ Min length - 1] [ Max length - 100]
4. relaxedValidation: Setting this to true will make sure you don't get an error on non trading pairs, they will just be filtered out of the response. [ Default - true]
5. e: The exchange to obtain data from [ Min length - 2] [ Max length - 30] [ Default - cccagg_or_exchange]
6. extraParams: The name of your application (we recommend you send it) [ Min length - 1] [ Max length - 2000] [ Default - NotAvailable]
7. sign: If set to true, the server will sign the requests (by default we don't sign them), this is useful for usage in smart contracts [ Default - false]
"""
function get_multisymbol_price(fsyms::Array{String,1}, tsyms::Array{String,1}; tryConversion::Bool=true, relaxedValidation::Bool=true,
                                e::String="cccagg_or_exchange", extraParams::String="", sign::Bool=false)
    url = build_price_url("multiple_symbol_price", fsyms=fsyms, tsyms=tsyms, e=e, tryConversion=tryConversion,
                          relaxedValidation=relaxedValidation, extraParams=extraParams, sign=sign)
    try
        str = make_API_call(url)
        jobj = JSON.Parser.parse(str)
        datadict = jobj
        return datadict
    catch e
        return e
    end
end

"""
    get_multisymbol_fulldata(fsyms::Array{String,1}, tsyms::Array{String,1}; tryConversion::Bool=true, relaxedValidation::Bool=true, e::String="cccagg_or_exchange", extraParams::String="", sign::Bool=false)

Get all the current trading info (price, vol, open, high, low etc) of any list of cryptocurrencies in any other currency that you need. If the crypto does not trade directly into the toSymbol requested, BTC will be used for conversion.
This API also returns Display values for all the fields. If the opposite pair trades we invert it (eg.: BTC-XMR)

1. tryConversion: If set to false, it will try to get only direct trading values. This parameter is only valid for e=CCCAGG value [ Default - true]
2. fsyms [Required]: Comma separated cryptocurrency symbols list [ Min length - 1] [ Max length - 300]
3. tsyms [Required]: Comma separated cryptocurrency symbols list to convert into [ Min length - 1] [ Max length - 100]
4. relaxedValidation: Setting this to true will make sure you don't get an error on non trading pairs, they will just be filtered out of the response. [ Default - true]
5. e: The exchange to obtain data from [ Min length - 2] [ Max length - 30] [ Default - cccagg_or_exchange]
6. extraParams: The name of your application (we recommend you send it) [ Min length - 1] [ Max length - 2000] [ Default - NotAvailable]
7. sign: If set to true, the server will sign the requests (by default we don't sign them), this is useful for usage in smart contracts [ Default - false]
"""
function get_multisymbol_fulldata(fsyms::Array{String,1}, tsyms::Array{String,1}; tryConversion::Bool=true, relaxedValidation::Bool=true,
                                e::String="cccagg_or_exchange", extraParams::String="", sign::Bool=false)
    url = build_price_url("multiple_symbol_full", fsyms=fsyms, tsyms=tsyms, e=e, tryConversion=tryConversion,
                          relaxedValidation=relaxedValidation, extraParams=extraParams, sign=sign)
    try
        str = make_API_call(url)
        jobj = JSON.Parser.parse(str)
        datadict = jobj
        return datadict
    catch e
        return e
    end
end

"""
    get_custom_average()

Compute the current trading info (price, vol, open, high, low etc) of the requested pair as a volume weighted average based on the exchanges requested.

1. fsym [Required]: The cryptocurrency symbol of interest [ Min length - 1] [ Max length - 30]
2. tsym [Required]: The currency symbol to convert into [ Min length - 1] [ Max length - 30]
3. e [Required]: The exchange to obtain data from [ Min length - 2] [ Max length - 150]
4. extraParams: The name of your application (we recommend you send it) [ Min length - 1] [ Max length - 2000] [ Default - NotAvailable]
5. sign: If set to true, the server will sign the requests (by default we don't sign them), this is useful for usage in smart contracts [ Default - false]
"""
function get_custom_average(fsym::String, tsym::String, e::String; extraParams::String="", sign::Bool=false)
    url = build_price_url("generateAvg", fsym=fsym, tsym=tsym, e=e, extraParams=extraParams, sign=sign)
    try
        str = make_API_call(url)
        jobj = JSON.Parser.parse(str)
        datadict = jobj
        return datadict
    catch e
        return e
    end
end


text:
global INPUT_PROMPT = "julia> "
global INPUT_PROMPT_PREFIX = Base.text_colors[:green]

function update_interface(interface)
    main_mode = interface.modes[1]
    main_mode.prompt_prefix = INPUT_PROMPT_PREFIX
    main_mode.prompt = INPUT_PROMPT
end

function input_prompt!(s::Union{String, Function}, col = :green)
    global INPUT_PROMPT_PREFIX = get(Base.text_colors, Symbol(col), "\e[2m")
    global INPUT_PROMPT = isa(s, String) ? s * " " : () -> string(s(), " ")
    isdefined(Base, :active_repl) && isdefined(Base.active_repl, :interface) && update_interface(Base.active_repl.interface)
    return
end

global OUTPUT_PROMPT = ""
global OUTPUT_PROMPT_PREFIX = ""

function output_prompt!(s::Union{String, Function}, col = :red)
    global OUTPUT_PROMPT_PREFIX = string("\e[1m", get(Base.text_colors, Symbol(col), Base.text_colors[:red]))
    global OUTPUT_PROMPT = s
    return
end


text:
#!/usr/bin/env julia

using Luxor
using Test

using Random
Random.seed!(42)

function drawctrlpoints(bezpath, r)
    @layer begin
        for seg in bezpath
            circle.(seg, r, :fill)
        end
    end
end

function bezpathtopolytest(fname)

    ng = ngon(O, 300, 5, vertices=true)

    bprough = makebezierpath(ng, smoothing=0.5)
    bpsmooth = makebezierpath(ng, smoothing=0.25)

    @test length(bprough) == 5
    @test typeof(bprough[1][1]) == Luxor.Point

    @test length(bpsmooth) == 5
    @test typeof(bpsmooth[1][1]) == Luxor.Point

    p1 = bezierpathtopoly(bprough)
    p2 = bezierpathtopoly(bpsmooth)

    @test length(p1) == 55
    @test typeof(p1[1]) == Luxor.Point
    @test length(p2) == 55
    @test typeof(p2[1]) == Luxor.Point

    Random.seed!(3)
    setline(0.01)
    currentwidth = 800
    currentheight = 800
    Drawing(currentwidth, currentheight, fname)
    origin()
    background("white")
    setopacity(0.5)

    # draw original polygon
    sethue("purple")
    prettypoly(ng, :stroke, close=true, () -> circle(O, 26, :fill))

    # draw the rough (non-smoothed) bezierpath
    sethue("green")
    drawctrlpoints(bprough, 15)
    drawbezierpath(bprough, :stroke)

    # draw the smoother bezierpath
    sethue("blue")
    drawctrlpoints(bpsmooth, 10)
    drawbezierpath(bpsmooth, :stroke)

    sethue("orange")
    prettypoly(p1, :stroke, () -> circle(O, 6, :fill))

    @test 254257 < polyarea(p1) < 254258
    @test 234992 < polyarea(p2) < 234993
    @test 213987 < polyarea(ng) < 213988

    @test finish() == true

end

fname = "bezpathtopolytest.svg"
bezpathtopolytest(fname)

println("...finished bezier path conversion tests: output in $(fname)")


text:
using LinearAlgebra, Polynomials
@testset "graphops" begin
    graph = Compgraph()

    # Graph evaluation.

    # Instructions for  (I + 2*(I + A/5))^{-1} (I + 1/2 *(I + A/5)^2)
    add_lincomb!(graph, :C, 1.0, :I, 1 / 5, :A)
    add_mult!(graph, :Csqr, :C, :C)
    add_lincomb!(graph, :N, 1.0, :I, 1 / 2, :Csqr)
    add_lincomb!(graph, :D, 1.0, :I, 2, :C)
    add_ldiv!(graph, :out, :D, :N)
    add_output!(graph, :out)

    A = 0.3
    E = eval_graph(graph, A)
    Z = (I + 2 * (I + A / 5)) \ (I + 1 / 2 * (I + A / 5)^2)
    @test Z ≈ E

    A = [0.5; 0.4]
    E = eval_graph(graph, A)
    Z = zero(A)
    for i = 1:2
        a = A[i]
        Z[i] = (I + 2 * (I + a / 5)) \ (I + 1 / 2 * (I + a / 5)^2)
    end
    @test Z ≈ E

    A = [0.4 0.2; 1.1 0.3]
    E = eval_graph(graph, A)
    Z = (I + 2 * (I + A / 5)) \ (I + 1 / 2 * (I + A / 5)^2)
    @test Z ≈ E

    # Node removal.
    del_node!(graph, :D) #Remove rational part
    del_output!(graph, :out)
    @test isempty(graph.outputs)
    del_node!(graph, :out)
    add_output!(graph, :N)
    rename_node!(graph, :N, :N)
    rename_node!(graph, :N, :N_new)
    A = Polynomial("x")
    E = eval_graph(graph, A)
    Z = (1 + 1 / 2 * (1 + A / 5)^2)
    @test Z ≈ E
    del_output!(graph, :N_new)
    @test isempty(graph.outputs)

    # Valid names and manipulation of the output list
    names =
        [:Acoeff_type, :coeff1A, :Bcoeff2, :My_output, :output1_My, :output1MY2]
    for name in names
        add_lincomb!(graph, name, 1.0, :I, 1 / 5, :A)
        add_mult!(graph, name, :I, :A)
        add_ldiv!(graph, name, :D, :N)
        add_output!(graph, name)
    end

    # Clearance of output nodes.
    clear_outputs!(graph)
    @test isempty(graph.outputs)

    # Node renaming
    graph = Compgraph()
    add_lincomb!(graph, :AI, 2.0, :A, 2.0, :I)
    add_mult!(graph, :Pout, :AI, :A)
    add_output!(graph, :Pout)

    graph1 = deepcopy(graph)
    rename_node!(graph1, :AI, :B)
    @test eval_graph(graph1, A) == eval_graph(graph, A)

    graph1 = deepcopy(graph)
    rename_node!(graph1, :Pout, :B)
    @test eval_graph(graph1, A) == eval_graph(graph, A)

    graph1 = deepcopy(graph)
    rename_node!(graph1, :A, :A2tmp)
    add_mult!(graph1, :A2tmp, :A, :A)
    A = [0.4 0.2; 1.1 0.3]
    @test eval_graph(graph1, A) == eval_graph(graph, A^2)

    # Input kwarg to eval_graph.
    graph1 = deepcopy(graph)
    new_input = :B
    rename_node!(graph, :A, new_input)
    @test eval_graph(graph1, A) == eval_graph(graph, A, input = new_input)

    # Removal of output node
    del_output!(graph, :Pout)
    @test isempty(graph.outputs)

    # Test extract_sum on graph for the function:
    # T := (I + 2*A + 3*A^2)
    # U  := A^3 * T
    # V  := 3*T + 4*A^3 + 5*A^4
    # Z  := (2*U+V) \ (U-2*V)
    # where Z is the output node
    graph = Compgraph(Float64)
    add_mult!(graph, :A2, :A, :A)
    add_mult!(graph, :A3, :A, :A2)
    add_mult!(graph, :A4, :A2, :A2)
    add_lincomb!(graph, :T0, 1.0, :I, 2.0, :A)
    add_lincomb!(graph, :T, 1.0, :T0, 3.0, :A2)
    add_mult!(graph, :U, :A3, :T)
    add_lincomb!(graph, :V1, 3.0, :T, 4.0, :A3)
    add_lincomb!(graph, :V, 1.0, :V1, 5.0, :A4)
    add_lincomb!(graph, :LHS, 2.0, :U, 3.0, :V)
    add_lincomb!(graph, :RHS, 3.0, :U, -2.0, :V)
    add_ldiv!(graph, :Z, :RHS, :LHS)
    add_output!(graph, :Z)

    Z = extract_sums(graph)
    R = [
        ([1.0, 2.0, 3.0], [:I, :A, :A2], [:T0, :T])
        ([3.0, 4.0, 5.0], [:T, :A3, :A4], [:V1, :V])
        ([2.0, 3.0], [:U, :V], [:LHS])
        ([3.0, -2.0], [:U, :V], [:RHS])
    ]
    @test all(map(x -> x in R, Z)) && all(map(x -> x in Z, R))
end


text:
# # [Lotka-Volterra Model](@id predation_example)
#
#md # [![](https://img.shields.io/badge/show-nbviewer-579ACA.svg)](@__NBVIEWER_ROOT_URL__/examples/predation/lotka-volterra.ipynb)

using AlgebraicPetri

using Petri
using OrdinaryDiffEq
using Plots

using Catlab
using Catlab.Theories
using Catlab.Programs
using Catlab.CategoricalAlgebra.ShapeDiagrams
using Catlab.WiringDiagrams
using Catlab.Graphics

display_wd(ex) = to_graphviz(ex, orientation=LeftToRight, labels=true);

# #### Step 1: Define the building block Petri nets needed to construct the model

birth_petri = PetriCospan([1], Petri.Model([1], [(Dict(1=>1), Dict(1=>2))]), [1]);
Graph(decoration(birth_petri))
#-
predation_petri = PetriCospan([1,2], Petri.Model(1:2, [(Dict(1=>1,2=>1), Dict(2=>1.15))]), [2]);
Graph(decoration(predation_petri))
#-
death_petri = PetriCospan([1], Petri.Model([1], [(Dict(1=>1), Dict{Int,Int}())]), [1]);
Graph(decoration(death_petri))

# #### Step 2: Define a presentation of the free biproduct category
# that encodes the domain specific information

@present Predation(FreeBiproductCategory) begin
    prey::Ob
    predator::Ob
    birth::Hom(prey,prey)
    predation::Hom(prey⊗predator,predator)
    death::Hom(predator,predator)
end;

rabbits,wolves,birth,predation,death = generators(Predation);

F(ex) = functor((PetriCospanOb, PetriCospan), ex, generators=Dict(
                 rabbits=>PetriCospanOb(1),wolves=>PetriCospanOb(1),
                 birth=>birth_petri, predation=>predation_petri, death=>death_petri));

# #### Step 3: Generate models using the hom expression or program notations

lotka_volterra = (birth ⊗ id(wolves)) ⋅ predation ⋅ death
lotka_petri = decoration(F(lotka_volterra))
display_wd(lotka_volterra)
#-
Graph(lotka_petri)

# Generate appropriate vector fields, define parameters, and visualize solution

u0 = [40, 2];
p = [4.0, 1.0, 2.0];
prob = ODEProblem(lotka_petri,u0,(0.0,8.0),p);
sol = solve(prob,Tsit5(),abstol=1e-6);
plot(sol)

# There is also a second syntax that is easier to write for programmers
# than the hom expression syntax. Here is an example of the same model
# as before along with a test of equivalency

lotka_volterra2 = @program Predation (r::prey, w::predator) begin
  r_2 = birth(r)
  w_2 = predation(r_2, w)
  return death(w_2)
end
lotka_petri2 = decoration(F(to_hom_expr(FreeBiproductCategory, lotka_volterra2)))
lotka_petri == lotka_petri2

# #### Step 4: Extend your presentation to handle more complex phenomena
# such as a small food chain

@present DualPredation <: Predation begin
    Predator::Ob
    Predation::Hom(predator⊗Predator,Predator)
    Death::Hom(Predator,Predator)
end;

fish,Fish,Shark,birth,predation,death,Predation,Death = generators(DualPredation);

F(ex) = functor((PetriCospanOb, PetriCospan), ex, generators=Dict(
                 fish=>PetriCospanOb(1),Fish=>PetriCospanOb(1),
                 birth=>birth_petri, predation=>predation_petri, death=>death_petri,
                 Shark=>PetriCospanOb(1),Predation=>predation_petri, Death=>death_petri));

# Define a new model where fish are eaten by Fish which are then eaten by Sharks

dual_lv = @program DualPredation (fish::prey, Fish::predator, Shark::Predator) begin
  f_2 = birth(fish)
  F_2 = predation(f_2, Fish)
  F_3 = death(F_2)
  S_2 = Predation(F_3, Shark)
  S_3 = Death(S_2)
end
display_wd(dual_lv)
#-
dual_lv_petri = decoration(F(to_hom_expr(FreeBiproductCategory, dual_lv)))
Graph(dual_lv_petri)

# Generate a new solver, provide parameters, and analyze results

u0 = [40, 2, 1];
p = [4.0, 1.0, 2.0, 2.5, 1.5];
prob = ODEProblem(dual_lv_petri,u0,(0.0,8.0),p);
sol = solve(prob,Tsit5(),abstol=1e-6);
plot(sol)