text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

struct TrustedIdProvidersApi <: SwaggerApi
    client::Swagger.Client
end

"""

Creates or updates the specified trusted identity provider. During update, the trusted identity provider with the specified name will be replaced with this new provider
Param: subscriptionId::String (required)
Param: resourceGroupName::String (required)
Param: accountName::String (required)
Param: trustedIdProviderName::String (required)
Param: parameters::CreateOrUpdateTrustedIdProviderParameters (required)
Param: api_version::String (required)
Return: TrustedIdProvider
"""
function _swaggerinternal_trustedIdProvidersCreateOrUpdate(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, parameters, api_version::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", TrustedIdProvider, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DataLakeStore/accounts/{accountName}/trustedIdProviders/{trustedIdProviderName}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "accountName", accountName)  # type String
    Swagger.set_param(_ctx.path, "trustedIdProviderName", trustedIdProviderName)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function trustedIdProvidersCreateOrUpdate(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, parameters, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersCreateOrUpdate(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, parameters, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function trustedIdProvidersCreateOrUpdate(_api::TrustedIdProvidersApi, response_stream::Channel, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, parameters, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersCreateOrUpdate(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, parameters, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Deletes the specified trusted identity provider from the specified Data Lake Store account
Param: subscriptionId::String (required)
Param: resourceGroupName::String (required)
Param: accountName::String (required)
Param: trustedIdProviderName::String (required)
Param: api_version::String (required)
Return: Nothing
"""
function _swaggerinternal_trustedIdProvidersDelete(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DataLakeStore/accounts/{accountName}/trustedIdProviders/{trustedIdProviderName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "accountName", accountName)  # type String
    Swagger.set_param(_ctx.path, "trustedIdProviderName", trustedIdProviderName)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function trustedIdProvidersDelete(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersDelete(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function trustedIdProvidersDelete(_api::TrustedIdProvidersApi, response_stream::Channel, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersDelete(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets the specified Data Lake Store trusted identity provider.
Param: subscriptionId::String (required)
Param: resourceGroupName::String (required)
Param: accountName::String (required)
Param: trustedIdProviderName::String (required)
Param: api_version::String (required)
Return: TrustedIdProvider
"""
function _swaggerinternal_trustedIdProvidersGet(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", TrustedIdProvider, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DataLakeStore/accounts/{accountName}/trustedIdProviders/{trustedIdProviderName}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "accountName", accountName)  # type String
    Swagger.set_param(_ctx.path, "trustedIdProviderName", trustedIdProviderName)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function trustedIdProvidersGet(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersGet(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function trustedIdProvidersGet(_api::TrustedIdProvidersApi, response_stream::Channel, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersGet(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Lists the Data Lake Store trusted identity providers within the specified Data Lake Store account.
Param: subscriptionId::String (required)
Param: resourceGroupName::String (required)
Param: accountName::String (required)
Param: api_version::String (required)
Return: TrustedIdProviderListResult
"""
function _swaggerinternal_trustedIdProvidersListByAccount(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, api_version::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", TrustedIdProviderListResult, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DataLakeStore/accounts/{accountName}/trustedIdProviders", ["azure_auth"])
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "accountName", accountName)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function trustedIdProvidersListByAccount(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersListByAccount(_api, subscriptionId, resourceGroupName, accountName, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function trustedIdProvidersListByAccount(_api::TrustedIdProvidersApi, response_stream::Channel, subscriptionId::String, resourceGroupName::String, accountName::String, api_version::String; _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersListByAccount(_api, subscriptionId, resourceGroupName, accountName, api_version; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Updates the specified trusted identity provider.
Param: subscriptionId::String (required)
Param: resourceGroupName::String (required)
Param: accountName::String (required)
Param: trustedIdProviderName::String (required)
Param: api_version::String (required)
Param: parameters::UpdateTrustedIdProviderParameters
Return: TrustedIdProvider
"""
function _swaggerinternal_trustedIdProvidersUpdate(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; parameters=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", TrustedIdProvider, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.DataLakeStore/accounts/{accountName}/trustedIdProviders/{trustedIdProviderName}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "accountName", accountName)  # type String
    Swagger.set_param(_ctx.path, "trustedIdProviderName", trustedIdProviderName)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function trustedIdProvidersUpdate(_api::TrustedIdProvidersApi, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; parameters=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersUpdate(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, api_version; parameters=parameters, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function trustedIdProvidersUpdate(_api::TrustedIdProvidersApi, response_stream::Channel, subscriptionId::String, resourceGroupName::String, accountName::String, trustedIdProviderName::String, api_version::String; parameters=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_trustedIdProvidersUpdate(_api, subscriptionId, resourceGroupName, accountName, trustedIdProviderName, api_version; parameters=parameters, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export trustedIdProvidersCreateOrUpdate, trustedIdProvidersDelete, trustedIdProvidersGet, trustedIdProvidersListByAccount, trustedIdProvidersUpdate


text:
function sque(r)
    if startswith(r, "
")
        ra = replace(r, "
" => "")
        rb = replace(ra, "	" => ",")
        rc = replace(rb, "
" => "")
        rc
    else
        ""
    end
end

function isnotblank(d)
    if d == ""
        false
    else
        true
    end
end

function doing(name)
    f = open("" * name * ".ehtml", "r")
    data = read(f, String)
    close(f)
    lines = split(data, "\n")
    ret = map(x -> sque(x), lines)
    reta = filter(isnotblank, ret)
    ans = join(reta, "\n")
    #   print(ans)
    head = "震度計番号,震度観測点名称,x,y,震度,最大加速度NS[cm/s/s],最大加速度EW[cm/s/s],最大加速度UD[cm/s/s],最大加速度3成分合成[cm/s/s],最大速度NS[cm/s],最大速度EW[cm/s],最大速度UD[cm/s],最大速度3成分合成[cm/s],最大変位NS[cm],最大変位EW[cm],最大変位UD[cm],最大変位3成分合成[cm]"
    body = [head,ans]
    body_txt = join(body, "\n")
    w = open("" * name * ".csv", "w")
    write(w, body_txt)
    close(w)
end

map(x -> doing(x), ARGS)

ext: jl


text:
import Printf: @printf
getGeneratorStatus(mcp) = icxx"$(mcp)->getGeneratorStatus();"
getSimulatorStatus(mcp) = icxx"$(mcp)->getSimulatorStatus();"
getPDG(mcp) = icxx"$(mcp)->getPDG();"

getParents(mcp) = icxx"$(mcp)->getParents();"

function printMCParticle(mcp)
    id = getPDG(mcp)
    genStatus = getMCPGenStatus(mcp)
    p4 = getP4(mcp)
    @printf("%-7d%-3d%s\n", id, genStatus, p4)
end


text:
using ArgCheck
using Dates
using Tables

function read(
    source::IO;
    lower::Union{Nothing, TimeLike}=nothing,
    upper::Union{Nothing, TimeLike}=nothing
)::Vector{<:NamedTuple}
    metadata = Base.read(source, Header.TeaFileMetadata)
    return Body.read_items(source, metadata; lower=lower, upper=upper)
end

function read(
    source::AbstractString;
    lower::Union{Nothing, TimeLike}=nothing,
    upper::Union{Nothing, TimeLike}=nothing
)::Vector{<:NamedTuple}
    return open(source; read=true) do io
        read(io; lower=lower, upper=upper)
    end
end

function _create_metadata_from_schema(
    @nospecialize(schema::Tables.Schema),
    item_type_name::AbstractString,
    content_description::AbstractString,
    name_values::AbstractVector{Header.NameValue}
)::Header.TeaFileMetadata
    # From the schema, create a NamedTuple which has the correct field names and types. We
    # can then use the internal API.
    item_type = NamedTuple{schema.names, Tuple{schema.types...}}
    return Header.create_metadata_julia_time(
        item_type;
        item_type_name=item_type_name,
        content_description=content_description,
        name_values=name_values
    )
end

function write(
    destination::AbstractString,
    table;
    append_only::Bool=true,
    total_rewrite::Bool=false,
    item_type_name::AbstractString="",
    content_description::AbstractString="",
    name_values::AbstractVector{Header.NameValue}=Header.NameValue[]
)
    @argcheck Tables.istable(table)

    create_new_file = total_rewrite || !isfile(destination)

    if isfile(destination) && create_new_file
        # The destination is a file, but we wish to rewrite it.
        rm(destination)
    end

    # TODO use append_only & create_new_file
    @assert create_new_file
    @assert append_only

    metadata = _create_metadata_from_schema(
        Tables.schema(table),
        item_type_name,
        content_description,
        name_values
    )

    # TODO We could avoid multiple calls to write if we know that the whole table is in the
    # correct binary form already.
    # All we need is to have every row accessible as a namedtuple for writing. Do this
    # prior to opening the file in case it takes a non-trivial amount of time.
    row_iterator = Tables.namedtupleiterator(table)

    # Perform writing
    # TODO check item ordering if there is at least one time column.
    open(destination; write=true) do io
        Base.write(io, metadata)
        for row in row_iterator
            Base.write(io, [row])
        end
    end
end


text:
# accept/reject computed integration step, propose next step, and apply callbacks
function OrdinaryDiffEq.loopfooter!(integrator::DDEIntegrator)
  # apply same logic as in OrdinaryDiffEq
  OrdinaryDiffEq._loopfooter!(integrator)

  if !integrator.accept_step
    # reset ODE integrator to the cached values if the last step failed
    move_back_ode_integrator!(integrator)

    # track propagated discontinuities for dependent delays
    if integrator.opts.adaptive && integrator.iter > 0 && has_dependent_lags(integrator)
      track_propagated_discontinuities!(integrator)
    end
  end

  nothing
end

# save current state of the integrator
function DiffEqBase.savevalues!(integrator::HistoryODEIntegrator, force_save = false,
                                reduce_size = false)::Tuple{Bool,Bool}
  integrator.saveiter += 1
  # TODO: save history only for a subset of components
  copyat_or_push!(integrator.sol.t,integrator.saveiter,integrator.t)
  copyat_or_push!(integrator.sol.u, integrator.saveiter, integrator.u)

  integrator.saveiter_dense += 1
  copyat_or_push!(integrator.sol.k, integrator.saveiter_dense, integrator.k)

  if iscomposite(integrator.alg)
    copyat_or_push!(integrator.sol.alg_choice, integrator.saveiter, integrator.cache.current)
  end

  true, true
end

function DiffEqBase.savevalues!(integrator::DDEIntegrator, force_save = false,
                                reduce_size = false)::Tuple{Bool,Bool}
  ode_integrator = integrator.integrator

  # update time of ODE integrator (can be slightly modified (< 10ϵ) because of time stops)
  # integrator.EEst has unitless type of integrator.t
  if typeof(integrator.EEst) <: AbstractFloat
    if ode_integrator.t != integrator.t
      abs(integrator.t - ode_integrator.t) < 10eps(integrator.t) ||
        error("unexpected time discrepancy detected")

      ode_integrator.t = integrator.t
      ode_integrator.dt = ode_integrator.t - ode_integrator.tprev
    end
  end

  # if forced, then the user or an event changed the state u directly.
  if force_save
    if isinplace(integrator.sol.prob)
      ode_integrator.u .= integrator.u
    else
      ode_integrator.u = integrator.u
    end
  end

  # update history
  saved, savedexactly = DiffEqBase.savevalues!(ode_integrator, force_save,
                                               false) # reduce_size = false

  # check that history was actually updated
  saved || error("dense history could not be updated")

  # update prev2_idx to indices of tprev and u(tprev) in solution
  # allows reset of ODE integrator (and hence history function) to the last
  # successful time step after failed steps
  integrator.prev2_idx = integrator.prev_idx

  # cache dt of interval [tprev, t] of ODE integrator since it can only be retrieved by
  # a possibly incorrect subtraction
  # NOTE: does not interfere with usual use of dtcache for non-adaptive methods since ODE
  # integrator is only used for inter- and extrapolation of future values and saving of
  # the solution but does not affect the size of time steps
  ode_integrator.dtcache = ode_integrator.dt

  # update solution
  OrdinaryDiffEq._savevalues!(integrator, force_save, reduce_size)
end

# clean up the solution of the integrator
function DiffEqBase.postamble!(integrator::HistoryODEIntegrator)
  if integrator.saveiter == 0 || integrator.sol.t[integrator.saveiter] != integrator.t
    integrator.saveiter += 1
    copyat_or_push!(integrator.sol.t, integrator.saveiter, integrator.t)
    copyat_or_push!(integrator.sol.u, integrator.saveiter, integrator.u)

    integrator.saveiter_dense +=1
    copyat_or_push!(integrator.sol.k, integrator.saveiter_dense, integrator.k)

    if iscomposite(integrator.alg)
      copyat_or_push!(integrator.sol.alg_choice, integrator.saveiter, integrator.cache.current)
    end
  end

  resize!(integrator.sol.t, integrator.saveiter)
  resize!(integrator.sol.u, integrator.saveiter)
  resize!(integrator.sol.k, integrator.saveiter_dense)

  nothing
end

function DiffEqBase.postamble!(integrator::DDEIntegrator)
  # clean up solution of the ODE integrator
  DiffEqBase.postamble!(integrator.integrator)

  # clean solution of the DDE integrator
  OrdinaryDiffEq._postamble!(integrator)
end

# perform next integration step
function OrdinaryDiffEq.perform_step!(integrator::DDEIntegrator)
  @unpack cache, history = integrator

  # reset boolean which indicates if the history function was evaluated at a time point
  # past the final point of the current solution
  history.isout = false

  # perform always at least one calculation of the stages
  OrdinaryDiffEq.perform_step!(integrator, cache)

  # if the history function was evaluated at time points past the final time point of the
  # solution, i.e. returned extrapolated values, continue with a fixed-point iteration
  if history.isout
    # perform fixed-point iteration
    OrdinaryDiffEq.nlsolve!(integrator.fpsolver, integrator)
  end

  # update ODE integrator to next time interval together with correct interpolation
  advance_or_update_ode_integrator!(integrator)

  nothing
end

# initialize the integrator
function OrdinaryDiffEq.initialize!(integrator::DDEIntegrator)
  ode_integrator = integrator.integrator

  # initialize the cache
  OrdinaryDiffEq.initialize!(integrator, integrator.cache)

  # copy interpolation data to the ODE integrator
  @inbounds for i in 1:length(integrator.k)
    copyat_or_push!(ode_integrator.k, i, integrator.k[i])
  end

  nothing
end

# signal the integrator that state u was modified
function DiffEqBase.u_modified!(integrator::DDEIntegrator, bool::Bool)
  integrator.u_modified = bool
end

# return next integration time step
DiffEqBase.get_proposed_dt(integrator::DDEIntegrator) = integrator.dtpropose

# set next integration time step
function DiffEqBase.set_proposed_dt!(integrator::DDEIntegrator, dt)
  integrator.dtpropose = dt
  nothing
end

# obtain caches
DiffEqBase.get_tmp_cache(integrator::DDEIntegrator) =
  get_tmp_cache(integrator, integrator.alg, integrator.cache)
DiffEqBase.user_cache(integrator::DDEIntegrator) = user_cache(integrator.cache)
DiffEqBase.u_cache(integrator::DDEIntegrator) = u_cache(integrator.cache)
DiffEqBase.du_cache(integrator::DDEIntegrator) = du_cache(integrator.cache)
DiffEqBase.full_cache(integrator::DDEIntegrator) = full_cache(integrator.cache)

# change number of components
Base.resize!(integrator::DDEIntegrator, i::Int) = resize!(integrator, integrator.cache, i)
function Base.resize!(integrator::DDEIntegrator, cache, i)
  # resize ODE integrator (do only have to care about u and k)
  ode_integrator = integrator.integrator
  resize!(ode_integrator.u, i)
  for k in ode_integrator.k
    resize!(k, i)
  end

  # resize DDE integrator
  for c in full_cache(cache)
    resize!(c, i)
  end
  OrdinaryDiffEq.resize_nlsolver!(integrator, i)
  OrdinaryDiffEq.resize_J_W!(cache, integrator, i)
  resize_non_user_cache!(integrator, cache, i)
  resize_fpsolver!(integrator, i)
  nothing
end

DiffEqBase.resize_non_user_cache!(integrator::DDEIntegrator, cache, i) = nothing

function DiffEqBase.resize_non_user_cache!(integrator::DDEIntegrator,
                                           cache::RosenbrockMutableCache, i)
  cache.J = similar(cache.J, i, i)
  cache.W = similar(cache.W, i, i)
  cache.jac_config = DiffEqBase.resize_jac_config!(cache.jac_config, i)
  cache.grad_config = OrdinaryDiffEq.resize_grad_config!(cache.grad_config, i)
  nothing
end

# delete component(s)
function Base.deleteat!(integrator::DDEIntegrator, idxs)
  # delete components of ODE integrator (do only have to care about u and k)
  ode_integrator = integrator.integrator
  deleteat!(ode_integrator.u, idxs)
  for k in ode_integrator.k
    deleteat!(k, idxs)
  end

  # delete components of DDE integrator
  for c in full_cache(integrator)
    deleteat!(c, idxs)
  end
  deleteat_non_user_cache!(integrator, integrator.cache, i)
end

function DiffEqBase.deleteat_non_user_cache!(integrator::DDEIntegrator, cache, idxs)
  i = length(integrator.u)
  resize_non_user_cache!(integrator, cache, i)
end

# add component(s)
function DiffEqBase.addat!(integrator::DDEIntegrator, idxs)
  # add components to ODE integrator (do only have to care about u and k)
  ode_integrator = integrator.integrator
  addat!(ode_integrator.u, idxs)
  for k in ode_integrator.k
    addat!(k, idxs)
  end

  # add components to DDE integrator
  for c in full_cache(integrator)
    addat!(c, idxs)
  end
  addat_non_user_cache!(integrator, integrator.cache, idxs)
end

function DiffEqBase.addat_non_user_cache!(integrator::DDEIntegrator, cache, idxs)
  i = length(integrator.u)
  resize_non_user_cache!(integrator, cache, i)
end

# error check
DiffEqBase.last_step_failed(integrator::DDEIntegrator) =
  integrator.last_stepfail && !integrator.opts.adaptive

# terminate integration
function DiffEqBase.terminate!(integrator::DDEIntegrator, retcode = :Terminated)
  integrator.sol = DiffEqBase.solution_new_retcode(integrator.sol, retcode)
  integrator.opts.tstops.valtree = typeof(integrator.opts.tstops.valtree)()
  nothing
end

# integrator can be reinitialized
DiffEqBase.has_reinit(::HistoryODEIntegrator) = true
DiffEqBase.has_reinit(integrator::DDEIntegrator) = true

function DiffEqBase.reinit!(integrator::HistoryODEIntegrator, u0 = integrator.sol.prob.u0;
                            t0 = integrator.sol.prob.tspan[1],
                            tf = integrator.sol.prob.tspan[end],
                            erase_sol = true)
  # reinit initial values of the integrator
  if isinplace(integrator.sol.prob)
    recursivecopy!(integrator.u, u0)
    recursivecopy!(integrator.uprev, integrator.u)
  else
    integrator.u = u0
    integrator.uprev = integrator.u
  end
  integrator.t = t0
  integrator.tprev = t0
  integrator.dt = zero(integrator.dt)
  integrator.dtcache = zero(integrator.dtcache)

  # erase solution
  if erase_sol
    # resize vectors in solution
    resize!(integrator.sol.u, 1)
    resize!(integrator.sol.t, 1)
    resize!(integrator.sol.k, 1)
    iscomposite(integrator.alg) && resize!(integrator.sol.alg_choice, 1)

    # save initial values
    copyat_or_push!(integrator.sol.t, 1, integrator.t)
    copyat_or_push!(integrator.sol.u, 1, integrator.u)

    # reset iteration counter
    integrator.saveiter = 1
  end

  nothing
end

"""
    reinit!(integrator::DDEIntegrator[, u0 = integrator.sol.prob.u0;
            t0 = integrator.sol.prob.tspan[1],
            tf = integrator.sol.prob.tspan[2],
            erase_sol = true,
            kwargs...])

Reinitialize `integrator` with (optionally) different initial state `u0`, different
integration interval from `t0` to `tf`, and erased solution if `erase_sol = true`.
"""
function DiffEqBase.reinit!(integrator::DDEIntegrator, u0 = integrator.sol.prob.u0;
                            t0 = integrator.sol.prob.tspan[1],
                            tf = integrator.sol.prob.tspan[end],
                            erase_sol = true,
                            tstops = integrator.opts.tstops_cache,
                            saveat = integrator.opts.saveat_cache,
                            d_discontinuities = integrator.opts.d_discontinuities_cache,
                            order_discontinuity_t0 = t0 == integrator.sol.prob.tspan[1] && u0 == integrator.sol.prob.u0 ? integrator.order_discontinuity_t0 : 0,
                            reset_dt = iszero(integrator.dtcache) && integrator.opts.adaptive,
                            reinit_callbacks = true, initialize_save = true,
                            reinit_cache = true)
  # reinit history
  reinit!(integrator.integrator, u0; t0 = t0, tf = tf, erase_sol = true)

  # reinit initial values of the integrator
  if isinplace(integrator.sol.prob)
    recursivecopy!(integrator.u, u0)
    recursivecopy!(integrator.uprev, integrator.u)
  else
    integrator.u = u0
    integrator.uprev = integrator.u
  end

  if OrdinaryDiffEq.alg_extrapolates(integrator.alg)
    if isinplace(integrator.sol.prob)
      recursivecopy!(integrator.uprev2, integrator.uprev)
    else
      integrator.uprev2 = integrator.uprev
    end
  end
  integrator.t = t0
  integrator.tprev = t0

  # reinit time stops, time points at which solution is saved, and discontinuities
  maximum_order = OrdinaryDiffEq.alg_maximum_order(integrator.alg)
  tType = typeof(integrator.t)
  tstops_internal, saveat_internal, d_discontinuities_internal =
    OrdinaryDiffEq.tstop_saveat_disc_handling(tstops, saveat, d_discontinuities,
                                              (tType(t0), tType(tf)),
                                              order_discontinuity_t0, maximum_order,
                                              integrator.sol.prob.constant_lags,
                                              integrator.sol.prob.neutral)

  integrator.opts.tstops = tstops_internal
  integrator.opts.saveat = saveat_internal
  integrator.opts.d_discontinuities = d_discontinuities_internal

  # update order of initial discontinuity
  integrator.order_discontinuity_t0 = order_discontinuity_t0

  # erase solution
  if erase_sol
    # resize vectors in solution
    resize_start = integrator.opts.save_start ? 1 : 0
    resize!(integrator.sol.u, resize_start)
    resize!(integrator.sol.t, resize_start)
    resize!(integrator.sol.k, resize_start)
    iscomposite(integrator.alg) && resize!(integrator.sol.alg_choice, resize_start)
    integrator.sol.u_analytic !== nothing && resize!(integrator.sol.u_analytic, 0)

    # save initial values
    if integrator.opts.save_start
      copyat_or_push!(integrator.sol.t, 1, integrator.t)
      if integrator.opts.save_idxs === nothing
        copyat_or_push!(integrator.sol.u, 1, integrator.u)
      else
        u_initial = integrator.u[integrator.opts.save_idxs]
        copyat_or_push!(integrator.sol.u, 1, u_initial, Val{false})
      end
    end

    # reset iteration counter
    integrator.saveiter = resize_start

    # erase array of tracked discontinuities
    if order_discontinuity_t0 ≤ OrdinaryDiffEq.alg_maximum_order(integrator.alg)
      resize!(integrator.tracked_discontinuities, 1)
      integrator.tracked_discontinuities[1] = Discontinuity(integrator.tdir * integrator.t, order_discontinuity_t0)
    else
      resize!(integrator.tracked_discontinuities, 0)
    end

    # reset history counters
    integrator.prev_idx = 1
    integrator.prev2_idx = 1
  end

  # reset integration counters
  integrator.iter = 0
  integrator.success_iter = 0

  # full re-initialize the PI in timestepping
  integrator.qold = integrator.opts.qoldinit
  integrator.q11 = one(integrator.t)
  integrator.erracc = one(integrator.erracc)
  integrator.dtacc = one(integrator.dtacc)
  integrator.u_modified = false

  if reset_dt
    DiffEqBase.auto_dt_reset!(integrator)
  end

  if reinit_callbacks
    OrdinaryDiffEq.initialize_callbacks!(integrator, initialize_save)
  end

  if reinit_cache
    OrdinaryDiffEq.initialize!(integrator)
  end

  nothing
end

function DiffEqBase.auto_dt_reset!(integrator::DDEIntegrator)
  @unpack f, u, t, tdir, opts, sol, destats = integrator
  @unpack prob = sol
  @unpack abstol, reltol, internalnorm = opts

  # determine maximal time step
  if has_constant_lags(prob)
    dtmax = tdir * min(abs(opts.dtmax), minimum(abs, prob.constant_lags))
  else
    dtmax = opts.dtmax
  end

  # determine initial time step
  ode_prob = ODEProblem(f, prob.u0, prob.tspan, prob.p)
  integrator.dt = OrdinaryDiffEq.ode_determine_initdt(
    u, t, tdir, dtmax, opts.abstol, opts.reltol, opts.internalnorm, ode_prob, integrator)

  # update statistics
  destats.nf += 2

  nothing
end

function DiffEqBase.add_tstop!(integrator::DDEIntegrator,t)
  integrator.tdir * (t - integrator.t) < 0 && error("Tried to add a tstop that is behind the current time. This is strictly forbidden")
  push!(integrator.opts.tstops, integrator.tdir * t)
end

function DiffEqBase.add_saveat!(integrator::DDEIntegrator,t)
  integrator.tdir * (t - integrator.t) < 0 && error("Tried to add a saveat that is behind the current time. This is strictly forbidden")
  push!(integrator.opts.saveat, integrator.tdir * t)
end

@inline function DiffEqBase.get_du(integrator::DDEIntegrator)
  integrator.fsallast
end

@inline function DiffEqBase.get_du!(out,integrator::DDEIntegrator)
  out .= integrator.fsallast
end

DiffEqBase.has_destats(::DDEIntegrator) = true

DiffEqBase.addsteps!(integrator::DDEIntegrator,args...) = OrdinaryDiffEq._ode_addsteps!(integrator,args...)
DiffEqBase.change_t_via_interpolation!(integrator::DDEIntegrator,
                                        t,modify_save_endpoint::Type{Val{T}}=Val{false}) where T =
                                          OrdinaryDiffEq._change_t_via_interpolation!(integrator,t,modify_save_endpoint)

# update integrator when u is modified by callbacks
function OrdinaryDiffEq.handle_callback_modifiers!(integrator::DDEIntegrator)
    integrator.reeval_fsal = true # recalculate fsalfirst after applying step

    # update heap of discontinuities
    # discontinuity is assumed to be of order 0, i.e. solution x is discontinuous
    push!(integrator.opts.d_discontinuities, Discontinuity(integrator.tdir * integrator.t, 0))
end

# recalculate interpolation data and update the ODE integrator
function DiffEqBase.reeval_internals_due_to_modification!(
  integrator::DDEIntegrator, x::Type{Val{not_initialization}} = Val{true}) where not_initialization

  ode_integrator = integrator.integrator

  if not_initialization
    # update interpolation data of the integrator using the old dense history
    # of the ODE integrator
    resize!(integrator.k, integrator.kshortsize)
    DiffEqBase.addsteps!(integrator, integrator.f, true, true, true)

    # copy interpolation data to the ODE integrator
    recursivecopy!(ode_integrator.k, integrator.k)
  end

  # adjust current interval of the ODE integrator
  ode_integrator.t = integrator.t
  ode_integrator.dt = integrator.dt
  if isinplace(integrator.sol.prob)
    recursivecopy!(ode_integrator.u, integrator.u)
  else
    ode_integrator.u = integrator.u
  end

  integrator.u_modified = false
end

# perform one step
function DiffEqBase.step!(integrator::DDEIntegrator)
  @inbounds begin
    if integrator.opts.advance_to_tstop
      while integrator.tdir * integrator.t < top(integrator.opts.tstops)
        OrdinaryDiffEq.loopheader!(integrator)
        DiffEqBase.check_error!(integrator) === :Success || return
        OrdinaryDiffEq.perform_step!(integrator)
        OrdinaryDiffEq.loopfooter!(integrator)
      end
    else
      OrdinaryDiffEq.loopheader!(integrator)
      DiffEqBase.check_error!(integrator) === :Success || return
      OrdinaryDiffEq.perform_step!(integrator)
      OrdinaryDiffEq.loopfooter!(integrator)

      while !integrator.accept_step
        OrdinaryDiffEq.loopheader!(integrator)
        OrdinaryDiffEq.perform_step!(integrator)
        OrdinaryDiffEq.loopfooter!(integrator)
      end
    end
    OrdinaryDiffEq.handle_tstop!(integrator)
  end
end


text:
export order, point

"""
    order(cc::ComponentComplement)

The order of the given component of the complement.
"""
order(cc::ComponentComplement) = cc.order

"""
    point(cc::ComponentComplement)

A point in the given component of the complement.
"""
point(cc::ComponentComplement) = cc.x

"""
    isbounded(cc::ComponentComplement)

Returns whether the component of the complement `cc` is bounded.
"""
isbounded(cc::ComponentComplement) = cc.bounded

function Base.show(io::IO, cc::ComponentComplement{N}) where N
    print(io,
        "ComponentComplement{$N} with order ",
        tuple(cc.order...),
        cc.bounded ? " (bounded)" : " (unbounded)",)
end

@recipe function plot(CC::Vector{ComponentComplement}; show_orders=true, show_markers=!show_orders)
    legend --> false
    markerstrokewidth --> 0.0
    if show_markers
        markersize --> 6.0
    else
        markersize --> 0.0
    end
    markercolor --> :orange
    @series begin
        st := :scatter
        points = point.(CC)
        xs, ys = unzip(points)

        if show_orders
            series_annotations := map(order.(CC)) do ord
                "($(ord[1]),$(ord[2]))"
            end
        end

        xs, ys
    end
end

"""
    components_complement(amoeba_approximation, f; nsamples=512)

Compute a all components of the complement of the amoeba of `f` from the given
`amoeba_approximation` `Bitmap2D`.
"""
function components_complement(M::Bitmap2D, f::MP.AbstractPolynomial{T}; kwargs...) where T
    components_complement(M, AmoebaFiber2D(f), SP.Polynomial(promote_type(T, Float64), f); kwargs...)
end
function components_complement(M::Bitmap2D, F::AmoebaFiber2D, f::SP.Polynomial{T}; nsamples=1024) where {T}
    newt = newtonpolygon(SP.exponents(f))
    boundaries = complement_boundaries(M, f, newt, nsamples)
    components = Vector{ComponentComplement{2}}()
    # we avoid some allocations in `order` with this
    working_vec = zeros(complex(T), 2)
    gen = TorusStartValueGenerator{2}()
    options = MembershipTestOptions(maxiters=200, ntries=50)
    for (α, boundary) in boundaries
        try
            c = point_in_complement(boundary, α, f, M.grid)
            bounded = !on_boundary(newt, α)
            # We validate that the points is definitely not in the amoeba
            if membershiptest(F, (c[1], c[2]), gen, options).successfull
                continue
            end
            push!(components, ComponentComplement{2}(α, c, bounded))
        catch err
            @warn err
        end
    end

    components, boundaries
end

function point_in_complement(component_boundary, component_order, f::SP.Polynomial{T}, grid) where T
    working_vec = zeros(complex(T), 2)
    k = 0
    while k < 10
        try
            chull = convexhull_vertices(component_boundary)
            c = poly_centroid(component_boundary[chull], grid)
            ord = round.(Int, real.(order(f, c, working_vec, 1024)))
            if ord == component_order
                return c
            else
                c = boundary_average(component_boundary, grid)
                ord = round.(Int, real.(order(f, c, working_vec, 1024)))
                if ord == component_order
                    return c
                else
                    # We discard all vertices of the convex hull as outliers
                    # (One of them is an outlier)
                    deleteat!(component_boundary, chull)
                end
            end
        catch err
            @warn err
            # An error indicates that our complement component is not 2-dimensional
            # but rather a line. I.e. it is sufficient to consider the
            # average of all (unique) grid points on the line
            points = sort!(unique(component_boundary))
            if length(points) == 1
                c = grid[points[1]]
            else
                m = div(length(points), 2)
                c = grid[points[m]...]
            end
            ord = round.(Int, real.(order(f, c, working_vec, 1024)))
            if ord == component_order
                return c
            else
                throw(ErrorException("Cannot locate point in component with order $component_order."))
            end
        end
    end
    throw(ErrorException("Cannot locate point in component with order $component_order."))
end

"""
    boundary_average(boundary, grid)

Compute the average of the contour
"""
function boundary_average(boundary::Vector{NTuple{2, Int}}, grid::Grid2D)
    mean(p -> SVector(grid[p]), boundary)
end

function centroid(b::Vector{NTuple{2, Int}}, grid::Grid2D)
    try
        return poly_centroid(b[convexhull_vertices(b)], grid)
    catch
        # An error indicates that our complement component is not 2-dimensional
        # but rather a line. I.e. it is sufficient to consider the
        # average of all (unique) grid points on the line
        points = sort!(unique(b))
        if length(points) == 1
            return grid[points[1]]
        else
            m = div(length(points), 2)
            return grid[points[m]]
        end
    end
end

function poly_centroid(boundary::Vector{NTuple{2, Int}}, grid::Grid2D)
    A = 0.0
    cx = 0.0
    cy = 0.0

    n = length(boundary)
    i = n
    j = 1

    while j ≤ n
        xi, yi = grid[boundary[i]]
        xi1, yi1 = grid[boundary[j]]
        a = xi * yi1 - xi1 * yi
        cx += (xi + xi1) * a
        cy += (yi + yi1) * a
        A += a
        i = j
        j += 1
    end
    # @show A, length(boundary)
    (1 / (3A)) .* SVector(cx, cy)
end

"""
    complement_boundaries(M::Bitmap2D, f, newt)

Compute the boundaries of all complement components (as grid indices).
Note that this is noisy. There can be duplicate components usually arising
from small additional components (with a boundary of length 5).
"""
function complement_boundaries(M::Bitmap2D, f::SP.Polynomial, newt, nsamples)
    # we will add a padding of 1 around the image to get closed contours only
    # Therefore we have to add two points to the x and y-coordinates
    # x
    boundaries = contour_boundaries(M)
    sort!(boundaries, lt=((a, b) -> length(a) < length(b)), rev=true)
    split_with_order_map(boundaries, M.grid, f, newt, nsamples)
end

function contour_boundaries(M)
    # we will add a padding of 1 around the image to get closed contours only
    # Therefore we have to add two points to the x and y-coordinates
    # x
    xcoords = xcoordinates(M.grid)
    xspace = [xcoords[1] - step(xcoords)]
    append!(xspace, xcoords)
    push!(xspace, xcoords[end] + step(xcoords))

    ycoords = ycoordinates(M.grid)
    yspace = [ycoords[1] - step(ycoords)]
    append!(yspace, ycoords)
    push!(yspace, ycoords[end] + step(ycoords))

    values = floatpadd(M.data)
    lines = Contour.contour(xspace, yspace, values, 1e-30) |> Contour.lines
    boundaries = map(lines) do line
        xs, ys = Contour.coordinates(line)
        line_grid_points = Vector{NTuple{2, Int}}()
        for (x, y) in zip(xs, ys)
            i, j = gridpoint(M.grid, x, y)
            i = clamp(i, 1, size(M.grid, 1))
            j = clamp(j, 1, size(M.grid, 2))
            if !M[i,j]
                push!(line_grid_points, (i, j))
            end
        end
        line_grid_points
    end
end

"""
    split_with_order_map(boundaries, grid, f, newt)

Split the boundaries by using the order map.
"""
function split_with_order_map(boundaries, G, f::SP.Polynomial{T}, newt, nsamples) where T
    splitted_boundaries = Vector{eltype(boundaries)}()
    splitted_orders = Vector{SVector{2, Int}}()
    # we need to handle the "jump" between different orders
    index_bookkeeping = Dict{SVector{2, Int}, Int}()
    last_order = (-1, -1)
    last_index = 0
    working_vec = zeros(complex(T), 2)
    for boundary in boundaries
        for p in boundary
            imag_ord = order(f, G[p...], working_vec, nsamples)
            ord = round.(Int, real.(imag_ord))
            if norm(ord - imag_ord, Inf) > 1e-4
                continue
            end
            if ord == last_order
                index = last_index
            elseif haskey(index_bookkeeping, ord)
                index = index_bookkeeping[ord]
            elseif iscontained(newt, ord)
                push!(splitted_boundaries, Vector{Tuple{Int, Int}}())
                push!(splitted_orders, ord)
                index = length(splitted_boundaries)
                push!(index_bookkeeping, ord => index)
            else
                continue
            end

            push!(splitted_boundaries[index], p)

            last_index = index
            last_order = ord
        end
    end
    zip(splitted_orders, splitted_boundaries)
end

"""
    order(f, w)

Compute the order ``(v_1, v_2)`` of the given complements.

The ``j``-th order of ``f`` at ``w=(w_1,w_2)`` can be computed by the number of zeros
(minus the number of poles) of the one-variable Laurent-polynomial
```math
    u ↦ f(c_1^u^{δ_{1j}}, c_2^u^{δ_{2j}})
```
inside the unit circle ``|u|=1``, where ``(c1, c2)`` is any vector with ``Log(c1, c2) = w`` [^1].

In order to compute this we can use the
[argument principle](https://en.m.wikipedia.org/wiki/Argument_principle).
For this we have to rewrite the integral (here only for the first component of the order)
```math
\frac{1}{2πi}∫_{|u|=1}\frac{f'(e^{w_1}u, e^{w_2})}{f(e^{w_1}u, e^{w_2})}du
```
With a change of variables we get
```math
\frac{1}{2πi}∫_0^{2π}\frac{f'(e^{w_1}e^{iθ}, e^{w_2})}{f(e^{w_1}e^{iθ}, e^{w_2})}ie^{iθ}dθ
```
[^1]: Forsberg, Mikael, Mikael Passare, and August Tsikh. "Laurent determinants and arrangements of hyperplane PolynomialAmoebas." Advances in mathematics 151.1 (2000): 45-70.
"""
function order(f::SP.Polynomial, w, working_vec::AbstractVector, nsamples=128)
    v1 = 0.0im
    v2 = 0.0im
    h = im * 2π / nsamples
    c1, c2 = exp.(w)
    for k=0:nsamples-1
        u = exp(h * k)
        # g1(θ) = f(c1 * exp(iθ), c2)
        # g1'(θ) = c1 * f_x(c1 * exp(iθ), c2)
        # p1(θ) = g1'(θ) * i * exp(iθ) / g1(θ)
        # v1 += p1(θ)
        c1u = c1 * u
        x = SVector(c1u, c2)
        f_x = SP.gradient(f, x)[1]
        val = SP.evaluate(f, x)
        v1 += c1u * f_x / val

        # g2(θ) = f(c1, c2 * exp(iθ))
        # g2'(θ) = c2 * f_y(c1, c2 * exp(iθ))
        # p2(θ) = g2'(θ) * i * exp(iθ) / g2(θ)
        # v2 += p1(θ)
        c2u = c2 * u
        x = SVector(c1, c2u)
        f_y = SP.gradient(f, x)[2]
        val = SP.evaluate(f, x)
        v2 += c2u * f_y / val
    end
    v1 = v1 / (nsamples)
    v2 = v2 / (nsamples)
    SVector{2}(v1, v2)
end

"Add a rectangle of `true`s around the `BitArray`"
function floatpadd(A::BitArray)
    m, n = size(A)
    M = ones(m + 2, n + 2)
    for i=1:m, j=1:n
        M[i+1, j+1] = float(A[i, j])
    end
    M
end


text:
using ITensors
using LinearAlgebra

@testset "Test TensorNetwork struct and interface functions" begin
    # create empty tensor network
    tn = TensorNetwork()

    # create two tensors with one common index
    i1 = Index(2)
    i2 = Index(3)
    a_inds = [i1, Index(4)]
    b_inds = [i1, i2]
    tensor_a = push!(tn, a_inds, rand(2, 4))
    tensor_b = push!(tn, b_inds, rand(2, 3))
    @test length(tn) == 2
    @test length(collect(tn)) == 2

    # check the number of bonds 2
    # and that i1 connects to two tensors
    @test length(bonds(tn)) == 3
    @test length(tn[i1]) == 2
    @test all(tn[i1] .== [tensor_a, tensor_b])

    @test length(keys(tn)) == 2
    @test length(tn) == 2

    @test size(tensor_data(tn, tensor_a)) == (2, 4)

    tn2 = TensorNetwork()
    tensor_c = push!(tn2, [i2], rand(3))
    tn3 = merge(tn, tn2)
    @test length(tn3) == 3
    @test length(tn3[i2]) == 2

    @test length(neighbours(tn, tensor_b)) == 1
    @test length(neighbours(tn3, tensor_b)) == 2

    # Test delete!
    delete!(tn, tensor_a)
    @test length(tn) == 1
    @test haskey(tn.tensor_map, tensor_a) == false
    @test length(neighbours(tn, tensor_b)) == 0

    # Test TN copy
    a = TensorNetwork()
    tensor_a = push!(a, a_inds, rand(2, 4))
    tensor_b = push!(a, b_inds, rand(2, 3))
    b = copy(a)
    @test length(a) == length(b)
    @test keys(a) == keys(b) # test tensor symbols are the same.
    delete!(a, tensor_a)
    @test length(a) != length(b)

    # Test TN push kwargs
    a = TensorNetwork()
    tensor_a = push!(a, a_inds, rand(2, 4); tid = :t1)
    @test haskey(a, :t1)
end

@testset "Test TensorNetworkCircuit struct and interface functions" begin
    # create empty tensor network
    tnc = TensorNetworkCircuit(2)

    @test qubits(tnc) == 2
    @test length(tnc) == 0

    # add single qubit gate
    push!(tnc, [1], rand(2, 2))
    @test length(tnc) == 1

    # add two qubit gate
    push!(tnc, [1, 2], rand(4, 4), decompose=false)
    @test length(tnc) == 2

    # adding input
    add_input!(tnc, "01")
    @test length(tnc) == 4
    @test tensor_data(tnc, input_tensors(tnc)[1]) == [1., 0.]
    @test tensor_data(tnc, input_tensors(tnc)[2]) == [0., 1.]

    # adding output
    add_output!(tnc, "+-")
    @test length(tnc) == 6
    @test tensor_data(tnc, output_tensors(tnc)[1]) == [1., 1.]/sqrt(2)
    @test tensor_data(tnc, output_tensors(tnc)[2]) == [1., -1.]/sqrt(2)

    # test Base.copy on tnc
    tnc2 = copy(tnc)
    @test tensor_data(tnc2, output_tensors(tnc2)[1]) == [1., 1.]/sqrt(2)
    @test tensor_data(tnc2, output_tensors(tnc2)[2]) == [1., -1.]/sqrt(2)
    @test length(tnc) == length(tnc2)
end

@testset "Test circuit to Tensor Network Circuit conversion" begin
    # check tensornetwork size when no input or output
    tnc = create_test_tnc(no_input=true, no_output=true, decompose=false)
    @test qubits(tnc) == 3
    @test length(tnc) == 3
    # make sure there are gates on all qubits as expected
    @test all(tnc.input_indices .!= tnc.output_indices)

    tnc = create_test_tnc(no_input=true, no_output=true, decompose=true)
    @test qubits(tnc) == 3
    @test length(tnc) == 5
    # make sure there are gates on all qubits as expected
    @test all(tnc.input_indices .!= tnc.output_indices)

    # convert again adding input
    tnc = create_test_tnc(no_input=false, no_output=true, decompose=false)
    @test length(tnc) == 6
end

@testset "Test simple circuit contraction to verify conversion to circuit working" begin

    # we add input but no output to get full output vector
    tnc = create_test_tnc(no_input=false, no_output=true)

    output = simple_contraction(tnc.tn)
    output = reshape(output, 8)
    ref = zeros(8)
    ref[[1,8]] .= 1/sqrt(2)
    @test all(output .≈ ref)

    tnc =  create_test_tnc(no_input=false, no_output=true, decompose=false)

    output = simple_contraction(tnc)
    output = reshape(output, 8)
    ref = zeros(8)
    ref[[1,8]] .= 1/sqrt(2)
    @test all(output .≈ ref)

    tnc =  create_test_tnc(no_input=false, no_output=true, decompose=false)

    simple_contraction!(tnc)
    ref = zeros(8)
    ref[[1,8]] .= 1/sqrt(2)
    output = tensor_data(tnc, first(keys(tnc)))
    output = reshape(output, prod(size(output)))
    @test all(output .≈ ref)
end

@testset "Test mock tensors" begin
    # create a mock tensor and check dimension reported correctly
    dim = (2 << 20, 2<< 20)
    a_store = MockTensor(dim)
    @test length(a_store) == prod(dim)

    # create two tensors using mock tensor as storage and contract
    b_store = MockTensor((dim[1], 2, 4));
    a_inds = Index.(dim)
    a = QXTensor(collect(a_inds), a_store)
    b = QXTensor([a_inds[1], Index(2), Index(4)], b_store)
    c = contract_tensors(a, b, mock=true)
    @test size(c) == (dim[2], 2, 4)
end

# @testset "Test tensor decomnposition" begin
#     # prepare the circuit.
#     tnc =  create_test_tnc(no_input=false, no_output=false, decompose=false)
#     disable_hyperindices!(tnc)
#     @assert length(tnc.tn.tensor_map) == 9

#     # Find a tensor with four indices to decompose.
#     t_id = :_
#     for id in keys(tnc.tn.tensor_map)
#         if length(inds(tnc.tn.tensor_map[id])) == 4
#             t_id = id
#             break
#         end
#     end
#     @assert length(inds(tnc.tn.tensor_map[t_id])) == 4
#     left_inds = collect(inds(tnc.tn.tensor_map[t_id]))
#     left_inds = left_inds[1:2]

#     # test svd
#     Uid, Sid, Vid = replace_with_svd!(tnc.tn, t_id, left_inds;
#                                       maxdim=2,
#                                       cutoff=1e-13)
#     @test length(tnc.tn.tensor_map) == 9 + 2

#     SVid = contract_pair!(tnc.tn, Sid, Vid)
#     USVid = contract_pair!(tnc.tn, Uid, SVid)
#     @assert length(tnc.tn.tensor_map) == 9

#     Uid, Vid = decompose_tensor!(tnc, USVid, left_inds;
#                                         maxdim=2,
#                                         cutoff=1e-13)
#     @test length(tnc.tn.tensor_map) == 9 + 1
# end

@testset "Test hyperedge detection" begin
    # prepare the circuit.
    tnc = TensorNetworkCircuit(3)
    push!(tnc, [1], QXTns.Gates.h(); decompose=false)
    push!(tnc, [2], QXTns.Gates.h(); decompose=false)
    push!(tnc, [3], QXTns.Gates.h(); decompose=false)
    push!(tnc, [1], QXTns.Gates.h(); decompose=false)
    push!(tnc, [2], QXTns.Gates.h(); decompose=false)
    push!(tnc, [3], QXTns.Gates.h(); decompose=false)
    @assert length(tnc.tn.bond_map) == 9

    # For a tn with no diagonal tensors, each hyperedge consists of a single edge.
    hyperedges = get_hyperedges(tnc)
    @test Set(hyperedges) == Set(values(tnc.tn.bond_map))

    # Check if there are exactly 6 hyperedges found in the GHZ circuit, with 2 hyperedges
    # containing 4 tensors and 4 hyperedges containing 2 tensors.
    tnc =  create_test_tnc(no_input=false, no_output=false, decompose=true)
    hyperedges = get_hyperedges(tnc)
    @test length(hyperedges) == 6
    @test QXTns.counter(length.(hyperedges)) == Dict(4=>2, 2=>4)
end

@testset "Test disable hyperindices" begin
    ai = [Index(2) for _ in 1:4]
    ci = [Index(2) for _ in 1:4]
    bi = [ai[3], ai[4], ci[1], ci[2]]

    a = QXTensor(ai, [[1,3], [2,4]])
    b = QXTensor(bi, [[1,3], [2,4]])
    c = QXTensor(ci, [[1,3], [2,4]])

    tn = TensorNetwork([a, b, c])
    @test all(map(x -> length(hyperindices(x)) > 0, tn))
    disable_hyperindices!(tn)
    @test all(map(x -> length(hyperindices(x)) == 0, tn))

    tn = TensorNetwork()
    t = QXTensor([Index(4), Index(4)], Diagonal(ones(4)))
    sym = push!(tn, t)
    @test size(tensor_data(tn, sym; consider_hyperindices=false)) == (4,4)
    @test size(tensor_data(tn, sym; consider_hyperindices=true)) == (4,)
    disable_hyperindices!(tn)
    @test size(tensor_data(tn, sym; consider_hyperindices=true)) == (4,4)
end

@testset "Test disable hyperindices" begin
    ai = [Index(2) for _ in 1:4]
    bi = [ai[3], ai[4], Index(2), Index(2)]

    a = QXTensor(ai, [[2,4]])
    b = QXTensor(bi, [[1,3], [2,4]])
    tn = TensorNetwork([a, b])
    # look at index which is not connected
    @test length(setdiff(find_connected_indices(tn, ai[1]), [ai[1]])) == 0
    # look at index connected to two others
    @test length(setdiff(find_connected_indices(tn, ai[2]), [ai[2], ai[4], bi[4]])) == 0
    # look at index connected to one other
    @test length(setdiff(find_connected_indices(tn, ai[3]), [ai[3], bi[3]])) == 0

    # look at case of global connection of hyper indices
    a = QXTensor(ai, [[1,3], [2,4]])
    b = QXTensor(bi, [[1,2], [3,4]])
    tn = TensorNetwork([a, b])
    # now ai[1] and ai[2] shoudl be connected the indices in b are related there
    group = find_connected_indices(tn, ai[1])
    @test ai[2] ∈ group
end

@testset "Test hyperindex finding when considering global hyperindices" begin
    ai = [Index(2) for _ in 1:4]
    bi = [ai[3], ai[4], Index(2), Index(2)]
    a = QXTensor(ai, [[1,3], [2,4]], rand(2,2,2,2))
    b = QXTensor(bi, [[1,2], [3,4]], rand(2,2,2,2))

    tn = TensorNetwork()
    a_sym = push!(tn, a)
    b_sym = push!(tn, b)

    # test that global hyperindices are taken into account by default when getting hyperindices
    # for a tensor from a tensor network. In this case all indices of a for a single group
    @test Set(hyperindices(tn, a_sym)[1]) == Set(ai)

    # when global hyperindices are disabled, only local groups are returned
    @test hyperindices(tn, a_sym, global_hyperindices=false) == [ai[[1,3]], ai[[2,4]]]

    # test that the same behavior is observed when looking at the data retrieved
    @test size(tensor_data(tn, first(keys(tn)))) == (2,)
    @test size(tensor_data(tn, first(keys(tn)), global_hyperindices=false)) == (2, 2)
    @test size(tensor_data(tn, first(keys(tn)), consider_hyperindices=false)) == (2,2,2,2)

    # create an example where tensors are linked via a 3rd tensor
    ai = [Index(2) for _ in 1:3]
    bi = [ai[1], Index(2)]
    ci = [ai[2], bi[2]]

    tn = TensorNetwork()
    a_sym = push!(tn, QXTensor(ai, [[2,3]], rand(2,2,2)))
    b_sym = push!(tn, QXTensor(bi, rand(2,2)))
    c_sym = push!(tn, QXTensor(ci, [[1,2]], rand(2,2)))

    @test Set(hyperindices(tn, b_sym)[1]) == Set([bi[2], ai[2], ai[3]])
    @test hyperindices(tn, b_sym, global_hyperindices=false) == []
end

@testset "Test contractions when hyper indices are present" begin
    # create an example where tensors are linked via a 3rd tensor
    ai = [Index(2) for _ in 1:3]
    bi = [ai[1], Index(2),Index(2)]
    ci = [ai[2], bi[2]]

    tn = TensorNetwork()
    a_sym = push!(tn, QXTensor(ai, [[2,3]], rand(2,2,2)))
    b_sym = push!(tn, QXTensor(bi, rand(2,2,2)))
    c_sym = push!(tn, QXTensor(ci, [[1,2]], rand(2,2)))
    r = contraction_indices(tn, a_sym, b_sym)

    @test r.a_labels == [1,2]
    @test r.b_labels == [1,2,3]
    @test r.c_labels == [2,3]
    @test Set(r.c_indices[1]) == Set([bi[2], ai[2], ai[3]])
    @test Set(r.c_indices[2]) == Set([bi[3]])

    tn_copy = copy(tn)
    d_sym = contract_pair!(tn_copy, a_sym, b_sym, mock=true)
    @test size(tn_copy[d_sym]) == (2,2,2,2)

    tn_copy = copy(tn)
    d_sym = contract_pair!(tn_copy, a_sym, b_sym, mock=false)
    @test size(tn_copy[d_sym]) == (2,2,2,2)

    # test corner case with no scalar output
    ai = [Index(2),Index(2)]
    bi = copy(ai)

    tn = TensorNetwork()
    a_sym = push!(tn, QXTensor(ai, rand(2,2)))
    b_sym = push!(tn, QXTensor(bi, rand(2,2)))
    r = contraction_indices(tn, a_sym, b_sym)
    c_sym = contract_pair!(tn, a_sym, b_sym, mock=true)
end


text:
using Documenter, PseudoBoolean

makedocs(
    modules = [PseudoBoolean],
    format = Documenter.HTML(; prettyurls = get(ENV, "CI", nothing) == "true"),
    authors = "Adam Glos",
    sitename = "PseudoBoolean.jl",
    pages = Any["index.md"]
    # strict = true,
    # clean = true,
    # checkdocs = :exports,
)

deploydocs(
    repo = "github.com/qkitchen/PseudoBoolean.jl.git",
    push_preview = true
)


text:
using FastSigmoid
using Base.Test

# comprehensively test that transcoding of fast sigmoids works.

#integration tests.

@test FastSigmoid.__decomp(reinterpret(Posit{16,0}, 0x0001)) == (false, -14, 0x0000)
@test FastSigmoid.__p2f(reinterpret(Posit{16,0}, 0x0001)) == 6.1035156f-5

#discovered incorrect conversions.
@test Posit{8,0}(-56.0) == reinterpret(Posit{8,0}, 0x81)
@test Posit{8,0}(-13.21875) == reinterpret(Posit{8,0},0x85)
@test Posit{8,1}(0.000244140625) == reinterpret(Posit{8,1}, 0x01)
@test Posit{8,1}(0.0009765625) == reinterpret(Posit{8,1}, 0x02)

const UIntLookup = Dict(8 => UInt8, 16 => UInt16, 32 => UInt32, 64 => UInt64)
topbits(N) = one(UIntLookup[N]) << (N - 1)

#conversion and deconversion of 8-bit posits
for fs_val = 0x00:0xFF
  pval = reinterpret(Posit{8,0}, fs_val)
  @test (Posit{8,0}(FastSigmoid.__p2f(pval)), fs_val) == (pval, fs_val)
end
for fs_val = 0x00:0xFF
  pval = reinterpret(Posit{8,1}, fs_val)
  @test (Posit{8,1}(FastSigmoid.__p2f(pval)), fs_val) == (pval, fs_val)
end
for fs_val = 0x00:0xFF
  pval = reinterpret(Posit{8,2}, fs_val)
  @test (Posit{8,2}(FastSigmoid.__p2f(pval)), fs_val) == (pval, fs_val)
end

#conversion and deconversion of 16-bit posits
for fs_val = 0x0000:0xFFFF
  pval = reinterpret(Posit{16,0}, fs_val)
  @test (Posit{16,0}(FastSigmoid.__p2f(pval)), fs_val) == (pval, fs_val)
end

#discovered incorrect tests.
@test reinterpret(Posit{8,0}, 0x81) == reinterpret(Posit{8,0}, 0x82) + reinterpret(Posit{8,0},0x83)

#tests on the generated c library
include("c-lib-test.jl")


text:
#------------split_op.jl-------------------------------------------------------#
#
# Plotting: to plot individual timesteps, use gnuplot like so:
#               p "output00000.dat" u 1:2 w l
#               rep "output00000.dat" u 1:3 w l
#
#------------------------------------------------------------------------------#

struct Param
    xmax::Float64
    res::Int64
    dt::Float64
    timesteps::Int64
    dx::Float64
    x::Vector{Float64}
    dk::Float64
    k::Vector{Float64}
    im_time::Bool

    Param() = new(10.0, 512, 0.05, 1000, 2 * 10.0/512,
                  Vector{Float64}(-10.0 + 10.0/512 : 20.0/512 : 10.0),
                  pi / 10.0,
                  Vector{Float64}(vcat(0:512/2 - 1, -512/2 : -1) * pi/10.0),
                  false)
    Param(xmax::Float64, res::Int64, dt::Float64, timesteps::Int64,
          im_val::Bool) = new(
              xmax, res, dt, timesteps,
              2*xmax/res, Vector{Float64}(-xmax+xmax/res:2*xmax/res:xmax),
              pi/xmax, Vector{Float64}(vcat(0:res/2-1, -res/2:-1)*pi/(xmax)),
              im_val
          )
end

mutable struct Operators
    V::Vector{Complex{Float64}}
    R::Vector{Complex{Float64}}
    K::Vector{Complex{Float64}}
    wfc::Vector{Complex{Float64}}

    Operators(res) = new(Vector{Complex{Float64}}(res),
                         Vector{Complex{Float64}}(res),
                         Vector{Complex{Float64}}(res),
                         Vector{Complex{Float64}}(res))
end

# Function to initialize the wfc and potential
function init(par::Param, voffset::Float64, wfcoffset::Float64)
    opr = Operators(length(par.x))
    opr.V = 0.5 * (par.x - voffset).^2
    opr.wfc = exp.(-(par.x - wfcoffset).^2/2)
    if (par.im_time)
        opr.K = exp.(-0.5*par.k.^2*par.dt)
        opr.R = exp.(-0.5*opr.V*par.dt)
    else
        opr.K = exp.(-im*0.5*par.k.^2*par.dt)
        opr.R = exp.(-im*0.5*opr.V*par.dt)
    end

    return opr
end

# Function for the split-operator loop
function split_op(par::Param, opr::Operators)

    for i = 1:par.timesteps
        # Half-step in real space
        opr.wfc = opr.wfc .* opr.R

        # fft to momentum space
        opr.wfc = fft(opr.wfc)

        # Full step in momentum space
        opr.wfc = opr.wfc .* opr.K

        # ifft back
        opr.wfc = ifft(opr.wfc)

        # final half-step in real space
        opr.wfc = opr.wfc .* opr.R

        # density for plotting and potential
        density = abs2.(opr.wfc)

        # renormalizing for imaginary time
        if (par.im_time)
            renorm_factor = sum(density) * par.dx

            for j = 1:length(opr.wfc)
                opr.wfc[j] /= sqrt(renorm_factor)
            end
        end

        # Outputting data to file. Plotting can also be done in a similar way
        # This is set to output exactly 100 files, no matter how many timesteps
        if ((i-1) % div(par.timesteps, 100) == 0)
            outfile = open("output" *string(lpad(i-1, 5, 0))* ".dat","w")

            # Outputting for gnuplot. Any plotter will do.
            for j = 1:length(density)
                write(outfile, string(par.x[j]) * "\t"
                               * string(density[j]) * "\t"
                               * string(real(opr.V[j])) * "\n")
            end

            close(outfile)
            println("Outputting step: ", i)
        end
    end
end

# We are calculating the energy to check <Psi|H|Psi>
function calculate_energy(par, opr)
    # Creating real, momentum, and conjugate wavefunctions
    wfc_r = opr.wfc
    wfc_k = fft(wfc_r)
    wfc_c = conj(wfc_r)

    # Finding the momentum and real-space energy terms
    energy_k = 0.5*wfc_c.*ifft((par.k.^2) .* wfc_k)
    energy_r = wfc_c.*opr.V .* wfc_r

    # Integrating over all space
    energy_final = 0
    for i = 1:length(energy_k)
        energy_final += real(energy_k[i] + energy_r[i])
    end

    return energy_final*par.dx
end

# main function
function main()
    par = Param(5.0, 256, 0.05, 100, true)

    # Starting wavefunction slightly offset so we can see it change
    opr = init(par, 0.0, -1.00)
    split_op(par, opr)

    energy = calculate_energy(par, opr)
    println("Energy is: ", energy)
end

main()

max_stars_repo_name: MaxJWeinstein/max-algorithm-archive

max_issues_repo_name: MaxJWeinstein/max-algorithm-archive

max_forks_repo_name: MaxJWeinstein/max-algorithm-archive


text:
module Simulacrum

using HyperGraphs, Symbolics
import SymbolicUtils: Term, Sym, Symbolic
using SimpleTraits
using ModelingToolkit
using Catalyst

const SymTypes = Union{Num, Symbolic}
export SymTypes

include("patterns.jl")
include("bridges/catalyst.jl")
include("connections.jl")
include("operations.jl")
include("reactions.jl")
include("utils.jl")
include("wip.jl")

export

# bridges: catalyst
catalyst_reactions,

# connections
connect, connect!, couple,

# operations
clone,

# patterns
AbstractPattern, indices,
AllToAll, Cycle, Path,

# reactions
isunimolecular, ismultimolecular,
reversible_reaction, @reversible,

# utils
make_var

end # module


text:
module JuliaQubit2

using PyCall
using TensorOperations

export JuliaQubit

qml = pyimport("pennylane")
devices_mod = pyimport("pennylane.devices")

@pydef mutable struct JuliaQubit <: devices_mod.DefaultQubit

    name = "Julia Qubit PennyLane plugin"
    short_name = "julia.qubit"
    pennylane_requires = "dev?"
    version = "0.0.1"
    author = "Christina Lee"

    operations = [
        "PauliX",
        "PauliY",
        "PauliZ",
        "Hadamard",
        "S",
        "T",
        "CNOT",
        "SWAP",
        "CSWAP",
        "Toffoli",
        "CZ",
        "PhaseShift",
        "RX",
        "RY",
        "RZ",
        "Rot",
        "CRX",
        "CRY",
        "CRZ",
        "CRot"
    ]

    observables = ["PauliX", "PauliY", "PauliZ", "Hadamard", "Identity"]

    function __init__(self, wires, args...; shots=None, cache=0)
            qml.devices.DefaultQubit.__init__(self, wires, shots=shots, cache=cache)
    end

    function apply_operation(self, state, op)
        dev_wires =  [self.wires_map[w] for w in op.wires]

        state_indices = -collect(1:self.num_wires)
        op_indices = cat(zeros(Int,length(op.wires)), (1:length(op.wires)), dims=1)

        for (i, w) in enumerate(reverse(dev_wires))
            state_indices[w]= i
            op_indices[i] = -w
        end

        matr = reshape(op.matrix, repeat([2], 2*op.wires.__len__())...)

        return ncon((matr, state), (op_indices, state_indices))
    end

    function apply(self, operations, args...; rotations=None, kwargs...)

        self._state = zeros(Complex{Float64}, repeat([2], self.num_wires)...)
        self._state[1] = 1.0

        self.wires_map = Dict(zip(self._wires, 1:self.num_wires))

        for op in operations
            self._state = self.apply_operation(self._state, op)
        end

        self._prerotated_state = self._state
    end

end

end


text:
module SequentialMonteCarlo

import Statistics.mean
using RNGPool

include("structures.jl")
include("categorical.jl")
include("common.jl")
include("serial.jl")
include("parallel.jl")
include("interface.jl")

export smc!, csmc!, SMCModel, SMCIO

end # module


text:
module AppliSales

using Dates

include("./infrastructure/infrastructure.jl")

export process

end # module


text:
using Base.Test
using Etcd
using Memento

const LOG_LEVEL = "info"      # could also be "debug", "notice", "warn", etc

Memento.config(LOG_LEVEL; fmt="[{level}] {msg}")
const logger = getlogger(current_module())

# const timeout = 600     # A longer timeout for travis testing
const timeout = 60    # More reasonable local timeout
const server = Etcd.start(timeout)  # Start server with timeout of 60 sec
const host = "localhost"
const port = 2379
const version = "v2"

@testset "Etcd" begin
    cli = Etcd.connect(host, port, version)

    @testset "requests" begin
        @testset "HTTPError" begin
            err = HTTPError(Requests.get("http://localhost:$port/$version/bad"))
            @test isa(Etcd.response(err), Requests.Response)
            show_out = sprint(showerror, err)
            @test startswith(show_out, "HTTPError: 404 page not found")
        end

        @testset "EtcdError" begin
            try
                create(cli, "/mykey", "myvalue"; ttl=2)
                create(cli, "/mykey", "myvalue"; ttl=2)
            catch err
                @test isa(Etcd.response(err), Dict)
                show_out = sprint(showerror, err)
                @test startswith(show_out, "EtcdError: Key already exists - /mykey (105).")
            end

            sleep(2)
        end
    end

    @testset "api" begin
        @testset "machines" begin
            resp = machines(cli)
            @test isa(resp, AbstractArray)
            @test length(resp) >= 1
            @test contains(resp[1], host)
            @test contains(resp[1], "$port")
        end

        @testset "stats" begin
            resp = stats(cli, "store")
            @test isa(resp, Dict)
            resp = stats(cli, "self")
            @test isa(resp, Dict)
            @test_throws HTTPError stats(cli, "foobar")
        end

        @testset "members" begin
            resp = members(cli)
            @test isa(resp, Dict)
            @test length(resp) == 1
        end

        @testset "leaders" begin
            resp = leader(cli)
            @test isa(resp, Dict)
        end

        @testset "keys" begin
            @testset "set" begin
                resp = set(cli, "/mykey", "myvalue"; ttl=1)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "set"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mykey"
                @test haskey(resp["node"], "value")
                @test resp["node"]["value"] == "myvalue"

                sleep(2)    # expire
            end

            @testset "create" begin
                resp = create(cli, "/mykey", "myvalue"; ttl=2)

                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "create"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mykey"
                @test haskey(resp["node"], "value")
                @test resp["node"]["value"] == "myvalue"

                @test_throws EtcdError create(cli, "/mykey", "myvalue"; ttl=1)
                sleep(3)    # expire
            end

            @testset "update" begin
                set(cli, "/mykey", "myvalue"; ttl=2)
                resp = update(cli, "/mykey", "mynewvalue"; ttl=1)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "update"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mykey"
                @test haskey(resp["node"], "value")
                @test resp["node"]["value"] == "mynewvalue"

                sleep(3)    # expire
            end

            @testset "setdir" begin
                resp = setdir(cli, "/mydir"; ttl=1)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "set"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mydir"
                @test haskey(resp["node"], "dir")
                @test resp["node"]["dir"]

                sleep(2)    # expire
            end

            @testset "createdir" begin
                resp = createdir(cli, "/mydir"; ttl=2)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "create"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mydir"
                @test haskey(resp["node"], "dir")
                @test resp["node"]["dir"]

                @test_throws EtcdError createdir(cli, "/mydir"; ttl=1)

                sleep(3)    # expire
            end

            @testset "updatedir" begin
                @test_throws EtcdError updatedir(cli, "/mydir"; ttl=1)
                setdir(cli, "/mydir"; ttl=2)
                resp = updatedir(cli, "/mydir"; ttl=1)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "update"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mydir"
                @test haskey(resp["node"], "dir")
                @test resp["node"]["dir"]

                sleep(3)    # expire
            end

            @testset "ordered_set" begin
                resp = set(cli, "/queue", "Job1"; ttl=3, ordered=true)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "create"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "value")
                @test resp["node"]["value"] == "Job1"
                resp = set(cli, "/queue", "Job2"; ttl=2, ordered=true)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "create"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "value")
                @test resp["node"]["value"] == "Job2"
                resp = get(cli, "/queue"; sort=true, recursive=true)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "get"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "nodes")
                @test isa(resp["node"]["nodes"], AbstractArray)
                @test length(resp["node"]["nodes"]) == 2

                sleep(3)
            end

            @testset "haskey" begin
                set(cli, "/mykey", "myvalue"; ttl=2)
                @test haskey(cli, "/mykey")
                @test !haskey(cli, "/mymissingkey")

                sleep(3)    # expire
            end

            @testset "cas" begin
                set(cli, "/mykey", "myvalue"; ttl=2)
                resp = Etcd.cas(cli, "/mykey", "mynewvalue"; prev_value="myvalue", ttl=1)
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "compareAndSwap"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mykey"
                @test haskey(resp["node"], "value")
                @test resp["node"]["value"] == "mynewvalue"
                @test haskey(resp, "prevNode")
                @test haskey(resp["prevNode"], "key")
                @test resp["prevNode"]["key"] == "/mykey"
                @test haskey(resp["prevNode"], "value")
                @test resp["prevNode"]["value"] == "myvalue"

                # @test_throws EtcdError Etcd.cas(cli, "/mykey", "myvalue")

                sleep(3)
            end

            @testset "cad" begin
                set(cli, "/mykey", "myvalue"; ttl=2)
                # @test_throws EtcdError Etcd.cad(cli, "/mykey")

                resp = Etcd.cad(cli, "/mykey"; prev_value="myvalue")
                @test isa(resp, Dict)
                @test haskey(resp, "action")
                @test resp["action"] == "compareAndDelete"
                @test haskey(resp, "node")
                @test haskey(resp["node"], "key")
                @test resp["node"]["key"] == "/mykey"
                @test haskey(resp, "prevNode")
                @test haskey(resp["prevNode"], "key")
                @test resp["prevNode"]["key"] == "/mykey"
                @test haskey(resp["prevNode"], "value")
                @test resp["prevNode"]["value"] == "myvalue"

                sleep(3)
            end

            @testset "watch" begin
                @testset "Basic" begin
                    c = Channel{Dict}(32)
                    set_resp = set(cli, "/mykey", "myvalue"; ttl=2)
                    idx = set_resp["node"]["modifiedIndex"] + 1

                    t = watch(cli, "/mykey"; wait_index=idx, recursive=true) do resp
                        put!(c, resp)
                    end

                    set_resp = set(cli, "/mykey", "newvalue"; ttl=2)
                    wait(t)
                    c_resp = take!(c)
                    @test set_resp == c_resp || c_resp["action"] == "expire"

                    sleep(2)
                end

                @testset "Loop" begin
                    @testset "Infinite" begin
                        c = Channel{Dict}(32)

                        t = watchloop(cli, "/mykey"; recursive=true) do resp
                            put!(c, resp)
                        end

                        set_resp = set(cli, "/mykey", "val1"; ttl=1)
                        c_resp = take!(c)
                        @test set_resp == c_resp || c_resp["action"] == "expire"
                        set_resp = set(cli, "/mykey", "val2"; ttl=1)
                        c_resp = take!(c)
                        @test set_resp == c_resp || c_resp["action"] == "expire"
                        try
                            schedule(t, InterruptException(); error=true)
                            wait(t)
                        end

                        sleep(2)
                    end

                    @testset "Predicate" begin
                        c = Channel{Dict}(32)
                        set_resp = set(cli, "/mykey", "val1"; ttl=2)
                        idx = set_resp["node"]["modifiedIndex"] + 1
                        predicate(r) = r["node"]["modifiedIndex"] > (idx + 5)

                        t = watchloop(cli, "/mykey", predicate; wait_index=idx, recursive=true) do resp
                            put!(c, resp)
                        end

                        i = 2
                        set_resp = set(cli, "/mykey", "val$i"; ttl=1)
                        sleep(0.2)
                        while isready(c)
                            c_resp = take!(c)
                            @test set_resp == c_resp || c_resp["action"] == "expire"
                            i += 1
                            set_resp = set(cli, "/mykey", "val$i"; ttl=1)
                            sleep(0.2)
                        end

                        wait(t)
                        sleep(2)
                    end
                end
            end
        end
    end
end

sleep(5)
info(logger, "Stopping etcd server...")
kill(server)


text:
"""
モザイクプロットは，の帯グラフにおいて，帯の幅をグループの相対度数に反映させたものである。

帯グラフ（積み上げ相対度数分布グラフ）は帯の幅を変えることができないので，以下のような関数を書く。
"""

using FreqTables
using Plots
function mosaicplot(t; xlabel="", ylabel="",
            color=1:size(t, 1), disp=:num, alpha=0.6, plotsize=(400, 400))
      function rect(x, i, y, j, color)
            plot!([x[i], x[i+1], x[i+1], x[i], x[i]],
                  [y[j], y[j], y[j+1], y[j+1], y[j]],
                  seriestype=:shape, linecolor=:yellow,
                  fillcolor=color, alpha=alpha, label="")
      end
      t = reverse(t, dims=1)
      dispt = disp == :num ? t : round.(t ./ sum(t), digits=3)
      rownames, colnames = names(t)
      color = reverse(color)
      nrow, ncol = size(t)
      n = sum(t)
      colsums = vec(sum(t, dims=1));
      colcumsums = cumsum(colsums) ./ n;
      pushfirst!(colcumsums, 0);
      colmid = (colcumsums[1:ncol] .+ colcumsums[2:end]) ./ 2;
      p = plot(grid=false, tick_direction=:out,
            xlabel=xlabel, xlims=(0,1),
            ylabel=ylabel, ylims=(0,1),
            aspect_ratio=1, size=plotsize, label="");
      for col = 1:ncol # col = 1
            x1, x2 = colcumsums[col:col+1]
            rowsums = t[:, col] ./ sum(t[:, col])
            rowcumsums = vec(cumsum(rowsums))
            pushfirst!(rowcumsums, 0)
            rowmid = (rowcumsums[1:end-1] .+ rowcumsums[2:end]) ./ 2
            for row = 1:nrow
                  rect(colcumsums, col, rowcumsums, row, color[row])
                  annotate!(colmid[col], rowmid[row],
                        text("$(colnames[col])\n$(rownames[row])\n$(dispt[row, col])", :white, 8,),
                        label="")
            end
      end
      display(p)
end

#=
使用例

てんとう虫の住んでいる場所と色についてのデータをモザイクプロットで描いてみる。

ladybirds_morph_colour.csv
https://github.com/R4All/datasets/blob/master/ladybirds_morph_colour.csv

julia> io = IOBuffer("""
           Habitat,Site,morph_colour,number
           Rural,R1,black,10
           Rural,R2,black,3
           Rural,R3,black,4
           Rural,R4,black,7
           Rural,R5,black,6
           Rural,R1,red,15
           Rural,R2,red,18
           Rural,R3,red,9
           Rural,R4,red,12
           Rural,R5,red,16
           Industrial,U1,black,32
           Industrial,U2,black,25
           Industrial,U3,black,25
           Industrial,U4,black,17
           Industrial,U5,black,16
           Industrial,U1,red,17
           Industrial,U2,red,23
           Industrial,U3,red,21
           Industrial,U4,red,9
           Industrial,U5,red,15""")
IOBuffer(data=UInt8[...], readable=true, writable=false, seekable=true, append=false, size=416, maxsize=Inf, ptr=1, mark=-1)

julia> using CSV, DataFrames, FreqTables

julia> dat = CSV.read(io, DataFrame);

julia> table = freqtable(dat.morph_colour, dat.Habitat, weights=dat.number)
2×2 Named Matrix{Int64}
Dim1 ╲ Dim2 │ "Industrial"       "Rural"
────────────┼───────────────────────────
"black"     │          115            30
"red"       │           85            70

julia> mosaicplot(table; xlabel="Havitat", ylabel="morph_colour", color=[:black, :red])
=#

max_stars_repo_name: r-de-r/stats

max_issues_repo_name: r-de-r/stats

max_forks_repo_name: r-de-r/stats


text:
using PlotlyJS
Random.seed!(42)

function heatmap1()
    plot(heatmap(z=[1 20 30; 20 1 60; 30 60 1]))
end

function heatmap2()
    trace = heatmap(
        x=["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
        y=["Morning", "Afternoon", "Evening"],
        z=rand(1:30, 5, 3)
    )
    plot(trace)
end


text:
module PolyLog

include("Li2.jl")
include("Li3.jl")
include("Li4.jl")
include("Li5.jl")
include("Li6.jl")

export li2
export li3
export li4
export li5
export li6

end