text:
# Code used to generate Semidefinite Relaxation of Mixed Integer Quadratic Objective problems with an accurate
# solution from MOSEK

# Original problem has the following format:
# min_x   ||Ax-b||_2^2
# s.t.    x ∈ Z^n

workspace()
include("../../OSSDP/Code/src/Solver.jl")

using JLD, JuMP, Mosek, OSSDP

# this function creates a matrix A that slices out the diagonal entries Xii of a vectorized square matrix x=vec(X)
function createDiagonalExtractor(n)
  A = spzeros(n,n^2)
  A[1,1] = 1
  for iii=2:n-1
    col = (iii-1)*(n+1)
    A[iii,col+1] = 1
  end
  A[n,n^2] = 1
  return A
end

function createLMIconstMatrix(n)
  # assume the decision vector is like this [x,vec(X)]
  # M = spzeros((n+1)*(2*n),n+n^2)

  # # first add parts that belong to x and assign correct position in LMI
  # for iii=1:n
  #   E = spzeros(n+1,n+1)
  #   E[iii,end] = 1
  #   E[end,iii] = 1
  #   M[:,iii] = vec(E)
  # end

  # ind = n
  # # assign correct position of elements of X in LMI constraint
  # for jjj=1:n, iii=1:n
  #   E = spzeros(n+1,n+1)
  #   E[iii,jjj] = 1
  #   ind+=1
  #   M[:,ind] = vec(E)
  # end
  A1 = [zeros(n^2,n) kron(speye(n),speye(n))]

  # takes care of vec([X;x']) part
  Aa = [A1[1:n,:];1 zeros(1,n+n^2-1)]
  for i=1:n-1
    Aa = [Aa;A1[i*n+1:(i+1)*n,:];[zeros(1,i) 1 zeros(1,n+n^2-1-i)]]
  end
  # add vec([x;0]) part
  for i=0:n-1
    Aa = [Aa;zeros(1,i) 1 zeros(1,n+n^2-1-i)]
  end
  Aa = [Aa;spzeros(1,n+n^2)]
  return Aa
end

rng = MersenneTwister(12345)
dirPath =  "../DataFiles/Julia/MIQO/"
!ispath(dirPath) && mkdir(dirPath)

