text:
"""
Computes the sizes for the actual set splitting in `splitIntoSets`.
"""
function splitIntoSets_sizes(n_scenarios::Int, sizes::Array{Float64, 1})
  @assert abs(sum(sizes) - 1.) < 1e-8 "Relative sizes for each set do not sum up to 1."

  # First approximation of the number of items per set: just round.
  n_each_sets = Array{Int}(round(sizes * n_scenarios))

  # With potential rounding issues, ensure all samples are taken! (No more, no fewer.)
  if sum(n_each_sets) != n_scenarios
    if sum(n_each_sets) < n_scenarios
      # Too *few* scenarios distributed! If some of them are at zero, prefer adding some to them.
      candidates = find(n_each_sets .== 0)
      if length(candidates) > 0
        i = 1
        while sum(n_each_sets) < n_scenarios && i <= length(candidates)
          n_each_sets[candidates[i]] += 1
          i += 1
        end
      end

      # Loop and add elements to each set until convergence.
      i = 1
      while sum(n_each_sets) < n_scenarios
        n_each_sets[i] += 1
        i += 1
      end
    else
      # Too *many* scenarios distributed! Remove elements from the sets that have most of them first.
      candidates = sortperm(n_each_sets)
      i = 1
      while sum(n_each_sets) > n_scenarios
        n_each_sets[candidates[i]] += 1
        i += 1
      end
    end
  end

  @assert sum(n_each_sets) == n_scenarios "Not all scenarios are split in sets!"

  return n_each_sets
end

"""
Splits the various scenarios in `TS` in different sets (e.g., learning set and test set), whose relative sizes are given in `sizes`
(i.e. if `sizes = [.8, .2]`, the output will be two sets, one having 80% of the scenarios, the other the remaining 20%).
The actual separation in sets is random. In other words, this function implements random subsampling.
"""
function splitIntoSets(TS::Array{TimeSeries.TimeArray{Float64, 1, DateTime, Array{Float64, 1}}, 1}, sizes::Array{Float64, 1}; forced_perm::Array{Int, 1}=zeros(Int, 0))
  n_scenarios = length(TS)
  n_each_sets = splitIntoSets_sizes(n_scenarios, sizes)

  @assert n_scenarios >= 2 "Not enough scenarios to split in different sets (only one scenario given)."

  # Actually perform the sets separation with a *permutation* of the input scenarios (this is where the randomness comes from).
  if isempty(forced_perm)
    permutation = randperm(n_scenarios)
  else
    permutation = forced_perm
  end
  sc_permuted = TS[permutation]

  cumn = [0; cumsum(n_each_sets)]
  return Array{TimeSeries.TimeArray{Float64, 1, DateTime, Array{Float64, 1}}, 1}[sc_permuted[cumn[i] + 1:cumn[i + 1]] for i in 1:length(n_each_sets)]
end

splitIntoSets(r::NaturalRiver,  sizes::Array{Float64, 1}; kwargs...) =  NaturalRiver[copy(r, scenarios=sc) for sc in splitIntoSets(r.scenarios, sizes; kwargs...)]
splitIntoSets(r::DivertedRiver, sizes::Array{Float64, 1}; kwargs...) = DivertedRiver[copy(r, scenarios=sc) for sc in splitIntoSets(r.scenarios, sizes; kwargs...)]

function splitIntoSets(reservoir::Reservoir, sizes::Array{Float64, 1})
  permutation = randperm(countScenarios(reservoir))
  lnr = [splitIntoSets(r, sizes, forced_perm=permutation) for r in  naturalRivers(reservoir)]
  ldr = [splitIntoSets(r, sizes, forced_perm=permutation) for r in divertedRivers(reservoir)]
  return Reservoir[copy(reservoir, rivers_in=NaturalRiver[lnr[j][i] for j in 1:length(lnr)], rivers_diverted=DivertedRiver[ldr[j][i] for j in 1:length(ldr)]) for i in 1:length(sizes)]
end


text:
using Test
using AtmosphericProfilesLibrary

iscallable(f) = !isempty(methods(f))
@testset "AtmosphericProfilesLibrary" begin
    for name in names(AtmosphericProfilesLibrary; all = true)
        startswith(string(name), "#") && continue
        name == :AtmosphericProfilesLibrary && continue
        name == :TRMM_LBA_z && continue # returns an array for other profiles
        name == :ARM_SGP_z && continue # returns an array for other profiles
        name == :GATE_III_z && continue # returns an array for other profiles
        name == :GATE_III_z_in && continue # returns an array for other profiles
        name == :ARM_SGP_time && continue # returns an array for other profiles
        name == :DryBubble_updrafts_z && continue # returns an array for other profiles
        name == :eval && continue
        name == :include && continue
        prof = getproperty(AtmosphericProfilesLibrary, name)
        iscallable(prof) || @show name

        # Test that function is callable
        @test iscallable(prof)
        # Test for type-stability
        @test @inferred Float32 iscallable(prof(Float32))
    end
end

ext: jl


text:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Description
# ==============================================================================
#
#   Functions to compute the Celestial Intermediate Origin (CIO).
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# References
# ==============================================================================
#
#   [1] Vallado, D. A (2013). Fundamentals of Astrodynamics and Applications.
#       Microcosm Press, Hawthorn, CA, USA.
#
#   [2] Vallado, D. A (06-Feb-2018). Consolidated Errata of Fundamentals of
#       Astrodynamics and Applications 4th Ed.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

export cio_iau2006

"""
    cio_iau2006(jd_tt::Number)

Compute the coordinates `X` and `Y` of the Celestial Intermediate Pole (CIP)
with respect to the Geocentric Celestial Reference Frame (GCRF), and the CIO
locator `s`. The algorithm is based on the IAU-2006 theory.

The CIO locator `s` provides the position of the CIO on the Equator of the CIP
corresponding to the kinematical definition of the non-rotation origin in the
GCRS when the CIP is moving with respect to the GCRS between the reference epoch
and the epoch due to precession and nutation **[1]**(p. 214).

# Returns

* The coordinate `X` of the CIP w.r.t. the GCRF.
* The coordinate `Y` of the CIP w.r.t. the GCRF.
* The CIO locator `s`.

# References

- **[1]**: Vallado, D. A (2013). Fundamentals of Astrodynamics and Applications.
    Microcosm Press, Hawthorn, CA, USA.
"""
function cio_iau2006(jd_tt::Number)
    # Compute the Julian Centuries from `jd_tt`.
    t_tt = (jd_tt - JD_J2000) / 36525

    # Auxiliary variables
    # ===================

    a2d = 1 / 3600
    d2r = π / 180
    a2r = a2d * d2r

    # Fundamental arguments
    # =====================

    # Luni-solar part.
    M_s, M_m, u_Mm, D_s, Ω_m = luni_solar_args_iau2006(jd_tt)

    # Planetary part.
    λ_M☿, λ_M♀, λ_Me, λ_M♂, λ_M♃, λ_M♄, λ_M⛢, λ_M♆, p_λ = planetary_args_iau2006(jd_tt)

    # X position of the CIP
    # ==========================================================================

    ΔX = _iau2006_sum(
        (
            COEFS_IAU2006_CIP_X0,
            COEFS_IAU2006_CIP_X1,
            COEFS_IAU2006_CIP_X2,
            COEFS_IAU2006_CIP_X3,
            COEFS_IAU2006_CIP_X4,
        ),
        t_tt,
        M_s,
        M_m,
        u_Mm,
        D_s,
        Ω_m,
        λ_M☿,
        λ_M♀,
        λ_Me,
        λ_M♂,
        λ_M♃,
        λ_M♄,
        λ_M⛢,
        λ_M♆,
        p_λ
    )

    X = @evalpoly(
        t_tt,
        -0.016_617,
        +2004.191_898,
        -0.429_782_9,
        -0.198_618_34,
        +0.000_007_578,
        +0.000_005_928_5
    ) + ΔX

    # Convert to [rad].
    X *= a2r

    # Y position of the CIP
    # ==========================================================================

    ΔY = _iau2006_sum(
        (
            COEFS_IAU2006_CIP_Y0,
            COEFS_IAU2006_CIP_Y1,
            COEFS_IAU2006_CIP_Y2,
            COEFS_IAU2006_CIP_Y3,
            COEFS_IAU2006_CIP_Y4
        ),
        t_tt,
        M_s,
        M_m,
        u_Mm,
        D_s,
        Ω_m,
        λ_M☿,
        λ_M♀,
        λ_Me,
        λ_M♂,
        λ_M♃,
        λ_M♄,
        λ_M⛢,
        λ_M♆,
        p_λ
    )

    Y = @evalpoly(
        t_tt,
        -0.006_951,
        -0.025_896,
        -22.407_274_7,
        +0.001_900_59,
        +0.001_112_526,
        +0.000_000_135_8
    ) + ΔY

    # Convert to [rad].
    Y *= a2r

    # Parameter `s` (CIO locator)
    # ==========================================================================
    #
    # The value `s` provides the position of the CIO on the Equator of the CIP
    # corresponding to the kinematical definition of the non-rotation origin in
    # the GCRS when the CIP is moving with respect to the GCRS between the
    # reference epoch and the epoch due to precession and nutation [1, p. 214].

    Δs = _iau2006_sum(
        (
            COEFS_IAU2006_CIO_S0,
            COEFS_IAU2006_CIO_S1,
            COEFS_IAU2006_CIO_S2,
            COEFS_IAU2006_CIO_S3,
            COEFS_IAU2006_CIO_S4
        ),
        t_tt,
        M_s,
        M_m,
        u_Mm,
        D_s,
        Ω_m,
        λ_M☿,
        λ_M♀,
        λ_Me,
        λ_M♂,
        λ_M♃,
        λ_M♄,
        λ_M⛢,
        λ_M♆,
        p_λ
    )

    s = @evalpoly(
        t_tt,
        # We must convert this term to [arcsec] to match the units.
        #    ||
        # |------|
        (-X * Y / 2) / a2r + 0.000_094,
        +0.003_808_65,
        -0.000_122_68,
        -0.072_574_11,
        +0.000_027_98,
        +0.000_015_65
    ) + Δs

    # Convert to [rad].
    s *= a2r

    return X, Y, s
end


text:
function get_itrf_version(obj::VersionedITRF)
    return jcall(obj, "getITRFVersion", ITRFVersion, ())
end


text:
using RandomODE
using Test
using LinearAlgebra

@testset "Deterministic" begin
    @test include("deterministictest.jl")
end


text:
function cir(nom, uv_max = 5.0)
    x = zeros(nom * nom)  # exclude r=0
    y = zeros(nom * nom)
    w = zeros(nom * nom)
    k = 1
    for i = 1:nom # r=0 excluded
        for j = 0:(nom-1) # phi=2*pi excluded
            x[k] = i * uv_max / nom * cos(j * 2 * π / nom)
            y[k] = i * uv_max / nom * sin(j * 2 * π / nom)
            w[k] = (2 * i - 1) * (uv_max / nom)^2 * π / nom
            k += 1
        end
    end

    return x, y, w
end

function get_moments(f, u, v, ω)
    w = zeros(eltype(f), 4)
    w[1] = discrete_moments(f, u, ω, 0)
    w[2] = discrete_moments(f, u, ω, 1)
    w[3] = discrete_moments(f, v, ω, 1)
    w[4] = 0.5 * (discrete_moments(f, u, ω, 2) + discrete_moments(f, v, ω, 2))
    return w
end

u, v, weights = cir(160)

using KitBase, Test

prim = [1.0, 0.0, 0.0, 1.0]
γ = 2.0
w = prim_conserve(prim, γ)

M = maxwellian(u, v, prim)
w1 = get_moments(M, u, v, weights)

@test w ≈ w1 atol = 0.05

max_stars_repo_name: CSMMLab/Flowmachine

max_issues_repo_name: CSMMLab/Flowmachine

max_forks_repo_name: CSMMLab/Flowmachine


text:
using Test

using DiffEqBase
using DiffEqBase: prob2dtmin, timedepentdtmin

