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

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

"""
Creates a synchronous action.

Param: info::InstanceActionInfo (required)
Return: Nothing
"""
function createSyncAction(_api::DefaultApi, info; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", Nothing, "/actions", [], info)
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Returns general information about an instance.

Return: InstanceInfo
"""
function describeInstance(_api::DefaultApi; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", InstanceInfo, "/", [])
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Gets the machine configuration of the VM.
Gets the machine configuration of the VM. When called before the PUT operation, it will return the default values for the vCPU count (=1), memory size (=128 MiB). By default Hyperthreading is disabled and there is no CPU Template.
Return: MachineConfiguration
"""
function machineConfigGet(_api::DefaultApi; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", MachineConfiguration, "/machine-config", [])
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Get the MMDS data store.

Return: Any
"""
function mmdsGet(_api::DefaultApi; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", Any, "/mmds", [])
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Updates the MMDS data store.

Param: body::Any
Return: Nothing
"""
function mmdsPatch(_api::DefaultApi; body=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", Nothing, "/mmds", [], body)
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Creates a MMDS (Microvm Metadata Service) data store.

Param: body::Any
Return: Nothing
"""
function mmdsPut(_api::DefaultApi; body=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", Nothing, "/mmds", [], body)
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Updates the properties of a drive.
Updates the properties of the drive with the ID specified by drive_id path parameter. Will fail if update is not possible.
Param: drive_id::String (required)
Param: body::PartialDrive (required)
Return: Nothing
"""
function patchGuestDriveByID(_api::DefaultApi, drive_id::String, body; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", Nothing, "/drives/{drive_id}", [], body)
    Swagger.set_param(_ctx.path, "drive_id", drive_id)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Creates or updates the boot source.
Creates new boot source if one does not already exist, otherwise updates it. Will fail if update is not possible. Note that the only currently supported boot source is LocalImage.
Param: body::BootSource (required)
Return: Nothing
"""
function putGuestBootSource(_api::DefaultApi, body; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", Nothing, "/boot-source", [], body)
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Creates or updates a drive.
Creates new drive with ID specified by drive_id path parameter. If a drive with the specified ID already exists, updates its state based on new input. Will fail if update is not possible.
Param: drive_id::String (required)
Param: body::Drive (required)
Return: Nothing
"""
function putGuestDriveByID(_api::DefaultApi, drive_id::String, body; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", Nothing, "/drives/{drive_id}", [], body)
    Swagger.set_param(_ctx.path, "drive_id", drive_id)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Creates a network interface.
Creates new network interface with ID specified by iface_id path parameter. Updating existing interfaces is currently not allowed.
Param: iface_id::String (required)
Param: body::NetworkInterface (required)
Return: Nothing
"""
function putGuestNetworkInterfaceByID(_api::DefaultApi, iface_id::String, body; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", Nothing, "/network-interfaces/{iface_id}", [], body)
    Swagger.set_param(_ctx.path, "iface_id", iface_id)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Initializes the logger by specifying two named pipes (i.e. for the logs and metrics output).

Param: body::Logger (required)
Return: Nothing
"""
function putLogger(_api::DefaultApi, body; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", Nothing, "/logger", [], body)
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""
Updates the Machine Configuration of the VM.
Updates the Virtual Machine Configuration with the specified input. Firecracker starts with default values for vCPU count (=1) and memory size (=128 MiB). With Hyperthreading enabled, the vCPU count is restricted to be 1 or an even number, otherwise there are no restrictions regarding the vCPU count. If any of the parameters has an incorrect value, the whole update fails.
Param: body::MachineConfiguration
Return: Nothing
"""
function putMachineConfiguration(_api::DefaultApi; body=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", Nothing, "/machine-config", [], body)
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    Swagger.exec(_ctx)
end

export createSyncAction, describeInstance, machineConfigGet, mmdsGet, mmdsPatch, mmdsPut, patchGuestDriveByID, putGuestBootSource, putGuestDriveByID, putGuestNetworkInterfaceByID, putLogger, putMachineConfiguration


text:
# file = "clusterIds_temporal-(perc_50%,1980-2015).tif"
# x = GeoArrays.read(file);
function gdal_polygonize(raster_file, band = 1, out_file = "out.shp";
    fieldname = "grid", nodata = NaN)

    layername = "out"
    ds_raster = GDAL.gdalopen(raster_file, GDAL.GA_ReadOnly)
    band = GDAL.gdalgetrasterband(ds_raster, band)

    # if !isnan(nodata); GDAL.gdalsetrasternodatavalue(band, nodata); end
    # dst_ds = GDAL.ogr_dr_createdatasource(drv, dst_filename, C_NULL)
    drive = GDAL.gdalgetdriverbyname("ESRI Shapefile")
    ds_shp = GDAL.gdalcreate(drive, out_file, 0, 0, 0, GDAL.GDT_Unknown, C_NULL)

    REF = GDAL.osrnewspatialreference(C_NULL)
    GDAL.osrimportfromepsg(REF, 4326)
    # REF = C_NULL
    # REF = "WGS_1984"
    layer = GDAL.gdaldatasetcreatelayer(ds_shp, layername, REF, GDAL.wkbPolygon, C_NULL)

    fielddefn = GDAL.ogr_fld_create(fieldname, GDAL.OFTInteger)
    field = GDAL.ogr_l_createfield(layer, fielddefn, GDAL.TRUE)

    GDAL.gdalpolygonize(
        band,   # band
        C_NULL, # mask
        layer, field,
        C_NULL, C_NULL, C_NULL)
    GDAL.gdalclose(ds_shp)
    GDAL.gdalclose(ds_raster)
end

# function gdalsetrasternodatavalue()
# end

export gdal_polygonize

ext: jl


text:
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
    EulerIntr

Intrinsic right-handed rotation by the ZXZ axes.
"""
struct EulerIntr <: RotationConvention end
axesseq(::Type{EulerIntr}) = :ZXZ
orientation(::Type{EulerIntr}) = (:CCW,:CCW,:CCW)
angleunits(::Type{EulerIntr}) = :RAD
mainaxis(::Type{EulerIntr}) = :X
isextrinsic(::Type{EulerIntr}) = false


text:
export convert_pkg, convert_file, convert_folder

using ParserCombinator

const ws = P"\s*"
const ws1 = P"\s\s*"
const indent = p"\s*" > string
const body = p".*" > string
const braces = p"\(.*\)" > (x -> string(x[2:end-1]))
const chars = p"[a-zA-Z][a-zA-Z]*" > string
const nocomment = p"[^#]*"

#### context
type Context
    name
end
context_name = (P"context|facts") + braces
context_header = context_name + ws + E"do" > Context
writecore(c::Context) = string("@testset", " ", c.name, " begin")

type Fact code end

Fact(args...) = Fact(string(args...))
FactThrows(args...) = FactThrows(string(args...))

fact_throws = p"[^#]*@fact_throws" + nocomment > Fact
fact = p"[^#]*@fact" + nocomment > Fact
facts = fact_throws | fact

function writecore(f::Fact)
    ex = f.code |> parse |> MacroTools.striplines
    isincomplete(ex) && return "$(f.code) # TODO FactCheck2TestSets Parsing Error"
    ex |> fc2ts |> string |> sugar
end

type Line
    indent
    core
    comment
end

comment = (p"#.*" | ws) > string
core = context_header | facts
line = indent + core + ws + comment > Line

writecomment(s) = s == "" ? "" : string(" ", s)
function writeline(l::Line)
    string(l.indent, writecore(l.core), writecomment(l.comment))
end

type Blob code end
blob = p".*" > Blob
writeline(b::Blob) = b.code

#### ignore
immutable BitBucket end

ignore_exitstatus = ws + (E"FactCheck.exitstatus()"|ws) + ws + Eos() > BitBucket
ignore_usingtest = ws + (E"using Base.Test") + ws + Eos() > BitBucket
ignore = ignore_usingtest | ignore_exitstatus

writeline(::BitBucket) = ""

immutable UsingFactCheck end
usingfactcheck = ws + E"using FactCheck" + ws + Eos() > UsingFactCheck
writeline(::UsingFactCheck) = "using Base.Test"
anyline = usingfactcheck | ignore | line | blob

function convert_line(s::String)
    #isinteresting(s) || return s
    parse_one(s, anyline) |> unpack |> writeline
end


text:
using DateDataFrames
using Test

using Test

using DateDataFrames
using DataFrames
using MarketData

@testset "DateDataFrames.jl" begin
    # Write your tests here.

    @testset "change ability and resample" begin
        df = DataFrame(AAPL) # TimeArray -> DataFrame
        ddf = DateDataFrame(DateTime.(df.timestamp), df[!, 2:end])
        ddf[DateTime(1980, 12, 12), :Open] = 100
        @test df[1, :Open] == 100
        ddf2 = resample(Nearest(), ddf, Day(1))
        ddf3 = DateDataFrame(collect(ddf2.timestamp), ddf2.df)
    end

    @testset "broadcasting" begin
        df = DataFrame(Dict(:a=>[1,2,3], :b=>[2,3,4]))
        ddf = DateDataFrame(DateTime(1989,6,4):Day(1):DateTime(1989,6,6), df)

        ddf2 = deepcopy(ddf)
        ddf2 .= 0

        @test ddf2[1,1] == 0

        ddf2 .= ddf

        @test ddf2[1,1] == 1

        ddf[!, :a] .= ddf2[!, :b] # ddf[!, :a] = ddf2[!, :b] is `setindex!`, not broadcasting.

        @test ddf[1, :a] == 2

        ddf = ddf .* ddf

        @test ddf[1, :a] == 4

        ddf .= ddf .* ddf

        @test ddf[1, :a] == 16

        ddf[!, :b] .= 0

        @test ddf[1, :b] == 0

        ddf = ddf .* ddf[!, :b]

        @test ddf[1,1] == 0

        ddf_v = ddf[!, :a]
        ddf_v .= 1

        @test ddf_v[1] == 1

        ddf_v[:] .= 2

        @test ddf_v[1] == 2
    end
end


text:
module LoopVectorization

# if (!isnothing(get(ENV, "TRAVIS_BRANCH", nothing)) || !isnothing(get(ENV, "APPVEYOR", nothing))) && isdefined(Base, :Experimental) && isdefined(Base.Experimental, Symbol("@optlevel"))
    # @eval Base.Experimental.@optlevel 1
# end

using VectorizationBase, SLEEFPirates, UnPack, OffsetArrays
using VectorizationBase: register_size, register_count, cache_linesize, has_opmask_registers,
    mask, pick_vector_width, MM, data,
    maybestaticlength, maybestaticsize, staticm1, staticp1, staticmul, vzero,
    maybestaticrange, offsetprecalc, lazymul,
    maybestaticfirst, maybestaticlast, scalar_less, scalar_greaterequal, gep, gesp, pointerforcomparison, NativeTypes,
    vfmadd, vfmsub, vfnmadd, vfnmsub, vfmadd_fast, vfmsub_fast, vfnmadd_fast, vfnmsub_fast, vfmadd231, vfmsub231, vfnmadd231, vfnmsub231,
    vfma_fast, vmuladd_fast, vdiv_fast, vadd_fast, vsub_fast, vmul_fast,
    relu, stridedpointer, StridedPointer, StridedBitPointer, AbstractStridedPointer,
    reduced_add, reduced_prod, reduce_to_add, reduce_to_prod, reduced_max, reduced_min, reduce_to_max, reduce_to_min,
    vsum, vprod, vmaximum, vminimum, unwrap

using IfElse: ifelse

using ThreadingUtilities
using SLEEFPirates: pow
using Base.Broadcast: Broadcasted, DefaultArrayStyle
using LinearAlgebra: Adjoint, Transpose
using Base.Meta: isexpr
using DocStringExtensions
import LinearAlgebra # for check_args

using Base.FastMath: add_fast, sub_fast, mul_fast, div_fast, inv_fast, abs2_fast, rem_fast, max_fast, min_fast

using ArrayInterface
using ArrayInterface: OptionallyStaticUnitRange, Zero, One, StaticBool, True, False#, static_length
const Static = ArrayInterface.StaticInt

using Requires

export LowDimArray, stridedpointer,
    @avx, @_avx, *ˡ, _avx_!,
    vmap, vmap!, vmapt, vmapt!, vmapnt, vmapnt!, vmapntt, vmapntt!, tanh_fast, sigmoid_fast,
    vfilter, vfilter!, vmapreduce, vreduce

const VECTORWIDTHSYMBOL, ELTYPESYMBOL = Symbol("##Wvecwidth##"), Symbol("##Tloopeltype##")

include("vectorizationbase_compat/contract_pass.jl")
include("vectorizationbase_compat/subsetview.jl")
include("closeopen.jl")
include("getconstindexes.jl")
include("predicates.jl")
include("map.jl")
include("filter.jl")
include("costs.jl")
include("operations.jl")
include("graphs.jl")
include("operation_evaluation_order.jl")
include("memory_ops_common.jl")
include("add_loads.jl")
include("add_stores.jl")
include("add_compute.jl")
include("add_constants.jl")
include("add_ifelse.jl")
include("determinestrategy.jl")
include("line_number_nodes.jl")
include("loopstartstopmanager.jl")
include("lower_compute.jl")
include("lower_constant.jl")
include("lower_memory_common.jl")
include("lower_load.jl")
include("lower_store.jl")
include("lowering.jl")
include("split_loops.jl")
include("condense_loopset.jl")
include("reconstruct_loopset.jl")
include("constructors.jl")
include("user_api_conveniences.jl")
include("mapreduce.jl")
include("broadcast.jl")

"""
LoopVectorization provides macros and functions that combine SIMD vectorization and
loop-reordering so as to improve performance:

- [`@avx`](@ref): transform `for`-loops and broadcasting
- [`@_avx`](@ref): similar to `@avx` but does not use type information
- [`vmap`](@ref) and `vmap!`: vectorized version of `map` and `map!`
- [`vmapnt`](@ref) and `vmapnt!`: non-temporal variants of `vmap` and `vmap!`
- [`vmapntt`](@ref) and `vmapntt!`: threaded variants of `vmapnt` and `vmapnt!`
- [`vfilter`](@ref) and `vfilter!`: vectorized versions of `filter` and `filter!`
"""
LoopVectorization

include("precompile.jl")
_precompile_()

# import ChainRulesCore, ForwardDiff
# include("vmap_grad.jl")
function __init__()
    @require ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" begin
        @require ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" include("vmap_grad.jl")
    end
end

end # module


text:
export SuperpositionMeasure

@doc raw"""
    struct SuperpositionMeasure{X,NT} <: AbstractMeasure
        components :: NT
    end
Superposition of measures is analogous to mixture distributions, but (because
measures need not be normalized) requires no scaling.
The superposition of two measures μ and ν can be more concisely written as μ + ν.
Superposition measures satisfy

    basemeasure(μ + ν) == basemeasure(μ) + basemeasure(ν)

```math
    \begin{aligned}\frac{\mathrm{d}(\mu+\nu)}{\mathrm{d}(\alpha+\beta)} & =\frac{f\,\mathrm{d}\alpha+g\,\mathrm{d}\beta}{\mathrm{d}\alpha+\mathrm{d}\beta}\\
     & =\frac{f\,\mathrm{d}\alpha}{\mathrm{d}\alpha+\mathrm{d}\beta}+\frac{g\,\mathrm{d}\beta}{\mathrm{d}\alpha+\mathrm{d}\beta}\\
     & =\frac{f}{1+\frac{\mathrm{d}\beta}{\mathrm{d}\alpha}}+\frac{g}{\frac{\mathrm{d}\alpha}{\mathrm{d}\beta}+1}\\
     & =\frac{f}{1+\left(\frac{\mathrm{d}\alpha}{\mathrm{d}\beta}\right)^{-1}}+\frac{g}{\frac{\mathrm{d}\alpha}{\mathrm{d}\beta}+1}\ .
    \end{aligned}
```
"""
struct SuperpositionMeasure{NT} <: AbstractMeasure
    components::NT
end

function Pretty.tile(d::SuperpositionMeasure)
    result = Pretty.literal("SuperpositionMeasure(")
    result *= Pretty.list_layout([Pretty.tile.(d.components)...])
    result *= Pretty.literal(")")
end

testvalue(μ::SuperpositionMeasure) = testvalue(first(μ.components))

# SuperpositionMeasure(ms :: AbstractMeasure...) = SuperpositionMeasure{X,length(ms)}(ms)

# SuperpositionMeasure(m::NTuple{N, Measure{X}}) where {N,X} = SuperpositionMeasure(m...)

# Base.length(::SuperpositionMeasure{X,N}) where {X,N} = N

# function Base.:+(μ::SuperpositionMeasure{N1}, ν::SuperpositionMeasure{N2}) where {N1,N2}
#     components = (μ.components..., ν.components...)
#     SuperpositionMeasure{X, N1+N2}(components)
# end

# function Base.:+(μ::AbstractMeasure, ν::SuperpositionMeasure{X,N}) where {X,N}
#     components = (μ, ν.components...)
#     SuperpositionMeasure{X,N+1}(components)
# end

# function Base.:+(μ::SuperpositionMeasure{X,N}, ν::AbstractMeasure) where {X,N}
#     components = (μ.components..., ν)
#     SuperpositionMeasure{X,N+1}(components)
# end

function Base.:+(μ::AbstractMeasure, ν::AbstractMeasure)
    components = (μ, ν)
    superpose(components)
end

logdensity(μ::SuperpositionMeasure, x) = logsumexp((logdensity(m, x) for m in μ.components))

basemeasure(μ::SuperpositionMeasure) = superpose(map(basemeasure, μ.components))

# TODO: Fix `rand` method (this one is wrong)
# function Base.rand(μ::SuperpositionMeasure{X,N}) where {X,N}
#     return rand(rand(μ.components))
# end


text:
import Base: @propagate_inbounds

const IsingSpin = Int64
const IsingDistribution = IsingSpin[-1,1]
const IsingConf = Array{IsingSpin}

const IsingTc = 1/(1/2*log(1+sqrt(2)))

"""
Famous Ising model on a cubic lattice.

    IsingModel(; dims, L)

Create Ising model on `dims`-dimensional cubic lattice
with linear system size `L`.
"""
@with_kw_noshow struct IsingModel{C<:AbstractLattice} <: Model # noshow because we override it below
    L::Int
    dims::Int
    l::C = choose_lattice(IsingModel, dims, L)
    energy::Ref{Float64} = Ref(0.0)
end

init!(mc::MC, m::IsingModel) = energy(mc, m, mc.conf)

function choose_lattice(::Type{IsingModel}, dims::Int, L::Int)
    if dims == 1
        return Chain(L)
    elseif dims == 2
        return SquareLattice(L)
    else
        return CubicLattice(dims, L)
    end
end

"""
    IsingModel(params::Dict)
    IsingModel(params::NamedTuple)

Create an Ising model with (keyword) parameters as specified in the
dictionary/named tuple `params`.
"""
IsingModel(params::Dict{Symbol, T}) where T = IsingModel(; params...)
IsingModel(params::NamedTuple) = IsingModel(; params...)

# convenience
@inline Base.ndims(m::IsingModel) = m.dims

# cosmetics
import Base.summary
import Base.show
Base.summary(model::IsingModel) = "$(model.dims)D-Ising model"
# Base.show(io::IO, model::IsingModel{LT}) where LT<:AbstractCubicLattice =
    # print(io, "$(model.dims)D-Ising model, L=$(model.L) ($(model.l.sites) sites)")
function Base.show(io::IO, model::IsingModel{LT}) where LT<:AbstractLattice
    print(io,
        "Ising model on $(replace(string(LT), "MonteCarlo."=>"")), " *
        "L=$(model.L) ($(model.l.sites) sites)"
    )
end
Base.show(io::IO, m::MIME"text/plain", model::IsingModel) = print(io, model)

# implement `Model` interface
@inline lattice(m::IsingModel) = m.l

# implement `MC` interface
Base.rand(::Type{MC}, m::IsingModel) = rand(IsingDistribution, fill(m.L, ndims(m))...)

@propagate_inbounds @bm function propose_local(mc::MC, m::IsingModel, i::Int, conf::IsingConf)
    field = 0.0
    @inbounds for trg in neighbors(m.l, i)
        field += conf[trg]
    end
    delta_E = 2.0 * conf[i] * field
    return delta_E, nothing
end

@propagate_inbounds @bm function accept_local!(
        mc::MC, m::IsingModel, i::Int, conf::IsingConf, delta_E::Float64, passthrough
    )
    m.energy[] += delta_E
    conf[i] *= -1
    nothing
end

# optimized for 2D case
@propagate_inbounds @bm function propose_local(
        mc::MC, m::IsingModel{SquareLattice}, i::Int, conf::IsingConf
    )
    neighs = m.l.neighs
    @inbounds delta_E = 2.0 * conf[i] * (
        conf[neighs[1, i]] + conf[neighs[2, i]] +
        conf[neighs[3, i]] + conf[neighs[4, i]]
    )
    return delta_E, nothing
end

# optional functions/methods
"""
    global_move(mc::MC, m::IsingModel, conf::IsingConf) -> accepted::Bool

Constructs a Wolff cluster spinflip for configuration `conf`.
Returns wether a cluster spinflip has been performed (any spins have been flipped).
"""
@bm function global_move(mc::MC, m::IsingModel, conf::IsingConf)
    N = length(lattice(m))
    beta = mc.p.beta

    cluster = Array{Int, 1}()
    tocheck = Array{Int, 1}()

    s = rand(1:N)
    push!(tocheck, s)
    push!(cluster, s)

    while !isempty(tocheck)
        cur = pop!(tocheck)
        @inbounds for n in neighbors(m.l, cur)

            if conf[cur] == conf[n] && !(n in cluster) && rand() < (1 - exp(- 2.0 * beta))
                push!(tocheck, n)
                push!(cluster, n)
            end

        end
    end

    for spin in cluster
        conf[spin] *= -1
    end
    model.energy[] = energy(mc, m, conf)

    return length(cluster)>1
end

"""
    energy(mc::MC, m::IsingModel, conf::IsingConf)

Calculate energy of Ising configuration `conf` for Ising model `m`.
"""
function energy(mc::MC, m::IsingModel, conf::IsingConf)
    E = 0.0
    for (src, trg) in neighbors(m.l)
        E -= conf[src]*conf[trg]
    end
    m.energy[] = E
    return E
end

function energy(mc::MC, m::IsingModel{LT}, conf::IsingConf) where {
        LT <: Union{Chain, SquareLattice, CubicLattice}
    }
    E = 0.0
    @inbounds for (src, trg) in neighbors(m.l, Val(false))
        E -= conf[src]*conf[trg]
    end
    m.energy[] = E
    return E
end

"""
    energy(mc::MC, m::IsingModel{SquareLattice}, conf::IsingConf)

Calculate energy of Ising configuration `conf` for 2D Ising model `m`.
This method is a faster variant of the general method for the
square lattice case. (It is roughly twice as fast in this case.)
"""
function energy(mc::MC, m::IsingModel{SquareLattice}, conf::IsingConf)
    neighs = m.l.neighs
    E = 0.0
    @inbounds @simd for i in 1:length(lattice(m))
        E -= conf[i]*conf[neighs[1,i]] + conf[i]*conf[neighs[2,i]]
    end
    m.energy[] = E
    return E
end

function save_model(
        file::JLDFile,
        m::IsingModel,
        entryname::String="Model"
    )
    write(file, entryname * "/VERSION", 1)
    write(file, entryname * "/tag", "IsingModel")

    write(file, entryname * "/L", m.L)
    write(file, entryname * "/dims", m.dims)
    save_lattice(file, m.l, entryname * "/l")
    write(file, entryname * "/energy", m.energy[])
    nothing
end

#     load_model(data, ::Type{<: IsingModel})
#
# Loads an IsingModel from a given `data` dictionary produced by
# `JLD.load(filename)`.
function _load(data, ::Val{:IsingModel})
    if !(data["VERSION"] == 1)
        throw(ErrorException("Failed to load IsingModel version $(data["VERSION"])"))
    end

    l = _load(data["l"], to_tag(data["l"]))
    model = IsingModel(
        L = data["L"],
        dims = data["dims"],
        l = l
    )
    model.energy[] = data["energy"]
    model
end
to_tag(::Type{<: IsingModel}) = Val(:IsingModel)

compress(mc::MC, ::IsingModel, c) = BitArray(c .== 1)
compressed_conf_type(::Type{<: MC}, ::Type{<: IsingModel}) = BitArray
function decompress(mc::MC{M, CT}, ::IsingModel, c) where {M, CT}
    CT(2c .- 1)
end

include("measurements.jl")


text:
abstract type AbstractObserver end

measure!(o::AbstractObserver; kwargs...) = nothing
checkdone!(o::AbstractObserver; kwargs...) = false

"""
NoObserver is a trivial implementation of an
observer type which can be used as a default
argument for DMRG routines taking an AbstractObserver
"""
struct NoObserver <: AbstractObserver
end

const DMRGMeasurement = Vector{Vector{Float64}}

"""
DMRGObserver is an implementation of an
observer object (<:AbstractObserver) which
implements custom measurements and allows
the `dmrg` function to return early if an
energy convergence criterion is met.
"""
struct DMRGObserver <: AbstractObserver
  ops::Vector{String}
  sites::Vector{<:Index}
  measurements::Dict{String,DMRGMeasurement}
  energies::Vector{Float64}
  truncerrs::Vector{Float64}
  etol::Float64
  minsweeps::Int64

  function DMRGObserver(energy_tol=0.0,
                        minsweeps=2)
    new([],[],Dict{String,DMRGMeasurement}(),[],[],energy_tol,minsweeps)
  end

  function DMRGObserver(ops::Vector{String},
                        sites::Vector{<:Index};
                        energy_tol=0.0,
                        minsweeps=2)
    measurements = Dict(o => DMRGMeasurement() for o in ops)
    return new(ops,sites,measurements,[],[],energy_tol,minsweeps)
  end
end

measurements(o::DMRGObserver) = o.measurements
energies(o::DMRGObserver) = o.energies
sites(obs::DMRGObserver) = obs.sites
ops(obs::DMRGObserver) = obs.ops
truncerrors(obs::DMRGObserver) = obs.truncerrs

function measurelocalops!(obs::DMRGObserver,
                          wf::ITensor,
                          i::Int)
  for o in ops(obs)
    m = dot(wf, noprime(op(sites(obs),o,i)*wf))
    imag(m)>1e-8 && (@warn "encountered finite imaginary part when measuring $o")
    measurements(obs)[o][end][i]=real(m)
  end
end

function measure!(obs::DMRGObserver;
                  kwargs...)
  half_sweep = kwargs[:half_sweep]
  b = kwargs[:bond]
  energy = kwargs[:energy]
  psi = kwargs[:psi]
  truncerr = truncerror(kwargs[:spec])

  if half_sweep==2
    N = length(psi)

    if b==(N-1)
      for o in ops(obs)
        push!(measurements(obs)[o],zeros(N))
      end
      push!(truncerrors(obs),0.0)
    end

    # when sweeping left the orthogonality center is located
    # at site n=b after the bond update.
    # We want to measure at n=b+1 because there the tensor has been
    # already fully updated (by the right and left pass of the sweep).
    wf = psi[b]*psi[b+1]
    measurelocalops!(obs,wf,b+1)

    if b==1
      push!(energies(obs), energy)
      measurelocalops!(obs,wf,b)
    end
    truncerr > truncerrors(obs)[end] && (truncerrors(obs)[end] = truncerr)
  end
end

function checkdone!(o::DMRGObserver; kwargs...)
  outputlevel = get(kwargs,:outputlevel,false)
  if (length(energies(o)) > o.minsweeps &&
      abs(energies(o)[end] - energies(o)[end-1]) < o.etol)
    outputlevel > 0 && println("Energy difference less than $(o.etol), stopping DMRG")
    return true
  end
  return false
end


text:
using OrdinaryDiffEq, Flux, Optim, Random, Plots
using Zygote
using ForwardDiff
using LinearAlgebra, Statistics
using ProgressBars, Printf
using Flux.Optimise: update!, ExpDecay
using Flux.Losses: mae, mse
using BSON: @save, @load

Random.seed!(1234);

###################################
# Argments
is_restart = true;
p_cutoff = 0.0;
n_epoch = 100000;
n_plot = 100;
opt = ADAMW(1.f-3, (0.9, 0.999), 1.f-6);
datasize = 50;
tstep = 1;
n_exp_train = 20;
n_exp_test = 10;
n_exp = n_exp_train + n_exp_test;
noise = 0.05;
ns = 6;
nr = 3;
alg = Tsit5();
atol = 1e-5;
rtol = 1e-2;

p = randn(Float32, nr * (ns + 2) + 1) .* 1.f-1;
p[1:nr] .+= 0.8;
p[nr * (ns + 1) + 1:nr * (ns + 2)] .+= 0.8;
p[nr * (ns + 2) + 1] = 0.1;

lambda = 0.1
alpha = ones(Float32, ns);

lb = 1.f-5;
ub = 1.f1;
####################################

function trueODEfunc(dydt, y, k, t)
    # TG(1),ROH(2),DG(3),MG(4),GL(5),R'CO2R(6)
    r1 = k[1] * y[1] * y[2];
    r2 = k[2] * y[3] * y[2];
    r3 = k[3] * y[4] * y[2];
    dydt[1] = - r1;  # TG
    dydt[2] = - r1 - r2 - r3;  # TG
    dydt[3] = r1 - r2;  # DG
    dydt[4] = r2 - r3;  # MG
    dydt[5] = r3;  # GL
    dydt[6] = r1 + r2 + r3;  # R'CO2R
    dydt[7] = 0.f0;
end

logA = Float32[18.60f0, 19.13f0, 7.93f0];
Ea = Float32[14.54f0, 14.42f0, 6.47f0];  # kcal/mol

function Arrhenius(logA, Ea, T)
    R = 1.98720425864083f-3;
    k = exp.(logA) .* exp.(-Ea ./ R ./ T);
    return k;
end

# Generate data sets
u0_list = rand(Float32, (n_exp, ns + 1));
u0_list[:, 1:2] = u0_list[:, 1:2] .* 2.0 .+ 0.2;
u0_list[:, 3:ns] .= 0.0;
u0_list[:, ns + 1] = u0_list[:, ns + 1] .* 20.0 .+ 323.0;  # T[K]
tspan = Float32[0.0, datasize * tstep];
tsteps = range(tspan[1], tspan[2], length=datasize);
ode_data_list = zeros(Float32, (n_exp, ns, datasize));
std_list = [];

# u0 = u0_list[1, :];
# k = Arrhenius(logA, Ea, u0[end]);
# prob_trueode = ODEProblem(trueODEfunc, u0, tspan, k);
# ode_data = Array(solve(prob_trueode, alg, saveat=tsteps))

function max_min(ode_data)
    return maximum(ode_data, dims=2) .- minimum(ode_data, dims=2) .+ lb
end

for i in 1:n_exp
    u0 = u0_list[i, :];
    k = Arrhenius(logA, Ea, u0[end]);
    prob_trueode = ODEProblem(trueODEfunc, u0, tspan, k);
    ode_data = Array(solve(prob_trueode, alg, saveat=tsteps))[1:end - 1, :];
    ode_data += randn(size(ode_data)) .* ode_data .* noise
    ode_data_list[i, :, :] = ode_data
    push!(std_list, max_min(ode_data));
end

y_std = maximum(hcat(std_list...), dims=2);
# y_std[3:4] ./= 2.f0;

function p2vec(p)
    slope = p[nr * (ns + 2) + 1] .* 1.f2;
    w_b = p[1:nr] .* slope;
    w_out = reshape(p[nr + 1:nr * (ns + 1)], ns, nr);

    # w_out[3, 1] = -1

    index = findall(abs.(w_out) .< p_cutoff);
    w_out[index] .= 0;

    # w_out = clamp.(w_out, -2.5, 2.5);
    w_in_Ea = abs.(p[nr * (ns + 1) + 1:nr * (ns + 2)] .* slope);
    # w_in_Ea = clamp.(w_in_Ea, 0.f0, 30.f0);

    w_in = clamp.(-w_out, 0.f0, 4.f0);
    w_in = vcat(w_in, w_in_Ea');

    return w_in, w_b, w_out
end

w_in, w_b, w_out = p2vec(p);

R = 1.98720425864083f-3;
function crnn(du, u, p, t)
    logX = @. log(clamp(u[1:end - 1], lb, ub));
    w_in_x = w_in' * vcat(logX, -1.f0 / R / u[end]);
    du .= vcat(w_out * (@. exp(w_in_x + w_b)), 0.f0);
end

u0 = u0_list[1, :];
prob = ODEProblem(crnn, u0, tspan, saveat=tsteps,
                  atol=atol, rtol=rtol)
# @benchmark sol = solve(prob, alg, u0=u0, p=p)

function predict_neuralode(u0, p)
    global w_in, w_b, w_out = p2vec(p);
    pred = clamp.(Array(solve(prob, alg, u0=u0, p=p)), -ub, ub)
    return pred
end
# @benchmark predict_neuralode(u0, p)
predict_neuralode(u0, p)

function display_p(p)
    w_in, w_b, w_out = p2vec(p);

    println("species (column) reaction (row)")
    println("w_in")
    show(stdout, "text/plain", round.(w_in', digits=3))

    println("\nw_b")
    show(stdout, "text/plain", round.(w_b', digits=3))

    println("\nw_out")
    show(stdout, "text/plain", round.(w_out', digits=3))

    println("\n\n")
end
display_p(p)

i_obs = [1, 2, 3, 4, 5, 6];
function loss_neuralode(p, i_exp)
    ode_data = @view ode_data_list[i_exp, i_obs, :]
    pred = predict_neuralode(u0_list[i_exp, :], p)[i_obs, :]
    loss = mae(ode_data ./ y_std[i_obs], pred ./ y_std[i_obs])
    # loss = mean(abs.(ode_data .- pred) ./ y_std[i_obs], dims=2)
    return loss
end
# loss_neuralode(p, 1);

species = ["TG","ROH","DG","MG","GL","R'CO2R"];
cbi = function (p, i_exp)
    ode_data = ode_data_list[i_exp, :, :]
    pred = predict_neuralode(u0_list[i_exp, :], p)

    @save "./checkpoint/cbi27_m3.bson" ode_data pred tsteps;

    list_plt = []
    for i in 1:ns
        plt = scatter(tsteps, ode_data[i,:],
                      markercolor=:transparent,
                      label="Exp",
                      framestyle=:box)
        plot!(plt, tsteps, pred[i,:], label="CRNN")
        plot!(xlabel="Time (minute)", ylabel="["*species[i]*"]")

        if i == 1
            plot!(plt, legend=true, framealpha=0)
        else
            plot!(plt, legend=false)
        end

        push!(list_plt, plt)
    end
    plt_all = plot(list_plt...)
    png(plt_all, string("figs/i_exp_", i_exp))
    return false
end

list_loss_train = []
list_loss_val = []
iter = 1
cb = function (p, loss_train, loss_val)
    global list_loss_train, list_loss_val, iter
    push!(list_loss_train, loss_train)
    push!(list_loss_val, loss_val)

    if iter % n_plot == 0
        display_p(p)

        @printf("min loss train %.4e val %.4e\n", minimum(list_loss_train), minimum(list_loss_val))

        list_exp = randperm(n_exp)[1:1];
        println("update plot for ", list_exp)
        for i_exp in list_exp
            cbi(p, i_exp)
        end

        plt_loss = plot(list_loss_train, xscale=:log10, yscale=:log10, framestyle=:box, label="Training");
        plot!(plt_loss, list_loss_val, label="Validation");
        plot!(xlabel="Epoch", ylabel="Loss")
        plot!(size=(400, 350))
        png(plt_loss, "figs/loss");

        # @save "./checkpoint/mymodel.bson" p opt list_loss_train list_loss_val iter;
    end

    iter += 1;
end

if is_restart
    @load "./checkpoint/mymodel.bson" p opt list_loss_train list_loss_val iter;
    iter += 1;
end

p_cutoff = 0.01

i_exp = 1
epochs = ProgressBar(iter:n_epoch)
loss_epoch = zeros(Float32, n_exp);

for i_exp in 1:n_exp
    loss_epoch[i_exp] = loss_neuralode(p, i_exp)
end
loss_train = mean(loss_epoch[1:n_exp_train]);
loss_val = mean(loss_epoch[n_exp_train + 1:end]);
# cb(p, loss_train, loss_val);
cbi(p, 27);

display_p(p)

pw = vcat(w_in, w_b', w_out)'
using DelimitedFiles
writedlm( "weights.csv",  pw, ',')

@printf("clip loss p_cutoff train val [%.1e, %.4e, %.4e]\n", p_cutoff, loss_train, loss_val)

# @printf("Fine tunning")

# opt = ADAMW(1.e-4, (0.9, 0.999), 1.f-10);

# for epoch in epochs
#     global p
#     for i_exp in randperm(n_exp_train)
#         grad = gradient(p) do x
#             Zygote.forwarddiff(x) do x
#                 loss_neuralode(x, i_exp)
#             end
#         end
#         update!(opt, p, grad[1])
#     end
#     for i_exp in 1:n_exp
#         loss_epoch[i_exp] = loss_neuralode(p, i_exp)
#     end
#     loss_train = mean(loss_epoch[1:n_exp_train]);
#     loss_val = mean(loss_epoch[n_exp_train + 1:end]);
#     set_description(epochs, string(@sprintf("Loss train %.4e val %.4e", loss_train, loss_val)))
#     cb(p, loss_train, loss_val);
# end

# @printf("fine tunning loss p_cutoff train val [%.1e, %.4e, %.4e]\n", p_cutoff, loss_train, loss_val)


text:
preptime(layers) = 2layers
remaining_time(current_time) = 60 - current_time
total_working_time(layers, current_time) = preptime(layers) + current_time


text:
abstract type AbstractVLAE end

function elbo(m::AbstractVLAE, x::AbstractArray{T,4}) where T
    # encoder pass - KL divergence
    μzs_σzs = _encoded_mu_vars(m, x)
    zs = map(y->rptrick(y...), μzs_σzs)
    kldl = sum(map(y->Flux.mean(kld(y...)), μzs_σzs))

    # decoder pass - logpdf
    lpdf = Flux.mean(logpdf(m, x, zs...))

    -kldl + lpdf
end

function _encoded_mu_vars(m::AbstractVLAE, x)
    nl = length(m.e)

    h = x
    mu_vars = map(1:nl) do i
        h = m.e[i](h)
        h, μz, σz = _extract_mu_var(m.f, h, i)
        (μz, σz)
    end
    mu_vars
end

function _extract_mu_var(f, h::AbstractArray{T,4}, i) where T
    nch = floor(Int,size(h,3)/2)
    μz, σz = mu_var(f[i](h[:,:,(nch+1):end,:]))
    h = h[:,:,1:nch,:]
    h, μz, σz
end

function _extract_mu_var(f, h::AbstractArray{T,2}, i) where T
    nch = floor(Int,size(h,1)/2)
    μz, σz = mu_var(f[i](h[(nch+1):end,:]))
    h = h[1:nch,:]
    h, μz, σz
end

function _decoder_out(m::AbstractVLAE, zs...)
    nl = length(m.d)
    @assert length(zs) == nl

    h = m.g[1](zs[end])
    # now, propagate through the decoder
    for i in 1:nl-1
        h1 = m.d[i](h)
        h2 = m.g[i+1](zs[end-i])
        h = _cat_arrays(h1, h2)
    end
    h = m.d[end](h)
end
function _decoded_mu_var(m::AbstractVLAE, zs...)
    h = _decoder_out(m, zs...)
    μx, σx = mu_var(h)
end
function _decoded_mu_var1(m::AbstractVLAE, zs...)
    h = _decoder_out(m, zs...)
    μx, σx = mu_var1(h)
end
_cat_arrays(h1::AbstractArray{T,4}, h2::AbstractArray{T,4}) where T = cat(h1, h2, dims=3)
_cat_arrays(h1::AbstractArray{T,2}, h2::AbstractArray{T,2}) where T = cat(h1, h2, dims=1)

# encoding functions
function _batched_encs(f, m, x, batchsize, args...; kwargs...)
    local encs
    @suppress begin
        encs = map(y->f(gpu(m), gpu(y), args...; kwargs...),
            Flux.Data.DataLoader(x, batchsize=batchsize))
    end
    [cat([y[i] for y in encs]..., dims=2) for i in 1:length(encs[1])]
end
function _batched_encs(f, m, x::AbstractArray{T,2}, batchsize, args...; kwargs...) where T
    local encs
    @suppress begin
        encs = map(y->cpu(f(m, y, args...; kwargs...)),
            Flux.Data.DataLoader(x, batchsize=batchsize))
    end
    [cat([y[i] for y in encs]..., dims=2) for i in 1:length(encs[1])]
end
function _encode_ith(m::AbstractVLAE, x, i::Int; mean=false)
    μzs_σzs = _encoded_mu_vars(m, x)
    if mean
        return [μzs_σzs[i][1]]
    else
        return [rptrick(μzs_σzs[i]...)]
    end
end
_encode_ith_batched(m::AbstractVLAE, x, i::Int; mean=false, batchsize=128) =
    _batched_encs(_encode_ith, m, x, batchsize, i; mean=mean)[1]
function _encode_all(m::AbstractVLAE, x; mean=false)
    if mean
        return Tuple(map(y->y[1], _encoded_mu_vars(m, x)))
    else
        return Tuple(map(y->rptrick(y...), _encoded_mu_vars(m, x)))
    end
end

"""
    encode(m::AbstractVLAE, x, [i::Int]; mean=false, batchsize=128)

Encoding in the i-th latent layer. If i is not given, all encodings are returned instead.
"""
encode(m::AbstractVLAE, x, i::Int; batchsize::Int=128, mean=false) =
    _encode_ith_batched(m , x, i; batchsize=batchsize, mean=mean)
encode(m::AbstractVLAE, x; batchsize::Int=128, mean=false) =
    _batched_encs(_encode_all, m, x, batchsize; mean=mean)
encode_mean(args...; kwargs...) = encode(args...; mean=true, kwargs...)
encode_all(m::AbstractVLAE, x; kwargs...) =
     encode(m, x; kwargs...)

# decoding functions
function decode(m::AbstractVLAE, zs...)
    # this is for 2D data
    if length(m.xdim) == 1
        μx, σx = _decoded_mu_var(m, zs...)
        return rptrick(μx, σx)
    end
    # this is for images
    if m.xdist == Val(:gaussian)
        μx, σx = _decoded_mu_var1(m, zs...)
        return devectorize(rptrick(μx, σx), m.xdim...)
    else # bernoulli
        return _decoder_out(m, zs...)
    end
end

reconstruct(m::AbstractVLAE, x) = decode(m, encode_all(m, x)...)

function reconstruction_probability(m::AbstractVLAE, x::AbstractArray{T,2}) where T
    zs = map(y->rptrick(y...), _encoded_mu_vars(m, x))
    return -logpdf(m, x, zs...)
end
function reconstruction_probability(m::AbstractVLAE, x::AbstractArray{T,4}) where T
    gx = gpu(x)
    zs = map(y->rptrick(y...), _encoded_mu_vars(m, gx))
    return -logpdf(m, gx, zs...)
end
reconstruction_probability(m::AbstractVLAE, x, L::Int) = mean([reconstruction_probability(m,x) for _ in 1:L])
function reconstruction_probability(m::AbstractVLAE, x, L::Int, batchsize::Int)
    if size(x, ndims(x)) == 0
        return Float32[]
    else
        return vcat(map(b->cpu(reconstruction_probability(m, b, L)), Flux.Data.DataLoader(x, batchsize=batchsize))...)
    end
end

function generate(m::AbstractVLAE, n::Int)
    nl = length(m.e)
    zs = [randn(Float32, m.zdim, n) for _ in 1:nl]

    if is_gpu(m)
        zs = gpu(zs)
    end

    cpu(decode(m, zs...))
end

is_gpu(m::AbstractVLAE) = typeof(m.f[1][2].W) <: Flux.CUDA.CuArray

max_stars_repo_name: vitskvara/HierarchicalAD

max_issues_repo_name: vitskvara/HierarchicalAD

max_forks_repo_name: vitskvara/HierarchicalAD


text:
using ApproxFun, SingularIntegralEquations, HypergeometricFunctions, SpecialFunctions, LinearAlgebra, Test
import SingularIntegralEquations: x̄sqrtx2real, sqrtx2, joukowskyinverse,
        joukowskyinversereal, joukowskyinverseabs, ⁺, ⁻, logabslegendremoment,
        stieltjeslegendremoment, stieltjesjacobimoment, stieltjesmoment, Directed,
        HypergeometricFunctions
import HypergeometricFunctions: _₂F₁general,_₂F₁Inf

## Special functions

@testset "Special function tests" begin
    for (a,b,c) in ((1,1,2),(2,2,4)), x in (1.1,10.1,1.5)
        @test _₂F₁(a,b,c,x+eps()im) ≈ _₂F₁(a,b,c,(x)⁺)
        @test _₂F₁(a,b,c,x-eps()im) ≈ _₂F₁(a,b,c,(x)⁻)
    end

    @test x̄sqrtx2real(2.0+3.0im) ≈ real(sqrtx2(2.0+3.0im)*(2.0-3.0im))

    for s in (true,false)
        for z in (2.0+3.0im,2.0,0.1)
            @test real(joukowskyinverse(Val{s},z+0im)) ≈ joukowskyinversereal(Val{s},z)
            @test abs(joukowskyinverse(Val{s},z+0im)) ≈ joukowskyinverseabs(Val{s},z)
        end

        p=0.1
        @test joukowskyinverse(Val{s},(p)⁺) ≈ joukowskyinverse(Val{s},p+0im)
        @test joukowskyinverse(Val{s},(p)⁻) ≈ joukowskyinverse(Val{s},p-0im)
    end

    x=Fun()
    @test sum(logabs(x-2.0)) ≈ logabslegendremoment(2.0)
    @test sum(logabs(x-(2.0+im))) ≈ logabslegendremoment(2.0+im)

    @test sqrt(Directed{true}(-0.1)) ≈ sqrt(-0.1-0.0im)
    @test sqrt(Directed{false}(-0.1)) ≈ sqrt(-0.1+0.0im)

    @test stieltjesmoment(Legendre(),0,0.1+0im) ≈ stieltjesmoment(Legendre(),0,Directed{true}(0.1))
    @test stieltjesmoment(Legendre(),0,0.1-0im) ≈ stieltjesmoment(Legendre(),0,Directed{false}(0.1))
    @test stieltjesjacobimoment(0.,0.,1,0.1+0im) ≈ stieltjesjacobimoment(0.,0.,1,0.1⁺)
    @test stieltjesjacobimoment(0.,0.,1,0.1-0im) ≈ stieltjesjacobimoment(0.,0.,1,0.1⁻)

    @test (stieltjesjacobimoment(0,0,0,0.1+0im)-stieltjesjacobimoment(0,0,0,0.1-0im))/(-2π*im) ≈ 1.0
    @test (stieltjesjacobimoment(0,0,1,0.1+0im)-stieltjesjacobimoment(0,0,1,0.1-0im))/(-2π*im) ≈ 0.1

    @test stieltjesjacobimoment(0.5,0,0,Directed{true}(0.1)) ≈ stieltjesjacobimoment(0.5,0,0,0.1+0im)
    @test stieltjesjacobimoment(0.5,0,0,Directed{false}(0.1)) ≈ stieltjesjacobimoment(0.5,0,0,0.1-0.0im)
end

include("HilbertTest.jl")
include("stieltjesmomentTest.jl")
include("stieltjesintegraltest.jl")
include("logkerneltest.jl")
include("CurveTest.jl")
include("FundamentalSolutionsTest.jl")
include("convolutionProductFunTest.jl")
include("GreensFunTest.jl")
include("NonlocalOperatorsTest.jl")

# Testing Travis CI abilities. Currently, Examples tests are slow.
#println("\nExamples test\n")
#
#include("ExamplesTest.jl")


text:
module MacroExpander
using  ..Fxcrd.MacroDatabase
using  ..Fxcrd.Tokenize
using  ..Fxcrd.ShellInterop
export MacroCall, analyze_line, compile_io, compile_str,
       ismacro, isend, ismultiline,
       nameof, preof, argsof, inputof

mutable struct MacroCall
  name::String
  pre::String
  args::Vector{String}
  input::String
  ismultiline::Bool

  MacroCall() = new("","",[],"",true)
end

ismacro(m::MacroCall) = m.name != "" && m.name != "@end"
ismultiline(m::MacroCall) = m.ismultiline
preof(m::MacroCall) = m.pre
nameof(m::MacroCall) = m.name
argsof(m::MacroCall) = m.args
inputof(m::MacroCall) = m.input
isend(m::MacroCall) = m.name == "@end"

function compile_io(io)
  compile_lines(readlines(io))
end

function compile_str(str)
  compile_lines(split(str, "\n"))
end

function compile_lines(lines)
  i = 1
  output = String[]
  gotmacro = false
  evaluate = false

  while i <= length(lines)
    m, i = read_macrocall(lines, i)
    if ismacro(m)
      ex = expand_macro(m)
      !isempty(ex) && append!(output, split(ex,"\n"))
      gotmacro = true
    else
      push!(output, lines[i])
      i += 1
    end
  end

  if gotmacro
    outstr = compile_lines(output)
  else
    outstr = join(output, "\n")
  end
  return outstr
end

function expand_macro(mcall)
  m = get_macro(mcall.name)
  return macrocall(m, mcall.args..., input=mcall.input)
end

function read_macrocall(lines, i)
  m = analyze_line(lines[i])
  if ismacro(m)
    if ismultiline(m)
      indent=""
      minput = String[]
      nested = 1
      ml = nothing
      while nested > 0
        @assert i < length(lines) "closing @end not found after multiline macro call ($m, $ml)"
        i += 1
        line = lines[i]
        ml = analyze_line(line)
        if ismacro(ml)
          if ismultiline(ml)
            nested += 1
          end
          push!(minput, line)
        elseif isend(ml)
          @assert argsof(ml) == [] && inputof(ml) == "" "other code alongside @end is not allowed"
          nested -= 1
          nested == 0 || push!(minput, line)
          nested == 0 && (indent = " "^(findfirst(line, '@')-1))
        else
          push!(minput, line)
        end
      end
      m.input = join(map(ln->remove_indent(indent,ln), minput),"\n")
    end
    i += 1
  end
  return m, i
end

function remove_indent(indent, line)
  if startswith(line, indent)
    indent != "" && (line = line[length(indent):end])
    if startswith(line, "  ")
      return line[3:end]
    else
      return line
    end
  else
    return line
  end
end

function analyze_line(line)
  tokens = tokenize(line)
  state = :pre
  macrocall = MacroCall()

  for t in tokens
    if state == :pre
      if t.typ == :macro
        macrocall.name = t.token
        macrocall.pre  = line[1:t.index-1]
        state = :args
      else
        pre_index = t.index
      end
    elseif state == :args
      if t.typ == :macromma
        macrocall.input = line[t.index+2:end]
        macrocall.ismultiline = false
        break
      else
        push!(macrocall.args, t.token)
      end
    end
  end

  return macrocall
end
end

max_stars_repo_name: fcard/Fxcrd

max_issues_repo_name: fcard/Fxcrd

max_forks_repo_name: fcard/Fxcrd


text:
"""
    ElectricFieldChargeDriftModel <: AbstractChargeDriftModel
"""
struct ElectricFieldChargeDriftModel{T <: SSDFloat} <: AbstractChargeDriftModel{T} end

ElectricFieldChargeDriftModel(T::Type{<:SSDFloat}) = ElectricFieldChargeDriftModel{T}()

function get_electron_drift_field(ef::Array{SVector{3,T},3}, ::ElectricFieldChargeDriftModel)::Array{SVector{3,T},3} where {T <: SSDFloat}
    return -ef
end
function get_hole_drift_field(ef::Array{SVector{3,T},3}, ::ElectricFieldChargeDriftModel)::Array{SVector{3,T},3} where {T <: SSDFloat}
    return ef
end

function getVe(fv::SVector{3, T}, cdm::ElectricFieldChargeDriftModel)::SVector{3, T} where {T <: SSDFloat}
    return -fv
end
function getVh(fv::SVector{3, T}, cdm::ElectricFieldChargeDriftModel)::SVector{3, T} where {T <: SSDFloat}
    return fv
end


text:
struct LabeledGraph{T}
    graph::LightGraphs.AbstractGraph
    labels::Dict{T, Int}
end

function LabeledGraph(g::LightGraphs.AbstractGraph)
    return LabeledGraph{Int}(g, Dict(i => i for i = LightGraphs.vertices(g)))
end

Base.copy(lg::LabeledGraph) = LabeledGraph(copy(lg.graph), copy(lg.labels))

function lg_vertices(lg::LabeledGraph{T})::Set{T} where {T}
    return Set(keys(lg.labels))
end

function convert_vertices(labels::Dict{T, Int}, vertices) where {T}
    rev = _reverse_labels(labels)
    return map(vertex -> rev[vertex], vertices)
end

function convert_vertices_rev(labels::Dict{T, Int}, vertices) where {T}
    return map(vertex -> labels[vertex], collect(vertices))
end

function lg_rem_vertex!(lg::LabeledGraph{T}, v::T)::Bool where {T}
    rev = _reverse_labels(lg.labels)

    n = lg.labels[v]
    last = rev[LightGraphs.nv(lg.graph)]
    lg.labels[last] = n
    delete!(lg.labels, v)
    return LightGraphs.rem_vertex!(lg.graph, n)
end

function lg_add_vertex!(lg::LabeledGraph{T}, v::T)::Bool where {T}
    lg.labels[v] = LightGraphs.nv(lg.graph) + 1
    return LightGraphs.add_vertex!(lg.graph)
end

function lg_add_edge!(lg::LabeledGraph{T}, x::T, y::T)::Bool where {T}
    return LightGraphs.add_edge!(lg.graph, lg.labels[x], lg.labels[y])
end

function lg_is_complete(lg::LabeledGraph{T})::Bool where {T}
    num_edges = LightGraphs.ne(lg.graph)
    num_vertices = LightGraphs.nv(lg.graph)
    return num_edges == (num_vertices * (num_vertices - 1)) / 2
end

function _reverse_labels(labels::Dict{K, V})::Dict{V, K} where {K, V}
    return Dict(value => key for (key, value) in labels)
end


text:
using LinearAlgebra
using BenchmarkTools

function run(n)
    nops = 2 * n ^ 3
    A, B, C = rand(n, n), rand(n, n), rand(n, n)
    b = @benchmark mul!($C, $A, $B)
    return nops / mean(b.times)
end

function bench()
    BLAS.set_num_threads(56)
    for i in 4096:-256:512
        println(i, ", ", run(i))
    end
    for i in 512:-32:64
        println(i, ", ", run(i))
    end
    for i in 64:-1:16
        println(i, ", ", run(i))
    end
end

max_stars_repo_name: marwahaha/QTensor

max_issues_repo_name: marwahaha/QTensor

max_forks_repo_name: marwahaha/QTensor


text:
#InspectDR: Top/high-level functionnality of Gtk layer
#-------------------------------------------------------------------------------

#==Callback wrapper functions (PlotWidget-level)
===============================================================================#
#=COMMENTS
 -Define callback wrapper functions with concrete types to assist with precompile.
 -Remove unecessary arguments/convert to proper types
=#
@guarded function cb_keypress(w::Ptr{Gtk.GObject}, event::Gtk.GdkEventKey, pwidget::PlotWidget)
	handleevent_keypress(pwidget.state, pwidget, event)
	nothing #Void signature
end
@guarded function cb_scalechanged(w::Ptr{Gtk.GObject}, pwidget::PlotWidget)
	handleevent_scalechanged(pwidget.state, pwidget)
	nothing #Void signature
end
@guarded function cb_mousepress(w::Ptr{Gtk.GObject}, event::Gtk.GdkEventButton, pwidget::PlotWidget)
	handleevent_mousepress(pwidget.state, pwidget, event)
	nothing #Void signature
end
@guarded function cb_mouserelease(w::Ptr{Gtk.GObject}, event::Gtk.GdkEventButton, pwidget::PlotWidget)
	handleevent_mouserelease(pwidget.state, pwidget, event)
	nothing #Void signature
end
@guarded function cb_mousemove(w::Ptr{Gtk.GObject}, event::Gtk.GdkEventMotion, pwidget::PlotWidget)
	handleevent_mousemove(pwidget.state, pwidget, event)
	nothing #Void signature
end
@guarded function cb_mousescroll(w::Ptr{Gtk.GObject}, event::Gtk.GdkEventScroll, pwidget::PlotWidget)
	handleevent_mousescroll(pwidget.state, pwidget, event)
	nothing #Void signature
end

#==Callback wrapper functions (GtkPlot-level)
===============================================================================#
@guarded function cb_mnufileexport(w::Ptr{Gtk.GObject}, gplot::GtkPlot)
	filepath = Gtk.save_dialog("Export plot...", _Gtk.Null(),
		(_Gtk.@FileFilter("*.png,*.svg,*.eps", name="All supported formats"), "*.png", "*.svg", "*.eps")
	)
	if isempty(filepath); return nothing; end

	ext = splitext(filepath)[end]
	mime = get(MAPEXT2MIME, ext, nothing)
	if nothing == mime
		Gtk.warn_dialog("Unrecognized file type: '$ext'")
		return nothing
	end

	try
		_write(filepath, mime, gplot)
	catch
		Gtk.warn_dialog("Write failed: '$filepath'")
	end
	nothing #Void signature
end
@guarded function cb_mnufileclose(w::Ptr{Gtk.GObject}, gplot::GtkPlot)
	window_close(gplot.wnd)
	nothing #Void signature
end

#==Higher-level event handlers
===============================================================================#
#plothover event: show plot coordinates under mouse.
#-------------------------------------------------------------------------------
plothover_coordformatting(lstyle::TickLabelStyle, lines::AbstractGridLines) =
	number_fmt() #Just use default
function plothover_coordformatting(lstyle::TickLabelStyle, lines::GridLines)
	fmt = TickLabelFormatting(lstyle, lines.rnginfo).fmt
	fmt.ndigits += 2 #TODO: Better algorithm?
	return fmt
end

function plothover_coordstr(axes::AxesRect, ext::PExtents2D, xlstyle::TickLabelStyle, ylstyle::TickLabelStyle, x::DReal, y::DReal)
	x = datamap_rev(x, axes.xscale)
	y = datamap_rev(y, axes.yscale)
	grid = gridlines(axes, ext)
	fmt = plothover_coordformatting(xlstyle, grid.xlines)
	xstr = formatted(x, fmt)
	fmt = plothover_coordformatting(ylstyle, grid.ylines)
	ystr = formatted(y, fmt)
	return "(x, y) = ($xstr, $ystr)"
end

#Show rectangular coordinates for Smith (not transformed, for the moment):
plothover_coordstr(axes::AxesSmith, ext::PExtents2D, xlstyle::TickLabelStyle, ylstyle::TickLabelStyle, x::DReal, y::DReal) =
	plothover_coordstr(AxesRect(:lin, :lin), ext, xlstyle, ylstyle, x, y)

function handleevent_plothover(gplot::GtkPlot, pwidget::PlotWidget, x::DReal, y::DReal)
	plot = pwidget.src
	lyt = plot.layout
	ext = getextents_xfrm(plot)
	statstr = plothover_coordstr(plot.axes, ext, lyt.xlabelformat, lyt.ylabelformat, x, y)
	setproperty!(gplot.status, :label, statstr)
end

#==Menu builders:
===============================================================================#
function Gtk_addmenu(parent::Union{_Gtk.Menu, _Gtk.MenuBar}, name::AbstractString)
	item = _Gtk.@MenuItem(name)
	mnu = _Gtk.@Menu(item)
	push!(parent, item)
	return mnu
end
function Gtk_addmenuitem(mnu::_Gtk.Menu, name::AbstractString)
	item = _Gtk.@MenuItem(name)
	push!(mnu, item)
	return item
end

#=="Constructors"
===============================================================================#

#-------------------------------------------------------------------------------
function PlotWidget(plot::Plot)
	vbox = _Gtk.@Box(true, 0)
		can_focus(vbox, true)
#		setproperty!(vbox, "focus-on-click", true)
#		setproperty!(vbox, :focus_on_click, true)
	canvas = Gtk.@Canvas()
		setproperty!(canvas, :vexpand, true)
	w_xscale = _Gtk.@Scale(false, 1:XAXIS_SCALEMAX)
		xscale = _Gtk.@Adjustment(w_xscale)
		setproperty!(xscale, :value, 1)
#		draw_value(w_xscale, false)
		value_pos(w_xscale, Int(GtkPositionType.GTK_POS_RIGHT))
	w_xpos = _Gtk.@Scale(false, -.5:XAXIS_POS_STEPRES:.5)
		xpos = _Gtk.@Adjustment(w_xpos)
		setproperty!(xpos, :value, 0)
#		draw_value(w_xpos, false)
		value_pos(w_xpos, Int(GtkPositionType.GTK_POS_RIGHT))

	push!(vbox, canvas)
	push!(vbox, w_xpos)
	push!(vbox, w_xscale)

	bufsurf = Cairo.CairoRGBSurface(width(canvas), height(canvas))
	#TODO: how do we get a maximum surface for all monitors?
	#TODO: or can we resize in some intelligent way??
	#bufsurf = Cairo.CairoRGBSurface(1920,1200) #Appears slow for average monitor size???
#	bufsurf = Gtk.cairo_surface_for(canvas) #create similar - does not work here
	pwidget = PlotWidget(vbox, canvas, plot,
		BoundingBox(0,1,0,1), ISNormal(),
		w_xscale, xscale, w_xpos, xpos,
		bufsurf, GtkSelection(), true, true,
		#Event handlers:
		nothing
	)

	#Register callback functions:
	signal_connect(cb_scalechanged, xscale, "value-changed", Void, (), false, pwidget)
	signal_connect(cb_scalechanged, xpos, "value-changed", Void, (), false, pwidget)
	signal_connect(cb_keypress, vbox, "key-press-event", Void, (Ref{Gtk.GdkEventKey},), false, pwidget)
	signal_connect(cb_mousepress, vbox, "button-press-event", Void, (Ref{Gtk.GdkEventButton},), false, pwidget)
	signal_connect(cb_mouserelease, vbox, "button-release-event", Void, (Ref{Gtk.GdkEventButton},), false, pwidget)
	signal_connect(cb_mousemove, vbox, "motion-notify-event", Void, (Ref{Gtk.GdkEventMotion},), false, pwidget)
	signal_connect(cb_mousescroll, vbox, "scroll-event", Void, (Ref{Gtk.GdkEventScroll},), false, pwidget)

	#Register event: draw function
	Gtk.@guarded Gtk.draw(pwidget.canvas) do canvas
		#=NOTE:
		PlotWidget should probably be subclassed from GtkCanvas (the draw event
		would then have a reference to the PlotWidget...), but Julia does not
		make this easy.  Instead, this function generates an annonymous function
		that implicitly has a reference to the appropriate PlotWidget instance.
		=#
		if invalidbuffersize(pwidget)
			render(pwidget)
		end
		ctx = getgc(pwidget.canvas)
		Cairo.set_source_surface(ctx, pwidget.bufsurf, 0, 0)
		Cairo.paint(ctx) #Applies contents of bufsurf
		selectionbox_draw(ctx, pwidget)
		#TODO: Can/should we explicitly Cairo.destroy(ctx)???
	end

	return pwidget
end

#-------------------------------------------------------------------------------
function GtkPlot(mp::Multiplot)
	#Generate graphical elements:
	mb = _Gtk.@MenuBar()
	mnufile = Gtk_addmenu(mb, "_File")
		mnuexport = Gtk_addmenuitem(mnufile, "_Export")
		push!(mnufile, _Gtk.@SeparatorMenuItem())
		mnuquit = Gtk_addmenuitem(mnufile, "_Quit")
	grd = Gtk.@Grid() #Main grid with different subplots.
		setproperty!(grd, :column_homogeneous, true)
		#setproperty!(grd, :column_spacing, 15) #Gap between
	status = _Gtk.@Label("")#"(x,y) =")
		setproperty!(status, :hexpand, true)
		setproperty!(status, :ellipsize, PANGO_ELLIPSIZE_END)
		setproperty!(status, :xalign, 0.0)
		sbar_frame = _Gtk.@Frame(status)
			setproperty!(sbar_frame, "shadow-type", GtkShadowType.GTK_SHADOW_ETCHED_IN)

	vbox = _Gtk.@Box(true, 0)
		push!(vbox, mb) #Menu bar
		push!(vbox, grd) #Subplots
		push!(vbox, sbar_frame) #status bar
	wnd = Gtk.@Window(vbox, "", 640, 480, true)
	settitle(GtkPlot, wnd, mp.title)

	properties = copy_properties(mp)
	gplot = GtkPlot(wnd, grd, [], properties, status)

	_focus = nothing
	ncols = properties.ncolumns

	#Add subplots:
	for (i, sp) in enumerate(mp.subplots)
		row = div(i-1, ncols)+1
		col = i - ((row-1)*ncols)
		pwidget = PlotWidget(sp)
		pwidget.eh_plothover = HandlerInfo(gplot, handleevent_plothover)
		_focus = pwidget.widget
		push!(gplot.subplots, pwidget)
		grd[col, row] = pwidget.widget
	end

	if _focus != nothing
		focus(wnd, _focus)
	end

	showall(wnd)
	signal_connect(cb_mnufileexport, mnuexport, "activate", Void, (), false, gplot)
	signal_connect(cb_mnufileclose, mnuquit, "activate", Void, (), false, gplot)

	return gplot
end

#-------------------------------------------------------------------------------
function GtkPlot(plot::Plot, args...; kwargs...)
	mp = Multiplot(args...; kwargs...)
	add(mp, plot)
	return GtkPlot(mp)
end
GtkPlot(args...; kwargs...) = GtkPlot(Plot2D(), args...; kwargs...)

#==High-level interface
===============================================================================#
function Base.display(d::GtkDisplay, mp::Multiplot)
	return GtkPlot(mp)
end
function Base.display(d::GtkDisplay, p::Plot)
	return GtkPlot(p)
end

#Last line


text:
module ColorMaps

using Colors
access_dict = Dict()

defaultN = 64

include("named_maps.jl")
include("data_only_maps.jl")
include("cubehelix.jl")
include("construct_from_string.jl")

# 1) from sequence of colors
# 1a) array of colors
# 1b) string of colors

# 2) by name

include("api_sets.jl")

end # module

include("../local_testing/all.jl")

max_stars_repo_name: lobingera/ColorMaps


text:
using FragProcessing
using Test

@testset "FragProcessing.jl" begin
    # Write your own tests here.
end


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

using Logging

using CUTEst
using NLPModels
using SolverBenchmark

using Printf
using DataFrames
using SolverTools
using Stopping

using OneDmin

probnames = sort(CUTEst.select(min_var=1,
                               max_var=1500,
                               max_con=0,
                               only_free_var=true))

@show length(probnames)
# Comment for the true test
 probnames = probnames[10:15]  # for testing quickly on a subset
# add a dummy copy of the first problem
probnames = insert!(probnames, 1, probnames[1])

problems = (CUTEstModel(probname) for probname in probnames)

γ = 1.0e-5
a = 0.0
b = Inf

scale = 1.0e-5

for (fn, fnsimple) ∈ [(:bracket_N, :N),(:bracket_s, :s),(:bracket_N3, :N3),(:bracket_s2Opt, :s2) ]

    @eval begin

        function $fnsimple(nlp)

            # Prepare a oneD model from a NLP model by using the line
            # model in the direction of the scaled gradient at the x0 point
            # of the NLP

            dir = -grad(nlp, nlp.meta.x0) * scale
            h = LineModel(nlp, nlp.meta.x0, dir);
            dϕt0 = grad(h,a)
            @assert dϕt0 < 0.0
            ϵ = max(abs(dϕt0),1.0)
            α = -γ*ϵ
            β =  γ*ϵ

            # setup the Stopping object
            stp = NLPStopping(h, OneDAtX(0.0,zeros(2)), tol_check=(a,b,c) -> ones(2))

            stp.meta.max_iter = 100

            reset!(h)
            reset!(nlp)
            reinit!(stp)

            OneDmin.initInf!()

            # Actual timing and execution
            t = @timed    stp = eval($fn)(h, a=a, b=b, α=α, β=β, stp=stp)

            # convert the information in Stopping to the "standard" diagnostic in JSO
            st = stp.meta.optimal
            fb = !stp.meta.unbounded_pb
            tb = !stp.meta.unbounded
            ferr = stp.meta.domainerror
            tired = stp.meta.tired
            iter = stp.meta.nb_of_stop

            tsol = stp.current_state.x
            fh = stp.current_state.fx
            dh = stp.current_state.gx

            status = :unknown
            st &&    (status = :first_order)
            (!fb) && (status = :unbounded)
            (!tb) && (status = :infeasible)
            (ferr)&& (status = :exception)
            tired && (status = :max_iter)  # should be more specific

            return GenericExecutionStats(status, h,
                                         solution = [tsol],
                                         iter = iter,
                                         primal_feas = tsol,  #  cheat to display the scalar solution
                                         dual_feas = abs(dh),
                                         objective = fh,
                                         elapsed_time = t[2],
                                         )
        end

    end
end

using OrderedCollections

solvers = OrderedDict{Symbol,Function}(
    :Sec => s,
    :Nwt => N,
    :Sec2 => s2,
    :Nwt3 => N3
)

# use versions accepting OrderedDict
include("my_profile_tools.jl")

stats = my_bmark_solvers(solvers, problems,
                      colstats = [:name, :nvar, :status, :neval_obj, :neval_grad, :objective, :dual_feas, :primal_feas])

# remove the dummy copy of the first problem for statistics
for s in solvers
    stats[s[1]] = stats[s[1]][2:end,:]
end

include("PPpdfPaper.jl")

p = my_performance_profile(stats,costs[1], title = costnames[1])
Plots.pdf(p, "Figure2")


text:
# http://docs.julialang.org/en/stable/stdlib/numbers/#random-numbers

new_name() = join(map(x->Char(x), rand(65:90, 2))) * repr(rand(100:999))

mutable struct Robot
    name::AbstractString

    Robot() = new(new_name())
end

function reset!(instance::Robot)
    instance.name = new_name()
    instance
end