nn = 25

 for iii =1:1:nn
  # choose size of problem
  np = rand(rng,5:15)
  mp = 2*np
  A = randn(rng,mp,np)
  P = A'*A
  #xc: continous relaxation solution
  xc = rand(rng,np)
  q = -P*xc

  # scale problem to get fcts = -q'Pinv*q = -1
  # s = -q'*(P\q)
  # q = q./-s
  # P = P./-s
  # put problem into solver format
  # min   x'Ix - 1*t
  # s.t.  Ax + s1 = 0
  #       x = s4
  #       -t <= c'*x <=t
  # s1 in 0, s2,s3 in R+, s4 in SDPcone

  n = np+np^2
  m = (np+1)^2+np

  D = createDiagonalExtractor(np)
  LMI = createLMIconstMatrix(np)
  Aa = [speye(np,np) -D;-LMI]
  ba = [spzeros(np,1);spzeros((np+1)^2-1,1);1]
  Pa = spzeros(np+np^2,np+np^2)
  qa = [2*q;vec(P)]
  ra = 0.

  # specify cone
  Kf = 0
  Kl = np
  Kq = []
  Ks = [(np+1)^2]

  # K = OSSDPTypes.Cone(Kf,Kl,Kq,Ks)
  # setOFF = OSSDPSettings(rho=0.1,sigma=1e-6,alpha=1.6,max_iter=5000,verbose=true,checkTermination=1,scaling = 0,eps_abs = 1e-5,eps_rel=1e-5,adaptive_rho=false)
  # res1,nothing = OSSDP.solve(Pa,qa,Aa,ba,K,setOFF);

  # model = Model()
  # @variable(model, 0 <= x[1:np] <= 1,Int)
  # @objective(model,Min, norm(A*x-b)^2)

  # status = JuMP.solve(model)

  # solve accurately once with mosek
  model = Model(solver=MosekSolver())
  @variable(model, X[1:np,1:np])
  @variable(model, x[1:np])
  @objective(model,Min, trace(P*X) + 2*q'*x)

  @SDconstraint(model, [X x;x' 1] >= 0)
  for i=1:np
    @constraint(model, X[i,i] >= x[i])
  end
  status = JuMP.solve(model)

  objTrue = getobjectivevalue(model)
  solTrue = getvalue(x)

  nr = "$(iii)"
  if iii < 10
    nr = "0$(iii)"
  end
  problemType = "MIQO Relaxation"
  problemName = "MIQO"*nr

  fn = "MIQO"*nr*".jld"
  JLD.save(dirPath*fn,"n",n,"m",m,"A",Aa,"b",ba,"P",Pa,"q",qa,"r",ra,"objTrue",objTrue,"solTrue",solTrue,"problemType",problemType,"problemName",problemName,"Kf",Kf,"Kl",Kl,"Kq",Kq,"Ks",Ks)
  println("$(iii)/$(nn) completed!")
end


text:
module MicMods

using ModelingToolkit

export chak21_simp_system, chak21_phys_system

include("chakrawal21/chakrawal21simp.jl")
include("chakrawal21/chakrawal21phys.jl")

# Write your package code here.

end

ext: jl


text:
using Nextion: RangeNumber
#using Nextion: NoRangeNumber
using Test

@testset "RangeNumber" begin
    @testset "construct / isequal" begin
        a = RangeNumber(3, 1:7)
        @test a == 3
    end

    @testset "addition / overflow" begin
        a = RangeNumber(3, 1:7)
        @test a + a == 6
        @test_throws ErrorException a + a + a == 9
    end

    @testset "other construct" begin
        a = RangeNumber{Int64, 1:7}(3)
        @test a == 3

        @test_throws ErrorException a = RangeNumber{Int64, 1:7}(8)
    end

    #@testset "NoRangeNumber" begin
    #    a = NoRangeNumber(3)
    #    @test a == 3
    #end

end


text:
struct Progression
    severity::Severity
    # times given with respect to the infection time
    incubation_time::TimeDiff
    mild_symptoms_time::Union{Missing,TimeDiff}
    severe_symptoms_time::Union{Missing,TimeDiff}
    #critical_symptoms_time::Float32
    recovery_time::Union{Missing,TimeDiff}
    death_time::Union{Missing, TimeDiff}
    #Progression(severity::Severity, incubation_time::Real, mild_time::Real, severe_time::Real, recovery_time) = incubation < mild_time < severe_time < recovery_time
end

Progression() = Progression(Asymptomatic, missing, missing, missing, missing, missing)

# Asymptotic not allowed as yet (some asserts prevent them)
const severity_dists = [
  Categorical([0,  0.852,  0.144,  0.004]),
  Categorical([0,  0.848,  0.144,  0.008]),
  Categorical([0,  0.832,  0.141,  0.027]),
  Categorical([0,  0.793,  0.134,  0.073]),
  Categorical([0,  0.716,  0.121,  0.163]),
  Categorical([0,  0.596,  0.102,  0.302]),
]

const death_probs = [0.0, 0.0, 0.0, 0.49]

function sample_severity(rng::AbstractRNG, age::Real)
  dist = severity_dists[1]
  if age < 0;       error("age should be non-negative")
  elseif age < 40;  dist = severity_dists[1]
  elseif age < 50;  dist = severity_dists[2]
  elseif age < 60;  dist = severity_dists[3]
  elseif age < 70;  dist = severity_dists[4]
  elseif age < 80;  dist = severity_dists[5]
  else;             dist = severity_dists[6]
  end
  severity_int = rand(rng, dist)
  severity = rand(rng, dist) |> Severity
end

function sample_if_death(rng::AbstractRNG, severity::Severity)
  severity_int = severity |> UInt8
  death_prob = death_probs[severity_int]
  rand(rng) < death_prob
end

@inline function sample_progression(rng::AbstractRNG, age::Real,
    dist_incubation,
    dist_symptom_onset,
    dist_hospitalization,
    dist_mild_recovery,
    dist_severe_recovery,
    dist_death_time
  )

  severity = sample_severity(rng, age)

  mild_symptoms_time = missing
  severe_symptoms_time = missing
  recovery_time = missing
  death_time = missing

  incubation_time = rand(rng, dist_incubation)

  mild_symptoms_time = incubation_time + rand(rng, dist_symptom_onset)

  severe_symptoms_time = missing
  recovery_time = missing
  death_time = missing
  if (severity==Severe) || (severity==Critical)
    severe_symptoms_time = incubation_time + rand(rng, dist_hospitalization)
    if severe_symptoms_time <= mild_symptoms_time
      mild_symptoms_time = missing
    end
    recovery_time = severe_symptoms_time + rand(rng, dist_severe_recovery)
  else
    recovery_time = mild_symptoms_time + rand(rng, dist_mild_recovery)
  end

  if sample_if_death(rng, severity)
    death_time = incubation_time + rand(rng, dist_death_time)
    if death_time < severe_symptoms_time
      death_time = severe_symptoms_time
    end
    recovery_time = missing
  end

  Progression(
    severity,
    incubation_time |> TimeDiff,
    ismissing(mild_symptoms_time) ? missing : TimeDiff(mild_symptoms_time),
    ismissing(severe_symptoms_time) ? missing : TimeDiff(severe_symptoms_time),
    ismissing(recovery_time) ? missing : TimeDiff(recovery_time),
    ismissing(death_time) ? missing : TimeDiff(death_time)
  )
end

function resample!(
  rng::AbstractRNG,
  progressions, ages::AbstractArray{T} where T <: Real,
  dist_incubation_time,
  dist_symptom_onset_time,
  dist_hospitalization_time,
  dist_mild_recovery_time,
  dist_severe_recovery_time,
  dist_death_time)

  for i in 1:length(ages)
    progressions[i] = sample_progression(rng, ages[i],
      dist_incubation_time,
      dist_symptom_onset_time,
      dist_hospitalization_time,
      dist_mild_recovery_time,
      dist_severe_recovery_time,
      dist_death_time)
  end
  progressions
end

storagefloat(t::Union{Missing,TimeDiff})::Float32 = ismissing(t) ? NaN32 : Float32(t)
storagefloat(p::Progression, symbol::Symbol) = getproperty(p, symbol) |> storagefloat

function saveparams(dict, progressions::AbstractVector{Progression}, prefix::AbstractString="")
    dict[prefix*"severities"] = getproperty.(progressions, :severity)
    dict[prefix*"incubation_times"] = storagefloat.(progressions, :incubation_time)
    dict[prefix*"mild_symptoms_times"] = storagefloat.(progressions, :mild_symptoms_time)
    dict[prefix*"severe_symptoms_times"] = storagefloat.(progressions, :severe_symptoms_time)
    dict[prefix*"recovery_times"] = storagefloat.(progressions, :recovery_time)
    dict[prefix*"death_times"] = storagefloat.(progressions, :death_time)
end


text:
# include("./JlrsReflect.jl")

module SingleFieldBits
struct BitsTypeBool
    a::Bool
end

struct BitsTypeChar
    a::Char
end

struct BitsTypeUInt8
    a::UInt8
end

struct BitsTypeUInt16
    a::UInt16
end

struct BitsTypeUInt32
    a::UInt32
end

struct BitsTypeUInt64
    a::UInt64
end

struct BitsTypeUInt
    a::UInt
end

struct BitsTypeInt8
    a::Int8
end

struct BitsTypeInt16
    a::Int16
end

struct BitsTypeInt32
    a::Int32
end

struct BitsTypeInt64
    a::Int64
end

struct BitsTypeInt
    a::Int
end

struct BitsTypeFloat32
    a::Float32
end

struct BitsTypeFloat64
    a::Float64
end
end

module MultiFieldBits
struct BitsIntBool
    a::Int
    b::Bool
end

struct BitsCharFloat32Float64
    a::Char
    b::Float32
    c::Float64
end
end

module BitsWithCustom
struct BitsIntChar
    a::Int
    b::Char
end

struct BitsCharBitsIntChar
    a::Char
    b::BitsIntChar
end
end

module BitsWithTuples
struct BitsUInt8TupleInt32Int64
    a::UInt8
    b::Tuple{Int32, Int64}
end

struct BitsUInt8TupleInt32TupleInt16UInt16
    a::UInt8
    b::Tuple{Int32, Tuple{Int16, UInt16}}
end
end

module WithBitsUnion
struct SingleVariant
    a::Int8
    b::Union{Int32}
    c::Int8
end

struct DoubleVariant
    a::Int8
    b::Union{Int16, Int32}
    c::Int8
end

struct SizeAlignMismatch
    a::Int8
    b::Union{Tuple{Int16, Int16, Int16}, Int32}
    c::Int8
end

struct UnionInTuple
    a::Int8
    b::Tuple{Union{Int16, Int32}}
    c::Int8
end
end

module WithNonBitsUnion
struct NonBitsUnion
    a::Union{String,Real}
end
end

module WithStrings
struct WithString
    a::String
end
end

module WithGeneric
struct WithGenericT{T}
    a::T
end

struct WithNestedGenericT{T}
    a::WithGenericT{T}
end

struct WithSetGeneric
    a::WithGenericT{Int64}
end

struct WithValueType{N}
    a::Int64
end

withvaluetype(a::Int64) = WithValueType{2}(a)

struct WithGenericUnionAll
    a::WithGenericT
end

struct WithSetGenericTuple
    a::Tuple{WithGenericT{Int64}}
end

struct WithPropagatedLifetime
    a::WithGenericT{Module}
end

struct WithPropagatedLifetimes
    a::WithGenericT{Tuple{Int32, WithGenericT{Array{Int32, 2}}}}
end
end

module ZST
struct ZeroSized end
end

# JlrsReflect.reflect([
#     SingleFieldBits.BitsTypeBool,
#     SingleFieldBits.BitsTypeChar,
#     SingleFieldBits.BitsTypeUInt8,
#     SingleFieldBits.BitsTypeUInt16,
#     SingleFieldBits.BitsTypeUInt32,
#     SingleFieldBits.BitsTypeUInt64,
#     SingleFieldBits.BitsTypeUInt,
#     SingleFieldBits.BitsTypeInt8,
#     SingleFieldBits.BitsTypeInt16,
#     SingleFieldBits.BitsTypeInt32,
#     SingleFieldBits.BitsTypeInt64,
#     SingleFieldBits.BitsTypeInt,
#     SingleFieldBits.BitsTypeFloat32,
#     SingleFieldBits.BitsTypeFloat64,
#     MultiFieldBits.BitsIntBool,
#     MultiFieldBits.BitsCharFloat32Float64,
#     BitsWithCustom.BitsIntChar,
#     BitsWithCustom.BitsCharBitsIntChar,
#     BitsWithTuples.BitsUInt8TupleInt32Int64,
#     BitsWithTuples.BitsUInt8TupleInt32TupleInt16UInt16,
#     WithBitsUnion.SingleVariant,
#     WithBitsUnion.DoubleVariant,
#     WithBitsUnion.SizeAlignMismatch,
#     WithBitsUnion.UnionInTuple,
#     WithNonBitsUnion.NonBitsUnion,
#     WithGeneric.WithGenericT,
#     WithGeneric.WithNestedGenericT,
#     WithGeneric.WithSetGeneric,
#     WithGeneric.WithValueType,
#     WithGeneric.WithGenericUnionAll,
#     WithGeneric.WithSetGenericTuple,
#     WithGeneric.WithPropagatedLifetime,
#     WithGeneric.WithPropagatedLifetimes,
#     ZST.ZeroSized
# ])

max_stars_repo_name: marhkb/jlrs

max_issues_repo_name: marhkb/jlrs

max_forks_repo_name: marhkb/jlrs


text:
module Counters

export Counter, counter, clean!, incr!, mean, csv_print, collect_by_counts

import Base: show, length, getindex, sum, keys, (+), (==), hash
import Base: setindex!, collect
import Base: iterate
import Base: values
#import Base: start, done, next, iterate

using SparseArrays
export nnz

"""
A `Counter` is a device for keeping a count of how often we observe
various objects. It is created by giving a type such as
`c=Counter{String}()`.

Counts are retrieved with square brackets like a dictionary: `c["hello"]`.
It is safe to retrieve the count of an object never encountered, e.g.,
`c["goodbye"]`; in this case `0` is returned.

Counts may be assigned with `c[key]=amount`, but the more likely use
case is using `c[key]+=1` to count each time `key` is encountered.
"""
struct Counter{T<:Any} <: AbstractDict{T,Int}
    data::Dict{T,Int}
    function Counter{T}() where {T}
        d = Dict{T,Int}()
        C = new(d)
    end
end

Counter() = Counter{Any}()

# These items enable this to satisfy the Associative properties
#
# start(c::Counter) = start(c.data)
# done(c::Counter,s) = done(c.data,s)
# next(c::Counter,s) = next(c.data,s)

iterate(C::Counter{T}) where {T} = iterate(keys(C.data))
iterate(C::Counter{T}, s::Int) where {T} = iterate(keys(C.data), s)

"""
`length(c::Counter)` gives the number of entries monitored
by the Counter. Conceivably, some may have value `0`.

See also: `nnz`.
"""
length(c::Counter) = length(c.data)

function show(io::IO, c::Counter{T}) where {T}
    n = length(c.data)
    word = ifelse(n == 1, "entry", "entries")
    msg = "with $n $word"
    print(io, "Counter{$T} $msg")
end

show(c::Counter{T}) where {T} = show(stdout, c)

import Base.Multimedia.display

function display(c::Counter{T}) where {T}
    println("Counter{$T} with these nonzero values:")
    klist = collect(keys(c))
    try
        sort!(klist)
    catch
        1 + 1 # no action required if fail to sort
    end

    for k in klist
        if c[k] != 0
            println("$k ==> $(c.data[k])")
        end
    end
end

function getindex(c::Counter{T}, x::T) where {T}
    return get(c.data, x, 0)
end

"""
`keys(c::Counter)` returns an interator for the things counted by `c`.
"""
keys(c::Counter) = keys(c.data)

"""
`values(c::Counter)` returns an iterator for the counts in `c`.
"""
values(c::Counter) = values(c.data)

"""
`sum(c::Counter)` gives the total of the counts for all things
in `c`.
"""
sum(c::Counter) = sum(values(c))

"""
`nnz(c::Counter)` gives the number of keys in
the `Counter` with nonzero value.

See also: `length`.
"""
function SparseArrays.nnz(c::Counter)
    amt::Int = 0
    for k in keys(c)
        if c.data[k] != 0
            amt += 1
        end
    end
    return amt
end

setindex!(c::Counter{T}, val::Int, k::T) where {T} = c.data[k] = val > 0 ? val : 0

function ==(c::Counter{T}, d::Counter{T}) where {T}
    for k in keys(c)
        if c[k] != d[k]
            return false
        end
    end

    for k in keys(d)
        if c[k] != d[k]
            return false
        end
    end

    return true
end

isequal(c::Counter{T}, d::Counter{T}) where {T} = c == d

"""
`clean!(c)` removes all keys from `c` whose value is `0`.
Generally, it's not necessary to invoke this unless one
suspects that `c` contains *a lot* of keys associated with
a zero value.
"""
function clean!(c::Counter{T}) where {T}
    for k in keys(c)
        if c[k] == 0
            delete!(c.data, k)
        end
    end
    nothing
end

"""
`incr!(c,x)` increments the count for `x` by 1. This is equivalent to
`c[x]+=1`.

`incr!(c,items)` is more useful. Here `items` is an iterable collection
of keys and we increment the count for each element in `items`.

`incr!(c,d)` where `c` and `d` are counters will increment `c` by
the amounts held in `d`.
"""
incr!(c::Counter{T}, x::T) where {T} = c[x] += 1

function incr!(c::Counter, items)
    for x in items
        c[x] += 1
    end
end

function incr!(c::Counter{T}, d::Counter{T}) where {T}
    for k in keys(d)
        c[k] += d[k]
    end
end

"""
If `c` and `d` are `Counter`s, then `c+d` creates a new `Counter`
in which the count associated with an object `x` is `c[x]+d[x]`.
"""
function (+)(c::Counter{T}, d::Counter{T}) where {T}
    result = deepcopy(c)
    incr!(result, d)
    return result
end

"""
`collect(C)` for a `Counter` returns an array containing the elements of `C`
each repeated according to its multiplicty.
"""
function collect(c::Counter{T}) where {T}
    result = Vector{T}(undef, sum(c))
    idx = 0
    for k in keys(c)
        m = c[k]
        for j = 1:m
            idx += 1
            result[idx] = k
        end
    end
    return result
end

"""
    collect_by_counts(C::Counter)

Return a list of the elements counted by `C` in which the element
with the highest count is first, the element with the second highest
count is second, and so forth. Elements whose count is zero are excluded.
"""
function collect_by_counts(C::Counter{T}) where {T}
    clean!(C)
    lt(a::Pair{T,Int}, b::Pair{T,Int})::Bool = a[2] >= b[2]
    pairs = collect(C.data)
    sort!(pairs, lt = lt)
    return [p[1] for p in pairs]
end

"""
`mean(C::Counter)` computes the weighted average of the objects in `C`.
Of course, the counted objects must be a `Number`; their multiplicity
(weight) in the average is determined by their `C`-value.
"""
function mean(C::Counter{T}) where {T<:Number}
    total = zero(T)
    for k in keys(C)
        total += k * C[k]
    end
    return total / sum(C)
end

"""
`csv_print(C::Counter)` prints out `C` in a manner suitable for import into
a spreadsheet.
"""
function csv_print(C::Counter)
    klist = collect(keys(C))
    try
        sort!(klist)
    catch
    end
    for k in klist
        println("$k, $(C[k])")
    end
    nothing
end

"""
`counter(list)` creates a `Counter` whose elements are the
members of `list` with the appropriate multiplicities.
This may also be used if `list` is a `Set` or an `IntSet`
(in which case multiplicities will all be 1).
"""
function counter(list::AbstractArray)
    T = eltype(list)
    C = Counter{T}()
    for x in list
        incr!(C, x)
    end
    return C
end

counter(S::Base.AbstractSet) = counter(collect(S))

"""
Performing `hash` on a `Counter` will first apply `clean!` to the
`Counter` in order that equal `Counter` objects hash the same.
"""
function hash(C::Counter, h::UInt64 = UInt64(0))
    clean!(C)
    return hash(C.data, h)
end

end # module


text:
"""
    module Dispersions
"""
module Dispersions

export AbstractDispersion
export TwoLevelSystem
export susceptability
export jacobian_lasing

abstract type AbstractDispersion end

susceptability(χs::Tuple,args...) = map(x->susceptability(x,args...),χs)

include("Dispersions/TwoLevelSystems.jl")
using .TwoLevelSystems

include("Dispersions/Kerrs.jl")
using .Kerrs

end # module


text:
using BenchmarkTools

SUITE = BenchmarkGroup()
SUITE["sum"] = @benchmarkable sum($(randn(10_000)))


text:
struct WorkQueue{T}
  items::Vector{T}
end

WorkQueue{T}() where T = WorkQueue(T[])

WorkQueue() = WorkQueue{Any}()

function Base.push!(q::WorkQueue, x)
  i = findfirst(==(x), q.items)
  i === nothing || (deleteat!(q.items, i))
  push!(q.items, x)
  return q
end

function Base.push!(q::WorkQueue, xs...)
  for x in xs
    push!(q, x)
  end
  return q
end

Base.pop!(q::WorkQueue) = pop!(q.items)
Base.isempty(q::WorkQueue) = isempty(q.items)


text:
using Test

let
cd(@__DIR__)
midi = readMIDIFile("serenade_full.mid")
piano = midi.tracks[4]
notes = getnotes(piano, midi.tpq)
tpq = 960

triplets = [0, 1//3, 2//3, 1]
sixteenths = [0, 1//4, 2//4, 3//4, 1]

@testset "Classify triplets" begin

    @test isgrid(triplets)

    class = classify(notes, triplets)
    inbetw = [246
    450
    618
    619
    620
    627
    628
    629
    637
    638
    639
    640]

    @test length(class) == length(notes)
    @test findall(class .== 2) == inbetw

    @test sum( sum( class .== n ) for n in 1:4) == length(notes)
end
@testset "Classify 16ths" begin
    @test isgrid(sixteenths)
    class = classify(notes, sixteenths)
    @test length(class) == length(notes)
    @test sum( sum( class .== n ) for n in 1:5) == length(notes)
end

@testset "Quantize" begin

    tripletstpq = triplets.*960
    qnotes = quantize(notes, triplets)

    @test qnotes.tpq == notes.tpq
    @test length(notes) == length(qnotes)

    for f in (velocities, pitches)
        @test f(notes) == f(qnotes)
    end
    @test durations(notes) != durations(qnotes)

    qqnotes = quantize(notes, triplets, false)
    @test durations(notes) == durations(qqnotes)

    pos = positions(notes)
    qpos = positions(qnotes)

    @test positions(notes) !== positions(qnotes)
    @test mod.(qpos, 320) == zeros(length(notes))
end

@testset "quantize duration" begin

    for (i, grid) in enumerate([triplets, sixteenths])

        qnotes = quantize(notes, grid)

        dnotes = quantize_duration!(deepcopy(qnotes), grid)

        for note in dnotes
            @test note.duration != 0
            @test mod(note.duration, tpq÷(2+i)) == 0
        end

    end

end

end

@testset "Noninteger grid*tpq product" begin

    cd(@__DIR__)
    grid = [0,0.383,0.73,1]
    midi = readMIDIFile("serenade_full.mid")
    notes = getnotes(midi, 4)
    tpq = 960
    qnotes = quantize(notes, grid)
    for note in qnotes
        @test note.duration != 0
    end

end


text:
module Stations

using Utils
import Utils.GeoLoc

using Calendar
import Calendar.CalendarTime

import Base.show

abstract AbstractStation

type Observation

    # station of origin
    station::AbstractStation

    # observation time
    tm::CalendarTime

    # observed value
    value::Float64

    # name of the variable
    obs_type::String

    # variance of the observation
    var :: Float64

    # default constructor
    Observation(s, tm, value, obs_type, var) = new(s, tm, value, obs_type, var)

end

type Station <: AbstractStation

    # station id
    id::String

    # station name
    name::String

    # station location (lat/lon decimal)
    loc::GeoLoc

    # nearest grid point (tuple)
    ngp::(Int64, Int64)

    # station elevation (meters)
    elevation::Float64

    # dictionary mapping variable names to observations
    obs::Dict{String,Array{Observation}}

    # available observation types from the station
    sensors :: Array{String}

    Station() = new("", "", GeoLoc(0.0, 0.0), (-1,-1), 0.0,  Dict{String,Array{Observation}}(), Array(String,0))

    Station(id, name, loc, elevation) = new(id, name, loc, (-1,-1), elevation, Dict{String,Array{Observation}}(), Array(String,0))

end

obs_variance(o::Observation) = o.var
obs_value(o::Observation) = o.value
obs_type(o::Observation) = o.obs_type
obs_station(o::Observation) = o.station
obs_station_id(o::Observation) = o.station.id
nearest_grid_point(o::Observation) = o.station.ngp

function show(io::IO, o::Observation)
#    write(io, "Obs($o.value of $o.obs_type at $o.station.id, $o.tm with var $o.var)")
    print(io, "Obs(", o.obs_type, "=", o.value, " at ", o.station.id, ", ", o.tm, " with var ", o.var, ")")
end

obs_times(s::Station, obs_type::String) = [o.tm for o in observations(s, obs_type)]
obs_var(s::Station, obs_type::String) = s.obs[obs_type]
id(s::Station) = s.id
name(s::Station) = s.name
observations(s::Station, obs_type::String) = s.obs[obs_type]

function register_to_grid(s::Station, lat::Array{Float64,2}, lon::Array{Float64,2})
    s.ngp = ind2sub(size(lat), indmin( (s.loc.lat - lat).^2 + (s.loc.lon - lon).^2 ))
end

function observations(s::Station, obs_type::String, tm::Array{CalendarTime})

    # retrieve all the observations for the given type
    obs = s.obs[obs_type]
    otm = [o.tm for o in obs]
    obs_ret = Dict(CalendarTime, Observation)

    i, j = 1, 1
    while (i <= length(tm)) && (j <= length(otm))
        if tm[i] == otm[j]
            obs_ret[tm[i]] = obs[i]
            i += 1
            j += 1
        elseif tm[i] > obst[j]
            j += 1
        elseif tm[i] < obst[j]
            j += 1
        end
    end

    return obs_ret
end

function load_station_info(fname :: String)

    s = Station()

    # open file
    io = open(fname, "r")

    # read station id
    s.id = strip(readline_skip_comments(io))

    # read station name
    s.name = strip(readline_skip_comments(io))

    # read station geo location
    s.loc = Utils.parse_geolocation(readline_skip_comments(io))

    # read elevation
    s.elevation = float(strip(readline_skip_comments(io)))

    # read all observation types acquired by the station
    s.sensors = map(x -> strip(x), split(readline_skip_comments(io), ","))

    # create var time series containers
    for v in s.sensors
        s.obs[v] = Array(Float64, 0)
    end

    # close the info file
    close(io)

    return s
end

function load_station_data(s::Station, fname::String)
    # open file
    io = open(fname, "r")

    # read observations, time is first (and in GMT), then one value per measurement or nan if not available
    while !eof(io)

        # read the date (if cannot read date, file is empty)
        tm_line = readline_skip_comments(io)
        if tm_line == nothing  break end
        tm_str = strip(tm_line)
        tm = Calendar.parse("yyyy-MM-dd_HH:mm", tm_str, "GMT")

        # read in observed variables
        variables = map(x -> strip(x), split(readline_skip_comments(io), ","))

        # read in observed values
        vals = map(x -> float(x), split(readline_skip_comments(io), ","))

        # read in variances of observations
        variances = map(x -> float(x), split(readline_skip_comments(io), ","))

        # add each observation to the station dictionary
        for i in 1:length(variables)
            var = variables[i]
            push!(s.obs[var], Observation(s, tm, vals[i], var, variances[i]))
        end

    end

    # cleanup
    close(io)

    # return the created station
    return s

end

function build_observation_data(ss::Array{Station}, obs_type::String)
    Ns = length(ss)
    obs = Observation[]

    # observation data
    for s in ss
        append!(obs, observations(s, obs_type))
    end

    # repackage into a time-indexed structure
    obs_data = Dict{CalendarTime,Array{Observation}}()
    for o in obs
        if haskey(obs_data, o.tm) push!(obs_data[o.tm], o) else obs_data[o.tm] = [o] end
    end

    return obs_data
end

function readline_skip_comments(io :: IO)
    s = "#"
    while (length(s) == 0) || (s[1] == '#')
        if !eof(io)
            s = readline(io)
        else
            return nothing
        end
    end
    return s
end

end


text:
@doc raw"""
Axisymmetric tokamak equilibrium in (x,y,z) coordinates with covariant
components of the vector potential given by
```math
A (x,y,z) = \frac{1}{2} \frac{B_0}{q_0} \, \bigg( \frac{q_0 R_0 x z - r^2 y}{R^2} , \, \frac{q_0 R_0 y z + r^2 x}{R^2} , \, - q_0 R_0 \, \ln \bigg( \frac{R}{R_0} \bigg) \bigg)^T ,
```
resulting in the magnetic field with covariant components
```math
B (x,y,z) = \frac{B_0}{q_0} \, \bigg( - \frac{q_0 R_0 y + x z}{R^2} , \, \frac{q_0 R_0 x - y z}{R^2} , \, \frac{R - R_0}{R} \bigg)^T ,
```
where $R = \sqrt{ x^2 + y^2 }$ and $r = \sqrt{ (R - R_0)^2 + z^2 }$.

Parameters:
 * `R₀`: position of magnetic axis
 * `B₀`: B-field at magnetic axis
 * `q₀`: safety factor at magnetic axis
"""
struct AxisymmetricTokamakCartesian{T <: Number} <: CartesianEquilibrium
    name::String
    R₀::T
    B₀::T
    q₀::T

    function AxisymmetricTokamakCartesian{T}(R₀::T, B₀::T, q₀::T) where T <: Number
        new("AxisymmetricTokamakCartesianEquilibrium", R₀, B₀, q₀)
    end
end

AxisymmetricTokamakCartesian(R₀::T=1.0, B₀::T=1.0, q₀::T=2.0) where T <: Number = AxisymmetricTokamakCartesian{T}(R₀, B₀, q₀)

function Base.show(io::IO, equ::AxisymmetricTokamakCartesian)
    print(io, "Axisymmetric Tokamak Equilibrium in (x,y,z) Coordinates with\n")
    print(io, "  R₀ = ", equ.R₀, "\n")
    print(io, "  B₀ = ", equ.B₀, "\n")
    print(io, "  q₀ = ", equ.q₀)
end

function R(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    sqrt(R²(x,equ))
end

function R²(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    X(x,equ)^2 + Y(x,equ)^2
end

function r(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    sqrt(r²(x,equ))
end

function r²(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    (R(x,equ) - equ.R₀)^2 + Z(x,equ)^2
end

function θ(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    atan2(Z(x, equ), R(x, equ) - equ.R₀)
end

function ϕ(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    atan2(Y(x,equ), X(x,equ))
end

function A₁(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    + equ.B₀ * (equ.R₀ * X(x,equ) * Z(x,equ) - r²(x,equ) * Y(x,equ) / equ.q₀ ) / R²(x,equ) / 2
end

function A₂(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    + equ.B₀ * (equ.R₀ * Y(x,equ) * Z(x,equ) + r²(x,equ) * X(x,equ) / equ.q₀ ) / R²(x,equ) / 2
end

function A₃(x::AbstractArray{T,1}, equ::AxisymmetricTokamakCartesian) where {T <: Number}
    - equ.B₀ * equ.R₀ * log(R(x,equ) / equ.R₀) / 2
end

macro axisymmetric_tokamak_equilibrium_cartesian(R₀, B₀, q₀)
    generate_equilibrium_code(AxisymmetricTokamakCartesian(R₀, B₀, q₀); output=false)
end


text:
using CSV
using CategoricalArrays
using DataFrames
using MixedModels
using StandardizedPredictors
using StatsModels
using Tables

using MKL

# R-code provided by JA
# library(tidyverse)
# tot.add <- read_csv("tot.add.csv")

# tot <- tot.add %>%
#   select(-1) %>%
#   gather(region, conn, -(subjectID:scanner), -(timepoint)) %>%
#   mutate(timepoint.nu = as.numeric(timepoint),
#          timepoint = as.character(timepoint),
#          timepoint.nu = scale(timepoint.nu, center = TRUE, scale = FALSE))

dat = DataFrame(CSV.File("tot.add.csv"; missingstrings=["NA","","NaN"]))
select!(dat, Not([:Column1, :X1]))
dat = stack(dat,
            Not([:subjectID, :sex, :age, :ethnicity, :YoE, :YoE_labels, :inc_par, :income_labels, :scanner, :timepoint]);
            variable_name=:region, value_name=:conn)
transform!(dat, :subjectID => compress ∘ categorical,
                :sex => compress ∘ categorical,
                :ethnicity => compress ∘ categorical,
                :YoE_labels => compress ∘ categorical,
                :income_labels => compress ∘ categorical,
                :region => compress ∘ categorical;
           renamecols=false)

numeric = Dict(:timepoint => Center(2),
               :region => Grouping(),
               :subjectID => Grouping())
categoric = Dict(:timepoint => HelmertCoding(),
                 :region => Grouping(),
                 :subjectID => Grouping())

form = @formula(conn ~ 1 + timepoint + (1+timepoint|subjectID) + (1+timepoint|region))

# let's see if we can even construct a big model
@time mod_numeric = LinearMixedModel(form, dat; contrasts=numeric)
# seems to work, let's fit
@time let fname = "mod_numeric.json"
    if isfile(fname)
        restoreoptsum!(mod_numeric, fname)
    else
        # about 1s/iter on my computer, 600-700 iterations necessary
        fit!(mod_numeric)
        saveoptsum(fname, mod_numeric)
    end
    mod_numeric
end

# let's see if we can even construct a big model
@time mod_categoric = LinearMixedModel(form, dat; contrasts=categoric)

# sparsity doesn't help here
# tbl, _ = StatsModels.missing_omit(Tables.columntable(dat), form)
# sch = schema(form, tbl, categoric)
# form = apply_schema(form, sch, LinearMixedModel)
# y, Xs = modelcols(form, tbl)
# fe = first(Xs)
# Base.summarysize(fe)
# Base.summarysize(sparse(fe))
# mod_categoric = LinearMixedModel(y, Xs, form)

@time let fname = "mod_categoric.json"
    if isfile(fname)
        restoreoptsum!(mod_categoric, fname)
    else
        # about 10s/iter on my computer, 5200-5300 iterations necessary
        fit!(mod_categoric)
        saveoptsum(fname, mod_categoric)
    end

    mod_categoric
end

form_interaction = @formula(conn ~ 1 + timepoint + (1+timepoint|subjectID) + (1+timepoint|region & subjectID))

# let's see if we can even construct a big model
@time mod_numeric_interaction = LinearMixedModel(form_interaction, dat; contrasts=numeric)
# seems to work, let's fit
@time let fname = "mod_numeric_interaction.json"
    if isfile(fname)
        restoreoptsum!(mod_numeric_interaction, fname)
    else
        # about 15s/iter on my computer, did not let run for more than a few dozen iterations
        fit!(mod_numeric_interaction)
        saveoptsum(fname, mod_numeric_interaction)
    end
    mod_numeric_interaction
end

@time mod_categoric_interaction = LinearMixedModel(form_interaction, dat; contrasts=categoric)
@time let fname = "mod_categoric_interaction.json"
    if isfile(fname)
        restoreoptsum!(mod_categoric_interaction, fname)
    else
        # did not even try this
        fit!(mod_categoric_interaction)
        saveoptsum(fname, mod_categoric_interaction)
    end

    mod_categoric_interaction
end

max_stars_repo_name: palday/ades-fmri-lmm

max_issues_repo_name: palday/ades-fmri-lmm

max_forks_repo_name: palday/ades-fmri-lmm


text:
using Optim
using PyPlot
using StatsBase
using ForwardDiff
using celerite
include("regress.jl")

function test_sp500()

function log_like_derivative_wrapper(p0,p,x,t,y)
  n = length(t)
  nex = (4(p-p0)+2p0+1)*(n-1)+1
  m1 = 2(p-p0)+p0+2
  if p0 == p
    m1 = p0+ 1
  end
  width = 2m1+1
  indx::Vector{Int64} = collect(1:nex)
#  aex = zeros(Number,width,nex)
#  al_small= zeros(Number,m1,nex)
#  bex = zeros(Number,nex)

  function log_like(x::Vector)
    w0 = exp(x[1])
    alpha = exp(x[2:p+1])
    beta_real = exp(x[p+2:2p+1])
    beta_imag = zeros(eltype(x),p)
    if p > p0
      beta_imag[p0+1:p] = exp(x[2p+2:3p-p0+1])
    end
    aex = zeros(eltype(x),width,nex)
    al_small= zeros(eltype(x),m1,nex)
    bex = zeros(eltype(x),nex)
    logdeta = compile_matrix_symm(alpha,beta_real,beta_imag,w0,t,nex,aex,al_small,indx)
    log_like = compute_likelihood(p,p0,y,aex,al_small,indx,logdeta,bex)
#    println("alpha: ",alpha," beta_real: ",beta_real," white: ",w0," log_like: ",log_like)
    return -log_like
  end

## Optimize the likelihood:
  xdiff = copy(x)
## Now perturb x:
#  dlogdx = zeros(eltype(x),length(x))
#  log_like0=log_like(x)
#  println(log_like0,x)
#  log_like0=log_like(x)
#  x0 = copy(x)
#  for i=1:length(x)
#    x    = copy(x0)
#    if (x[i] == 0.) then
#      h = 1e-6
#    else
#      h = 1e-6*x[i]
#    end
#    x[i] = x[i]+h
#    println(i," ",x,size(x))
#    log_like_h = log_like(x)
#    dlogdx[i]=(log_like_h-log_like0)/h
#  end
#  result=ForwardDiff.gradient(log_like,xdiff)
#  result=ForwardDiff.gradient(log_like,xdiff)
#  println("Gradient AutoDiff:    ",result)
#  println("Gradient Finite diff: ",dlogdx)

  lower = log([1e-15, 1e-8,1e-8,1e-8,1e-8,1e-8, 1e-8,1e-8,1e-8,1e-8,1e-8, 1e-3,1e-3,1e-3,1e-3,1e-3])
  upper = log([1e4, 1e8,1e8,1e8,1e8,1e8, 1e4,1e4,1e4,1e4,1e4, 1e3,1e3,1e3,1e3,1e3])
#  result = optimize(log_like, xdiff, BFGS(), OptimizationOptions(autodiff = true))
#  result = optimize(DifferentiableFunction(log_like), xdiff, lower, upper, Fminbox(), optimizer=GradientDescent)
#  result = optimize(DifferentiableFunction(log_like), xdiff, lower, upper, Fminbox(), optimizer=NelderMead)
  result = optimize(DifferentiableFunction(log_like), xdiff, lower, upper, Fminbox(), optimizer=BFGS, optimizer_o= OptimizationOptions(autodiff = true))
#  result = optimize(DifferentiableFunction(log_like), xdiff, lower, upper, Fminbox(), optimizer=ConjugateGradient)
#  result = optimize(log_like, xdiff, BFGS())
#  result = optimize(log_like, x0, BFGS())
#  result = optimize(log_like, xdiff)
  println(result)
  return exp(Optim.minimizer(result)),Optim.minimum(result)
#  return result
end

# Read in S&P 500 data:

data = readdlm("data/table.csv",',')
#Date,Open,High,Low,Close,Volume,Adj Close
sp500 = Array{Float64}(vec(data[:,5]))
sp500 = log(sp500)
nt = length(sp500)
println("Length of data: ",length(sp500))
time = zeros(nt)
for i=1:nt
  time[i] = Date(data[i,1])-Date(data[nt,1])
end
plot(time,sp500)
read(STDIN,Char)

# Carry out linear regression:
ord = 1
fn = zeros(ord+1,nt)
tnorm = (time-time[1])/(time[nt]-time[1])
for i=1:ord+1
  fn[i,:]=tnorm.^(i-1)
end
sig = ones(nt)
coeff,cov = regress(fn,sp500,sig)
println("Coeff: ",coeff)
sp500_trend = zeros(nt)
sp500_sub = copy(sp500)
for i=1:nt
  for j=1:ord+1
    sp500_trend[i] += coeff[j]*fn[j,i]
  end
  sp500_sub[i] -= sp500_trend[i]
end

plot(time,sp500)
plot(time,sp500_trend)
plot(time,sp500_sub)
read(STDIN,Char)

# Compute ACF:
nt = length(time)
dt = median(time[2:nt]-time[1:nt-1])
lags = collect(0:1:200)
println(typeof(lags))
acf = autocov(sp500_sub,lags)
lags *=dt
clf()
# Now, model covariance:
acf_model = 3.5.*exp(-lags./100.).*cos(2.*pi.*lags)+0.5*cos(2.*pi*lags/0.5)
clf()
plot(lags,acf)
plot(lags,acf_model)
plot(lags,acf-acf_model)
#read(STDIN,Char)

# Initialize model with guessed parameters:

nperiod = 1
#period = logspace(log10(5.0),log10(5.0),nperiod)
#period = logspace(-1.0,2.0,nperiod)
period = logspace(0.0,0.0,nperiod)
#period = logspace(log10(1.1),log10(1.1),nperiod)
# Best fit from initial run with 3 kernels:
#[7.50113753448555e-14,0.052634997384683246,3.814476305265215,0.2990524739656785,0.43730650302365087,19.982885984516415,0.00012381766899862475,0.0001249074549875943,0.2638033900492329,6.285942400966896,12.5689911272956,0.2470381285466161]

# Best fit from initial run with 5 kernels.  ACF match looks terrible....  sp500_psd_v01.png
#New best fit- initial params: [-0.5986951906468994,-0.47390425458548036,0.9609731796508907,0.30004136703676076,-0.7217327410001237,0.5288721138262757,-0.16943295213003973,-0.012994821145197122,0.14289041773272704,-0.8402580004438254,-0.8430719194021692,0.4293014742447645,0.5908973910877733,-0.9694619555140389,-0.3467403161436997] best params: [0.7170661453521265,0.47776707889546643,0.7454845071892328,0.6907093846757348,0.40009162284219685,0.8568580106404585,0.0009290130419164398,1.234040420311936e-7,1.0270102480925339e-8,0.0004132060175645361,0.0003972692197700031,1.2044944615613637,1.572711606998557,0.3807616972409821,0.673615655353782] log like: -6.656152972205763e8

nkernel=2
xopt = Float64[]
log_like_opt = Inf

#xsave = -1.0+2.0*rand(15)
xsave = -1.0+2.0*rand(6)
nx = length(xsave)
for iperiod=1:nperiod
#  alpha   = [0.0526,3.814,0.3,0.5]
#  beta_real = [20.,1e-4,1e-4,0.26]
#  alpha   = [0.1,0.1,0.1,0.1]
#  beta_real = [1e-2,1e-2,1e-2,1e-2]
#  beta_imag = 2pi./[1.0,0.5,period[iperiod]]
  x0 = copy(xsave)
#  x0[nx]=log(2pi/period[iperiod])
  p = nkernel
  p0 = 1
  xbest,log_like_best = log_like_derivative_wrapper(p0,p,x0,time,sp500_sub)
  if log_like_best < log_like_opt
    println("New best fit- initial params: ",x0," best params: ",xbest," log like: ",log_like_best)
    log_like_opt = log_like_best
    xopt = xbest
# Plot the optimized ACF:
    acf_model = xbest[2].*exp(-lags.*xbest[nkernel+2])
    for j=2:nkernel
      acf_model += xbest[j+1]*exp(-lags.*xbest[nkernel+j+1]).*cos(lags.*xbest[2*nkernel+j])
    end
    acf_model[1] += xbest[1]
    clf()
    fig, axes = subplots(2,1)
    ax = axes[1,1]
    ax[:plot](lags,acf_model,"b-")
    ax[:plot](lags,acf,"r-")
    ax[:plot](lags,acf-acf_model,"g-")
    ax[:set_xlabel]("Time [yr]")
    ax[:set_ylabel]("Covariance [(ppm CO2)^2]")
#    read(STDIN,Char)
# Plot the power spectrum:
    nfreq = 1000
    omega = collect(logspace(log10(0.001),log10(1000.),nfreq))
    psd = zeros(nfreq)
    for i=1:nfreq
      psd[i] = 2.0*xbest[2]*xbest[nkernel+2]/(omega[i]^2+xbest[nkernel+2]^2)
      for j=2:nkernel
        psd[i] += 2.0*xbest[j+1]*xbest[nkernel+j+1]/((omega[i]-xbest[2*nkernel+j])^2+xbest[nkernel+j+1]^2)
      end
    end
#    clf()
    ax = axes[2,1]
    ax[:loglog](omega,psd,"k-")
    ax[:set_xlabel]("Frequency/omega [rad/yr]")
    ax[:set_ylabel]("Power")
    read(STDIN,Char)
  end
end
return
end


text:
# During handling of an execute_request (when execute_msg is !nothing),
# we redirect STDOUT and STDERR into "stream" messages sent to the IPython
# front-end.

const orig_STDOUT = STDOUT
const orig_STDERR = STDERR

# logging in verbose mode goes to original stdio streams.  Use macros
# so that we do not even evaluate the arguments in no-verbose modes
macro vprintln(x...)
    quote
        if verbose::Bool
            println(orig_STDOUT, $(x...))
        end
    end
end
macro verror_show(e, bt)
    quote
        if verbose::Bool
            Base.error_show(orig_STDERR, $e, $bt)
        end
    end
end

function send_stream(s::String, name::String)
    if !isempty(s)
        send_ipython(publish,
                     msg_pub(execute_msg, "stream",
                             ["name" => name, "data" => s]))
    end
end

function watch_stream(rd::IO, name::String)
    try
        while true
            s = readavailable(rd) # blocks until something available
	    send_stream(s, name)
            sleep(0.1) # a little delay to accumulate output
        end
    catch e
        # the IPython manager may send us a SIGINT if the user
        # chooses to interrupt the kernel; don't crash on this
        if isa(e, InterruptException)
            watch_stream(rd, name)
        else
            rethrow()
        end
    end
end

const read_stdout, write_stdout = redirect_stdout()
const read_stderr, write_stderr = redirect_stderr()

function watch_stdio()
    @async watch_stream(read_stdout, "stdout")
    @async watch_stream(read_stderr, "stderr")
end


text:
using CPUTime
using Plots, Colors

mutable struct Node
    x::Int64
    y::Int64
    cost::Float64
    parent::Tuple{Any, Any}
end

"""移動可能なノード

・なぜか関数dijkstra内で定義したらエラー
・[]が良くない？
"""
function options(x, y, x_max, y_max, gridmap)
    options = []
    if x+1 <= x_max
        if y+1 <= y_max
            if gridmap[y+1, x+1] == 0
                push!(options, (1, 1, sqrt(2)))
            end
        end
        if y >= 2
            if gridmap[y-1, x+1] == 0
                push!(options, (1, -1, sqrt(2)))
            end
        end
        if gridmap[y, x+1] == 0
            push!(options, (1, 0, 1.0))
        end
    end
    if x >= 2
        if y+1 <= y_max
            if gridmap[y+1, x-1] == 0
                push!(options, (-1, 1, sqrt(2)))
            end
        end
        if y >= 2
            if gridmap[y-1, x-1] == 0
                push!(options, (-1, -1, sqrt(2)))
            end
        end
        if gridmap[y, x-1] == 0
            push!(options, (-1, 0, 1.0))
        end
    else
        if y+1 <= y_max
            if gridmap[y+1, x] == 0
                push!(options, (0, 1, 1.0))
            end
        end
        if y >= 2
            if gridmap[y-1, x] == 0
            push!(options, (0, -1, 1.0))
            end
        end
    end

    return options
end

"""ダイクストラで最短経路探索"""
function dijkstra(gridmap::Matrix{Int64}, start, goal)

    x_max = size(gridmap)[1]
    y_max = size(gridmap)[2]

    """一番costが小さいnodeのidを探す"""
    function find_MinCost_id(d)
        for (i, id) in enumerate(keys(d))
            if i==1
                global minid = id
            elseif d[id].cost < d[minid].cost
                minid = id
            end
        end
        minid
    end

    start_node = Node(start[1], start[2], 0, (nothing, nothing))
    goal_node = Node(goal[1], goal[2], typemax(Float64), (nothing, nothing))

    open_set = Dict()
    closed_set = Dict()

    start_id = (start_node.x, start_node.y)
    open_set[start_id] = start_node

    while true
        temp_id = find_MinCost_id(open_set)
        temp_node = open_set[temp_id]

        if temp_node.x == goal_node.x & temp_node.y == goal_node.y
            println("探索終了")
            goal_node.parent = temp_node.parent
            goal_node.cost = temp_node.cost
            break
        end

        delete!(open_set, temp_id)
        closed_set[temp_id] = temp_node

        os = options(temp_node.x, temp_node.y, x_max, y_max, gridmap)
        for o in os
            Δx, Δy, Δcost = o
            new_node = Node(temp_node.x + Δx, temp_node.y + Δy, temp_node.cost + Δcost, temp_id)
            new_id = (new_node.x, new_node.y)

            if haskey(closed_set, new_id)
                """決定済みのとき"""
                continue
            elseif !haskey(open_set, new_id)
                """未探索のとき"""
                open_set[new_id] = new_node
            else
                """未決定のとき"""
                if open_set[new_id].cost >= new_node.cost
                    open_set[new_id] = new_node
                end
            end
        end
    end

    """決定済み集合から最短経路を組む"""
    function compute_optiomal_path(start_node, goal_node, closed_set)

        rx, ry = [goal_node.x], [goal_node.y]
        parent = goal_node.parent
        cost = goal_node.cost

        while parent != (start_node.x, start_node.y)
            node = closed_set[parent]
            push!(rx, node.x)
            push!(ry, node.y)
            cost += node.cost
            parent = node.parent
        end

        push!(rx, start_node.x)
        push!(ry, start_node.y)

        rx, ry, cost
    end

    rx, ry, total_cost = compute_optiomal_path(start_node, goal_node, closed_set)

    rx, ry, total_cost
end

function draw(rx, ry, start, goal, gridmap)
    plot(
        rx, ry,
        aspect_ratio=1, label="optiomal path", legend=:bottomright,
        xlims=(0, 11), ylims=(0, 11)
    )
    scatter!(start, markershape=:diamond, label="start")
    scatter!(goal, markershape=:star6, label="goal")

    # 障害物位置のデータ作成
    obs_id = findall(gridmap .> 0)  # 障害物のindex検索
    obs_x = Vector{Int64}(undef, length(obs_id))
    obs_y = Vector{Int64}(undef, length(obs_id))
    for i in 1:length(obs_id)
        obs_x[i] = obs_id[i][2]
        obs_y[i] = obs_id[i][1]

    end
    scatter!(obs_x, obs_y, marlershape=:star, label="obstacle")
end

function main_1()
    map_example = [
        0 0 0 0 0 0 1 0 0 0
        0 1 0 0 0 0 0 0 1 0
        0 1 1 1 1 0 0 0 1 0
        0 0 0 0 0 0 0 0 1 0
        0 0 0 1 1 0 0 0 1 0
        0 0 0 1 1 0 0 0 1 0
        0 0 0 1 1 0 0 0 0 0
        0 0 0 0 0 0 1 0 0 0
        0 0 0 0 0 0 1 0 0 0
        0 0 0 0 0 0 1 0 0 0
    ]  # mapの例．0は通過可能な点，1は通貨不可能な点を示す

    start = (1, 1)
    goal = (10, 10)

    rx, ry, total_cost = dijkstra(map_example, start, goal)  # ダイクストラ法実行
    draw(rx, ry, start, goal, map_example)

end

@time main_1()


text:
"""
Along same lines as  `@test_throws` but to test if a macro throw an exception when it is
expanded.
"""
macro test_macro_throws(err_expr, expr)
    quote
        err = nothing
        try
            @macroexpand($(esc(expr)))
        catch _err
            # https://github.com/JuliaLang/julia/pull/38379
            if VERSION >= v"1.7.0-DEV.937"
                err = _err
            else
                # until Julia v1.7
                # all errors thrown at macro expansion time are LoadErrors, we need to unwrap
                @assert _err isa LoadError
                err = _err.error
            end
        end
        # Reuse `@test_throws` logic
        if err !== nothing
            @test_throws $(esc(err_expr)) ($(Meta.quot(expr)); throw(err))
        else
            @test_throws $(esc(err_expr)) $(Meta.quot(expr))
        end
    end
end

# struct need to be defined outside of tests for julia 1.0 compat
struct NonDiffExample
    x
end

struct NonDiffCounterExample
    x
end

module NonDiffModuleExample
nondiff_2_1(x, y) = fill(7.5, 100)[x + y]
end

@testset "rule_definition_tools.jl" begin
    @testset "@non_differentiable" begin
        @testset "two input one output function" begin
            nondiff_2_1(x, y) = fill(7.5, 100)[x + y]
            @non_differentiable nondiff_2_1(::Any, ::Any)
            @test frule((ZeroTangent(), 1.2, 2.3), nondiff_2_1, 3, 2) == (7.5, NoTangent())
            res, pullback = rrule(nondiff_2_1, 3, 2)
            @test res == 7.5
            @test pullback(4.5) == (NoTangent(), NoTangent(), NoTangent())
        end

        @testset "one input, 2-tuple output function" begin
            nondiff_1_2(x) = (5.0, 3.0)
            @non_differentiable nondiff_1_2(::Any)
            @test frule((ZeroTangent(), 1.2), nondiff_1_2, 3.1) == ((5.0, 3.0), NoTangent())
            res, pullback = rrule(nondiff_1_2, 3.1)
            @test res == (5.0, 3.0)
            @test isequal(
                pullback(Tangent{Tuple{Float64,Float64}}(1.2, 3.2)),
                (NoTangent(), NoTangent()),
            )
        end

        @testset "constrained signature" begin
            nonembed_identity(x) = x
            @non_differentiable nonembed_identity(::Integer)

            @test frule((ZeroTangent(), 1.2), nonembed_identity, 2) == (2, NoTangent())
            @test frule((ZeroTangent(), 1.2), nonembed_identity, 2.0) == nothing

            res, pullback = rrule(nonembed_identity, 2)
            @test res == 2
            @test pullback(1.2) == (NoTangent(), NoTangent())

            @test rrule(nonembed_identity, 2.0) == nothing
        end

        @testset "Pointy UnionAll constraints" begin
            pointy_identity(x) = x
            @non_differentiable pointy_identity(::Vector{<:AbstractString})

            @test frule((ZeroTangent(), 1.2), pointy_identity, ["2"]) ==
                  (["2"], NoTangent())
            @test frule((ZeroTangent(), 1.2), pointy_identity, 2.0) == nothing

            res, pullback = rrule(pointy_identity, ["2"])
            @test res == ["2"]
            @test pullback(1.2) == (NoTangent(), NoTangent())

            @test rrule(pointy_identity, 2.0) == nothing
        end

        @testset "kwargs" begin
            kw_demo(x; kw=2.0) = x + kw
            @non_differentiable kw_demo(::Any)

            @testset "not setting kw" begin
                @assert kw_demo(1.5) == 3.5

                res, pullback = rrule(kw_demo, 1.5)
                @test res == 3.5
                @test pullback(4.1) == (NoTangent(), NoTangent())

                @test frule((ZeroTangent(), 11.1), kw_demo, 1.5) == (3.5, NoTangent())
            end

            @testset "setting kw" begin
                @assert kw_demo(1.5; kw=3.0) == 4.5

                res, pullback = rrule(kw_demo, 1.5; kw=3.0)
                @test res == 4.5
                @test pullback(1.1) == (NoTangent(), NoTangent())

                @test frule((ZeroTangent(), 11.1), kw_demo, 1.5; kw=3.0) ==
                      (4.5, NoTangent())
            end
        end

        @testset "Constructors" begin
            @non_differentiable NonDiffExample(::Any)

            @test isequal(
                frule((ZeroTangent(), 1.2), NonDiffExample, 2.0),
                (NonDiffExample(2.0), NoTangent()),
            )

            res, pullback = rrule(NonDiffExample, 2.0)
            @test res == NonDiffExample(2.0)
            @test pullback(1.2) == (NoTangent(), NoTangent())

            # https://github.com/JuliaDiff/ChainRulesCore.jl/issues/213
            # problem was that `@nondiff Foo(x)` was also defining rules for other types.
            # make sure that isn't happenning
            @test frule((ZeroTangent(), 1.2), NonDiffCounterExample, 2.0) === nothing
            @test rrule(NonDiffCounterExample, 2.0) === nothing
        end

        @testset "Varargs" begin
            fvarargs(a, xs...) = sum((a, xs...))
            @testset "xs::Float64..." begin
                @non_differentiable fvarargs(a, xs::Float64...)

                y, pb = rrule(fvarargs, 1)
                @test y == fvarargs(1)
                @test pb(1) == (NoTangent(), NoTangent())

                y, pb = rrule(fvarargs, 1, 2.0, 3.0)
                @test y == fvarargs(1, 2.0, 3.0)
                @test pb(1) == (NoTangent(), NoTangent(), NoTangent(), NoTangent())

                @test frule((1, 1), fvarargs, 1, 2.0) == (fvarargs(1, 2.0), NoTangent())

                @test frule((1, 1), fvarargs, 1, 2) == nothing
                @test rrule(fvarargs, 1, 2) == nothing
            end

            @testset "::Float64..." begin
                @non_differentiable fvarargs(a, ::Float64...)

                y, pb = rrule(fvarargs, 1, 2.0, 3.0)
                @test y == fvarargs(1, 2.0, 3.0)
                @test pb(1) == (NoTangent(), NoTangent(), NoTangent(), NoTangent())

                @test frule((1, 1), fvarargs, 1, 2.0) == (fvarargs(1, 2.0), NoTangent())
            end

            @testset "::Vararg{Float64}" begin
                @non_differentiable fvarargs(a, ::Vararg{Float64})

                y, pb = rrule(fvarargs, 1, 2.0, 3.0)
                @test y == fvarargs(1, 2.0, 3.0)
                @test pb(1) == (NoTangent(), NoTangent(), NoTangent(), NoTangent())

                @test frule((1, 1), fvarargs, 1, 2.0) == (fvarargs(1, 2.0), NoTangent())
            end

            @testset "::Vararg" begin
                @non_differentiable fvarargs(a, ::Vararg)
                @test frule((1, 1), fvarargs, 1, 2) == (fvarargs(1, 2), NoTangent())

                y, pb = rrule(fvarargs, 1, 1)
                @test y == fvarargs(1, 1)
                @test pb(1) == (NoTangent(), NoTangent(), NoTangent())
            end

            @testset "xs..." begin
                @non_differentiable fvarargs(a, xs...)
                @test frule((1, 1), fvarargs, 1, 2) == (fvarargs(1, 2), NoTangent())

                y, pb = rrule(fvarargs, 1, 1)
                @test y == fvarargs(1, 1)
                @test pb(1) == (NoTangent(), NoTangent(), NoTangent())
            end
        end

        @testset "Functors" begin
            (f::NonDiffExample)(y) = fill(7.5, 100)[f.x + y]
            @non_differentiable (::NonDiffExample)(::Any)
            @test frule((Tangent{NonDiffExample}(; x=1.2), 2.3), NonDiffExample(3), 2) ==
                  (7.5, NoTangent())
            res, pullback = rrule(NonDiffExample(3), 2)
            @test res == 7.5
            @test pullback(4.5) == (NoTangent(), NoTangent())
        end

        @testset "Module specified explicitly" begin
            @non_differentiable NonDiffModuleExample.nondiff_2_1(::Any, ::Any)
            @test frule(
                (ZeroTangent(), 1.2, 2.3), NonDiffModuleExample.nondiff_2_1, 3, 2
            ) == (7.5, NoTangent())
            res, pullback = rrule(NonDiffModuleExample.nondiff_2_1, 3, 2)
            @test res == 7.5
            @test pullback(4.5) == (NoTangent(), NoTangent(), NoTangent())
        end

        @testset "Not supported (Yet)" begin
            # Where clauses are not supported.
            @test_macro_throws(
                ErrorException,
                (@non_differentiable where_identity(::Vector{T}) where {T<:AbstractString})
            )
        end
    end

    @testset "@scalar_rule" begin
        @testset "@scalar_rule with multiple output" begin
            simo(x) = (x, 2x)
            @scalar_rule(simo(x), 1.0f0, 2.0f0)

            y, simo_pb = rrule(simo, π)

            @test simo_pb((10.0f0, 20.0f0)) == (NoTangent(), 50.0f0)

            y, ẏ = frule((NoTangent(), 50.0f0), simo, π)
            @test y == (π, 2π)
            @test ẏ == Tangent{typeof(y)}(50.0f0, 100.0f0)
            # make sure type is exactly as expected:
            @test ẏ isa Tangent{Tuple{Irrational{:π},Float64},Tuple{Float32,Float32}}

            xs, Ω = (3,), (3, 6)
            @test ChainRulesCore.derivatives_given_output(Ω, simo, xs...) ==
                  ((1.0f0,), (2.0f0,))
        end

        @testset "@scalar_rule projection" begin
            make_imaginary(x) = im * x
            @scalar_rule make_imaginary(x) im

            # note: the === will make sure that these are Float64, not ComplexF64
            @test (NoTangent(), 1.0) === rrule(make_imaginary, 2.0)[2](1.0 * im)
            @test (NoTangent(), 0.0) === rrule(make_imaginary, 2.0)[2](1.0)

            @test (NoTangent(), 1.0 + 0.0im) === rrule(make_imaginary, 2.0im)[2](1.0 * im)
            @test (NoTangent(), 0.0 - 1.0im) === rrule(make_imaginary, 2.0im)[2](1.0)
        end

        @testset "Regression tests against #276 and #265" begin
            # https://github.com/JuliaDiff/ChainRulesCore.jl/pull/276
            # https://github.com/JuliaDiff/ChainRulesCore.jl/pull/265
            # Symptom of these problems is creation of global variables and type instability

            num_globals_before = length(names(ChainRulesCore; all=true))

            simo2(x) = (x, 2x)
            @scalar_rule(simo2(x), 1.0, 2.0)
            _, simo2_pb = rrule(simo2, 43.0)
            # make sure it infers: inferability implies type stability
            @inferred simo2_pb(Tangent{Tuple{Float64,Float64}}(3.0, 6.0))

            # Test no new globals were created
            @test length(names(ChainRulesCore; all=true)) == num_globals_before

            # Example in #265
            simo3(x) = sincos(x)
            @scalar_rule simo3(x) @setup((sinx, cosx) = Ω) cosx -sinx
            _, simo3_pb = @inferred rrule(simo3, randn())
            @inferred simo3_pb(Tangent{Tuple{Float64,Float64}}(randn(), randn()))
        end
    end
end

#! format: off
# workaround for https://github.com/domluna/JuliaFormatter.jl/issues/484
module IsolatedModuleForTestingScoping
    # check that rules can be defined by macros without any additional imports
    using ChainRulesCore: @scalar_rule, @non_differentiable, @opt_out

    # ensure that functions, types etc. in module `ChainRulesCore` can't be resolved
    const ChainRulesCore = nothing

    # this is
    # https://github.com/JuliaDiff/ChainRulesCore.jl/issues/317
    fixed(x) = :abc
    @non_differentiable fixed(x)

    # check name collision between a primal input called `kwargs` and the actual keyword
    # arguments
    fixed_kwargs(x; kwargs...) = :abc
    @non_differentiable fixed_kwargs(kwargs)

    my_id(x) = x
    @scalar_rule(my_id(x), 1.0)

    # @opt_out
    first_oa(x, y) = x
    @scalar_rule(first_oa(x, y), (1, 0))
    # Declared without using the ChainRulesCore namespace qualification
    # see https://github.com/JuliaDiff/ChainRulesCore.jl/issues/545
    @opt_out rrule(::typeof(first_oa), x::T, y::T) where {T<:Float16}
    @opt_out frule(::Any, ::typeof(first_oa), x::T, y::T) where {T<:Float16}

    module IsolatedSubmodule
        # check that rules defined in isolated module without imports can be called
        # without errors
        using ChainRulesCore: frule, rrule, ZeroTangent, NoTangent, derivatives_given_output
        using ChainRulesCore: no_rrule, no_frule
        using ..IsolatedModuleForTestingScoping: fixed, fixed_kwargs, my_id, first_oa
        using Test

        @testset "@non_differentiable" begin
            for f in (fixed, fixed_kwargs)
                y, ẏ = frule((ZeroTangent(), randn()), f, randn())
                @test y === :abc
                @test ẏ === NoTangent()

                y, f_pullback = rrule(f, randn())
                @test y === :abc
                @test f_pullback(randn()) === (NoTangent(), NoTangent())
            end

            y, f_pullback = rrule(fixed_kwargs, randn(); keyword=randn())
            @test y === :abc
            @test f_pullback(randn()) === (NoTangent(), NoTangent())
        end

        @testset "@scalar_rule" begin
            x, ẋ = randn(2)
            y, ẏ = frule((ZeroTangent(), ẋ), my_id, x)
            @test y == x
            @test ẏ == ẋ

            Δy = randn()
            y, f_pullback = rrule(my_id, x)
            @test y == x
            @test f_pullback(Δy) == (NoTangent(), Δy)

            @test derivatives_given_output(y, my_id, x) == ((1.0,),)
        end

        @testset "@optout" begin
            # rrule
            @test rrule(first_oa, Float16(3.0), Float16(4.0)) === nothing
            @test !isempty(
                Iterators.filter(methods(no_rrule)) do m
                    m.sig <: Tuple{Any,typeof(first_oa),T,T} where {T<:Float16}
                end,
            )

            # frule
            @test frule((NoTangent(), 1, 0), first_oa, Float16(3.0), Float16(4.0)) ===
                nothing
            @test !isempty(
                Iterators.filter(methods(no_frule)) do m
                    m.sig <: Tuple{Any,Any,typeof(first_oa),T,T} where {T<:Float16}
                end,
            )
        end
    end
end
#! format: on


text:
# # Google Search 3.0

using Julio
using Julio: Events
using ContextManagers: @with, SharedResource

# This is an example taken from Rob Pike's 2012 talk *Go Concurrency Patterns*.

# Avoid timeout (search engine replicas)
# <https://talks.golang.org/2012/concurrency.slide#48>

# `replicas` is a tuple of callables with the signature `query -> promise`;
# e.g., `replicas = webs = (web1, web2)`.

first_response!(send_endpoint, query::AbstractString, replicas::Tuple) =
    put!(send_endpoint, Julio.select(Events.fetch.(query .|> replicas)...))

# Google Search 3.0
# <https://talks.golang.org/2012/concurrency.slide#50>

function replicated_search(webs, images, videos)
    query = "Julio"
    results = String[]
    send_endpoint, receive_endpoint = Julio.channel()
    try
        Julio.withtaskgroup() do tg
            @with(handle = SharedResource(send_endpoint)) do
                Julio.spawn!(first_response!, tg, handle, query, webs)
                Julio.spawn!(first_response!, tg, handle, query, images)
                Julio.spawn!(first_response!, tg, handle, query, videos)
            end
            Julio.spawn!(tg) do
                Julio.sleep(0.08)
                Julio.cancel!(tg)
            end
            append!(results, receive_endpoint)
            Julio.cancel!(tg)
        end
    finally
        close(receive_endpoint)
    end
    return results
end

# Setup code:

replicated_search_demo() = with_search_engines(replicated_search)

function with_close_hook(f)
    resources = []
    function closing(r)
        push!(resources, r)
        return r
    end
    try
        f(closing)
    finally
        foreach(close, resources)
    end
end

function spawn_fakesearch!(tg, label, closing)
    send_endpoint, receive_endpoint = Julio.channel()
    closing(send_endpoint)
    Julio.spawn!(tg) do
        try
            for (query, reply) in receive_endpoint
                sleep(rand(0.01:0.01:0.1))
                reply[] = "$label result for $query"
            end
        finally
            close(receive_endpoint)
        end
    end
    function request(query)
        reply = Julio.Promise()
        put!(send_endpoint, query => reply)
        return reply
    end
    return request
end

function with_search_engines(f)
    Julio.withtaskgroup() do tg
        with_close_hook() do closing
            web1 = spawn_fakesearch!(tg, "web1", closing)
            web2 = spawn_fakesearch!(tg, "web2", closing)
            image1 = spawn_fakesearch!(tg, "image1", closing)
            image2 = spawn_fakesearch!(tg, "image2", closing)
            video1 = spawn_fakesearch!(tg, "video1", closing)
            video2 = spawn_fakesearch!(tg, "video2", closing)
            f((web1, web2), (image1, image2), (video1, video2))
        end
    end
end

using Test

function test_replicated_search_demo()
    nok = 0
    for _ in 1:10
        results = replicated_search_demo()
        nok += length(results) == 3
    end
    @test nok > 0
end


text:
using Base.Test
using MPI

MPI.Init()

function gatherv_array(A, counts::Vector{Cint}, root)
    comm = MPI.COMM_WORLD
    B = MPI.Gatherv(A, counts, root, comm)
end

comm = MPI.COMM_WORLD
size = MPI.Comm_size(comm)
rank = MPI.Comm_rank(comm)
root = 0

# Defining this to make ones work for Char
Base.one(::Type{Char}) = '\01'

for typ in MPI.MPIDatatype.types

    A = ones(typ, mod(rank,2) + 1)
    counts = Cint[ mod(i,2) + 1 for i in 0:(size-1)]
    B = gatherv_array(A, counts, root)
    if rank == root
        @test B == ones(typ, 3 * div(size,2) + mod(size,2))
    end
end

MPI.Finalize()


text:
@testset "BidAsk functions" begin
    dt = DateTime(2000, 1, 1)
    ba = BidAsk(dt, 500.0, 501.1)

    @test midprice(ba) == (500.0 + 501.1)/2
    @test midprice(500.0, 501.1) == (500.0 + 501.1)/2

    @test spread(ba) == 501.1 - 500.0
    @test spread(500.0, 501.1) == 501.1 - 500.0
end


text:
struct OperationsProblemResults <: PSIResults
    base_power::Float64
    variable_values::Dict{Symbol, DataFrames.DataFrame}
    total_cost::Dict
    optimizer_log::Dict
    time_stamp::DataFrames.DataFrame
    dual_values::Dict{Symbol, Any}
    parameter_values::Dict{Symbol, DataFrames.DataFrame}
end

IS.get_base_power(result::OperationsProblemResults) = result.base_power
IS.get_variables(result::OperationsProblemResults) = result.variable_values
IS.get_total_cost(result::OperationsProblemResults) = result.total_cost
IS.get_optimizer_log(results::OperationsProblemResults) = results.optimizer_log
IS.get_time_stamp(result::OperationsProblemResults) = result.time_stamp
get_duals(result::OperationsProblemResults) = result.dual_values
IS.get_parameters(result::OperationsProblemResults) = result.parameter_values

function get_variable(res_model::OperationsProblemResults, key::Symbol)
    var_result = get(res_model.variable_values, key, nothing)
    if isnothing(var_result)
        throw(IS.ConflictingInputsError("No variable with key $(key) has been found."))
    end
    return var_result
end

function _find_duals(variables::Array)
    duals = []
    for i in 1:length(variables)
        if occursin("dual", String.(variables[i]))
            duals = vcat(duals, variables[i])
        end
    end
    return duals
end

"""
    results = load_operation_results(path)

This function can be used to load results from a folder
of results from a single-step problem, or for a single foulder
within a simulation.

# Arguments
- `path::AbstractString = folder path`
- `directory::AbstractString = "2019-10-03T09-18-00"`: the foulder name that contains
feather files of the results.

# Example
```julia
results = load_operation_results("/Users/test/2019-10-03T09-18-00")
```
"""
function load_operation_results(folder_path::AbstractString)
    if isfile(folder_path)
        throw(ArgumentError("Not a folder path."))
    end
    files_in_folder = readdir(folder_path)
    variable_list = setdiff(
        files_in_folder,
        ["time_stamp.feather", "base_power.json", "optimizer_log.json", "check.sha256"],
    )
    vars_result = Dict{Symbol, DataFrames.DataFrame}()
    dual_result = Dict{Symbol, Any}()
    dual_names = _find_duals(variable_list)
    param_names = _find_params(variable_list)
    variable_list = setdiff(variable_list, vcat(dual_names, param_names, ".DS_Store"))
    param_values = Dict{Symbol, DataFrames.DataFrame}()
    for name in variable_list
        variable_name = splitext(name)[1]
        file_path = joinpath(folder_path, name)
        vars_result[Symbol(variable_name)] = Feather.read(file_path)
    end
    for name in dual_names
        dual_name = splitext(name)[1]
        file_path = joinpath(folder_path, name)
        dual_result[Symbol(dual_name)] = Feather.read(file_path)
    end
    for name in param_names
        param_name = splitext(name)[1]
        file_path = joinpath(folder_path, name)
        param_values[Symbol(param_name)] = Feather.read(file_path)
    end
    optimizer_log = read_json(joinpath(folder_path, "optimizer_log.json"))
    time_stamp = Feather.read(joinpath(folder_path, "time_stamp.feather"))
    time_stamp = convert.(Dates.DateTime, time_stamp)
    base_power = JSON.read(joinpath(folder_path, "base_power.json"))[1]
    if size(time_stamp, 1) > find_var_length(vars_result, variable_list)
        time_stamp = shorten_time_stamp(time_stamp)
    end
    obj_value = Dict{Symbol, Any}(:OBJECTIVE_FUNCTION => optimizer_log["obj_value"])
    check_file_integrity(folder_path)
    results = OperationsProblemResults(
        base_power,
        vars_result,
        obj_value,
        optimizer_log,
        time_stamp,
        dual_result,
        param_values,
    )
    return results
end

# This method is also used by OperationsProblemResults
"""
    write_results(results::PSIResults, save_path::String)

Exports Operational Problem Results to a path

# Arguments
- `results::OperationsProblemResults`: results from the simulation
- `save_path::String`: folder path where the files will be written

# Accepted Key Words
- `file_type = CSV`: only CSV and featherfile are accepted
"""
function IS.write_results(results::PSIResults, folder_path::String; kwargs...)
    if !isdir(folder_path)
        throw(IS.ConflictingInputsError("Specified path is not valid. Run write_results to save results."))
    end
    write_data(get_variables(results), folder_path; kwargs...)
    if !isempty(get_duals(results))
        write_data(get_duals(results), folder_path; duals = true, kwargs...)
    end
    if !isempty(IS.get_parameters(results))
        write_data(IS.get_parameters(results), folder_path; params = true, kwargs...)
    end
    write_data(IS.get_base_power(results), folder_path)
    write_optimizer_log(results.optimizer_log, folder_path)
    write_data(IS.get_time_stamp(results), folder_path, "time_stamp"; kwargs...)
    files = readdir(folder_path)
    compute_file_hash(folder_path, files)
    @info("Files written to $folder_path folder.")
    return
end

# writes the results to CSV files in a folder path, but they can't be read back
function write_to_CSV(results::OperationsProblemResults, save_path::String; kwargs...)
    if !isdir(save_path)
        throw(IS.ConflictingInputsError("Specified path is not valid. Run write_results to save results."))
    end
    folder_path = mkdir(joinpath(
        save_path,
        replace_chars("$(round(Dates.now(), Dates.Minute))", ":", "-"),
    ))
    export_variables = Dict()
    for (k, v) in IS.get_variables(results)
        start = decode_symbol(k)[1]
        if start !== "ON" || start !== "START" || start != "STOP"
            export_variables[k] = IS.get_base_power(results) .* v
        else
            export_variables[k] = v
        end
    end
    write_data(export_variables, folder_path; file_type = CSV, kwargs...)
    if !isempty(get_duals(results))
        write_data(
            get_duals(results),
            folder_path;
            duals = true,
            file_type = CSV,
            kwargs...,
        )
    end
    export_parameters = Dict()
    if !isempty(IS.get_parameters(results))
        for (p, v) in IS.get_parameters(results)
            export_parameters[p] = IS.get_base_power(results) .* v
        end
        write_data(
            export_parameters,
            folder_path;
            params = true,
            file_type = CSV,
            kwargs...,
        )
    end
    write_optimizer_log(results.optimizer_log, folder_path)
    write_data(
        IS.get_time_stamp(results),
        folder_path,
        "time_stamp";
        file_type = CSV,
        kwargs...,
    )
    files = readdir(folder_path)
    compute_file_hash(folder_path, files)
    @info("Files written to $folder_path folder.")
    return
end

function _find_params(variables::Array)
    params = []
    for i in 1:length(variables)
        if occursin("parameter", String.(variables[i]))
            params = vcat(params, variables[i])
        end
    end
    return params
end


text:
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/allocator.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_zero_initialized_allocator()
    ccall((:rcutils_get_zero_initialized_allocator, librcutils), rcutils_allocator_t, ())
end

function rcutils_get_default_allocator()
    ccall((:rcutils_get_default_allocator, librcutils), rcutils_allocator_t, ())
end

function rcutils_allocator_is_valid(allocator)
    ccall((:rcutils_allocator_is_valid, librcutils), Bool, (Ptr{rcutils_allocator_t},), allocator)
end

function rcutils_reallocf(pointer, size, allocator)
    ccall((:rcutils_reallocf, librcutils), Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t, Ptr{rcutils_allocator_t}), pointer, size, allocator)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/cmdline_parser.h
# Automatically generated using Clang.jl wrap_c

function rcutils_cli_option_exist(_begin, _end, option)
    ccall((:rcutils_cli_option_exist, librcutils), Bool, (Ptr{Cstring}, Ptr{Cstring}, Cstring), _begin, _end, option)
end

function rcutils_cli_get_option(_begin, _end, option)
    ccall((:rcutils_cli_get_option, librcutils), Cstring, (Ptr{Cstring}, Ptr{Cstring}, Cstring), _begin, _end, option)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/error_handling.h
# Automatically generated using Clang.jl wrap_c

function rcutils_initialize_error_handling_thread_local_storage(allocator)
    ccall((:rcutils_initialize_error_handling_thread_local_storage, librcutils), rcutils_ret_t, (rcutils_allocator_t,), allocator)
end

function rcutils_set_error_state(error_string, file, line_number)
    ccall((:rcutils_set_error_state, librcutils), Cvoid, (Cstring, Cstring, Csize_t), error_string, file, line_number)
end

function rcutils_error_is_set()
    ccall((:rcutils_error_is_set, librcutils), Bool, ())
end

function rcutils_get_error_state()
    ccall((:rcutils_get_error_state, librcutils), Ptr{rcutils_error_state_t}, ())
end

function rcutils_get_error_string()
    ccall((:rcutils_get_error_string, librcutils), rcutils_error_string_t, ())
end

function rcutils_reset_error()
    ccall((:rcutils_reset_error, librcutils), Cvoid, ())
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/filesystem.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_cwd(buffer, max_length)
    ccall((:rcutils_get_cwd, librcutils), Bool, (Cstring, Csize_t), buffer, max_length)
end

function rcutils_is_directory(abs_path)
    ccall((:rcutils_is_directory, librcutils), Bool, (Cstring,), abs_path)
end

function rcutils_is_file(abs_path)
    ccall((:rcutils_is_file, librcutils), Bool, (Cstring,), abs_path)
end

function rcutils_exists(abs_path)
    ccall((:rcutils_exists, librcutils), Bool, (Cstring,), abs_path)
end

function rcutils_is_readable(abs_path)
    ccall((:rcutils_is_readable, librcutils), Bool, (Cstring,), abs_path)
end

function rcutils_is_writable(abs_path)
    ccall((:rcutils_is_writable, librcutils), Bool, (Cstring,), abs_path)
end

function rcutils_is_readable_and_writable(abs_path)
    ccall((:rcutils_is_readable_and_writable, librcutils), Bool, (Cstring,), abs_path)
end

function rcutils_join_path(left_hand_path, right_hand_path, allocator)
    ccall((:rcutils_join_path, librcutils), Cstring, (Cstring, Cstring, rcutils_allocator_t), left_hand_path, right_hand_path, allocator)
end

function rcutils_to_native_path(path, allocator)
    ccall((:rcutils_to_native_path, librcutils), Cstring, (Cstring, rcutils_allocator_t), path, allocator)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/find.h
# Automatically generated using Clang.jl wrap_c

function rcutils_find(str, delimiter)
    ccall((:rcutils_find, librcutils), Csize_t, (Cstring, Cchar), str, delimiter)
end

function rcutils_findn(str, delimiter, string_length)
    ccall((:rcutils_findn, librcutils), Csize_t, (Cstring, Cchar, Csize_t), str, delimiter, string_length)
end

function rcutils_find_last(str, delimiter)
    ccall((:rcutils_find_last, librcutils), Csize_t, (Cstring, Cchar), str, delimiter)
end

function rcutils_find_lastn(str, delimiter, string_length)
    ccall((:rcutils_find_lastn, librcutils), Csize_t, (Cstring, Cchar, Csize_t), str, delimiter, string_length)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/format_string.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/get_env.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_env(env_name, env_value)
    ccall((:rcutils_get_env, librcutils), Cstring, (Cstring, Ptr{Cstring}), env_name, env_value)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/isalnum_no_locale.h
# Automatically generated using Clang.jl wrap_c

function rcutils_isalnum_no_locale()
    ccall((:rcutils_isalnum_no_locale, librcutils), Cint, ())
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/logging.h
# Automatically generated using Clang.jl wrap_c

function rcutils_logging_initialize_with_allocator(allocator)
    ccall((:rcutils_logging_initialize_with_allocator, librcutils), rcutils_ret_t, (rcutils_allocator_t,), allocator)
end

function rcutils_logging_initialize()
    ccall((:rcutils_logging_initialize, librcutils), rcutils_ret_t, ())
end

function rcutils_logging_shutdown()
    ccall((:rcutils_logging_shutdown, librcutils), rcutils_ret_t, ())
end

function rcutils_logging_severity_level_from_string(severity_string, allocator, severity)
    ccall((:rcutils_logging_severity_level_from_string, librcutils), rcutils_ret_t, (Cstring, rcutils_allocator_t, Ptr{Cint}), severity_string, allocator, severity)
end

function rcutils_logging_get_output_handler()
    ccall((:rcutils_logging_get_output_handler, librcutils), rcutils_logging_output_handler_t, ())
end

function rcutils_logging_set_output_handler(_function)
    ccall((:rcutils_logging_set_output_handler, librcutils), Cvoid, (rcutils_logging_output_handler_t,), _function)
end

function rcutils_logging_format_message(location, severity, name, timestamp, msg, logging_output)
    ccall((:rcutils_logging_format_message, librcutils), rcutils_ret_t, (Ptr{rcutils_log_location_t}, Cint, Cstring, rcutils_time_point_value_t, Cstring, Ptr{rcutils_char_array_t}), location, severity, name, timestamp, msg, logging_output)
end

function rcutils_logging_get_default_logger_level()
    ccall((:rcutils_logging_get_default_logger_level, librcutils), Cint, ())
end

function rcutils_logging_set_default_logger_level(level)
    ccall((:rcutils_logging_set_default_logger_level, librcutils), Cvoid, (Cint,), level)
end

function rcutils_logging_get_logger_level(name)
    ccall((:rcutils_logging_get_logger_level, librcutils), Cint, (Cstring,), name)
end

function rcutils_logging_get_logger_leveln(name, name_length)
    ccall((:rcutils_logging_get_logger_leveln, librcutils), Cint, (Cstring, Csize_t), name, name_length)
end

function rcutils_logging_set_logger_level(name, level)
    ccall((:rcutils_logging_set_logger_level, librcutils), rcutils_ret_t, (Cstring, Cint), name, level)
end

function rcutils_logging_logger_is_enabled_for(name, severity)
    ccall((:rcutils_logging_logger_is_enabled_for, librcutils), Bool, (Cstring, Cint), name, severity)
end

function rcutils_logging_get_logger_effective_level(name)
    ccall((:rcutils_logging_get_logger_effective_level, librcutils), Cint, (Cstring,), name)
end

# HACK: comment out because Clang.jl doesn't support va_list
# function rcutils_logging_console_output_handler(location, severity, name, timestamp, format, args)
#     ccall((:rcutils_logging_console_output_handler, librcutils), Cvoid, (Ptr{rcutils_log_location_t}, Cint, Cstring, rcutils_time_point_value_t, Cstring, Ptr{va_list}), location, severity, name, timestamp, format, args)
# end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/logging_macros.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/macros.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/repl_str.h
# Automatically generated using Clang.jl wrap_c

function rcutils_repl_str(str, from, to, allocator)
    ccall((:rcutils_repl_str, librcutils), Cstring, (Cstring, Cstring, Cstring, Ptr{rcutils_allocator_t}), str, from, to, allocator)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/snprintf.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/split.h
# Automatically generated using Clang.jl wrap_c

function rcutils_split(str, delimiter, allocator, string_array)
    ccall((:rcutils_split, librcutils), rcutils_ret_t, (Cstring, Cchar, rcutils_allocator_t, Ptr{rcutils_string_array_t}), str, delimiter, allocator, string_array)
end

function rcutils_split_last(str, delimiter, allocator, string_array)
    ccall((:rcutils_split_last, librcutils), rcutils_ret_t, (Cstring, Cchar, rcutils_allocator_t, Ptr{rcutils_string_array_t}), str, delimiter, allocator, string_array)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/stdatomic_helper.h
# Automatically generated using Clang.jl wrap_c

function rcutils_atomic_load_bool(a_bool)
    ccall((:rcutils_atomic_load_bool, librcutils), Bool, (Ptr{atomic_bool},), a_bool)
end

function rcutils_atomic_load_int64_t(a_int64_t)
    ccall((:rcutils_atomic_load_int64_t, librcutils), Int64, (Ptr{atomic_int_least64_t},), a_int64_t)
end

function rcutils_atomic_load_uint64_t(a_uint64_t)
    ccall((:rcutils_atomic_load_uint64_t, librcutils), UInt64, (Ptr{atomic_uint_least64_t},), a_uint64_t)
end

function rcutils_atomic_load_uintptr_t(a_uintptr_t)
    ccall((:rcutils_atomic_load_uintptr_t, librcutils), Csize_t, (Ptr{atomic_uintptr_t},), a_uintptr_t)
end

function rcutils_atomic_compare_exchange_strong_uint_least64_t(a_uint_least64_t, expected, desired)
    ccall((:rcutils_atomic_compare_exchange_strong_uint_least64_t, librcutils), Bool, (Ptr{atomic_uint_least64_t}, Ptr{UInt64}, UInt64), a_uint_least64_t, expected, desired)
end

function rcutils_atomic_exchange_bool(a_bool, desired)
    ccall((:rcutils_atomic_exchange_bool, librcutils), Bool, (Ptr{atomic_bool}, Bool), a_bool, desired)
end

function rcutils_atomic_exchange_int64_t(a_int64_t, desired)
    ccall((:rcutils_atomic_exchange_int64_t, librcutils), Int64, (Ptr{atomic_int_least64_t}, Int64), a_int64_t, desired)
end

function rcutils_atomic_exchange_uint64_t(a_uint64_t, desired)
    ccall((:rcutils_atomic_exchange_uint64_t, librcutils), UInt64, (Ptr{atomic_uint_least64_t}, UInt64), a_uint64_t, desired)
end

function rcutils_atomic_exchange_uintptr_t(a_uintptr_t, desired)
    ccall((:rcutils_atomic_exchange_uintptr_t, librcutils), Csize_t, (Ptr{atomic_uintptr_t}, Csize_t), a_uintptr_t, desired)
end

function rcutils_atomic_fetch_add_uint64_t(a_uint64_t, arg)
    ccall((:rcutils_atomic_fetch_add_uint64_t, librcutils), UInt64, (Ptr{atomic_uint_least64_t}, UInt64), a_uint64_t, arg)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/strdup.h
# Automatically generated using Clang.jl wrap_c

function rcutils_strdup(str, allocator)
    ccall((:rcutils_strdup, librcutils), Cstring, (Cstring, rcutils_allocator_t), str, allocator)
end

function rcutils_strndup(str, string_length, allocator)
    ccall((:rcutils_strndup, librcutils), Cstring, (Cstring, Csize_t, rcutils_allocator_t), str, string_length, allocator)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/time.h
# Automatically generated using Clang.jl wrap_c

function rcutils_system_time_now(now)
    ccall((:rcutils_system_time_now, librcutils), rcutils_ret_t, (Ptr{rcutils_time_point_value_t},), now)
end

function rcutils_steady_time_now(now)
    ccall((:rcutils_steady_time_now, librcutils), rcutils_ret_t, (Ptr{rcutils_time_point_value_t},), now)
end

function rcutils_time_point_value_as_nanoseconds_string(time_point, str, str_size)
    ccall((:rcutils_time_point_value_as_nanoseconds_string, librcutils), rcutils_ret_t, (Ptr{rcutils_time_point_value_t}, Cstring, Csize_t), time_point, str, str_size)
end

function rcutils_time_point_value_as_seconds_string(time_point, str, str_size)
    ccall((:rcutils_time_point_value_as_seconds_string, librcutils), rcutils_ret_t, (Ptr{rcutils_time_point_value_t}, Cstring, Csize_t), time_point, str, str_size)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/visibility_control.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/stdatomic_helper/gcc/stdatomic.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/stdatomic_helper/win32/stdatomic.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types/array_list.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_zero_initialized_array_list()
    ccall((:rcutils_get_zero_initialized_array_list, librcutils), rcutils_array_list_t, ())
end

function rcutils_array_list_init(array_list, initial_capacity, data_size, allocator)
    ccall((:rcutils_array_list_init, librcutils), rcutils_ret_t, (Ptr{rcutils_array_list_t}, Csize_t, Csize_t, Ptr{rcutils_allocator_t}), array_list, initial_capacity, data_size, allocator)
end

function rcutils_array_list_fini(array_list)
    ccall((:rcutils_array_list_fini, librcutils), rcutils_ret_t, (Ptr{rcutils_array_list_t},), array_list)
end

function rcutils_array_list_add(array_list, data)
    ccall((:rcutils_array_list_add, librcutils), rcutils_ret_t, (Ptr{rcutils_array_list_t}, Ptr{Cvoid}), array_list, data)
end

function rcutils_array_list_set(array_list, index, data)
    ccall((:rcutils_array_list_set, librcutils), rcutils_ret_t, (Ptr{rcutils_array_list_t}, Csize_t, Ptr{Cvoid}), array_list, index, data)
end

function rcutils_array_list_remove(array_list, index)
    ccall((:rcutils_array_list_remove, librcutils), rcutils_ret_t, (Ptr{rcutils_array_list_t}, Csize_t), array_list, index)
end

function rcutils_array_list_get(array_list, index, data)
    ccall((:rcutils_array_list_get, librcutils), rcutils_ret_t, (Ptr{rcutils_array_list_t}, Csize_t, Ptr{Cvoid}), array_list, index, data)
end

function rcutils_array_list_get_size(array_list, size)
    ccall((:rcutils_array_list_get_size, librcutils), rcutils_ret_t, (Ptr{rcutils_array_list_t}, Ptr{Csize_t}), array_list, size)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types/char_array.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_zero_initialized_char_array()
    ccall((:rcutils_get_zero_initialized_char_array, librcutils), rcutils_char_array_t, ())
end

function rcutils_char_array_init(char_array, buffer_capacity, allocator)
    ccall((:rcutils_char_array_init, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t}, Csize_t, Ptr{rcutils_allocator_t}), char_array, buffer_capacity, allocator)
end

function rcutils_char_array_fini(char_array)
    ccall((:rcutils_char_array_fini, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t},), char_array)
end

function rcutils_char_array_resize(char_array, new_size)
    ccall((:rcutils_char_array_resize, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t}, Csize_t), char_array, new_size)
end

function rcutils_char_array_expand_as_needed(char_array, new_size)
    ccall((:rcutils_char_array_expand_as_needed, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t}, Csize_t), char_array, new_size)
end

function rcutils_char_array_strncat(char_array, src, n)
    ccall((:rcutils_char_array_strncat, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t}, Cstring, Csize_t), char_array, src, n)
end

function rcutils_char_array_strcat(char_array, src)
    ccall((:rcutils_char_array_strcat, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t}, Cstring), char_array, src)
end

function rcutils_char_array_memcpy(char_array, src, n)
    ccall((:rcutils_char_array_memcpy, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t}, Cstring, Csize_t), char_array, src, n)
end

function rcutils_char_array_strcpy(char_array, src)
    ccall((:rcutils_char_array_strcpy, librcutils), rcutils_ret_t, (Ptr{rcutils_char_array_t}, Cstring), char_array, src)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types/hash_map.h
# Automatically generated using Clang.jl wrap_c

function rcutils_hash_map_string_hash_func(key_str)
    ccall((:rcutils_hash_map_string_hash_func, librcutils), Csize_t, (Ptr{Cvoid},), key_str)
end

function rcutils_hash_map_string_cmp_func(val1, val2)
    ccall((:rcutils_hash_map_string_cmp_func, librcutils), Cint, (Ptr{Cvoid}, Ptr{Cvoid}), val1, val2)
end

function rcutils_get_zero_initialized_hash_map()
    ccall((:rcutils_get_zero_initialized_hash_map, librcutils), rcutils_hash_map_t, ())
end

function rcutils_hash_map_init(hash_map, initial_capacity, key_size, data_size, key_hashing_func, key_cmp_func, allocator)
    ccall((:rcutils_hash_map_init, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t}, Csize_t, Csize_t, Csize_t, rcutils_hash_map_key_hasher_t, rcutils_hash_map_key_cmp_t, Ptr{rcutils_allocator_t}), hash_map, initial_capacity, key_size, data_size, key_hashing_func, key_cmp_func, allocator)
end

function rcutils_hash_map_fini(hash_map)
    ccall((:rcutils_hash_map_fini, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t},), hash_map)
end

function rcutils_hash_map_get_capacity(hash_map, capacity)
    ccall((:rcutils_hash_map_get_capacity, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t}, Ptr{Csize_t}), hash_map, capacity)
end

function rcutils_hash_map_get_size(hash_map, size)
    ccall((:rcutils_hash_map_get_size, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t}, Ptr{Csize_t}), hash_map, size)
end

function rcutils_hash_map_set(hash_map, key, value)
    ccall((:rcutils_hash_map_set, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t}, Ptr{Cvoid}, Ptr{Cvoid}), hash_map, key, value)