@testset "tspan2dtmin" begin
  tspan2dtmin(tspan; kwargs...) = prob2dtmin(ODEProblem(identity, 1, tspan); kwargs...)
  @test tspan2dtmin((10, 100.0)) === eps(100.0)
  @test tspan2dtmin((-10000.0, 100.0)) === eps(10000.0)
  @test tspan2dtmin((1, 2)) === 0
  @test tspan2dtmin((1//10, 2//10)) === 1//10^10
  @test tspan2dtmin((2//10, Inf)) === eps(1.0)
  @test tspan2dtmin((2//1, Inf)) === eps(2.0)
  @test tspan2dtmin((0, Inf)) === tspan2dtmin((0.0, Inf)) === eps(1.0)
  @test_throws ArgumentError tspan2dtmin((Inf, 100.0))
  @test tspan2dtmin((0f0, 1f5); use_end_time=false) === eps(1f0)
  @test timedepentdtmin(10f0, eps(1f0)) === eps(10f0)
  @test timedepentdtmin(10, eps(1f0)) === eps(1f0)
end


text:
using DataDepsGenerators
using Test

using ReferenceTests

@testset "DataDryad test" begin
    # Via URL
    @test_reference "references/DataDryad Ecology.txt" generate(DataDryad(), "https://datadryad.org/resource/doi:10.5061/dryad.74699")
    #Via DOI
    @test_reference "references/DataDryad Ecology.txt" generate(DataDryad(), "https://datadryad.org/resource/doi:10.5061/dryad.74699")

    #Checking files with multiple files available for download
    @test_reference "references/DataDryad Plasticity.txt" generate(DataDryad(), "https://datadryad.org/resource/doi:10.5061/dryad.f9s4424")
    @test_reference "references/DataDryad Drought.txt" generate(DataDryad(), "https://datadryad.org/resource/doi:10.5061/dryad.cc8834s")
end


text:
function main()
    a::Array{String} = append!([PROGRAM_FILE], ARGS)
    cmd::String = a[0+1]
    if cmd == "dart"
        # pass
    else

        @assert(findfirst("sys_argv", cmd) != Nothing)
    end
    if length(a) > 1
        println(join([a[1+1]], " "))
    else

        println(join(["OK"], " "))
    end
end

main()


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

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

"""

Lists the available SKUs supported by Microsoft.Storage for given subscription.
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: StorageSkuListResult
"""
function _swaggerinternal_skusList(_api::SkusApi, api_version::String, subscriptionId::String; _mediaType=nothing)
    Swagger.validate_param("api_version", "skusList", :minLength, api_version, 1)

    Swagger.validate_param("subscriptionId", "skusList", :minLength, subscriptionId, 1)

    _ctx = Swagger.Ctx(_api.client, "GET", StorageSkuListResult, "/subscriptions/{subscriptionId}/providers/Microsoft.Storage/skus", ["azure_auth"])
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function skusList(_api::SkusApi, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_skusList(_api, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function skusList(_api::SkusApi, response_stream::Channel, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_skusList(_api, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export skusList


text:
module LimitOrderBook
export LimitOrder, trader, side, id
export PriceLevel, orders, add!, remove!
export PriceLevels
export BUY, SELL
export OrderBook, limitorder!, marketorder!, cancel!, update!
export best_bid, best_bid_size
export best_ask, best_ask_size
export match!
export get_level
export amount
export insert_order!
export cancel!

include("constants.jl")
include("order.jl")
include("pricelevel.jl")
include("pricelevels.jl")
include("orderbook.jl")

end


text:
abstract type AbstractPenalty{T} end

mutable struct PowerPenalty{T} <: AbstractPenalty{T}
    p::T
end
(P::PowerPenalty)(x) = x^P.p

mutable struct RationalPenalty{T} <: AbstractPenalty{T}
    p::T
end
(R::RationalPenalty)(x) = sinh(R.p*x)/sinh(R.p)

import Base: copy
copy(p::TP) where {TP<:AbstractPenalty} = TP(p.p)


text:
function BlackScholesDP(CallPutFlag, S, X, t1, T2, T1, r1, r2, b, v)

#=
considers later payment especially for OTC derivatives
Usage:

t1 is the time elapsing from t to payment, 2 days is 2/365
T2 is the time to expiration plus t1
r1 is the shorter term rate
r2 is the longer term rate
BlackScholesDP("c", 130, 120, 2/365, 0.5 + 2/365, 0.5, 0.5, 0.1, 0.1, 0.12)

=#

  d1 = (log(S / X) + (b + v^2 / 2) * T1) / (v * sqrt(T1))
  d2 = d1 - v * sqrt(T1)

  if CallPutFlag == "c"
    BS = exp(r1 * t1) * exp(-r2* T2) * (S * exp(b * T1) * CND(d1) - X * CND(d2))
  elseif CallPutFlag == "p"
    BS = exp(r1 * t1) * exp(-r2* T2) * (X * CND(-d2) - S* exp(-r * T) * CND(-d1))
  end

end


text:
@testset "MC: IsingModel Simulation" begin
    Random.seed!(123)
    m = IsingModel(dims=2, L=8);
    mc = MC(m, beta=0.35);
    run!(mc, sweeps=1000, thermalization=10, verbose=false);

    # Check measurements
    measured = measurements(mc)
    @test   25.47  ≈ measured[:Magn].M |> mean         atol=0.01
    @test    0.82  ≈ measured[:Magn].M |> std_error    atol=0.01
    @test  887.    ≈ measured[:Magn].M2 |> mean        atol=1.0
    @test   46.    ≈ measured[:Magn].M2 |> std_error   atol=1.0
    @test    0.398 ≈ measured[:Magn].m |> mean         atol=0.001
    @test    0.013 ≈ measured[:Magn].m |> std_error    atol=0.001
    @test    1.300 ≈ measured[:Magn].chi |> mean       atol=0.001

    @test  -59.10  ≈ measured[:Energy].E |> mean       atol=0.01
    @test    0.88  ≈ measured[:Energy].E |> std_error  atol=0.01
    @test 3799.    ≈ measured[:Energy].E2 |> mean      atol=1.0
    @test  111.    ≈ measured[:Energy].E2 |> std_error atol=1.0
    @test   -0.924 ≈ measured[:Energy].e |> mean       atol=0.001
    @test    0.014 ≈ measured[:Energy].e |> std_error  atol=0.001
    @test    0.585 ≈ measured[:Energy].C |> mean       atol=0.001

    @test isempty(mc.configs) == true
end

@testset "DQMC: attractive HubbardModel Simulation" begin
    Random.seed!(123)
    m = HubbardModelAttractive(4, 2);
    N = 4*4
    mc = DQMC(m, beta=1.0);
    mc[:G]    = greens_measurement(mc, m)
    mc[:CDC]  = charge_density_correlation(mc, m)
    mc[:SDCx] = spin_density_correlation(mc, m, :x)
    mc[:SDCy] = spin_density_correlation(mc, m, :y)
    mc[:SDCz] = spin_density_correlation(mc, m, :z)
    mc[:PC]   = pairing_correlation(mc, m, K=5)
    run!(mc, sweeps=1000, thermalization=10, verbose=false);

    # Check measurements
    measured = measurements(mc)
    atol = 4mc.p.delta_tau^2

    # Greens
    @test [
        0.49561029949409063, -0.1687665008733178, 0.0015443171080505057, -0.15826706293908882, -0.16327912018676052, -0.0012912048380092711, 0.0400134279416359, -0.00023897687325203078, 0.000518924115176036, 0.033287082427197835, 0.0005610925623708709, 0.03355362536026409, -0.15336955536802732, -0.0007173109462335704, 0.03718701046356412, -0.0022646318329721314, -0.14109173845075432, 0.5456869842396492, -0.1525774255084264, -0.0015902930984101192, -0.003972801810470219, -0.147697038758823, -0.006993551226533865, 0.0317398340650569, 0.03569896564560615, -0.002229218421481367, 0.03249972621062017, 0.003111775344433114, -0.0033357701715413125, -0.14806231575170986, -0.008110575189421874, 0.030666958318547568, 0.0038059320775098364, -0.16090801844840802, 0.5032221284134659, -0.15778023976270292, 0.0367526260302524, 0.00023018604121051174, -0.16079082152419452, -0.0010189093870493398, -0.0027078526122727925, 0.0336042768732646, 0.0008804171894124407, 0.033585930261204204, 0.03423464450554678, 0.0006837814205788495, -0.1592860297970792, -0.0003197793263157921, -0.1510513906355696, -0.0034189296295932077, -0.16601307222929637, 0.46555705577562784, -0.0006208387011797379, 0.035210820362588824, -0.004374176132786647, -0.15554493499728533, 0.03670070195921949, -0.00017999900586424726, 0.03469552002832713, 0.0022877300718145426, 0.003952996066706437, 0.03505257718654688, -0.002083353870407342, -0.15675730648887862, -0.1454501498690891, -0.0034662657448121335, 0.034685694594513254, 0.0005482353387074046, 0.5018800205034198, -0.15216739261435402, -0.004924498879078514, -0.14889945089915826, -0.15893883813326026, 0.0009345312712633184, 0.03381036671119939, -0.001992914856789758, 0.00035316037660027374, 0.03495708791272885, 0.004181195516540646, 0.033319239577225296, 8.803222558820038e-5, -0.16437996929845947, -0.0003227236454807117, 0.037632153131398324, -0.15980309033462356, 0.48161597161151826, -0.16277949407760503, -0.0013931230133652577, 0.003570089898415349, -0.14602655909333703, 0.00266995053412048, 0.03225258977042409, 0.033289689554501456, 0.0023638040393705647, 0.03643878282831864, 0.0010641748060031425, 0.03263683609628051, -0.006004129868195169, -0.1560336142069483, -0.0021332633846873196, -0.002379304268578448, -0.15028971193668583, 0.5166721724125727, -0.14957564177647462, 0.0373204798824859, 0.0032270856425180507, -0.15087086172218744, -0.0009643853135129485, 0.0005179212144537478, 0.03358000578484016, -0.0047333049189295, 0.03243947002002746, 0.0011020560884685057, 0.03688282409580619, 0.0034042726779896617, -0.15675864085720137, -0.1543908575302831, -0.0031745035622491435, -0.16477145217633254, 0.538160088615617, -0.0002784974063055064, 0.03200297369828768, -0.001087913141663623, -0.14768221051226266, 0.03277958950609755, -0.0007340129807579421, 0.03756082712851951, 0.00030239985806428197, 0.001981442814477685, 0.034903185780452796, -0.00187065416406773, 0.03132279699448782, -0.15013125056311932, 0.0022040950566253954, 0.0331640243940833, 0.0033574986957033526, 0.48812350967966184, -0.14422651158934308, 0.002297851607470225, -0.14010307142667747, -0.14575193297748285, 0.0036369829875460952, 0.03252890672337301, -0.001469026609155827, 0.03498167403603111, -0.0010828646746416902, 0.03654366377401215, -0.001799356145910054, 0.0009692227295256147, -0.1591018959282234, 0.002464828141500206, 0.03643858101101029, -0.17521504904012353, 0.497185551259633, -0.15941146055784833, 0.0015457701208019927, 0.00025409858926587906, -0.16171205676354916, -0.0018792626376814602, 0.0367914838027299, -0.0006287109079948039, 0.03823425030557243, -0.0020697827416925963, 0.03649740703188446, 0.03482791096741246, -0.0017878943345419971, -0.16168477708742987, -0.003128425368425258, 0.006703448997269299, -0.15146977935989922, 0.49445220876879736, -0.14948675596829367, 0.034898941203370615, 0.0009079035617771938, -0.1623965512726413, -0.002113962373845439, 0.034530883422275456, 0.0034866654926869467, 0.036541175050748304, 0.0014740114088499364, -0.00511861295500145, 0.03589227906034798, -0.004786013535523526, -0.15551790644627334, -0.17226974203702553, 0.004016341998689895, -0.15940337534065374, 0.47502497421432127, 8.435792947765405e-6, 0.036753256150736234, 0.0005862414959520833, -0.15647796151676352, -0.14658908837491919, -0.004541553911689515, 0.034686801261314376, 0.004153542379188954, -0.0018589976659021234, 0.03369319545523831, 0.003344096142851812, 0.03356008826413151, -0.16419401971120845, 0.0018554072527899865, 0.03566244149957983, 0.002083211163272423, 0.5096548821759186, -0.16140939125332018, -0.0030520389686069732, -0.15256958459493178, -0.00013396457500532762, -0.1634084261501946, 0.0016892556067786032, 0.035813426922792505, 0.034806109696506424, 0.0033621549366931723, 0.036297835543780785, 0.00022924963655465144, 0.0014791713885626764, -0.14646897576594442, 0.0015024730011948325, 0.030743348720024936, -0.15494766455596282, 0.47657618050113093, -0.1592775952165905, -0.004273376964622415, 0.029229326644345743, -0.009089728658843783, -0.1492259062343542, 0.0006819029818598053, 0.003224313646518353, 0.03223172756479698, -0.0037546701007679793, 0.03207630934007616, 0.034797483355109356, 0.0005685316171704344, -0.14729883913610578, -0.0012375296766150062, -0.00048236386995160747, -0.1477759042585998, 0.5310600856182538, -0.13984676729889742, 8.263499723165622e-5, 0.03759339612082147, -6.164967903564072e-5, -0.15771502115431643, 0.03384092934372584, 0.0020287459133012035, 0.03720410216143907, -0.001077933958772017, -0.00016789936977114548, 0.0328823121771512, -0.002635672835872482, -0.1494398494339179, -0.15675568099246326, -0.002108732173327703, -0.16091738294994276, 0.5174007428593362
    ] ≈ (measured[:G] |> mean)[:]           atol = atol
    @test [
        0.01903630965131304, 0.005367516479841765, 0.0024584912434881534, 0.004890991356523148, 0.006363727124689783, 0.002670798811073267, 0.0021066937139101443, 0.00301559391676348, 0.003194080063641578, 0.0013442384852690233, 0.0021844921675267036, 0.0017208532918349584, 0.004902256544938516, 0.003022457879188603, 0.001959177525541325, 0.0023162054411693, 0.004275338756144313, 0.016190447778031265, 0.00622439056707409, 0.0027891086921042144, 0.0024747787231799347, 0.004743929829605756, 0.0026022570507337954, 0.0018811623274672816, 0.0020296410229540124, 0.001917007923316469, 0.0017821822872064257, 0.0015874651085898946, 0.002073785126319732, 0.005203727105701843, 0.0024428864285170842, 0.0014482403743486525, 0.002732283686976738, 0.006241513316141949, 0.017947118144596073, 0.0066844610214952535, 0.002073388696305197, 0.0026748418574992702, 0.006343349608775392, 0.002119334209726534, 0.0019276798962566477, 0.001912086325670065, 0.0027078659347968587, 0.0017274987770035345, 0.001730730946599209, 0.002755975555112104, 0.0062626591213190445, 0.002538493010301427, 0.006098666836121245, 0.002351234708256203, 0.007537561825151221, 0.01482652736208729, 0.002226492682037637, 0.0018870261129214604, 0.0028813646224384037, 0.0056738286375110775, 0.001978694193790825, 0.0015194200298218336, 0.0018930490650442217, 0.002954208794234731, 0.002539403264143692, 0.002043787453315343, 0.002465116172071212, 0.00633723160781742, 0.005152182403326165, 0.00221980109044263, 0.00209307523188663, 0.002279203611722848, 0.01727462737987002, 0.006193953525747859, 0.0022950804203056424, 0.00605660516317818, 0.0056744842883902765, 0.0021411097877753606, 0.0015106572026585446, 0.002285965572601132, 0.0025851060623688572, 0.0019413813197430884, 0.0018293773252474807, 0.0018633913153026519, 0.0023424483738403476, 0.00560666781142671, 0.0028486833567268675, 0.0018996697083859427, 0.006778416349325631, 0.015529197915268668, 0.005802396675855519, 0.002577418620315891, 0.002537373388636465, 0.004267295023739163, 0.002216982496441896, 0.0014470288731124991, 0.0015448157761172826, 0.0026749909170203207, 0.0015960502414737114, 0.0018638971133579443, 0.002176172975333444, 0.0024661226628342214, 0.0059976529594891895, 0.0024275919659689023, 0.0024874460957389284, 0.004866152879901385, 0.016989888842258615, 0.00606786788834373, 0.0023650404715101145, 0.0022059530709299794, 0.006279985224570244, 0.0022591078220764883, 0.002244262826955961, 0.0017607727293324292, 0.002805151032378269, 0.0019203802814192405, 0.002808211640591048, 0.0014493790069284944, 0.0026815107294531825, 0.005244751689767846, 0.004457555716976892, 0.0027461862709045517, 0.007432682630957972, 0.01755180302734928, 0.0027546143757098953, 0.0013564156087778078, 0.002707184989403521, 0.005099207586692647, 0.00150711950287787, 0.0018469456135621182, 0.0021664965287707533, 0.0028573759197268573, 0.002257562058149153, 0.0018752987165948749, 0.0018474643382295432, 0.0015607159782713032, 0.004821113270875764, 0.002364393502281104, 0.0015914287961616067, 0.002017966865185779, 0.016678090766298847, 0.005532950615319388, 0.0025109463649847317, 0.00490999391748333, 0.005540189949851306, 0.0025778872950522782, 0.0015297393649903565, 0.0021526364720696263, 0.0015571786088503922, 0.0030715698656264088, 0.0019442247942314111, 0.001959609115393741, 0.002451806750645247, 0.00559182183037939, 0.002364438409286417, 0.002033163891428257, 0.007385122100593753, 0.016250001923804477, 0.00588029391580204, 0.0022664676364664562, 0.0022713083805696375, 0.004920463385631935, 0.002555556649254254, 0.0024253973749420706, 0.0016998977444620306, 0.0023730453964623094, 0.0026884831369355915, 0.002052298758092647, 0.0017405567697183519, 0.0025459146940258817, 0.006477775129878893, 0.0027559441428842125, 0.002507883713380407, 0.005579200483908438, 0.015149687637628374, 0.005716157182003588, 0.0020198143514409796, 0.002678143865896058, 0.005627834489234238, 0.0019505457843814742, 0.0015667358381430906, 0.0019693925268430904, 0.0017634657213137022, 0.0027309321641583004, 0.0023192160020215594, 0.001492816198492005, 0.002785975799730211, 0.005637866774905859, 0.007373646876499863, 0.0024441882113822207, 0.005057050695680436, 0.016981962144626644, 0.0026358465926791313, 0.0021629519326452178, 0.001978862212401592, 0.00559129466697721, 0.0053878998822222395, 0.002378047860973303, 0.0021696210935349316, 0.0021858413712564696, 0.002603168942043464, 0.0018142457233731126, 0.0019318206065561722, 0.0016916601775288252, 0.006462811051987628, 0.0023964206261950405, 0.00201234725665299, 0.0020856386696421355, 0.01818721557230035, 0.0078336450885551, 0.002879127598649167, 0.005559421935709471, 0.0025272247116726937, 0.006749213317453175, 0.002407881174684203, 0.001723770533529353, 0.001685814864352903, 0.002595017712103584, 0.001784867442122867, 0.0016512832001637893, 0.0029511346895967168, 0.004831990577677809, 0.002363895478273945, 0.0017365815749286698, 0.0061205221823493194, 0.017463498150406046, 0.006898041663060922, 0.002930549060657847, 0.0013097885169025025, 0.002477957003239124, 0.005041328409858466, 0.0022703149157202326, 0.0017091772829437746, 0.0014423544812366467, 0.0026124944984324892, 0.0017586921671544939, 0.0018143303377610813, 0.001981021736540454, 0.005538479554528282, 0.0015071193020268251, 0.0023646394774796474, 0.005869543468904877, 0.01732179843958681, 0.004853138482281587, 0.0019211890883876162, 0.0019921005132619825, 0.0029311927912516376, 0.005390881176746915, 0.0014190304988554389, 0.0018902190049541409, 0.0023298593140222215, 0.0024414631574547737, 0.0025022457477321563, 0.001662072259828581, 0.0022766455352105424, 0.0052142514926209705, 0.005934479064251144, 0.002908842935009184, 0.006626344451829513, 0.017266063739950332
    ] ≈ (measured[:G] |> std_error)[:]      atol = atol

    # Configurations :conf
    @test [
        0.16 0.1 -0.04 -0.04 -0.12 0.06 0.14 -0.08 0.04 -0.12; -0.04 -0.24 -0.08 -0.2 -0.28 -0.3 -0.1 -0.06 0.0 0.16; -0.16 -0.1 0.18 0.1 -0.08 -0.1 0.2 0.18 -0.06 -0.1; 0.04 0.1 0.0 0.12 0.2 0.1 -0.04 0.1 -0.02 0.08; 0.1 -0.1 -0.08 -0.14 0.0 -0.08 0.06 -0.12 0.06 0.12; 0.22 0.04 -0.24 0.2 -0.1 0.06 0.02 -0.02 -0.16 0.24; -0.08 -0.02 -0.3 -0.08 0.08 0.02 0.12 -0.18 -0.06 0.1; -0.2 -0.02 0.04 -0.06 0.08 -0.12 -0.02 0.04 -0.16 -0.2; -0.1 -0.12 -0.08 0.14 0.08 0.02 0.02 0.14 0.12 0.14; 0.16 0.08 0.04 -0.02 0.08 -0.08 -0.14 0.02 -0.14 0.0; 0.08 -0.14 0.16 0.02 0.06 -0.12 -0.06 0.16 -0.06 0.0; 0.08 0.24 0.08 0.0 0.14 0.08 0.04 -0.14 0.04 -0.04; -0.06 0.0 0.06 -0.08 0.08 0.02 -0.08 -0.06 0.22 -0.2; 0.1 0.04 0.0 -0.06 0.04 0.02 0.24 -0.02 0.08 0.06; -0.16 -0.14 -0.18 -0.1 -0.1 0.0 -0.14 0.14 0.12 -0.1; 0.0 -0.02 0.0 0.08 -0.12 -0.06 -0.18 -0.1 0.14 -0.16
    ] ≈ [MonteCarlo.decompress(mc, m, c) for c in mc.configs] |> mean                    atol = atol

    # Charge Density Correlation
    @test [
        1.5475639544924544, 0.9357147275890807, 0.9356142612712862, 0.9357147275890806, 0.9356142612712864, 0.9942520649617483, 0.9890339109627417, 0.9865241580609763, 1.0016167591618215, 0.9865241580609763, 0.989033910962742, 0.9879509583797096, 0.9879509583797096, 0.9845001897680479, 0.9845001897680479, 0.9956993671839532
    ][:] ≈ mean(measured[:CDC]) atol = atol
    @test [
        0.013869638657504228, 0.013470915194620922, 0.013282700278496358, 0.013470915194621087, 0.013282700278496358, 0.013550942726610091, 0.014307471098069393, 0.014492552221530538, 0.014129517405169136, 0.01449255222153069, 0.014307471098069393, 0.013948472512305249, 0.01394847251230509, 0.01389084520478554, 0.01389084520478546, 0.013133272694007561
    ][:] ≈ std_error(measured[:CDC]) atol = atol

    # Spin density correlations (x, y, z)
    @test [
        0.4429653314717919, -0.04370216965399458, -0.043612330295362885, -0.04370216965399458, -0.04361233029536289, -0.000946359143464255, -0.0008341145546385382, -0.0009155800316996598, -0.0010002441809075038, -0.0009155800316996598, -0.0008341145546385382, -0.00201357312086348, -0.00201357312086348, -0.0020135699303120863, -0.0020135699303120867, -0.000515078257581753
    ][:] ≈ mean(measured[:SDCx]) atol = atol
    @test [
        0.0015350907401287547, 0.0002368878415500336, 0.0002607507287443457, 0.0002368878415500336, 0.00026075072874433736, 6.64636472973452e-5, 2.9316744933934093e-5, 3.521865202114811e-5, 6.282380159287888e-5, 3.521865202114811e-5, 2.931674493393406e-5, 2.5828399958572843e-5, 2.5828399958573172e-5, 2.7096518574704045e-5, 2.7096518574704045e-5, 2.605149773144738e-5
    ][:] ≈ std_error(measured[:SDCx]) atol = atol
    @test [
        0.4429653314717919, -0.04370216965399458, -0.043612330295362885, -0.04370216965399458, -0.04361233029536289, -0.000946359143464255, -0.0008341145546385382, -0.0009155800316996598, -0.0010002441809075038, -0.0009155800316996598, -0.0008341145546385382, -0.00201357312086348, -0.00201357312086348, -0.0020135699303120863, -0.0020135699303120867, -0.000515078257581753
    ][:] ≈ mean(measured[:SDCy]) atol = atol
    @test [
        0.0015350907401287547, 0.0002368878415500336, 0.0002607507287443457, 0.0002368878415500336, 0.00026075072874433736, 6.64636472973452e-5, 2.9316744933934093e-5, 3.521865202114811e-5, 6.282380159287888e-5, 3.521865202114811e-5, 2.931674493393406e-5, 2.5828399958572843e-5, 2.5828399958573172e-5, 2.7096518574704045e-5, 2.7096518574704045e-5, 2.605149773144738e-5
    ][:] ≈ std_error(measured[:SDCy]) atol = atol
    @test [
        0.4429653314717919, -0.04370216965399458, -0.043612330295362885, -0.04370216965399457, -0.04361233029536289, -0.0009463591434642553, -0.0008341145546385382, -0.0009155800316996598, -0.0010002441809075038, -0.0009155800316996595, -0.0008341145546385383, -0.0020135731208634792, -0.0020135731208634797, -0.0020135699303120867, -0.0020135699303120863, -0.0005150782575817528
    ][:] ≈ mean(measured[:SDCz]) atol = atol
    @test [
        0.0015350907401287547, 0.00023688784155001527, 0.00026075072874433736, 0.00023688784155001527, 0.0002607507287443457, 6.64636472973453e-5, 2.9316744933933842e-5, 3.521865202114802e-5, 6.282380159287893e-5, 3.521865202114805e-5, 2.931674493393381e-5, 2.58283999585735e-5, 2.5828399958572843e-5, 2.7096518574704045e-5, 2.7096518574704357e-5, 2.605149773144732e-5
    ][:] ≈ std_error(measured[:SDCz]) atol = atol

    # Pairing Correlations
    @test [
        0.28088501277304245, 0.027926386314808847, 0.02702952307269744, 0.027920423229791748, 0.027071962006014926, 0.0005612430524459908, 0.0006651149853086413, 0.0006023514782578597, 0.0006352869286941741, 0.0006859016157082934, 0.0006837873971011032, 0.001584559907969527, 0.0014934661569067464, 0.0015394206509506594, 0.0015249733043811522, 0.0003586305892719369, -0.0779325928437434, -0.07794925719585194, 7.416939833433938e-5, 9.15430602819799e-5, 3.19349681863787e-5, 5.0159394714072806e-5, -1.288889846012798e-6, -4.695336246856413e-6, 0.00016454132272085645, 1.0937473902704468e-5, -4.279726198492107e-6, -9.664522816562855e-6, -9.716213047452465e-6, 3.771336153438404e-5, -1.1515192479893092e-5, 2.9429803791175528e-5, -0.0772508688913746, 0.00013501873026766536, -0.07726093910138591, 5.889697348896871e-5, -2.2220048907671005e-5, 7.369155335708185e-5, 6.085129408823017e-5, -1.0778828906975566e-5, -1.8676076720939018e-5, -4.786661202307681e-6, -1.2876201803912958e-5, -1.4953866393419861e-5, -1.760690808706339e-5, -4.452207672717376e-7, 2.8425762199885675e-5, 2.2775640733343408e-5, -0.07794925719585194, 1.0937473902704485e-5, 5.0159394714072833e-5, -0.0779325928437434, 0.0001645413227208564, -9.664522816562854e-6, 7.416939833433935e-5, 3.193496818637875e-5, -1.151519247989311e-5, 9.154306028197997e-5, -9.71621304745246e-6, -1.2888898460127964e-6, 2.942980379117552e-5, -4.27972619849211e-6, -4.695336246856416e-6, 3.771336153438404e-5, -0.07726093910138591, 7.369155335708191e-5, -1.2876201803912897e-5, 6.0851294088230125e-5, -0.0772508688913746, -1.760690808706339e-5, -4.452207672717368e-7, 5.8896973488968724e-5, 0.00013501873026766534, -1.4953866393419858e-5, -2.222004890767103e-5, 2.27756407333434e-5, -1.867607672093901e-5, -1.077882890697556e-5, -4.786661202307683e-6, 2.8425762199885668e-5, -0.07859139986086838, 8.888907823292415e-5, 0.00014656429746926159, -0.07834056326103467, 0.0001513957115637485, -4.682986314791741e-5, 0.0001642531102651869, 0.00019875875307477653, -5.4125970583499646e-5, 5.2057810074839686e-5, -8.470622870508169e-6, -5.276940183550647e-5, 3.7141011539808865e-5, 1.2332949974708236e-6, -4.2160756611833586e-5, 4.766458316662073e-5, 0.2495895813286457, 0.022954991176478735, 0.02398097084544921, 0.02298009953656085, 0.023910501204576894, 5.4833169644117366e-5, 4.642514619320383e-5, 4.582708161074575e-5, 6.542703890551616e-5, 0.00024413961458778788, -0.000144066436784289, 0.0011158848132819471, 0.0011668657753312306, 0.0011712942415251502, 0.0011114247748410123, 4.2931267786458114e-5, -0.0015007810852782828, -0.005327078304510117, 0.02288341686126135, 0.02293220048521649, -0.005259843794446752, 4.748720016663828e-5, -0.0012258302903106015, 5.387019974456772e-5, 1.153367887444192e-6, 3.991187106418889e-5, 4.286465364428433e-5, -0.005362307960117761, 0.0011816301657752778, -0.005300335269468484, 0.0011855560463505564, 6.442747228391055e-7, -0.0013266522530175431, 0.02433136703549239, -0.005264614125114294, 0.021851084826997286, -0.005228753179755653, -7.484692724507751e-5, 0.00018796620688712808, 0.0001942095054481029, -7.335640516701494e-5, -0.0013021050790755955, 2.042615450265304e-5, -0.0052769774528154045, 0.0012321288203439612, 0.0011138317570835224, -0.005234988278855624, 1.3715768892637092e-5, -0.0012487099373695975, -0.005325137080154086, -0.005274764413017183, 0.02292834236893734, 0.02289712540051836, 9.0297447745732e-7, 4.972149106661189e-5, -0.0012803740674616798, 4.50684552181906e-5, 3.2504175966694957e-5, 4.7042059413310644e-5, 0.001192322495830393, 0.0011777652114412615, -0.005280374853320025, -0.005330383852096999, -8.864368846026459e-6, -0.07779690853913088, 0.0001817990091141154, 4.2070500031567376e-5, 0.0001575572577323118, -0.07810223185568085, -3.3132179576222714e-5, -5.085772380217953e-5, 0.0001663383638541108, 0.00012505529214518315, -2.583593850388535e-5, 2.202526660397117e-5, 4.621839823449776e-5, -4.5141783301678965e-5, -4.0788777495563147e-5, -3.449422840683064e-5, 4.023549219865053e-5, -0.0014410778616140139, 0.02293322083037406, -0.005277974918237465, -0.005340680819248391, 0.022933175836744132, 5.228613008300481e-5, 3.4708518208706857e-6, 4.073337290093473e-5, -0.0013797137555183992, 5.452249809501785e-5, 5.860355725281192e-5, 0.001179146188767435, -0.005244260572844597, 0.001182474299353308, -0.005288409762402226, -4.2085011574278875e-6, 0.2495420049095391, 0.02452059418295243, 0.022904127732794356, 0.024614800714463557, 0.02283649526881342, 5.045562218584725e-5, 4.931687881476536e-5, 6.254927720962045e-5, 5.647210546660332e-5, -0.00013085973250382947, 0.00025685490606991153, 0.0012048463899164367, 0.0011239583159664895, 0.0011325554450582233, 0.0011930868034999644, 4.7197276893688556e-5, -0.0012585718645914312, -0.005338039852469405, -0.0052734582947536815, 0.022947948190710474, 0.022898820943539486, -5.862151526396677e-6, 4.550528059506005e-5, -0.0012828251636973183, 6.791639186421846e-5, 3.864027667258746e-5, 5.9905221667360414e-5, 0.0011883352172190587, 0.0011705763265564186, -0.005262665005385117, -0.005307992161072422, -1.028796516340341e-5, -0.0012520938261888354, -0.005317132386989721, 0.024130107681884748, -0.005359003102714416, 0.021806165147681446, -7.972696500038395e-5, -6.874354990804345e-5, 0.0001957000500281929, 0.00020730545247240947, 1.5310226898631656e-5, -0.0013068031737986465, 0.0012728363040334272, -0.005323216450756551, -0.0053766403456330485, 0.0011303021212156785, 2.0275323583875018e-5, -0.07834056326103467, -0.07859139986086838, 0.0001642531102651869, 5.2057810074839686e-5, 0.00019875875307477653, 0.00014656429746926159, -5.276940183550647e-5, -4.2160756611833586e-5, 0.0001513957115637485, 8.888907823292415e-5, 1.2332949974708236e-6, -4.682986314791741e-5, -8.470622870508169e-6, 4.766458316662073e-5, -5.4125970583499646e-5, 3.7141011539808865e-5, -0.0013021050790755955, 0.021851084826997286, -0.005276977452815404, 0.02433136703549239, -0.005234988278855622, 0.00018796620688712808, -7.484692724507752e-5, -7.335640516701496e-5, 0.00019420950544810292, -0.001326652253017543, 1.37157688926371e-5, -0.005264614125114294, 0.0011138317570835224, 0.0012321288203439612, -0.005228753179755653, 2.0426154502653046e-5, -0.00128037406746168, 0.02289712540051836, 0.02292834236893734, -0.005330383852096998, -0.005280374853320025, -0.0012487099373695975, 3.250417596669496e-5, -8.864368846026459e-6, 4.7042059413310644e-5, 4.50684552181906e-5, 4.972149106661189e-5, -0.005325137080154085, -0.005274764413017183, 0.001192322495830393, 0.0011777652114412617, 9.029744774573195e-7, 0.24958958132864567, 0.022954991176478735, 0.02398097084544921, 0.022980099536560855, 0.023910501204576894, 5.483316964411738e-5, 4.642514619320382e-5, 4.582708161074574e-5, 6.542703890551616e-5, 0.00024413961458778785, -0.00014406643678428906, 0.0011158848132819471, 0.0011668657753312306, 0.0011712942415251504, 0.0011114247748410123, 4.293126778645812e-5, -0.001225830290310602, 0.02288341686126135, -0.005300335269468485, -0.005362307960117761, 0.02293220048521649, 4.286465364428432e-5, 6.442747228391006e-7, 3.9911871064188896e-5, -0.0015007810852782832, 4.748720016663828e-5, 5.3870199744567726e-5, 0.0011816301657752778, -0.00525984379444675, 0.0011855560463505564, -0.005327078304510117, 1.1533678874441946e-6, -0.07810223185568085, 0.00012505529214518315, -0.07779690853913088, 0.0001663383638541108, 2.202526660397117e-5, 0.0001817990091141154, 0.0001575572577323118, -4.0788777495563147e-5, -4.5141783301678965e-5, -3.449422840683064e-5, 4.2070500031567376e-5, -2.583593850388535e-5, -3.3132179576222714e-5, -5.085772380217953e-5, 4.023549219865053e-5, 4.621839823449776e-5, -0.001282825163697318, 0.022898820943539486, 0.022947948190710474, -0.005307992161072422, -0.005262665005385119, -0.0012585718645914312, 3.864027667258746e-5, -1.0287965163403406e-5, 5.99052216673604e-5, 6.791639186421846e-5, 4.5505280595060044e-5, -0.005338039852469405, -0.0052734582947536815, 0.001188335217219059, 0.0011705763265564184, -5.86215152639668e-6, -0.0013068031737986463, -0.005323216450756552, 0.021806165147681446, -0.005376640345633047, 0.024130107681884755, 0.00020730545247240947, 0.0001957000500281929, -6.874354990804346e-5, -7.972696500038395e-5, 2.027532358387502e-5, -0.0012520938261888354, 0.0011303021212156785, -0.00531713238698972, -0.0053590031027144144, 0.0012728363040334272, 1.531022689863166e-5, -0.0013797137555183988, -0.005288409762402227, 0.02293322083037406, 0.022933175836744132, -0.005244260572844597, 5.452249809501785e-5, -0.001441077861614014, 5.860355725281193e-5, -4.208501157427894e-6, 4.073337290093473e-5, 5.22861300830048e-5, -0.005340680819248391, 0.001179146188767435, -0.005277974918237465, 0.0011824742993533082, 3.4708518208706925e-6, 0.2495420049095391, 0.024520594182952427, 0.02290412773279436, 0.024614800714463557, 0.02283649526881342, 5.045562218584725e-5, 4.9316878814765344e-5, 6.254927720962045e-5, 5.647210546660332e-5, -0.00013085973250382947, 0.00025685490606991153, 0.0012048463899164367, 0.0011239583159664897, 0.0011325554450582233, 0.0011930868034999644, 4.7197276893688556e-5
    ] ≈ mean(measured[:PC])[:] atol = atol
    @test [
        0.0032863968694560874, 0.00042772252675633826, 0.0003518557357542367, 0.0004743615772443992, 0.0003187801835120089, 4.807866876266873e-5, 2.7443632781155007e-5, 3.087921747910029e-5, 4.295229784612734e-5, 2.7131480773117706e-5, 2.3360145651071746e-5, 4.6038701058516214e-5, 5.688082298878186e-5, 3.477280028969865e-5, 3.0122652022979076e-5, 2.028509759307593e-5, 0.0006793221509329129, 0.0006754871522655642, 0.00011843270443530931, 0.00011834451604052362, 0.00010615690256295016, 0.0001243664358098925, 0.00011105578571808066, 0.00012160922087931815, 2.8535027637957004e-5, 2.7566801509094677e-5, 2.1371276153817884e-5, 2.6505038538425558e-5, 2.4270303829044734e-5, 2.7585721128230576e-5, 3.5578032465851165e-5, 3.792786779387757e-5, 0.0006820245874155875, 0.00011194387420314651, 0.0006431256216668431, 0.00010798281383960798, 0.00011839952161819387, 2.747026452012285e-5, 0.00012140889313203758, 2.6049298318322218e-5, 0.00011433387417751547, 0.00012556056981436842, 2.3905752587305103e-5, 2.509640204375193e-5, 3.635761848562791e-5, 2.465954105096387e-5, 2.5137728666196422e-5, 3.594115483339847e-5, 0.000675487152265577, 0.0001243664358098925, 0.00011105578571808066, 0.0006793221509329129, 0.00012160922087931817, 0.00011834451604052362, 2.6505038538425558e-5, 2.4270303829044734e-5, 2.7585721128230576e-5, 0.00011843270443530931, 0.00010615690256295016, 2.7566801509094677e-5, 2.1371276153817884e-5, 3.792786779387757e-5, 2.8535027637957007e-5, 3.5578032465851165e-5, 0.0006431256216668431, 0.00012140889313203759, 0.00011433387417751547, 0.00012556056981436842, 0.0006820245874155747, 2.509640204375193e-5, 2.465954105096387e-5, 0.00011194387420314651, 0.00011839952161819387, 2.5137728666196422e-5, 0.00010798281383960797, 3.594115483339846e-5, 2.7470264520122846e-5, 2.6049298318322218e-5, 2.3905752587305103e-5, 3.6357618485627904e-5, 0.0005712777277038281, 0.00011138201020643361, 0.00011547593940896772, 0.0006185946733805882, 0.0001250322089856034, 0.00011099025943433941, 2.2911566901869562e-5, 2.7069997775801493e-5, 2.547577645224039e-5, 0.00011394307751195347, 0.00011775034186131933, 2.516833737154611e-5, 2.5865813768100625e-5, 3.5584130541739836e-5, 2.4073549197964844e-5, 3.3867429395236943e-5, 0.003539859671041112, 0.00016362767390622782, 0.0002246191699138663, 0.00017845343617490725, 0.00021268203128181403, 3.8944094417145216e-5, 1.1728571613108348e-5, 1.1083582357649566e-5, 3.267501471471958e-5, 1.2586212552108007e-5, 1.0841571469820574e-5, 2.0426518109442387e-5, 2.0692330560425303e-5, 2.198816223405185e-5, 2.075131248696356e-5, 1.4831088536320838e-5, 0.0003515926250209984, 8.364142899254581e-5, 0.00014397768229978744, 0.00015017652713828134, 6.957343027475577e-5, 1.2452188285585125e-5, 1.239432966071291e-5, 1.170251699251169e-5, 1.2510294872646639e-5, 0.00035642112923309986, 1.118906729995006e-5, 7.789029219399845e-5, 2.226663792917963e-5, 2.036813610782931e-5, 6.491932854948363e-5, 1.3179372854946754e-5, 0.0003739027082114623, 0.00024321517489145862, 6.247968326554638e-5, 0.00011844392077501222, 6.85233902257041e-5, 0.0003876668716336736, 1.8169742082622794e-5, 2.0000420131148687e-5, 1.6304784801120634e-5, 1.8452438168822835e-5, 1.9947241100376264e-5, 6.670410552204984e-5, 6.65542070420358e-5, 2.4596544124544127e-5, 1.96976597592882e-5, 1.6180256909043756e-5, 0.0003515376320593395, 7.232255697701556e-5, 7.068637292329068e-5, 0.00015234503654893702, 0.00015095582137596026, 1.4494089296318829e-5, 1.227868057837655e-5, 1.3777969885874737e-5, 1.3804986335903444e-5, 1.1115952291683665e-5, 0.0003455496357607849, 2.1224866990386695e-5, 7.8317894232434e-5, 2.0719827570342864e-5, 6.534385175842493e-5, 1.1001207962411203e-5, 0.0006235602912179505, 0.00011871663414839694, 0.00012212270640311318, 0.00011953805525290922, 0.000620221577511302, 2.3188118242046084e-5, 2.7692702639765495e-5, 0.00011079105994197718, 0.0001158178029217961, 2.4528820820853455e-5, 0.00012000417025520125, 3.5920923142131966e-5, 2.500081224729451e-5, 2.866707037909041e-5, 2.594548700031861e-5, 3.595985463636785e-5, 0.0003759489283794092, 0.00014814065865731806, 7.202950072343839e-5, 7.270595014281034e-5, 0.00014942849039939674, 1.4941393663445203e-5, 1.4004128039011912e-5, 0.0003352754974847287, 1.2861788315205813e-5, 1.5430611673346766e-5, 1.2180076096398397e-5, 2.246155755059947e-5, 7.752875372782713e-5, 7.116360379326014e-5, 2.172539102064846e-5, 1.220029529846814e-5, 0.003582411455132999, 0.0002825484222289856, 0.00018099728215045593, 0.0003012407141657386, 0.00017876709707790486, 3.915089723405503e-5, 1.2658245820587652e-5, 1.2771479152914011e-5, 3.2790573680904847e-5, 1.297033650205429e-5, 1.0730709603946599e-5, 2.76191232435535e-5, 2.8418952423800635e-5, 2.143839940531424e-5, 2.000220367457017e-5, 1.6179065936505336e-5, 0.0003489193143297205, 7.455741065724246e-5, 6.928355385121493e-5, 0.00015452264028963485, 0.00015484581765932366, 1.2996421657299983e-5, 1.3936851912543852e-5, 1.2758762469247603e-5, 1.3025773586153131e-5, 1.288541383164654e-5, 0.00032266596637020817, 2.168642281079922e-5, 7.852068318219601e-5, 2.2004304032514555e-5, 6.674635580332466e-5, 1.307995089540432e-5, 0.00037025964275628185, 7.432900732372818e-5, 0.00023730774991964098, 7.765883516354168e-5, 0.00013037536437217285, 2.0332637110704405e-5, 1.87160378916926e-5, 2.0473022691921813e-5, 0.0003660098090677224, 2.0992174207137846e-5, 2.155902062952222e-5, 3.961712150627199e-5, 2.3168964349629955e-5, 7.398702065306552e-5, 7.433944300255508e-5, 1.855683938692942e-5, 0.0006185946733805882, 0.0005712777277038281, 0.00011394307751195347, 0.00011099025943433941, 0.00011775034186131933, 0.00011138201020643361, 0.00011547593940896772, 0.0001250322089856034, 2.4073549197964844e-5, 2.516833737154611e-5, 2.5865813768100625e-5, 2.2911566901869562e-5, 2.7069997775801493e-5, 2.547577645224039e-5, 3.3867429395236943e-5, 3.5584130541739836e-5, 0.00038766687163367355, 0.0001184439207750168, 6.670410552204831e-5, 0.00024321517489145862, 6.655420704203732e-5, 0.0003739027082114623, 1.845243816882282e-5, 1.9947241100376264e-5, 1.6180256909043756e-5, 1.8169742082622794e-5, 2.0000420131148687e-5, 6.2479683265548e-5, 6.852339022570557e-5, 1.96976597592882e-5, 2.4596544124543955e-5, 1.6304784801120634e-5, 0.0003455496357607849, 0.0001509558213759674, 0.00015234503654893702, 7.8317894232434e-5, 6.53438517584244e-5, 1.3777969885874739e-5, 0.0003515376320593395, 1.3804986335903442e-5, 1.1115952291683665e-5, 1.449408929631883e-5, 1.1001207962411203e-5, 7.232255697701509e-5, 2.0719827570343067e-5, 7.068637292328972e-5, 2.1224866990386895e-5, 1.227868057837655e-5, 0.003539859671041112, 0.00016362767390622782, 0.00022461916991386148, 0.0001784534361749194, 0.00021268203128181403, 3.894409441714523e-5, 1.1728571613108352e-5, 1.1083582357649566e-5, 3.2675014714719584e-5, 1.2586212552108007e-5, 1.0841571469820574e-5, 2.0426518109442387e-5, 2.0692330560425506e-5, 2.198816223405185e-5, 2.075131248696356e-5, 1.4831088536320838e-5, 0.00035642112923309986, 0.00014397768229979497, 6.491932854948468e-5, 7.789029219399845e-5, 0.00015017652713828134, 1.239432966071291e-5, 1.2510294872646642e-5, 0.0003515926250209984, 1.118906729995006e-5, 1.3179372854946755e-5, 1.2452188285585125e-5, 2.03681361078291e-5, 8.3641428992545e-5, 6.957343027475577e-5, 2.226663792917944e-5, 1.170251699251169e-5, 0.000620221577511302, 0.00011079105994197718, 0.0006235602912179505, 0.00012000417025520125, 0.0001158178029217961, 2.500081224729451e-5, 0.00011871663414839694, 2.866707037909041e-5, 0.00012212270640311318, 0.00011953805525290922, 2.594548700031861e-5, 2.3188118242046084e-5, 3.595985463636785e-5, 2.7692702639765495e-5, 2.4528820820853455e-5, 3.5920923142131966e-5, 0.0003226659663702083, 0.00015484581765932366, 0.0001545226402896208, 7.852068318219601e-5, 6.674635580332466e-5, 1.2758762469247605e-5, 0.0003489193143297205, 1.3025773586153133e-5, 1.2885413831646546e-5, 1.2996421657299983e-5, 1.307995089540432e-5, 7.455741065724246e-5, 2.2004304032514555e-5, 6.92835538512154e-5, 2.168642281079922e-5, 1.3936851912543852e-5, 0.00036600980906772247, 7.398702065306415e-5, 0.00013037536437217285, 7.433944300255508e-5, 0.0002373077499196364, 1.855683938692942e-5, 2.047302269192182e-5, 1.8716037891692603e-5, 0.00037025964275628185, 2.155902062952222e-5, 2.0992174207137846e-5, 2.3168964349629955e-5, 3.961712150627209e-5, 7.432900732372909e-5, 7.765883516354168e-5, 2.0332637110704405e-5, 0.0003352754974847287, 7.752875372782625e-5, 0.00014814065865731074, 0.000149428490399404, 7.11636037932587e-5, 1.2180076096398397e-5, 1.4941393663445203e-5, 1.2200295298468141e-5, 1.4004128039011908e-5, 0.00037594892837940913, 1.2861788315205815e-5, 7.270595014281173e-5, 2.172539102064846e-5, 2.246155755059975e-5, 7.202950072343933e-5, 1.5430611673346766e-5, 0.003582411455132999, 0.0002825484222289856, 0.00018099728215046192, 0.0003012407141657386, 0.00017876709707790486, 3.9150897234055034e-5, 1.2658245820587652e-5, 1.2771479152914011e-5, 3.279057368090484e-5, 1.297033650205429e-5, 1.0730709603946597e-5, 2.7619123243553578e-5, 2.841895242380056e-5, 2.143839940531424e-5, 2.0002203674570274e-5, 1.6179065936505336e-5
    ] ≈ std_error(measured[:PC])[:] atol = atol
end

@testset "DQMC: repulsive HubbardModel Simulation" begin
    Random.seed!(123)
    m = HubbardModelRepulsive(2, 2);
    mc = DQMC(m, beta=1.0);
    mc[:G]    = greens_measurement(mc, m)
    mc[:CDC]  = charge_density_correlation(mc, m)
    mc[:Mx]   = magnetization(mc, m, :x)
    mc[:My]   = magnetization(mc, m, :y)
    mc[:Mz]   = magnetization(mc, m, :z)
    mc[:SDCx] = spin_density_correlation(mc, m, :x)
    mc[:SDCy] = spin_density_correlation(mc, m, :y)
    mc[:SDCz] = spin_density_correlation(mc, m, :z)
    mc[:PC]   = pairing_correlation(mc, m, K=3)
    run!(mc, sweeps=1000, thermalization=10, verbose=false);

    # Check measurements
    measured = measurements(mc)
    atol = 2mc.p.delta_tau^2

    # Greens
    @test [
        0.5094932784468137 -0.2348865407826436 -0.23381326365575295 0.008301184859789675 0.0 0.0 0.0 0.0; -0.24464834998108553 0.4672410264922629 0.0033319326734337754 -0.22509256608721934 0.0 0.0 0.0 0.0; -0.2502971103485778 0.001926720252228231 0.5029784365108798 -0.23494310099935523 0.0 0.0 0.0 0.0; 0.011304831806515332 -0.2455124144577661 -0.24557286313656093 0.4918300158786517 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.49050672155318586 -0.24464834998108517 -0.25029711034857766 -0.011304831806514657; 0.0 0.0 0.0 0.0 -0.23488654078264354 0.5327589735077374 -0.0019267202522278266 -0.24551241445776575; 0.0 0.0 0.0 0.0 -0.23381326365575275 -0.0033319326734333942 0.49702156348912013 -0.24557286313656065; 0.0 0.0 0.0 0.0 -0.008301184859788962 -0.22509256608721948 -0.23494310099935553 0.5081699841213461
    ] ≈ measured[:G] |> mean           atol = atol
    @test [
        0.015558677710177986 0.008330899904555777 0.008184425352547245 0.009154682712334604 0.0 0.0 0.0 0.0; 0.007410831061669652 0.01648129284257949 0.008625434463440258 0.007294508374789638 0.0 0.0 0.0 0.0; 0.006843413476789877 0.008445936622654146 0.013787211108014254 0.008058662653954283 0.0 0.0 0.0 0.0; 0.009844147766786396 0.008848693062785571 0.008838191580658811 0.020082028056368488 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.01555867771017795 0.007410831061669576 0.0068434134767897965 0.009844147766786278; 0.0 0.0 0.0 0.0 0.008330899904555801 0.01648129284257949 0.008445936622654148 0.008848693062785485; 0.0 0.0 0.0 0.0 0.008184425352547372 0.008625434463440267 0.013787211108014214 0.008838191580658834; 0.0 0.0 0.0 0.0 0.009154682712334624 0.007294508374789657 0.008058662653954276 0.020082028056368446
    ] ≈ measured[:G] |> std_error      atol = atol

    # Configurations :conf
    @test [
        0.06 0.2 -0.06 -0.28 -0.08 0.24 -0.02 0.08 -0.04 -0.14; 0.24 0.0 0.18 -0.04 0.12 0.12 0.12 -0.16 0.02 0.2; 0.16 -0.08 -0.12 -0.12 -0.08 0.0 0.06 -0.12 -0.14 0.16; 0.08 -0.06 -0.16 -0.1 0.04 0.16 0.02 0.02 0.28 0.04
    ] ≈ [MonteCarlo.decompress(mc, m, c) for c in mc.configs] |> mean                    atol = atol

    # Charge Density Correlation
    @test [
        1.4536419565506418, 0.8933030762569415, 0.8929164176835145, 0.9881514596933688
    ][:] ≈ mean(measured[:CDC])
    @test [
        0.002734862709277855, 0.0011120013039444745, 0.0010697404888432946, 0.0011271551926820696
    ][:] ≈ std_error(measured[:CDC])

    # Magnetization
    @test [
        0.0, 0.0, 0.0, 0.0
    ] ≈ mean(measured[:Mx])        atol = atol
    @test [
        0.0, 0.0, 0.0, 0.0
    ] ≈ std_error(measured[:Mx])   atol = atol
    @test [
        0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im, 0.0 + 0.0im
    ] ≈ mean(measured[:My])        atol = atol
    @test [
        0.0, 0.0, 0.0, 0.0
    ] ≈ std_error(measured[:My])   atol = atol
    @test [
        -0.018986556893627594, 0.06551794701547445, -0.005956873021759989, 0.016339968242694104
    ] ≈ mean(measured[:Mz])
    @test [
        0.031117355420355968, 0.03296258568515908, 0.027574422216028457, 0.04016405611273709
    ] ≈ std_error(measured[:Mz])

    # Spin density correlations (x, y, z)
    @test [
        0.5463580434493592, -0.1273462888485946, -0.12435020680856286, 0.01466078984729855
    ][:] ≈ mean(measured[:SDCx])
    @test [
        0.0027348627092750135, 0.002691219601002444, 0.002555831150492111, 0.0013440578305848455
    ][:] ≈ std_error(measured[:SDCx])
    @test [
        0.5463580434493592, -0.1273462888485946, -0.12435020680856286, 0.01466078984729855
    ][:] ≈ mean(measured[:SDCy])
    @test [
        0.0027348627092750135, 0.002691219601002444, 0.002555831150492111, 0.0013440578305848455
    ][:] ≈ std_error(measured[:SDCy])
    @test [
        0.5463580434493591, -0.11333275743170461, -0.11689726433492126, 0.017147314487977648
    ][:] ≈ mean(measured[:SDCz])
    @test [
        0.0027348627092748106, 0.00791852904864558, 0.007824969460855756, 0.006651107663992822
    ][:] ≈ std_error(measured[:SDCz])

    # Pairing Correlations
    @test [
        0.22682097827532022, 0.05334846187152967, 0.05354179115824349, -0.005924270153316071, -0.11773619915899722, -0.12077912195248058, 0.001104084370179573, -0.001374257495660194, -0.11778109283006905, 0.0012516557597017698, -0.1204198265233939, -0.0014936273909555147, -0.11923359177243059, -0.12227651456591387, 0.0013742574956600933, -0.0011040843701796868, 0.25165895842216107, 0.0636731444242973, 0.05574825297980578, -0.0028551159149248174, 0.00042990464544593004, 0.058983987360184134, 0.05880721177394884, 0.00758867997850756, -0.11825901211393497, 0.0014936273909554115, -0.12089774580725984, -0.0012516557597018804, 0.0013725125805160244, 0.058807211773948855, 0.05898398736018413, 0.006646072043437454, 0.2524534205046084, 0.05544415520975516, 0.062175103404281444, -0.0028926923763113897
    ] ≈ mean(measured[:PC])[:]
    @test [
        0.001367431354637659, 0.0005560006519724946, 0.0005348702444204311, 0.0005635775963397751, 0.002483170888063298, 0.0019995138471234027, 0.0016765856228872162, 0.0017201184012394855, 0.002131747013786726, 0.0017425693779002111, 0.0022456690936882052, 0.0017307653829596891, 0.002243883064771306, 0.002225762938342551, 0.001720118401239482, 0.0016765856228872218, 0.001947254588881961, 0.001345609800501222, 0.0007977932487371304, 0.0007110834841664547, 0.003803528962932711, 0.0007363554205369239, 0.0007285186026716149, 0.003882312744872355, 0.002142487249272225, 0.0017307653829596863, 0.002077188962229575, 0.0017425693779002172, 0.0038833853421802026, 0.000728518602671597, 0.0007363554205368886, 0.00393584111062321, 0.001906193690791037, 0.0008143580947866242, 0.0012779155752460556, 0.0007228031157513561
    ] ≈ std_error(measured[:PC])[:]
end

# TODO
# remove this / make this an example / make this faster
#=

"""
    stat_equal(
        expected_value, actual_values, standard_errors;
        min_error = 0.1^3, order=2, rtol = 0, debug=false
    )

Compare an `expected_value` (i.e. literature value, exact result, ...) to a set
of `actual_values` and `standard_errors` (i.e. calculated from DQMC or MC).

- `order = 2`: Sets the number of σ-intervals included. (This affects the
accuracy of the comaprison and the number of matches required)
- `min_error = 0.1^3`: Sets a lower bound for the standard error. (If one
standard error falls below `min_error`, `min_error` is used instead. This
happens before `order` is multiplied.)
- `rtol = 0`: The relative tolerance passed to `isapprox`.
- `debug = false`: If `debug = true` information on comparisons is always printed.
"""
function stat_equal(
        expected_value, actual_values::Vector, standard_errors::Vector;
        min_error = 0.001, order=2, debug=false, rtol=0.0
    )

    @assert order > 1
    N_matches = floor(length(actual_values) * (1 - 1 / order^2))
    if N_matches == 0
        error("No matches required. Try increasing the sample size or σ-Interval")
    elseif N_matches < 3
        @warn "Only $N_matches out of $(length(actual_values)) are required!"
    end

    is_approx_equal = [
        isapprox(expected_value, val, atol=order * max(min_error, err), rtol=rtol)
        for (val, err) in zip(actual_values, standard_errors)
    ]
    does_match = sum(is_approx_equal) >= N_matches

    if debug || !does_match
        printstyled("────────────────────────────────\n", color = :light_magenta)
        print("stat_equal returned ")
        printstyled("$(does_match)\n\n", color = does_match ? :green : :red)
        print("expected: $expected_value\n")
        print("values:   [")
        for i in eachindex(actual_values)
            if i < length(actual_values)
                printstyled("$(actual_values[i])", color = is_approx_equal[i] ? :green : :red)
                print(", ")
            else
                printstyled("$(actual_values[i])", color = is_approx_equal[i] ? :green : :red)
            end
        end
        print("]\n")
        print("$(order)-σ:      [")
        for i in eachindex(standard_errors)
            if i < length(standard_errors)
                printstyled("$(standard_errors[i])", color = is_approx_equal[i] ? :green : :red)
                print(", ")
            else
                printstyled("$(standard_errors[i])", color = is_approx_equal[i] ? :green : :red)
            end
        end
        print("]\n")
        print("checks:   [")
        for i in eachindex(standard_errors)
            if i < length(standard_errors)
                printstyled("$(is_approx_equal[i])", color = is_approx_equal[i] ? :green : :red)
                print(", ")
            else
                printstyled("$(is_approx_equal[i])", color = is_approx_equal[i] ? :green : :red)
            end
        end
        print("]\n")
        printstyled("────────────────────────────────\n", color = :light_magenta)
    end
    does_match
end

@testset "DQMC: triangular Hubbard model vs dos Santos Paper" begin
    # > Attractive Hubbard model on a triangular lattice
    # dos Santos
    # https://journals.aps.org/prb/abstract/10.1103/PhysRevB.48.3976
    Random.seed!()
    sample_size = 5

    @time for (k, (mu, lit_oc, lit_pc,  beta, L)) in enumerate([
            (-2.0, 0.12, 1.0,  5.0, 4),
            (-1.2, 0.48, 1.50, 5.0, 4),
            ( 0.0, 0.88, 0.95, 5.0, 4),
            ( 1.2, 1.25, 1.55, 5.0, 4),
            ( 2.0, 2.00, 0.0,  5.0, 4),

            # (-2.0, 0.12, 1.0,  8.0, 4),
            # (-1.2, 0.48, 1.82, 8.0, 4),
            # ( 0.0, 0.88, 0.95, 8.0, 4),
            # ( 1.2, 1.25, 1.65, 8.0, 4),
            # ( 2.0, 2.00, 0.0,  8.0, 4),

            # (-2.0, 0.40, 1.0,  5.0, 6),
            # (-1.2, 0.40, 1.05, 5.0, 6),
            # (0.01, 0.80, 1.75, 5.0, 6),
            # ( 1.2, 1.40, 2.0,  5.0, 6),
            # ( 2.0, 2.00, 0.0,  5.0, 6)
        ])
        @info "[$(k)/15] μ = $mu   L = $L   β = $beta (literature check)"
        m = HubbardModelAttractive(
            l = MonteCarlo.TriangularLattice(L),
            t = 1.0, U = 4.0, mu = mu
        )
        OC_sample = []
        OC_errors = []
        PC_sample = []
        PC_errors = []
        for i in 1:sample_size
            mc = DQMC(
                m, beta=5.0, delta_tau=0.125, safe_mult=8,
                thermalization=2000, sweeps=2000, measure_rate=1,
                measurements = Dict{Symbol, MonteCarlo.AbstractMeasurement}()
            )
            push!(mc, :occ => MonteCarlo.OccupationMeasurement)
            push!(mc, :PC => MonteCarlo.PairingCorrelationMeasurement)
            run!(mc, verbose=false)
            measured = measurements(mc)

            # mean(measured[:G]) = MC mean
            # diag gets c_i c_i^† terms
            # 2 (1 - mean(c_i c_i^†)) = 2 mean(c_i^† c_i) where 2 follows from 2 spins
            occupation = 2 - 2(measured[:occ].obs |> mean |> mean)
            push!(OC_sample, occupation)
            push!(OC_errors, 2(measured[:occ].obs |> std_error |> mean))
            push!(PC_sample, measured[:PC] |> swave |> mean)
            push!(PC_errors, measured[:PC] |> swave |> std_error)
        end
        # min_error should compensate read-of errors & errors in the results
        # dos Santos used rather few sweeps, which seems to affect PC peaks strongly
        @info "Occupation"
        @test stat_equal(lit_oc, OC_sample, OC_errors, min_error=0.025)
        @info "Pairing Correlation"
        @test stat_equal(lit_pc, PC_sample, PC_errors, min_error=0.05)
    end
end

=#


text:
module PlotlyLocal

import JSON
export PlotlyVis, layout, layout!, data, data!, plot, plot!, iplot

const plotlylocal = Pkg.dir("PlotlyLocal", "deps", "plotly-latest.min.js")

#--------------------------------------------------------------------# PlotlyVis
type PlotlyVis
    data::Vector{Dict}         # vector of traces
    layout::Dict               # optional, can be empty
end

#-----------------------------------------------------------------------# layout
layout!(p::PlotlyVis, d::Associative) = merge!(p.layout, d)
layout!(p::PlotlyVis; kw...) = layout!(p, Dict(kw))

#-------------------------------------------------------------------------# data
# Edit the i-th trace
data!(p::PlotlyVis, i::Int, d::Associative) = merge!(p.data[i], d)
data!(p::PlotlyVis, i::Int; kw...) = merge!(p.data[i], Dict(kw))

# Add a new trace
data!(p::PlotlyVis, trace::Associative) = push!(p.data, trace)

#-------------------------------------------------------------------------# plot
function plot{T<:Associative}(data::Vector{T}, layout::Associative)
    p = PlotlyVis(data, layout)
    writehtml(p)
    p
end

# refresh plot after changes
plot!(p::PlotlyVis) = writehtml(p)

#---------------------------------------------------------------# write and open
function writehtml(p::PlotlyVis, dest::AbstractString = tempname(); verbose::Bool = false)
    mypath = string(dest, "tempfile.html")

    myhtml = """
    <!DOCTYPE html>

      <title>PlotlyLocal Visualization</title>

    """

    touch(mypath)
    outfile = open(mypath, "w")
    write(outfile, myhtml)
    close(outfile)

    verbose && println(myhtml)
    open_file(mypath)
end

function open_file(filename)
    @osx_only   return run(`open $(filename)`)
    @linux_only return run(`xdg-open $(filename)`)
    @windows_only return run(`$(ENV["COMSPEC"]) /c start $(filename)`)
    warn("Unknown OS... cannot open browser window.")
end

#-------------------------------------------------------------------------# iplot
function iplot{T<:Associative}(data::Vector{T}, layout::Associative)
    p = PlotlyVis(data, layout)
    id = Base.Random.uuid4()

    init_notebook_mode = """

    """

    myhtml = """

 Drawing...

  """

  display(Base.HTML(init_notebook_mode * myhtml))
end

end # module


text:
# using Revise
using ClusterManagers
using Distributed

worker_ids = if "SLURM_JOBID" in keys(ENV)
    wids = ClusterManagers.addprocs_slurm(parse(Int, ENV["SLURM_NTASKS"]))
    wids
else
    addprocs(4)
end

Distributed.@everywhere begin
    using Pkg
    Pkg.activate(".")
    Pkg.instantiate()
end

Distributed.@everywhere begin
    using POMDPs
	using POMDPModels
	using POMDPSimulators
	using POMDPPolicies
	using POMDPModelTools
	using BeliefUpdaters
	using POMCPOW
	using BasicPOMCP
	using VOOTreeSearch
	using ParticleFilters
	using Distributions
	using Random
	using VDPTag2
	using ProgressMeter
	using DataFrames
	using Statistics
	using MCTS
	using LinearAlgebra
	using Dates
	using CSV
	import Distances: euclidean
end

on_cluster = true
save_data = true

if on_cluster
    n_iter = 1000
    state_width_list = [1, 3, 5, 7, 10]
	action_width_list = [50, 100, 150, 200]
else
    n_iter = 10
    state_width_list = [1, 2]
	action_width_list = [10, 20]
end

# VOWSS parameters
depth = 3
vowss_p = 0.8
vowss_sig = 0.5
action_width_decay = 0.4
vowss_epsilon = vowss_sig/10.0

# LQG test
N = 2
R_gain = 1
V_sig = 0.1
W_sig = 0.1
init_cov_sig = 0.1

eye = [1.0 0.0 ; 0.0 1.0]
A_mat = eye
B_mat = eye
C_mat = eye
Q_mat = eye
R_mat = R_gain * eye
V_mat = V_sig^2 * eye
W_mat = W_sig^2 * eye
init_state_time = [-10.0 ; 10.0 ; 0.0]
init_state = init_state_time[1:end-1]
init_cov = init_cov_sig^2 * [1.0 ; 1.0]
a_space = BoxND(2, [-10.0, -10.0], [10.0, 10.0])
belief = MvNormal([init_state; 1.0], diagm([init_cov; 1e-16]))

lqg_pomdp = LQGPOMDP(A_matrix = A_mat,
		        B_matrix = B_mat,
		        C_matrix = C_mat,
		        Q_matrix = Q_mat,
		        R_matrix = R_mat,
		        V_matrix = V_mat,
		        W_matrix = W_mat,
		        initial_state = init_state,
		        initial_cov_vector = init_cov,
		        a_space = a_space,
		        horizon = N)

@everywhere begin
	abstract type Sims end

	struct MySims <: Sims
	    pomdp::POMDP
	    solver::Any
	    initial_belief::Any
	    lqg_solution::Any
	end

    function get_action_dist(sim::Sims)
    	solver = solve(sim.solver, sim.pomdp)
		a = action(solver, sim.initial_belief)
		return euclidean(a, sim.lqg_solution)
    end

    function gen_sims(pomdp::POMDP, state_width, action_width, lqg_solution, n_iter)
		sims = []
		for i = 1:n_iter
			cont_action_dim = 2
			rng = MersenneTwister(10_000 + i)

			voo = VOOActionGenerator(vowss_p, Distributions.Uniform(), MvNormal(cont_action_dim, vowss_sig),
				rng, vowss_epsilon)
			vowss_opt = VOWSSOptions(depth, state_width, action_width, action_width_decay, true, voo)
			solver = VOOSparseSamplingSolver(vowss_opt, rng)

			sim = MySims(deepcopy(pomdp), solver, belief, deepcopy(lqg_solution))
			push!(sims, sim)
		end
		return sims
	end
end

lqg_solution = solve_LQG_one_step(lqg_pomdp)
results_csv = DataFrame(s_width=Float64[], a_width=Float64[], dist_mean=Float64[], dist_se=Float64[])
datestring = Dates.format(now(), "e_d_u_Y_HH_MM")

try
	println(stderr, "VOWSS Results:")
	for state_width in state_width_list
		for action_width in action_width_list
			sims = gen_sims(lqg_pomdp, state_width, action_width, lqg_solution, n_iter)
			result = @showprogress pmap(get_action_dist, sims)
			println(stderr, "State Width: ", state_width, ", Action Width: ", action_width, " -- mean dist: ", mean(result), ", se dist: ", (std(result)/sqrt(n_iter)))
			push!(results_csv, (state_width, action_width, mean(result), (std(result)/sqrt(n_iter))))
		end
	end

	println(stderr, results_csv)
	###### SAVE DATA ######

	if save_data
        fname_csv = joinpath(@__DIR__, "../data", "LQG_vowss_action_table"*"_"*datestring*".csv")
        CSV.write(fname_csv, results_csv)
        println(stderr,"Saving parameters to ", fname_csv)
    end
finally
	Distributed.rmprocs(worker_ids)
end


text:
### A Pluto.jl notebook ###
# v0.12.7

using Markdown
using InteractiveUtils

# ╔═╡ 71a23086-18c6-11eb-0731-0f0f76002c68
println

# ╔═╡ 7d9a612e-18c6-11eb-0373-9b40bb1b896d
println("¡Estoy emocionado por aprender Julia!")

# ╔═╡ 7d9aaa26-18c6-11eb-3c4c-61c644c08dff
123

# ╔═╡ 7da0ae8a-18c6-11eb-1146-91372b5a82ea
456

# ╔═╡ 7da6f31c-18c6-11eb-0747-196816dcdf5c
mi_respuesta = 42

# ╔═╡ 7dad8baa-18c6-11eb-1775-8bc4b5deec69
typeof(mi_respuesta)

# ╔═╡ 7db3600c-18c6-11eb-2a3e-7b3cbdee2799
my_pi = 3.14159

# ╔═╡ 7dbb0d20-18c6-11eb-1b76-a103f1974ada
typeof(my_pi)

# ╔═╡ 7dc351c4-18c6-11eb-147f-cbef2d55dda3
mi_nombre = "Miguel"

# ╔═╡ 7dc967c6-18c6-11eb-01a2-8de1cf354248
typeof(mi_nombre)

# ╔═╡ 7dd2edfa-18c6-11eb-3d7e-a99176756b90
typeof(mi_nombre)

# ╔═╡ 7dd93ad4-18c6-11eb-1bb2-17f2185955fb
# Puedes dejar un comentario en una sola línea usando la tecla de gato

#=

Para comentarios de varias lineas,
usa la secuencia de '#= =#' .

=#

suma = 3 + 7

# ╔═╡ 7dda5f68-18c6-11eb-0d9b-436902fe4d57
resta = 10 - 3

# ╔═╡ 7de36796-18c6-11eb-13bc-c3624e0c996d
producto = 20 * 5

# ╔═╡ 7de9cf0c-18c6-11eb-3b0b-537f2c8fc017
cociente = 100 / 10

# ╔═╡ 7df0258c-18c6-11eb-16c4-b718652ea3dd
potencia = 10 ^ 2

# ╔═╡ 7df2850c-18c6-11eb-265a-0951708b233b
módulo = 101 % 2

# ╔═╡ Cell order:
# ╠═71a23086-18c6-11eb-0731-0f0f76002c68
# ╠═7d9a612e-18c6-11eb-0373-9b40bb1b896d
# ╠═7d9aaa26-18c6-11eb-3c4c-61c644c08dff
# ╠═7da0ae8a-18c6-11eb-1146-91372b5a82ea
# ╠═7da6f31c-18c6-11eb-0747-196816dcdf5c
# ╠═7dad8baa-18c6-11eb-1775-8bc4b5deec69
# ╠═7db3600c-18c6-11eb-2a3e-7b3cbdee2799
# ╠═7dbb0d20-18c6-11eb-1b76-a103f1974ada
# ╠═7dc351c4-18c6-11eb-147f-cbef2d55dda3
# ╠═7dc967c6-18c6-11eb-01a2-8de1cf354248
# ╠═7dd2edfa-18c6-11eb-3d7e-a99176756b90
# ╠═7dd93ad4-18c6-11eb-1bb2-17f2185955fb
# ╠═7dda5f68-18c6-11eb-0d9b-436902fe4d57
# ╠═7de36796-18c6-11eb-13bc-c3624e0c996d
# ╠═7de9cf0c-18c6-11eb-3b0b-537f2c8fc017
# ╠═7df0258c-18c6-11eb-16c4-b718652ea3dd
# ╠═7df2850c-18c6-11eb-265a-0951708b233b

max_stars_repo_name: miguelraz/JuliaTutorials

max_issues_repo_name: miguelraz/JuliaTutorials

max_forks_repo_name: miguelraz/JuliaTutorials


text:
if !isdefined(Main, :Groebner)
    import Groebner
end

import AbstractAlgebra
using BenchmarkTools
using Logging
global_logger(ConsoleLogger(stderr, Logging.Error))

function benchmark_system_my(system)
    system = Groebner.change_ordering(system, :degrevlex)
    Groebner.groebner([system[1]])
    @btime gb = Groebner.groebner($system, reduced=false)
end

function run_f4_ff_degrevlex_benchmarks(ground)
    systems = [
        ("cyclic 12", Groebner.rootn(12, ground=ground)),
        ("cyclic 13", Groebner.rootn(13, ground=ground)),
        ("katsura 9", Groebner.katsura9(ground=ground)),
        ("katsura 10",Groebner.katsura10(ground=ground)),
        ("noon 6"    ,Groebner.noonn(6, ground=ground)),
        ("noon 7"    ,Groebner.noonn(7, ground=ground))
    ]

    for (name, system) in systems
        println("$name")
        benchmark_system_my(system)
    end
end

ground = AbstractAlgebra.GF(2^31 - 1)
run_f4_ff_degrevlex_benchmarks(ground)

#=
cyclic 12
68.460 ms (184276 allocations: 29.25 MiB)
cyclic 13
255.064 ms (459892 allocations: 74.68 MiB)
katsura 9
344.615 ms (82539 allocations: 22.35 MiB)
katsura 10
2.725 s (250078 allocations: 74.80 MiB)
noon 6
36.954 ms (101244 allocations: 21.19 MiB)
noon 7
289.916 ms (494536 allocations: 100.91 MiB)
=#


text:
const DEFAULT_GRAVITATIONAL_ACCELERATION = SVector(0.0, 0.0, -9.81)

"""
$(TYPEDEF)

A `Mechanism` represents an interconnection of rigid bodies and joints.
`Mechanism`s store the joint layout and inertia parameters, but no
state-dependent information.
"""
mutable struct Mechanism{T}
    graph::DirectedGraph{RigidBody{T}, Joint{T}}
    tree::SpanningTree{RigidBody{T}, Joint{T}}
    environment::ContactEnvironment{T}
    gravitational_acceleration::FreeVector3D{SVector{3, T}} # TODO: consider removing
    modcount::Int

    @doc """
    $(SIGNATURES)

    Create a new `Mechanism` containing only a root body, to which other bodies can
    be attached with joints.

    The `gravity` keyword argument can be used to set the gravitational acceleration
    (a 3-vector expressed in the `Mechanism`'s root frame). Default: `$(DEFAULT_GRAVITATIONAL_ACCELERATION)`.
    """ ->
    function Mechanism(root_body::RigidBody{T}; gravity::AbstractVector=DEFAULT_GRAVITATIONAL_ACCELERATION) where {T}
        graph = DirectedGraph{RigidBody{T}, Joint{T}}()
        add_vertex!(graph, root_body)
        tree = SpanningTree(graph, root_body)
        gravitational_acceleration = FreeVector3D(default_frame(root_body), convert(SVector{3, T}, gravity))
        environment = ContactEnvironment{T}()
        new{T}(graph, tree, environment, gravitational_acceleration, 0)
    end
end

Base.eltype(::Type{Mechanism{T}}) where {T} = T

"""
$(SIGNATURES)

Return the `Joint`s that are part of the `Mechanism` as an iterable collection.
"""
joints(mechanism::Mechanism) = edges(mechanism.graph)

"""
$(SIGNATURES)

Return the `Joint`s that are part of the `Mechanism`'s spanning tree as an iterable collection.
"""
tree_joints(mechanism::Mechanism) = edges(mechanism.tree)

"""
$(SIGNATURES)

Return the `Joint`s that are not part of the `Mechanism`'s spanning tree as an iterable collection.
"""
non_tree_joints(mechanism::Mechanism) = setdiff(edges(mechanism.graph), edges(mechanism.tree))

"""
$(SIGNATURES)

Return the `RigidBody`s that are part of the `Mechanism` as an iterable collection.
"""
bodies(mechanism::Mechanism) = vertices(mechanism.graph)

"""
$(SIGNATURES)

Return the root (stationary 'world') body of the `Mechanism`.
"""
root_body(mechanism::Mechanism) = first(bodies(mechanism))

"""
$(SIGNATURES)

Return the default frame of the root body.
"""
root_frame(mechanism::Mechanism) = default_frame(root_body(mechanism))

"""
$(SIGNATURES)

Return the path from rigid body `from` to `to` along edges of the `Mechanism`'s
kinematic tree.
"""
path(mechanism::Mechanism, from::RigidBody, to::RigidBody) = TreePath(from, to, mechanism.tree)

has_loops(mechanism::Mechanism) = num_edges(mechanism.graph) > num_edges(mechanism.tree)

@inline modcount(mechanism::Mechanism) = mechanism.modcount
register_modification!(mechanism::Mechanism) = mechanism.modcount += 1

function Base.show(io::IO, mechanism::Mechanism)
    println(io, "Spanning tree:")
    print(io, mechanism.tree)
    nontreejoints = non_tree_joints(mechanism)
    println(io)
    if isempty(nontreejoints)
        print(io, "No non-tree joints.")
    else
        print(io, "Non-tree joints:")
        for joint in nontreejoints
            println(io)
            show(IOContext(io, :compact => true), joint)
            print(io, ", predecessor: ")
            show(IOContext(io, :compact => true), predecessor(joint, mechanism))
            print(io, ", successor: ")
            show(IOContext(io, :compact => true), successor(joint, mechanism))
        end
    end
end

isroot(b::RigidBody{T}, mechanism::Mechanism{T}) where {T} = b == root_body(mechanism)
non_root_bodies(mechanism::Mechanism) = Base.unsafe_view(bodies(mechanism), 2 : length(bodies(mechanism)))
num_bodies(mechanism::Mechanism) = num_vertices(mechanism.graph)

"""
$(SIGNATURES)

Return the dimension of the joint configuration vector ``q``.
"""
num_positions(mechanism::Mechanism)::Int = mapreduce(num_positions, +, tree_joints(mechanism); init=0)

"""
$(SIGNATURES)

Return the dimension of the joint velocity vector ``v``.
"""
num_velocities(mechanism::Mechanism)::Int = mapreduce(num_velocities, +, tree_joints(mechanism); init=0)

"""
$(SIGNATURES)

Return the number of constraints imposed by the mechanism's non-tree joints (i.e., the number of rows of the constraint Jacobian).
"""
num_constraints(mechanism::Mechanism)::Int = mapreduce(num_constraints, +, non_tree_joints(mechanism); init=0)

"""
$(SIGNATURES)

Return the dimension of the vector of additional states ``s`` (used for stateful contact models).
"""
function num_additional_states(mechanism::Mechanism)
    num_states_per_environment_element = 0
    for body in bodies(mechanism), point in contact_points(body)
        num_states_per_environment_element += num_states(contact_model(point))
    end
    num_states_per_environment_element * length(mechanism.environment)
end

"""
$(SIGNATURES)

Return the `RigidBody` to which `frame` is attached.

Note: this function is linear in the number of bodies and is not meant to be
called in tight loops.
"""
function body_fixed_frame_to_body(mechanism::Mechanism, frame::CartesianFrame3D)
    for body in bodies(mechanism)
        if is_fixed_to_body(body, frame)
            return body
        end
    end
    error("Unable to determine to what body $(frame) is attached")
end

"""
$(SIGNATURES)

Return the definition of body-fixed frame `frame`, i.e., the `Transform3D` from
`frame` to the default frame of the body to which it is attached.

Note: this function is linear in the number of bodies and is not meant to be
called in tight loops.

See also [`default_frame`](@ref), [`frame_definition`](@ref).
"""
function body_fixed_frame_definition(mechanism::Mechanism, frame::CartesianFrame3D)
    frame_definition(body_fixed_frame_to_body(mechanism, frame), frame)
end

"""
$(SIGNATURES)

Return the transform from `CartesianFrame3D` `from` to `to`, both of which are
rigidly attached to the same `RigidBody`.

Note: this function is linear in the number of bodies and is not meant to be
called in tight loops.
"""
function fixed_transform(mechanism::Mechanism, from::CartesianFrame3D, to::CartesianFrame3D)
    fixed_transform(body_fixed_frame_to_body(mechanism, from), from, to)
end

"""
$(SIGNATURES)

Return the body 'before' the joint, i.e. the 'tail' of the joint interpreted as an
arrow in the `Mechanism`'s kinematic graph.

See [`Joint`](@ref).
"""
predecessor(joint::Joint, mechanism::Mechanism) = source(joint, mechanism.graph)

"""
$(SIGNATURES)

Return the body 'after' the joint, i.e. the 'head' of the joint interpreted as an
arrow in the `Mechanism`'s kinematic graph.

See [`Joint`](@ref).
"""
successor(joint::Joint, mechanism::Mechanism) = target(joint, mechanism.graph)

"""
$(SIGNATURES)

Return the joints that have `body` as their [`predecessor`](@ref).
"""
out_joints(body::RigidBody, mechanism::Mechanism) = out_edges(body, mechanism.graph)

"""
$(SIGNATURES)

Return the joints that have `body` as their [`successor`](@ref).
"""
in_joints(body::RigidBody, mechanism::Mechanism) = in_edges(body, mechanism.graph)

"""
$(SIGNATURES)

Return the joints that are part of the mechanism's kinematic tree and have
`body` as their predecessor.
"""
joints_to_children(body::RigidBody, mechanism::Mechanism) = edges_to_children(body, mechanism.tree)

"""
$(SIGNATURES)

Return the joint that is part of the mechanism's kinematic tree and has
`body` as its successor.
"""
joint_to_parent(body::RigidBody, mechanism::Mechanism) = edge_to_parent(body, mechanism.tree)

function add_body_fixed_frame!(mechanism::Mechanism{T}, transform::Transform3D) where {T}
    add_frame!(body_fixed_frame_to_body(mechanism, transform.to), transform)
end

function canonicalize_frame_definitions!(mechanism::Mechanism{T}, body::RigidBody{T}) where {T}
    if !isroot(body, mechanism)
        change_default_frame!(body, frame_after(joint_to_parent(body, mechanism)))
    end
    for joint in in_joints(body, mechanism)
        set_joint_to_successor!(joint, frame_definition(body, frame_after(joint)))
    end
    for joint in out_joints(body, mechanism)
        set_joint_to_predecessor!(joint, frame_definition(body, frame_before(joint)))
    end
end

function canonicalize_frame_definitions!(mechanism::Mechanism)
    for body in bodies(mechanism)
        canonicalize_frame_definitions!(mechanism, body)
    end
end

function gravitational_spatial_acceleration(mechanism::Mechanism)
    frame = mechanism.gravitational_acceleration.frame
    SpatialAcceleration(frame, frame, frame, zero(SVector{3, eltype(mechanism)}), mechanism.gravitational_acceleration.v)
end

findbody(mechanism::Mechanism, name::String) = findunique(b -> string(b) == name, bodies(mechanism))
findjoint(mechanism::Mechanism, name::String) = findunique(j -> string(j) == name, joints(mechanism))


text:
struct Dirichlet <: Distribution{Vector{Float64}} end

"""
    dirichlet(alpha::AbstractArray{U}) where {U<:Real}

Samples a `Vector{Float64}` value from a dirichlet
"""
const dirichlet = Dirichlet()

function logpdf(::Dirichlet, x::AbstractArray{T}, alpha::AbstractArray{U}) where {T <: Real, U <: Real}
    if !(isapprox(sum(x),1) & all(x .>= 0) & all(x .<= 1))
        -Inf
    elseif all(alpha .> 0.)
        Distributions.logpdf(Distributions.Dirichlet(alpha), x)
    else
        -Inf
    end
end

function logpdf_grad(::Dirichlet, x::AbstractArray{T}, alpha::AbstractArray{U}) where {T <: Real, U <: Real}
    if (isapprox(sum(x),1) & all(x .>= 0) & all(x .<= 1))
        deriv_x = sum((alpha.-1) ./ x)
        deriv_alpha = log.(x) .+ digamma(sum(alpha)) .- digamma.(alpha)
    else
        error("x has to be a simplex: $x")
    end
    Tuple(vcat([deriv_x, deriv_alpha]...))
end

function random(::Dirichlet, alpha::AbstractVector{U}) where {U <: Real}
    """ sample data from Dirichlet distribution with parameter vector alpha
    """
    rand(Distributions.Dirichlet(alpha))
end

is_discrete(::Dirichlet) = false
(::Dirichlet)(alpha) = random(Dirichlet(), alpha)

has_output_grad(::Dirichlet) = true
# has_argument_grads(::Dirichlet) = (true, true)

export dirichlet


text:
module Referencer

import Compat: String

"""
Name in a module.
"""
type ModuleName
    name::String
    exported::Bool
    objtype::String
end

"""
A whole reference of a module.
"""
type ModuleReference
    name::String
    names::Vector{ModuleName}
end

"""
    reference(m::Module)

Build a reference of an imported module.
"""
function reference(m::Module)
    exported_names = names(m)
    module_names = map(names(m,true)) do name
        typestring = try
            string(typeof(m.eval(name)))
        catch
            "undefined"
        end
        ModuleName(
            string(name),
            (name in exported_names),
            typestring
        )
    end
    ModuleReference(string(m), module_names)
end

end # module


text:
struct SomeType end
@testset "ObsDim" begin
    @testset "Type tree" begin
        @test_throws MethodError LearnBase.ObsDim.Constant(2.0)

        @test typeof(LearnBase.ObsDim.First()) <: LearnBase.ObsDimension
        @test typeof(LearnBase.ObsDim.First()) <: LearnBase.ObsDim.First
        @test typeof(LearnBase.ObsDim.First()) <: LearnBase.ObsDim.Constant{1}

        @test typeof(LearnBase.ObsDim.Last()) <: LearnBase.ObsDimension
        @test typeof(LearnBase.ObsDim.Last()) <: LearnBase.ObsDim.Last

        @test typeof(LearnBase.ObsDim.Constant(2)) <: LearnBase.ObsDimension
        @test typeof(LearnBase.ObsDim.Constant(2)) <: LearnBase.ObsDim.Constant{2}
    end

    @testset "Constructors" begin
        @test_throws ArgumentError convert(LearnBase.ObsDimension, "test")
        @test_throws ArgumentError convert(LearnBase.ObsDimension, 1.0)

        @test @inferred(convert(LearnBase.ObsDimension, LearnBase.ObsDim.First())) === LearnBase.ObsDim.First()
        @test @inferred(convert(LearnBase.ObsDimension, LearnBase.ObsDim.First())) === LearnBase.ObsDim.Constant(1)
        @test @inferred(convert(LearnBase.ObsDimension, LearnBase.ObsDim.Last()))  === LearnBase.ObsDim.Last()
        @test @inferred(convert(LearnBase.ObsDimension, LearnBase.ObsDim.Constant(2))) === LearnBase.ObsDim.Constant(2)

        @test_throws ErrorException @inferred convert(LearnBase.ObsDimension, 1)
        @test_throws ErrorException @inferred convert(LearnBase.ObsDimension, 6)
        @test convert(LearnBase.ObsDimension, 1) === LearnBase.ObsDim.First()
        @test convert(LearnBase.ObsDimension, 2) === LearnBase.ObsDim.Constant(2)
        @test convert(LearnBase.ObsDimension, 6) === LearnBase.ObsDim.Constant(6)
        @test_throws ErrorException @inferred convert(LearnBase.ObsDimension, :first)
        @test_throws ErrorException @inferred convert(LearnBase.ObsDimension, "first")
        @test convert(LearnBase.ObsDimension, (:first,:last))  === (LearnBase.ObsDim.First(),LearnBase.ObsDim.Last())
        @test convert(LearnBase.ObsDimension, :first)  === LearnBase.ObsDim.First()
        @test convert(LearnBase.ObsDimension, :begin)  === LearnBase.ObsDim.First()
        @test convert(LearnBase.ObsDimension, "first") === LearnBase.ObsDim.First()
        @test convert(LearnBase.ObsDimension, "BEGIN") === LearnBase.ObsDim.First()
        @test convert(LearnBase.ObsDimension, :end)   === LearnBase.ObsDim.Last()
        @test convert(LearnBase.ObsDimension, :last)  === LearnBase.ObsDim.Last()
        @test convert(LearnBase.ObsDimension, "End")  === LearnBase.ObsDim.Last()
        @test convert(LearnBase.ObsDimension, "LAST") === LearnBase.ObsDim.Last()
        @test convert(LearnBase.ObsDimension, :nothing) === LearnBase.ObsDim.Undefined()
        @test convert(LearnBase.ObsDimension, :none) === LearnBase.ObsDim.Undefined()
        @test convert(LearnBase.ObsDimension, :na) === LearnBase.ObsDim.Undefined()
        @test convert(LearnBase.ObsDimension, :null) === LearnBase.ObsDim.Undefined()
        @test convert(LearnBase.ObsDimension, :undefined) === LearnBase.ObsDim.Undefined()
        @test convert(LearnBase.ObsDimension, nothing) === LearnBase.ObsDim.Undefined()
    end

    @testset "Default values" begin
        @testset "Arrays, SubArrays, and Sparse Arrays" begin
            @test @inferred(LearnBase.default_obsdim(rand(10))) === LearnBase.ObsDim.Last()
            @test @inferred(LearnBase.default_obsdim(view(rand(10),:))) === LearnBase.ObsDim.Last()
            @test @inferred(LearnBase.default_obsdim(rand(10,5))) === LearnBase.ObsDim.Last()
            @test @inferred(LearnBase.default_obsdim(view(rand(10,5),:,:))) === LearnBase.ObsDim.Last()
            @test @inferred(LearnBase.default_obsdim(sprand(10,0.5))) === LearnBase.ObsDim.Last()
            @test @inferred(LearnBase.default_obsdim(sprand(10,5,0.5))) === LearnBase.ObsDim.Last()
        end

        @testset "Types with no specified default" begin
            @test @inferred(LearnBase.default_obsdim(SomeType())) === LearnBase.ObsDim.Undefined()
        end

        @testset "Tuples" begin
            @test @inferred(LearnBase.default_obsdim((SomeType(),SomeType()))) === (LearnBase.ObsDim.Undefined(), LearnBase.ObsDim.Undefined())
            @test @inferred(LearnBase.default_obsdim((SomeType(),rand(2,2)))) === (LearnBase.ObsDim.Undefined(), LearnBase.ObsDim.Last())
            @test @inferred(LearnBase.default_obsdim((rand(10),SomeType()))) === (LearnBase.ObsDim.Last(), LearnBase.ObsDim.Undefined())
            @test @inferred(LearnBase.default_obsdim((rand(10),rand(2,2)))) === (LearnBase.ObsDim.Last(), LearnBase.ObsDim.Last())
        end
    end
end


text:
# loading and storing custom parameters

export ColoringParamsInt, loadParams, saveParams

function saveParams(filename::AbstractString, path, params::Dict)
  h5open(filename, "w") do file
    saveParams(file, path, params)
  end
end

mutable struct ColoringParamsInt
  cmin::Float64
  cmax::Float64
  cmap::Int64
end

function saveParams(file, path, params::Dict)
  for (key,value) in params
    ppath = joinpath(path,string(key))
    if typeof(value) <: Bool
      write(file, ppath, UInt8(value))
      dset = file[ppath]
      attrs(dset)["isbool"] = "true"
    elseif typeof(value) <: AbstractRange
      write(file, ppath, [first(value),step(value),last(value)])
      dset = file[ppath]
      attrs(dset)["isrange"] = "true"
    elseif value == nothing
      write(file, ppath, "")
      dset = file[ppath]
      attrs(dset)["isnothing"] = "true"
    elseif typeof(value) <: ColoringParamsInt
      tmp = zeros(3)
      tmp[1] = value.cmin
      tmp[2] = value.cmax
      tmp[3] = value.cmap

      write(file, ppath, tmp)
      dset = file[ppath]
      attrs(dset)["iscoloring"] = "true"
    elseif typeof(value) <: Array{ColoringParamsInt,1}
      tmp = zeros(3,length(value))
      for i=1:length(value)
        tmp[1,i] = value[i].cmin
        tmp[2,i] = value[i].cmax
        tmp[3,i] = value[i].cmap
      end
      write(file, ppath, tmp)
      dset = file[ppath]
      attrs(dset)["iscoloringarray"] = "true"
    elseif typeof(value) <: Array{Any}
      write(file, ppath, [v for v in value])
    elseif typeof(value) <: MPIFile
      @debug "Do nothing"
    else
      write(file, ppath, value)
    end
  end
end

function loadParams(filename::AbstractString, path)
  params = h5open(filename, "r") do file
   loadParams(file, path)
 end
  return params
end

function loadParams(file, path)
  params = Dict{Symbol,Any}()

  g = file[path]
  for obj in g
    key = last(splitdir(HDF5.name(obj)))
    data = read(obj)
    attr = attrs(obj)
    if exists(attr, "isbool")
      params[Symbol(key)] = Bool(data)
    elseif exists(attr, "isrange")
      if data[2] == 1
        params[Symbol(key)] = data[1]:data[3]
      else
        params[Symbol(key)] = data[1]:data[2]:data[3]
      end
    elseif exists(attr, "isnothing")
       params[Symbol(key)] = nothing
    elseif exists(attr, "iscoloring")
       params[Symbol(key)] = ColoringParamsInt(data[1], data[2],round(Int64,data[3]))
    elseif exists(attr, "iscoloringarray")
       coloring = ColoringParamsInt[]
       for i=1:size(data,2)
         push!(coloring, ColoringParamsInt(data[1,i], data[2,i],round(Int64,data[3,i])))
       end
       params[Symbol(key)] = coloring
    else
      params[Symbol(key)] = data
    end
  end

  return params
end