end

function rcutils_hash_map_unset(hash_map, key)
    ccall((:rcutils_hash_map_unset, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t}, Ptr{Cvoid}), hash_map, key)
end

function rcutils_hash_map_key_exists(hash_map, key)
    ccall((:rcutils_hash_map_key_exists, librcutils), Bool, (Ptr{rcutils_hash_map_t}, Ptr{Cvoid}), hash_map, key)
end

function rcutils_hash_map_get(hash_map, key, data)
    ccall((:rcutils_hash_map_get, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t}, Ptr{Cvoid}, Ptr{Cvoid}), hash_map, key, data)
end

function rcutils_hash_map_get_next_key_and_data(hash_map, previous_key, key, data)
    ccall((:rcutils_hash_map_get_next_key_and_data, librcutils), rcutils_ret_t, (Ptr{rcutils_hash_map_t}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), hash_map, previous_key, key, data)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types/rcutils_ret.h
# Automatically generated using Clang.jl wrap_c

# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types/string_array.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_zero_initialized_string_array()
    ccall((:rcutils_get_zero_initialized_string_array, librcutils), rcutils_string_array_t, ())
end

function rcutils_string_array_init(string_array, size, allocator)
    ccall((:rcutils_string_array_init, librcutils), rcutils_ret_t, (Ptr{rcutils_string_array_t}, Csize_t, Ptr{rcutils_allocator_t}), string_array, size, allocator)
end

function rcutils_string_array_fini(string_array)
    ccall((:rcutils_string_array_fini, librcutils), rcutils_ret_t, (Ptr{rcutils_string_array_t},), string_array)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types/string_map.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_zero_initialized_string_map()
    ccall((:rcutils_get_zero_initialized_string_map, librcutils), rcutils_string_map_t, ())
end

function rcutils_string_map_init(string_map, initial_capacity, allocator)
    ccall((:rcutils_string_map_init, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Csize_t, rcutils_allocator_t), string_map, initial_capacity, allocator)
end

function rcutils_string_map_fini(string_map)
    ccall((:rcutils_string_map_fini, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t},), string_map)
end

function rcutils_string_map_get_capacity(string_map, capacity)
    ccall((:rcutils_string_map_get_capacity, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Ptr{Csize_t}), string_map, capacity)
end

function rcutils_string_map_get_size(string_map, size)
    ccall((:rcutils_string_map_get_size, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Ptr{Csize_t}), string_map, size)
end

function rcutils_string_map_reserve(string_map, capacity)
    ccall((:rcutils_string_map_reserve, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Csize_t), string_map, capacity)
end

function rcutils_string_map_clear(string_map)
    ccall((:rcutils_string_map_clear, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t},), string_map)
end

function rcutils_string_map_set(string_map, key, value)
    ccall((:rcutils_string_map_set, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Cstring, Cstring), string_map, key, value)
end

function rcutils_string_map_set_no_resize(string_map, key, value)
    ccall((:rcutils_string_map_set_no_resize, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Cstring, Cstring), string_map, key, value)
end

function rcutils_string_map_unset(string_map, key)
    ccall((:rcutils_string_map_unset, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Cstring), string_map, key)
end

function rcutils_string_map_key_exists(string_map, key)
    ccall((:rcutils_string_map_key_exists, librcutils), Bool, (Ptr{rcutils_string_map_t}, Cstring), string_map, key)
end

function rcutils_string_map_key_existsn(string_map, key, key_length)
    ccall((:rcutils_string_map_key_existsn, librcutils), Bool, (Ptr{rcutils_string_map_t}, Cstring, Csize_t), string_map, key, key_length)
end

function rcutils_string_map_get(string_map, key)
    ccall((:rcutils_string_map_get, librcutils), Cstring, (Ptr{rcutils_string_map_t}, Cstring), string_map, key)
end

function rcutils_string_map_getn(string_map, key, key_length)
    ccall((:rcutils_string_map_getn, librcutils), Cstring, (Ptr{rcutils_string_map_t}, Cstring, Csize_t), string_map, key, key_length)
end

function rcutils_string_map_get_next_key(string_map, key)
    ccall((:rcutils_string_map_get_next_key, librcutils), Cstring, (Ptr{rcutils_string_map_t}, Cstring), string_map, key)
end

function rcutils_string_map_copy(src_string_map, dst_string_map)
    ccall((:rcutils_string_map_copy, librcutils), rcutils_ret_t, (Ptr{rcutils_string_map_t}, Ptr{rcutils_string_map_t}), src_string_map, dst_string_map)
end
# Julia wrapper for header: /opt/ros/crystal/include/rcutils/types/uint8_array.h
# Automatically generated using Clang.jl wrap_c

function rcutils_get_zero_initialized_uint8_array()
    ccall((:rcutils_get_zero_initialized_uint8_array, librcutils), rcutils_uint8_array_t, ())
end

function rcutils_uint8_array_init(uint8_array, buffer_capacity, allocator)
    ccall((:rcutils_uint8_array_init, librcutils), rcutils_ret_t, (Ptr{rcutils_uint8_array_t}, Csize_t, Ptr{rcutils_allocator_t}), uint8_array, buffer_capacity, allocator)
end

function rcutils_uint8_array_fini(uint8_array)
    ccall((:rcutils_uint8_array_fini, librcutils), rcutils_ret_t, (Ptr{rcutils_uint8_array_t},), uint8_array)
end

function rcutils_uint8_array_resize(uint8_array, new_size)
    ccall((:rcutils_uint8_array_resize, librcutils), rcutils_ret_t, (Ptr{rcutils_uint8_array_t}, Csize_t), uint8_array, new_size)
end